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
-
В файле
i18n.jsonдобавьте объект"ail"в объектbuckets:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "ail": {} } } -
В объекте
"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:
-
Выполните следующую команду:
npx lingo.dev@latest loginОткроется ваш браузер по умолчанию и попросит пройти аутентификацию.
-
Следуйте инструкциям.
Шаг 7. Сгенерируйте переводы
В каталоге, где находится файл i18n.json, выполните следующую команду:
npx lingo.dev@latest run
Эта команда:
- Считывает файл
i18n.json. - Находит файлы, которые нужно перевести.
- Извлекает переводимый контент из файлов.
- Использует настроенный LLM для перевода извлечённого контента.
- Записывает переведённый контент обратно в файловую систему.
При первом запуске генерации переводов создаётся файл 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