Поведение автодополнения в Awesomplete определяется не только списком данных, но и тем, как эти данные сравниваются, фильтруются и отображаются. При переходе к мультиязычным интерфейсам, где присутствуют разные алфавиты, диакритика, направления письма и региональные правила сортировки, стандартная логика сравнения строк становится недостаточной.
Ключевая задача региональной настройки — обеспечить предсказуемое и естественное поведение поиска для конкретного языка или набора языков, сохраняя при этом минимальный вес библиотеки.
По умолчанию Awesomplete использует простое сравнение подстрок:
indexOfТакой подход работает для латиницы в простых интерфейсах, но ломается в случаях:
Базовый шаг адаптации — приведение строк к нормализованному виду.
function normalizeText(str) {
return str
.toString()
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "");
}
NFD разлагает символы с диакритикойtoLowerCase() выравнивает регистрПример поведения:
| Ввод | Сравниваемое значение |
|---|---|
| café | cafe |
| São | sao |
| Żubr | zubr |
Awesomplete позволяет переопределять фильтр через
filter:
new Awesomplete(input, {
list: ["München", "São Paulo", "Zürich", "Алматы", "Караганда"],
filter: function(text, input) {
const t = normalizeText(text);
const i = normalizeText(input);
return t.indexOf(i) !== -1;
}
});
Такой подход унифицирует поиск для разных языков без изменения исходного списка.
В разных языках порядок отображения должен соответствовать локальным
правилам. Для этого используется Intl.Collator.
const collator = new Intl.Collator("ru", { sensitivity: "base" });
new Awesomplete(input, {
list: ["Яблоко", "Ёж", "Абрикос", "Банан"],
sort: function(a, b) {
return collator.compare(a.label || a, b.label || b);
}
});
Intl.Collator:sensitivity: "base" — игнорирование регистра и
диакритикиnumeric: true — корректная сортировка чиселignorePunctuation: true — игнорирование символовПри работе с кириллицей основная проблема — не фильтрация, а транслитерационные различия:
ё vs еРасширенная нормализация:
function cyrillicNormalize(str) {
return normalizeText(str)
.replace(/ё/g, "е")
.replace(/й/g, "и");
}
Фильтр:
filter: function(text, input) {
return cyrillicNormalize(text).includes(cyrillicNormalize(input));
}
Языки с направлением письма справа налево требуют не только отображения, но и корректной работы автодополнения.
HTML-контейнер Awesomplete можно адаптировать:
input.setAttribute("dir", "rtl");
И стили:
.awesomplete {
text-align: right;
}
Особенности:
Во многих приложениях список не является универсальным — он зависит от региона пользователя.
Пример динамической загрузки:
async function loadList(region) {
const response = await fetch(`/data/list-${region}.json`);
return await response.json();
}
loadList("kz").then(list => {
new Awesomplete(input, { list });
});
В некоторых регионах одна и та же сущность может вводиться разными способами:
Расширение фильтра:
function flexibleMatch(text, input) {
const t = normalizeText(text);
const i = normalizeText(input);
return t.includes(i) ||
t.replace(/kz/g, "kaz").includes(i);
}
При больших объёмах данных локальная фильтрация становится неэффективной. В этом случае Awesomplete используется только как UI-слой, а фильтрация выполняется на сервере:
input.addEventListener("input", async function() {
const query = input.value;
const response = await fetch(`/search?q=${query}&lang=ru`);
const data = await response.json();
awesomplete.list = data;
});
lang,
region)В разных языках диакритика имеет разный статус:
I vs
ı)Пример локализованного сравнения:
const trCollator = new Intl.Collator("tr", { sensitivity: "base" });
Использование правильной локали предотвращает ошибки сопоставления.
При объединении нескольких регионов важно управлять приоритетом результатов:
const list = [
{ label: "Almaty", region: "kz" },
{ label: "Moscow", region: "ru" },
{ label: "Berlin", region: "de" }
];
function sortByRegionPriority(a, b) {
const priority = { kz: 1, ru: 2, de: 3 };
return priority[a.region] - priority[b.region];
}
Awesomplete позволяет кастомизировать отображение элементов через
item:
new Awesomplete(input, {
list: list,
item: function(text, input) {
const el = document.createElement("li");
el.innerHTML = `
<span class="label">${text}</span>
<span class="hint">${detectRegion(text)}</span>
`;
return el;
}
});
Региональная метка может отображать страну, язык или категорию.
Современные интерфейсы должны учитывать:
Безопасная обработка:
function safeUnicode(str) {
return Array.from(str).join("");
}
Это предотвращает проблемы с суррогатными парами и некорректной длиной строк.
Региональная адаптация Awesomplete строится на нескольких слоях:
Intl.Collator)Совокупность этих механизмов позволяет использовать Awesomplete в интерфейсах, где одновременно присутствуют разные языки, алфавиты и культурные нормы ввода без изменения самой архитектуры библиотеки.