Skip to main content

Panduan react-intl: Persediaan Pengantarabangsaan React

Sediakan react-intl daripada FormatJS dalam aplikasi React dengan IntlProvider, FormattedMessage, useIntl, format mesej ICU, dan terjemahan automatik.

Menggunakan react-i18next? Lihat panduan react-i18next kami

1

Pasang react-intl

react-intl ialah sebahagian daripada projek FormatJS. Pustaka ini menyediakan komponen dan cangkuk React untuk memformat rentetan, nombor, tarikh, dan bentuk jamak menggunakan standard ICU MessageFormat.

react-intl tidak mempunyai kebergantungan masa jalan selain React. Pustaka ini menggunakan Intl API terbina dalam pelayar untuk pemformatan nombor dan tarikh serta menyertakan penghurai ICU MessageFormat sendiri untuk bentuk jamak, select, dan teks kaya.
Terminal
npm install react-intl
2

Konfigurasikan IntlProvider

Balut aplikasi dengan IntlProvider pada akar. Teruskan bahasa aktif dan objek messages rata. Setiap komponen di bawahnya kemudian boleh mengakses terjemahan melalui FormattedMessage atau useIntl.

src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { IntlProvider } from 'react-intl';
import App from './App';
import enMessages from './messages/en.json';
import deMessages from './messages/de.json';

const messages: Record<string, Record<string, string>> = {
  en: enMessages,
  de: deMessages,
};

// Detect locale from browser or your routing layer
const locale = navigator.language.split('-')[0] || 'en';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <IntlProvider locale={locale} messages={messages[locale] || messages.en}>
      <App />
    </IntlProvider>
  </React.StrictMode>
);
IntlProvider memerlukan objek messages kekunci-nilai rata (contohnya { "app.greeting": "Hello" }). JSON tersarang perlu diratakan sebelum diteruskan kepada IntlProvider, atau gunakan utiliti seperti flat untuk menukar struktur tersarang.

Fail Mesej

Cipta satu fail JSON bagi setiap bahasa. react-intl menggunakan sintaks ICU MessageFormat secara natif—bentuk jamak, select, dan pemboleh ubah semuanya dinyatakan sebaris dalam rentetan mesej.

messages/en.json & messages/de.json
// messages/en.json
{
  "app.greeting": "Hello, {name}!",
  "nav.home": "Home",
  "nav.about": "About",
  "nav.settings": "Settings",
  "cart.itemCount": "{count, plural, one {# item} other {# items}} in your cart"
}

// messages/de.json
{
  "app.greeting": "Hallo, {name}!",
  "nav.home": "Startseite",
  "nav.about": "Über uns",
  "nav.settings": "Einstellungen",
  "cart.itemCount": "{count, plural, one {# Artikel} other {# Artikel}} in Ihrem Warenkorb"
}
Gunakan ID yang dipisahkan titik seperti "nav.home" untuk penyusunan. Tidak seperti react-i18next, react-intl menjangkakan objek messages rata—anda meratakan kekunci, bukan strukturnya.
3

Gunakan Terjemahan dalam Komponen

react-intl menyediakan dua API utama: komponen FormattedMessage untuk memaparkan JSX terjemahan dan cangkuk useIntl untuk akses imperatif (ruang letak, label aria, pemformatan berprogram).

Komponen FormattedMessage

Gunakan FormattedMessage untuk terjemahan deklaratif dalam JSX. Teruskan ID mesej dan sebarang nilai interpolasi. Komponen memaparkan rentetan terjemahan secara langsung.

Greeting.tsx
import { FormattedMessage } from 'react-intl';

function Greeting({ userName }: { userName: string }) {
  return (
    <div>
      <h1>
        <FormattedMessage
          id="app.greeting"
          values={{ name: userName }}
        />
      </h1>
      <nav>
        <a href="/"><FormattedMessage id="nav.home" /></a>
        <a href="/about"><FormattedMessage id="nav.about" /></a>
      </nav>
    </div>
  );
}

Cangkuk useIntl

Gunakan useIntl() apabila memerlukan rentetan terjemahan sebagai nilai biasa—untuk ruang letak input, label aria, document.title, atau apabila meneruskan rentetan kepada API bukan React. Cangkuk juga menyediakan formatNumber, formatDate, dan formatRelativeTime.

SearchBar.tsx
import { useIntl } from 'react-intl';

function SearchBar() {
  const intl = useIntl();

  return (
    <input
      type="search"
      placeholder={intl.formatMessage({ id: 'search.placeholder' })}
      aria-label={intl.formatMessage({ id: 'search.ariaLabel' })}
    />
  );
}

// useIntl also gives you formatNumber, formatDate, formatRelativeTime:
function PriceTag({ amount, currency }: { amount: number; currency: string }) {
  const intl = useIntl();
  return (
    <span>{intl.formatNumber(amount, { style: 'currency', currency })}</span>
  );
}

Teks Kaya (HTML dalam Terjemahan)

Benamkan JSX dalam terjemahan menggunakan teg seperti XML dalam rentetan mesej. Teruskan pengendali teg melalui prop values untuk memaparkan pautan, teks tebal, atau sebarang komponen React dalam mesej terjemahan.

SignUp.tsx
import { FormattedMessage } from 'react-intl';

// Message: "By signing up, you agree to our <link>Terms</link>."
// Key: "signup.terms"
// Value: "By signing up, you agree to our <link>Terms</link>."

function SignUp() {
  return (
    <FormattedMessage
      id="signup.terms"
      values={{
        link: (chunks) => <a href="/terms" className="underline">{chunks}</a>,
      }}
    />
  );
}
FormattedMessage memaparkan React Fragment secara lalai. Jika memerlukan elemen pembalut tertentu, teruskan prop textComponent kepada IntlProvider atau balut FormattedMessage dalam elemen sendiri.

Pengekstrakan Mesej dengan @formatjs/cli

FormatJS menyediakan CLI untuk mengekstrak ID mesej secara automatik daripada kod sumber ke dalam fail JSON. Ini memastikan fail mesej kekal segerak dengan komponen tanpa pencatatan manual.

Terminal
# Install the CLI
npm install -g @formatjs/cli

# Extract messages from source code into a JSON file
formatjs extract 'src/**/*.tsx' --out-file messages/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'

# Or use explicit IDs (recommended):
formatjs extract 'src/**/*.tsx' --out-file messages/en.json

# Compile messages for production (optional, improves perf)
formatjs compile messages/en.json --out-file compiled/en.json
formatjs compile messages/de.json --out-file compiled/de.json
4

Bentuk Jamak dan ICU Select

react-intl menggunakan ICU MessageFormat secara natif. Bentuk jamak, select berasaskan jantina, dan pemformatan tersarang semuanya dinyatakan terus dalam rentetan mesej—tanpa konvensyen akhiran atau kekunci berasingan.

ICU plural syntax by language
// ICU MessageFormat syntax — react-intl uses this natively
// English
{
  "cart.itemCount": "{count, plural, one {# item} other {# items}} in your cart",
  "inbox.unread": "You have {count, plural, =0 {no unread messages} one {# unread message} other {# unread messages}}"
}

// Arabic — 6 plural forms
{
  "cart.itemCount": "{count, plural, zero {لا عناصر} one {عنصر واحد} two {عنصران} few {# عناصر} many {# عنصرًا} other {# عنصر}} في سلتك"
}

// Japanese — 1 form (other)
{
  "cart.itemCount": "カートに{count}個の商品があります"
}
Jangan sekali-kali mengkod keras logik bentuk jamak dalam JavaScript. Bahasa seperti Arab mempunyai 6 bentuk jamak, Perancis menganggap 0 sebagai tunggal, dan Jepun tidak membezakan bentuk jamak. Biarkan ICU MessageFormat mengendalikan peraturan—hanya teruskan nilai count.

ICU Select untuk Jantina dan Peranan

Gunakan sintaks ICU select untuk terjemahan bergantung pada konteks seperti jantina, peranan pengguna, atau nilai keadaan. Ungkapan select memilih varian yang betul berdasarkan nilai yang diberikan.

ICU select syntax
// Gender-dependent messages using ICU select
{
  "user.greeting": "{gender, select, male {He} female {She} other {They}} liked your post.",
  "user.invitation": "{role, select, admin {You can manage all settings.} editor {You can edit content.} other {You can view content.}}"
}

// Usage:
<FormattedMessage
  id="user.greeting"
  values={{ gender: user.gender }}
/>

Automatikkan Kualiti Terjemahan

Kesan kekunci hilang dan ruang letak rosak sebelum dikeluarkan dengan i18n-validate. Uji UI dengan terjemahan pseudo menggunakan i18n-pseudo sebelum terjemahan sebenar tersedia.

Kesilapan Umum

Terlalu Bergantung pada defaultMessage

defaultMessage ialah sandaran pembangunan, bukan strategi terjemahan. Jika menggunakan defaultMessage untuk semua rentetan, output pengekstrakan mesej akan mengandungi teks bahasa Inggeris, tetapi penterjemah mungkin terlepas kekunci baharu. Sentiasa ekstrak dan selenggara fail bahasa sumber yang lengkap.

Objek Tersarang, Bukan Kekunci Rata

IntlProvider menjangkakan Record&lt;string, string&gt; rata untuk messages. Jika anda meneruskan JSON tersarang seperti { nav: { home: "Home" } }, react-intl tidak akan menemui kekunci "nav.home". Ratakan messages sebelum meneruskannya atau gunakan pustaka seperti flat.

IntlProvider Menyebabkan Paparan Semula

Jika mencipta objek messages secara sebaris dalam fungsi render, IntlProvider menerima rujukan objek baharu pada setiap paparan, lalu menyebabkan semua pengguna memaparkan semula. Memoisasikan messages dengan useMemo atau takrifkannya di luar komponen.

IntlProvider Hilang dalam Ujian

Komponen yang menggunakan FormattedMessage atau useIntl akan melemparkan ralat jika dipaparkan tanpa induk IntlProvider. Dalam ujian, balut komponen dengan IntlProvider menggunakan locale="en" dan objek messages kosong atau minimum.

Struktur Fail yang Disyorkan

Project Structure
my-react-app/
├── messages/
│   ├── en.json              # Source of truth (English)
│   ├── de.json              # German
│   ├── ja.json              # Japanese
│   └── es.json              # Spanish
├── compiled/                # Optional: compiled messages for prod
│   ├── en.json
│   └── ...
├── src/
│   ├── main.tsx             # App entry with IntlProvider
│   ├── App.tsx
│   └── components/
│       ├── Greeting.tsx      # Uses FormattedMessage
│       └── SearchBar.tsx     # Uses useIntl
└── package.json

Cuba i18n Agent Sekarang

Lepaskan fail terjemahan anda di sini

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

atau klik untuk semak imbas

Bahasa sasaran

Tidak perlu mendaftarAnggaran serta-merta

Sandaran Bahasa dengan react-intl-locale-chain

Apabila kekunci terjemahan tiada dalam bahasa serantau seperti pt-BR, react-intl terus beralih kepada bahasa lalai dan bukannya memeriksa bahasa induk pt terlebih dahulu.

Terminal
npm install react-intl-locale-chain
Configuration
<LocaleChainProvider
  fallbacks={{
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  }}
  defaultLocale="en"
>
  <App />
</LocaleChainProvider>

Lihat Panduan Sandaran Bahasa kami untuk senarai lengkap rangka kerja yang disokong dan 75 rantaian terbina dalam. Learn more →

Soalan Lazim