@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: Dominios personalizados
|
|
5
|
+
description: Aprenda a configurar el enrutamiento de locales basado en dominios en Intlayer para servir diferentes locales desde nombres de host dedicados.
|
|
6
|
+
keywords:
|
|
7
|
+
- Dominios personalizados
|
|
8
|
+
- Enrutamiento por dominio
|
|
9
|
+
- Enrutamiento
|
|
10
|
+
- Internacionalización
|
|
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: "Se agregó el enrutamiento de locales basado en dominios a través de la configuración routing.domains."
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Dominios personalizados
|
|
23
|
+
|
|
24
|
+
Intlayer admite el enrutamiento de locales basado en dominios, lo que le permite servir locales específicos desde nombres de host dedicados. Por ejemplo, los visitantes chinos pueden ser dirigidos a `intlayer.zh` en lugar de `intlayer.org/zh`.
|
|
25
|
+
|
|
26
|
+
## Cómo funciona
|
|
27
|
+
|
|
28
|
+
El mapa `domains` en `routing` asocia cada locale con un nombre de host. Intlayer utiliza este mapa en dos lugares:
|
|
29
|
+
|
|
30
|
+
1. **Generación de URL** (`getLocalizedUrl`): cuando el locale de destino vive en un dominio _diferente_ al de la página actual, se devuelve una URL absoluta (por ejemplo, `https://intlayer.zh/about`). Cuando ambos dominios coinciden, se devuelve una URL relativa (por ejemplo, `/fr/about`).
|
|
31
|
+
2. **Proxy del servidor** (Next.js y Vite): las solicitudes entrantes se redirigen o reescriben en función del dominio en el que llegan.
|
|
32
|
+
|
|
33
|
+
### Dominios exclusivos frente a compartidos
|
|
34
|
+
|
|
35
|
+
La distinción clave es la **exclusividad**:
|
|
36
|
+
|
|
37
|
+
- **Dominio exclusivo** — solo un locale se asigna a ese nombre de host (por ejemplo, `zh → intlayer.zh`). El dominio en sí identifica el locale, por lo que no se añade ningún prefijo de locale a la ruta. `https://intlayer.zh/about` sirve contenido en chino.
|
|
38
|
+
- **Dominio compartido** — varios locales se asignan al mismo nombre de host (por ejemplo, `en` y `fr` se asignan a `intlayer.org`). Se aplica el enrutamiento estándar basado en prefijos. `intlayer.org/fr/about` sirve contenido en francés.
|
|
39
|
+
|
|
40
|
+
## Configuración
|
|
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
|
+
// Dominio compartido — en y fr usan enrutamiento por prefijo en intlayer.org
|
|
59
|
+
en: "intlayer.org",
|
|
60
|
+
// Dominio exclusivo — zh tiene su propio nombre de host, no se necesita el prefijo /zh/
|
|
61
|
+
zh: "intlayer.zh",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default config;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Los locales que no figuran en `domains` continúan usando el enrutamiento estándar por prefijo sin ninguna anulación de dominio.
|
|
70
|
+
|
|
71
|
+
## Generación de URL
|
|
72
|
+
|
|
73
|
+
`getLocalizedUrl` produce automáticamente el tipo de URL correcto según el contexto de la llamada.
|
|
74
|
+
|
|
75
|
+
### Locale en el mismo dominio (URL relativa)
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// Página actual: intlayer.org/about
|
|
79
|
+
getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.org" });
|
|
80
|
+
// → "/fr/about"
|
|
81
|
+
|
|
82
|
+
getLocalizedUrl("/about", "en", { currentDomain: "intlayer.org" });
|
|
83
|
+
// → "/about" (locale predeterminado, sin prefijo)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Locale en un dominio diferente (URL absoluta)
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// Página actual: intlayer.org/about
|
|
90
|
+
getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.org" });
|
|
91
|
+
// → "https://intlayer.zh/about" (dominio exclusivo, sin prefijo /zh/)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Servir desde el propio dominio del locale
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// Página actual: intlayer.zh/about
|
|
98
|
+
getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.zh" });
|
|
99
|
+
// → "/about" (ya está en el dominio correcto — URL relativa)
|
|
100
|
+
|
|
101
|
+
getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.zh" });
|
|
102
|
+
// → "https://intlayer.org/fr/about" (enlace entre dominios de vuelta a intlayer.org)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Autodetección del dominio actual
|
|
106
|
+
|
|
107
|
+
`currentDomain` es opcional. Cuando se omite, `getLocalizedUrl` lo resuelve en este orden:
|
|
108
|
+
|
|
109
|
+
1. El nombre de host de una URL de entrada absoluta (por ejemplo, `https://intlayer.org/about` → `intlayer.org`).
|
|
110
|
+
2. `window.location.hostname` en entornos de navegador.
|
|
111
|
+
3. Si ninguno está disponible (SSR sin opción explícita), se devuelve una URL relativa para locales del mismo dominio y no se produce ninguna URL absoluta — este es el respaldo seguro.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// Navegador — window.location.hostname === 'intlayer.org'
|
|
115
|
+
getLocalizedUrl("/about", "zh");
|
|
116
|
+
// → "https://intlayer.zh/about" (detectado automáticamente desde window)
|
|
117
|
+
|
|
118
|
+
// Desde una URL absoluta — dominio detectado automáticamente
|
|
119
|
+
getLocalizedUrl("https://intlayer.org/about", "zh");
|
|
120
|
+
// → "https://intlayer.zh/about"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `getMultilingualUrls` con dominios
|
|
124
|
+
|
|
125
|
+
`getMultilingualUrls` llama a `getLocalizedUrl` para cada locale, por lo que produce una mezcla de URL relativas y absolutas según el dominio de quien lo llama:
|
|
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
|
+
Estas URL absolutas están listas para usarse en etiquetas `<link rel="alternate" hreflang="...">` para SEO.
|
|
139
|
+
|
|
140
|
+
## Comportamiento del Proxy
|
|
141
|
+
|
|
142
|
+
### Next.js
|
|
143
|
+
|
|
144
|
+
El middleware `intlayerProxy` maneja automáticamente el enrutamiento de dominios. Agréguelo a su `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
|
+
**Redirección** — la solicitud llega al dominio equivocado para un prefijo de locale dado:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
GET intlayer.org/zh/about
|
|
158
|
+
→ 301 https://intlayer.zh/about
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Reescritura** — la solicitud llega al dominio exclusivo del locale sin un prefijo:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
GET intlayer.zh/about
|
|
165
|
+
→ reescritura a /zh/about (solo enrutamiento interno de Next.js, la URL se mantiene limpia)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Vite
|
|
169
|
+
|
|
170
|
+
El complemento Vite `intlayerProxy` aplica la misma lógica durante el desarrollo:
|
|
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
|
+
> **Nota**: en el desarrollo local normalmente se encuentra en `localhost`, por lo que las redirecciones entre dominios apuntarán a los dominios en vivo en lugar de a otro puerto local. Use una anulación en el archivo hosts (por ejemplo, `127.0.0.1 intlayer.zh`) o un proxy inverso si necesita probar el enrutamiento multidominio localmente.
|
|
182
|
+
|
|
183
|
+
## Selector de locale
|
|
184
|
+
|
|
185
|
+
El hook `useLocale` de `next-intlayer` maneja la navegación consciente del dominio automáticamente. Cuando un usuario cambia a un locale en un dominio diferente, el hook realiza una navegación de página completa (`window.location.href`) en lugar de un push del enrutador del lado del cliente, porque el enrutador de Next.js no puede cruzar orígenes.
|
|
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
|
+
No se requiere configuración adicional — `useLocale` detecta `window.location.hostname` internamente y decide entre `router.replace` (mismo dominio) y `window.location.href` (dominio cruzado).
|
|
213
|
+
|
|
214
|
+
## SEO: Enlaces alternativos `hreflang`
|
|
215
|
+
|
|
216
|
+
El enrutamiento basado en dominios se usa comúnmente junto con `hreflang` para indicar a los motores de búsqueda qué URL indexar para cada idioma. Use `getMultilingualUrls` para generar el conjunto completo de URL alternativas:
|
|
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, // ej. "intlayer.org"
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
alternates: {
|
|
229
|
+
languages: alternates,
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Esto produce:
|
|
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
|
+
## Utilidades principales
|
|
245
|
+
|
|
246
|
+
| Utilidad | Descripción |
|
|
247
|
+
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
248
|
+
| `getLocalizedUrl(url, locale, { currentDomain })` | Devuelve una URL relativa o absoluta dependiendo de si el locale de destino está en el dominio actual. |
|
|
249
|
+
| `getMultilingualUrls(url, { currentDomain })` | Devuelve un mapa de URL localizadas por locale, mezclando relativas y absolutas según sea necesario. |
|
|
250
|
+
| `getPrefix(locale, { domains })` | Devuelve un prefijo vacío para locales de dominio exclusivo, de lo contrario, un prefijo normal. |
|
|
@@ -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
|
### Paso 5: Crear el diseño raíz (Root Layout)
|
|
165
166
|
|
|
166
|
-
Configure su diseño raíz para soportar la internacionalización utilizando `
|
|
167
|
+
Configure su diseño raíz para soportar la internacionalización utilizando `useParams` para detectar el idioma actual y estableciendo los atributos `lang` y `dir` en la etiqueta `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
|
-
// Intenta encontrar el idioma en los parámetros de cualquier coincidencia activa
|
|
194
|
-
// Esto asume que utiliza el segmento dinámico "/{-$locale}" en su árbol de rutas
|
|
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
|
### Paso 6: Crear el diseño de idioma (Opcional)
|
|
@@ -459,18 +446,12 @@ export default LocaleSwitcher;
|
|
|
459
446
|
|
|
460
447
|
### Paso 11: Gestión de atributos HTML
|
|
461
448
|
|
|
462
|
-
Como vimos en el Paso 5, puede gestionar los atributos `lang` y `dir` de la etiqueta `html` utilizando `
|
|
449
|
+
Como vimos en el Paso 5, puede gestionar los atributos `lang` y `dir` de la etiqueta `html` utilizando `useParams` en su componente raíz. Esto asegura que se establezcan los atributos correctos tanto en el servidor como en el cliente.
|
|
463
450
|
|
|
464
451
|
```tsx fileName="src/routes/__root.tsx"
|
|
465
452
|
const RootComponent: ParentComponent = (props) => {
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
// Intenta encontrar el idioma en los parámetros de cualquier coincidencia activa
|
|
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}>
|
|
@@ -183,31 +183,41 @@ export default config;
|
|
|
183
183
|
|
|
184
184
|
### Paso 5: Crear el diseño raíz (Root Layout)
|
|
185
185
|
|
|
186
|
-
Configura tu diseño raíz para admitir la internacionalización mediante el uso de `
|
|
186
|
+
Configura tu diseño raíz para admitir la internacionalización mediante el uso de `useParams` para detectar la configuración regional actual y estableciendo los atributos `lang` y `dir` en la etiqueta `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
|
-
// Intenta encontrar la configuración regional en los parámetros de cualquier coincidencia activa
|
|
208
|
-
// Esto supone que utilizas el segmento dinámico "/{-$locale}" en tu árbol de rutas
|
|
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
|
### Paso 10: Gestión de atributos HTML
|
|
560
572
|
|
|
561
|
-
Como se vio en el Paso 5, puedes gestionar los atributos `lang` y `dir` de la etiqueta `html` utilizando `
|
|
573
|
+
Como se vio en el Paso 5, puedes gestionar los atributos `lang` y `dir` de la etiqueta `html` utilizando `useParams` en tu componente raíz. Esto garantiza que los atributos correctos se establezcan en el servidor y el cliente.
|
|
562
574
|
|
|
563
575
|
```tsx fileName="src/routes/__root.tsx"
|
|
564
576
|
function RootDocument({ children }: { children: ReactNode }) {
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
// Intenta encontrar la configuración regional en los parámetros de cualquier coincidencia activa
|
|
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}>
|