Библиотека Globalize в JavaScript опирается на CLDR (Unicode Common Locale Data Repository), и корректная работа большинства API напрямую зависит от того, загружены ли необходимые данные для конкретной локали. Ошибки в рантайме часто возникают не из-за вызовов методов, а из-за отсутствующих фрагментов CLDR: числовых форматов, календарей, валют, правил pluralization и локализованных сообщений.
Основной принцип проверки доступности данных заключается в том, что Globalize не предоставляет единого «центра состояния готовности», поэтому контроль осуществляется через проверку факта загрузки 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.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()
может завершиться ошибкой, поскольку форматтер не может построить
правила округления и разделителей.
const hasNumbersData = !!Globalize.cldr.get("main/ru/numbers");
Структура numbers содержит:
Отсутствие любого из этих блоков приводит к неполноценному форматированию.
Работа с датами в 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.
Механизм сообщений 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;
}
Отсутствие ключа не всегда является ошибкой, но отсутствие набора сообщений приводит к деградации интерфейса.
В реальных приложениях проверка доступности данных сводится к агрегированному состоянию. Вместо проверки отдельных блоков формируется единый индикатор готовности.
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
);
}
Такая проверка объединяет:
Состояние частичной загрузки является наиболее проблемным сценарием. Например, может быть загружена локаль без календаря или с отсутствующими числами.
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.
Механизм 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 загружаются поэтапно. Проверка перед инициализацией позволяет избежать ошибок инициализации форматтеров.
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 отдельно.
При отсутствии CLDR данных поведение API варьируется:
toString()Отсутствие единообразного поведения делает проверку доступности данных обязательной частью архитектуры приложения, использующего Globalize как слой интернационализации.