better-i18n Doctor:自動化された翻訳品質モニタリング
コードベースの不足した翻訳、オーファンキー、プレースホルダーの不一致をスキャンします。コミットごとに0〜100のヘルススコアを取得できます。
better-i18n Doctor:自動化された翻訳品質モニタリング
アプリケーションは12の言語でリリースされています。しかし、すべての画面、すべてのエラーメッセージ、すべてのツールチップが翻訳されているかどうか、どのように確認しますか?英語の{count}というプレースホルダーがフランス語で誤って{nombre}と書かれていないか、どのように確認しますか?3スプリント前にコードベースから削除したキーが、まだ翻訳ファイルに残って混乱を招いていないか、どのように確認しますか?
ほとんどのチームは、翻訳の問題をユーザーから指摘されて初めて気づきます。東京のユーザーが挨拶の代わりにdashboard.welcome_messageという生のキーを見てしまいます。ドイツ人ユーザーが実際の金額ではなく{amount}が表示されると報告します。QAエンジニアがJSONファイルを手動で比較し、スペイン語翻訳に先月追加された47個のキーが不足していることを発見します。
better-i18n Doctorは、コードベースと翻訳ファイルをスキャンし、すべてのカテゴリの翻訳問題を特定し、0〜100のヘルススコアを生成する自動化されたi18nヘルスチェックツールです。CLIでローカルに実行でき、CI/CDパイプラインに統合でき、経時的な追跡のためにbetter-i18nプラットフォームに結果を報告します。
ヘルススコアの仕組み
Doctorは単一の数値、0〜100のヘルススコアを生成します。このスコアは、i18n品質の異なる側面を評価する4つのカテゴリの加重集計です。
4つのカテゴリ
**Coverage(カバレッジ)**は、コード内で使用されているすべてのキーがすべてのターゲット言語ファイルに存在するかどうかを測定します。英語に存在するが日本語に存在しないキーはカバレッジギャップです。カバレッジは翻訳問題の最も一般的な原因です。新機能が翻訳依頼されていないキーとともにリリースされたり、開発者が1つのnamespaceにキーを追加して他のnamespaceへの追加を忘れたりすることがあります。
**Quality(品質)**は、構造的な正確さについて翻訳のコンテンツをチェックします。プレースホルダーの不一致が主な懸念事項です。英語の文字列に{count}と{name}がある場合、ドイツ語の翻訳には全く同じプレースホルダーが必要です。Qualityは空の翻訳(キーが存在するが値が空白のもの)、UIレイアウトを壊す可能性のある過度に長い翻訳、ソース言語と同一の文字列(英語からコピーされた未翻訳コンテンツを示している可能性があります)もチェックします。
**Structure(構造)**は翻訳ファイルの構成を評価します。オーファンキー(翻訳ファイルに存在するがソースコードで参照されていないキー)をチェックします。オーファンキーは無害ですが、メンテナンスの負担を生みます。翻訳者はユーザーが決して見ない文字列を更新するために時間を費やし、開発者は未使用機能の翻訳をレビューするために時間を無駄にします。Structureは一貫したキーの命名、重複キー、namespaceの構成もチェックします。
**Code(コード)**は、AST レベルの解析を使用して、国際化すべきハードコードされた文字列のソースコードをスキャンします。JSXコンポーネント内のユーザー向け文字列、UI関数に渡されたテンプレートリテラル、エラーメッセージや通知で使用される文字列定数を検出します。このカテゴリはi18n技術的負債の最も一般的な原因を捉えます。開発者が後で修正するつもりで速さを優先して<p>{t('common.loading')}</p>の代わりに<p>Loading...</p>と書いてしまうケースです。DoctorはこれらをリリースPR前に発見します。
スコアの計算
各カテゴリは、合格チェック数と総チェック数の比率に基づいて0〜100のサブスコアを生成します。全体のヘルススコアは加重平均です:
| カテゴリ | 重み | 測定内容 |
|---|---|---|
| Coverage | 40% | 言語間の不足している翻訳キー |
| Quality | 30% | プレースホルダーの不一致、空の値、疑わしいコンテンツ |
| Structure | 20% | オーファンキー、命名の一貫性、重複 |
| Code | 10% | ソースコード内のハードコードされた文字列 |
Coverageが最も高い重みを持つのは、欠落した翻訳が最も直接的なユーザー影響を持つためです。生のキーやフォールバック言語がユーザーに表示されます。コード分析の重みが最も低いのは、ハードコードされた文字列はユーザーエクスペリエンスを即座には壊さない技術的負債だからです(時間をかけて対処すべきですが)。
合格/不合格の閾値
全体スコアが80以上でエラー数がゼロの場合、スキャンは合格とマークされます(警告ではなくエラー)。エラーは直接ユーザーに影響する問題です。完全な機能の翻訳が欠落している、ランタイムエラーを引き起こすプレースホルダーの不一致、存在しないnamespaceを参照するキーなどです。警告はユーザーエクスペリエンスを壊さないが修正すべき問題です。オーファンキー、命名の不一致、ハードコードされた文字列などです。
チームの基準に合わせて合格閾値を設定できます:
bi18n doctor --threshold 90
Doctorのローカル実行
基本スキャン
プロジェクトルートから完全なヘルスチェックを実行します:
bi18n doctor
Doctorはbetter-i18n.yml設定に基づいて、または一般的なディレクトリ構造(locales/、messages/、i18n/、lib/l10n/)を検出することで、自動的に翻訳ファイルを発見します。ソースファイルをスキャンしてキーの使用状況を確認し、すべてを相互参照してヘルスレポートを生成します。
出力は全体スコア、カテゴリの内訳、個別のルール結果を示す構造化されたレポートです:
i18n Doctor Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overall Score: 87/100 ✓ PASSED
Coverage 92/100 ██████████████████░░ 3 missing keys
Quality 85/100 █████████████████░░░ 2 placeholder mismatches
Structure 78/100 ███████████████░░░░░ 12 orphan keys
Code 90/100 ██████████████████░░ 4 hardcoded strings
Errors: 0 Warnings: 21
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ターゲットスキャン
即時のニーズに関係ない、または時間がかかりすぎるカテゴリをスキップします:
# コード分析をスキップ(より速いスキャン)
bi18n doctor --skip-code
# ヘルス/品質チェックをスキップ(カバレッジと構造のみ)
bi18n doctor --skip-health
# 同期状態チェックをスキップ
bi18n doctor --skip-sync
# 詳細出力 — 失敗だけでなくすべてのルール結果を表示
bi18n doctor --verbose
個別チェックコマンド
Doctorは独立して実行できるいくつかのチェックをまとめています:
# すべての言語で不足している翻訳キーをチェック
bi18n check:missing
# ソースコードで参照されていないオーファンキーをチェック
bi18n check:unused
# すべてのチェックを実行(コード分析なしのdoctorと同等)
bi18n check
# ハードコードされた文字列のソースコードをスキャン
bi18n scan
# 同期状態 — ローカルファイルとプラットフォームの状態を比較
bi18n sync --dry-run
各コマンドは特定の懸念事項に焦点を当てた出力を生成します。特定のカテゴリの問題を修正する際に役立ちます。
CI/CD統合
GitHub Actions
DoctorはすべてのプルリクエストでCIチェックとして実行するように設計されています。--ciフラグはGitHub Actionsが理解できる形式で結果を出力し、問題のあるファイルにインラインアノテーションを生成します:
# .github/workflows/i18n-doctor.yml
name: i18n Health Check
on:
pull_request:
paths:
- "locales/**"
- "src/**"
- "messages/**"
jobs:
doctor:
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: Run i18n Doctor
run: bunx @better-i18n/cli doctor --ci --threshold 80
env:
BETTER_I18N_API_KEY: ${{ secrets.BETTER_I18N_API_KEY }}
--ciフラグが設定されると、Doctorは:
- スキャンが失敗した場合(スコアが閾値を下回るか、エラーが存在する場合)コード1で終了し、GitHub Actionsチェックを失敗させます
- GitHub Actions形式でアノテーションを出力し、問題がPR diffのインラインコメントとして表示されます
- GitHub Actionsチェック出力に表示されるサマリーを生成します
GitHub Actionsワークフローの自動生成
ワークフローファイルを手動で書きたくない場合、better-i18nが作成することができます。プラットフォームダッシュボードで Integrations、次に GitHub Actions に移動し、Create Doctor Workflow をクリックします。これにより、プロジェクトの設定に合わせた事前設定済みのワークフローファイルを含むプルリクエストがリポジトリに作成されます。
自動生成されたワークフローには以下が含まれます:
- 翻訳ファイルの場所に一致するパスフィルター
- 設定された閾値
- APIキーのセットアップ手順
- 失敗時のオプションのSlack通知
プラットフォームへの報告
Doctorが--reportフラグとAPIキーで実行されると、完全なレポートをbetter-i18nプラットフォームに送信します:
bi18n doctor --report --api-key $BETTER_I18N_API_KEY
レポートには以下が含まれます:
- スコアと合格/不合格の状態
- カテゴリごとのエラーと警告の数
- 影響を受けるキーとファイルを含む個別のルール結果
- メタデータ:コミットSHA、ブランチ名、スキャンされたファイル数、チェックされたキー数、タイムスタンプ
プラットフォームに送信されたレポートは保存され、プロジェクトダッシュボードに表示されます。経時的なスコアのトレンドを確認し、ブランチ間でレポートを比較し、どのカテゴリが改善または低下しているかを追跡できます。
CIレポートの送信
CI環境では、--ciと--reportを組み合わせて、PRを検証しながらレポートを送信します:
- name: Run i18n Doctor
run: bunx @better-i18n/cli doctor --ci --report --threshold 85
env:
BETTER_I18N_API_KEY: ${{ secrets.BETTER_I18N_API_KEY }}
これにより2つのフィードバックループが得られます:
- 即時:PRチェックが合格または不合格になり、開発者はインラインアノテーションを確認できます
- 履歴:レポートはトレンド分析とチームの可視性のためにプラットフォームに保存されます
ルールの詳細
Doctorは各カテゴリ内のルールセットを評価します。最も影響力のあるルールとその検出内容を示します。
Coverageルール
missing-keys:ソースコードで使用されているすべてのキーについて、すべてのターゲット言語ファイルに翻訳が存在するかチェックします。不足しているキーは最も一般的なi18n問題であり、最もユーザーに見えます。生のキー名またはフォールバック言語が表示されます。
namespace-coverage:コードで参照されているすべてのnamespaceが、すべてのターゲット言語に対応する翻訳ファイルを持っているかチェックします。開発者がt('checkout.confirm_order')を追加しても、checkout namespaceファイルが韓国語に存在しない場合があります。
Qualityルール
placeholder-mismatch:ソースとターゲットの翻訳間でプレースホルダーを比較します。en: "Hello {name}, you have {count} items"が存在する場合、他のすべての言語の翻訳に{name}と{count}が含まれているかチェックします。余分なまたは不足しているプレースホルダーはランタイムエラーまたは生のプレースホルダー構文の表示を引き起こします。
empty-translation:ターゲット言語に存在するが空の文字列値を持つキーにフラグを立てます。空の翻訳は、実際の翻訳コンテンツを提供せずにプログラムでキーを追加した結果であることが多いです。
source-identical:ソース言語と文字単位で同一の翻訳にフラグを立てます。一部の文字列(ブランド名、URL、技術用語)は言語間で合法的に同一ですが、ソース同一の文字列が多い場合は通常、未翻訳のコンテンツを示しています。
Structureルール
orphan-keys:ソースコードのどこにも参照されていない翻訳ファイル内のキーを識別します。オーファンキーは機能が削除されても翻訳ファイルがクリーンアップされない場合に蓄積されます。翻訳者の労力を無駄にし、何がアクティブに使用されているかについての混乱を生みます。
duplicate-keys:単一のファイルまたはnamespace内で同じキーが複数回定義されていることを検出します。重複は予測不可能な動作を引き起こします。翻訳エンジンはそのうちの1つを使用しますが、どちらを使用するかは実装の詳細に依存します。
naming-consistency:キー名が一貫したパターンに従っているかチェックします。ほとんどのキーがsnake_caseを使用している場合、camelCaseを使用するキーはフラグが立てられます。一貫性のない命名はキーを見つけて維持することを難しくします。
Codeルール
hardcoded-jsx:AST解析を使用してJSX要素内の文字列リテラルを検出します。<h1>Welcome</h1>はフラグが立てられます;<h1>{t('welcome')}</h1>は立てられません。このルールはJSXを理解し、CSSクラス名やデータ属性などのユーザー向けでない文字列を無視します。
hardcoded-template:トースト通知、アラートダイアログ、エラーメッセージなど、通常ユーザー向けの出力を生成する関数に渡される文字列リテラルを検出します。showToast("Operation successful")はフラグが立てられます。
hardcoded-constant:errorMessage、label、title、placeholderなどのユーザー向けの名前を持つ変数に割り当てられた文字列定数で、翻訳関数にラップされていないものを識別します。
プラットフォームダッシュボード
--reportで送信されたレポートはbetter-i18nプラットフォームダッシュボードで視覚化されます。
スコアのトレンド
時系列チャートが時間の経過とともにヘルススコアを表示します。各ポイントは日付順にプロットされたDoctorレポートを表します。ブランチでフィルタリングしてmainとフィーチャーブランチのヘルス軌跡を確認できます。トレンドラインにより、i18n品質が改善、安定、または低下しているかどうかを簡単に確認できます。
カテゴリの内訳
各カテゴリにドリルダウンして、どのルールが合格しているかどうかを確認します。不合格のルールごとに、関連するキーとファイルを確認できます。キーをクリックして翻訳エディタで開き、ファイルをクリックしてリポジトリのコンテキストで確認します。
クロスプロジェクト比較
複数のプロジェクトを持つ組織の場合、ダッシュボードはすべてのプロジェクトのヘルススコアを表示します。これはどのプロジェクトがi18nの注意を必要としているかを特定し、組織全体の品質基準を設定するのに役立ちます。
アラート
ヘルススコアが閾値を下回ったときに通知を受けるようにアラートを設定します:
- メール:ヘルススコアの変化の週次ダイジェスト
- Slack:レポートが失敗した際の即時通知
- Webhook:監視スタックのためのカスタム統合
実用的な例
例1:リリース前の不足した翻訳を検出
チームが30個の新しい翻訳キーを持つ新しいチェックアウトフローを追加しました。開発者はすべてのキーを英語ファイルに追加しました。フランス語とドイツ語の翻訳は依頼されましたが、まだ完了していません。Doctorなしでは、フランス語とドイツ語のユーザーに生のキーが表示された状態でリリースされます。
CIでDoctorを使用すると:
Coverage 60/100 ████████████░░░░░░░░ 30 missing keys (fr, de)
Error: 30 keys missing in target languages
checkout.confirm_order — missing in: fr, de
checkout.payment_method — missing in: fr, de
checkout.shipping_address — missing in: fr, de
... (27 more)
Result: FAILED (score 60, threshold 80)
PRがブロックされます。開発者はインラインアノテーションを確認し、翻訳を依頼し、翻訳が完了した後にのみPRがマージされます。
例2:プレースホルダーの不一致を検出
翻訳者が通知文字列のドイツ語翻訳を更新します。英語ソースにはYou have {count} new messages from {sender}があります。ドイツ語翻訳が誤って{count}の代わりに{anzahl}を使用します。
Doctorがこれを検出します:
Quality 75/100 ███████████████░░░░░ 1 placeholder mismatch
Error: Placeholder mismatch in notifications.new_messages (de)
Source placeholders: {count}, {sender}
Target placeholders: {anzahl}, {sender}
Missing: {count}
Extra: {anzahl}
例3:機能削除後のクリーンアップ
チームが6ヶ月前にレガシーダッシュボードを削除しました。コードはなくなりましたが、翻訳ファイルにはlegacy_dashboard namespace下に85個のキーが残っています。翻訳者が一括翻訳作業をする際に、誰も見ていないコンテンツを更新するために時間を費やすことがあります。
Doctorがオーファンキーを見つけます:
Structure 65/100 █████████████░░░░░░░ 85 orphan keys
Warning: 85 keys in namespace "legacy_dashboard" are not referenced in source code
legacy_dashboard.welcome — not referenced
legacy_dashboard.stats_header — not referenced
legacy_dashboard.chart_title — not referenced
... (82 more)
例4:ハードコードされた文字列を見つける
新しい開発者がチームに参加し、翻訳システムを使用せずに機能を実装します。すべての文字列をJSXに直接ハードコードします:
// Doctor適用前
<div>
<h2>Account Settings</h2>
<p>Manage your account preferences below.</p>
<button>Save Changes</button>
</div>
Doctorがすべてのハードコードされた文字列にフラグを立てます:
Code 40/100 ████████░░░░░░░░░░░░ 3 hardcoded strings
Warning: Hardcoded string in JSX element (src/pages/Settings.tsx:15)
<h2>Account Settings</h2>
Suggestion: <h2>{t('settings.account_title')}</h2>
Warning: Hardcoded string in JSX element (src/pages/Settings.tsx:16)
<p>Manage your account preferences below.</p>
Warning: Hardcoded string in JSX element (src/pages/Settings.tsx:17)
<button>Save Changes</button>
代替との比較
手動JSONの差分比較:翻訳ファイルを手動で比較するチームはカバレッジの問題を検出できますが、その他のすべては見逃します。プレースホルダーの不一致、オーファンキー、ハードコードされた文字列などです。手動チェックはエラーが起きやすく、いくつかの言語を超えてはスケールしません。
ESLint i18nプラグイン:eslint-plugin-i18nextのようなlintルールはJSXのハードコードされた文字列を検出しますが、翻訳ファイルの品質、言語間のカバレッジ、または構造的な問題をチェックしません。Doctorはコード分析を4つのカテゴリの1つとして含み、i18n問題の全範囲をカバーします。
Phrase QPS(品質パフォーマンススコア):Phraseは翻訳品質スコアを提供しますが、技術的品質(不足しているキー、プレースホルダーの不一致、オーファンキー)よりも言語的品質(文法、用語)に焦点を当てています。Doctorは技術的な側面に焦点を当てています。ランタイムエラーと壊れたUIを引き起こす問題です。
自動化されたチェックなし:多くのチームには自動化されたi18nチェックがまったくありません。問題はユーザーまたはQAエンジニアによって発見されます。Doctorはいかなる環境にも到達する前に問題を検出する包括的な自動化されたカバレッジを提供します。
よくある質問
Doctorスキャンにはどのくらい時間がかかりますか?
10,000個のキー、8言語、200個のソースファイルを持つプロジェクトの典型的なスキャンは10秒未満で完了します。コード分析(AST解析)は最も遅いカテゴリです。カバレッジと品質チェックのみが必要な場合は、より速いスキャンのために--skip-codeを使用してください。
better-i18nプラットフォームに接続せずにDoctorを実行できますか?
はい。Doctorはデフォルトで完全にローカルで実行されます。--reportフラグはオプションであり、トレンド追跡のためにプラットフォームに結果を送信する場合にのみ必要です。
コード分析はどのフレームワークをサポートしていますか? コード分析は現在、React(JSX/TSX)、Vue(SFCテンプレート)、Svelteコンポーネントをサポートしています。Angularサポートは計画中です。フレームワーク検出はプロジェクトの依存関係に基づいて自動的です。
カスタムルールを追加できますか? カスタムルールはロードマップに含まれています。現在、ルールの重大度(エラーと警告)を設定し、プロジェクトに関連しない特定のルールを無効にすることができます。
DoctorはMonorepoで動作しますか? はい。Doctorはワークスペースを意識したスキャンをサポートしています。ワークスペースの境界を検出し、各パッケージを独立してスキャンし、パッケージごとのレポートと集計された全体スコアを生成します。
GitHub Actionsワークフローの作成はどのように機能しますか?
better-i18nダッシュボードでは、Create Doctor WorkflowアクションがGitHub APIを使用して、事前設定済みの.github/workflows/i18n-doctor.ymlファイルを含むプルリクエストをリポジトリに作成します。PRをレビューしてマージすることでワークフローが有効になります。
i18nヘルスの監視を開始する
翻訳の問題はユーザーではなく、CIで検出されるべきです。better-i18n Doctorはチームに継続的で自動化されたヘルスチェックを提供し、i18n品質のすべての側面をスコア化し、壊れた翻訳のリリースをブロックします。
無料トライアルを開始するして、5分以内に最初のDoctorスキャンを実行してください。