@intlayer/docs 9.5.2 → 9.5.3

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 (384) hide show
  1. package/README.md +1 -1
  2. package/blog/ar/i18next_vs_intlayer-i18next.md +327 -0
  3. package/blog/ar/i18next_vs_intlayer.md +445 -0
  4. package/blog/ar/is_i18next_outdated.md +1 -1
  5. package/blog/ar/is_next-intl_outdated.md +1 -1
  6. package/blog/ar/is_vue-i18n_outdated.md +1 -1
  7. package/blog/ar/lingui_vs_intlayer-lingui.md +304 -0
  8. package/blog/ar/lingui_vs_intlayer.md +381 -0
  9. package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  10. package/blog/ar/next-intl_vs_intlayer-next-intl.md +309 -0
  11. package/blog/ar/next-intl_vs_intlayer.md +397 -0
  12. package/blog/ar/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  13. package/blog/ar/vue-i18n_vs_intlayer-vue-i18n.md +286 -0
  14. package/blog/ar/vue-i18n_vs_intlayer_benchmark.md +0 -0
  15. package/blog/de/i18next_vs_intlayer-i18next.md +327 -0
  16. package/blog/de/i18next_vs_intlayer.md +445 -0
  17. package/blog/de/is_i18next_outdated.md +1 -1
  18. package/blog/de/is_next-intl_outdated.md +1 -1
  19. package/blog/de/is_vue-i18n_outdated.md +1 -1
  20. package/blog/de/lingui_vs_intlayer-lingui.md +304 -0
  21. package/blog/de/lingui_vs_intlayer.md +381 -0
  22. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  23. package/blog/de/next-intl_vs_intlayer-next-intl.md +309 -0
  24. package/blog/de/next-intl_vs_intlayer.md +415 -0
  25. package/blog/de/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  26. package/blog/de/vue-i18n_vs_intlayer_benchmark.md +355 -0
  27. package/blog/en/i18next_vs_intlayer-i18next.md +327 -0
  28. package/blog/en/i18next_vs_intlayer.md +445 -0
  29. package/blog/en/is_i18next_outdated.md +1 -1
  30. package/blog/en/is_next-intl_outdated.md +1 -1
  31. package/blog/en/is_vue-i18n_outdated.md +1 -1
  32. package/blog/en/lingui_vs_intlayer-lingui.md +304 -0
  33. package/blog/en/lingui_vs_intlayer.md +381 -0
  34. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  35. package/blog/en/next-intl_vs_intlayer-next-intl.md +309 -0
  36. package/blog/en/next-intl_vs_intlayer.md +415 -0
  37. package/blog/en/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  38. package/blog/en/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  39. package/blog/en/vue-i18n_vs_intlayer.md +1 -1
  40. package/blog/en/vue-i18n_vs_intlayer_benchmark.md +361 -0
  41. package/blog/en-GB/i18next_vs_intlayer-i18next.md +327 -0
  42. package/blog/en-GB/i18next_vs_intlayer.md +445 -0
  43. package/blog/en-GB/is_i18next_outdated.md +1 -1
  44. package/blog/en-GB/is_next-intl_outdated.md +1 -1
  45. package/blog/en-GB/is_vue-i18n_outdated.md +1 -1
  46. package/blog/en-GB/lingui_vs_intlayer-lingui.md +304 -0
  47. package/blog/en-GB/lingui_vs_intlayer.md +381 -0
  48. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  49. package/blog/en-GB/next-intl_vs_intlayer-next-intl.md +309 -0
  50. package/blog/en-GB/next-intl_vs_intlayer.md +415 -0
  51. package/blog/en-GB/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  52. package/blog/en-GB/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  53. package/blog/en-GB/vue-i18n_vs_intlayer.md +1 -1
  54. package/blog/en-GB/vue-i18n_vs_intlayer_benchmark.md +245 -0
  55. package/blog/es/i18next_vs_intlayer-i18next.md +327 -0
  56. package/blog/es/i18next_vs_intlayer.md +445 -0
  57. package/blog/es/is_i18next_outdated.md +1 -1
  58. package/blog/es/is_next-intl_outdated.md +1 -1
  59. package/blog/es/is_vue-i18n_outdated.md +1 -1
  60. package/blog/es/lingui_vs_intlayer-lingui.md +304 -0
  61. package/blog/es/lingui_vs_intlayer.md +381 -0
  62. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  63. package/blog/es/next-intl_vs_intlayer-next-intl.md +309 -0
  64. package/blog/es/next-intl_vs_intlayer.md +417 -0
  65. package/blog/es/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  66. package/blog/es/vue-i18n_vs_intlayer_benchmark.md +363 -0
  67. package/blog/fr/i18next_vs_intlayer-i18next.md +327 -0
  68. package/blog/fr/i18next_vs_intlayer.md +445 -0
  69. package/blog/fr/is_i18next_outdated.md +1 -1
  70. package/blog/fr/is_next-intl_outdated.md +1 -1
  71. package/blog/fr/is_vue-i18n_outdated.md +1 -1
  72. package/blog/fr/lingui_vs_intlayer-lingui.md +304 -0
  73. package/blog/fr/lingui_vs_intlayer.md +381 -0
  74. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  75. package/blog/fr/next-intl_vs_intlayer-next-intl.md +309 -0
  76. package/blog/fr/next-intl_vs_intlayer.md +417 -0
  77. package/blog/fr/vue-i18n_vs_intlayer-vue-i18n.md +287 -0
  78. package/blog/fr/vue-i18n_vs_intlayer_benchmark.md +39 -0
  79. package/blog/hi/i18next_vs_intlayer-i18next.md +327 -0
  80. package/blog/hi/i18next_vs_intlayer.md +445 -0
  81. package/blog/hi/is_i18next_outdated.md +1 -1
  82. package/blog/hi/is_next-intl_outdated.md +1 -1
  83. package/blog/hi/is_vue-i18n_outdated.md +1 -1
  84. package/blog/hi/lingui_vs_intlayer-lingui.md +304 -0
  85. package/blog/hi/lingui_vs_intlayer.md +381 -0
  86. package/blog/hi/next-intl_vs_intlayer-next-intl.md +309 -0
  87. package/blog/hi/next-intl_vs_intlayer.md +397 -0
  88. package/blog/hi/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  89. package/blog/hi/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  90. package/blog/hi/vue-i18n_vs_intlayer_benchmark.md +0 -0
  91. package/blog/id/i18next_vs_intlayer-i18next.md +327 -0
  92. package/blog/id/i18next_vs_intlayer.md +445 -0
  93. package/blog/id/is_i18next_outdated.md +1 -1
  94. package/blog/id/is_next-intl_outdated.md +1 -1
  95. package/blog/id/is_vue-i18n_outdated.md +1 -1
  96. package/blog/id/lingui_vs_intlayer-lingui.md +304 -0
  97. package/blog/id/lingui_vs_intlayer.md +381 -0
  98. package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  99. package/blog/id/next-intl_vs_intlayer-next-intl.md +310 -0
  100. package/blog/id/next-intl_vs_intlayer.md +397 -0
  101. package/blog/id/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  102. package/blog/id/vue-i18n_vs_intlayer-vue-i18n.md +36 -0
  103. package/blog/id/vue-i18n_vs_intlayer.md +1 -1
  104. package/blog/id/vue-i18n_vs_intlayer_benchmark.md +41 -0
  105. package/blog/it/i18next_vs_intlayer-i18next.md +327 -0
  106. package/blog/it/i18next_vs_intlayer.md +445 -0
  107. package/blog/it/is_i18next_outdated.md +1 -1
  108. package/blog/it/is_next-intl_outdated.md +1 -1
  109. package/blog/it/is_vue-i18n_outdated.md +1 -1
  110. package/blog/it/lingui_vs_intlayer-lingui.md +304 -0
  111. package/blog/it/lingui_vs_intlayer.md +381 -0
  112. package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  113. package/blog/it/next-intl_vs_intlayer-next-intl.md +309 -0
  114. package/blog/it/next-intl_vs_intlayer.md +418 -0
  115. package/blog/it/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  116. package/blog/it/vue-i18n_vs_intlayer_benchmark.md +34 -0
  117. package/blog/ja/i18next_vs_intlayer-i18next.md +327 -0
  118. package/blog/ja/i18next_vs_intlayer.md +447 -0
  119. package/blog/ja/is_i18next_outdated.md +1 -1
  120. package/blog/ja/is_next-intl_outdated.md +1 -1
  121. package/blog/ja/is_vue-i18n_outdated.md +1 -1
  122. package/blog/ja/lingui_vs_intlayer-lingui.md +304 -0
  123. package/blog/ja/lingui_vs_intlayer.md +381 -0
  124. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  125. package/blog/ja/next-intl_vs_intlayer-next-intl.md +310 -0
  126. package/blog/ja/next-intl_vs_intlayer.md +422 -0
  127. package/blog/ja/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  128. package/blog/ja/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  129. package/blog/ja/vue-i18n_vs_intlayer.md +1 -1
  130. package/blog/ja/vue-i18n_vs_intlayer_benchmark.md +0 -0
  131. package/blog/ko/i18next_vs_intlayer-i18next.md +327 -0
  132. package/blog/ko/i18next_vs_intlayer.md +447 -0
  133. package/blog/ko/is_i18next_outdated.md +1 -1
  134. package/blog/ko/is_next-intl_outdated.md +1 -1
  135. package/blog/ko/is_vue-i18n_outdated.md +1 -1
  136. package/blog/ko/lingui_vs_intlayer-lingui.md +304 -0
  137. package/blog/ko/lingui_vs_intlayer.md +381 -0
  138. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  139. package/blog/ko/next-intl_vs_intlayer-next-intl.md +309 -0
  140. package/blog/ko/next-intl_vs_intlayer.md +397 -0
  141. package/blog/ko/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  142. package/blog/ko/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  143. package/blog/ko/vue-i18n_vs_intlayer.md +1 -1
  144. package/blog/ko/vue-i18n_vs_intlayer_benchmark.md +366 -0
  145. package/blog/pl/i18next_vs_intlayer-i18next.md +327 -0
  146. package/blog/pl/i18next_vs_intlayer.md +445 -0
  147. package/blog/pl/is_i18next_outdated.md +1 -1
  148. package/blog/pl/is_next-intl_outdated.md +1 -1
  149. package/blog/pl/is_vue-i18n_outdated.md +1 -1
  150. package/blog/pl/lingui_vs_intlayer-lingui.md +304 -0
  151. package/blog/pl/lingui_vs_intlayer.md +381 -0
  152. package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  153. package/blog/pl/next-intl_vs_intlayer-next-intl.md +309 -0
  154. package/blog/pl/next-intl_vs_intlayer.md +397 -0
  155. package/blog/pl/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  156. package/blog/pl/vue-i18n_vs_intlayer-vue-i18n.md +289 -0
  157. package/blog/pl/vue-i18n_vs_intlayer.md +1 -1
  158. package/blog/pl/vue-i18n_vs_intlayer_benchmark.md +0 -0
  159. package/blog/pt/i18next_vs_intlayer-i18next.md +327 -0
  160. package/blog/pt/i18next_vs_intlayer.md +445 -0
  161. package/blog/pt/is_i18next_outdated.md +1 -1
  162. package/blog/pt/is_next-intl_outdated.md +1 -1
  163. package/blog/pt/is_vue-i18n_outdated.md +1 -1
  164. package/blog/pt/lingui_vs_intlayer-lingui.md +304 -0
  165. package/blog/pt/lingui_vs_intlayer.md +381 -0
  166. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  167. package/blog/pt/next-intl_vs_intlayer-next-intl.md +309 -0
  168. package/blog/pt/next-intl_vs_intlayer.md +411 -0
  169. package/blog/pt/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  170. package/blog/pt/vue-i18n_vs_intlayer_benchmark.md +0 -0
  171. package/blog/ru/i18next_vs_intlayer-i18next.md +327 -0
  172. package/blog/ru/i18next_vs_intlayer.md +445 -0
  173. package/blog/ru/is_i18next_outdated.md +1 -1
  174. package/blog/ru/is_next-intl_outdated.md +1 -1
  175. package/blog/ru/is_vue-i18n_outdated.md +1 -1
  176. package/blog/ru/lingui_vs_intlayer-lingui.md +304 -0
  177. package/blog/ru/lingui_vs_intlayer.md +381 -0
  178. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  179. package/blog/ru/next-intl_vs_intlayer-next-intl.md +309 -0
  180. package/blog/ru/next-intl_vs_intlayer.md +417 -0
  181. package/blog/ru/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  182. package/blog/ru/vue-i18n_vs_intlayer_benchmark.md +54 -0
  183. package/blog/tr/i18next_vs_intlayer-i18next.md +327 -0
  184. package/blog/tr/i18next_vs_intlayer.md +445 -0
  185. package/blog/tr/is_i18next_outdated.md +1 -1
  186. package/blog/tr/is_next-intl_outdated.md +1 -1
  187. package/blog/tr/is_vue-i18n_outdated.md +1 -1
  188. package/blog/tr/lingui_vs_intlayer-lingui.md +304 -0
  189. package/blog/tr/lingui_vs_intlayer.md +381 -0
  190. package/blog/tr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  191. package/blog/tr/next-intl_vs_intlayer-next-intl.md +309 -0
  192. package/blog/tr/next-intl_vs_intlayer.md +397 -0
  193. package/blog/tr/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  194. package/blog/tr/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  195. package/blog/tr/vue-i18n_vs_intlayer.md +1 -1
  196. package/blog/tr/vue-i18n_vs_intlayer_benchmark.md +0 -0
  197. package/blog/uk/i18next_vs_intlayer-i18next.md +327 -0
  198. package/blog/uk/i18next_vs_intlayer.md +445 -0
  199. package/blog/uk/is_i18next_outdated.md +1 -1
  200. package/blog/uk/is_next-intl_outdated.md +1 -1
  201. package/blog/uk/is_vue-i18n_outdated.md +1 -1
  202. package/blog/uk/lingui_vs_intlayer-lingui.md +304 -0
  203. package/blog/uk/lingui_vs_intlayer.md +381 -0
  204. package/blog/uk/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  205. package/blog/uk/next-intl_vs_intlayer-next-intl.md +309 -0
  206. package/blog/uk/next-intl_vs_intlayer.md +397 -0
  207. package/blog/uk/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  208. package/blog/uk/vue-i18n_vs_intlayer-vue-i18n.md +270 -0
  209. package/blog/uk/vue-i18n_vs_intlayer.md +1 -1
  210. package/blog/uk/vue-i18n_vs_intlayer_benchmark.md +0 -0
  211. package/blog/vi/i18next_vs_intlayer-i18next.md +327 -0
  212. package/blog/vi/i18next_vs_intlayer.md +445 -0
  213. package/blog/vi/is_i18next_outdated.md +1 -1
  214. package/blog/vi/is_next-intl_outdated.md +1 -1
  215. package/blog/vi/is_vue-i18n_outdated.md +1 -1
  216. package/blog/vi/lingui_vs_intlayer-lingui.md +304 -0
  217. package/blog/vi/lingui_vs_intlayer.md +381 -0
  218. package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  219. package/blog/vi/next-intl_vs_intlayer-next-intl.md +309 -0
  220. package/blog/vi/next-intl_vs_intlayer.md +397 -0
  221. package/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  222. package/blog/vi/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  223. package/blog/vi/vue-i18n_vs_intlayer.md +1 -1
  224. package/blog/vi/vue-i18n_vs_intlayer_benchmark.md +0 -0
  225. package/blog/zh/i18next_vs_intlayer-i18next.md +327 -0
  226. package/blog/zh/i18next_vs_intlayer.md +445 -0
  227. package/blog/zh/is_i18next_outdated.md +1 -1
  228. package/blog/zh/is_next-intl_outdated.md +1 -1
  229. package/blog/zh/is_vue-i18n_outdated.md +1 -1
  230. package/blog/zh/lingui_vs_intlayer-lingui.md +304 -0
  231. package/blog/zh/lingui_vs_intlayer.md +381 -0
  232. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  233. package/blog/zh/next-intl_vs_intlayer-next-intl.md +309 -0
  234. package/blog/zh/next-intl_vs_intlayer.md +422 -0
  235. package/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
  236. package/blog/zh/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
  237. package/blog/zh/vue-i18n_vs_intlayer.md +1 -1
  238. package/blog/zh/vue-i18n_vs_intlayer_benchmark.md +30 -0
  239. package/dist/cjs/generated/blog.entry.cjs +160 -0
  240. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  241. package/dist/cjs/generated/frequentQuestions.entry.cjs +20 -0
  242. package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
  243. package/dist/esm/generated/blog.entry.mjs +160 -0
  244. package/dist/esm/generated/blog.entry.mjs.map +1 -1
  245. package/dist/esm/generated/frequentQuestions.entry.mjs +20 -0
  246. package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
  247. package/dist/types/generated/blog.entry.d.ts +8 -0
  248. package/dist/types/generated/blog.entry.d.ts.map +1 -1
  249. package/dist/types/generated/frequentQuestions.entry.d.ts +1 -0
  250. package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -1
  251. package/docs/ar/benchmark/nextjs.md +1 -1
  252. package/docs/ar/benchmark/solid.md +1 -1
  253. package/docs/ar/benchmark/svelte.md +1 -1
  254. package/docs/ar/benchmark/tanstack.md +1 -1
  255. package/docs/ar/benchmark/vue.md +1 -1
  256. package/docs/ar/interest_of_intlayer.md +1 -1
  257. package/docs/bn/interest_of_intlayer.md +1 -1
  258. package/docs/cs/interest_of_intlayer.md +1 -1
  259. package/docs/de/benchmark/nextjs.md +1 -1
  260. package/docs/de/benchmark/solid.md +1 -1
  261. package/docs/de/benchmark/svelte.md +1 -1
  262. package/docs/de/benchmark/tanstack.md +1 -1
  263. package/docs/de/benchmark/vue.md +1 -1
  264. package/docs/de/interest_of_intlayer.md +1 -1
  265. package/docs/en/benchmark/nextjs.md +1 -1
  266. package/docs/en/benchmark/solid.md +1 -1
  267. package/docs/en/benchmark/svelte.md +1 -1
  268. package/docs/en/benchmark/tanstack.md +1 -1
  269. package/docs/en/benchmark/vue.md +1 -1
  270. package/docs/en/interest_of_intlayer.md +1 -1
  271. package/docs/en-GB/benchmark/nextjs.md +1 -1
  272. package/docs/en-GB/benchmark/solid.md +1 -1
  273. package/docs/en-GB/benchmark/svelte.md +1 -1
  274. package/docs/en-GB/benchmark/tanstack.md +1 -1
  275. package/docs/en-GB/benchmark/vue.md +1 -1
  276. package/docs/en-GB/interest_of_intlayer.md +1 -1
  277. package/docs/es/benchmark/nextjs.md +1 -1
  278. package/docs/es/benchmark/solid.md +1 -1
  279. package/docs/es/benchmark/svelte.md +1 -1
  280. package/docs/es/benchmark/tanstack.md +1 -1
  281. package/docs/es/benchmark/vue.md +1 -1
  282. package/docs/es/interest_of_intlayer.md +1 -1
  283. package/docs/fr/benchmark/nextjs.md +1 -1
  284. package/docs/fr/benchmark/solid.md +1 -1
  285. package/docs/fr/benchmark/svelte.md +1 -1
  286. package/docs/fr/benchmark/tanstack.md +1 -1
  287. package/docs/fr/benchmark/vue.md +1 -1
  288. package/docs/fr/interest_of_intlayer.md +1 -1
  289. package/docs/hi/benchmark/nextjs.md +1 -1
  290. package/docs/hi/benchmark/solid.md +1 -1
  291. package/docs/hi/benchmark/svelte.md +1 -1
  292. package/docs/hi/benchmark/tanstack.md +1 -1
  293. package/docs/hi/benchmark/vue.md +1 -1
  294. package/docs/hi/interest_of_intlayer.md +1 -1
  295. package/docs/id/benchmark/nextjs.md +1 -1
  296. package/docs/id/benchmark/solid.md +1 -1
  297. package/docs/id/benchmark/svelte.md +1 -1
  298. package/docs/id/benchmark/tanstack.md +1 -1
  299. package/docs/id/benchmark/vue.md +1 -1
  300. package/docs/id/interest_of_intlayer.md +1 -1
  301. package/docs/it/benchmark/nextjs.md +1 -1
  302. package/docs/it/benchmark/solid.md +1 -1
  303. package/docs/it/benchmark/svelte.md +1 -1
  304. package/docs/it/benchmark/tanstack.md +1 -1
  305. package/docs/it/benchmark/vue.md +1 -1
  306. package/docs/it/interest_of_intlayer.md +1 -1
  307. package/docs/ja/benchmark/nextjs.md +1 -1
  308. package/docs/ja/benchmark/solid.md +1 -1
  309. package/docs/ja/benchmark/svelte.md +1 -1
  310. package/docs/ja/benchmark/tanstack.md +1 -1
  311. package/docs/ja/benchmark/vue.md +1 -1
  312. package/docs/ja/interest_of_intlayer.md +1 -1
  313. package/docs/ko/benchmark/nextjs.md +1 -1
  314. package/docs/ko/benchmark/solid.md +1 -1
  315. package/docs/ko/benchmark/svelte.md +1 -1
  316. package/docs/ko/benchmark/tanstack.md +1 -1
  317. package/docs/ko/benchmark/vue.md +1 -1
  318. package/docs/ko/interest_of_intlayer.md +1 -1
  319. package/docs/nl/interest_of_intlayer.md +1 -1
  320. package/docs/pl/benchmark/nextjs.md +1 -1
  321. package/docs/pl/benchmark/solid.md +1 -1
  322. package/docs/pl/benchmark/svelte.md +1 -1
  323. package/docs/pl/benchmark/tanstack.md +1 -1
  324. package/docs/pl/benchmark/vue.md +1 -1
  325. package/docs/pl/interest_of_intlayer.md +1 -1
  326. package/docs/pt/benchmark/nextjs.md +1 -1
  327. package/docs/pt/benchmark/solid.md +1 -1
  328. package/docs/pt/benchmark/svelte.md +1 -1
  329. package/docs/pt/benchmark/tanstack.md +1 -1
  330. package/docs/pt/benchmark/vue.md +1 -1
  331. package/docs/pt/interest_of_intlayer.md +1 -1
  332. package/docs/ru/benchmark/nextjs.md +1 -1
  333. package/docs/ru/benchmark/solid.md +1 -1
  334. package/docs/ru/benchmark/svelte.md +1 -1
  335. package/docs/ru/benchmark/tanstack.md +1 -1
  336. package/docs/ru/benchmark/vue.md +1 -1
  337. package/docs/ru/interest_of_intlayer.md +1 -1
  338. package/docs/tr/benchmark/nextjs.md +1 -1
  339. package/docs/tr/benchmark/solid.md +1 -1
  340. package/docs/tr/benchmark/svelte.md +1 -1
  341. package/docs/tr/benchmark/tanstack.md +1 -1
  342. package/docs/tr/benchmark/vue.md +1 -1
  343. package/docs/tr/interest_of_intlayer.md +1 -1
  344. package/docs/uk/benchmark/nextjs.md +1 -1
  345. package/docs/uk/benchmark/solid.md +1 -1
  346. package/docs/uk/benchmark/svelte.md +1 -1
  347. package/docs/uk/benchmark/tanstack.md +1 -1
  348. package/docs/uk/benchmark/vue.md +1 -1
  349. package/docs/uk/interest_of_intlayer.md +1 -1
  350. package/docs/ur/interest_of_intlayer.md +1 -1
  351. package/docs/vi/benchmark/nextjs.md +1 -1
  352. package/docs/vi/benchmark/solid.md +1 -1
  353. package/docs/vi/benchmark/svelte.md +1 -1
  354. package/docs/vi/benchmark/tanstack.md +1 -1
  355. package/docs/vi/benchmark/vue.md +1 -1
  356. package/docs/vi/interest_of_intlayer.md +1 -1
  357. package/docs/zh/benchmark/nextjs.md +1 -1
  358. package/docs/zh/benchmark/solid.md +1 -1
  359. package/docs/zh/benchmark/svelte.md +1 -1
  360. package/docs/zh/benchmark/tanstack.md +1 -1
  361. package/docs/zh/benchmark/vue.md +1 -1
  362. package/docs/zh/interest_of_intlayer.md +1 -1
  363. package/docs/zh-TW/interest_of_intlayer.md +1 -1
  364. package/frequent_questions/ar/claude_code_token_consumption.md +152 -0
  365. package/frequent_questions/de/claude_code_token_consumption.md +152 -0
  366. package/frequent_questions/en/claude_code_token_consumption.md +152 -0
  367. package/frequent_questions/en-GB/claude_code_token_consumption.md +152 -0
  368. package/frequent_questions/es/claude_code_token_consumption.md +152 -0
  369. package/frequent_questions/fr/claude_code_token_consumption.md +152 -0
  370. package/frequent_questions/hi/claude_code_token_consumption.md +152 -0
  371. package/frequent_questions/id/claude_code_token_consumption.md +152 -0
  372. package/frequent_questions/it/claude_code_token_consumption.md +152 -0
  373. package/frequent_questions/ja/claude_code_token_consumption.md +152 -0
  374. package/frequent_questions/ko/claude_code_token_consumption.md +152 -0
  375. package/frequent_questions/pl/claude_code_token_consumption.md +152 -0
  376. package/frequent_questions/pt/claude_code_token_consumption.md +152 -0
  377. package/frequent_questions/ru/claude_code_token_consumption.md +152 -0
  378. package/frequent_questions/tr/claude_code_token_consumption.md +152 -0
  379. package/frequent_questions/uk/claude_code_token_consumption.md +152 -0
  380. package/frequent_questions/vi/claude_code_token_consumption.md +152 -0
  381. package/frequent_questions/zh/claude_code_token_consumption.md +152 -0
  382. package/package.json +6 -6
  383. package/src/generated/blog.entry.ts +160 -0
  384. package/src/generated/frequentQuestions.entry.ts +20 -0
@@ -0,0 +1,422 @@
1
+ ---
2
+ createdAt: 2026-09-13
3
+ updatedAt: 2026-09-13
4
+ title: "next-intl vs Intlayer: 2026 基准测试与对比"
5
+ description: Bundle 大小、内容泄漏、locale 切换响应性和开发者体验在 Next.js 和 TanStack Start 上的测量。你应该在 2026 年选择哪个 i18n 库?
6
+ keywords:
7
+ - next-intl
8
+ - use-intl
9
+ - Intlayer
10
+ - Internationalization
11
+ - i18n
12
+ - Benchmark
13
+ - Bundle size
14
+ - Blog
15
+ - Next.js
16
+ - TanStack Start
17
+ - JavaScript
18
+ - React
19
+ slugs:
20
+ - blog
21
+ - next-intl-vs-intlayer
22
+ author: aymericzip
23
+ ---
24
+
25
+ # next-intl VS Intlayer | Next.js 国际化 (i18n) 基准测试
26
+
27
+ `next-intl` 是 Next.js 最流行的 i18n 库。Intlayer 是一个基于编译器、组件作用域的替代方案。两者都可以本地化 App Router 应用程序。问题是应用程序构建后每个库的成本是多少。
28
+
29
+ 本文不是教程。这是一个由 [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) 的数据支持的比较,Benchmark Bloom 是一个开源基准测试套件,它使用每个库构建相同的应用程序,并测量浏览器实际下载和执行的内容。
30
+
31
+ <TOC/>
32
+
33
+ > **tl;dr**: 在相同的 Next.js 应用上,`next-intl` 在每个页面上增加 **+12.6 KB gzip** 的 JavaScript,而 Intlayer 仅增加 **+0.3 KB**。无需额外工作,`next-intl` 在每个页面上附带 **~90% 的外语页面字符串**。要通过 `next-intl` 达到 0% 泄漏,需要命名空间作用域和按页面的 `pick(messages, [...])`。Intlayer 默认达到 0%,因为其编译器按组件作用内容。如果你想要 Intlayer 输出的 `next-intl` API,`@intlayer/next-intl` 适配器测得每个页面 **147.5 KB** 对比原始的 **153.6 KB**。
34
+
35
+ ## 简而言之
36
+
37
+ - **next-intl** - 轻量级、文档齐全、支持 ICU 消息格式、App Router 第一类支持(含 middleware)、formatters 和 navigation 助手。内容存储在集中式 JSON catalogs 中;性能优化(namespaces、per-page message picking、lazy loading)需要你自己实现。
38
+ - **Intlayer** - 以组件为中心的内容模型。`.content.ts` 字典与服务的组件并置,build-time compiler 对每个组件和每个 locale 进行 tree-shake 和 lazy-load,从你的内容生成严格的 TypeScript 类型,缺失的翻译在 build 时会失败。提供 middleware、SEO 助手、Visual Editor / CMS 和 AI 辅助翻译。
39
+
40
+ | 库 | GitHub Stars | 总提交数 | 最后提交 | 首个版本 | NPM 版本 | NPM 下载量 |
41
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
42
+ | `aymericzip/intlayer` | [![GitHub Repo stars](https://img.shields.io/github/stars/aymericzip/intlayer?style=for-the-badge&label=%E2%AD%90%20stars)](https://github.com/aymericzip/intlayer/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/aymericzip/intlayer?style=for-the-badge&label=commits)](https://github.com/aymericzip/intlayer/commits) | [![Last Commit](https://img.shields.io/github/last-commit/aymericzip/intlayer?style=for-the-badge)](https://github.com/aymericzip/intlayer/commits) | 2024年4月 | [![npm](https://img.shields.io/npm/v/intlayer?style=for-the-badge)](https://www.npmjs.com/package/intlayer) | [![npm downloads](https://img.shields.io/npm/dm/intlayer?style=for-the-badge)](https://www.npmjs.com/package/intlayer) |
43
+ | `amannn/next-intl` | [![GitHub Repo stars](https://img.shields.io/github/stars/amannn/next-intl?style=for-the-badge&label=%E2%AD%90%20stars)](https://github.com/amannn/next-intl/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/amannn/next-intl?style=for-the-badge&label=commits)](https://github.com/amannn/next-intl/commits) | [![Last Commit](https://img.shields.io/github/last-commit/amannn/next-intl?style=for-the-badge)](https://github.com/amannn/next-intl/commits) | 2020年11月 | [![npm](https://img.shields.io/npm/v/next-intl?style=for-the-badge)](https://www.npmjs.com/package/next-intl) | [![npm downloads](https://img.shields.io/npm/dm/next-intl?style=for-the-badge)](https://www.npmjs.com/package/next-intl) |
44
+
45
+ > 徽章自动更新。快照会随时间变化。
46
+
47
+ ## 并排功能比较
48
+
49
+ | 功能 | `next-intlayer` (Intlayer) | `next-intl` |
50
+ | ----------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
51
+ | **组件附近的翻译** | ✅ 是的,`.content.ts` 与每个组件并置 | ❌ 否,集中的 `messages/{locale}.json` |
52
+ | **TypeScript 集成** | ✅ 从内容自动生成的严格类型 | ✅ 良好,通过 `global.d.ts` 增强类型化的键 |
53
+ | **缺失翻译检测** | ✅ TypeScript 错误 + 构建时错误/警告 | ⚠️ 运行时回退 + 控制台警告 |
54
+ | **富内容(JSX / Markdown / 组件)** | ✅ 直接支持 | ⚠️ `t.rich()` / `t.markup()` 配合标签占位符 |
55
+ | **ICU 支持** | ⚠️ 开发中 | ✅ 是 |
56
+ | **格式化(日期、数字、货币)** | ✅ `useNumber`、`useDate` 等(底层使用 Intl) | ✅ `useFormatter()`(底层使用 Intl) |
57
+ | **本地化路由与中间件** | ✅ 内置代理/中间件,`getMultilingualUrls` | ✅ 内置中间件,`Link`,`redirect`,`usePathname` |
58
+ | **SEO 助手(hreflang、sitemap、robots)** | ✅ 内置助手 | ⚠️ 手动配置,基于路由配置 |
59
+ | **同步服务器组件** | ✅ `useIntlayer` 来自 `next-intlayer/server`,适用于任何子服务器组件 | ⚠️ `getTranslations` 是异步的;同步子组件需要通过 props 传递 `t` |
60
+ | **静态渲染** | ✅ 不阻止静态渲染 | ⚠️ 需要 `setRequestLocale()`;命名空间 catalogs 在我们的测试中仍会使页面退出静态渲染 |
61
+ | **Tree-shaking(仅发送使用过的内容)** | ✅ 按组件、按语言,由编译器自动化 | ⚠️ 手动:命名空间 + 每个页面的 `pick(messages, [...])` |
62
+ | **懒加载** | ✅ `importMode: 'dynamic'`(一行配置) | ⚠️ 手动在 `getRequestConfig` 中进行动态导入 |
63
+ | **清除未使用的内容** | ✅ 已过时的字典在构建时被移除 | ❌ 未内置 |
64
+ | **测试缺失的翻译 (CLI / CI)** | ✅ `npx intlayer content test` | ⚠️ 未内置;文档建议使用 `npx @lingual/i18n-check` |
65
+ | **AI 驱动的翻译** | ✅ 内置,使用您自己的提供者密钥 | ❌ 否 |
66
+ | **Visual Editor / CMS** | ✅ 免费可视化编辑器 + 可选 CMS | ❌ 否(外部本地化平台) |
67
+ | **MCP server & Agent Skills** | ✅ 是 | ❌ 否 |
68
+ | **Ecosystem / community** | ⚠️ 较小但增长迅速 | ✅ 大型,Next.js 的参考标准 |
69
+
70
+ ## 基准测试
71
+
72
+ ### 测量的内容
73
+
74
+ [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) 套件使用每个库构建**相同的应用程序**:**10 个页面**(首页、关于、博客、职业、联系、常见问题、定价、产品、设置、团队),**10 个语言环境**(`en`、`fr`、`es`、`de`、`it`、`pt`、`zh`、`ja`、`ko`、`ru`),相同的组件和相同的内容。页面在 `en` 和 `fr` 中进行测量。每个库实现了多达四种**加载策略**,从最初的设置到最优的设置:
75
+
76
+ | 策略 | 描述 | 谁在这样做 |
77
+ | ------------------ | ------------------------------------------------------- | --------------------- |
78
+ | **static** | 每个 locale 和每个页面打包在一起 | 快速原型、AI 生成代码 |
79
+ | **dynamic** | 仅加载活跃的 locale,但同时加载所有页面 | 大多数项目 |
80
+ | **scoped-static** | 按路由命名空间,无懒加载 | 罕见 |
81
+ | **scoped-dynamic** | 按路由命名空间 + 懒加载。仅发送当前 locale 中的当前页面 | 性能预算严格的应用 |
82
+
83
+ Intlayer 没有"scoped"变体:编译器会自动按**组件**对内容进行作用域划分,因此其 `static` 和 `dynamic` 行已经是作用域的。
84
+
85
+ 对于每次构建,该套件记录:
86
+
87
+ - **Lib size**: 仅导入 i18n 库的空组件的 gzip 大小。运行时的固定成本。
88
+ - **Page JS**: 每个页面下载的 gzip JavaScript,在所有页面和语言环境中平均计算。
89
+ - **Locale leak %**: 下载的 JS 中找到的已翻译字符串中属于用户**未**查看的语言环境的份额(在 `en` 和 `fr` 上进行指纹识别,因此 50% 表示"另一个测量的语言环境完全存在";使用 10 个捆绑的语言环境时,实际浪费更高)。
90
+ - **Page leak %**: 下载的 JS 中找到的已翻译字符串中属于用户**未**浏览的页面的份额。
91
+ - **Component avg**: 各个编译的每个组件的平均 gzip 大小。显示单个组件拖入多少 i18n 运行时。
92
+ - **E2E reactivity**: 选择新locale和`html[lang]`在DOM中更新之间的实时时间(Playwright,5次迭代)。
93
+ - **Hydration**: React hydration阶段持续时间。
94
+
95
+ > 下面的数字来自**2026-09-12**运行,使用`next-intl` 4.14.2、`use-intl` 4.14.2和`intlayer` 9.5.1。测试应用程序故意很小(每个locale只有几十个字符串),所以泄漏百分比描述的是一个**模式**:随着您的内容增长而增长,但运行时成本保持固定。
96
+
97
+ ### Next.js (App Router)上的结果
98
+
99
+ | Library | Strategy | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Hydration |
100
+ | ------------------------------ | -------------- | ------------: | ---------------: | ----------: | --------: | -----------------: | -------------: | --------: |
101
+ | **base** (no i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
102
+ | `next-intl` | static | 14.7 KB | 153.6 KB | 4.2% | 89.8% | 21.8 KB | 16.0 ms | 14.7 ms |
103
+ | `next-intl` | dynamic | 14.7 KB | 153.6 KB | 9.7% | 89.9% | 21.8 KB | 15.6 ms | 14.8 ms |
104
+ | `next-intl` | scoped-static | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 80.1 KB | 17.9 ms | 17.4 ms |
105
+ | `next-intl` | scoped-dynamic | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 22.9 KB | 17.8 ms | 16.8 ms |
106
+ | **`next-intlayer`** | static | **5.5 KB** | **141.3 KB** | **0.0%** | **0.0%** | **8.5 KB** | **15.5 ms** | 16.9 ms |
107
+ | **`next-intlayer`** | dynamic | **5.5 KB** | **141.3 KB** | **0.0%** | **0.0%** | **6.9 KB** | **15.3 ms** | 15.9 ms |
108
+ | `@intlayer/next-intl` (compat) | static | 8.0 KB | 147.5 KB | 0.0% | 0.0% | 8.1 KB | 14.5 ms | 12.8 ms |
109
+ | `@intlayer/next-intl` (compat) | dynamic | 8.0 KB | 148.7 KB | 0.0% | 0.0% | 8.1 KB | 11.7 ms | 12.8 ms |
110
+
111
+ **如何阅读**
112
+
113
+ - **运行时成本。** 基础应用程序每页重 141.0 KB。`next-intl` 将其增加到 153.6 KB(**每页额外 +12.6 KB gzip**),Intlayer 增加到 141.3 KB(**额外 +0.3 KB**)。这个差异不取决于你有多少个字符串:它是库运行时的成本。
114
+ - **Leakage.** 在两个最多团队实际使用的设置中(`static` 和 `dynamic`),`next-intl` 会在每个页面上传送 **~90% 的外语页面字符串**:整个 `en.json` 都会进入客户端 provider。要达到 0% 需要使用 `scoped-*` 设置:将目录分割成命名空间,然后在每个页面中 `pick()` 正确的。Intlayer 在两行中都是 0%,无需任何额外配置。
115
+ - **每页面 JS 大小在不同策略间对 `next-intl` 没有变化。** 测试内容很小,所以 ~90% 的泄漏这里只有几 KB。在一个有数百个字符串每页面的真实应用中,这个比例会成为主导成本。同时 +12.6 KB 的 runtime 在每个配置中都会被支付。
116
+ - **组件大小。** 调用 `useTranslations()` 的组件编译到平均 21.8 KB;使用 `useIntlayer()` 的相同组件编译到 6.9 KB。在 `scoped-static` 设置中,`next-intl` 组件跳升到 80.1 KB,因为每个组件都内联其命名空间 catalog。
117
+ - **Reactivity 和 hydration** 在 Next.js 上对两个库都处于相同的范围(15-18 ms)。这里都不是瓶颈。
118
+
119
+ ### TanStack Start 上的结果(`use-intl`)
120
+
121
+ `use-intl` 是 `next-intl` 的框架无关核心。相同的 API,相同的消息格式。在 TanStack Start 上将其与 `intlayer` 进行比较,移除了方程的 Next.js 特定部分。
122
+
123
+ | Library | Strategy | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity |
124
+ | ----------------------------- | -------------- | ------------: | ---------------: | ----------: | --------: | -----------------: | -------------: |
125
+ | **base** (no i18n) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms |
126
+ | `use-intl` | static | 14.1 KB | 179.8 KB | 50.0% | 89.8% | 76.0 KB | 6.7 ms |
127
+ | `use-intl` | dynamic | 14.1 KB | 119.4 KB | 0.0% | 89.8% | 75.9 KB | 7.0 ms |
128
+ | `use-intl` | scoped-static | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 20.9 ms |
129
+ | `use-intl` | scoped-dynamic | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 13.3 ms |
130
+ | **`intlayer`** | static | **5.0 KB** | **125.8 KB** | 50.0% | **0.0%** | **8.1 KB** | **3.2 ms** |
131
+ | **`intlayer`** | dynamic | **5.0 KB** | **118.6 KB** | **0.0%** | **0.0%** | **6.3 KB** | **3.6 ms** |
132
+ | `@intlayer/use-intl` (compat) | dynamic | 7.3 KB | 129.7 KB | 0.0% | 0.0% | 9.3 KB | 8.7 ms |
133
+
134
+ **如何阅读**
135
+
136
+ - 朴素的 `use-intl` 设置比基础应用多装载了 **68.8 KB 的 JS**,其中一半的字符串属于错误的语言环境,90% 属于错误的页面。
137
+ - `use-intl` 在 `dynamic` 模式下达到 119.4 KB,接近 Intlayer 的 118.6 KB,但仍然存在 **89.8% 页面泄漏**:活跃 locale 的所有页面字符串都在每个页面加载。按路由作用域划分(`scoped-*`)可以消除泄漏,但需要额外支付约 9 KB 的 chunk 开销。
138
+ - Intlayer 的 `static` 行已经实现 **0% 页面泄漏**:编译器仅打包页面上的组件使用的字典。启用 `importMode: 'dynamic'`(在 `intlayer.config.ts` 中只需一行)也消除了 locale 泄漏。
139
+ - **组件大小是架构的亮点**:使用 `use-intl` 每个组件 76-87 KB,而使用 Intlayer 仅 6-8 KB。`useTranslations()` 将每个组件绑定到全局消息树;`useIntlayer()` 将其绑定到自己的字典。
140
+ - **区域设置切换**使用 Intlayer 快 2-4 倍(3 毫秒 vs 7-21 毫秒)。
141
+
142
+ ## 为什么存在差距?集中式目录 vs. 编译的字典
143
+
144
+ `next-intl` 遵循经典模型:每个区域设置一个 JSON,在 `getRequestConfig` 中加载,推送到 `NextIntlClientProvider`,通过 `t("namespace.key")` 读取。
145
+
146
+ ```bash
147
+ .
148
+ ├── messages
149
+ │ ├── en.json
150
+ │ └── fr.json
151
+ └── src
152
+ ├── i18n
153
+ │ ├── request.ts
154
+ │ └── routing.ts
155
+ ├── middleware.ts
156
+ └── app
157
+ └── [locale]
158
+ ├── layout.tsx
159
+ └── about
160
+ └── page.tsx
161
+ ```
162
+
163
+ 运行时无法知道页面将使用哪些 key,因此安全的默认做法是发送整个 catalog。优化意味着**你**需要将 catalog 拆分成 namespace,**你**需要决定每个页面需要哪些 namespace,并且**你**需要在组件移动时保持该映射同步。基准测试中的 `scoped-dynamic` 行是该工作的回报,但大多数团队从未实现过。
164
+
165
+ Intlayer 翻转了这个责任。内容在组件旁边声明:
166
+
167
+ ```bash
168
+ .
169
+ ├── intlayer.config.ts
170
+ └── src
171
+ ├── middleware.ts
172
+ ├── app
173
+ │ └── [locale]
174
+ │ ├── layout.tsx
175
+ │ └── about
176
+ │ ├── page.tsx
177
+ │ └── page.content.ts
178
+ └── components
179
+ └── Counter
180
+ ├── index.tsx
181
+ └── index.content.ts
182
+ ```
183
+
184
+ 在构建时,编译器(`@intlayer/swc` / `@intlayer/babel`)会检查哪个组件导入了哪个字典。它只为活跃的语言环境捆绑那些字典,并删除未被导入的字典。"scoped-dynamic"模式成为构建的输出,而不是团队必须维护的纪律。
185
+
186
+ > 要获得 `dynamic` 行的数字,请在 `intlayer.config.ts` 中设置 `dictionary.importMode: 'dynamic'`。请参阅 [bundle 优化文档](https://intlayer.org/doc/concept/bundle-optimization)。
187
+
188
+ ## 开发者体验
189
+
190
+ ### Client 组件
191
+
192
+ **next-intl**
193
+
194
+ ```json fileName="messages/en.json"
195
+ {
196
+ "counter": {
197
+ "label": "Counter",
198
+ "increment": "Increment"
199
+ }
200
+ }
201
+ ```
202
+
203
+ ```tsx fileName="src/components/Counter.tsx"
204
+ "use client";
205
+
206
+ import { useState } from "react";
207
+ import { useTranslations, useFormatter } from "next-intl";
208
+
209
+ export const Counter = () => {
210
+ // 使用 useTranslations 获取 counter 命名空间的翻译
211
+ const t = useTranslations("counter");
212
+ // 使用 useFormatter 获取数字格式化工具
213
+ const format = useFormatter();
214
+ const [count, setCount] = useState(0);
215
+
216
+ return (
217
+ <div>
218
+ <p>{format.number(count)}</p>
219
+ <button aria-label={t("label")} onClick={() => setCount((c) => c + 1)}>
220
+ {t("increment")}
221
+ </button>
222
+ </div>
223
+ );
224
+ };
225
+ ```
226
+
227
+ > 记住在渲染此组件的每个页面上,将 `counter` 命名空间包含在传递给 `NextIntlClientProvider` 的消息中。
228
+
229
+ **Intlayer**
230
+
231
+ ```ts fileName="src/components/Counter/index.content.ts"
232
+ import { t, type Dictionary } from "intlayer";
233
+
234
+ const counterContent = {
235
+ key: "counter",
236
+ content: {
237
+ label: t({ zh: "计数器", en: "Counter", fr: "Compteur" }),
238
+ increment: t({ zh: "增加", en: "Increment", fr: "Incrémenter" }),
239
+ },
240
+ } satisfies Dictionary;
241
+
242
+ export default counterContent;
243
+ ```
244
+
245
+ ```tsx fileName="src/components/Counter/index.tsx"
246
+ "use client";
247
+
248
+ import { useState } from "react";
249
+ import { useIntlayer } from "next-intlayer";
250
+ import { useNumber } from "next-intlayer/format";
251
+
252
+ export const Counter = () => {
253
+ // 获取国际化内容
254
+ const { label, increment } = useIntlayer("counter");
255
+ // 获取数字格式化工具
256
+ const number = useNumber();
257
+ const [count, setCount] = useState(0);
258
+
259
+ return (
260
+ <div>
261
+ <p>{number(count)}</p>
262
+ <button aria-label={label} onClick={() => setCount((c) => c + 1)}>
263
+ {increment}
264
+ </button>
265
+ </div>
266
+ );
267
+ };
268
+ ```
269
+
270
+ 无需在页面上注册任何内容:该组件包含其自己的内容。
271
+
272
+ ### 同步服务器组件
273
+
274
+ 设计系统组件(导航栏、页脚、卡片)通常是作为客户端组件的子组件渲染的服务器组件,因此它们不能是 `async`。
275
+
276
+ **next-intl**
277
+
278
+ ```tsx fileName="src/components/ServerCounter.tsx"
279
+ type ServerCounterProps = {
280
+ t: (key: string) => string;
281
+ formattedCount: string;
282
+ };
283
+
284
+ export const ServerCounter = ({ t, formattedCount }: ServerCounterProps) => (
285
+ <div>
286
+ <p>{formattedCount}</p>
287
+ <button aria-label={t("label")}>{t("increment")}</button>
288
+ </div>
289
+ );
290
+ ```
291
+
292
+ 页面必须 `await getTranslations("counter")` 和 `await getFormatter()`,然后将结果作为 props 向下传递。该组件不再是自包含的。
293
+
294
+ **Intlayer**
295
+
296
+ ```tsx fileName="src/components/ServerCounter.tsx"
297
+ import { useIntlayer } from "next-intlayer/server";
298
+ import { useNumber } from "next-intlayer/server/format";
299
+
300
+ export const ServerCounter = ({ count }: { count: number }) => {
301
+ const { label, increment } = useIntlayer("counter");
302
+ const number = useNumber();
303
+
304
+ return (
305
+ <div>
306
+ <p>{number(count)}</p>
307
+ <button aria-label={label}>{increment}</button>
308
+ </div>
309
+ );
310
+ };
311
+ ```
312
+
313
+ ### 元数据
314
+
315
+ **next-intl**
316
+
317
+ ```tsx fileName="src/app/[locale]/about/page.tsx"
318
+ import type { Metadata } from "next";
319
+ import { getTranslations } from "next-intl/server";
320
+ import { routing } from "@/i18n/routing";
321
+
322
+ // 本地化路径函数
323
+ const localizedPath = (locale: string, path: string) =>
324
+ locale === routing.defaultLocale ? path : `/${locale}${path}`;
325
+
326
+ // 生成元数据
327
+ export const generateMetadata = async ({
328
+ params,
329
+ }: {
330
+ params: Promise<{ locale: string }>;
331
+ }): Promise<Metadata> => {
332
+ const { locale } = await params;
333
+ const t = await getTranslations({ locale, namespace: "about" });
334
+
335
+ const languages = Object.fromEntries(
336
+ routing.locales.map((l) => [l, localizedPath(l, "/about")])
337
+ );
338
+
339
+ return {
340
+ title: t("title"),
341
+ description: t("description"),
342
+ alternates: {
343
+ canonical: localizedPath(locale, "/about"),
344
+ languages: { ...languages, "x-default": "/about" },
345
+ },
346
+ };
347
+ };
348
+ ```
349
+
350
+ **Intlayer**
351
+
352
+ ```tsx fileName="src/app/[locale]/about/page.tsx"
353
+ import { getIntlayer, getMultilingualUrls } from "intlayer";
354
+ import type { Metadata } from "next";
355
+ import type { LocalPromiseParams } from "next-intlayer";
356
+
357
+ export const generateMetadata = async ({
358
+ params,
359
+ }: LocalPromiseParams): Promise<Metadata> => {
360
+ const { locale } = await params;
361
+ const metadata = getIntlayer("about-metadata", locale);
362
+ const multilingualUrls = getMultilingualUrls("/about");
363
+
364
+ return {
365
+ ...metadata,
366
+ alternates: {
367
+ canonical: multilingualUrls[locale as keyof typeof multilingualUrls],
368
+ languages: { ...multilingualUrls, "x-default": "/about" },
369
+ },
370
+ };
371
+ };
372
+ ```
373
+
374
+ ## 保持 next-intl API,获得 Intlayer 的输出
375
+
376
+ 您不必重写组件来获得上述基准数字。`@intlayer/next-intl` 是一个开箱即用的适配器:它保持 `useTranslations`、`getTranslations`、`useFormatter`、`t.rich()`、ICU 复数形式和 `next-intl/navigation` 助手,并从 Intlayer 编译器编译的 Intlayer 字典中提供它们。
377
+
378
+ ```ts fileName="next.config.ts"
379
+ import type { NextConfig } from "next";
380
+ ts fileName="next.config.ts"
381
+ import { createNextIntlPlugin } from "@intlayer/next-intl/plugin";
382
+
383
+ const withIntlayer = createNextIntlPlugin();
384
+
385
+ const nextConfig: NextConfig = {};
386
+
387
+ export default withIntlayer(nextConfig);
388
+ ```
389
+
390
+ 在基准测试中,同一应用的兼容性构建从**每页 153.6 KB 降至 147.5 KB**,从**每个组件 21.8 KB 降至 8.1 KB**,以及从**约 90% 的页面泄漏降至 0%**,应用代码保持不变。你现有的 `messages/{locale}.json` 文件可以通过 [JSON 同步插件](https://intlayer.org/doc/compatibility/next-intl)保持作为真实来源。
391
+
392
+ 查看 [next-intl 迁移指南](https://intlayer.org/doc/migration/next-intl)获取分步说明。
393
+
394
+ ## 何时选择哪个?
395
+
396
+ - **选择 next-intl** 如果你想要 Next.js 生态标准、依赖 ICU MessageFormat、应用规模小到中等,或者你集成了翻译平台(Crowdin、Phrase、Lokalise...)期望集中式 JSON。如果性能重要,需要预留时间来命名空间目录和按页面挑选消息。
397
+ - **选择 Intlayer** 如果你想要**组件作用域内容**、**严格的 TypeScript**、**构建时缺失键错误检测**、**零成本的 tree-shaking 和懒加载**、同步服务器组件,以及内置编辑工具(Visual Editor、CMS、AI 翻译、MCP server)。特别适合大型、模块化的 codebase 和设计系统。
398
+ - **选择 `@intlayer/next-intl`** 如果你已经在使用 `next-intl`,想要获得 bundle 优化而无需重写。
399
+
400
+ ## 相关比较
401
+
402
+ - [i18next vs Intlayer](https://intlayer.org/blog/i18next-vs-intlayer) (同一基准测试)
403
+ - [Lingui vs Intlayer](https://intlayer.org/blog/lingui-vs-intlayer) (同一基准测试)
404
+ - [vue-i18n vs Intlayer benchmark](https://intlayer.org/blog/vue-i18n-vs-intlayer-benchmark) (同一基准测试)
405
+ - [next-i18next vs next-intl vs Intlayer](https://intlayer.org/blog/next-i18next-vs-next-intl-vs-intlayer)
406
+ - [Is next-intl outdated?](https://intlayer.org/blog/is-next-intl-outdated)
407
+
408
+ ## GitHub Stars
409
+
410
+ GitHub Stars 是项目受欢迎程度、社区信任度和长期相关性的强有力指标。虽然不是技术质量的直接衡量标准,但它们反映了有多少开发者认为该项目有用、关注其进展,以及可能采用它的开发者数量。
411
+
412
+ [![Star History Chart](https://api.star-history.com/chart?repos=amannn%2Fnext-intl%2Caymericzip%2Fintlayer&type=date&legend=top-left)](https://star-history.com/#amannn/next-intl&aymericzip/intlayer)
413
+
414
+ ## 结论
415
+
416
+ `next-intl` 是一个可靠的、维护良好的库,基准测试证实它远不是 Next.js 上最差的选择。但是它的集中式目录模型将每项优化都交给了开发者:天真的设置会泄漏约 90% 的外语页面内容,而 runtime 本身在每个页面上就花费 +12.6 KB gzip。
417
+
418
+ Intlayer 将这些工作转移到编译器中。按组件字典、按语言环境的懒加载和无用内容清理是构建输出,而不是约定。在同一个应用上的结果:**每页 +0.3 KB**,**0% 泄漏**,组件**小 3 倍**,以及在 TanStack Start 上语言切换**快 2-4 倍**。
419
+
420
+ 所有原始数据、测试应用和脚本都在 [Benchmark Bloom 仓库](https://github.com/intlayer-org/benchmark-bloom) 中。自己运行它。
421
+
422
+ 有关更多详细信息,请参阅 ['为什么选择 Intlayer?' 文档](https://intlayer.org/doc/why)。
@@ -130,7 +130,7 @@ author: aymericzip
130
130
 
131
131
  GitHub stars 是项目受欢迎程度、社区信任度和长期相关性的强有力指标。虽然不是技术质量的直接衡量标准,但它们反映了有多少开发者认为该项目有用、关注其进展,以及可能会采用它。对于评估项目价值,stars 有助于比较不同替代方案的吸引力,并提供对生态系统增长的洞察。
132
132
 
133
- [![Star History Chart](https://api.star-history.com/chart?repos=formatjs/formatjs%2Ci18next/react-i18next%2Caymericzip/intlayer&type=date&legend=top-left)](https://www.star-history.com/#formatjs/formatjs&i18next/react-i18next&aymericzip/intlayer)
133
+ [![Star History Chart](https://api.star-history.com/chart?repos=formatjs/formatjs%2Ci18next/react-i18next%2Caymericzip/intlayer&type=date&legend=top-left)](https://star-history.com/#formatjs/formatjs&i18next/react-i18next&aymericzip/intlayer)
134
134
 
135
135
  ## 结论
136
136