用原始语言切换gettext翻译语言

我用德语中的所有文本启动了我的PHP应用程序,然后使用gettext提取所有字符串并将它们翻译成英语。 所以,现在我有一个.po文件,其中包含德语中的所有msgids和英语中的msgstrs。我想切换它们,以便我的源代码包含英文为msgids,原因有两个: 更多的翻译人员会懂英语,因此只提供一个英文msgids的文件是合适的。我总是可以在我发出文件之前切换文件,然后收到它,但是naaah。 这会帮助我写英文对象&如果内容文本也是英文,则为函数名称和注释。我想这样做,所以该项目对其他开源合作者更开放(更有可能知道英语而不是德语)。 我可以手动执行此操作,这是一种任务,我预计它将花费更多时间为它编写一个自动例程(因为我对shell脚本非常糟糕)而不是手动执行。但我也期望鄙视手动计算机劳动的每一分钟(感觉就像矛盾,对吧?)就像我一直这样。 有人曾经这样做过吗?我认为这将是一个常见的问题,但找不到任何东西。非常感谢。 示例问题:
<title><?=_('Routinen')?></title>

#: /users/ruben/sites/v/routinen.php:43
msgid "Routinen"
msgstr "Routines"
我以为我会把问题缩小。 .po文件中的开关当然没有问题,就像它一样简单
preg_replace('/msgid "(.+)"nmsgstr "(.+)"/', '/msgid "$2"nmsgstr "$1"/', $str);
对我来说问题是在我的项目文件夹文件中搜索
_('$msgid')
并在解析.po文件时替换
_('msgstr')
的例程(在所有.po文件包含包含所有文件路径的注释之后,这可能不是最优雅的方式) msgid发生的地方)。 在akirk回答了一点之后,我遇到了一些问题。 因为我有
_('xxx')
_("xxx")
的混合,我必须小心(un)逃避。 msgstr和msgstrs中的双引号必须是非转义的,但不能删除斜杠,因为它可能是双引号也在PHP中被转义 单引号在被替换为PHP时必须进行转义,但是它们也必须在.po文件中进行更改。幸运的是,单引号只出现在英文文本中。 msgids和msgstrs可以有多行,然后它们看起来像这样  
msgid = ""
 
"line 1n"
 
"line 2n"
 
msgstr = ""
 
"line 1n"
 
"line 2n"
当然,复数形式被跳过了,但在我的情况下,这不是问题 poedit希望删除过时的字符串似乎已成功切换,我不知道为什么会在(很多)情况下发生这种情况。 我今晚必须停止工作。似乎仍然使用解析器而不是RegExps不会有点矫枉过正。     
已邀请:
请参阅http://code.activestate.com/recipes/475109-regular-expression-for-python-string-literals/以获取基于python的正则表达式,以查找字符串文字,并考虑转义。虽然它是python,但对于多行字符串和其他极端情况来说这可能相当不错。 请参阅http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/poswap.html,以获取.po文件的现成的,开箱即用的基本语言交换器。 例如,以下命令行将基于德语的西班牙语翻译转换为基于英语的西班牙语翻译。您必须确保在开始转换之前100%翻译您的新基本语言(英语):
poswap -i de-en.po -t de-es.po -o en-es.po
最后将英文po文件交换到德语po文件,使用swappo: http://manpages.ubuntu.com/manpages/hardy/man1/swappo.1.html 交换文件后,可能需要对结果文件进行一些手动抛光。例如,标题可能会被破坏,并且可能会出现一些重复的文本     
我建立在akirk的答案之上,并希望在这里保留我想出的答案,以防有人遇到同样的问题。 这不是递归的,但当然可以很容易地改变。随意改进评论,我将观看和编辑这篇文章。
$po = file_get_contents("locale/en_GB/LC_MESSAGES/messages.po");

$translations = array(); // german => english
$rawmsgids = array(); // find later
$msgidhits = array(); // record success
$msgstrs = array(); // find later

preg_match_all('/msgid "(.+)"nmsgstr "(.+)"/', $po, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    $german = str_replace('"','"',$match[1]); // unescape double quotes (could misfire if you escaped double quotes in PHP _("<a href="bla">bla</a>") but in my case that was one case versus many)
    $english = str_replace('"','"',$match[2]);


    $en_sq_e = str_replace("'","'",$english); // escape single quotes

    $translations['_(''. $german . '''] = '_('' . $en_sq_e . ''';
    $rawmsgids['_(''. $german . '''] = $match[1]; // find raw msgid with searchstr as key

    $translations['_("'. $match[1] . '"'] = '_("' . $match[2] . '"';
    $rawmsgids['_("'. $match[1] . '"'] = $match[1];

    $translations['__(''. $german . '''] = '__('' . $en_sq_e . ''';
    $rawmsgids['__(''. $german . '''] = $match[1];

    $translations['__("'. $match[1] . '"'] = '__("' . $match[2] . '"';
    $rawmsgids['__("'. $match[1] . '"'] = $match[1];

    $msgstrs[$match[1]] = $match[2]; // msgid => msgstr
}


foreach (glob("*.php") as $file) {
    $code = file_get_contents($file);

    $filehits = 0; // how many replacements per file

    foreach($translations AS $msgid => $msgstr) {
        $hits = 0;
        $code = str_replace($msgid,$msgstr,$code,$hits);
        $filehits += $hits;

        if($hits!=0) $msgidhits[$rawmsgids[$msgid]] = 1; // this serves to record if the msgid was found in at least one incarnation
        elseif(!isset($msgidhits[$rawmsgids[$msgid]])) $msgidhits[$rawmsgids[$msgid]] = 0;
    }
    // file_put_contents($file, $code); // be careful to test this first before doing the actual replace (and do use a version control system!) 
    echo "$file : $filehits <br>"; 
    echo $code;
}
/* debug */ 
$found = array_keys($msgidhits, 1, true);
foreach($found AS $mid) echo $mid . " => " . $msgstrs[$mid] . "nn";

echo "Not Found: <br>";
$notfound = array_keys($msgidhits, 0, true);
foreach($notfound AS $mid) echo $mid . " => " . $msgstrs[$mid] . "nn";

/*
following steps are still needed:
    * convert plurals (ngettext)
    * convert multi-line msgids and msgstrs (format mentioned in question)
    * resolve uniqueness conflict (msgids are unique, msgstrs are not), so you may have duplicate msgids (poedit finds these)
*/
    
因此,如果我理解正确,您想用英语替换所有德语gettext调用。要替换目录中的内容,这样的东西可以工作。
$po = file_get_contents("translation.pot");
$translations = array(); // german => english
preg_match_all('/msgid "(.+)"nmsgstr "(.+)"/', $po, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
    $translations['_("'. $match[1] . '")'] = '_("' . $match[2] . '")';
    $translations['_(''. $match[1] . '')'] = '_('' . $match[2] . '')';
}
foreach (glob("*.php") as $file) {
    $code = file_get_contents($file);
    $code = str_replace(array_keys($translations), array_values($translations), $code);
    //file_put_contents($file, $code);
    echo $code; // be careful to test this first before doing the actual replace (and do use a version control system!)
}
    

要回复问题请先登录注册