33 Übersetzungen / Internationalization in Angular

Angular bietet mit seinem Internationalisierungsframework (i18n) umfassende Werkzeuge für die Entwicklung mehrsprachiger Anwendungen. Dieses Kapitel führt Sie durch die wichtigsten Konzepte und Implementierungen von Übersetzungen in Angular.

33.1 Grundlagen der Internationalisierung

Internationalisierung (i18n) bezeichnet den Prozess, eine Anwendung so zu gestalten, dass sie an verschiedene Sprachen und Regionen angepasst werden kann, ohne den Quellcode zu ändern. Lokalisierung (l10n) ist dagegen der Prozess der tatsächlichen Anpassung an eine bestimmte Sprache oder Region.

In Angular umfasst dies: - Übersetzung von Texten - Formatierung von Datum, Zahlen und Währungen - Anpassung von Richtlinien für rechts-nach-links Sprachen - Berücksichtigung kultureller Besonderheiten

33.2 Angular i18n Konzepte

Angular bietet zwei Hauptansätze für die Internationalisierung:

  1. Kompilierungszeitbasierte Übersetzungen (klassisches i18n)
  2. Laufzeitbasierte Übersetzungen (ngx-translate, @angular/localize, Transloco)

33.2.1 Kompilierungszeitbasierte Übersetzungen

Dieser Ansatz erstellt separate Builds für jede Sprache. Die Vorteile sind: - Bessere Performance, da keine Übersetzungen zur Laufzeit geladen werden müssen - Vollständige AOT-Kompatibilität (Ahead-of-Time Kompilierung)

Der Nachteil ist, dass für jede unterstützte Sprache ein separater Build erforderlich ist.

33.2.2 Laufzeitbasierte Übersetzungen

Bei diesem Ansatz werden Übersetzungen zur Laufzeit geladen. Die Vorteile sind: - Ein einzelner Build unterstützt mehrere Sprachen - Sprachänderungen können ohne Neuladen der Anwendung durchgeführt werden

Der Nachteil ist eine möglicherweise leicht verringerte Performance.

33.3 Einrichtung der Internationalisierung in Angular

33.3.1 Installation der erforderlichen Pakete

Ab Angular 9 wurde das i18n-Framework in separate Pakete ausgelagert. Für ein neues Projekt:

ng add @angular/localize

Dies fügt die notwendigen Abhängigkeiten zur package.json hinzu und aktualisiert die Konfiguration.

33.3.2 Texte für Übersetzung markieren

33.3.2.1 Textinhalte in Templates

<h1 i18n="@@welcomeHeader">Willkommen zu unserer Anwendung</h1>

Die i18n-Attribute bieten verschiedene Möglichkeiten: - i18n - Markiert den Text zur Übersetzung - i18n="bedeutung|beschreibung@@id" - Mit zusätzlichen Metadaten: - bedeutung - Kontext der Übersetzung - beschreibung - Hinweise für Übersetzer - id - Eindeutige ID für die Übersetzung

33.3.2.2 Attribute in Templates

Für Attribute wie title oder placeholder:

<input placeholder="Name eingeben" i18n-placeholder="@@namePlaceholder">

33.3.2.3 Übersetzungen in TypeScript-Code

Für Übersetzungen im TypeScript-Code verwenden Sie $localize:

import { Component } from '@angular/core';
import { $localize } from '@angular/localize/init';

@Component({
  selector: 'app-root',
  template: `<h1>{{ title }}</h1>`
})
export class AppComponent {
  title = $localize`Willkommen zu unserer Anwendung`;
}

33.3.3 Extrahieren der Übersetzungen

Um die zu übersetzenden Texte zu extrahieren:

ng extract-i18n --output-path src/locale

Dies erzeugt eine messages.xlf-Datei im angegebenen Verzeichnis. Diese Datei folgt dem XLIFF-Format (XML Localization Interchange File Format).

33.3.4 Übersetzungsdateien erstellen

Kopieren Sie die generierte messages.xlf für jede Sprache und benennen Sie sie entsprechend:

Passen Sie dann die Übersetzungen in jeder Datei an. Ein Beispiel für eine messages.de.xlf:

<trans-unit id="welcomeHeader" datatype="html">
  <source>Welcome to our application</source>
  <target>Willkommen zu unserer Anwendung</target>
  <context-group purpose="location">
    <context context-type="sourcefile">src/app/app.component.html</context>
    <context context-type="linenumber">2</context>
  </context-group>
</trans-unit>

33.3.5 Konfiguration für mehrere Sprachen

In der angular.json konfigurieren Sie die verschiedenen Sprachen:

{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "configurations": {
            "production": { ... },
            "de": {
              "localize": ["de"],
              "baseHref": "/de/"
            },
            "en": {
              "localize": ["en"],
              "baseHref": "/en/"
            }
          }
        },
        "serve": {
          "configurations": {
            "production": { ... },
            "de": {
              "browserTarget": "my-app:build:de"
            },
            "en": {
              "browserTarget": "my-app:build:en"
            }
          }
        }
      }
    }
  }
}

33.3.6 Builds erstellen

Für jede Sprache erstellen Sie einen separaten Build:

ng build --configuration=de
ng build --configuration=en

33.4 Moderne Ansätze ab Angular 17/18

Mit neueren Angular-Versionen (17-18) wurden die Möglichkeiten zur Internationalisierung erweitert und vereinfacht.

33.4.1 Verbesserungen in @angular/localize

Das @angular/localize-Paket wurde stark verbessert und bietet nun:

  1. Bessere Integration mit Ivy: Der neue Renderer unterstützt Übersetzungen effizienter.

  2. Vereinfachte API: Die API wurde konsistenter gestaltet.

  3. Formatierungs-APIs: Datums-, Zahlen- und Währungsformatierung gemäß Lokalisierungsstandards.

33.4.2 Laufzeit-Übersetzungen mit Transloco

Transloco ist eine moderne Alternative, die in neueren Angular-Versionen gut funktioniert:

ng add @ngneat/transloco

Mit Transloco können Sie Übersetzungen dynamisch laden:

// app.module.ts
import { HttpClientModule } from '@angular/common/http';
import { TranslocoModule, TRANSLOCO_CONFIG, TranslocoConfig } from '@ngneat/transloco';
import { translocoLoader } from './transloco.loader';

@NgModule({
  imports: [
    HttpClientModule,
    TranslocoModule
  ],
  providers: [
    {
      provide: TRANSLOCO_CONFIG,
      useValue: {
        availableLangs: ['en', 'de'],
        defaultLang: 'de',
        reRenderOnLangChange: true,
        prodMode: environment.production
      } as TranslocoConfig
    },
    translocoLoader
  ]
})
export class AppModule {}

Verwendung in Templates:

<h1>{{ 'welcomeHeader' | transloco }}</h1>

Oder in TypeScript:

import { TranslocoService } from '@ngneat/transloco';

export class AppComponent {
  constructor(private translocoService: TranslocoService) {}
  
  changeLanguage(lang: string) {
    this.translocoService.setActiveLang(lang);
  }
  
  getTranslatedText() {
    return this.translocoService.translate('welcomeHeader');
  }
}

33.4.3 Verbesserte Lokalisierung in neueren Angular-Versionen

In aktuellen Angular-Versionen wurde die Lokalisierungsunterstützung weiter verbessert:

  1. Vereinfachte Konfiguration: Die Konfiguration in der angular.json wurde übersichtlicher gestaltet.

  2. Verbesserte Laufzeitunterstützung: Bessere Integration für dynamisches Laden von Übersetzungen.

  3. Erweiterter $localize-Support: Erweiterte Formatierungsoptionen und bessere Typunterstützung.

  4. Standalone-Komponenten-Unterstützung: Bessere Integration mit dem Standalone-API-Ansatz.

Beispiel für eine moderne Konfiguration in aktuellen Angular-Versionen:

{
  "projects": {
    "my-app": {
      "i18n": {
        "sourceLocale": "en",
        "locales": {
          "de": {
            "translation": "src/locale/messages.de.xlf",
            "baseHref": "/de/"
          },
          "fr": {
            "translation": "src/locale/messages.fr.xlf",
            "baseHref": "/fr/"
          }
        }
      }
    }
  }
}

33.5 Fortgeschrittene Konzepte

33.5.1 Pluralisierung

Für Texte, die je nach Anzahl variieren:

<span i18n>
  {itemCount, plural,
    =0 {Keine Elemente}
    =1 {Ein Element}
    other {# Elemente}
  }
</span>

33.5.2 Geschlecht-abhängige Übersetzungen

Für geschlechtsspezifische Texte:

<span i18n>
  {gender, select,
    male {Er hat}
    female {Sie hat}
    other {Die Person hat}
  } das Dokument geteilt.
</span>

33.5.3 Verschachtelte Expressions

Komplexe Kombinationen sind möglich:

<span i18n>
  {gender, select,
    male {Er hat}
    female {Sie hat}
    other {Die Person hat}
  } {itemCount, plural,
    =0 {keine Elemente}
    =1 {ein Element}
    other {# Elemente}
  } geteilt.
</span>

33.5.4 Richtlinien für RTL-Sprachen (Right-to-Left)

Für Sprachen wie Arabisch oder Hebräisch:

<html dir="rtl" lang="ar">

Zusammen mit entsprechenden CSS-Anpassungen:

/* Für RTL-Sprachen */
[dir='rtl'] .some-element {
  margin-right: 0;
  margin-left: 10px;
}

33.6 Bewährte Praktiken

  1. Verwenden Sie Schlüssel statt direkter Texte: Dies erleichtert die Wartung.

  2. Dokumentieren Sie den Kontext: Geben Sie den Übersetzern Hinweise zum Kontext.

  3. Vermeiden Sie Verkettungen: Vollständige Sätze sind besser als zusammengesetzte Teile.

  4. Testen Sie mit Pseudoübersetzungen: So finden Sie nicht extrahierte Texte.

  5. Beachten Sie kulturelle Unterschiede: Farben, Symbole und Bilder können unterschiedliche Bedeutungen haben.

  6. Performance-Optimierung: Bei Runtime-Übersetzungen nur die benötigten Sprachdateien laden.

  7. Verwenden Sie sprachspezifische Routing-Strategien: Dies verbessert die SEO.

33.7 Integration mit SSR (Server-Side Rendering)

Angular Universal unterstützt Internationalisierung in SSR-Anwendungen:

// server.ts
import { ngExpressEngine } from '@nguniversal/express-engine';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';

app.engine('html', (_, options, callback) => {
  const engine = ngExpressEngine({
    bootstrap: AppServerModule,
    providers: [
      { provide: REQUEST, useValue: options.req },
      { provide: RESPONSE, useValue: options.res }
    ]
  });
  
  engine(_, options, callback);
});

// Spracherkennung basierend auf URL
app.get(/^\/(de|en|fr)\//, (req, res, next) => {
  const lang = req.path.split('/')[1];
  req.language = lang;
  next();
});

Im AppServerModule können Sie dann die erkannte Sprache verwenden.