# 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:**
```bash
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:**
```bash
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:**
```bash
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:**
```python
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:**
```bash
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:**
```python
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

```python
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

```python
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

```python
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) -> TranslationResponse`
- `translate_batch(requests: List[TranslationRequest]) -> List[TranslationResponse]`
- `is_available() -> bool`
- `health_check() -> ProviderHealthStatus`
- `get_name() -> str`
