Плюрализация

Плюрализация в международной локализации представляет собой механизм выбора правильной формы слова в зависимости от числового значения. В JavaScript-библиотеке Globalize этот процесс основан на стандартах CLDR (Unicode Common Locale Data Repository), где для каждого языка определены категории множественности и правила их применения.

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

  • zero
  • one
  • two
  • few
  • many
  • other

Не все языки используют полный набор категорий. Например:

  • В английском языке используются только one и other
  • В русском языке — one, few, many, other
  • В арабском языке применяется более детальная система, включающая несколько категорий, зависящих от чисел и их окончаний

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

Подготовка данных CLDR в Globalize

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

Минимальный набор данных включает:

  • likelySubtags
  • plurals
  • numbers
  • ca-gregorian (если используются даты вместе с сообщениями)

Пример загрузки:

Globalize.load(
  require("cldr-data/supplemental/likelySubtags"),
  require("cldr-data/supplemental/plurals"),
  require("cldr-data/main/ru/numbers"),
  require("cldr-data/main/ru/plurals")
);

Globalize.locale("ru");

Без загрузки данных о множественности любые операции, связанные с pluralization, будут невозможны.

Базовый механизм plural

Основной интерфейс работы с множественными формами в Globalize строится вокруг форматирования сообщений с поддержкой CLDR plural rules.

Простейший пример использования:

const globalize = new Globalize("en");

globalize.formatMessage(
  "{count, plural, one {# item} other {# items}}",
  { count: 1 }
);
// "1 item"

При изменении значения:

globalize.formatMessage(
  "{count, plural, one {# item} other {# items}}",
  { count: 5 }
);
// "5 items"

Символ # автоматически подставляет значение числового параметра.

Локализационные различия в plural rules

Английский язык

"{count, plural, one {# file} other {# files}}"

Правило простое: единица — форма one, все остальные значения — other.

Русский язык

const globalize = new Globalize("ru");

globalize.formatMessage(
  "{count, plural, one {# файл} few {# файла} many {# файлов} other {# файла}}",
  { count: 3 }
);

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

  • 1, 21, 31 → one
  • 2–4, 22–24 → few
  • 0, 5–20, 25–30 → many

Globalize полностью делегирует выбор категории CLDR-движку, не требуя ручной логики ветвления.

Арабский язык

В арабской локали система ещё более детализирована:

"{count, plural, zero {لا عناصر} one {عنصر واحد} two {عنصران} few {# عناصر} many {# عنصراً} other {# عنصر}}"

Здесь каждая числовая группа имеет отдельную грамматическую форму.

Явные числовые совпадения (=n)

CLDR позволяет задавать точные числовые совпадения, которые имеют приоритет над категориями plural rules.

"{count, plural, =0 {нет файлов} one {# файл} other {# файлов}}"

Поведение:

  • 0 → «нет файлов»
  • 1 → «1 файл»
  • остальные значения → «N файлов»

Этот механизм полезен для исключений, где стандартные категории не подходят.

Вложенные выражения и сложные сообщения

Pluralization в Globalize интегрируется в систему ICU MessageFormat, что позволяет строить вложенные структуры:

"{count, plural,
  one {{name} имеет # сообщение}
  other {{name} имеет # сообщений}
}"

Допускается комбинирование с другими типами форматирования:

"{count, plural,
  one {{count} файл был загружен}
  few {{count} файла было загружено}
  many {{count} файлов было загружено}
}"

Использование переменных и вычислений

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

globalize.formatMessage(
  "{count, plural, one {# item processed} other {# items processed}}",
  { count: items.length }
);

Таким образом обеспечивается разделение логики и представления.

Особенности работы с нулём

В зависимости от языка, ноль может относиться к разным категориям:

  • В английском: 0 → other
  • В русском: 0 → many
  • В некоторых языках: отдельная категория zero

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

Производительность и кеширование

При частом форматировании сообщений plural-форматы компилируются в функции форматирования. Это позволяет:

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

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

const message = globalize.messageFormatter(
  "{count, plural, one {# item} other {# items}}"
);

message({ count: 10 });

Функция messageFormatter создаёт предкомпилированный форматтер.

Интеграция plural с другими форматами Globalize

Pluralization часто комбинируется с:

  • форматированием чисел (numberFormatter)
  • форматированием валют
  • форматированием дат в сообщениях

Пример:

"{count, plural,
  one {{count} файл, обновлён {date}}
  other {{count} файлов, обновлены {date}}
}"

Где date предварительно форматируется через dateFormatter.

Ошибки конфигурации и типичные ограничения

При работе с pluralization в Globalize встречаются следующие ограничения:

  • отсутствие CLDR данных приводит к невозможности определения категорий
  • пропущенные категории вызывают fallback в other
  • несоответствие локали и загруженных данных приводит к некорректному выбору форм
  • использование неподдерживаемых ICU-синтаксических конструкций вызывает ошибки парсинга

Согласованность с ICU MessageFormat

Синтаксис plural в Globalize полностью совместим с ICU MessageFormat:

{variable, plural, one {...} other {...}}

Это обеспечивает переносимость сообщений между различными системами интернационализации и серверными платформами.

Обобщённая модель поведения

Механизм pluralization в Globalize можно представить как последовательность шагов:

  1. Получение числового значения
  2. Определение локали
  3. Применение CLDR правил к числу
  4. Выбор соответствующей категории
  5. Подстановка строки из шаблона
  6. Интерполяция переменных

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