@intlayer/docs 8.6.1 → 8.6.10
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/dist/cjs/doc.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +60 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/doc.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +60 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/doc.d.ts.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +3 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/cli/index.md +54 -42
- package/docs/ar/cli/init.md +32 -20
- package/docs/ar/cli/standalone.md +91 -0
- package/docs/ar/configuration.md +39 -7
- package/docs/ar/custom_domains.md +250 -0
- package/docs/ar/intlayer_with_tanstack+solid.md +14 -33
- package/docs/ar/intlayer_with_tanstack.md +25 -16
- package/docs/ar/intlayer_with_vanilla.md +506 -0
- package/docs/bn/cli/index.md +195 -0
- package/docs/bn/cli/init.md +96 -0
- package/docs/bn/cli/standalone.md +91 -0
- package/docs/bn/configuration.md +46 -14
- package/docs/bn/custom_domains.md +250 -0
- package/docs/bn/intlayer_with_vanilla.md +506 -0
- package/docs/cs/cli/index.md +195 -0
- package/docs/cs/cli/init.md +96 -0
- package/docs/cs/cli/standalone.md +91 -0
- package/docs/cs/configuration.md +46 -7
- package/docs/cs/custom_domains.md +250 -0
- package/docs/cs/intlayer_with_vanilla.md +506 -0
- package/docs/de/cli/index.md +53 -41
- package/docs/de/cli/standalone.md +91 -0
- package/docs/de/configuration.md +46 -7
- package/docs/de/custom_domains.md +250 -0
- package/docs/de/intlayer_with_tanstack+solid.md +14 -33
- package/docs/de/intlayer_with_tanstack.md +25 -16
- package/docs/de/intlayer_with_vanilla.md +506 -0
- package/docs/en/bundle_optimization.md +288 -23
- package/docs/en/cli/index.md +6 -1
- package/docs/en/cli/init.md +13 -1
- package/docs/en/cli/standalone.md +91 -0
- package/docs/en/configuration.md +46 -7
- package/docs/en/custom_domains.md +245 -0
- package/docs/en/intlayer_with_tanstack+solid.md +14 -33
- package/docs/en/intlayer_with_tanstack.md +25 -16
- package/docs/en/intlayer_with_vanilla.md +506 -0
- package/docs/en-GB/cli/index.md +56 -44
- package/docs/en-GB/cli/init.md +28 -21
- package/docs/en-GB/cli/standalone.md +91 -0
- package/docs/en-GB/configuration.md +53 -14
- package/docs/en-GB/custom_domains.md +250 -0
- package/docs/en-GB/intlayer_with_tanstack+solid.md +14 -33
- package/docs/en-GB/intlayer_with_tanstack.md +25 -16
- package/docs/en-GB/intlayer_with_vanilla.md +506 -0
- package/docs/es/cli/index.md +65 -53
- package/docs/es/cli/init.md +33 -21
- package/docs/es/cli/standalone.md +91 -0
- package/docs/es/configuration.md +39 -1
- package/docs/es/custom_domains.md +250 -0
- package/docs/es/intlayer_with_tanstack+solid.md +14 -33
- package/docs/es/intlayer_with_tanstack.md +25 -16
- package/docs/es/intlayer_with_vanilla.md +506 -0
- package/docs/fr/cli/index.md +43 -31
- package/docs/fr/cli/init.md +37 -25
- package/docs/fr/cli/standalone.md +91 -0
- package/docs/fr/configuration.md +46 -7
- package/docs/fr/custom_domains.md +250 -0
- package/docs/fr/intlayer_with_tanstack+solid.md +14 -33
- package/docs/fr/intlayer_with_tanstack.md +25 -16
- package/docs/fr/intlayer_with_vanilla.md +506 -0
- package/docs/hi/cli/index.md +71 -59
- package/docs/hi/cli/init.md +37 -33
- package/docs/hi/cli/standalone.md +91 -0
- package/docs/hi/configuration.md +39 -7
- package/docs/hi/custom_domains.md +250 -0
- package/docs/hi/intlayer_with_tanstack+solid.md +14 -33
- package/docs/hi/intlayer_with_tanstack.md +25 -16
- package/docs/hi/intlayer_with_vanilla.md +506 -0
- package/docs/id/cli/index.md +59 -47
- package/docs/id/cli/init.md +32 -25
- package/docs/id/cli/standalone.md +91 -0
- package/docs/id/configuration.md +46 -7
- package/docs/id/custom_domains.md +250 -0
- package/docs/id/intlayer_with_tanstack+solid.md +14 -33
- package/docs/id/intlayer_with_tanstack.md +25 -16
- package/docs/id/intlayer_with_vanilla.md +506 -0
- package/docs/it/cli/index.md +58 -41
- package/docs/it/cli/init.md +37 -38
- package/docs/it/cli/standalone.md +91 -0
- package/docs/it/configuration.md +46 -7
- package/docs/it/custom_domains.md +250 -0
- package/docs/it/intlayer_with_tanstack+solid.md +14 -33
- package/docs/it/intlayer_with_tanstack.md +25 -16
- package/docs/it/intlayer_with_vanilla.md +506 -0
- package/docs/ja/cli/index.md +59 -47
- package/docs/ja/cli/init.md +36 -24
- package/docs/ja/cli/standalone.md +91 -0
- package/docs/ja/configuration.md +46 -7
- package/docs/ja/custom_domains.md +250 -0
- package/docs/ja/intlayer_with_tanstack+solid.md +14 -33
- package/docs/ja/intlayer_with_tanstack.md +25 -16
- package/docs/ja/intlayer_with_vanilla.md +506 -0
- package/docs/ko/cli/index.md +58 -46
- package/docs/ko/cli/init.md +39 -35
- package/docs/ko/cli/standalone.md +91 -0
- package/docs/ko/configuration.md +47 -8
- package/docs/ko/custom_domains.md +250 -0
- package/docs/ko/intlayer_with_tanstack+solid.md +14 -33
- package/docs/ko/intlayer_with_tanstack.md +25 -16
- package/docs/ko/intlayer_with_vanilla.md +506 -0
- package/docs/nl/cli/index.md +195 -0
- package/docs/nl/cli/init.md +96 -0
- package/docs/nl/cli/standalone.md +91 -0
- package/docs/nl/configuration.md +46 -7
- package/docs/nl/custom_domains.md +250 -0
- package/docs/nl/intlayer_with_vanilla.md +506 -0
- package/docs/pl/cli/index.md +56 -44
- package/docs/pl/cli/init.md +36 -32
- package/docs/pl/cli/standalone.md +91 -0
- package/docs/pl/configuration.md +46 -7
- package/docs/pl/custom_domains.md +250 -0
- package/docs/pl/intlayer_with_tanstack+solid.md +14 -33
- package/docs/pl/intlayer_with_tanstack.md +25 -16
- package/docs/pl/intlayer_with_vanilla.md +506 -0
- package/docs/pt/cli/index.md +64 -52
- package/docs/pt/cli/init.md +35 -31
- package/docs/pt/cli/standalone.md +91 -0
- package/docs/pt/configuration.md +46 -7
- package/docs/pt/custom_domains.md +250 -0
- package/docs/pt/intlayer_with_tanstack+solid.md +14 -33
- package/docs/pt/intlayer_with_tanstack.md +25 -16
- package/docs/pt/intlayer_with_vanilla.md +506 -0
- package/docs/ru/cli/index.md +54 -42
- package/docs/ru/cli/init.md +31 -27
- package/docs/ru/cli/standalone.md +91 -0
- package/docs/ru/configuration.md +46 -7
- package/docs/ru/custom_domains.md +250 -0
- package/docs/ru/intlayer_with_tanstack+solid.md +14 -33
- package/docs/ru/intlayer_with_tanstack.md +25 -16
- package/docs/ru/intlayer_with_vanilla.md +506 -0
- package/docs/tr/cli/index.md +64 -52
- package/docs/tr/cli/init.md +37 -30
- package/docs/tr/cli/standalone.md +91 -0
- package/docs/tr/configuration.md +46 -7
- package/docs/tr/custom_domains.md +250 -0
- package/docs/tr/intlayer_with_tanstack+solid.md +14 -33
- package/docs/tr/intlayer_with_tanstack.md +25 -16
- package/docs/tr/intlayer_with_vanilla.md +506 -0
- package/docs/uk/cli/index.md +60 -55
- package/docs/uk/cli/init.md +32 -20
- package/docs/uk/cli/standalone.md +91 -0
- package/docs/uk/configuration.md +46 -7
- package/docs/uk/custom_domains.md +250 -0
- package/docs/uk/intlayer_with_tanstack+solid.md +14 -33
- package/docs/uk/intlayer_with_tanstack.md +25 -16
- package/docs/uk/intlayer_with_vanilla.md +506 -0
- package/docs/ur/cli/index.md +195 -0
- package/docs/ur/cli/init.md +96 -0
- package/docs/ur/cli/standalone.md +91 -0
- package/docs/ur/configuration.md +46 -7
- package/docs/ur/custom_domains.md +250 -0
- package/docs/ur/intlayer_with_vanilla.md +506 -0
- package/docs/vi/cli/index.md +72 -61
- package/docs/vi/cli/init.md +33 -21
- package/docs/vi/cli/standalone.md +91 -0
- package/docs/vi/configuration.md +46 -7
- package/docs/vi/custom_domains.md +250 -0
- package/docs/vi/intlayer_with_tanstack+solid.md +14 -33
- package/docs/vi/intlayer_with_tanstack.md +25 -16
- package/docs/vi/intlayer_with_vanilla.md +506 -0
- package/docs/zh/cli/index.md +56 -49
- package/docs/zh/cli/init.md +30 -18
- package/docs/zh/cli/standalone.md +91 -0
- package/docs/zh/configuration.md +46 -7
- package/docs/zh/custom_domains.md +250 -0
- package/docs/zh/intlayer_with_tanstack+solid.md +14 -33
- package/docs/zh/intlayer_with_tanstack.md +25 -16
- package/docs/zh/intlayer_with_vanilla.md +506 -0
- package/package.json +8 -8
- package/src/doc.ts +4 -1
- package/src/generated/docs.entry.ts +60 -0
- package/docs/ar/bundle_optimization.md +0 -185
- package/docs/de/bundle_optimization.md +0 -195
- package/docs/en-GB/bundle_optimization.md +0 -184
- package/docs/es/bundle_optimization.md +0 -194
- package/docs/fr/bundle_optimization.md +0 -184
- package/docs/hi/bundle_optimization.md +0 -185
- package/docs/id/bundle_optimization.md +0 -185
- package/docs/it/bundle_optimization.md +0 -185
- package/docs/ja/bundle_optimization.md +0 -185
- package/docs/ko/bundle_optimization.md +0 -185
- package/docs/pl/bundle_optimization.md +0 -185
- package/docs/pt/bundle_optimization.md +0 -184
- package/docs/ru/bundle_optimization.md +0 -185
- package/docs/tr/bundle_optimization.md +0 -184
- package/docs/uk/bundle_optimization.md +0 -186
- package/docs/vi/bundle_optimization.md +0 -185
- package/docs/zh/bundle_optimization.md +0 -185
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-02
|
|
3
|
+
updatedAt: 2026-04-02
|
|
4
|
+
title: نطاقات مخصصة (Custom Domains)
|
|
5
|
+
description: تعرف على كيفية تكوين توجيه اللغات القائم على النطاق في Intlayer لخدمة لغات مختلفة من أسماء مضيفين مخصصة.
|
|
6
|
+
keywords:
|
|
7
|
+
- نطاقات مخصصة
|
|
8
|
+
- توجيه النطاق
|
|
9
|
+
- التوجيه
|
|
10
|
+
- التدويل
|
|
11
|
+
- i18n
|
|
12
|
+
slugs:
|
|
13
|
+
- doc
|
|
14
|
+
- concept
|
|
15
|
+
- custom_domains
|
|
16
|
+
history:
|
|
17
|
+
- version: 8.5.0
|
|
18
|
+
date: 2026-04-02
|
|
19
|
+
changes: "إضافة توجيه اللغات القائم على النطاق عبر تكوين routing.domains."
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# نطاقات مخصصة
|
|
23
|
+
|
|
24
|
+
يدعم Intlayer توجيه اللغات القائم على النطاق، مما يسمح لك بتقديم لغات محددة من أسماء مضيفين مخصصة. على سبيل المثال، يمكن توجيه الزوار الصينيين إلى `intlayer.zh` بدلاً من `intlayer.org/zh`.
|
|
25
|
+
|
|
26
|
+
## كيف يعمل
|
|
27
|
+
|
|
28
|
+
تربط خريطة `domains` في `routing` كل لغة باسم مضيف. يستخدم Intlayer هذه الخريطة في مكانين:
|
|
29
|
+
|
|
30
|
+
1. **توليد الرابط** (`getLocalizedUrl`): عندما تكون اللغة المستهدفة موجودة على نطاق _مختلف_ عن الصفحة الحالية، يتم إرجاع رابط مطلق (مثل `https://intlayer.zh/about`). عندما يتطابق كلا النطاقين، يتم إرجاع رابط نسبي (مثل `/fr/about`).
|
|
31
|
+
2. **بروكسي الخادم** (Next.js و Vite): تتم إعادة توجيه الطلبات الواردة أو إعادة كتابتها بناءً على النطاق الذي تصل إليه.
|
|
32
|
+
|
|
33
|
+
### النطاقات الحصرية مقابل المشتركة
|
|
34
|
+
|
|
35
|
+
الفرق الرئيسي هو **الحصرية**:
|
|
36
|
+
|
|
37
|
+
- **نطاق حصري** — لغة واحدة فقط ترتبط باسم المضيف هذا (مثل `zh → intlayer.zh`). النطاق نفسه يحدد اللغة، لذا لا يتم إضافة بادئة لغة إلى المسار. يخدم `https://intlayer.zh/about` المحتوى الصيني.
|
|
38
|
+
- **نطاق مشترك** — ترتبط لغات متعددة بنفس اسم المضيف (مثل `en` و `fr` كلاهما يرتبطان بـ `intlayer.org`). يتم تطبيق التوجيه التقليدي القائم على البادئة. يخدم `intlayer.org/fr/about` المحتوى الفرنسي.
|
|
39
|
+
|
|
40
|
+
## التكوين
|
|
41
|
+
|
|
42
|
+
```typescript fileName="intlayer.config.ts"
|
|
43
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
44
|
+
|
|
45
|
+
const config: IntlayerConfig = {
|
|
46
|
+
internationalization: {
|
|
47
|
+
locales: [
|
|
48
|
+
Locales.ENGLISH,
|
|
49
|
+
Locales.FRENCH,
|
|
50
|
+
Locales.SPANISH,
|
|
51
|
+
Locales.CHINESE,
|
|
52
|
+
],
|
|
53
|
+
defaultLocale: Locales.ENGLISH,
|
|
54
|
+
},
|
|
55
|
+
routing: {
|
|
56
|
+
mode: "prefix-no-default",
|
|
57
|
+
domains: {
|
|
58
|
+
// نطاق مشترك — en و fr يستخدمان توجيه البادئة على intlayer.org
|
|
59
|
+
en: "intlayer.org",
|
|
60
|
+
// نطاق حصري — zh لها اسم مضيف خاص بها، لا حاجة لبادئة /zh/
|
|
61
|
+
zh: "intlayer.zh",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default config;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
تستمر اللغات غير المدرجة في `domains` في استخدام توجيه البادئة القياسي دون أي تجاوز للنطاق.
|
|
70
|
+
|
|
71
|
+
## توليد الرابط (URL Generation)
|
|
72
|
+
|
|
73
|
+
يقوم `getLocalizedUrl` تلقائيًا بإنتاج نوع الرابط الصحيح بناءً على سياق الاستدعاء.
|
|
74
|
+
|
|
75
|
+
### لغة في نفس النطاق (رابط نسبي)
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// الصفحة الحالية: intlayer.org/about
|
|
79
|
+
getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.org" });
|
|
80
|
+
// ← "/fr/about"
|
|
81
|
+
|
|
82
|
+
getLocalizedUrl("/about", "en", { currentDomain: "intlayer.org" });
|
|
83
|
+
// ← "/about" (اللغة الافتراضية، لا توجد بادئة)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### لغة في نطاق مختلف (رابط مطلق)
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// الصفحة الحالية: intlayer.org/about
|
|
90
|
+
getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.org" });
|
|
91
|
+
// ← "https://intlayer.zh/about" (نطاق حصري، لا توجد بادئة /zh/)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### الخدمة من النطاق الخاص باللغة
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// الصفحة الحالية: intlayer.zh/about
|
|
98
|
+
getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.zh" });
|
|
99
|
+
// ← "/about" (بالفعل على النطاق الصحيح — رابط نسبي)
|
|
100
|
+
|
|
101
|
+
getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.zh" });
|
|
102
|
+
// ← "https://intlayer.org/fr/about" (رابط عبر النطاقات يعود إلى intlayer.org)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### الكشف التلقائي عن النطاق الحالي
|
|
106
|
+
|
|
107
|
+
خيار `currentDomain` اختياري. عند حذفه، يقوم `getLocalizedUrl` بحله بهذا الترتيب:
|
|
108
|
+
|
|
109
|
+
1. اسم المضيف لرابط إدخال مطلق (مثلاً `https://intlayer.org/about` ← `intlayer.org`).
|
|
110
|
+
2. `window.location.hostname` في بيئات المتصفح.
|
|
111
|
+
3. إذا لم يتوفر أي منهما (SSR بدون خيار صريح)، يتم إرجاع رابط نسبي للغات الموجودة على نفس النطاق ولا يتم إنتاج رابط مطلق — وهذا هو التراجع الآمن.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// المتصفح — window.location.hostname === 'intlayer.org'
|
|
115
|
+
getLocalizedUrl("/about", "zh");
|
|
116
|
+
// ← "https://intlayer.zh/about" (تم اكتشافه تلقائيًا من النافذة)
|
|
117
|
+
|
|
118
|
+
// من رابط مطلق — تم اكتشاف النطاق تلقائيًا
|
|
119
|
+
getLocalizedUrl("https://intlayer.org/about", "zh");
|
|
120
|
+
// ← "https://intlayer.zh/about"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `getMultilingualUrls` مع النطاقات
|
|
124
|
+
|
|
125
|
+
يستدعي `getMultilingualUrls` الدالة `getLocalizedUrl` لكل لغة، لذا فهو ينتج مزيجًا من الروابط النسبية والمطلقة اعتمادًا على نطاق المستدعي:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
// currentDomain: 'intlayer.org'
|
|
129
|
+
getMultilingualUrls("/about", { currentDomain: "intlayer.org" });
|
|
130
|
+
// {
|
|
131
|
+
// en: "/about",
|
|
132
|
+
// fr: "/fr/about",
|
|
133
|
+
// es: "/es/about",
|
|
134
|
+
// zh: "https://intlayer.zh/about",
|
|
135
|
+
// }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
هذه الروابط المطلقة جاهزة للاستخدام في وسوم `<link rel="alternate" hreflang="...">` لـ SEO.
|
|
139
|
+
|
|
140
|
+
## سلوك البروكسي (Proxy Behaviour)
|
|
141
|
+
|
|
142
|
+
### Next.js
|
|
143
|
+
|
|
144
|
+
يتعامل وسيط `intlayerProxy` مع توجيه النطاق تلقائيًا. أضفه إلى ملف `middleware.ts`:
|
|
145
|
+
|
|
146
|
+
```typescript fileName="middleware.ts"
|
|
147
|
+
export { intlayerProxy as default } from "next-intlayer/proxy";
|
|
148
|
+
|
|
149
|
+
export const config = {
|
|
150
|
+
matcher: "/((?!api|static|assets|robots|sitemap|.*\\..*|_next).*)",
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**إعادة التوجيه (Redirect)** — يصل الطلب إلى النطاق الخطأ لبادئة لغة معينة:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
GET intlayer.org/zh/about
|
|
158
|
+
← 301 https://intlayer.zh/about
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**إعادة الكتابة (Rewrite)** — يصل الطلب إلى النطاق الحصري للغة بدون بادئة:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
GET intlayer.zh/about
|
|
165
|
+
← إعادة الكتابة إلى /zh/about (توجيه Next.js الداخلي فقط، يظل الرابط نظيفًا)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Vite
|
|
169
|
+
|
|
170
|
+
يطبق ملحق `intlayerProxy` الخاص بـ Vite نفس المنطق أثناء التطوير:
|
|
171
|
+
|
|
172
|
+
```typescript fileName="vite.config.ts"
|
|
173
|
+
import { defineConfig } from "vite";
|
|
174
|
+
import { intlayerProxy } from "vite-intlayer";
|
|
175
|
+
|
|
176
|
+
export default defineConfig({
|
|
177
|
+
plugins: [intlayerProxy()],
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> **ملاحظة**: في التطوير المحلي، تكون عادةً على `localhost` ن لذا ستشير عمليات إعادة التوجيه عبر النطاقات إلى النطاقات المباشرة بدلاً من منفذ محلي آخر. استخدم تجاوز ملف hosts (مثلاً `127.0.0.1 intlayer.zh`) أو بروكسي عكسي إذا كنت بحاجة إلى اختبار توجيه النطاقات المتعددة محليًا.
|
|
182
|
+
|
|
183
|
+
## مبدل اللغة (Locale Switcher)
|
|
184
|
+
|
|
185
|
+
يتعامل خطاف `useLocale` من `next-intlayer` مع التنقل المدرك للنطاق تلقائيًا. عندما ينتقل المستخدم إلى لغة على نطاق مختلف، يقوم الخطاف بتنقل كامل للصفحة (`window.location.href`) بدلاً من دفع موجه جانب العميل، لأن موجه Next.js لا يمكنه تجاوز الأصول (origins).
|
|
186
|
+
|
|
187
|
+
```tsx fileName="components/LocaleSwitcher.tsx"
|
|
188
|
+
"use client";
|
|
189
|
+
|
|
190
|
+
import { useLocale } from "next-intlayer";
|
|
191
|
+
|
|
192
|
+
export const LocaleSwitcher = () => {
|
|
193
|
+
const { availableLocales, locale, setLocale } = useLocale();
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<ul>
|
|
197
|
+
{availableLocales.map((localeEl) => (
|
|
198
|
+
<li key={localeEl}>
|
|
199
|
+
<button
|
|
200
|
+
onClick={() => setLocale(localeEl)}
|
|
201
|
+
aria-current={localeEl === locale ? "true" : undefined}
|
|
202
|
+
>
|
|
203
|
+
{l.toUpperCase()}
|
|
204
|
+
</button>
|
|
205
|
+
</li>
|
|
206
|
+
))}
|
|
207
|
+
</ul>
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
لا يلزم تكوين إضافي — يكتشف `useLocale` داخليًا `window.location.hostname` ويقرر بين `router.replace` (نفس النطاق) و `window.location.href` (عبر النطاقات).
|
|
213
|
+
|
|
214
|
+
## SEO: روابط `hreflang` البديلة
|
|
215
|
+
|
|
216
|
+
يشيع استخدام التوجيه القائم على النطاق مع `hreflang` لإخبار محركات البحث بالرابط الذي يجب أرشفته لكل لغة. استخدم `getMultilingualUrls` لإنشاء المجموعة الكاملة من الروابط البديلة:
|
|
217
|
+
|
|
218
|
+
```tsx fileName="app/[locale]/layout.tsx"
|
|
219
|
+
import { getMultilingualUrls } from "intlayer";
|
|
220
|
+
import type { Metadata } from "next";
|
|
221
|
+
|
|
222
|
+
export const generateMetadata = (): Metadata => {
|
|
223
|
+
const alternates = getMultilingualUrls("/", {
|
|
224
|
+
currentDomain: process.env.NEXT_PUBLIC_DOMAIN, // مثلًا "intlayer.org"
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
alternates: {
|
|
229
|
+
languages: alternates,
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
ينتج عن هذا:
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<link rel="alternate" hreflang="en" href="https://intlayer.org/" />
|
|
239
|
+
<link rel="alternate" hreflang="fr" href="https://intlayer.org/fr/" />
|
|
240
|
+
<link rel="alternate" hreflang="es" href="https://intlayer.org/es/" />
|
|
241
|
+
<link rel="alternate" hreflang="zh" href="https://intlayer.zh/" />
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## الأدوات الأساسية (Core Utilities)
|
|
245
|
+
|
|
246
|
+
| الأداة | الوصف |
|
|
247
|
+
| ------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
248
|
+
| `getLocalizedUrl(url, locale, { currentDomain })` | يرجع رابطًا نسبيًا أو مطلقًا اعتمادًا على ما إذا كانت اللغة المستهدفة في النطاق الحالي. |
|
|
249
|
+
| `getMultilingualUrls(url, { currentDomain })` | يرجع خريطة روابط محلية مفهرسة باللغة، تجمع بين الروابط النسبية والمطلقة حسب الحاجة. |
|
|
250
|
+
| `getPrefix(locale, { domains })` | يرجع بادئة فارغة للغات ذات النطاق الحصري، وبادئة عادية في حالات أخرى. |
|
|
@@ -16,6 +16,7 @@ slugs:
|
|
|
16
16
|
- doc
|
|
17
17
|
- environment
|
|
18
18
|
- tanstack-start
|
|
19
|
+
- solid
|
|
19
20
|
applicationTemplate: https://github.com/aymericzip/intlayer-tanstack-start-solid-template
|
|
20
21
|
youtubeVideo: https://www.youtube.com/watch?v=_XTdKVWaeqg
|
|
21
22
|
history:
|
|
@@ -162,59 +163,45 @@ export default defineConfig({
|
|
|
162
163
|
|
|
163
164
|
### الخطوة 5: إنشاء التخطيط الجذري (Root Layout)
|
|
164
165
|
|
|
165
|
-
قم بتكوين التخطيط الجذري الخاص بك لدعم التدويل باستخدام `
|
|
166
|
+
قم بتكوين التخطيط الجذري الخاص بك لدعم التدويل باستخدام `useParams` لاكتشاف اللغة الحالية وتعيين سمات `lang` و `dir` على وسم `html`.
|
|
166
167
|
|
|
167
168
|
```tsx fileName="src/routes/__root.tsx"
|
|
168
169
|
import {
|
|
169
170
|
HeadContent,
|
|
170
|
-
Outlet,
|
|
171
171
|
Scripts,
|
|
172
172
|
createRootRouteWithContext,
|
|
173
|
-
useMatches,
|
|
174
173
|
} from "@tanstack/solid-router";
|
|
175
|
-
import { TanStackRouterDevtools } from "@tanstack/solid-router-devtools";
|
|
176
174
|
import { HydrationScript } from "solid-js/web";
|
|
177
|
-
import { Suspense } from "solid-js";
|
|
175
|
+
import { Suspense, type ParentComponent } from "solid-js";
|
|
178
176
|
import { IntlayerProvider } from "solid-intlayer";
|
|
179
|
-
import { defaultLocale, getHTMLTextDir
|
|
177
|
+
import { defaultLocale, getHTMLTextDir } from "intlayer";
|
|
178
|
+
import { Route as LocaleRoute } from "./{-$locale}/route";
|
|
180
179
|
|
|
181
180
|
export const Route = createRootRouteWithContext()({
|
|
182
181
|
shellComponent: RootComponent,
|
|
183
182
|
});
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
function RootComponent() {
|
|
190
|
-
const matches = useMatches();
|
|
191
|
-
|
|
192
|
-
// محاولة العثور على اللغة في معلمات أي مطابقة نشطة
|
|
193
|
-
// يفترض هذا أنك تستخدم الجزء الديناميكي "/{-$locale}" في شجرة المسارات الخاصة بك
|
|
194
|
-
const locale =
|
|
195
|
-
(
|
|
196
|
-
matches().find((match) => match.routeId === "/{-$locale}/")
|
|
197
|
-
?.params as Params
|
|
198
|
-
)?.locale ?? defaultLocale;
|
|
184
|
+
const RootComponent: ParentComponent = (props) => {
|
|
185
|
+
const params = LocaleRoute.useParams();
|
|
186
|
+
const locale = params()?.locale ?? defaultLocale;
|
|
199
187
|
|
|
200
188
|
return (
|
|
201
189
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
202
190
|
<head>
|
|
203
191
|
<HydrationScript />
|
|
192
|
+
<HeadContent />
|
|
204
193
|
</head>
|
|
205
194
|
<body>
|
|
206
|
-
<HeadContent />
|
|
207
195
|
<IntlayerProvider locale={locale}>
|
|
208
196
|
<Suspense>
|
|
209
|
-
|
|
210
|
-
<TanStackRouterDevtools />
|
|
197
|
+
{props.children}
|
|
211
198
|
</Suspense>
|
|
212
199
|
</IntlayerProvider>
|
|
213
200
|
<Scripts />
|
|
214
201
|
</body>
|
|
215
202
|
</html>
|
|
216
203
|
);
|
|
217
|
-
}
|
|
204
|
+
};
|
|
218
205
|
```
|
|
219
206
|
|
|
220
207
|
### الخطوة 6: إنشاء تخطيط اللغة (اختياري)
|
|
@@ -458,18 +445,12 @@ export default LocaleSwitcher;
|
|
|
458
445
|
|
|
459
446
|
### الخطوة 11: إدارة سمات HTML
|
|
460
447
|
|
|
461
|
-
كما رأيت في الخطوة 5، يمكنك إدارة سمات `lang` و `dir` لوسم `html` باستخدام `
|
|
448
|
+
كما رأيت في الخطوة 5، يمكنك إدارة سمات `lang` و `dir` لوسم `html` باستخدام `useParams` في المكون الجذري الخاص بك. يضمن ذلك تعيين السمات الصحيحة على كل من الخادم والعميل.
|
|
462
449
|
|
|
463
450
|
```tsx fileName="src/routes/__root.tsx"
|
|
464
451
|
const RootComponent: ParentComponent = (props) => {
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
// محاولة العثور على اللغة في معلمات أي مطابقة نشطة
|
|
468
|
-
const locale =
|
|
469
|
-
(
|
|
470
|
-
matches().find((match) => match.routeId === "/{-$locale}/")
|
|
471
|
-
?.params as Params
|
|
472
|
-
)?.locale ?? defaultLocale;
|
|
452
|
+
const params = LocaleRoute.useParams();
|
|
453
|
+
const locale = params()?.locale ?? defaultLocale;
|
|
473
454
|
|
|
474
455
|
return (
|
|
475
456
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
@@ -182,31 +182,41 @@ export default config;
|
|
|
182
182
|
|
|
183
183
|
### الخطوة 5: إنشاء التخطيط الجذري
|
|
184
184
|
|
|
185
|
-
قم بتكوين التخطيط الجذري الخاص بك لدعم التدويل باستخدام `
|
|
185
|
+
قم بتكوين التخطيط الجذري الخاص بك لدعم التدويل باستخدام `useParams` للكشف عن اللغة الحالية وتعيين سمات `lang` و `dir` على علامة `html`.
|
|
186
186
|
|
|
187
187
|
```tsx fileName="src/routes/__root.tsx"
|
|
188
188
|
import {
|
|
189
189
|
createRootRouteWithContext,
|
|
190
190
|
HeadContent,
|
|
191
|
-
Outlet,
|
|
192
191
|
Scripts,
|
|
193
|
-
useMatches,
|
|
194
192
|
} from "@tanstack/react-router";
|
|
195
193
|
import { defaultLocale, getHTMLTextDir } from "intlayer";
|
|
196
194
|
import { type ReactNode } from "react";
|
|
197
195
|
import { IntlayerProvider } from "react-intlayer";
|
|
196
|
+
import { Route as LocaleRoute } from "./{-$locale}/route";
|
|
198
197
|
|
|
199
198
|
export const Route = createRootRouteWithContext<{}>()({
|
|
199
|
+
head: () => ({
|
|
200
|
+
meta: [
|
|
201
|
+
{
|
|
202
|
+
charSet: "utf-8",
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
content: "width=device-width, initial-scale=1",
|
|
206
|
+
name: "viewport",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
title: "TanStack Start Starter",
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
}),
|
|
213
|
+
|
|
200
214
|
shellComponent: RootDocument,
|
|
201
215
|
});
|
|
202
216
|
|
|
203
217
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
// حاول العثور على اللغة في معلمات أي مطابقة نشطة
|
|
207
|
-
// يفترض هذا أنك تستخدم الجزء الديناميكي "/{-$locale}" في شجرة المسارات الخاصة بك
|
|
208
|
-
const localeRoute = matches.find((match) => match.routeId === "/{-$locale}");
|
|
209
|
-
const locale = localeRoute?.params?.locale ?? defaultLocale;
|
|
218
|
+
const params = LocaleRoute.useParams();
|
|
219
|
+
const locale = params?.locale ?? defaultLocale;
|
|
210
220
|
|
|
211
221
|
return (
|
|
212
222
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
@@ -214,7 +224,9 @@ function RootDocument({ children }: { children: ReactNode }) {
|
|
|
214
224
|
<HeadContent />
|
|
215
225
|
</head>
|
|
216
226
|
<body>
|
|
217
|
-
<IntlayerProvider locale={locale}>
|
|
227
|
+
<IntlayerProvider locale={locale}>
|
|
228
|
+
{children}
|
|
229
|
+
</IntlayerProvider>
|
|
218
230
|
<Scripts />
|
|
219
231
|
</body>
|
|
220
232
|
</html>
|
|
@@ -557,15 +569,12 @@ export const LocaleSwitcher: FC = () => {
|
|
|
557
569
|
|
|
558
570
|
### الخطوة 11: إدارة سمات HTML
|
|
559
571
|
|
|
560
|
-
كما رأينا في الخطوة 5، يمكنك إدارة سمات `lang` و `dir` لعلامة `html` باستخدام `
|
|
572
|
+
كما رأينا في الخطوة 5، يمكنك إدارة سمات `lang` و `dir` لعلامة `html` باستخدام `useParams` في مكونك الجذري. يضمن هذا تعيين السمات الصحيحة على الخادم والعميل.
|
|
561
573
|
|
|
562
574
|
```tsx fileName="src/routes/__root.tsx"
|
|
563
575
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
// حاول العثور على اللغة في معلمات أي مطابقة نشطة
|
|
567
|
-
const localeRoute = matches.find((match) => match.routeId === "/{-$locale}");
|
|
568
|
-
const locale = localeRoute?.params?.locale ?? defaultLocale;
|
|
576
|
+
const params = LocaleRoute.useParams();
|
|
577
|
+
const locale = params?.locale ?? defaultLocale;
|
|
569
578
|
|
|
570
579
|
return (
|
|
571
580
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|