Example #1
0
    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)
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
 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)
Example #5
0
 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)
Example #6
0
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
Example #7
0
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