Localization

Contents...

Webasyst framework has built-in support for multi-lingual applications. The localization mechanism utilizes the functions provided by PHP extension gettext or, if it is not installed on the server, similar functions written in PHP are used.

Localization of apps

To display string word translated to the current user language, you can use the following syntax:

If no translation for string word is found, the string is displayed without translation: word.

gettext localization files containing translations of interface strings to other languages must be placed inside the application file system according to following rule: wa-apps/[app_id]/locale/[LOCALE]/LC_MESSAGES/[app_id].po. For example, a localization file containing translation of text strings used in an application with the blog identifier into the Russian language must be located at wa-apps/[app_id]/locale/ru_RU/LC_MESSAGES/blog.po.

A file with the .po extension is a text file of in a special format, which contains translations of text strings for a specific language locale. In order to allow the application to use translations from a .po file, the file must be compiled to a file with the .mo extension; e.g., using the popular poEdit program.

Below is shown an example of a .po file containing translations into Russian:

msgid ""
msgstr ""
"Project-Id-Version: Guestbook\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2011-04-27 10:30+0300\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=((((n%10)==1)&&((n%100)!=11))?(0):(((((n%10)>=2)&&
((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2));\n"
"X-Poedit-Language: Russian\n"
"X-Poedit-Country: Russian Federation\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: .\n"
"X-Poedit-SearchPath-1: .\n"

msgid "Name"
msgstr "Имя"

msgid "Message"
msgstr "Сообщение"

msgid "post"
msgid_plural "posts"
msgstr[0] "запись"
msgstr[1] "записи"
msgstr[2] "записей"

"Key–translation" pairs

A localization key and its translation are represented in a .po file by a pair of lines as shown below:

msgid "Name"
msgstr "Имя"

We recommend using English strings as localization keys. This will allow your application to have a fully functional web interface in English. If translations of some or all interface strings are missing, then their English keys will be displayed in a browser.

Multiple forms of localization strings

Multiple translation forms allow an application developer to easily display localization strings in the correct form depending on the context, if it is required by the rules of a specific language; e.g. (there are several plural forms of the Russian word запись = record): 21 запись, 22 записи, 25 записей.

The following code in the header of a .po file is used to specify that there are three plural forms in the Russian language (as shown in the above example) and contains a formula to determine the correct plural form of a word depending on the number used with that word:

"Plural-Forms: nplurals=3; plural=((((n%10)==1)&&((n%100)!=11))?(0):(((((n%10)>=2)&&
((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2));\n"

A translation example of multiple word forms in a .po file:

msgid "post"
msgid_plural "posts"
msgstr[0] "запись"
msgstr[1] "записи"
msgstr[2] "записей"

To obtain the desired localization form for a word in PHP code, use the following syntax:

// this code will return one of the values запись, записи, or записей depending
  on the value of $n in accordance to the formula contained in the .po file
_w('post', 'posts', $n);

Below is shown a similar structure for use in Smarty templates:

{_w('post', 'posts', $n)}

Note the difference between the above example for Smarty and the syntax used to display single-value localization strings in template files: for single-value strings syntax [`word`] should be used.

Function _w() is also capable of automatically replacing substring %d by the value of $n within the translated string using PHP function sprintf; e.g.:

_w('%d file', '%d files', 21); // 21 файл (Russian for "21 files")
_w('%d file', '%d files', 22); // 22 файла (Russian for "22 files")
_w('%d file', '%d files', 25); // 25 файлов (Russian for "25 files")

Automatic generation of .po files

The framework supports automatic analysis of the entire source code of an application in order to collect all localization keys and to append missing keys to the .po file. If there is no .po file for an application, it is created automatically. To launch the automatic .po file generation scripts, run the following command on your server:

Example
php locale myapp

Auto-generation of .po files for plugins, widgets, and design themes is performed in a similar way:

php wa.php locale [app_id]/plugins/[plugin_id]
php wa.php locale [app_id]/widgets/[widget_id]
php wa.php locale [app_id]/themes/[theme_id]
Examples
php wa.php locale someapp/plugins/myplugin
php wa.php locale someapp/widgets/mywidget
php wa.php locale someapp/themes/mytheme

Generation of localization files in the debug mode

The script can add to .po files comments with paths to source files in which a particular localization key was found.

Example
#: /wa-apps/myapp/templates/actions/info.html:38
msgid "Company"
msgstr ""

Such a comment shows that a localization key was found on line 38 of the specified file. If you have doubts as to how to translate some localization string, you have a convenient opportunity to look up the logic used in the file where that string is used.

To add such comments to your .po file, run the script with --debug parameter.

Example
php wa.php locale myapp --debug

Once you have translated all strings in a .po file, run the script again—without the --debug parameter. Another execution of the script will simply delete unnecessary debugging comments from the localization file and reduce the size of the localization file, which will be included in the product installation archive.

Localization of app plugins

To use plugins' own localization files in PHP code, use function _wp() instead of _w().

Plugin localization files must reside, like those of apps, in locale/[LOCALE]/LC_MESSAGES/ inside plugin's subdirectory, and their names must match rule [app_id]_[plugin_id].po and [app_id]_[plugin_id].mo. For example, a Russian localization .po file of some plugin with ID some for the shop app must be available at wa-apps/shop/plugins/some/locale/ru_RU/LC_MESSAGES/shop_some.po (a .mo file must be located in the same directory).

Design theme localization

Design themes support 2 methods of localizing text strings:

Design theme localization via manifest file theme.xml

This is a traditional localization method for design themes. To use it, add element <locales></locales> by the following example to the manifest file’s root XML element:

<locales>
    <locale>
        <msgid>String key</msgid>
        <msgstr locale="ru_RU">Перевод строки</msgstr>
    </locale>
    <locale>
        <msgid>Another string key</msgid>
        <msgstr locale="ru_RU">Перевод другой строки</msgstr>
    </locale>
</locales>

Localization keys must be specified in templates files in the form

[`String key`]

Localization of design themes via manifest files does not support convenient use of plural forms; therefore, it is advisable to use the gettext localization option.

Design theme localization via gettext

Localization files must be placed at paths built by the following example: wa-apps/[app_id]/themes/[theme_id]/locale/[locale_id]/LC_MESSAGES/[app_id]_[theme_id].po. To quickly create localization files, use the .po file generation script.

When you use this localization option, specify string keys in template files in the same way:

[`String key`]

If you need to use plural forms, specify them in template files in the following format:

{_wp('%d entry', '%d entries', $n)}

Localization of system plugins

Names of localization files used for system plugins, which are located in wa-plugins/ directory, must have a suffix matching plugin's type, i.e. payment_, shipping_, or sms_. Here is an example of a Russian localization .po file of some payment plugin with ID some: wa-plugins/payment/some/locale/ru_RU/LC_MESSAGES/payment_some.po

To include localization strings of your plugin in its source code, use public method _w() of base class waSystemPlugin as shown in the examples below:

Development of a single-locale product

If you are absolutely sure that your product, an app or a plugin, will be used only with one language locale, then you do not need to use the localization mechanism. In this case simply type localization strings directly in the source code. Functions _w(), _wp(), and [``] constructs should not be used in such a product.