angularinternationalizationangular-i18n

Angular i18n for text containing routerLink and requires different word order


I am struggling to find the most efficient way to translate the text containing routerLink or text where some words should be wrapped in html tags ( word ).

Let's see how it looks without the i18n implementation:

example.component.html

<div>
 Hello and welcome to this test example. In order to proceed click on this 
 <a [routerLink]="['settings/subscription']">Link</a>
</div>

Now let's add i18n to it, and use one possible approach to deal with the routerLink: en.json

{
  "WELCOME_LABEL": "Hello and welcome to this test example. In order to proceed click on this,
  "LINK_LABEL": "link"
}

example.component.html

<div>
 {{'WELCOME_LABEL' | translate}} 
 <a [routerLink]="['settings/subscription']">{{'LINK_LABEL' | translate}}</a>
</div>

The problem with this approach is that different languages could have words in a different order. For example. "Please click on this link" in some other language could have the order where "link" is at the begining or in the middle of a sentence.

Is there some general / official approach to deal with this situation?

The one way how I could solve it is to get the current locale in the component and then do the if check in the template based on it.

I don't like this way because I'm kind of stepping out of i18n practice, and creating separate JSON objects based on locale just to be able to fit the word ordering needs.

example.component.ts

constructor(
    @Inject( LOCALE_ID ) protected localeId: string
) {
    console.log(this.localeId);
}

example.component.html

<div *ngIf="localeId === 'en-Us'">
 {{'WELCOME_LABEL_EN' | translate}} 
 <a [routerLink]="['settings/subscription']">{{'LINK_LABEL_EN' | translate}}</a>
</div>
<div *ngIf="localeId === 'otherLanguage'">
 {{'WELCOME_LABEL_1_OTHER' | translate}} 
 <a [routerLink]="['settings/subscription']">{{'LINK_LABEL_OTHER' | translate}}</a>
 {{'WELCOME_LABEL_2_OTHER' | translate}} 
</div>

Solution

  • What if you simply define the <div> in three parts? Like, the text start, the link, then the end.

    <div>
      {{'WELCOME_LABEL_START' | translate}}
      <a [routerLink]="['settings/subscription']">{{'LINK_LABEL' | translate}}</a>
      {{'WELCOME_LABEL_END' | translate}}
    </div>
    

    This way, according to the language, you just have to define the sentence in two parts.

    {
      "WELCOME_LABEL_START": "In order to proceed, click on this",
      "LINK_LABEL": "link",
      "WELCOME_LABEL_END": " whatever language you have."
    }
    

    And you just let the start / end empty if unnecessary.