summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Carey <jecarey@us.ibm.com>2014-07-03 20:40:44 +0000
committerJames Carey <jecarey@us.ibm.com>2014-07-07 15:39:16 +0000
commit3d90045d2d1ce1df89f75937f415e3982e111063 (patch)
tree5b3316322c2d1139d3f13d1e9e2e2c8511883b88
parent53a232ef9dfed6bf3654847703b968906cec66d1 (diff)
downloadoslo-incubator-3d90045d2d1ce1df89f75937f415e3982e111063.tar.gz
Backport code for i18n to check lazy at runtime
Currently in the oslo-incubator version of i18n support the TranslationFactory generates a direct translation method based on the passed lazy parameter. This means that when the default is assigned to _ during its intial import, lazy isn't specified, which defaults to False, so the TranslationFactory returns a method that does not support lazy translation. The _ method is not changed until enable_lazy is called, thus any import of _ prior to that will cache the initial method that does not support lazy translation even when it has been enabled. This problem was exposed by the cinder test case: cinder/tests/test_wsgi.py test test_cinder_exception_with_localized_explanation when the file: cinder/api/middleware/fault.py had the line: from cinder.openstack.common.gettextutils import _ added to it. This behavior is corrected in the i18n library such that the generated method checks the global _lazy.USE_LAZY to determine if lazy translation should be used in commit: Iae22668 Check the lazy flag at runtime Note that this removes the lazy parameter from the signature of install and the TranslationFactory to match the library. Change-Id: If1832b012d4b72708d0850367a1ec55cb0cd63e8
-rw-r--r--openstack/common/gettextutils.py63
-rw-r--r--tests/unit/test_gettext.py47
2 files changed, 45 insertions, 65 deletions
diff --git a/openstack/common/gettextutils.py b/openstack/common/gettextutils.py
index 87229a93..59545c49 100644
--- a/openstack/common/gettextutils.py
+++ b/openstack/common/gettextutils.py
@@ -23,7 +23,6 @@ Usual usage in an openstack.common module:
"""
import copy
-import functools
import gettext
import locale
from logging import handlers
@@ -42,7 +41,7 @@ class TranslatorFactory(object):
"""Create translator functions
"""
- def __init__(self, domain, lazy=False, localedir=None):
+ def __init__(self, domain, localedir=None):
"""Establish a set of translation functions for the domain.
:param domain: Name of translation domain,
@@ -55,7 +54,6 @@ class TranslatorFactory(object):
:type localedir: str
"""
self.domain = domain
- self.lazy = lazy
if localedir is None:
localedir = os.environ.get(domain.upper() + '_LOCALEDIR')
self.localedir = localedir
@@ -75,16 +73,19 @@ class TranslatorFactory(object):
"""
if domain is None:
domain = self.domain
- if self.lazy:
- return functools.partial(Message, domain=domain)
- t = gettext.translation(
- domain,
- localedir=self.localedir,
- fallback=True,
- )
- if six.PY3:
- return t.gettext
- return t.ugettext
+ t = gettext.translation(domain,
+ localedir=self.localedir,
+ fallback=True)
+ # Use the appropriate method of the translation object based
+ # on the python version.
+ m = t.gettext if six.PY3 else t.ugettext
+
+ def f(msg):
+ """oslo.i18n.gettextutils translation function."""
+ if USE_LAZY:
+ return Message(msg, domain=domain)
+ return m(msg)
+ return f
@property
def primary(self):
@@ -147,19 +148,11 @@ def enable_lazy():
your project is importing _ directly instead of using the
gettextutils.install() way of importing the _ function.
"""
- # FIXME(dhellmann): This function will be removed in oslo.i18n,
- # because the TranslatorFactory makes it superfluous.
- global _, _LI, _LW, _LE, _LC, USE_LAZY
- tf = TranslatorFactory('oslo', lazy=True)
- _ = tf.primary
- _LI = tf.log_info
- _LW = tf.log_warning
- _LE = tf.log_error
- _LC = tf.log_critical
+ global USE_LAZY
USE_LAZY = True
-def install(domain, lazy=False):
+def install(domain):
"""Install a _() function using the given translation domain.
Given a translation domain, install a _() function using gettext's
@@ -170,26 +163,14 @@ def install(domain, lazy=False):
a translation-domain-specific environment variable (e.g.
NOVA_LOCALEDIR).
+ Note that to enable lazy translation, enable_lazy must be
+ called.
+
:param domain: the translation domain
- :param lazy: indicates whether or not to install the lazy _() function.
- The lazy _() introduces a way to do deferred translation
- of messages by installing a _ that builds Message objects,
- instead of strings, which can then be lazily translated into
- any available locale.
"""
- if lazy:
- from six import moves
- tf = TranslatorFactory(domain, lazy=True)
- moves.builtins.__dict__['_'] = tf.primary
- else:
- localedir = '%s_LOCALEDIR' % domain.upper()
- if six.PY3:
- gettext.install(domain,
- localedir=os.environ.get(localedir))
- else:
- gettext.install(domain,
- localedir=os.environ.get(localedir),
- unicode=True)
+ from six import moves
+ tf = TranslatorFactory(domain)
+ moves.builtins.__dict__['_'] = tf.primary
class Message(six.text_type):
diff --git a/tests/unit/test_gettext.py b/tests/unit/test_gettext.py
index 47490534..1d9d6ad2 100644
--- a/tests/unit/test_gettext.py
+++ b/tests/unit/test_gettext.py
@@ -39,6 +39,7 @@ class GettextTest(test_base.BaseTestCase):
self.mox = moxfixture.mox
# remember so we can reset to it later
self._USE_LAZY = gettextutils.USE_LAZY
+ gettextutils.USE_LAZY = False
def tearDown(self):
# reset to value before test
@@ -59,28 +60,14 @@ class GettextTest(test_base.BaseTestCase):
gettextutils.install('blaa')
self.assertTrue(isinstance(_('A String'), six.text_type)) # noqa
- gettextutils.install('blaa', lazy=True)
+ def test_gettextutils_install_with_enable(self):
+ gettextutils.install('blaa')
+ self.assertTrue(isinstance(_('A String'), six.text_type)) # noqa
+
+ gettextutils.enable_lazy()
self.assertTrue(isinstance(_('A Message'), # noqa
gettextutils.Message))
- def test_gettext_install_looks_up_localedir(self):
- with mock.patch('os.environ.get') as environ_get:
- with mock.patch('gettext.install') as gettext_install:
- environ_get.return_value = '/foo/bar'
-
- gettextutils.install('blaa')
-
- environ_get.assert_called_once_with('BLAA_LOCALEDIR')
- if six.PY3:
- gettext_install.assert_called_once_with(
- 'blaa',
- localedir='/foo/bar')
- else:
- gettext_install.assert_called_once_with(
- 'blaa',
- localedir='/foo/bar',
- unicode=True)
-
def test_get_available_languages(self):
# All the available languages for which locale data is available
def _mock_locale_identifiers():
@@ -718,9 +705,21 @@ class TranslationHandlerTestCase(test_base.BaseTestCase):
class TranslatorFactoryTest(test_base.BaseTestCase):
+ def setUp(self):
+ super(TranslatorFactoryTest, self).setUp()
+ # remember so we can reset to it later
+ self._USE_LAZY = gettextutils.USE_LAZY
+ gettextutils.USE_LAZY = False
+
+ def tearDown(self):
+ # reset to value before test
+ gettextutils.USE_LAZY = self._USE_LAZY
+ super(TranslatorFactoryTest, self).tearDown()
+
def test_lazy(self):
with mock.patch.object(gettextutils, 'Message') as msg:
- tf = gettextutils.TranslatorFactory('domain', lazy=True)
+ tf = gettextutils.TranslatorFactory('domain')
+ gettextutils.enable_lazy()
tf.primary('some text')
msg.assert_called_with('some text', domain='domain')
@@ -731,7 +730,7 @@ class TranslatorFactoryTest(test_base.BaseTestCase):
translation.return_value = trans
trans.gettext.side_effect = AssertionError(
'should have called ugettext')
- tf = gettextutils.TranslatorFactory('domain', lazy=False)
+ tf = gettextutils.TranslatorFactory('domain')
tf.primary('some text')
trans.ugettext.assert_called_with('some text')
@@ -742,14 +741,14 @@ class TranslatorFactoryTest(test_base.BaseTestCase):
translation.return_value = trans
trans.ugettext.side_effect = AssertionError(
'should have called gettext')
- tf = gettextutils.TranslatorFactory('domain', lazy=False)
+ tf = gettextutils.TranslatorFactory('domain')
tf.primary('some text')
trans.gettext.assert_called_with('some text')
def test_log_level_domain_name(self):
with mock.patch.object(gettextutils.TranslatorFactory,
'_make_translation_func') as mtf:
- tf = gettextutils.TranslatorFactory('domain', lazy=False)
+ tf = gettextutils.TranslatorFactory('domain')
tf._make_log_translation_func('mylevel')
mtf.assert_called_with('domain-log-mylevel')
@@ -765,7 +764,7 @@ class LogLevelTranslationsTest(test_base.BaseTestCase):
def test(self):
with mock.patch.object(gettextutils.TranslatorFactory,
'_make_translation_func') as mtf:
- tf = gettextutils.TranslatorFactory('domain', lazy=False)
+ tf = gettextutils.TranslatorFactory('domain')
getattr(tf, 'log_%s' % self.level)
mtf.assert_called_with('domain-log-%s' % self.level)