> For the complete documentation index, see [llms.txt](https://cansahin.gitbook.io/react-boilerplate-cra-template/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cansahin.gitbook.io/react-boilerplate-cra-template/building-blocks/i18n.md).

# i18n Internationalization & Pluralization

[react-i18next](https://react.i18next.com/) is a powerful internationalization framework for React / React Native which is based on `i18next`. It is a library to manage internationalization and pluralization support for your React application. This involves multi-language support for both the static text but also things like variable numbers, words, or names that change with the application state.

## Usage

The setup and translations are in the **`locales/`** folder. You can add more language to subfolder `de`, `en`, `fr`, and so on.

**`i18n.ts`** is the setup file. It initiates `i18next` with the translations. We also include a helper function here to help use your translations with intellisense support in your project, rather than having to rely on a `something.otherthing.title` kind of string-based format which is error-prone and **not** refactorable. It maps your JSON translation file to JavaScript objects so that you can call them like, surprise, regular objects.

{% hint style="info" %}
🧙**Tips:** Check the example application of this boilerplate to see how you can separate your translations into logical groups and make everything intellisense-supported 💪
{% endhint %}

### Using translations with hooks

Let's say your translation JSON is this:

```javascript
{
  "HomePage": {
    "Features": {
      "someItem": "Some text in English"
    }
  }
}
```

Now you can get the **`someItem`** translation very easily and safely with intellisense support.

```typescript
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { translations } from 'locales/translations';

export function MyComponent() {
  const { t, i18n } = useTranslation();
  const changLanguageButtonClicked = evt => {
    const language = event.target.value;
    i18n.changeLanguage(language);
  };
  // The nested objects are intellisense supported ✅
  return <div>{t(translations.HomePage.Features.someItem)}</div>;
}
```

Check the [react-i18next](https://react.i18next.com/) docs for other usage types. Its very flexible and well-featured.

## Extracting JSON Files

You don't have to add or delete each entry in `translation.json` manually. Using [i18next-scanner](https://github.com/i18next/i18next-scanner) its fairly straight-forward to extract all the translations into JSON files. It scans your code and whenever it sees something like `t('a.b.c')` it adds `{a: {b : { c: ""}}}` into the JSON files.

Simply, run this script

```
yarn run extract-messages
```

{% hint style="warning" %}
**WARNING:** The rest below only applies if you want to use `translations` object and want to extract messages later on. If you are going with the default `t('a.b')` approach or if you don't want to extract messages you don't need the `messages.ts` below
{% endhint %}

However, there is a catch here. As mentioned above, we provide **helper object** for translations so that they are type-safe and intellisense-supported. This ruins the scanning ability of `i18next-scanner`. In order to overcome this, we need to define our translated messages in a file

#### `messages.ts`

```typescript
import { translations } from 'locales/translations';
import { _t } from 'utils/messages';

export const messages = {
  someItem: () => _t(translations.HomePage.Features.someItem, 'default value'),
  // ...
};
```

then we use `messages` in our react component

```typescript
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { messages } from './messages';

export function MyComponent() {
  const { t } = useTranslation();
  return <div>{t(...messages.someItem()}</div>;
}
```

The reason behind this is, we have to convert this

`t(translations.Homepage.Features.someItem)`

to

`t('Homeage.Features.someItem')`

before `i18next-scanner` parses the file. To do that there is custom [function](https://github.com/react-boilerplate/react-boilerplate-cra-template/tree/eb707bf261671d821b6f4fd9d8c9b9e953cdca7f/internals/extractMessages/stringfyTranslations.js) running before the parsing happens. This function looks at `_t(...)`'s and converts them to strings. Then, scanner carries out its duty...

The example application includes this usage and you can take a look at there for a working example.
