"""HTTP client for the translation service.""" from __future__ import annotations import logging from typing import List, Optional, Sequence, Union import requests from config.services_config import get_translation_config logger = logging.getLogger(__name__) class TranslationServiceClient: """Business-side translation client that talks to the translator service.""" def __init__( self, *, base_url: Optional[str] = None, default_model: Optional[str] = None, default_scene: Optional[str] = None, timeout_sec: Optional[float] = None, ) -> None: cfg = get_translation_config() self.base_url = (base_url or cfg.service_url).rstrip("/") self.default_model = cfg.normalize_model_name(default_model or cfg.default_model) self.default_scene = (default_scene or cfg.default_scene or "general").strip() or "general" self.timeout_sec = float(timeout_sec or cfg.timeout_sec or 10.0) @property def model(self) -> str: return self.default_model @property def supports_batch(self) -> bool: return True def translate( self, text: Union[str, Sequence[str]], target_lang: str, source_lang: Optional[str] = None, context: Optional[str] = None, prompt: Optional[str] = None, model: Optional[str] = None, scene: Optional[str] = None, ) -> Union[Optional[str], List[Optional[str]]]: if isinstance(text, tuple): text = list(text) payload = { "text": text, "target_lang": target_lang, "source_lang": source_lang or "auto", "model": (model or self.default_model), "scene": (scene or context or self.default_scene), } if prompt: payload["prompt"] = prompt try: response = requests.post( f"{self.base_url}/translate", json=payload, timeout=self.timeout_sec, ) if response.status_code != 200: logger.warning( "Translation service request failed: status=%s body=%s", response.status_code, (response.text or "")[:300], ) return self._empty_result_for(text) data = response.json() return data.get("translated_text") except Exception as exc: logger.warning("Translation service request error: %s", exc, exc_info=True) return self._empty_result_for(text) @staticmethod def _empty_result_for( text: Union[str, Sequence[str]], ) -> Union[Optional[str], List[Optional[str]]]: if isinstance(text, (list, tuple)): return [None for _ in text] return None