From 3739cc4549df5bdbbad9e6d730457f118c487540 Mon Sep 17 00:00:00 2001 From: Omar Al-Ithawi Date: Wed, 5 Apr 2017 14:29:43 +0300 Subject: [PATCH] Make the course lang override platform lang --- lms/djangoapps/bulk_email/admin.py | 1 + lms/djangoapps/bulk_email/tasks.py | 13 +++-- lms/djangoapps/bulk_email/tests/test_email.py | 53 +++++++++++++++++-- lms/djangoapps/bulk_email/tests/test_tasks.py | 1 + 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lms/djangoapps/bulk_email/admin.py b/lms/djangoapps/bulk_email/admin.py index e42f7f535f..ac6937a7da 100644 --- a/lms/djangoapps/bulk_email/admin.py +++ b/lms/djangoapps/bulk_email/admin.py @@ -37,6 +37,7 @@ Other tags that may be used (surrounded by one curly brace on each side): {platform_name} : the name of the platform {course_title} : the name of the course {course_root} : the URL path to the root of the course +{course_language} : the course language. The default is None. {course_url} : the course's full URL {email} : the user's email address {account_settings_url} : URL at which users can change account preferences diff --git a/lms/djangoapps/bulk_email/tasks.py b/lms/djangoapps/bulk_email/tasks.py index 6a8f788f8c..f64da3e29c 100644 --- a/lms/djangoapps/bulk_email/tasks.py +++ b/lms/djangoapps/bulk_email/tasks.py @@ -110,6 +110,7 @@ def _get_course_email_context(course): email_context = { 'course_title': course_title, 'course_root': course_root, + 'course_language': course.language, 'course_url': course_url, 'course_image_url': image_url, 'course_end_date': course_end_date, @@ -351,7 +352,7 @@ def _filter_optouts_from_recipients(to_list, course_id): return to_list, num_optout -def _get_source_address(course_id, course_title, truncate=True): +def _get_source_address(course_id, course_title, course_language, truncate=True): """ Calculates an email address to be used as the 'from-address' for sent emails. @@ -374,7 +375,12 @@ def _get_source_address(course_id, course_title, truncate=True): # character appears. course_name = re.sub(r"[^\w.-]", '_', course_id.course) - with override_language(settings.LANGUAGE_CODE): + # Use course.language if present + language = course_language if course_language else settings.LANGUAGE_CODE + with override_language(language): + # RFC2821 requires the byte order of the email address to be the name then email + # e.g. "John Doe " + # Although the display will be flipped in RTL languages, the byte order is still the same. from_addr_format = u'{name} {email}'.format( # Translators: Bulk email from address e.g. ("Physics 101" Course Staff) name=_('"{course_title}" Course Staff'), @@ -481,10 +487,11 @@ def _send_course_email(entry_id, email_id, to_list, global_email_context, subtas subtask_status.increment(skipped=num_optout) course_title = global_email_context['course_title'] + course_language = global_email_context['course_language'] # use the email from address in the CourseEmail, if it is present, otherwise compute it from_addr = course_email.from_addr if course_email.from_addr else \ - _get_source_address(course_email.course_id, course_title) + _get_source_address(course_email.course_id, course_title, course_language) # use the CourseEmailTemplate that was associated with the CourseEmail course_email_template = course_email.get_template() diff --git a/lms/djangoapps/bulk_email/tests/test_email.py b/lms/djangoapps/bulk_email/tests/test_email.py index 9c1fa2d543..6d2f5680b1 100644 --- a/lms/djangoapps/bulk_email/tests/test_email.py +++ b/lms/djangoapps/bulk_email/tests/test_email.py @@ -8,6 +8,7 @@ from mock import patch, Mock from nose.plugins.attrib import attr import os from unittest import skipIf +import ddt from django.conf import settings from django.core import mail @@ -133,9 +134,10 @@ class EmailSendFromDashboardTestCase(SharedModuleStoreTestCase): BulkEmailFlag.objects.all().delete() -@attr(shard=1) -@patch.dict(settings.FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True, 'REQUIRE_COURSE_EMAIL_AUTH': False}) -class TestLocalizedFromAddress(EmailSendFromDashboardTestCase): +class SendEmailWithMockedUgettextMixin(object): + """ + Mock uggetext for EmailSendFromDashboardTestCase. + """ def send_email(self): """ Sends a dummy email to check the `from_addr` translation. @@ -165,11 +167,20 @@ class TestLocalizedFromAddress(EmailSendFromDashboardTestCase): return mail.outbox[0] + +@attr(shard=1) +@patch.dict(settings.FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True, 'REQUIRE_COURSE_EMAIL_AUTH': False}) +@ddt.ddt +class LocalizedFromAddressPlatformLangTestCase(SendEmailWithMockedUgettextMixin, EmailSendFromDashboardTestCase): + """ + Tests to ensure that the bulk email has the "From" address localized according to LANGUAGE_CODE. + """ @override_settings(LANGUAGE_CODE='en') def test_english_platform(self): """ Ensures that the source-code language (English) works well. """ + self.assertIsNone(self.course.language) # Sanity check message = self.send_email() self.assertRegexpMatches(message.from_email, '.*Course Staff.*') @@ -178,10 +189,44 @@ class TestLocalizedFromAddress(EmailSendFromDashboardTestCase): """ Tests the fake Esperanto language to ensure proper gettext calls. """ + self.assertIsNone(self.course.language) # Sanity check message = self.send_email() self.assertRegexpMatches(message.from_email, '@EO .* Course Staff@') +@attr(shard=1) +@patch.dict(settings.FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True, 'REQUIRE_COURSE_EMAIL_AUTH': False}) +@ddt.ddt +class LocalizedFromAddressCourseLangTestCase(SendEmailWithMockedUgettextMixin, EmailSendFromDashboardTestCase): + """ + Test if the bulk email "From" address uses the course.language if present instead of LANGUAGE_CODE. + + This is similiar to LocalizedFromAddressTestCase but creating a different test case to allow + changing the class-wide course object. + """ + + @classmethod + def setUpClass(cls): + """ + Creates a different course. + """ + super(LocalizedFromAddressCourseLangTestCase, cls).setUpClass() + course_title = u"ẗëṡẗ イэ" + cls.course = CourseFactory.create( + display_name=course_title, + language='ar', + default_store=ModuleStoreEnum.Type.split + ) + + @override_settings(LANGUAGE_CODE='eo') + def test_esperanto_platform_arabic_course(self): + """ + The course language should override the platform's. + """ + message = self.send_email() + self.assertRegexpMatches(message.from_email, '@AR .* Course Staff@') + + @attr(shard=1) @patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True)) class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase): @@ -444,7 +489,7 @@ class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase) instructor = InstructorFactory(course_key=course.id) unexpected_from_addr = _get_source_address( - course.id, course.display_name, truncate=False + course.id, course.display_name, course_language=None, truncate=False ) __, encoded_unexpected_from_addr = forbid_multi_line_headers( "from", unexpected_from_addr, 'utf-8' diff --git a/lms/djangoapps/bulk_email/tests/test_tasks.py b/lms/djangoapps/bulk_email/tests/test_tasks.py index c5eca9edd8..f01d85eb33 100644 --- a/lms/djangoapps/bulk_email/tests/test_tasks.py +++ b/lms/djangoapps/bulk_email/tests/test_tasks.py @@ -440,6 +440,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase): result = _get_course_email_context(self.course) self.assertIn('course_title', result) self.assertIn('course_root', result) + self.assertIn('course_language', result) self.assertIn('course_url', result) self.assertIn('course_image_url', result) self.assertIn('course_end_date', result)