Быстрый способ настроить i18n для компонентов Stencil без зависимостей.

Я использовал ту же стратегию для быстрой интернационализации компонентов Stencil без зависимостей в различных проектах. В том числе для проекта Owlly или Bonjour Foundation.

Поскольку все эти проекты имеют открытый код, я поделюсь с вами своим рецептом 🧑‍🍳.

Цель

Я недавно с помощью сообщества интернационализировал наш проект DeckDeckGo, но цель этой статьи - добавить переводы к относительно небольшому компоненту или набору компонентов без зависимости.

Я использую это решение, когда создаю компоненты, которые содержат несколько slot со значениями по умолчанию и которые имеют основной рынок нашей прекрасной «четыре языка + английский по умолчанию» в Швейцарии 🇨🇭.

Настраивать

В вашем проекте создайте новую утилиту translations.util.ts и добавьте объявления.

interface Translation {
  [key: string]: string;
}

interface Translations {
  de: Translation;
  en: Translation;
}

В этом примере я буду использовать «только» немецкий и английский языки. Для практического использования дополните его своими требованиями.

Я объявил interface Translation, но его можно заменить на TypeScript Record<string, string>. Результат такой же, как вам больше нравится.

После объявлений добавьте константу для языка по умолчанию (запасного) и список поддерживаемых языков.

const DEFAULT_LANGUAGE: 'en' = 'en';

const SUPPORTED_LANGUAGES: string[] = ['de', 'en'];

Наконец, добавьте эффективные переводы.

const TRANSLATIONS: Translations = {
  de: {
    question: 'Wie fühlen Sie sich heute?',
    super: 'Sehr gut',
    bad: 'Nicht gut'
  },
  en: {
    question: 'How do you feel today?',
    super: 'Super',
    bad: 'Bad'
  }
};

В этом решении, поскольку моя цель - сделать его быстрым и простым, я кодирую переводы.

Их можно обрабатывать в отдельных json файлах и import динамически во время выполнения. Эти две функции я разработал для более сложного случая использования. В конце концов, мне действительно может понадобиться написать об этом в блоге? Напишите мне, если вы думаете, что это будет интересная тема!

Определить языки

Я не изобретал велосипед. Я взглянул на широко используемую библиотеку с открытым исходным кодом ngx-translate и реализовал ее определение языков браузера.

В том же файле добавьте следующую функцию и инициализацию языка по умолчанию.

const initBrowserLang = (): string | undefined => {
  if (typeof window === 'undefined' 
      || typeof window.navigator === 'undefined') {
    return undefined;
  }

  let browserLang: string | null =
    window.navigator.languages 
    && window.navigator.languages.length > 0 ? 
              window.navigator.languages[0] : null;
  // @ts-ignore
  browserLang = browserLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;

  if (typeof browserLang === 'undefined') {
    return undefined;
  }

  if (browserLang.indexOf('-') !== -1) {
    browserLang = browserLang.split('-')[0];
  }

  if (browserLang.indexOf('_') !== -1) {
    browserLang = browserLang.split('_')[0];
  }

  return browserLang;
}

const browserLang: string | undefined = initBrowserLang();

Функция

Настройка и обнаружение готовы, нам нужна функция для рендеринга переводов.

export const translate = 
             (key: string, customLang?: 'de' | 'en'): string => {
  const lang: string | undefined = customLang || browserLang;
  return TRANSLATIONS[lang !== undefined 
                      && SUPPORTED_LANGUAGES.includes(lang) ? 
                         lang : DEFAULT_LANGUAGE][key];
};

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

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

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

import {Component, h, Host} from '@stencil/core';

import {translate} from './translations.utils';

@Component({
  tag: 'question',
  shadow: true
})
export class Question {
  render() {
    return <Host>
      <p>{translate('question')}</p>
      <slot name="answer">{translate('super', 'de')}</slot>
    </Host>;
  }
}

Он отображает текст с указанием языка или без него, а также может использоваться с slot.

Резюме

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

Бесконечность не предел!

Дэйвид

Вы можете связаться со мной в Твиттере или на моем сайте.

Попробуйте DeckDeckGo для следующих слайдов 🤟.