How to integrate i18n-js into React Native Expo app

I am having problems instantiating I18n in an Expo application. TL; The DR problem is that components that need translations are rendered before

Expo.Util.getLocaleAsync()

      

returns and sets the locale. I can't figure out the best way to set it up. At this point, I have a file for my I18n instance, which I then import and use throughout my application. It looks something like this:

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;

      

Then in my root app component, I do the following:

import 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);

      

The logs show the expected values ​​- first the default locale and then the updated locale in main2. The problem is that child views are rendered with the first locale before the change is made, and I don't understand why?

I can't figure out how best to do this, any ideas / advice would be much appreciated :-)

+3


source to share


2 answers


This is what worked for me:

In 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>
    );
  )

      

and in some component:

import I18n from '../i18n';

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

      

And from the root dir I created 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;

      

my original Dutch translation file in i18n/nl.json

:

{
  favorites: 'Jouw Favorieten',
}

      

I have this in my package.json

:

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

      

+2


source


This might be the solution for you: https://github.com/xcarpentier/ex-react-native-i18n



+1


source







All Articles