Angular Localization With Transifex Native

Pablo Sanchez
April 7, 2022
12 min read

When considering Angular localization, the most common and out-of-the-box solution is a file based approach that will hold all your strings. There are some libraries out there, which manage strings for you: the built-in Angular i18n module or the library ngx-translate are ones of the most used. There is also the library i18next, which is a general localization framework that supports both pure JS and framework-powered applications.

The built-in i18n module is the easiest way to start localizing an Angular application but it has some downsides: first of all you can’t change the locale on the fly, but you need to compile all the languages and generate the application for each of them, there is no easy way to create a custom translations loader. Secondly, only supports XML files, which are more complex to maintain than, for example, JSON ones.

The second one, ngx-translate, was created to bypass those limitations. It works well, it’s mature and has a high rate of adoption, but despite of that, the built-in module is evolving fast and soon will support all the features provided by this great third-party library. Its main downside is, again, the file based approach.

The last one, i18next is a mature and powerful library for managing file based translations, it has a lot of features and probably will not be superseded by the built-in Angular module for localization. It’s constantly maintained but it has the same downside of all the previously referred solutions: it’s a file based approach which needs much more effort in order to perform different tasks like branching, releasing, etc.

In this post, we will guide you on how to implement Angular localization and internationalization using a different approach, which does not involve managing files. More specifically, we will focus on an alternative called Transifex Native, which you can simply use in your code with no additional work on your side. All translatable content is managed by Transifex Native and all translation updates are served over the air, with additional caching and grouping functionality that you control.

Installation

To start using Transifex Native, you will need to install the Transifex Native JavaScript SDK and the additional Angular components library to your code. After that, you have to create a Transifex Native project in the Transifex application. The Transifex project will provide the required credentials for linking your application to the content delivery system (CDS) that will serve all your content.

npm install @transifex/native @transifex/angular @transifex/cli --save

As we want to use the Transifex Native Angular SDK in our application we need some extra steps to take advantage of all the elements exposed by the SDK in our templates and code.

Declare the TXNativeModule

In our main application module we need to add the Native module, like this:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { TxNativeModule } from '@transifex/angular';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    TxNativeModule.forRoot(),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

This way we can have available all the elements provided by the Transifex Native Angular SDK in our application.

Initialize the singleton translation service

In our entry component, we need to inject the translation service provided by the SDK and initialize the library with the generated token from our Transifex project. The service is a singleton instance and can be used in any part of our application, as the initialization is done globally.

import { Component } from '@angular/core';
import { TranslationService } from '@transifex/angular';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private translationService: TranslationService) {
    translationService.init({
      token: '1/adfdaca976eb9b4d554d7******',
    });
  }
}

The Internationalization Process

With the SDK in place, you can start using the provided functions in your code. The Native SDK offers different ways in order to mark strings for localization:

  • The T and UT components for using in templates
  • The T decorator for using in variable declarations
  • The translate pipe for using in templates

This is an example of using Transifex Native on a template:

  <h2>{{ 'Hello world!' | translate }}</h2>
  <p>
    <UT
      str="To review the <b>terms of service</b> click here: <a href=\'terms\'>View terms</a>">
    </UT>
  </p>
  <br/>
  <p>
    <T
      str="Number of apples in the basket: {apples}"
      [vars]="{ apples: apples_number }">
    </T>
  </p>

As you can see in the example above, we’ve used the translate pipe and the T/UT components in order to mark the strings you want to translate, and pass attributes, like variables. Other attributes available are key identifier, tags, character limit, comments, and context. These attributes will be available to the localization team as additional context to do their work better.

You can also define pluralized strings using the ICU syntax inside your strings, like in the example below.

<UT
  str="Updated: {minutes, plural, =0 {just now} =1 {one minute ago} other
  {# minutes ago}}"
  [vars]="{ minutes: minutes }"
></UT>

If you need to get some variables translated in the component’s code, you can do it like this:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @T('Angular Transifex Native Demo')
  mainTitle!: string;
...

And then use the variable inside the component’s template, like this:

<span><UT str="{title} is running!" [vars]="{ title: mainTitle }"></UT></span>

Using the syntax and T function shared above, you can proceed by marking strings in all your existing code files; no extra file is needed. 

More about this in our Angular internationalization guide.

And just like that you are ready to proceed with Angular localization.

Using the translation service

The translation service can be used inside your code, in components or libraries. It is a powerful singleton instance and exposes methods and observables which can help you with your specific flow. Using the service you can:

  • Initialize an instance
  • Add, delete or select an alternative instance
  • Set and get the current locale
  • Translate a string
  • Fetch translations in batches for lazy loading and performance
  • Retrieve the available languages

Also you can subscribe to two events, in order to monitorize the flow:

  • Locale changed
  • Translations fetched

Using the built-in language picker

The Angular SDK provides a ready to use component called language picker, in order to select the current locale and move with angular localization effortlessly. The component exposes an event to detect when the current locale has changed.

<!-- Toolbar -->
<div class="toolbar" role="banner"> 
  <span class="welcome">{{ 'Welcome' | translate }}</span>
  <div class="spacer"></div>
  <tx-language-picker class="languagePicker"></tx-language-picker>
</div>

Pushing content for translation

To push content for translation, you will need the txjs-cli tool installed on your system. You will also need the tokens created in your Transifex Project to be able to send content to your project. Using the CLI tool will scan all files in the selected folder and push the translatable content to your Transifex project using the command shown below.

$ npx txjs-cli push <SRC_FOLDER> --token=<PROJECT_TOKEN> --secret=<PROJECT_SECRET>

Using additional parameters, you can mark the content you push with custom tags, or make sure that you clean up any unused content. Read all the details in our CLI documentation.

Previewing translations

To preview translations in your application, you simply switch languages using your language picker. Angular components for Native SDK include a language picker that binds with the Native service to request translations, but you can build your own picker, too.

When a new language is selected, Native SDK will check if the latest translation versions are cached. If not, they will be fetched and made available in the application. As new translations are added to the Transifex project, they are made available in the application within an hour.

If you want to get the latest translations in your localhost or live environment, you can use an invalidate command from your command-line interface.

$ npx txjs-cli invalidate --token=<PROJECT_TOKEN> --secret=<PROJECT_SECRET>

Working with translations in Transifex

Entering the Transifex interface, all the content you have pushed from your code is added to the resources of your Transifex Native project. To access the phrases you pushed, visit the editor.

In the editor interface, you will see the full list of phrases and a set of tools that assist in content localization. You and your localization team can start working on the content by adding new translations or improving existing ones. Whenever a translation is saved, it is automatically made available in your Native application.

With Transifex Native, you can also fix a typo or improve the copywriting of your original text. Click the edit source string option and improve your content. Similar to translations, all edits are available in your Native application.

When will I see updated content in my application?

Transifex Native translations are served from a secure CDN server, called Transifex CDS, and are updated once every hour. Native CDS is an open-source server that you can install within your own infrastructure for additional modifications and security.

Angular localization with Transifex Native

 

Optimize your workflow further

Transifex Native is flexible enough to support more complex workflows with an open architecture and toolset for Angular localization to work more efficiently.

Working with branches

If you are working on multiple branches, you can mark the strings you push to Native by adding tags directly to the CLI command. This way, you can prioritize localization work in Transifex, as your localization team can filter by tags in the Editor. To push with tags, use the command shown below.

txjs-cli push <SRC_FOLDER> --token=<PROJECT_TOKEN> --secret=<PROJECT_SECRET> --append-tags=<YOUR_TAG>

Working with string keys, increase re-usability

If you want to improve your workflow in a development team and optimize the amount of content your localization team has to translate, use keys for your strings.

To use keys, you will need to add an extra attribute in the Native function that marks strings as translatable. Keys are unique identifiers that can be re-used in other areas of the code. Multiple strings with the same key are pushed as a single string in Transifex. So, the localization team will only need to add a single translation.

To use the key attribute, simply pass the _key parameter in the T component:

<Text><T _str="Hello world" _key=”welcome.string” /></Text>

Content splitting

To serve smaller chunks of translation on specific pages, you can use the content-splitting functionality. Breaking your content into smaller chunks is very useful in cases where your application has a lot of content but is not needed on every screen. For example, there is no reason to fetch over the air your help center content while the visitor is on your application settings page.

Content splitting works on top of tags, so you can either set a new tag or use any pre-existing ones to segment your content.

To use content splitting, set the appropriate tag in the tx.init function:

tx.init({
  token: 'project_token',
  filterTags: 'homepage',
});

You can combine content splitting with your branching tags, so you can test or debug localization in your localhost or staging environments:

tx.init({
  token: 'project_token',
  filterTags: 'new-login-page-branch',
});

Read the documentation on content splitting for a full overview.

Lazy loading translations

In combination with content splitting you can load translations in batches whenever is needed, for performance reasons.

You can fetch specific translations when the component first renders, for example:

  constructor(private translationService: TranslationService) { }

  async ngOnInit(): void {
    await this.translationService.fetchTranslations('menu');
  }

or in a section of a template in order to fetch a group of translations marked with a specific combination of tags, for example:

  <p class="small-text" [txLoadTranslations]="'menu'">
    <a href="#/home">
      <UT str="home" key="text.home" inline=true></UT>
    </a>
    &nbsp;
    <a href="#/terms">
      <UT str="terms of service" key="text.terms_of_service_1" inline=true></UT>
    </a>
    &nbsp;
    <a href="#/privacy">
      <UT str="privacy policy" key="text.privacy_policy_1" inline=true></UT>
    </a>
    <a class="align-right" href="#/login">
      <UT str="logout" key="text.logout" inline=true></UT>
    </a>
  </p>

Automating Application Releases

When your feature or branch is ready for deployment, you can do some housekeeping on your content using Native, too. Because content is always added to your Transifex Native resource, you might end up with many string artifacts while you are testing things on your branch.

You can clean up all the faulty content from the Native CLI tool using the purge attribute when pushing:

$ txjs-cli push <SRC_FOLDER> --token=<PROJECT_TOKEN> --secret=<PROJECT_SECRET> --purge

Purge will parse all code files found in the <SRC_FOLDER> and keep only the phrases detected in those files, deleting any phrases that are not detected in the code files.

By including the purge option in your deployment flow, you have housekeeping on auto-pilot.

Add more context for better translations

Your localization team working in Transifex will need more context for each phrase you are pushing. You can provide that context directly from your Angular components by using additional attributes of the T function:

  • Context, to provide more details about a phrase
  • Comments, where you can share instructions about the phrase
  • Character limit, to share a specific requirement regarding the length of the translation
  • Tags, for better string grouping.


An example of this context is as follows:

<Text><T _str="Hello world" _context=”login screen, welcome screen” _comments=”String displayed as header and is followed by explanation paragraph” _charlimit=”30” /></Text>

All the additional information you attached to each phrase is available in the Context tab of the editor.

3 Reasons for Angular Localization with Transifex Native

Now you know how to install Transifex Native, but do you know the “why”? Here are 3 reasons why you should install Native on your stack: 

  • Less work for developers: Native minimizes developers’ involvement in the localization process by making localization a part of your code.
  • No more files: A big part of the old-fashioned localization method is transferring files back and forth from the TMS to your platform. Such a simple task could surely be automated, right? That’s a big part of what Transifex Native is all about.
  • Focus on localization: Forget about having to implement translation updates to your app. Native separates localization from development so that translators can focus on translating and engineers on programming.

Wrapping up

There are several libraries to deal with Angular localization and internationalization. The majority of them are using the file-based approach to handle the translations in each locale. Transifex Native offers a solution based on a new approach, over the air, which has a lot of benefits and has different tools and SDKs to assist the migration to this new approach. It’s very easy to give a try and compare with the traditional techniques, and decide which fits better in your working flow. 

Further reading: 

TRANSIFEX
Start your localization journey
Bring your brand to the world and create global experiences with the power of AI
FREE TRIAL
Pablo Sanchez
FacebookgithubGoogle+Fill 88Twitter