如何将本地化信息从 react 组件中的 this.context 传递到其子常量?



我已经根据这个文件实现了 React-native 应用程序的本地化作为 LocalizationContext.js:

import React from 'react';
import Translations, {DEFAULT_LANGUAGE} from '../constants/Translations';
import AsyncStorage from '@react-native-community/async-storage';
import * as RNLocalize from 'react-native-localize';
const APP_LANGUAGE = 'appLanguage';
export const LocalizationContext = React.createContext({
Translations,
setAppLanguage: () => {},
appLanguage: DEFAULT_LANGUAGE,
initializeAppLanguage: () => {},
});
export const LocalizationProvider = ({children}) => {
const [appLanguage, setAppLanguage] = React.useState(DEFAULT_LANGUAGE);
const setLanguage = language => {
Translations.setLanguage(language);
setAppLanguage(language);
AsyncStorage.setItem(APP_LANGUAGE, language);
};
const initializeAppLanguage = async () => {
const currentLanguage = await AsyncStorage.getItem(APP_LANGUAGE);
if (!currentLanguage) {
let localeCode = DEFAULT_LANGUAGE;
const supportedLocaleCodes = Translations.getAvailableLanguages();
const phoneLocaleCodes = RNLocalize.getLocales().map(
locale => locale.languageCode,
);
phoneLocaleCodes.some(code => {
if (supportedLocaleCodes.includes(code)) {
localeCode = code;
return true;
}
});
setLanguage(localeCode);
} else {
setLanguage(currentLanguage);
}
};
return (
<LocalizationContext.Provider
value={{
Translations,
setAppLanguage: setLanguage,
appLanguage,
initializeAppLanguage,
}}>
{children}
</LocalizationContext.Provider>
);
};

它在不同的屏幕上工作正常,但 App.js 文件,如下所示:

const MainTabs = createBottomTabNavigator(
{
Profile: {
screen: ProfileStack,
navigationOptions: {
// tabBarLabel: Translations.PROFILE_TAB,
},
},
HomePage: {
screen: HomeStack,
navigationOptions: {
tabBarLabel: Translations.HOME_TAB,
},
},
},
{
initialRouteName: 'HomePage'
},
},
);
export default class App extends Component {
// static contextType = LocalizationContext;
render() {
// const Translations = this.context.Translations;
// console.log(Translations.PROFILE_TAB);
return (
<LocalizationProvider>
<SafeAreaView style={{flex: 1}}>
<AppNavigator />
</SafeAreaView>
</LocalizationProvider>
);
}
}

我确实访问了应用程序中的翻译组件,因为您可以在注释行中找到它们,但是如何将相关信息传递给某些常量,例如选项卡标题?Translations.PROFILE_TAB未定义。

我最终将其更改为服务。 此外,我还使用 redux 并将商店传入以获取用户首选项并设置它们:

import * as RNLocalize from 'react-native-localize';
import { saveUserOptions } from '../actions/login';
import LocalizedStrings from 'react-native-localization';
export const DEFAULT_LANGUAGE = 'ar';
let _reduxStore;
function setStore(store){
_reduxStore = store
}
const _translations = {
en: {
WELCOME_TITLE: 'Welcome!',
STEP1: 'Step One',
SEE_CHANGES: 'See Your Changes',
CHANGE_LANGUAGE: 'Change Language',
LANGUAGE_SETTINGS: 'Change Language',
BACK: 'Back'
},
ar: {
WELCOME_TITLE: 'صباحك فُل!',
...
}
};
let translation = new LocalizedStrings(_translations);
const setAppLanguage = language => {
translation.setLanguage(language);
_reduxStore.dispatch(saveUserOptions('user_language',language))
};

const initializeAppLanguage = async () => {
const currentLanguage = _reduxStore.getState().login.user_language
if (!currentLanguage) {
let localeCode = DEFAULT_LANGUAGE;
const supportedLocaleCodes = translation.getAvailableLanguages();
const phoneLocaleCodes = RNLocalize.getLocales().map(
locale => locale.languageCode,
);
phoneLocaleCodes.some(code => {
if (supportedLocaleCodes.includes(code)) {
localeCode = code;
return true;
}
});
setAppLanguage(localeCode);
} else {
setAppLanguage(currentLanguage);
}
};

export default {
setStore,
translation,
setAppLanguage,
initializeAppLanguage
} 

我需要首先在我的顶级主组件中设置东西:

LocalizationService.setStore(store)
...
// add the below to componentDidMount by which time persisted stores are populated usually
LocalizationService.initializeAppLanguage()

我需要在哪里获取字符串,我这样做:

import LocalizationService from '../../utils/LocalizationService';
....
static navigationOptions = () => {
// return here was needed otherwise the translation didn't work
return { 
title:   LocalizationService.translation.WELCOME_TITLE,
}
}

编辑要强制更新标题,您需要设置导航参数:

this.props.navigation.setParams({ otherParam: 'Updated!' })

**进一步编辑 ** 道具导航更改黑客仅适用于当前屏幕,如果我们想刷新所有屏幕,我们需要为所有屏幕设置参数。这可以使用每个屏幕上的侦听器或将屏幕导航选项绑定到 redux 状态来完成。

我正在使用导航服务(请参阅 https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html(,因此我创建了以下函数来运行我的屏幕并在所有屏幕上设置参数,并强制更新所有屏幕:

function setParamsForAllScreens(param, value) {
const updateAllScreens = (navState) => {
// Does this route have more routes in it?
if (navState.routes) {
navState.routes.forEach((route) => {
updateAllScreens(route)
})
}
// Does this route have a name?
else if (navState.routeName) {
// Does it end in Screen? This is a convention we are using
if (navState.routeName.endsWith('Screen')) {
// this is likely a leaf
const action = NavigationActions.setParams({
params: {
[param]: value
},
key: navState.key,
})
_navigator.dispatch(action)
}
}
}
if (_navigator && _navigator.state)
updateAllScreens(_navigator.state.nav)
}

最新更新