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

This commit is contained in:
2026-06-14 10:44:46 +02:00
parent feea02033b
commit 5fd087979b
21 changed files with 157 additions and 1942 deletions

View File

@@ -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))