Intl.PluralRules — это часть стандарта ECMAScript
Internationalization API, предназначенная для определения формы
множественного числа в зависимости от языка и числа. Основная задача API
— корректный выбор грамматической формы (например, «1 товар», «2
товара», «5 товаров») с учётом правил конкретной локали.
Ключевая проблема, которую решает Intl.PluralRules,
заключается в том, что правила множественного числа в разных языках
существенно различаются. Например:
Intl.PluralRules абстрагирует эти правила, предоставляя
унифицированный API.
Создание экземпляра происходит с указанием локали:
const rules = new Intl.PluralRules('ru-RU');
rules.select(1); // "one"
rules.select(2); // "few"
rules.select(5); // "many"
Метод select() возвращает категорию множественного
числа:
"zero""one""two""few""many""other"Важно понимать, что возвращаемые значения — это не сами слова языка, а абстрактные категории, используемые в CLDR (Common Locale Data Repository).
const ruRules = new Intl.PluralRules('ru-RU');
function formatCount(count) {
const rule = ruRules.select(count);
const forms = {
one: 'товар',
few: 'товара',
many: 'товаров',
other: 'товара'
};
return `${count} ${forms[rule]}`;
}
formatCount(1); // 1 товар
formatCount(3); // 3 товара
formatCount(10); // 10 товаров
Такой подход уже позволяет реализовать базовую локализацию без сторонних библиотек, но становится сложным при масштабировании.
Несмотря на стандартизацию, Intl.PluralRules имеет ряд
ограничений:
Именно здесь появляется необходимость в полифилле.
Экосистема FormatJS предоставляет полноценный полифилл
Intl.PluralRules, обеспечивающий:
Основной пакет:
npm install @formatjs/intl-pluralrules
Для глобального расширения Intl:
import '@formatjs/intl-pluralrules/polyfill';
После подключения объект Intl.PluralRules становится
доступным даже в средах, где он отсутствует.
Полифилл не включает все языки по умолчанию, чтобы уменьшить размер бандла. Локали подключаются отдельно:
import '@formatjs/intl-pluralrules/locale-data/en';
import '@formatjs/intl-pluralrules/locale-data/ru';
import '@formatjs/intl-pluralrules/locale-data/de';
Это позволяет контролировать размер приложения.
После полифилла API остаётся полностью идентичным стандартному:
const rules = new Intl.PluralRules('ru');
console.log(rules.select(1)); // one
console.log(rules.select(2)); // few
console.log(rules.select(5)); // many
Разница заключается в том, что теперь поведение гарантировано даже в средах без нативной поддержки.
Полифилл состоит из нескольких уровней:
Базовый слой реализует:
Используются данные Unicode CLDR:
Это позволяет добиться поведения, идентичного нативной реализации современных браузеров.
Shim-слой подменяет глобальный Intl.PluralRules:
if (!global.Intl.PluralRules) {
global.Intl.PluralRules = PolyfilledPluralRules;
}
Одно из ключевых преимуществ полифилла — модульная загрузка локалей.
import '@formatjs/intl-pluralrules/polyfill';
import '@formatjs/intl-pluralrules/locale-data/ru';
Такой подход:
Хотя Intl.PluralRules работает отдельно, в реальных
приложениях он часто используется вместе с ICU MessageFormat.
Пример:
const rules = new Intl.PluralRules('ru');
const messages = {
one: '{count} файл',
few: '{count} файла',
many: '{count} файлов'
};
function format(count) {
return messages[rules.select(count)].replace('{count}', count);
}
В Node.js важно обеспечить одинаковое поведение на сервере и клиенте.
Полифилл позволяет:
Пример SSR:
import '@formatjs/intl-pluralrules/polyfill';
import '@formatjs/intl-pluralrules/locale-data/ru';
export function render(count) {
const rules = new Intl.PluralRules('ru');
return rules.select(count);
}
Полифилл оптимизирован для:
Однако следует учитывать:
PluralRules может быть
дороже кешированного вариантаРекомендуется:
const ruRules = new Intl.PluralRules('ru');
вместо создания на каждый вызов.
| Характеристика | Нативный Intl | FormatJS polyfill |
|---|---|---|
| Поддержка старых браузеров | Нет | Да |
| Полнота локалей | Зависит от браузера | Полная CLDR база |
| Поведение | Может отличаться | Стандартизировано |
| Tree-shaking локалей | Нет | Да |
new Intl.PluralRules(); // поведение зависит от окружения
Корректно:
new Intl.PluralRules('ru');
const forms = {
one: 'file',
other: 'files'
};
Ошибка: в русском языке недостаточно двух форм.
function format(n) {
return new Intl.PluralRules('ru').select(n);
}
Это ухудшает производительность.
В масштабных системах локализации Intl.PluralRules часто
является базовым строительным блоком:
В экосистеме FormatJS он используется совместно с:
react-intlintl-messageformat@formatjs/intl polyfillsПример различий:
new Intl.PluralRules('en').select(1); // one
new Intl.PluralRules('en').select(2); // other
new Intl.PluralRules('ru').select(1); // one
new Intl.PluralRules('ru').select(2); // few
new Intl.PluralRules('ru').select(5); // many
new Intl.PluralRules('ar').select(0); // zero
new Intl.PluralRules('ar').select(2); // two
new Intl.PluralRules('ar').select(3); // few
Эти различия невозможно корректно реализовать вручную без CLDR-таблиц.
Intl.PluralRules можно рассматривать как:
Полифилл обеспечивает, чтобы этот слой оставался стабильным во всех средах исполнения, независимо от поддержки браузера или Node.js версии.