1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Business Applications
5 # Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
23 from tools.translate import _
26 from mygengo import MyGengo
28 raise osv.except_osv(_('Gengo ImportError'), _('Please install mygengo lib from http://pypi.python.org/pypi/mygengo'))
34 _logger = logging.getLogger(__name__)
39 'ar_SA': ('ar', 'Arabic'),
40 'id_ID': ('id', 'Indonesian'),
41 'nl_NL': ('nl', 'Dutch'),
42 'fr_CA': ('fr-ca', 'French (Canada)'),
43 'pl_PL': ('pl', 'Polish'),
44 'zh_TW': ('zh-tw', 'Chinese (Traditional)'),
45 'sv_SE': ('sv', 'Swedish'),
46 'ko_KR': ('ko', 'Korean'),
47 'pt_PT': ('pt', 'Portuguese (Europe)'),
48 'en_US': ('en', 'English'),
49 'ja_JP': ('ja', 'Japanese'),
50 'es_ES': ('es', 'Spanish (Spain)'),
51 'zh_CN': ('zh', 'Chinese (Simplified)'),
52 'de_DE': ('de', 'German'),
53 'fr_FR': ('fr', 'French'),
54 'fr_BE': ('fr', 'French'),
55 'ru_RU': ('ru', 'Russian'),
56 'it_IT': ('it', 'Italian'),
57 'pt_BR': ('pt-br', 'Portuguese (Brazil)')
63 'interval_number': 30,
64 'interval_type': 'minutes',
66 'model': "'base.update.translations'",
71 class base_update_translation(osv.osv_memory):
73 _name = 'base.update.translations'
74 _inherit = "base.update.translations"
76 def gengo_authentication(self, cr, uid, context=None):
77 ''' To Send Request and Get Response from Gengo User needs Public and Private
78 key for that user need to sign up to gengo and get public and private
79 key which is provided by gengo to authentic user '''
81 user = self.pool.get('res.users').browse(cr, uid, uid, context)
82 if not user.company_id.gengo_public_key or not user.company_id.gengo_private_key:
83 return (False, " - Invalid gengo configuration, Either Gengo authentication `Public Key` or `Private Key` is missing. Complete Gengo authentication parameter under `Settings > Companies > Gengo Parameters`.")
86 public_key=user.company_id.gengo_public_key.encode('ascii'),
87 private_key=user.company_id.gengo_private_key.encode('ascii'),
90 gengo.getAccountStats()
93 return (False, "Gengo Connection Error\n%s"%e)
95 def pack_jobs_request(self, cr, uid, term_ids, context):
97 gengo_parameter_pool = self.pool.get('res.users').browse(cr, uid, uid, context)
98 translation_pool = self.pool.get('ir.translation')
99 auto_approve = gengo_parameter_pool.company_id.gengo_auto_approve and 1 or 0
100 for term in translation_pool.browse(cr, uid, term_ids, context):
101 if re.search(r"\w", term.src or ""):
102 job = {'type': 'text',
103 'slug': 'single::English to ' + LANG_CODE_MAPPING[term.lang][1],
104 'tier': tools.ustr(gengo_parameter_pool.company_id.gengo_tier),
105 'body_src': term.src,
107 'lc_tgt': LANG_CODE_MAPPING[term.lang][0],
108 'auto_approve': auto_approve,
109 'comment': gengo_parameter_pool.company_id.gengo_comment}
110 jobs.update({term.id: job})
111 return {'jobs': jobs}
113 def check_lang_support(self, cr, uid, langs, context=None):
115 flag, gengo = self.gengo_authentication(cr, uid, context)
119 user = self.pool.get('res.users').browse(cr, uid, uid, context)
120 tier = user.company_id.gengo_tier
121 if tier == "machine":
123 lang_pair = gengo.getServiceLanguagePairs(lc_src='en')
124 if lang_pair['opstat'] == 'ok':
125 for g_lang in lang_pair['response']:
127 if LANG_CODE_MAPPING[l][0] == g_lang['lc_tgt'] and g_lang['tier'] == tier:
129 return list(set(new_langs))
131 def _update_terms(self, cr, uid, ids, response, tier, context):
132 translation_pool = self.pool.get('ir.translation')
133 for jobs in response['jobs']:
134 for t_id, res in jobs.items():
136 if tier == "machine":
137 vals.update({'value': res['body_tgt'], 'state': 'translated'})
139 vals.update({'job_id': res['job_id'], 'state': 'inprogress'})
140 translation_pool.write(cr, uid, [t_id], vals, context)
143 def _send_translation_terms(self, cr, uid, ids, term_ids, context):
145 Lazy Polling will be perform when user or cron request for the translation.
147 user = self.pool.get('res.users').browse(cr, uid, uid, context)
148 flag, gengo = self.gengo_authentication(cr, uid, context)
150 request = self.pack_jobs_request(cr, uid, term_ids, context)
152 result = gengo.postTranslationJobs(jobs=request)
153 if result['opstat'] == 'ok':
154 self._update_terms(cr, uid, ids, result['response'], user.company_id.gengo_tier, context)
159 def do_check_schedular(self, cr, uid, xml_id, name, fn, context=None):
160 cron_pool = self.pool.get('ir.cron')
163 model, res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base_gengo', xml_id)
164 cron_pool.write(cr, uid, [res], {'active': True}, context=context)
166 CRON_VALS.update({'name': name, "function": fn})
167 return cron_pool.create(cr, uid, CRON_VALS, context)
169 def act_update(self, cr, uid, ids, context=None):
172 lang_pool = self.pool.get('res.lang')
173 super(base_update_translation, self).act_update(cr, uid, ids, context)
174 msg = "1. Translation file loaded successfully.\n2. Processing Gengo Translation:\n"
175 flag, gengo = self.gengo_authentication(cr, uid, context)
179 for res in self.browse(cr, uid, ids, context):
180 lang_id = lang_pool.search(cr, uid, [('code', '=', res.lang)])
181 lang_name = self._get_lang_name(cr, uid, res.lang)
183 if LANG_CODE_MAPPING[res.lang][0]:
184 lang_search = lang_pool.search(cr, uid, [('gengo_sync', '=', True), ('id', '=', lang_id[0])])
186 msg += ' - This language `%s` is already in queue for translation.' % (lang_name)
188 msg += ' - The language `%s` is queued for translation through Gengo translation.' % (lang_name)
189 lang_pool.write(cr, uid, lang_id, {'gengo_sync': True})
190 _logger.info('Translation request for language `%s` has been queued successfully.', lang_name)
191 self.do_check_schedular(cr, uid, 'gengo_sync_send_request_scheduler', 'Gengo Sync Translation (Request)', '_sync_request', context)
192 self.do_check_schedular(cr, uid, 'gengo_sync_receive_request_scheduler', 'Gengo Sync Translation (Response)', '_sync_response', context)
193 self._sync_request(cr, uid, ids, context)
195 msg +=' - The Language `%s` is not supported by Gengo Traditional Service.'%(lang_name)
197 context.update({'message': msg})
198 obj_model = self.pool.get('ir.model.data')
199 model_data_ids = obj_model.search(cr, uid, [('model', '=', 'ir.ui.view'), ('name', '=', 'update_translation_wizard_view_confirm')])
200 view_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
204 'res_model': 'gengo.update.message',
205 'views': [(view_id, 'form')],
206 'type': 'ir.actions.act_window',
211 def _sync_response(self, cr, uid, ids=False, context=None):
213 This method will be call by cron services to get translation from
214 gengo for translation terms which are posted to be translated. It will
215 read translated terms and comments from gengo and will update respective
216 translation in openerp """
217 translation_pool = self.pool.get('ir.translation')
218 flag, gengo = self.gengo_authentication(cr, uid, context)
220 _logger.warning("%s", gengo)
222 translation_id = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', '=', True)], limit=LIMIT, context=context)
223 for term in translation_pool.browse(cr, uid, translation_id, context):
226 job_response = gengo.getTranslationJob(id=term.job_id)
227 if job_response['opstat'] != 'ok':
228 _logger.warning("Invalid Response! Skipping translation Terms with `id` %s."%(term.job_id))
230 if job_response['response']['job']['status'] == 'approved':
231 vals.update({'state': 'translated',
232 'value': job_response['response']['job']['body_tgt'],
233 'gengo_control': True})
234 job_comment = gengo.getTranslationJobComments(id=term.job_id)
235 if job_comment['opstat']=='ok':
237 for comment in job_comment['response']['thread']:
238 gengo_comments+='%s by %s at %s. \n' %(comment['body'],comment['author'],time.ctime(comment['ctime']))
239 vals.update({'gengo_comment':gengo_comments})
241 translation_pool.write(cr, uid, term.id,vals)
244 def _sync_request(self, cr, uid, ids=False, context=None):
245 """This scheduler will send a job request to the gengo , which terms are
246 in translate state and gengo_translation is true"""
249 language_pool = self.pool.get('res.lang')
250 translation_pool = self.pool.get('ir.translation')
252 lang_ids = language_pool.search(cr, uid, [('gengo_sync', '=', True)])
253 langs = [lang.code for lang in language_pool.browse(cr, uid, lang_ids)]
254 langs = self.check_lang_support(cr, uid, langs)
255 term_ids = translation_pool.search(cr, uid, [('state', '=', 'to_translate'), ('gengo_translation', '=', True), ('lang', 'in', langs)], limit=LIMIT)
257 self._send_translation_terms(cr, uid, ids, term_ids, context)
258 _logger.info("Translation terms %s has been posted to gengo successfully", len(term_ids))
260 _logger.info('No Translation terms to process.')
262 _logger.error("%s", e)
264 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: