Hi folks,
tommorow i will publish a big update.
I modified the complete logic, because some people on the german forum complained about the use of the alias field because it breaks the nature of speaking urls. So now i use the description field for my approach. I could do it with a template variable too, but maybe i post this later.
What changed?
The languageChooser points to the actual page in the corresponding languages.
If the actual page can´t be found in the other language it will take you to the root of the language.
So no more 404s if you switch the language and the page doesn´t exist.
You now can have unique aliases for every page.
This is the old version. Look at first post for the actual version.
Multilingual Websites with MODx
After reading the solutions in this forum, none of them convinced me. I wanted that the user stays on the same page if he switches the language.
But i didn´t want to assign the relation between the languages via a template variable. It should function automatic.
So i found a solution for myself. It performs well, but surely has potential for improvements.
Comments and improvements are welcome. Hope my solution helps someone.
Update
I found out that my solution couldn´t handle subfolders in the language folder. Too bad that my site needs subfolders. So i rewrote the main snippet "language" from scratch. Now I have a very good solution and even a 404 error page, that shows a sitemap in your selected language. If the language can´t be determined, it will show the default language of your site (defined in configuration/site root).
Changes between the previous version are:
Put the snippet [[language]] in the first line of your template.
Add the placeholder [+language+] where you need it. For example if you have different images in your languages.
A brandnew 404 error page
Placeholder "[+debugMsg+]" for tracing the language snippet
End Update
Here we go:
EDIT:
1. Modify your configuration under Tools/Configuration
Use the following settings:
friendly URLs: yes
Use friendly aliases: yes
Use friendly alias path: yes
Allow duplicate aliases: yes
2. build Site Tree
First make a new folder and name it with your main language as the title. For example „english“, „deutsch“, „français“.
This is what a visitor sees to set his language.
The alias for this folder is a two-letter ISO Country Code that you can find here:
http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
Now you create your pages as you would normally and give them an alias. After that you duplicate the whole folder for your next language and change the title and the country code in the alias field.
The alias of the pages in your language folders is always the same. So if the first page has the alias „home“, the name in every other language is also „home“!!!
Example:
english / alias: en / type: folder
|-> Welcome / alias: home (2)
deutsch / alias: de / type: folder
|-> Willkommen / alias: home (3)
Now under configuration "set Site start": enter the id of the first page of your main language (2 in this example)
3. create snippets
Snippet Name: „language“.
Description: creates placeholders and stores the actual language
<?php
// Placeholders set by this
$debugMsg = '$language is: '.$language.'<br />';
$debugMsg = 'LanguageID from cookie: '.$_COOKIE['LanguageID'].'<br />';
$params['topLevel'] =1;
$aliasPath = '';
// Regular Page
// find Ultimate Parent of this page. The alias of this page sets the language variable
if ($modx->config['error_page'] != $modx->documentIdentifier){
$up = $modx->runSnippet("UltimateParent", $params);
$tv = $modx->getTemplateVar('alias', "", $up);
$language = $tv['value'];
setcookie("Language",$language,time()+604800, "/", "", 0);
// LanguageID is needed for the 404 error page, to show the sitemap in the actual language
setcookie("LanguageID",$up,time()+604800, "/", "", 0);
$modx->setPlaceholder('LanguageID',$up);
$aliasPath = str_replace($language.'/','/',$modx->virtualDir.'/[*alias*]');
}
else{
// If Error Page
$debugMsg .= '<p>Error Page Start<br />';
if ( !empty ($_COOKIE['LanguageID'])){
$debugMsg .='$language is empty, try to read from cookie';
$language = $_COOKIE['Language'];
$LanguageID = $_COOKIE['LanguageID'];
$params['id'] = $LanguageID;
$up = $modx->runSnippet("UltimateParent", $params);
//setcookie("LanguageID",$up,time()+604800, "/", "", 0);
$modx->setPlaceholder('LanguageID',$up);
}
else {
$debugMsg .= '<p>LanguageID Cookie is empty, get ID from Site start</p>'.$modx->config['site_start'];
$params['id'] = $modx->config['site_start'];
$up = $modx->runSnippet("UltimateParent", $params);
//setcookie("LanguageID",$up,time()+604800, "/", "", 0);
$modx->setPlaceholder('LanguageID',$up);
}
}
$debugMsg .= 'LanguageID at finish: [+LanguageID+]<br />';
$debugMsg .= '$aliasPath: '.$aliasPath.'<br />';
$modx->setPlaceholder('aliasPath', $aliasPath);
$debugMsg .= '$language: '.$language.'<br />';
$modx->setPlaceholder('debugMsg', $debugMsg);
$modx->setPlaceholder('language', $language);
if (file_exists("assets/languages/$language.php")) include "assets/languages/$language.php";
?>
Snippet "languageInclude" is no longer needed
Snippet Name: „LanguageChooser“
Description: „shortcut for the wayfinder“
<?php
echo '[!Wayfinder?&startId=0&level=1&rowTpl=LanguageRow&titleOfLinks=alias!]';
?>
The titleOfLinks=alias sends the two-letter-language-code to the LanguageRow Snippet.
create ChunkUpdate
Chunk Name: „LanguageRow“
Description: „prints a flag and the name of the language as a list item“
Content:
<li class="category [+wf.classnames+]"><a href="[(site_url)][+wf.title+][+aliasPath+]"><img src="[(base_url)]/assets/images/flags/gif/[+wf.title+].gif" alt="[+wf.linktext+]" /></a> <a href="[(site_url)][+wf.title+][+aliasPath+]" >[+wf.linktext+]</a>[+wf.wrapper+]</li>
4. modify Site-TemplateUpdate
Now you insert the follwing code in your template:
inf first row of your template insert the placeholder "[[language]]"
<div id="languageselection">
[[LanguageChooser]]
</div>
<div id="navigation">
[!Wayfinder? &startId=`[[UltimateParent]]`!]
</div>
This includes the languageChooser and the php-file in the actual language. And you get a navigation with only the sites in the selected language.
5. Download Icons
This is an optional step. However, if you skip this step, you will need to change the "LanguageRow" snippet below.
- Download a set of icons whose names correspond to a two-letter Country Code and extract the folder to assets/images/flags
you get nice looking flags from here: http://www.famfamfam.com/lab/icons/flags/
- Make a directory assets/languages
6. Forms
Open the language file under assets/snippets/eform/lang and add your variables to it
$_lang['yourname'] = "Your Name";
You can add as many variables as you need.
Now you have to assign those variables to the fields array:
Create a new snippet „setPrompts“
<?php
function setPrompts(&$fields) {
global $_lang;
$fields['yourname'] = $_lang['yourname'];
return true;
}
?>
When you create your form chunk you have access to all the placeholders that you defined in the setPrompts snippet:
[+validationmessage+]
<form method="post" action="[~[*id*]~]">
<input type="hidden" name="formid" value="feedbackForm" />
<label for="cf[+yourname+]">[+yourname+]: </label>
<input name="Your Name" id="cf[+yourname+]" class="required text" type="text" eform="[+yourname+]::1:" />
Now insert your form on your contact page with the following code:
[[setPrompts]]
[!eForm? &formid=`feedbackForm` &to=`[email protected]`&eFormOnBeforeFormMerge=`setPrompts` &language=`german` &subject=`Web site feedback`!]
Most important are the parameters „&language = `german`“ (name needs to be the same as in the assets/snippets/eform/lang folder) and „eFormOnBeforeFormMerge=`setPrompts`“ !
Multilingual 404 Error Page
Create a new folder in MODx that is unpublished.
Then create and publish a new page with the title "[+errorpage+]" in it.
Alias: "404"
[[language]]
[+errorpage+]
[!Wayfinder? &startId=`[+LanguageID+]` &showDescription=`1`!]
Now in your assets/languages/en.php (enter your 2 letter-language-code), add the following:
<?php
$modx->setPlaceholder("errorpage",'404 - Page not found');
?>
<br />Translate this message for all of your languages and insert it in the language files.<br /><br />Your 404 error page is done and provides a sitemap in the actual language.<br />If the user selects a language for a page, that isn´t yet published for that language, he will be redirected to the 404-page in the selected language.<br /><br />[b]Thats it. Please comment.[/b]