multi Block in Übersetzungs config eingefügt.
This commit is contained in:
+325
-33
@@ -16,9 +16,10 @@ Dieses Programm:
|
||||
- liest eine DXF Datei und sammelt alle TEXT und MTEXT Objekte
|
||||
ODER liest Texte aus einer TXT Datei (ein Text pro Zeile)
|
||||
ODER liest den 'untranslated' Block aus einer JSON Datei
|
||||
ODER übersetzt TEXT/MTEXT direkt in einer DXF und erstellt neue übersetzte DXF
|
||||
- filtert die Texte basierend auf Mustern in translator.cfg
|
||||
- übersetzt optional Texte mit Trigrammen, Bigrammen und Einzelwörtern aus translation/<LANG>.cfg
|
||||
- schreibt die Ergebnisse in eine Excel- oder JSON-Datei
|
||||
- schreibt die Ergebnisse in eine Excel-, JSON- oder Text-Datei
|
||||
- speichert die Ausgabedatei im PROJECT_WORK Verzeichnis
|
||||
"""
|
||||
|
||||
@@ -33,7 +34,7 @@ def check_environment_var(env_str: str) -> Path:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def load_translation_config(translation_lang: str, translation_dir: Path) -> tuple[dict[str, str], dict[str, str], dict[str, str]]:
|
||||
def load_translation_config(translation_lang: str, translation_dir: Path) -> tuple[dict[str, str], dict[str, str], dict[str, str], dict[str, str]]:
|
||||
"""
|
||||
Lädt eine Übersetzungs-Config-Datei (z.B. CSK.cfg, EN.cfg, FR.cfg).
|
||||
|
||||
@@ -42,7 +43,7 @@ def load_translation_config(translation_lang: str, translation_dir: Path) -> tup
|
||||
translation_dir: Verzeichnis mit Übersetzungs-Configs (aus PROJECT_TRANSLATION)
|
||||
|
||||
Returns:
|
||||
Tuple mit (Trigramme-Dict, Bigramme-Dict, Single-Dict)
|
||||
Tuple mit (Multi-Dict, Trigramme-Dict, Bigramme-Dict, Single-Dict)
|
||||
"""
|
||||
config_file = translation_dir / f"{translation_lang}.cfg"
|
||||
|
||||
@@ -60,10 +61,19 @@ def load_translation_config(translation_lang: str, translation_dir: Path) -> tup
|
||||
print(f"Fehler beim Lesen der Übersetzungs-Konfiguration: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
multi = {}
|
||||
trigramme = {}
|
||||
bigramme = {}
|
||||
single = {}
|
||||
|
||||
# Lade Multi (4+ Wörter)
|
||||
if config.has_section('multi'):
|
||||
for key in config['multi']:
|
||||
original = key
|
||||
translation = config['multi'][key]
|
||||
if translation and not translation.startswith('#'):
|
||||
multi[original] = translation
|
||||
|
||||
# Lade Trigramme
|
||||
if config.has_section('trigramme'):
|
||||
for key in config['trigramme']:
|
||||
@@ -89,11 +99,12 @@ def load_translation_config(translation_lang: str, translation_dir: Path) -> tup
|
||||
single[original] = translation
|
||||
|
||||
print(f"\nÜbersetzungs-Config geladen ({translation_lang}):")
|
||||
print(f" Multi-Phrasen: {len(multi)}")
|
||||
print(f" Trigramme: {len(trigramme)}")
|
||||
print(f" Bigramme: {len(bigramme)}")
|
||||
print(f" Einzelwörter: {len(single)}")
|
||||
|
||||
return trigramme, bigramme, single
|
||||
return multi, trigramme, bigramme, single
|
||||
|
||||
|
||||
def load_ignore_patterns(cfg_path: Path) -> tuple[list[str], list[str]]:
|
||||
@@ -152,10 +163,10 @@ def load_ignore_patterns(cfg_path: Path) -> tuple[list[str], list[str]]:
|
||||
return wildcard_patterns, regex_patterns
|
||||
|
||||
|
||||
def translate_text(text: str, trigramme: dict[str, str], bigramme: dict[str, str], single: dict[str, str]) -> str:
|
||||
def translate_text(text: str, multi: dict[str, str], trigramme: dict[str, str], bigramme: dict[str, str], single: dict[str, str]) -> str:
|
||||
"""
|
||||
Übersetzt einen Text durch Ersetzen von Trigrammen, Bigrammen und Einzelwörtern.
|
||||
Ersetzungen erfolgen in dieser Reihenfolge: Trigramme → Bigramme → Einzelwörter.
|
||||
Übersetzt einen Text durch Ersetzen von Multi-Phrasen, Trigrammen, Bigrammen und Einzelwörtern.
|
||||
Ersetzungen erfolgen in dieser Reihenfolge: Multi → Trigramme → Bigramme → Einzelwörter.
|
||||
|
||||
Bei Einzelwörtern werden auch Satzzeichen und eingebettete Wörter berücksichtigt:
|
||||
- "Weight:" wird zu "Hmotnost:" (Doppelpunkt bleibt erhalten)
|
||||
@@ -166,6 +177,7 @@ def translate_text(text: str, trigramme: dict[str, str], bigramme: dict[str, str
|
||||
|
||||
Args:
|
||||
text: Zu übersetzender Text
|
||||
multi: Dictionary mit Multi-Wort-Phrasen (4+ Wörter)
|
||||
trigramme: Dictionary mit Drei-Wort-Phrasen
|
||||
bigramme: Dictionary mit Zwei-Wort-Phrasen
|
||||
single: Dictionary mit Einzelwörtern
|
||||
@@ -176,19 +188,25 @@ def translate_text(text: str, trigramme: dict[str, str], bigramme: dict[str, str
|
||||
translated_text = text
|
||||
has_translation = False
|
||||
|
||||
# 1. Trigramme ersetzen (längste Phrasen zuerst)
|
||||
# 1. Multi-Phrasen ersetzen (längste Phrasen zuerst)
|
||||
for original, translation in multi.items():
|
||||
if original in translated_text:
|
||||
translated_text = translated_text.replace(original, translation)
|
||||
has_translation = True
|
||||
|
||||
# 2. Trigramme ersetzen
|
||||
for original, translation in trigramme.items():
|
||||
if original in translated_text:
|
||||
translated_text = translated_text.replace(original, translation)
|
||||
has_translation = True
|
||||
|
||||
# 2. Bigramme ersetzen
|
||||
# 3. Bigramme ersetzen
|
||||
for original, translation in bigramme.items():
|
||||
if original in translated_text:
|
||||
translated_text = translated_text.replace(original, translation)
|
||||
has_translation = True
|
||||
|
||||
# 3. Einzelwörter ersetzen
|
||||
# 4. Einzelwörter ersetzen
|
||||
words = translated_text.split()
|
||||
translated_words = []
|
||||
for word in words:
|
||||
@@ -256,7 +274,7 @@ def should_ignore_text(text: str, wildcard_patterns: list[str], regex_patterns:
|
||||
|
||||
def extract_text_from_dxf(filename: Path) -> list[str]:
|
||||
"""
|
||||
Extrahiert alle TEXT und MTEXT Objekte aus einer DXF Datei.
|
||||
Extrahiert alle TEXT und MTEXT Objekte sowie TEXT-D Attribute aus Blöcken einer DXF Datei.
|
||||
Verwendet ein Set, um Duplikate zu vermeiden.
|
||||
Filtert leere Texte heraus.
|
||||
|
||||
@@ -267,9 +285,14 @@ def extract_text_from_dxf(filename: Path) -> list[str]:
|
||||
Alphabetisch sortierte Liste aller gefundenen Texte (ohne Duplikate, ohne leere Texte)
|
||||
"""
|
||||
texts_set = set() # Set für eindeutige Texte
|
||||
total_count = 0
|
||||
text_count = 0
|
||||
mtext_count = 0
|
||||
block_count = 0
|
||||
empty_count = 0
|
||||
|
||||
# Attribute die ein Block haben muss, damit TEXT-D extrahiert wird
|
||||
required_attributes = {'IO', 'ID', 'VERW', 'BEZEICHNUNG', 'KENNZEICHNUNG', 'TEXT-D'}
|
||||
|
||||
try:
|
||||
doc = ezdxf.readfile(filename)
|
||||
msp = doc.modelspace()
|
||||
@@ -277,7 +300,7 @@ def extract_text_from_dxf(filename: Path) -> list[str]:
|
||||
# Sammle alle TEXT Objekte
|
||||
for entity in msp.query('TEXT'):
|
||||
if entity.dxf.text:
|
||||
total_count += 1
|
||||
text_count += 1
|
||||
text = entity.dxf.text.strip() # Entferne führende/nachfolgende Leerzeichen
|
||||
|
||||
# Ignoriere leere Texte
|
||||
@@ -290,7 +313,7 @@ def extract_text_from_dxf(filename: Path) -> list[str]:
|
||||
# Sammle alle MTEXT Objekte
|
||||
for entity in msp.query('MTEXT'):
|
||||
if entity.text:
|
||||
total_count += 1
|
||||
mtext_count += 1
|
||||
text = entity.text.strip() # Entferne führende/nachfolgende Leerzeichen
|
||||
|
||||
# Ignoriere leere Texte
|
||||
@@ -300,11 +323,37 @@ def extract_text_from_dxf(filename: Path) -> list[str]:
|
||||
|
||||
texts_set.add(text)
|
||||
|
||||
# Sammle TEXT-D aus Blöcken mit den erforderlichen Attributen
|
||||
for entity in msp.query('INSERT'):
|
||||
if entity.has_attrib:
|
||||
# Sammle alle vorhandenen Attribute des Blocks
|
||||
block_attributes = set()
|
||||
text_d_value = None
|
||||
|
||||
for attrib in entity.attribs:
|
||||
block_attributes.add(attrib.dxf.tag)
|
||||
if attrib.dxf.tag == 'TEXT-D':
|
||||
text_d_value = attrib.dxf.text.strip() if attrib.dxf.text else None
|
||||
|
||||
# Prüfe ob Block alle erforderlichen Attribute hat
|
||||
if required_attributes.issubset(block_attributes) and text_d_value:
|
||||
block_count += 1
|
||||
|
||||
# Ignoriere leere Texte
|
||||
if not text_d_value:
|
||||
empty_count += 1
|
||||
continue
|
||||
|
||||
texts_set.add(text_d_value)
|
||||
|
||||
# Konvertiere Set zu sortierter Liste
|
||||
texts = sorted(texts_set)
|
||||
|
||||
print(f"Anzahl gefundener TEXT/MTEXT Objekte: {total_count}")
|
||||
print(f"Anzahl gefundener TEXT Objekte: {text_count}")
|
||||
print(f"Anzahl gefundener MTEXT Objekte: {mtext_count}")
|
||||
print(f"Anzahl gefundener TEXT-D in Blöcken: {block_count}")
|
||||
print(f"Leere Texte ignoriert: {empty_count}")
|
||||
total_count = text_count + mtext_count + block_count
|
||||
print(f"Duplikate entfernt: {total_count - empty_count - len(texts)}")
|
||||
print(f"Eindeutige Texte extrahiert: {len(texts)}")
|
||||
|
||||
@@ -440,8 +489,173 @@ def read_texts_from_json(filename: Path) -> list[str]:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def load_translations_from_json(filename: Path) -> dict[str, str]:
|
||||
"""
|
||||
Liest Übersetzungen aus dem 'translations' Block einer JSON-Datei.
|
||||
Erwartet eine Struktur mit "translations": [{"source": "...", "target": "..."}, ...]
|
||||
|
||||
Args:
|
||||
filename: Pfad zur JSON-Datei
|
||||
|
||||
Returns:
|
||||
Dictionary mit source -> target Mappings
|
||||
"""
|
||||
try:
|
||||
with open(filename, '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)
|
||||
|
||||
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)
|
||||
|
||||
translations = {}
|
||||
for idx, entry in enumerate(translations_list):
|
||||
if not isinstance(entry, dict):
|
||||
print(f"WARNUNG: Eintrag {idx} in 'translations' ist kein Object, überspringe")
|
||||
continue
|
||||
|
||||
if 'source' not in entry or 'target' not in entry:
|
||||
print(f"WARNUNG: Eintrag {idx} in 'translations' fehlt 'source' oder 'target', überspringe")
|
||||
continue
|
||||
|
||||
source = entry['source']
|
||||
target = entry['target']
|
||||
if source and target: # Ignoriere leere Einträge
|
||||
translations[source] = target
|
||||
|
||||
print(f"Übersetzungen aus JSON-Datei geladen: {len(translations)}")
|
||||
return translations
|
||||
|
||||
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 Lesen der JSON-Datei: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def translate_dxf_texts(input_dxf: Path, output_dxf: Path, translations: dict[str, str],
|
||||
wildcard_patterns: list[str], regex_patterns: list[str]):
|
||||
"""
|
||||
Übersetzt alle TEXT, MTEXT Objekte und TEXT-D Attribute in Blöcken einer DXF-Datei.
|
||||
|
||||
Args:
|
||||
input_dxf: Pfad zur Quell-DXF
|
||||
output_dxf: Pfad zur Ziel-DXF
|
||||
translations: Dictionary mit source -> target Mappings
|
||||
wildcard_patterns: Wildcard-Muster zum Filtern
|
||||
regex_patterns: Regex-Muster zum Filtern
|
||||
"""
|
||||
# Attribute die ein Block haben muss, damit TEXT-D übersetzt wird
|
||||
required_attributes = {'IO', 'ID', 'VERW', 'BEZEICHNUNG', 'KENNZEICHNUNG', 'TEXT-D'}
|
||||
|
||||
try:
|
||||
doc = ezdxf.readfile(input_dxf)
|
||||
msp = doc.modelspace()
|
||||
|
||||
text_translated = 0
|
||||
text_skipped = 0
|
||||
text_ignored = 0
|
||||
mtext_translated = 0
|
||||
mtext_skipped = 0
|
||||
mtext_ignored = 0
|
||||
block_translated = 0
|
||||
block_skipped = 0
|
||||
block_ignored = 0
|
||||
|
||||
# Übersetze TEXT Objekte
|
||||
for entity in msp.query('TEXT'):
|
||||
if entity.dxf.text:
|
||||
original_text = entity.dxf.text.strip()
|
||||
|
||||
# Prüfe ob Text ignoriert werden soll
|
||||
if should_ignore_text(original_text, wildcard_patterns, regex_patterns):
|
||||
text_ignored += 1
|
||||
continue
|
||||
|
||||
# Suche Übersetzung
|
||||
if original_text in translations:
|
||||
entity.dxf.text = translations[original_text]
|
||||
text_translated += 1
|
||||
else:
|
||||
text_skipped += 1
|
||||
|
||||
# Übersetze MTEXT Objekte
|
||||
for entity in msp.query('MTEXT'):
|
||||
if entity.text:
|
||||
original_text = entity.text.strip()
|
||||
|
||||
# Prüfe ob Text ignoriert werden soll
|
||||
if should_ignore_text(original_text, wildcard_patterns, regex_patterns):
|
||||
mtext_ignored += 1
|
||||
continue
|
||||
|
||||
# Suche Übersetzung
|
||||
if original_text in translations:
|
||||
entity.text = translations[original_text]
|
||||
mtext_translated += 1
|
||||
else:
|
||||
mtext_skipped += 1
|
||||
|
||||
# Übersetze TEXT-D in Blöcken
|
||||
for entity in msp.query('INSERT'):
|
||||
if entity.has_attrib:
|
||||
# Sammle alle vorhandenen Attribute des Blocks
|
||||
block_attributes = set()
|
||||
text_d_attrib = None
|
||||
|
||||
for attrib in entity.attribs:
|
||||
block_attributes.add(attrib.dxf.tag)
|
||||
if attrib.dxf.tag == 'TEXT-D':
|
||||
text_d_attrib = attrib
|
||||
|
||||
# Prüfe ob Block alle erforderlichen Attribute hat
|
||||
if required_attributes.issubset(block_attributes) and text_d_attrib:
|
||||
original_text = text_d_attrib.dxf.text.strip() if text_d_attrib.dxf.text else None
|
||||
|
||||
if original_text:
|
||||
# Prüfe ob Text ignoriert werden soll
|
||||
if should_ignore_text(original_text, wildcard_patterns, regex_patterns):
|
||||
block_ignored += 1
|
||||
continue
|
||||
|
||||
# Suche Übersetzung
|
||||
if original_text in translations:
|
||||
text_d_attrib.dxf.text = translations[original_text]
|
||||
block_translated += 1
|
||||
else:
|
||||
block_skipped += 1
|
||||
|
||||
# Speichere neue DXF
|
||||
doc.saveas(output_dxf)
|
||||
|
||||
translated_count = text_translated + mtext_translated + block_translated
|
||||
skipped_count = text_skipped + mtext_skipped + block_skipped
|
||||
ignored_count = text_ignored + mtext_ignored + block_ignored
|
||||
|
||||
print(f"\nDXF-Übersetzung abgeschlossen:")
|
||||
print(f" TEXT übersetzt: {text_translated}, übersprungen: {text_skipped}, ignoriert: {text_ignored}")
|
||||
print(f" MTEXT übersetzt: {mtext_translated}, übersprungen: {mtext_skipped}, ignoriert: {mtext_ignored}")
|
||||
print(f" TEXT-D (Blöcke) übersetzt: {block_translated}, übersprungen: {block_skipped}, ignoriert: {block_ignored}")
|
||||
print(f" Gesamt: {translated_count} übersetzt, {skipped_count} übersprungen, {ignored_count} ignoriert")
|
||||
print(f" Ausgabe-Datei: {output_dxf}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Übersetzen der DXF-Datei: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def write_texts_to_excel(texts: list[str], output_path: Path,
|
||||
translation_dicts: tuple[dict[str, str], dict[str, str], dict[str, str]] = None):
|
||||
translation_dicts: tuple[dict[str, str], dict[str, str], dict[str, str], dict[str, str]] = None):
|
||||
"""
|
||||
Schreibt die Texte in die erste Spalte einer Excel-Datei.
|
||||
Optional: Schreibt Übersetzungen in die zweite Spalte.
|
||||
@@ -449,7 +663,7 @@ def write_texts_to_excel(texts: list[str], output_path: Path,
|
||||
Args:
|
||||
texts: Liste der zu schreibenden Texte
|
||||
output_path: Pfad zur Ausgabe-Excel-Datei
|
||||
translation_dicts: Optional: Tuple mit (Trigramme, Bigramme, Single) für Übersetzungen
|
||||
translation_dicts: Optional: Tuple mit (Multi, Trigramme, Bigramme, Single) für Übersetzungen
|
||||
"""
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
@@ -466,8 +680,8 @@ def write_texts_to_excel(texts: list[str], output_path: Path,
|
||||
|
||||
# Optional: Übersetzung in zweite Spalte
|
||||
if translation_dicts:
|
||||
trigramme, bigramme, single = translation_dicts
|
||||
translated = translate_text(text, trigramme, bigramme, single)
|
||||
multi, trigramme, bigramme, single = translation_dicts
|
||||
translated = translate_text(text, multi, trigramme, bigramme, single)
|
||||
if translated: # Nur wenn Übersetzung gefunden wurde
|
||||
ws[f'B{idx}'] = translated
|
||||
# Sonst bleibt die Zelle leer
|
||||
@@ -488,7 +702,7 @@ def write_texts_to_excel(texts: list[str], output_path: Path,
|
||||
|
||||
|
||||
def write_texts_to_json(texts: list[str], ignored_texts: list[str], output_path: Path,
|
||||
translation_dicts: tuple[dict[str, str], dict[str, str], dict[str, str]] = None):
|
||||
translation_dicts: tuple[dict[str, str], dict[str, str], dict[str, str], dict[str, str]] = None):
|
||||
"""
|
||||
Schreibt die Texte in eine JSON-Datei mit drei Blöcken.
|
||||
|
||||
@@ -501,19 +715,19 @@ def write_texts_to_json(texts: list[str], ignored_texts: list[str], output_path:
|
||||
texts: Liste der akzeptierten Texte
|
||||
ignored_texts: Liste der ignorierten Texte
|
||||
output_path: Pfad zur Ausgabe-JSON-Datei
|
||||
translation_dicts: Optional: Tuple mit (Trigramme, Bigramme, Single) für Übersetzungen
|
||||
translation_dicts: Optional: Tuple mit (Multi, Trigramme, Bigramme, Single) für Übersetzungen
|
||||
"""
|
||||
output_data = {}
|
||||
|
||||
# Block 1: Übersetzte Texte (als Liste von Dicts mit source/target)
|
||||
# Block 2: Nicht übersetzte Texte (als Liste von Dicts mit source und leerem target)
|
||||
if translation_dicts:
|
||||
trigramme, bigramme, single = translation_dicts
|
||||
multi, trigramme, bigramme, single = translation_dicts
|
||||
translations = []
|
||||
untranslated = []
|
||||
|
||||
for text in texts:
|
||||
translated = translate_text(text, trigramme, bigramme, single)
|
||||
translated = translate_text(text, multi, trigramme, bigramme, single)
|
||||
if translated: # Übersetzung vorhanden
|
||||
translations.append({
|
||||
"source": text,
|
||||
@@ -552,7 +766,7 @@ def write_texts_to_json(texts: list[str], ignored_texts: list[str], output_path:
|
||||
|
||||
|
||||
def write_texts_to_text(texts: list[str], ignored_texts: list[str], output_path: Path,
|
||||
translation_dicts: tuple[dict[str, str], dict[str, str], dict[str, str]] = None):
|
||||
translation_dicts: tuple[dict[str, str], dict[str, str], dict[str, str], dict[str, str]] = None):
|
||||
"""
|
||||
Schreibt die Texte in eine Textdatei mit drei Abschnitten.
|
||||
|
||||
@@ -576,18 +790,18 @@ def write_texts_to_text(texts: list[str], ignored_texts: list[str], output_path:
|
||||
texts: Liste der akzeptierten Texte
|
||||
ignored_texts: Liste der ignorierten Texte
|
||||
output_path: Pfad zur Ausgabe-Textdatei
|
||||
translation_dicts: Optional: Tuple mit (Trigramme, Bigramme, Single) für Übersetzungen
|
||||
translation_dicts: Optional: Tuple mit (Multi, Trigramme, Bigramme, Single) für Übersetzungen
|
||||
"""
|
||||
try:
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
# Block 1: Übersetzte Texte
|
||||
if translation_dicts:
|
||||
trigramme, bigramme, single = translation_dicts
|
||||
multi, trigramme, bigramme, single = translation_dicts
|
||||
translations = []
|
||||
untranslated = []
|
||||
|
||||
for text in texts:
|
||||
translated = translate_text(text, trigramme, bigramme, single)
|
||||
translated = translate_text(text, multi, trigramme, bigramme, single)
|
||||
if translated:
|
||||
translations.append((text, translated))
|
||||
else:
|
||||
@@ -617,7 +831,7 @@ def write_texts_to_text(texts: list[str], ignored_texts: list[str], output_path:
|
||||
|
||||
print(f"Text-Datei erfolgreich erstellt: {output_path}")
|
||||
if translation_dicts:
|
||||
translations_count = sum(1 for text in texts if translate_text(text, trigramme, bigramme, single))
|
||||
translations_count = sum(1 for text in texts if translate_text(text, multi, trigramme, bigramme, single))
|
||||
untranslated_count = len(texts) - translations_count
|
||||
print(f" Übersetzungen: {translations_count}")
|
||||
print(f" Nicht übersetzte Texte: {untranslated_count}")
|
||||
@@ -632,11 +846,11 @@ def write_texts_to_text(texts: list[str], ignored_texts: list[str], output_path:
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Extrahiert TEXT/MTEXT aus DXF, filtert Texte aus TXT, oder verarbeitet untranslated Block aus JSON. Optional mit Übersetzungsfunktion.',
|
||||
description='Extrahiert TEXT/MTEXT aus DXF, filtert Texte aus TXT, verarbeitet JSON, oder übersetzt DXF direkt. Optional mit Übersetzungsfunktion.',
|
||||
prog='translate'
|
||||
)
|
||||
|
||||
# Mutually exclusive group: entweder DXF-Extraktion, TXT-Filterung oder JSON-Reprocessing
|
||||
# Mutually exclusive group: entweder DXF-Extraktion, TXT-Filterung, JSON-Reprocessing oder DXF-zu-DXF
|
||||
input_group = parser.add_mutually_exclusive_group(required=True)
|
||||
input_group.add_argument(
|
||||
'-e', '--extract',
|
||||
@@ -655,6 +869,12 @@ if __name__ == '__main__':
|
||||
metavar='FILE.json',
|
||||
help='Liest untranslated Block aus JSON-Datei und übersetzt erneut (benötigt --translate)'
|
||||
)
|
||||
input_group.add_argument(
|
||||
'--todxf',
|
||||
action='store',
|
||||
metavar='OUTPUT.dxf',
|
||||
help='Übersetzt TEXT/MTEXT in DXF und schreibt neue DXF-Datei (benötigt --filename)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--filename',
|
||||
@@ -686,6 +906,12 @@ if __name__ == '__main__':
|
||||
metavar='LANG',
|
||||
help='Übersetzt Texte mit Config aus translation/<LANG>.cfg (z.B. CSK, EN, FR)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--translation-json',
|
||||
action='store',
|
||||
metavar='FILE.json',
|
||||
help='JSON-Datei mit Übersetzungen für --todxf (Standard: <filename>_texts.json)'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -693,14 +919,22 @@ if __name__ == '__main__':
|
||||
if args.extract and not args.filename:
|
||||
parser.error("--extract benötigt --filename")
|
||||
|
||||
# Validierung: --filename nur mit --extract
|
||||
if args.filename and not args.extract:
|
||||
parser.error("--filename kann nur mit --extract verwendet werden")
|
||||
# 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: --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
|
||||
work_dir = check_environment_var('PROJECT_WORK')
|
||||
cfg_dir = check_environment_var('PROJECT_CFG')
|
||||
@@ -717,6 +951,64 @@ if __name__ == '__main__':
|
||||
if args.debug:
|
||||
print("DEBUG-Modus aktiviert")
|
||||
|
||||
# Spezieller Workflow: DXF-zu-DXF Übersetzung
|
||||
if args.todxf:
|
||||
print("=== DXF-zu-DXF Übersetzung ===\n")
|
||||
|
||||
# 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)
|
||||
|
||||
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
|
||||
translations = load_translations_from_json(translation_json)
|
||||
|
||||
# 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
|
||||
translate_dxf_texts(source_dxf, output_dxf, translations, wildcard_patterns, regex_patterns)
|
||||
|
||||
print("\nVerarbeitung erfolgreich abgeschlossen.")
|
||||
sys.exit(0)
|
||||
|
||||
# Bestimme Input-Modus und Datei
|
||||
if args.extract:
|
||||
# DXF/DWG-Modus
|
||||
|
||||
@@ -97,8 +97,11 @@ with TEF=with TEF
|
||||
# ## deutsch
|
||||
Abhänger=Závěs
|
||||
BLOCK=BLOK
|
||||
Betriebsbereit=Provozuschopný
|
||||
Betriebshalt=Zastavení provozu
|
||||
Belastung=Zatížení
|
||||
Brandschutztor=protipožární vrata
|
||||
Reset=Obnovení
|
||||
Säule=Sloup
|
||||
Schnitt=Řez
|
||||
Unterverteiler=Rozvaděč
|
||||
@@ -178,4 +181,16 @@ Weight=Hmotnost
|
||||
with=s
|
||||
|
||||
|
||||
[multi]
|
||||
LM Störung=Porucha LM
|
||||
Not-Halt Kanal=Kanál nouzového zastavení
|
||||
DT Anlage Aus=DT zařízení vypnuto
|
||||
LDT Anlage Ein=LDT zařízení zapnuto
|
||||
LM Brandfall=Požár LM
|
||||
LM Druckluft fehlt=LM: chybí stlačený vzduch
|
||||
LM Lampentest=Test lampy LM
|
||||
LM Motorschutz hat ausgelöst=LM: ochrana motoru se spustila
|
||||
LM Sicherung hat ausgelöst=LM: pojistka byla vypla
|
||||
LDT Start nach Störung=LDT: spuštění po poruše
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user