Spaces:
Sleeping
Sleeping
File size: 6,071 Bytes
93f4eb2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | from googletrans import Translator, LANGUAGES
import asyncio
from typing import List, Dict, Optional, Tuple
import logging
logger = logging.getLogger(__name__)
class TranslationService:
def __init__(self):
self.translator = Translator()
self.languages = LANGUAGES
# Кэш для обратного поиска языков
self._name_to_code_cache = None
def _build_name_cache(self):
"""Построить кэш для поиска кода языка по названию"""
if self._name_to_code_cache is None:
self._name_to_code_cache = {}
for code, name in self.languages.items():
self._name_to_code_cache[name.lower()] = code
# Добавляем русские названия
russian_names = {
'russian': 'ru', 'английский': 'en', 'немецкий': 'de',
'французский': 'fr', 'испанский': 'es', 'итальянский': 'it',
'португальский': 'pt', 'китайский': 'zh-cn', 'японский': 'ja',
'корейский': 'ko', 'арабский': 'ar', 'турецкий': 'tr'
}
self._name_to_code_cache.update(russian_names)
return self._name_to_code_cache
def get_language_code(self, lang: str) -> str:
"""Получить код языка из названия или кода"""
if not lang or lang == 'auto':
return 'auto'
# Если это уже код языка
if lang in self.languages:
return lang
# Ищем по названию
name_cache = self._build_name_cache()
return name_cache.get(lang.lower(), 'auto')
def get_language_name(self, code: str) -> str:
"""Получить название языка по коду"""
return self.languages.get(code, code)
async def translate(self, text: str, dest: str = 'ru', src: str = 'auto') -> Dict:
"""Асинхронный перевод текста"""
try:
# Получаем коды языков
dest_code = self.get_language_code(dest)
src_code = self.get_language_code(src) if src != 'auto' else 'auto'
# Выполняем перевод в отдельном потоке, так как googletrans не асинхронный
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(
None,
lambda: self.translator.translate(text, src=src_code, dest=dest_code)
)
# Получаем альтернативные переводы (если есть)
alternatives = []
if hasattr(result, 'extra_data') and result.extra_data:
possible_translations = result.extra_data.get('possible-translations', [])
if possible_translations and len(possible_translations) > 0:
for translation_group in possible_translations[:3]:
if translation_group and len(translation_group) > 0:
for translation_item in translation_group[:2]:
if isinstance(translation_item, list) and len(translation_item) > 1:
alternatives.append(translation_item[1])
return {
'original_text': result.origin,
'translated_text': result.text,
'source_lang': result.src,
'target_lang': dest_code,
'source_lang_name': self.get_language_name(result.src),
'target_lang_name': self.get_language_name(dest_code),
'pronunciation': result.pronunciation,
'alternatives': alternatives[:5] if alternatives else None
}
except Exception as e:
logger.error(f"Translation error: {str(e)}")
raise Exception(f"Ошибка перевода: {str(e)}")
async def translate_batch(self, texts: List[str], dest: str = 'ru', src: str = 'auto') -> List[Dict]:
"""Пакетный перевод текстов"""
tasks = [self.translate(text, dest, src) for text in texts]
results = await asyncio.gather(*tasks, return_exceptions=True)
translations = []
for result in results:
if isinstance(result, Exception):
translations.append({
'error': str(result),
'original_text': '',
'translated_text': ''
})
else:
translations.append(result)
return translations
async def detect_language(self, text: str) -> Dict:
"""Определение языка текста"""
try:
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(
None,
lambda: self.translator.detect(text)
)
return {
'lang': result.lang,
'lang_name': self.get_language_name(result.lang),
'confidence': result.confidence
}
except Exception as e:
logger.error(f"Language detection error: {str(e)}")
raise Exception(f"Ошибка определения языка: {str(e)}")
def get_supported_languages(self) -> List[Dict]:
"""Получить список поддерживаемых языков"""
languages = []
for code, name in sorted(self.languages.items()):
languages.append({
'code': code,
'name': name,
'native_name': name # Можно добавить маппинг на родные названия
})
return languages |