在 php 中搜索函数调用以生成翻译文件


Search for function call in php in order to generate a translation file

我正在开发一个需要多语言的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来标记源代码,然后浏览令牌并查找值为tT_FUNCTION

无需重新发明轮子

Drupal使用相同的t()函数进行本地化,potx模块是你的朋友。

如果您还没有或想要安装 drupal 实例,您可以查看 potx.inc 文件并在脚本中重用它。

以下是翻译模板提取器的完整 API 文档。

试试这个脚本 http://pastie.org/4568713

用法:

php script.php ./proj-directory lang1 lang2 lang3

这将在目录中创建lang1.phplang2.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

你需要的是一个(非常简单的)"模板系统",但你的问题中有两个模板实例。

  1. 将"Hello $X!"转换为"Hello Jonh!"或"Hello Maria!",设置$X(PHP 在字符串声明中为您执行此操作)。
  2. 选择适当的模板:"Hello $X!"表示英语,"¡Hola $X!"表示西班牙语。
第 1 项比较

简单,但算法顺序为 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;
}