def trans_load(cr, filename, lang, verbose=True, module_name=None, context=None): cr.execute("select id from ir_module_module where name=%s", (module_name,)) module_id = cr.fetchone()[0] cr.execute("select id,checksum from ir_module_module_file" " where module_id=%s and filename=%s", (module_id, filename)) checksum = cr.fetchone() module_file_id = checksum and checksum[0] or False checksum = checksum and checksum[1] or '' sha256 = hashlib.sha256() sha256.update(misc.file_open(filename).read()) checksum_new = sha256.hexdigest() file_modified = not checksum == checksum_new result = None try: fileobj = misc.file_open(filename) _logger.info("%s %s", file_modified and 'loading' or 'no changes', filename) fileformat = os.path.splitext(filename)[-1][1:].lower() if file_modified: result = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) fileobj.close() except IOError: if verbose: _logger.error("couldn't read translation file %s", filename) if file_modified: if module_file_id: cr.execute("update ir_module_module_file set checksum=%s, write_date=now() where id=%s", (checksum_new, module_file_id)) else: cr.execute( "insert into ir_module_module_file(filename,module_id,checksum,create_date,create_uid,write_date,write_uid)" " values(%s,%s,%s,now(),1,now(),1)", (filename,module_id,checksum_new)) return result
def process_report(self, node): values = {} for dest, f in (('name','string'), ('model','model'), ('report_name','name')): values[dest] = getattr(node, f) assert values[dest], "Attribute %s of report is empty !" % (f,) for field,dest in (('rml','report_rml'),('file','report_rml'),('xml','report_xml'),('xsl','report_xsl'),('attachment','attachment'),('attachment_use','attachment_use')): if getattr(node, field): values[dest] = getattr(node, field) if node.auto: values['auto'] = eval(node.auto) if node.sxw: sxw_file = misc.file_open(node.sxw) try: sxw_content = sxw_file.read() values['report_sxw_content'] = sxw_content finally: sxw_file.close() if node.header: values['header'] = eval(node.header) values['multi'] = node.multi and eval(node.multi) xml_id = node.id self.validate_xml_id(xml_id) self._set_group_values(node, values) id = self.pool.get('ir.model.data')._update(self.cr, 1, "ir.actions.report.xml", \ self.module, values, xml_id, noupdate=self.isnoupdate(node), mode=self.mode) self.id_map[xml_id] = int(id) if not node.menu or eval(node.menu): keyword = node.keyword or 'client_print_multi' value = 'ir.actions.report.xml,%s' % id replace = node.replace or True self.pool.get('ir.model.data').ir_set(self.cr, 1, 'action', \ keyword, values['name'], [values['model']], value, replace=replace, isobject=True, xml_id=xml_id)
def convert_file(cr, module, filename, idref, mode='update', noupdate=False, kind=None, report=None, pathname=None): if pathname is None: pathname = os.path.join(module, filename) fp = misc.file_open(pathname) ext = os.path.splitext(filename)[1].lower() try: if ext == '.csv': convert_csv_import(cr, module, pathname, fp.read(), idref, mode, noupdate) elif ext == '.sql': convert_sql_import(cr, fp) elif ext == '.yml': convert_yaml_import(cr, module, fp, kind, idref, mode, noupdate, report) elif ext == '.xml': convert_xml_import(cr, module, fp, idref, mode, noupdate, report) elif ext == '.js': pass # .js files are valid but ignored here. else: _logger.warning("Can't load unknown file type %s.", filename) finally: fp.close()
def process_report(self, node): values = {} for dest, f in (('name','string'), ('model','model'), ('report_name','name')): values[dest] = getattr(node, f) assert values[dest], "Attribute %s of report is empty !" % (f,) for field,dest in (('rml','report_rml'),('file','report_rml'),('xml','report_xml'),('xsl','report_xsl'),('attachment','attachment'),('attachment_use','attachment_use')): if getattr(node, field): values[dest] = getattr(node, field) if node.auto: values['auto'] = eval(node.auto) if node.sxw: sxw_file = misc.file_open(node.sxw) try: sxw_content = sxw_file.read() values['report_sxw_content'] = sxw_content finally: sxw_file.close() if node.header: values['header'] = eval(node.header) values['multi'] = node.multi and eval(node.multi) xml_id = node.id self.validate_xml_id(xml_id) self._set_group_values(node, values) id = self.pool.get('ir.model.data')._update(self.cr, SUPERUSER_ID, "ir.actions.report.xml", \ self.module, values, xml_id, noupdate=self.isnoupdate(node), mode=self.mode) self.id_map[xml_id] = int(id) if not node.menu or eval(node.menu): keyword = node.keyword or 'client_print_multi' value = 'ir.actions.report.xml,%s' % id replace = node.replace or True self.pool.get('ir.model.data').ir_set(self.cr, SUPERUSER_ID, 'action', \ keyword, values['name'], [values['model']], value, replace=replace, isobject=True, xml_id=xml_id)
def process_report(self, node): values = {} for dest, f in (("name", "string"), ("model", "model"), ("report_name", "name")): values[dest] = getattr(node, f) assert values[dest], "Attribute %s of report is empty !" % (f,) for field, dest in ( ("rml", "report_rml"), ("file", "report_rml"), ("xml", "report_xml"), ("xsl", "report_xsl"), ("attachment", "attachment"), ("attachment_use", "attachment_use"), ): if getattr(node, field): values[dest] = getattr(node, field) if node.auto: values["auto"] = eval(node.auto) if node.sxw: sxw_file = misc.file_open(node.sxw) try: sxw_content = sxw_file.read() values["report_sxw_content"] = sxw_content finally: sxw_file.close() if node.header: values["header"] = eval(node.header) values["multi"] = node.multi and eval(node.multi) xml_id = node.id self.validate_xml_id(xml_id) self._set_group_values(node, values) id = self.pool["ir.model.data"]._update( self.cr, SUPERUSER_ID, "ir.actions.report.xml", self.module, values, xml_id, noupdate=self.isnoupdate(node), mode=self.mode, ) self.id_map[xml_id] = int(id) if not node.menu or eval(node.menu): keyword = node.keyword or "client_print_multi" value = "ir.actions.report.xml,%s" % id replace = node.replace or True self.pool["ir.model.data"].ir_set( self.cr, SUPERUSER_ID, "action", keyword, values["name"], [values["model"]], value, replace=replace, isobject=True, xml_id=xml_id, )
def export_code_terms_from_file(fname, path, root, terms_type): fabsolutepath = join(root, fname) frelativepath = fabsolutepath[len(path):] module = get_module_from_path(fabsolutepath, mod_paths=mod_paths) is_mod_installed = module in installed_modules if (('all' in modules) or (module in modules)) and is_mod_installed: _logger.debug("Scanning code of %s at module: %s", frelativepath, module) src_file = misc.file_open(fabsolutepath, subdir='') try: code_string = src_file.read() finally: src_file.close() 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('""'): assert src.endswith( '""' ), "Incorrect usage of _(..) function (should contain only literal strings!) in file %s near: %s" % ( frelativepath, src[:30]) 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, 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("''"): assert src.endswith( "''" ), "Incorrect usage of _(..) function (should contain only literal strings!) in file %s near: %s" % ( frelativepath, src[:30]) 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, code_line, encode(src)) code_line += i.group(1).count('\n') code_offset = i.end( ) # we have counted newlines up to the match end
def f(): time.sleep(delay) cr = None fp = None try: cr = sql_db.db_connect(db_name).cursor() fp = misc.file_open(file_name) convert_yaml_import(cr, module_name, fp, {}, 'update', True) finally: if cr: cr.close() if fp: fp.close()
def trans_load(cr, filename, lang, verbose=True, module_name=None, context=None): try: fileobj = misc.file_open(filename) _logger.info("loading %s", filename) fileformat = os.path.splitext(filename)[-1][1:].lower() result = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context) fileobj.close() return result except IOError: if verbose: _logger.error("couldn't read translation file %s", filename) return None
def _tag_report(self, cr, rec, data_node=None, mode=None): res = {} for dest,f in (('name','string'),('model','model'),('report_name','name')): res[dest] = rec.get(f,'').encode('utf8') assert res[dest], "Attribute %s of report is empty !" % (f,) for field,dest in (('rml','report_rml'),('file','report_rml'),('xml','report_xml'),('xsl','report_xsl'), ('attachment','attachment'),('attachment_use','attachment_use'), ('usage','usage'), ('report_type', 'report_type'), ('parser', 'parser')): if rec.get(field): res[dest] = rec.get(field).encode('utf8') if rec.get('auto'): res['auto'] = eval(rec.get('auto','False')) if rec.get('sxw'): sxw_content = misc.file_open(rec.get('sxw')).read() res['report_sxw_content'] = sxw_content if rec.get('header'): res['header'] = eval(rec.get('header','False')) res['multi'] = rec.get('multi') and eval(rec.get('multi','False')) xml_id = rec.get('id','').encode('utf8') self._test_xml_id(xml_id) if rec.get('groups'): g_names = rec.get('groups','').split(',') groups_value = [] for group in g_names: if group.startswith('-'): group_id = self.id_get(cr, group[1:]) groups_value.append((3, group_id)) else: group_id = self.id_get(cr, group) groups_value.append((4, group_id)) res['groups_id'] = groups_value if rec.get('paperformat'): pf_name = rec.get('paperformat') pf_id = self.id_get(cr,pf_name) res['paperformat_id'] = pf_id id = self.pool['ir.model.data']._update(cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode) self.idref[xml_id] = int(id) if not rec.get('menu') or eval(rec.get('menu','False')): keyword = str(rec.get('keyword', 'client_print_multi')) value = 'ir.actions.report.xml,'+str(id) ir_values_id = self.pool['ir.values'].set_action(cr, self.uid, res['name'], keyword, res['model'], value) self.pool['ir.actions.report.xml'].write(cr, self.uid, id, {'ir_values_id': ir_values_id}) elif self.mode=='update' and eval(rec.get('menu','False'))==False: # Special check for report having attribute menu=False on update value = 'ir.actions.report.xml,'+str(id) self._remove_ir_values(cr, res['name'], value, res['model']) self.pool['ir.actions.report.xml'].write(cr, self.uid, id, {'ir_values_id': False}) return id
def export_code_terms_from_file(fname, path, root, terms_type): fabsolutepath = join(root, fname) frelativepath = fabsolutepath[len(path):] module = get_module_from_path(fabsolutepath, mod_paths=mod_paths) is_mod_installed = module in installed_modules if (('all' in modules) or (module in modules)) and is_mod_installed: _logger.debug("Scanning code of %s at module: %s", frelativepath, module) src_file = misc.file_open(fabsolutepath, subdir='') try: code_string = src_file.read() finally: src_file.close() 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('""'): assert src.endswith('""'), "Incorrect usage of _(..) function (should contain only literal strings!) in file %s near: %s" % (frelativepath, src[:30]) 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, 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("''"): assert src.endswith("''"), "Incorrect usage of _(..) function (should contain only literal strings!) in file %s near: %s" % (frelativepath, src[:30]) 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, code_line, encode(src)) code_line += i.group(1).count('\n') code_offset = i.end() # we have counted newlines up to the match end
def convert_file(cr, module, filename, idref, mode='update', noupdate=False, kind=None, report=None): pathname = os.path.join(module, filename) fp = misc.file_open(pathname) ext = os.path.splitext(filename)[1].lower() try: if ext == '.csv': convert_csv_import(cr, module, pathname, fp.read(), idref, mode, noupdate) elif ext == '.sql': convert_sql_import(cr, fp) elif ext == '.yml': convert_yaml_import(cr, module, fp, kind, idref, mode, noupdate, report) elif ext == '.xml': convert_xml_import(cr, module, fp, idref, mode, noupdate, report) elif ext == '.js': pass # .js files are valid but ignored here. else: _logger.warning("Can't load unknown file type %s.", filename) finally: fp.close()
def convert_file(cr, module, filename, idref, mode="update", noupdate=False, kind=None, report=None, pathname=None): if pathname is None: pathname = os.path.join(module, filename) fp = misc.file_open(pathname) ext = os.path.splitext(filename)[1].lower() try: if ext == ".csv": convert_csv_import(cr, module, pathname, fp.read(), idref, mode, noupdate) elif ext == ".sql": convert_sql_import(cr, fp) elif ext == ".yml": convert_yaml_import(cr, module, fp, kind, idref, mode, noupdate, report) elif ext == ".xml": convert_xml_import(cr, module, fp, idref, mode, noupdate, report) elif ext == ".js": pass # .js files are valid but ignored here. else: raise ValueError("Can't load unknown file type %s.", filename) finally: fp.close()
def trans_generate(lang, modules, cr): dbname = cr.dbname pool = pooler.get_pool(dbname) trans_obj = pool.get('ir.translation') model_data_obj = pool.get('ir.model.data') uid = 1 l = pool.models.items() l.sort() query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules),) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = [] def push_translation(module, type, name, id, source, comments=None): tuple = (module, source, name, id, type, comments or []) # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: _logger.debug("Ignoring empty or 1-letter source term: %r", tuple) return if tuple not in _to_translate: _to_translate.append(tuple) def encode(s): if isinstance(s, unicode): return s.encode('utf8') return s for (xml_name,model,res_id,module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if not pool.get(model): _logger.error("Unable to find object %r", model) continue exists = pool.get(model).exists(cr, uid, res_id) if not exists: _logger.warning("Unable to find object %r with id %d", model, res_id) continue obj = pool.get(model).browse(cr, uid, res_id) if model=='ir.ui.view': d = etree.XML(encode(obj.arch)) for t in trans_parse_view(d): push_translation(module, 'view', encode(obj.model), 0, t) elif model=='ir.actions.wizard': service_name = 'wizard.'+encode(obj.wiz_name) import openerp.netsvc as netsvc if netsvc.Service._services.get(service_name): obj2 = netsvc.Service._services[service_name] for state_name, state_def in obj2.states.iteritems(): if 'result' in state_def: result = state_def['result'] if result['type'] != 'form': continue name = "%s,%s" % (encode(obj.wiz_name), state_name) def_params = { 'string': ('wizard_field', lambda s: [encode(s)]), 'selection': ('selection', lambda s: [encode(e[1]) for e in ((not callable(s)) and s or [])]), 'help': ('help', lambda s: [encode(s)]), } # export fields if not result.has_key('fields'): _logger.warning("res has no fields: %r", result) continue for field_name, field_def in result['fields'].iteritems(): res_name = name + ',' + field_name for fn in def_params: if fn in field_def: transtype, modifier = def_params[fn] for val in modifier(field_def[fn]): push_translation(module, transtype, res_name, 0, val) # export arch arch = result['arch'] if arch and not isinstance(arch, UpdateableStr): d = etree.XML(arch) for t in trans_parse_view(d): push_translation(module, 'wizard_view', name, 0, t) # export button labels for but_args in result['state']: button_name = but_args[0] button_label = but_args[1] res_name = name + ',' + button_name push_translation(module, 'wizard_button', res_name, 0, button_label) elif model=='ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue objmodel = pool.get(obj.model) if not objmodel or not field_name in objmodel._columns: continue field_def = objmodel._columns[field_name] name = "%s,%s" % (encode(obj.model), field_name) push_translation(module, 'field', name, 0, encode(field_def.string)) if field_def.help: push_translation(module, 'help', name, 0, encode(field_def.help)) if field_def.translate: ids = objmodel.search(cr, uid, []) obj_values = objmodel.read(cr, uid, ids, [field_name]) for obj_value in obj_values: res_id = obj_value['id'] if obj.name in ('ir.model', 'ir.ui.menu'): res_id = 0 model_data_ids = model_data_obj.search(cr, uid, [ ('model', '=', model), ('res_id', '=', res_id), ]) if not model_data_ids: push_translation(module, 'model', name, 0, encode(obj_value[field_name])) if hasattr(field_def, 'selection') and isinstance(field_def.selection, (list, tuple)): for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model=='ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: fname = obj.report_xsl parse_func = trans_parse_xsl report_type = "xsl" if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception("couldn't export translation for report %s %s %s", name, report_type, fname)
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.error('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_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry['ir.translation'] model_data_obj = registry['ir.model.data'] uid = 1 query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules),) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = set() def push_translation(module, type, name, id, source, comments=None): # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: return tnx = (module, source, name, id, type, tuple(comments or ())) _to_translate.add(tnx) def encode(s): if isinstance(s, unicode): return s.encode('utf8') return s def push(mod, type, name, res_id, term): term = (term or '').strip() if len(term) > 2 or term in ENGLISH_SMALL_WORDS: push_translation(mod, type, name, res_id, term) def get_root_view(xml_id): view = model_data_obj.xmlid_to_object(cr, uid, xml_id) if view: while view.mode != 'primary': view = view.inherit_id xml_id = view.get_external_id(cr, uid).get(view.id, xml_id) return xml_id for (xml_name,model,res_id,module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue Model = registry[model] if not Model._translate: # explicitly disabled continue obj = Model.browse(cr, uid, res_id) if not obj.exists(): _logger.warning("Unable to find object %r with id %d", model, res_id) continue if model=='ir.ui.view': d = etree.XML(encode(obj.arch)) if obj.type == 'qweb': view_id = get_root_view(xml_name) push_qweb = lambda t,l: push(module, 'view', 'website', view_id, t) _extract_translatable_qweb_terms(d, push_qweb) else: push_view = lambda t,l: push(module, 'view', obj.model, xml_name, t) trans_parse_view(d, push_view) elif model=='ir.actions.wizard': pass # TODO Can model really be 'ir.actions.wizard' ? elif model=='ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue objmodel = registry.get(obj.model) if (objmodel is None or field_name not in objmodel._columns or not objmodel._translate): continue field_def = objmodel._columns[field_name] name = "%s,%s" % (encode(obj.model), field_name) push_translation(module, 'field', name, 0, encode(field_def.string)) if field_def.help: push_translation(module, 'help', name, 0, encode(field_def.help)) if field_def.translate: ids = objmodel.search(cr, uid, []) obj_values = objmodel.read(cr, uid, ids, [field_name]) for obj_value in obj_values: res_id = obj_value['id'] if obj.name in ('ir.model', 'ir.ui.menu'): res_id = 0 model_data_ids = model_data_obj.search(cr, uid, [ ('model', '=', model), ('res_id', '=', res_id), ]) if not model_data_ids: push_translation(module, 'model', name, 0, encode(obj_value[field_name])) if hasattr(field_def, 'selection') and isinstance(field_def.selection, (list, tuple)): for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model=='ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: fname = obj.report_xsl parse_func = trans_parse_xsl report_type = "xsl" if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception("couldn't export translation for report %s %s %s", name, report_type, fname)
def trans_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry.get('ir.translation') model_data_obj = registry.get('ir.model.data') uid = 1 l = registry.models.items() l.sort() query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules), ) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = [] def push_translation(module, type, name, id, source, comments=None): tuple = (module, source, name, id, type, comments or []) # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: _logger.debug("Ignoring empty or 1-letter source term: %r", tuple) return if tuple not in _to_translate: _to_translate.append(tuple) def encode(s): if isinstance(s, unicode): return s.encode('utf8') return s for (xml_name, model, res_id, module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue exists = registry[model].exists(cr, uid, res_id) if not exists: _logger.warning("Unable to find object %r with id %d", model, res_id) continue obj = registry[model].browse(cr, uid, res_id) if model == 'ir.ui.view': d = etree.XML(encode(obj.arch)) for t in trans_parse_view(d): push_translation(module, 'view', encode(obj.model), 0, t) elif model == 'ir.actions.wizard': pass # TODO Can model really be 'ir.actions.wizard' ? elif model == 'ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue objmodel = registry[obj.model] if not objmodel or not field_name in objmodel._columns: continue field_def = objmodel._columns[field_name] name = "%s,%s" % (encode(obj.model), field_name) push_translation(module, 'field', name, 0, encode(field_def.string)) if field_def.help: push_translation(module, 'help', name, 0, encode(field_def.help)) if field_def.translate: ids = objmodel.search(cr, uid, []) obj_values = objmodel.read(cr, uid, ids, [field_name]) for obj_value in obj_values: res_id = obj_value['id'] if obj.name in ('ir.model', 'ir.ui.menu'): res_id = 0 model_data_ids = model_data_obj.search( cr, uid, [ ('model', '=', model), ('res_id', '=', res_id), ]) if not model_data_ids: push_translation(module, 'model', name, 0, encode(obj_value[field_name])) if hasattr(field_def, 'selection') and isinstance( field_def.selection, (list, tuple)): for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model == 'ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: fname = obj.report_xsl parse_func = trans_parse_xsl report_type = "xsl" if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception( "couldn't export translation for report %s %s %s", name, report_type, fname)
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 _tag_report(self, cr, rec, data_node=None): res = {} for dest, f in (("name", "string"), ("model", "model"), ("report_name", "name")): res[dest] = rec.get(f, "").encode("utf8") assert res[dest], "Attribute %s of report is empty !" % (f,) for field, dest in ( ("rml", "report_rml"), ("file", "report_rml"), ("xml", "report_xml"), ("xsl", "report_xsl"), ("attachment", "attachment"), ("attachment_use", "attachment_use"), ("usage", "usage"), ): if rec.get(field): res[dest] = rec.get(field).encode("utf8") if rec.get("auto"): res["auto"] = eval(rec.get("auto", "False")) if rec.get("sxw"): sxw_content = misc.file_open(rec.get("sxw")).read() res["report_sxw_content"] = sxw_content if rec.get("header"): res["header"] = eval(rec.get("header", "False")) if rec.get("report_type"): res["report_type"] = rec.get("report_type") res["multi"] = rec.get("multi") and eval(rec.get("multi", "False")) xml_id = rec.get("id", "").encode("utf8") self._test_xml_id(xml_id) if rec.get("groups"): g_names = rec.get("groups", "").split(",") groups_value = [] for group in g_names: if group.startswith("-"): group_id = self.id_get(cr, group[1:]) groups_value.append((3, group_id)) else: group_id = self.id_get(cr, group) groups_value.append((4, group_id)) res["groups_id"] = groups_value id = self.pool.get("ir.model.data")._update( cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode, ) self.idref[xml_id] = int(id) if not rec.get("menu") or eval(rec.get("menu", "False")): keyword = str(rec.get("keyword", "client_print_multi")) value = "ir.actions.report.xml," + str(id) replace = rec.get("replace", True) self.pool.get("ir.model.data").ir_set( cr, self.uid, "action", keyword, res["name"], [res["model"]], value, replace=replace, isobject=True, xml_id=xml_id, ) elif self.mode == "update" and eval(rec.get("menu", "False")) == False: # Special check for report having attribute menu=False on update value = "ir.actions.report.xml," + str(id) self._remove_ir_values(cr, res["name"], value, res["model"]) return id
def trans_generate(lang, modules, cr): dbname = cr.dbname pool = pooler.get_pool(dbname) trans_obj = pool.get('ir.translation') model_data_obj = pool.get('ir.model.data') uid = 1 l = pool.models.items() l.sort() query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules), ) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = [] def push_translation(module, type, name, id, source, comments=None): tuple = (module, source, name, id, type, comments or []) # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: _logger.debug("Ignoring empty or 1-letter source term: %r", tuple) return if tuple not in _to_translate: _to_translate.append(tuple) def encode(s): if isinstance(s, unicode): return s.encode('utf8') return s for (xml_name, model, res_id, module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if not pool.get(model): _logger.error("Unable to find object %r", model) continue exists = pool.get(model).exists(cr, uid, res_id) if not exists: _logger.warning("Unable to find object %r with id %d", model, res_id) continue obj = pool.get(model).browse(cr, uid, res_id) if model == 'ir.ui.view': d = etree.XML(encode(obj.arch)) for t in trans_parse_view(d): push_translation(module, 'view', encode(obj.model), 0, t) elif model == 'ir.actions.wizard': service_name = 'wizard.' + encode(obj.wiz_name) import openerp.netsvc as netsvc if netsvc.Service._services.get(service_name): obj2 = netsvc.Service._services[service_name] for state_name, state_def in obj2.states.iteritems(): if 'result' in state_def: result = state_def['result'] if result['type'] != 'form': continue name = "%s,%s" % (encode(obj.wiz_name), state_name) def_params = { 'string': ('wizard_field', lambda s: [encode(s)]), 'selection': ('selection', lambda s: [ encode(e[1]) for e in ((not callable(s)) and s or []) ]), 'help': ('help', lambda s: [encode(s)]), } # export fields if not result.has_key('fields'): _logger.warning("res has no fields: %r", result) continue for field_name, field_def in result[ 'fields'].iteritems(): res_name = name + ',' + field_name for fn in def_params: if fn in field_def: transtype, modifier = def_params[fn] for val in modifier(field_def[fn]): push_translation( module, transtype, res_name, 0, val) # export arch arch = result['arch'] if arch and not isinstance(arch, UpdateableStr): d = etree.XML(arch) for t in trans_parse_view(d): push_translation(module, 'wizard_view', name, 0, t) # export button labels for but_args in result['state']: button_name = but_args[0] button_label = but_args[1] res_name = name + ',' + button_name push_translation(module, 'wizard_button', res_name, 0, button_label) elif model == 'ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue objmodel = pool.get(obj.model) if not objmodel or not field_name in objmodel._columns: continue field_def = objmodel._columns[field_name] name = "%s,%s" % (encode(obj.model), field_name) push_translation(module, 'field', name, 0, encode(field_def.string)) if field_def.help: push_translation(module, 'help', name, 0, encode(field_def.help)) if field_def.translate: ids = objmodel.search(cr, uid, []) obj_values = objmodel.read(cr, uid, ids, [field_name]) for obj_value in obj_values: res_id = obj_value['id'] if obj.name in ('ir.model', 'ir.ui.menu'): res_id = 0 model_data_ids = model_data_obj.search( cr, uid, [ ('model', '=', model), ('res_id', '=', res_id), ]) if not model_data_ids: push_translation(module, 'model', name, 0, encode(obj_value[field_name])) if hasattr(field_def, 'selection') and isinstance( field_def.selection, (list, tuple)): for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model == 'ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: fname = obj.report_xsl parse_func = trans_parse_xsl report_type = "xsl" if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception( "couldn't export translation for report %s %s %s", name, report_type, fname)
def _tag_report(self, cr, rec, data_node=None): res = {} for dest, f in (('name', 'string'), ('model', 'model'), ('report_name', 'name')): res[dest] = rec.get(f, '').encode('utf8') assert res[dest], "Attribute %s of report is empty !" % (f, ) for field, dest in (('rml', 'report_rml'), ('file', 'report_rml'), ('xml', 'report_xml'), ('xsl', 'report_xsl'), ('attachment', 'attachment'), ('attachment_use', 'attachment_use')): if rec.get(field): res[dest] = rec.get(field).encode('utf8') if rec.get('auto'): res['auto'] = eval(rec.get('auto', 'False')) if rec.get('sxw'): sxw_content = misc.file_open(rec.get('sxw')).read() res['report_sxw_content'] = sxw_content if rec.get('header'): res['header'] = eval(rec.get('header', 'False')) if rec.get('report_type'): res['report_type'] = rec.get('report_type') res['multi'] = rec.get('multi') and eval(rec.get('multi', 'False')) xml_id = rec.get('id', '').encode('utf8') self._test_xml_id(xml_id) if rec.get('groups'): g_names = rec.get('groups', '').split(',') groups_value = [] # groups_obj = self.pool.get('res.groups') for group in g_names: if group.startswith('-'): group_id = self.id_get(cr, group[1:]) groups_value.append((3, group_id)) else: group_id = self.id_get(cr, group) groups_value.append((4, group_id)) res['groups_id'] = groups_value id = self.pool.get('ir.model.data')._update( cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode, context=self.context) self.idref[xml_id] = int(id) if not rec.get('menu') or eval(rec.get('menu', 'False')): keyword = str(rec.get('keyword', 'client_print_multi')) # keys = [('action',keyword),('res_model',res['model'])] value = 'ir.actions.report.xml,' + str(id) replace = rec.get('replace', True) self.pool.get('ir.model.data').ir_set(cr, self.uid, 'action', keyword, res['name'], [res['model']], value, replace=replace, isobject=True, xml_id=xml_id) elif self.mode == 'update' and eval(rec.get('menu', 'False')) == False: # Special check for report having attribute menu=False on update value = 'ir.actions.report.xml,' + str(id) self._remove_ir_values(cr, res['name'], value, res['model']) return False
def trans_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry["ir.translation"] model_data_obj = registry["ir.model.data"] uid = 1 query = "SELECT name, model, res_id, module" " FROM ir_model_data" query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if "all_installed" in modules: query += " WHERE module IN ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if "all" not in modules: query += " WHERE module IN %s" query_models += " AND imd.module in %s" query_param = (tuple(modules),) query += " ORDER BY module, model, name" query_models += " ORDER BY module, model" cr.execute(query, query_param) _to_translate = set() def push_translation(module, type, name, id, source, comments=None): # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: return tnx = (module, source, name, id, type, tuple(comments or ())) _to_translate.add(tnx) def encode(s): if isinstance(s, unicode): return s.encode("utf8") return s def push(mod, type, name, res_id, term): term = (term or "").strip() if len(term) > 2 or term in ENGLISH_SMALL_WORDS: push_translation(mod, type, name, res_id, term) def get_root_view(xml_id): view = model_data_obj.xmlid_to_object(cr, uid, xml_id) if view: while view.mode != "primary": view = view.inherit_id xml_id = view.get_external_id(cr, uid).get(view.id, xml_id) return xml_id for (xml_name, model, res_id, module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue Model = registry[model] if not Model._translate: # explicitly disabled continue obj = Model.browse(cr, uid, res_id) if not obj.exists(): _logger.warning("Unable to find object %r with id %d", model, res_id) continue if model == "ir.ui.view": d = etree.XML(encode(obj.arch)) if obj.type == "qweb": view_id = get_root_view(xml_name) push_qweb = lambda t, l: push(module, "view", "website", view_id, t) _extract_translatable_qweb_terms(d, push_qweb) else: push_view = lambda t, l: push(module, "view", obj.model, xml_name, t) trans_parse_view(d, push_view) elif model == "ir.actions.wizard": pass # TODO Can model really be 'ir.actions.wizard' ? elif model == "ir.model.fields": try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue objmodel = registry.get(obj.model) if objmodel is None or field_name not in objmodel._columns or not objmodel._translate: continue field_def = objmodel._columns[field_name] name = "%s,%s" % (encode(obj.model), field_name) push_translation(module, "field", name, 0, encode(field_def.string)) if field_def.help: push_translation(module, "help", name, 0, encode(field_def.help)) if field_def.translate: ids = objmodel.search(cr, uid, []) obj_values = objmodel.read(cr, uid, ids, [field_name]) for obj_value in obj_values: res_id = obj_value["id"] if obj.name in ("ir.model", "ir.ui.menu"): res_id = 0 model_data_ids = model_data_obj.search(cr, uid, [("model", "=", model), ("res_id", "=", res_id)]) if not model_data_ids: push_translation(module, "model", name, 0, encode(obj_value[field_name])) if hasattr(field_def, "selection") and isinstance(field_def.selection, (list, tuple)): for dummy, val in field_def.selection: push_translation(module, "selection", name, 0, encode(val)) elif model == "ir.actions.report.xml": name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: fname = obj.report_xsl parse_func = trans_parse_xsl report_type = "xsl" if fname and obj.report_type in ("pdf", "xsl"): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception("couldn't export translation for report %s %s %s", name, report_type, fname)
def trans_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry["ir.translation"] model_data_obj = registry["ir.model.data"] uid = 1 query = "SELECT name, model, res_id, module" " FROM ir_model_data" query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if "all_installed" in modules: query += " WHERE module IN ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if "all" not in modules: query += " WHERE module IN %s" query_models += " AND imd.module in %s" query_param = (tuple(modules),) query += " ORDER BY module, model, name" query_models += " ORDER BY module, model" cr.execute(query, query_param) _to_translate = set() def push_translation(module, type, name, id, source, comments=None): # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. sanitized_term = (source or "").strip() try: # verify the minimal size without eventual xml tags # wrap to make sure html content like '<a>b</a><c>d</c>' is accepted by lxml wrapped = "<div>%s</div>" % sanitized_term node = etree.fromstring(wrapped) sanitized_term = etree.tostring(node, encoding="UTF-8", method="text") except etree.ParseError: pass # remove non-alphanumeric chars sanitized_term = re.sub(r"\W+", "", sanitized_term) if not sanitized_term or len(sanitized_term) <= 1: return tnx = (module, source, name, id, type, tuple(comments or ())) _to_translate.add(tnx) def push(mod, type, name, res_id, term): term = (term or "").strip() if len(term) > 2 or term in ENGLISH_SMALL_WORDS: push_translation(mod, type, name, res_id, term) def get_root_view(xml_id): view = model_data_obj.xmlid_to_object(cr, uid, xml_id) if view: while view.mode != "primary": view = view.inherit_id xml_id = view.get_external_id(cr, uid).get(view.id, xml_id) return xml_id for (xml_name, model, res_id, module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue Model = registry[model] if not Model._translate: # explicitly disabled continue obj = Model.browse(cr, uid, res_id) if not obj.exists(): _logger.warning("Unable to find object %r with id %d", model, res_id) continue if model == "ir.model.fields": try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue field_model = registry.get(obj.model) if field_model is None or not field_model._translate or field_name not in field_model._fields: continue field_def = field_model._fields[field_name] if hasattr(field_def, "selection") and isinstance(field_def.selection, (list, tuple)): name = "%s,%s" % (encode(obj.model), field_name) for dummy, val in field_def.selection: push_translation(module, "selection", name, 0, encode(val)) elif model == "ir.actions.report.xml": name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: continue if fname and obj.report_type in ("pdf", "xsl"): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception("couldn't export translation for report %s %s %s", name, report_type, fname)
def trans_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry.get('ir.translation') model_data_obj = registry.get('ir.model.data') uid = 1 l = registry.models.items() l.sort() query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules), ) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = [] def push_translation(module, type, name, id, source, comments=None): tuple = (module, source, name, id, type, comments or []) # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: _logger.debug("Ignoring empty or 1-letter source term: %r", tuple) return if tuple not in _to_translate: _to_translate.append(tuple) def encode(s): if isinstance(s, unicode): return s.encode('utf8') return s for (xml_name, model, res_id, module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue exists = registry[model].exists(cr, uid, res_id) if not exists: _logger.warning("Unable to find object %r with id %d", model, res_id) continue obj = registry[model].browse(cr, uid, res_id) if model == 'ir.ui.view': d = etree.XML(encode(obj.arch)) for t in trans_parse_view(d): push_translation(module, 'view', encode(obj.model), 0, t) elif model == 'ir.actions.wizard': pass # TODO Can model really be 'ir.actions.wizard' ? elif model == 'ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue objmodel = registry.get(obj.model) if not objmodel or not field_name in objmodel._columns: continue field_def = objmodel._columns[field_name] name = "%s,%s" % (encode(obj.model), field_name) push_translation(module, 'field', name, 0, encode(field_def.string)) if field_def.help: push_translation(module, 'help', name, 0, encode(field_def.help)) if field_def.translate: ids = objmodel.search(cr, uid, []) obj_values = objmodel.read(cr, uid, ids, [field_name]) for obj_value in obj_values: res_id = obj_value['id'] if obj.name in ('ir.model', 'ir.ui.menu'): res_id = 0 model_data_ids = model_data_obj.search( cr, uid, [ ('model', '=', model), ('res_id', '=', res_id), ]) if not model_data_ids: push_translation(module, 'model', name, 0, encode(obj_value[field_name])) if hasattr(field_def, 'selection') and isinstance( field_def.selection, (list, tuple)): for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model == 'ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: fname = obj.report_xsl parse_func = trans_parse_xsl report_type = "xsl" if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception( "couldn't export translation for report %s %s %s", name, report_type, fname)
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_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry['ir.translation'] model_data_obj = registry['ir.model.data'] uid = 1 query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules),) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = set() def push_translation(module, type, name, id, source, comments=None): # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. if not source or len(source.strip()) <= 1: return tnx = (module, source, name, id, type, tuple(comments or ())) _to_translate.add(tnx) def push(mod, type, name, res_id, term): term = (term or '').strip() if len(term) > 2 or term in ENGLISH_SMALL_WORDS: push_translation(mod, type, name, res_id, term) def get_root_view(xml_id): view = model_data_obj.xmlid_to_object(cr, uid, xml_id) if view: while view.mode != 'primary': view = view.inherit_id xml_id = view.get_external_id(cr, uid).get(view.id, xml_id) return xml_id for (xml_name,model,res_id,module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue Model = registry[model] if not Model._translate: # explicitly disabled continue obj = Model.browse(cr, uid, res_id) if not obj.exists(): _logger.warning("Unable to find object %r with id %d", model, res_id) continue if model=='ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue field_model = registry.get(obj.model) if (field_model is None or not field_model._translate or field_name not in field_model._fields): continue field_def = field_model._fields[field_name] if hasattr(field_def, 'selection') and isinstance(field_def.selection, (list, tuple)): name = "%s,%s" % (encode(obj.model), field_name) for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model=='ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: continue if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception("couldn't export translation for report %s %s %s", name, report_type, fname)
def _tag_report(self, cr, rec, data_node=None, mode=None): res = {} #funkring.net begin report_type = rec.get('report_type') is_aeroo_report = report_type and report_type == "aeroo" if is_aeroo_report: res["tml_source"] = "file" res["parser_state"] = "loc" res["styles_mode"] = "global" res["active"] = True res["stylesheet_id"] = None for dest, f in (('in_format', 'in_format'), ('out_format', 'out_format')): res[dest] = rec.get(f, '').encode('utf8') assert res[dest], "Attribute %s of report is empty !" % (f, ) if dest == 'out_format': t_outFormatCode = res[dest] t_ids = self.pool.get('report.mimetypes').search( cr, self.uid, [('code', '=', t_outFormatCode)]) if t_ids: res[dest] = t_ids[0] else: assert res[ dest], "Output format %s of report not found !" % ( f, ) #funkring.net end for dest, f in (('name', 'string'), ('model', 'model'), ('report_name', 'name')): res[dest] = rec.get(f, '').encode('utf8') assert res[dest], "Attribute %s of report is empty !" % (f, ) for field, dest in ( ('rml', 'report_rml'), ('file', 'report_rml'), ('xml', 'report_xml'), ('xsl', 'report_xsl'), ('attachment', 'attachment'), ('attachment_use', 'attachment_use'), ('usage', 'usage'), #funkring.net begin // aeroo report specific ('parser', 'parser_loc'), ('parser_state', 'parser_state'), ('stylesheet', 'styles_mode'), ('process_sep', 'process_sep'), #funkring.net end ('report_type', 'report_type'), ('parser', 'parser')): if rec.get(field): #funkring.net begin if field == "stylesheet": value = rec.get(field).encode('utf8') value_lower = value.lower() if value_lower in ["none", "default"]: res[dest] = "default" elif value_lower in [ "global", "global_landscape", "intern", "intern_landscape" ]: res[dest] = value_lower else: res[dest] = "specified" stylesheet_ids = self.pool.get( "report.stylesheets").search( cr, self.uid, [("name", "=", value)]) assert stylesheet_ids, "Stylesheet %s not found!" % ( value, ) res["stylesheet_id"] = stylesheet_ids[0] elif field == "process_sep": res["process_sep"] = eval(rec.get('process_sep', 'False')) else: res[dest] = rec.get(field).encode('utf8') #funkrnig.net end if rec.get('auto'): res['auto'] = safe_eval(rec.get('auto', 'False')) if rec.get('sxw'): sxw_content = misc.file_open(rec.get('sxw')).read() res['report_sxw_content'] = sxw_content if rec.get('header'): res['header'] = safe_eval(rec.get('header', 'False')) res['multi'] = rec.get('multi') and safe_eval(rec.get( 'multi', 'False')) xml_id = rec.get('id', '').encode('utf8') self._test_xml_id(xml_id) if rec.get('groups'): g_names = rec.get('groups', '').split(',') groups_value = [] for group in g_names: if group.startswith('-'): group_id = self.id_get(cr, group[1:]) groups_value.append((3, group_id)) else: group_id = self.id_get(cr, group) groups_value.append((4, group_id)) res['groups_id'] = groups_value #funkring.net begin // aeroo report specific full_xml_id = xml_id if not "." in full_xml_id: full_xml_id = "%s.%s" % (self.module, xml_id) report_rec = self.pool['ir.model.data'].xmlid_to_object( cr, self.uid, full_xml_id, raise_if_not_found=False) if report_rec and report_rec.report_type in ( "qweb-pdf", "aeroo") and hasattr( report_rec, "user_defined") and report_rec.user_defined: res["tml_source"] = report_rec.tml_source res["parser_state"] = report_rec.parser_state if report_rec.styles_mode == "specified": res["styles_mode"] = "specified" res["stylesheet_id"] = report_rec.stylesheet_id.id #funkring.net end id = self.pool['ir.model.data']._update( cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode) self.idref[xml_id] = int(id) if not rec.get('menu') or safe_eval(rec.get('menu', 'False')): keyword = str(rec.get('keyword', 'client_print_multi')) value = 'ir.actions.report.xml,' + str(id) replace = rec.get('replace', True) self.pool['ir.model.data'].ir_set(cr, self.uid, 'action', keyword, res['name'], [res['model']], value, replace=replace, isobject=True, xml_id=xml_id) elif self.mode == 'update' and safe_eval(rec.get('menu', 'False')) == False: # Special check for report having attribute menu=False on update value = 'ir.actions.report.xml,' + str(id) self._remove_ir_values(cr, res['name'], value, res['model']) return id
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)
import fparser import misc as appmisc import sys # make sure this file is being run directly if __name__ == '__main__': if len(sys.argv) == 1: appmisc.usage(sys.argv[0]) exit(1) else: file = appmisc.file_open(sys.argv[1]) if (file != None): appparser = fparser.Parser(file) appparser.parse() appmisc.file_close(file) else: appmisc.print_err("{}: no such file or directory".format(sys.argv[1])) exit(1) pass
def trans_generate(lang, modules, cr): dbname = cr.dbname registry = openerp.registry(dbname) trans_obj = registry['ir.translation'] model_data_obj = registry['ir.model.data'] uid = 1 query = 'SELECT name, model, res_id, module' \ ' FROM ir_model_data' query_models = """SELECT m.id, m.model, imd.module FROM ir_model AS m, ir_model_data AS imd WHERE m.id = imd.res_id AND imd.model = 'ir.model' """ if 'all_installed' in modules: query += ' WHERE module IN ( SELECT name FROM ir_module_module WHERE state = \'installed\') ' query_models += " AND imd.module in ( SELECT name FROM ir_module_module WHERE state = 'installed') " query_param = None if 'all' not in modules: query += ' WHERE module IN %s' query_models += ' AND imd.module in %s' query_param = (tuple(modules), ) query += ' ORDER BY module, model, name' query_models += ' ORDER BY module, model' cr.execute(query, query_param) _to_translate = set() def push_translation(module, type, name, id, source, comments=None): # empty and one-letter terms are ignored, they probably are not meant to be # translated, and would be very hard to translate anyway. sanitized_term = (source or '').strip() try: # verify the minimal size without eventual xml tags # wrap to make sure html content like '<a>b</a><c>d</c>' is accepted by lxml wrapped = "<div>%s</div>" % sanitized_term node = etree.fromstring(wrapped) sanitized_term = etree.tostring(node, encoding='UTF-8', method='text') except etree.ParseError: pass # remove non-alphanumeric chars sanitized_term = re.sub(r'\W+', '', sanitized_term) if not sanitized_term or len(sanitized_term) <= 1: return tnx = (module, source, name, id, type, tuple(comments or ())) _to_translate.add(tnx) def push(mod, type, name, res_id, term): term = (term or '').strip() if len(term) > 2 or term in ENGLISH_SMALL_WORDS: push_translation(mod, type, name, res_id, term) def get_root_view(xml_id): view = model_data_obj.xmlid_to_object(cr, uid, xml_id) if view: while view.mode != 'primary': view = view.inherit_id xml_id = view.get_external_id(cr, uid).get(view.id, xml_id) return xml_id for (xml_name, model, res_id, module) in cr.fetchall(): module = encode(module) model = encode(model) xml_name = "%s.%s" % (module, encode(xml_name)) if model not in registry: _logger.error("Unable to find object %r", model) continue Model = registry[model] if not Model._translate: # explicitly disabled continue obj = Model.browse(cr, uid, res_id) if not obj.exists(): _logger.warning("Unable to find object %r with id %d", model, res_id) continue if model == 'ir.model.fields': try: field_name = encode(obj.name) except AttributeError, exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue field_model = registry.get(obj.model) if (field_model is None or not field_model._translate or field_name not in field_model._fields): continue field_def = field_model._fields[field_name] if hasattr(field_def, 'selection') and isinstance( field_def.selection, (list, tuple)): name = "%s,%s" % (encode(obj.model), field_name) for dummy, val in field_def.selection: push_translation(module, 'selection', name, 0, encode(val)) elif model == 'ir.actions.report.xml': name = encode(obj.report_name) fname = "" if obj.report_rml: fname = obj.report_rml parse_func = trans_parse_rml report_type = "report" elif obj.report_xsl: continue if fname and obj.report_type in ('pdf', 'xsl'): try: report_file = misc.file_open(fname) try: d = etree.parse(report_file) for t in parse_func(d.iter()): push_translation(module, report_type, name, 0, t) finally: report_file.close() except (IOError, etree.XMLSyntaxError): _logger.exception( "couldn't export translation for report %s %s %s", name, report_type, fname)