@intlayer/docs 9.0.0-canary.2 → 9.0.0-canary.3
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/docs/ar/plugins/sync-json.md +222 -49
- package/docs/de/plugins/sync-json.md +222 -49
- package/docs/en/plugins/sync-json.md +56 -2
- package/docs/en-GB/plugins/sync-json.md +245 -13
- package/docs/es/plugins/sync-json.md +222 -49
- package/docs/fr/plugins/sync-json.md +244 -12
- package/docs/hi/plugins/sync-json.md +221 -48
- package/docs/id/plugins/sync-json.md +222 -49
- package/docs/it/plugins/sync-json.md +224 -51
- package/docs/ja/plugins/sync-json.md +222 -49
- package/docs/ko/plugins/sync-json.md +223 -50
- package/docs/pl/plugins/sync-json.md +246 -14
- package/docs/pt/plugins/sync-json.md +222 -49
- package/docs/ru/plugins/sync-json.md +269 -95
- package/docs/tr/plugins/sync-json.md +222 -50
- package/docs/uk/plugins/sync-json.md +56 -2
- package/docs/vi/plugins/sync-json.md +230 -57
- package/docs/zh/plugins/sync-json.md +223 -50
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-03-13
|
|
3
|
-
updatedAt:
|
|
3
|
+
updatedAt: 2026-06-21
|
|
4
4
|
title: Sync JSON plugin
|
|
5
5
|
description: Synchronise Intlayer dictionaries with third‑party i18n JSON files (i18next, next-intl, react-intl, vue-i18n, and more). Keep your existing i18n while using Intlayer to manage, translate, and test your messages.
|
|
6
6
|
keywords:
|
|
@@ -24,6 +24,9 @@ slugs:
|
|
|
24
24
|
- sync-json
|
|
25
25
|
youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
|
|
26
26
|
history:
|
|
27
|
+
- version: 9.0.0
|
|
28
|
+
date: 2026-06-21
|
|
29
|
+
changes: "Add splitKeys option (one dictionary per top-level namespace key) for next-intl / react-intl single-file layouts"
|
|
27
30
|
- version: 7.5.0
|
|
28
31
|
date: 2025-12-13
|
|
29
32
|
changes: "Add ICU and i18next format support"
|
|
@@ -41,7 +44,7 @@ Use Intlayer as an add‑on to your existing i18n stack. This plugin keeps your
|
|
|
41
44
|
|
|
42
45
|
- Keep i18next, next‑intl, react‑intl, vue‑i18n, next‑translate, nuxt‑i18n, Solid‑i18next, svelte‑i18n, etc.
|
|
43
46
|
- Manage and translate your messages with Intlayer (CLI, CI, providers, CMS), without refactoring your app.
|
|
44
|
-
- Deliver tutorials and SEO content targeting each ecosystem,
|
|
47
|
+
- Deliver tutorials and SEO content targeting each ecosystem, whilst recommending Intlayer as the JSON management layer.
|
|
45
48
|
|
|
46
49
|
Notes and current scope:
|
|
47
50
|
|
|
@@ -62,7 +65,63 @@ pnpm add -D @intlayer/sync-json-plugin
|
|
|
62
65
|
npm i -D @intlayer/sync-json-plugin
|
|
63
66
|
```
|
|
64
67
|
|
|
65
|
-
##
|
|
68
|
+
## Plugins
|
|
69
|
+
|
|
70
|
+
This package provides two plugins:
|
|
71
|
+
|
|
72
|
+
- `loadJSON`: Load JSON files into Intlayer dictionaries.
|
|
73
|
+
- This plugin is used to load JSON files from a source and will be loaded into Intlayer dictionaries. It can scan all the codebase and search for specific JSON files.
|
|
74
|
+
This plugin can be used
|
|
75
|
+
- if you use an i18n library that imposes a specific location for your JSON to be loaded (ex: `next-intl`, `i18next`, `react-intl`, `vue-i18n`, etc.), but you want to place your content declaration where you want in your code base.
|
|
76
|
+
- It can also be used if you want to fetch your messages from a remote source (ex: a CMS, an API, etc.) and store your messages in JSON files.
|
|
77
|
+
|
|
78
|
+
> Under the hood, this plugin will scan all the codebase and search for specific JSON files and load them into Intlayer dictionaries.
|
|
79
|
+
> Note that this plugin will not write the output and translations back to the JSON files.
|
|
80
|
+
|
|
81
|
+
- `syncJSON`: Synchronise JSON files with Intlayer dictionaries.
|
|
82
|
+
- This plugin is used to synchronise JSON files with Intlayer dictionaries. It can scan the given location and load the JSON that match the pattern for specific JSON files. This plugin is useful if you want to get the benefits of Intlayer whilst using another i18n library.
|
|
83
|
+
|
|
84
|
+
## Using both plugins
|
|
85
|
+
|
|
86
|
+
```ts fileName="intlayer.config.ts"
|
|
87
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
88
|
+
import { loadJSON, syncJSON } from "@intlayer/sync-json-plugin";
|
|
89
|
+
|
|
90
|
+
const config: IntlayerConfig = {
|
|
91
|
+
internationalization: {
|
|
92
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
93
|
+
defaultLocale: Locales.ENGLISH,
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
// Keep your current JSON files in sync with Intlayer dictionaries
|
|
97
|
+
plugins: [
|
|
98
|
+
/**
|
|
99
|
+
* Will load all the JSON files in the src that match the pattern {key}.i18n json
|
|
100
|
+
*/
|
|
101
|
+
loadJSON({
|
|
102
|
+
source: ({ key }) => `./src/**/${key}.i18n.json`,
|
|
103
|
+
locale: Locales.ENGLISH,
|
|
104
|
+
priority: 1, // Ensures these JSON files take precedence over files at `./locales/en/${key}.json`
|
|
105
|
+
format: "intlayer", // Format of the JSON content
|
|
106
|
+
}),
|
|
107
|
+
/**
|
|
108
|
+
* Will load, and write the output and translations back to the JSON files in the locales directory
|
|
109
|
+
*/
|
|
110
|
+
syncJSON({
|
|
111
|
+
format: "i18next",
|
|
112
|
+
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
113
|
+
priority: 0,
|
|
114
|
+
format: "i18next",
|
|
115
|
+
}),
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export default config;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## `syncJSON` plugin
|
|
123
|
+
|
|
124
|
+
### Quick start
|
|
66
125
|
|
|
67
126
|
Add the plugin to your `intlayer.config.ts` and point it at your existing JSON structure.
|
|
68
127
|
|
|
@@ -81,6 +140,7 @@ const config: IntlayerConfig = {
|
|
|
81
140
|
syncJSON({
|
|
82
141
|
// Per-locale, per-namespace layout (e.g., next-intl, i18next with namespaces)
|
|
83
142
|
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
143
|
+
format: "icu",
|
|
84
144
|
}),
|
|
85
145
|
],
|
|
86
146
|
};
|
|
@@ -91,14 +151,27 @@ export default config;
|
|
|
91
151
|
Alternative: single file per locale (common with i18next/react-intl setups):
|
|
92
152
|
|
|
93
153
|
```ts fileName="intlayer.config.ts"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
154
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
155
|
+
import { syncJSON } from "@intlayer/sync-json-plugin";
|
|
156
|
+
|
|
157
|
+
const config: IntlayerConfig = {
|
|
158
|
+
internationalization: {
|
|
159
|
+
locales: [Locales.ENGLISH, Locales.FRENCH],
|
|
160
|
+
defaultLocale: Locales.ENGLISH,
|
|
161
|
+
},
|
|
162
|
+
plugins: [
|
|
163
|
+
syncJSON({
|
|
164
|
+
format: "i18next",
|
|
165
|
+
source: ({ locale }) => `./locales/${locale}.json`,
|
|
166
|
+
format: "i18next",
|
|
167
|
+
}),
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export default config;
|
|
99
172
|
```
|
|
100
173
|
|
|
101
|
-
|
|
174
|
+
#### How it works
|
|
102
175
|
|
|
103
176
|
- Read: the plugin discovers JSON files from your `source` builder and loads them as Intlayer dictionaries.
|
|
104
177
|
- Write: after builds and fills, it writes localised JSON back to the same paths (with a final newline to avoid formatting issues).
|
|
@@ -112,6 +185,7 @@ syncJSON({
|
|
|
112
185
|
location?: string, // optional label, default: "plugin"
|
|
113
186
|
priority?: number, // optional priority for conflict resolution, default: 0
|
|
114
187
|
format?: 'intlayer' | 'icu' | 'i18next', // optional formatter, used for intlayer runtime compatibility
|
|
188
|
+
splitKeys?: boolean, // optional, split a single file into one dictionary per top-level key (auto-detected)
|
|
115
189
|
});
|
|
116
190
|
```
|
|
117
191
|
|
|
@@ -136,17 +210,49 @@ syncJSON({
|
|
|
136
210
|
}),
|
|
137
211
|
```
|
|
138
212
|
|
|
139
|
-
|
|
213
|
+
#### `splitKeys` (boolean)
|
|
214
|
+
|
|
215
|
+
Controls whether a single JSON file whose **first-level keys are namespaces** should become one dictionary per top-level key, instead of a single dictionary holding the whole file.
|
|
216
|
+
|
|
217
|
+
This matches the namespace model of libraries like `next-intl` and `react-intl`, where one `messages/{locale}.json` file groups several namespaces by its first-level keys, each addressed independently (e.g. `useTranslations('Hero')` resolves to the `Hero` dictionary).
|
|
218
|
+
|
|
219
|
+
- `undefined` (default): **auto-detected** — the file is split when the `source` pattern has no `{key}` segment (one file holds every namespace), and kept as a single dictionary otherwise (one file per key).
|
|
220
|
+
- `true`: always split each top-level key into its own dictionary.
|
|
221
|
+
- `false`: never split; the whole file becomes a single dictionary.
|
|
222
|
+
|
|
223
|
+
Given a single `messages/{locale}.json` file:
|
|
224
|
+
|
|
225
|
+
```json fileName="messages/en.json"
|
|
226
|
+
{
|
|
227
|
+
"Hero": { "title": "Full-stack developer" },
|
|
228
|
+
"Nav": { "work": "Work", "about": "About" },
|
|
229
|
+
"About": { "lead": "I build apps end to end." }
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```ts fileName="intlayer.config.ts"
|
|
234
|
+
syncJSON({
|
|
235
|
+
format: "icu",
|
|
236
|
+
source: ({ locale }) => `./messages/${locale}.json`,
|
|
237
|
+
// splitKeys: true, // implied because the pattern has no `{key}` segment
|
|
238
|
+
}),
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
This produces three dictionaries — `Hero`, `Nav`, and `About` — so `useTranslations('Hero')` (next-intl) resolves correctly. On write-back, all namespaces are re-assembled into the same per-locale file.
|
|
242
|
+
|
|
243
|
+
> When you keep the explicit `{key}` segment in your `source` (e.g. `./locales/${locale}/${key}.json`), each file is already one namespace, so splitting is disabled by default.
|
|
244
|
+
|
|
245
|
+
### Multiple JSON sources and priority
|
|
140
246
|
|
|
141
247
|
You can add multiple `syncJSON` plugins to synchronise different JSON sources. This is useful when you have multiple i18n libraries or different JSON structures in your project.
|
|
142
248
|
|
|
143
|
-
|
|
249
|
+
#### Priority system
|
|
144
250
|
|
|
145
251
|
When multiple plugins target the same dictionary key, the `priority` parameter determines which plugin takes precedence:
|
|
146
252
|
|
|
147
253
|
- Higher priority numbers win over lower ones
|
|
148
254
|
- Default priority of `.content` files is `0`
|
|
149
|
-
- Default priority of plugins
|
|
255
|
+
- Default priority of plugins is `0`
|
|
150
256
|
- Plugins with the same priority are processed in the order they appear in the configuration
|
|
151
257
|
|
|
152
258
|
```ts fileName="intlayer.config.ts"
|
|
@@ -189,7 +295,133 @@ const config: IntlayerConfig = {
|
|
|
189
295
|
export default config;
|
|
190
296
|
```
|
|
191
297
|
|
|
192
|
-
|
|
298
|
+
## Load JSON plugin
|
|
299
|
+
|
|
300
|
+
### Quick start
|
|
301
|
+
|
|
302
|
+
Add the plugin to your `intlayer.config.ts` to ingest existing JSON files as Intlayer dictionaries. This plugin is read‑only (no writes to disk):
|
|
303
|
+
|
|
304
|
+
```ts fileName="intlayer.config.ts"
|
|
305
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
306
|
+
import { loadJSON } from "@intlayer/sync-json-plugin";
|
|
307
|
+
|
|
308
|
+
const config: IntlayerConfig = {
|
|
309
|
+
internationalization: {
|
|
310
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
311
|
+
defaultLocale: Locales.ENGLISH,
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
plugins: [
|
|
315
|
+
// Ingest JSON messages located anywhere in your source tree
|
|
316
|
+
loadJSON({
|
|
317
|
+
source: ({ key }) => `./src/**/${key}.i18n.json`,
|
|
318
|
+
// Load a single locale per plugin instance (defaults to the config defaultLocale)
|
|
319
|
+
locale: Locales.ENGLISH,
|
|
320
|
+
priority: 0,
|
|
321
|
+
}),
|
|
322
|
+
],
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export default config;
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Alternative: per‑locale layout, still read‑only (only the selected locale is loaded):
|
|
329
|
+
|
|
330
|
+
```ts fileName="intlayer.config.ts"
|
|
331
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
332
|
+
import { loadJSON } from "@intlayer/sync-json-plugin";
|
|
333
|
+
|
|
334
|
+
const config: IntlayerConfig = {
|
|
335
|
+
internationalization: {
|
|
336
|
+
locales: [Locales.ENGLISH, Locales.FRENCH],
|
|
337
|
+
defaultLocale: Locales.ENGLISH,
|
|
338
|
+
},
|
|
339
|
+
plugins: [
|
|
340
|
+
loadJSON({
|
|
341
|
+
// Only files for Locales.FRENCH will be loaded from this pattern
|
|
342
|
+
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
343
|
+
locale: Locales.FRENCH,
|
|
344
|
+
}),
|
|
345
|
+
],
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
export default config;
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### How it works
|
|
352
|
+
|
|
353
|
+
- Discover: builds a glob from your `source` builder and collects matching JSON files.
|
|
354
|
+
- Ingest: loads each JSON file as an Intlayer dictionary with the provided `locale`.
|
|
355
|
+
- Read‑only: does not write or format output files; use `syncJSON` if you need round‑trip sync.
|
|
356
|
+
- Auto‑fill ready: defines a `fill` pattern so `intlayer content fill` can populate missing keys.
|
|
357
|
+
|
|
358
|
+
### API
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
loadJSON({
|
|
362
|
+
// Build paths to your JSON. `locale` is optional if your structure has no locale segment
|
|
363
|
+
source: ({ key, locale }) => string,
|
|
364
|
+
|
|
365
|
+
// Target locale for the dictionaries loaded by this plugin instance
|
|
366
|
+
// Defaults to configuration.internationalization.defaultLocale
|
|
367
|
+
locale?: Locale,
|
|
368
|
+
|
|
369
|
+
// Optional label to identify the source
|
|
370
|
+
location?: string, // default: "plugin"
|
|
371
|
+
|
|
372
|
+
// Priority used for conflict resolution against other sources
|
|
373
|
+
priority?: number, // default: 0
|
|
374
|
+
|
|
375
|
+
// Optional formatter for the JSON content
|
|
376
|
+
format?: 'intlayer' | 'icu' | 'i18next', // default: 'intlayer'
|
|
377
|
+
|
|
378
|
+
// Split a single file into one dictionary per top-level key (auto-detected)
|
|
379
|
+
splitKeys?: boolean,
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
384
|
+
|
|
385
|
+
Specifies the formatter to use for the dictionary content when loading JSON files. This allows using different message formatting syntaxes compatible with various i18n libraries.
|
|
386
|
+
|
|
387
|
+
- `'intlayer'`: The default Intlayer formatter (default).
|
|
388
|
+
- `'icu'`: Uses ICU message formatting (compatible with libraries like react-intl, vue-i18n).
|
|
389
|
+
- `'i18next'`: Uses i18next message formatting (compatible with i18next, next-i18next, Solid-i18next).
|
|
390
|
+
|
|
391
|
+
**Example:**
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
loadJSON({
|
|
395
|
+
source: ({ key }) => `./src/**/${key}.i18n.json`,
|
|
396
|
+
locale: Locales.ENGLISH,
|
|
397
|
+
format: "icu", // Use ICU formatting for compatibility
|
|
398
|
+
}),
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### `splitKeys` (boolean)
|
|
402
|
+
|
|
403
|
+
Same behaviour as in [`syncJSON`](#splitkeys-boolean): when a single JSON file groups several namespaces by its first-level keys, each top-level key becomes its own dictionary.
|
|
404
|
+
|
|
405
|
+
- `undefined` (default): **auto-detected** — split when the `source` pattern has no `{key}` segment, single dictionary otherwise.
|
|
406
|
+
- `true` / `false`: force or disable splitting.
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
loadJSON({
|
|
410
|
+
source: ({ locale }) => `./messages/${locale}.json`,
|
|
411
|
+
format: "icu",
|
|
412
|
+
// splitKeys auto-enabled: `Hero`, `Nav`, `About`, … each become a dictionary
|
|
413
|
+
}),
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Behavior and conventions
|
|
417
|
+
|
|
418
|
+
- If your `source` mask includes a locale placeholder, only files for the selected `locale` are ingested.
|
|
419
|
+
- If there is no `{key}` segment in your mask, each top-level key of the file becomes its own dictionary by default (see [`splitKeys`](#splitkeys-boolean)). Set `splitKeys: false` to instead load the whole file as a single `index` dictionary.
|
|
420
|
+
- Keys are derived from file paths by substituting the `{key}` placeholder in your `source` builder.
|
|
421
|
+
- The plugin only uses discovered files and does not fabricate missing locales or keys.
|
|
422
|
+
- The `fill` path is inferred from your `source` and used to update missing values via CLI when you opt‑in.
|
|
423
|
+
|
|
424
|
+
## Conflict resolution
|
|
193
425
|
|
|
194
426
|
When the same translation key exists in multiple JSON sources:
|
|
195
427
|
|