Hi JD,
Apologies for the delay in my reply (but I think the length of this answer would explain it

).
You had asked three different questions in your post.
I'll try to answer all of them. To keep things a bit simple, I'll use the example of the following multi-lingual site that has only one section (news) implemented in three different languages -
- Code: Select all
site_root
|_couch (folder)
|
|_index.php
|
|_en (folder)
| |_news.php
|
|_de (folder)
| |_nachrichten.php
|
|_de (folder)
|_nouvelle.php
Your first question was -
The downside of the folder-approach is of course the extra effort of maintaining 3 different sites with their respective assets (images etc.), which can become a nightmare.
I agree with you. Taking the example of our sample site above, as far as text inputs are concerned, the three languages will in any case have have three separate editable regions for you to maintain. It is the non-text (i.e. assets like images, files etc.) that are problematic as you'd require to upload the same assets in three different languages.
One solution for this problem could be to define the assets only in one of the three templates (I'll assume it is the EN version) and them relate the other two templates to it. This way, e.g., while creating a news item, the images will be uploaded only in the EN page and the DE and FR pages will fetch those from the EN version using the relation between them and the EN version page.
As an example, consider the definitions in the three templates -
en/news.php- Code: Select all
<cms:template clonable='1' dynamic_folders='1' >
<cms:editable name='my_text' type='textarea' />
<!-- following resources will be shared by all other languages -->
<cms:editable name='my_image' type='image' />
<cms:editable name='my_file' type='file' />
</cms:template>
de/nachrichten.php- Code: Select all
<cms:template clonable='1' dynamic_folders='1' >
<cms:editable name='my_text' type='textarea' />
<!-- related EN page -->
<cms:editable type='relation' name='related_page' label='Related English Page' masterpage='en/news.php' has='one' reverse_has='one' />
</cms:template>
fr/nouvelle.php- Code: Select all
<cms:template clonable='1' dynamic_folders='1' >
<cms:editable name='my_text' type='textarea' />
<!-- related EN page -->
<cms:editable type='relation' name='related_page' label='Related English Page' masterpage='en/news.php' has='one' reverse_has='one' />
</cms:template>
Notice how each of the three templates has its own text editable region but the image and file regions are defined only in the EN version.
The DE and FR versions identically define a one-to-one relation with the EN version. This way while creating a DE or FR page, you can choose its counterpart EN page from a dropdown to set their relation.
Displaying the data in an EN page is straightforward -
EDIT: Original code redacted. An easier solution is given below.Moving on to your second question -
I would like that the user is able to switch between those languages at any time on any site from the menu (little flag buttons to choose language version).
I don't know if you have pondered over this problem but it is a little trickier than what it, prima-facie, appears.
However, if you are willing to put in a little more effort, we can use the relation we created between the templates above to effect this.
EDIT: The method described originally using <cms:reverse_related_pages /> tags was proving too difficult for some users.
So, I've created a tag that basically encapsulates all the grunge work within itself leaving you to deal only with that single tag.
The following discussion replaces the original solution.
/// begin revised solution ///
Download and unzip the attached file. Place the extracted 'multi_lang.php' within in your couch/addons/ folder. Register the addon by adding the following line of code to couch/addons/kfunctions.php -
- Code: Select all
require_once( K_COUCH_DIR.'addons/multi_lang.php' );
The addon activated above will make available a tag named <cms:lang_group />.
In the example code we are using, the three templates (i.e. en/news.php, de/nachrichten.php and fr/nouvelle.php) logically belong to a single group (i.e. 'news'). We need to add the following <cms:lang_group /> tag *identically into each of them* -
- Code: Select all
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
/>
As you can see, with the code above we are making it known to the <cms:lang_group /> tag all the templates that logically form a group.
To elaborate this point further, assume the blog section of the site comprises of another three templates (one for each language e.g. en/blog.php, fr/blogue.php and de/blog.php). To group together these three templates into one group, we need to place the following in each of them -
- Code: Select all
<cms:lang_group
en='en/blog.php'
fr='fr/blogue.php'
de='de/blog.php'
/>
The right location to place the code would be somewhere at the top of each template before any other Couch tag. Placing it just below the opening mandatory PHP statement should do just fine. So our en/news.php template becomes as follows -
- Code: Select all
<?php require_once( '../couch/cms.php' ); ?>
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
/>
<cms:template clonable='1' dynamic_folders='1' >
<cms:editable name='my_text' type='textarea' />
<!-- following resources will be shared by all other languages -->
<cms:editable name='my_image' type='image' />
<cms:editable name='my_file' type='file' />
</cms:template>
..
..
<?php COUCH::invoke(); ?>
Exactly the same addition needs to be done in the other two templates. For example, the 'fr/nouvelle.php' would now become -
- Code: Select all
<?php require_once( '../couch/cms.php' ); ?>
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
/>
<cms:template clonable='1' dynamic_folders='1' >
<cms:editable name='my_text' type='textarea' />
<!-- related EN page -->
<cms:editable type='relation' name='related_page' label='Related English Page' masterpage='en/news.php' has='one' reverse_has='one' />
</cms:template>
..
..
<?php COUCH::invoke(); ?>
And now, courtesy the <cms:lang_group />, whenever any of the three templates is executed, Couch automatically sets for you three variables -
'my_link_en', 'my_link_de' and 'my_link_fr'. The three variables contains links to pages of other languages related to the current page being visited.
It should now be easy-peasy to create a menu (maybe showing the little flags you mentioned) that always links all the related pages together e.g as the following very simple menu -
- Code: Select all
<a href="<cms:show my_link_en />">EN</a> |
<a href="<cms:show my_link_de />">DE</a> |
<a href="<cms:show my_link_fr />">FR</a>
A note about the variables 'my_link_en', 'my_link_de' and 'my_link_fr' -
Why only three variables? That is because we declared three languages in the <cms:lang_group /> tag -
- Code: Select all
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
/>
If there were, suppose, four languages with the new one being Russian with a template named 'ru/news.php'. The following declaration would specify the new template and now we'll also find a fourth variable named 'my_link_ru' getting set by Couch -
- Code: Select all
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
ru='ru/news.php'
/>
The 'en', 'de', 'fr' and 'ru' in the names of these variables ('my_link_
en', 'my_link_
de', 'my_link_
fr', 'my_link_
ru') were in fact taken from what we declared in the <cms:lang_group /> tag above.
So, for example, if we had the following declaration -
- Code: Select all
<cms:lang_group
english='en/news.php'
french='fr/nouvelle.php'
deutche='de/nachrichten.php'
russian='ru/news.php'
/>
- the variables would have been set as 'my_link_english', 'my_link_french', 'my_link_deutche' and 'my_link_russian' instead
Some additional very important points regarding <cms:lang_group /> tag - A. From the way we have created our three templates, we know that the 'en/news.php' is the primary template.
Two reasons for that -
1. All the assets are defined only in this template
2. This template does *not* contain the type 'relation' editable region found in the other two templates.
To convey this fact to <cms:lang_group /> tag, we have to
specify the primary template as the very first template (as seen in all examples above).
B. By default, tag <cms:lang_group /> assumes the name of the type 'relation' editable region to be 'related_page' (please see the declaration of this region in the 'fr' and 'de' templates). If you choose to use a different name for this region, this needs to be conveyed to <cms:lang_group /> tag using its '_related_by' parameter. For example, suppose the name of the 'relation' region is 'my_other_language_page'. The declaration of <cms:lang_group /> would now become -
- Code: Select all
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
_related_by = 'my_other_language_page'
/>
C. Finally, we can ask <cms:lang_group /> tag to make available the assets editable regions, we defined in the primary template, in all templates of the group. In our example, they were in the form of two editable regions named 'my_image' and 'my_file' defined in the 'en/news.php' template.
If we modify the <cms:lang_group /> declaration placed in the three templates as follows -
- Code: Select all
<cms:lang_group
en='en/news.php'
fr='fr/nouvelle.php'
de='de/nachrichten.php'
_common_fields='my_image | my_file'
/>
- , you'll find that you can use 'my_image' and 'my_file' variables in *all* the three templates page-views (although normally they would be available only in the page-view of 'en/news.php' as that is the template that actually contains these regions).
So, for example, you can use the following common code in *all* templates of the group -
- Code: Select all
<img src="<cms:show my_image />" width='200' />
<a href="<cms:show my_file />">File</a>
/// end revised solution ///
Finally your last question
the site should detect the default language of the visitor's browser and switch accordingly to the language version (EN, DE, ES). If, however, the visitor is not using one of the available site languages, the English version should be served as a standard.
We can use the technique explained in the link suggested by @Tomarnst for that.
The couchified version of the code would be -
- Code: Select all
<cms:php>
$lc = ""; // Initialize the language code variable
// Check to see that the global language server variable isset()
// If it is set, we cut the first two characters from that string
if( isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ){
$lc = strtolower( substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) );
}
// set it as a Couch variable
global $CTX;
$CTX->set( 'my_lang', $lc, 'global' );
</cms:php>
<cms:if "<cms:not my_lang='en' || my_lang='de' || my_lang='fr' />" >
<cms:set my_lang='en' 'global' />
</cms:if>
If we place the code above in the 'index.php' of root, we can now use the 'my_lang' variable to redirect the visitor to the right language e.g.
- Code: Select all
<cms:if my_lang='en'>
<cms:redirect 'en/index.php' />
</cms:if>
<cms:if my_lang='de'>
<cms:redirect 'de/index.php' />
</cms:if>
<cms:if my_lang='fr'>
<cms:redirect 'fr/index.php' />
</cms:if>
Or simply use the following -
- Code: Select all
<cms:redirect "<cms:show my_lang />/index.php" />
Hope it helps.
Do let me know.
Thanks.