Problemi Traduzione Url

Ciao a tutti,

ho un problemino e prima di provare a fare override di classi e metodi provo qua.

Ho un sito in varie lingue, creo dinamicamente delle rules per l’urlManager avendo creato una classe che implementa il metodo processRules.

Le regole sono di questo tipo.




'<lang:it>/monete'=>'coin/index',

'<lang:en>/coins'=>'coin/index',

'<lang:fr>/monnaies'=>'coin/index'

....



Poi nel mio box per fare lo switch della lingua voglio creare degli url per riportare alla medesima pagina però in un altra lingua, nel caso delle rules sopradescritte farei così:


$this->createUrl('coin/index', array('lang'=>'en');

Il problema è che l’url creato prende sempre la prima regola corrispondente, in questo caso mi crea un link en/monete, mentre io mi aspetterei en/coins e fr/monnaies se passassi fr come parametro.

Sto sbagliando qualcosa o è il funzionamento corretto e per fare come voglio devo fare un override?

grazie.

Ho risolto da solo,


'<lang:it>/monete'=>array('coin/index', 'matchValue'=>true),

'<lang:en>/coins'=>array('coin/index', 'matchValue'=>true),

'<lang:fr>/monnaies'=>array('coin/index', 'matchValue'=>true),

se ti va, documenta un pò il tutto, sarebbe molto interessante per il forum.

Ok, proverò a spiegare cosa ho fatto.

Imposto come sourceLanguage un codice non esistente come suggerito in questo post http://www.yiiframework.com/wiki/243/how-to-translate-and-do-the-translations-the-easy-way/

Nel file di configurazione ho rimosso le rules di default e imposto una mia classe per la gestione degli Url.

Nella variabile sections metto un array che contiene tutte le sezioni del mio sito (non ho creato una tabella per gestirli perché non ne ho necessità, non varieranno spesso)




'sourceLanguage'=>'00',

'language'=>'it',


'components'=>array(

	'urlManager'=>array(

		'class' => 'MyUrlManager',

		'urlFormat'=>'path',

		'showScriptName'=>false,

		'sections' => array(

			array('controller'=>'site', 'action'=>'index', 'menu'=>true, 'label'=>'Home', 'slug'=>'', 'submenu'=>array()),

			array('controller'=>'coin', 'action'=>'index', 'menu'=>true, 'label'=>'Monete', 'slug'=>'monete',  'submenu'=>array(

				array('action'=>'index', 'label'=>'Offerte', 'slug'=>'offerte', 'menu'=>true, 'params'=>array('slug'=>'offerte')),

				array('action'=>'page', 'label'=>'Il nostro negozio', 'slug'=>'il-nostro-negozio', 'menu'=>true, 'params'=>array('slug'=>'il-nostro-negozio')),

			)

		),

		...



Dopodiché nella mia classe che estende CUrlManager faccio l’override del metodo processRules

Prelevo da tabella o da cache le lingue attive e mi creo dinamicamente tutte le regole per ogni lingua passando attraverso l’array sections impostato nel file di configurazione.

Le regole le creo passando dalla funzione Yii::t per la traduzione, passando come codice lingua quello attuale.




class MyUrlManager extends CUrlManager {

   // We override the processRules function of Yii's CUrlManager to handle our dynamically generated rules


	public $sections = array();


	protected function processRules()

	{


		$languages = Language::model()->active()->cache(3600*24)->findAll();


		foreach($languages as $language) {

			foreach($this->sections as $attributes) {

				foreach($attributes['submenu'] as $sub_attributes) {

					if(empty($sub_attributes['slug'])) continue;


					if(isset($sub_attributes['appendSlug']) && $sub_attributes['appendSlug']===false) {

						if($sub_attributes['action']=='page')

							$this->rules["<lang:".$language->code.">/<slug:".Yii::t('slug', $sub_attributes['slug'], array(), null, $language->code).">"]=array($attributes['controller']."/page", 'matchValue'=>true);

						else

							$this->rules["<lang:".$language->code.">/". Yii::t('slug', $sub_attributes['slug'], array(), null, $language->code)]=array($attributes['controller']."/".$sub_attributes['action'], 'matchValue'=>true);

					}

					else

						$this->rules["<lang:".$language->code.">/". Yii::t('slug', $attributes['slug'], array(), null, $language->code) ."/". "<slug:".Yii::t('slug', $sub_attributes['slug'], array(), null, $language->code).">"]=array($attributes['controller']."/".$sub_attributes['action'], 'matchValue'=>true);

				}


				if(empty($attributes['slug'])) continue;

				if($attributes['action']=='page')

					$this->rules["<lang:".$language->code.">/<slug:".Yii::t('slug', $attributes['params']['slug'], array(), null, $language->code).">"]=array($attributes['controller']."/page", 'matchValue'=>true);

				else {

					$this->rules["<lang:".$language->code.">/". Yii::t('slug', $attributes['slug'], array(), null, $language->code). "/<slug>"]=array($attributes['controller']."/view", 'matchValue'=>true);

					$this->rules["<lang:".$language->code.">/". Yii::t('slug', $attributes['slug'], array(), null, $language->code)]=array($attributes['controller']."/".$attributes['action'], 'matchValue'=>true);

				}

			}


			$this->rules["<lang:".$language->code.">"]=array('site/index', 'matchValue'=>true);


			$this->rules["<lang:".$language->code.">/". Yii::t('slug', 'utente', array(), null, $language->code) ."/". Yii::t('slug', 'my-gadoury', array(), null, $language->code)]=array('user/index', 'matchValue'=>true);

			$this->rules["<lang:".$language->code.">/". Yii::t('slug', 'utente', array(), null, $language->code) ."/". Yii::t('slug', 'registrazione', array(), null, $language->code)]=array('user/register', 'matchValue'=>true);

			$this->rules["<lang:".$language->code.">/". Yii::t('slug', 'utente', array(), null, $language->code) ."/". Yii::t('slug', 'carrello', array(), null, $language->code)]=array('user/cart', 'matchValue'=>true);

			$this->rules["<lang:".$language->code.">/". Yii::t('slug', 'utente', array(), null, $language->code) ."/". Yii::t('slug', 'login', array(), null, $language->code)]=array('user/login', 'matchValue'=>true);

			$this->rules["<lang:".$language->code.">/". Yii::t('slug', 'utente', array(), null, $language->code) ."/". Yii::t('slug', 'logout', array(), null, $language->code)]=array('user/logout', 'matchValue'=>true);

		}


		return parent::processRules();

	}

}



In questo modo mi troverò ad avere rules di questo tipo:




'<lang:en>/coins'=> 'coin/index'

'<lang:it>/monete'=> 'coin/index'

'<lang:fr>/monnaies'=> 'coin/index'

'<lang:en>/coins/<slug:offers>'=> 'coin/index'   

'<lang:it>/monete/<slug:offerte>'=> 'coin/index'

'<lang:fr>/monnaies/<slug:offres>'=> 'coin/index'

'<lang:en>/coins/<slug:our-shop>'=> 'coin/page'  //static page

'<lang:it>/monete/<slug:il-nostro-negozio>'=> 'coin/page'    //static page

'<lang:fr>/monnaies/<slug:notre-magasin>' => 'coin/page'   //static page

'<lang:en>/coins/<slug>' => 'coin/view' 

'<lang:it>/monete/<slug>'=> 'coin/view'

'<lang:fr>/monnaies/<slug>' => 'coin/view'



controller coin

action:

index => elenchi monete

page => pagine statiche

view => moneta specifica

NB: Le regole più generiche vanno per ultime, ad esempio

‘<lang:it>/monete/<slug:offerte>’=> ‘coin/index’

‘<lang:it>/monete/<slug>’=> ‘coin/view’

Se invertissi l’ordine qualsiasi chiamata a it/monete/offerte finirebbe al controller view perché sarebbe il primo ad avere il match

Nel mio controller coin




public function actions()

{

	// return external action classes, e.g.:

	return array(

		'page'=>array(

			'class'=>'CViewAction',

			'basePath'=>'pages/'.Yii::app()->language,

			'viewParam'=>'slug'

		),

	);

}


public function actionIndex($slug=null)

{

....


public function actionView($slug)

{




La domanda era sorta perché creando il box per lo switch della lingua rimandavo sempre in homepage a prescindere dalla pagina in cui mi trovavo, mentre chiaramente è bello che se mi trovo in miosito.com/it/monete il link per cambiare da Italiano ad Inglese mi porti non ad miosito.com/en bensì ad miosito.com/en/coins

Senza mettere matchValue=true nell’array delle rules il link creato era il primo che incontrava nella lista delle rules.

Ovvero se uso come esempio l’elenco di rules sopra descritte, il link creato per fare lo switch in italiano era

miosito.com/it/coins, mentre per il francese miosito.com/fr/coins

Qua sotto il widget per il box della lingua e la sua vista




class LangBox extends CWidget

{

	public function run()

	{

		$currentLanguage = Yii::app()->language;


		$enabledLanguages = Language::model()->active()->cache(3600*24)->findAll();

		$this->render('langBox', array('currentLanguage' => $currentLanguage, 'enabledLanguages'=>$enabledLanguages));

	}

}






	$languages = CHtml::listData($enabledLanguages, 'code', 'language');


	foreach($enabledLanguages as $language) {

		$label = CHtml::image(Yii::app()->request->baseUrl . '/images/flags/'.$language->code.'.png') . "&nbsp;" . $language->language;

		$params = $_GET;

		if(isset($params['slug'])) {

			$params['slug'] = Yii::t('slug', $params['slug'], array(), null, $language->code);

		}

		$params['lang']=$language->code;

		$item = array('label'=>$label, 'url'=>array_merge(array($this->getOwner()->id ."/". $this->getOwner()->action->id), $params));

		//$item = array('label'=>$label, 'url'=>array('site/index', 'lang'=>$language->code));

		$currentLanguage==$language->code ? $items[0] = $item : $items[1]['items'][] = $item;

	}

	ksort($items);


	$this->widget('bootstrap.widgets.TbButtonGroup', array(

		'encodeLabel' => false,

		'buttons' => $items

	));




Mettendo matchValue=true il tutto funziona e mi ritrovo con i link per fare lo switch nel modo corretto.

Spero di non esser stato troppo confusionario e scusate se il codice è tutto su una riga e quindi poco leggibile nel forum.