FormatJS представляет собой набор библиотек для интернационализации, построенный вокруг ICU MessageFormat и строгой типизации сообщений. В рамках React-приложений ключевым компонентом выступает react-intl, который в версиях v2/v3 реализует разные подходы к API, контексту и работе с форматированием сообщений.
Миграция между v2 и v3 связана не только с изменением интерфейсов, но и с переходом от HOC-подхода к более гибкой модели с хуками, улучшенной типизацией и изменённой стратегией экспорта API.
В v2 основная модель потребления интернационализации строилась вокруг:
injectIntlFormattedMessageFormattedNumber, FormattedDateВ v3 добавляется и активно закрепляется функциональный стиль:
useIntlКлючевое отличие заключается в том, что доступ к API интернационализации перестаёт зависеть от обёрток высшего порядка и становится напрямую доступным внутри функциональных компонентов.
Существенное изменение:
В обеих версиях используется IntlProvider, однако
поведение контекста в v3 становится более предсказуемым и
оптимизированным для Concurrent Rendering.
Основные изменения:
localeВ v2:
<IntlProvider locale="ru" messages={messages}>
<App />
</IntlProvider>
В v3 структура сохраняется, но внутренний механизм обработки
сообщений изменяется: больше внимания уделяется стабильности ссылок на
messages и оптимизации их передачи через контекст.
В react-intl v2:
intl.formatMessage({ id: 'hello' })
В v3 сохраняется базовая сигнатура, но усиливается строгая работа с типами и кешированием результатов форматирования.
Изменения:
Компонент высшего порядка:
export default injectIntl(MyComponent);
Использование:
props.intl.formatMessage(...)
Недостатки подхода:
Функциональный доступ:
const intl = useIntl();
intl.formatMessage({ id: 'key' });
Ключевые преимущества:
FormatJS продолжает использовать ICU-синтаксис:
Пример:
{
"items": "{count, plural, one {# элемент} few {# элемента} other {# элементов}}"
}
intl.formatNumber(1000, { style: 'currency', currency: 'USD' })
В v3 улучшена:
intl.formatDate(new Date(), { year: 'numeric', month: 'long' })
Изменения:
Intl.DateTimeFormatВ обеих версиях используется:
defineMessages({
title: {
id: 'app.title',
defaultMessage: 'Заголовок'
}
});
В v3 усиливается интеграция с TypeScript и строгая типизация
id.
FormatJS активно использует Babel-плагины:
babel-plugin-react-intlФункциональность:
defaultMessageВ обеих версиях:
<IntlProvider locale="en" messages={messages}>
В v3:
Код, завязанный на HOC, требует рефакторинга в сторону hooks.
В v2 часто intl передавался через props, в v3 предпочтение отдано
прямому вызову useIntl.
Некорректные ICU-строки, ранее допускавшиеся, в v3 могут приводить к ошибкам сборки или рантайма.
Поведение кеша отличается, что может влиять на редкие кейсы динамического форматирования.
| Область | v2 | v3 |
|---|---|---|
| Доступ к intl | injectIntl | useIntl |
| Производительность | базовая | улучшенная |
| ICU валидация | мягкая | строгая |
| Типизация | ограниченная | расширенная |
| Архитектура | HOC | Hooks + context |
Основные изменения затрагивают:
В процессе миграции возможны гибридные сценарии:
react-intl v3 сохраняет обратную совместимость на уровне базовых API, однако архитектурные изменения делают постепенный переход более предсказуемым при поэтапной замене компонентов.