loading...

Using MessageFormat with Transloco

coly010 profile image Colum Ferry ・4 min read

🎸 Using MessageFormat with Transloco

Transloco, an Angular Internationalization Library, was released recently (2019-08-16), with the tagline "Angular Internationalization Done Right". After playing about with the library, it's very clear to see that it greatly simplifies i18n within Angular applications, providing multiple methods to use it within your templates:

  • Structural Directive
  • Attribute Directive
  • Pipe

The most performant of the above methods is the Structural Directive approach as it opens only one subscription for your template. You can find out more about incorporating Transloco in their docs.

However, it soon became apparent that the library did not support messageformat out of the box. This could have been a real deal breaker for us, and for other companies that use messageformat to handle pluralization and gender in applications. If those phrases are new to you, have you encountered any of the following:

return mins + mins === 1 ? ' minute' : ' minutes' + ' ago';

let pronoun = 'They';
if (user.gender === 'male') {
    pronoun = 'He';
} else if (user.gender === 'female') {
    pronoun = 'She';
}

return `${pronoun} went to the shop.`;

Doing this every time we need to handle plurals and genders can get tedious, to the point we may put these into their own methods or services to reuse them. But what if we can remove this logic from our codebase altogether? What if we need to support multiple languages, will we need to add additional logic to return the correct pronoun for the active language?

No. Rather, we should let our translation files handle this for us! I recently made a PR to the Transloco library to add support for messageformat. For now, it will be apart of Transloco >= 1.1.1, however there are plans to move this functionality into a plugin, as not all users may want it.

Below I will show you how to setup and use messageformat with Transloco.

🔧 Prerequisites

Ensure you have the Angular CLI installed globally. If you do not, run the following command:

npm install -g @angular/cli

If you do not have an application that is currently being developed, create a new one using the command:

ng new <application-name>

🔨 Setup

If you haven't already installed Transloco, first, add it using the ng add @ngneat/transloco command. This should install the required packages and scaffold the required files for Transloco to function.

You can find more on installing Transloco here.

To use messageformat we need to tell Transloco to use the MessageFormatTranspiler rather than the DefaultTranspiler. To do this, open your app.module.ts and the following:

import { TRANSLOCO_TRANSPILER, MessageFormatTranspiler } from '@ngneat/transloco';

In the providers array of the @NgModule

@NgModule({
    providers: [
        ...,
        { provide: TRANSLOCO_PROVIDER, useClass: MessageFormatTranspiler }
    ]
})

This will allow Transloco to correctly interpret messageformat formatted strings in your translation files.

🚀 Usage

After the setup, using messageformat is very simple. You can now do the following within your translation files:

en.json

{
  "noParams": "Hello - english",
  "params": "The following {{ value }} was replaced by Transloco - english",
  "plural": "{count, plural, =0 {no results} one {one result} other {# results}} - english",
  "gender": "{gender, select, male {he} female {she} other {they}} went to the shop - english"
}

es.json

{
  "noParams": "Hello - spanish",
  "params": "The following {{ value }} was replaced by Transloco - spanish",
  "plural": "{count, plural, =0 {no results} one {one result} other {# results}} - spanish",
  "gender": "{gender, select, male {he} female {she} other {they}} went to the shop - spanish"
}

In your templates:

Structural Directive Approach

<ng-container *transloco="let t">
    <ul>
        <li>{{ t.noParams }}</li>
        <li>{{ t.params | translocoParams: {value: "word" } }}</li>
        <li>{{ t.plural | translocoParams: {count: 2} }}</li>
        <li>{{ t.plural | translocoParams: {count: 1} }}</li>
        <li>{{ t.gender | translocoParams: {gender: "male"} }}</li>
        <li>{{ t.gender | translocoParams: {gender: ""} }}</li>
    </ul>
</ng-container>

Attribute Directive Approach

<ul>
    <li><span transloco="noParams"></span> }}</li>
    <li><span transloco="params" [translocoParams]="{value: 'word'}"></span></li>
    <li><span transloco="plural" [translocoParams]="{count: 2}"></span></li>
    <li><span transloco="plural" [translocoParams]="{count: 1}"></span></li>
    <li><span transloco="gender" [translocoParams]="{gender: 'male'}"></span></li>
    <li><span transloco="gender" [translocoParams]="{gender: ''}"></span></li>
</ul>

Pipe Approach

<ul>
    <li>{{ 'noParams' | transloco }}</li>
    <li>{{ 'params' | transloco: {value: "word" } }}</li>
    <li>{{ 'plural' | transloco: {count: 2} }}</li>
    <li>{{ 'plural' | transloco: {count: 1} }}</li>
    <li>{{ 'gender' | transloco: {gender: "male"} }}</li>
    <li>{{ 'gender' | transloco: {gender: ""} }}</li>
</ul>

🎉 Results

Now, whichever approach you choose, when you run your app, the output will be:

When language is en:

Hello - english
The following word was replaced by Transloco - english
2 results - english
1 result - english
He went to the shop - english
They went to the shop - english

When language is es:

Hello - spanish
The following word was replaced by Transloco - spanish
2 results - spanish
1 result - spanish
He went to the shop - spanish
They went to the shop - spanish

🍻 Conclusion

As you can see from above, using the MessageFormatTranspiler with Transloco can drastically reduce the amount of logic in your codebase around grammar relating to pluralization and genders. It makes i18n much easier to implement as you can simply give your en.json file to your translation team and they can provide translations for all identifiers. These translations can be added, removed and maintained without affecting the business logic of your application!

If you haven't already looked at Transloco you definitely should. It's i18n made easy!

Thanks for reading!

Posted on by:

coly010 profile

Colum Ferry

@coly010

Full Stack JS Developer and JS Enthusiast

Discussion

markdown guide