From 244d0ee88acc5638441ff5bf1f4279ae027c64f8 Mon Sep 17 00:00:00 2001 From: MattHag <16444067+MattHag@users.noreply.github.com> Date: Sat, 1 Jun 2024 18:09:55 +0200 Subject: [PATCH] solaar: clean up locale code Usage example for German: LC_ALL=de_DE.UTF-8 solaar Related #2507 --- lib/solaar/gtk.py | 5 +-- lib/solaar/i18n.py | 59 +++++++++++++++++++++--------------- tests/solaar/ui/test_i18n.py | 28 +++++++++++++++++ 3 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 tests/solaar/ui/test_i18n.py diff --git a/lib/solaar/gtk.py b/lib/solaar/gtk.py index 9c16f05e..86a947b3 100755 --- a/lib/solaar/gtk.py +++ b/lib/solaar/gtk.py @@ -19,6 +19,7 @@ import argparse import faulthandler import importlib +import locale import logging import os.path import platform @@ -31,7 +32,6 @@ from traceback import format_exc import solaar.cli as _cli import solaar.configuration as _configuration import solaar.dbus as _dbus -import solaar.i18n as _i18n import solaar.listener as _listener import solaar.ui as _ui import solaar.ui.common as _common @@ -122,7 +122,8 @@ def _parse_arguments(): if not args.action: if logger.isEnabledFor(logging.INFO): - logger.info("version %s, language %s (%s)", __version__, _i18n.language, _i18n.encoding) + language, encoding = locale.getlocale() + logger.info("version %s, language %s (%s)", __version__, language, encoding) return args diff --git a/lib/solaar/i18n.py b/lib/solaar/i18n.py index 47df7e01..1d4976ca 100644 --- a/lib/solaar/i18n.py +++ b/lib/solaar/i18n.py @@ -14,43 +14,52 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import gettext as _gettext +import gettext import locale -import os.path as _path -import sys as _sys +import os +import sys -from glob import glob as _glob +from glob import glob -from solaar import NAME as _NAME +from solaar import NAME -# -# -# +_LOCALE_DOMAIN = NAME.lower() -def _find_locale_path(lc_domain): - prefix_share = _path.normpath(_path.join(_path.realpath(_sys.path[0]), "..")) - src_share = _path.normpath(_path.join(_path.realpath(_sys.path[0]), "..", "share")) +def _find_locale_path(locale_domain: str) -> str: + prefix_share = os.path.normpath(os.path.join(os.path.realpath(sys.path[0]), "..")) + src_share = os.path.normpath(os.path.join(os.path.realpath(sys.path[0]), "..", "share")) for location in prefix_share, src_share: - mo_files = _glob(_path.join(location, "locale", "*", "LC_MESSAGES", lc_domain + ".mo")) + mo_files = glob(os.path.join(location, "locale", "*", "LC_MESSAGES", locale_domain + ".mo")) if mo_files: - return _path.join(location, "locale") + return os.path.join(location, "locale") + raise FileNotFoundError(f"Could not find locale path for {locale_domain}") -try: - locale.setlocale(locale.LC_ALL, "") -except Exception: - pass +def set_locale_to_system_default(): + """Sets locale for translations to the system default. -language, encoding = locale.getlocale() + Set LC_ALL environment variable to enforce a locale setting e.g. + 'de_DE.UTF-8'. Run Solaar with your desired localization, for German + use: + 'LC_ALL=de_DE.UTF-8 solaar' + """ + try: + locale.setlocale(locale.LC_ALL, "") + except PermissionError: + pass -_LOCALE_DOMAIN = _NAME.lower() -path = _find_locale_path(_LOCALE_DOMAIN) + try: + path = _find_locale_path(_LOCALE_DOMAIN) + except FileNotFoundError: + path = None + gettext.bindtextdomain(_LOCALE_DOMAIN, path) + gettext.textdomain(_LOCALE_DOMAIN) + gettext.install(_LOCALE_DOMAIN) -_gettext.bindtextdomain(_LOCALE_DOMAIN, path) -_gettext.textdomain(_LOCALE_DOMAIN) -_gettext.install(_LOCALE_DOMAIN) -_ = _gettext.gettext -ngettext = _gettext.ngettext +set_locale_to_system_default() + +_ = gettext.gettext +ngettext = gettext.ngettext diff --git a/tests/solaar/ui/test_i18n.py b/tests/solaar/ui/test_i18n.py new file mode 100644 index 00000000..3df6f013 --- /dev/null +++ b/tests/solaar/ui/test_i18n.py @@ -0,0 +1,28 @@ +import locale +import os +import platform + +import pytest + +from solaar import i18n + + +@pytest.fixture +def set_locale_de(): + backup_lang = os.environ.get("LC_ALL", "") + try: + yield + finally: + os.environ["LC_ALL"] = backup_lang + i18n.set_locale_to_system_default() + + +@pytest.mark.skipif(platform.system() == "Linux", reason="Adapt test for Linux") +def test_set_locale_to_system_default(set_locale_de): + os.environ["LC_ALL"] = "de_DE.UTF-8" + i18n.set_locale_to_system_default() + + language, encoding = locale.getlocale() + + assert language == "de_DE" + assert encoding == "UTF-8"