雲端 Mac 用 XLIFF 驗收 Xcode 在地化匯入

雲端 Mac 用 XLIFF 驗收 Xcode 在地化匯入

當版本即將定版時,翻譯供應商通常會交回數個 .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 工具鏈與相同匯出參數能產生可解釋的結果。

在 GPUMini 的雲端 Mac 上執行時,先於控制台確認目前可選的配置,再選擇用於驗收的節點。這項工作通常不依賴高度平行處理,但若匯入後需要完整編譯大型專案,仍應將記憶體與磁碟剩餘空間納入規劃。

從目前專案匯出基準

對於 .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 本質上是 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 解析器,分別讀取每個 trans-unitsourcetarget,將預留位置正規化後再比較多重集合。

檢查項目 阻斷條件 處理方式
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 匯入成功是否代表可以發佈?

不是。匯入成功只代表 Xcode 能處理檔案,仍須核對佔位符、複數規則、資源差異,並執行目標 Scheme 的乾淨建置。

可以直接在主要工作目錄匯入譯文嗎?

不建議。應在暫存分支或獨立 worktree 執行,保留匯入記錄與差異摘要,再合併已確認的資源變更。

獨享實體節點

為開發與建置任務選擇一台雲端 Mac

比較兩種 M4 設定、四種租用週期與四個在售節點,再依任務需求完成部署。

選擇設定並下單