@intlayer/docs 9.0.0-canary.7 → 9.0.0-canary.8

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.
Files changed (98) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +0 -20
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +0 -20
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +0 -1
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/dynamic_dictionaries/index.md +24 -18
  8. package/docs/ar/dynamic_dictionaries/variants.md +280 -22
  9. package/docs/ar/plugins/sync-json.md +0 -1
  10. package/docs/ar/releases/v9.md +35 -12
  11. package/docs/de/dynamic_dictionaries/index.md +22 -22
  12. package/docs/de/dynamic_dictionaries/variants.md +272 -14
  13. package/docs/de/plugins/sync-json.md +0 -1
  14. package/docs/de/releases/v9.md +35 -12
  15. package/docs/en/dynamic_dictionaries/index.md +20 -14
  16. package/docs/en/dynamic_dictionaries/variants.md +266 -8
  17. package/docs/en/plugins/sync-json.md +0 -1
  18. package/docs/en/releases/v9.md +35 -12
  19. package/docs/en-GB/dynamic_dictionaries/index.md +21 -15
  20. package/docs/en-GB/dynamic_dictionaries/variants.md +268 -10
  21. package/docs/en-GB/plugins/sync-json.md +0 -1
  22. package/docs/en-GB/releases/v9.md +35 -12
  23. package/docs/es/dynamic_dictionaries/index.md +25 -19
  24. package/docs/es/dynamic_dictionaries/variants.md +275 -17
  25. package/docs/es/plugins/sync-json.md +0 -1
  26. package/docs/es/releases/v9.md +35 -12
  27. package/docs/fr/dynamic_dictionaries/index.md +26 -20
  28. package/docs/fr/dynamic_dictionaries/variants.md +273 -15
  29. package/docs/fr/plugins/sync-json.md +0 -1
  30. package/docs/fr/releases/v9.md +35 -12
  31. package/docs/hi/dynamic_dictionaries/index.md +28 -22
  32. package/docs/hi/dynamic_dictionaries/variants.md +282 -24
  33. package/docs/hi/plugins/sync-json.md +0 -1
  34. package/docs/hi/releases/v9.md +35 -12
  35. package/docs/id/dynamic_dictionaries/index.md +25 -19
  36. package/docs/id/dynamic_dictionaries/variants.md +274 -16
  37. package/docs/id/plugins/sync-json.md +0 -1
  38. package/docs/id/releases/v9.md +35 -12
  39. package/docs/it/dynamic_dictionaries/index.md +26 -20
  40. package/docs/it/dynamic_dictionaries/variants.md +273 -15
  41. package/docs/it/plugins/sync-json.md +0 -1
  42. package/docs/it/releases/v9.md +35 -12
  43. package/docs/ja/dynamic_dictionaries/index.md +27 -21
  44. package/docs/ja/dynamic_dictionaries/variants.md +276 -18
  45. package/docs/ja/plugins/sync-json.md +0 -1
  46. package/docs/ja/releases/v9.md +35 -12
  47. package/docs/ko/dynamic_dictionaries/index.md +23 -17
  48. package/docs/ko/dynamic_dictionaries/variants.md +273 -15
  49. package/docs/ko/plugins/sync-json.md +0 -1
  50. package/docs/ko/releases/v9.md +35 -12
  51. package/docs/pl/dynamic_dictionaries/index.md +26 -20
  52. package/docs/pl/dynamic_dictionaries/variants.md +275 -17
  53. package/docs/pl/plugins/sync-json.md +0 -1
  54. package/docs/pl/releases/v9.md +35 -12
  55. package/docs/pt/dynamic_dictionaries/index.md +25 -19
  56. package/docs/pt/dynamic_dictionaries/variants.md +276 -18
  57. package/docs/pt/plugins/sync-json.md +0 -1
  58. package/docs/pt/releases/v9.md +35 -12
  59. package/docs/ru/dynamic_dictionaries/index.md +25 -19
  60. package/docs/ru/dynamic_dictionaries/variants.md +277 -19
  61. package/docs/ru/plugins/sync-json.md +0 -1
  62. package/docs/ru/releases/v9.md +35 -12
  63. package/docs/tr/dynamic_dictionaries/index.md +27 -21
  64. package/docs/tr/dynamic_dictionaries/variants.md +274 -16
  65. package/docs/tr/plugins/sync-json.md +0 -1
  66. package/docs/tr/releases/v9.md +35 -12
  67. package/docs/uk/dynamic_dictionaries/index.md +25 -19
  68. package/docs/uk/dynamic_dictionaries/variants.md +277 -19
  69. package/docs/uk/plugins/sync-json.md +0 -1
  70. package/docs/uk/releases/v9.md +35 -12
  71. package/docs/vi/dynamic_dictionaries/index.md +28 -22
  72. package/docs/vi/dynamic_dictionaries/variants.md +278 -20
  73. package/docs/vi/plugins/sync-json.md +0 -1
  74. package/docs/vi/releases/v9.md +35 -12
  75. package/docs/zh/dynamic_dictionaries/index.md +24 -18
  76. package/docs/zh/dynamic_dictionaries/variants.md +274 -16
  77. package/docs/zh/plugins/sync-json.md +0 -1
  78. package/docs/zh/releases/v9.md +35 -12
  79. package/package.json +6 -6
  80. package/src/generated/docs.entry.ts +0 -20
  81. package/docs/ar/dynamic_dictionaries/dynamic_content.md +0 -271
  82. package/docs/de/dynamic_dictionaries/dynamic_content.md +0 -271
  83. package/docs/en/dynamic_dictionaries/dynamic_content.md +0 -271
  84. package/docs/en-GB/dynamic_dictionaries/dynamic_content.md +0 -271
  85. package/docs/es/dynamic_dictionaries/dynamic_content.md +0 -271
  86. package/docs/fr/dynamic_dictionaries/dynamic_content.md +0 -271
  87. package/docs/hi/dynamic_dictionaries/dynamic_content.md +0 -271
  88. package/docs/id/dynamic_dictionaries/dynamic_content.md +0 -271
  89. package/docs/it/dynamic_dictionaries/dynamic_content.md +0 -271
  90. package/docs/ja/dynamic_dictionaries/dynamic_content.md +0 -271
  91. package/docs/ko/dynamic_dictionaries/dynamic_content.md +0 -271
  92. package/docs/pl/dynamic_dictionaries/dynamic_content.md +0 -271
  93. package/docs/pt/dynamic_dictionaries/dynamic_content.md +0 -271
  94. package/docs/ru/dynamic_dictionaries/dynamic_content.md +0 -271
  95. package/docs/tr/dynamic_dictionaries/dynamic_content.md +0 -271
  96. package/docs/uk/dynamic_dictionaries/dynamic_content.md +0 -271
  97. package/docs/vi/dynamic_dictionaries/dynamic_content.md +0 -271
  98. package/docs/zh/dynamic_dictionaries/dynamic_content.md +0 -271
@@ -1,13 +1,15 @@
1
1
  ---
2
2
  createdAt: 2026-06-12
3
- updatedAt: 2026-06-12
3
+ updatedAt: 2026-06-26
4
4
  title: Варіанти
5
- description: Використовуйте поле метаданих variant у файлах вмісту Intlayer для оголошення іменованих альтернатив вмісту (A/B-тести, сезонні банери, тексти з прапорцями функцій) і перемикання між ними під час виконання без зміни коду.
5
+ description: Використовуйте поле метаданих variant у файлах контенту Intlayer, щоб оголошувати іменовані або структуровані альтернативи контенту — A/B-тести, сезонні банери, тексти під feature-прапорцями, записи CMS, контент конкретного користувача — і перемикатися між ними під час виконання без змін коду.
6
6
  keywords:
7
7
  - Варіанти
8
- - A/B Тестування
9
- - Прапорці Функцій
10
- - Динамічний Вміст
8
+ - A/B-тестування
9
+ - Feature-прапорці
10
+ - Динамічний контент
11
+ - Динамічні записи
12
+ - CMS
11
13
  - Intlayer
12
14
  - Інтернаціоналізація
13
15
  slugs:
@@ -17,17 +19,27 @@ slugs:
17
19
  history:
18
20
  - version: 9.0.0
19
21
  date: 2026-06-12
20
- changes: "Випуск функції варіантів словників"
22
+ changes: "Випуск функції варіантів"
23
+ - version: 9.1.0
24
+ date: 2026-06-26
25
+ changes: "`variant` тепер приймає рядок або об'єкт — колишні `meta` / динамічні записи оголошуються як об'єктні варіанти"
21
26
  author: aymericzip
22
27
  ---
23
28
 
24
29
  # Варіанти
25
30
 
26
- **Варіант** (Variant) — це набір файлів вмісту, які мають спільний ключ словника (`key`), але кожен має власну назву варіанта (`variant`). Intlayer надає відповідний файл на основі селектора, переданого в `useIntlayer`.
31
+ **Варіант** — це набір файлів контенту, що мають спільний ключ словника (`key`), але кожен несе своє значення `variant`. Intlayer віддає відповідний файл на основі селектора, переданого до `useIntlayer`.
27
32
 
28
- ## Оголошення варіантів
33
+ Значення `variant` може набувати **двох форм**:
29
34
 
30
- Кожен файл представляє одну іменовану альтернативу. Опущення `variant` (або встановлення значення `"default"`) позначає його як варіант за замовчуванням (fallback).
35
+ - **Рядок** одна іменована альтернатива (A/B-тести, сезонні банери, feature-прапорці).
36
+ - **Об'єкт** — структурований дискримінатор, адресований набором полів (записи CMS, контент конкретного користувача, будь-який контент із непрозорим ID як ключем). Ідентичністю є весь об'єкт: селектор має надати **рівний** об'єкт, щоб розв'язати запис.
37
+
38
+ > Об'єктна форма замінює колишнє поле `meta`. Усюди, де раніше ви писали `meta: { id, … }`, пишіть `variant: { id, … }` і вибирайте її через `{ variant: { id, … } }`.
39
+
40
+ ## Іменовані (рядкові) варіанти
41
+
42
+ Кожен файл представляє одну іменовану альтернативу. Пропуск `variant` (або значення `"default"`) позначає його як запасний.
31
43
 
32
44
  ```ts fileName="hero-banner.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
33
45
  import { t, type Dictionary } from "intlayer";
@@ -65,9 +77,9 @@ const dictionary = {
65
77
  export default dictionary;
66
78
  ```
67
79
 
68
- ## Використання варіантів
80
+ ### Використання іменованих варіантів
69
81
 
70
- ### Варіант за замовчуванням
82
+ #### Варіант за замовчуванням
71
83
 
72
84
  <Tabs group="framework">
73
85
  <Tab label="React" value="react">
@@ -209,7 +221,7 @@ export default dictionary;
209
221
  </Tab>
210
222
  </Tabs>
211
223
 
212
- ### Іменований варіант
224
+ #### Іменований варіант
213
225
 
214
226
  ```tsx
215
227
  const { headline, cta } = useIntlayer("hero-banner", {
@@ -217,18 +229,264 @@ const { headline, cta } = useIntlayer("hero-banner", {
217
229
  });
218
230
  ```
219
231
 
220
- ### Іменований варіант із явною локаллю
232
+ #### Іменований варіант із явною локаллю
221
233
 
222
234
  ```tsx
223
235
  const content = useIntlayer("hero-banner", {
224
236
  variant: "black_friday",
225
- locale: "uk",
237
+ locale: "fr",
226
238
  });
227
239
  ```
228
240
 
229
- ## Типові варіанти використання
241
+ ## Об'єктні (структуровані) варіанти
242
+
243
+ Об'єктний варіант адресує контент довільним набором пар ключ-значення, оголошених у полі `variant`, — що дозволяє моделювати записи CMS, контент конкретного користувача або будь-який контент із непрозорим ID як ключем. Ідентичністю є **весь об'єкт**: селектор має надати рівний об'єкт, щоб запис було розв'язано.
244
+
245
+ ```ts fileName="product.abc.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
246
+ import { t, type Dictionary } from "intlayer";
247
+
248
+ const dictionary = {
249
+ key: "product",
250
+ variant: { id: "prod_abc", userId: "user_123" },
251
+ content: {
252
+ name: t({ en: "Widget Pro", fr: "Widget Pro" }),
253
+ description: t({ en: "The best widget.", fr: "Le meilleur widget." }),
254
+ },
255
+ } satisfies Dictionary;
256
+
257
+ export default dictionary;
258
+ ```
259
+
260
+ ```ts fileName="product.abcd.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
261
+ import { t, type Dictionary } from "intlayer";
262
+
263
+ const dictionary = {
264
+ key: "product",
265
+ variant: { id: "prod_abcd", userId: "user_123" },
266
+ content: {
267
+ name: t({ en: "Widget Lite", fr: "Widget Lite" }),
268
+ description: t({ en: "A lighter option.", fr: "Une option plus légère." }),
269
+ },
270
+ } satisfies Dictionary;
271
+
272
+ export default dictionary;
273
+ ```
274
+
275
+ ### Використання об'єктних варіантів
276
+
277
+ Передайте відповідний об'єкт у `variant`. Кожне поле, оголошене у словнику, має бути надане й рівне; інакше результат — `null`. Порядок полів не має значення.
278
+
279
+ <Tabs group="framework">
280
+ <Tab label="React" value="react">
281
+ ```tsx fileName="Product.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
282
+ import { useIntlayer } from "react-intlayer";
283
+
284
+ export const Product = ({
285
+ productId,
286
+ userId,
287
+ }: {
288
+ productId: string;
289
+ userId: string;
290
+ }) => {
291
+ const content = useIntlayer("product", {
292
+ variant: { id: productId, userId },
293
+ });
294
+
295
+ if (!content) return null;
296
+
297
+ return <p>{content.description}</p>;
298
+ };
299
+ ```
300
+
301
+ </Tab>
302
+ <Tab label="Next.js" value="nextjs">
303
+ ```tsx fileName="Product.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
304
+ import { useIntlayer } from "next-intlayer";
305
+
306
+ export const Product = ({
307
+ productId,
308
+ userId,
309
+ }: {
310
+ productId: string;
311
+ userId: string;
312
+ }) => {
313
+ const content = useIntlayer("product", {
314
+ variant: { id: productId, userId },
315
+ });
316
+
317
+ if (!content) return null;
318
+
319
+ return <p>{content.description}</p>;
320
+ };
321
+ ```
322
+
323
+ </Tab>
324
+ <Tab label="Vue" value="vue">
325
+ ```vue fileName="Product.vue" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
326
+ <script setup>
327
+ import { useIntlayer } from "vue-intlayer";
328
+
329
+ const props = defineProps({
330
+ productId: String,
331
+ userId: String,
332
+ });
333
+
334
+ const content = useIntlayer("product", {
335
+ variant: { id: props.productId, userId: props.userId },
336
+ });
337
+ </script>
338
+
339
+ <template>
340
+ <p v-if="content">{{ content.description }}</p>
341
+ </template>
342
+ ```
343
+
344
+ </Tab>
345
+ <Tab label="Svelte" value="svelte">
346
+ ```svelte fileName="Product.svelte" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
347
+ <script lang="ts">
348
+ import { useIntlayer } from "svelte-intlayer";
349
+
350
+ export let productId: string;
351
+ export let userId: string;
352
+
353
+ const content = useIntlayer("product", {
354
+ variant: { id: productId, userId },
355
+ });
356
+ </script>
357
+
358
+ {#if $content}
359
+ <p>{$content.description}</p>
360
+ {/if}
361
+ ```
362
+
363
+ </Tab>
364
+ <Tab label="Preact" value="preact">
365
+ ```tsx fileName="Product.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
366
+ import { useIntlayer } from "preact-intlayer";
367
+
368
+ export const Product = ({
369
+ productId,
370
+ userId,
371
+ }: {
372
+ productId: string;
373
+ userId: string;
374
+ }) => {
375
+ const content = useIntlayer("product", {
376
+ variant: { id: productId, userId },
377
+ });
378
+
379
+ if (!content) return null;
380
+
381
+ return <p>{content.description}</p>;
382
+ };
383
+ ```
384
+
385
+ </Tab>
386
+ <Tab label="Solid" value="solid">
387
+ ```tsx fileName="Product.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
388
+ import { useIntlayer } from "solid-intlayer";
389
+
390
+ export const Product = (props: {
391
+ productId: string;
392
+ userId: string;
393
+ }) => {
394
+ const content = useIntlayer("product", {
395
+ variant: { id: props.productId, userId: props.userId },
396
+ });
397
+
398
+ return (
399
+ <>
400
+ {content() && <p>{content().description}</p>}
401
+ </>
402
+ );
403
+ };
404
+ ```
405
+
406
+ </Tab>
407
+ <Tab label="Angular" value="angular">
408
+ ```typescript fileName="product.component.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
409
+ import { Component, Input, OnInit } from "@angular/core";
410
+ import { useIntlayer } from "angular-intlayer";
411
+
412
+ @Component({
413
+ selector: "app-product",
414
+ template: `
415
+ @if (content()) {
416
+ <p>{{ content().description }}</p>
417
+ }
418
+ `,
419
+ })
420
+ export class ProductComponent implements OnInit {
421
+ @Input() productId!: string;
422
+ @Input() userId!: string;
423
+
424
+ content: any;
425
+
426
+ ngOnInit() {
427
+ this.content = useIntlayer("product", {
428
+ variant: { id: this.productId, userId: this.userId },
429
+ });
430
+ }
431
+ }
432
+ ```
433
+
434
+ </Tab>
435
+ <Tab label="Vanilla JS" value="vanilla">
436
+ ```javascript fileName="product.js"
437
+ import { useIntlayer } from "vanilla-intlayer";
438
+
439
+ const content = useIntlayer("product", {
440
+ variant: { id: "prod_abcd", userId: "user_123" },
441
+ });
442
+
443
+ if (content) {
444
+ document.body.innerHTML = `<p>${content.description}</p>`;
445
+ }
446
+ ```
447
+
448
+ </Tab>
449
+ </Tabs>
450
+
451
+ #### З явною локаллю
452
+
453
+ ```tsx
454
+ const content = useIntlayer("product", {
455
+ variant: { id: "prod_abc", userId: "user_123" },
456
+ locale: "fr",
457
+ });
458
+ ```
459
+
460
+ #### Відсутнє поле — немає збігу
461
+
462
+ ```ts
463
+ // Повертає null: відсутній `userId`, тож об'єкт не збігається з оголошеним варіантом
464
+ const content = useIntlayer("product", { variant: { id: "prod_abc" } });
465
+ ```
466
+
467
+ ## Режим завантаження
468
+
469
+ Об'єктні варіанти часто завантажуються ліниво. Задайте `importMode` у словнику, щоб керувати цим:
470
+
471
+ ```ts contentDeclarationFormat={["typescript", "esm", "commonjs"]}
472
+ const dictionary = {
473
+ key: "product",
474
+ importMode: "fetch", // or "dynamic"
475
+ variant: { id: "prod_abc", userId: "user_123" },
476
+ content: { … },
477
+ } satisfies Dictionary;
478
+
479
+ export default dictionary;
480
+ ```
481
+
482
+ Див. [оптимізацію бандла](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/bundle_optimization.md) для деталей про режими `static`, `dynamic` і `fetch`.
483
+
484
+ ## Типові сценарії використання
230
485
 
231
- - A/B-тестування текстів, кероване ключем експерименту
232
- - Сезонні або промо-банери
233
- - Повідомлення, керовані прапорцями функцій (feature flags)
234
- - Маркетингові кампанії для конкретних регіонів
486
+ - A/B-тести тексту, керовані ключем експерименту
487
+ - Сезонні або рекламні банери
488
+ - Повідомлення під feature-прапорцями
489
+ - Маркетингові кампанії для конкретної локалі
490
+ - Маркетинговий текст за товарами, керований у CMS
491
+ - Контент конкретного користувача або акаунта
492
+ - Будь-який контент, адресований непрозорим ID під час виконання
@@ -108,7 +108,6 @@ const config: IntlayerConfig = {
108
108
  * Завантажить та запише результати й переклади назад у JSON-файли в директорії locales
109
109
  */
110
110
  syncJSON({
111
- format: "i18next",
112
111
  source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
113
112
  priority: 0,
114
113
  format: "i18next",
@@ -1,15 +1,14 @@
1
1
  ---
2
2
  createdAt: 2026-06-14
3
- updatedAt: 2026-06-25
3
+ updatedAt: 2026-06-26
4
4
  title: Новий Intlayer v9 - Що нового?
5
- description: Дізнайтеся, що нового в Intlayer v9. Представляємо сумісні пакети швидкої заміни (drop-in) для популярних бібліотек i18n та підтримку Collections, Variants та Dynamic Records.
5
+ description: Дізнайтеся, що нового в Intlayer v9. Представляємо сумісні пакети швидкої заміни (drop-in) для популярних бібліотек i18n та підтримку Collections та Variants.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - Сумісність
9
9
  - Міграція
10
10
  - Колекції
11
11
  - Варіанти
12
- - Динамічні записи
13
12
  - i18next
14
13
  - next-intl
15
14
  - vue-i18n
@@ -22,7 +21,7 @@ author: aymericzip
22
21
 
23
22
  # Новий Intlayer v9 - Що нового?
24
23
 
25
- Ласкаво просимо до Intlayer v9! Цей мажорний реліз є величезною віхою у спрощенні шляху міграції на Intlayer завдяки **Compat Adapter Packages** (пакетам адаптерів сумісності) для основних бібліотек i18n (`react-i18next`, `next-intl`, `vue-i18n` тощо) та додає підтримку складних структур контенту: **Collections** (Колекцій), **Variants** (Варіантів) та **Dynamic Records** (Динамічних записів).
24
+ Ласкаво просимо до Intlayer v9! Цей мажорний реліз є величезною віхою у спрощенні шляху міграції на Intlayer завдяки **Compat Adapter Packages** (пакетам адаптерів сумісності) для основних бібліотек i18n (`react-i18next`, `next-intl`, `vue-i18n` тощо) та додає підтримку складних структур контенту: **Collections** (Колекцій) та **Variants** (Варіантів).
26
25
 
27
26
  ## Зміст
28
27
 
@@ -41,8 +40,10 @@ author: aymericzip
41
40
  - `@intlayer/i18next`
42
41
  - `@intlayer/react-i18next`
43
42
  - `@intlayer/next-intl`
43
+ - `@intlayer/react-intl`
44
44
  - `@intlayer/next-i18next`
45
45
  - `@intlayer/vue-i18n`
46
+ - `@intlayer/lingui`
46
47
 
47
48
  Наприклад, просто змініть:
48
49
 
@@ -100,7 +101,7 @@ export default defineConfig({
100
101
 
101
102
  ---
102
103
 
103
- ## Специфікація функцій: Collections, Variants та Dynamic Records
104
+ ## Специфікація функцій: Collections та Variants
104
105
 
105
106
  Intlayer v9 виходить за рамки статичних об'єктів типу ключ-значення, дозволяючи словникам оголошувати динамічні структури макетів, які повністю типізовані від початку до кінця (end-to-end).
106
107
 
@@ -144,6 +145,8 @@ const faq = useIntlayer("faq", { item: 1 }); // -> { question: string, answer: s
144
145
 
145
146
  Надавайте A/B тести, сезонні заголовки, feature flags або кастомні цільові сторінки (landing pages):
146
147
 
148
+ #### Рядкові варіанти (наприклад, A/B-тестування)
149
+
147
150
  ```ts fileName="hero.content.ts"
148
151
  import { t, type Dictionary } from "intlayer";
149
152
 
@@ -167,16 +170,14 @@ export default {
167
170
  const banner = useIntlayer("hero-banner", { variant: "black_friday" });
168
171
  ```
169
172
 
170
- ### 3. Динамічні записи (Dynamic Records)
171
-
172
- Визначайте словники, записи яких завантажуються динамічно під час виконання за допомогою ідентифікаторів запитів (query IDs):
173
+ #### Об'єктні варіанти (наприклад, динамічні записи)
173
174
 
174
175
  ```ts fileName="product.content.ts"
175
176
  import { t, type Dictionary } from "intlayer";
176
177
 
177
178
  export default {
178
179
  key: "product-copy",
179
- meta: {
180
+ variant: {
180
181
  id: "prod_123",
181
182
  category: "books",
182
183
  },
@@ -229,7 +230,7 @@ export default defineConfig({
229
230
  });
230
231
  ```
231
232
 
232
- - **Compiler**: Активується автоматично, коли встановлено `compiler.enabled` та налаштована шлях `compiler.output`. Вам більше не потрібно реєструвати `intlayerCompiler()` окремо.
233
+ - **Compiler**: Активується автоматично, коли `compiler.enabled` встановлено у `true` та налаштовано шлях `compiler.output`. Вам більше не потрібно реєструвати `intlayerCompiler()` окремо.
233
234
  - **Proxy**: Активується автоматично на основі нового параметра `routing.enableProxy` (`true` за замовчуванням). Він підключає middleware виявлення локалей / перенаправлення / переписування в режимі розробки, попереднього перегляду та production SSR. Вам більше не потрібно реєструвати `intlayerProxy()` окремо.
234
235
 
235
236
  ### Опція `routing.enableProxy`
@@ -252,6 +253,27 @@ export default config;
252
253
 
253
254
  ---
254
255
 
256
+ ## Компілятор вимкнено за замовчуванням
257
+
258
+ Починаючи з Intlayer v9, **компілятор вимкнено за замовчуванням** (значення `compiler.enabled` тепер за замовчуванням дорівнює `false`). Щоб увімкнути вилучення ваших файлів `.content.ts` під час збірки, встановіть `compiler.enabled: true` у своїй конфігурації:
259
+
260
+ ```ts fileName="intlayer.config.ts"
261
+ import type { IntlayerConfig } from "intlayer";
262
+
263
+ const config: IntlayerConfig = {
264
+ compiler: {
265
+ enabled: true, // За замовчуванням: false — потрібно для увімкнення компілятора починаючи з v9
266
+ output: ({ fileName }) => `./${fileName}.content.ts`,
267
+ },
268
+ };
269
+
270
+ export default config;
271
+ ```
272
+
273
+ Коли компілятор вимкнено, Intlayer пропускає крок вилучення під час збірки та покладається на вже оголошені вами словники. Вмикайте його лише тоді, коли хочете, щоб плагін збирача (`@intlayer/swc`, `@intlayer/babel` або Vite-плагін `intlayer()`) вилучав вміст автоматично.
274
+
275
+ ---
276
+
255
277
  ## React Native: імпорт з одного пакета
256
278
 
257
279
  У програмі React Native або Expo вам більше не потрібно жонглювати `react-intlayer` та `react-native-intlayer`. Пакет `react-native-intlayer` тепер **реекспортує весь API `react-intlayer`** (хуки, утиліти та підшляхи `/format`, `/html` і `/markdown`), а його `IntlayerProvider` автоматично застосовує поліфіли React Native.
@@ -278,13 +300,14 @@ npm install intlayer react-native-intlayer
278
300
 
279
301
  Якщо ви оновлюєтеся з v8, зверніть увагу, що v9 не містить критичних змін (breaking changes). Проте ось ключові зміни:
280
302
 
303
+ - **Компілятор вимкнено за замовчуванням**: значення `compiler.enabled` тепер за замовчуванням дорівнює `false`. Якщо ви покладаєтеся на вилучення ваших файлів `.content.ts` під час збірки, встановіть `compiler.enabled: true` у своєму `intlayer.config.ts`.
281
304
  - **Locales & Dialects**: Якщо ви використовуєте зовнішні залежності i18n, додайте відповідні плагіни адаптерів сумісності у вашу конфігурацію або налаштування бандлера для автоматичного перезапису імпортів.
282
- - **Custom Selectors**: При виклику `useIntlayer` другий параметр тепер зарезервований для об'єкта опцій, що містить `{ locale, item, variant, id }`. Якщо раніше ви передавали рядок локалі безпосередньо, ви все ще можете це робити, але для розширеного вибору рекомендується використовувати об'єкт опцій.
305
+ - **Custom Selectors**: При виклику `useIntlayer` другий параметр тепер зарезервований для об'єкта опцій, що містить `{ locale, item, variant }`. Якщо раніше ви передавали рядок локалі безпосередньо, ви все ще можете це робити, але для розширеного вибору рекомендується використовувати об'єкт опцій.
283
306
 
284
307
  ---
285
308
 
286
309
  ## Корисні посилання
287
310
 
288
311
  - [Посібник з пакетів адаптерів сумісності (Compat Adapter Packages)](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/compat/index.md)
289
- - [Динамічні словники - Collections, Variants та Dynamic Records](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dynamic_dictionaries/index.md)
312
+ - [Динамічні словники - Collections та Variants](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/dynamic_dictionaries/index.md)
290
313
  - [Довідник з конфігурації](https://github.com/aymericzip/intlayer/blob/main/docs/docs/uk/configuration.md)
@@ -1,13 +1,12 @@
1
1
  ---
2
2
  createdAt: 2026-06-12
3
- updatedAt: 2026-06-12
4
- title: Từ Điển Động
5
- description: Tổng quan về ba tính năng từ điển động của Intlayer — bộ sưu tập, biến thể và bản ghi động — để xây dựng nội dung i18n linh hoạt, được điều khiển bằng runtime.
3
+ updatedAt: 2026-06-26
4
+ title: Từ điển động
5
+ description: Tổng quan về các tính năng từ điển động của Intlayer — bộ sưu tập biến thể — để xây dựng nội dung i18n linh hoạt, được điều khiển trong thời gian chạy.
6
6
  keywords:
7
- - Từ Điển Động
8
- - Bộ Sưu Tập
9
- - Biến Thể
10
- - Bản Ghi Động
7
+ - Từ điển động
8
+ - Bộ sưu tập
9
+ - Biến thể
11
10
  - Intlayer
12
11
  - Quốc tế hóa
13
12
  slugs:
@@ -18,31 +17,38 @@ history:
18
17
  - version: 9.0.0
19
18
  date: 2026-06-12
20
19
  changes: "Phát hành tính năng từ điển động"
20
+ - version: 9.1.0
21
+ date: 2026-06-26
22
+ changes: "Hợp nhất bản ghi động vào biến thể — `variant` giờ chấp nhận một chuỗi hoặc một đối tượng"
21
23
  author: aymericzip
22
24
  ---
23
25
 
24
- # Từ Điển Động
26
+ # Từ điển động
25
27
 
26
- Intlayer hỗ trợ ba cơ chế để thể hiện nội dung vượt ra ngoài một từ điển tĩnh duy nhất cho mỗi khóa. Mỗi cơ chế được khai báo thông qua một **trường siêu dữ liệu (metadata) cấp cao nhất** trong tệp nội dung; không cần hàm bao (wrapper).
28
+ Intlayer hỗ trợ hai cơ chế để diễn đạt nội dung vượt ra ngoài một từ điển tĩnh duy nhất cho mỗi khóa. Mỗi cơ chế được khai báo qua một **trường metadata cấp cao nhất** trong tệp nội dung; không cần hàm bao bọc.
27
29
 
28
- | Tính năng | Trường siêu dữ liệu | Bộ chọn trong `useIntlayer` |
29
- | --------------------------------------------------------------------------------------------------------------------- | ------------------- | --------------------------- |
30
- | [Bộ Sưu Tập](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dynamic_dictionaries/collections.md) | `item: N` | `{ item: N }` |
31
- | [Biến Thể](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dynamic_dictionaries/variants.md) | `variant: "name"` | `{ variant: "name" }` |
32
- | [Bản Ghi Động](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dynamic_dictionaries/dynamic_content.md) | `meta: { id, … }` | `{ id, … }` |
30
+ | Tính năng | Trường metadata | Bộ chọn trong `useIntlayer` |
31
+ | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------- |
32
+ | [Bộ sưu tập](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dynamic_dictionaries/collections.md) | `item: N` | `{ item: N }` |
33
+ | [Biến thể](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dynamic_dictionaries/variants.md) | `variant: "name"` _hoặc_ `variant: { … }` | `{ variant: "name" }` _hoặc_ `{ variant: { … } }` |
33
34
 
34
- Cả ba cơ chế đều kết hợp với đối số ngôn ngữ (locale) và hỗ trợ tải chọn lọc / tải lười (lazy loading) thông qua `importMode`.
35
+ Cả hai đều kết hợp với đối số locale và hỗ trợ tải chọn lọc / lười qua `importMode`.
35
36
 
36
- ## Khi nào nên sử dụng tính năng nào
37
+ ## Khi nào dùng cái nào
37
38
 
38
- - **Bộ sưu tập** — danh sách các mục thứ tự được quản lý trong các tệp riêng biệt (mục FAQ, bài viết blog, sản phẩm).
39
- - **Biến thể** — các lựa chọn nội dung thay thế được đặt tên cho các thử nghiệm A/B, biểu ngữ theo mùa hoặc cờ tính năng (feature flags).
40
- - **Bản ghi động** nội dung được truy xuất tại runtime bằng một ID ẩn (bản ghi CMS, nội dung dành riêng cho người dùng).
39
+ - **Bộ sưu tập** — danh sách mục được sắp xếp, quản lý trong các tệp riêng (mục FAQ, bài blog, sản phẩm).
40
+ - **Biến thể** — các lựa chọn nội dung được đặt tên hoặc cấu trúc:
41
+ - biến thể **chuỗi** cho thử nghiệm A/B, banner theo mùa hoặc feature flag;
42
+ - biến thể **đối tượng** cho bản ghi CMS, nội dung riêng theo người dùng, hoặc bất kỳ nội dung nào được định địa chỉ bằng một tập hợp trường ("bản ghi động" trước đây).
41
43
 
42
- ## Giải quyết xung đột bộ chọn
44
+ > Các phiên bản trước cung cấp một trường `meta` riêng cho nội dung được khóa theo bản ghi. Nó đã được hợp nhất vào `variant`: hãy truyền một **đối tượng** cho `variant` thay vì dùng `meta`.
43
45
 
44
- Khi nhiều bộ chọn tồn tại trên cùng một từ điển, thứ tự ưu tiên giải quyết là:
46
+ ## Khử nhập nhằng bộ chọn
47
+
48
+ Một khóa có thể khai báo cả hai chiều cùng lúc (ví dụ một bộ sưu tập mà mỗi mục có một biến thể). Chúng được phân giải theo thứ tự:
45
49
 
46
50
  ```
47
- variant → meta → item
51
+ variant → item
48
52
  ```
53
+
54
+ Vì vậy, `{ variant: "promo" }` trên khóa variant × item trả về mọi mục promo dưới dạng mảng, và thêm `{ item: 2 }` thu hẹp lại còn một mục duy nhất.