From a305c9efac56a3270a103d85a90dd6a48353e2f8 Mon Sep 17 00:00:00 2001 From: str4d Date: Sun, 14 Jul 2013 07:00:00 +0000 Subject: [PATCH] Patched Flask-Babel to support multiple gettext domains --- multi-domain.patch | 115 +++++++++++++++++++++++++++++++++++++++++++++ setup_venv.sh | 2 + 2 files changed, 117 insertions(+) create mode 100644 multi-domain.patch diff --git a/multi-domain.patch b/multi-domain.patch new file mode 100644 index 00000000..9548d56e --- /dev/null +++ b/multi-domain.patch @@ -0,0 +1,115 @@ +--- env/lib/python2.7/site-packages/flaskext/babel.py 2013-07-13 00:00:00 +0000 ++++ env/lib/python2.7/site-packages/flaskext/babel.py 2013-07-13 00:00:00 +0000 +@@ -19,6 +19,7 @@ + from datetime import datetime + from flask import _request_ctx_stack + from babel import dates, numbers, support, Locale ++from gettext import NullTranslations + from werkzeug import ImmutableDict + try: + from pytz.gae import pytz +@@ -55,9 +56,11 @@ + }) + + def __init__(self, app=None, default_locale='en', default_timezone='UTC', +- date_formats=None, configure_jinja=True): ++ date_formats=None, configure_jinja=True, ++ default_domain=support.Translations.DEFAULT_DOMAIN): + self._default_locale = default_locale + self._default_timezone = default_timezone ++ self._default_domain = default_domain + self._date_formats = date_formats + self._configure_jinja = configure_jinja + self.app = app +@@ -77,6 +80,7 @@ + + app.config.setdefault('BABEL_DEFAULT_LOCALE', self._default_locale) + app.config.setdefault('BABEL_DEFAULT_TIMEZONE', self._default_timezone) ++ app.config.setdefault('BABEL_DEFAULT_DOMAIN', self._default_domain) + if self._date_formats is None: + self._date_formats = self.default_date_formats.copy() + +@@ -95,6 +99,7 @@ + + self.locale_selector_func = None + self.timezone_selector_func = None ++ self.domain_selector_func = None + + if self._configure_jinja: + app.jinja_env.filters.update( +@@ -142,6 +147,19 @@ + self.timezone_selector_func = f + return f + ++ def domainselector(self, f): ++ """Registers a callback function for domain selection. The default ++ behaves as if a function was registered that returns `None` all the ++ time. If `None` is returned, the domain falls back to the one from ++ the configuration. ++ ++ This has to return the domain as a list of strings (eg: ``['messages']``) ++ """ ++ assert self.domain_selector_func is None, \ ++ 'a localeselector function is already registered' ++ self.domain_selector_func = f ++ return f ++ + + def list_translations(self): + """Returns a list of all the locales translations exist for. The +@@ -178,6 +196,13 @@ + """ + return timezone(self.app.config['BABEL_DEFAULT_TIMEZONE']) + ++ @property ++ def default_domain(self): ++ """The default domain from the configuration as instance of a ++ `string` object. ++ """ ++ return self.app.config['BABEL_DEFAULT_DOMAIN'] ++ + + def get_translations(): + """Returns the correct gettext translations that should be used for +@@ -191,7 +216,10 @@ + translations = getattr(ctx, 'babel_translations', None) + if translations is None: + dirname = os.path.join(ctx.app.root_path, 'translations') +- translations = support.Translations.load(dirname, [get_locale()]) ++ locale = get_locale() ++ for domain in get_domains(): ++ dt = support.Translations.load(dirname, [locale], domain) ++ translations = dt if translations is None or isinstance(translations, NullTranslations) else translations.merge(dt) + ctx.babel_translations = translations + return translations + +@@ -243,6 +271,29 @@ + return tzinfo + + ++def get_domains(): ++ """Returns the domains that should be used for this request as ++ `list` object. This returns `None` if used outside of ++ a request. ++ """ ++ ctx = _request_ctx_stack.top ++ if ctx is None: ++ return None ++ domains = getattr(ctx, 'babel_domains', None) ++ if domains is None: ++ babel = ctx.app.extensions['babel'] ++ if babel.domain_selector_func is None: ++ domains = [babel.default_domain] ++ else: ++ rv = babel.domain_selector_func() ++ if rv is None: ++ domains = [babel.default_domain] ++ else: ++ domains = rv ++ ctx.babel_domains = domains ++ return domains ++ ++ + def refresh(): + """Refreshes the cached timezones and locale information. This can + be used to switch a translation between a request and if you want diff --git a/setup_venv.sh b/setup_venv.sh index af98f169..79d46ba2 100755 --- a/setup_venv.sh +++ b/setup_venv.sh @@ -11,4 +11,6 @@ else . $venv_dir/bin/activate pip install -r reqs.txt + # Apply multi-domain patch to Flask-Babel + patch -p0