wiki:Dev/i18n

Version 4 (modified by pferreir, 3 years ago) (diff)

--

Internationalization: Quick Start

From v0.98 on, Indico relies on Babel in order to manage language dictionaries and provide some basic date formatting and other locale-related functions.

Writing i18n-aware code

It's very hard to write/maintain an application that is 100% internationalized, since this requires a great deal of coordination not only with the translators, but between developers as well. Not only people usually forget to properly internationalize strings, but also when they remember to do so they choose to do it at the wrong place. Here are some examples of some good/bad practices.

For example:

class UserContainer(object):
    _userTypes = {
        # wrong!
        'admin': _('Administrator'),
        'regular': _('Regular user')
    }

    # ...

    def getUserType(self):
        # can you spot the problem?
        return UserContainer._userTypes[self.user_type]

Why is this wrong? Class attributes are initialized only once, at module load time. So, since modules are normally only loaded once per process, a French user that is using this app will theoretically (see paragraph below) get the same translation as a Japanese one. The right way to do so would be delaying translation till the template is rendered: we could have a dictionary of "English" strings and then just call _() from the piece of template (or other i18n-safe code) that calls getUserType.

Fortunately our current i18n code supports Lazy translation (meaning that it replaces the result string with a proxy object that will only execute the translation when it is asked for its string value), and the situation above would not be problematic. However, it not at all good practice and should be avoided.

Another classic mistake is:

from persistent import Persistent

# ...

class User(Persistent):
    def __init__(self, name, position):
        self.position = _(position)

This one should be easier to spot, if you consider that Persistent objects are stored in the database. By translating position, we get it in the language that was in use at the time of object creation. The right way to do it is, once again, to translate "as late as possible".