phpMinAdmin – překlady

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

U globálního projektu je nezbytné, aby existoval v anglické jazykové verzi. Pro místní uživatele je ale samozřejmě vhodné připravit i lokalizovanou verzi. Jak to řeší phpMinAdmin? Překlady jsou uloženy přímo v PHP skriptu v poli $translations[$LANG], kde klíčem je identifikátor překladu (který odpovídá anglické jazykové verzi) a hodnotou je samotný překlad. O přeložení se stará jednoduchá funkce, která na základě nastaveného jazyka vybere překlad (pokud existuje) nebo vrátí předaný identifikátor:

<?php
/** Získání překladu z pole $translations[$LANG]
* @param mixed počet určující variantu překladu
* @param mixed další parametry předané funkci sprintf
* @return string přeložený text nebo $idf, pokud překlad neexistuje, s dosazenými parametry
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function lang_array($idf, $number = null) {
    global $LANG, $translations;
    $translation = $translations[$LANG][$idf];
    if (is_array($translation) && $translation) {
        switch ($LANG) {
            case 'cs': $pos = ($number == 1 ? 0 : (!$number || $number >= 5 ? 2 : 1)); break;
            default: $pos = ($number == 1 ? 0 : 1);
        }
        $translation = $translation[$pos];
    }
    $args = func_get_args();
    array_shift($args);
    return vsprintf(($translation ? $translation : $idf), $args);
}
?>

Překlady závislé na počtu

Znáte to: 1 záznam, 2 záznamy, 5 záznamů. phpMinAdmin to řeší tak, že tyto překlady ukládá do pole místo do řetězce a který prvek pole vzít, se rozhodne podle parametru funkce. Počet druhů hlášek stejně jako pravidla pro jejich výběr jsou v každém jazyce jiná, řeší to jednoduchý switch. V češtině se první tvar použije u počtu 1, druhý tvar u počtu 2–4, jinak třetí tvar (záporná čísla se nepoužívají). Angličtina má pravidlo jednodušší.

Teoreticky by mohly existovat hlášky obsahující více čísel („2 příkazy provedly 5 změn“). To funkce neřeší a takovouto hlášku by bylo potřeba rozdělit do dvou. Číslo by také nemuselo být uvedeno na prvním místě („Příkaz %s provedl %d změn“), to se dá ale snadno vyřešit změnou pořadí parametrů podporovanou funkcemi rodiny printf – „Příkaz %2$s provedl %1$d změn“. To se ostatně může hodit i u běžných překladů.

Detekce jazyka

Jazyk si uživatel může v rozhraní zvolit nebo se detekuje z hlavičky Accept-Language, která je ve formátu jazyk-varianta;q=priorita, …:

<?php
/** Získání vhodného jazyka z hlavičky Accept-Language
* @param array přípustné jazyky v klíčích pole
* @return string vhodný jazyk z pole $translations nebo false, pokud není nalezen
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function acceptable_language($translations) {
    $accept_language = array();
    preg_match_all('~([-a-z]+)(;q=([0-9.]+))?~', strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]), $matches, PREG_SET_ORDER);
    foreach ($matches as $match) {
        $accept_language[$match[1]] = (isset($match[3]) ? $match[3] : 1);
    }
    arsort($accept_language);
    foreach ($accept_language as $lang => $q) {
        if (isset($translations[$lang])) {
            return $lang;
        }
        $lang = preg_replace('~-.*~', '', $lang);
        if (!isset($accept_language[$lang]) && isset($translations[$lang])) {
            return $lang;
        }
    }
    return false;
}
?>

Funkce zohledňuje i prioritu, kterou má uživatel pro jednotlivé jazyky nastavenou. Pokud nenajde odpovídající jazykovou verzi včetně varianty, tak ji hledá jen na základě jazyka.

Předávání jazyka

Nastavený jazyk se v rozporu s mými vlastními radami přenáší v cookie a ne v URL. Hlavní důvod je ten, že zvolená jazyková verze se použije i při budoucích přístupech do aplikace. Uživatel by si sice do oblíbených položek mohl uložit odkaz včetně parametru jazyka, někdo ale raději zadává URL ručně. Vyhledávače do aplikace nechodí (nedostanou se přes přihlášení, navíc je indexování explicitně zakázané), takže ani těm existence více jazykových verzí na stejném URL (podpořená navíc automatickou detekcí jazyka) nevadí. A pokud chci někomu poslat odkaz do aplikace, jde tam hlavně o data – překlad rozhraní je vlastně jen taková omáčka okolo, odkaz na konkrétní jazykovou verzi je navíc možné také získat. Pro uživatele se zakázanými cookies se informace o jazykové verzi ukládá i do session proměnné, takže ani ti nepřijdou zkrátka.

Jakub Vrána, Adminer, 6.8.2007, diskuse: 5 (nové: 0)

Diskuse

Ondrej Ivanic:

Presne tak, toto je priklad kde je vhodne mat jazyk v cookie - nic sa tym nepokazi.

Co sa tyka mnoznych cisel je to presne ako s gettext-om, ale tiez by som ho nepouzil v tekejto aplikacii.

marau:

Přesně něco podobného akorát trochu složitějšího jsem si zhruba před rokem napsal a zhruba před měsícem ještě vyplepšil a jsem s tím řešením naprosto spokojenej http://www.megablog.cz/snad-elegantni-jazykove-mutace-t250.html

ikona dgx:

Jen k té detekci jazyků: některé prohlížeče posílají cs_CZ namísto cs-CZ apod.

ikona finc:

Pro identifikaci jazykove verze, ktera je nastavena v prohlizeci, pouzivaji webove frameworky pro Javu (JSF, atd.). Osobne se mi tento pristup libi asi nejvice.
Co vidim jako velke plus je, ze se pouzivaji klasicke plan-text soubory (Bundle.properties), ktere muze upravovat i neprogramator. Osobne si myslim, ze by stringy mely byt takto oddelene od jakehokoli kodu. Prime preklady pak mohou delat uplne vsichni.

SendiMyrkr:

Já bych k těm překladům závislým na počtu přidal ještě samostatně variantu pro 0:
0   -> Žádné řádky(nebo žádný řádek)
1   -> 1 řádek
2-4 -> 2 řádky
5=< -> 5 řádků

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 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.