Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zend_Translate - Zend_Navigation and Routing combination problem!

I'm having some difficulties with the combination of Zend_Navigation, Zend_Translate and the routing needed.

My site navigation is done through Zend_Navigation based on and XML file. I've now added translation to the site based on Zend_Translate and added to following change of routing to the bootstrap:

protected function _initRoutes()

    $config = new Zend_Config($this->getOptions());
    $languages = array_keys($config->languages->toArray());
    $zl = new Zend_Locale();
    $lang = in_array($zl->getLanguage(), $languages)
                  ? $zl->getLanguage() : 'en';

    $zfc = Zend_Controller_Front::getInstance();


    // add language to default route
    $route = new Zend_Controller_Router_Route(
            ':lang/:module/:controller/:action/*',
      array('controller'=>'index',
                'action' => 'index',
                'module'=>'default',
                'lang'=>$lang));

    $router = $zfc->getRouter();
    $router->addRoute('default', $route);
    $zfc->setRouter($router);

I've then created a View_Helper with a preDispatc method:

    $language = $request->getParam('lang','');

 if ($language !== 'en' && $language !== 'da')
     $request->setParam('lang','en');

 $language = $request->getParam('lang');
 if ($language == 'en')
     $locale = 'en_EN';
 else
     $locale = 'da_DK';

 $zl = new Zend_Locale();
 $zl->setLocale($locale);
 Zend_Registry::set('Zend_Locale', $zl);

 $translate = new Zend_Translate('csv', APPLICATION_PATH . '/configs/language/'. $language . '.csv' , $language);
 Zend_Registry::set('Zend_Translate', $translate);

Now when I go to: "site/en/module/controller/action" it works fine.

When I go to: "site/da/module/controller/action" the translation works fine, but my links from Zend_Navigation is pointing to the default 'en' language link "site/en/module2/controller2/"

I cant figure out to know that your at /da/ language. Any help would be appriciated.

Kind regards,

Morten

like image 251
Morten Avatar asked Feb 27 '10 08:02

Morten


2 Answers

This doesn't directly answer your question. But Zend_View_Helper_Navigation, the view helper for navigation, has a setTranslator() method that will provide implicit translation of the navigation 'pages' that you have added to the Zend_Navigation container.

class MyModule_Bootstrap extends Zend_Application_Module_Bootstrap
{
   protected function _initMyModuleNavigation()
   {
    $langSess = new Zend_Session_Namespace('language');
    $translate = $langSess->translate;

    $this->getApplication()->bootstrap('navigation');

    $view = $this->getApplication()->getResource('view');

    $navigationHelper = $view->getHelper('navigation');

    $navigation = $navigationHelper->getContainer();

    $navigationHelper->setTranslator($translate);

    //...
}

This saves you having to manually call translate for each item

$navigation->addPages(array(
        new Zend_Navigation_Page_Mvc(array(
            'label' => $translate->_('Wiki'), //<-- This can be eliminated
            'action' => 'index',
            'controller' => 'article',
            'module' => 'wiki',
            'pages' => //...

as it will be done automatically because setTranslator() was done.

like image 156
Kurt Krueckeberg Avatar answered Oct 05 '22 23:10

Kurt Krueckeberg


Because Zend_Navigation_Page_Mvc only checks for Module, Controller and Action it looks like it will never goes to additional routing element.

One solution could be to use a new class such as: Zend_Navigation_Page_Mvcl which will handle language.

But it seems a bit complex so I found one solution by using a larger navigation which includes all the pages in all the languages.

This is my xml config for navigation for 2 pages "home","test" in french and english:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <nav>
        <fr>
            <label>menu.home</label>
            <params>
                <lang>fr</lang>
            </params>
            <action>index</action>
            <controller>homepage</controller>
            <route>langcontrolleraction</route>
            <pages>
                <home>
                    <label>menu.home</label>
                    <params>
                        <lang>fr</lang>
                    </params>
                    <action>index</action>
                    <controller>homepage</controller>
                    <route>langcontrolleraction</route>
                </home>
                <test>
                    <label>menu.wallet</label>
                    <params>
                        <lang>fr</lang>
                    </params>
                    <action>index</action>
                    <controller>wallet</controller>
                    <route>langcontrolleraction</route>
                </test>
            </pages>
        </fr>
        <en>
            <label>menu.home</label>
            <params>
                <lang>en</lang>
            </params>
            <action>index</action>
            <controller>homepage</controller>
            <route>langcontrolleraction</route>
            <pages>
                <home>
                    <label>menu.home</label>
                    <params>
                        <lang>en</lang>
                    </params>
                    <action>index</action>
                    <controller>homepage</controller>
                    <route>langcontrolleraction</route>
                </home>
                <test>
                    <label>menu.wallet</label>
                    <params>
                        <lang>en</lang>
                    </params>
                    <action>index</action>
                    <controller>wallet</controller>
                    <route>langcontrolleraction</route>
                </test>
            </pages>
        </en>
    </nav>
</config>

As you can see it's quite long just for 2 pages. Actually you will have (pages + 1) x languages items in the navigation

I did use a 'trick': the homepage is present twice.

  • once as main menu item
  • once as first submenu item

The idea is to define which submenu to display based on the selected lang and this is automatically done via the router, so all you have to do is to tell your application to draw the submenu instead of the menu. So here is the line I use for that in my layout file:

<?php 
echo $this->navigation()->menu()->renderSubMenu() 
?>

I didn't see how you added the Zend_Navigation so here is mine from Bootstrap.php:

<?php
protected function _initNavigation() {
    $config = new Zend_Config_Xml(Zend_Registry::get ( 'config' )
            ->resources->navigation->file, 'nav');
    $navigationContainer = new Zend_Navigation($config);
    // Store the container in the proxy helper:
    $view = $this->getResource ( 'view' );
    $view->getHelper('navigation')->setContainer($navigationContainer);
}
?>

By the way, in the same Bootstrap.php I can keep the default language to 'en', here is my _initRoutes():

<?php
protected function _initRoutes() {
    $router = Zend_Controller_Front::getInstance ()->getRouter ();
    $router->removeDefaultRoutes ();
    $myRoute = new Zend_Controller_Router_Route (
        ':lang/:controller/:action',
        array (
            'lang' => 'en',
            'controller' => 'index',
            'action' => 'index',
        )
    );
    $router->addRoute ( 'langcontrolleraction', $myRoute );
}
?>

And for translation it's automatically done if you registered your Zend_Translate. In my example: menu.home will give:

  • Home in english
  • Accueil in french

I hope this helps.

I would prefer another more subtle solution but I didn't find it yet.

like image 37
Sébastien Barbieri Avatar answered Oct 05 '22 23:10

Sébastien Barbieri