spájame
slovenskú
IT komunitu
pridaj sa
Registrácia · Login

Matúš Koprda 3.2.2011, článok je súčasťou seriálu Ako sa stať PHP ninja s Yii Frameworkom
Hodnoť článok:
1 0

Yii framework: I18n ako naučiť aplikáciu po slovensky (2)

V dnešnom pokračovaní seriálu tutoriálov o Yii frameworku je tu exkluzívna možnosť dozvedieť sa ako spraviť funkčné a efektívne prehadzovanie jazykov.

V predchádzajúcej časti sme si popísali 2 spôsoby akými sa dá v Yii prekladať obsah multijazyčných stránok a tiež sme si ukázali ako internacionalizovať komponenty ako je datepicker. Podporu prekladov má síce Yii dosť fajn, ale autori akosi zabudli na to, že podstatou internacionalizácie je, aby sa dali jazyky aj meniť. Možno preto sú záležitosti okolo prepínania jazykov zdokumentované najbiednejšie zo všetkého, čo som o Yii čítal. Na zajtra.sk máte exkluzívnu:) možnosť sa dozvedieť ako jednoducho spraviť funkčné a efektívne prehadzovanie jazykov. Až mi je ľúto, že nepíšeme po anglicky, aby som ušetril nervy viacerým nešťastníkom.

V prvom rade musíme zobrať do úvahy dosť dôležitú otázku ako si budeme pamätať vybraný jazyk. Zvolil som (podľa mňa) najschodnejšiu cestu, kedy budeme mať jazyk v URL, čiže adresy by vyzerali ako http://drist.sk/sk/bla/tisic. Mať jazyk v adrese je dobré jednak kvôli SEO - ak by sme si pamätali jazyk napríklad len v cookie, crawlery by sa neboli schopné dostať na viac ako jednu jazykovú mutáciu (čo by bolo fakt zlé) a jednak z dôvodu, že keď niekomu posielate link na takú stránku, bude ju vidieť rovnako ako vy.

Dropdown

Najskôr vytvoríme dropdown s jazykmi dostupný po celej stránke. Predvolený v ňom bude aktuálny jazyk a pri jeho zmene (onchange) chceme, aby sa načítala tá istá stránka len v inej reči. SEO poznámka: crawlery sa nedostanú ani cez takýto dropdown, takže treba buď vytvoriť sitemap alebo niekde (do footera?) podávať linky na všetky jazyky!

HTML pre dropdown doplníme do hlavného templejtu (protected/views/layouts/main.php):

<div id="logo">
	<?php echo CHtml::encode(Yii::app()->name) ?>

	<?php echo CHtml::beginForm(array('site/changelang'), 'post', array('style'=> 'float: right; font-size: 50%;')) ?>
		<?php echo Yii::t('nin', 'Language') ?>:
		<?php echo CHtml::dropDownList('lang', Yii::app()->getLanguage(),
			array('en' => 'English', 'sk' => 'Slovenčina'),
			array('onchange'=>'this.form.submit()'));
		?>
		<?php echo CHtml::hiddenField('return', Yii::app()->request->url) ?>
	<?php echo CHtml::endForm() ?>
</div>

Tu by malo byť viac menej všetko zrejmé. Pre istotu ale spomeniem, že Yii::app()->getLanguage() vracia aktuálny jazyk (komplementárnou metódou setLanguage() sa dá zase jazyk hocikedy zmeniť), v štýle je 50%-ná veľkosť preto, že nadradený kontainer (s nadpisom) nastaví veľkosť na 200%, v hidden políčku je URL pre návrat na aktuálnu stránku a CHtml::beginForm() používam namiesto klasického HTML markupu z dôvodu, že mi sám vygeneruje vhodnú URL pre akciu formulára.

SiteController

Akciu, na ktorú sa odošle formulár, musíme doplniť aj do controllera (protected/controllers/SiteController.php). Pri tej príležitosti pridáme autodetekciu jazyka na hlavnú stránku a SEO optimalizáciu v jednom (hlavná stránka je vlastne akcia index v controlleri SiteController).

public function actionChangelang()
{
	if ($_POST['return'] == '/' || preg_match('/^\/[a-z]{2}\/?$/', $_POST['return']) )
		$this->redirect("/" . $_POST['lang']);
	else
		$this->redirect("/" . $_POST['lang'] . substr($_POST['return'], 3));
}
Nahradíme aktuálny jazyk v URL novým jazykom. Ak je v návratovej ceste len nejaký kýpeť™ ;) typu "/", "/sk" alebo "/en/", rovno redirectneme na "/[nový jazyk]", pri plných cestách odstránime prvé 3 znaky (t.j. lomítko + pre každý jazyk budeme vždy používať len 2 písmená) a dáme namiesto nich do cesty "/[nový jazyk]".
public function actionIndex() { if ($_SERVER['REQUEST_URI'] == '/') { if (substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) == 'sk') $this->redirect('/sk'); else $this->redirect('/en'); }
Pokiaľ používateľ príde na hlavnú stránku /, pokúsime sa zistiť akým jazykom by sme na neho mali vybehnúť a následne ho presmerujeme na adresu /[zistený jazyk]. Jazyk sa dá determinovať na základe HTTP hlavičky "HTTP_ACCEPT_LANGUAGE", ktorá má cca. takýto formát: sk-SK,sk;q=0.9,en;q=0.8. Každý browser ju však generuje inak a napríklad Opera mi zistila ako primárny jazyk slovenčinu, kým Firefox angličtinu.. so yeah. Za každých okolností nám ale stačí prečítať prvé 2 písmená a zariadiť sa podľa nich. Z hľadiska SEO je toto presmerovanie tiež dôležité. Ak by sme ho neuskutočnili, bol by na dvoch rôznych adresách ("/" a "/sk") rovnaký obsah a potom by nás Google nemal rád. :)
$this->render('index', array('users'=> CHtml::listData(User::model()->with('role')->findAll(), 'email', 'role.name'))); }

Konfigurácia UrlManagera

URL manažér zabezpečí, že Yii rozpoznáva a generuje adresy podľa určených pravidiel. Nastavenia pravidiel URL manažéra (rules) sú v hlavnom configu (protected/config/main.php) a je to jedna z najčudnejších vecí v Yii. Fungujú natoľko zamotane, že sa nimi v podstate ani nemusíte zaoberať a ušetriť si zatiaľ nervy. :)

'urlManager'=>array(
	'urlFormat'=>'path',
	'showScriptName'=>false,
Tieto 2 riadky nastavujú generovanie "čistých" URL. Presnejšie urlFormat = path odstráni GET parameter (/index.php?r=bla/drist -> /index.php/bla/drist) a showScriptName = false z cesty odstráni aj index.php, takže generované adresy budú mať v konečom dôsledku tvar /bla/drist
'rules'=>array( '<language:[a-z]{2}>'=>'site/index', '<language:[a-z]{2}>/<controller:\w+>/<id:\d+>'=>'<controller>/view', '<language:[a-z]{2}>/<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>', '<language:[a-z]{2}>/<controller>' => '<controller>', '<language:[a-z]{2}>/<controller>/<action>' => '<controller>/<action>', '<language:[a-z]{2}>/<module>/<controller>/<action>*' => '<module>/<controller>/<action>',
Pravidlá pre cesty.. uf.. tak na toto treba pár odstavcov, čítajte nižšie :)
), 'class' => 'I18nUrlManager',
I18UrlManager je naša trieda, ktorou sa má nahradiť pôvodný UrlManager.
),

O nastaveniach ciest v Yii by sa dal napísať aj celý tutoriál, ale v skratke - na ľavej strane je adresa akú vidí používateľ a na pravej controller a akcia (prípadne aj modul). Ostatné parametre ako "language", "id" alebo čokoľvek, čo v ľavej časti definujete, sú potom v controlleri prístupné z _GETu.

Pre lepšiu predstavu - napríklad druhé pravidlo zabezpečuje, že pri ceste v tvare /sk/user/1 sa zavolá controller a akcia user/view a ako parameter bude predané idčko (a jazyk). Keďže jednotlivé časti cesty ako <controller> sú čisto len stringy bez významu, 5. pravidlo zachytáva okrem adries v tvare /sk/controller/akcia aj adresy /sk/modul/controller. Obdobne funguje aj 4. a 6. pravidlo. Adresa /sk/gii/crud by sa vyhodnotila ako controller gii a akcia crud, ktoré neexistujú, takže by bola ďalej posunutá na spracovanie modulom a tam by ju modul gii odchytil.

Parameter language musí mať zrovna 2 písmená (regexp [a-z]{2}) preto, aby sme vedeli, že naozaj ide o jazyk a nie je to napríklad meno modulu (gii). Je to celé mätúce, kľudne môžete pravidlá UrlManagera preskočiť a vrátiť sa k nim až keď budete potrebovať ťažko customizovať cesty. :)

UrlManager

Nasleduje spomínaný vlastný UrlManager, ktorého funkcia je generovať adresy obsahujúce v sebe jazyk a nastaviť správny jazyk podľa URL, na ktorej sa používateľ nachádza.

protected/components/I18nUrlManager.php

class I18nUrlManager extends CUrlManager {

public function createUrl ($route, $params=array(), $ampersand='&')
{
	if (!isset($params['language'])) $params['language'] = Yii::app()->getLanguage();
	return parent::createUrl($route, $params, $ampersand);
Metóda createUrl() sa volá vždy keď treba generovať link. Celá jej činnosť spočíva v tom, že nastaví parameter 'language' podľa aktuálne zvoleného jazyka a zavolá pôvodnú metódu createUrl().
} public function parsePathInfo($pathInfo) { parent::parsePathInfo($pathInfo); $lang = Yii::app()->getRequest()->getParam('language'); if ( in_array($lang, array('en', 'sk')) ) Yii::app()->setLanguage($lang);
ParsePathInfo rozbíja URL na jej jednotlivé časti, čiže controller, akciu a parametre. Na základe pravidiel sa do parametra 'language' zapíše obsah prvého segmentu adresy a podľa neho nastavíme jazyk. Táto metóda sa volá v momente keď sa zisťuje aký controller sa má vôbec použiť, takže kým začnete chcieť niečo prekladať, jazyk by už mal byť správne nastavený.
} }

Na úplný záver hodíme do rootu (t.j. tam kde je index.php) Apachovský súbor .htaccess určený na generovanie pekných adries (clean URLs). Je kopec návodov zaoberajúcich sa peknými URL a modulom mod_rewrite, takže kód nebudem nejak veľmi rozpitvávať.

Asi len toľko, že vďaka RewriteCond sa otvorí súbor na danej adrese namiesto generovania stránky, v prípade že súbor exisuje (napr. /images/haluz.png), inak RewriteRule prilepí celú adresu (od lomítka po koniec) za index.php (/bla/drist -> index.php/bla/drist) a ten sa postará o zvyšok.

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . index.php

Pro tip + download aplikácie

Po prečítaní tohoto návodu by ste mali byť vyzbrojení všetkým čo treba na kompletnú i18n. Na záver už len malý tip: ako som spomenul v prvej časti tutoriálu, písať Yii::t('kategoria', 'string') je strašne zdĺhavé a pokiaľ sa chcete ušetriť od sústavného opakovania, priamo v index.php si môžete vytvoriť takúto užitočnú funkciu:

function t($string, $params = array())
{
	return Yii::t('kategoria', $string, $params);
}

Možno sa to na prvý pohľad nezdá, ale písať len t('niečo') dramaticky pridáva na pohodlnosti. Ak hrozí, že budete mať veľa stringov na preklad, nezabudnite využívať kategórie a vytvorte si aj viac pomocných funkcií.

Kompletné funkčné zdrojáky si môžete stiahnuť tu: Yii I18n demo [rar].

Matúš Koprda Matúš Koprda

Momentálne robím internety a keď budem veľký, snáď sa dostanem aj k hrám alebo niečomu zmysluplnému. :) Mám rád minimalizmus, obskúrnu hudbu, všetko geeky a rýpanie sa v detailoch. Ďalšie kecy odo mňa nájdeš na brm.sk a na Twitteri @blade_sk.


Hodnoť článok:
1 0

1 komentár k článku:

Komentovať môžu iba prihlásení

Zaregistruj sa cez bezplatnú registráciu alebo použi login cez Facebook (FB Connect)

Prihlás sa tu, ak už máš profil na Zajtra.sk:


Zabudol som heslo

0 0 Jana Mičeková 8.11.2012 14:36:32
Mohol by mi niekto poradiť ako sa správne prekladá slovo "scenario"? Napr. pri spustení validácie za behu. "Validation is performed in a scenario basis. The scenario property specifies which scenario the model is being used in and which set of validation rules should be used." Díky moc
Zajtra.sk > Programovanie > PHP > Yii framework: I18n ako naučiť aplikáciu po slovensky (2)


Kritika

Vieš ako robiť veci lepšie? Pomôž našim odvážnejším členom a skritizuj im projekty!

Reklama

Seriály zo Zajtra.sk

Reklama