2
\$\begingroup\$

I have 3 functions which are annoyingly similar, but I can't figure out a way to refactor them without making the code unreadable.

The three functions deal with xml files (.resx), the first function reads all files in a directory and "collects" all strings inside a data.value tag, adds them to a set and returns that set, for example:

<data name="AccessibilityTitleResource1.Text" xml:space="preserve">
<value>Pages Accessibility</value>

The second function reads these same files, and swaps the values read previously with a translation which is inside a dict called definicoes (definicoes[english] = translation), with the previous example, then saves the file. So from our previous example definicoes["Pages Accessibility"] = "Acessibilidade de Páginas". The xml file would become:

<data name="AccessibilityTitleResource1.Text" xml:space="preserve">
<value>Acessibilidade de Páginas</value>

The third function simply checks if the xml file is fully translatable, so it checks all the values <value> tags inside the <data> ones against the ones in the dict, if there is any value not present on the dict it returns False.

Here are the three functions:

def ler_todos(caminho) -> set:
    definicoes = set()
    for file in os.listdir(caminho):
        if file.endswith(".ascx.resx") or file.endswith(".aspx.resx"):
            tree = ET.parse(caminho + file)
            root = tree.getroot()
            for child in root.iter('data'):
                if child.attrib.get('namespace') == 'preserve':
                    node = child[0]
                    if node.tag == "value" and node.text != None and not node.text in definicoes:
                        definicoes.add(node.text)
    return definicoes


def escrever_arquivo(definicoes, caminho):
    if caminho.endswith(".pt.resx"):
        tree = ET.parse(caminho)
        root = tree.getroot()
        for child in root.iter('data'):
            if child.attrib.get('namespace') == 'preserve':
                node = child[0]
                if node.tag == "value" and node.text != None and node.text in definicoes:
                    node.text = definicoes[node.text]
        tree.write(caminho, encoding="UTF-8")
        anexar_cabecalho(caminho)

def existe_traducao(definicoes, caminho):
    if caminho.endswith(".resx"):
        tree = ET.parse(caminho)
        root = tree.getroot()
        for child in root.iter('data'):
            if child.attrib.get('namespace') == 'preserve':
                node = child[0]
                if node.tag == "value" and node.text != None and len(node.text) > 0 and node.text not in definicoes:
                    return False
        return True
\$\endgroup\$
  • \$\begingroup\$ I wonder why you're not using the Standard for resx localization using the usual locale specifiers... C# (and Vb.NET) deals just fine with ResourceFile.pt_PT.resx \$\endgroup\$ – Vogel612 Aug 20 '17 at 10:20
2
\$\begingroup\$

One of the possible ways to improve on following the DRY principle would be to extract the XML tree iteration part which is the same in all 3 functions. Something like this generator:

def values(tree):
    root = tree.getroot()
    for child in root.iter('data'):
        if child.attrib.get('namespace') == 'preserve':
            node = child[0]
            if node.tag == "value" and node.text is not None:
                yield node

Then, you can use it this way:

tree = ET.parse(caminho)
for node in values(tree):
    # do something with node
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.