@intlayer/docs 9.1.1 → 9.1.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/dynamic_dictionaries/variants.md +214 -1
- package/docs/de/dynamic_dictionaries/variants.md +174 -1
- package/docs/en/dynamic_dictionaries/variants.md +174 -1
- package/docs/en-GB/dynamic_dictionaries/variants.md +174 -1
- package/docs/es/dynamic_dictionaries/variants.md +174 -1
- package/docs/fr/dynamic_dictionaries/variants.md +174 -1
- package/docs/hi/dynamic_dictionaries/variants.md +174 -1
- package/docs/id/dynamic_dictionaries/variants.md +174 -1
- package/docs/it/dynamic_dictionaries/variants.md +174 -1
- package/docs/ja/dynamic_dictionaries/variants.md +174 -1
- package/docs/ko/dynamic_dictionaries/variants.md +174 -1
- package/docs/pl/dynamic_dictionaries/variants.md +174 -1
- package/docs/pt/dynamic_dictionaries/variants.md +174 -1
- package/docs/ru/dynamic_dictionaries/variants.md +174 -1
- package/docs/tr/dynamic_dictionaries/variants.md +174 -1
- package/docs/uk/dynamic_dictionaries/variants.md +174 -1
- package/docs/vi/dynamic_dictionaries/variants.md +174 -1
- package/docs/zh/dynamic_dictionaries/variants.md +174 -1
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2026-06-12
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-08-04
|
|
4
4
|
title: المتغيرات
|
|
5
5
|
description: استخدم حقل البيانات الوصفية variant في ملفات محتوى Intlayer لإعلان بدائل محتوى مُسمّاة أو منظّمة — اختبارات A/B، لافتات موسمية، نصوص بأعلام الميزات، سجلات CMS، محتوى خاص بالمستخدم — والتبديل بينها في وقت التشغيل دون تغييرات في الشيفرة.
|
|
6
6
|
keywords:
|
|
@@ -26,6 +26,9 @@ history:
|
|
|
26
26
|
- version: 9.1.1
|
|
27
27
|
date: 2026-07-31
|
|
28
28
|
changes: "تُعرّف المتغيرة فقط المفاتيح التي تتجاوزها؛ بينما تتراجع المتغيرات غير المُعرّفة إلى الإدخال الافتراضي"
|
|
29
|
+
- version: 9.1.2
|
|
30
|
+
date: 2026-08-04
|
|
31
|
+
changes: "تقبل المزوِّدات خاصية `variant` محيطية؛ وتقبل المحدِّدات سلسلة تفضيل مرتَّبة"
|
|
29
32
|
author: aymericzip
|
|
30
33
|
---
|
|
31
34
|
|
|
@@ -40,6 +43,46 @@ author: aymericzip
|
|
|
40
43
|
|
|
41
44
|
> يحلّ الشكل الكائني محل حقل `meta` السابق. في كل مكان كنت تكتب فيه سابقًا `meta: { id, … }`، اكتب `variant: { id, … }`، وحدّدها بـ `{ variant: { id, … } }`.
|
|
42
45
|
|
|
46
|
+
## المتغيرات المسماة (سلسلة نصية)
|
|
47
|
+
|
|
48
|
+
يمثّل كل ملف بديلًا مُسمّى واحدًا. وإغفال `variant` (أو ضبطه على `"default"`) يجعله البديل الاحتياطي.
|
|
49
|
+
|
|
50
|
+
```ts fileName="hero-banner.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
51
|
+
import { t, type Dictionary } from "intlayer";
|
|
52
|
+
|
|
53
|
+
const dictionary = {
|
|
54
|
+
key: "hero-banner",
|
|
55
|
+
variant: "default",
|
|
56
|
+
content: {
|
|
57
|
+
headline: t({
|
|
58
|
+
en: "Build faster with Intlayer",
|
|
59
|
+
fr: "Développez plus vite avec Intlayer",
|
|
60
|
+
}),
|
|
61
|
+
cta: t({ en: "Get started", fr: "Commencer" }),
|
|
62
|
+
},
|
|
63
|
+
} satisfies Dictionary;
|
|
64
|
+
|
|
65
|
+
export default dictionary;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```ts fileName="hero-banner.black-friday.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
69
|
+
import { t, type Dictionary } from "intlayer";
|
|
70
|
+
|
|
71
|
+
const dictionary = {
|
|
72
|
+
key: "hero-banner",
|
|
73
|
+
variant: "black_friday",
|
|
74
|
+
content: {
|
|
75
|
+
headline: t({
|
|
76
|
+
en: "50 % off — today only",
|
|
77
|
+
fr: "−50 % — aujourd'hui seulement",
|
|
78
|
+
}),
|
|
79
|
+
cta: t({ en: "Shop now", fr: "Acheter maintenant" }),
|
|
80
|
+
},
|
|
81
|
+
} satisfies Dictionary;
|
|
82
|
+
|
|
83
|
+
export default dictionary;
|
|
84
|
+
```
|
|
85
|
+
|
|
43
86
|
### المتغيرات الجزئية
|
|
44
87
|
|
|
45
88
|
تُعرّف المتغيرة **فقط المفاتيح التي تتجاوزها**؛ ويتم وراثة الباقي من الإدخال الافتراضي.
|
|
@@ -494,6 +537,176 @@ const content = useIntlayer("product", {
|
|
|
494
537
|
const content = useIntlayer("product", { variant: { id: "prod_abc" } });
|
|
495
538
|
```
|
|
496
539
|
|
|
540
|
+
## المتغير المحيطي
|
|
541
|
+
|
|
542
|
+
بعض أبعاد المتغيرات ثابتة طوال الجلسة — المستأجر، ونوع المدرسة، ومستوى الخطة. تُحلّ مرة واحدة، ولا ينبغي لأي مكوّن أن يمررها يدويًا.
|
|
543
|
+
|
|
544
|
+
> لا تغلّف `useIntlayer` داخل خطّاف خاص بك لحقنها. فتحسين وقت البناء لا يعيد كتابة سوى استدعاء `useIntlayer("key")` الحرفي المستورد من حزمة إطار العمل، لذا لن يُحزَم أي شيء خلف غلاف.
|
|
545
|
+
|
|
546
|
+
بدلًا من ذلك، صرّح عن المتغير مرة واحدة على المزوِّد، تمامًا مثل `locale`:
|
|
547
|
+
|
|
548
|
+
<Tabs group="framework">
|
|
549
|
+
<Tab label="React" value="react">
|
|
550
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
551
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
552
|
+
|
|
553
|
+
export const App = ({ locale, schoolType }) => (
|
|
554
|
+
<IntlayerProvider locale={locale} variant={schoolType}>
|
|
555
|
+
<Hero />
|
|
556
|
+
</IntlayerProvider>
|
|
557
|
+
);
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
</Tab>
|
|
561
|
+
<Tab label="Next.js" value="nextjs">
|
|
562
|
+
```tsx fileName="layout.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
563
|
+
import { IntlayerServerProvider } from "next-intlayer/server";
|
|
564
|
+
import { IntlayerClientProvider } from "next-intlayer";
|
|
565
|
+
|
|
566
|
+
export default async function Layout({ children, params }) {
|
|
567
|
+
const { locale } = await params;
|
|
568
|
+
const schoolType = await getSchoolType();
|
|
569
|
+
|
|
570
|
+
return (
|
|
571
|
+
<IntlayerServerProvider locale={locale} variant={schoolType}>
|
|
572
|
+
<IntlayerClientProvider locale={locale} variant={schoolType}>
|
|
573
|
+
{children}
|
|
574
|
+
</IntlayerClientProvider>
|
|
575
|
+
</IntlayerServerProvider>
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
</Tab>
|
|
581
|
+
<Tab label="Vue" value="vue">
|
|
582
|
+
```ts fileName="main.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
583
|
+
import { createApp } from "vue";
|
|
584
|
+
import { installIntlayer } from "vue-intlayer";
|
|
585
|
+
import App from "./App.vue";
|
|
586
|
+
|
|
587
|
+
const app = createApp(App);
|
|
588
|
+
|
|
589
|
+
installIntlayer(app, { locale: "en", variant: schoolType });
|
|
590
|
+
|
|
591
|
+
app.mount("#app");
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
</Tab>
|
|
595
|
+
<Tab label="Svelte" value="svelte">
|
|
596
|
+
```svelte fileName="+layout.svelte" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
597
|
+
<script lang="ts">
|
|
598
|
+
import { setupIntlayer } from "svelte-intlayer";
|
|
599
|
+
|
|
600
|
+
export let schoolType: string;
|
|
601
|
+
|
|
602
|
+
setupIntlayer("en", schoolType);
|
|
603
|
+
</script>
|
|
604
|
+
|
|
605
|
+
<slot />
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
</Tab>
|
|
609
|
+
<Tab label="Preact" value="preact">
|
|
610
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
611
|
+
import { IntlayerProvider } from "preact-intlayer";
|
|
612
|
+
|
|
613
|
+
export const App = ({ locale, schoolType }) => (
|
|
614
|
+
<IntlayerProvider locale={locale} variant={schoolType}>
|
|
615
|
+
<Hero />
|
|
616
|
+
</IntlayerProvider>
|
|
617
|
+
);
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
</Tab>
|
|
621
|
+
<Tab label="Solid" value="solid">
|
|
622
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
623
|
+
import { IntlayerProvider } from "solid-intlayer";
|
|
624
|
+
|
|
625
|
+
export const App = (props) => (
|
|
626
|
+
<IntlayerProvider locale={props.locale} variant={props.schoolType}>
|
|
627
|
+
<Hero />
|
|
628
|
+
</IntlayerProvider>
|
|
629
|
+
);
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
</Tab>
|
|
633
|
+
<Tab label="Angular" value="angular">
|
|
634
|
+
```typescript fileName="app.config.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
635
|
+
import { ApplicationConfig } from "@angular/core";
|
|
636
|
+
import { provideIntlayer } from "angular-intlayer";
|
|
637
|
+
|
|
638
|
+
export const appConfig: ApplicationConfig = {
|
|
639
|
+
providers: [provideIntlayer("en", true, schoolType)],
|
|
640
|
+
};
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
</Tab>
|
|
644
|
+
<Tab label="Vanilla JS" value="vanilla">
|
|
645
|
+
```javascript fileName="main.js"
|
|
646
|
+
import { installIntlayer } from "vanilla-intlayer";
|
|
647
|
+
|
|
648
|
+
installIntlayer({ locale: "en", variant: schoolType });
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
</Tab>
|
|
652
|
+
</Tabs>
|
|
653
|
+
|
|
654
|
+
أصبحت كل قراءة قاموس أسفل المزوِّد تُحلّ وفق ذلك المتغير، ويفوز دائمًا المحدِّد الموجود في موضع الاستدعاء:
|
|
655
|
+
|
|
656
|
+
```tsx
|
|
657
|
+
useIntlayer("hero-banner");
|
|
658
|
+
// → متغير المزوِّد
|
|
659
|
+
|
|
660
|
+
useIntlayer("hero-banner", { variant: "summer" });
|
|
661
|
+
// → "summer" — يستبدل متغير المزوِّد ولا يوسّعه
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### الأشكال
|
|
665
|
+
|
|
666
|
+
تقبل خاصية `variant` ثلاثة أشكال:
|
|
667
|
+
|
|
668
|
+
| الشكل | المعنى |
|
|
669
|
+
| --------------------------------------------------------- | ----------------------------- |
|
|
670
|
+
| `variant="school1"` | متغير مسمّى واحد لكل المفاتيح |
|
|
671
|
+
| `variant={["school1", "default"]}` | سلسلة تفضيل مرتَّبة |
|
|
672
|
+
| `variant={{ "hero-banner": "school1", default: "base" }}` | متغير لكل مفتاح قاموس |
|
|
673
|
+
|
|
674
|
+
#### سلسلة التفضيل
|
|
675
|
+
|
|
676
|
+
تُجرَّب السلسلة من اليسار إلى اليمين مقابل المدخلات التي يصرّح بها كل مفتاح، ويفوز أول مدخل مُصرَّح به. وعندما لا يكون أي منها مُصرَّحًا به، يُستخدم المدخل الافتراضي الضمني — تمامًا كما في حالة القيمة المفردة.
|
|
677
|
+
|
|
678
|
+
```tsx
|
|
679
|
+
<IntlayerProvider variant={["school1", "school2"]} />
|
|
680
|
+
// `hero-banner` لا يصرّح بمدخل `school1` لكنه يصرّح بـ `school2` ← "school2"
|
|
681
|
+
// مفتاح لا يصرّح بأي منهما ← المدخل الافتراضي
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
لذا تُقرأ `["black_friday", "summer"]` على أنها «black friday إن كان لهذا المفتاح واحد، وإلا summer، وإلا الافتراضي». وتُقبل السلاسل أيضًا في موضع الاستدعاء:
|
|
685
|
+
|
|
686
|
+
```tsx
|
|
687
|
+
useIntlayer("hero-banner", { variant: ["black_friday", "summer"] });
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
> لاحظ أن هذا هو الصورة المعكوسة للمصفوفة التي يقبلها **حقل** `variant` في ملف المحتوى: فهناك تُصرِّح المصفوفة بمدخل لكل عنصر، أما هنا فتستهلكها بترتيب الأولوية.
|
|
691
|
+
|
|
692
|
+
#### خريطة لكل مفتاح
|
|
693
|
+
|
|
694
|
+
خاطب كل مفتاح قاموس على حدة. ويغطي المدخل المحجوز `default` كل المفاتيح غير المذكورة:
|
|
695
|
+
|
|
696
|
+
```tsx
|
|
697
|
+
<IntlayerProvider
|
|
698
|
+
variant={{
|
|
699
|
+
"hero-banner": "school1",
|
|
700
|
+
product: ["school1", "default"],
|
|
701
|
+
default: "base",
|
|
702
|
+
}}
|
|
703
|
+
/>
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
> على المزوِّد، يُقرأ الكائن البسيط **دائمًا** كخريطة لكل مفتاح، ولا يُقرأ أبدًا كمتغير كائني — فالاثنان متطابقان بنيويًا. ولتثبيت متغير كائني عالميًا، ضعه متداخلًا تحت مدخل: `variant={{ default: { id: "prod_abc" } }}`.
|
|
707
|
+
|
|
708
|
+
ولأن مفاتيح الخريطة تُدقَّق مقابل مفاتيح القواميس المصرَّح بها، فإن أي خطأ مطبعي — أو متغيرًا كائنيًا مكتوبًا مباشرة مثل `variant={{ id: "prod_abc" }}` — يُعدّ خطأ في وقت الترجمة.
|
|
709
|
+
|
|
497
710
|
## وضع التحميل
|
|
498
711
|
|
|
499
712
|
غالبًا ما تُحمَّل المتغيرات الكائنية بشكل كسول. اضبط `importMode` على القاموس للتحكم في ذلك:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2026-06-12
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-08-04
|
|
4
4
|
title: Varianten
|
|
5
5
|
description: Verwenden Sie das variant-Metadatenfeld in Intlayer-Inhaltsdateien, um benannte oder strukturierte Inhaltsalternativen zu deklarieren — A/B-Tests, saisonale Banner, Feature-Flag-Texte, CMS-Datensätze, benutzerspezifische Inhalte — und zur Laufzeit ohne Codeänderungen zwischen ihnen zu wechseln.
|
|
6
6
|
keywords:
|
|
@@ -26,6 +26,9 @@ history:
|
|
|
26
26
|
- version: 9.1.1
|
|
27
27
|
date: 2026-07-31
|
|
28
28
|
changes: "Eine Variante deklariert nur die Schlüssel, die sie überschreibt; nicht deklarierte Varianten fallen auf den Standardeintrag zurück"
|
|
29
|
+
- version: 9.1.2
|
|
30
|
+
date: 2026-08-04
|
|
31
|
+
changes: "Provider akzeptieren eine ambiente `variant`-Prop; Selektoren akzeptieren eine geordnete Präferenzkette"
|
|
29
32
|
author: aymericzip
|
|
30
33
|
---
|
|
31
34
|
|
|
@@ -498,6 +501,176 @@ const content = useIntlayer("product", {
|
|
|
498
501
|
const content = useIntlayer("product", { variant: { id: "prod_abc" } });
|
|
499
502
|
```
|
|
500
503
|
|
|
504
|
+
## Ambiente Variante
|
|
505
|
+
|
|
506
|
+
Manche Variantendimensionen stehen für eine ganze Sitzung fest — der Mandant, der Schultyp, die Tarifstufe. Sie werden einmal aufgelöst, und keine Komponente sollte sie von Hand durchreichen müssen.
|
|
507
|
+
|
|
508
|
+
> Kapseln Sie `useIntlayer` nicht in einen eigenen Hook, um sie einzuschleusen. Die Optimierung zur Bauzeit schreibt nur einen literalen `useIntlayer("key")`-Aufruf um, der aus dem Framework-Paket importiert wurde — hinter einem Wrapper wird nichts gebündelt.
|
|
509
|
+
|
|
510
|
+
Deklarieren Sie die Variante stattdessen einmal am Provider, genau wie `locale`:
|
|
511
|
+
|
|
512
|
+
<Tabs group="framework">
|
|
513
|
+
<Tab label="React" value="react">
|
|
514
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
515
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
516
|
+
|
|
517
|
+
export const App = ({ locale, schoolType }) => (
|
|
518
|
+
<IntlayerProvider locale={locale} variant={schoolType}>
|
|
519
|
+
<Hero />
|
|
520
|
+
</IntlayerProvider>
|
|
521
|
+
);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
</Tab>
|
|
525
|
+
<Tab label="Next.js" value="nextjs">
|
|
526
|
+
```tsx fileName="layout.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
527
|
+
import { IntlayerServerProvider } from "next-intlayer/server";
|
|
528
|
+
import { IntlayerClientProvider } from "next-intlayer";
|
|
529
|
+
|
|
530
|
+
export default async function Layout({ children, params }) {
|
|
531
|
+
const { locale } = await params;
|
|
532
|
+
const schoolType = await getSchoolType();
|
|
533
|
+
|
|
534
|
+
return (
|
|
535
|
+
<IntlayerServerProvider locale={locale} variant={schoolType}>
|
|
536
|
+
<IntlayerClientProvider locale={locale} variant={schoolType}>
|
|
537
|
+
{children}
|
|
538
|
+
</IntlayerClientProvider>
|
|
539
|
+
</IntlayerServerProvider>
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
</Tab>
|
|
545
|
+
<Tab label="Vue" value="vue">
|
|
546
|
+
```ts fileName="main.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
547
|
+
import { createApp } from "vue";
|
|
548
|
+
import { installIntlayer } from "vue-intlayer";
|
|
549
|
+
import App from "./App.vue";
|
|
550
|
+
|
|
551
|
+
const app = createApp(App);
|
|
552
|
+
|
|
553
|
+
installIntlayer(app, { locale: "en", variant: schoolType });
|
|
554
|
+
|
|
555
|
+
app.mount("#app");
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
</Tab>
|
|
559
|
+
<Tab label="Svelte" value="svelte">
|
|
560
|
+
```svelte fileName="+layout.svelte" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
561
|
+
<script lang="ts">
|
|
562
|
+
import { setupIntlayer } from "svelte-intlayer";
|
|
563
|
+
|
|
564
|
+
export let schoolType: string;
|
|
565
|
+
|
|
566
|
+
setupIntlayer("en", schoolType);
|
|
567
|
+
</script>
|
|
568
|
+
|
|
569
|
+
<slot />
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
</Tab>
|
|
573
|
+
<Tab label="Preact" value="preact">
|
|
574
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
575
|
+
import { IntlayerProvider } from "preact-intlayer";
|
|
576
|
+
|
|
577
|
+
export const App = ({ locale, schoolType }) => (
|
|
578
|
+
<IntlayerProvider locale={locale} variant={schoolType}>
|
|
579
|
+
<Hero />
|
|
580
|
+
</IntlayerProvider>
|
|
581
|
+
);
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
</Tab>
|
|
585
|
+
<Tab label="Solid" value="solid">
|
|
586
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
587
|
+
import { IntlayerProvider } from "solid-intlayer";
|
|
588
|
+
|
|
589
|
+
export const App = (props) => (
|
|
590
|
+
<IntlayerProvider locale={props.locale} variant={props.schoolType}>
|
|
591
|
+
<Hero />
|
|
592
|
+
</IntlayerProvider>
|
|
593
|
+
);
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
</Tab>
|
|
597
|
+
<Tab label="Angular" value="angular">
|
|
598
|
+
```typescript fileName="app.config.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
599
|
+
import { ApplicationConfig } from "@angular/core";
|
|
600
|
+
import { provideIntlayer } from "angular-intlayer";
|
|
601
|
+
|
|
602
|
+
export const appConfig: ApplicationConfig = {
|
|
603
|
+
providers: [provideIntlayer("en", true, schoolType)],
|
|
604
|
+
};
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
</Tab>
|
|
608
|
+
<Tab label="Vanilla JS" value="vanilla">
|
|
609
|
+
```javascript fileName="main.js"
|
|
610
|
+
import { installIntlayer } from "vanilla-intlayer";
|
|
611
|
+
|
|
612
|
+
installIntlayer({ locale: "en", variant: schoolType });
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
</Tab>
|
|
616
|
+
</Tabs>
|
|
617
|
+
|
|
618
|
+
Jeder Wörterbuchzugriff unterhalb des Providers wird nun gegen diese Variante aufgelöst, und ein Selektor an der Aufrufstelle gewinnt immer:
|
|
619
|
+
|
|
620
|
+
```tsx
|
|
621
|
+
useIntlayer("hero-banner");
|
|
622
|
+
// → die Variante des Providers
|
|
623
|
+
|
|
624
|
+
useIntlayer("hero-banner", { variant: "summer" });
|
|
625
|
+
// → "summer" — ersetzt die Provider-Variante, sie wird nicht erweitert
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### Formen
|
|
629
|
+
|
|
630
|
+
Die `variant`-Prop akzeptiert drei Formen:
|
|
631
|
+
|
|
632
|
+
| Form | Bedeutung |
|
|
633
|
+
| --------------------------------------------------------- | ------------------------------------------ |
|
|
634
|
+
| `variant="school1"` | eine benannte Variante für jeden Schlüssel |
|
|
635
|
+
| `variant={["school1", "default"]}` | eine geordnete Präferenzkette |
|
|
636
|
+
| `variant={{ "hero-banner": "school1", default: "base" }}` | eine Variante pro Wörterbuchschlüssel |
|
|
637
|
+
|
|
638
|
+
#### Präferenzkette
|
|
639
|
+
|
|
640
|
+
Eine Kette wird von links nach rechts gegen die von jedem Schlüssel deklarierten Einträge geprüft; der erste deklarierte gewinnt. Ist keiner deklariert, wird der implizite Standardeintrag verwendet — genau wie bei einem Einzelwert.
|
|
641
|
+
|
|
642
|
+
```tsx
|
|
643
|
+
<IntlayerProvider variant={["school1", "school2"]} />
|
|
644
|
+
// `hero-banner` deklariert keinen `school1`-Eintrag, aber `school2` → "school2"
|
|
645
|
+
// ein Schlüssel, der keinen von beiden deklariert → der Standardeintrag
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
`["black_friday", "summer"]` liest sich also als „black friday, falls dieser Schlüssel eine hat, sonst summer, sonst Standard“. Ketten werden auch an der Aufrufstelle akzeptiert:
|
|
649
|
+
|
|
650
|
+
```tsx
|
|
651
|
+
useIntlayer("hero-banner", { variant: ["black_friday", "summer"] });
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
> Beachten Sie, dass dies das Spiegelbild des Arrays ist, das das `variant`-**Feld** einer Inhaltsdatei akzeptiert: dort _deklariert_ ein Array einen Eintrag je Element, hier _konsumiert_ es sie in Prioritätsreihenfolge.
|
|
655
|
+
|
|
656
|
+
#### Zuordnung je Schlüssel
|
|
657
|
+
|
|
658
|
+
Sprechen Sie jeden Wörterbuchschlüssel einzeln an. Der reservierte Eintrag `default` deckt alle nicht aufgeführten Schlüssel ab:
|
|
659
|
+
|
|
660
|
+
```tsx
|
|
661
|
+
<IntlayerProvider
|
|
662
|
+
variant={{
|
|
663
|
+
"hero-banner": "school1",
|
|
664
|
+
product: ["school1", "default"],
|
|
665
|
+
default: "base",
|
|
666
|
+
}}
|
|
667
|
+
/>
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
> An einem Provider wird ein einfaches Objekt **immer** als Zuordnung je Schlüssel gelesen, nie als Objektvariante — beide sind strukturell identisch. Um eine Objektvariante global festzulegen, verschachteln Sie sie unter einem Eintrag: `variant={{ default: { id: "prod_abc" } }}`.
|
|
671
|
+
|
|
672
|
+
Da die Schlüssel der Zuordnung gegen Ihre deklarierten Wörterbuchschlüssel geprüft werden, ist ein Tippfehler — oder eine direkt geschriebene Objektvariante wie `variant={{ id: "prod_abc" }}` — ein Compilerfehler.
|
|
673
|
+
|
|
501
674
|
## Lademodus
|
|
502
675
|
|
|
503
676
|
Objekt-Varianten werden oft verzögert geladen. Setzen Sie `importMode` im Wörterbuch, um dies zu steuern:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2026-06-12
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-08-04
|
|
4
4
|
title: Variants
|
|
5
5
|
description: Use the variant metadata field in Intlayer content files to declare named or structured content alternatives — A/B tests, seasonal banners, feature-flagged copy, CMS records, user-specific content — and switch between them at runtime without code changes.
|
|
6
6
|
keywords:
|
|
@@ -26,6 +26,9 @@ history:
|
|
|
26
26
|
- version: 9.1.1
|
|
27
27
|
date: 2026-07-31
|
|
28
28
|
changes: "A variant declares only the keys it overrides; undeclared variants fall back to the default entry"
|
|
29
|
+
- version: 9.1.2
|
|
30
|
+
date: 2026-08-04
|
|
31
|
+
changes: "Providers accept an ambient `variant` prop; selectors accept an ordered preference chain"
|
|
29
32
|
author: aymericzip
|
|
30
33
|
---
|
|
31
34
|
|
|
@@ -498,6 +501,176 @@ const content = useIntlayer("product", {
|
|
|
498
501
|
const content = useIntlayer("product", { variant: { id: "prod_abc" } });
|
|
499
502
|
```
|
|
500
503
|
|
|
504
|
+
## Ambient variant
|
|
505
|
+
|
|
506
|
+
Some variant dimensions are fixed for a whole session — the tenant, the school type, the plan tier. They are resolved once, and no component should have to pass them by hand.
|
|
507
|
+
|
|
508
|
+
> Do not wrap `useIntlayer` in your own hook to inject them. The build-time optimization only rewrites a literal `useIntlayer("key")` imported from the framework package, so nothing behind a wrapper gets bundled.
|
|
509
|
+
|
|
510
|
+
Declare the variant once on the provider instead, exactly like `locale`:
|
|
511
|
+
|
|
512
|
+
<Tabs group="framework">
|
|
513
|
+
<Tab label="React" value="react">
|
|
514
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
515
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
516
|
+
|
|
517
|
+
export const App = ({ locale, schoolType }) => (
|
|
518
|
+
<IntlayerProvider locale={locale} variant={schoolType}>
|
|
519
|
+
<Hero />
|
|
520
|
+
</IntlayerProvider>
|
|
521
|
+
);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
</Tab>
|
|
525
|
+
<Tab label="Next.js" value="nextjs">
|
|
526
|
+
```tsx fileName="layout.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
527
|
+
import { IntlayerServerProvider } from "next-intlayer/server";
|
|
528
|
+
import { IntlayerClientProvider } from "next-intlayer";
|
|
529
|
+
|
|
530
|
+
export default async function Layout({ children, params }) {
|
|
531
|
+
const { locale } = await params;
|
|
532
|
+
const schoolType = await getSchoolType();
|
|
533
|
+
|
|
534
|
+
return (
|
|
535
|
+
<IntlayerServerProvider locale={locale} variant={schoolType}>
|
|
536
|
+
<IntlayerClientProvider locale={locale} variant={schoolType}>
|
|
537
|
+
{children}
|
|
538
|
+
</IntlayerClientProvider>
|
|
539
|
+
</IntlayerServerProvider>
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
</Tab>
|
|
545
|
+
<Tab label="Vue" value="vue">
|
|
546
|
+
```ts fileName="main.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
547
|
+
import { createApp } from "vue";
|
|
548
|
+
import { installIntlayer } from "vue-intlayer";
|
|
549
|
+
import App from "./App.vue";
|
|
550
|
+
|
|
551
|
+
const app = createApp(App);
|
|
552
|
+
|
|
553
|
+
installIntlayer(app, { locale: "en", variant: schoolType });
|
|
554
|
+
|
|
555
|
+
app.mount("#app");
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
</Tab>
|
|
559
|
+
<Tab label="Svelte" value="svelte">
|
|
560
|
+
```svelte fileName="+layout.svelte" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
561
|
+
<script lang="ts">
|
|
562
|
+
import { setupIntlayer } from "svelte-intlayer";
|
|
563
|
+
|
|
564
|
+
export let schoolType: string;
|
|
565
|
+
|
|
566
|
+
setupIntlayer("en", schoolType);
|
|
567
|
+
</script>
|
|
568
|
+
|
|
569
|
+
<slot />
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
</Tab>
|
|
573
|
+
<Tab label="Preact" value="preact">
|
|
574
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
575
|
+
import { IntlayerProvider } from "preact-intlayer";
|
|
576
|
+
|
|
577
|
+
export const App = ({ locale, schoolType }) => (
|
|
578
|
+
<IntlayerProvider locale={locale} variant={schoolType}>
|
|
579
|
+
<Hero />
|
|
580
|
+
</IntlayerProvider>
|
|
581
|
+
);
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
</Tab>
|
|
585
|
+
<Tab label="Solid" value="solid">
|
|
586
|
+
```tsx fileName="App.tsx" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
587
|
+
import { IntlayerProvider } from "solid-intlayer";
|
|
588
|
+
|
|
589
|
+
export const App = (props) => (
|
|
590
|
+
<IntlayerProvider locale={props.locale} variant={props.schoolType}>
|
|
591
|
+
<Hero />
|
|
592
|
+
</IntlayerProvider>
|
|
593
|
+
);
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
</Tab>
|
|
597
|
+
<Tab label="Angular" value="angular">
|
|
598
|
+
```typescript fileName="app.config.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
|
|
599
|
+
import { ApplicationConfig } from "@angular/core";
|
|
600
|
+
import { provideIntlayer } from "angular-intlayer";
|
|
601
|
+
|
|
602
|
+
export const appConfig: ApplicationConfig = {
|
|
603
|
+
providers: [provideIntlayer("en", true, schoolType)],
|
|
604
|
+
};
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
</Tab>
|
|
608
|
+
<Tab label="Vanilla JS" value="vanilla">
|
|
609
|
+
```javascript fileName="main.js"
|
|
610
|
+
import { installIntlayer } from "vanilla-intlayer";
|
|
611
|
+
|
|
612
|
+
installIntlayer({ locale: "en", variant: schoolType });
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
</Tab>
|
|
616
|
+
</Tabs>
|
|
617
|
+
|
|
618
|
+
Every dictionary read below the provider now resolves against that variant, and a call-site selector always wins:
|
|
619
|
+
|
|
620
|
+
```tsx
|
|
621
|
+
useIntlayer("hero-banner");
|
|
622
|
+
// → the provider variant
|
|
623
|
+
|
|
624
|
+
useIntlayer("hero-banner", { variant: "summer" });
|
|
625
|
+
// → "summer" — replaces the provider variant, it is not extended
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### Forms
|
|
629
|
+
|
|
630
|
+
The `variant` prop accepts three forms:
|
|
631
|
+
|
|
632
|
+
| Form | Meaning |
|
|
633
|
+
| --------------------------------------------------------- | ------------------------------- |
|
|
634
|
+
| `variant="school1"` | one named variant for every key |
|
|
635
|
+
| `variant={["school1", "default"]}` | an ordered preference chain |
|
|
636
|
+
| `variant={{ "hero-banner": "school1", default: "base" }}` | one variant per dictionary key |
|
|
637
|
+
|
|
638
|
+
#### Preference chain
|
|
639
|
+
|
|
640
|
+
A chain is tried left to right against the entries each key declares, and the first declared one wins. When none is declared, the implicit default entry is used — exactly as for a single value.
|
|
641
|
+
|
|
642
|
+
```tsx
|
|
643
|
+
<IntlayerProvider variant={["school1", "school2"]} />
|
|
644
|
+
// `hero-banner` declares no `school1` entry but declares `school2` → "school2"
|
|
645
|
+
// a key declaring neither → the default entry
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
So `["black_friday", "summer"]` reads as "black friday if this key has one, else summer, else default". Chains are also accepted at the call site:
|
|
649
|
+
|
|
650
|
+
```tsx
|
|
651
|
+
useIntlayer("hero-banner", { variant: ["black_friday", "summer"] });
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
> Note this is the mirror image of the array accepted by the `variant` **field** of a content file: there an array _declares_ one entry per element, here it _consumes_ them in priority order.
|
|
655
|
+
|
|
656
|
+
#### Per-key map
|
|
657
|
+
|
|
658
|
+
Address each dictionary key separately. The reserved `default` entry covers every key not listed:
|
|
659
|
+
|
|
660
|
+
```tsx
|
|
661
|
+
<IntlayerProvider
|
|
662
|
+
variant={{
|
|
663
|
+
"hero-banner": "school1",
|
|
664
|
+
product: ["school1", "default"],
|
|
665
|
+
default: "base",
|
|
666
|
+
}}
|
|
667
|
+
/>
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
> On a provider a plain object is **always** read as the per-key map, never as an object variant — the two are structurally identical. To pin an object variant globally, nest it under an entry: `variant={{ default: { id: "prod_abc" } }}`.
|
|
671
|
+
|
|
672
|
+
Because the map's keys are checked against your declared dictionary keys, a typo — or an object variant written directly, such as `variant={{ id: "prod_abc" }}` — is a compile-time error.
|
|
673
|
+
|
|
501
674
|
## Loading mode
|
|
502
675
|
|
|
503
676
|
Object variants are often loaded lazily. Set `importMode` on the dictionary to control this:
|