Интеграция начинается с установки ядра экосистемы FormatJS для React — пакета интернационализации, обеспечивающего форматирование строк, чисел, дат и управление словарями сообщений через ICU-синтаксис.
Основные зависимости:
npm install react-intl
В современных проектах часто требуется дополнительная настройка Babel или TypeScript для извлечения сообщений и строгой типизации, но базовый слой строится вокруг провайдера контекста и компонентов форматирования.
Ключевой элемент архитектуры — провайдер локали, который передаёт текущий язык и набор сообщений всем вложенным компонентам.
Вся система интернационализации в React строится вокруг компонента провайдера контекста:
import { IntlProvider } from "react-intl";
const messages = {
ru: {
welcome: "Добро пожаловать",
items: "У вас {count} сообщений"
}
};
function App() {
return (
<IntlProvider locale="ru" messages={messages.ru}>
<Root />
</IntlProvider>
);
}
IntlProvider решает три задачи:
locale)messages)При изменении языка компонент вызывает повторный рендер всего дерева, что делает локализацию реактивной частью состояния приложения.
FormatJS использует ICU MessageFormat — стандарт описания интернационализированных строк.
Пример базового сообщения:
{
"greeting": "Привет, {name}"
}
Сообщения могут содержать:
Пример с условиями:
{
"notifications": "У вас {count, plural, one {# уведомление} few {# уведомления} many {# уведомлений} other {# уведомления}}"
}
ICU-синтаксис позволяет избежать ручного управления грамматическими правилами языка и переносит логику в слой форматирования.
Современный способ работы с переводами основан на хуке:
import { useIntl } from "react-intl";
function Header() {
const intl = useIntl();
return (
<h1>
{intl.formatMessage({ id: "welcome" })}
</h1>
);
}
useIntl предоставляет объект с методами:
formatMessageformatNumberformatDateformatTimeformatRelativeTimeТакой подход исключает необходимость прокидывания props через дерево компонентов.
Для декларативного использования сообщений применяется компонент:
import { FormattedMessage } from "react-intl";
function Profile({ name }) {
return (
<FormattedMessage
id="greeting"
values={{ name }}
/>
);
}
Особенности:
idПри необходимости можно использовать render-prop стиль:
<FormattedMessage id="greeting">
{(text) => <span>{text}</span>}
</FormattedMessage>
FormatJS оборачивает нативный Intl.NumberFormat,
обеспечивая единообразное API:
const intl = useIntl();
intl.formatNumber(123456.78, {
style: "currency",
currency: "RUB"
});
Использование компонента:
import { FormattedNumber } from "react-intl";
<FormattedNumber
value={1000}
style="currency"
currency="USD"
/>
Поддерживаются режимы:
import { FormattedDate } from "react-intl";
<FormattedDate
value={Date.now()}
year="numeric"
month="long"
day="2-digit"
/>
Через useIntl:
intl.formatDate(new Date(), {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
Аналогично доступно форматирование времени:
intl.formatTime(new Date(), {
hour: "2-digit",
minute: "2-digit"
});
ICU plural rules зависят от локали и автоматически применяются:
intl.formatMessage(
{ id: "cart.items" },
{ count: 5 }
);
Пример сообщения:
{
"cart.items": "В корзине {count, plural, one {# товар} few {# товара} many {# товаров} other {# товара}}"
}
Система учитывает правила языка без дополнительной логики в коде.
FormatJS поддерживает HTML-подобные конструкции внутри сообщений:
{
"terms": "Я принимаю <link>условия использования</link>"
}
Рендер:
<FormattedMessage
id="terms"
values={{
link: (chunks) => <a href="/terms">{chunks}</a>
}}
/>
Это позволяет безопасно внедрять интерактивные элементы в переводимые строки без ручного HTML.
Архитектура предполагает хранение словарей по языкам:
const messages = {
en: { welcome: "Welcome" },
ru: { welcome: "Добро пожаловать" }
};
Переключение реализуется через состояние:
const [locale, setLocale] = useState("ru");
<IntlProvider locale={locale} messages={messages[locale]}>
<App />
</IntlProvider>
При смене locale React пересобирает дерево с новыми
переводами.
intl.formatRelativeTime(-1, "day");
Результаты зависят от локали:
Компонент:
import { FormattedRelativeTime } from "react-intl";
<FormattedRelativeTime value={-3} unit="day" />
При работе с большими приложениями важны следующие аспекты:
messages на каждый рендерПример стабилизации объектов:
const messages = useMemo(() => loadMessages(locale), [locale]);
Server-Side Rendering требует синхронизации локали между сервером и клиентом.
На сервере:
import { renderToString } from "react-dom/server";
const html = renderToString(
<IntlProvider locale="ru" messages={messages.ru}>
<App />
</IntlProvider>
);
На клиенте важно использовать те же данные, чтобы избежать расхождения гидратации:
В крупных проектах применяется строгая типизация ключей сообщений:
type MessageIds = "welcome" | "cart.items";
const messages: Record<MessageIds, string> = {
welcome: "Добро пожаловать",
cart.items: "Товары в корзине"
};
Дополнительно возможно генерировать типы через Babel-плагины FormatJS для автоматической синхронизации ключей.
React выступает базовой платформой для построения интерфейсов, а система интернационализации FormatJS расширяет её слой представления, отделяя текстовую логику от компонентов.
React Intl интегрируется через контекст React и формирует единый слой управления локализацией без необходимости внешних сервисов или ручной обработки языковых правил.
Такое разделение обеспечивает: