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); } ?>
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ů.
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.
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.
Diskuse je zrušena z důvodu spamu.