多言語化:.poファイルのフォーマットについて調べてみた

WordPressを多言語化するにあたり、.moファイルが必要になりました。
このファイルは翻訳内容を記述した.poファイルにから生成するのですが、.poファイルの書き方がわからないので調べてみました。

仕様書はどこにある?

そもそも.poファイルから.moファイルへの変換は、gettextというツールが行っているようです。
Poeditなどのアプリは、内部でこのツールを呼び出しています。

そこでgettextのマニュアルを探してみると、ありました!
GNU gettext utilities

中身は英語です。
全て読むのは時間がかかるので、.poファイルに関する部分だけ読んでみました。

フォーマット概要

コメント

行頭に # があると、コメントとみなされます。
コメントにはいくつか種類があって、#に続く文字で判別されます。

■コメントの種類

文字 意味
' '(スペース) 翻訳者のコメント # translator-comments
'.'(ドット) プログラマーから翻訳者へのコメント #. extracted-comments
':'(コロン) ソースコードの参照先 #: xxx.php:111
','(カンマ) フラグ #, fuzzy
'|'(縦線) 未翻訳の文字 #| msgid xxxx

■フラグ

フラグはgettextツールで参照されます。
その意味ではコメントではありませんね。

次のようなフラグがあります。

フラグ 否定 意味
fuzzy なし 翻訳が正しくない可能性があるという意味
c-format あり 翻訳がc形式であるという意味
objc-format あり 翻訳がObjective C形式であるという意味
python-format あり 翻訳がPython形式であるという意味
python-brace-format あり 翻訳がPython brace形式であるという意味
java-format あり 翻訳がJavaのMessageFormat形式であるという意味
java-printf-format あり 翻訳がJavaのprintf形式であるという意味
csharp-format あり 翻訳がC#形式であるという意味
javascript-format あり 翻訳がJavaScript形式であるという意味
scheme-format あり 翻訳がScheme形式であるという意味
lisp-format あり 翻訳がLisp形式であるという意味
elisp-format あり 翻訳がEmacs Lisp形式であるという意味
librep-format あり 翻訳がlibrep形式であるという意味
ruby-format あり 翻訳がRuby形式であるという意味
sh-format あり 翻訳がShell形式であるという意味
awk-format あり 翻訳がawk形式であるという意味
lua-format あり 翻訳がLua形式であるという意味
object-pascal-format あり 翻訳がObject Pascal形式であるという意味
smalltalk-format あり 翻訳がSmalltalk形式であるという意味
qt-format あり 翻訳がQt形式であるという意味
qt-plural-format あり 翻訳がQt plural形式であるという意味
kde-format あり 翻訳がKDE形式であるという意味
boost-format あり 翻訳がBoost形式であるという意味
tcl-format あり 翻訳がTcl形式であるという意味
perl-format あり 翻訳がPerl形式であるという意味
php-format あり 翻訳がPHP形式であるという意味
gcc-internal-format あり 翻訳がGCC sources形式であるという意味
gfc-internal-format あり 翻訳がGNU Fortran Compiler sources形式であるという意味
ycp-format あり 翻訳がYCP形式であるという意味

最初のfuzzy以外は、先頭に 'no-' を付けることで否定の意味になります。

例:
#, no-c-format
→ 翻訳がc形式ではないという意味

この大量にある○○形式とは何かというと、ようするに文字の置き換えを想定しています。
置き換えのルールはプログラミング言語ごとに異なるため、「翻訳結果は〇〇という言語向けです」ということを明示しているわけです。

否定形は、翻訳結果が○○の形式に見えても、そうではないという意味で用いられます。

ヘッダー

.poファイルの先頭部分は、ヘッダーとして翻訳者やgettextツール、およびPoeditなど向けの情報が記述されます。

例としてWordPress の翻訳/国際化対応にある、POファイルのヘッダー情報を挙げてみます。

  • # LANGUAGE (LOCALE) translation for WordPress.
  • # Copyright (C) YEAR WordPress contributors.
  • # This file is distributed under the same license as the WordPress package.
  • # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
  • #
  • #, fuzzy
  • msgid ""
  • msgstr ""
  • "Project-Id-Version: WordPress VERSION\n"
  • "Report-Msgid-Bugs-To: \n"
  • "POT-Creation-Date: 2005-02-27 17:11-0600\n"
  • "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
  • "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  • "Language-Team: LANGUAGE <LL@li.org>\n"
  • "MIME-Version: 1.0\n"
  • "Content-Type: text/plain; charset=CHARSET\n"
  • "Content-Transfer-Encoding: 8bit\n"
AFFS Simple Code Viewer
Copy

ヘッダーコメント

まずはコメントで、翻訳ファイルについての情報が記述されています。
この部分は必須ではないですが、可能なら記述しておいた方がよさそうです。

ツールやアプリ向けの情報

mgsid と msgstr の行は必須です。
その後に続く行は、ツールやアプリ向けの情報です。

この情報には、次の表のようなエントリーがあります。

エントリー名 内容
Project-Id-Version 翻訳のプロジェクト名やバージョン
Report-Msgid-Bugs-To 文字列の問題点の報告先:メールアドレスやURL
POT-Creation-Date .potファイルの作成日時
PO-Revision-Date .poファイルの保存日時
Last-Translator 連絡先:名前とメールアドレス
Language-Team 言語の英語名と、言語チームのメールアドレスやURL
Language jaなどの言語コード
MIME-Version 1.0:MIMEのバージョン
Content-Type ファイルのエンコード情報
Content-Transfer-Encoding 8bit
Plural-Forms 複数形を使用するとき必要。こちら参照

この他にも、Poeditなどのアプリが独自に追加したものがあります。

Plural-Forms

翻訳で複数形を使用するとき、Plural-Formsが必要です。

例:
"Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n"

最初の nplurals=2; は、翻訳結果が2通りあるという意味です。
3通りあるときは、 nplurals=3; と記述します。

後に続く plural=n == 1 ? 0 : 1; はC言語の構文で、変数pluralに使用する文字のインデックスをセットしています。
変数nは、計算のもととなる数値です。

通常は、インデックス0に単数形の翻訳結果を、インデックス1に複数形の翻訳結果が用意されています。
この状態で1という数値が与えられた場合はインデックス0を、それ以外は1をセットする必要があります。
それを表した数式が、n == 1 ? 0 : 1; です。

この仕組みを利用すると、もっと多くのケース分けができます。

例えば次のような翻訳結果があるとします。

インデックス0: '0個'
インデックス1: '1つ'
インデックス2: '2通り'
インデックス3: 'たくさん'

3以上は'たくさん'を返すことにします。

このとき、Plural-Formsは次のような記述になります。
たぶん・・・(実際に試していないので、間違えていたらすみません)

"Plural-Forms: nplurals=4; plural=n <= 2 ? n : 3;\n"

翻訳データ:基本形

一対一の翻訳を行う場合、次のように msgidmsgstr を記述します。

  • msgid 'keyword'
  • msgstr 'キーワード'
AFFS Simple Code Viewer
Copy

msgid は、翻訳前の文字を記述します。
msgstr は、翻訳後の文字を記述します。

翻訳データ:コンテキスト

コンテキスト指定子msgctxtを使用すると、同じ msgid に対して複数の翻訳を記述できます。

  • #
  • msgctxt "morning"
  • msgid "Hello"
  • msgstr "おはよう"
  • #
  • msgctxt "afternoon"
  • msgid "Hello"
  • msgstr "こんにちは"
AFFS Simple Code Viewer
Copy

翻訳データ:複数形

複数形は、次のように記述します。

  • msgid "One Comment"
  • msgid_plural "%d Comments"
  • msgstr[0] "1件のコメント"
  • msgstr[1] "%d件のコメント"
AFFS Simple Code Viewer
Copy

msgid_pluralは、翻訳前の複数形です。

単数はmsgidを、複数形はmsgid_pluralを参考にして、翻訳します。

翻訳後はmsgstrの後に、[1]、[2]、[3]とインデックスを記述します。

アプリを使おう

Poeditというアプリを使うと、.poファイルの生成から.moファイルの作成までおこなえます。
.poファイルの仕様をしらなくても、問題ありませんでした。

Poeditの使い方。新規から作成してmoをテーマやプラグインに適用する方法