2026-05-07 iOS 字符串目錄(xcstrings) 本地化 CI 門禁與租用 Apple Silicon雲 Mac(香港 / 東京 / 首爾 / 新加坡 / 美國)
字符串漂移是 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 的任務是把缺失鍵、畸形複數或非法佔位符放大到與編譯失敗同等音量。
在租用雲 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 猜測。
複數、設備與寬度變體
現代應用需要手錶併發症、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 分鐘。
凍結字符串前的九步清單
- 凍結產品文案;用提交 SHA 通知本地化供應商。
- 從發布分支導出基線 XLIFF。
- 用與 App Store 構建相同的 Xcode 運行目錄校驗。
- 把供應商文件導入臨時分支;diff JSON 狀態。
- 在三種語言跑 UI 冒煙:LTR、RTL、CJK。
- 若應用內文案與 App Store 元數據同步,驗證後者。
- 對本地化目錄跑
du -sh快照以跟蹤 NVMe 回歸。 - 打標籤合併;為合規歸檔附加校驗和清單。
- 安排發布後審計
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。