[FIX] Gengo - Update modoel ir_translation for gengo and make it working. Works with order and not job, because when you send a batch to translate, you don't know all the job but only the order.
This commit is contained in:
parent
65f68c1f65
commit
18bb52ee88
|
@ -1,22 +1,53 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import openerp
|
import openerp
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.addons.web import http
|
from openerp.addons.web import http
|
||||||
from openerp.addons.web.http import request
|
from openerp.addons.web.http import request
|
||||||
|
|
||||||
|
from werkzeug.wrappers import BaseResponse as Response
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
class website_gengo(http.Controller):
|
class website_gengo(http.Controller):
|
||||||
|
|
||||||
|
def get_gengo_key(self, cr):
|
||||||
|
icp = request.registry['ir.config_parameter']
|
||||||
|
return icp.get_param(cr, SUPERUSER_ID, request.registry['base.gengo.translations'].GENGO_KEY, default="")
|
||||||
|
|
||||||
@http.route('/website/gengo_callback', type='http', auth='none')
|
@http.route('/website/gengo_callback', type='http', auth='none')
|
||||||
def gengo_callback(self,**post):
|
def gengo_callback(self, **post):
|
||||||
cr, uid, context = request.cr, openerp.SUPERUSER_ID, request.context
|
cr, uid, context = request.cr, openerp.SUPERUSER_ID, request.context
|
||||||
translation_pool = request.registry['ir.translation']
|
translation_pool = request.registry['ir.translation']
|
||||||
if post and post.get('job'):
|
if post and post.get('job') and post.get('pgk'):
|
||||||
job = json.loads(post['job'])
|
if post.get('pgk') != self.get_gengo_key(cr):
|
||||||
|
return Response("Bad authentication - 403/412", status=412)
|
||||||
|
job = json.loads(post['job'], 'utf-8')
|
||||||
tid = job.get('custom_data', False)
|
tid = job.get('custom_data', False)
|
||||||
if (job.get('status') == 'approved') and tid:
|
if (job.get('status') == 'approved') and tid:
|
||||||
term = translation_pool.browse(cr, uid, int(tid), context=context)
|
term = translation_pool.browse(cr, uid, int(tid), context=context)
|
||||||
if term.job_id <> job.get('job_id'):
|
if term.src != job.get('body_src'):
|
||||||
raise 'Error'
|
return Response("Text Altered - Not saved", status=100)
|
||||||
vals = {'state': 'translated', 'value': job.get('body_tgt')}
|
domain = [
|
||||||
translation_pool.write(cr, uid, [int(tid)], vals, context=context)
|
'|',
|
||||||
|
('id', "=", int(tid)),
|
||||||
|
'&', '&', '&', '&', '&',
|
||||||
|
('state', '=', term.state),
|
||||||
|
('gengo_translation', '=', term.gengo_translation),
|
||||||
|
('src', "=", term.src),
|
||||||
|
('type', "=", term.type),
|
||||||
|
('name', "=", term.name),
|
||||||
|
('lang', "=", term.lang),
|
||||||
|
#('order_id', "=", term.order_id),
|
||||||
|
]
|
||||||
|
|
||||||
|
all_ir_tanslations = translation_pool.search(cr, uid, domain, context=context or {})
|
||||||
|
|
||||||
|
if all_ir_tanslations:
|
||||||
|
vals = {'state': 'translated', 'value': job.get('body_tgt')}
|
||||||
|
translation_pool.write(cr, uid, all_ir_tanslations, vals, context=context)
|
||||||
|
return Response("OK", status=200)
|
||||||
|
else:
|
||||||
|
return Response("No terms found", status=104)
|
||||||
|
return Response("Not saved", status=100)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<field name="interval_number">6</field>
|
<field name="interval_number">6</field>
|
||||||
<field name="interval_type">hours</field>
|
<field name="interval_type">hours</field>
|
||||||
<field name="numbercall">-1</field>
|
<field name="numbercall">-1</field>
|
||||||
|
<field name="doall">0</field>
|
||||||
<field eval="'base.gengo.translations'" name="model"></field>
|
<field eval="'base.gengo.translations'" name="model"></field>
|
||||||
<field eval="'_sync_response'" name="function"/>
|
<field eval="'_sync_response'" name="function"/>
|
||||||
<field eval="'(20,)'" name="args"/>
|
<field eval="'(20,)'" name="args"/>
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
<field name="interval_number">6</field>
|
<field name="interval_number">6</field>
|
||||||
<field name="interval_type">hours</field>
|
<field name="interval_type">hours</field>
|
||||||
<field name="numbercall">-1</field>
|
<field name="numbercall">-1</field>
|
||||||
|
<field name="doall">0</field>
|
||||||
<field eval="'base.gengo.translations'" name="model"></field>
|
<field eval="'base.gengo.translations'" name="model"></field>
|
||||||
<field eval="'_sync_request'" name="function"/>
|
<field eval="'_sync_request'" name="function"/>
|
||||||
<field eval="'(20,)'" name="args"/>
|
<field eval="'(20,)'" name="args"/>
|
||||||
|
|
|
@ -56,16 +56,18 @@ LANG_CODE_MAPPING = {
|
||||||
'fi_FI': ('fi', 'Finnish')
|
'fi_FI': ('fi', 'Finnish')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ir_translation(osv.Model):
|
class ir_translation(osv.Model):
|
||||||
_name = "ir.translation"
|
_name = "ir.translation"
|
||||||
_inherit = "ir.translation"
|
_inherit = "ir.translation"
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'gengo_comment': fields.text("Comments & Activity Linked to Gengo"),
|
'gengo_comment': fields.text("Comments & Activity Linked to Gengo"),
|
||||||
'job_id': fields.char('Gengo Job ID', size=32),
|
'order_id': fields.char('Gengo Order ID', size=32),
|
||||||
"gengo_translation": fields.selection([('machine', 'Translation By Machine'),
|
"gengo_translation": fields.selection([('machine', 'Translation By Machine'),
|
||||||
('standard', 'Standard'),
|
('standard', 'Standard'),
|
||||||
('pro', 'Pro'),
|
('pro', 'Pro'),
|
||||||
('ultra', 'Ultra')], "Gengo Translation Service Level", help='You can select here the service level you want for an automatic translation using Gengo.'),
|
('ultra', 'Ultra')], "Gengo Translation Service Level", help='You can select here the service level you want for an automatic translation using Gengo.'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_all_supported_languages(self, cr, uid, context=None):
|
def _get_all_supported_languages(self, cr, uid, context=None):
|
||||||
|
@ -83,3 +85,19 @@ class ir_translation(osv.Model):
|
||||||
|
|
||||||
def _get_gengo_corresponding_language(cr, lang):
|
def _get_gengo_corresponding_language(cr, lang):
|
||||||
return lang in LANG_CODE_MAPPING and LANG_CODE_MAPPING[lang][0] or lang
|
return lang in LANG_CODE_MAPPING and LANG_CODE_MAPPING[lang][0] or lang
|
||||||
|
|
||||||
|
def _get_source_query(self, cr, uid, name, types, lang, source, res_id):
|
||||||
|
query, params = super(ir_translation, self)._get_source_query(name, types, lang, source, res_id)
|
||||||
|
|
||||||
|
query += """
|
||||||
|
ORDER BY
|
||||||
|
CASE
|
||||||
|
WHEN gengo_translation=%s then 10
|
||||||
|
WHEN gengo_translation=%s then 20
|
||||||
|
WHEN gengo_translation=%s then 30
|
||||||
|
WHEN gengo_translation=%s then 40
|
||||||
|
ELSE 0
|
||||||
|
END DESC
|
||||||
|
"""
|
||||||
|
params += ('machine', 'standard', 'ultra', 'pro',)
|
||||||
|
return (query, params)
|
||||||
|
|
|
@ -19,12 +19,13 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
import uuid
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from openerp.osv import osv, fields
|
from openerp.osv import osv, fields
|
||||||
from openerp import tools
|
from openerp import tools, SUPERUSER_ID
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
@ -36,7 +37,9 @@ except ImportError:
|
||||||
|
|
||||||
GENGO_DEFAULT_LIMIT = 20
|
GENGO_DEFAULT_LIMIT = 20
|
||||||
|
|
||||||
|
|
||||||
class base_gengo_translations(osv.osv_memory):
|
class base_gengo_translations(osv.osv_memory):
|
||||||
|
GENGO_KEY = "Gengo.UUID"
|
||||||
|
|
||||||
_name = 'base.gengo.translations'
|
_name = 'base.gengo.translations'
|
||||||
_columns = {
|
_columns = {
|
||||||
|
@ -46,9 +49,20 @@ class base_gengo_translations(osv.osv_memory):
|
||||||
'lang_id': fields.many2one('res.lang', 'Language', required=True),
|
'lang_id': fields.many2one('res.lang', 'Language', required=True),
|
||||||
'sync_limit': fields.integer("No. of terms to sync"),
|
'sync_limit': fields.integer("No. of terms to sync"),
|
||||||
}
|
}
|
||||||
_defaults = {'sync_type' : 'both',
|
_defaults = {
|
||||||
'sync_limit' : 20
|
'sync_type': 'both',
|
||||||
}
|
'sync_limit': 20
|
||||||
|
}
|
||||||
|
|
||||||
|
def init(self, cr):
|
||||||
|
icp = self.pool['ir.config_parameter']
|
||||||
|
if not icp.get_param(cr, SUPERUSER_ID, self.GENGO_KEY, default=None):
|
||||||
|
icp.set_param(cr, SUPERUSER_ID, self.GENGO_KEY, str(uuid.uuid4()))
|
||||||
|
|
||||||
|
def get_gengo_key(self, cr):
|
||||||
|
icp = self.pool['ir.config_parameter']
|
||||||
|
return icp.get_param(cr, SUPERUSER_ID, self.GENGO_KEY, default="Undefined")
|
||||||
|
|
||||||
def gengo_authentication(self, cr, uid, context=None):
|
def gengo_authentication(self, cr, uid, context=None):
|
||||||
'''
|
'''
|
||||||
This method tries to open a connection with Gengo. For that, it uses the Public and Private
|
This method tries to open a connection with Gengo. For that, it uses the Public and Private
|
||||||
|
@ -113,48 +127,68 @@ class base_gengo_translations(osv.osv_memory):
|
||||||
_logger.warning("%s", gengo)
|
_logger.warning("%s", gengo)
|
||||||
else:
|
else:
|
||||||
offset = 0
|
offset = 0
|
||||||
all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "!=", False)], context=context)
|
all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('order_id', "!=", False)], context=context)
|
||||||
while True:
|
while True:
|
||||||
translation_ids = all_translation_ids[offset:offset + limit]
|
translation_ids = all_translation_ids[offset:offset + limit]
|
||||||
offset += limit
|
offset += limit
|
||||||
if not translation_ids:
|
if not translation_ids:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
terms_progress = {
|
||||||
|
'gengo_order_ids': set(),
|
||||||
|
'ir_translation_ids': set(),
|
||||||
|
}
|
||||||
translation_terms = translation_pool.browse(cr, uid, translation_ids, context=context)
|
translation_terms = translation_pool.browse(cr, uid, translation_ids, context=context)
|
||||||
gengo_job_id = [term.job_id for term in translation_terms]
|
for term in translation_terms:
|
||||||
if gengo_job_id:
|
terms_progress['gengo_order_ids'].add(term.order_id)
|
||||||
gengo_ids = ','.join(gengo_job_id)
|
terms_progress['ir_translation_ids'].add(tools.ustr(term.id))
|
||||||
|
|
||||||
|
for order_id in terms_progress['gengo_order_ids']:
|
||||||
|
order_response = gengo.getTranslationOrderJobs(id=order_id)
|
||||||
|
jobs_approved = order_response.get('response', []).get('order', []).get('jobs_approved', [])
|
||||||
|
gengo_ids = ','.join(jobs_approved)
|
||||||
|
|
||||||
|
if gengo_ids: # Need to check, because getTranslationJobBatch don't catch this case and so call the getTranslationJobs because no ids in url
|
||||||
try:
|
try:
|
||||||
job_response = gengo.getTranslationJobBatch(id=gengo_ids)
|
job_response = gengo.getTranslationJobBatch(id=gengo_ids)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
if job_response['opstat'] == 'ok':
|
if job_response['opstat'] == 'ok':
|
||||||
for job in job_response['response'].get('jobs', []):
|
for job in job_response['response'].get('jobs', []):
|
||||||
self._update_terms_job(cr, uid, job, context=context)
|
if job.get('custom_data') in terms_progress['ir_translation_ids']:
|
||||||
|
self._update_terms_job(cr, uid, job, context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _update_terms_job(self, cr, uid, job, context=None):
|
def _update_terms_job(self, cr, uid, job, context=None):
|
||||||
translation_pool = self.pool.get('ir.translation')
|
translation_pool = self.pool.get('ir.translation')
|
||||||
tid = int(job['custom_data'])
|
tid = int(job['custom_data'])
|
||||||
vals = {}
|
vals = {}
|
||||||
if job.get('job_id', False):
|
if job.get('status', False) in ('queued', 'available', 'pending', 'reviewable'):
|
||||||
vals['job_id'] = job['job_id']
|
|
||||||
vals['state'] = 'inprogress'
|
vals['state'] = 'inprogress'
|
||||||
if job.get('status', False) in ('queued','available','pending','reviewable'):
|
if job.get('body_tgt', False) and job.get('status', False) == 'approved':
|
||||||
vals['state'] = 'inprogress'
|
|
||||||
if job.get('body_tgt', False) and job.get('status', False)=='approved':
|
|
||||||
vals['value'] = job['body_tgt']
|
vals['value'] = job['body_tgt']
|
||||||
if job.get('status', False) in ('approved', 'canceled'):
|
if job.get('status', False) in ('approved', 'canceled'):
|
||||||
vals['state'] = 'translated'
|
vals['state'] = 'translated'
|
||||||
if vals:
|
if vals:
|
||||||
translation_pool.write(cr, uid, [tid], vals, context=context)
|
translation_pool.write(cr, uid, [tid], vals, context=context)
|
||||||
|
|
||||||
def _update_terms(self, cr, uid, response, context=None):
|
def _update_terms(self, cr, uid, response, term_ids, context=None):
|
||||||
"""
|
"""
|
||||||
Update the terms after their translation were requested to Gengo
|
Update the terms after their translation were requested to Gengo
|
||||||
"""
|
"""
|
||||||
for jobs in response.get('jobs', []):
|
translation_pool = self.pool.get('ir.translation')
|
||||||
|
|
||||||
|
vals = {
|
||||||
|
'order_id': response.get('order_id', ''),
|
||||||
|
'state': 'inprogress'
|
||||||
|
}
|
||||||
|
|
||||||
|
translation_pool.write(cr, uid, term_ids, vals, context=context)
|
||||||
|
jobs = response.get('jobs', [])
|
||||||
|
if jobs:
|
||||||
for t_id, res in jobs.items():
|
for t_id, res in jobs.items():
|
||||||
self._update_terms_job(cr, uid, res, context=context)
|
self._update_terms_job(cr, uid, res, context=context)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def pack_jobs_request(self, cr, uid, term_ids, context=None):
|
def pack_jobs_request(self, cr, uid, term_ids, context=None):
|
||||||
|
@ -173,7 +207,7 @@ class base_gengo_translations(osv.osv_memory):
|
||||||
if re.search(r"\w", term.src or ""):
|
if re.search(r"\w", term.src or ""):
|
||||||
comment = user.company_id.gengo_comment or ''
|
comment = user.company_id.gengo_comment or ''
|
||||||
if term.gengo_comment:
|
if term.gengo_comment:
|
||||||
comment+='\n' + term.gengo_comment
|
comment += '\n' + term.gengo_comment
|
||||||
jobs[time.strftime('%Y%m%d%H%M%S') + '-' + str(term.id)] = {
|
jobs[time.strftime('%Y%m%d%H%M%S') + '-' + str(term.id)] = {
|
||||||
'type': 'text',
|
'type': 'text',
|
||||||
'slug': 'Single :: English to ' + term.lang,
|
'slug': 'Single :: English to ' + term.lang,
|
||||||
|
@ -184,10 +218,9 @@ class base_gengo_translations(osv.osv_memory):
|
||||||
'lc_tgt': translation_pool._get_gengo_corresponding_language(term.lang),
|
'lc_tgt': translation_pool._get_gengo_corresponding_language(term.lang),
|
||||||
'auto_approve': auto_approve,
|
'auto_approve': auto_approve,
|
||||||
'comment': comment,
|
'comment': comment,
|
||||||
'callback_url': self.pool.get('ir.config_parameter').get_param(cr, uid,'web.base.url') + '/website/gengo_callback'
|
'callback_url': self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + '/website/gengo_callback?pgk=' + self.get_gengo_key(cr)
|
||||||
}
|
}
|
||||||
return {'jobs': jobs, 'as_group': 1}
|
return {'jobs': jobs, 'as_group': 0}
|
||||||
|
|
||||||
|
|
||||||
def _send_translation_terms(self, cr, uid, term_ids, context=None):
|
def _send_translation_terms(self, cr, uid, term_ids, context=None):
|
||||||
"""
|
"""
|
||||||
|
@ -200,7 +233,7 @@ class base_gengo_translations(osv.osv_memory):
|
||||||
if request['jobs']:
|
if request['jobs']:
|
||||||
result = gengo.postTranslationJobs(jobs=request)
|
result = gengo.postTranslationJobs(jobs=request)
|
||||||
if result['opstat'] == 'ok':
|
if result['opstat'] == 'ok':
|
||||||
self._update_terms(cr, uid, result['response'], context=context)
|
self._update_terms(cr, uid, result['response'], term_ids, context=context)
|
||||||
else:
|
else:
|
||||||
_logger.error(gengo)
|
_logger.error(gengo)
|
||||||
return True
|
return True
|
||||||
|
@ -218,10 +251,10 @@ class base_gengo_translations(osv.osv_memory):
|
||||||
context = {}
|
context = {}
|
||||||
language_pool = self.pool.get('res.lang')
|
language_pool = self.pool.get('res.lang')
|
||||||
translation_pool = self.pool.get('ir.translation')
|
translation_pool = self.pool.get('ir.translation')
|
||||||
domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "=", False)]
|
domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('order_id', "=", False)]
|
||||||
if context.get('gengo_language', False):
|
if context.get('gengo_language', False):
|
||||||
lc = language_pool.browse(cr, uid, context['gengo_language'], context=context).code
|
lc = language_pool.browse(cr, uid, context['gengo_language'], context=context).code
|
||||||
domain.append( ('lang', '=', lc) )
|
domain.append(('lang', '=', lc))
|
||||||
|
|
||||||
all_term_ids = translation_pool.search(cr, uid, domain, context=context)
|
all_term_ids = translation_pool.search(cr, uid, domain, context=context)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
var nodialog = 'website_translator_nodialog';
|
var nodialog = 'website_translator_nodialog';
|
||||||
|
|
||||||
website.EditorBar.include({
|
website.EditorBar.include({
|
||||||
|
do_not_translate : ['-','*','!'],
|
||||||
events: _.extend({}, website.EditorBar.prototype.events, {
|
events: _.extend({}, website.EditorBar.prototype.events, {
|
||||||
'click a[data-action=edit_master]': 'edit_master',
|
'click a[data-action=edit_master]': 'edit_master',
|
||||||
}),
|
}),
|
||||||
|
@ -129,7 +130,7 @@
|
||||||
node.className += ' oe_translatable_inprogress';
|
node.className += ' oe_translatable_inprogress';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node.className += ' oe_translatable_todo';
|
node.className += this.do_not_translate.indexOf(node.textContent.trim()) ? ' oe_translatable_todo' : '';
|
||||||
}
|
}
|
||||||
node.contentEditable = true;
|
node.contentEditable = true;
|
||||||
var nid = _.uniqueId();
|
var nid = _.uniqueId();
|
||||||
|
|
|
@ -288,6 +288,31 @@ class ir_translation(osv.osv):
|
||||||
})
|
})
|
||||||
return len(ids)
|
return len(ids)
|
||||||
|
|
||||||
|
def _get_source_query(self, cr, uid, name, types, lang, source, res_id):
|
||||||
|
if source:
|
||||||
|
query = """SELECT value
|
||||||
|
FROM ir_translation
|
||||||
|
WHERE lang=%s
|
||||||
|
AND type in %s
|
||||||
|
AND src=%s"""
|
||||||
|
params = (lang or '', types, tools.ustr(source))
|
||||||
|
if res_id:
|
||||||
|
query += "AND res_id=%s"
|
||||||
|
params += (res_id,)
|
||||||
|
if name:
|
||||||
|
query += " AND name=%s"
|
||||||
|
params += (tools.ustr(name),)
|
||||||
|
else:
|
||||||
|
query = """SELECT value
|
||||||
|
FROM ir_translation
|
||||||
|
WHERE lang=%s
|
||||||
|
AND type in %s
|
||||||
|
AND name=%s"""
|
||||||
|
|
||||||
|
params = (lang or '', types, tools.ustr(name))
|
||||||
|
|
||||||
|
return (query, params)
|
||||||
|
|
||||||
@tools.ormcache(skiparg=3)
|
@tools.ormcache(skiparg=3)
|
||||||
def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
|
def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
|
||||||
"""
|
"""
|
||||||
|
@ -310,27 +335,10 @@ class ir_translation(osv.osv):
|
||||||
return tools.ustr(source or '')
|
return tools.ustr(source or '')
|
||||||
if isinstance(types, basestring):
|
if isinstance(types, basestring):
|
||||||
types = (types,)
|
types = (types,)
|
||||||
if source:
|
|
||||||
query = """SELECT value
|
query, params = self._get_source_query(cr, uid, name, types, lang, source, res_id)
|
||||||
FROM ir_translation
|
|
||||||
WHERE lang=%s
|
cr.execute(query, params)
|
||||||
AND type in %s
|
|
||||||
AND src=%s"""
|
|
||||||
params = (lang or '', types, tools.ustr(source))
|
|
||||||
if res_id:
|
|
||||||
query += "AND res_id=%s"
|
|
||||||
params += (res_id,)
|
|
||||||
if name:
|
|
||||||
query += " AND name=%s"
|
|
||||||
params += (tools.ustr(name),)
|
|
||||||
cr.execute(query, params)
|
|
||||||
else:
|
|
||||||
cr.execute("""SELECT value
|
|
||||||
FROM ir_translation
|
|
||||||
WHERE lang=%s
|
|
||||||
AND type in %s
|
|
||||||
AND name=%s""",
|
|
||||||
(lang or '', types, tools.ustr(name)))
|
|
||||||
res = cr.fetchone()
|
res = cr.fetchone()
|
||||||
trad = res and res[0] or u''
|
trad = res and res[0] or u''
|
||||||
if source and not trad:
|
if source and not trad:
|
||||||
|
|
Loading…
Reference in New Issue