チュートリアル//9 読了時間

GitHub Translation Sync:ローカライゼーションワークフローを自動化する

Eray Gündoğmuş
共有

ブランチに散在する翻訳ファイル、JSONキーの手動コピー&ペースト、「フランス語の翻訳を誰かプッシュした?」というSlackメッセージ——これに心当たりがあるなら、ローカライゼーションワークフローに自動化が必要です。

GitHub Translation Syncは、翻訳ファイルをコードベースと同期させる手作業を排除します。リポジトリの新しい翻訳キーを監視し、翻訳のために送信(AIまたは人間)し、完成した翻訳をPull Requestとして返却します——すべてGitワークフローを離れることなく行われます。

このガイドでは、GitHub Translation Syncをゼロからセットアップし、PRベースのワークフローを設定し、CI/CDと統合し、チームコラボレーションに最適化する方法を順を追って説明します。


GitHub Translation Syncとは?

GitHub Translation Syncは、GitリポジトリとTranslation Management Platform(翻訳管理プラットフォーム)間の双方向同期メカニズムです。翻訳ファイルを手動でプッシュ・プルする代わりに、Syncが以下を行います:

  1. 新規または変更されたキーを検出します(コードをプッシュしたとき)
  2. 翻訳プラットフォームに送信します(翻訳のため)
  3. 完成した翻訳をPull Requestとして返却します
  4. 翻訳ファイルをブランチ間で同期し続けます

なぜPRベースの翻訳デリバリーなのか?

従来のローカライゼーションワークフローではCLIのプッシュ/プルコマンドを使用します。PRベースのアプローチが優れている理由:

CLI Push/PullPRベースのSync
手動プロセスで忘れやすい自動的に常に同期
翻訳のレビュー工程なしPRレビューで問題を検出
メインブランチへの直接コミットブランチ保護が尊重される
監査証跡なし翻訳の完全なGit履歴
一人の責任PR通知でチームに公開
マージコンフリクトが多発SyncがRebaseを自動処理

前提条件

GitHub Translation Syncをセットアップする前に、以下が必要です:

  • 翻訳ファイルを含むGitHubリポジトリ(JSON、YAML、PO、ARB形式)
  • Better i18nプロジェクト(better-i18n.comでサインアップ)
  • リポジトリの管理者アクセス(GitHub Appのインストール用)
  • 一貫したディレクトリ構造の翻訳ファイル

サポートされているディレクトリ構造

# パターン1:ロケールディレクトリ
locales/
  en/
    common.json
    dashboard.json
  es/
    common.json
    dashboard.json

# パターン2:ロケールファイルサフィックス
locales/
  common.en.json
  common.es.json
  dashboard.en.json
  dashboard.es.json

# パターン3:単一ディレクトリにロケールプレフィックス
i18n/
  en.json
  es.json
  fr.json

# パターン4:フレームワーク固有(例:Flutter ARB)
lib/l10n/
  app_en.arb
  app_es.arb

ステップ1:GitHub Appをインストールする

GitHub SyncはGitHub Appを通じて動作し、リポジトリの翻訳ファイルへの読み書きアクセスを持ちます。

  1. Better i18nプロジェクトのダッシュボードに移動します
  2. SettingsIntegrations に進みます
  3. Connect GitHub をクリックします
  4. 同期したいリポジトリを選択します
  5. 要求された権限を承認します

権限の説明

権限必要な理由
Read: Code新規/変更された翻訳キーを検出するため
Read/Write: Pull Requests完成した翻訳でPRを作成するため
Read: Metadataリポジトリ情報にアクセスするため
WebhooksSyncトリガーのプッシュイベントを受信するため

GitHub Appは翻訳関連のファイルにのみアクセスします。ソースコード、環境変数、シークレットは読み取りません。


ステップ2:Syncを設定する

リポジトリのルートに設定ファイルを作成します:

# better-i18n.yml
sync:
  # ソース言語 — このロケールのファイルからキーが抽出されます
  sourceLanguage: en

  # ターゲット言語 — これらの翻訳が生成されます
  targetLanguages:
    - es
    - fr
    - de
    - ja
    - ko
    - "zh-CN"

  # 翻訳ファイルのパスパターン
  # {locale}と{namespace}プレースホルダーを使用したGlobパターンをサポート
  paths:
    - "locales/{locale}/{namespace}.json"

  # 代替:ロケールごとに1ファイル
  # paths:
  #   - "locales/{locale}.json"

  # 変更を監視するブランチ(デフォルト:main)
  baseBranch: main

  # 翻訳の配信方法
  delivery:
    # "pr"はPull Requestを作成、"commit"は直接プッシュ(非推奨)
    method: pr

    # PRブランチの命名パターン
    branchPattern: "i18n/sync-{timestamp}"

    # すべてのチェックが通過したときにPRを自動マージ(ブランチ保護が必要)
    autoMerge: false

    # 翻訳PRに割り当てるレビュアー
    reviewers:
      - "@i18n-team"

    # 翻訳PRに追加するラベル
    labels:
      - "i18n"
      - "automated"

  # AI翻訳設定
  ai:
    # 新しいキーをAIで自動翻訳
    autoTranslate: true

    # PR作成前に人間の承認を要求
    requireApproval: false

    # AI翻訳者へのカスタム指示
    instructions: |
      - Use formal register for German (Sie, not du)
      - Keep brand name "Better i18n" untranslated in all languages
      - Use Oxford comma in English translations

設定オプションリファレンス

オプションデフォルト説明
sourceLanguagestring"en"ソースロケールコード
targetLanguagesstring[][]ターゲットロケールコード
pathsstring[]自動検出翻訳ファイルのGlobパターン
baseBranchstring"main"監視するブランチ
delivery.methodstring"pr"配信方法:prまたはcommit
delivery.autoMergebooleanfalseチェック通過時に自動マージ
delivery.reviewersstring[][]PRレビュアー(ユーザーまたはチーム)
delivery.labelsstring[]["i18n"]PRラベル
ai.autoTranslatebooleantrue新しいキーをAIで翻訳
ai.requireApprovalbooleanfalsePR前に承認を要求
ai.instructionsstring""カスタムAI指示

ステップ3:Syncワークフローを理解する

設定後、典型的な開発サイクルで起こることは以下のとおりです:

新しいキーの追加

開発者                   GitHub                Better i18n              GitHub
    |                        |                       |                      |
    |-- コミットプッシュ ---->|                       |                      |
    |   (en/common.jsonに    |-- Webhook ----------->|                      |
    |    新しいキーを追加)    |                       |                      |
    |                        |                       |-- AIが翻訳 -------->|
    |                        |                       |   全ターゲット言語   |
    |                        |                       |   向けに新キーを翻訳 |
    |                        |                       |                      |
    |                        |<---------- 翻訳付きPRを作成 ---------------|
    |                        |                       |                      |
    |<-- PR通知 ------------|                       |                      |
    |                        |                       |                      |
    |-- レビュー&マージ ---->|                       |                      |

既存キーの更新

既存キーのソーステキストを変更した場合:

  1. SyncがWebhook経由で変更を検出します
  2. 既存の翻訳が「要レビュー」としてマークされます
  3. AIが更新された翻訳を生成します
  4. 更新された翻訳でPRが作成されます
  5. レビュアーの比較のため、以前の翻訳がPRの説明に保存されます

キーの削除

ソースロケールからキーを削除した場合:

  1. Syncが削除を検出します
  2. 対応するキーがすべてのターゲットロケールファイルから削除されます
  3. 削除内容を含むPRが作成されます
  4. 監査目的で削除されたすべてのキーがPRの説明に一覧表示されます

ステップ4:CI/CD統合

翻訳がマージされる前に問題を検出するために、CI/CDパイプラインに翻訳バリデーションを追加します。

GitHub Actionsワークフロー

# .github/workflows/i18n-validate.yml
name: Validate Translations

on:
  pull_request:
    paths:
      - "locales/**"
    types: [opened, synchronize]

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

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Install dependencies
        run: bun install

      - name: Validate translation coverage
        run: |
          bunx @better-i18n/cli coverage \
            --min 95 \
            --format github-actions

      - name: Validate ICU syntax
        run: |
          bunx @better-i18n/cli validate \
            --format github-actions

      - name: Check for unused keys
        run: |
          bunx @better-i18n/cli lint \
            --unused \
            --format github-actions

      - name: Comment coverage report on PR
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const { execSync } = require('child_process');
            const report = execSync('bunx @better-i18n/cli coverage --format markdown').toString();
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## Translation Coverage Report\n\n${report}`
            });

必須ステータスチェック

翻訳バリデーションを必須にするためブランチ保護を設定します:

  1. SettingsBranchesBranch protection rules に移動します
  2. Require status checks to pass before merging を有効にします
  3. 以下のチェックを追加します:
    • Validate translation coverage
    • Validate ICU syntax

これにより、翻訳が壊れているまたはカバレッジが不十分なPRはマージできなくなります。


ステップ5:翻訳のためのブランチ戦略

デフォルト:単一翻訳ブランチ

デフォルトでは、各Syncが完成した翻訳を含む新しいブランチを作成します:

main ------------------------------------------------
  \                                 |
   \-- i18n/sync-20260315 ---------/
       (新しいキーの翻訳)

これはほとんどのチームに適しています。各Syncが独立しており、マージ前に翻訳を確認できます。

高度な設定:フィーチャーブランチSync

フィーチャーブランチを使用するチームのために、フィーチャーブランチをターゲットにするようSyncを設定します:

# better-i18n.yml
sync:
  baseBranch: main
  featureBranchSync:
    enabled: true
    # これらのブランチをターゲットにするPRの翻訳を同期
    targetBranches:
      - "main"
      - "develop"
    # フィーチャーPRと同じブランチをターゲットにする翻訳PRを作成
    followBranch: true

フィーチャーブランチSyncを使用すると:

main ------------------------------------------------
  \
   \-- feature/new-checkout -------------------------
        \                           |
         \-- i18n/new-checkout -----/
             (このフィーチャーの翻訳)

マージコンフリクトの処理

SyncはほとんどのマージコンフリクトをP自動的に処理します:

  1. PR作成前に翻訳ブランチをRebase
  2. 翻訳ファイルにJSON対応マージ(行ベースではない)を使用
  3. コンフリクトが検出された場合にSyncを再トリガー

自動解決が不可能な場合、SyncはPRにコメントを追加してコンフリクトを説明し、手動解決の手順を提案します。


ステップ6:モニタリングとトラブルシューティング

Syncステータスダッシュボード

Better i18nダッシュボードでSync状態を監視します:

  • Sync履歴: ステータス付きの各Syncイベント(成功、部分的、失敗)
  • 保留中の翻訳: 翻訳待ちのキー
  • カバレッジトレンド: 言語ごとの時系列翻訳カバレッジ
  • PRアクティビティ: オープン、マージ済み、クローズ済みの翻訳PR

よくある問題と解決策

問題:プッシュ時にSyncがトリガーされない

  • GitHub Appがリポジトリにインストールされていることを確認します
  • SettingsWebhooks でWebhookがアクティブかチェックします
  • プッシュが設定済みのbaseBranchに対して行われていることを確認します
  • 変更されたファイルが設定済みのpathsパターンに一致することを確認します

問題:PRにマージコンフリクトがある

  • Syncは自動的にRebaseしますが、ブランチが大幅に分岐している場合は手動解決が必要な場合があります
  • 翻訳PRのコンフリクトを解決してからプッシュしてください——Syncはあなたの解決を上書きしません

問題:AI翻訳の品質が低い

  • 設定に詳細なai.instructionsを追加します
  • 用語集と ブランドガイドラインを含めます
  • 重要な言語に対してrequireApprovalの有効化を検討します

問題:小さなPRが多すぎる

  • 変更をまとめるためにdelivery.batchWindowを設定します:
sync:
  delivery:
    # 複数のプッシュを1つのPRにまとめるために30分待機
    batchWindow: 30

高度な設定

ネームスペースフィルタリング

特定のネームスペースのみ同期します:

sync:
  paths:
    - "locales/{locale}/common.json"
    - "locales/{locale}/marketing.json"
  # 内部ネームスペースを明示的に除外
  exclude:
    - "locales/{locale}/internal.json"
    - "locales/{locale}/test-fixtures.json"

カスタムコミットメッセージ

sync:
  delivery:
    commitMessage: "chore(i18n): sync translations for {languages}"
    prTitle: "chore(i18n): translations update ({date})"
    prBody: |
      ## Automated Translation Update

      This PR contains translations synced from Better i18n.

      **Languages updated:** {languages}
      **Keys added:** {keysAdded}
      **Keys updated:** {keysUpdated}
      **Keys removed:** {keysRemoved}

      ---
      _Generated by Better i18n GitHub Sync_

Webhookイベント

カスタム統合のために、WebhookでSyncイベントをサブスクライブできます:

sync:
  webhooks:
    - url: "https://your-server.com/api/i18n-webhook"
      events:
        - sync.completed
        - sync.failed
        - pr.created
        - pr.merged
      secret: "${WEBHOOK_SECRET}"  # Better i18nダッシュボードで設定

実際の例:ECサイトアプリのセットアップ

Next.jsを使用した典型的なECサイトアプリケーションの完全な設定例です:

# better-i18n.yml
sync:
  sourceLanguage: en
  targetLanguages:
    - es
    - fr
    - de
    - ja
    - "pt-BR"
    - "zh-CN"

  paths:
    - "messages/{locale}/{namespace}.json"

  baseBranch: main

  delivery:
    method: pr
    branchPattern: "i18n/translations-{date}"
    autoMerge: true  # CIが通過したら自動マージ
    reviewers:
      - "@frontend-team"
    labels:
      - "i18n"
      - "auto-merge"
    batchWindow: 15  # 15分以内の変更をまとめる

  ai:
    autoTranslate: true
    requireApproval: false
    instructions: |
      E-commerce context:
      - "Cart" should use shopping cart terminology (not vehicle)
      - Currency amounts should not be translated (they are formatted by code)
      - Product names in {curly braces} are variables — do not translate
      - Use formal register for German and Japanese
      - Use informal register for Spanish and Portuguese
      - Keep "Better i18n" as-is in all languages

  featureBranchSync:
    enabled: true
    targetBranches: ["main", "staging"]
    followBranch: true

この設定では:

  1. mainまたはstagingへのプッシュがSyncをトリガーします
  2. 新しいキーが数分以内にAIで翻訳されます
  3. 翻訳が自動マージ可能なPRとして届きます
  4. フィーチャーブランチが独自の翻訳PRを受け取ります
  5. CI/CDがマージ前にカバレッジと構文を検証します

まとめ

GitHub Translation Syncは、ローカライゼーションを手作業で error-prone(エラーが起きやすい)なプロセスから、既存の開発ワークフローに自然に統合される自動化パイプラインへと変革します。重要な原則:

  1. 翻訳はGitに存在する — 完全な履歴、ブランチ保護、コードレビュー
  2. Syncは自動的 — 忘れがちな手動プッシュ/プルコマンドが不要
  3. PRがレビューを可能にする — 翻訳が他のコード変更と同様にレビューされます
  4. CI/CDが品質を強制する — カバレッジしきい値と構文バリデーションが問題のある翻訳をブロック
  5. AIが加速する — 新しいキーが数日ではなく数分で翻訳されます

セットアップには約30分かかります。最初の週に節約される時間は、通常、セットアップへの投資を上回ります。


翻訳ワークフローを自動化する準備はできましたか?Better i18nを始めて、数分でGitHubリポジトリを接続しましょう。

Comments

Loading comments...