Vícejazyčné routy – styly pro konkrétní jazyk

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

Ahoj,
řeším naprosto shodný problém jako uživatel lucass v tomto threadu, ale nespokojím se s tímto řešením:

$router[] = new Route('cs/<presenter #cs-presenter>/<action>/<name>', array(
        'lang' => 'cs',
        'presenter' => 'Default',
        'action' => 'default',
        'name' => NULL
));

$router[] = new Route('en/<presenter #en-presenter>/<action>/<name>', array(
        'lang' => 'en',
        'presenter' => 'Default',
        'action' => 'default',
        'name' => NULL
));

(fakt nechci mít počet rout = potřebný počet rout x počet jazyků aplikace)

Jde o to, že se potřebuji dostat ke zvolenému jazyku v URL (který je reprezentován persistentním parametrem v BasePresenteru) ještě před definicí rout, abych tam mohl dát nějakou podmínku, podle které se vybere překladový slovník.

Anebo spojit tyto dvě routy do jedné, ale by to fungovalo, jak má :) (při lang cs v URL „produkty“, při en „products“ atd.)

redhead
Člen | 1313
+
0
-

Tohle řeším teď také a je to fakt peklíčko.

Neměl jsem jinou možnost a tahám lang přímo z URL přes regulár. Ještě větší peklo je do toho naroubouvat překladové pole z anotací presenterů a action/render metod (kde názvy předkládám do jiných jazyků než angličtiny). Ale jde mi to jen s jednou routou. Jediný problém je, když měním jazyk mezi dvěma ne-anglickými jazyky mimo homepage (přepíše totiž url na presenter/view který v překladovým slovníku 2. jazyka pochopitelně neexistuje a skončí chybou :( ).

Ale rád bych viděl jiné řešení (že by samotných rout?) a lang nějak měnit už při definici rout..

Jan Tvrdík
Nette guru | 2595
+
0
-

Jsem líný to číst a přemýšlet nad tím, ale vlastní router (interně může využívat třídu Route) je určitě funkční řešení :)

Vyki
Člen | 388
+
0
-

Já už zápas s obecnými routy v nette také vzdal. Je to napsané pěkně, ale je jasné, že každému to vyhovovat nemůže. Napsat vlastní routu mi zabralo méně času než vymýšlet jak to udělat pomocí multi route. Nevýhodu je udržování vlastních rout. Vždy když se lehce změní filozofie v linkování, musím přepsat routu.

Ondřej Mirtes
Člen | 1536
+
0
-

Já to asi taky vzdám – ale tím způsobem, že před definicí rout rozparsuju aktuální query string a zvolený jazyk z toho nějak uhodnu.

Třída Route je v Nette totiž moc pěkná a zatím mi vždy stačila :)

Mohl by se k tomu vyjádřit David – řešit DG!

Honza Marek
Člen | 1664
+
0
-

Napsat vlastní router OM! :D

Ondřej Mirtes
Člen | 1536
+
0
-

Honza Marek napsal(a):

Napsat vlastní router OM! :D

Hehe :o) Já mám za to, že „řešit DG“ jsou ještě pořád klíčový slova, který občas David zadává do hledání a prochází thready, který se mu ukážou…

Honza Kuchař
Člen | 1662
+
0
-

Ondřej Mirtes napsal(a):

Honza Marek napsal(a):

Napsat vlastní router OM! :D

Hehe :o) Já mám za to, že „řešit DG“ jsou ještě pořád klíčový slova, který občas David zadává do hledání a prochází thready, který se mu ukážou…

Myslím, že už je to příliš profláknuté. :)

David Grudl
Nette Core | 8152
+
0
-

Vymyslet OM!

Ondřej Mirtes
Člen | 1536
+
0
-

Protože se ty dvě routy liší naprosto minimálně, napadlo mě, že by se do definice tvaru routy dala zavést syntaxe pro nahrazování proměnných. Příklad:

$router[] = new Route('<lang>/<presenter #@lang-presenter>/<action>/<name>', array(
        'lang' => NULL,
        'presenter' => 'Default',
        'action' => 'default',
        'name' => NULL
));

Pokud bych šel na url začínající na /cs/, tak by se ve výsledku aplikoval slovník z třídy #cs-presenter. Je tu pár problémů:

  • Jak poznám, že končí název té proměnné? Jelikož mě nenapadá jiné využití této syntaxe, než u těch překladových tříd, tak by se mohla použít ta pomlčka. Anebo na to jít obráceně – projít všechny definované parametry a hledat jejich @param podobu ve tvaru routy.
  • Uživatel může do URL zadat cokoli a já takovou třídu nemám definovanou, co s tím? Co třeba nepřekládat?
  • Pokud bych zadal #@param a přitom by param nebyl nikde definovaný – žádný persistentní parametr, žádný parametr actionu, žádný handler signálu – vyhodil bych výjimku…

Uff, Windows mi vyhodily BSOD v momentě odeslání příspěvku :o)

Editoval Ondřej Mirtes (26. 1. 2010 23:26)

kravčo
Člen | 721
+
0
-

Kým tu filozofuješ nad tým, ako by sa to mohlo implementovať do Nette, mohol si mať napísaný vlastný router!

class OM_Vymyslet_Router extends Route
{
    public function match(IHttpRequest $httpRequest)
    {
        $appRequest = parent::match($httpRequest);
        OM_Vymyslet_Translator::inverse_translate($appRequest);
        return $appRequest;
    }

    public function constructUrl(PresenterRequest $appRequest, IHttpRequest $httpRequest)
    {
        OM_Vymyslet_Translator::translate($appRequest);
        return parent::constructUrl($appRequest, $httpRequest);
    }
}

Stačí už len vymyslieť translator, ktorý sa postará o logiku.

Vlastne logiku som vymyslel ja… treba už len Translator, ktorý to preloží…

PaBi3
Bronze Partner | 62
+
0
-

Myslím, že tvoje riešenie po preklade pozmení aj PresenterRequest a nie iba URL ako sa vyžaduje. Problém je v tom, že neexistuje čistý spôsob pre načítanie parametra z routy predtým, než sa nastaví prekladová tabuľka. Možné riešenie je napr. pridať udalosť onStartup triede Application a následne vyparsovať jazyk z URL. Zjednodušiť by to mohol nový objekt HttpRequest. Prípadne by sa toto celé dalo zrealizovať v konštruktore služby Nette\Application\IRoute (vlastný MultiRouter).

Editoval PaBi3 (27. 1. 2010 5:33)

norbe
Backer | 405
+
0
-

Já na podobné věci používám upravený SeoRouter (původní měl nějaké nedostatky, kvůli kterým se choval dost divně, už si nepamatuju co přesně jsem upravoval), který mi umožňuje zapsat routy v následujícím tvaru:

/****** All pages ~ Article ~ Homepage  *****/
$router[] = new SeoRouter( // display one item
	'<lang>/<presenter>/<id>',
	array(
		'module' => 'Frontend',
		'action' => 'default',
	),
	0,
	array(
		'presenter' => array('lang'),
		'id' => array('lang', 'presenter'),
	),
	array(
		array('id', new Action(), 'presenter' => 'action'),
		array('id', new News(), 'presenter' => 'news'),
		array('id', new PhotogalleryAlbum(), 'presenter' => 'photogallery'),
		array('presenter', new RouteFilter()),
	));

/****** Articles *****/
$router[] = new SeoRouter(
	'<lang>/<id>',
	array(
		'module' => 'Frontend',
		'presenter' => 'Article',
		'action' => 'default',
	),
	SeoRouter::SITE_MAP,
	array(
		'id' => array('lang'),
	),
	array(
		array('id', new Article()),
	));
...

Není to sice ideální, ale na napsání celého vlastního routeru zatím nebyl čas. Každopádně kdyby měl někdo zájem, tady si ho můžete stáhnout (snad se původní autor nebude zlobit).

Ondřej Mirtes
Člen | 1536
+
0
-

kravčo: A co když usiluju o to, aby to bylo ve frameworku? Vždyť každý potřebujeme psát vícejazyčné weby – a současné řešení rozhodně není DRY, ani efektivní. Co když budu potřebovat čtyřjazyčný web? To dělá třeba 4×6 rout.

A proč by si každý, co tohle potřebuje vyřešit, psal vlastní router, když ve frameworku už je téměř vše potřebné (překladové třídy) a zbývá poslední krůček, aby to bylo použitelné?

Pro mě za mě bych si napsal $lang = substr($_SERVER['REQUEST_URI'], 0, 2) a dával to do tvaru rout, ale jde mi o ideální řešení, což je podpora ve frameworku.

kravčo
Člen | 721
+
0
-

Ondřej Mirtes napsal(a):

kravčo: A co když usiluju o to, aby to bylo ve frameworku? Vždyť každý potřebujeme psát vícejazyčné weby – a současné řešení rozhodně není DRY, ani efektivní. Co když budu potřebovat čtyřjazyčný web? To dělá třeba 4×6 rout.

Asi sa budem opakovať, ale takéto usilovanie je veľmi príjemné… Aj ja mám miliónpäťsto nápadov, čo všetko by mohlo byť vo frameworku a nemusel som to riešiť ja, no David na to podľa mojich výpočtov čas nemá…

Možnosťou, ako zabezpečiť, že niečo vo frameworku bude je aj napísať to, vyladiť to, otestovať to a požiadať o zaradenie do frameworku. Máme github ktorý z toho robí operáciu na pár klikov. Ak David vylepšenie z akéhokoľvek dôvodu do frameworku nepridá, je možné to hodiť do addons, čím k nemu komunita získa prístup tak či tak.

A proč by si každý, co tohle potřebuje vyřešit, psal vlastní router, když ve frameworku už je téměř vše potřebné (překladové třídy) a zbývá poslední krůček, aby to bylo použitelné?

Aj ty môžeš byť tým, kto ten posledný krok urobí.

Pro mě za mě bych si napsal $lang = substr($_SERVER['REQUEST_URI'], 0, 2) a dával to do tvaru rout, ale jde mi o ideální řešení, což je podpora ve frameworku.

Prečítaj si ešte raz náčrt, ktorý som napísal vyššie, a skús mu porozumieť.

Ondřej Mirtes
Člen | 1536
+
0
-

Jasně, tohle už je rozumnější příspěvek :) Ten kód výše chápu, o něco takového se pokusím. Případně rovnou upravím třídu Route, aby to šlo začlenit do frameworku.

kravčo
Člen | 721
+
0
-

Ondřej Mirtes napsal(a):

Jasně, tohle už je rozumnější příspěvek :) Ten kód výše chápu, o něco takového se pokusím. Případně rovnou upravím třídu Route, aby to šlo začlenit do frameworku.

Ten prvý zrejme vyznel inak ako som ho myslel, stáva sa… Šlo mi o to, že namiesto siahodlhého filozofovania o tom ako by to mohol niekto iný urobiť je niekedy lepšie prísť s vlastným riešením (a napríklad zistiť, že je úplne ale úplne zlé), na tom sa oveľa viac naučíme…