diff --git a/lib/translate.py b/lib/translate.py index c6b1339..6e0b6d5 100644 --- a/lib/translate.py +++ b/lib/translate.py @@ -1282,6 +1282,187 @@ def write_texts_to_text(texts: list[str], ignored_texts: list[str], output_path: sys.exit(1) +def retranslate_json_file(json_path: Path, + translation_dicts_all: dict[str, tuple], + translation_languages: list[str]): + """ + Re-übersetzt eine JSON-Datei mit neuen Übersetzungs-Configs. + Liest alle "source" Texte aus dem "translations" Block und übersetzt sie neu. + Überschreibt die ursprüngliche JSON-Datei mit den aktualisierten Übersetzungen. + + Unterstützt beide Strukturen: + - Alte Struktur: "translations": [{"source": "...", "target": "..."}, ...] + - Hierarchische Struktur: "[LANG]": {"translations": [...], ...} + + Args: + json_path: Pfad zur JSON-Datei + translation_dicts_all: Dict mit {LANG: (multi, trigramme, bigramme, single), ...} + translation_languages: Liste der Sprachen in der Reihenfolge der Verarbeitung + """ + try: + # Lade bestehende JSON-Datei + with open(json_path, 'r', encoding='utf-8') as f: + data = json.load(f) + + if not isinstance(data, dict): + print(f"FEHLER: JSON-Datei hat ungültige Struktur (erwartet Object, bekam {type(data).__name__})") + sys.exit(1) + + # Erkenne Struktur + structure_type, existing_languages = detect_json_structure(data) + + updated_count = 0 + unchanged_count = 0 + new_count = 0 + + if structure_type == "legacy": + # Alte Struktur: ein Sprach-Block + if 'translations' not in data: + print(f"FEHLER: JSON-Datei enthält keinen 'translations' Block") + sys.exit(1) + + translations_list = data['translations'] + if not isinstance(translations_list, list): + print(f"FEHLER: 'translations' Block hat ungültige Struktur (erwartet Array)") + sys.exit(1) + + # Verwende erste Sprache für Re-Übersetzung + if not translation_languages or translation_languages[0] not in translation_dicts_all: + print(f"FEHLER: Keine Übersetzungs-Config für Re-Übersetzung verfügbar") + sys.exit(1) + + multi, trigramme, bigramme, single = translation_dicts_all[translation_languages[0]] + + # Re-übersetze alle Einträge + for entry in translations_list: + if not isinstance(entry, dict) or 'source' not in entry: + continue + + source = entry['source'] + old_target = entry.get('target', '') + + # Neue Übersetzung berechnen + new_target = translate_text(source, multi, trigramme, bigramme, single) + + if new_target: + if new_target != old_target: + entry['target'] = new_target + updated_count += 1 + else: + unchanged_count += 1 + else: + # Keine Übersetzung mehr verfügbar -> in untranslated verschieben + if 'untranslated' not in data: + data['untranslated'] = [] + data['untranslated'].append({ + "source": source, + "target": "" + }) + translations_list.remove(entry) + print(f" WARNUNG: Übersetzung für '{source}' nicht mehr verfügbar, verschoben zu 'untranslated'") + + print(f"\nRe-Übersetzung abgeschlossen (alte Struktur, Sprache: {translation_languages[0]}):") + print(f" Aktualisiert: {updated_count}") + print(f" Unverändert: {unchanged_count}") + + elif structure_type == "multilang": + # Hierarchische mehrsprachige Struktur + print(f"Erkannte mehrsprachige Struktur mit Sprachen: {', '.join(existing_languages)}") + + # Re-übersetze für alle angegebenen Sprachen + for lang in translation_languages: + lang_key = f"[{lang}]" + + # Wenn Sprache nicht in JSON existiert, erstelle neuen Block + if lang_key not in data: + print(f" Erstelle neuen Sprach-Block: [{lang}]") + data[lang_key] = { + "translations": [], + "untranslated": [] + } + new_count += 1 + + lang_data = data[lang_key] + if not isinstance(lang_data, dict): + print(f"WARNUNG: [{lang}] Block ist kein Object, überspringe") + continue + + # Stelle sicher dass translations Block existiert + if 'translations' not in lang_data: + lang_data['translations'] = [] + if 'untranslated' not in lang_data: + lang_data['untranslated'] = [] + + translations_list = lang_data['translations'] + if not isinstance(translations_list, list): + print(f"WARNUNG: [{lang}][translations] ist kein Array, überspringe") + continue + + # Hole Übersetzungs-Config für diese Sprache + if lang not in translation_dicts_all: + print(f"WARNUNG: Keine Übersetzungs-Config für [{lang}] verfügbar, überspringe") + continue + + multi, trigramme, bigramme, single = translation_dicts_all[lang] + + lang_updated = 0 + lang_unchanged = 0 + + # Re-übersetze alle Einträge für diese Sprache + for entry in translations_list[:]: # Kopie der Liste für sicheres Entfernen + if not isinstance(entry, dict) or 'source' not in entry: + continue + + source = entry['source'] + old_target = entry.get('target', '') + + # Neue Übersetzung berechnen + new_target = translate_text(source, multi, trigramme, bigramme, single) + + if new_target: + if new_target != old_target: + entry['target'] = new_target + lang_updated += 1 + else: + lang_unchanged += 1 + else: + # Keine Übersetzung mehr verfügbar -> in untranslated verschieben + lang_data['untranslated'].append({ + "source": source, + "target": "" + }) + translations_list.remove(entry) + print(f" WARNUNG: [{lang}] Übersetzung für '{source}' nicht mehr verfügbar, verschoben zu 'untranslated'") + + updated_count += lang_updated + unchanged_count += lang_unchanged + + print(f" [{lang}] Aktualisiert: {lang_updated}, Unverändert: {lang_unchanged}") + + print(f"\nRe-Übersetzung abgeschlossen (mehrsprachige Struktur):") + print(f" Gesamt aktualisiert: {updated_count}") + print(f" Gesamt unverändert: {unchanged_count}") + if new_count > 0: + print(f" Neue Sprach-Blöcke erstellt: {new_count}") + + else: + print(f"FEHLER: JSON-Datei hat unbekannte Struktur") + sys.exit(1) + + # Schreibe aktualisierte JSON-Datei zurück + with open(json_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + print(f"\nJSON-Datei erfolgreich aktualisiert: {json_path}") + + except json.JSONDecodeError as e: + print(f"Fehler beim Parsen der JSON-Datei: {e}") + sys.exit(1) + except Exception as e: + print(f"Fehler beim Re-Übersetzen der JSON-Datei: {e}") + sys.exit(1) + + if __name__ == '__main__': parser = argparse.ArgumentParser( description='Extrahiert TEXT/MTEXT aus DXF, filtert Texte aus TXT, verarbeitet JSON, oder übersetzt DXF direkt. Optional mit Übersetzungsfunktion.', @@ -1307,6 +1488,12 @@ if __name__ == '__main__': metavar='FILE.json', help='Liest untranslated Block aus JSON-Datei und übersetzt erneut (benötigt --translate)' ) + input_group.add_argument( + '--retranslate-json', + action='store', + metavar='FILE.json', + help='Re-übersetzt translations Block in JSON-Datei mit aktueller Sprachkonfig (benötigt --translate)' + ) input_group.add_argument( '--todxf', action='store', @@ -1384,6 +1571,10 @@ if __name__ == '__main__': if args.fromjson and not args.translate: parser.error("--fromjson benötigt --translate (Übersetzung ist erforderlich)") + # Validierung: --retranslate-json benötigt --translate + if args.retranslate_json and not args.translate: + parser.error("--retranslate-json benötigt --translate (Übersetzung ist erforderlich)") + # Validierung: --todxf benötigt --filename if args.todxf and not args.filename: parser.error("--todxf benötigt --filename (Quell-DXF muss angegeben werden)") @@ -1442,6 +1633,34 @@ if __name__ == '__main__': if args.debug: print("DEBUG-Modus aktiviert") + # Spezieller Workflow: Re-Übersetzung einer JSON-Datei + if args.retranslate_json: + print("=== Re-Übersetzung JSON-Datei ===\n") + + # Finde JSON-Datei + input_filename = args.retranslate_json + if not input_filename.lower().endswith('.json'): + print("Mit --retranslate-json nur .json Dateien erlaubt") + sys.exit(1) + + json_file = work_dir / input_filename + if not json_file.exists(): + json_file = Path(input_filename) + if not json_file.exists(): + print(f"JSON-Datei nicht gefunden: {input_filename}") + print(f" Geprüft in Work-Ordner: {work_dir / input_filename}") + print(f" Geprüft als vollständiger Pfad: {json_file}") + sys.exit(1) + + print(f"JSON-Datei: {json_file}") + print(f"Sprachen: {', '.join(translation_languages)}") + + # Re-übersetze JSON-Datei + retranslate_json_file(json_file, translation_dicts_all, translation_languages) + + print("\nVerarbeitung erfolgreich abgeschlossen.") + sys.exit(0) + # Spezieller Workflow: DXF-zu-DXF Übersetzung if args.todxf: print("=== DXF-zu-DXF Übersetzung ===\n")