Skip to content

Commit 7378da1

Browse files
committed
Refactor internationalization in engines: load language files from package resources
This commit includes a diff of changes to the following files: * `Core/engines_loader/base.py` * `Core/engines_loader/registry.py` * `
1 parent 63bcc66 commit 7378da1

5 files changed

Lines changed: 70 additions & 150 deletions

File tree

Core/engines_loader/base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ def ensure_tools_installed(self, gui) -> bool:
141141
gui.log.append(f"⚠️ Error ensuring tools installed: {e}")
142142
return False
143143

144+
def apply_i18n(self, gui, tr: dict) -> None:
145+
"""
146+
Apply internationalization translations to the engine UI.
147+
Default implementation does nothing - engines should override this.
148+
"""
149+
pass
150+
144151
def get_log_prefix(self, file_basename: str) -> str:
145152
"""
146153
Return a log prefix string for the engine's compilation messages.

Core/engines_loader/registry.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from __future__ import annotations
1717

18+
import os
1819
from typing import Optional, Any
1920

2021
from .base import CompilerEngine
@@ -306,6 +307,62 @@ def get_engine_for_tab(index: int) -> Optional[str]:
306307
return None
307308

308309

310+
def load_engine_language_file(engine_package: str, code: str) -> dict:
311+
"""Load language file for an engine from its package's languages folder.
312+
313+
Args:
314+
engine_package: The engine's package name (e.g., 'ENGINES.nuitka')
315+
code: Language code (e.g., 'fr', 'en')
316+
317+
Returns:
318+
Dict containing the language data, or empty dict if not found
319+
"""
320+
try:
321+
import importlib.resources as ilr
322+
import json
323+
324+
lang_data = {}
325+
326+
# Try exact code first
327+
try:
328+
with ilr.as_file(
329+
ilr.files(engine_package).joinpath("languages", f"{code}.json")
330+
) as p:
331+
if os.path.isfile(str(p)):
332+
with open(str(p), encoding="utf-8") as f:
333+
lang_data = json.load(f) or {}
334+
return lang_data
335+
except Exception:
336+
pass
337+
338+
# Fallback to base language (e.g., "fr" from "fr-CA")
339+
if "-" in code:
340+
base = code.split("-", 1)[0]
341+
try:
342+
with ilr.as_file(
343+
ilr.files(engine_package).joinpath("languages", f"{base}.json")
344+
) as p:
345+
if os.path.isfile(str(p)):
346+
with open(str(p), encoding="utf-8") as f:
347+
lang_data = json.load(f) or {}
348+
return lang_data
349+
except Exception:
350+
pass
351+
352+
# Final fallback to English
353+
try:
354+
with ilr.as_file(ilr.files(engine_package).joinpath("languages", "en.json")) as p:
355+
if os.path.isfile(str(p)):
356+
with open(str(p), encoding="utf-8") as f:
357+
lang_data = json.load(f) or {}
358+
except Exception:
359+
pass
360+
361+
return lang_data
362+
except Exception:
363+
return {}
364+
365+
309366
def create(eid: str) -> CompilerEngine:
310367
cls = get_engine(eid)
311368
if not cls:

ENGINES/cx_freeze/__init__.py

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,13 @@ def should_compile_file(
245245
def apply_i18n(self, gui, tr: dict) -> None:
246246
"""Apply internationalization translations to the engine UI."""
247247
try:
248-
from Core.engines_loader.registry import resolve_language_code
248+
from Core.engines_loader.registry import resolve_language_code, load_engine_language_file
249249

250250
# Resolve language code
251251
code = resolve_language_code(gui, tr)
252252

253253
# Load engine-local translations
254-
lang_data = self._load_language_file(code)
254+
lang_data = load_engine_language_file(__package__, code)
255255

256256
# Apply translations to UI elements if they exist
257257
if hasattr(self, "_cx_onefile") and "onefile_checkbox" in lang_data:
@@ -264,51 +264,3 @@ def apply_i18n(self, gui, tr: dict) -> None:
264264
self._cx_output_dir.setPlaceholderText(lang_data["output_placeholder"])
265265
except Exception:
266266
pass
267-
268-
def _load_language_file(self, code: str) -> dict:
269-
"""Load language file for the given code."""
270-
try:
271-
import importlib.resources as ilr
272-
import json
273-
274-
pkg = __package__
275-
lang_data = {}
276-
277-
# Try exact code first
278-
try:
279-
with ilr.as_file(
280-
ilr.files(pkg).joinpath("languages", f"{code}.json")
281-
) as p:
282-
if os.path.isfile(str(p)):
283-
with open(str(p), encoding="utf-8") as f:
284-
lang_data = json.load(f) or {}
285-
return lang_data
286-
except Exception:
287-
pass
288-
289-
# Fallback to base language (e.g., "fr" from "fr-CA")
290-
if "-" in code:
291-
base = code.split("-", 1)[0]
292-
try:
293-
with ilr.as_file(
294-
ilr.files(pkg).joinpath("languages", f"{base}.json")
295-
) as p:
296-
if os.path.isfile(str(p)):
297-
with open(str(p), encoding="utf-8") as f:
298-
lang_data = json.load(f) or {}
299-
return lang_data
300-
except Exception:
301-
pass
302-
303-
# Final fallback to English
304-
try:
305-
with ilr.as_file(ilr.files(pkg).joinpath("languages", "en.json")) as p:
306-
if os.path.isfile(str(p)):
307-
with open(str(p), encoding="utf-8") as f:
308-
lang_data = json.load(f) or {}
309-
except Exception:
310-
pass
311-
312-
return lang_data
313-
except Exception:
314-
return {}

ENGINES/nuitka/__init__.py

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,13 @@ def should_compile_file(
309309
def apply_i18n(self, gui, tr: dict) -> None:
310310
"""Apply internationalization translations to the engine UI."""
311311
try:
312-
from Core.engines_loader.registry import resolve_language_code
312+
from Core.engines_loader.registry import resolve_language_code, load_engine_language_file
313313

314314
# Resolve language code
315315
code = resolve_language_code(gui, tr)
316316

317317
# Load engine-local translations
318-
lang_data = self._load_language_file(code)
318+
lang_data = load_engine_language_file(__package__, code)
319319

320320
# Apply translations to UI elements if they exist
321321
if hasattr(self, "_nuitka_onefile") and "onefile_checkbox" in lang_data:
@@ -351,54 +351,6 @@ def apply_i18n(self, gui, tr: dict) -> None:
351351
except Exception:
352352
pass
353353

354-
def _load_language_file(self, code: str) -> dict:
355-
"""Load language file for the given code."""
356-
try:
357-
import importlib.resources as ilr
358-
import json
359-
360-
pkg = __package__
361-
lang_data = {}
362-
363-
# Try exact code first
364-
try:
365-
with ilr.as_file(
366-
ilr.files(pkg).joinpath("languages", f"{code}.json")
367-
) as p:
368-
if os.path.isfile(str(p)):
369-
with open(str(p), encoding="utf-8") as f:
370-
lang_data = json.load(f) or {}
371-
return lang_data
372-
except Exception:
373-
pass
374-
375-
# Fallback to base language (e.g., "fr" from "fr-CA")
376-
if "-" in code:
377-
base = code.split("-", 1)[0]
378-
try:
379-
with ilr.as_file(
380-
ilr.files(pkg).joinpath("languages", f"{base}.json")
381-
) as p:
382-
if os.path.isfile(str(p)):
383-
with open(str(p), encoding="utf-8") as f:
384-
lang_data = json.load(f) or {}
385-
return lang_data
386-
except Exception:
387-
pass
388-
389-
# Final fallback to English
390-
try:
391-
with ilr.as_file(ilr.files(pkg).joinpath("languages", "en.json")) as p:
392-
if os.path.isfile(str(p)):
393-
with open(str(p), encoding="utf-8") as f:
394-
lang_data = json.load(f) or {}
395-
except Exception:
396-
pass
397-
398-
return lang_data
399-
except Exception:
400-
return {}
401-
402354
def add_data(self) -> None:
403355
"""Add data files or directories to be included with Nuitka."""
404356
choix, ok = QInputDialog.getItem(

ENGINES/pyinstaller/__init__.py

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -325,13 +325,13 @@ def should_compile_file(
325325
def apply_i18n(self, gui, tr: dict) -> None:
326326
"""Apply internationalization translations to the engine UI."""
327327
try:
328-
from Core.engines_loader.registry import resolve_language_code
328+
from Core.engines_loader.registry import resolve_language_code, load_engine_language_file
329329

330330
# Resolve language code
331331
code = resolve_language_code(gui, tr)
332332

333333
# Load engine-local translations
334-
lang_data = self._load_language_file(code)
334+
lang_data = load_engine_language_file(__package__, code)
335335

336336
# Apply translations to UI elements if they exist
337337
if hasattr(self, "_opt_onefile") and "onefile_checkbox" in lang_data:
@@ -362,54 +362,6 @@ def apply_i18n(self, gui, tr: dict) -> None:
362362
except Exception:
363363
pass
364364

365-
def _load_language_file(self, code: str) -> dict:
366-
"""Load language file for the given code."""
367-
try:
368-
import importlib.resources as ilr
369-
import json
370-
371-
pkg = __package__
372-
lang_data = {}
373-
374-
# Try exact code first
375-
try:
376-
with ilr.as_file(
377-
ilr.files(pkg).joinpath("languages", f"{code}.json")
378-
) as p:
379-
if os.path.isfile(str(p)):
380-
with open(str(p), encoding="utf-8") as f:
381-
lang_data = json.load(f) or {}
382-
return lang_data
383-
except Exception:
384-
pass
385-
386-
# Fallback to base language (e.g., "fr" from "fr-CA")
387-
if "-" in code:
388-
base = code.split("-", 1)[0]
389-
try:
390-
with ilr.as_file(
391-
ilr.files(pkg).joinpath("languages", f"{base}.json")
392-
) as p:
393-
if os.path.isfile(str(p)):
394-
with open(str(p), encoding="utf-8") as f:
395-
lang_data = json.load(f) or {}
396-
return lang_data
397-
except Exception:
398-
pass
399-
400-
# Final fallback to English
401-
try:
402-
with ilr.as_file(ilr.files(pkg).joinpath("languages", "en.json")) as p:
403-
if os.path.isfile(str(p)):
404-
with open(str(p), encoding="utf-8") as f:
405-
lang_data = json.load(f) or {}
406-
except Exception:
407-
pass
408-
409-
return lang_data
410-
except Exception:
411-
return {}
412-
413365
def add_data(self) -> None:
414366
"""Add data files or directories to be included with PyInstaller."""
415367
choix, ok = QInputDialog.getItem(

0 commit comments

Comments
 (0)