Проверка доступности данных

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

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

Проверка наличия CLDR-глобальных данных

CLDR-данные подключаются отдельно и доступны через объект Globalize.cldr. На уровне базовой проверки используется доступ к внутренним структурам CLDR:

import Globalize from "globalize";
import cldrData from "cldr-data";

Globalize.load(cldrData.entireSupplemental());
Globalize.load(cldrData.entireMainFor("ru"));

Фактическая проверка доступности данных строится вокруг CLDR-методов:

const cldr = Globalize.cldr;

const hasLocaleData = !!cldr.get(`main/ru`);

Если выражение возвращает undefined, локальные данные не загружены. При наличии корректной загрузки структура main/{locale} содержит все основные наборы: числа, даты, календари, термины.

Проверка наличия локали в Globalize

Globalize хранит текущую локаль, но сама по себе локаль не гарантирует наличие данных. Проверка обычно разделяется на два уровня: установленная локаль и наличие данных для неё.

Globalize.locale("ru");

const currentLocale = Globalize.locale().locale;
const isLocaleSet = typeof currentLocale === "string";

Однако установка локали не эквивалентна готовности форматтеров. При отсутствии CLDR соответствующей локали форматирование либо падает, либо возвращает некорректные значения.


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

Форматирование чисел в Globalize зависит от загрузки numberingSystems, numbers и currencies из CLDR. Проверка строится через попытку создания форматтера или через косвенное определение наличия данных.

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

let numberFormatterAvailable = false;

try {
  const formatter = Globalize.numberFormatter();
  numberFormatterAvailable = typeof formatter === "function";
} catch (e) {
  numberFormatterAvailable = false;
}

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

Проверка наличия числовых данных в CLDR

const hasNumbersData = !!Globalize.cldr.get("main/ru/numbers");

Структура numbers содержит:

  • decimalFormats
  • scientificFormats
  • percentFormats
  • symbols

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


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

Работа с датами в Globalize требует наличия CLDR-данных календарей (ca-gregorian), временных форматов и временных зон.

Проверка календарных данных

const hasCalendarData =
  !!Globalize.cldr.get("main/ru/ca-gregorian");

Если календарь отсутствует, невозможны операции:

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

Проверка через создание форматтера даты

let dateFormatterAvailable = false;

try {
  const formatter = Globalize.dateFormatter();
  dateFormatterAvailable = typeof formatter === "function";
} catch (e) {
  dateFormatterAvailable = false;
}

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

Проверка временных зон

const hasTimeZoneData =
  !!Globalize.cldr.get("supplemental/timeData");

Отсутствие данных временных зон приводит к ошибкам при использовании dateFormatter с параметрами timeZone.


Проверка доступности сообщений (messages)

Механизм сообщений Globalize позволяет локализовать строки интерфейса. Он не является частью CLDR напрямую, но зависит от ручной загрузки через Globalize.loadMessages.

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

const messages = Globalize.messages("ru");

const hasMessages = messages && Object.keys(messages).length > 0;

Если сообщения не загружены, вызов Globalize.messageFormatter() возвращает функцию, которая либо возвращает ключ, либо пустую строку.

Проверка через форматтер сообщений

let messageFormatterAvailable = false;

try {
  const mf = Globalize.messageFormatter("hello");
  messageFormatterAvailable = typeof mf === "function";
} catch (e) {
  messageFormatterAvailable = false;
}

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


Комплексная проверка состояния данных Globalize

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

function isGlobalizeReady(locale = "ru") {
  const cldr = Globalize.cldr;

  const hasMainData =
    !!cldr.get(`main/${locale}`);

  const hasNumbers =
    !!cldr.get(`main/${locale}/numbers`);

  const hasCalendar =
    !!cldr.get(`main/${locale}/ca-gregorian`);

  let canFormatNumbers = false;
  let canFormatDates = false;

  try {
    Globalize.locale(locale);

    Globalize.numberFormatter();
    canFormatNumbers = true;
  } catch (e) {
    canFormatNumbers = false;
  }

  try {
    Globalize.dateFormatter();
    canFormatDates = true;
  } catch (e) {
    canFormatDates = false;
  }

  return (
    hasMainData &&
    hasNumbers &&
    hasCalendar &&
    canFormatNumbers &&
    canFormatDates
  );
}

Такая проверка объединяет:

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

Обработка частично загруженных данных

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

Проверка деградации форматирования

function safeNumberFormat(value) {
  try {
    return Globalize.numberFormatter()(value);
  } catch (e) {
    return String(value);
  }
}

Проверка деградации дат

function safeDateFormat(date) {
  try {
    return Globalize.dateFormatter()(date);
  } catch (e) {
    return date.toISOString();
  }
}

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


Проверка доступности plural rules

Механизм pluralization зависит от CLDR правил для конкретного языка.

let pluralAvailable = false;

try {
  const pr = Globalize.plural();
  pluralAvailable = typeof pr === "function";
} catch (e) {
  pluralAvailable = false;
}

Дополнительно можно проверить наличие rules:

const hasPluralRules =
  !!Globalize.cldr.get(`supplemental/plurals-type-cardinal`);

Отсутствие plural rules делает невозможным корректную локализацию количественных выражений.


Проверка зависимостей CLDR перед инициализацией

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

function ensureCLDR(locale) {
  const cldr = Globalize.cldr;

  const requiredPaths = [
    `main/${locale}`,
    `main/${locale}/numbers`,
    `main/${locale}/ca-gregorian`,
    `supplemental/likelySubtags`
  ];

  return requiredPaths.every(path => !!cldr.get(path));
}

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

Для сложных систем полезна диагностика конкретного недостающего блока:

function diagnose(locale) {
  const cldr = Globalize.cldr;

  const report = {
    main: !!cldr.get(`main/${locale}`),
    numbers: !!cldr.get(`main/${locale}/numbers`),
    calendar: !!cldr.get(`main/${locale}/ca-gregorian`),
    timeData: !!cldr.get("supplemental/timeData"),
    plurals: !!cldr.get("supplemental/plurals-type-cardinal"),
    likelySubtags: !!cldr.get("supplemental/likelySubtags")
  };

  return report;
}

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


Поведение Globalize при отсутствии данных

При отсутствии CLDR данных поведение API варьируется:

  • форматтеры могут выбрасывать исключения
  • некоторые функции возвращают fallback значения
  • сообщения могут возвращать ключи вместо текста
  • числовые форматы деградируют до toString()

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