Эволюция API и причины
несовместимости
Библиотека Globalize в экосистеме JavaScript прошла несколько этапов
развития, каждый из которых сопровождался существенными изменениями
архитектуры и API. Наиболее заметный разрыв связан с переходом от
версии, основанной на форматировании через локальные данные jQuery UI, к
современной реализации, использующей стандартизированные данные CLDR
(Unicode Common Locale Data Repository).
Ключевые причины несовместимости между версиями:
- переход от частично встроенных локалей к полной зависимости от
CLDR;
- отказ от синхронной загрузки локализационных данных в пользу
модульной структуры;
- изменение модели форматирования (строки формата заменены на
ICU-подобные паттерны);
- пересмотр API чисел, дат и валют;
- переход на явную инициализацию локалей вместо неявного
поведения.
Каждое из этих изменений направлено на повышение предсказуемости и
соответствие международным стандартам, однако приводит к необходимости
адаптации существующего кода.
Основные поколения
Globalize и точки разрыва
Globalize до версии 0.x
Ранние версии ориентировались на интеграцию с jQuery и использовали
упрощённую модель локализации:
- данные локали часто встраивались частично;
- форматирование дат и чисел выполнялось через ограниченный набор
шаблонов;
- отсутствовала строгая зависимость от CLDR;
- поведение было тесно связано с браузерной средой.
Типичный код:
$.global.format(1234.56, "n2");
$.global.format(new Date(), "D");
Проблемы данной модели:
- отсутствие единых правил локализации;
- ограниченная поддержка региональных особенностей;
- невозможность масштабирования на большое количество языков;
- зависимость от jQuery как обязательного слоя.
Globalize 1.x и переход к
CLDR
С версии 1.x архитектура была полностью переработана. Основой стала
библиотека CLDR, предоставляющая стандартизированные данные о
локалях.
Основные изменения:
- отказ от jQuery-зависимости;
- введение явной загрузки CLDR-данных;
- разделение функциональности на модули;
- использование ICU-подобных шаблонов;
- асинхронная подготовка окружения локали.
Пример современного подхода:
Globalize.load(
require("cldr-data").entireSupplemental(),
require("cldr-data").entireMainFor("ru")
);
Несовместимость
API как структурная особенность
Изменение модели
инициализации
Старый подход допускал неявную локализацию:
- локаль определялась автоматически;
- данные могли подгружаться частично;
- поведение зависело от окружения.
Современная модель требует явной подготовки:
Globalize.locale("ru");
Перед этим необходимо загрузить соответствующие CLDR-данные.
Отсутствие данных приводит к исключениям или деградации
функциональности.
Форматы чисел
Существенные изменения затронули форматирование чисел.
Ранее:
$.global.format(12345.67, "n2");
Современный вариант:
Globalize.numberFormatter({ minimumFractionDigits: 2 })(12345.67);
Различия:
- строковые паттерны заменены объектами конфигурации;
- добавлена поддержка расширенных правил округления;
- поведение строго привязано к локали;
- устранены неоднозначности форматов.
Форматы дат
Старые версии использовали фиксированные обозначения:
Новая модель опирается на CLDR:
Globalize.dateFormatter({ datetime: "short" })(new Date());
Изменения:
- унификация форматов между языками;
- разделение date, time и datetime;
- расширенная настройка календарей;
- поддержка нестандартных локалей.
Стратегии
обеспечения обратной совместимости
Обёртки над старым API
Один из подходов заключается в создании адаптеров, имитирующих старое
поведение поверх новой версии.
Пример концептуальной обёртки:
function formatNumberLegacy(value, format) {
if (format === "n2") {
return Globalize.numberFormatter({ minimumFractionDigits: 2 })(value);
}
}
Такие адаптеры:
- снижают затраты на миграцию;
- позволяют поэтапно заменять устаревший код;
- увеличивают поддерживаемость старых проектов.
Миграционные слои
В крупных приложениях используется промежуточный слой
локализации:
- единая точка доступа к форматированию;
- изоляция зависимости от Globalize;
- возможность замены реализации без изменения бизнес-кода.
Пример структуры:
/i18n
formatter.js
date.js
number.js
Этот слой:
- скрывает различия версий;
- позволяет тестировать локализацию отдельно;
- упрощает поддержку нескольких библиотек.
Поддержка параллельных
версий
В некоторых системах допускается одновременное использование старой и
новой версии Globalize:
- legacy-модули используют старый API;
- новые модули переходят на CLDR-основу;
- общий слой маршрутизации определяет, какая версия используется.
Риски такого подхода:
- увеличение размера бандла;
- дублирование локализационных данных;
- усложнение отладки.
Проблемы миграции между
версиями
Несовпадение форматов
Одной из наиболее частых проблем становится различие в интерпретации
форматов:
- старые паттерны не имеют прямых аналогов;
- поведение округления может отличаться;
- разные правила разделителей тысяч и десятичных знаков.
Отсутствие
автоматического преобразования
Переход между API не поддерживает автоматическую трансляцию:
- строковые форматы не конвертируются в ICU-паттерны;
- конфигурационные объекты требуют ручной настройки;
- поведение локали зависит от загруженных CLDR-данных.
Различия в загрузке данных
Старый подход:
- локали часто включены в сборку;
- нет строгой структуры данных.
Новый подход:
- обязательная загрузка main + supplemental данных CLDR;
- строгая зависимость от версии данных;
- необходимость синхронизации версий CLDR и Globalize.
Подходы к снижению затрат
на переход
Инкапсуляция форматирования
Выделение всех операций локализации в отдельный слой позволяет:
- ограничить распространение устаревших API;
- централизовать изменения;
- упростить тестирование.
Использование фасадов
Фасадный слой скрывает различия между версиями:
const i18n = {
formatNumber: (value) => Globalize.numberFormatter()(value),
formatDate: (date) => Globalize.dateFormatter()(date)
};
Фасады обеспечивают:
- стабильный интерфейс;
- независимость бизнес-логики;
- возможность замены реализации.
Инкрементальная миграция
Миграция выполняется поэтапно:
- выделение модулей локализации;
- замена форматирования чисел;
- переход на даты;
- финальное удаление legacy-слоя.
Каждый этап снижает риск регрессий и упрощает контроль изменений.
Влияние
обратной совместимости на архитектуру приложений
Переход между версиями Globalize оказывает влияние на структуру
приложения:
- усиливается модульность;
- вводится явная зависимость от локализационного слоя;
- уменьшается количество неявных глобальных состояний;
- повышается предсказуемость поведения в разных регионах.
Архитектура становится более строгой, но требует дисциплины при
управлении зависимостями и локализационными данными.