DEV Community

Cover image for Advanced enterprise localisation process with Lingui, Locize, GitHub Actions, Docker, React
Gleb Krishin
Gleb Krishin

Posted on

Advanced enterprise localisation process with Lingui, Locize, GitHub Actions, Docker, React

I have experience in integrating localisation into three applications of different sizes. In this article, I will share my experience only with the enterprise localisation process. If you are interested in localisation for other project sizes, please share your thoughts in the comments πŸ’­

General idea πŸš€

The main idea was to have a process allowing developers to do fewer actions and have everything automated in the CI, from uploading to downloading the translations.
We want a source of truth for keys in the code and a source of truth for translations - a 3rd party translation platform (in our case - locize).

Choosing front-end library πŸ“š

Quick Summary:

We choose lingui.

Comparison table for front-end libs

First, we should check out the libs for the front end, which will work with our localisation.

Name Size (minified + gzipped) Dependecies Typescript Open/Closed issues Last publish
react-i18next 6.7kB 2 8% 8/1044 a month ago
lingui 7.8kB 3 89% 20/693 4 months ago
react-intl 17.8kB 10 77% 12/1686 4 days ago
react-translated 7.8kB 2 0% 3/6 3 years ago

Also, a big plus was a minimal amount of issues for lingui/react. Previously I tried react-i18next, which was good, but we didn't go with it because the feedback from the other organisation members was good. Our application already has system modules that were integrated with lingui.

Here is a detailed article about how to choose the proper library.

Choosing 3rd party localisation service πŸ—ΊοΈ

Quick Summary:

We choose locize.

Localisation platforms comparison

service integration pricing for 10k/m experience for translator developer features summary
locize.com good doc, easy fluid pricing depends on the usage bad UX, hard to collaborate versioning, plurals, reach API & CLI Unlimited Contributors, Unlimited projects
poeditor.com GitHub app $38.24 comments, good UI, machine translations plurals, versioning, multiple projects Unlimited Contributors, Unlimited Projects
lokalise.com GitHub app $230 (only 10 seats included) discussions, good UI plurals, work with multiple branches Really high price with no machine translations, limited seats
translation.com sync cli/platform $0.01/ key active projects $100 $0.005/key archive project $50 discussions, machine translations, good UI plurals Promoted by lingui, easy to use, cheap
smartling - - - - Push you to buy annual, high price for a small number of features
Π‘rowdin GitHub, Gitlab 0.01$/key with no available integrations, basic subscription is so limited, you also need additional payments for translation managers - - good UI, not so hard to use
phrase - 70usd per month for 3 users (100api/request per user monthly) - - too expensive, most of the features are the same or less as everywhere else

Minus sign in the table has the meaning of not having a feature or doesn't have enough info about features in the specific service.

At first glance, I realised there would be little difference in localisation platforms. For our team, the crucial point was to have a good amount of features for a reasonable price and a robust API which would allow us to deeply integrate our CI with a translation platform.

Platform locize was chosen for:

  1. Fluid pricing systems that depend on the actual usage of the platform
  2. Good versioning system, which allows you to use a semver versioning system
  3. Reach API and CLI for a better low-level integration
  4. Unlimited Contributors and Unlimited projects
  5. Easy way to integrate with client library - lingui.
  6. Fast support from the creator

Upload new keys process πŸ“‘

Here is a sequence diagram which explains the whole process of uploading. Your detailed implementation can be different according to your project tools.
If you don't know what is sequence diagram you can check out this documentation in mermaid

Upload new keys process

Implementation details

This section will describe some implementation details inside our project. If you're using another tech stack, feel free to skip it and go on.

Step 1

We only trigger the upload process in the origin/main branch when merging the PR.

Step 2

Our project is a monorepo containing several front-ends which need localisation.

Rush provides an excellent way to understand what project is changed by running rush change.

After that, we pick these projects inside the CI step and analyse the package.json of this project for the localisation: true flag. We put a flag inside our front-end project for a faster localisation check. This config section is rarely used, but so cool to know about.

package.json

{
  ...,
  devDependencies: {...},
  config: {
    localisation: true
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3

To extract the translations keys from the code, we used lingui extract

lingui extract --clean

This tool works as we need it - developers do nothing, and everything is automated. He/she is just putting translation keys into the code, and this command will automatically search for the keys and put them into all translation files if the key doesn't exist there yet.

Version calculation

We're calculating a future version and returning a major or minor version.

Steps 4-9

We upgrade a minor version when developers add new keys to the translations.

These steps are done by manipulating the Locize API

Steps 10-14

When a developer removes translation keys, we're upgrading a major version.

These steps are done by manipulating the Locize API

Download new keys process πŸ“²

Download new keys process

Implementation details

This section will describe some implementation details inside our project. If you're using another tech stack, feel free to skip it and go further.

Most steps are part of the download-localisation.sh script.

Step 1

The developer pushes code to the remote repository.

Step 2

Inside Github CI, we're building a docker image of the application.

Step 3

We run the image with environment variables.

Useful env variables were:

  1. Translation version. For the different dev environments, we used different translation versions.
  2. Project id from locize. As I wrote, we had several projects inside one repository, so we need several in locize. Also, we need our script to be reusable across the organisation.
  3. Namespace.

Step 4

This part of the download-localisation script is responsible for pulling languages for the project.

LANGUAGES="$(
  curl -s "https://api.locize.app/languages/$LOCIZE_PROJECT_ID" \
  | jq -r 'keys | join(" ")'
)"
Enter fullscreen mode Exit fullscreen mode

Step 5

Code piece which helps us to download translations

for language in $LANGUAGES
do
    printf "Downloading translation for $language..."

    if [ -d "$TRANSLATIONS_DIR/$language" ]
    then
        rm -fr "$TRANSLATIONS_DIR/$language"
    fi

    mkdir -p "$TRANSLATIONS_DIR/$language"

    curl -s -o "$TRANSLATIONS_DIR/$language/$LOCIZE_NAMESPACE.json" "$LOCIZE_API_BASE/$LOCIZE_PROJECT_ID/$LOCIZE_VERSION/$language/$LOCIZE_NAMESPACE"

    echo "Done"
done
Enter fullscreen mode Exit fullscreen mode

Step 6

Loading the translations is happening with the help of @lingui/remote-loader. This remote loader wasn't listed in the lingui documentation but exists in npm and the codebase. Finding this module took some time, so right now, you can use that time wisely!

Finish 🏁

I hope you enjoyed reading this article. Please leave your thoughts about such localisation design architecture.

Cover design by: Julia Mazur

Top comments (0)