#!/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()