В системе i18next обработка множественных форм основана на правилах
CLDR (Common Locale Data Repository), где каждая локаль имеет
собственный набор категорий: zero, one,
two, few, many,
other. Библиотека автоматически выбирает нужную форму на
основе значения count, однако корректность результата
зависит от структуры переводов и соответствия языковым правилам.
Основной принцип: значение count определяет ключ,
который будет использован при выборе перевода. Ошибка возникает, когда
структура ресурсов не учитывает все формы или когда используется
упрощённая схема с одной-двумя формами для языков, где требуется больше
вариантов.
В i18next допускаются два основных подхода:
item_one
item_few
item_many
item_other
или более компактный вариант:
item
item_plural
Однако упрощённый вариант корректен только для языков с бинарной системой (например, английский), где различаются только singular/plural.
Пример конфигурации:
{
"item_one": "{{count}} предмет",
"item_few": "{{count}} предмета",
"item_many": "{{count}} предметов",
"item_other": "{{count}} предметов"
}
Одной из наиболее частых проблем становится использование только двух форм в языках с более сложной морфологией.
Пример некорректной структуры:
{
"item_one": "{{count}} элемент",
"item_other": "{{count}} элементов"
}
Для русского языка этого недостаточно, поскольку отсутствуют формы
few и many. В результате библиотека вынуждена
подставлять fallback, что приводит к грамматически неправильным
строкам.
Русская локаль использует три основные формы:
one — 1, 21, 31, 41…few — 2–4, 22–24, 32–34…many — 0, 5–20, 25–30…other — резервная формаi18next маппит эти правила автоматически, но только при наличии соответствующих ключей.
Корректная структура:
{
"car_one": "{{count}} машина",
"car_few": "{{count}} машины",
"car_many": "{{count}} машин"
}
Ключевой источник ошибок — некорректная передача count.
i18next использует его для выбора формы.
Пример корректного вызова:
i18next.t('car', { count: 5 });
При этом ресурс должен быть структурирован как:
{
"car_one": "машина",
"car_few": "машины",
"car_many": "машин"
}
Если count передаётся как строка, возможны ошибки
приведения типов, особенно при использовании кастомных интерполяций:
i18next.t('car', { count: "5" });
В этом случае поведение зависит от конфигурации
returnObjects и внутренних преобразований.
Частая ошибка связана с рассинхронизацией ключей в разных namespace.
Пример:
i18next.t('common:car', { count: 2 });
Если в common отсутствует car_few, система
может перейти к fallback-локали или использовать other, что
ломает грамматическую корректность.
Некоторые языки выделяют отдельную форму zero. В i18next
она поддерживается, но часто не используется.
Ошибка:
{
"message_one": "сообщение",
"message_other": "сообщения"
}
При count = 0 может потребоваться отдельная форма:
{
"message_zero": "сообщений нет",
"message_one": "1 сообщение",
"message_few": "{{count}} сообщения",
"message_many": "{{count}} сообщений"
}
Отсутствие zero приводит к неестественным формулировкам
вроде «0 сообщений» там, где требуется специальная семантика.
i18next позволяет комбинировать pluralization и interpolation:
{
"apples_one": "Есть {{count}} яблоко",
"apples_few": "Есть {{count}} яблока",
"apples_many": "Есть {{count}} яблок"
}
Ошибка возникает при попытке использовать вложенные выражения:
{
"apples_many": "Есть {{formatCount count}} яблок"
}
Функции интерполяции не должны вмешиваться в выбор plural key. Нарушение этого правила приводит к тому, что plural resolver работает с некорректным значением.
При отсутствии формы в текущей локали i18next обращается к fallback.
Конфигурация:
i18next.init({
fallbackLng: 'en'
});
Проблема возникает, когда fallback локаль имеет другую систему plural
forms. Например, английский использует только one/other, а
русский требует few/many. В результате fallback может
возвращать грамматически неправильные строки.
_pluralУпрощённый формат:
{
"item": "item",
"item_plural": "items"
}
Работает только для языков с бинарной системой. При использовании в
русской локали происходит деградация до other, что создаёт
систематические ошибки в формах 2–4 и 5+.
i18next позволяет переопределять правила:
i18next.init({
pluralResolver: {
getPluralFormsOfKey: () => []
}
});
Ошибочная реализация приводит к тому, что все значения
count сводятся к одному ключу. Это полностью ломает систему
морфологии и делает локализацию статической.
При использовании i18next-icu появляется альтернативный
синтаксис:
{count, plural, one {# файл} few {# файла} many {# файлов}}
Конфликт возникает при смешивании ICU и стандартных суффиксов i18next. В этом случае:
При объединении ресурсов через merge возможна
ситуация:
{
"file_one": "файл"
}
и позже:
{
"file_few": "файла"
}
Если структура загрузки непоследовательна, часть форм может быть перезаписана или потеряна, особенно при асинхронной загрузке namespace.
Антипаттерн:
i18next.t(`item_${type}`, { count });
Если type не синхронизирован с plural системой,
возникает расхождение между выбранной формой и фактическим
count. Это приводит к несоответствию:
Часто plural формы проектируются без учёта интерфейсной логики:
zeroВ результате логика интерфейса и языковая модель расходятся, и i18next не может компенсировать это автоматически без явного определения всех форм.