@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: 同步 JSON 插件
|
|
5
5
|
description: 将 Intlayer 字典与第三方 i18n JSON 文件(如 i18next、next-intl、react-intl、vue-i18n 等)同步。保持您现有的 i18n,同时使用 Intlayer 管理、翻译和测试您的消息。
|
|
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: "添加 splitKeys 选项(每个顶级命名空间键一个字典),用于 next-intl / react-intl 单文件布局"
|
|
27
30
|
- version: 7.5.0
|
|
28
31
|
date: 2025-12-13
|
|
29
32
|
changes: "添加 ICU 和 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
|
+
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 impose 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, a 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`: Synchronize JSON files with Intlayer dictionaries.
|
|
82
|
+
- This plugin is used to synchronize 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 while 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
|
将插件添加到您的 `intlayer.config.ts` 中,并指向您现有的 JSON 结构。
|
|
68
127
|
|
|
@@ -81,6 +140,7 @@ const config: IntlayerConfig = {
|
|
|
81
140
|
syncJSON({
|
|
82
141
|
// 每个语言环境,每个命名空间的布局(例如,next-intl,带命名空间的 i18next)
|
|
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
|
替代方案:每个语言环境一个文件(常见于 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
|
+
#### 工作原理
|
|
102
175
|
|
|
103
176
|
- 读取:插件从您的 `source` 构建器发现 JSON 文件,并将其加载为 Intlayer 字典。
|
|
104
177
|
- 写入:在构建和填充之后,它将本地化的 JSON 写回相同路径(末尾带有换行符以避免格式问题)。
|
|
@@ -112,6 +185,7 @@ syncJSON({
|
|
|
112
185
|
location?: string, // 可选标签,默认值:"plugin"
|
|
113
186
|
priority?: number, // 可选优先级,用于冲突解决,默认值:0
|
|
114
187
|
format?: 'intlayer' | 'icu' | 'i18next', // 可选格式化器,用于 Intlayer 运行时兼容性
|
|
188
|
+
splitKeys?: boolean, // 可选,将单个文件拆分为每个顶级键一个字典(自动检测)
|
|
115
189
|
});
|
|
116
190
|
```
|
|
117
191
|
|
|
@@ -136,11 +210,43 @@ syncJSON({
|
|
|
136
210
|
}),
|
|
137
211
|
```
|
|
138
212
|
|
|
139
|
-
|
|
213
|
+
#### `splitKeys` (boolean)
|
|
214
|
+
|
|
215
|
+
控制单个 JSON 文件(其**第一级键是命名空间**)是否应拆分为每个顶级键一个字典,而不是将整个文件作为一个字典。
|
|
216
|
+
|
|
217
|
+
这与 `next-intl` 和 `react-intl` 等库的命名空间模型相匹配,其中一个 `messages/{locale}.json` 文件通过其第一级键将多个命名空间分组,每个命名空间独立寻址(例如 `useTranslations('Hero')` 解析为 `Hero` 字典)。
|
|
218
|
+
|
|
219
|
+
- `undefined` (默认):**自动检测** — 当 `source` 模式没有 `{key}` 段时(一个文件包含所有命名空间),文件将被拆分;否则(每个键一个文件),文件将保持为单个字典。
|
|
220
|
+
- `true`:始终将每个顶级键拆分为其自己的字典。
|
|
221
|
+
- `false`:从不拆分;整个文件将成为一个字典。
|
|
222
|
+
|
|
223
|
+
给定一个 `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, // 隐含,因为模式没有 `{key}` 段
|
|
238
|
+
}),
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
这将生成三个字典 — `Hero`、`Nav` 和 `About` — 因此 `useTranslations('Hero')` (next-intl) 可以正确解析。在写回时,所有命名空间将重新组装到同一个按语言环境的文件中。
|
|
242
|
+
|
|
243
|
+
> 当您在 `source` 中保留显式的 `{key}` 段时(例如 `./locales/${locale}/${key}.json`),每个文件已经是一个命名空间,因此默认禁用拆分。
|
|
244
|
+
|
|
245
|
+
### 多个 JSON 源和优先级
|
|
140
246
|
|
|
141
247
|
你可以添加多个 `syncJSON` 插件来同步不同的 JSON 源。当你的项目中使用多个 i18n 库或有不同的 JSON 结构时,这非常有用。
|
|
142
248
|
|
|
143
|
-
|
|
249
|
+
#### 优先级系统
|
|
144
250
|
|
|
145
251
|
当多个插件针对同一个词典键时,`priority` 参数决定哪个插件优先:
|
|
146
252
|
|
|
@@ -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
|
+
### Quick start
|
|
195
301
|
|
|
196
|
-
|
|
197
|
-
2. 优先级较低的源作为缺失键的备用
|
|
198
|
-
3. 这允许您在逐步迁移到新结构的同时,保持旧版翻译
|
|
302
|
+
将插件添加到您的 `intlayer.config.ts` 以将现有 JSON 文件作为 Intlayer 字典导入。此插件是只读的(不写入磁盘):
|
|
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
|
+
},
|
|
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
|
+
};
|
|
203
324
|
|
|
204
|
-
|
|
325
|
+
export default config;
|
|
326
|
+
```
|
|
205
327
|
|
|
206
|
-
|
|
328
|
+
替代方案:按语言环境布局,仍然是只读的(只加载选定的语言环境):
|
|
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
|
+
// Only files for Locales.FRENCH will be loaded from this pattern
|
|
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
|
+
### How it works
|
|
222
352
|
|
|
223
|
-
|
|
353
|
+
- 发现:从您的 `source` 构建器构建一个 glob 并收集匹配的 JSON 文件。
|
|
354
|
+
- 导入:将每个 JSON 文件作为 Intlayer 字典加载,并使用提供的 `locale`。
|
|
355
|
+
- 只读:不写入或格式化输出文件;如果您需要往返同步,请使用 `syncJSON`。
|
|
356
|
+
- 自动填充就绪:定义一个 `fill` 模式,以便 `intlayer content fill` 可以在您选择时填充缺失的键。
|
|
224
357
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
+
});
|
|
231
381
|
```
|
|
232
382
|
|
|
233
|
-
|
|
383
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
234
384
|
|
|
235
|
-
|
|
385
|
+
指定在加载 JSON 文件时用于字典内容的格式化器。这允许使用与各种 i18n 库兼容的不同消息格式化语法。
|
|
236
386
|
|
|
237
|
-
|
|
387
|
+
- `'intlayer'`:默认的 Intlayer 格式化器(默认值)。
|
|
388
|
+
- `'icu'`:使用 ICU 消息格式化(与 react-intl、vue-i18n 等库兼容)。
|
|
389
|
+
- `'i18next'`:使用 i18next 消息格式化(与 i18next、next-i18next、Solid-i18next 兼容)。
|
|
238
390
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
})
|
|
244
|
-
|
|
391
|
+
**示例:**
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
loadJSON({
|
|
395
|
+
source: ({ key }) => `./src/**/${key}.i18n.json`,
|
|
396
|
+
locale: Locales.ENGLISH,
|
|
397
|
+
format: "icu", // 使用 ICU 格式化以保持兼容性
|
|
398
|
+
}),
|
|
245
399
|
```
|
|
246
400
|
|
|
247
|
-
|
|
401
|
+
#### `splitKeys` (boolean)
|
|
248
402
|
|
|
249
|
-
|
|
403
|
+
与 [`syncJSON`](#splitkeys-boolean) 中的行为相同:当单个 JSON 文件通过其第一级键将多个命名空间分组时,每个顶级键都将成为其自己的字典。
|
|
250
404
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
405
|
+
- `undefined` (默认):**自动检测** — 当 `source` 模式没有 `{key}` 段时拆分,否则为单个字典。
|
|
406
|
+
- `true` / `false`:强制或禁用拆分。
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
loadJSON({
|
|
410
|
+
source: ({ locale }) => `./messages/${locale}.json`,
|
|
411
|
+
format: "icu",
|
|
412
|
+
// splitKeys 自动启用:`Hero`、`Nav`、`About` 等每个都成为一个字典
|
|
413
|
+
}),
|
|
257
414
|
```
|
|
258
415
|
|
|
416
|
+
### Behavior and conventions
|
|
417
|
+
|
|
418
|
+
- 如果您的 `source` 掩码包含语言环境占位符,则只导入所选 `locale` 的文件。
|
|
419
|
+
- 如果您的掩码中没有 `{key}` 段,则文件的每个顶级键默认会成为其自己的字典(请参阅 [`splitKeys`](#splitkeys-boolean))。将 `splitKeys: false` 设置为将整个文件加载为单个 `index` 字典。
|
|
420
|
+
- 键通过替换 `source` 构建器中的 `{key}` 占位符从文件路径派生。
|
|
421
|
+
- 插件只使用发现的文件,不制造缺失的语言环境或键。
|
|
422
|
+
- `fill` 路径从您的 `source` 推断,并用于在您选择时通过 CLI 更新缺失值。
|
|
423
|
+
|
|
424
|
+
## Conflict resolution
|
|
425
|
+
|
|
426
|
+
当相同的翻译键存在于多个 JSON 源中时:
|
|
427
|
+
|
|
428
|
+
1. 优先级最高的插件决定最终的值
|
|
429
|
+
2. 优先级较低的源作为缺失键的备用
|
|
430
|
+
3. 这允许您在逐步迁移到新结构的同时,保持旧版翻译
|
|
431
|
+
|
|
259
432
|
## CLI
|
|
260
433
|
|
|
261
434
|
同步的 JSON 文件将被视为其他 `.content` 文件。这意味着所有 intlayer 命令都可以用于同步的 JSON 文件,包括:
|
|
@@ -268,13 +441,13 @@ plugins: [
|
|
|
268
441
|
|
|
269
442
|
请参阅[Intlayer CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/cli/index.md)了解更多详情。
|
|
270
443
|
|
|
271
|
-
##
|
|
444
|
+
## Limitations (current)
|
|
272
445
|
|
|
273
446
|
- 针对第三方库时不支持插入或复数/ICU。
|
|
274
447
|
- 非 Intlayer 运行时尚不支持可视化编辑器。
|
|
275
448
|
- 仅支持 JSON 同步;不支持非 JSON 目录格式。
|
|
276
449
|
|
|
277
|
-
##
|
|
450
|
+
## Why this matters
|
|
278
451
|
|
|
279
452
|
- 我们可以推荐成熟的 i18n 解决方案,并将 Intlayer 定位为附加组件。
|
|
280
453
|
- 通过教程利用它们的 SEO/关键词,教程最后建议使用 Intlayer 来管理 JSON。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/docs",
|
|
3
|
-
"version": "9.0.0-canary.
|
|
3
|
+
"version": "9.0.0-canary.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Intlayer documentation",
|
|
6
6
|
"keywords": [
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"watch": "webpack --config ./webpack.config.ts --watch"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@intlayer/config": "9.0.0-canary.
|
|
77
|
-
"@intlayer/core": "9.0.0-canary.
|
|
78
|
-
"@intlayer/types": "9.0.0-canary.
|
|
76
|
+
"@intlayer/config": "9.0.0-canary.3",
|
|
77
|
+
"@intlayer/core": "9.0.0-canary.3",
|
|
78
|
+
"@intlayer/types": "9.0.0-canary.3"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@intlayer/api": "9.0.0-canary.
|
|
82
|
-
"@intlayer/cli": "9.0.0-canary.
|
|
81
|
+
"@intlayer/api": "9.0.0-canary.3",
|
|
82
|
+
"@intlayer/cli": "9.0.0-canary.3",
|
|
83
83
|
"@types/node": "25.9.3",
|
|
84
84
|
"@utils/ts-config": "1.0.4",
|
|
85
85
|
"@utils/ts-config-types": "1.0.4",
|