Spaces:
Sleeping
Sleeping
| 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 |