Распознавание локальных форматов

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


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

  • форматирование (formatting) — преобразование чисел, дат и валют в строку согласно локали
  • разбор (parsing) — обратное преобразование строки в структурированный тип данных

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

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

Globalize использует данные CLDR для построения правил разбора, а не эвристики, что обеспечивает предсказуемость поведения.


Разбор чисел в локальном формате

Числа — наиболее частый тип локализованного ввода. Различия между локалями касаются десятичного и тысячного разделителей.

Примеры:

  • 1,234.56 (en-US)
  • 1.234,56 (de-DE)
  • 1 234,56 (fr-FR)

В Globalize разбор выполняется через parseNumber, который учитывает текущую локаль:

Globalize.locale("de");

const value = Globalize.parseNumber("1.234,56");
console.log(value); // 1234.56

Механика разбора:

  • определение символа группировки
  • удаление разделителей тысяч
  • преобразование десятичного разделителя в точку
  • нормализация строки перед конвертацией в Number

Нормализация числового ввода

При разборе чисел важно учитывать не только символы, но и их контекст:

  • повторяющиеся разделители групп игнорируются
  • пробелы могут выступать разделителями (тонкие неразрывные пробелы в некоторых локалях)
  • знаки плюса и минуса могут быть представлены локальными символами

Пример:

Globalize.locale("fr");

Globalize.parseNumber("−1 234,50"); // -1234.5

Здесь используется не стандартный ASCII-минус, а Unicode-минус, а также неразрывный пробел как разделитель групп.


Разбор валютных значений

Форматы валют включают числовую часть и символ валюты, который может располагаться до или после числа.

Особенности:

  • $1,000.00 (en-US)
  • 1 000,00 € (fr-FR)
  • €1.000,00 (de-DE)

В Globalize разбор валют учитывает локальный шаблон:

Globalize.locale("de");

const amount = Globalize.parseNumber("1.000,00 €");
console.log(amount); // 1000

При этом символ валюты удаляется на этапе нормализации, но его позиция используется для идентификации формата.


Разбор дат и времени

Даты представляют более сложный случай из-за вариативности порядка компонентов.

Сравнение:

  • 12/31/2025 (en-US)
  • 31.12.2025 (ru-RU, de-DE)
  • 2025-12-31 (ISO)

В Globalize разбор дат выполняется через CLDR-основанные шаблоны:

Globalize.locale("ru");

const date = Globalize.parseDate("31.12.2025");
console.log(date); // Date object

Механизм включает:

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

Классификация форматов дат

Globalize различает несколько уровней формата:

  • short — компактный формат (31.12.25)
  • medium — стандартный формат (31.12.2025)
  • long — расширенный формат (31 декабря 2025 г.)
  • full — полный формат с днем недели

Разбор всегда опирается на соответствующий шаблон:

Globalize.locale("ru");

Globalize.parseDate("31 декабря 2025 г.");

Неоднозначность и стратегия разрешения

Некоторые строки могут быть неоднозначны без локального контекста:

  • 01/02/2025 → 1 февраля или 2 января
  • 10-11-12 → разные интерпретации порядка

Globalize устраняет неоднозначность через:

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

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


Разбор чисел с десятичными вариациями

Некоторые локали используют нестандартные символы:

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

Globalize приводит все символы к нормализованному виду перед парсингом:

Globalize.locale("ar");

Globalize.parseNumber("١٬٢٣٤٫٥٦");

Результат:

1234.56

Роль CLDR в распознавании форматов

CLDR (Unicode Common Locale Data Repository) является основным источником правил:

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

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


Обработка пользовательского ввода в реальных сценариях

При работе с формами важно учитывать:

  • пользователь может вводить данные в «своем» формате
  • сервер может ожидать нормализованные значения
  • интерфейс может отображать один формат, а принимать другой

Типичный поток:

  1. пользователь вводит строку в локальном формате
  2. Globalize выполняет parseNumber / parseDate
  3. приложение получает нормализованный объект
  4. данные передаются в бизнес-логику

Смешанные форматы и ограничения

Некоторые случаи требуют осторожности:

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

Пример проблемного ввода:

"около 1.000 евро"

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


Принцип детерминированного разбора

Ключевая характеристика механизма распознавания:

  • одинаковый ввод + одинаковая локаль = одинаковый результат
  • отсутствие скрытых эвристик
  • строгая зависимость от CLDR

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