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

В реальных интерфейсах редко встречаются простые сообщения, зависящие только от числа или только от категории. Чаще требуется учитывать сразу несколько параметров: количество элементов, пол пользователя, статус объекта, режим отображения и другие условия. В 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 применяются следующие подходы:

1. Сначала plural, затем select

Если число влияет на грамматику сильнее, чем категория, его выносят наружу:

plural → select

Это снижает дублирование текстов.


2. Минимизация повторяющихся строк

Плохая практика:

Он оставил комментарий
Она оставила комментарий
Пользователь оставил комментарий

Хорошая практика:

{gender, select,
  male {Он}
  female {Она}
  other {Пользователь}
} оставил {count, plural, ...}

Так уменьшается дублирование и упрощается поддержка.


3. Вынос повторяющихся конструкций

Если внутри каждого select повторяется один и тот же plural, можно централизовать структуру:

{count, plural,
  one {{gender, select, male {...} female {...} other {...}}}
  other {{gender, select, male {...} female {...} other {...}}}
}

Хотя это увеличивает вложенность, оно уменьшает расхождения в логике.


Работа с русской локализацией

Русский язык требует точной обработки форм множественного числа. FormatJS использует CLDR-правила:

  • one — 1
  • few — 2–4
  • many — 0, 5–20, 25–30 и т.д.
  • other — технический fallback

При комбинировании с 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 {Она заняла #-е место}
    }
  }
}

Здесь добавляется третий слой логики, но структура остаётся прежней: внешний контекст → числовая форма.


Типичные ошибки при комбинировании

1. Потеря синхронизации форм

Если в одной ветке отсутствует few или many, поведение будет некорректным для русской локали.


2. Избыточная вложенность

Чрезмерное использование вложенных ICU-конструкций ухудшает поддержку:

select → plural → select → plural → select

Такая структура должна быть пересмотрена в пользу разбиения на несколько сообщений.


3. Дублирование текста

Повторение одинаковых строк в разных ветках select усложняет локализацию и увеличивает вероятность ошибок.


Оптимизация архитектуры сообщений

В крупных приложениях FormatJS часто используется совместно с системой шаблонов сообщений.

Подходы к оптимизации:

  • разделение сообщений по доменам (UI, уведомления, ошибки);
  • вынос gender-логики в отдельные ключи;
  • использование параметризации вместо дублирования текста;
  • ограничение вложенности до 2 уровней.

Практический паттерн: композиция сообщений

Вместо глубоких ICU-цепочек можно собирать сообщение из частей:

const subject = formatMessage({ id: 'user.gender.male' }, {});
const action = formatMessage({ id: 'comment.added', values: { count } });

return `${subject} ${action}`;

Так plural остаётся изолированным, а select не смешивается с числовой логикой.


Итоговая модель комбинирования

Комбинация select + plural в FormatJS строится на трёх принципах:

  • разделение логик: категория и число не должны конфликтовать;
  • иерархия условий: внешний контекст определяет форму, внутренний — количество;
  • полная поддержка локализации: каждая ветка обязана содержать все plural-формы.

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