JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 29
  • Score
    100M100P100Q87436F
  • License MIT

AI-powered i18n automation CLI for React โ€” scan, translate, and transform hardcoded strings into react-i18next calls

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (rancc) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    ๐ŸŒ RanCC

    The i18n automation CLI built for React developers.

    Stop writing t("key") by hand. RanCC scans your React codebase, translates with AI, and rewrites your components โ€” fully automated.

    npm license built with bun react


    React First

    RanCC is designed exclusively for React projects using react-i18next. Every feature โ€” scanning, transforming, and the runtime setup โ€” is built around React's component model, JSX syntax, and the hooks-based API of react-i18next.

    It does not support Vue, Angular, Svelte, React Native, or next-intl. React + react-i18next is the one thing it does, and it does it completely.


    The Problem Every React Developer Faces

    You build a React app in English. It works. Then the requirement comes: support Hindi, French, German. Now you face this:

    // Your current components โ€” hundreds of them
    function HeroSection() {
      return (
        <>
          <h1>Welcome Back</h1>
          <p>The fastest way to build your product</p>
          <button>Get Started</button>
          <input placeholder="Search products..." />
        </>
      );
    }

    To internationalize this manually you have to:

    1. Hunt every hardcoded string across 50+ components
    2. Create a locales/en.json with consistent keys
    3. Replace every string with t("welcome_back") by hand
    4. Add const { t } = useTranslation() to every component
    5. Add import { useTranslation } from 'react-i18next' to every file
    6. Translate the JSON into every target language โ€” one key at a time
    7. Repeat this every time your UI text changes
    8. Keep all locale files in sync when you rename or delete strings

    For a mid-sized app, this process takes days and produces inconsistent results.

    RanCC automates every single step.

    // After running: rancc scan && rancc translate && rancc transform
    import { useTranslation } from "react-i18next";
    
    function HeroSection() {
      const { t } = useTranslation();
      return (
        <>
          <h1>{t("Welcome Back")}</h1>
          <p>{t("The fastest way to build your product")}</p>
          <button>{t("Get Started")}</button>
          <input placeholder={t("Search products...")} />
        </>
      );
    }

    Installation

    npm install -g rancc
    # or
    bun add -g rancc
    # or
    pnpm add -g rancc

    Quick Start

    # 1. Run in your React project root
    rancc init
    
    # 2. Extract all UI strings from your source files
    rancc scan
    
    # 3. AI-translate into all target languages
    rancc translate
    
    # 4. Generate i18n.ts and inject import into your entry file
    rancc setup
    
    # 5. Install react-i18next in your React project (printed by setup)
    npm install i18next react-i18next
    
    # 6. Rewrite components to use t()
    rancc transform --dry-run    # preview first
    rancc transform --backup     # then apply

    That's it. Your React app is now internationalized.


    Configuration

    Running rancc init creates auto-i18n-config.json in your project root:

    {
      "sourceLang": "en",
      "targetLang": ["hi", "fr", "de"],
      "provider": "groq",
      "scanProvider": "groq",
      "localeDir": "./locales",
      "i18nLibrary": "react-i18next",
      "ignore": [
        "**/node_modules/**",
        "**/.next/**",
        "**/dist/**",
        "**/build/**"
      ]
    }
    Field Description
    sourceLang Source language code (e.g. "en")
    targetLang Array of target language codes
    provider AI provider used by rancc translate
    scanProvider AI provider used by rancc scan --ai (can differ from translate)
    localeDir Directory where locale JSON files are stored
    i18nLibrary i18n library ("react-i18next" only)
    ignore Glob patterns to exclude from scanning

    API Keys

    Add your API key to a .env file in the project root where you run RanCC:

    GROQ_API_KEY=your_key_here
    OPENAI_API_KEY=your_key_here
    GOOGLE_API_KEY=your_key_here
    ANTHROPIC_API_KEY=your_key_here
    OPENROUTER_API_KEY=your_key_here

    Key formats and where to get them:

    Provider Env variable Key format Get your key
    OpenAI OPENAI_API_KEY sk-... platform.openai.com/api-keys
    Groq GROQ_API_KEY gsk_... console.groq.com/keys
    Google Gemini GOOGLE_API_KEY AIzaSy... aistudio.google.com/apikey
    Anthropic Claude ANTHROPIC_API_KEY sk-ant-... console.anthropic.com/settings/keys
    OpenRouter OPENROUTER_API_KEY sk-or-... openrouter.ai/keys

    Bun automatically loads .env from the current working directory โ€” no dotenv configuration needed.


    Commands In Depth


    rancc init

    ๐Ÿง™ Interactive configuration wizard

    Walks you through setting up the project configuration. Prompts for:

    • Source language (the language your app is currently written in)
    • Target languages (what you want to translate into)
    • Locale directory path
    • i18n library selection
    • Translation provider โ€” which AI to use for rancc translate
    • Scan provider โ€” which AI to use for rancc scan --ai (can be a cheaper/faster model like Groq)

    Writes auto-i18n-config.json and shows a summary:

    (โยดโ—ก`โ) Configuration setup done!
    
      Translate provider : groq
      Scan provider      : groq
      Locale dir         : ./locales
      Source language    : en
      Target languages   : hi, fr, de

    rancc scan

    ๐Ÿ” Extract UI strings from your React codebase using Babel AST

    Parses every .js, .jsx, .ts, .tsx file and extracts strings that are likely UI text. Uses a multi-layer approach:

    What gets extracted

    JSX text content:

    <h1>Hello World</h1>          // โœ… extracted
    <p>Click here to continue</p> // โœ… extracted

    Translatable HTML attributes:

    <input placeholder="Search..."  /> // โœ… extracted
    <img alt="Profile photo" />        // โœ… extracted
    <button title="Close panel" />     // โœ… extracted
    <div aria-label="Navigation" />    // โœ… extracted

    Data array patterns โ€” object property keys:

    // โœ… extracted: name, usedFor, badge, description, label, title...
    const features = [
      { name: "AI Agent", description: "Autonomous coding", badge: "New" },
    ]

    Notification/alert calls:

    toast.error("Something went wrong")  // โœ… extracted
    alert("Are you sure?")               // โœ… extracted
    enqueueSnackbar("Saved!")            // โœ… extracted

    What gets filtered out (heuristic)

    The AST extractor automatically discards:

    • Tailwind/CSS class strings ("flex items-center gap-2")
    • CSS values ("radial-gradient(...)", "0.5s ease")
    • SVG path data ("M 50,50 L 15,20")
    • Hex colors, rgba strings
    • URL strings
    • File paths
    • Cron expressions ("0 9 * * *")
    • Shell/code commands ("npm install ...")
    • Template placeholders ("{value}px", "stream-{id}")
    • Model IDs and API slugs ("gpt-4o-mini", "openrouter/free")
    • Pure numbers, env var names, UUIDs

    Scan flags

    rancc scan              # Fast, heuristic-only โ€” always works, no API needed
    rancc scan --ai         # AST + LLM verification pass
    rancc scan --review     # AST + interactive developer approval
    rancc scan --ai --review  # All three layers combined

    --ai flag โ€” LLM-powered verification

    When --ai is passed, RanCC sends extracted candidates to your scanProvider in batches of 80. Each entry includes the string value, source file path, and line number so the model has full context:

    {
      "Free Tier": { "value": "Free Tier", "file": "src/Providers.tsx", "line": 18 },
      "openrouter/free": { "value": "openrouter/free", "file": "src/Providers.tsx", "line": 19 }
    }

    The LLM sees that "Free Tier" on line 18 is a badge label (keep) and "openrouter/free" on line 19 is a config slug (reject). This context makes the filter dramatically more accurate than heuristics alone.

    If the API key for scanProvider is not set in .env, --ai degrades gracefully to heuristic-only with a warning โ€” it never crashes.

    --review flag โ€” developer approval

    Presents every extracted string one by one in the terminal. You press Y to keep or N to discard. Shows file path and line number next to each string:

      [1/42] Welcome Back   src/HeroSection.tsx:8
      Keep? โ€บ Yes
    
      [2/42] flex items-center gap-2   src/Navbar.tsx:12
      Keep? โ€บ No

    Ctrl+C saves progress so far โ€” you won't lose approved strings if you stop midway.


    rancc translate

    ๐ŸŒ AI-powered translation with incremental updates

    Translates your source locale (en.json) into every configured target language using your AI provider.

    Incremental translation

    Only new strings are translated. If hi.json already exists with 380 keys and you added 5 new strings, only those 5 get sent to the AI. Existing translations are preserved.

      โ–ถ  Translating โ†’ Hindi (+5 new keys) โ€” 1 chunk
        [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100% (1/1 chunks)
        โœ“ Saved locales/hi.json (380 existing + 5 new)

    Batch processing

    Strings are sent in batches of 100 to stay within context limits. Each batch:

    • Retries up to 3ร— with exponential backoff on failure
    • Validates every key in the model response before merging
    • Falls back to the source value for any key the model drops or fails

    The final merged file preserves the original source key order.


    rancc check

    ๐Ÿ”Ž Show every untranslated key per language

      โœ“ Hindi (hi)   โ€” fully translated
      โš  French (fr)  โ€” 3 untranslated key(s):
          โ€ข "contact_support"  โ†’ "Contact Support"
          โ€ข "order_status"     โ†’ "Order Status"
          โ€ข "delete_account"   โ†’ "Delete Account"
    
    โš  3 total untranslated key(s). Run `translate` to fix.

    Shows the source value alongside each missing key so you know exactly what needs translating.


    rancc clean

    ๐Ÿงน Remove stale keys from locale files

    After you rename or delete strings in your React app, re-run scan to update en.json, then run clean to remove the deleted keys from all target locale files.

      โœ“ Hindi (hi)   โ€” removed 2 stale key(s): "old_hero_title", "unused_cta"
      โœ“ French (fr)  โ€” nothing to clean
    
    โœ“ Removed 2 stale key(s) total.

    rancc stats

    ๐Ÿ“Š Translation coverage dashboard

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚          ๐Ÿ“Š i18n Statistics           โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
    
    Project
    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    Files Scanned        : 34
    Strings Extracted    : 381
    Source Language      : en
    
    Locales
    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    en.json              : 381
    hi.json              : 381
    fr.json              : 378
    
    Missing Keys
    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    fr:
      3 key(s) missing โ€” run `check` for details
    
    Coverage
    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    en  : 381 / 381  (100%)
    hi  : 381 / 381  (100%)
    fr  : 378 / 381   (99%)
    
    โœ“ Done

    rancc stats --verbose

    Adds:

    • File type breakdown (JS/JSX/TS/TSX counts)
    • Duplicate string count
    • Full list of missing keys per language
    • Last scan timestamp (from source file mtime)

    rancc modify-langs

    โœ๏ธ Add or remove target languages interactively

    Opens a multi-select prompt pre-checked with your current targets. Make changes and confirm. RanCC:

    • Updates auto-i18n-config.json
    • Deletes locale files for removed languages
    • Leaves existing locale files for added languages (they'll be created on next translate)

    rancc setup

    ๐Ÿ”ง Wire up react-i18next in your React project

    This is a one-time command that bootstraps the react-i18next runtime configuration for your React app.

    What it does:

    1. Detects your React entry file โ€” checks src/main.tsx, src/main.jsx, src/index.tsx, src/index.jsx
    2. Generates src/i18n.ts โ€” a complete react-i18next configuration pre-wired with all your configured languages
    3. Injects import "./i18n" into your entry file after the last existing import (never duplicates)

    Generated src/i18n.ts:

    import i18n from "i18next";
    import { initReactI18next } from "react-i18next";
    
    import en from "../locales/en.json";
    import hi from "../locales/hi.json";
    import fr from "../locales/fr.json";
    
    i18n.use(initReactI18next).init({
      resources: {
        en: { translation: en },
        hi: { translation: hi },
        fr: { translation: fr },
      },
      lng: localStorage.getItem("lang") ?? "en",
      fallbackLng: "en",
      interpolation: {
        escapeValue: false, // React already handles XSS
      },
    });
    
    export default i18n;

    After running setup, it prints install instructions for all package managers:

      Install required packages in your React project:
    
        npm   npm install i18next react-i18next
        yarn  yarn add i18next react-i18next
        pnpm  pnpm add i18next react-i18next
        bun   bun add i18next react-i18next

    rancc transform

    โšก Rewrite React components to use t() โ€” fully AST-based

    The core V2 feature. Traverses every React source file and rewrites hardcoded UI strings into t() calls. Automatically injects the useTranslation hook and import. Only transforms strings that exist in your source locale (en.json) โ€” nothing else is touched.

    Everything is AST-based

    RanCC uses @babel/parser, @babel/traverse, @babel/types, and @babel/generator. Zero regex rewriting. Zero string replacement. Every transformation is a proper AST mutation, which means:

    • Correct handling of JSX edge cases
    • No risk of corrupting code structure
    • Output is formatted with your project's own Prettier config

    JSX text transformation

    // Before
    <h1>Welcome Back</h1>
    <button>Get Started</button>
    
    // After
    <h1>{t("Welcome Back")}</h1>
    <button>{t("Get Started")}</button>

    Attribute transformation

    Supported attributes: placeholder, alt, title, aria-label, aria-description

    // Before
    <input placeholder="Search products..." />
    <img alt="Profile photo" />
    
    // After
    <input placeholder={t("Search products...")} />
    <img alt={t("Profile photo")} />

    Hook injection

    If const { t } = useTranslation() is not already in the component, it is injected at the top of the function body:

    // Before
    function HeroSection() {
      return <h1>Welcome</h1>;
    }
    
    // After
    function HeroSection() {
      const { t } = useTranslation();
      return <h1>{t("Welcome")}</h1>;
    }

    Hook injection is never duplicated โ€” if it already exists, it is skipped.

    Import injection

    If import { useTranslation } from "react-i18next" is missing, it is added after the last existing import. Never duplicated.

    Supported component patterns

    function App() { ... }              // โœ… named function declaration
    const App = () => { ... }           // โœ… arrow function with block body
    const App = function() { ... }      // โœ… function expression

    What is never touched

    {user.name}          // expression โ€” already dynamic
    {t("hello")}         // already translated
    {`${count} items`}   // template literal
    value={someVar}      // non-string attribute
    // Ignored attributes: id, key, className, type, name, src, href, value, role...

    Options

    rancc transform               # transform and write files in place
    rancc transform --dry-run     # show coloured diff, write nothing
    rancc transform --backup      # save originals to .edge-backups/ before overwriting

    --dry-run output

      ~ src/HeroSection.tsx (3 strings)
    @@ -3,7 +3,8 @@
    
     function HeroSection() {
    +  const { t } = useTranslation();
       return (
    -    <h1>Welcome Back</h1>
    +    <h1>{t("Welcome Back")}</h1>
       );
     }

    --backup

    Creates .edge-backups/ and mirrors your project structure inside it before any file is overwritten:

    .edge-backups/
      src/
        HeroSection.tsx
        components/
          Navbar.tsx
          Footer.tsx

    Complete Workflow

    # โ”€โ”€ First time setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    
    rancc init                   # configure providers, languages, locale dir
    
    rancc scan                   # extract strings (heuristic)
    rancc scan --ai              # or: AST + AI verification (recommended)
    rancc scan --ai --review     # or: AST + AI + you approve each one
    
    rancc translate              # AI-translate into all target languages
    
    rancc setup                  # generate src/i18n.ts, inject import
    
    # Install in your React project:
    npm install i18next react-i18next
    
    rancc transform --dry-run    # preview what will be rewritten
    rancc transform --backup     # apply transformations with backup
    
    # โ”€โ”€ Ongoing maintenance โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    
    rancc scan                   # after adding new UI text
    rancc translate              # only new strings are sent to AI
    rancc clean                  # after removing/renaming strings
    rancc check                  # verify coverage
    rancc stats                  # dashboard overview
    rancc stats --verbose        # detailed report

    Scan Pipeline In Detail

    The scan goes through up to three layers, each optional:

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚                    Layer 1: AST Extraction                   โ”‚
    โ”‚  Babel parses every .js/.jsx/.ts/.tsx file                  โ”‚
    โ”‚  Extracts from: JSXText, translatable attributes,           โ”‚
    โ”‚  data object keys, alert/toast calls                        โ”‚
    โ”‚  Heuristic filters remove CSS, SVG, cron, code snippets     โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚  Map<string, { value, file, line }>
                          โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚              Layer 2: LLM Verification (--ai)               โ”‚
    โ”‚  Batches of 80 strings sent to scanProvider                 โ”‚
    โ”‚  Each entry includes file path + line number as context     โ”‚
    โ”‚  Model returns array of keys to KEEP                        โ”‚
    โ”‚  Auto-skips gracefully if API key not set                   โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚  Map<string, TranslationEntry>
                          โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚           Layer 3: Developer Review (--review)              โ”‚
    โ”‚  Each string shown with file:line context                   โ”‚
    โ”‚  Y = keep, N = discard                                      โ”‚
    โ”‚  Ctrl+C saves progress                                      โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
                          โ–ผ
                    locales/en.json

    Supported AI Providers

    Provider Config value Env variable Recommended for
    OpenAI openai OPENAI_API_KEY Translate
    Groq groq GROQ_API_KEY Scan filter (fast + free tier)
    Google Gemini google-gemini GOOGLE_API_KEY Translate
    Anthropic Claude claude ANTHROPIC_API_KEY Translate (highest quality)
    OpenRouter openrouter OPENROUTER_API_KEY Both

    You can use different providers for scan and translate. A common setup:

    • scanProvider: "groq" โ€” fast, cheap, handles classification well
    • provider: "claude" โ€” higher quality for actual translation

    Supported Languages

    English ยท Hindi ยท French ยท German ยท Spanish ยท Italian ยท Portuguese ยท Russian ยท Japanese ยท Korean ยท Chinese


    Project Structure

    rancc/
    โ”œโ”€โ”€ index.ts                      CLI entry โ€” all Commander commands
    โ”œโ”€โ”€ constants.ts                  Language list, attribute sets, data key sets
    โ”œโ”€โ”€ types.ts                      TransLationConfig type, CSS_KEYWORDS
    โ”‚
    โ”œโ”€โ”€ Text_Extractor/
    โ”‚   โ”œโ”€โ”€ method.ts                 Core logic: scan, translate, check, clean,
    โ”‚   โ”‚                             stats, llmFilterStrings, reviewStrings
    โ”‚   โ”œโ”€โ”€ extractor.ts              shouldTranslate() filters, addText()
    โ”‚   โ”œโ”€โ”€ config-ask.ts             Interactive init wizard
    โ”‚   โ””โ”€โ”€ traverse_import_helper.ts Babel traverse ESM compatibility shim
    โ”‚
    โ””โ”€โ”€ src/transform/
        โ”œโ”€โ”€ types.ts                  TransformResult, TransformOptions interfaces
        โ”œโ”€โ”€ reverseLookup.ts          Builds value โ†’ key map from en.json
        โ”œโ”€โ”€ injectImport.ts           AST: inject/merge useTranslation import
        โ”œโ”€โ”€ injectHook.ts             AST: inject const { t } = useTranslation()
        โ”œโ”€โ”€ replaceJSXText.ts         AST: replace JSX text nodes with t()
        โ”œโ”€โ”€ replaceAttributes.ts      AST: replace attribute values with t()
        โ”œโ”€โ”€ transformFile.ts          Orchestrates parse โ†’ traverse โ†’ generate โ†’ prettier
        โ”œโ”€โ”€ transformProject.ts       File discovery, I/O, backup, per-file logging
        โ”œโ”€โ”€ backup.ts                 .edge-backups/ folder management
        โ”œโ”€โ”€ dryRun.ts                 Coloured unified diff output
        โ””โ”€โ”€ index.ts                  runTransform() + runSetup() entry points

    Local Development

    Since RanCC runs on Bun, you can test changes directly without building:

    bun index.ts scan
    bun index.ts translate
    bun index.ts transform --dry-run

    Or link it globally for testing as a real CLI:

    bun link
    
    # Then from any React project:
    rancc scan
    rancc transform

    Build for publishing:

    bun run build
    npm publish --access=public

    Notes

    • Transform is idempotent โ€” running it twice won't double-wrap strings already wrapped in t()
    • Only known strings are transformed โ€” if a string isn't in en.json, it is never touched
    • RanCC excludes its own source โ€” getFilePaths ignores Text_Extractor/, src/transform/, config files, so running in the RanCC repo itself is safe
    • Prettier respects your project โ€” output is formatted using prettier.resolveConfig(filePath), so your existing .prettierrc is honoured
    • Bun loads .env automatically โ€” no dotenv configuration needed when using Bun

    License

    MIT ยฉ 2026