@intlayer/docs 8.6.0 → 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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 +15 -36
- 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: Власні домени
|
|
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. **Генерація URL** (`getLocalizedUrl`): коли цільова локаль знаходиться на _іншому_ домені, ніж поточна сторінка, повертається абсолютний URL (наприклад, `https://intlayer.zh/about`). Коли обидва домени збігаються, повертається відносний URL (наприклад, `/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
|
|
72
|
+
|
|
73
|
+
`getLocalizedUrl` автоматично створює правильний тип URL на основі контексту виклику.
|
|
74
|
+
|
|
75
|
+
### Локаль на тому самому домені (відносний URL)
|
|
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
|
+
### Міждоменна локаль (абсолютний URL)
|
|
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" (вже на правильному домені — відносний URL)
|
|
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. Ім'я хоста з абсолютного вхідного URL (наприклад, `https://intlayer.org/about` → `intlayer.org`).
|
|
110
|
+
2. `window.location.hostname` у браузерному середовищі.
|
|
111
|
+
3. Якщо жоден з варіантів не доступний (SSR без явно вказаного параметра), повертається відносний URL для локалей на тому самому домені, а абсолютний URL не створюється — це безпечний резервний варіант.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// Браузер — window.location.hostname === 'intlayer.org'
|
|
115
|
+
getLocalizedUrl("/about", "zh");
|
|
116
|
+
// → "https://intlayer.zh/about" (автоматично визначено з window)
|
|
117
|
+
|
|
118
|
+
// З абсолютного URL — домен визначено автоматично
|
|
119
|
+
getLocalizedUrl("https://intlayer.org/about", "zh");
|
|
120
|
+
// → "https://intlayer.zh/about"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `getMultilingualUrls` з доменами
|
|
124
|
+
|
|
125
|
+
`getMultilingualUrls` викликає `getLocalizedUrl` для кожної локалі, тому він створює суміш відносних та абсолютних URL залежно від домену зухника:
|
|
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
|
+
Ці абсолютні URL готові до використання в тегах `<link rel="alternate" hreflang="...">` для SEO.
|
|
139
|
+
|
|
140
|
+
## Поведінка проксі
|
|
141
|
+
|
|
142
|
+
### Next.js
|
|
143
|
+
|
|
144
|
+
Посередник (middleware) `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, URL залишається чистим)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Vite
|
|
169
|
+
|
|
170
|
+
Плагін Vite `intlayerProxy` застосовує ту саму логіку під час розробки:
|
|
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
|
+
{localeEl.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`, щоб повідомити пошуковим системам, який URL індексувати для кожної мови. Використовуйте `getMultilingualUrls` для генерації повного набору альтернативних URL:
|
|
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
|
+
## Основні утиліти
|
|
245
|
+
|
|
246
|
+
| Утиліта | Опис |
|
|
247
|
+
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
248
|
+
| `getLocalizedUrl(url, locale, { currentDomain })` | Повертає відносний або абсолютний URL залежно від того, чи знаходиться цільова локаль на поточному домені. |
|
|
249
|
+
| `getMultilingualUrls(url, { currentDomain })` | Повертає карту локалізованих URL за ключем локалі, змішуючи відносні та абсолютні за потреби. |
|
|
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: Створіть кореневий Layout
|
|
184
184
|
|
|
185
|
-
Налаштуйте кореневий layout для підтримки інтернаціоналізації, використовуючи `
|
|
185
|
+
Налаштуйте кореневий layout для підтримки інтернаціоналізації, використовуючи `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
|
-
// Спробуйте знайти locale в params будь-якого активного match
|
|
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
|
-
// Спробуйте знайти locale в params будь-якого активного match
|
|
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}>
|