Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
49 posts Page 1 of 5
Hi,

I have recently discovered your great CMS, I downloaded the portable version to test it, and I most say it's an amazing CMS.
However, I have a situation over here, regarding implementing the CMS into a multilanguage site (english and french), which also has to menu bars: one horizontal and another vertical (a sidebar).
The horizontal menu is ok: I have the menu items which I don't have to change, each link brings me to some static pages, where I can implement the CMS using your tutorial.
The problem is with the vertical menu which contains product names, so I have to be able to add and delete products (links) from it. I tried to build this menu by creating cloned pages using your blog tutorial and it's working partly, but only with the involved cloned pages. But I also have to display this vertical menu on each page of the website: vertical + horizontal menu pages. And this is my problem, I don't now how to do this.
Another question is if it's possible to achieve all this in 2 different languages/1 website: an english version + a french version.
Can you point me to the right solution?

Thanks,
Attila
Hi Attila,

Welcome and we are glad you liked Couch.
I'll try and answer your questions -

>> display this vertical menu on each page of the website

You said you created the vertical menu dynamically to show the cloned pages, so your code should roughly be something like this -
Code: Select all
<ul>
<cms:pages masterpage='yourtemplate.php' >
    <li>
        <a href="<cms:show k_page_link/>"><cms:show k_page_title /></a>
    </li>
</cms:pages>
</ul>

To display this menu on each page of your website, you can keep the code above within a separate file, e.g. menu.html, and place the file within the couch/snippets folder.
Now you can place the following code within all the other templates of your site -
Code: Select all
<cms:embed 'menu.html' />

This way you can dynamically embed the menu in all the pages using the templates.

>>if it's possible to achieve all this in 2 different languages/1 website: an english version + a french version.

I have tried to explain the ways we can try and create multi-lingual sites using Couch in the another thread on this forum but I'll repeat it here for you-

Let us suppose you need the contents of the site to be in two languages - English and French.
There can be two different approaches to tackle this -

1. Give each language its own domain e.g
en.yourwebsite.com
fr.yourwebsite.com
In this approach, we have two different domains so Couch will need to be installed in both of them. Basically you'll have two separate sites each with its own separate admin section, so nothing new here.

2. Give each language a sub-folder e.g.
http://www.yourwebsite.com/en/
http://www.yourwebsite.com/fr/
This seems to be the most followed approach out there and so I'll look at it a little closer -

Suppose this was the original structure of a Couch managed site with only one language (say, English) -
Code: Select all
site_root
  |_couch (folder)
  |_index.php
  |_about.php
  |_news.php

There are three templates with the news template being a clonable template.
Each of the templates will be enclosed within the mandatory
<?php require_once( 'couch/cms.php' ); ?> and <?php COUCH::invoke(); ?> lines.
In any Couch tag where the masterpage parameter (i.e. name of the template ) needs to be supplied, we can use 'index.php', 'about.php' and 'news.php' as the names of the three templates.
This is all routine stuff. I am repeating it so that it can be compared to what follows.

Had the same site been multi-lingual (say English and French), the following could be a possible setup -
Code: Select all
site_root
  |_couch (folder)
  |_en (folder)
  |   |_index.php
  |   |_about.php
  |   |_news.php
  |_fr (folder)
  |   |_index.php
  |   |_apropos.php
  |   |_nouvelle.php
  |_index.php

We have now created the French versions of the three templates and placed them within a separate folder named 'fr' while the English templates are moved to a folder named 'en'.
So now we have six templates instead of three. Notice also the index.php that resides directly in the root which makes it seven templates in all. We'll talk about it in just a while.
Important thing is that there is only one couch installation.

Placing the templates within sub-folders will require two little changes that you need to be aware of -
1.
The mandatory php code placed at the beginnng of the templates placed within the subfolders will now become -
Code: Select all
<?php require_once( '../couch/cms.php' ); ?>

Notice the '..' that denotes that the couch folder is one level up in the hierarchy.
The seventh template that resides directly within the root will not need this adjustment.

2.
The name of the templates will now become -
'en/index.php', 'en/about.php', 'en/news.php', 'fr/index.php', 'fr/apropos.php', 'fr/nouvelle.php'
Notice how the names now have the folder names prefixed.
The seventh template will be simply 'index.php'.
So now any tag that has the masterpage attribute will need to be given these adjusted names.

With this setup, you can now create contents in both the languages as the admin panel will show them as separate templates.

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
Code: Select all
<cms:redirect url='http://www.yourwebsite.com/en/' />


With prettyURLs enabled, the links to pages will be -
http://www.yourwebsite.com/
http://www.yourwebsite.com/en/
http://www.yourwebsite.com/en/about/
http://www.yourwebsite.com/en/news/
http://www.yourwebsite.com/en/news/my_news.html
http://www.yourwebsite.com/fr/
http://www.yourwebsite.com/fr/apropos/
http://www.yourwebsite.com/fr/nouvelle/
http://www.yourwebsite.com/fr/nouvelle/ ... elles.html

Hope this helps. Let me know.

EDIT: One potential drawback of this method is the duplication of assets (images, files etc.) amongst the templates of different languages. For a solution please see the following thread -
viewtopic.php?f=2&p=18935
KK, thanks for your quick and veeeeeeeeeery detailed explanations on my questions. I was very close to the solution for the first part of my question, but it seems somehow I didn't realised how easy is to make it work. But now, thanks to your help, i got it working. I tried very quickly the recommended solution for the 2 languages, and as far as I can see, this works too.
What can I say... CouchCMS is a great cms, with a great support!

Attila
Continuing the discussion above regarding multi-lingual sites, I'd like to add a third method of handling them -

UPDATE:
This method now has a new addon that should make the process of implementing it much simpler -
viewtopic.php?f=5&t=10979


3. Creating a separate editable region for each language
As opposed to the solution above where we give each language a separate template, this method requires only a single template.
Pros:
    Does not clutter the sidebar with multiple templates.
    Does not require the user to upload static assets (e.g. images, files etc.) multiple times - one for each language.
    Might be easier to implement

Cons:
    There will be a single URL for any given page for all the languages - this could have SEO implications.
    Likewise, comments of all languages will appear on the same page.

As you can see, this method is not without limitations but, anyways, it is always good to have choices and there will be cases where this method would be the best.

How it works:
For simplicity let us suppose we have a template that requires only two editable regions - one for an image and other for content.
This could be our initial single-language version -
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
   <cms:template>
      <cms:editable name="photo" type="image" />
      <cms:editable name="content" type="textarea" />
   </cms:template>

   <h1>Language Test</h1>
   <p> <img src="<cms:show photo />" /> </p>
   <cms:show content />
   
<?php COUCH::invoke(); ?>

Let us suppose we need to have the content in three different languages - English, French and Spanish.
What we do is, instead of creating a single editable region, we create three editable regions - one for each language.
Thus our template will now look like this -
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
   <cms:template>
      <cms:editable name="photo" type="image" />
      <cms:editable name="content_en" type="textarea" />
      <cms:editable name="content_fr" type="textarea" />
      <cms:editable name="content_es" type="textarea" />
   </cms:template>

   <h1>Language Test</h1>
   <p> <img src="<cms:show photo />" /> </p>
   <cms:show content />
   
<?php COUCH::invoke(); ?>

Notice how instead of one region for the content, we now have three - each suffixed by a language identifier.
Also notice that we still have a single image region.

Next just suppose for the time being that we set a variable named 'my_lang' somewhere at the beginning of our code that contains the name of the selected language - the value could be either 'en' or 'fr' or 'es'.
Code: Select all
<cms:set my_lang ='fr' 'global' />

We can now easily display content in the selected language by using a simple conditional like this -
Code: Select all
   <cms:if my_lang='en'><cms:show content_en /></cms:if>
   <cms:if my_lang='fr'><cms:show content_fr /></cms:if>
   <cms:if my_lang='es'><cms:show content_es /></cms:if>

Our template now becomes -
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
   <cms:set my_lang ='fr' 'global' />
   <cms:template>
      <cms:editable name="photo" type="image" />
      <cms:editable name="content_en" type="textarea" />
      <cms:editable name="content_fr" type="textarea" />
      <cms:editable name="content_es" type="textarea" />
   </cms:template>

   <h1>Language Test</h1>
   <p> <img src="<cms:show photo />" /> </p>
   <cms:if my_lang='en'><cms:show content_en /></cms:if>
   <cms:if my_lang='fr'><cms:show content_fr /></cms:if>
   <cms:if my_lang='es'><cms:show content_es /></cms:if>
   
<?php COUCH::invoke(); ?>

Of course, since we have manually hard-coded 'my_lang' to 'fr' in our example, our code will always show the French version of the content. We'll fix that soon - for now let it be the way it is.

So as you can see from the code above, instead of a single <cms:show variable_name /> statement, we now have to use as many statements as there are languages - each within a conditional.
If this seems tedious, you can use the following single statement instead -
Code: Select all
<cms:get "content_<cms:show my_lang />" />

If 'cms:get' seems unfamiliar to you, please take a look at the documentation.
It is slightly different from 'cms:show' in that it takes a string as its parameter and so we can fabricate a string dynamically as we did in our example above.
The <cms:get "content_<cms:show my_lang />" /> will evaluate to
<cms:get "content_en" /> if my_lang is 'en' and
<cms:get "content_fr" /> if it is 'fr'.
As you can see, you may have any number of languages but you'll only require to use only one 'cms:get' statement.

Following is our template using the alternative method of displaying content-
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
   <cms:set my_lang ='fr' 'global' />
   <cms:template>
      <cms:editable name="photo" type="image" />
      <cms:editable name="content_en" type="textarea" />
      <cms:editable name="content_fr" type="textarea" />
      <cms:editable name="content_es" type="textarea" />
   </cms:template>

   <h1>Language Test</h1>
   <p> <img src="<cms:show photo />" /> </p>
   <cms:get "content_<cms:show my_lang />" />   
   
<?php COUCH::invoke(); ?>

So the 'my_lang' variable holds the key to our solution - if it can be dynamically set to the user's preferred language, the template will automatically show content in that language.

In the files attached with this post, you'll find a snippet named 'lang_getter.html'.
This is its complete content -
Code: Select all
   <cms:php>
   session_start();
   global $accepted_langs, $selected_lang;
   
   // Set your languages here
   $accepted_langs = array( 'en', 'fr', 'es' );
   
   if( isset($_SESSION['lang']) && in_array($_SESSION['lang'], $accepted_langs) ){
      $selected_lang = $_SESSION['lang'];
   }
   else{
      $selected_lang = 'en'; // Set your default language here
   }
   </cms:php>
   
   <cms:set my_lang = "<cms:php>global $selected_lang; echo $selected_lang;</cms:php>" 'global' />

Place 'lang_getter.html' within your couch installation's 'snippets' folder as we'll embed this in our template (we could have pasted the code directly in the template but we'll be reusing the code in all other templates of our site so it is better to embed it).

What the code does is - it checks if the user has saved his preferred language (in session) and that the language is one of the acceptable languages of our site (please make sure to modify this array to the languages your site caters to)
Code: Select all
   // Set your languages here
   $accepted_langs = array( 'en', 'fr', 'es' );

If no language has been selected (will happen when the user visits the site for the first time), it selects a default language (make sure to change this too)
Code: Select all
   $selected_lang = 'en'; // Set your default language here

Finally, it sets a variable for Couch named 'my_lang' that contains the preferred language.
Yes, it the same 'my_lang' variable that we manually set in our example.
So now we can substitute that line of code in our template where we hard-coded 'my_lang' with an embed to this snippet -
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
   <cms:embed 'lang_getter.html' />
   <cms:template>
      <cms:editable name="photo" type="image" />
      <cms:editable name="content_en" type="textarea" />
      <cms:editable name="content_fr" type="textarea" />
      <cms:editable name="content_es" type="textarea" />
   </cms:template>

   <h1>Language Test</h1>
   <p> <img src="<cms:show photo />" /> </p>
   <cms:if my_lang='en'><cms:show content_en /></cms:if>
   <cms:if my_lang='fr'><cms:show content_fr /></cms:if>
   <cms:if my_lang='es'><cms:show content_es /></cms:if>
   
   <!-- Alternate method of showing variable -->
   <br />
   <cms:get "content_<cms:show my_lang />" />   
   
<?php COUCH::invoke(); ?>

OK, but how does the visitor gets to choose and save his preferred language in session?
This is the final piece of the puzzle and then our solution is complete.

We make use of two scripts (both attached below)
1. A snippet named 'lang_switcher_menu.html'
We'll embed this file in our template (don't forget to save it within Couch's 'snippets' folder) to create a language selection menu.

2. A standalone PHP script named 'switch.php'.
Make sure to place 'switch.php' within your Couch installation folder (along with Couch's core files).
This script will do the job of persisting the visitor's selected language in session (apart for sanitizing the supplied parameters as a security measure).

The 'lang_switcher_menu.html' simply outputs an HTML list showing the available languages to the visitor
Code: Select all
   <!-- lang selector menu -->
   <ul id="lang_selector">
      <cms:php>
      global $accepted_langs, $selected_lang;
      foreach( $accepted_langs as $lang ){
         $selected_class = ( $lang==$selected_lang ) ? ' selected' : '';
         echo'<li class="'.$lang.$selected_class.'"><a href="<cms:show k_admin_link />switch.php?lang='.$lang.'&redirect='.urlencode($_SERVER["REQUEST_URI"]).'"><span>'.strtoupper($lang).'</span></a></li>';
      }
      </cms:php>
   </ul>

Let us embed this to create a menu in our template and we get the final version of our multi-lingual template-
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
   <cms:embed 'lang_getter.html' />
   <cms:template>
      <cms:editable name="photo" type="image" />
      <cms:editable name="content_en" type="textarea" />
      <cms:editable name="content_fr" type="textarea" />
      <cms:editable name="content_es" type="textarea" />
   </cms:template>

   <cms:embed 'lang_switcher_menu.html' />
   
   <h1>Language Test</h1>
   <p> <img src="<cms:show photo />" /> </p>
   <cms:if my_lang='en'><cms:show content_en /></cms:if>
   <cms:if my_lang='fr'><cms:show content_fr /></cms:if>
   <cms:if my_lang='es'><cms:show content_es /></cms:if>
   
   <!-- Alternate method of showing variable -->
   <br />
   <cms:get "content_<cms:show my_lang />" />   
   
<?php COUCH::invoke(); ?>

You can embed 'lang_switcher_menu.html' anywhere on your template to create the language selection menu but make sure to embed it below the 'lang_getter.html'.
The menu is generic enough to be styled anyway you desire but you can also modify it to create your own version.

The important thing to note is that when a visitor clicks on any of the shown languages, the 'switch.php' script is invoked. 'switch.php' persists the selected language in session and then redirects the visitor to the page he used the menu from.

And that is it. That was the final version of our multi-lingual template.

It might have seemed like a very long tutorial but essentially it only consisted of
1. Placing 'lang_getter.html', 'lang_switcher_menu.html' within Couch's snippets folder and placing 'switch.php' within Couch's main installation folder .
2. Embedding 'lang_switcher_menu.html' in our template to create a language selection menu.
3. Embedding 'lang_getter.html' somewhere at the top of our template to find out the selected language.
4. Creating multiple editable regions (one for each language).
5. Outputting the value from the right editable region taking into consideration the selected language.

Hope this helps.
Do feel free to contact us if you have any questions.

Attachments

Hi KK,

I have been racking my brain all night long over the exact same task before finding this great thread - what a relief! :D

It really is a joy to read your explanations, and it is fascinating to even be offered several ways to retrofit a multi-lingual site. I am really looking forward to trying out the interesting solutions shown above.

Very impressed by this great CMS with every new task I am confronted with!

Solaris
Hi KK,

Is it now possible to set a "session" (with 1.3.5) to handle this? I am trying the following but keet getting a logic error - perhaps it's something very simple:

Template code - very simple test setup:

Code: Select all
<cms:template clonable='0' nested_pages='0' hidden='1' title='Sessions and Cookies'>

<cms:editable name='content_en' label='English Content' type='text' />

<cms:editable name='content_fr' label='French Content' type='text' />

</cms:template>


Below is the two forms to select English or French - the current language bit is just to test the session variable is been set correctly (which it is when I don't include any conditional statements to select the content fields.

Code: Select all
         <cms:form method="post" anchor='0'>
            <cms:if k_success >
                <cms:set_session name='language' value='content_fr' />
                <cms:redirect k_page_link />   
            </cms:if>
            <cms:input name="submit" type="submit" value="French" />
         </cms:form>      
         
         <cms:form method="post" anchor='0'>
            <cms:if k_success >
                <cms:set_session name='language' value='content_en' />
                <cms:redirect k_page_link />   
            </cms:if>
            <cms:input name="submit" type="submit" value="English" />
         </cms:form>   
         

          <p>Current Language: <strong><cms:get_session 'language' /></strong></p>
         
         <cms:if "<cms:get_session 'language' />" eq 'content_fr'>
         <p class="alert"><cms:show content_fr /></p>
         </cms:if>
Hi Patrick,

With Couch 1.3.5 now supporting session variables, it is indeed possible to implement the last described method without using PHP.

For the sake of uniformity, please allow me to use the original example to illustrate how to do this.

Now that we have 'cms:set_session' and 'cms:get_session' tags, the 'lang_getter.html' snippet we used in <cms:embed 'lang_getter.html' /> statement can now simply become -
Code: Select all
<cms:set my_lang="<cms:get_session 'language' />" />
<cms:if my_lang!='en' &&  my_lang!='fr' && my_lang!='es'>
    <cms:set my_lang='en' />
</cms:if>

while the 'lang_switcher_menu.html' snippet used in
<cms:embed 'lang_switcher_menu.html' /> statement can become (I am using your code here, Patrick, but one may also use a single form with dropdown here or use images for the submit buttons etc.)
Code: Select all
<cms:form method="post" anchor='0'>
    <cms:if k_success >
        <cms:set_session name='language' value='en' />
        <cms:redirect k_page_link />   
    </cms:if>
    <cms:input name="submit" type="submit" value="English" />
</cms:form>

<cms:form method="post" anchor='0'>
    <cms:if k_success >
        <cms:set_session name='language' value='fr' />
        <cms:redirect k_page_link />   
    </cms:if>
    <cms:input name="submit" type="submit" value="French" />
</cms:form>     

<cms:form method="post" anchor='0'>
    <cms:if k_success >
        <cms:set_session name='language' value='es' />
        <cms:redirect k_page_link />   
    </cms:if>
    <cms:input name="submit" type="submit" value="Spanish" />
</cms:form> 

This works just the same as the original code (and, IMHO, is a tad simpler to understand).
Thank you for making me realize that we can now use native Couch tags :)

P.S. As to why the code you pasted does not work as expected. I think it the following thread will answer that
viewtopic.php?f=4&t=7111&p=9487
Hi KK,

Thanks for that! Working perfectly now, it's a nice neat way to select languages and I'd agree that the new "sessions" setting function makes the code a little easier to understand.

One questions - how would you make the session setting out of href and a select dropdown? I fiddled with a select / option but was not sure how to handle the if_k_success part.
- how would you make the session setting out of href and a select dropdown?

Here is a language selector (courtesy @cheesypoof) using a dropdown
Code: Select all
<cms:form method='post' anchor='0'>
    <cms:if k_success && (frm_lang == 'en' || frm_lang == 'fr' || frm_lang == 'es')>
        <cms:set_session name='language' value=frm_lang />
        <cms:redirect k_page_link />
    </cms:if>
    <cms:input type='dropdown' name='lang' opt_values='English=en | French=fr | Spanish=es' opt_selected=my_lang onchange='this.form.submit();'/>
    <noscript>
        <input type="submit" value="Go"/>
    </noscript>
</cms:form>
KK wrote: 2. A standalone PHP script named 'switch.php'.
Make sure to place 'switch.php' within your Couch installation folder (along with Couch's core files).
This script will do the job of persisting the visitor's selected language in session (apart for sanitizing the supplied parameters as a security measure).


After trying to implement this file, it requests me to have a license file. I would believe that this is released before Couch went open-source.

It seems the easy way, is not viable, will try to implement form based as stated below. Thanks for solutions posted.
49 posts Page 1 of 5