В международной локализации ключевая сложность возникает в момент, когда язык перестаёт оперировать простой бинарной моделью singular/plural. Библиотека Globalize опирается на данные CLDR (Unicode Common Locale Data Repository), где правила плюрализации описываются через набор категорий и функций выбора формы в зависимости от числового значения.
CLDR вводит универсальную модель категорий:
Не каждый язык использует весь набор категорий. Однако архитектура Globalize предполагает их поддержку как универсального интерфейса, позволяющего унифицировать обработку форм.
В основе работы лежит функция, определяющая категорию числа в зависимости от локали:
const Globalize = require("globalize");
// предполагается предварительная загрузка CLDR-данных
Globalize.locale("ru");
const pluralGenerator = Globalize.pluralGenerator();
Функция генератора возвращает определение категории для конкретного числа:
pluralGenerator(1); // "one"
pluralGenerator(2); // "few"
pluralGenerator(5); // "many"
Эти категории затем используются при формировании строк через
messageFormatter.
Под «нестандартной плюрализацией» понимаются языки, в которых:
Globalize не содержит собственных правил, а делегирует их CLDR. Это позволяет одинаково обрабатывать даже крайне сложные системы.
Русский язык использует три категории:
Функция выбора в CLDR учитывает последние две цифры числа:
onefewmanyПример использования Globalize:
const formatter = Globalize.messageFormatter({
one: "{count} файл",
few: "{count} файла",
many: "{count} файлов"
});
formatter({ count: 1 }); // 1 файл
formatter({ count: 3 }); // 3 файла
formatter({ count: 10 }); // 10 файлов
Польская система ещё более детализирована:
Особенность заключается в перекрытии диапазонов и необходимости строгой проверки десятков.
const formatter = Globalize.messageFormatter({
one: "{count} plik",
few: "{count} pliki",
many: "{count} plików"
});
Арабская локаль представляет один из самых сложных случаев в CLDR:
Globalize использует эти категории напрямую, без упрощения.
const formatter = Globalize.messageFormatter({
zero: "لا ملفات",
one: "ملف واحد",
two: "ملفان",
few: "{count} ملفات",
many: "{count} ملفًا",
other: "{count} ملف"
});
Особенность заключается в том, что даже числа 100 и выше могут
попадать в категорию other, что требует строгого следования
CLDR-правилам.
Некоторые языки сохраняют категорию dual, формально
отображаемую как two.
Примеры:
В CLDR эта категория унифицирована, но поведение зависит от локали.
Исландская система демонстрирует зависимость от грамматической формы, а не только от числового значения.
Категории:
Но выбор формы может зависеть от контекста существительного, что усложняет шаблоны сообщений.
const formatter = Globalize.messageFormatter({
one: "{count} skrá",
other: "{count} skrár"
});
Нулевая форма (zero) не универсальна. В ряде языков:
many (русский, польский);Globalize сохраняет явную поддержку категории, но её наличие зависит от CLDR-данных конкретной локали.
Типичный поток работы включает:
Globalize.locale("ru");
const formatter = Globalize.messageFormatter({
one: "{count} элемент",
few: "{count} элемента",
many: "{count} элементов"
});
const result = formatter({ count: 23 });
Внутренне происходит:
pluralGeneratorНекоторые языки требуют обработки не только одиночных чисел, но и диапазонов:
const formatter = Globalize.messageFormatter({
one: "{count} запись",
few: "{count} записи",
many: "{count} записей",
"one..few": "{count} записи (диапазон)"
});
Хотя CLDR напрямую не оперирует такими ключами, Globalize позволяет расширять шаблоны поверх базовой системы.
В большинстве локалей дробные значения автоматически попадают в
категорию other:
pluralGenerator(1.2); // "other"
pluralGenerator(0.5); // "other"
Однако в некоторых языках (например, в французском) поведение может
быть смещено в сторону one при округлении.
| Тип языка | Количество категорий | Характеристика |
|---|---|---|
| Английский | 2 | простая бинарная модель |
| Русский | 3 | зависимость от последних цифр |
| Польский | 3–4 | сложные диапазоны |
| Арабский | 5–6 | многоступенчатая система |
| Исландский | 2 | синтаксическая зависимость |
При попытке самостоятельно реализовать плюрализацию без CLDR часто возникают проблемы:
Globalize устраняет эти ошибки за счёт полной делегации правил внешнему репозиторию CLDR.
CLDR хранит правила в виде выражений:
i = integer part
v = visible fraction digits
n = number
t = trailing zeros
Пример правила:
n mod 10 in 2..4 and n mod 100 not in 12..14 -> few
Эти выражения интерпретируются библиотекой и не требуют ручной обработки.
Если данные CLDR для локали неполные:
otherЭто обеспечивает предсказуемость даже при частичной загрузке данных.
Плюрализация редко используется изолированно. В Globalize она интегрируется с:
const formatter = Globalize.messageFormatter({
one: "{count} файл загружен {date}",
few: "{count} файла загружено {date}",
many: "{count} файлов загружено {date}"
});
Система комбинирует несколько локализационных подсистем в едином шаблоне.