機能プラグイン料金リソース
言語を変更
リソースDrupalの.poファイルをAIで翻訳する方法

Drupalの.poファイルをAIで翻訳する方法

SimplePoTranslate Team2026年6月6日
Drupalの.poファイルをAIで翻訳する方法

ほとんどの人は.poファイルをWordPressと関連付けますが、gettextフォーマットはWordPressよりも数十年古く、オープンソースの世界全体でインターフェース翻訳を支えています。Drupalはその最大の利用者の1つです。多言語対応のDrupalサイトを運営している場合、すべてのメニューラベル、フィールドの説明、エラーメッセージ、モジュール文字列は、WordPressと同じように.poファイルを介して処理されますが、プレースホルダーの表記法とインポートワークフローが異なります。そしてWordPressと同様に、サイトの文字列が数個を超えると、それらのファイルを手作業で翻訳することがボトルネックになります。

このガイドでは、DrupalをDrupalたらしめているものを壊すことなく、AIを使ってDrupalの.poファイルを翻訳する方法について説明します。Drupalの翻訳システム、文字列が実際にどこから来るのか、WordPressとは異なり絶対に保持しなければならないプレースホルダー構文、そして繰り返し可能なdrushコマンドを含む、完全なエクスポート、翻訳、再インポートのループについて詳しく見ていきます。

Drupalの翻訳システムの仕組み

Drupalは、コアのlocaleモジュール(現代のDrupalでは「インターフェース翻訳」と呼ばれることもあります)を通じてインターフェース翻訳を処理します。有効にすると、ソース文字列とその言語ごとの翻訳のデータベーステーブルを管理し、それらの翻訳を標準のgettext .poファイルとしてインポートおよびエクスポートできます。

管理インターフェースは/admin/config/regional/translateにあります。そこから、未翻訳の文字列を検索したり、インラインで編集したり、そして重要なことですが、.poファイルをインポートして翻訳を一括で読み込んだり、現在の状態を.poファイルにエクスポートしてオフラインで編集したりできます。このエクスポート/編集/インポートのサイクルこそが、私たちが最適化しようとしているワークフローです。

各プラグインやテーマがlanguages/ディレクトリに独自の.poファイルと.moファイルを同梱するWordPressとは異なり、Drupalはインターフェース文字列をデータベースに一元化し、.poファイルを交換形式として扱います。エクスポートし、ファイルで作業し、それをインポートし直します。WordPressが必要とするコンパイル済みの.moステップは内部的に処理されます。

文字列の出所

Drupalの文字列は3つの場所から生成され、完全な翻訳ではそれらすべてをカバーする必要があります。

  • コア:管理UI、フォーム、システムメッセージ用の数千の翻訳可能な文字列が同梱されています。
  • Contribモジュール(Views、Webform、Commerceなど)はそれぞれ、t()関数を通じて独自の文字列を登録します。
  • テーマ:テンプレート文字列、リージョンラベル、テーマ設定の説明に貢献します。

/admin/config/regional/translateからエクスポートする際、エクスポート範囲を翻訳済み、未翻訳、またはすべての文字列に設定できます。初めての翻訳パスでは、未翻訳の文字列のみをエクスポートすることで、残りの作業のみに焦点を絞った.poファイルが得られます。

この3つのソース構造の実用的な結果として、翻訳作業が真に「完了」することはありません。Contribモジュールを追加したり、新しい機能を有効にしたり、Drupalコアを更新したりするたびに、未翻訳のmsgidエントリが新しく locale テーブルに表示されます。これが、Drupalチームが翻訳を一度限りのローンチタスクとしてではなく、繰り返されるパイプラインとして扱う理由です。モジュールに触れるすべてのデプロイメントで同じエクスポート、翻訳、再インポートのループが実行され、そのループが速ければ速いほど、リリース間の翻訳負債の蓄積が少なくなります。

また、Drupalはコアおよび人気のcontribモジュールについて、コミュニティが提供する翻訳をlocalize.drupal.orgから自動的に取得できる点も注目に値します。これらは一般的な文字列をカバーしますが、カスタムモジュール、テーマ、またはサイトで実際に使用されているプロジェクト固有のフレーズをカバーすることはめったにありません。コミュニティ翻訳と完全にローカライズされたサイトとの間のギャップは、AIのパスによって迅速に埋められる作業です。

DrupalのプレースホルダーはWordPressのプレースホルダーではありません

Drupalの.poファイルをAI翻訳ツールに送信する前に理解すべき最も重要な点は次のとおりです。Drupalは、WordPressで主流のprintfスタイルの%s%1$sプレースホルダーを使用しません。Drupalのt()関数は、それぞれ異なるエスケープ動作を持つ3つの異なるプレースホルダープレフィックスを使用します。

  • @variable — 値はHTMLエスケープされ、ユーザー提供テキストの安全なデフォルトです。
  • %variable — 値はエスケープされ、<em>強調マークアップで囲まれます。
  • :placeholder — URL属性に使用され、URLサニタイズが適用されます。

典型的なDrupalのソース文字列は、エクスポートされた.poファイルで次のようになります。

#: core/modules/node/node.module
msgid "@count comments"
msgid_plural "@count comments"
msgstr[0] ""
msgstr[1] ""

#: core/modules/user/user.module
msgid "Welcome @name, you last logged in on %date."
msgstr ""

翻訳者が@count@cuentaに変更したり、@nameを「name」の翻訳語に置き換えたり、@count@ countにするスペースを挿入したりすると、プレースホルダーはt()呼び出しが渡すものと一致しなくなります。するとDrupalは、実際の数値の代わりにリテラルトークン@countをページに出力します。翻訳は完了しているように見えますが、サイトは明らかに壊れています。

これはWordPressの%s文字列に影響するバグと同じ種類のもので、その一般的な原則については、コード変数と破損せずにPOファイルを翻訳する方法で詳しく説明しています。Drupalのひねりは、プレースホルダーのスタイルが1つではなく3つあり、翻訳ツールがそれらすべてを認識する必要があるという点です。

なぜ一般的な翻訳ツールはここで失敗するのか

そのnode.module文字列を消費者向けの機械翻訳ボックスに貼り付けると、@countが破損したり、<em>で囲まれた%dateが異なるトークンにローカライズされたり、複数形が1つにまとめられたりすることがよくあります。これらのツールのいずれもgettextのセマンティクスを念頭に置いて構築されていません。それらはテキストを翻訳するだけであり、@countがアプリケーションコードとの契約であることを理解していません。

構文ロックを備えたgettext対応の翻訳パイプラインは、@variable%variable、および:placeholderを不変のトークンとして扱います。これらは翻訳前にロックされ、翻訳後に復元されるため、周囲の文は翻訳されますが、プレースホルダーはそのまま通過します。同じロックはWordPressの%s%1$s、i18nextの{{name}}、およびインラインHTMLにも適用されるため、単一のツールでDrupal、Symfony、LaravelプロジェクトをWordPressプロジェクトと同じくらい簡単に処理できます。msgid_pluralを介したDrupalの複数形は、平坦化されずに複数形として保持されます。これは、Drupalの言語には1つから6つの複数形バリアントがあるため重要です。

見過ごされがちな、より巧妙な失敗モードもあります。Drupalの文字列は、翻訳可能なテキスト内にRead the <a href=":url">documentation</a>のようにインラインマークアップやリンクを埋め込むことがよくあります。ここで:urlはプレースホルダーであり、<a>タグは維持されなければなりません。構造を理解していない翻訳ツールは、href属性を翻訳したり、閉じタグを削除したり、プレースホルダー名をローカライズしたりする可能性があります。文字列全体をユニットとして読み取るコンテキスト認識AIは、トークンロックと組み合わせることで、マークアップと:urlの契約の両方を無傷に保ちつつ、人間が読める「documentation」テキストのみを翻訳します。

エクスポート、翻訳、再インポートのループ

繰り返し可能なワークフローには3つのステージがあり、drushを使用するとエクスポートとインポートをスクリプト化できるため、毎回管理UIをクリックする必要がありません。

ステップ1:POファイルをエクスポートする

/admin/config/regional/translateのUIから、言語とエクスポート範囲を選択してエクスポートすることも、コマンドラインから行うこともできます。localeモジュールはDrupalの翻訳サービスを通じてエクスポートを公開しており、ほとんどのチームはこれをスクリプト化しています。翻訳のインポート(ステップ3で使用する逆の操作)をトリガーする典型的なdrushの呼び出しは次のようになります。

# Re-import a translated PO file for Spanish, overwriting customized strings
drush locale:import es /var/www/translations/es-untranslated.po \
  --type=customized --override=all

# Rebuild caches so the new strings render immediately
drush cache:rebuild

エクスポート側では、管理エクスポートフォームが.poファイルを生成します。多くのチームは、完全に自動化するために、localeエクスポートサービスを小さなカスタムDrushコマンドでラップしています。どちらの方法でも、未翻訳のmsgidエントリを含む標準のgettext .poファイルが得られます。

ステップ2:ファイルを翻訳する

これは、AIが何時間もの手動編集を置き換えるステージです。エクスポートした.poファイルをクラウド翻訳ツールにアップロードし、ターゲット言語を選択して処理させます。大規模サイト向けのDrupalの.poファイルは、コア、contrib、テーマを組み合わせると日常的に10MBを超えるため、ここではスマートバッチ処理が重要になります。ファイルは手動で分割したりサイズ制限に達したりすることなく、チャンクに分割され、翻訳され、再結合されます。出力は、すべてのmsgstrが埋められ、すべての@count%date、および:urlプレースホルダーが元の位置に正確に配置された完全な.poファイルです。

ステップ3:Drupalに再インポートする

翻訳されたファイルを/admin/config/regional/translateまたは上記のdrush locale:importコマンドを介してDrupalに再インポートし、キャッシュを再構築します。Drupalは翻訳を locale テーブルにマージし、文字列はサイト全体に即座に表示されます。モジュールを追加したり、コアを更新したりするたびに、新しい未翻訳の文字列が追加されるため、このループを再度実行してください。

インポートの重要な詳細が1つあります。--overrideフラグは、受信する翻訳が既存の翻訳を置き換えるかどうかを制御します。AI翻訳されたファイルを権威あるものにしたい場合は--override=allを使用し、Drupal UIで手動で調整した特定の文字列を上書きしたくない場合は、より保守的な設定を使用してください。ほとんどの自動化されたパイプラインでは、.poファイルを信頼できる情報源として扱い、すべてを上書きすることでシステムを予測可能に保ちます。つまり、バージョン管理下のファイルがサイトに表示されるものです。それ以上でもそれ以下でもありません。

複数のターゲット言語を持つ多言語サイトの場合、ループは言語ごとに1回実行されます。未翻訳のセットをエクスポートし、ドイツ語に翻訳してインポートします。再度エクスポートし、スペイン語に翻訳してインポートする、といった具合です。各言語が独立した.poファイルであるため、それらを並行して実行でき、クラウド翻訳ツールが同時に処理することで、かつては1週間の請負業者の作業だったものが午後の数時間で完了します。

DrupalのPOは数ある形式の1つ

gettextの.poファイルがDrupalの翻訳処理の唯一の方法ではないことにも注目する価値があります。設定およびコンテンツエンティティはXLIFFとしても交換できます。これは、プロの翻訳ベンダーのワークフローのためにTranslation Management Tool (TMGMT)モジュールが依拠する標準です。Drupalのローカライゼーションがインターフェースの.poファイルではなくXLIFFを介して実行される場合、プレースホルダーの保持原則は同じですが、ファイル構造が異なります。このパスについては、Drupal、Symfony、Angular用のXLIFFファイルを翻訳するで説明しています。

ただし、インターフェース翻訳レイヤーでは、.poファイルが主力であり続けています。エクスポート、AI翻訳、再インポートのループは、数日かかる手作業を数分の処理に変え、使用するツールがgettextのプレースホルダーを真に理解している限り、@variableの契約は損なわれず、Drupalサイトは出荷するすべての言語で破損することなく稼働し続けます。

単一の@variableを壊すことなく、Drupalの.poファイルを翻訳する準備はできましたか?SimplePoTranslateを無料でお試しください — クレジットカードは不要です。無料ティアでは、標準のgettext .poファイルと.potファイルを完全な構文ロックで処理するため、Drupalのプレースホルダーはコードが期待する通りに正確に通過します。