DEV Community

Cover image for Configuring i18n for react
Abhijeet Yadav
Abhijeet Yadav

Posted on

Configuring i18n for react

This post is second in series of react i18n integration.

To summarise the previous post, we installed bunch of dependency related to i18next library. Then we created locale folder inside the public directory.

Now let's see how those steps come together to make a config file.

Start by creating a file i18n.js inside src/utils/ directory.
paste the following code...

import LocalStorageBackend from 'i18next-localstorage-backend';
import XHRBackEnd from 'i18next-xhr-backend';

export const isDevelopmentEnv = process.env.NODE_ENV === 'development';

export const backEnds = isDevelopmentEnv ? [XHRBackEnd] : [LocalStorageBackend, XHRBackEnd];

export const loadPath = () => '/locales/{{lng}}/{{ns}}.json';

export const backEndOptions = isDevelopmentEnv
  ? [{ loadPath }] : [{ prefix: 'app_name_', versions: { en: 'v1', es: 'v1' } }, { loadPath }];
Enter fullscreen mode Exit fullscreen mode

Let's break this line by line

import LocalStorageBackend from 'i18next-localstorage-backend';
Enter fullscreen mode Exit fullscreen mode

Provides option to store the translated contents once downloaded.

import XHRBackEnd from 'i18next-xhr-backend';
Enter fullscreen mode Exit fullscreen mode

Loads translations from the locales directory.

export const loadPath = () => '/locales/{{lng}}/{{ns}}.json';
Enter fullscreen mode Exit fullscreen mode

loadPath when executed translates to '/locales/en/home.json' OR '/locales/es/home.json'. ns stands for namespace which is defaulted to fileName.

export const backEndOptions = isDevelopmentEnv
  ? [{ loadPath }] : [{ prefix: 'app_name_', versions: { en: 'v1', es: 'v1' } }, { loadPath }];
Enter fullscreen mode Exit fullscreen mode

What does prefix and the versions option inside the backEndOptions stand for?.

Let's say your app is released to production, when the user downloads and opens the web page, the translations are saved in localStorage. What if we make a hotfix after the release. The hotfix contains additional translations. How do we let the app know that the content stored in localStorage is a stale one. We do that by bumping the version number. When version don't match new request is made to translate recent contents.

export const isDevelopmentEnv = process.env.NODE_ENV === 'development';
Enter fullscreen mode Exit fullscreen mode

What is isDevelopmentEnv boolean flag.

You see, when we imported i18next-localstorage-backend on the first line we did so with the intention of using localstorage to store all the translations once it was downloaded. However, this may not be the ideal behaviour we would expect when developing since we may keep changing the translation files.

Sigh!

Let's now create our config file named i18n.js inside the src/ directory. Remember the one we created above was utils for our config file.

Add the following code...

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-chained-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { backEnds, backEndOptions, isDevelopmentEnv } from 'utils/i18n';

if (isDevelopmentEnv) {
  window.i18n = i18n; //useful for debugging
}

i18n
  .use(Backend) 
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    ns: ['common'],
    defaultNS: 'common',
    fallbackLng: 'en',
    debug: true,
    load: 'languageOnly',
    returnObjects: true,
    joinArrays: true,
    cleanCode: true,
    interpolation: {
      escapeValue: false,
    },
    react: {
      wait: true,
      useSuspense: false,
    },
    backend: {
      backends: backEnds,
      backendOptions: backEndOptions,
    },
  });

export default i18n;
Enter fullscreen mode Exit fullscreen mode

Going through each and every config option is beyond the scope of this blog post. Let's quickly glance over the one's that are important.

.use(Backend) 
Enter fullscreen mode Exit fullscreen mode

Chains multiple backend provided in the utils, namely XHR and LocalStorage.

.use(LanguageDetector)
Enter fullscreen mode Exit fullscreen mode

Detects Language in given order...

['querystring', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag', 'path', 'subdomain']. Querystring used is ?lng. When set the contents are translated.

use(initReactI18next)
Enter fullscreen mode Exit fullscreen mode

provides react bindings.

ns: ['common'],
Enter fullscreen mode Exit fullscreen mode

ns stands for namespace. When the app is bootstrapped, files mentioned in the ns list are downloaded. Above example downloads common.json file.

defaultNS: 'common',
Enter fullscreen mode Exit fullscreen mode

When binding translation key to view, the keys will be searched inside the common namespace unless explicitly mentioned otherwise.

fallbackLng: 'en',
Enter fullscreen mode Exit fullscreen mode

If language is not mentioned it will fallback to en. Hence the loadPath defined in utils file will be equal to '/locales/en/common.json'

load: 'languageOnly',
Enter fullscreen mode Exit fullscreen mode

If not set to languageOnly. The lng inside the loadPath will default to en-EN or es-Es.

react: {
 wait: true,
 useSuspense: false,
}
Enter fullscreen mode Exit fullscreen mode

since the process of loading translation file is asynchronous, How should we let our React app know that the file are being fetched? before it shows flash of key,value bindings instead of actual translations. We do that by setting above flags.

I guess, that's it for the config file. In the next post we will look into the providers that will consume the above config and spit out API's for changing language, loading name space based on routes.

Find the github repo containing all codes mentioned in this series here

Top comments (0)