DEV Community

Nikolas ⚡️
Nikolas ⚡️

Posted on

Internationalize React application with i18n

Internationalization (also known as i18n) allows your application to be available in different locales. The aim of
internationalization is to remove the barriers to localizing or deploying an application internationally. Application's
users may speak different languages and have varying conventions for numbers, dates or strings.

In Javascript there are plenty of libraries for internationalization: i18next, node-gettext or gloablize.
However, in this article we will focus on using the i18next library with React.js.

React-i18next

react-i18next is an internationalization framework that can be used with both React and React Native apps. This framework
is based on i18next.

The i18next and react-i18next is the most popular duo when it comes to React localization. Here are the main
advantages of this solution for your application:

  • i18next can be used in any Javascript environment with any UI framework,
  • the library was created in 2011 and is available open source,
  • there is plenty of extensions that can be used with this solution.

Setup project

In this article I'll be using simple React project bootstrapped with Create React App (CRA) with the following command:

npx create-react-app react-i18n-project

After creating the project you can change the directory and start the server:

cd react-i18n-project
npm start
Enter fullscreen mode Exit fullscreen mode

Add the dependencies

As stated previously react-i18next is based on i18next, so we will need both packages to successfully translate
our app:

npm install react-i18next i18next i18next-browser-languagedetector --save

Speaking of extensions, i18next-browser-languagedetector is an i18next plugin used to detect user language in the
browser. It also supports features as cookies, localStorage, query strings and more.

Getting started

Let's start with basic config listed in i18n.js file:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    debug: true,
    fallbackLng: 'en',
    resources: {
      en: {
        translation: {
          // here we will place our translations...
        }
      }
    }
  });

export default i18n;
Enter fullscreen mode Exit fullscreen mode

We should have it imported in the index.js file:

import React from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App';

// import i18n (needs to be bundled ;))
import './i18n';

const root = createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

Let's quickly go through each line of the configuration file:

  • .use(LanguageDetector) - detects user language,
  • .use(initReactI18next) - passes the i18n instance to the module of react-i18next,
  • .init({... - inits i18next,
  • debug: true - helps in i18n debugging with browser's console,
  • fallbackLng: 'en' - sets default language to English,

Create translation files

In this section we are going to learn how to translate normal text from one language to another. We need to have some place
to store translated texts in all languages that we need. Let's create directory named eg. locales and inside we should
create JSON files with names corresponding to the language codes of the translations - es for Spanish, fr for French and
so on.

// locales/es.json
{
    "welcome": "Angular es mi framework Javascirpt favorito",
    "article": {
        "heading": "Por qué me gusta tanto Angular",
    }
};

// locales/fr.json
{
    "welcome": "Angular est mon framework Javascirpt préféré.",
    "article": {
        "heading": "Pourquoi j'adore Angular",
    }
};
Enter fullscreen mode Exit fullscreen mode

Disclaimer: I have no knowledge of Spanish and French. I used Google Translate to take these texts!

The last part of the setup is to import those JSON files to out config file:

// ...
import translation_es from './locales/es.json';
import translation_fr from './locales/fr.json';

// ...
resources: {
    es: {
        translations: translation_es
    },
    fr: {
        translations: translation_fr
    }
}
Enter fullscreen mode Exit fullscreen mode

Using Trans component and useTranslation hook

Now we have the translations ready. Of course the folders structure and file names may differ in your applications.
In much more complex apps it is recommended to come with better system where you can have separate translation files for
different views in your app or even use lazy loading to drastically improve your application performance.

To use the translations and translate the content we can use to solutions provided by i18next-react.

Trans component

import React from 'react';
import { Trans, useTranslation } from 'react-i18next'

function MyComponent() {
    return <h1><Trans i18nKey="welcome">Angular is my favorite Javascript framework</Trans></h1>;
}
Enter fullscreen mode Exit fullscreen mode

Please keep in mind that according to the documentation: "s long you have no React/HTML nodes integrated into a cohesive
sentence (text formatting like strong, em, link components, maybe others), you won't need it - most of the times you
will be using the good old t function". So, here is an alternative way to translate your content.

useTranslation

import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';

function MyComponent() {
  const { t, i18n } = useTranslation();

  return <h1>{t('welcome')}</h1>
}
Enter fullscreen mode Exit fullscreen mode

How to switch languages

Let's add s simple component with buttons that allows users to switch the language of our app.

import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';

const languages = {
    en: {displayName: 'English'},
    es: {displayName: 'Spanish'},
}

function MyComponent() {
    const { t, i18n } = useTranslation();

    return (
        <div>
            <h1>{t("welcome")}</h1>
            <div>
                <button
                    onClick={() => i18n.changeLanguage(languages.en)}
                    style={{
                        fontWeight: i18n.resolvedLanguage === languages.en ? "bold" : "normal",
                    }}
                >
                    {languages.en.displayName}
                </button>
                <button
                    onClick={() => i18n.changeLanguage(languages.es)}
                    style={{
                        fontWeight: i18n.resolvedLanguage === languages.es ? "bold" : "normal",
                    }}
                >
                    {languages.es.displayName}
                </button>
            </div>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

As you can see in the code example above useTranslation hook gives us possibility to read current active language and
change the language of the whole app.

Here we have added two buttons that switch the language of the app and the font weight of the text inside of them
indicates the active language.

As you may remember form the previous paragraphs we have installed i18next-browser-languagedetector and added it to
our config file. i18next tries to detect the browser language and automatically use that language if the corresponding
translation file is available.

Speaking of our buttons for switching languages - manually selected language is persisted in the localStorage and it will
be used as preferred language even after closing the browser and opening the app the other day.

Summary

There are many other topics to cover in terms of internationalization React apps using i18next. In the next articles
I'm going to explain how to handle plurals, interpolation and formatting dates. I hope that it was a great introduction
to the i18n, peace 🏻.

Top comments (0)