Mirin webspace

Nejbohatší život má ten, kdo žije s minimem nároků

22. 11. 2007 Zend Framework

Překládáme se Zend_Translate

Dnes popíši několik zkušeností, které jsem nasbíral při pokusu alespoň částečně lokalizovat své stránky. Bude se to týkat hlavně modulu Zend_Translate.

První věc, kterou je potřeba zmínit je, že Zend_Translate nám slouží k lokalizaci jen určitých čáští aplikace - statických textů - zejména jde o nadpisy, menu, hlášky apod. Takové texty jsou většinou součástí designu, v případě Zend_Frameworku jsou tedy ve view šablonách. Zend_Translate nám nepomůže s lokalizací obsahu aplikace, např. s texty článků pokud píšeme nějaké CMS, s popisy zboží pokud děláme e-shop atd. V tom si musíme pomoci sami viz třeba článek Jakuba Vrány.

Stávající PHP nabízí jedinou možnost a to gettext. Samozřejmě si to také můžeme řešit sámi přes nějaké pole apod. Gettext je můžné klidně použít i se Zend_Frameworkem, nicméně musíte si dát pozor na to, že gettext sám o sobě a tím pádem ani gettext PHP extenze není thread safe a nemůžete ho použít v multithreaded prostředích (zejména asi IIS, Apache jsem v reálu používat jako multithreaded ještě neviděl).

V čem tedy spočívá práce Zend_Translate? Jedná se o třídu, které podhodíte nějaký řetezec, který chcete přeložit, ona si prostřednictvím adaptéru najde v nějakém externím zdroji jeho překlad a vrátí vám ho, pokud překlad nenajde vrátí ten samý řetězec, co jste jí poslali. Adaptérů je vícero, od obyčejného PHP pole, přes gettext,cvs až po XML a připravuje se i SQL. Osobně jsem používal jen gettext, protože má dobrou podporu externích nástrojů pro práci s překlady a je díky kompaktnímu binárnímu formátu i rychlý. Je nutné poznamenat, že Zend_Translate pracuje s binárními gettext soubory bez použití php gettext rozšíření. Gettext doporučují i i v referenčním manuálu.

Pro použití Zend_Translate lze postupoval takto:

  • Zaintegrovat inicializaci Zend_Translate do bootstapu, případně controller pluginu.
  • Napsat si View Helper, hlášky jsou většinou všechny ve view šablonách.
  • Přepsat některé hlášky v šablonách na volání helperu.
  • Pomocí externích utilit proscanovat view šablony a vyrobit překlady.
  • Otestovat.
  • Dopřeložit zbytek.

Zend_Translate je dobré si v bootstrapu inicializovat překladem daného jazyka, například podle toho, jaký jazyk si uživatel vybral atd. Stejně tak můžeme použít plugin controller. Název zvoleného jazyka můžeme s výhodou použít pro vybrání souboru s překladem. Objekt si pak pro pozdější použití uložíme do Zend_Registry.


 //somewhere in bootstrap index.php
 $lang="cs";
 $translator=new Zend_Translate("gettext","/app languages/messages.{$lang}.mo",$lang);
 Zend_Registry::set("translator",$translator);

Pak si napíšeme view helper, například takto:


<?php
class MyApp_View_Helper_Trans
{
 /**
  * translator
  * @var Zend_Tranlate
  */
 private $_translator;

//======================================================
/**
 * Sets the translator from the registry.
 */
public function __construct()
{
 $this->_translator=Zend_Registry::get("translator");
}

//======================================================
/**
 * Main helper function.
 * Returns translation for a given string.
 * @var string $str string for a translation
 * @return string
 */
public function trans($str)
{
 return $this->_translator->_($str);
}

#END CLASS
}

Přepínání jazyků můžeme zajistit nějakou controller akcí. Zend_Translate samozřejmě metody na přepínání jazyků poskytuje.

Někde ve view skriptu pak budeme pracovat s překládaným textem takto:


 <h2><?php echo $this->trans("Description")?></h2>
 <p>What is it? Some useless description.</p>

Adresář pro překlady - languages jsem umístil dle doporučení referenčního manuálu takto:

app
 languages
 lib
 modules
  blog
   controllers
   models
   views
  default
   controllers

Teď příjde na řadu projít naše zdrojové kódy a vytahat z nich řetězce, které chceme přeložit. S gettextem do jde poměrně dobře, mě stačil tento shell skriptík, který spouštím z adresáře ../app přes makefile. Skipt projde zdrojové kódy, vytahá z nich argumenty funkce trans a zaktualizuje soubory s překlady (.po - Portable Object) a nakonec z nich vytvoří binární soubory (.mo - Machine Object). Bohužel nelze použít keyword $this->trans, scanovací program xgettext pak nic nenajde.


$ cat app/languages/gettextUtils.sh
#!/bin/sh
mainDir=../../app/
langDir=$mainDir/languages
messagesFile=$langDir/messages.pot
messagesCS=$langDir/messages.cs.po
messagesCSMO=$langDir/messages.cs.mo
messagesEN=$langDir/messages.en.po
messagesENMO=$langDir/messages.en.mo
sourceDir=$mainDir

> $messagesFile

for file in `find $sourceDir -type f \( -name *.phtml -o -name *.php \) -print`; do
 echo "scannig $file"
 xgettext -j --keyword=trans --from-code=ascii \
 --default-domain=messages --language=php \
 --output=$messagesFile \
 $file
done

echo "updating CS PO"
msgmerge -U $messagesCS $messagesFile
echo "updating EN PO"
msgmerge -U $messagesEN $messagesFile

echo "formating CS MO"
msgfmt $messagesCS -o $messagesCSMO
echo "formating EN MO"
msgfmt $messagesEN -o $messagesENMO

rm -f $langDir/*~

Soubory s překlady upravuji normálně v textovém editoru, s překlady je potřeba pracovat v utf-8, Zend_Translate s tím počítá.

Interně Zend_Translate pracuje tak, že si všechny překlady natáhne po inicializaci přes daný adaptér do paměti a pak překlady prohledává v paměti, na soubor s překladem už nesahá. Podporováno je i více jakyků zárověn, ačkoli to asi moc lidí nevyužije.

Potřebu view helperu si uvědimili i sami autoři Zend_Frameworku a vznikl návrh na Zend_View_Helper_Translate. Zajímavé na něm je, že má poskytovat metodu "podtržítko". Ve view se bude moci používat stylem podpobným jako metoda Zend_Translate::_(), tedy $this->_("Some string"). Jen jsem dost zvědav, jak se bude ve view inicializovat. Kvůli jmenné konvenci a umístění helperů si to teď dost dobře nedokážu představit. Podle mě budou muset nějak ohnout samotný view objekt.


Komentáře (0)

Komentáře jsou uzavřeny.