next-auto-i18n 0.5.2 β†’ 0.7.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 (82) hide show
  1. package/DOCUMENTATION.md +138 -14
  2. package/dist/cli/doc-generator.d.ts +23 -0
  3. package/dist/cli/doc-generator.d.ts.map +1 -0
  4. package/dist/cli/doc-generator.js +187 -0
  5. package/dist/cli/doc-generator.js.map +1 -0
  6. package/dist/cli/index.js +333 -37
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/prompts.d.ts +10 -0
  9. package/dist/cli/prompts.d.ts.map +1 -1
  10. package/dist/cli/prompts.js +35 -4
  11. package/dist/cli/prompts.js.map +1 -1
  12. package/dist/generator/index.d.ts +12 -3
  13. package/dist/generator/index.d.ts.map +1 -1
  14. package/dist/generator/index.js +29 -6
  15. package/dist/generator/index.js.map +1 -1
  16. package/dist/generator/key-builder.d.ts +0 -20
  17. package/dist/generator/key-builder.d.ts.map +1 -1
  18. package/dist/generator/key-builder.js +1 -22
  19. package/dist/generator/key-builder.js.map +1 -1
  20. package/dist/injector/index.d.ts +0 -1
  21. package/dist/injector/index.d.ts.map +1 -1
  22. package/dist/injector/index.js +1 -1
  23. package/dist/injector/index.js.map +1 -1
  24. package/dist/injector/layout-injector.d.ts.map +1 -1
  25. package/dist/injector/layout-injector.js +0 -2
  26. package/dist/injector/layout-injector.js.map +1 -1
  27. package/dist/injector/locale-structure-injector.d.ts.map +1 -1
  28. package/dist/injector/locale-structure-injector.js +0 -16
  29. package/dist/injector/locale-structure-injector.js.map +1 -1
  30. package/dist/injector/request-injector.d.ts.map +1 -1
  31. package/dist/injector/request-injector.js +0 -3
  32. package/dist/injector/request-injector.js.map +1 -1
  33. package/dist/injector/switcher-injector.d.ts +0 -4
  34. package/dist/injector/switcher-injector.d.ts.map +1 -1
  35. package/dist/injector/switcher-injector.js +0 -22
  36. package/dist/injector/switcher-injector.js.map +1 -1
  37. package/dist/rewriter/attr-rewriter.d.ts.map +1 -1
  38. package/dist/rewriter/attr-rewriter.js +0 -3
  39. package/dist/rewriter/attr-rewriter.js.map +1 -1
  40. package/dist/rewriter/const-rewriter.d.ts +0 -10
  41. package/dist/rewriter/const-rewriter.d.ts.map +1 -1
  42. package/dist/rewriter/const-rewriter.js +1 -19
  43. package/dist/rewriter/const-rewriter.js.map +1 -1
  44. package/dist/rewriter/index.d.ts +9 -0
  45. package/dist/rewriter/index.d.ts.map +1 -1
  46. package/dist/rewriter/index.js +6 -2
  47. package/dist/rewriter/index.js.map +1 -1
  48. package/dist/rewriter/jsx-rewriter.d.ts +0 -4
  49. package/dist/rewriter/jsx-rewriter.d.ts.map +1 -1
  50. package/dist/rewriter/jsx-rewriter.js +0 -11
  51. package/dist/rewriter/jsx-rewriter.js.map +1 -1
  52. package/dist/scanner/ast-parser.d.ts +0 -8
  53. package/dist/scanner/ast-parser.d.ts.map +1 -1
  54. package/dist/scanner/ast-parser.js +0 -8
  55. package/dist/scanner/ast-parser.js.map +1 -1
  56. package/dist/scanner/filters.d.ts +1 -1
  57. package/dist/scanner/filters.js +2 -2
  58. package/dist/scanner/index.d.ts +0 -2
  59. package/dist/scanner/index.d.ts.map +1 -1
  60. package/dist/scanner/index.js +1 -10
  61. package/dist/scanner/index.js.map +1 -1
  62. package/dist/scanner/string-extractor.d.ts +0 -4
  63. package/dist/scanner/string-extractor.d.ts.map +1 -1
  64. package/dist/scanner/string-extractor.js +0 -13
  65. package/dist/scanner/string-extractor.js.map +1 -1
  66. package/dist/translator/deepl.d.ts +0 -1
  67. package/dist/translator/deepl.d.ts.map +1 -1
  68. package/dist/translator/deepl.js +0 -5
  69. package/dist/translator/deepl.js.map +1 -1
  70. package/dist/utils/config.d.ts +0 -4
  71. package/dist/utils/config.d.ts.map +1 -1
  72. package/dist/utils/config.js +0 -4
  73. package/dist/utils/config.js.map +1 -1
  74. package/dist/utils/deps.d.ts +0 -7
  75. package/dist/utils/deps.d.ts.map +1 -1
  76. package/dist/utils/deps.js +0 -7
  77. package/dist/utils/deps.js.map +1 -1
  78. package/dist/utils/env.d.ts +0 -13
  79. package/dist/utils/env.d.ts.map +1 -1
  80. package/dist/utils/env.js +0 -13
  81. package/dist/utils/env.js.map +1 -1
  82. package/package.json +1 -1
package/DOCUMENTATION.md CHANGED
@@ -24,6 +24,7 @@ next-auto-i18n is a CLI tool that fully automates internationalization (i18n) in
24
24
  - [Commands](#commands)
25
25
  - [How It Works](#how-it-works)
26
26
  - [Supported String Types](#supported-string-types)
27
+ - [Module-scope Strings](#module-scope-strings)
27
28
  - [Safety & Backups](#safety--backups)
28
29
  - [DeepL API](#deepl-api)
29
30
  - [Troubleshooting](#troubleshooting)
@@ -270,6 +271,72 @@ next-auto-i18n add-locale zh
270
271
 
271
272
  ---
272
273
 
274
+ ### `next-auto-i18n extract`
275
+
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.
277
+
278
+ ```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
282
+ ```
283
+
284
+ | Flag | Description |
285
+ |------|-------------|
286
+ | `--locale <locales>` | Comma-separated target locales (used if no `auto-i18n.config.json` exists) |
287
+ | `--out <path>` | Output path for the Markdown guide (default: `i18n-guide.md`) |
288
+
289
+ **What it does:**
290
+
291
+ 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
296
+
297
+ **What it does NOT do:** modify any `.tsx`/`.ts`/`.jsx`/`.js` source file.
298
+
299
+ **Generated guide contents:**
300
+
301
+ - Summary table (strings found, keys generated, files)
302
+ - List of generated translation files
303
+ - Usage examples (Client Component with `useTranslations`, Server Component with `getTranslations`)
304
+ - Module-scope strings section with before/after code examples
305
+ - Per-file string tables with line number, type, original text, key, and replacement code
306
+ - Complete key reference table
307
+
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
+ ...
319
+
320
+ β–Έ GΓ©nΓ©ration des clΓ©s
321
+ βœ“ 42 clΓ©s β†’ ./messages/fr.json
322
+
323
+ β–Έ Traduction via DeepL
324
+ βœ“ 84 strings traduites
325
+ ./messages/en.json
326
+ ./messages/es.json
327
+
328
+ β–Έ Analyse du code source
329
+ ⚠ 3 strings module-scope dΓ©tectΓ©es (action manuelle requise β€” voir guide)
330
+
331
+ β–Έ GΓ©nΓ©ration du guide
332
+ βœ“ Guide gΓ©nΓ©rΓ© : i18n-guide.md
333
+
334
+ βœ“ Extraction terminΓ©e β€” aucun fichier source modifiΓ©
335
+ Consultez le guide pour intΓ©grer les traductions manuellement.
336
+ ```
337
+
338
+ ---
339
+
273
340
  ### `next-auto-i18n missing`
274
341
 
275
342
  Reports untranslated keys per target locale.
@@ -562,6 +629,52 @@ export default function Button() {
562
629
 
563
630
  ---
564
631
 
632
+ ## Module-scope Strings
633
+
634
+ Some strings live inside `const` arrays or objects declared **at module level** (outside any component body). Because `t()` can only be called inside a component, these strings cannot be auto-rewritten.
635
+
636
+ **Example:**
637
+
638
+ ```tsx
639
+ // ❌ Module-scope β€” t() is not available here
640
+ const navItems = [
641
+ { label: 'Accueil', href: '/' },
642
+ { label: 'Γ€ propos', href: '/about' },
643
+ ];
644
+
645
+ export function Navbar() {
646
+ return <nav>{navItems.map(i => <a href={i.href}>{i.label}</a>)}</nav>;
647
+ }
648
+ ```
649
+
650
+ **What next-auto-i18n does:**
651
+
652
+ - Detects these strings via AST analysis
653
+ - Adds them to the JSON translation files (they are translated)
654
+ - **Does NOT rewrite the source file** β€” doing so would break the code
655
+ - Warns in the CLI with file path, line number, and the target key
656
+ - Includes guidance and a before/after example in the `extract` guide
657
+
658
+ **How to fix manually:**
659
+
660
+ ```tsx
661
+ // βœ… Function-scope β€” t() is available
662
+ import { useTranslations } from 'next-intl';
663
+
664
+ export function Navbar() {
665
+ const t = useTranslations();
666
+ const navItems = [
667
+ { label: t('accueil'), href: '/' },
668
+ { label: t('a_propos'), href: '/about' },
669
+ ];
670
+ return <nav>{navItems.map(i => <a href={i.href}>{i.label}</a>)}</nav>;
671
+ }
672
+ ```
673
+
674
+ Move the `const` declaration inside the component body so `t()` is in scope.
675
+
676
+ ---
677
+
565
678
  ## Safety & Backups
566
679
 
567
680
  ### `--dry-run` mode
@@ -775,12 +888,19 @@ npx vitest
775
888
  ```
776
889
  next-auto-i18n/
777
890
  β”œβ”€β”€ src/
778
- β”‚ β”œβ”€β”€ cli/ # CLI entry point + interactive prompts
779
- β”‚ β”œβ”€β”€ scanner/ # AST parsing + string extraction + filtering
780
- β”‚ β”œβ”€β”€ generator/ # Key generation + JSON file creation
781
- β”‚ β”œβ”€β”€ translator/ # DeepL API client + translation orchestration
782
- β”‚ β”œβ”€β”€ rewriter/ # JSX/attribute rewriting via AST
783
- β”‚ β”œβ”€β”€ injector/ # Next.js config injection:
891
+ β”‚ β”œβ”€β”€ cli/
892
+ β”‚ β”‚ β”œβ”€β”€ index.ts # CLI entry point (Commander.js) β€” all commands
893
+ β”‚ β”‚ β”œβ”€β”€ prompts.ts # Interactive prompts + dry-run confirmation
894
+ β”‚ β”‚ └── doc-generator.ts # Markdown guide generator (used by extract)
895
+ β”‚ β”œβ”€β”€ scanner/ # AST parsing + string extraction + filtering
896
+ β”‚ β”œβ”€β”€ generator/ # Key generation + JSON file creation
897
+ β”‚ β”œβ”€β”€ translator/ # DeepL API client + translation orchestration
898
+ β”‚ β”œβ”€β”€ rewriter/
899
+ β”‚ β”‚ β”œβ”€β”€ index.ts # Rewrite orchestration + FileRewriteDetail
900
+ β”‚ β”‚ β”œβ”€β”€ jsx-rewriter.ts # JSX text + template literal rewriting
901
+ β”‚ β”‚ β”œβ”€β”€ attr-rewriter.ts # JSX attribute rewriting
902
+ β”‚ β”‚ └── const-rewriter.ts # String literal rewriting + module-scope detection
903
+ β”‚ β”œβ”€β”€ injector/ # Next.js config injection:
784
904
  β”‚ β”‚ β”œβ”€β”€ config-injector.ts # next.config wrapping
785
905
  β”‚ β”‚ β”œβ”€β”€ middleware-injector.ts # middleware.ts / proxy.ts
786
906
  β”‚ β”‚ β”œβ”€β”€ routing-injector.ts # i18n/routing.ts
@@ -788,9 +908,9 @@ next-auto-i18n/
788
908
  β”‚ β”‚ β”œβ”€β”€ switcher-injector.ts # LanguageSwitcher component
789
909
  β”‚ β”‚ β”œβ”€β”€ locale-structure-injector.ts # app/[locale]/ structure
790
910
  β”‚ β”‚ └── layout-injector.ts # layout utilities
791
- β”‚ └── utils/ # Config, env, logger, dependency utilities
792
- β”œβ”€β”€ tests/ # Vitest test suites (298 tests)
793
- └── DOCUMENTATION.md # This file
911
+ β”‚ └── utils/ # Config, env, logger, dependency utilities
912
+ β”œβ”€β”€ tests/ # Vitest test suites (343 tests)
913
+ └── DOCUMENTATION.md # This file
794
914
  ```
795
915
 
796
916
  ### Running tests
@@ -805,14 +925,15 @@ The test suite covers all modules:
805
925
  |--------|-------|
806
926
  | Scanner (filters) | 109 |
807
927
  | Generator (key-builder) | 39 |
808
- | Rewriter | 33 |
928
+ | Rewriter | 49 |
809
929
  | Injector | 25 |
810
- | Translator (DeepL) | 23 |
811
- | Generator | 20 |
930
+ | Translator (DeepL) | 26 |
931
+ | Generator | 27 |
812
932
  | Scanner (string-extractor) | 20 |
813
933
  | CLI (config, env) | 18 |
814
934
  | Translator (orchestration) | 11 |
815
- | **Total** | **298** |
935
+ | Doc generator | 9 |
936
+ | **Total** | **343** |
816
937
 
817
938
  ### Submitting changes
818
939
 
@@ -829,8 +950,9 @@ The test suite covers all modules:
829
950
 
830
951
  ### v1.x β€” Enhancements
831
952
 
832
- - [x] `next-auto-i18n sync` β€” rescan and incremental update
953
+ - [x] `next-auto-i18n sync` β€” rescan and incremental update (stable key merge)
833
954
  - [x] `next-auto-i18n missing` β€” report untranslated keys
955
+ - [x] `next-auto-i18n extract` β€” translate + generate guide without touching source
834
956
  - [x] Floating language switcher widget (auto-injected, customizable)
835
957
  - [x] Automatic `next-intl` dependency installation
836
958
  - [x] `app/[locale]/` structure auto-creation (required by next-intl App Router)
@@ -838,6 +960,8 @@ The test suite covers all modules:
838
960
  - [x] Dynamic `<html lang>` attribute
839
961
  - [x] Next.js 16 `proxy.ts` detection
840
962
  - [x] Scan scope limited to Next.js conventional directories
963
+ - [x] Module-scope string detection β€” warn instead of breaking code
964
+ - [x] Detailed CLI output β€” per-file results, string counts, module-scope warnings
841
965
  - [ ] `--watch` mode β€” auto-sync on file changes
842
966
  - [ ] Support for Vite + React (without Next.js)
843
967
  - [ ] Custom key naming strategies
@@ -0,0 +1,23 @@
1
+ import type { ExtractedString } from '../scanner/string-extractor.js';
2
+ export interface FileDocEntry {
3
+ filePath: string;
4
+ /** Chemin relatif depuis projectRoot (pour l'affichage). */
5
+ relPath: string;
6
+ strings: ExtractedString[];
7
+ /** Valeurs des strings au module-scope (non réécrivables automatiquement). */
8
+ moduleScopeValues: Set<string>;
9
+ }
10
+ export interface DocOptions {
11
+ projectRoot: string;
12
+ sourceLocale: string;
13
+ targetLocales: string[];
14
+ /** Chemin relatif du dossier messages (pour l'affichage). */
15
+ messagesDir: string;
16
+ keyMap: Map<string, string>;
17
+ files: FileDocEntry[];
18
+ outputPath: string;
19
+ date: string;
20
+ }
21
+ export declare function buildDoc(options: DocOptions): string;
22
+ export declare function generateDoc(options: DocOptions): Promise<void>;
23
+ //# sourceMappingURL=doc-generator.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,187 @@
1
+ import { writeFile } from 'fs/promises';
2
+ // ── Helpers ────────────────────────────────────────────────────────────────
3
+ function escapeCell(s) {
4
+ return s.replace(/\|/g, '\\|').replace(/[\r\n]+/g, ' ');
5
+ }
6
+ function trunc(s, max = 55) {
7
+ return s.length > max ? s.slice(0, max) + '…' : s;
8
+ }
9
+ function typeLabel(type) {
10
+ switch (type) {
11
+ case 'jsx-text': return 'JSX texte';
12
+ case 'jsx-attribute': return 'Attribut';
13
+ case 'template-literal': return 'Template';
14
+ case 'template-literal-dynamic': return 'Template dynamique';
15
+ case 'string-literal': return 'Constante';
16
+ }
17
+ }
18
+ function replacementCode(s, key) {
19
+ if (s.type === 'template-literal-dynamic' && s.variables?.length) {
20
+ const params = s.variables.join(', ');
21
+ return `{t("${key}", { ${params} })}`;
22
+ }
23
+ if (s.type === 'string-literal') {
24
+ return `t("${key}")`;
25
+ }
26
+ return `{t("${key}")}`;
27
+ }
28
+ // ── Markdown builder ───────────────────────────────────────────────────────
29
+ export function buildDoc(options) {
30
+ const { sourceLocale, targetLocales, messagesDir, keyMap, files, date } = options;
31
+ const totalStrings = files.reduce((sum, f) => sum + f.strings.length, 0);
32
+ const totalKeys = keyMap.size;
33
+ const moduleScopeTotal = files.reduce((sum, f) => sum + f.moduleScopeValues.size, 0);
34
+ const L = [];
35
+ // ── En-tΓͺte ──────────────────────────────────────────────────────────────
36
+ L.push('# Guide d\'intΓ©gration i18n β€” next-auto-i18n');
37
+ L.push('');
38
+ L.push(`> GΓ©nΓ©rΓ© le **${date}**&nbsp;&nbsp;Β·&nbsp;&nbsp;βœ… Aucun fichier source modifiΓ©.`);
39
+ L.push('');
40
+ // ── RΓ©sumΓ© ───────────────────────────────────────────────────────────────
41
+ L.push('## RΓ©sumΓ©');
42
+ L.push('');
43
+ L.push(`| | |`);
44
+ L.push(`|---|---|`);
45
+ L.push(`| Strings dΓ©tectΓ©es | **${totalStrings}** dans **${files.length}** fichier${files.length > 1 ? 's' : ''} |`);
46
+ L.push(`| ClΓ©s i18n gΓ©nΓ©rΓ©es | **${totalKeys}** β†’ \`${messagesDir}/${sourceLocale}.json\` |`);
47
+ L.push(`| Traductions gΓ©nΓ©rΓ©es | ${targetLocales.map(l => `\`${messagesDir}/${l}.json\``).join(', ')} |`);
48
+ if (moduleScopeTotal > 0) {
49
+ L.push(`| ⚠️ Action manuelle | **${moduleScopeTotal}** string${moduleScopeTotal > 1 ? 's' : ''} module-scope (voir section dédiée) |`);
50
+ }
51
+ L.push('');
52
+ // ── Fichiers gΓ©nΓ©rΓ©s ─────────────────────────────────────────────────────
53
+ L.push('## Fichiers gΓ©nΓ©rΓ©s');
54
+ L.push('');
55
+ L.push('| Fichier | Description |');
56
+ L.push('|---------|-------------|');
57
+ L.push(`| \`${messagesDir}/${sourceLocale}.json\` | Textes source (${sourceLocale}) |`);
58
+ for (const locale of targetLocales) {
59
+ L.push(`| \`${messagesDir}/${locale}.json\` | Traductions (${locale}) |`);
60
+ }
61
+ L.push('');
62
+ // ── Guide d'utilisation ───────────────────────────────────────────────────
63
+ L.push('## Comment utiliser les traductions');
64
+ L.push('');
65
+ L.push('### Composant Client (`\'use client\'`)');
66
+ L.push('');
67
+ L.push('```tsx');
68
+ L.push("'use client';");
69
+ L.push("import { useTranslations } from 'next-intl';");
70
+ L.push('');
71
+ L.push('export function MonComposant() {');
72
+ L.push(' const t = useTranslations();');
73
+ L.push(' return <p>{t("ma_cle")}</p>;');
74
+ L.push('}');
75
+ L.push('```');
76
+ L.push('');
77
+ L.push('### Composant Serveur (async)');
78
+ L.push('');
79
+ L.push('```tsx');
80
+ L.push("import { getTranslations } from 'next-intl/server';");
81
+ L.push('');
82
+ L.push('export default async function Page() {');
83
+ L.push(' const t = await getTranslations();');
84
+ L.push(' return <p>{t("ma_cle")}</p>;');
85
+ L.push('}');
86
+ L.push('```');
87
+ L.push('');
88
+ L.push('> πŸ’‘ Lancez `npx next-auto-i18n init` pour configurer automatiquement le routing, le middleware et les layouts.');
89
+ L.push('');
90
+ // ── Section module-scope ─────────────────────────────────────────────────
91
+ if (moduleScopeTotal > 0) {
92
+ L.push('---');
93
+ L.push('');
94
+ L.push('## ⚠️ Strings module-scope β€” action manuelle requise');
95
+ L.push('');
96
+ L.push('Ces strings sont dans des `const` **en dehors du corps d\'un composant**.');
97
+ L.push('La fonction `t()` n\'est accessible qu\'Γ  l\'intΓ©rieur d\'un composant.');
98
+ L.push('Elles ont Γ©tΓ© traduites dans les fichiers JSON, mais le code source doit Γͺtre adaptΓ© manuellement.');
99
+ L.push('');
100
+ L.push('**Solution :** dΓ©placez la `const` Γ  l\'intΓ©rieur de votre composant :');
101
+ L.push('');
102
+ L.push('```tsx');
103
+ L.push('// ❌ Module-scope β€” t() inaccessible ici');
104
+ L.push("const items = [{ label: 'Mon texte' }];");
105
+ L.push('export function Page() {');
106
+ L.push(' return <ul>{items.map(i => <li>{i.label}</li>)}</ul>;');
107
+ L.push('}');
108
+ L.push('');
109
+ L.push('// βœ… Function-scope β€” t() accessible');
110
+ L.push("import { useTranslations } from 'next-intl';");
111
+ L.push('export function Page() {');
112
+ L.push(' const t = useTranslations();');
113
+ L.push(" const items = [{ label: t('ma_cle') }];");
114
+ L.push(' return <ul>{items.map(i => <li>{i.label}</li>)}</ul>;');
115
+ L.push('}');
116
+ L.push('```');
117
+ L.push('');
118
+ }
119
+ // ── Strings par fichier ───────────────────────────────────────────────────
120
+ L.push('---');
121
+ L.push('');
122
+ L.push('## Strings par fichier');
123
+ L.push('');
124
+ L.push('Pour chaque string, remplacez le texte original par le code indiquΓ© dans la colonne **Code**.');
125
+ L.push('');
126
+ for (const fileEntry of files) {
127
+ const { relPath, strings, moduleScopeValues } = fileEntry;
128
+ const hasModuleScope = moduleScopeValues.size > 0;
129
+ const autoStrings = strings.filter(s => !moduleScopeValues.has(s.value));
130
+ const manualStrings = strings.filter(s => moduleScopeValues.has(s.value));
131
+ L.push(`### \`${relPath}\``);
132
+ L.push('');
133
+ if (hasModuleScope) {
134
+ L.push(`> ⚠️ **${moduleScopeValues.size}** string${moduleScopeValues.size > 1 ? 's' : ''} module-scope dans ce fichier.`);
135
+ L.push('');
136
+ }
137
+ // Strings auto-remplaΓ§ables
138
+ if (autoStrings.length > 0) {
139
+ if (hasModuleScope)
140
+ L.push('**Remplacements automatiques :**');
141
+ L.push('');
142
+ L.push('| Ligne | Type | Texte original | ClΓ© | Code |');
143
+ L.push('|------:|------|----------------|-----|------|');
144
+ for (const s of autoStrings) {
145
+ const key = keyMap.get(s.value) ?? '';
146
+ const text = escapeCell(trunc(s.value));
147
+ const code = replacementCode(s, key);
148
+ L.push(`| ${s.line} | ${typeLabel(s.type)} | \`${text}\` | \`${key}\` | \`${code}\` |`);
149
+ }
150
+ L.push('');
151
+ }
152
+ // Strings module-scope (action manuelle)
153
+ if (manualStrings.length > 0) {
154
+ L.push('**Action manuelle requise (module-scope) :**');
155
+ L.push('');
156
+ L.push('| Ligne | Texte original | ClΓ© | Code cible |');
157
+ L.push('|------:|----------------|-----|-----------|');
158
+ for (const s of manualStrings) {
159
+ const key = keyMap.get(s.value) ?? '';
160
+ const text = escapeCell(trunc(s.value));
161
+ L.push(`| ${s.line} | \`${text}\` | \`${key}\` | \`t("${key}")\` |`);
162
+ }
163
+ L.push('');
164
+ L.push('> DΓ©placez la `const` contenant ces strings Γ  l\'intΓ©rieur du composant.');
165
+ L.push('');
166
+ }
167
+ L.push('---');
168
+ L.push('');
169
+ }
170
+ // ── Toutes les clΓ©s ───────────────────────────────────────────────────────
171
+ L.push('## Référence complète des clés');
172
+ L.push('');
173
+ L.push(`Toutes les clΓ©s gΓ©nΓ©rΓ©es dans \`${messagesDir}/${sourceLocale}.json\` :`);
174
+ L.push('');
175
+ L.push('| ClΓ© | Valeur source |');
176
+ L.push('|-----|--------------|');
177
+ for (const [value, key] of [...keyMap.entries()].sort(([, a], [, b]) => a.localeCompare(b))) {
178
+ L.push(`| \`${key}\` | ${escapeCell(trunc(value, 70))} |`);
179
+ }
180
+ L.push('');
181
+ return L.join('\n');
182
+ }
183
+ export async function generateDoc(options) {
184
+ const content = buildDoc(options);
185
+ await writeFile(options.outputPath, content, 'utf-8');
186
+ }
187
+ //# sourceMappingURL=doc-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-generator.js","sourceRoot":"","sources":["../../src/cli/doc-generator.ts"],"names":[],"mappings":"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"}