def _update_translation_node(self, new_translation, text_node, value_node, attributes=None, delete_node=True): if delete_node and not new_translation: # Remove the node if it already exists if value_node.exists(): value_node.xml.getparent().remove(value_node.xml) return # Create the node if it does not already exist if not value_node.exists(): e = etree.Element("{f}value".format(**namespaces), attributes) text_node.xml.append(e) value_node = WrappedNode(e) # Update the translation value_node.xml.tail = '' for node in value_node.findall("./*"): node.xml.getparent().remove(node.xml) escaped_trans = self.escape_output_value(new_translation) value_node.xml.text = escaped_trans.text for n in escaped_trans.getchildren(): value_node.xml.append(n)
def get_value_node(text_node_): try: return next( n for n in text_node_.findall("./{f}value") if 'form' not in n.attrib or n.get('form') == 'default') except StopIteration: return WrappedNode(None)
def _get_value_node(self, text_node_): default_value_nodes = list(self._get_default_value_nodes(text_node_)) if len(default_value_nodes) > 1: raise XFormException(_("Found conflicting nodes for label {}").format(text_node_.get('id'))) if default_value_nodes: return default_value_nodes[0] return WrappedNode(None)
def _test(self, escaped_itext, expected): itext_value = ItextValue.from_node( WrappedNode( '<value xmlns="http://www.w3.org/2002/xforms">%s</value>' % ( escaped_itext ) ) ) self.assertEqual(itext_value, expected)
def _update_translation_node(new_translation, value_node, attributes=None): if new_translation: # Create the node if it does not already exist if not value_node.exists(): e = etree.Element( "{f}value".format(**namespaces), attributes ) text_node.xml.append(e) value_node = WrappedNode(e) # Update the translation value_node.xml.tail = '' for node in value_node.findall("./*"): node.xml.getparent().remove(node.xml) escaped_trans = escape_output_value(new_translation) value_node.xml.text = escaped_trans.text for n in escaped_trans.getchildren(): value_node.xml.append(n) else: # Remove the node if it already exists if value_node.exists(): value_node.xml.getparent().remove(value_node.xml)
def update_form_translations(sheet, rows, missing_cols, app): """ Modify the translations of a form given a sheet of translation data. This does not save the changes to the DB. :param sheet: a WorksheetJSONReader :param rows: The rows of the sheet (we can't get this from the sheet because sheet.__iter__ can only be called once) :param missing_cols: :param app: :return: Returns a list of message tuples. The first item in each tuple is a function like django.contrib.messages.error, and the second is a string. """ msgs = [] mod_text, form_text = sheet.worksheet.title.split("_") module_index = int(mod_text.replace("module", "")) - 1 form_index = int(form_text.replace("form", "")) - 1 form = app.get_module(module_index).get_form(form_index) if form.source: xform = form.wrapped_xform() else: # This Form doesn't have an xform yet. It is empty. # Tell the user this? return msgs try: itext = xform.itext_node except XFormException: return msgs # Make language nodes for each language if they don't yet exist # # Currently operating under the assumption that every xForm has at least # one translation element, that each translation element has a text node # for each question and that each text node has a value node under it template_translation_el = None # Get a translation element to be used as a template for new elements for lang in app.langs: trans_el = itext.find("./{f}translation[@lang='%s']" % lang) if trans_el.exists(): template_translation_el = trans_el assert template_translation_el is not None # Add missing translation elements for lang in app.langs: trans_el = itext.find("./{f}translation[@lang='%s']" % lang) if not trans_el.exists(): new_trans_el = copy.deepcopy(template_translation_el.xml) new_trans_el.set("lang", lang) if lang != app.langs[0]: # If the language isn't the default language new_trans_el.attrib.pop("default", None) else: new_trans_el.set("default", "") itext.xml.append(new_trans_el) # Update the translations for lang in app.langs: translation_node = itext.find("./{f}translation[@lang='%s']" % lang) assert translation_node.exists() for row in rows: label_id = row["label"] text_node = translation_node.find("./{f}text[@id='%s']" % label_id) if not text_node.exists(): msgs.append( ( messages.warning, "Unrecognized translation label {0} in sheet {1}. That row" " has been skipped".format(label_id, sheet.worksheet.title), ) ) continue # Add or remove translations for trans_type in ["default", "audio", "image", "video"]: if trans_type == "default": attributes = None value_node = next(n for n in text_node.findall("./{f}value") if "form" not in n.attrib) else: attributes = {"form": trans_type} value_node = text_node.find("./{f}value[@form='%s']" % trans_type) col_key = get_col_key(trans_type, lang) new_translation = row[col_key] if not new_translation and col_key not in missing_cols: # If the cell corresponding to the label for this question # in this language is empty, fall back to another language for l in app.langs: fallback = row[get_col_key(trans_type, l)] if fallback: new_translation = fallback break if new_translation: # Create the node if it does not already exist if not value_node.exists(): e = etree.Element("{f}value".format(**namespaces), attributes) text_node.xml.append(e) value_node = WrappedNode(e) # Update the translation value_node.xml.text = new_translation else: # Remove the node if it already exists if value_node.exists(): value_node.xml.getparent().remove(value_node.xml) save_xform(app, form, etree.tostring(xform.xml, encoding="unicode")) return msgs
def update_form_translations(sheet, rows, missing_cols, app): """ Modify the translations of a form given a sheet of translation data. This does not save the changes to the DB. :param sheet: a WorksheetJSONReader :param rows: The rows of the sheet (we can't get this from the sheet because sheet.__iter__ can only be called once) :param missing_cols: :param app: :return: Returns a list of message tuples. The first item in each tuple is a function like django.contrib.messages.error, and the second is a string. """ msgs = [] mod_text, form_text = sheet.worksheet.title.split("_") module_index = int(mod_text.replace("module", "")) - 1 form_index = int(form_text.replace("form", "")) - 1 form = app.get_module(module_index).get_form(form_index) if form.source: xform = form.wrapped_xform() else: # This Form doesn't have an xform yet. It is empty. # Tell the user this? return msgs try: itext = xform.itext_node except XFormException: return msgs # Make language nodes for each language if they don't yet exist # # Currently operating under the assumption that every xForm has at least # one translation element, that each translation element has a text node # for each question and that each text node has a value node under it template_translation_el = None # Get a translation element to be used as a template for new elements for lang in app.langs: trans_el = itext.find("./{f}translation[@lang='%s']" % lang) if trans_el.exists(): template_translation_el = trans_el assert (template_translation_el is not None) # Add missing translation elements for lang in app.langs: trans_el = itext.find("./{f}translation[@lang='%s']" % lang) if not trans_el.exists(): new_trans_el = copy.deepcopy(template_translation_el.xml) new_trans_el.set('lang', lang) if lang != app.langs[0]: # If the language isn't the default language new_trans_el.attrib.pop('default', None) else: new_trans_el.set('default', '') itext.xml.append(new_trans_el) # Update the translations for lang in app.langs: translation_node = itext.find("./{f}translation[@lang='%s']" % lang) assert (translation_node.exists()) for row in rows: label_id = row['label'] text_node = translation_node.find("./{f}text[@id='%s']" % label_id) if not text_node.exists(): msgs.append(( messages.warning, "Unrecognized translation label {0} in sheet {1}. That row" " has been skipped".format(label_id, sheet.worksheet.title))) continue # Add or remove translations for trans_type in ['default', 'audio', 'image', 'video']: if trans_type == 'default': attributes = None value_node = next(n for n in text_node.findall("./{f}value") if 'form' not in n.attrib) else: attributes = {'form': trans_type} value_node = text_node.find("./{f}value[@form='%s']" % trans_type) try: col_key = get_col_key(trans_type, lang) new_translation = row[col_key] except KeyError: # error has already been logged as unrecoginzed column continue if not new_translation and col_key not in missing_cols: # If the cell corresponding to the label for this question # in this language is empty, fall back to another language for l in app.langs: key = get_col_key(trans_type, l) if key in missing_cols: continue fallback = row[key] if fallback: new_translation = fallback break if new_translation: # Create the node if it does not already exist if not value_node.exists(): e = etree.Element("{f}value".format(**namespaces), attributes) text_node.xml.append(e) value_node = WrappedNode(e) # Update the translation value_node.xml.tail = '' for node in value_node.findall("./*"): node.xml.getparent().remove(node.xml) escaped_trans = escape_output_value(new_translation) value_node.xml.text = escaped_trans.text for n in escaped_trans.getchildren(): value_node.xml.append(n) else: # Remove the node if it already exists if value_node.exists(): value_node.xml.getparent().remove(value_node.xml) save_xform(app, form, etree.tostring(xform.xml, encoding="unicode")) return msgs