@intlayer/docs 7.0.7 → 7.0.8

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 (726) hide show
  1. package/blog/ar/i18n_using_next-i18next.md +1068 -0
  2. package/blog/ar/i18n_using_next-intl.md +768 -0
  3. package/blog/ar/intlayer_with_react-intl.md +0 -4
  4. package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +5 -4
  5. package/blog/de/i18n_using_next-i18next.md +1107 -0
  6. package/blog/de/i18n_using_next-intl.md +760 -0
  7. package/blog/de/intlayer_with_react-intl.md +0 -4
  8. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  9. package/blog/en/i18n_using_next-i18next.md +1073 -0
  10. package/blog/en/i18n_using_next-intl.md +757 -0
  11. package/blog/en/intlayer_with_i18next.md +71 -8
  12. package/blog/en/intlayer_with_next-i18next.md +71 -8
  13. package/blog/en/intlayer_with_next-intl.md +71 -8
  14. package/blog/en/intlayer_with_react-i18next.md +69 -8
  15. package/blog/en/intlayer_with_react-intl.md +68 -9
  16. package/blog/en/intlayer_with_vue-i18n.md +68 -7
  17. package/blog/en/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
  18. package/blog/en/vue-i18n_vs_intlayer.md +2 -0
  19. package/blog/en-GB/i18n_using_next-i18next.md +1074 -0
  20. package/blog/en-GB/i18n_using_next-intl.md +757 -0
  21. package/blog/en-GB/intlayer_with_i18next.md +15 -6
  22. package/blog/en-GB/intlayer_with_next-i18next.md +16 -6
  23. package/blog/en-GB/intlayer_with_next-intl.md +16 -6
  24. package/blog/en-GB/intlayer_with_react-i18next.md +16 -7
  25. package/blog/en-GB/intlayer_with_react-intl.md +14 -9
  26. package/blog/en-GB/intlayer_with_vue-i18n.md +16 -7
  27. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  28. package/blog/en-GB/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
  29. package/blog/en-GB/vue-i18n_vs_intlayer.md +2 -0
  30. package/blog/es/i18n_using_next-i18next.md +1066 -0
  31. package/blog/es/i18n_using_next-intl.md +757 -0
  32. package/blog/es/intlayer_with_react-intl.md +0 -4
  33. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  34. package/blog/fr/i18n_using_next-i18next.md +1078 -0
  35. package/blog/fr/i18n_using_next-intl.md +759 -0
  36. package/blog/fr/intlayer_with_react-intl.md +0 -4
  37. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  38. package/blog/hi/i18n_using_next-i18next.md +1068 -0
  39. package/blog/hi/i18n_using_next-intl.md +758 -0
  40. package/blog/hi/intlayer_with_react-intl.md +0 -4
  41. package/blog/hi/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  42. package/blog/id/i18n_using_next-i18next.md +1078 -0
  43. package/blog/id/i18n_using_next-intl.md +757 -0
  44. package/blog/id/index.md +69 -0
  45. package/blog/id/internationalization_and_SEO.md +364 -0
  46. package/blog/id/intlayer_with_react-intl.md +0 -4
  47. package/blog/id/list_i18n_technologies/CMS/drupal.md +143 -0
  48. package/blog/id/list_i18n_technologies/CMS/wix.md +167 -0
  49. package/blog/id/list_i18n_technologies/CMS/wordpress.md +188 -0
  50. package/blog/id/list_i18n_technologies/frameworks/angular.md +125 -0
  51. package/blog/id/list_i18n_technologies/frameworks/flutter.md +150 -0
  52. package/blog/id/list_i18n_technologies/frameworks/react-native.md +217 -0
  53. package/blog/id/list_i18n_technologies/frameworks/react.md +155 -0
  54. package/blog/id/list_i18n_technologies/frameworks/svelte.md +131 -0
  55. package/blog/id/list_i18n_technologies/frameworks/vue.md +130 -0
  56. package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +1500 -0
  57. package/blog/id/nextjs-multilingual-seo-comparison.md +361 -0
  58. package/blog/id/rag_powered_documentation_assistant.md +288 -0
  59. package/blog/id/react-i18next_vs_react-intl_vs_intlayer.md +164 -0
  60. package/blog/id/vue-i18n_vs_intlayer.md +278 -0
  61. package/blog/id/what_is_internationalization.md +166 -0
  62. package/blog/it/i18n_using_next-i18next.md +1078 -0
  63. package/blog/it/i18n_using_next-intl.md +758 -0
  64. package/blog/it/intlayer_with_react-intl.md +0 -4
  65. package/blog/it/react-i18next_vs_react-intl_vs_intlayer.md +4 -0
  66. package/blog/it/vue-i18n_vs_intlayer.md +2 -0
  67. package/blog/ja/i18n_using_next-i18next.md +1078 -0
  68. package/blog/ja/i18n_using_next-intl.md +758 -0
  69. package/blog/ja/intlayer_with_react-intl.md +0 -4
  70. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  71. package/blog/ko/i18n_using_next-i18next.md +1075 -0
  72. package/blog/ko/i18n_using_next-intl.md +759 -0
  73. package/blog/ko/intlayer_with_react-intl.md +0 -4
  74. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  75. package/blog/pl/i18n_using_next-i18next.md +1078 -0
  76. package/blog/pl/i18n_using_next-intl.md +758 -0
  77. package/blog/pl/index.md +69 -0
  78. package/blog/pl/internationalization_and_SEO.md +363 -0
  79. package/blog/pl/intlayer_with_react-intl.md +0 -4
  80. package/blog/pl/list_i18n_technologies/CMS/drupal.md +143 -0
  81. package/blog/pl/list_i18n_technologies/CMS/wix.md +167 -0
  82. package/blog/pl/list_i18n_technologies/CMS/wordpress.md +196 -0
  83. package/blog/pl/list_i18n_technologies/frameworks/angular.md +125 -0
  84. package/blog/pl/list_i18n_technologies/frameworks/flutter.md +151 -0
  85. package/blog/pl/list_i18n_technologies/frameworks/react-native.md +217 -0
  86. package/blog/pl/list_i18n_technologies/frameworks/react.md +155 -0
  87. package/blog/pl/list_i18n_technologies/frameworks/svelte.md +131 -0
  88. package/blog/pl/list_i18n_technologies/frameworks/vue.md +130 -0
  89. package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +1501 -0
  90. package/blog/pl/nextjs-multilingual-seo-comparison.md +362 -0
  91. package/blog/pl/rag_powered_documentation_assistant.md +288 -0
  92. package/blog/pl/react-i18next_vs_react-intl_vs_intlayer.md +164 -0
  93. package/blog/pl/vue-i18n_vs_intlayer.md +278 -0
  94. package/blog/pl/what_is_internationalization.md +167 -0
  95. package/blog/pt/i18n_using_next-i18next.md +1067 -0
  96. package/blog/pt/i18n_using_next-intl.md +760 -0
  97. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  98. package/blog/ru/i18n_using_next-i18next.md +1106 -0
  99. package/blog/ru/i18n_using_next-intl.md +759 -0
  100. package/blog/ru/intlayer_with_react-intl.md +0 -4
  101. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  102. package/blog/tr/i18n_using_next-i18next.md +1078 -0
  103. package/blog/tr/i18n_using_next-intl.md +760 -0
  104. package/blog/tr/intlayer_with_react-intl.md +0 -4
  105. package/blog/tr/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  106. package/blog/tr/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
  107. package/blog/tr/vue-i18n_vs_intlayer.md +2 -0
  108. package/blog/vi/i18n_using_next-i18next.md +1080 -0
  109. package/blog/vi/i18n_using_next-intl.md +758 -0
  110. package/blog/vi/index.md +69 -0
  111. package/blog/vi/internationalization_and_SEO.md +363 -0
  112. package/blog/vi/intlayer_with_react-intl.md +0 -4
  113. package/blog/vi/list_i18n_technologies/CMS/drupal.md +143 -0
  114. package/blog/vi/list_i18n_technologies/CMS/wix.md +167 -0
  115. package/blog/vi/list_i18n_technologies/CMS/wordpress.md +188 -0
  116. package/blog/vi/list_i18n_technologies/frameworks/angular.md +125 -0
  117. package/blog/vi/list_i18n_technologies/frameworks/flutter.md +150 -0
  118. package/blog/vi/list_i18n_technologies/frameworks/react-native.md +217 -0
  119. package/blog/vi/list_i18n_technologies/frameworks/react.md +155 -0
  120. package/blog/vi/list_i18n_technologies/frameworks/svelte.md +131 -0
  121. package/blog/vi/list_i18n_technologies/frameworks/vue.md +130 -0
  122. package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +1520 -0
  123. package/blog/vi/nextjs-multilingual-seo-comparison.md +362 -0
  124. package/blog/vi/rag_powered_documentation_assistant.md +288 -0
  125. package/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md +164 -0
  126. package/blog/vi/vue-i18n_vs_intlayer.md +278 -0
  127. package/blog/vi/what_is_internationalization.md +168 -0
  128. package/blog/zh/i18n_using_next-i18next.md +1105 -0
  129. package/blog/zh/i18n_using_next-intl.md +758 -0
  130. package/blog/zh/intlayer_with_react-intl.md +0 -4
  131. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  132. package/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
  133. package/dist/cjs/common.cjs +0 -4
  134. package/dist/cjs/common.cjs.map +1 -1
  135. package/dist/cjs/generated/blog.entry.cjs +38 -6
  136. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  137. package/dist/cjs/generated/docs.entry.cjs +0 -6
  138. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  139. package/dist/cjs/generated/frequentQuestions.entry.cjs +0 -6
  140. package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
  141. package/dist/cjs/generated/legal.entry.cjs +0 -6
  142. package/dist/cjs/generated/legal.entry.cjs.map +1 -1
  143. package/dist/esm/generated/blog.entry.mjs +38 -0
  144. package/dist/esm/generated/blog.entry.mjs.map +1 -1
  145. package/dist/types/generated/blog.entry.d.ts +2 -0
  146. package/dist/types/generated/blog.entry.d.ts.map +1 -1
  147. package/docs/ar/component_i18n.md +1 -1
  148. package/docs/ar/configuration.md +6 -0
  149. package/docs/ar/intlayer_cli.md +8 -3
  150. package/docs/ar/intlayer_with_next-i18next.md +619 -0
  151. package/docs/ar/intlayer_with_next-intl.md +446 -0
  152. package/docs/ar/intlayer_with_nextjs_16.md +21 -0
  153. package/docs/ar/intlayer_with_tanstack.md +4 -0
  154. package/docs/ar/intlayer_with_vite+react.md +4 -0
  155. package/docs/de/component_i18n.md +1 -1
  156. package/docs/de/configuration.md +6 -0
  157. package/docs/de/intlayer_cli.md +8 -3
  158. package/docs/de/intlayer_with_next-i18next.md +627 -0
  159. package/docs/de/intlayer_with_next-intl.md +451 -0
  160. package/docs/de/intlayer_with_nextjs_16.md +21 -0
  161. package/docs/de/intlayer_with_tanstack.md +4 -0
  162. package/docs/de/intlayer_with_vite+react.md +4 -0
  163. package/docs/en/component_i18n.md +1 -1
  164. package/docs/en/intlayer_cli.md +8 -1
  165. package/docs/en/intlayer_with_astro.md +10 -2
  166. package/docs/en/intlayer_with_create_react_app.md +8 -0
  167. package/docs/en/intlayer_with_lynx+react.md +8 -0
  168. package/docs/en/intlayer_with_nestjs.md +10 -0
  169. package/docs/en/intlayer_with_nextjs_14.md +10 -2
  170. package/docs/en/intlayer_with_nextjs_15.md +21 -4
  171. package/docs/en/intlayer_with_nextjs_16.md +17 -0
  172. package/docs/en/intlayer_with_nuxt.md +8 -0
  173. package/docs/en/intlayer_with_react_native+expo.md +10 -2
  174. package/docs/en/intlayer_with_react_router_v7.md +8 -0
  175. package/docs/en/intlayer_with_tanstack.md +10 -0
  176. package/docs/en/intlayer_with_vite+preact.md +10 -2
  177. package/docs/en/intlayer_with_vite+react.md +21 -4
  178. package/docs/en/intlayer_with_vite+vue.md +10 -2
  179. package/docs/en-GB/component_i18n.md +1 -1
  180. package/docs/en-GB/configuration.md +6 -0
  181. package/docs/en-GB/intlayer_cli.md +8 -3
  182. package/docs/en-GB/intlayer_with_angular.md +4 -4
  183. package/docs/en-GB/intlayer_with_express.md +4 -4
  184. package/docs/en-GB/intlayer_with_lynx+react.md +12 -12
  185. package/{blog/en/_intlayer_with_next-i18next.md → docs/en-GB/intlayer_with_next-i18next.md} +241 -42
  186. package/{blog/en/_intlayer_with_next-intl.md → docs/en-GB/intlayer_with_next-intl.md} +144 -29
  187. package/docs/en-GB/intlayer_with_nextjs_16.md +21 -0
  188. package/docs/en-GB/intlayer_with_tanstack.md +5 -1
  189. package/docs/en-GB/intlayer_with_vite+react.md +4 -0
  190. package/docs/en-GB/packages/next-intlayer/t.md +2 -2
  191. package/docs/es/component_i18n.md +1 -1
  192. package/docs/es/configuration.md +6 -0
  193. package/docs/es/intlayer_cli.md +8 -3
  194. package/docs/es/intlayer_with_next-i18next.md +628 -0
  195. package/docs/es/intlayer_with_next-intl.md +446 -0
  196. package/docs/es/intlayer_with_nextjs_16.md +21 -0
  197. package/docs/es/intlayer_with_tanstack.md +4 -0
  198. package/docs/es/intlayer_with_vite+react.md +4 -0
  199. package/docs/fr/configuration.md +6 -0
  200. package/docs/fr/intlayer_cli.md +8 -3
  201. package/docs/fr/intlayer_with_next-i18next.md +628 -0
  202. package/docs/fr/intlayer_with_next-intl.md +446 -0
  203. package/docs/fr/intlayer_with_nextjs_16.md +23 -2
  204. package/docs/fr/intlayer_with_tanstack.md +4 -0
  205. package/docs/fr/intlayer_with_vite+react.md +4 -0
  206. package/docs/hi/component_i18n.md +1 -1
  207. package/docs/hi/configuration.md +6 -0
  208. package/docs/hi/intlayer_cli.md +8 -0
  209. package/docs/hi/intlayer_with_next-i18next.md +628 -0
  210. package/docs/hi/intlayer_with_next-intl.md +446 -0
  211. package/docs/hi/intlayer_with_nextjs_16.md +21 -0
  212. package/docs/hi/intlayer_with_tanstack.md +4 -0
  213. package/docs/hi/intlayer_with_vite+react.md +4 -0
  214. package/docs/id/CI_CD.md +198 -0
  215. package/docs/id/autoFill.md +284 -0
  216. package/docs/id/component_i18n.md +186 -0
  217. package/docs/id/configuration.md +710 -0
  218. package/docs/id/dictionary/condition.md +231 -0
  219. package/docs/id/dictionary/content_file.md +1092 -0
  220. package/docs/id/dictionary/enumeration.md +245 -0
  221. package/docs/id/dictionary/file.md +237 -0
  222. package/docs/id/dictionary/function_fetching.md +214 -0
  223. package/docs/id/dictionary/gender.md +273 -0
  224. package/docs/id/dictionary/insertion.md +192 -0
  225. package/docs/id/dictionary/markdown.md +381 -0
  226. package/docs/id/dictionary/nesting.md +273 -0
  227. package/docs/id/dictionary/translation.md +310 -0
  228. package/docs/id/formatters.md +596 -0
  229. package/docs/id/how_works_intlayer.md +256 -0
  230. package/docs/id/index.md +176 -0
  231. package/docs/id/interest_of_intlayer.md +293 -0
  232. package/docs/id/intlayer_CMS.md +549 -0
  233. package/docs/id/intlayer_cli.md +850 -0
  234. package/docs/id/intlayer_visual_editor.md +288 -0
  235. package/docs/id/intlayer_with_angular.md +694 -0
  236. package/docs/id/intlayer_with_astro.md +252 -0
  237. package/docs/id/intlayer_with_create_react_app.md +1233 -0
  238. package/docs/id/intlayer_with_express.md +411 -0
  239. package/docs/id/intlayer_with_lynx+react.md +518 -0
  240. package/docs/id/intlayer_with_nestjs.md +272 -0
  241. package/docs/id/intlayer_with_next-i18next.md +628 -0
  242. package/docs/id/intlayer_with_next-intl.md +446 -0
  243. package/docs/id/intlayer_with_nextjs_14.md +1617 -0
  244. package/docs/id/intlayer_with_nextjs_15.md +1698 -0
  245. package/docs/id/intlayer_with_nextjs_16.md +21 -0
  246. package/docs/id/intlayer_with_nextjs_page_router.md +1478 -0
  247. package/docs/id/intlayer_with_nuxt.md +808 -0
  248. package/docs/id/intlayer_with_react_native+expo.md +699 -0
  249. package/docs/id/intlayer_with_react_router_v7.md +496 -0
  250. package/docs/id/intlayer_with_tanstack.md +564 -0
  251. package/docs/id/intlayer_with_vite+preact.md +1737 -0
  252. package/docs/id/intlayer_with_vite+react.md +1413 -0
  253. package/docs/id/intlayer_with_vite+solid.md +289 -0
  254. package/docs/id/intlayer_with_vite+svelte.md +289 -0
  255. package/docs/id/intlayer_with_vite+vue.md +1088 -0
  256. package/docs/id/introduction.md +218 -0
  257. package/docs/id/locale_mapper.md +242 -0
  258. package/docs/id/mcp_server.md +211 -0
  259. package/docs/id/packages/express-intlayer/t.md +458 -0
  260. package/docs/id/packages/intlayer/getConfiguration.md +145 -0
  261. package/docs/id/packages/intlayer/getEnumeration.md +159 -0
  262. package/docs/id/packages/intlayer/getHTMLTextDir.md +122 -0
  263. package/docs/id/packages/intlayer/getLocaleLang.md +81 -0
  264. package/docs/id/packages/intlayer/getLocaleName.md +119 -0
  265. package/docs/id/packages/intlayer/getLocalizedUrl.md +309 -0
  266. package/docs/id/packages/intlayer/getMultilingualUrls.md +223 -0
  267. package/docs/id/packages/intlayer/getPathWithoutLocale.md +75 -0
  268. package/docs/id/packages/intlayer/getTranslation.md +190 -0
  269. package/docs/id/packages/intlayer/getTranslationContent.md +188 -0
  270. package/docs/id/packages/next-intlayer/t.md +352 -0
  271. package/docs/id/packages/next-intlayer/useDictionary.md +271 -0
  272. package/docs/id/packages/next-intlayer/useIntlayer.md +264 -0
  273. package/docs/id/packages/next-intlayer/useLocale.md +166 -0
  274. package/docs/id/packages/react-intlayer/t.md +303 -0
  275. package/docs/id/packages/react-intlayer/useDictionary.md +287 -0
  276. package/docs/id/packages/react-intlayer/useI18n.md +267 -0
  277. package/docs/id/packages/react-intlayer/useIntlayer.md +254 -0
  278. package/docs/id/packages/react-intlayer/useLocale.md +210 -0
  279. package/docs/id/per_locale_file.md +323 -0
  280. package/docs/id/readme.md +261 -0
  281. package/docs/id/releases/v6.md +305 -0
  282. package/docs/id/roadmap.md +362 -0
  283. package/docs/id/testing.md +202 -0
  284. package/docs/id/vs_code_extension.md +126 -0
  285. package/docs/it/component_i18n.md +1 -1
  286. package/docs/it/configuration.md +6 -0
  287. package/docs/it/intlayer_cli.md +8 -3
  288. package/docs/it/intlayer_with_next-i18next.md +628 -0
  289. package/docs/it/intlayer_with_next-intl.md +446 -0
  290. package/docs/it/intlayer_with_nextjs_16.md +21 -0
  291. package/docs/it/intlayer_with_tanstack.md +4 -0
  292. package/docs/it/intlayer_with_vite+react.md +4 -0
  293. package/docs/ja/component_i18n.md +1 -1
  294. package/docs/ja/configuration.md +6 -0
  295. package/docs/ja/intlayer_cli.md +8 -3
  296. package/docs/ja/intlayer_with_next-i18next.md +627 -0
  297. package/docs/ja/intlayer_with_next-intl.md +446 -0
  298. package/docs/ja/intlayer_with_nextjs_16.md +21 -0
  299. package/docs/ja/intlayer_with_tanstack.md +4 -0
  300. package/docs/ja/intlayer_with_vite+react.md +4 -0
  301. package/docs/ko/configuration.md +6 -0
  302. package/docs/ko/intlayer_cli.md +8 -3
  303. package/docs/ko/intlayer_with_next-i18next.md +627 -0
  304. package/docs/ko/intlayer_with_next-intl.md +446 -0
  305. package/docs/ko/intlayer_with_nextjs_16.md +21 -0
  306. package/docs/ko/intlayer_with_tanstack.md +4 -0
  307. package/docs/ko/intlayer_with_vite+react.md +4 -0
  308. package/docs/pl/CI_CD.md +198 -0
  309. package/docs/pl/autoFill.md +284 -0
  310. package/docs/pl/component_i18n.md +186 -0
  311. package/docs/pl/configuration.md +710 -0
  312. package/docs/pl/dictionary/condition.md +232 -0
  313. package/docs/pl/dictionary/content_file.md +1130 -0
  314. package/docs/pl/dictionary/enumeration.md +245 -0
  315. package/docs/pl/dictionary/file.md +234 -0
  316. package/docs/pl/dictionary/function_fetching.md +214 -0
  317. package/docs/pl/dictionary/gender.md +276 -0
  318. package/docs/pl/dictionary/insertion.md +188 -0
  319. package/docs/pl/dictionary/markdown.md +408 -0
  320. package/docs/pl/dictionary/nesting.md +273 -0
  321. package/docs/pl/dictionary/translation.md +310 -0
  322. package/docs/pl/formatters.md +596 -0
  323. package/docs/pl/how_works_intlayer.md +256 -0
  324. package/docs/pl/index.md +176 -0
  325. package/docs/pl/interest_of_intlayer.md +291 -0
  326. package/docs/pl/intlayer_CMS.md +549 -0
  327. package/docs/pl/intlayer_cli.md +857 -0
  328. package/docs/pl/intlayer_visual_editor.md +288 -0
  329. package/docs/pl/intlayer_with_angular.md +690 -0
  330. package/docs/pl/intlayer_with_astro.md +280 -0
  331. package/docs/pl/intlayer_with_create_react_app.md +1235 -0
  332. package/docs/pl/intlayer_with_express.md +411 -0
  333. package/docs/pl/intlayer_with_lynx+react.md +518 -0
  334. package/docs/pl/intlayer_with_nestjs.md +272 -0
  335. package/docs/pl/intlayer_with_next-i18next.md +628 -0
  336. package/docs/pl/intlayer_with_next-intl.md +446 -0
  337. package/docs/pl/intlayer_with_nextjs_14.md +1594 -0
  338. package/docs/pl/intlayer_with_nextjs_15.md +1701 -0
  339. package/docs/pl/intlayer_with_nextjs_16.md +21 -0
  340. package/docs/pl/intlayer_with_nextjs_page_router.md +1513 -0
  341. package/docs/pl/intlayer_with_nuxt.md +885 -0
  342. package/docs/pl/intlayer_with_react_native+expo.md +698 -0
  343. package/docs/pl/intlayer_with_react_router_v7.md +503 -0
  344. package/docs/pl/intlayer_with_tanstack.md +562 -0
  345. package/docs/pl/intlayer_with_vite+preact.md +1736 -0
  346. package/docs/pl/intlayer_with_vite+react.md +1438 -0
  347. package/docs/pl/intlayer_with_vite+solid.md +290 -0
  348. package/docs/pl/intlayer_with_vite+svelte.md +289 -0
  349. package/docs/pl/intlayer_with_vite+vue.md +1116 -0
  350. package/docs/pl/introduction.md +209 -0
  351. package/docs/pl/locale_mapper.md +242 -0
  352. package/docs/pl/mcp_server.md +211 -0
  353. package/docs/pl/packages/express-intlayer/t.md +458 -0
  354. package/docs/pl/packages/intlayer/getConfiguration.md +146 -0
  355. package/docs/pl/packages/intlayer/getEnumeration.md +160 -0
  356. package/docs/pl/packages/intlayer/getHTMLTextDir.md +121 -0
  357. package/docs/pl/packages/intlayer/getLocaleLang.md +81 -0
  358. package/docs/pl/packages/intlayer/getLocaleName.md +118 -0
  359. package/docs/pl/packages/intlayer/getLocalizedUrl.md +300 -0
  360. package/docs/pl/packages/intlayer/getMultilingualUrls.md +221 -0
  361. package/docs/pl/packages/intlayer/getPathWithoutLocale.md +75 -0
  362. package/docs/pl/packages/intlayer/getTranslation.md +190 -0
  363. package/docs/pl/packages/intlayer/getTranslationContent.md +189 -0
  364. package/docs/pl/packages/next-intlayer/t.md +353 -0
  365. package/docs/pl/packages/next-intlayer/useDictionary.md +270 -0
  366. package/docs/pl/packages/next-intlayer/useIntlayer.md +263 -0
  367. package/docs/pl/packages/next-intlayer/useLocale.md +166 -0
  368. package/docs/pl/packages/react-intlayer/t.md +303 -0
  369. package/docs/pl/packages/react-intlayer/useDictionary.md +289 -0
  370. package/docs/pl/packages/react-intlayer/useI18n.md +249 -0
  371. package/docs/pl/packages/react-intlayer/useIntlayer.md +256 -0
  372. package/docs/pl/packages/react-intlayer/useLocale.md +210 -0
  373. package/docs/pl/per_locale_file.md +321 -0
  374. package/docs/pl/readme.md +261 -0
  375. package/docs/pl/releases/v6.md +305 -0
  376. package/docs/pl/roadmap.md +362 -0
  377. package/docs/pl/testing.md +202 -0
  378. package/docs/pl/vs_code_extension.md +126 -0
  379. package/docs/pt/component_i18n.md +1 -1
  380. package/docs/pt/configuration.md +6 -0
  381. package/docs/pt/intlayer_cli.md +8 -3
  382. package/docs/pt/intlayer_with_next-i18next.md +627 -0
  383. package/docs/pt/intlayer_with_next-intl.md +446 -0
  384. package/docs/pt/intlayer_with_nextjs_16.md +21 -0
  385. package/docs/pt/intlayer_with_tanstack.md +4 -0
  386. package/docs/pt/intlayer_with_vite+react.md +4 -0
  387. package/docs/ru/component_i18n.md +1 -1
  388. package/docs/ru/configuration.md +6 -0
  389. package/docs/ru/intlayer_cli.md +301 -22
  390. package/docs/ru/intlayer_with_next-i18next.md +629 -0
  391. package/docs/ru/intlayer_with_next-intl.md +448 -0
  392. package/docs/ru/intlayer_with_nextjs_16.md +21 -0
  393. package/docs/ru/intlayer_with_tanstack.md +4 -0
  394. package/docs/ru/intlayer_with_vite+react.md +4 -0
  395. package/docs/tr/component_i18n.md +1 -1
  396. package/docs/tr/configuration.md +6 -0
  397. package/docs/tr/intlayer_cli.md +8 -0
  398. package/docs/tr/intlayer_with_next-i18next.md +627 -0
  399. package/docs/tr/intlayer_with_next-intl.md +446 -0
  400. package/docs/tr/intlayer_with_nextjs_16.md +21 -0
  401. package/docs/tr/intlayer_with_tanstack.md +4 -0
  402. package/docs/tr/intlayer_with_vite+react.md +4 -0
  403. package/docs/vi/CI_CD.md +198 -0
  404. package/docs/vi/autoFill.md +284 -0
  405. package/docs/vi/component_i18n.md +186 -0
  406. package/docs/vi/configuration.md +710 -0
  407. package/docs/vi/dictionary/condition.md +237 -0
  408. package/docs/vi/dictionary/content_file.md +1115 -0
  409. package/docs/vi/dictionary/enumeration.md +255 -0
  410. package/docs/vi/dictionary/file.md +234 -0
  411. package/docs/vi/dictionary/function_fetching.md +212 -0
  412. package/docs/vi/dictionary/gender.md +275 -0
  413. package/docs/vi/dictionary/insertion.md +191 -0
  414. package/docs/vi/dictionary/markdown.md +381 -0
  415. package/docs/vi/dictionary/nesting.md +273 -0
  416. package/docs/vi/dictionary/translation.md +309 -0
  417. package/docs/vi/formatters.md +595 -0
  418. package/docs/vi/how_works_intlayer.md +256 -0
  419. package/docs/vi/index.md +174 -0
  420. package/docs/vi/interest_of_intlayer.md +292 -0
  421. package/docs/vi/intlayer_CMS.md +549 -0
  422. package/docs/vi/intlayer_cli.md +850 -0
  423. package/docs/vi/intlayer_visual_editor.md +288 -0
  424. package/docs/vi/intlayer_with_angular.md +692 -0
  425. package/docs/vi/intlayer_with_astro.md +252 -0
  426. package/docs/vi/intlayer_with_create_react_app.md +1230 -0
  427. package/docs/vi/intlayer_with_express.md +409 -0
  428. package/docs/vi/intlayer_with_lynx+react.md +520 -0
  429. package/docs/vi/intlayer_with_nestjs.md +272 -0
  430. package/docs/vi/intlayer_with_next-i18next.md +628 -0
  431. package/docs/vi/intlayer_with_next-intl.md +446 -0
  432. package/docs/vi/intlayer_with_nextjs_14.md +1584 -0
  433. package/docs/vi/intlayer_with_nextjs_15.md +1738 -0
  434. package/docs/vi/intlayer_with_nextjs_16.md +21 -0
  435. package/docs/vi/intlayer_with_nextjs_page_router.md +1504 -0
  436. package/docs/vi/intlayer_with_nuxt.md +821 -0
  437. package/docs/vi/intlayer_with_react_native+expo.md +700 -0
  438. package/docs/vi/intlayer_with_react_router_v7.md +498 -0
  439. package/docs/vi/intlayer_with_tanstack.md +562 -0
  440. package/docs/vi/intlayer_with_vite+preact.md +1722 -0
  441. package/docs/vi/intlayer_with_vite+react.md +1407 -0
  442. package/docs/vi/intlayer_with_vite+solid.md +287 -0
  443. package/docs/vi/intlayer_with_vite+svelte.md +289 -0
  444. package/docs/vi/intlayer_with_vite+vue.md +1071 -0
  445. package/docs/vi/introduction.md +215 -0
  446. package/docs/vi/locale_mapper.md +242 -0
  447. package/docs/vi/mcp_server.md +211 -0
  448. package/docs/vi/packages/express-intlayer/t.md +457 -0
  449. package/docs/vi/packages/intlayer/getConfiguration.md +145 -0
  450. package/docs/vi/packages/intlayer/getEnumeration.md +162 -0
  451. package/docs/vi/packages/intlayer/getHTMLTextDir.md +121 -0
  452. package/docs/vi/packages/intlayer/getLocaleLang.md +81 -0
  453. package/docs/vi/packages/intlayer/getLocaleName.md +129 -0
  454. package/docs/vi/packages/intlayer/getLocalizedUrl.md +309 -0
  455. package/docs/vi/packages/intlayer/getMultilingualUrls.md +221 -0
  456. package/docs/vi/packages/intlayer/getPathWithoutLocale.md +75 -0
  457. package/docs/vi/packages/intlayer/getTranslation.md +201 -0
  458. package/docs/vi/packages/intlayer/getTranslationContent.md +188 -0
  459. package/docs/vi/packages/next-intlayer/t.md +352 -0
  460. package/docs/vi/packages/next-intlayer/useDictionary.md +273 -0
  461. package/docs/vi/packages/next-intlayer/useIntlayer.md +264 -0
  462. package/docs/vi/packages/next-intlayer/useLocale.md +166 -0
  463. package/docs/vi/packages/react-intlayer/t.md +304 -0
  464. package/docs/vi/packages/react-intlayer/useDictionary.md +288 -0
  465. package/docs/vi/packages/react-intlayer/useI18n.md +295 -0
  466. package/docs/vi/packages/react-intlayer/useIntlayer.md +256 -0
  467. package/docs/vi/packages/react-intlayer/useLocale.md +210 -0
  468. package/docs/vi/per_locale_file.md +326 -0
  469. package/docs/vi/readme.md +261 -0
  470. package/docs/vi/releases/v6.md +305 -0
  471. package/docs/vi/roadmap.md +346 -0
  472. package/docs/vi/testing.md +202 -0
  473. package/docs/vi/vs_code_extension.md +126 -0
  474. package/docs/zh/configuration.md +6 -0
  475. package/docs/zh/intlayer_cli.md +8 -3
  476. package/docs/zh/intlayer_with_next-i18next.md +628 -0
  477. package/docs/zh/intlayer_with_next-intl.md +448 -0
  478. package/docs/zh/intlayer_with_nextjs_16.md +21 -0
  479. package/docs/zh/intlayer_with_tanstack.md +4 -0
  480. package/docs/zh/intlayer_with_vite+react.md +4 -0
  481. package/frequent_questions/ar/SSR_Next_no_[locale].md +1 -2
  482. package/frequent_questions/ar/array_as_content_declaration.md +1 -2
  483. package/frequent_questions/ar/build_dictionaries.md +1 -2
  484. package/frequent_questions/ar/build_error_CI_CD.md +1 -2
  485. package/frequent_questions/ar/bun_set_up.md +1 -2
  486. package/frequent_questions/ar/customized_locale_list.md +1 -2
  487. package/frequent_questions/ar/domain_routing.md +1 -2
  488. package/frequent_questions/ar/esbuild_error.md +1 -2
  489. package/frequent_questions/ar/get_locale_cookie.md +1 -2
  490. package/frequent_questions/ar/intlayer_command_undefined.md +1 -2
  491. package/frequent_questions/ar/locale_incorect_in_url.md +1 -2
  492. package/frequent_questions/ar/static_rendering.md +1 -3
  493. package/frequent_questions/ar/translated_path_url.md +1 -2
  494. package/frequent_questions/ar/unknown_command.md +1 -2
  495. package/frequent_questions/de/SSR_Next_no_[locale].md +1 -2
  496. package/frequent_questions/de/array_as_content_declaration.md +1 -2
  497. package/frequent_questions/de/build_dictionaries.md +1 -2
  498. package/frequent_questions/de/build_error_CI_CD.md +1 -2
  499. package/frequent_questions/de/bun_set_up.md +1 -2
  500. package/frequent_questions/de/customized_locale_list.md +1 -2
  501. package/frequent_questions/de/domain_routing.md +1 -2
  502. package/frequent_questions/de/esbuild_error.md +1 -2
  503. package/frequent_questions/de/get_locale_cookie.md +1 -2
  504. package/frequent_questions/de/intlayer_command_undefined.md +1 -2
  505. package/frequent_questions/de/locale_incorect_in_url.md +1 -2
  506. package/frequent_questions/de/static_rendering.md +1 -3
  507. package/frequent_questions/de/translated_path_url.md +1 -2
  508. package/frequent_questions/de/unknown_command.md +1 -2
  509. package/frequent_questions/en/SSR_Next_no_[locale].md +1 -2
  510. package/frequent_questions/en/array_as_content_declaration.md +1 -2
  511. package/frequent_questions/en/build_dictionaries.md +1 -2
  512. package/frequent_questions/en/build_error_CI_CD.md +1 -2
  513. package/frequent_questions/en/bun_set_up.md +1 -2
  514. package/frequent_questions/en/customized_locale_list.md +1 -2
  515. package/frequent_questions/en/domain_routing.md +1 -2
  516. package/frequent_questions/en/esbuild_error.md +1 -2
  517. package/frequent_questions/en/get_locale_cookie.md +1 -2
  518. package/frequent_questions/en/intlayer_command_undefined.md +1 -2
  519. package/frequent_questions/en/locale_incorect_in_url.md +1 -2
  520. package/frequent_questions/en/static_rendering.md +1 -3
  521. package/frequent_questions/en/translated_path_url.md +1 -2
  522. package/frequent_questions/en/unknown_command.md +1 -2
  523. package/frequent_questions/en-GB/SSR_Next_no_[locale].md +1 -2
  524. package/frequent_questions/en-GB/array_as_content_declaration.md +1 -2
  525. package/frequent_questions/en-GB/build_dictionaries.md +1 -2
  526. package/frequent_questions/en-GB/build_error_CI_CD.md +1 -2
  527. package/frequent_questions/en-GB/bun_set_up.md +1 -2
  528. package/frequent_questions/en-GB/customized_locale_list.md +1 -2
  529. package/frequent_questions/en-GB/domain_routing.md +1 -2
  530. package/frequent_questions/en-GB/esbuild_error.md +1 -2
  531. package/frequent_questions/en-GB/get_locale_cookie.md +1 -2
  532. package/frequent_questions/en-GB/intlayer_command_undefined.md +1 -2
  533. package/frequent_questions/en-GB/locale_incorect_in_url.md +1 -2
  534. package/frequent_questions/en-GB/static_rendering.md +1 -3
  535. package/frequent_questions/en-GB/translated_path_url.md +1 -2
  536. package/frequent_questions/en-GB/unknown_command.md +1 -2
  537. package/frequent_questions/es/SSR_Next_no_[locale].md +1 -2
  538. package/frequent_questions/es/array_as_content_declaration.md +1 -2
  539. package/frequent_questions/es/build_dictionaries.md +1 -2
  540. package/frequent_questions/es/build_error_CI_CD.md +1 -2
  541. package/frequent_questions/es/bun_set_up.md +1 -2
  542. package/frequent_questions/es/customized_locale_list.md +1 -2
  543. package/frequent_questions/es/domain_routing.md +1 -2
  544. package/frequent_questions/es/esbuild_error.md +1 -2
  545. package/frequent_questions/es/get_locale_cookie.md +1 -2
  546. package/frequent_questions/es/intlayer_command_undefined.md +1 -2
  547. package/frequent_questions/es/locale_incorect_in_url.md +1 -2
  548. package/frequent_questions/es/static_rendering.md +1 -3
  549. package/frequent_questions/es/translated_path_url.md +1 -2
  550. package/frequent_questions/es/unknown_command.md +1 -2
  551. package/frequent_questions/fr/SSR_Next_no_[locale].md +1 -2
  552. package/frequent_questions/fr/array_as_content_declaration.md +1 -2
  553. package/frequent_questions/fr/build_dictionaries.md +1 -2
  554. package/frequent_questions/fr/build_error_CI_CD.md +1 -2
  555. package/frequent_questions/fr/bun_set_up.md +1 -2
  556. package/frequent_questions/fr/customized_locale_list.md +1 -2
  557. package/frequent_questions/fr/domain_routing.md +1 -2
  558. package/frequent_questions/fr/esbuild_error.md +1 -2
  559. package/frequent_questions/fr/get_locale_cookie.md +1 -2
  560. package/frequent_questions/fr/intlayer_command_undefined.md +1 -2
  561. package/frequent_questions/fr/locale_incorect_in_url.md +1 -2
  562. package/frequent_questions/fr/static_rendering.md +1 -3
  563. package/frequent_questions/fr/translated_path_url.md +1 -2
  564. package/frequent_questions/fr/unknown_command.md +1 -2
  565. package/frequent_questions/hi/SSR_Next_no_[locale].md +1 -2
  566. package/frequent_questions/hi/array_as_content_declaration.md +1 -2
  567. package/frequent_questions/hi/build_dictionaries.md +1 -2
  568. package/frequent_questions/hi/build_error_CI_CD.md +1 -2
  569. package/frequent_questions/hi/bun_set_up.md +1 -2
  570. package/frequent_questions/hi/customized_locale_list.md +1 -2
  571. package/frequent_questions/hi/domain_routing.md +1 -2
  572. package/frequent_questions/hi/esbuild_error.md +1 -2
  573. package/frequent_questions/hi/get_locale_cookie.md +1 -2
  574. package/frequent_questions/hi/intlayer_command_undefined.md +1 -2
  575. package/frequent_questions/hi/locale_incorect_in_url.md +1 -2
  576. package/frequent_questions/hi/static_rendering.md +1 -3
  577. package/frequent_questions/hi/translated_path_url.md +1 -2
  578. package/frequent_questions/hi/unknown_command.md +1 -2
  579. package/frequent_questions/id/SSR_Next_no_[locale].md +104 -0
  580. package/frequent_questions/id/array_as_content_declaration.md +71 -0
  581. package/frequent_questions/id/build_dictionaries.md +58 -0
  582. package/frequent_questions/id/build_error_CI_CD.md +74 -0
  583. package/frequent_questions/id/bun_set_up.md +53 -0
  584. package/frequent_questions/id/customized_locale_list.md +64 -0
  585. package/frequent_questions/id/domain_routing.md +113 -0
  586. package/frequent_questions/id/esbuild_error.md +29 -0
  587. package/frequent_questions/id/get_locale_cookie.md +142 -0
  588. package/frequent_questions/id/intlayer_command_undefined.md +155 -0
  589. package/frequent_questions/id/locale_incorect_in_url.md +73 -0
  590. package/frequent_questions/id/static_rendering.md +44 -0
  591. package/frequent_questions/id/translated_path_url.md +55 -0
  592. package/frequent_questions/id/unknown_command.md +97 -0
  593. package/frequent_questions/it/SSR_Next_no_[locale].md +1 -2
  594. package/frequent_questions/it/array_as_content_declaration.md +1 -2
  595. package/frequent_questions/it/build_dictionaries.md +1 -2
  596. package/frequent_questions/it/build_error_CI_CD.md +1 -2
  597. package/frequent_questions/it/bun_set_up.md +1 -2
  598. package/frequent_questions/it/customized_locale_list.md +1 -2
  599. package/frequent_questions/it/domain_routing.md +1 -2
  600. package/frequent_questions/it/esbuild_error.md +1 -2
  601. package/frequent_questions/it/get_locale_cookie.md +1 -2
  602. package/frequent_questions/it/intlayer_command_undefined.md +1 -2
  603. package/frequent_questions/it/locale_incorect_in_url.md +1 -2
  604. package/frequent_questions/it/static_rendering.md +1 -3
  605. package/frequent_questions/it/translated_path_url.md +1 -2
  606. package/frequent_questions/it/unknown_command.md +1 -2
  607. package/frequent_questions/ja/SSR_Next_no_[locale].md +1 -2
  608. package/frequent_questions/ja/array_as_content_declaration.md +1 -2
  609. package/frequent_questions/ja/build_dictionaries.md +1 -2
  610. package/frequent_questions/ja/build_error_CI_CD.md +1 -2
  611. package/frequent_questions/ja/bun_set_up.md +1 -2
  612. package/frequent_questions/ja/customized_locale_list.md +1 -2
  613. package/frequent_questions/ja/domain_routing.md +1 -2
  614. package/frequent_questions/ja/esbuild_error.md +1 -2
  615. package/frequent_questions/ja/get_locale_cookie.md +1 -2
  616. package/frequent_questions/ja/intlayer_command_undefined.md +1 -2
  617. package/frequent_questions/ja/locale_incorect_in_url.md +1 -2
  618. package/frequent_questions/ja/static_rendering.md +1 -3
  619. package/frequent_questions/ja/translated_path_url.md +1 -2
  620. package/frequent_questions/ja/unknown_command.md +1 -2
  621. package/frequent_questions/ko/SSR_Next_no_[locale].md +1 -2
  622. package/frequent_questions/ko/array_as_content_declaration.md +1 -2
  623. package/frequent_questions/ko/build_dictionaries.md +1 -2
  624. package/frequent_questions/ko/build_error_CI_CD.md +1 -2
  625. package/frequent_questions/ko/bun_set_up.md +1 -2
  626. package/frequent_questions/ko/customized_locale_list.md +1 -2
  627. package/frequent_questions/ko/domain_routing.md +1 -2
  628. package/frequent_questions/ko/esbuild_error.md +1 -2
  629. package/frequent_questions/ko/get_locale_cookie.md +1 -2
  630. package/frequent_questions/ko/intlayer_command_undefined.md +1 -2
  631. package/frequent_questions/ko/locale_incorect_in_url.md +1 -2
  632. package/frequent_questions/ko/static_rendering.md +1 -3
  633. package/frequent_questions/ko/translated_path_url.md +1 -2
  634. package/frequent_questions/ko/unknown_command.md +1 -2
  635. package/frequent_questions/pl/SSR_Next_no_[locale].md +104 -0
  636. package/frequent_questions/pl/array_as_content_declaration.md +71 -0
  637. package/frequent_questions/pl/build_dictionaries.md +58 -0
  638. package/frequent_questions/pl/build_error_CI_CD.md +74 -0
  639. package/frequent_questions/pl/bun_set_up.md +54 -0
  640. package/frequent_questions/pl/customized_locale_list.md +64 -0
  641. package/frequent_questions/pl/domain_routing.md +113 -0
  642. package/frequent_questions/pl/esbuild_error.md +29 -0
  643. package/frequent_questions/pl/get_locale_cookie.md +142 -0
  644. package/frequent_questions/pl/intlayer_command_undefined.md +155 -0
  645. package/frequent_questions/pl/locale_incorect_in_url.md +73 -0
  646. package/frequent_questions/pl/static_rendering.md +44 -0
  647. package/frequent_questions/pl/translated_path_url.md +55 -0
  648. package/frequent_questions/pl/unknown_command.md +97 -0
  649. package/frequent_questions/pt/SSR_Next_no_[locale].md +1 -2
  650. package/frequent_questions/pt/array_as_content_declaration.md +1 -2
  651. package/frequent_questions/pt/build_dictionaries.md +1 -2
  652. package/frequent_questions/pt/build_error_CI_CD.md +1 -2
  653. package/frequent_questions/pt/bun_set_up.md +1 -2
  654. package/frequent_questions/pt/customized_locale_list.md +1 -2
  655. package/frequent_questions/pt/domain_routing.md +1 -2
  656. package/frequent_questions/pt/esbuild_error.md +1 -2
  657. package/frequent_questions/pt/get_locale_cookie.md +1 -2
  658. package/frequent_questions/pt/intlayer_command_undefined.md +1 -2
  659. package/frequent_questions/pt/locale_incorect_in_url.md +1 -2
  660. package/frequent_questions/pt/static_rendering.md +1 -3
  661. package/frequent_questions/pt/translated_path_url.md +1 -2
  662. package/frequent_questions/pt/unknown_command.md +1 -2
  663. package/frequent_questions/ru/SSR_Next_no_[locale].md +1 -2
  664. package/frequent_questions/ru/array_as_content_declaration.md +1 -2
  665. package/frequent_questions/ru/build_dictionaries.md +1 -2
  666. package/frequent_questions/ru/build_error_CI_CD.md +1 -2
  667. package/frequent_questions/ru/bun_set_up.md +1 -2
  668. package/frequent_questions/ru/customized_locale_list.md +1 -2
  669. package/frequent_questions/ru/domain_routing.md +1 -2
  670. package/frequent_questions/ru/esbuild_error.md +1 -2
  671. package/frequent_questions/ru/get_locale_cookie.md +1 -2
  672. package/frequent_questions/ru/intlayer_command_undefined.md +1 -2
  673. package/frequent_questions/ru/locale_incorect_in_url.md +1 -2
  674. package/frequent_questions/ru/static_rendering.md +1 -2
  675. package/frequent_questions/ru/translated_path_url.md +1 -2
  676. package/frequent_questions/ru/unknown_command.md +1 -2
  677. package/frequent_questions/tr/SSR_Next_no_[locale].md +1 -2
  678. package/frequent_questions/tr/array_as_content_declaration.md +1 -2
  679. package/frequent_questions/tr/build_dictionaries.md +1 -2
  680. package/frequent_questions/tr/build_error_CI_CD.md +1 -2
  681. package/frequent_questions/tr/bun_set_up.md +1 -2
  682. package/frequent_questions/tr/customized_locale_list.md +1 -2
  683. package/frequent_questions/tr/domain_routing.md +1 -2
  684. package/frequent_questions/tr/esbuild_error.md +1 -2
  685. package/frequent_questions/tr/get_locale_cookie.md +1 -2
  686. package/frequent_questions/tr/intlayer_command_undefined.md +1 -2
  687. package/frequent_questions/tr/locale_incorect_in_url.md +1 -2
  688. package/frequent_questions/tr/static_rendering.md +1 -2
  689. package/frequent_questions/tr/translated_path_url.md +1 -2
  690. package/frequent_questions/tr/unknown_command.md +1 -2
  691. package/frequent_questions/vi/SSR_Next_no_[locale].md +106 -0
  692. package/frequent_questions/vi/array_as_content_declaration.md +71 -0
  693. package/frequent_questions/vi/build_dictionaries.md +58 -0
  694. package/frequent_questions/vi/build_error_CI_CD.md +74 -0
  695. package/frequent_questions/vi/bun_set_up.md +53 -0
  696. package/frequent_questions/vi/customized_locale_list.md +64 -0
  697. package/frequent_questions/vi/domain_routing.md +113 -0
  698. package/frequent_questions/vi/esbuild_error.md +29 -0
  699. package/frequent_questions/vi/get_locale_cookie.md +142 -0
  700. package/frequent_questions/vi/intlayer_command_undefined.md +155 -0
  701. package/frequent_questions/vi/locale_incorect_in_url.md +73 -0
  702. package/frequent_questions/vi/static_rendering.md +44 -0
  703. package/frequent_questions/vi/translated_path_url.md +55 -0
  704. package/frequent_questions/vi/unknown_command.md +97 -0
  705. package/frequent_questions/zh/SSR_Next_no_[locale].md +1 -2
  706. package/frequent_questions/zh/array_as_content_declaration.md +1 -2
  707. package/frequent_questions/zh/build_dictionaries.md +1 -2
  708. package/frequent_questions/zh/build_error_CI_CD.md +1 -2
  709. package/frequent_questions/zh/bun_set_up.md +1 -2
  710. package/frequent_questions/zh/customized_locale_list.md +1 -2
  711. package/frequent_questions/zh/domain_routing.md +1 -2
  712. package/frequent_questions/zh/esbuild_error.md +1 -2
  713. package/frequent_questions/zh/get_locale_cookie.md +1 -2
  714. package/frequent_questions/zh/intlayer_command_undefined.md +1 -2
  715. package/frequent_questions/zh/locale_incorect_in_url.md +1 -2
  716. package/frequent_questions/zh/static_rendering.md +1 -3
  717. package/frequent_questions/zh/translated_path_url.md +1 -2
  718. package/frequent_questions/zh/unknown_command.md +1 -2
  719. package/legal/id/privacy_notice.md +83 -0
  720. package/legal/id/terms_of_service.md +55 -0
  721. package/legal/pl/privacy_notice.md +83 -0
  722. package/legal/pl/terms_of_service.md +55 -0
  723. package/legal/vi/privacy_notice.md +83 -0
  724. package/legal/vi/terms_of_service.md +55 -0
  725. package/package.json +19 -18
  726. package/src/generated/blog.entry.ts +38 -0
@@ -0,0 +1,1080 @@
1
+ ---
2
+ createdAt: 2025-11-01
3
+ updatedAt: 2025-11-01
4
+ title: Cách quốc tế hóa ứng dụng Next.js của bạn bằng next-i18next
5
+ description: Thiết lập i18n với next-i18next - các thực hành tốt nhất và mẹo SEO cho ứng dụng Next.js đa ngôn ngữ, bao gồm quốc tế hóa, tổ chức nội dung và thiết lập kỹ thuật.
6
+ slugs:
7
+ - blog
8
+ - nextjs-internationalization-using-next-i18next
9
+ applicationTemplate: https://github.com/aymericzip/next-i18next-template
10
+ history:
11
+ - version: 7.0.6
12
+ date: 2025-11-01
13
+ changes: Phiên bản đầu tiên
14
+ ---
15
+
16
+ # Cách quốc tế hóa ứng dụng Next.js của bạn bằng next-i18next trong năm 2025
17
+
18
+ ## Mục lục
19
+
20
+ <TOC/>
21
+
22
+ ## next-i18next là gì?
23
+
24
+ **next-i18next** là một giải pháp quốc tế hóa (i18n) phổ biến cho các ứng dụng Next.js. Trong khi gói `next-i18next` ban đầu được thiết kế cho Pages Router, hướng dẫn này sẽ chỉ cho bạn cách triển khai i18next với **App Router** hiện đại bằng cách sử dụng trực tiếp `i18next` và `react-i18next`.
25
+
26
+ Với cách tiếp cận này, bạn có thể:
27
+
28
+ - **Tổ chức các bản dịch** bằng cách sử dụng namespace (ví dụ: `common.json`, `about.json`) để quản lý nội dung tốt hơn.
29
+ - **Tải bản dịch hiệu quả** bằng cách chỉ tải các namespace cần thiết cho mỗi trang, giảm kích thước gói.
30
+ - **Hỗ trợ cả thành phần server và client** với xử lý SSR và hydration đúng cách.
31
+ - **Đảm bảo hỗ trợ TypeScript** với cấu hình locale và khóa dịch có kiểu an toàn.
32
+ - **Tối ưu hóa cho SEO** với metadata phù hợp, sitemap và quốc tế hóa robots.txt.
33
+
34
+ > Ngoài ra, bạn cũng có thể tham khảo [hướng dẫn next-intl](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/i18n_using_next-intl.md), hoặc sử dụng trực tiếp [Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_with_nextjs_16.md).
35
+
36
+ > Xem so sánh tại [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md).
37
+
38
+ ## Các thực hành bạn nên tuân theo
39
+
40
+ Trước khi đi vào triển khai, đây là một số thực hành bạn nên tuân theo:
41
+
42
+ - **Đặt thuộc tính `lang` và `dir` cho HTML**
43
+ Trong layout của bạn, tính toán `dir` bằng cách sử dụng `getLocaleDirection(locale)` và đặt `<html lang={locale} dir={dir}>` để đảm bảo khả năng truy cập và SEO đúng cách.
44
+ - **Phân tách thông điệp theo namespace**
45
+ Tổ chức các file JSON theo locale và namespace (ví dụ: `common.json`, `about.json`) để chỉ tải những gì bạn cần.
46
+ - **Giảm thiểu payload cho client**
47
+ Trên các trang, chỉ gửi các namespace cần thiết đến `NextIntlClientProvider` (ví dụ: `pick(messages, ['common', 'about'])`).
48
+ - **Ưu tiên các trang tĩnh**
49
+ Sử dụng trang tĩnh càng nhiều càng tốt để cải thiện hiệu suất và SEO.
50
+ - **I18n trong các component server**
51
+ Các component server, như các trang hoặc tất cả các component không được đánh dấu là `client` là tĩnh và có thể được pre-render tại thời điểm build. Vì vậy, chúng ta sẽ phải truyền các hàm dịch cho chúng dưới dạng props.
52
+ - **Thiết lập kiểu TypeScript**
53
+ Để đảm bảo an toàn kiểu cho các locales của bạn trong toàn bộ ứng dụng.
54
+ - **Proxy cho chuyển hướng**
55
+ Sử dụng proxy để xử lý việc phát hiện locale và định tuyến, đồng thời chuyển hướng người dùng đến URL có tiền tố locale phù hợp.
56
+ - **Quốc tế hóa metadata, sitemap, robots.txt của bạn**
57
+ Quốc tế hóa metadata, sitemap, robots.txt bằng cách sử dụng hàm `generateMetadata` do Next.js cung cấp để đảm bảo các công cụ tìm kiếm có thể khám phá tốt hơn ở tất cả các locales.
58
+ - **Địa phương hóa các liên kết**
59
+ Địa phương hóa các liên kết sử dụng component `Link` để chuyển hướng người dùng đến URL có tiền tố locale phù hợp. Điều này rất quan trọng để đảm bảo các trang của bạn được khám phá ở tất cả các locales.
60
+ - **Tự động hóa kiểm thử và dịch thuật**
61
+ Tự động hóa kiểm thử và dịch thuật giúp tiết kiệm thời gian duy trì ứng dụng đa ngôn ngữ của bạn.
62
+
63
+ > Xem tài liệu của chúng tôi liệt kê mọi thứ bạn cần biết về quốc tế hóa và SEO: [Quốc tế hóa (i18n) với next-intl](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/internationalization_and_SEO.md).
64
+
65
+ ---
66
+
67
+ ## Hướng Dẫn Từng Bước Để Thiết Lập i18next Trong Ứng Dụng Next.js
68
+
69
+ <iframe
70
+ src="https://stackblitz.com/github/aymericzip/next-i18next-template?embed=1&ctl=1&file=src/app/i18n.ts"
71
+ className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
72
+ title="Demo CodeSandbox - Cách Quốc tế hóa ứng dụng của bạn sử dụng Intlayer"
73
+ sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
74
+ loading="lazy"
75
+
76
+ > Xem [Mẫu Ứng Dụng](https://github.com/aymericzip/next-i18next-template) trên GitHub.
77
+
78
+ Cấu trúc dự án mà chúng ta sẽ tạo:
79
+
80
+ ```bash
81
+ .
82
+ ├── i18n.config.ts
83
+ └── src # Thư mục Src là tùy chọn
84
+ ├── locales
85
+ │ ├── en
86
+ │ │ ├── common.json
87
+ │ │ └── about.json
88
+ │ └── fr
89
+ │ ├── common.json
90
+ │ └── about.json
91
+ ├── types
92
+ │ └── i18next.d.ts
93
+ ├── app
94
+ │ ├── proxy.ts
95
+ │ ├── i18n
96
+ │ │ └── server.ts
97
+ │ └── [locale]
98
+ │ ├── layout.tsx
99
+ │ ├── (home) # / (Nhóm Route để không làm lộn xộn tất cả các trang với các thông điệp trang chủ)
100
+ │ │ ├── layout.tsx
101
+ │ │ └── page.tsx
102
+ │ └── about # /about
103
+ │ ├── layout.tsx
104
+ │ └── page.tsx
105
+ └── components
106
+ ├── I18nProvider.tsx
107
+ ├── ClientComponent.tsx
108
+ └── ServerComponent.tsx
109
+ ```
110
+
111
+ ### Bước 1: Cài Đặt Các Phụ Thuộc
112
+
113
+ Cài đặt các gói cần thiết bằng npm:
114
+
115
+ ```bash packageManager="npm"
116
+ npm install i18next react-i18next i18next-resources-to-backend
117
+ ```
118
+
119
+ ```bash packageManager="pnpm"
120
+ pnpm add i18next react-i18next i18next-resources-to-backend
121
+ ```
122
+
123
+ ```bash packageManager="yarn"
124
+ yarn add i18next react-i18next i18next-resources-to-backend
125
+ ```
126
+
127
+ - **i18next**: Framework quốc tế hóa cốt lõi xử lý việc tải và quản lý bản dịch.
128
+ - **react-i18next**: Liên kết React cho i18next cung cấp các hook như `useTranslation` cho các component phía client.
129
+ - **i18next-resources-to-backend**: Plugin cho phép tải động các file bản dịch, giúp bạn chỉ tải những namespace cần thiết.
130
+
131
+ ### Bước 2: Cấu Hình Dự Án Của Bạn
132
+
133
+ Tạo một file cấu hình để định nghĩa các locale được hỗ trợ, locale mặc định, và các hàm trợ giúp cho việc địa phương hóa URL. File này đóng vai trò là nguồn dữ liệu duy nhất cho thiết lập i18n của bạn và đảm bảo an toàn kiểu trong toàn bộ ứng dụng.
134
+
135
+ Việc tập trung cấu hình locale giúp tránh sự không nhất quán và dễ dàng thêm hoặc loại bỏ các locale trong tương lai. Các hàm trợ giúp đảm bảo việc tạo URL nhất quán cho SEO và định tuyến.
136
+
137
+ ```ts fileName="i18n.config.ts"
138
+ // Định nghĩa các locale được hỗ trợ dưới dạng mảng const để đảm bảo an toàn kiểu
139
+ // Câu lệnh 'as const' giúp TypeScript suy luận các kiểu literal thay vì string[]
140
+ export const locales = ["en", "fr"] as const;
141
+
142
+ // Trích xuất kiểu Locale từ mảng locales
143
+ // Điều này tạo ra kiểu hợp nhất: "en" | "fr"
144
+ export type Locale = (typeof locales)[number];
145
+
146
+ // Đặt locale mặc định được sử dụng khi không có locale nào được chỉ định
147
+ export const defaultLocale: Locale = "en";
148
+
149
+ // Các ngôn ngữ viết từ phải sang trái cần xử lý hướng văn bản đặc biệt
150
+ export const rtlLocales = ["ar", "he", "fa", "ur"] as const;
151
+
152
+ // Kiểm tra xem một locale có yêu cầu hướng văn bản RTL (từ phải sang trái) hay không
153
+ // Dùng cho các ngôn ngữ như Ả Rập, Do Thái, Ba Tư và Urdu
154
+ export const isRtl = (locale: string) =>
155
+ (rtlLocales as readonly string[]).includes(locale);
156
+
157
+ // Tạo đường dẫn đã được địa phương hóa cho một locale và đường dẫn nhất định
158
+ // Đường dẫn của locale mặc định không có tiền tố (ví dụ: "/about" thay vì "/en/about")
159
+ // Các locale khác có tiền tố (ví dụ: "/fr/about")
160
+ export function localizedPath(locale: string, path: string) {
161
+ return locale === defaultLocale ? path : `/${locale}${path}`;
162
+ }
163
+
164
+ // URL cơ sở cho các URL tuyệt đối (dùng trong sitemap, metadata, v.v.)
165
+ const ORIGIN = "https://example.com";
166
+
167
+ // Tạo URL tuyệt đối với tiền tố locale
168
+ // Dùng cho metadata SEO, sitemap và URL chuẩn
169
+ export function absoluteUrl(locale: string, path: string) {
170
+ return `${ORIGIN}${localizedPath(locale, path)}`;
171
+ }
172
+
173
+ // Dùng để thiết lập cookie locale trong trình duyệt
174
+ export function getCookie(locale: Locale) {
175
+ return [
176
+ `NEXT_LOCALE=${locale}`,
177
+ "Path=/",
178
+ `Max-Age=${60 * 60 * 24 * 365}`, // 1 năm
179
+ "SameSite=Lax",
180
+ ].join("; ");
181
+ }
182
+ ```
183
+
184
+ ### Bước 3: Tập trung các namespace dịch thuật
185
+
186
+ Tạo một nguồn dữ liệu duy nhất cho mọi namespace mà ứng dụng của bạn cung cấp. Tái sử dụng danh sách này giúp đồng bộ mã phía server, client và công cụ, đồng thời mở khóa kiểu dữ liệu mạnh cho các hàm hỗ trợ dịch thuật.
187
+
188
+ ```ts fileName="src/i18n.namespaces.ts"
189
+ export const namespaces = ["common", "about"] as const;
190
+
191
+ export type Namespace = (typeof namespaces)[number];
192
+ ```
193
+
194
+ ### Bước 4: Định kiểu mạnh cho các khóa dịch với TypeScript
195
+
196
+ Mở rộng `i18next` để trỏ tới các file ngôn ngữ chuẩn của bạn (thường là tiếng Anh). TypeScript sẽ suy luận các khóa hợp lệ theo từng namespace, do đó các lời gọi tới `t()` được kiểm tra toàn diện.
197
+
198
+ ```ts fileName="src/types/i18next.d.ts"
199
+ import "i18next";
200
+
201
+ declare module "i18next" {
202
+ interface CustomTypeOptions {
203
+ defaultNS: "common";
204
+ resources: {
205
+ common: typeof import("@/locales/en/common.json");
206
+ about: typeof import("@/locales/en/about.json");
207
+ };
208
+ }
209
+ }
210
+ ```
211
+
212
+ > Mẹo: Lưu khai báo này trong thư mục `src/types` (tạo thư mục nếu chưa có). Next.js đã bao gồm `src` trong `tsconfig.json`, vì vậy phần mở rộng này sẽ được tự động nhận diện. Nếu không, hãy thêm đoạn sau vào file `tsconfig.json` của bạn:
213
+
214
+ ```json5 fileName="tsconfig.json"
215
+ {
216
+ "include": ["src/types/**/*.ts"],
217
+ }
218
+ ```
219
+
220
+ Với thiết lập này, bạn có thể dựa vào tính năng tự động hoàn thành và kiểm tra lỗi khi biên dịch:
221
+
222
+ ```tsx
223
+ import { useTranslation, type TFunction } from "react-i18next";
224
+
225
+ const { t } = useTranslation("about");
226
+
227
+ // Đúng, đã định kiểu: t("counter.increment")
228
+ // Lỗi, lỗi biên dịch: t("doesNotExist")
229
+ export type AboutTranslator = TFunction<"about">;
230
+ ```
231
+
232
+ ### Bước 5: Thiết lập khởi tạo i18n phía server
233
+
234
+ Tạo một hàm khởi tạo phía máy chủ để tải các bản dịch cho các thành phần server. Hàm này tạo một instance i18next riêng biệt cho việc render phía server, đảm bảo rằng các bản dịch được tải trước khi render.
235
+
236
+ Các thành phần server cần có instance i18next riêng vì chúng chạy trong ngữ cảnh khác với các thành phần client. Việc tải trước các bản dịch trên server ngăn chặn hiện tượng nhấp nháy nội dung chưa được dịch và cải thiện SEO bằng cách đảm bảo các công cụ tìm kiếm nhìn thấy nội dung đã được dịch.
237
+
238
+ ```ts fileName="src/app/i18n/server.ts"
239
+ import { createInstance } from "i18next";
240
+ import { initReactI18next } from "react-i18next/initReactI18next";
241
+ import resourcesToBackend from "i18next-resources-to-backend";
242
+ import { defaultLocale } from "@/i18n.config";
243
+ import { namespaces, type Namespace } from "@/i18n.namespaces";
244
+
245
+ // Cấu hình tải tài nguyên động cho i18next
246
+ // Hàm này nhập động các file JSON bản dịch dựa trên locale và namespace
247
+ // Ví dụ: locale="fr", namespace="about" -> nhập "@/locales/fr/about.json"
248
+ const backend = resourcesToBackend(
249
+ (locale: string, namespace: string) =>
250
+ import(`@/locales/${locale}/${namespace}.json`)
251
+ );
252
+
253
+ const DEFAULT_NAMESPACES = [
254
+ namespaces[0],
255
+ ] as const satisfies readonly Namespace[];
256
+
257
+ /**
258
+ * Khởi tạo instance i18next cho việc render phía server
259
+ *
260
+ * @returns Instance i18next đã được khởi tạo sẵn sàng sử dụng phía server
261
+ */
262
+ export async function initI18next(
263
+ locale: string,
264
+ ns: readonly Namespace[] = DEFAULT_NAMESPACES
265
+ ) {
266
+ // Tạo một instance i18next mới (tách biệt với instance phía client)
267
+ const i18n = createInstance();
268
+
269
+ // Khởi tạo với tích hợp React và bộ tải backend
270
+ await i18n
271
+ .use(initReactI18next) // Kích hoạt hỗ trợ React hooks
272
+ .use(backend) // Kích hoạt tải tài nguyên động
273
+ .init({
274
+ lng: locale,
275
+ fallbackLng: defaultLocale,
276
+ ns, // Chỉ tải các namespace được chỉ định để tăng hiệu suất
277
+ defaultNS: "common", // Namespace mặc định khi không có namespace nào được chỉ định
278
+ interpolation: { escapeValue: false }, // Không escape HTML (React xử lý bảo vệ XSS)
279
+ react: { useSuspense: false }, // Tắt Suspense để tương thích SSR
280
+ returnNull: false, // Trả về chuỗi rỗng thay vì null cho các key bị thiếu
281
+ initImmediate: false, // Hoãn khởi tạo cho đến khi tài nguyên được tải xong (tăng tốc SSR)
282
+ });
283
+ return i18n;
284
+ }
285
+ ```
286
+
287
+ ### Bước 6: Tạo Provider i18n phía Client
288
+
289
+ Tạo một component provider phía client bao bọc ứng dụng của bạn với context i18next. Provider này nhận các bản dịch đã được tải sẵn từ server để ngăn chặn hiện tượng flash nội dung chưa dịch (FOUC) và tránh việc tải lặp lại.
290
+
291
+ Các component phía client cần một instance i18next riêng chạy trong trình duyệt. Bằng cách nhận tài nguyên đã tải sẵn từ server, chúng ta đảm bảo quá trình hydration mượt mà và ngăn chặn hiện tượng nhấp nháy nội dung. Provider cũng quản lý việc thay đổi locale và tải namespace một cách động.
292
+
293
+ ```tsx fileName="src/components/I18nProvider.tsx"
294
+ "use client";
295
+
296
+ import { useEffect, useState } from "react";
297
+ import { I18nextProvider } from "react-i18next";
298
+ import { createInstance, type ResourceLanguage } from "i18next";
299
+ import { initReactI18next } from "react-i18next/initReactI18next";
300
+ import resourcesToBackend from "i18next-resources-to-backend";
301
+ import { defaultLocale } from "@/i18n.config";
302
+ import { namespaces as allNamespaces, type Namespace } from "@/i18n.namespaces";
303
+
304
+ // Cấu hình tải tài nguyên động cho phía client
305
+ // Cùng mẫu với phía server, nhưng instance này chạy trong trình duyệt
306
+ const backend = resourcesToBackend(
307
+ (locale: string, namespace: string) =>
308
+ import(`@/locales/${locale}/${namespace}.json`)
309
+ );
310
+
311
+ type Props = {
312
+ locale: string;
313
+ namespaces?: readonly Namespace[];
314
+ // Tài nguyên đã được tải sẵn từ server (ngăn chặn FOUC - Flash of Untranslated Content)
315
+ // Định dạng: { namespace: translationBundle }
316
+ resources?: Record<Namespace, ResourceLanguage>;
317
+ children: React.ReactNode;
318
+ };
319
+
320
+ /**
321
+ * Provider i18n phía client bao bọc ứng dụng với context i18next
322
+ * Nhận tài nguyên đã tải sẵn từ server để tránh tải lại bản dịch
323
+ */
324
+ export default function I18nProvider({
325
+ locale,
326
+ namespaces = [allNamespaces[0]] as const,
327
+ resources,
328
+ children,
329
+ }: Props) {
330
+ // Tạo instance i18n một lần sử dụng useState với lazy initializer
331
+ // Điều này đảm bảo instance chỉ được tạo một lần, không phải mỗi lần render
332
+ const [i18n] = useState(() => {
333
+ const i18nInstance = createInstance();
334
+
335
+ i18nInstance
336
+ .use(initReactI18next)
337
+ .use(backend)
338
+ .init({
339
+ lng: locale,
340
+ fallbackLng: defaultLocale,
341
+ ns: namespaces,
342
+ // Nếu có tài nguyên được cung cấp (từ server), sử dụng chúng để tránh tải lại bản dịch phía client
343
+ // Điều này ngăn chặn FOUC và cải thiện hiệu suất tải ban đầu
344
+ resources: resources ? { [locale]: resources } : undefined,
345
+ defaultNS: "common",
346
+ interpolation: { escapeValue: false },
347
+ react: { useSuspense: false },
348
+ returnNull: false, // Ngăn không trả về giá trị undefined
349
+ });
350
+
351
+ return i18nInstance;
352
+ });
353
+
354
+ // Cập nhật ngôn ngữ khi prop locale thay đổi
355
+ useEffect(() => {
356
+ i18n.changeLanguage(locale);
357
+ }, [locale, i18n]);
358
+
359
+ // Đảm bảo tất cả namespace cần thiết được tải phía client
360
+ // Sử dụng join("|") làm dependency để so sánh mảng chính xác
361
+ useEffect(() => {
362
+ i18n.loadNamespaces(namespaces);
363
+ }, [namespaces.join("|"), i18n]);
364
+
365
+ // Cung cấp instance i18n cho tất cả các component con thông qua React context
366
+ return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
367
+ }
368
+ ```
369
+
370
+ ### Bước 7: Định nghĩa các tuyến đường động theo locale
371
+
372
+ Thiết lập routing động cho các locale bằng cách tạo thư mục `[locale]` trong thư mục app của bạn. Điều này cho phép Next.js xử lý routing dựa trên locale, trong đó mỗi locale trở thành một phân đoạn URL (ví dụ: `/en/about`, `/fr/about`).
373
+
374
+ Việc sử dụng các tuyến đường động cho phép Next.js tạo các trang tĩnh cho tất cả các locale trong quá trình build, cải thiện hiệu suất và SEO. Component layout sẽ thiết lập các thuộc tính HTML `lang` và `dir` dựa trên locale, điều này rất quan trọng cho khả năng truy cập và hiểu biết của công cụ tìm kiếm.
375
+
376
+ ```tsx fileName="src/app/[locale]/layout.tsx"
377
+ import type { ReactNode } from "react";
378
+ import { locales, defaultLocale, isRtl, type Locale } from "@/i18n.config";
379
+
380
+ // Vô hiệu hóa dynamic params - tất cả các locale phải được biết tại thời điểm build
381
+ // Điều này đảm bảo việc tạo trang tĩnh cho tất cả các tuyến đường theo locale
382
+ export const dynamicParams = false;
383
+
384
+ /**
385
+ * Tạo các tham số tĩnh cho tất cả các locale tại thời điểm build
386
+ * Next.js sẽ tiền kết xuất các trang cho mỗi locale được trả về ở đây
387
+ * Ví dụ: [{ locale: "en" }, { locale: "fr" }]
388
+ */
389
+ export function generateStaticParams() {
390
+ return locales.map((locale) => ({ locale }));
391
+ }
392
+
393
+ /**
394
+ * Component layout gốc xử lý các thuộc tính HTML theo locale
395
+ * Thiết lập thuộc tính lang và hướng văn bản (ltr/rtl) dựa trên locale
396
+ */
397
+ export default function LocaleLayout({
398
+ children,
399
+ params,
400
+ }: {
401
+ children: ReactNode;
402
+ params: { locale: string };
403
+ }) {
404
+ // Xác thực locale từ tham số URL
405
+ // Nếu locale không hợp lệ được cung cấp, sử dụng locale mặc định
406
+ const locale: Locale = (locales as readonly string[]).includes(params.locale)
407
+ ? (params.locale as any)
408
+ : defaultLocale;
409
+
410
+ // Xác định hướng văn bản dựa trên locale
411
+ // Các ngôn ngữ RTL như tiếng Ả Rập cần dir="rtl" để hiển thị văn bản đúng
412
+ const dir = isRtl(locale) ? "rtl" : "ltr";
413
+
414
+ return (
415
+ <html lang={locale} dir={dir}>
416
+ <body>{children}</body>
417
+ </html>
418
+ );
419
+ }
420
+ ```
421
+
422
+ ### Bước 8: Tạo các tệp dịch của bạn
423
+
424
+ Tạo các tệp JSON cho mỗi locale và namespace. Cấu trúc này cho phép bạn tổ chức các bản dịch một cách hợp lý và chỉ tải những gì bạn cần cho mỗi trang.
425
+
426
+ Tổ chức các bản dịch theo namespace (ví dụ: `common.json`, `about.json`) cho phép tách mã và giảm kích thước gói. Bạn chỉ tải các bản dịch cần thiết cho mỗi trang, cải thiện hiệu suất.
427
+
428
+ ```json fileName="src/locales/en/common.json"
429
+ {
430
+ "appTitle": "Next.js i18n App",
431
+ "appDescription": "Example Next.js application with internationalization using i18next"
432
+ }
433
+ ```
434
+
435
+ ```json fileName="src/locales/fr/common.json"
436
+ {
437
+ "appTitle": "Application Next.js i18n",
438
+ "appDescription": "Exemple d'application Next.js avec internationalisation utilisant i18next"
439
+ }
440
+ ```
441
+
442
+ ```json fileName="src/locales/en/home.json"
443
+ {
444
+ "title": "Home",
445
+ "description": "Home page description",
446
+ "welcome": "Welcome",
447
+ "greeting": "Hello, world!",
448
+ "aboutPage": "About Page",
449
+ "documentation": "Documentation"
450
+ }
451
+ ```
452
+
453
+ ```json fileName="src/locales/vi/home.json"
454
+ {
455
+ "title": "Trang chủ",
456
+ "description": "Mô tả trang chủ",
457
+ "welcome": "Chào mừng",
458
+ "greeting": "Xin chào thế giới!",
459
+ "aboutPage": "Trang Giới thiệu",
460
+ "documentation": "Tài liệu"
461
+ }
462
+ ```
463
+
464
+ ```json fileName="src/locales/en/about.json"
465
+ {
466
+ "title": "About",
467
+ "description": "About page description",
468
+ "counter": {
469
+ "label": "Counter",
470
+ "increment": "Increment",
471
+ "description": "Click the button to increase the counter"
472
+ }
473
+ }
474
+ ```
475
+
476
+ ```json fileName="src/locales/vi/about.json"
477
+ {
478
+ "title": "Giới thiệu",
479
+ "description": "Mô tả trang Giới thiệu",
480
+ "counter": {
481
+ "label": "Bộ đếm",
482
+ "increment": "Tăng",
483
+ "description": "Nhấn nút để tăng bộ đếm"
484
+ }
485
+ }
486
+ ```
487
+
488
+ ### Bước 9: Sử dụng Bản dịch trong Trang của Bạn
489
+
490
+ Tạo một component trang khởi tạo i18next trên server và truyền các bản dịch cho cả component server và client. Điều này đảm bảo các bản dịch được tải trước khi render và ngăn chặn hiện tượng nhấp nháy nội dung.
491
+
492
+ Việc khởi tạo phía server tải các bản dịch trước khi trang được render, cải thiện SEO và ngăn chặn FOUC (Flash of Unstyled Content). Bằng cách truyền tài nguyên đã tải sẵn cho provider phía client, chúng ta tránh việc tải trùng lặp và đảm bảo quá trình hydration mượt mà.
493
+
494
+ ```tsx fileName="src/app/[locale]/about/index.tsx"
495
+ import I18nProvider from "@/components/I18nProvider";
496
+ import { initI18next } from "@/app/i18n/server";
497
+ import type { Locale } from "@/i18n.config";
498
+ import { namespaces as allNamespaces, type Namespace } from "@/i18n.namespaces";
499
+ import type { ResourceLanguage } from "i18next";
500
+ import ClientComponent from "@/components/ClientComponent";
501
+ import ServerComponent from "@/components/ServerComponent";
502
+
503
+ /**
504
+ * Component trang phía server xử lý khởi tạo i18n
505
+ * Tải trước các bản dịch trên server và truyền chúng cho các component phía client
506
+ */
507
+ export default async function AboutPage({
508
+ params: { locale },
509
+ }: {
510
+ params: { locale: Locale };
511
+ }) {
512
+ // Định nghĩa các namespace bản dịch mà trang này cần
513
+ // Tái sử dụng danh sách tập trung để đảm bảo an toàn kiểu và tự động hoàn thành
514
+ const pageNamespaces = allNamespaces;
515
+
516
+ // Khởi tạo i18next trên server với các namespace cần thiết
517
+ // Việc này tải các file JSON bản dịch phía server
518
+ const i18n = await initI18next(locale, pageNamespaces);
519
+
520
+ // Lấy hàm dịch cố định cho namespace "about"
521
+ // getFixedT khóa namespace, nên dùng t("title") thay vì t("about:title")
522
+ const tAbout = i18n.getFixedT(locale, "about");
523
+
524
+ // Trích xuất các gói dịch từ instance i18n
525
+ // Dữ liệu này được truyền cho I18nProvider để hydrate i18n phía client
526
+ // Ngăn ngừa FOUC (Flash of Untranslated Content) và tránh tải lặp lại
527
+ const resources = Object.fromEntries(
528
+ pageNamespaces.map((ns) => [ns, i18n.getResourceBundle(locale, ns)])
529
+ ) satisfies Record<Namespace, ResourceLanguage>;
530
+
531
+ return (
532
+ <I18nProvider
533
+ locale={locale}
534
+ namespaces={pageNamespaces}
535
+ resources={resources}
536
+ >
537
+ <main>
538
+ <h1>{tAbout("title")}</h1>
539
+
540
+ <ClientComponent />
541
+ <ServerComponent t={tAbout} locale={locale} count={0} />
542
+ </main>
543
+ </I18nProvider>
544
+ );
545
+ }
546
+ ```
547
+
548
+ ### Bước 10: Sử dụng Dịch trong Các Component Client
549
+
550
+ Các component client có thể sử dụng hook `useTranslation` để truy cập bản dịch. Hook này cung cấp hàm dịch và instance i18n, cho phép bạn dịch nội dung và truy cập thông tin locale.
551
+
552
+ Các component client cần React hooks để truy cập bản dịch. Hook `useTranslation` tích hợp mượt mà với i18next và cung cấp cập nhật phản ứng khi locale thay đổi.
553
+
554
+ > Đảm bảo trang/provider chỉ bao gồm các namespace bạn cần (ví dụ: `about`).
555
+ > Nếu bạn dùng React < 19, hãy memo hóa các bộ định dạng nặng như `Intl.NumberFormat`.
556
+
557
+ ```tsx fileName="src/components/ClientComponent.tsx"
558
+ "use client";
559
+
560
+ import { useState } from "react";
561
+ import { useTranslation } from "react-i18next";
562
+
563
+ /**
564
+ * Ví dụ component client sử dụng React hooks cho việc dịch
565
+ * Có thể sử dụng các hook như useState, useEffect, và useTranslation
566
+ */
567
+ const ClientComponent = () => {
568
+ // Hook useTranslation cung cấp hàm dịch và instance i18n
569
+ // Chỉ định namespace để chỉ tải bản dịch cho namespace "about"
570
+ const { t, i18n } = useTranslation("about");
571
+ const [count, setCount] = useState(0);
572
+
573
+ // Tạo bộ định dạng số theo locale
574
+ // i18n.language cung cấp locale hiện tại (ví dụ: "en", "fr")
575
+ // Intl.NumberFormat định dạng số theo quy ước locale
576
+ const numberFormat = new Intl.NumberFormat(i18n.language);
577
+
578
+ return (
579
+ <div className="flex flex-col items-center gap-4">
580
+ {/* Định dạng số sử dụng định dạng theo locale cụ thể */}
581
+ <p className="text-5xl font-bold text-white m-0">
582
+ {numberFormat.format(count)}
583
+ </p>
584
+ <button
585
+ type="button"
586
+ className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
587
+ aria-label={t("counter.label")}
588
+ onClick={() => setCount((c) => c + 1)}
589
+ >
590
+ {t("counter.increment")}
591
+ </button>
592
+ </div>
593
+ );
594
+ };
595
+
596
+ export default ClientComponent;
597
+ ```
598
+
599
+ ### Bước 11: Sử dụng bản dịch trong các Server Components
600
+
601
+ Các server component không thể sử dụng React hooks, vì vậy chúng nhận các bản dịch thông qua props từ các component cha của chúng. Cách tiếp cận này giữ cho server component đồng bộ và cho phép chúng được lồng bên trong các client component.
602
+
603
+ Các server component có thể được lồng dưới các ranh giới client cần phải đồng bộ. Bằng cách truyền các chuỗi đã dịch và thông tin locale dưới dạng props, chúng ta tránh các thao tác bất đồng bộ và đảm bảo việc render chính xác.
604
+
605
+ ```tsx fileName="src/components/ServerComponent.tsx"
606
+ import type { TFunction } from "i18next";
607
+
608
+ type ServerComponentProps = {
609
+ // Hàm dịch được truyền từ server component cha
610
+ // Server component không thể sử dụng hooks, nên bản dịch được truyền qua props
611
+ t: TFunction<"about">;
612
+ locale: string;
613
+ count: number;
614
+ };
615
+
616
+ /**
617
+ * Ví dụ server component - nhận bản dịch qua props
618
+ * Có thể được lồng bên trong các client component (server component bất đồng bộ)
619
+ * Không thể sử dụng React hooks, vì vậy tất cả dữ liệu phải đến từ props hoặc các thao tác bất đồng bộ
620
+ */
621
+ const ServerComponent = ({ t, locale, count }: ServerComponentProps) => {
622
+ // Định dạng số phía server sử dụng locale
623
+ // Điều này chạy trên server trong SSR, cải thiện thời gian tải trang ban đầu
624
+ const formatted = new Intl.NumberFormat(locale).format(count);
625
+
626
+ return (
627
+ <div className="flex flex-col items-center gap-4">
628
+ <p className="text-5xl font-bold text-white m-0">{formatted}</p>
629
+ {/* Sử dụng hàm dịch được truyền qua prop */}
630
+ <div className="flex flex-col items-center gap-2">
631
+ <span className="text-xl font-semibold text-white">
632
+ {t("counter.label")}
633
+ </span>
634
+ <span className="text-sm opacity-80 italic">
635
+ {t("counter.description")}
636
+ </span>
637
+ </div>
638
+ </div>
639
+ );
640
+ };
641
+
642
+ export default ServerComponent;
643
+ ```
644
+
645
+ ---
646
+
647
+ ### (Tùy chọn) Bước 12: Thay đổi ngôn ngữ nội dung của bạn
648
+
649
+ Để thay đổi ngôn ngữ nội dung trong Next.js, cách được khuyến nghị là sử dụng URL có tiền tố locale và các liên kết Next.js. Ví dụ dưới đây đọc locale hiện tại từ route, loại bỏ nó khỏi pathname, và hiển thị một liên kết cho mỗi locale có sẵn.
650
+
651
+ ```tsx fileName="src/components/LocaleSwitcher.tsx"
652
+ "use client";
653
+
654
+ import Link from "next/link";
655
+ import { useParams, usePathname } from "next/navigation";
656
+ import { useMemo } from "react";
657
+ import { defaultLocale, getCookie, type Locale, locales } from "@/i18n.config";
658
+
659
+ export default function LocaleSwitcher() {
660
+ const params = useParams();
661
+ const pathname = usePathname();
662
+
663
+ const activeLocale = (params?.locale as Locale | undefined) ?? defaultLocale;
664
+
665
+ const getLocaleLabel = (locale: Locale): string => {
666
+ try {
667
+ const displayNames = new Intl.DisplayNames([locale], {
668
+ type: "language",
669
+ });
670
+ return displayNames.of(locale) ?? locale.toUpperCase();
671
+ } catch {
672
+ return locale.toUpperCase();
673
+ }
674
+ };
675
+
676
+ const basePath = useMemo(() => {
677
+ if (!pathname) return "/";
678
+
679
+ const segments = pathname.split("/").filter(Boolean);
680
+
681
+ if (segments.length === 0) return "/";
682
+
683
+ const maybeLocale = segments[0] as Locale;
684
+
685
+ if ((locales as readonly string[]).includes(maybeLocale)) {
686
+ const rest = segments.slice(1).join("/");
687
+ return rest ? `/${rest}` : "/";
688
+ }
689
+
690
+ return pathname;
691
+ }, [pathname]);
692
+
693
+ return (
694
+ <nav aria-label="Bộ chọn ngôn ngữ">
695
+ {(locales as readonly Locale[]).map((locale) => {
696
+ const isActive = locale === activeLocale;
697
+
698
+ const href =
699
+ locale === defaultLocale ? basePath : `/${locale}${basePath}`;
700
+
701
+ return (
702
+ <Link
703
+ key={locale}
704
+ href={href}
705
+ aria-current={isActive ? "page" : undefined}
706
+ onClick={() => {
707
+ document.cookie = getCookie(locale);
708
+ }}
709
+ >
710
+ {getLocaleLabel(locale)}
711
+ </Link>
712
+ );
713
+ })}
714
+ </nav>
715
+ );
716
+ }
717
+ ```
718
+
719
+ ### (Tùy chọn) Bước 13: Xây dựng một component Link có hỗ trợ đa ngôn ngữ
720
+
721
+ Tái sử dụng các URL đã được địa phương hóa trong toàn bộ ứng dụng giúp điều hướng nhất quán và thân thiện với SEO. Bao bọc `next/link` trong một helper nhỏ để thêm tiền tố locale đang hoạt động vào các route nội bộ trong khi giữ nguyên các URL bên ngoài.
722
+
723
+ ```tsx fileName="src/components/LocalizedLink.tsx"
724
+ "use client";
725
+
726
+ import NextLink, { type LinkProps } from "next/link";
727
+ import { useParams } from "next/navigation";
728
+ import type { ComponentProps, PropsWithChildren } from "react";
729
+ import {
730
+ defaultLocale,
731
+ type Locale,
732
+ locales,
733
+ localizedPath,
734
+ } from "@/i18n.config";
735
+
736
+ const isExternal = (href: string) => /^https?:\/\//.test(href);
737
+
738
+ type LocalizedLinkProps = PropsWithChildren<
739
+ Omit<LinkProps, "href"> &
740
+ Omit<ComponentProps<"a">, "href"> & { href: string; locale?: Locale }
741
+ >;
742
+
743
+ export default function LocalizedLink({
744
+ href,
745
+ locale,
746
+ children,
747
+ ...props
748
+ }: LocalizedLinkProps) {
749
+ const params = useParams();
750
+ const fallback = (params?.locale as Locale | undefined) ?? defaultLocale;
751
+ const normalizedLocale = (locales as readonly string[]).includes(fallback)
752
+ ? ((locale ?? fallback) as Locale)
753
+ : defaultLocale;
754
+
755
+ const normalizedPath = href.startsWith("/") ? href : `/${href}`;
756
+ const localizedHref = isExternal(href)
757
+ ? href
758
+ : localizedPath(normalizedLocale, normalizedPath);
759
+
760
+ return (
761
+ <NextLink href={localizedHref} {...props}>
762
+ {children}
763
+ </NextLink>
764
+ );
765
+ }
766
+ ```
767
+
768
+ > Mẹo: Vì `LocalizedLink` là một thành phần thay thế trực tiếp, hãy di chuyển dần dần bằng cách thay đổi các import và để thành phần xử lý các URL theo locale cụ thể.
769
+
770
+ ### (Tùy chọn) Bước 14: Truy cập locale đang hoạt động bên trong Server Actions
771
+
772
+ Server Actions thường cần locale hiện tại để gửi email, ghi log hoặc tích hợp với bên thứ ba. Kết hợp cookie locale được proxy của bạn thiết lập với header `Accept-Language` làm phương án dự phòng.
773
+
774
+ ```ts fileName="src/app/actions/get-current-locale.ts"
775
+ "use server";
776
+
777
+ import { cookies, headers } from "next/headers";
778
+ import { defaultLocale, locales, type Locale } from "@/i18n.config";
779
+
780
+ const KNOWN_LOCALES = new Set(locales as readonly string[]);
781
+
782
+ const normalize = (value: string | undefined): Locale | undefined => {
783
+ if (!value) return undefined;
784
+ const base = value.toLowerCase().split("-")[0];
785
+ return KNOWN_LOCALES.has(base) ? (base as Locale) : undefined;
786
+ };
787
+
788
+ export async function getCurrentLocale(): Promise<Locale> {
789
+ const cookieLocale = normalize(cookies().get("NEXT_LOCALE")?.value);
790
+
791
+ if (cookieLocale) return cookieLocale;
792
+
793
+ const headerLocale = normalize(headers().get("accept-language"));
794
+ return headerLocale ?? defaultLocale;
795
+ }
796
+
797
+ // Ví dụ về một server action sử dụng locale hiện tại
798
+ export async function stuffFromServer(formData: FormData) {
799
+ const locale = await getCurrentLocale();
800
+
801
+ // Sử dụng locale cho các tác động phụ theo ngôn ngữ (email, CRM, v.v.)
802
+ console.log(`Stuff from server with locale ${locale}`);
803
+ }
804
+ ```
805
+
806
+ > Vì helper dựa vào cookies và headers của Next.js, nó hoạt động trong Route Handlers, Server Actions và các ngữ cảnh chỉ dành cho server khác.
807
+
808
+ ### (Tùy chọn) Bước 15: Quốc tế hóa Metadata của bạn
809
+
810
+ Dịch nội dung là quan trọng, nhưng mục tiêu chính của quốc tế hóa là làm cho trang web của bạn trở nên dễ tiếp cận hơn với thế giới. I18n là một đòn bẩy tuyệt vời để cải thiện khả năng hiển thị trang web của bạn thông qua SEO đúng cách.
811
+
812
+ Metadata được quốc tế hóa đúng cách giúp các công cụ tìm kiếm hiểu được những ngôn ngữ nào có sẵn trên các trang của bạn. Điều này bao gồm việc thiết lập thẻ meta hreflang, dịch tiêu đề và mô tả, và đảm bảo các URL chuẩn (canonical) được thiết lập chính xác cho từng ngôn ngữ.
813
+
814
+ Dưới đây là danh sách các thực hành tốt liên quan đến SEO đa ngôn ngữ:
815
+
816
+ - Đặt thẻ meta hreflang trong thẻ `<head>` để giúp các công cụ tìm kiếm hiểu được những ngôn ngữ nào có trên trang
817
+ - Liệt kê tất cả các bản dịch trang trong sitemap.xml sử dụng schema XML `http://www.w3.org/1999/xhtml`
818
+ - Đừng quên loại trừ các trang có tiền tố khỏi robots.txt (ví dụ: `/dashboard`, `/fr/dashboard`, `/es/dashboard`)
819
+ - Sử dụng component Link tùy chỉnh để chuyển hướng đến trang được địa phương hóa nhất (ví dụ, bằng tiếng Pháp `<a href="/fr/about">À propos</a>`)
820
+
821
+ Các nhà phát triển thường quên tham chiếu đúng các trang của họ qua các locale. Hãy sửa điều đó:
822
+
823
+ ```tsx fileName="src/app/[locale]/about/layout.tsx"
824
+ import type { Metadata } from "next";
825
+ import {
826
+ locales,
827
+ defaultLocale,
828
+ localizedPath,
829
+ absoluteUrl,
830
+ } from "@/i18n.config";
831
+
832
+ /**
833
+ * Tạo metadata SEO cho mỗi phiên bản locale của trang
834
+ * Hàm này chạy cho mỗi locale tại thời điểm build
835
+ */
836
+ export async function generateMetadata({
837
+ params,
838
+ }: {
839
+ params: { locale: string };
840
+ }): Promise<Metadata> {
841
+ const { locale } = params;
842
+
843
+ // Nhập động file dịch cho locale này
844
+ // Dùng để lấy tiêu đề và mô tả đã dịch cho metadata
845
+ const messages = (await import(`@/locales/${locale}/about.json`)).default;
846
+
847
+ // Tạo bản đồ hreflang cho tất cả các locale
848
+ // Giúp các công cụ tìm kiếm hiểu các lựa chọn ngôn ngữ thay thế
849
+ // Định dạng: { "en": "/about", "fr": "/fr/about" }
850
+ const languages = Object.fromEntries(
851
+ locales.map((locale) => [locale, localizedPath(locale, "/about")])
852
+ );
853
+
854
+ return {
855
+ title: messages.title,
856
+ description: messages.description,
857
+ alternates: {
858
+ // URL chuẩn cho phiên bản locale này
859
+ canonical: absoluteUrl(locale, "/about"),
860
+ // Các lựa chọn ngôn ngữ thay thế cho SEO (thẻ hreflang)
861
+ // "x-default" chỉ định phiên bản locale mặc định
862
+ languages: {
863
+ ...languages,
864
+ "x-default": absoluteUrl(defaultLocale, "/about"),
865
+ },
866
+ },
867
+ };
868
+ }
869
+
870
+ export default async function AboutPage() {
871
+ return <h1>Giới thiệu</h1>;
872
+ }
873
+ ```
874
+
875
+ ### (Tùy chọn) Bước 16: Quốc tế hóa Sitemap của bạn
876
+
877
+ Tạo một sitemap bao gồm tất cả các phiên bản locale của các trang của bạn. Điều này giúp các công cụ tìm kiếm khám phá và lập chỉ mục tất cả các phiên bản ngôn ngữ của nội dung của bạn.
878
+
879
+ Một sitemap được quốc tế hóa đúng cách đảm bảo các công cụ tìm kiếm có thể tìm thấy và lập chỉ mục tất cả các phiên bản ngôn ngữ của các trang của bạn. Điều này cải thiện khả năng hiển thị trong kết quả tìm kiếm quốc tế.
880
+
881
+ ```ts fileName="src/app/sitemap.ts"
882
+ import type { MetadataRoute } from "next";
883
+ import { defaultLocale, locales } from "@/i18n";
884
+
885
+ const origin = "https://example.com";
886
+
887
+ const formatterLocalizedPath = (locale: string, path: string) =>
888
+ // Định dạng đường dẫn có locale, nếu là locale mặc định thì không thêm locale vào URL
889
+ locale === defaultLocale ? `${origin}${path}` : `${origin}/${locale}${path}`;
890
+
891
+ /**
892
+ * Lấy bản đồ tất cả các locale và đường dẫn đã được địa phương hóa
893
+ *
894
+ * Ví dụ đầu ra:
895
+ * {
896
+ * "en": "https://example.com",
897
+ * "fr": "https://example.com/fr",
898
+ * "es": "https://example.com/es",
899
+ * "x-default": "https://example.com"
900
+ * }
901
+ */
902
+ const getLocalizedMap = (path: string) =>
903
+ Object.fromEntries([
904
+ // Tạo mảng các cặp [locale, đường dẫn đã định dạng]
905
+ ...locales.map((locale) => [locale, formatterLocalizedPath(locale, path)]),
906
+ ["x-default", formatterLocalizedPath(defaultLocale, path)],
907
+ ]);
908
+
909
+ // Tạo sitemap với tất cả các biến thể ngôn ngữ để cải thiện SEO
910
+ // Trường alternates thông báo cho các công cụ tìm kiếm về các phiên bản ngôn ngữ
911
+ export default function sitemap(): MetadataRoute.Sitemap {
912
+ return [
913
+ {
914
+ url: formatterLocalizedPath(defaultLocale, "/"),
915
+ lastModified: new Date(),
916
+ changeFrequency: "monthly",
917
+ priority: 1.0,
918
+ alternates: { languages: getLocalizedMap("/") },
919
+ },
920
+ {
921
+ url: formatterLocalizedPath(defaultLocale, "/about"),
922
+ lastModified: new Date(),
923
+ changeFrequency: "monthly",
924
+ priority: 0.7,
925
+ alternates: { languages: getLocalizedMap("/about") },
926
+ },
927
+ ];
928
+ }
929
+ ```
930
+
931
+ ### (Tùy chọn) Bước 17: Quốc tế hóa tệp robots.txt của bạn
932
+
933
+ Tạo một tệp robots.txt xử lý đúng tất cả các phiên bản ngôn ngữ của các tuyến đường được bảo vệ của bạn. Điều này đảm bảo rằng các công cụ tìm kiếm không lập chỉ mục các trang quản trị hoặc bảng điều khiển bằng bất kỳ ngôn ngữ nào.
934
+
935
+ Cấu hình đúng robots.txt cho tất cả các ngôn ngữ ngăn các công cụ tìm kiếm lập chỉ mục các trang nhạy cảm bằng bất kỳ ngôn ngữ nào. Điều này rất quan trọng cho bảo mật và quyền riêng tư.
936
+
937
+ ```ts fileName="src/app/robots.ts"
938
+ import type { MetadataRoute } from "next";
939
+ import { defaultLocale, locales } from "@/i18n";
940
+
941
+ const origin = "https://example.com";
942
+
943
+ // Tạo đường dẫn cho tất cả các ngôn ngữ (ví dụ: /admin, /fr/admin, /es/admin)
944
+ const withAllLocales = (path: string) => [
945
+ path,
946
+ ...locales
947
+ .filter((locale) => locale !== defaultLocale)
948
+ .map((locale) => `/${locale}${path}`),
949
+ ];
950
+
951
+ const disallow = [...withAllLocales("/dashboard"), ...withAllLocales("/admin")];
952
+
953
+ export default function robots(): MetadataRoute.Robots {
954
+ return {
955
+ rules: { userAgent: "*", allow: ["/"], disallow },
956
+ host: origin,
957
+ sitemap: `${origin}/sitemap.xml`,
958
+ };
959
+ }
960
+ ```
961
+
962
+ ### (Tùy chọn) Bước 18: Thiết lập Middleware cho Định tuyến Ngôn ngữ
963
+
964
+ Tạo một proxy để tự động phát hiện ngôn ngữ ưu tiên của người dùng và chuyển hướng họ đến URL có tiền tố ngôn ngữ phù hợp. Điều này cải thiện trải nghiệm người dùng bằng cách hiển thị nội dung theo ngôn ngữ họ ưu thích.
965
+
966
+ Middleware đảm bảo người dùng được tự động chuyển hướng đến ngôn ngữ ưu tiên khi họ truy cập trang web của bạn. Nó cũng lưu trữ lựa chọn ngôn ngữ của người dùng trong cookie cho các lần truy cập sau.
967
+
968
+ ```ts fileName="src/proxy.ts"
969
+ import { NextResponse, type NextRequest } from "next/server";
970
+ import { defaultLocale, locales } from "@/i18n.config";
971
+
972
+ // Biểu thức chính quy để khớp các tệp có phần mở rộng (ví dụ: .js, .css, .png)
973
+ // Dùng để loại trừ các tài sản tĩnh khỏi việc định tuyến theo locale
974
+ const PUBLIC_FILE = /\.[^/]+$/;
975
+
976
+ /**
977
+ * Trích xuất locale từ header Accept-Language
978
+ * Xử lý các định dạng như "fr-CA", "en-US", v.v.
979
+ * Sử dụng locale mặc định nếu ngôn ngữ trình duyệt không được hỗ trợ
980
+ */
981
+ const pickLocale = (accept: string | null) => {
982
+ // Lấy ưu tiên ngôn ngữ đầu tiên (ví dụ: "fr-CA" từ "fr-CA,en-US;q=0.9")
983
+ const raw = accept?.split(",")[0] ?? defaultLocale;
984
+ // Trích xuất mã ngôn ngữ cơ bản (ví dụ: "fr" từ "fr-CA")
985
+ const base = raw.toLowerCase().split("-")[0];
986
+ // Kiểm tra xem chúng ta có hỗ trợ locale này không, nếu không thì dùng mặc định
987
+ return (locales as readonly string[]).includes(base) ? base : defaultLocale;
988
+ };
989
+
990
+ /**
991
+ * Proxy Next.js để phát hiện và định tuyến locale
992
+ * Chạy trên mỗi yêu cầu trước khi trang được render
993
+ * Tự động chuyển hướng đến URL có tiền tố locale khi cần thiết
994
+ */
995
+ export function proxy(request: NextRequest) {
996
+ const { pathname } = request.nextUrl;
997
+
998
+ // Bỏ qua proxy cho các phần nội bộ Next.js, API routes và các file tĩnh
999
+ // Những phần này không nên có tiền tố locale
1000
+ if (
1001
+ pathname.startsWith("/_next") ||
1002
+ pathname.startsWith("/api") ||
1003
+ pathname.startsWith("/static") ||
1004
+ PUBLIC_FILE.test(pathname)
1005
+ ) {
1006
+ return;
1007
+ }
1008
+
1009
+ // Kiểm tra xem URL đã có tiền tố locale chưa
1010
+ // Ví dụ: "/fr/about" hoặc "/en" sẽ trả về true
1011
+ const hasLocale = (locales as readonly string[]).some(
1012
+ (locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)
1013
+ );
1014
+
1015
+ // Nếu không có tiền tố locale, phát hiện locale và chuyển hướng
1016
+ if (!hasLocale) {
1017
+ // Cố gắng lấy locale từ cookie trước (ưu tiên người dùng)
1018
+ const cookieLocale = request.cookies.get("NEXT_LOCALE")?.value;
1019
+
1020
+ // Sử dụng locale từ cookie nếu hợp lệ, nếu không thì phát hiện từ header trình duyệt
1021
+ const locale =
1022
+ cookieLocale && (locales as readonly string[]).includes(cookieLocale)
1023
+ ? cookieLocale
1024
+ : pickLocale(request.headers.get("accept-language"));
1025
+
1026
+ // Sao chép URL để sửa đổi pathname
1027
+ const url = request.nextUrl.clone();
1028
+ // Thêm tiền tố locale vào pathname
1029
+ // Xử lý đặc biệt đường dẫn gốc để tránh dấu gạch chéo kép
1030
+ url.pathname = `/${locale}${pathname === "/" ? "" : pathname}`;
1031
+
1032
+ // Tạo phản hồi chuyển hướng và đặt cookie ngôn ngữ
1033
+ const res = NextResponse.redirect(url);
1034
+ res.cookies.set("NEXT_LOCALE", locale, { path: "/" });
1035
+ return res;
1036
+ }
1037
+ }
1038
+
1039
+ export const config = {
1040
+ matcher: [
1041
+ // Khớp với tất cả các đường dẫn ngoại trừ:
1042
+ // - Các route API (/api/*)
1043
+ // - Các phần nội bộ của Next.js (/_next/*)
1044
+ // - Các file tĩnh (/static/*)
1045
+ // - Các file có phần mở rộng (.*\\..*)
1046
+ "/((?!api|_next|static|.*\\..*).*)",
1047
+ ],
1048
+ };
1049
+ ```
1050
+
1051
+ ### (Tùy chọn) Bước 19: Tự động hóa bản dịch của bạn bằng Intlayer
1052
+
1053
+ Intlayer là một thư viện **miễn phí** và **mã nguồn mở** được thiết kế để hỗ trợ quá trình bản địa hóa trong ứng dụng của bạn. Trong khi i18next xử lý việc tải và quản lý bản dịch, Intlayer giúp tự động hóa quy trình làm việc bản dịch.
1054
+
1055
+ Việc quản lý bản dịch thủ công có thể tốn nhiều thời gian và dễ xảy ra lỗi. Intlayer tự động hóa việc kiểm thử, tạo và quản lý bản dịch, giúp bạn tiết kiệm thời gian và đảm bảo tính nhất quán trên toàn bộ ứng dụng của bạn.
1056
+
1057
+ Intlayer sẽ cho phép bạn:
1058
+
1059
+ - **Khai báo nội dung của bạn ở bất cứ đâu bạn muốn trong codebase**
1060
+ Intlayer cho phép khai báo nội dung của bạn ở bất cứ đâu bạn muốn trong codebase bằng cách sử dụng các file `.content.{ts|js|json}`. Điều này sẽ giúp tổ chức nội dung tốt hơn, đảm bảo khả năng đọc và bảo trì codebase hiệu quả hơn.
1061
+
1062
+ - **Kiểm thử các bản dịch còn thiếu**
1063
+ Intlayer cung cấp các hàm kiểm thử có thể tích hợp vào pipeline CI/CD của bạn hoặc trong các unit test. Tìm hiểu thêm về [kiểm thử bản dịch của bạn](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/testing.md).
1064
+
1065
+ - **Tự động hóa việc dịch của bạn**,
1066
+ Intlayer cung cấp một CLI và một tiện ích mở rộng VSCode để tự động hóa việc dịch của bạn. Nó có thể được tích hợp vào pipeline CI/CD của bạn. Tìm hiểu thêm về [tự động hóa việc dịch của bạn](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_cli.md).
1067
+ Bạn có thể sử dụng **khóa API riêng của bạn và nhà cung cấp AI mà bạn chọn**. Nó cũng cung cấp các bản dịch nhận biết ngữ cảnh, xem thêm [tự động điền nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/autoFill.md).
1068
+
1069
+ - **Kết nối nội dung bên ngoài**
1070
+ - **Tự động hóa việc dịch của bạn**,
1071
+ Intlayer cung cấp một CLI và một tiện ích mở rộng VSCode để tự động hóa việc dịch của bạn. Nó có thể được tích hợp vào pipeline CI/CD của bạn. Tìm hiểu thêm về [tự động hóa việc dịch của bạn](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_cli.md).
1072
+ Bạn có thể sử dụng **khóa API riêng của bạn và nhà cung cấp AI bạn chọn**. Nó cũng cung cấp các bản dịch nhận biết ngữ cảnh, xem thêm [tự động điền nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/autoFill.md).
1073
+
1074
+ - **Kết nối nội dung bên ngoài**
1075
+ Intlayer cho phép bạn kết nối nội dung của mình với hệ thống quản lý nội dung bên ngoài (CMS). Để lấy nội dung một cách tối ưu và chèn vào tài nguyên JSON của bạn. Tìm hiểu thêm về [lấy nội dung bên ngoài](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/function_fetching.md).
1076
+
1077
+ - **Trình chỉnh sửa trực quan**
1078
+ Intlayer cung cấp một trình chỉnh sửa trực quan miễn phí để chỉnh sửa nội dung của bạn bằng trình chỉnh sửa trực quan. Tìm hiểu thêm về [chỉnh sửa trực quan bản dịch của bạn](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_visual_editor.md).
1079
+
1080
+ Và còn nhiều hơn nữa. Để khám phá tất cả các tính năng mà Intlayer cung cấp, vui lòng tham khảo [Lợi ích của tài liệu Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/interest_of_intlayer.md).