From 5b8b94d7386d87371fb919c644f0665f706dd7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Collonval?= Date: Sun, 14 Jul 2024 11:23:40 +0200 Subject: [PATCH 1/2] Fixes to support pseudo-language The pseudo-language allows for in-app translation of the interface. --- jupyterlab_server/translation_utils.py | 30 ++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/jupyterlab_server/translation_utils.py b/jupyterlab_server/translation_utils.py index 540f4e4..92c7751 100644 --- a/jupyterlab_server/translation_utils.py +++ b/jupyterlab_server/translation_utils.py @@ -5,6 +5,7 @@ Localization utilities to find available language packs and packages with localization data. """ + from __future__ import annotations import gettext @@ -40,6 +41,9 @@ L10N_SCHEMA_NAME = "@jupyterlab/translation-extension:plugin" PY37_OR_LOWER = sys.version_info[:2] <= (3, 7) +# Pseudo language locale for in-context translation +PSEUDO_LANGUAGE = "ach_UG" + _default_schema_context = "schema" _default_settings_context = "settings" _lab_i18n_config = "jupyter.lab.internationalization" @@ -151,7 +155,9 @@ def is_valid_locale(locale_: str) -> bool: - Brazilian German: "de_BR" """ # Add exception for Norwegian - if locale_ == "no_NO": + if locale_ in { + "no_NO", + }: return True valid = False @@ -183,8 +189,11 @@ def get_display_name(locale_: str, display_locale: str = DEFAULT_LOCALE) -> str: """ locale_ = locale_ if is_valid_locale(locale_) else DEFAULT_LOCALE display_locale = display_locale if is_valid_locale(display_locale) else DEFAULT_LOCALE - loc = babel.Locale.parse(locale_) - display_name = loc.get_display_name(display_locale) + try: + loc = babel.Locale.parse(locale_) + display_name = loc.get_display_name(display_locale) + except babel.UnknownLocaleError: + display_name = display_locale if display_name: display_name = display_name[0].upper() + display_name[1:] return display_name # type:ignore[return-value] @@ -326,6 +335,15 @@ def get_language_packs(display_locale: str = DEFAULT_LOCALE) -> tuple[dict, str] } if invalid_locales: + if PSEUDO_LANGUAGE in invalid_locales: + invalid_locales.remove(PSEUDO_LANGUAGE) + locales[PSEUDO_LANGUAGE] = { + "displayName": "Pseudo-language", + # Trick to ensure the proper language is selected in the language menu + "nativeName": "to translate the UI" + if display_locale != PSEUDO_LANGUAGE + else "Pseudo-language", + } messages.append(f"The following locales are invalid: {invalid_locales}!") return locales, "\n".join(messages) @@ -351,7 +369,11 @@ def get_language_pack(locale_: str) -> tuple: found_packages_locales, message = get_installed_packages_locale(locale_) locale_data = {} messages = message.split("\n") - if not message and is_valid_locale(locale_) and locale_ in found_locales: + if ( + not message + and (locale_ == PSEUDO_LANGUAGE or is_valid_locale(locale_)) + and locale_ in found_locales + ): path = found_locales[locale_] for root, __, files in os.walk(path, topdown=False): for name in files: From 5a32839c03b5764026adccb763f0c035410d6feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Collonval?= Date: Sun, 14 Jul 2024 20:49:41 +0200 Subject: [PATCH 2/2] Fix bugs to ensure the selected language menu is consistent --- jupyterlab_server/settings_utils.py | 10 ++++++++-- jupyterlab_server/translation_utils.py | 22 +++++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/jupyterlab_server/settings_utils.py b/jupyterlab_server/settings_utils.py index 82be181..abd32f2 100644 --- a/jupyterlab_server/settings_utils.py +++ b/jupyterlab_server/settings_utils.py @@ -17,7 +17,13 @@ from jupyter_server.services.config.manager import ConfigManager, recursive_update from tornado import web -from .translation_utils import DEFAULT_LOCALE, L10N_SCHEMA_NAME, SYS_LOCALE, is_valid_locale +from .translation_utils import ( + DEFAULT_LOCALE, + L10N_SCHEMA_NAME, + PSEUDO_LANGUAGE, + SYS_LOCALE, + is_valid_locale, +) # The JupyterLab settings file extension. SETTINGS_EXTENSION = ".jupyterlab-settings" @@ -497,7 +503,7 @@ def get_current_locale(self) -> str: current_locale = settings.get("settings", {}).get("locale") or SYS_LOCALE if current_locale == "default": current_locale = SYS_LOCALE - if not is_valid_locale(current_locale): + if not is_valid_locale(current_locale) and current_locale != PSEUDO_LANGUAGE: current_locale = DEFAULT_LOCALE return current_locale diff --git a/jupyterlab_server/translation_utils.py b/jupyterlab_server/translation_utils.py index 92c7751..6d3faf5 100644 --- a/jupyterlab_server/translation_utils.py +++ b/jupyterlab_server/translation_utils.py @@ -321,16 +321,20 @@ def get_language_packs(display_locale: str = DEFAULT_LOCALE) -> tuple[dict, str] else: invalid_locales.append(locale_) - display_locale = display_locale if display_locale in valid_locales else DEFAULT_LOCALE + display_locale_ = display_locale if display_locale in valid_locales else DEFAULT_LOCALE locales = { DEFAULT_LOCALE: { - "displayName": get_display_name(DEFAULT_LOCALE, display_locale), + "displayName": ( + get_display_name(DEFAULT_LOCALE, display_locale_) + if display_locale != PSEUDO_LANGUAGE + else "Default" + ), "nativeName": get_display_name(DEFAULT_LOCALE, DEFAULT_LOCALE), } } for locale_ in valid_locales: locales[locale_] = { - "displayName": get_display_name(locale_, display_locale), + "displayName": get_display_name(locale_, display_locale_), "nativeName": get_display_name(locale_, locale_), } @@ -340,11 +344,15 @@ def get_language_packs(display_locale: str = DEFAULT_LOCALE) -> tuple[dict, str] locales[PSEUDO_LANGUAGE] = { "displayName": "Pseudo-language", # Trick to ensure the proper language is selected in the language menu - "nativeName": "to translate the UI" - if display_locale != PSEUDO_LANGUAGE - else "Pseudo-language", + "nativeName": ( + "to translate the UI" + if display_locale != PSEUDO_LANGUAGE + else "Pseudo-language" + ), } - messages.append(f"The following locales are invalid: {invalid_locales}!") + # Check again as the pseudo-language was maybe the only invalid locale + if invalid_locales: + messages.append(f"The following locales are invalid: {invalid_locales}!") return locales, "\n".join(messages)