2012-08-17 06:27:30 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2012-08-06 07:40:35 +00:00
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# OpenERP, Open Source Business Applications
|
|
|
|
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as
|
|
|
|
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
2012-08-17 06:27:30 +00:00
|
|
|
from osv import osv
|
2012-08-27 09:41:37 +00:00
|
|
|
from tools.translate import _
|
2012-08-27 13:37:59 +00:00
|
|
|
import re
|
2012-08-27 09:40:27 +00:00
|
|
|
try:
|
2012-08-27 09:41:37 +00:00
|
|
|
from mygengo import MyGengo
|
2012-08-27 09:40:27 +00:00
|
|
|
except ImportError:
|
|
|
|
raise osv.except_osv(_('Gengo ImportError'), _('Please install mygengo lib from http://pypi.python.org/pypi/mygengo'))
|
|
|
|
|
2012-08-06 07:40:35 +00:00
|
|
|
import logging
|
2012-08-27 06:52:18 +00:00
|
|
|
import tools
|
2012-08-27 10:54:13 +00:00
|
|
|
import time
|
2012-08-27 07:27:43 +00:00
|
|
|
|
2012-08-06 07:40:35 +00:00
|
|
|
_logger = logging.getLogger(__name__)
|
2012-08-27 09:40:27 +00:00
|
|
|
|
2012-08-27 06:52:18 +00:00
|
|
|
LANG_CODE_MAPPING = {
|
2012-08-27 13:37:59 +00:00
|
|
|
'ar_SA': ('ar', 'Arabic'),
|
|
|
|
'id_ID': ('id', 'Indonesian'),
|
|
|
|
'nl_NL': ('nl', 'Dutch'),
|
|
|
|
'fr_CA': ('fr-ca', 'French (Canada)'),
|
2012-08-28 08:40:36 +00:00
|
|
|
'pl_PL': ('pl', 'Polish'),
|
2012-08-27 13:37:59 +00:00
|
|
|
'zh_TW': ('zh-tw', 'Chinese (Traditional)'),
|
|
|
|
'sv_SE': ('sv', 'Swedish'),
|
|
|
|
'ko_KR': ('ko', 'Korean'),
|
|
|
|
'pt_PT': ('pt', 'Portuguese (Europe)'),
|
|
|
|
'en_US': ('en', 'English'),
|
|
|
|
'ja_JP': ('ja', 'Japanese'),
|
|
|
|
'es_ES': ('es', 'Spanish (Spain)'),
|
|
|
|
'zh_CN': ('zh', 'Chinese (Simplified)'),
|
|
|
|
'de_DE': ('de', 'German'),
|
|
|
|
'fr_FR': ('fr', 'French'),
|
|
|
|
'fr_BE': ('fr', 'French'),
|
|
|
|
'ru_RU': ('ru', 'Russian'),
|
|
|
|
'it_IT': ('it', 'Italian'),
|
|
|
|
'pt_BR': ('pt-br', 'Portuguese (Brazil)')
|
2012-08-27 06:52:18 +00:00
|
|
|
}
|
2012-08-06 07:40:35 +00:00
|
|
|
|
2012-08-28 08:40:36 +00:00
|
|
|
CRON_VALS = {
|
2012-08-24 13:21:25 +00:00
|
|
|
'name': 'Gengo Sync',
|
|
|
|
'active': True,
|
2012-08-28 11:04:26 +00:00
|
|
|
'interval_number': 20,
|
2012-08-24 13:21:25 +00:00
|
|
|
'interval_type': 'minutes',
|
|
|
|
'numbercall': -1,
|
|
|
|
'model': "'base.update.translations'",
|
2012-08-28 11:04:26 +00:00
|
|
|
'function': "",
|
|
|
|
'args': "'(20,)'",
|
2012-08-23 13:42:57 +00:00
|
|
|
}
|
2012-08-06 10:25:17 +00:00
|
|
|
|
2012-08-06 07:40:35 +00:00
|
|
|
|
2012-08-23 13:42:57 +00:00
|
|
|
class base_update_translation(osv.osv_memory):
|
2012-08-24 13:21:25 +00:00
|
|
|
|
2012-08-27 10:54:13 +00:00
|
|
|
_name = 'base.update.translations'
|
|
|
|
_inherit = "base.update.translations"
|
|
|
|
|
2012-08-27 06:52:18 +00:00
|
|
|
def gengo_authentication(self, cr, uid, context=None):
|
|
|
|
''' To Send Request and Get Response from Gengo User needs Public and Private
|
2012-08-27 13:37:59 +00:00
|
|
|
key for that user need to sign up to gengo and get public and private
|
2012-08-27 06:52:18 +00:00
|
|
|
key which is provided by gengo to authentic user '''
|
|
|
|
|
|
|
|
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
|
|
|
if not user.company_id.gengo_public_key or not user.company_id.gengo_private_key:
|
2012-08-28 09:47:22 +00:00
|
|
|
return (False, " - Invalid gengo configuration, Either Gengo authentication `Public Key` or `Private Key` is missing. Complete Gengo authentication parameter under `Settings > Companies > Gengo Parameters`.")
|
2012-08-27 06:52:18 +00:00
|
|
|
try:
|
|
|
|
gengo = MyGengo(
|
|
|
|
public_key=user.company_id.gengo_public_key.encode('ascii'),
|
|
|
|
private_key=user.company_id.gengo_private_key.encode('ascii'),
|
|
|
|
sandbox=True,
|
|
|
|
)
|
|
|
|
gengo.getAccountStats()
|
|
|
|
return (True, gengo)
|
|
|
|
except Exception, e:
|
2012-08-28 08:40:36 +00:00
|
|
|
return (False, "Gengo Connection Error\n%s"%e)
|
2012-08-27 06:52:18 +00:00
|
|
|
|
|
|
|
def pack_jobs_request(self, cr, uid, term_ids, context):
|
|
|
|
jobs = {}
|
|
|
|
gengo_parameter_pool = self.pool.get('res.users').browse(cr, uid, uid, context)
|
|
|
|
translation_pool = self.pool.get('ir.translation')
|
2012-08-28 10:18:16 +00:00
|
|
|
auto_approve = gengo_parameter_pool.company_id.gengo_auto_approve and 1 or 0
|
2012-08-27 06:52:18 +00:00
|
|
|
for term in translation_pool.browse(cr, uid, term_ids, context):
|
2012-08-28 10:18:16 +00:00
|
|
|
if re.search(r"\w", term.src or ""):
|
|
|
|
job = {'type': 'text',
|
|
|
|
'slug': 'single::English to ' + LANG_CODE_MAPPING[term.lang][1],
|
|
|
|
'tier': tools.ustr(gengo_parameter_pool.company_id.gengo_tier),
|
|
|
|
'body_src': term.src,
|
|
|
|
'lc_src': 'en',
|
|
|
|
'lc_tgt': LANG_CODE_MAPPING[term.lang][0],
|
|
|
|
'auto_approve': auto_approve,
|
|
|
|
'comment': gengo_parameter_pool.company_id.gengo_comment}
|
|
|
|
jobs.update({term.id: job})
|
2012-08-27 06:52:18 +00:00
|
|
|
return {'jobs': jobs}
|
|
|
|
|
|
|
|
def check_lang_support(self, cr, uid, langs, context=None):
|
|
|
|
new_langs = []
|
|
|
|
flag, gengo = self.gengo_authentication(cr, uid, context)
|
|
|
|
if not flag:
|
|
|
|
return []
|
|
|
|
else:
|
|
|
|
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
|
|
|
tier = user.company_id.gengo_tier
|
|
|
|
if tier == "machine":
|
|
|
|
tier = "nonprofit"
|
|
|
|
lang_pair = gengo.getServiceLanguagePairs(lc_src='en')
|
|
|
|
if lang_pair['opstat'] == 'ok':
|
|
|
|
for g_lang in lang_pair['response']:
|
|
|
|
for l in langs:
|
2012-08-27 13:37:59 +00:00
|
|
|
if LANG_CODE_MAPPING[l][0] == g_lang['lc_tgt'] and g_lang['tier'] == tier:
|
2012-08-27 06:52:18 +00:00
|
|
|
new_langs.append(l)
|
|
|
|
return list(set(new_langs))
|
2012-08-27 13:37:59 +00:00
|
|
|
|
2012-08-28 11:37:55 +00:00
|
|
|
def _update_terms(self, cr, uid, response, tier, context):
|
2012-08-06 10:25:17 +00:00
|
|
|
translation_pool = self.pool.get('ir.translation')
|
2012-08-28 10:18:16 +00:00
|
|
|
for jobs in response['jobs']:
|
2012-08-23 13:42:57 +00:00
|
|
|
for t_id, res in jobs.items():
|
2012-08-28 10:18:16 +00:00
|
|
|
vals = {}
|
2012-08-23 13:42:57 +00:00
|
|
|
if tier == "machine":
|
|
|
|
vals.update({'value': res['body_tgt'], 'state': 'translated'})
|
|
|
|
else:
|
|
|
|
vals.update({'job_id': res['job_id'], 'state': 'inprogress'})
|
|
|
|
translation_pool.write(cr, uid, [t_id], vals, context)
|
|
|
|
return
|
|
|
|
|
2012-08-28 11:37:55 +00:00
|
|
|
def _send_translation_terms(self, cr, uid, term_ids, context):
|
2012-08-23 13:42:57 +00:00
|
|
|
"""
|
2012-08-27 13:37:59 +00:00
|
|
|
Lazy Polling will be perform when user or cron request for the translation.
|
2012-08-23 13:42:57 +00:00
|
|
|
"""
|
2012-08-06 07:40:35 +00:00
|
|
|
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
2012-08-27 06:52:18 +00:00
|
|
|
flag, gengo = self.gengo_authentication(cr, uid, context)
|
2012-08-24 13:21:25 +00:00
|
|
|
if flag:
|
2012-08-27 06:52:18 +00:00
|
|
|
request = self.pack_jobs_request(cr, uid, term_ids, context)
|
2012-08-27 13:37:59 +00:00
|
|
|
if request['jobs']:
|
2012-08-24 13:21:25 +00:00
|
|
|
result = gengo.postTranslationJobs(jobs=request)
|
|
|
|
if result['opstat'] == 'ok':
|
2012-08-28 11:37:55 +00:00
|
|
|
self._update_terms(cr, uid, result['response'], user.company_id.gengo_tier, context)
|
2012-08-24 13:21:25 +00:00
|
|
|
else:
|
|
|
|
_logger.error(gengo)
|
2012-08-23 13:42:57 +00:00
|
|
|
return True
|
2012-08-06 10:25:17 +00:00
|
|
|
|
2012-08-23 13:42:57 +00:00
|
|
|
def do_check_schedular(self, cr, uid, xml_id, name, fn, context=None):
|
|
|
|
cron_pool = self.pool.get('ir.cron')
|
2012-08-06 07:40:35 +00:00
|
|
|
try:
|
2012-08-24 13:21:25 +00:00
|
|
|
res = []
|
|
|
|
model, res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base_gengo', xml_id)
|
|
|
|
cron_pool.write(cr, uid, [res], {'active': True}, context=context)
|
2012-08-23 13:42:57 +00:00
|
|
|
except:
|
2012-08-28 08:40:36 +00:00
|
|
|
CRON_VALS.update({'name': name, "function": fn})
|
|
|
|
return cron_pool.create(cr, uid, CRON_VALS, context)
|
2012-08-06 10:25:17 +00:00
|
|
|
|
2012-08-23 13:42:57 +00:00
|
|
|
def act_update(self, cr, uid, ids, context=None):
|
|
|
|
if context == None:
|
|
|
|
context = {}
|
|
|
|
lang_pool = self.pool.get('res.lang')
|
2012-08-24 13:21:25 +00:00
|
|
|
super(base_update_translation, self).act_update(cr, uid, ids, context)
|
2012-08-27 13:37:59 +00:00
|
|
|
msg = "1. Translation file loaded successfully.\n2. Processing Gengo Translation:\n"
|
2012-08-27 06:52:18 +00:00
|
|
|
flag, gengo = self.gengo_authentication(cr, uid, context)
|
2012-08-24 13:21:25 +00:00
|
|
|
if not flag:
|
|
|
|
msg += gengo
|
|
|
|
else:
|
|
|
|
for res in self.browse(cr, uid, ids, context):
|
|
|
|
lang_id = lang_pool.search(cr, uid, [('code', '=', res.lang)])
|
2012-08-28 08:40:36 +00:00
|
|
|
lang_name = self._get_lang_name(cr, uid, res.lang)
|
|
|
|
try:
|
|
|
|
if LANG_CODE_MAPPING[res.lang][0]:
|
|
|
|
lang_search = lang_pool.search(cr, uid, [('gengo_sync', '=', True), ('id', '=', lang_id[0])])
|
|
|
|
if lang_search:
|
2012-08-28 10:18:16 +00:00
|
|
|
msg += ' - This language `%s` is already in queue for translation.' % (lang_name)
|
2012-08-28 08:40:36 +00:00
|
|
|
else:
|
2012-08-28 10:18:16 +00:00
|
|
|
msg += ' - The language `%s` is queued for translation through Gengo translation.' % (lang_name)
|
2012-08-28 08:40:36 +00:00
|
|
|
lang_pool.write(cr, uid, lang_id, {'gengo_sync': True})
|
2012-08-28 10:18:16 +00:00
|
|
|
_logger.info('Translation request for language `%s` has been queued successfully.', lang_name)
|
2012-08-28 08:40:36 +00:00
|
|
|
self.do_check_schedular(cr, uid, 'gengo_sync_send_request_scheduler', 'Gengo Sync Translation (Request)', '_sync_request', context)
|
|
|
|
self.do_check_schedular(cr, uid, 'gengo_sync_receive_request_scheduler', 'Gengo Sync Translation (Response)', '_sync_response', context)
|
2012-08-28 11:04:26 +00:00
|
|
|
self._sync_request(cr, uid, limit=20)
|
2012-08-28 08:40:36 +00:00
|
|
|
except:
|
2012-08-28 10:18:16 +00:00
|
|
|
msg +=' - The Language `%s` is not supported by Gengo Traditional Service.'%(lang_name)
|
2012-08-24 13:21:25 +00:00
|
|
|
|
|
|
|
context.update({'message': msg})
|
|
|
|
obj_model = self.pool.get('ir.model.data')
|
|
|
|
model_data_ids = obj_model.search(cr, uid, [('model', '=', 'ir.ui.view'), ('name', '=', 'update_translation_wizard_view_confirm')])
|
|
|
|
view_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
|
|
|
|
return {
|
|
|
|
'view_type': 'form',
|
|
|
|
'view_mode': 'form',
|
|
|
|
'res_model': 'gengo.update.message',
|
|
|
|
'views': [(view_id, 'form')],
|
|
|
|
'type': 'ir.actions.act_window',
|
|
|
|
'target': 'new',
|
|
|
|
'context': context,
|
|
|
|
}
|
2012-08-06 10:25:17 +00:00
|
|
|
|
2012-08-28 11:04:26 +00:00
|
|
|
def _sync_response(self, cr, uid, limit=20, context=None):
|
2012-08-27 10:54:13 +00:00
|
|
|
"""
|
|
|
|
This method will be call by cron services to get translation from
|
|
|
|
gengo for translation terms which are posted to be translated. It will
|
|
|
|
read translated terms and comments from gengo and will update respective
|
2012-08-28 11:04:26 +00:00
|
|
|
translation in openerp.
|
|
|
|
"""
|
2012-08-06 10:25:17 +00:00
|
|
|
translation_pool = self.pool.get('ir.translation')
|
2012-08-27 06:52:18 +00:00
|
|
|
flag, gengo = self.gengo_authentication(cr, uid, context)
|
2012-08-24 13:21:25 +00:00
|
|
|
if not flag:
|
|
|
|
_logger.warning("%s", gengo)
|
|
|
|
else:
|
2012-08-28 11:04:26 +00:00
|
|
|
translation_id = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', '=', True)], limit=limit, context=context)
|
2012-08-27 10:54:13 +00:00
|
|
|
for term in translation_pool.browse(cr, uid, translation_id, context):
|
2012-08-28 11:37:55 +00:00
|
|
|
up_term = up_comment = 0
|
2012-08-27 10:54:13 +00:00
|
|
|
if term.job_id:
|
|
|
|
vals={}
|
|
|
|
job_response = gengo.getTranslationJob(id=term.job_id)
|
|
|
|
if job_response['opstat'] != 'ok':
|
2012-08-28 10:18:16 +00:00
|
|
|
_logger.warning("Invalid Response! Skipping translation Terms with `id` %s."%(term.job_id))
|
2012-08-27 10:54:13 +00:00
|
|
|
continue
|
2012-08-24 13:21:25 +00:00
|
|
|
if job_response['response']['job']['status'] == 'approved':
|
2012-08-27 10:54:13 +00:00
|
|
|
vals.update({'state': 'translated',
|
|
|
|
'value': job_response['response']['job']['body_tgt'],
|
|
|
|
'gengo_control': True})
|
2012-08-28 11:37:55 +00:00
|
|
|
up_term += 1
|
2012-08-27 10:54:13 +00:00
|
|
|
job_comment = gengo.getTranslationJobComments(id=term.job_id)
|
|
|
|
if job_comment['opstat']=='ok':
|
|
|
|
gengo_comments=""
|
|
|
|
for comment in job_comment['response']['thread']:
|
2012-08-28 11:37:55 +00:00
|
|
|
gengo_comments+='%s Commented on %s by %s. \n'%(comment['body'], time.ctime(comment['ctime']), comment['author'])
|
2012-08-27 10:54:13 +00:00
|
|
|
vals.update({'gengo_comment':gengo_comments})
|
2012-08-28 11:37:55 +00:00
|
|
|
up_comment +=1
|
2012-08-27 10:54:13 +00:00
|
|
|
if vals:
|
|
|
|
translation_pool.write(cr, uid, term.id,vals)
|
2012-08-28 11:37:55 +00:00
|
|
|
_logger.info("Successfully Updated `%d` terms and Comments for `%d` terms."%(up_term, up_comment ))
|
2012-08-23 13:42:57 +00:00
|
|
|
return True
|
2012-08-06 10:25:17 +00:00
|
|
|
|
2012-08-28 11:04:26 +00:00
|
|
|
def _sync_request(self, cr, uid, limit=20, context=None):
|
|
|
|
"""
|
|
|
|
This scheduler will send a job request to the gengo , which terms are
|
|
|
|
in translate state and gengo_translation is true
|
|
|
|
"""
|
2012-08-06 07:40:35 +00:00
|
|
|
if context is None:
|
2012-08-06 10:25:17 +00:00
|
|
|
context = {}
|
2012-08-24 13:21:25 +00:00
|
|
|
language_pool = self.pool.get('res.lang')
|
|
|
|
translation_pool = self.pool.get('ir.translation')
|
2012-08-06 07:40:35 +00:00
|
|
|
try:
|
2012-08-24 13:21:25 +00:00
|
|
|
lang_ids = language_pool.search(cr, uid, [('gengo_sync', '=', True)])
|
|
|
|
langs = [lang.code for lang in language_pool.browse(cr, uid, lang_ids)]
|
2012-08-27 06:52:18 +00:00
|
|
|
langs = self.check_lang_support(cr, uid, langs)
|
2012-08-28 11:04:26 +00:00
|
|
|
term_ids = translation_pool.search(cr, uid, [('state', '=', 'to_translate'), ('gengo_translation', '=', True), ('lang', 'in', langs)], limit=limit)
|
2012-08-24 13:21:25 +00:00
|
|
|
if term_ids:
|
2012-08-28 11:37:55 +00:00
|
|
|
self._send_translation_terms(cr, uid, term_ids, context)
|
2012-08-24 13:21:25 +00:00
|
|
|
_logger.info("Translation terms %s has been posted to gengo successfully", len(term_ids))
|
2012-08-23 13:42:57 +00:00
|
|
|
else:
|
2012-08-24 13:21:25 +00:00
|
|
|
_logger.info('No Translation terms to process.')
|
2012-08-06 07:40:35 +00:00
|
|
|
except Exception, e:
|
2012-08-24 13:21:25 +00:00
|
|
|
_logger.error("%s", e)
|
2012-08-06 07:40:35 +00:00
|
|
|
|
2012-08-06 10:25:17 +00:00
|
|
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|