############################################################################## # # Copyright (c) 2004-2005 TINY SPRL. (http://tiny.be) All Rights Reserved. # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## import csv, xml.dom, re, os import osv, tools, sql_db import convert import ir import netsvc _cache_source = {} _cache = {} # # TODO: a caching method # def translate(cr, uid, name, tt, lang, source=None, res_ids=None): if source: cr.execute('select value from ir_translation where lang=%s and type=%s and name=%s and src=%s', (lang, tt, str(name), source)) else: cr.execute('select value from ir_translation where lang=%s and type=%s and name=%s', (lang, tt, str(name))) res_trans = cr.fetchone() if res_trans: return res_trans[0] return False def trans_parse_xsl(out, name, de, lang, cr, uid): pool = osv.osv.osv_pools for n in [i for i in de.childNodes if (i.nodeType == i.ELEMENT_NODE)]: if n.hasAttribute("t"): for m in [j for j in n.childNodes if (j.nodeType == j.TEXT_NODE)]: l = m.data.strip().replace('\n',' ') if len(l): res = pool.get('ir.translation')._get_source(cr,uid,name,'xsl',lang,l.encode('utf8')) or '' out.append(["xsl",name,"0",l.encode("utf8"),res]) trans_parse_xsl(out,name,n,lang,cr,uid) def trans_parse_rml(out, name, de, lang, cr, uid): pool = osv.osv.osv_pools for n in [i for i in de.childNodes if (i.nodeType == i.ELEMENT_NODE)]: for m in [j for j in n.childNodes if (j.nodeType == j.TEXT_NODE)]: string = m.data.strip().replace('\n',' ') string_list = [s.strip() for s in re.split('\[\[.+?\]\]', string)] for s in string_list: if len(s): res = pool.get('ir.translation')._get_source(cr, uid, name, 'rml', lang, s.encode('utf8')) or '' out.append(["rml", name, "0", s.encode("utf8"), res]) trans_parse_rml(out, name, n, lang, cr, uid) def trans_parse_view(out, name, de, lang, cr, uid): pool = osv.osv.osv_pools if de.hasAttribute("string"): res = de.getAttribute('string') if res: res2 = pool.get('ir.translation')._get_source(cr,uid,name,'view',lang,res.encode('utf8')) or '' out.append(["view",name,"0",res.encode("utf8"),res2]) for n in [i for i in de.childNodes if (i.nodeType == i.ELEMENT_NODE)]: trans_parse_view(out,name,n,lang,cr,uid) # tests whether an object is in a list of modules def in_modules(object_name, modules): if 'all' in modules: return True module_dict = { 'ir': 'base', 'res': 'base', 'workflow': 'base', } module = object_name.split('.')[0] module = module_dict.get(module, module) return module in modules def trans_generate(filename, lang, modules): pool = osv.osv.osv_pools cr = sql_db.db.cursor() uid = 1 l = pool.obj_pool.items() l.sort() out = [["type","name","res_id","src","value"]] # object fields for (obj_name,obj) in l: if in_modules(obj_name, modules): for (k,v) in obj._columns.items(): name = obj_name + "," + k value = "" if lang: cr.execute("SELECT * FROM ir_translation WHERE type='field' AND name=%s AND lang=%s", (name,lang)) res = cr.dictfetchall() if len(res): value = res[0]['value'] out.append(["field", name, "0", v.string.encode('utf8'), value]) if v.translate: aaa = osv.orm.orm.search(obj,cr,uid,[]) ici = obj.read(cr,uid,aaa,[k]) cr.execute('select count(*) from '+obj._table) for i in ici: value = "" if lang: cr.execute("SELECT * FROM ir_translation WHERE type='model' AND name=%s AND res_id=%d AND lang=%s",(name,i['id'],lang)) res = cr.dictfetchall() if len(res): value = res[0]['value'] out.append(["model", name, i['id'], i[k], value]) if hasattr(v,'selection') and (type(v.selection)==type([]) or type(v.selection)==type(())): for (key,val) in v.selection: val2 = pool.get('ir.translation')._get_source(cr, uid, name, 'selection', lang, val) out.append(["selection", name, '0', val.encode('utf8'), val2 or '']) # reports (xsl and rml) obj = pool.get("ir.actions.report.xml") for i in obj.read(cr, uid, osv.orm.orm.search(obj, cr, uid, [])): if in_modules(i["model"], modules): name = i["report_name"] if i["report_rml"]: try: xmlstr = tools.file_open(i["report_rml"]).read() d = xml.dom.minidom.parseString(xmlstr) de = d.documentElement trans_parse_rml(out, name, de, lang, cr, uid) except IOError: pass if i["report_xsl"]: try: xmlstr = tools.file_open(i["report_xsl"]).read() d = xml.dom.minidom.parseString(xmlstr) de = d.documentElement trans_parse_xsl(out, name, de, lang, cr, uid) except IOError: pass # views obj = pool.get("ir.ui.view") for i in obj.read(cr, uid, osv.orm.orm.search(obj, cr, uid, [])): if in_modules(i["model"], modules): d = xml.dom.minidom.parseString(i['arch']) de = d.documentElement trans_parse_view(out, i['model'], de, lang, cr, uid) # write output writer = csv.writer(file(filename, "w")) for row in out: writer.writerow(row) cr.close() def trans_load(filename, lang, strict=False): logger = netsvc.Logger() logger.notifyChannel("init", netsvc.LOG_INFO, 'loading translation file for language %s from %s' % (lang, filename)) try: uid = 1 cr = sql_db.db.cursor() cr.execute('delete from ir_translation where lang=%s', (lang,)) pool = osv.osv.osv_pools ids = pool.get('res.lang').search(cr, uid, [('code','=',lang)]) if not ids: ids = pool.get('res.lang').create(cr, uid, {'code':lang,'name':lang,'translatable':1}) else: pool.get('res.lang').write(cr, uid, ids, {'translatable':1}) lang_ids = pool.get('res.lang').search(cr, uid, []) langs = pool.get('res.lang').read(cr, uid, lang_ids) ls = map(lambda x: (x['code'],x['name']), langs) ir.ir_set(cr, uid, 'meta', 'lang', 'lang', [('res.users',False,)], 'en', True, False, meta = {'type':'selection', 'string':'Language', 'selection':ls}) reader = csv.reader(file(filename,'r').read().split('\n')) # read the first line of the file (it contains columns titles) for row in reader: f = row break # read the rest of the file i5 =1 for row in reader: i5 += 1 try: if (not row) or (not row[4]): 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 pool.get('ir.translation')._columns[f[i]]._type=='integer': row[i] = row[i] and int(row[i]) or False dic[f[i]] = row[i] if dic['type']=='model' and not strict: (model,field) = dic['name'].split(',') # get the ids of the ressources of this model which share # the same source obj = pool.get(model) ids = osv.orm.orm.search(obj,cr,uid,[(field,'=',dic['src'])]) # if the ressource id (res_id) is in that list, use it, otherwise use the whole list #CHECKME: #Ged> maybe, we should never use the whole list and only use the res_id if it is in the list but then # if a ressource id has changed (for example menu items), the translation will fail. for id in (dic['res_id'] in ids) and [dic['res_id']] or ids: dic['res_id'] = id try: pool.get('ir.translation').create(cr,uid,dic) except Exception, e: print "ImportError ", e, ' in ', row else: try: pool.get('ir.translation').create(cr,uid,dic) except Exception, e: print "ImportError ", e ,' in ',row except: print 'Error on line %d !' % (i5,) cr.commit() cr.close() logger.notifyChannel("init", netsvc.LOG_INFO, 'translation file loaded succesfully') except IOError: logger.notifyChannel("init", netsvc.LOG_ERROR, "couldn't read file")