Latest Version: 0.9.6.2
/Users/bbangert/Programming/Python/pylons/pylons/i18n/translation.py
0001"""Translation/Localization functions.
0002
0003Provides ``gettext`` translation functions via an app's ``pylons.translator``
0004and get/set_lang for changing the language translated to.
0005"""
0006import os
0007from gettext import NullTranslations, translation
0008
0009import pylons
0010
0011__all__ = ['_', 'add_fallback', 'get_lang', 'gettext', 'gettext_noop',
0012           'lazy_gettext', 'lazy_ngettext', 'lazy_ugettext', 'lazy_ungettext',
0013           'ngettext', 'set_lang', 'ugettext', 'ungettext', 'LanguageError',
0014           'N_']
0015
0016class LanguageError(Exception):
0017    """Exception raised when a problem occurs with changing languages"""
0018    pass
0019
0020
0021class LazyString(object):
0022    """Has a number of lazily evaluated functions replicating a string. Just
0023    override the eval() method to produce the actual value.
0024
0025    This method copied from TurboGears.
0026    """
0027
0028    def __init__(self, func, *args, **kwargs):
0029        self.func = func
0030        self.args = args
0031        self.kwargs = kwargs
0032
0033    def eval(self):
0034        return self.func(*self.args, **self.kwargs)
0035
0036    def __unicode__(self):
0037        return unicode(self.eval())
0038
0039    def __str__(self):
0040        return str(self.eval())
0041
0042    def __mod__(self, other):
0043        return self.eval() % other
0044
0045
0046def lazify(func):
0047    """Decorator to return a lazy-evaluated version of the original"""
0048    def newfunc(*args, **kwargs):
0049        return LazyString(func, *args, **kwargs)
0050    try:
0051        newfunc.__name__ = 'lazy_%s' % func.__name__
0052    except TypeError: # Python < 2.4
0053        pass
0054    newfunc.__doc__ = 'Lazy-evaluated version of the %s function\n\n%s' %           (func.__name__, func.__doc__)
0056    return newfunc
0057
0058
0059def gettext_noop(value):
0060    """Mark a string for translation without translating it. Returns value.
0061
0062    Used for global strings, e.g.:
0063
0064    .. code-block:: Python
0065
0066        foo = N_('Hello')
0067
0068        class Bar:
0069            def __init__(self):
0070                self.local_foo = _(foo)
0071
0072        h.set_lang('fr')
0073        assert Bar().local_foo == 'Bonjour'
0074        h.set_lang('es')
0075        assert Bar().local_foo == 'Hola'
0076        assert foo == 'Hello'
0077    """
0078    return value
0079N_ = gettext_noop
0080
0081
0082def gettext(value):
0083    """Mark a string for translation. Returns the localized string of value.
0084
0085    Mark a string to be localized as follows:
0086
0087    .. code-block:: Python
0088
0089        gettext('This should be in lots of languages')
0090    """
0091    return pylons.translator.gettext(value)
0092lazy_gettext = lazify(gettext)
0093
0094
0095def ugettext(value):
0096    """Mark a string for translation. Returns the localized unicode string of
0097    value.
0098
0099    Mark a string to be localized as follows:
0100
0101    .. code-block:: Python
0102
0103        _('This should be in lots of languages')
0104    """
0105    return pylons.translator.ugettext(value)
0106_ = ugettext
0107lazy_ugettext = lazify(ugettext)
0108
0109
0110def ngettext(singular, plural, n):
0111    """Mark a string for translation. Returns the localized string of the
0112    pluralized value.
0113
0114    This does a plural-forms lookup of a message id. ``singular`` is used as
0115    the message id for purposes of lookup in the catalog, while ``n`` is used
0116    to determine which plural form to use. The returned message is a string.
0117
0118    Mark a string to be localized as follows:
0119
0120    .. code-block:: Python
0121
0122        ngettext('There is %(num)d file here', 'There are %(num)d files here',
0123                 n) % {'num': n}
0124    """
0125    return pylons.translator.ngettext(singular, plural, n)
0126lazy_ngettext = lazify(ngettext)
0127
0128
0129def ungettext(singular, plural, n):
0130    """Mark a string for translation. Returns the localized unicode string of
0131    the pluralized value.
0132
0133    This does a plural-forms lookup of a message id. ``singular`` is used as
0134    the message id for purposes of lookup in the catalog, while ``n`` is used
0135    to determine which plural form to use. The returned message is a Unicode
0136    string.
0137
0138    Mark a string to be localized as follows:
0139
0140    .. code-block:: Python
0141
0142        ungettext('There is %(num)d file here', 'There are %(num)d files here',
0143                  n) % {'num': n}
0144    """
0145    return pylons.translator.ungettext(singular, plural, n)
0146lazy_ungettext = lazify(ungettext)
0147
0148
0149def _get_translator(lang, **kwargs):
0150    """Utility method to get a valid translator object from a language name"""
0151    conf = pylons.config.current_conf()
0152    # XXX: root_path is deprecated
0153    rootdir = conf['pylons.paths'].get('root',
0154                                       conf['pylons.paths'].get('root_path'))
0155    localedir = os.path.join(rootdir, 'i18n')
0156    if not isinstance(lang, list):
0157        lang = [lang]
0158    try:
0159        translator = translation(conf['pylons.package'], localedir,
0160                                 languages=lang, **kwargs)
0161    except IOError, ioe:
0162        raise LanguageError('IOError: %s' % ioe)
0163    translator.pylons_lang = lang
0164    return translator
0165
0166
0167def set_lang(lang, **kwargs):
0168    """Set the i18n language used"""
0169    registry = pylons.request.environ['paste.registry']
0170    if not lang:
0171        registry.replace(pylons.translator, NullTranslations())
0172    else:
0173        translator = _get_translator(lang, **kwargs)
0174        registry.replace(pylons.translator, translator)
0175
0176
0177def get_lang():
0178    """Return the current i18n language used"""
0179    return getattr(pylons.translator, 'pylons_lang', None)
0180
0181
0182def add_fallback(lang, **kwargs):
0183    """Add a fallback language from which words not matched in other languages
0184    will be translated to.
0185    """
0186    return pylons.translator.add_fallback(_get_translator(lang, **kwargs))

Top