From 07648a919394641ea629f9cf0b05d26afebc2e35 Mon Sep 17 00:00:00 2001 From: mistangl Date: Tue, 10 Feb 2026 10:16:56 +0100 Subject: [PATCH] Verweise auf Pfad wieder mit %~dp0 gemacht --- bin/tr2dxf_cs.bat | 4 +- bin/tr2dxf_en.bat | 4 +- bin/tr2dxf_es.bat | 4 +- bin/tr2dxf_fr.bat | 4 +- bin/tr2dxf_it.bat | 4 +- lib/translate.py | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 197 insertions(+), 10 deletions(-) diff --git a/bin/tr2dxf_cs.bat b/bin/tr2dxf_cs.bat index 72780f3..f0c3d6f 100644 --- a/bin/tr2dxf_cs.bat +++ b/bin/tr2dxf_cs.bat @@ -1,6 +1,6 @@ @echo off -REM Wrapper für Tschechisch-Übersetzungen +REM Wrapper f r Tschechisch- bersetzungen REM Ruft tr2dxf.bat mit CS als Sprachparameter auf -call C:\kabellaengen\bin\setenv.bat +call "%~dp0setenv.bat" call "%PROJECT_BIN%\tr2dxf.bat" CS %1 diff --git a/bin/tr2dxf_en.bat b/bin/tr2dxf_en.bat index 8751c44..a75647c 100644 --- a/bin/tr2dxf_en.bat +++ b/bin/tr2dxf_en.bat @@ -1,6 +1,6 @@ @echo off -REM Wrapper für Englisch-Übersetzungen +REM Wrapper für Englisch-Übersetzungen REM Ruft tr2dxf.bat mit EN als Sprachparameter auf -call C:\kabellaengen\bin\setenv.bat +call "%~dp0setenv.bat" call "%PROJECT_BIN%\tr2dxf.bat" EN %1 diff --git a/bin/tr2dxf_es.bat b/bin/tr2dxf_es.bat index e35d04a..c882ada 100644 --- a/bin/tr2dxf_es.bat +++ b/bin/tr2dxf_es.bat @@ -1,6 +1,6 @@ @echo off -REM Wrapper für Spanisch-Übersetzungen +REM Wrapper für Spanisch-Übersetzungen REM Ruft tr2dxf.bat mit ES als Sprachparameter auf -call C:\kabellaengen\bin\setenv.bat +call "%~dp0setenv.bat" call "%PROJECT_BIN%\tr2dxf.bat" ES %1 diff --git a/bin/tr2dxf_fr.bat b/bin/tr2dxf_fr.bat index fc16247..38059bb 100644 --- a/bin/tr2dxf_fr.bat +++ b/bin/tr2dxf_fr.bat @@ -1,6 +1,6 @@ @echo off -REM Wrapper für Französisch-Übersetzungen +REM Wrapper für Französisch-Übersetzungen REM Ruft tr2dxf.bat mit FR als Sprachparameter auf -call C:\kabellaengen\bin\setenv.bat +call "%~dp0setenv.bat" call "%PROJECT_BIN%\tr2dxf.bat" FR %1 diff --git a/bin/tr2dxf_it.bat b/bin/tr2dxf_it.bat index 572eb9d..9cf1726 100644 --- a/bin/tr2dxf_it.bat +++ b/bin/tr2dxf_it.bat @@ -1,6 +1,6 @@ @echo off -REM Wrapper für Italienisch-Übersetzungen +REM Wrapper für Italienisch-Übersetzungen REM Ruft tr2dxf.bat mit IT als Sprachparameter auf -call C:\kabellaengen\bin\setenv.bat +call "%~dp0setenv.bat" call "%PROJECT_BIN%\tr2dxf.bat" IT %1 diff --git a/lib/translate.py b/lib/translate.py index 6e0b6d5..fde8c3b 100644 --- a/lib/translate.py +++ b/lib/translate.py @@ -25,6 +25,181 @@ Dieses Programm: """ +def _filter_self_translations(section_name: str, translations: dict[str, str]) -> dict[str, str]: + """ + Prüft ob in einem Übersetzungs-Block auf beiden Seiten dasselbe steht (z.B. AMR ILS=AMR ILS). + Gibt eine bereinigte Kopie zurück und gibt für jeden Fund eine Warnung aus. + + Args: + section_name: Name des Abschnitts (für die Warnmeldung) + translations: Zu prüfendes Dictionary + + Returns: + Bereinigtes Dictionary ohne Selbstübersetzungen + """ + filtered = {} + for key, value in translations.items(): + if key == value: + print(f" WARNUNG [{section_name}]: Selbstübersetzung: '{key}'") + else: + filtered[key] = value + return filtered + + +def _check_translation_chains( + lang: str, + multi: dict[str, str], + trigramme: dict[str, str], + bigramme: dict[str, str], + single: dict[str, str]) -> None: + """ + Prüft ob Übersetzungsketten entstehen würden: wenn die Ausgabe eines Blocks + durch einen nachgelagerten Block weiter übersetzt würde. + + Verarbeitungsreihenfolge: multi → trigramme → bigramme → single + - multi-Ausgaben werden gegen trigramme/bigramme/single geprüft + - trigramme-Ausgaben werden gegen bigramme/single geprüft + - bigramme-Ausgaben werden gegen single geprüft + + Ändert nichts, gibt nur Warnungen aus. + + Args: + lang: Sprach-Code (für die Warnmeldung) + multi: Multi-Phrasen-Dict + trigramme: Trigramme-Dict + bigramme: Bigramme-Dict + single: Einzelwörter-Dict + """ + + def find_substring_matches(value: str, d: dict[str, str]) -> list[str]: + """Findet alle Keys aus d, die als Teilstring in value vorkommen.""" + return [key for key in d if key in value] + + def find_single_matches(value: str) -> list[str]: + """ + Findet alle Single-Keys, die in value vorkommen würden. + Spiegelt die Logik von translate_text wider: + - Direkt-Match wenn ein Leerzeichen-Token in single enthalten ist + - Sub-Match wenn ein [\\w-]+ Teilausdruck eines Tokens in single enthalten ist + """ + found = [] + seen = set() + words = value.split() + for word in words: + if word in single: + if word not in seen: + found.append(word) + seen.add(word) + else: + for m in re.finditer(r'[\w-]+', word): + sub_word = m.group(0) + if sub_word in single and sub_word not in seen: + found.append(sub_word) + seen.add(sub_word) + return found + + chain_warnings = [] + + # multi → trigramme, bigramme, single + for orig, transl in multi.items(): + for key in find_substring_matches(transl, trigramme): + chain_warnings.append( + f"[multi] '{orig}' → '{transl}' → [trigramme] würde Treffer auf '{key}' erzeugen" + ) + for key in find_substring_matches(transl, bigramme): + chain_warnings.append( + f"[multi] '{orig}' → '{transl}' → [bigramme] würde Treffer auf '{key}' erzeugen" + ) + for key in find_single_matches(transl): + chain_warnings.append( + f"[multi] '{orig}' → '{transl}' → [single] würde Treffer auf '{key}' erzeugen" + ) + + # trigramme → bigramme, single + for orig, transl in trigramme.items(): + for key in find_substring_matches(transl, bigramme): + chain_warnings.append( + f"[trigramme] '{orig}' → '{transl}' → [bigramme] würde Treffer auf '{key}' erzeugen" + ) + for key in find_single_matches(transl): + chain_warnings.append( + f"[trigramme] '{orig}' → '{transl}' → [single] würde Treffer auf '{key}' erzeugen" + ) + + # bigramme → single + for orig, transl in bigramme.items(): + for key in find_single_matches(transl): + chain_warnings.append( + f"[bigramme] '{orig}' → '{transl}' → [single] würde Treffer auf '{key}' erzeugen" + ) + + if chain_warnings: + print(f"\nWARNUNG [{lang}]: {len(chain_warnings)} mögliche Übersetzungskette(n) gefunden:") + for w in chain_warnings: + print(f" WARNUNG: {w}") + else: + print(f" Keine Übersetzungsketten gefunden.") + + +def _check_leading_spaces(config_file: Path, translation_lang: str) -> None: + """ + Liest die Config-Datei zeilenweise und prüft ob Zeilen mit einem Leerzeichen + oder Tabulator beginnen. Solche Zeilen werden vom RawConfigParser als Fortsetzung + der vorherigen Zeile interpretiert (zusammengezogen), was zu fehlerhaften + Übersetzungseinträgen führt. + + Gibt für jede betroffene Zeile eine Warnung mit Zeilennummer und Inhalt aus. + Leere Zeilen und Kommentarzeilen (# oder ;) werden ignoriert. + + Args: + config_file: Pfad zur Config-Datei + translation_lang: Sprach-Code (für die Warnmeldung) + """ + relevant_sections = {'multi', 'trigramme', 'bigramme', 'single'} + current_section = None + warnings_found = [] + + try: + with open(config_file, 'r', encoding='utf-8') as f: + for line_nr, line in enumerate(f, start=1): + # Zeilenende entfernen, führende Leerzeichen NICHT entfernen + raw_line = line.rstrip('\n\r') + stripped = raw_line.strip() + + # Abschnitts-Header erkennen + if stripped.startswith('[') and stripped.endswith(']'): + section_name = stripped[1:-1].lower() + current_section = section_name if section_name in relevant_sections else None + continue + + # Nur Zeilen innerhalb der relevanten Blöcke prüfen + if current_section is None: + continue + + # Leere Zeilen und Kommentarzeilen überspringen + if not stripped or stripped.startswith('#') or stripped.startswith(';'): + continue + + # Prüfe ob Zeile mit einem Whitespace-Zeichen beginnt (Leerzeichen, Tabulator, + # non-breaking space U+00A0 usw.) - ConfigParser behandelt alle isspace()-Zeichen + # als Fortsetzungszeichen und zieht die Zeile mit der vorherigen zusammen + if raw_line and raw_line[0].isspace(): + warnings_found.append((line_nr, current_section, raw_line)) + + except Exception as e: + print(f"WARNUNG: Fehler beim Prüfen auf führende Leerzeichen: {e}") + return + + if warnings_found: + print(f"\nWARNUNG [{translation_lang}]: {len(warnings_found)} Zeile(n) mit führendem Whitespace gefunden:") + print(f" (Leerzeichen, Tabulator, non-breaking space u.a. werden vom ConfigParser") + print(f" als Fortsetzungszeichen interpretiert und mit der vorherigen Zeile zusammengezogen!)") + for line_nr, section, line_content in warnings_found: + print(f" Zeile {line_nr:4d} [{section}]: '{line_content}'") + else: + print(f" Keine führenden Leerzeichen gefunden.") + + 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. CS.cfg, EN.cfg, FR.cfg). @@ -42,6 +217,9 @@ def load_translation_config(translation_lang: str, translation_dir: Path) -> tup print(f"FEHLER: Übersetzungs-Konfiguration nicht gefunden: {config_file}") sys.exit(1) + # Prüfe auf führende Leerzeichen vor dem Parsen (würden Zeilen zusammenziehen) + _check_leading_spaces(config_file, translation_lang) + # RawConfigParser mit case-sensitive Keys config = RawConfigParser() # Überschreibe optionxform um Groß-/Kleinschreibung zu erhalten @@ -89,12 +267,21 @@ def load_translation_config(translation_lang: str, translation_dir: Path) -> tup if translation and not translation.startswith('#'): single[original] = translation + # Prüfe Selbstübersetzungen in jedem Block und entferne sie mit Warnung + multi = _filter_self_translations('multi', multi) + trigramme = _filter_self_translations('trigramme', trigramme) + bigramme = _filter_self_translations('bigramme', bigramme) + single = _filter_self_translations('single', single) + 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)}") + # Prüfe Übersetzungsketten zwischen den Blöcken + _check_translation_chains(translation_lang, multi, trigramme, bigramme, single) + return multi, trigramme, bigramme, single