
คู่มือการทำให้ React รองรับหลายภาษาอย่างครบถ้วน
จากศูนย์สู่หลายภาษา : ตั้งค่า i18n ในแอป React แล้วทำให้การแปลเป็นอัตโนมัติด้วย AI
ติดตั้งแพ็กเกจ
คุณต้องใช้สามแพ็กเกจ ได้แก่ react-i18next (การเชื่อมโยงกับ React), i18next (ไลบรารีหลัก) และ i18next-browser-languagedetector ซึ่งเป็นตัวเลือกเสริมสำหรับตรวจหาภาษาอัตโนมัติ
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backendกำหนดค่าอินสแตนซ์ i18n
สร้างไฟล์กำหนดค่า i18n ที่เริ่มต้น i18next ด้วยภาษาเริ่มต้น ทรัพยากรคำแปล และลำดับปลั๊กอิน ต้องนำเข้าไฟล์นี้ที่จุดเริ่มต้นของแอปก่อนเรนเดอร์คอมโพเนนต์ใดๆ
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;ครอบแอปด้วย I18nextProvider
นำเข้าไฟล์กำหนดค่า i18n ที่รากของแอป แล้วครอบโครงสร้างคอมโพเนนต์ด้วย I18nextProvider หากไม่ทำเช่นนี้ useTranslation() จะคืนคีย์ดิบแทนข้อความที่แปลแล้ว
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>
);สร้างไฟล์แปล
สร้างไฟล์ JSON หนึ่งไฟล์ต่อภาษา ใช้คีย์ซ้อนเพื่อจัดระเบียบข้อความตามฟีเจอร์หรือหน้า และให้ภาษาต้นฉบับ ซึ่งมักเป็นภาษาอังกฤษ เป็นแหล่งข้อมูลจริงเพียงแห่งเดียว
// 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"
}
}ใช้คำแปลในคอมโพเนนต์
เรียก useTranslation() ในคอมโพเนนต์ใดก็ได้เพื่อรับฟังก์ชัน t() ใช้กับข้อความทั่วไป ตัวแปรแทรกค่า และคำแปลที่ฝัง JSX ผ่านคอมโพเนนต์ 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" />
}} />
);
}จัดการพหูพจน์และตัวแปร
i18next จัดการพหูพจน์ด้วยกฎ CLDR ไม่ใช่เพียงเอกพจน์กับพหูพจน์ ภาษาอาหรับมี 6 รูปแบบ (zero, one, two, few, many, other) ส่วนภาษาญี่ปุ่นมี 1 รูปแบบ (other) ให้กำหนดรูปแบบที่จำเป็นทั้งหมดในไฟล์แปล แล้ว i18next จะเลือกค่าที่ถูกต้องโดยอัตโนมัติ
// 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}}個のアイテム"
}เพิ่มการสลับและตรวจหาภาษา
สร้างตัวเลือกภาษาที่เรียก i18n.changeLanguage() ใช้ร่วมกับตัวตรวจหาภาษาของเบราว์เซอร์เพื่อตรวจหาภาษาที่ผู้ใช้ต้องการโดยอัตโนมัติในการเข้าชมครั้งแรก แล้วบันทึกตัวเลือกที่ผู้ใช้เลือกเอง
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>
);
}ทำให้การแปลเป็นอัตโนมัติ
เมื่อตั้งค่า i18n เสร็จแล้ว ให้แปลไฟล์ภาษาด้วย AI โดยบอกผู้ช่วย AI ใน IDE ให้แปลไฟล์ต้นฉบับ หรือใช้ CLI ของ i18n Agent ในไปป์ไลน์ 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,esทำให้คุณภาพการแปลเป็นอัตโนมัติ
ข้อผิดพลาดที่พบบ่อย
คำแปลแสดงคีย์ดิบ
ข้อผิดพลาด Suspense เมื่อไม่มี fallback
Hydration ของ SSR ไม่ตรงกัน
ไม่มีการเติมข้อความอัตโนมัติสำหรับคีย์คำแปล
โครงสร้างไฟล์ที่แนะนำ
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.jsonแปลรายการต่อไปนี้ได้ด้วย :
ลองใช้ i18n Agent ตอนนี้
ลากและวางไฟล์แปลของคุณที่นี่
JSON, YAML, PO, XML, CSV, Markdown, Properties
หรือคลิกเพื่อเลือกไฟล์
ภาษาเป้าหมาย