Intl.Collator: примеры (JAVASCRIPT)

Использование Intl.Collator для сравнения строк
Раздел: Интернационазация, Сортировка
Intl.Collator(locales (string, Array), options (object)): Intl.Collator

Что такое Intl.Collator

Intl.Collator – это конструктор объектов для сравнения и сортировки строк с учетом правил конкретного языка или локали. Он используется, когда необходимо упорядочить строки не по бинарному коду символов, а согласно лингвистическим нормам, таким как алфавитный порядок, учет акцентов или особенностей алфавита.

Конструктор принимает два необязательных аргумента:

  • locales – строка с тегом языка (например, 'ru', 'en-US') или их массив. Определяет локаль для сравнения.
  • options – объект с настройками. Основные свойства:
    • localeMatcher – алгоритм выбора локали ('lookup' или 'best fit').
    • usage – назначение ('sort' для сортировки или 'search' для поиска).
    • sensitivity – чувствительность к различиям ('base' – только базовые буквы, 'accent' – базовые и акценты, 'case' – базовые и регистр, 'variant' – все различия).
    • ignorePunctuation – игнорировать знаки пунктуации (true или false).
    • numeric – числовое сравнение (true или false).
    • caseFirst – приоритет регистра ('upper', 'lower' или 'false').

Метод compare возвращает число: отрицательное, если первая строка меньше второй, положительное – если больше, и ноль – при равенстве. Объект также имеет метод resolvedOptions(), возвращающий примененные настройки.

Базовые примеры Intl.Collator

Сравнение строк для английского языка с чувствительностью к базовым буквам:

const collator = new Intl.Collator('en');
console.log(collator.compare('apple', 'banana'));
-1

Сравнение с учетом числового порядка:

const collatorNum = new Intl.Collator('en', { numeric: true });
console.log(collatorNum.compare('file10', 'file2'));
1

Сравнение с игнорированием регистра:

const collatorCase = new Intl.Collator('en', { sensitivity: 'base' });
console.log(collatorCase.compare('A', 'a'));
0

Сравнение с учетом акцентов для французского языка:

const collatorAccent = new Intl.Collator('fr', { sensitivity: 'accent' });
console.log(collatorAccent.compare('é', 'e'));
1

Похожие функции в JavaScript

Для сравнения строк в JavaScript также применяется метод String.prototype.localeCompare(). Он предоставляет схожую функциональность, но менее гибкий в настройках. Например, не позволяет явно задать usage: 'search'. Intl.Collator предпочтительнее для сложной сортировки больших массивов, так как объект кэширует настройки, что повышает производительность. Для простого сравнения в одной локале подходит localeCompare.

console.log('ä'.localeCompare('z', 'de'));
console.log('ä'.localeCompare('z', 'sv'));
-1
1

Аналоги в других языках

В PHP для сравнения с локалью используется класс Collator из расширения intl.

$collator = new Collator('ru_RU');
echo $collator->compare('Яблоко', 'Абрикос');
1

В Python можно использовать функцию locale.strxfrm() для преобразования строк перед сортировкой.

import locale
locale.setlocale(locale.LC_COLLATE, 'ru_RU.UTF-8')
sorted_list = sorted(['Яблоко', 'Абрикос'], key=locale.strxfrm)
['Абрикос', 'Яблоко']

В MySQL для запросов применяется оператор COLLATE.

SELECT * FROM items ORDER BY name COLLATE utf8mb4_ru_ci;

В C для сравнения с локалью служит функция strcoll из библиотеки <locale.h>.

Распространенные ошибки

Передача неверного формата локали или несуществующего кода языка может привести к использованию локали по умолчанию без явной ошибки.

const collator = new Intl.Collator('xx-YY');
console.log(collator.resolvedOptions().locale);
(результат зависит от реализации, например, 'en-US')

Непонимание параметра sensitivity может вызвать неожиданные результаты сортировки. Например, при sensitivity: 'base' регистр и акценты игнорируются.

const collator = new Intl.Collator('en', { sensitivity: 'base' });
console.log(collator.compare('Resume', 'résumé'));
0

Использование объекта Collator, созданного с одними настройками, для другой задачи, например, для поиска вместо сортировки, может дать некорректный результат.

Обновления в спецификации

В более новых версиях ECMAScript добавлена опция caseFirst, позволяющая указать, должны ли строки в верхнем регистре идти первыми. Также улучшена поддержка локалей и алгоритм 'best fit' для выбора локали. В некоторых средах выполнения, например Node.js, для полной функциональности может потребоваться актуальная версия ICU библиотеки.

Расширенные сценарии применения

Сортировка массива объектов по строковому свойству с учетом локали:

Пример javascript
const items = [
  { name: 'Яблоко', price: 100 },
  { name: 'абрикос', price: 200 },
  { name: 'Банан', price: 150 }
];
const collatorRu = new Intl.Collator('ru', { sensitivity: 'variant' });
items.sort((a, b) => collatorRu.compare(a.name, b.name));
console.log(items.map(i => i.name));
['абрикос', 'Банан', 'Яблоко']

Использование для поиска с игнорированием пунктуации:

Пример javascript
const collatorSearch = new Intl.Collator('en', {
  usage: 'search',
  ignorePunctuation: true,
  sensitivity: 'base'
});
const string = 'Hello, world!';
const searchTerm = 'world';
const normalized = string.split('').filter(ch => 
  !collatorSearch.resolvedOptions().ignorePunctuation || 
  /[\p{L}\p{N}]/u.test(ch)
).join('');
const match = collatorSearch.compare(searchTerm, normalized) === 0;
console.log(match);
false // (Пример упрощен, требуется полная реализация нормализации)

Создание пользовательского порядка сортировки, например, для специфичной категории товаров:

Пример javascript
const customOrder = ['small', 'medium', 'large'];
const collatorEn = new Intl.Collator('en');
const data = ['large', 'small', 'medium'];
data.sort((a, b) => 
  customOrder.indexOf(a) - customOrder.indexOf(b)
);
console.log(data);
['small', 'medium', 'large']

Сравнение с использованием нескольких локалей с fallback:

Пример javascript
const collatorDE = new Intl.Collator(['de', 'en']);
console.log(collatorDE.compare('z', 'ä'));
1 // В немецком 'ä' считается близко к 'a'

JS Intl.Collator function comments

En
Intl.Collator String comparison according to locale