[EXTENSION] langhandler

This extension will set up your applications target language according to visitors browser setting, accepted languages list and country code passed in url.

For more information check documentation section http://www.yiiframew…on/langhandler/

Please report any bugs, wanted futures and ask questions here.

quote from Yurik

Hi,

I’m using this extension and need a little help on this last post, refering to a modification in ELangCUrlManager.

I’ve configured it like this :




		'ELangHandler'=>array(

			'class'=>'application.extensions.langhandler.ELangHandler',

			'languages'=> array('en','fr','es'),

		),



…and my browser prefered language is ‘fr’. Now if I want to switch to english, I set the lang parameter to ‘en


/yiiWebApp/index.php?r=site/index&lang=en

…and the page is displayed in english. But as sourceLanguage is ‘en’, the ELangCUrlManager does not add the ‘lang’ parameter to URL it creates (this is what the optimization does). On the next page request, as there is no ‘lang’ parameter, the browser prefered language is choosen ‘fr’ (because in my case, it is supported) : the page is now in french, it switched from ‘en’ for ‘fr’ because there was no ‘lang’ parameter defined.

Maybe I’ve missed something in the configuration … any help is appreciated.

8)

Hi, I seem to have problems using this extension to work with static pages.

Yii generate the standard about page under


/site/page?view=about

The code sits in main.php:


<?php echo CHtml::link('this link will open current page in german',array('','lang'=>'de')) ?>

for the above page makes the link only:


/de/site/page/

instead of:

[color="#1C2837"][font="monospace"][size="2"]


/de/site/page?view=about

[/size][/font][/color]

the ?view=about part went missing.

I got the home page and contact page working correctly.

Can anyone help? Thanx.

Isn’t it how stock urlManager creates links as well? Url is created for controller “site” and action “page”. Now, you have to pass “view” GET parameter with static page name. When you create an url without any routes it just points to current controller/action but you have to input GET parameter once again. Hence the whole idea of langhandler, it makes sure lang GET parameter is passed between requests.

For this particular example correct function call should look like this:


<?php echo CHtml::link('this link will open current page in german',array('','lang'=>'de','view'=>'about')) ?>

For reference check this:

http://www.yiiframework.com/doc/api/1.1/CViewAction

and this:

http://www.yiiframework.com/doc/api/1.1/CUrlManager#createUrl-detail

I see. I’m new to Yii, thank you for the explanation and pointed to me documentation that led a temporary solution.

Is there a way to just pass the GET parameter (only if there are params) in without statically declare it?

I place the CHtml::link in the main.php expecting to behave as language box switcher, so the page may be a static page or it may not.

The original code was something like this:




echo CHtml::link('English', array('','lang'=>'en'), array('class'=>'en'));

echo CHtml::link('中文', array('','lang'=>'tw'), array('class'=>'tw'));

echo CHtml::link('日本語', array('','lang'=>'jp'), array('class'=>'jp'));

I temporarily solve it by using this:




$hasViewParam=isset($this->action->viewParam);

if ($hasViewParam) {

    $viewParam = $this->action->viewParam;

    $requestedView = $this->action->requestedView;

    echo CHtml::link('English', array('',$viewParam=>$requestedView,'lang'=>'en'), array('class'=>'en'));

    echo CHtml::link('中文', array('',$viewParam=>$requestedView,'lang'=>'tw'), array('class'=>'tw'));

    echo CHtml::link('日本語', array('',$viewParam=>$requestedView,'lang'=>'jp'), array('class'=>'jp'));

 } else {

     echo CHtml::link('English', array('','lang'=>'en'), array('class'=>'en'));

     echo CHtml::link('中文', array('','lang'=>'tw'), array('class'=>'tw'));

     echo CHtml::link('日本語', array('','lang'=>'jp'), array('class'=>'jp'));



}

However, this will break if I have a static page in a subfolder and it looks butt ugly. Is there a better way to go at this?

Thanx again for any help.

Maybe you should take a look at these extensions:

http://www.yiiframework.com/extension/dropdownredirect/ - this one should work well with langhandler

http://www.yiiframework.com/extension/languagepicker/ - this may be plug&play solution for your problem

Thanx for the quick reply. I did try out languagepicker before I tried yours, but the design requires a list of links instead of a drop down list. I’m not sure if I can turn it into a list of links.

I’ll check them out and see if I can make it work, thank you.

Try this:


<?php echo CHtml::link('this link will open current page in german',array_merge($_GET, array('lang' => 'de'))) ?>

Thanx, but nope, not working.

I then tried:


echo CHtml::link('中文', array('',$_GET,'lang'=>'tw'));

It would give me:


/site/page?0%5Bview%5D=about&0%5Blang%5D=en&lang=tw

getting close, 0%5B and 0%5D is the left and right square bracket. No idea how it got in there and how to get rid of them…

Setup the route rules to make lang param a prefix and then I did it by force:





<?php

    $request = $_SERVER['REQUEST_URI'];

    $path_a = explode("/",$request);

    $uri = (isSet($_GET["lang"])?

        substr($request, strlen($path_a[1])+1) //strip language prefix and the slash

        :$request);                           	//don't process if the page is in default language

    echo CHtml::link('English', CHtml::normalizeUrl($uri)); //no need to add default language prefix

    echo CHtml::link('中文', CHtml::normalizeUrl('/tw'.$uri));

    echo CHtml::link('日本語', CHtml::normalizeUrl('/jp'.$uri));

?>

I tried:


echo CHtml::link('中文',CHtml::normalizeUrl(array_merge($_GET, array('lang' => 'tw'))));

which I thought should have worked, but didn’t.

This is very, very close. Here’s what I did.




<?php

$params = $_GET; if(isset($params['_lang'])) unset($params['_lang']); // prevents your '_lang' from being overwritten by the parameter in $_GET

echo CHtml::link('German', array_merge(array('', '_lang' => 'de'), $params));

?>



I ended up using this:




        <?php 

        $request = $_SERVER['REQUEST_URI'];

        $path_a = explode("/",$request);

        $haveLang = isSet($_GET["lang"]);

        $uri = ($haveLang?

                substr($request, strlen($path_a[1])+1) //strip language prefix and the slash

                :$request);                               //don't process if the page is in default language

        echo CHtml::link(CHtml::encode(Yii::app()->name), CHtml::normalizeUrl(($haveLang?'/'.$_GET["lang"].'/':'/')), array('id'=>'logo')); 

        ?>

          <div id="lang_switch">                  

            <?php

            echo CHtml::link('English', CHtml::normalizeUrl($uri), array('class'=>'en')); //no need to add default language prefix

            echo CHtml::link('中文', CHtml::normalizeUrl('/tw'.$uri), array('class'=>'tw'));

            echo CHtml::link('日本語', CHtml::normalizeUrl('/jp'.$uri), array('class'=>'jp'));

            ?>

with routing rules like:


'<lang:(en|tw|jp)>/<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

It works.

I tried your code, it seems to work, and much better than mine. Thanx a million!

I used to use this but I’m starting to have concernes.

Hello there,

I have some question about Url routing


[url="http://kgm.dev/en/collection/view.html?id=2&title=spring-summer-2012"]"http://kgm.dev/en/co...ing-summer-2012[/url]"

this was my actualy Url

how can i change it to


[url="http://kgm.dev/en/collection/view/2/spring-summer-2012.html"]http://kgm.dev/en/co...ummer-2012.html[/url]

i use CMenu this is my item


label' => $item->title,

            	'url' => array(

                	'/collection/view/',

                	'id' => $item->id,

                	'title' => $this->title($item->title),

                	'lang' => Yii::app()->getLanguage()

            	),

my cofiguration config/main


'ELangHandler' => array (

        	'class' => 'application.extensions.langhandler.ELangHandler',

        	'languages' => array('de','en'),

        	'strict' => true,

    	),


'urlManager'=>array(

        	'class'=>'application.extensions.langhandler.ELangCUrlManager',

        	'urlFormat'=>'path',

        	'showScriptName'=>false,

        	'urlSuffix' => '.html',

			'rules'=>array(

            	'<lang:(de|en)>/<_c>/<_a>/' => '<_c>/<_a>',

            	'<lang:(de|en)>/collection/view/<id:\d+>/<title:\w+>' => array('/collection/view'),

            	'<lang:[a-z]{2}_[a-z]{2,}>/<_m>/<_c>/<_a>' => '<_m>/<_c>/<_a>',

			),

		),

hope anybody can help me quickly thx a lot

I would suggest you to play with the order of the rules. I think the rules are match in sequence, once a rule is matched the rest are skipped. So if you have a link that would fit two rules, then put the rule you would like it to apply to the front of the list.

So, in your example, I would try something like:




            'rules'=>array(

               	'<lang:(de|en)>/collection/view/<id:\d+>/<title:\w+>' => array('/collection/view'),

     			'<lang:[a-z]{2}_[a-z]{2,}>/<_m>/<_c>/<_a>' => '<_m>/<_c>/<_a>',

                '<lang:(de|en)>/<_c>/<_a>/' => '<_c>/<_a>',

            ),

Also, for the first rule, I would change it to (removing the first / on the right):


<lang:(de|en)>/collection/view/<id:\d+>/<title:\w+>' => array('collection/view'),

I could be wrong though, anyone care to chime in?