Перейти к основному содержимому

`Intl.ListFormat`

· 3 мин. чтения
Матиас Биненс ([@mathias](https://twitter.com/mathias)) и Фрэнк Юнг-Фонг Танг

Современные веб-приложения часто используют списки, состоящие из динамических данных. Например, приложение для просмотра фотографий может отображать что-то вроде:

Эта фотография включает Аду, Эдит и Грейс.

Текстовая игра может иметь другой вид списка:

Выберите свою суперсилу: невидимость, психокинез или эмпатию.

Так как у каждого языка есть свои собственные правила форматирования списков и слова, реализация локализованного форматирования списка является нетривиальной задачей. Это требует не только списка всех слов (например, «и» или «или» в приведенных выше примерах) для каждого поддерживаемого языка — к тому же нужно описать точные правила форматирования для всех этих языков! Unicode CLDR предоставляет эти данные, но чтобы использовать их в JavaScript, их нужно интегрировать и включить в библиотеку. Это, к сожалению, увеличивает размер пакета для таких библиотек, что негативно сказывается на времени загрузки, стоимости обработки/компиляции и потреблении памяти.

Совершенно новый API Intl.ListFormat перекладывает эту задачу на JavaScript-движок, который может предоставлять данные локализации и делать их доступными непосредственно разработчикам JavaScript. Intl.ListFormat позволяет локализованно форматировать списки без ущерба для производительности.

Примеры использования

Следующий пример показывает, как создать форматтер списка для соединений, используя английский язык:

const lf = new Intl.ListFormat('en');
lf.format(['Frank']);
// → 'Frank'
lf.format(['Frank', 'Christine']);
// → 'Frank and Christine'
lf.format(['Frank', 'Christine', 'Flora']);
// → 'Frank, Christine, and Flora'
lf.format(['Frank', 'Christine', 'Flora', 'Harrison']);
// → 'Frank, Christine, Flora, and Harrison'

Используя параметр options, также можно работать с дизъюнкциями («или» на английском):

const lf = new Intl.ListFormat('en', { type: 'disjunction' });
lf.format(['Frank']);
// → 'Frank'
lf.format(['Frank', 'Christine']);
// → 'Frank or Christine'
lf.format(['Frank', 'Christine', 'Flora']);
// → 'Frank, Christine, or Flora'
lf.format(['Frank', 'Christine', 'Flora', 'Harrison']);
// → 'Frank, Christine, Flora, or Harrison'

Вот пример использования другого языка (китайского, с языковым кодом zh):

const lf = new Intl.ListFormat('zh');
lf.format(['永鋒']);
// → '永鋒'
lf.format(['永鋒', '新宇']);
// → '永鋒和新宇'
lf.format(['永鋒', '新宇', '芳遠']);
// → '永鋒、新宇和芳遠'
lf.format(['永鋒', '新宇', '芳遠', '澤遠']);
// → '永鋒、新宇、芳遠和澤遠'

Параметр options позволяет более продвинутое использование. Вот обзор различных опций и их комбинаций, а также их соответствие шаблонам списков, определенным UTS#35:

ТипОпцииОписаниеПримеры
стандартный (или нет типа){} (по умолчанию)Типичный список с «и» для произвольных заполнителей'January, February, and March'
или{ type: 'disjunction' }Типичный список с «или» для произвольных заполнителей'January, February, or March'
единица{ type: 'unit' }Список, подходящий для широких единиц измерения'3 feet, 7 inches'
единица-короткий{ type: 'unit', style: 'short' }Список, подходящий для коротких единиц измерения'3 ft, 7 in'
единица-узкий{ type: 'unit', style: 'narrow' }Список, подходящий для узких единиц измерения, где пространство экрана строго ограничено'3′ 7″'

Учтите, что во многих языках (например, английском) может не быть различий между многими из этих списков. В других же изменение пробелов, длины или наличия соединительного слова, а также разделителей может быть явным.

Заключение

По мере того как API Intl.ListFormat становится все более доступным, вы обнаружите, что библиотеки отказываются от зависимости от жестко закодированных баз данных CLDR в пользу встроенной функции форматирования списков, тем самым улучшая производительность времени загрузки, времени разбора и компиляции, производительность во время выполнения и использование памяти.

Поддержка Intl.ListFormat