我正在开发一个需要多语言的php网站。出于这个原因,我实现了一个具有以下标头的翻译函数:
function t($string, $replace_pairs = array(), $language = NULL)
基本上,这个函数在我的项目的多个文件中是这样调用的:
echo '<p>' . t('Hello world!') . '</p>';
$hello_String = t("Hello @name!", array('@name'=>$username));
我还没有生成翻译字符串,我想自动生成多个翻译文件(每种语言一个)。
我正在寻找的是一个bash程序(或单个命令,例如使用grep),它将查找对此t()函数的每次调用并生成具有以下结构的php文件:
<?php
/* Translation file "fr.php" */
$strings['fr']['Hello world!'] = '';
$strings['fr']['Hello @name!'] = '';
有没有人遇到过这种情况,可以帮助我解决这个问题?
谢谢。
亲切问候
马修
是的,你并不是第一个遇到这个问题的人。 :)
你可以为此使用古老的gettext系统,你不需要发明自己的函数。然后你会使用 xgettext
,这是一个命令行实用程序,使用 _()
函数提取字符串。
如果你想出于某种原因推出自己的系统,最好的办法是编写一个PHP脚本,该脚本使用token_get_all
来标记源代码,然后浏览令牌并查找值为t
的T_FUNCTION
。
无需重新发明轮子
Drupal使用相同的t()函数进行本地化,potx模块是你的朋友。
如果您还没有或想要安装 drupal 实例,您可以查看 potx.inc 文件并在脚本中重用它。
以下是翻译模板提取器的完整 API 文档。
试试这个脚本 http://pastie.org/4568713
用法:
php script.php ./proj-directory lang1 lang2 lang3
这将在目录中创建lang1.php
、lang2.php
lang3.php
文件./lang
你需要两个函数:
1-扫描PHP文件的目录。 像这样
2-匹配您的t函数,grep字符串并生成语言文件。
function genLang($file) {
$content = file_get_contents($file);
preg_match(...);
foreach(...){
echo(...);
}
}
Yii 框架也使用相同的功能,查看他们的消息命令类https://github.com/yiisoft/yii/blob/master/framework/cli/commands/MessageCommand.php#L125
你需要的是一个(非常简单的)"模板系统",但你的问题中有两个模板实例。
- 将"
Hello $X!
"转换为"Hello Jonh!
"或"Hello Maria!
",设置$X(PHP 在字符串声明中为您执行此操作)。 - 选择适当的模板:"
Hello $X!
"表示英语,"¡Hola $X!
"表示西班牙语。
简单,但算法顺序为 2,1(第 2 项为第 1 项)。对于这个简单的任务,你不需要正则表达式(重新发明PHP的"带占位符的字符串")。
说明
对于第 1 项,最简单的方法是声明一个专门的函数来表示"Hello",
// for any PHP version.
function template1($name) { return "<p>Hello $name!</p>";}
print template1("Maria");
对于第 2 项,您需要一个概括,PHP 也为您做,通过闭包,
header('Content-Type: text/html; charset=utf-8'); // only for remember UTF8.
// for PHP 5.3+. Use
function generalTemplate1($K) {
// $K was a literal constant, now is a customized content.
return function($name) use ($K) {return "<p>$K $name!</p>"; };
}
// Configuring template1 (T1) for each language:
$T1_en = generalTemplate1('Hello'); // english template
$T1_es = generalTemplate1('¡Hola'); // spanish template
// using the T1 multilingual
print $T1_en('Jonh'); // Hello Jonh!
print $T1_es('Maria'); // ¡Hola Maria!
如需更多模板,请使用 generalTemplate2()、generalTemplate3() 等; $T2_en
、$T2_es
、$T2_fr
、$T3_en
、$T3_es
等。
溶液
现在,为了实际使用,您喜欢使用数组...嗯,有一个数据结构问题,和更多的 1 级概括。成本是占位符的变量名称分析器。我将简单的正则表达式与 preg_replace_callback() 一起使用。
function expandMultilangTemplate($T,$K,$lang,$X) {
// string $T is a template, a HTML structure with $K and $X placeholders.
// array $K is a specific language constants for the template.
// array $lang is the language, a standard 2-letter code. "en", "fr", etc.
// array $X is a set of name-value (compatible with $T placeholders).
// Parsing steps:
$T = str_replace('{#K}',$K[$lang],$T); // STEP-1: expand K into T with lang.
// STEP-2: expand X into T
global $_expMultTpl_X; // need to be global for old PHP versions
$_expMultTpl_X = $X;
$T = preg_replace_callback(
'/@([a-z]+)/',
create_function(
'$m',
'global $_expMultTpl_X;
return array_key_exists($m[1],$_expMultTpl_X)?
$_expMultTpl_X[$m[1]]:
"";
'
),
$T
);
return $T;
}
// CONFIGURING YOUR TEMPLATE AND LANGUAGES:
$T = "<p>{#K} @name@surname!</p>";
$K = array('en'=>'Hello','es'=>'¡Hola');
// take care with things like "!", that is generic, and "¡" that is not.
// USING!
print expandMultilangTemplate(
$T, $K, 'en', array('name'=>'Jonh', 'surname'=>' Smith') );
print expandMultilangTemplate($T, $K, 'es', array('name'=>'Maria'));
我用 PHP5 测试了这个脚本,但它运行在较旧的 (PHP 4.0.7+) 上。
关于"多语言文件":如果您的翻译是文件,您可以使用类似
$K = getTranslation('translationFile.txt');
function getTranslation($file,$sep='|') {
$K = array();
foreach (file($file) as $line) {
list($lang,$words) = explode($sep,$line);
$K[$lang]=$words;
}
}
和一个文件
en|Hello
es|¡Hola
最简单的 PHP 5.3
如果你使用 PHP 5.3+,有一种简单优雅的方式来表达这个"最简单的多语言模板系统",
function expandMultilangTemplate($T,$K,$lang,$X) {
$T = str_replace('{#K}',$K[$lang],$T);
$T = preg_replace_callback(
'/@([a-z]+)/',
function($m,$X=NULL) use ($X) {
return array_key_exists($m[1],$X)? $X[$m[1]]: '';
},
$T
);
return $T;
}