comparison sat.tac @ 69:86f1f7f6d332

i18n first draft - gettext support added in SàT - first draft of french translation - added README with a HOWTO for translators
author Goffi <goffi@goffi.org>
date Wed, 03 Mar 2010 17:12:23 +1100
parents 9b842086d915
children f271fff3a713
comparison
equal deleted inserted replaced
68:9b842086d915 69:86f1f7f6d332
23 'client_name' : u'SàT (Salut à toi)', 23 'client_name' : u'SàT (Salut à toi)',
24 'client_version' : u'0.0.2D', #Please add 'D' at the end for dev versions 24 'client_version' : u'0.0.2D', #Please add 'D' at the end for dev versions
25 'local_dir' : '~/.sat' 25 'local_dir' : '~/.sat'
26 } 26 }
27 27
28
28 from twisted.application import internet, service 29 from twisted.application import internet, service
29 from twisted.internet import glib2reactor, protocol, task 30 from twisted.internet import glib2reactor, protocol, task
30 glib2reactor.install() 31 glib2reactor.install()
31 32
32 from twisted.words.protocols.jabber import jid, xmlstream 33 from twisted.words.protocols.jabber import jid, xmlstream
46 import os.path 47 import os.path
47 48
48 from tools.memory import Memory 49 from tools.memory import Memory
49 from tools.xml_tools import XMLTools 50 from tools.xml_tools import XMLTools
50 from glob import glob 51 from glob import glob
52
53 import gettext
54 gettext.install('sat', "i18n", unicode=True)
51 55
52 try: 56 try:
53 from twisted.words.protocols.xmlstream import XMPPHandler 57 from twisted.words.protocols.xmlstream import XMPPHandler
54 except ImportError: 58 except ImportError:
55 from wokkel.subprotocols import XMPPHandler 59 from wokkel.subprotocols import XMPPHandler
79 83
80 def _authd(self, xmlstream): 84 def _authd(self, xmlstream):
81 print "SatXMPPClient" 85 print "SatXMPPClient"
82 client.XMPPClient._authd(self, xmlstream) 86 client.XMPPClient._authd(self, xmlstream)
83 self.__connected=True 87 self.__connected=True
84 print "********** [%s] CONNECTED **********" % self.profile 88 info (_("********** [%s] CONNECTED **********") % self.profile)
85 self.streamInitialized() 89 self.streamInitialized()
86 self.host_app.bridge.connected(self.profile) #we send the signal to the clients 90 self.host_app.bridge.connected(self.profile) #we send the signal to the clients
87 91
88 def streamInitialized(self): 92 def streamInitialized(self):
89 """Called after _authd""" 93 """Called after _authd"""
90 debug ("XML stream is initialized") 94 debug (_("XML stream is initialized"))
91 self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire) 95 self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire)
92 self.keep_alife.start(180) 96 self.keep_alife.start(180)
93 97
94 self.disco = SatDiscoProtocol(self) 98 self.disco = SatDiscoProtocol(self)
95 self.disco.setHandlerParent(self) 99 self.disco.setHandlerParent(self)
105 def isConnected(self): 109 def isConnected(self):
106 return self.__connected 110 return self.__connected
107 111
108 def connectionLost(self, connector, unused_reason): 112 def connectionLost(self, connector, unused_reason):
109 self.__connected=False 113 self.__connected=False
110 print "********** [%s] DISCONNECTED **********" % self.profile 114 info (_("********** [%s] DISCONNECTED **********") % self.profile)
111 try: 115 try:
112 self.keep_alife.stop() 116 self.keep_alife.stop()
113 except AttributeError: 117 except AttributeError:
114 debug("No keep_alife") 118 debug (_("No keep_alife"))
115 self.host_app.bridge.disconnected(self.profile) #we send the signal to the clients 119 self.host_app.bridge.disconnected(self.profile) #we send the signal to the clients
116 120
117 121
118 class SatMessageProtocol(xmppim.MessageProtocol): 122 class SatMessageProtocol(xmppim.MessageProtocol):
119 123
120 def __init__(self, host): 124 def __init__(self, host):
121 xmppim.MessageProtocol.__init__(self) 125 xmppim.MessageProtocol.__init__(self)
122 self.host = host 126 self.host = host
123 127
124 def onMessage(self, message): 128 def onMessage(self, message):
125 debug (u"got_message from: %s", message["from"]) 129 debug (_(u"got message from: %s"), message["from"])
126 for e in message.elements(): 130 for e in message.elements():
127 if e.name == "body": 131 if e.name == "body":
128 type = message['type'] if message.hasAttribute('type') else 'chat' #FIXME: check specs 132 type = message['type'] if message.hasAttribute('type') else 'chat' #FIXME: check specs
129 self.host.bridge.newMessage(message["from"], e.children[0], type, profile=self.parent.profile) 133 self.host.bridge.newMessage(message["from"], e.children[0], type, profile=self.parent.profile)
130 self.host.memory.addToHistory(self.parent.jid, jid.JID(message["from"]), self.parent.jid, "chat", e.children[0]) 134 self.host.memory.addToHistory(self.parent.jid, jid.JID(message["from"]), self.parent.jid, "chat", e.children[0])
162 'from': str(item.subscriptionFrom), 166 'from': str(item.subscriptionFrom),
163 'ask': str(item.ask) 167 'ask': str(item.ask)
164 } 168 }
165 if item.name: 169 if item.name:
166 item_attr['name'] = item.name 170 item_attr['name'] = item.name
167 info ("new contact in roster list: %s", item.jid.full()) 171 info (_("new contact in roster list: %s"), item.jid.full())
168 self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) 172 self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile)
169 self.host.bridge.newContact(item.jid.full(), item_attr, item.groups, self.parent.profile) 173 self.host.bridge.newContact(item.jid.full(), item_attr, item.groups, self.parent.profile)
170 174
171 def onRosterRemove(self, entity): 175 def onRosterRemove(self, entity):
172 """Called when a roster removal event is received""" 176 """Called when a roster removal event is received"""
173 #TODO: send a signal to frontends 177 #TODO: send a signal to frontends
174 print "removing %s from roster list" % entity.full() 178 print _("removing %s from roster list") % entity.full()
175 self.host.memory.delContact(entity, self.parent.profile) 179 self.host.memory.delContact(entity, self.parent.profile)
176 180
177 class SatPresenceProtocol(xmppim.PresenceClientProtocol): 181 class SatPresenceProtocol(xmppim.PresenceClientProtocol):
178 182
179 def __init__(self, host): 183 def __init__(self, host):
180 xmppim.PresenceClientProtocol.__init__(self) 184 xmppim.PresenceClientProtocol.__init__(self)
181 self.host = host 185 self.host = host
182 186
183 def availableReceived(self, entity, show=None, statuses=None, priority=0): 187 def availableReceived(self, entity, show=None, statuses=None, priority=0):
184 info ("presence update for [%s]", entity) 188 info (_("presence update for [%s]"), entity)
185 189
186 if statuses.has_key(None): #we only want string keys 190 if statuses.has_key(None): #we only want string keys
187 statuses["default"] = statuses[None] 191 statuses["default"] = statuses[None]
188 del statuses[None] 192 del statuses[None]
189 193
209 statuses[None] = statuses['default'] 213 statuses[None] = statuses['default']
210 del statuses['default'] 214 del statuses['default']
211 xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority) 215 xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority)
212 216
213 def subscribedReceived(self, entity): 217 def subscribedReceived(self, entity):
214 debug ("subscription approved for [%s]" % entity.userhost()) 218 debug (_("subscription approved for [%s]") % entity.userhost())
215 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) 219 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
216 self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile) 220 self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile)
217 221
218 def unsubscribedReceived(self, entity): 222 def unsubscribedReceived(self, entity):
219 debug ("unsubscription confirmed for [%s]" % entity.userhost()) 223 debug (_("unsubscription confirmed for [%s]") % entity.userhost())
220 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) 224 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
221 self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile) 225 self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile)
222 226
223 def subscribeReceived(self, entity): 227 def subscribeReceived(self, entity):
224 debug ("subscription request for [%s]" % entity.userhost()) 228 debug (_("subscription request for [%s]") % entity.userhost())
225 self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile) 229 self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile)
226 self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile) 230 self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile)
227 231
228 def unsubscribeReceived(self, entity): 232 def unsubscribeReceived(self, entity):
229 debug ("unsubscription asked for [%s]" % entity.userhost()) 233 debug (_("unsubscription asked for [%s]") % entity.userhost())
230 self.host.memory.addWaitingSub('unsubscribe', entity.userhost(), self.parent.profile) 234 self.host.memory.addWaitingSub('unsubscribe', entity.userhost(), self.parent.profile)
231 self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile) 235 self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile)
232 236
233 class SatDiscoProtocol(disco.DiscoClientProtocol): 237 class SatDiscoProtocol(disco.DiscoClientProtocol):
234 def __init__(self, host): 238 def __init__(self, host):
250 self.host = host 254 self.host = host
251 self.jabber_host = jabber_host 255 self.jabber_host = jabber_host
252 self.user_login = user_login 256 self.user_login = user_login
253 self.user_pass = user_pass 257 self.user_pass = user_pass
254 self.answer_id = answer_id 258 self.answer_id = answer_id
255 print "Registration asked for",user_login, user_pass, jabber_host 259 print _("Registration asked for"),user_login, user_pass, jabber_host
256 260
257 def connectionMade(self): 261 def connectionMade(self):
258 print "connectionMade" 262 print "connectionMade"
259 263
260 self.xmlstream.namespace = "jabber:client" 264 self.xmlstream.namespace = "jabber:client"
268 _pass = query.addElement('password') 272 _pass = query.addElement('password')
269 _pass.addContent(self.user_pass) 273 _pass.addContent(self.user_pass)
270 reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure) 274 reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure)
271 275
272 def registrationAnswer(self, answer): 276 def registrationAnswer(self, answer):
273 debug ("registration answer: %s" % answer.toXml()) 277 debug (_("registration answer: %s") % answer.toXml())
274 answer_type = "SUCCESS" 278 answer_type = "SUCCESS"
275 answer_data={"message":"Registration successfull"} 279 answer_data={"message":_("Registration successfull")}
276 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data) 280 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
277 self.xmlstream.sendFooter() 281 self.xmlstream.sendFooter()
278 282
279 def registrationFailure(self, failure): 283 def registrationFailure(self, failure):
280 info ("Registration failure: %s" % str(failure.value)) 284 info (_("Registration failure: %s") % str(failure.value))
281 answer_type = "ERROR" 285 answer_type = "ERROR"
282 answer_data = {} 286 answer_data = {}
283 if failure.value.condition == 'conflict': 287 if failure.value.condition == 'conflict':
284 answer_data['reason'] = 'conflict' 288 answer_data['reason'] = 'conflict'
285 answer_data={"message":"Username already exists, please choose an other one"} 289 answer_data={"message":_("Username already exists, please choose an other one")}
286 else: 290 else:
287 answer_data['reason'] = 'unknown' 291 answer_data['reason'] = 'unknown'
288 answer_data={"message":"Registration failed (%s)" % str(failure.value.condition)} 292 answer_data={"message":_("Registration failed (%s)") % str(failure.value.condition)}
289 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data) 293 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
290 self.xmlstream.sendFooter() 294 self.xmlstream.sendFooter()
291 295
292 296
293 class SAT(service.Service): 297 class SAT(service.Service):
296 return sat_next_id() 300 return sat_next_id()
297 301
298 def get_const(self, name): 302 def get_const(self, name):
299 """Return a constant""" 303 """Return a constant"""
300 if not CONST.has_key(name): 304 if not CONST.has_key(name):
301 error('Trying to access an undefined constant') 305 error(_('Trying to access an undefined constant'))
302 raise Exception 306 raise Exception
303 return CONST[name] 307 return CONST[name]
304 308
305 def set_const(self, name, value): 309 def set_const(self, name, value):
306 """Save a constant""" 310 """Save a constant"""
307 if CONST.has_key(name): 311 if CONST.has_key(name):
308 error('Trying to redefine a constant') 312 error(_('Trying to redefine a constant'))
309 raise Exception 313 raise Exception
310 CONST[name] = value 314 CONST[name] = value
311 315
312 def __init__(self): 316 def __init__(self):
313 #TODO: standardize callback system 317 #TODO: standardize callback system
364 for plug in plug_lst: 368 for plug in plug_lst:
365 plug_path = 'plugins.'+plug 369 plug_path = 'plugins.'+plug
366 __import__(plug_path) 370 __import__(plug_path)
367 mod = sys.modules[plug_path] 371 mod = sys.modules[plug_path]
368 plug_info = mod.PLUGIN_INFO 372 plug_info = mod.PLUGIN_INFO
369 info ("importing plugin: %s", plug_info['name']) 373 info (_("importing plugin: %s"), plug_info['name'])
370 self.plugins[plug_info['import_name']] = getattr(mod, plug_info['main'])(self) 374 self.plugins[plug_info['import_name']] = getattr(mod, plug_info['main'])(self)
371 if plug_info.has_key('handler') and plug_info['handler'] == 'yes': 375 if plug_info.has_key('handler') and plug_info['handler'] == 'yes':
372 self.plugins[plug_info['import_name']].is_handler = True 376 self.plugins[plug_info['import_name']].is_handler = True
373 else: 377 else:
374 self.plugins[plug_info['import_name']].is_handler = False 378 self.plugins[plug_info['import_name']].is_handler = False
378 """Connect to jabber server""" 382 """Connect to jabber server"""
379 383
380 384
381 profile = self.memory.getProfileName(profile_key) 385 profile = self.memory.getProfileName(profile_key)
382 if not profile_key: 386 if not profile_key:
383 error ('Trying to connect a non-exsitant profile') 387 error (_('Trying to connect a non-exsitant profile'))
384 return 388 return
385 389
386 if (self.isConnected()): 390 if (self.isConnected()):
387 info("already connected !") 391 info(_("already connected !"))
388 return 392 return
389 print "connecting..." 393 print "connecting..."
390 current = self.profiles[profile] = SatXMPPClient(self, profile, 394 current = self.profiles[profile] = SatXMPPClient(self, profile,
391 jid.JID(self.memory.getParamA("JabberID", "Connection", profile_key = profile_key), profile), 395 jid.JID(self.memory.getParamA("JabberID", "Connection", profile_key = profile_key), profile),
392 self.memory.getParamA("Password", "Connection", profile_key = profile_key), 396 self.memory.getParamA("Password", "Connection", profile_key = profile_key),
406 410
407 current.versionHandler = generic.VersionHandler(self.get_const('client_name'), 411 current.versionHandler = generic.VersionHandler(self.get_const('client_name'),
408 self.get_const('client_version')) 412 self.get_const('client_version'))
409 current.versionHandler.setHandlerParent(current) 413 current.versionHandler.setHandlerParent(current)
410 414
411 debug ("setting plugins parents") 415 debug (_("setting plugins parents"))
412 416
413 for plugin in self.plugins.iteritems(): 417 for plugin in self.plugins.iteritems():
414 if plugin[1].is_handler: 418 if plugin[1].is_handler:
415 plugin[1].getHandler().setHandlerParent(current) 419 plugin[1].getHandler().setHandlerParent(current)
416 420
417 current.startService() 421 current.startService()
418 422
419 def disconnect(self, profile_key='@DEFAULT@'): 423 def disconnect(self, profile_key='@DEFAULT@'):
420 """disconnect from jabber server""" 424 """disconnect from jabber server"""
421 if (not self.isConnected(profile_key)): 425 if (not self.isConnected(profile_key)):
422 info("not connected !") 426 info(_("not connected !"))
423 return 427 return
424 profile = self.memory.getProfileName(profile_key) 428 profile = self.memory.getProfileName(profile_key)
425 info("Disconnecting...") 429 info(_("Disconnecting..."))
426 self.profiles[profile].stopService() 430 self.profiles[profile].stopService()
427 431
428 def startService(self): 432 def startService(self):
429 info("Salut à toi ô mon frère !") 433 info("Salut à toi ô mon frère !")
430 self.connect() 434 self.connect()
432 def stopService(self): 436 def stopService(self):
433 self.memory.save() 437 self.memory.save()
434 info("Salut aussi à Rantanplan") 438 info("Salut aussi à Rantanplan")
435 439
436 def run(self): 440 def run(self):
437 debug("running app") 441 debug(_("running app"))
438 reactor.run() 442 reactor.run()
439 443
440 def stop(self): 444 def stop(self):
441 debug("stopping app") 445 debug(_("stopping app"))
442 reactor.stop() 446 reactor.stop()
443 447
444 ## Misc methods ## 448 ## Misc methods ##
445 449
446 def getJidNStream(self, profile_key): 450 def getJidNStream(self, profile_key):
474 user = jid.parse(self.memory.getParamA("JabberID", "Connection"))[0] 478 user = jid.parse(self.memory.getParamA("JabberID", "Connection"))[0]
475 password = self.memory.getParamA("Password", "Connection") 479 password = self.memory.getParamA("Password", "Connection")
476 server = self.memory.getParamA("Server", "Connection") 480 server = self.memory.getParamA("Server", "Connection")
477 481
478 if not user or not password or not server: 482 if not user or not password or not server:
479 info ('No user or server given') 483 info (_('No user or server given'))
480 #TODO: a proper error message must be sent to frontend 484 #TODO: a proper error message must be sent to frontend
481 self.actionResult(id, "ERROR", {'message':"No user, password or server given, can't register new account."}) 485 self.actionResult(id, "ERROR", {'message':_("No user, password or server given, can't register new account.")})
482 return 486 return
483 487
484 confirm_id = sat_next_id() 488 confirm_id = sat_next_id()
485 self.__private_data[confirm_id]=id 489 self.__private_data[confirm_id]=id
486 490
487 self.askConfirmation(confirm_id, "YES/NO", 491 self.askConfirmation(confirm_id, "YES/NO",
488 {"message":"Are you sure to register new account [%s] to server %s ?" % (user, server)}, 492 {"message":_("Are you sure to register new account [%(user)s] to server %(server)s ?") % {'user':user, 'server':server}},
489 self.regisConfirmCB) 493 self.regisConfirmCB)
490 print ("===============+++++++++++ REGISTER NEW ACCOUNT++++++++++++++============") 494 print ("===============+++++++++++ REGISTER NEW ACCOUNT++++++++++++++============")
491 print "id=",id 495 print "id=",id
492 print "data=",data 496 print "data=",data
493 497
494 def regisConfirmCB(self, id, accepted, data): 498 def regisConfirmCB(self, id, accepted, data):
495 #FIXME: gof: profile not managed here ! 499 #FIXME: gof: profile not managed here !
496 print "register Confirmation CB ! (%s)" % str(accepted) 500 print _("register Confirmation CB ! (%s)") % str(accepted)
497 action_id = self.__private_data[id] 501 action_id = self.__private_data[id]
498 del self.__private_data[id] 502 del self.__private_data[id]
499 user = jid.parse(self.memory.getParamA("JabberID", "Connection"))[0] 503 user = jid.parse(self.memory.getParamA("JabberID", "Connection"))[0]
500 password = self.memory.getParamA("Password", "Connection") 504 password = self.memory.getParamA("Password", "Connection")
501 server = self.memory.getParamA("Server", "Connection") 505 server = self.memory.getParamA("Server", "Connection")
523 form = XMLTools.tupleList2dataForm(fields) 527 form = XMLTools.tupleList2dataForm(fields)
524 query.addChild(form.toElement()) 528 query.addChild(form.toElement())
525 elif action=='CANCEL': 529 elif action=='CANCEL':
526 query.addElement('remove') 530 query.addElement('remove')
527 else: 531 else:
528 error ("FIXME FIXME FIXME: Unmanaged action (%s) in submitForm" % action) 532 error (_("FIXME FIXME FIXME: Unmanaged action (%s) in submitForm") % action)
529 raise NotImplementedError 533 raise NotImplementedError
530 534
531 deferred = iq.send(target) 535 deferred = iq.send(target)
532 return (iq['id'], deferred) 536 return (iq['id'], deferred)
533 537
534 ## Client management ## 538 ## Client management ##
535 539
536 def setParam(self, name, value, category, profile_key='@DEFAULT@'): 540 def setParam(self, name, value, category, profile_key='@DEFAULT@'):
537 """set wanted paramater and notice observers""" 541 """set wanted paramater and notice observers"""
538 info ("setting param: %s=%s in category %s", name, value, category) 542 info (_("setting param: %(name)s=%(value)s in category %(category)s") % {'name':name, 'value':value, 'category':category})
539 self.memory.setParam(name, value, category, profile_key) 543 self.memory.setParam(name, value, category, profile_key)
540 544
541 def isConnected(self, profile_key='@DEFAULT@'): 545 def isConnected(self, profile_key='@DEFAULT@'):
542 """Return connection status of profile 546 """Return connection status of profile
543 @param profile_key: key_word or profile name to determine profile name 547 @param profile_key: key_word or profile name to determine profile name
544 @return True if connected 548 @return True if connected
545 """ 549 """
546 profile = self.memory.getProfileName(profile_key) 550 profile = self.memory.getProfileName(profile_key)
547 if not profile: 551 if not profile:
548 error ('asking connection status for a non-existant profile') 552 error (_('asking connection status for a non-existant profile'))
549 raise Exception #TODO: raise a proper exception 553 raise Exception #TODO: raise a proper exception
550 if not self.profiles.has_key(profile): 554 if not self.profiles.has_key(profile):
551 return False 555 return False
552 return self.profiles[profile].isConnected() 556 return self.profiles[profile].isConnected()
553 557
560 """ 564 """
561 if type=="button": 565 if type=="button":
562 try: 566 try:
563 cb_name = self.memory.getParamA(data["name"], data["category"], "callback") 567 cb_name = self.memory.getParamA(data["name"], data["category"], "callback")
564 except KeyError: 568 except KeyError:
565 error ("Incomplete data") 569 error (_("Incomplete data"))
566 return "" 570 return ""
567 id = sat_next_id() 571 id = sat_next_id()
568 self.callGeneralCB(cb_name, id, data) 572 self.callGeneralCB(cb_name, id, data)
569 return id 573 return id
570 else: 574 else:
571 error ("Unknown action type") 575 error (_("Unknown action type"))
572 return "" 576 return ""
573 577
574 578
575 ## jabber methods ## 579 ## jabber methods ##
576 580
578 print "sendtype=", type #gof 582 print "sendtype=", type #gof
579 #FIXME: check validity of recipient 583 #FIXME: check validity of recipient
580 profile = self.memory.getProfileName(profile_key) 584 profile = self.memory.getProfileName(profile_key)
581 assert(profile) 585 assert(profile)
582 current_jid = self.profiles[profile].jid 586 current_jid = self.profiles[profile].jid
583 debug("Sending jabber message to %s...", to) 587 debug(_("Sending jabber message to %s..."), to)
584 message = domish.Element(('jabber:client','message')) 588 message = domish.Element(('jabber:client','message'))
585 message["to"] = jid.JID(to).full() 589 message["to"] = jid.JID(to).full()
586 message["from"] = current_jid.full() 590 message["from"] = current_jid.full()
587 message["type"] = type 591 message["type"] = type
588 message.addElement("body", "jabber:client", msg) 592 message.addElement("body", "jabber:client", msg)
601 def subscription(self, type, raw_jid, profile_key='@DEFAULT@'): 605 def subscription(self, type, raw_jid, profile_key='@DEFAULT@'):
602 """Called to manage subscription""" 606 """Called to manage subscription"""
603 profile = self.memory.getProfileName(profile_key) 607 profile = self.memory.getProfileName(profile_key)
604 assert(profile) 608 assert(profile)
605 to_jid = jid.JID(raw_jid) 609 to_jid = jid.JID(raw_jid)
606 debug ('subsciption request [%s] for %s', type, to_jid.full()) 610 debug (_('subsciption request [%(type)s] for %(jid)s') % {'type':type, 'jid':to_jid.full()})
607 if type=="subscribe": 611 if type=="subscribe":
608 self.profiles[profile].presence.subscribe(to_jid) 612 self.profiles[profile].presence.subscribe(to_jid)
609 elif type=="subscribed": 613 elif type=="subscribed":
610 self.profiles[profile].subscribed(to_jid) 614 self.profiles[profile].subscribed(to_jid)
611 contact = self.memory.getContact(to_jid) 615 contact = self.memory.getContact(to_jid)
612 if not contact or not bool(contact['to']): #we automatically subscribe to 'to' presence 616 if not contact or not bool(contact['to']): #we automatically subscribe to 'to' presence
613 debug('sending automatic "to" subscription request') 617 debug(_('sending automatic "to" subscription request'))
614 self.subscription('subscribe', to_jid.userhost()) 618 self.subscription('subscribe', to_jid.userhost())
615 elif type=="unsubscribe": 619 elif type=="unsubscribe":
616 self.profiles[profile].presence.unsubscribe(to_jid) 620 self.profiles[profile].presence.unsubscribe(to_jid)
617 elif type=="unsubscribed": 621 elif type=="unsubscribed":
618 self.profiles[profile].presence.unsubscribed(to_jid) 622 self.profiles[profile].presence.unsubscribed(to_jid)
639 ## callbacks ## 643 ## callbacks ##
640 644
641 def serverDisco(self, disco): 645 def serverDisco(self, disco):
642 """xep-0030 Discovery Protocol.""" 646 """xep-0030 Discovery Protocol."""
643 for feature in disco.features: 647 for feature in disco.features:
644 debug ("Feature found: %s",feature) 648 debug (_("Feature found: %s"),feature)
645 self.server_features.append(feature) 649 self.server_features.append(feature)
646 for cat, type in disco.identities: 650 for cat, type in disco.identities:
647 debug ("Identity found: [%s/%s] %s" % (cat, type, disco.identities[(cat,type)])) 651 debug (_("Identity found: [%(category)s/%(type)s] %(identity)s") % {'category':cat, 'type':type, 'identity':disco.identities[(cat,type)]})
648 652
649 653
650 ## Generic HMI ## 654 ## Generic HMI ##
651 655
652 def actionResult(self, id, type, data): 656 def actionResult(self, id, type, data):
662 @param id: same id used with action 666 @param id: same id used with action
663 @param type: result type /!\ only "DICT_DICT" for this method 667 @param type: result type /!\ only "DICT_DICT" for this method
664 @param data: dictionary of dictionaries 668 @param data: dictionary of dictionaries
665 """ 669 """
666 if type != "DICT_DICT": 670 if type != "DICT_DICT":
667 error("type for actionResultExt must be DICT_DICT, fixing it") 671 error(_("type for actionResultExt must be DICT_DICT, fixing it"))
668 type = "DICT_DICT" 672 type = "DICT_DICT"
669 self.bridge.actionResultExt(type, id, data) 673 self.bridge.actionResultExt(type, id, data)
670 674
671 675
672 676
676 @param type: confirmation type ("YES/NO", "FILE_TRANSFERT") 680 @param type: confirmation type ("YES/NO", "FILE_TRANSFERT")
677 @param data: data (depend of confirmation type) 681 @param data: data (depend of confirmation type)
678 @param cb: callback called with the answer 682 @param cb: callback called with the answer
679 """ 683 """
680 if self.__waiting_conf.has_key(id): 684 if self.__waiting_conf.has_key(id):
681 error ("Attempt to register two callbacks for the same confirmation") 685 error (_("Attempt to register two callbacks for the same confirmation"))
682 else: 686 else:
683 self.__waiting_conf[id] = cb 687 self.__waiting_conf[id] = cb
684 self.bridge.askConfirmation(type, id, data) 688 self.bridge.askConfirmation(type, id, data)
685 689
686 690
687 def confirmationAnswer(self, id, accepted, data): 691 def confirmationAnswer(self, id, accepted, data):
688 """Called by frontends to answer confirmation requests""" 692 """Called by frontends to answer confirmation requests"""
689 debug ("Received confirmation answer for id [%s]: %s", id, "accepted" if accepted else "refused") 693 debug (_("Received confirmation answer for id [%(id)s]: %(success)s") % {'id': id, 'success':u("accepted") if accepted else _("refused")})
690 if not self.__waiting_conf.has_key(id): 694 if not self.__waiting_conf.has_key(id):
691 error ("Received an unknown confirmation") 695 error (_("Received an unknown confirmation"))
692 else: 696 else:
693 cb = self.__waiting_conf[id] 697 cb = self.__waiting_conf[id]
694 del self.__waiting_conf[id] 698 del self.__waiting_conf[id]
695 cb(id, accepted, data) 699 cb(id, accepted, data)
696 700
699 self.__progress_cb_map[id] = CB 703 self.__progress_cb_map[id] = CB
700 704
701 def removeProgressCB(self, id): 705 def removeProgressCB(self, id):
702 """Remove a progress callback""" 706 """Remove a progress callback"""
703 if not self.__progress_cb_map.has_key(id): 707 if not self.__progress_cb_map.has_key(id):
704 error ("Trying to remove an unknow progress callback") 708 error (_("Trying to remove an unknow progress callback"))
705 else: 709 else:
706 del self.__progress_cb_map[id] 710 del self.__progress_cb_map[id]
707 711
708 def getProgress(self, id): 712 def getProgress(self, id):
709 """Return a dict with progress information 713 """Return a dict with progress information
723 self.__general_cb_map[name] = CB 727 self.__general_cb_map[name] = CB
724 728
725 def removeGeneralCB(self, name): 729 def removeGeneralCB(self, name):
726 """Remove a general callback""" 730 """Remove a general callback"""
727 if not self.__general_cb_map.has_key(name): 731 if not self.__general_cb_map.has_key(name):
728 error ("Trying to remove an unknow general callback") 732 error (_("Trying to remove an unknow general callback"))
729 else: 733 else:
730 del self.__general_cb_map[name] 734 del self.__general_cb_map[name]
731 735
732 def callGeneralCB(self, name, *args, **kwargs): 736 def callGeneralCB(self, name, *args, **kwargs):
733 """Call general function back""" 737 """Call general function back"""
734 try: 738 try:
735 return self.__general_cb_map[name](*args, **kwargs) 739 return self.__general_cb_map[name](*args, **kwargs)
736 except KeyError: 740 except KeyError:
737 error("Trying to call unknown function") 741 error(_("Trying to call unknown function"))
738 return None 742 return None
739 743
740 application = service.Application('SàT') 744 application = service.Application('SàT')
741 service = SAT() 745 service = SAT()
742 service.setServiceParent(application) 746 service.setServiceParent(application)