2 # EASY-INSTALL-ENTRY-SCRIPT: 'Babel==0.9.6','console_scripts','pybabel'
3 __requires__ = 'Babel==0.9.6'
5 from pkg_resources import load_entry_point
8 from lxml import etree as elt
9 from babel.messages import extract
11 if __name__ == '__main__':
13 load_entry_point('Babel==0.9.6', 'console_scripts', 'pybabel')()
16 XMLJS_EXPR = re.compile(r"""(?:\_t *\( *((?:"(?:[^"\\]|\\.)*")|(?:'(?:[^'\\]|\\.)*')) *\))""")
18 TRANSLATION_FLAG_COMMENT = "openerp-web"
20 def extract_xmljs(fileobj, keywords, comment_tags, options):
21 """Extract messages from Javascript code embedded into XML documents.
22 This complements the ``extract_javascript`` extractor which works
23 only on pure .js files, and the``extract_qweb`` extractor, which only
26 :param fileobj: the file-like object the messages should be extracted
28 :param keywords: a list of keywords (i.e. function names) that should
29 be recognized as translation functions
30 :param comment_tags: a list of translator tags to search for and
31 include in the results
32 :param options: a dictionary of additional options (optional)
33 :return: an iterator over ``(lineno, funcname, message, comments)``
37 content = fileobj.read()
38 found = XMLJS_EXPR.finditer(content)
44 while index < f.start():
45 if content[index] == "\n":
48 yield (line_nbr, None, msg, [TRANSLATION_FLAG_COMMENT])
50 def extract_qweb(fileobj, keywords, comment_tags, options):
51 """Extract messages from qweb template files.
52 :param fileobj: the file-like object the messages should be extracted
54 :param keywords: a list of keywords (i.e. function names) that should
55 be recognized as translation functions
56 :param comment_tags: a list of translator tags to search for and
57 include in the results
58 :param options: a dictionary of additional options (optional)
59 :return: an iterator over ``(lineno, funcname, message, comments)``
64 def handle_text(text, lineno):
65 text = (text or "").strip()
66 if len(text) > 1: # Avoid mono-char tokens like ':' ',' etc.
67 result.append((lineno, None, text, [TRANSLATION_FLAG_COMMENT]))
69 # not using elementTree.iterparse because we need to skip sub-trees in case
70 # the ancestor element had a reason to be skipped
71 def iter_elements(current_element):
72 for el in current_element:
73 if "t-js" not in el.attrib and \
74 not ("t-jquery" in el.attrib and "t-operation" not in el.attrib) and \
75 not ("t-translation" in el.attrib and el.attrib["t-translation"].strip() == "off"):
76 handle_text(el.text, el.sourceline)
77 for att in ('title', 'alt', 'label'):
79 handle_text(el.attrib[att], el.sourceline)
81 handle_text(el.tail, el.sourceline)
83 tree = elt.parse(fileobj)
84 iter_elements(tree.getroot())
88 def extract_javascript(fileobj, keywords, comment_tags, options):
89 """Extract messages from Javascript source files. This extractor delegates
90 to babel's buit-in javascript extractor, but adds a special comment
91 used as a flag to identify web translations.
93 :param fileobj: the file-like object the messages should be extracted
95 :param keywords: a list of keywords (i.e. function names) that should
96 be recognized as translation functions
97 :param comment_tags: a list of translator tags to search for and
98 include in the results
99 :param options: a dictionary of additional options (optional)
100 :return: an iterator over ``(lineno, funcname, message, comments)``
104 for (message_lineno, funcname, messages, comments) in \
105 extract.extract_javascript(fileobj, keywords, comment_tags, options):
106 comments.append(TRANSLATION_FLAG_COMMENT)
107 yield (message_lineno, funcname, messages, comments)