loading...

How to translate your React.js app with i18next

ksushiva profile image Oksana Ivanchenko Updated on ・3 min read

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.

Posted on by:

Discussion

pic
Editor guide
 

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 of public/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:

const Loader = () => {
  return <div>loading...</div>
};
export default props => {
    return (
        <Suspense fallback={<Loader />}>
        ...
        </Suspense>
    )
}

Thank you in advance Oksana!

 

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

 

Thanks for sharing the post, its content is very valuable.

 

Thanks Oksana, nice article. Could you explain why locales should be placed in the public folder? Thanks

 

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.

 

It works fine with props? I mean suppose I have a header component that receive a prop title to render some things like this.

 

I read and integrated follow i18next documents but my project failed. Since I read your post and follow it, I very surprise. I got it. You are my idol. Thank you so much!

 

Thank you, for me es better i18n than react-intl, works fine and it's super easy to config

 

Wonderful. Able to set up our entire app in just a week..!! Thanks a lot :)