2

我正在使用集中式语言系统开发多语言应用程序。它基于每种语言的语言文件和一个简单的辅助函数:

en.php

$lang['access_denied'] = "Access denied.";
$lang['action-required'] = "You need to choose an action.";
...
return $lang;

language_helper.php

...
function __($line) {
  return $lang[$line];
}

到目前为止,所有字符串都是发送给当前用户的系统消息,因此我总是可以这样做。现在,我需要创建其他消息,其中字符串应取决于动态值。例如,在模板文件中,我想回显操作点的数量。如果用户只有 1 分,它应该回显“你有 1 分。”;但是对于零分或超过 1 分,它应该是“你有 12 分”。

出于替换目的(字符串和数字),我创建了一个新函数

function __s($line, $subs = array()) {
  $text = $lang[$line];
  while (count($subs) > 0) {
    $text = preg_replace('/%s/', array_shift($subs), $text, 1);
  }
  return $text;
}

调用函数看起来像__s('current_points', array($points)).

$lang['current_points']在这种情况下是"You have %s point(s).",效果很好。

更进一步,我想摆脱“(s)”部分。所以我创建了另一个函数

function __c($line, $subs = array()) {
  $text = $lang[$line];
  $text = (isset($sub[0] && $sub[0] == 1) ? $text[0] : $text[1];
  while (count($subs) > 0) {
    $text = preg_replace('/%d/', array_shift($subs), $text, 1);
  }
  return $text;
}

调用函数看起来仍然像__s('current_points', array($points)).

$lang['current_points']现在是array("You have %d point.","You have %d points.")

我现在如何结合这两个功能。例如,如果我想打印用户名和分数(比如排名)。函数调用类似于being __x('current_points', array($username,$points))$lang['current_points']array("$s has %d point.","%s has %d points.")

我尝试使用preg_replace_callback(),但无法将替代值传递给该回调函数。

$text = preg_replace_callback('/%([sd])/', 
  create_function(
    '$type',
    'switch($type) {
      case "s": return array_shift($subs); break;
      case "d": return array_shift($subs); break;
    }'),
  $text);

显然,$subs 没有定义,因为我收到“内存不足”错误,就好像函数没有离开 while 循环一样。

谁能指出我正确的方向?可能有一种完全不同(更好)的方法来解决这个问题。另外,我仍然想像这样扩展它:

$lang['invite_party'] = "%u invited you to $g party.";应该成为Adam invited you to his party."男性和"Betty invited you to her party."女性。两者的传递$subs$u$g将是一个用户对象。

4

3 回答 3

4

正如评论所提到的,我猜gettext()是另一种选择

但是,如果您需要其他方法,这里有一个解决方法

class ll
{
    private $lang = array(),
            $langFuncs = array(),
            $langFlags = array();

    function __construct()
    {
        $this->lang['access'] = 'Access denied';
        $this->lang['points'] = 'You have %s point{{s|}}';
        $this->lang['party'] = 'A %s invited you to {{his|her}} parteh !';
        $this->lang['toto'] = 'This glass seems %s, {{no one drank in already|someone came here !}}';

        $this->langFuncs['count'] = function($in) { return ($in>1)?true:false; };
        $this->langFuncs['gender'] = function($in) { return (strtolower($in)=='male')?true:false; };
        $this->langFuncs['emptfull'] = function($in) { return ($in=='empty')?true:false; };

        $this->langFlags['points'] = 'count';
        $this->langFlags['toto'] = 'emptfull';
        $this->langFlags['party'] = 'gender';
    }

    public function __($type,$param=null)
    {
        if (isset($this->langFlags[$type])) {
            $f = $this->lang[$type];
            preg_match("/{{(.*?)}}/",$f,$m);

            list ($ifTrue,$ifFalse) = explode("|",$m[1]);

            if($this->langFuncs[$this->langFlags[$type]]($param)) {
                return $this->__s(preg_replace("/{{(.*?)}}/",$ifTrue,$this->lang[$type]),$param);
            } else {
                return $this->__s(preg_replace("/{{(.*?)}}/",$ifFalse,$this->lang[$type]),$param);
            }
        } else {
            return $this->__s($this->lang[$type],$param);
        }
    }
    private function __s($s,$i=null)
    {
        return str_replace("%s",$i,$s);
    }
}

$ll = new ll();

echo "Call : access - NULL\n";
echo $ll->__('access'),"\n\n";
echo "Call : points - 1\n";
echo $ll->__('points',1),"\n\n";
echo "Call : points - 175\n";
echo $ll->__('points',175),"\n\n";
echo "Call : party - Male\n";
echo $ll->__('party','Male'),"\n\n";
echo "Call : party - Female\n";
echo $ll->__('party','Female'),"\n\n";
echo "Call : toto - empty\n";
echo $ll->__('toto','empty'),"\n\n";
echo "Call : toto - full\n";
echo $ll->__('toto','full');

这输出

Call : access - NULL
Access denied

Call : points - 1
You have 1 point

Call : points - 175
You have 175 points

Call : party - Male
A Male invited you to his parteh !

Call : party - Female
A Female invited you to her parteh !

Call : toto - empty
This glass seems empty, no one drank in already

Call : toto - full
This glass seems full, someone came here !

这可能会让您了解如何集中您的语言可能性,创建自己的函数来解析一个或另一个文本。

希望这对您有所帮助。

于 2012-10-03T15:09:12.847 回答
0

如果前一段时间做过这样的事情,但通过分离关注点避免了所有的陷阱。

在较低级别上,我在模板中注入了一个格式化程序,它负责处理特定于语言的所有内容。例如格式化数字或日期。它有一个带有三个参数的函数“plural”:$value、$singular、$plural,并根据返回的值返回后两者之一。它没有回显值本身,因为这是留给数字格式的。

整个翻译是在模板引擎中完成的。是Dwoo,它可以做模板继承,所以我设置了一个主模板,里面有所有的HTML结构,还有很多占位符。每种语言都继承了这个 HTML 母版,并用正确的语言输出替换了所有占位符。但是因为我们仍然处于模板引擎领域,所以可以“翻译”格式化程序函数的使用。Dwoo 将在第一次调用时编译模板继承,包括对格式化程序的所有后续调用,包括所有已翻译的参数。

性别问题将得到基本相同的解决方案:gender($sex, $male, $female),其中 $sex 是主题的性别,其他参数是男性或女性的措辞。

于 2012-10-03T14:44:31.133 回答
0

也许更好的方法是函数 t 在 Drupal 中使用的方法,看看:

http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7

http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/format_string/7

于 2012-10-03T14:56:07.063 回答