import os import re import sys from typing import Dict, Tuple import polib VERBOSE = False DEBUG = False SKIP_TRANSLATED_ENTRIES = True try: from deep_translator import GoogleTranslator except ImportError: print("Error: This util script needs `deep_translator` to be installed") sys.exit(1) _patterns = [ ":c:func:`[^`]+`", ":c:type:`[^`]+`", ":c:macro:`[^`]+`", ":c:member:`[^`]+`", ":c:data:`[^`]+`", ":py:data:`[^`]+`", ":py:mod:`[^`]+`", ":func:`[^`]+`", ":mod:`[^`]+`", ":ref:`[^`]+`", ":class:`[^`]+`", ":pep:`[^`]+`", ":data:`[^`]+`", ":exc:`[^`]+`", ":term:`[^`]+`", ":meth:`[^`]+`", ":envvar:`[^`]+`", ":file:`[^`]+`", ":attr:`[^`]+`", ":const:`[^`]+`", ":issue:`[^`]+`", ":opcode:`[^`]+`", ":option:`[^`]+`", ":program:`[^`]+`", ":keyword:`[^`]+`", ":RFC:`[^`]+`", ":rfc:`[^`]+`", ":doc:`[^`]+`", ":source:`[^`]+`", ":manpage:`[^`]+`", ":mimetype:`[^`]+`", ":sup:`[^`]+`", "``[^`]+``", "`[^`]+`__", "`[^`]+`_", "\*\*[^\*]+\*\*", # bold text between ** "\*[^\*]+\*", # italic text between * ] _exps = [re.compile(e) for e in _patterns] def protect_sphinx_directives(s: str) -> Tuple[dict, str]: """ Parameters: string containing the text to translate Returns: dictionary containing all the placeholder text as keys and the correct value. """ i = 0 d: Dict[str, str] = {} for exp in _exps: matches = exp.findall(s) if DEBUG: print(exp, matches) for match in matches: ph = f"XASDF{str(i).zfill(2)}" s = s.replace(match, ph) if ph in d and VERBOSE: print(f"Error: {ph} is already in the dictionary") print("new", match) print("old", d[ph]) d[ph] = match i += 1 return d, s def undo_sphinx_directives_protection(placeholders: dict, translated_text: str) -> str: for ph, value in placeholders.items(): translated_text = translated_text.replace(ph, value) if DEBUG: print(ph, value) print(translated_text) return translated_text if __name__ == "__main__": filename = sys.argv[1] if not os.path.isfile(filename): print(f"File not found: '{filename}'") sys.exit(-1) po = polib.pofile(filename) translator = GoogleTranslator(source="en", target="es") for entry in po: # If the entry has already a translation, skip. if SKIP_TRANSLATED_ENTRIES and entry.msgstr: continue print("\nEN|", entry.msgid) placeholders, temp_text = protect_sphinx_directives(entry.msgid) if VERBOSE: print(temp_text) print(placeholders) # Translate the temporary text without sphinx statements translated_text = translator.translate(temp_text) # Recover sphinx statements real_text = undo_sphinx_directives_protection(placeholders, translated_text) print("ES|", real_text) # Replace the po file translated entry entry.msgstr = real_text # Save the file after all the entries are translated po.save()