Функция Intl.Collator в JavaScript предоставляет стандартный механизм сортировки строк с учетом локали. Однако по умолчанию она использует базовые правила Unicode, которые часто не соответствуют ожиданиям пользователей на конкретных языках (например, русские буквы «ё» и «е», пробелы после знаков препинания). Для корректной работы необходимо явно указывать регион (locale) и настраивать чувствительность к регистру. Без этих настроек сортировка будет работать по латинскому алфавиту или игнорировать специфические символы, что приведет к ошибкам в списках товаров, контактах и результатах поиска.
Как работает Intl.Collator и почему локализация требует настройки
Объект Intl.Collator создает объект, который определяет порядок сортировки строк. Он принимает два основных аргумента: код региона (locale) и объект опций.
Если не указать locale или использовать пустую строку, функция использует базовые правила Unicode. Это означает, что символы будут сортироваться по их кодовым точкам в таблице Unicode. Для русского языка это часто приводит к тому, что «ё» стоит после всех букв «е», а пробелы могут обрабатываться не так, как ожидается пользователем.
Указание locale (например, 'ru-RU') активирует правила конкретного региона. Это включает в себя специфические правила сортировки, такие как игнорирование пробелов после знаков препинания или правильное позиционирование букв с диакритическими знаками.
Важно понимать, что Intl.Collator не заменяет собой логику бизнес-правилов. Он отвечает только за лексикографический порядок символов согласно правилам выбранного региона.
Шаг 1: Определение региона (locale) для сортировки
Первым шагом является выбор правильного кода региона. Для русского языка стандартным выбором является 'ru-RU'. Этот код указывает на использование правил Российской Федерации.
Можно также использовать 'ru' без суффикса страны, но 'ru-RU' предпочтительнее для строгого соответствия стандартам.
Пример создания объекта сортировки:
const collator = new Intl.Collator('ru-RU', { sensitivity: 'base' });
В этом примере мы явно указываем регион. Если опустить второй аргумент, будут использоваться все доступные настройки по умолчанию для этого региона.
Проверка работы:
const names = ['Иванов', 'Петров', 'Сидоров'];
names.sort((a, b) => collator.compare(a, b));
Результатом будет правильный порядок: Иванов, Петров, Сидоров. Если бы мы использовали английский регион ('en-US'), то символы «И», «П», «С» могли бы быть отсортированы иначе в зависимости от версии библиотеки или реализации Unicode.
Шаг 2: Настройка чувствительности к регистру и акцентам
Опция sensitivity определяет, учитывает ли сортировка регистр букв (верхний/нижний) и диакритические знаки.
Значение 'base' игнорирует регистр и диакритические знаки. Это полезно для поиска или сортировки, где «Иванов» и «иванов» должны стоять рядом, а «Иванов» с «ё» — рядом с «Иванов» без «ё».
Значение 'accent' учитывает диакритические знаки, но игнорирует регистр. Это важно для языков, где «е» и «ё» считаются разными буквами (например, в русском языке «ё» часто стоит после «е» или отдельно).
Значение 'case' учитывает регистр, но игнорирует диакритические знаки.
Значение 'variant' учитывает все различия, включая регистр и диакритические знаки. Это наиболее строгий режим.
Для большинства задач с именами на русском языке рекомендуется использовать 'base', если нужно объединить «е» и «ё», или 'accent', если важно разделять их.
Пример:
const collatorBase = new Intl.Collator('ru-RU', { sensitivity: 'base' });
const namesMixed = ['Иванов', 'иванов', 'ИВАНОВ'];
namesMixed.sort((a, b) => collatorBase.compare(a, b)); // Все варианты будут отсортированы вместе
const collatorAccent = new Intl.Collator('ru-RU', { sensitivity: 'accent' });
const namesWithYo = ['Иванов', 'Иванёв'];
namesWithYo.sort((a, b) => collatorAccent.compare(a, b)); // «Иванёв» будет после «Иванов»
Шаг 3: Обработка специфических правил сортировки (например, «ё» или пробелы)
В русском языке буква «ё» исторически и в некоторых стандартах считается отдельной буквой, которая должна стоять после всех букв «е», но перед другими буквами.
Стандартные правила Unicode для 'ru-RU' обычно соблюдают это требование. Однако при работе с пользовательским контентом важно убедиться, что сортировка работает корректно.
Пробелы после знаков препинания: в некоторых локализованных правилах пробелы после точек или запятых игнорируются при сравнении. Это позволяет сортировать «Иванов.» и «Иванов» как равные или с учетом только текста без пробела.
Если требуется строгое соблюдение всех символов, включая пробелы, можно использовать режим 'variant' или не указывать опцию sensitivity (что использует настройки по умолчанию для региона).
Пример:
const namesWithPunctuation = ['Иванов.', 'Иванов', 'Иванов,'];
const collatorStrict = new Intl.Collator('ru-RU', { sensitivity: 'variant' });
namesWithPunctuation.sort((a, b) => collatorStrict.compare(a, b)); // Сортировка будет учитывать знаки препинания и пробелы
Шаг 4: Интеграция с формами ввода и валидацией
При работе с формами ввода (например, поиск по базе клиентов) сортировка должна применяться к результатам поиска, а не к данным формы напрямую.
Валидация данных в форме не зависит от Intl.Collator, но сортировка результатов поиска должна использовать настроенный объект collator.
Пример реализации поиска и сортировки:
const searchInput = document.getElementById('search-input');
const resultsContainer = document.getElementById('results-container');
const collator = new Intl.Collator('ru-RU', { sensitivity: 'base' });
function filterAndSortNames(names, query) {
const filtered = names.filter(name => name.toLowerCase().includes(query));
return filtered.sort((a, b) => collator.compare(a, b));
}
Этот подход позволяет пользователю вводить текст без учета регистра и получать отсортированный список результатов.
Важно: не сортируйте данные на сервере перед отправкой. Сортировку выполняйте на стороне клиента после фильтрации, используя Intl.Collator.
Шаг 5: Оптимизация производительности при работе с большими массивами
Intl.Collator не требует создания нового объекта для каждой сортировки. Объект можно создать один раз и использовать многократно.
Для больших массивов данных (например, тысячи имен) создание одного объекта collator значительно ускоряет процесс.
Пример:
const collator = new Intl.Collator('ru-RU', { sensitivity: 'base' });
const largeArray = […]; // Массив из 10 000+ элементов
largeArray.sort((a, b) => collator.compare(a, b));
Избегайте создания нового объекта collator внутри цикла или функции, если он не меняется.
Если сортировка выполняется в реальном времени (например, при вводе текста), используйте debounce для отложенного вызова сортировки, чтобы избежать лишних вычислений.
Шаг 6: Обработка ошибок и невалидных аргументов Intl.Collator
Intl.Collator может抛出 ошибку, если указан неверный код региона (например, 'ru-XX', где XX — несуществующая страна).
Всегда проверяйте корректность кода региона перед созданием объекта.
Пример обработки ошибок:
try {
const collator = new Intl.Collator('ru-RU');
} catch (e) {
console.error('Неверный код региона:', e.message);
// Фоллбэк на базовую сортировку или другой регион
}
Шаг 7: Адаптация под мобильные устройства и разные браузеры
Intl.Collator поддерживается всеми современными браузерами, включая мобильные (Chrome, Safari, Firefox).
На старых версиях Internet Explorer эта функция отсутствует. Для таких случаев необходимо использовать полифиллы или библиотеки типа polyfill-intl-localematcher.
В современных проектах (React, Vue, Angular) Intl.Collator работает стабильно на всех мобильных устройствах.
Если проект поддерживает старые браузеры, добавьте проверку перед использованием:
if ('Intl' in window && 'Collator' in Intl) {
// Использовать Intl.Collator
} else {
// Использовать fallback-сортировку (например, String.prototype.localeCompare)
}
Шаг 8: Тестирование на реальных данных пользователя
Перед запуском проекта протестируйте сортировку на реальных данных пользователей.
Используйте тестовые данные, включающие имена с «ё», разные регистры, знаки препинания и пробелы.
Пример тестового набора:
const testNames = ['Иванов', 'Иванёв', 'иванов', 'ИВАНОВ', 'Петров.', 'Сидоров,'];
const collator = new Intl.Collator('ru-RU', { sensitivity: 'base' });
testNames.sort((a, b) => collator.compare(a, b));
Проверьте результат вручную и убедитесь, что он соответствует ожиданиям пользователей.
Если сортировка не работает как ожидается, проверьте код региона и настройки sensitivity.
Вопросы и ответы
Можно ли использовать Intl.Collator для других языков?
Да, Intl.Collator поддерживает множество регионов (например, 'en-US', 'de-DE', 'fr-FR'). Просто измените код региона в конструкторе.
Как отсортировать массив без создания объекта collator?
Можно использовать метод String.prototype.localeCompare с указанием locale: array.sort((a, b) => a.localeCompare(b, 'ru-RU', { sensitivity: 'base' }));. Однако создание объекта collator предпочтительнее для производительности.
Что делать, если Intl.Collator не поддерживается браузером?
Используйте полифиллы или библиотеки типа polyfill-intl-localematcher. Также можно использовать fallback-сортировку через String.prototype.localeCompare.
const collator = new Intl.Collator('ru-RU', { sensitivity: 'base' });
const names = ['Иванов', 'Петров', 'Сидоров'];
names.sort((a, b) => collator.compare(a, b));


