如何在React Native Expo应用程序中集成i18n-js

6

我在我的Expo应用程序中实例化I18n时遇到了问题。问题的TL;DR是需要翻译的组件在渲染之前。

Expo.Util.getLocaleAsync()

返回并设置语言环境。我无法弄清如何最好地设置它。目前,我有一个用于我的I18n实例的文件,然后我导入并在应用程序的其他地方使用它。它看起来像这样:

import Expo from 'expo';
import I18n from 'i18n-js';
import english from './resources/strings/en';
import danish from './resources/strings/da';

I18n.defaultLocale = 'en-GB';
I18n.fallbacks = true;

I18n.initAsync = async () => {
  var locale = 'en-GB';
  try {
    locale = await Expo.Util.getCurrentLocaleAsync();
  } catch (error) {
    console.log('Error getting locale: ' + error);
  }

  I18n.locale = locale ? locale.replace(/_/, '-') : '';
};

I18n.translations = {
  en: english,
  da: danish,
};

export default I18n;

然后,在我的根应用程序组件中,我执行以下操作:

导入I18n from './src/i18n';

class App extends React.Component {
  async componentWillMount() {
    console.log('Current locale (main1): ' + I18n.currentLocale());
    try {
      await I18n.initAsync();
    } catch (error) {
      console.log('Error setting locale ' + error);
    }

    console.log('Current locale (main2): ' + I18n.currentLocale());
  }

  render() {
    return <AppContainer />;
  }
}

Expo.registerRootComponent(App);

日志记录了预期值 - 首先是默认语言环境,然后是在main2中更新的语言环境。问题是更改之前子视图使用第一个语言环境进行渲染,我不明白为什么会这样?

我找不到更好的解决方法,有什么想法/提示将不胜感激 :-)


经过更多的搜索,似乎将componentWillMount()变成异步并不一定会使它等待await返回,正如Flow为我指出的那样。请参见此问题中的讨论:https://github.com/facebook/flow/issues/1803。这意味着这种策略不可行,必须以其他方式完成。至于如何完成,我还不知道 :-) - jhm
你有可行的解决方案吗?你能发布更新吗? - Yossi
1
我们最终在那个项目中没有做到这一点,但请查看https://docs.expo.io/versions/latest/sdk/localization/ @Yossi。 - jhm
3个回答

3
这是我成功的方法:
main.js 文件中:
import I18n from 'react-native-i18n';

class App extends React.Component {
  state = {
    appIsReady: false,
  }

  async componentWillMount() {
    await I18n.initAsync();
    this.setState({appIsReady: true});
  }

  render() {
    if (!this.state.appIsReady) {
      return (
          <AppLoading />
      );
    }
    return ( 
      <RootComponent>
    );
  )

并且在某些组件中:

import I18n from '../i18n';

  render() {
    return (
         <View>
           <Text>{I18n.t('favorites')}</Text>
           <Text>{I18n.locale}</Text>
         </View>
    )
  }

我从根目录创建了 i18n/index.js

import I18n from 'react-native-i18n';

I18n.fallbacks = true; // let 'en-GB' fallback to 'en' if not found
I18n.translations = {
  'en': require('./en.json'),
  'nl': require('./nl.json'),
}

export default I18n;

我的最初的荷兰语翻译文件在i18n/nl.json中:

{
  favorites: 'Jouw Favorieten',
}

我在package.json文件中有以下内容:

"react-native-i18n": "git+https://github.com/xcarpentier/ex-react-native-i18n.git",

1

嘿,Matty,感谢你的建议 :-) 我确实发现了相同的代码库,但是:1.它基本上使用相同的方法,因此将具有相同的问题;2.对于我的项目,我更喜欢不使用一个分支的分支,而是找出如何更好地实现原始的、更受支持的项目。从他在index.js中的代码来看,据我所知,他正在做完全相同的事情 :-) - jhm
所以你已经将 componentWillMount() 改成异步的了,并且在调用 setLocale() 之前加上了 await? - MattyK14
1
正确的,更新了问题以显示代码如何被调用 :-) - jhm

1
在React Native Expo中,这很容易。
1- 步骤 1:安装并导入。
expo install expo-localization

app.js

import { I18nManager } from 'react-native';
    import * as Localization from 'expo-localization';
    import i18n from 'i18n-js';

1- 步骤2:创建一个支持语言的对象。

i18n.translations = {
  en: { addPrice: 'add Price Here',subTax:' Sub Tax -'},
 ar: {addPrice: 'ادخل السعر هنا' ,subTax:'قبل ضريبة - '}
};

// Set the locale once at the starting app.

i18n.locale = Localization.locale;

// When a value is missing from a language it'll fallback to another language with the key present.

i18n.fallbacks = true;

//don't change app dir to rtl. 
I18nManager.forceRTL(false);
I18nManager.allowRTL(false);

1- 步骤3:到处使用它
<TouchableOpacity >

<Text >{i18n.t('subTax')}</Text>

</TouchableOpacity>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接