Мультиязычность

SkateJS — это современная библиотека для создания веб-компонентов, построенная на стандартных возможностях Custom Elements и Shadow DOM. Организация мультиязычности в компонентах SkateJS требует системного подхода, который объединяет реактивность, управление состоянием и динамическое обновление текста на основе выбранного языка.

Локализация текста через свойства компонента

В SkateJS свойства компонентов (props) играют ключевую роль в мультиязычной архитектуре. Для реализации мультиязычности часто создается свойство locale, которое хранит текущий язык интерфейса. Например:

import { component, h, prop } from 'skatejs';

class MyComponent extends HTMLElement {
  static props = {
    locale: prop.string({ attribute: true, default: 'en' })
  };

  render() {
    const translations = {
      en: { greeting: 'Hello' },
      ru: { greeting: 'Привет' },
      es: { greeting: 'Hola' }
    };
    const t = translations[this.locale] || translations['en'];

    return <div>{t.greeting}, world!</div>;
  }
}

customElements.define('my-component', MyComponent);

Ключевой момент: любое изменение свойства locale автоматически инициирует повторный рендер компонента, благодаря реактивной системе SkateJS.

Использование внешних файлов переводов

Для больших проектов удобнее хранить переводы отдельно в JSON или JS-файлах. Это позволяет динамически подгружать языковые пакеты и уменьшает размер исходного кода компонента.

Пример структуры переводов:

// locales/en.js
export default {
  greeting: 'Hello',
  farewell: 'Goodbye'
};

// locales/ru.js
export default {
  greeting: 'Привет',
  farewell: 'До свидания'
};

В компоненте это подключается через динамический импорт:

async updateLocale(lang) {
  const translations = await import(`./locales/${lang}.js`);
  this.translations = translations.default;
  this.update(); // вручную инициируем повторный рендер
}

Особенность SkateJS: this.update() можно использовать для ручного обновления, если изменение данных происходит вне реактивных свойств.

Реактивное переключение языка

Чтобы компонент автоматически менял язык при изменении свойства locale, можно использовать хук updated:

updated(prevProps) {
  if (prevProps.locale !== this.locale) {
    this.loadTranslations(this.locale);
  }
}

async loadTranslations(lang) {
  const translations = await import(`./locales/${lang}.js`);
  this.translations = translations.default;
}

Здесь updated позволяет отслеживать изменения и подгружать нужные переводы без перезагрузки страницы.

Форматирование данных

Мультиязычность включает не только тексты, но и форматирование дат, чисел и валют. В SkateJS это можно интегрировать через стандартный API Intl:

const date = new Date();
const formattedDate = new Intl.DateTimeFormat(this.locale, {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}).format(date);

return <div>{formattedDate}</div>;

Преимущество: поддержка локализации без сторонних библиотек, полная совместимость с любым языком, поддерживаемым браузером.

Интернационализация событий и атрибутов

Помимо текста, важно локализовать пользовательские события и атрибуты компонента. Например, если компонент генерирует уведомления:

this.dispatchEvent(new CustomEvent('message', {
  detail: { text: this.translations.farewell }
}));

Это гарантирует, что внешний код, подписанный на события компонента, всегда получает корректный текст на текущем языке.

Поддержка RTL и динамических стилей

Для языков с правосторонним письмом (rtl) необходимо менять CSS компонента динамически:

static get observedAttributes() {
  return ['locale'];
}

attributeChangedCallback(name, oldValue, newValue) {
  if (name === 'locale') {
    this.style.direction = newValue === 'ar' ? 'rtl' : 'ltr';
  }
}

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

Интеграция с внешними библиотеками

SkateJS можно легко интегрировать с i18n-библиотеками, такими как i18next, для управления сложными проектами. Основная идея сохраняется: локаль хранится в свойстве, а перевод берется из централизованного менеджера.

import i18next from 'i18next';

class MyComponent extends HTMLElement {
  static props = { locale: prop.string({ attribute: true }) };

  updated(prevProps) {
    if (prevProps.locale !== this.locale) {
      i18next.changeLanguage(this.locale);
      this.update();
    }
  }

  render() {
    return <div>{i18next.t('greeting')}</div>;
  }
}

Вывод

Реализация мультиязычности в SkateJS строится на комбинации реактивных свойств, динамических переводов, корректного форматирования данных и учета специфики различных языков (LTR/RTL). Такой подход обеспечивает модульность, легкость масштабирования и полную совместимость с современными веб-стандартами.