Skip to content

Commit 2cb21ae

Browse files
author
PyCompiler ARK++ Team
committed
feat(header_injector): détection de licence robuste; pas d'injection si absente; i18n via API_SDK (sctx.tr)
1 parent cd6deab commit 2cb21ae

2 files changed

Lines changed: 70 additions & 13 deletions

File tree

API/header_injector/__init__.py

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
BCASL_TAGS = ["pre-compilation", "license", "SPDX"]
1919

2020
import re
21+
import asyncio
2122
from pathlib import Path
2223
from typing import Optional
2324

@@ -221,12 +222,47 @@ def _inject_license_for_file(path: Path, text: str, spdx_id: str) -> str:
221222
description="Injecte une ligne de licence (SPDX) en tête des fichiers ciblés",
222223
)
223224
class LicenseInjector(PluginBase):
225+
_i18n: dict | None = None
226+
227+
def _ensure_i18n(self) -> None:
228+
if self._i18n is not None:
229+
return
230+
try:
231+
try:
232+
self._i18n = asyncio.run(API_SDK.load_plugin_translations(Path(__file__)))
233+
except RuntimeError:
234+
loop = asyncio.new_event_loop()
235+
try:
236+
self._i18n = loop.run_until_complete(API_SDK.load_plugin_translations(Path(__file__)))
237+
finally:
238+
try:
239+
loop.close()
240+
except Exception:
241+
pass
242+
except Exception:
243+
self._i18n = {}
244+
245+
def _t(self, sctx, key: str, fr: str, en: str, **fmt) -> str:
246+
text = None
247+
try:
248+
if isinstance(self._i18n, dict):
249+
text = self._i18n.get(key)
250+
except Exception:
251+
text = None
252+
if not isinstance(text, str) or not text.strip():
253+
text = sctx.tr(fr, en)
254+
try:
255+
return text.format(**fmt) if fmt else text
256+
except Exception:
257+
return text
258+
224259
def on_pre_compile(self, ctx: PreCompileContext) -> None:
225260
try:
226261
sctx = wrap_context(ctx)
227262
except RuntimeError as exc:
228263
print(f"[ERROR][license_injector] {exc}")
229264
return
265+
self._ensure_i18n()
230266

231267
cfg = sctx.config_view
232268
subcfg = cfg.for_plugin(getattr(self, "id", "license_injector"))
@@ -235,7 +271,9 @@ def on_pre_compile(self, ctx: PreCompileContext) -> None:
235271
spdx_id, lic_name = _detect_workspace_license(sctx.workspace_root)
236272
if not spdx_id:
237273
sctx.log_info(
238-
sctx.tr(
274+
self._t(
275+
sctx,
276+
"no_license",
239277
"license_injector: aucune licence détectée (pyproject ou fichiers LICENSE/LICENCE/COPYING/NOTICE). Aucune injection.",
240278
"license_injector: no license detected (pyproject or LICENSE/LICENCE/COPYING/NOTICE files). No injection performed.",
241279
)
@@ -252,20 +290,24 @@ def on_pre_compile(self, ctx: PreCompileContext) -> None:
252290

253291
# Demande confirmation
254292
if not sctx.msg_question(
255-
sctx.tr("License Injector", "License Injector"),
256-
sctx.tr(
257-
f"Injecter la licence (SPDX: {spdx_id}) dans les fichiers correspondant aux motifs: {patterns} ?",
258-
f"Inject license (SPDX: {spdx_id}) into files matching: {patterns} ?",
293+
self._t(sctx, "title", "License Injector", "License Injector"),
294+
self._t(
295+
sctx,
296+
"confirm",
297+
"Injecter la licence (SPDX: {spdx}) dans les fichiers correspondant aux motifs: {patterns} ?",
298+
"Inject license (SPDX: {spdx}) into files matching: {patterns} ?",
299+
spdx=spdx_id,
300+
patterns=patterns,
259301
),
260302
default_yes=False,
261303
):
262-
sctx.log_warn(sctx.tr("license_injector: opération annulée par l'utilisateur", "license_injector: operation canceled by user"))
304+
sctx.log_warn(self._t(sctx, "canceled", "license_injector: opération annulée par l'utilisateur", "license_injector: operation canceled by user"))
263305
return
264306

265307
# Phase 1: analyse des cibles
266308
ph = API_SDK.progress(
267-
sctx.tr("Injection de licence", "License Injection"),
268-
sctx.tr("Analyse des fichiers cibles...", "Scanning target files..."),
309+
self._t(sctx, "progress_title", "Injection de licence", "License Injection"),
310+
self._t(sctx, "progress_scan", "Analyse des fichiers cibles...", "Scanning target files..."),
269311
maximum=0,
270312
cancelable=True,
271313
)
@@ -275,7 +317,7 @@ def on_pre_compile(self, ctx: PreCompileContext) -> None:
275317
skipped_dup = 0
276318
for p in sctx.iter_files(patterns, exclude=exclude, enforce_workspace=True):
277319
if ph.canceled:
278-
sctx.log_warn(sctx.tr("license_injector: opération annulée par l'utilisateur", "license_injector: operation canceled by user"))
320+
sctx.log_warn(self._t(sctx, "canceled", "license_injector: opération annulée par l'utilisateur", "license_injector: operation canceled by user"))
279321
return
280322
found += 1
281323
try:
@@ -310,7 +352,7 @@ def on_pre_compile(self, ctx: PreCompileContext) -> None:
310352
changed = 0
311353
for i, p in enumerate(to_modify, start=1):
312354
if ph.canceled:
313-
sctx.log_warn(sctx.tr("license_injector: opération annulée par l'utilisateur", "license_injector: operation canceled by user"))
355+
sctx.log_warn(self._t(sctx, "canceled", "license_injector: opération annulée par l'utilisateur", "license_injector: operation canceled by user"))
314356
return
315357
rel = p.relative_to(sctx.workspace_root)
316358
ph.update(i, f"{i}/{len(to_modify)}: {rel}")
@@ -328,9 +370,14 @@ def on_pre_compile(self, ctx: PreCompileContext) -> None:
328370
sctx.log_warn(f"Écriture échouée pour {rel}: {e}")
329371

330372
sctx.log_info(
331-
sctx.tr(
332-
f"license_injector: terminé. Modifiés={changed}, déjà avec SPDX={skipped_dup}, total scannés={found}",
333-
f"license_injector: done. Changed={changed}, already SPDX={skipped_dup}, total scanned={found}",
373+
self._t(
374+
sctx,
375+
"done",
376+
"license_injector: terminé. Modifiés={changed}, déjà avec SPDX={skipped}, total scannés={found}",
377+
"license_injector: done. Changed={changed}, already SPDX={skipped}, total scanned={found}",
378+
changed=changed,
379+
skipped=skipped_dup,
380+
found=found,
334381
)
335382
)
336383
finally:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"_meta": { "code": "en", "name": "English" },
3+
"title": "License Injector",
4+
"no_license": "license_injector: no license detected (pyproject or LICENSE/LICENCE/COPYING/NOTICE files). No injection performed.",
5+
"confirm": "Inject license (SPDX: {spdx}) into files matching: {patterns} ?",
6+
"progress_title": "License Injection",
7+
"progress_scan": "Scanning target files...",
8+
"canceled": "license_injector: operation canceled by user",
9+
"done": "license_injector: done. Changed={changed}, already SPDX={skipped}, total scanned={found}"
10+
}

0 commit comments

Comments
 (0)