В библиотеках кастомных селектов, построенных поверх нативного
<select>, текстовые элементы интерфейса обычно
выносятся в конфигурацию экземпляра. Slim Select относится к таким
решениям: строки интерфейса не «зашиты» в DOM, а формируются через набор
параметров, что позволяет реализовать динамическую смену языка без
модификации разметки.
Типовая структура текстов интерфейса включает:
Именно эти поля становятся точками локализации при переключении языка.
При инициализации Slim Select набор строк задаётся через объект конфигурации:
new SlimSelect({
select: '#example',
settings: {
placeholderText: 'Select value',
searchPlaceholder: 'Search...',
searchText: 'No results',
searchingText: 'Searching...',
searchHighlight: true,
closeOnSelect: true
}
});
Ключевым моментом является то, что текстовые поля не являются статичными. Они могут быть пересозданы, обновлены или заменены при смене локали.
Основные локализуемые свойства:
Смена языка в Slim Select обычно реализуется одним из трёх подходов:
Наиболее стабильной моделью считается пересоздание экземпляра, поскольку внутреннее состояние компонента слабо рассчитано на горячую замену всех текстов.
Базовый паттерн смены языка заключается в уничтожении текущего экземпляра и создании нового с обновлёнными строками:
let slim = new SlimSelect({
select: '#example',
settings: {
placeholderText: i18n['en'].placeholderText,
searchPlaceholder: i18n['en'].searchPlaceholder,
searchText: i18n['en'].searchText,
searchingText: i18n['en'].searchingText
}
});
function changeLanguage(lang) {
slim.destroy();
slim = new SlimSelect({
select: '#example',
settings: {
placeholderText: i18n[lang].placeholderText,
searchPlaceholder: i18n[lang].searchPlaceholder,
searchText: i18n[lang].searchText,
searchingText: i18n[lang].searchingText
}
});
}
Такой подход гарантирует полное обновление интерфейса, включая все внутренние состояния списка.
Для масштабируемых интерфейсов используется словарь локализаций:
const i18n = {
en: {
placeholderText: 'Select value',
searchPlaceholder: 'Search...',
searchText: 'No results found',
searchingText: 'Searching...'
},
ru: {
placeholderText: 'Выберите значение',
searchPlaceholder: 'Поиск...',
searchText: 'Ничего не найдено',
searchingText: 'Поиск...'
},
kz: {
placeholderText: 'Мәнді таңдаңыз',
searchPlaceholder: 'Іздеу...',
searchText: 'Ештеңе табылмады',
searchingText: 'Ізделуде...'
}
};
Такая структура позволяет синхронизировать UI с глобальной системой i18n без привязки к конкретной библиотеке.
В некоторых сценариях применяется частичное обновление DOM без уничтожения экземпляра. Этот способ зависит от внутренней реализации Slim Select и может быть нестабилен, но используется для минимизации пересборки интерфейса.
Подход основан на ручном обновлении текстовых узлов:
function updateTexts(lang) {
const root = document.querySelector('.ss-main');
const placeholder = root.querySelector('.ss-placeholder');
if (placeholder) {
placeholder.textContent = i18n[lang].placeholderText;
}
const searchInput = root.querySelector('.ss-search input');
if (searchInput) {
searchInput.placeholder = i18n[lang].searchPlaceholder;
}
const noResult = root.querySelector('.ss-no-results');
if (noResult) {
noResult.textContent = i18n[lang].searchText;
}
}
Недостаток метода заключается в том, что внутренние состояния (например, сообщения при фильтрации) могут перерисовываться библиотекой, перезаписывая вручную изменённые значения.
В SPA-приложениях смена языка обычно управляется глобальным стором. Slim Select интегрируется через подписку на изменение языка:
let currentLang = 'en';
function setLanguage(lang) {
currentLang = lang;
changeLanguage(lang);
}
document.querySelector('#lang-switch').addEventListener('change', (e) => {
setLanguage(e.target.value);
});
При использовании state manager (Redux, Zustand, Pinia-подобные модели) смена языка становится реактивной, а Slim Select выступает как визуальный слой, пересобираемый при изменении состояния.
Помимо интерфейсных строк, часто требуется локализация самих option-значений. Это решается через трансформацию входного массива данных перед передачей в Slim Select:
const options = {
en: [
{ text: 'Apple', value: 'apple' },
{ text: 'Orange', value: 'orange' }
],
ru: [
{ text: 'Яблоко', value: 'apple' },
{ text: 'Апельсин', value: 'orange' }
]
};
function rebuildOptions(lang) {
slim.destroy();
slim = new SlimSelect({
select: '#example',
data: options[lang],
settings: {
placeholderText: i18n[lang].placeholderText,
searchPlaceholder: i18n[lang].searchPlaceholder
}
});
}
Такой подход обеспечивает полную консистентность языка между UI и содержимым списка.
При пересоздании экземпляра важно сохранить текущее выбранное значение:
let selectedValue = null;
function rebuildWithState(lang) {
const select = document.querySelector('#example');
selectedValue = select.value;
slim.destroy();
slim = new SlimSelect({
select: '#example',
data: options[lang],
settings: i18n[lang]
});
slim.set(selectedValue);
}
Метод set используется для восстановления состояния
после пересборки.
При загрузке локализаций с сервера возникает необходимость ожидания данных перед инициализацией компонента:
async function loadLanguage(lang) {
const res = await fetch(`/i18n/${lang}.json`);
const dict = await res.json();
i18n[lang] = dict;
slim.destroy();
slim = new SlimSelect({
select: '#example',
settings: i18n[lang]
});
}
Этот подход позволяет масштабировать систему переводов независимо от фронтенд-кода.
Для языков с направлением письма справа налево требуется дополнительная синхронизация с DOM:
function applyDirection(lang) {
const rtlLanguages = ['ar', 'he', 'fa'];
document.documentElement.setAttribute(
'dir',
rtlLanguages.includes(lang) ? 'rtl' : 'ltr'
);
}
Slim Select автоматически наследует направление текста от
родительского контейнера, поэтому достаточно управлять глобальным
атрибутом dir.
При переключении локали необходимо сбрасывать фильтр поиска, иначе остаётся старый результат:
function resetSearch() {
const input = document.querySelector('.ss-search input');
if (input) {
input.value = '';
input.dispatchEvent(new Event('input'));
}
}
Это предотвращает ситуацию, когда результаты поиска относятся к предыдущему языку, но отображаются в новом интерфейсе.
На практике применяется объединённый подход:
function switchLang(lang) {
const value = document.querySelector('#example').value;
applyDirection(lang);
slim.destroy();
slim = new SlimSelect({
select: '#example',
data: options[lang],
settings: i18n[lang]
});
slim.set(value);
resetSearch();
}
Такой сценарий обеспечивает целостность интерфейса при любом изменении локали.