Překlad url adresy do více jazyků
- raketoplan2005
- Člen | 147
Ahoj,
v aplikaci používám gettext překladač (tento https://componette.org/search/?…). V databázi mám uložený seznam url základních rubrik (např. photos, videos, audio…) v angličtině.
Čeho bych chtěl docílit jsou takovéto URL:
mujweb/cs/fotky
mujweb/en/photos
mujweb/pl/zdjecja
Našel jsem v sekci o routování možnost definování slovníku:
$route = new Route('<presenter>/<action>/<id>', array(
'presenter' => array(
Route::VALUE => 'Homepage',
Route::FILTER_TABLE => array(
// řetězec v URL => presenter
'produkt' => 'Product',
'kosik' => 'Cart',
'katalog' => 'Catalog',
),
),
'action' => 'default',
'id' => NULL,
));
Do toho bych ale musel definovat všechny kategorie ručně pro všechny jazyky a tyto překlady tedy udržovat v databázi místo využití gettextu, že?
Napadá vás prosím nějaké rozumné řešení?
Děkuji!
Editoval raketoplan2005 (22. 7. 2012 21:57)
- raketoplan2005
- Člen | 147
Teď mě napadá:
Route::FILTER_OUT => function ($str) {
return $this->getContext()->translator->translate($str);
}
Je to hloupost?
- Filip Procházka
- Moderator | 4668
Jenom částečně :)
Route::FILTER_OUT => function ($str) use ($container) {
return $container->translator->translate($str);
}
- raketoplan2005
- Člen | 147
Paráda, opravdu děkuji moc, nicméně jsem to koukám stejně nedomyslel. Nedokážu totiž sestavit FILTER_IN který jsem si tajně myslel že nebudu potřebovat :(
Editoval raketoplan2005 (24. 7. 2012 0:03)
- raketoplan2005
- Člen | 147
Tak jsem se vrátil ke starému problému a stále si s ním nevím rady, jednu chvíli se mi zdálo že to funguje i pouze s filter out, ale zjevně jen do doby, kdy mi to začalo kolidovat s jinými pravidlami rout.
Jak řešíte (pokud ano) překlad URL vy?
- raketoplan2005
- Člen | 147
Ahoj ještě jednou,
řeším stále stejný problém a jak vidím v dalších vláknech, nejsem možná sám.
Jde o překlad URL adresy za předpokladu použití gettextu. Svůj problém zkonkretizuji a rád bych se s vámi poradil o jeho řešení.
Oproti původnímu dotazu jsem nyní změnil strukturu URL změnil na následující:
web/kategorie
kde jako kategorie můžu mít libovolně dlouhý řetěz kategorií oddělených lomítkem např.
web/pecivo/rohliky/svetle
(inspirováno tímto https://forum.nette.org/…egorie-z-url )
Tento řetězec by měl být přeložený gettextovým překladačem do aktuálně zvoleného jazyka, kategorie jsou uložené v databázi, každá má mj. ID a název.
Teď jak bych to chtěl (resp. jediné co mě napadlo) řešit, protože k původnímu nedokáži napsat FILTER_IN (nedokáži z translatoru vytáhnout originální řetězec podle přeloženého):
Do filtrů routy
<lang [a-z]{2}>/]<id_kategorie>
bych přidal funkci uriToId a IdToUri, které by zajišťovaly převod na a z ID kategorie a pracovala by zřejmě s poli.
Tato pole by měla např. následující strukturu:
array(
1 => "pecivo"
2 => "pecivo/rohliky"
)
přičemž pole by se vytvořilo pro výchozí jazyk standardně a pro ostatní projitím cýchozího pole, explodováním podle „/“, přeložením jednotlivých částí a opetovným složením.
Tato pole by se po vytvoření uložila do cache.
Co si o tom myslíte? Přijde mi to samotnému hloupé, ale jiné řešení jsem nevymyslel.
Související:
https://forum.nette.org/…u-z-gettextu
https://forum.nette.org/…met-en-title
Editoval raketoplan2005 (26. 8. 2012 18:43)
- Aurielle
- Člen | 1281
Své řešení (nejspíš mírně neobratné) jsem dával sem: https://forum.nette.org/…ekonecna-url
- raketoplan2005
- Člen | 147
Děkuji moc za tip, na ten topic jsem sám nenarazil. Bude lepší když překlady (jen) URL budu řešit v databázi a zbytek gettextem?
Editoval raketoplan2005 (26. 8. 2012 23:16)
- raketoplan2005
- Člen | 147
Ahoj,
na zaklade vasich rad a odkazu jsem si pripravil nasledujici reseni, ktere bych s vami rad probral. Muzete se na to vy zkusenejsi, prosim, podivat?
Zatim se zda ze to funguje, nicmene chtel bych s vami konzultovat reseni
obecne, co by bylo podle vas vhodne cachovat a take problem, ktery se mi
objevil.
Pokud mam duplicitni cast URL a tedy porovnavam i jine nez posledni
cast URL, vrati mi filter in sice spravne ID kategorie, ale skoncim ve „Smycce
pri presmerovani“. Pokud v presenteru nastavim autoCanonicalize na FALSE,
pote se chyba neprojevi.
--
Upadte: Problém s cyklením jsem již opravil, měl jsem špatně práci s poli v categoryFilterIn.
--
DĚKUJI!
Vyuzivam FilterRoute a to nasledovne:
$router[] = $route = new FilterRoute("[<lang [a-z]{2}>/]<category .*?>/", array(
"presenter" => "Homepage",
"action" => "default",
"category" => NULL
));
$route->addFilter('category', callback($container->categoryRouter, "categoryFilterIn"),
callback($container->categoryRouter, "categoryFilterOut"));
Trida CategoryRouter pak obsahuje filtracni metody:
<?php
class CategoryRouter extends \Nette\Object {
private $context;
private $menu;
public function __construct(\Nette\DI\Container $container) {
$this->context = $container;
$this->menu = $this->context->createMenu();
}
public function categoryFilterIn($slug, \Nette\Application\Request $request) {
// ziskame jazyk
$lang = $request->parameters['lang'];
// nastaveni gettextoveho prekladace
$translator = $this->context->translator;
$translator->setLang($lang);
// rozdeleni URL na casti
$temp = explode('/', trim($slug, '/'));
$slugs = array();
// stahneme vsechny dostupne URL pro kategorie v originalnim (EN) jazyce
$result = $this->menu->getCategorySlugs();
// pripravime si prelozene URL pro kategorie
foreach ($result as $cat_id => $slug) {
$slug = $translator->translate($slug);
$slugs[$cat_id] = $slug;
}
// dohledame ID kategorie pro preklad posledni casti URL
$actual_slug = end($temp);
$matches = array_keys($slugs, $actual_slug);
// pokud je toto unikatni, vratine rovnou ID kategorie
if (count($matches) == 1) {
$return = $matches[0];
}
// pokud neznam tuto URL, nema cenu pokracovat
elseif (count($matches) == 0) {
$return = NULL;
// jinak - tzn. mam vice moznych ID k danemu slovu
} else {
// pro kazdou tuto moznost ziskam z databaze vsechny rodice
$candidates = array();
foreach ($matches as $candidate) {
$candidates[$candidate] = $this->menu->getCategoryParentsIds($candidate);
}
$temp = array_reverse($temp);
$actual = reset($temp);
$actual = next($temp);
// postupne porovnavam explodovane casti URL az do okamziku kdy nemam
// duplicitni cast
while (!is_null($key = key($temp))) {
$finalists = array();
foreach ($candidates as $can_key => $can_val) {
if ($slugs[$can_val[$key]] == $actual) {
$finalists[$can_key] = $candidates[$can_key];
}
}
if (count($finalists) === 1) {
$return = key($finalists);
} elseif (count($finalists) === 0) {
$return = NULL;
} else {
$candidates = $finalists;
}
$actual = next($temp);
}
}
// vratim ID rubriky
return $return;
}
public function categoryFilterOut($id, \Nette\Application\Request $request) {
// nastavim gettextovy prekladac
$translator = $this->context->translator;
$translator->setLang($request->parameters['lang']);
// z databaze vezmeme vsechny nadrazene rubriky
$result = $this->menu->getCategoryParentsById($id);
// sestavime prelozenou URL
$return = NULL;
foreach ($result as $slug) {
if ($return == NULL) {
$return = $translator->translate($slug);
} else {
$return = $return . "/" . $translator->translate($slug);
}
}
// vratime URL
return $return;
}
}
Editoval raketoplan2005 (6. 11. 2012 15:58)