{"id":48554592,"url":"https://github.com/happy-cyber/ai-translate","last_synced_at":"2026-04-14T16:00:32.793Z","repository":{"id":349949799,"uuid":"1204707495","full_name":"Happy-cyber/ai-translate","owner":"Happy-cyber","description":"Zero-config AI localization. One command translates Django, Flask, FastAPI, Flutter, Android, iOS apps using AI.","archived":false,"fork":false,"pushed_at":"2026-04-08T09:05:28.000Z","size":106,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-12T14:27:35.995Z","etag":null,"topics":["ai","android","arb","automation","cli","developer-tools","django","fastapi","flask","flutter","gemini","gettext","i18n","ios","l10n","localization","openai","python","translation"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/ai-translate/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Happy-cyber.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-08T08:55:21.000Z","updated_at":"2026-04-09T14:52:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Happy-cyber/ai-translate","commit_stats":null,"previous_names":["happy-cyber/ai-translate"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/Happy-cyber/ai-translate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Happy-cyber%2Fai-translate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Happy-cyber%2Fai-translate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Happy-cyber%2Fai-translate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Happy-cyber%2Fai-translate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Happy-cyber","download_url":"https://codeload.github.com/Happy-cyber/ai-translate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Happy-cyber%2Fai-translate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31757482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T13:27:56.013Z","status":"ssl_error","status_checked_at":"2026-04-13T13:21:23.512Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","android","arb","automation","cli","developer-tools","django","fastapi","flask","flutter","gemini","gettext","i18n","ios","l10n","localization","openai","python","translation"],"created_at":"2026-04-08T10:02:10.497Z","updated_at":"2026-04-13T15:00:43.520Z","avatar_url":"https://github.com/Happy-cyber.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ai-translate\n\n**Zero-config AI localization for developers. One command. Every platform.**\n\n[![PyPI version](https://img.shields.io/pypi/v/ai-translate)](https://pypi.org/project/ai-translate/)\n[![Downloads](https://static.pepy.tech/badge/ai-translate)](https://pepy.tech/projects/ai-translate)\n[![Python](https://img.shields.io/pypi/pyversions/ai-translate)](https://pypi.org/project/ai-translate/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n```bash\npip install -U ai-translate\ncd your-project/\nai-translate\n```\n\nThat's it. Your app speaks 10 languages. No accounts. No dashboards. No config files.\n\n---\n\n## What It Does\n\n`ai-translate` scans your project, finds translatable strings, detects missing translations, translates them using AI, and writes the results directly to your locale files.\n\n**One command. Zero setup. Works across 6 platforms.**\n\n## Supported Platforms\n\n| Platform | Detection | Source Format | Plural Support |\n|----------|-----------|---------------|----------------|\n| **Django** | `manage.py` | `.po` files | `ngettext()` with `msgid_plural` |\n| **Flask** | `app.py` with Flask import | `.po` files (Babel) | `ngettext()` with `msgid_plural` |\n| **FastAPI** | `main.py` with FastAPI import | `.po` files (Babel) | `ngettext()` with `msgid_plural` |\n| **Flutter** | `pubspec.yaml` | `.arb` files | ICU MessageFormat |\n| **Android** | `app/build.gradle` | `strings.xml` | `\u003cplurals\u003e` XML elements |\n| **iOS** | `*.xcodeproj` | `.xcstrings` / `.strings` | `.xcstrings` variations |\n\nThe platform is detected automatically from your project structure. You never specify it.\n\n## Supported AI Providers\n\n| Provider | Env Variable | Model | Quality |\n|----------|-------------|-------|---------|\n| **Claude** (Anthropic) | `ANTHROPIC_API_KEY` | claude-sonnet-4 | Excellent |\n| **OpenAI** | `OPENAI_API_KEY` | gpt-4o | High |\n| **Google Gemini** | `GOOGLE_GEMINI_KEY` | gemini-2.5-flash | High |\n| **OpenRouter** | `OPENROUTER_API_KEY` | 100+ models | Varies |\n| **Mistral** | `MISTRAL_API_KEY` | mistral-large | High |\n\nThe provider is auto-detected from your environment variables. If no key is found, the tool guides you through setup interactively.\n\n## Installation\n\n```bash\n# Core tool\npip install -U ai-translate\n\n# With a specific provider\npip install \"ai-translate[claude]\"\npip install \"ai-translate[openai]\"\npip install \"ai-translate[gemini]\"\n\n# With all providers\npip install \"ai-translate[all]\"\n```\n\n**Requirements:** Python 3.10+\n\n## Quick Start\n\n### 1. Install\n\n```bash\npip install -U ai-translate\n```\n\n### 2. Set an API key (any ONE of these)\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...     # Claude (recommended)\nexport OPENAI_API_KEY=sk-...             # OpenAI\nexport GOOGLE_GEMINI_KEY=...             # Gemini (cheapest)\n```\n\nOr skip this step entirely — the tool will ask you interactively:\n\n```\n⚠ No API key detected. Let's set one up!\n\n┌─────────────────────────────────────────────────┐\n│         SELECT TRANSLATION ENGINE                │\n├─────────────────────────────────────────────────┤\n│  [1]  ⚡  Claude (Anthropic)  · Recommended     │\n│  [2]  🧠  OpenAI GPT          · Powerful         │\n│  [3]  🔥  OpenRouter           · 100+ Models     │\n│  [4]  ✦   Google Gemini        · Ultra Fast      │\n│  [5]  🇪🇺  Mistral AI          · EU Languages    │\n└─────────────────────────────────────────────────┘\n\n→ Enter your choice: 1\n\n🔑 Claude (Anthropic) API Key Required\n\n  Get your key at:\n  https://console.anthropic.com/settings/keys\n\n→ Enter your Claude API key: sk-ant-...\n\n● API key saved to .env\n```\n\n### 3. Run\n\n```bash\ncd your-project/\nai-translate\n```\n\nDone. Your locale files are updated.\n\n## How It Works\n\n```\nai-translate\n     │\n     ├── Step 1: Detect platform (Django/Flask/FastAPI/Flutter/Android/iOS)\n     ├── Step 2: Load environment + API key\n     ├── Step 3: Scan source code for translatable strings\n     ├── Step 4: Detect target languages (config first, then locale files)\n     ├── Step 5: Find missing translations\n     ├── Step 6: Translate via AI (with caching, batching, retry)\n     ├── Step 7: Write translations to locale files (atomic writes)\n     └── Step 8: Compile .mo files (Django/Flask/FastAPI only)\n```\n\n### String Detection by Platform\n\n**Django / Flask / FastAPI** — AST parses all `.py` files:\n```python\n_(\"Welcome\")                          # gettext\ngettext_lazy(\"Submit\")                # lazy gettext\nngettext(\"%(count)d item\", \"%(count)d items\", count)  # plurals\n```\n\n**Flutter** — Reads `.arb` files or scans `.dart` source:\n```json\n{\"welcome\": \"Welcome back\", \"itemCount\": \"{count, plural, =0{No items} =1{1 item} other{{count} items}}\"}\n```\n\n**Android** — Parses `strings.xml` or scans Kotlin/Java:\n```xml\n\u003cstring name=\"welcome\"\u003eWelcome\u003c/string\u003e\n\u003cplurals name=\"item_count\"\u003e\n    \u003citem quantity=\"one\"\u003e%d item\u003c/item\u003e\n    \u003citem quantity=\"other\"\u003e%d items\u003c/item\u003e\n\u003c/plurals\u003e\n```\n\n**iOS** — Reads `.xcstrings` / `.strings` or scans Swift:\n```swift\n\"Hello\".localized\nNSLocalizedString(\"Welcome\", comment: \"\")\n```\n\n### Language Detection Priority\n\nEach platform detects languages using a priority system — **project config is always checked first**, then locale files:\n\n| Platform | Priority 1 (Config) | Priority 2 (Files) |\n|----------|--------------------|--------------------|\n| **Django** | `LANGUAGES` in `settings.py` | `locale/*/LC_MESSAGES/*.po` files |\n| **Flask/FastAPI** | `LANGUAGES` / `SUPPORTED_LANGUAGES` in config | `translations/*/LC_MESSAGES/*.po` files |\n| **Flutter** | `@@locale` in `.arb` files | — (ARB files ARE the config) |\n| **Android** | `resConfigs` in `build.gradle` | `res/values-*/strings.xml` files |\n| **iOS** | `.xcstrings` JSON / `.xcodeproj` knownRegions | `.lproj/` dirs with `.strings` files |\n\nThis ensures the tool respects your project's explicit language configuration rather than guessing from directory structure.\n\n### Input Validation\n\nAll user inputs are validated before the pipeline starts:\n\n| Flag | Validation | Error Example |\n|------|-----------|---------------|\n| `--lang` | ISO 639 format (e.g., `es`, `zh-TW`, `pt-BR`) | `Invalid language code: 'zzzz'` |\n| `--workers` | Must be 1-10 | `--workers must be between 1 and 10` |\n| `--batch-size` | Must be \u003e= 0 | `--batch-size must be non-negative` |\n| `--min-quality` | Must be 0-100 | `--min-quality must be between 0 and 100` |\n\n## CLI Reference\n\n### Basic Usage\n\n```bash\nai-translate                          # Auto-detect everything, translate\nai-translate --provider claude        # Use Claude specifically\nai-translate --provider openrouter --model deepseek/deepseek-chat-v3-0324  # Budget mode\nai-translate --dry-run                # Preview without writing files\nai-translate --details                # Show comprehensive help guide\n```\n\n### All Flags\n\n| Flag | Description |\n|------|-------------|\n| `--provider PROVIDER` | Force a provider: `claude`, `openai`, `openrouter`, `gemini`, `mistral`, `skip` |\n| `--model MODEL_ID` | OpenRouter model ID (e.g., `deepseek/deepseek-chat-v3-0324`) |\n| `--dry-run` | Preview what would be translated. No API calls, no file writes. |\n| `--estimate` | Show cost comparison across all providers, then exit. |\n| `--review` | Interactive review: accept, edit, or skip each translation before writing. |\n| `--min-quality N` | Quality gate (0-100). Translations below threshold marked as fuzzy. |\n| `--lang CODES` | Translate specific languages: `--lang es,fr,de`. Auto-creates locale structure + updates config. |\n| `--glossary PATH` | Path to glossary JSON for consistent terminology. |\n| `--context TEXT` | Project context injected into AI prompt: `--context \"medical app\"` |\n| `--check` | Regression detection: re-translate cached strings, flag any drift. |\n| `--changed-only` | Only scan files changed since last run (uses `git diff`). |\n| `--quiet` | Zero output, exit code only. For CI/CD. |\n| `--json` | JSON output. For CI/CD pipelines that parse results. |\n| `--workers N` | Parallel translation workers (default: 4, max: 10). Speeds up large projects. |\n| `--batch-size N` | Override auto batch size (default: 10-25 based on string count). |\n| `--no-auto-install` | Don't auto-install missing provider SDKs. |\n| `--debug` | Verbose debug logging. |\n| `--details` | Show detailed usage guide. |\n\n## Features\n\n### Cost Estimation\n\nSee what translation will cost BEFORE spending money:\n\n```bash\nai-translate --estimate\n```\n\n```\n  Cost Estimate  │  42 strings × 10 languages\n\n  Provider                    Cost          Time     Quality\n  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n  Claude (Anthropic)        $0.0025         ~12s     Excellent\n  OpenAI GPT-4o             $0.0030         ~15s     High\n  Google Gemini             $0.0001 ← best  ~6s     High\n  DeepSeek (OpenRouter)     $0.0002          ~8s     Good\n```\n\n### Glossary (Consistent Terminology)\n\nCreate `.ai-translate-glossary.json` in your project root:\n\n```json\n{\n  \"Dashboard\": {\"es\": \"Panel de control\", \"fr\": \"Tableau de bord\"},\n  \"Submit\": {\"es\": \"Enviar\", \"fr\": \"Soumettre\"},\n  \"Sign in\": {\"es\": \"Iniciar sesion\", \"fr\": \"Se connecter\"}\n}\n```\n\nThe tool auto-discovers this file. Terms are injected into the AI prompt as mandatory terminology.\n\n### Interactive Review\n\nReview translations before they're written:\n\n```bash\nai-translate --review\n```\n\n```\n[1/42] \"Welcome back\"\n├── es: \"Bienvenido de nuevo\"      Score: 95%\n├── fr: \"Bon retour\"               Score: 93%\n└── ja: \"おかえりなさい\"              Score: 91%\n\n[A]ccept / [E]dit / [S]kip\n```\n\n### Quality Gate\n\nOnly accept high-confidence translations:\n\n```bash\nai-translate --min-quality 80\n```\n\nTranslations scoring below 80% are marked as fuzzy (not used at runtime in Django). You review and approve them manually.\n\n### Regression Detection\n\nCheck if AI model updates changed your existing translations:\n\n```bash\nai-translate --check\n```\n\n```\n⚠ TRANSLATION DRIFT DETECTED\n\n  \"Cancel\" (es):\n    Cached:  \"Cancelar\"\n    New AI:  \"Anular\"\n```\n\n### Provider Failover\n\nIf your primary provider is down, the tool automatically tries the next available provider:\n\n```\n● Provider: Claude (auto-detected)\nℹ Failover chain: OpenAI GPT, Google Gemini\n```\n\nIf Claude fails after 3 retries → OpenAI is tried → if that fails → Gemini is tried.\n\n**Runtime failover:** If a provider breaks mid-translation (after batch 50 of 400), the tool detects 3 consecutive failures and automatically switches to the next working provider for the remaining batches — no restart needed.\n\n### Auto Language Setup\n\nWhen no target languages are detected, the tool guides you through setup and automatically configures your project:\n\n```bash\nai-translate --lang es,fr,de\n```\n\n```\n  ✓ Created language structure for: es, fr, de\n  ✓ Updated project config with: es, fr, de\n```\n\nWhat happens per platform:\n\n| Platform | Files Created | Config Updated |\n|----------|--------------|----------------|\n| **Django** | `locale/\u003clang\u003e/LC_MESSAGES/django.po` | `LANGUAGES` in `settings.py` |\n| **Flask/FastAPI** | `translations/\u003clang\u003e/LC_MESSAGES/messages.po` | `SUPPORTED_LANGUAGES` in config |\n| **Flutter** | `lib/l10n/app_\u003clang\u003e.arb` | ARB files ARE the config |\n| **Android** | `res/values-\u003clang\u003e/strings.xml` | `resConfigs` in `build.gradle` |\n| **iOS (.strings)** | `\u003clang\u003e.lproj/Localizable.strings` | `knownRegions` in `.xcodeproj` |\n| **iOS (.xcstrings)** | Locale entries in JSON | `knownRegions` in `.xcodeproj` |\n\nExisting languages are never removed or duplicated — only new codes are added.\n\n### Parallel Translation\n\nSpeed up large projects with parallel workers:\n\n```bash\nai-translate --workers 8       # 8 parallel workers (default: 4)\n```\n\n```\nBefore:  400 batches × ~3s each = ~20 minutes (sequential)\nAfter:   400 batches ÷ 4 workers × ~3s = ~5 minutes (4x faster)\n```\n\nQuality stays the same — same prompts, same AI, just parallel.\n\n### Incremental Progress Saving\n\nThe tool saves translation progress every 20 batches. If the tool crashes or is interrupted at batch 200 of 400, only the last ~20 batches are lost. Run again and it picks up from the cache.\n\n### Smart Path Detection\n\nWhen multiple `.env` files or locale directories exist in your project, the tool asks you to choose:\n\n```\n  △ Multiple locale directorys found. Please choose one:\n\n  [1]  /project/MyApp/locale     10 .po files, 13,520 translations\n  [2]  /project/locale           empty (no .po files)\n\n  ❯ Choose locale directory [1/2]: 1\n  ✓ Using: /project/MyApp/locale\n  › Choice saved — won't ask again for this project.\n```\n\nYour choice is saved per-project in `~/.ai-translate/projects/\u003chash\u003e/prefs.json`. Next run uses it automatically.\n\n### Auto SDK Installation\n\nMissing provider SDKs are installed automatically with a progress spinner:\n\n```\n  › Auto-installing anthropic...\n  ⠋ Installing anthropic...\n  ✓ SDK for 'claude' installed successfully\n```\n\nUse `--no-auto-install` to disable this in CI/CD environments.\n\n### Placeholder Validation\n\nAfter translation, the tool validates that all placeholders are preserved:\n\n```python\n# Source:\n_(\"%(count)d Posts deleted by %(name)s\")\n\n# If AI drops a placeholder, you get warned:\n▲ [es] \"%(count)d Posts...\" → Missing placeholders: %(name)s\n```\n\nThis prevents runtime crashes from broken format strings.\n\n## Caching\n\n### Zero Project Pollution\n\nThe tool stores ALL data in `~/.ai-translate/`. Nothing is written to your project folder (except `.env` for API keys and locale files for translations).\n\n```\n~/.ai-translate/\n├── global_cache.json              ← Shared across ALL your projects\n└── projects/\n    ├── a1b2c3d4e5f6/\n    │   ├── cache.json             ← Project-specific translations\n    │   ├── prefs.json             ← Saved user choices (locale dir, .env path)\n    │   └── meta.json              ← Project path, platform, last run\n    └── ...\n```\n\n### Cross-Project Sharing\n\nTranslate \"Submit\" → \"Enviar\" in Project A → Project B gets it for FREE. The global cache means common strings (Submit, Cancel, Save, Delete, Settings, etc.) are translated once and reused everywhere.\n\n### How Caching Saves Money\n\n```\nFirst run:   42 strings × 5 languages = 210 API calls     → $0.18\nSecond run:  3 new strings × 5 languages = 15 API calls   → $0.01 (39 cached)\nThird run:   0 new strings = 0 API calls                   → $0.00\n```\n\n## CI/CD Integration\n\n### GitHub Actions — Simple\n\n```yaml\n# .github/workflows/translate.yml\nname: Auto Translate\non:\n  push:\n    branches: [main]\n\njobs:\n  translate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v5\n        with:\n          python-version: '3.12'\n      - run: pip install -U ai-translate\n      - name: Translate\n        run: ai-translate --quiet --provider claude\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n      - name: Commit translations\n        run: |\n          git config user.name \"ai-translate\"\n          git config user.email \"bot@ai-translate.dev\"\n          git add locale/ translations/ lib/l10n/ app/src/main/res/\n          git diff --staged --quiet || git commit -m \"chore: auto-translate\"\n          git push\n```\n\n### GitHub Actions — With Slack Notification\n\n```yaml\n      - name: Translate\n        id: translate\n        run: |\n          RESULT=$(ai-translate --json --provider claude)\n          echo \"translated=$(echo $RESULT | jq -r '.translated')\" \u003e\u003e $GITHUB_OUTPUT\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n\n      - name: Notify Slack\n        if: steps.translate.outputs.translated != '0'\n        uses: slackapi/slack-github-action@v1\n        with:\n          payload: '{\"text\": \"Translated ${{ steps.translate.outputs.translated }} strings\"}'\n        env:\n          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}\n```\n\n### GitHub Actions — Block PR if Translations Missing\n\n```yaml\n# .github/workflows/translate-check.yml\nname: Translation Check\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v5\n        with:\n          python-version: '3.12'\n      - run: pip install -U ai-translate\n      - name: Check translations\n        run: |\n          RESULT=$(ai-translate --json --provider skip)\n          MISSING=$(echo \"$RESULT\" | jq -r '.missing_count')\n          if [ \"$MISSING\" -gt \"0\" ]; then\n            echo \"::error::$MISSING strings need translation\"\n            exit 1\n          fi\n```\n\n### CI/CD Output Modes\n\n| Flag | Output | Exit Code | Use Case |\n|------|--------|-----------|----------|\n| (none) | Rich terminal UI | 0/1 | Developer in terminal |\n| `--quiet` | Zero bytes | 0 = success, 1 = failure | Pass/fail gate |\n| `--json` | `{\"status\": \"...\", \"translated\": N, ...}` | 0/1 | Parse results, post to Slack |\n\n### JSON Output Format\n\n```json\n{\n  \"status\": \"success\",\n  \"platform\": \"django\",\n  \"source_count\": 42,\n  \"missing_count\": 8,\n  \"translated\": 8,\n  \"approved\": 6,\n  \"fuzzy\": 2,\n  \"lang_count\": 3,\n  \"languages\": [\"es\", \"fr\", \"de\"],\n  \"elapsed\": 12.4,\n  \"provider\": \"Claude (Anthropic)\"\n}\n```\n\n## Plural Support\n\nEvery platform's plural system is fully supported:\n\n### Django / Flask / FastAPI\n\n```python\nfrom django.utils.translation import ngettext\nmsg = ngettext(\"%(count)d item\", \"%(count)d items\", count)\n```\n\nGenerated `.po` file:\n```po\nmsgid \"%(count)d item\"\nmsgid_plural \"%(count)d items\"\nmsgstr[0] \"%(count)d elemento\"\nmsgstr[1] \"%(count)d elementos\"\n```\n\nThe tool sets the correct `Plural-Forms` header per language (Russian gets 3 forms, Arabic gets 6, Japanese gets 1).\n\n### Flutter (ICU MessageFormat)\n\n```json\n{\n  \"itemCount\": \"{count, plural, =0{No items} =1{1 item} other{{count} items}}\"\n}\n```\n\nICU plural syntax is preserved during translation. The AI is instructed to translate each variant inside the braces.\n\n### Android\n\n```xml\n\u003cplurals name=\"item_count\"\u003e\n    \u003citem quantity=\"one\"\u003e%d item\u003c/item\u003e\n    \u003citem quantity=\"other\"\u003e%d items\u003c/item\u003e\n\u003c/plurals\u003e\n```\n\n### iOS (.xcstrings)\n\n```json\n{\n  \"item_count\": {\n    \"localizations\": {\n      \"es\": {\n        \"variations\": {\n          \"plural\": {\n            \"one\": {\"stringUnit\": {\"value\": \"%lld elemento\"}},\n            \"other\": {\"stringUnit\": {\"value\": \"%lld elementos\"}}\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n## Project Structure\n\n```\nai-translate/\n├── pyproject.toml                     # Package config\n├── ai_translate/\n│   ├── __init__.py                    # Version\n│   ├── config.py                      # Centralized constants\n│   ├── cli/\n│   │   ├── main.py                    # CLI entry point + pipeline\n│   │   └── ui.py                      # Rich terminal UI\n│   ├── platforms/\n│   │   ├── __init__.py                # Platform detection\n│   │   ├── _shared.py                 # Shared AST utils, PO helpers, plural forms\n│   │   ├── django.py                  # Django handler\n│   │   ├── flask_fastapi.py           # Flask / FastAPI handler\n│   │   ├── flutter.py                 # Flutter handler\n│   │   ├── android.py                 # Android handler\n│   │   └── ios.py                     # iOS handler\n│   └── services/\n│       ├── cache.py                   # Translation cache (global + per-project)\n│       ├── env_manager.py             # .env management\n│       └── translators/\n│           ├── __init__.py            # Provider registry + factory\n│           ├── base.py                # Base class, prompt builder, retry, scoring\n│           ├── claude.py              # Anthropic Claude\n│           ├── openai_provider.py     # OpenAI GPT\n│           ├── openrouter.py          # OpenRouter (100+ models)\n│           ├── gemini.py              # Google Gemini\n│           └── mistral.py             # Mistral AI\n└── tests/\n    ├── conftest.py                    # 8 shared fixtures\n    ├── test_platforms.py              # Platform detection + handler tests\n    ├── test_translators.py            # Provider + prompt tests\n    ├── test_cache.py                  # Cache + global sharing tests\n    ├── test_cli.py                    # CLI flag tests\n    ├── test_plurals.py                # Plural support tests (all platforms)\n    └── test_business_logic.py         # Real-world scenario tests\n```\n\n## FAQ\n\n### How much does it cost?\n\nThe tool itself is free. You only pay for AI API calls:\n\n| Provider | 500 strings, 5 languages | Quality |\n|----------|-------------------------|---------|\n| Gemini Flash | ~$0.01 | High |\n| DeepSeek (via OpenRouter) | ~$0.02 | Good |\n| Claude | ~$0.20 | Excellent |\n| OpenAI GPT-4o | ~$0.25 | High |\n\nCached strings cost $0. The global cache means common strings are translated once across all your projects.\n\n### Does it overwrite my existing translations?\n\nNo. The tool only fills in MISSING translations. If a translation already exists (non-empty `msgstr` in `.po`, existing key in `.arb`, etc.), it is never touched.\n\n### Does it create files in my project?\n\nOnly the locale files your platform needs (`.po`, `.arb`, `strings.xml`, `.xcstrings`). The translation cache is stored in `~/.ai-translate/`, not in your project.\n\nThe only non-locale file created is `.env` (if you enter an API key interactively), which is a standard developer convention.\n\n### What if I don't have any locale files yet?\n\nThe tool creates them. For a brand new project with no locale directory, it will:\n1. Scan your source code for translatable strings\n2. Ask you for target languages (if it can't detect them), or use `--lang es,fr,de`\n3. Create the locale directories and files automatically\n4. Update your project config (`LANGUAGES` in settings.py, `resConfigs` in build.gradle, etc.)\n5. On the next run, languages are auto-detected from the config — no need to specify again\n\n### Can I use it in a monorepo?\n\nYes. Run it from the root of the specific project you want to translate. The tool detects the platform from the current directory.\n\n### What about API key security?\n\n- Keys are stored in `.env` (add to `.gitignore`)\n- Keys are masked in terminal output (first 4 + dots + last 4)\n- Keys are never written to the cache\n- In CI/CD, use environment secrets (e.g., GitHub Secrets)\n\n### What Python versions are supported?\n\nPython 3.10, 3.11, 3.12, 3.13.\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n\n## Author\n\nBuilt by [Happy-Cyber](https://github.com/Happy-cyber).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhappy-cyber%2Fai-translate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhappy-cyber%2Fai-translate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhappy-cyber%2Fai-translate/lists"}