# Copyright 2012 Red Hat, Inc. # Copyright 2013 IBM Corp. # All Rights Reserved. # # 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. import gettext import logging from unittest import mock from babel import localedata from oslotest import base as test_base import six from oslo_i18n import _factory from oslo_i18n import _gettextutils from oslo_i18n import _lazy from oslo_i18n import _message LOG = logging.getLogger(__name__) class GettextTest(test_base.BaseTestCase): def setUp(self): super(GettextTest, self).setUp() # remember so we can reset to it later in case it changes self._USE_LAZY = _lazy.USE_LAZY self.t = _factory.TranslatorFactory('oslo_i18n.test') def tearDown(self): # reset to value before test _lazy.USE_LAZY = self._USE_LAZY super(GettextTest, self).tearDown() def test_gettext_does_not_blow_up(self): LOG.info(self.t.primary('test')) 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') _lazy.enable_lazy(True) self.assertTrue(isinstance(self.t.primary('A Message'), _message.Message)) def test_gettext_install_looks_up_localedir(self): with mock.patch('os.environ.get') as environ_get: with mock.patch('gettext.install'): environ_get.return_value = '/foo/bar' _gettextutils.install('blaa') environ_get.assert_has_calls([mock.call('BLAA_LOCALEDIR')]) def test_gettext_install_updates_builtins(self): with mock.patch('os.environ.get') as environ_get: with mock.patch('gettext.install'): environ_get.return_value = '/foo/bar' if '_' in six.moves.builtins.__dict__: del six.moves.builtins.__dict__['_'] _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 return ['zh', 'es', 'nl', 'fr', 'zh_Hant', 'zh_Hant_HK', 'fil'] mock_patcher = mock.patch.object(localedata, 'list' if hasattr(localedata, 'list') else 'locale_identifiers', _mock_locale_identifiers) mock_patcher.start() self.addCleanup(mock_patcher.stop) # Only the languages available for a specific translation domain def _mock_gettext_find(domain, localedir=None, languages=None, all=0): languages = languages or [] if domain == 'domain_1': return 'translation-file' if any(x in ['zh', 'es', 'fil'] for x in languages) else None elif domain == 'domain_2': return 'translation-file' if any(x in ['fr', 'zh_Hant'] for x in languages) else None return None mock_patcher = mock.patch.object(gettext, 'find', _mock_gettext_find) mock_patcher.start() self.addCleanup(mock_patcher.stop) # Ensure that no domains are cached _gettextutils._AVAILABLE_LANGUAGES = {} # 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') 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 # with their respective aliases when it applies self.assertEqual(6, len(domain_1_languages)) self.assertIn('zh', domain_1_languages) self.assertIn('zh_CN', domain_1_languages) self.assertIn('es', domain_1_languages) self.assertIn('fil', domain_1_languages) self.assertIn('tl_PH', domain_1_languages) self.assertEqual(4, len(domain_2_languages)) 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)) # Now test an unknown domain, only en_US should be included unknown_domain_languages = _gettextutils.get_available_languages('huh') self.assertEqual(1, len(unknown_domain_languages)) self.assertIn('en_US', unknown_domain_languages) def test_cached_find(self): domain = 'my-unique-domain' key = (domain, None, None, 0) self.assertNotIn(key, _gettextutils._FIND_CACHE) gettext.find(domain) self.assertIn(key, _gettextutils._FIND_CACHE) _gettextutils._FIND_CACHE[key] = "spoof result" self.assertEqual("spoof result", gettext.find(domain)) _gettextutils._FIND_CACHE.pop(key)