So here's my solution to the problem that so many have: I wanted pretty URLs for a multilanguage site, no ugly ?lang parameters.
Four changes:
1. Tell SS which languages you are ready to take
Being a complete noob to SS, I had to hardcode this. In your _config.php add this:
i18n::enable();
global $allowed_i18n;
$allowed_i18n = array('en', 'de', 'fr');
2. Have SS understand which language to present
I defined that the first URL segment is the language element: http://mysite.com/en/page/
/sapphire/main.php strips the URL apart, checks if the first segment is in the definition list above and sets the language.
This has two consequences: You can not use a language called 'db' because this is needed for the admin database
maintenance operations, and you can not have page names that are the same as your language codes.
Add this immediately before the default director rules (near line 122 in SS 2.2.2) in /sapphire/main.php
if(substr($url,0,strlen($baseURL)) == $baseURL) $url = substr($url,strlen($baseURL));
global $allowed_i18n;
if(sizeof($allowed_i18n) > 0) {
$tmp_url = preg_replace( array( '/\/+/','/^\//', '/\/$/'),array('/','',''),$url);
$tmp_urlParts = split('/+', $tmp_url);
$lng = array_shift($tmp_urlParts);
$bSetLang = false;
if(in_array(strtolower($lng), $allowed_i18n)) {
$url = "/".join('/', $tmp_urlParts);
$_REQUEST['url'] = $url;
$bSetLang = true;
}
if(isset($_GET['lang']) && in_array(strtolower($_GET['lang']), $allowed_i18n)) {
$lng = $_GET['lang'];
$bSetLang = true;
}
if($bSetLang) {
$_GET['lang'] = $lng;
$_REQUEST['lang'] = $lng;
}
}
3. Prepare language switcher
Simply add the following function to your page controller
function LanguageSwitcher() {
$langs = i18n::get_existing_content_languages();
$data = new DataObjectSet();
foreach(array_keys($langs) as $code) {
if($code == Translatable::current_lang()) {
continue;
}
$page = Translatable::get_one_by_lang("SiteTree", $code, "`SiteTree`.ID = " . Controller::curr()->ID);
$data->push(new ArrayData(array('name' => i18n::get_language_name($code, true),
'link' => Director::protocolAndHost() . Director::baseURL() . "$code/" . $page->URLSegment,
'code' => $code)));
}
return $data;
}
4. Integrate the language switcher into your template
I use the following snippet in an include file
<ul class="LanguageChooser">
<% _t('VIEWIN', 'View this site in:') %>
<% control LanguageSwitcher %>
<li><a href="$link">$name</a></li>
<% end_control %>
</ul>
As you will notice I have "borrowed" from others. Standing on the shoulders of giants ...
Please comment and improve.
Cheers.
[edit: changed the main.php hack - setting $_GET['lang'] as well]
[ANOTHER edit: changed the main.php hack - doesn't reset the admin language anymore. that was bad for editing translations]