Комбинирование с plural

Plural-формы в FormatJS основаны на ICU MessageFormat, который опирается на стандартные правила множественности языка через Intl.PluralRules. Каждая локаль определяет набор категорий: zero, one, two, few, many, other. В JavaScript реальное поведение зависит от реализации Intl, но логика MessageFormat абстрагирует это через декларативные шаблоны.

Базовая конструкция plural в формате сообщений:

const message = {
  one: "1 файл",
  other: "{count} файлов"
};

В ICU-синтаксисе:

"{count, plural, one {# файл} few {# файла} many {# файлов} other {# файла}}"

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

Архитектура комбинирования plural с переменными

Plural в FormatJS не существует изолированно. Он всегда является частью более крупного сообщения, где одновременно могут использоваться:

  • интерполяция переменных
  • select-ветвления
  • вложенные plural-выражения
  • форматирование чисел через number
  • условия через select

Комбинация строится как вложенная грамматика ICU, где plural является узлом дерева сообщений.

Пример комбинирования с дополнительной переменной:

"{gender, select,
  male {{count, plural, one {Он добавил # элемент} other {Он добавил # элементов}}}
  female {{count, plural, one {Она добавила # элемент} other {Она добавила # элементов}}}
  other {{count, plural, one {Добавлено # элемент} other {Добавлено # элементов}}}
}"

Здесь происходит двухуровневая диспетчеризация:

  1. select определяет грамматический род
  2. внутри каждой ветки работает plural

Вложенные plural-конструкции

FormatJS поддерживает вложенные plural-выражения, но важно учитывать приоритеты парсинга ICU: каждое вложение является отдельным поддеревом AST.

Пример глубокой вложенности:

"{users, plural,
  one {{
    messages, plural,
      one {# пользователь и # сообщение}
      other {# пользователь и # сообщений}
  }}
  other {{
    messages, plural,
      one {# пользователей и # сообщение}
      other {# пользователей и # сообщений}
  }}
}"

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

Комбинирование plural и select

На практике наиболее частая комбинация — plural + select. Это позволяет учитывать грамматические категории одновременно с числовыми формами.

Пример сообщения с контекстом действия:

"{action, select,
  invite {{
    count, plural,
      one {Приглашён # участник}
      other {Приглашено # участников}
  }}
  remove {{
    count, plural,
      one {Удалён # элемент}
      other {Удалено # элементов}
  }}
  other {{
    count, plural,
      one {Обновлён # элемент}
      other {Обновлено # элементов}
  }}
}"

Здесь plural отвечает за число, select — за семантику действия.

Использование offset в plural-комбинациях

offset позволяет сдвигать значение счётчика, исключая текущий элемент из отображаемого числа. Это особенно важно при формировании сообщений типа «ты и ещё N пользователей».

"{count, plural, offset:1
  one {Ты}
  other {Ты и ещё # человек}
}"

Комбинация offset с другими параметрами:

"{count, plural, offset:1
  one {{name} и ещё никто}
  other {{name} и ещё # человек}
}"

Offset изменяет семантику вычисления категории plural, но не влияет на внешний доступ к переменной count.

Форматирование чисел внутри plural

FormatJS позволяет применять форматирование number внутри plural-конструкций, что критично для локалей, где числа требуют разделителей или специфических форматов.

"{count, plural,
  one {# файл}
  other {{count, number} файлов}
}"

Здесь # и {count, number} могут давать разные визуальные результаты в зависимости от локали (например, 1 000 vs 1,000).

Совмещение plural с форматами даты и валют

Plural часто комбинируется с форматированием других типов данных:

"{count, plural,
  one {Сумма {price, number, currency} за # товар}
  other {Сумма {price, number, currency} за # товара}
}"

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

Множественные plural в одном сообщении

FormatJS допускает использование нескольких независимых plural-выражений в одной строке сообщения:

"В корзине {items, plural,
  one {# товар}
  other {# товаров}
} и {services, plural,
  one {# услуга}
  other {# услуг}
}"

Каждый plural обрабатывается отдельно, что позволяет формировать сложные составные фразы.

Приоритеты вычисления и порядок разрешения

При разборе ICU-сообщения FormatJS строит AST, где:

  1. Сначала разрешаются вложенные select
  2. Затем вычисляются plural-ветки
  3. После этого применяется форматирование (number, date, time)
  4. В конце происходит интерполяция строк

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

Комбинирование plural с динамическими ключами

В продвинутых сценариях ключи plural могут зависеть от внешних параметров, например:

const message = "{key, plural, one {# элемент} other {# элементов}}";

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

Влияние локали на комбинированные plural-конструкции

Одна и та же комбинация plural + select может вести себя по-разному в разных языках.

Пример:

  • в английском: one / other
  • в русском: one / few / many / other
  • в арабском: до шести категорий

Сообщение:

"{count, plural,
  one {# файл}
  few {# файла}
  many {# файлов}
  other {# файла}
}"

При добавлении select поведение становится ещё более зависимым от локали, так как plural выбирает категорию до применения select-ветвления.

Ошибки комбинирования plural

Типовые ошибки возникают при:

  • отсутствии категории other
  • попытке вложить некорректный синтаксис ICU
  • использовании переменных вне области видимости plural
  • конфликте offset и #

Пример некорректной конструкции:

"{count, plural, one {# файл}}"

Отсутствие other делает сообщение неполным и может приводить к fallback-логике.

Практика построения сложных сообщений

Сложные сообщения в FormatJS строятся как композиция:

  • plural для числовой грамматики
  • select для семантики
  • number/date для форматирования
  • вложенные блоки для контекста

Пример комплексной структуры:

"{status, select,
  active {{
    users, plural,
      one {# активный пользователь сейчас онлайн}
      other {# активных пользователей сейчас онлайн}
  }}
  inactive {{
    users, plural,
      one {# пользователь неактивен}
      other {# пользователей неактивны}
  }}
}"

Такая композиция формирует полноценную грамматическую систему внутри одного сообщения ICU, где plural является центральным механизмом согласования чисел с контекстом.