Advanced Installer (AIL)

AI-перевод файлов локализации Advanced Installer с помощью Lingo.dev CLI

Что такое Advanced Installer AIL?

Advanced Installer — это инструмент для создания установщиков Windows, который помогает разработчикам создавать MSI-пакеты (Microsoft Installer). AIL (Advanced Installer Localization) — это основанный на XML многоязычный формат словаря, используемый для локализации диалоговых окон, кнопок, сообщений и свойств установщика. Все переводы для разных языков хранятся в одном файле AIL.

Что такое Lingo.dev CLI?

Lingo.dev CLI — это бесплатный open-source CLI для перевода приложений и контента с помощью ИИ. Он создан, чтобы заменить традиционные системы управления переводами и легко интегрируется в существующие пайплайны.

Подробнее см. в разделе Обзор.

О данном руководстве

В этом руководстве объясняется, как переводить файлы Advanced Installer AIL с помощью Lingo.dev CLI.

Вы узнаете, как:

  • Создать проект с нуля
  • Настроить пайплайн перевода
  • Генерировать переводы с помощью ИИ

Необходимые условия

Для работы с Lingo.dev CLI убедитесь, что установлен Node.js v18+:

❯ node -v
v22.17.0

Шаг 1. Создайте проект

В каталоге вашего проекта создайте файл i18n.json:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {}
}

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

Подробнее о доступных свойствах см. в разделе i18n.json.

Шаг 2. Настройте исходную локаль

Исходная локаль — это оригинальный язык и регион, на которых был написан ваш контент. Чтобы настроить исходную локаль, укажите свойство locale.source в файле i18n.json:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {}
}

Исходная локаль должна быть указана в виде языкового тега BCP 47.

Полный список кодов локалей, поддерживаемых Lingo.dev CLI, смотрите в разделе Поддерживаемые коды локалей.

Шаг 3. Настройте целевые локали

Целевые локали — это языки и регионы, на которые вы хотите перевести свой контент. Чтобы настроить целевые локали, укажите свойство locale.targets в файле i18n.json:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {}
}

Шаг 4. Создайте исходный контент

Если вы ещё не сделали этого, создайте файл AIL, который будет содержать переводимый контент. Файлы AIL используют XML-структуру, где все переводы языков хранятся в одном файле.

Структура файла:

<?xml version="1.0" encoding="UTF-8"?>
<DICTIONARY type="multilanguage">
  <ENTRY id="Control.Text.WelcomeDlg#Title">
    <STRING lang="en" value="Welcome to the Setup Wizard"/>
  </ENTRY>
  <ENTRY id="Control.Button.Next">
    <STRING lang="en" value="Next"/>
  </ENTRY>
</DICTIONARY>

Переводимый контент:

  • Каждый элемент ENTRY представляет собой переводимую строку с уникальным атрибутом id
  • Элементы STRING внутри каждого ENTRY содержат переводы для конкретных языков
  • Атрибут lang указывает код языка
  • Атрибут value содержит переводимый текст

Правила для ID записей:

Файлы AIL используют структурированные ID для организации содержимого установщика:

  • Текст элементов управления: Control.Text.DialogName#ElementName
  • Кнопки управления: Control.Button.ButtonName
  • Свойства: Property.PropertyName

Например:

  • Control.Text.WelcomeDlg#Title — заголовок окна приветствия
  • Control.Button.Next — текст для кнопки "Далее"
  • Property.ProductName — свойство с названием продукта

Переменные Advanced Installer:

Файлы AIL поддерживают переменные Advanced Installer, которые подставляются во время выполнения:

  • [ProductName] — заменяется на имя продукта
  • [ProductVersion] — заменяется на версию продукта
  • [Manufacturer] — заменяется на имя производителя

Эти переменные сохраняются при переводе:

<ENTRY id="Control.Text.WelcomeDlg#Title">
  <STRING lang="en" value="Welcome to [ProductName] Setup"/>
</ENTRY>

Режим вывода:

AIL bucket изменяет исходный файл, а не создаёт отдельные файлы для каждой локали. При запуске перевода CLI добавляет или обновляет элементы STRING для целевых локалей прямо в существующем AIL-файле. Это связано с тем, что файлы AIL предназначены для хранения всех языковых переводов в одном файле.

Шаг 5. Создайте bucket

  1. В файле i18n.json добавьте объект "ail" в объект buckets:

    {
      "$schema": "https://lingo.dev/schema/i18n.json",
      "version": "1.10",
      "locale": {
        "source": "en",
        "targets": ["es"]
      },
      "buckets": {
        "ail": {}
      }
    }
    
  2. В объекте "ail" определите массив из одного или нескольких паттернов include:

    {
      "$schema": "https://lingo.dev/schema/i18n.json",
      "version": "1.10",
      "locale": {
        "source": "en",
        "targets": ["es"]
      },
      "buckets": {
        "ail": {
          "include": ["./*.ail"]
        }
      }
    }
    

    Эти паттерны определяют, какие файлы переводить.

    Сами паттерны:

    • могут указывать на пути к файлам (например, "./installer.ail")
    • могут использовать звёздочки как подстановочные знаки (например, "./*.ail")
    • не используют плейсхолдер [locale] (так как все локали в одном файле)

    Рекурсивные glob-паттерны (например, **/*.ail) не поддерживаются.

Шаг 6. Настройте LLM

Lingo.dev CLI использует большие языковые модели (LLM) для перевода контента с помощью ИИ. Чтобы использовать одну из этих моделей, вам нужен API-ключ от поддерживаемого провайдера.

Чтобы начать как можно быстрее, рекомендуем использовать Lingo.dev Engine:

  1. Зарегистрируйтесь в Lingo.dev.

  2. Выполните следующую команду:

    npx lingo.dev@latest login
    

    Откроется ваш браузер по умолчанию и попросит пройти аутентификацию.

  3. Следуйте инструкциям.

Шаг 7. Сгенерируйте переводы

В каталоге, где находится файл i18n.json, выполните следующую команду:

npx lingo.dev@latest run

Эта команда:

  1. Считывает файл i18n.json.
  2. Находит файлы, которые нужно перевести.
  3. Извлекает переводимый контент из файлов.
  4. Использует настроенный LLM для перевода извлечённого контента.
  5. Записывает переведённый контент обратно в файловую систему.

При первом запуске генерации переводов создаётся файл i18n.lock. Этот файл отслеживает, какой контент уже переведён, чтобы избежать лишних повторных переводов при следующих запусках.

Пример

До перевода (example.ail)

<?xml version="1.0" encoding="UTF-8"?>
<DICTIONARY type="multilanguage">
  <ENTRY id="Control.Text.WelcomeDlg#Title">
    <STRING lang="en" value="Welcome to the [ProductName] Setup Wizard"/>
  </ENTRY>
  <ENTRY id="Control.Text.WelcomeDlg#Description">
    <STRING lang="en" value="The Setup Wizard will install [ProductName] on your computer. Click Next to continue or Cancel to exit the Setup Wizard."/>
  </ENTRY>
  <ENTRY id="Control.Text.LicenseAgreementDlg#Title">
    <STRING lang="en" value="End-User License Agreement"/>
  </ENTRY>
  <ENTRY id="Control.Text.LicenseAgreementDlg#AcceptCheckbox">
    <STRING lang="en" value="I accept the terms in the License Agreement"/>
  </ENTRY>
  <ENTRY id="Control.Button.Next">
    <STRING lang="en" value="Next"/>
  </ENTRY>
  <ENTRY id="Control.Button.Cancel">
    <STRING lang="en" value="Cancel"/>
  </ENTRY>
  <ENTRY id="Property.ProductName">
    <STRING lang="en" value="My Application"/>
  </ENTRY>
</DICTIONARY>

После перевода (example.ail)

<?xml version="1.0" encoding="UTF-8"?>
<DICTIONARY type="multilanguage">
  <ENTRY id="Control.Text.WelcomeDlg#Title">
    <STRING lang="en" value="Welcome to the [ProductName] Setup Wizard"/>
    <STRING lang="es" value="Bienvenido al asistente de instalación de [ProductName]"/>
  </ENTRY>
  <ENTRY id="Control.Text.WelcomeDlg#Description">
    <STRING lang="en" value="The Setup Wizard will install [ProductName] on your computer. Click Next to continue or Cancel to exit the Setup Wizard."/>
    <STRING lang="es" value="El asistente de instalación instalará [ProductName] en su ordenador. Haga clic en Siguiente para continuar o en Cancelar para salir del asistente de instalación."/>
  </ENTRY>
  <ENTRY id="Control.Text.LicenseAgreementDlg#Title">
    <STRING lang="en" value="End-User License Agreement"/>
    <STRING lang="es" value="Acuerdo de licencia para el usuario final"/>
  </ENTRY>
  <ENTRY id="Control.Text.LicenseAgreementDlg#AcceptCheckbox">
    <STRING lang="en" value="I accept the terms in the License Agreement"/>
    <STRING lang="es" value="Acepto los términos del acuerdo de licencia"/>
  </ENTRY>
  <ENTRY id="Control.Button.Next">
    <STRING lang="en" value="Next"/>
    <STRING lang="es" value="Siguiente"/>
  </ENTRY>
  <ENTRY id="Control.Button.Cancel">
    <STRING lang="en" value="Cancel"/>
    <STRING lang="es" value="Cancelar"/>
  </ENTRY>
  <ENTRY id="Property.ProductName">
    <STRING lang="en" value="My Application"/>
    <STRING lang="es" value="My Application"/>
  </ENTRY>
</DICTIONARY>

i18n.json

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {
    "ail": {
      "include": ["./*.ail"]
    }
  }
}

i18n.lock

version: 1
checksums:
  f84d41a1c3ad7e70e25c84811ef9baef:
    Control.Text.WelcomeDlg%23Title: 93af4b47a8c0a84ce9fb82d2ee2bca13
    Control.Text.WelcomeDlg%23Description: 9cbc6500217ae2a7b3ffd74a3c723493
    Control.Text.LicenseAgreementDlg%23Title: 3fe6d3757d7129ede78b41dd06042bf2
    Control.Text.LicenseAgreementDlg%23AcceptCheckbox: 768d9d11db014facbc1b65af8e39e260
    Control.Button.Next: 4c49d903308e8e3f5c866cfd78ef0e89
    Control.Button.Cancel: a149e8d5b349f68b3cfc9fbe6b23cbb4
    Property.ProductName: c215a8d46c95f00089c5ea0d17eef742