Skip to content

Internationalization

Petr Škoda edited this page Mar 24, 2021 · 2 revisions

dcat-ap-viewer supports multiple languages. Although there are standard ways how to translate/localize application, many of them are not ready to be used in our case. The reason is that many of the labels are resolved online and are not part of the application e.g. codelists. This lead to a situation where we have static and dynamic content that needs to be translated.

Overall there are three areas where the translation is needed:

  • strings (static text as in i18next)
  • labels (for RDF entities like publishers, datasets, etc.)
  • URLs (as we do URL path resolution on client site, to minimize server configuration)

Existing solution: i18next

There are standard libraries for React like react-i18next. The main disadvantage is their size and a fact that they would still require considerable effort to integrate especially because of the Language detection. There are nice tutorials how to use react-i18next.

The basic idea behind react-i18next is to use Component composition to provide function t in the props, that is responsible for the translation. Example:

function Gator({ gator }) {
  return (
    <I18n>
      {(t) => (
            <div>
              <label>{ t('name.label') }</label>
            </div>
      )}
    </I18n>
  )
}

What is the most compelling part of react-i18next is the babel-plugin-i18next-extract that can extract keys from the code, so they can be easily translated.

Another issue is, that we need to know all the translation of URLs up-front so we can decide about the language. This would require custom implementation on top of the react-i18next.

Our solution

For the above reasons, we decided to go with a custom implementation of translation inspired by the react-i18next. That support not only static content but also dynamic content and URLs.

Static content

We adopt the use of t function from react-i18next in order to be compatible with i18next.

Dynamic content translation

The tLiteral can be used to select value form a language string. For resource labels selectLabel function should be used. This function is returned by useLabelApi hook. The label API monitor loaded JSON resources for labels, but is also able to make a fetch request to obtain missing labels.

URL translation

The tUrl function can be used to get URL in given language together with provided query arguments.

Translation files

The translation of static content and URL string must be provided as a part of a component registration using the register function. It is recommended to create separate translation file per-view, with following structure:

{
  "${language}": { }
}

import it into the component code:

import translations from "./publisher-list.json";

and use when registering the component:

register({
  "url": "/publishers",
  "name": "publishers-list.view",
  "view": PublisherList,
  "navigation": {
    "cs": {
      "/publishers": "/poskytovatelé",
    },
    "en": {
      "/publishers": "/publishers",
    },
  },
  "translations": translations,
});

From the example we can see that the navigation translation map is part of the component code.

Limitations

We do not support the translation of keywords as it is not supported by DCAT-AP.