@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: Sync 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
+ 이 패키지는 두 가지 플러그인을 제공합니다:
71
+
72
+ - `loadJSON`: JSON 파일을 Intlayer 사전으로 로드합니다.
73
+ - 이 플러그인은 소스에서 JSON 파일을 로드하고 Intlayer 사전으로 로드하는 데 사용됩니다. 모든 코드베이스를 스캔하고 특정 JSON 파일을 검색할 수 있습니다.
74
+ 이 플러그인은 다음 경우에 사용할 수 있습니다.
75
+ - JSON 파일이 로드될 특정 위치를 강제하는 i18n 라이브러리(예: `next-intl`, `i18next`, `react-intl`, `vue-i18n` 등)를 사용하지만, 코드베이스의 원하는 위치에 콘텐츠 선언을 배치하려는 경우.
76
+ - 원격 소스(예: CMS, API 등)에서 메시지를 가져와 JSON 파일에 저장하려는 경우에도 사용할 수 있습니다.
77
+
78
+ > 내부적으로 이 플러그인은 모든 코드베이스를 스캔하고 특정 JSON 파일을 검색하여 Intlayer 사전으로 로드합니다.
79
+ > 이 플러그인은 출력 및 번역을 JSON 파일에 다시 쓰지 않습니다.
80
+
81
+ - `syncJSON`: JSON 파일을 Intlayer 사전과 동기화합니다.
82
+ - 이 플러그인은 JSON 파일을 Intlayer 사전과 동기화하는 데 사용됩니다. 지정된 위치를 스캔하고 특정 JSON 파일의 패턴과 일치하는 JSON을 로드할 수 있습니다. 이 플러그인은 다른 i18n 라이브러리를 사용하면서 Intlayer의 이점을 얻으려는 경우에 유용합니다.
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
+ // 현재 JSON 파일을 Intlayer 사전과 동기화 상태로 유지
97
+ plugins: [
98
+ /**
99
+ * src에서 {key}.i18n.json 패턴과 일치하는 모든 JSON 파일을 로드합니다.
100
+ */
101
+ loadJSON({
102
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
103
+ locale: Locales.ENGLISH,
104
+ priority: 1, // 이 JSON 파일이 `./locales/en/${key}.json`의 파일보다 우선하도록 보장합니다.
105
+ format: "intlayer", // JSON 콘텐츠의 형식
106
+ }),
107
+ /**
108
+ * 출력 및 번역을 로케일 디렉토리의 JSON 파일로 로드하고 다시 씁니다.
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
- 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
- ### 작동 방식
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
- ## 여러 JSON 소스 및 우선순위
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
+ ### Multiple JSON sources and priority
140
246
 
141
247
  여러 `syncJSON` 플러그인을 추가하여 서로 다른 JSON 소스를 동기화할 수 있습니다. 이는 프로젝트에 여러 i18n 라이브러리나 다양한 JSON 구조가 있을 때 유용합니다.
142
248
 
143
- ### 우선순위 시스템
249
+ #### Priority system
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
- 동일한 번역 키가 여러 JSON 소스에 존재할 때:
300
+ ### Quick start
195
301
 
196
- 1. 가장 높은 우선순위를 가진 플러그인이 최종 값을 결정합니다.
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
+ // 소스 트리의 어느 곳에나 있는 JSON 메시지를 가져옵니다.
316
+ loadJSON({
317
+ source: ({ key }) => `./src/**/${key}.i18n.json`,
318
+ // 플러그인 인스턴스당 단일 로케일을 로드합니다 (구성의 defaultLocale로 기본 설정됨).
319
+ locale: Locales.ENGLISH,
320
+ priority: 0,
321
+ }),
322
+ ],
323
+ };
203
324
 
204
- ### i18next
325
+ export default config;
326
+ ```
205
327
 
206
- 일반적인 파일 구조: `./public/locales/{locale}/{namespace}.json` 또는 `./locales/{locale}/{namespace}.json`.
328
+ 대안: 로케일별 레이아웃, 여전히 읽기 전용 (선택된 로케일만 로드됨):
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
+ // 이 패턴에서 Locales.FRENCH에 대한 파일만 로드됩니다.
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
+ ### How it works
222
352
 
223
- 로케일별 JSON 메시지(보통 `./messages/{locale}.json`) 또는 네임스페이스별.
353
+ - 발견: `source` 빌더에서 glob을 구축하고 일치하는 JSON 파일을 수집합니다.
354
+ - 가져오기: 각 JSON 파일을 제공된 `locale`로 Intlayer 사전으로 로드합니다.
355
+ - 읽기 전용: 출력 파일을 쓰거나 포맷하지 않습니다. 왕복 동기화가 필요한 경우 `syncJSON`을 사용하세요.
356
+ - 자동 채우기 준비: `fill` 패턴을 정의하여 `intlayer content fill`이 누락된 키를 채울 수 있도록 합니다.
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
+ // JSON 파일 경로를 빌드합니다. 구조에 로케일 세그먼트가 없는 경우 `locale`은 선택 사항입니다.
363
+ source: ({ key, locale }) => string,
364
+
365
+ // 이 플러그인 인스턴스에 의해 로드된 사전에 대한 대상 로케일
366
+ // configuration.internationalization.defaultLocale로 기본 설정됩니다.
367
+ locale?: Locale,
368
+
369
+ // 소스를 식별하는 선택적 레이블
370
+ location?: string, // default: "plugin"
371
+
372
+ // 다른 소스와의 충돌 해결에 사용되는 우선순위
373
+ priority?: number, // default: 0
374
+
375
+ // JSON 콘텐츠에 대한 선택적 포맷터
376
+ format?: 'intlayer' | 'icu' | 'i18next', // default: 'intlayer'
377
+
378
+ // 단일 파일을 최상위 키당 하나의 사전으로 분할 (자동 감지)
379
+ splitKeys?: boolean,
380
+ });
231
381
  ```
232
382
 
233
- 참고: `docs/ko/intlayer_with_next-intl.md`.
383
+ #### `format` ('intlayer' | 'icu' | 'i18next')
234
384
 
235
- ### react-intl
385
+ JSON 파일을 로드할 때 사전 콘텐츠에 사용할 포맷터를 지정합니다. 이를 통해 다양한 i18n 라이브러리와 호환되는 다양한 메시지 포맷팅 구문을 사용할 수 있습니다.
236
386
 
237
- 로케일별 단일 JSON이 일반적입니다:
387
+ - `'intlayer'`: 기본 Intlayer 포맷터 (기본값).
388
+ - `'icu'`: ICU 메시지 포맷팅을 사용합니다 (react-intl, vue-i18n과 같은 라이브러리와 호환).
389
+ - `'i18next'`: i18next 메시지 포맷팅을 사용합니다 (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
+ **예시:**
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
- ### vue-i18n
401
+ #### `splitKeys` (boolean)
248
402
 
249
- 로케일별 단일 파일 또는 네임스페이스별 파일 하나를 사용합니다:
403
+ [`syncJSON`](#splitkeys-boolean)과 동일한 동작: 단일 JSON 파일이 최상위 키별로 여러 네임스페이스를 그룹화할 때, 각 최상위 키는 자체 사전이 됩니다.
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` (기본값): **자동 감지** — `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) 참조). 대신 전체 파일을 단일 `index` 사전으로 로드하려면 `splitKeys: false`로 설정하세요.
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/ko/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
  - 튜토리얼에서 Intlayer를 사용하여 JSON을 관리하도록 제안함으로써 SEO/키워드를 활용할 수 있습니다.