rancc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +455 -0
  3. package/dist/index.js +102328 -0
  4. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,455 @@
1
+ # Edge — AI-Powered i18n Automation CLI for React
2
+
3
+ > Built specifically for React projects. Edge takes the grunt work out of internationalization — from extracting strings to rewriting your components — so you can ship multilingual apps without the manual overhead.
4
+
5
+ ---
6
+
7
+ ## The Problem
8
+
9
+ If you've ever added i18n to a real React app, you know the pain:
10
+
11
+ - You have hundreds of components with hardcoded text like `<h1>Welcome Back</h1>` and `placeholder="Search..."`
12
+ - You have to hunt down every single string manually across every file
13
+ - Create a locale JSON file with consistent, meaningful keys
14
+ - Go back and replace every string with `t("welcome_back")` by hand
15
+ - Add `const { t } = useTranslation()` to every component that has text
16
+ - Add the import at the top of every file
17
+ - Then do all of that again for every language you support
18
+ - Then keep all of it in sync every time your UI text changes
19
+
20
+ For a mid-sized React app (50+ components) this process takes **days** and is full of human error — missed strings, inconsistent keys, untranslated languages, stale keys that pile up.
21
+
22
+ **Edge solves all of it from the terminal.**
23
+
24
+ ---
25
+
26
+ ## Stack
27
+
28
+ - **Runtime:** Bun
29
+ - **Language:** TypeScript
30
+ - **CLI:** Commander.js
31
+ - **AST:** `@babel/parser`, `@babel/traverse`, `@babel/types`, `@babel/generator`
32
+ - **Formatting:** Prettier
33
+ - **AI Translation:** Vercel AI SDK (`ai`)
34
+ - **Supported Providers:** OpenAI, Groq, Google Gemini, Claude, OpenRouter
35
+ - **i18n Library:** react-i18next (V2 transform only)
36
+
37
+ ---
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ bun install
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Configuration
48
+
49
+ Running `Edge init` creates `auto-i18n-config.json` in the current directory:
50
+
51
+ ```json
52
+ {
53
+ "sourceLang": "en",
54
+ "targetLang": ["hi", "fr", "de"],
55
+ "provider": "groq",
56
+ "localeDir": "./locales",
57
+ "ignore": ["**/node_modules/**", "**/.next/**", "**/dist/**", "**/build/**"],
58
+ "i18nLibrary": "react-i18next"
59
+ }
60
+ ```
61
+
62
+ Set your API key in a `.env` file in the project root where you run Edge:
63
+
64
+ ```env
65
+ GROQ_API_KEY=your_key_here
66
+ # or
67
+ OPENAI_API_KEY=your_key_here
68
+ # or
69
+ GOOGLE_API_KEY=your_key_here
70
+ # or
71
+ ANTHROPIC_API_KEY=your_key_here
72
+ # or
73
+ OPENROUTER_API_KEY=your_key_here
74
+ ```
75
+
76
+ > Bun automatically loads `.env` from the current working directory — no extra setup needed.
77
+
78
+ ---
79
+
80
+ ## Commands
81
+
82
+ ### `Edge init`
83
+
84
+ Interactive setup wizard. Prompts for:
85
+ - Source language
86
+ - Target languages
87
+ - Locale directory
88
+ - AI provider
89
+ - i18n library
90
+
91
+ Writes `auto-i18n-config.json`.
92
+
93
+ ---
94
+
95
+ ### `Edge scan`
96
+
97
+ Scans all `.js`, `.jsx`, `.ts`, `.tsx` files in your project using Babel AST. Extracts:
98
+ - All JSX text content (`<h1>Hello</h1>`)
99
+ - Translatable attributes (`placeholder`, `alt`, `title`, `aria-label`, `aria-description`)
100
+
101
+ Writes extracted strings to `locales/en.json` (or your configured source locale).
102
+
103
+ ```
104
+ ┌─────────────────────────────────┐
105
+ │ 🔍 Starting i18n Scan │
106
+ └─────────────────────────────────┘
107
+
108
+ → Loading config...
109
+ ✓ Config loaded (source: en)
110
+ → Scanning project files...
111
+
112
+ Scanning: src/App.tsx
113
+ Scanning: src/components/Navbar.tsx
114
+
115
+ ✓ Extracted 42 strings
116
+ → Locale dir ready: ./locales
117
+ ✓ Saved to locales/en.json
118
+
119
+ ✨ Scan complete!
120
+ ```
121
+
122
+ ---
123
+
124
+ ### `Edge translate`
125
+
126
+ Translates `en.json` into all configured target languages using your AI provider.
127
+
128
+ **Incremental** — only translates keys that are missing from an existing target locale file. Already-translated keys are preserved.
129
+
130
+ - Sends strings in batches of 100 keys per request
131
+ - Retries each batch up to 3 times with backoff on failure
132
+ - Falls back to source value if a key fails after all retries
133
+ - Validates every key in the model response before merging
134
+
135
+ ```
136
+ ▶ Translating → hi (+5 new keys) — 1 chunk
137
+ [████████████████████] 100% (1/1 chunks)
138
+ ✓ Saved locales/hi.json (38 existing + 5 new)
139
+ ```
140
+
141
+ ---
142
+
143
+ ### `Edge check`
144
+
145
+ Shows every untranslated key per target language, with the source value alongside each missing key.
146
+
147
+ ```
148
+ ✓ Hindi (hi) — fully translated
149
+ ⚠ French (fr) — 3 untranslated key(s):
150
+ • "contact_support" → "Contact Support"
151
+ • "order_status" → "Order Status"
152
+ • "delete_account" → "Delete Account"
153
+
154
+ ⚠ 3 total untranslated key(s). Run `translate` to fix.
155
+ ```
156
+
157
+ ---
158
+
159
+ ### `Edge clean`
160
+
161
+ Removes keys from target locale files that no longer exist in the source (`en.json`). Useful after you rename or remove strings.
162
+
163
+ ```
164
+ ✓ Hindi (hi) — nothing to clean
165
+ ✓ French (fr) — removed 2 stale key(s): "old_key", "unused_label"
166
+
167
+ ✓ Removed 2 stale key(s) total.
168
+ ```
169
+
170
+ ---
171
+
172
+ ### `Edge stats`
173
+
174
+ Overview of your translation coverage.
175
+
176
+ ```
177
+ ┌──────────────────────────────────────┐
178
+ │ 📊 i18n Statistics │
179
+ └──────────────────────────────────────┘
180
+
181
+ Project
182
+ ────────────────────────────────────────
183
+ Files Scanned : 34
184
+ Strings Extracted : 381
185
+ Source Language : en
186
+
187
+ Locales
188
+ ────────────────────────────────────────
189
+ en.json : 381
190
+ hi.json : 381
191
+ fr.json : 378
192
+
193
+ Missing Keys
194
+ ────────────────────────────────────────
195
+ fr:
196
+ 3 key(s) missing — run `check` for details
197
+
198
+ Coverage
199
+ ────────────────────────────────────────
200
+ en : 381 / 381 (100%)
201
+ hi : 381 / 381 (100%)
202
+ fr : 378 / 381 (99%)
203
+
204
+ ✓ Done
205
+ ```
206
+
207
+ #### `Edge stats --verbose`
208
+
209
+ Adds file type breakdown, duplicate string count, full list of missing keys, and last scan timestamp.
210
+
211
+ ---
212
+
213
+ ### `Edge modify-langs`
214
+
215
+ Interactive multi-select to add or remove target languages from your config. Automatically deletes locale files for removed languages.
216
+
217
+ ---
218
+
219
+ ### `Edge setup` *(V2)*
220
+
221
+ Generates the `react-i18next` runtime configuration for your React project.
222
+
223
+ 1. Detects your React entry file (`src/main.tsx`, `src/main.jsx`, `src/index.tsx`, `src/index.jsx`)
224
+ 2. Generates `src/i18n.ts` with all configured languages pre-wired
225
+ 3. Injects `import "./i18n"` into your entry file (safe — never duplicates)
226
+
227
+ ```ts
228
+ // generated src/i18n.ts
229
+ import i18n from "i18next";
230
+ import { initReactI18next } from "react-i18next";
231
+
232
+ import en from "../locales/en.json";
233
+ import hi from "../locales/hi.json";
234
+ import fr from "../locales/fr.json";
235
+
236
+ i18n.use(initReactI18next).init({
237
+ resources: {
238
+ en: { translation: en },
239
+ hi: { translation: hi },
240
+ fr: { translation: fr },
241
+ },
242
+ lng: localStorage.getItem("lang") ?? "en",
243
+ fallbackLng: "en",
244
+ interpolation: { escapeValue: false },
245
+ });
246
+
247
+ export default i18n;
248
+ ```
249
+
250
+ After setup, it prints install instructions for all package managers:
251
+
252
+ ```
253
+ Install required packages in your React project:
254
+
255
+ npm npm install i18next react-i18next
256
+ yarn yarn add i18next react-i18next
257
+ pnpm pnpm add i18next react-i18next
258
+ bun bun add i18next react-i18next
259
+ ```
260
+
261
+ ---
262
+
263
+ ### `Edge transform` *(V2)*
264
+
265
+ **The core V2 feature.** Rewrites your React source files to replace hardcoded strings with `t()` calls. Fully AST-based — no regex, no string replacement.
266
+
267
+ #### What it transforms
268
+
269
+ **JSX text:**
270
+ ```tsx
271
+ // before
272
+ <h1>Hello</h1>
273
+ <button>Buy Now</button>
274
+
275
+ // after
276
+ <h1>{t("Hello")}</h1>
277
+ <button>{t("Buy Now")}</button>
278
+ ```
279
+
280
+ **Translatable attributes** (`placeholder`, `alt`, `title`, `aria-label`, `aria-description`):
281
+ ```tsx
282
+ // before
283
+ <input placeholder="Search Products" />
284
+
285
+ // after
286
+ <input placeholder={t("Search Products")} />
287
+ ```
288
+
289
+ **Hook injection** (if not already present):
290
+ ```tsx
291
+ // before
292
+ function App() {
293
+ return <h1>Hello</h1>;
294
+ }
295
+
296
+ // after
297
+ function App() {
298
+ const { t } = useTranslation();
299
+ return <h1>{t("Hello")}</h1>;
300
+ }
301
+ ```
302
+
303
+ **Import injection** (if not already present):
304
+ ```tsx
305
+ import { useTranslation } from "react-i18next";
306
+ ```
307
+
308
+ #### What it skips
309
+
310
+ - `{user.name}` — already an expression
311
+ - `{t("hello")}` — already translated
312
+ - `` {`${count} items`} `` — template literals
313
+ - Strings not found in `en.json` — only transforms known keys
314
+ - Ignored attributes: `id`, `key`, `className`, `type`, `name`, `src`, `href`, `value`, etc.
315
+
316
+ #### Supported component patterns
317
+
318
+ ```tsx
319
+ function App() { ... } // named function declaration
320
+ const App = () => { ... } // arrow function with block body
321
+ const App = function() { ... } // function expression
322
+ ```
323
+
324
+ #### Options
325
+
326
+ ```bash
327
+ Edge transform # transform and write files
328
+ Edge transform --dry-run # preview diff, write nothing
329
+ Edge transform --backup # save originals to .edge-backups/ first
330
+ ```
331
+
332
+ #### `--dry-run` output
333
+
334
+ ```diff
335
+ ~ src/App.tsx (3 strings)
336
+ @@ -4,7 +4,9 @@
337
+ function App() {
338
+ + const { t } = useTranslation();
339
+ return (
340
+ - <h1>Hello</h1>
341
+ + <h1>{t("Hello")}</h1>
342
+ );
343
+ }
344
+ ```
345
+
346
+ #### `--backup`
347
+
348
+ Saves original files to `.edge-backups/` preserving folder structure before overwriting.
349
+
350
+ ```
351
+ .edge-backups/
352
+ src/
353
+ App.tsx
354
+ components/
355
+ Navbar.tsx
356
+ ```
357
+
358
+ ---
359
+
360
+ ## Complete Workflow
361
+
362
+ ```bash
363
+ # 1. Set up config (one time)
364
+ Edge init
365
+
366
+ # 2. Extract all hardcoded strings from your codebase
367
+ Edge scan
368
+
369
+ # 3. Translate into all target languages
370
+ Edge translate
371
+
372
+ # 4. Check for any gaps
373
+ Edge check
374
+
375
+ # 5. Wire up react-i18next runtime (one time)
376
+ Edge setup
377
+
378
+ # Install packages printed by setup in your React project
379
+ npm install i18next react-i18next
380
+
381
+ # 6. Rewrite source files to use t()
382
+ Edge transform --dry-run # review first
383
+ Edge transform --backup # then apply
384
+
385
+ # 7. As your app grows — re-scan and re-translate incrementally
386
+ Edge scan
387
+ Edge translate # only new strings get sent to AI
388
+
389
+ # 8. Clean up stale keys after renames/deletions
390
+ Edge clean
391
+
392
+ # 9. Monitor coverage anytime
393
+ Edge stats
394
+ Edge stats --verbose
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Project Structure
400
+
401
+ ```
402
+ auto-i18n-ai/
403
+ ├── index.ts CLI entry — all Commander commands
404
+ ├── constants.ts Language list, attribute sets
405
+ ├── types.ts TransLationConfig type
406
+ ├── auto-i18n-config.json Generated config (gitignore this or commit it)
407
+ ├── locales/
408
+ │ ├── en.json Source locale (generated by scan)
409
+ │ ├── hi.json Target locale (generated by translate)
410
+ │ └── fr.json
411
+ ├── Text_Extractor/
412
+ │ ├── method.ts Core scan, translate, check, clean, stats logic
413
+ │ └── config-ask.ts Interactive init wizard
414
+ └── src/
415
+ └── transform/
416
+ ├── types.ts TransformResult, TransformOptions interfaces
417
+ ├── reverseLookup.ts Builds value → key map from en.json
418
+ ├── injectImport.ts AST: inject useTranslation import
419
+ ├── injectHook.ts AST: inject const { t } = useTranslation()
420
+ ├── replaceJSXText.ts AST: replace JSX text nodes with t()
421
+ ├── replaceAttributes.ts AST: replace attribute values with t()
422
+ ├── transformFile.ts Orchestrates parse → traverse → generate → prettier
423
+ ├── transformProject.ts Discovers files, handles I/O, backup, dry-run
424
+ ├── backup.ts .edge-backups/ management
425
+ ├── dryRun.ts Coloured unified diff output
426
+ └── index.ts runTransform() + runSetup() entry points
427
+ ```
428
+
429
+ ---
430
+
431
+ ## Supported AI Providers
432
+
433
+ | Provider | Config value | Env variable |
434
+ |---|---|---|
435
+ | OpenAI | `openai` | `OPENAI_API_KEY` |
436
+ | Groq | `groq` | `GROQ_API_KEY` |
437
+ | Google Gemini | `google-gemini` | `GOOGLE_API_KEY` |
438
+ | Anthropic Claude | `claude` | `ANTHROPIC_API_KEY` |
439
+ | OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
440
+
441
+ ---
442
+
443
+ ## Supported Languages
444
+
445
+ English, Hindi, French, German, Spanish, Italian, Portuguese, Russian, Japanese, Korean, Chinese
446
+
447
+ ---
448
+
449
+ ## Notes
450
+
451
+ - **Transform only acts on strings that exist in `en.json`** — run `scan` before `transform`
452
+ - **Transform is idempotent** — running it twice won't double-wrap strings
453
+ - **The CLI ignores its own source files** during scan and transform to prevent self-modification
454
+ - **Prettier formats output** using your project's own `.prettierrc` if present
455
+ - **Bun loads `.env` automatically** — no `dotenv` package needed