Переопределение поведения по умолчанию

Базовая модель поведения библиотеки

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

  • активной локали (Globalize.locale(...))
  • загруженных CLDR-данных
  • стандартных параметров форматирования (числа, даты, сообщения)
  • встроенных правил выбора форматов (short/long/medium и т.д.)
  • механизмов fallback при отсутствии данных

Переопределение поведения заключается в изменении одного или нескольких из этих слоёв без модификации исходного кода библиотеки.


Управление глобальной локалью как основной механизм переопределения

Ключевой точкой управления поведением является установка глобальной локали:

Globalize.locale("ru");

или переключение на другую локаль:

Globalize.locale("en");

После установки локали изменяется:

  • формат чисел (разделители, группировка)
  • формат даты и времени
  • правила множественных форм
  • шаблоны сообщений
  • порядок отображения компонентов дат

Важно: локаль является глобальным состоянием, поэтому любое изменение влияет на все последующие вызовы форматтеров и парсеров.


Переопределение поведения через конфигурацию CLDR

Библиотека не хранит локализацию внутри себя — она зависит от внешних данных CLDR. Это создаёт возможность «переопределения» через управление загрузкой данных.

Частичная загрузка CLDR

Можно загрузить только необходимые части данных, изменяя поведение системы:

Globalize.load(
  require("cldr-data/supplemental/likelySubtags"),
  require("cldr-data/main/ru/ca-gregorian"),
  require("cldr-data/main/ru/numbers")
);

Если исключить некоторые сегменты, поведение форматирования станет ограниченным или будет использовать fallback-правила.


Переопределение форматов чисел

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

const numberFormatter = Globalize.numberFormatter({
  minimumFractionDigits: 2,
  maximumFractionDigits: 4
});

Это изменяет стандартное поведение, заданное локалью.

Пример переопределения группировки

const formatter = Globalize.numberFormatter({
  useGrouping: false
});

Результат:

  • стандартно: 1 000 000
  • переопределено: 1000000

Переопределение форматов дат и времени

Форматирование дат зависит от набора шаблонов CLDR, но может быть изменено через опции:

const dateFormatter = Globalize.dateFormatter({
  datetime: "medium"
});

или через кастомный формат:

const customFormatter = Globalize.dateFormatter({
  skeleton: "yMMMMdHm"
});

Изменение поведения через skeleton

Skeleton позволяет переопределить стандартный выбор формата:

  • локаль определяет шаблон
  • skeleton задаёт требуемую структуру

Пример:

Globalize.dateFormatter({ skeleton: "Ehm" });

Переопределение правил сообщений

Система сообщений использует ICU MessageFormat. Поведение можно полностью изменить через загрузку собственных сообщений:

Globalize.loadMessages({
  ru: {
    greeting: "Привет, {name}!"
  }
});

Переопределение через динамическую локаль

Globalize.locale("ru");

const messageFormatter = Globalize.messageFormatter("greeting");
messageFormatter({ name: "Иван" });

Изменение сообщений фактически полностью заменяет поведение встроенной локализации.


Переопределение поведения множественных форм

Правила plural rules берутся из CLDR, но могут быть «перекрыты» через альтернативные сообщения:

Globalize.loadMessages({
  ru: {
    items: "{count, plural, one {# элемент} few {# элемента} many {# элементов} other {# элемента}}"
  }
});

Это позволяет:

  • игнорировать стандартные правила CLDR
  • задать собственную логику отображения

Переопределение fallback-логики

Если данные отсутствуют для текущей локали, Globalize использует fallback на:

  • базовую локаль (например, en)
  • частично совпадающие региональные локали (например, ru-KZru)

Поведение можно контролировать косвенно:

1. Управление доступными данными

Если не загружать fallback-локаль, система будет ограничена:

Globalize.loadMessages({
  en: { hello: "Hello" }
});

2. Явное переключение локали

Globalize.locale("en");

Переопределение форматов через пользовательские функции

В некоторых сценариях стандартные форматтеры заменяются обёртками.

Кастомный числовой форматтер

function customNumber(value) {
  return "≈ " + Globalize.numberFormatter()(value);
}

Здесь изменяется поведение без изменения самой библиотеки.


Переопределение поведения через кеширование форматтеров

Globalize кеширует созданные форматтеры, что влияет на поведение при повторных вызовах.

Можно переопределить стратегию, создавая собственный слой кеша:

const cache = new Map();

function getFormatter(locale) {
  if (!cache.has(locale)) {
    Globalize.locale(locale);
    cache.set(locale, Globalize.numberFormatter());
  }
  return cache.get(locale);
}

Такое переопределение:

  • снижает стоимость создания форматтеров
  • фиксирует поведение для каждой локали

Переопределение форматов через composition API

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

const base = Globalize.dateFormatter();
const custom = (value) => "[" + base(value) + "]";

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


Изменение поведения через управление загрузкой модулей

Архитектура Globalize модульная, поэтому поведение определяется набором подключённых компонентов:

  • number module
  • date module
  • message module
  • plural module

Если часть модулей не загружена, соответствующее поведение становится недоступным или изменяется.


Переопределение локальных шаблонов форматов

CLDR содержит предустановленные шаблоны, но их можно заменить через пользовательские skeleton и options:

Globalize.dateFormatter({
  datetime: "full"
});

или через более строгую настройку:

Globalize.dateFormatter({
  skeleton: "yyyyMMddHHmm"
});

Приоритеты переопределения поведения

Поведение формируется по слоям приоритета:

  1. пользовательские параметры форматтера
  2. skeleton / options
  3. активная локаль
  4. данные CLDR
  5. fallback-локали

Любое переопределение на верхнем уровне полностью перекрывает нижележащие уровни.


Переопределение поведения через смену контекста локали

Локаль может меняться динамически внутри выполнения:

Globalize.locale("ru");
const ruFormatter = Globalize.numberFormatter();

Globalize.locale("en");
const enFormatter = Globalize.numberFormatter();

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


Переопределение правил форматирования валют

Хотя валюты зависят от CLDR, поведение можно модифицировать через параметры:

const currencyFormatter = Globalize.currencyFormatter("USD", {
  style: "code"
});

или:

Globalize.currencyFormatter("USD", {
  minimumFractionDigits: 0
});

Это изменяет стандартное поведение отображения валютных значений.


Переопределение поведения парсинга

Парсинг также подчиняется локали, но может быть изменён через настройки:

const parser = Globalize.numberParser({
  strict: false
});

Это влияет на:

  • допустимые разделители
  • обработку пробелов
  • интерпретацию нестандартных числовых строк

Переопределение через изоляцию локалей

Можно создать изолированные окружения поведения:

const globalizeRu = new Globalize("ru");
const globalizeEn = new Globalize("en");

Каждый экземпляр:

  • имеет собственную локаль
  • использует собственные форматтеры
  • не влияет на глобальное состояние

Переопределение поведения через расширение сообщений

Сообщения могут расширяться поверх базовых:

Globalize.loadMessages({
  ru: {
    base: "Базовое сообщение",
    extended: "Расширенное: {value}"
  }
});

При этом можно строить цепочки логики без изменения ядра.