L'internazionalizzazione (i18n) è essenziale per costruire applicazioni Angular globali. Questa guida ti mostra come implementare i18next in Angular con un caricamento corretto delle risorse, inizializzazione e modelli di utilizzo.
i18next è uno dei framework i18n più popolari, offrendo funzionalità potenti e flessibilità:
Installa i18next usando npm o yarn:
npm install i18nextEcco fatto! i18next è una libreria autonoma senza dipendenze specifiche per framework. Non hai bisogno di angular-i18next o di alcun altro wrapper - usa semplicemente i18next direttamente nella tua applicazione Angular.
Ci sono due approcci principali per caricare risorse di traduzione in Angular con i18next:
Utilizzare importazioni dinamiche sfrutta la suddivisione del codice di Webpack per caricare le traduzioni su richiesta. Questo approccio è ideale per applicazioni con molte lingue o file di traduzione di grandi dimensioni.
Vantaggi:
Esempio: Caricamento con Importazioni Dinamiche
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`);
}Questo approccio importa file di traduzione come moduli ES, consentendo a Webpack di suddividerli automaticamente in chunk separati che vengono caricati su richiesta.
Il plugin HTTP backend carica le traduzioni tramite richieste HTTP da un server o CDN. Questo è utile quando vuoi aggiornare le traduzioni senza ricompilare la tua app.
Vantaggi:
Svantaggi:
Esempio: Caricamento con 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,
});Questo approccio recupera i file di traduzione da un server durante l'esecuzione. Nota che questo richiede una configurazione aggiuntiva per SSR.
Inizializzare correttamente i18next è cruciale per evitare errori di runtime e garantire che le traduzioni siano disponibili quando la tua app viene renderizzata.
La funzione provideAppInitializer di Angular (introdotta in Angular 18) garantisce che i18next sia completamente inizializzato prima che l'applicazione inizi a renderizzare. La funzione fornita viene eseguita durante l'avvio dell'app, e l'inizializzazione non è completata fino a quando la Promise non si risolve. Questo previene che le chiavi di traduzione appaiano al posto del testo tradotto.
Esempio: Configurazione dell'App Initializer
export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
provideAppInitializer(initializeI18n),
// ... more providers
],
};Perché Questo È Importante:
La funzione di inizializzazione gestisce il caricamento delle risorse e la configurazione delle impostazioni di i18next.
Esempio: Inizializzazione di 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,
},
});
}Punti Chiave:
La pipe di traduzione di Angular fornisce un modo pulito per utilizzare le traduzioni nei template.
Esempio: Pipe di Traduzione
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);
}
}Il pipe è contrassegnato come puro: false per garantire che si aggiorni quando la lingua cambia. Questo è importante perché i cambiamenti di lingua non modificano la chiave di traduzione stessa.
Nei Template:
<!-- 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'interpolazione consente di inserire valori dinamici nelle tue traduzioni. Puoi passare variabili, utilizzare i pipe di Angular per la formattazione e combinare più valori in una singola stringa di traduzione.
Nel Codice del Componente:
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' });
}Per l'uso nei template, la sintassi del pipe è pulita e leggibile. Per l'accesso programmatico, chiama t() direttamente. Questo è utile per mostrare notifiche, impostare titoli dinamici o gestire traduzioni nella logica del componente.
Usa la notazione a punti che riflette la struttura della tua app: 'auth:login.title' invece di 'loginTitle' o testo grezzo.
Dividi le traduzioni in namespace logici (ad es., common.json, auth.json, dashboard.json) per una migliore manutenibilità.
Usa il supporto integrato per la pluralizzazione di i18next per gestire correttamente le forme singolari/plurali in tutte le lingue.
Assicurati sempre che i18next sia inizializzato prima di rendere la tua app utilizzando provideAppInitializer() per eseguire l'inizializzazione durante l'avvio dell'app.
Usa TypeScript per estrarre le chiavi di traduzione direttamente dai tuoi file JSON per una completa sicurezza dei tipi. Invece di mantenere manualmente le definizioni dei tipi, sfrutta typeof di TypeScript e le importazioni dinamiche per generare automaticamente i tipi dai tuoi file di traduzione effettivi.
Definisci un tipo che estrae tutte le possibili chiavi dai tuoi file di traduzione JSON utilizzando un tipo helper NestedKeys ricorsivo.
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>}`;Cambia il metodo transform del pipe per accettare TranslationKey invece di string. Questo fornisce sicurezza dei tipi nei template e garantisce che possano essere utilizzate solo chiavi di traduzione valide.
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);
}
}
Ora ottieni il completamento automatico completo di IntelliSense e errori di compilazione per chiavi non valide sia nel codice TypeScript che nei template.
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 errorVantaggi delle Chiavi di Traduzione Sicure:
Implementa un rilevamento intelligente della lingua e consenti agli utenti di cambiare lingua a runtime con caricamento automatico delle risorse.
Determina la lingua dell'utente da utilizzare quando la tua app si avvia controllando più fonti in ordine di 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;
}Questo approccio controlla prima localStorage (preferenza dell'utente), poi torna alla lingua del browser (navigator.language), e infine predefinisce alla lingua predefinita dell'app.
Cambia lingua a runtime mentre carica automaticamente le risorse di traduzione su richiesta.
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);
}
}Quando si usano importazioni dinamiche, le traduzioni vengono caricate su richiesta. Il metodo switchLanguage() controlla se le risorse sono già caricate usando getResourceBundle(). Se mancano, le importa dinamicamente e le aggiunge usando addResourceBundle(). Questo previene richieste di rete ridondanti garantendo che tutte le traduzioni necessarie siano disponibili.
Dettagli Chiave di Implementazione:
Gestire le traduzioni manualmente attraverso più lingue è dispendioso in termini di tempo e soggetto a errori. È qui che entra in gioco la localizzazione potenziata dall'AI.
l10n.dev è un servizio di traduzione potenziato dall'AI specificamente progettato per i file JSON di i18next:
Risparmia ore di lavoro di traduzione manuale ed evita errori comuni come segnaposto rotti o forme plurali errate.
Pronto a semplificare il tuo flusso di lavoro Angular i18n?
Carica i tuoi file i18n e lascia che l'IA gestisca la traduzione con consapevolezza del contesto e formattazione corretta
Scopri perché la traduzione potenziata dall'IA è migliore per i file i18n rispetto ai metodi tradizionali
Integra la localizzazione potenziata dall'IA direttamente nella tua pipeline CI/CD
Porta la localizzazione AI nel tuo flusso di lavoro con le nostre estensioni e plugin
Implementare i18next in Angular con strategie di inizializzazione e caricamento delle risorse adeguate garantisce un'esperienza di internazionalizzazione fluida.
Combinato con servizi di traduzione potenziati dall'AI come l10n.dev, puoi costruire applicazioni veramente globali più velocemente e con meno errori.
Inizia a costruire app Angular multilingue oggi!