next-auto-i18n 0.1.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 (88) hide show
  1. package/DOCUMENTATION.md +749 -0
  2. package/LICENSE +21 -0
  3. package/README.md +168 -0
  4. package/dist/cli/index.d.ts +3 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +291 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/cli/prompts.d.ts +11 -0
  9. package/dist/cli/prompts.d.ts.map +1 -0
  10. package/dist/cli/prompts.js +58 -0
  11. package/dist/cli/prompts.js.map +1 -0
  12. package/dist/generator/index.d.ts +24 -0
  13. package/dist/generator/index.d.ts.map +1 -0
  14. package/dist/generator/index.js +35 -0
  15. package/dist/generator/index.js.map +1 -0
  16. package/dist/generator/key-builder.d.ts +28 -0
  17. package/dist/generator/key-builder.d.ts.map +1 -0
  18. package/dist/generator/key-builder.js +58 -0
  19. package/dist/generator/key-builder.js.map +1 -0
  20. package/dist/injector/config-injector.d.ts +11 -0
  21. package/dist/injector/config-injector.d.ts.map +1 -0
  22. package/dist/injector/config-injector.js +56 -0
  23. package/dist/injector/config-injector.js.map +1 -0
  24. package/dist/injector/index.d.ts +43 -0
  25. package/dist/injector/index.d.ts.map +1 -0
  26. package/dist/injector/index.js +63 -0
  27. package/dist/injector/index.js.map +1 -0
  28. package/dist/injector/layout-injector.d.ts +11 -0
  29. package/dist/injector/layout-injector.d.ts.map +1 -0
  30. package/dist/injector/layout-injector.js +111 -0
  31. package/dist/injector/layout-injector.js.map +1 -0
  32. package/dist/injector/middleware-injector.d.ts +10 -0
  33. package/dist/injector/middleware-injector.d.ts.map +1 -0
  34. package/dist/injector/middleware-injector.js +30 -0
  35. package/dist/injector/middleware-injector.js.map +1 -0
  36. package/dist/injector/routing-injector.d.ts +13 -0
  37. package/dist/injector/routing-injector.d.ts.map +1 -0
  38. package/dist/injector/routing-injector.js +33 -0
  39. package/dist/injector/routing-injector.js.map +1 -0
  40. package/dist/rewriter/attr-rewriter.d.ts +3 -0
  41. package/dist/rewriter/attr-rewriter.d.ts.map +1 -0
  42. package/dist/rewriter/attr-rewriter.js +36 -0
  43. package/dist/rewriter/attr-rewriter.js.map +1 -0
  44. package/dist/rewriter/index.d.ts +26 -0
  45. package/dist/rewriter/index.d.ts.map +1 -0
  46. package/dist/rewriter/index.js +133 -0
  47. package/dist/rewriter/index.js.map +1 -0
  48. package/dist/rewriter/jsx-rewriter.d.ts +20 -0
  49. package/dist/rewriter/jsx-rewriter.d.ts.map +1 -0
  50. package/dist/rewriter/jsx-rewriter.js +98 -0
  51. package/dist/rewriter/jsx-rewriter.js.map +1 -0
  52. package/dist/scanner/ast-parser.d.ts +19 -0
  53. package/dist/scanner/ast-parser.d.ts.map +1 -0
  54. package/dist/scanner/ast-parser.js +59 -0
  55. package/dist/scanner/ast-parser.js.map +1 -0
  56. package/dist/scanner/filters.d.ts +8 -0
  57. package/dist/scanner/filters.d.ts.map +1 -0
  58. package/dist/scanner/filters.js +146 -0
  59. package/dist/scanner/filters.js.map +1 -0
  60. package/dist/scanner/index.d.ts +16 -0
  61. package/dist/scanner/index.d.ts.map +1 -0
  62. package/dist/scanner/index.js +82 -0
  63. package/dist/scanner/index.js.map +1 -0
  64. package/dist/scanner/string-extractor.d.ts +19 -0
  65. package/dist/scanner/string-extractor.d.ts.map +1 -0
  66. package/dist/scanner/string-extractor.js +108 -0
  67. package/dist/scanner/string-extractor.js.map +1 -0
  68. package/dist/translator/deepl.d.ts +19 -0
  69. package/dist/translator/deepl.d.ts.map +1 -0
  70. package/dist/translator/deepl.js +111 -0
  71. package/dist/translator/deepl.js.map +1 -0
  72. package/dist/translator/index.d.ts +14 -0
  73. package/dist/translator/index.d.ts.map +1 -0
  74. package/dist/translator/index.js +57 -0
  75. package/dist/translator/index.js.map +1 -0
  76. package/dist/utils/config.d.ts +19 -0
  77. package/dist/utils/config.d.ts.map +1 -0
  78. package/dist/utils/config.js +50 -0
  79. package/dist/utils/config.js.map +1 -0
  80. package/dist/utils/env.d.ts +18 -0
  81. package/dist/utils/env.d.ts.map +1 -0
  82. package/dist/utils/env.js +70 -0
  83. package/dist/utils/env.js.map +1 -0
  84. package/dist/utils/logger.d.ts +10 -0
  85. package/dist/utils/logger.d.ts.map +1 -0
  86. package/dist/utils/logger.js +25 -0
  87. package/dist/utils/logger.js.map +1 -0
  88. package/package.json +64 -0
@@ -0,0 +1,749 @@
1
+ <p align="center">
2
+ <h1 align="center">next-auto-i18n</h1>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/next-auto-i18n"><img src="https://img.shields.io/npm/v/next-auto-i18n.svg" alt="npm version"></a>
7
+ <a href="https://github.com/stevenkoulo/next-auto-i18n/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/next-auto-i18n.svg" alt="license"></a>
8
+ <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/next-auto-i18n.svg" alt="node version"></a>
9
+ </p>
10
+
11
+ <p align="center"><strong>Translate your Next.js project automatically in under 5 minutes.</strong></p>
12
+
13
+ next-auto-i18n is a CLI tool that fully automates internationalization (i18n) in existing Next.js projects. It scans your codebase via AST, extracts translatable strings, translates them through DeepL, rewrites your components to use `t("key")` calls, and configures [next-intl](https://next-intl-docs.vercel.app/) — all in a single command.
14
+
15
+ ---
16
+
17
+ ## Table of Contents
18
+
19
+ - [Why next-auto-i18n?](#why-next-auto-i18n)
20
+ - [Prerequisites](#prerequisites)
21
+ - [Installation](#installation)
22
+ - [Quick Start](#quick-start)
23
+ - [Configuration](#configuration)
24
+ - [Commands](#commands)
25
+ - [How It Works](#how-it-works)
26
+ - [Supported String Types](#supported-string-types)
27
+ - [Safety & Backups](#safety--backups)
28
+ - [DeepL API](#deepl-api)
29
+ - [Troubleshooting](#troubleshooting)
30
+ - [Contributing](#contributing)
31
+ - [Roadmap](#roadmap)
32
+ - [License](#license)
33
+
34
+ ---
35
+
36
+ ## Why next-auto-i18n?
37
+
38
+ ### Manual setup vs next-auto-i18n
39
+
40
+ | | Manual i18n setup | next-auto-i18n |
41
+ |---|---|---|
42
+ | **Time** | 4-8 hours (medium project) | < 5 minutes |
43
+ | **Steps** | 6+ manual steps across dozens of files | 1 command |
44
+ | **Human error** | Missed strings, typos in keys, broken config | Zero — AST-powered, deterministic |
45
+ | **Translations** | Copy-paste into Google Translate | Automated via DeepL API |
46
+ | **Maintenance** | Re-scan manually after every change | `next-auto-i18n sync` |
47
+
48
+ - **Zero manual work** — from raw project to fully translated site in one command
49
+ - **AST-powered scanning** — finds every translatable string, including dynamic template literals
50
+ - **Incremental by design** — `sync` only translates what changed, preserving existing translations
51
+ - **Safe** — automatic backups, `--dry-run` mode, and `.gitignore` management
52
+
53
+ ---
54
+
55
+ ## Prerequisites
56
+
57
+ - **Node.js >= 18**
58
+ - **A Next.js project** using the App Router (`app/` directory)
59
+ - **A DeepL API key** — [sign up for free](https://www.deepl.com/pro-api) (500,000 characters/month at no cost)
60
+
61
+ ---
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ # Run directly without installing (recommended)
67
+ npx next-auto-i18n init
68
+
69
+ # Or install globally
70
+ npm install -g next-auto-i18n
71
+ next-auto-i18n init
72
+
73
+ # Or as a dev dependency
74
+ npm install -D next-auto-i18n
75
+ npx next-auto-i18n init
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Quick Start
81
+
82
+ ### 1. Run the init command
83
+
84
+ ```bash
85
+ npx next-auto-i18n init
86
+ ```
87
+
88
+ ### 2. Answer the prompts
89
+
90
+ ```
91
+ ▸ Configuration
92
+ ? Source locale (ISO code): fr
93
+ ? Target locales (comma-separated): en, es
94
+ ? DeepL API key: ********
95
+ ✓ API key saved to .env.local
96
+ ✓ .gitignore updated (.env.local, *.backup)
97
+ ✓ auto-i18n.config.json created
98
+ ```
99
+
100
+ ### 3. Watch it work
101
+
102
+ ```
103
+ ▸ Scanning project
104
+ ✓ 47 strings found
105
+
106
+ ▸ Generating keys
107
+ ✓ 42 keys generated → ./messages/fr.json
108
+
109
+ ▸ Translating via DeepL
110
+ ✓ Translation EN (42 strings)
111
+ ✓ Translation ES (42 strings)
112
+ ✓ 84 strings translated
113
+
114
+ ▸ Rewriting components
115
+ ✓ 47 replacements in 12 files
116
+
117
+ ▸ Configuring Next.js
118
+ ✓ layout.tsx configured
119
+ ✓ next.config configured
120
+ ✓ middleware.ts created
121
+ ✓ i18n/routing.ts created
122
+
123
+ ✓ Internationalization configured successfully!
124
+ Languages: fr → en, es
125
+ Backups available in *.backup
126
+ ```
127
+
128
+ ### 4. Start your app
129
+
130
+ ```bash
131
+ npm run dev
132
+ ```
133
+
134
+ Your site now supports `fr`, `en`, and `es`. Visit `/en` or `/es` to see the translations.
135
+
136
+ ---
137
+
138
+ ## Configuration
139
+
140
+ ### auto-i18n.config.json
141
+
142
+ Generated automatically by `next-auto-i18n init`. This file is safe to commit.
143
+
144
+ ```json
145
+ {
146
+ "sourceLocale": "fr",
147
+ "targetLocales": ["en", "es"],
148
+ "provider": "deepl",
149
+ "apiKeyEnv": "AUTO_I18N_DEEPL_KEY",
150
+ "messagesDir": "./messages",
151
+ "ignore": ["node_modules", ".next", "**/*.test.*", "**/*.spec.*"]
152
+ }
153
+ ```
154
+
155
+ | Field | Type | Default | Description |
156
+ |-------|------|---------|-------------|
157
+ | `sourceLocale` | `string` | — | ISO code of your source language (e.g. `"fr"`) |
158
+ | `targetLocales` | `string[]` | — | List of target language codes (e.g. `["en", "es"]`) |
159
+ | `provider` | `string` | `"deepl"` | Translation provider |
160
+ | `apiKeyEnv` | `string` | `"AUTO_I18N_DEEPL_KEY"` | Name of the environment variable holding the API key |
161
+ | `messagesDir` | `string` | `"./messages"` | Directory where JSON translation files are stored |
162
+ | `ignore` | `string[]` | `["node_modules", ".next", "**/*.test.*", "**/*.spec.*"]` | Glob patterns of files/directories to skip |
163
+
164
+ ### .env.local
165
+
166
+ The DeepL API key is stored in `.env.local` and **never** in the config file.
167
+
168
+ ```bash
169
+ # .env.local (auto-generated, never committed)
170
+ AUTO_I18N_DEEPL_KEY=your-deepl-api-key-here
171
+ ```
172
+
173
+ next-auto-i18n automatically adds `.env.local` and `*.backup` to your `.gitignore`.
174
+
175
+ ---
176
+
177
+ ## Commands
178
+
179
+ ### `next-auto-i18n init`
180
+
181
+ Full project initialization: scan, translate, rewrite, and configure.
182
+
183
+ ```bash
184
+ next-auto-i18n init # Interactive mode
185
+ next-auto-i18n init --dry-run # Preview changes, ask before applying
186
+ next-auto-i18n init --locale en,es,de # Skip locale prompt
187
+ ```
188
+
189
+ | Flag | Description |
190
+ |------|-------------|
191
+ | `--dry-run` | Scans and generates keys, then shows a summary and asks for confirmation before translating, rewriting, or modifying config files |
192
+ | `--locale <locales>` | Comma-separated target locales, skips the interactive prompt |
193
+
194
+ **Example output with `--dry-run`:**
195
+
196
+ ```
197
+ ▸ Scanning project
198
+ ✓ 47 strings found
199
+
200
+ ▸ Generating keys
201
+ ✓ 42 keys generated → ./messages/fr.json
202
+
203
+ Strings found: 47
204
+ Keys generated: 42
205
+ Files to rewrite: 12
206
+ Target locales: en, es
207
+
208
+ ? Apply these changes? (Y/n)
209
+ ```
210
+
211
+ ---
212
+
213
+ ### `next-auto-i18n sync`
214
+
215
+ Re-scans the project and translates only new or modified strings. Existing translations are preserved.
216
+
217
+ ```bash
218
+ next-auto-i18n sync
219
+ ```
220
+
221
+ **Example output:**
222
+
223
+ ```
224
+ ▸ Scanning project
225
+ ✓ 53 strings found
226
+
227
+ ▸ Updating keys
228
+ ✓ 48 keys → ./messages/fr.json
229
+
230
+ ▸ Incremental translation
231
+ ✓ Translation EN (6 strings)
232
+ ✓ Translation ES (6 strings)
233
+ ✓ 12 new translations
234
+ ```
235
+
236
+ Use `sync` after adding new components, changing text, or removing strings.
237
+
238
+ ---
239
+
240
+ ### `next-auto-i18n add-locale <locale>`
241
+
242
+ Adds a new target language and translates all existing keys into it.
243
+
244
+ ```bash
245
+ next-auto-i18n add-locale ar
246
+ next-auto-i18n add-locale pt-BR
247
+ next-auto-i18n add-locale zh
248
+ ```
249
+
250
+ **Example output:**
251
+
252
+ ```
253
+ ✓ ar added to auto-i18n.config.json
254
+
255
+ ▸ Translating to AR
256
+ ✓ Translation AR (42 strings)
257
+ ✓ 42 strings translated
258
+ ```
259
+
260
+ ---
261
+
262
+ ### `next-auto-i18n missing`
263
+
264
+ Reports untranslated keys per target locale.
265
+
266
+ ```bash
267
+ next-auto-i18n missing
268
+ ```
269
+
270
+ **Example output:**
271
+
272
+ ```
273
+ ✓ en — complete
274
+ ⚠ es — 3 missing keys
275
+ new_feature_title
276
+ new_feature_description
277
+ cta_button
278
+ ✓ de — complete
279
+
280
+ ℹ 3 missing keys total
281
+ Run "next-auto-i18n sync" to translate them.
282
+ ```
283
+
284
+ ---
285
+
286
+ ## How It Works
287
+
288
+ ```
289
+ npx next-auto-i18n init
290
+
291
+
292
+ ┌──────────────────────────────────────┐
293
+ │ 1. Interactive Configuration │
294
+ │ Source locale, targets, API key │
295
+ │ → auto-i18n.config.json │
296
+ │ → .env.local │
297
+ └──────────────────────────────────────┘
298
+
299
+
300
+ ┌──────────────────────────────────────┐
301
+ │ 2. AST Scan │
302
+ │ Parses .tsx/.jsx/.ts/.js files │
303
+ │ Extracts 3 types of strings: │
304
+ │ • JSX text: <p>Hello</p> │
305
+ │ • Attributes: placeholder="..." │
306
+ │ • Template literals: `Hello` │
307
+ └──────────────────────────────────────┘
308
+
309
+
310
+ ┌──────────────────────────────────────┐
311
+ │ 3. Key Generation │
312
+ │ messages/fr.json │
313
+ │ { "hello": "Bonjour", │
314
+ │ "welcome_name": "Bienvenue {name}" } │
315
+ └──────────────────────────────────────┘
316
+
317
+
318
+ ┌──────────────────────────────────────┐
319
+ │ 4. DeepL Translation │
320
+ │ messages/en.json │
321
+ │ messages/es.json │
322
+ │ Batched, placeholder-safe │
323
+ └──────────────────────────────────────┘
324
+
325
+
326
+ ┌──────────────────────────────────────┐
327
+ │ 5. Component Rewriting │
328
+ │ <p>Bonjour</p> │
329
+ │ → <p>{t("hello")}</p> │
330
+ │ │
331
+ │ + useTranslations / getTranslations │
332
+ │ + import statements │
333
+ └──────────────────────────────────────┘
334
+
335
+
336
+ ┌──────────────────────────────────────┐
337
+ │ 6. Next.js Config Injection │
338
+ │ • layout.tsx → NextIntlClientProvider │
339
+ │ • next.config → createNextIntlPlugin │
340
+ │ • middleware.ts → routing │
341
+ │ • i18n/routing.ts → locale definitions │
342
+ └──────────────────────────────────────┘
343
+
344
+
345
+ ✓ i18n-ready site
346
+ ```
347
+
348
+ ### AST Scanning
349
+
350
+ The scanner uses [ts-morph](https://ts-morph.com/) to parse TypeScript/JSX via AST (Abstract Syntax Tree). This means it understands your code structure, not just raw text.
351
+
352
+ **What gets detected:**
353
+
354
+ - JSX text content: `<h1>Welcome</h1>`
355
+ - Translatable HTML attributes: `placeholder`, `alt`, `title`, `aria-label`, `aria-placeholder`, `aria-description`, `aria-details`, `label`, `content`
356
+ - Static template literals: `` `Hello world` ``
357
+ - Dynamic template literals: `` `Hello ${name}` `` (converted to `t("key", { name })`)
358
+
359
+ **What gets ignored automatically:**
360
+
361
+ - Technical strings: CSS classes, hex colors, URLs, routes, MIME types, env vars
362
+ - Technical attributes: `className`, `id`, `type`, `href`, `src`, `key`, `style`, etc.
363
+ - Technical keywords: CSS values (`flex`, `grid`, `bold`...), HTTP methods, HTML input types, boolean values, encoding names
364
+ - Short/numeric strings: empty strings, pure numbers, single characters
365
+ - Config files: `next.config.*`, `tailwind.config.*`, `vite.config.*`, etc.
366
+ - Test files: `*.test.*`, `*.spec.*`
367
+ - Directories: `node_modules`, `.next`, `.git`, `dist`, `build`, `out`, `coverage`, `public`
368
+
369
+ ### API Key Security
370
+
371
+ - The DeepL API key is **never** stored in config files or source code
372
+ - It lives exclusively in `.env.local`, which is automatically added to `.gitignore`
373
+ - The config file only stores the **name** of the environment variable (`AUTO_I18N_DEEPL_KEY`), not the value
374
+
375
+ ---
376
+
377
+ ## Supported String Types
378
+
379
+ ### JSX Text
380
+
381
+ ```tsx
382
+ // Before
383
+ <h1>Bienvenue sur notre site</h1>
384
+ <p>Découvrez nos produits</p>
385
+
386
+ // After
387
+ <h1>{t("bienvenue_sur_notre_site")}</h1>
388
+ <p>{t("decouvrez_nos_produits")}</p>
389
+ ```
390
+
391
+ ### HTML Attributes
392
+
393
+ ```tsx
394
+ // Before
395
+ <input placeholder="Rechercher un produit" />
396
+ <img alt="Photo de profil" />
397
+ <button title="Fermer la fenêtre">X</button>
398
+ <div aria-label="Menu principal">...</div>
399
+
400
+ // After
401
+ <input placeholder={t("rechercher_un_produit")} />
402
+ <img alt={t("photo_de_profil")} />
403
+ <button title={t("fermer_la_fenetre")}>X</button>
404
+ <div aria-label={t("menu_principal")}>...</div>
405
+ ```
406
+
407
+ **Supported attributes:** `placeholder`, `alt`, `title`, `aria-label`, `aria-placeholder`, `aria-description`, `aria-details`, `label`, `content`
408
+
409
+ ### Static Template Literals
410
+
411
+ ```tsx
412
+ // Before
413
+ const greeting = `Bonjour le monde`;
414
+
415
+ // After
416
+ const greeting = t("bonjour_le_monde");
417
+ ```
418
+
419
+ ### Dynamic Template Literals
420
+
421
+ ```tsx
422
+ // Before
423
+ const message = `Bienvenue ${userName}, vous avez ${count} messages`;
424
+
425
+ // After
426
+ const message = t("bienvenue_username_vous_avez_count", { userName, count });
427
+ ```
428
+
429
+ The corresponding JSON entry uses ICU-style placeholders:
430
+
431
+ ```json
432
+ {
433
+ "bienvenue_username_vous_avez_count": "Bienvenue {userName}, vous avez {count} messages"
434
+ }
435
+ ```
436
+
437
+ ### Server Components vs Client Components
438
+
439
+ next-auto-i18n automatically detects whether a file is a Server Component or a Client Component:
440
+
441
+ **Server Components** (no `'use client'` directive):
442
+
443
+ ```tsx
444
+ import { getTranslations } from "next-intl/server";
445
+
446
+ export default async function Page() {
447
+ const t = await getTranslations();
448
+ return <h1>{t("hello")}</h1>;
449
+ }
450
+ ```
451
+
452
+ **Client Components** (has `'use client'` directive):
453
+
454
+ ```tsx
455
+ "use client";
456
+ import { useTranslations } from "next-intl";
457
+
458
+ export default function Button() {
459
+ const t = useTranslations();
460
+ return <button>{t("submit")}</button>;
461
+ }
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Safety & Backups
467
+
468
+ ### `--dry-run` mode
469
+
470
+ Preview everything next-auto-i18n will do before it makes any changes:
471
+
472
+ ```bash
473
+ next-auto-i18n init --dry-run
474
+ ```
475
+
476
+ In dry-run mode, the tool:
477
+ 1. Scans your project and extracts strings
478
+ 2. Generates keys and shows a summary
479
+ 3. Asks for your confirmation before proceeding
480
+ 4. Only applies changes if you confirm
481
+
482
+ ### Automatic backups
483
+
484
+ Before modifying any file, next-auto-i18n creates a `.backup` copy:
485
+
486
+ ```
487
+ app/layout.tsx → app/layout.tsx.backup
488
+ app/page.tsx → app/page.tsx.backup
489
+ next.config.ts → next.config.ts.backup
490
+ ```
491
+
492
+ ### Restoring from backup
493
+
494
+ To revert a single file:
495
+
496
+ ```bash
497
+ cp app/page.tsx.backup app/page.tsx
498
+ ```
499
+
500
+ To revert all changes:
501
+
502
+ ```bash
503
+ # Restore all backup files
504
+ for f in $(find . -name "*.backup" -not -path "*/node_modules/*"); do
505
+ cp "$f" "${f%.backup}"
506
+ done
507
+ ```
508
+
509
+ To clean up backup files after you're satisfied:
510
+
511
+ ```bash
512
+ find . -name "*.backup" -not -path "*/node_modules/*" -delete
513
+ ```
514
+
515
+ ### Idempotency
516
+
517
+ All operations are idempotent. Running `next-auto-i18n init` twice will not duplicate imports, providers, or configuration. The tool detects what's already in place and skips it.
518
+
519
+ ---
520
+
521
+ ## DeepL API
522
+
523
+ ### Getting a free API key
524
+
525
+ 1. Go to [deepl.com/pro-api](https://www.deepl.com/pro-api)
526
+ 2. Sign up for a **DeepL API Free** account
527
+ 3. Copy your API key from the account dashboard
528
+
529
+ ### Free plan limits
530
+
531
+ | | DeepL API Free | DeepL API Pro |
532
+ |---|---|---|
533
+ | Characters/month | 500,000 | Unlimited (pay-per-use) |
534
+ | Cost | Free | $5.49/million characters |
535
+ | API endpoint | `api-free.deepl.com` | `api.deepl.com` |
536
+
537
+ 500,000 characters is enough for most projects. A medium-sized Next.js app typically has 5,000-20,000 characters of translatable text.
538
+
539
+ next-auto-i18n automatically detects whether your key is Free (ends with `:fx`) or Pro and uses the correct endpoint.
540
+
541
+ ### Storing the API key
542
+
543
+ The API key is stored in `.env.local` and loaded via `dotenv`:
544
+
545
+ ```bash
546
+ # .env.local
547
+ AUTO_I18N_DEEPL_KEY=your-api-key-here
548
+ ```
549
+
550
+ You can also set it as a system environment variable:
551
+
552
+ ```bash
553
+ export AUTO_I18N_DEEPL_KEY=your-api-key-here
554
+ next-auto-i18n init
555
+ ```
556
+
557
+ ### Placeholder protection
558
+
559
+ Dynamic strings containing variables like `{name}` are protected during translation using XML tags. DeepL preserves XML tags in output, ensuring placeholders are never translated:
560
+
561
+ ```
562
+ Input: "Bienvenue <x>name</x>"
563
+ Output: "Welcome <x>name</x>"
564
+ → Restored: "Welcome {name}"
565
+ ```
566
+
567
+ ---
568
+
569
+ ## Troubleshooting
570
+
571
+ ### "Invalid or unauthorized API key" (403)
572
+
573
+ Your DeepL API key is invalid or expired.
574
+
575
+ ```
576
+ ✗ DeepL API error (403): clé API invalide ou non autorisée
577
+ ```
578
+
579
+ **Fix:** Verify your key at [deepl.com/your-account/keys](https://www.deepl.com/your-account/keys) and update `.env.local`:
580
+
581
+ ```bash
582
+ # .env.local
583
+ AUTO_I18N_DEEPL_KEY=your-correct-key-here
584
+ ```
585
+
586
+ ---
587
+
588
+ ### "Quota exceeded" (456)
589
+
590
+ You've used all 500,000 free characters for the current month.
591
+
592
+ ```
593
+ ✗ DeepL API error (456): quota de traduction dépassé
594
+ ```
595
+
596
+ **Fix:** Wait for the monthly reset, upgrade to DeepL Pro, or reduce the scope by translating fewer locales at once.
597
+
598
+ ---
599
+
600
+ ### "No translatable strings found"
601
+
602
+ The scanner found no strings in your project.
603
+
604
+ ```
605
+ ⚠ No translatable string found — stopping
606
+ ```
607
+
608
+ **Fix:** Make sure your components contain actual text (not just variables or technical strings). Check that your source files are in `app/` or `src/app/` and use `.tsx`, `.jsx`, `.ts`, or `.js` extensions.
609
+
610
+ ---
611
+
612
+ ### "layout.tsx not found"
613
+
614
+ The injector can't find your root layout file.
615
+
616
+ ```
617
+ ⚠ layout.tsx — layout.tsx introuvable
618
+ ```
619
+
620
+ **Fix:** Ensure you have `app/layout.tsx` or `src/app/layout.tsx` in your project. next-auto-i18n checks both locations.
621
+
622
+ ---
623
+
624
+ ### "auto-i18n.config.json not found"
625
+
626
+ You're running `sync`, `add-locale`, or `missing` before `init`.
627
+
628
+ ```
629
+ ✗ ENOENT: no such file or directory, open 'auto-i18n.config.json'
630
+ ```
631
+
632
+ **Fix:** Run `next-auto-i18n init` first to generate the config file.
633
+
634
+ ---
635
+
636
+ ### "Too many requests" (429)
637
+
638
+ DeepL rate limit reached.
639
+
640
+ ```
641
+ ✗ DeepL API error (429): trop de requêtes
642
+ ```
643
+
644
+ **Fix:** Wait a few seconds and retry. next-auto-i18n sends translations in batches of 50 strings to minimize this, but it can still occur with very large projects. Simply re-run the command.
645
+
646
+ ---
647
+
648
+ ## Contributing
649
+
650
+ ### Setup
651
+
652
+ ```bash
653
+ git clone https://github.com/stevenkoulo/next-auto-i18n.git
654
+ cd next-auto-i18n
655
+ npm install
656
+ ```
657
+
658
+ ### Development
659
+
660
+ ```bash
661
+ # Run the CLI in dev mode (no build needed)
662
+ npm run dev -- init --dry-run
663
+
664
+ # Build
665
+ npm run build
666
+
667
+ # Run tests
668
+ npm test
669
+
670
+ # Run tests in watch mode
671
+ npx vitest
672
+ ```
673
+
674
+ ### Project structure
675
+
676
+ ```
677
+ next-auto-i18n/
678
+ ├── src/
679
+ │ ├── cli/ # CLI entry point + interactive prompts
680
+ │ ├── scanner/ # AST parsing + string extraction + filtering
681
+ │ ├── generator/ # Key generation + JSON file creation
682
+ │ ├── translator/ # DeepL API client + translation orchestration
683
+ │ ├── rewriter/ # JSX/attribute rewriting via AST
684
+ │ ├── injector/ # Next.js config injection (layout, config, middleware, routing)
685
+ │ └── utils/ # Config, env, logger utilities
686
+ ├── tests/ # Vitest test suites (298 tests)
687
+ ├── auto-i18n-specs.md # Project specifications
688
+ └── DOCUMENTATION.md # This file
689
+ ```
690
+
691
+ ### Running tests
692
+
693
+ ```bash
694
+ npm test
695
+ ```
696
+
697
+ The test suite covers all modules:
698
+
699
+ | Module | Tests |
700
+ |--------|-------|
701
+ | Scanner (filters) | 109 |
702
+ | Generator (key-builder) | 39 |
703
+ | Rewriter | 33 |
704
+ | Injector | 25 |
705
+ | Translator (DeepL) | 23 |
706
+ | Generator | 20 |
707
+ | Scanner (string-extractor) | 20 |
708
+ | CLI (config, env) | 18 |
709
+ | Translator (orchestration) | 11 |
710
+ | **Total** | **298** |
711
+
712
+ ### Submitting changes
713
+
714
+ 1. Fork the repository
715
+ 2. Create a feature branch: `git checkout -b feature/my-feature`
716
+ 3. Write tests for your changes
717
+ 4. Ensure all tests pass: `npm test`
718
+ 5. Ensure the build succeeds: `npm run build`
719
+ 6. Submit a Pull Request
720
+
721
+ ---
722
+
723
+ ## Roadmap
724
+
725
+ ### v1.x — Enhancements
726
+
727
+ - [ ] `next-auto-i18n sync` — rescan and incremental update *(done)*
728
+ - [ ] `next-auto-i18n missing` — report untranslated keys *(done)*
729
+ - [ ] `--watch` mode — auto-sync on file changes
730
+ - [ ] Support for Vite + React (without Next.js)
731
+ - [ ] Custom key naming strategies
732
+
733
+ ### v2.0 — Multi-provider support
734
+
735
+ - [ ] OpenAI (GPT-4) as translation provider
736
+ - [ ] Google Cloud Translation API
737
+ - [ ] Configurable provider via `auto-i18n.config.json`
738
+
739
+ ### v3.0 — Ecosystem
740
+
741
+ - [ ] Web dashboard for team translation management
742
+ - [ ] CI/CD integration (GitHub Actions)
743
+ - [ ] Public API for programmatic access
744
+
745
+ ---
746
+
747
+ ## License
748
+
749
+ [MIT](./LICENSE) — Steven KOULO