解析php中的模板语言

时间:2015-01-16 11:14:17

标签: php parsing templates internationalization

前几天我从维基媒体基金会找到了jquery.i18n,可以翻译Welcome, $1Found $1 {{PLURAL:$1|result|results}}等字符串。

我想在PHP中重新创建该功能仅用于教育目的。

我能够创建一个解析像Welcome, $1这样的字符串的解析器,但现在我想重新创建第二个功能Found $1 {{METHOD:$1|parameters|...}},但我无法弄清楚如何创建一些功能来实现这一点

有人能把我推向正确的方向吗?我已经查看了jquery.i18n库的源代码,我不打算实现另一个现有的翻译库,只需自己创建一个。

这是我为简单的参数解析函数所获得的:

public function parse($message, $replacements)
{
    if (strrpos($message, '{{') === false) {
        return $this->simpleParse($message, $replacements);
    }
}

protected function simpleParse($message, $replacements)
{
    return preg_replace_callback('/\$(\d+)/', function ($match) use ($replacements) {
        $key = $match[1] - 1;
        if (isset($replacements[$key])) {
            return $replacements[$key];
        }

        return $match[0];
    }, $message);
}

1 个答案:

答案 0 :(得分:1)

这似乎运作良好:

function parse($msg, $args) {
    return preg_replace_callback('~{{(\w+):(.+?)}}|\$(\d+)~', function($m) use($args) {
        if(strlen($m[1]))
            return parse_func(
                strtolower($m[1]),
                explode('|', $m[2]),
                $args);
        return $args[$m[3] - 1];
    }, $msg);
}

function parse_func($name, $params, $args) {
    foreach($params as &$p) {
        if(preg_match('~^\$(\d+)$~', $p, $m))
            $p = $args[$m[1] - 1];
    }
    return call_user_func_array("handle_$name", $params);
}

function handle_plural($value, $sing, $plu) {
    return intval($value) > 1 ? $plu : $sing;
}

// works!

$msg = "Found $1 {{PLURAL:$1|mouse|mice}} and $2 {{PLURAL:$2|apple|apples}}\n";

print parse($msg, [1, 5]);
print parse($msg, [6, 1]);

我们的想法是立即更换所有东西(美元和大括号),并在替换功能中采取适当的措施。您可以通过定义其他handle_xxx函数来添加更多“方法”,例如“复数”。