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

Matúš Koprda 31.1.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 (1)

S <em>in·ter·na·ci·o·na·li·zá·ci·ou</em> sa často stretnete pod skratkou I18n, keďže "internationalization" je slovo dlhšie ako by bolo zdravé a nikomu sa ho nechce písať celé. V dnešnom tutoriále k Yii frameworku sa práve na internacionalizáciu pozrieme z blízka.

S in·ter·na·ci·o·na·li·zá·ci·ou sa často stretnete pod skratkou I18n, keďže "internationalization" je slovo dlhšie ako by bolo zdravé a nikomu sa ho nechce písať celé.
V preklade je to jednoducho viacjazyčnosť - t.j. budeme chcieť, aby sa na stránke dal vyberať jazyk a všetko sa návštevníkom zobrazovalo pekne preložené a prispôsobené pomerom danej krajiny (formát dátumu, desatinné čiarky, atď).

Naučte sa i18n v Yii frameworku

V Yii sa preklad realizuje pomocou správ (messages), ktoré sa zvyknú ukladať do súborov (aj keď kľudne ich môžete mať v DB, pokiaľ vám je ľúto výkonu:). Povieme si o dvoch spôsoboch ako v Yii niečo preložiť:

Prvý spôsob

Prvou možnosťou je globálne dostupná funkcia Yii::t(). Budeme ju volať pri každom reťazci, ktorý chceme preložiť s nasledujúcou syntaxou:

Yii::t(<kategória>, <string na preklad>, <pole s hodnotami>)

Kategórie existujú preto, aby nemuseli byť všetky preklady v jednom súbore. Ten by mohol mať pri väčších aplikáciách vcelku gigantické rozmery, čo by dosť spomaľovalo server. Nevýhoda tohoto prístupu je, že musíte zakaždým uvádzať kategóriu a to zase zdržuje vás (povieme si ako sa dá aj tomu vyhnúť).
String na preklad sa podľa nastaveného jazyka jedoducho nahradí prekladom. V špeciálnom prípade, že by obsahoval premenlivú hodnotu, sa to rieši pomocou poľa s hodnotami, ktorými sa nahradia "tokeny" ({file}, [line], !brmbrm, a podobne):

Yii::t('bla', 'Failed to parse file "{file}"!', array('{file}' => $filename );

Funkciu t() môžete použiť aj na pluralizáciu slov (1 porta pro, 3 porty prá, 5 pôrt pôr ;), ak ju spustíte so špeciálnou formou parametrov - namiesto stringu na preklad zadáte string vo formáte počet#slovo|počet#slovo a ako ďalší parameter pole s číslom reprezentujúcim počet/množstvo, podľa ktorého sa vyberie tvar plurálu:
echo "$n " . Yii::t("nin", "1#ball|n==0||n>1#balls", array($n)); // pre n==1 sa pouzije "ball" pre n==0 alebo n>1 "balls"

Pluralizáciu má Yii obzvlášť dobre vyriešenú a finta je v tom, že sa prekladá celý tento formátovaný reťazec. Efekt je potom taký, že pri jazykoch so zložitejšími pravidlami plurálu (ako je slovenčina) sa nemusíte obmedzovať iba na 2 tvary angličtiny. Do prekladu "balls" by sme mohli hodiť napríklad "1#guľa|n>1&&n<5#gule|n==0||n>5#gúľ™" a všetko by fungovalo tak jak má.

Súbory s prekladmi okupujú adresár protected/messages/[JAZYK]/[KATEGORIA].php a štruktúrované sú ako asociatívne pole s prekladmi. Konkrétny príklad použijem zo súboru, ktorý nájdete aj v stiahnuteľnej ukážkovej aplikácii:
protected/messages/sk/nin.php

<?php
return array(
	'Language' => 'Jazyk',
	'Home' => 'Úvod',
	'Users' => 'Používatelia',
	'Roles' => 'Role',
	'About' => 'O stránke',
	'Contact' => 'Kontakt',

	'1#ball|n==0||n>1#balls' => '1#guľa|n>1&&n<5#gule|n==0||n>5#gúľ™',

	...
);

Druhý spôsob...

...ako v Yii zabezpečiť preklady, je vytváranie celých preložených view-ov. Je to úplne jednoduché - napríklad k viewu protected/views/role/index.php by sme vytvorili súbor protected/views/role/sk/index.php a celý ho prepísali do cieľovej reči.

Prvý spôsob je dobré používať pri stránkach, kde je pár kratších stringov (napr. formuláre) a druhý pri takých, ktoré obsahujú veľký kus textu (napr. "about" stránka). Druhý spôsob má aj tú výhodu, že môžete pomocou neho poskytovať pre každý jazyk úplne iný obsah.

Ak by ste si chceli otestovať preklady, do konfiguračného súboru (protected/config/main.php) pridajte 'language'=>'sk'. To je predvolený jazyk stránky, podľa ktorého sa prekladá všetko na nej. Nám, samozrejme, iba jeden jazyk nestačí a povieme si aj ako spraviť dropdown s výberom jazykov a ako pomeniť URLká, aby stránka mohla fungovať medzinárodne.

Formulár, CGridView a DatePicker

Ukážeme si, ako lokalizáciu prakticky uplatniť na zozname používateľov a na formulári, lebo tie tvoria substanciu aplikácie, s ktorou pracujeme. Ako prvý zlokalizujeme model používateľa, keďže práve z neho sa ťahajú názvy políčok do formulára aj CGridView-u.

Model používateľa (models/User.php)

public function attributeLabels()
{
	return array(
		'id' => 'ID',
		'id_role' => Yii::t('nin','Role'),
		'email' => Yii::t('nin','Email'),
		'password' => Yii::t('nin','Password'),
		'name' => Yii::t('nin','Name'),
		'member_since' => Yii::t('nin','Member Since'),
		'status' => Yii::t('nin','Status'),
	);
}
Tu nerobíme nič prevratné, oproti pôvodnému modelu sme iba poobaľovali názvy do Yii::t(). 'nin' je názov kategórie.
function afterFind() { if ($this->member_since == '0000-00-00') $this->member_since = ''; else $this->member_since = Yii::app()->dateFormatter->formatDateTime(strtotime($this->member_since), 'medium', null); $this->_oldPassword = $this->password; $this->password = ''; return parent::afterFind(); }
Namiesto pevného formátu dátumu použijeme dateFormatter. Ten dátum naformátuje podľa jazyka aplikácie (resp. podľa locale daného jazyka). Prvý parameter je timestamp, druhý dĺžka dátumu (short, medium, long, wide) a posledným parametrom dĺžka času. Čas nechceme zobraziť, takže namiesto dĺžky poskytneme iba hodnotu null. Zvyšok metódy sa nemení. V slovenčine nám teda vypadne dátum v tvare 11.1.2011, v angličtine Jan 11, 2011.

CGridView (views/user/admin.php)

$this->breadcrumbs=array(
	Yii::t('nin','Users')=>array('index'),
	Yii::t('nin','Manage'),
);

$this->menu=array(
	array('label'=>Yii::t('nin','Create User'), 'url'=>array('create')),
);
?>

<h1><?php echo Yii::t('nin', 'Manage Users') ?></h1>

<?php
	$roles = CHtml::listData(Role::model()->findAll(), 'id','name');
	foreach ($roles as $k => $v) $roles[$k] = Yii::t('nin', $v);
?>
Vytvoríme a preložíme zoznam rolí, ktorý potrebujeme pre dropdown filter v tabuľke. Prvé čo vám môže prísť divné je, že nepoužívam foreach s referenciou aj keď robím presne to, na čo je určený. Dôvod je taký, že ešte aj v PHP 5.3 je zabugovaný a občas kvôli nemu padá class autoloading a tým pádom aj celý skript.
<?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'user-grid', 'dataProvider'=>$model->with('role')->search(), 'filter'=>$model, 'columns'=>array( 'id', array( 'name'=>'id_role', 'filter'=>$roles, 'value'=>'Yii::t("nin", $data->role->name)',
Všimnite si, že tu je celý výraz v úvodzovkách, keďže 'value' sa eval()uje pre každý riadok tabuľky.
), array( 'name'=>'email', 'type'=>'email', ), //'password', 'name', 'member_since', array( 'name'=>'status', 'filter'=>array('active'=>Yii::t('nin','active'), 'blocked'=>Yii::t('nin','blocked')), 'value'=>'Yii::t("nin", $data->status)', ), array( 'class'=>'CButtonColumn', ), ), )); ?>

Po týchto úpravách by malo byť preložené všetko na stránke zoznamu používateľov až na jeden malý detail. Pravé menu stále nesie nápis "Operations" a zmeniť ho môžete na trochu nečakanom mieste v súbore protected/views/layouts/column2.php.

Posledným dôležitým krokom bude pridanie lokalizovaného jQuery UI DatePickera do formulára - protected/views/user/_form.php. Zaujímavou vlastnosťou je, že okrem názvov dní, mesiacov a formátu dátumu sa mení aj rozloženie kalendára. Nie všetky krajiny totiž začínajú týždeň pondelkom, ako je u nás zvykom.

<div class="row">
	<?php echo $form->labelEx($model,'member_since'); ?>
	<?php echo $this->widget('zii.widgets.jui.CJuiDatePicker', array('model'=>$model,
		'attribute'=>'member_since',
		'language' => (Yii::app()->getLanguage() == 'en' ? null : Yii::app()->getLanguage()) ),
		true) ?>
	<?php echo $form->error($model,'member_since'); ?>
</div>

Asi sa pýtate prečo chodíme okolo horúcej kaše™ s ternárnym operátorom pri atribúte "language".. nuž chyba je čiastočne v jQuery UI a prejavuje sa tak, že pokiaľ nevie nájsť zadaný jazyk, použije čínštinu (wtf). Ešte čudnejšie je, že angličtinu nemá definovanú ako "en" (čiže ju nenájde) a použije ju iba ak neuvediete žiadny jazyk.

Pro tip: v PHP 5.3 má ternárny operátor aj alternatívnu syntax, kedy sa použije ako prvá hodnota podmienka. V praxi by sme namiesto $hodnota ? $hodnota : "nie je nastavená hodnota" mohli napísať len $hodnota ? : "nie je nastavená hodnota".

Na dokončenie prekladu celej aplikácie treba ešte poprepisovať pár drístov vo zvyšných view-och. To už nebudem rozpitvávať, keďže v každom view-e stačí poobalovať pár slov do Yii::t(). V podstate je to repetitívna činnosť, ktorej sa chceme vyhnúť a preto si niekedy nabudúce povieme ako customizovať generátor kódu, aby toto robil za nás. ^^

Pokračovanie nabudúce
Tutoriál dokončíme v ďalšej časti, kde sa dozviete ako vytvoriť všade prítomný dropdown na zmenu jazyka, ako zohľadniť i18n z hľadiska SEO a ako generovať pekné/clean adresy URL. Toto pokračovanie zverejníme vo štvrtok 3. februára 2011 o 20:00. Tak si nastavte prípomienky. Alebo nás sledujte cez RSS, Facebook či Twitter.

Ďalšie časti seriálu Ako sa stať PHP ninja s Yii Frameworkom nájdeš tu:
dev > Yii

P.S.: Ak sa ti tento framework zdá veľmi zložitý, pozri si naše video lekcie k frameworku CodeIgniter na Zajtra.sk.
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

2 komentáre 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á 5.2.2012 15:18:07
Ďakujem za článok. Možno by sa zišlo upozorniť, že Yii je v utf8 a diaktritika nepôjde, pokiaľ editujete súbory napríklad s nastaveným editorom v ISO-8859-2. Ak to bolo spomenuté, tak som si to nevšimla.
0 0 Roland Csibrei (fb) 5.2.2011 00:00:00
Diky za clanok, je dobre, ze niekto si najde cas aj na toto :) K i18n activerecordov by som odporucal pouzivat behavior a nie overrideovat kazdy model: http://www.yiiframework.com/doc/api/1.1/CActiveRecordBehavior/
Zajtra.sk > Programovanie > PHP > Yii framework: I18n ako naučiť aplikáciu po slovensky (1)


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