From b12860f7d7dedd3463ef1bb988bd6b166128f388 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 5 Jan 2024 18:05:34 +0100 Subject: [PATCH] Added multilingual text input options --- sbapp/buildozer.spec | 2 +- sbapp/main.py | 110 ++++++++++++++++++++++++++++-- sbapp/sideband/core.py | 5 ++ sbapp/ui/announces.py | 12 +++- sbapp/ui/conversations.py | 17 ++++- sbapp/ui/helpers.py | 1 + sbapp/ui/layouts.py | 139 +++++++++++++++++++++++++++++++++++++- sbapp/ui/messages.py | 2 + sbapp/ui/objectdetails.py | 9 ++- sbapp/ui/telemetry.py | 8 ++- 10 files changed, 287 insertions(+), 18 deletions(-) diff --git a/sbapp/buildozer.spec b/sbapp/buildozer.spec index 78dd030..1797ed8 100644 --- a/sbapp/buildozer.spec +++ b/sbapp/buildozer.spec @@ -10,7 +10,7 @@ source.exclude_patterns = app_storage/*,venv/*,Makefile,./Makefil*,requirements, version.regex = __version__ = ['"](.*)['"] version.filename = %(source.dir)s/main.py -android.numeric_version = 20240103 +android.numeric_version = 20240105 # Cryptography recipe is currently broken, using RNS-internal crypto for now requirements = kivy==2.2.1,libbz2,pillow,qrcode==7.3.1,usb4a,usbserial4a diff --git a/sbapp/main.py b/sbapp/main.py index dfedba6..a240057 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -69,8 +69,8 @@ if args.daemon: colors = DaemonElement; Telemeter = DaemonElement; CustomMapMarker = DaemonElement; MBTilesMapSource = DaemonElement; MapSource = DaemonElement; webbrowser = DaemonElement; Conversations = DaemonElement; MsgSync = DaemonElement; NewConv = DaemonElement; Telemetry = DaemonElement; ObjectDetails = DaemonElement; Announces = DaemonElement; - Messages = DaemonElement; ts_format = DaemonElement; messages_screen_kv = DaemonElement; plyer = DaemonElement; - ContentNavigationDrawer = DaemonElement; DrawerList = DaemonElement; IconListItem = DaemonElement; + Messages = DaemonElement; ts_format = DaemonElement; messages_screen_kv = DaemonElement; plyer = DaemonElement; multilingual_markup = DaemonElement; + ContentNavigationDrawer = DaemonElement; DrawerList = DaemonElement; IconListItem = DaemonElement; escape_markup = DaemonElement; else: from kivymd.app import MDApp @@ -96,6 +96,7 @@ else: from mapview import CustomMapMarker from mapview.mbtsource import MBTilesMapSource from mapview.source import MapSource + from kivy.utils import escape_markup import webbrowser import kivy.core.image kivy.core.image.Logger = redirect_log() @@ -110,6 +111,7 @@ else: from ui.announces import Announces from ui.messages import Messages, ts_format, messages_screen_kv from ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem + from ui.helpers import multilingual_markup from jnius import cast from jnius import autoclass @@ -130,6 +132,7 @@ else: from .ui.objectdetails import ObjectDetails from .ui.messages import Messages, ts_format, messages_screen_kv from .ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem + from .ui.helpers import multilingual_markup from kivy.config import Config Config.set('input', 'mouse', 'mouse,disable_multitouch') @@ -180,6 +183,7 @@ class SidebandApp(MDApp): self.set_ui_theme() self.font_config() + self.update_input_language() self.dark_theme_text_color = dark_theme_text_color self.conversations_view = None @@ -367,7 +371,21 @@ class SidebandApp(MDApp): LabelBase.register(name="emoji", fn_regular=fb_path+"NotoEmoji-Regular.ttf") - + LabelBase.register(name="combined", + fn_regular=fb_path+"NotoSans-Regular.ttf", + fn_bold=fb_path+"NotoSans-Bold.ttf", + fn_italic=fb_path+"NotoSans-Italic.ttf", + fn_bolditalic=fb_path+"NotoSans-BoldItalic.ttf") + + def update_input_language(self): + language = self.sideband.config["input_language"] + if language == None: + self.input_font = "Roboto" + RNS.log("Setting input language to default set", RNS.LOG_DEBUG) + else: + self.input_font = language + RNS.log("Setting input language to "+str(language), RNS.LOG_DEBUG) + def update_ui_colors(self): if self.sideband.config["dark_ui"]: @@ -1071,7 +1089,8 @@ class SidebandApp(MDApp): self.messages_view.ids.messages_scrollview.add_widget(list_widget) self.messages_view.ids.messages_scrollview.scroll_y = 0.0 - self.messages_view.ids.messages_toolbar.title = self.sideband.peer_display_name(context_dest) + conv_title = multilingual_markup(escape_markup(str(self.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8") + self.messages_view.ids.messages_toolbar.title = conv_title self.messages_view.ids.messages_scrollview.active_conversation = context_dest self.sideband.setstate("app.active_conversation", context_dest) @@ -1629,6 +1648,8 @@ class SidebandApp(MDApp): self.settings_screen.ids.settings_scrollview.effect_cls = ScrollEffect + self.settings_screen.ids.settings_info_lang.text = "\nIf you write messages in another script than Latin, Greek or Cyrillic, you can configure the text input language for messages and other fields below.\n" + info1_text = "\nYou can set your [b]Display Name[/b] to a custom value, or leave it as the default unspecified value. " info1_text += "This name will be included in any announces you send, and will be visible to others on the network. " info1_text += "\n\nYou can manually specify which [b]Propagation Node[/b] to use, but if none is specified, Sideband will " @@ -1676,6 +1697,54 @@ class SidebandApp(MDApp): self.sideband.config["lxmf_propagation_node"] = new_addr self.sideband.set_active_propagation_node(self.sideband.config["lxmf_propagation_node"]) + def save_input_lang(sender=None, event=None): + if sender.active: + if sender != self.settings_screen.ids.settings_lang_default: + self.settings_screen.ids.settings_lang_default.active = False + + if sender != self.settings_screen.ids.settings_lang_chinese: + self.settings_screen.ids.settings_lang_chinese.active = False + + if sender != self.settings_screen.ids.settings_lang_japanese: + self.settings_screen.ids.settings_lang_japanese.active = False + + if sender != self.settings_screen.ids.settings_lang_korean: + self.settings_screen.ids.settings_lang_korean.active = False + + if sender != self.settings_screen.ids.settings_lang_devangari: + self.settings_screen.ids.settings_lang_devangari.active = False + + if sender != self.settings_screen.ids.settings_lang_hebrew: + self.settings_screen.ids.settings_lang_hebrew.active = False + + RNS.log("Sender: "+str(sender)) + + if self.settings_screen.ids.settings_lang_default.active: + self.sideband.config["input_language"] = None + self.settings_screen.ids.settings_display_name.font_name = "" + elif self.settings_screen.ids.settings_lang_chinese.active: + self.sideband.config["input_language"] = "chinese" + self.settings_screen.ids.settings_display_name.font_name = "chinese" + elif self.settings_screen.ids.settings_lang_japanese.active: + self.sideband.config["input_language"] = "japanese" + self.settings_screen.ids.settings_display_name.font_name = "japanese" + elif self.settings_screen.ids.settings_lang_korean.active: + self.sideband.config["input_language"] = "korean" + self.settings_screen.ids.settings_display_name.font_name = "korean" + elif self.settings_screen.ids.settings_lang_devangari.active: + self.sideband.config["input_language"] = "combined" + self.settings_screen.ids.settings_display_name.font_name = "combined" + elif self.settings_screen.ids.settings_lang_hebrew.active: + self.sideband.config["input_language"] = "hebrew" + self.settings_screen.ids.settings_display_name.font_name = "hebrew" + else: + self.sideband.config["input_language"] = None + self.settings_screen.ids.settings_display_name.font_name = "" + + + self.sideband.save_configuration() + self.update_input_language() + def save_dark_ui(sender=None, event=None): self.sideband.config["dark_ui"] = self.settings_screen.ids.settings_dark_ui.active self.sideband.save_configuration() @@ -1840,6 +1909,39 @@ class SidebandApp(MDApp): self.settings_screen.ids.settings_debug.active = self.sideband.config["debug"] self.settings_screen.ids.settings_debug.bind(active=save_debug) + self.settings_screen.ids.settings_lang_default.active = False + self.settings_screen.ids.settings_lang_chinese.active = False + self.settings_screen.ids.settings_lang_japanese.active = False + self.settings_screen.ids.settings_lang_korean.active = False + self.settings_screen.ids.settings_lang_devangari.active = False + self.settings_screen.ids.settings_lang_default.bind(active=save_input_lang) + self.settings_screen.ids.settings_lang_chinese.bind(active=save_input_lang) + self.settings_screen.ids.settings_lang_japanese.bind(active=save_input_lang) + self.settings_screen.ids.settings_lang_korean.bind(active=save_input_lang) + self.settings_screen.ids.settings_lang_devangari.bind(active=save_input_lang) + self.settings_screen.ids.settings_lang_hebrew.bind(active=save_input_lang) + input_lang = self.sideband.config["input_language"] + if input_lang == None: + self.settings_screen.ids.settings_lang_default.active = True + self.settings_screen.ids.settings_display_name.font_name = "" + elif input_lang == "chinese": + self.settings_screen.ids.settings_lang_chinese.active = True + self.settings_screen.ids.settings_display_name.font_name = "chinese" + elif input_lang == "japanese": + self.settings_screen.ids.settings_lang_japanese.active = True + self.settings_screen.ids.settings_display_name.font_name = "japanese" + elif input_lang == "korean": + self.settings_screen.ids.settings_lang_korean.active = True + self.settings_screen.ids.settings_display_name.font_name = "korean" + elif input_lang == "devangari": + self.settings_screen.ids.settings_lang_devangari.active = True + self.settings_screen.ids.settings_display_name.font_name = "combined" + elif input_lang == "hebrew": + self.settings_screen.ids.settings_lang_hebrew.active = True + self.settings_screen.ids.settings_display_name.font_name = "hebrew" + else: + self.settings_screen.ids.settings_display_name.font_name = "" + self.settings_ready = True def close_settings_action(self, sender=None): diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index e389f14..5325aca 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -414,6 +414,11 @@ class SidebandCore(): if not "display_style_in_contact_list" in self.config: self.config["display_style_in_contact_list"] = False + if not "input_language" in self.config: + self.config["input_language"] = None + if not "allow_predictive_text" in self.config: + self.config["allow_predictive_text"] = False + if not "connect_transport" in self.config: self.config["connect_transport"] = False if not "connect_rnode" in self.config: diff --git a/sbapp/ui/announces.py b/sbapp/ui/announces.py index 3f8ee07..d7de0fd 100644 --- a/sbapp/ui/announces.py +++ b/sbapp/ui/announces.py @@ -16,6 +16,12 @@ from kivymd.uix.dialog import MDDialog from kivy.lang.builder import Builder +from kivy.utils import escape_markup +if RNS.vendor.platformutils.get_platform() == "android": + from ui.helpers import multilingual_markup +else: + from .helpers import multilingual_markup + if RNS.vendor.platformutils.get_platform() == "android": from ui.helpers import ts_format else: @@ -93,9 +99,9 @@ class Announces(): trust_icon = "account-question" def gen_info(ts, dest, name, dtype): + name = multilingual_markup(escape_markup(str(name)).encode("utf-8")).decode("utf-8") def x(sender): - yes_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) - + yes_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) if dtype == "lxmf.delivery": ad_text = "[size=22dp]LXMF Peer[/size]\n\nReceived: "+ts+"\nAnnounced Name: "+name+"\nAddress: "+RNS.prettyhexrep(dest) @@ -118,7 +124,7 @@ class Announces(): time_string = time.strftime(ts_format, time.localtime(ts)) if dest_type == "lxmf.delivery": - disp_name = self.app.sideband.peer_display_name(context_dest) + disp_name = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8") iconl = IconLeftWidget(icon=trust_icon) elif dest_type == "lxmf.propagation": diff --git a/sbapp/ui/conversations.py b/sbapp/ui/conversations.py index a0822fa..58bc101 100644 --- a/sbapp/ui/conversations.py +++ b/sbapp/ui/conversations.py @@ -17,6 +17,12 @@ from kivymd.uix.dialog import MDDialog from kivy.lang.builder import Builder +from kivy.utils import escape_markup +if RNS.vendor.platformutils.get_platform() == "android": + from ui.helpers import multilingual_markup +else: + from .helpers import multilingual_markup + class NewConv(BoxLayout): pass @@ -162,9 +168,10 @@ class Conversations(): unread = conv["unread"] last_activity = conv["last_activity"] + peer_disp_name = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8") if not context_dest in self.added_item_dests: iconl = self.get_icon(conv) - item = OneLineAvatarIconListItem(text=self.app.sideband.peer_display_name(context_dest), on_release=self.app.conversation_action) + item = OneLineAvatarIconListItem(text=peer_disp_name, on_release=self.app.conversation_action) item.add_widget(iconl) item.last_activity = last_activity item.iconl = iconl @@ -185,6 +192,11 @@ class Conversations(): yes_button = MDRectangleFlatButton(text="Save",font_size=dp(18), theme_text_color="Custom", line_color=self.app.color_accept, text_color=self.app.color_accept) no_button = MDRectangleFlatButton(text="Cancel",font_size=dp(18)) dialog_content = ConvSettings(disp_name=disp_name, context_dest=RNS.hexrep(dest, delimit=False), trusted=is_trusted, telemetry=send_telemetry, allow_requests=allow_requests) + if self.app.sideband.config["input_language"] != None: + dialog_content.ids.name_field.font_name = self.app.sideband.config["input_language"] + else: + dialog_content.ids.name_field.font_name = "" + dialog = MDDialog( title="Edit Conversation", text= "With "+RNS.prettyhexrep(dest), @@ -388,7 +400,6 @@ class Conversations(): else: for w in self.list.children: if w.sb_uid == context_dest: - disp_name = self.app.sideband.peer_display_name(context_dest) trust_icon = self.trust_icon(conv) trusted = conv["trust"] == 1 da = self.app.sideband.DEFAULT_APPEARANCE @@ -410,7 +421,7 @@ class Conversations(): if w.iconl.icon != trust_icon: w.iconl.icon = trust_icon if w.sb_unread != unread: w.sb_unread = unread - if w.text != disp_name: w.text = disp_name + if w.text != peer_disp_name: w.text = peer_disp_name self.list.children.sort(key=lambda w: (w.trusted, w.last_activity)) diff --git a/sbapp/ui/helpers.py b/sbapp/ui/helpers.py index 5957982..f6a5f12 100644 --- a/sbapp/ui/helpers.py +++ b/sbapp/ui/helpers.py @@ -117,6 +117,7 @@ codepoint_map = { 0xa960: [0xa97f, "korean"], 0xac00: [0xd7af, "korean"], 0xd7b0: [0xd7ff, "korean"], + 0x0900: [0x097f, "combined"], # Devangari } emoji_lookup = ['⌚','⌛','','⏪','⏫','⏬','⏰','⏳','◽','◾','☔','☕','♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓','♿','⚓','⚡','⚪','⚫','⚽','⚾','⛄','⛅','⛎','⛔','⛪','⛲','⛳','⛵','⛺','⛽','✅','✊','✋','✨','❌','❎','❓','❔','❕','❗','➕','➖','➗','➰','➿','⬛','⬜','⭐','⭕','🀄','🃏','🆎','🆑','🆒','🆓','🆔','🆕','🆖','🆗','🆘','🆙','🆚','🈁','🈚','🈯','🈲','🈳','🈴','🈵','🈶','🈸','🈹','🈺','🉐','🉑','🌀','🌁','🌂','🌃','🌄','🌅','🌆','🌇','🌈','🌉','🌊','🌋','🌌','🌍','🌎','🌏','🌐','🌑','🌒','🌓','🌔','🌕','🌖','🌗','🌘','🌙','🌚','🌛','🌜','🌝','🌞','🌟','🌠','🌭','🌮','🌯','🌰','🌱','🌲','🌳','🌴','🌵','🌷','🌸','🌹','🌺','🌻','🌼','🌽','🌾','🌿','🍀','🍁','🍂','🍃','🍄','🍅','🍆','🍇','🍈','🍉','🍊','🍋','🍌','🍍','🍎','🍏','🍐','🍑','🍒','🍓','🍔','🍕','🍖','🍗','🍘','🍙','🍚','🍛','🍜','🍝','🍞','🍟','🍠','🍡','🍢','🍣','🍤','🍥','🍦','🍧','🍨','🍩','🍪','🍫','🍬','🍭','🍮','🍯','🍰','🍱','🍲','🍳','🍴','🍵','🍶','🍷','🍸','🍹','🍺','🍻','🍼','🍾','🍿','🎀','🎁','🎂','🎃','🎄','🎅','🎆','🎇','🎈','🎉','🎊','🎋','🎌','🎍','🎎','🎏','🎐','🎑','🎒','🎓','🎠','🎡','🎢','🎣','🎤','🎥','🎦','🎧','🎨','🎩','🎪','🎫','🎬','🎭','🎮','🎯','🎰','🎱','🎲','🎳','🎴','🎵','🎶','🎷','🎸','🎹','🎺','🎻','🎼','🎽','🎾','🎿','🏀','🏁','🏂','🏃','🏄','🏅','🏆','🏇','🏈','🏉','🏊','🏏','🏐','🏑','🏒','🏓','🏠','🏡','🏢','🏣','🏤','🏥','🏦','🏧','🏨','🏩','🏪','🏫','🏬','🏭','🏮','🏯','🏰','🏴','🏸','🏹','🏺','🏻','🏼','🏽','🏾','🏿','🐀','🐁','🐂','🐃','🐄','🐅','🐆','🐇','🐈','🐉','🐊','🐋','🐌','🐍','🐎','🐏','🐐','🐑','🐒','🐓','🐔','🐕','🐖','🐗','🐘','🐙','🐚','🐛','🐜','🐝','🐞','🐟','🐠','🐡','🐢','🐣','🐤','🐥','🐦','🐧','🐨','🐩','🐪','🐫','🐬','🐭','🐮','🐯','🐰','🐱','🐲','🐳','🐴','🐵','🐶','🐷','🐸','🐹','🐺','🐻','🐼','🐽','🐾','👀','👂','👃','👄','👅','👆','👇','👈','👉','👊','👋','👌','👍','👎','👏','👐','👑','👒','👓','👔','👕','👖','👗','👘','👙','👚','👛','👜','👝','👞','👟','👠','👡','👢','👣','👤','👥','👦','👧','👨','👩','👪','👫','👬','👭','👮','👯','👰','👱','👲','👳','👴','👵','👶','👷','👸','👹','👺','👻','👼','👽','👾','👿','💀','💁','💂','💃','💄','💅','💆','💇','💈','💉','💊','💋','💌','💍','💎','💏','💐','💑','💒','💓','💔','💕','💖','💗','💘','💙','💚','💛','💜','💝','💞','💟','💠','💡','💢','💣','💤','💥','💦','💧','💨','💩','💪','💫','💬','💭','💮','💯','💰','💱','💲','💳','💴','💵','💶','💷','💸','💹','💺','💻','💼','💽','💾','💿','📀','📁','📂','📃','📄','📅','📆','📇','📈','📉','📊','📋','📌','📍','📎','📏','📐','📑','📒','📓','📔','📕','📖','📗','📘','📙','📚','📛','📜','📝','📞','📟','📠','📡','📢','📣','📤','📥','📦','📧','📨','📩','📪','📫','📬','📭','📮','📯','📰','📱','📲','📳','📴','📵','📶','📷','📸','📹','📺','📻','📼','📿','🔀','🔁','🔂','🔃','🔄','🔅','🔆','🔇','🔈','🔉','🔊','🔋','🔌','🔍','🔎','🔏','🔐','🔑','🔒','🔓','🔔','🔕','🔖','🔗','🔘','🔙','🔚','🔛','🔜','🔝','🔞','🔟','🔠','🔡','🔢','🔣','🔤','🔥','🔦','🔧','🔨','🔩','🔪','🔫','🔬','🔭','🔮','🔯','🔰','🔱','🔲','🔳','🔴','🔵','🔶','🔷','🔸','🔹','🔺','🔻','🔼','🔽','🕋','🕌','🕍','🕎','🕐','🕑','🕒','🕓','🕔','🕕','🕖','🕗','🕘','🕙','🕚','🕛','🕜','🕝','🕞','🕟','🕠','🕡','🕢','🕣','🕤','🕥','🕦','🕧','🖕','🖖','🗻','🗼','🗽','🗾','🗿','😀','😁','😂','😃','😄','😅','😆','😇','😈','😉','😊','😋','😌','😍','😎','😏','😐','😑','😒','😓','😔','😕','😖','😗','😘','😙','😚','😛','😜','😝','😞','😟','😠','😡','😢','😣','😤','😥','😦','😧','😨','😩','😪','😫','😬','😭','😮','😯','😰','😱','😲','😳','😴','😵','😶','😷','😸','😹','😺','😻','😼','😽','😾','😿','🙀','🙁','🙂','🙃','🙄','🙅','🙆','🙇','🙈','🙉','🙊','🙋','🙌','🙍','🙎','🙏','🚀','🚁','🚂','🚃','🚄','🚅','🚆','🚇','🚈','🚉','🚊','🚋','🚌','🚍','🚎','🚏','🚐','🚑','🚒','🚓','🚔','🚕','🚖','🚗','🚘','🚙','🚚','🚛','🚜','🚝','🚞','🚟','🚠','🚡','🚢','🚣','🚤','🚥','🚦','🚧','🚨','🚩','🚪','🚫','🚬','🚭','🚮','🚯','🚰','🚱','🚲','🚳','🚴','🚵','🚶','🚷','🚸','🚹','🚺','🚻','🚼','🚽','🚾','🚿','🛀','🛁','🛂','🛃','🛄','🛅','🛌','🛐','🛫','🛬','🤐','🤑','🤒','🤓','🤔','🤕','🤖','🤗','🤘','🦀','🦁','🦂','🦃','🦄','🧀','🇦🇨','🇦🇩','🇦🇪','🇦🇫','🇦🇬','🇦🇮','🇦🇱','🇦🇲','🇦🇴','🇦🇶','🇦🇷','🇦🇸','🇦🇹','🇦🇺','🇦🇼','🇦🇽','🇦🇿','🇧🇦','🇧🇧','🇧🇩','🇧🇪','🇧🇫','🇧🇬','🇧🇭','🇧🇮','🇧🇯','🇧🇱','🇧🇲','🇧🇳','🇧🇴','🇧🇶','🇧🇷','🇧🇸','🇧🇹','🇧🇻','🇧🇼','🇧🇾','🇧🇿','🇨🇦','🇨🇨','🇨🇩','🇨🇫','🇨🇬','🇨🇭','🇨🇮','🇨🇰','🇨🇱','🇨🇲','🇨🇳','🇨🇴','🇨🇵','🇨🇷','🇨🇺','🇨🇻','🇨🇼','🇨🇽','🇨🇾','🇨🇿','🇩🇪','🇩🇬','🇩🇯','🇩🇰','🇩🇲','🇩🇴','🇩🇿','🇪🇦','🇪🇨','🇪🇪','🇪🇬','🇪🇭','🇪🇷','🇪🇸','🇪🇹','🇪🇺','🇫🇮','🇫🇯','🇫🇰','🇫🇲','🇫🇴','🇫🇷','🇬🇦','🇬🇧','🇬🇩','🇬🇪','🇬🇫','🇬🇬','🇬🇭','🇬🇮','🇬🇱','🇬🇲','🇬🇳','🇬🇵','🇬🇶','🇬🇷','🇬🇸','🇬🇹','🇬🇺','🇬🇼','🇬🇾','🇭🇰','🇭🇲','🇭🇳','🇭🇷','🇭🇹','🇭🇺','🇮🇨','🇮🇩','🇮🇪','🇮🇱','🇮🇲','🇮🇳','🇮🇴','🇮🇶','🇮🇷','🇮🇸','🇮🇹','🇯🇪','🇯🇲','🇯🇴','🇯🇵','🇰🇪','🇰🇬','🇰🇭','🇰🇮','🇰🇲','🇰🇳','🇰🇵','🇰🇷','🇰🇼','🇰🇾','🇰🇿','🇱🇦','🇱🇧','🇱🇨','🇱🇮','🇱🇰','🇱🇷','🇱🇸','🇱🇹','🇱🇺','🇱🇻','🇱🇾','🇲🇦','🇲🇨','🇲🇩','🇲🇪','🇲🇫','🇲🇬','🇲🇭','🇲🇰','🇲🇱','🇲🇲','🇲🇳','🇲🇴','🇲🇵','🇲🇶','🇲🇷','🇲🇸','🇲🇹','🇲🇺','🇲🇻','🇲🇼','🇲🇽','🇲🇾','🇲🇿','🇳🇦','🇳🇨','🇳🇪','🇳🇫','🇳🇬','🇳🇮','🇳🇱','🇳🇴','🇳🇵','🇳🇷','🇳🇺','🇳🇿','🇴🇲','🇵🇦','🇵🇪','🇵🇫','🇵🇬','🇵🇭','🇵🇰','🇵🇱','🇵🇲','🇵🇳','🇵🇷','🇵🇸','🇵🇹','🇵🇼','🇵🇾','🇶🇦','🇷🇪','🇷🇴','🇷🇸','🇷🇺','🇷🇼','🇸🇦','🇸🇧','🇸🇨','🇸🇩','🇸🇪','🇸🇬','🇸🇭','🇸🇮','🇸🇯','🇸🇰','🇸🇱','🇸🇲','🇸🇳','🇸🇴','🇸🇷','🇸🇸','🇸🇹','🇸🇻','🇸🇽','🇸🇾','🇸🇿','🇹🇦','🇹🇨','🇹🇩','🇹🇫','🇹🇬','🇹🇭','🇹🇯','🇹🇰','🇹🇱','🇹🇲','🇹🇳','🇹🇴','🇹🇷','🇹🇹','🇹🇻','🇹🇼','🇹🇿','🇺🇦','🇺🇬','🇺🇲','🇺🇸','🇺🇾','🇺🇿','🇻🇦','🇻🇨','🇻🇪','🇻🇬','🇻🇮','🇻🇳','🇻🇺','🇼🇫','🇼🇸','🇽🇰','🇾🇪','🇾🇹','🇿🇦','🇿🇲','🇿🇼']; \ No newline at end of file diff --git a/sbapp/ui/layouts.py b/sbapp/ui/layouts.py index 6bed446..b2de6e6 100644 --- a/sbapp/ui/layouts.py +++ b/sbapp/ui/layouts.py @@ -1438,8 +1438,8 @@ MDScreen: MDBoxLayout: orientation: "horizontal" size_hint_y: None - padding: [0,0,dp(24),dp(0)] - height: dp(48) + padding: [0,0,dp(24),dp(24)] + height: dp(48+24) MDLabel: text: "Debug Logging" @@ -1450,6 +1450,141 @@ MDScreen: pos_hint: {"center_y": 0.3} disabled: False active: False + + MDLabel: + text: "Input Options & Localisation" + font_style: "H6" + size_hint_y: None + height: self.texture_size[1] + + MDLabel: + id: settings_info_lang + markup: True + text: "" + size_hint_y: None + height: self.texture_size[1] + + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Latin, Greek, Cyrillic" + font_style: "H6" + + MDSwitch: + id: settings_lang_default + pos_hint: {"center_y": 0.3} + active: False + + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Chinese" + font_style: "H6" + + MDSwitch: + id: settings_lang_chinese + pos_hint: {"center_y": 0.3} + active: False + + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Japanese" + font_style: "H6" + + MDSwitch: + id: settings_lang_japanese + pos_hint: {"center_y": 0.3} + active: False + + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Korean" + font_style: "H6" + + MDSwitch: + id: settings_lang_korean + pos_hint: {"center_y": 0.3} + active: False + + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Devangari" + font_style: "H6" + + MDSwitch: + id: settings_lang_devangari + pos_hint: {"center_y": 0.3} + active: False + + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Hebrew (incomplete)" + font_style: "H6" + + MDSwitch: + id: settings_lang_hebrew + pos_hint: {"center_y": 0.3} + active: False + + # MDBoxLayout: + # orientation: "horizontal" + # size_hint_y: None + # padding: [0,0,dp(24),dp(0)] + # height: dp(48) + + # MDLabel: + # text: "Allow Predictive Text" + # font_style: "H6" + + # MDSwitch: + # id: settings_allow_predictive_text + # pos_hint: {"center_y": 0.3} + # active: False + + # MDBoxLayout: + # orientation: "vertical" + # size_hint_y: None + # height: self.minimum_height + # padding: [0, dp(24), 0, dp(24)] + + # MDRectangleFlatIconButton: + # id: hardware_rnode_button + # icon: "translate" + # text: "Input Languages" + # padding: [dp(0), dp(14), dp(0), dp(14)] + # icon_size: dp(24) + # font_size: dp(16) + # size_hint: [1.0, None] + # on_release: root.app.input_languages_action(self) + """ layout_repository_screen = """ diff --git a/sbapp/ui/messages.py b/sbapp/ui/messages.py index b5f7a87..6e7d2d0 100644 --- a/sbapp/ui/messages.py +++ b/sbapp/ui/messages.py @@ -176,6 +176,8 @@ class Messages(): intensity_msgs = intensity_msgs_light mt_color = [1.0, 1.0, 1.0, 0.95] + self.ids.message_text.font_name = self.app.input_font + if self.loading_earlier_messages: self.new_messages.reverse() diff --git a/sbapp/ui/objectdetails.py b/sbapp/ui/objectdetails.py index 2ac773d..f208464 100644 --- a/sbapp/ui/objectdetails.py +++ b/sbapp/ui/objectdetails.py @@ -20,6 +20,11 @@ from kivymd.toast import toast from datetime import datetime +from kivy.utils import escape_markup +if RNS.vendor.platformutils.get_platform() == "android": + from ui.helpers import multilingual_markup +else: + from .helpers import multilingual_markup if RNS.vendor.platformutils.get_platform() == "android": from ui.helpers import ts_format @@ -138,7 +143,7 @@ class ObjectDetails(): self.coords = None self.telemetry_list.data = [] - pds = self.app.sideband.peer_display_name(source_dest) + pds = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(source_dest))).encode("utf-8")).decode("utf-8") appearance = self.app.sideband.peer_appearance(source_dest) self.screen.ids.name_label.text = pds @@ -330,7 +335,7 @@ class RVDetails(MDRecycleView): Clipboard.copy(istr) toast("Copied to clipboard") release_function = copy_info - external_text = escape_markup(istr) + external_text = multilingual_markup(escape_markup(istr).encode("utf-8")).decode("utf-8") formatted_values = f"[b]Information[/b]: {external_text}" elif name == "Received": formatted_values = "" diff --git a/sbapp/ui/telemetry.py b/sbapp/ui/telemetry.py index df78cce..209edd8 100644 --- a/sbapp/ui/telemetry.py +++ b/sbapp/ui/telemetry.py @@ -15,11 +15,8 @@ from kivy.effects.scroll import ScrollEffect from kivy.clock import Clock from sideband.sense import Telemeter import threading - - from datetime import datetime - if RNS.vendor.platformutils.get_platform() == "android": from ui.helpers import ts_format from android.permissions import request_permissions, check_permission @@ -374,6 +371,11 @@ class Telemetry(): self.sensors_screen.ids.telemetry_s_information_text.text = str(self.app.sideband.config["telemetry_s_information_text"]) self.sensors_screen.ids.telemetry_s_information_text.bind(focus=self.sensors_save) + if self.app.sideband.config["input_language"] != None: + self.sensors_screen.ids.telemetry_s_information_text.font_name = self.app.sideband.config["input_language"] + else: + self.sensors_screen.ids.telemetry_s_information_text.font_name = "" + def sensors_open(self, sender=None, direction="left", no_transition=False): if no_transition: self.app.root.ids.screen_manager.transition = self.app.no_transition