Работа с текстом в JavaScript неизбежно опирается на Unicode — универсальную систему кодирования, в которой каждый символ любого языка представлен отдельным кодовым пунктом или последовательностью кодовых пунктов. Однако визуальное и лингвистическое поведение символов далеко не всегда совпадает с их внутренним представлением.
Разные письменности предъявляют разные требования к обработке строк: сортировка, сравнение, разбиение на слова и даже отображение зависят от языка и культурных правил. Именно для этого используется Intl API, предоставляющий стандартизированные механизмы локализованной обработки текста.
Встроенные операции JavaScript для строк (===,
<, >, localeCompare) не
учитывают полноценные лингвистические особенности. Например:
Ключевая проблема: строка как последовательность байтов не равна строке как лингвистической единице.
Латинская письменность используется во множестве языков, и даже внутри неё существуют значимые различия.
Символы вроде é, ü, ñ могут
быть представлены:
Например:
é → U+00E9e + ́ → U+0065 U+0301С точки зрения визуального восприятия они идентичны, но прямое
сравнение строк даст false.
Для устранения таких различий используется нормализация:
Однако ручная нормализация не всегда достаточна, поскольку языковые правила сортировки также различаются.
Кириллица используется в русском, украинском, болгарском и других языках, но порядок букв и правила сопоставления могут отличаться.
Примеры особенностей:
Стандартная сортировка JavaScript не учитывает эти различия, поэтому используется:
Intl.Collator
const collator = new Intl.Collator('ru');
collator.compare('ёж', 'яблоко');
Collator применяет языковые правила русского языка, а не бинарное сравнение кодов символов.
Арабская письменность имеет фундаментальные отличия от латиницы и кириллицы:
Визуально идентичные слова могут содержать разные кодовые последовательности из-за:
const collator = new Intl.Collator('ar');
collator.compare('كتاب', 'كتب');
Collator учитывает арабские правила сортировки, которые не совпадают с Unicode-порядком.
Системы письма CJK представляют наибольшую сложность для алгоритмической обработки.
const collator = new Intl.Collator('zh');
collator.compare('北京', '上海');
Результат зависит от выбранной локали и параметров сортировки (например, stroke-based или pinyin-based сортировка в системах, поддерживающих расширенные правила).
Intl.Locale позволяет описывать язык и региональные особенности:
const locale = new Intl.Locale('ru-RU');
Локаль влияет на:
Основной инструмент для работы с различными алфавитами.
locale — язык сравненияsensitivity — чувствительность сравненияignorePunctuation — игнорирование знаков
препинанияnumeric — числовая сортировкаbase — игнорирует диакритику и регистрaccent — учитывает диакритикуcase — учитывает регистрvariant — максимальная точностьПример:
const collator = new Intl.Collator('fr', {
sensitivity: 'base'
});
collator.compare('e', 'é'); // считается равным
Диакритические знаки особенно важны для европейских языков:
é, è, êä, ö, üñВ зависимости от локали:
base игнорирует различия;accent учитывает их как значимые.В латинице и кириллице регистр играет важную роль, но:
const collator = new Intl.Collator('en', {
sensitivity: 'case'
});
collator.compare('Apple', 'apple');
Intl.Segmenter используется для корректного разбиения строк:
const segmenter = new Intl.Segmenter('ja', { granularity: 'word' });
Особенности:
Intl.DisplayNames позволяет получать локализованные названия языков и систем письма:
const dn = new Intl.DisplayNames('ru', { type: 'language' });
dn.of('ar'); // "арабский"
dn.of('ja'); // "японский"
Это важно при отображении интерфейсов, поддерживающих множество алфавитов.
При работе с несколькими письменностями одновременно возникают дополнительные сложности:
Пример:
const collator = new Intl.Collator(['ru', 'en'], {
numeric: true,
sensitivity: 'base'
});
Unicode определяет кодовые точки, но не определяет:
Эти задачи полностью передаются уровню Intl API, который использует CLDR (Common Locale Data Repository) для определения правил.
При поиске строк важно:
const collator = new Intl.Collator('de', {
sensitivity: 'base'
});
const items.sort((a, b) => collator.compare(a, b));
В разных локалях один и тот же список будет упорядочен по-разному.
Unicode допускает множество способов представления одного символа:
Это приводит к тому, что: