В реальных интерфейсах редко встречаются простые сообщения, зависящие
только от числа или только от категории. Чаще требуется учитывать сразу
несколько параметров: количество элементов, пол пользователя, статус
объекта, режим отображения и другие условия. В FormatJS это решается
через вложенные ICU-выражения, где plural и
select комбинируются в одном сообщении.
ICU MessageFormat поддерживает вложенные конструкции, где одно
условие становится частью другого. Наиболее частый сценарий — внешний
select (например, пол), внутри которого находится
plural (количество).
Общий шаблон выглядит так:
{variable, select,
case {
other { ... {count, plural, ...} ... }
}
}
Ключевой принцип: sel ect определяет контекст, plural уточняет количественное значение внутри этого контекста.
Рассмотрим сообщение о комментариях, где учитывается пол автора и количество комментариев:
import { formatMessage } fr om 'formatjs';
const message = `
{gender, select,
male {
{count, plural,
one {Он оставил # комментарий}
few {Он оставил # комментария}
many {Он оставил # комментариев}
other {Он оставил # комментария}
}
}
female {
{count, plural,
one {Она оставила # комментарий}
few {Она оставила # комментария}
many {Она оставила # комментариев}
other {Она оставила # комментария}
}
}
other {
{count, plural,
one {Пользователь оставил # комментарий}
few {Пользователь оставил # комментария}
many {Пользователь оставил # комментариев}
other {Пользователь оставил # комментария}
}
}
}
`;
formatMessage(message, { gender: 'male', count: 3 });
Здесь:
select выбирает форму обращения;plural определяет грамматическую форму
числа;# автоматически подставляет значение
count.FormatJS допускает более сложные комбинации, где select
может находиться внутри plural, хотя это используется реже
из-за усложнения читаемости.
Пример: разные формулировки для одного и нескольких объектов с дополнительной категорией:
const message = `
{count, plural,
one {
{type, select,
photo {Добавлена фотография}
video {Добавлено видео}
other {Добавлен файл}
}
}
other {
{type, select,
photo {Добавлено # фотографии}
video {Добавлено # видео}
other {Добавлено # файлов}
}
}
}
`;
Здесь:
select уточняет тип контента.При усложнении ICU-выражений возникает риск потери читаемости. Поэтому в практике FormatJS применяются следующие подходы:
Если число влияет на грамматику сильнее, чем категория, его выносят наружу:
plural → select
Это снижает дублирование текстов.
Плохая практика:
Он оставил комментарий
Она оставила комментарий
Пользователь оставил комментарий
Хорошая практика:
{gender, select,
male {Он}
female {Она}
other {Пользователь}
} оставил {count, plural, ...}
Так уменьшается дублирование и упрощается поддержка.
Если внутри каждого select повторяется один и тот же
plural, можно централизовать структуру:
{count, plural,
one {{gender, select, male {...} female {...} other {...}}}
other {{gender, select, male {...} female {...} other {...}}}
}
Хотя это увеличивает вложенность, оно уменьшает расхождения в логике.
Русский язык требует точной обработки форм множественного числа. FormatJS использует CLDR-правила:
При комбинировании с select важно помнить, что каждая
ветка должна содержать полный набор plural-форм:
{gender, select,
male {
{count, plural,
one {Он добавил # файл}
few {Он добавил # файла}
many {Он добавил # файлов}
other {Он добавил # файла}
}
}
female {
{count, plural,
one {Она добавила # файл}
few {Она добавила # файла}
many {Она добавила # файлов}
other {Она добавила # файла}
}
}
}
Ошибка в одной ветке приводит к несогласованности интерфейса.
selectordinal вместе с plural и selectИногда требуется учитывать порядковые числительные:
{gender, select,
male {
{rank, selectordinal,
one {Он занял #-е место}
two {Он занял #-е место}
few {Он занял #-е место}
other {Он занял #-е место}
}
}
female {
{rank, selectordinal,
one {Она заняла #-е место}
two {Она заняла #-е место}
few {Она заняла #-е место}
other {Она заняла #-е место}
}
}
}
Здесь добавляется третий слой логики, но структура остаётся прежней: внешний контекст → числовая форма.
Если в одной ветке отсутствует few или
many, поведение будет некорректным для русской локали.
Чрезмерное использование вложенных ICU-конструкций ухудшает поддержку:
select → plural → select → plural → select
Такая структура должна быть пересмотрена в пользу разбиения на несколько сообщений.
Повторение одинаковых строк в разных ветках select
усложняет локализацию и увеличивает вероятность ошибок.
В крупных приложениях FormatJS часто используется совместно с системой шаблонов сообщений.
Подходы к оптимизации:
Вместо глубоких ICU-цепочек можно собирать сообщение из частей:
const subject = formatMessage({ id: 'user.gender.male' }, {});
const action = formatMessage({ id: 'comment.added', values: { count } });
return `${subject} ${action}`;
Так plural остаётся изолированным, а select не смешивается с числовой логикой.
Комбинация select + plural в FormatJS строится на трёх
принципах:
Эта модель позволяет строить масштабируемые интерфейсные сообщения, пригодные для сложных мультиязычных систем без потери грамматической точности.