@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
|
+
## Переключатель локалей
|
|
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`, чтобы сообщить поисковым системам, какой 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 по локалям, смешивая относительные и абсолютные URL по мере необходимости. |
|
|
250
|
+
| `getPrefix(locale, { domains })` | Возвращает пустой префикс для локалей с эксклюзивным доменом, в противном случае — обычный префикс. |
|
|
@@ -17,6 +17,7 @@ slugs:
|
|
|
17
17
|
- doc
|
|
18
18
|
- environment
|
|
19
19
|
- tanstack-start
|
|
20
|
+
- solid
|
|
20
21
|
applicationTemplate: https://github.com/aymericzip/intlayer-tanstack-start-solid-template
|
|
21
22
|
youtubeVideo: https://www.youtube.com/watch?v=_XTdKVWaeqg
|
|
22
23
|
history:
|
|
@@ -163,59 +164,45 @@ export default defineConfig({
|
|
|
163
164
|
|
|
164
165
|
### Шаг 5: Создание корневого макета (Root Layout)
|
|
165
166
|
|
|
166
|
-
Настройте ваш корневой макет для поддержки интернационализации, используя `
|
|
167
|
+
Настройте ваш корневой макет для поддержки интернационализации, используя `useParams` для определения текущей локали и устанавливая атрибуты `lang` и `dir` для тега `html`.
|
|
167
168
|
|
|
168
169
|
```tsx fileName="src/routes/__root.tsx"
|
|
169
170
|
import {
|
|
170
171
|
HeadContent,
|
|
171
|
-
Outlet,
|
|
172
172
|
Scripts,
|
|
173
173
|
createRootRouteWithContext,
|
|
174
|
-
useMatches,
|
|
175
174
|
} from "@tanstack/solid-router";
|
|
176
|
-
import { TanStackRouterDevtools } from "@tanstack/solid-router-devtools";
|
|
177
175
|
import { HydrationScript } from "solid-js/web";
|
|
178
|
-
import { Suspense } from "solid-js";
|
|
176
|
+
import { Suspense, type ParentComponent } from "solid-js";
|
|
179
177
|
import { IntlayerProvider } from "solid-intlayer";
|
|
180
|
-
import { defaultLocale, getHTMLTextDir
|
|
178
|
+
import { defaultLocale, getHTMLTextDir } from "intlayer";
|
|
179
|
+
import { Route as LocaleRoute } from "./{-$locale}/route";
|
|
181
180
|
|
|
182
181
|
export const Route = createRootRouteWithContext()({
|
|
183
182
|
shellComponent: RootComponent,
|
|
184
183
|
});
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
function RootComponent() {
|
|
191
|
-
const matches = useMatches();
|
|
192
|
-
|
|
193
|
-
// Попытка найти локаль в параметрах любого активного совпадения
|
|
194
|
-
// Это предполагает, что вы используете динамический сегмент "/{-$locale}" в дереве маршрутов
|
|
195
|
-
const locale =
|
|
196
|
-
(
|
|
197
|
-
matches().find((match) => match.routeId === "/{-$locale}/")
|
|
198
|
-
?.params as Params
|
|
199
|
-
)?.locale ?? defaultLocale;
|
|
185
|
+
const RootComponent: ParentComponent = (props) => {
|
|
186
|
+
const params = LocaleRoute.useParams();
|
|
187
|
+
const locale = params()?.locale ?? defaultLocale;
|
|
200
188
|
|
|
201
189
|
return (
|
|
202
190
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
203
191
|
<head>
|
|
204
192
|
<HydrationScript />
|
|
193
|
+
<HeadContent />
|
|
205
194
|
</head>
|
|
206
195
|
<body>
|
|
207
|
-
<HeadContent />
|
|
208
196
|
<IntlayerProvider locale={locale}>
|
|
209
197
|
<Suspense>
|
|
210
|
-
|
|
211
|
-
<TanStackRouterDevtools />
|
|
198
|
+
{props.children}
|
|
212
199
|
</Suspense>
|
|
213
200
|
</IntlayerProvider>
|
|
214
201
|
<Scripts />
|
|
215
202
|
</body>
|
|
216
203
|
</html>
|
|
217
204
|
);
|
|
218
|
-
}
|
|
205
|
+
};
|
|
219
206
|
```
|
|
220
207
|
|
|
221
208
|
### Шаг 6: Создание макета локали (необязательно)
|
|
@@ -459,18 +446,12 @@ export default LocaleSwitcher;
|
|
|
459
446
|
|
|
460
447
|
### Шаг 11: Управление HTML-атрибутами
|
|
461
448
|
|
|
462
|
-
Как показано на шаге 5, вы можете управлять атрибутами `lang` и `dir` тега `html`, используя `
|
|
449
|
+
Как показано на шаге 5, вы можете управлять атрибутами `lang` и `dir` тега `html`, используя `useParams` в вашем корневом компоненте. Это гарантирует правильную установку атрибутов как на сервере, так и на клиенте.
|
|
463
450
|
|
|
464
451
|
```tsx fileName="src/routes/__root.tsx"
|
|
465
452
|
const RootComponent: ParentComponent = (props) => {
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
// Попытка найти локаль в параметрах любого активного совпадения
|
|
469
|
-
const locale =
|
|
470
|
-
(
|
|
471
|
-
matches().find((match) => match.routeId === "/{-$locale}/")
|
|
472
|
-
?.params as Params
|
|
473
|
-
)?.locale ?? defaultLocale;
|
|
453
|
+
const params = LocaleRoute.useParams();
|
|
454
|
+
const locale = params()?.locale ?? defaultLocale;
|
|
474
455
|
|
|
475
456
|
return (
|
|
476
457
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
@@ -879,9 +860,7 @@ export default defineConfig({
|
|
|
879
860
|
import { createFileRoute } from "@tanstack/solid-router";
|
|
880
861
|
import { generateSitemap } from "intlayer";
|
|
881
862
|
|
|
882
|
-
const SITE_URL =
|
|
883
|
-
import.meta.env.VITE_SITE_URL ?? "http://localhost:3000"
|
|
884
|
-
).replace(/\/$/, "");
|
|
863
|
+
const SITE_URL = "http://localhost:3000";
|
|
885
864
|
|
|
886
865
|
export const Route = createFileRoute("/sitemap.xml")({
|
|
887
866
|
server: {
|
|
@@ -183,31 +183,41 @@ export default config;
|
|
|
183
183
|
|
|
184
184
|
### Шаг 5: Создайте корневой макет
|
|
185
185
|
|
|
186
|
-
Настройте корневой макет для поддержки интернационализации, используя `
|
|
186
|
+
Настройте корневой макет для поддержки интернационализации, используя `useParams` для определения текущей локали и установив атрибуты `lang` и `dir` в теге `html`.
|
|
187
187
|
|
|
188
188
|
```tsx fileName="src/routes/__root.tsx"
|
|
189
189
|
import {
|
|
190
190
|
createRootRouteWithContext,
|
|
191
191
|
HeadContent,
|
|
192
|
-
Outlet,
|
|
193
192
|
Scripts,
|
|
194
|
-
useMatches,
|
|
195
193
|
} from "@tanstack/react-router";
|
|
196
194
|
import { defaultLocale, getHTMLTextDir } from "intlayer";
|
|
197
195
|
import { type ReactNode } from "react";
|
|
198
196
|
import { IntlayerProvider } from "react-intlayer";
|
|
197
|
+
import { Route as LocaleRoute } from "./{-$locale}/route";
|
|
199
198
|
|
|
200
199
|
export const Route = createRootRouteWithContext<{}>()({
|
|
200
|
+
head: () => ({
|
|
201
|
+
meta: [
|
|
202
|
+
{
|
|
203
|
+
charSet: "utf-8",
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
content: "width=device-width, initial-scale=1",
|
|
207
|
+
name: "viewport",
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
title: "TanStack Start Starter",
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
}),
|
|
214
|
+
|
|
201
215
|
shellComponent: RootDocument,
|
|
202
216
|
});
|
|
203
217
|
|
|
204
218
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
// Попробуйте найти локаль в параметрах любого активного совпадения
|
|
208
|
-
// Это предполагает использование динамического сегмента "/{-$locale}" в дереве маршрутов
|
|
209
|
-
const localeRoute = matches.find((match) => match.routeId === "/{-$locale}");
|
|
210
|
-
const locale = localeRoute?.params?.locale ?? defaultLocale;
|
|
219
|
+
const params = LocaleRoute.useParams();
|
|
220
|
+
const locale = params?.locale ?? defaultLocale;
|
|
211
221
|
|
|
212
222
|
return (
|
|
213
223
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
@@ -215,7 +225,9 @@ function RootDocument({ children }: { children: ReactNode }) {
|
|
|
215
225
|
<HeadContent />
|
|
216
226
|
</head>
|
|
217
227
|
<body>
|
|
218
|
-
<IntlayerProvider locale={locale}>
|
|
228
|
+
<IntlayerProvider locale={locale}>
|
|
229
|
+
{children}
|
|
230
|
+
</IntlayerProvider>
|
|
219
231
|
<Scripts />
|
|
220
232
|
</body>
|
|
221
233
|
</html>
|
|
@@ -558,15 +570,12 @@ export const LocaleSwitcher: FC = () => {
|
|
|
558
570
|
|
|
559
571
|
### Шаг 11: Управление атрибутами HTML
|
|
560
572
|
|
|
561
|
-
Как показано на шаге 5, вы можете управлять атрибутами `lang` и `dir` тега `html`, используя `
|
|
573
|
+
Как показано на шаге 5, вы можете управлять атрибутами `lang` и `dir` тега `html`, используя `useParams` в вашем корневом компоненте. Это гарантирует правильную установку атрибутов как на сервере, так и на клиенте.
|
|
562
574
|
|
|
563
575
|
```tsx fileName="src/routes/__root.tsx"
|
|
564
576
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
// Попробуйте найти локаль в параметрах любого активного совпадения
|
|
568
|
-
const localeRoute = matches.find((match) => match.routeId === "/{-$locale}");
|
|
569
|
-
const locale = localeRoute?.params?.locale ?? defaultLocale;
|
|
577
|
+
const params = LocaleRoute.useParams();
|
|
578
|
+
const locale = params?.locale ?? defaultLocale;
|
|
570
579
|
|
|
571
580
|
return (
|
|
572
581
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|