Множественные языки

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

Структура ресурсов

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

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

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

Свойства компонента

Polymer поддерживает реактивные свойства, которые автоматически обновляют шаблон при изменении значений. Для мультиязычного интерфейса создается свойство language и вычисляемое свойство currentTranslations:

import { PolymerElement, html } from '@polymer/polymer';

class MultiLangComponent extends PolymerElement {
  static get properties() {
    return {
      language: {
        type: String,
        value: 'en',
        observer: '_languageChanged'
      },
      currentTranslations: {
        type: Object,
        computed: '_computeTranslations(language)'
      }
    };
  }

  static get template() {
    return html`
      <div>
        <p>[[currentTranslations.greeting]]</p>
        <p>[[currentTranslations.farewell]]</p>
      </div>
    `;
  }

  _computeTranslations(language) {
    return translations[language] || translations.en;
  }

  _languageChanged(newLang) {
    this.currentTranslations = this._computeTranslations(newLang);
  }
}

customElements.define('multi-lang-component', MultiLangComponent);

Ключевые моменты:

  • Использование вычисляемого свойства _computeTranslations обеспечивает автоматическое обновление текста при смене языка.
  • Observer _languageChanged позволяет реагировать на внешние изменения свойства language, например, при переключении через настройки пользователя.

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

Смена языка может происходить через изменение свойства компонента:

const component = document.querySelector('multi-lang-component');
component.language = 'ru';

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

Локализация атрибутов и других элементов

Не всегда требуется менять только текст внутри <p> или <span>. Атрибуты элементов также могут быть локализованы с помощью биндинга:

<input placeholder="[[currentTranslations.searchPlaceholder]]">

Пример структуры словаря с атрибутами:

const translations = {
  en: { searchPlaceholder: "Search..." },
  ru: { searchPlaceholder: "Поиск..." }
};

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

Для крупных приложений может использоваться сторонняя библиотека i18n, например i18next, в связке с Polymer. Тогда объект currentTranslations формируется на основе API этой библиотеки:

import i18next from 'i18next';

_computeTranslations(language) {
  return i18next.getResourceBundle(language, 'translation');
}

Это позволяет использовать расширенные возможности: pluralization, форматирование дат и чисел, вложенные ключи и динамические параметры.

Поддержка lazy-load переводов

Для оптимизации загрузки можно подгружать ресурсы языков асинхронно. Например, хранить JSON-файлы с переводами на сервере и загружать их только при необходимости:

async _loadTranslations(language) {
  const response = await fetch(`/locales/${language}.json`);
  const data = await response.json();
  this.currentTranslations = data;
}

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

Реактивность и Shadow DOM

Polymer использует Shadow DOM, поэтому все биндинги внутри шаблона компонента остаются локальными. Это гарантирует корректное обновление текста независимо от структуры внешнего DOM и позволяет создавать независимые мультиязычные компоненты, которые можно повторно использовать без конфликтов.

Динамическая генерация контента

Иногда необходимо создавать элементы с текстом на лету. Polymer позволяет использовать шаблонные повторители dom-repeat с локализованными данными:

<template is="dom-repeat" items="[[currentTranslations.items]]">
  <li>[[item]]</li>
</template>

Словарь для примера:

ru: { items: ["Элемент 1", "Элемент 2", "Элемент 3"] }

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

  • Централизовать все текстовые ресурсы в одном объекте или внешних JSON-файлах.
  • Использовать реактивные свойства и вычисляемые значения для автоматического обновления интерфейса.
  • Поддерживать асинхронную загрузку переводов для оптимизации производительности.
  • Локализовать не только текстовые узлы, но и атрибуты, плейсхолдеры, заголовки.
  • Рассматривать интеграцию с внешними библиотеками i18n для сложных требований (pluralization, форматирование чисел, даты).

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