How to Implement localization in React i18next 2022
react-i18next is a powerful internationalization framework for React / React Native which is based on i18next. In this tutorial, we will implement localization in react project step by step.
1. Let's install create-react-app package.
npm i -g create-react-app
2. Create a new react project
create-react-app react-localization
Note:- In this tutorial, we will use bootstrap free pricing template - Pricing example for Bootstrap (getbootstrap.com)
3. After creating our project integrate the above html template.(checkout github repo)
import './App.css';
import HeaderComponent from './components/comman/header.component';
import HomeComponent from './components/pages/home.component';
function App() {
return (
<>
<HeaderComponent />
<div className="container">
<HomeComponent />
</div>
</>
);
}
export default App;
4. Install i18next and some dependencies.
npm i i18next react-i18next i18next-browser-languagedetector
5. Create a lang folder inside src for storing translation files. inside lang folder create two folders en and fr for storing english and french translations.
next, we need to create json files inside these folders. let's create homepage.json for each language.
/src
/lang
/en
homepage.json
/fr
homepage.json
Note: In this tutorial, I am using single file homepage.json but you can use multiple files based on your requirement.
6. Now we need to update our translation based on our components(html).
//en/homepage.json
{
"plan_title": "Pricing",
"plan_text": "Pick a plan that suits you.",
"free": "Free",
"pro": "Pro",
"month": "month",
"enterprise": "Enterprise",
"users_included": "{{total}} users included",
"storage_included": "{{total}} GB of storage",
"email_included": "{{total}} email account"
}
//fr/homepage.json
{
"plan_title": "Prix",
"plan_text": "Choisissez un plan qui vous convient.",
"free": "libre",
"pro": "Pro",
"month": "mois",
"enterprise": "Enterprise",
"users_included": "{{total}} utilisateurs inclus",
"storage_included": "{{total}} Go de stockage",
"email_included": "{{total}} compte de messagerie"
}
Note: for the dynamic value, we need to use curly braces {{variable}}
7. Inside the src folder create i18n.js file. open this file initialize i18n.
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
let homepageFr = require('./lang/fr/homepage.json');
let homepageEn = require('./lang/en/homepage.json');
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: {
translations: { ...homepageEn }
},
fr: {
translations: { ...homepageFr }
}
},
fallbackLng: "en",
debug: true,
ns: ["translations"],
defaultNS: "translations",
keySeparator: false,
interpolation: {
escapeValue: false
}
});
export default i18n;
Note:- In case of multiple translation files you can pass comma separate with spread operator.
en: {
translations: { ...homepageEn, ...file2.json, ...file3.json }
}
8. Open index.js and import i18n.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import "bootstrap/dist/css/bootstrap.css";
import i18n from "./i18n";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
9. Now we need to replace our hardcoded text with t function. i18next provides 2 ways for handling translation.
(a). t function
(b). Trans component
t(key, object)
t('plan_title') --> Pricing
<Trans i18nKey='key' values={object}/>
<Trans i18nKey='plan_title'/> --> Pricing
If we need to pass any dynamic data into our translation then we need to pass an object.
// suppose translation.json
{
"welcome": "Hello {{name}}"
}
t('welcome', { name: 'akash' })
<Trans i18nKey='welcome' values={{ name: 'akash' }}/>
// both gives you "Hello akash"
Ref:- Trans Component - react-i18next documentation
10. Finally open HomeComponent of our project and replace hardcoded text with t function.
import React from 'react';
import { useTranslation } from "react-i18next";
const HomeComponent = () => {
const { t, i18n } = useTranslation();
return (
<>
<div className="pricing-header p-3 pb-md-4 mx-auto text-center">
<h1 className="display-5 fw-normal">{ t('plan_title') }</h1>
<p className="fs-5 text-muted">{ t('plan_text') }</p>
</div>
<main>
<div className="row row-cols-1 row-cols-md-3 mb-3 text-center">
<div className="col">
<div className="card mb-4 rounded-3 shadow-sm">
<div className="card-header py-3">
<h4 className="my-0 fw-normal">{ t('free') }</h4>
</div>
<div className="card-body">
<h1 className="card-title pricing-card-title">$0<small className="text-muted fw-light">/{ t('month') }</small></h1>
<ul className="list-unstyled mt-3 mb-4">
<li>{ t('users_included', {'total': 10 }) }</li>
<li>{ t('storage_included', {'total': 2 }) }</li>
<li>{ t('email_included', {'total': 1 }) }</li>
</ul>
</div>
</div>
</div>
<div className="col">
<div className="card mb-4 rounded-3 shadow-sm">
<div className="card-header py-3">
<h4 className="my-0 fw-normal">Pro</h4>
</div>
<div className="card-body">
<h1 className="card-title pricing-card-title">$15<small className="text-muted fw-light">/{ t('month') }</small></h1>
<ul className="list-unstyled mt-3 mb-4">
<li>{ t('users_included', {'total': 20 }) }</li>
<li>{ t('storage_included', {'total': 10 }) }</li>
<li>{ t('email_included', {'total': 5 }) }</li>
</ul>
</div>
</div>
</div>
<div className="col">
<div className="card mb-4 rounded-3 shadow-sm border-primary">
<div className="card-header py-3 text-white bg-primary border-primary">
<h4 className="my-0 fw-normal">Enterprise</h4>
</div>
<div className="card-body">
<h1 className="card-title pricing-card-title">$29<small className="text-muted fw-light">/{ t('month') }</small></h1>
<ul className="list-unstyled mt-3 mb-4">
<li>{ t('users_included', {'total' : 30 }) }</li>
<li>{ t('storage_included', {'total' : 15 }) }</li>
<li>{ t('email_included', {'total' : 10 }) }</li>
</ul>
</div>
</div>
</div>
</div>
</main>
</>
);
}
export default HomeComponent;
Note:- If you are using class components then you can use withTranslation() HOC.
import React from 'react';
import { withTranslation } from 'react-i18next';
function HomeComponent(props) {
const { t, i18n } = props;
return (
);
}
export default withTranslation()(HomeComponent);
11. Now we need to create a select box so users are able to switch languages. open HeaderComponent make changes like this
import React from 'react';
import { useTranslation } from "react-i18next";
const HeaderComponent = () => {
const { i18n } = useTranslation();
const handleLanguage = (e) => {
i18n.changeLanguage(e.target.value);
}
return (
<header>
<div className="d-flex flex-column flex-md-row align-items-center pb-3 mb-4 mt-2 ms-3 border-bottom">
<a href="/" className="d-flex align-items-center text-dark text-decoration-none">
<span className="fs-4">React Localization</span>
</a>
<nav className="d-inline-flex mt-2 mt-md-0 ms-md-auto">
<span className="me-3 py-2 text-dark">
<select className="form-select form-select-sm language-switcher" onClick={handleLanguage}>
<option value="en">English</option>
<option value="fr">French</option>
</select>
</span>
</nav>
</div>
</header>
);
}
export default HeaderComponent;
Note:- If you are using class components then you can use withTranslation() HOC.
import React from 'react';
import { withTranslation } from 'react-i18next';
function HomeComponent(props) {
const { t, i18n } = props;
const handleLanguage = (e) => {
i18n.changeLanguage(e.target.value);
}
return (
);
}
export default withTranslation()(HomeComponent);
Note:- You can print get the current language from i18n object.
console.log(i18n.language) //en
12. Finally run the project.
npm start
open http://localhost:3000 in the browser and try to change the language.
Checkout my react localization example.
https://github.com/ultimateakash/react-localization
If you facing any issues. please post a comment. I will be happy to help you,
Thanks
Leave Your Comment