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/>.
#
##############################################################################
import logging
2012-11-16 13:50:21 +00:00
import re
2012-08-27 10:54:13 +00:00
import time
2012-08-27 07:27:43 +00:00
2012-11-16 13:50:21 +00:00
from openerp . osv import osv , fields
from openerp import tools
from openerp . tools . translate import _
2012-08-06 07:40:35 +00:00
_logger = logging . getLogger ( __name__ )
2012-08-27 09:40:27 +00:00
2012-11-16 13:50:21 +00:00
try :
from mygengo import MyGengo
except ImportError :
_logger . warning ( ' Gengo library not found, Gengo features disabled. If you plan to use it, please install the mygengo library from http://pypi.python.org/pypi/mygengo ' )
class MyGengo ( object ) :
def __init__ ( self , * args , * * kwargs ) :
# no context for translations - so don't bother
raise ImportError ( ' Gengo library not found, please install mygengo from http://pypi.python.org/pypi/mygengo ' )
2012-08-29 08:26:47 +00:00
GENGO_DEFAULT_LIMIT = 20
2012-08-30 16:14:29 +00:00
class base_gengo_translations ( osv . osv_memory ) :
2012-08-06 07:40:35 +00:00
2012-08-30 16:14:29 +00:00
_name = ' base.gengo.translations '
_columns = {
2014-03-21 07:14:38 +00:00
' sync_type ' : fields . selection ( [ ( ' send ' , ' Send New Terms ' ) ,
( ' receive ' , ' Receive Translation ' ) ,
( ' both ' , ' Both ' ) ] , " Sync Type " ) ,
2012-11-16 13:50:21 +00:00
' lang_id ' : fields . many2one ( ' res.lang ' , ' Language ' , required = True ) ,
2014-03-28 11:37:15 +00:00
' sync_limit ' : fields . integer ( " No. of terms to sync " ) ,
2012-08-30 16:14:29 +00:00
}
2014-03-28 11:37:15 +00:00
_defaults = { ' sync_type ' : ' both ' ,
' sync_limit ' : 20
}
2012-08-27 06:52:18 +00:00
def gengo_authentication ( self , cr , uid , context = None ) :
2012-08-30 16:14:29 +00:00
'''
This method tries to open a connection with Gengo . For that , it uses the Public and Private
keys that are linked to the company ( given by Gengo on subscription ) . It returns a tuple with
* as first element : a boolean depicting if the authentication was a success or not
* as second element : the connection , if it was a success , or the error message returned by
Gengo when the connection failed .
This error message can either be displayed in the server logs ( if the authentication was called
by the cron ) or in a dialog box ( if requested by the user ) , thus it ' s important to return it
translated .
'''
2012-08-29 08:26:47 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
2012-08-27 06:52:18 +00:00
if not user . company_id . gengo_public_key or not user . company_id . gengo_private_key :
2012-11-16 13:50:21 +00:00
return ( False , _ ( " Gengo `Public Key` or `Private Key` are missing. Enter your Gengo authentication parameters 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 ' ) ,
2014-04-03 15:17:46 +00:00
sandbox = user . company_id . gengo_sandbox ,
2012-08-27 06:52:18 +00:00
)
gengo . getAccountStats ( )
return ( True , gengo )
except Exception , e :
2012-11-16 13:50:21 +00:00
_logger . exception ( ' Gengo connection failed ' )
return ( False , _ ( " Gengo connection failed with this message: \n `` %s `` " ) % e )
2012-08-29 08:26:47 +00:00
2012-08-23 13:42:57 +00:00
def act_update ( self , cr , uid , ids , context = None ) :
2012-08-30 16:14:29 +00:00
'''
Function called by the wizard .
'''
2014-04-03 15:17:46 +00:00
if context is None :
2012-08-23 13:42:57 +00:00
context = { }
2012-08-24 13:21:25 +00:00
2012-08-30 16:14:29 +00:00
flag , gengo = self . gengo_authentication ( cr , uid , context = context )
if not flag :
raise osv . except_osv ( _ ( ' Gengo Authentication Error ' ) , gengo )
for wizard in self . browse ( cr , uid , ids , context = context ) :
supported_langs = self . pool . get ( ' ir.translation ' ) . _get_all_supported_languages ( cr , uid , context = context )
language = self . pool . get ( ' ir.translation ' ) . _get_gengo_corresponding_language ( wizard . lang_id . code )
if language not in supported_langs :
2012-11-16 13:50:21 +00:00
raise osv . except_osv ( _ ( " Warning " ) , _ ( ' This language is not supported by the Gengo translation services. ' ) )
2012-08-30 16:14:29 +00:00
ctx = context . copy ( )
ctx [ ' gengo_language ' ] = wizard . lang_id . id
2014-03-28 11:37:15 +00:00
if wizard . sync_limit > 200 or wizard . sync_limit < 1 :
raise osv . except_osv ( _ ( " Warning " ) , _ ( ' Sync limit should between 1 to 200 for Gengo translation services. ' ) )
2014-04-03 15:17:46 +00:00
if wizard . sync_type in [ ' send ' , ' both ' ] :
2014-03-28 11:37:15 +00:00
self . _sync_request ( cr , uid , wizard . sync_limit , context = ctx )
2014-04-03 15:17:46 +00:00
if wizard . sync_type in [ ' receive ' , ' both ' ] :
self . _sync_response ( cr , uid , wizard . sync_limit , context = ctx )
2012-08-30 16:14:29 +00:00
return { ' type ' : ' ir.actions.act_window_close ' }
2012-08-06 10:25:17 +00:00
2012-08-29 08:26:47 +00:00
def _sync_response ( self , cr , uid , limit = GENGO_DEFAULT_LIMIT , context = None ) :
2012-08-27 10:54:13 +00:00
"""
2012-08-30 16:14:29 +00:00
This method will be called by cron services to get translations from
2014-04-03 15:17:46 +00:00
Gengo . It will read translated terms and comments from Gengo and will
2012-08-30 16:14:29 +00:00
update respective ir . translation in openerp .
2012-08-28 11:04:26 +00:00
"""
2012-08-06 10:25:17 +00:00
translation_pool = self . pool . get ( ' ir.translation ' )
2012-08-30 16:14:29 +00:00
flag , gengo = self . gengo_authentication ( cr , uid , context = context )
2012-08-24 13:21:25 +00:00
if not flag :
_logger . warning ( " %s " , gengo )
else :
2014-04-03 15:17:46 +00:00
offset = 0
while True :
translation_ids = translation_pool . search ( cr , uid , [ ( ' state ' , ' = ' , ' inprogress ' ) , ( ' gengo_translation ' , ' in ' , ( ' machine ' , ' standard ' , ' pro ' , ' ultra ' ) ) , ( ' job_id ' , " != " , False ) ] , limit = limit , offset = offset , context = context )
if not translation_ids :
break
offset + = limit
translation_terms = translation_pool . browse ( cr , uid , translation_ids , context = context )
gengo_job_id = [ term . job_id for term in translation_terms ]
if gengo_job_id :
gengo_ids = ' , ' . join ( gengo_job_id )
job_response = gengo . getTranslationJobBatch ( id = gengo_ids )
if job_response [ ' opstat ' ] == ' ok ' :
job_response_dict = dict ( [ ( job [ ' job_id ' ] , job ) for job in job_response [ ' response ' ] [ ' jobs ' ] ] )
for term in translation_terms :
up_term = up_comment = 0
vals = { }
if job_response_dict [ term . job_id ] [ ' status ' ] == ' approved ' :
vals . update ( { ' state ' : ' translated ' ,
' value ' : job_response_dict [ term . job_id ] [ ' body_tgt ' ] } )
up_term + = 1
job_comment = gengo . getTranslationJobComments ( id = term . job_id )
if job_comment [ ' opstat ' ] == ' ok ' :
gengo_comments = " "
for comment in job_comment [ ' response ' ] [ ' thread ' ] :
gengo_comments + = _ ( ' %s \n -- Commented on %s by %s . \n \n ' ) % ( comment [ ' body ' ] , time . ctime ( comment [ ' ctime ' ] ) , comment [ ' author ' ] )
vals . update ( { ' gengo_comment ' : gengo_comments } )
up_comment + = 1
if vals :
translation_pool . write ( cr , uid , term . id , vals )
_logger . info ( " Successfully Updated ` %d ` terms and %d Comments. " % ( up_term , up_comment ) )
2012-08-30 16:14:29 +00:00
return True
def _update_terms ( self , cr , uid , response , context = None ) :
"""
Update the terms after their translation were requested to Gengo
"""
translation_pool = self . pool . get ( ' ir.translation ' )
for jobs in response [ ' jobs ' ] :
for t_id , res in jobs . items ( ) :
vals = { }
t_id = int ( t_id )
tier = translation_pool . read ( cr , uid , [ t_id ] , [ ' gengo_translation ' ] , context = context ) [ 0 ] [ ' gengo_translation ' ]
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 = context )
return
def pack_jobs_request ( self , cr , uid , term_ids , context = None ) :
''' prepare the terms that will be requested to gengo and returns them in a dictionary with following format
{ ' jobs ' : {
' term1.id ' : { . . . }
' term2.id ' : { . . . }
}
} '''
translation_pool = self . pool . get ( ' ir.translation ' )
jobs = { }
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
auto_approve = 1 if user . company_id . gengo_auto_approve else 0
for term in translation_pool . browse ( cr , uid , term_ids , context = context ) :
if re . search ( r " \ w " , term . src or " " ) :
jobs [ term . id ] = { ' type ' : ' text ' ,
' slug ' : ' single::English to ' + term . lang ,
' tier ' : tools . ustr ( term . gengo_translation ) ,
' body_src ' : term . src ,
' lc_src ' : ' en ' ,
' lc_tgt ' : translation_pool . _get_gengo_corresponding_language ( term . lang ) ,
' auto_approve ' : auto_approve ,
2014-03-31 12:19:32 +00:00
' comment ' : user . company_id . gengo_comment and " %s %s " % ( user . company_id . gengo_comment , term . gengo_comment ) or term . gengo_comment ,
' callback_url ' : self . pool . get ( ' ir.config_parameter ' ) . get_param ( cr , uid , ' web.base.url ' ) + ' /website/gengo_callback/ ' + str ( term . id )
2012-08-30 16:14:29 +00:00
}
return { ' jobs ' : jobs }
2014-04-03 15:17:46 +00:00
def _send_translation_terms ( self , cr , uid , term_ids , context = None ) :
2012-08-30 16:14:29 +00:00
"""
Send a request to Gengo with all the term_ids in a different job , get the response and update the terms in
database accordingly .
"""
flag , gengo = self . gengo_authentication ( cr , uid , context = context )
if flag :
request = self . pack_jobs_request ( cr , uid , term_ids , context = context )
if request [ ' jobs ' ] :
result = gengo . postTranslationJobs ( jobs = request )
if result [ ' opstat ' ] == ' ok ' :
self . _update_terms ( cr , uid , result [ ' response ' ] , context = context )
else :
_logger . error ( gengo )
2012-08-23 13:42:57 +00:00
return True
2012-08-06 10:25:17 +00:00
2012-08-29 08:26:47 +00:00
def _sync_request ( self , cr , uid , limit = GENGO_DEFAULT_LIMIT , context = None ) :
2012-08-30 16:14:29 +00:00
"""
This scheduler will send a job request to the gengo , which terms are
waiing to be translated and for which gengo_translation is enabled .
A special key ' gengo_language ' can be passed in the context in order to
request only translations of that language only . Its value is the language
ID in openerp .
"""
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-30 16:14:29 +00:00
#by default, the request will be made for all terms that needs it, whatever the language
lang_ids = language_pool . search ( cr , uid , [ ] , context = context )
if context . get ( ' gengo_language ' ) :
#but if this specific key is given, then we restrict the request on terms of this language only
lang_ids = [ context . get ( ' gengo_language ' ) ]
2012-08-29 08:26:47 +00:00
langs = [ lang . code for lang in language_pool . browse ( cr , uid , lang_ids , context = context ) ]
2014-04-03 15:17:46 +00:00
offset = 0
while True :
#search for the n first terms to translate
term_ids = translation_pool . search ( cr , uid , [ ( ' state ' , ' = ' , ' to_translate ' ) , ( ' gengo_translation ' , ' in ' , ( ' machine ' , ' standard ' , ' pro ' , ' ultra ' ) ) , ( ' lang ' , ' in ' , langs ) , ( ' job_id ' , " = " , False ) ] , limit = limit , offset = offset , context = context )
if term_ids :
self . _send_translation_terms ( cr , uid , term_ids , context = context )
offset + = limit
_logger . info ( " %s Translation terms have been posted to Gengo successfully " , len ( term_ids ) )
else :
break
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: