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 в FormatJS не существует изолированно. Он всегда является частью более крупного сообщения, где одновременно могут использоваться:
numberselectКомбинация строится как вложенная грамматика ICU, где plural является узлом дерева сообщений.
Пример комбинирования с дополнительной переменной:
"{gender, select,
male {{count, plural, one {Он добавил # элемент} other {Он добавил # элементов}}}
female {{count, plural, one {Она добавила # элемент} other {Она добавила # элементов}}}
other {{count, plural, one {Добавлено # элемент} other {Добавлено # элементов}}}
}"
Здесь происходит двухуровневая диспетчеризация:
select определяет грамматический родpluralFormatJS поддерживает вложенные plural-выражения, но важно учитывать приоритеты парсинга ICU: каждое вложение является отдельным поддеревом AST.
Пример глубокой вложенности:
"{users, plural,
one {{
messages, plural,
one {# пользователь и # сообщение}
other {# пользователь и # сообщений}
}}
other {{
messages, plural,
one {# пользователей и # сообщение}
other {# пользователей и # сообщений}
}}
}"
Такой подход используется для случаев, где множественность зависит от нескольких независимых параметров.
На практике наиболее частая комбинация —
plural + select. Это позволяет учитывать грамматические
категории одновременно с числовыми формами.
Пример сообщения с контекстом действия:
"{action, select,
invite {{
count, plural,
one {Приглашён # участник}
other {Приглашено # участников}
}}
remove {{
count, plural,
one {Удалён # элемент}
other {Удалено # элементов}
}}
other {{
count, plural,
one {Обновлён # элемент}
other {Обновлено # элементов}
}}
}"
Здесь plural отвечает за число, select — за семантику действия.
offset позволяет сдвигать значение счётчика, исключая
текущий элемент из отображаемого числа. Это особенно важно при
формировании сообщений типа «ты и ещё N пользователей».
"{count, plural, offset:1
one {Ты}
other {Ты и ещё # человек}
}"
Комбинация offset с другими параметрами:
"{count, plural, offset:1
one {{name} и ещё никто}
other {{name} и ещё # человек}
}"
Offset изменяет семантику вычисления категории plural, но не влияет
на внешний доступ к переменной count.
FormatJS позволяет применять форматирование number
внутри plural-конструкций, что критично для локалей, где числа требуют
разделителей или специфических форматов.
"{count, plural,
one {# файл}
other {{count, number} файлов}
}"
Здесь # и {count, number} могут давать
разные визуальные результаты в зависимости от локали (например,
1 000 vs 1,000).
Plural часто комбинируется с форматированием других типов данных:
"{count, plural,
one {Сумма {price, number, currency} за # товар}
other {Сумма {price, number, currency} за # товара}
}"
Такой подход применяется в финансовых интерфейсах, где число элементов влияет на грамматику, а сумма требует локализованного валютного формата.
FormatJS допускает использование нескольких независимых plural-выражений в одной строке сообщения:
"В корзине {items, plural,
one {# товар}
other {# товаров}
} и {services, plural,
one {# услуга}
other {# услуг}
}"
Каждый plural обрабатывается отдельно, что позволяет формировать сложные составные фразы.
При разборе ICU-сообщения FormatJS строит AST, где:
number,
date, time)Это важно при комбинировании plural с другими конструкциями, так как порядок влияет на итоговую локализованную строку.
В продвинутых сценариях ключи plural могут зависеть от внешних параметров, например:
const message = "{key, plural, one {# элемент} other {# элементов}}";
где key может быть динамически подставляемым значением,
определяющим числовую категорию.
Одна и та же комбинация plural + select может вести себя
по-разному в разных языках.
Пример:
one / otherone / few / many / otherСообщение:
"{count, plural,
one {# файл}
few {# файла}
many {# файлов}
other {# файла}
}"
При добавлении select поведение становится ещё более
зависимым от локали, так как plural выбирает категорию до применения
select-ветвления.
Типовые ошибки возникают при:
otheroffset и #Пример некорректной конструкции:
"{count, plural, one {# файл}}"
Отсутствие other делает сообщение неполным и может
приводить к fallback-логике.
Сложные сообщения в FormatJS строятся как композиция:
Пример комплексной структуры:
"{status, select,
active {{
users, plural,
one {# активный пользователь сейчас онлайн}
other {# активных пользователей сейчас онлайн}
}}
inactive {{
users, plural,
one {# пользователь неактивен}
other {# пользователей неактивны}
}}
}"
Такая композиция формирует полноценную грамматическую систему внутри одного сообщения ICU, где plural является центральным механизмом согласования чисел с контекстом.