Skip to main content

Ръководство за react-intl: настройване на интернационализацията в React

Настройте FormatJS react-intl във Вашето React приложение с IntlProvider, FormattedMessage, useIntl, формата за ICU съобщения и автоматизирани преводи.

Вместо това използвате react-i18next? Вижте ръководството ни за react-i18next

1

Инсталирайте react-intl

react-intl е част от проекта FormatJS. Той предоставя React компоненти и hooks за форматиране на низове, числа, дати и форми за множествено число чрез стандарта ICU MessageFormat.

Освен React, react-intl няма други зависимости по време на изпълнение. Той използва вградения в браузъра Intl API за форматиране на числа и дати и включва собствен анализатор на ICU MessageFormat за множествено число, select и форматиран текст.
Terminal
npm install react-intl
2

Конфигурирайте IntlProvider

Обвийте приложението си с IntlProvider в корена. Подайте активния локал и плосък обект messages. След това всеки вложен компонент ще има достъп до преводите чрез FormattedMessage или 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 изисква плосък обект от двойки ключ–стойност за съобщенията (например { "app.greeting": "Hello" }). Вложеният JSON трябва да бъде преобразуван в плоска структура, преди да бъде подаден на IntlProvider. Можете също да използвате помощна библиотека като flat за преобразуването.

Файлове със съобщения

Създайте по един JSON файл за всеки локал. react-intl използва директно синтаксиса ICU MessageFormat — множественото число, select и променливите се задават в самите низове на съобщенията.

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"
}
За по-добра организация използвайте идентификатори, разделени с точки, като „nav.home“. За разлика от react-i18next, react-intl очаква плосък обект със съобщения — преобразуват се ключовете, а не структурата.
3

Използвайте преводите в компонентите

react-intl Ви предоставя два основни API: компонента FormattedMessage за показване на преведен JSX и hook-а useIntl за императивен достъп (заместващ текст, aria етикети и програмно форматиране).

Компонентът FormattedMessage

Използвайте FormattedMessage за декларативни преводи в JSX. Подайте идентификатора на съобщението и всички стойности за интерполация. Компонентът показва директно преведения низ.

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>
  );
}

Hook-ът useIntl

Използвайте useIntl(), когато Ви е необходим преведеният низ като обикновена стойност — за заместващ текст в полета за въвеждане, aria-labels, document.title или при подаване на низове към API извън React. Той предоставя и formatNumber, formatDate и 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>
  );
}

Форматиран текст (HTML в преводите)

Вграждайте JSX в преводите чрез тагове, подобни на XML, в низовете на съобщенията. Подайте обработчиците на тагове чрез свойството values, за да показвате връзки, удебелен текст или произволен React компонент в преведено съобщение.

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 създава React Fragment. Ако Ви е необходим конкретен обгръщащ елемент, подайте свойството textComponent на IntlProvider или обвийте FormattedMessage със собствен елемент.

Извличане на съобщения с @formatjs/cli

FormatJS предоставя CLI за автоматично извличане на идентификаторите на съобщения от изходния Ви код в JSON файл. Така файлът със съобщения остава синхронизиран с компонентите Ви без ръчно проследяване.

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

Множествено число и ICU Select

react-intl използва директно ICU MessageFormat. Множественото число, select според рода и вложеното форматиране се задават направо в низовете на съобщенията — не са необходими суфикси или отделни ключове.

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}個の商品があります"
}
Никога не задавайте логиката за множествено число ръчно в JavaScript. Езици като арабския имат 6 форми за множествено число, френският третира 0 като единствено число, а японският не разграничава единствено от множествено число. Оставете ICU MessageFormat да приложи правилата — подайте само стойността за брой.

ICU Select за род и роли

Използвайте синтаксиса ICU select за зависими от контекста преводи, например според рода, потребителската роля или стойността на състоянието. Изразът select избира правилния вариант според подадената стойност.

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 }}
/>

Автоматизирайте контрола на качеството на преводите

Откривайте липсващи ключове и повредени заместващи параметри с i18n-validate, преди да достигнат до потребителите. Тествайте интерфейса си с псевдопреводи чрез i18n-pseudo, преди да са готови истинските преводи.

Често срещани затруднения

Прекомерно разчитане на defaultMessage

defaultMessage е резервен вариант за разработка, а не стратегия за превод. Ако използвате defaultMessage за всички низове, резултатът от извличането ще съдържа английския текст, но преводачите може да пропуснат нови ключове. Винаги извличайте и поддържайте пълен файл за изходния локал.

Вложени обекти вместо плоски ключове

IntlProvider очаква плосък Record&lt;string, string&gt; за messages. Ако подадете вложен JSON като { nav: { home: "Home" } }, react-intl няма да намери ключа „nav.home“. Преобразувайте съобщенията в плоска структура, преди да ги подадете, или използвайте библиотека като flat.

IntlProvider предизвиква повторно изобразяване

Ако създавате обекта messages непосредствено във функцията за изобразяване, при всяко изобразяване IntlProvider получава нова препратка към обект и всички зависими компоненти се изобразяват отново. Мемоизирайте обекта messages чрез useMemo или го дефинирайте извън компонента.

Липсващ IntlProvider в тестовете

Компонентите, които използват FormattedMessage или useIntl, ще хвърлят изключение, ако бъдат изобразени без родителски IntlProvider. В тестовете обвийте компонента си с IntlProvider с locale="en" и празен или минимален обект messages.

Препоръчителна файлова структура

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

Изпробвайте i18n Agent сега

Пуснете тук Вашия файл за превод

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

или натиснете, за да изберете файл

Целеви езици

Не се изисква регистрацияНезабавна оценка

Резервни локали с react-intl-locale-chain

Когато липсва ключ за превод в регионален локал като pt-BR, react-intl преминава директно към локала по подразбиране, вместо първо да провери родителския локал pt.

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>

Вижте нашето ръководство за резервни локали с пълния списък на поддържаните софтуерни рамки и 75 вградени вериги. Learn more →

Често задавани въпроси