Building a multilingual website with basic CMSMS functions

Do something cool with CMS? Show us ...
This board is for 'Answers', and the discussion of answers... Not for questions.
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Building a multilingual website with basic CMSMS functions

Post by Rolf »

In this topic I will try to give a description of the steps I took to create my own multilingual website.
I really can't do this in 10 lines, so I have tried to make it as clear as possible. Don't be frightened by the size of the topic and the amount of code. When you take a closer look at it, you will see the minor changes you have to make to let it all work. And you really don't need to have all explained features in a small multilingual website...

Beside some playing with basic CMSMS tags, you need to create an User Defined Tag.
This tag reads the language setting of the visitors webbrowser. This value is passed to the template with the parameter $lang. Based on this language the visitor is diverted to his language homepage, and creates the content of the Error 404 template.

Some features:
- Pretty urls like http://www.buispost.eu/e and http://www.buispost.eu/e/contact
- Opening the website root http://www.buispost.eu diverts the visitor based on browserlanguage automatically to the homepage of his language
- Uses different templates for each language, so no need to use cookies
- If set, internal links to the same pages with different languages. If not set, diverts to the language homepage
- Multilingual Breadcrumbs
- Error 404 page in browserlanguage
- Forms in different languages >>
- Search box in different languages >>


Okay, a few known shortcomings:
- You can't have a different style for an active parent, due to the Internal Link to the homepage. I use the Internal Link here, to get nicer URLs. The custom-url feature in the coming 1.9 will solve this I think. I will change this topic after the releasing of 1.9.
- Modules like News, CompanyDirectory, etc. can't have urls with the language step in it. But using detailpages for each language the layout will change.


1. Install pretty url

When you use pretty url (mod_rewrite) on the website you get the best results. At least thats my opinion...  ;)
Look here to read which steps you have to take:
http://forum.cmsmadesimple.org/index.ph ... 912.0.html
Or do a quick search in the forum or wiki on this.

(Note: If you have questions on how to create pretty url, please don't use this multilingual topic... It is a bit off-topic)


2. Page structure

1 default [default page]

2 Start [Important: set page alias in options tab to 'nl']
  2.1 Start [Set Internal Link to 2 ^ ]
  2.2 Dutch page 1
  2.3 Dutch page 2

3 Accueil [Important: set page alias in options tab to 'fr']
  3.1 Accueil [Set Internal Link to 3 ^ ]
  3.2 French page 1
  3.3 French page 2

4 Anfang [Important: set page alias in options tab to 'd']
  4.1 Anfang [Set Internal Link to 4 ^ ]
  4.2 German page 1
  4.3 German page 2

5 Homepage [Important: set page alias in options tab to 'e']
  5.1 Homepage [Set Internal Link to 5 ^ ]
  5.2 English page 1
  5.3 English page 2

6 Error 404 [Errorpage 404]


3. Create UDT get_browserlanguage

Opening the right entry page based on the visitors browser language setting

UDT: get_browserlanguage

Code: Select all

$gCms = cmsms();

// Read browser language
$foo = $_SERVER['HTTP_ACCEPT_LANGUAGE'];

// Only need the first two characters
$lang = substr($foo,0,2); 

// Passing the parameter $lang to the template
$smarty = &$gCms->GetSmarty();
$smarty->assign('lang', $lang);
(Based on RonnyK's UDT)


4. Call UDT in the default index page

Open Page 1 - index
Set the WYSIWYG editor off in the Options tab.

Put into the content field:

Code: Select all

{get_browserlanguage}

{if $lang == 'nl'}
      {redirect_page page="nl"}
 {elseif $lang == 'fr'}
      {redirect_page page="fr"}
 {elseif $lang == 'de'}
      {redirect_page page="d"}
 {else}
      {redirect_page page="e"}
{/if}

5. Create Global Content Blocks with country flags

Create for each language a Global Content Block.
These blocks will show the flag images on the frontend and create the link to the alternative page in another language. If not set it will go to the language homepage.
Upload your own images to your folder, and edit the right path in the code below.

If you don't have any images yourself... You will find them here: http://en.wikipedia.org/wiki/List_of_countries

Global Content Block, named: flag-nl

Code: Select all

{if $dutch_version}
      {cms_selflink page=$dutch_version image="images/layout/flag-nl.png" title="Nederlandstalige versie" alt="Nederlandstalige versie" imageonly=1}
   {else}
      {cms_selflink page="nl" image="images/layout/flag-nl.png" title="Nederlandstalige versie" alt="Nederlandstalige versie" imageonly=1}
{/if}
Global Content Block, named: flag-fr

Code: Select all

{if $french_version}
      {cms_selflink page=$french_version image="images/layout/flag-fr.png" title="Version Française" alt="Version Française" imageonly=1}
   {else}
      {cms_selflink page="fr" image="images/layout/flag-fr.png" title="Version Française" alt="Version Française" imageonly=1}
{/if}
Global Content Block, named: flag-d

Code: Select all

{if $german_version}
      {cms_selflink page=$german_version image="images/layout/flag-de.png" title="Deutschsprachige Version" alt="Deutschsprachige Version" imageonly=1}
   {else}
      {cms_selflink page="d" image="images/layout/flag-de.png" title="Deutschsprachige Version" alt="Deutschsprachige Version" imageonly=1}
{/if}
Global Content Block, named: flag-e

Code: Select all

{if $english_version}
      {cms_selflink page=$english_version image="images/layout/flag-uk.png" title="English version" alt="English version" imageonly=1}
    {else}
      {cms_selflink page="e" image="images/layout/flag-uk.png" title="English version" alt="English version" imageonly=1}
{/if}

6. Create a Global Content Block footer for each language

You can create for each language a different footer.
Besides text in different languages, you can also use this for different links to the language homepage, sitemap, copyright text, etc.

You should give the blocks the names:
- footer-nl
- footer-fr
- footer-d
- footer-e


7. Creating HTML templates

First thing you do is create a working HTML template based on only one language!!
If this one is working fine, you can copy it to create a template for each language.

In the following example templates you will find some basic layout parts.
In red you will see the small changes that are needed for each language.

You should add the code you need to your own template, and style it yourself.


Dutch template

Code: Select all

{process_pagedata}

{sitename} - {title}
{metadata}
{cms_stylesheet}

  {menu template="accessible_simple_navigation.tpl" start_element='2.1' show_root_siblings="1" number_of_levels='3'}

   {content block="german_version" assign="german_version" wysiwyg="false" oneline="true" label="Page alias German Alternative"}
   {content block="english_version" assign="english_version" wysiwyg="false" oneline="true" label="Page alias English Alternative"}
   {content block="french_version" assign="french_version" wysiwyg="false" oneline="true" label="Page alias French Alternative"}

   {global_content name='flag-d'}
   {global_content name='flag-e'}
   {global_content name='flag-fr'}

  {breadcrumbs starttext='U bent hier' root='nl' delimiter='>'}
   
  {title}
  {content}

{global_content name='footer-nl'}
French template

Code: Select all

{process_pagedata}

{sitename} - {title}
{metadata}
{cms_stylesheet}

  {menu template="accessible_simple_navigation.tpl" start_element='3.1' show_root_siblings="1" number_of_levels='3'}

   {content block="dutch_version" assign="dutch_version" wysiwyg="false" oneline="true" label="Page alias Dutch Alternative"}
   {content block="german_version" assign="german_version" wysiwyg="false" oneline="true" label="Page alias German Alternative"}
   {content block="english_version" assign="english_version" wysiwyg="false" oneline="true" label="Page alias English Alternative"}

   {global_content name='flag-nl'}
   {global_content name='flag-d'}
   {global_content name='flag-e'}
   
   {breadcrumbs starttext='Vous êtes ici' root='fr' delimiter='>'}
   
  {title}
  {content}

{global_content name='footer-fr'}
German Template

Code: Select all

{process_pagedata}

{sitename} - {title}
{metadata}
{cms_stylesheet}

  {menu template="accessible_simple_navigation.tpl" start_element='4.1' show_root_siblings="1" number_of_levels='3'}

   {content block="dutch_version" assign="dutch_version" wysiwyg="false" oneline="true" label="Page alias Dutch Alternative"}
   {content block="english_version" assign="english_version" wysiwyg="false" oneline="true" label="Page alias English Alternative"}
   {content block="french_version" assign="french_version" wysiwyg="false" oneline="true" label="Page alias French Alternative"}

   {global_content name='flag-nl'}
   {global_content name='flag-e'}
   {global_content name='flag-fr'}
   
        {breadcrumbs starttext='Sie sind hier' root='d' delimiter='>'}
   
  {title}
  {content}

{global_content name='footer-d'}
English template

Code: Select all

{process_pagedata}

{sitename} - {title}
{metadata}
{cms_stylesheet}

  {menu template="accessible_simple_navigation.tpl" start_element='5.1' show_root_siblings="1" number_of_levels='3'}

   {content block="dutch_version" assign="dutch_version" wysiwyg="false" oneline="true" label="Page alias Dutch Alternative"}
   {content block="german_version" assign="german_version" wysiwyg="false" oneline="true" label="Page alias German Alternative"}
   {content block="french_version" assign="french_version" wysiwyg="false" oneline="true" label="Page alias French Alternative"}

   {global_content name='flag-nl'}
   {global_content name='flag-d'}
   {global_content name='flag-fr'}

   {breadcrumbs starttext='You are here' root='e' delimiter='>'}
   
  {title}
  {content}

{global_content name='footer-e'}

Error 404 template

Code: Select all

{process_pagedata}

{sitename} - {title}
{metadata}
{cms_stylesheet}

{get_browserlanguage}

{if $lang == "nl"}
      {menu template='accessible_simple_navigation.tpl' start_element='2.1' show_root_siblings="1" number_of_levels='3'}
   {elseif $lang == "fr"}
      {menu template='accessible_simple_navigation.tpl' start_element='3.1' show_root_siblings="1" number_of_levels='3'}
   {elseif $lang == "de"}
      {menu template='accessible_simple_navigation.tpl' start_element='4.1' show_root_siblings="1" number_of_levels='3'}
   {else}
      {menu template='accessible_simple_navigation.tpl' start_element='5.1' show_root_siblings="1" number_of_levels='3'}
   {/if}

   {if $lang != "nl"}
      {global_content name='flag-nl'}
   {/if}
   {if $lang != "fr"}
       {global_content name='flag-fr'}
   {/if}
   {if $lang != "de"}
      {global_content name='flag-d'}
   {/if}
   {if $lang != "en"}
       {global_content name='flag-e'}
   {/if}

  {title}
{content label="Dutch text" assign="content_dutch"}
{content block="german" wysiwyg="true" label="German text" assign="content_german"}
{content block="english" wysiwyg="true" label="English text" assign="content_english"}
{content block="french" wysiwyg="true" label="French text" assign="content_french"}


{if $lang == "nl"}
                {$content_dutch}
    {elseif $lang == "fr"}
                {$content_french}
    {elseif $lang == "de"}
                {$content_german}
    {else}
                {$content_english}
{/if}

    {if $lang == "nl"}
	{global_content name='footer-nl'}
    {elseif $lang == "fr"}
	{global_content name='footer-fr'}
    {elseif $lang == "de"}
	{global_content name='footer-d'}
    {else}
	{global_content name='footer-e'}
{/if}

8. Changing template for the matching language

We want to have the template dropdown in the main tab of the page editor:

Site Admin >> Global Settings >> Advanced setup >> Basic Properties >> Select 'Template'

Now you can open each page and assign the matching language template.


9. Assigning page alternatives

When the website content is finished, you can assign alternative page aliases to each page.
In the page editor you will find 3 fields where you can fill in the page alias of the same page in a different language.
Clicking on a flag of a certain page will open the same page in a different language


10. The Error 404 page

Opening the Error 404 page in the page editor, you will find 4 editors.
Each language has his own WYSIWYG box.
You can write your own 404 message in these boxes.

When a visitor tries to open a not excisting page, the Error 404 template will create a page based on the browserlanguage.
For example the browserlanguage is set to French.
The navigation is in French, the content text is in French, the footer text is in French, and so on...

You should have a real multilingual website now...
It is a lot of text and code, I can't guarantee there aren't little errors in it right now. Please let me know it if you find one.

Hope this helps, Rolf  :)
Last edited by Rolf on Thu Nov 11, 2010 3:02 pm, edited 1 time in total.
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
Jean le Chauve

Re: Building a multilingual website with basic CMS Made Simple functions

Post by Jean le Chauve »

Great, thank you  :)
vilkis

Re: Building a multilingual website with basic CMS Made Simple functions

Post by vilkis »

You can write UDT that catches a root alias and then sets a language variable. Then, it is possible to use one template for all languages. This is more complex to implement but simpler to use or modify.

vilkis
User avatar
Dr.CSS
Moderator
Moderator
Posts: 12687
Joined: Thu Mar 09, 2006 5:32 am
Location: Arizona

Re: Building a multilingual website with basic CMS Made Simple functions

Post by Dr.CSS »

I could show how I did it with one template for all pages with the text changing for each lang. by having the english pages all copied under a lang. section header set to not show in the menu then using a select menu template choosing a lang/section header which becomes the root page alias it changes everything...
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Re: Building a multilingual website with basic CMS Made Simple functions

Post by Rolf »

vilkis wrote: You can write UDT that catches a root alias and then sets a language variable. Then, it is possible to use one template for all languages. This is more complex to implement but simpler to use or modify.
When I build the website, I started with a one template plan, with a UDT to switch languages.
But like you said, the template is getting far more complex by this.
And you still need a field in the editor to attach a page with a language.

Modifying these multiple templates is imho not more work. Just open them in different tabs in your browser and do the work. Because the templates are less complex, it is easier to read and so easier to change.

I think the method with multiple templates is also better to use for the less experienced user.

Grtz. Rolf  :)
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
moonoo
Forum Members
Forum Members
Posts: 77
Joined: Fri Jan 08, 2010 12:23 am
Location: Wales - UK

Re: Building a multilingual website with basic CMS Made Simple functions

Post by moonoo »

Great Read!

What about using AdvancedContent plugin to have each language in a separate tab for editing content?

And then conditional statements in the one template to determine what lang is active.
User avatar
manuel
Power Poster
Power Poster
Posts: 351
Joined: Fri Nov 30, 2007 9:15 am

Re: Building a multilingual website with basic CMS Made Simple functions

Post by manuel »

Thanks for posting this Rolf!
Great and safe way to have multilingual functionality!! (i'm still hoping for a single content tree solution embedded in cmsms 2.0 some day   ;D) > oops, just checked and it seems it's being planned for cmsms 2.2 now... anyway, i'm hoping for this to be realized as soon as developperly possible lol  ;D

FYI: i believe you should update the UDT to no longer include the $gCms as it will be removed in cmsms 1.9
Actually, i already couldn't get the UDT with the $gCms to work on my "let's mess around" cms setup which is only 1.6.7 (i'm in the process of transferring/upgrading my websites to my php5 server and cmsms 1.8.2, don't worry)

cmsms 1.9 announcement: http://forum.cmsmadesimple.org/index.ph ... 209.0.html
15) Removed the $gCms variable from smarty.
This has been a contentious issue, but it was decided that for security reasons this variable should not be exported to smarty.  This may break some sites that are using some of the internal CMSMS variables to do some things directly in smarty.

Code: Select all

// Read browser language
$foo = $_SERVER['HTTP_ACCEPT_LANGUAGE'];

// Only need the first two characters
$lang = substr($foo,0,2);

// Passing the parameter $lang to the template
$smarty->assign('lang', $lang);
ps: please don't forget to also update the dutch forum post where i first found your great piece of work!!  ;)

Greetings,
Manuel
Do you like your open source cms? Buy from the CMSMS partners || Donate
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Re: Building a multilingual website with basic CMS Made Simple functions

Post by Rolf »

manuel wrote: FYI: i believe you should update the UDT to no longer include the $gCms as it will be removed in cmsms 1.9
Actually, i already couldn't get the UDT with the $gCms to work on my "let's mess around" cms setup which is only 1.6.7 (i'm in the process of transferring/upgrading my websites to my php5 server and cmsms 1.8.2, don't worry)

cmsms 1.9 announcement: http://forum.cmsmadesimple.org/index.ph ... 209.0.html
15) Removed the $gCms variable from smarty.
This has been a contentious issue, but it was decided that for security reasons this variable should not be exported to smarty.  This may break some sites that are using some of the internal CMSMS variables to do some things directly in smarty.
Hi Manuel,

The UDT in my first post is also working in release 1.9!

Code: Select all

global $gCms;
is replaced by

Code: Select all

$gCms = cmsms();
This works from release 1.8.x+

Hope this helps,

Rolf  :)
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Re: Building a multilingual website with basic CMS Made Simp

Post by Rolf »

Addition: Multilingual search

Code: Select all

{search searchtext="Uw zoekwoord..." submit="Versturen" search_method="post"}

Code: Select all

{search searchtext="Enter search..." submit="Submit" search_method="post"}

Code: Select all

{search searchtext="Ihr Suchwort..." submit="Suchen" search_method="post"}

Code: Select all

{search searchtext="Recherche..." submit="Envoyer" search_method="post"}
Regards, Rolf  :)
Last edited by Rolf on Tue Nov 23, 2010 11:32 am, edited 1 time in total.
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Re: Building a multilingual website with basic CMS Made Simp

Post by Rolf »

Addition: Multilanguage forms with FormBuilder

Create 4 seperate forms in FormBuilder, one for each language.
The tags for the pages would be:

Code: Select all

{cms_module module='FormBuilder' form='contact-nl' lang='nl_NL'}

Code: Select all

{cms_module module='FormBuilder' form='contact-fr' lang='fr_FR'}

Code: Select all

{cms_module module='FormBuilder' form='contact-d' lang='de_DE'}

Code: Select all

{cms_module module='FormBuilder' form='contact-e' lang='en_EN'}
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
ataxel
Forum Members
Forum Members
Posts: 41
Joined: Thu Jul 19, 2007 1:32 pm

Re: Building a multilingual website with basic CMS Made Simple functions

Post by ataxel »

Huge thank you.
I use to work with MLE. You solution is a little longer to get working but deploy easily with your instructions.

Can't wait to have a simple tree solution though!
User avatar
manuel
Power Poster
Power Poster
Posts: 351
Joined: Fri Nov 30, 2007 9:15 am

Re: Building a multilingual website with basic CMS Made Simple functions

Post by manuel »

Hi Rolf,

Maybe you can add to your "Addition: Multilingual search" post that because of the pretty URL's {search search_method="post"} is needed for the search module?

greetings,
Manuel
Do you like your open source cms? Buy from the CMSMS partners || Donate
User avatar
Rolf
Dev Team Member
Dev Team Member
Posts: 7825
Joined: Wed Apr 23, 2008 7:53 am
Location: The Netherlands
Contact:

Re: Building a multilingual website with basic CMS Made Simple functions

Post by Rolf »

manuel wrote: Maybe you can add to your "Addition: Multilingual search" post that because of the pretty URL's {search search_method="post"} is needed for the search module?
Correct, thanks  :)
- + - + - + - + - + - + -
LATEST TUTORIAL AT CMS CAN BE SIMPLE:
Migrating Company Directory module to LISE
- + - + - + - + - + - + -
Image
User avatar
moonie
Forum Members
Forum Members
Posts: 81
Joined: Tue Feb 13, 2007 3:08 pm
Location: Switzerland

Re: Building a multilingual website with basic CMS Made Simple functions

Post by moonie »

Hi Rolf

This is a great multilingual tutorial, will be very helpful in the future!

Maybe you have found a way to tinker with the search results too when it comes to multilingual page trees? What I would want to do is only target pages under my FR tree when I do a search in the FR template (Post: http://forum.cmsmadesimple.org/index.ph ... 117.0.html). Right now it also displays results that reside under DE tree if they share the same keywords, and this doesn't look very clean in the search results. Maybe you have found a solution to this?

Regards
Fab
ZeNono
New Member
New Member
Posts: 3
Joined: Mon Jan 05, 2009 2:17 pm

Re: Building a multilingual website with basic CMS Made Simp

Post by ZeNono »

I have an issue with the breadcrumbs.
I'm using the 1.9.2

I have the following pages as you explained
1 - Default
2 - Homepage (alias 'en')
2.1 - Home
2.2 - About
2.3 - Services
2.3.1 - Training

When in my english template I put
{breadcrumbs delimiter='»' root='en'}

I get on my page Homepage >> Homepage >> Home
The two first elements are clickable and leads to /dpm/en
If I click on one of those links, I'm getting a timeout after 60 sec.
The last one is not a link

If I uncheck the "Show in Menu", I'll get Homepage >> Home
Is there a way to show only from the third level, that is to say, only >>Home ?
Or what should I have in the en page itself ?
Locked

Return to “Tips and Tricks”