Internationalisierung (i18n) ist für den Aufbau globaler Angular-Anwendungen unerlässlich. Dieser Leitfaden zeigt Ihnen, wie Sie i18next in Angular mit korrektem Laden von Ressourcen, Initialisierung und Nutzungsmustern implementieren.
i18next ist eines der beliebtesten i18n-Frameworks und bietet leistungsstarke Funktionen sowie Flexibilität:
Installieren Sie i18next mit npm oder yarn:
npm install i18nextDas war's! i18next ist eine eigenständige Bibliothek ohne frameworkspezifische Abhängigkeiten. Sie benötigen kein angular-i18next oder andere Wrapper – verwenden Sie i18next einfach direkt in Ihrer Angular-Anwendung.
Es gibt zwei Hauptansätze zum Laden von Übersetzungsressourcen in Angular mit i18next:
Die Verwendung dynamischer Importe nutzt das Code-Splitting von Webpack, um Übersetzungen bei Bedarf zu laden. Dieser Ansatz ist ideal für Anwendungen mit vielen Sprachen oder großen Übersetzungsdateien.
Vorteile:
Beispiel: Laden mit dynamischen Importen
private async loadLanguageResources(
lang: string,
): Promise<Record<string, Record<string, unknown>>> {
const languageResources: Record<string, Record<string, unknown>> = {};
// Load all namespaces for the given language in parallel
await Promise.all(
NAMESPACES.map(async (namespace) => {
const translationModule = await this.loadJson(lang, namespace);
languageResources[namespace] = translationModule.default;
}),
);
return languageResources;
}
private async loadJson(
language: string,
namespace: string,
): Promise<{ default: Record<string, unknown> }> {
// Webpack automatically code-splits this into separate chunks
return import(`../../i18n/${language}/${namespace}.json`);
}Dieser Ansatz importiert Übersetzungsdateien als ES-Module, wodurch Webpack sie automatisch in separate Chunks aufteilen kann, die bei Bedarf geladen werden.
Das HTTP-Backend-Plugin lädt Übersetzungen über HTTP-Anfragen von einem Server oder CDN. Dies ist nützlich, wenn Sie Übersetzungen aktualisieren möchten, ohne Ihre App neu zu erstellen.
Vorteile:
Nachteile:
Beispiel: Laden mit HTTP-Backend
import HttpBackend from 'i18next-http-backend';
await init({
lng: initialLanguage,
fallbackLng: DEFAULT_LANGUAGE,
backend: {
loadPath: '/assets/i18n/{{lng}}/{{ns}}.json',
},
use: [HttpBackend],
ns: NAMESPACES,
defaultNS: DEFAULT_NAMESPACE,
});Dieser Ansatz ruft Übersetzungsdateien zur Laufzeit von einem Server ab. Beachten Sie, dass dies eine zusätzliche Konfiguration für SSR erfordert.
Die korrekte Initialisierung von i18next ist entscheidend, um Laufzeitfehler zu vermeiden und sicherzustellen, dass Übersetzungen verfügbar sind, wenn Ihre App gerendert wird.
Die Funktion provideAppInitializer von Angular (eingeführt in Angular 18) stellt sicher, dass i18next vollständig initialisiert ist, bevor die Anwendung mit dem Rendern beginnt. Die bereitgestellte Funktion wird während des App-Bootstraps ausgeführt, und die Initialisierung ist erst abgeschlossen, wenn das Promise aufgelöst wurde. Dies verhindert, dass Übersetzungsschlüssel anstelle von übersetztem Text erscheinen.
Beispiel: Konfiguration des App-Initializers
export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
provideAppInitializer(initializeI18n),
// ... more providers
],
};Warum das wichtig ist:
Die Initialisierungsfunktion übernimmt das Laden von Ressourcen und das Konfigurieren der i18next-Einstellungen.
Beispiel: i18next-Initialisierung
public async initializeI18n(): Promise<void> {
const initialLanguage = this.getInitialLanguage();
const resources: Record<string, Record<string, Record<string, unknown>>> = {};
if (isPlatformBrowser(this.platformId)) {
// Browser: Only load the specific language needed
const languageResources = await this.loadLanguageResources(initialLanguage);
resources[initialLanguage] = languageResources;
} else {
// SSR: Load all languages for prerendering
for (const lang of SUPPORTED_LANGUAGES) {
const languageResources = await this.loadLanguageResources(lang);
resources[lang] = languageResources;
}
}
await init({
lng: initialLanguage,
fallbackLng: DEFAULT_LANGUAGE,
resources,
ns: NAMESPACES,
defaultNS: DEFAULT_NAMESPACE,
interpolation: {
escapeValue: false,
},
});
}Wichtige Punkte:
Die Angular Translation Pipe bietet eine saubere Möglichkeit, Übersetzungen in Templates zu verwenden.
Beispiel: Translation Pipe
import { Pipe, PipeTransform } from '@angular/core';
import { t } from 'i18next';
@Pipe({
name: 't',
standalone: true,
pure: false, // Need to update when language changes
})
export class TranslatePipe implements PipeTransform {
transform(key: string, options?: Record<string, unknown>): string {
return t(key, options);
}
}Die Pipe ist als pure: false markiert, um sicherzustellen, dass sie aktualisiert wird, wenn sich die Sprache ändert. Dies ist wichtig, da Sprachänderungen den Übersetzungsschlüssel selbst nicht ändern.
In Templates:
<!-- With namespace -->
<p>{{ "common:welcomeMessage" | t }}</p>
<!-- With nested keys -->
<p>{{ "dashboard.title" | t }}</p>
<!-- Simple interpolation -->
<p>{{ "greeting" | t: { name: userName } }}</p>
<!-- Result: "Hello, John!" from greeting: "Hello, {{name}}!" -->
<!-- With Angular pipes -->
<p>{{ "price" | t: { amount: 29.99 | currency } }}</p>
<!-- Result: "Price: $29.99" from: "Price: {{amount}}" -->
<!-- Multiple variables -->
<p>{{ "updated" | t: { date: lastModified | date, user: currentUser } }}</p>
<!-- Result: "Updated on Jan 15, 2024 by Alice" from: "Updated on {{date}} by {{user}}." -->
Die Interpolation ermöglicht es Ihnen, dynamische Werte in Ihre Übersetzungen einzufügen. Sie können Variablen übergeben, Angular-Pipes zur Formatierung verwenden und mehrere Werte in einem einzigen Übersetzungsstring kombinieren.
Im Komponenten-Code:
import { Component } from '@angular/core';
import { t } from 'i18next';
@Component({
selector: 'app-dashboard',
template: `
<h1>{{ title }}</h1>
<p>{{ welcomeMsg }}</p>
`,
})
export class DashboardComponent {
title = t('dashboard.title');
welcomeMsg = t('greeting', { name: 'John' });
}Für die Verwendung im Template ist die Pipe-Syntax sauber und lesbar. Für den programmgesteuerten Zugriff rufen Sie t() direkt auf. Dies ist nützlich, um Benachrichtigungen anzuzeigen, dynamische Titel zu setzen oder Übersetzungen in der Komponentenlogik zu handhaben.
Verwenden Sie eine Punktnotation, die Ihre App-Struktur widerspiegelt: 'auth:login.title' anstelle von 'loginTitle' oder Rohtext.
Teilen Sie Übersetzungen in logische Namespaces auf (z. B. common.json, auth.json, dashboard.json) für eine bessere Wartbarkeit.
Verwenden Sie die integrierte Pluralisierungsunterstützung von i18next, um Singular-/Pluralformen in allen Sprachen korrekt zu behandeln.
Stellen Sie immer sicher, dass i18next vor dem Rendern Ihrer App initialisiert wird, indem Sie provideAppInitializer() verwenden, um die Initialisierung während des App-Bootstraps auszuführen.
Verwenden Sie TypeScript, um Übersetzungsschlüssel direkt aus Ihren JSON-Dateien für vollständige Typsicherheit zu extrahieren. Anstatt Typdefinitionen manuell zu pflegen, nutzen Sie typeof und dynamische Importe von TypeScript, um automatisch Typen aus Ihren tatsächlichen Übersetzungsdateien zu generieren.
Definieren Sie einen Typ, der alle möglichen Schlüssel aus Ihren JSON-Übersetzungsdateien mithilfe eines rekursiven NestedKeys-Hilfstyps extrahiert.
import common from './en/common.json'; // defaultNS: DEFAULT_NAMESPACE,
import auth from './en/auth.json'; // namespaces
type NestedKeys<T, Prefix extends string = ''> = T extends object
? {
[K in keyof T & (string | number)]: T[K] extends object
?
| NestedKeys<T[K], `${Prefix}${K & (string | number)}.`>
| `${Prefix}${K & (string | number)}`
: `${Prefix}${K & (string | number)}`;
}[keyof T & (string | number)]
: never;
export type TranslationKey =
| `common:${NestedKeys<typeof common>}`
| `auth:${NestedKeys<typeof auth>}`;Ändern Sie die transform-Methode der Pipe, um TranslationKey anstelle von string zu akzeptieren. Dies bietet Typsicherheit in Templates und stellt sicher, dass nur gültige Übersetzungsschlüssel verwendet werden können.
import { Pipe, PipeTransform } from '@angular/core';
import { t } from 'i18next';
import { TranslationKey } from '../../i18n/translation-key';
@Pipe({
name: 't',
standalone: true,
pure: false, // Need to update when language changes
})
export class TranslatePipe implements PipeTransform {
transform(key: TranslationKey, options?: Record<string, unknown>): string {
return t(key, options);
}
}
Jetzt erhalten Sie vollständige IntelliSense-Autovervollständigung und Kompilierzeitfehler für ungültige Schlüssel sowohl im TypeScript-Code als auch in Templates.
t('common:greeting'); // ✅ Autocomplete
t('auth:login.title'); // ✅ Valid
t('invalid.key'); // ❌ IDE shows error
{{ "common:greeting" | t }} // ✅ Valid in templates
{{ "invalid.key" | t }} // ❌ IDE shows errorVorteile von typsicheren Übersetzungsschlüsseln:
Implementieren Sie eine intelligente Spracherkennung und ermöglichen Sie Benutzern den Sprachwechsel zur Laufzeit mit automatischem Laden von Ressourcen.
Bestimmen Sie die Sprache des Benutzers beim Start Ihrer App, indem Sie mehrere Quellen in der Prioritätsreihenfolge prüfen.
private getInitialLanguage(): string {
if (isPlatformBrowser(this.platformId)) {
// Try to get language from localStorage (user preference)
const savedLang = localStorage.getItem('language');
if (savedLang) {
return savedLang;
}
// Fall back to browser language
return navigator.language ?? DEFAULT_LANGUAGE;
}
// Default language for SSR
return DEFAULT_LANGUAGE;
}Dieser Ansatz prüft zuerst localStorage (Benutzereinstellung), greift dann auf die Sprache des Browsers (navigator.language) zurück und verwendet schließlich die Standardsprache der App.
Wechseln Sie die Sprache zur Laufzeit, während Übersetzungsressourcen automatisch bei Bedarf geladen werden.
public async switchLanguage(
language: string
): Promise<void> {
// In browser, check if we need to load the translation first
if (isPlatformBrowser(this.platformId)) {
const i18next = await import('i18next');
await Promise.all(
NAMESPACES.map(async (namespace) => {
const currentResources = i18next.default.getResourceBundle(
lang,
namespace,
);
// Check if any namespace is missing for this language
if (!currentResources) {
// Translation not loaded yet, load it dynamically
const translationModule = await this.loadJson(lang, namespace);
i18next.default.addResourceBundle(
lang,
namespace,
translationModule.default,
);
}
}),
);
}
// Switch to the new language
await changeLanguage(lang);
// Save preference to localStorage
if (isPlatformBrowser(this.platformId)) {
localStorage.setItem('language', lang);
}
}Bei der Verwendung dynamischer Importe werden Übersetzungen bei Bedarf geladen. Die Methode switchLanguage() prüft mit getResourceBundle(), ob Ressourcen bereits geladen sind. Falls sie fehlen, werden sie dynamisch importiert und mit addResourceBundle() hinzugefügt. Dies verhindert redundante Netzwerkanfragen und stellt sicher, dass alle benötigten Übersetzungen verfügbar sind.
Wichtige Implementierungsdetails:
Das manuelle Verwalten von Übersetzungen in mehreren Sprachen ist zeitaufwendig und fehleranfällig. Hier kommt KI-gestützte Lokalisierung ins Spiel.
l10n.dev ist ein KI-gestützter Übersetzungsdienst, der speziell für i18next-JSON-Dateien entwickelt wurde:
Sparen Sie Stunden manueller Übersetzungsarbeit und vermeiden Sie häufige Fehler wie defekte Platzhalter oder falsche Pluralformen.
Bereit, Ihren Angular-i18n-Workflow zu optimieren?
Laden Sie Ihre i18n-Dateien hoch und lassen Sie die KI die Übersetzung mit Kontextbewusstsein und korrekter Formatierung übernehmen
Entdecken Sie, warum KI-gestützte Lokalisierung für i18n-Dateien besser ist als herkömmliche Methoden
Integrieren Sie KI-gestützte Lokalisierung direkt in Ihre CI/CD-Pipeline
Bringen Sie KI-Lokalisierung mit unseren Erweiterungen und Plugins in Ihren Lokalisierungsworkflow
Die Implementierung von i18next in Angular mit korrekten Initialisierungs- und Ressourcenladestrategien sorgt für eine reibungslose Internationalisierungserfahrung.
In Kombination mit KI-gestützten Übersetzungsdiensten wie l10n.dev können Sie schneller und mit weniger Fehlern wirklich globale Anwendungen erstellen.
Starten Sie noch heute mit der Erstellung mehrsprachiger Angular-Apps!