Using MessageFormat with Transloco
Tags: typescript, transloco, internationalization, angular
Published: 2019-08-17 11:52:45

# :guitar: Using MessageFormat with Transloco

[Transloco](https://github.com/ngneat/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](https://github.com/ngneat/transloco/blob/master/README.md).

However, it soon became apparent that the library did not support [messageformat](https://messageformat.github.io/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:

```ts
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](https://github.com/ngneat/transloco/pull/15) to the [Transloco](https://github.com/ngneat/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.

## :wrench: 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>`

## :hammer: 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](https://github.com/ngneat/transloco#installation).

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:

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

In the providers array of the `@NgModule`

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

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

## :rocket: Usage

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

`en.json`

```ts
{
  "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`

```ts
{
  "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

```html
<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

```html
<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

```html
<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>
```

## :tada: 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
```

## :beers: 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](https://github.com/ngneat/transloco) you definitely should. It's i18n made easy!

Thanks for reading!