i18n
stands for Internationalization, i-18 letters-n
.
i18next
Install:
npm install react-i18next i18next --save
# if you'd like to detect user language and load translation
npm install i18next-http-backend i18next-browser-languagedetector --save
i18n.js
: settings.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
i18n.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
}
});
export default i18n;
index.js
need to load it.
import React, { Component } from "react";
import ReactDOM from "react-dom";
import App from './App';
// import i18n (needs to be bundled ;))
import './i18n';
ReactDOM.render(
<App />,
document.getElementById("root")
);
App.js
use case:
import React, { Component, Suspense } from 'react';
import { useTranslation, withTranslation, Trans } from 'react-i18next';
import logo from './logo.svg';
import './App.css';
// use hoc for class based components
class LegacyWelcomeClass extends Component {
render() {
const { t } = this.props;
return <h2>{t('title')}</h2>;
}
}
const Welcome = withTranslation()(LegacyWelcomeClass);
// Component using the Trans component
function MyComponent() {
return (
<Trans i18nKey="description.part1">
To get started, edit <code>src/App.js</code> and save to reload.
</Trans>
);
}
// page uses the hook
function Page() {
const { t, i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<Welcome />
<button type="button" onClick={() => changeLanguage('de')}>
de
</button>
<button type="button" onClick={() => changeLanguage('en')}>
en
</button>
</div>
<div className="App-intro">
<MyComponent />
</div>
<div>{t('description.part2')}</div>
</div>
);
}
// loading component for suspense fallback
const Loader = () => (
<div className="App">
<img src={logo} className="App-logo" alt="logo" />
<div>loading...</div>
</div>
);
// here app catches the suspense from page in case translations are not yet loaded
export default function App() {
return (
<Suspense fallback={<Loader />}>
<Page />
</Suspense>
);
}
// useTranslation hook can also accept a namespace
const { t, i18n } = useTranslation(['translation', 'common']);
t('common:a.b');
translation files:
public/locales/<lng>/translation.json
{
"title": "Welcome to react using react-i18next",
"description": {
"part1": "To get started, edit <1>src/App.js</1> and save to reload.",
"part2": "Switch language between english and german using buttons above."
}
}