Skip to main content

Internationalization

i18next is an internationalization-framework written in and for JavaScript.

i18next provides:

For more information visit the website:

How to use: development​

Direct string translation​

In the case that we only need to translate a string without any dynamic content inside and without any HTML elements or React components, we simply need to use the following t() function, with the first parameter being the id or key that should be used on that spot.

// i18n
import { useTranslation } from 'react-i18next';
[...]
export const Home = (): JSX.Element => {
const { t, i18n } = useTranslation();
[...]
return <p>{t('to_translate')}</p>

Translation json:

{
"to_translate": "Acá hay un poco de texto que necesitamos traducir."
}

Issue #1: Text with html nodes or react components inside​

In the case that we have HTML nodes (<b>, <strong>, <a>, <i>, <br>, etc.), or React components altogether inside of a string we're trying to make translatable, we can import and use the Trans react component, which transforms the code into a translatable string for i18next. In these cases, we MUST include the "default" translation/content in English, with the elements inside all wrapped with the <Trans> component. This is required because the <Trans> component needs to know what each of the elements inside need to be transformed to.

// i18n
import { Trans } from 'react-i18next';
[...]
export const Home = (): JSX.Element => {
[...]
return <Trans i18nKey="edit_save_react">
Edit <code>src/App.tsx</code> and save to reload. <ReactComponent attribute="first">Make sure to love React.js!<ReactComponent>
</Trans>

Any tags gets extracted as <#>[content]</#>, with only the number and no extra information, and the same tags need to be used in the translation. They may do "skips" in number (ie, tag 1, then tag 5). Translation json:

{
"edit_save_react": "Editá <1>src/App.tsx</1> y guardá para recargar. <2>Asegurate de amar React.js!<2>"
}

Plurals / Variable interpolation​

In order to define a plural, you must use the count variable. When it's used, an extra key is created, which is a copy of the original key, but with _plural appended to it. In the case of the <Trans> component, include the i18nKey attribute.

Another thing to notice is that the attribute MUST be count. If there's a case with more than a single plural required in a string, see the caveat below.

return <p>{t('child', {count: variableWithAmount})}</p>;

--- OR ---

return (
<Trans i18nKey="child" count={variableWithAmount}>
There is {{count}} child
</Trans>
);

Translation implementation

{
"child": "There is {{count}} child",
"child_plural": "There are {{count}} children"
}

Multiple plurals (e.g. Arabic)​

When the translation requires multiple keys due to plurals, the suffixes are as follows:

{
"key_0": "zero",
"key_1": "singular",
"key_2": "two",
"key_3": "few",
"key_4": "many",
"key_5": "other"
}

Then in the code, you'd write this:

i18next.t('key', {count: 0}); // -> "zero"
i18next.t('key', {count: 1}); // -> "singular"
i18next.t('key', {count: 2}); // -> "two"
i18next.t('key', {count: 3}); // -> "few"
i18next.t('key', {count: 4}); // -> "few"
i18next.t('key', {count: 5}); // -> "few"
i18next.t('key', {count: 11}); // -> "many"
i18next.t('key', {count: 99}); // -> "many"
i18next.t('key', {count: 100}); // -> "other"

Read more over here: https://www.i18next.com/translation-function/plurals

Caveat: String with multiple plurals​

https://www.i18next.com/translation-function/nesting#passing-options-to-nestings

Dates & Times​

i18n-next does not provide any date handling library, so we will use date-fns. This is necessary for localizing the different formats of dates.

In order to translate a date, from the code, generate a proper key with a date variable. The type of the variable being Date is what lets the formatter kick in:

  <li>{t('date_example.short', { date: new Date() })}</li>
<li>{t('date_example.long', { date: new Date() })}</li>
<li>{t('date_example.relative', { date: new Date() })}</li>
<li>{t('date_example.ago', { date: new Date() })}</li>

Then, over at the translation file is where you set the format you want to use for the date object. It can be one of four keywords explained below, or a format compatible with date-fns. The keywords will handle localization automatically.

{
"date_example.ago": "This is an example date of type `ago`: {{ date, ago }}",
"date_example.long": "This is an example date of type `long`: {{ date, long }}",
"date_example.relative": "This is an example date of type `relative`: {{ date, relative }}",
"date_example.short": "This is an example date of type `short`: {{ date, short }}"
}

There are four helper formats: ago, long, relative, short. These produce the following output:

This is an example date of type `short`:    04/22/2021
This is an example date of type `long`: Thursday, April 22nd, 2021
This is an example date of type `relative`: today at 5:55 PM
This is an example date of type `ago`: less than a minute ago

Changing language​

Changing the language is dead simple:

import { useTranslation } from 'react-i18next';
[...]
export function MyComponent() {
const { t, i18n } = useTranslation();
i18n.changeLanguage('en-US');

How to use: Implementation​

To implement, simply include the following file as a sibling to your index.tsx:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

// Include one of these per language
import translationEN from './locales/en/translation.json';
import translationES from './locales/es/translation.json';

// Add them to the resources variable
const resources = {
en: { translation: translationEN },
es: { translation: translationES }
};

i18n
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next. Options: https://www.i18next.com/overview/configuration-options
.init({
resources,
fallbackLng: 'en',
lng: 'es',
debug: true,

interpolation: {
escapeValue: false // not needed for react as it escapes by default
}
});

export default i18n;

Additionally, edit your index.tsx file and add the following import:

// i18n
import './i18n';

How to use: Translation​

This example is without namespaces. Each translation file is located under ./src/locales/[lang]/translation.json. A translation file is a json object, with the key being each of the strings inside the t() function or i18nKey attribute of the <Trans> component, and the value being the translation.

Example:

{
"learn_react": "Aprendé React",
"pokemon_randomizer": "Aleatorizador de PĂłkemons",
"edit_save_reload.": "Editá <1>src/App.tsx</1> y guardá para recargar.",
""
}