@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: 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
|
-
##
|
|
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
|
-
|
|
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
|
+
#### 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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
298
|
+
## Load JSON plugin
|
|
193
299
|
|
|
194
|
-
|
|
300
|
+
### Inicio rápido
|
|
195
301
|
|
|
196
|
-
|
|
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
|
-
|
|
304
|
+
```ts fileName="intlayer.config.ts"
|
|
305
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
306
|
+
import { loadJSON } from "@intlayer/sync-json-plugin";
|
|
201
307
|
|
|
202
|
-
|
|
308
|
+
const config: IntlayerConfig = {
|
|
309
|
+
internationalization: {
|
|
310
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
311
|
+
defaultLocale: Locales.ENGLISH,
|
|
312
|
+
},
|
|
203
313
|
|
|
204
|
-
|
|
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
|
-
|
|
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 {
|
|
331
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
332
|
+
import { loadJSON } from "@intlayer/sync-json-plugin";
|
|
210
333
|
|
|
211
|
-
|
|
334
|
+
const config: IntlayerConfig = {
|
|
335
|
+
internationalization: {
|
|
336
|
+
locales: [Locales.ENGLISH, Locales.FRENCH],
|
|
337
|
+
defaultLocale: Locales.ENGLISH,
|
|
338
|
+
},
|
|
212
339
|
plugins: [
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
###
|
|
351
|
+
### Cómo funciona
|
|
222
352
|
|
|
223
|
-
|
|
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
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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
|
-
|
|
383
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
234
384
|
|
|
235
|
-
|
|
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
|
-
|
|
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
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
|
|
401
|
+
#### `splitKeys` (boolean)
|
|
248
402
|
|
|
249
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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:
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
+
#### 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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|