Переключение языков

Slim.js — это легковесная библиотека для создания веб-компонентов с реактивностью и декларативным синтаксисом. Одной из часто востребованных задач является организация многоязычного интерфейса и динамическое переключение языков в приложении.


Основные принципы многоязычности

Многоязычность в Slim.js реализуется через:

  • централизованное хранение текстовых ресурсов;
  • реактивное обновление компонентов при смене языка;
  • минимальное вмешательство в разметку компонентов.

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


Хранение и организация локалей

Наиболее распространенный подход — объект с ключами языков и вложенными объектами строк:

const locales = {
  en: {
    greeting: "Hello",
    farewell: "Goodbye",
    date: "Date"
  },
  ru: {
    greeting: "Привет",
    farewell: "До свидания",
    date: "Дата"
  },
  es: {
    greeting: "Hola",
    farewell: "Adiós",
    date: "Fecha"
  }
};

Ключевой момент — единообразие ключей в каждом языке. Это позволяет использовать динамическую подстановку текста без проверки наличия ключа.


Глобальное состояние языка

Для реактивного обновления необходимо создать наблюдаемое состояние:

import { Slim, store } from "slim-js";

const languageStore = store({
  current: "en"
});

export default languageStore;

store создаёт реактивный объект. Любые компоненты, использующие его свойства, автоматически перерисовываются при изменении языка.


Использование локалей в компонентах

В Slim.js текстовые данные вставляются через биндинг:

import Slim from "slim-js";
import languageStore from "./languageStore.js";
import { locales } from "./locales.js";

class GreetingComponent extends Slim {
  get template() {
    return `
      <div>
        <p>{{text.greeting}}</p>
        <p>{{text.farewell}}</p>
      </div>
    `;
  }

  get text() {
    return locales[languageStore.current];
  }
}

customElements.define('greeting-component', GreetingComponent);

Каждый раз, когда languageStore.current меняется, text автоматически обновляется, и компонент перерисовывается с новым языком.


Переключение языка

Для изменения языка достаточно обновить свойство current в глобальном хранилище:

function switchLanguage(lang) {
  if(locales[lang]) {
    languageStore.current = lang;
  }
}

switchLanguage("ru"); // Все компоненты автоматически обновят текст

Важно проверять, существует ли выбранная локаль, чтобы избежать ошибок в шаблонах.


Динамические ключи и форматирование текста

Slim.js поддерживает динамическую подстановку через функции:

const locales = {
  en: {
    welcome: (name) => `Welcome, ${name}!`,
  },
  ru: {
    welcome: (name) => `Добро пожаловать, ${name}!`,
  }
};

class WelcomeComponent extends Slim {
  get template() {
    return `<p>{{text.welcome("Алексей")}}</p>`;
  }

  get text() {
    return locales[languageStore.current];
  }
}

customElements.define('welcome-component', WelcomeComponent);

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


Интеграция с пользовательскими элементами управления

Переключатель языка можно реализовать как отдельный компонент:

class LanguageSwitcher extends Slim {
  get template() {
    return `
      <select @change="changeLanguage($event)">
        <option value="en">English</option>
        <option value="ru">Русский</option>
        <option value="es">Español</option>
      </select>
    `;
  }

  changeLanguage(event) {
    languageStore.current = event.target.value;
  }
}

customElements.define('language-switcher', LanguageSwitcher);

Все компоненты, привязанные к languageStore.current, обновляются автоматически при выборе нового языка в селекте.


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

Для многоязычного интерфейса важна не только замена текста, но и корректное форматирование дат и чисел:

function formatDate(date) {
  return new Intl.DateTimeFormat(languageStore.current).format(date);
}

function formatNumber(number) {
  return new Intl.NumberFormat(languageStore.current).format(number);
}

Эти функции можно использовать в Slim-шаблонах:

<p>{{formatDate(new Date())}}</p>
<p>{{formatNumber(1234567.89)}}</p>

Рекомендации по структуре проекта

  • Разделять локали по файлам: locales/en.js, locales/ru.js и т. д.
  • Хранить глобальное состояние языка в отдельном модуле.
  • Использовать функции для динамических строк и форматирования.
  • Компоненты должны быть максимально независимыми от конкретного языка, используя биндинг через languageStore.

Реактивность и производительность

Slim.js обновляет только те узлы DOM, которые изменились. Поэтому использование глобального store не приводит к полной перерисовке приложения, а только к обновлению текстовых узлов, что обеспечивает высокую производительность при масштабировании интерфейса.