Полифиллы

Современная библиотека интернационализации Globalize опирается на несколько уровней стандартов: ECMAScript Internationalization API (Intl), форматирование дат и чисел, а также структурированные языковые данные CLDR (Unicode Common Locale Data Repository). Полифиллы становятся связующим слоем, обеспечивающим одинаковое поведение в средах, где часть этих стандартов отсутствует или реализована частично.

Основная задача полифиллов в контексте Globalize заключается не в расширении функциональности библиотеки, а в выравнивании базового окружения выполнения. В результате код интернационализации становится предсказуемым независимо от версии браузера или версии Node.js.


Зависимость Globalize от стандартов ECMAScript и CLDR

Globalize не реализует собственные алгоритмы локализации «с нуля». Вместо этого используется комбинация:

  • стандартного API Intl (если доступен),
  • структурированных данных CLDR,
  • собственных модулей форматирования и парсинга.

CLDR выступает ключевым источником локализационных правил: форматы дат, чисел, валют, правил плюрализации и отображения текстов. Однако CLDR сам по себе не является исполняемым API — это данные, которые необходимо загрузить и интерпретировать.

Именно здесь появляется необходимость в полифиллах: они обеспечивают наличие базовых API, на которые Globalize опирается при обработке этих данных.


Intl как основной объект полифилинга

В современных средах Intl является встроенным объектом, но его поддержка исторически была неполной. Особенно это касается:

  • Intl.NumberFormat
  • Intl.DateTimeFormat
  • Intl.Collator
  • локализованных календарей и валют

Globalize использует Intl как ускоренный путь выполнения операций форматирования, а при его отсутствии переключается на CLDR-основанную реализацию.

Типичная стратегия выглядит следующим образом:

  1. Проверяется наличие Intl
  2. При наличии используется нативная реализация
  3. При отсутствии подключается полифилл

Подключение полифиллов Intl

В проектах, где требуется поддержка старых окружений, используется отдельный пакет:

npm install intl

Далее полифилл подключается до инициализации Globalize:

import 'intl';
import 'intl/locale-data/jsonp/ru';

import Globalize from 'globalize';

После подключения становится доступным базовый набор форматтеров, которые Globalize может использовать как ускоренную ветку выполнения.


Полифиллы ECMAScript как базовый слой совместимости

Globalize сам по себе не требует полного набора ES6+ возможностей, однако экосистема вокруг него (webpack-бандлы, загрузка CLDR, динамические импорты) часто использует современные API.

Поэтому в реальных проектах подключаются дополнительные полифиллы:

  • core-js — для Promise, Map, Set, Array.from
  • regenerator-runtime — для генераторов и async/await в старых средах

Пример базовой инициализации окружения:

import 'core-js/stable';
import 'regenerator-runtime/runtime';

Эти полифиллы не являются частью Globalize, но критичны для корректной загрузки CLDR и асинхронной инициализации локализационных данных.


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

В Node.js наличие Intl зависит от версии среды и сборки ICU. В минимальных сборках Node могут отсутствовать полноценные локали, что приводит к деградации форматирования.

В браузерах ситуация аналогична: старые версии Safari и Android WebView имеют частичную поддержку Intl.

Globalize учитывает эти различия следующим образом:

  • при наличии полноценного Intl используется его реализация
  • при частичной поддержке применяется CLDR-ветка
  • при отсутствии Intl активируется полифилл

Сборка через Webpack и влияние полифиллов

В современных сборках 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);
}

В этом сценарии полифиллы становятся частью динамической загрузки среды, а не статической инициализации.


Взаимодействие Globalize с отсутствующими API

При отсутствии Intl Globalize не ломается, поскольку архитектура библиотеки изначально рассчитана на fallback-механизмы.

Основные сценарии деградации:

  • форматирование чисел через CLDR вместо Intl.NumberFormat
  • форматирование дат через CLDR вместо Intl.DateTimeFormat
  • ручная обработка локалей без ICU-данных

Такой дизайн делает полифиллы не дополнительной опцией, а обязательным элементом стабильной работы в старых окружениях.


Типовые ошибки при работе с полифиллами

На практике ошибки возникают не в Globalize, а в порядке и полноте подключения зависимостей:

  • загрузка CLDR до инициализации Globalize
  • отсутствие likelySubtags, из-за чего не определяется локаль
  • частичная загрузка numbers или ca-gregorian
  • конфликт версий Intl и его полифилла
  • отсутствие regenerator-runtime при асинхронной загрузке данных

Эти проблемы приводят к неконсистентному форматированию, особенно в многоязычных интерфейсах.


Производительность и издержки полифиллов

Полифиллы оказывают прямое влияние на производительность:

  • увеличивают размер бандла (core-js, intl)
  • добавляют время инициализации CLDR
  • создают дополнительные ветвления при проверке наличия Intl
  • увеличивают количество синхронных операций форматирования при отсутствии нативных API

С другой стороны, использование нативного Intl без полифиллов снижает нагрузку, но ограничивает совместимость. Globalize балансирует между этими режимами через гибкую архитектуру fallback-слоёв.


Архитектурная роль полифиллов в Globalize

Полифиллы в экосистеме Globalize выполняют три ключевые функции:

  • обеспечение совместимости с устаревшими JavaScript-движками
  • замещение отсутствующих компонентов Intl
  • поддержка асинхронной загрузки и обработки CLDR-данных

В результате формируется многоуровневая модель интернационализации, где каждый слой может быть заменён либо нативной реализацией, либо полифиллом, либо CLDR-данными в зависимости от возможностей среды выполнения.