Механизм select в FormatJS основан на ICU MessageFormat
и предназначен для выбора текстового варианта в зависимости от
конкретного значения переменной. В отличие от plural,
который ориентирован на числовые формы, select работает с
произвольными строковыми ключами и используется для ветвления логики
формирования сообщения.
Базовая структура выражения:
{variable, select,
key1 {вариант 1}
key2 {вариант 2}
other {значение по умолчанию}
}
Ключевой элемент — сопоставление значения переменной с заранее
определёнными ветками. Если совпадение не найдено, используется
other.
В экосистеме FormatJS select применяется внутри
сообщений react-intl или напрямую через API форматирования
сообщений.
Пример базового сообщения:
const messages = {
status: {
id: 'user.status',
defaultMessage: '{status, select, active {Активен} inactive {Неактивен} pending {Ожидает} other {Неизвестно}}'
}
};
Использование:
intl.formatMessage(messages.status, {
status: 'active'
});
Результат:
Активен
Механизм выполняет строгое сравнение значения status с
ключами active, inactive,
pending.
Ключ other является обязательной частью устойчивых
сообщений. Он гарантирует корректное отображение даже при неожиданных
значениях переменной.
{role, select,
admin {Администратор}
user {Пользователь}
other {Гость}
}
Если role содержит значение moderator, не
предусмотренное в списке, будет выбрана ветка other.
Это предотвращает разрыв UI при изменении данных или расширении бизнес-логики.
Наиболее частые сценарии применения select связаны с
классификацией сущностей:
Пример статусов заказа:
const orderMessage = {
id: 'order.status',
defaultMessage:
'{status, select, created {Создан} paid {Оплачен} shipped {Отправлен} delivered {Доставлен} canceled {Отменён} other {Неизвестно}}'
};
intl.formatMessage(orderMessage, { status: 'shipped' });
FormatJS позволяет комбинировать select с другими
ICU-конструкциями, включая plural и интерполяцию
переменных.
Пример вложенности:
const message = {
id: 'notification.message',
defaultMessage:
'{gender, select, male {Он получил {count, plural, one {# сообщение} few {# сообщения} other {# сообщений}}} female {Она получила {count, plural, one {# сообщение} few {# сообщения} other {# сообщений}}} other {Пользователь получил {count, plural, one {# сообщение} few {# сообщения} other {# сообщений}}}}'
};
Здесь выполняется двухуровневая логика:
genderplural для
countВ react-intl select используется через
компонент FormattedMessage или хук
useIntl.
<FormattedMessage
id="profile.badge"
defaultMessage="{tier, select, gold {Золотой уровень} silver {Серебряный уровень} bronze {Бронзовый уровень} other {Без уровня}}"
values={{ tier: userTier }}
/>
const intl = useIntl();
const label = intl.formatMessage(
{
id: 'profile.badge',
defaultMessage:
'{tier, select, gold {Золото} silver {Серебро} bronze {Бронза} other {Нет}}'
},
{ tier: userTier }
);
select не выполняет типизацию значений. Все сравнения
происходят как строковые ключи.
Это означает:
active и Active считаются разными
значениямиПример:
{mode, select,
1 {Режим 1}
2 {Режим 2}
other {Неизвестно}
}
При передаче mode: 1 фактически используется строковое
сравнение "1".
select широко применяется для интерфейсных сообщений,
зависящих от состояния приложения.
Пример состояния загрузки:
const loadingMessage = {
id: 'app.loading',
defaultMessage:
'{state, select, idle {Ожидание} loading {Загрузка...} success {Готово} error {Ошибка} other {Неизвестно}}'
};
Такой подход позволяет централизовать текстовую логику без условных операторов в JSX.
Одно из ключевых применений — перенос части ветвлений из кода в слой локализации.
Пример отображения типа подписки:
const subscription = {
id: 'user.subscription',
defaultMessage:
'{plan, select, free {Бесплатный план} pro {Профессиональный план} enterprise {Корпоративный план} other {Неизвестный план}}'
};
Это позволяет:
if/else в UIFormatJS поддерживает использование нескольких переменных внутри
одного сообщения, где select управляет только одной из
них.
{
id: 'system.event',
defaultMessage:
'{env, select, prod {Продакшн} dev {Разработка} other {Среда}}: {status}'
}
В этом случае env управляет ветвлением, а
status подставляется напрямую.
Если переменная:
undefinednullто механизм переходит к other.
Пример:
{theme, select,
dark {Тёмная тема}
light {Светлая тема}
other {Стандартная тема}
}
При отсутствии theme всегда используется
other.
Одной из распространённых проблем является несоответствие ключей данных и ICU-шаблона:
Admin vs admin)"in progress" без кавычек
недопустим в ключах)Корректная форма:
{status, select,
in_progress {В процессе}
done {Завершено}
other {Неизвестно}
}
Нельзя использовать:
{status, select,
in progress {В процессе}
}
без нормализации ключа в in_progress.
До внедрения ICU-форматов логика часто выглядела так:
let label;
if (role === 'admin') {
label = 'Администратор';
} else if (role === 'user') {
label = 'Пользователь';
} else {
label = 'Гость';
}
С использованием select:
const message = '{role, select, admin {Администратор} user {Пользователь} other {Гость}}';
Это переносит ветвление в декларативную форму, совместимую с системой переводов FormatJS.
FormatJS компилирует ICU-строки в эффективные функции форматирования.
select обрабатывается как hash-lookup по ключам, что
обеспечивает:
В больших приложениях select становится частью стандарта
описания UI-состояний:
Типичная архитектура предполагает хранение сообщений отдельно от
компонентов, где select служит декларативным
маршрутизатором текстов внутри строки.