
Hướng dẫn đầy đủ về quốc tế hóa React
Từ con số 0 đến ứng dụng đa ngôn ngữ: thiết lập i18n trong ứng dụng React rồi tự động dịch bằng AI.
Cài đặt gói
Bạn cần ba gói: react-i18next (các liên kết React), i18next (thư viện lõi) và i18next-browser-languagedetector tùy chọn để tự động phát hiện locale.
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backendCấu hình phiên bản i18n
Tạo tệp cấu hình i18n để khởi tạo i18next với ngôn ngữ mặc định, tài nguyên bản dịch và chuỗi plugin của bạn. Bạn phải nhập tệp này tại điểm vào của ứng dụng trước khi bất kỳ thành phần nào hiển thị.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // Must come before .init()
.init({
fallbackLng: 'en',
debug: process.env.NODE_ENV === 'development',
interpolation: {
escapeValue: false, // React already escapes
},
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
});
export default i18n;Bọc ứng dụng bằng I18nextProvider
Nhập tệp cấu hình i18n tại gốc ứng dụng và bọc cây thành phần bằng I18nextProvider. Nếu thiếu bước này, useTranslation() sẽ trả về khóa thô thay vì văn bản đã dịch.
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n'; // Import your config
import App from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<Suspense fallback={<div>Loading...</div>}>
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
</Suspense>
</React.StrictMode>
);Tạo tệp bản dịch
Tạo một tệp JSON cho mỗi ngôn ngữ. Dùng khóa lồng nhau để sắp xếp chuỗi theo tính năng hoặc trang. Duy trì ngôn ngữ nguồn (thường là tiếng Anh) làm nguồn dữ liệu chuẩn duy nhất.
// public/locales/en/translation.json
{
"nav": {
"home": "Home",
"about": "About",
"settings": "Settings"
},
"greeting": "Hello, {{name}}!",
"cart": {
"itemCount_one": "{{count}} item",
"itemCount_other": "{{count}} items"
}
}
// public/locales/de/translation.json
{
"nav": {
"home": "Startseite",
"about": "Über uns",
"settings": "Einstellungen"
},
"greeting": "Hallo, {{name}}!",
"cart": {
"itemCount_one": "{{count}} Artikel",
"itemCount_other": "{{count}} Artikel"
}
}Dùng bản dịch trong thành phần
Gọi useTranslation() trong bất kỳ thành phần nào để lấy hàm t(). Dùng hàm này cho chuỗi đơn giản, biến nội suy và bản dịch nhúng JSX với thành phần Trans.
import { useTranslation } from 'react-i18next';
function Greeting({ userName }: { userName: string }) {
const { t } = useTranslation();
return (
<div>
<h1>{t('greeting', { name: userName })}</h1>
<nav>
<a href="/">{t('nav.home')}</a>
<a href="/about">{t('nav.about')}</a>
</nav>
</div>
);
}import { Trans, useTranslation } from 'react-i18next';
// For JSX inside translations:
// "terms": "By signing up, you agree to our <link>Terms</link>."
function SignUp() {
const { t } = useTranslation();
return (
<Trans i18nKey="terms" components={{
link: <a href="/terms" className="underline" />
}} />
);
}Xử lý số nhiều và biến
i18next xử lý số nhiều theo quy tắc CLDR chứ không chỉ dạng số ít/số nhiều. Tiếng Ả Rập có 6 dạng (zero, one, two, few, many, other). Tiếng Nhật có 1 dạng (other). Hãy định nghĩa mọi dạng bắt buộc trong tệp bản dịch để i18next tự động chọn đúng dạng.
// English: 2 forms (one, other)
{
"itemCount_one": "{{count}} item",
"itemCount_other": "{{count}} items"
}
// Arabic: 6 forms (zero, one, two, few, many, other)
{
"itemCount_zero": "لا عناصر",
"itemCount_one": "عنصر واحد",
"itemCount_two": "عنصران",
"itemCount_few": "{{count}} عناصر",
"itemCount_many": "{{count}} عنصرًا",
"itemCount_other": "{{count}} عنصر"
}
// Japanese: 1 form (other)
{
"itemCount_other": "{{count}}個のアイテム"
}Thêm tính năng chuyển đổi và phát hiện ngôn ngữ
Tạo bộ chọn ngôn ngữ gọi i18n.changeLanguage(). Kết hợp với trình phát hiện ngôn ngữ của trình duyệt để tự động nhận biết ngôn ngữ người dùng ưu tiên trong lần truy cập đầu tiên rồi lưu lựa chọn rõ ràng của họ.
import { useTranslation } from 'react-i18next';
const LANGUAGES = [
{ code: 'en', label: 'English' },
{ code: 'de', label: 'Deutsch' },
{ code: 'ja', label: '日本語' },
{ code: 'es', label: 'Español' },
];
function LanguageSwitcher() {
const { i18n } = useTranslation();
return (
<select
value={i18n.language}
onChange={(e) => i18n.changeLanguage(e.target.value)}
>
{LANGUAGES.map(({ code, label }) => (
<option key={code} value={code}>{label}</option>
))}
</select>
);
}Tự động hóa bản dịch
Sau khi hoàn tất thiết lập i18n, hãy dùng AI để dịch các tệp locale. Trong IDE, yêu cầu trợ lý AI dịch tệp nguồn hoặc dùng CLI i18n Agent trong quy trình CI/CD.
# In your IDE, ask your AI assistant:
> Translate public/locales/en/translation.json to German, Japanese, and Spanish
✓ de/translation.json created (1.2s)
✓ ja/translation.json created (1.5s)
✓ es/translation.json created (1.1s)
# Or use the CLI in CI/CD:
npx i18n-agent translate public/locales/en/translation.json --lang de,ja,esTự động bảo đảm chất lượng bản dịch
Lỗi thường gặp
Bản dịch hiển thị khóa thô
Lỗi Suspense khi không có phương án dự phòng
SSR hydration không khớp
Không tự động hoàn thành khóa bản dịch
Cấu trúc tệp đề xuất
my-react-app/
├── public/
│ └── locales/
│ ├── en/
│ │ ├── translation.json # Default namespace
│ │ ├── common.json # Shared strings
│ │ └── dashboard.json # Feature namespace
│ ├── de/
│ │ ├── translation.json
│ │ ├── common.json
│ │ └── dashboard.json
│ └── ja/
│ └── ...
├── src/
│ ├── i18n.ts # i18n configuration
│ ├── main.tsx # App entry with Provider
│ ├── App.tsx
│ └── components/
│ └── LanguageSwitcher.tsx
└── package.jsonDùng thử i18n Agent ngay
Thả tệp bản dịch của bạn vào đây
JSON, YAML, PO, XML, CSV, Markdown, Properties
hoặc nhấp để duyệt
Ngôn ngữ đích