DevOps / CI·CD 7 мая 2026

2026-05-07 iOS String Catalog (xcstrings)гейты локализации CI на арендованном облачном Mac Apple Silicon (HK / JP / KR / SG / US)

MacXCode Engineering Team 7 мая 2026 ~24 мин чтения

Дрейф строк тихо убивает отправки в App Store: скриншоты на английском выглядят хорошо, но обрезание, пропущенные правила множественного числа или устаревшие варианты проявляются только когда QA меняет язык системы на устройстве, которого нет в руках. Xcode String Catalog (.xcstrings) собирает всё вместе, но аренда Mac mini M4 в HK/JP/KR/SG/US всё равно требует контракта CI: проверять каталоги на каждом PR, экспортировать XLIFF переводчикам, импортировать с обнаружением конфликтов и прогонять хотя бы один автоматический UI-проход по критичным локалям. Гайд 2026-05-07 соединяет операционные детали, которые редко попадают в релиз-ноты—как держать xcodebuild быстрым при 12+ локалях, как совместить с лимитами параллельных задач и не раздувать DerivedData при регенерации локализаций—см. изоляцию TMPDIR/xcresult. Если разрешение зависимостей делит хост, добавьте гигиену кеша SwiftPM, чтобы экспорт и resolve пакетов не конкурировали за очередь NVMe в релизную неделю.

Почему локализация ломается последней

Функциональные тесты проходят на английском; маркетинг согласует материалы вне репозитория; ZIP для переводчиков устаревает к возврату. Каталоги не чинят процесс—они дают единый артефакт для diff в Git. Задача CI—сделать отсутствующие ключи, некорректные множественные числа или незаконные плейсхолдеры такими же громкими, как ошибка компилятора.

Якорь: блокируйте merge, если в любой обязательной локали нет перевода для ключей из PR—как упавший unit test.

xcstrings против разрозненных .strings / stringsdict

Наследие разбрасывает переводы по файлам; ревьюеры пропускают удаления. .xcstrings объединяет метаданные, состояния и варианты—автоматизация проще, конфликты merge чаще. Во время миграции держите матрицу совместимости и быстро уберите двойные источники.

Контроль качества в GitHub/GitLab

  • Синтаксическая проверка — тот же DEVELOPER_DIR, что и у релиза.
  • Покрытие ключей — провал, если NEW_KEY без translated в tier-1 локалях.
  • Согласованность плейсхолдеров — отклонять несовпадения %@, %d, позиций.
  • Screenshot lint — опционально; со скриншот-тестами гоняйте неанглийскую локаль ночью.

Импорт/экспорт для headless-билдеров

Только SSH: повторяемые команды вместо кликов GUI.

xcodebuild -exportLocalizations -project YourApp.xcodeproj -localizationPath ./exports xcodebuild -importLocalizations -project YourApp.xcodeproj -localizationPath ./imports

Экспорт на том же NVMe, что и IPA и загрузки ASC, чтобы права и umask совпадали. Только выделенный CI-пользователь, не root.

Гигиена кругового XLIFF

Переводчикам нужны стабильные ID; инженерам—детерминированный импорт. Храните XLIFF под контролем версий или в объектном хранилище с checksum-тегами. Отклоняйте импорты, меняющие ключи вне базового каталога или снимающие поля note. Правила для регионов (zh-Hans vs zh-Hant) кодируйте в YAML.

Совет по merge: конфликты XLIFF как код—не «бери оба» без сверки плейсхолдеров.

Множественное число, устройства и варианты ширины

Современным приложениям нужны ширины под осложнения Apple Watch, Dynamic Type и Shortcuts. Варианты работают только если QA-матрица их перечисляет. Зафиксируйте обязательное и best effort и отразите в порогах CI.

Параллельная матрица локалей без перегрева хоста

Каждая новая локаль умножает работу с ассетами в XCTest. Ограничивайте одновременные назначения как в параллельных xcodebuild. Шардинг: полоса A — Восточная Азия, B — Европа, C — RTL-smoke. Если p95 растёт более чем на 25 % к кварталу—добавьте второй узел ближе к переводчикам.

Диск, DerivedData и кеши локализации

Импорт/экспорт трогают тысячи мелких файлов—идеальная нагрузка для APFS-метаданных. Перед полным экспортом держите минимум 18 % свободного места; старые XLIFF уводите в холодное хранилище. Следуйте изоляции TMPDIR и xcresult, чтобы не удалять артефакты других пайплайнов.

Числовые цели для внутренней публикации

  • 100 % покрытие tier-1 до тега RC.
  • 0 нерешённых ключей stale старше 14 дней.
  • < 12 минут для инкрементальной проверки локализации типичных PR.

Девять шагов перед заморозкой строк

  1. Заморозить продуктовый текст; уведомить вендоров SHA коммита.
  2. Экспорт базового XLIFF из релизной ветки.
  3. Проверить каталог тем же Xcode, что и App Store.
  4. Импортировать файлы вендоров во временную ветку; diff состояний JSON.
  5. UI-smoke в трёх локалях: LTR, RTL, CJK.
  6. Проверить метаданные App Store, если синхронизированы.
  7. Снимок du -sh по каталогам локализации.
  8. Тегнуть merge; приложить checksum-манифест для комплаенса.
  9. Запланировать аудит пост-релиза для needs_review.

FAQ: ревью App Store, CI-пользователь, гибрид Pods

ВопросПрактический ответ (2026-05-07)
Гибрид CocoaPods + SPM?Да—локализуйте после разрешения зависимостей, чтобы сгенерированные бандлы были на месте; см. SwiftPM и CocoaPods.
Пропустить UI-тесты из-за опечатки?Только если изменение только пробелов и политика-бот доказывает—иначе хотя бы один неанглийский smoke.

Почему Mac mini M4 1–2 ТБ подходит для CI с тяжёлой локализацией

Пайплайны локализации случайны по метаданным: тысячи мелких файлов бьют по тому же NVMe, что уже обслуживает xcodebuild test. Узлы Mac mini M4 на MacXCode сохраняют предсказуемую задержку. Ёмкость: региональные цены; онбординг: справка.

Запас NVMe перед волной локализации

Mac mini M4 · HK / JP / KR / SG / US · SSH / optional VNC