xcarpentier/ex-react-native-i18n

Both in android and ios locale always returns 'en'

raarts opened this issue ยท 9 comments

My code:

import I18n from 'react-native-i18n';
const deviceLocale = I18n.locale;

returns 'en' on a Dutch emulator. So does I18n.currentLocale()

Version:

{
  "name": "neemop-app",
  "version": "0.0.0",
  "description": "Hello Expo!",
  "author": null,
  "private": true,
  "main": "main.js",
  "dependencies": {
    "expo": "17.0.0",
    "react": "16.0.0-alpha.6",
    "react-native": "https://github.com/expo/react-native/archive/sdk-17.0.0.tar.gz",
    "react-native-elements": "^0.12.2",
    "react-native-i18n": "git+https://github.com/xcarpentier/ex-react-native-i18n.git",
    "react-navigation": "^1.0.0-beta.11"
  }
}

Following the example code:

  async componentWillMount() {
    console.log('App await locale');
   try {
      await I18n.initAsync();
    }
    catch (e) {
      console.log(e);
      return;
    }
    console.log('App locale done');
  }

I put this in my App component, but the component that shows the current locale is rendered while await is waiting for I18n.initAsync to finish. I am now using the above code in all components, and use forceUpdate() at the end. Even though I doubt that is the correct approach.

Maybe this should be labeled as a request for a better example?

Hello @raarts,
Sorry ๐Ÿ™ˆ
If you follow expo example you have a state on your main component named appIsReady... I think you should get locale before setting appIsReady to true...

Thanks! BTW the example also mentions import I18n from 'ex-react-native-i18n', but of course it should be import I18n from 'react-native-i18n' ;-)

Where can i find the expo example you guys are talking about?

There is not yet an example yet but it's a good idea, I will do that.
Thanks.

Hi @raarts, based on this issue, @xcarpentier is now recommending that we do this:

async componentWillMount() {
    await I18n.initAsync();
}

But this doesn't make sense to me since componentWillMount runs asynchronously and there's nothing after initAsync. So it could have just as easily been written like this:

componentWillMount() {
    I18n.initAsync();
}

In other words, why is async/await needed here?

Thanks,
Alvaro

@alvaro1728 Right. I think the example is incomplete, in real life you want to set appIsReady : true after the I18n.initAsync call, and that's why you await it. Lightly edited from my own code:

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

  async componentWillMount() {
    const [dummy, deviceCountry, currentTimeZone ] = await Promise.all([
      I18n.initAsync(),
      Expo.Util.getCurrentDeviceCountryAsync(),
      Expo.Util.getCurrentTimeZoneAsync(), 
      // I persist the store on a regular basis, and load it here at app startup
      // load assets and fonts here...
    ]);

    this.setState({appIsReady: true }); // when all above promises above are resolved
  }

  render() {
    if (!this.state.appIsReady) {
      return (
        <Provider store={store}>
        <View>
          <AppLoading />
        </View>
        </Provider>
      );
    }

    return(
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    )
  }

I'm getting an unhandled promise rejection on the following

async componentWillMount() {
const [dummy, deviceCountry, currentTimeZone ] = await Promise.all([
I18n.initAsync(),
Expo.Util.getCurrentDeviceCountryAsync(),
Expo.Util.getCurrentTimeZoneAsync(),
// I persist the store on a regular basis, and load it here at app startup
// load assets and fonts here...
]);

Any ideas?

@napoleonjones In an new app I recently started I also had troubles with i18n I could not fix, I ended up switching to i18next and react-i18next.