From cca6876a3c72f88be32dc7df347ad4e8729497b9 Mon Sep 17 00:00:00 2001
From: Nick Parlante <nick.parlante@cs.stanford.edu>
Date: Tue, 3 Sep 2013 16:39:43 -0700
Subject: [PATCH] Targeted string customization in the LMS UI

Add the text_customization dict in advanced settings, which contains
customizations checked in specific spots. Here it is used to enable
the customization of the "Check" and "Final Check" button titles
under the keys custom_check and custom_final_check.
---
 CHANGELOG.rst                                 |  4 +++
 common/lib/xmodule/xmodule/capa_module.py     | 32 +++++++++++++++----
 .../xmodule/modulestore/inheritance.py        |  7 +++-
 .../xmodule/xmodule/tests/test_capa_module.py | 18 ++++++++++-
 4 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 42ea098066d..b0a4c81eb50 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,6 +8,10 @@ the top.  Include a label indicating the component affected.
 
 LMS: Fix issue with CourseMode expiration dates
 
+CMS: Add text_customization Dict to advanced settings which can support
+string customization at particular spots in the UI.  At first just customizing
+the Check/Final Check buttons with keys: custom_check and custom_final_check
+
 LMS: Add PaidCourseRegistration mode, where payment is required before course
 registration.
 
diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py
index 88b911a745d..03a4ad6365f 100644
--- a/common/lib/xmodule/xmodule/capa_module.py
+++ b/common/lib/xmodule/xmodule/capa_module.py
@@ -152,6 +152,12 @@ class CapaFields(object):
         help="Source code for LaTeX and Word problems. This feature is not well-supported.",
         scope=Scope.settings
     )
+    text_customization = Dict(
+        help="String customization substitutions for particular locations",
+        scope=Scope.settings
+        # TODO: someday it should be possible to not duplicate this definition here
+        # and in inheritance.py
+    )
 
 
 class CapaModule(CapaFields, XModule):
@@ -342,14 +348,26 @@ class CapaModule(CapaFields, XModule):
         Determine the name for the "check" button.
 
         Usually it is just "Check", but if this is the student's
-        final attempt, change the name to "Final Check"
-        """
-        if self.max_attempts is not None:
-            final_check = (self.attempts >= self.max_attempts - 1)
+        final attempt, change the name to "Final Check".
+        The text can be customized by the text_customization setting.
+        """
+        # The logic flow is a little odd so that _('xxx') strings can be found for
+        # translation while also running _() just once for each string.
+        check = _('Check')
+        final_check = _('Final Check')
+
+        # Apply customizations if present
+        if 'custom_check' in self.text_customization:
+            check = _(self.text_customization.get('custom_check'))
+        if 'custom_final_check' in self.text_customization:
+            final_check = _(self.text_customization.get('custom_final_check'))
+        # TODO: need a way to get the customized words into the list of
+        # words to be translated
+
+        if self.max_attempts is not None and self.attempts >= self.max_attempts - 1:
+            return final_check
         else:
-            final_check = False
-
-        return _("Final Check") if final_check else _("Check")
+            return check
 
     def should_show_check_button(self):
         """
diff --git a/common/lib/xmodule/xmodule/modulestore/inheritance.py b/common/lib/xmodule/xmodule/modulestore/inheritance.py
index d68c121b96b..a518034e610 100644
--- a/common/lib/xmodule/xmodule/modulestore/inheritance.py
+++ b/common/lib/xmodule/xmodule/modulestore/inheritance.py
@@ -1,7 +1,7 @@
 from datetime import datetime
 from pytz import UTC
 
-from xblock.fields import Scope, Boolean, String, Float, XBlockMixin
+from xblock.fields import Scope, Boolean, String, Float, XBlockMixin, Dict
 from xmodule.fields import Date, Timedelta
 from xblock.runtime import KeyValueStore
 
@@ -43,6 +43,10 @@ class InheritanceMixin(XBlockMixin):
         scope=Scope.settings
     )
     static_asset_path = String(help="Path to use for static assets - overrides Studio c4x://", scope=Scope.settings, default='')
+    text_customization = Dict(
+        help="String customization substitutions for particular locations",
+        scope=Scope.settings
+    )
 
 
 def compute_inherited_metadata(descriptor):
@@ -87,6 +91,7 @@ def own_metadata(module):
     """
     return module.get_explicitly_set_fields_by_scope(Scope.settings)
 
+
 class InheritanceKeyValueStore(KeyValueStore):
     """
     Common superclass for kvs's which know about inheritance of settings. Offers simple
diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py
index c47cfc2ca85..7cbdc130ae4 100644
--- a/common/lib/xmodule/xmodule/tests/test_capa_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py
@@ -77,7 +77,8 @@ class CapaFactory(object):
                attempts=None,
                problem_state=None,
                correct=False,
-               done=None
+               done=None,
+               text_customization=None
                ):
         """
         All parameters are optional, and are added to the created problem if specified.
@@ -113,6 +114,8 @@ class CapaFactory(object):
             field_data['rerandomize'] = rerandomize
         if done is not None:
             field_data['done'] = done
+        if text_customization is not None:
+            field_data['text_customization'] = text_customization
 
         descriptor = Mock(weight="1")
         if problem_state is not None:
@@ -837,6 +840,19 @@ class CapaModuleTest(unittest.TestCase):
         module = CapaFactory.create(attempts=0)
         self.assertEqual(module.check_button_name(), "Check")
 
+    def test_check_button_name_customization(self):
+        module = CapaFactory.create(attempts=1,
+                                    max_attempts=10,
+                                    text_customization={"custom_check": "Submit", "custom_final_check": "Final Submit"}
+                                    )
+        self.assertEqual(module.check_button_name(), "Submit")
+
+        module = CapaFactory.create(attempts=9,
+                                    max_attempts=10,
+                                    text_customization={"custom_check": "Submit", "custom_final_check": "Final Submit"}
+                                    )
+        self.assertEqual(module.check_button_name(), "Final Submit")
+
     def test_should_show_check_button(self):
 
         attempts = random.randint(1, 10)
-- 
GitLab