changeset 2181:0cfaeae59452

add force_locale context manager for flask-babel
author Ana Balica <ana.balica@gmail.com>
date Tue, 03 Sep 2013 23:50:11 +0300
parents ec2029ab6585
children 827d351c7c96
files MoinMoin/i18n/__init__.py MoinMoin/i18n/_tests/test_i18n.py
diffstat 2 files changed, 57 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/i18n/__init__.py	Tue Sep 03 22:59:38 2013 +0300
+++ b/MoinMoin/i18n/__init__.py	Tue Sep 03 23:50:11 2013 +0300
@@ -15,8 +15,9 @@
 
 
 from babel import Locale
+from contextlib import contextmanager
 
-from flask import current_app, request
+from flask import current_app, request, _request_ctx_stack
 from flask import g as flaskg
 from flask.ext.babel import Babel, gettext, ngettext, lazy_gettext
 
@@ -66,3 +67,37 @@
     u = getattr(flaskg, 'user', None)
     if u and u.timezone is not None:
         return u.timezone
+
+
+# Original source is a patch to Flask Babel
+# https://github.com/lalinsky/flask-babel/commit/09ee1702c7129598bb202aa40a0e2e19f5414c24
+@contextmanager
+def force_locale(locale):
+    """Temporarily overrides the currently selected locale. Sometimes
+    it is useful to switch the current locale to different one, do
+    some tasks and then revert back to the original one. For example,
+    if the user uses German on the web site, but you want to send
+    them an email in English, you can use this function as a context
+    manager::
+
+        with force_locale('en_US'):
+            send_email(gettext('Hello!'), ...)
+    """
+    ctx = _request_ctx_stack.top
+    if ctx is None:
+        yield
+        return
+    babel = ctx.app.extensions['babel']
+    orig_locale_selector_func = babel.locale_selector_func
+    orig_attrs = {}
+    for key in ('babel_translations', 'babel_locale'):
+        orig_attrs[key] = getattr(ctx, key, None)
+    try:
+        babel.locale_selector_func = lambda: locale
+        for key in orig_attrs:
+            setattr(ctx, key, None)
+        yield
+    finally:
+        babel.locale_selector_func = orig_locale_selector_func
+        for key, value in orig_attrs.iteritems():
+            setattr(ctx, key, value)
--- a/MoinMoin/i18n/_tests/test_i18n.py	Tue Sep 03 22:59:38 2013 +0300
+++ b/MoinMoin/i18n/_tests/test_i18n.py	Tue Sep 03 23:50:11 2013 +0300
@@ -5,8 +5,12 @@
 Test for i18n
 """
 
-from MoinMoin.i18n import get_locale, get_timezone
+import pytest
 
+from flask import Flask
+from flask.ext import babel
+
+from MoinMoin.i18n import get_locale, get_timezone, force_locale
 from MoinMoin.i18n import _, L_, N_
 
 
@@ -32,3 +36,19 @@
     assert result1 == 'text1'
     result2 = N_('text1', 'text2', 2)
     assert result2 == 'text2'
+
+
+def test_force_locale():
+    pytest.skip("This test needs to be run with --assert=reinterp or --assert=plain flag")
+    app = Flask(__name__)
+    b = babel.Babel(app)
+
+    @b.localeselector
+    def select_locale():
+        return 'de_DE'
+
+    with app.test_request_context():
+        assert str(babel.get_locale()) == 'de_DE'
+        with force_locale('en_US'):
+            assert str(babel.get_locale()) == 'en_US'
+        assert str(babel.get_locale()) == 'de_DE'