diff --git a/pyxform/question.py b/pyxform/question.py
index 579b7cf17..945af4bd4 100644
--- a/pyxform/question.py
+++ b/pyxform/question.py
@@ -195,11 +195,16 @@ def build_xml(self):
if self["itemset"] and isinstance(self["itemset"], basestring):
choice_filter = self.get("choice_filter")
itemset, file_extension = os.path.splitext(self["itemset"])
+ has_media = False
+
+ if choices.get(itemset):
+ has_media = bool(choices[itemset][0].get("media"))
+
if file_extension in [".csv", ".xml"]:
itemset = itemset
itemset_label_ref = "label"
else:
- if not multi_language:
+ if not multi_language and not has_media:
itemset = self["itemset"]
itemset_label_ref = "label"
else:
diff --git a/pyxform/survey.py b/pyxform/survey.py
index f4c416d01..4ec4100d9 100644
--- a/pyxform/survey.py
+++ b/pyxform/survey.py
@@ -227,12 +227,13 @@ def _generate_static_instances(list_name, choice_list):
"""
instance_element_list = []
multi_language = isinstance(choice_list[0].get("label"), dict)
+ has_media = bool(choice_list[0].get("media"))
for idx, choice in enumerate(choice_list):
choice_element_list = []
# Add a unique id to the choice element in case there is itext
# it references
- if multi_language:
- itext_id = "-".join(["static_instance", list_name, str(idx)])
+ if multi_language or has_media:
+ itext_id = "-".join([list_name, str(idx)])
choice_element_list.append(node("itextId", itext_id))
for name, value in sorted(choice.items()):
@@ -590,31 +591,41 @@ def _setup_choice_translations(name, choice_value, itext_id):
self._translations = defaultdict(dict) # pylint: disable=W0201
for element in self.iter_descendants():
- for d in element.get_translations(self.default_language):
-
- translation_path = d["path"]
- form = "long"
-
- if "guidance_hint" in d["path"]:
- translation_path = d["path"].replace("guidance_hint", "hint")
- form = "guidance"
-
- self._translations[d["lang"]][translation_path] = self._translations[
- d["lang"]
- ].get(translation_path, {})
-
- self._translations[d["lang"]][translation_path].update(
- {form: {"text": d["text"], "output_context": d["output_context"],}}
- )
+ # Skip creation of translations for choices in filtered selects
+ # The creation of these translations is done futher below in this
+ # function
+ parent = element.get("parent")
+ if parent and not parent.get("choice_filter"):
+ for d in element.get_translations(self.default_language):
+ translation_path = d["path"]
+ form = "long"
+
+ if "guidance_hint" in d["path"]:
+ translation_path = d["path"].replace("guidance_hint", "hint")
+ form = "guidance"
+
+ self._translations[d["lang"]][
+ translation_path
+ ] = self._translations[d["lang"]].get(translation_path, {})
+
+ self._translations[d["lang"]][translation_path].update(
+ {
+ form: {
+ "text": d["text"],
+ "output_context": d["output_context"],
+ }
+ }
+ )
# This code sets up translations for choices in filtered selects.
for list_name, choice_list in self.choices.items():
multi_language = isinstance(choice_list[0].get("label"), dict)
- if not multi_language:
+ has_media = bool(choice_list[0].get("media"))
+ if not multi_language and not has_media:
continue
for idx, choice in zip(range(len(choice_list)), choice_list):
for name, choice_value in choice.items():
- itext_id = "-".join(["static_instance", list_name, str(idx)])
+ itext_id = "-".join([list_name, str(idx)])
if isinstance(choice_value, dict):
_setup_choice_translations(name, choice_value, itext_id)
elif name == "label":
@@ -651,14 +662,8 @@ def _setup_media(self):
{language : {element_xpath : {media_type : media}}}
It matches the xform nesting order.
"""
- if not self._translations:
- self._translations = defaultdict(dict) # pylint: disable=W0201
-
- for survey_element in self.iter_descendants():
-
- translation_key = survey_element.get_xpath() + ":label"
- media_dict = survey_element.get("media")
+ def _set_up_media_translations(media_dict, translation_key):
# This is probably papering over a real problem, but anyway,
# in py3, sometimes if an item is on an xform with multiple
# languages and the item only has media defined in # "default"
@@ -702,6 +707,19 @@ def _setup_media(self):
translations_trans_key[media_type] = media
+ if not self._translations:
+ self._translations = defaultdict(dict) # pylint: disable=W0201
+
+ for survey_element in self.iter_descendants():
+ # Skip set up of media for choices in filtered selects.
+ # Translations for the media content should have been set up
+ # in _setup_translations
+ parent = survey_element.get("parent")
+ if parent and not parent.get("choice_filter"):
+ translation_key = survey_element.get_xpath() + ":label"
+ media_dict = survey_element.get("media")
+ _set_up_media_translations(media_dict, translation_key)
+
def itext(self):
"""
This function creates the survey's itext nodes from _translations
diff --git a/pyxform/tests_v1/test_inline_translations.py b/pyxform/tests_v1/test_inline_translations.py
index 2c4fc4727..3cd82a426 100644
--- a/pyxform/tests_v1/test_inline_translations.py
+++ b/pyxform/tests_v1/test_inline_translations.py
@@ -30,12 +30,12 @@ def test_inline_translations(self):
"",
],
model__excludes=[
- '',
- '',
- '',
- "static_instance-states-0",
- "static_instance-states-1",
- "static_instance-states-2",
+ '',
+ '',
+ '',
+ "states-0",
+ "states-1",
+ "states-2",
],
xml__contains=[''],
xml__excludes=[''],
@@ -59,12 +59,12 @@ def test_multiple_translations(self):
name="data",
id_string="some-id",
model__contains=[
- '',
- '',
- '',
- "static_instance-states-0",
- "static_instance-states-1",
- "static_instance-states-2",
+ '',
+ '',
+ '',
+ "states-0",
+ "states-1",
+ "states-2",
],
model__excludes=[
"",
@@ -74,3 +74,75 @@ def test_multiple_translations(self):
xml__contains=[''],
xml__excludes=[''],
)
+
+ def test_select_with_media_and_choice_filter_and_no_translations_generates_media(
+ self,
+ ):
+ """
+ Selects with media and choice filter should generate itext fields for the media.
+ """
+ xform_md = """
+ | survey | | | | |
+ | | type | name | label | choice_filter |
+ | | select_one consent | consent | Would you like to participate ? | |
+ | | select_one mood | enumerator_mood | How are you feeling today ? | selected(${consent}, 'y') |
+ | choices |
+ | | list_name | name | label | media::image |
+ | | mood | h | Happy | happy.jpg |
+ | | mood | s | Sad | sad.jpg |
+ | | consent | y | Yes | |
+ | | consent | n | No | |
+ """
+ self.assertPyxformXform(
+ name="data",
+ id_string="some-id",
+ md=xform_md,
+ errored=False,
+ debug=False,
+ model__contains=[
+ '',
+ '',
+ "mood-0",
+ "mood-1",
+ ],
+ model__excludes=[
+ '',
+ '',
+ ],
+ xml__contains=[''],
+ xml__excludes=[''],
+ )
+
+ def test_select_with_choice_filter_and_translations_generates_single_translation(
+ self,
+ ):
+ """
+ Selects with choice filter and translations should only have a single itext entry.
+ """
+ xform_md = """
+ | survey | | | | |
+ | | type | name | label | choice_filter |
+ | | select_one list | foo | Foo | name != " |
+ | choices |
+ | | list_name | name | label | image | label::French |
+ | | list | a | A | a.jpg | Ah |
+ | | list | b | B | b.jpg | Bé |
+ | | list | c | C | c.jpg | Cé |
+ """
+ self.assertPyxformXform(
+ name="data",
+ id_string="some-id",
+ md=xform_md,
+ errored=False,
+ debug=False,
+ itext__contains=[
+ '',
+ '',
+ '',
+ ],
+ itext__excludes=[
+ '',
+ '',
+ '',
+ ],
+ )