Automate your translation process with Lokalise and your CI

Alizée Camarasa
Inside Aircall
Published in
4 min readFeb 17, 2021

If your app is available in many countries, the chances are that you will need to support multiple languages. It’s possible to handle this by updating your strings.xml files on your own, but it can become very tedious as your app grows. You will need to create a pull request manually for each new translation, change, or typo.

Thankfully, there are some translation tools like Lokalise, PhraseApp, Transifex, etc… At Aircall, we use Lokalise.

Thanks to those tools, the internationalization process of your product can scale and be shared across several teams (product team, content team, etc…) but it can become hard to follow. You’ll need to pull all those new translations every day, and before each release.

At first, this is what we did. We were creating a pull request from Lokalise’s dashboard, with Order keys by: First added, and Empty translations: Don’t export (this will be important for later).

In order to improve our process and remove this manual step as much as possible, we have integrated it into our CI. Every night, a nightly build will pull all translations from Lokalise, and create a PR if there are changes.

In this article, I will show how we did it with CircleCI and Bitbucket, but it can easily be adapted for your CI and source code management tool.
This article will also be focused on Android, but I guess this can easily be adapted to iOS.

Option 1: with Fastlane

Fastlane is a very convenient automation tool.

You can write your own lane (a lane is like a method that runs multiple commands/steps) in order to perform the action you need, and you can also use actions and plugins provided by the community.

Here is the one provided by Lokalise.

It’s not a plugin, it’s an action, so it is just a ruby file that uses Lokalise’s API, and that can be executed in your lane.

The first step is to copy the lokalise_download.rb file in your fastlane/actions directory. You can also customize options the way you want.

Then simply add in your Fastfile.

Fastfile

When I first tried it at the end of 2020, if a translation was missing on a language, like Italian for example, it would return an empty translation.
Indeed in lokalise_download.rb, in request_data we had:

export_empty_as: “empty”

This is not the behavior we want. If something is not translated in Italian yet, we don’t want to export the translation in this language’s file, so it will fall back to our main language, English.

This totally depends on the choice you and your product team will make, of course. Maybe you want those translations to be empty in order to be detected more easily and prevent a release with untranslated content.

I gave it another try while writing this article, in February 2021, and now if the translation is empty, it’s still exported but with the default language instead of an empty string.

The configuration is:

export_empty_as: “base”

With this configuration, the behavior would be the same as we already had. Untranslated strings would be in English, as expected. But the strings.xml files would be different from what we had.

We still want to be able to do a manual pull, in case we need a specific translation immediately to continue a task.

The output of the file pulled by the CI, or manually via Lokalise, should be exactly the same unless there is a new or an updated translation.

Another difference between what Lokalise’s action offers and what we want is the sorting order. It sorts translation keys by alphabetical order (A-Z), and we are sorting them by creation date.

It’s possible to use this Fastlane action for any use case, and you can easily adapt it to fit your needs.

For our example, we just have to change this:

To this:

There is also an action to upload translation files.

Option 2: CLI

Lokalise also provides a CLI tool that allows us to do the exact same thing, and much more.

For our usage, Fastlane is enough but you can look into the CLI documentation if you need to do something else other than pulling or pushing translations files.

First of all, you will need to get the binary depending on your platform. Here is the documentation.

Then, it’s a simple command line to execute in order to pull translation files.

lokalise2 --token $LOKALISE_API_TOKEN -- project-id $LOKALISE_PROJECT_ID file download --unzip-to “your_translations_file_path”

You can also set the options you need (see the full list here).

This is how we configured it.

With those two options, you will simply pull the new translation files. The way you create a pull request or a merge request will depend on the source code management tool you use.

This is how we do with Bitbucket.

Using the CLI method

Our pull_translation job, which is integrated into a workflow that is launched every night.

Your circleCI job

And this is our Fastfile:

Your Fastfile

Using the Fastlane method

For the Fastlane method, you can add:

In your Fastlane, call the 3 lanes, one by one, in your CircleCI job. Or, you can create a single lane that calls the 3 others.

You can also include this job in your release workflow, in order to make sure that you include the latest translations in your new version.

And that’s it! You don’t have to bother with translations anymore!

In this article, I talked about two ways to automate your translation process in your CI, but there is more to explore. If you use Jenkins, Lokalise has integration for that. If you need to do something else than pulling or pushing translation files, you can find everything you need in the CLI documentation, or you can write your own Fastlane action in Ruby.

Big thanks to Aircall’s Android team for the review of this article!

--

--