116 lines
3.9 KiB
Python
116 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
patch_missing_alarms.py
|
|
|
|
Re-translates specific keys that failed during a previous run of
|
|
generate_alarm_translations.py (e.g. due to LLM JSON-format glitches),
|
|
then regenerates AlarmKnowledgeBase.cs with the now-complete English set.
|
|
|
|
Translates one key per API call to dodge the multi-key JSON formatting
|
|
issue that caused the original failures.
|
|
|
|
Edit MISSING below to set which keys to retry per language, then run:
|
|
cd csharp/App/Backend
|
|
python3 patch_missing_alarms.py
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
from generate_alarm_translations import (
|
|
translate_batch,
|
|
parse_kb_key_sections,
|
|
write_knowledge_base_cs,
|
|
load_env_file,
|
|
CHECKED_FILE,
|
|
KNOWLEDGE_BASE,
|
|
RESOURCES_DIR,
|
|
TARGET_LANGUAGES,
|
|
)
|
|
|
|
# Keys that failed during the 2026-04-28 run.
|
|
# Update this dict if a new run produces different failures.
|
|
MISSING = {
|
|
"en": [
|
|
"DcBusOvervoltage",
|
|
"DcBusUndervoltage",
|
|
"DcBusVoltageUnbalance",
|
|
"BusSlowOvervoltage",
|
|
"HardwareBusOvervoltage",
|
|
],
|
|
"it": [
|
|
"NtcTemperatureSensorBroken",
|
|
"SyncSignalAbnormal",
|
|
"GridStartupConditionsNotMet",
|
|
"BatteryCommunicationFailure",
|
|
"BatteryDisconnected",
|
|
],
|
|
}
|
|
|
|
|
|
def main():
|
|
api_key = os.environ.get("MISTRAL_API_KEY", "").strip()
|
|
if not api_key:
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
api_key = load_env_file(os.path.join(script_dir, ".env")).get("MISTRAL_API_KEY", "").strip()
|
|
if not api_key:
|
|
print("ERROR: MISTRAL_API_KEY not found in environment or .env file.")
|
|
sys.exit(1)
|
|
print("MISTRAL_API_KEY loaded.")
|
|
|
|
with open(CHECKED_FILE, encoding="utf-8-sig") as f:
|
|
de = json.load(f)
|
|
|
|
en_translations = None
|
|
|
|
for lang_code, missing_keys in MISSING.items():
|
|
lang_name = TARGET_LANGUAGES[lang_code]
|
|
out_file = os.path.join(RESOURCES_DIR, f"AlarmTranslationsChecked.{lang_code}.json")
|
|
with open(out_file, encoding="utf-8") as f:
|
|
existing = json.load(f)
|
|
|
|
# Idempotent: only translate keys that are still genuinely missing from the JSON.
|
|
actually_missing = [
|
|
k for k in missing_keys
|
|
if k in de and (k not in existing or not existing[k].get("Explanation"))
|
|
]
|
|
if not actually_missing:
|
|
print(f"\n── {lang_name} ({lang_code}) already complete ({len(existing)} entries) — skipping translation ──")
|
|
else:
|
|
print(f"\n── Patching {lang_name} ({lang_code}) — {len(actually_missing)} keys ──")
|
|
translated = {}
|
|
for key in actually_missing:
|
|
print(f" {key}")
|
|
result = translate_batch(api_key, {key: de[key]}, lang_name)
|
|
if result and key in result:
|
|
r = result[key]
|
|
translated[key] = {
|
|
"Explanation": r.get("Explanation", ""),
|
|
"Causes": r.get("Causes", []),
|
|
"NextSteps": r.get("NextSteps", []),
|
|
}
|
|
snippet = r.get("Explanation", "")[:80]
|
|
print(f" OK: {snippet}{'...' if len(r.get('Explanation','')) > 80 else ''}")
|
|
else:
|
|
print(f" FAILED: {key}")
|
|
|
|
existing.update(translated)
|
|
with open(out_file, "w", encoding="utf-8") as f:
|
|
json.dump(existing, f, ensure_ascii=False, indent=2)
|
|
print(f" ✓ Wrote {len(existing)} total entries → {out_file}")
|
|
|
|
if lang_code == "en":
|
|
en_translations = existing
|
|
|
|
if en_translations is not None and os.path.exists(KNOWLEDGE_BASE):
|
|
print("\n── Regenerating AlarmKnowledgeBase.cs ──")
|
|
key_sections = parse_kb_key_sections(KNOWLEDGE_BASE)
|
|
write_knowledge_base_cs(KNOWLEDGE_BASE, en_translations, key_sections)
|
|
|
|
print("\n✓ Patch done.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|