2011-01-15 11 views
9

Ho avviato la mia applicazione PHP con tutto il testo in tedesco, quindi ho usato gettext per estrarre tutte le stringhe e tradurle in inglese.
Quindi, ora ho un file .po con tutti i msgids in tedesco e msgstrs in inglese. Voglio cambiare loro, in modo che il mio codice sorgente contiene l'inglese come msgid per due motivi principali:Cambia lingua tradotta gettext con la lingua originale

  1. Più traduttori conoscere l'inglese, quindi è solo opportuno servirli su un file con msgid in inglese. I potrebbe passare sempre il file prima di darlo e dopo averlo ricevuto, ma naaah.
  2. Sarebbe utile scrivere nomi di funzioni e commenti degli oggetti inglesi & se il testo del contenuto era anche inglese. Mi piacerebbe farlo, quindi il progetto è più aperto ad altri collaboratori Open Source (è più probabile che conoscano l'inglese che il tedesco).

ho potuto fare questo manualmente e questo è il tipo di operazione in cui prevedo che mi ci vorrà più tempo per scrivere una routine automatizzate per esso (perché io sono molto male con gli script di shell) di farlo a mano. Ma prevedo anche di disprezzare ogni minuto di lavoro manuale del computer (mi sembra un ossimoro, giusto?) Come faccio sempre.

Qualcuno l'ha già fatto? Ho pensato che sarebbe stato un problema comune, ma non ho trovato nulla. Molte grazie in anticipo.

Problema Esempio:

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

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

ho pensato di circoscrivere il problema. L'interruttore nel .po file è alcun problema, naturalmente, è così semplice come

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

Il problema per me è la routine che cerca i miei file cartella del progetto per _('$msgid') e sostituti _('msgstr') durante l'analisi della .po- file (che probabilmente non è nemmeno il modo più elegante, dopo tutto il file .po contiene commenti che contengono tutti i percorsi dei file in cui si verifica msgid).


Dopo fooling around con la risposta di akirk un po ', mi sono imbattuto in qualche problema in più.

  1. Perché ho un misto di _('xxx') e _("xxx") chiamate, devo stare attento a (in) fuga.
    • virgolette doppie "msgid e msgstrs devono essere escape, ma i tagli non possono essere rimossi, perché può essere che il doppio citazione è stata anche sfuggito in PHP
    • citazioni singole devono essere sfuggito quando sono sostituiti in PHP, ma poi devono essere cambiati anche nel file .po. Fortunatamente per me, le virgolette singole appaiono solo nel testo inglese.
  2. msgid e msgstrs possono avere più linee, poi simile a questa
    msgid = ""
    "line 1\n"
    "line 2\n"
    msgstr = ""
    "line 1\n"
    "line 2\n"
  3. forme plurali sono naturalmente saltato in questo momento, ma nel mio caso questo non è un problema
  4. poedit vuole rimuovere stringhe come obsolete che sembrano scambiate con successo e non ho idea del perché questo avvenga in (molti) casi.

Dovrò smettere di lavorare su questo per stanotte. Tuttavia sembra che utilizzare il parser anziché RegExps non sia eccessivo.

+0

difficile, non solo è necessario passare le voci nei file gettext, sarà anche necessario sostituire tutte le stringhe nel codice. – markus

+0

@tharkun: sì certo, è quello che dovrei fare, ma non mi sembra così complicato. Penso che potrei farlo con una stringa PHP, ma non con la shell. nel modo più semplice si dovrebbe solo analizzare (o cercare) il file .po per msgids e strs e quindi cercare e sostituire tutti i file in una cartella per quella stringa. Ho incluso l'interruttore nel post, per restringere il problema. – Ruben

+0

Penso che tu sia sulla strada giusta qui. Il trucco sarebbe quello di assicurarsi che il regEx che si utilizza non cambi inavvertitamente la sorgente effettiva. Non dimenticare che regEx dovrebbe anche gestire le chiamate a virgolette singole e doppie a '_ (...)'. In bocca al lupo. –

risposta

1

Vedi http://code.activestate.com/recipes/475109-regular-expression-for-python-string-literals/ per una buona pitone a base di espressioni regolari per la ricerca di stringhe, tenendo fughe in considerazione. Sebbene sia Python, potrebbe essere abbastanza buono per stringhe multilinea e altri casi angolari.

Vedere http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/poswap.html per uno swapper di lingua base pronto per i file .po.

Ad esempio, la seguente riga di comando convertirà la traduzione spagnola basata in tedesco nella traduzione spagnola basata in inglese. Devi solo per assicurarsi che la nuova lingua di base (inglese) è al 100% tradotto prima della conversione di iniziare:

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

E infine per scambiare file po Inglese a file po tedesco, utilizzare swappo: http://manpages.ubuntu.com/manpages/hardy/man1/swappo.1.html

Dopo scambiando file, potrebbe essere necessaria una lucidatura manuale dei file risultanti. Ad esempio, le intestazioni potrebbero essere interrotte e potrebbero verificarsi alcuni testi duplicati.

+0

Ho pubblicato uno script Python per scambiare sorgenti/destinazioni in file PO. Questo potrebbe essere utile per questo caso: http://mola.io/2013/09/17/swapping-languages-in-gettext-po-file/ – smola

1

Quindi, se ho capito bene, vorresti sostituire tutte le chiamate gettext tedesche con quelle inglesi. Per sostituire i contenuti nella directory, qualcosa del genere potrebbe funzionare.

$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!) 
} 
+0

Sì, ma anche se ovviamente posso dare il file po come stringa, ho bisogno di cercare e sostituire una directory __ di file php__, non una stringa. Mi piacerebbe anche sapere, alla fine, quali msgids non possono essere trovati (sarebbero chiamate di funzione per forme plurali e segnaposti: così pochi che potrei farli a mano). Speravo che il parser gettext stesso potesse essere usato in qualche modo, dopotutto fa già qualcosa di molto simile (analizza i file php e trova msgids nelle chiamate di funzione specificate). – Ruben

+0

Non sono a conoscenza di uno strumento nella distribuzione gettext, dovrai farlo a mano (che non è noioso). Ho cambiato il mio codice per riflettere questo. – akirk

+0

Ho scherzato un po 'con il tuo script http://pastebin.com/J7ipM1fy per vedere più facilmente quali stringhe sono state trovate. Trattare le virgolette e le stringhe multi-linea non è tuttavia banale e aggiornerò la mia domanda per riflettere questo. – Ruben

5

ho costruito sulla risposta akirk e volevano preservare ciò che mi è venuta come una risposta qui, nel caso in cui qualcuno ha lo stesso problema. Questo non è ricorsivo, ma potrebbe facilmente cambiare naturalmente. Sentiti libero di commentare con miglioramenti, guarderò e modificherò questo post.

$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) 
*/ 
+1

Ottimo! Mi hai salvato la giornata :) –

Problemi correlati