Отсутствующие данные локали

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

Ключевая особенность архитектуры Globalize заключается в том, что библиотека не содержит локали «из коробки». Любая операция форматирования или парсинга требует предварительно загруженных данных. Отсюда возникает центральная проблема: отсутствие необходимых фрагментов локали в рантайме приводит не к мягкому fallback, а к ошибкам выполнения.

Структура зависимости Globalize от CLDR

Globalize не работает автономно. Он опирается на следующие группы данных:

  • cldr/supplemental/likelySubtags
  • cldr/supplemental/plurals
  • cldr/supplemental/timeData
  • cldr/main/{locale}/numbers
  • cldr/main/{locale}/ca-gregorian
  • cldr/main/{locale}/currencies
  • cldr/main/{locale}/dateFields

Каждая функция форматирования требует строго определённого подмножества этих данных. Например:

  • форматирование даты — ca-gregorian + dateFields + timeZoneNames (частично)
  • форматирование валют — numbers + currencies
  • форматирование относительного времени — dateFields + timeData + plurals

Отсутствие любого из этих блоков приводит к невозможности корректного выполнения операции.

Типы отсутствующих данных локали

Полное отсутствие локали

Сценарий возникает, когда локаль вообще не загружена:

Globalize.locale("fr-FR");

Globalize.formatDate(new Date());
// Ошибка: отсутствуют данные для локали fr-FR

Внутренне Globalize проверяет наличие пакета cldr/main/fr/. Если он не загружен, создаётся исключение, поскольку библиотека не может построить форматтер.

Особенность поведения:

  • нет автоматического fallback на en
  • нет частичной деградации функциональности
  • выполнение прерывается сразу

Частично загруженная локаль

Более сложный случай — загружены только отдельные части CLDR:

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

Globalize.locale("ru");

Globalize.formatDate(new Date());

Ошибка возникает даже при наличии числовых данных, потому что отсутствует календарный модуль ca-gregorian.

Поведение Globalize в таких условиях строго детерминировано:

  • проверка идёт по цепочке зависимостей
  • отсутствие одного узла разрывает всю операцию
  • сообщение об ошибке не указывает «рекомендуемые» исправления, только факт отсутствия данных

Отсутствие supplemental-данных

Supplemental-данные — критический слой, который часто упускается при ручной сборке локалей.

Наиболее важные блоки:

  • likelySubtags
  • plurals
  • numberingSystems

Пример ошибки при отсутствии plurals:

Globalize.formatMessage("{count, plural, one {# item} other {# items}}", {
  count: 3
});

При отсутствии правил множественного числа:

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

Механизм проверки наличия данных

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

Внутренний принцип:

  1. функция форматирования запрашивает CLDR-модуль
  2. происходит проверка наличия пути в загруженных данных
  3. при отсутствии узла вызывается исключение RuntimeError

Пример типичного сценария:

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

Globalize.locale("ru");

const numberFormatter = Globalize.numberFormatter();
numberFormatter(12345);

Если отсутствует numberingSystems, результат будет недоступен, даже если числа формально загружены.

Ошибки, связанные с отсутствием календарных данных

Наиболее частая группа проблем связана с датами.

Отсутствие ca-gregorian

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

Globalize.locale("en");

Globalize.formatDate(new Date());

Результат:

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

Globalize требует наличие структуры:

cldr.main.<locale>.dates.calendars.gregorian

Отсутствие dateFields

Даже при наличии календаря возможны ошибки в относительном времени:

Globalize.formatRelativeTime(-1, "day");

Без dateFields:

  • невозможна локализация единиц времени
  • отсутствуют строки вроде “yesterday”, “tomorrow”
  • форматтер не может построить текстовое представление

Неполные валютные данные

Работа с валютами требует одновременного наличия:

  • числовых форматов (numbers)
  • валютных кодов (currencies)
  • паттернов форматирования

Пример проблемной конфигурации:

Globalize.load(
  require("cldr-data/main/ja/numbers")
);

Globalize.locale("ja");

Globalize.currencyFormatter("JPY")(1000);

Ошибка возникает из-за отсутствия currencies, даже если числовой формат присутствует.

Внутреннее поведение:

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

Проблемы с plural rules

Множественные числа — один из наиболее чувствительных компонентов CLDR.

Globalize.load(
  require("cldr-data/supplemental/likelySubtags")
);

Globalize.locale("en");

Globalize.plural(1);

Без supplemental/plurals невозможна даже базовая классификация чисел:

  • one
  • other
  • few (для некоторых языков)
  • many

Отсутствие этих правил блокирует:

  • форматирование сообщений
  • i18n-шаблоны
  • message interpolations

Диагностика отсутствующих данных

Globalize не предоставляет встроенного диагностического режима, однако состояние можно анализировать через косвенные методы.

Проверка через инициализацию форматтера

try {
  Globalize.dateFormatter();
} catch (e) {
  console.log(e.message);
}

Типичные сообщения:

  • missing required cldr data
  • invalid locale
  • undefined calendar data
  • missing supplemental plural rules

Ручная инспекция CLDR

Так как CLDR загружается как JSON:

const cldr = Globalize.cldr;

console.log(cldr.main("ru").dates);

При отсутствии данных:

  • undefined на уровне ключей
  • либо частично заполненные структуры

Стратегии предотвращения ошибок отсутствующих данных

Полная загрузка минимального набора CLDR

Базовый набор, необходимый почти для всех сценариев:

  • supplemental/likelySubtags
  • supplemental/plurals
  • supplemental/numberingSystems
  • main/{locale}/numbers
  • main/{locale}/ca-gregorian
  • main/{locale}/currencies
  • main/{locale}/dateFields

Такой набор обеспечивает стабильную работу большинства API Globalize.

Контроль сборки локалей

При использовании bundler’ов (Webpack, Rollup, Vite):

  • локали часто разбиваются на чанки
  • возможна потеря supplemental-данных
  • tree-shaking может удалить «неиспользуемые» JSON

Типичный источник ошибок:

  • импорт только numbers
  • отсутствие supplemental

Явная инициализация зависимостей

Рекомендуемый подход — централизованная загрузка:

import Globalize from "globalize";

import likelySubtags from "cldr-data/supplemental/likelySubtags";
import plurals from "cldr-data/supplemental/plurals";
import numbers from "cldr-data/main/ru/numbers";
import calendar from "cldr-data/main/ru/ca-gregorian";
import currencies from "cldr-data/main/ru/currencies";
import dateFields from "cldr-data/main/ru/dateFields";

Globalize.load(
  likelySubtags,
  plurals,
  numbers,
  calendar,
  currencies,
  dateFields
);

Globalize.locale("ru");

Отсутствие любого элемента приводит к деградации всей цепочки форматирования.

Поведение Globalize при ошибках данных

Globalize придерживается строгой модели:

  • отсутствие данных → исключение
  • отсутствие частичного fallback
  • отсутствие автоматического восстановления

Это означает:

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

В отличие от библиотек с мягким fallback (например, Intl API браузера), Globalize требует полного соответствия структуре данных CLDR перед выполнением операций.

Особенности работы с несколькими локалями

При переключении локали:

Globalize.locale("en");
Globalize.locale("ru");

данные не «переключаются» автоматически. Они уже должны быть загружены заранее.

Отсутствие данных для одной из локалей приводит к ошибкам только при фактическом вызове форматирования.

Типичная проблема:

  • загружена только en
  • переключение на ru
  • вызов formatDate → ошибка

Итоговая модель поведения системы данных

Архитектура Globalize можно рассматривать как систему строгих зависимостей:

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

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