@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,245 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-03
|
|
3
|
+
updatedAt: 2026-04-03
|
|
4
|
+
title: Custom Domains
|
|
5
|
+
description: Configure domain-based locale routing in Intlayer to serve different locales from dedicated hostnames.
|
|
6
|
+
keywords:
|
|
7
|
+
- Custom Domains
|
|
8
|
+
- Domain Routing
|
|
9
|
+
- Routing
|
|
10
|
+
- Internationalization
|
|
11
|
+
- i18n
|
|
12
|
+
slugs:
|
|
13
|
+
- doc
|
|
14
|
+
- concept
|
|
15
|
+
- custom_domains
|
|
16
|
+
history:
|
|
17
|
+
- version: 8.7.0
|
|
18
|
+
date: 2026-04-03
|
|
19
|
+
changes: "Add domain-based locale routing via routing.domains configuration."
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Custom Domains
|
|
23
|
+
|
|
24
|
+
Intlayer supports domain-based locale routing, allowing you to serve specific locales from dedicated hostnames. For example, Chinese visitors can be directed to `intlayer.zh` instead of `intlayer.org/zh`.
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
The `domains` map in `routing` associates each locale with a hostname. Intlayer uses this map in two places:
|
|
29
|
+
|
|
30
|
+
1. **URL generation** (`getLocalizedUrl`): when the target locale lives on a _different_ domain than the current page, an absolute URL is returned (e.g. `https://intlayer.zh/about`). When both domains match, a relative URL is returned (e.g. `/fr/about`).
|
|
31
|
+
2. **Server proxy** (Next.js & Vite): incoming requests are redirected or rewritten based on the domain they arrive on.
|
|
32
|
+
|
|
33
|
+
### Exclusive vs. shared domains
|
|
34
|
+
|
|
35
|
+
The key distinction is **exclusivity**:
|
|
36
|
+
|
|
37
|
+
- **Exclusive domain** — only one locale maps to that hostname (e.g. `zh → intlayer.zh`). The domain itself identifies the locale, so no locale prefix is added to the path. `https://intlayer.zh/about` serves Chinese content.
|
|
38
|
+
- **Shared domain** — multiple locales map to the same hostname (e.g. `en` and `fr` both map to `intlayer.org`). Normal prefix-based routing applies. `intlayer.org/fr/about` serves French content.
|
|
39
|
+
|
|
40
|
+
## Configuration
|
|
41
|
+
|
|
42
|
+
```typescript fileName="intlayer.config.ts"
|
|
43
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
44
|
+
|
|
45
|
+
const config: IntlayerConfig = {
|
|
46
|
+
internationalization: {
|
|
47
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.CHINESE],
|
|
48
|
+
defaultLocale: Locales.ENGLISH,
|
|
49
|
+
},
|
|
50
|
+
routing: {
|
|
51
|
+
mode: "prefix-no-default",
|
|
52
|
+
domains: {
|
|
53
|
+
// Shared domain — en and fr use prefix routing on intlayer.org
|
|
54
|
+
en: "intlayer.org",
|
|
55
|
+
// Exclusive domain — zh has its own hostname, no /zh/ prefix needed
|
|
56
|
+
zh: "intlayer.zh",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default config;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Locales that are not listed in `domains` continue to use the standard prefix routing without any domain override.
|
|
65
|
+
|
|
66
|
+
## URL Generation
|
|
67
|
+
|
|
68
|
+
`getLocalizedUrl` automatically produces the correct URL type based on the calling context.
|
|
69
|
+
|
|
70
|
+
### Same-domain locale (relative URL)
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// Current page: intlayer.org/about
|
|
74
|
+
getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.org" });
|
|
75
|
+
// → "/fr/about"
|
|
76
|
+
|
|
77
|
+
getLocalizedUrl("/about", "en", { currentDomain: "intlayer.org" });
|
|
78
|
+
// → "/about" (default locale, no prefix)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Cross-domain locale (absolute URL)
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
// Current page: intlayer.org/about
|
|
85
|
+
getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.org" });
|
|
86
|
+
// → "https://intlayer.zh/about" (exclusive domain, no /zh/ prefix)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Serving from the locale's own domain
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
// Current page: intlayer.zh/about
|
|
93
|
+
getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.zh" });
|
|
94
|
+
// → "/about" (already on the correct domain — relative URL)
|
|
95
|
+
|
|
96
|
+
getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.zh" });
|
|
97
|
+
// → "https://intlayer.org/fr/about" (cross-domain link back to intlayer.org)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Current domain auto-detection
|
|
101
|
+
|
|
102
|
+
`currentDomain` is optional. When omitted, `getLocalizedUrl` resolves it in this order:
|
|
103
|
+
|
|
104
|
+
1. The hostname of an absolute input URL (e.g. `https://intlayer.org/about` → `intlayer.org`).
|
|
105
|
+
2. `window.location.hostname` in browser environments.
|
|
106
|
+
3. If neither is available (SSR without explicit option), a relative URL is returned for same-domain locales and no absolute URL is produced — this is the safe fallback.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
// Browser — window.location.hostname === 'intlayer.org'
|
|
110
|
+
getLocalizedUrl("/about", "zh");
|
|
111
|
+
// → "https://intlayer.zh/about" (auto-detected from window)
|
|
112
|
+
|
|
113
|
+
// From an absolute URL — domain detected automatically
|
|
114
|
+
getLocalizedUrl("https://intlayer.org/about", "zh");
|
|
115
|
+
// → "https://intlayer.zh/about"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `getMultilingualUrls` with domains
|
|
119
|
+
|
|
120
|
+
`getMultilingualUrls` calls `getLocalizedUrl` for every locale, so it produces a mix of relative and absolute URLs depending on the caller's domain:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// currentDomain: 'intlayer.org'
|
|
124
|
+
getMultilingualUrls("/about", { currentDomain: "intlayer.org" });
|
|
125
|
+
// {
|
|
126
|
+
// en: "/about",
|
|
127
|
+
// fr: "/fr/about",
|
|
128
|
+
// es: "/es/about",
|
|
129
|
+
// zh: "https://intlayer.zh/about",
|
|
130
|
+
// }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
These absolute URLs are ready to use in `<link rel="alternate" hreflang="...">` tags for SEO.
|
|
134
|
+
|
|
135
|
+
## Proxy Behaviour
|
|
136
|
+
|
|
137
|
+
### Next.js
|
|
138
|
+
|
|
139
|
+
The `intlayerProxy` middleware handles domain routing automatically. Add it to your `middleware.ts`:
|
|
140
|
+
|
|
141
|
+
```typescript fileName="middleware.ts"
|
|
142
|
+
export { intlayerProxy as default } from "next-intlayer/proxy";
|
|
143
|
+
|
|
144
|
+
export const config = {
|
|
145
|
+
matcher: "/((?!api|static|assets|robots|sitemap|.*\\..*|_next).*)",
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Redirect** — request arrives on the wrong domain for a given locale prefix:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
GET intlayer.org/zh/about
|
|
153
|
+
→ 301 https://intlayer.zh/about
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Rewrite** — request arrives on the locale's exclusive domain without a prefix:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
GET intlayer.zh/about
|
|
160
|
+
→ rewrite to /zh/about (internal Next.js routing only, URL stays clean)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Vite
|
|
164
|
+
|
|
165
|
+
The `intlayerProxy` Vite plugin applies the same logic during development:
|
|
166
|
+
|
|
167
|
+
```typescript fileName="vite.config.ts"
|
|
168
|
+
import { defineConfig } from "vite";
|
|
169
|
+
import { intlayerProxy } from "vite-intlayer";
|
|
170
|
+
|
|
171
|
+
export default defineConfig({
|
|
172
|
+
plugins: [intlayerProxy()],
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> **Note**: in local development you are typically on `localhost`, so cross-domain redirects will point to the live domains rather than another local port. Use a hosts-file override (e.g. `127.0.0.1 intlayer.zh`) or a reverse proxy if you need to test multi-domain routing locally.
|
|
177
|
+
|
|
178
|
+
## Locale Switcher
|
|
179
|
+
|
|
180
|
+
The `useLocale` hook from `next-intlayer` handles domain-aware navigation automatically. When a user switches to a locale on a different domain the hook performs a full-page navigation (`window.location.href`) instead of a client-side router push, because the Next.js router cannot cross origins.
|
|
181
|
+
|
|
182
|
+
```tsx fileName="components/LocaleSwitcher.tsx"
|
|
183
|
+
"use client";
|
|
184
|
+
|
|
185
|
+
import { useLocale } from "next-intlayer";
|
|
186
|
+
|
|
187
|
+
export const LocaleSwitcher = () => {
|
|
188
|
+
const { availableLocales, locale, setLocale } = useLocale();
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<ul>
|
|
192
|
+
{availableLocales.map((localeEl) => (
|
|
193
|
+
<li key={localeEl}>
|
|
194
|
+
<button
|
|
195
|
+
onClick={() => setLocale(localeEl)}
|
|
196
|
+
aria-current={localeEl === locale ? "true" : undefined}
|
|
197
|
+
>
|
|
198
|
+
{localeEl.toUpperCase()}
|
|
199
|
+
</button>
|
|
200
|
+
</li>
|
|
201
|
+
))}
|
|
202
|
+
</ul>
|
|
203
|
+
);
|
|
204
|
+
};
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
No extra configuration is required — `useLocale` detects `window.location.hostname` internally and decides between `router.replace` (same domain) and `window.location.href` (cross-domain).
|
|
208
|
+
|
|
209
|
+
## SEO: `hreflang` Alternate Links
|
|
210
|
+
|
|
211
|
+
Domain-based routing is commonly used together with `hreflang` to tell search engines which URL to index for each language. Use `getMultilingualUrls` to generate the full set of alternate URLs:
|
|
212
|
+
|
|
213
|
+
```tsx fileName="app/[locale]/layout.tsx"
|
|
214
|
+
import { getMultilingualUrls } from "intlayer";
|
|
215
|
+
import type { Metadata } from "next";
|
|
216
|
+
|
|
217
|
+
export const generateMetadata = (): Metadata => {
|
|
218
|
+
const alternates = getMultilingualUrls("/", {
|
|
219
|
+
currentDomain: process.env.NEXT_PUBLIC_DOMAIN, // e.g. "intlayer.org"
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
alternates: {
|
|
224
|
+
languages: alternates,
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
This produces:
|
|
231
|
+
|
|
232
|
+
```html
|
|
233
|
+
<link rel="alternate" hreflang="en" href="https://intlayer.org/" />
|
|
234
|
+
<link rel="alternate" hreflang="fr" href="https://intlayer.org/fr/" />
|
|
235
|
+
<link rel="alternate" hreflang="es" href="https://intlayer.org/es/" />
|
|
236
|
+
<link rel="alternate" hreflang="zh" href="https://intlayer.zh/" />
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Core Utilities
|
|
240
|
+
|
|
241
|
+
| Utility | Description |
|
|
242
|
+
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
243
|
+
| `getLocalizedUrl(url, locale, { currentDomain })` | Returns relative or absolute URL depending on whether the target locale is on the current domain. |
|
|
244
|
+
| `getMultilingualUrls(url, { currentDomain })` | Returns a locale-keyed map of localized URLs, mixing relative and absolute as needed. |
|
|
245
|
+
| `getPrefix(locale, { domains })` | Returns an empty prefix for exclusive-domain locales, normal prefix otherwise. |
|
|
@@ -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:
|
|
@@ -166,59 +167,45 @@ export default defineConfig({
|
|
|
166
167
|
|
|
167
168
|
### Step 5: Create Root Layout
|
|
168
169
|
|
|
169
|
-
Configure your root layout to support internationalization by using `
|
|
170
|
+
Configure your root layout to support internationalization by using `useParams` to detect the current locale and setting the `lang` and `dir` attributes on the `html` tag.
|
|
170
171
|
|
|
171
172
|
```tsx fileName="src/routes/__root.tsx"
|
|
172
173
|
import {
|
|
173
174
|
HeadContent,
|
|
174
|
-
Outlet,
|
|
175
175
|
Scripts,
|
|
176
176
|
createRootRouteWithContext,
|
|
177
|
-
useMatches,
|
|
178
177
|
} from "@tanstack/solid-router";
|
|
179
|
-
import { TanStackRouterDevtools } from "@tanstack/solid-router-devtools";
|
|
180
178
|
import { HydrationScript } from "solid-js/web";
|
|
181
|
-
import { Suspense } from "solid-js";
|
|
179
|
+
import { Suspense, type ParentComponent } from "solid-js";
|
|
182
180
|
import { IntlayerProvider } from "solid-intlayer";
|
|
183
|
-
import { defaultLocale, getHTMLTextDir
|
|
181
|
+
import { defaultLocale, getHTMLTextDir } from "intlayer";
|
|
182
|
+
import { Route as LocaleRoute } from "./{-$locale}/route";
|
|
184
183
|
|
|
185
184
|
export const Route = createRootRouteWithContext()({
|
|
186
185
|
shellComponent: RootComponent,
|
|
187
186
|
});
|
|
188
187
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
function RootComponent() {
|
|
194
|
-
const matches = useMatches();
|
|
195
|
-
|
|
196
|
-
// Try to find locale in params of any active match
|
|
197
|
-
// This assumes you use the dynamic segment "/{-$locale}" in your route tree
|
|
198
|
-
const locale =
|
|
199
|
-
(
|
|
200
|
-
matches().find((match) => match.routeId === "/{-$locale}/")
|
|
201
|
-
?.params as Params
|
|
202
|
-
)?.locale ?? defaultLocale;
|
|
188
|
+
const RootComponent: ParentComponent = (props) => {
|
|
189
|
+
const params = LocaleRoute.useParams();
|
|
190
|
+
const locale = params()?.locale ?? defaultLocale;
|
|
203
191
|
|
|
204
192
|
return (
|
|
205
193
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
206
194
|
<head>
|
|
207
195
|
<HydrationScript />
|
|
196
|
+
<HeadContent />
|
|
208
197
|
</head>
|
|
209
198
|
<body>
|
|
210
|
-
<HeadContent />
|
|
211
199
|
<IntlayerProvider locale={locale}>
|
|
212
200
|
<Suspense>
|
|
213
|
-
|
|
214
|
-
<TanStackRouterDevtools />
|
|
201
|
+
{props.children}
|
|
215
202
|
</Suspense>
|
|
216
203
|
</IntlayerProvider>
|
|
217
204
|
<Scripts />
|
|
218
205
|
</body>
|
|
219
206
|
</html>
|
|
220
207
|
);
|
|
221
|
-
}
|
|
208
|
+
};
|
|
222
209
|
```
|
|
223
210
|
|
|
224
211
|
### Step 6: Create Locale Layout (Optional)
|
|
@@ -462,18 +449,12 @@ export default LocaleSwitcher;
|
|
|
462
449
|
|
|
463
450
|
### Step 10: HTML Attributes Management
|
|
464
451
|
|
|
465
|
-
As seen in Step 5, you can manage the `lang` and `dir` attributes of the `html` tag using `
|
|
452
|
+
As seen in Step 5, you can manage the `lang` and `dir` attributes of the `html` tag using `useParams` in your root component. This ensures that the correct attributes are set on the server and client.
|
|
466
453
|
|
|
467
454
|
```tsx fileName="src/routes/__root.tsx"
|
|
468
455
|
const RootComponent: ParentComponent = (props) => {
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
// Try to find locale in params of any active match
|
|
472
|
-
const locale =
|
|
473
|
-
(
|
|
474
|
-
matches().find((match) => match.routeId === "/{-$locale}/")
|
|
475
|
-
?.params as Params
|
|
476
|
-
)?.locale ?? defaultLocale;
|
|
456
|
+
const params = LocaleRoute.useParams();
|
|
457
|
+
const locale = params()?.locale ?? defaultLocale;
|
|
477
458
|
|
|
478
459
|
return (
|
|
479
460
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
@@ -186,31 +186,41 @@ export default config;
|
|
|
186
186
|
|
|
187
187
|
### Step 5: Create Root Layout
|
|
188
188
|
|
|
189
|
-
Configure your root layout to support internationalization by using `
|
|
189
|
+
Configure your root layout to support internationalization by using `useParams` to detect the current locale and setting the `lang` and `dir` attributes on the `html` tag.
|
|
190
190
|
|
|
191
191
|
```tsx fileName="src/routes/__root.tsx"
|
|
192
192
|
import {
|
|
193
193
|
createRootRouteWithContext,
|
|
194
194
|
HeadContent,
|
|
195
|
-
Outlet,
|
|
196
195
|
Scripts,
|
|
197
|
-
useMatches,
|
|
198
196
|
} from "@tanstack/react-router";
|
|
199
197
|
import { defaultLocale, getHTMLTextDir } from "intlayer";
|
|
200
198
|
import { type ReactNode } from "react";
|
|
201
199
|
import { IntlayerProvider } from "react-intlayer";
|
|
200
|
+
import { Route as LocaleRoute } from "./{-$locale}/route";
|
|
202
201
|
|
|
203
202
|
export const Route = createRootRouteWithContext<{}>()({
|
|
203
|
+
head: () => ({
|
|
204
|
+
meta: [
|
|
205
|
+
{
|
|
206
|
+
charSet: "utf-8",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
content: "width=device-width, initial-scale=1",
|
|
210
|
+
name: "viewport",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
title: "TanStack Start Starter",
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
}),
|
|
217
|
+
|
|
204
218
|
shellComponent: RootDocument,
|
|
205
219
|
});
|
|
206
220
|
|
|
207
221
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
// Try to find locale in params of any active match
|
|
211
|
-
// This assumes you use the dynamic segment "/{-$locale}" in your route tree
|
|
212
|
-
const localeRoute = matches.find((match) => match.routeId === "/{-$locale}");
|
|
213
|
-
const locale = localeRoute?.params?.locale ?? defaultLocale;
|
|
222
|
+
const params = LocaleRoute.useParams();
|
|
223
|
+
const locale = params?.locale ?? defaultLocale;
|
|
214
224
|
|
|
215
225
|
return (
|
|
216
226
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
@@ -218,7 +228,9 @@ function RootDocument({ children }: { children: ReactNode }) {
|
|
|
218
228
|
<HeadContent />
|
|
219
229
|
</head>
|
|
220
230
|
<body>
|
|
221
|
-
<IntlayerProvider locale={locale}>
|
|
231
|
+
<IntlayerProvider locale={locale}>
|
|
232
|
+
{children}
|
|
233
|
+
</IntlayerProvider>
|
|
222
234
|
<Scripts />
|
|
223
235
|
</body>
|
|
224
236
|
</html>
|
|
@@ -561,15 +573,12 @@ export const LocaleSwitcher: FC = () => {
|
|
|
561
573
|
|
|
562
574
|
### Step 10: HTML Attributes Management
|
|
563
575
|
|
|
564
|
-
As seen in Step 5, you can manage the `lang` and `dir` attributes of the `html` tag using `
|
|
576
|
+
As seen in Step 5, you can manage the `lang` and `dir` attributes of the `html` tag using `useParams` in your root component. This ensures that the correct attributes are set on the server and client.
|
|
565
577
|
|
|
566
578
|
```tsx fileName="src/routes/__root.tsx"
|
|
567
579
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
// Try to find locale in params of any active match
|
|
571
|
-
const localeRoute = matches.find((match) => match.routeId === "/{-$locale}");
|
|
572
|
-
const locale = localeRoute?.params?.locale ?? defaultLocale;
|
|
580
|
+
const params = LocaleRoute.useParams();
|
|
581
|
+
const locale = params?.locale ?? defaultLocale;
|
|
573
582
|
|
|
574
583
|
return (
|
|
575
584
|
<html dir={getHTMLTextDir(locale)} lang={locale}>
|