Jazyk jako GET parametr a odebrani z URL

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
hurvajs
Člen | 86
+
0
-

Zdravím, přepínání jazyků jsem měl už vyřešené, ale zákazník přišel s tím, že nechce URL ve tvaru http://admin/ a ne http://cs/admin/ s tím, že si může kdykoliv vybrat jazyk. Ten se pak předá přes GET. Přepínání mi funguje, ale chtěl bych se zeptat, jestli jde nějak GET parametr „vyndat“. Raději uvedu příklad:

Admin v
* češtině: http://admin/?lang=cs nebo http://admin/
* angličtině: http://admin/?lang=en

Jednoduše mi jde o to, aby v HTML kódu byly URL generovány ve tvaru http://admin/?lang=cs, ale aby router takovou adresu zachytil, ale vygeneroval URL jen ve tvaru http://admin/ s tím, že lang si uloží do persistentniho parametru.

Je mi jasné, že by to šlo řešit napsaním vlastního routeru, kde si to upravím jak potřebuji. Jen se mi to zdá zbytěčné.

Momentálně to mám takto (zatím jen zjednodušená verze)

<?php
if (function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) {
	Route::addStyle('?lang', null);
	Route::setStyleProperty('?lang', Route::PATTERN, '[a-z]{1,3}');

	Route::setStyleProperty('?lang', Route::FILTER_OUT, 'getLangNameById');
	Route::setStyleProperty('?lang', Route::FILTER_IN, 'getLangIdByName');

	$router[] = new Route('admin/<presenter>/<action>/<id> ? <lang>', array(
		'module'    => 'Backend',
		'presenter' => 'Default',
		'action'    => 'default',
		'id'        => null,
		'lang'      => null
	));
} else {
	$router[] = new SimpleRouter('Frontend:Homepage:show');
}


function getLangNameById($s)
{
	return $s == 'cs' ? null : 'en';
}

function getLangIdByName($s)
{
	return $s == 'cs' ? null: 'en';
}
?>
Toto funguje pouze za předpokladu, že dostanu url ve tvaru
http://admin/
http://admin/?lang=en
Selže na
http://admin/?lang=cs – což je samozřejmě pochopitelné, protože místo ‚cs‘ vracím ‚null‘.
_Martin_
Generous Backer | 679
+
0
-

Jestli ti dobře rozumím, tak akorát ten parametr lang vyndej z tvaru URL (čili <lang> pryč) a nech mu výchozí hodnotu na cs. Potom jej Nette bude předávat jako standardní parametr za otazníkem. A v případě, že se bude rovnat cs, tak převede na kanonickou URL bez toho parametru.

hurvajs
Člen | 86
+
0
-

No uplne presne je mym cilem to, aby Nette reflektovalo nastaveni jakyka, ale nezobrazovalo mi ho v URL prohlizece. Ci-li abych v URL mel treba /admin/user/list/, ale v HTML byly vygenerovany s lang/admin/user/list/?lang=cs. S tim, ze se ?lang ulozi treba do $_SERVER.

Doufam, ze je to srozumitelne.

To _martin_: pripadne mohu poskytnout ICQ a muzeme to probrat… ;-)

Editoval hurvajs (15. 11. 2009 16:44)

_Martin_
Generous Backer | 679
+
0
-

hurvajs napsal(a):

No uplne presne je mym cilem to, aby Nette reflektovalo nastaveni jakyka, ale nezobrazovalo mi ho v URL prohlizece. Ci-li abych v URL mel treba /admin/user/list/, ale v HTML byly vygenerovany s lang/admin/user/list/?lang=cs. S tim, ze se ?lang ulozi treba do $_SERVER.

Doufam, ze je to srozumitelne.

To _martin_: pripadne mohu poskytnout ICQ a muzeme to probrat… ;-)

No, asi tak: pokud chceš reflektovat nějaký stav aplikace a ten stav nemá být zohledněn v URL, pak (vzhledem k tomu, že protokol HTTP je bezstavový) nezbývá, než si jej uložit někam jinam – třeba do session.

Můj názor sice je, že zrovna jazyk by měl být v URL zohledněn, ovšem tvého klienta asi těžko přesvědčím…

Proti ICQ bych se nebránil, ale když to řešíme tady, tak má víc uživatelů šanci, že na to narazí při řešení svého problému.

hurvajs
Člen | 86
+
0
-

Jasne, to chápu, že musím někam tu proměnnou uložit, abych si pamatoval její nastavení. Rozdodně odmítám cookies.

Mě by v podstatě stačilo, říct nějak MultiRouteru, aby při překládání URL nepoužil ?lang=cs. Protože, jestli chápu dobře router, tak se nejprve zjistí jestli daná URL odpovídá masce routeru (match()) a pak se dál v aplikaci volá (constructUrl()).

Ted pro gettext nastavuji přes putenv() proměnnou s jazykem, na základě ní pak nastavím gettext. Zkoušel jsem i unsetnout parametr lang, ale nic nezabralo.

_Martin_ napsal(a):
Můj názor sice je, že zrovna jazyk by měl být v URL zohledněn, ovšem tvého klienta asi těžko přesvědčím…

Tak to je i můj názor. Proto jsem měl původně URL ve tvaru http://cs/admin/. Bohužel to tak zákazník chce a stojí si na tom, že to chce ukládat max. do serverového prostředí.

Jinak to s tim ICQ, jsem myslel, tak že by to bylo rychlejší, nemám problém to řešit zde a bude to jak, píšeš přínosem i pro jiné.

_Martin_
Generous Backer | 679
+
0
-

No, když to nemá být v URL, tak to nesmí být ani v routeru. A pakliže (jestli to dobře chápu) máš ten jazyk v URL kvůli přepínání mezi jazyky, tak bude lepším řešením použít signál. Samotný lang do routeru vůbec nedávej. A to, že defaultně bude čeština, nastav logikou, která si to ukládá (třeba do té SESSION – neni klíč v SESSION, nastaví ho na cs).

hurvajs
Člen | 86
+
0
-

_Martin_ napsal(a):

No, když to nemá být v URL, tak to nesmí být ani v routeru. A pakliže (jestli to dobře chápu) máš ten jazyk v URL kvůli přepínání mezi jazyky, tak bude lepším řešením použít signál. Samotný lang do routeru vůbec nedávej. A to, že defaultně bude čeština, nastav logikou, která si to ukládá (třeba do té SESSION – neni klíč v SESSION, nastaví ho na cs).

To jsem si myslel, že to nesmí být ani routeru. Řešení pomocí signálu mě nenapadlo, ještě jsem to neřešil. Takže musím nastudovat signály. Předpokládám, že to bude v dokumentaci, ale neměl bys nějaké malé rychlé how to? ;-)

Ten session je opravdu jediné řešení, protože pokud nemohu použít cookies, tak to není kam uložit, tak abych měl informaci i pro další stránky.

lucass
Člen | 89
+
0
-

Třeba do BasePresenteru si dej handleChangeLang() s parametrem $lang.

<?php

...

public function handleChangeLang($lang) {
	$sess = Environment::getSession('project');
	$sess->lang = $lang;
}

...

?>

Defaultně, třeba při startupu, si tu session získej a zjisti aktuální nastavení jazyka, a když bude lang v session prázdný, tak mu šoupni nějakej default, třeba cs.

V šabloně s jazyky by pak mělo stačit:

<a href="{plink changeLang! 'cs'}">česky</a>
<a href="{plink changeLang! 'en'}">anglicky</a>

Editoval lucass (15. 11. 2009 20:28)

_Martin_
Generous Backer | 679
+
0
-

Lucass mě s odpovědí předběhl, ale nevadí – líp bych to ani já nesepsal=)

K té cookie: myslel jsi to tak, že do cookie nechceš ukládat přímo ten jazyk? Protože při použití session slouží cookie jako její identifikátor, čili cookie musí být použita. Možná jsi to přesně tak myslel – jen chci mít jistotu, že si rozumíme.