Djangoアプリを複数の言語でリリースしたことがあるなら、この流れをご存知でしょう。文字列を gettext() で囲み、makemessages を実行し、何百ものエントリがある .po ファイルを開いて、一行ずつ翻訳を始めます。2言語で50文字列なら許容範囲です。6言語で500文字列となると、二度と戻ってこない丸一日の作業です。
このガイドでは、Djangoの国際化(i18n)パイプラインを最初から最後までカバーし、どこで破綻するかを説明し、AI駆動の翻訳で最も苦痛な部分を自動化する方法を紹介します。
標準的なDjango i18nワークフロー
Djangoの組み込みi18nシステムはよく設計されています。コアループは次のようになります:
ステップ1:Pythonコードとテンプレートで翻訳対象の文字列をマーク:
from django.utils.translation import gettext as _
def dashboard(request):
welcome = _("Welcome back, %(name)s!") % {"name": request.user.first_name}
return render(request, "dashboard.html", {"welcome": welcome})
{% load i18n %}
<h1>{% trans "Account Settings" %}</h1>
<p>{% blocktrans %}You have {{ count }} unread messages.{% endblocktrans %}</p>
ステップ2:文字列を .po ファイルに抽出:
python manage.py makemessages -l de -l fr -l nl
これはコードベース全体をスキャンし、言語ごとに1つの .po ファイルを生成します。すべての翻訳可能な文字列が含まれます:
#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""
#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""
ステップ3:すべての空の msgstr を手動で翻訳。
ステップ4:完成した .po ファイルをバイナリの .mo ファイルにコンパイル:
python manage.py compilemessages
ステップ1、2、4は速いです。ステップ3がプロセスが崩壊するところです。
手動翻訳がスケールしない理由
典型的なDjangoアプリケーションには200から2,000の翻訳可能な文字列があります。これにターゲット言語の数を掛けると、深刻な時間的コミットメントになります。
これは理論的な不満ではありません。有名なDjango Forumのスレッドで、あるデベロッパーは .po ファイルあたり8時間以上を手動翻訳に費やしたと報告しました。Djangoコアコントリビューターの一人は、コミュニティから寄せられた翻訳を1つのリリースに統合するのに10時間以上かかったと述べています。その大部分はレビュー、フォーマットの修正、壊れたプレースホルダーの修復でした。
問題は時間とともに複合化します:
- プレースホルダーが壊れる。
Welcome, %(name)s!のような文字列をGoogle翻訳にコピーすると、Willkommen, %(Name)s!やBienvenue, %(nom)s!が返ってくることがよくあります。この微妙な破損はランタイムクラッシュを引き起こします。 - 一貫性がずれる。 用語集がなければ、"dashboard"はあるファイルでは「Instrumententafel」、別のファイルでは「Dashboard」と翻訳されます。3ヶ月後、どちらが意図的だったか誰も覚えていません。
- スプリントが文字列を追加する。 すべてのフィーチャーブランチが新しい翻訳可能な文字列を追加します。前四半期に完全な翻訳パスの費用を支払ったとしても、今は
.poファイルに40の未翻訳エントリが散在しています。 - AIアシスタントは一度だけ助ける。
.poファイルをChatGPTやClaudeに貼り付けて、まともな結果を得ることができます。しかし次のスプリントで15の新しい文字列が現れると、ゼロからプロンプトを書き、ファイル全体を再翻訳し、既存の翻訳と一貫性が保たれることを祈ることになります。
根本原因は、翻訳がインクリメンタルで反復可能なプロセスではなく、一度きりのイベントとして扱われていることです。
AIによる翻訳の自動化
アイデアは単純です:人間が各 .po ファイルを開いて msgstr の値を埋める代わりに、ツールがファイルを読み、未翻訳の文字列をAIモデルまたは翻訳APIに送信し、結果を書き戻し、その他すべて(コメント、ファイル構造、プレースホルダー、複数形)を保持します。
TranslateBot Django は、まさにこれを行うオープンソースパッケージです。Djangoの管理コマンドシステムに統合されるため、既存のワークフローにフィットします。
ステップバイステップのセットアップ
1. パッケージをインストール
pip install translatebot-django
または、uv(推奨)を使用している場合:
uv add --dev translatebot-django
開発依存関係としてインストールするのは意図的です。TranslateBotは翻訳を生成するときにのみ必要で、本番環境のランタイムでは不要です。
2. INSTALLED_APPSに追加
# settings.py
INSTALLED_APPS = [
# ...
"translatebot_django",
]
3. AIプロバイダーを設定
# settings.py
import os
TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"
TranslateBotは内部でLiteLLMを使用しており、1つの文字列を変更するだけで100以上のモデルのいずれかに切り替えることができます:
| プロバイダー | TRANSLATEBOT_MODEL の値 |
|---|---|
| OpenAI | gpt-4o-mini, gpt-4o |
| Anthropic | claude-sonnet-4-5-20250929 |
gemini/gemini-2.5-flash |
|
| Azure OpenAI | azure/gpt-4o-mini |
| DeepL | 代わりに TRANSLATEBOT_PROVIDER = "deepl" を使用 |
DeepLの場合、エクストラをインストールします:pip install translatebot-django[deepl]。DeepLの無料枠は月50万文字を無料で提供しており、ほとんどの小中規模プロジェクトに十分です。
4. 言語を定義
# settings.py
LANGUAGES = [
("en", "English"),
("de", "German"),
("fr", "French"),
("nl", "Dutch"),
("ja", "Japanese"),
]
5. 翻訳を実行
python manage.py translate
以上です。TranslateBotはプロジェクト内の .po ファイルをスキャンし、未翻訳のエントリを特定し、最適化されたバッチで設定済みのAIモデルに送信し、結果を書き戻します。既存の翻訳はそのまま残ります。
単一の言語を翻訳するには:
python manage.py translate --target-lang nl
出力はこのようになります:
Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings
6. 通常通りコンパイル
python manage.py compilemessages
完全なワークフローは次のようになります:
python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages
3つのコマンド。すべての言語。すべてのスプリント。
設計によるインクリメンタル
反復可能なワークフローにとって最も重要な機能はインクリメンタル翻訳です。TranslateBotは msgstr が空のエントリのみを翻訳します。500の文字列があり、このスプリントで15が新しい場合、その15だけがAPIに送信されます。
これは実用的な理由で重要です:
- コスト。 新しい文字列に対してのみ支払い、ファイル全体ではありません。
- 速度。 15文字列の翻訳は秒単位で、分単位ではありません。
- 安定性。 すでにレビューして承認した翻訳は決して上書きされません(明示的に
--overwriteを渡さない限り)。
プレースホルダーの安全性
Djangoはいくつかのプレースホルダー形式を使用します:%(name)s、%s、%d、{0}、{name}、そしてインラインHTMLタグ(<strong> や <a href="..."> など)。翻訳でこれらのいずれかが壊れると、ランタイムエラーや壊れたマークアップが発生します。
TranslateBotはAIモデルにすべてのプレースホルダー形式を保持するよう指示し、出力を検証します。次のような文字列:
Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.
オランダ語では次のように翻訳されます:
Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.
すべてのプレースホルダーがそのまま保持されます。
TRANSLATING.mdによる品質管理
AIモデルはコンテキストを理解するとより良い翻訳を行います。TranslateBotはプロジェクトルートで TRANSLATING.md ファイルを探し、すべての翻訳リクエストにその内容を含めます。
# Translation Context
## About This Project
A B2B project management tool for construction companies.
## Terminology
- "project" means a construction project, not a software project
- "plan" means a building plan/blueprint, not a subscription plan
- Keep "Gantt chart" as-is in all languages
## Tone
- German: use formal "Sie" form (business context)
- French: use formal "vous" form
- Dutch: use informal "je" form
## Do Not Translate
- Brand name: "BuildFlow"
- Feature names: "SmartSchedule", "CostTracker"
このファイルはコードと一緒にバージョン管理されるため、チーム全体が同じ翻訳コンテキストを共有します。専門用語を持つアプリごとに TRANSLATING.md ファイルを配置することもできます。医療記録モジュールと請求モジュールは、それぞれ独自の用語集を持つことができます。
コミット前のプレビュー
--dry-run フラグは、APIコールやファイルの変更なしに、何が翻訳されるかを正確に表示します:
python manage.py translate --target-lang fr --dry-run
Found 15 untranslated entries
Dry run mode: skipping LLM translation
Would translate 'Welcome to our site'
Would translate 'Hello, %(name)s!'
...
Dry run complete: 15 entries would be translated
これは大規模な翻訳実行の前や、新しいチームメンバーがAPIコストを負担する前にコマンドの動作を理解したい場合に便利です。
CI/CDインテグレーション
強制なしでは翻訳が古くなることは避けられません。TranslateBotにはCIパイプライン用に設計された check_translations 管理コマンドが含まれています:
# .github/workflows/ci.yml
jobs:
translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- run: uv python install
- run: uv sync --frozen
- name: Install gettext
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends gettext
- name: Check translations
run: uv run python manage.py check_translations --makemessages
--makemessages フラグは最初に makemessages -a --no-obsolete を実行し、チェック前に .po ファイルが現在のソースコードを反映していることを確認します。未翻訳またはファジーなエントリがある場合、コマンドはコード1で終了しビルドを失敗させます:
locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed
典型的な開発者ワークフローは次のようになります:
- フィーチャーブランチで新しい翻訳可能な文字列を追加。
- CIが文字列が未翻訳のため失敗。
- ローカルで
python manage.py translateを実行。 - 更新された
.poファイルをコミット。 - CIが成功。
翻訳が知らないうちにずれることはありません。
データベースコンテンツの翻訳
アプリケーションがデータベースに翻訳可能なコンテンツ(製品名、ブログ記事のタイトル、カテゴリラベル)を保存している場合、TranslateBotはdjango-modeltranslationとも統合します:
pip install translatebot-django[modeltranslation]
# Translate all registered model fields
python manage.py translate --target-lang de --models
# Translate specific models only
python manage.py translate --target-lang de --models Product Category
同じインクリメンタルロジックが適用されます:ターゲット言語の値が空のフィールドのみが翻訳されます。
コスト比較
最も一般的な質問の1つは、AI翻訳が代替手段と比較してコスト効率が良いかどうかです。5言語で500の翻訳可能な文字列を持つプロジェクトのおおまかな比較です:
| アプローチ | 推定コスト | 時間投資 |
|---|---|---|
| 手動(開発者の時間) | 自己負担$0、20-40時間以上 | 非常に高い |
| プロの翻訳サービス | $500-2,000以上 | 低い(ただし納期が長い) |
| SaaSローカリゼーションプラットフォーム | $50-200/月 | 中程度 |
| TranslateBot + GPT-4o-mini | 約$0.05(一回限り) | 数分 |
| TranslateBot + DeepL Free | $0(月50万文字まで) | 数分 |
| TranslateBot + Claude/GPT-4o | 約$0.30(一回限り) | 数分 |
数値は文字列数とターゲット言語によって変わりますが、桁違いの差は一貫しています。継続的なメンテナンス(各スプリントで追加される20-50の新しい文字列の翻訳)では、AIコストは実質的にゼロです。
ベストプラクティス
--dry-run から始める。最初の実際の翻訳実行の前に、何が起こるかをプレビューしてください。これにより信頼が生まれ、設定の問題を早期に発見できます。
翻訳前に .po ファイルをコミットする。何か問題が起きた場合、git checkout で即座にクリーンな状態に戻れます。
初日から TRANSLATING.md を書く。プロジェクトの説明といくつかの用語ルールだけの簡潔なファイルでも、翻訳品質を測定可能に向上させます。
CIに check_translations を追加する。この1つのステップで、最も一般的なi18n障害モード(翻訳対象としてマークされたが実際には翻訳されなかった文字列)を防止できます。
コスト効率のために gpt-4o-mini またはDeepLを使用する。精度が重要なプロジェクト(マーケティングコピー、法的テキスト、ドメイン固有の用語など)には、GPT-4oやClaudeなどのプレミアムモデルを取っておきましょう。
重要な文字列をレビューする。AI翻訳はほとんどのUIテキストには十分ですが、法的拘束力のあるもの、安全性に関わるもの、またはハイリスクな状況で顧客に面するものは、ネイティブスピーカーにレビューしてもらいましょう。
数時間から数秒へ
DjangoのI18nフレームワークは翻訳の抽出とコンパイルに優れています。ギャップは常に翻訳ステップそのもの、つまり複数の言語で何百もの msgstr 値を埋めるという退屈でエラーの起きやすい作業にありました。
TranslateBotはそのギャップを埋めます。インストールし、AIプロバイダーに向け、1つのコマンドを実行するだけです。新しい文字列は翻訳されます。既存の文字列はそのまま残ります。プレースホルダーはそのまま保持されます。CIが漏れを検出します。
.po ファイルは面倒な作業ではなくなり、ビルドの一部になります。
pip install translatebot-django
translatebot.dev で始めましょう。