Shift public API to top level package
Rather than forcing everyone to say "from oslo.i18n import gettextutils" allow "from oslo import i18n". Change-Id: If87182beb8c7fa6a12f7a1524fdda4910b4e19d5
This commit is contained in:
parent
01f3f96bfe
commit
490466b2a2
@ -2,12 +2,12 @@
|
||||
API
|
||||
=====
|
||||
|
||||
oslo.i18n.gettextutils
|
||||
======================
|
||||
oslo.i18n
|
||||
=========
|
||||
|
||||
.. automodule:: oslo.i18n.gettextutils
|
||||
.. automodule:: oslo.i18n
|
||||
|
||||
.. autoclass:: oslo.i18n.gettextutils.TranslatorFactory
|
||||
.. autoclass:: oslo.i18n.TranslatorFactory
|
||||
:members:
|
||||
|
||||
.. seealso::
|
||||
@ -15,15 +15,15 @@ oslo.i18n.gettextutils
|
||||
An example of using a :class:`TranslatorFactory` is provided in
|
||||
:ref:`integration-module`.
|
||||
|
||||
.. autofunction:: oslo.i18n.gettextutils.enable_lazy
|
||||
.. autofunction:: oslo.i18n.enable_lazy
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`lazy-translation`
|
||||
|
||||
.. autofunction:: oslo.i18n.gettextutils.translate
|
||||
.. autofunction:: oslo.i18n.translate
|
||||
|
||||
.. autofunction:: oslo.i18n.gettextutils.get_available_languages
|
||||
.. autofunction:: oslo.i18n.get_available_languages
|
||||
|
||||
oslo.i18n.log
|
||||
=============
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
Text messages the user sees via exceptions or API calls should be
|
||||
translated using
|
||||
:py:attr:`TranslatorFactory.primary <oslo.i18n.gettextutils.TranslatorFactory.primary>`, which should
|
||||
:py:attr:`TranslatorFactory.primary <oslo.i18n.TranslatorFactory.primary>`, which should
|
||||
be installed as ``_()`` in the integration module.
|
||||
|
||||
.. seealso::
|
||||
|
@ -16,14 +16,14 @@ Creating an Integration Module
|
||||
|
||||
To use oslo.i18n in a project, you will need to create a small
|
||||
integration module to hold an instance of
|
||||
:class:`~oslo.i18n.gettextutils.TranslatorFactory` and references to
|
||||
:class:`~oslo.i18n.TranslatorFactory` and references to
|
||||
the marker functions the factory creates.
|
||||
|
||||
::
|
||||
|
||||
from oslo.i18n import gettextutils
|
||||
from oslo import i18n
|
||||
|
||||
_translators = gettextutils.TranslatorFactory(domain='myapp')
|
||||
_translators = i18n.TranslatorFactory(domain='myapp')
|
||||
|
||||
# The primary translation function using the well-known name "_"
|
||||
_ = _translators.primary
|
||||
@ -85,14 +85,14 @@ To enable lazy translation, call :func:`enable_lazy`.
|
||||
|
||||
::
|
||||
|
||||
from oslo.i18n import gettextutils
|
||||
from oslo import i18n
|
||||
|
||||
gettextutils.enable_lazy()
|
||||
i18n.enable_lazy()
|
||||
|
||||
Translating Messages
|
||||
====================
|
||||
|
||||
Use :func:`~oslo.i18n.gettextutils.translate` to translate strings to
|
||||
Use :func:`~oslo.i18n.translate` to translate strings to
|
||||
a specific locale. :func:`translate` handles delayed translation and
|
||||
strings that have already been translated immediately. It should be
|
||||
used at the point where the locale to be used is known, which is often
|
||||
@ -101,9 +101,9 @@ emitted.
|
||||
|
||||
::
|
||||
|
||||
from oslo.i18n import gettextutils
|
||||
from oslo import i18n
|
||||
|
||||
trans_msg = gettextutils.translate(msg, desired_locale=my_locale)
|
||||
trans_msg = i18n.translate(msg, desired_locale=my_locale)
|
||||
|
||||
if desired_locale is not specified then the default locale is used.
|
||||
|
||||
@ -112,14 +112,14 @@ Available Languages
|
||||
|
||||
Only the languages that have translations provided are available for
|
||||
translation. To determine which languages are available the
|
||||
:func:`~oslo.i18n.gettextutils.get_available_languages` is provided. Since different languages
|
||||
:func:`~oslo.i18n.get_available_languages` is provided. Since different languages
|
||||
can be installed for each domain, the domain must be specified.
|
||||
|
||||
::
|
||||
|
||||
from oslo.i18n import gettextutils
|
||||
from oslo import i18n
|
||||
|
||||
avail_lang = gettextutils.get_available_languages('myapp')
|
||||
avail_lang = i18n.get_available_languages('myapp')
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from ._factory import *
|
||||
from ._gettextutils import *
|
||||
from ._lazy import *
|
||||
from ._translate import *
|
@ -26,6 +26,11 @@ from oslo.i18n import _locale
|
||||
from oslo.i18n import _message
|
||||
|
||||
|
||||
__all__ = [
|
||||
'TranslatorFactory',
|
||||
]
|
||||
|
||||
|
||||
class TranslatorFactory(object):
|
||||
"Create translator functions"
|
||||
|
||||
|
@ -24,11 +24,13 @@ import os
|
||||
from babel import localedata
|
||||
import six
|
||||
|
||||
# Expose a few internal pieces as part of our public API.
|
||||
from oslo.i18n._factory import TranslatorFactory # noqa
|
||||
from oslo.i18n._lazy import enable_lazy # noqa
|
||||
from oslo.i18n import _factory
|
||||
from oslo.i18n import _locale
|
||||
from oslo.i18n._translate import translate # noqa
|
||||
|
||||
__all__ = [
|
||||
'install',
|
||||
'get_available_languages',
|
||||
]
|
||||
|
||||
|
||||
def install(domain):
|
||||
@ -50,7 +52,7 @@ def install(domain):
|
||||
any available locale.
|
||||
"""
|
||||
from six import moves
|
||||
tf = TranslatorFactory(domain)
|
||||
tf = _factory.TranslatorFactory(domain)
|
||||
moves.builtins.__dict__['_'] = tf.primary
|
||||
|
||||
|
@ -14,6 +14,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
__all__ = [
|
||||
'enable_lazy',
|
||||
]
|
||||
|
||||
USE_LAZY = False
|
||||
|
||||
|
||||
|
@ -16,6 +16,10 @@
|
||||
|
||||
import six
|
||||
|
||||
__all__ = [
|
||||
'translate',
|
||||
]
|
||||
|
||||
|
||||
def translate(obj, desired_locale=None):
|
||||
"""Gets the translated unicode representation of the given object.
|
||||
|
@ -18,9 +18,9 @@ import mock
|
||||
from oslotest import base as test_base
|
||||
import six
|
||||
|
||||
from oslo.i18n import _factory
|
||||
from oslo.i18n import _lazy
|
||||
from oslo.i18n import _message
|
||||
from oslo.i18n import gettextutils
|
||||
|
||||
|
||||
class TranslatorFactoryTest(test_base.BaseTestCase):
|
||||
@ -36,56 +36,56 @@ class TranslatorFactoryTest(test_base.BaseTestCase):
|
||||
super(TranslatorFactoryTest, self).tearDown()
|
||||
|
||||
def test_lazy(self):
|
||||
gettextutils.enable_lazy(True)
|
||||
_lazy.enable_lazy(True)
|
||||
with mock.patch.object(_message, 'Message') as msg:
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
tf = _factory.TranslatorFactory('domain')
|
||||
tf.primary('some text')
|
||||
msg.assert_called_with('some text', domain='domain')
|
||||
|
||||
def test_not_lazy(self):
|
||||
gettextutils.enable_lazy(False)
|
||||
_lazy.enable_lazy(False)
|
||||
with mock.patch.object(_message, 'Message') as msg:
|
||||
msg.side_effect = AssertionError('should not use Message')
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
tf = _factory.TranslatorFactory('domain')
|
||||
tf.primary('some text')
|
||||
|
||||
def test_change_lazy(self):
|
||||
gettextutils.enable_lazy(True)
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
_lazy.enable_lazy(True)
|
||||
tf = _factory.TranslatorFactory('domain')
|
||||
r = tf.primary('some text')
|
||||
self.assertIsInstance(r, _message.Message)
|
||||
gettextutils.enable_lazy(False)
|
||||
_lazy.enable_lazy(False)
|
||||
r = tf.primary('some text')
|
||||
# Python 2.6 doesn't have assertNotIsInstance().
|
||||
self.assertFalse(isinstance(r, _message.Message))
|
||||
|
||||
def test_py2(self):
|
||||
gettextutils.enable_lazy(False)
|
||||
_lazy.enable_lazy(False)
|
||||
with mock.patch.object(six, 'PY3', False):
|
||||
with mock.patch('gettext.translation') as translation:
|
||||
trans = mock.Mock()
|
||||
translation.return_value = trans
|
||||
trans.gettext.side_effect = AssertionError(
|
||||
'should have called ugettext')
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
tf = _factory.TranslatorFactory('domain')
|
||||
tf.primary('some text')
|
||||
trans.ugettext.assert_called_with('some text')
|
||||
|
||||
def test_py3(self):
|
||||
gettextutils.enable_lazy(False)
|
||||
_lazy.enable_lazy(False)
|
||||
with mock.patch.object(six, 'PY3', True):
|
||||
with mock.patch('gettext.translation') as translation:
|
||||
trans = mock.Mock()
|
||||
translation.return_value = trans
|
||||
trans.ugettext.side_effect = AssertionError(
|
||||
'should have called gettext')
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
tf = _factory.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,
|
||||
with mock.patch.object(_factory.TranslatorFactory,
|
||||
'_make_translation_func') as mtf:
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
tf = _factory.TranslatorFactory('domain')
|
||||
tf._make_log_translation_func('mylevel')
|
||||
mtf.assert_called_with('domain-log-mylevel')
|
||||
|
@ -23,9 +23,10 @@ from oslotest import base as test_base
|
||||
from oslotest import moxstubout
|
||||
import six
|
||||
|
||||
from oslo.i18n import _factory
|
||||
from oslo.i18n import _gettextutils
|
||||
from oslo.i18n import _lazy
|
||||
from oslo.i18n import _message
|
||||
from oslo.i18n import gettextutils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -40,7 +41,7 @@ class GettextTest(test_base.BaseTestCase):
|
||||
self.mox = moxfixture.mox
|
||||
# remember so we can reset to it later in case it changes
|
||||
self._USE_LAZY = _lazy.USE_LAZY
|
||||
self.t = gettextutils.TranslatorFactory('oslo.i18n.test')
|
||||
self.t = _factory.TranslatorFactory('oslo.i18n.test')
|
||||
|
||||
def tearDown(self):
|
||||
# reset to value before test
|
||||
@ -50,14 +51,14 @@ class GettextTest(test_base.BaseTestCase):
|
||||
def test_gettext_does_not_blow_up(self):
|
||||
LOG.info(self.t.primary('test'))
|
||||
|
||||
def test_gettextutils_install(self):
|
||||
gettextutils.install('blaa')
|
||||
gettextutils.enable_lazy(False)
|
||||
def test__gettextutils_install(self):
|
||||
_gettextutils.install('blaa')
|
||||
_lazy.enable_lazy(False)
|
||||
self.assertTrue(isinstance(self.t.primary('A String'),
|
||||
six.text_type))
|
||||
|
||||
gettextutils.install('blaa')
|
||||
gettextutils.enable_lazy(True)
|
||||
_gettextutils.install('blaa')
|
||||
_lazy.enable_lazy(True)
|
||||
self.assertTrue(isinstance(self.t.primary('A Message'),
|
||||
_message.Message))
|
||||
|
||||
@ -65,7 +66,7 @@ class GettextTest(test_base.BaseTestCase):
|
||||
with mock.patch('os.environ.get') as environ_get:
|
||||
with mock.patch('gettext.install'):
|
||||
environ_get.return_value = '/foo/bar'
|
||||
gettextutils.install('blaa')
|
||||
_gettextutils.install('blaa')
|
||||
environ_get.assert_calls([mock.call('BLAA_LOCALEDIR')])
|
||||
|
||||
def test_gettext_install_updates_builtins(self):
|
||||
@ -74,14 +75,15 @@ class GettextTest(test_base.BaseTestCase):
|
||||
environ_get.return_value = '/foo/bar'
|
||||
if '_' in six.moves.builtins.__dict__:
|
||||
del six.moves.builtins.__dict__['_']
|
||||
gettextutils.install('blaa')
|
||||
_gettextutils.install('blaa')
|
||||
self.assertIn('_', six.moves.builtins.__dict__)
|
||||
|
||||
def test_get_available_languages(self):
|
||||
# All the available languages for which locale data is available
|
||||
def _mock_locale_identifiers():
|
||||
# 'zh', 'zh_Hant'. 'zh_Hant_HK', 'fil' all have aliases missing
|
||||
# from babel but we add them in gettextutils, we test that here too
|
||||
# 'zh', 'zh_Hant'. 'zh_Hant_HK', 'fil' all have aliases
|
||||
# missing from babel but we add them in _gettextutils, we
|
||||
# test that here too
|
||||
return ['zh', 'es', 'nl', 'fr', 'zh_Hant', 'zh_Hant_HK', 'fil']
|
||||
|
||||
self.stubs.Set(localedata,
|
||||
@ -102,8 +104,8 @@ class GettextTest(test_base.BaseTestCase):
|
||||
|
||||
# en_US should always be available no matter the domain
|
||||
# and it should also always be the first element since order matters
|
||||
domain_1_languages = gettextutils.get_available_languages('domain_1')
|
||||
domain_2_languages = gettextutils.get_available_languages('domain_2')
|
||||
domain_1_languages = _gettextutils.get_available_languages('domain_1')
|
||||
domain_2_languages = _gettextutils.get_available_languages('domain_2')
|
||||
self.assertEqual('en_US', domain_1_languages[0])
|
||||
self.assertEqual('en_US', domain_2_languages[0])
|
||||
# The domain languages should be included after en_US with
|
||||
@ -118,8 +120,8 @@ class GettextTest(test_base.BaseTestCase):
|
||||
self.assertIn('fr', domain_2_languages)
|
||||
self.assertIn('zh_Hant', domain_2_languages)
|
||||
self.assertIn('zh_TW', domain_2_languages)
|
||||
self.assertEqual(2, len(gettextutils._AVAILABLE_LANGUAGES))
|
||||
self.assertEqual(2, len(_gettextutils._AVAILABLE_LANGUAGES))
|
||||
# Now test an unknown domain, only en_US should be included
|
||||
unknown_domain_languages = gettextutils.get_available_languages('huh')
|
||||
unknown_domain_languages = _gettextutils.get_available_languages('huh')
|
||||
self.assertEqual(1, len(unknown_domain_languages))
|
||||
self.assertIn('en_US', unknown_domain_languages)
|
||||
|
@ -17,7 +17,6 @@
|
||||
from oslotest import base as test_base
|
||||
|
||||
from oslo.i18n import _lazy
|
||||
from oslo.i18n import gettextutils
|
||||
|
||||
|
||||
class LazyTest(test_base.BaseTestCase):
|
||||
@ -32,10 +31,10 @@ class LazyTest(test_base.BaseTestCase):
|
||||
|
||||
def test_enable_lazy(self):
|
||||
_lazy.USE_LAZY = False
|
||||
gettextutils.enable_lazy()
|
||||
_lazy.enable_lazy()
|
||||
self.assertTrue(_lazy.USE_LAZY)
|
||||
|
||||
def test_disable_lazy(self):
|
||||
_lazy.USE_LAZY = True
|
||||
gettextutils.enable_lazy(False)
|
||||
_lazy.enable_lazy(False)
|
||||
self.assertFalse(_lazy.USE_LAZY)
|
||||
|
@ -17,7 +17,7 @@
|
||||
import mock
|
||||
from oslotest import base as test_base
|
||||
|
||||
from oslo.i18n import gettextutils
|
||||
from oslo.i18n import _factory
|
||||
|
||||
|
||||
class LogLevelTranslationsTest(test_base.BaseTestCase):
|
||||
@ -35,8 +35,8 @@ class LogLevelTranslationsTest(test_base.BaseTestCase):
|
||||
self._test('critical')
|
||||
|
||||
def _test(self, level):
|
||||
with mock.patch.object(gettextutils.TranslatorFactory,
|
||||
with mock.patch.object(_factory.TranslatorFactory,
|
||||
'_make_translation_func') as mtf:
|
||||
tf = gettextutils.TranslatorFactory('domain')
|
||||
tf = _factory.TranslatorFactory('domain')
|
||||
getattr(tf, 'log_%s' % level)
|
||||
mtf.assert_called_with('domain-log-%s' % level)
|
||||
|
44
tests/test_public_api.py
Normal file
44
tests/test_public_api.py
Normal file
@ -0,0 +1,44 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""A few tests that use the public API to ensure the imports work.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
|
||||
from oslo import i18n
|
||||
from oslo.i18n import _lazy
|
||||
|
||||
|
||||
class PublicAPITest(unittest.TestCase):
|
||||
|
||||
def test_create_factory(self):
|
||||
i18n.TranslatorFactory('domain')
|
||||
|
||||
def test_install(self):
|
||||
with mock.patch('six.moves.builtins'):
|
||||
i18n.install('domain')
|
||||
|
||||
def test_get_available_languages(self):
|
||||
i18n.get_available_languages('domains')
|
||||
|
||||
def test_toggle_lazy(self):
|
||||
original = _lazy.USE_LAZY
|
||||
try:
|
||||
i18n.enable_lazy(True)
|
||||
i18n.enable_lazy(False)
|
||||
finally:
|
||||
i18n.enable_lazy(original)
|
||||
|
||||
def test_translate(self):
|
||||
i18n.translate(u'string')
|
2
tox.ini
2
tox.ini
@ -35,7 +35,7 @@ commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
show-source = True
|
||||
ignore = E123,E125,H803
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,__init__.py
|
||||
|
||||
[hacking]
|
||||
import_exceptions =
|
||||
|
Loading…
x
Reference in New Issue
Block a user