Переключение языка перевода gettext с языка оригинала

я запустил приложение PHP со всем текстом на немецком языке, затем использовал gettext для извлечения всех строк и перевода их на английский язык.
Итак, теперь у меня есть .po файл со всеми msgids по-немецки и msgstrs на английском языке. Я хочу переключить их, чтобы мой исходный код содержал английский как msgids по двум основным причинам:

  1. больше переводчиков будут знать английский язык, так что это только подходит, чтобы служить им файл с msgids на английском языке. Я!--14-- > мог бы всегда переключайте файл, прежде чем я его выдам и после того, как я его получу, но нааа.
  2. это поможет мне написать английские имена объектов и функций и комментарии, если текст контента также был английским. Я бы хотел это сделать, поэтому проект более открыт для других сотрудников с открытым исходным кодом (скорее всего, знает английский, чем немецкий).

я мог бы сделать это вручную, и это та задача, которую я ожидаю мне потребуется больше времени, чтобы написать для него автоматическую процедуру (потому что я очень плохо со скриптами оболочки), чем сделать это вручную. Но я также предвижу презрение к каждой минуте руководство по эксплуатации компьютерного труда (похоже на оксюморон, верно? как и всегда.

кто-нибудь делал это раньше? Я подумал, что это будет обычная проблема, но ничего не смог найти. Большое спасибо вперед.

Пример:

<title><?=_('Routinen')?></title>

#: /users/ruben/sites/v/routinen.php:43
msgid "Routinen"
msgstr "Routines"

I решил сузить круг проблем. Выключатель в ... po-файл не проблема, конечно, это так же просто, как

preg_replace('/msgid "(.+)"nmsgstr "(.+)"/', '/msgid ""nmsgstr ""/', $str);

проблема для меня-это процедура, которая ищет мои файлы папок проекта для _('$msgid') и заменители _('msgstr') при разборе .po-файл (что, вероятно, даже не самый элегантный способ, в конце концов .po-файл содержит комментарии, которые содержат все пути к файлам, где например происходит).


после дурачиться с akirk по ответьте немного, я столкнулся еще с некоторыми проблемами.

  1. потому что у меня есть смесь _('xxx') и _("xxx") звонки, я должен быть осторожен с (ООН)побегом.
    • двойные кавычки " в msgids и msgstrs должны быть unescaped, но косые черты не могут быть удалены, потому что может быть, что двойная кавычка также была экранирована в PHP
    • одинарные кавычки должны быть экранированы, когда они заменены на PHP, но затем они также должны быть изменены .po-файл. К счастью для меня, одинарные кавычки появляются только в английском тексте.
  2. msgids и msgstrs могут иметь несколько строк, тогда они выглядят так
    msgid = ""
    "line 1n"
    "line 2n"
    msgstr = ""
    "line 1n"
    "line 2n"
  3. формы множественного числа, конечно, пропущены в данный момент, но в моем случае это не проблема
  4. poedit хочет удалить строки как устаревшие, которые кажутся успешно переключенными, и я понятия не имею, почему это случается в (многих) случаях.

я должен прекратить работать над этим сегодня вечером. Еще кажется через парсер вместо регулярок не будет излишним.

3 ответов


см 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 для готового, из коробки базового языка swapper для .почтовый файлы.

например, следующая командная строка преобразует немецкий испанский перевод в английский испанский перевод. Вам просто нужно убедиться, что ваш новый базовый язык (английский) переведен на 100% перед началом преобразования:

poswap -i de-en.po -t de-es.po -o en-es.po

и, наконец, своп-файла по немецкому po-файл, используйте swappo: http://manpages.ubuntu.com/manpages/hardy/man1/swappo.1.html

после замены файлов, некоторая ручная полировка могут потребоваться результирующие файлы. Например, заголовки могут быть сломаны, и могут возникнуть некоторые дубликаты текстов.


Я построил ответ акирка и хотел сохранить то, что я придумал в качестве ответа здесь, в случае, если у кого-то есть та же проблема. Это не рекурсивно, но это может легко измениться, конечно. Не стесняйтесь комментировать улучшения, я буду смотреть и редактировать этот пост.

$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] . "\n\n";

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

/*
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!)
}