DEV Community

Cover image for Localization in Angular with DevOps and Crowdin
Nicolai Ringbæk for IT Minds

Posted on • Originally published at

Localization in Angular with DevOps and Crowdin

It's not uncommon for projects to require localization at some point. Setting up and using localization over time, including translation management, can become a tedious and time-consuming task if not done properly.

This post will dig into the localization setup needed for Angular and how to integrate Crowdin and DevOps to automate as many boring tasks as possible.

  • DevOps is Microsofts DevOps services
  • Crowdin is an online localization tool to manage translations

The POC project

The project we want to enable localization for, is a simple Angular 9.1 solution. It contains one component with some sample text.

The gist of enabling localization in Angular is to ng add @angular/localize and utilize the i18n-tag. This enables the Angular tooling to extract and create translation source files.

The angular.json-file can then be extended for our project to include our localization setup regarding what locales that should be supported. In combination with this, we can add two npm tasks to simply localization support.

"i18n": {
    "sourceLocale": "en-US",
    "locales": {
      "da": "src/locale/da/messages.xlf"
Enter fullscreen mode Exit fullscreen mode
"scripts": {
  "ng": "ng",
  "build": "ng build --prod --localize",
  "localize": "ng xi18n --output-path src/locale"
Enter fullscreen mode Exit fullscreen mode

The localize tasks builds and extracts any strings in our application that supports localization using the Angular CLI command xi18n. It uses our setup from our angular.json-file. In this case, it extracts text with the expectation of it being en-US and places it in the file src/locale/messages.xlf.

The build command with the --locale argument builds our application and outputs a compiled application for each locale defined. Metadata such as the <base>-tag and i18nLocale is automatically applied, which reduces the need to create customized build configurations for each supported locale in most cases - required in previous Angular versions.

Output builds

Crowdin integration

The setup for Crowdin is somewhat straight forward. Within integrations, we can enable Azure Repos and setup our branch target and configuration. This creates a crowdin.yml-file in our repository with the given translation targets.


  - source: /src/src/locale/messages.xlf
    translation: /src/src/locale/%two_letters_code%/%original_file_name%
Enter fullscreen mode Exit fullscreen mode

At this point, our strings is now ready to be translated in the Crowdin portal.

Crowdin portal

Crowdin automatically detects when new translations has been created. It then creates a pull-request with the updated translations ready to be merged.

PR Overview
PR File

The result

Our translation is handled by Crowdin and automatic synchronization has been enabled between our repository and Crowdin. To serve our different locales locally, we need to add locale-specific configuration targets in our angular.json-file.

"build": {
  "configurations": {
    "da": {
      "localize": ["da"]
"serve": {
  "configurations": {
    "da": {
      "browserTarget": "loca:build:da"
Enter fullscreen mode Exit fullscreen mode

We can now start a local instance of our application. The -c argument specifies our target configuration. Our port defaults to 4200 for our setup, so to run multiple instances, we need to specify a free port.

ng serve -c=da
ng serve --port=4201
Enter fullscreen mode Exit fullscreen mode

Localization result

Future of Angular localization

A much wanted feature for Angular is to add native support for localization in component/TS code. We're getting closer and closer. According to an issue on GitHub, the support can be expected to land with the release of Angular 10... Fingers crossed - until then, we can add our translation definitions in template code using the i18n-tag and apply the same id across to map at compile-time.

The syntax will utilize the $localize command. Support for the command itself is already added with the ng add @angular/localize import.

This boils down to a syntax looking like the following with the i18n ID explicitly defined.

title = $localize`:@@title:Localization demo`;

Top comments (0)