# -*- coding: utf-8 -*- """ kalapy.i18n.utils ~~~~~~~~~~~~~~~~~ This module implements i18n support functions. :copyright: (c) 2010 Amit Mendapara. :license: BSD, see LICENSE for more details. """ import os, sys from pytz import timezone, UTC from babel import Locale from babel.support import LazyProxy, Translations from kalapy.conf import settings #: cache of loaded translations (speedup) TRANSLATIONS = {} def get_translations(): """Returns gettext translations to be used for current locale. """ locale = str(get_locale()) translations = TRANSLATIONS.get(locale) if translations is None: translations = load_translations('kalapy', locale) if isinstance(translations, Translations): for package in settings.INSTALLED_PACKAGES: tr = load_translations(package, locale) if isinstance(tr, Translations): translations.merge(tr) TRANSLATIONS[locale] = translations return translations def load_translations(import_name, locale): """Loads gettext translations for the given locale from the specified package represented by the given import name. """ if import_name not in sys.modules: return None path = os.path.abspath(os.path.dirname(sys.modules[import_name].__file__)) path = os.path.join(path, 'locale') return Translations.load(path, [locale]) def get_locale(): """Returns the locale to be used for current request as `babel.Locale` object. If used outside of a request, it return default locale as specified by `settings.DEFAULT_LOCALE`. """ from kalapy.web import request try: locale = getattr(request, 'babel_locale', None) except: locale = None if locale is None: try: locale = Locale.parse(request.accept_languages.best, sep='-') request.babel_locale = locale except: locale = Locale.parse(settings.DEFAULT_LOCALE) return locale def get_timezone(): """Returns the timezone to be used for current request as `pytz.timezone` object. If used outside of a request, it return default timezone as specified by `settings.DEFAULT_TIMEZONE`. """ from kalapy.web import request try: tzinfo = getattr(request, 'babel_tzinfo', None) except: tzinfo = None if tzinfo is None: #XXX: should use user timezone tzinfo = timezone(settings.DEFAULT_TIMEZONE) if request: request.babel_tzinfo = tzinfo return tzinfo def gettext(string, **kwargs): """Translates the given string with current locale and passes the given keyword variables as a mapping to format the string. The returned value is a lazy instance which will be translated when it is actually used. Example:: h1 = gettext('Hello World!') h2 = gettext('Hello %(name)s!', name='World') @web.route('/say') def say(): return h1 :param string: the string to be translated :param kwargs: mapping to the format place holders :returns: a lazy instance to delay actual translation, translation will be performed when result is actually used. """ def lazy(s, **kw): return get_translations().ugettext(s) % kw return LazyProxy(lazy, string, **kwargs) def ngettext(string, plural, num, **kwargs): """Translates the given string with current locale and passes the given keyword variables as a mapping to format the string. It does a plural-forms lookup of a given string depending on the `num` and uses `plural` instead of `string` if `num` represents plural in the current locale. The returned value is a lazy instance which will be translated when it is actually used. Example:: ngettext('%(num)d Apple', '%(num)d Apples!', num=len(apples)) :param string: the string to be translated, singular form :param plural: the plural form of the string :param num: value of num placeholder :param kwargs: mapping to the format place holders :returns: a lazy instance to delay actual translation, translation will be performed when result is actually used. """ def lazy(s, p, n, **kw): kw.setdefault('num', n) return get_translations().ungettext(s, p, n) % kw return LazyProxy(lazy, string, plural, num, **kwargs)