From 6573580f3cc9127a9e4225a7ceb9d343115d456a Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Sun, 6 Feb 2022 15:37:26 +0100 Subject: [PATCH] ability to change language --- locales/de_DE/LC_MESSAGES/messages.mo | Bin 3473 -> 4062 bytes locales/de_DE/LC_MESSAGES/messages.po | 56 ++++++++++++++++---------- locales/messages.pot | 40 ++++++++++-------- main.py | 7 +--- raven/i18n.py | 5 +++ raven/mainwindow.py | 32 ++++----------- raven/plugins/domain/raction.py | 55 ++++++++++++++++++++++++- raven/plugins/ravenlogplugin.py | 45 ++++++++++++++++----- 8 files changed, 158 insertions(+), 82 deletions(-) diff --git a/locales/de_DE/LC_MESSAGES/messages.mo b/locales/de_DE/LC_MESSAGES/messages.mo index 6fe4c4a14b9c8c8ae8f9927ed83108de76e9490d..510acab27009595bb7bc5c34bd2bfbb2d2ea424f 100644 GIT binary patch delta 2011 zcmY+ETWDNG7{@0y*{#`JOj@fZZ8~jCtL9?TYMRC-8k@EVt_3%U1uxm`&hDOea}v+l zb#3ynC>p%I)Flr^RD`Ing@Sz%1p|FhK?TJpi~4FS>O)oV_WLI%REP7;@0;0gzT2F$ zXF4zKtX^ubUp9;*$aZ9MlQC&ntY>2U++a)${sPGzndiXHJzG@yr*~>;2%F(N^1-=HagKtAQcqiIF2XA2g5#%vnMEnLev%Umx zgqNXe*hCchjYIiuhC06;))U|KqikVgA8dt3VFEq^WjF(QOvt1}7NHz1LH)iAb?#j# zKkq|T_z6@8zKYi0!<$+E812{7jxEGDZ73vbdZ04ygFI%4Ni83R`aKEdcnT`PC!i8I z36;yK#bC@mD4av#$LnSaAt;Z7dUmHi+ki#U@fyW__$ulWH2<6~8 zI1FEj_CJpJCFC*RF>QsHqjeo^P$!z16sH5q|1PM`_BPS~T`1#`!8BB$Jd~q(s5^ZD z>T1qH-QkpTahH1uD=#PzlB8vjVk8?13t11j^5`DvAuJp;}gioHZ}Pd*O1l z{u(NgAD{wUg}g`RFQ|kY@T%Wipeo!A)zLnv1P(#HE61S{orWi2H9(Q!w@`^(fvWTm zh;Q>Z)PW|9x?mUF3&)`B9aO-lpgOS#mEarE?<-K}&Ouz6&mpgh*@LiOHDf44h_ahN z6zo1^W9VBxgy;p`h8#gg5mm3is!pR9QGku1BsYd$@@`}jxed|(ibkKl|2x+8|ILG} zRK12>o7cYpsrnC4t94zw5nYr1IVo&y=w5e5`glZP1W|`J#+@j)65sSAhY`Km8XbsQ zsC(Uq+>abU^j_SB=*7GT(YOiGb?rxXAR7ACH3rtPHs8*y>(aOzIVfe%#7ynMh7X&Z zTX1$RXOmu7s>NeZwx)xu^X>7RO;sFPEgL(~n)dVMbl%y+1vHnfosA7Q=ei!BTtnw zjlJe?z{+g(c{#_7a)YdOL0FDq7H3@n3#mP3%sjL`VtDLXy~1B@?1KOBczcLSEg zJCNrcGesxH#5CkG?`f*wC#W30Lpk^b7r`>JQ9@zMD6C{0gS9XPOW-cZ5|e@Qx8Kem zfr}X*h1JA2XXsQgaS3V%6HozfLM^-t6?htI;Y+9;yo1`|XFL7|LyU`XqWK8a^Kr;6 z(+QPWH&i8hVUYM{kA2`Ul;dMi35`GnK5OT%Ku*V8gK~HsYUj7%8aM^R@QuAc3$=lt zQ2zWxRYjIUjq9LOO(#xA52j(W$Cw_d`4eOlfft|>yG6q-a}O$k2X_3(j-NxVdj+{n zo<@N_LiwMCT3<|g+hD*?{dJ?832`sff&sV$9)~LBC{(~PD97VaFJl(2f;oGC1}eZ? zsP!M9O8x`tXy&1gBt#IcYpS6Ba@@y+0`H@d;{nTIsD?FbpC${ngGs2fz7K2QW4IE&hB5dB z>iG~4$#Emp4iiv`WT5UJfLb>QRdHvO4oALVo9XFnWJ)NF4K zTac{%FHAjbM%wj1>!7m^MG+?Je`M>G2qfiT$q^Dz}>VIA|9f>UD z7QD~gC#477gfHa|`&!+HzNcJ#L}u F>u=!ea1;Ol diff --git a/locales/de_DE/LC_MESSAGES/messages.po b/locales/de_DE/LC_MESSAGES/messages.po index 187e642..86405b6 100644 --- a/locales/de_DE/LC_MESSAGES/messages.po +++ b/locales/de_DE/LC_MESSAGES/messages.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: RavenLog\n" -"POT-Creation-Date: 2022-02-03 18:28+0100\n" -"PO-Revision-Date: 2022-02-03 18:35+0100\n" +"POT-Creation-Date: 2022-02-06 08:14+0100\n" +"PO-Revision-Date: 2022-02-06 08:19+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -21,7 +21,7 @@ msgstr "" msgid "About RavenLog" msgstr "Über RavenLog" -#: aboutdialog.py:23 raven/mainwindow.py:40 ravenui.py:19 +#: aboutdialog.py:23 raven/mainwindow.py:39 ravenui.py:19 msgid "RavenLog" msgstr "RavenLog" @@ -45,7 +45,7 @@ msgstr "In &Datei Kopieren" msgid "Select &All" msgstr "&Alles Selektieren" -#: bigtext.py:188 raven/mainwindow.py:117 +#: bigtext.py:188 raven/mainwindow.py:101 msgid "&Highlighter" msgstr "&Hervorhebungen" @@ -87,19 +87,19 @@ msgstr "Passion Fruit Sugar" #: colorbutton.py:24 msgid "Sunrise Yellow" -msgstr "" +msgstr "Sonnenaufganggelb" #: colorbutton.py:25 msgid "Magical Mustard" -msgstr "" +msgstr "Magischer Senf" #: colorbutton.py:27 msgid "Trendy Green" -msgstr "" +msgstr "Trendiges Grün" #: colorbutton.py:28 msgid "Garden Of Sweden" -msgstr "" +msgstr "Garten von Schweden" #: colorbutton.py:30 msgid "Light Sky Blue" @@ -119,7 +119,7 @@ msgstr "" #: colorbutton.py:36 msgid "Breeze of Mist" -msgstr "" +msgstr "Nebelbriese" #: colorbutton.py:37 msgid "Light Grey" @@ -201,32 +201,32 @@ msgstr "Nicht Gespeicherte Änderungen" msgid "You have unsaved changes." msgstr "Du hast nicht gespeicherte Änderungen." -#: raven/mainwindow.py:48 raven/plugins/openfileplugin.py:31 +#: raven/mainwindow.py:47 raven/plugins/openfileplugin.py:31 msgid "Open &Recent" msgstr "Zu&letzt geöffnete Dateien" -#: raven/mainwindow.py:67 +#: raven/mainwindow.py:66 #: venv310/lib/python3.10/site-packages/PySide6/examples/widgets/gettext/main.py:57 msgid "&File" msgstr "&Datei" -#: raven/mainwindow.py:68 +#: raven/mainwindow.py:67 msgid "&Settings" msgstr "&Einstellungen" -#: raven/mainwindow.py:69 +#: raven/mainwindow.py:68 msgid "&Window" msgstr "&Fenster" -#: raven/mainwindow.py:70 +#: raven/mainwindow.py:69 msgid "&Help" msgstr "&Hilfe" -#: raven/mainwindow.py:125 +#: raven/mainwindow.py:109 msgid "Highlight &Searches" msgstr "&Suchtreffer Hervorheben" -#: raven/mainwindow.py:134 +#: raven/mainwindow.py:118 msgid "Open Tab on Save As File" msgstr "Öffne neues Tab wenn Selektion als neue Datei gespeichert wird" @@ -254,27 +254,39 @@ msgstr "&Öffnen..." msgid "Open File" msgstr "Öffne Datei" -#: raven/plugins/ravenlogplugin.py:40 +#: raven/plugins/ravenlogplugin.py:43 msgid "&Languages" msgstr "&Sprachen" -#: raven/plugins/ravenlogplugin.py:41 +#: raven/plugins/ravenlogplugin.py:44 msgid "&Default" msgstr "&Standard" -#: raven/plugins/ravenlogplugin.py:42 +#: raven/plugins/ravenlogplugin.py:45 msgid "&English" msgstr "&English" -#: raven/plugins/ravenlogplugin.py:43 +#: raven/plugins/ravenlogplugin.py:46 msgid "&German" msgstr "&Deutsch" -#: raven/plugins/ravenlogplugin.py:65 +#: raven/plugins/ravenlogplugin.py:70 +msgid "Language Changed" +msgstr "Sprache geändert" + +#: raven/plugins/ravenlogplugin.py:71 +msgid "" +"The language for this application has been changed. The change will take " +"effect the next time the application is started." +msgstr "" +"Die Anwendungssprache wurde geändert. Die Änderung wird erst beim " +"nächsten Start der Anwendung wirksam." + +#: raven/plugins/ravenlogplugin.py:88 msgid "&About" msgstr "&Über RavenLog" -#: raven/plugins/ravenlogplugin.py:73 +#: raven/plugins/ravenlogplugin.py:96 msgid "E&xit" msgstr "&Beenden" diff --git a/locales/messages.pot b/locales/messages.pot index c4af51e..2283cf2 100644 --- a/locales/messages.pot +++ b/locales/messages.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2022-02-03 18:28+0100\n" +"POT-Creation-Date: 2022-02-06 08:14+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,7 +19,7 @@ msgstr "" msgid "About RavenLog" msgstr "" -#: ./aboutdialog.py:23 ./raven/mainwindow.py:40 ./ravenui.py:19 +#: ./aboutdialog.py:23 ./raven/mainwindow.py:39 ./ravenui.py:19 msgid "RavenLog" msgstr "" @@ -43,7 +43,7 @@ msgstr "" msgid "Select &All" msgstr "" -#: ./bigtext.py:188 ./raven/mainwindow.py:117 +#: ./bigtext.py:188 ./raven/mainwindow.py:101 msgid "&Highlighter" msgstr "" @@ -199,32 +199,32 @@ msgstr "" msgid "You have unsaved changes." msgstr "" -#: ./raven/mainwindow.py:48 ./raven/plugins/openfileplugin.py:31 +#: ./raven/mainwindow.py:47 ./raven/plugins/openfileplugin.py:31 msgid "Open &Recent" msgstr "" -#: ./raven/mainwindow.py:67 +#: ./raven/mainwindow.py:66 #: ./venv310/lib/python3.10/site-packages/PySide6/examples/widgets/gettext/main.py:57 msgid "&File" msgstr "" -#: ./raven/mainwindow.py:68 +#: ./raven/mainwindow.py:67 msgid "&Settings" msgstr "" -#: ./raven/mainwindow.py:69 +#: ./raven/mainwindow.py:68 msgid "&Window" msgstr "" -#: ./raven/mainwindow.py:70 +#: ./raven/mainwindow.py:69 msgid "&Help" msgstr "" -#: ./raven/mainwindow.py:125 +#: ./raven/mainwindow.py:109 msgid "Highlight &Searches" msgstr "" -#: ./raven/mainwindow.py:134 +#: ./raven/mainwindow.py:118 msgid "Open Tab on Save As File" msgstr "" @@ -252,27 +252,35 @@ msgstr "" msgid "Open File" msgstr "" -#: ./raven/plugins/ravenlogplugin.py:40 +#: ./raven/plugins/ravenlogplugin.py:43 msgid "&Languages" msgstr "" -#: ./raven/plugins/ravenlogplugin.py:41 +#: ./raven/plugins/ravenlogplugin.py:44 msgid "&Default" msgstr "" -#: ./raven/plugins/ravenlogplugin.py:42 +#: ./raven/plugins/ravenlogplugin.py:45 msgid "&English" msgstr "" -#: ./raven/plugins/ravenlogplugin.py:43 +#: ./raven/plugins/ravenlogplugin.py:46 msgid "&German" msgstr "" -#: ./raven/plugins/ravenlogplugin.py:65 +#: ./raven/plugins/ravenlogplugin.py:70 +msgid "Language Changed" +msgstr "" + +#: ./raven/plugins/ravenlogplugin.py:71 +msgid "The language for this application has been changed. The change will take effect the next time the application is started." +msgstr "" + +#: ./raven/plugins/ravenlogplugin.py:88 msgid "&About" msgstr "" -#: ./raven/plugins/ravenlogplugin.py:73 +#: ./raven/plugins/ravenlogplugin.py:96 msgid "E&xit" msgstr "" diff --git a/main.py b/main.py index 1a1028c..daca9b8 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,10 @@ import logging -import os import signal import ctypes -from pathlib import Path from PySide6 import QtCore from PySide6.QtWidgets import QApplication -from PySide6.QtCore import QTimer, QLibraryInfo, QTranslator, QLocale +from PySide6.QtCore import QTimer from PySide6.QtGui import QIcon import sys @@ -15,9 +13,6 @@ from raven.pluginregistry import PluginRegistry from ravenui import RavenUI import gettext - -from settingsstore import SettingsStore - gettext.install('ravenlog', 'locale') logging.basicConfig(level=logging.INFO) diff --git a/raven/i18n.py b/raven/i18n.py index 9c53511..eefb20e 100644 --- a/raven/i18n.py +++ b/raven/i18n.py @@ -2,11 +2,14 @@ import gettext import os from pathlib import Path +from raven.pluginregistry import PluginRegistry from settingsstore import SettingsStore settings = SettingsStore.load() locale = os.environ['LANG'] if os.environ['LANG'] else "en" +print("locale1: %s" % locale) locale = settings.session.get('general', 'lang', fallback=locale) +print("locale2: %s" % locale) _ = False src_dir = Path(__file__).resolve().parent.parent @@ -16,9 +19,11 @@ try: translation.install() _ = translation.gettext ngettext = translation.ngettext + PluginRegistry.execute("set_locale", locale) except FileNotFoundError: pass if not _: _ = gettext.gettext ngettext = gettext.ngettext + PluginRegistry.execute("set_locale", '') print('No translation found') diff --git a/raven/mainwindow.py b/raven/mainwindow.py index 77aa140..7a0bc71 100644 --- a/raven/mainwindow.py +++ b/raven/mainwindow.py @@ -11,7 +11,6 @@ from raven.pluginregistry import PluginRegistry from raven.plugins.domain.menucontribution import MenuContribution, sort_menu_contributions from raven.plugins.domain.raction import RAction from raven.plugins.domain.rmenu import RMenu -from raven.plugins.ravenlog.Tab import Tab from settingsstore import SettingsStore from highlightingdialog import HighlightingDialog from tabs import Tabs @@ -77,7 +76,7 @@ class MainWindow(QMainWindow): continue for menu_contribution in mcs: if menu_contribution.action: - action = self._raction_to_qaction(menu_contribution.action, menu) + action = menu_contribution.action.to_qaction(menu) menu.addAction(action) if menu_contribution.menu: submenu = QMenu(menu_contribution.menu.label, menu_bar) @@ -93,25 +92,10 @@ class MainWindow(QMainWindow): def _rmenu_update(self, qmenu: QMenu, rmenu: RMenu): qmenu.clear() - for action in rmenu.actions: - action = self._raction_to_qaction(action, qmenu) + for raction in rmenu.actions: + action = raction.to_qaction(qmenu) qmenu.addAction(action) - def _raction_to_qaction(self, raction: RAction, qmenu: QMenu) -> QAction: - action = QAction(_(raction.label), qmenu) - if raction.icon_from_theme: - action.setIcon(QIcon.fromTheme(raction.icon_from_theme)) - if raction.icon_file: - action.setIcon(QIcon(raction.icon_file)) - if raction.shortcut: - action.setShortcut(raction.shortcut) - if raction.action: - action.triggered.connect(raction.action) - if raction.checkable: - action.setCheckable(raction.checkable) - action.setChecked(raction.checked) - return action - def _action_highlighter(self): manage = RAction( _("&Highlighter"), @@ -121,13 +105,11 @@ class MainWindow(QMainWindow): return manage def _action_highlight_search_terms(self): - highlight_search_terms = RAction( - _("Highlight &Searches"), - action=lambda checked: self.settings.set_session("general", "highlight_search_term", - str(checked)) or self.update() - ) + highlight_search_terms = RAction(_("Highlight &Searches")) highlight_search_terms.set_checkable(True) highlight_search_terms.set_checked(self.settings.session.getboolean("general", "highlight_search_term")) + highlight_search_terms.set_action(lambda: self.settings.set_session("general", "highlight_search_term", + str(highlight_search_terms.checked)) or self.update()) return highlight_search_terms def _action_new_tab(self): @@ -135,7 +117,7 @@ class MainWindow(QMainWindow): new_tab.set_checkable(True) new_tab.set_checked(self.settings.session.getboolean("general", "open_tab_on_save_as_file")) new_tab.set_action( - lambda checked: self.settings.set_session("general", "open_tab_on_save_as_file", str(checked))) + lambda: self.settings.set_session("general", "open_tab_on_save_as_file", str(new_tab.checked))) return new_tab def dragEnterEvent(self, e: QDragEnterEvent): diff --git a/raven/plugins/domain/raction.py b/raven/plugins/domain/raction.py index b42edb2..ee403b0 100644 --- a/raven/plugins/domain/raction.py +++ b/raven/plugins/domain/raction.py @@ -1,14 +1,30 @@ +from typing import Callable + +from PySide6.QtGui import QAction, QIcon +from PySide6.QtWidgets import QMenu + + class RAction(): def __init__(self, label: str, - action=None, + action: Callable[[], None] = None, shortcut: str = None, icon_from_theme: str = None, icon_file: str = None, checkable: bool = False, checked: bool = False ): + """ + + :param label: the label + :param action: the callback to be executed when clicked. Note: use the setter when creating a checkable menu item + :param shortcut: the shortcut, e.g. 'Ctrl+X' + :param icon_from_theme: environment specific name of an icon. On Linux: /usr/share/icons + :param icon_file: path to an icon + :param checkable: if this menu item behaves like a checkbox + :param checked: if it is checked + """ super(RAction, self).__init__() self.label = label self.action = action @@ -17,9 +33,16 @@ class RAction(): self.icon_file = icon_file self.checkable = checkable self.checked = checked + self._action: QAction = None def set_action(self, action): - self.action = action + self.action = lambda *args: self.decorated_action(action) + + def decorated_action(self, action): + if self.checkable: + self.checked = not self.checked + self._update_check_state() + action() def set_icon_from_theme(self, icon_from_theme: str): self.icon_from_theme = icon_from_theme @@ -35,3 +58,31 @@ class RAction(): def set_checked(self, checked: bool): self.checked = checked + self._update_check_state() + + def _update_check_state(self): + if self._action: + if self.checked: + self._action.setIcon(QIcon("icons/ionicons/checkbox-outline.svg")) + else: + self._action.setIcon(QIcon("icons/ionicons/square-outline.svg")) + + def set_label(self, label: str): + if self._action: + self._action.setText(label) + + def to_qaction(self, qmenu: QMenu) -> QAction: + action = QAction(self.label, qmenu) + self._action = action + if self.icon_from_theme: + action.setIcon(QIcon.fromTheme(self.icon_from_theme)) + if self.icon_file: + action.setIcon(QIcon(self.icon_file)) + if self.shortcut: + action.setShortcut(self.shortcut) + if self.action: + action.triggered.connect(self.action) + if self.checkable: + self._update_check_state() + + return action diff --git a/raven/plugins/ravenlogplugin.py b/raven/plugins/ravenlogplugin.py index 33b1439..caaf285 100644 --- a/raven/plugins/ravenlogplugin.py +++ b/raven/plugins/ravenlogplugin.py @@ -1,8 +1,8 @@ import sys -from typing import Optional, Callable +from typing import Optional, Callable, Dict from PySide6.QtCore import Qt -from PySide6.QtWidgets import QDockWidget +from PySide6.QtWidgets import QDockWidget, QMessageBox import constants from aboutdialog import AboutDialog @@ -12,7 +12,7 @@ from raven.plugins.domain.menucontribution import MenuContribution from raven.plugins.domain.raction import RAction from raven.plugins.domain.rmenu import RMenu from raven.plugins.ravenlog.Tab import Tab -from raven.i18n import _ +from raven.i18n import _, locale from settings import Settings @@ -20,6 +20,9 @@ class RavenLogPlugin(PluginBase): def __init__(self): super(RavenLogPlugin, self).__init__() self.main_window = None + self._locale = locale + self._locale_actions = {} + self.settings = None def set_settings(self, settings: Settings): self.settings = settings @@ -38,16 +41,36 @@ class RavenLogPlugin(PluginBase): def _sub_menu_languages(self) -> RMenu: menu = RMenu(_("&Languages")) - menu.add_action(RAction(_("&Default"), lambda: self._set_lang(''))) - menu.add_action(RAction(_("&English"), lambda: self._set_lang('en'))) - menu.add_action(RAction(_("&German"), lambda: self._set_lang('de'))) + self._locale_actions[''] = RAction(_("&Default"), lambda: self._change_locale(''), checkable=True) + self._locale_actions['en'] = RAction(_("&English"), lambda: self._change_locale('en'), checkable=True) + self._locale_actions['de'] = RAction(_("&German"), lambda: self._change_locale('de'), checkable=True) + + for (key, action) in self._locale_actions.items(): + action.checked = self._locale == key + menu.add_action(action) + + if not self._locale in self._locale_actions.keys(): + self._locale_actions[''].checked = True return menu - def _set_lang(self, lang: str): - if (lang == ''): - self.settings.session.remove_option('general', 'lang') - else: - self.settings.session.set('general', 'lang', lang) + def _change_locale(self, locale: str): + if self._locale != locale: + if self._locale in self._locale_actions: + self._locale_actions[self._locale].set_checked(False) + + self._locale_actions[locale].set_checked(True) + self._locale = locale + if locale == '': + self.settings.session.remove_option('general', 'lang') + else: + self.settings.session.set('general', 'lang', locale) + + info = QMessageBox( + QMessageBox.Icon.Information, + _("Language Changed"), + _("The language for this application has been changed. The change will take effect the next time the application is started.")) + info.setStandardButtons(QMessageBox.Ok) + info.exec() def current_file(self) -> Optional[str]: return self.main_window.tabs.current_file()