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

同期の自動化

最も効果的な同期方法は、3 つの層を組み合わせます。1)コミットごとに同期を検証する pre-commit フック。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

またはクリックしてファイルを選択

翻訳先言語

登録不要すぐに見積もり

翻訳ファイル同期のよくある質問