How we translated the Avocode website written in Next.js with the i18next package (2/2)

Matouš Roskovec
Avocode  — From Design to Code
6 min readDec 5, 2017

--

Hello, 你好, Здравствуйте

Don't you just love it when you meet a tourist in your own country and suddenly he starts speaking in your native language? Only last month, we had people from 126 countries visiting our website. One day, we'd like to start the conversation — break the ice, if you will — with all these people in their mother tongue.

How to translate a website that is always changing?

Our website keeps getting bigger and we really need it to be flexible to change. That's why we've chosen the Next.js framework, which you might have read on our blog last week. So how does the Next.js framework stand when it comes to localization?

As with every project, we had 2 requirements for the user experience…

  • The website language mutation needs to load automatically based on specific parameters like the country IP address point of access combined with the language settings of the user’s browser.
  • The users need to be able to switch languages directly on the page where they are, without being redirected to the homepage.

… and 2 requirements for the web editing:

  • We need to be able to define which content gets translated and which doesn't.
  • We need to be able to exclude translated content from the not translated to easily order new translations from an external service.

Our solution: i18next package, Locize, & TextMaster

Translating a website with a few thousands of words spread around in different components was challenging. After a bit of research, we have stumbled upon the i18next package which turned out to be a suitable fit. The package comes with plugins:

  • to detect the user language,
  • to load translations,
  • to optionally cache the translations,
  • and to extend them by using post-processing.

The i18next package works (quite) well with a service called Locize — which stores all strings of text as keys separately so you can have them translated.

Locize shows translated components as editable “keys” and comes with an in-context editor to quickly click on the content and translate components into other languages. It’s a neat tool for quick edits.

However, if you need to translate the whole website at once (and don’t have a native speaker in house), you might want to reach out to a translation service. There is an option to connect Locize to services like Gengo or TextMaster via API. For our purposes we chose TextMaster.

The Locize environment enables you to place a translation order to TextMaster via their UI (which you then need to confirm in TextMaster), and since the Locize can easily recognize what “key” is new in your content, you can simply tick “exclude values that are already translated.”

Once the translation is completed you can check it in TextMaster, request changes or approve it immediately. Sadly, the TextMaster platform is closed and doesn’t allow their translators to see any visual context of the copy (like using the Locize context editor).

This is how the final translation looks like in the TextMaster.

How do we work with the i18next package?

There are two config files, one for our production backend and one for the Locize service.

First, we import the “translate” method in the nested component where we store the text, like this:

import { translate } from ‘react-i18next’

The “translate” method defines the namespace which should be pulled from the backend. So for example when someone visits the login page, the JSON file with the “login” namespace will be pulled.

We use a high order component to arrange a proper connection between our i18next configuration on the server side and client’s browser.

Since the Locize in-context editor can work only with one namespace, there is one JSON file for each supported language forex, for example namespace.en.json, namespace.ru.json, namespace.de.json, etc.

Unfortunately, this causes slower loading than if we had a namespace for each page of the web. Hopefully, Locize in-context editor will be soon able to communicate with with multiple namespaces.

Each string of text is wrapped with a “t” method, which defines a place where the translated text should be inserted:

<Jumbotron heading={t(‘Share and inspect Photoshop and Sketch designs in a heartbeat’)}/>

The string in the brackets ‘Share and inspect Photoshop and Sketch designs in a heartbeat’ serves as the text key which will be translated. In this case, it’s identical as the English mutation of the website. In other words, the key stays the same, only the translation changes.

The second i18n.js config file which I mentioned above, is connected to a special build just for the Locize translation environment. When we launch the website in this special build, we need to manually go through all of our websites and modals to export the wrapped strings.

Unfortunately, the i18next package is not able to export all wrapped strings automatically at once so we could import them to Locize. We’re thinking about writing a custom script to do it for us, so we don’t have to export strings manually, but it would be wicked if the i18next package contained this feature.

Why do we load the language mutation from our backend and not from Locize?

Locize pricing is mostly based on a number of requests to download the translation. If we were to keep the translation JSONs only in Locize:

  • We’d pay for each time someone opens our web in a different translation,
  • Our website would load much slower (because it would have to wait for the JSON to be sent upon request)…
  • … and we would have to rely on Locize’s server provider.

Therefore we download the JSON manually each time we have a new translation (which is not so often — usually like once in two months) and add it to our Next.js devstack as a dependency.

Useful links:

If you'd like to know why and how we rewrote our web to Next.js in the first place, check this article.

Can you help?

If you’re a native Russian or Chinese speaker and you noticed a mistake on our website, please tell me at matous@avocode.com, and I'll make sure we rework the copy.

Cheers. 🙏🏼

Avocode is a design hand-off and inspect tool for teams which are building next-generation Web, iOS, & Android projects.

--

--

Creative Lead @Avocode, 500 Startups alumni, ex-Content Strategist @SignalsNetwork, marketing strategy consultant, wannabe chef, addicted to Netflix.