[IMP] translations: parse views iteratively instead of recursively
[odoo/odoo.git] / openerp / tools / translate.py
index 4a75e7f..37e6492 100644 (file)
@@ -195,26 +195,31 @@ class GettextAlias(object):
     def _get_lang(self, frame):
         # try, in order: context.get('lang'), kwargs['context'].get('lang'),
         # self.env.lang, self.localcontext.get('lang')
-        if 'context' in frame.f_locals:
-            return frame.f_locals['context'].get('lang')
-        kwargs = frame.f_locals.get('kwargs', {})
-        if 'context' in kwargs:
-            return kwargs['context'].get('lang')
-        s = frame.f_locals.get('self')
-        if hasattr(s, 'env'):
-            return s.env.lang
-        if hasattr(s, 'localcontext'):
-            return s.localcontext.get('lang')
-        # Last resort: attempt to guess the language of the user
-        # Pitfall: some operations are performed in sudo mode, and we
-        #          don't know the originial uid, so the language may
-        #          be wrong when the admin language differs.
-        pool = getattr(s, 'pool', None)
-        (cr, dummy) = self._get_cr(frame, allow_create=False)
-        uid = self._get_uid(frame)
-        if pool and cr and uid:
-            return pool['res.users'].context_get(cr, uid)['lang']
-        return None
+        lang = None
+        if frame.f_locals.get('context'):
+            lang = frame.f_locals['context'].get('lang')
+        if not lang:
+            kwargs = frame.f_locals.get('kwargs', {})
+            if kwargs.get('context'):
+                lang = kwargs['context'].get('lang')
+        if not lang:
+            s = frame.f_locals.get('self')
+            if hasattr(s, 'env'):
+                lang = s.env.lang
+            if not lang:
+                if hasattr(s, 'localcontext'):
+                    lang = s.localcontext.get('lang')
+            if not lang:
+                # Last resort: attempt to guess the language of the user
+                # Pitfall: some operations are performed in sudo mode, and we
+                #          don't know the originial uid, so the language may
+                #          be wrong when the admin language differs.
+                pool = getattr(s, 'pool', None)
+                (cr, dummy) = self._get_cr(frame, allow_create=False)
+                uid = self._get_uid(frame)
+                if pool and cr and uid:
+                    lang = pool['res.users'].context_get(cr, uid)['lang']
+        return lang
 
     def __call__(self, source):
         res = source
@@ -561,18 +566,17 @@ def trans_parse_view(element, callback):
         :param callable callback: a callable in the form ``f(term, source_line)``,
             that will be called for each extracted term.
     """
-    if (not isinstance(element, SKIPPED_ELEMENT_TYPES)
-            and element.tag.lower() not in SKIPPED_ELEMENTS
-            and element.text):
-        _push(callback, element.text, element.sourceline)
-    if element.tail:
-        _push(callback, element.tail, element.sourceline)
-    for attr in ('string', 'help', 'sum', 'confirm', 'placeholder'):
-        value = element.get(attr)
-        if value:
-            _push(callback, value, element.sourceline)
-    for n in element:
-        trans_parse_view(n, callback)
+    for el in element.iter():
+        if (not isinstance(el, SKIPPED_ELEMENT_TYPES)
+                and el.tag.lower() not in SKIPPED_ELEMENTS
+                and el.text):
+            _push(callback, el.text, el.sourceline)
+        if el.tail:
+            _push(callback, el.tail, el.sourceline)
+        for attr in ('string', 'help', 'sum', 'confirm', 'placeholder'):
+            value = el.get(attr)
+            if value:
+                _push(callback, value, el.sourceline)
 
 # tests whether an object is in a list of modules
 def in_modules(object_name, modules):
@@ -593,9 +597,9 @@ def _extract_translatable_qweb_terms(element, callback):
         a QWeb template, and call ``callback(term)`` for each
         translatable term that is found in the document.
 
-        :param ElementTree element: root of etree document to extract terms from
-        :param callable callback: a callable in the form ``f(term, source_line)``,
-            that will be called for each extracted term.
+        :param etree._Element element: root of etree document to extract terms from
+        :param Callable callback: a callable in the form ``f(term, source_line)``,
+                                  that will be called for each extracted term.
     """
     # not using elementTree.iterparse because we need to skip sub-trees in case
     # the ancestor element had a reason to be skipped
@@ -615,6 +619,7 @@ def _extract_translatable_qweb_terms(element, callback):
 
 def babel_extract_qweb(fileobj, keywords, comment_tags, options):
     """Babel message extractor for qweb template files.
+
     :param fileobj: the file-like object the messages should be extracted from
     :param keywords: a list of keywords (i.e. function names) that should
                      be recognized as translation functions
@@ -623,7 +628,7 @@ def babel_extract_qweb(fileobj, keywords, comment_tags, options):
     :param options: a dictionary of additional options (optional)
     :return: an iterator over ``(lineno, funcname, message, comments)``
              tuples
-    :rtype: ``iterator``
+    :rtype: Iterable
     """
     result = []
     def handle_text(text, lineno):