Узнайте, как можно добавить интернационализацию (i18n) в свое приложение Preact с помощью preact-i18n.

中 中文 中 (китайская версия): https://medium.com/@limhenry/how-to-add-i18n-to-preact-chinese-b49cfaf3a07b

Что такое интернационализация (i18n)?

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

В этой статье вы собираетесь использовать библиотеку preact-i18n для добавления интернационализации в ваше приложение Preact.

Шаг 1. Настройка Preact CLI и создание нового проекта

Боковое примечание: если вы уже знакомы с Preact, вы можете перейти к следующему шагу.

Если вы не установили Preact CLI на свой компьютер, используйте следующую команду для установки CLI. Убедитесь, что у вас установлен Node.js 6.x или выше.

$ npm install -g preact-cli

После установки Preact CLI давайте создадим новый проект, используя default template, и назовем его my-project.

$ preact create default my-project

Запустите сервер разработки с помощью следующей команды:

$ cd my-project && npm run start

Теперь откройте свой браузер и перейдите в http://localhost:8080, и вы должны увидеть что-то вроде этого на своем экране:

Шаг 2. Добавьте preact-i18n библиотеку

Установите библиотеку preact-i18n в свой проект, используя следующую команду:

$ npm install --save preact-i18n

preact-i18n очень прост в использовании и, что наиболее важно, очень мал - около 1,3 КБ после сжатия с помощью gzip. Вы можете узнать больше о библиотеке здесь:



Шаг 3. Создайте файл определения

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

В этом случае вам нужно будет сохранить этот файл в src/i18n/zh-tw.json:

{ 
  "home": {
    "title": "主頁", 
    "text": "這是個Home組件。"
  }
}

Шаг 4. Импортируйте IntlProvider и файл определения

Затем откройте файл app.js, который находится в папке src/components. Затем импортируйте IntlProvider и ваш definition файл в app.jsfile:

import { IntlProvider } from 'preact-i18n';
import definition from '../i18n/zh-tw.json';

Шаг 5. Разместите определение с помощью ‹IntlProvider›

После этого вам нужно будет открыть файл определения всему приложению через <IntlProvider>. Сделав это, вы сможете читать файл определения повсюду в приложении.

render() {
  return(
    <IntlProvider definition={definition}>
      <div id="app" />
    </IntlProvider>
  );
}

В настоящий момент ваш app.js файл должен выглядеть следующим образом:

import { h, Component } from 'preact';
import { Router } from 'preact-router';
import Header from './header';
import Home from '../routes/home';
import Profile from '../routes/profile';
// Import IntlProvider and the definition file.
import { IntlProvider } from 'preact-i18n';
import definition from '../i18n/zh-tw.json';
export default class App extends Component {
 
 handleRoute = e => {
  this.currentUrl = e.url;
 };
render() {
  return (
   // Expose the definition to your whole app via <IntlProvider>
   <IntlProvider definition={definition}>
    <div id="app">
     <Header />
     <Router onChange={this.handleRoute}>
      <Home path="/" />
      <Profile path="/profile/" user="me" />
      <Profile path="/profile/:user" />
     </Router>
    </div>
   </IntlProvider>
  );
 }
}

Шаг 6. Используйте ‹Text› для перевода строковых литералов

Вы почти закончили, теперь вам просто нужно заменить текст на странице на <Text>. В этом случае вам нужно будет обновить содержимое домашней страницы (src/routes/home/index.js), добавив <Text> внутри тегов <h1> и <p>.

import { Text } from 'preact-i18n';
const Home = () => ( 
  <div> 
    <h1> 
      <Text id="home.title">Home</Text> 
    </h1> 
    <p> 
      <Text id="home.text">This is the Home component.</Text> 
    </p> 
  </div> 
); 
export default Home;

Резервный текст

Чтобы предотвратить отображение пустого текста на странице, вы должны установить резервный текст на <Text>. Если вы не включили определение для unknown.definition, библиотека отобразит любой текст, содержащийся в <Text>…</Text>, как резервный текст:

<Text id="unknown.definition">This is a fallback text.</Text>
// It will render this text: "This is a fallback text."

‹Localizer› и ‹MarkupText›

Если вы хотите перевести текст значения атрибута HTML (например: placeholder="", title="" и т. Д.), Вам нужно будет использовать <Localizer> вместо <Text>.

Однако, если вы хотите включить разметку HTML в отображаемую строку, вам нужно будет использовать <MarkupText>. С помощью этого компонента ваш текст будет отображаться в теге <span>.

В приведенном ниже примере вы собираетесь добавить еще несколько строк кода в свой файл определения. first_name и last_name будут использоваться для примера <Localizer>, а link - для примера для <MarkupText>.

{ 
  "first_name": "名",
  "last_name": "姓",
  "link": "這是個<a href='https://www.google.com'>連結</a>"
}

При этом вы сможете использовать на странице <Localizer> и <MarkupText>. Обратите внимание, что вам необходимо импортировать Localizer и MarkupText в файл src/routes/home/index.js.

import { Text, Localizer, MarkupText } from 'preact-i18n';
const Home = () => ( 
  <div> 
    <Localizer> 
      <input placeholder={<Text id="first_name" />} /> 
    </Localizer> 
    <Localizer> 
      <input placeholder={<Text id="last_name" />} /> 
    </Localizer> 
    <MarkupText id="link"> 
      This is a <a href="https://www.google.com">link</a>
    </MarkupText>
  </div>
);
export default Home;

Шаблоны

Если вы хотите добавить в определение настраиваемую строку или значение, вы можете сделать это с помощью fields props.

Во-первых, вам нужно обновить файл определения с помощью заполнителя {{field}}. Заполнитель будет заменен согласованными ключами в объекте, который вы передали в fields реквизитах.

{
  "page": "{{count}} / {{total}} 頁"
}

Затем вам нужно будет добавить атрибут fields вместе со значением в <Text />. В результате ваш код должен выглядеть так:

import { Text } from 'preact-i18n'; 
const Home = () => ( 
  <div>
    <h2> 
      <Text id="page" fields={{ count: 5, total: 10 }}>
         5 / 10 Pages
      </Text> 
    </h2> 
  </div> 
); 
export default Home;

Плюрализация

С preact-i18n у вас есть 3 способа указать значения множественного числа:

  • "key": { "singular":"apple", "plural":"apples" }
  • "key": { "none":"no apples", "one":"apple", "many":"apples" }
  • "key": ["apples", "apple"]

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

{
  "apple": { 
    "singular": "Henry has {{count}} apple.", 
    "plural":"Henry has {{count}} apples." 
  }
}

Затем вы обновите домашнюю страницу (src/routes/home/index.js) следующим кодом:

import { Text } from 'preact-i18n'; 
const Home = () => ( 
  <div> 
    <p> 
      <Text id="apple" plural={1} fields={{ count: 1 }} /> 
    </p> 
    <p> 
      <Text id="apple" plural={100} fields={{ count: 100 }} /> 
    </p> 
  </div> 
); 
export default Home;

С помощью описанного выше метода вы сможете добавить плюрализацию и шаблоны в свое приложение Preact.

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

В реальном сценарии вы хотели бы установить язык сайта на основе выбора пользователя, который либо основан на navigator.language, либо пользователь может изменить язык сайта самостоятельно.

Однако, чтобы предотвратить импорт всех ненужных файлов определений в проект, вы можете динамически импортировать файл определения языка с помощью import(). Сделав это, вы можете импортировать файл определения языка в зависимости от выбора пользователя.

import { Component } from 'preact'; 
import { IntlProvider } from 'preact-i18n'; 
import defaultDefinition from '../i18n/zh-tw.json'; 
export default class App extends Component { 
  state = { 
    definition: defaultDefinition 
  } 
  changeLanguage = (lang) => { 
    // Call this function to change language 
    import(`../i18n/${lang}.json`) 
      .then(definition => this.setState({ definition })); 
  }; 
  render({ }, { definition }) { 
    return ( 
      <IntlProvider definition={definition}> 
        <div id="app" /> 
      </IntlProvider> 
    ); 
  } 
}

В этом случае вы можете вызвать функцию this.changeLanguage('zh-TW'), чтобы изменить язык сайта.

Кто использует preact-i18n?

Я использую preact-i18n для своего побочного проекта: Remote for Slides.

Remote for Slides - это прогрессивное веб-приложение + расширение Chrome, которое позволяет пользователю управлять своими слайдами Google на любом устройстве удаленно, без необходимости в дополнительном оборудовании.

Прогрессивное веб-приложение Remote for Slides поддерживает более 8 языков, в том числе: катала, английский, испанский, европейский, французский, польский, традиционный китайский и упрощенный китайский.

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

Кроме того, прогрессивное веб-приложение Remote for Slides установит язык в зависимости от языка браузера (navigator.language) или параметра URL (например, s.limhenry.xyz/?hl=zh-tw), либо пользователь может изменить его на странице настроек.

Вы можете узнать больше о Remote for Slides здесь:



Ресурсы