Use p28n - http://bakery.cakephp.org/articles/view/p28n-the-top-to-bottom-persistent-internationalization-tutorial
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.