ローカライズ
t()
関数
導入
ローカライズについてお話しする際、t()
関数が開発者が主に気をつけるべき関数です。
この関数は、一つ以上のパラメーターを許容します。最初のパラメーターは、翻訳すべき文字列です。例えば、キャンセルボタンは次のように記述することができます。
<button><?php echo t('Cancel'); ?></button>
concrete5 が自動的に Cancel を現在のユーザーの言語に翻訳してくれるわけです。いいでしょう?
パラメーター
しばしば、翻訳する文字列にダイナミックなコンテンツを挿入したい場合があります。
例を見てみましょう。もし $blockTypeName
がブロックタイプ名を格納している場合、次のようなコードを翻訳表示したいと思います。
echo 'Edit '.$blockTypeName;
そのまま考えると、 echo t('Edit '.$blockTypeName)
のように記述すれば良いと思うかもしれませんが、これは間違いです。なぜなら、翻訳する文字列は、変化してはいけないからです。また、 echo t('Edit').' '.$blockTypeName;
のように書きたいかもしれませんが、この方法も避けるべきです。なぜなら、すべての言語で 'Edit' の言葉がブロックタイプ名の前に来るとは限らないからです(例えば、ドイツ語では逆になります)。ですので、正しい方法は echo sprintf(t('Edit %s'), $blockTypeName);
という書き方になります。t
関数を使うと、PHP の sprintf 関数を使わずに、次のように記述することが可能です。
echo t('Edit %s', $blockTypeName);
翻訳する文字列に、複数の変数がある場合はどうでしょうか。このケースでは、言語によって言葉の順番が違うことに注意する必要があります。
例えば、次のようなメッセージを翻訳したいとしましょう。
echo 'Posted by '.$user.' on '.$date;
この場合、 echo t('Posted by %s on %s', $user, $date);
のように書くのではなく、
echo t('Posted by %1$s on %2$s', $user, $date);
のように数字をつけた引数を設定し、言語ごとに異なる順番で正しく翻訳することが可能になります。
PS: 変数のプレースホルダーの詳細は、PHPマニュアルの sprintf ページを参照ください。
コメント
パラメーターを使用する際は、翻訳者に変数プレースホルダーが何を意味しているのかを伝えるためにコメントを書くことができます。
コメントは、次のように、シンプルにPHPでコメントを記述すればOKです。
echo t(/*i18n %1$s is a user name, %2$s is a date/time*/'Posted by %1$s at %2$s', $user, $date);
これらのパラメーターが翻訳者に表示される際に、翻訳の手助けとなるでしょう。
t2()
関数
単数系とと複数形など、数字に依存した文字列を翻訳したい場合があると思います。良くある間違いとしては、シンプルにPHPの if-then-else で記述してしまうことです。
echo ($pages == 1) ? t('%d page', $pages) : t('%d pages', $pages);
この方法は、すべての言語が1かそれ以上という2つの複数形である場合にしか使えません。この過程は、誤りです。例えば、ロシア語は3つの複数形を持っていますし、フランス語では、単数系はゼロのときに使います。
このような理由で、複数形を翻訳する際は、 t()
関数ではなく、 t2()
関数を使います。この関数は、少なくとも3つのパラメーターをとります。
echo t2('%d page', '%d pages', $pages);
t2()
関数は、3つ目のパラメーター(この場合は $pages)に基づいて、正しい複数形を返します。さらに、sprintfが呼び出され、$pages が結果の文字列に挿入されます。
tc()
関数
しばしば、英語のテキストは複数の意味を持ち、複数の翻訳が存在する場合があります。例えば、set という言葉について考えてみましょう。この単語は実に様々な意味を持ちますので、様々な翻訳が存在します。どれが正しい翻訳でしょうか?それは、この単語が使われるコンテキストに依存します。tc()
関数を使うと、テキストのコンテキストを指定することが可能です。この関数は t()
関数と似ていますが、最初のパラメーターがコンテキストを表す文字列になります。例えば、
echo tc('A group of items', 'Set');
または
echo tc('Apply a value to an option', 'Set');
のように、同じ単語に複数のコンテキストを設定できます。コンテキストを使うことで、同じ英語のテキストに異なる翻訳を割り当てることが可能になります。コンテキスト以外のオプションを使用していないことに注意してください。Set という同じ単語に対して、英語のテキストを理解するのを助ける働きもあります。
おそらく、コンテキストを使うべきなのはいつなのかという疑問があると思います。コンテキストを使いすぎると、翻訳作業が不必要に増えていきます。tc()
をあまり使わないと、翻訳者を悩ませ、ウェブページにわかりにくい翻訳が増えることになります。
一般的に、翻訳されるテキストは長く(3つ以上の単語に)なりますので、そのテキスト自体がコンテキストを表しているため、コンテキストは必要にはなりません。短いテキストの場合は、コンテキストに依存します。単語が set のように複数の意味を持つときは、コンテキストを使うべきでしょう(つまり tc()
を使い t()
は使わない)。もし単語が OK のように複数の意味を持たない場合は、コンテキストを使わない方が良いでしょう。
何れにしても、翻訳者からのフィードバックに耳を傾けてください。正しい方法は、ひとつとは限らないのですから。
コアコンテキスト
翻訳上の問題を回避するため、concrete5 は次のコンテキストを実装しています。
AreaName
エリア名AttributeKeyName
属性キー名AttributeSetName
属性セット名AttributeTypeName
属性タイプ名BlockTypeSetName
ブロックセット名ConversationEditorName
エディター名ConversationRatingTypeName
会話の評価タイプ名FeedDescription
フィードの説明FeedTitle
フィードのタイトルGatheringDataSourceName
ギャザリングのデータソース名GatheringItemTemplateName
ギャザリングのアイテムテンプレート名GroupDescription
ユーザーグループの説明GroupName
ユーザーグループ名ImageEditorControlSetName
names of the control sets of the image editorImageEditorFilterName
names of the filters of the image editorJobSetName
names of the job setsPageTemplateName
names of the page templatesPageTypeComposerControlName
names of the controls of the page type composersPageTypeComposerControlTypeName
names of the types controls of the page type composersPageTypeComposerFormLayoutSetControlCustomLabel
names of the set of layouts of the page type composersPageTypeComposerFormLayoutSetName
names of the sets of page type composer formsPageTypePublishTargetTypeName
names of the targets of page typesPermissionAccessEntityTypeName
names of permission access entity typesPermissionKeyDescription
descriptions of permission keysPermissionKeyName
names of permission keysPresetName
names of style presetsSelectAttributeValue
values of the select attribute typesStyleName
names of the stylesStyleSetName
names of the set of stylesSystemContentEditorSnippetName
names of the snippets of the content editorTemplateFileName
names associated to template filesThumbnailTypeName
names of the types of the image thumbnailsTopic
topicsTopicCategoryName
names of the topic categoriesTopicName
topic namesTreeName
names of the trees
日付と時間
PHPでは、現在の月を表示したい場合に次のように記述できます。
echo date('F');
しかし、現在のサイトの言語に従った月の名前を取得するにはどうすれば良いでしょうか。
concrete5のテーマでは、日付についての記述を助ける Date ヘルパを使うことができます。使い方は次のようになります。
$dateHelper = \Core::make('helper/date');
ローカライズされた月の名前を取得するには、PHPのdate関数と同じように使うことができます。
echo $dateHelper->date('F');
これでOKです。このメソッドはPHPのdate関数と同じフォーマットの文字列をパラメーターとして受け付けます。
さらに、日付のフォーマットを指定したい場合があると思います。現在の日付を英語の長いフォーマットで表示するには、次のように記述することができます。
echo date('F d, Y');
おそらく、 $dateHelper->date('F d, Y');
のように記述することができるのではないかと思われるかもしれませんが、すべての言語で月を名前で表記し(F)、次に日付を表示し(d)、カンマの後に年を表示する(Y)わけではないため、これは誤りです。
正しい日付と時間のローカライズのためには、あらかじめ用意された Date ヘルパのメソッドを使用するのが良いでしょう。
$dateHelper->formatDate()
日付のみのフォーマット (リファレンス)$dateHelper->formatTime()
時間のみのフォーマット (リファレンス)$dateHelper->formatDateTime()
日付と時間のフォーマット (リファレンス)
Date ヘルパはその他にも便利な日付関連の機能を持っています。詳細はAPIドキュメントを参照ください。
パッケージの翻訳
パッケージを開発した?素晴らしい!世界を変えるための準備はほぼできたというわけです。実際に世界中で使われるようにするために、t()
関数で翻訳の準備も整えたとしましょう。
では次に?あなたの翻訳可能なパッケージが他の言語で表示されるには何をしたらいいのでしょうか。
PHPファイルから翻訳可能な文字列を抽出し、翻訳したい言語ごとに言語ファイルを作成する必要があります。
バージョン 5.7.5.4 から、concrete5 自身にこの作業をさせることができます。コンソールウィンドウを開き、次のコマンドを実行してください(Windowsの場合は / を ¥ に変更してください)。
PATH-TO-CONCRETE5-ROOT-FOLDER/concrete/bin/concrete5 c5:package-translate PACKAGE_HANDLE OPTIONS
詳細
PATH-TO-CONCRETE5-ROOT-FOLDER
は concrete5 がインストールされたディレクトリへのパスです。PACKAGE_HANDLE
はパッケージのハンドルです(または、パッケージを含むディレクトリのパスでも構いません)。OPTIONS
--help
で利用可能なオプションのリストを見ることができます。もっとも重要なものは--locale
(または短く-l
) で、作成したい言語を指定することができます。
例えば、 handyman
というハンドルでパッケージを開発していたとしましょう。翻訳を抽出しドイツ語とイタリア語の言語ファイルを作成したい場合は、次のコマンドを実行します。
concrete5 c5:package-translate handyman -l it_IT -l de_DE
このコマンドは次のファイルを生成します。
packages/handyman/languages/messages.pot
このファイルは gettext の Portable Object Template ファイルです。このファイルは、パッケージ内のすべての翻訳可能な文字列を含みます。このテンプレートファイルは新しい言語ファイルを作成するために使用できますが、コマンドで実行することもできますので、無視して構いません。packages/handyman/languages/it_IT/LC_MESSAGES/messages.po
このファイルはイタリア語に翻訳されるべき Portable Object ファイルです。packages/handyman/languages/it_IT/LC_MESSAGES/messages.mo
このファイルは .po ファイルがコンパイルされた Machine Object ファイルです。packages/handyman/languages/de_DE/LC_MESSAGES/messages.po
it_IT ディレクトリ内のファイルと同じですが、ドイツ語用です。packages/handyman/languages/de_DE/LC_MESSAGES/messages.mo
it_IT ディレクトリ内のファイルと同じですがドイツ語用です。
次に行うことは、翻訳者が .po ファイルを翻訳することです。UTF-8 をサポートした普通のテキストエディターも使えますが、専用のソフトを使う方が楽でしょう(例えば、POEdit, BetterPOEditor, など)。
concrete5 は .po ファイルを直接使うことはできないため、.mo ファイルにコンパイルする必要があります。コンパイルを行うためには、単に再度 c5:package-translate
コマンドを実行すればOKです(パッケージハンドルの指定だけで可能です)。
concrete5 c5:package-translate handyman
このコマンドは作成済みのイタリア語とドイツ語の .po ファイルを見つけ、.mo フォーマットにコンパイルします(別の c5:package-pack コマンドを使うこともできます)。
.po フィアルを困ぱいつしたら、concrete5 のキャッシュをクリアして、新しい翻訳を確認しましょう。キャッシュのクリアは、管理画面からか、 c5:clear-cache
コマンドで実行できます。
PS:パッケージを配信する際、concrete5 は .mo ファイルしか使用しないため、.pot ファイルと .po ファイルは削除して構いません。c5:package-pack
コマンドはそのように処理します。
原文:Localization