From c264e58c2706ce2b3bd6b1d3bc5568a635df1971 Mon Sep 17 00:00:00 2001 From: Romain Lebbadi-Breteau Date: Sun, 3 May 2020 20:23:13 -0400 Subject: [PATCH] improve translations and gui for runtime change of language. V2.1.0 --- CHANGELOG.md | 7 +++--- src/api.py | 27 ++++++++++++-------- src/gui.py | 41 ++++++++++++++++-------------- src/server.py | 6 +++++ src/translate.py | 54 ++++++++++++++++++++++++++-------------- src/translations/en.yaml | 3 +++ src/translations/fr.yaml | 3 +++ 7 files changed, 90 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dbe25e..ee3e743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [2.1.0] - 2020-05-03 ### Added - Trust functionnality - Translation of all messages in French - Translation of all messages in English -- Settings +- Persistent settings for username and language +- Translation language can be changed during execution ### Fixed - Messages received when connexion not trusted are buffered instead of diplayed @@ -230,7 +231,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Basic server and client - Use regex to parse commands -[Unreleased]: https://github.com/RomainL972/isn/compare/v2.0.0...HEAD +[2.1.0]: https://github.com/RomainL972/isn/compare/v2.0.0...v2.1.0 [2.0.0]: https://github.com/RomainL972/isn/compare/v1.1.1...v2.0.0 [1.1.1]: https://github.com/RomainL972/isn/compare/v1.1.0...v1.1.1 [1.1.0]: https://github.com/RomainL972/isn/compare/v1.0.0...v1.1.0 diff --git a/src/api.py b/src/api.py index c7aa596..ce938dd 100644 --- a/src/api.py +++ b/src/api.py @@ -2,13 +2,14 @@ from server import SocketServer from backend import TuringChat from trust import TrustManager -from translate import tr +from translate import Translate, setObject from settings import Settings import re class Interface(): def __init__(self, uiPrintMessage, sendQuit=None): + self.settings = Settings(self.printMessage) self.turing = TuringChat() self.client = None self.server = None @@ -17,11 +18,12 @@ def __init__(self, uiPrintMessage, sendQuit=None): self.connexion = None self.server = SocketServer(self.turing, self.printMessage, self.writeMessages) self.client = SocketClient(self.turing, self.printMessage, self.writeMessages) - self.username = None + self.username = self.settings.getSetting("username") self.otherUsername = None self.trustManager = TrustManager(self.printMessage) self.msgBuffer = [] - self.settings = Settings(self.printMessage) + self.translate = Translate(self.printMessage, self.settings.getSetting("language")) + setObject(self.translate) def printMessage(self, text, message=False, username=None): if message and not self.trustManager.connexionTrusted(): @@ -45,7 +47,7 @@ def startServer(self): self.server.start() def stopServer(self): - if self.server.listening(): + if self.server.listening() or self.server.isStopped(): self.server.stop() self.server.join() self.server = SocketServer(self.turing, self.printMessage, self.writeMessages) @@ -59,9 +61,10 @@ def stopClient(self): def setUsername(self, username): self.username = username + self.settings.setSetting("username", username) if self.connexion: self.connexion.send(self.turing.createMessage("username", username)) - self.printMessage(tr("username.changed") + username) + self.printMessage(self.translate.tr("username.changed") + username) def parseCommand(self, command): regex = re.search("^/([a-z]*)( ([a-zA-Z0-9\\.]*))?$", command) @@ -90,17 +93,21 @@ def parseCommand(self, command): self.trustManager.setTrust(arg) elif(command == "fingerprint"): self.printMessage(self.turing.getMyFingerprint()) + elif(command == "language" and (arg == "en" or arg == "fr")): + self.translate.setLanguage(arg) + self.settings.setSetting("language", arg) + self.printMessage(self.translate.tr("language.set")) elif(command == "help"): - helpText = tr("command.help.text") + helpText = self.translate.tr("command.help.text") self.printMessage(helpText) else: - self.printMessage(tr("error.incorrect.command")) + self.printMessage(self.translate.tr("error.incorrect.command")) else: if not self.connexion: - self.printMessage(tr("error.not.connected")) + self.printMessage(self.translate.tr("error.not.connected")) return if not self.trustManager.connexionTrusted(): - self.printMessage(tr("error.connexion.not.trusted")) + self.printMessage(self.translate.tr("error.connexion.not.trusted")) return - self.printMessage(tr("user.you") + command) + self.printMessage(self.translate.tr("user.you") + command) self.connexion.send(self.turing.createMessage("message", command)) diff --git a/src/gui.py b/src/gui.py index 3e9d025..af88093 100755 --- a/src/gui.py +++ b/src/gui.py @@ -8,6 +8,7 @@ interface = None stop = False +msg_list = None def quit(): @@ -16,7 +17,7 @@ def quit(): def disc(): - global interface + global interface, writeMsgFunc, msg_list for c in wd.winfo_children(): c.destroy() msg = StringVar() # pour le message qui sera envoyé @@ -27,24 +28,8 @@ def disc(): chp = Entry(wd, width=70, font=(22), bg="#56646A", fg="white", bd=2, relief=SUNKEN, textvariable=msg) chp.pack(side=BOTTOM, pady=10) - def writeMsg(msg, message=False, username=None): - if username: - interface.otherUsername = username - return writeMsg(tr("username.other.changed") + username) - global stop - if stop: - return - msg_list.config(state=NORMAL) - if message: - username = interface.otherUsername - if(not username): - username = tr("user.other") - msg_list.insert(END, username + " : ") - msg_list.insert(END, msg + "\n") - msg_list.see(END) - msg_list.config(state=DISABLED) - - interface = api.Interface(writeMsg, quit) + #interface = api.Interface(writeMsg, quit) + writeMsgFunc = writeMsg def send(e): Thread(target=interface.parseCommand, args=[msg.get()]).start() @@ -52,6 +37,24 @@ def send(e): chp.bind("", send) # definir "send" comme envoyer le message +def writeMsg(msg, message=False, username=None): + if username: + interface.otherUsername = username + return writeMsg(tr("username.other.changed") + username) + global stop + if stop: + return + msg_list.config(state=NORMAL) + if message: + username = interface.otherUsername + if(not username): + username = tr("user.other") + msg_list.insert(END, username + " : ") + msg_list.insert(END, msg + "\n") + msg_list.see(END) + msg_list.config(state=DISABLED) + +interface = api.Interface(writeMsg, quit) # creer une fenetre wd.title(tr("app.title")) diff --git a/src/server.py b/src/server.py index 0ef1fe6..ed48b26 100644 --- a/src/server.py +++ b/src/server.py @@ -23,6 +23,7 @@ def __init__(self, turing, printMessage, rdyWrite, host='0.0.0.0', port=1234): self.sock_threads = [] self.sock = None self.__stop = False + self.stopped = False def listening(self): return not not self.sock @@ -75,6 +76,8 @@ def close(self): self.upnp.deleteportmapping(self.port, 'TCP') except Exception: self.printMessage(tr("upnp.error.remove")) + + self.stopped = True def run(self): """ Accept an incoming connection. @@ -101,3 +104,6 @@ def run(self): def stop(self): self.__stop = True + + def isStopped(self): + return self.stopped diff --git a/src/translate.py b/src/translate.py index f3c7e42..282b359 100644 --- a/src/translate.py +++ b/src/translate.py @@ -1,28 +1,44 @@ import yaml import os -data = {} +class Translate(): + def __init__(self, printMessage, language): + self.printMessage = printMessage + self.language = language + self.messages = {} + self.loadTranslations() -def loadMessages(language="fr"): - global data + def loadTranslations(self): + script_dir = os.path.dirname(__file__) + rel_path = "translations/" + self.language + ".yaml" - script_dir = os.path.dirname(__file__) - rel_path = "translations/" + language + ".yaml" + with open(os.path.join(script_dir, rel_path), 'r') as stream: + try: + self.messages = yaml.safe_load(stream) + except yaml.YAMLError as exc: + self.printMessage("error.yaml") - with open(os.path.join(script_dir, rel_path), 'r') as stream: - try: - data = yaml.safe_load(stream) - except yaml.YAMLError as exc: - print(exc) + def getMessage(self, data, keys): + if isinstance(data, str): + return data + key = keys.pop(0) + return self.getMessage(data[key], keys) -def getMessage(data, keys): - if isinstance(data, str): - return data - key = keys.pop(0) - return getMessage(data[key], keys) + def tr(self, message): + keys = message.split(".") + return self.getMessage(self.messages, keys) -def tr(message): - keys = message.split(".") - return getMessage(data, keys) + def setLanguage(self, language): + self.language = language + self.loadTranslations() + +translate = None -loadMessages() +def setObject(object): + global translate + translate = object + +def tr(message): + if translate: + return translate.tr(message) + return "" diff --git a/src/translations/en.yaml b/src/translations/en.yaml index 4125d1e..84c96fc 100644 --- a/src/translations/en.yaml +++ b/src/translations/en.yaml @@ -10,6 +10,7 @@ command: - /nick : Change username - /trust : Choose trust level (0: never, 1: once, 2: always) - /fingerprint: Show the fingerprint of my public key + - /language : Set the language - message : Send a message error: incorrect: @@ -77,3 +78,5 @@ trust: saved: blacklist: "Blacklist saved" whitelist: "Trust saved" +language: + set: Language set to English diff --git a/src/translations/fr.yaml b/src/translations/fr.yaml index 2af90dd..f577361 100644 --- a/src/translations/fr.yaml +++ b/src/translations/fr.yaml @@ -10,6 +10,7 @@ command: - /nick : Changer le username - /trust : Choisis le niveau de confiance (0: jamais, 1: une fois, 2: toujours) - /fingerprint: Affiche la fingerprint de ma clé + - /language : Choisir la langue - message : Envoie un message error: incorrect: @@ -77,3 +78,5 @@ trust: saved: blacklist: "Blacklist enregistré" whitelist: "Confiance enregistrée" +language: + set: Langue mise à Français