When our app becomes more or less popular, it starts to be used by a larger and larger audience. But if we want to expand the circle of users, even more, we should think about the internationalization of our application.
And at first glance, it seems like a simple task. After all, the architecture is already laid out, the basic logic of the application is already described, and the code is already written. And even bugs are reliably hidden and crutched.
Depending on the languages we are going to support, we will have to deal with issues such as pluralization, currency rules, case and ending differences, RTL language support, date display, and so on. Let’s try to figure out how we can solve these issues.
We will share the experience of the Intspirit team and briefly consider the main approaches for internationalizing Angular apps in this article. Let’s go through the advantages and disadvantages. And also we will investigate in detail the method that is built directly into the Angular framework itself.
Article aspects in brief:
Main libraries for translating Angular applications and their differences:
Built-in Angular solution — @angular/localize
- Configuring and usage
Overview of solutions
Let's walk through what we can use to solve our translation problem:
1) ngx-translate — probably the most popular library we’re going to consider.
- fairly easy to use
- there is a built-in loader for extracting files with translations along the specified path
- supports is provided for Ahead-of-time compilation
- files are stored in json format that makes them easily manageable
- possible to handle the lack of translation
- there is a special editor (BabelEdit) to work with translations.
- this library was developed as a temporary solution and will become deprecated sooner or later. Therefore, if you are developing a large Angular app, this solution is not the best choice
- decreases the performance of the application as it loads the Angular app with additional logic.
2) I18next — internationalization framework. It is not tied to any particular framework or library and can be used together with ReactJS, Angular2+, as well as many other solutions, including Vanilla.JS.
- Sustainability — strict attitude of the development team to backward compatibility
- Maturity — one of the very first solutions for internationalization
- Extensibility — it has many separate plugins and utilities, supports the most popular frameworks
- Richness — by using just one function, you get a lot of functionality including caching, support for working with arrays and objects, support for ICU specifications, and much more.
- i18next is complicated — quite wide documentation
- i18next is bloated — huge bundle size
- most likely, this framework has no advantages over the internationalization module @angular/localize built into Angular. Therefore, we would not recommend using it for Angular applications.
3) Transloco — relatively new and actively growing lib. It works only within Angular apps:
- Clean and DRY templates — Keep your templates clean and DRY using the Transloco structural directive
- Support for Lazy Load — Load translation files on-demand using Transloco’s built-in scope feature
- Rich Plugins — Transloco has a rich plugins ecosystem that provides the tools you need for both development and production environments
- Support for Multiple Fallbacks — Extensive support for fallbacks. Multiple fallbacks for failed requests and missing keys replacement
- Support for SSR — Pre-render your translations with Angular SSR and Transloco
- L10N — Localize your app with Transloco. Transloco provides the transloco-locale package which provides pipes such as Date, Number, Currency, and more.
- Since the library works with translations in a dynamic mode, and does not prepare static files for rendering, it slows down the performance of the application just like ngx-translate.
- Due to the fact that the library is quite new, it hasn’t such a wide community as the others.
4) Angular built-in module (@angular/localize) — initially, this module had some problems and limitations. But now it fully covers all the needs of developers, with the exception of a few minor inconveniences which we will discuss later in the article.
- has shown the best results in terms of application speed
- the official solution supported by the Angular development team
- Integration with Unicode CLDR
- a special tool to extract strings into translation files
- support for the Ahead of Time compilation
- an ability to provide context for translations
- supports ICU message format
- translations work in a static mode, which means you need to generate a separate bundle for every language
- creating new translation files is not well-automated at the moment
Now let’s take a closer look at Angular’s built-in module and, to start, deploy a quick test stand:
We assume you have the latest stable Node.js version installed.
Step 1 — Installing Angular-CLI:
$ npm install -g @angular/cli
Step — 2. Initializing the app:
$ ng new angular-sandbox
Step — 3. Adding the Localize module:
$ ng add @angular/localize
Step — 4. Modifying angular.json:
Step — 5. Marking templates using a special attribute “i18n”:
We can also add some metadata such as meaning, description, and id so we could easily manage our translations later. After this, the HTML file will look like this:
Step — 6. Launching the extract script using Angular CLI:
$ ng xi18n --output-path src/i18n
As a result, we get a file in the src/i18n directory
Step — 7. Creating a translation file for a new language. To do it we just create a copy of the initial messages.xlf file, rename it to messages.ru.xlf and add a
<target> tag which will contain the translation, under the
Step — 8. Checking the configuration’s performance:
$ ng serve --configuration=ru
To create a packaged version of the application, we can use the following command:
$ ng build --prod --localize
This command will produce 2 builds as the output (for Russian and English languages).
And with that, we have performed the minimal set of actions required to set up translations (for Russian and English languages in this case).
In case we need to translate attributes, we can also use the following syntax:
i18n-<ATTRIBUTE_NAME>="@@<VARIABLE_NAME>". For example:
If we want to have pluralization, then we need to add the following code:
If we want to use pipe, then we need to add these lines to app.module.ts:
After this, we could use standard Angular pipes, such as DatePipe, CurrencyPipe, DecimalPipe, PercentPipe, and I18nPluralPipe. An example of this:
When serving the “ru” configuration of the app, the text in this place will be “воскресенье, 3 октября 2021 г.”
To implement the translations in .ts files we can use the $localize function. Let’s add this:
After which running this command:
$ ng xi18n --output-path src/i18n
will add a section for our new phrase to messages.xlf:
Houston, we have a problem!
The first problem you may encounter is the lack of automation.
Let’s say that the application is being actively developed and every day more and more phrases for translation appear. This means that you need to run the following command regularly:
$ ng xi18n --output-path src/i18n
This will update messages.xls, which contains the source phrases for translation, but it won’t update messages.ru.xls, messages.fr.xls, messages.ar.xls, and other files containing the translations. This means that you have to transfer tons of data manually from one file to another. And in the course of such manipulations, you can easily lose a bit of data.
There are two solutions to this problem:
- Using the @ngx-i18nsupport/tooling library. It automates the process of updating translation files
- Using a third-party service — in this case, Lokalise. It provides many convenient features but it’s a paid service (oops!).
The second problem is that, in order to be able to run multiple languages at the same time, you have to host several bundles at once. But this is typical for this application translating approach, and the Angular team is not going to switch it up anytime soon.
Despite the fact that @angular/localize has its share of shortcomings, from the experience of the Intspirit team, this library is the most promising and successful solution at the moment, especially considering that the Angular team is directly involved in its support and development. Plus, this solution has shown the best results in terms of application speed.
Wishing you zero sleepless nights caused by bugs in production, and stay tuned for new articles!