Internasionalisasi (i18n) sangat penting untuk membangun aplikasi Angular global. Panduan ini menunjukkan cara menerapkan i18next di Angular dengan pemuatan sumber daya yang tepat, inisialisasi, dan pola penggunaan.
i18next adalah salah satu kerangka kerja i18n yang paling populer, menawarkan fitur kuat dan fleksibilitas:
Instal i18next menggunakan npm atau yarn:
npm install i18nextItu saja! i18next adalah perpustakaan mandiri tanpa ketergantungan spesifik kerangka kerja. Anda tidak perlu angular-i18next atau pembungkus lainnya - cukup gunakan i18next langsung di aplikasi Angular Anda.
Ada dua pendekatan utama untuk memuat sumber daya terjemahan di Angular dengan i18next:
Menggunakan impor dinamis memanfaatkan pemisahan kode Webpack untuk memuat terjemahan sesuai permintaan. Pendekatan ini ideal untuk aplikasi dengan banyak bahasa atau file terjemahan besar.
Keuntungan:
Contoh: Memuat dengan Impor Dinamis
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`);
}Pendekatan ini mengimpor file terjemahan sebagai modul ES, memungkinkan Webpack untuk secara otomatis memisahkan kode menjadi bagian terpisah yang dimuat sesuai permintaan.
Plugin backend HTTP memuat terjemahan melalui permintaan HTTP dari server atau CDN. Ini berguna ketika Anda ingin memperbarui terjemahan tanpa membangun ulang aplikasi Anda.
Keuntungan:
Kerugian:
Contoh: Memuat dengan 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,
});Pendekatan ini mengambil file terjemahan dari server saat runtime. Perhatikan bahwa ini memerlukan konfigurasi tambahan untuk SSR.
Menginisialisasi i18next dengan benar sangat penting untuk menghindari kesalahan runtime dan memastikan terjemahan tersedia saat aplikasi Anda dirender.
Fungsi provideAppInitializer Angular (diperkenalkan di Angular 18) memastikan i18next sepenuhnya diinisialisasi sebelum aplikasi mulai merender. Fungsi yang disediakan dieksekusi selama bootstrap aplikasi, dan inisialisasi tidak selesai sampai Promise terpecahkan. Ini mencegah kunci terjemahan muncul alih-alih teks yang diterjemahkan.
Contoh: Konfigurasi App Initializer
export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
provideAppInitializer(initializeI18n),
// ... more providers
],
};Mengapa Ini Penting:
Fungsi inisialisasi menangani pemuatan sumber daya dan mengonfigurasi pengaturan i18next.
Contoh: Inisialisasi 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,
},
});
}Poin Penting:
Pipa terjemahan Angular menyediakan cara yang bersih untuk menggunakan terjemahan dalam template.
Contoh: Pipa Terjemahan
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);
}
}Pipa ditandai sebagai murni: false untuk memastikan ia diperbarui saat bahasa berubah. Ini penting karena perubahan bahasa tidak memodifikasi kunci terjemahan itu sendiri.
Dalam 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}}." -->
Interpolasi memungkinkan Anda untuk menyisipkan nilai dinamis ke dalam terjemahan Anda. Anda dapat meneruskan variabel, menggunakan pipa Angular untuk pemformatan, dan menggabungkan beberapa nilai dalam satu string terjemahan.
Dalam Kode Komponen:
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' });
}Untuk penggunaan template, sintaks pipa bersih dan mudah dibaca. Untuk akses programatik, panggil t() langsung. Ini berguna untuk menampilkan notifikasi, mengatur judul dinamis, atau menangani terjemahan dalam logika komponen.
Gunakan notasi titik yang mencerminkan struktur aplikasi Anda: 'auth:login.title' alih-alih 'loginTitle' atau teks mentah.
Pisahkan terjemahan ke dalam namespace logis (misalnya, common.json, auth.json, dashboard.json) untuk pemeliharaan yang lebih baik.
Gunakan dukungan pluralisasi bawaan i18next untuk menangani bentuk tunggal/jamak dengan benar dalam semua bahasa.
Selalu pastikan i18next diinisialisasi sebelum merender aplikasi Anda menggunakan provideAppInitializer() untuk menjalankan inisialisasi selama bootstrap aplikasi.
Gunakan TypeScript untuk mengekstrak kunci terjemahan langsung dari file JSON Anda untuk keamanan tipe yang lengkap. Alih-alih secara manual memelihara definisi tipe, manfaatkan typeof dan impor dinamis TypeScript untuk secara otomatis menghasilkan tipe dari file terjemahan Anda yang sebenarnya.
Tentukan tipe yang mengekstrak semua kunci yang mungkin dari file terjemahan JSON Anda menggunakan tipe pembantu NestedKeys yang rekursif.
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>}`;Ubah metode transformasi pipa untuk menerima TranslationKey alih-alih string. Ini memberikan keamanan tipe dalam template dan memastikan hanya kunci terjemahan yang valid yang dapat digunakan.
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);
}
}
Sekarang Anda mendapatkan autocompletion IntelliSense penuh dan kesalahan waktu kompilasi untuk kunci yang tidak valid baik di kode TypeScript maupun 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 errorManfaat Kunci Terjemahan yang Aman Tipe:
Terapkan deteksi bahasa yang cerdas dan izinkan pengguna untuk mengganti bahasa saat runtime dengan pemuatan sumber daya otomatis.
Tentukan bahasa pengguna yang akan digunakan saat aplikasi Anda dimulai dengan memeriksa beberapa sumber dalam urutan prioritas.
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;
}Pendekatan ini memeriksa localStorage terlebih dahulu (preferensi pengguna), kemudian kembali ke bahasa browser (navigator.language), dan akhirnya default ke bahasa default aplikasi.
Ganti bahasa saat runtime sambil secara otomatis memuat sumber daya terjemahan sesuai permintaan.
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);
}
}Saat menggunakan impor dinamis, terjemahan dimuat sesuai permintaan. Metode switchLanguage() memeriksa apakah sumber daya sudah dimuat menggunakan getResourceBundle(). Jika tidak ada, ia mengimpor secara dinamis dan menambahkannya menggunakan addResourceBundle(). Ini mencegah permintaan jaringan yang berlebihan sambil memastikan semua terjemahan yang diperlukan tersedia.
Detail Implementasi Kunci:
Mengelola terjemahan secara manual di berbagai bahasa memakan waktu dan rentan terhadap kesalahan. Di sinilah lokalisasi berbasis AI berperan.
l10n.dev adalah layanan terjemahan berbasis AI yang dirancang khusus untuk file JSON i18next:
Hemat berjam-jam kerja terjemahan manual dan hindari kesalahan umum seperti placeholder yang rusak atau bentuk jamak yang tidak benar.
Siap untuk menyederhanakan alur kerja i18n Angular Anda?
Unggah file i18n Anda dan biarkan AI menangani terjemahan dengan kesadaran konteks dan format yang tepat
Temukan mengapa terjemahan berbasis AI lebih baik untuk file i18n dibandingkan metode tradisional
Integrasikan lokalisasi berbasis AI langsung ke dalam pipeline CI/CD Anda
Bawa lokalisasi AI ke dalam alur kerja Anda dengan ekstensi dan plugin kami
Mengimplementasikan i18next di Angular dengan strategi inisialisasi dan pemuatan sumber daya yang tepat memastikan pengalaman internasionalisasi yang lancar.
Dipadukan dengan layanan terjemahan berbasis AI seperti l10n.dev, Anda dapat membangun aplikasi global yang benar-benar lebih cepat dan dengan lebih sedikit kesalahan.
Mulai bangun aplikasi Angular multibahasa hari ini!