Компонент IntlProvider

Компонент FormatJS IntlProvider является центральным элементом архитектуры библиотеки react-intl и отвечает за передачу контекста интернационализации во всё дерево React-компонентов. Он инкапсулирует локаль, набор сообщений, параметры форматирования и дополнительные настройки, обеспечивая единообразное поведение локализации без необходимости прокидывать данные через props на каждом уровне.

IntlProvider формирует контекст, в котором выполняются все операции форматирования текста, чисел, дат и множественных форм. Он опирается на механизм React Context API и предоставляет доступ к объекту intl всем дочерним компонентам, включая FormattedMessage, useIntl, injectIntl и другие инструменты библиотеки.

Ключевая идея заключается в централизованном управлении локализацией:

  • локаль (locale) задаёт языковую и региональную специфику
  • messages содержит словарь переводов
  • formats определяет правила форматирования
  • defaultLocale используется как резервный язык
  • timeZone влияет на отображение дат и времени

Базовая структура использования

Компонент обычно располагается на верхнем уровне приложения, оборачивая корневой компонент.

import { IntlProvider } from "react-intl";

const messages = {
  greeting: "Привет, мир",
  farewell: "До свидания"
};

function App() {
  return (
    <IntlProvider locale="ru" messages={messages}>
      <Main />
    </IntlProvider>
  );
}

В этом контексте любые дочерние компоненты получают доступ к переводу без дополнительной передачи данных.

Механизм работы контекста

IntlProvider создаёт объект intl, который включает:

  • formatMessage
  • formatDate
  • formatTime
  • formatNumber
  • formatPlural
  • formatRelativeTime

Этот объект вычисляется один раз при изменении входных props и кэшируется для оптимизации производительности. Внутри используется мемоизация, чтобы предотвратить лишние пересоздания форматтеров, основанных на ICU MessageFormat.

Основные props компонента

locale

Определяет текущую локаль интерфейса. Используется всеми форматтерами для выбора правил языка.

<IntlProvider locale="en">

Значение влияет на:

  • грамматические правила множественного числа
  • формат дат и чисел
  • порядок слов в сообщениях
  • выбор fallback-стратегий

messages

Объект переводов, где ключи соответствуют идентификаторам сообщений.

const messages = {
  welcome: "Добро пожаловать",
  items: "У вас {count} товаров"
};

При изменении объекта messages происходит пересборка контекста intl.

defaultLocale

Используется как резервная локаль при отсутствии перевода в текущем наборе messages.

<IntlProvider locale="ru" defaultLocale="en">

В случае отсутствия ключа в русских переводах будет использован английский вариант.

timeZone

Определяет временную зону для форматирования дат.

<IntlProvider locale="ru" timeZone="Europe/Moscow">

Используется внутри formatDate, formatTime и formatRelativeTime.

formats

Позволяет задавать именованные правила форматирования.

const formats = {
  number: {
    currency: {
      style: "currency",
      currency: "RUB"
    }
  }
};

Используется как централизованный реестр шаблонов форматирования.

Доступ к intl через useIntl

Хотя IntlProvider сам по себе не предоставляет API для прямого использования, он является источником данных для хука useIntl.

import { useIntl } from "react-intl";

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

  return <h1>{intl.formatMessage({ id: "welcome" })}</h1>;
}

Все методы intl зависят от конфигурации, заданной в IntlProvider.

Динамическое изменение локали

При изменении props locale и messages происходит пересоздание контекста. Это позволяет реализовать переключение языка без перезагрузки приложения.

<IntlProvider locale={currentLocale} messages={currentMessages}>
  <App />
</IntlProvider>

Важно учитывать, что изменение объекта messages должно быть иммутабельным, иначе возможны лишние перерисовки.

Вложенные IntlProvider

Допускается использование нескольких провайдеров, каждый из которых переопределяет контекст в своей области дерева компонентов.

<IntlProvider locale="ru" messages={ruMessages}>
  <Page>
    <IntlProvider locale="en" messages={enMessages}>
      <Widget />
    </IntlProvider>
  </Page>
</IntlProvider>

Внутренний провайдер полностью перекрывает внешний в своей области видимости.

Поведение при отсутствии сообщений

Если ключ отсутствует в messages:

  1. Проверяется defaultLocale
  2. Если fallback отсутствует, возвращается ID сообщения
  3. Возможно применение dev-режима с предупреждением

Такой механизм предотвращает “тихие” ошибки локализации.

Производительность и оптимизация

IntlProvider оптимизирует работу через:

  • мемоизацию intl-объекта
  • кеширование ICU форматтеров
  • переиспользование объектов messages
  • ленивое создание форматтеров

Особое внимание уделяется уменьшению затрат при частом переключении локали.

Server-Side Rendering

При SSR IntlProvider используется для синхронизации локали между сервером и клиентом.

const html = renderToString(
  <IntlProvider locale="ru" messages={messages}>
    <App />
  </IntlProvider>
);

Ключевой аспект — совпадение данных на сервере и клиенте для предотвращения гидрационных расхождений.

Гидратация и согласованность состояния

При гидратации React важно, чтобы:

  • locale совпадал
  • messages были идентичны по структуре
  • formats не изменялись между сервером и клиентом

Несоответствие приводит к повторному рендеру и возможным визуальным скачкам интерфейса.

Расширенные сценарии использования

Поддержка пользовательских форматов

const formats = {
  date: {
    short: {
      year: "numeric",
      month: "short",
      day: "numeric"
    }
  }
};
<IntlProvider locale="ru" formats={formats}>

Изоляция модулей интерфейса

Отдельные части приложения могут использовать собственные локали, например виджеты или встроенные панели.

Интеграция с состоянием приложения

IntlProvider часто связывается с глобальным состоянием (Redux, Zustand, Context), где locale хранится как часть пользовательских настроек.

Обработка чисел и множественности через intl

Хотя основная роль компонента — передача контекста, он напрямую влияет на правила обработки грамматики.

Пример множественных форм:

const messages = {
  items: "У вас {count, plural, one {# товар} few {# товара} many {# товаров} other {# товара}}"
};

Форматирование зависит от locale, заданного в IntlProvider.

Влияние на дочерние компоненты

Все дочерние компоненты автоматически получают доступ к:

  • локали
  • форматтерам
  • словарю сообщений
  • функциям форматирования

Это исключает необходимость ручного прокидывания i18n-данных через props-цепочки.

Типичные ошибки конфигурации

  • передача изменяемого объекта messages без мемоизации
  • несоответствие locale и данных сообщений
  • отсутствие defaultLocale при неполных переводах
  • динамическое создание IntlProvider на каждом рендере без необходимости

Такие ошибки приводят к деградации производительности и нестабильному поведению интерфейса.