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') . " " . $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.