L'internationalisation (i18n) est essentielle pour construire des applications Angular globales. Ce guide vous montre comment implémenter i18next dans Angular avec un chargement de ressources approprié, une initialisation et des modèles d'utilisation.
i18next est l'un des frameworks i18n les plus populaires, offrant des fonctionnalités puissantes et de la flexibilité :
Installez i18next en utilisant npm ou yarn :
npm install i18nextC'est tout ! i18next est une bibliothèque autonome sans dépendances spécifiques au framework. Vous n'avez pas besoin d'angular-i18next ou d'un autre wrapper - utilisez simplement i18next directement dans votre application Angular.
Il existe deux approches principales pour charger des ressources de traduction dans Angular avec i18next :
L'utilisation des imports dynamiques exploite la séparation de code de Webpack pour charger les traductions à la demande. Cette approche est idéale pour les applications avec de nombreuses langues ou de grands fichiers de traduction.
Avantages :
Exemple : Chargement avec des imports dynamiques
private async loadLanguageResources(
lang: string,
): Promise<Record<string, Record<string, unknown>>> {
const languageResources: Record<string, Record<string, unknown>> = {};
for (const namespace of NAMESPACES) {
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`);
}Cette approche importe des fichiers de traduction en tant que modules ES, permettant à Webpack de les diviser automatiquement en morceaux séparés qui sont chargés à la demande.
Le plugin HTTP backend charge les traductions via des requêtes HTTP depuis un serveur ou un CDN. Cela est utile lorsque vous souhaitez mettre à jour les traductions sans reconstruire votre application.
Avantages :
Inconvénients :
Exemple : Chargement avec le backend HTTP
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,
});Cette approche récupère des fichiers de traduction depuis un serveur à l'exécution. Notez que cela nécessite une configuration supplémentaire pour SSR.
Initialiser i18next correctement est crucial pour éviter les erreurs d'exécution et garantir que les traductions sont disponibles lorsque votre application se rend.
La fonction provideAppInitializer d'Angular (introduite dans Angular 18) garantit qu'i18next est entièrement initialisé avant que l'application ne commence à se rendre. La fonction fournie est exécutée pendant le démarrage de l'application, et l'initialisation ne se termine pas tant que la promesse n'est pas résolue. Cela empêche les clés de traduction d'apparaître à la place du texte traduit.
Exemple : Configuration de l'initialiseur d'application
export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
provideAppInitializer(initializeI18n),
// ... more providers
],
};Pourquoi cela compte :
La fonction d'initialisation gère le chargement des ressources et la configuration des paramètres d'i18next.
Exemple : Initialisation d'i18next
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,
},
});
}Points clés :
Le pipe de traduction d'Angular fournit un moyen propre d'utiliser des traductions dans les modèles.
Exemple : Pipe de traduction
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);
}
}Le pipe est marqué comme pur : false pour s'assurer qu'il se met à jour lorsque la langue change. C'est important car les changements de langue ne modifient pas la clé de traduction elle-même.
Dans les Modèles :
<!-- 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}}." -->
L'interpolation vous permet d'insérer des valeurs dynamiques dans vos traductions. Vous pouvez passer des variables, utiliser des pipes Angular pour le formatage, et combiner plusieurs valeurs dans une seule chaîne de traduction.
Dans le Code du Composant :
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' });
}Pour l'utilisation dans les modèles, la syntaxe du pipe est claire et lisible. Pour un accès programmatique, appelez t() directement. Cela est utile pour afficher des notifications, définir des titres dynamiques, ou gérer des traductions dans la logique du composant.
Utilisez une notation par points qui reflète la structure de votre application : 'auth:login.title' au lieu de 'loginTitle' ou de texte brut.
Divisez les traductions en espaces de noms logiques (par exemple, common.json, auth.json, dashboard.json) pour une meilleure maintenabilité.
Utilisez le support de pluralisation intégré d'i18next pour gérer correctement les formes singulières/plurielle dans toutes les langues.
Assurez-vous toujours qu'i18next est initialisé avant de rendre votre application en utilisant provideAppInitializer() pour exécuter l'initialisation pendant le démarrage de l'application.
Utilisez TypeScript pour extraire les clés de traduction directement de vos fichiers JSON pour une sécurité de type complète. Au lieu de maintenir manuellement les définitions de type, tirez parti de typeof de TypeScript et des imports dynamiques pour générer automatiquement des types à partir de vos fichiers de traduction réels.
Définissez un type qui extrait toutes les clés possibles de vos fichiers de traduction JSON en utilisant un type d'aide NestedKeys récursif.
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>}`;Changez la méthode transform du pipe pour accepter TranslationKey au lieu de string. Cela fournit une sécurité de type dans les modèles et garantit que seules des clés de traduction valides peuvent être utilisées.
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);
}
}
Vous obtenez maintenant un autocomplétion IntelliSense et des erreurs de compilation pour les clés invalides dans le code TypeScript et les modèles.
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 errorAvantages des Clés de Traduction Sécurisées :
Implémentez une détection de langue intelligente et permettez aux utilisateurs de changer de langue à l'exécution avec un chargement automatique des ressources.
Déterminez la langue de l'utilisateur à utiliser lorsque votre application démarre en vérifiant plusieurs sources par ordre de priorité.
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;
}Cette approche vérifie d'abord localStorage (préférence de l'utilisateur), puis se rabat sur la langue du navigateur (navigator.language), et enfin se fixe à la langue par défaut de l'application.
Changez de langue à l'exécution tout en chargeant automatiquement les ressources de traduction à la demande.
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');
// Check if any namespace is missing for this language
for (const namespace of NAMESPACES) {
const currentResources = i18next.default.getResourceBundle(lang, namespace);
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);
}
}Lors de l'utilisation des imports dynamiques, les traductions sont chargées à la demande. La méthode switchLanguage() vérifie si les ressources sont déjà chargées en utilisant getResourceBundle(). Si elles manquent, elle les importe dynamiquement et les ajoute en utilisant addResourceBundle(). Cela empêche les requêtes réseau redondantes tout en s'assurant que toutes les traductions nécessaires sont disponibles.
Points Clés de Mise en Œuvre :
Gérer les traductions manuellement dans plusieurs langues est chronophage et sujet à erreurs. C'est là que la localisation alimentée par l'IA entre en jeu.
l10n.dev est un service de traduction alimenté par l'IA spécifiquement conçu pour les fichiers JSON i18next :
Économisez des heures de travail de traduction manuelle et évitez des erreurs courantes comme des espaces réservés cassés ou des formes plurielles incorrectes.
Prêt à rationaliser votre flux de travail Angular i18n ?
Téléchargez vos fichiers i18n et laissez l'IA gérer la traduction avec conscience du contexte et formatage approprié
Découvrez pourquoi la traduction alimentée par l'IA est meilleure pour les fichiers i18n que les méthodes traditionnelles
Intégrez la localisation alimentée par l'IA directement dans votre pipeline CI/CD
Apportez la localisation par IA dans votre flux de travail avec nos extensions et plugins
Mettre en œuvre i18next dans Angular avec des stratégies d'initialisation et de chargement de ressources appropriées assure une expérience d'internationalisation fluide.
Associé à des services de traduction alimentés par l'IA comme l10n.dev, vous pouvez construire des applications véritablement mondiales plus rapidement et avec moins d'erreurs.
Commencez à construire des applications Angular multilingues aujourd'hui !