PHPのお手軽多言語対応改善版

以前の投稿の続きです。


早い話が、↓のようにすればいいのではと思います。もちろん本番ではファイルを分割して拡張、メンテしやすくすることが必要です。前回との差分としては、
– yamlではなく普通の多次元配列とした
– 想定されていない文字列が入ってもエラーにはならず、falseが返るようにした
– 想定されていない言語が入ったらenglishとして扱うようにした
– 一つのファイルにまとめた
– 命名をわかりやすくした
です。

<?php

<?php

$script_valid_languages = array('en', 'ja', 'fr');
$script_i18n['reset_password']['en'] = 'reset password';
$script_i18n['reset_password']['ja'] = 'パスワードを再設定';
$script_i18n['reset_password']['fr'] = 'réinitialiser le mot de passe';

class Localizer {

	private $target_language;
	private $script_i18n;

	public function __construct($target_language = 'en') {
		global $script_valid_languages;
		global $script_i18n;
		$this->target_language = in_array($target_language, $script_valid_languages) ? $target_language : 'en';
		$this->script_i18n = $script_i18n;
	}

	public function g($text) {
		return isset($this->script_i18n[$text][$this->target_language]) ? $this->script_i18n[$text][$this->target_language] : FALSE;
	}

}

$l1 = new Localizer('en');
var_dump($l1->g('reset_password'));
$l2 = new Localizer('ja');
var_dump($l2->g('reset_password'));
$l3 = new Localizer('fr');
var_dump($l3->g('reset_password'));

/* 想定されない文字列を代入してみる → FALSE が 返却されるはず */
var_dump($l3->g('invalid_text'));

/* 想定されていない言語を代入してみる → 自動的に english に変換する */
$l4 = new Localizer('de');
var_dump($l4->g('reset_password'));

実行結果
string(14) "reset password"
string(27) "パスワードを再設定"
string(30) "réinitialiser le mot de passe"
bool(false)
string(14) "reset password"

PHPのお手軽多言語対応

@2014-08-25
改善しました。
http://mitsuakikawamorita.com/blog/?p=2477
↑こちらです。
↓の内容は古いです。


PHPで英語と日本語の切り替えが出来るといいなと思ってあれこれ調べてみたのですが、

– gettextを使う
– フレームワークにおまかせ

がベストプラクティスのようです。gettextはいまいち分かりにくいですし、フレームワークは多言語対応以外の学習コストが高いですね。

というわけで、yamlとクラスを使って、言語切替がそこそこ簡単に出来る(と個人的には思える)ものを作ってみました(下の方にコードと実行例が書いてあります。エラー処理はしていないので、実運用の際はエラー処理を書く必要があります)。

端的に言えば、

– yamlで各言語毎に記述
– Langクラスを作成し、インスタンス生成の際に言語を指定して、getメソッドで取得

です。要はレイヤーを挟むわけです。もっともgettextもフレームワークも似たような仕組みのようですね。

蛇足:

わざわざyamlでなくても普通に多次元配列で書けば良い気もしてきました^^; yamlも大きくなればパースのコストもバカにならないでしょうし。

<?php
$script = array();
$script['reset_password']['en'] = 'reset password';
$script['reset_password']['ja'] = 'パスワードを再設定';
$script['reset_password']['fr'] = 'réinitialiser le mot de passe';
こんな感じで十分ですね。。。

コード
<?php

$yaml = <<<EOD
---
en:
  email: email
  password: password
  reset_password: reset password
jp:
  email: メール
  password: パスワード
  reset_password: パスワードをリセット
...
EOD;

class Lang {

	private $lang;
	private $scripts;

	public function __construct($lang) {
		global $yaml;
		$this->lang = $lang;
		$this->scripts = yaml_parse($yaml);
	}

	public function get($str) {
		return $this->scripts[$this->lang][$str];
	}

}

echo "-----多言語対応の試験 (enとjp)-----\n";
$lang = new Lang('en');
echo $lang->get('email') . "\n";
echo $lang->get('password') . "\n";
echo $lang->get('reset_password') . "\n";

echo "-----言語をen→jpに変更-----\n";

$lang = new Lang('jp');
echo $lang->get('email') . "\n";
echo $lang->get('password') . "\n";
echo $lang->get('reset_password') . "\n";


実行例:
-----多言語対応の試験 (enとjp)-----
email
password
reset password
-----言語をen→jpに変更-----
メール
パスワード
パスワードをリセット