translate: implement a counter to export the code line number
[odoo/odoo.git] / bin / tools / translate.py
index a296f0e..8cf09f9 100644 (file)
@@ -33,12 +33,11 @@ import tarfile
 import tempfile
 import threading
 from os.path import join
-import logging
 
 from datetime import datetime
 from lxml import etree
 
-import tools, pooler
+import tools
 import netsvc
 from tools.misc import UpdateableStr
 
@@ -159,8 +158,7 @@ class GettextAlias(object):
         # find current DB based on thread/worker db name (see netsvc)
         db_name = getattr(threading.currentThread(), 'dbname', None)
         if db_name:
-            dbname = getattr(threading.currentThread(), 'dbname')
-            return pooler.get_db_only(dbname)
+            return pooler.get_db_only(db_name)
 
     def _get_cr(self, frame):
         is_new_cr = False
@@ -220,6 +218,7 @@ class GettextAlias(object):
                 logger.debug('no translation language detected, skipping translation for "%r" ', source)
         except Exception:
             logger.debug('translation went wrong for "%r", skipped', source)
+                # if so, double-check the root/base translations filenames
         finally:
             if cr and is_new_cr:
                 cr.close()
@@ -251,8 +250,8 @@ class TinyPoFile(object):
         self.logger = logging.getLogger('i18n')
         self.buffer = buffer
 
-    def warn(self, msg):
-        self.logger.warning(msg)
+    def warn(self, msg, *args):
+        self.logger.warning(msg, *args)
 
     def __iter__(self):
         self.buffer.seek(0)
@@ -438,7 +437,9 @@ def trans_export(lang, modules, buffer, format, dbname=None):
             rows_by_module = {}
             for row in rows:
                 module = row[0]
-                rows_by_module.setdefault(module, []).append(row)
+                # first row is the "header", as in csv, it will be popped
+                rows_by_module.setdefault(module, [['module', 'type', 'name', 'res_id', 'src', ''],])
+                rows_by_module[module].append(row)
 
             tmpdir = tempfile.mkdtemp()
             for mod, modrows in rows_by_module.items():
@@ -747,6 +748,10 @@ def trans_generate(lang, modules, dbname=None):
         path_list = apaths
     else :
         path_list = [root_path,] + apaths
+    
+    # Also scan these non-addon paths
+    for bin_path in ['osv', 'report' ]:
+        path_list.append(os.path.join(tools.config['root_path'], bin_path))
 
     logger.debug("Scanning modules at paths: ", path_list)
 
@@ -767,6 +772,8 @@ def trans_generate(lang, modules, dbname=None):
             if module in installed_modules:
                 frelativepath = str("addons" + frelativepath)
             ite = re_dquotes.finditer(code_string)
+            code_offset = 0
+            code_line = 1
             for i in ite:
                 src = i.group(1)
                 if src.startswith('""'):
@@ -774,11 +781,18 @@ def trans_generate(lang, modules, dbname=None):
                     src = src[2:-2]
                 else:
                     src = join_dquotes.sub(r'\1', src)
+                # try to count the lines from the last pos to our place:
+                code_line += code_string[code_offset:i.start(1)].count('\n')
                 # now, since we did a binary read of a python source file, we
                 # have to expand pythonic escapes like the interpreter does.
                 src = src.decode('string_escape')
-                push_translation(module, terms_type, frelativepath, 0, encode(src))
+                push_translation(module, terms_type, frelativepath, code_line, encode(src))
+                code_line += i.group(1).count('\n')
+                code_offset = i.end() # we have counted newlines up to the match end
+
             ite = re_quotes.finditer(code_string)
+            code_offset = 0 #reset counters
+            code_line = 1
             for i in ite:
                 src = i.group(1)
                 if src.startswith("''"):
@@ -786,8 +800,11 @@ def trans_generate(lang, modules, dbname=None):
                     src = src[2:-2]
                 else:
                     src = join_quotes.sub(r'\1', src)
+                code_line += code_string[code_offset:i.start(1)].count('\n')
                 src = src.decode('string_escape')
-                push_translation(module, terms_type, frelativepath, 0, encode(src))
+                push_translation(module, terms_type, frelativepath, code_line, encode(src))
+                code_line += i.group(1).count('\n')
+                code_offset = i.end() # we have counted newlines up to the match end
 
     for path in path_list:
         logger.debug("Scanning files of modules at %s", path)
@@ -808,13 +825,13 @@ def trans_generate(lang, modules, dbname=None):
     cr.close()
     return out
 
-def trans_load(db_name, filename, lang, strict=False, verbose=True, context=None):
+def trans_load(db_name, filename, lang, verbose=True, context=None):
     logger = logging.getLogger('i18n')
     try:
         fileobj = open(filename,'r')
         logger.info("loading %s", filename)
         fileformat = os.path.splitext(filename)[-1][1:].lower()
-        r = trans_load_data(db_name, fileobj, fileformat, lang, strict=strict, verbose=verbose, context=context)
+        r = trans_load_data(db_name, fileobj, fileformat, lang, verbose=verbose, context=context)
         fileobj.close()
         return r
     except IOError:
@@ -822,7 +839,7 @@ def trans_load(db_name, filename, lang, strict=False, verbose=True, context=None
             logger.error("couldn't read translation file %s", filename)
         return None
 
-def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=None, verbose=True, context=None):
+def trans_load_data(db_name, fileobj, fileformat, lang, lang_name=None, verbose=True, context=None):
     logger = logging.getLogger('i18n')
     if verbose:
         logger.info('loading translation file for language %s', lang)
@@ -924,52 +941,20 @@ def trans_load_data(db_name, fileobj, fileformat, lang, strict=False, lang_name=
                 else:
                     dic['res_id'] = False
 
-            if dic['type'] == 'model' and not strict:
-                (model, field) = dic['name'].split(',')
-
-                # get the ids of the resources of this model which share
-                # the same source
-                obj = pool.get(model)
-                if obj:
-                    if field not in obj.fields_get_keys(cr, uid):
-                        continue
-                    # Using search() instead of _search() will limit the
-                    # returned list to the ids visible to uid, which is not
-                    # in the extended view group. We want all of them and use
-                    # _search().
-                    ids = obj._search(cr, uid, [(field, '=', dic['src'])])
-
-                    # if the resource id (res_id) is in that list, use it,
-                    # otherwise use the whole list
-                    if not ids:
-                        ids = []
-                    ids = (dic['res_id'] in ids) and [dic['res_id']] or ids
-                    for id in ids:
-                        dic['res_id'] = id
-                        ids = trans_obj.search(cr, uid, [
-                            ('lang', '=', lang),
-                            ('type', '=', dic['type']),
-                            ('name', '=', dic['name']),
-                            ('src', '=', dic['src']),
-                            ('res_id', '=', dic['res_id'])
-                        ])
-                        if ids:
-                            if context.get('overwrite', False):
-                                trans_obj.write(cr, uid, ids, {'value': dic['value']})
-                        else:
-                            trans_obj.create(cr, uid, dic)
+            args = [
+                ('lang', '=', lang),
+                ('type', '=', dic['type']),
+                ('name', '=', dic['name']),
+                ('src', '=', dic['src']),
+            ]
+            if dic['type'] == 'model':
+                args.append(('res_id', '=', dic['res_id']))
+            ids = trans_obj.search(cr, uid, args)
+            if ids:
+                if context.get('overwrite'):
+                    trans_obj.write(cr, uid, ids, {'value': dic['value']})
             else:
-                ids = trans_obj.search(cr, uid, [
-                    ('lang', '=', lang),
-                    ('type', '=', dic['type']),
-                    ('name', '=', dic['name']),
-                    ('src', '=', dic['src'])
-                ])
-                if ids:
-                    if context.get('overwrite', False):
-                        trans_obj.write(cr, uid, ids, {'value': dic['value']})
-                else:
-                    trans_obj.create(cr, uid, dic)
+                trans_obj.create(cr, uid, dic)
             cr.commit()
         cr.close()
         if verbose: