DIY international (i18n) urls in cake 1.1.x or lower

by Dieter_be
CakePHP 1.2 will have decent i18n functionality, but until you switch you can use the simple but decent solution that i have created. It allows you to use urls in any foreign language, which are translated right before the routing happens, so nothing intervenes with all the other logic (which is usually in english)
So, if you want to program in english (action names in controllers for example), but you want to use urls in an other language, and you are using a cakePHP version prior to 1.2? Here's the solution!

What you can expect: (example from one of my projects)
browse to urls like /activiteiten/overzicht/toekomst
cake will interpret it as /activities/index/future

after the translation and interpretation, the routing happens, so you have all the freedom to define routes for english urls, like you are used to.

put these 2 lines in app/config/routes.php above the routing rules.

PHP Snippet:

<?php 
include_once("translate.php");
$from_url translate($from_url,true);
?>

then, create the file app/config/translate.php and put this in it:

PHP Snippet:

<?php 
function translate($str null,$total false)
    {
        
$translatetable = array('kalender' => 'events',
                    
'fotos' => 'images',
                    
'afbeeldingen' => 'images',
                    
'activiteiten' => 'events',
                    
'paginas' => 'pages',
                    
'standaard' => 'default',
                    
'voegtoe' => 'add',
                    
'verwijder' => 'delete',
                    
'bewerk' => 'edit',
                    
'bekijk' => 'view',
                    
'overzicht' => 'index',
                    
'toekomst' => 'future',
                    
'verleden' => 'past',
                    
'nu' => 'now',
                    
'vragenenantwoorden' => 'faq'
                                
);
        if(
$str)
        {
            if(
$total)
            { 
                
$old explode('/',$str);
                
$lastone end($old);
                if(empty(
$lastone)) array_pop($old);
                
$new = array();
                                
                
/* translate each part or leave untranslated part */

                
for($i $i <sizeof($old) ; $i++)
                {
                    
$new[$i] = translate($old[$i]);
                }

                
                
/* construct the translated url.  this also adds a trailing "/" even if it wasn't in the original */
                
$new_url="";
                foreach(
$new as $n)
                {
                    
$new_url .= $n."/";
                }
                
                return 
$new_url;
            }
            else
            {
                foreach (
$translatetable as $orig => $new)
                {
                    if(
$str == $orig$str $new;
                }
                return 
$str;
            }
        }
    }
?>

If you want to use multiple languages, you can put all the rules in the same array. But in this case, you could have collisions (words that are written the same, but mean different things, for example the same word in different languages). This happens very rarily, but if you would encounter this, you could expand the logic by for example adding a 2-letter language identifier like '/nl/' in the url to choose the right array.

Report

More on Tutorials

Advertising

Comments

  • ThE_-_BliZZarD posted on 08/21/09 03:50:30 AM
    Dear Mr. Plaetinck,

    your article on translatebal URLs is great. But, in the first paragraph, you mentioned that Cake > 1.2 has this feature itself. Could you provide any additional information on that topic as I couldnt find ANY hint or tutorial on how to achieve this.
    Thanks in advance,
    Philipp Berger
  • walker posted on 11/06/06 06:42:26 PM
    Could you expand on adding /nl/ or another abbreviation that can be used to internationalize a webapp?

    I would like to do something like:
    http://domain.com/de/controller/action/id
    I am having trouble wrapping my head around this one and would appreciate any help.
    • Dieter_be posted on 11/07/06 03:03:54 AM
      Well, keep in mind that my solution is meant for translation of urls, not for the contents of the site itself. (there are already solutions for that)
      I've modified the translate.php to become something you could use, and you could even combine it with other i18n systems that translate the contents of the site itself, by checking the constant LANG_I18N. (or whatever you like to call it)

      [code php] function translate($str = null,$total = false)
      {
      $translatetable['de'] = array(...);
      $translatetable['nl'] = array(...);

      );
      if($str)
      {
      if($total)
      {
      $old = explode('/',$str);
      $lastone = end($old);
      if(empty($lastone)) array_pop($old);
      $new = array();

      if(isset($old[0])) define('LANG_I18N', $old[0]) ;
      /* translate each part or leave untranslated part */

      for($i = 0 ; $i {
      $new[$i] = translate($old[$i+1]);
      }


      /* construct the translated url. this also adds a trailing "/" even if it wasn't in the original */
      $new_url="";
      foreach($new as $n)
      {
      $new_url .= $n."/";
      }

      return $new_url;
      }
      else if(isset($translatetable[LANG_I18N]))
      {
      foreach ($translatetable[LANG_I18N] as $orig => $new)
      {
      if($str == $orig) $str = $new;
      }
      return $str;
      }
      }
      }
      • TommyO posted on 12/08/06 09:05:56 AM
        Nice article! I haven't touched multilanguage sites yet, but I will need to migrate my site to spanish very soon.

        Well, keep in mind that my solution is meant for translation of urls, not for the contents of the site itself. (there are already solutions for that) Do you have a favorite? Or maybe point to a good place to start?

        My two cents:
        By reworking that last 'else if' block with the following code, adding addition languages is as simple as dropping a new translations file into app/config/i18n/

        else if (file_exists(CONFIGS.'i18n'.DS.'translate_table_'.LANG_I18N.'.php')
        {
            include_once(CONFIGS.'i18n'.DS.'translate_table_'.LANG_I18N.'.php');
            foreach ($translatetable as $orig => $new)
            { ...

        The german translate_table_de.php for example might contain the $translatetable as it was originally posted, whereas a french table, translate_table_fr.php, would define the same array slightly differently.
        • Dieter_be posted on 01/04/07 03:33:44 AM
          No i don't have a favorite, as i actually know very less about the subject :) I just needed to have the urls in a custom language, i don't have to worry about the contents of the site (as they are in my case, until now, always in one language)

          A good place to start would be the bakery, cakeforge, cakephp's google group, etc.
          With 1.2 it will be built-in btw.
    • clouserw posted on 11/30/99 12:00:00 AM
      I would like to do something like:
      http://domain.com/de/controller/action/id

      Assuming you have an array of valid languages, I implemented the URLs with the $lang in them by putting the following in routes.php:

      foreach ($valid_languages as $language => $mapping) {

      // If they just go to /$lang/
      $Route->connect("/{$language}", array('controller' => 'addons', 'action' => 'home'));

      // connect localized, static pages
      $Route->connect("/{$language}/pages/*", array('controller' => 'pages', 'action' => 'display'));

      // Magical undocumented routing syntax
      $Route->connect("/{$language}/:controller/:action/*", array('controller' => 'pages', 'action' => 'index'));
      }

      (I hope that code looks better on the page than it does in this textbox...)
login to post a comment.