We write a multilingual application on React Native

We write a multilingual application on React Native

The localization of products is very important for international companies that develop new countries and regions. Similarly, localization is needed for mobile applications. If a developer starts 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 app using the package react-native-localize.

Skillbox recommends: Educational online course "Profession Java Developer".
We remind you: for all readers of "Habr" - a discount of 10 rubles when enrolling in any Skillbox course using the "Habr" promotional code.

Tools and skills

Understanding this article requires basic React Native skills. To get acquainted with the settings of the working machine, you can use 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 we create a new project using react-native-cli. To do this, in the terminal you need to type this:

$ react-native init multiLanguage
$ cd multilanguage

Adding the required libraries

The first step is to install react-native-localize by typing the following:
$ yarn add react-native-localize

If you encounter problems during the installation process, check out the installation manual.

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

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

$ 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 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 textual information.

Value (value) is the text that needs to be shown to the user.

English:

{ "hello": "Hello World!"}

French

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

Arab

{ "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 imports 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 will be 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 (
      <SafeAreaView style={styles.safeArea}>
        <Text style={styles.value}>{translate("hello")}</Text>
      </SafeAreaView>
    );
  }
}
 
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 we need to add an event listener to componentDidMount() , this element will listen for updates and call handleLocalizationChange() when they occur.

The handleLocalizationChange() method invokes setI18nConfig() and forceUpdate(). This is necessary for Android devices, as the component must be rendered in order for the changes to become visible.

Then we need to remove the listener from the componentWillUnmount() method.

Finally, hello is returned in render() by using translate() and adding a key parameter to it. After these steps, the application will be able to β€œunderstand” which language is needed and show messages in it.

Application launch

Now is the time to check how the translation works.

First we run the application in the simulator or emulator by typing

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

It will look something like this:

We write a multilingual application on React Native

Now you can try to change the language to French by launching the application.

We write a multilingual application on React Native

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

So far everything is going well.

But what happens if you select a random language that doesn't have a translation in the app?

It turns out that the task of findBestLanguage is to provide the best possible translation among all available. As a result, the language that was set by default will be displayed.

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

We write a multilingual application on React Native

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

bonus

react-native-localize has an API that provides access to a large number of language elements. Before starting work, it is worth reading 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 range of users of your application.

Project source code is here.

Skillbox recommends:

Source: habr.com

Add a comment