Переопределение CLDR данных

CLDR (Common Locale Data Repository) представляет собой стандартизированную базу локализационных данных, используемую во множестве международных библиотек JavaScript через Intl-API и его полифиллы. В контексте FormatJS именно CLDR определяет поведение форматирования дат, чисел, относительного времени, правил плюрализации и множества других языковых особенностей.

FormatJS не хранит эти правила в виде «жёстко зашитой логики». Вместо этого используется набор пакетов, основанных на CLDR-данных, которые подключаются и при необходимости могут быть расширены или переопределены.


Архитектурная роль CLDR в FormatJS

В экосистеме FormatJS CLDR используется как источник:

  • правил плюрализации (one, few, many и т.д.)
  • форматов дат и времени
  • календарных систем
  • правил отображения чисел (разделители, группировка, десятичные знаки)
  • относительных временных выражений («1 день назад», «через 2 часа»)
  • локалей и их канонических форм

Эти данные инкапсулируются внутри пакетов:

  • @formatjs/intl-numberformat
  • @formatjs/intl-datetimeformat
  • @formatjs/intl-pluralrules
  • @formatjs/intl-relativetimeformat
  • @formatjs/intl-locale

Каждый из них содержит собственный слой CLDR-данных, адаптированный под Intl-совместимый интерфейс.


Причины переопределения CLDR данных

Переопределение CLDR-слоя используется в ситуациях, когда:

  • требуется нестандартное поведение локализации
  • необходимо ограничить или изменить набор поддерживаемых локалей
  • используются корпоративные правила форматирования
  • требуется согласование с внутренними стандартами UX/UX-writing
  • требуется исправление или замена данных для редких локалей
  • необходимо уменьшить размер бандла за счёт урезанных данных

Механизм подключения пользовательских CLDR-данных

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

NumberFormat: регистрация данных

import '@formatjs/intl-numberformat/polyfill';
import '@formatjs/intl-numberformat/locale-data/ru';

Intl.NumberFormat.__addLocaleData(
  require('@formatjs/intl-numberformat/locale-data/ru')
);

Здесь происходит загрузка стандартного CLDR-подобного набора данных для чисел и его регистрация в полифилле.


DateTimeFormat: переопределение календарных и временных правил

import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/locale-data/ru';

Intl.DateTimeFormat.__addLocaleData(
  require('@formatjs/intl-datetimeformat/locale-data/ru')
);

Этот слой управляет форматами:

  • дат
  • времени
  • длинных и коротких форматов
  • календарных систем

RelativeTimeFormat: изменение правил относительного времени

import '@formatjs/intl-relativetimeformat/polyfill';
import '@formatjs/intl-relativetimeformat/locale-data/ru';

Intl.RelativeTimeFormat.__addLocaleData(
  require('@formatjs/intl-relativetimeformat/locale-data/ru')
);

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

  • «1 минута назад»
  • «через 5 дней»
  • «2 часа назад»

PluralRules: замена правил плюрализации

import '@formatjs/intl-pluralrules/polyfill';
import '@formatjs/intl-pluralrules/locale-data/ru';

Intl.PluralRules.__addLocaleData(
  require('@formatjs/intl-pluralrules/locale-data/ru')
);

Именно этот слой критически зависит от CLDR, так как разные языки используют существенно отличающиеся системы множественных форм.


Полное переопределение CLDR данных

В некоторых сценариях требуется не добавление, а именно замена стандартных данных. Это используется при:

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

Подмена набора данных через локальный пакет

const customLocaleData = {
  data: {
    // пользовательские правила плюрализации
  },
  locale: 'ru'
};

Intl.PluralRules.__addLocaleData(customLocaleData);

Такой подход позволяет подменять стандартные CLDR-наборы собственными структурами.


Изоляция и контроль загружаемых локалей

CLDR в FormatJS не загружается автоматически полностью. Вместо этого используется модель явной регистрации:

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

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

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

Совмещение CLDR с пользовательскими форматами

FormatJS позволяет комбинировать CLDR-данные с пользовательскими форматами через ICU Message Syntax. При этом CLDR влияет на низкоуровневую интерпретацию, а сообщения остаются декларативными.

Пример:

{count, plural,
  one {# элемент}
  few {# элемента}
  many {# элементов}
}

Правила выбора формы «one/few/many» определяются именно CLDR-данными, а не самим сообщением.


Приоритет данных при переопределении

При конфликте данных действует следующий порядок:

  1. пользовательские данные, зарегистрированные через __addLocaleData
  2. данные полифилла FormatJS
  3. fallback-реализация браузерного Intl
  4. базовые CLDR-правила по умолчанию

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


Частичная замена CLDR-слоёв

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

  • только числовые форматы
  • только правила плюрализации
  • только относительное время
  • только дата/время

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


Типовые ошибки при переопределении CLDR

На практике встречаются следующие проблемы:

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

Такие ситуации приводят к падению форматирования или к возврату к fallback-логике.


Влияние переопределения на ICU MessageFormat

CLDR-данные напрямую влияют на:

  • выбор plural-форм
  • интерпретацию селекторов (select, plural)
  • форматирование дат внутри сообщений
  • интерпретацию числовых аргументов

ICU-сообщения остаются неизменными, но результат их выполнения зависит от активного CLDR-набора.


Кастомные локали и расширение CLDR

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

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

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