Update __init__.py
fix language Detection
This commit is contained in:
+54
-82
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user