Translate your expo.io (react-native) mobile application

in technology •  7 years ago 

In this getting started guide you will learn how to translate your mobile application created using expo.io. The code works also for pure react-native projects, but expo.io did an awesome job lowering the entry hurdle using react-native.

For instrumenting our code we will use react-i18next which is the react.js integration for the i18next framework: learn once — translate everywhere.

The result:

If you like to directly get to the running example and check the code on github just open: https://github.com/i18next/react-i18next/tree/master/example/react-native-expo

First step

To get started we used create-react-native-app as it takes away the complete pain of start using react-native.

npm start

And you will get the nice qr code to start your app directly in the expo.io app. Awesome.

Translate your views

In the next step you will need to add i18next and react-i18next packages:

npm i i18next react-i18next --save

Create a first file to configure and init i18next i18n.js:

import i18n from 'i18next';
import Expo from 'expo';
// creating a language detection plugin using expo
// http://i18next.com/docs/ownplugin/#languagedetector
const languageDetector = {
  type: 'languageDetector',
  async: true, // async detection
  detect: (cb) => {
    return Expo.Util.getCurrentLocaleAsync()
      .then(lng => { cb(lng); })
  },
  init: () => {},
  cacheUserLanguage: () => {}
}
i18n
  .use(languageDetector)
  .init({
    fallbackLng: 'en',
    // the translations
    // realworld load that via xhr or bundle those using webpack    
    resources: {
      en: {
        home: {
          title: 'Welcome''
        }
      },
      de: {
        home: {
          title: 'Willkommen'
        }
      },
      // have a initial namespace
      ns: ['translation'],
      defaultNS: 'translation',
      interpolation: {
        escapeValue: false // not needed for react
      }
  });
export default i18n;

For realworld usage you should load the translation using:

Getting a translation function to your components

Now it’s time to expose the i18n instance to your components by first adding a i18nextProvider which will expose needed functionality using react context.

To make this sample more useful we also integrate react-navigation.

In your app.js:

import React from 'react';
import { I18nextProvider, translate } from 'react-i18next';
import { StackNavigator } from 'react-navigation';
// the previous created file
import i18n from './js/i18n';
// our content pages
import Home from './js/pages/Home';
import Page2 from './js/pages/Page2';
// the navigation stack
const Stack = StackNavigator({
  Home: { screen: Home },
  Page2: { screen: Page2 }
});
// Wrapping a stack with translation hoc asserts we trigger new render on language change
// the hoc is set to only trigger rerender on languageChanged
const WrappedStack = () => {
  return <Stack screenProps={{ t: i18n.getFixedT() }} />;
}
const ReloadAppOnLanguageChange = translate('translation', {
  bindI18n: 'languageChanged',
  bindStore: false
})(WrappedStack);
// The entry point using a react navigation stack navigation
// gets wrapped by the I18nextProvider enabling using translations
// https://github.com/i18next/react-i18next#i18nextprovider
export default class App extends React.Component {
  render() {
    return (
      <I18nextProvider i18n={ i18n }>
        <ReloadAppOnLanguageChange />
      </I18nextProvider>
    );
  }
}

Now your ready to wrap your component with the translate hoc to pass down a translation function. Your pages will look like this:

import React from 'react';
import { translate } from 'react-i18next';
import { StyleSheet, Text, View, Button } from 'react-native';
// using the translation hoc to provie t function in props using home as default namespace
// https://github.com/i18next/react-i18next#translate-hoc
@translate(['home', 'common'], { wait: true })
export default class Home extends React.Component {
  static navigationOptions = ({ navigation, screenProps }) => ({
    title: screenProps.t('home:title')
  });
render() {
    const { t, i18n, navigation } = this.props;
    const { navigate } = navigation;
return (
      <View style={styles.container}>
        <Text>{t('common:currentLanguage', { lng: i18n.language })}</Text>
        <Button
          onPress={() => { i18n.changeLanguage('en') }}
          title={t('common:actions.toggleToEnglish')}
        />
        <Button
          onPress={() => { i18n.changeLanguage('de') }}
          title={t('common:actions.toggleToGerman')}
        />
        <Text style={styles.separate}>{t('introduction')}</Text>
        <Button
          onPress={() => navigate('Page2')}
          title={t('common:actions.goToPage2')}
        />
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  separate: {
    marginTop: 50
  }
});

You can use i18n.changeLanguage(lng) to change the language pragmatically.

For richer translation options there is the trans component which allows you to translate nested react components like:

<Trans i18nKey="userMessagesUnread" count={count}>
    Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
</Trans>

Thats all needed to get your react-native application translated.

Learn more:

Checkout the working sample: https://github.com/i18next/react-i18next/tree/master/example/react-native-expo

react-i18next documentation: https://react.i18next.com
i18next documentation: http://i18next.com



follow me on:
steemit
twitter

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!