Stimulus — легковесный JavaScript-фреймворк, ориентированный на улучшение HTML через data- атрибуты и минимизацию написания сложного JavaScript-кода. Одной из типичных задач в веб-приложениях является поддержка нескольких языков и возможность динамической смены локализации без перезагрузки страницы. Stimulus предоставляет удобные инструменты для управления состоянием элементов и реакции на пользовательские действия, что делает его идеальным для реализации динамического изменения языков.
Основой динамической локализации является объект с текстами на разных языках. Он может быть оформлен в виде JSON или JavaScript-объекта:
const translations = {
en: {
welcome: "Welcome",
login: "Login",
logout: "Logout"
},
ru: {
welcome: "Добро пожаловать",
login: "Войти",
logout: "Выйти"
},
es: {
welcome: "Bienvenido",
login: "Iniciar sesión",
logout: "Cerrar sesión"
}
};
Ключевым моментом является использование одинаковых ключей для всех языков. Это позволяет легко менять язык, просто подставляя другой набор значений.
Stimulus-контроллер управляет состоянием языка и обновлением текста на странице. Основная логика заключается в хранении текущего языка, прослушивании событий выбора языка и обновлении элементов с нужными локализованными значениями.
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["text"];
static values = { language: String };
connect() {
this.languageValue ||= "en"; // язык по умолчанию
this.updateTexts();
}
changeLanguage(event) {
this.languageValue = event.target.value;
this.updateTexts();
}
updateTexts() {
this.textTargets.forEach((element) => {
const key = element.dataset.translationKey;
if (translations[this.languageValue][key]) {
element.textContent = translations[this.languageValue][key];
}
});
}
}
Ключевые моменты:
textTargets — элементы страницы, подлежащие
локализации.dataset.translationKey — ключ текста в объекте
переводов.languageValue — текущий выбранный язык, управляемый
через Stimulus values.updateTexts() — метод, обновляющий текст на странице в
соответствии с выбранным языком.Для работы контроллера необходимо правильно расставить атрибуты
data-controller, data-action и
data-target. Пример:
<div data-controller="i18n" data-i18n-language-value="en">
<select data-action="change->i18n#changeLanguage">
<option value="en">English</option>
<option value="ru">Русский</option>
<option value="es">Español</option>
</select>
<h1 data-i18n-target="text" data-translation-key="welcome"></h1>
<button data-i18n-target="text" data-translation-key="login"></button>
<button data-i18n-target="text" data-translation-key="logout"></button>
</div>
В этом примере <select> инициирует событие
change, которое вызывает метод changeLanguage
контроллера i18n. Все элементы с
data-i18n-target="text" автоматически обновляются при смене
языка.
Если элементы создаются динамически (через AJAX или другие методы),
Stimulus позволяет автоматически подключать их к контроллеру, если они
находятся внутри области действия контроллера. Необходимо лишь
убедиться, что у вновь созданных элементов корректно проставлены
data-i18n-target и data-translation-key. После
вставки можно вызвать updateTexts():
const newElement = document.createElement("button");
newElement.dataset.i18nTarget = "text";
newElement.dataset.translationKey = "login";
this.element.appendChild(newElement);
this.updateTexts();
localStorage или cookies для
восстановления при следующем посещении.fetch, а затем вызывать
updateTexts().Переводы часто нужны не только для текстового содержимого, но и для
атрибутов, например, placeholder:
<input type="text" data-i18n-target="text" data-translation-key="login_placeholder">
Контроллер может расширяться, обновляя не только
textContent, но и атрибуты:
updateAttributes() {
this.textTargets.forEach((element) => {
const key = element.dataset.translationKey;
if (translations[this.languageValue][key]) {
if (element.tagName === "INPUT") {
element.placeholder = translations[this.languageValue][key];
} else {
element.textContent = translations[this.languageValue][key];
}
}
});
}
Stimulus легко сочетается с другими фреймворками и библиотеками, например, с Turbo или Alpine.js. При динамическом обновлении страницы с помощью Turbo Streams контроллер автоматически подключается к новым элементам и обновляет их тексты, что делает систему локализации полностью реактивной без дополнительных сложных решений.
Динамическая смена языков через Stimulus сочетает простоту управления DOM и гибкость JavaScript. Использование контроллеров, таргетов и значений обеспечивает централизованное управление текстами, позволяет легко расширять функциональность и интегрировать локализацию в современные веб-приложения с минимальными затратами кода.