angular-i18n pour contourner les traductions en code?




angular5 (2)

Ce polyfill semble être la meilleure voie à suivre pour le moment:

https://github.com/ngx-translate/i18n-polyfill

Il vous permet d’envelopper tout ce que vous voulez traduire dans une fonction i18n() (cette API sera probablement préservée dans une prochaine version d’Angular - voir mes notes au bas de cette réponse).

Le polyfill est principalement écrit par Olivier Combe, membre de l'équipe Angular responsable de i18n:

Pour Angular 5, vous aurez besoin de la version 0.2.0 pour installer:

npm install @ngx-translate/[email protected] --save

Pour Angular 6, procurez-vous la dernière version - actuellement 1.0.0:

npm install @ngx-translate/[email protected] --save

Le polyfill fonctionne pour les compilations JIT et AOT , pour Angular 5 (cela fonctionnera également pour Angular 6). Voici ce que vous devez faire pour traduire dans une seule langue (c’est un bon moyen de faire en sorte que cela fonctionne. Vous pouvez alors utiliser plusieurs langues plus tard, ce que j’explique plus loin):

app.module.ts

Ajoutez les importations suivantes à votre module angulaire racine:

import { TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core';
import { I18n } from '@ngx-translate/i18n-polyfill';

ajoutez la constante suivante et spécifiez les fournisseurs dans votre module racine:

// add this after import + export statements
// you need to specify the location for your translations file
// this is the translations file that will be used for translations in .ts files

const translations = require(`raw-loader!../locale/messages.fr.xlf`);

@NgModule({ ....

  providers:
  [
    I18n,
    {provide: TRANSLATIONS, useValue: translations},
    {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
    ...

Remarque sur l'utilisation de la compilation AOT : si vous utilisez la compilation AOT pour traduire vos modèles, la traduction des messages dans les fichiers .ts sera toujours effectuée au moment de l'exécution à l'aide de la compilation JIT (vous devez donc référencer TRANSLATIONS et TRANSLATIONS_FORMAT au lieu de les spécifier). dans vos scripts de construction).

* .ts

Dans le fichier .ts où vous souhaitez fournir une traduction, ajoutez ceci:

import { I18n } from '@ngx-translate/i18n-polyfill';

constructor(private i18n: I18n) {
    console.log(i18n("This is a test {{myVar}} !", {myVar: "^_^"}));
}

Cela montre que vous pouvez même inclure des interpolations dans les messages que vous souhaitez traduire.

Vous pouvez utiliser les définitions i18n (c.-à-d. Spécifier la traduction 'id' source, signification, description) comme suit:

this.i18n({value: 'Some message', id: 'Some message id', meaning: 'Meaning of some message', description: 'Description of some message'})

Vous aurez toujours besoin d'extraire les messages, et vous pouvez utiliser l'outil ngx-extractor pour le faire. Ceci est inclus lorsque vous installez polyfill, et j'ai ajouté un exemple ci-dessous sur son utilisation dans un script npm. Voir aussi le readme sur la page polyfill .

Plusieurs langues

Pour pouvoir basculer entre plusieurs langues, vous aurez besoin d'un fournisseur d'usine pour vos traductions. Il y a des détails dans le readme de la https://github.com/ngx-translate/i18n-polyfill . Vous aurez besoin de quelque chose comme ceci dans votre module racine (ou pour la compilation AOT, remplacez la valeur de retour pour localeFactory par une fonction qui détecte la variante de langage compilé AOT de votre application en cours d'exécution):

  export function localeFactory(): string {
    return (window.clientInformation && window.clientInformation.language) || window.navigator.language;
  }

  providers:
  [
    {
      provide: TRANSLATIONS,
      useFactory: (locale) => {
        locale = locale || 'en'; // default to english if no locale provided
        return require(`raw-loader!../locale/messages.${locale}.xlf`);
      },
      deps: [LOCALE_ID]
    },
    {
      provide: LOCALE_ID,
      useFactory: localeFactory
    },

Extraction de message et xliffmerge

Tout cela est compatible avec xliffmerge , qui est un excellent outil pour fusionner automatiquement toutes les nouvelles traductions que vous ajoutez, sans écraser les traductions existantes. Xliffmerge peut également effectuer automatiquement des traductions à l'aide de Google Translate (vous aurez besoin d'une clé API Google Translate). Pour que cela fonctionne, je fais l'extraction et la fusion / traduction dans l'ordre suivant, avant de faire la construction AOT proprement dite:

"extract-i18n-template-messages": "ng xi18n --outputPath=src/locale --i18n-format=xlf",
"extract-i18n-ts-messages": "ngx-extractor --input=\"src/**/*.ts\" --format=xlf --out-file=src/locale/messages.xlf",
"generate-new-translations": "xliffmerge --profile xliffmerge.json en fr es de zh"

La version AOT d'une version linguistique spécifique du site se présente comme suit:

"build:fr": "ng build --aot --output-path=dist/fr --base-href /fr/ --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr",

Statut actuel de ce polyfill:

Ceci est principalement écrit par Olivier Combe, un membre de l'équipe Angular responsable de i18n. À ce stade, il s’agit d’un polyfill «spéculatif» pour la traduction de variables ou de chaînes dans le fichier .ts. Elle sera probablement remplacée par une API intégrée à Angular qui sera très similaire. Une mise à niveau ultérieure devrait donc être raisonnablement gérable. Voici le diclaimer de la page Github:

Cette bibliothèque est un polyfill spéculatif, cela signifie qu’elle est supposée remplacer une API à venir. Si l'API est différente, un outil de migration sera fourni si cela est possible et nécessaire.

Il y a eu des discussions sur le support dans les prochaines versions mineures de Angular 6 pour la traduction de variables / chaînes en code.

Voici une citation d'Olivier Combe (de mars de cette année), issue de la discussion suivante sur Github:

https://github.com/angular/angular/issues/11405

Le premier PR pour le runtime i18n a été fusionné avec master, avec une application de démonstration hello world que nous utiliserons pour tester les fonctionnalités. Il fonctionne à l'exécution et supporte théoriquement les traductions de code, même s'il n'y a pas encore de service pour cela. Pour l'instant, le support est très minime (chaînes statiques), nous travaillons à l'ajout de nouvelles fonctionnalités (l'extraction fonctionnera la semaine prochaine, puis la chaîne dynamique avec des espaces réservés et des variables). Après cela, nous ferons le service pour les traductions de code. Dès qu'une nouvelle fonctionnalité est finie, elle est fusionnée dans la version principale, vous n'aurez pas à attendre une nouvelle majeure.

Nous devons attendre Angular 6 pour que angular-i18n prenne en charge les traductions dans le code pour les messages d'erreur et autres.

Pour ceux qui utilisent angular-i18n (au lieu de ngx-translate par exemple), que faites-vous entre-temps pour gérer les traductions en code? Il me semble que s’il n’ya pas beaucoup de chaînes, un simple service linguistique avec des méthodes pour obtenir des traductions par code de langue et un identifiant fonctionnerait, mais je suis intéressé par quelque chose de plus élégant et "angulaire".

Je ne sais pas à quoi ressemblera le support de traduction de code promis, mais toute solution temporaire serait idéalement facilement convertie de la manière angulaire-i18n lorsqu’elle sera mise en production.

Que font les gens pour gérer ce problème? Des idées?


J'ai un contournement "bizarro" On peut avoir deux composants

app-text.component.ts

import { Component} from '@angular/core';

@Component({
  selector: 'text',
  template:`<ng-content></ng-content>`
})
export class AppTextComponent{}

et app-translation.component.ts

import { Component, QueryList, ElementRef, ContentChildren } from '@angular/core';
import { AppTextComponent } from './app-text.component';

@Component({
  selector: 'app-translation',
  template: `<ng-content></ng-content>`
})
export class AppTranslationComponent{
  @ContentChildren(AppTextComponent, { read: ElementRef }) divs: QueryList<ElementRef>;
  constructor() { }

  translate(id: string): string {
    let nativeElement: any = this.divs.find(e => e.nativeElement.id == id);
    return nativeElement ? nativeElement.nativeElement.innerText : "";
  }
}

Ensuite, dans un composant on peut en avoir comme

  <app-translation #translations style="visibility:collapsed">
    <text id="message1">Translation app</text>
    <text id="message2">Hola Mundo</text>
  </app-translation>

//In your code you can use a ViewChild and the function "traslate"
  @ViewChild('translations') t;

  alert(this.t.translate("message1"));




angular-i18n