feat: add Vietnamese localization to GUI
Introduces a two-language (EN/VI) i18n system with hot-swap support. All ~160 user-facing strings are centralised in gui/locales.py; views retranslate in-place on language switch without restarting the app. - gui/locales.py: new file — _EN/_VI dicts, t() lookup, set_language(), get_language(); assert guard ensures EN/VI key parity - gui/app.py: switch_language(), _apply_startup_language(), _save_language_pref(), _rebuild_nav_labels(); language stored in config.json under ui.language; pipeline step headers and run_tool status lines translated - gui/views/settings.py: Language dropdown card (English / Tiếng Việt) - gui/views/dashboard.py: all strings via t(); static header widgets stored and retranslated in refresh() - gui/views/mods.py: all strings via t(); _STATUS dict built at call time so server status labels update on language switch - gui/views/tools.py: all strings via _translatable registry; tab names and segmented-button values kept in English (CTkTabview constraint) - gui/views/logs.py: title + Copy/Clear buttons stored, retranslated - gui/wizard.py: all 3 pages fully translated - docs/huong-dan-su-dung.md: full Vietnamese user guide - CLAUDE.md: documents localization architecture and constraints
This commit is contained in:
27
CLAUDE.md
27
CLAUDE.md
@@ -110,6 +110,33 @@ Pass 2 builds `ok_disk_names` — the set of disk names that already match the s
|
||||
|
||||
**`run_tool` subprocess streaming:** Tool scripts are launched via `subprocess.Popen` (not `subprocess.run`) with `stdout=PIPE, stderr=STDOUT`, read line-by-line via `iter(proc.stdout.readline, "")`, and posted to the log queue immediately. Python's own output buffering is disabled with the `-u` flag and `PYTHONUNBUFFERED=1` in the environment — without these, output would batch inside the pipe and only appear when the script exits.
|
||||
|
||||
### GUI localization (`gui/locales.py`)
|
||||
|
||||
All user-facing strings are centralised in `gui/locales.py`. Two languages are supported: English (`"en"`) and Vietnamese (`"vi"`).
|
||||
|
||||
**API:**
|
||||
```python
|
||||
from gui.locales import t, set_language, get_language
|
||||
|
||||
t("nav.dashboard") # → "Dashboard" or "Tổng quan"
|
||||
t("dashboard.stats", total=42, shared=10) # → "42 mods · 10 shared"
|
||||
set_language("vi") # switch active language
|
||||
get_language() # → "vi"
|
||||
```
|
||||
|
||||
**Key naming:** flat dot-notation — `"<view>.<widget_purpose>"`, e.g. `"dashboard.run_btn"`, `"wizard.step1_title"`, `"tools.cn_warn"`.
|
||||
|
||||
**Dynamic strings** use `str.format_map` with keyword args. The dict value contains `{placeholder}` and the caller passes `t("key", placeholder=value)`.
|
||||
|
||||
**Hot-swap:** `app.switch_language(lang)` calls `set_language()`, saves the preference to `config.json` under `"ui": {"language": "..."}`, retranslates sidebar nav buttons, then calls `view.refresh()` on every cached view. Views that build all content in `refresh()` (Settings, Mods) update automatically. Views with static `build()`-time widgets (Dashboard, Logs, Tools) store widget references and retranslate them at the top of `refresh()`.
|
||||
|
||||
**Constraints:**
|
||||
- `CTkTabview` tab names in `tools.py` are kept in English — they double as frame lookup keys (`tv.tab("Check Names")`) and cannot be renamed after creation.
|
||||
- Segmented button values in `tools.py` (`"Status"`, `"Link"`, `"Unlink"`) are kept in English — they drive the logic in `_lm_on_change()`.
|
||||
- `_VIEW_NAMES` routing keys (`"Dashboard"`, `"Mods"`, etc.) are kept in English — they are `_view_cache` dict keys.
|
||||
|
||||
**Adding a new string:** Add the key to both `_EN` and `_VI` dicts in `locales.py`. The `assert set(_EN.keys()) == set(_VI.keys())` guard at module load will catch any mismatch.
|
||||
|
||||
## Python Version Compatibility
|
||||
|
||||
Minimum is Python **3.9**. All files that use `X | Y` union type annotations **must** have `from __future__ import annotations` as the first import. Without it, the `|` syntax raises `TypeError` at runtime on Python < 3.10. Every module in `arma_modlist_tools/` already has it; any new CLI script you add must include it too.
|
||||
|
||||
Reference in New Issue
Block a user