Today, I will show you how to translate the text and date in your React.js application.
First of all, you must install some dependencies:
yarn add i18next i18next-xhr-backend i18next-browser-languagedetector react-i18next
Now we need to create a file called i18n.js in our src folder:
import i18n from 'i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
const fallbackLng = ['en'];
const availableLanguages = ['en', 'ru'];
i18n
.use(Backend) // load translation using xhr -> see /public/locales. We will add locales in the next step
.use(LanguageDetector) // detect user language
.use(initReactI18next) // pass the i18n instance to react-i18next.
.init({
fallbackLng, // if user computer language is not on the list of available languages, than we will be using the fallback language specified earlier
debug: true,
whitelist: availableLanguages,
interpolation: {
escapeValue: false
},
});
export default i18n;
Then we will import i18n in index.js in src/index.js:
...
import './i18n';
ReactDOM.render(<App />, document.getElementById('root'));
...
The next step is to create our locales: public/locales/en/translation.json and public/locales/ru/translation.json. This translation will be loaded automatically thanks to i18next-xhr-backend.
Also, in our App.js we need to add Suspense in oder to display a loading indicator.
import React, { Suspense } from 'react';
...
function App() {
return (
<div className="App">
<Suspense fallback={(<div>Loading</div>)}>
<WeatherForecast />
</Suspense>
</div>
);
}
...
Now we go to the component that we want to translate. If you have a Class Component we will be using the Higher Order Component withTranslation:
import React, { Component } from 'react';
import { withTranslation } from 'react-i18next';
class News extends Component {
render(){
const { t } = this.props;
return (
<h1>{t('news.title')}</h1>
)
};
};
export default withTranslation()(News);
If you have a Functional Component you should use the react hook useTranslation:
import React from 'react';
import { useTranslation } from 'react-i18next';
const WeatherForecast = () => {
const { t } = useTranslation();
return (
<h1>{t('weather.title')}</h1>
)
};
export default WeatherForecast;
Now we will modify our locales. In public/locales/en/translation.json:
{
"news": {
"title": "Our news"
},
"weather": {
"title": "Weather forecast"
}
}
In public/locales/ru/translation.json:
{
"news": {
"title": "Наши новости"
},
"weather": {
"title": "Прогноз погоды"
}
}
If you want to translate a phrase with a variable in it, you need do this:
<p>{t('weather.temprature', {number: temprature})}</p>
And in your .json locale file you need to write:
"temprature": "Today in Lyon is cloudy: {{number}}°C."
We will the same do for our Russian or any other version.
Now I will show you how to translate a date. To do this I will be using moment.js.
yarn add moment
In my WeatherForecast.js I add:
<p>{t('weather.date', {date: Date.now()})}</p>
Now in public/locales/en/translation.json:
"weather": {
"date": "Today's date: {{date, currentDate}}"
},
Here in {{}}
date is value, variable that we asigned in our component and currentDate is the format that we will use next.
In our i18n.js file, we must import moment.js and configure the translation for our date:
import moment from 'moment';
...
availableLanguages.forEach((element) => {
if (element !== 'en') {
import(`moment/locale/${element}`);
}
}); // we are importing only the locales that we need.
.init({
...
interpolation: {
escapeValue: false,
format: (value, format, lng) => {
if (format === 'currentDate') return
moment(value).locale(lng).format('LL');
return value;
},//if the format is 'currentDate', then take its __value__ transfom it to a moment object, translate it to the current language and show it in Month DD, YYYY format.
},
});
It should work well. Hope this article was helpful.
Top comments (15)
Thank you for your article Oksana!
How do you manage the fact that translations files may be cached by the browser and therefore if you publish an updated translation file, let's say
public/locales/ru/translation.json
, the browser may still continue to use an outdated cached version ofpublic/locales/ru/translation.json
.Did you find a solution for that as well?
Hi Oksana! Great solution, thank you! I'd like to ask you about an issue I have whenever I run it...
It outputs a red screen, with white fonts and the following error:
“A React component suspended while rendering, but no fallback UI was specified. Add a component higher in the tree to provide a loading indicator or placeholder to display”
I don't understand where does it come from, since the
<Suspense/>
component has already been filled with the fallback:Thank you in advance Oksana!
Thank you for the summary. I found that those i18n-libraries are not enough to keep translation-files in sync, which is why I wrote "attranslate" as an additional tool for file-synchronization: github.com/fkirc/attranslate you can give it a try if you are seeking a free solution
Thanks for sharing the post, its content is very valuable.
Beginner web developer? I've read a lot of solutions for i18next and you have been the only one that has made my app be translated correctly, all very clear. You are agoddess!!! Thanks a lot!!!
Wow! Thanks for your comment! I’m very happy that you found this article helpful
Cool, now I have something to play with on the weekend.
Thank you Oksana! It works like a charm!
The simplest just to the point explanation I've seen so far about i18next. Thx a lot for sharing this. i18next should put this article in their website as Getting Started.
i18next-xhr-backend is deprecated, i18next-http-backend can be used now.
i.e. dev.to/adrai/how-to-properly-inter...
It works fine with props? I mean suppose I have a header component that receive a prop title to render some things like this.