How to use angular 9 $localize with plurals?
Asked Answered
B

3

19

Since Angular 9 we can use

$localize`Hello ${name}:name:`

For i18n in typescript code. This still has some limitations as the ng xi18n command does not detect the strings, but if these texts are added manually to the translation file it works.

The $localize function is quite well documented in the JSDoc in the source, however it does not explain how to work with plurals. What I mean is something like this (pseudo-code):

$localize`Hello {${count}, plural, =1 {reader} other {readers}}`

Is this possible with $localize? If yes: How? If no: How does Angular compile such expressions from HTML to TypeScript?

Barbey answered 9/3, 2020 at 8:54 Comment(5)
does this help you <span i18n>Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago}}</span> ? Thats in the docs. Pretty similar to what you wantDisorder
@DavePastor: Yes, I tried that. I changed that in the question now. Nevertheless it is pseudo-code, just to illustrate what I want to achieve.Barbey
@DavePastor: (concerning the second comment): No, this does not help. This is HTML, not TypeScript.Barbey
Ok so you want to handle this on the TS side. Got it.Disorder
Check this blog.ninja-squad.com/2019/12/10/angular-localizeDisorder
L
9

For now, it is not possible to use ICUs with $localize, as discussed in this github issue. From the last comments, it looks like angular team is considering it if it remains lightweight.

Meanwhile, the suggested workaround is to create your own helper method that returns the correct translation based on the count parameter.

    title = $localize `Hi ${this.name}! You have ${
        plural(this.users.length. {
          0: $localize `no users`,
          1: $localize `one user`,
          other: $localize`${this.users.length} users`,
    }.`

    function plural(value, options) {
      // Handle 0, 1, ... cases
      const directResult = options[value];
      if (directResult !== undefined) { return directResult; }
      // handle zero, one, two, few, many
      // ...
      return options.other;
    } 
Loris answered 12/3, 2020 at 11:26 Comment(0)
B
4

I've just read issue https://github.com/angular/angular/issues/35912 and I think that intl-messageformat can do what you need.

See https://github.com/formatjs/formatjs/tree/master/packages/intl-messageformat.

Biafra answered 12/3, 2020 at 21:59 Comment(0)
S
3

For anyone interested in 2023, you don't have to use a separate library to achieve this feature. I've found a workaround using the i18nPluralPipe.

First of all follow the instructions in this answer, to get the i18nPluralPipe working in your module.

In your desired component use Angular DI and inject the following:

...
constructor(
    private i18nPluralPipe: I18nPluralPipe,
    @Inject(LOCALE_ID) private _locale: string) {}
...

when you want to translate a message:

...
    const plural = this.i18nPluralPipe.transform(
      numericVariable,
      {
        '=0': $localize`No results found.`,
        '=1': $localize`One result found.`,
        'other': $localize`${numericVariable} results found.`
      },
      this._locale
    );

   // do what you want with this pluralized variable
   console.log(plural);
...

Don't forget to generate the translations using ng extract-i18n!

Sauter answered 28/12, 2023 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.