1
"""Translation/Localization functions.
3
Provides :mod:`gettext` translation functions via an app's
4
``pylons.translator`` and get/set_lang for changing the language
9
from gettext import NullTranslations, translation
13
__all__ = ['_', 'add_fallback', 'get_lang', 'gettext', 'gettext_noop',
14
'lazy_gettext', 'lazy_ngettext', 'lazy_ugettext', 'lazy_ungettext',
15
'ngettext', 'set_lang', 'ugettext', 'ungettext', 'LanguageError',
18
class LanguageError(Exception):
19
"""Exception raised when a problem occurs with changing languages"""
23
class LazyString(object):
24
"""Has a number of lazily evaluated functions replicating a
25
string. Just override the eval() method to produce the actual value.
27
This method copied from TurboGears.
30
def __init__(self, func, *args, **kwargs):
36
return self.func(*self.args, **self.kwargs)
38
def __unicode__(self):
39
return unicode(self.eval())
42
return str(self.eval())
44
def __mod__(self, other):
45
return self.eval() % other
49
"""Decorator to return a lazy-evaluated version of the original"""
50
def newfunc(*args, **kwargs):
51
return LazyString(func, *args, **kwargs)
52
newfunc.__name__ = 'lazy_%s' % func.__name__
53
newfunc.__doc__ = 'Lazy-evaluated version of the %s function\n\n%s' % \
54
(func.__name__, func.__doc__)
58
def gettext_noop(value):
59
"""Mark a string for translation without translating it. Returns
62
Used for global strings, e.g.::
68
self.local_foo = _(foo)
71
assert Bar().local_foo == 'Bonjour'
73
assert Bar().local_foo == 'Hola'
82
"""Mark a string for translation. Returns the localized string of
85
Mark a string to be localized as follows::
87
gettext('This should be in lots of languages')
90
return pylons.translator.gettext(value)
91
lazy_gettext = lazify(gettext)
95
"""Mark a string for translation. Returns the localized unicode
98
Mark a string to be localized as follows::
100
_('This should be in lots of languages')
103
return pylons.translator.ugettext(value)
105
lazy_ugettext = lazify(ugettext)
108
def ngettext(singular, plural, n):
109
"""Mark a string for translation. Returns the localized string of
110
the pluralized value.
112
This does a plural-forms lookup of a message id. ``singular`` is
113
used as the message id for purposes of lookup in the catalog, while
114
``n`` is used to determine which plural form to use. The returned
117
Mark a string to be localized as follows::
119
ngettext('There is %(num)d file here', 'There are %(num)d files here',
123
return pylons.translator.ngettext(singular, plural, n)
124
lazy_ngettext = lazify(ngettext)
127
def ungettext(singular, plural, n):
128
"""Mark a string for translation. Returns the localized unicode
129
string of the pluralized value.
131
This does a plural-forms lookup of a message id. ``singular`` is
132
used as the message id for purposes of lookup in the catalog, while
133
``n`` is used to determine which plural form to use. The returned
134
message is a Unicode string.
136
Mark a string to be localized as follows::
138
ungettext('There is %(num)d file here', 'There are %(num)d files here',
142
return pylons.translator.ungettext(singular, plural, n)
143
lazy_ungettext = lazify(ungettext)
146
def _get_translator(lang, **kwargs):
147
"""Utility method to get a valid translator object from a language
150
return NullTranslations()
151
if 'pylons_config' in kwargs:
152
conf = kwargs.pop('pylons_config')
154
conf = pylons.config.current_conf()
155
localedir = os.path.join(conf['pylons.paths']['root'], 'i18n')
156
if not isinstance(lang, list):
159
translator = translation(conf['pylons.package'], localedir,
160
languages=lang, **kwargs)
162
raise LanguageError('IOError: %s' % ioe)
163
translator.pylons_lang = lang
167
def set_lang(lang, **kwargs):
168
"""Set the current language used for translations.
170
``lang`` should be a string or a list of strings. If a list of
171
strings, the first language is set as the main and the subsequent
172
languages are added as fallbacks.
174
translator = _get_translator(lang, **kwargs)
175
environ = pylons.request.environ
176
environ['pylons.pylons'].translator = translator
177
if 'paste.registry' in environ:
178
environ['paste.registry'].replace(pylons.translator, translator)
182
"""Return the current i18n language used"""
183
return getattr(pylons.translator, 'pylons_lang', None)
186
def add_fallback(lang, **kwargs):
187
"""Add a fallback language from which words not matched in other
188
languages will be translated to.
190
This fallback will be associated with the currently selected
191
language -- that is, resetting the language via set_lang() resets
192
the current fallbacks.
194
This function can be called multiple times to add multiple
197
return pylons.translator.add_fallback(_get_translator(lang, **kwargs))