React Native,如何在语言更改后更新视图

IT技术 reactjs react-native view internationalization updates
2021-05-05 15:05:04

我想支持语言更改(由用户手动)。为此,我正在使用react-native-i18n我找到了如何在运行时更改显示语言,但我没有找到如何更新当前视图。

我的代码

在此处输入图片说明

环境

环境:

  • 节点:8.9.4
  • 纱线:1.3.2
  • npm:4.0.5

预期行为

当我使用I18n.locale ='en';not in function.. 时,文本将使用英语,而当我使用时I18n.locale ='he';,文本将使用希伯来语。但是我需要在运行时更改语言。所以我希望当我点击每个按钮时,语言会改变并显示出来。

实际行为

什么也没发生.. 我想我需要重新加载/重新渲染/更新视图,但我没有找到方法。

3个回答

你可以试试这样的

<View style={styles.container}>
    <Button onPress={this.setLocale()} title={strings('test.b1')}> 
</View>

public setLocale() {
    this.setState({stateOfLocale: 'en'});
    I18n.locale = stateOfLocale;
}

在我有按钮或选择更改语言的页面上,除非文本依赖于语言,否则不会发生任何事情。

在每个字符串上,我都可以像这样将语言环境作为可选参数传递,{I18n.t("email", { locale: language })}如果它发生变化,这将立即导致重新渲染。

无需重新启动或刷新。

在下面的示例中,我使用选择来修改状态中的语言。由于可选的 locale 参数,文本字段依赖于它,并将立即重新呈现。

为了保持更改,我实现了一个 Save 按钮,它将区域设置保存到 AsyncStorage 并调用在单独的 i18n.js 文件中定义的 changeLanguage 函数

import React, { useState } from "react";
import { View, Text, Button } from "react-native";
import I18n, { changeLanguage } from "../i18n/i18n";
import RNPickerSelect as Select from 'react-native-picker-select';
import AsyncStorage from '@react-native-async-storage/async-storage';

function ProfileScreen() {
  const locale = I18n.currentLocale();
  const [language, setLanguage] = useState(locale);

  const saveProfile = async () => {
    if (locale !== language) {
      AsyncStorage.setItem("language", language);
      changeLanguage(language);
    }
  }
  
  return (
  <View>
    <Text>{I18n.t("email", { locale: language })}</Text>
    <Select 
      value={language}
      onValueChange={(value) => setLanguage(value)}
      placeholder={I18n.t("selectAppLanguage")}
      items={[
        { label: I18n.t("English", { locale: language }), value: "en" },
        { label: I18n.t("Finnish", { locale: language }), value: "fi" },
        { label: I18n.t("Swedish", { locale: language }), value: "se" },
      ]}
    />
    <Button
      title={I18n.t("save", { locale: language })}
      onPress={saveProfile} 
    />    
  </View>
  );
}
export default ProfileScreen;

这是我的 i18n.js 文件。我正在使用 react-native-localize 因为 react-native-i18n 不再维护并且一旦发布就会在 Android 上产生问题。改变语言就这么简单I18n.locale = lang

//i18n/i18n.js
import I18n from "i18n-js";
import * as RNLocalize from "react-native-localize";
import en from './languages/en';
import fi from './languages/fi';
import se from './languages/se';

const locales = RNLocalize.getLocales();

if (Array.isArray(locales)) {
  I18n.locale = locales[0].languageCode;
}

export const changeLanguage = lang => {
  if (lang) {
    I18n.locale = lang;
  } else if (Array.isArray(locales)) {
    I18n.locale = locales[0].languageCode;
  }
}

I18n.fallbacks = true;

I18n.translations = {
  en,
  fi,
  se,
};

export default I18n;

最后一件事,在 App.js 中,在应用程序启动时,我从 useEffect 内部的本地存储中检索语言并覆盖设备的语言。所以语言是坚持的。

//App.js
import React, { useEffect } from "react";
import I18n, { changeLanguage } from "./src/i18n/i18n";
import AsyncStorage from '@react-native-async-storage/async-storage';

function App() {
  useEffect(() => {
    const setLanguage = async () => {
      const language = await AsyncStorage.getItem("language");
      changeLanguage(language)
    }
    setLanguage()
  }, [])
  return ( // ...navigation, etc.
  );
}
export default <App />

这里有几点建议,

  1. 当您的应用程序初始化时,您可以设置 I18n.locale
      I18n.locale = 'en'
  1. 当您尝试更改语言时,请确保所有组件都有 i18n 翻译,即。i18.t()I18n.translate功能如下图:
  ...
  <TouchableOpacity>
    <View>
     <Text>{I18n.t('LANG.CHANGE')}</Text>
   </View>
  </TouchableOpacity>
  ...

你的 en.json

  ...
  { 
    'LANG': {
       'CHANGE': "Change Language"
     }
  }
  ...
  1. 在语言更改时,即当您更改时i18.locale,您可以通知所有连接到 store 的组件,以便它们重新渲染,即典型的 react-redux 流程。

希望这可以帮助。