i18n first draft

- gettext support added in SàT
- first draft of french translation
- added README with a HOWTO for translators
This commit is contained in:
Goffi 2010-03-03 17:12:23 +11:00
commit 4a293cdaa1
5 changed files with 1463 additions and 153 deletions

View file

@ -59,13 +59,13 @@ PLUGIN_INFO = {
"dependencies": [],
"main": "XEP_0054",
"handler": "yes",
"description": """Implementation of vcard-temp"""
"description": _("""Implementation of vcard-temp""")
}
class XEP_0054():
def __init__(self, host):
info("Plugin XEP_0054 initialization")
info(_("Plugin XEP_0054 initialization"))
self.host = host
self.avatar_path = os.path.expanduser(self.host.get_const('local_dir') + AVATAR_PATH)
self.vcard_cache = host.memory.getPrivate("vcard_cache") or {} #used to store nicknames and avatar, key = jid
@ -108,24 +108,24 @@ class XEP_0054():
"""Parse a <PHOTO> elem and save the picture"""
for elem in photo_xml.elements():
if elem.name == 'TYPE':
info('Photo of type [%s] found' % str(elem))
info(_('Photo of type [%s] found') % str(elem))
if elem.name == 'BINVAL':
debug('Decoding binary')
debug(_('Decoding binary'))
decoded = b64decode(str(elem))
hash = sha1(decoded).hexdigest()
filename = self.avatar_path+'/'+hash
if not os.path.exists(filename):
with open(filename,'wb') as file:
file.write(decoded)
debug("file saved to %s" % hash)
debug(_("file saved to %s") % hash)
else:
debug("file [%s] already in cache" % hash)
debug(_("file [%s] already in cache") % hash)
return hash
@defer.deferredGenerator
def vCard2Dict(self, vcard, target):
"""Convert a VCard to a dict, and save binaries"""
debug ("parsing vcard")
debug (_("parsing vcard"))
dictionary = {}
d = defer.Deferred()
@ -151,24 +151,24 @@ class XEP_0054():
else:
self.update_cache(target, 'avatar', dictionary['avatar'])
else:
info ('FIXME: [%s] VCard tag is not managed yet' % elem.name)
info (_('FIXME: [%s] VCard tag is not managed yet') % elem.name)
yield dictionary
def vcard_ok(self, answer):
"""Called after the first get IQ"""
debug ("VCard found")
debug (_("VCard found"))
if answer.firstChildElement().name == "vCard":
d = self.vCard2Dict(answer.firstChildElement(), jid.JID(answer["from"]))
d.addCallback(lambda data: self.host.bridge.actionResult("RESULT", answer['id'], data))
else:
error ("FIXME: vCard not found as first child element")
error (_("FIXME: vCard not found as first child element"))
self.host.bridge.actionResult("SUPPRESS", answer['id'], {}) #FIXME: maybe an error message would be best
def vcard_err(self, failure):
"""Called when something is wrong with registration"""
error ("Can't find VCard of %s" % failure.value.stanza['from'])
error (_("Can't find VCard of %s") % failure.value.stanza['from'])
self.host.bridge.actionResult("SUPPRESS", failure.value.stanza['id'], {}) #FIXME: maybe an error message would be best
def getCard(self, target, profile_key='@DEFAULT@'):
@ -177,10 +177,10 @@ class XEP_0054():
@result: id to retrieve the profile"""
current_jid, xmlstream = self.host.getJidNStream(profile_key)
if not xmlstream:
error ('Asking profile for an non-existant or not connected profile')
error (_('Asking vcard for an non-existant or not connected profile'))
return ""
to_jid = jid.JID(target)
debug("Asking for %s's VCard" % to_jid.userhost())
debug(_("Asking for %s's VCard") % to_jid.userhost())
reg_request=IQ(xmlstream,'get')
reg_request["from"]=current_jid.full()
reg_request["to"] = to_jid.userhost()
@ -195,7 +195,7 @@ class XEP_0054():
"""
filename = self.avatar_path+'/'+hash
if not os.path.exists(filename):
error ("Asking for an uncached avatar [%s]" % hash)
error (_("Asking for an uncached avatar [%s]") % hash)
return ""
return filename
@ -242,5 +242,5 @@ class XEP_0054_handler(XMPPHandler):
hash = str(elem)
old_avatar = self.plugin_parent.get_cache(to_jid, 'avatar')
if not old_avatar or old_avatar != hash:
debug('New avatar found, requesting vcard')
debug(_('New avatar found, requesting vcard'))
self.plugin_parent.getCard(to_jid.userhost(), self.parent.profile)

View file

@ -86,7 +86,7 @@ PLUGIN_INFO = {
"protocols": ["XEP-0065"],
"main": "XEP_0065",
"handler": "yes",
"description": """Implementation of SOCKS5 Bytestreams"""
"description": _("""Implementation of SOCKS5 Bytestreams""")
}
STATE_INITIAL = 0
@ -132,7 +132,7 @@ REPLY_ADDR_NOT_SUPPORTED = 0x08
class SOCKSv5(protocol.Protocol, FileSender):
def __init__(self):
debug("Protocol init")
debug(_("Protocol init"))
self.state = STATE_INITIAL
self.buf = ""
self.supportedAuthMechs = [ AUTHMECH_ANON ]
@ -214,7 +214,7 @@ class SOCKSv5(protocol.Protocol, FileSender):
self.transport.loseConnection()
def addConnection(self, address, connection):
info("Adding connection: %s, %s", address, connection)
info(_("Adding connection: %(address)s, %(connection)s") % {'address':address, 'connection':connection})
olist = self.pendingConns.get(address, [])
if len(olist) <= 1:
olist.append(connection)
@ -310,7 +310,7 @@ class SOCKSv5(protocol.Protocol, FileSender):
self.loseConnection()
return
debug("Saving file in %s.", self.data["dest_path"])
debug(_("Saving file in %s."), self.data["dest_path"])
self.dest_file = open(self.data["dest_path"], 'w')
self.state = STATE_TARGET_READY
self.activateCB(self.target_jid, self.initiator_jid, self.sid, self.IQ_id, self.xmlstream)
@ -328,7 +328,7 @@ class SOCKSv5(protocol.Protocol, FileSender):
self._startNegotiation()
def connectRequested(self, addr, port):
debug(("connectRequested"))
debug("connectRequested")
# Check for special connect to the namespace -- this signifies that the client
# is just checking to ensure it can connect to the streamhost
if addr == "http://jabber.org/protocol/bytestreams":
@ -361,7 +361,7 @@ class SOCKSv5(protocol.Protocol, FileSender):
data["position"] = ""
def fileTransfered(self, d):
info("File transfer completed, closing connection")
info(_("File transfer completed, closing connection"))
self.transport.loseConnection()
def updateTransfered(self, data):
@ -435,20 +435,20 @@ class Socks5ServerFactory(protocol.ServerFactory):
def startedConnecting(self, connector):
debug ("Socks 5 server connection started")
debug (_("Socks 5 server connection started"))
def clientConnectionLost(self, connector, reason):
debug ("Socks 5 server connection lost (reason: %s)", reason)
debug (_("Socks 5 server connection lost (reason: %s)"), reason)
class Socks5ClientFactory(protocol.ClientFactory):
protocol = SOCKSv5
protocol.mode = "target" #FIXME: Q&D way, fix it
def startedConnecting(self, connector):
debug ("Socks 5 client connection started")
debug (_("Socks 5 client connection started"))
def clientConnectionLost(self, connector, reason):
debug ("Socks 5 client connection lost (reason: %s)", reason)
debug (_("Socks 5 client connection lost (reason: %s)"), reason)
class XEP_0065():
@ -465,9 +465,9 @@ class XEP_0065():
"""
def __init__(self, host):
info("Plugin XEP_0065 initialization")
info(_("Plugin XEP_0065 initialization"))
self.host = host
debug("registering")
debug(_("registering"))
self.server_factory = Socks5ServerFactory()
self.server_factory.protocol.host = self.host #needed for progress CB
self.client_factory = Socks5ClientFactory()
@ -477,7 +477,7 @@ class XEP_0065():
host.memory.setDefault("IP", "File Transfert", self.getExternalIP)
port = int(self.host.memory.getParamA("Port", "File Transfert"))
info("Launching Socks5 Stream server on port %d", port)
info(_("Launching Socks5 Stream server on port %d"), port)
reactor.listenTCP(port, self.server_factory)
def getHandler(self):
@ -493,7 +493,7 @@ class XEP_0065():
def sendFile(self, id, filepath, size):
#lauching socks5 initiator
debug("Launching socks5 initiator")
debug(_("Launching socks5 initiator"))
self.server_factory.protocol.mode = "initiator"
self.server_factory.protocol.filepath = filepath
self.server_factory.protocol.filesize = size
@ -508,7 +508,7 @@ class XEP_0065():
IQ_id = iq['id']
for element in SI_elem.elements():
if element.name == "streamhost":
info ("Stream proposed: host=[%s] port=[%s]", element['host'], element['port'])
info (_("Stream proposed: host=[%(host)s] port=[%(post)s]") % {'host':element['host'], 'port':element['port']})
factory = self.client_factory
self.server_factory.protocol.mode = "target"
factory.protocol.host = self.host #needed for progress CB
@ -524,7 +524,7 @@ class XEP_0065():
reactor.connectTCP(element['host'], int(element['port']), factory)
def activateStream(self, from_jid, to_jid, sid, IQ_id, xmlstream):
debug("activating stream")
debug(_("activating stream"))
result = domish.Element(('', 'iq'))
result['type'] = 'result'
result['id'] = IQ_id

View file

@ -38,13 +38,13 @@ PLUGIN_INFO = {
"protocols": ["XEP-0077"],
"dependencies": [],
"main": "XEP_0077",
"description": """Implementation of in-band registration"""
"description": _("""Implementation of in-band registration""")
}
class XEP_0077():
def __init__(self, host):
info("Plugin XEP_0077 initialization")
info(_("Plugin XEP_0077 initialization"))
self.host = host
self.triggers = {} #used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid
host.bridge.addMethod("in_band_register", ".communication", in_sign='ss', out_sign='s', method=self.in_band_register)
@ -59,10 +59,10 @@ class XEP_0077():
try:
x_elem = filter (lambda x:x.name == "x", answer.firstChildElement().elements())[0] #We only want the "x" element (data form)
except IndexError:
info("No data form found")
info(_("No data form found"))
#TODO: manage registration without data form
answer_data = {}
answer_data={"reason": "unmanaged", "message":"This gateway can't be managed by SàT, sorry :("}
answer_data={"reason": "unmanaged", "message":_("This gateway can't be managed by SàT, sorry :(")}
answer_type = "ERROR"
self.host.bridge.actionResult(answer_type, answer['id'], answer_data)
return
@ -73,7 +73,7 @@ class XEP_0077():
def reg_err(self, failure):
"""Called when something is wrong with registration"""
info ("Registration failure: %s" % str(failure.value))
info (_("Registration failure: %s") % str(failure.value))
answer_data = {}
answer_data['reason'] = 'unknown'
answer_data={"message":"%s [code: %s]" % (failure.value.condition, failure.value.code)}
@ -81,39 +81,39 @@ class XEP_0077():
self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data)
def unregistrationAnswer(self, answer):
debug ("registration answer: %s" % answer.toXml())
debug (_("registration answer: %s") % answer.toXml())
answer_type = "SUCCESS"
answer_data={"message":"Your are now unregistred"}
answer_data={"message":_("Your are now unregistred")}
self.host.bridge.actionResult(answer_type, answer['id'], answer_data)
def unregistrationFailure(self, failure):
info ("Unregistration failure: %s" % str(failure.value))
info (_("Unregistration failure: %s") % str(failure.value))
answer_type = "ERROR"
answer_data = {}
answer_data['reason'] = 'unknown'
answer_data={"message":"Unregistration failed: %s" % failure.value.condition}
answer_data={"message":_("Unregistration failed: %s") % failure.value.condition}
self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data)
def registrationAnswer(self, answer):
debug ("registration answer: %s" % answer.toXml())
debug (_("registration answer: %s") % answer.toXml())
answer_type = "SUCCESS"
answer_data={"message":"Registration successfull"}
answer_data={"message":_("Registration successfull")}
self.host.bridge.actionResult(answer_type, answer['id'], answer_data)
if self.triggers.has_key(answer["from"]):
self.triggers[answer["from"]](answer["from"])
del self.triggers[answer["from"]]
def registrationFailure(self, failure):
info ("Registration failure: %s" % str(failure.value))
info (_("Registration failure: %s") % str(failure.value))
print failure.value.stanza.toXml()
answer_type = "ERROR"
answer_data = {}
if failure.value.condition == 'conflict':
answer_data['reason'] = 'conflict'
answer_data={"message":"Username already exists, please choose an other one"}
answer_data={"message":_("Username already exists, please choose an other one")}
else:
answer_data['reason'] = 'unknown'
answer_data={"message":"Registration failed"}
answer_data={"message":_("Registration failed")}
self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data)
if self.triggers.has_key(answer["from"]):
del self.triggers[answer["from"]]
@ -131,10 +131,10 @@ class XEP_0077():
"""register to a target JID"""
current_jid, xmlstream = self.host.getJidNStream(profile_key)
if not xmlstream:
error ('Asking profile for an non-existant or not connected profile')
error (_('Asking for an non-existant or not connected profile'))
return ""
to_jid = jid.JID(target)
debug("Asking registration for [%s]" % to_jid.full())
debug(_("Asking registration for [%s]") % to_jid.full())
reg_request=IQ(xmlstream,'get')
reg_request["from"]=current_jid.full()
reg_request["to"] = to_jid.full()

View file

@ -49,13 +49,13 @@ PLUGIN_INFO = {
"dependencies": ["XEP_0065"],
"main": "XEP_0096",
"handler": "yes",
"description": """Implementation of SI File Transfert"""
"description": _("""Implementation of SI File Transfert""")
}
class XEP_0096():
def __init__(self, host):
info("Plugin XEP_0096 initialization")
info(_("Plugin XEP_0096 initialization"))
self.host = host
self._waiting_for_approval = {}
host.bridge.addMethod("sendFile", ".communication", in_sign='sss', out_sign='s', method=self.sendFile)
@ -64,7 +64,7 @@ class XEP_0096():
return XEP_0096_handler(self)
def xep_96(self, IQ, profile):
info ("XEP-0096 management")
info (_("XEP-0096 management"))
IQ.handled=True
SI_elem = IQ.firstChildElement()
debug(SI_elem.toXml())
@ -72,7 +72,7 @@ class XEP_0096():
file_size = ""
for element in SI_elem.elements():
if element.name == "file":
info ("File proposed: name=[%s] size=%s", element['name'], element['size'])
info (_("File proposed: name=[%(name)s] size=%(size)s") % {'name':element['name'], 'size':element['size']})
filename = element["name"]
file_size = element["size"]
elif element.name == "feature":
@ -88,15 +88,15 @@ class XEP_0096():
self.host.plugins["XEP_0065"].setData(data, id)
self.approved(id)
else:
debug ("Transfert [%s] refused", id)
debug (_("Transfert [%s] refused"), id)
del(self._waiting_for_approval[id])
def approved(self, id):
"""must be called when a file transfert has be accepted by client"""
debug ("Transfert [%s] accepted", id)
debug (_("Transfert [%s] accepted"), id)
if ( not self._waiting_for_approval.has_key(id) ):
error ("Approved unknow id !")
error (_("Approved unknow id !"))
#TODO: manage this (maybe approved by several frontends)
else:
element, from_id, size, profile = self._waiting_for_approval[id]
@ -108,7 +108,7 @@ class XEP_0096():
#FIXME: over ultra mega ugly, need to be generic
client = self.host.getClient(profile)
assert(client)
info ("Feature negociation")
info (_("Feature negociation"))
data = feat_elem.firstChildElement()
field = data.firstChildElement()
#FIXME: several options ! Q&D code for test only
@ -151,7 +151,7 @@ class XEP_0096():
"""
current_jid, xmlstream = self.host.getJidNStream(profile_key)
if not xmlstream:
error ('Asking profile for an non-existant or not connected profile')
error (_('Asking for an non-existant or not connected profile'))
return ""
debug ("sendfile (%s) to %s", filepath, to )
print type(filepath), type(to)

View file

@ -34,13 +34,13 @@ PLUGIN_INFO = {
"protocols": ["XEP-0100"],
"dependencies": ["XEP_0077"],
"main": "XEP_0100",
"description": """Implementation of Gateways protocol"""
"description": _("""Implementation of Gateways protocol""")
}
class XEP_0100():
def __init__(self, host):
info("Gateways plugin initialization")
info(_("Gateways plugin initialization"))
self.host = host
self.__gateways = {} #dict used to construct the answer to findGateways. Key = target jid
host.bridge.addMethod("findGateways", ".communication", in_sign='ss', out_sign='s', method=self.findGateways)
@ -50,7 +50,7 @@ class XEP_0100():
self.__gateways[request_id]['__handled_items']+=1
if self.__gateways[request_id]['__total_items'] == self.__gateways[request_id]['__handled_items']:
debug ("All items checked for id [%s]" % str(request_id))
debug (_("All items checked for id [%s]") % str(request_id))
del self.__gateways[request_id]['__total_items']
del self.__gateways[request_id]['__handled_items']
@ -61,7 +61,7 @@ class XEP_0100():
for identity in disco.identities:
if identity[0] == 'gateway':
print ("Found gateway (%s): %s" % (entity.full(), disco.identities[identity]))
print (_("Found gateway (%(jid)s): %(identity)s") % {'jid':entity.full(), 'identity':disco.identities[identity]})
self.__gateways[request_id][entity.full()] = {
'name':disco.identities[identity],
'type':identity[1]
@ -72,7 +72,7 @@ class XEP_0100():
def discoInfoErr(self, failure, entity, request_id):
"""Something is going wrong with disco"""
failure.trap(jab_error.StanzaError)
error("Error when discovering [%s]: %s" % (entity.full(), failure.value.condition))
error(_("Error when discovering [%(jid)s]: %(condition)s") % {'jid':entity.full(), 'condition':failure.value.condition})
self.__inc_handled_items(request_id)
@ -81,19 +81,19 @@ class XEP_0100():
#FIXME: target is used as we can't find the original iq node (parent is None)
# an other way would avoid this useless parameter (is there a way with wokkel ?)
if len(disco._items) == 0:
debug ("No gateway found")
debug (_("No gateway found"))
self.host.actionResultExt(request_id,"DICT_DICT",{})
return
self.__gateways[request_id] = {'__total_items':len(disco._items), '__handled_items':0, '__private__':{'target':target.full()}}
for item in disco._items:
debug ("item found: %s", item.name)
debug (_("item found: %s"), item.name)
client.disco.requestInfo(item.entity).addCallback(self.discoInfo, entity=item.entity, request_id=request_id)
client.disco.requestInfo(item.entity).addErrback(self.discoInfoErr, entity=item.entity, request_id=request_id)
def registrationSuccessful(self, target):
"""Called when in_band registration is ok, we must now follow the rest of procedure"""
print "Registration successful, doing the rest"
debug (_("Registration successful, doing the rest"))
self.host.addContact(target)
self.host.setPresence(target)
@ -109,9 +109,8 @@ class XEP_0100():
"""
client = self.host.getClient(profile_key)
assert(client)
print "target ===>", target
to_jid = jid.JID(target)
debug ("find gateways (target = %s)" % to_jid.full())
debug (_("find gateways (target = %s)") % to_jid.full())
request_id = self.host.get_next_id()
client.disco.requestItems(to_jid).addCallback(self.discoItems, request_id=request_id, target = to_jid, client = client)
return request_id