Руководство по React Intl: локализация React‑приложений
О чём эта статья
В этой инструкции кратко и последовательно показано, как установить и применять React Intl, как организовать файлы переводов, как форматировать строки, числа и даты, а также какие практики и проверки помогут избежать распространённых ошибок. Включены чек‑листы для разработчика, переводчика и QA, готовые примеры кода и рекомендации по миграции и безопасности.
Когда использовать React Intl
React Intl хорошо подходит, если вам нужно:
- Локализовать UI‑тексты и шаблоны с плейсхолдерами.
- Форматировать числа, валюты, проценты и даты в соответствии с локалью.
- Централизованно управлять набором сообщений и fallback‑локалью.
Когда не подходит:
- Если ваша цель — динамическая загрузка переводов на лету (lazy-load) с очень сложной логикой, возможно, подойдёт сочетание React Intl с внешними загрузчиками или альтернативные библиотеки (см. раздел “Альтернативы”).
Быстрые определения
- i18n — интернационализация, процесс подготовки приложения к локализации.
- Локаль (locale) — строка вида “en”, “fr” или “ru-RU”, влияющая на форматирование.
Установка React Intl
React Intl доступен через npm, yarn или pnpm. Пример для npm:
npm install react-intl
Для yarn:
yarn add react-intl
(Исходные блоки сохранены — используйте менеджер пакетов по вашей политике.)
Базовый рабочий поток
- Создать файлы переводов (по локалям).
- Обернуть корневой компонент приложения в IntlProvider и передать locale, defaultLocale и messages.
- Использовать FormattedMessage, FormattedNumber, FormattedDate или API‑хуки для вывода локализованных данных.
Файлы переводов
Файл переводов — это объект с парами ключ → строка. Строки могут содержать плейсхолдеры вида {name}.
Пример (как в исходнике):
export const messagesInFrench = {
greeting: "Bonjour {name}"
}
export const messagesInItalian = {
greeting: "Buongiorno {name}"
}
Советы:
- Используйте единую конвенцию ключей (например, namespace.module.key).
- Для сложных шаблонов применяйте ICU‑форматирование (поддерживается React Intl).
- Храните переводы в отдельной папке /locales и разделяйте по языкам.
IntlProvider — настройка контекста
IntlProvider передаёт локаль и сообщения всему приложению.
Пример обёртки корня (сохранён исходный код):
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { IntlProvider } from "react-intl";
import { messagesInFrench } from "./translation";
ReactDOM.createRoot(document.getElementById("root")).render(
);
Практика: определяйте locale динамически (из настроек пользователя или navigator.language) и загружайте messages лениво для больших приложений.
Пример динамического выбора локали (шаблон):
const browserLocale = navigator.language || navigator.userLanguage || 'en';
const supported = ['en', 'fr', 'it', 'ru'];
const locale = supported.includes(browserLocale.split('-')[0]) ? browserLocale : 'en';
// Затем подгружаем соответствующие messages (sync или async)FormattedMessage — перевод строк
FormattedMessage выводит строку из messages по id. Он поддерживает defaultMessage и values.
Исходный пример сохранён:
import React from "react";
import { FormattedMessage } from "react-intl";
function App() {
return (
);
}
export default App;
Советы:
- Всегда указывайте defaultMessage для fallback и удобства работы переводчиков.
- Для сложной логики (множественные формы, plural) используйте ICU‑синтаксис в сообщениях.
Пример ICU‑plural:
const messages = {
items: "You have {count, plural, =0 {no items} one {# item} other {# items}}"
};Форматирование чисел — FormattedNumber
FormattedNumber форматирует числа по локали. Исходный пример:
import React from "react";
import { FormattedNumber } from "react-intl";
function App() {
return (
Decimal:
Percent:
);
}
export default App;
Локализация примера для российского рынка (пример с RUB):
import { FormattedNumber } from 'react-intl';
// В компоненте
Пояснения:
- style: “decimal” | “percent” | “currency”.
- currency: ISO‑код валюты (RUB, USD, EUR и т.д.).
- minimumFractionDigits / maximumFractionDigits — управление точностью.
Форматирование дат — FormattedDate
FormattedDate форматирует даты и время по локали. Исходный пример:
import React from "react";
import { FormattedDate } from "react-intl";
function App() {
const today = new Date();
return (
Today's date is
);
}
export default App;
Пример показа времени:
Поддерживаемые опции (кратко): year, month, day, hour, minute, second, timeZoneName. Значения: “numeric”, “2-digit”, “short”, “long”, “narrow”.
Практики структуры переводов
- Разделяйте по функциональным областям: common, auth, dashboard.
- Не дублируйте тексты — используйте ключи.
- Версионируйте файлы переводов при изменениях UI.
Когда React Intl может не подойти
- Если нужен полностью серверный рендер с поздней загрузкой переводов, потребуются дополнительные шаги синхронизации между сервером и клиентом.
- Для проектов с очень динамическим редактированием перевода напрямую в UI может быть удобнее headless‑решение с CMS для переводов.
Альтернативы и сочетания
- i18next — более богат функционалом для загрузки переводов, но требует адаптации под ICU.
- FormatJS — набор инструментов, часть экосистемы, откуда пришёл react-intl.
Выбор: React Intl удобен, если приоритет — корректное форматирование чисел/дат/валют и поддержка ICU. Для сложных workflow перевода можно комбинировать React Intl с системой управления переводами (TMS).
Чек‑лист по ролям
Разработчик:
- Установить react-intl и настроить IntlProvider.
- Организовать /locales и конвенцию ключей.
- Предусмотреть динамическую подгрузку messages.
- Добавить unit‑тесты для ключевых сообщений.
Переводчик / Локализатор:
- Получить список ключей и контекст (скриншоты).
- Проверить плейсхолдеры и ICU‑формат.
- Протестировать строки в UI на предмет переноса строк и длины.
QA:
- Проверить fallback (defaultMessage) на отсутствующие переводы.
- Проверить формат чисел/дат/валют для целевых локалей.
- Тестировать RTL (если применимо) и адаптивность верстки.
Мини‑методология внедрения (4 шага)
- Инвентаризация: найти все «жёстко закодированные» строки.
- Экстракция: вынести строки в messages с ключами и defaultMessage.
- Интеграция: подключить IntlProvider и заменить строки на FormattedMessage.
- Тестирование: проверка локалей, edge‑cases, fallback.
Тесты и критерии приёмки
- Все видимые тексты используют FormattedMessage или эквивалент.
- Числа и даты корректно форматируются для ru и en.
- При отсутствии перевода отображается defaultMessage.
- Переключение локали работает без перезагрузки (если заявлено).
Миграция и совместимость
- При миграции с другой библиотеки: сперва подготовьте экспорт ключей и defaultMessage.
- Для SSR: обеспечьте одинаковый locale и messages на сервере и клиенте.
- Следите за версией Intl в браузерах: современные браузеры поддерживают Intl API, но для старых может потребоваться полифилл.
Безопасность и приватность
- Не включайте в сообщения персональные данные — передавайте данные через values и форматируйте на месте.
- Сообщения не должны содержать секретных ключей или чувствительных данных.
Типичные ошибки и как их избежать
- Забыт defaultMessage → создаёт пустые строки в UI.
- Дублирование ключей → затрудняет работу переводчиков.
- Форматирование чисел/валют без указания currency → неверное представление для других локалей.
- Надёжное решение: добавить линтер для i18n‑ключей и CI‑проверки наличия defaultMessage.
Decision flow (простое дерево выбора)
flowchart TD
A[Нужно локализовать UI?] -->|Да| B{Есть ли ICU шаблоны?}
B -->|Да| C[Использовать react-intl]
B -->|Нет| D[Можно использовать простую ключ‑систему]
C --> E{Требуется ленивый импорт?}
E -->|Да| F[Подгружать messages асинхронно]
E -->|Нет| G[Хранить messages в bundle]
A -->|Нет| H[Нет действий]Справочный мини‑глоссарий
- Locale — обозначает языковую и региональную настройку.
- Messages — объект с сообщениями для локали.
- ICU — формат сообщений, поддерживающий plural, select и пр.
Короткий пример локализации с динамической загрузкой
// Примерный паттерн (pseudo-code)
const loadMessages = async (locale) => {
switch (locale) {
case 'fr': return (await import('./locales/fr.json')).default;
case 'ru': return (await import('./locales/ru.json')).default;
default: return (await import('./locales/en.json')).default;
}
};
function AppRoot() {
const [messages, setMessages] = React.useState(null);
const locale = getUserLocale();
React.useEffect(() => {
loadMessages(locale).then(setMessages);
}, [locale]);
if (!messages) return Loading…;
return (
);
}Резюме
React Intl даёт набор инструментов для корректной локализации UI: управление сообщениями, форматирование чисел, валют и дат в соответствии с локалью. Правильная организация файлов переводов, использование defaultMessage и тесты гарантируют надёжную локализацию. При больших кодовых базах применяйте ленивую загрузку сообщений и добавьте автоматическую проверку наличия ключей.
Важно
- Тестируйте локали в условиях, приближённых к реальному использованию (разная длина строк, RTL, разные форматы дат).
Ключевые шаги
- Инвентаризуйте строки → Экспортируйте в messages → Настройте IntlProvider → Замените на Formatted* → Тестируйте.
Краткий чек‑лист
- defaultMessage указан
- Плейсхолдеры корректны и безопасны
- Тесты покрывают переключение локали
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone