Sharing technology, ideas, insights!
Call: +91 710 466 0336         Email: hello@sanisoft.com

Blog

Multilingual apps with CakePHP

Note: If you are looking for a way to set page titles in CakePHP it is here

There are basic two ways to creating a multilingual app in traditional PHP, using a file with variables for each of the phrase which our Coppermine Picture Gallery uses and then there is the gettext series of functions in PHP, which while a very good option for desktop apps can be a pain for web apps because they are dependent on server as well as client LOCALE. CakePHP V1.2 is the framework which allows you to take the quantum leap of using gettext like functionality with minimum of hassles and at the same time address the common problems which a PHP programmer faces while creating multilingual apps

What I outline below is an example of translating a sentence in a view and some tips on working with .po files. The sentence which I want to make multilingual is “Hello Grandma!” starting with the view – you write

Thats it! As far as your ‘view’ is concerned it is now multilingual ready, no I am not joking really, if you do not do anything else the ‘Hello Grandma’ will still render properly, do note that you are not required to write echo or print if you use the __() function without the second parameter.

OK, while making the view multilingual ready take less work than your regular echo(ing) making the translations work takes a bit more work. We now want ‘Hello Grandma’ to appear in French – ‘Bonjour grand-maman’.

Start by creating a file /app/locale/fre/LC_MESSAGES/default.po

Note here that the ISO 639-2 language codes are used to name the folder, and you have rightly guessed fre is the code for French, the default.po file is what will contain the translated text and is written in the following simple pattern

[code] msgid “Hello Grandma”
msgstr “Bonjour grand-maman”
[/code]

Some people prefer the msgid to be more varaiblish like ‘hello_grandma’ (with a corresponding change in the view) but I rather prefer to give the msgid in plain English, which also happens to be the default language for all of my development.

Now the only step that remains is setting the language to use. For this in your controller write

If you write the same key to session then the language code in session will take precedence – I use this trick to allow for user selectable languages.

Since we are now using gettext, if you are on a *nix development machine you get a number of useful CLI tools which ease the process of creating .po files the first among them is xgettext a utility to extract gettext strings from source and create a .po file. If your view files is called hello.ctp then from the commandline while in the same directory as your view file do
[code]xgettext -L php –keyword=__ hello.ctp[/code] this will result in a file called messages.po which will have all the strings which you need to translate as msgid, xgettext is very powerful and can work on entire folders with subfolders. See the xgettext man page for more information.

Two other useful utilities are msgcat and msgattr, msgcat allows you to combine several message catalogs and msgattrib allows for attribute matching and manipulation on message catalog.

An idea for combining several .po files into one without any duplication can be done with something like
[code] msgcat –use-first general.po [^g]*.po | msgattrib –no-fuzzy -o default.po[/code] as shown here

If you have any particular trick of your own I would love to hear from you….

Update: Running ./cake extract from the command line allows you to extract all the messages to be translated into a convenient default.pot file

About the Author

Dr. Tarique Sani is a pediatrician and forensic expert by education. He is a PHP programmer of 'wrote the book' caliber and has to his credit several very popular open source as well as commercial PHP projects. He leads a team of dynamic programmers at SANIsoft who have in-depth understanding of Web scalability, development tools and usability practices with strong developmental skills in PHP, MySQL/PostgreSQL, HTML, Javascript, and Linux/Apache

17 comments

  1. Pingback: developercast.com » Sanisoft Blog: Multilingual apps with CakePHP

  2. Hi,

    I’m interested to know how you set up your URL strucutre.

    I’ve done it a few ways, mod-rewritten sub-domains

    en.domain.com/store/shirts/

    and first url segment

    domain.com/en/store/shirts/

    last url segment

    domain.com/store/shirts/en/

    and query string

    domain.com/store/shirts.php?lang=en

    I’ve never really decided what is the best semantically. For big apps I now use sub-domain, for smaller I use first url segment … it’s easier to ID it, vs using last url segment which can confuse dispatching (if all URL’s in the site do not have the same number of segments … which is normal, then you have to test the last segment of each url etc …)

    But what is more meaningful … to imply that there be two “stores”

    domain.com/fr/store/
    domain.com/en/store/

    ? or would there be one store, with sub page per lang
    domain.com/stores/shirts/fr/
    domain.com/stores/shirts/en/

    domain.com/home/en/

    I’m really interested to know what others think.

  3. I prefer doing domain.com/fr/store/ or domain.com/en/store/ would be most appropriate as it indicates a clear hierarchy in URL with two stores one French and one English

  4. Pingback: DuperMag » Archivo » Que fácil es hacer sitios multi-idioma con CakePHP 1.2

  5. Do you by any chance know how to only get the string but not to output in the new cakePHP?

    I tried setting page title
    $this->pageTitle = __(‘My page title’);

    but this only echos my translated string to output (where it shouldn’t) and my page title is not what I want it to be.

    Any ideas ?
    I was searching tutorials but this does not seem to be covered at so well.

  6. Hi all!
    I just start a new site with cakephp 1.2 and while searching for “Multilingual” example I found this really useful post.

    I’d like to implement the “domain.com/en/store/shirts/” web link solution but I’m not able to found a clear tutorial about this…

    I just use the admin routing from cakephp manual but I think is not applicable in this situation…

    Can you help me? Do you know any tutorial about this procedure?
    Tnx!

  7. Pingback: Blog Dot Php With cakePHP » Полезные ссылки по cakePHP

  8. hi!

    nice article, very helpful for me.

    A little correction: I’ve found that to extract the messages to be translated should be executed the ./cake i18n command.

    Thank you again.

  9. Pingback: AmZ: Witaj!

  10. Hi, in default.po file i have writen
    msgid “Hello Grandma”
    msgstr “Bonjour grand-maman”

    now i want to display the text of msgstr using msgid. Could I get the details stape.
    Thanks

  11. This is not very clear, i do not know if cakephp is still developing this feature, or it is just well documented, but each place tells one thing apart on how to do it…. It is just starting to be like ACL some months ago… getting crazy…

Leave a Reply