I recently build a tiny routing 'extension', that calls the routes from a MySQL table (structure downwards). I think it's worth to be mentioned, that this page runs in multiple languages (German and English). So - relying on the cookie, that's currently set in the client's browser - the corresponding routings get connected.
The problem is, that if the user cannot (externally) be linked to a german content page, if his browser's language cookie was set to the English language (because the english routes got connected).
Does anyone got a proper solution for this? To be honest, I don't really know, how to programmatically extend the Router-class' functionality.
The MySQL table's structure looks like this:
CREATE TABLE `routes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`language` varchar(5) COLLATE latin1_general_ci NOT NULL DEFAULT 'de',
`route` varchar(64) COLLATE latin1_general_ci NOT NULL,
`controller` varchar(64) COLLATE latin1_general_ci NOT NULL,
`action` varchar(64) COLLATE latin1_general_ci NOT NULL,
PRIMARY KEY (`id`)
)
It works well, I use it a lot and it's part of my standard build now.
I also have a script that will return translated urls depending on the chosen language. I can't remember where I found the script it's based on, but if it helps I can try to send you a clean version.
EDIT: Okay, here's the bones:
This script will translate urls so that they remain SEO friendly across languages. The language switching and message translation is handled by p28n (above) and po.
Put this line in your app/config/bootstrap.php
file:
include_once("translate.php");
Put this as the first line of code in app/config/routes.php
:
$fromUrl = translate($fromUrl,true);
Now you need to create the file app/config/translate.php
which contains all of the routing information:
function translate($str = null,$total = false)
{
// If this is an RSS route, ignore it and bounce straight out
if (strpos($str,".rss")!==false)
return $str;
$translatetable = array(
'some-url-in-german' => array('/articles/msome-url-in-german',1),
'some-url-in-english' => array('/articles/some-url-in-german',2),
'a-german-article' => array('/posts/a-german-article',1),
'an-english-article' => array('/posts/a-german-article',2)
);
if($str)
{
if($total)
{
$old = explode('/',$str);
$lastone = end($old);
if(empty($lastone)) array_pop($old);
$new = array();
/* translate each part or leave untranslated part */
for($i = 0 ; $i <sizeof($old) ; $i++)
{
$new[$i] = translate($old[$i]);
}
/* construct the translated url. This also adds
a trailing "/" even if it wasn't in the original */
$new_url="";
foreach($new as $n)
{
$new_url .= $n."/";
}
return $new_url;
}
else
{
foreach ($translatetable as $orig => $new)
{
if($str == $orig)
{
$str = $new[0];
switchLanguage($new[1]);
}
}
return $str;
}
}
}
function switchLanguage($lang)
{
if($lang>0)
{
$translatetable = array(
'1' => 'de',
'2'=> 'eng'
);
Configure::write(array('Config.language'=>$translatetable[$lang]));
}
}
It's quite straightforward really - the trick is getting it to feed into CakePHP at the right places. I hope it is of some use to you.