我在React Native中还很陌生,我试图了解如何将父组件中编写的函数传递(继承)给任何子代和子代子代。特别是,我正在使用以下库来国际化我的App:
import * as RNLocalize from 'react-native-localize'
import i18n from 'i18n-js'
但是我注意到我必须为整个项目的每个组件实现translate(...)
函数,并且这似乎被夸大了,因为实现翻译功能需要很多工作(我遵循this tutorial)。
请注意,我对如何使用this.props传递函数或某些数据有基本的了解,所以我不问props是如何从父母到一个孩子的。我要问的是:如何避免从//BEGIN ...
到//END...
重复代码(请参阅WithSecurityScreen文件),以及避免重复执行handleLocalizationChange,RNLocalize.addEventListener,< [RNLocalize.removeEventListener和translate。
const SecurityScreen = () => <View><Text>{translate('USER_SURNAME')}😂</Text></View>;
但是我无法将函数传递给整个项目的每个组件。项目结构为:translate(...)
App.js
import { withSecurityScreen } from './src/components/withSecurityScreen'
import App from "./SecureApp.js"
export default withSecurityScreen(App);
SecureApp.js
const MainNavigator = createStackNavigator({
Home: {
screen: Welcome,
navigationOptions: {
headerShown: false
}
},
UserProfile: {
screen: CoreApp,
navigationOptions: {
headerShown: false
}
},
NumPad: {
screen: NumPad,
navigationOptions: {
header: 'PIN Creation',
headerShown: false
}
}, /* , navigationOptions: {headerLeft: () => null} */
QrScan: {
screen: QrScan, navigationOptions: {
header: 'QR Scan',
headerShown: false
}
},
...
});
export default createAppContainer(MainNavigator);
WithSecurityScreen.js
// START: https://heartbeat.fritz.ai/how-to-use-react-native-localize-in-react-native-apps-3bb3d510f801
import * as RNLocalize from 'react-native-localize'
import i18n from 'i18n-js'
import memoize from 'lodash.memoize'
const translationGetters = {
en: () => require('./../../assets/locales/en/en.json'),
it: () => require('./../../assets/locales/it/it.json')
};
const translate = memoize(
(key, config) => i18n.t(key, config),
(key, config) => (config ? key + JSON.stringify(config) : key)
)
const setI18nConfig = () => {
const fallback = { languageTag: 'en' }
const { languageTag } =
RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
fallback
translate.cache.clear()
i18n.translations = { [languageTag]: translationGetters[languageTag]() }
i18n.locale = languageTag
}
// END: https://heartbeat.fritz.ai/how-to-use-react-native-localize-in-react-native-apps-3bb3d510f801
const SecurityScreen = () => <View><Text>{translate('USER_SURNAME')}😂</Text></View>;
const showSecurityScreenFromAppState = appState =>
['background', 'inactive'].includes(appState);
const withSecurityScreenIOS = Wrapped => {
return class WithSecurityScreen extends React.Component {
constructor(props) {
super(props)
setI18nConfig()
}
state = {
showSecurityScreen: showSecurityScreenFromAppState(AppState.currentState)
};
componentDidMount() {
AppState.addEventListener('change', this.onChangeAppState)
RNLocalize.addEventListener('change', this.handleLocalizationChange)
}
componentWillUnmount() {
AppState.removeEventListener('change', this.onChangeAppState)
RNLocalize.removeEventListener('change', this.handleLocalizationChange)
}
handleLocalizationChange = () => {
setI18nConfig()
.then(() => this.forceUpdate())
.catch(error => {
console.error(error)
})
}
onChangeAppState = nextAppState => {
const showSecurityScreen = showSecurityScreenFromAppState(nextAppState);
this.setState({showSecurityScreen})
};
render() {
return this.state.showSecurityScreen
? <SecurityScreen/>
: <Wrapped {...this.props} />
}
}
};
const withSecurityScreenAndroid = Wrapped => Wrapped;
export const withSecurityScreen = Platform.OS === 'ios'
? withSecurityScreenIOS
: withSecurityScreenAndroid;
Welcome.js
export default class Welcome extends Component {
let username = 'UserName';
render() {
return (
<View style={styles.container}>
<LinearGradient colors={globalStyles.colors.gradientGreen} style={{flex: 1}}>
<View style={styles.upperView}><Text style={styles.upperViewText}>{this.props.translate('WELCOME_TEXT')}{this.username}</Text>
</View>
</LinearGradient>
</View>
);
}
}
我收到以下错误:
import i18n from "i18next"
进行翻译。这是配置文件:
//config/i18n
import i18n from "i18next";
import { reactI18nextModule, initReactI18next } from "react-i18next";
import translationFR from '../translation/fr/translation.json';
import translationEN from '../translation/en/translation.json';
import DeviceInfo from 'react-native-device-info';
let locale = DeviceInfo.getDeviceLocale().substring(0, 2);
if (locale != 'fr') {
locale = 'en';
}
// the translations
const resources = {
en: translationEN,
fr: translationFR,
};
i18n
.use(reactI18nextModule) // passes i18n down to react-i18next
.init({
resources: resources,
lng: locale,
fallbackLng: ['en', 'fr'],
keySeparator: false, // we do not use keys in form messages.welcome
interpolation: {
escapeValue: false // react already safes from xss
}
});
export default i18n;
用途之一是
import i18n from 'config/i18n'
并使用像这样在文件中翻译
i18n.t('bottomTab:home_tab')
您还可以使用'react-i18next'中的withNamespaces
包装组件,如下所示:
export default withNamespaces([], {wait: true})(Welcome)
然后访问翻译:
this.props.t('welcome_message')
translate
和setI18nConfig
local.js
import * as RNLocalize from 'react-native-localize'
import i18n from 'i18n-js'
import memoize from 'lodash.memoize'
const translationGetters = {
en: () => require('./../../assets/locales/en/en.json'),
it: () => require('./../../assets/locales/it/it.json')
};
export const translate = memoize(
(key, config) => i18n.t(key, config),
(key, config) => (config ? key + JSON.stringify(config) : key)
)
export const setI18nConfig = () => {
const fallback = { languageTag: 'en' }
const { languageTag } =
RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
fallback
translate.cache.clear()
i18n.translations = { [languageTag]: translationGetters[languageTag]() }
i18n.locale = languageTag
}
并将此功能导入您想使用该功能的组件中App.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { setI18nConfig, translate } from './locale';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
setI18nConfig(); // This should be called only once through out the app at the time of changing locale.
return (
<View>
<Text> translate ('key_from_json_to_label') </Text>
</View>
);
}
}
有关更多详细信息,您可以在我已经实现相同的位置refer this repo。>>希望这会有所帮助。