最近、ちょっと訳あって Codeigniter をいじってます。
すでに PHP が分かっていれば、学習コストも低く、直感的に使えるんでなかなか良いっすよ。
Codeigniter で、国際化するために用意されてる言語クラスですが、通常は以下のようにして使います。
application/language ディレクトリに各言語のサブフォルダ(例:japanese)を用意する。
その中に _lang.php (例:error_lang.php) というファイルを作成して、連想配列 $lang にテキストをセットする。
$lang['language_key'] = "実際に表示されるメッセージ";
Controller で言語ファイルを読み込む。
$this->lang->load('filename');
lang オブジェクトの line メソッドか、lang() 関数で、キーを指定してテキストを取得する。
$message = $this->lang->line('language_key'); // または echo lang('language_key');
ただ、これだとキーとの対比とか、メンテナンスがめんどくさいので、できれば .mo ファイル作って gettext() で処理したい所です。
幸い Codeigniter は、コアシステムクラスを簡単に拡張できます。
っつうわけで、言語クラス CI_Lang を拡張して gettext で言語リソースを扱えるようにしてみました。
まず、以下の内容で application/core/MY_Lang.php を作成します。
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); /** * Code Igniter Gettext Extension library * * This Library overides the original CI's language class. Needs the $config['language'] variable set as ja_JP or en_EN or fr_FR ... * * @package Gettext Extension * @author wokamoto * @copyright Copyright (c) 2012 * @license http://www.gnu.org/licenses/lgpl.txt * @link * @version Version 0.1 * @since 2012 January, 27th */ // ------------------------------------------------------------------------ class MY_Lang extends CI_Lang { private $gettext_language; private $gettext_codeset; private $gettext_domain; private $gettext_path; /** * The constructor initialize the library * * @return MY_Lang */ function __construct() { parent::__construct(); } /** * This method overides the original load method. Its duty is loading the domain files by config or by default internal settings. * * @access public * @param string $userlang the language, set as ja_JP or it_IT or en_EN or fr_FR ... * @param string $codeset the codeset, set as UTF-8 or EUC ... * @return bool */ public function load_gettext( $textdomain = false, $userlang = false, $codeset = false, $path = false ) { $config =& get_config(); $this->gettext_language = $userlang ? $userlang : $config['language']; $this->gettext_codeset = $codeset ? $codeset : $config['charset']; $this->gettext_domain = $textdomain ? $textdomain : $this->gettext_domain; $this->gettext_path = $path ? $path : APPPATH.'language/locale'; /* put env and set locale */ putenv("LANG={$this->gettext_language}"); setlocale(LC_ALL, $this->gettext_language); /* bind text domain */ bindtextdomain($this->gettext_domain, $this->gettext_path); bind_textdomain_codeset($this->gettext_domain, $this->gettext_codeset); textdomain($this->gettext_domain); return true; } /** * Fetch a single line of text from the language array * * @access public * @param string $line the original string to translate * @param array $params the plural parameters * @return string translated */ public function line($line = '', $params = FALSE) { if ( $params !== FALSE || FALSE === ($value = parent::line($line)) ) $value = $this->_trans( $line, $params ); return $value ? $value : $line; } /** * Plural forms added by Tchinkatchuk * http://www.codeigniter.com/forums/viewthread/2168/ */ /** * The translator method * * @access private * @param string $original the original string to translate * @param array $aParams the plural parameters * @return string translated */ private function _trans( $original, $aParams = false ) { if ( !isset($this->gettext_domain) ) return false; if ( $aParams && isset($aParams['plural']) && isset($aParams['count']) ) { $sTranslate = ngettext($original, $aParams['plural'], $aParams['count']); $sTranslate = $this->replaceDynamically($sTranslate, $aParams); } else { $sTranslate = gettext( $original ); if ( is_array($aParams) && count($aParams) ) { $sTranslate = $this->replaceDynamically($sTranslate, $aParams); } } return $sTranslate; } /** * Allow dynamic allocation in traduction * * @access private * @param string $sString * @return string */ private function replaceDynamically($sString) { $aTrad = array(); for ( $i=1, $iMax = func_num_args(); $i<$iMax; $i++) { $arg = func_get_arg($i); if (is_array($arg)) { foreach ($arg as $key => $sValue) { $aTrad['%'.$key] = $sValue; } } else { $aTrad['%'.$key] = $arg; } } return strtr($sString, $aTrad); } }
そんで、application/language ディレクトリに、以下のようにファイルを言語リソースを配置。
language
+ locale
+ ja_JP (ロケール: ja_JP or en_EN or fr_FR …)
+ LC_MESSAGES
– lang.mo
– lang.po
これを、実際に使う時は以下のようにします。
Controller で言語ファイルを読み込む。
$this->lang->load_gettext('lang', 'ja_JP');
※第一引数は textdomain、第二引数はロケール。
後は、同じように使えます。
$message = $this->lang->line('Hello World!'); // または echo lang('Hello World!');
WordPress で慣れてるんで gettext 使いたいすよね。