def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, module_name=None, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname registry = openerp.registry(db_name) lang_obj = registry.get('res.lang') trans_obj = registry.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: ids = lang_obj.search(cr, SUPERUSER_ID, [('code','=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, SUPERUSER_ID, lang=lang, lang_name=lang_name) # Parse also the POT: it will possibly provide additional targets. # (Because the POT comments are correct on Launchpad but not the # PO comments due to a Launchpad limitation. See LP bug 933496.) pot_reader = [] # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: fields = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) fields = ['type', 'name', 'res_id', 'src', 'value', 'comments'] # Make a reader for the POT file and be somewhat defensive for the # stable branch. if fileobj.name.endswith('.po'): try: # Normally the path looks like /path/to/xxx/i18n/lang.po # and we try to find the corresponding # /path/to/xxx/i18n/xxx.pot file. # (Sometimes we have 'i18n_extra' instead of just 'i18n') addons_module_i18n, _ = os.path.split(fileobj.name) addons_module, i18n_dir = os.path.split(addons_module_i18n) addons, module = os.path.split(addons_module) pot_handle = misc.file_open(os.path.join( addons, module, i18n_dir, module + '.pot')) pot_reader = TinyPoFile(pot_handle) except: pass else: _logger.info('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # Read the POT references, and keep them indexed by source string. class Target(object): def __init__(self): self.value = None self.targets = set() # set of (type, name, res_id) self.comments = None pot_targets = defaultdict(Target) for type, name, res_id, src, _, comments in pot_reader: if type is not None: target = pot_targets[src] target.targets.add((type, name, res_id)) target.comments = comments # read the rest of the file irt_cursor = trans_obj._get_import_cursor(cr, SUPERUSER_ID, context=context) def process_row(row): """Process a single PO (or POT) entry.""" # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ..., 'module':...} dic = dict.fromkeys(('type', 'name', 'res_id', 'src', 'value', 'comments', 'imd_model', 'imd_name', 'module')) dic['lang'] = lang dic.update(zip(fields, row)) # discard the target from the POT targets. src = dic['src'] if src in pot_targets: target = pot_targets[src] target.value = dic['value'] target.targets.discard((dic['type'], dic['name'], dic['res_id'])) # This would skip terms that fail to specify a res_id res_id = dic['res_id'] if not res_id: return if isinstance(res_id, (int, long)) or \ (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) dic['module'] = module_name else: # res_id is an xml id dic['res_id'] = None dic['imd_model'] = dic['name'].split(',')[0] if '.' in res_id: dic['module'], dic['imd_name'] = res_id.split('.', 1) else: dic['module'], dic['imd_name'] = False, res_id irt_cursor.push(dic) # First process the entries from the PO file (doing so also fills/removes # the entries from the POT file). for row in reader: process_row(row) # Then process the entries implied by the POT file (which is more # correct w.r.t. the targets) if some of them remain. pot_rows = [] for src, target in pot_targets.iteritems(): if target.value: for type, name, res_id in target.targets: pot_rows.append((type, name, res_id, src, target.value, target.comments)) pot_targets.clear() for row in pot_rows: process_row(row) irt_cursor.finish() trans_obj.clear_caches() if verbose: _logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) _logger.exception("couldn't read translation file %s", filename)
def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, module_name=None, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname pool = pooler.get_pool(db_name) lang_obj = pool.get('res.lang') trans_obj = pool.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: ids = lang_obj.search(cr, SUPERUSER_ID, [('code','=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, SUPERUSER_ID, lang=lang, lang_name=lang_name) # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: f = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) f = ['type', 'name', 'res_id', 'src', 'value', 'comments'] else: _logger.error('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # read the rest of the file line = 1 irt_cursor = trans_obj._get_import_cursor(cr, SUPERUSER_ID, context=context) for row in reader: line += 1 # skip empty rows and rows where the translation field (=last fiefd) is empty #if (not row) or (not row[-1]): # continue # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ..., 'module':...} dic = dict.fromkeys(('name', 'res_id', 'src', 'type', 'imd_model', 'imd_name', 'module', 'value', 'comments')) dic['lang'] = lang for i, field in enumerate(f): dic[field] = row[i] # This would skip terms that fail to specify a res_id if not dic.get('res_id'): continue res_id = dic.pop('res_id') if res_id and isinstance(res_id, (int, long)) \ or (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) dic['module'] = module_name else: tmodel = dic['name'].split(',')[0] if '.' in res_id: tmodule, tname = res_id.split('.', 1) else: tmodule = False tname = res_id dic['imd_model'] = tmodel dic['imd_name'] = tname dic['module'] = tmodule dic['res_id'] = None irt_cursor.push(dic) irt_cursor.finish() if verbose: _logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) _logger.exception("couldn't read translation file %s", filename)
def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, module_name=None, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname pool = pooler.get_pool(db_name) lang_obj = pool.get('res.lang') trans_obj = pool.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: ids = lang_obj.search(cr, SUPERUSER_ID, [('code','=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, SUPERUSER_ID, lang=lang, lang_name=lang_name) # Parse also the POT: it will possibly provide additional targets. # (Because the POT comments are correct on Launchpad but not the # PO comments due to a Launchpad limitation. See LP bug 933496.) pot_reader = [] # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: f = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) f = ['type', 'name', 'res_id', 'src', 'value', 'comments'] # Make a reader for the POT file and be somewhat defensive for the # stable branch. if fileobj.name.endswith('.po'): try: # Normally the path looks like /path/to/xxx/i18n/lang.po # and we try to find the corresponding # /path/to/xxx/i18n/xxx.pot file. head, _ = os.path.split(fileobj.name) head2, _ = os.path.split(head) head3, tail3 = os.path.split(head2) pot_handle = misc.file_open(os.path.join(head3, tail3, 'i18n', tail3 + '.pot')) pot_reader = TinyPoFile(pot_handle) except: pass else: _logger.error('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # Read the POT `reference` comments, and keep them indexed by source # string. pot_targets = {} for type, name, res_id, src, _, comments in pot_reader: if type is not None: pot_targets.setdefault(src, {'value': None, 'targets': []}) pot_targets[src]['targets'].append((type, name, res_id)) # read the rest of the file irt_cursor = trans_obj._get_import_cursor(cr, SUPERUSER_ID, context=context) def process_row(row): """Process a single PO (or POT) entry.""" # skip empty rows and rows where the translation field (=last fiefd) is empty #if (not row) or (not row[-1]): # return # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ..., 'module':...} dic = dict.fromkeys(('name', 'res_id', 'src', 'type', 'imd_model', 'imd_name', 'module', 'value', 'comments')) dic['lang'] = lang for i, field in enumerate(f): dic[field] = row[i] # Get the `reference` comments from the POT. src = row[3] if pot_reader and src in pot_targets: pot_targets[src]['targets'] = filter(lambda x: x != row[:3], pot_targets[src]['targets']) pot_targets[src]['value'] = row[4] if not pot_targets[src]['targets']: del pot_targets[src] # This would skip terms that fail to specify a res_id if not dic.get('res_id'): return res_id = dic.pop('res_id') if res_id and isinstance(res_id, (int, long)) \ or (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) dic['module'] = module_name else: tmodel = dic['name'].split(',')[0] if '.' in res_id: tmodule, tname = res_id.split('.', 1) else: tmodule = False tname = res_id dic['imd_model'] = tmodel dic['imd_name'] = tname dic['module'] = tmodule dic['res_id'] = None irt_cursor.push(dic) # First process the entries from the PO file (doing so also fills/removes # the entries from the POT file). for row in reader: process_row(row) # Then process the entries implied by the POT file (which is more # correct w.r.t. the targets) if some of them remain. pot_rows = [] for src in pot_targets: value = pot_targets[src]['value'] for type, name, res_id in pot_targets[src]['targets']: pot_rows.append((type, name, res_id, src, value, comments)) for row in pot_rows: process_row(row) irt_cursor.finish() trans_obj.clear_caches() if verbose: _logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) _logger.exception("couldn't read translation file %s", filename)
def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname pool = pooler.get_pool(db_name) lang_obj = pool.get('res.lang') trans_obj = pool.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: uid = 1 ids = lang_obj.search(cr, uid, [('code', '=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, 1, lang=lang, lang_name=lang_name) # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: f = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) f = ['type', 'name', 'res_id', 'src', 'value'] else: _logger.error('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # read the rest of the file line = 1 irt_cursor = trans_obj._get_import_cursor(cr, uid, context=context) for row in reader: line += 1 # skip empty rows and rows where the translation field (=last fiefd) is empty #if (not row) or (not row[-1]): # continue # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ...} dic = {'lang': lang} dic_module = False for i in range(len(f)): if f[i] in ('module', ): continue dic[f[i]] = row[i] # This would skip terms that fail to specify a res_id if not dic.get('res_id', False): continue res_id = dic.pop('res_id') if res_id and isinstance(res_id, (int, long)) \ or (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) else: try: tmodel = dic['name'].split(',')[0] if '.' in res_id: tmodule, tname = res_id.split('.', 1) else: tmodule = dic_module tname = res_id dic['imd_model'] = tmodel dic['imd_module'] = tmodule dic['imd_name'] = tname dic['res_id'] = None except Exception: _logger.warning( "Could not decode resource for %s, please fix the po file.", dic['res_id'], exc_info=True) dic['res_id'] = None irt_cursor.push(dic) irt_cursor.finish() if verbose: _logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) _logger.exception("couldn't read translation file %s", filename)
def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, module_name=None, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname registry = openerp.registry(db_name) lang_obj = registry.get('res.lang') trans_obj = registry.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: ids = lang_obj.search(cr, SUPERUSER_ID, [('code','=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, SUPERUSER_ID, lang=lang, lang_name=lang_name) # Parse also the POT: it will possibly provide additional targets. # (Because the POT comments are correct on Launchpad but not the # PO comments due to a Launchpad limitation. See LP bug 933496.) pot_reader = [] # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: f = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) f = ['type', 'name', 'res_id', 'src', 'value', 'comments'] # Make a reader for the POT file and be somewhat defensive for the # stable branch. if fileobj.name.endswith('.po'): try: # Normally the path looks like /path/to/xxx/i18n/lang.po # and we try to find the corresponding # /path/to/xxx/i18n/xxx.pot file. head, _ = os.path.split(fileobj.name) head2, _ = os.path.split(head) head3, tail3 = os.path.split(head2) pot_handle = misc.file_open(os.path.join(head3, tail3, 'i18n', tail3 + '.pot')) pot_reader = TinyPoFile(pot_handle) except: pass else: _logger.error('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # Read the POT `reference` comments, and keep them indexed by source # string. pot_targets = {} for type, name, res_id, src, _, comments in pot_reader: if type is not None: pot_targets.setdefault(src, {'value': None, 'targets': []}) pot_targets[src]['targets'].append((type, name, res_id)) # read the rest of the file irt_cursor = trans_obj._get_import_cursor(cr, SUPERUSER_ID, context=context) def process_row(row): """Process a single PO (or POT) entry.""" # skip empty rows and rows where the translation field (=last fiefd) is empty #if (not row) or (not row[-1]): # return # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ..., 'module':...} dic = dict.fromkeys(('name', 'res_id', 'src', 'type', 'imd_model', 'imd_name', 'module', 'value', 'comments')) dic['lang'] = lang for i, field in enumerate(f): dic[field] = row[i] # Get the `reference` comments from the POT. src = row[3] if pot_reader and src in pot_targets: pot_targets[src]['targets'] = filter(lambda x: x != row[:3], pot_targets[src]['targets']) pot_targets[src]['value'] = row[4] if not pot_targets[src]['targets']: del pot_targets[src] # This would skip terms that fail to specify a res_id if not dic.get('res_id'): return res_id = dic.pop('res_id') if res_id and isinstance(res_id, (int, long)) \ or (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) dic['module'] = module_name else: tmodel = dic['name'].split(',')[0] if '.' in res_id: tmodule, tname = res_id.split('.', 1) else: tmodule = False tname = res_id dic['imd_model'] = tmodel dic['imd_name'] = tname dic['module'] = tmodule dic['res_id'] = None irt_cursor.push(dic) # First process the entries from the PO file (doing so also fills/removes # the entries from the POT file). for row in reader: process_row(row) # Then process the entries implied by the POT file (which is more # correct w.r.t. the targets) if some of them remain. pot_rows = [] for src in pot_targets: value = pot_targets[src]['value'] for type, name, res_id in pot_targets[src]['targets']: pot_rows.append((type, name, res_id, src, value, comments)) for row in pot_rows: process_row(row) irt_cursor.finish() trans_obj.clear_caches() if verbose: _logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) _logger.exception("couldn't read translation file %s", filename)
def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, module_name=None, context=None): """Populates the ir_translation table.""" if verbose: _logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname registry = openerp.registry(db_name) lang_obj = registry.get('res.lang') trans_obj = registry.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: ids = lang_obj.search(cr, SUPERUSER_ID, [('code', '=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, SUPERUSER_ID, lang=lang, lang_name=lang_name) # Parse also the POT: it will possibly provide additional targets. # (Because the POT comments are correct on Launchpad but not the # PO comments due to a Launchpad limitation. See LP bug 933496.) pot_reader = [] # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: fields = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) fields = ['type', 'name', 'res_id', 'src', 'value', 'comments'] # Make a reader for the POT file and be somewhat defensive for the # stable branch. if fileobj.name.endswith('.po'): try: # Normally the path looks like /path/to/xxx/i18n/lang.po # and we try to find the corresponding # /path/to/xxx/i18n/xxx.pot file. # (Sometimes we have 'i18n_extra' instead of just 'i18n') addons_module_i18n, _ = os.path.split(fileobj.name) addons_module, i18n_dir = os.path.split(addons_module_i18n) addons, module = os.path.split(addons_module) pot_handle = misc.file_open( os.path.join(addons, module, i18n_dir, module + '.pot')) pot_reader = TinyPoFile(pot_handle) except: pass else: _logger.info('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # Read the POT references, and keep them indexed by source string. class Target(object): def __init__(self): self.value = None self.targets = set() # set of (type, name, res_id) self.comments = None pot_targets = defaultdict(Target) for type, name, res_id, src, _, comments in pot_reader: if type is not None: target = pot_targets[src] target.targets.add((type, name, res_id)) target.comments = comments # read the rest of the file irt_cursor = trans_obj._get_import_cursor(cr, SUPERUSER_ID, context=context) def process_row(row): """Process a single PO (or POT) entry.""" # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ..., 'module':...} dic = dict.fromkeys( ('type', 'name', 'res_id', 'src', 'value', 'comments', 'imd_model', 'imd_name', 'module')) dic['lang'] = lang dic.update(zip(fields, row)) # discard the target from the POT targets. src = dic['src'] if src in pot_targets: target = pot_targets[src] target.value = dic['value'] target.targets.discard( (dic['type'], dic['name'], dic['res_id'])) # This would skip terms that fail to specify a res_id res_id = dic['res_id'] if not res_id: return if isinstance(res_id, (int, long)) or \ (isinstance(res_id, basestring) and res_id.isdigit()): dic['res_id'] = int(res_id) dic['module'] = module_name else: # res_id is an xml id dic['res_id'] = None dic['imd_model'] = dic['name'].split(',')[0] if '.' in res_id: dic['module'], dic['imd_name'] = res_id.split('.', 1) else: dic['module'], dic['imd_name'] = False, res_id irt_cursor.push(dic) # First process the entries from the PO file (doing so also fills/removes # the entries from the POT file). for row in reader: process_row(row) # Then process the entries implied by the POT file (which is more # correct w.r.t. the targets) if some of them remain. pot_rows = [] for src, target in pot_targets.iteritems(): if target.value: for type, name, res_id in target.targets: pot_rows.append((type, name, res_id, src, target.value, target.comments)) pot_targets.clear() for row in pot_rows: process_row(row) irt_cursor.finish() trans_obj.clear_caches() if verbose: _logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) _logger.exception("couldn't read translation file %s", filename)
def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, context=None): """Populates the ir_translation table. Fixing the res_ids so that they point correctly to ir_model_data is done in a separate step, using the 'trans_update_res_ids' function below.""" logger = logging.getLogger('i18n') if verbose: logger.info('loading translation file for language %s', lang) if context is None: context = {} db_name = cr.dbname pool = pooler.get_pool(db_name) lang_obj = pool.get('res.lang') trans_obj = pool.get('ir.translation') iso_lang = misc.get_iso_codes(lang) try: uid = 1 ids = lang_obj.search(cr, uid, [('code','=', lang)]) if not ids: # lets create the language with locale information lang_obj.load_lang(cr, 1, lang=lang, lang_name=lang_name) # now, the serious things: we read the language file fileobj.seek(0) if fileformat == 'csv': reader = csv.reader(fileobj, quotechar='"', delimiter=',') # read the first line of the file (it contains columns titles) for row in reader: f = row break elif fileformat == 'po': reader = TinyPoFile(fileobj) f = ['type', 'name', 'res_id', 'src', 'value'] else: logger.error('Bad file format: %s', fileformat) raise Exception(_('Bad file format')) # read the rest of the file line = 1 for row in reader: line += 1 # skip empty rows and rows where the translation field (=last fiefd) is empty #if (not row) or (not row[-1]): # continue # dictionary which holds values for this line of the csv file # {'lang': ..., 'type': ..., 'name': ..., 'res_id': ..., # 'src': ..., 'value': ...} dic = {'lang': lang} for i in range(len(f)): if f[i] in ('module',): continue dic[f[i]] = row[i] try: dic['res_id'] = dic['res_id'] and int(dic['res_id']) or 0 dic['module'] = False dic['xml_id'] = False except: split_id = dic['res_id'].split('.', 1) dic['module'] = split_id[0] dic['xml_id'] = split_id[1] dic['res_id'] = False args = [ ('lang', '=', lang), ('type', '=', dic['type']), ('name', '=', dic['name']), ('src', '=', dic['src']), ] if dic['type'] == 'model': if dic['res_id'] is False: args.append(('module', '=', dic['module'])) args.append(('xml_id', '=', dic['xml_id'])) else: args.append(('res_id', '=', dic['res_id'])) ids = trans_obj.search(cr, uid, args) if ids: if context.get('overwrite') and dic['value']: trans_obj.write(cr, uid, ids, {'value': dic['value']}) else: trans_obj.create(cr, uid, dic) if verbose: logger.info("translation file loaded succesfully") except IOError: filename = '[lang: %s][format: %s]' % (iso_lang or 'new', fileformat) logger.exception("couldn't read translation file %s", filename)