Lingo.dev CLI переводит Xcode String Catalogs (.xcstrings) через настроенный движок локализации. String Catalogs — это современный формат локализации от Apple, представленный в Xcode 15, где все языки хранятся в одном JSON-файле. CLI изменяет этот файл напрямую — отдельные папки для каждой локали не нужны.
В этом руководстве разберём локализацию iOS-приложения от начала до конца: настроим CLI, выполним перевод локально и автоматизируем процесс через GitHub Actions, чтобы переводы выкатывались с каждым push.
Демо-репозиторий
Клонируйте или форкните lingodotdev/ios-app-localization-example, чтобы пройти всё на практике. В репозитории есть рабочий проект Xcode со String Catalogs, конфигурация CLI Lingo.dev и Процесс GitHub Actions.
Как работают String Catalogs#
До Xcode 15 локализация iOS требовала поддерживать отдельные файлы .strings и .stringsdict в каталогах [locale].lproj/. String Catalogs заменяют всё это одним файлом Localizable.xcstrings, который Xcode поддерживает автоматически.
Когда вы помечаете строку как локализуемую в SwiftUI или UIKit, Xcode обнаруживает её во время сборки и добавляет запись в String Catalog. В каждой записи хранится исходная строка, её переводы для всех настроенных локалей и необязательное поле комментария, которое даёт переводчикам дополнительный контекст.
| Параметр | Устаревшие .strings | String Catalogs .xcstrings |
|---|---|---|
| Количество файлов | Один на локаль для каждой таблицы | Один файл для всех локалей |
| Формат | Текст в формате ключ-значение | Структурированный JSON |
| Поддержка множественного числа | Отдельный файл .stringsdict | Встроенные правила множественного числа |
| Интеграция с Xcode | Ручной экспорт и импорт | Автоматическое определение |
| Заметки для переводчиков | Не поддерживаются | Поле комментария для каждой записи |
Тип bucket xcode-xcstrings в CLI разбирает эту JSON-структуру, переводит каждую запись через движок локализации и записывает переводы обратно в тот же файл, сохраняя комментарии, формы множественного числа и метаданные.
Что понадобится#
Создайте движок локализации
При каждом запуске CLI контент проходит через движок локализации — конфигурацию, которая определяет, какая LLM-модель, glossary, тональность бренда и instructions будут использоваться. Создайте его в Lingo.dev dashboard и сгенерируйте API key.
Проверьте Node.js
Для CLI требуется Node.js 18 или выше:
node -vВключите локализацию в Xcode
В проекте Xcode откройте Project Settings > Info > Localizations и добавьте нужные целевые языки. Xcode создаст записи в String Catalog для каждой добавленной локали. Подробнее — в документации Apple по локализации.
Настройка CLI#
Создайте файл i18n.json в корне проекта. Bucket xcode-xcstrings подсказывает CLI, что нужно разобрать формат String Catalog и изменить файл на месте:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"xcode-xcstrings": {
"include": ["MyApp/Localizable.xcstrings"]
}
}
}Поскольку String Catalogs хранят все локали в одном файле, заполнитель [locale] в шаблоне include не нужен. CLI считывает записи исходного языка, переводит их и записывает все целевые языки обратно в тот же файл .xcstrings.
Несколько String Catalogs
Если в проекте используется несколько файлов String Catalog (например, по одному на каждый target фреймворка), перечислите их все в массиве include:
{
"buckets": {
"xcode-xcstrings": {
"include": [
"MyApp/Localizable.xcstrings",
"MyAppWidgets/Localizable.xcstrings"
]
}
}
}Локальный перевод#
Укажите API key и запустите CLI:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runCLI считывает ваш String Catalog, находит непереведённые записи с помощью lockfile, переводит изменения через ваш движок локализации и записывает результат обратно в файл .xcstrings. Откройте файл в Xcode, чтобы увидеть переводы для каждой настроенной локали.
Чтобы во время разработки переводить только в конкретную локаль:
npx lingo.dev@latest run --target-locale esЗаметки для переводчиков#
String Catalogs поддерживают поле комментария для каждой записи, и CLI включает его в запросы на перевод. Эти комментарии дают контекст движку локализации: помогают снять неоднозначность терминов, задать нужный тон или объяснить, где строка отображается в интерфейсе.
В Xcode выберите строку в редакторе String Catalog и добавьте комментарий в панели инспектора. Комментарий сохраняется в JSON .xcstrings:
{
"sourceLanguage": "en",
"strings": {
"Set": {
"comment": "Refers to a collection of items, not the verb",
"localizations": { }
}
}
}CLI отправляет этот комментарий вместе со строкой, помогая модели выбрать правильную интерпретацию. Без контекста "Set" во многих языках может переводиться как глагол — комментарий снимает эту неоднозначность. Больше примеров — в разделе Translator Notes.
Множественное число#
String Catalogs изначально поддерживают формы множественного числа на основе CLDR plural rules. Когда вы задаёте вариант множественного числа в Xcode, String Catalog сохраняет правила для каждой категории множественного числа (zero, one, two, few, many, other), которая нужна целевому языку.
CLI сохраняет эту структуру при переводе и создаёт правильные категории множественного числа для каждой целевой локали. В английском их две (one и other), в арабском — шесть, в польском — четыре, а в японском — одна. Движок локализации учитывает эти различия автоматически.
Автоматизация через GitHub Actions#
Добавьте файл Процесса в .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 key как 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