アプリを壊さずにPOファイルを翻訳する方法
TABLE OF CONTENTS
POファイルは一見シンプルなテキストファイルのように見えますが、翻訳された%s、不足している複数形、編集されたmsgidがアプリを壊すことがあります。このワークフローを使えば、gettextの構造を壊さずにユーザー向けの文字列だけを翻訳できます。
POファイル全体を通常のテキスト翻訳ツールに貼り付けてはいけません。POファイルはソースコードに近い存在です。単語は翻訳できますが、ファイル構造、プレースホルダー、コメント、複数形インデックスはそのまま残す必要があります。
方法1:POファイル翻訳ツールを使う
最速かつ安全な下訳が欲しい場合や、msgid / msgstrペアを手作業で編集したくない場合におすすめです。
-
元の
.poファイルをバックアップする。 翻訳に出す前に、リポジトリにクリーンなコピーを必ず保存しておきましょう。翻訳後のファイルが壊れた場合、正常なバージョンと比較するために必要です。 -
PO対応の翻訳ツールを開く。 gettextファイル専用のツール(例:OpenL PO Translatorなどの従量課金型ドキュメント翻訳ツール)を使いましょう。PO対応ツールは、ソース文字列、コメント、プレースホルダー、ファイル構造を維持したまま、対象文字列だけを翻訳します。ツール選びで迷っている場合は、おすすめPO翻訳ツールガイドも参考にしてください。
-
.poファイルをアップロードする。msgidとmsgstrエントリが含まれている言語ファイルを使います。.potテンプレートしかない場合は、まずターゲット言語用の.poファイルを作成してからアップロードしてください。 -
ソース言語とターゲット言語を選択する。 ソース言語は管理画面の言語ではなく、
msgid内のテキストの言語に合わせてください。たとえば、ファイル内のmsgidが英語で、スペイン語に翻訳したい場合は「英語→スペイン語」を選びます。 -
翻訳済みファイルをダウンロードする。 フレームワークが期待するロケール命名規則で保存しましょう。WordPressプラグインではテキストドメイン+ロケール形式が一般的で、Djangoでは通常
locale/<language>/LC_MESSAGES/以下にファイルを配置します。 -
リスクの高い文字列を最初に確認する。 翻訳済みファイル内で
%、{、}、<、>、msgid_plural、msgctxt、#, fuzzyを検索してください。これらは実行時の動作に最も影響を与える可能性が高いエントリです。 -
翻訳済みファイルをアプリでテストする。 言語ファイルをローカルで読み込み、翻訳された文字列が使われている画面を実際にクリックして確認しましょう。POファイルは翻訳が完了した時点で終わりではなく、アプリが正しく表示されることを確認して初めて完了となります。
方法2: PoeditでPOファイルを翻訳する
人によるレビューが必要な場合や、WordPressとの互換性、または一つ一つ丁寧に翻訳したい場合にこの方法を選んでください。
-
Poeditでファイルを開く。 PoeditはPOファイルや他のローカライズ形式に特化した翻訳エディタです。基本エディタは無料で利用でき、より高度なワークフロー向けに有料のPro機能もあります。WordPressの場合、公式のPolyglotsハンドブックによると、PoeditはPOTファイルから
.poおよび.moファイルを作成でき、複数形やUTF-8にも対応しています。 -
ソースが変更された場合はPOTテンプレートから更新する。 開発者がアプリのテキストを変更した場合は、翻訳前に最新の
.potファイルから.poファイルを更新してください。これにより、新規・削除・曖昧な文字列が可視化され、古いUIテキストがそのまま出荷されるのを防げます。 -
msgstrフィールドのみを翻訳する。msgidはアプリが翻訳を検索するための元の文字列です。通常のgettextワークフローでは、翻訳者はmsgidではなくmsgstrを編集してください。 -
プレースホルダーは完全にそのまま残す。
%s、%d、%1$s、{name}、%(count)s、:name、HTMLタグなどの変数は翻訳やスペースの変更をしないでください。語順を変える必要がある場合は、プレースホルダー全体を一つの単位として移動させてください。 -
複数形は個別に翻訳する。 複数形のエントリには
msgid、msgid_plural、複数のmsgstr[n]値が含まれます。ターゲット言語で必要なすべての複数形スロットを埋め、同じ文をすべてにコピーしないようにしましょう。 -
アプリが必要とする場合は
.moファイルを保存・コンパイルする。 一部の開発環境では開発中に.poファイルを直接読み込みますが、WordPress や多くの gettext システムでは実行時にコンパイル済みの.moファイルを使用します。Poedit では保存時に自動で.moをコンパイルできますし、Django ではdjango-admin compilemessagesコマンドでメッセージをコンパイルできます。 -
アップロード前に警告を解消する。 Poedit では警告アイコンが壊れたプレースホルダーや不足している変数、複数形の不一致などを示します。これらは WordPress、Django、Drupal、またはリリースブランチに翻訳をインポートする前に必ず修正してください。
方法3:ローカリゼーションプラットフォームを使う
複数の翻訳者、レビュワー、リリースマネージャーが同じ PO ファイルで作業する必要がある場合におすすめです。
-
gettext に対応したプラットフォームに PO ファイルをインポートする。 Weblate などのローカリゼーションプラットフォームは PO ワークフローに対応しています。チーム向けのローカリゼーションプラットフォームは有料の場合が多いですが、Weblate にはオープンソースのセルフホスト版もあります。コメント、ヘッダー、ファジーストリング、プレースホルダーの扱いはプラットフォームごとに異なるため、本番用ファイルをアップロードする前にフォーマット設定を確認してください。
-
プレースホルダーやタグのチェックを設定する。 printf 形式のプレースホルダー、名前付き変数、HTML/XML タグ、複数形の QA ルールを有効にしましょう。これらのチェックは通常のスペルチェックでは見逃されるミスを防ぎます。
-
開発者コメントを見える状態に保つ。 PO コメントにはソース参照や抽出された開発者ノート、フラグ、以前のソース文字列などのコンテキストが含まれます。「Open」のような短い UI ラベルが動詞、形容詞、メニューコマンドのいずれかである場合、翻訳者にはこうしたノートが必要です。
-
レビュー付きで翻訳メモリを活用する。 翻訳メモリは繰り返し出てくる UI 文字列に便利ですが、古い翻訳が新しい文脈にそのままコピーされることもあります。
msgctxtやソース参照、周囲の UI が変わった場合は再利用された文字列を必ずレビューしましょう。 -
PO ファイルをエクスポートし、ローカルでチェックする。 エクスポート結果を鵜呑みにしないでください。翻訳済みファイルをアプリに戻し、必要ならコンパイルし、画面をテストしてからマージしましょう。
絶対に破ってはいけない PO ファイルのルール
| PO項目 | 翻訳するか? | 安全な例 | 重要な理由 |
|---|---|---|---|
msgid | いいえ | msgid "Save changes" | アプリはこのソース文字列を多くのgettextワークフローで検索キーとして使用します。 |
msgstr | はい | msgstr "Guardar cambios" | これはユーザーが見る対象言語のテキストです。 |
msgctxt | いいえ | msgctxt "button" | コンテキストは同一のソース文字列の意味を区別します。 |
%s, %d, %1$s | いいえ | Hello, %s -> Hola, %s | 実行時コードがこれらのプレースホルダーを実際の値に置き換えます。 |
{name}, %(count)s, :name | いいえ | Welcome, {name} | 名前付き変数はアプリコードと一致している必要があります。 |
| HTMLタグ | 通常は不要 | <strong>Warning</strong> | テキストのみ翻訳し、タグ構文はそのままにします。 |
msgid_plural | いいえ | msgid_plural "%d files" | ソースの複数形は元のコードパスに属します。 |
msgstr[0], msgstr[1] | はい、慎重に | msgstr[0] "%d file" | 各対象言語には独自の複数形ルールがあります。 |
#, fuzzy | まず確認 | #, fuzzy | Fuzzyは翻訳が古い、または未確認であることを示します。 |
#. 開発者コメント | 通常は不要 | #. Button label | これらのメモは翻訳者がコンテキストを理解する助けになります。 |
クイック例:安全なPO翻訳と壊れたPO翻訳
通常のgettextエントリは以下の通りです:
#. %s はユーザーの表示名です。
#, c-format
msgid "Welcome back, %s"
msgstr ""
安全なスペイン語訳では %s をそのまま残します:
#. %s はユーザーの表示名です。
#, c-format
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, %s"
壊れた翻訳はプレースホルダーを変更しています:
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, % s"
この小さなスペースが問題になることがあります。GNU msgfmt --check-format は % プレースホルダーの誤りなどフォーマット文字列の不一致を検出するために設計されており、Poeditも一般的なプレースホルダーの問題について警告します。翻訳せずにそのまま残すべき文字列のより広いリストについては、翻訳してはいけないものガイドをご参照ください。
翻訳済みPOファイルのチェック方法
- gettext がインストールされている場合は、gettext のバリデーションを実行します。
msgfmt --check --check-format -o /tmp/messages.mo path/to/messages.po
このコマンドは構文、ヘッダー、フォーマット文字列をチェックし、ファイルが有効な場合は一時的なコンパイル済みカタログを書き出します。
- フレームワークが期待する方法でファイルをコンパイルします。
django-admin compilemessages
Django プロジェクトの場合、compilemessages は makemessages で作成された .po ファイルを gettext 用の .mo ファイルにコンパイルします。
- 未翻訳のエントリを検索します。
grep -n 'msgstr ""' path/to/messages.po
空の msgstr フィールドは未翻訳エントリのために意図的に残されている場合もありますが、リリース時に予期せぬものがないか確認しましょう。
- ファジィ(fuzzy)な文字列を検索します。
grep -n '#, fuzzy' path/to/messages.po
ファジィな文字列はリリース前に必ず人の目で確認してください。デフォルトでは、msgfmt は --use-fuzzy オプションを付けてコンパイルしない限りファジィ翻訳を使用しません。そのため、ファジィなエントリは最終的なカタログでは未翻訳文字列として扱われることがあります。
- 実際の UI でテストします。 フォーム、複数形カウント、エラーメッセージ、アカウントメニュー、決済フローなどを含む画面を開いて確認しましょう。PO ファイルのバリデーションはファイルの問題を検出しますが、不自然な表現や文字のはみ出し、文脈の不足などは UI テストでしか発見できません。
どの方法を使うべきか
| 状況 | 最適な方法 | 理由 |
|---|---|---|
| 1つのPOファイルの初稿がすぐに必要な場合 | POファイル翻訳ツール | 構造を保ったまま最速で作成可能 |
| WordPressプラグインやテーマを管理している場合 | Poedit | .moコンパイルを含むWordPressに馴染みのあるワークフロー |
| Djangoアプリを管理している場合 | PO翻訳ツールまたはPoedit、その後compilemessages | 翻訳自体は迅速だが、フレームワークのコンパイルが必要 |
| 多言語・複数レビュワーがいる場合 | ローカリゼーションプラットフォーム | 割り当て、履歴、QA、レビュー管理がしやすい |
| 開発者向けの文字列を翻訳する場合 | 機械翻訳後の人力レビュー | コード用語、プレースホルダー、文脈がより重要 |
| JSONやフロントエンドのi18nファイルもローカライズする場合 | フォーマット別のワークフローを利用 | POのルールはJSON、YAML、ICUメッセージには必ずしも適用されない |
プロジェクトでgettextのPOファイルとJSONロケールファイルを混在して扱う場合は、それぞれの構造を理解したツールで翻訳してください。POファイルはmsgidとmsgstrを中心に構成され、JSONローカライズはキーと値が中心です。このワークフローについては、2026年版おすすめJSON翻訳ツールガイドをご覧ください。
よくある質問
POファイルをGoogle翻訳で翻訳できますか?
個々のmsgstr値を一般的な翻訳ツールにコピーすることは可能ですが、POファイル全体をプレーンテキスト翻訳ツールにアップロードまたは貼り付けるのは危険です。一般的な翻訳ツールはmsgidやコメント、クォートのエスケープ、複数形インデックス、プレースホルダーなどを変更してしまう可能性があります。POファイル対応の翻訳ツール、Poedit、またはローカリゼーションプラットフォームを利用してください。
.po、.pot、.moの違いは何ですか?
.potはソースコードから抽出されたテンプレートファイルで、通常は元の文字列のみを含み、翻訳は含まれていません。.poは1つのターゲット言語用の編集可能な翻訳ファイルです。.moは多くのgettextベースのアプリが実行時に読み込むコンパイル済みバイナリカタログです。
msgidは翻訳すべきですか?
いいえ、通常のワークフローではそうしません。msgstr を翻訳してください。GNU gettext マニュアルでは、msgid は元の未翻訳文字列、msgstr はその翻訳と説明されています。msgid の文字列は gettext ツールによって生成・管理されます。
POファイルが有効かどうかを確認するには?
gettext が利用可能な場合は msgfmt --check --check-format を実行するか、Poedit でファイルを開くか、ローカライズプラットフォームのQAチェックを利用してください。その後、アプリ内でファイルをコンパイルしてテストします。バリデーションは必要ですが、UIテストの代わりにはなりません。
プレースホルダーを壊した場合はどうなりますか?
最良の場合、アプリに奇妙な文字列が表示されます。最悪の場合、実行時フォーマッターがエラーを投げることがあります。これは、翻訳後の文字列がコードから渡される変数と一致しなくなるためです。プレースホルダーは必ず完全なトークンとして移動し、翻訳や部分的な編集は絶対にしないでください。
OpenL で PO ファイルを翻訳できますか?
はい。OpenL PO Translator は gettext の .po ファイル用に作られており、100以上の言語で翻訳する際もプレースホルダーや変数をそのまま保持すると説明されています。従量課金制のドキュメント翻訳ワークフローを採用しているため、PO構造の維持を重視し、すべてを手作業で行うよりも素早く下訳を作りたい場合に便利です。.pot テンプレートしか持っていない場合は、OpenL を使う前にターゲット言語の .po ファイルを作成してください。
参考文献
- GNU gettext マニュアル: PO ファイル — PO ファイル形式に関する公式 gettext の解説。
- GNU gettext マニュアル: PO ファイルエントリ —
msgid、msgstr、コメント、フラグ、エントリ構造の情報源。 - GNU gettext マニュアル: 複数形エントリ — 複数形エントリの構造に関する情報源。
- GNU gettext マニュアル: msgfmt の使い方 —
msgfmt --checkやフォーマット文字列の検証についての情報源。 - OpenL PO Translator — プレースホルダーや変数を保持しながら
.poファイルを翻訳できる OpenL 製品ページ。 - Poedit — PO 翻訳エディタおよび Pro 版の公式 Poedit サイト。
- WordPress Polyglots Handbook: Poedit — Poedit の使い方、POT ファイル、PO ファイル、MO コンパイル、プレースホルダー警告に関する WordPress のガイド。
- Django ドキュメント: 翻訳 — メッセージファイルと翻訳のための Django ワークフロー。
- Django ドキュメント: compilemessages —
.poファイルを.moファイルにコンパイルする Django コマンドリファレンス。 - Drupal ドキュメント: PO および POT ファイル —
.po、.pot、コンテキスト、複数形、コメント、変数についての Drupal の解説。 - Weblate ドキュメント: GNU gettext PO — PO ヘッダー、以前のソース文字列、廃止された文字列、生成された MO ファイルに関するローカリゼーションプラットフォームの注意点。