Repository: oppia/oppia

Issue:
[CD Reduce Toil] Auto-translate/handle translation cards that only consist of digits
With the enabling of translating interactions, multiple choice questions can be translated, but for math lessons, frequently a multiple choice option will be only a digit (see below screenshot) that doesn't need to be translated. We should be handling these types of contents automatically in some way.

Additionally, it may be helpful to group all the choices together in one translation card.

<img width="797" alt="Screen Shot 2021-06-11 at 5 06 33 PM" src="https://user-images.githubusercontent.com/9004726/121748693-67039700-cad7-11eb-86bd-fecd8a7a8bec.png">



Discussion:
Just a note -- not all numbers can be systematically translated (but whole numbers should be OK). I just learned that 3.67 is 3,67 in several countries, and vice versa.
(We can probably handle those automatically too but just noting that there's a little subtlety here.)
Oh interesting, thanks! I'll make sure to address that case.

Resolving patch:
diff --git a/core/domain/state_domain.py b/core/domain/state_domain.py
--- a/core/domain/state_domain.py
+++ b/core/domain/state_domain.py
@@ -3109,9 +3109,12 @@ def _get_all_translatable_content(self):
         for ca_dict in self.interaction.customization_args.values():
             subtitled_htmls = ca_dict.get_subtitled_html()
             for subtitled_html in subtitled_htmls:
-                if subtitled_html.html != '':
+                html_string = subtitled_html.html
+                # Make sure we don't include content that only consists of
+                # numbers. See issue #13055.
+                if html_string != '' and not html_string.isnumeric():
                     content_id_to_string[subtitled_html.content_id] = (
-                        subtitled_html.html)
+                        html_string)
 
             subtitled_unicodes = ca_dict.get_subtitled_unicode()
             for subtitled_unicode in subtitled_unicodes:


Test patch:
diff --git a/core/domain/state_domain_test.py b/core/domain/state_domain_test.py
--- a/core/domain/state_domain_test.py
+++ b/core/domain/state_domain_test.py
@@ -1424,6 +1424,70 @@ def test_get_content_id_mapping_needing_translations_with_interaction_translatio
                 'ca_placeholder_0': 'Placeholder'
             })
 
+    def test_get_content_id_mapping_needing_translations_does_not_return_numeric_content(self): # pylint: disable=line-too-long
+        exploration = exp_domain.Exploration.create_default_exploration('0')
+        init_state = exploration.states[exploration.init_state_name]
+        # Set the content.
+        init_state.update_content(
+            state_domain.SubtitledHtml.from_dict({
+                'content_id': 'content',
+                'html': '<p>This is content</p>'
+            }))
+        # Set the multiple choice interaction.
+        init_state.update_interaction_id('MultipleChoiceInput')
+        state_interaction_cust_args = {
+            'showChoicesInShuffledOrder': {
+                'value': True
+            },
+            'choices': {
+                'value': [
+                    {
+                        'content_id': 'ca_choices_0',
+                        'html': '\u003cp\u003eoption 1\u003c/p\u003e'
+                    },
+                    {
+                        'content_id': 'ca_choices_1',
+                        'html': '1,000'
+                    },
+                    {
+                        'content_id': 'ca_choices_2',
+                        'html': '100'
+                    }
+                ]
+            }
+        }
+        init_state.update_interaction_customization_args(
+            state_interaction_cust_args)
+        # Set the default outcome.
+        default_outcome = state_domain.Outcome(
+            'Introduction', state_domain.SubtitledHtml(
+                'default_outcome', '<p>The default outcome.</p>'),
+            False, [], None, None
+        )
+        init_state.update_interaction_default_outcome(default_outcome)
+        # Set the translations.
+        written_translations_dict = {
+            'translations_mapping': {
+                'content': {},
+                'default_outcome': {},
+                'ca_choices_0': {},
+                'ca_choices_1': {},
+                'ca_choices_2': {}
+            }
+        }
+        written_translations = state_domain.WrittenTranslations.from_dict(
+            written_translations_dict)
+        init_state.update_written_translations(written_translations)
+
+        # Choice 2 should not be returned as its value is numeric.
+        self.assertEqual(
+            init_state.get_content_id_mapping_needing_translations('hi'), {
+                'content': '<p>This is content</p>',
+                'default_outcome': '<p>The default outcome.</p>',
+                'ca_choices_0': '\u003cp\u003eoption 1\u003c/p\u003e',
+                'ca_choices_1': '1,000',
+            })
+
     def test_add_translation_works_correctly(self):
         exploration = exp_domain.Exploration.create_default_exploration('0')
         init_state = exploration.states[exploration.init_state_name]