Система плюрализации в Globalize основана на стандартах CLDR (Common Locale Data Repository), где для каждого языка определяются правила выбора формы множественного числа. В отличие от упрощённого подхода «один / много», реальная лингвистическая модель включает несколько категорий, зависящих от языка и числового значения.
Ключевые категории CLDR:
Не каждый язык использует все категории. Например, английский
ограничивается двумя: one и other, тогда как
славянские языки используют минимум три, а арабские — до шести
категорий.
Globalize не «угадывает» правила, а опирается на загруженные CLDR-данные, что делает поведение предсказуемым и локализованным.
Globalize требует явной загрузки необходимых частей CLDR: языковых данных, числовых форматов и правил плюрализации.
import Globalize from "globalize";
import likelySubtags from "cldr-data/supplemental/likelySubtags.json";
import plurals from "cldr-data/supplemental/plurals.json";
import ruNumbers from "cldr-data/main/ru/numbers.json";
Globalize.load(likelySubtags);
Globalize.load(plurals);
Globalize.load(ruNumbers);
const globalize = new Globalize("ru");
Без подключения supplemental/plurals.json механизм
выбора форм множественного числа работать не будет, поскольку именно там
описаны языковые правила.
Globalize использует метод plural(),
который возвращает категорию для числа в заданной локали.
globalize.plural(1); // "one"
globalize.plural(2); // "few"
globalize.plural(5); // "many"
Для русского языка логика соответствует правилам:
Важно, что в разных локалях эти правила кардинально отличаются.
Русский, украинский, польский и ряд других языков демонстрируют более сложную систему, основанную не только на последней цифре, но и на диапазонах чисел.
| Число | Категория |
|---|---|
| 1 | one |
| 2–4 | few |
| 5–20 | many |
| 21 | one |
| 22–24 | few |
| 25+ | many |
Особенность заключается в модуле 10 и 100:
n % 10 === 1 и n % 100 !== 11 → onen % 10 in 2..4 и n % 100 not in 12..14 →
fewGlobalize абстрагирует эти вычисления, предоставляя готовую категорию.
Plural-правила чаще всего применяются не напрямую, а через шаблоны сообщений.
const message = {
one: "{count} книга",
few: "{count} книги",
many: "{count} книг"
};
function format(count) {
const category = globalize.plural(count);
return message[category].replace("{count}", count);
}
format(1); // 1 книга
format(3); // 3 книги
format(10); // 10 книг
messageFormatterGlobalize предоставляет более системный способ через
messageFormatter, где plural-ветвление встроено в
синтаксис.
const formatter = globalize.messageFormatter({
one: "{count} книга",
few: "{count} книги",
many: "{count} книг"
});
formatter({ count: 1 });
formatter({ count: 3 });
formatter({ count: 10 });
Globalize сам определяет категорию и выбирает нужную ветку.
Plural-формы могут быть частью более сложных сообщений, включая вложенные параметры и дополнительные условия.
const formatter = globalize.messageFormatter({
one: "{name} добавил {count} файл",
few: "{name} добавил {count} файла",
many: "{name} добавил {count} файлов"
});
formatter({ name: "Иван", count: 2 });
В реальных системах локализации такие структуры часто комбинируются с датами, числами и валютами.
zero и otherНе все языки игнорируют ноль. Например:
0 files → otherzero используется активноПример (гипотетическая логика для языков с zero):
{
zero: "нет файлов",
one: "{count} файл",
other: "{count} файлов"
}
Арабский язык использует до шести категорий:
Правила зависят от диапазонов:
Globalize обрабатывает это автоматически при корректно загруженных CLDR-данных.
Существуют языки, где форма множественного числа фактически не различается. Например, японский и китайский.
В таких случаях CLDR возвращает всегда:
otherПример:
globalize.plural(1); // "other"
globalize.plural(5); // "other"
Шаблоны сообщений обычно имеют одну форму:
{
other: "{count} 件"
}
Globalize приводит значения к нормализованному виду перед вычислением категории:
globalize.plural(-1); // "one"
globalize.plural(1.0); // "one"
globalize.plural(1.2); // зависит от языка
Plural-логика часто используется совместно с
numberFormatter, поскольку итоговая строка должна содержать
корректно локализованное число.
const numberFormatter = globalize.numberFormatter();
const formatter = globalize.messageFormatter({
one: "{n} элемент",
few: "{n} элемента",
many: "{n} элементов"
});
const n = 21;
formatter({ n: numberFormatter(n) });
Это важно для языков, где формат числа влияет на восприятие формы.
При попытке реализовать plural-правила вручную часто возникают ошибки:
n === 1Globalize устраняет эти проблемы за счёт стандартизации CLDR.
Определение категории множественного числа в Globalize:
Это делает механизм пригодным для высоконагруженных интерфейсов, включая SSR и клиентские приложения.
В реальных интерфейсах plural-логика редко используется изолированно. Она комбинируется с:
Пример комбинированного сообщения:
const formatter = globalize.messageFormatter({
one: "На {date} будет {count} событие",
few: "На {date} будет {count} события",
many: "На {date} будет {count} событий"
});
Главная сложность plural-системы заключается не в вычислениях, а в поддержании согласованности:
Globalize обеспечивает эту согласованность через единый слой абстракции над CLDR-данными.