# JSON Translator

A smart JSON and text translation tool with LLM-powered translation and intelligent caching.

## Features

- **JSON Translation** - Translates JSON values while preserving structure and keys
- **Text Translation** - Simple text-to-text translation
- **Language Detection** - Auto-detect source language (CJK, Cyrillic, Latin scripts)
- **Smart Caching** - Two-level cache (memory + file) at text-level granularity
- **Sync/Async API** - Both synchronous and asynchronous interfaces

## Installation

The translator is included in the `sdkrouter` package:

```python
from sdkrouter import SDKRouter

client = SDKRouter(api_key="your-api-key")
translator = client.translator
```

## Quick Start

### Translate Text

```python
from sdkrouter import SDKRouter

client = SDKRouter()

# Basic translation
text = client.translator.translate(
    "Привет, мир!",
    target_language="en"
)
# "Hello, world!"

# With explicit source language
text = client.translator.translate(
    "Bonjour le monde",
    target_language="en",
    source_language="fr"
)
```

### Translate JSON

```python
data = {
    "title": "Автомобиль",
    "description": "Новый седан с турбодвигателем",
    "specs": {
        "engine": "Двигатель 2.0L",
        "power": "200 л.с."
    },
    "features": ["Климат-контроль", "Навигация"]
}

result = client.translator.translate_json(data, target_language="en")
# {
#     "title": "Car",
#     "description": "New sedan with turbocharged engine",
#     "specs": {
#         "engine": "2.0L Engine",
#         "power": "200 HP"
#     },
#     "features": ["Climate control", "Navigation"]
# }
```

**Important**: JSON keys are NEVER translated, only values.

### Async Usage

```python
from sdkrouter import AsyncSDKRouter
import asyncio

async def main():
    client = AsyncSDKRouter()

    text = await client.translator.translate("Привет!", target_language="en")
    data = await client.translator.translate_json({"msg": "Привет"}, target_language="en")

asyncio.run(main())
```

## How It Works

### Translation Flow

```
1. translate_json() called with JSON object
   ↓
2. Extract all translatable text values from JSON
   ↓
3. Check cache for each text (cache hits vs misses)
   ↓
4. Create partial JSON with ONLY uncached texts
   ↓
5. Send to LLM with strict prompt: "translate values, NOT keys"
   ↓
6. Parse LLM response and extract translations
   ↓
7. Cache ALL new translations (text-level)
   ↓
8. Apply ALL translations (cached + new) to original JSON
   ↓
9. Return fully translated JSON with preserved structure
```

### Caching Strategy

The translator uses a two-level caching system:

1. **Memory Cache** - Fast in-memory dict with LRU eviction (1000 entries max)
2. **File Cache** - Persistent JSON files organized by language pairs

Cache files are stored at `~/.sdkrouter/cache/translator/`:
```
~/.sdkrouter/cache/translator/
├── ru-en.json    # Russian → English translations
├── ko-en.json    # Korean → English translations
├── zh-en.json    # Chinese → English translations
└── ...
```

Each file contains text hashes mapped to translations:
```json
{
  "a1b2c3d4...": "Hello",
  "e5f6g7h8...": "World"
}
```

**Benefits:**
- Translates only what's not cached
- Minimizes LLM API calls and costs
- Translations persist across sessions
- Text-level caching means repeated texts are only translated once

## API Reference

### TranslatorResource

#### `translate(text, target_language, source_language, ...)`

Translate a single text string.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `text` | `str` | required | Text to translate |
| `target_language` | `str` | `"en"` | Target language code |
| `source_language` | `str` | `"auto"` | Source language (`"auto"` for detection) |
| `fail_silently` | `bool` | `False` | Return original on error |
| `model` | `str` | `None` | LLM model override |
| `temperature` | `float` | `0.1` | LLM temperature |

**Returns:** Translated text string

#### `translate_json(data, target_language, source_language, ...)`

Translate a JSON object (dict).

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `data` | `Dict[str, Any]` | required | JSON object to translate |
| `target_language` | `str` | `"en"` | Target language code |
| `source_language` | `str` | `"auto"` | Source language |
| `fail_silently` | `bool` | `False` | Return original on error |
| `model` | `str` | `None` | LLM model override |
| `temperature` | `float` | `0.1` | LLM temperature |

**Returns:** Translated JSON object with same structure

#### `detect_language(text)`

Detect the language of text using script analysis.

| Parameter | Type | Description |
|-----------|------|-------------|
| `text` | `str` | Text to analyze |

**Returns:** Language code (`"ko"`, `"ja"`, `"zh"`, `"ru"`, `"en"`, etc.)

#### `needs_translation(text, source_language, target_language)`

Check if text needs translation.

**Returns:** `True` if translation is needed

#### `get_stats()`

Get cache statistics.

**Returns:**
```python
{
    "memory_cache_size": 42,
    "cache_dir": "/Users/.../.sdkrouter/cache/translator",
    "language_pairs": [
        {"pair": "ru-en", "translations": 150, "file_size": 12345},
        {"pair": "ko-en", "translations": 80, "file_size": 8765}
    ]
}
```

#### `clear_cache(source_lang, target_lang)`

Clear translation cache.

```python
# Clear specific language pair
client.translator.clear_cache("ru", "en")

# Clear all caches
client.translator.clear_cache()
```

## Supported Languages

The translator supports detection and translation of:

| Code | Language |
|------|----------|
| `en` | English |
| `ru` | Russian |
| `ko` | Korean |
| `zh` | Chinese |
| `ja` | Japanese |
| `es` | Spanish |
| `fr` | French |
| `de` | German |
| `it` | Italian |
| `pt` | Portuguese |
| `ar` | Arabic |
| `hi` | Hindi |
| `tr` | Turkish |
| `pl` | Polish |
| `uk` | Ukrainian |

## Architecture

```
translator/
├── __init__.py       # Package exports
├── translator.py     # TranslatorResource, AsyncTranslatorResource
├── cache.py          # TranslationCacheManager
├── detectors.py      # ScriptDetector, LanguageDetector
└── utils.py          # TextUtils, PromptBuilder
```

### Components

- **TranslatorResource** - Main orchestrator, coordinates all components
- **TranslationCacheManager** - Two-level cache (memory + file)
- **ScriptDetector** - Detects language by character scripts (CJK, Cyrillic)
- **LanguageDetector** - Detects language by common word patterns
- **TextUtils** - Determines if text needs translation, filters technical content
- **PromptBuilder** - Builds optimized prompts for LLM translation

## Error Handling

```python
from sdkrouter import TranslationError

try:
    result = client.translator.translate_json(data, target_language="en")
except TranslationError as e:
    print(f"Translation failed: {e}")

# Or use fail_silently to return original on error
result = client.translator.translate_json(
    data,
    target_language="en",
    fail_silently=True  # Returns original data on error
)
```

## Best Practices

1. **Use `fail_silently=True`** in production to gracefully handle LLM failures
2. **Reuse client instances** - cache is tied to the translator instance
3. **Pre-warm cache** by translating common texts during initialization
4. **Use specific source language** when known for better accuracy
5. **Clear cache periodically** if translations become stale

## Performance Tips

- The first translation of a text incurs an LLM API call
- Subsequent translations of the same text are instant (from cache)
- Translating large JSON objects with many repeated texts is efficient
- Cache persists across application restarts
