Интернационализация компонентов

Интернационализация (i18n) компонентов в Lit обеспечивает возможность динамического отображения текста, дат, чисел и других данных в соответствии с локалью пользователя. В Lit подход к i18n строится на декларативном управлении шаблонами и реактивных свойствах, что позволяет гибко интегрировать локализацию без утяжеления кода.

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

Реактивные свойства и локаль

Lit поддерживает реактивные свойства через декораторы @property. Для интернационализации важно завести свойство locale:

import { LitElement, html, css } from 'lit';
import { property } from 'lit/decorators.js';

class LocalizedComponent extends LitElement {
  @property({ type: String })
  locale = 'en';

  @property({ type: Object })
  messages = {};
  
  static styles = css`
    :host {
      display: block;
      font-family: sans-serif;
    }
  `;

  render() {
    return html`<p>${this.messages[this.locale]?.greeting || 'Hello'}</p>`;
  }
}
customElements.define('localized-component', LocalizedComponent);

Здесь locale определяет текущую локаль, а объект messages содержит все переводы. Доступ к переводу осуществляется через реактивное свойство, что позволяет автоматически обновлять DOM при изменении локали.

Организация ресурсов локализации

Для крупных приложений рекомендуется хранить переводы в отдельных JSON-файлах. Пример структуры:

locales/
├─ en.json
├─ ru.json
└─ fr.json

Пример ru.json:

{
  "greeting": "Привет",
  "farewell": "До свидания",
  "date_format": "DD.MM.YYYY"
}

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

async loadLocale(locale) {
  this.messages = await import(`./locales/${locale}.json`);
  this.locale = locale;
}

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

Форматирование дат и чисел

Для корректного отображения дат, времени и чисел используется стандарт Intl:

formatDate(date) {
  return new Intl.DateTimeFormat(this.locale, { day: '2-digit', month: 'long', year: 'numeric' }).format(date);
}

formatNumber(number) {
  return new Intl.NumberFormat(this.locale, { style: 'currency', currency: 'USD' }).format(number);
}

При изменении locale все вызовы форматирования автоматически обновляются, если использовать их внутри рендер-функции.

Локализация шаблонов

В Lit шаблоны создаются с помощью html-тегов, что делает интеграцию локализации удобной. Можно создавать вспомогательные функции:

t(key) {
  return this.messages[this.locale]?.[key] || key;
}

render() {
  return html`
    <h1>${this.t('greeting')}</h1>
    <p>${this.t('farewell')}</p>
    <p>${this.formatDate(new Date())}</p>
  `;
}

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

Динамическое переключение локали

Смена языка в реальном времени реализуется через обновление свойства locale:

<button @click=${() => this.loadLocale('ru')}>RU</button>
<button @click=${() => this.loadLocale('en')}>EN</button>

Благодаря реактивности Lit, все элементы интерфейса автоматически перерисовываются с новыми локализованными значениями.

Особенности и рекомендации

  • Кэширование переводов: для улучшения производительности рекомендуется кэшировать JSON-файлы локалей, чтобы не загружать их повторно при смене языка.
  • Множественное использование компонентов: если один перевод используется в нескольких компонентах, лучше вынести его в общий сервис или модуль.
  • Динамические строки: для строк с параметрами (например, “Привет, {name}”) удобно использовать шаблоны или библиотеку lit-html с интерполяцией.
  • Поддержка RTL: при работе с языками, которые читаются справа налево, необходимо учитывать CSS-свойство direction и при необходимости применять классы к корневым элементам.

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

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

  • Поддержка вложенных ключей и пространств имён.
  • Плейсхолдеры и интерполяция параметров.
  • Динамическая загрузка локалей.
  • Поддержка множественных форм чисел и падежей для разных языков.

Lit хорошо сочетается с такими библиотеками, поскольку реактивные свойства позволяют обновлять шаблон при изменении локали без дополнительной работы с DOM.