def test_markup(mofile): mo = polib.mofile(mofile) for entry in mo.translated_entries(): if is_markup(entry.msgid): # If this is a plural, check each of the plural translations if entry.msgid_plural: xlations = entry.msgstr_plural else: xlations = {None: entry.msgstr} for plural_id, msgstr in xlations.items(): # Check if the markup is valid at all try: # pylint: disable=unescaped-markup ET.fromstring('<markup>%s</markup>' % msgstr) except ET.ParseError: if entry.msgid_plural: raise AssertionError("Invalid markup translation for %d translation of msgid %s" % (plural_id, entry.msgid)) else: raise AssertionError("Invalid markup translation for msgid %s" % entry.msgid) # Check if the markup has the same number and kind of tags if not markup_match(entry.msgid, msgstr): if entry.msgid_plural: raise AssertionError("Markup does not match for %d translation of msgid %s" % (plural_id, entry.msgid)) else: raise AssertionError("Markup does not match for msgid %s" % entry.msgid)
def test_markup(pofile): po = polib.pofile(pofile) for entry in po.translated_entries(): if is_markup(entry.msgid): # If this is a plural, check each of the plural translations if entry.msgid_plural: xlations = entry.msgstr_plural else: xlations = {None: entry.msgstr} for plural_id, msgstr in xlations.items(): # Check if the markup is valid at all try: # pylint: disable=unescaped-markup ET.fromstring('<markup>%s</markup>' % msgstr) except ET.ParseError: if entry.msgid_plural: raise AssertionError("Invalid markup translation for %d translation of msgid %s\n%s" % (plural_id, entry.msgid, msgstr)) else: raise AssertionError("Invalid markup translation for msgid %s\n%s" % (entry.msgid, msgstr)) # Check if the markup has the same number and kind of tags if not markup_match(entry.msgid, msgstr): if entry.msgid_plural: raise AssertionError("Markup does not match for %d translation of msgid %s\n%s" % (plural_id, entry.msgid, msgstr)) else: raise AssertionError("Markup does not match for msgid %s\n%s" % (entry.msgid, msgstr))
def test_markup(poentry): # Unnecessary markup is markup applied to an entire string, such as # _("<b>Bold Text</b>"). This could be instead be translated as # "<b>%s</b>" % _("Bold Text"), and then the translator doesn't have to see # the markup at all. if is_markup(poentry.msgid): # Wrap the string in <markup> nodes, parse it, test it # The markup is unescaped on purpose # pylint: disable=unescaped-markup tree = ET.fromstring("<markup>%s</markup>" % poentry.msgid) if not markup_necessary(tree): raise AssertionError("Unnecessary markup")
def test_markup(mofile): mo = polib.mofile(mofile) for entry in mo.translated_entries(): if is_markup(entry.msgid): # If this is a plural, check each of the plural translations if entry.msgid_plural: for plural_id, msgstr in entry.msgstr_plural.items(): if not markup_match(entry.msgid, msgstr): raise AssertionError( "Markup does not match for %d translation of msgid %s" % (plural_id, entry.msgid) ) elif not markup_match(entry.msgid, entry.msgstr): raise AssertionError("Markup does not match for msgid %s" % entry.msgid)
def visit_const(self, node): if not isinstance(node.value, (str, bytes)): return if not is_markup(node.value): return self._validate_pango_markup_string(node, node.value) # Check if this the left side of a % operation curr = node formatOp = None while curr.parent: if isinstance(curr.parent, astroid.BinOp) and curr.parent.op == "%" and \ curr.parent.left == curr: formatOp = curr.parent break curr = curr.parent # Check whether the right side of the % operation is escaped if formatOp: if isinstance(formatOp.right, astroid.CallFunc): if getattr(formatOp.right.func, "name", "") not in escapeMethods: self.add_message("W9922", node=formatOp.right) # If a tuple, each item in the tuple must be escaped elif isinstance(formatOp.right, astroid.Tuple): for elt in formatOp.right.elts: if not isinstance(elt, astroid.CallFunc) or\ getattr(elt.func, "name", "") not in escapeMethods: self.add_message("W9922", node=elt) # If a dictionary, each value must be escaped elif isinstance(formatOp.right, astroid.Dict): for item in formatOp.right.items: if not isinstance(item[1], astroid.CallFunc) or\ getattr(item[1].func, "name", "") not in escapeMethods: self.add_message("W9922", node=item[1]) else: self.add_message("W9922", node=formatOp)
def visit_const(self, node): if not isinstance(node.value, (str, bytes)): return if not is_markup(node.value): return self._validate_pango_markup_string(node, node.value) # Check translated versions of the string if requested if self.config.translate_markup: global podicts # Check if this is a translatable string curr = node i18nFunc = None while curr.parent: if isinstance(curr.parent, astroid.CallFunc) and \ getattr(curr.parent.func, "name", "") in i18n_funcs: i18nFunc = curr.parent break curr = curr.parent if i18nFunc: # If not done already, import polib and read the translations if not podicts: try: from pocketlint.translatepo import translate_all except ImportError: print("Unable to load po translation module") sys.exit(99) else: podicts = translate_all(os.path.join(os.environ.get('top_srcdir', '.'), 'po')) if i18nFunc.func.name in i18n_ctxt_funcs: msgctxt = i18nFunc.args[0].value else: msgctxt = None # Loop over all translations for the string for podict in podicts.values(): try: node_values = podict.get(node.value, msgctxt) except KeyError: continue for value in node_values: self._validate_pango_markup_string(node, value, podict.metadata['Language']) # Check that the markup matches, roughly if not markup_match(node.value, value): self.add_message("W9925", node=node, args=(podict.metadata['Language'],)) # Check if this the left side of a % operation curr = node formatOp = None while curr.parent: if isinstance(curr.parent, astroid.BinOp) and curr.parent.op == "%" and \ curr.parent.left == curr: formatOp = curr.parent break curr = curr.parent # Check whether the right side of the % operation is escaped if formatOp: if isinstance(formatOp.right, astroid.CallFunc): if getattr(formatOp.right.func, "name", "") not in escapeMethods: self.add_message("W9922", node=formatOp.right) # If a tuple, each item in the tuple must be escaped elif isinstance(formatOp.right, astroid.Tuple): for elt in formatOp.right.elts: if not isinstance(elt, astroid.CallFunc) or\ getattr(elt.func, "name", "") not in escapeMethods: self.add_message("W9922", node=elt) # If a dictionary, each value must be escaped elif isinstance(formatOp.right, astroid.Dict): for item in formatOp.right.items: if not isinstance(item[1], astroid.CallFunc) or\ getattr(item[1].func, "name", "") not in escapeMethods: self.add_message("W9922", node=item[1]) else: self.add_message("W9922", node=formatOp)