@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.
- package/README.md +304 -151
- package/dist/api.d.ts +79 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +151 -0
- package/dist/api.js.map +1 -0
- package/dist/bin.js +51 -17
- package/dist/bin.js.map +1 -1
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +18 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pull.d.ts +7 -0
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +15 -2
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/status.d.ts +12 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +16 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts +10 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +23 -4
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/watch.d.ts +14 -0
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +23 -3
- package/dist/commands/watch.js.map +1 -1
- package/dist/config/config-internals/args.d.ts +11 -0
- package/dist/config/config-internals/args.d.ts.map +1 -0
- package/dist/config/config-internals/args.js +22 -0
- package/dist/config/config-internals/args.js.map +1 -0
- package/dist/config/config-internals/env.d.ts +10 -0
- package/dist/config/config-internals/env.d.ts.map +1 -0
- package/dist/config/config-internals/env.js +35 -0
- package/dist/config/config-internals/env.js.map +1 -0
- package/dist/config/config-internals/file.d.ts +11 -0
- package/dist/config/config-internals/file.d.ts.map +1 -0
- package/dist/config/config-internals/file.js +28 -0
- package/dist/config/config-internals/file.js.map +1 -0
- package/dist/config/config-internals/resolve.d.ts +21 -0
- package/dist/config/config-internals/resolve.d.ts.map +1 -0
- package/dist/config/config-internals/resolve.js +73 -0
- package/dist/config/config-internals/resolve.js.map +1 -0
- package/dist/config/config-internals/root.d.ts +9 -0
- package/dist/config/config-internals/root.d.ts.map +1 -0
- package/dist/config/config-internals/root.js +22 -0
- package/dist/config/config-internals/root.js.map +1 -0
- package/dist/config/config-internals/types.d.ts +83 -0
- package/dist/config/config-internals/types.d.ts.map +1 -0
- package/dist/config/config-internals/types.js +9 -0
- package/dist/config/config-internals/types.js.map +1 -0
- package/dist/config/resolve-config.d.ts +9 -90
- package/dist/config/resolve-config.d.ts.map +1 -1
- package/dist/config/resolve-config.js +7 -123
- package/dist/config/resolve-config.js.map +1 -1
- package/dist/core/api-internals/pull.d.ts +9 -1
- package/dist/core/api-internals/pull.d.ts.map +1 -1
- package/dist/core/api-internals/pull.js +41 -28
- package/dist/core/api-internals/pull.js.map +1 -1
- package/dist/core/api-internals/sync.d.ts +9 -2
- package/dist/core/api-internals/sync.d.ts.map +1 -1
- package/dist/core/api-internals/sync.js +18 -2
- package/dist/core/api-internals/sync.js.map +1 -1
- package/dist/core/cache-internals/format.d.ts +16 -0
- package/dist/core/cache-internals/format.d.ts.map +1 -1
- package/dist/core/cache-internals/format.js +17 -0
- package/dist/core/cache-internals/format.js.map +1 -1
- package/dist/core/cache-internals/params.d.ts.map +1 -1
- package/dist/core/cache-internals/params.js +24 -24
- package/dist/core/cache-internals/params.js.map +1 -1
- package/dist/core/cache-internals/pull.d.ts +12 -0
- package/dist/core/cache-internals/pull.d.ts.map +1 -1
- package/dist/core/cache-internals/pull.js +13 -0
- package/dist/core/cache-internals/pull.js.map +1 -1
- package/dist/core/cache-internals/sync.d.ts +23 -0
- package/dist/core/cache-internals/sync.d.ts.map +1 -1
- package/dist/core/cache-internals/sync.js +33 -0
- package/dist/core/cache-internals/sync.js.map +1 -1
- package/dist/core/cache-internals/types.d.ts +20 -0
- package/dist/core/cache-internals/types.d.ts.map +1 -1
- package/dist/core/scanner-internals/ast.d.ts +23 -5
- package/dist/core/scanner-internals/ast.d.ts.map +1 -1
- package/dist/core/scanner-internals/ast.js +25 -5
- package/dist/core/scanner-internals/ast.js.map +1 -1
- package/dist/core/scanner-internals/file-walker.d.ts +3 -2
- package/dist/core/scanner-internals/file-walker.d.ts.map +1 -1
- package/dist/core/scanner-internals/file-walker.js +10 -12
- package/dist/core/scanner-internals/file-walker.js.map +1 -1
- package/dist/core/scanner-internals/import-resolver.d.ts +9 -1
- package/dist/core/scanner-internals/import-resolver.d.ts.map +1 -1
- package/dist/core/scanner-internals/import-resolver.js +58 -63
- package/dist/core/scanner-internals/import-resolver.js.map +1 -1
- package/dist/core/scanner-internals/key-extractor.d.ts +12 -8
- package/dist/core/scanner-internals/key-extractor.d.ts.map +1 -1
- package/dist/core/scanner-internals/key-extractor.js +125 -97
- package/dist/core/scanner-internals/key-extractor.js.map +1 -1
- package/dist/core/scanner-internals/route-detector.d.ts +16 -8
- package/dist/core/scanner-internals/route-detector.d.ts.map +1 -1
- package/dist/core/scanner-internals/route-detector.js +37 -33
- package/dist/core/scanner-internals/route-detector.js.map +1 -1
- package/dist/core/scanner.d.ts.map +1 -1
- package/dist/core/scanner.js +25 -8
- package/dist/core/scanner.js.map +1 -1
- package/dist/next.d.ts +28 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +65 -0
- package/dist/next.js.map +1 -0
- package/dist/preview/internals/highlight.d.ts +16 -7
- package/dist/preview/internals/highlight.d.ts.map +1 -1
- package/dist/preview/internals/highlight.js +71 -60
- package/dist/preview/internals/highlight.js.map +1 -1
- package/dist/scaffold/intenrals/scaffold.d.ts +17 -0
- package/dist/scaffold/intenrals/scaffold.d.ts.map +1 -1
- package/dist/scaffold/intenrals/scaffold.js +19 -0
- package/dist/scaffold/intenrals/scaffold.js.map +1 -1
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -1,18 +1,98 @@
|
|
|
1
1
|
# @translation-cms/sync
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
CMS,
|
|
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
|
-
##
|
|
7
|
+
## Integration Methods
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Choose the approach that fits your workflow:
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
+
console.log(`Added ${result.keysAdded} keys`);
|
|
124
|
+
```
|
|
28
125
|
|
|
29
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
181
|
+
## Step 3: Set Up CMS Credentials
|
|
47
182
|
|
|
48
|
-
|
|
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
|
-
|
|
188
|
+
CMS_SYNC_API_KEY=your-jwt-api-key
|
|
54
189
|
```
|
|
55
190
|
|
|
56
|
-
|
|
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
|
-
##
|
|
199
|
+
## Step 4: Automatic Setup (Recommended)
|
|
59
200
|
|
|
60
|
-
Run
|
|
201
|
+
Run the interactive setup wizard:
|
|
61
202
|
|
|
62
203
|
```bash
|
|
63
204
|
pnpm sync-translations init
|
|
64
205
|
```
|
|
65
206
|
|
|
66
|
-
|
|
207
|
+
This automatically creates:
|
|
67
208
|
|
|
68
209
|
```
|
|
69
210
|
src/lib/i18n/
|
|
70
|
-
├── settings.ts # i18next
|
|
71
|
-
├── types.ts # TypeScript types
|
|
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 #
|
|
77
|
-
└── nl.json #
|
|
217
|
+
├── en.json # English (empty, filled by pull)
|
|
218
|
+
└── nl.json # Dutch (empty, filled by pull)
|
|
78
219
|
```
|
|
79
220
|
|
|
80
|
-
|
|
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
|
-
**
|
|
92
|
-
sensible defaults
|
|
232
|
+
**Note:** `routeParams` can stay empty! The scanner automatically generates
|
|
233
|
+
sensible defaults for all dynamic routes.
|
|
93
234
|
|
|
94
|
-
##
|
|
235
|
+
## Step 5: First Sync — Upload Keys
|
|
95
236
|
|
|
96
|
-
Scan
|
|
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
|
-
|
|
243
|
+
This will:
|
|
103
244
|
|
|
104
|
-
1.
|
|
105
|
-
2.
|
|
106
|
-
3.
|
|
107
|
-
4.
|
|
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
|
-
|
|
250
|
+
Check in the CMS if your keys appeared.
|
|
110
251
|
|
|
111
|
-
**
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
##
|
|
256
|
+
## Step 5b: Add Translations in CMS
|
|
117
257
|
|
|
118
|
-
1. Open
|
|
119
|
-
2.
|
|
120
|
-
3.
|
|
121
|
-
4.
|
|
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
|
-
##
|
|
263
|
+
## Step 6: Fetch Translations
|
|
124
264
|
|
|
125
|
-
|
|
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
|
-
|
|
271
|
+
This fetches translations from the CMS and writes them to local JSON:
|
|
132
272
|
|
|
133
|
-
- `dictionaries/en.json` → English
|
|
134
|
-
- `dictionaries/nl.json` →
|
|
135
|
-
- etc. (
|
|
273
|
+
- `dictionaries/en.json` → English translations
|
|
274
|
+
- `dictionaries/nl.json` → Dutch translations
|
|
275
|
+
- etc. (one per locale)
|
|
136
276
|
|
|
137
|
-
##
|
|
277
|
+
## Step 7: Integration in Your Project
|
|
138
278
|
|
|
139
279
|
### A. Root Layout Setup
|
|
140
280
|
|
|
141
|
-
|
|
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 (
|
|
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 (
|
|
331
|
+
### D. Multiple Namespaces (With Type-Checking)
|
|
192
332
|
|
|
193
333
|
```tsx
|
|
194
334
|
const { t } = useTranslation(['common', 'auth']);
|
|
195
335
|
|
|
196
|
-
//
|
|
336
|
+
// This works
|
|
197
337
|
t('common:nav.home');
|
|
198
338
|
t('auth:login.email');
|
|
199
339
|
|
|
200
|
-
//
|
|
201
|
-
t('payments:amount'); // namespace
|
|
340
|
+
// This gives a type error
|
|
341
|
+
t('payments:amount'); // namespace not added
|
|
202
342
|
```
|
|
203
343
|
|
|
204
|
-
##
|
|
344
|
+
## Step 8: Automatic Sync in Your Workflow
|
|
205
345
|
|
|
206
|
-
|
|
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
|
-
|
|
357
|
+
Now you automatically pull the latest translations on startup.
|
|
218
358
|
|
|
219
|
-
##
|
|
359
|
+
## Step 9 (Optional): Set Up Preview Mode
|
|
220
360
|
|
|
221
|
-
Enable live in-context preview — editors
|
|
222
|
-
app
|
|
361
|
+
Enable live in-context preview — editors can live see how their text looks in
|
|
362
|
+
your app.
|
|
223
363
|
|
|
224
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
405
|
+
## Basic Commands
|
|
266
406
|
|
|
267
407
|
```bash
|
|
268
|
-
# Scan code + upload
|
|
408
|
+
# Scan code + upload to CMS
|
|
269
409
|
pnpm sync-translations sync
|
|
270
410
|
|
|
271
|
-
# Download
|
|
411
|
+
# Download translations to local JSON
|
|
272
412
|
pnpm sync-translations pull
|
|
273
413
|
|
|
274
|
-
#
|
|
414
|
+
# See what would change (without upload)
|
|
275
415
|
pnpm sync-translations sync --dry-run
|
|
276
416
|
|
|
277
|
-
#
|
|
417
|
+
# See difference from previous sync
|
|
278
418
|
pnpm sync-translations status
|
|
279
419
|
|
|
280
|
-
# Watch mode — auto-sync
|
|
420
|
+
# Watch mode — auto-sync on file changes
|
|
281
421
|
pnpm sync-translations watch
|
|
282
422
|
|
|
283
|
-
#
|
|
423
|
+
# Interactive setup
|
|
284
424
|
pnpm sync-translations init
|
|
285
425
|
```
|
|
286
426
|
|
|
287
427
|
## Advanced Flags
|
|
288
428
|
|
|
289
|
-
| Flag |
|
|
290
|
-
| ----------------- |
|
|
291
|
-
| `--dry-run` |
|
|
292
|
-
| `--force` |
|
|
293
|
-
| `--output <dir>` | Custom output
|
|
294
|
-
| `--env <name>` | Pull
|
|
295
|
-
| `--ttl <ms>` |
|
|
296
|
-
| `--project-id` |
|
|
297
|
-
| `--api-key` |
|
|
298
|
-
| `--cms-url` |
|
|
299
|
-
| `--report <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
|
-
##
|
|
441
|
+
## Examples
|
|
302
442
|
|
|
303
443
|
```bash
|
|
304
|
-
# Force refresh,
|
|
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
|
|
450
|
+
# Pull from staging environment
|
|
311
451
|
pnpm sync-translations pull --env staging
|
|
312
452
|
|
|
313
|
-
#
|
|
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 —
|
|
459
|
+
# Key Scanner — How It Works
|
|
320
460
|
|
|
321
|
-
|
|
461
|
+
The tool recognizes these patterns in your code:
|
|
322
462
|
|
|
323
463
|
```ts
|
|
324
|
-
//
|
|
464
|
+
// React-i18next hook
|
|
325
465
|
const { t } = useTranslation('blog');
|
|
326
466
|
t('blog:post.title');
|
|
327
467
|
|
|
328
|
-
//
|
|
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
|
-
//
|
|
332
|
-
|
|
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
|
-
|
|
489
|
+
All keys must follow this format. Otherwise you'll get a warning:
|
|
338
490
|
|
|
339
491
|
```ts
|
|
340
|
-
//
|
|
492
|
+
// Good
|
|
341
493
|
t('common:button.save');
|
|
342
494
|
|
|
343
|
-
//
|
|
495
|
+
// Wrong — namespace missing
|
|
344
496
|
t('save');
|
|
345
497
|
```
|
|
346
498
|
|
|
347
|
-
###
|
|
499
|
+
### Dynamic Routes — Auto-Generated routeParams
|
|
348
500
|
|
|
349
|
-
**
|
|
501
|
+
**How it works:**
|
|
350
502
|
|
|
351
|
-
|
|
503
|
+
At each `pnpm sync-translations sync`:
|
|
352
504
|
|
|
353
|
-
1. Scanner
|
|
505
|
+
1. Scanner automatically detects all routes with dynamic parameters (e.g.
|
|
354
506
|
`/[locale]/blog/[slug]`)
|
|
355
|
-
2.
|
|
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.
|
|
362
|
-
4.
|
|
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
|
-
**
|
|
516
|
+
**You don't have to do anything!** — everything works out-of-the-box.
|
|
365
517
|
|
|
366
|
-
**
|
|
518
|
+
**Manual override (optional):**
|
|
367
519
|
|
|
368
|
-
|
|
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
|
-
|
|
380
|
-
|
|
531
|
+
This overrides the auto-generated values. Everything you add here takes
|
|
532
|
+
priority.
|
|
381
533
|
|
|
382
|
-
### Cache
|
|
534
|
+
### Cache Files
|
|
383
535
|
|
|
384
|
-
|
|
536
|
+
At each sync two cache files are created:
|
|
385
537
|
|
|
386
|
-
- `.cms-sync-cache.json` —
|
|
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 (
|
|
389
|
-
|
|
540
|
+
- `.cms-sync-cache-meta.json` — Auto-generated route params (you can add to
|
|
541
|
+
.gitignore)
|
|
390
542
|
|
|
391
|
-
### Scanner
|
|
543
|
+
### Scanner Options
|
|
392
544
|
|
|
393
|
-
Customize scan
|
|
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
|
|
410
|
-
|
|
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
|
-
|
|
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
|
-
|
|
594
|
+
After `sync-translations pull` these kinds of files are generated:
|
|
443
595
|
|
|
444
596
|
```json
|
|
445
597
|
{
|
|
446
598
|
"common": {
|
|
447
|
-
"app.title": "
|
|
448
|
-
"button.save": "
|
|
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": "
|
|
605
|
+
"login.password": "Password"
|
|
454
606
|
}
|
|
455
607
|
}
|
|
456
608
|
```
|
|
457
609
|
|
|
458
|
-
**
|
|
610
|
+
**Structure:**
|
|
459
611
|
|
|
460
612
|
- Top-level keys = namespaces
|
|
461
613
|
- Nested keys = translation strings
|
|
462
|
-
- 1
|
|
614
|
+
- 1 file per language (`en.json`, `nl.json`, etc.)
|
|
463
615
|
|
|
464
616
|
---
|
|
465
617
|
|
|
466
618
|
# Troubleshooting
|
|
467
619
|
|
|
468
|
-
###
|
|
620
|
+
### No keys found
|
|
469
621
|
|
|
470
622
|
```bash
|
|
471
|
-
# Check scanner
|
|
623
|
+
# Check scanner configuration
|
|
472
624
|
pnpm sync-translations sync --dry-run
|
|
473
625
|
```
|
|
474
626
|
|
|
475
|
-
|
|
627
|
+
Make sure your keys use `namespace:key` format.
|
|
476
628
|
|
|
477
|
-
### Environment variables
|
|
629
|
+
### Environment variables not found
|
|
478
630
|
|
|
479
|
-
|
|
631
|
+
Check `.env.local`:
|
|
480
632
|
|
|
481
633
|
```bash
|
|
482
|
-
|
|
634
|
+
grep -E 'CMS_URL|CMS_PROJECT_ID|CMS_SYNC_API_KEY' .env.local
|
|
483
635
|
```
|
|
484
636
|
|
|
485
|
-
|
|
486
|
-
`
|
|
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
|
|
641
|
+
### Pull doesn't work
|
|
489
642
|
|
|
490
643
|
```bash
|
|
491
|
-
# Force refresh,
|
|
644
|
+
# Force refresh, ignore cache
|
|
492
645
|
pnpm sync-translations pull --force
|
|
493
646
|
|
|
494
|
-
# Check
|
|
647
|
+
# Check configuration
|
|
495
648
|
cat .translationsrc.json
|
|
496
649
|
```
|
|
497
650
|
|
|
498
651
|
### Type errors in TypeScript
|
|
499
652
|
|
|
500
|
-
|
|
501
|
-
`.translationsrc.json
|
|
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. **
|
|
508
|
-
2. **
|
|
509
|
-
3. **Commit `.translationsrc.json`**
|
|
510
|
-
4. **
|
|
660
|
+
1. **Use server components** where possible — better 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**
|
|
517
|
-
6. **
|
|
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
|
|