ai-localize-cli 2.0.5 → 2.0.6

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 (3) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +537 -0
  3. package/package.json +10 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # ai-localize-cli
2
2
 
3
+ ## 2.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Add per-package README.md files so each package displays documentation on npmjs.com
8
+ - Update README version badge to 2.0.6
9
+
3
10
  ## 2.0.5
4
11
 
5
12
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,537 @@
1
+ # ai-localize-core
2
+
3
+ > Enterprise-grade deterministic localization + CloudFront CDN migration platform for React, Vue, and Angular.
4
+
5
+ **No AI. No cloud API. Fully offline. Reproducible outputs.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/ai-localize-cli.svg)](https://www.npmjs.com/package/ai-localize-cli)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
9
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
10
+ [![Version](https://img.shields.io/badge/version-2.0.5-blue)](CHANGELOG.md)
11
+
12
+ ---
13
+
14
+ ## What's New in v2.0.5
15
+
16
+ | Fix | Details |
17
+ |---|---|
18
+ | **`validate` always returned "valid"** | `MissingKeyValidator` now correctly detects keys where the target language value equals the English source placeholder. These are seeded automatically by `extract` and must be replaced with real translations. Error message: `Missing translation for "key" in "fr" (value equals source)` |
19
+ | **`full-migrate` appeared to only generate a report** | `staticKeys` from config is now wired through to the extractor. `--dry-run` now shows a full preview. Validation and report are correctly skipped in dry-run mode. |
20
+ | **`report` crashed with `RangeError: Invalid count value`** | Coverage % went negative when all keys were untranslated (missingKeys counted per-language). Now clamped to `[0, 100]`. All bar renderers guard against negative `String.repeat()`. |
21
+
22
+ ---
23
+
24
+ ## What it does
25
+
26
+ `ai-localize-core` automates the full localization lifecycle using static AST analysis:
27
+
28
+ 1. **Scan** — finds every hardcoded UI string in your source code
29
+ 2. **Extract** — generates deterministic locale JSON files (`en.json`, `fr.json`, …)
30
+ 3. **Codemod** — injects `useTranslation()` and wraps strings with `t('key')` automatically
31
+ 4. **Validate** — catches missing, unused, duplicate, and placeholder-mismatch keys
32
+ 5. **Report** — produces a comprehensive HTML report with legends and full details
33
+ 6. **CDN Migrate** — uploads assets to S3, replaces legacy CDN URLs with CloudFront paths
34
+
35
+ ---
36
+
37
+ ## Supported Frameworks
38
+
39
+ | Framework | Detection | Codemods | Default i18n Library |
40
+ |---|---|---|---|
41
+ | React (CRA, Vite, Next.js) | ✅ | ✅ | `react-i18next` |
42
+ | Angular (ngx-translate, i18n) | ✅ | ✅ | `@ngx-translate/core` |
43
+ | Vue 3 (vue-i18n) | ✅ | ✅ | `vue-i18n` |
44
+ | jQuery / Vanilla JS | ✅ | — | — |
45
+ | JSP | ✅ | — | — |
46
+ | Custom hook (any architecture) | ✅ | ✅ | configurable |
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ # Global install (gives you the `ai-localize` command everywhere)
54
+ npm install -g ai-localize-cli
55
+
56
+ # Or as a project dev dependency
57
+ npm install --save-dev ai-localize-cli
58
+
59
+ # Or use without installing
60
+ npx ai-localize-cli <command>
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Quick Start
66
+
67
+ ```bash
68
+ # 1. Initialize — creates ai-localize.config.json with all options
69
+ cd your-project
70
+ npx ai-localize init
71
+
72
+ # 2. Scan for hardcoded text
73
+ npx ai-localize scan
74
+
75
+ # 3. Extract locale files
76
+ npx ai-localize extract
77
+ # → locales/en/translation.json, locales/fr/translation.json …
78
+
79
+ # 4. Preview codemods (dry run first!)
80
+ npx ai-localize full-migrate --dry-run
81
+
82
+ # 5. Apply codemods
83
+ npx ai-localize full-migrate
84
+
85
+ # 6. Validate locale files
86
+ npx ai-localize validate
87
+
88
+ # 7. Generate HTML report
89
+ npx ai-localize report
90
+ # → .ai-localize-reports/report-2026-05-26T12-00-00.html
91
+ ```
92
+
93
+ ---
94
+
95
+ ## CLI Commands
96
+
97
+ | Command | Description |
98
+ |---|---|
99
+ | `ai-localize init` | Initialize config with auto-detected framework + all fields |
100
+ | `ai-localize scan` | Scan source for hardcoded text + asset references |
101
+ | `ai-localize extract` | Generate locale JSON files |
102
+ | `ai-localize validate` | Check for missing / unused / duplicate / placeholder-mismatch keys. Also flags keys whose target value still equals the English source (un-translated placeholders seeded by `extract`). |
103
+ | `ai-localize cleanup` | Remove unused locale keys |
104
+ | `ai-localize report` | Generate a comprehensive HTML report |
105
+ | `ai-localize full-migrate` | Run the full pipeline: scan → extract → codemod → validate → report |
106
+ | `ai-localize migrate-cdn` | Upload assets to S3 + replace legacy CDN URLs + invalidate CloudFront |
107
+ | `ai-localize upload-assets` | Upload static assets to S3 |
108
+ | `ai-localize replace-cdn` | Replace legacy CDN URLs using an existing asset manifest |
109
+
110
+ ### Common options (all commands)
111
+
112
+ | Option | Description |
113
+ |---|---|
114
+ | `--cwd <path>` | Working directory (default: `process.cwd()`) |
115
+ | `--dry-run` | Preview changes without writing files |
116
+
117
+ ### `scan` options
118
+
119
+ | Option | Description |
120
+ |---|---|
121
+ | `--incremental` | Only scan git-changed files |
122
+ | `--staged` | Only scan git-staged files |
123
+ | `--output <path>` | Save full scan results as JSON |
124
+ | `--extract-cdns <path>` | Save discovered CDN/legacy URLs to JSON |
125
+
126
+ ### `report` options
127
+
128
+ | Option | Description |
129
+ |---|---|
130
+ | `--output-dir <path>` | Report directory (default: `.ai-localize-reports`) |
131
+ | `--filename <name>` | Custom filename (default: `report-<timestamp>.html`) |
132
+
133
+ ### `full-migrate` options
134
+
135
+ | Option | Description |
136
+ |---|---|
137
+ | `--no-codemods` | Skip codemod injection phase |
138
+ | `--no-report` | Skip HTML report generation |
139
+ | `--report-dir <path>` | Report directory (default: `.ai-localize-reports`) |
140
+
141
+ ---
142
+
143
+ ## Configuration
144
+
145
+ Running `npx ai-localize init` creates `ai-localize.config.json` with every field included:
146
+
147
+ ```json
148
+ {
149
+ "framework": "react-vite",
150
+ "defaultLanguage": "en",
151
+ "targetLanguages": ["fr", "de"],
152
+ "sourceDir": "src",
153
+ "localesDir": "locales",
154
+ "localeStructure": "nested",
155
+ "ignorePatterns": ["node_modules", "dist", ".git", "coverage"],
156
+ "includePatterns": [],
157
+ "keyPrefix": "",
158
+ "namespaces": [],
159
+ "incrementalCache": true,
160
+ "cacheDir": ".ai-localize-cache",
161
+ "codemods": {
162
+ "importPackage": "react-i18next",
163
+ "hookName": "useTranslation",
164
+ "translationFunction": "t",
165
+ "namespace": "",
166
+ "accessorStyle": "function"
167
+ },
168
+ "aws": {
169
+ "region": "us-east-1",
170
+ "bucket": "",
171
+ "distributionId": "",
172
+ "cdnBaseUrl": "",
173
+ "legacyCdnPattern": "",
174
+ "assetsPrefix": "assets",
175
+ "profile": ""
176
+ },
177
+ "plugins": []
178
+ }
179
+ ```
180
+
181
+ ### Config field reference
182
+
183
+ | Field | Type | Default | Description |
184
+ |---|---|---|---|
185
+ | `framework` | string | `"unknown"` | Framework — controls which codemod runs. Values: `"react"` `"react-cra"` `"react-vite"` `"react-nextjs"` `"angular"` `"angular-ngx"` `"angular-i18n"` `"vue"` `"vue-i18n"` `"jquery"` `"vanilla-js"` `"jsp"` `"unknown"` |
186
+ | `defaultLanguage` | string | `"en"` | Source language code (any BCP-47 tag) |
187
+ | `targetLanguages` | string[] | `[]` | Languages to generate locale files for |
188
+ | `sourceDir` | string | `"src"` | Root directory to scan |
189
+ | `localesDir` | string | `"locales"` | Where locale files are written |
190
+ | `localeStructure` | `"nested"` \| `"flat"` | `"nested"` | `"nested"` — one file per language+namespace (`locales/en/translation.json`). `"flat"` — one file per language, all keys merged (`locales/en.json`) |
191
+ | `keyStyle` | `"path"` \| `"screaming_snake"` | `"path"` | `"path"` — hierarchical dot-notation from file path + text: `settings.page.save_changes`. `"screaming_snake"` — UPPER_SNAKE_CASE from text value: `"Save Changes"` → `SAVE_CHANGES` |
192
+ | `staticKeys` | object | `{}` | Key/value pairs injected into every locale file regardless of scanning. Use for enum labels, status codes, or strings not hardcoded in source files. Example: `{"MAX_COUNT":"Max Count","ALLOWED":"Allowed"}` |
193
+ | `ignorePatterns` | string[] | `["node_modules","dist",…]` | Dirs/patterns to skip |
194
+ | `includePatterns` | string[] | — | If set, only scan matching files (supports `*` and `**` globs) |
195
+ | `keyPrefix` | string | — | Prefix added to every generated key (e.g. `"myapp"` → `"myapp.components.button.save"`) |
196
+ | `namespaces` | string[] | — | Explicit namespace list. If omitted, derived from first path segment after `sourceDir` |
197
+ | `incrementalCache` | boolean | `true` | Cache file hashes for faster re-runs |
198
+ | `cacheDir` | string | `".ai-localize-cache"` | Cache directory |
199
+ | `codemods` | object | — | Codemod injection options (see below) |
200
+ | `aws` | object | — | AWS S3 + CloudFront settings |
201
+ | `plugins` | string[] | `[]` | Custom plugin module paths |
202
+
203
+ ---
204
+
205
+ ## Locale File Layout
206
+
207
+ ### `localeStructure: "nested"` (default)
208
+
209
+ ```
210
+ locales/
211
+ en/
212
+ common.json
213
+ dashboard.json
214
+ fr/
215
+ common.json
216
+ dashboard.json
217
+ ```
218
+
219
+ ### `localeStructure: "flat"`
220
+
221
+ ```
222
+ locales/
223
+ en.json ← all namespaces merged
224
+ fr.json
225
+ ```
226
+
227
+ Set in config:
228
+ ```json
229
+ { "localeStructure": "flat" }
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Codemod Configuration
235
+
236
+ The `codemods` block controls what code is injected. All fields are optional with framework-specific defaults.
237
+
238
+ | Field | Default | Description |
239
+ |---|---|---|
240
+ | `importPackage` | `"react-i18next"` | npm package **or** project-relative path (e.g. `"src/hooks/useTranslation"`) |
241
+ | `hookName` | `"useTranslation"` | Hook function to import and call |
242
+ | `translationFunction` | `"t"` | Accessor destructured from the hook |
243
+ | `namespace` | — | Argument to the hook: `useTranslation("common")` |
244
+ | `accessorStyle` | `"function"` | `"function"` → `t('key')` · `"bracket"` → `t['key']` |
245
+
246
+ ### Standard react-i18next
247
+
248
+ ```json
249
+ {
250
+ "codemods": {
251
+ "importPackage": "react-i18next",
252
+ "hookName": "useTranslation",
253
+ "translationFunction": "t"
254
+ }
255
+ }
256
+ ```
257
+
258
+ Injects:
259
+ ```tsx
260
+ import { useTranslation } from 'react-i18next';
261
+ // inside component:
262
+ const { t } = useTranslation();
263
+ return <h1>{t('header.welcome')}</h1>;
264
+ ```
265
+
266
+ ### Custom local hook (per-file path resolution)
267
+
268
+ ```json
269
+ {
270
+ "codemods": {
271
+ "importPackage": "src/hooks/useTranslation",
272
+ "hookName": "useTranslation",
273
+ "translationFunction": "t"
274
+ }
275
+ }
276
+ ```
277
+
278
+ The codemod automatically computes the correct relative path **per file**:
279
+
280
+ | File | Injected import |
281
+ |---|---|
282
+ | `src/App.tsx` | `import { useTranslation } from './hooks/useTranslation'` |
283
+ | `src/components/Button.tsx` | `import { useTranslation } from '../../hooks/useTranslation'` |
284
+ | `src/pages/dashboard/Header.tsx` | `import { useTranslation } from '../../../hooks/useTranslation'` |
285
+
286
+ ### Bracket notation
287
+
288
+ ```json
289
+ {
290
+ "codemods": {
291
+ "accessorStyle": "bracket"
292
+ }
293
+ }
294
+ ```
295
+
296
+ Generates `t['some.key']` instead of `t('some.key')`.
297
+
298
+ ---
299
+
300
+ ## Scanner: Recognising Custom Translation Calls
301
+
302
+ Set `codemods.importPackage` and the scanner will automatically skip strings already wrapped by your custom hook — they won't be re-reported as hardcoded text.
303
+
304
+ **Supported import path formats:**
305
+
306
+ | Format | Example |
307
+ |---|---|
308
+ | npm package | `"react-i18next"` |
309
+ | Scoped npm package | `"@angular/core"` |
310
+ | Project-relative path | `"src/hooks/useTranslation"` |
311
+ | Path alias | `"@/hooks/useTranslation"` |
312
+ | Relative path | `"../../hooks/useTranslation"` |
313
+
314
+ All relative/alias forms match by **tail segment comparison**, so `hooks/useTranslation` matches `../../hooks/useTranslation`, `./hooks/useTranslation`, and `@/hooks/useTranslation`.
315
+
316
+ ---
317
+
318
+ ## HTML Report
319
+
320
+ Running `npx ai-localize report` generates a self-contained HTML file:
321
+
322
+ ```bash
323
+ npx ai-localize report
324
+ # → .ai-localize-reports/report-2026-05-26T12-00-00.html
325
+
326
+ npx ai-localize report --output-dir ./audit --filename localization-audit.html
327
+ ```
328
+
329
+ The report contains:
330
+ - **8 summary cards** — Files Scanned, Hardcoded Texts, Keys Generated, Missing Translations, Unused Keys, Assets Found, Assets Uploaded, Legacy CDN URLs
331
+ - **Explainer box** — why Hardcoded Texts and Keys Generated may differ
332
+ - **Hardcoded Texts table** — file, line, text, suggested key, context
333
+ - **Missing Translations table** — key, language, file, message
334
+ - **Unused Keys table** — keys to clean up
335
+ - **Assets table** — uploaded asset paths, S3 keys, CloudFront URLs
336
+ - Each section has a **legend** explaining what the data means and what action to take
337
+
338
+ ---
339
+
340
+ ## AWS / CDN Migration
341
+
342
+ Fill in the `aws` block in your config (or use environment variables):
343
+
344
+ ```json
345
+ {
346
+ "aws": {
347
+ "region": "us-east-1",
348
+ "bucket": "my-assets-bucket",
349
+ "distributionId": "E1ABCDEFGHIJKL",
350
+ "cdnBaseUrl": "https://d123.cloudfront.net",
351
+ "legacyCdnPattern": "https://old-legacy-cdn.company.com",
352
+ "assetsPrefix": "static-assets/v1"
353
+ }
354
+ }
355
+ ```
356
+
357
+ Or via `.env`:
358
+ ```bash
359
+ AWS_S3_BUCKET=my-assets-bucket
360
+ AWS_CF_DISTRIBUTION_ID=E1ABCDEFGHIJKL
361
+ AI_LOCALIZE_CDN_BASE_URL=https://d123.cloudfront.net
362
+ AI_LOCALIZE_LEGACY_CDN_PATTERN=https://old-legacy-cdn.company.com
363
+ ```
364
+
365
+ One-step CDN migration:
366
+ ```bash
367
+ npx ai-localize migrate-cdn --assets-dir ./public --invalidate
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Before / After Example
373
+
374
+ **Before:**
375
+ ```tsx
376
+ export const Banner = () => (
377
+ <div>
378
+ <h1>Welcome to the Dashboard</h1>
379
+ <p>Manage your campaigns easily.</p>
380
+ <button>Get Started</button>
381
+ </div>
382
+ );
383
+ ```
384
+
385
+ **After `npx ai-localize full-migrate`:**
386
+ ```tsx
387
+ import { useTranslation } from 'react-i18next';
388
+
389
+ export const Banner = () => {
390
+ const { t } = useTranslation();
391
+ return (
392
+ <div>
393
+ <h1>{t('banner.welcome_to_the_dashboard')}</h1>
394
+ <p>{t('banner.manage_your_campaigns_easily')}</p>
395
+ <button>{t('banner.get_started')}</button>
396
+ </div>
397
+ );
398
+ };
399
+ ```
400
+
401
+ **Generated `locales/en/common.json`:**
402
+ ```json
403
+ {
404
+ "banner.get_started": "Get Started",
405
+ "banner.manage_your_campaigns_easily": "Manage your campaigns easily.",
406
+ "banner.welcome_to_the_dashboard": "Welcome to the Dashboard"
407
+ }
408
+ ```
409
+
410
+ **Generated `locales/fr/common.json`** (seeded with English values for translators):
411
+ ```json
412
+ {
413
+ "banner.get_started": "Get Started",
414
+ "banner.manage_your_campaigns_easily": "Manage your campaigns easily.",
415
+ "banner.welcome_to_the_dashboard": "Welcome to the Dashboard"
416
+ }
417
+ ```
418
+
419
+ > **Tip — run `validate` after seeding:** New target-language entries are seeded with
420
+ > the English source value. `ai-localize validate` flags these as
421
+ > `"Missing translation (value equals source)"` until real translations are provided.
422
+
423
+ ---
424
+
425
+ ## Key Generation
426
+
427
+ Keys are generated deterministically from the file path + text:
428
+
429
+ ```
430
+ src/pages/dashboard/Banner.tsx + "Welcome to the Dashboard"
431
+ → pages.dashboard.banner.welcome_to_the_dashboard
432
+ ```
433
+
434
+ Format: `<folder>.<folder>.<component>.<slugified_text>`
435
+
436
+ - Relative to `sourceDir`
437
+ - CamelCase segments are snake_cased
438
+ - Text is lowercased, punctuation stripped, spaces replaced with `_`, truncated to 60 chars
439
+ - Duplicate strings across files share the same key
440
+
441
+ ---
442
+
443
+ ## Programmatic API
444
+
445
+ ```ts
446
+ import { ProjectScanner } from 'ai-localize-scanner';
447
+ import { LocaleExtractor, LocaleWriter } from 'ai-localize-locale-engine';
448
+ import { CodemodRunner } from 'ai-localize-codemods';
449
+ import { LocaleValidator } from 'ai-localize-validators';
450
+ import { buildReport, generateHtmlReport } from 'ai-localize-reporting';
451
+
452
+ const config = {
453
+ framework: 'react-vite',
454
+ defaultLanguage: 'en',
455
+ targetLanguages: ['fr'],
456
+ sourceDir: 'src',
457
+ localesDir: 'locales',
458
+ };
459
+
460
+ // Scan
461
+ const scanner = new ProjectScanner(config);
462
+ const scanResult = await scanner.scan();
463
+
464
+ // Extract
465
+ const extractor = new LocaleExtractor({ defaultLanguage: 'en', targetLanguages: ['fr'] });
466
+ const { localeFiles } = extractor.extract(scanResult.detectedTexts);
467
+
468
+ // Write
469
+ const writer = new LocaleWriter({ localesDir: './locales' });
470
+ writer.write(localeFiles);
471
+
472
+ // Validate
473
+ const validator = new LocaleValidator({ localesDir: './locales', sourceDir: './src', defaultLanguage: 'en', targetLanguages: ['fr'] });
474
+ const validation = validator.validate();
475
+
476
+ // Report
477
+ const report = buildReport({ scanResult, validationResult: validation });
478
+ generateHtmlReport(report, './report.html');
479
+ ```
480
+
481
+ ---
482
+
483
+ ## Monorepo Packages
484
+
485
+ | Package | npm install | Description |
486
+ |---|---|---|
487
+ | `ai-localize-shared` | `npm i ai-localize-shared` | Shared types, utilities, constants |
488
+ | `ai-localize-config` | `npm i ai-localize-config` | Config loading + Zod validation |
489
+ | `ai-localize-framework-detectors` | `npm i ai-localize-framework-detectors` | Auto-detect React / Angular / Vue |
490
+ | `ai-localize-scanner` | `npm i ai-localize-scanner` | Babel AST scanner + incremental scanning |
491
+ | `ai-localize-codemods` | `npm i ai-localize-codemods` | React / Vue / Angular i18n injection |
492
+ | `ai-localize-locale-engine` | `npm i ai-localize-locale-engine` | Locale file extraction, writing, merging |
493
+ | `ai-localize-validators` | `npm i ai-localize-validators` | Missing / unused / duplicate key validation |
494
+ | `ai-localize-aws-cloudfront` | `npm i ai-localize-aws-cloudfront` | S3 upload + CloudFront invalidation |
495
+ | `ai-localize-reporting` | `npm i ai-localize-reporting` | HTML + CLI report generation |
496
+ | `ai-localize-cli` | `npm i -g ai-localize-cli` | Full CLI (`ai-localize` command) |
497
+
498
+ ---
499
+
500
+ ## CI/CD Integration
501
+
502
+ ### GitHub Actions
503
+
504
+ ```yaml
505
+ - name: Localization check
506
+ run: |
507
+ npx ai-localize scan
508
+ npx ai-localize validate
509
+ npx ai-localize report --output-dir ./reports
510
+ ```
511
+
512
+ ### Pre-commit hook
513
+
514
+ ```bash
515
+ npx ai-localize scan --staged
516
+ npx ai-localize validate
517
+ ```
518
+
519
+ ---
520
+
521
+ ## Full Documentation
522
+
523
+ See [`INSTRUCTION_GUIDE.md`](INSTRUCTION_GUIDE.md) for the complete developer guide including:
524
+ - All CLI options with examples
525
+ - Full config field reference
526
+ - Codemod config deep-dive
527
+ - Custom hook integration
528
+ - Locale layout options
529
+ - CDN migration walkthrough
530
+ - HTML report guide
531
+ - Troubleshooting
532
+
533
+ ---
534
+
535
+ ## License
536
+
537
+ MIT © ai-localize-core contributors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-localize-cli",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "CLI for ai-localize-core: scan, extract, validate, codemod and migrate CDN",
5
5
  "bin": {
6
6
  "ai-localize": "./dist/cli.js"
@@ -35,15 +35,15 @@
35
35
  "chalk": "^5.3.0",
36
36
  "ora": "^8.0.1",
37
37
  "inquirer": "^9.2.12",
38
- "ai-localize-shared": "2.0.5",
39
- "ai-localize-config": "2.0.5",
40
- "ai-localize-codemods": "2.0.5",
41
- "ai-localize-framework-detectors": "2.0.5",
42
- "ai-localize-scanner": "2.0.5",
43
- "ai-localize-locale-engine": "2.0.5",
44
- "ai-localize-validators": "2.0.5",
45
- "ai-localize-aws-cloudfront": "2.0.5",
46
- "ai-localize-reporting": "2.0.5"
38
+ "ai-localize-shared": "2.0.6",
39
+ "ai-localize-framework-detectors": "2.0.6",
40
+ "ai-localize-codemods": "2.0.6",
41
+ "ai-localize-locale-engine": "2.0.6",
42
+ "ai-localize-scanner": "2.0.6",
43
+ "ai-localize-config": "2.0.6",
44
+ "ai-localize-validators": "2.0.6",
45
+ "ai-localize-reporting": "2.0.6",
46
+ "ai-localize-aws-cloudfront": "2.0.6"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/inquirer": "^9.0.7",