Major changes across backend, frontend, infrastructure: - Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud) - Admin panel: user management, pricing, settings - Glossary system with CSV import/export - Subscription and tier quota management - Security hardening (rate limiting, API key auth, path traversal fixes) - Docker compose for dev, prod, and IONOS deployment - Alembic migrations for new tables - Frontend: dashboard, pricing page, landing page, i18n (en/fr) - Test suite and verification scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Translation Providers
This directory contains translation provider implementations for the office_translator service.
Available Providers
Google Translate (google_provider.py)
Production-ready Google Translate provider with:
- Robust error handling with specific error codes
- Retry logic with exponential backoff
- Health check with result caching (60s TTL)
- Usage metrics logging
Configuration:
GOOGLE_TRANSLATE_ENABLED=true
GOOGLE_TRANSLATE_TIMEOUT=30
GOOGLE_TRANSLATE_MAX_RETRIES=3
GOOGLE_TRANSLATE_RETRY_DELAY=1
API Usage:
- Free tier: 500,000 characters/month
- 5,000 characters max per request
- Cost: ~$20 per million characters (paid tier)
Error Codes:
| Code | Description |
|---|---|
GOOGLE_QUOTA_EXCEEDED |
API quota exceeded (429) |
GOOGLE_INVALID_KEY |
Invalid API key (401/403) |
GOOGLE_NETWORK_ERROR |
Network/timeout error (502) |
GOOGLE_UNSUPPORTED_LANGUAGE |
Language not supported (400) |
GOOGLE_TEXT_TOO_LONG |
Text exceeds 5000 chars (413) |
DeepL (deepl_provider.py)
Production-ready DeepL provider with:
- Automatic Free/Pro endpoint detection based on API key format
- Robust error handling with specific error codes
- Retry logic with exponential backoff
- Health check with result caching (60s TTL)
- Language code normalization for DeepL compatibility
Configuration:
DEEPL_ENABLED=true
DEEPL_API_KEY=your_deepl_api_key_here # Free keys end with :fx
DEEPL_TIMEOUT=30
DEEPL_MAX_RETRIES=3
DEEPL_RETRY_DELAY=1
Free vs Pro API Keys:
| Type | Key Format | Endpoint |
|---|---|---|
| Free | Ends with :fx |
https://api-free.deepl.com/v2/translate |
| Pro | Does NOT end with :fx |
https://api.deepl.com/v2/translate |
API Usage:
- Free tier: 500,000 characters/month
- Pro tier: ~€25 per million characters
- 128KB max per request
- Higher quality for European languages
Supported Languages: BG, CS, DA, DE, EL, EN-GB, EN-US, ES, ET, FI, FR, HU, ID, IT, JA, KO, LT, LV, NB, NL, PL, PT-BR, PT-PT, RO, RU, SK, SL, SV, TR, UK, ZH
Language Notes:
- English has two variants: EN-GB, EN-US (defaults to EN-US)
- Portuguese has two variants: PT-BR, PT-PT (defaults to PT-BR)
- Language codes are case-sensitive (uppercase)
- Auto-detect uses
auto(like Google)
Error Codes:
| Code | HTTP | Description |
|---|---|---|
DEEPL_QUOTA_EXCEEDED |
429 | Character quota exceeded |
DEEPL_INVALID_KEY |
401 | Invalid API key |
DEEPL_NETWORK_ERROR |
502 | Network/timeout error |
DEEPL_UNSUPPORTED_LANGUAGE |
400 | Language not supported |
DEEPL_TEXT_TOO_LONG |
413 | Text exceeds 128KB |
OpenAI (openai_provider.py)
Cloud LLM translation provider with:
- GPT-4/GPT-4o/GPT-4o-mini model support
- Custom system prompt support for translation context
- Robust error handling with specific error codes
- Retry logic with exponential backoff
- Fast timeout for cloud API (default 60s)
- Health check with result caching (60s TTL)
Configuration:
OPENAI_ENABLED=true
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_MODEL=gpt-4o-mini
OPENAI_TIMEOUT=60
OPENAI_MAX_RETRIES=3
OPENAI_RETRY_DELAY=1.0
# OPENAI_BASE_URL=https://api.openai.com/v1 # Optional: for Azure OpenAI or proxies
Prerequisites:
- OpenAI API key from https://platform.openai.com/api-keys
- Valid billing method on your OpenAI account
Recommended Models for Translation:
| Model | Cost | Speed | Quality | Best For |
|---|---|---|---|---|
gpt-4o-mini |
$0.15/M tokens | Fast | Good | Default choice, cost-effective |
gpt-4o |
$2.50/M tokens | Medium | Excellent | High-quality requirements |
gpt-4 |
$30/M tokens | Slower | Excellent | Critical translations |
gpt-3.5-turbo |
$0.50/M tokens | Fastest | Good | Speed priority |
Custom System Prompt:
request = TranslationRequest(
text="Hello",
target_language="fr",
metadata={"custom_prompt": "Translate formally for business context"}
)
Rate Limiting:
- OpenAI has strict rate limits per tier
- The provider automatically handles 429 errors with retry
- Retry-After header is respected when available
- Exponential backoff for transient errors
Error Codes:
| Code | HTTP | Description |
|---|---|---|
OPENAI_RATE_LIMITED |
429 | Rate limit hit, retry suggested |
OPENAI_INVALID_KEY |
401 | Invalid API key |
OPENAI_QUOTA_EXCEEDED |
429 | Billing quota exceeded |
OPENAI_TIMEOUT |
502 | Request timeout |
OPENAI_SERVICE_ERROR |
502 | OpenAI server error |
OPENAI_CONTEXT_TOO_LONG |
413 | Text exceeds model limit |
Ollama (ollama_provider.py)
Local LLM translation provider with:
- Custom system prompt support for translation context
- Automatic model availability checking
- Robust error handling with specific error codes
- Retry logic with exponential backoff
- Longer timeout for LLM operations (default 120s)
- Health check with result caching (60s TTL)
Configuration:
OLLAMA_ENABLED=true
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama3
OLLAMA_VISION_MODEL=llava
OLLAMA_TIMEOUT=120
OLLAMA_MAX_RETRIES=2
OLLAMA_RETRY_DELAY=2
Prerequisites:
- Ollama must be installed and running:
ollama serve - Model must be pulled before use:
ollama pull llama3
Recommended Models for Translation:
| Model | Size | Best For |
|---|---|---|
llama3 |
8B | General translation, good balance |
llama3:70b |
70B | High-quality translation |
mistral |
7B | Fast translation |
qwen2 |
7B | Strong non-English support |
Custom System Prompt:
request = TranslationRequest(
text="Hello",
target_language="fr",
metadata={"custom_prompt": "Translate formally for business context"}
)
Error Codes:
| Code | HTTP | Description |
|---|---|---|
OLLAMA_UNAVAILABLE |
502 | Ollama service not reachable |
OLLAMA_MODEL_NOT_FOUND |
400 | Model not pulled |
OLLAMA_TIMEOUT |
502 | Request timeout |
OLLAMA_GENERATION_ERROR |
502 | LLM generation failed |
OLLAMA_CONTEXT_TOO_LONG |
413 | Text exceeds model limit |
Usage
from services.providers.google_provider import GoogleTranslationProvider
from services.providers.deepl_provider import DeepLTranslationProvider
from services.providers.openai_provider import OpenAITranslationProvider
from services.providers.ollama_provider import OllamaTranslationProvider
from services.providers.schemas import TranslationRequest
# Google provider
google_provider = GoogleTranslationProvider()
request = TranslationRequest(text="Hello", target_language="fr")
response = google_provider.translate_text(request)
# DeepL provider (requires API key)
deepl_provider = DeepLTranslationProvider(api_key="your-key:fx")
request = TranslationRequest(text="Hello", target_language="fr")
response = deepl_provider.translate_text(request)
# OpenAI provider (requires API key)
openai_provider = OpenAITranslationProvider(
api_key="sk-...",
model="gpt-4o-mini"
)
request = TranslationRequest(text="Hello", target_language="fr")
response = openai_provider.translate_text(request)
# OpenAI with custom prompt
request = TranslationRequest(
text="Hello",
target_language="fr",
metadata={"custom_prompt": "Translate formally for business context"}
)
response = openai_provider.translate_text(request)
# Ollama provider (requires local Ollama running)
ollama_provider = OllamaTranslationProvider(
base_url="http://localhost:11434",
model="llama3"
)
request = TranslationRequest(text="Hello", target_language="fr")
response = ollama_provider.translate_text(request)
# Ollama with custom prompt
request = TranslationRequest(
text="Hello",
target_language="fr",
metadata={"custom_prompt": "Translate formally"}
)
response = ollama_provider.translate_text(request)
if response.success:
print(response.translated_text)
else:
print(f"Error: {response.error_code} - {response.error}")
Registry Usage
from services.providers import registry
# List all providers
print(registry.list_all())
# Get first available from fallback chain
provider = registry.get_first_available(["google", "deepl", "openai", "ollama"])
# Check if provider is available
print(registry.list_available())
Health Check
status = provider.health_check()
print(f"Available: {status.available}")
print(f"Latency: {status.latency_ms}ms")
print(f"Last Check: {status.last_check}")
Architecture
All providers extend TranslationProvider base class and implement:
translate_text(request: TranslationRequest) -> TranslationResponsetranslate_batch(requests: List[TranslationRequest]) -> List[TranslationResponse]is_available() -> boolhealth_check() -> ProviderHealthStatusget_name() -> str