In this post, I want to show how to use Lingui.js to do i18n/l10n of React applications. I will use Node 10.10 and yarn
, but I guess npm
and other versions of Node would work too. The full source code is here. Each step of the tutorial is done as a separate commit, so you can trace all changes of the code.
Usage with React Router
npm install --save react-router react-router-dom
# or using Yarn
yarn add react-router react-router-dom
Add BrowserRouter
, Switch
, Route
.
import { BrowserRouter, Switch, Route } from "react-router-dom";
// ...
<BrowserRouter>
<Switch>
<Route path="/" component={Home} exact />
</Switch>
</BrowserRouter>;
Add NotFound
page.
<Switch>
<Route path="/" component={Home} exact />
<Route component={NotFound} />
</Switch>
Add I18nRoutes
:
const I18nRoutes = ({ match }) => { /* ... */ }
// ...
<Switch>
<Route path="/:locale" component={I18nRoutes} />
<Route component={NotFound} />
</Switch>
It will pick locale
from path:
const I18nRoutes = ({ match }) => {
let { locale } = match.params;
//...
};
It will check if it is supported locale
, if not it will return NotFound
page:
if (!supportedLocale(locale)) {
i18n.activate(defaultLocale);
return <NotFound />;
}
it is supported locale
it will activate given locale
and return nested routes:
i18n.activate(locale);
return (
<Switch>
<Route path={`${match.path}/`} component={Home} exact />
<Route component={NotFound} />
</Switch>
);
Redirect from root path to localised page
Add redirect from root path to localised page based on the browser preferences:
const RootRedirect = () => {
let [locale] = (
navigator.language ||
navigator.browserLanguage ||
defaultLocale
).split("-");
if (!supportedLocale(locale)) locale = defaultLocale;
return <Redirect to={`/${locale}`} />;
};
// ...
<Switch>
<Route path="/" component={RootRedirect} exact />
<Route path="/:locale" component={I18nRoutes} />
</Switch>;
Reimplement LanguageSwitcher
for React Router
The simplest LanguageSwitcher
can be implemented with NavLink
:
import { NavLink } from "react-router-dom";
export default ({ locales }) =>
Object.keys(locales).map(locale => {
const url = `/${locale}`;
return (
<NavLink
key={locale}
to={url}
activeClassName={s.selected}
className={s.link}
>
{locales[locale]}
</NavLink>
);
});
This implementation will always redirect to the root of localized pages, for example from /en/some/subpage
to /cz
.
If we want to change the locale, but preserve path we need to use Route
:
import { NavLink, Route } from "react-router-dom";
export default ({ locales }) => (
<Route
children={({ match }) =>
Object.keys(locales).map(locale => {
const url = match.url.replace(
new RegExp(`^/${match.params.locale}`),
`/${locale}`
);
// ...
})
}
/>
);
Add meta tags with the help of React Helmet
npm install --save react-helmet
# or using Yarn
yarn add react-helmet
The code is very similar to the one we used in "Reimplement LanguageSwitcher
for React Router":
import React from "react";
import { Route } from "react-router-dom";
import Helmet from "react-helmet";
export default ({ locales }) => (
<Route
children={({ match }) => (
<Helmet
htmlAttributes={{ lang: match.params.locale }}
link={Object.keys(locales).map(locale => {
const url = match.url.replace(
new RegExp(`^/${match.params.locale}`),
`/${locale}`
);
return { rel: "alternate", href: url, hreflang: locale };
})}
/>
)}
/>
);
Add it to Home
component:
import Meta from "./Meta";
export default function Home() {
return (
<div style={{ padding: "20px 50px" }}>
<Meta locales={locales} />
{/* ... */}
</div>
);
}