В системе сообщений ICU MessageFormat, которую использует FormatJS,
механизм выбора вариантов не ограничивается диапазонами
(one, few, other) или условными
селекторами (select). Одним из наиболее строгих и при этом
часто недооценённых инструментов являются точные совпадения через
оператор =.
Они позволяют привязывать конкретное значение переменной напрямую к строке перевода, минуя любые правила множественных форм или классификации.
Формат ICU MessageFormat допускает использование конструкции:
{variable, plural,
=0 {...}
=1 {...}
other {...}
}
или в более общем виде:
{variable, select,
=value {...}
other {...}
}
Ключевой элемент — запись =n, где n
представляет конкретное числовое значение.
Это не диапазон, не категория и не правило языка. Это строгое сравнение.
=n в plural-правилахПри использовании plural система обычно опирается на
CLDR-правила языка, которые определяют формы вроде one,
few, many, other.
Однако =n имеет приоритет выше любых категорий.
Пример:
{count, plural,
=0 {Нет элементов}
=1 {Один элемент}
one {# элемент}
other {# элементов}
}
Если count === 1, будет выбрано именно
=1 {Один элемент}, а не one.
Это критично для случаев, где бизнес-логика требует полного контроля над отдельными значениями.
Система выбора в ICU MessageFormat работает по строгой иерархии:
=none, few,
many, other)other как универсальный fallbackТаким образом, даже если языковая модель предлагает альтернативу, точное совпадение всегда выигрывает.
{messages, plural,
=0 {Нет новых сообщений}
=1 {Одно новое сообщение}
=2 {Два сообщения}
few {Несколько сообщений}
other {# сообщений}
}
Здесь явно задаются отдельные строки для 0, 1 и 2, несмотря на то что язык может уже иметь свои правила для этих значений.
Оператор = работает не только с числовыми
plural-формами, но и в select, где сравниваются строки.
Пример:
{status, select,
=draft {Черновик}
=published {Опубликовано}
=archived {Архивировано}
other {Неизвестный статус}
}
Здесь status сравнивается буквально, без преобразований
и без языковой логики.
=Без точного совпадения запись выглядела бы так:
{status, select,
draft {Черновик}
published {Опубликовано}
archived {Архивировано}
other {Неизвестный статус}
}
Однако добавление = усиливает семантику: значение
воспринимается как строгое равенство, а не как ключ категории.
В большинстве реализаций ICU это избыточно для строковых ключей, но полезно для унификации стиля и предотвращения неоднозначности при динамической генерации шаблонов.
Точные совпадения часто применяются для защиты от неожиданных значений.
{count, plural,
=0 {Пусто}
=100 {Ровно сто элементов}
other {# элементов}
}
Даже если языковая система считает 100 обычным other,
разработчик может выделить его отдельно.
Если ни одно =n не совпало, система продолжает
стандартный путь:
otherЭто делает использование = безопасным: отсутствие
совпадения не ломает шаблон, а лишь переключает на стандартное
поведение.
Точные совпадения можно комбинировать с интерполяцией:
{count, plural,
=0 {Нет элементов}
=1 {Один элемент}
=2 {Два элемента}
other {Всего {count} элементов}
}
Здесь важно, что внутри блоков =n допустимы любые
вложенные выражения ICU, включая форматирование чисел, дат и других
параметров.
={count, plural,
=1 {Один}
one {Один (по правилам языка)}
}
Вторая ветка фактически становится недостижимой при
count === 1.
=1, =2, =3, =4, =5 ...
Такой подход превращает plural-логику в ручной switch-case, нарушая идею ICU и усложняя поддержку.
=
без необходимостиВо многих случаях достаточно категорий one/few/many.
= оправдан только при необходимости строгого контроля
отдельных значений.
Конструкция =n фактически вводит уровень
детерминированной логики в декларативную систему форматирования.
Она переводит часть ответственности с языковых правил на бизнес-логику, позволяя:
В связке с FormatJS точные совпадения особенно полезны в интерфейсах, где важны:
Если значение переменной вычисляется во время выполнения:
const count = getCount();
то ICU сравнивает его строго:
count === 0 → =0count === 1 → =1other или категория pluralВажно учитывать типизацию: строка "1" не всегда равна
числу 1 в зависимости от реализации парсинга.
Хотя = даёт полный контроль, он может снижать
переносимость переводов:
=nПоэтому такие конструкции обычно используются точечно, а не повсеместно.
В крупных приложениях ICU-шаблоны часто делятся на уровни:
one, other)=n=n занимает верхний слой этой иерархии, задавая жёсткие
поведенческие якоря внутри гибкой системы локализации.