String Catalog 多语言测试:2026 远程 Mac 怎么自动化?

这篇文章面向维护多语言 SwiftUI、UIKit 或混合项目的独立开发者与小团队。文章不会把翻译完成率当成唯一标准,而是从字符串提取、语言地区矩阵、运行时界面、截图证据和最终 Archive 资源五个层面,建立可以在远程 Mac 上持续执行的本地化验收流程。

适合:需要反复验证多语言界面、截图和发布产物的独立开发者,尤其适合没有常驻本地 Mac、但仍要持续运行 Xcode 测试的团队。
不适合:只根据翻译完成率判断发布质量的项目,因为绿色状态并不能证明运行时布局、地区格式和 Archive 资源都没有问题。

String Catalog 多语言测试不应被理解成“检查翻译是否全部完成”。可执行的方案是先固定字符串提取规则和语言地区矩阵,再用 Test Plan、UI 测试、截图与最终构建产物完成闭环;如果本地没有一台长期保留 Xcode、模拟器和测试结果的 Mac,把流程部署到远程 Mac 更适合持续回归。

这篇文章适合三类人:维护多语言 SwiftUI App、希望自动发现新增或失效字符串的单人开发者;正在从 stringsstringsdict、Storyboard 或 XIB 逐步迁移的 UIKit 存量项目;以及需要在多个市场、地区和界面尺寸上执行发布验收的小团队。

00先把 String Catalog 多语言测试拆成五类证据

String Catalog 管理的不只是翻译文本,还涉及语言、复数、设备变体和本地化资源。Apple 的文档明确说明,Xcode 可以在构建时提取可本地化字符串,并将其更新到 String Catalog;但这只说明“字符串进入了目录”,不代表它在运行时一定显示正确。可先参考 Apple 关于 String Catalog 的官方说明

为了避免把不同问题混成一个“本地化通过”,建议把验收拆成下面五层:

验证层 要回答的问题 主要证据
字符串提取 新增文本是否进入 String Catalog? .xcstrings 变更、构建日志
翻译状态 每个目标语言是否有可用翻译、复数和变体? String Catalog 状态、导出文件
运行时语言 App 在指定语言下是否真的替换文本? UI 测试、运行截图
地区与布局 日期、货币、数字、RTL 和长文本是否正常? Test Plan 配置、UI 断言
发布产物 Archive 是否包含预期语言和资源? .xcarchive、App Bundle 检查

其中最容易被忽略的是最后一层。编辑器中的绿色翻译状态属于项目编辑证据,不能代替安装后运行证据,更不能代替最终 Archive 验收。

用关键用户路径控制测试范围

不要一开始把所有页面都放进本地化 UI 测试。优先选择登录、订阅购买、核心创作、导出结果和错误提示等路径,因为这些页面通常同时包含按钮、动态文本、复数、金额或网络状态。

每条路径至少保留一个成功分支和一个失败分支。例如购买页面不能只检查“购买”按钮,还应覆盖价格加载失败、订阅不可用和恢复购买等状态。这样能够更早发现某个语言下的错误提示没有提取,或者长文本把主要操作按钮挤出屏幕。

01按项目类型建立不同的自动化起点

SwiftUI 项目:先查提取,再查变体

SwiftUI 视图中的部分用户可见字符串会通过 LocalizedStringKey 自动进入 String Catalog,但普通 Swift 代码中的人类可读文本仍然需要使用本地化 API。Apple 对这一区别有明确说明,可查看 SwiftUI 与其他代码的本地化字符串提取规则

建议先建立一个最小样本,至少包含:

  • 普通标题和按钮文本;
  • 一个带插值参数的字符串;
  • 一个单复数变化;
  • 一个长文本或多行说明;
  • 一个需要设备或界面变体的文本。

然后执行一次 Build,检查新增代码是否进入预期的 .xcstrings。如果某段文本没有出现,不要直接手工把它复制进目录,而应先确认代码是否使用了正确的本地化 API、是否进入了正确的 tableName,以及该代码是否属于实际构建的 Target。

仅看翻译百分比是不够的。某个语言达到完整状态,仍可能存在插值顺序错误、复数规则未覆盖或文本在小屏设备上截断的问题。

UIKit 与混合项目:把旧资源边界标出来

UIKit 或混合项目经常同时存在 String Catalog、.strings.stringsdict、Storyboard、XIB 和 Info.plist 中的可本地化文本。迁移时最危险的做法,是为了格式统一而一次性替换全部资源。

更稳妥的方式是按模块迁移:

  1. 先列出 App、扩展、Framework 和测试 Target 的本地化资源;
  2. 标记每个资源属于哪个 Target,以及最终是否进入 App Bundle;
  3. 选择一个功能模块迁移到 String Catalog;
  4. 构建并运行该模块的语言测试;
  5. 确认旧资源没有被重复加载,再处理下一个模块。

UIKit 项目要特别检查 Storyboard 和 XIB 中的控件文本,因为代码搜索不一定能发现这些资源。对于扩展和 Framework,也不能只检查主 App 的目录;最终证据应来自构建后的 Bundle 和实际运行界面,而不是项目导航器里的文件列表。

02用语言地区矩阵配置 Xcode 和 Test Plan

语言和地区不是同一个变量。语言决定字符串使用哪种本地化内容,地区则会影响日期、货币、数字、单位和部分格式化结果。Apple 的 本地化运行测试文档 说明,可以在 Scheme 或测试配置中选择 App Language 与 App Region。

建议建立一张小而真实的矩阵:

测试配置 适合覆盖的风险 必查内容
英语 + 美国 基准路径和默认资源 主流程、金额、日期
德语 + 德国 长文本和复合词 按钮宽度、标题换行
法语 + 法国 文本长度与格式化 数字、货币、说明文字
日语 + 日本 字符宽度与换行 导航、表单、辅助说明
阿拉伯语 + 代表地区 RTL 布局 对齐、图标方向、手势
中文 + 目标市场地区 主要用户市场 核心流程和发布截图

这张表不是要求每个项目都照抄,而是提醒开发者按真实市场选择组合。一个只支持英语、日语和简体中文的 App,没有必要为所有地区建立完整模拟器矩阵;但如果产品涉及订阅、发票或本地化价格,地区测试就不能只设置语言而忽略 Region。

在 Test Plan 中,每种关键组合应独立成为一个 Configuration。Apple 的 Test Plan 配置说明列出了 Application Language、Application Region、Localization Screenshots 和测试附件等选项。这样同一组 UI 测试可以在不同配置下复用,而不必复制多套测试代码。

用截图验证界面,但不要把截图当营销素材

如果要把本地化界面交给翻译人员或内部审核,Test Plan 可以为不同语言配置生成截图。Apple 的 本地化截图文档说明,开启 Localization Screenshots 后,Xcode 会保存对应语言的截图,并附带字符串与画面位置的关联信息。

截图应带有环境标识,例如语言、地区、构建号和测试配置名称。它们主要用于:

  • 复核长文本是否截断;
  • 对照翻译上下文;
  • 检查错误提示和空状态;
  • 记录发布前回归证据。

不要直接把自动化测试截图当作 App Store 营销素材。测试截图的尺寸、状态和内容通常服务于验收,不一定符合商店展示要求。

03把本地化任务拆成可重跑的远程 Mac 流程

String Catalog 能否在持续集成中自动检查,关键不在于“是否使用某个云端工具”,而在于任务是否被拆开,并且每一步都有可保存的证据。推荐按下面 7 步部署:

  1. 固定构建入口
    明确项目、Scheme、Configuration、测试账号和依赖安装方式,避免本地开发者使用不同 Scheme 导致结果不一致。

  2. 先执行字符串提取或导出
    使用 Xcode 菜单或 xcodebuild -exportLocalizations 导出指定语言。Apple 的 本地化导出文档给出了命令参数和 -includeScreenshots 选项。

  3. 保存目录差异
    将本次 .xcstrings、XLIFF 或导出目录与基线比较,重点关注新增 key、删除 key、未翻译内容和异常变体。

  4. 按 Test Plan 运行核心 UI 测试
    每个语言地区配置单独输出日志和测试结果,不要让一个语言失败后直接掩盖其他配置的状态。

  5. 生成并归档截图
    对关键页面开启本地化截图,同时保留测试附件和失败时的诊断信息。

  6. 构建 Archive 并检查 Bundle
    检查最终产物中是否包含预期语言目录、资源和扩展 Target 内容。不能只检查源码目录,因为资源归属错误可能在构建阶段才暴露。

  7. 验证重启、断线和重跑
    在远程 Mac 上模拟 SSH 断线、主机重启和任务重新执行,确认结果目录不会被覆盖成无法追溯的状态,并且失败任务可以从明确阶段重新开始。

⚠️ 经验提醒:依赖模拟器和截图的任务通常需要图形登录会话。SSH 能连接主机,不等于 UI 测试已经获得可用的图形环境;如果这一区别没有提前验证,脚本可能能完成编译,却在启动模拟器或抓取截图时失败。

如果项目还需要把翻译文件导回工程,可使用 xcodebuild -importLocalizations,或按 Apple 的 本地化导入说明检查导入警告。导入成功后仍要重新构建和测试,不能把“文件已导入”当成运行时通过。

04用条件分支决定测试规模和远程 Mac 方案

下面的条件列表可以帮助独立开发者确定自动化深度:

  • 若项目只有 1—2 种语言、页面少于核心路径范围,且每次发布都由同一人手动验收,则先采用本地 Test Plan 和少量 UI 测试;否则回退到完整的语言地区矩阵。
  • 若项目包含订阅、货币、复数或 RTL 布局,则至少保留代表性地区配置;否则不能只运行默认语言。
  • 若 SwiftUI 文本提取稳定,但 UIKit、Storyboard 或扩展资源仍未迁移,则按 Target 和模块逐步迁移;否则不要为了统一格式一次性重写全部资源。
  • 若 CI 只需要编译和单元测试,则普通命令行环境可能足够;若需要模拟器 UI 测试、截图和本地化验收,则选择具备图形会话的远程 Mac。
  • 若任务需要每天或每次提交都执行,并且本地 Mac 经常关机、磁盘不足或被其他工作占用,则适合把测试环境长期放在远程 Mac;若项目需要物理设备、专用外设或本地调试硬件,则应保留本地设备作为主环境。

如果需要评估远程主机是否适合持续测试,可以先参考 NUKCLOUD 的 Mac 远程使用入口,再根据测试频率和团队协作方式选择合适的 Mac 租赁方案。重点不是单纯追求一台“能打开 Xcode”的机器,而是确认它能否长期保留项目依赖、模拟器数据、签名环境和测试结果。

05发布前按负责人角色完成最后验收

独立开发者:确认新增字符串没有静默遗漏

单人项目最常见的问题不是完全没有本地化,而是某次提交新增了一个错误提示、弹窗标题或设置项,却没有进入预期的 String Catalog。提交检查可以先比较目录变化,再运行一条覆盖核心路径的多语言 UI 测试。

如果文本来自普通 Swift、UIKit 或 AppKit 代码,应优先检查本地化 API;如果来自 SwiftUI,则要确认它确实属于用户可见的本地化字符串,而不是被拼接、包装或放在不会被构建扫描的路径中。

存量项目维护者:确认迁移没有造成重复和回退

迁移旧版 stringsstringsdict 时,应保留可回退的提交边界。每次只迁移一个模块,完成构建、运行、截图和资源检查后再合并。

如果导入翻译后出现警告,应查看 Xcode 的差异和问题视图。不要直接覆盖旧文件,因为重复 key、错误 Table 名称和 Target 资源归属问题,往往需要回到具体模块处理。

出海团队:把缺陷分成三个等级

发布负责人可以按下面方式处理结果:

  • 阻断发布:关键语言缺失、购买或登录流程无法使用、Archive 缺少目标语言资源;
  • 修复后重跑:核心页面截断、地区格式错误、复数显示不正确、RTL 布局错位;
  • 记录后跟进:非核心页面的措辞优化、截图标注问题或不影响操作的轻微间距差异。

最终结论应明确写成“继续发布”“修复后重跑”或“回退本地化改动”,并保存对应的测试结果、截图、导出目录和 Archive 检查记录。这样下一次回归才有可比较的基线。

06常见问题:把搜索意图落到执行细节

如何确认 String Catalog 里没有漏掉新的文本?

先使用可本地化 API,并通过 Xcode Build 更新 String Catalog;SwiftUI 中的 LocalizedStringKey 通常会被自动发现,但普通 Swift、UIKit 或 AppKit 文本仍需使用对应的本地化初始化方式。随后用代表性页面运行 UI 测试,并检查生成的目录、运行界面和最终 Bundle,不能只看编辑器里的翻译百分比。

怎样为多个语言和地区复用同一批 iOS 测试?

在 Test Plan 中为实际支持的语言和地区建立配置,分别设置 Application Language 与 Application Region,再运行同一组核心 UI 测试。矩阵应优先覆盖真实市场、复数规则、货币日期格式、从右到左布局和关键设备尺寸,不建议机械组合所有语言与模拟器。

String Catalog 适合接入 CI 做自动校验吗?

可以,但持续集成不应只检查文件是否存在。可以将字符串导出、指定语言测试、UI 测试、截图收集和 Archive 资源检查拆成独立任务,并用 xcodebuild、Test Plan 与测试结果文件保存证据;需要图形界面的模拟器测试时,还要提前验证远程 Mac 的登录会话。

在远程 Mac 上执行多语言界面测试要准备什么?

先通过 SSH 将代码、依赖和签名环境准备好,再由远程 Mac 执行指定 Scheme 或 Test Plan。每种语言配置独立保存测试结果、截图和日志;如果任务依赖模拟器图形会话,就不能把它当作普通无界面脚本运行,还要测试断线、重启和重跑后的结果是否一致。

发布前怎样判断本地化验收是否真正完成?

至少检查新增字符串是否被提取、翻译状态是否完整、复数和插值是否正确、文本是否截断、日期货币数字是否符合地区、RTL 布局是否可用,以及最终 Archive 是否包含预期语言资源。缺失翻译、界面问题和基础设施失败应分级处理,分别决定继续发布、修复后重跑或回退改动。

07让 String Catalog 多语言测试成为发布门禁

真正稳定的自动化流程,不是把所有语言一次性塞进一个巨大任务,而是让每个阶段都能单独回答一个问题:字符串是否提取、翻译是否可用、界面是否可操作、截图是否可复核、产物是否完整。

如果当前方案依赖开发者本地 Mac 手动切换语言,常见缺点是环境无法长期在线、模拟器和 Xcode 资源会占用本地磁盘、测试结果容易散落在个人电脑中,而且多人协作时很难复现同一套语言地区配置。对于需要持续执行的多语言 UI 测试,把流程迁移到 NUKCLOUD 的远程 Mac,可以让 Xcode、Test Plan、模拟器和结果归档保留在一个可重复使用的环境中;但如果项目长期重度依赖实体 iPhone、专用外设或本地硬件调试,仍应保留本地 Mac 与真机作为主要验收设备。

当语言地区矩阵已经确定,下一步应检查远程主机是否能稳定保留构建依赖、签名环境和测试证据,再结合任务频率选择按需或持续使用的 NUKCLOUD Mac 方案