Современная библиотека интернационализации Globalize опирается на несколько уровней стандартов: ECMAScript Internationalization API (Intl), форматирование дат и чисел, а также структурированные языковые данные CLDR (Unicode Common Locale Data Repository). Полифиллы становятся связующим слоем, обеспечивающим одинаковое поведение в средах, где часть этих стандартов отсутствует или реализована частично.
Основная задача полифиллов в контексте Globalize заключается не в расширении функциональности библиотеки, а в выравнивании базового окружения выполнения. В результате код интернационализации становится предсказуемым независимо от версии браузера или версии Node.js.
Globalize не реализует собственные алгоритмы локализации «с нуля». Вместо этого используется комбинация:
Intl (если доступен),CLDR выступает ключевым источником локализационных правил: форматы дат, чисел, валют, правил плюрализации и отображения текстов. Однако CLDR сам по себе не является исполняемым API — это данные, которые необходимо загрузить и интерпретировать.
Именно здесь появляется необходимость в полифиллах: они обеспечивают наличие базовых API, на которые Globalize опирается при обработке этих данных.
В современных средах Intl является встроенным объектом,
но его поддержка исторически была неполной. Особенно это касается:
Intl.NumberFormatIntl.DateTimeFormatIntl.CollatorGlobalize использует Intl как ускоренный путь выполнения
операций форматирования, а при его отсутствии переключается на
CLDR-основанную реализацию.
Типичная стратегия выглядит следующим образом:
IntlВ проектах, где требуется поддержка старых окружений, используется отдельный пакет:
npm install intl
Далее полифилл подключается до инициализации Globalize:
import 'intl';
import 'intl/locale-data/jsonp/ru';
import Globalize from 'globalize';
После подключения становится доступным базовый набор форматтеров, которые Globalize может использовать как ускоренную ветку выполнения.
Globalize сам по себе не требует полного набора ES6+ возможностей, однако экосистема вокруг него (webpack-бандлы, загрузка CLDR, динамические импорты) часто использует современные API.
Поэтому в реальных проектах подключаются дополнительные полифиллы:
core-js — для Promise, Map,
Set, Array.fromregenerator-runtime — для генераторов и async/await в
старых средахПример базовой инициализации окружения:
import 'core-js/stable';
import 'regenerator-runtime/runtime';
Эти полифиллы не являются частью Globalize, но критичны для корректной загрузки CLDR и асинхронной инициализации локализационных данных.
В отличие от классических полифиллов API, CLDR выполняет роль данных, компенсирующих отсутствие встроенных локализационных правил.
Globalize требует явной загрузки CLDR-модулей:
Пример загрузки:
import Globalize from "globalize";
import likelySubtags from "cldr-data/supplemental/likelySubtags";
import currencyData from "cldr-data/supplemental/currencyData";
import plurals from "cldr-data/supplemental/plurals";
import numbers from "cldr-data/main/ru/numbers";
import currencies from "cldr-data/main/ru/currencies";
import caGregorian from "cldr-data/main/ru/ca-gregorian";
Globalize.load(
likelySubtags,
currencyData,
plurals,
numbers,
currencies,
caGregorian
);
Такой подход делает CLDR фактическим полифиллом локализационной логики, компенсируя отсутствие встроенных правил в рантайме.
В Node.js наличие Intl зависит от версии среды и сборки
ICU. В минимальных сборках Node могут отсутствовать полноценные локали,
что приводит к деградации форматирования.
В браузерах ситуация аналогична: старые версии Safari и Android
WebView имеют частичную поддержку Intl.
Globalize учитывает эти различия следующим образом:
Intl используется его
реализацияIntl активируется полифиллВ современных сборках Globalize часто используется вместе с Webpack, где полифиллы интегрируются на этапе бандлинга.
Типовая конфигурация:
module.exports = {
entry: [
'core-js/stable',
'regenerator-runtime/runtime',
'./src/index.js'
]
};
Особенность заключается в том, что CLDR JSON-данные также включаются в бандл или подгружаются лениво. Это влияет на стратегию полифиллинга: часть «данных» становится статической заменой отсутствующих системных API.
В крупных приложениях CLDR и Intl-полифиллы часто загружаются асинхронно, чтобы не увеличивать стартовый размер бандла.
Подход:
async function initLocale(locale) {
if (!global.Intl) {
await import('intl');
}
const Globalize = (await import('globalize')).default;
const cldrData = await Promise.all([
import(`cldr-data/main/${locale}/numbers`),
import(`cldr-data/main/${locale}/ca-gregorian`),
import(`cldr-data/supplemental/plurals`)
]);
Globalize.load(...cldrData);
}
В этом сценарии полифиллы становятся частью динамической загрузки среды, а не статической инициализации.
При отсутствии Intl Globalize не ломается, поскольку
архитектура библиотеки изначально рассчитана на fallback-механизмы.
Основные сценарии деградации:
Intl.NumberFormatIntl.DateTimeFormatТакой дизайн делает полифиллы не дополнительной опцией, а обязательным элементом стабильной работы в старых окружениях.
На практике ошибки возникают не в Globalize, а в порядке и полноте подключения зависимостей:
GlobalizelikelySubtags, из-за чего не определяется
локальnumbers или
ca-gregorianIntl и его полифиллаregenerator-runtime при асинхронной загрузке
данныхЭти проблемы приводят к неконсистентному форматированию, особенно в многоязычных интерфейсах.
Полифиллы оказывают прямое влияние на производительность:
IntlС другой стороны, использование нативного Intl без
полифиллов снижает нагрузку, но ограничивает совместимость. Globalize
балансирует между этими режимами через гибкую архитектуру
fallback-слоёв.
Полифиллы в экосистеме Globalize выполняют три ключевые функции:
IntlВ результате формируется многоуровневая модель интернационализации, где каждый слой может быть заменён либо нативной реализацией, либо полифиллом, либо CLDR-данными в зависимости от возможностей среды выполнения.