La localisation est essentielle pour créer des applications Angular mondiales. Ce guide vous montre comment implémenter i18next dans Angular avec un chargement des ressources, une initialisation et des modèles d'utilisation appropriés.
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 de tout autre wrapper - utilisez simplement i18next directement dans votre application Angular.
Il existe deux approches principales pour charger les ressources de traduction dans Angular avec i18next :
L'utilisation des importations dynamiques exploite le découpage de code de Webpack pour charger les traductions à la demande. Cette approche est idéale pour les applications avec de nombreuses langues ou de gros fichiers de traduction.
Avantages :
Exemple : Chargement avec des importations dynamiques
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`);
}Cette approche importe les 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 backend HTTP charge les traductions via des requêtes HTTP depuis un serveur ou un CDN. Ceci est utile lorsque vous souhaitez mettre à jour les traductions sans reconstruire votre application.
Avantages :
Inconvénients :
Exemple : Chargement avec 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 les fichiers de traduction depuis un serveur au moment de l'exécution. Notez que cela nécessite une configuration supplémentaire pour le SSR.
Initialiser correctement i18next est crucial pour éviter les erreurs d'exécution et garantir que les traductions sont disponibles lorsque votre application s'affiche.
La fonction provideAppInitializer d'Angular (introduite dans Angular 18) garantit qu'i18next est entièrement initialisé avant que l'application ne commence à s'afficher. La fonction fournie est exécutée lors du bootstrap 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 est-ce important :
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 Angular offre un moyen propre d'utiliser les 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 pure: false pour garantir qu'il se mette à 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 une utilisation dans les modèles, la syntaxe du pipe est propre et lisible. Pour un accès programmatique, appelez t() directement. Ceci est utile pour afficher des notifications, définir des titres dynamiques ou gérer les traductions dans la logique du composant.
Utilisez la 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 la prise en charge intégrée de la pluralisation d'i18next pour gérer correctement les formes singulières/plurielles dans toutes les langues.
Assurez-vous toujours qu'i18next est initialisé avant de rendre votre application en utilisant provideAppInitializer() pour exécuter l'initialisation lors du bootstrap 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, exploitez typeof et les importations dynamiques de TypeScript 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'assistance récursif NestedKeys.
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>}`;Modifiez 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 une saisie semi-automatique IntelliSense complète et des erreurs de compilation pour les clés invalides, tant dans le code TypeScript que dans 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 par type :
Implémentez une détection intelligente de la langue et permettez aux utilisateurs de changer de langue au moment de l'exécution avec un chargement automatique des ressources.
Déterminez la langue de l'utilisateur à utiliser au démarrage de votre application 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 utilisateur), puis revient à la langue du navigateur (navigator.language), et enfin utilise par défaut la langue par défaut de l'application.
Changez de langue au moment de 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');
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);
}
}Lors de l'utilisation des importations 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 sont manquantes, elle les importe dynamiquement et les ajoute en utilisant addResourceBundle(). Cela évite les requêtes réseau redondantes tout en garantissant que toutes les traductions nécessaires sont disponibles.
Détails d'implémentation clés :
Gérer les traductions manuellement dans plusieurs langues prend du temps et est sujet aux erreurs. C'est là qu'intervient la localisation assistée par IA.
l10n.dev est un service de traduction assistée par IA spécifiquement conçu pour les fichiers JSON d'i18next :
Économisez des heures de travail de traduction manuel et évitez les erreurs courantes comme les espaces réservés cassés ou les formes plurielles incorrectes.
Prêt à rationaliser votre flux de travail i18n Angular ?
Téléversez vos fichiers i18n et laissez l'IA gérer la traduction avec une conscience du contexte et une préservation du format
Découvrez pourquoi la traduction assistée par IA est meilleure pour les fichiers i18n que les méthodes traditionnelles
Intégrez la localisation assistée par IA directement dans votre pipeline CI/CD
Intégrez la localisation assistée par IA dans votre flux de travail avec nos extensions et plugins
L'implémentation d'i18next dans Angular avec des stratégies d'initialisation et de chargement des ressources appropriées garantit une expérience de localisation fluide.
Combiné avec des services de traduction assistée par IA comme l10n.dev, vous pouvez créer des applications véritablement mondiales plus rapidement et avec moins d'erreurs.
Commencez à créer des applications Angular multilingues dès aujourd'hui !