取り組みの背景 — なぜ Gemini API で翻訳を自動化するのか
アプリやWebサービスをグローバルに展開するとき、多言語対応は避けて通れない課題です。従来の機械翻訳サービスは単純な文の置き換えには優れていますが、ブランドのトーンを維持したり、技術用語を正確に統一したりするには限界がありましました。
Gemini API は大規模言語モデルの強みを活かし、文脈を理解した自然な翻訳を実現します。System Instructions でトーンや用語集を指定できるため、プロジェクト固有の翻訳ルールを一貫して適用できる点が大きなメリットです。
ここではGemini API(Python SDK)を使って多言語翻訳パイプラインを構築する方法をステップバイステップで解説します。対象読者は、API の基本的な呼び出し方を理解していて、翻訳ワークフローを自動化したいエンジニアやプロダクトマネージャーです。
環境準備と API キーの取得
まず、Google AI Studio(aistudio.google.com)で API キーを取得します。取得後は環境変数に設定してコード内にハードコードしないようにしましょう。
# API キーを環境変数に設定
export GEMINI_API_KEY="YOUR_API_KEY"
# Python SDK のインストール
pip install google-genaiPython SDK をインポートして基本的な接続を確認します。
from google import genai
client = genai.Client(api_key="YOUR_API_KEY")
# 接続テスト
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Hello, respond with 'Connection successful'"
)
print(response.text)
# 期待する出力: Connection successful基本的な翻訳リクエストの実装
Gemini API で翻訳を行う場合、System Instructions に翻訳ルールを、ユーザーメッセージに原文を渡すのが基本パターンです。
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
def translate_text(text: str, target_lang: str, glossary: dict = None) -> str:
"""Gemini API を使ってテキストを翻訳する"""
# 用語集がある場合はルールに追加
glossary_rules = ""
if glossary:
terms = "\n".join(f"- {k} → {v}" for k, v in glossary.items())
glossary_rules = f"\n\n## 用語集(必ず以下の訳語を使用すること)\n{terms}"
system_instruction = f"""あなたはプロフェッショナルな翻訳者です。
以下のルールに従って翻訳してください。
## 基本ルール
- 原文のニュアンスとトーンを維持する
- 技術用語は対象言語で一般的な表記を使用する
- マークダウン記法やHTMLタグはそのまま保持する
- コードブロック内のコメントのみ翻訳し、コード自体は変更しない
- 翻訳結果のみを返し、説明や注釈は付けない
## 対象言語
{target_lang}{glossary_rules}"""
response = client.models.generate_content(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.3, # 翻訳の一貫性を高めるため低めに設定
),
contents=text,
)
return response.text
# 使用例
source = "Gemini API makes it easy to build intelligent applications."
result = translate_text(
text=source,
target_lang="日本語",
glossary={"intelligent applications": "インテリジェントアプリケーション"}
)
print(result)
# 期待する出力: Gemini API を使えば、インテリジェントアプリケーションを簡単に構築できます。temperature を 0.3 に設定しているのがポイントです。翻訳では創造性よりも一貫性が重要なため、低い値を指定して出力のばらつきを抑えます。
用語集(グロッサリー)を活用した品質管理
大規模なローカライゼーションプロジェクトでは、用語の統一が品質を左右します。JSON ファイルで用語集を管理し、翻訳時に自動的に適用するパイプラインを構築しましょう。
import json
from pathlib import Path
def load_glossary(glossary_path: str, target_lang: str) -> dict:
"""言語別の用語集を読み込む"""
path = Path(glossary_path)
if not path.exists():
return {}
with open(path, "r", encoding="utf-8") as f:
all_glossaries = json.load(f)
return all_glossaries.get(target_lang, {})
# glossary.json の例
# {
# "ja": {
# "machine learning": "機械学習",
# "fine-tuning": "ファインチューニング",
# "context window": "コンテキストウィンドウ",
# "grounding": "グラウンディング"
# },
# "fr": {
# "machine learning": "apprentissage automatique",
# "fine-tuning": "ajustement fin",
# "context window": "fenêtre de contexte"
# }
# }
glossary = load_glossary("glossary.json", "ja")
translated = translate_text(
text="Fine-tuning improves model performance within a specific context window.",
target_lang="日本語",
glossary=glossary
)
print(translated)
# 期待する出力: ファインチューニングにより、特定のコンテキストウィンドウ内でのモデル性能が向上します。用語集を外部ファイルで管理することで、翻訳チームとエンジニアリングチームが独立して用語を更新できるようになります。
バッチ翻訳で複数ファイルを一括処理する
実際のローカライゼーションでは、数十〜数百のファイルを一度に翻訳する必要があります。以下は、ディレクトリ内の Markdown ファイルを一括翻訳するスクリプトです。
import asyncio
import time
from pathlib import Path
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
async def translate_file(
source_path: Path,
output_dir: Path,
target_lang: str,
glossary: dict,
) -> dict:
"""1ファイルを翻訳して保存する"""
content = source_path.read_text(encoding="utf-8")
glossary_rules = ""
if glossary:
terms = "\n".join(f"- {k} → {v}" for k, v in glossary.items())
glossary_rules = f"\n\n## 用語集\n{terms}"
system_instruction = f"""プロフェッショナルな翻訳者として、
Markdownファイルを{target_lang}に翻訳してください。
- マークダウン構造(見出し・リスト・コードブロック)を保持
- フロントマター(YAML)の title と description のみ翻訳
- コードブロック内のコメントのみ翻訳{glossary_rules}"""
response = client.models.generate_content(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.3,
),
contents=content,
)
output_path = output_dir / source_path.name
output_path.write_text(response.text, encoding="utf-8")
return {
"file": source_path.name,
"status": "success",
"chars": len(response.text),
}
async def batch_translate(
source_dir: str,
output_dir: str,
target_lang: str,
glossary_path: str = None,
concurrency: int = 3,
):
"""ディレクトリ内の全 Markdown ファイルを一括翻訳"""
src = Path(source_dir)
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
files = list(src.glob("*.md")) + list(src.glob("*.mdx"))
glossary = load_glossary(glossary_path, target_lang) if glossary_path else {}
# 同時実行数を制限して API レート制限を回避
semaphore = asyncio.Semaphore(concurrency)
async def limited_translate(f):
async with semaphore:
result = await asyncio.to_thread(
lambda: asyncio.run(
translate_file(f, out, target_lang, glossary)
)
)
# API レート制限対策として少し待機
await asyncio.sleep(1.0)
return result
# ※ 実運用では asyncio.to_thread で同期呼び出しをラップ
results = []
for f in files:
r = translate_file(f, out, target_lang, glossary)
results.append(r)
time.sleep(1.0) # レート制限対策
print(f"翻訳完了: {len(results)} ファイル")
for r in results:
print(f" {r['file']}: {r['chars']} 文字")
# 実行例
# asyncio.run(batch_translate(
# source_dir="content/en",
# output_dir="content/ja",
# target_lang="日本語",
# glossary_path="glossary.json",
# ))concurrency パラメータで同時実行数を制御しています。Gemini API にはレート制限がありますので、無料プランでは concurrency=2、有料プランでは concurrency=5 程度を目安にしてください。
翻訳品質の自動チェック
翻訳後に品質を自動チェックする仕組みを組み込むと、レビュー工数を大幅に削減できます。Gemini API 自身に翻訳結果を評価させるアプローチが効果的です。
def check_translation_quality(
original: str,
translated: str,
target_lang: str,
) -> dict:
"""翻訳品質を自動チェックする"""
system_instruction = """あなたは翻訳品質の審査員です。
原文と翻訳文を比較し、以下の観点で評価してください。
評価結果は必ず以下のJSON形式で返してください:
{
"score": 1-10の整数,
"issues": ["問題点のリスト"],
"suggestions": ["改善提案のリスト"]
}
## 評価観点
- accuracy: 原文の意味が正確に伝わっているか
- fluency: 対象言語として自然な文章か
- terminology: 技術用語の訳語が適切か
- completeness: 情報の欠落や追加がないか"""
prompt = f"""## 原文
{original}
## 翻訳文({target_lang})
{translated}
上記の翻訳を評価してください。"""
response = client.models.generate_content(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.2,
response_mime_type="application/json",
),
contents=prompt,
)
return json.loads(response.text)
# 使用例
quality = check_translation_quality(
original="The context caching feature reduces API costs by up to 90%.",
translated="コンテキストキャッシュ機能により、APIコストを最大90%削減できます。",
target_lang="日本語",
)
print(f"スコア: {quality['score']}/10")
print(f"問題点: {quality['issues']}")
# 期待する出力:
# スコア: 9/10
# 問題点: []response_mime_type="application/json" を指定することで、Gemini API が必ず JSON 形式で応答を返してくれます。構造化出力について詳しく知りたい方は、Gemini 構造化出力の実践ガイドもご覧ください。
アプリのローカライゼーションファイルを一括変換する
モバイルアプリや Web アプリの i18n ファイル(JSON / YAML / .strings)を一括翻訳するユースケースも非常に多いです。以下は JSON 形式の i18n ファイルを翻訳するスクリプトです。
def translate_i18n_json(
source_json: dict,
target_lang: str,
glossary: dict = None,
) -> dict:
"""i18n JSON ファイルのバリュー部分のみを翻訳する"""
glossary_rules = ""
if glossary:
terms = "\n".join(f"- {k} → {v}" for k, v in glossary.items())
glossary_rules = f"\n\n## 用語集\n{terms}"
system_instruction = f"""あなたはアプリのローカライゼーション専門家です。
以下のJSON内の値(value)を{target_lang}に翻訳してください。
## ルール
- キー(key)は変更しない
- プレースホルダー({{name}} や %d など)はそのまま保持する
- UIテキストとして自然な長さに調整する(ボタンラベルは短く)
- 翻訳済みのJSONのみを返す{glossary_rules}"""
response = client.models.generate_content(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction=system_instruction,
temperature=0.2,
response_mime_type="application/json",
),
contents=json.dumps(source_json, ensure_ascii=False, indent=2),
)
return json.loads(response.text)
# 使用例
en_strings = {
"app.title": "My AI Assistant",
"app.welcome": "Welcome back, {{name}}!",
"button.submit": "Submit",
"button.cancel": "Cancel",
"error.network": "Network error. Please try again.",
"settings.language": "Language",
"settings.notifications": "Notifications",
}
ja_strings = translate_i18n_json(en_strings, "日本語")
print(json.dumps(ja_strings, ensure_ascii=False, indent=2))
# 期待する出力:
# {
# "app.title": "AI アシスタント",
# "app.welcome": "おかえりなさい、{{name}}さん!",
# "button.submit": "送信",
# "button.cancel": "キャンセル",
# "error.network": "ネットワークエラーが発生しました。もう一度お試しください。",
# "settings.language": "言語",
# "settings.notifications": "通知"
# }このスクリプトの重要なポイントは、プレースホルダー({{name}} や %d)を保持するよう System Instructions で明示していることです。ローカライゼーションで最もよくあるバグの一つが、プレースホルダーの欠落や変更です。
エラーハンドリングやリトライの実装パターンについては、Gemini API エラーハンドリング・リトライパターンで詳しく解説しています。
まとめ
Gemini API を活用した多言語翻訳・ローカライゼーションの自動化について、基本的な翻訳リクエストから用語集管理、バッチ処理、品質チェックまでを解説しました。
ポイントをおさらいすると、System Instructions でトーンと用語集を明示することで翻訳の一貫性が大幅に向上します。temperature は低め(0.2〜0.3)に設定し、response_mime_type="application/json" で構造化された出力を取得するのが実用的なパターンです。
より高度な翻訳パイプラインを構築したい方には、PDF や画像内テキストの翻訳も含めたマルチモーダルドキュメント処理の高度ガイドがおすすめです。