В экосистеме FormatJS обратная совместимость рассматривается как
сочетание стабильности формата сообщений, предсказуемости API и
контролируемой эволюции библиотек для интернационализации. Основная цель
заключается в том, чтобы приложения, однажды внедрившие ICU
MessageFormat и инфраструктуру форматирования, могли обновлять версии
библиотек без переписывания текстов, шаблонов и значительной части
логики локализации.
Ключевым элементом совместимости выступает ICU MessageFormat.
Синтаксис сообщений в FormatJS опирается на стандарт ICU, который
изначально проектировался как кросс-языковая система форматирования.
Базовая устойчивость
синтаксиса
Сообщения вида:
Hello, {name}!
или более сложные конструкции:
{count, plural,
one {# item}
other {# items}
}
сохраняют совместимость между версиями библиотек, поскольку:
- синтаксис ICU стабилен на уровне спецификации;
- изменения происходят в реализации парсера, а не в языке
сообщений;
- поведение форматирования чисел, дат и множественных форм привязано к
Unicode CLDR.
CLDR как источник
неизменяемых правил
Библиотека использует данные Unicode CLDR для правил локализации. Это
означает:
- изменение языка не требует изменения сообщений;
- обновления CLDR не ломают существующие шаблоны;
- корректировки касаются только данных, а не API.
Внутренние пакеты runtime (например, intl-messageformat)
развиваются с учётом строгих контрактов:
- вход: строка ICU-сообщения + набор переменных;
- выход: локализованная строка;
- побочные эффекты отсутствуют.
Это позволяет обеспечивать совместимость даже при изменении
внутренних алгоритмов форматирования.
Изоляция внутреннего парсера
Парсер сообщений может меняться между версиями, но:
- AST (абстрактное синтаксическое дерево) не экспонируется
наружу;
- публичный API остаётся неизменным;
- сериализация сообщений обратно в строку не требуется.
Совместимость
React-интеграции
В связке с React широко используется React Intl, который является
обёрткой над core FormatJS API.
Модель неизменяемых
компонентов
Компоненты:
<FormattedMessage id="app.title" defaultMessage="Hello world" />
сохраняют поведение между версиями благодаря следующим принципам:
id остаётся ключевым контрактом;
defaultMessage используется как fallback без
зависимости от сборки;
- форматирование происходит через стабильный runtime.
Минимизация breaking changes
При переходах между major-версиями:
- изменения чаще касаются TypeScript типов, а не runtime;
- устаревшие API помечаются deprecated перед удалением;
- сохранение поведения форматирования считается приоритетом.
Обратная
совместимость и polyfill-стратегия
Одним из критических факторов является поддержка Intl в
JavaScript.
Нативный Intl vs polyfill
FormatJS использует:
- нативный
Intl в современных средах;
- полифиллы для старых браузеров и Node.js окружений.
Типичная схема:
- если
Intl.PluralRules отсутствует → подключается
polyfill;
- если
Intl.NumberFormat ограничен → расширяется
shim-реализацией.
Контроль версий polyfill
Пакеты вида @formatjs/intl-* проектируются так,
чтобы:
- не конфликтовать с нативными реализациями;
- не переопределять API без необходимости;
- включаться только при отсутствии поддержки.
Совместимость при
сборке и транспиляции
Система сборки сообщений через Babel и CLI-инструменты играет
ключевую роль в стабильности.
Инструменты извлечения сообщений:
- анализируют исходный код;
- формируют JSON-структуры сообщений;
- не зависят от runtime-версии FormatJS.
Пример результата:
{
"app.greeting": {
"defaultMessage": "Hello {name}",
"description": "Greeting message"
}
}
Эта структура сохраняется между версиями CLI.
Версионирование и
стратегия изменений
Экосистема придерживается semver-подхода:
- patch: исправления форматирования, багфиксы CLDR;
- minor: добавление новых функций без изменения поведения;
- major: потенциально breaking изменения API.
Контракт на поведение
сообщений
Основное правило совместимости:
- одинаковое сообщение должно давать одинаковый результат
форматирования при одинаковых входных данных.
Даже при внутренних изменениях алгоритмов результат нормализуется под
CLDR-правила.
Совместимость между
браузерами и Node.js
Различия окружений
Проблемы обратной совместимости часто возникают не в самой
библиотеке, а в среде выполнения:
- разные версии Node.js имеют разные уровни Intl поддержки;
- старые браузеры требуют полифиллов;
- server-side rendering может использовать ICU-lite сборки.
Унификация поведения
FormatJS компенсирует различия:
- единая точка форматирования;
- детектирование возможностей окружения;
- fallback-цепочки для Intl API.
Стабильность типов и
TypeScript-слой
В TypeScript-экосистеме обратная совместимость поддерживается
через:
- расширяемые интерфейсы сообщений;
- генерацию типов из JSON каталогов;
- минимизацию breaking changes в типах props.
Пример типовой структуры:
type Messages = {
"app.title": string;
"app.count": number;
};
Изменения в типах происходят аккуратно, чтобы не ломать существующие
проекты при обновлении minor-версий.
FormatJS расширяет ICU, добавляя:
- вложенные форматтеры;
- селекторы;
- кастомные форматы дат и чисел.
Несмотря на расширения:
- базовый ICU синтаксис не изменяется;
- расширения добавляются как надстройки;
- старые сообщения продолжают корректно интерпретироваться.
Обратная
совместимость и кэширование сообщений
В продакшн-системах используется кэширование:
- сериализованные сообщения;
- precompiled ICU AST;
- локализованные словари.
FormatJS обеспечивает:
- стабильность структуры AST между версиями;
- возможность повторного использования кэша;
- отсутствие зависимости кэшированных данных от
runtime-реализации.
Миграции без нарушения
контрактов
Эволюция между версиями сопровождается механиками мягкой
миграции:
- сохранение старых API параллельно с новыми;
- постепенное отключение legacy-функций;
- поддержка dual-mode поведения в переходный период.
Типичный сценарий:
- старая версия продолжает работать с существующими сообщениями;
- новая версия добавляет расширенные возможности форматирования;
- проект мигрирует без изменения текстовых ресурсов.
Совместимость локалей и
данных CLDR
CLDR обновляется регулярно, что влияет на:
- правила множественных форм;
- форматирование дат;
- валютные обозначения.
FormatJS минимизирует риск несовместимости:
- обновления CLDR не изменяют API;
- изменения локалей отражаются только в результатах
форматирования;
- поведение старых сообщений остаётся корректным.
Контракт стабильности
форматирования
Главный принцип совместимости можно выразить как:
- сообщение является декларацией намерения;
- runtime является интерпретатором;
- результат зависит от локали и входных данных, но не от версии API в
пределах совместимого диапазона.
Это позволяет сохранять предсказуемость поведения при обновлениях
библиотек и инфраструктуры интернационализации.