Writing a multilingual application on React Native

Original author: Vikrant Negi
  • Transfer


Localization of products is very important for international companies exploring new countries and regions. Similarly, localization is needed for mobile applications. If a developer begins international expansion, it is important to give users from another country the opportunity to work with the interface in their native language. In this article, we will create a React Native application using the react-native-localize package .

Skillbox recommends: The on-line educational course "Profession Java-developer" .
We remind you: for all readers of “Habr” - a discount of 10,000 rubles when registering for any Skillbox course using the “Habr” promo code.

Tools and skills


To understand this article, you need basic React Native skills. To familiarize yourself with the settings of the working machine, you can use the official instructions .

We need these versions of software tools:
  • Node v10.15.0
  • npm 6.4.1
  • yarn 1.16.0
  • react-native 0.59.9
  • react-native-localize 1.1.3
  • i18n-js 3.3.0

Getting started


We will create an application that will support English, French and Arabic. First, create a new project using react-native-cli. To do this, type the following in the terminal:

$ react-native init multiLanguage
$ cd multiLanguage


Add the required libraries

First, install react-native-localize by typing the following:
$ yarn add react-native-localize

If problems arise during the installation, it’s worth study the installation manual .

The react-native-localize library gives the developer access to multilingual functions. But she needs another library - i18n.

This article describes the use of I18n.js in order to provide JavaScript translation.

$ yarn add i18n-js

Well, since i18n-js does not provide caching or memoization, I suggest using lodash.memoize for this:

$ yarn add lodash.memoize

Working with translations

In order for the application to work skillfully with other languages, you first need to create a translations directory inside src, then three JSON files for each of the languages.

1. en.json for English;

2. fr.json for French;

3. ar.json for Arabic.

These files contain JSON objects with keys and values. The key will be the same for each language. It is used by the application to display text information.

The value is the text to be shown to the user.

English:

{"Hello": "Hello World!"}

French

{"hello": "Salut le Monde!"}

Arabic

{"hello": "أهلاً بالعالم"}

Other languages ​​can be added in the same way.

Main code


At this point, you need to open the App.js file and add the import to it:

import React from "react";
import * as RNLocalize from "react-native-localize";
import i18n from "i18n-js";
import memoize from "lodash.memoize"; // Use for caching/memoize for better performance
import {
  I18nManager,
  SafeAreaView,
  ScrollView,
  StyleSheet,
  Text,
  View
} from "react-native";

After that, auxiliary functions and constants are added, which are useful later.

const translationGetters = {
  // lazy requires (metro bundler does not support symlinks)
  ar: () => require("./src/translations/ar.json"),
  en: () => require("./src/translations/en.json"),
  fr: () => require("./src/translations/fr.json")
};
const translate = memoize(
  (key, config) => i18n.t(key, config),
  (key, config) => (config ? key + JSON.stringify(config) : key)
);
const setI18nConfig = () => {
  // fallback if no available language fits
  const fallback = { languageTag: "en", isRTL: false };
  const { languageTag, isRTL } =
    RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
    fallback;
  // clear translation cache
  translate.cache.clear();
  // update layout direction
  I18nManager.forceRTL(isRTL);
  // set i18n-js config
  i18n.translations = { [languageTag]: translationGetters[languageTag]() };
  i18n.locale = languageTag;
};

Well, now let's create a component of the App class:

export default class App extends React.Component {
  constructor(props) {
    super(props);
    setI18nConfig(); // set initial config
  }
  componentDidMount() {
    RNLocalize.addEventListener("change", this.handleLocalizationChange);
  }
  componentWillUnmount() {
    RNLocalize.removeEventListener("change", this.handleLocalizationChange);
  }
  handleLocalizationChange = () => {
    setI18nConfig();
    this.forceUpdate();
  };
  render() {
    return (
      {translate("hello")}
    );
  }
}
const styles = StyleSheet.create({
  safeArea: {
    backgroundColor: "white",
    flex: 1,
    alignItems: "center",
    justifyContent: "center"
  },
  value: {
    fontSize: 18
  }
});

The first element - setI18nConfig () - sets the initial configuration.

Then you need to add event listener to componentDidMount (), this element will track updates and call handleLocalizationChange () when they happen.

The handleLocalizationChange () method activates setI18nConfig () and forceUpdate (). This is necessary for Android devices, since the component must be rendered so that the changes become noticeable.

Then you need to remove the listening from the componentWillUnmount () method.

Finally, hello is returned in render () by using translate () and adding the key parameter to it. After these actions, the application will be able to "understand" which language is needed, and display messages on it.

Application launch


Now is the time to check how the translation works.

First, run the application in a simulator or emulator by typing

$ react-native run-ios
$ react-native run-android

It will look something like this:



Now you can try changing the language to French, then launching the application.



We do the same with the Arabic language, there is no difference.

So far, so good.

But what happens if you select a random language whose translation is not in the application?

It turns out that the task of findBestLanguage is to provide the optimal translation of all available. As a result, the default language will be displayed.

It's about phone settings. So, for example, in the iOS emulator, you can see the order of languages.



If the selected language is not preferred, findBestAvailableLanguage returns undefined, so that the default language is displayed.

Bonus


React-native-localize has an API that provides access to a large number of language elements. Before you begin, you should familiarize yourself with the documentation .

conclusions


The application can be made multilingual without any problems. React-native-localize is a great option that allows you to expand the circle of users of the application.

The source code of the project is here .

Skillbox recommends:


Also popular now: