Локализация пользовательского интерфейса

Stimulus — это минималистичный JavaScript-фреймворк, ориентированный на повышение интерактивности страниц без перегрузки кода. Одним из ключевых аспектов современных веб-приложений является локализация интерфейса (i18n), позволяющая адаптировать текст и поведение приложения под различные языки и культурные особенности пользователей. В Stimulus локализация достигается через сочетание контроллеров, данных HTML и внешних ресурсов локализации.

Stimulus контроллеры обеспечивают мост между HTML и JavaScript, позволяя динамически изменять содержимое элементов на основе текущей локали. Основная задача локализации в Stimulus — сделать так, чтобы интерфейс реагировал на изменение языка без полной перезагрузки страницы.


Хранение и подключение ресурсов локализации

Для удобства управление текстами осуществляется через объект JSON, в котором ключи представляют идентификаторы сообщений, а значения — переводы:

{
  "en": {
    "greeting": "Hello, %{name}!",
    "submit": "Submit"
  },
  "ru": {
    "greeting": "Привет, %{name}!",
    "submit": "Отправить"
  }
}

Такой подход позволяет централизованно управлять всеми текстовыми элементами интерфейса и легко расширять поддержку новых языков.

Подключение JSON-файлов к приложению Stimulus осуществляется через стандартный импорт:

import locales from "../locales/messages.json";

Контроллер локализации

Создание отдельного Stimulus-контроллера для управления локализацией позволяет автоматически обновлять текстовые элементы при смене языка. Пример структуры контроллера:

import { Controller } from "@hotwired/stimulus";
import locales from "../locales/messages.json";

export default class extends Controller {
  static values = { locale: String };

  connect() {
    this.renderTexts();
  }

  localeValueChanged() {
    this.renderTexts();
  }

  renderTexts() {
    const locale = this.localeValue || "en";
    this.element.querySelectorAll("[data-i18n-key]").forEach(el => {
      const key = el.dataset.i18nKey;
      if (locales[locale] && locales[locale][key]) {
        el.textContent = this.interpolate(locales[locale][key]);
      }
    });
  }

  interpolate(text) {
    return text.replace(/%\{(\w+)\}/g, (match, p1) => this.element.dataset[p1] || "");
  }
}

Ключевые моменты работы контроллера:

  • static values определяет локаль как реактивное значение, изменение которого автоматически вызывает метод localeValueChanged.
  • data-i18n-key на HTML-элементе связывает его с конкретным переводом.
  • Метод interpolate позволяет вставлять динамические данные, используя атрибуты data-*.

Использование в HTML

Элементы интерфейса связываются с контроллером и ключами локализации через атрибуты:

<div data-controller="i18n" data-i18n-locale-value="ru">
  <h1 data-i18n-key="greeting" data-name="Алексей"></h1>
  <button data-i18n-key="submit"></button>
</div>

В примере:

  • <h1> автоматически заменит текст на Привет, Алексей!.
  • <button> получит текст Отправить.
  • Любое изменение data-i18n-locale-value вызовет обновление текста на новую локаль.

Динамическая смена языка

Stimulus обеспечивает реактивность без перезагрузки страницы. Изменение локали через JavaScript выглядит так:

const i18nController = document.querySelector("[data-controller='i18n']").controller;
i18nController.localeValue = "en";

В результате все элементы с data-i18n-key автоматически обновят свои тексты на английский.


Работа с формами и атрибутами

Для локализации атрибутов, таких как placeholder, title или aria-label, контроллер можно расширить:

renderTexts() {
  const locale = this.localeValue || "en";
  this.element.querySelectorAll("[data-i18n-key]").forEach(el => {
    const key = el.dataset.i18nKey;
    const text = locales[locale][key] ? this.interpolate(locales[locale][key]) : "";
    if (el.tagName === "INPUT" || el.tagName === "TEXTAREA") {
      el.placeholder = text;
    } else {
      el.textContent = text;
    }
  });
}

Это позволяет локализовать формы и другие интерактивные элементы без дублирования логики.


Локализация динамического контента

Для контента, добавляемого через AJAX или в процессе работы приложения, можно использовать наблюдателя за DOM:

const observer = new MutationObserver(() => {
  document.querySelectorAll("[data-controller='i18n']").forEach(controllerEl => {
    const controller = controllerEl.controller;
    controller?.renderTexts();
  });
});

observer.observe(document.body, { childList: true, subtree: true });

Такой подход гарантирует, что новые элементы с ключами локализации автоматически получат нужный текст при добавлении на страницу.


Вывод

Stimulus предоставляет удобный, минималистичный способ реализации локализации через контроллеры, реактивные значения и связывание с атрибутами HTML. Основные принципы включают централизованное хранение текстов, использование data-i18n-key, реактивное обновление при смене локали и поддержку динамически добавляемого контента. Такой подход обеспечивает чистую архитектуру, легко расширяемую для поддержки нескольких языков.