В Globalize паттерны форматирования опираются на стандарты CLDR и ICU MessageFormat. Любое отклонение от синтаксических правил приводит к тому, что форматтер либо выбрасывает исключение, либо возвращает некорректный результат (например, исходную строку без обработки).
Невалидные паттерны возникают в трёх основных категориях:
Globalize не «исправляет» паттерны автоматически, а строго следует спецификации ICU.
Форматирование чисел в Globalize основано на ICU Number Patterns.
Пример корректного паттерна:
Globalize("en").numberFormatter({ minimumFractionDigits: 2 })(1234.5);
// "1,234.50"
Ошибочным считается использование некорректных группировок:
# и 0Globalize("en").numberFormatter({ raw: "#,,##0.##" })(1234);
Такой паттерн не имеет смысла: двойная запятая ломает правила группировки.
В числовых паттернах допустим только ограниченный набор символов:
0 — обязательная цифра# — необязательная цифра, — разделитель групп. — десятичный разделитель% — процентЛюбые другие символы приводят к ошибке:
Globalize("en").numberFormatter({ raw: "###0abc###" })(1000);
Результат зависит от реализации, но чаще всего это
Error: Invalid number pattern.
Паттерн может содержать только один десятичный разделитель:
Globalize("en").numberFormatter({ raw: "#0.##.##" })(12.34);
Такая строка считается невалидной, поскольку ICU не определяет вторую точку как допустимую часть формата.
Ошибки часто возникают при комбинировании символов:
Globalize("en").numberFormatter({ raw: "#0%#E0" })(1000);
Процентный формат и экспоненциальная запись не могут быть объединены в одном паттерне.
Форматирование дат в Globalize опирается на ICU DateTime Pattern Syntax.
Каждый символ в паттерне имеет строгое значение:
y — годM — месяцd — деньH — часыИспользование неизвестных символов приводит к ошибке:
Globalize("en").dateFormatter({ raw: "yyyy-XMM-dd" })(new Date());
Символ X не определён в ICU и делает паттерн
невалидным.
ICU использует одинарные кавычки для экранирования текста.
Невалидные случаи:
Globalize("en").dateFormatter({ raw: "yyyy-MM-dd 'at HH:mm" })(new Date());
Здесь отсутствует закрывающая кавычка, что приводит к разборочной ошибке.
Некоторые паттерны могут быть формально корректными, но не поддерживаться локалью:
Globalize("ar").dateFormatter({ raw: "EEEE, MMMM d, yyyy GGGG" })(new Date());
Если CLDR для данной локали не содержит данных для календарной эры
GGGG, результат становится неопределённым или
fallback-строкой.
Хотя skeleton-подход более абстрактен, попытка смешивания его с raw-паттернами вызывает ошибки интерпретации:
Globalize("en").dateFormatter({ skeleton: "yMMMxyz" });
xyz не является частью допустимого skeleton-набора.
MessageFormat в Globalize использует ICU Message syntax.
Самая частая ошибка:
Globalize("en").messageFormatter(
"{count, plural, one {1 item} other {# items}"
);
Отсутствует закрывающая } для блока plural.
ICU требует строго определённые категории: one,
few, many, other.
Globalize("en").messageFormatter(
"{count, plural, one {1 item} zero {no items} other {# items}}"
);
Категория zero не поддерживается для английской локали в
CLDR, что делает паттерн невалидным.
Globalize("en").messageFormatter(
"{rank, selectordinal, 1 {1st} 2 {2nd} few {#th} other {#th}}"
);
Здесь категория few не соответствует правилам ordinal
selection.
ICU использует апостроф как управляющий символ.
Ошибочный пример:
Globalize("en").messageFormatter(
"It's {count} items"
);
Апостроф трактуется как начало escape-последовательности, и строка может быть разобрана неверно. Корректный вариант требует удвоения:
"It''s {count} items"
Даже корректный синтаксически паттерн может стать невалидным при отсутствии данных в CLDR.
Globalize("xx").numberFormatter({ style: "currency", currency: "USD" })(100);
Если локаль не существует в CLDR, форматтер не сможет определить правила отображения валюты.
Некоторые локали могут не содержать:
Это приводит к fallback-поведению, которое часто воспринимается как «невалидный паттерн».
Globalize разделяет два подхода:
raw — явный ICU-паттернskeleton — абстрактное описание форматаИх смешивание в одном вызове приводит к неопределённому поведению:
Globalize("en").dateFormatter({
raw: "yyyy-MM-dd",
skeleton: "yMd"
});
Приоритет одного из параметров не гарантирован, результат может зависеть от версии реализации.
Некорректное использование:
Globalize("en").numberFormatter({ raw: "#0%%" })(0.12);
Двойной символ % не соответствует ICU-правилам.
Globalize("en").numberFormatter({ raw: "#0,0,0" })(1000);
ICU требует строгого порядка разделителей групп, нарушение делает шаблон невалидным.
Типичные проявления ошибок:
Error: Invalid patternrootПричины обычно фиксируются на этапе парсинга паттерна, а не во время выполнения форматирования.
ICU-парсер не всегда полностью отклоняет строку. Возможны случаи:
Это особенно характерно для сложных MessageFormat выражений с вложенными блоками.