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.
- package/CHANGELOG.md +7 -0
- package/README.md +537 -0
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
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
|
+
[](https://www.npmjs.com/package/ai-localize-cli)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://nodejs.org)
|
|
10
|
+
[](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.
|
|
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.
|
|
39
|
-
"ai-localize-
|
|
40
|
-
"ai-localize-codemods": "2.0.
|
|
41
|
-
"ai-localize-
|
|
42
|
-
"ai-localize-scanner": "2.0.
|
|
43
|
-
"ai-localize-
|
|
44
|
-
"ai-localize-validators": "2.0.
|
|
45
|
-
"ai-localize-
|
|
46
|
-
"ai-localize-
|
|
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",
|