最近のPHPフレームワークでは日本語・英語・など言語サイトを作成するための設定があらかじめ用意されています。
・PHPフレームワーク「Laravel」の多言語ファイル階層
/resources
/lang
/en
messages.php
/ja
messages.php
・Laravelの言語ファイル messages.php の中身
単純に配列を return しているだけです。
<?php
return [
'lang01' => 'Welcome to our application'
];
・PHPフレームワーク「CodeIgniter」の多言語ファイル階層
/application
/language
/en
myapp_lang.php (【任意の名前】_lang.php )
/ja
myapp_lang.php (【任意の名前】_lang.php )
・CodeIgniterの言語ファイル XXXXX_lang.php の中身
$lang連想配列に値をセットしているだけです。
<?php
$lang['lang01'] = 'Hello';
<?php
$lang['lang01'] = 'こんにちは';
こうやって、言語ファイルの数だけ設定ファイルを用意しておいて、使用する言語(ロケール)を設定ファイルで指定したり、動的に変更したりして多言語対応サイトが出来上がります。
が、実際に 作業を行ってみると(と、いいますか行ってみるまでもなく)次のような問題が発生します。)
● 言語ファイルを手動で作成・検証するのは非常に面倒である
言語ファイルには、言語テキストごとに変数( 上の例で言うと ‘lang01’ )を付ける必要があります。
これを言語ファイルごとにつけて回るだけでも相当な手間ですし、検証時には対応する変数名があっているかどうかもチェックしなくてはなりません。
また、翻訳テキストが全て一気に出揃うことはまれなので、どのテキストがまだ翻訳前なのかをチェックするだけでも一苦労です。
● 言語ファイルは自動で作成しよう
そこで、次の PHP スクリプトを使用して言語ファイルを自動に生成します。
CodeIgniter用ですが、最後の行に return $lang; とすると、Laravelでも使用できます。
● 言語ファイル用エクセルファイルを用意する
このようなエクセルファイルを作成します。
● 言語ファイルコンバートPHPスクリプト ci_lang_conv.php
ci_lang_conv.php
<?php
require_once __DIR__ . '/vendor/autoload.php';
/**
* excelファイルからCodeIgniter用の言語ファイルを生成します
*
* @version 0.03 言語データが無い時にエラー表示するように
* @version 0.04 言語データにクォーテーションが入っていた時の不具合修正
*/
// ===================== 設定 =====================
// 生成する CodeIgniterの言語ファイル格納ディレクトリ
$ci_lang_dir = '../../../codeigniter/application/language';
// ファイル名取得カラム
$lang_file_name_col = 'B'; // 列名(A〜Z)
$lang_file_name_row = 1; // 行名(1〜999)
// データヘッダ行
$data_header_col = 'B'; // 列名(A〜Z)
$data_header_row = 2; // 行名(1〜999)
// データ開始行
$data_start_row = 3; // 行名(1〜999)
// データエラー時の挙動( view_error:エラーを表示する )
$on_data_error = 'view_error';
// ===================== 設定 =====================
// ディレクトリが存在しなければエラーとする
if( ! file_exists($ci_lang_dir) ){
die ("ディレクトリ({$ci_lang_dir})が存在しません");
}
print "<pre>\n";
$data = excel_dump('lang.xls'); // 配列は [1] からはじまる。
// 変数名に重複がないかチェックする
check_variable_duplication( $data );
// 指定した列と行から、生成する言語ファイル名を取得し、「ディレクトリ」、「中身がからのファイル」を作成する
$lang_file_name_line = $data[$lang_file_name_row];
$data_header_line = $data[$data_header_row];
foreach ($lang_file_name_line as $column_name => $vv) {
if ( strcmp($column_name,$lang_file_name_col)==0 ){
$filename = $vv; // myapp_lang.php
}
}
$skip_flag = 1;
foreach ($data_header_line as $column_name => $vv) {
if ( strcmp($column_name,$lang_file_name_col)==0 ){
$skip_flag = 0;
}
if ( $skip_flag == 0 ){
// ディレクトリが存在しなければ作成
$lang_name = $vv;
if( ! file_exists("{$ci_lang_dir}/{$lang_name}") ){ mkdir("{$ci_lang_dir}/{$lang_name}"); }
// ファイルが存在しなければ作成
$php_filename = "{$ci_lang_dir}/{$lang_name}/{$filename}";
echo "ファイル({$php_filename})を作成します<br>\n";
if( ! file_exists($php_filename) ){ touch($php_filename); }
// CSVファイルから言語ファイルを生成する
$php_source = "<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); \n\n";
$php_source .= "// generated by ci_lang_conv (c) https://econosys-system.com/ " . date('Y/m/d H:i:s') . "\n\n";
$i = 0;
foreach ($data as $data_k => $data_v) {
if ( $i == 0 ){ $i++; continue; }
$param_name = $data_v['A'];
if ( ! $param_name ){ $php_source .= "\n"; continue; }
$value = $data_v[$column_name];
if ( ! $value ){
if ( strcmp($on_data_error,'view_error')==0 ){
$value = "<span style=\"color:red;\">{$param_name}</span>";
}
} else {
// $value = addslashes($value);
$value = preg_replace("/'/","\'",$value);
}
$comment = '';
$header = '';
if ( $_GET['comment_flg']==1 ){
$comment = "<!--( {$lang_name} : {$param_name} )-->";
}
if ( isset($_GET['header']) ){
$header = $_GET['header'];
}
if ( isset($_GET['footer']) ){
$footer = $_GET['footer'];
}
$php_source .= <<< DOC_END
\$lang['{$param_name}'] = '{$header}{$value}{$footer}{$comment}';
DOC_END;
}
print_r($php_source);
$tmp_filename = getmypid().'.tmp';
$fp = fopen($tmp_filename, 'w') or die("can not open tmp_file :{$tmp_filename}");
fwrite($fp, $php_source);
fclose( $fp );
rename($tmp_filename, $php_filename) or die("can not rename tmp_file :{$tmp_filename} :{$php_filename}");
echo "\n<h2>CSV to CodeIgniter language file convert done !!<br> lang:({$lang_name})<br> file:({$php_filename}) </h2><br>\n\n";
echo "<hr>";
}
}
function check_variable_duplication( $data=array() )
{
$error_array = array();
$check_array = array();
$error_flag = false;
for ($i=0; $i < count($data); $i++) {
if ( $i < 2 ){ continue; } // 最初の2行はスキップする
$h = $data[$i];
if ( strcmp($h['A'],'')==0 ){ continue; } // 変数名がカラの場合はスキップする
if ( in_array($h['A'],$check_array) ){
array_push($error_array, $h);
echo ("<b style='color:red;'>エラー : {$h['A']} </b>は既に登録があります。<br>");
$error_flag = true;
}
array_push($check_array, $h['A']);
}
if ( $error_flag ){
print_r($error_array);
}
}
function excel_dump($path)
{
$excel = PHPExcel_IOFactory::createReader('Excel5');
$book = $excel->load($path);
$sheet = $book->getActiveSheet();
return $sheet->toArray(null, true, true, true);
}
● 言語ファイルコンバータの使い方
WEBから使用します。ターミナルではありません。
・excelファイルから言語ファイルを生成する(ヘッダー : ■ フッター : □ )
http://YOUR_SERVER/ci_lang_conv.php?comment_flg=0&header=■&footer=□
テキストの先頭に ■
テキストの最後に □
をつけて言語ファイルから呼び出してきたテキストと、直接記述しているテキストの違いを見分けられるようにします。
・excelファイルから言語ファイルを生成する(テキストの後ろに変数名をコメントで埋め込みます)
http://YOUR_SERVER/ci_lang_conv.php?comment_flg=1
・excelファイルから言語ファイルを生成する(本番用)
純粋にテキストのみを生成します。
http://YOUR_SERVER/ci_lang_conv.php
以上です。
本ページ掲載のスクリプトはMITライセンスとしますので改変などはご自由にどうぞ。