Skip to content

Commit 0846b11

Browse files
author
PyCompiler ARK++
committed
i18n renforcer pour les plugin
1 parent 75bc6b4 commit 0846b11

1 file changed

Lines changed: 103 additions & 1 deletion

File tree

Plugins_SDK/GeneralContext/i18n.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
"""
2020

2121
from typing import Any
22+
from pathlib import Path
23+
import json
2224

2325
# Keep live Plugins instances to support dynamic interactions (e.g., i18n refresh)
2426
# We avoid importing BCASL types here to keep this utility decoupled.
@@ -64,4 +66,104 @@ def apply_translations(gui: Any, tr: dict) -> None:
6466
except Exception:
6567
continue
6668
except Exception:
67-
pass
69+
pass
70+
71+
# --- Synchronization helpers ---
72+
73+
def _project_root() -> Path:
74+
try:
75+
# Plugins_SDK/GeneralContext/i18n.py -> project root is three parents up
76+
return Path(__file__).resolve().parents[2]
77+
except Exception:
78+
return Path.cwd()
79+
80+
81+
def _global_language_sync() -> str:
82+
"""Return the current global language preference synchronously.
83+
Falls back to 'en' on failure.
84+
"""
85+
try:
86+
from Core.i18n import get_current_language_sync # late import to avoid cycles
87+
code = get_current_language_sync() or "en"
88+
return str(code)
89+
except Exception:
90+
return "en"
91+
92+
93+
def _load_local_lang_sync(pkg_dir: Path, code: str) -> dict:
94+
"""Load a plugin-local language json from <pkg_dir>/languages/<code>.json with robust fallbacks."""
95+
try:
96+
base = pkg_dir / "languages"
97+
raw = (code or "en").strip()
98+
low = raw.lower().replace("_", "-")
99+
candidates = []
100+
if raw:
101+
candidates.append(raw)
102+
if low and low not in candidates:
103+
candidates.append(low)
104+
base_code = None
105+
try:
106+
if "-" in low:
107+
base_code = low.split("-", 1)[0]
108+
except Exception:
109+
base_code = None
110+
if base_code and base_code not in candidates:
111+
candidates.append(base_code)
112+
if "en" not in candidates:
113+
candidates.append("en")
114+
for c in candidates:
115+
f = base / f"{c}.json"
116+
if f.is_file():
117+
with open(f, encoding="utf-8") as fp:
118+
data = json.load(fp)
119+
if isinstance(data, dict):
120+
return data
121+
except Exception:
122+
pass
123+
return {"_meta": {"code": code or "en", "name": code or "en"}}
124+
125+
126+
def sync_with_global_language(gui: Any) -> dict:
127+
"""Synchronize all registered plugin instances with the current global language.
128+
- Resolves global language (Core.i18n.get_current_language_sync)
129+
- For each registered plugin instance, attempts to locate its package directory and
130+
load a local languages/<code>.json and call apply_i18n(gui, tr).
131+
- Returns the last loaded translation dict for convenience (can be ignored).
132+
Notes:
133+
- A plugin class may expose an attribute '__package_dir__' or a method 'get_package_dir()'
134+
returning a Path to its package root (containing languages/). If absent, this function
135+
attempts to infer the directory from the module of the class.
136+
"""
137+
code = _global_language_sync()
138+
last_tr: dict = {"_meta": {"code": code, "name": code}}
139+
try:
140+
for pid, inst in list(INSTANCES.items()):
141+
try:
142+
# Resolve package directory
143+
pkg_dir: Path | None = None
144+
try:
145+
if hasattr(inst, "get_package_dir") and callable(getattr(inst, "get_package_dir")):
146+
pkg_dir = Path(inst.get_package_dir())
147+
elif hasattr(inst, "__package_dir__"):
148+
pkg_dir = Path(getattr(inst, "__package_dir__"))
149+
else:
150+
mod = getattr(inst.__class__, "__module__", None)
151+
if mod:
152+
import importlib, inspect
153+
m = importlib.import_module(mod)
154+
f = Path(inspect.getfile(m))
155+
pkg_dir = f.parent
156+
except Exception:
157+
pkg_dir = None
158+
if not pkg_dir:
159+
continue
160+
tr = _load_local_lang_sync(pkg_dir, code)
161+
last_tr = tr
162+
fn = getattr(inst, "apply_i18n", None)
163+
if callable(fn):
164+
fn(gui, tr)
165+
except Exception:
166+
continue
167+
except Exception:
168+
pass
169+
return last_tr

0 commit comments

Comments
 (0)