I18n process for ReactNative apps

Alexander Kuttig
Horizon Alpha
Published in
6 min readFeb 5, 2020

--

Internationalization gives you access to more markets.

I think there’s hardly any developer out there who hasn’t get in touch with the challenge of multi-language support for an application. And if you haven’t, start thinking about it immediately. GooglePlay and Apple’s AppStore make it super easy to provide an application in nearly every country of the world (yeah — China is still a problem) and since you want to reach as many people as possible and give your customers the best experience possible, you have to adapt the language of your app to the language of your customers.

There are some things to consider, when starting with Internationalization (I18n) of your application. One thing it the technical implementation. I will describe my setup, but this is not what this article is about. In this article I will focus on the other things you have to keep in mind with I18n. I want to describe the problems which came up when we started supporting more and more languages (which means to work with external translators) and how we achieved to solve them by adapting our processes and architecture. At this point, we are supporting 36 languages including three RTL (right-to-left) languages as well as Japanese, Chinese and Russian. We are publishing new releases every two to three weeks with around 15 to 50 new strings every release.

Technical Challenges

There have been a bunch of things which have to be considered, before we were able to support that many languages. As I said this is not the main focus of the article, but since it could be helpful for some of you, I share the top three :-)

ReactNative Implementation

I18n in ReactNative this is not a problem anymore. There are plenty of good libraries out there, to achieve I18n with a lot of cool features like pluralization etc. I worked with react-native-i18n until it got deprecated and switched to react-native-localize and i18n-js after that. There is a good blog post about how to get this setup running (https://medium.com/@nicolas.kovacs/react-native-localize-and-i18n-js-117f09428017). But as I said, there are many more libraries, which work quite well.

Font

You have to keep in mind, that not every font supports every language. There are some languages which use completely different characters than we do in our US/EU world. There are two solutions for this problem. You can either use different fonts in different languages or search for a font which supports all languages you use. I can recommend Google’s “Noto Font”. This is a font which was designed to provide good readability in every language. You can find more on this here: https://www.google.com/get/noto/

RTL support

ReactNative has really good RTL support out of the box. There is an article which describes how it works on the RN homepage (https://facebook.github.io/react-native/blog/2016/08/19/right-to-left-support-for-react-native-apps). We made the experience that it works like a charm when using the device language. If you want to change the language inside the app (and switch from LTR to RTL) you have to restart the app to let the change fully take effect.

After solving the technical Issues, we had to think about how to get translations to 36 languages.

Get translators on board

Since our team is not able to do all the translations internally, we had to get some external translators on board. The translation was done like this. We put together an Excel File with all our strings and sent it to a professional translation company. After some time, we got the Excel back, parsed it, wrote the translations to .json files, added the files to our app and made the release.

Working with translators can be quite difficult

Now we had translations to all languages we wanted, but there was a lot of problems. The whole roundtrip took us around four to five weeks. Since we wanted to run a release cycle of two to three weeks, this was unacceptable. The second thing was, that the quality of the translation to some languages was very different from what we think it was. The reason for this was mainly that the translator didn’t know our app. So he didn’t actually know what he was translating.

So we changed some things and started another attempt. We searched for translators on upwork.com. We gave them our app and explained how it works. We told them we want to have a long term partnership and order new translations for our app on a regularly basis. We found some really nice and reliable people there and the quality of the translations became a lot better. Not only did this reduce the translation errors, it also increased the wording in every language a lot and guaranteed some kind of consistency in every language, since all the translations came from the same person.

Speed things up

After ensuring the quality of the translations, we had to speed things up. We wanted to be able to do all the translation work for a release in less than 36 hours, which is a lot faster than the four two five weeks our first runs needed. So we started using a service called “crowdin”.

This is a webapplication where you can store all of you translations, give translators access and check and approve translations. The really cool thing is, that you can upload screenshots to crowdin for every string. So the translator gets some context on what will be translated. Another very important thing for us was, that crowdin offers an API, where we are able to automatically fetch the translations.

So out new process looked like this: We uploaded the new strings with some screenshots to crowdin, informed our pool of trusted translators, waited for 36 hours and ran our CI build pipeline, where we integrated the step of fetching the latest translation files. This really worked quite well for most cases.

Support the process with our application architecture

We didn’t want to have to wait with our release, only because one of 36 translators was not able to deliver in time.

But most cases were not enough for us. There were always cases where a translator was on holiday or wasn’t able to deliver in our 36 hour window. On the one hand, we didn’t want to delay our release for one missing translation file, on the other hand we didn’t want to have an app out there, where we weren’t able to deliver the translations until the next release.

So we added a lazy loading/updating of the translation files to our app. We still add the latest translation files to the release bundle but every time a user opens the app, we are checking for a UI translations version number. If the number in our remote db is higher than the one on the device, we fetch the translation files from the server (Firebase Storage in our case) and use it in the app. This gave us the flexibility to deliver the translations, even if the release was already out while also having translation files bundled in every release.

This lazy loading/updating brings another advantage. If we detect an error in the translations, we are able to fix it in minutes now.

So our whole process looks like this at the moment:

  1. Dev team uploads strings with screenshots to crowdin.
  2. Translators translate strings.
  3. After 36 hours we run our CI build, publish our release and write the latest translations to our server.
  4. If we get some translations “late”, we write them to our server as soon as we get them.
  5. The app fetches the latest translations as soon as they are on the server.

This process works quite well for us.

I think in the end everyone has to find his/her own process, but I can give some final advice from my experience.

Always work with the same translators

This really gave us a huge boost in translation quality

Be as flexible as possible and support updating translations without a release

You WILL need it!

As always, I hope this article was useful for you. I’m happy about any feedback, experience and other solutions.

--

--