4

我正在开发一个需要多语言的 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!'] = '';

有没有人遇到过这种情况并可以帮助我解决这个问题?

非常感谢你。

亲切的问候,

马蒂厄

4

6 回答 6

11

是的,您并不是第一个遇到这种情况的人。:)

您可以为此使用古老的 gettext 系统,而无需发明自己的功能。然后你就可以使用了,这是一个命令行实用程序,可以使用函数xgettext来提取字符串。_()

如果您出于某种原因想推出自己的系统,最好的办法是编写一个 PHP 脚本,用于token_get_all标记源代码,然后检查标记并查找T_FUNCTION具有 value 的 s t

于 2012-08-13T16:03:01.430 回答
2

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

用法:

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

这会在目录中创建lang1.php, lang2.php,lang3.php文件./lang

于 2012-08-22T15:32:20.537 回答
2

无需重新发明轮子

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

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

这是翻译模板提取器的完整API 文档

于 2012-08-24T01:27:09.157 回答
0

你需要两个功能:

1- 扫描目录中的 php 文件。像这样

2-匹配您的 t 函数,grep 字符串并生成语言文件。像

  function genLang($file) {
    $content = file_get_contents($file);
    preg_match(...);
    foreach(...){
        echo(...);
    }
  }
于 2012-08-23T21:12:42.363 回答
0

Yii 框架也使用相同的功能,请参阅他们的 MessageCommand 类 https://github.com/yiisoft/yii/blob/master/framework/cli/commands/MessageCommand.php#L125

于 2012-08-24T20:04:32.743 回答
0

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

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

项目 1 更简单,但算法顺序为 2,1(项目 2 和项目 1)。对于这个简单的任务,您不需要正则表达式(重新发明 PHP 的“带占位符的字符串”)。

说明

对于第 1 项,最简单的方法是声明一个专门的函数来说“你好”,

// 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;
}
于 2012-08-24T22:04:45.270 回答