Механизм локализации интерфейса в компонентах выбора строится на разделении текстовых ресурсов и логики отображения. В случае Tom Select текстовые строки, используемые в подсказках, плейсхолдерах, сообщениях об отсутствии результатов и состояниях загрузки, выносятся в отдельный слой конфигурации и могут быть переопределены в рантайме без пересоздания всей структуры приложения.
Локализация в Tom Select опирается на набор ключей, соответствующих
элементам интерфейса. Эти ключи группируются в объект, который
передаётся через конфигурацию i18n. Каждый язык
представляет собой независимый словарь.
const i18n_en = {
no_results: 'No results found',
loading: 'Loading...',
add_item: 'Add',
max_items: 'Maximum items reached',
remove_item: 'Remove'
};
const i18n_ru = {
no_results: 'Совпадений не найдено',
loading: 'Загрузка...',
add_item: 'Добавить',
max_items: 'Достигнут лимит элементов',
remove_item: 'Удалить'
};
Каждый ключ связан с конкретным состоянием интерфейса. Отсутствие ключа в словаре приводит к использованию дефолтного текста библиотеки либо пустого значения, в зависимости от версии реализации.
При создании экземпляра Tom Select словарь передаётся через параметр
i18n. Это фиксирует язык на этапе инициализации
компонента.
const tom = new TomSelect('#select', {
options: [
{ value: '1', text: 'Option 1' },
{ value: '2', text: 'Option 2' }
],
i18n: i18n_en,
placeholder: 'Select item'
});
При таком подходе все текстовые элементы интерфейса берутся исключительно из переданного словаря. Это включает системные сообщения и вспомогательные подписи.
Внутренние строки интерфейса распределены по нескольким зонам:
Каждая зона использует отдельный ключ словаря. Это позволяет менять язык выборочно, не затрагивая всю конфигурацию.
Смена языка в рантайме возможна через обновление конфигурации
экземпляра. Tom Select хранит ссылку на объект i18n,
поэтому его можно заменить напрямую.
tom.settings.i18n = i18n_ru;
tom.refreshOptions(false);
Метод refreshOptions используется для обновления
визуального состояния без полной перерисовки компонента. Однако не все
строки обновляются автоматически, поскольку часть текста кэшируется при
первичной отрисовке.
Для полного обновления интерфейса применяется принудительная перерисовка:
tom.clear();
tom.sync();
tom.refreshItems();
В зависимости от версии библиотеки может потребоваться дополнительное обновление placeholder:
tom.control_input.setAttribute('placeholder', tom.settings.placeholder);
Более стабильный способ динамической смены языка заключается в уничтожении текущего экземпляра и создании нового. Такой подход исключает проблемы кэширования строк и несинхронизированных состояний.
tom.destroy();
tom = new TomSelect('#select', {
options: [
{ value: '1', text: 'Option 1' },
{ value: '2', text: 'Option 2' }
],
i18n: i18n_ru,
placeholder: 'Выберите элемент'
});
Пересоздание обеспечивает полное применение нового словаря, включая все внутренние состояния.
При масштабных интерфейсах словари выносятся в отдельный модуль. Это позволяет управлять локализацией централизованно.
export const languages = {
en: {
no_results: 'No results found',
loading: 'Loading...'
},
ru: {
no_results: 'Совпадений не найдено',
loading: 'Загрузка...'
},
kz: {
no_results: 'Нәтиже табылмады',
loading: 'Жүктелуде...'
}
};
Далее используется индексный доступ к нужному языку:
function setLanguage(tom, lang) {
tom.settings.i18n = languages[lang];
tom.refreshOptions(false);
}
В прикладных интерфейсах язык часто связан с глобальным состоянием. При изменении языка требуется синхронное обновление всех компонентов, включая селекты.
let currentLanguage = 'en';
function updateLanguage(lang) {
currentLanguage = lang;
tom.settings.i18n = languages[lang];
tom.refreshOptions(false);
}
При этом важно учитывать, что некоторые элементы DOM могут сохранять старые строки, если они были сгенерированы до смены словаря.
Сообщения поиска и загрузки часто формируются в момент выполнения запроса. Для корректной локализации такие строки должны формироваться на основе текущего словаря в момент вызова.
tom.on('type', function() {
tom.dropdown_content.innerHTML = tom.settings.i18n.loading;
});
При обновлении языка подобные обработчики должны учитывать актуальный словарь, иначе интерфейс будет частично локализован.
Placeholder не всегда входит в i18n, так как является
частью общей конфигурации поля. При смене языка он должен обновляться
отдельно.
function updatePlaceholder(tom, text) {
tom.settings.placeholder = text;
tom.control_input.setAttribute('placeholder', text);
}
Это важно при мультиязычных формах, где placeholder несёт смысловую нагрузку.
Tom Select позволяет переопределять рендеринг элементов через
render. При динамической смене языка такие шаблоны также
должны учитывать текущий словарь.
tom.settings.render.option = function(data, escape) {
return `
<div>
<span>${escape(data.text)}</span>
<small>${tom.settings.i18n.add_item}</small>
</div>
`;
};
После смены языка требуется повторное применение render-логики:
tom.refreshOptions(false);
Для предотвращения утечек состояния язык не должен храниться внутри
отдельных элементов DOM. Все текстовые значения должны вычисляться на
основе текущего состояния settings.i18n.
Любое кэширование строк на уровне замыканий приводит к рассинхронизации интерфейса при переключении языка.
При использовании удалённых источников данных сообщения о загрузке формируются асинхронно. При смене языка во время запроса возможна ситуация, при которой старый язык отображается в промежуточных состояниях.
tom.load(function(callback) {
fetch('/api/items')
.then(res => res.json())
.then(data => {
callback(data);
});
});
В таких сценариях важно, чтобы текстовые сообщения не были зафиксированы до завершения запроса.
При динамической смене языка важно сохранять выбранные значения. Tom
Select хранит их отдельно от текстовых меток, поэтому обновление словаря
не должно затрагивать value.
const selected = tom.getValue();
tom.settings.i18n = i18n_ru;
tom.refreshOptions(false);
tom.setValue(selected);
Такое разделение обеспечивает независимость данных и представления.
При наличии нескольких селектов с разными языками необходимо избегать
глобального изменения словаря. Каждый экземпляр должен иметь собственный
i18n объект.
const tom1 = new TomSelect('#select1', {
i18n: i18n_en
});
const tom2 = new TomSelect('#select2', {
i18n: i18n_ru
});
Общие ссылки на один объект словаря приводят к одновременному изменению всех компонентов.
После изменения языка требуется синхронизация следующих частей интерфейса:
function applyLanguage(tom, lang) {
tom.settings.i18n = languages[lang];
tom.refreshOptions(false);
tom.refreshItems();
tom.control_input.setAttribute('placeholder', tom.settings.placeholder);
}
Комплексное обновление исключает частичное отображение старых текстов.
Часть строк может быть зафиксирована в момент инициализации и не
реагировать на изменения i18n. Это характерно для версий,
где внутренние компоненты создаются один раз и не пересобираются при
обновлении настроек.
В таких случаях единственным стабильным решением остаётся полное пересоздание экземпляра, обеспечивающее согласованность всех текстовых слоёв интерфейса.