Table Of Contents

Previous topic

Configuring and using the Logging System

Next topic

Working With SQLAlchemy And Your Data Model

Handling Internationalization And Localization

Status:Work in progress

Turbogears2 relies on Babel for i18n and l10n support. So if this document is not enough you will want to check their respective documentation:

A quickstarted project comes fully i18n enabled so you should get started quickly.

If you’re lucky enough you’ll even see “Your application is now running” message in your language.

Language Auto-Select

Turbogears2 contains the logic (hardwired in the TurboGearsController class at the moment) to setup request’s language based on browser’s preferences(*).

[*] - Every modern browser sends a special header along with every web request which tells the server which language it would prefer to see in a response.

Making your code international

Whenever you write a message that has to displayed you must let TurboGears know that it has to be translated.

Even though TurboGears is able to automatically detect content inside tags and mark them for translation all the strings inside controllers must be explicitly marked as translated.

This can be achieved with the tg.i18n.ugettext and tg.i18n.lazy_ugettext calls which are usually imported with _ and l_ names:

from tg.i18n import ugettext as _

class RootController(BaseController):
    @expose('myproj.templates.index')
    def index(self):
        return dict(msg=_('Hello World'))

In the previous example the ‘Hello World’ string will be detect by TurboGears when collecting translatable text and will display in the browser language if a translation for that language is available.

While ugettext works perfectly to translate strings inside a request it does not allow translating strings outside a request. This is due to the fact that TurboGears won’t know the browser language when there isn’t a running request. To translate global variables, parameters default values or any other string which is created outside a controller method the lazy_ugettext method must be used:

from tg.i18n import lazy_ugettext as l_

class RootController(BaseController):
    @expose('myproj.templates.index')
    def index(self, msg=l_('Hello World')):
        return dict(msg=msg)

In this case the msg parameter is translated using lazy_ugettext as it is constructed at controller import time when no request is available. This will create an object that will translate the given string only when the string itself is displayed or evaluated.

Keep in mind that as the lazy string object built by lazy_ugetted is translated whenever the string is evaluated joining strings or editing it will force the translation. So the resulting object must still be evaluated only inside a request or it will always be translated to the default project language only.

An i18n Quick Start

After quickstarting your project, you will notice that the setup.py file contains the following section:

message_extractors = {'yourapp': [
         ('**.py', 'python', None),
         ('templates/**.mako', 'mako', None),
         ('templates/**.html', 'genshi', None),
         ('public/**', 'ignore', None)]},

This is an extraction method mapping that indicates to distutils which files should be searched for strings to be translated. TurboGears2 uses Babel to extract messages to a .pot file in your project’s i18n directory. Don’t forget to add it to your revision control system if you use one.

1. Extract all the translatable strings from your project’s files by using the following command:

python setup.py extract_messages

This command will generate a “pot” file in the i18n folder of your application. This pot file is the reference file that serves for all the different translations.

2. Create a translation catalog for your language, let’s take ‘zh_tw’ for example:

python setup.py init_catalog -l zh_tw

3. Edit your language in i18n/[country code]/LC_MESSAGES/[project-name].po

If you’re not an expert in i18n or if you would like to give the files to someone else so that he helps you we recommend that you use the really nice poedit program. This program works nicely on GNU/Linux and Windows and provides a nice user-interface to edit po files.

../_images/poedit.png
  1. Compile your lang:

    python setup.py compile_catalog
  2. Config development.ini:

    [app:main]
    use = egg: my-project
    full_stack = true
    lang = zh_tw
  3. Start server:

    paster serve --reload development.ini

And see the local message show on the screen.

Commands

To fresh start a translation, you could use the following command to handle your locales:

init_catalog

You can extract all messages from the project with the following command:

python setup.py init_catalog -l [country code]

The country code could be es(Spanish), fr(France), zh_tw(Taiwan), jp(JAPAN), ru(Russian), or any other country code.

Compile Catalog

You can extract all messages from the project with the following command:

python setup.py compile_catalog

Update Catalog

You can update the catalog with the following command:

python setup.py update_catalog