Outils pour utilisateurs

Outils du site


lang:angular:traduction

Ceci est une ancienne révision du document !


@angular/localize

Présentation

Le système de traduction natif intégré à Angular.

Avantages :

  • Pas de dépendances externes,
  • Le texte est traduit en dur dans le code généré, pas de pipe,
  • On compile une fois mais on génère un site par langue.

Inconvénient :

Initialisation

Installation

npm i --save @angular/localize

Configuration

Il faut activer les options localize et aot. Voir la i18n d'Angular.

Dans le code source, on met une langue par défaut (anglais par exemple) et la traduction dans le fichier .xlf.

Ajouter l'action extract-i18n dans la librairie qu'on souhaite traduire. ng xi18n not working for library Archive du 03/03/2020 le 23/08/2021

angular.json
{
  "projects": {
    "lib-library": {
      "architect": {
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "angular-i18n:build"
          }
        }
      }
    },
    "app-main": {
      "i18n": {
        "sourceLocale": "en-US",
        "locales": {
          "fr": "projects/app-main/src/locale/messages.fr.xlf"
        }
      },
      "architect": {
        "build": {
          "options": {
            "localize": true,
            "aot": true
          }
        }
      }
    }
  }
}

Sources

  • Librairie

Il faut ajouter au fichier test.ts:

test.ts
/******************************************************************************
 * Load `$localize` onto the global scope - used if i18n tags appear in Angular
 * templates.
 */
import '@angular/localize/init';
  • Application

Il faut ajouter la même chose au fichier polyfills.ts:

polyfills.ts
/******************************************************************************
 * Load `$localize` onto the global scope - used if i18n tags appear in Angular
 * templates.
 */
import '@angular/localize/init';

Traduction

  • .html

Il suffit d'ajouter un attribut i18n. Il est possible d'ajouter des catégories aux textes descriptifs.

<label for="width" i18n="input form|Foundation strip width">Width: </label>
  • Extraction des données
ng extract-i18n --output-path ./projects/app-main/src/locale

S'il y a une librairie et une application, la traduction fusionne les textes de la librairie et de l'application.

  • Traduire la langue

Copier le fichier généré dans ./projects/app-main/src/locale/messages.xlf.

En dessous de chaque <source>…</source>, ajouter la traduction <target>…</target>.

<source>Width: </source>
<target>Largeur : </target>

La traduction peut aussi gérer le binding :

<pre i18n="output form|Output of Meyerhof calculation">
Form Values: {{ result | json }}</pre>
<source>Form Values: <x id="INTERPOLATION"/></source>
<target>Résultats : <x id="INTERPOLATION"/></target>

@ngx-translate/core

Présentation

L'inverse de @angular/localize. C'est donc une dépendance externe à Angular.

Avantages :

Inconvénient :

  • Comme c'est une dépendance externe, on ne profite pas d'une intégration profonde des avantages du compilateur,
  • Dépendance externe,
  • Le texte est traduit à la volée. Avant la conversion, le texte est manquant. Cela peut donc réduire l'expérience utilisateur,
  • Nécessite de définir l'utilisation d'un pipe pour chaque composant.

Initialisation

Installation

npm i --save @ngx-translate/core

Configuration

Il n'y a besoin de rien.

Sources

Exemple bien détaillé avec une librairie et une application: Translate Angular >=4 with ngx-translate and multiple modules Archive du 09/08/2017 le 24/08/2021

  • Librairie

Il faut exporter le module de traduction. @ngx-translate/core - SharedModule Archive du 28/05/2021 le 24/08/2021

lib-jessica/src/lib/lib-jessica.module.ts
import { TranslateModule } from '@ngx-translate/core';
 
@NgModule({
  imports: [..., TranslateModule],
  exports: [
    ...,
    TranslateModule
  ]
})
  • Application
app-main/src/app/app.component.spec.ts
import { TranslateService } from '@ngx-translate/core';
 
export class AppComponent {
  ...
 
  constructor(public translate: TranslateService) {
    translate.addLangs(['en', 'fr']);
    translate.setDefaultLang('en');
  }
}
app-main/src/app/util/translate/multi-translate-http-loader.ts
import { HttpClient } from '@angular/common/http';
import { TranslateLoader } from '@ngx-translate/core';
import { forkJoin, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
 
export class MultiTranslateHttpLoader implements TranslateLoader {
  constructor(
    private http: HttpClient,
    public resources: { prefix: string; suffix: string }[] = [
      {
        prefix: './assets/i18n/',
        suffix: '.json'
      }
    ]
  ) {}
 
  public getTranslation(lang: string): Observable<unknown> {
    return forkJoin(
      this.resources.map((config) => {
        return this.http.get(`${config.prefix}${lang}${config.suffix}`);
      })
    ).pipe(
      map((response) => {
        return response.reduce((a, b) => {
          return Object.assign(a, b);
        });
      })
    );
  }
}
app-main/src/app/app.module.ts
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
 
import { MultiTranslateHttpLoader } from './util/translate/multi-translate-http-loader';
 
export function createTranslateLoader(http: HttpClient): TranslateLoader {
  return new MultiTranslateHttpLoader(http, [
    { prefix: './assets/i18n/', suffix: '.json' },
    { prefix: './assets/i18n/library-', suffix: '.json' }
  ]);
}
 
@NgModule({
  ...,
  imports: [
    ...,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: createTranslateLoader,
        deps: [HttpClient]
      },
      defaultLanguage: 'en'
    })
  ],
  ...
})
...

Traduction

  • HTML
{{ 'HOME.TITLE' | translate }}
  • Traduction
app-main/src/assets/i18n/en.json
{
  "HOME": {
    "TITLE": "Calculator for Meherhof foundation!"
  }
}

Tests

ngx-translate how to test components Archive du 09/11/2019 le 24/08/2021

How to fix ngx-translate error when running tests Archive du 02/10/2019 le 24/08/2021

Pour les tests unitaires (pas end-to-end), il n'est généralement pas nécessaire de charger la librairie. Avantage : gain de temps. Inconvénient, l'aspect graphique ne sera pas conforme.

Dans le composant principal de l'application :

app-main/src/app/app.component.spec.ts
import {
  TranslateFakeLoader,
  TranslateLoader,
  TranslateModule
} from '@ngx-translate/core';
 
describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        ...,
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useClass: TranslateFakeLoader
          }
        })
      ],
      ...

Dans chaque composant de l'application, on utilise le pipe de traduction de la librairie :

app-main/src/app/ui/main/main.component.spec.ts
import { TranslateMockPipe } from 'lib-library';
 
describe('MainComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        ...,
        TranslateMockPipe
      ]
    }).compileComponents();
  });

Dans chaque composant de la librairie, on utilise le même pipe de traduction :

lib-jessica/src/lib/xxx.component.spec.ts
import { TranslateMockPipe } from '../../../util/translation/translate-mock.pipe';
 
describe('FoundationStripFormComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      ...,
      declarations: [..., TranslateMockPipe]
    }).compileComponents();
  });
lib-library/src/lib/translate-mock.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
 
@Pipe({
  name: 'translate'
})
export class TranslateMockPipe implements PipeTransform {
  public name = 'translate';
 
  public transform(query: string): string {
    return query;
  }
}
projects/lib-jessica/src/public-api.ts
export * from './lib/util/translation/translate-mock.pipe';
lang/angular/traduction.1633158755.txt.gz · Dernière modification : 2021/10/02 09:12 de root