Překlad url adresy do více jazyků

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

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
+
0
-

Teď mě napadá:

Route::FILTER_OUT => function ($str) {
   return $this->getContext()->translator->translate($str);
}

Je to hloupost?

Filip Procházka
Moderator | 4668
+
0
-

Jenom částečně :)

Route::FILTER_OUT => function ($str) use ($container) {
	return $container->translator->translate($str);
}
raketoplan2005
Člen | 147
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

Své řešení (nejspíš mírně neobratné) jsem dával sem: https://forum.nette.org/…ekonecna-url

raketoplan2005
Člen | 147
+
0
-

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
+
0
-

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)