1 #!/usr/bin/env python2.5
2 # -*- coding: utf-8 -*-
4 PygTranslator - pas de doc cette fois-ci... :-P
6 Copyright : Agence universitaire de la Francophonie
7 Licence : GNU General Public Licence, version 2
8 Auteur : Jean Christophe André
9 Date de création : 28 septembre 2009
12 from threading
import Thread
13 from Queue
import Queue
21 #print "\x1b[31;1mDEBUG\x1b[m:", message
24 class XmppTranslator(Thread
):
26 def __init__(self
, jid
, password
):
29 self
._input_queue
= Queue(0)
30 self
._output_queue
= Queue(0)
33 self
._jid
= xmpp
.JID(jid
)
34 self
._password
= password
35 if self
._jid
.getResource() == '':
36 self
._jid
.setResource('translator')
38 self
._client
= xmpp
.Client(self
._jid
.getDomain(), debug
=[])
41 if self
._client
and not self
._client
.isConnected():
43 self
._client
.sendPresence(typ
='unavailable')
44 self
._client
.disconnect()
48 if not self
._client
.connect():
51 raise IOError, "can't connect to '%s'" % self
._jid
.getDomain()
52 self
._client
.RegisterHandler('message', self
._messageHandler
)
54 auth
= self
._client
.auth(self
._jid
.getNode(), self
._password
,
55 self
._jid
.getResource())
57 raise IOError, "unable to authenticate '%s'" % self
._jid
.getNode()
58 self
._client
.sendInitPresence(requestRoster
=0)
60 def _messageHandler(self
, client
, message
):
61 if message
.getType() == 'error':
63 translation_path
= message
.getFrom().getNode()
64 text
= message
.getBody()
65 self
._output_queue
.put( (translation_path
, text
) )
66 raise xmpp
.NodeProcessed
68 def _process_input_queue(self
):
69 if self
._input_queue
.empty():
71 # process pending translation job
72 translation_path
, text
= self
._input_queue
.get()
73 jid
= '%s@bot.talk.google.com' % translation_path
74 message
= xmpp
.Message(to
=jid
, typ
='chat', body
=text
)
75 self
._client
.send(message
)
76 DEBUG("sent [%s] to '%s'." % (text
, jid
))
77 self
._input_queue
.task_done()
81 self
._client
.Process(1)
83 self
._process_input_queue()
84 self
._client
.Process(1)
86 def request_translation(self
, translation_path
, text
):
87 # remove any pending translation job
88 while not self
._input_queue
.empty():
89 self
._input_queue
.get()
90 DEBUG("removed a pending translation job")
91 self
._input_queue
.task_done()
92 # put a new translation job
93 self
._input_queue
.put( (translation_path
, text
) )
95 def translation_result(self
):
96 if self
._output_queue
.empty():
98 translation_path
, text
= self
._output_queue
.get()
99 return translation_path
, text
101 def translation_done(self
):
102 self
._output_queue
.task_done()
104 class GtkTranslator(object):
106 def __init__(self
, translator
):
107 self
._translator
= translator
111 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
112 self
.window
.set_title(u
"PygTranslator")
113 self
.window
.set_border_width(0)
114 self
.window
.connect("destroy", lambda w
: gtk
.main_quit())
115 self
.window
.connect("delete_event", self
.delete_event
)
117 vbox
= gtk
.VBox(True, 0)
120 textview
= gtk
.TextView()
121 textview
.set_size_request(400, 100)
122 textview
.set_wrap_mode(gtk
.WRAP_WORD
)
124 scroll
= gtk
.ScrolledWindow()
127 frame
= gtk
.Frame(u
"Texte en français")
128 frame
.connect("key_release_event", self
.key_release_event
, 'fr')
131 vbox
.pack_start(frame
, True, True, 0)
132 self
._textbuf
['fr'] = textview
.get_buffer()
134 textview
= gtk
.TextView()
135 textview
.set_size_request(400, 100)
136 textview
.set_wrap_mode(gtk
.WRAP_WORD
)
138 scroll
= gtk
.ScrolledWindow()
141 frame
= gtk
.Frame(u
"Text in English")
142 frame
.connect("key_release_event", self
.key_release_event
, 'en')
145 vbox
.pack_start(frame
, True, True, 0)
146 self
._textbuf
['en'] = textview
.get_buffer()
148 self
.window
.add(vbox
)
152 DEBUG("running graphic interface")
153 gobject
.timeout_add(100, self
.process_translation_result
)
154 gtk
.gdk
.threads_init()
157 def delete_event(self
, widget
, event
, data
=None):
158 DEBUG("caught delete event")
162 def key_release_event(self
, widget
, event
, lang
):
163 start
, end
= self
._textbuf
[lang
].get_bounds()
164 text
= self
._textbuf
[lang
].get_text(start
, end
)
165 other_lang
= (set(self
._textbuf
.keys()) - set((lang
,))).pop()
166 translation_path
= lang
+ '2' + other_lang
167 self
._translator
.request_translation(translation_path
, text
)
169 def process_translation_result(self
):
171 # FIXME: to transform into an iterator...
173 r
= self
._translator
.translation_result()
176 translation_path
, text
= r
177 lang
= translation_path
[3:]
178 if lang
in self
._textbuf
:
181 DEBUG("unknown destination language '%s'" % lang
)
182 self
._translator
.translation_done()
183 for lang
, text
in result
.items():
184 self
._textbuf
[lang
].set_text(text
)
185 gobject
.timeout_add(100, self
.process_translation_result
)
187 if __name__
== "__main__":
189 if len(sys
.argv
) != 3:
190 print "Usage: %s <jid> <password>" % sys
.argv
[0]
193 translator
= XmppTranslator(sys
.argv
[1], sys
.argv
[2])
196 pygtranslator
= GtkTranslator(translator
)
199 except KeyboardInterrupt:
202 translator
._quit
= True