Cool
I may as well share this with you then since I seem to be working on a similar thing to you.
I have found that it is ideal to have a different base url for each language in use; it means your content gets indexed separately by the search engines, and each language can have pages that can be bookmarked. This could be done with separate document trees (mydomain.com/en/ etc) but what if only parts of your page are going to be translated, and you want to fall back to a default language if a translation is not available? I prefer to use TVs for elements of a page that is to be translated.
One easy way to achieve this without separate document trees is to set up subdomains of your domain or register your domain in other tlds and make them aliases of your main domain, eg:
fr.mydomain.com
or
mydomain.fr
I have two plugins, one that establishes the page language based on the server and registers some global variables that can be used by snippets, and one that replaces custom placeholders within the documentOutput which you use in your templates like this: ((lang.switcher)) - the language switcher, the base href ((base.href)), language direction ((dir)) language 2-letter code ((lang)) and language ((language)).
Language:
<?php
/*
Title: Language
Author: Mark Croxton, [email protected]
Desc: Plugin triggered OnParseDocument
Updated: May 15 2009
*/
global $modx;
$domains = array(
'de' => array('Deutsch','de.mydomain.com','ltr'),
'en' => array('English','mydomain.com','ltr'),
'es' => array('Español','es.mydomain.com','ltr'),
'fr' => array('Français','fr.mydomain.com','ltr'),
'zh' => array('中文','cn.mydomain.com','ltr')
);
// what's the URI of the current page?
$url = $_SERVER['REQUEST_URI'];
# what's the name of the server?
$server = $domains['en'][1]; // English by default
$language = 'en';
# check that the server name is in the predefined array before assigning it
# to prevent injection via headers
foreach ($domains as $key => $value) {
if ($value[1] == $_SERVER['SERVER_NAME']) {
$server = $value[1];
$language = $key;
}
}
if ($server != $_SERVER['SERVER_NAME']) {
// domain not recognised, redirect to default
$modx->sendRedirect('http://'.$server.$url);
}
$GLOBALS['domains'] = $domains;
$GLOBALS['language'] = $language;
?>
Language switcher:
<?php
/*
Title: Language switcher
Author: Mark Croxton, [email protected]
Desc: Plugin triggered OnWebPagePrerender
Sets language placeholders based on site url
Updated: May 15 2009
*/
global $modx, $domains, $language;
# server
$server = 'http://'.$domains[$language][1];
# text direction
$dir = $domains[$language][2];
# what's the URI of the current page?
$url = $_SERVER['REQUEST_URI'];
$tplRow = '
<li[+active+]><a href="[+server+][+url+]"><em>[+lang+] ([+lang.code+])</em></a></li>
';
$tplOuter ='
<ul>
[+rows+]
</ul>
';
$rows ='';
foreach ($domains as $key => $value) {
$active='';
if ($key == $language) {
$active =' class="active"';
}
$f = array('[+active+]','[+server+]','[+url+]','[+lang+]','[+lang.code+]');
$v = array($active,'http://'.$domains[$key][1],$url,$domains[$key][0],$key);
$rows.= str_replace($f,$v,$tplRow);
}
$switcher = str_replace('[+rows+]',$rows,$tplOuter);
# replace placeholders using a custom syntax to ensure these values are never cached ((placeholder))
$fields = array('((base.href))','((dir))','((lang))','((language))','((lang.switcher))');
$values = array($server, $dir, $language, $domains[$language][0], $switcher);
$modx->documentOutput = str_replace($fields,$values,$modx->documentOutput);
?>
I use a snippet to translate on the fly - either a document field, a chunk or hardcoded word:
<?php
/*
Title: Translate
Author: Mark Croxton, [email protected]
Desc: Translates a document field, tv, or chunk, into the global language
Updated: May 18 2009
*/
global $modx, $language;
$field = isset($field)? $field : 'pagetitle';
$tpl = isset($tpl)? $tpl : '';
$word = isset($word)? $word : '';
$docid = isset($id)? $id : $modx->documentIdentifier;
if ($word != '') {
$lexicon = array(
'Members' => array(
'en' => 'Members',
'de' => 'Mitglieder',
'es' => 'Miembros',
'fr' => 'Membres',
'zh' => '会员'
),
'Map' => array(
'en' => 'Map',
'de' => 'Karte',
'es' => 'Mapa',
'fr' => 'Cartes',
'zh' => '地图'
),
'Search' => array(
'en' => 'Search',
'de' => 'Suche',
'es' => 'Buscar',
'fr' => 'Trouver',
'zh' => '搜索'
),
'News' => array(
'en' => 'News',
'de' => 'News',
'es' => 'Noticias',
'fr' => 'Nouvelle',
'zh' => '新闻'
),
'Press releases' => array(
'en' => 'Press releases',
'de' => 'Artikel',
'es' => 'Noticias',
'fr' => 'Articles',
'zh' => '新闻稿件'
),
'Find press releases' => array(
'en' => 'Press releases',
'de' => 'Pressemitteilungen finden',
'es' => 'Buscador de comunicados de prensa',
'fr' => 'Trouver des communiqués',
'zh' => '查找新闻稿件'
),
'Events' => array(
'en' => 'Events',
'de' => 'Events',
'es' => 'Eventos',
'fr' => 'Événements',
'zh' => '活动'
),
'Login' => array(
'en' => 'Login',
'de' => '',
'es' => '',
'fr' => '',
'zh' => ''
),
'Contact' => array(
'en' => 'Contact',
'de' => '',
'es' => '',
'fr' => '',
'zh' => ''
),
'Profile' => array(
'en' => 'Profile',
'de' => 'Profil',
'es' => 'Perfil',
'fr' => 'Profil',
'zh' => '外形'
),
'Other offices' => array(
'en' => 'Other offices',
'de' => 'Andere Büros',
'es' => 'Otras oficinas',
'fr' => 'D\'autres bureaux',
'zh' => '其他办公室'
),
'Key contact' => array(
'en' => 'Key contact',
'de' => 'Hauptkontakt',
'es' => 'Contacto principal',
'fr' => 'Contact principal',
'zh' => '主要联络'
),
'Firm name' => array(
'en' => 'Firm name',
'de' => 'Firmenname',
'es' => 'Nombre de la empresa',
'fr' => 'Nom de la firme',
'zh' => '事务所名称'
),
'City' => array(
'en' => 'City',
'de' => 'Stadt',
'es' => 'Ciudad',
'fr' => 'Ville',
'zh' => '城市'
),
'Country' => array(
'en' => 'Country',
'de' => 'Land',
'es' => 'País',
'fr' => 'Pays',
'zh' => '国家'
),
'A-Z' => array(
'en' => 'A-Z',
'de' => 'A-Z',
'es' => 'A-Z',
'fr' => 'A-Z',
'zh' => '字母'
)
);
return $lexicon[$word][$language];
} else if ($tpl=='') {
$lang_field = $field;
if ($language != 'en') { // ignore english
$lang_field = $field.$language;
}
$docfield = $modx->getTemplateVarOutput(array($lang_field), $docid, 1);
if ($docfield[$lang_field] == '') { // no content for the selected language, so use english
$docfield = $modx->getTemplateVarOutput(array($field), $docid, 1);
return $docfield[$field];
} else {
return $docfield[$lang_field];
}
} else {
// eg myChunk_en, myChunk_de etc
return $modx->getChunk($tpl.'_'.$language);
}
?>
Hope this helps in some way.