Lingo.dev CLI переводит Android-строковые ресурсы (strings.xml) через настроенный движок локализации. Тип bucket android в CLI нативно поддерживает элементы <resources>, <string>, <string-array> и <plurals>, сохраняя структуру XML и создавая корректные категории множественного числа для каждой целевой локали.
Это руководство пошагово показывает, как локализовать Android-приложение от начала до конца: настроить CLI, переводить локально и автоматизировать процесс через GitHub Actions, чтобы переводы попадали в релиз при каждом push.
Демо-репозиторий
Клонируйте или форкните lingodotdev/android-app-localization-example, чтобы повторять всё по ходу. В репозитории есть рабочий Android-проект со строковыми ресурсами, конфигурация CLI Lingo.dev и workflow GitHub Actions.
Как работает локализация Android#
Android использует соглашение о каталогах ресурсов, при котором для каждой локали создаётся отдельный каталог values-[locale]/. Во время выполнения система загружает нужный strings.xml в зависимости от языковых настроек устройства.
app/src/main/res/
values/ # Default (source) strings
strings.xml
values-es/ # Spanish
strings.xml
values-fr/ # French
strings.xml
values-ja/ # Japanese
strings.xmlТипичный strings.xml содержит три типа элементов:
<resources>
<!-- Simple strings -->
<string name="app_name">My App</string>
<string name="welcome_message">Welcome back!</string>
<!-- String arrays -->
<string-array name="planets">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
</string-array>
<!-- Plurals -->
<plurals name="items_count">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
</resources>CLI разбирает все три типа элементов, переводит их содержимое через движок локализации и записывает файлы для каждой локали в соответствующие каталоги values-[locale]/.
Что понадобится#
Создайте движок локализации
При каждом запуске CLI контент проходит через движок локализации — конфигурацию, которая определяет, какая LLM-модель, глоссарий, тональность бренда и инструкции будут применяться. Создайте его в панели Lingo.dev и сгенерируйте API-ключ.
Проверьте Node.js
Для CLI требуется Node.js 18 или выше:
node -vПодготовьте Android-проект
В проекте должен быть файл strings.xml по умолчанию в каталоге app/src/main/res/values/. Android Studio создаёт его при создании нового проекта. О настройке каталогов ресурсов подробнее — в руководстве по локализации Android.
Настройте CLI#
Создайте файл i18n.json в корне проекта. Bucket android подсказывает CLI, что нужно разбирать Android XML-ресурсы и создавать отдельные файлы для каждой локали:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"]
}
}
}Заполнитель [locale] во время выполнения подставляет код каждой настроенной локали. CLI подставляет исходную локаль в шаблон — поэтому при source: "en" он ищет values-en/strings.xml. Для целевых локалей будут созданы values-es/strings.xml, values-fr/strings.xml и так далее.
Свяжите каталог локали по умолчанию#
Android хранит строки по умолчанию в values/ (без суффикса локали), но CLI интерпретирует [locale] буквально и ищет values-en/strings.xml. Создайте символическую ссылку, чтобы связать эти два соглашения:
cd app/src/main/res
ln -s values values-enТак исходные строки будут доступны и по пути values/strings.xml (где их ожидает Android), и по пути values-en/strings.xml (где их ищет CLI). Закоммитьте символическую ссылку в репозиторий — git нативно отслеживает symlink на macOS и Linux.
Windows
Git в Windows может извлекать symlink как обычные текстовые файлы — это зависит от конфигурации. Если вы работаете в Windows, выполните git config core.symlinks true перед клонированием или просто скопируйте каталог values/ в values-en/.
Несколько файлов ресурсов
Если строки в проекте разбиты по нескольким файлам (например, strings.xml и arrays.xml), перечислите их все. Символическая ссылка охватывает весь каталог, поэтому все файлы внутри values/ будут доступны через values-en/:
{
"buckets": {
"android": {
"include": [
"app/src/main/res/values-[locale]/strings.xml",
"app/src/main/res/values-[locale]/arrays.xml"
]
}
}
}Переводите локально#
Укажите API-ключ и запустите CLI:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runCLI читает исходный strings.xml, находит непереведённые записи с помощью lockfile, переводит изменения через ваш движок локализации и записывает результат в целевые каталоги values-[locale]/. Откройте любой целевой файл, чтобы увидеть переведённые строки.
Чтобы работать с конкретной локалью во время разработки:
npx lingo.dev@latest run --target-locale esМножественное число#
Android использует элементы <plurals> с строками количества CLDR (zero, one, two, few, many, other) для обработки форм множественного числа. Разным языкам нужны разные категории множественного числа: английскому — две (one и other), русскому — четыре, арабскому — шесть.
CLI сохраняет структуру <plurals> при переводе и создаёт корректные элементы quantity для каждой целевой локали. Например, исходная запись с двумя категориями:
<plurals name="messages_count">
<item quantity="one">%d new message</item>
<item quantity="other">%d new messages</item>
</plurals>даёт корректные категории для каждого целевого языка. Движок локализации знает, какие правила множественного числа CLDR применяются к каждой локали, и создаёт только те категории, которые действительно нужны этому языку.
Блокировка ключей#
Некоторые строковые значения должны оставаться одинаковыми на всех языках — например, названия брендов, API-эндпоинты или шаблоны форматирования. Используйте блокировку ключей, чтобы копировать такие значения без перевода:
{
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"],
"lockedKeys": ["app_name", "api_base_url"]
}
}
}Заблокированные ключи копируются из исходного файла во все целевые файлы, не попадая в пайплайн перевода.
Автоматизируйте с GitHub Actions#
Добавьте файл workflow в .github/workflows/translate.yml, чтобы запускать перевод при каждом push:
Переводы коммитятся напрямую в main — минимум лишних шагов, идеально для небольших команд:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lingo.dev
uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}Сохраните API-ключ как LINGODOTDEV_API_KEY в разделе Settings > Secrets and variables > Actions вашего репозитория GitHub.
Проверьте перед деплоем#
Используйте флаг --frozen как условие деплоя, чтобы в production не попала ни одна непереведённая строка. Если какие-либо записи требуют перевода, CLI завершится с ненулевым статусом:
npx lingo.dev@latest run --frozenДобавьте это как отдельный шаг CI перед сборкой:
- name: Verify translations
run: npx lingo.dev@latest run --frozen