BlogInsightsHow-to?

Pluralization and React-Native: A How-To Guide

A guide for using Over-the-Air updates and pluralization with React-Native and Applanga

Pluralization and React-Native: A How-To Guide

As you start translating you App, sooner or later you will come across pluralization. Different languages have different concepts of pluralization rules; it's not always as simple as "one apple" and "two apples".

In this guide we will cover how to pluralize your translations in JavaScript together with the i18n library react-i18next and Applanga.

If you already want to get straight to examples, see our React-Native i18n example.

How Does Pluralization Work

To use plurals in React-Native it's common to use the react-i18next package. Let's assume we have a simple phrase "I buy X apple(s)". The amount of apples is calculated so we don't know it yet. Some languages have different rules depending on the amount. In english it's simple, if it's more than one OR zero then append an s.

For every rule we add the whole phrase to our dedicated string file which is a json file working with i18next. We use the string key buying-apples here. The plural rule is appended at the end of the key with an underscore plus the rule.

Possible rules are: zero, one, two, few, many, other.

For the english language we need the rules one, other and zero. This results in the following example:

//en.json
{
    "buying-apples_one": "I buy one apple",
    "buying-apples_other": "I buy two apples",
    "buying-apples_zero": "I don't buy apples",
}

Installation

First, we need to install our i18next and applanga dependencies:

$ npm install react-i18next i18next applanga-react-native --save

To be able to run applanga-react-native on Android we also need to add the Applanga maven repository to our app/build.gradle file:

repositories {
    maven { url 'https://maven.applanga.com/'}
}

For more information read the react-i18next getting-started article and our Applanga React-Native documentation.

Create String Files

We create two string files in a json format. One for english with the name en.json and one for german with the name de.json.

We create a few translations:

//en.json
{
    "test-1": "Hello Example",
    "buying-apples_one": "I buy one apple",
    "buying-apples_other": "I buy two apples",
    "buying-apples_zero": "I don't buy apples",
    "some_array-here": [
        "one",
        "two",
        "three"
    ]
}

Applanga supports the i18next json v4 Format.

Localization Initialization

We want to separate the i18n logic into a new file called: i18n.config.ts

First, we need to create a resource map for i18n with our en.json and de.json

// i18n.config.ts
import en from './strings/en.json';
import de from './strings/de.json';

var resources = {
  en: {
    translation: en,
  },
  de: {
    translation: de,
  },
}

We pass this resource map to i18n in a function we call later in our App.tsx.

// i18n.config.ts
async function initLocalisations(): Promise<void> {
  await i18n.use(initReactI18next).init({
    resources,
    //language to use if translations in user language are not available
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false, // not needed for react!!
    },
  });
}

We have now initialized i18n-next and we can use the plural forms of our strings. To make over-the-air updates work, we need applanga-react-native with its Applanga.localizeMapI18NextJsonV4() method.

Get the Over-the-Air Updates

In our example we create a method called initApplangaLocalisations which first updates all local translations with the newest one from your Applanga dashboard and then we pass those updates to our i18next instance.

Do the Applanga.update() Call

The first step is the Applanga update to get all newest over-the-air translations. Here we pass in all languages we want to update, otherwise Applanga will update only the current device language and it may not be the language you want to show later.

// i18n.config.ts
await Applanga.update(['en', 'de']);

Update your Translation Map

The method Applanga.localizeMapI18NextJsonV4(map) accepts a map of keys and its translations and returns its keys and updated translations as a promise.

If the keys and translations do not exist on your Applanga dashboard, run your iOS or Android app in Debug Mode and the map and all its keys and (local) translations will be uploaded.

Then we use the updated map as resources which we later pass on to our i18next instance.

// i18n.config.ts
var map = await Applanga.localizeMapI18NextJsonV4(m);

resources = {
  en: {
    translation: map.en,
  },
  de: {
    translation: map.de,
  },
};

Update your i18next Instance

Now we update the i18next instance with our translated strings. Note that we also call changeLanguage with our current language to actually let i18next know that the translations have been updated.

// i18n.config.ts
i18n.addResourceBundle('en', 'translation', resources.en.translation);
i18n.addResourceBundle('de', 'translation', resources.de.translation);
i18n.changeLanguage(i18n.language);

Start the Update

In our example we start the Applanga update and it's update to our i18next instance in an useEffect hook in our App.tsx.

// App.tsx
  const _init = async () => {
    var success = false;
    try {
      await initApplangaLocalisations();
      success = true;
    } catch (e) {
      console.log("Couldn't init localisations");
      console.log(e);
    }
    if (success) {
      setApplangaInitialized(success);
    }
  };

  useEffect(() => {
    _init();
  }, []);

Display your plural strings

To display i18next plural strings it's as easy as t('string_key', {count: myCount}) for example. myCount is the count of objects you are talking about, i18next takes care of choosing the right translation for you.

// App.tsx
<Section title={t('buying-apples', {count: 0})} />
<Section title={t('buying-apples', {count: 1})} />
<Section title={t('buying-apples', {count: 2})} />

Change language

You also can change a language as you would normally do with your i18next instance. Be aware that if you want to use the over-the-air updates from Applanga, you have to first do an update call with that language.

// LanguagePicker.tsx
i18n.changeLanguage(lang.name);

Related Articles