Metadata-Version: 2.4
Name: mobile-ai-translator
Version: 1.1.0
Summary: AI-powered translation for Flutter, Android & iOS — one command, all platforms
Author-email: Happy Cyber <dhamasaniyahappy3931@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/Happy-cyber/mobile-ai-translator
Project-URL: Repository, https://github.com/Happy-cyber/mobile-ai-translator
Project-URL: Issues, https://github.com/Happy-cyber/mobile-ai-translator/issues
Project-URL: Author, https://github.com/Happy-cyber
Keywords: flutter,android,ios,mobile,translation,i18n,l10n,localization,ai,claude,openai,gemini,mistral,arb,strings-xml,xcstrings
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Internationalization
Classifier: Topic :: Software Development :: Localization
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Requires-Dist: python-dotenv>=1.0
Requires-Dist: rich>=13.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: claude
Requires-Dist: anthropic>=0.30; extra == "claude"
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: openrouter
Requires-Dist: openai>=1.0; extra == "openrouter"
Provides-Extra: gemini
Requires-Dist: google-generativeai>=0.5; extra == "gemini"
Provides-Extra: mistral
Requires-Dist: mistralai>=1.0; extra == "mistral"
Provides-Extra: all
Requires-Dist: anthropic>=0.30; extra == "all"
Requires-Dist: openai>=1.0; extra == "all"
Requires-Dist: google-generativeai>=0.5; extra == "all"
Requires-Dist: mistralai>=1.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Dynamic: license-file

# mobile-ai-translator

**AI-powered translation for Flutter, Android & iOS — one command, all platforms.**

[![PyPI](https://img.shields.io/pypi/v/mobile-ai-translator)](https://pypi.org/project/mobile-ai-translator/)
[![Python](https://img.shields.io/pypi/pyversions/mobile-ai-translator)](https://pypi.org/project/mobile-ai-translator/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Tests](https://img.shields.io/badge/tests-176%20passed-brightgreen)]()

```
  ╔╦╗ ╔═╗ ╔╗  ╦ ╦  ╔═╗        ╔═╗ ╦
  ║║║ ║ ║ ╠╩╗ ║ ║  ║╣  ────── ╠═╣ ║
  ╩ ╩ ╚═╝ ╚═╝ ╩ ╩═╝╚═╝        ╩ ╩ ╩
  ╔╦╗ ╦═╗ ╔═╗ ╔╗╔ ╔═╗ ╦  ╔═╗ ╔╦╗ ╔═╗ ╦═╗
   ║  ╠╦╝ ╠═╣ ║║║ ╚═╗ ║  ╠═╣  ║  ║ ║ ╠╦╝
   ╩  ╩╚═ ╩ ╩ ╝╚╝ ╚═╝ ╩═╝╩ ╩  ╩  ╚═╝ ╩╚═
```

Stop hand-translating your mobile app. `mobile-ai-translate` reads your existing localization files, finds every missing translation, and fills them in using the AI provider of your choice. It works with Flutter `.arb` files, Android `strings.xml`, and iOS `.strings` / `.xcstrings` — all from a single command.

---

## Table of Contents

- [Why This Tool](#why-this-tool)
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [CLI Reference](#cli-reference)
- [Supported Platforms](#supported-platforms)
- [AI Providers](#ai-providers)
- [Configuration](#configuration)
- [Safety Guarantees](#safety-guarantees)
- [Best Practices](#best-practices)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)

---

## Why This Tool

| Problem | Solution |
|---------|----------|
| You added 50 new strings and need them in 8 languages | Run one command. Done in seconds. |
| Translators are expensive for early-stage apps | Use any AI provider — Claude, GPT, Gemini, Mistral, or 100+ models via OpenRouter |
| You're afraid automation will corrupt your files | Only **missing** keys are added. Existing translations are never touched. Placeholders are preserved exactly. |
| Your CI pipeline needs non-interactive translation | `--no-input --provider claude` runs headless with zero prompts |
| You don't know which localization format your project uses | The tool auto-detects Flutter, Android, or iOS from your project files |

---

## Features

- **Auto-detection** — Detects Flutter (`pubspec.yaml`), Android (`build.gradle`), or iOS (`.xcodeproj`) automatically
- **5 AI providers** — Claude, OpenAI, Gemini, Mistral, and OpenRouter (access to 100+ models including DeepSeek, Llama, Qwen)
- **Flutter** — `.arb` files with full ICU `{placeholder}` and plural/select syntax support
- **Android** — `strings.xml` with `<string>`, `<string-array>`, `<plurals>`, and `translatable="false"` handling
- **iOS** — Both classic `.strings` files in `*.lproj/` and modern `.xcstrings` (Xcode 15+)
- **Safe writes** — Only missing translations are added; existing values are never overwritten
- **Dry-run mode** — Preview what would be translated before writing a single file
- **Batch translation** — Sends strings in configurable batches with automatic retry on failure
- **Premium CLI** — Rich-powered boot animation, interactive menus, progress bars, and summary reports
- **CI/CD ready** — `--no-input` mode for fully automated pipelines

---

## Installation

**Requirements:** Python 3.10 or higher

### Basic install

```bash
pip install mobile-ai-translator
```

### With a specific AI provider

```bash
pip install "mobile-ai-translator[claude]"      # Anthropic Claude
pip install "mobile-ai-translator[openai]"      # OpenAI GPT-4o
pip install "mobile-ai-translator[gemini]"      # Google Gemini
pip install "mobile-ai-translator[mistral]"     # Mistral AI
pip install "mobile-ai-translator[openrouter]"  # OpenRouter (100+ models)
pip install "mobile-ai-translator[all]"         # Every provider
```

### For development

```bash
git clone https://github.com/Happy-cyber/mobile-ai-translator.git
cd mobile-ai-translator
pip install -e ".[dev]"
```

---

## Quick Start

### 1. Navigate to your mobile project

```bash
cd ~/projects/my-flutter-app
```

### 2. Run the command

```bash
mobile-ai-translate
```

### 3. Follow the interactive prompts

The tool will:

1. **Detect your platform** — Flutter, Android, or iOS (auto-detected from project files)
2. **Show API key status** — Which provider keys are configured in your `.env`
3. **Scan source strings** — Read your English localization file
4. **Detect target languages** — Found from existing locale files (e.g., `app_es.arb`, `values-fr/`, `es.lproj/`)
5. **Count missing translations** — Only strings that haven't been translated yet
6. **Let you pick an AI provider** — Interactive menu with all 5 options
7. **Verify your API key** — Checks the key works before translating
8. **Translate in batches** — With a real-time progress bar
9. **Write the files** — Missing translations added to each language file
10. **Show a summary report** — How many strings were translated, how long it took

### First-time example output

```
$ cd ~/projects/my-flutter-app
$ mobile-ai-translate

  ╔╦╗ ╔═╗ ╔╗  ╦ ╦  ╔═╗        ╔═╗ ╦
  ...
  ● System Boot Complete
  ● Translation Engine Online

─── STEP 1 ┃ PLATFORM DETECTION ───
  🦋 Platform Auto-Detected: FLUTTER
  Project:       /home/user/projects/my-flutter-app
  Source locale:  en
  Languages:      3 target language(s)

─── STEP 2 ┃ SCANNING SOURCE STRINGS ───
  ● Found 42 source strings
  ● Languages:  Spanish(es)  French(fr)  Japanese(ja)

─── STEP 3 ┃ DETECTING MISSING TRANSLATIONS ───
  ● Missing translations: 87

─── STEP 4 ┃ SELECT TRANSLATION ENGINE ───
  [1]  ⚡  Claude (Anthropic)  · Recommended
  [2]  🧠  OpenAI GPT          · Powerful
  [3]  🔥  OpenRouter           · 100+ Models
  [4]  ✦   Google Gemini        · Ultra Fast
  [5]  🇪🇺  Mistral AI           · EU Languages
  [6]  ⏭   Skip Translation     · No AI
  → Enter your choice: 1

─── STEP 5 ┃ API KEY VERIFICATION ───
  ⚠ ANTHROPIC_API_KEY not found in .env
  → Enter your Claude API key: sk-ant-...
  ● Claude (Anthropic) API key verified!

─── STEP 6 ┃ TRANSLATING ───
  Translating... ━━━━━━━━━━━━━━━━━━━━ 100% • 12.4s

─── STEP 7 ┃ WRITING TRANSLATIONS ───
  ● Updated: es  →  42 entries
  ● Updated: fr  →  42 entries
  ● Updated: ja  →  42 entries

─── TRANSLATION REPORT ───
  Platform                Flutter
  Source strings          42
  Missing translations    87
  Successfully translated 42
  Languages processed     3
  Execution time          12.4s

  ✅  MISSION COMPLETE
  Your app now speaks 3 languages.
  126 translation entries generated.
```

---

## CLI Reference

```
mobile-ai-translate [OPTIONS]
```

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--platform` | `flutter` `android` `ios` | auto-detect | Force a specific platform instead of auto-detection |
| `--provider` | `claude` `openai` `openrouter` `gemini` `mistral` `skip` | interactive | AI provider to use (skips the menu) |
| `--model` | string | `anthropic/claude-sonnet-4` | Model ID for OpenRouter |
| `--dry-run` | flag | off | Show what would be translated without writing files |
| `--no-input` | flag | off | Non-interactive mode for CI/CD (skips all prompts) |
| `--batch-size` | int | `10` | Number of strings sent per API request (minimum: 1) |
| `--debug` | flag | off | Enable verbose logging to diagnose issues |
| `--project-dir` | path | `.` | Path to the project root (if not the current directory) |
| `--version` | flag | — | Print version and exit |
| `--help` | flag | — | Print help and exit |

### Examples

```bash
# Translate a Flutter project using Claude, non-interactively
mobile-ai-translate --platform flutter --provider claude --no-input

# Preview what would be translated (no files written)
mobile-ai-translate --dry-run

# Use a specific OpenRouter model
mobile-ai-translate --provider openrouter --model deepseek/deepseek-chat-v3-0324

# Translate a project in another directory
mobile-ai-translate --project-dir ~/projects/my-android-app

# CI/CD pipeline with smaller batches for rate-limited APIs
mobile-ai-translate --provider openai --no-input --batch-size 5

# Debug a failing translation
mobile-ai-translate --debug 2>&1 | tee translate.log
```

For the full CLI guide with real-world scenarios, see [docs/usage.md](docs/usage.md).

---

## Supported Platforms

### Flutter (.arb)

**Auto-detected by:** `pubspec.yaml` at project root

**Source file:** Defined in `l10n.yaml`, defaults to `lib/l10n/app_en.arb`

```yaml
# l10n.yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
```

```json
{
  "@@locale": "en",
  "appTitle": "My App",
  "@appTitle": { "description": "The title of the application" },
  "welcomeMessage": "Welcome, {username}!",
  "@welcomeMessage": {
    "placeholders": { "username": { "type": "String" } }
  },
  "itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}"
}
```

**What gets preserved:**
- `{placeholder}` variables (e.g., `{username}`, `{count}`)
- ICU plural/select syntax (e.g., `{count, plural, =0{...} other{...}}`)
- `@@locale` and `@key` metadata entries (never translated)

**Target languages:** Detected from existing `app_{lang}.arb` files in the arb directory.

### Android (strings.xml)

**Auto-detected by:** `app/build.gradle` or `app/build.gradle.kts`

**Source file:** `app/src/main/res/values/strings.xml`

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">My App</string>
    <string name="welcome_message">Welcome, %1$s!</string>
    <string name="item_count">%d items</string>
    <string name="debug_label" translatable="false">DEBUG</string>
    <string-array name="colors">
        <item>Red</item>
        <item>Blue</item>
    </string-array>
    <plurals name="items">
        <item quantity="one">%d item</item>
        <item quantity="other">%d items</item>
    </plurals>
</resources>
```

**What gets preserved:**
- Format specifiers: `%1$s`, `%d`, `%2$s`
- `translatable="false"` strings are skipped entirely
- `<string-array>` items are translated individually
- `<plurals>` quantity items are translated individually
- XML entities: `&amp;`, `&lt;`, `&gt;`

**Target languages:** Detected from existing `values-{lang}/` directories (e.g., `values-es/`, `values-fr/`). New directories are created automatically.

### iOS (.strings / .xcstrings)

**Auto-detected by:** `.xcodeproj` or `.xcworkspace` at project root

#### Classic .strings format

**Source file:** `en.lproj/Localizable.strings` or `Base.lproj/Localizable.strings`

```
/* App title */
"app_title" = "My App";

/* Greeting with name parameter */
"welcome_message" = "Welcome, %@!";

/* Item count */
"item_count" = "%d items";
```

**Target languages:** Detected from existing `*.lproj/` directories. New `.lproj/Localizable.strings` files are created automatically.

#### Modern .xcstrings format (Xcode 15+)

**Source file:** `Localizable.xcstrings` (single JSON file)

```json
{
  "sourceLanguage": "en",
  "strings": {
    "app_title": {
      "localizations": {
        "en": { "stringUnit": { "state": "translated", "value": "My App" } }
      }
    }
  }
}
```

**What gets preserved (both formats):**
- Format specifiers: `%@`, `%d`, `%ld`, `%1$@`
- Escape sequences: `\n`, `\"`
- For `.xcstrings`, translated entries get `"state": "translated"`

**Target languages:** For `.xcstrings`, detected from existing language entries across all strings. For `.strings`, detected from `*.lproj/` directories.

---

## AI Providers

| Provider | Env Variable | Install Command | Translation Model | Validation Model |
|----------|-------------|-----------------|-------------------|------------------|
| Claude (Anthropic) | `ANTHROPIC_API_KEY` | `pip install "mobile-ai-translator[claude]"` | claude-sonnet-4 | claude-sonnet-4 |
| OpenAI GPT | `OPENAI_API_KEY` | `pip install "mobile-ai-translator[openai]"` | gpt-4o | gpt-4o-mini |
| Google Gemini | `GOOGLE_GEMINI_KEY` | `pip install "mobile-ai-translator[gemini]"` | gemini-2.0-flash | gemini-2.0-flash |
| Mistral AI | `MISTRAL_API_KEY` | `pip install "mobile-ai-translator[mistral]"` | mistral-large-latest | mistral-large-latest |
| OpenRouter | `OPENROUTER_API_KEY` | `pip install "mobile-ai-translator[openrouter]"` | Your choice (10+ options) | Same model |

### Setting up API keys

**Option A: `.env` file (recommended)**

Create a `.env` file in your project root:

```env
# Pick one (or more)
ANTHROPIC_API_KEY=sk-ant-your-key-here
OPENAI_API_KEY=sk-your-key-here
OPENROUTER_API_KEY=sk-or-your-key-here
GOOGLE_GEMINI_KEY=your-key-here
MISTRAL_API_KEY=your-key-here
```

**Option B: Environment variables**

```bash
export ANTHROPIC_API_KEY=sk-ant-your-key-here
mobile-ai-translate --provider claude
```

**Option C: Interactive prompt**

If no key is found, the tool will ask for it and save it to `.env` automatically.

For detailed provider setup including how to get each API key, see [docs/providers.md](docs/providers.md).

---

## Configuration

### Auto-detection

The tool detects your platform by checking for these files at the project root:

| Check | Result |
|-------|--------|
| `pubspec.yaml` exists | Flutter |
| `app/build.gradle` or `app/build.gradle.kts` exists | Android |
| Any `.xcodeproj` or `.xcworkspace` directory exists | iOS |

Detection priority: **Flutter > Android > iOS** (so a Flutter project that also has `app/build.gradle` is correctly identified as Flutter).

### Manual overrides

```bash
# Force platform detection
mobile-ai-translate --platform android

# Point to a different project directory
mobile-ai-translate --project-dir /path/to/project
```

### Target languages

If no target language files exist yet (first-time setup), the tool prompts you to enter language codes:

```
→ Enter language codes: es,fr,de,ja,ko
```

Common codes: `es` (Spanish), `fr` (French), `de` (German), `it` (Italian), `pt` (Portuguese), `ja` (Japanese), `ko` (Korean), `zh` (Chinese), `ar` (Arabic), `hi` (Hindi), `ru` (Russian), `tr` (Turkish), `nl` (Dutch), `pl` (Polish), `sv` (Swedish), `da` (Danish), `no` (Norwegian), `fi` (Finnish), `th` (Thai), `vi` (Vietnamese)

---

## Safety Guarantees

This tool is designed to be safe to run repeatedly on any project:

1. **Existing translations are never overwritten.** If a key already has a value in a target file, it is left untouched.
2. **Source files are never modified.** Only target language files are written to.
3. **Placeholders are preserved exactly.** The AI prompt includes platform-specific rules that instruct the model to keep `{username}`, `%1$s`, `%@`, and all other format specifiers intact.
4. **Metadata is preserved.** Flutter `@@locale` and `@key` entries, Android `translatable="false"` strings, and `.xcstrings` `state` fields are all handled correctly.
5. **Dry-run mode lets you preview.** Use `--dry-run` to see exactly what would be translated before any file is modified.
6. **Atomic file writes.** All files are written via temp file + rename — a crash or power loss mid-write can never corrupt your existing localization files.
7. **Broken file recovery.** If a target file contains invalid JSON/XML, the tool logs a warning and continues instead of crashing. Run it again after fixing the file.
8. **Partial failure resilience.** If some AI batches fail (timeout, rate limit), the tool writes whatever succeeded and tells you how many batches to retry.

---

## Best Practices

### CI/CD integration

```bash
# In your GitHub Actions / GitLab CI pipeline:
pip install "mobile-ai-translator[claude]"
mobile-ai-translate --provider claude --no-input --batch-size 5
```

The `--no-input` flag ensures the tool never waits for interactive input. If API keys or target languages are missing, it exits with a non-zero code instead of hanging.

### Large projects (500+ strings)

- Use `--batch-size 5` for rate-limited APIs (especially free tiers)
- Use `--batch-size 20` for high-throughput APIs (Claude, GPT-4o)
- The default of `10` works well for most projects

### Running after adding new strings

The tool is designed for incremental use. When you add new strings to your source file and run the command again, it only translates the **new** strings — existing translations are not re-sent to the API.

### Multiple AI providers

You can run the tool multiple times with different providers. Since existing translations are never overwritten, switching providers is safe.

---

## Troubleshooting

| Problem | Solution |
|---------|----------|
| `Could not auto-detect mobile platform` | Use `--platform flutter` or check that you're in the right directory |
| `No source strings found` | Verify your localization file exists (e.g., `lib/l10n/app_en.arb` for Flutter) |
| `ANTHROPIC_API_KEY not set` in `--no-input` mode | Set the key in `.env` or as an environment variable before running |
| `AUTHENTICATION FAILURE` | Your API key is invalid or expired — regenerate it from the provider's dashboard |
| Translations look wrong | Try a different provider or model; Claude and GPT-4o generally produce the best results |
| Some translations are missing after a run | The AI may have failed on some batches — run the command again to fill gaps |
| `--batch-size must be at least 1` | Batch size must be a positive integer |

For the full troubleshooting guide with debug mode instructions, see [docs/troubleshooting.md](docs/troubleshooting.md).

---

## Contributing

### Running locally

```bash
git clone https://github.com/Happy-cyber/mobile-ai-translator.git
cd mobile-ai-translator
pip install -e ".[dev]"
pytest
```

### Running the full test suite

```bash
# Unit + integration + hardening tests (100 tests)
pytest tests/unit/ tests/integration/ -v

# Production QA validation suite (76 tests)
pytest tests/qa_production_validation.py -v

# All tests (157+ unit/integration + QA)
pytest tests/ tests/qa_production_validation.py -v
```

### Adding a new AI provider

1. Create `mobile_ai_translator/services/translators/your_provider.py`
2. Extend `BaseTranslator` with `validate_key()` and `_call_api()` methods
3. Register it in `translators/__init__.py` (add to `TRANSLATOR_MAP`, `PROVIDER_ENV_KEYS`, `ALL_ENV_KEYS`)
4. Add the provider to the `PROVIDER_MENU` list in `cli/ui.py`
5. Add the provider choice to the `--provider` argument in `cli/main.py`
6. Add tests in `tests/unit/test_translators.py`

### Code standards

- Python 3.10+ type hints
- Format with `ruff`
- All tests must pass before submitting a PR

---

## Project Structure

```
mobile-ai-translator/
├── mobile_ai_translator/
│   ├── __init__.py                  # Version: 1.1.0
│   ├── cli/
│   │   ├── ui.py                    # Rich-powered terminal UI
│   │   └── main.py                  # CLI entry point (argparse)
│   ├── platforms/
│   │   ├── __init__.py              # Platform detection + registry
│   │   ├── flutter.py               # ARB parser + scanner
│   │   ├── android.py               # strings.xml parser + scanner
│   │   └── ios.py                   # .strings / .xcstrings parser
│   └── services/
│       ├── env_manager.py           # .env file detection + API key management
│       └── translators/
│           ├── __init__.py          # Provider registry + factory
│           ├── base.py              # Base class + retry logic + prompt builder
│           ├── claude.py            # Anthropic Claude
│           ├── openai.py            # OpenAI GPT
│           ├── gemini.py            # Google Gemini
│           ├── mistral.py           # Mistral AI
│           └── openrouter.py        # OpenRouter (100+ models)
├── tests/                           # 157+ tests
├── docs/                            # Extended documentation
├── pyproject.toml
├── LICENSE                          # MIT
└── README.md
```

For a detailed architecture walkthrough, see [docs/architecture.md](docs/architecture.md).

---

## License

MIT License — see [LICENSE](LICENSE) for details.

## Author

**Happy-Cyber** — [GitHub](https://github.com/Happy-cyber)

Built with love. If this tool saved you time, consider giving it a star on GitHub.
