运维 / CI·CD 2026年5月7日

2026-05-07 iOS 字符串目录(xcstrings) 本地化 CI 门禁租用 Apple Silicon云 Mac(香港 / 东京 / 首尔 / 新加坡 / 美国

MacXCode 技术团队 2026年5月7日 约 24 分钟阅读

字符串漂移是 App Store 提交过程中最安静的杀手:英文截图一切正常,但截断缺失的复数规则或陈旧的变体文案往往只在 QA 把系统语言切到你手中没有实体机时才浮现。Xcode 字符串目录.xcstrings)把这些问题集中到单一制品,然而在香港、东京、首尔、新加坡或美国租用 Mac mini M4 的团队仍需要一份CI 契约:在每个 PR 上校验目录、向译者导出 XLIFF、带冲突检测地导入,并对每个业务关键语言至少跑一遍自动化 UI。这份 2026-05-07 指南把发行说明里常被省略的运维细节串起来——当你把语言加到 12+ 个时如何保持 xcodebuild 速度,如何与 并行 xcodebuild 车道上限 对齐,以及如何避免本地化资源再生时 DerivedData 失控膨胀——参见 按作业隔离。若依赖解析与本地化共用同一主机,请同时阅读 SwiftPM 注册表缓存卫生,以免导出周里包解析与本地化任务争抢同一 NVMe 队列深度。

许多团队把本地化当作「发版前一周」的工序,结果是在冻结窗口里才发现键缺失或占位符不匹配。把字符串目录纳入 CI 的意义在于:让缺失翻译与编译错误一样大声,而不是等到 App Review 退回才补课。对于在香港或新加坡维护区域构建池的团队,这一点尤其关键——跨时区的译者反馈链路更长,任何能在合并阶段拦截的问题都会降低远程协作成本。

本文默认你在裸金属租用节点上以专用 CI 用户运行流水线;若你还混用自助 macOS Runner,请把相同的 DEVELOPER_DIR 与目录隔离策略复制过去,否则「本地能通过、云上失败」会继续折磨发布经理。下面的章节从格式差异讲到磁盘预算,便于你把 checklist 拆进现有的 GitHub Actions 或自建 Jenkins。

为何本地化总在流水线末端才出问题

功能测试默认跑英文;市场审核的是永远不会进仓库的 decks;译者收到的 ZIP 往往在返回文件时已经过时。字符串目录不会 magically 修复流程——它给你一个在 Git 里可 diff 的单一制品。CI 的任务是把缺失键、畸形复数或非法占位符放大到与编译失败同等音量。

锚点:当 PR 引入的键在任一必选语言缺少翻译时阻止合并——把它当成单元测试失败。

在租用云 Mac 上,你还可以把「本地化验证作业」与「二进制构建作业」拆到不同队列:前者 IO 模式偏随机小文件,后者偏大块链接产物;拆队列能减少互相导致的 tail latency。

xcstrings 与分散的 .strings / stringsdict

旧布局把翻译散落在几十个文件里,评审容易漏删。.xcstrings 打包元数据、状态与变体,自动化更简单,但合并冲突面更大。迁移期间请在基础设施仓库维护兼容矩阵列出哪些 target 仍消费旧文件。尽快移除双源——对同一键并行维护两种格式会让 git blame 彻底失真。

可在 GitHub/GitLab 强制执行的质量门禁

  • 语法校验 — 与正式发布相同的 DEVELOPER_DIR 编译目录。
  • 键覆盖 — 若一级列表中的语言对 NEW_KEY 缺少 translated 状态则失败。
  • 占位符一致 — 拒绝不匹配的 %@%d 或位置参数。
  • 截图 Lint(可选) — 若使用截图测试,至少每晚跑一次非英语语言。

无头构建机的导入 / 导出手册

假设仅有 SSH。用可重复命令代替 GUI 点击:

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

把导出放在与 IPA 导出与 ASC 上传 相同的 NVMe 卷上,以便权限与 umask 在签名与本地化自动化之间保持一致。始终以专用 CI 用户运行,而非 root,以保留 TCC 决策。

XLIFF 往返卫生

译者需要稳定 ID;工程师需要确定性导入。将 XLIFF 纳入版本控制或带校验和标签的对象存储。拒绝修改基础目录中不存在键的导入,拒绝剥离评审依赖的 note 字段的文件。当多个区域贡献变体(例如 zh-Hans vs zh-Hant)时,把业务规则写进 YAML,避免 CI 猜测。

合并提示:把 XLIFF 冲突当作代码冲突——未经占位符和解不要盲目「两者都要」;预防 UI 崩溃比事后靠 App Store 评论诊断便宜得多。

复数、设备与宽度变体

现代应用需要手表并发症、Dynamic Type 截图与快捷指令等场景的设备特定宽度。目录支持变体,但前提是 QA 矩阵列出它们。文档化哪些变体是必选 vs尽力而为,并反映到 CI 阈值——否则工程师会把一切标成 needs_review 来 unblock 合并。

并行语言矩阵而不烤糊主机

每增加一种语言, XCTest 在跑 UI 流程时都会放大资产工作量。用与 并行 xcodebuild 作业 相同的队列纪律限制每台主机并发 destination。优先分片:车道 A 跑东亚语言,车道 B 跑欧洲语言,车道 C 跑 RTL 冒烟。记录每个分片的墙钟时间;若 p95 环比上升超过 25%,在离译者最近的地理区域增加第二台租用节点。

磁盘、DerivedData 与本地化缓存

导入导出会触碰成千上万小文件——正是让 APFS 元数据繁忙的工作负载。完整导出前请在构建卷上保持至少 18% 空闲,并把旧版 XLIFF drop 归档到冷存储,而非让其堆积在 DerivedData 旁。遵循 TMPDIR + xcresult 隔离,避免本地化作业删除另一条流水线的产物。

可在内部公布的数值目标

  • 发布候选前一级语言100%覆盖。
  • 目录中超过 14 天的未解决 stale 键数量为 0
  • 典型 PR 的增量本地化校验 < 12 分钟

冻结字符串前的九步清单

  1. 冻结产品文案;用提交 SHA 通知本地化供应商。
  2. 从发布分支导出基线 XLIFF。
  3. 用与 App Store 构建相同的 Xcode 运行目录校验。
  4. 把供应商文件导入临时分支;diff JSON 状态。
  5. 三种语言跑 UI 冒烟:LTR、RTL、CJK。
  6. 若应用内文案与 App Store 元数据同步,验证后者。
  7. 对本地化目录跑 du -sh 快照以跟踪 NVMe 回归。
  8. 打标签合并;为合规归档附加校验和清单。
  9. 安排发布后审计 needs_review 条目。

常见问题:App Store 审核、CI 用户与混合 Pods

问题 实操答案(2026-05-07)
CocoaPods + SPM 混合仓库需要额外步骤吗? 需要——在依赖解析之后跑本地化,以便生成 bundle 已就位;顺序参见 SwiftPM 与 CocoaPods
小错别字修复可以跳过 UI 测试吗? 仅当变更仅为空白且策略机器人可证明——否则至少跑一次非英语冒烟。

为何 1–2 TB 的 Mac mini M4 仍适合重本地化 CI

本地化流水线是元数据随机型的:成千上万小文件会与已在服务 xcodebuild test 的同一 NVMe 控制器争用。MacXCode 上的裸金属 Mac mini M4 节点保持延迟可预测,使你的门禁衡量译者吞吐而非邻居噪声。当容量规划要求再加构建机时,引用 香港 / 东京 / 首尔 / 新加坡 / 美国区域定价,并把入驻步骤留在 帮助文档,方便本地化供应商与发布工程师共用 SSH。

下一波本地化前先腾出 NVMe 余量

Mac mini M4 · 香港 / 东京 / 首尔 / 新加坡 / 美国 · SSH / 可选 VNC