@translation-cms/sync 1.2.9 → 1.2.12

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 (116) hide show
  1. package/README.md +304 -151
  2. package/dist/api.d.ts +79 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +151 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/bin.js +51 -17
  7. package/dist/bin.js.map +1 -1
  8. package/dist/commands/init.d.ts +8 -0
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +18 -0
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/commands/pull.d.ts +7 -0
  13. package/dist/commands/pull.d.ts.map +1 -1
  14. package/dist/commands/pull.js +15 -2
  15. package/dist/commands/pull.js.map +1 -1
  16. package/dist/commands/status.d.ts +12 -0
  17. package/dist/commands/status.d.ts.map +1 -1
  18. package/dist/commands/status.js +16 -0
  19. package/dist/commands/status.js.map +1 -1
  20. package/dist/commands/sync.d.ts +10 -0
  21. package/dist/commands/sync.d.ts.map +1 -1
  22. package/dist/commands/sync.js +23 -4
  23. package/dist/commands/sync.js.map +1 -1
  24. package/dist/commands/watch.d.ts +14 -0
  25. package/dist/commands/watch.d.ts.map +1 -1
  26. package/dist/commands/watch.js +23 -3
  27. package/dist/commands/watch.js.map +1 -1
  28. package/dist/config/config-internals/args.d.ts +11 -0
  29. package/dist/config/config-internals/args.d.ts.map +1 -0
  30. package/dist/config/config-internals/args.js +22 -0
  31. package/dist/config/config-internals/args.js.map +1 -0
  32. package/dist/config/config-internals/env.d.ts +10 -0
  33. package/dist/config/config-internals/env.d.ts.map +1 -0
  34. package/dist/config/config-internals/env.js +35 -0
  35. package/dist/config/config-internals/env.js.map +1 -0
  36. package/dist/config/config-internals/file.d.ts +11 -0
  37. package/dist/config/config-internals/file.d.ts.map +1 -0
  38. package/dist/config/config-internals/file.js +28 -0
  39. package/dist/config/config-internals/file.js.map +1 -0
  40. package/dist/config/config-internals/resolve.d.ts +21 -0
  41. package/dist/config/config-internals/resolve.d.ts.map +1 -0
  42. package/dist/config/config-internals/resolve.js +73 -0
  43. package/dist/config/config-internals/resolve.js.map +1 -0
  44. package/dist/config/config-internals/root.d.ts +9 -0
  45. package/dist/config/config-internals/root.d.ts.map +1 -0
  46. package/dist/config/config-internals/root.js +22 -0
  47. package/dist/config/config-internals/root.js.map +1 -0
  48. package/dist/config/config-internals/types.d.ts +83 -0
  49. package/dist/config/config-internals/types.d.ts.map +1 -0
  50. package/dist/config/config-internals/types.js +9 -0
  51. package/dist/config/config-internals/types.js.map +1 -0
  52. package/dist/config/resolve-config.d.ts +9 -90
  53. package/dist/config/resolve-config.d.ts.map +1 -1
  54. package/dist/config/resolve-config.js +7 -123
  55. package/dist/config/resolve-config.js.map +1 -1
  56. package/dist/core/api-internals/pull.d.ts +9 -1
  57. package/dist/core/api-internals/pull.d.ts.map +1 -1
  58. package/dist/core/api-internals/pull.js +41 -28
  59. package/dist/core/api-internals/pull.js.map +1 -1
  60. package/dist/core/api-internals/sync.d.ts +9 -2
  61. package/dist/core/api-internals/sync.d.ts.map +1 -1
  62. package/dist/core/api-internals/sync.js +18 -2
  63. package/dist/core/api-internals/sync.js.map +1 -1
  64. package/dist/core/cache-internals/format.d.ts +16 -0
  65. package/dist/core/cache-internals/format.d.ts.map +1 -1
  66. package/dist/core/cache-internals/format.js +17 -0
  67. package/dist/core/cache-internals/format.js.map +1 -1
  68. package/dist/core/cache-internals/params.d.ts.map +1 -1
  69. package/dist/core/cache-internals/params.js +24 -24
  70. package/dist/core/cache-internals/params.js.map +1 -1
  71. package/dist/core/cache-internals/pull.d.ts +12 -0
  72. package/dist/core/cache-internals/pull.d.ts.map +1 -1
  73. package/dist/core/cache-internals/pull.js +13 -0
  74. package/dist/core/cache-internals/pull.js.map +1 -1
  75. package/dist/core/cache-internals/sync.d.ts +23 -0
  76. package/dist/core/cache-internals/sync.d.ts.map +1 -1
  77. package/dist/core/cache-internals/sync.js +33 -0
  78. package/dist/core/cache-internals/sync.js.map +1 -1
  79. package/dist/core/cache-internals/types.d.ts +20 -0
  80. package/dist/core/cache-internals/types.d.ts.map +1 -1
  81. package/dist/core/scanner-internals/ast.d.ts +23 -5
  82. package/dist/core/scanner-internals/ast.d.ts.map +1 -1
  83. package/dist/core/scanner-internals/ast.js +25 -5
  84. package/dist/core/scanner-internals/ast.js.map +1 -1
  85. package/dist/core/scanner-internals/file-walker.d.ts +3 -2
  86. package/dist/core/scanner-internals/file-walker.d.ts.map +1 -1
  87. package/dist/core/scanner-internals/file-walker.js +10 -12
  88. package/dist/core/scanner-internals/file-walker.js.map +1 -1
  89. package/dist/core/scanner-internals/import-resolver.d.ts +9 -1
  90. package/dist/core/scanner-internals/import-resolver.d.ts.map +1 -1
  91. package/dist/core/scanner-internals/import-resolver.js +58 -63
  92. package/dist/core/scanner-internals/import-resolver.js.map +1 -1
  93. package/dist/core/scanner-internals/key-extractor.d.ts +12 -8
  94. package/dist/core/scanner-internals/key-extractor.d.ts.map +1 -1
  95. package/dist/core/scanner-internals/key-extractor.js +125 -97
  96. package/dist/core/scanner-internals/key-extractor.js.map +1 -1
  97. package/dist/core/scanner-internals/route-detector.d.ts +16 -8
  98. package/dist/core/scanner-internals/route-detector.d.ts.map +1 -1
  99. package/dist/core/scanner-internals/route-detector.js +37 -33
  100. package/dist/core/scanner-internals/route-detector.js.map +1 -1
  101. package/dist/core/scanner.d.ts.map +1 -1
  102. package/dist/core/scanner.js +25 -8
  103. package/dist/core/scanner.js.map +1 -1
  104. package/dist/next.d.ts +28 -0
  105. package/dist/next.d.ts.map +1 -0
  106. package/dist/next.js +65 -0
  107. package/dist/next.js.map +1 -0
  108. package/dist/preview/internals/highlight.d.ts +16 -7
  109. package/dist/preview/internals/highlight.d.ts.map +1 -1
  110. package/dist/preview/internals/highlight.js +71 -60
  111. package/dist/preview/internals/highlight.js.map +1 -1
  112. package/dist/scaffold/intenrals/scaffold.d.ts +17 -0
  113. package/dist/scaffold/intenrals/scaffold.d.ts.map +1 -1
  114. package/dist/scaffold/intenrals/scaffold.js +19 -0
  115. package/dist/scaffold/intenrals/scaffold.js.map +1 -1
  116. package/package.json +16 -3
package/README.md CHANGED
@@ -1,18 +1,98 @@
1
1
  # @translation-cms/sync
2
2
 
3
- Automatisch vertaalsleutels uit je codebase scannen, syncen met de Translations
4
- CMS, en vertalingen ophalen als lokale JSON-bestanden. Gebouwd voor Next.js +
5
- i18next.
3
+ Automatically scan translation keys from your codebase, sync with the
4
+ Translations CMS, and fetch translations as local JSON files. Built for
5
+ Next.js + i18next.
6
6
 
7
- ## Wat is dit?
7
+ ## Integration Methods
8
8
 
9
- Een CLI-tool die je workflow vereenvoudigt:
9
+ Choose the approach that fits your workflow:
10
10
 
11
- - 🔍 **Scant** je code voor translation keys (React-i18next patroon)
12
- - 📤 **Synct** nieuwe keys naar de Translations CMS
13
- - 📥 **Haalt** vertalingen op als JSON-bestanden
14
- - 🎯 **Preview** functie waarin editors live kunnen zien hoe hun tekst in je app
15
- eruit ziet
11
+ - **Next.js Plugin** (Recommended) Automatic sync on `next dev` and
12
+ `next build`
13
+ - **CLI** (Manual) `pnpm sync-translations` for on-demand control
14
+ - **Programmatic API** Call sync/pull directly in your code or scripts
15
+
16
+ ### Method 1: Next.js Plugin (Automatic)
17
+
18
+ Edit `next.config.ts`:
19
+
20
+ ```ts
21
+ import withTranslationsCMS from '@translation-cms/sync/next';
22
+
23
+ export default withTranslationsCMS(
24
+ {
25
+ // your Next.js config
26
+ },
27
+ {
28
+ pullOnBuild: true, // auto pull on build
29
+ pullOnDev: true, // auto pull on dev startup
30
+ }
31
+ );
32
+ ```
33
+
34
+ Your translations sync automatically. That's it. No extra commands needed.
35
+
36
+ ### Method 2: CLI (Manual)
37
+
38
+ ```bash
39
+ # Scan code + upload to CMS
40
+ pnpm sync-translations sync
41
+
42
+ # Download translations
43
+ pnpm sync-translations pull
44
+
45
+ # Watch mode — auto-sync on file changes
46
+ pnpm sync-translations watch
47
+
48
+ # Interactive setup
49
+ pnpm sync-translations init
50
+ ```
51
+
52
+ ### Method 3: Programmatic API
53
+
54
+ Use in scripts, build tools, or CI/CD:
55
+
56
+ ```ts
57
+ import { syncTranslations, pullTranslations } from '@translation-cms/sync/api';
58
+
59
+ // Scan and upload keys
60
+ await syncTranslations({
61
+ projectRoot: './my-app',
62
+ verbose: true,
63
+ });
64
+
65
+ // Download translations
66
+ await pullTranslations({
67
+ projectRoot: './my-app',
68
+ environment: 'production',
69
+ });
70
+
71
+ // Sync and pull in one go
72
+ import { syncAndPull } from '@translation-cms/sync/api';
73
+ await syncAndPull({ projectRoot: './my-app' });
74
+ ```
75
+
76
+ ### Choose Your Method
77
+
78
+ | Method | When to Use | Setup Time |
79
+ | -------------------- | --------------------------------- | ---------- |
80
+ | **Next.js Plugin** | Team projects, automatic workflow | 5 min |
81
+ | **CLI** | Manual control, debugging, CI/CD | 10 min |
82
+ | **Programmatic API** | Custom workflows, scripts | 5 min |
83
+
84
+ **Recommended:** Start with the **Next.js Plugin** for automatic updates during
85
+ development, then add CLI or API commands as needed.
86
+
87
+ ## What is this?
88
+
89
+ Hybrid translation management system with three integration methods:
90
+
91
+ - **Scans** your code for translation keys (React-i18next pattern)
92
+ - **Syncs** new keys to the Translations CMS
93
+ - **Fetches** translations as JSON files
94
+ - **Automatic or manual** — choose what works for your team
95
+ - **Programmatic API** — bring your own CI/CD or tooling
16
96
 
17
97
  ```
18
98
  Your Code → scan → CMS → pull → JSON files → i18next → Your App
@@ -20,64 +100,125 @@ Your Code → scan → CMS → pull → JSON files → i18next → Your App
20
100
 
21
101
  ---
22
102
 
23
- # Setup Handleiding — Van Nul Tot Functie
103
+ ## Programmatic API Reference
104
+
105
+ Use these functions when you need fine-grained control or integration with
106
+ custom workflows. Perfect for CI/CD pipelines, build tools, or custom scripts.
107
+
108
+ ### `syncTranslations(options?)`
109
+
110
+ Scans your codebase for translation keys and uploads them to the CMS.
24
111
 
25
- ## Stap 1: Vereisten
112
+ ```ts
113
+ import { syncTranslations } from '@translation-cms/sync/api';
114
+
115
+ const result = await syncTranslations({
116
+ projectRoot: './apps/web', // auto-detect if omitted
117
+ dryRun: false, // preview without uploading
118
+ force: false, // ignore cache
119
+ reportPath: './sync-report.json', // optional report output
120
+ verbose: true, // detailed logging
121
+ });
26
122
 
27
- Controleer wat je nodig hebt:
123
+ console.log(`Added ${result.keysAdded} keys`);
124
+ ```
28
125
 
29
- - ✅ Next.js project (v14+)
30
- - ✅ pnpm (aanbevolen) of npm
31
- - ✅ Translations CMS account + project aangemaakt
32
- - ✅ CMS project credentials (URL, project ID, API key)
126
+ ### `pullTranslations(options?)`
33
127
 
34
- ## Stap 2: Installatie
128
+ Fetches translations from the CMS and writes them as JSON files.
129
+
130
+ ```ts
131
+ import { pullTranslations } from '@translation-cms/sync/api';
132
+
133
+ const result = await pullTranslations({
134
+ projectRoot: './apps/web', // auto-detect if omitted
135
+ outputDir: './src/i18n/locales', // custom output location
136
+ force: false, // ignore cache
137
+ ttl: 300000, // cache duration in ms
138
+ environment: 'production', // pull from specific env
139
+ verbose: true, // detailed logging
140
+ });
141
+ ```
142
+
143
+ ### `syncAndPull(options?)`
144
+
145
+ Convenience function: sync keys then pull translations in one call.
146
+
147
+ ```ts
148
+ import { syncAndPull } from '@translation-cms/sync/api';
149
+
150
+ const { synced, pulled } = await syncAndPull({
151
+ projectRoot: './apps/web',
152
+ verbose: true,
153
+ });
154
+ ```
155
+
156
+ ---
157
+
158
+ # Setup Guide — From Zero to Working
159
+
160
+ ## Step 1: Prerequisites
161
+
162
+ Check what you need:
163
+
164
+ - Next.js project (v14+)
165
+ - pnpm (recommended) or npm
166
+ - Translations CMS account + project created
167
+ - CMS project credentials (URL, project ID, API key)
168
+
169
+ ## Step 2: Installation
35
170
 
36
171
  ```bash
37
172
  pnpm add @translation-cms/sync
38
173
  ```
39
174
 
40
- Plus de peer dependencies:
175
+ Plus the peer dependencies:
41
176
 
42
177
  ```bash
43
178
  pnpm add i18next react-i18next i18next-resources-to-backend
44
179
  ```
45
180
 
46
- ## Stap 3: CMS Credentials Instellen
181
+ ## Step 3: Set Up CMS Credentials
47
182
 
48
- Maak `.env.local` aan in je project root:
183
+ Create `.env.local` in your project root:
49
184
 
50
185
  ```bash
51
186
  NEXT_PUBLIC_CMS_URL=https://cms.example.com
52
187
  NEXT_PUBLIC_CMS_PROJECT_ID=your-project-id
53
- NEXT_PUBLIC_CMS_ANON_KEY=your-api-key
188
+ CMS_SYNC_API_KEY=your-jwt-api-key
54
189
  ```
55
190
 
56
- Deze krijg je uit je CMS project settings.
191
+ The `CMS_SYNC_API_KEY` is a **JWT token**. You can find it in the CMS under
192
+ **Project Settings → Environments → your environment → API Key**. If the key
193
+ there still looks like a UUID, use "Regenerate" to generate a JWT.
194
+
195
+ > **Note:** use `CMS_SYNC_API_KEY` (without `NEXT_PUBLIC_`). This prevents the
196
+ > JWT from accidentally ending up in the browser. The old name
197
+ > `NEXT_PUBLIC_CMS_ANON_KEY` still works as a fallback, but is discouraged.
57
198
 
58
- ## Stap 4: Automatische Setup (Aanbevolen)
199
+ ## Step 4: Automatic Setup (Recommended)
59
200
 
60
- Run de interactive setup wizard:
201
+ Run the interactive setup wizard:
61
202
 
62
203
  ```bash
63
204
  pnpm sync-translations init
64
205
  ```
65
206
 
66
- Dit maakt automatisch aan:
207
+ This automatically creates:
67
208
 
68
209
  ```
69
210
  src/lib/i18n/
70
- ├── settings.ts # i18next configuratie
71
- ├── types.ts # TypeScript types voor translations
211
+ ├── settings.ts # i18next configuration
212
+ ├── types.ts # TypeScript types for translations
72
213
  ├── client.ts # 'use client' hook + static imports
73
214
  ├── server.ts # Server component support
74
215
  ├── provider.tsx # Provider wrapper
75
216
  └── dictionaries/
76
- ├── en.json # Engels (leeg, wordt gevuld door pull)
77
- └── nl.json # Nederlands (leeg, wordt gevuld door pull)
217
+ ├── en.json # English (empty, filled by pull)
218
+ └── nl.json # Dutch (empty, filled by pull)
78
219
  ```
79
220
 
80
- Ook `.translationsrc.json` wordt gegenereerd:
221
+ Also `.translationsrc.json` is generated:
81
222
 
82
223
  ```json
83
224
  {
@@ -88,57 +229,56 @@ Ook `.translationsrc.json` wordt gegenereerd:
88
229
  }
89
230
  ```
90
231
 
91
- **Let op:** `routeParams` kan leeg blijven! De scanner genereert automatisch
92
- sensible defaults voor alle dynamic routes.
232
+ **Note:** `routeParams` can stay empty! The scanner automatically generates
233
+ sensible defaults for all dynamic routes.
93
234
 
94
- ## Stap 5: Eerste Sync — Keys Uploaden
235
+ ## Step 5: First Sync — Upload Keys
95
236
 
96
- Scan je code en upload gedetecteerde keys naar de CMS:
237
+ Scan your code and upload detected keys to the CMS:
97
238
 
98
239
  ```bash
99
240
  pnpm sync-translations sync
100
241
  ```
101
242
 
102
- Dit zal:
243
+ This will:
103
244
 
104
- 1. Je code scannen op translation keys (`t('namespace:key')` patroon)
105
- 2. Route detecteren waar elke key gebruikt wordt
106
- 3. Nieuwe keys naar CMS uploaden
107
- 4. Rapport tonen (welke keys toegevoegd/gewijzigd)
245
+ 1. Scan your code for translation keys (`t('namespace:key')` pattern)
246
+ 2. Detect routes where each key is used
247
+ 3. Upload new keys to CMS
248
+ 4. Show report (which keys added/changed)
108
249
 
109
- Controleer in de CMS of je keys verschenen zijn ✅
250
+ Check in the CMS if your keys appeared.
110
251
 
111
- **Bij eerste sync:** je krijgt mogelijk een error dat geen vertalingen kunnen
112
- worden gedownload dit is normaal! De keys zijn net geupload maar hebben nog
113
- geen vertalingen. Ga naar je CMS, vul vertalingen in, dan draai je `pull`
114
- opnieuw.
252
+ **On first sync:** you might get an error that no translations can be downloaded
253
+ this is normal! The keys were just uploaded but don't have translations yet.
254
+ Go to your CMS, fill in translations, then run `pull` again.
115
255
 
116
- ## Stap 5b: Vertalingen Toevoegen in CMS
256
+ ## Step 5b: Add Translations in CMS
117
257
 
118
- 1. Open je Translations CMS project
119
- 2. Je keys staan nu gelistd (zonder vertalingen)
120
- 3. Vul vertalingen in per locale (English, Nederlands, etc.)
121
- 4. Klik Save
258
+ 1. Open your Translations CMS project
259
+ 2. Your keys are now listed (without translations)
260
+ 3. Fill in translations per locale (English, Dutch, etc.)
261
+ 4. Click Save
122
262
 
123
- ## Stap 6: Vertalingen Ophalen
263
+ ## Step 6: Fetch Translations
124
264
 
125
- Als je de eerste sync hebt gedaan EN vertalingen in de CMS hebt ingevuld:
265
+ If you've done the first sync AND filled in translations in the CMS:
126
266
 
127
267
  ```bash
128
268
  pnpm sync-translations pull
129
269
  ```
130
270
 
131
- Dit haalt vertalingen op van de CMS en schrijft ze naar lokale JSON:
271
+ This fetches translations from the CMS and writes them to local JSON:
132
272
 
133
- - `dictionaries/en.json` → English vertalingen
134
- - `dictionaries/nl.json` → Nederlandse vertalingen
135
- - etc. (één per locale)
273
+ - `dictionaries/en.json` → English translations
274
+ - `dictionaries/nl.json` → Dutch translations
275
+ - etc. (one per locale)
136
276
 
137
- ## Stap 7: Integratie in je Project
277
+ ## Step 7: Integration in Your Project
138
278
 
139
279
  ### A. Root Layout Setup
140
280
 
141
- Voeg de provider toe aan je `src/app/layout.tsx`:
281
+ Add the provider to your `src/app/layout.tsx`:
142
282
 
143
283
  ```tsx
144
284
  import { TranslationProvider } from '@/lib/i18n/provider';
@@ -158,7 +298,7 @@ export default function RootLayout({
158
298
  }
159
299
  ```
160
300
 
161
- ### B. Server Components (Aanbevolen)
301
+ ### B. Server Components (Recommended)
162
302
 
163
303
  ```tsx
164
304
  import { getTranslation } from '@/lib/i18n/server';
@@ -188,22 +328,22 @@ export function MyButton() {
188
328
  }
189
329
  ```
190
330
 
191
- ### D. Multiple Namespaces (Met Type-Checking)
331
+ ### D. Multiple Namespaces (With Type-Checking)
192
332
 
193
333
  ```tsx
194
334
  const { t } = useTranslation(['common', 'auth']);
195
335
 
196
- // Dit werkt
336
+ // This works
197
337
  t('common:nav.home');
198
338
  t('auth:login.email');
199
339
 
200
- // Dit geeft een type error
201
- t('payments:amount'); // namespace niet toegevoegd
340
+ // This gives a type error
341
+ t('payments:amount'); // namespace not added
202
342
  ```
203
343
 
204
- ## Stap 8: Automatische Sync in je Workflow
344
+ ## Step 8: Automatic Sync in Your Workflow
205
345
 
206
- Voeg dit toe aan `package.json`:
346
+ Add this to `package.json`:
207
347
 
208
348
  ```json
209
349
  {
@@ -214,14 +354,14 @@ Voeg dit toe aan `package.json`:
214
354
  }
215
355
  ```
216
356
 
217
- Nu pull je automatisch de latest vertalingen bij startup
357
+ Now you automatically pull the latest translations on startup.
218
358
 
219
- ## Stap 9 (Optioneel): Preview Mode Instellen
359
+ ## Step 9 (Optional): Set Up Preview Mode
220
360
 
221
- Enable live in-context preview — editors kunnen live zien hoe hun tekst in je
222
- app eruit ziet.
361
+ Enable live in-context preview — editors can live see how their text looks in
362
+ your app.
223
363
 
224
- Voeg dit toe aan je root layout:
364
+ Add this to your root layout:
225
365
 
226
366
  ```tsx
227
367
  'use client';
@@ -233,7 +373,7 @@ export function CMSPreview() {
233
373
  if (process.env.NODE_ENV === 'development') {
234
374
  initPreviewListener({
235
375
  onLocaleSwitch: locale => {
236
- // wijzig taal als CMS een ander locale selecteert
376
+ // change language if CMS selects a different locale
237
377
  window.location.href = `/${locale}`;
238
378
  },
239
379
  });
@@ -243,7 +383,7 @@ export function CMSPreview() {
243
383
  }
244
384
  ```
245
385
 
246
- En voeg toe in layout:
386
+ And add to layout:
247
387
 
248
388
  ```tsx
249
389
  <TranslationProvider>
@@ -252,7 +392,7 @@ En voeg toe in layout:
252
392
  </TranslationProvider>
253
393
  ```
254
394
 
255
- Voeg `data-cms-key` toe op elementen voor nauwkeurige highlighting:
395
+ Add `data-cms-key` to elements for precise highlighting:
256
396
 
257
397
  ```tsx
258
398
  <h1 data-cms-key="common:page.title">{t('common:page.title')}</h1>
@@ -262,110 +402,122 @@ Voeg `data-cms-key` toe op elementen voor nauwkeurige highlighting:
262
402
 
263
403
  # CLI Commands Reference
264
404
 
265
- ## Basiscommands
405
+ ## Basic Commands
266
406
 
267
407
  ```bash
268
- # Scan code + upload naar CMS
408
+ # Scan code + upload to CMS
269
409
  pnpm sync-translations sync
270
410
 
271
- # Download vertalingen naar lokale JSON
411
+ # Download translations to local JSON
272
412
  pnpm sync-translations pull
273
413
 
274
- # Bekijk wat er zou veranderen (zonder upload)
414
+ # See what would change (without upload)
275
415
  pnpm sync-translations sync --dry-run
276
416
 
277
- # Bekijk verschil met vorige sync
417
+ # See difference from previous sync
278
418
  pnpm sync-translations status
279
419
 
280
- # Watch mode — auto-sync bij bestand wijzigingen
420
+ # Watch mode — auto-sync on file changes
281
421
  pnpm sync-translations watch
282
422
 
283
- # Interactieve setup
423
+ # Interactive setup
284
424
  pnpm sync-translations init
285
425
  ```
286
426
 
287
427
  ## Advanced Flags
288
428
 
289
- | Flag | Beschrijving |
290
- | ----------------- | ------------------------------------ |
291
- | `--dry-run` | Toon wijzigingen, voer niet uit |
292
- | `--force` | Negeer cache, force hernieuwen |
293
- | `--output <dir>` | Custom output map voor JSON |
294
- | `--env <name>` | Pull uit staging/production omgeving |
295
- | `--ttl <ms>` | Overschrijf cache TTL (ms) |
296
- | `--project-id` | Overschrijf project ID |
297
- | `--api-key` | Overschrijf API key |
298
- | `--cms-url` | Overschrijf CMS URL |
299
- | `--report <file>` | Schrijf sync rapport naar JSON file |
429
+ | Flag | Description |
430
+ | ----------------- | ---------------------------------------- |
431
+ | `--dry-run` | Show changes, don't execute |
432
+ | `--force` | Ignore cache, force refresh |
433
+ | `--output <dir>` | Custom output directory for JSON |
434
+ | `--env <name>` | Pull from staging/production environment |
435
+ | `--ttl <ms>` | Override cache TTL (ms) |
436
+ | `--project-id` | Override project ID |
437
+ | `--api-key` | Override API key |
438
+ | `--cms-url` | Override CMS URL |
439
+ | `--report <file>` | Write sync report to JSON file |
300
440
 
301
- ## Voorbeelden
441
+ ## Examples
302
442
 
303
443
  ```bash
304
- # Force refresh, negeer cache
444
+ # Force refresh, ignore cache
305
445
  pnpm sync-translations pull --force
306
446
 
307
447
  # Custom output directory
308
448
  pnpm sync-translations pull --output ./locales
309
449
 
310
- # Pull uit staging environment
450
+ # Pull from staging environment
311
451
  pnpm sync-translations pull --env staging
312
452
 
313
- # Schrijf rapport van wijzigingen
453
+ # Write report of changes
314
454
  pnpm sync-translations sync --report ./sync-report.json
315
455
  ```
316
456
 
317
457
  ---
318
458
 
319
- # Key Scanner — Hoe Werkt Het
459
+ # Key Scanner — How It Works
320
460
 
321
- De tool herkent deze patronen in je code:
461
+ The tool recognizes these patterns in your code:
322
462
 
323
463
  ```ts
324
- // React-i18next hook
464
+ // React-i18next hook
325
465
  const { t } = useTranslation('blog');
326
466
  t('blog:post.title');
327
467
 
328
- // Trans component
468
+ // Server-side helper
469
+ const { t } = await getTranslation('blog');
470
+ t('blog:post.title');
471
+
472
+ // CMS client helper
473
+ const t = await client.getTranslations(locale, 'blog');
474
+ t('blog:post.title');
475
+
476
+ // Trans component
329
477
  <Trans i18nKey="blog:post.title" />
330
478
 
331
- // String literal
332
- const key = 'blog:post.title';
479
+ // I18nKey-typed config (only if the file imports `I18nKey`)
480
+ import type { I18nKey } from '@/lib/i18n/types';
481
+ const label: I18nKey = 'sidebar:settings';
482
+
483
+ // Object properties ending in "Key"
484
+ const config = { titleKey: 'blog:post.title' };
333
485
  ```
334
486
 
335
487
  ### Format: `namespace:key`
336
488
 
337
- Alle keys moeten dit format volgen. Anders krijg je een warning:
489
+ All keys must follow this format. Otherwise you'll get a warning:
338
490
 
339
491
  ```ts
340
- // ✅ Goed
492
+ // Good
341
493
  t('common:button.save');
342
494
 
343
- // Fout — namespace mist
495
+ // Wrong — namespace missing
344
496
  t('save');
345
497
  ```
346
498
 
347
- ### Dynamische Routes — Auto-Generated routeParams
499
+ ### Dynamic Routes — Auto-Generated routeParams
348
500
 
349
- **Hoe het werkt:**
501
+ **How it works:**
350
502
 
351
- Bij elke `pnpm sync-translations sync`:
503
+ At each `pnpm sync-translations sync`:
352
504
 
353
- 1. Scanner detecteert automatisch alle routes met dynamic parameters (bijv.
505
+ 1. Scanner automatically detects all routes with dynamic parameters (e.g.
354
506
  `/[locale]/blog/[slug]`)
355
- 2. Voor elke `[param]` wordt automatisch een sensible default gegenereerd:
507
+ 2. For each `[param]` a sensible default is automatically generated:
356
508
  - `locale` / `lang` → `"en"`
357
509
  - `id`, `postId`, `productId` → `"123"`
358
510
  - `slug` → `"demo"`
359
511
  - `username` → `"demo-user"`
360
512
  - `email` → `"demo@example.com"`
361
- 3. Dit wordt opgeslagen in `.cms-sync-cache-meta.json` (mag je negeren)
362
- 4. De CMS gebruikt deze om werkende preview URLs te genereren
513
+ 3. This is saved in `.cms-sync-cache-meta.json` (you can ignore it)
514
+ 4. The CMS uses this to generate working preview URLs
363
515
 
364
- **Je hoeft niks te doen!** — alles werkt out-of-the-box.
516
+ **You don't have to do anything!** — everything works out-of-the-box.
365
517
 
366
- **Handmatig overschrijven (optioneel):**
518
+ **Manual override (optional):**
367
519
 
368
- Als je andere test-waarden wil gebruiken, vul je `.translationsrc.json` in:
520
+ If you want to use different test values, fill in `.translationsrc.json`:
369
521
 
370
522
  ```json
371
523
  {
@@ -376,21 +528,21 @@ Als je andere test-waarden wil gebruiken, vul je `.translationsrc.json` in:
376
528
  }
377
529
  ```
378
530
 
379
- Dit overschrijft de auto-generated waarden. Alles wat je hier toevoegt krijgt
380
- prioriteit.
531
+ This overrides the auto-generated values. Everything you add here takes
532
+ priority.
381
533
 
382
- ### Cache bestanden
534
+ ### Cache Files
383
535
 
384
- Bij elke sync worden twee cache bestanden aangemaakt:
536
+ At each sync two cache files are created:
385
537
 
386
- - `.cms-sync-cache.json` — Geüploade keys en hun routes (voor diff bij volgende
538
+ - `.cms-sync-cache.json` — Uploaded keys and their routes (for diff on next
387
539
  sync)
388
- - `.cms-sync-cache-meta.json` — Auto-generated route params (mag je .gitignore
389
- toevoegen)
540
+ - `.cms-sync-cache-meta.json` — Auto-generated route params (you can add to
541
+ .gitignore)
390
542
 
391
- ### Scanner Opties
543
+ ### Scanner Options
392
544
 
393
- Customize scan gedrag in `.translationsrc.json`:
545
+ Customize scan behavior in `.translationsrc.json`:
394
546
 
395
547
  ```json
396
548
  {
@@ -406,8 +558,8 @@ Customize scan gedrag in `.translationsrc.json`:
406
558
 
407
559
  ## Preview Mode — Live Highlighting
408
560
 
409
- Editors kunnen in de CMS klikken op "Show in app" en je app opent in een iframe
410
- met live highlighting van het element.
561
+ Editors can click "Show in app" in the CMS and your app opens in an iframe with
562
+ live highlighting of the element.
411
563
 
412
564
  ### Setup
413
565
 
@@ -428,7 +580,7 @@ useEffect(() => {
428
580
 
429
581
  ### Element Targeting
430
582
 
431
- Gebruik `data-cms-key` voor nauwkeurige targeting:
583
+ Use `data-cms-key` for precise targeting:
432
584
 
433
585
  ```tsx
434
586
  <h1 data-cms-key="blog:title">{t('blog:title')}</h1>
@@ -439,82 +591,83 @@ Gebruik `data-cms-key` voor nauwkeurige targeting:
439
591
 
440
592
  # JSON Output Format
441
593
 
442
- Na `sync-translations pull` worden dit soort bestanden gegenereerd:
594
+ After `sync-translations pull` these kinds of files are generated:
443
595
 
444
596
  ```json
445
597
  {
446
598
  "common": {
447
- "app.title": "Mijn App",
448
- "button.save": "Opslaan",
599
+ "app.title": "My App",
600
+ "button.save": "Save",
449
601
  "nav.home": "Home"
450
602
  },
451
603
  "auth": {
452
604
  "login.email": "Email",
453
- "login.password": "Wachtwoord"
605
+ "login.password": "Password"
454
606
  }
455
607
  }
456
608
  ```
457
609
 
458
- **Structuur:**
610
+ **Structure:**
459
611
 
460
612
  - Top-level keys = namespaces
461
613
  - Nested keys = translation strings
462
- - 1 bestand per taal (`en.json`, `nl.json`, etc.)
614
+ - 1 file per language (`en.json`, `nl.json`, etc.)
463
615
 
464
616
  ---
465
617
 
466
618
  # Troubleshooting
467
619
 
468
- ### Geen keys gevonden
620
+ ### No keys found
469
621
 
470
622
  ```bash
471
- # Check scanner configuratie
623
+ # Check scanner configuration
472
624
  pnpm sync-translations sync --dry-run
473
625
  ```
474
626
 
475
- Zorg dat je keys `namespace:key` format gebruiken.
627
+ Make sure your keys use `namespace:key` format.
476
628
 
477
- ### Environment variables niet gevonden
629
+ ### Environment variables not found
478
630
 
479
- Controleer `.env.local`:
631
+ Check `.env.local`:
480
632
 
481
633
  ```bash
482
- cat .env.local | grep NEXT_PUBLIC_CMS
634
+ grep -E 'CMS_URL|CMS_PROJECT_ID|CMS_SYNC_API_KEY' .env.local
483
635
  ```
484
636
 
485
- Moet `NEXT_PUBLIC_CMS_URL`, `NEXT_PUBLIC_CMS_PROJECT_ID`,
486
- `NEXT_PUBLIC_CMS_ANON_KEY` bevatten.
637
+ Must contain `NEXT_PUBLIC_CMS_URL`, `NEXT_PUBLIC_CMS_PROJECT_ID` and
638
+ `CMS_SYNC_API_KEY`. The value of `CMS_SYNC_API_KEY` is a JWT token — get it from
639
+ the CMS Project Settings.
487
640
 
488
- ### Pull werkt niet
641
+ ### Pull doesn't work
489
642
 
490
643
  ```bash
491
- # Force refresh, negeer cache
644
+ # Force refresh, ignore cache
492
645
  pnpm sync-translations pull --force
493
646
 
494
- # Check configuratie
647
+ # Check configuration
495
648
  cat .translationsrc.json
496
649
  ```
497
650
 
498
651
  ### Type errors in TypeScript
499
652
 
500
- Zorg dat `src/lib/i18n/types.ts` correct gegenereerd is en dat je namespaces in
501
- `.translationsrc.json` staan.
653
+ Make sure `src/lib/i18n/types.ts` is generated correctly and that your
654
+ namespaces are in `.translationsrc.json`.
502
655
 
503
656
  ---
504
657
 
505
658
  # Best Practices
506
659
 
507
- 1. **Gebruik server components** waar mogelijkbeter voor performance
508
- 2. **Voeg `data-cms-key` toe** op visueel belangrijke elementen
509
- 3. **Commit `.translationsrc.json`** naar git — niet `.env.local`
510
- 4. **Negeer cache bestanden:** voeg toe aan `.gitignore`:
660
+ 1. **Use server components** where possiblebetter for performance
661
+ 2. **Add `data-cms-key`** on visually important elements
662
+ 3. **Commit `.translationsrc.json`** to git — not `.env.local`
663
+ 4. **Ignore cache files:** add to `.gitignore`:
511
664
  ```
512
665
  .cms-sync-cache.json
513
666
  .cms-sync-cache-meta.json
514
667
  .last-pulled
515
668
  ```
516
- 5. **Run `sync` in CI/CD** op main branch — catch missing translations
517
- 6. **Voeg `pull` toe aan build script** — altijd fresh translations
669
+ 5. **Run `sync` in CI/CD** on main branch — catch missing translations
670
+ 6. **Add `pull` to build script** — always fresh translations
518
671
 
519
672
  ---
520
673