diff --git a/lib/translate.py b/lib/translate.py index 4fd21a8..c762c27 100644 --- a/lib/translate.py +++ b/lib/translate.py @@ -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/.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/.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: _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: _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 diff --git a/translation/CSK.cfg b/translation/CSK.cfg index 83cf45e..d154ef9 100644 --- a/translation/CSK.cfg +++ b/translation/CSK.cfg @@ -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 +