@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.
Files changed (197) hide show
  1. package/dist/cjs/doc.cjs.map +1 -1
  2. package/dist/cjs/generated/docs.entry.cjs +60 -0
  3. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  4. package/dist/esm/doc.mjs.map +1 -1
  5. package/dist/esm/generated/docs.entry.mjs +60 -0
  6. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  7. package/dist/types/doc.d.ts.map +1 -1
  8. package/dist/types/generated/docs.entry.d.ts +3 -0
  9. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  10. package/docs/ar/cli/index.md +54 -42
  11. package/docs/ar/cli/init.md +32 -20
  12. package/docs/ar/cli/standalone.md +91 -0
  13. package/docs/ar/configuration.md +39 -7
  14. package/docs/ar/custom_domains.md +250 -0
  15. package/docs/ar/intlayer_with_tanstack+solid.md +14 -33
  16. package/docs/ar/intlayer_with_tanstack.md +25 -16
  17. package/docs/ar/intlayer_with_vanilla.md +506 -0
  18. package/docs/bn/cli/index.md +195 -0
  19. package/docs/bn/cli/init.md +96 -0
  20. package/docs/bn/cli/standalone.md +91 -0
  21. package/docs/bn/configuration.md +46 -14
  22. package/docs/bn/custom_domains.md +250 -0
  23. package/docs/bn/intlayer_with_vanilla.md +506 -0
  24. package/docs/cs/cli/index.md +195 -0
  25. package/docs/cs/cli/init.md +96 -0
  26. package/docs/cs/cli/standalone.md +91 -0
  27. package/docs/cs/configuration.md +46 -7
  28. package/docs/cs/custom_domains.md +250 -0
  29. package/docs/cs/intlayer_with_vanilla.md +506 -0
  30. package/docs/de/cli/index.md +53 -41
  31. package/docs/de/cli/standalone.md +91 -0
  32. package/docs/de/configuration.md +46 -7
  33. package/docs/de/custom_domains.md +250 -0
  34. package/docs/de/intlayer_with_tanstack+solid.md +15 -36
  35. package/docs/de/intlayer_with_tanstack.md +25 -16
  36. package/docs/de/intlayer_with_vanilla.md +506 -0
  37. package/docs/en/bundle_optimization.md +288 -23
  38. package/docs/en/cli/index.md +6 -1
  39. package/docs/en/cli/init.md +13 -1
  40. package/docs/en/cli/standalone.md +91 -0
  41. package/docs/en/configuration.md +46 -7
  42. package/docs/en/custom_domains.md +245 -0
  43. package/docs/en/intlayer_with_tanstack+solid.md +15 -36
  44. package/docs/en/intlayer_with_tanstack.md +25 -16
  45. package/docs/en/intlayer_with_vanilla.md +506 -0
  46. package/docs/en-GB/cli/index.md +56 -44
  47. package/docs/en-GB/cli/init.md +28 -21
  48. package/docs/en-GB/cli/standalone.md +91 -0
  49. package/docs/en-GB/configuration.md +53 -14
  50. package/docs/en-GB/custom_domains.md +250 -0
  51. package/docs/en-GB/intlayer_with_tanstack+solid.md +15 -36
  52. package/docs/en-GB/intlayer_with_tanstack.md +25 -16
  53. package/docs/en-GB/intlayer_with_vanilla.md +506 -0
  54. package/docs/es/cli/index.md +65 -53
  55. package/docs/es/cli/init.md +33 -21
  56. package/docs/es/cli/standalone.md +91 -0
  57. package/docs/es/configuration.md +39 -1
  58. package/docs/es/custom_domains.md +250 -0
  59. package/docs/es/intlayer_with_tanstack+solid.md +15 -36
  60. package/docs/es/intlayer_with_tanstack.md +25 -16
  61. package/docs/es/intlayer_with_vanilla.md +506 -0
  62. package/docs/fr/cli/index.md +43 -31
  63. package/docs/fr/cli/init.md +37 -25
  64. package/docs/fr/cli/standalone.md +91 -0
  65. package/docs/fr/configuration.md +46 -7
  66. package/docs/fr/custom_domains.md +250 -0
  67. package/docs/fr/intlayer_with_tanstack+solid.md +15 -36
  68. package/docs/fr/intlayer_with_tanstack.md +25 -16
  69. package/docs/fr/intlayer_with_vanilla.md +506 -0
  70. package/docs/hi/cli/index.md +71 -59
  71. package/docs/hi/cli/init.md +37 -33
  72. package/docs/hi/cli/standalone.md +91 -0
  73. package/docs/hi/configuration.md +39 -7
  74. package/docs/hi/custom_domains.md +250 -0
  75. package/docs/hi/intlayer_with_tanstack+solid.md +14 -33
  76. package/docs/hi/intlayer_with_tanstack.md +25 -16
  77. package/docs/hi/intlayer_with_vanilla.md +506 -0
  78. package/docs/id/cli/index.md +59 -47
  79. package/docs/id/cli/init.md +32 -25
  80. package/docs/id/cli/standalone.md +91 -0
  81. package/docs/id/configuration.md +46 -7
  82. package/docs/id/custom_domains.md +250 -0
  83. package/docs/id/intlayer_with_tanstack+solid.md +14 -33
  84. package/docs/id/intlayer_with_tanstack.md +25 -16
  85. package/docs/id/intlayer_with_vanilla.md +506 -0
  86. package/docs/it/cli/index.md +58 -41
  87. package/docs/it/cli/init.md +37 -38
  88. package/docs/it/cli/standalone.md +91 -0
  89. package/docs/it/configuration.md +46 -7
  90. package/docs/it/custom_domains.md +250 -0
  91. package/docs/it/intlayer_with_tanstack+solid.md +15 -36
  92. package/docs/it/intlayer_with_tanstack.md +25 -16
  93. package/docs/it/intlayer_with_vanilla.md +506 -0
  94. package/docs/ja/cli/index.md +59 -47
  95. package/docs/ja/cli/init.md +36 -24
  96. package/docs/ja/cli/standalone.md +91 -0
  97. package/docs/ja/configuration.md +46 -7
  98. package/docs/ja/custom_domains.md +250 -0
  99. package/docs/ja/intlayer_with_tanstack+solid.md +15 -36
  100. package/docs/ja/intlayer_with_tanstack.md +25 -16
  101. package/docs/ja/intlayer_with_vanilla.md +506 -0
  102. package/docs/ko/cli/index.md +58 -46
  103. package/docs/ko/cli/init.md +39 -35
  104. package/docs/ko/cli/standalone.md +91 -0
  105. package/docs/ko/configuration.md +47 -8
  106. package/docs/ko/custom_domains.md +250 -0
  107. package/docs/ko/intlayer_with_tanstack+solid.md +15 -36
  108. package/docs/ko/intlayer_with_tanstack.md +25 -16
  109. package/docs/ko/intlayer_with_vanilla.md +506 -0
  110. package/docs/nl/cli/index.md +195 -0
  111. package/docs/nl/cli/init.md +96 -0
  112. package/docs/nl/cli/standalone.md +91 -0
  113. package/docs/nl/configuration.md +46 -7
  114. package/docs/nl/custom_domains.md +250 -0
  115. package/docs/nl/intlayer_with_vanilla.md +506 -0
  116. package/docs/pl/cli/index.md +56 -44
  117. package/docs/pl/cli/init.md +36 -32
  118. package/docs/pl/cli/standalone.md +91 -0
  119. package/docs/pl/configuration.md +46 -7
  120. package/docs/pl/custom_domains.md +250 -0
  121. package/docs/pl/intlayer_with_tanstack+solid.md +14 -33
  122. package/docs/pl/intlayer_with_tanstack.md +25 -16
  123. package/docs/pl/intlayer_with_vanilla.md +506 -0
  124. package/docs/pt/cli/index.md +64 -52
  125. package/docs/pt/cli/init.md +35 -31
  126. package/docs/pt/cli/standalone.md +91 -0
  127. package/docs/pt/configuration.md +46 -7
  128. package/docs/pt/custom_domains.md +250 -0
  129. package/docs/pt/intlayer_with_tanstack+solid.md +15 -36
  130. package/docs/pt/intlayer_with_tanstack.md +25 -16
  131. package/docs/pt/intlayer_with_vanilla.md +506 -0
  132. package/docs/ru/cli/index.md +54 -42
  133. package/docs/ru/cli/init.md +31 -27
  134. package/docs/ru/cli/standalone.md +91 -0
  135. package/docs/ru/configuration.md +46 -7
  136. package/docs/ru/custom_domains.md +250 -0
  137. package/docs/ru/intlayer_with_tanstack+solid.md +15 -36
  138. package/docs/ru/intlayer_with_tanstack.md +25 -16
  139. package/docs/ru/intlayer_with_vanilla.md +506 -0
  140. package/docs/tr/cli/index.md +64 -52
  141. package/docs/tr/cli/init.md +37 -30
  142. package/docs/tr/cli/standalone.md +91 -0
  143. package/docs/tr/configuration.md +46 -7
  144. package/docs/tr/custom_domains.md +250 -0
  145. package/docs/tr/intlayer_with_tanstack+solid.md +14 -33
  146. package/docs/tr/intlayer_with_tanstack.md +25 -16
  147. package/docs/tr/intlayer_with_vanilla.md +506 -0
  148. package/docs/uk/cli/index.md +60 -55
  149. package/docs/uk/cli/init.md +32 -20
  150. package/docs/uk/cli/standalone.md +91 -0
  151. package/docs/uk/configuration.md +46 -7
  152. package/docs/uk/custom_domains.md +250 -0
  153. package/docs/uk/intlayer_with_tanstack+solid.md +14 -33
  154. package/docs/uk/intlayer_with_tanstack.md +25 -16
  155. package/docs/uk/intlayer_with_vanilla.md +506 -0
  156. package/docs/ur/cli/index.md +195 -0
  157. package/docs/ur/cli/init.md +96 -0
  158. package/docs/ur/cli/standalone.md +91 -0
  159. package/docs/ur/configuration.md +46 -7
  160. package/docs/ur/custom_domains.md +250 -0
  161. package/docs/ur/intlayer_with_vanilla.md +506 -0
  162. package/docs/vi/cli/index.md +72 -61
  163. package/docs/vi/cli/init.md +33 -21
  164. package/docs/vi/cli/standalone.md +91 -0
  165. package/docs/vi/configuration.md +46 -7
  166. package/docs/vi/custom_domains.md +250 -0
  167. package/docs/vi/intlayer_with_tanstack+solid.md +14 -33
  168. package/docs/vi/intlayer_with_tanstack.md +25 -16
  169. package/docs/vi/intlayer_with_vanilla.md +506 -0
  170. package/docs/zh/cli/index.md +56 -49
  171. package/docs/zh/cli/init.md +30 -18
  172. package/docs/zh/cli/standalone.md +91 -0
  173. package/docs/zh/configuration.md +46 -7
  174. package/docs/zh/custom_domains.md +250 -0
  175. package/docs/zh/intlayer_with_tanstack+solid.md +15 -36
  176. package/docs/zh/intlayer_with_tanstack.md +25 -16
  177. package/docs/zh/intlayer_with_vanilla.md +506 -0
  178. package/package.json +8 -8
  179. package/src/doc.ts +4 -1
  180. package/src/generated/docs.entry.ts +60 -0
  181. package/docs/ar/bundle_optimization.md +0 -185
  182. package/docs/de/bundle_optimization.md +0 -195
  183. package/docs/en-GB/bundle_optimization.md +0 -184
  184. package/docs/es/bundle_optimization.md +0 -194
  185. package/docs/fr/bundle_optimization.md +0 -184
  186. package/docs/hi/bundle_optimization.md +0 -185
  187. package/docs/id/bundle_optimization.md +0 -185
  188. package/docs/it/bundle_optimization.md +0 -185
  189. package/docs/ja/bundle_optimization.md +0 -185
  190. package/docs/ko/bundle_optimization.md +0 -185
  191. package/docs/pl/bundle_optimization.md +0 -185
  192. package/docs/pt/bundle_optimization.md +0 -184
  193. package/docs/ru/bundle_optimization.md +0 -185
  194. package/docs/tr/bundle_optimization.md +0 -184
  195. package/docs/uk/bundle_optimization.md +0 -186
  196. package/docs/vi/bundle_optimization.md +0 -185
  197. 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: Tên miền tùy chỉnh
5
+ description: Tìm hiểu cách cấu hình điều hướng ngôn ngữ dựa trên tên miền trong Intlayer để phục vụ các ngôn ngữ khác nhau từ các tên miền riêng biệt.
6
+ keywords:
7
+ - Tên miền tùy chỉnh
8
+ - Điều hướng theo tên miền
9
+ - Điều hướng
10
+ - Quốc tế hóa
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: "Thêm điều hướng ngôn ngữ dựa trên tên miền thông qua cấu hình routing.domains."
20
+ ---
21
+
22
+ # Tên miền tùy chỉnh
23
+
24
+ Intlayer hỗ trợ điều hướng ngôn ngữ dựa trên tên miền, cho phép bạn phục vụ các ngôn ngữ cụ thể từ các tên miền riêng biệt. Ví dụ: khách truy cập từ Trung Quốc có thể được điều hướng đến `intlayer.zh` thay vì `intlayer.org/zh`.
25
+
26
+ ## Cách thức hoạt động
27
+
28
+ Bản đồ `domains` trong `routing` liên kết mỗi ngôn ngữ với một tên miền. Intlayer sử dụng bản đồ này ở hai nơi:
29
+
30
+ 1. **Tạo URL** (`getLocalizedUrl`): khi ngôn ngữ mục tiêu nằm trên một tên miền _khác_ với trang hiện tại, một URL tuyệt đối sẽ được trả về (ví dụ: `https://intlayer.zh/about`). Khi cả hai tên miền khớp nhau, một URL tương đối sẽ được trả về (ví dụ: `/fr/about`).
31
+ 2. **Proxy máy chủ** (Next.js & Vite): Các yêu cầu đến sẽ được chuyển hướng hoặc ghi lại dựa trên tên miền mà chúng đến.
32
+
33
+ ### Tên miền độc quyền vs Tên miền chung
34
+
35
+ Sự khác biệt chính là **tính độc quyền**:
36
+
37
+ - **Tên miền độc quyền** — Chỉ một ngôn ngữ ánh xạ tới tên miền đó (ví dụ: `zh → intlayer.zh`). Bản thân tên miền đó xác định ngôn ngữ, vì vậy không có tiền tố ngôn ngữ nào được thêm vào đường dẫn. `https://intlayer.zh/about` phục vụ nội dung tiếng Trung.
38
+ - **Tên miền chung** — Nhiều ngôn ngữ ánh xạ tới cùng một tên miền (ví dụ: cả `en` và `fr` đều ánh xạ tới `intlayer.org`). Điều hướng dựa trên tiền tố thông thường sẽ được áp dụng. `intlayer.org/fr/about` phục vụ nội dung tiếng Pháp.
39
+
40
+ ## Cấu hình
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
+ // Tên miền chung — en và fr sử dụng điều hướng tiền tố trên intlayer.org
59
+ en: "intlayer.org",
60
+ // Tên miền độc quyền — zh có tên miền riêng, không cần tiền tố /zh/
61
+ zh: "intlayer.zh",
62
+ },
63
+ },
64
+ };
65
+
66
+ export default config;
67
+ ```
68
+
69
+ Các ngôn ngữ không được liệt kê trong `domains` tiếp tục sử dụng điều hướng tiền tố tiêu chuẩn mà không có bất kỳ ghi đè tên miền nào.
70
+
71
+ ## Tạo URL
72
+
73
+ `getLocalizedUrl` tự động tạo loại URL chính xác dựa trên ngữ cảnh cuộc gọi.
74
+
75
+ ### Ngôn ngữ cùng tên miền (URL tương đối)
76
+
77
+ ```ts
78
+ // Trang hiện tại: intlayer.org/about
79
+ getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.org" });
80
+ // → "/fr/about"
81
+
82
+ getLocalizedUrl("/about", "en", { currentDomain: "intlayer.org" });
83
+ // → "/about" (ngôn ngữ mặc định, không tiền tố)
84
+ ```
85
+
86
+ ### Ngôn ngữ khác tên miền (URL tuyệt đối)
87
+
88
+ ```ts
89
+ // Trang hiện tại: intlayer.org/about
90
+ getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.org" });
91
+ // → "https://intlayer.zh/about" (tên miền độc quyền, không có tiền tố /zh/)
92
+ ```
93
+
94
+ ### Phục vụ từ chính tên miền của ngôn ngữ
95
+
96
+ ```ts
97
+ // Trang hiện tại: intlayer.zh/about
98
+ getLocalizedUrl("/about", "zh", { currentDomain: "intlayer.zh" });
99
+ // → "/about" (đã ở đúng tên miền — URL tương đối)
100
+
101
+ getLocalizedUrl("/about", "fr", { currentDomain: "intlayer.zh" });
102
+ // → "https://intlayer.org/fr/about" (liên kết xuyên tên miền quay lại intlayer.org)
103
+ ```
104
+
105
+ ### Tự động phát hiện tên miền hiện tại
106
+
107
+ `currentDomain` là tùy chọn. Khi được bỏ qua, `getLocalizedUrl` sẽ giải quyết nó theo thứ tự này:
108
+
109
+ 1. Tên miền của một URL đầu vào tuyệt đối (ví dụ: `https://intlayer.org/about` → `intlayer.org`).
110
+ 2. `window.location.hostname` trong môi trường trình duyệt.
111
+ 3. Nếu không có cái nào khả dụng (SSR không có tùy chọn rõ ràng), một URL tương đối sẽ được trả về cho các ngôn ngữ cùng tên miền và không có URL tuyệt đối nào được tạo — đây là phương án dự phòng an toàn.
112
+
113
+ ```ts
114
+ // Trình duyệt — window.location.hostname === 'intlayer.org'
115
+ getLocalizedUrl("/about", "zh");
116
+ // → "https://intlayer.zh/about" (tự động phát hiện từ window)
117
+
118
+ // Từ một URL tuyệt đối — tên miền được phát hiện tự động
119
+ getLocalizedUrl("https://intlayer.org/about", "zh");
120
+ // → "https://intlayer.zh/about"
121
+ ```
122
+
123
+ ### `getMultilingualUrls` với tên miền
124
+
125
+ `getMultilingualUrls` gọi `getLocalizedUrl` cho mọi ngôn ngữ, vì vậy nó tạo ra sự kết hợp giữa URL tương đối và tuyệt đối tùy thuộc vào tên miền của người gọi:
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
+ Các URL tuyệt đối này đã sẵn sàng để sử dụng trong các thẻ `<link rel="alternate" hreflang="...">` cho SEO.
139
+
140
+ ## Hành vi Proxy
141
+
142
+ ### Next.js
143
+
144
+ Phần mềm trung gian `intlayerProxy` tự động xử lý điều hướng tên miền. Thêm nó vào `middleware.ts` của bạn:
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
+ **Chuyển hướng** — yêu cầu đến sai tên miền cho một tiền tố ngôn ngữ nhất định:
155
+
156
+ ```
157
+ GET intlayer.org/zh/about
158
+ → 301 https://intlayer.zh/about
159
+ ```
160
+
161
+ **Ghi lại (Rewrite)** — yêu cầu đến tên miền độc quyền của ngôn ngữ mà không có tiền tố:
162
+
163
+ ```
164
+ GET intlayer.zh/about
165
+ → ghi lại thành /zh/about (chỉ điều hướng nội bộ Next.js, URL vẫn sạch sẽ)
166
+ ```
167
+
168
+ ### Vite
169
+
170
+ Plugin Vite `intlayerProxy` áp dụng logic tương tự trong quá trình phát triển:
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
+ > **Lưu ý**: trong quá trình phát triển cục bộ, bạn thường ở `localhost`, vì vậy các chuyển hướng xuyên tên miền sẽ trỏ đến các tên miền trực tiếp thay vì một cổng cục bộ khác. Sử dụng ghi đè tệp hosts (ví dụ: `127.0.0.1 intlayer.zh`) hoặc một proxy ngược nếu bạn cần kiểm tra điều hướng đa tên miền cục bộ.
182
+
183
+ ## Trình chuyển đổi ngôn ngữ (Locale Switcher)
184
+
185
+ Hook `useLocale` từ `next-intlayer` tự động xử lý điều hướng nhận biết tên miền. Khi người dùng chuyển sang một ngôn ngữ trên một tên miền khác, hook thực hiện điều hướng toàn bộ trang (`window.location.href`) thay vì đẩy bộ định tuyến phía máy khách, vì bộ định tuyến Next.js không thể xuyên suốt các nguồn (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
+ Không cần cấu hình thêm — `useLocale` tự động phát hiện `window.location.hostname` bên trong và quyết định giữa `router.replace` (cùng tên miền) và `window.location.href` (khác tên miền).
213
+
214
+ ## SEO: `hreflang` Liên kết thay thế
215
+
216
+ Điều hướng dựa trên tên miền thường được sử dụng cùng với `hreflang` để thông báo cho các công cụ tìm kiếm biết URL nào nên lập chỉ mục cho mỗi ngôn ngữ. Sử dụng `getMultilingualUrls` để tạo bộ URL thay thế đầy đủ:
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, // ví dụ: "intlayer.org"
225
+ });
226
+
227
+ return {
228
+ alternates: {
229
+ languages: alternates,
230
+ },
231
+ };
232
+ };
233
+ ```
234
+
235
+ Điều này tạo ra:
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
+ ## Các tiện ích cốt lõi
245
+
246
+ | Tiện ích | Mô tả |
247
+ | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
248
+ | `getLocalizedUrl(url, locale, { currentDomain })` | Trả về URL tương đối hoặc tuyệt đối tùy thuộc vào việc ngôn ngữ mục tiêu có nằm trên tên miền hiện tại hay không. |
249
+ | `getMultilingualUrls(url, { currentDomain })` | Trả về một bản đồ các URL được bản địa hóa theo khóa ngôn ngữ, kết hợp tương đối và tuyệt đối khi cần thiết. |
250
+ | `getPrefix(locale, { domains })` | Trả về một tiền tố trống cho các ngôn ngữ thuộc tên miền độc quyền, tiền tố bình thường nếu ngược lại. |
@@ -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
  ### Bước 5: Tạo Root Layout
164
165
 
165
- Cấu hình layout gốc của bạn để hỗ trợ đa ngôn ngữ bằng cách sử dụng `useMatches` để phát hiện ngôn ngữ hiện tại và thiết lập các thuộc tính `lang` và `dir` trên thẻ `html`.
166
+ Cấu hình layout gốc của bạn để hỗ trợ đa ngôn ngữ bằng cách sử dụng `useParams` để phát hiện ngôn ngữ hiện tại và thiết lập các thuộc tính `lang` và `dir` trên thẻ `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, type Locale } from "intlayer";
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
- type Params = {
186
- locale: Locale;
187
- };
188
-
189
- function RootComponent() {
190
- const matches = useMatches();
191
-
192
- // Thử tìm locale trong các tham số của bất kỳ match nào đang hoạt động
193
- // Giả định rằng bạn sử dụng phần động "/{-$locale}" trong cây route của mình
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
- <Outlet />
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
  ### Bước 6: Tạo Locale Layout (Tùy chọn)
@@ -458,18 +445,12 @@ export default LocaleSwitcher;
458
445
 
459
446
  ### Bước 11: Quản lý các thuộc tính HTML
460
447
 
461
- Như đã thấy ở Bước 5, bạn có thể quản lý các thuộc tính `lang` và `dir` của thẻ `html` bằng cách sử dụng `useMatches` trong component gốc của mình. Điều này đảm bảo rằng các thuộc tính chính xác được thiết lập trên cả server và client.
448
+ Như đã thấy ở Bước 5, bạn có thể quản lý các thuộc tính `lang` và `dir` của thẻ `html` bằng cách sử dụng `useParams` trong component gốc của mình. Điều này đảm bảo rằng các thuộc tính chính xác được thiết lập trên cả server và client.
462
449
 
463
450
  ```tsx fileName="src/routes/__root.tsx"
464
451
  const RootComponent: ParentComponent = (props) => {
465
- const matches = useMatches();
466
-
467
- // Thử tìm locale trong các tham số của bất kỳ match nào đang hoạt động
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
  ### Bước 5: Tạo Root Layout
184
184
 
185
- Cấu hình root layout của bạn để hỗ trợ quốc tế hóa bằng cách sử dụng `useMatches` để phát hiện locale hiện tại và đặt các thuộc tính `lang` và `dir` trên thẻ `html`.
185
+ Cấu hình root layout của bạn để hỗ trợ quốc tế hóa bằng cách sử dụng `useParams` để phát hiện locale hiện tại và đặt các thuộc tính `lang` và `dir` trên thẻ `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 matches = useMatches();
205
-
206
- // Thử tìm locale trong params của bất kỳ match đang hoạt động nào
207
- // Điều này giả định bạn sử dụng segment động "/{-$locale}" trong cây route của mình
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}>{children}</IntlayerProvider>
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
  ### Bước 11: Quản lý Thuộc tính HTML
559
571
 
560
- Như đã thấy trong Bước 5, bạn có thể quản lý các thuộc tính `lang` và `dir` của thẻ `html` bằng cách sử dụng `useMatches` trong component gốc của bạn. Điều này đảm bảo các thuộc tính được đặt đúng trên server và client.
572
+ Như đã thấy trong Bước 5, bạn có thể quản lý các thuộc tính `lang` và `dir` của thẻ `html` bằng cách sử dụng `useParams` trong component gốc của bạn. Điều này đảm bảo các thuộc tính được đặt đúng trên server và client.
561
573
 
562
574
  ```tsx fileName="src/routes/__root.tsx"
563
575
  function RootDocument({ children }: { children: ReactNode }) {
564
- const matches = useMatches();
565
-
566
- // Thử tìm locale trong params của bất kỳ match đang hoạt động nào
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}>