用 PHP 中的等效文本替换文本

Replace a text by it's equivalent in PHP

编辑: 我知道 gettext、i18n 和其他东西已经存在,但这是为了学习目的。

我正在研究一种方法来翻译我的网站,方法是使用包含不同语言的所需翻译的 .json 文件。

所以我做了一个 index.php 调用我的 class 函数 Parser::render($file),这是未完成的代码:

home.php:

<h1>{website.welcome}</h1>
<h2>{website.tagline}</h2>
<p>{website.home.introduction}</p>

lang-fr.json:

{
    "_lang":
    {
        "author": "ThanosS",
        "version": "0.0.3",
        "flag": "fr",
        "country": "France",
        "state": "100%"
    },

    "website":
    {
        "title": "Mon putain de site",
        "welcome": "Bienvenue",
        "tagline": "Je suis un texte en français.",

        "home":
        {
            "introduction": "Ceci est un exemple pour gérer les traductions sur un site web"
        }
    }
}

lang-en.json:

{
    "_lang":
    {
        "author": "ThanosS",
        "version": "0.0.2",
        "flag": "en",
        "country": "USA",
        "state": "100%"
    },

    "website":
    {
        "title": "My fucking website",
        "welcome": "Welcome",
        "tagline": "I'm a text in english.",

        "home":
        {
            "introduction": "This is an example to handle website translations properly"
        }
    }
}

Parser.class.php:

<?php
/**
*   Translation Example
*   @version   0.0.1
**/

class Parser
{
    private $langsPath = '';
    private $langsExt = 'json';
    private $currentLang = 'en';

    public function __construct($langsPath, $langsExt = 'json', $currentLang = 'en')
    {
        $this->langsPath = $langsPath;
        $this->langsExt = ($this->langsExt != $langsExt) ? $langsExt : $this->langsExt;
        $this->currentLang = ($this->currentLang != $currentLang) ? $currentLang : $this->currentLang;
    }

    public function render($file)
    {
        $cLang = json_decode($this->loadLangFile($this->currentLang));
        $cFile = $this->loadPageFile($file);

        $langInfos = $cLang->_lang;
        unset($cLang->_lang);

        if (preg_match_all('/{([^}].*)}/i', $cFile, $matches))
        {
            $keys = $matches[1];
            foreach ($keys as $value)
            {
                $indexs = explode('.', $value);



            }
        }

        return $parsedFile;
    }

    private function loadLangFile($lang)
    {
        return file_get_contents($this->langsPath.'lang-'.$lang.'.'.$this->langsExt);
    }

    private function loadPageFile($page)
    {
        return file_get_contents($page);
    }
}

我想找到一种方法将 {key.other.key} 转换为当前 lang 文件中的值(类似于 <?php echo $cLang->key->other->key; ?>

所以 Parser::render('home.php'); 应该 return :

<h1>Bienvenue</h1>
<h2>Je suis un texte en français</h2>
<p>Ceci est un exemple pour gérer les traductions sur un site web</p>

提前致谢,我在 2 天前进行了搜索,但我的大脑还没有进化到这样做:/

好的,所以你的问题是如何在解码的 json 结构中导航...

这是一个工作示例。没有实施错误处理以保持简单。它应该对您有所帮助 :-) 我保留了语言文件和 home.php 模板不变。以下 index.php 文件仅用于此演示,以使用下面的解析器 class。我略微整理了那个解析器 class 的实现。但基本上唯一的变化是我用直接调用 preg_replace_callback() 替换了你的 preg_match() 调用并将所需的字典导航编码为用作回调的匿名函数:

index.php:

<?php
require 'parser.class.php';
$parser = new Parser('./', 'json', 'fr');
$output = $parser->render('home.php');
echo $output;

parser_class.php:

<?php
class Parser
{
    const LANG_PATH = '.';
    const LANG_EXT  = 'json';

    private $langsPath = '';
    private $langsExt = 'json';
    private $langCode = 'en';
    private $langInfos = [];

    protected $dictionary;

    public function __construct($langCode = 'en')
    {
        $this->langCode = $this->langCode;
        $this->dictionary = $this->loadDictionary();
        $this->langInfos  = $this->dictionary;
        unset($this->dictionary->_lang);
    }

    public function render($file)
    {
        $rawPayload = file_get_contents($file);

        $transPayload = preg_replace_callback(
            '/({([^}]+)})/',
            function($match) {
                $matches = explode('.', $match[2]);
                $_p = &$this->dictionary;
                foreach ($matches as $step) {
                    if (property_exists($_p, $step)) {
                        $_p = &$_p->$step;
                    } else {
                        return '-- undefined i18n string --';
                    }
                }
                return $_p;
            },
            $rawPayload);

        return $transPayload;
    }

    private function loadDictionary()
    {
        // here a lot of error handling is required, probably throwing exceptions
        $langFilePath = sprintf('%s/lang-%s.%s', self::LANG_PATH, $this->langCode, self::LANG_EXT);
        $dictionaryContent = file_get_contents($langFilePath);
        return json_decode($dictionaryContent);
    }
}

您本人几乎就在那里,这就是为什么我坚持让您说明编码的实际问题是什么。但是我自己知道这些情况:几乎就在那里,一切都清楚了,除了... :-)

无论如何:这基本上归结为在解码字典中使用内部 "pointer"。您以贪婪的方式通过正则表达式提取可翻译的字符串。这些字符串被分解成 "dot notation" 的各个部分(您的方法)。这些部分 ("steps") 然后用于通过将指针向最终翻译的字符串进一步移动一步来在字典内导航。就这样。

玩得开心!