main Funktion aufgeteilt

This commit is contained in:
2026-02-10 17:25:07 +01:00
parent 002b5e0bf1
commit 28cd3c630e
+207 -230
View File
@@ -9,7 +9,7 @@ from fnmatch import fnmatch
import ezdxf
from openpyxl import Workbook
from utils import check_environment_var
from utils import check_environment_var, check_file_in_work
"""
@@ -1810,7 +1810,32 @@ def retranslate_json_file(json_path: Path,
sys.exit(1)
if __name__ == '__main__':
def resolve_input_file(name: str, work_dir: Path, label: str = "Datei") -> Path:
"""
Sucht eine Datei zuerst im Work-Ordner, dann als vollständigen/relativen Pfad.
Gibt den aufgelösten Path zurück oder beendet das Programm mit Fehlermeldung.
Verwendet intern check_file_in_work() aus utils für die Dateisuche.
Args:
name: Dateiname oder Pfad (wie vom Benutzer angegeben)
work_dir: Arbeitsverzeichnis, in dem zuerst gesucht wird
label: Bezeichnung der Datei für die Fehlermeldung (z.B. "DXF-Datei")
Returns:
Path zur gefundenen Datei
"""
path, found = check_file_in_work(work_dir, name)
if not found:
print(f"{label} nicht gefunden: {name}")
print(f" Geprüft in Work-Ordner: {work_dir / name}")
print(f" Geprüft als vollständiger Pfad: {Path(name)}")
sys.exit(1)
return path
def _build_arg_parser() -> argparse.ArgumentParser:
"""Erstellt und konfiguriert den Argument-Parser für translate.py."""
parser = argparse.ArgumentParser(
description='Extrahiert TEXT/MTEXT aus DXF, filtert Texte aus TXT, verarbeitet JSON, oder übersetzt DXF direkt. Optional mit Übersetzungsfunktion.',
prog='translate'
@@ -1890,69 +1915,213 @@ if __name__ == '__main__':
metavar='FILE.json',
help='JSON-Datei mit Übersetzungen für --todxf (Standard: <filename>_texts.json)'
)
return parser
def _run_retranslate(
args,
work_dir: Path,
translation_dicts_all: dict,
translation_languages: list) -> None:
"""Workflow: Re-Übersetzung einer bestehenden JSON-Datei (--retranslate-json)."""
print("=== Re-Übersetzung JSON-Datei ===\n")
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 = resolve_input_file(input_filename, work_dir, "JSON-Datei")
print(f"JSON-Datei: {json_file}")
print(f"Sprachen: {', '.join(translation_languages)}")
retranslate_json_file(json_file, translation_dicts_all, translation_languages)
print("\nVerarbeitung erfolgreich abgeschlossen.")
sys.exit(0)
def _run_todxf(
args,
work_dir: Path,
translation_languages: list,
wildcard_patterns: list,
regex_patterns: list,
source_attr_name: str,
target_attr_name: str,
target_layer_name: str | None) -> None:
"""Workflow: DXF-zu-DXF Übersetzung (--todxf)."""
print("=== DXF-zu-DXF Übersetzung ===\n")
input_filename = args.filename
if not input_filename.lower().endswith(('.dxf', '.dwg')):
print("Mit --todxf nur .dxf oder .dwg Dateien als Quelle erlaubt")
sys.exit(1)
source_dxf = resolve_input_file(input_filename, work_dir, "Quell-DXF")
print(f"Quell-DXF: {source_dxf}")
# Bestimme JSON-Datei mit Übersetzungen
if args.translation_json:
translation_json = resolve_input_file(args.translation_json, work_dir, "Übersetzungs-JSON")
else:
# Standard: <filename>_texts.json im Work-Ordner
translation_json = work_dir / (Path(input_filename).stem + "_texts.json")
if not translation_json.exists():
print(f"Standard-Übersetzungs-JSON nicht gefunden: {translation_json}")
print(f"Bitte erstellen Sie die Datei oder geben Sie eine alternative mit --translation-json an")
sys.exit(1)
print(f"Übersetzungs-JSON: {translation_json}")
target_lang = translation_languages[0] if translation_languages else None
translations = load_translations_from_json(translation_json, target_lang)
output_dxf_name = args.todxf
if not output_dxf_name.lower().endswith(('.dxf', '.dwg')):
output_dxf_name += '.dxf'
output_dxf = work_dir / output_dxf_name
print(f"Ziel-DXF: {output_dxf}")
translate_dxf_texts(
source_dxf,
output_dxf,
translations,
wildcard_patterns,
regex_patterns,
source_attr_name,
target_attr_name,
target_layer_name,
)
print("\nVerarbeitung erfolgreich abgeschlossen.")
sys.exit(0)
def _run_extract_or_import(
args,
work_dir: Path,
wildcard_patterns: list,
regex_patterns: list,
translation_dicts,
translation_dicts_all: dict,
translation_languages: list,
export_types: list,
source_attr_name: str) -> None:
"""Workflow: Texte extrahieren oder importieren (--extract, --fromtxt, --fromjson)."""
if args.extract:
input_filename = args.filename
if not input_filename.lower().endswith(('.dxf', '.dwg')):
print("Mit --extract nur .dxf oder .dwg Dateien erlaubt")
sys.exit(1)
filename = resolve_input_file(input_filename, work_dir, "DXF-Datei")
print(f"Lese DXF Datei: {filename}")
all_texts = extract_text_from_dxf(filename, source_attr_name)
elif args.fromtxt:
input_filename = args.fromtxt
if not input_filename.lower().endswith('.txt'):
print("Mit --fromtxt nur .txt Dateien erlaubt")
sys.exit(1)
filename = resolve_input_file(input_filename, work_dir, "Textdatei")
print(f"Lese Textdatei: {filename}")
all_texts = read_texts_from_file(filename)
else: # args.fromjson
input_filename = args.fromjson
if not input_filename.lower().endswith('.json'):
print("Mit --fromjson nur .json Dateien erlaubt")
sys.exit(1)
filename = resolve_input_file(input_filename, work_dir, "JSON-Datei")
print(f"Lese JSON-Datei: {filename}")
all_texts = read_texts_from_json(filename)
texts, ignored_texts = filter_texts(all_texts, wildcard_patterns, regex_patterns, args.debug)
extension_map = {
'excel': '.xlsx',
'json': '.json',
'text': '.txt'
}
print(f"\nExportiere in {len(export_types)} Format(e): {', '.join(export_types)}")
for export_type in export_types:
if args.outname:
base_name = args.outname
for ext in extension_map.values():
if base_name.endswith(ext):
base_name = base_name[:-len(ext)]
break
output_filename = f"{base_name}{extension_map[export_type]}"
else:
output_filename = f"{filename.stem}_texts{extension_map[export_type]}"
output_path = work_dir / output_filename
if export_type == 'excel':
write_texts_to_excel(texts, output_path, translation_dicts)
elif export_type == 'json':
write_texts_to_json(texts, ignored_texts, output_path, translation_dicts, translation_dicts_all, translation_languages)
else: # text
write_texts_to_text(texts, ignored_texts, output_path, translation_dicts)
print(f" [OK] {export_type}: {output_path}")
print("\nVerarbeitung erfolgreich abgeschlossen.")
def main() -> None:
"""Einstiegspunkt für translate.py. Parst Argumente und delegiert an Workflow-Funktionen."""
parser = _build_arg_parser()
args = parser.parse_args()
# Parse und validiere Export-Typen (komma-separierte Liste)
valid_export_types = {'excel', 'json', 'text'}
export_types = [t.strip() for t in args.export_type.split(',')]
# Validiere jeden Export-Typ
for export_type in export_types:
if export_type not in valid_export_types:
parser.error(f"Ungültiger Export-Typ: '{export_type}'. Erlaubt sind: {', '.join(sorted(valid_export_types))}")
# Entferne Duplikate und behalte Reihenfolge
seen = set()
seen: set = set()
export_types = [t for t in export_types if not (t in seen or seen.add(t))]
# Validierung: --extract benötigt --filename
# Validierung der Argument-Kombinationen
if args.extract and not args.filename:
parser.error("--extract benötigt --filename")
# Validierung: --filename nur mit --extract oder --todxf
if args.filename and not (args.extract or args.todxf):
parser.error("--filename kann nur mit --extract oder --todxf verwendet werden")
# Validierung: --fromjson benötigt --translate
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)")
# Validierung: --translation-json nur mit --todxf
if args.translation_json and not args.todxf:
parser.error("--translation-json kann nur mit --todxf verwendet werden")
# Prüfe Umgebungsvariablen
# Umgebungsvariablen und gemeinsame Konfiguration laden
work_dir = check_environment_var('PROJECT_WORK')
cfg_dir = check_environment_var('PROJECT_CFG')
# Lade Ignore-Muster aus Konfigurationsdatei
wildcard_patterns, regex_patterns = load_ignore_patterns(cfg_dir)
# Lade Symbol-Attribut- und Layer-Mapping
symbol_attr_mapping = load_symbol_attribute_mapping(cfg_dir)
symbol_layer_mapping = load_symbol_layer_mapping(cfg_dir)
# Parse Sprachen aus --translate Parameter (kommaseparierte Liste)
# Zielsprachen parsen (kommasepariert, dedupliziert)
translation_languages = []
if args.translate:
translation_languages = [lang.strip().upper() for lang in args.translate.split(',')]
# Entferne Duplikate und behalte Reihenfolge
seen = set()
translation_languages = [lang for lang in translation_languages if lang and not (lang in seen or seen.add(lang))]
translation_languages = [
lang for lang in (l.strip().upper() for l in args.translate.split(','))
if lang and not (lang in seen or seen.add(lang))
]
# Bestimme Quell-Attributnamen basierend auf Sprachcode
# Attribut- und Layer-Namen bestimmen
source_attr_name = symbol_attr_mapping.get(args.lang_source, 'TEXT-D')
# Für --todxf: verwende nur die erste Sprache als Ziel (backwards compatibility)
target_attr_name = symbol_attr_mapping.get(translation_languages[0], 'TEXT-CS') if translation_languages else 'TEXT-CS'
target_layer_name = symbol_layer_mapping.get(translation_languages[0]) if translation_languages else None
@@ -1966,223 +2135,31 @@ if __name__ == '__main__':
else:
print(f" Ziel-Sprachen (--translate): {', '.join(translation_languages)}")
# Optional: Lade Übersetzungs-Configs für alle Sprachen
# translation_dicts_all ist ein Dict: {LANG: (multi, trigramme, bigramme, single), ...}
# Übersetzungs-Configs laden: {LANG: (multi, trigramme, bigramme, single), ...}
translation_dicts_all = {}
if translation_languages:
translation_dir = check_environment_var('PROJECT_TRANSLATION')
for lang in translation_languages:
translation_dicts_all[lang] = load_translation_config(lang, translation_dir)
# Für backwards compatibility: wenn nur eine Sprache, setze translation_dicts wie früher
# Für backwards compatibility: bei genau einer Sprache flaches Dict bereitstellen
translation_dicts = translation_dicts_all.get(translation_languages[0]) if len(translation_languages) == 1 else None
if args.debug:
print("DEBUG-Modus aktiviert")
# Spezieller Workflow: Re-Übersetzung einer JSON-Datei
# Workflow delegieren
if args.retranslate_json:
print("=== Re-Übersetzung JSON-Datei ===\n")
_run_retranslate(args, work_dir, translation_dicts_all, translation_languages)
# 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")
_run_todxf(args, work_dir, translation_languages, wildcard_patterns, regex_patterns,
source_attr_name, target_attr_name, target_layer_name)
# Finde Quell-DXF
input_filename = args.filename
if not input_filename.lower().endswith(('.dxf', '.dwg')):
print("Mit --todxf nur .dxf oder .dwg Dateien als Quelle erlaubt")
sys.exit(1)
_run_extract_or_import(args, work_dir, wildcard_patterns, regex_patterns,
translation_dicts, translation_dicts_all, translation_languages,
export_types, source_attr_name)
source_dxf = work_dir / input_filename
if not source_dxf.exists():
source_dxf = Path(input_filename)
if not source_dxf.exists():
print(f"Quell-DXF nicht gefunden: {input_filename}")
print(f" Geprüft in Work-Ordner: {work_dir / input_filename}")
print(f" Geprüft als vollständiger Pfad: {source_dxf}")
sys.exit(1)
print(f"Quell-DXF: {source_dxf}")
# Bestimme JSON-Datei mit Übersetzungen
if args.translation_json:
translation_json = work_dir / args.translation_json
if not translation_json.exists():
translation_json = Path(args.translation_json)
if not translation_json.exists():
print(f"Übersetzungs-JSON nicht gefunden: {args.translation_json}")
print(f" Geprüft in Work-Ordner: {work_dir / args.translation_json}")
print(f" Geprüft als vollständiger Pfad: {translation_json}")
sys.exit(1)
else:
# Standard: <filename>_texts.json im Work-Ordner
translation_json = work_dir / (Path(input_filename).stem + "_texts.json")
if not translation_json.exists():
print(f"Standard-Übersetzungs-JSON nicht gefunden: {translation_json}")
print(f"Bitte erstellen Sie die Datei oder geben Sie eine alternative mit --translation-json an")
sys.exit(1)
print(f"Übersetzungs-JSON: {translation_json}")
# Lade Übersetzungen (verwende erste Sprache als Ziel-Sprache)
target_lang = translation_languages[0] if translation_languages else None
translations = load_translations_from_json(translation_json, target_lang)
# Bestimme Ausgabe-DXF
output_dxf_name = args.todxf
if not output_dxf_name.lower().endswith(('.dxf', '.dwg')):
output_dxf_name += '.dxf'
output_dxf = work_dir / output_dxf_name
print(f"Ziel-DXF: {output_dxf}")
# Übersetze DXF (inkl. ggf. neuer TEXT-Attribute und Layer)
translate_dxf_texts(
source_dxf,
output_dxf,
translations,
wildcard_patterns,
regex_patterns,
source_attr_name,
target_attr_name,
target_layer_name,
)
print("\nVerarbeitung erfolgreich abgeschlossen.")
sys.exit(0)
# Bestimme Input-Modus und Datei
if args.extract:
# DXF/DWG-Modus
input_filename = args.filename
file_extension = input_filename.lower()
if not file_extension.endswith(('.dxf', '.dwg')):
print("Mit --extract nur .dxf oder .dwg Dateien erlaubt")
sys.exit(1)
# Versuche zuerst Datei im Work-Ordner zu finden
filename = work_dir / input_filename
if not filename.exists():
# Falls nicht gefunden, prüfe ob es ein vollständiger Pfad ist
filename = Path(input_filename)
if not filename.exists():
print(f"Datei nicht gefunden: {input_filename}")
print(f" Geprüft in Work-Ordner: {work_dir / input_filename}")
print(f" Geprüft als vollständiger Pfad: {filename}")
sys.exit(1)
print(f"Lese DXF Datei: {filename}")
all_texts = extract_text_from_dxf(filename, source_attr_name)
elif args.fromtxt:
# TXT-Modus
input_filename = args.fromtxt
if not input_filename.lower().endswith('.txt'):
print("Mit --fromtxt nur .txt Dateien erlaubt")
sys.exit(1)
# Versuche zuerst Datei im Work-Ordner zu finden
filename = work_dir / input_filename
if not filename.exists():
# Falls nicht gefunden, prüfe ob es ein vollständiger Pfad ist
filename = Path(input_filename)
if not filename.exists():
print(f"Datei nicht gefunden: {input_filename}")
print(f" Geprüft in Work-Ordner: {work_dir / input_filename}")
print(f" Geprüft als vollständiger Pfad: {filename}")
sys.exit(1)
print(f"Lese Textdatei: {filename}")
all_texts = read_texts_from_file(filename)
else: # args.fromjson
# JSON-Modus
input_filename = args.fromjson
if not input_filename.lower().endswith('.json'):
print("Mit --fromjson nur .json Dateien erlaubt")
sys.exit(1)
# Versuche zuerst Datei im Work-Ordner zu finden
filename = work_dir / input_filename
if not filename.exists():
# Falls nicht gefunden, prüfe ob es ein vollständiger Pfad ist
filename = Path(input_filename)
if not filename.exists():
print(f"Datei nicht gefunden: {input_filename}")
print(f" Geprüft in Work-Ordner: {work_dir / input_filename}")
print(f" Geprüft als vollständiger Pfad: {filename}")
sys.exit(1)
print(f"Lese JSON-Datei: {filename}")
all_texts = read_texts_from_json(filename)
# Schritt 2: Texte filtern
texts, ignored_texts = filter_texts(all_texts, wildcard_patterns, regex_patterns, args.debug)
# Mapping für Dateiendungen
extension_map = {
'excel': '.xlsx',
'json': '.json',
'text': '.txt'
}
# Export für jeden angegebenen Typ durchführen
print(f"\nExportiere in {len(export_types)} Format(e): {', '.join(export_types)}")
for export_type in export_types:
# Erstelle Output-Dateinamen basierend auf Export-Typ
if args.outname:
# Verwende benutzerdefinierten Namen
base_name = args.outname
# Entferne existierende Endung falls vorhanden
for ext in extension_map.values():
if base_name.endswith(ext):
base_name = base_name[:-len(ext)]
break
# Füge korrekte Endung hinzu
output_filename = f"{base_name}{extension_map[export_type]}"
else:
# Standardname basierend auf Eingabedatei
output_filename = f"{filename.stem}_texts{extension_map[export_type]}"
output_path = work_dir / output_filename
# Schreibe Texte in gewähltem Format
if export_type == 'excel':
write_texts_to_excel(texts, output_path, translation_dicts)
elif export_type == 'json':
write_texts_to_json(texts, ignored_texts, output_path, translation_dicts, translation_dicts_all, translation_languages)
else: # text
write_texts_to_text(texts, ignored_texts, output_path, translation_dicts)
print(f" [OK] {export_type}: {output_path}")
print("\nVerarbeitung erfolgreich abgeschlossen.")
if __name__ == '__main__':
main()