Skip to content

Commit f351528

Browse files
author
PyCompiler ARK++
committed
revue de la doc de bcasl et du cleaner
1 parent 0846b11 commit f351528

2 files changed

Lines changed: 76 additions & 14 deletions

File tree

Plugins/Cleaner/__init__.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737

3838
# classe principale du plugin
3939
class Cleaner(BcPluginBase):
40+
__package_dir__ = Path(__file__).parent
41+
4042
def __init__(self):
4143
super().__init__(META)
4244
self.cleaned_files = 0
@@ -104,9 +106,16 @@ def on_pre_compile(self, ctx: PreCompileContext):
104106
log.log_info(cancelled_msg)
105107

106108
def apply_i18n(self, gui, tr: dict[str, str]) -> None:
107-
"""Apply plugin-local i18n from Plugins/Cleaner/languages/*.json independent of app languages."""
109+
"""Apply plugin-local i18n from Plugins/Cleaner/languages/*.json independent of app languages.
110+
Accepts either a preloaded plugin-local translation dict (preferred) or a generic
111+
translation meta with a language code to resolve the plugin-local file.
112+
"""
108113
try:
109114
self._gui = gui
115+
# If 'tr' already contains our plugin keys, use it directly (comes from sync_with_global_language)
116+
if isinstance(tr, dict) and any(k in tr for k in ("cleaner_title", "cleaner_question", "cleaner_completed")):
117+
self._lang_data = tr
118+
return
110119
# Resolve language code preference
111120
code = None
112121
try:
@@ -126,7 +135,7 @@ def apply_i18n(self, gui, tr: dict[str, str]) -> None:
126135
# Fallback
127136
if not code:
128137
code = "en"
129-
138+
130139
# Normalize codes and build robust fallback candidates
131140
raw = str(code)
132141
low = raw.lower().replace("_", "-")
@@ -144,7 +153,7 @@ def apply_i18n(self, gui, tr: dict[str, str]) -> None:
144153
"zh-cn": "zh-CN",
145154
}
146155
mapped = aliases.get(low, raw)
147-
156+
148157
# Candidate order: mapped -> base (before '-') -> exact lower -> exact raw -> 'en'
149158
candidates = []
150159
if mapped not in candidates:
@@ -165,14 +174,14 @@ def apply_i18n(self, gui, tr: dict[str, str]) -> None:
165174
candidates.append(raw)
166175
if "en" not in candidates:
167176
candidates.append("en")
168-
177+
169178
# Load plugin-local JSON using the first existing candidate
170179
import importlib.resources as ilr
171180
import json as _json
172-
181+
173182
pkg = __package__
174183
lang_data = {}
175-
184+
176185
def _load_lang(c: str) -> bool:
177186
nonlocal lang_data
178187
try:
@@ -186,15 +195,21 @@ def _load_lang(c: str) -> bool:
186195
except Exception:
187196
pass
188197
return False
189-
198+
190199
for cand in candidates:
191200
if _load_lang(cand):
192201
break
193-
202+
194203
self._lang_data = lang_data
195204
except Exception:
196205
self._lang_data = {}
197206

207+
def get_package_dir(self) -> Path:
208+
try:
209+
return Path(__file__).parent
210+
except Exception:
211+
return Path.cwd()
212+
198213

199214
# enregistrement automatique du plugin dans le registre de bcasl
200215
PLUGIN = Cleaner()

docs/how_to_create_a_BC_plugin.md

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,66 @@ PLUGIN = MyPlugin()
7676

7777
## 4) Internationalization
7878

79-
- Place JSON translation files under `languages/`
79+
BCASL supports plugin‑local i18n files and a lightweight synchronization API so your plugin updates its texts automatically when the app language changes or when using the BCASL only_mod Studio.
80+
81+
- Place JSON translation files under `languages/` in your plugin package
8082
- Always include `en.json` as the fallback
81-
- Use `apply_i18n(gui, tr)` in your plugin to update UI if any is exposed
83+
- Implement `apply_i18n(gui, tr)` in your plugin; it will be called with a translation dict
84+
- Register your plugin instance for i18n so that synchronization can target it
85+
- Optionally expose your package directory so the sync layer can auto‑discover your languages folder
8286

8387
Example `languages/en.json`:
8488
```json
8589
{
8690
"_meta": {"code": "en", "name": "English"},
87-
"title": "My BC Plugin",
88-
"question": "Proceed with pre‑build checks?"
91+
"myplugin_title": "My BC Plugin",
92+
"myplugin_question": "Proceed with pre‑build checks?"
8993
}
9094
```
9195

96+
Example `__init__.py` snippets:
97+
```python
98+
from pathlib import Path
99+
from Plugins_SDK.GeneralContext.i18n import register_instance
100+
101+
class MyPlugin(BcPluginBase):
102+
__package_dir__ = Path(__file__).parent # helps i18n sync discover languages/
103+
104+
def apply_i18n(self, gui, tr: dict[str, str]) -> None:
105+
# Prefer preloaded plugin-local dict; else resolve by code
106+
if tr and any(k in tr for k in ("myplugin_title", "myplugin_question")):
107+
self._lang = tr
108+
else:
109+
code = (tr or {}).get("_meta", {}).get("code", "en")
110+
# resolve languages/<code>.json with fallbacks (code-base, en)
111+
# ... load into self._lang
112+
# update any exposed text
113+
# gui elements or log messages can use self._lang.get("myplugin_title", "...")
114+
115+
PLUGIN = MyPlugin()
116+
117+
def bcasl_register(manager):
118+
manager.add_plugin(PLUGIN)
119+
register_instance(PLUGIN.meta.id, PLUGIN) # enable i18n synchronization
120+
```
121+
122+
Synchronization helpers available:
123+
- `apply_translations(gui, tr)`: broadcast a translation dict to all registered plugins (used by only_mod Studio)
124+
- `sync_with_global_language(gui)`: load each registered plugin’s `languages/<code>.json` based on the global language and call `apply_i18n` for them
125+
126+
Tips:
127+
- Use distinct keys per plugin (prefix like `myplugin_`) to avoid collisions
128+
- Keep translations small and focused on end‑user strings
129+
- Prefer English as a base and verify JSON validity
130+
92131
## 5) Testing and logging
93132

94-
- Use the GUI log (`gui.log.append(...)`) to provide feedback when applicable
133+
- Use the BCASL Studio (only_mod) to quickly iterate on your plugin:
134+
- Launch: `python main.py --bcasl-only` or `python main.py bcasl`
135+
- Select workspace, enable your plugin, reorder with drag‑and‑drop
136+
- Pick a language from the Language combo or set the app’s global language
137+
- Observe live i18n updates if your plugin implements `apply_i18n`
138+
- Prefer the provided Dialog/logging facilities to report information/warnings
95139
- Ensure code is idempotent and resilient to being called multiple times
96140
- Avoid blocking the UI thread; long operations should be asynchronous
97141

@@ -101,6 +145,9 @@ Example `languages/en.json`:
101145
- [ ] Global `PLUGIN` instance
102146
- [ ] `on_pre_compile()` implemented and safe
103147
- [ ] Robust error handling (raise to abort build if necessary)
104-
- [ ] i18n files with `en.json` fallback
148+
- [ ] i18n files with `en.json` fallback under `languages/`
149+
- [ ] `apply_i18n(gui, tr)` implemented (supports preloaded dict or language code)
150+
- [ ] Plugin registered for i18n (`register_instance(plugin_id, instance)`)
151+
- [ ] Optional: expose `__package_dir__` or `get_package_dir()` for auto-discovery
105152
- [ ] Clear logs for users
106153

0 commit comments

Comments
 (0)