Локализация числовых форматов

Работа с числовыми форматами в различных локалях валидации данных требует учёта различий в записи десятичных и тысячных разделителей, а также особенностей региональных стандартов представления чисел. В контексте библиотеки Validator.js эти задачи решаются через набор функций, ориентированных на проверку строковых значений, интерпретируемых как числа, с возможностью учёта локализации.

В различных странах применяются разные соглашения:

  • В англоязычных форматах используется точка как десятичный разделитель: 1234.56
  • В ряде европейских локалей применяется запятая: 1234,56
  • Разделение тысяч может выполняться пробелом, точкой или запятой: 1 234, 1.234, 1,234

Эти различия делают невозможным универсальную проверку числовых строк без учёта локали.

Validator.js учитывает эту проблему через параметр locale в некоторых числовых валидаторах.

Проверка чисел с плавающей точкой с учётом локали

Функция isFloat предназначена для проверки чисел с плавающей точкой и поддерживает локализованные форматы через опции.

import validator from 'validator';

validator.isFloat('1234.56'); // true (en-US формат)
validator.isFloat('1234,56', { locale: 'de-DE' }); // true

Поддерживаемые локали включают распространённые региональные форматы, такие как:

  • en-US
  • de-DE
  • fr-FR
  • it-IT
  • es-ES

При использовании локали библиотека автоматически интерпретирует:

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

Влияние локали на допустимые форматы

При изменении параметра locale изменяется логика разбора строки:

Английская локаль

validator.isFloat('1,234.56', { locale: 'en-US' }); // true
validator.isFloat('1.234,56', { locale: 'en-US' }); // false

Здесь запятая рассматривается как разделитель тысяч, а точка — как десятичный разделитель.

Немецкая локаль

validator.isFloat('1.234,56', { locale: 'de-DE' }); // true
validator.isFloat('1,234.56', { locale: 'de-DE' }); // false

В этом случае роли разделителей меняются местами.

Проверка десятичных значений

Функция isDecimal используется для строгой проверки десятичных чисел. Она также поддерживает локализацию:

validator.isDecimal('1234,56', { locale: 'fr-FR' }); // true
validator.isDecimal('1234.56', { locale: 'fr-FR' }); // false

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

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

Ограничения локализации в isInt

Функция isInt ориентирована на проверку целых чисел и не поддерживает полноценную локализацию числовых разделителей. Основные опции:

  • min, max — диапазон значений
  • allow_leading_zeroes — разрешение ведущих нулей
  • gt, lt, ge, le — логические ограничения
validator.isInt('1234'); // true
validator.isInt('1,234'); // false

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

Проблема нормализации входных данных

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

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

Типичный подход:

function normalizeNumber(input) {
  return input
    .replace(/\s/g, '')       // удаление пробелов
    .replace(/\u202F/g, '')   // узкий неразрывный пробел
    .replace(',', '.');       // приведение запятой к точке
}

После нормализации данные можно проверять стандартными методами:

validator.isFloat(normalizeNumber('1 234,56'));

Разделители и допустимые символы

Validator.js строго ограничивает допустимые символы при проверке чисел:

  • цифры 0–9
  • один допустимый десятичный разделитель (в зависимости от локали)
  • знак минус в начале числа
  • группирующие символы (если поддерживаются локалью в isFloat или isDecimal)

Недопустимыми считаются:

  • множественные разделители
  • смешение локальных форматов (1,234.56 в de-DE)
  • посторонние символы (1234€, 12 34a)

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

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

function toStandardFloat(value) {
  const cleaned = value
    .replace(/\./g, '')
    .replace(',', '.');
  return cleaned;
}

validator.isFloat(toStandardFloat('1.234,56'));

Такой подход позволяет унифицировать обработку чисел перед валидацией.

Ошибки интерпретации при смешанных форматах

Распространённая проблема — строки, содержащие одновременно несколько типов разделителей:

  • 1.234,56 — допустимо только для de-DE
  • 1,234.56 — допустимо только для en-US
  • 1.234.56 — недопустимо в любом формате

Validator.js в таких случаях строго следует указанной локали и отклоняет некорректные комбинации.

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

Если параметр locale не задан, используется стандартный формат:

  • десятичный разделитель — точка
  • группировка тысяч не учитывается как допустимая
validator.isFloat('1234.56'); // true
validator.isFloat('1234,56'); // false

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

Комбинация локализации и дополнительных опций

В isFloat и isDecimal локализация может использоваться вместе с дополнительными ограничениями:

validator.isFloat('1234,56', {
  locale: 'de-DE',
  min: 0,
  max: 2000
});

Такая комбинация позволяет одновременно:

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

Обработка пограничных случаев

Особое внимание требуется к следующим ситуациям:

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

Пример:

validator.isFloat('-1 234,56', { locale: 'de-DE' }); // true
validator.isFloat(' - 1234,56', { locale: 'de-DE' }); // false

Лишние пробелы вокруг знака минус приводят к отклонению строки.

Роль нормализации в архитектуре валидации

В реальных приложениях локализация чисел редко ограничивается только Validator.js. Обычно используется двухэтапная схема:

  1. Нормализация входных данных (очистка, приведение формата)
  2. Валидация через isFloat или isDecimal

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