Překlad formátovaného textu

Školení, která pořádám

Při překládání statických textů je občas potřeba se nějak vypořádat i s formátováním. Jak se postavit např. k překladu věty <em>The newest</em> articles are available at the <a href="/">home page</a>?

První řešení, které by nás mohlo napadnout, je nechat přeložit jen prostý text: <em><?php echo lang('The newest'); ?></em> <?php echo lang('articles are available at the'); ?> <a href="/"><?php echo lang('home page'); ?></a>. Toto řešení je samozřejmě nevhodné z několika důvodů – slova jsou vytržena z kontextu, takže pro ně nelze zvolit správný tvar (např. home page by se přeložilo jako domácí stránka, i když v kontextu věty by mělo být použité domácí stránce). Kromě toho různé jazyky používají různý slovosled.

Proto bude vhodnější nechat přeložit celou větu včetně formátovacích značek: <?php echo lang('<em>The newest</em> articles are available at the <a href="/">home page</a>'); ?>. Překlad ovšem bude vhodné nějak zkontrolovat – jednak jestli vůbec tvoří validní kód a jednak jestli obsahuje stejné značky jako originál (kvůli jinému slovosledu nicméně mohou být v jiném pořadí). Nejsnáze se o to může postarat rozšíření SimpleXML:

<?php
/** Porovnání názvů a počtu XML značek libovolného zanoření
* @param string řetězec k porovnání
* @param string řetězec k porovnání
* @return bool true, false při neshodě značek nebo v případě chyby
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function compare_tags($s1, $s2) {
    $xml1 = @simplexml_load_string("<s>$s1</s>");
    $xml2 = @simplexml_load_string("<s>$s2</s>");
    if ($xml1 === false || $xml2 === false) {
        return false;
    }
    $tags1 = array();
    foreach ($xml1->xpath("//*") as $tag) {
        $tags1[$tag->getName()]++;
    }
    $tags2 = array();
    foreach ($xml2->xpath("//*") as $tag) {
        $tags2[$tag->getName()]++;
    }
    return ($tags1 == $tags2);
}
?>

Funkce na vstupu očekává dva XML řetězce a porovná, zda obsahují stejné značky libovolného zanoření v libovolném pořadí (atributy se nekontrolují). Zároveň zjistí, jestli jsou řetězce v pořádku. Pokud bychom značky očekávali ve stejném pořadí, byla by funkce paradoxně jednodušší – stačilo by na základě prvního řetězce sestavit regulární výraz a ten se pokusit napasovat na druhý řetězec.

Stejný princip mimochodem využívá i nástroj pro překlad rozhraní Google. Na tento nástroj jsem ovšem zanevřel poté, co jsem přeložil celý Google Toolbar do češtiny, ale můj překlad se do žádné verze tohoto nástroje nedostal (přestože jsem na dokončení překladu upozorňoval i e-mailem) a několik hodin mé práce tak vyšlo vniveč.

Šalamounským řešením by bylo použít nějaký nástroj pro formátování textu, např. Texy!. Potřeba zkontrolovat, zda výstup používá stejné značky, by ovšem zůstala.

Jakub Vrána, Dobře míněné rady, 25.6.2008, diskuse: 3 (nové: 0)

Diskuse

kozotvor:

A co třeba použít printf() s tím, že za každé %s vložím jednotlivé kusy (X)HTML kódu?

ikona Jakub Vrána OpenID:

Pokud překladatel ví, že v případě změny slovosledu musí použít např. %2$s a pokud to naopak nevyužije např. pro prohození uzavírací a otevírací značky, tak je to taky možné řešení. Také je potřeba ošetřit stav, kdy by překladatel vložil víc nebo míň %s.

Karel:

Využil jsem to na jednom webu. Díky za skvělé nápady.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.