Files
office_translator/services/providers/base.py
sepehr 67365918ae
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 3m36s
feat(ui,api): wave 3 — editorial pricing, real cancel, server history, DeepL purge
Pricing: full editorial redesign — serif card headers with accent pills
replace the colored font-black blocks, tone sweep across toggle/metrics/
features/CTAs, PLAN_COLORS removed; one design system app-wide.

Translate: decorative titles one step down (CTA hierarchy restored);
glossary and image-translation blocks hidden entirely for free users
(progressive disclosure — three controls for free).

Reviews: XLIFF hint line explains the exchange format; backend errors
routed through a friendly mapper (session/not-found/rate-limit/server).

Landing: fabricated hero UI cards (fake 'Context Engine' overlay)
removed — the photo no longer promises screens that don't exist.

Nav: single DashboardNavLinks component shared by sidebar and mobile
drawer (was duplicated markup).

API: GET /api/v1/translations (user job history, paginated; completed
jobs retained 24h) and POST /api/v1/translations/{id}/cancel —
cooperative cancellation with worker checkpoints before dispatch and
before finalisation, reserved quota released immediately. Translate
monitor now offers a real 'Cancel translation' next to 'Back to start';
recent-jobs list reads server history first, localStorage fallback.

DeepL purge (backend): provider module, registry registration, config
attrs/defaults, dispatch branch, admin settings schema + test branch,
legacy availability block, validation rules, plan provider lists,
error-code mappings, MCP enums, translator prompt mention, related
tests updated/removed. Fallback resolver skips unknown providers, so
stale chains containing 'deepl' degrade gracefully.

Verified: backend 110 tests passed; frontend build exit 0, vitest 9/9,
0 missing i18n keys, eslint 63 errors (vs 64 at HEAD).
2026-08-30 22:42:29 +02:00

123 lines
3.5 KiB
Python

"""
Abstract base class for translation providers.
Provides a common interface for all translation provider implementations.
"""
from abc import ABC, abstractmethod
from typing import Optional, List
import time
from .schemas import (
TranslationRequest,
TranslationResponse,
BatchTranslationRequest,
BatchTranslationResponse,
ProviderHealthStatus,
)
class TranslationProvider(ABC):
"""
Abstract base class for translation providers.
All translation providers must implement this interface to ensure
consistent behavior across different translation services.
"""
@abstractmethod
def translate_text(self, request: TranslationRequest) -> TranslationResponse:
"""
Translate a single text string.
Args:
request: TranslationRequest containing text, target_language, and source_language
Returns:
TranslationResponse with translated text and metadata
"""
pass
@abstractmethod
def get_name(self) -> str:
"""
Return the provider name for logging and registry.
Returns:
Provider name as a string (e.g., "google", "openai")
"""
pass
@abstractmethod
def is_available(self) -> bool:
"""
Check if the provider is configured and reachable.
Returns:
True if the provider can perform translations, False otherwise
"""
pass
def translate_batch(
self, requests: List[TranslationRequest]
) -> List[TranslationResponse]:
"""
Translate multiple texts. Default implementation uses individual calls.
Subclasses can override this for optimized batch processing.
Args:
requests: List of TranslationRequest objects
Returns:
List of TranslationResponse objects in the same order as requests
"""
return [self.translate_text(req) for req in requests]
def translate(
self, text: str, target_language: str, source_language: str = "auto"
) -> str:
"""
Compatibility method for the legacy interface.
Translates a single text string synchronously.
"""
req = TranslationRequest(
text=text,
target_language=target_language,
source_language=source_language,
)
resp = self.translate_text(req)
if resp.error:
raise Exception(f"[{resp.error_code or 'UNKNOWN'}] {resp.error}")
return resp.translated_text
def health_check(self) -> ProviderHealthStatus:
"""
Return health status details for the provider.
Performs a lightweight check to verify the provider is operational.
Returns:
ProviderHealthStatus with availability and latency information
"""
start_time = time.time()
try:
available = self.is_available()
latency_ms = (time.time() - start_time) * 1000
return ProviderHealthStatus(
name=self.get_name(),
available=available,
latency_ms=round(latency_ms, 2),
error=None if available else "Provider not available",
)
except Exception as e:
latency_ms = (time.time() - start_time) * 1000
return ProviderHealthStatus(
name=self.get_name(),
available=False,
latency_ms=round(latency_ms, 2),
error=str(e),
)