*********************************** 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 :data:`biryani.states.default_state` (an instance of class :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: .. raw:: html
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)