Internationalization & Localization

Biryani uses gettext for internationalization and localization.

Translations for Biryani messages are located in biryani/i18n directory.

To translate messages, Biryani converters use the _() method of their state parameter.

The defaut state parameter biryani.states.default_state (an instance of class biryani.states.State) has a _() method that returns the given message asis, without any translation. So, to translate Biryani messages you should define a new state that redefines it.

Translations status

Biryani uses Transifex to translate its messages.

Here is the current status of Biryani translations:

Loading chart...

Using a localized state

Here is an example of how to have french error messages with Biryani:

>>> import gettext
>>> import os
>>> import pkg_resources
>>> from biryani import states
...
>>> french_translation = gettext.translation('biryani',
...     os.path.join(pkg_resources.get_distribution('biryani').location, 'biryani', 'i18n'),languages = ['fr'])
...
>>> class FrenchState(states.State):
...     _ = staticmethod(french_translation.ugettext)
...
>>> french_state = FrenchState()

Note

If you get an IOError: [Errno 2] No translation file found for domain: 'biryani', your Biryani translations are not properly installed. To avoid this error, you can specify a localedir argument to gettext.translation, like:

french_translation = gettext.translation('biryani', localedir = 'path/to/biryani/i18n', languages = ['fr'])

or, if the content of biryani/i18n directory has been copied in /usr/local/share/local:

french_translation = gettext.translation('biryani', '/usr/local/share/locale', languages = ['fr'])

Once the state has been properly defined, you can use it for your conversions:

>>> from biryani import baseconv as conv
...
>>> conv.not_none(None)
(None, u'Missing value')
>>> conv.not_none(None, state = states.default_state)
(None, u'Missing value')
>>> conv.not_none(None, state = french_state)
(None, u'Valeur manquante')
>>> conv.pipe(conv.input_to_int, conv.not_none)(None, state = french_state)
(None, u'Valeur manquante')
>>> conv.pipe(conv.input_to_int, conv.not_none)(u'Hello world!')
(u'Hello world!', u'Value must be an integer')
>>> conv.pipe(conv.input_to_int, conv.not_none)(u'Hello world!', state = french_state)
(u'Hello world!', u'La valeur doit \xeatre un entier')

Using an internationalized state

When using Biryani in web applications, for example, you will often need to display error messages using the current user’s prefered languages.

>>> class UserState(states.State):
...     _translations_cache = {}
...     languages = ['en_US', 'en'] # Default languages for user
...
...     @property
...     def _(self):
...         languages = tuple(self.languages)
...         translation = self._translations_cache.get(languages)
...         if translation is None:
...             self._translations_cache[languages] = translation = gettext.translation('biryani',
...                 os.path.join(pkg_resources.get_distribution('biryani').location, 'biryani', 'i18n'),
...                 fallback = True, languages = languages)
...         return translation.ugettext
>>> user_state = UserState()
>>> conv.not_none(None, state = user_state)
(None, u'Missing value')
>>> french_user_state = UserState()
>>> french_user_state.languages = ['fr_FR', 'fr']
>>> conv.not_none(None, state = french_user_state)
(None, u'Valeur manquante')
>>> conv.pipe(conv.input_to_int, conv.not_none)(u'Hello world!', state = french_user_state)
(u'Hello world!', u'La valeur doit \xeatre un entier')

Using Biryani translations in an internationalized application

When using Biryani in an application that defines its own internationalized messages, you need to merge the translations.

One way to do this is to chain the translations using the fallback mechanism.

For example, if the application using Biryani is named myapp and stores its localized messages in myapp/i18n you could chain its translations with those of Biryani using some code like:

languages = ['fr']
biryani_translation = gettext.translation('biryani',
    os.path.join(pkg_resources.get_distribution('biryani').location, 'biryani', 'i18n'), fallback = True,
    languages = languages)
translation = gettext.translation('myapp', 'myapp/i18n', fallback = True, languages = languages)
translation.add_fallback(biryani_translation)