Когда версия приближается к этапу заморозки, поставщик локализации обычно возвращает один или несколько файлов .xcloc или .xliff. Импортировать их двойным щелчком прямо в повседневную рабочую копию разработчика кажется быстрым решением, но вместе с переводами в проект могут попасть устаревшие ключи, неверно указанные целевые языки и повреждённые заполнители. Надёжнее создать на облачном Mac одноразовый каталог для проверки: экспортировать эталон из текущего коммита, выполнить предварительную проверку полученных файлов, а затем импортировать их, изучить различия и запустить сборку.
Зафиксируйте среду проверки
Узел проверки должен начинать работу с чистого коммита. Не используйте повторно рабочую копию, в которую уже импортировалась локализация, и не проводите проверку в каталоге с незакоммиченными изменениями. Для каждой поставки можно создать временную ветку или отдельный worktree:
git fetch origin
git worktree add ../localization-review origin/main
cd ../localization-review
git switch -c review/localization-batch
xcodebuild -version
git status --short
Запишите в журнал вывод xcodebuild -version, SHA коммита, целевую Scheme и идентификатор партии перевода. Если команда использует несколько версий Xcode, явно задайте DEVELOPER_DIR, чтобы интерактивный терминал и автоматические задания не запускали разные наборы инструментов.
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
xcode-select -p
git rev-parse HEAD
Критерий успешной проверки локализации — не просто возможность открыть файл, а получение объяснимого результата для одного и того же коммита, одной и той же версии инструментов Xcode и одного набора параметров экспорта.
При выполнении проверки на облачном Mac от GPUMini сначала просмотрите в консоли доступные конфигурации, а затем выберите подходящий узел. Для этой задачи обычно не требуется высокая степень параллелизма, однако при полной сборке крупного проекта после импорта необходимо учитывать доступный объём памяти и свободное место на диске.
Экспортируйте эталон из текущего проекта
Для .xcodeproj используйте параметр проекта. Если проект работает через Workspace, замените его на -workspace и укажите общую Scheme. В следующем примере экспортируются упрощённый китайский, японский и французский языки. Чтобы добавить другие языки, повторите параметр -exportLanguage:
mkdir -p Artifacts/Baseline
xcodebuild \
-project ExampleApp.xcodeproj \
-scheme ExampleApp \
-exportLocalizations \
-localizationPath Artifacts/Baseline \
-exportLanguage zh-Hans \
-exportLanguage ja \
-exportLanguage fr
После завершения экспорта сначала сохраните список файлов, не перезаписывая сразу полученные переводы:
find Artifacts/Baseline -type f -print0 \
| sort -z \
| xargs -0 shasum -a 256 > Artifacts/baseline.sha256
Эталон отвечает на три вопроса: какие единицы текущего проекта доступны для перевода, как выглядит их содержимое на исходном языке и какие целевые языки распознаёт Xcode. Если в полученных файлах есть ключи, отсутствующие в эталоне, перевод, скорее всего, был подготовлен на основе старого коммита. Если же в эталоне появилось много новых непереведённых единиц, в поставку могли не войти недавно добавленные функции.
Проверьте структуру XLIFF и заполнители до импорта
XLIFF представляет собой XML. Сначала проверьте корректность формата системными средствами, а затем извлеките языковые атрибуты и количество единиц перевода. Не изменяйте XML с помощью регулярных выражений. На этапе предварительной проверки файлы можно читать, но исправления следует вносить в средстве локализации или с помощью прошедшего ревью сценария.
find Incoming -name "*.xliff" -print0 |
while IFS= read -r -d '' file; do
echo "Checking $file"
xmllint --noout "$file"
xmllint --xpath \
'string(/*[local-name()="xliff"]/*[local-name()="file"][1]/@target-language)' \
"$file"
echo
done
Ошибки в заполнителях — важнейшая причина блокировать импорт. %@, %d, позиционные параметры и переменные, созданные String Catalog, должны сохранять смысловое соответствие между исходным и целевым текстом. Простого подсчёта знаков процента недостаточно: %%, ширина поля и позиционные параметры имеют разное значение. Рекомендуется с помощью XML-парсера отдельно прочитать source и target каждого trans-unit, нормализовать заполнители и сравнить полученные мультимножества.
| Проверка | Условие блокировки | Действие |
|---|---|---|
| Структура XML | xmllint возвращает ненулевой код |
Вернуть полученный файл |
| Целевой язык | Не соответствует партии перевода | Исправить сопоставление языков и повторить экспорт |
| Единицы перевода | Обнаружены неизвестные ID | Проверить коммит эталона |
| Заполнители | Не совпадают типы или количество | Исправить перевод и повторить проверку |
| Пустой перевод | Целевой текст важного элемента интерфейса пуст | Уточнить, разрешён ли откат к исходному тексту |
В строках форматирования, видимых пользователю, также выборочно проверяйте переносы строк, управляющие последовательности и ветви множественного числа. Порядок заполнителей может меняться в зависимости от языка, но при использовании позиционных параметров их индексы должны оставаться допустимыми.
Импортируйте в изолированном каталоге и проверьте различия
После успешной предварительной проверки импортируйте пакеты .xcloc по одному. Сразу после каждого импорта фиксируйте состояние репозитория, чтобы можно было определить, какой именно файл привёл к отклонениям:
mkdir -p Artifacts/Logs
for package in Incoming/*.xcloc; do
name="$(basename "$package" .xcloc)"
xcodebuild \
-project ExampleApp.xcodeproj \
-importLocalizations \
-localizationPath "$package" \
2>&1 | tee "Artifacts/Logs/import-${name}.log"
test "${PIPESTATUS[0]}" -eq 0 || exit 1
git status --short
done
Успешный импорт ещё не означает завершения проверки. Сначала оцените масштаб изменений с помощью git diff --stat, а затем изучите различия по каждому файлу. Ожидаемые изменения должны быть сосредоточены в String Catalog, строковых ресурсах или каталогах соответствующих языков. Если изменились Scheme, параметры сборки, настройки подписи или посторонние файлы проекта, остановите процесс и выясните причину.
git diff --stat
git diff --check
git diff -- '*.xcstrings' '*.strings' '*.stringsdict' 'project.pbxproj'
Команда git diff --check позволяет обнаружить некоторые замыкающие пробелы и следы конфликтов, но не оценивает смысл перевода. Рекомендуется сформировать сводку добавленных, удалённых и изменённых единиц перевода и сохранить её как артефакт конвейера вместе с журналами импорта.
Завершите цикл сборкой и повторным экспортом
В завершение выполните чистую сборку целевой Scheme. Если проект содержит несколько целевых приложений или расширений, проверка должна охватывать реальный путь выпуска, а не только минимальную библиотечную цель.
set -o pipefail
xcodebuild \
-project ExampleApp.xcodeproj \
-scheme ExampleApp \
-configuration Release \
-destination 'generic/platform=iOS Simulator' \
clean build |
tee Artifacts/Logs/localization-build.log
После успешной сборки снова экспортируйте XLIFF из проекта с импортированными переводами и сравните результат с эталоном. Повторный экспорт помогает обнаружить переводы, которые фактически не попали в проект, ошибки сопоставления языковых кодов и единицы, оставшиеся непереведёнными после импорта. При сравнении игнорируйте изменения, связанные только с сортировкой или созданными инструментами метаданными. Анализируйте исходный и целевой текст, статус и примечания каждой единицы перевода.
Поддерживаемый конвейер проверки должен сохранять четыре категории подтверждающих данных: сведения о наборе инструментов и коммите, отчёты предварительной проверки, сводку различий после импорта и журналы сборки. При сбое не очищайте рабочий каталог автоматически — сначала сохраните его состояние для анализа. После успешной проверки удалите временный worktree, чтобы следующая поставка не унаследовала прежнее состояние.
Итоговые условия допуска можно сформулировать так: XML корректно разбирается, целевой язык указан верно, наборы заполнителей совпадают, неизвестные единицы перевода отсутствуют, область изменений соответствует ожиданиям, а целевая Scheme успешно собирается. В таком процессе облачный Mac становится воспроизводимым узлом проверки локализации, а не ещё одной средой импорта, состояние которой приходится поддерживать по памяти вручную.
Часто задаваемые вопросы
Зачем перед проверкой перевода экспортировать свежий XLIFF?
Свежий экспорт фиксирует набор строк, исходный текст и языки текущей версии проекта, поэтому устаревшие и неизвестные единицы перевода сразу заметны.
Достаточно ли успешного импорта XLIFF для выпуска?
Нет. Нужно отдельно проверить плейсхолдеры, формы множественного числа, изменения файлов проекта и выполнить чистую сборку нужной схемы.
Можно ли импортировать перевод прямо в основную рабочую копию?
Лучше использовать временную ветку или отдельное рабочее дерево, сохранить журнал импорта и переносить только проверенные изменения ресурсов.
Как выбрать облачный Mac для разработки и сборки
Сравните две конфигурации M4, четыре срока аренды и четыре доступных узла, а затем выполните развертывание под задачи проекта.