next-auto-i18n 0.7.2 → 0.8.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 (92) hide show
  1. package/DOCUMENTATION.md +86 -37
  2. package/README.md +141 -115
  3. package/dist/cli/doc-generator.d.ts +1 -2
  4. package/dist/cli/doc-generator.d.ts.map +1 -1
  5. package/dist/cli/doc-generator.js +0 -11
  6. package/dist/cli/doc-generator.js.map +1 -1
  7. package/dist/cli/index.js +184 -320
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/engine/analysis.d.ts +10 -0
  10. package/dist/engine/analysis.d.ts.map +1 -0
  11. package/dist/engine/analysis.js +139 -0
  12. package/dist/engine/analysis.js.map +1 -0
  13. package/dist/engine/apply.d.ts +11 -0
  14. package/dist/engine/apply.d.ts.map +1 -0
  15. package/dist/engine/apply.js +265 -0
  16. package/dist/engine/apply.js.map +1 -0
  17. package/dist/engine/index.d.ts +6 -0
  18. package/dist/engine/index.d.ts.map +1 -0
  19. package/dist/engine/index.js +6 -0
  20. package/dist/engine/index.js.map +1 -0
  21. package/dist/engine/planning.d.ts +24 -0
  22. package/dist/engine/planning.d.ts.map +1 -0
  23. package/dist/engine/planning.js +192 -0
  24. package/dist/engine/planning.js.map +1 -0
  25. package/dist/engine/report.d.ts +6 -0
  26. package/dist/engine/report.d.ts.map +1 -0
  27. package/dist/engine/report.js +132 -0
  28. package/dist/engine/report.js.map +1 -0
  29. package/dist/engine/types.d.ts +104 -0
  30. package/dist/engine/types.d.ts.map +1 -0
  31. package/dist/engine/types.js +2 -0
  32. package/dist/engine/types.js.map +1 -0
  33. package/dist/generator/index.d.ts +7 -17
  34. package/dist/generator/index.d.ts.map +1 -1
  35. package/dist/generator/index.js +13 -14
  36. package/dist/generator/index.js.map +1 -1
  37. package/dist/injector/layout-injector.d.ts +0 -1
  38. package/dist/injector/layout-injector.d.ts.map +1 -1
  39. package/dist/injector/layout-injector.js +0 -1
  40. package/dist/injector/layout-injector.js.map +1 -1
  41. package/dist/injector/locale-structure-injector.d.ts +0 -4
  42. package/dist/injector/locale-structure-injector.d.ts.map +1 -1
  43. package/dist/injector/locale-structure-injector.js +34 -64
  44. package/dist/injector/locale-structure-injector.js.map +1 -1
  45. package/dist/injector/middleware-injector.d.ts.map +1 -1
  46. package/dist/injector/middleware-injector.js +0 -6
  47. package/dist/injector/middleware-injector.js.map +1 -1
  48. package/dist/injector/request-injector.d.ts.map +1 -1
  49. package/dist/injector/request-injector.js +0 -2
  50. package/dist/injector/request-injector.js.map +1 -1
  51. package/dist/injector/routing-injector.d.ts.map +1 -1
  52. package/dist/injector/routing-injector.js +0 -2
  53. package/dist/injector/routing-injector.js.map +1 -1
  54. package/dist/rewriter/const-rewriter.d.ts.map +1 -1
  55. package/dist/rewriter/const-rewriter.js +0 -8
  56. package/dist/rewriter/const-rewriter.js.map +1 -1
  57. package/dist/rewriter/index.d.ts +0 -12
  58. package/dist/rewriter/index.d.ts.map +1 -1
  59. package/dist/rewriter/index.js +0 -10
  60. package/dist/rewriter/index.js.map +1 -1
  61. package/dist/rewriter/jsx-rewriter.d.ts +7 -10
  62. package/dist/rewriter/jsx-rewriter.d.ts.map +1 -1
  63. package/dist/rewriter/jsx-rewriter.js +66 -18
  64. package/dist/rewriter/jsx-rewriter.js.map +1 -1
  65. package/dist/scanner/ast-parser.d.ts +0 -1
  66. package/dist/scanner/ast-parser.d.ts.map +1 -1
  67. package/dist/scanner/ast-parser.js +0 -1
  68. package/dist/scanner/ast-parser.js.map +1 -1
  69. package/dist/scanner/filters.d.ts +2 -0
  70. package/dist/scanner/filters.d.ts.map +1 -1
  71. package/dist/scanner/filters.js +23 -20
  72. package/dist/scanner/filters.js.map +1 -1
  73. package/dist/scanner/index.d.ts +17 -2
  74. package/dist/scanner/index.d.ts.map +1 -1
  75. package/dist/scanner/index.js +28 -11
  76. package/dist/scanner/index.js.map +1 -1
  77. package/dist/scanner/string-extractor.d.ts +7 -1
  78. package/dist/scanner/string-extractor.d.ts.map +1 -1
  79. package/dist/scanner/string-extractor.js +3 -19
  80. package/dist/scanner/string-extractor.js.map +1 -1
  81. package/dist/translator/deepl.d.ts.map +1 -1
  82. package/dist/translator/deepl.js +0 -1
  83. package/dist/translator/deepl.js.map +1 -1
  84. package/dist/translator/index.d.ts +2 -0
  85. package/dist/translator/index.d.ts.map +1 -1
  86. package/dist/translator/index.js +37 -6
  87. package/dist/translator/index.js.map +1 -1
  88. package/dist/translator/provider.d.ts +5 -0
  89. package/dist/translator/provider.d.ts.map +1 -0
  90. package/dist/translator/provider.js +25 -0
  91. package/dist/translator/provider.js.map +1 -0
  92. package/package.json +1 -1
package/DOCUMENTATION.md CHANGED
@@ -8,15 +8,18 @@
8
8
  <a href="https://github.com/stvekoulo/next-auto-i18n/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/next-auto-i18n" alt="license"></a>
9
9
  </p>
10
10
 
11
- <p align="center"><strong>Translate your Next.js project automatically in under 5 minutes.</strong></p>
11
+ <p align="center"><strong>Conservative i18n automation for Next.js App Router projects.</strong></p>
12
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.
13
+ > This document complements the README. The README is the shortest source of truth for public guarantees. When behavior differs between examples and real project constraints, the engine always prefers safe refusal or manual guidance over risky mutation.
14
+
15
+ next-auto-i18n is a CLI tool for existing Next.js projects. It scans the codebase via AST, extracts translatable strings, translates them through DeepL, rewrites safe cases automatically, and applies conservative `next-intl` injection when the project structure is compatible.
14
16
 
15
17
  ---
16
18
 
17
19
  ## Table of Contents
18
20
 
19
21
  - [Why next-auto-i18n?](#why-next-auto-i18n)
22
+ - [Compatibility Matrix](#compatibility-matrix)
20
23
  - [Prerequisites](#prerequisites)
21
24
  - [Installation](#installation)
22
25
  - [Quick Start](#quick-start)
@@ -34,6 +37,49 @@ next-auto-i18n is a CLI tool that fully automates internationalization (i18n) in
34
37
 
35
38
  ---
36
39
 
40
+ ## Compatibility Matrix
41
+
42
+ ### Project structure
43
+
44
+ | Target | Status | Notes |
45
+ |---|---|---|
46
+ | `app/` | Supported | Primary target |
47
+ | `src/app/` | Supported | Scanner and injectors handle both roots |
48
+ | `components/`, `ui/`, `features/`, `shared/` | Supported for scan | Included in the default scan scope |
49
+ | custom monorepo layouts | Partial | Depends on actual source tree and ignore rules |
50
+
51
+ ### Rewriting behavior
52
+
53
+ | Case | Status | Behavior |
54
+ |---|---|---|
55
+ | simple JSX text | Supported | auto rewrite |
56
+ | supported JSX attributes | Supported | auto rewrite |
57
+ | template literals | Supported | generated key + rewrite when safe |
58
+ | module-scope strings | Partial | translated, but often manual integration |
59
+ | ambiguous JSX spacing | Conservative | skipped with diagnostics |
60
+ | unparseable source file | Blocked | file skipped, warning emitted |
61
+
62
+ ### Next.js injection
63
+
64
+ | Target | Status | Behavior |
65
+ |---|---|---|
66
+ | `next.config.*` | Supported | inject if compatible, otherwise block |
67
+ | `middleware.ts` / `proxy.ts` | Supported | created or skipped if already present |
68
+ | `i18n/routing.ts` | Supported | created or skipped |
69
+ | `i18n/request.ts` | Supported | created or skipped |
70
+ | `LanguageSwitcher` | Supported | can be injected independently |
71
+ | `app/[locale]/` restructuring | Conservative | refused on complex root layouts |
72
+
73
+ ### Runtime guarantees
74
+
75
+ | Situation | Outcome |
76
+ |---|---|
77
+ | safe project shape | full or near-full automation |
78
+ | mixed safe and unsafe operations | partial run with explicit manual actions |
79
+ | risky mutation candidate | skipped instead of forced |
80
+
81
+ ---
82
+
37
83
  ## Why next-auto-i18n?
38
84
 
39
85
  ### Manual setup vs next-auto-i18n
@@ -273,28 +319,37 @@ next-auto-i18n add-locale zh
273
319
 
274
320
  ### `next-auto-i18n extract`
275
321
 
276
- Scans the project, translates all strings, and generates a Markdown integration guide — **without modifying any source file**. Use this command when you want to keep full control over the integration process.
322
+ Scans the project, translates all strings, and generates a Markdown integration guide — **without modifying any source file**.
277
323
 
278
324
  ```bash
279
- next-auto-i18n extract # Interactive (asks locale if no config)
280
- next-auto-i18n extract --locale en,es # Skip locale prompt
281
- next-auto-i18n extract --out docs/i18n-guide.md # Custom output path
325
+ next-auto-i18n extract # Interactive (asks locale if no config)
326
+ next-auto-i18n extract --locale en,es # Skip locale prompt
327
+ next-auto-i18n extract --out docs/i18n-guide.md # Custom output path
328
+ next-auto-i18n extract --inject # Also configure Next.js after extraction
329
+ next-auto-i18n extract --switcher # Inject only the Language Switcher widget
330
+ next-auto-i18n extract --no-module-scope # Exclude module-scope const strings entirely
282
331
  ```
283
332
 
284
333
  | Flag | Description |
285
334
  |------|-------------|
286
- | `--locale <locales>` | Comma-separated target locales (used if no `auto-i18n.config.json` exists) |
335
+ | `--locale <locales>` | Comma-separated target locales (used if no config file exists) |
287
336
  | `--out <path>` | Output path for the Markdown guide (default: `i18n-guide.md`) |
337
+ | `--inject` | Runs the full Next.js setup after translation: `next.config`, `middleware.ts`, `i18n/routing.ts`, `i18n/request.ts`, `app/[locale]/` structure, Language Switcher |
338
+ | `--switcher` | Injects only the floating Language Switcher component (without `--inject`) |
339
+ | `--no-module-scope` | Excludes strings declared inside module-scope `const` from detection and translation |
288
340
 
289
341
  **What it does:**
290
342
 
291
343
  1. Scans your project for translatable strings (same AST engine as `init`)
292
- 2. Generates/updates `messages/<sourceLocale>.json` with stable key merge
293
- 3. Translates to all target locales via DeepL (incremental — only new strings)
294
- 4. Detects module-scope strings that require manual integration
295
- 5. Generates `i18n-guide.md` with full integration instructions
344
+ 2. *(if `--no-module-scope`)* Detects and filters out module-scope strings before key generation
345
+ 3. Generates/updates `messages/<sourceLocale>.json` with stable key merge
346
+ 4. Translates to all target locales via DeepL (incremental — only new strings)
347
+ 5. Detects module-scope strings that require manual integration (unless `--no-module-scope`)
348
+ 6. *(if `--inject`)* Configures the full Next.js i18n infrastructure
349
+ 7. *(if `--switcher`)* Injects the Language Switcher component
350
+ 8. Generates `i18n-guide.md` with full integration instructions
296
351
 
297
- **What it does NOT do:** modify any `.tsx`/`.ts`/`.jsx`/`.js` source file.
352
+ **What it never does:** modify any `.tsx`/`.ts`/`.jsx`/`.js` source file.
298
353
 
299
354
  **Generated guide contents:**
300
355
 
@@ -302,38 +357,29 @@ next-auto-i18n extract --out docs/i18n-guide.md # Custom output path
302
357
  - List of generated translation files
303
358
  - Usage examples (Client Component with `useTranslations`, Server Component with `getTranslations`)
304
359
  - Module-scope strings section with before/after code examples
305
- - Per-file string tables with line number, type, original text, key, and replacement code
360
+ - Per-file tables: line number, type, original text, key, ready-to-paste replacement code
306
361
  - Complete key reference table
307
362
 
308
- **Example output:**
309
-
310
- ```
311
- ▸ Configuration
312
- ✓ Configuration chargée (fr → en, es)
313
-
314
- ▸ Scan du projet
315
- ✓ 47 strings trouvées dans 12 fichiers
316
- components/Hero.tsx 8 strings
317
- components/Navbar.tsx 5 strings
318
- ...
363
+ ---
319
364
 
320
- Génération des clés
321
- ✓ 42 clés → ./messages/fr.json
365
+ ### `next-auto-i18n extract sync`
322
366
 
323
- Traduction via DeepL
324
- ✓ 84 strings traduites
325
- ./messages/en.json
326
- ./messages/es.json
367
+ Sub-command of `extract`. Rescans the project, integrates new strings, and synchronises translations — **without rewriting source files**. Uses the same stable key merge as `sync`.
327
368
 
328
- ▸ Analyse du code source
329
- 3 strings module-scope détectées (action manuelle requise — voir guide)
369
+ ```bash
370
+ next-auto-i18n extract sync # Rescan + update JSON + translate
371
+ next-auto-i18n extract sync --inject # + configure Next.js after sync
372
+ next-auto-i18n extract sync --switcher # + inject the Language Switcher
373
+ next-auto-i18n extract sync --no-module-scope # Exclude module-scope strings
374
+ ```
330
375
 
331
- Génération du guide
332
- ✓ Guide généré : i18n-guide.md
376
+ | Flag | Description |
377
+ |------|-------------|
378
+ | `--inject` | Runs full Next.js setup after synchronisation |
379
+ | `--switcher` | Injects only the Language Switcher component |
380
+ | `--no-module-scope` | Excludes module-scope strings from detection and translation |
333
381
 
334
- Extraction terminée aucun fichier source modifié
335
- Consultez le guide pour intégrer les traductions manuellement.
336
- ```
382
+ Requires an existing `auto-i18n.config.json` and `messages/<sourceLocale>.json` (run `init` or `extract` first).
337
383
 
338
384
  ---
339
385
 
@@ -953,6 +999,9 @@ The test suite covers all modules:
953
999
  - [x] `next-auto-i18n sync` — rescan and incremental update (stable key merge)
954
1000
  - [x] `next-auto-i18n missing` — report untranslated keys
955
1001
  - [x] `next-auto-i18n extract` — translate + generate guide without touching source
1002
+ - [x] `next-auto-i18n extract sync` — incremental sync without source rewrite
1003
+ - [x] `--inject` / `--switcher` options on `extract` and `extract sync`
1004
+ - [x] `--no-module-scope` option to exclude const module-scope strings
956
1005
  - [x] Floating language switcher widget (auto-injected, customizable)
957
1006
  - [x] Automatic `next-intl` dependency installation
958
1007
  - [x] `app/[locale]/` structure auto-creation (required by next-intl App Router)
package/README.md CHANGED
@@ -4,70 +4,89 @@
4
4
  ![npm downloads](https://img.shields.io/npm/dm/next-auto-i18n)
5
5
  ![license](https://img.shields.io/npm/l/next-auto-i18n)
6
6
 
7
- > Automatise l'internationalisation d'un projet React / Next.js en une seule commande.
7
+ > CLI d’internationalisation pour projets Next.js App Router, avec scan AST, génération de messages, traduction DeepL, réécriture prudente et injection `next-intl`.
8
8
 
9
- **next-auto-i18n** scanne votre code, extrait les strings traduisibles, les traduit via DeepL, et reconfigure votre projet pour utiliser [next-intl](https://next-intl-docs.vercel.app/) sans intervention manuelle.
9
+ `next-auto-i18n` scanne votre code, extrait les strings traduisibles, génère les clés i18n, remplit les fichiers `messages/*.json`, traduit via DeepL et applique les mutations sûres du projet. Quand une réécriture ou une injection n’est pas jugée fiable, le CLI s’arrête proprement sur cette cible et renvoie une action manuelle recommandée au lieu de modifier silencieusement votre code.
10
10
 
11
- **[Documentation complete](./DOCUMENTATION.md)**
11
+ La version actuelle est pensée pour être **utile en automatique**, mais aussi **conservatrice** sur les cas ambigus.
12
+
13
+ Le complément de documentation se trouve dans [DOCUMENTATION.md](./DOCUMENTATION.md).
12
14
 
13
15
  ## Installation
14
16
 
15
17
  ```bash
16
- npm install -D next-auto-i18n
18
+ npm install -D next-auto-i18n next-intl
17
19
  ```
18
20
 
19
- Ou directement via npx :
21
+ Ou directement :
20
22
 
21
23
  ```bash
22
24
  npx next-auto-i18n init
23
25
  ```
24
26
 
25
- ## Pre-requis
27
+ ## Prérequis
28
+
29
+ - Node.js `>= 18`
30
+ - Un projet Next.js avec App Router
31
+ - `next-intl` installé dans le projet
32
+ - Une clé API DeepL
33
+
34
+ ## Ce que le package fait vraiment
26
35
 
27
- - Node.js >= 18
28
- - Un projet Next.js (App Router)
29
- - Une cle API DeepL ([inscription gratuite](https://www.deepl.com/pro-api))
36
+ - Scan AST des fichiers `.tsx`, `.jsx`, `.ts`, `.js`
37
+ - Extraction des strings JSX, attributs traduisibles et template literals
38
+ - Génération incrémentale des clés dans `messages/<locale>.json`
39
+ - Traduction DeepL avec validation des placeholders
40
+ - Réécriture automatique des cas sûrs
41
+ - Détection des cas risqués : module-scope, JSX ambigu, fichiers non parsables
42
+ - Injection Next.js conservatrice : applique ce qui est sûr, bloque ce qui doit rester manuel
43
+ - Reporting structuré : `success`, `partial`, `failed`, diagnostics et actions manuelles
30
44
 
31
- ## Utilisation rapide
45
+ ## Ce que le package ne promet pas
46
+
47
+ - Il ne réécrit pas tous les cas JSX complexes.
48
+ - Il ne force pas la restructuration `app/[locale]` si le layout racine paraît trop personnalisé.
49
+ - Il ne “corrige pas quand même” un projet ambigu.
50
+ - Il ne garantit pas un projet 100% migré sans validation humaine sur les cas avancés.
51
+
52
+ ## Démarrage rapide
32
53
 
33
54
  ```bash
34
55
  npx next-auto-i18n init
35
56
  ```
36
57
 
37
- Le CLI vous guide interactivement :
58
+ Le CLI vous guide sur :
38
59
 
39
- 1. Langue source (ex: `fr`)
40
- 2. Langues cibles (ex: `en, es, de`)
41
- 3. Cle API DeepL
60
+ 1. la locale source
61
+ 2. les locales cibles
62
+ 3. la clé DeepL
42
63
 
43
- Et en quelques secondes :
64
+ Puis il :
44
65
 
45
- - Scanne tous vos composants via AST
46
- - Genere `messages/fr.json` avec les cles i18n
47
- - Traduit automatiquement vers chaque langue cible
48
- - Installe `next-intl` automatiquement si absent
49
- - Remplace les strings en dur par `t("cle")`
50
- - Configure `next.config`, `middleware.ts` (ou `proxy.ts` sur Next.js 16+)
51
- - Genere `i18n/routing.ts` + `i18n/request.ts` (requis pour les Server Components)
52
- - Cree la structure `app/[locale]/` requise par le App Router next-intl
53
- - Injecte un **Language Switcher flottant** (personnalisable) pour changer de langue
54
- - Detecte les strings dans les `const` module-scope et vous guide pour les integrer manuellement
66
+ - crée `auto-i18n.config.json`
67
+ - alimente `messages/<sourceLocale>.json`
68
+ - traduit les locales cibles
69
+ - réécrit les fichiers sûrs
70
+ - tente les injections Next.js sûres
71
+ - signale clairement les parties à traiter manuellement
55
72
 
56
73
  ## Commandes
57
74
 
58
75
  ### `next-auto-i18n init`
59
76
 
60
- Initialisation complete du projet.
77
+ Initialise le projet : scan, messages, traduction, réécriture, injection.
61
78
 
62
79
  ```bash
63
- next-auto-i18n init # mode interactif
64
- next-auto-i18n init --dry-run # preview sans modification
65
- next-auto-i18n init --locale en,es,de # langues cibles en ligne de commande
80
+ next-auto-i18n init
81
+ next-auto-i18n init --dry-run
82
+ next-auto-i18n init --locale en,es,de
66
83
  ```
67
84
 
85
+ `--dry-run` montre d’abord un aperçu et demande confirmation avant d’appliquer.
86
+
68
87
  ### `next-auto-i18n sync`
69
88
 
70
- Rescanne le projet, integre les nouvelles strings et synchronise toutes les traductions (mode incrementiel les cles existantes sont preservees).
89
+ Rescanne le projet, fusionne les nouvelles strings et synchronise les traductions sans régénérer toute la base.
71
90
 
72
91
  ```bash
73
92
  next-auto-i18n sync
@@ -75,19 +94,30 @@ next-auto-i18n sync
75
94
 
76
95
  ### `next-auto-i18n extract`
77
96
 
78
- Traduit toutes les strings et genere un **guide d'integration Markdown** sans modifier aucun fichier source. Utile pour garder le controle sur la reecriture du code.
97
+ Génère ou met à jour les fichiers `messages/*.json`, traduit, puis produit un guide Markdown sans modifier les fichiers source applicatifs.
79
98
 
80
99
  ```bash
81
- next-auto-i18n extract # guide genere dans i18n-guide.md
82
- next-auto-i18n extract --out docs/i18n-guide.md # chemin personnalise
83
- next-auto-i18n extract --locale en,es # langues cibles (si pas de config)
100
+ next-auto-i18n extract
101
+ next-auto-i18n extract --out docs/i18n-guide.md
102
+ next-auto-i18n extract --inject
103
+ next-auto-i18n extract --switcher
104
+ next-auto-i18n extract --no-module-scope
84
105
  ```
85
106
 
86
- Le guide genere inclut : exemples d'utilisation Client/Server Component, tableaux par fichier (ligne, type, cle, code a copier-coller), section dedicee aux strings module-scope.
107
+ ### `next-auto-i18n extract sync`
108
+
109
+ Version incrémentale de `extract`.
110
+
111
+ ```bash
112
+ next-auto-i18n extract sync
113
+ next-auto-i18n extract sync --inject
114
+ next-auto-i18n extract sync --switcher
115
+ next-auto-i18n extract sync --no-module-scope
116
+ ```
87
117
 
88
118
  ### `next-auto-i18n add-locale <locale>`
89
119
 
90
- Ajoute une nouvelle langue et traduit toutes les cles existantes.
120
+ Ajoute une locale cible, traduit les clés existantes et met à jour l’infrastructure Next.js avec les mêmes garde-fous que le reste du moteur.
91
121
 
92
122
  ```bash
93
123
  next-auto-i18n add-locale ar
@@ -95,121 +125,117 @@ next-auto-i18n add-locale ar
95
125
 
96
126
  ### `next-auto-i18n missing`
97
127
 
98
- Affiche les cles non traduites par langue.
128
+ Affiche les clés manquantes par locale cible.
99
129
 
100
130
  ```bash
101
131
  next-auto-i18n missing
102
132
  ```
103
133
 
104
- ## Configuration
105
-
106
- Le fichier `auto-i18n.config.json` est genere automatiquement :
107
-
108
- ```json
109
- {
110
- "sourceLocale": "fr",
111
- "targetLocales": ["en", "es"],
112
- "provider": "deepl",
113
- "apiKeyEnv": "AUTO_I18N_DEEPL_KEY",
114
- "messagesDir": "./messages",
115
- "ignore": ["node_modules", ".next", "**/*.test.*", "**/*.spec.*"]
116
- }
117
- ```
118
-
119
- La cle API est stockee dans `.env.local` (jamais commitee) :
134
+ ## Modèle de sécurité
120
135
 
121
- ```bash
122
- AUTO_I18N_DEEPL_KEY=votre-cle-ici
123
- ```
136
+ - `.env.local` et `*.backup` sont ajoutés au `.gitignore`
137
+ - les placeholders de traduction sont validés avant écriture
138
+ - les réécritures ambiguës sont exclues au lieu d’être appliquées de force
139
+ - les injecteurs Next.js retournent `applicable`, `already_present`, `manual_required` ou `blocked`
140
+ - le run global peut finir en `partial` avec actions manuelles listées
124
141
 
125
- ## Fonctionnement
142
+ ## Compatibilité
126
143
 
127
- ### 1. Scan AST
144
+ ### Structures de projet
128
145
 
129
- Analyse les fichiers `.tsx`, `.jsx`, `.ts`, `.js` via [ts-morph](https://ts-morph.com/) :
146
+ | Structure | Statut | Notes |
147
+ |---|---|---|
148
+ | `app/` | supporté | cas principal |
149
+ | `src/app/` | supporté | supporté par le scanner et les injecteurs |
150
+ | `components/`, `ui/`, `features/`, `shared/` | supporté au scan | scan AST étendu |
151
+ | monorepo avec conventions très custom | partiel | dépend de la structure réellement scannée |
130
152
 
131
- - Texte JSX : `<p>Bonjour</p>`
132
- - Attributs : `placeholder="Rechercher..."`
133
- - Template literals : `` `Bienvenue ${name}` ``
153
+ ### Réécriture AST
134
154
 
135
- Ignore automatiquement les classNames, imports, strings techniques, fichiers de config.
155
+ | Cas | Statut | Comportement |
156
+ |---|---|---|
157
+ | texte JSX simple | supporté | réécriture automatique |
158
+ | attributs traduisibles | supporté | réécriture automatique |
159
+ | template literals simples | supporté | génération de clé + réécriture |
160
+ | strings module-scope | partiel | traduites, mais intégration souvent manuelle |
161
+ | JSX inline ambigu ou espaces sensibles | conservateur | exclu de la réécriture auto |
162
+ | fichier non parsable | bloqué | diagnostic remonté, aucune mutation |
136
163
 
137
- ### 2. Generation des cles
164
+ ### Injection Next.js
138
165
 
139
- Chaque string devient une cle i18n normalisee :
166
+ | Cible | Statut | Comportement |
167
+ |---|---|---|
168
+ | `next.config.*` | supporté | injection si sûre, sinon blocage explicite |
169
+ | `middleware.ts` / `proxy.ts` | supporté | création prudente selon contexte |
170
+ | `i18n/routing.ts` | supporté | création ou skip si déjà présent |
171
+ | `i18n/request.ts` | supporté | création ou skip si déjà présent |
172
+ | `LanguageSwitcher` | supporté | injecteur isolé possible |
173
+ | `app/[locale]/` | conservateur | refus explicite sur layout complexe |
140
174
 
141
- | String | Cle |
142
- |--------|-----|
143
- | `Bonjour` | `bonjour` |
144
- | `Ajouter au panier` | `ajouter_au_panier` |
145
- | `` `Bienvenue ${name}` `` | `bienvenue_name` |
175
+ ### Versions et dépendances
146
176
 
147
- ### 3. Traduction DeepL
177
+ | Élément | Statut |
178
+ |---|---|
179
+ | Node.js 18+ | requis |
180
+ | Next.js App Router | requis |
181
+ | `next-intl` | requis |
182
+ | DeepL Free / Pro | supporté |
148
183
 
149
- - Appel batch avec protection des placeholders (`{name}` → `<x>name</x>`)
150
- - Mode incrementiel : seules les cles manquantes sont traduites
151
- - Compatible DeepL Free (500k chars/mois) et Pro
152
- - Restauration automatique des entites HTML (`&apos;`, `&#39;`, etc.)
184
+ ## Exemples de comportement
153
185
 
154
- ### 4. Reecriture des composants
186
+ ### Cas sûr
155
187
 
156
- | Avant | Apres |
157
- |-------|-------|
158
- | `<p>Bonjour</p>` | `<p>{t("bonjour")}</p>` |
159
- | `placeholder="Chercher"` | `placeholder={t("chercher")}` |
160
- | `` `Salut ${name}` `` | `t("salut_name", { name })` |
188
+ ```tsx
189
+ <p>Bonjour</p>
190
+ ```
161
191
 
162
- - Server Components : `await getTranslations()` (next-intl/server)
163
- - Client Components : `useTranslations()` (next-intl)
164
- - Les strings dans des `const` module-scope (hors composant) sont **detectees et signalees** avec le fichier + numero de ligne — elles sont traduites dans les JSON mais pas reecrites automatiquement (voir section suivante)
192
+ devient :
165
193
 
166
- ### Strings module-scope
194
+ ```tsx
195
+ <p>{t("bonjour")}</p>
196
+ ```
167
197
 
168
- Les `const` declarees au niveau module (hors fonction/composant) ne peuvent pas utiliser `t()` directement. next-auto-i18n les detecte, les traduit, et vous indique quoi faire :
198
+ ### Cas module-scope
169
199
 
170
200
  ```tsx
171
- // avant — const module-scope, t() inaccessible ici
172
- const items = ['Accueil', 'A propos', 'Contact'];
173
-
174
- // ✅ apres — deplacez la const dans le composant
175
- export function Nav() {
176
- const t = useTranslations();
177
- const items = [t('accueil'), t('a_propos'), t('contact')];
178
- }
201
+ const items = ['Accueil', 'Contact'];
179
202
  ```
180
203
 
181
- Utilisez `next-auto-i18n extract` pour obtenir un guide complet avec tous les cas a corriger.
204
+ Le package peut générer les messages, mais laissera une action manuelle plutôt que d’injecter `t()` à un endroit où il n’est pas accessible.
182
205
 
183
- ### 5. Injection config Next.js
206
+ ### Cas layout complexe
184
207
 
185
- - `next.config` : wrappe avec `createNextIntlPlugin`
186
- - `middleware.ts` / `proxy.ts` : routing i18n (proxy.ts si Next.js >= 16)
187
- - `i18n/routing.ts` : definit les locales
188
- - `i18n/request.ts` : configuration `getRequestConfig` pour les Server Components
189
- - `app/[locale]/layout.tsx` : cree avec `NextIntlClientProvider` + `LanguageSwitcher`
190
- - `app/[locale]/page.tsx` : la page existante est deplacee ici
191
- - `app/layout.tsx` : simplifie en HTML shell (`<html><body>{children}</body></html>`)
208
+ Si le layout racine contient de la logique sensible ou certains patterns considérés à risque, l’injection de `app/[locale]` est marquée `manual required`. Les autres injections sûres peuvent continuer.
192
209
 
193
- ### 6. Language Switcher
210
+ ## Configuration
194
211
 
195
- Un composant flottant est automatiquement genere dans `components/LanguageSwitcher.tsx` et inclus dans `app/[locale]/layout.tsx` (dans le provider). Personnalisable via `SWITCHER_CONFIG` : position, theme (light/dark), couleur d'accent, offset.
212
+ Le fichier `auto-i18n.config.json` est généré automatiquement :
196
213
 
197
- ## Securite
214
+ ```json
215
+ {
216
+ "sourceLocale": "fr",
217
+ "targetLocales": ["en", "es"],
218
+ "provider": "deepl",
219
+ "apiKeyEnv": "AUTO_I18N_DEEPL_KEY",
220
+ "messagesDir": "./messages",
221
+ "ignore": ["node_modules", ".next", "**/*.test.*", "**/*.spec.*"]
222
+ }
223
+ ```
224
+
225
+ La clé API est stockée dans `.env.local` :
198
226
 
199
- - La cle API n'est **jamais** dans le code source
200
- - `.env.local` et `*.backup` sont ajoutes au `.gitignore`
201
- - Mode `--dry-run` pour verifier avant modification
202
- - Backups automatiques (`*.backup`) avant chaque reecriture
227
+ ```bash
228
+ AUTO_I18N_DEEPL_KEY=votre-cle
229
+ ```
203
230
 
204
- ## Developpement
231
+ ## Développement
205
232
 
206
233
  ```bash
207
- git clone https://github.com/stvekoulo/auto-i18n.git
234
+ git clone https://github.com/stvekoulo/next-auto-i18n.git
208
235
  cd next-auto-i18n
209
236
  npm install
210
- npm test # vitest
211
- npm run build # tsc
212
- npm run dev -- init # test local
237
+ npm run build
238
+ npm test
213
239
  ```
214
240
 
215
241
  ## Licence
@@ -4,14 +4,13 @@ export interface FileDocEntry {
4
4
  /** Chemin relatif depuis projectRoot (pour l'affichage). */
5
5
  relPath: string;
6
6
  strings: ExtractedString[];
7
- /** Valeurs des strings au module-scope (non réécrivables automatiquement). */
7
+ /** Valeurs des strings au module-scope. */
8
8
  moduleScopeValues: Set<string>;
9
9
  }
10
10
  export interface DocOptions {
11
11
  projectRoot: string;
12
12
  sourceLocale: string;
13
13
  targetLocales: string[];
14
- /** Chemin relatif du dossier messages (pour l'affichage). */
15
14
  messagesDir: string;
16
15
  keyMap: Map<string, string>;
17
16
  files: FileDocEntry[];
@@ -1 +1 @@
1
- {"version":3,"file":"doc-generator.d.ts","sourceRoot":"","sources":["../../src/cli/doc-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,8EAA8E;IAC9E,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAmCD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAwKpD;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpE"}
1
+ {"version":3,"file":"doc-generator.d.ts","sourceRoot":"","sources":["../../src/cli/doc-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,2CAA2C;IAC3C,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAgCD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CA+JpD;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpE"}
@@ -1,5 +1,4 @@
1
1
  import { writeFile } from 'fs/promises';
2
- // ── Helpers ────────────────────────────────────────────────────────────────
3
2
  function escapeCell(s) {
4
3
  return s.replace(/\|/g, '\\|').replace(/[\r\n]+/g, ' ');
5
4
  }
@@ -25,19 +24,16 @@ function replacementCode(s, key) {
25
24
  }
26
25
  return `{t("${key}")}`;
27
26
  }
28
- // ── Markdown builder ───────────────────────────────────────────────────────
29
27
  export function buildDoc(options) {
30
28
  const { sourceLocale, targetLocales, messagesDir, keyMap, files, date } = options;
31
29
  const totalStrings = files.reduce((sum, f) => sum + f.strings.length, 0);
32
30
  const totalKeys = keyMap.size;
33
31
  const moduleScopeTotal = files.reduce((sum, f) => sum + f.moduleScopeValues.size, 0);
34
32
  const L = [];
35
- // ── En-tête ──────────────────────────────────────────────────────────────
36
33
  L.push('# Guide d\'intégration i18n — next-auto-i18n');
37
34
  L.push('');
38
35
  L.push(`> Généré le **${date}**&nbsp;&nbsp;·&nbsp;&nbsp;✅ Aucun fichier source modifié.`);
39
36
  L.push('');
40
- // ── Résumé ───────────────────────────────────────────────────────────────
41
37
  L.push('## Résumé');
42
38
  L.push('');
43
39
  L.push(`| | |`);
@@ -49,7 +45,6 @@ export function buildDoc(options) {
49
45
  L.push(`| ⚠️ Action manuelle | **${moduleScopeTotal}** string${moduleScopeTotal > 1 ? 's' : ''} module-scope (voir section dédiée) |`);
50
46
  }
51
47
  L.push('');
52
- // ── Fichiers générés ─────────────────────────────────────────────────────
53
48
  L.push('## Fichiers générés');
54
49
  L.push('');
55
50
  L.push('| Fichier | Description |');
@@ -59,7 +54,6 @@ export function buildDoc(options) {
59
54
  L.push(`| \`${messagesDir}/${locale}.json\` | Traductions (${locale}) |`);
60
55
  }
61
56
  L.push('');
62
- // ── Guide d'utilisation ───────────────────────────────────────────────────
63
57
  L.push('## Comment utiliser les traductions');
64
58
  L.push('');
65
59
  L.push('### Composant Client (`\'use client\'`)');
@@ -87,7 +81,6 @@ export function buildDoc(options) {
87
81
  L.push('');
88
82
  L.push('> 💡 Lancez `npx next-auto-i18n init` pour configurer automatiquement le routing, le middleware et les layouts.');
89
83
  L.push('');
90
- // ── Section module-scope ─────────────────────────────────────────────────
91
84
  if (moduleScopeTotal > 0) {
92
85
  L.push('---');
93
86
  L.push('');
@@ -116,7 +109,6 @@ export function buildDoc(options) {
116
109
  L.push('```');
117
110
  L.push('');
118
111
  }
119
- // ── Strings par fichier ───────────────────────────────────────────────────
120
112
  L.push('---');
121
113
  L.push('');
122
114
  L.push('## Strings par fichier');
@@ -134,7 +126,6 @@ export function buildDoc(options) {
134
126
  L.push(`> ⚠️ **${moduleScopeValues.size}** string${moduleScopeValues.size > 1 ? 's' : ''} module-scope dans ce fichier.`);
135
127
  L.push('');
136
128
  }
137
- // Strings auto-remplaçables
138
129
  if (autoStrings.length > 0) {
139
130
  if (hasModuleScope)
140
131
  L.push('**Remplacements automatiques :**');
@@ -149,7 +140,6 @@ export function buildDoc(options) {
149
140
  }
150
141
  L.push('');
151
142
  }
152
- // Strings module-scope (action manuelle)
153
143
  if (manualStrings.length > 0) {
154
144
  L.push('**Action manuelle requise (module-scope) :**');
155
145
  L.push('');
@@ -167,7 +157,6 @@ export function buildDoc(options) {
167
157
  L.push('---');
168
158
  L.push('');
169
159
  }
170
- // ── Toutes les clés ───────────────────────────────────────────────────────
171
160
  L.push('## Référence complète des clés');
172
161
  L.push('');
173
162
  L.push(`Toutes les clés générées dans \`${messagesDir}/${sourceLocale}.json\` :`);