Skip to main content

翻譯檔案同步:保持各語系的 i18n 鍵同步

每當開發人員向源語系新增一個鍵,其他 15 個語系檔案就會失去同步。缺失鍵會向使用者顯示原始路徑,過時鍵則浪費譯者時間並增大套件。自動同步可讓所有內容保持一致。

1

同步問題

翻譯檔案不斷產生偏差。一位開發人員向 en.json 新增 'settings.notifications.title',卻忘記新增到其他 15 個語系檔案。另一位開發人員從程式碼中移除 'onboarding.welcome',卻將它留在所有語系檔案中。第三位開發人員在英語檔案中將 'user.name' 重命名為 'user.displayName',但未更新其他語系。幾個月後,語系檔案開始分化:不同檔案間出現缺失、過時或不匹配的鍵。

The drift problem
// The problem: translation files drift out of sync

// Developer adds a new feature with new keys:
// en.json (source of truth)
{
  "nav.home": "Home",
  "nav.about": "About",
  "nav.pricing": "Pricing",     // NEW
  "nav.changelog": "Changelog"  // NEW
}

// de.json (out of sync - missing new keys)
{
  "nav.home": "Startseite",
  "nav.about": "Über uns"
  // nav.pricing - MISSING
  // nav.changelog - MISSING
}

// de.json also has stale keys from deleted features:
{
  "nav.home": "Startseite",
  "nav.about": "Über uns",
  "nav.legacy_page": "Alte Seite"  // STALE - removed from en.json
}
缺失鍵比缺失翻譯更糟。缺失翻譯可以回退到來源語言;缺失鍵則會導致執行階段錯誤、向使用者顯示原始鍵路徑或呈現空字串。同步必須強制執行,不能寄希望於人工自覺。
2

偵測缺失鍵

缺失鍵是源語系中存在、但目標語系中不存在的鍵。這是最常見、破壞性也最大的同步問題:使用者會看到 'settings.notifications.title' 等原始鍵路徑,而不是翻譯文字。i18n-validate 透過比較每個語系與來源檔案的鍵結構來偵測缺失鍵。

Terminal
# Detect missing and stale keys
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json'

# Output:
# locales/de.json:
#   Missing keys (2):
#     - nav.pricing
#     - nav.changelog
#   Stale keys (1):
#     - nav.legacy_page
#   Coverage: 66.7% (2/3 keys)
#
# locales/ja.json:
#   Missing keys (5):
#     - nav.pricing
#     - nav.changelog
#     - settings.theme
#     - settings.language
#     - settings.notifications
#   Coverage: 50.0% (5/10 keys)
使用 --check missing-keys 標誌執行 i18n-validate,可專門檢查同步問題。使用 --severity error 讓缺失鍵導致 CI 失敗,確保在合併前修復。
3

偵測過時鍵

過時鍵存在於翻譯檔案中,但程式碼已不再引用。它們會浪費譯者時間(翻譯無人看到的字串)、增大套件,並造成維護混亂。偵測過時鍵需要交叉檢查語系檔案和程式碼引用。

Terminal
# Step 1: Check which files are out of sync
npx i18n-validate sync --source locales/en.json --targets 'locales/*.json'

# Step 2: Auto-fill missing keys with source values (as placeholders)
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --fill-missing \
  --fill-value "[NEEDS TRANSLATION] {{source}}"

# Step 3: Remove stale keys no longer in source
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --remove-stale

# Step 4: Sort keys to match source order (cleaner diffs)
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --sort-keys

# All at once:
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --fill-missing \
  --remove-stale \
  --sort-keys
4

自動同步

最有效的同步策略結合三層保障:1)每次提交時驗證同步的預提交鈎子;2)阻止存在同步問題的合併的 CI 管線檢查;3)發現熱修復和手動編輯所累積偏差的定期全面審核。

.husky/pre-commit
# .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Check if source locale file changed
SOURCE_CHANGED=$(git diff --cached --name-only | grep -c 'locales/en.json')

if [ "$SOURCE_CHANGED" -gt 0 ]; then
  echo "Source locale changed - checking sync..."

  npx i18n-validate sync \
    --source locales/en.json \
    --targets 'locales/*.json' \
    --fail-on-missing \
    --min-coverage 90

  if [ $? -ne 0 ]; then
    echo ""
    echo "Translation files are out of sync!"
    echo "Run: npx i18n-validate sync --fill-missing"
    exit 1
  fi
fi
.github/workflows/i18n-sync.yml
# .github/workflows/i18n-sync.yml
name: Translation Sync Check

on:
  pull_request:
    paths:
      - 'locales/**'

jobs:
  sync-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check translation sync
        run: npx i18n-validate sync \
          --source locales/en.json \
          --targets 'locales/*.json' \
          --fail-on-missing \
          --min-coverage 95

      - name: Comment on PR if out of sync
        if: failure()
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: 'Translation files are out of sync. Please run npx i18n-validate sync --fill-missing and commit.'
            })
5

翻譯覆蓋率報告

翻譯覆蓋率是每個目標語系中已翻譯源鍵的百分比。i18n-validate 會產生顯示各語系百分比的覆蓋率報告,突出顯示進度落後的語系。在 CI 中使用覆蓋率閾值,當覆蓋率降至可接受水平以下時阻止合併。

Namespace-based sync
// Split large translation files by feature/namespace
// locales/
// ├── en/
// │   ├── common.json      (nav, footer, errors)
// │   ├── auth.json         (login, register, reset)
// │   ├── dashboard.json    (dashboard-specific)
// │   └── settings.json     (settings page)
// ├── de/
// │   ├── common.json
// │   ├── auth.json
// │   ├── dashboard.json
// │   └── settings.json

// Sync with namespace support:
npx i18n-validate sync \
  --source 'locales/en/*.json' \
  --targets 'locales/*/%.json' \
  --namespace-pattern '{locale}/{namespace}.json'

// Benefits:
// - Smaller files, easier to review
// - Feature teams own their translations
// - Lazy-load only needed namespaces
// - Parallel translation workflows
為不同語系設定不同覆蓋率閾值。主要語系(de、fr、ja)可能要求 100% 覆蓋,新新增的語系(th、vi)則可從 80% 開始,並隨時間逐步提高。

立即試用 i18n Agent

將翻譯檔案拖放到此處

JSON, YAML, PO, XML, CSV, Markdown, Properties

或點擊選擇檔案

目標語言

無需註冊即時估價

翻譯檔案同步常見問題