Angular-i18n Work-Around für Übersetzungen in Code?




angular5 (2)

Diese Polyfüllung scheint derzeit der beste Weg zu sein:

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

Sie können damit alles, was Sie übersetzen möchten, in eine i18n() Funktion i18n() diese API wird wahrscheinlich in einer zukünftigen Version von Angular beibehalten - siehe meine Notizen am Ende dieser Antwort).

Die Polyfüllung wird hauptsächlich von Olivier Combe geschrieben, einem Mitglied des Angular-Teams, das für i18n verantwortlich ist:

Für Angular 5 benötigen Sie Version 0.2.0, wenn Sie Folgendes installieren:

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

Holen Sie sich für Angular 6 die neueste Version - derzeit 1.0.0:

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

Ich habe die Polyfill sowohl für die JIT- als auch für die AOT-Kompilierung für Angular 5 zum Laufen gebracht (sie funktioniert auch für Angular 6). Hier ist, was Sie tun müssen, um in eine einzelne Sprache zu übersetzen (dies ist ein guter Weg, um dies zum Laufen zu bringen - Sie können später mehrere Sprachen zum Laufen bringen, was ich weiter unten erläutere):

app.module.ts

Fügen Sie Ihrem Stamm-Winkelmodul die folgenden Importe hinzu:

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

Fügen Sie die folgende Konstante hinzu und geben Sie die Anbieter in Ihrem Stammmodul an:

// 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'},
    ...

Hinweis zur Verwendung der AOT-Kompilierung : Wenn Sie zur Übersetzung Ihrer Vorlagen die AOT-Kompilierung verwenden, wird die Übersetzung der Nachrichten in .ts-Dateien zur Laufzeit weiterhin mithilfe der JIT-Kompilierung durchgeführt (daher müssen Sie auf TRANSLATIONS und TRANSLATIONS_FORMAT verweisen, anstatt diese nur anzugeben in Ihren Build-Skripten).

* .ts

Fügen Sie in der .ts-Datei, in der Sie eine Übersetzung bereitstellen möchten, Folgendes hinzu:

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

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

Dies zeigt, dass Sie sogar Interpolationen in die Nachrichten einfügen können, die Sie übersetzen möchten.

Sie können i18n-Definitionen verwenden (dh indem Sie die 'Quell'-ID, die Bedeutung und die Beschreibung der Übersetzung angeben):

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

Sie müssen die Nachrichten noch extrahieren, und Sie können das ngx-extractor-Tool verwenden, um dies zu tun. Dies ist enthalten, wenn Sie die Polyfill installieren, und ich habe unten ein Beispiel zu ihrer Verwendung in einem npm-Skript hinzugefügt. Siehe auch die Readme-Datei auf der Polyfill-Seite .

Mehrere Sprachen

Um das Umschalten zwischen mehreren Sprachen zu unterstützen, benötigen Sie einen Anbieter, der Ihre Übersetzungen bereitstellt. Details finden Sie in der Readme- https://github.com/ngx-translate/i18n-polyfill der https://github.com/ngx-translate/i18n-polyfill . Sie benötigen so etwas in Ihrem Root-Modul (oder ersetzen Sie für die AOT-Kompilierung den Rückgabewert für localeFactory durch eine Funktion, die erkennt, welche AOT-kompilierte Sprachvariante Ihrer App derzeit ausgeführt wird):

  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
    },

Nachrichtenextraktion und xliffmerge

All dies ist kompatibel mit xliffmerge , einem großartigen Tool zum automatischen Zusammenführen aller neu hinzugefügten Übersetzungen, ohne vorhandene Übersetzungen zu überschreiben. Xliffmerge kann auch automatisch Übersetzungen mit Google Übersetzer ausführen (Sie benötigen einen Google Übersetzer-API-Schlüssel). Damit dies funktioniert, führe ich das Extrahieren und Zusammenführen / Übersetzen in der folgenden Reihenfolge durch, bevor ich den eigentlichen AOT-Build durchführe:

"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"

Der AOT-Build für eine bestimmte Sprachversion der Site sieht folgendermaßen aus:

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

Aktueller Status dieser Polyfill:

Dies wird hauptsächlich von Olivier Combe geschrieben, einem Mitglied des Angular-Teams, das für i18n verantwortlich ist. In diesem Stadium handelt es sich um eine spekulative Polyfüllung zum Übersetzen von Variablen oder Zeichenfolgen in der .ts-Datei. Es wird wahrscheinlich durch eine in Angular integrierte API ersetzt, die sehr ähnlich ist. Ein späteres Upgrade sollte daher einigermaßen verwaltbar sein. Hier ist der Haftungsausschluss von der Github-Seite:

Diese Bibliothek ist eine spekulative Polyfill. Sie soll eine API ersetzen, die in Zukunft verfügbar sein wird. Wenn sich die API unterscheidet, wird ein Migrationstool bereitgestellt, sofern dies möglich und erforderlich ist.

In den kommenden Nebenversionen von Angular 6 wurde die Unterstützung für die Übersetzung von Variablen / Zeichenfolgen im Code diskutiert.

Hier ist ein Zitat von Olivier Combe (vom März dieses Jahres) aus der folgenden Diskussion über Github:

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

Der erste PR für Runtime i18n wurde in Master zusammen mit einer Hallo-Welt-Demo-App zusammengeführt, mit der wir die Funktionen testen werden. Es funktioniert zur Laufzeit und unterstützt theoretisch Code-Übersetzungen, auch wenn es noch keinen Service dafür gibt. Im Moment ist die Unterstützung sehr gering (statische Zeichenfolgen). Wir arbeiten daran, neue Funktionen hinzuzufügen (die Extrahierung wird nächste Woche ausgeführt, und anschließend werden dynamische Zeichenfolgen mit Platzhaltern und Variablen verwendet). Danach erledigen wir den Service für Codeübersetzungen. Sobald ein neues Feature fertig ist, wird es in Master eingebunden und Sie müssen nicht auf einen neuen Major warten.

Wir müssen bis Angular 6 warten, bis Angular-i18n Übersetzungen im Code für Fehlermeldungen und dergleichen unterstützt.

Was tun Sie in der Zwischenzeit für diejenigen, die angle-i18n verwenden (anstelle von ngx-translate zum Beispiel), um Übersetzungen im Code zu verarbeiten? Mir fällt ein, dass wenn es nicht viele Zeichenfolgen gibt, ein einfacher Sprachdienst mit Methoden zum Abrufen von Übersetzungen per Sprachcode und einer ID funktionieren würde, aber ich interessiere mich für etwas Eleganteres und "eckigeres".

Ich weiß nicht, wie die versprochene Unterstützung für Codeübersetzungen aussehen wird, aber jede vorübergehende Lösung lässt sich idealerweise einfach in die Angular-i18n-Methode umwandeln, wenn sie live geht.

Was tun die Leute da draußen, um dieses Problem zu lösen? Irgendwelche Ideen?


Ich habe eine "bizarre" Abhilfe Wir können zwei Komponenten haben

app-text.component.ts

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

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

und 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 : "";
  }
}

Dann können wir in einer Komponente einige wie haben

  <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