Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
4 posts Page 1 of 1
Hi, I've got this multilanguage system working, it's on a live site. I still have some work on the language switcher, but I've got an idea in mind that has the potential of succeeding. The only thing that is bothering me now are the urls that are the same for the both languages for some particular pages.
Because I'm working with single template for all languages, but with cookies to select the current language.

For example: I'm having a /about page that depending on the cookie returns a result in a different language.
At the moment I have a Dutch and an English version.
I would always need the cookie, because non-page related items I call my "building blocks" are language dependent too (menu, footer, etc.)
Also it allows me to use just a single template and it doesn't matter how many languages are used, it remains very clean.
I can add languages afterwards without having to alter code. I can do it from the admin panel only. I'll show you some code after explaining the current problem.

I would like to add a Dutch url "/over-ons" that is actually the same page as the "/about" page and alter the cookie depending on the fact if the url matches the language of the cookie.
If not I can alter the cookie so it matches the url and therefor all other content can be shown in the same language.

So to make it clear: I would like to have an "/over-ons" url and an "/about" url that would both point to "/about" but keep the requested name (so no redirect but rather masking the actual page name).

I've been messing with the .htaccess, but it doesn't seem to work. I've tried copying the generated .htaccess code from the "about" page and replacing the first part with "over-ons", but no success.

Now the code to help you understand this case (feel free to use it for your own project if you like)

languages.php
Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
<cms:template title="Languages" clonable="1" executable='0'>
    <cms:editable name="language_code" label="Language Code" desc="Ex. EN" type="text"></cms:editable>   
    <cms:editable name="index" label="Index Number" desc="Used for sorting languages" type="text" validator="integer"></cms:editable>
    <cms:editable name="icon" label="Icon" type="image" />
</cms:template>

<?php COUCH::invoke(); ?>


This is the admin template I use for sorting my entries (just link them in the functions to the right templates), this only works with cloned pages, haven't found a way yet to get it to work with nested pages, however the translating itself works, the back-end sorting doesn't
Code: Select all
<cms:php>
    // Set info about selected folder
    global $DB, $CTX, $FUNCS;
   
    $fid = ( isset($_GET['fid']) && $FUNCS->is_non_zero_natural($_GET['fid']) ) ? (int)$_GET['fid'] : null;
    if( $fid ){
        $rs = $DB->select( K_TBL_FOLDERS, array('name'), "id='" . $DB->sanitize( $fid ). "'" );
        if( count($rs) ){
            $fname = $rs[0]['name'];
        }
    }
   
    $CTX->set( 'my_selected_fid', $fid, 'global' );
    $CTX->set( 'my_selected_fname', $fname, 'global' );
   
    if ( isset($_GET['lang']) && preg_match("/^[a-z0-9\-]+$/", $_GET['lang']) ){
        $CTX->set( 'filtered_language', $_GET['lang'], 'global' );
    }
</cms:php>

<cms:capture into='my_folders' scope='global'>
    <cms:if k_folder_totalchildren >
        <div class="bulk-actions">
           
            <cms:dropdownfolders masterpage=k_template_name prompt='View all folders' hierarchical='1' selected_id=my_selected_fid />
           
            <a class="button" id="btn_folder_submit"
                href="<cms:admin_link />"
                onclick="this.style.cursor='wait'; return false;" >
                <span>Filter</span>
            </a>
           
        </div>
    </cms:if>
</cms:capture>


<cms:set translatable_template_id=k_template_id scope="global"/>
<cms:set current_template_name=k_template_name scope='global'/>
<a href='?act=list&tpl=<cms:show translatable_template_id />'>All(<cms:show k_folder_totalpagecount />)</a>
<cms:pages masterpage='languages.php' orderby="index" order="asc">
    <cms:set counter="0" scope="global"/>
    <cms:set requested_language=k_page_name scope="global" />
    <cms:pages masterpage=current_template_name>
        <cms:if current_language=requested_language>
            <cms:incr counter />
        </cms:if>
    </cms:pages>
   &nbsp;|&nbsp;
   <a href='?act=list&tpl=<cms:show translatable_template_id />&lang=<cms:show k_page_name />'><cms:show k_page_title />(<cms:show counter />)</a>
   <cms:if requested_language=k_page_name >
       <cms:set current_page_title="<cms:show k_page_title /> (<cms:show counter />)" scope="global"/>
   </cms:if>
</cms:pages>
<h3 style="margin-top:20px; margin-bottom:5px;">
    <cms:if "<cms:not_empty requested_language/>">
        <cms:show current_page_title />
    <cms:else />
        <cms:show "All (<cms:show k_folder_totalpagecount />)" />
    </cms:if>
</h3>


<cms:capture into='my_list' scope='global'>
    <table class="listing clear" cellspacing="0" cellpadding="0">
   
        <thead>
            <tr>
                <th class="checkbox">
                    <input type="checkbox" name="check-all" onclick="$$('.page-selector').set('checked', this.checked);">
                </th>
               
                <!-- EDIT -->
                <th>Title</th>
                <th>&nbsp;</th>
                <th>Folder</th>
                <th>Date</th>
                <th>Actions</th>
                <!-- END EDIT -->
               
            </tr>
        </thead>
       
        <tbody>   
            <cms:pages masterpage=k_template_name folder=my_selected_fname paginate='1' limit='15' show_unpublished='1' >
               
                     <cms:if (current_language=filtered_language) || (filtered_language="") >
               
                        <cms:if k_paginated_bottom >
                            <cms:if k_paginator_required >
                                <cms:capture into='my_paginator' scope='global'>
                                    <cms:php>
                                        global $CTX, $FUNCS;

                                        // Paginator assumes front-end template link as base. Make it point to the back-end.
                                        $pagination_link = $CTX->get( 'k_page_being_paginated' );
                                        $pagination_link = str_replace( $CTX->get('k_template_link'), $CTX->get('k_admin_link'), $pagination_link );
                                        $CTX->set( 'k_page_being_paginated', $pagination_link );
                                    </cms:php>
                                    <cms:paginator adjacents='2' />
                                    <div class="record-count">Showing <cms:show k_record_from />-<cms:show k_record_to /> / <cms:show k_total_records /></div>
                                </cms:capture>   
                            </cms:if>
                            <cms:set row_class='last_row' />
                        </cms:if>

                        <!-- EDIT -->
                        <tr>
                            <td class="checkbox <cms:show row_class />">
                                <input type="checkbox" value="<cms:show k_page_id />" class="page-selector" name="page-id[]">
                            </td>

                            <td class="name <cms:show row_class />">
                                <a href="<cms:admin_link />" title="<cms:show k_page_title />">
                                    <cms:excerpt count='48' truncate_chars='1'><cms:show k_page_title /></cms:excerpt>
                                </a>
                            </td>

                            <td class="comments-count <cms:show row_class />">&nbsp;</td>

                            <td class="folder <cms:show row_class />"><cms:show k_page_foldertitle /></td>

                            <td class="date <cms:show row_class />"><cms:if k_page_date=='0000-00-00 00:00:00' >Unpublished<cms:else /><cms:date k_page_date format='M jS Y' /></cms:if></td>

                            <td class="actions <cms:show row_class />">
                                <!-- edit -->
                                <a href="<cms:admin_link />">
                                    <img src="<cms:show k_admin_link />theme/images/page_white_edit.gif" title="Edit">
                                </a>

                                <!-- delete -->
                                <a href="<cms:admin_delete_link />"
                                    onclick="if( confirm('Are you sure you want to delete page: <cms:show k_page_name />?') ) { return true; } return false;">
                                    <img src="<cms:show k_admin_link />theme/images/page_white_delete.gif" title="Delete">
                                </a>

                                <!-- view -->
                                <a href="<cms:show k_page_link />" target="_blank" title="View">
                                    <img src="<cms:show k_admin_link />theme/images/magnifier.gif">
                                </a>
                            </td>
                        </tr>

                        <cms:no_results>
                            <tr><td colspan="6" class="last_row" style="text-align:center">No pages found</td></tr>
                        </cms:no_results>

                        <!-- END EDIT -->

                    </cms:if>

            </cms:pages>
        </tbody>
    </table>
</cms:capture>


<form name="frm_list_pages" id="frm_list_pages" action="" method="post">

    <div class="wrap-paginator">
        <cms:show my_folders />
        <cms:show my_paginator />
    </div>

    <div class="group-wrapper listing">
        <cms:show my_list />
    </div>

    <div class="wrap-paginator">
        <div class="bulk-actions">
            <a class="button" id="btn_bulk_submit" href="#">
                <span>Delete Selected</span>
            </a>
        </div>
       
        <cms:show my_paginator />
    </div>
   
    <input type="hidden" id="nonce" name="nonce" value="<cms:php>global $FUNCS; echo $FUNCS->create_nonce( 'bulk_action_page' );</cms:php>">
    <input type="hidden" id="bulk-action" name="bulk-action" value="delete">
   
</form>

<script type="text/javascript">
    //<![CDATA[
    window.addEvent('domready', function(){
        if( $('btn_folder_submit') ){
            $('btn_folder_submit').addEvent('click', function(e){
                var link = this.href
                var fid = $('f_k_folders').value;
                if( fid != -1 ){
                    link += '&fid=' + fid;
                }
                document.location.href = link;
            });
        }
    });
   
    function k_hook_bulk_submit(){
        if( $('btn_bulk_submit') ){
            $('btn_bulk_submit').addEvent('click', function(e){
                var col = $$('.page-selector');
                for( var x=0; x<col.length; x++ ){
                    if( col[x].checked ){
                        if( confirm('<cms:php> global $FUNCS; echo $FUNCS->t('confirm_delete_selected_pages'); </cms:php>') ){
                            $$('body').setStyle('cursor', 'wait');
                            $('frm_list_pages').submit();
                        }
                        return false;
                    }
                }
                return false;
                });
        }
    }
    window.addEvent( 'domready', k_hook_bulk_submit );
    //]]>
</script>


setting and getting the cookie (embed snippet on each page you want translated)
Code: Select all

<cms:set cookie_language="" scope="global"/>

<cms:pages masterpage="languages.php">
    <cms:if k_page_name="<cms:get_cookie 'current_language' />">
       
        <cms:set cookie_language=k_page_name scope="global" />
    </cms:if>
</cms:pages>

<cms:if "<cms:not_empty cookie_language />">
    <cms:set requested_language=cookie_language scope="global"/>
<cms:else />
    <cms:pages masterpage="languages.php" limit="1" order_by="index" order="asc">
        <cms:set requested_language=k_page_name  scope="global"/>
    </cms:pages>
    <cms:set_cookie name='current_language' value=current_language  expire='-1'/>
</cms:if>



add the translatable.php snippet to each template you want to translate
Code: Select all
 <!-- Start generate options with dropdown -->
<cms:set available_languages="---Select---=-" scope='global'/>

<cms:pages masterpage='languages.php'>
    <cms:set available_languages="<cms:concat available_languages '|' k_page_title '=' k_page_name />" scope='global' />
</cms:pages>

<cms:editable
    type='dropdown' 
    name='current_language'
    label='Language'
    desc='The language this particular page is written in.'
    opt_values=available_languages
    required='1'
/>
<!-- end generate options with dropdown -->
<cms:ignore>
<cms:set current_masterpage=k_template_name scope='global' />


<cms:pages masterpage='languages.php'>
    <cms:set translation_language=k_page_name scope='global' />
    <cms:set dropdown_name="<cms:concat k_page_name '_translation' />" scope='global'/>
    <cms:set available_translations="---Select---=\"\"" scope='global'/>
    <cms:pages masterpage=current_masterpage >
        <cms:if current_language = translation_language >
            <cms:set available_translations="<cms:concat available_translations '|' k_page_title '=' k_page_name />" scope='global' />
        </cms:if>
    </cms:pages>
    <cms:editable
        type='dropdown'
        name=dropdown_name
        masterpage=current_masterpage
        required='0'
        opt_values=available_translations
    />
</cms:pages>
</cms:ignore>



translate.php is the functionality for the switcher, at the moment only pointing to index, but I'm working on a more advanced switcher
Code: Select all
 <?php require_once( 'couch/cms.php' ); ?>
<cms:template title="Translate" clonable="0" executable='1' hidden="1" order='100'>
   
</cms:template>

<cms:set lang="<cms:php>if(isset($_GET['lang'])){echo $_GET['lang']; }</cms:php>" scope="global" />
<cms:set page="<cms:php>if(isset($_GET['page'])){echo $_GET['page']; }</cms:php>" scope="global" />

<cms:pages masterpage="languages.php">
    <cms:if lang=k_page_name>
         <cms:set_cookie name='current_language' value=lang />
    </cms:if>
</cms:pages>

<cms:redirect "index.php" />

<?php COUCH::invoke(); ?>




snippet for displaying the current language switcher
Code: Select all
             <cms:pages masterpage="languages.php" >
                <a href="<cms:show k_site_link />translate.php?lang=<cms:show k_page_name/>&page=<cms:show current_page />" style="float:right; margin-right: 5px; margin-top:5px;" >
                    <img src="<cms:show icon />" style="margin:auto;" />
                </a>
            </cms:pages>
         




I use the custom_field option and exclude option while listing pages / folders / nested pages (this sometimes requires some looping up front, but not always) to filter out the other languages.

I guess that's about it. This is working really well for me, I hope someone can help me out with the url issue. Then it would almost be perfect :) (but the other flaws aren't bothering me that much)
Hi :) How about embedding 2 different snippets on /about ?
/over-ons would be then a dummy page, always redirecting to /about. In /about you show the content dependent on the selected language. This way it can be manageable..
@trendoman: yes that would work, but it would require to add templates when more languages are added, again resulting in a cluttered admin panel. If I could not display some templates in the admin panel, that would be awesome, I also have this stylesheet just sitting there while it has no input fields since it gets its color settings from my skin template...
So, you got one template for many languages and editables are stacked one under another? If so, how do you show proper editables with cms:pages?
4 posts Page 1 of 1