Recently, I already wrote
an article on how you can conveniently validate forms in React with the help of the Formsy-React component. Today I would like to talk about the approach that I used to internationalize the developed application. As a bonus, the library used adds the possibility of pluralization, which is a very useful feature when developing a multilingual application. If interested, please under the cat!
I spent a lot of time looking for the right library for this purpose. And when I found it all the same, for a long time I could not understand how to use it correctly, because developers were too lazy to write normal documentation. Actually the library itself is
i18next . It provides many opportunities, but in this article two of them will be considered.
1. Internationalization. i18next allows us to create a dictionary of words for each specific language, and then to write variables from these dictionaries instead of text inside applications. When the component is initialized, we select the language, and instead of the variable, the word is automatically substituted from the necessary dictionary. You can find the link to the repository with the full source code below, and now I’m going to give small fragments of the test application.
We will use 2 languages ​​- English and Russian. Each of them is stored in the file en.json and ru.json respectively. The dictionary can look like this:
')
en.json
{ "en": { "translation": { "test_message": "This is a test message" } } }
ru.json
{ "ru": { "translation": { "test_message": " " } } }
It should be noted that the key names for the text (in this case, test_message) must match in all dictionaries. In this example, we have one key that we can use inside our component. To do this, before initializing the component (inside the componentWillMount () function) set the default language, for example, English
componentWillMount() { this.setLanguage('en'); }
The setLanguage () function might look like this:
setLanguage(language) { i18next.init({ lng: language, resources: require(`json!./${language}.json`) }); this.props.actions.changeLanguage(i18next); }
In the parameter we pass the name of the language, and then use it to initialize the library. An important point, inside the initialization function, the value of the lng key must match the language name inside the dictionary (in this case, lng == en, like the first object inside the en.json file). The path to the dictionary file must be passed to resources. I used json-loader, so the function looks like this. Also, you should not forget to update the component's state, otherwise the language will change, and the render will not be called and the text will not change.
The basic preparations have been made; now you can begin to use internationalization inside the component.
render() { return ( <div> <div> <Button bsStyle="primary" onClick={this.setLanguage.bind(this, 'en')}>English</Button> <Button bsStyle="primary" onClick={this.setLanguage.bind(this, 'ru')}></Button> </div> <div>{i18next.t('test_message')}</div> </div> ) }
At the top there are 2 buttons for each of the languages, when clicked, the language will be changed. It is important to use bind, otherwise the setLanguage function will be called endlessly and will cause looping. After rendering, instead of the strange construction i18next.t ('test_message'), the user will receive a correct translation, namely, This is a test message or This is a test message, depending on the installed language.
In fact, that's all. This is how the internationalization of the application works with the help of the i18next library. Now, as promised, we will consider another useful library function - pluralization.
2. Pluralization. In short, this term means that depending on the quantitative trait, the ending of a word will change. For example, in English, s (one car -> five cars) is added to the word at the end. But in Russian the situation is somewhat worse, because for each word there are 3 different ending options, for example: 1 banana, 2 bananas, 5 bananas. Of course, inside the application you can do something like “Number of bananas: 2”, but it looks not so impressive. And with the help of i18next this situation can be fixed very easily!
The library website has a
label with pluraforms , in which for each language it shows how many different endings can be. There are 3 of them in Russian.
To use this function, you must add the following keys to our dictionary:
en.json
"amount_of_bananas": "{{count}} banana", "amount_of_bananas_plural": "{{count}} bananas"
When rendering the component, the option will be selected depending on the digit that will be transferred as count. Those. if we pass 1 inside the component, the first option will be selected, otherwise the second option will be selected. How does the library understand which option to choose? The second key ends in _plural, which helps the library with a choice. Each language has its own endings, you can find them in the table, the link to which I left above. For example, for the Russian language, the dictionary will look like this:
"amount_of_bananas_0": "{{count}} ", "amount_of_bananas_1": "{{count}} ", "amount_of_bananas_2": "{{count}} "
Those. in component 1, “1 banana” will be given during transmission 1, during transmission 2 - “2 bananas” and during transmission 5 - “5 bananas”. It is very convenient that we ourselves set the translation of the word for one or another quantity.
As a result, returning to the component, it will look like this:
<div>{i18next.t('amount_of_bananas', {count: 5})}</div>
where at the exit a person will receive "5 banans" or "5 bananas"
So here, simply enough, we can translate your application into languages ​​that need to be supported. Separately it is necessary to say about the dictionaries. In this case, we have only 2 words, but in large applications there may be much more. The choice of organization of the language depends on you. This can be either a breakdown by component, or, in order to avoid repetition, by any signs (for example, buttons, shapes, etc.).
That's all, thank you for your attention!
Link to the repository with an example -
https://github.com/theWaR13/i18next-example