Forum for discussing general topics related to Couch.
29 posts Page 1 of 3
I am currently in the process of planning a multilanguage site with Couch.

Having read @KK 's detailed explanation on the technical possibilities (viewtopic.php?f=8&t=74&hilit=multilanguage), and doing some research on multilanguage SEO, I came to the conclusion that it is probably best to organize the site in respective folders for each language (http://searchengineland.com/the-ultimat ... seo-157838) in order to provide language-specific on-page optimization and clear language-specific URLs:

Code: Select all
site_root
  |_couch (folder)
  |_en (folder)
  |   |_index.php
  |   |_about.php
  |   |_news.php
  |_es (folder)
  |   |_index.php
  |   |_nosotros.php
  |   |_novedades.php
  |_de (folder)
  |   |_index.php
  |   |_ueber.php
  |   |_nachrichten.php
  |_index.php


Although I like the simplicity of dynamically loading the editable fields according to the set language cookie and managing all fields in one template, I read some SEO sources that recommend against this approach as a page might not rank well. The downside of the folder-appraoch is of course the extra effort of maintaining 3 different sites with their respective assets (images etc.), which can become a nightmare.

I would appreciate your thoughts and experiences on how you handle multilanguage sites from a SEO perspective?

I have another question relating to the folder approach:

The index.php that resides in the root can be used to direct the users to their desired language. It could be by explicitly asking them their preferred language or you can use the redirect tag to automatically make them land on the default language, say English


Ideally, 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.

Furthermore, 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 would appreciate your advice how to set this up. Thanks.
Hi,

Ideally, 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.


I think this link can help you on this http://www.developphp.com/page.php?id=588
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
Hi JD,

You have some very pertinent points there.
Allow me a little time to think about how best to handle those.

I'll get back with the answers.

Thanks.
Thanks @KK.

I am sure that other users might be interested as well in a standardized , "best practice" solution in terms of language-detection and solid SEO.
@KK , did you have the chance to think about an approach?

Thanks.
@JD, @KK has been having some computer issues. Please do give him a little bit longer to respond. Thanks.
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.

Attachments

Thank you for this very detailed answer, KK.

I will try to implement this asap on a multi-language site and will let you know how this works out.
Hi KK,

HUUUUUGE THANKS!!!!!! :P

I 've read the new solution through - all is clear and simple, real easy-peasy as you said, I am up to implement it right now!

Amazingly simple now and smooth, just like an everyday language - thanks!!!

Tanja
You are always welcome, Tanja :)
I'm glad you found the revised solution easier than the original one.

Do keep us posted how your implementation goes.
29 posts Page 1 of 3