Skip to main content

Panduan Lengkap Internasionalisasi React

Dari nol hingga multibahasa: siapkan i18n di aplikasi React, lalu otomatiskan penerjemahan dengan AI.

1

Instal Paket

Anda memerlukan tiga paket: react-i18next (binding React), i18next (library inti), dan i18next-browser-languagedetector sebagai pilihan untuk mendeteksi bahasa secara otomatis.

react-i18next menyediakan hook dan komponen React. i18next adalah mesin inti yang menangani pemuatan terjemahan, interpolasi, dan bentuk jamak. Plugin pendeteksi bahasa membaca preferensi bahasa browser secara otomatis.
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

Konfigurasikan Instance i18n

Buat file konfigurasi i18n yang menginisialisasi i18next dengan bahasa default, sumber daya terjemahan, dan rantai plugin. File ini harus diimpor di titik masuk aplikasi sebelum komponen apa pun dirender.

src/i18n.ts
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;
"You will need to pass in an i18next instance by using initReactI18next"—kesalahan ini berarti Anda lupa memanggil i18n.use(initReactI18next) sebelum i18n.init(). Panggilan .use() harus ditempatkan sebelum .init().
3

Bungkus Aplikasi dengan I18nextProvider

Impor file konfigurasi i18n di root aplikasi dan bungkus pohon komponen dengan I18nextProvider. Tanpanya, useTranslation() mengembalikan kunci mentah, bukan teks terjemahan.

src/main.tsx
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>
);
Jika terjemahan menampilkan kunci mentah seperti "welcome" alih-alih "Welcome to our app", penyebab paling umum adalah I18nextProvider yang tidak ada atau file konfigurasi i18n yang belum diimpor.
4

Buat File Terjemahan

Buat satu file JSON untuk setiap bahasa. Gunakan kunci bertingkat untuk menyusun string menurut fitur atau halaman. Jadikan bahasa sumber (biasanya Inggris) sebagai satu-satunya acuan utama.

public/locales/en/translation.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"
  }
}
Namai kunci berdasarkan hal yang dijelaskannya, bukan tempat tampilnya: "cart.itemCount" lebih baik daripada "homepageCartLabel". Kunci seharusnya tetap bertahan setelah UI didesain ulang.
5

Gunakan Terjemahan dalam Komponen

Panggil useTranslation() di komponen mana pun untuk mendapatkan fungsi t(). Gunakan untuk string sederhana, variabel interpolasi, dan terjemahan yang disematkan dalam JSX dengan komponen Trans.

Greeting.tsx
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>
  );
}
Trans component for JSX
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" />
    }} />
  );
}
Kunci dinamis seperti t(`error.$'{code}'`) berfungsi saat runtime, tetapi tidak dapat diekstrak secara statis oleh alat seperti i18next-scanner. Jika menggunakan alat ekstraksi, cantumkan kunci dinamis secara eksplisit atau gunakan petunjuk komentar.
6

Tangani Bentuk Jamak dan Variabel

i18next menangani bentuk jamak dengan aturan CLDR—bukan hanya tunggal/jamak. Bahasa Arab memiliki 6 bentuk (zero, one, two, few, many, other). Jepang memiliki 1 (other). Tentukan semua bentuk yang diperlukan dalam file terjemahan dan i18next akan memilih bentuk yang benar secara otomatis.

Plural forms by language
// 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}}個のアイテム"
}
Jangan pernah meng-hardcode count === 1 untuk mendeteksi bentuk tunggal. Bahasa seperti Prancis menganggap 0 sebagai tunggal. Rusia, Arab, dan Polski memiliki bentuk yang tidak ada dalam bahasa Inggris. Biarkan i18next menangani aturan bentuk jamak.
7

Tambahkan Pengalihan dan Deteksi Bahasa

Buat pemilih bahasa yang memanggil i18n.changeLanguage(). Gabungkan dengan pendeteksi bahasa browser untuk mendeteksi bahasa pilihan pengguna secara otomatis saat kunjungan pertama, lalu simpan pilihan eksplisit mereka.

LanguageSwitcher.tsx
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>
  );
}
Jika Anda menggunakan SSR (Next.js, Remix), server mungkin mendeteksi bahasa berbeda dari klien (server tidak memiliki preferensi browser). Ini menyebabkan hydration mismatch. Perbaikan: teruskan bahasa yang terdeteksi dari server ke klien sebagai prop atau cookie agar keduanya merender bahasa yang sama.
8

Otomatiskan Penerjemahan

Setelah penyiapan i18n selesai, terjemahkan file bahasa dengan AI. Di IDE, minta asisten AI menerjemahkan file sumber atau gunakan CLI i18n Agent di pipeline CI/CD.

Terminal
# 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
Terjemahkan secara bertahap—saat menambahkan kunci baru ke file sumber, terjemahkan hanya diff, bukan membuat ulang semua file. Ini mempertahankan terjemahan yang telah ditinjau manusia.

Otomatiskan Kualitas Terjemahan

Temukan kunci hilang dan placeholder rusak sebelum dirilis dengan i18n-validate. Uji UI dengan terjemahan palsu menggunakan i18n-pseudo sebelum terjemahan asli tersedia.

Kesalahan Umum

Terjemahan Menampilkan Kunci Mentah

Penyebab: I18nextProvider tidak ada, konfigurasi i18n tidak diimpor di root aplikasi, namespace belum dimuat, atau terjemahan masih dimuat secara asinkron. Periksa konsol browser dengan debug: true untuk mendapatkan petunjuk.

Kesalahan Suspense Tanpa Fallback

"A component suspended while responding to synchronous input"—tambahkan batas '&lt;Suspense&gt;' di sekeliling aplikasi atau atur useSuspense: false dalam konfigurasi init i18next.

Ketidakcocokan Hidrasi SSR

Server merender dalam satu bahasa, tetapi klien melakukan hydration dalam bahasa lain. Pastikan keduanya menggunakan sumber bahasa yang sama—teruskan sebagai prop dari server dan jangan hanya mengandalkan deteksi browser.

Tidak Ada Pelengkapan Otomatis untuk Kunci Terjemahan

Perluas modul i18next dengan tipe sumber daya Anda: declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'. Ini memberikan panggilan t() yang aman secara tipe dengan pelengkapan otomatis.

Struktur File yang Disarankan

Project Structure
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

Coba i18n Agent Sekarang

Lepaskan file terjemahan Anda di sini

JSON, YAML, PO, XML, CSV, Markdown, Properties

atau klik untuk menjelajahi

Bahasa target

Tidak perlu mendaftarEstimasi instan

Pertanyaan yang Sering Diajukan