feat: unify multimodels translation providers, remove self-hosting (Ollama/LibreTranslate), and fix local SQLite configuration
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m21s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m21s
This commit is contained in:
@@ -64,6 +64,15 @@ class PDFTranslator:
|
||||
self._provider = provider
|
||||
self._font_path: Optional[str] = None
|
||||
self._translation_stats = {"attempted": 0, "changed": 0}
|
||||
self._custom_prompt: Optional[str] = None
|
||||
|
||||
def set_provider(self, provider) -> None:
|
||||
"""Set the translation provider."""
|
||||
self._provider = provider
|
||||
|
||||
def set_custom_prompt(self, prompt: Optional[str]) -> None:
|
||||
"""Set custom system prompt for LLM providers."""
|
||||
self._custom_prompt = prompt
|
||||
|
||||
def _get_font_path(self) -> Optional[str]:
|
||||
"""Resolve a Unicode-capable TTF/OTF font file."""
|
||||
@@ -811,15 +820,56 @@ class PDFTranslator:
|
||||
# Shared helpers
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def _translate_with_provider(
|
||||
self, texts: List[str], target_language: str, source_language: str
|
||||
) -> List[str]:
|
||||
"""Translate using the TranslationProvider interface (handles old & new styles)."""
|
||||
from services.providers.base import TranslationProvider as NewTranslationProvider
|
||||
|
||||
is_new_style = False
|
||||
if isinstance(self._provider, NewTranslationProvider):
|
||||
is_new_style = True
|
||||
elif hasattr(self._provider, "__class__") and self._provider.__class__.__name__ in (
|
||||
"MockTranslationProvider",
|
||||
"Mock",
|
||||
"MagicMock",
|
||||
):
|
||||
is_new_style = True
|
||||
|
||||
if is_new_style:
|
||||
from services.providers.schemas import TranslationRequest
|
||||
custom_prompt = getattr(self, "_custom_prompt", None)
|
||||
metadata = {"custom_prompt": custom_prompt} if custom_prompt else None
|
||||
|
||||
requests = [
|
||||
TranslationRequest(
|
||||
text=t,
|
||||
target_language=target_language,
|
||||
source_language=source_language,
|
||||
metadata=metadata,
|
||||
)
|
||||
for t in texts
|
||||
]
|
||||
responses = self._provider.translate_batch(requests)
|
||||
translated = [resp.translated_text for resp in responses]
|
||||
else:
|
||||
translated = self._provider.translate_batch(texts, target_language, source_language)
|
||||
|
||||
# Fallback: keep original text for any empty/failed result
|
||||
return [
|
||||
t if (t and t.strip()) else orig
|
||||
for t, orig in zip(translated, texts)
|
||||
]
|
||||
|
||||
def _translate_single(
|
||||
self, text: str, target_language: str, source_language: str
|
||||
) -> str:
|
||||
"""Translate a single text string."""
|
||||
if self._provider is not None:
|
||||
try:
|
||||
result = self._provider.translate(text, target_language, source_language)
|
||||
if result and result.strip():
|
||||
return result
|
||||
results = self._translate_with_provider([text], target_language, source_language)
|
||||
if results and results[0].strip():
|
||||
return results[0]
|
||||
except Exception as e:
|
||||
logger.warning("provider_single_failed", error=str(e))
|
||||
|
||||
@@ -840,7 +890,7 @@ class PDFTranslator:
|
||||
translated = None
|
||||
if self._provider is not None:
|
||||
try:
|
||||
translated = self._provider.translate_batch(texts, target_language, source_language)
|
||||
translated = self._translate_with_provider(texts, target_language, source_language)
|
||||
except Exception as e:
|
||||
logger.warning("provider_translate_failed", error=str(e))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user