@intlayer/docs 7.5.10 → 7.5.12

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 (313) hide show
  1. package/blog/ar/intlayer_with_i18next.md +0 -2
  2. package/blog/ar/intlayer_with_next-i18next.md +0 -2
  3. package/blog/ar/intlayer_with_react-i18next.md +0 -2
  4. package/blog/de/intlayer_with_i18next.md +0 -45
  5. package/blog/de/intlayer_with_next-i18next.md +0 -46
  6. package/blog/de/intlayer_with_react-i18next.md +0 -2
  7. package/blog/en/intlayer_with_i18next.md +0 -46
  8. package/blog/en/intlayer_with_next-i18next.md +0 -48
  9. package/blog/en/intlayer_with_next-intl.md +0 -44
  10. package/blog/en/intlayer_with_react-i18next.md +0 -44
  11. package/blog/en/intlayer_with_react-intl.md +0 -42
  12. package/blog/en/intlayer_with_vue-i18n.md +0 -44
  13. package/blog/en-GB/intlayer_with_i18next.md +0 -45
  14. package/blog/en-GB/intlayer_with_next-i18next.md +0 -47
  15. package/blog/en-GB/intlayer_with_next-intl.md +0 -42
  16. package/blog/en-GB/intlayer_with_react-i18next.md +0 -43
  17. package/blog/en-GB/intlayer_with_react-intl.md +0 -42
  18. package/blog/en-GB/intlayer_with_vue-i18n.md +0 -46
  19. package/blog/es/intlayer_with_i18next.md +0 -45
  20. package/blog/es/intlayer_with_next-i18next.md +0 -47
  21. package/blog/es/intlayer_with_next-intl.md +0 -42
  22. package/blog/es/intlayer_with_react-i18next.md +0 -43
  23. package/blog/es/intlayer_with_react-intl.md +0 -42
  24. package/blog/es/intlayer_with_vue-i18n.md +0 -46
  25. package/blog/fr/intlayer_with_i18next.md +0 -45
  26. package/blog/fr/intlayer_with_next-i18next.md +0 -47
  27. package/blog/fr/intlayer_with_next-intl.md +0 -42
  28. package/blog/fr/intlayer_with_react-i18next.md +0 -43
  29. package/blog/fr/intlayer_with_react-intl.md +0 -42
  30. package/blog/fr/intlayer_with_vue-i18n.md +0 -46
  31. package/blog/hi/intlayer_with_i18next.md +0 -2
  32. package/blog/hi/intlayer_with_next-i18next.md +0 -2
  33. package/blog/hi/intlayer_with_react-i18next.md +0 -2
  34. package/blog/id/intlayer_with_i18next.md +0 -2
  35. package/blog/id/intlayer_with_next-i18next.md +0 -2
  36. package/blog/id/intlayer_with_react-i18next.md +0 -2
  37. package/blog/it/intlayer_with_i18next.md +0 -2
  38. package/blog/it/intlayer_with_next-i18next.md +0 -2
  39. package/blog/it/intlayer_with_react-i18next.md +0 -2
  40. package/blog/ja/intlayer_with_i18next.md +0 -45
  41. package/blog/ja/intlayer_with_next-i18next.md +0 -46
  42. package/blog/ja/intlayer_with_next-intl.md +0 -42
  43. package/blog/ja/intlayer_with_react-i18next.md +0 -42
  44. package/blog/ja/intlayer_with_react-intl.md +0 -42
  45. package/blog/ja/intlayer_with_vue-i18n.md +0 -46
  46. package/blog/ko/intlayer_with_i18next.md +0 -2
  47. package/blog/ko/intlayer_with_next-i18next.md +0 -2
  48. package/blog/ko/intlayer_with_react-i18next.md +0 -1
  49. package/blog/pl/intlayer_with_i18next.md +0 -45
  50. package/blog/pl/intlayer_with_next-i18next.md +0 -46
  51. package/blog/pl/intlayer_with_next-intl.md +0 -42
  52. package/blog/pl/intlayer_with_react-i18next.md +0 -43
  53. package/blog/pl/intlayer_with_react-intl.md +0 -42
  54. package/blog/pl/intlayer_with_vue-i18n.md +0 -46
  55. package/blog/pt/intlayer_with_i18next.md +0 -2
  56. package/blog/pt/intlayer_with_next-i18next.md +0 -2
  57. package/blog/pt/intlayer_with_react-i18next.md +0 -2
  58. package/blog/ru/intlayer_with_i18next.md +0 -45
  59. package/blog/ru/intlayer_with_next-i18next.md +0 -47
  60. package/blog/ru/intlayer_with_next-intl.md +0 -42
  61. package/blog/ru/intlayer_with_react-i18next.md +0 -43
  62. package/blog/ru/intlayer_with_react-intl.md +0 -42
  63. package/blog/ru/intlayer_with_vue-i18n.md +0 -46
  64. package/blog/tr/intlayer_with_i18next.md +0 -2
  65. package/blog/tr/intlayer_with_next-i18next.md +0 -1
  66. package/blog/tr/intlayer_with_react-i18next.md +0 -2
  67. package/blog/vi/intlayer_with_i18next.md +0 -2
  68. package/blog/vi/intlayer_with_next-i18next.md +0 -2
  69. package/blog/vi/intlayer_with_react-i18next.md +0 -2
  70. package/blog/zh/intlayer_with_i18next.md +0 -2
  71. package/blog/zh/intlayer_with_next-i18next.md +0 -2
  72. package/blog/zh/intlayer_with_react-i18next.md +0 -2
  73. package/blog/zh/intlayer_with_vue-i18n.md +0 -46
  74. package/dist/cjs/generated/blog.entry.cjs +58 -29
  75. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  76. package/dist/cjs/generated/docs.entry.cjs +254 -97
  77. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  78. package/dist/cjs/generated/frequentQuestions.entry.cjs +30 -15
  79. package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
  80. package/dist/cjs/generated/legal.entry.cjs +4 -2
  81. package/dist/cjs/generated/legal.entry.cjs.map +1 -1
  82. package/dist/esm/generated/blog.entry.mjs +58 -29
  83. package/dist/esm/generated/blog.entry.mjs.map +1 -1
  84. package/dist/esm/generated/docs.entry.mjs +254 -97
  85. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  86. package/dist/esm/generated/frequentQuestions.entry.mjs +30 -15
  87. package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
  88. package/dist/esm/generated/legal.entry.mjs +4 -2
  89. package/dist/esm/generated/legal.entry.mjs.map +1 -1
  90. package/dist/types/generated/blog.entry.d.ts.map +1 -1
  91. package/dist/types/generated/docs.entry.d.ts +3 -0
  92. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  93. package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -1
  94. package/dist/types/generated/legal.entry.d.ts.map +1 -1
  95. package/docs/ar/cli/ci.md +137 -0
  96. package/docs/ar/cli/index.md +7 -1
  97. package/docs/ar/cli/list.md +39 -2
  98. package/docs/ar/cli/list_projects.md +131 -0
  99. package/docs/ar/intlayer_CMS.md +20 -0
  100. package/docs/ar/intlayer_with_next-i18next.md +0 -1
  101. package/docs/ar/intlayer_with_nextjs_14.md +28 -0
  102. package/docs/ar/intlayer_with_nextjs_15.md +28 -0
  103. package/docs/ar/intlayer_with_nextjs_16.md +28 -0
  104. package/docs/ar/intlayer_with_nextjs_no_locale_path.md +1159 -0
  105. package/docs/ar/plugins/sync-json.md +6 -2
  106. package/docs/de/cli/ci.md +137 -0
  107. package/docs/de/cli/index.md +7 -1
  108. package/docs/de/cli/list.md +39 -2
  109. package/docs/de/cli/list_projects.md +130 -0
  110. package/docs/de/intlayer_CMS.md +20 -0
  111. package/docs/de/intlayer_with_next-i18next.md +0 -1
  112. package/docs/de/intlayer_with_nextjs_14.md +28 -0
  113. package/docs/de/intlayer_with_nextjs_15.md +28 -0
  114. package/docs/de/intlayer_with_nextjs_16.md +28 -0
  115. package/docs/de/intlayer_with_nextjs_no_locale_path.md +1152 -0
  116. package/docs/de/plugins/sync-json.md +6 -2
  117. package/docs/en/cli/ci.md +137 -0
  118. package/docs/en/cli/index.md +14 -1
  119. package/docs/en/cli/list.md +39 -2
  120. package/docs/en/cli/list_projects.md +128 -0
  121. package/docs/en/interest_of_intlayer.md +1 -1
  122. package/docs/en/intlayer_CMS.md +20 -0
  123. package/docs/en/intlayer_with_next-i18next.md +0 -1
  124. package/docs/en/intlayer_with_nextjs_14.md +28 -0
  125. package/docs/en/intlayer_with_nextjs_15.md +28 -0
  126. package/docs/en/intlayer_with_nextjs_16.md +31 -1
  127. package/docs/en/intlayer_with_nextjs_no_locale_path.md +1132 -0
  128. package/docs/en/plugins/sync-json.md +6 -2
  129. package/docs/en-GB/cli/ci.md +137 -0
  130. package/docs/en-GB/cli/index.md +7 -1
  131. package/docs/en-GB/cli/list.md +39 -2
  132. package/docs/en-GB/cli/list_projects.md +130 -0
  133. package/docs/en-GB/intlayer_CMS.md +20 -0
  134. package/docs/en-GB/intlayer_with_next-i18next.md +0 -1
  135. package/docs/en-GB/intlayer_with_nextjs_14.md +28 -0
  136. package/docs/en-GB/intlayer_with_nextjs_15.md +28 -0
  137. package/docs/en-GB/intlayer_with_nextjs_16.md +28 -0
  138. package/docs/en-GB/intlayer_with_nextjs_no_locale_path.md +1154 -0
  139. package/docs/en-GB/plugins/sync-json.md +6 -2
  140. package/docs/es/cli/ci.md +137 -0
  141. package/docs/es/cli/index.md +7 -1
  142. package/docs/es/cli/list.md +39 -2
  143. package/docs/es/cli/list_projects.md +130 -0
  144. package/docs/es/intlayer_CMS.md +20 -0
  145. package/docs/es/intlayer_with_next-i18next.md +0 -1
  146. package/docs/es/intlayer_with_nextjs_14.md +28 -0
  147. package/docs/es/intlayer_with_nextjs_15.md +28 -0
  148. package/docs/es/intlayer_with_nextjs_16.md +28 -0
  149. package/docs/es/intlayer_with_nextjs_no_locale_path.md +1143 -0
  150. package/docs/es/plugins/sync-json.md +6 -2
  151. package/docs/fr/cli/ci.md +137 -0
  152. package/docs/fr/cli/index.md +7 -1
  153. package/docs/fr/cli/list.md +39 -2
  154. package/docs/fr/cli/list_projects.md +131 -0
  155. package/docs/fr/intlayer_CMS.md +20 -0
  156. package/docs/fr/intlayer_with_next-i18next.md +0 -1
  157. package/docs/fr/intlayer_with_nextjs_14.md +28 -0
  158. package/docs/fr/intlayer_with_nextjs_15.md +28 -0
  159. package/docs/fr/intlayer_with_nextjs_16.md +28 -0
  160. package/docs/fr/intlayer_with_nextjs_no_locale_path.md +1174 -0
  161. package/docs/fr/plugins/sync-json.md +9 -5
  162. package/docs/hi/cli/ci.md +137 -0
  163. package/docs/hi/cli/index.md +7 -1
  164. package/docs/hi/cli/list.md +38 -1
  165. package/docs/hi/cli/list_projects.md +130 -0
  166. package/docs/hi/intlayer_CMS.md +20 -0
  167. package/docs/hi/intlayer_with_next-i18next.md +0 -1
  168. package/docs/hi/intlayer_with_nextjs_14.md +28 -0
  169. package/docs/hi/intlayer_with_nextjs_15.md +28 -0
  170. package/docs/hi/intlayer_with_nextjs_16.md +28 -0
  171. package/docs/hi/intlayer_with_nextjs_no_locale_path.md +1151 -0
  172. package/docs/hi/plugins/sync-json.md +6 -2
  173. package/docs/id/cli/ci.md +137 -0
  174. package/docs/id/cli/index.md +7 -1
  175. package/docs/id/cli/list.md +38 -1
  176. package/docs/id/cli/list_projects.md +128 -0
  177. package/docs/id/intlayer_CMS.md +20 -0
  178. package/docs/id/intlayer_with_next-i18next.md +0 -1
  179. package/docs/id/intlayer_with_nextjs_14.md +28 -0
  180. package/docs/id/intlayer_with_nextjs_15.md +28 -0
  181. package/docs/id/intlayer_with_nextjs_16.md +28 -0
  182. package/docs/id/intlayer_with_nextjs_no_locale_path.md +1154 -0
  183. package/docs/id/plugins/sync-json.md +6 -2
  184. package/docs/it/cli/ci.md +137 -0
  185. package/docs/it/cli/index.md +7 -1
  186. package/docs/it/cli/list.md +39 -2
  187. package/docs/it/cli/list_projects.md +130 -0
  188. package/docs/it/intlayer_CMS.md +20 -0
  189. package/docs/it/intlayer_with_next-i18next.md +0 -1
  190. package/docs/it/intlayer_with_nextjs_14.md +28 -0
  191. package/docs/it/intlayer_with_nextjs_15.md +28 -0
  192. package/docs/it/intlayer_with_nextjs_16.md +28 -0
  193. package/docs/it/intlayer_with_nextjs_no_locale_path.md +1148 -0
  194. package/docs/it/plugins/sync-json.md +6 -2
  195. package/docs/ja/cli/ci.md +137 -0
  196. package/docs/ja/cli/index.md +7 -1
  197. package/docs/ja/cli/list.md +38 -1
  198. package/docs/ja/cli/list_projects.md +136 -0
  199. package/docs/ja/intlayer_CMS.md +20 -0
  200. package/docs/ja/intlayer_with_next-i18next.md +0 -1
  201. package/docs/ja/intlayer_with_nextjs_14.md +28 -0
  202. package/docs/ja/intlayer_with_nextjs_15.md +28 -0
  203. package/docs/ja/intlayer_with_nextjs_16.md +28 -0
  204. package/docs/ja/intlayer_with_nextjs_no_locale_path.md +1222 -0
  205. package/docs/ja/plugins/sync-json.md +6 -2
  206. package/docs/ko/cli/ci.md +137 -0
  207. package/docs/ko/cli/index.md +7 -1
  208. package/docs/ko/cli/list.md +38 -1
  209. package/docs/ko/cli/list_projects.md +128 -0
  210. package/docs/ko/intlayer_CMS.md +20 -0
  211. package/docs/ko/intlayer_with_next-i18next.md +0 -1
  212. package/docs/ko/intlayer_with_nextjs_14.md +28 -0
  213. package/docs/ko/intlayer_with_nextjs_15.md +28 -0
  214. package/docs/ko/intlayer_with_nextjs_16.md +28 -0
  215. package/docs/ko/intlayer_with_nextjs_no_locale_path.md +1205 -0
  216. package/docs/ko/plugins/sync-json.md +6 -2
  217. package/docs/pl/cli/ci.md +137 -0
  218. package/docs/pl/cli/index.md +7 -1
  219. package/docs/pl/cli/list.md +39 -2
  220. package/docs/pl/cli/list_projects.md +130 -0
  221. package/docs/pl/intlayer_CMS.md +20 -0
  222. package/docs/pl/intlayer_with_next-i18next.md +0 -1
  223. package/docs/pl/intlayer_with_nextjs_14.md +28 -0
  224. package/docs/pl/intlayer_with_nextjs_15.md +28 -0
  225. package/docs/pl/intlayer_with_nextjs_16.md +28 -0
  226. package/docs/pl/intlayer_with_nextjs_no_locale_path.md +1149 -0
  227. package/docs/pl/plugins/sync-json.md +6 -2
  228. package/docs/pt/cli/ci.md +137 -0
  229. package/docs/pt/cli/index.md +7 -1
  230. package/docs/pt/cli/list.md +39 -2
  231. package/docs/pt/cli/list_projects.md +134 -0
  232. package/docs/pt/intlayer_CMS.md +20 -0
  233. package/docs/pt/intlayer_with_next-i18next.md +0 -1
  234. package/docs/pt/intlayer_with_nextjs_14.md +28 -0
  235. package/docs/pt/intlayer_with_nextjs_15.md +28 -0
  236. package/docs/pt/intlayer_with_nextjs_16.md +28 -0
  237. package/docs/pt/intlayer_with_nextjs_no_locale_path.md +1152 -0
  238. package/docs/pt/plugins/sync-json.md +6 -2
  239. package/docs/ru/cli/ci.md +137 -0
  240. package/docs/ru/cli/index.md +7 -1
  241. package/docs/ru/cli/list.md +39 -2
  242. package/docs/ru/cli/list_projects.md +130 -0
  243. package/docs/ru/intlayer_CMS.md +20 -0
  244. package/docs/ru/intlayer_with_next-i18next.md +0 -1
  245. package/docs/ru/intlayer_with_nextjs_14.md +28 -0
  246. package/docs/ru/intlayer_with_nextjs_15.md +28 -0
  247. package/docs/ru/intlayer_with_nextjs_16.md +28 -0
  248. package/docs/ru/intlayer_with_nextjs_no_locale_path.md +1204 -0
  249. package/docs/ru/plugins/sync-json.md +6 -2
  250. package/docs/tr/cli/ci.md +137 -0
  251. package/docs/tr/cli/index.md +7 -1
  252. package/docs/tr/cli/list.md +39 -2
  253. package/docs/tr/cli/list_projects.md +134 -0
  254. package/docs/tr/intlayer_CMS.md +20 -0
  255. package/docs/tr/intlayer_with_next-i18next.md +0 -1
  256. package/docs/tr/intlayer_with_nextjs_14.md +28 -0
  257. package/docs/tr/intlayer_with_nextjs_15.md +28 -0
  258. package/docs/tr/intlayer_with_nextjs_16.md +28 -0
  259. package/docs/tr/intlayer_with_nextjs_no_locale_path.md +1159 -0
  260. package/docs/tr/plugins/sync-json.md +6 -2
  261. package/docs/uk/compiler.md +133 -0
  262. package/docs/uk/component_i18n.md +194 -0
  263. package/docs/uk/intlayer_with_nextjs_14.md +1646 -0
  264. package/docs/uk/intlayer_with_nextjs_15.md +1910 -0
  265. package/docs/uk/intlayer_with_nextjs_16.md +1763 -0
  266. package/docs/uk/intlayer_with_nextjs_no_locale_path.md +1159 -0
  267. package/docs/uk/intlayer_with_react_native+expo.md +715 -0
  268. package/docs/uk/packages/intlayer/getConfiguration.md +145 -0
  269. package/docs/uk/vs_code_extension.md +133 -0
  270. package/docs/vi/cli/ci.md +137 -0
  271. package/docs/vi/cli/index.md +7 -1
  272. package/docs/vi/cli/list.md +38 -1
  273. package/docs/vi/cli/list_projects.md +130 -0
  274. package/docs/vi/intlayer_CMS.md +20 -0
  275. package/docs/vi/intlayer_with_next-i18next.md +0 -1
  276. package/docs/vi/intlayer_with_nextjs_14.md +28 -0
  277. package/docs/vi/intlayer_with_nextjs_15.md +28 -0
  278. package/docs/vi/intlayer_with_nextjs_16.md +28 -0
  279. package/docs/vi/intlayer_with_nextjs_no_locale_path.md +1151 -0
  280. package/docs/vi/plugins/sync-json.md +6 -2
  281. package/docs/zh/cli/ci.md +137 -0
  282. package/docs/zh/cli/index.md +7 -1
  283. package/docs/zh/cli/list.md +38 -1
  284. package/docs/zh/cli/list_projects.md +130 -0
  285. package/docs/zh/intlayer_CMS.md +20 -0
  286. package/docs/zh/intlayer_with_next-i18next.md +0 -1
  287. package/docs/zh/intlayer_with_nextjs_14.md +28 -0
  288. package/docs/zh/intlayer_with_nextjs_15.md +28 -0
  289. package/docs/zh/intlayer_with_nextjs_16.md +28 -0
  290. package/docs/zh/intlayer_with_nextjs_no_locale_path.md +1206 -0
  291. package/docs/zh/plugins/sync-json.md +9 -5
  292. package/frequent_questions/ar/SSR_Next_no_[locale].md +1 -1
  293. package/frequent_questions/de/SSR_Next_no_[locale].md +1 -1
  294. package/frequent_questions/en/SSR_Next_no_[locale].md +1 -1
  295. package/frequent_questions/en-GB/SSR_Next_no_[locale].md +1 -1
  296. package/frequent_questions/es/SSR_Next_no_[locale].md +1 -1
  297. package/frequent_questions/fr/SSR_Next_no_[locale].md +1 -1
  298. package/frequent_questions/hi/SSR_Next_no_[locale].md +1 -1
  299. package/frequent_questions/id/SSR_Next_no_[locale].md +1 -1
  300. package/frequent_questions/it/SSR_Next_no_[locale].md +1 -1
  301. package/frequent_questions/ja/SSR_Next_no_[locale].md +1 -1
  302. package/frequent_questions/ko/SSR_Next_no_[locale].md +1 -1
  303. package/frequent_questions/pl/SSR_Next_no_[locale].md +1 -1
  304. package/frequent_questions/pt/SSR_Next_no_[locale].md +1 -1
  305. package/frequent_questions/ru/SSR_Next_no_[locale].md +1 -1
  306. package/frequent_questions/tr/SSR_Next_no_[locale].md +1 -1
  307. package/frequent_questions/vi/SSR_Next_no_[locale].md +1 -1
  308. package/frequent_questions/zh/SSR_Next_no_[locale].md +1 -1
  309. package/package.json +6 -6
  310. package/src/generated/blog.entry.ts +29 -0
  311. package/src/generated/docs.entry.ts +157 -0
  312. package/src/generated/frequentQuestions.entry.ts +15 -0
  313. package/src/generated/legal.entry.ts +2 -0
@@ -0,0 +1,1151 @@
1
+ ---
2
+ createdAt: 2026-01-10
3
+ updatedAt: 2026-01-10
4
+ title: Cách dịch ứng dụng Next.js 16 của bạn (không có [locale] trong đường dẫn trang) – Hướng dẫn i18n 2026
5
+ description: Tìm hiểu cách làm cho website Next.js 16 của bạn đa ngôn ngữ mà không cần [locale] trong đường dẫn trang. Làm theo tài liệu để quốc tế hóa (i18n) và dịch nội dung.
6
+ keywords:
7
+ - Quốc tế hóa
8
+ - Tài liệu
9
+ - Intlayer
10
+ - Next.js 16
11
+ - JavaScript
12
+ - React
13
+ slugs:
14
+ - doc
15
+ - environment
16
+ - nextjs
17
+ - no-locale-path
18
+ applicationTemplate: https://github.com/aymericzip/intlayer-next-no-lolale-path-template
19
+ youtubeVideo: https://www.youtube.com/watch?v=e_PPG7PTqGU
20
+ history:
21
+ - version: 1.0.0
22
+ date: 2026-01-10
23
+ changes: Phát hành ban đầu
24
+ ---
25
+
26
+ # Dịch trang web Next.js 16 của bạn (không có [locale] trong đường dẫn trang) bằng Intlayer | Quốc tế hóa (i18n)
27
+
28
+ <Tab defaultTab="video">
29
+ <TabItem label="Video" value="video">
30
+
31
+ <iframe title="Giải pháp i18n tốt nhất cho Next.js? Khám phá Intlayer" class="m-auto aspect-16/9 w-full overflow-hidden rounded-lg border-0" allow="autoplay; gyroscope;" loading="lazy" width="1080" height="auto" src="https://www.youtube.com/embed/e_PPG7PTqGU?autoplay=0&amp;origin=http://intlayer.org&amp;controls=0&amp;rel=1"/>
32
+
33
+ </TabItem>
34
+ <TabItem label="Mã" value="code">
35
+
36
+ <iframe
37
+ src="https://stackblitz.com/github/aymericzip/intlayer-next-16-no-locale-path-template?embed=1&ctl=1&file=intlayer.config.ts"
38
+ className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
39
+ title="Demo CodeSandbox - Cách quốc tế hóa ứng dụng của bạn bằng Intlayer"
40
+ sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
41
+ loading="lazy"
42
+ />
43
+
44
+ </TabItem>
45
+ </Tab>
46
+
47
+ Xem [Mẫu ứng dụng](https://github.com/aymericzip/intlayer-next-no-lolale-path-template) trên GitHub.
48
+
49
+ ## Mục lục
50
+
51
+ <TOC/>
52
+
53
+ ## Intlayer là gì?
54
+
55
+ **Intlayer** là một thư viện quốc tế hóa (i18n) mã nguồn mở, sáng tạo, được thiết kế để đơn giản hóa việc hỗ trợ đa ngôn ngữ trong các ứng dụng web hiện đại. Intlayer tích hợp liền mạch với framework **Next.js 16** mới nhất, bao gồm cả **App Router** mạnh mẽ. Nó được tối ưu để hoạt động với **Server Components** nhằm rendering hiệu quả và tương thích đầy đủ với [**Turbopack**](https://nextjs.org/docs/architecture/turbopack).
56
+
57
+ Với Intlayer, bạn có thể:
58
+
59
+ - **Quản lý bản dịch một cách dễ dàng** bằng cách sử dụng các từ điển khai báo ở cấp component.
60
+ - **Địa phương hóa động metadata**, routes và nội dung.
61
+ - **Truy cập bản dịch trong cả client-side và server-side components**.
62
+ - **Đảm bảo hỗ trợ TypeScript** với các kiểu tự động sinh, cải thiện tính tự hoàn thành và phát hiện lỗi.
63
+ - **Tận dụng các tính năng tiên tiến**, như phát hiện và chuyển đổi locale động.
64
+
65
+ > Intlayer tương thích với Next.js 12, 13, 14 và 16. Nếu bạn đang sử dụng Next.js Page Router, bạn có thể tham khảo [hướng dẫn này](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_with_nextjs_page_router.md). Đối với Next.js 12, 13, 14 với App Router, tham khảo [hướng dẫn này](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_with_nextjs_14.md).
66
+
67
+ ---
68
+
69
+ ## Hướng dẫn từng bước để cài đặt Intlayer trong ứng dụng Next.js
70
+
71
+ ### Bước 1: Cài đặt phụ thuộc
72
+
73
+ Cài đặt các gói cần thiết bằng npm:
74
+
75
+ ```bash packageManager="npm"
76
+ npm install intlayer next-intlayer
77
+ npx intlayer init
78
+ ```
79
+
80
+ ```bash packageManager="pnpm"
81
+ pnpm add intlayer next-intlayer
82
+ pnpm intlayer init
83
+ ```
84
+
85
+ ```bash packageManager="yarn"
86
+ yarn add intlayer next-intlayer
87
+ yarn intlayer init
88
+ ```
89
+
90
+ ```bash packageManager="bun"
91
+ bun add intlayer next-intlayer
92
+ bunx intlayer init
93
+ ```
94
+
95
+ - **intlayer**
96
+
97
+ Gói lõi cung cấp các công cụ quốc tế hóa cho quản lý cấu hình, dịch thuật, [khai báo nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/content_file.md), transpilation, và các [lệnh CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/cli/index.md).
98
+
99
+ - **next-intlayer**
100
+
101
+ Gói tích hợp Intlayer với Next.js. Nó cung cấp các context providers và hooks cho việc quốc tế hóa trong Next.js. Ngoài ra, nó bao gồm plugin Next.js để tích hợp Intlayer với [Webpack](https://webpack.js.org/) hoặc [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack), cũng như proxy để phát hiện locale ưa thích của người dùng, quản lý cookie và xử lý chuyển hướng URL.
102
+
103
+ ### Bước 2: Cấu hình dự án của bạn
104
+
105
+ Dưới đây là cấu trúc cuối cùng mà chúng ta sẽ tạo:
106
+
107
+ ```bash
108
+ .
109
+ ├── src
110
+ │ ├── app
111
+ │ │ ├── layout.tsx
112
+ │ │ ├── page.content.ts
113
+ │ │ └── page.tsx
114
+ │ ├── components
115
+ │ │ ├── clientComponentExample
116
+ │ │ │ ├── client-component-example.content.ts
117
+ │ │ │ └── ClientComponentExample.tsx
118
+ │ │ ├── localeSwitcher
119
+ │ │ │ ├── localeSwitcher.content.ts
120
+ │ │ │ └── LocaleSwitcher.tsx
121
+ │ │ └── serverComponentExample
122
+ │ │ ├── server-component-example.content.ts
123
+ │ │ └── ServerComponentExample.tsx
124
+ │ └── proxy.ts
125
+ ├── intlayer.config.ts
126
+ ├── next.config.ts
127
+ ├── package.json
128
+ └── tsconfig.json
129
+ ```
130
+
131
+ > Nếu bạn không muốn routing theo locale, intlayer có thể được sử dụng như một provider / hook đơn giản. Xem [hướng dẫn này](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_with_nextjs_no_locale_path.md) để biết thêm chi tiết.
132
+
133
+ Tạo một tệp cấu hình để xác định các ngôn ngữ cho ứng dụng của bạn:
134
+
135
+ ```typescript fileName="intlayer.config.ts" codeFormat="typescript"
136
+ import { Locales, type IntlayerConfig } from "intlayer";
137
+
138
+ const config: IntlayerConfig = {
139
+ internationalization: {
140
+ locales: [
141
+ Locales.ENGLISH,
142
+ Locales.FRENCH,
143
+ Locales.SPANISH,
144
+ // Các locale khác của bạn
145
+ ],
146
+ defaultLocale: Locales.ENGLISH,
147
+ },
148
+ routing: {
149
+ mode: "search-params", // hoặc `no-prefix` - Hữu ích cho việc phát hiện trong middleware
150
+ },
151
+ };
152
+
153
+ export default config;
154
+ ```
155
+
156
+ ```javascript fileName="intlayer.config.mjs" codeFormat="esm"
157
+ import { Locales } from "intlayer";
158
+
159
+ /** @type {import('intlayer').IntlayerConfig} */
160
+ const config = {
161
+ internationalization: {
162
+ locales: [
163
+ Locales.ENGLISH,
164
+ Locales.FRENCH,
165
+ Locales.SPANISH,
166
+ // Các locale khác của bạn
167
+ ],
168
+ defaultLocale: Locales.ENGLISH,
169
+ },
170
+ routing: {
171
+ mode: "search-params", // hoặc `no-prefix` - Hữu ích cho việc phát hiện trong middleware
172
+ },
173
+ };
174
+
175
+ export default config;
176
+ ```
177
+
178
+ ```javascript fileName="intlayer.config.cjs" codeFormat="commonjs"
179
+ const { Locales } = require("intlayer");
180
+
181
+ /** @type {import('intlayer').IntlayerConfig} */
182
+ const config = {
183
+ internationalization: {
184
+ locales: [
185
+ Locales.ENGLISH,
186
+ Locales.FRENCH,
187
+ Locales.SPANISH,
188
+ // Các locale khác của bạn
189
+ ],
190
+ defaultLocale: Locales.ENGLISH,
191
+ },
192
+ routing: {
193
+ mode: "search-params", // hoặc `no-prefix` - Hữu ích cho việc phát hiện middleware
194
+ },
195
+ };
196
+
197
+ module.exports = config;
198
+ ```
199
+
200
+ > Thông qua tệp cấu hình này, bạn có thể thiết lập các URL theo ngôn ngữ, chuyển hướng proxy, tên cookie, vị trí và phần mở rộng của các khai báo nội dung, tắt các log của Intlayer trên console, và nhiều thứ khác. Để xem danh sách đầy đủ các tham số có sẵn, tham khảo [tài liệu cấu hình](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/configuration.md).
201
+
202
+ ### Bước 3: Tích hợp Intlayer vào cấu hình Next.js của bạn
203
+
204
+ Configure your Next.js setup to use Intlayer:
205
+
206
+ ```typescript fileName="next.config.ts" codeFormat="typescript"
207
+ import type { NextConfig } from "next";
208
+ import { withIntlayer } from "next-intlayer/server";
209
+
210
+ const nextConfig: NextConfig = {
211
+ /* các tuỳ chọn cấu hình ở đây */
212
+ };
213
+
214
+ export default withIntlayer(nextConfig);
215
+ ```
216
+
217
+ ```typescript fileName="next.config.mjs" codeFormat="esm"
218
+ import { withIntlayer } from "next-intlayer/server";
219
+
220
+ /** @type {import('next').NextConfig} */
221
+ const nextConfig = {
222
+ /* các tùy chọn cấu hình ở đây */
223
+ };
224
+
225
+ export default withIntlayer(nextConfig);
226
+ ```
227
+
228
+ ```typescript fileName="next.config.cjs" codeFormat="commonjs"
229
+ const { withIntlayer } = require("next-intlayer/server");
230
+
231
+ /** @type {import('next').NextConfig} */
232
+ const nextConfig = {
233
+ /* các tùy chọn cấu hình ở đây */
234
+ };
235
+
236
+ module.exports = withIntlayer(nextConfig);
237
+ ```
238
+
239
+ > Plugin Next.js `withIntlayer()` được sử dụng để tích hợp Intlayer với Next.js. Nó đảm bảo việc xây dựng các tệp khai báo nội dung và giám sát chúng ở chế độ phát triển. Nó định nghĩa các biến môi trường của Intlayer trong các môi trường [Webpack](https://webpack.js.org/) hoặc [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack). Ngoài ra, nó cung cấp các alias để tối ưu hiệu năng và đảm bảo tương thích với server components.
240
+
241
+ > Hàm `withIntlayer()` là một hàm trả về promise. Nó cho phép chuẩn bị các từ điển của intlayer trước khi quá trình build bắt đầu. Nếu bạn muốn sử dụng nó cùng các plugin khác, bạn có thể await nó. Ví dụ:
242
+ >
243
+ > ```ts
244
+ > const nextConfig = await withIntlayer(nextConfig);
245
+ > const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);
246
+ >
247
+ > export default nextConfigWithOtherPlugins;
248
+ > ```
249
+ >
250
+ > Nếu bạn muốn sử dụng nó một cách đồng bộ, bạn có thể dùng hàm `withIntlayerSync()`. Ví dụ:
251
+ >
252
+ > ```ts
253
+ > const nextConfig = withIntlayerSync(nextConfig);
254
+ > const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);
255
+ >
256
+ > export default nextConfigWithOtherPlugins;
257
+ > ```
258
+ >
259
+ > Intlayer tự động phát hiện dự án của bạn đang sử dụng **webpack** hay **Turbopack** dựa trên các cờ dòng lệnh `--webpack`, `--turbo`, hoặc `--turbopack`, cũng như phiên bản **Next.js** hiện tại của bạn.
260
+ >
261
+ > Kể từ `next>=16`, nếu bạn đang sử dụng **Rspack**, bạn phải ép Intlayer sử dụng cấu hình webpack bằng cách tắt Turbopack:
262
+ >
263
+ > ```ts
264
+ > withRspack(withIntlayer(nextConfig, { enableTurbopack: false }));
265
+ > ```
266
+
267
+ ### Bước 4: Định nghĩa các route động theo locale
268
+
269
+ Xóa mọi nội dung trong `RootLayout` và thay thế bằng mã sau:
270
+
271
+ ```tsx {3} fileName="src/app/layout.tsx" codeFormat="typescript"
272
+ import type { Metadata } from "next";
273
+ import type { ReactNode } from "react";
274
+ import "./globals.css";
275
+ import { IntlayerClientProvider, LocalPromiseParams } from "next-intlayer";
276
+ import { getHTMLTextDir, getIntlayer } from "intlayer";
277
+ import { getLocale } from "next-intlayer/server";
278
+ export { generateStaticParams } from "next-intlayer";
279
+
280
+ export const generateMetadata = async ({
281
+ params,
282
+ }: LocalPromiseParams): Promise<Metadata> => {
283
+ const { locale } = await params;
284
+ const { title, description, keywords } = getIntlayer("metadata", locale);
285
+
286
+ return {
287
+ title,
288
+ description,
289
+ keywords,
290
+ };
291
+ };
292
+
293
+ const RootLayout = async ({
294
+ children,
295
+ }: Readonly<{
296
+ children: ReactNode;
297
+ }>) => {
298
+ const locale = await getLocale();
299
+
300
+ return (
301
+ <html lang={locale} dir={getHTMLTextDir(locale)}>
302
+ <IntlayerClientProvider defaultLocale={locale}>
303
+ <body>{children}</body>
304
+ </IntlayerClientProvider>
305
+ </html>
306
+ );
307
+ };
308
+
309
+ export default RootLayout;
310
+ ```
311
+
312
+ ```jsx {3} fileName="src/app/layout.mjx" codeFormat="esm"
313
+ import "./globals.css";
314
+ import { IntlayerClientProvider } from "next-intlayer";
315
+ import { getHTMLTextDir, getIntlayer } from "intlayer";
316
+ import { getLocale } from "next-intlayer/server";
317
+ export { generateStaticParams } from "next-intlayer";
318
+
319
+ export const generateMetadata = async ({ params }) => {
320
+ const { locale } = await params;
321
+ const { title, description, keywords } = getIntlayer("metadata", locale);
322
+
323
+ return {
324
+ title,
325
+ description,
326
+ keywords,
327
+ };
328
+ };
329
+
330
+ const RootLayout = async ({ children }) => {
331
+ const locale = await getLocale();
332
+
333
+ return (
334
+ <html lang={locale} dir={getHTMLTextDir(locale)}>
335
+ <IntlayerClientProvider defaultLocale={locale}>
336
+ <body>{children}</body>
337
+ </IntlayerClientProvider>
338
+ </html>
339
+ );
340
+ };
341
+
342
+ export default RootLayout;
343
+ ```
344
+
345
+ ```jsx {1,8} fileName="src/app/layout.csx" codeFormat="commonjs"
346
+ require("./globals.css");
347
+ const { IntlayerClientProvider } = require("next-intlayer");
348
+ const { getHTMLTextDir, getIntlayer } = require("intlayer");
349
+ const { getLocale } = require("next-intlayer/server");
350
+ const { generateStaticParams } = require("next-intlayer");
351
+
352
+ const generateMetadata = async ({ params }) => {
353
+ const { locale } = await params;
354
+ const { title, description, keywords } = getIntlayer("metadata", locale);
355
+
356
+ return {
357
+ title,
358
+ description,
359
+ keywords,
360
+ };
361
+ };
362
+
363
+ const RootLayout = async ({ children }) => {
364
+ const locale = await getLocale();
365
+
366
+ return (
367
+ <html lang={locale} dir={getHTMLTextDir(locale)}>
368
+ <IntlayerClientProvider defaultLocale={locale}>
369
+ <body>{children}</body>
370
+ </IntlayerClientProvider>
371
+ </html>
372
+ );
373
+ };
374
+
375
+ module.exports = {
376
+ default: RootLayout,
377
+ generateStaticParams,
378
+ generateMetadata,
379
+ };
380
+ ```
381
+
382
+ ### Bước 5: Khai báo nội dung của bạn
383
+
384
+ Tạo và quản lý các khai báo nội dung của bạn để lưu trữ các bản dịch:
385
+
386
+ ```tsx fileName="src/app/metadata.content.ts" contentDeclarationFormat="typescript"
387
+ import { t, type Dictionary } from "intlayer";
388
+ import { Metadata } from "next";
389
+
390
+ const metadataContent = {
391
+ key: "metadata",
392
+ content: {
393
+ title: t({
394
+ vi: "Tiêu đề dự án của tôi",
395
+ en: "My Project Title",
396
+ fr: "Le Titre de mon Projet",
397
+ es: "El Título de mi Proyecto",
398
+ }),
399
+
400
+ description: t({
401
+ vi: "Khám phá nền tảng sáng tạo của chúng tôi được thiết kế để đơn giản hóa quy trình làm việc và tăng năng suất.",
402
+ en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
403
+ fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
404
+ es: "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
405
+ }),
406
+
407
+ keywords: t({
408
+ vi: ["đổi mới", "năng suất", "quy trình làm việc", "SaaS"],
409
+ en: ["innovation", "productivity", "workflow", "SaaS"],
410
+ vi: ["đổi mới", "năng suất", "luồng công việc", "SaaS"],
411
+ fr: ["innovation", "productivité", "flux de travail", "SaaS"],
412
+ es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
413
+ }),
414
+ },
415
+ } as Dictionary<Metadata>;
416
+
417
+ export default metadataContent;
418
+ ```
419
+
420
+ ```tsx fileName="src/app/metadata.content.mjs" contentDeclarationFormat="typescript"
421
+ import { t, type Dictionary } from "intlayer";
422
+
423
+ /** @type {import('intlayer').Dictionary<import('next').Metadata>} */
424
+ const metadataContent = {
425
+ key: "metadata",
426
+ content: {
427
+ title: t({
428
+ vi: "Tiêu đề dự án của tôi",
429
+ en: "My Project Title",
430
+ fr: "Le Titre de mon Projet",
431
+ es: "El Título de mi Proyecto",
432
+ }),
433
+
434
+ description: t({
435
+ vi: "Khám phá nền tảng sáng tạo của chúng tôi được thiết kế để đơn giản hóa quy trình làm việc và tăng năng suất.",
436
+ en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
437
+ vi: "Khám phá nền tảng sáng tạo của chúng tôi được thiết kế để hợp lý hóa luồng công việc của bạn và tăng năng suất.",
438
+ fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
439
+ es: "Descubra su plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
440
+ }),
441
+
442
+ keywords: t({
443
+ vi: ["đổi mới", "năng suất", "luồng công việc", "SaaS"],
444
+ en: ["innovation", "productivity", "workflow", "SaaS"],
445
+ fr: ["innovation", "productivité", "flux de travail", "SaaS"],
446
+ es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
447
+ }),
448
+ },
449
+ };
450
+
451
+ export default metadataContent;
452
+ ```
453
+
454
+ ```javascript fileName="src/app/metadata.content.cjs" contentDeclarationFormat="commonjs"
455
+ const { t } = require("intlayer");
456
+
457
+ /** @type {import('intlayer').Dictionary<import('next').Metadata>} */
458
+ const metadataContent = {
459
+ key: "metadata",
460
+ content: {
461
+ title: t({
462
+ vi: "Tiêu đề dự án của tôi",
463
+ en: "My Project Title",
464
+ fr: "Le Titre de mon Projet",
465
+ es: "El Título de mi Proyecto",
466
+ }),
467
+
468
+ description: t({
469
+ vi: "Khám phá nền tảng sáng tạo của chúng tôi được thiết kế để tinh giản quy trình làm việc của bạn và tăng cường năng suất.",
470
+ en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
471
+ fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
472
+ es: "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
473
+ }),
474
+
475
+ keywords: t({
476
+ vi: ["đổi mới", "năng suất", "quy trình làm việc", "SaaS"],
477
+ en: ["innovation", "productivity", "workflow", "SaaS"],
478
+ fr: ["innovation", "productivité", "flux de travail", "SaaS"],
479
+ es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
480
+ }),
481
+ },
482
+ };
483
+
484
+ module.exports = metadataContent;
485
+ ```
486
+
487
+ ```json fileName="src/app/metadata.content.json" contentDeclarationFormat="json"
488
+ {
489
+ "key": "metadata",
490
+ "content": {
491
+ "title": {
492
+ "nodeType": "translation",
493
+ "translation": {
494
+ "vi": "Tiêu đề dự án của tôi",
495
+ "en": "My Project Title",
496
+ "fr": "Le Titre de mon Projet",
497
+ "es": "El Título de mi Proyecto"
498
+ }
499
+ },
500
+ "description": {
501
+ "nodeType": "translation",
502
+ "translation": {
503
+ "vi": "Khám phá nền tảng sáng tạo của chúng tôi được thiết kế để tối ưu hóa quy trình làm việc và tăng năng suất.",
504
+ "en": "Discover our innovative platform designed to streamline your workflow and boost productivity.",
505
+ "fr": "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
506
+ "es": "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad."
507
+ }
508
+ },
509
+ "keywords": {
510
+ "nodeType": "translation",
511
+ "translation": {
512
+ "vi": ["đổi mới", "năng suất", "luồng công việc", "SaaS"],
513
+ "en": ["innovation", "productivity", "workflow", "SaaS"],
514
+ "fr": ["innovation", "productivité", "flux de travail", "SaaS"],
515
+ "es": ["innovación", "productividad", "flujo de trabajo", "SaaS"]
516
+ }
517
+ }
518
+ }
519
+ }
520
+ ```
521
+
522
+ ```tsx fileName="src/app/page.content.ts" contentDeclarationFormat="typescript"
523
+ import { t, type Dictionary } from "intlayer";
524
+
525
+ const pageContent = {
526
+ key: "page",
527
+ content: {
528
+ getStarted: {
529
+ main: t({
530
+ vi: "Bắt đầu bằng cách chỉnh sửa",
531
+ en: "Get started by editing",
532
+ fr: "Commencez par éditer",
533
+ es: "Comience por editar",
534
+ }),
535
+ pageLink: "src/app/page.tsx",
536
+ },
537
+ },
538
+ } satisfies Dictionary;
539
+
540
+ export default pageContent;
541
+ ```
542
+
543
+ ```javascript fileName="src/app/page.content.mjs" contentDeclarationFormat="esm"
544
+ import { t } from "intlayer";
545
+
546
+ // Kiểu: import('intlayer').Dictionary
547
+ /** @type {import('intlayer').Dictionary} */
548
+ const pageContent = {
549
+ key: "page",
550
+ content: {
551
+ getStarted: {
552
+ main: t({
553
+ vi: "Bắt đầu bằng cách chỉnh sửa",
554
+ en: "Get started by editing",
555
+ fr: "Commencez par éditer",
556
+ es: "Comience por editar",
557
+ }),
558
+ pageLink: "src/app/page.tsx",
559
+ },
560
+ },
561
+ };
562
+
563
+ export default pageContent;
564
+ ```
565
+
566
+ ```javascript fileName="src/app/page.content.cjs" contentDeclarationFormat="commonjs"
567
+ const { t } = require("intlayer");
568
+
569
+ // Kiểu: import('intlayer').Dictionary
570
+ /** @type {import('intlayer').Dictionary} */
571
+ const pageContent = {
572
+ key: "page",
573
+ content: {
574
+ getStarted: {
575
+ main: t({
576
+ vi: "Bắt đầu bằng cách chỉnh sửa",
577
+ en: "Get started by editing",
578
+ fr: "Commencez par éditer",
579
+ vi: "Bắt đầu bằng cách chỉnh sửa",
580
+ es: "Comience por editar",
581
+ }),
582
+ pageLink: "src/app/page.tsx",
583
+ },
584
+ },
585
+ };
586
+
587
+ module.exports = pageContent;
588
+ ```
589
+
590
+ ```json fileName="src/app/page.content.json" contentDeclarationFormat="json"
591
+ {
592
+ "$schema": "https://intlayer.org/schema.json",
593
+ "key": "page",
594
+ "content": {
595
+ "getStarted": {
596
+ "nodeType": "translation",
597
+ "translation": {
598
+ "vi": "Bắt đầu bằng cách chỉnh sửa",
599
+ "en": "Get started by editing",
600
+ "fr": "Commencez par éditer",
601
+ "es": "Comience por editar"
602
+ }
603
+ },
604
+ "pageLink": "src/app/page.tsx"
605
+ }
606
+ }
607
+ ```
608
+
609
+ > Các khai báo nội dung của bạn có thể được định nghĩa ở bất kỳ đâu trong ứng dụng của bạn miễn là chúng được đưa vào thư mục `contentDir` (mặc định, `./src`). Và khớp với phần mở rộng tệp khai báo nội dung (mặc định, `.content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}`).
610
+
611
+ > Để biết thêm chi tiết, tham khảo [tài liệu khai báo nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/content_file.md).
612
+
613
+ ### Bước 6: Sử dụng Nội dung trong Mã của Bạn
614
+
615
+ Truy cập các từ điển nội dung của bạn trong toàn bộ ứng dụng:
616
+
617
+ ```tsx fileName="src/app/page.tsx" codeFormat="typescript"
618
+ import type { FC } from "react";
619
+ import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
620
+ import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
621
+ import {
622
+ IntlayerServerProvider,
623
+ useIntlayer,
624
+ getLocale,
625
+ } from "next-intlayer/server";
626
+ import { NextPage } from "next";
627
+ import { headers, cookies } from "next/headers";
628
+
629
+ const PageContent: FC = () => {
630
+ const content = useIntlayer("page");
631
+
632
+ return (
633
+ <>
634
+ <p>{content.getStarted.main}</p>
635
+ <code>{content.getStarted.pageLink}</code>
636
+ </>
637
+ );
638
+ };
639
+
640
+ const Page: NextPage = async () => {
641
+ const locale = await getLocale();
642
+
643
+ return (
644
+ <IntlayerServerProvider locale={locale}>
645
+ <PageContent />
646
+ <ServerComponentExample />
647
+ <ClientComponentExample />
648
+ </IntlayerServerProvider>
649
+ );
650
+ };
651
+
652
+ export default Page;
653
+ ```
654
+
655
+ ```jsx fileName="src/app/page.mjx" codeFormat="esm"
656
+ import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
657
+ import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
658
+ import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
659
+ import { getLocale } from "intlayer";
660
+ import { headers, cookies } from "next/headers";
661
+ import { NextPage } from "next";
662
+
663
+ const Page: NextPage = async () => {
664
+ const content = useIntlayer("page");
665
+
666
+ return (
667
+ <>
668
+ <p>{content.getStarted.main}</p>
669
+ <code>{content.getStarted.pageLink}</code>
670
+ </>
671
+ );
672
+ };
673
+
674
+ const Page = async () => {
675
+
676
+ const locale = await getLocale();
677
+
678
+ return (
679
+ <IntlayerServerProvider locale={locale}>
680
+ <PageContent />
681
+ <ServerComponentExample />
682
+ <ClientComponentExample />
683
+ </IntlayerServerProvider>
684
+ );
685
+ };
686
+
687
+ export default Page;
688
+ ```
689
+
690
+ ````jsx fileName="src/app/page.csx" codeFormat="commonjs"
691
+ import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
692
+ import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
693
+ import { IntlayerServerProvider, useIntlayer, getLocale } from "next-intlayer/server";
694
+ import { NextPage } from "next";
695
+ import { headers, cookies } from "next/headers";
696
+
697
+ const Page: NextPage = async () => {
698
+ const content = useIntlayer("page");
699
+
700
+ return (
701
+ <>
702
+ <p>{content.getStarted.main}</p>
703
+ <code>{content.getStarted.pageLink}</code>
704
+ </>
705
+ );
706
+ };
707
+
708
+ const Page: NextPage = async () => {
709
+ const locale = await getLocale();
710
+
711
+ return (
712
+ <IntlayerServerProvider locale={locale}>
713
+ <PageContent />
714
+ <ServerComponentExample />
715
+ <ClientComponentExample />
716
+ </IntlayerServerProvider>
717
+ );
718
+ };
719
+
720
+ - **`IntlayerClientProvider`** được sử dụng để cung cấp locale cho các component phía client. Nó có thể được đặt trong bất kỳ component cha nào, bao gồm cả layout. Tuy nhiên, khuyến nghị đặt nó trong layout vì Next.js chia sẻ mã layout giữa các trang, giúp hiệu quả hơn. Bằng cách sử dụng `IntlayerClientProvider` trong layout, bạn tránh phải khởi tạo lại cho mỗi trang, cải thiện hiệu năng và duy trì một ngữ cảnh localization nhất quán trong toàn bộ ứng dụng.
721
+ - **`IntlayerServerProvider`** được sử dụng để cung cấp locale cho các thành phần con chạy trên server. Nó không thể được đặt trong layout.
722
+
723
+ > Layout và page không thể chia sẻ cùng một server context vì hệ thống server context dựa trên một kho dữ liệu theo từng yêu cầu (thông qua cơ chế [React's cache](https://react.dev/reference/react/cache)), khiến mỗi "context" được tạo lại cho các đoạn khác nhau của ứng dụng. Đặt provider trong một layout chia sẻ sẽ phá vỡ sự cô lập này, ngăn việc truyền đúng các giá trị server context tới các server component của bạn.
724
+
725
+ ```tsx {4,7} fileName="src/components/clientComponentExample/ClientComponentExample.tsx" codeFormat="typescript"
726
+ "use client";
727
+
728
+ import type { FC } from "react";
729
+ import { useIntlayer } from "next-intlayer";
730
+
731
+ export const ClientComponentExample: FC = () => {
732
+ const content = useIntlayer("client-component-example"); // Tạo khai báo nội dung liên quan
733
+
734
+ return (
735
+ <div>
736
+ <h2>{content.title}</h2>
737
+ <p>{content.content}</p>
738
+ </div>
739
+ );
740
+ };
741
+ ````
742
+
743
+ ```jsx {3,6} fileName="src/components/clientComponentExample/ClientComponentExample.mjx" codeFormat="esm"
744
+ "use client";
745
+
746
+ import { useIntlayer } from "next-intlayer";
747
+
748
+ const ClientComponentExample = () => {
749
+ const content = useIntlayer("client-component-example"); // Tạo khai báo nội dung liên quan
750
+
751
+ return (
752
+ <div>
753
+ <h2>{content.title}</h2>
754
+ <p>{content.content}</p>
755
+ </div>
756
+ );
757
+ };
758
+ ```
759
+
760
+ ```jsx {3,6} fileName="src/components/clientComponentExample/ClientComponentExample.csx" codeFormat="commonjs"
761
+ "use client";
762
+
763
+ const { useIntlayer } = require("next-intlayer");
764
+
765
+ const ClientComponentExample = () => {
766
+ const content = useIntlayer("client-component-example"); // Tạo khai báo nội dung liên quan
767
+
768
+ return (
769
+ <div>
770
+ <h2>{content.title}</h2>
771
+ <p>{content.content}</p>
772
+ </div>
773
+ );
774
+ };
775
+ ```
776
+
777
+ ```tsx {2} fileName="src/components/serverComponentExample/ServerComponentExample.tsx" codeFormat="typescript"
778
+ import type { FC } from "react";
779
+ import { useIntlayer } from "next-intlayer/server";
780
+
781
+ export const ServerComponentExample: FC = () => {
782
+ const content = useIntlayer("server-component-example"); // Tạo khai báo nội dung liên quan
783
+
784
+ return (
785
+ <div>
786
+ <h2>{content.title}</h2>
787
+ <p>{content.content}</p>
788
+ </div>
789
+ );
790
+ };
791
+ ```
792
+
793
+ ```jsx {1} fileName="src/components/serverComponentExample/ServerComponentExample.mjx" codeFormat="esm"
794
+ import { useIntlayer } from "next-intlayer/server";
795
+
796
+ const ServerComponentExample = () => {
797
+ const content = useIntlayer("server-component-example"); // Tạo khai báo nội dung liên quan
798
+
799
+ return (
800
+ <div>
801
+ <h2>{content.title}</h2>
802
+ <p>{content.content}</p>
803
+ </div>
804
+ );
805
+ };
806
+ ```
807
+
808
+ ```jsx {1} fileName="src/components/serverComponentExample/ServerComponentExample.csx" codeFormat="commonjs"
809
+ const { useIntlayer } = require("next-intlayer/server");
810
+
811
+ const ServerComponentExample = () => {
812
+ const content = useIntlayer("server-component-example"); // Tạo khai báo nội dung liên quan
813
+
814
+ return (
815
+ <div>
816
+ <h2>{content.title}</h2>
817
+ <p>{content.content}</p>
818
+ </div>
819
+ );
820
+ };
821
+ ```
822
+
823
+ > Nếu bạn muốn sử dụng nội dung của mình trong một thuộc tính `string`, chẳng hạn như `alt`, `title`, `href`, `aria-label`, v.v., bạn phải gọi giá trị của hàm, ví dụ:
824
+
825
+ > ```jsx
826
+ > <img src={content.image.src.value} alt={content.image.value} />
827
+ > ```
828
+
829
+ > Để tìm hiểu thêm về hook `useIntlayer`, tham khảo [tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/next-intlayer/useIntlayer.md).
830
+
831
+ ### (Tùy chọn) Bước 7: Cấu hình Proxy để phát hiện locale
832
+
833
+ Thiết lập proxy để phát hiện locale ưu tiên của người dùng:
834
+
835
+ ```typescript fileName="src/proxy.ts" codeFormat="typescript"
836
+ export { intlayerProxy as proxy } from "next-intlayer/proxy";
837
+
838
+ export const config = {
839
+ matcher:
840
+ "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
841
+ };
842
+ ```
843
+
844
+ ```javascript fileName="src/proxy.mjs" codeFormat="esm"
845
+ export { intlayerProxy as proxy } from "next-intlayer/proxy";
846
+
847
+ export const config = {
848
+ matcher:
849
+ "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
850
+ };
851
+ ```
852
+
853
+ ```javascript fileName="src/proxy.cjs" codeFormat="commonjs"
854
+ const { intlayerProxy } = require("next-intlayer/proxy");
855
+
856
+ const config = {
857
+ matcher:
858
+ "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
859
+ };
860
+
861
+ module.exports = { proxy: intlayerProxy, config };
862
+ ```
863
+
864
+ > `intlayerProxy` được dùng để phát hiện ngôn ngữ ưa thích của người dùng và chuyển hướng họ đến URL phù hợp như được chỉ định trong [cấu hình](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/configuration.md). Ngoài ra, nó còn cho phép lưu ngôn ngữ ưa thích của người dùng vào cookie.
865
+
866
+ > Nếu bạn cần xâu chuỗi nhiều proxy với nhau (ví dụ: `intlayerProxy` cùng với proxy xác thực hoặc proxy tuỳ chỉnh), Intlayer hiện cung cấp một helper gọi là `multipleProxies`.
867
+
868
+ ```ts
869
+ import { multipleProxies, intlayerProxy } from "next-intlayer/proxy";
870
+ import { customProxy } from "@utils/customProxy";
871
+
872
+ export const proxy = multipleProxies([intlayerProxy, customProxy]);
873
+ ```
874
+
875
+ ### (Tùy chọn) Bước 8: Thay đổi ngôn ngữ nội dung của bạn
876
+
877
+ Để thay đổi ngôn ngữ nội dung của bạn trong Next.js, cách được khuyến nghị là sử dụng component `Link` để chuyển hướng người dùng đến trang đã được địa phương hóa tương ứng. Component `Link` cho phép prefetch trang, giúp tránh phải tải lại toàn bộ trang.
878
+
879
+ ```tsx fileName="src/components/localeSwitcher/LocaleSwitcher.tsx" codeFormat="typescript"
880
+ "use client";
881
+
882
+ import type { FC } from "react";
883
+ import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";
884
+ import { useLocale } from "next-intlayer";
885
+
886
+ export const LocaleSwitcher: FC = () => {
887
+ const { locale, availableLocales, setLocale } = useLocale({
888
+ onChange: () => window.location.reload(),
889
+ });
890
+
891
+ return (
892
+ <div>
893
+ <button popoverTarget="localePopover">{getLocaleName(locale)}</button>
894
+ <div id="localePopover" popover="auto">
895
+ {availableLocales.map((localeItem) => (
896
+ <button
897
+ key={localeItem}
898
+ aria-current={locale === localeItem ? "page" : undefined}
899
+ onClick={() => setLocale(localeItem)}
900
+ >
901
+ <span>
902
+ {/* Locale - ví dụ: FR */}
903
+ {localeItem}
904
+ </span>
905
+ <span>
906
+ {/* Tên ngôn ngữ theo chính locale đó - ví dụ: Français */}
907
+ {getLocaleName(localeItem, locale)}
908
+ </span>
909
+ <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
910
+ {/* Tên ngôn ngữ theo locale hiện tại - ví dụ: Francés khi locale hiện tại là Locales.SPANISH */}
911
+ {getLocaleName(localeItem)}
912
+ </span>
913
+ <span dir="ltr" lang={Locales.ENGLISH}>
914
+ {/* Ngôn ngữ bằng tiếng Anh - ví dụ: French */}
915
+ {getLocaleName(localeItem, Locales.ENGLISH)}
916
+ </span>
917
+ </button>
918
+ ))}
919
+ </div>
920
+ </div>
921
+ );
922
+ };
923
+ ```
924
+
925
+ ```jsx fileName="src/components/localeSwitcher/LocaleSwitcher.msx" codeFormat="esm"
926
+ "use client";
927
+
928
+ import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";
929
+ import { useLocale } from "next-intlayer";
930
+
931
+ export const LocaleSwitcher = () => {
932
+ const { locale, availableLocales, setLocale } = useLocale({
933
+ onChange: () => window.location.reload(),
934
+ });
935
+
936
+ return (
937
+ <div>
938
+ <button popoverTarget="localePopover">{getLocaleName(locale)}</button>
939
+ <div id="localePopover" popover="auto">
940
+ {availableLocales.map((localeItem) => (
941
+ <button
942
+ key={localeItem}
943
+ aria-current={locale === localeItem ? "page" : undefined}
944
+ onClick={() => setLocale(localeItem)}
945
+ >
946
+ <span>
947
+ {/* Locale - ví dụ: FR */}
948
+ {localeItem}
949
+ </span>
950
+ <span>
951
+ {/* Ngôn ngữ theo chính locale của nó - ví dụ: Français */}
952
+ {getLocaleName(localeItem, locale)}
953
+ </span>
954
+ <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
955
+ {/* Ngôn ngữ theo locale hiện tại - ví dụ: Francés khi locale hiện tại đặt thành Locales.SPANISH */}
956
+ {getLocaleName(localeItem)}
957
+ </span>
958
+ <span dir="ltr" lang={Locales.ENGLISH}>
959
+ {/* Ngôn ngữ bằng tiếng Anh - ví dụ: French */}
960
+ {getLocaleName(localeItem, Locales.ENGLISH)}
961
+ </span>
962
+ </button>
963
+ ))}
964
+ </div>
965
+ </div>
966
+ );
967
+ };
968
+ ```
969
+
970
+ ````jsx fileName="src/components/localeSwitcher/LocaleSwitcher.csx" codeFormat="commonjs"
971
+ "use client";
972
+
973
+ const { Locales, getHTMLTextDir, getLocaleName } = require("intlayer");
974
+ const { useLocale } = require("next-intlayer");
975
+
976
+ export const LocaleSwitcher = () => {
977
+ const path
978
+ const { locale availableLocales, setLocale } = useLocale({
979
+ onChange: ()=> window.location.reload(),
980
+ });
981
+
982
+ return (
983
+ <div>
984
+ <button popoverTarget="localePopover">{getLocaleName(locale)}</button>
985
+ <div id="localePopover" popover="auto">
986
+ {availableLocales.map((localeItem) => (
987
+ <button
988
+ key={localeItem}
989
+ aria-current={locale === localeItem ? "page" : undefined}
990
+ onClick={() => setLocale(localeItem)}
991
+ >
992
+ <span>
993
+ {/* Locale - ví dụ: FR */}
994
+ {localeItem}
995
+ </span>
996
+ <span>
997
+ {/* Tên ngôn ngữ theo chính locale của nó - ví dụ: Français */}
998
+ {getLocaleName(localeItem, locale)}
999
+ </span>
1000
+ <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
1001
+ {/* Tên ngôn ngữ theo locale hiện tại - ví dụ: Francés khi locale hiện tại được đặt là Locales.SPANISH */}
1002
+ {getLocaleName(localeItem)}
1003
+ </span>
1004
+ <span dir="ltr" lang={Locales.ENGLISH}>
1005
+ {/* Tên ngôn ngữ bằng tiếng Anh - ví dụ: French */}
1006
+ {getLocaleName(localeItem, Locales.ENGLISH)}
1007
+ </span>
1008
+ </button>
1009
+ ))}
1010
+ </div>
1011
+ </div>
1012
+ );
1013
+ };
1014
+
1015
+ > Một cách thay thế là sử dụng hàm `setLocale` được cung cấp bởi hook `useLocale`. Hàm này sẽ không cho phép prefetch trang. Xem tài liệu của [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/next-intlayer/useLocale.md) để biết thêm chi tiết.
1016
+
1017
+ > Tài liệu tham khảo:
1018
+ >
1019
+ > - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/next-intlayer/useLocale.md)
1020
+ > - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/next-intlayer/getLocaleName.md)
1021
+ > - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/next-intlayer/getLocalizedUrl.md)
1022
+ > - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/intlayer/getHTMLTextDir.md)
1023
+ > - [`hrefLang` thuộc tính](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr)
1024
+ > - [`lang` thuộc tính](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)
1025
+ > - [`dir` thuộc tính](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
1026
+ > - [`aria-current` thuộc tính](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)
1027
+
1028
+ ### (Tùy chọn) Bước 9: Lấy locale hiện tại trong Server Actions
1029
+
1030
+ Nếu bạn cần locale đang hoạt động bên trong một Server Action (ví dụ: để bản địa hóa email hoặc thực thi logic phụ thuộc locale), gọi `getLocale` từ `next-intlayer/server`:
1031
+
1032
+ ```tsx fileName="src/app/actions/getLocale.ts" codeFormat="typescript"
1033
+ "use server";
1034
+
1035
+ import { getLocale } from "next-intlayer/server";
1036
+
1037
+ export const myServerAction = async () => {
1038
+ const locale = await getLocale();
1039
+
1040
+ // Thực hiện xử lý với locale
1041
+ };
1042
+ ````
1043
+
1044
+ > Hàm `getLocale` tuân theo chiến lược phân lớp (cascading) để xác định locale của người dùng:
1045
+ >
1046
+ > 1. Đầu tiên, nó kiểm tra header của yêu cầu để tìm giá trị locale có thể đã được proxy thiết lập
1047
+ > 2. Nếu không tìm thấy locale trong header, nó sẽ tìm locale được lưu trong cookie
1048
+ > 3. Nếu không có cookie, nó sẽ cố gắng phát hiện ngôn ngữ ưa thích của người dùng từ cài đặt trình duyệt
1049
+ > 4. Trong trường hợp cuối cùng, nó sẽ sử dụng locale mặc định được cấu hình cho ứng dụng
1050
+ >
1051
+ > Điều này đảm bảo lựa chọn locale phù hợp nhất dựa trên ngữ cảnh hiện có.
1052
+
1053
+ ### (Tùy chọn) Bước 10: Tối ưu kích thước bundle của bạn
1054
+
1055
+ Khi sử dụng `next-intlayer`, các từ điển (dictionaries) được bao gồm trong bundle cho mọi trang theo mặc định. Để tối ưu kích thước bundle, Intlayer cung cấp một plugin SWC tùy chọn thay thế một cách thông minh các lần gọi `useIntlayer` bằng các macro. Điều này đảm bảo các từ điển chỉ được đưa vào bundle của những trang thực sự sử dụng chúng.
1056
+
1057
+ Để bật tối ưu này, cài đặt gói `@intlayer/swc`. Khi đã cài, `next-intlayer` sẽ tự động phát hiện và sử dụng plugin:
1058
+
1059
+ ```bash packageManager="npm"
1060
+ npm install @intlayer/swc --save-dev
1061
+ npx intlayer init
1062
+ ```
1063
+
1064
+ ```bash packageManager="pnpm"
1065
+ pnpm add @intlayer/swc --save-dev
1066
+ pnpm intlayer init
1067
+ ```
1068
+
1069
+ ```bash packageManager="yarn"
1070
+ yarn add @intlayer/swc --save-dev
1071
+ yarn intlayer init
1072
+ ```
1073
+
1074
+ ```bash packageManager="bun"
1075
+ bun add @intlayer/swc --dev
1076
+ bunx intlayer init
1077
+ ```
1078
+
1079
+ > Lưu ý: Tối ưu hóa này chỉ có sẵn cho Next.js 13 trở lên.
1080
+
1081
+ > Lưu ý: Gói này không được cài mặc định vì plugin SWC vẫn đang ở giai đoạn thử nghiệm trên Next.js. Điều này có thể thay đổi trong tương lai.
1082
+
1083
+ > Lưu ý: Nếu bạn đặt tùy chọn là `importMode: 'dynamic'` hoặc `importMode: 'live'`, nó sẽ phụ thuộc vào Suspense, vì vậy bạn phải bao bọc các lệnh gọi `useIntlayer` bằng một boundary `Suspense`. Điều đó có nghĩa là bạn sẽ không thể sử dụng `useIntlayer` trực tiếp ở cấp cao nhất của component Page / Layout.
1084
+
1085
+ ### Theo dõi thay đổi từ điển trên Turbopack
1086
+
1087
+ Khi sử dụng Turbopack làm development server với lệnh `next dev`, các thay đổi trong từ điển sẽ không được phát hiện tự động theo mặc định.
1088
+
1089
+ Hạn chế này xảy ra vì Turbopack không thể chạy các plugin webpack song song để theo dõi thay đổi trong các tệp nội dung của bạn. Để khắc phục, bạn cần dùng lệnh `intlayer watch` để chạy đồng thời development server và trình quan sát build của Intlayer.
1090
+
1091
+ ```json5 fileName="package.json"
1092
+ {
1093
+ // ... Cấu hình package.json hiện có của bạn
1094
+ "scripts": {
1095
+ // ... Cấu hình scripts hiện có của bạn
1096
+ "dev": "intlayer watch --with 'next dev'",
1097
+ },
1098
+ }
1099
+ ```
1100
+
1101
+ > Nếu bạn đang sử dụng next-intlayer@<=6.x.x, bạn cần giữ flag `--turbopack` để ứng dụng Next.js 16 hoạt động đúng với Turbopack. Chúng tôi khuyến nghị sử dụng next-intlayer@>=7.x.x để tránh hạn chế này.
1102
+
1103
+ ### Cấu hình TypeScript
1104
+
1105
+ Intlayer sử dụng module augmentation để tận dụng lợi ích của TypeScript và làm cho codebase của bạn mạnh mẽ hơn.
1106
+
1107
+ ![Tự hoàn thành](https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true)
1108
+
1109
+ ![Lỗi dịch](https://github.com/aymericzip/intlayer/blob/main/docs/assets/translation_error.png?raw=true)
1110
+
1111
+ Đảm bảo cấu hình TypeScript của bạn bao gồm các kiểu được tạo tự động.
1112
+
1113
+ ```json5 fileName="tsconfig.json"
1114
+ {
1115
+ // ... Các cấu hình TypeScript hiện có của bạn
1116
+ "include": [
1117
+ // ... Các cấu hình TypeScript hiện có của bạn
1118
+ ".intlayer/**/*.ts", // Bao gồm các kiểu được tạo tự động
1119
+ ],
1120
+ }
1121
+ ```
1122
+
1123
+ ### Cấu hình Git
1124
+
1125
+ Nên bỏ qua các tệp được Intlayer tạo ra. Điều này giúp bạn tránh commit chúng vào kho Git của mình.
1126
+
1127
+ Để làm điều này, bạn có thể thêm các hướng dẫn sau vào tệp `.gitignore` của mình:
1128
+
1129
+ ```plaintext fileName=".gitignore"
1130
+ # Bỏ qua các tệp do Intlayer tạo ra
1131
+ .intlayer
1132
+ ```
1133
+
1134
+ ### Tiện ích mở rộng VS Code
1135
+
1136
+ Để cải thiện trải nghiệm phát triển với Intlayer, bạn có thể cài đặt **Tiện ích mở rộng Intlayer cho VS Code** chính thức.
1137
+
1138
+ [Cài đặt từ VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
1139
+
1140
+ Tiện ích mở rộng này cung cấp:
1141
+
1142
+ - **Tự động hoàn thành** cho các khóa dịch.
1143
+ - **Phát hiện lỗi theo thời gian thực** cho các bản dịch bị thiếu.
1144
+ - **Xem trước trực tiếp** của nội dung đã dịch.
1145
+ - **Hành động nhanh** để dễ dàng tạo và cập nhật bản dịch.
1146
+
1147
+ Để biết chi tiết cách sử dụng extension, tham khảo [tài liệu Intlayer VS Code Extension](https://intlayer.org/doc/vs-code-extension).
1148
+
1149
+ ### Mở rộng
1150
+
1151
+ Để mở rộng, bạn có thể triển khai [trình soạn thảo trực quan](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_visual_editor.md) hoặc externalize nội dung của bạn bằng cách sử dụng [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_CMS.md).