简体   繁体   中英

Add a language parameter in url in zend framework

I have a site in zend framework . Now I am making site in multiple language. For it I need to modify the url.

For example if sitename is www.example.com then i want to make it like

www.example.com/ch 
www.example.com/fr

There can be some work around it that you can ask me to create a folder name ch and put a copy of code inside it. But for it I have to manage multiple folder when updating files on server.

What is the best or correct way to do it ?

My routs code is

public function _initRouter() {
        $frontController = Zend_Controller_Front::getInstance();
        $router = $frontController->getRouter();
        $routes = array(
            'page' => new Zend_Controller_Router_Route('page/:slug', array('controller' => 'staticpage', 'action' => 'page', 'slug' => ''))
        );


        $router->addRoutes($routes);

    }

Thanks

You have to add the language as parameter in your route(s). Here is an example: http://devzone.zend.com/1765/chaining-language-with-default-route/

You need a function to get a user choice of a language and a default language used if a user just starts with example.com.

You may want to get the current browser and Language Header from the users HTTP request.

Take a look at Zend_Locale and Zend_Translate.

You can use something like $locale = new Zend_Locale('browser'); to detect the users browser language.

Then look if Zend_Translate or your translation engine has the language available and set it to a cookie or session to store the date.

If the user then navigate to some language change site like example.com/?language=en you may want to set the locale based on the user choice and recheck if available in your translations.

If not, get back to original default language and present an error page or something like that.

If you want to get your Zend_Router urls to be language dependent, which might be a bad choice because of copy paste, backlinks or forum posts of your links, you need to add something before each route.

In my Applications i use something like the following in my main bootstrap.php file. I've cut some parts of to keep it simple.

protected function _initTranslate() {
    $session = new Zend_Session_Namespace("globals");
    // Get current registry
    $registry = Zend_Registry::getInstance();
    /**
     * Set application wide source string language
     * i.e. $this->translate('Hallo ich bin ein deutscher String!');
     */
    if(!$session->current_language) {
        try {
            $locale = new Zend_Locale('browser'); //detect browser language
        }
        catch (Zend_Locale_Exception $e) {
            //FIXME: get from db or application.ini
            $locale = new Zend_Locale('en_GB');  //use the default language
        }
    }
    else {
        $locale = new Zend_Locale($session->current_language);
    }

    $translate = new Zend_Translate(
        array(
            'adapter' => 'array',
            'content' => realpath(APPLICATION_PATH . '/../data/i18n/'),
            'locale'  => $locale,
            'scan'    => Zend_Translate::LOCALE_DIRECTORY,
            'reload'  => false,
            'disableNotices' => true, //dont get exception if language is not available
            'logUntranslated' => false //log untranslated values
        )
    );

    if(!$translate->isAvailable($locale->getLanguage())) {
        $locale = new Zend_Locale('en_GB');  //default
    }

    $translate->setLocale($locale);

    $session->current_language = $locale->getLanguage();

    //Set validation messages
    Zend_Validate_Abstract::setDefaultTranslator($translate);
    //Max lenght of Zend_Form Error Messages (truncated with ... ending)
    Zend_Validate::setMessageLength(100);
    //Zend_Form Validation messages get translated into the user language
    Zend_Form::setDefaultTranslator($translate);

    /**
     * Both of these registry keys are magical and makes do automagical things.
     */
    $registry->set('Zend_Locale', $locale);
    $registry->set('Zend_Translate', $translate);

    return $translate;
}

This is for the default translation setup of each visitor.

To set a user language depending on some HTTP parameters, I decided to create a Plugin, which will run on each request, see if the global language parameter is set (key=_language) and try setting the new language.

I then redirect the user to the new route, depending on his choice.

So, if the user click on the link for english language (example.com/de/test/123?_language=en) he will get redirected to example.com/en/test/123.

class Application_Plugin_Translate extends Core_Controller_Plugin_Abstract {

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        $frontController = Zend_Controller_Front::getInstance();

        // Get the registry object (global vars)
        $registry = Zend_Registry::getInstance();

        // Get our translate object from registry (set in bootstrap)
        $translate = $registry->get('Zend_Translate');
        // Get our locale object from registry (set in bootstrap)
        $locale = $registry->get('Zend_Locale');

        // Create Session block and save the current_language
        $session = new Zend_Session_Namespace('globals');

        //get the current language param from request object ($_REQUEST)
        $language = $request->getParam('_language',$session->current_language);
        // see if a language file is available for translate (scan auto)
        if($translate->isAvailable($language)) {
            //update global locale
            $locale = $registry->get('Zend_Locale');
            $locale->setLocale($language);
            $registry->set('Zend_Locale', $locale);

            //update global translate
            $translate = $registry->get('Zend_Translate');
            $translate->setLocale($locale);
            $registry->set('Zend_Translate', $translate);

            //language changed
            if($language!=$session->current_language) {
                //update session
                $session->current_language = $language;

                $redirector = new Zend_Controller_Action_Helper_Redirector;
                $redirector->gotoRouteAndExit(array());
            }
        }
        else {
            $request->setParam('_language', '');
            unset($session->current_language);

            $redirector = new Zend_Controller_Action_Helper_Redirector;
            $redirector->gotoRouteAndExit(array());
        }
    }
}

And finally, to prepare your router with the new language routes, you need to setup a base language route and chain your other language depending routes.

public function _initRouter() {
    $frontController = Zend_Controller_Front::getInstance();
    $router = $frontController->getRouter();

    $languageRoute = new Zend_Controller_Router_Route(
        ':language',
        array(
            'language' => "de"
        ),
        array('language' => '[a-z]{2}')
    );

    $defaultRoute = new Zend_Controller_Router_Route(
        ':@controller/:@action/*',
        array(
            'module' => 'default',
            'controller' => 'index',
            'action' => 'index'
        )
    );
    $router->addRoute(
        'default',
        $defaultRoute
    );

    $languageDefaultRoute = $languageRoute->chain($defaultRoute);

    $router->addRoute(
        'language',
        $languageDefaultRoute
    );
}

Good luck with your project, hope it will help you and others!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM