Skip to content

Commit

Permalink
Merge pull request #296 from janezd/language-selector
Browse files Browse the repository at this point in the history
Add language setting and translation function
  • Loading branch information
ales-erjavec authored May 31, 2024
2 parents 8a3ecf1 + 352808d commit 552df2c
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 1 deletion.
20 changes: 20 additions & 0 deletions orangecanvas/application/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
Signal)

from .. import config
from ..utils.localization import get_languages
from ..utils.settings import SettingChangedEvent
from ..utils.propertybindings import (
AbstractBoundProperty, PropertyBinding, BindingManager
Expand Down Expand Up @@ -274,6 +275,25 @@ def __setupUi(self):
form = FormLayout()
tab.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

languages = get_languages()
if languages:
langlay = QHBoxLayout()
label = QLabel(
"Changes will take effect on next application startup.")
label.setHidden(True)

cm_lang = QComboBox(
objectName="combo-language",
toolTip=self.tr("Select the application language.")
)
cm_lang.addItems(languages)
self.bind(cm_lang, "currentText", "application/language")
cm_lang.currentTextChanged.connect(lambda: label.setHidden(False))

langlay.addWidget(cm_lang)
langlay.addWidget(label)
form.addRow(self.tr("Language"), langlay)

nodes = QWidget(self, objectName="nodes")
nodes.setLayout(QVBoxLayout())
nodes.layout().setContentsMargins(0, 0, 0, 0)
Expand Down
6 changes: 6 additions & 0 deletions orangecanvas/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,12 @@ def init():
("startup/load-crashed-workflows", bool, True,
"Load crashed scratch workflows on startup"),

("application/language", str, "English",
"Application language"),

("application/last-used-language", str, "English",
"If different from application/language, widget discovery is forced"),

("stylesheet", str, "orange",
"QSS stylesheet to use"),

Expand Down
6 changes: 5 additions & 1 deletion orangecanvas/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from AnyQt.QtGui import QFont, QColor, QPalette
from AnyQt.QtCore import Qt, QSettings, QTimer, QUrl, QDir

from orangecanvas.utils import localization
from .utils.after_exit import run_after_exit
from .styles import style_sheet, breeze_dark as _breeze_dark
from .application.application import CanvasApplication
Expand Down Expand Up @@ -142,7 +143,8 @@ def run_discovery(self) -> WidgetRegistry:
Run the widget discovery and return the resulting registry.
"""
options = self.options
if not options.force_discovery:
language_changed = localization.language_changed()
if not (options.force_discovery or language_changed):
reg_cache = cache.registry_cache()
else:
reg_cache = None
Expand All @@ -168,6 +170,8 @@ def run_discovery(self) -> WidgetRegistry:
with open(cache_filename, "wb") as f:
pickle.dump(WidgetRegistry(widget_registry), f)
self.registry = widget_registry
if language_changed:
localization.update_last_used_language()
self.close_splash_screen()
return widget_registry

Expand Down
56 changes: 56 additions & 0 deletions orangecanvas/utils/localization/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import os
import json
import importlib

from AnyQt.QtCore import QSettings, QLocale

def pl(n: int, forms: str) -> str: # pylint: disable=invalid-name
"""
Choose a singular/plural form for English - or create one, for regular nouns
Expand Down Expand Up @@ -29,3 +35,53 @@ def pl(n: int, forms: str) -> str: # pylint: disable=invalid-name
if forms.isupper():
word = word.upper()
return word


def get_languages(package=None):
if package is None:
package = "orangecanvas"
package_path = os.path.dirname(importlib.import_module(package).__file__)
msgs_path = os.path.join(package_path, "i18n")
if not os.path.exists(msgs_path):
return []
return [name
for name, ext in map(os.path.splitext, os.listdir(msgs_path))
if ext == ".json"]


DEFAULT_LANGUAGE = QLocale().languageToString(QLocale().language())
if DEFAULT_LANGUAGE not in get_languages():
DEFAULT_LANGUAGE = "English"


def language_changed():
s = QSettings()
lang = s.value("application/language", DEFAULT_LANGUAGE)
last_lang = s.value("application/last-used-language", DEFAULT_LANGUAGE)
return lang != last_lang


def update_last_used_language():
s = QSettings()
lang = s.value("application/language", "English")
s.setValue("application/last-used-language", lang)


class Translator:
e = eval

def __init__(self, package, organization="biolab.si", application="Orange"):
s = QSettings(QSettings.IniFormat, QSettings.UserScope,
organization, application)
lang = s.value("application/language", DEFAULT_LANGUAGE)
# For testing purposes (and potential fallback)
# lang = os.environ.get("ORANGE_LANG", "English")
package_path = os.path.dirname(importlib.import_module(package).__file__)
path = os.path.join(package_path, "i18n", f"{lang}.json")
if not os.path.exists(path):
path = os.path.join(package_path, "i18n", f"{DEFAULT_LANGUAGE}.json")
assert os.path.exists(path), f"Missing language file {path}"
self.m = json.load(open(path))

def c(self, idx):
return compile(self.m[idx], '<string>', 'eval')

0 comments on commit 552df2c

Please sign in to comment.