tohokuaikiのチラシの裏

技術的ネタとか。

Smartyを使ったPHPアプリケーションをgettextで国際化する

普通にpoeditとgettextで行けるでしょ、って思ったらそうでもなかったということで。

potファイルの作成

gettextは、「ソースコード」→「.potファイル」→「.poファイル」→「.moファイル」となり最終的には.moファイルを使う。

.potファイルができれば.moファイルはpoeditで作れる。ソースコードから.potを作るにはxgettextを使う。その辺りは下記のエントリ参照。

atyks.hateblo.jp

ただ、このxgettextはPHPやC、Javaなどのプログラミング言語のgettext用のキーワードを抜き出しているのだけど当然その中にPHP-Smartyは含まれていないのである。今時のフレームワークPHPをテンプレートとして使うものなら問題ないのだけど、LaravelなんかのBladeテンプレートもさてどうするんだろうという感じである。

同じことを考えてる人はいるもので・・・

正規表現Smartyテンプレートから抜き出すかなぁ・・・と考えてたんだけどこんなのを見つけた。

github.com

ということで取り組んでみる。

手順

Smartyにおけるgettextの適用

こんな感じ。Smartyブロックで囲む。

<{t}>This is English sentence.<{/t}>

<{t 1=$user_name}>You are Login as %1.<{/t}>

このSmartyブロックは、smarty-gettextにblock.t.phpというファイルがあるので、Smartyプラグインディレクトリにコピーしておく。

Smartyファイルからのpot作成

Smartyテンプレート内に前述のようにgettextを適用したら、smarty-gettextにあるスクリプト、tsmarty2c.phpを使う。

このファイルのSmartyの「デリミタ」「gettext用ブロックプラグイン」「テンプレート拡張子」を自分が使っているものに変更する。

<?php
// smarty open tag
$ldq = preg_quote('<{');

// smarty close tag
$rdq = preg_quote('}>');

// smarty command
$cmd = preg_quote('t');

// extensions of smarty files, used when going through a directory
$extensions = array('html');

対象となるディレクトリやファイルを指定してpotを作成する。対象が複数ある場合は引数をどんどんと伸ばしていく。

php tsmarty2c.php -o smarty.pot target/smarty/template/directory target/smarty/template/file1.tpl target/smarty/template/file2.tpl

PHPスクリプトからもpot作成

対象となるPHPスクリプトの一覧をtarget_phpfile.listにfind使って書き出して、xgettextコマンドの実行。

xgettext --language=PHP --from-code=utf-8 -f target_phpfile.list --keyword=__ -o php.pot

作った2つのpotを結合

Smarty由来のpotと、PHPスクリプト由来のpotを合体。

msgcat smarty.pot php.pot > php_smarty.pot

2回目からは、翻訳があるpoと結合してから

既に翻訳を始めていながら、新しくsmartyテンプレートやPHPプログラムが追加になった場合は、既に翻訳済みのpoと合体させる。

msgmerge php_smarty_prevous.po new_version.pot -o php_smarty.po

これでSmartyPHPで共通の.po/.moを使ったgettextの活用ができるようになる。