i18n of React with Lingui.js #3
Tags: react, javascript, i18n
Published: 2018-11-18 22:01:59

---
title: i18n of React with Lingui.js #3
published: true
description: In this post, I want to show how to use Lingui.js to do i18n/l10n of React applications
tags: [react, js, i18n]
cover_image: https://thepracticaldev.s3.amazonaws.com/i/l7mb2u74g97zbfov2phw.png
series: i18n of React with Lingui.js
---

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](https://github.com/stereobooster/react-lingui-example). Each step of the tutorial is done as a separate commit, so you can trace all changes of the code.

## Usage with React Router

```shell
npm install --save react-router react-router-dom

# or using Yarn
yarn add react-router react-router-dom
```

Add `BrowserRouter`, `Switch`, `Route`.

```js
import { BrowserRouter, Switch, Route } from "react-router-dom";

// ...

<BrowserRouter>
  <Switch>
    <Route path="/" component={Home} exact />
  </Switch>
</BrowserRouter>;
```

Add `NotFound` page.

```js
<Switch>
  <Route path="/" component={Home} exact />
  <Route component={NotFound} />
</Switch>
```

Add `I18nRoutes`:

```js
const I18nRoutes = ({ match }) => { /* ... */ }

// ...

<Switch>
  <Route path="/:locale" component={I18nRoutes} />
  <Route component={NotFound} />
</Switch>
```

It will pick `locale` from path:

```js
const I18nRoutes = ({ match }) => {
  let { locale } = match.params;
  //...
};
```

It will check if it is supported `locale`, if not it will return `NotFound` page:

```js
if (!supportedLocale(locale)) {
  i18n.activate(defaultLocale);
  return <NotFound />;
}
```

it is supported `locale` it will activate given `locale` and return [nested routes](https://github.com/reactjs/react-router-tutorial/tree/master/lessons/04-nested-routes):

```js
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:

```js
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`:

```js
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`:

```js
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

```shell
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":

```js
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:

```js
import Meta from "./Meta";

export default function Home() {
  return (
    <div style={{ padding: "20px 50px" }}>
      <Meta locales={locales} />
      {/* ... */}
    </div>
  );
}
```