From 8d4ba650d95eac1a54dcf5077f2e1dab288a809f Mon Sep 17 00:00:00 2001 From: DrStone71 Date: Tue, 17 Jun 2025 02:22:24 +0200 Subject: [PATCH] Update __init__.py fix language Detection --- __init__.py | 136 +++++++++++++++++++++------------------------------- 1 file changed, 54 insertions(+), 82 deletions(-) diff --git a/__init__.py b/__init__.py index 84479df..74f7203 100644 --- a/__init__.py +++ b/__init__.py @@ -4,10 +4,13 @@ import traceback import os import threading from pathlib import Path +from langdetect import detect, DetectorFactory + +DetectorFactory.seed = 0 class ArgosTranslateManager: """Gestore per le operazioni di traduzione con Argos Translate""" - + # Mappa completa delle lingue supportate con i loro nomi completi LANGUAGE_MAP = { "auto": "Auto-detect", @@ -50,220 +53,189 @@ class ArgosTranslateManager: "uk": "Ukrainian (Українська)", "vi": "Vietnamese (Tiếng Việt)", } - + # Lock per thread safety durante il download _download_lock = threading.Lock() _downloading = set() - + @classmethod def get_language_list(cls): """Restituisce la lista delle lingue per il menu dropdown con nomi completi""" return [f"{code} - {name}" for code, name in cls.LANGUAGE_MAP.items()] - + @classmethod def get_language_code_from_display(cls, display_name): """Estrae il codice lingua dal nome visualizzato""" if " - " in display_name: return display_name.split(" - ")[0] return display_name - + @classmethod def get_language_display_names(cls): """Restituisce la lista dei nomi visualizzati delle lingue""" return [f"{code}: {name}" for code, name in cls.LANGUAGE_MAP.items()] - + + @classmethod + def autodetect_language(cls, text): + """ + Rileva la lingua usando langdetect, altrimenti fallback su simple_language_detect. + """ + if not text or len(text.strip()) < 3: + return "en" + try: + code = detect(text) + # 'zh-cn', 'zh-tw' ecc. → normalizza a 'zh' + if code.startswith("zh"): + code = "zh" + if code not in cls.LANGUAGE_MAP: + # Prova mapping per codici tipo 'pt', 'pt-br', 'pt-pt' + base = code.split('-')[0] + if base in cls.LANGUAGE_MAP: + code = base + else: + return "en" + return code + except Exception: + # fallback sul sistema grezzo + return cls.simple_language_detect(text) + @classmethod def simple_language_detect(cls, text): """Semplice rilevamento della lingua basato su caratteri comuni""" if not text or len(text.strip()) < 3: return "en" - text_lower = text.lower() - - # Controllo per cirillico (russo, ucraino) + # Cirillico if any(ord(char) >= 0x0400 and ord(char) <= 0x04FF for char in text): if any(word in text_lower for word in ["що", "але", "або", "який", "яка", "яке"]): - return "uk" # Ucraino - return "ru" # Russo - - # Controllo per caratteri cinesi/giapponesi/coreani + return "uk" + return "ru" if any(ord(char) >= 0x4E00 and ord(char) <= 0x9FFF for char in text): - return "zh" # Cinese - + return "zh" if any(ord(char) >= 0x3040 and ord(char) <= 0x309F for char in text): - return "ja" # Hiragana giapponese - + return "ja" if any(ord(char) >= 0xAC00 and ord(char) <= 0xD7AF for char in text): - return "ko" # Coreano - - # Controllo per arabo + return "ko" if any(ord(char) >= 0x0600 and ord(char) <= 0x06FF for char in text): return "ar" - - # Controllo per ebraico if any(ord(char) >= 0x0590 and ord(char) <= 0x05FF for char in text): return "he" - - # Controllo per greco if any(ord(char) >= 0x0370 and ord(char) <= 0x03FF for char in text): return "el" - - # Controllo per thai if any(ord(char) >= 0x0E00 and ord(char) <= 0x0E7F for char in text): return "th" - - # Controlli per lingue europee con caratteri speciali if any(char in text for char in "àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"): if any(word in text_lower for word in ["il", "la", "le", "di", "da", "in", "con", "per", "che", "non", "una", "uno"]): - return "it" # Italiano + return "it" elif any(word in text_lower for word in ["el", "la", "los", "las", "de", "del", "en", "con", "por", "que", "no", "es", "un", "una"]): - return "es" # Spagnolo + return "es" elif any(word in text_lower for word in ["le", "la", "les", "de", "du", "des", "en", "dans", "avec", "pour", "que", "ne", "un", "une"]): - return "fr" # Francese + return "fr" elif any(word in text_lower for word in ["der", "die", "das", "den", "dem", "des", "ein", "eine", "und", "oder", "nicht", "ist"]): - return "de" # Tedesco + return "de" elif any(word in text_lower for word in ["o", "a", "os", "as", "de", "do", "da", "em", "com", "por", "que", "não", "um", "uma"]): - return "pt" # Portoghese - - # Controlli per lingue nordiche + return "pt" if any(word in text_lower for word in ["och", "att", "är", "den", "det", "en", "ett", "för", "på", "av"]): - return "sv" # Svedese - + return "sv" if any(word in text_lower for word in ["og", "at", "er", "den", "det", "en", "et", "for", "på", "av"]): - return "no" # Norvegese - + return "no" if any(word in text_lower for word in ["og", "at", "er", "den", "det", "en", "et", "for", "på", "af"]): - return "da" # Danese - - # Default inglese + return "da" return "en" - + @classmethod def ensure_translation_package(cls, source_lang, target_lang): """Assicura che il pacchetto di traduzione sia installato, scaricandolo se necessario""" if source_lang == "auto": return True # Non possiamo pre-scaricare per auto-detect - if source_lang == target_lang: return True # Non serve traduzione - package_key = f"{source_lang}-{target_lang}" - - # Evita download multipli simultanei dello stesso pacchetto + with cls._download_lock: if package_key in cls._downloading: print(f"Package {package_key} is already being downloaded, waiting...") return False - try: # Controlla se il pacchetto è già installato installed_languages = argostranslate.translate.get_installed_languages() source_language = next((lang for lang in installed_languages if lang.code == source_lang), None) target_language = next((lang for lang in installed_languages if lang.code == target_lang), None) - if source_language and target_language: translation = source_language.get_translation(target_language) if translation: return True # Pacchetto già installato e funzionante - # Aggiorna l'indice dei pacchetti print(f"Updating package index...") argostranslate.package.update_package_index() - # Ottieni i pacchetti disponibili available_packages = argostranslate.package.get_available_packages() - # Trova il pacchetto per la traduzione richiesta target_package = next( - (pkg for pkg in available_packages + (pkg for pkg in available_packages if pkg.from_code == source_lang and pkg.to_code == target_lang), None ) - if target_package is None: print(f"No translation package available from '{source_lang}' to '{target_lang}'") return False - - if target_package.is_installed(): - print(f"Package {source_lang}->{target_lang} is already installed") - return True - - # Marca come in download - cls._downloading.add(package_key) - # Scarica e installa il pacchetto print(f"Downloading translation package: {source_lang} -> {target_lang}") - print(f"Package size: ~{target_package.size // 1024 // 1024}MB (this may take a while...)") - + print(f"Package size: ~{getattr(target_package, 'size', 0) // 1024 // 1024}MB (this may take a while...)") + cls._downloading.add(package_key) download_path = target_package.download() argostranslate.package.install_from_path(download_path) - print(f"Successfully installed package: {source_lang} -> {target_lang}") return True - except Exception as e: print(f"Error downloading package {source_lang}->{target_lang}: {e}") traceback.print_exc() return False finally: - # Rimuovi dalla lista dei download in corso cls._downloading.discard(package_key) - + @classmethod def translate_text(cls, text, source_lang="auto - Auto-detect", target_lang="en - English"): """Traduce il testo usando Argos Translate, scaricando i pacchetti se necessario""" if not text or not text.strip(): return text - try: # Estrai i codici lingua dai nomi visualizzati source_code = cls.get_language_code_from_display(source_lang) target_code = cls.get_language_code_from_display(target_lang) - # Auto-rilevamento se necessario if source_code == "auto": - detected_lang = cls.simple_language_detect(text) + detected_lang = cls.autodetect_language(text) print(f"Auto-detected language: {detected_lang} ({cls.LANGUAGE_MAP.get(detected_lang, 'Unknown')})") source_code = detected_lang - # Se è già nella lingua target, restituisci il testo originale if source_code == target_code: print(f"Text is already in target language ({target_code})") return text - # Assicura che il pacchetto di traduzione sia installato if not cls.ensure_translation_package(source_code, target_code): print(f"Could not ensure translation package for {source_code}->{target_code}") return text - # Ottieni le lingue installate (refresh dopo possibile download) installed_languages = argostranslate.translate.get_installed_languages() - # Trova le lingue sorgente e target source_language = next((lang for lang in installed_languages if lang.code == source_code), None) target_language = next((lang for lang in installed_languages if lang.code == target_code), None) - if source_language is None: print(f"Source language '{source_code}' not available after package check") return text - if target_language is None: print(f"Target language '{target_code}' not available after package check") return text - # Ottieni la traduzione translation = source_language.get_translation(target_language) - if translation is None: print(f"No translation model available from '{source_code}' to '{target_code}'") return text - # Esegui la traduzione translated_text = translation.translate(text) print(f"Translated ({source_code}->{target_code}): {text[:50]}{'...' if len(text) > 50 else ''}") - return translated_text - except Exception as e: print(f"Translation error: {e}") traceback.print_exc()