i18n-proto

Typings & protocol description for i18n interactions

Usage no npm install needed!

<script type="module">
  import i18nProto from 'https://cdn.skypack.dev/i18n-proto';
</script>

README

Интернационализационные пакеты и их использование

Слой интернационализации выполнен в виде нескольких минимально зависимых друг от друга пакетов, чтобы упростить их доработку и внедрение в рабочие проекты. Список пакетов на текущий момент включает:

  • i18n-proto - пакет с общими форматами и протоколами, используется для унификации договоренностей между остальными пакетами.
  • i18n-stex - STrings EXtractor, пакет, выделяющий из исходного кода строки переводов в формате, заданном протоколом.
  • i18n-json-po - конвертер из формата, заданного протоколом, в общепринятый формат PO/POT (он же формат gettext).
  • i18n-po-json - конвертер в обратную сторону.
  • i18n-dialect - независимая библиотека, которая инкапсулирует внутри себя всю грязную работу по локализации строк в рантайме приложения. В отличие от остальных пакетов, не может быть использована как отдельный CLI-tool и предназначена для внедрения непосредственно в целевое приложение в виде зависимости.

Основные концепции и идеи

В основу пакетной архитектуры легли следующие идеи и требования:

  • Слой интернационализации не должен ничего знать об архитектуре целевого приложения. Это позволит переиспользовать его практически без изменений в любом приложении, если оно написано на JS/TS.
  • Каждый пакет должен быть максимально простым для пользователя и выполнять единственную цель. По сути, это про UNIX-way и разделение ответственности. Требование простоты для пользователя можно также трактовать с точки зрения предоставляемого интерфейса: пакет или библиотека должны предоставлять максимально ограниченный интерфейс, достаточный для выполнения цели.
  • Каждый пакет должен быть покрыт тестами и документацией. Написание исчерпывающих тестов для программы с четко очерченной целью не должно представлять существенной сложности.

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

  • Если выявлен баг и его нужно поправить, обязательно нужны тесты на этот баг.
  • Если тем или иным образом уточняется или дополняется цель пакета, нужно убедиться, что обновленная цель соответствует вышеуказанным концепциям. В частности, не следует допускать размазывания ответственности и нечеткого назначения (типа, пакет делает вот это, но еще немного и вон то, хотя оно и не очень относится к первому).
  • Если выясняется, что пакет должен работать иначе, нужно опять же четко определить границы его ответственности.

Пример 1: библиотека интернационализации ни в коем случае не должна принимать на себя обязанность самостоятельной загрузки файлов переводов, поскольку конкретный способ загрузки определяет конечное приложение. Вместо этого библиотека должна принимать функцию получения перевода из конечного приложения в качестве параметра конфигурации.

Пример 2: пакет экстрактора строк не должен брать на себя обязанность формирования корректного файла PO/POT, поскольку это не его основная задача. При этом формирование данных в JSON-формате выглядит достаточно простым для реализации в составе экстрактора строк, поэтому разумно выбрать в качестве промежуточного именно этот формат.

Пример 3: библиотека интернационализации не должна брать на себя обязанность управления локализационными настройками (наименования валют, последовательность дней в неделе, формат даты, и т.д.), поскольку настройки не относятся к переводам. Можно даже сказать больше - выбор конкретного перевода зависит от одной из локальных настроек, поэтому реализацию локальных настроек должно брать на себя приложение. Кроме того, разные настройки могут зависеть от разных факторов; например, наименование валюты зависит только от текущей страны, с другой стороны формат даты может быть привязан к текущему выбранному языку.

Области ответственности пакетов и библиотек

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

  • i18n-proto
    • Единая точка задания контрактов между остальными пакетами.
    • Определяет интерфейсы взаимодействия.
  • i18n-stex
    • Вход: список файлов с исходным кодом конечного приложения.
    • Выход: список строк переводов с параметрами, контекстами, комментариями и прочим в формате, заданном протоколом
    • Также осуществляет проверку корректности вхождений строк переводов в исходных файлах и выдает ошибки и предупреждения при необходимости.
  • i18n-json-po
    • Вход: данные в формате, заданном протоколом.
    • Выход: валидный PO/POT файл, с которым могут работать любые стандартные gettext-утилиты.
    • Также осуществляет базовые проверки корректности данных, выдавая ошибки и предупреждения.
    • Также имеет некоторые настройки выходного формата, позволяющие, например, отключить указание вхождений строки в результирующем файле.
  • i18n-po-json
    • Вход: валидный PO/POT файл, с которым могут работать любые стандартные gettext-утилиты.
    • Выход: данные в формате, заданном протоколом.
    • Также осуществляет базовые проверки корректности данных, выдавая ошибки и предупреждения.
    • Также имеет некоторые настройки выходного формата, позволяющие, например, отключить указание вхождений строки в результирующем файле.
  • i18n-dialect
    • Единая точка входа для клиентского приложения
    • Предоставляет интернационализационные функции (_t, _pt, etc), используемые приложением в рантайме. Поддерживает необходимую функциональность, заявленную для этих функций (в частности, выбор плюральных форм, подстановки, макросы).
    • Гарантирует, что формат предоставляемых интернационализационных функций корректно обрабатывается парсером i18n-stex.
    • Предоставляет ограниченный интерфейс, позволяющий:
      • Получить перевод для строки в рантайме согласно текущим настройкам (это опять же про _t, _pt, etc).
      • Инициализировать смену текущего перевода на требуемый.
      • Задать способ получения данных переводов.
      • Задать способ сигнализирования клиентскому приложению о том, что переводы получены, готовы и их нужно перезагрузить.
      • Задать список общих макросов.
      • Передать иные настройки, определять которые должно конечное приложение, а не библиотека.

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