Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asadiqbal08-xblock translations initial tests #11628

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions cms/djangoapps/contentstore/tests/test_i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,131 @@

from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from contentstore.tests.utils import AjaxEnabledTestClient
from xmodule.modulestore.django import ModuleI18nService
from django.utils import translation
from django.utils.translation import get_language
from django.conf import settings
import mock
import gettext


class FakeTranslations(ModuleI18nService):
"""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):
return self.translations.get(msgid, msgid)

@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 TestModuleI18nService(ModuleStoreTestCase):
""" Test ModuleI18nService """

xblock_name = 'dummy_block'

def setUp(self):
""" Setting up tests """
super(TestModuleI18nService, self).setUp()
self.test_language = 'dummy language'
self.xblock_mock = mock.Mock()
self.xblock_mock.unmixed_class.__name__ = self.xblock_name
self.i18n_service = ModuleI18nService(self.xblock_mock)
self.addCleanup(translation.activate, settings.LANGUAGE_CODE)

def test_django_service_translation_works(self):
"""
Test django translation service works fine.
"""

def wrap_with_xyz(func):
"""
A decorator function that just adds 'XYZ ' to the front of all strings
"""
def new_func(*args, **kwargs):
""" custom function """
output = func(*args, **kwargs)
return "XYZ " + output
return new_func

old_lang = translation.get_language()

# Activate french, so that if the fr files haven't been loaded, they will be loaded now.
translation.activate("fr")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the test is going to change global state like the current language, then you need an addCleanup in setUp that will restore it. Setting it back inside the test isn't enough because the test won't complete if it fails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

french_translation = translation.trans_real._active.value # pylint: disable=protected-access

# wrap the ugettext functions so that 'TEST ' will prefix each translation
french_translation.ugettext = wrap_with_xyz(french_translation.ugettext)
self.assertEqual(self.i18n_service.ugettext(self.test_language), 'XYZ dummy language')

# Turn back on our old translations
translation.activate(old_lang)
del old_lang
self.assertEqual(self.i18n_service.ugettext(self.test_language), 'dummy language')

@mock.patch('django.utils.translation.ugettext', 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
"""
self.assertEqual(ModuleI18nService(block=None).ugettext(self.test_language), 'XYZ-TEST-LANGUAGE')

@mock.patch('django.utils.translation.ugettext', 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 = '/conf/locale'
translation.activate("es")
with mock.patch('gettext.translation', return_value=_translator(domain='domain', localedir=localedir,
languages=[get_language()])):
self.assertEqual(ModuleI18nService(self.xblock_mock).ugettext('Hello'), 'es-hello-world')

translation.activate("ar")
with mock.patch('gettext.translation', return_value=_translator(domain='domain', localedir=localedir,
languages=[get_language()])):
i18n_service_2 = ModuleI18nService(self.xblock_mock)
self.assertEqual(i18n_service_2.ugettext('Hello'), 'Hello')
self.assertNotEqual(i18n_service_2.ugettext('Hello'), 'fr-hello-world')
self.assertNotEqual(i18n_service_2.ugettext('Hello'), 'es-hello-world')

translation.activate("fr")
with mock.patch('gettext.translation', return_value=_translator(domain='domain', localedir=localedir,
languages=[get_language()])):
self.assertEqual(ModuleI18nService(self.xblock_mock).ugettext('Hello'), 'fr-hello-world')

# Django default translator should in use if we block is missing.
with mock.patch('gettext.translation', return_value=_translator(domain='domain', localedir=localedir,
languages=[get_language()])):
self.assertEqual(ModuleI18nService(block=None).ugettext('Hello'), 'XYZ-TEST-LANGUAGE')


class InternationalizationTest(ModuleStoreTestCase):
Expand Down
2 changes: 1 addition & 1 deletion common/lib/xmodule/xmodule/modulestore/django.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def create_modulestore_instance(
xblock_select=getattr(settings, 'XBLOCK_SELECT_FUNCTION', None),
disabled_xblock_types=disabled_xblock_types,
doc_store_config=doc_store_config,
i18n_service=i18n_service,
i18n_service=i18n_service or ModuleI18nService(),
fs_service=fs_service or xblock.reference.plugins.FSService(),
user_service=user_service or xb_user_service,
signal_handler=signal_handler or SignalHandler(class_),
Expand Down