Система множественных форм в Unicode CLDR (Common Locale Data Repository) является основой для интернационализации числовых выражений в современных JavaScript-библиотеках, включая FormatJS. Она определяет набор категорий, которые используются для выбора правильной формы слова в зависимости от числа.
В FormatJS и API Intl.PluralRules эти категории
применяются для построения локализованных сообщений, где грамматическая
форма зависит от числового значения.
Разные языки по-разному обрабатывают числа. В английском языке достаточно двух форм:
В то время как в других языках система значительно сложнее. CLDR вводит унифицированный набор категорий:
Каждая локаль использует подмножество этих категорий.
zeroКатегория zero используется в языках, где ноль имеет
отдельную грамматическую форму.
Примеры поведения:
otherПример использования через Intl.PluralRules:
const pr = new Intl.PluralRules('ar');
pr.select(0); // "zero"
oneКатегория one соответствует форме единственного
числа.
Она присутствует в большинстве языков, но её математическое определение зависит от локали.
Примеры:
const pr = new Intl.PluralRules('en');
pr.select(1); // "one"
twoКатегория two встречается в ограниченном числе языков и
используется для обозначения пары или двойственного числа.
Характерные особенности:
const pr = new Intl.PluralRules('ar');
pr.select(2); // "two"
fewКатегория few используется для небольших чисел, которые
не равны 1 или 2, но попадают в специальный грамматический диапазон.
Особенности:
Пример для русского языка:
const pr = new Intl.PluralRules('ru');
pr.select(3); // "few"
pr.select(4); // "few"
manyКатегория many применяется для больших чисел или
специфических диапазонов, которые не подпадают под one,
few или other.
Особенности:
const pr = new Intl.PluralRules('ar');
pr.select(11); // "many"
pr.select(100); // "many"
otherКатегория other является универсальной и используется
как fallback.
Она применяется:
Пример:
const pr = new Intl.PluralRules('en');
pr.select(5); // "other"
pr.select(0); // "other"
FormatJS использует CLDR через Intl.PluralRules и ICU
Message Syntax.
Пример сообщения:
import { defineMessages, useIntl } from 'react-intl';
const messages = defineMessages({
items: {
id: 'cart.items',
defaultMessage: `
{count, plural,
one {# товар}
few {# товара}
many {# товаров}
other {# товара}
}
`
}
});
В этом примере движок выбирает форму в зависимости от категории, возвращаемой CLDR.
en)Используются только:
1 → one
2, 3, 10 → other
ru)Используются:
1 → one
2–4 → few
5–20 → many
ar)Используются все категории:
0 → zero
1 → one
2 → two
3–10 → few
11–99 → many
100+ → other
Определение категории происходит через алгоритмы CLDR, основанные на:
JavaScript API инкапсулирует эти правила:
const pr = new Intl.PluralRules('ru');
pr.select(21); // "one"
pr.select(22); // "few"
pr.select(25); // "many"
FormatJS применяет ICU MessageFormat, где категории напрямую связаны с ключами:
{value, plural,
zero {нет элементов}
one {# элемент}
few {# элемента}
many {# элементов}
other {# элемента}
}
Каждая ветка соответствует конкретной категории CLDR.
Частые проблемы при реализации:
one/other для языков со сложной
морфологиейzero, что приводит к некорректным
формулировкамIntl.PluralRulesНативный API JavaScript полностью основан на CLDR:
new Intl.PluralRules('ru').resolvedOptions();
Результат включает информацию о локали и типе правил, но не раскрывает внутренние диапазоны — они определяются CLDR.
CLDR выполняет функцию стандарта, обеспечивающего:
Система категорий позволяет отделить логику языка от кода приложения, делая форматирование чисел декларативным.