【问题标题】:Dynamically toggle language and re-render react-native app动态切换语言并重新渲染 react-native 应用程序
【发布时间】:2021-10-01 00:28:03
【问题描述】:

我正在通过阅读一些博客并尝试在使用 Drawer(主页和关于屏幕)、堆栈(主页 -> 设置)和选项卡(主页和关于屏幕)导航的测试应用程序上复制这些概念来学习 react-native。到目前为止,一切顺利。

我正在使用 'react-native-localize'、'i18n-js' 和 'lodash.memoize' 来制作应用程序的多语言。在启动过程中,应用程序成功地从设备设置中确定了当前的区域设置,并根据区域设置显示正确的内容。

但是,我希望能够通过按设置屏幕上的切换语言按钮来动态更改它。我不知道如何更改语言环境并使整个应用程序(抽屉菜单选项名称、底部选项卡名称和所有屏幕文本内容)重新呈现和显示来自新语言环境的文本。有人可以帮帮我吗?

App.js

import * as i18n from './src/utils/i18n';

const App = () => {

  const [locale, setLocale] = useState(i18n.DEFAULT_LANGUAGE);
  const localizationContext = useMemo(
    () => ({
      t: (scope, options) => i18n.t(scope, {locale, ...options}),
      locale,
      setLocale
    }),
    [locale],
  );

  const handleLocalizationChange = useCallback(
    (newLocale) => {
      const newSetLocale = i18n.setI18nConfig(newLocale);
      setLocale(newSetLocale);
    },
    [locale],
  );

  useEffect(() => {
    handleLocalizationChange();

    RNLocalize.addEventListener('change', handleLocalizationChange);
    return () => {
      RNLocalize.removeEventListener('change', handleLocalizationChange);
    };
  }, []);
 
  return (
   <LocalizationContext.Provider value={localizationContext}>
      <NavigationContainer>
        <DrawerNavigator localizationChange={handleLocalizationChange}/>
      </NavigationContainer>
    </LocalizationContext.Provider>
  );
};

export default App;

i18n.js

import {I18nManager} from 'react-native';
import * as RNLocalize from 'react-native-localize';
import i18n from 'i18n-js';
import memoize from 'lodash.memoize';

export const DEFAULT_LANGUAGE = 'en';

export const translationGetters = {
  'en': () => require('../locales/en.json'),
  'es': () => require('../locales/es.json'),
};

export const translate = memoize(
  (key, config) => i18n.t(key, config),
  (key, config) => (config ? key + JSON.stringify(config) : key),
);

export const t = translate;

export const setI18nConfig = (codeLang = null) => {
  // Fallback if no available language fits
  const fallback = {languageTag: DEFAULT_LANGUAGE, isRTL: false};
  const lang = codeLang ? {languageTag: codeLang, isRTL: false} : null;
  
  const {languageTag, isRTL} = lang
    ? lang
    : RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
      fallback;

  // Enables fallbacks
  i18n.fallbacks = true;

  // Clear translation cache
  translate.cache.clear();

  // Update layout direction
  I18nManager.forceRTL(isRTL);

  // Set i18n-js config
  i18n.translations = {[languageTag]: translationGetters[languageTag]()};
  i18n.locale = languageTag;
  
  return languageTag;
};

DrawerNavigation.js

import React, { useContext } from "react";

import { AboutStackNavigator } from "./StackNavigator";
import TabNavigator from "./TabNavigator";

import { createDrawerNavigator } from "@react-navigation/drawer";

import LocalizationContext from '../providers/LocalizationContext';

const Drawer = createDrawerNavigator();

const DrawerNavigator = () => {
  const {t} = useContext(LocalizationContext);
  
  return (
    <Drawer.Navigator
      drawerContentOptions={{
        activeTintColor: 'gray',
        inactiveTintColor: 'gray',
      }}
    >
      <Drawer.Screen 
        name="Home" 
        component={ TabNavigator } 
        options={{
          title: t('title_home')
        }} 
      />
      <Drawer.Screen 
        name="About" 
        component={ AboutStackNavigator } 
        options={{
          title: t('title_about')
        }} 
      />
    </Drawer.Navigator>
  );
};

export default DrawerNavigator;

StackNavigator.js

import React, { useContext } from "react";
import { createStackNavigator } from "@react-navigation/stack";

import Home from "../screens/Home";
import About from "../screens/About";
import Settings from "../screens/Settings";

import LocalizationContext from '../providers/LocalizationContext';

const Stack = createStackNavigator();

const MainStackNavigator = () => {
  const {t} = useContext(LocalizationContext);
  return (
    <Stack.Navigator screenOptions={screenOptionStyle}>
      <Stack.Screen name="Home" component={ Home } options={{ headerShown:false }} />
      <Stack.Screen name="About" component={ About } options={{ title: t('title_about') }}/>
      <Stack.Screen name="Settings" component={ Settings } options={{ title: t('title_settings') }}/>
    </Stack.Navigator>
  );
};

const AboutStackNavigator = () => {
  const {t} = useContext(LocalizationContext);
  return (
    <Stack.Navigator screenOptions={screenOptionStyle}>
      <Stack.Screen name="About" component={ About } options={{ title: t('title_about') }} />
    </Stack.Navigator>
  );
};

const SettingsStackNavigator = () => {
  const {t} = useContext(LocalizationContext);
  return (
    <Stack.Navigator screenOptions={screenOptionStyle}>
      <Stack.Screen name="Settings" component={ Settings } options={{ title: t('title_settings') }} />
    </Stack.Navigator>
  );
};

const screenOptionStyle = {
  headerStyle: {
    backgroundColor: 'white',
  },
  headerTintColor: "gray",
  headerBackTitle: "Back",
};

export { 
  MainStackNavigator, 
  AboutStackNavigator, 
  SettingsStackNavigator 
};

TabNavigator.js

import React, { useContext } from 'react';

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

import { MainStackNavigator, AboutStackNavigator } from './StackNavigator';

import LocalizationContext from '../providers/LocalizationContext';

const Tab = createBottomTabNavigator();

const BottomTabNavigator = () => {
  const {t} = useContext(LocalizationContext);

  return (
    <Tab.Navigator
      tabBarOptions={{
        activeTintColor: 'black',
        inactiveTintColor: 'gray',
        activeBackgroundColor: 'white',
        inactiveBackgroundColor: 'white',
        labelStyle: {
          fontSize: 12,
        },
      }} >
      <Tab.Screen name="Home" component={ MainStackNavigator } options={{ title: t('title_home') }} />
      <Tab.Screen name="About" component={ AboutStackNavigator } options={{ title: t('title_about'), headerShown:false }} />
    </Tab.Navigator>
  );
}

export default BottomTabNavigator;

Home.js

import React, { useContext } from "react";
import { View, SafeAreaView, StyleSheet, Text, StatusBar } from "react-native";
import { Header } from 'react-native-elements';

import LocalizationContext from '../providers/LocalizationContext';

const Home = ({ navigation }) => {
  const {t} = useContext(LocalizationContext);
  
  return (
    <SafeAreaView style={styles.container}>
      <StatusBar barStyle="dark-content" backgroundColor='white' />
        <Header
          statusBarProps={{ barStyle: 'dark-content', backgroundColor: 'gray' }}
          placement="center"
          leftComponent={{ icon: 'menu', color: 'white', onPress: () => navigation.openDrawer() }}
          centerComponent={{ text: 'My App', style: styles.centerComponent }}
          rightComponent={{ icon: 'settings', color: 'white', onPress: () => navigation.navigate("Settings") }}
          containerStyle={{ backgroundColor: 'gray', justifyContent: 'space-around' }}
        /> 
        <View style={styles.center}>
          <Text>{t('text_home')}</Text>
        </View>
      </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  center: {
    flex: 1,
    backgroundColor: 'white',
    justifyContent: "center",
    alignItems: "center",
    textAlign: "center",
  },
  container: {
    flex: 1,
    backgroundColor: 'white',
  },
  centerComponent: {
    color: 'white', 
    fontWeight: 'bold', 
    fontSize: 20
  },
    
});

export default Home;

Settings.js

import React, { useContext, useState } from "react";
import { View, StyleSheet, Text, StatusBar, Button } from "react-native";

import LocalizationContext from '../providers/LocalizationContext';

const Settings = () => {
  const {t} = useContext(LocalizationContext);

  const [locale, setLocale] = useState('en');

  const toggleLanguage = (locale) => {
    setLocale(locale);
    console.log(locale);
  };

  return (
    <View style={styles.center}>
      <StatusBar barStyle="dark-content" backgroundColor='white' />
      <View style={styles.center}>
          <Text>{t('text_setings')}</Text>
          <Button onPress={() => toggleLanguage(locale == "es" ? "en" : "es")} title={locale == "es" ? "EN" : "ES"} />
        </View>
    </View>
  );
};

const styles = StyleSheet.create({
  center: {
    flex: 1,
    backgroundColor: 'white',
    justifyContent: "center",
    alignItems: "center",
    textAlign: "center",
  },
});

export default Settings;

【问题讨论】:

    标签: react-native localization internationalization render


    【解决方案1】:

    要允许更改语言显示,您可以使用以下方法(假设您要显示英语、法语和德语):

    1. 使用以下内容创建一个 globals.js(如果需要,添加更多项目):
    module.exports = {
    
    eunit:["Eldery Unit", "Unité des personnes âgées", "Senioreneinheit"],      
    skeysearch:["Search by Name", "Recherche par nom", "Suche mit Name"],       
    sstatus: ["Status", "Statut", "Status"]
    
    };
    
    
    1. 在您的 js 页面顶部添加以下行:
    GLOBAL = require('./globals');
    
    1. 在要显示不同语言的地方,使用以下命令:
    GLOBAL.skeysearch[this.state.lang]
    
    1. 根据您的需要更改语言状态。 (比如点击一个按钮), 所以,
    this.state.lang=0 for English 
    this.state.lang=1 for French
    this.state.lang=2 for German
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 2018-12-27
      • 1970-01-01
      • 2022-08-12
      相关资源
      最近更新 更多