Quick links: Content - sections - sub sections

Jelix has its own localization/internationalization mechanism. The setLocale and gettext functions from php are not used because too much constraining to setup, and their configuration is chancy on servers.


Each text or string that you want to translate is associated to a key. These associations are placed in "property files". Each property file is associated to a language and a character encoding. The default language and character encoding are configured in the config file of your application.

The following code will store the current locale in the lang variable.

//use the following line if in an function context
global $gJConfig;

$lang = $gJConfig->locale;

To be able to retrieve a string in the current language, simply call jLocale::get('LocaleSelector'), or, in templates, use the @LocaleSelector@ syntax (see the template page).

Property files

Property files are files containing translations. They follow strict conventions. They are located in the locales directory of the modules. This directory has a specific organization. It has a sub-directories for each language. Example: locales/fr_FR/ for France's french, locales/en_US/ for United States' english, and so on. In each language directory there are many property files, corresponding to the same language but different character encoding.

File name

The name of the property files has the following structure : codename.charset.properties. The codename will be used in the locale selectors, and charset corresponds to a character encoding. The codename can only use alphanumeric characters. Example: generic.ISO-8859-1.properties, generic.UTF-8.properties, etc.

If in the config file, the default language is en_US ("locale=en_US") and the default character encoding is UTF-8 ("charset=UTF-8"), then the en_US/*.UTF-8.properties files will be used (where * represent a given codename).

File content

The file content structure is quite simple. It's basically a key=translated string structure, with some improvements. There isn't real coding guidelines in the file, but you might organizing your locales using a 'generic.specific' scheme for the key names. You can't use double and single quotes to delimit your strings, new lines do this.

Here is an example for our english locale (en_US/generic.ISO-8859-1.properties) file :

title.offlineElements = elements to check
title.onlineElements = online elements

buttons.save = Save

And the equivalent in the french locale (fr_FR/generic.ISO-8859-1.properties) :

title.offlineElements = éléments à traiter
title.onlineElements = éléments en ligne
buttons.save = Enregistrer
Multi line

If the text is long and you want to write it in several lines, you can type an anti-slash (\) at the end of each line (excepted the last one of the text), to tell the parser to continue reading the translated string.

intro=this is a very very\
long text in\
several lines
message=this is a regular line

However, it doesn't insert a line break in the displayed string. If you want to insert a real line break, use \n or \r (\r\n on windows, \n on linux, \r on macs: \r\n should do the trick for everyone!):

intro=this is a very very\nlong text in\nseveral lines, but in\n one line\nin the source

You can also put some comments. They have to begin with a #. When the parser sees and #, the rest of the line is ignored. A comment can be at the beginning of a line, or in the middle of a line, or at the end of the line. If you want to use a # in a value, you have to escape it with an anti-slash (\#).


Whitespaces before and after a value are ignored. If you want to put a value equal to a space, you have to use \w

nospace= #this is using a regular space
space= \w#this is using a \w space

The value of space will be ' ', and the value of nospace, ''.

HTML entities

Localized strings shouldn't contain HTML entities. First because a localized string could be used for other content than HTML, and second because jelix escapes html characters for you when necessary (i.e. the title of a page). So if the given string contains entities, this entities will be escaped and the browser won't identify them. To summarize, © will become ©.

If you want to use specific characters (~ or © etc), choose the corresponding charset and directly use these characters. They will be escaped for you. This is why it is a good idea to use the UTF-8 character encoding in your application, since it includes every existing character in any language.

If you really want to put some html in a localized string, and to use it in a jtpl template with the {jlocale} tag, a possibility is to put a ".html" at the end of the locale name as follow:

my.nice.title.of.my.paragraph.html = <strong>My nice title of my paragraph</strong>

Then, the {jlocale} tag won't escape the content of the locale.

Retrieving a localized string

To retrieve a string, you have to use the get static method of jLocale. This method accepts a locale selector as the first argument, which has the following structure : module~codename.keystring. The "module~" part is optional if the requested property file is in the current module.

For example, to retrieve the value of buttons.save in generic.ISO-8859-1.properties in the "website" module:

  $string = jLocale:get("website~generic.buttons.save");

In a template, use the @LocaleSelector@ notation:

  <input type="button" value="{@website~generic.buttons.save@}" />

Localized string with parameters

It could be useful to have localized string with dynamic parameters. For example, you want to write this string:

   You will go on the http://www.jelix.org website and you will click on the 'documentation' section.

But you would like to use the same sentence with different websites or sections: you want to dynamically indicate the url of the web site and the name of the section. This is the purpose of parameters in the jLocale component.

  $string = jLocale::get("website~generic.sentence", array('http://www.jelix.org', 'documentation'));

And in the property file, you have to put a "%s" where you want to insert this dynamic values:

   sentence = You will go on the %s web site and you will click on the '%s' category.

Since the translated string is parsed by the sprintf php function, you should follow it's syntax. This means that you use %d for a number, %s for a string, and so on. The order of the parameters is extremely important.

    $string = jLocale::get("website~generic.sentence", array('http://www.jelix.org', 'documentation'));
    //will give you You will go on the http://www.jelix.org website and you will click on the 'documentation' section.

    $string = jLocale::get("website~generic.sentence", array('documentation', 'http://www.jelix.org'));
    //will give you You will go on the documentation website and you will click on the 'http://www.jelix.org' section.

It may happen in some language that the translation causes a change in the order of parameters. But since the code is language generic, you won't pass the parameters in a different order. So you will use the syntax %x$s where x is the order id. For example, you could have this sentence in english:

   sentence = You will go on the %s web site and you will click on the '%s' section.

But in another language, the translator would like to change the order of the parameters: the first parameter in the sentence will be the section name, not the website url. So for example, in French, he could translate like this:

   sentence = Cliquez sur la rubrique %2$s lorsque vous irez sur le site %1$s.

The first parameter will replace "%1$s", the second parameter will replace "%2$s", and so on.

Note that in template, you can't use the "@localeSelector@" syntax to indicate parameters. The only option left is to use the jLocale plugin:

   <p>{jlocale "website~generic.sentence", array('http://www.jelix.org', 'documentation')}</p>

Changing the language on the fly

Jelix provides a coordinator plugin supporting dynamic switching of languages : autolocale (located in lib/jelix/plugins/coord/). (see the documentation about coordinator plugins).

The autolocale plugin scans urls looking for a specific parameter indicating a language. If found, it switches your application and your user to this language by storing it in session. locale configuration option is re-written by autolocale after being loaded from the configuration, so the configuration file remains untouched.

Even though the autolocale modifies the locale setting, you still get the current locale as usual:

//use the following line if in an function context
global $gJConfig;

$lang = $gJConfig->locale;

To use autolocale plugin, copy lib/jelix/plugins/coord/autolocale/autolocale.coord.ini.php.dist into var/config/ and rename it autolocale.coord.ini.php.

There are four important configuration options in this file :

enableUrlDetection = on
urlParamNameLanguage = lang
availableLanguageCode = en_US,fr_FR

enableUrlDetection activate url-scanning. availableLanguageCode lists all of your supported languages. Any other language code will be ignored. urlParamNameLanguage is the url parameter defining a language code. You can then add a parameter on your urls to switch to other languages:

  <a href="?lang=fr_FR">français</a>
  <a href="?lang=en_EN">english</a>

Of course, if you use the significant url engine, you can still rewrite your urls specifically for each language.

The last step is to activate the plugin. In Jelix configuration file, edit [coordplugins] section :

autolocale = autolocale.coord.ini.php

Auto detection of the language

The autolocale plugin also allow to detect automatically the language of the user, by checking the http headers sent by the browser of the user when he visits your website for the first time.

If you want to enable this auto detection, you have to set the useDefaultLanguageBrowser parameter to on.

Localizing templates

There are situations where it would be better to localize an entire template than to create lots of locale strings.

To achieve this, just move your template in a sub-folder of its templates directory. As for locale files, there must be one sub-folder for each language (Example: templates/en_US/, templates/fr_FR/).