January 7, 2020

Using pipes with ngx-translate

Angular delivers it’s own i18n (internationalizion) API. Although the implementation is already very extensive and mature, some use cases are not covered. This also includes changing the language at run-time. When implementing Angular, a build must exist for each language. To close this gap, packages have been created that extend the functionality. A representative of this is ngx-translate, which we want to discuss in more detail in this post.

tl;dr
Even though Angular delivers it’s own i18n (internationalizion) API, the ngx-translate module is part of most Angular-developers toolkit. While the built-in capabilities of Angular try
to cover broader and more complex use-cases, ngx-translate helps to fill the gaps. In this post we have a look at the main use-case, where ngx-translate is superior: changing the language of an application at run-time. This fix comes with a cost though. The Angular pipes and especially the date-pipe don’t respond to the ngx-translate package. As workaround you can use a proxy pipe that extends the functionality and reestablishes the familiar behavior.

What’s the Problem?

When using Angular’s API the application can adapt to the browsers LOCALE_ID. For this to happen, the application has to be rebuild though.  When the use of multiple languages is used frequently, unpredictable or in the same session, this is can make the experience more than unpleasant. Luckily we can work around that shortcoming, using ngx-translate. The module makes it possible to switch between different languages as often and whenever you like. Without interrupting the workflow or rebuilding the Application. So far so good! There is one problem though. Using ngx-translate will not be recognized by all the nice pipes angular delivers us. Especially annoying is this behaviour when using the datepipe.

So is there an opportunity to use the advantages of ngx-translate and still be able to enjoy the convenience of the datepipe? Yes there is, let’s have a look how to manage it.

Using i18n API of Angular

First let’s have a look at the use of Angular’s i18n API. The built-in implementation relies on the use of the LOCALE_ID, which is consumed by dependency injection. You can set the LOCALE_ID by using providers as a container for the window.navigator.language value of the browser. This can be declared in the NgModule metadata of the appModule ( or any Child-Module you need to use it in). The following code-snippet shows an implementation:

Therefore the language is set according to the client’s browser language when building the app – and only when building the app. So unfortunately when we want to change the language on run-time, we are stuck. We would have to rebuild the app every time we want to change the language settings. this might be acceptable for apps, that a seldomly used in different languages or have different builds for different countries. But if we want to create one application, that is used globally and concurrently by user of different nationalities, we run into heavy UX problems. Luckily  Oliver Combe, the creator of the ngx-translate package, supplied us with a solution. Until recently he was working for Angular to incorporate the capabilities of his package into the build-in API, but for now it is not part of the API.

Using ngx-translate

So first let’s have a look at the basic usage of ngx-translate. We created a very basic app for demonstration purposes  with just one component, that shows the date of our next training (just the current date) and an option to switch between languages.

As you can see the usage of ngx-translate is pretty straight forward. after having installed the package with the package manager of your choice (we used npm):

Then we import the core as TranslateService an use it in the appComponent. Now we add the desired languages in the constructor with the function translate.addLangs(['en', 'fr', 'de']); . In our case it’s english, german and french. In the next step we set the default language to english: translate.setDefaultLang('en'); .  Regarding the configuration of the service, that’s already it. Now we define which language is used for starting the app – in our case we use the browser language.

Therefore we use the function translate.getBrowserLang();  to get the LOCALE_ID and store it in the constant const browserLang . To set a desired language we now can use the function translate.use(). Initially we want to determine if the browserLang is set to one of the choosable languages. If this is not the case, we initialize the component in english: translate.use(browserLang.match(/en|fr|de/) ? browserLang : 'en'); . So now the TranslateService is configured and the initial language set. To use the functionality in the template, we add two more functions. changeLanguage()changeLanguage(language: string)  which is called when switching the language dropdown and get currentLanguage(): string  to query the currently selected language.

Having set up the appCompontent.ts we now have a look on the template. We saved the different language strings in the three JSON-files en-json, de-json and fr-json. They all have the following structure:

Looking at the headline h2 we can see, we just print HOME.TITLE  and use the translate-pipe Angular delivers us. There’s no change in standard procedure.  the same happens with the other strings. For the date <p>{{ today | date: "full"}}</p>c  we use the Angular date-pipe.  For switching the languages we incorporate a select statement, which triggers the mentioned (change)="changeLanguage(langSelect.value)"  function on change and sets the current selection.

Finally we need to import the Translate Module in the appModule. To load the different language JSON-files, we register a loader for the Translate Module. This way the JSON-files can be loaded with the HttpClient.

Et Voila! We are all set up for a nice user experience for switching the languages we configured at run-time. Check it out and have an overview over the DEMO-app in the Stackblitz following project:

But wait! Everything works fine, despite the language and format conversion of the displayed date. Surprised? Well that’s the shortcoming of using ngx-translate. It doesn’t support the usage of Angular’s delivered pipes. Most prominent when it comes to language formatting is the date-pipe and therefore we focus on a solution for this problem . The logic is adaptable to every Angular pipe though.

Using ngx-translate with ProxyPipe

Luckily there is a lightweight workaround for our little inconvenience. We have to build a proxy pipe, that will be positioned on top of the Angular date-pipe and injects the selected language. As you can see in the following code-snippet we create DateProxyPipe with the name date . so this overrides the call of the Angular date-pipe. In this DateProxyPipe we create a new DatePipe in the transfom function that consumes the translateService.currentLang  function. The transform function of the DateProxyPipe takes a string for the  value of the date and one for the desired pattern. The strings are passed on to the transform function of the new ngPipe, which is returned.

Now we can give the ProxyDatePipe the current language that is registered in the TranslateService and the date format will be set accordingly. The following Stackblitz project we included the ProxyDatePipe. You can see how the behavior of the Angular date-pipe is back in action with just a little bit of extra work.

Related Posts

Janik Kessler
Developer at thecodecampus </>


One response to “Using pipes with ngx-translate”

  1. SEO Company says:

    Awesome post! Keep up the great work! 🙂

Leave a Reply

Add code to your comment in Markdown syntax.
Like this:
`inline example`

```
code block
example
```

Your email address will not be published.