We had a set of i18n tests that testing basic english is working on a page that's going away. It's not necessary. And then we have a skipped test that tests i18n. It would be good to have actual i18n tests and there are some other ones in this file at the block level that do test i18n but since this test isn't actually testing anything novel there's no need to keep it.
165 lines
6.9 KiB
Python
165 lines
6.9 KiB
Python
"""
|
|
Tests for validate Internationalization and XBlock i18n service.
|
|
"""
|
|
import gettext
|
|
from unittest import mock
|
|
|
|
from django.utils import translation
|
|
|
|
from django.utils.translation import get_language
|
|
from xblock.core import XBlock
|
|
from xmodule.modulestore.django import XBlockI18nService
|
|
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase
|
|
from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory
|
|
from xmodule.tests.test_export import PureXBlock
|
|
|
|
from cms.djangoapps.contentstore.views.preview import _prepare_runtime_for_preview
|
|
|
|
|
|
class FakeTranslations(XBlockI18nService):
|
|
"""A test GNUTranslations class that takes a map of msg -> translations."""
|
|
|
|
def __init__(self, translations): # pylint: disable=super-init-not-called
|
|
self.translations = translations
|
|
|
|
def ugettext(self, msgid):
|
|
"""
|
|
Mock override for ugettext translation operation
|
|
"""
|
|
return self.translations.get(msgid, msgid)
|
|
|
|
gettext = ugettext
|
|
|
|
@staticmethod
|
|
def translator(locales_map): # pylint: disable=method-hidden
|
|
"""Build mock translator for the given locales.
|
|
Returns a mock gettext.translation function that uses
|
|
individual TestTranslations to translate in the given locales.
|
|
:param locales_map: A map from locale name to a translations map.
|
|
{
|
|
'es': {'Hi': 'Hola', 'Bye': 'Adios'},
|
|
'zh': {'Hi': 'Ni Hao', 'Bye': 'Zaijian'}
|
|
}
|
|
"""
|
|
def _translation(domain, localedir=None, languages=None): # pylint: disable=unused-argument
|
|
"""
|
|
return gettext.translation for given language
|
|
"""
|
|
if languages:
|
|
language = languages[0]
|
|
if language in locales_map:
|
|
return FakeTranslations(locales_map[language])
|
|
return gettext.NullTranslations()
|
|
return _translation
|
|
|
|
|
|
class TestXBlockI18nService(ModuleStoreTestCase):
|
|
""" Test XBlockI18nService """
|
|
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
|
|
|
@XBlock.register_temp_plugin(PureXBlock, 'pure')
|
|
def setUp(self):
|
|
""" Setting up tests """
|
|
super().setUp()
|
|
self.test_language = 'dummy language'
|
|
self.request = mock.Mock()
|
|
self.course = CourseFactory.create()
|
|
self.block = BlockFactory(category="pure", parent=self.course)
|
|
_prepare_runtime_for_preview(self.request, self.block)
|
|
self.addCleanup(translation.deactivate)
|
|
|
|
def get_block_i18n_service(self, block):
|
|
"""
|
|
return the block i18n service.
|
|
"""
|
|
i18n_service = self.block.runtime.service(block, 'i18n')
|
|
self.assertIsNotNone(i18n_service)
|
|
self.assertIsInstance(i18n_service, XBlockI18nService)
|
|
return i18n_service
|
|
|
|
def test_django_service_translation_works(self):
|
|
"""
|
|
Test django translation service works fine.
|
|
"""
|
|
|
|
class wrap_ugettext_with_xyz: # pylint: disable=invalid-name
|
|
"""
|
|
A context manager function that just adds 'XYZ ' to the front
|
|
of all strings of the module ugettext function.
|
|
"""
|
|
|
|
def __init__(self, module):
|
|
self.module = module
|
|
self.old_ugettext = module.gettext
|
|
|
|
def __enter__(self):
|
|
def new_ugettext(*args, **kwargs):
|
|
""" custom function """
|
|
output = self.old_ugettext(*args, **kwargs)
|
|
return "XYZ " + output
|
|
self.module.ugettext = new_ugettext
|
|
self.module.gettext = new_ugettext
|
|
|
|
def __exit__(self, _type, _value, _traceback):
|
|
self.module.ugettext = self.old_ugettext
|
|
self.module.gettext = self.old_ugettext
|
|
|
|
i18n_service = self.get_block_i18n_service(self.block)
|
|
|
|
# Activate french, so that if the fr files haven't been loaded, they will be loaded now.
|
|
with translation.override("fr"):
|
|
french_translation = translation.trans_real._active.value # pylint: disable=protected-access
|
|
|
|
# wrap the ugettext functions so that 'XYZ ' will prefix each translation
|
|
with wrap_ugettext_with_xyz(french_translation):
|
|
self.assertEqual(i18n_service.ugettext(self.test_language), 'XYZ dummy language')
|
|
|
|
# Check that the old ugettext has been put back into place
|
|
self.assertEqual(i18n_service.ugettext(self.test_language), 'dummy language')
|
|
|
|
@mock.patch('django.utils.translation.gettext', mock.Mock(return_value='XYZ-TEST-LANGUAGE'))
|
|
def test_django_translator_in_use_with_empty_block(self):
|
|
"""
|
|
Test: Django default translator should in use if we have an empty block
|
|
"""
|
|
i18n_service = XBlockI18nService(None)
|
|
self.assertEqual(i18n_service.ugettext(self.test_language), 'XYZ-TEST-LANGUAGE')
|
|
|
|
@mock.patch('django.utils.translation.gettext', mock.Mock(return_value='XYZ-TEST-LANGUAGE'))
|
|
def test_message_catalog_translations(self):
|
|
"""
|
|
Test: Message catalog from FakeTranslation should return required translations.
|
|
"""
|
|
_translator = FakeTranslations.translator(
|
|
{
|
|
'es': {'Hello': 'es-hello-world'},
|
|
'fr': {'Hello': 'fr-hello-world'},
|
|
},
|
|
)
|
|
localedir = '/translations'
|
|
translation.activate("es")
|
|
with mock.patch('gettext.translation', return_value=_translator(domain='text', localedir=localedir,
|
|
languages=[get_language()])):
|
|
i18n_service = self.get_block_i18n_service(self.block)
|
|
self.assertEqual(i18n_service.ugettext('Hello'), 'es-hello-world')
|
|
|
|
translation.activate("ar")
|
|
with mock.patch('gettext.translation', return_value=_translator(domain='text', localedir=localedir,
|
|
languages=[get_language()])):
|
|
i18n_service = self.get_block_i18n_service(self.block)
|
|
self.assertEqual(i18n_service.gettext('Hello'), 'Hello')
|
|
self.assertNotEqual(i18n_service.gettext('Hello'), 'fr-hello-world')
|
|
self.assertNotEqual(i18n_service.gettext('Hello'), 'es-hello-world')
|
|
|
|
translation.activate("fr")
|
|
with mock.patch('gettext.translation', return_value=_translator(domain='text', localedir=localedir,
|
|
languages=[get_language()])):
|
|
i18n_service = self.get_block_i18n_service(self.block)
|
|
self.assertEqual(i18n_service.ugettext('Hello'), 'fr-hello-world')
|
|
|
|
def test_i18n_service_callable(self):
|
|
"""
|
|
Test: i18n service should be callable in studio.
|
|
"""
|
|
self.assertTrue(callable(self.block.runtime._services.get('i18n'))) # pylint: disable=protected-access
|