目次
ブランチに散在する翻訳ファイル、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が以下を行います:
- 新規または変更されたキーを検出します(コードをプッシュしたとき)
- 翻訳プラットフォームに送信します(翻訳のため)
- 完成した翻訳をPull Requestとして返却します
- 翻訳ファイルをブランチ間で同期し続けます
なぜPRベースの翻訳デリバリーなのか?
従来のローカライゼーションワークフローではCLIのプッシュ/プルコマンドを使用します。PRベースのアプローチが優れている理由:
| CLI Push/Pull | PRベースの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を通じて動作し、リポジトリの翻訳ファイルへの読み書きアクセスを持ちます。
- Better i18nプロジェクトのダッシュボードに移動します
- Settings → Integrations に進みます
- Connect GitHub をクリックします
- 同期したいリポジトリを選択します
- 要求された権限を承認します
権限の説明
| 権限 | 必要な理由 |
|---|---|
| Read: Code | 新規/変更された翻訳キーを検出するため |
| Read/Write: Pull Requests | 完成した翻訳でPRを作成するため |
| Read: Metadata | リポジトリ情報にアクセスするため |
| Webhooks | Syncトリガーのプッシュイベントを受信するため |
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
設定オプションリファレンス
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
sourceLanguage | string | "en" | ソースロケールコード |
targetLanguages | string[] | [] | ターゲットロケールコード |
paths | string[] | 自動検出 | 翻訳ファイルのGlobパターン |
baseBranch | string | "main" | 監視するブランチ |
delivery.method | string | "pr" | 配信方法:prまたはcommit |
delivery.autoMerge | boolean | false | チェック通過時に自動マージ |
delivery.reviewers | string[] | [] | PRレビュアー(ユーザーまたはチーム) |
delivery.labels | string[] | ["i18n"] | PRラベル |
ai.autoTranslate | boolean | true | 新しいキーをAIで翻訳 |
ai.requireApproval | boolean | false | PR前に承認を要求 |
ai.instructions | string | "" | カスタムAI指示 |
ステップ3:Syncワークフローを理解する
設定後、典型的な開発サイクルで起こることは以下のとおりです:
新しいキーの追加
開発者 GitHub Better i18n GitHub
| | | |
|-- コミットプッシュ ---->| | |
| (en/common.jsonに |-- Webhook ----------->| |
| 新しいキーを追加) | | |
| | |-- AIが翻訳 -------->|
| | | 全ターゲット言語 |
| | | 向けに新キーを翻訳 |
| | | |
| |<---------- 翻訳付きPRを作成 ---------------|
| | | |
|<-- PR通知 ------------| | |
| | | |
|-- レビュー&マージ ---->| | |
既存キーの更新
既存キーのソーステキストを変更した場合:
- SyncがWebhook経由で変更を検出します
- 既存の翻訳が「要レビュー」としてマークされます
- AIが更新された翻訳を生成します
- 更新された翻訳でPRが作成されます
- レビュアーの比較のため、以前の翻訳がPRの説明に保存されます
キーの削除
ソースロケールからキーを削除した場合:
- Syncが削除を検出します
- 対応するキーがすべてのターゲットロケールファイルから削除されます
- 削除内容を含むPRが作成されます
- 監査目的で削除されたすべてのキーが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}`
});
必須ステータスチェック
翻訳バリデーションを必須にするためブランチ保護を設定します:
- Settings → Branches → Branch protection rules に移動します
- Require status checks to pass before merging を有効にします
- 以下のチェックを追加します:
Validate translation coverageValidate 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自動的に処理します:
- PR作成前に翻訳ブランチをRebase
- 翻訳ファイルにJSON対応マージ(行ベースではない)を使用
- コンフリクトが検出された場合にSyncを再トリガー
自動解決が不可能な場合、SyncはPRにコメントを追加してコンフリクトを説明し、手動解決の手順を提案します。
ステップ6:モニタリングとトラブルシューティング
Syncステータスダッシュボード
Better i18nダッシュボードでSync状態を監視します:
- Sync履歴: ステータス付きの各Syncイベント(成功、部分的、失敗)
- 保留中の翻訳: 翻訳待ちのキー
- カバレッジトレンド: 言語ごとの時系列翻訳カバレッジ
- PRアクティビティ: オープン、マージ済み、クローズ済みの翻訳PR
よくある問題と解決策
問題:プッシュ時にSyncがトリガーされない
- GitHub Appがリポジトリにインストールされていることを確認します
- Settings → Webhooks で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
この設定では:
mainまたはstagingへのプッシュがSyncをトリガーします- 新しいキーが数分以内にAIで翻訳されます
- 翻訳が自動マージ可能なPRとして届きます
- フィーチャーブランチが独自の翻訳PRを受け取ります
- CI/CDがマージ前にカバレッジと構文を検証します
まとめ
GitHub Translation Syncは、ローカライゼーションを手作業で error-prone(エラーが起きやすい)なプロセスから、既存の開発ワークフローに自然に統合される自動化パイプラインへと変革します。重要な原則:
- 翻訳はGitに存在する — 完全な履歴、ブランチ保護、コードレビュー
- Syncは自動的 — 忘れがちな手動プッシュ/プルコマンドが不要
- PRがレビューを可能にする — 翻訳が他のコード変更と同様にレビューされます
- CI/CDが品質を強制する — カバレッジしきい値と構文バリデーションが問題のある翻訳をブロック
- AIが加速する — 新しいキーが数日ではなく数分で翻訳されます
セットアップには約30分かかります。最初の週に節約される時間は、通常、セットアップへの投資を上回ります。
翻訳ワークフローを自動化する準備はできましたか?Better i18nを始めて、数分でGitHubリポジトリを接続しましょう。