@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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-03-13
3
- updatedAt: 2025-12-13
3
+ updatedAt: 2026-06-21
4
4
  title: Plugin de sincronización JSON
5
5
  description: Sincroniza los diccionarios de Intlayer con archivos JSON i18n de terceros (i18next, next-intl, react-intl, vue-i18n y más). Mantén tu i18n existente mientras usas Intlayer para gestionar, traducir y probar tus mensajes.
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: "Añadida opción splitKeys (un diccionario por clave de espacio de nombres de nivel superior) para diseños de archivo único de next-intl / react-intl"
27
30
  - version: 7.5.0
28
31
  date: 2025-12-13
29
32
  changes: "Añadido soporte para formatos ICU e i18next"
@@ -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
- ## Inicio rápido
68
+ ## Plugins
69
+
70
+ Este paquete proporciona dos plugins:
71
+
72
+ - `loadJSON`: Carga archivos JSON en diccionarios de Intlayer.
73
+ - Este plugin se utiliza para cargar archivos JSON desde una fuente y se cargará en los diccionarios de Intlayer. Puede escanear toda la base de código y buscar archivos JSON específicos.
74
+ Este plugin se puede utilizar
75
+ - si utilizas una biblioteca i18n que impone una ubicación específica para que se carguen tus JSON (ej: `next-intl`, `i18next`, `react-intl`, `vue-i18n`, etc.), pero quieres colocar tu declaración de contenido donde quieras en tu base de código.
76
+ - También se puede utilizar si quieres obtener tus mensajes de una fuente remota (ej: un CMS, una API, etc.) y almacenar tus mensajes en archivos JSON.
77
+
78
+ > Bajo el capó, este plugin escaneará toda la base de código y buscará archivos JSON específicos y los cargará en los diccionarios de Intlayer.
79
+ > Ten en cuenta que este plugin no escribirá la salida y las traducciones de vuelta a los archivos JSON.
80
+
81
+ - `syncJSON`: Sincroniza archivos JSON con diccionarios de Intlayer.
82
+ - Este plugin se utiliza para sincronizar archivos JSON con diccionarios de Intlayer. Puede escanear la ubicación dada y cargar los JSON que coincidan con el patrón para archivos JSON específicos. Este plugin es útil si quieres obtener los beneficios de Intlayer mientras usas otra biblioteca i18n.
83
+
84
+ ## Usando ambos 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
+ // Mantén tus archivos JSON actuales sincronizados con los diccionarios de Intlayer
97
+ plugins: [
98
+ /**
99
+ * Cargará todos los archivos JSON en src que coincidan con el patrón {key}.i18n json
100
+ */
101
+ loadJSON({
102
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
103
+ locale: Locales.ENGLISH,
104
+ priority: 1, // Asegura que estos archivos JSON tengan precedencia sobre los archivos en `./locales/en/${key}.json`
105
+ format: "intlayer", // Formato del contenido JSON
106
+ }),
107
+ /**
108
+ * Cargará y escribirá la salida y las traducciones de vuelta a los archivos JSON en el directorio locales
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
+ ### Inicio rápido
66
125
 
67
126
  Agrega el plugin a tu `intlayer.config.ts` y apúntalo a tu estructura JSON existente.
68
127
 
@@ -81,6 +140,7 @@ const config: IntlayerConfig = {
81
140
  syncJSON({
82
141
  // Diseño por idioma, por espacio de nombres (por ejemplo, next-intl, i18next con espacios de nombres)
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
  Alternativa: archivo único por idioma (común en configuraciones i18next/react-intl):
92
152
 
93
153
  ```ts fileName="intlayer.config.ts"
94
- plugins: [
95
- syncJSON({
96
- source: ({ locale }) => `./locales/${locale}.json`,
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
- ### Cómo funciona
174
+ #### Cómo funciona
102
175
 
103
176
  - Lectura: el plugin descubre archivos JSON desde tu generador `source` y los carga como diccionarios de Intlayer.
104
177
  - Escritura: después de las compilaciones y llenados, escribe los JSON localizados de vuelta en las mismas rutas (con una nueva línea final para evitar problemas de formato).
@@ -112,6 +185,7 @@ syncJSON({
112
185
  location?: string, // etiqueta opcional, por defecto: "plugin"
113
186
  priority?: number, // prioridad opcional para resolución de conflictos, por defecto: 0
114
187
  format?: 'intlayer' | 'icu' | 'i18next', // formateador opcional, usado para compatibilidad con el runtime de Intlayer
188
+ splitKeys?: boolean, // opcional, divide un solo archivo en un diccionario por clave de espacio de nombres de nivel superior (autodetectado)
115
189
  });
116
190
  ```
117
191
 
@@ -136,17 +210,49 @@ syncJSON({
136
210
  }),
137
211
  ```
138
212
 
139
- ## Múltiples fuentes JSON y prioridad
213
+ #### `splitKeys` (boolean)
214
+
215
+ Controla si un único archivo JSON cuyas **claves de primer nivel son espacios de nombres** debe convertirse en un diccionario por cada clave de nivel superior, en lugar de un único diccionario que contenga todo el archivo.
216
+
217
+ Esto coincide con el modelo de espacio de nombres de bibliotecas como `next-intl` y `react-intl`, donde un archivo `messages/{locale}.json` agrupa varios espacios de nombres por sus claves de primer nivel, cada uno abordado de forma independiente (por ejemplo, `useTranslations('Hero')` se resuelve en el diccionario `Hero`).
218
+
219
+ - `undefined` (por defecto): **autodetectado** — el archivo se divide cuando el patrón `source` no tiene un segmento `{key}` (un archivo contiene todos los espacios de nombres), y se mantiene como un único diccionario en caso contrario (un archivo por clave).
220
+ - `true`: siempre divide cada clave de nivel superior en su propio diccionario.
221
+ - `false`: nunca divide; todo el archivo se convierte en un único diccionario.
222
+
223
+ Dado un único archivo `messages/{locale}.json`:
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, // implícito porque el patrón no tiene un segmento `{key}`
238
+ }),
239
+ ```
240
+
241
+ Esto produce tres diccionarios — `Hero`, `Nav` y `About` — por lo que `useTranslations('Hero')` (next-intl) se resuelve correctamente. Al volver a escribir, todos los espacios de nombres se reensamblan en el mismo archivo por localidad.
242
+
243
+ > Cuando mantienes el segmento `{key}` explícito en tu `source` (por ejemplo, `./locales/${locale}/${key}.json`), cada archivo ya es un espacio de nombres, por lo que la división está deshabilitada por defecto.
244
+
245
+ ### Múltiples fuentes JSON y prioridad
140
246
 
141
247
  Puedes agregar múltiples plugins `syncJSON` para sincronizar diferentes fuentes JSON. Esto es útil cuando tienes múltiples bibliotecas i18n o diferentes estructuras JSON en tu proyecto.
142
248
 
143
- ### Sistema de prioridad
249
+ #### Sistema de prioridad
144
250
 
145
251
  Cuando múltiples plugins apuntan a la misma clave del diccionario, el parámetro `priority` determina qué plugin tiene precedencia:
146
252
 
147
253
  - Los números de prioridad más altos ganan sobre los más bajos
148
254
  - La prioridad por defecto de los archivos `.content` es `0`
149
- - La prioridad por defecto de los archivos de contenido de plugins es `-1`
255
+ - La prioridad por defecto de los plugins es `0`
150
256
  - Los plugins con la misma prioridad se procesan en el orden en que aparecen en la configuración
151
257
 
152
258
  ```ts fileName="intlayer.config.ts"
@@ -189,73 +295,140 @@ const config: IntlayerConfig = {
189
295
  export default config;
190
296
  ```
191
297
 
192
- ### Resolución de conflictos
298
+ ## Load JSON plugin
193
299
 
194
- Cuando la misma clave de traducción existe en múltiples fuentes JSON:
300
+ ### Inicio rápido
195
301
 
196
- 1. El plugin con la prioridad más alta determina el valor final
197
- 2. Las fuentes con menor prioridad se usan como respaldo para claves faltantes
198
- 3. Esto permite mantener traducciones heredadas mientras se migra gradualmente a nuevas estructuras
302
+ Agrega el plugin a tu `intlayer.config.ts` para ingerir archivos JSON existentes como diccionarios de Intlayer. Este plugin es de solo lectura (no escribe en disco):
199
303
 
200
- ## Integraciones
304
+ ```ts fileName="intlayer.config.ts"
305
+ import { Locales, type IntlayerConfig } from "intlayer";
306
+ import { loadJSON } from "@intlayer/sync-json-plugin";
201
307
 
202
- A continuación se muestran mapeos comunes. Mantén tu entorno de ejecución sin cambios; solo agrega el plugin.
308
+ const config: IntlayerConfig = {
309
+ internationalization: {
310
+ locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
311
+ defaultLocale: Locales.ENGLISH,
312
+ },
203
313
 
204
- ### i18next
314
+ plugins: [
315
+ // Ingerir mensajes JSON ubicados en cualquier parte de tu árbol de código fuente
316
+ loadJSON({
317
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
318
+ // Cargar una sola localidad por instancia de plugin (por defecto a la localidad predeterminada de la configuración)
319
+ locale: Locales.ENGLISH,
320
+ priority: 0,
321
+ }),
322
+ ],
323
+ };
205
324
 
206
- Disposición típica de archivos: `./public/locales/{locale}/{namespace}.json` o `./locales/{locale}/{namespace}.json`.
325
+ export default config;
326
+ ```
327
+
328
+ Alternativa: diseño por localidad, aún de solo lectura (solo se carga la localidad seleccionada):
207
329
 
208
330
  ```ts fileName="intlayer.config.ts"
209
- import { syncJSON } from "@intlayer/sync-json-plugin";
331
+ import { Locales, type IntlayerConfig } from "intlayer";
332
+ import { loadJSON } from "@intlayer/sync-json-plugin";
210
333
 
211
- export default {
334
+ const config: IntlayerConfig = {
335
+ internationalization: {
336
+ locales: [Locales.ENGLISH, Locales.FRENCH],
337
+ defaultLocale: Locales.ENGLISH,
338
+ },
212
339
  plugins: [
213
- syncJSON({
214
- format: "i18next",
340
+ loadJSON({
341
+ // Solo los archivos para Locales.FRENCH se cargarán desde este patrón
215
342
  source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
343
+ locale: Locales.FRENCH,
216
344
  }),
217
345
  ],
218
346
  };
347
+
348
+ export default config;
219
349
  ```
220
350
 
221
- ### next-intl
351
+ ### Cómo funciona
222
352
 
223
- Mensajes JSON por localidad (a menudo `./messages/{locale}.json`) o por espacio de nombres.
353
+ - Descubrir: construye un glob a partir de tu generador `source` y recopila los archivos JSON coincidentes.
354
+ - Ingerir: carga cada archivo JSON como un diccionario de Intlayer con la `locale` proporcionada.
355
+ - Solo lectura: no escribe ni formatea archivos de salida; usa `syncJSON` si necesitas sincronización de ida y vuelta.
356
+ - Listo para auto‑relleno: define un patrón `fill` para que `intlayer content fill` pueda rellenar las claves faltantes.
224
357
 
225
- ```ts fileName="intlayer.config.ts"
226
- plugins: [
227
- syncJSON({
228
- source: ({ locale, key }) => `./messages/${locale}/${key}.json`,
229
- }),
230
- ];
358
+ ### API
359
+
360
+ ```ts
361
+ loadJSON({
362
+ // Construye rutas a tu JSON. `locale` es opcional si tu estructura no tiene un segmento de localidad
363
+ source: ({ key, locale }) => string,
364
+
365
+ // Localidad objetivo para los diccionarios cargados por esta instancia de plugin
366
+ // Por defecto a configuration.internationalization.defaultLocale
367
+ locale?: Locale,
368
+
369
+ // Etiqueta opcional para identificar la fuente
370
+ location?: string, // default: "plugin"
371
+
372
+ // Prioridad utilizada para la resolución de conflictos contra otras fuentes
373
+ priority?: number, // default: 0
374
+
375
+ // Formateador opcional para el contenido JSON
376
+ format?: 'intlayer' | 'icu' | 'i18next', // default: 'intlayer'
377
+
378
+ // Divide un solo archivo en un diccionario por clave de nivel superior (autodetectado)
379
+ splitKeys?: boolean,
380
+ });
231
381
  ```
232
382
 
233
- Véase también: `docs/es/intlayer_with_next-intl.md`.
383
+ #### `format` ('intlayer' | 'icu' | 'i18next')
234
384
 
235
- ### react-intl
385
+ Especifica el formateador a utilizar para el contenido del diccionario al cargar archivos JSON. Esto permite usar diferentes sintaxis de formateo de mensajes compatibles con varias bibliotecas i18n.
236
386
 
237
- Es común un único JSON por localidad:
387
+ - `'intlayer'`: El formateador Intlayer por defecto (por defecto).
388
+ - `'icu'`: Usa el formateo de mensajes ICU (compatible con bibliotecas como react-intl, vue-i18n).
389
+ - `'i18next'`: Usa el formateo de mensajes i18next (compatible con i18next, next-i18next, Solid-i18next).
238
390
 
239
- ```ts fileName="intlayer.config.ts"
240
- plugins: [
241
- syncJSON({
242
- source: ({ locale }) => `./locales/${locale}.json`,
243
- }),
244
- ];
391
+ **Ejemplo:**
392
+
393
+ ```ts
394
+ loadJSON({
395
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
396
+ locale: Locales.ENGLISH,
397
+ format: "icu", // Usar formateo ICU para compatibilidad
398
+ }),
245
399
  ```
246
400
 
247
- ### vue-i18n
401
+ #### `splitKeys` (boolean)
248
402
 
249
- Puede ser un solo archivo por locale o por namespace:
403
+ Mismo comportamiento que en [`syncJSON`](#splitkeys-boolean): cuando un único archivo JSON agrupa varios espacios de nombres por sus claves de primer nivel, cada clave de nivel superior se convierte en su propio diccionario.
250
404
 
251
- ```ts fileName="intlayer.config.ts"
252
- plugins: [
253
- syncJSON({
254
- source: ({ key, locale }) => `./src/locales/${locale}/${key}.json`,
255
- }),
256
- ];
405
+ - `undefined` (por defecto): **autodetectado** — se divide cuando el patrón `source` no tiene un segmento `{key}`, un único diccionario en caso contrario.
406
+ - `true` / `false`: fuerza o deshabilita la división.
407
+
408
+ ```ts
409
+ loadJSON({
410
+ source: ({ locale }) => `./messages/${locale}.json`,
411
+ format: "icu",
412
+ // splitKeys auto-enabled: `Hero`, `Nav`, `About`, … cada uno se convierte en un diccionario
413
+ }),
257
414
  ```
258
415
 
416
+ ### Comportamiento y convenciones
417
+
418
+ - Si tu máscara `source` incluye un marcador de posición de localidad, solo se ingieren los archivos para la `locale` seleccionada.
419
+ - Si no hay un segmento `{key}` en tu máscara, cada clave de nivel superior del archivo se convierte en su propio diccionario por defecto (ver [`splitKeys`](#splitkeys-boolean)). Establece `splitKeys: false` para cargar en su lugar todo el archivo como un único diccionario `index`.
420
+ - Las claves se derivan de las rutas de los archivos sustituyendo el marcador de posición `{key}` en tu generador `source`.
421
+ - El plugin solo utiliza los archivos descubiertos y no fabrica localidades o claves faltantes.
422
+ - La ruta `fill` se infiere de tu `source` y se utiliza para actualizar los valores faltantes a través de la CLI cuando optas por ello.
423
+
424
+ ## Resolución de conflictos
425
+
426
+ Cuando la misma clave de traducción existe en múltiples fuentes JSON:
427
+
428
+ 1. El plugin con la prioridad más alta determina el valor final
429
+ 2. Las fuentes con menor prioridad se usan como respaldo para claves faltantes
430
+ 3. Esto permite mantener traducciones heredadas mientras se migra gradualmente a nuevas estructuras
431
+
259
432
  ## CLI
260
433
 
261
434
  Los archivos JSON sincronizados serán considerados como otros archivos `.content`. Eso significa que todos los comandos de intlayer estarán disponibles para los archivos JSON sincronizados. Incluyendo:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-03-13
3
- updatedAt: 2025-12-13
3
+ updatedAt: 2026-06-21
4
4
  title: Plugin Sync JSON
5
5
  description: Synchronisez les dictionnaires Intlayer avec des fichiers JSON i18n tiers (i18next, next-intl, react-intl, vue-i18n, et plus). Conservez votre i18n existant tout en utilisant Intlayer pour gérer, traduire et tester vos 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: "Ajout de l'option splitKeys (un dictionnaire par clé de namespace de premier niveau) pour les layouts de fichiers uniques next-intl / react-intl"
27
30
  - version: 7.5.0
28
31
  date: 2025-12-13
29
32
  changes: "Ajout du support des formats ICU et i18next"
@@ -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
- ## Démarrage rapide
68
+ ## Plugins
69
+
70
+ Ce package fournit deux plugins :
71
+
72
+ - `loadJSON` : Charge les fichiers JSON dans les dictionnaires Intlayer.
73
+ - Ce plugin est utilisé pour charger les fichiers JSON d'une source et sera chargé dans les dictionnaires Intlayer. Il peut scanner l'ensemble de la codebase et rechercher des fichiers JSON spécifiques.
74
+ Ce plugin peut être utilisé
75
+ - si vous utilisez une bibliothèque i18n qui impose un emplacement spécifique pour le chargement de vos JSON (ex: `next-intl`, `i18next`, `react-intl`, `vue-i18n`, etc.), mais que vous souhaitez placer votre déclaration de contenu où vous le souhaitez dans votre codebase.
76
+ - Il peut également être utilisé si vous souhaitez récupérer vos messages d'une source distante (ex: un CMS, une API, etc.) et stocker vos messages dans des fichiers JSON.
77
+
78
+ > En coulisses, ce plugin scannera l'ensemble de la codebase et recherchera des fichiers JSON spécifiques pour les charger dans les dictionnaires Intlayer.
79
+ > Notez que ce plugin n'écrira pas la sortie et les traductions dans les fichiers JSON.
80
+
81
+ - `syncJSON` : Synchronise les fichiers JSON avec les dictionnaires Intlayer.
82
+ - Ce plugin est utilisé pour synchroniser les fichiers JSON avec les dictionnaires Intlayer. Il peut scanner l'emplacement donné et charger les JSON qui correspondent au modèle pour des fichiers JSON spécifiques. Ce plugin est utile si vous souhaitez bénéficier des avantages d'Intlayer tout en utilisant une autre bibliothèque i18n.
83
+
84
+ ## Utilisation des deux 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
+ // Gardez vos fichiers JSON actuels synchronisés avec les dictionnaires Intlayer
97
+ plugins: [
98
+ /**
99
+ * Chargera tous les fichiers JSON dans le dossier src qui correspondent au modèle {key}.i18n.json
100
+ */
101
+ loadJSON({
102
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
103
+ locale: Locales.ENGLISH,
104
+ priority: 1, // Garantit que ces fichiers JSON ont la priorité sur les fichiers à `./locales/en/${key}.json`
105
+ format: "intlayer", // Format du contenu JSON
106
+ }),
107
+ /**
108
+ * Chargera et écrira la sortie et les traductions dans les fichiers JSON du répertoire locales
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
+ ## Plugin `syncJSON`
123
+
124
+ ### Démarrage rapide
66
125
 
67
126
  Ajoutez le plugin à votre `intlayer.config.ts` et pointez-le vers votre structure JSON existante.
68
127
 
@@ -81,6 +140,7 @@ const config: IntlayerConfig = {
81
140
  syncJSON({
82
141
  // Mise en page par locale, par namespace (par exemple, next-intl, i18next avec 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 : un seul fichier par locale (courant avec les configurations i18next/react-intl) :
92
152
 
93
153
  ```ts fileName="intlayer.config.ts"
94
- plugins: [
95
- syncJSON({
96
- source: ({ locale }) => `./locales/${locale}.json`,
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
- ### Comment ça fonctionne
174
+ #### Comment ça fonctionne
102
175
 
103
176
  - Lecture : le plugin découvre les fichiers JSON à partir de votre générateur `source` et les charge comme des dictionnaires Intlayer.
104
177
  - Écriture : après les builds et les remplissages, il écrit les JSON localisés aux mêmes emplacements (avec une nouvelle ligne finale pour éviter les problèmes de formatage).
@@ -112,6 +185,7 @@ syncJSON({
112
185
  location?: string, // étiquette optionnelle, par défaut : "plugin"
113
186
  priority?: number, // priorité optionnelle pour la résolution des conflits, par défaut : 0
114
187
  format?: 'intlayer' | 'icu' | 'i18next', // formateur optionnel, utilisé pour la compatibilité avec le runtime Intlayer
188
+ splitKeys?: boolean, // optionnel, divise un fichier unique en un dictionnaire par clé de premier niveau (détection automatique)
115
189
  });
116
190
  ```
117
191
 
@@ -136,17 +210,49 @@ syncJSON({
136
210
  }),
137
211
  ```
138
212
 
139
- ## Sources JSON multiples et priorité
213
+ #### `splitKeys` (boolean)
214
+
215
+ Contrôle si un fichier JSON unique dont les **clés de premier niveau sont des namespaces** doit devenir un dictionnaire par clé de premier niveau, au lieu d'un seul dictionnaire contenant tout le fichier.
216
+
217
+ Cela correspond au modèle de namespace de bibliothèques comme `next-intl` et `react-intl`, où un fichier `messages/{locale}.json` regroupe plusieurs namespaces par ses clés de premier niveau, chacun étant adressé indépendamment (par exemple, `useTranslations('Hero')` se résout au dictionnaire `Hero`).
218
+
219
+ - `undefined` (par défaut) : **détection automatique** — le fichier est divisé lorsque le modèle `source` n'a pas de segment `{key}` (un fichier contient tous les namespaces), et conservé comme un seul dictionnaire sinon (un fichier par clé).
220
+ - `true` : divise toujours chaque clé de premier niveau en son propre dictionnaire.
221
+ - `false` : ne divise jamais ; le fichier entier devient un seul dictionnaire.
222
+
223
+ Étant donné un fichier `messages/{locale}.json` unique :
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, // implicite car le modèle n'a pas de segment `{key}`
238
+ }),
239
+ ```
240
+
241
+ Cela produit trois dictionnaires — `Hero`, `Nav`, et `About` — de sorte que `useTranslations('Hero')` (next-intl) se résout correctement. Lors de la réécriture, tous les namespaces sont réassemblés dans le même fichier par locale.
242
+
243
+ > Lorsque vous conservez le segment `{key}` explicite dans votre `source` (par exemple, `./locales/${locale}/${key}.json`), chaque fichier est déjà un namespace, donc la division est désactivée par défaut.
244
+
245
+ ### Sources JSON multiples et priorité
140
246
 
141
247
  Vous pouvez ajouter plusieurs plugins `syncJSON` pour synchroniser différentes sources JSON. Cela est utile lorsque vous avez plusieurs bibliothèques i18n ou différentes structures JSON dans votre projet.
142
248
 
143
- ### Système de priorité
249
+ #### Système de priorité
144
250
 
145
251
  Lorsque plusieurs plugins ciblent la même clé de dictionnaire, le paramètre `priority` détermine quel plugin a la priorité :
146
252
 
147
253
  - Les nombres de priorité plus élevés l'emportent sur les plus faibles
148
254
  - La priorité par défaut des fichiers `.content` est `0`
149
- - La priorité par défaut des fichiers de contenu des plugins est `-1`
255
+ - La priorité par défaut des plugins est `0`
150
256
  - Les plugins avec la même priorité sont traités dans l'ordre où ils apparaissent dans la 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
- ### Résolution des conflits
298
+ ## Load JSON plugin
299
+
300
+ ### Démarrage rapide
301
+
302
+ Ajoutez le plugin à votre `intlayer.config.ts` pour ingérer les fichiers JSON existants comme dictionnaires Intlayer. Ce plugin est en lecture seule (pas d'écriture sur le disque) :
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
+ // Ingérer les messages JSON situés n'importe où dans votre arborescence source
316
+ loadJSON({
317
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
318
+ // Charger une seule locale par instance de plugin (par défaut à la defaultLocale de la config)
319
+ locale: Locales.ENGLISH,
320
+ priority: 0,
321
+ }),
322
+ ],
323
+ };
324
+
325
+ export default config;
326
+ ```
327
+
328
+ Alternative : disposition par locale, toujours en lecture seule (seule la locale sélectionnée est chargée) :
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
+ // Seuls les fichiers pour Locales.FRENCH seront chargés à partir de ce modèle
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 : construit un glob à partir de votre générateur `source` et collecte les fichiers JSON correspondants.
354
+ - Ingest : charge chaque fichier JSON comme un dictionnaire Intlayer avec la `locale` fournie.
355
+ - Read‑only : n'écrit ni ne formate les fichiers de sortie ; utilisez `syncJSON` si vous avez besoin d'une synchronisation aller-retour.
356
+ - Auto‑fill ready : définit un modèle `fill` afin que `intlayer content fill` puisse remplir les clés manquantes.
357
+
358
+ ### API
359
+
360
+ ```ts
361
+ loadJSON({
362
+ // Construisez les chemins vers votre JSON. `locale` est optionnel si votre structure n'a pas de segment de locale
363
+ source: ({ key, locale }) => string,
364
+
365
+ // Locale cible pour les dictionnaires chargés par cette instance de plugin
366
+ // Par défaut à configuration.internationalization.defaultLocale
367
+ locale?: Locale,
368
+
369
+ // Étiquette optionnelle pour identifier la source
370
+ location?: string, // par défaut : "plugin"
371
+
372
+ // Priorité utilisée pour la résolution des conflits avec d'autres sources
373
+ priority?: number, // par défaut : 0
374
+
375
+ // Formateur optionnel pour le contenu JSON
376
+ format?: 'intlayer' | 'icu' | 'i18next', // par défaut : 'intlayer'
377
+
378
+ // Divise un fichier unique en un dictionnaire par clé de premier niveau (détection automatique)
379
+ splitKeys?: boolean,
380
+ });
381
+ ```
382
+
383
+ #### `format` ('intlayer' | 'icu' | 'i18next')
384
+
385
+ Spécifie le formateur à utiliser pour le contenu du dictionnaire lors du chargement des fichiers JSON. Cela permet d'utiliser différentes syntaxes de formatage de messages compatibles avec diverses bibliothèques i18n.
386
+
387
+ - `'intlayer'` : Le formateur Intlayer par défaut (par défaut).
388
+ - `'icu'` : Utilise le formatage de messages ICU (compatible avec des bibliothèques comme react-intl, vue-i18n).
389
+ - `'i18next'` : Utilise le formatage de messages i18next (compatible avec i18next, next-i18next, Solid-i18next).
390
+
391
+ **Exemple :**
392
+
393
+ ```ts
394
+ loadJSON({
395
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
396
+ locale: Locales.ENGLISH,
397
+ format: "icu", // Utiliser le formatage ICU pour la compatibilité
398
+ }),
399
+ ```
400
+
401
+ #### `splitKeys` (boolean)
402
+
403
+ Même comportement que dans [`syncJSON`](#splitkeys-boolean) : lorsqu'un fichier JSON unique regroupe plusieurs namespaces par ses clés de premier niveau, chaque clé de premier niveau devient son propre dictionnaire.
404
+
405
+ - `undefined` (par défaut) : **détection automatique** — divise lorsque le modèle `source` n'a pas de segment `{key}`, dictionnaire unique sinon.
406
+ - `true` / `false` : force ou désactive la division.
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
+ - Si votre masque `source` inclut un placeholder de locale, seuls les fichiers pour la `locale` sélectionnée sont ingérés.
419
+ - S'il n'y a pas de segment `{key}` dans votre masque, chaque clé de premier niveau du fichier devient son propre dictionnaire par défaut (voir [`splitKeys`](#splitkeys-boolean)). Définissez `splitKeys: false` pour charger plutôt l'ensemble du fichier comme un seul dictionnaire `index`.
420
+ - Les clés sont dérivées des chemins de fichiers en substituant le placeholder `{key}` dans votre générateur `source`.
421
+ - Le plugin n'utilise que les fichiers découverts et ne fabrique pas de locales ou de clés manquantes.
422
+ - Le chemin `fill` est inféré de votre `source` et utilisé pour mettre à jour les valeurs manquantes via la CLI lorsque vous l'activez.
423
+
424
+ ## Résolution des conflits
193
425
 
194
426
  Lorsque la même clé de traduction existe dans plusieurs sources JSON :
195
427