@intlayer/docs 9.5.6 → 9.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/blog/ar/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/ar/i18next_vs_intlayer.md +130 -16
- package/blog/ar/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ar/lingui_vs_intlayer.md +122 -15
- package/blog/ar/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/ar/next-intl_vs_intlayer.md +136 -20
- package/blog/ar/vue-i18n_vs_intlayer-vue-i18n.md +119 -17
- package/blog/ar/vue-i18n_vs_intlayer.md +193 -31
- package/blog/ar/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/de/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/de/i18next_vs_intlayer.md +128 -14
- package/blog/de/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/de/lingui_vs_intlayer.md +122 -15
- package/blog/de/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/de/next-intl_vs_intlayer.md +125 -15
- package/blog/de/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/de/vue-i18n_vs_intlayer.md +193 -31
- package/blog/en/i18next_vs_intlayer-i18next.md +121 -14
- package/blog/en/i18next_vs_intlayer.md +128 -14
- package/blog/en/is_intlayer_lighter_than_paraglide.md +288 -0
- package/blog/en/lingui_vs_intlayer.md +124 -15
- package/blog/en/next-intl_vs_intlayer-next-intl.md +123 -14
- package/blog/en/next-intl_vs_intlayer.md +125 -13
- package/blog/en/vue-i18n_vs_intlayer-vue-i18n.md +115 -15
- package/blog/en/vue-i18n_vs_intlayer.md +188 -27
- package/blog/en-GB/i18next_vs_intlayer-i18next.md +121 -14
- package/blog/en-GB/i18next_vs_intlayer.md +128 -14
- package/blog/en-GB/is_intlayer_lighter_than_paraglide.md +285 -0
- package/blog/en-GB/lingui_vs_intlayer.md +122 -15
- package/blog/en-GB/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/en-GB/next-intl_vs_intlayer.md +125 -15
- package/blog/en-GB/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/en-GB/vue-i18n_vs_intlayer.md +187 -25
- package/blog/en-GB/vue-i18n_vs_intlayer_benchmark.md +116 -0
- package/blog/es/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/es/i18next_vs_intlayer.md +128 -14
- package/blog/es/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/es/lingui_vs_intlayer.md +122 -15
- package/blog/es/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/es/next-intl_vs_intlayer.md +125 -15
- package/blog/es/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/es/vue-i18n_vs_intlayer.md +193 -31
- package/blog/fr/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/fr/i18next_vs_intlayer.md +128 -14
- package/blog/fr/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/fr/lingui_vs_intlayer.md +122 -15
- package/blog/fr/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/fr/next-intl_vs_intlayer.md +127 -15
- package/blog/fr/vue-i18n_vs_intlayer-vue-i18n.md +118 -17
- package/blog/fr/vue-i18n_vs_intlayer.md +192 -31
- package/blog/fr/vue-i18n_vs_intlayer_benchmark.md +329 -7
- package/blog/hi/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/hi/i18next_vs_intlayer.md +130 -16
- package/blog/hi/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/hi/lingui_vs_intlayer.md +122 -15
- package/blog/hi/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/hi/next-intl_vs_intlayer.md +135 -19
- package/blog/hi/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/hi/vue-i18n_vs_intlayer.md +193 -31
- package/blog/hi/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/id/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/id/i18next_vs_intlayer.md +128 -14
- package/blog/id/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/id/lingui_vs_intlayer.md +122 -15
- package/blog/id/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/id/next-intl_vs_intlayer.md +135 -19
- package/blog/id/vue-i18n_vs_intlayer-vue-i18n.md +354 -2
- package/blog/id/vue-i18n_vs_intlayer.md +188 -26
- package/blog/id/vue-i18n_vs_intlayer_benchmark.md +327 -7
- package/blog/it/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/it/i18next_vs_intlayer.md +128 -14
- package/blog/it/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/it/lingui_vs_intlayer.md +122 -15
- package/blog/it/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/it/next-intl_vs_intlayer.md +125 -15
- package/blog/it/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/it/vue-i18n_vs_intlayer.md +191 -31
- package/blog/it/vue-i18n_vs_intlayer_benchmark.md +332 -5
- package/blog/ja/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/ja/i18next_vs_intlayer.md +129 -17
- package/blog/ja/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ja/lingui_vs_intlayer.md +122 -15
- package/blog/ja/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/ja/next-intl_vs_intlayer.md +124 -14
- package/blog/ja/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/ja/vue-i18n_vs_intlayer.md +193 -31
- package/blog/ja/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/ko/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/ko/i18next_vs_intlayer.md +129 -17
- package/blog/ko/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ko/lingui_vs_intlayer.md +122 -15
- package/blog/ko/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/ko/next-intl_vs_intlayer.md +134 -18
- package/blog/ko/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/ko/vue-i18n_vs_intlayer.md +193 -31
- package/blog/pl/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/pl/i18next_vs_intlayer.md +128 -14
- package/blog/pl/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/pl/lingui_vs_intlayer.md +122 -15
- package/blog/pl/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/pl/next-intl_vs_intlayer.md +134 -18
- package/blog/pl/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/pl/vue-i18n_vs_intlayer.md +188 -26
- package/blog/pl/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/pt/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/pt/i18next_vs_intlayer.md +128 -14
- package/blog/pt/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/pt/lingui_vs_intlayer.md +122 -15
- package/blog/pt/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/pt/next-intl_vs_intlayer.md +131 -15
- package/blog/pt/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/pt/vue-i18n_vs_intlayer.md +193 -31
- package/blog/pt/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/ru/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/ru/i18next_vs_intlayer.md +130 -16
- package/blog/ru/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ru/lingui_vs_intlayer.md +122 -15
- package/blog/ru/next-intl_vs_intlayer-next-intl.md +125 -16
- package/blog/ru/next-intl_vs_intlayer.md +123 -13
- package/blog/ru/vue-i18n_vs_intlayer-vue-i18n.md +127 -27
- package/blog/ru/vue-i18n_vs_intlayer.md +193 -31
- package/blog/ru/vue-i18n_vs_intlayer_benchmark.md +326 -19
- package/blog/tr/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/tr/i18next_vs_intlayer.md +128 -14
- package/blog/tr/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/tr/lingui_vs_intlayer.md +122 -15
- package/blog/tr/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/tr/next-intl_vs_intlayer.md +136 -20
- package/blog/tr/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/tr/vue-i18n_vs_intlayer.md +188 -26
- package/blog/tr/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/uk/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/uk/i18next_vs_intlayer.md +130 -16
- package/blog/uk/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/uk/lingui_vs_intlayer.md +122 -15
- package/blog/uk/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/uk/next-intl_vs_intlayer.md +135 -19
- package/blog/uk/vue-i18n_vs_intlayer-vue-i18n.md +135 -17
- package/blog/uk/vue-i18n_vs_intlayer.md +188 -27
- package/blog/uk/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/vi/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/vi/i18next_vs_intlayer.md +128 -14
- package/blog/vi/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/vi/lingui_vs_intlayer.md +122 -15
- package/blog/vi/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/vi/next-intl_vs_intlayer.md +135 -19
- package/blog/vi/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/vi/vue-i18n_vs_intlayer.md +188 -26
- package/blog/vi/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/zh/i18next_vs_intlayer-i18next.md +122 -15
- package/blog/zh/i18next_vs_intlayer.md +128 -14
- package/blog/zh/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/zh/lingui_vs_intlayer.md +122 -15
- package/blog/zh/next-intl_vs_intlayer-next-intl.md +124 -15
- package/blog/zh/next-intl_vs_intlayer.md +125 -15
- package/blog/zh/vue-i18n_vs_intlayer-vue-i18n.md +117 -17
- package/blog/zh/vue-i18n_vs_intlayer.md +192 -31
- package/blog/zh/vue-i18n_vs_intlayer_benchmark.md +340 -9
- package/dist/cjs/generated/blog.entry.cjs +20 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +60 -40
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +20 -0
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +60 -40
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/blog.entry.d.ts +1 -0
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +3 -2
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/benchmark/nextjs.md +19 -16
- package/docs/ar/benchmark/solid.md +26 -9
- package/docs/ar/benchmark/svelte.md +22 -7
- package/docs/ar/benchmark/tanstack.md +20 -16
- package/docs/ar/benchmark/vue.md +19 -10
- package/docs/ar/chrome_extension.md +130 -0
- package/docs/ar/cli/index.md +11 -1
- package/docs/ar/cli/infra.md +162 -0
- package/docs/ar/cli/init.md +24 -1
- package/docs/ar/cli/upgrade.md +125 -0
- package/docs/ar/dictionary/html.md +173 -5
- package/docs/ar/dictionary/markdown.md +263 -1
- package/docs/ar/intlayer_with_analog.md +23 -1
- package/docs/ar/intlayer_with_angular_19.md +24 -1
- package/docs/ar/intlayer_with_angular_21.md +24 -1
- package/docs/ar/intlayer_with_astro.md +24 -1
- package/docs/ar/intlayer_with_astro_lit.md +25 -1
- package/docs/ar/intlayer_with_astro_preact.md +26 -1
- package/docs/ar/intlayer_with_astro_react.md +26 -1
- package/docs/ar/intlayer_with_astro_solid.md +26 -1
- package/docs/ar/intlayer_with_astro_svelte.md +25 -1
- package/docs/ar/intlayer_with_astro_vue.md +25 -1
- package/docs/ar/intlayer_with_remix_3.md +22 -1
- package/docs/ar/self_hosting.md +406 -231
- package/docs/de/benchmark/nextjs.md +19 -16
- package/docs/de/benchmark/solid.md +26 -9
- package/docs/de/benchmark/svelte.md +22 -7
- package/docs/de/benchmark/tanstack.md +20 -16
- package/docs/de/benchmark/vue.md +19 -10
- package/docs/de/chrome_extension.md +130 -0
- package/docs/de/cli/index.md +11 -1
- package/docs/de/cli/infra.md +162 -0
- package/docs/de/cli/init.md +24 -1
- package/docs/de/cli/upgrade.md +125 -0
- package/docs/de/dictionary/html.md +173 -5
- package/docs/de/dictionary/markdown.md +263 -1
- package/docs/de/intlayer_with_analog.md +23 -1
- package/docs/de/intlayer_with_angular_19.md +24 -1
- package/docs/de/intlayer_with_angular_21.md +24 -1
- package/docs/de/intlayer_with_astro.md +24 -1
- package/docs/de/intlayer_with_astro_lit.md +25 -1
- package/docs/de/intlayer_with_astro_preact.md +26 -1
- package/docs/de/intlayer_with_astro_react.md +26 -1
- package/docs/de/intlayer_with_astro_solid.md +26 -1
- package/docs/de/intlayer_with_astro_svelte.md +25 -1
- package/docs/de/intlayer_with_astro_vue.md +25 -1
- package/docs/de/intlayer_with_remix_3.md +22 -1
- package/docs/de/self_hosting.md +404 -227
- package/docs/en/agent_skills.md +29 -1
- package/docs/en/benchmark/nextjs.md +19 -16
- package/docs/en/benchmark/solid.md +26 -9
- package/docs/en/benchmark/svelte.md +22 -7
- package/docs/en/benchmark/tanstack.md +21 -17
- package/docs/en/benchmark/vue.md +20 -11
- package/docs/en/chrome_extension.md +130 -0
- package/docs/en/cli/index.md +11 -1
- package/docs/en/cli/infra.md +175 -0
- package/docs/en/cli/init.md +25 -1
- package/docs/en/cli/upgrade.md +125 -0
- package/docs/en/dictionary/html.md +173 -5
- package/docs/en/dictionary/markdown.md +263 -1
- package/docs/en/intlayer_with_analog.md +23 -1
- package/docs/en/intlayer_with_angular_19.md +24 -1
- package/docs/en/intlayer_with_angular_21.md +24 -1
- package/docs/en/intlayer_with_astro.md +24 -1
- package/docs/en/intlayer_with_astro_lit.md +25 -1
- package/docs/en/intlayer_with_astro_preact.md +26 -1
- package/docs/en/intlayer_with_astro_react.md +26 -1
- package/docs/en/intlayer_with_astro_solid.md +26 -1
- package/docs/en/intlayer_with_astro_svelte.md +25 -1
- package/docs/en/intlayer_with_astro_vue.md +25 -1
- package/docs/en/intlayer_with_remix_3.md +22 -1
- package/docs/en/self_hosting.md +418 -176
- package/docs/en-GB/benchmark/nextjs.md +19 -16
- package/docs/en-GB/benchmark/solid.md +26 -9
- package/docs/en-GB/benchmark/svelte.md +22 -7
- package/docs/en-GB/benchmark/tanstack.md +20 -16
- package/docs/en-GB/benchmark/vue.md +20 -11
- package/docs/en-GB/chrome_extension.md +130 -0
- package/docs/en-GB/cli/index.md +11 -1
- package/docs/en-GB/cli/infra.md +162 -0
- package/docs/en-GB/cli/init.md +24 -1
- package/docs/en-GB/cli/upgrade.md +125 -0
- package/docs/en-GB/dictionary/html.md +173 -5
- package/docs/en-GB/dictionary/markdown.md +263 -1
- package/docs/en-GB/intlayer_with_analog.md +23 -1
- package/docs/en-GB/intlayer_with_angular_19.md +24 -1
- package/docs/en-GB/intlayer_with_angular_21.md +24 -1
- package/docs/en-GB/intlayer_with_astro.md +24 -1
- package/docs/en-GB/intlayer_with_astro_lit.md +25 -1
- package/docs/en-GB/intlayer_with_astro_preact.md +26 -1
- package/docs/en-GB/intlayer_with_astro_react.md +26 -1
- package/docs/en-GB/intlayer_with_astro_solid.md +26 -1
- package/docs/en-GB/intlayer_with_astro_svelte.md +25 -1
- package/docs/en-GB/intlayer_with_astro_vue.md +25 -1
- package/docs/en-GB/intlayer_with_remix_3.md +22 -1
- package/docs/en-GB/self_hosting.md +381 -206
- package/docs/es/benchmark/nextjs.md +19 -16
- package/docs/es/benchmark/solid.md +26 -9
- package/docs/es/benchmark/svelte.md +22 -7
- package/docs/es/benchmark/tanstack.md +20 -16
- package/docs/es/benchmark/vue.md +19 -10
- package/docs/es/chrome_extension.md +130 -0
- package/docs/es/cli/index.md +11 -1
- package/docs/es/cli/infra.md +162 -0
- package/docs/es/cli/init.md +24 -1
- package/docs/es/cli/upgrade.md +125 -0
- package/docs/es/dictionary/html.md +173 -5
- package/docs/es/dictionary/markdown.md +263 -1
- package/docs/es/intlayer_with_analog.md +23 -1
- package/docs/es/intlayer_with_angular_19.md +24 -1
- package/docs/es/intlayer_with_angular_21.md +24 -1
- package/docs/es/intlayer_with_astro.md +24 -1
- package/docs/es/intlayer_with_astro_lit.md +25 -1
- package/docs/es/intlayer_with_astro_preact.md +26 -1
- package/docs/es/intlayer_with_astro_react.md +26 -1
- package/docs/es/intlayer_with_astro_solid.md +26 -1
- package/docs/es/intlayer_with_astro_svelte.md +25 -1
- package/docs/es/intlayer_with_astro_vue.md +25 -1
- package/docs/es/intlayer_with_remix_3.md +22 -1
- package/docs/es/self_hosting.md +400 -223
- package/docs/fr/benchmark/nextjs.md +19 -16
- package/docs/fr/benchmark/solid.md +26 -9
- package/docs/fr/benchmark/svelte.md +22 -7
- package/docs/fr/benchmark/tanstack.md +20 -16
- package/docs/fr/benchmark/vue.md +20 -11
- package/docs/fr/chrome_extension.md +130 -0
- package/docs/fr/cli/index.md +11 -1
- package/docs/fr/cli/infra.md +162 -0
- package/docs/fr/cli/init.md +24 -1
- package/docs/fr/cli/upgrade.md +125 -0
- package/docs/fr/dictionary/html.md +173 -5
- package/docs/fr/dictionary/markdown.md +265 -4
- package/docs/fr/intlayer_with_analog.md +23 -1
- package/docs/fr/intlayer_with_angular_19.md +24 -1
- package/docs/fr/intlayer_with_angular_21.md +24 -1
- package/docs/fr/intlayer_with_astro.md +24 -1
- package/docs/fr/intlayer_with_astro_lit.md +25 -1
- package/docs/fr/intlayer_with_astro_preact.md +26 -1
- package/docs/fr/intlayer_with_astro_react.md +26 -1
- package/docs/fr/intlayer_with_astro_solid.md +26 -1
- package/docs/fr/intlayer_with_astro_svelte.md +25 -1
- package/docs/fr/intlayer_with_astro_vue.md +25 -1
- package/docs/fr/intlayer_with_remix_3.md +22 -1
- package/docs/fr/self_hosting.md +401 -224
- package/docs/hi/benchmark/nextjs.md +19 -16
- package/docs/hi/benchmark/solid.md +26 -9
- package/docs/hi/benchmark/svelte.md +22 -7
- package/docs/hi/benchmark/tanstack.md +20 -16
- package/docs/hi/benchmark/vue.md +20 -11
- package/docs/hi/chrome_extension.md +130 -0
- package/docs/hi/cli/index.md +11 -1
- package/docs/hi/cli/infra.md +162 -0
- package/docs/hi/cli/init.md +24 -1
- package/docs/hi/cli/upgrade.md +125 -0
- package/docs/hi/dictionary/html.md +173 -5
- package/docs/hi/dictionary/markdown.md +263 -1
- package/docs/hi/intlayer_with_analog.md +23 -1
- package/docs/hi/intlayer_with_angular_19.md +24 -1
- package/docs/hi/intlayer_with_angular_21.md +24 -1
- package/docs/hi/intlayer_with_astro.md +24 -1
- package/docs/hi/intlayer_with_astro_lit.md +25 -1
- package/docs/hi/intlayer_with_astro_preact.md +26 -1
- package/docs/hi/intlayer_with_astro_react.md +26 -1
- package/docs/hi/intlayer_with_astro_solid.md +26 -1
- package/docs/hi/intlayer_with_astro_svelte.md +25 -1
- package/docs/hi/intlayer_with_astro_vue.md +25 -1
- package/docs/hi/intlayer_with_remix_3.md +22 -1
- package/docs/hi/self_hosting.md +409 -235
- package/docs/id/benchmark/nextjs.md +19 -16
- package/docs/id/benchmark/solid.md +26 -9
- package/docs/id/benchmark/svelte.md +22 -7
- package/docs/id/benchmark/tanstack.md +20 -16
- package/docs/id/benchmark/vue.md +20 -11
- package/docs/id/chrome_extension.md +130 -0
- package/docs/id/cli/index.md +11 -1
- package/docs/id/cli/infra.md +162 -0
- package/docs/id/cli/init.md +24 -1
- package/docs/id/cli/upgrade.md +125 -0
- package/docs/id/dictionary/html.md +173 -5
- package/docs/id/dictionary/markdown.md +263 -1
- package/docs/id/intlayer_with_analog.md +23 -1
- package/docs/id/intlayer_with_angular_19.md +24 -1
- package/docs/id/intlayer_with_angular_21.md +24 -1
- package/docs/id/intlayer_with_astro.md +24 -1
- package/docs/id/intlayer_with_astro_lit.md +25 -1
- package/docs/id/intlayer_with_astro_preact.md +26 -1
- package/docs/id/intlayer_with_astro_react.md +26 -1
- package/docs/id/intlayer_with_astro_solid.md +26 -1
- package/docs/id/intlayer_with_astro_svelte.md +25 -1
- package/docs/id/intlayer_with_astro_vue.md +25 -1
- package/docs/id/intlayer_with_remix_3.md +22 -1
- package/docs/id/self_hosting.md +416 -243
- package/docs/it/benchmark/nextjs.md +19 -16
- package/docs/it/benchmark/solid.md +26 -9
- package/docs/it/benchmark/svelte.md +22 -7
- package/docs/it/benchmark/tanstack.md +20 -16
- package/docs/it/benchmark/vue.md +19 -10
- package/docs/it/chrome_extension.md +130 -0
- package/docs/it/cli/index.md +11 -1
- package/docs/it/cli/infra.md +162 -0
- package/docs/it/cli/init.md +24 -1
- package/docs/it/cli/upgrade.md +125 -0
- package/docs/it/dictionary/html.md +173 -5
- package/docs/it/dictionary/markdown.md +263 -1
- package/docs/it/intlayer_with_analog.md +23 -1
- package/docs/it/intlayer_with_angular_19.md +24 -1
- package/docs/it/intlayer_with_angular_21.md +24 -1
- package/docs/it/intlayer_with_astro.md +24 -1
- package/docs/it/intlayer_with_astro_lit.md +25 -1
- package/docs/it/intlayer_with_astro_preact.md +26 -1
- package/docs/it/intlayer_with_astro_react.md +26 -1
- package/docs/it/intlayer_with_astro_solid.md +26 -1
- package/docs/it/intlayer_with_astro_svelte.md +25 -1
- package/docs/it/intlayer_with_astro_vue.md +25 -1
- package/docs/it/intlayer_with_remix_3.md +22 -1
- package/docs/it/self_hosting.md +412 -237
- package/docs/ja/benchmark/nextjs.md +19 -16
- package/docs/ja/benchmark/solid.md +26 -9
- package/docs/ja/benchmark/svelte.md +22 -7
- package/docs/ja/benchmark/tanstack.md +18 -14
- package/docs/ja/benchmark/vue.md +19 -10
- package/docs/ja/chrome_extension.md +130 -0
- package/docs/ja/cli/index.md +11 -1
- package/docs/ja/cli/infra.md +162 -0
- package/docs/ja/cli/init.md +24 -1
- package/docs/ja/cli/upgrade.md +125 -0
- package/docs/ja/dictionary/html.md +173 -5
- package/docs/ja/dictionary/markdown.md +263 -1
- package/docs/ja/intlayer_with_analog.md +23 -1
- package/docs/ja/intlayer_with_angular_19.md +24 -1
- package/docs/ja/intlayer_with_angular_21.md +24 -1
- package/docs/ja/intlayer_with_astro.md +24 -1
- package/docs/ja/intlayer_with_astro_lit.md +25 -1
- package/docs/ja/intlayer_with_astro_preact.md +26 -1
- package/docs/ja/intlayer_with_astro_react.md +26 -1
- package/docs/ja/intlayer_with_astro_solid.md +26 -1
- package/docs/ja/intlayer_with_astro_svelte.md +25 -1
- package/docs/ja/intlayer_with_astro_vue.md +25 -1
- package/docs/ja/intlayer_with_remix_3.md +22 -1
- package/docs/ja/self_hosting.md +398 -223
- package/docs/ko/benchmark/nextjs.md +19 -16
- package/docs/ko/benchmark/solid.md +26 -9
- package/docs/ko/benchmark/svelte.md +22 -7
- package/docs/ko/benchmark/tanstack.md +20 -16
- package/docs/ko/benchmark/vue.md +20 -11
- package/docs/ko/chrome_extension.md +130 -0
- package/docs/ko/cli/index.md +11 -1
- package/docs/ko/cli/infra.md +162 -0
- package/docs/ko/cli/init.md +24 -1
- package/docs/ko/cli/upgrade.md +126 -0
- package/docs/ko/dictionary/html.md +173 -5
- package/docs/ko/dictionary/markdown.md +263 -1
- package/docs/ko/intlayer_with_analog.md +23 -1
- package/docs/ko/intlayer_with_angular_19.md +24 -1
- package/docs/ko/intlayer_with_angular_21.md +24 -1
- package/docs/ko/intlayer_with_astro.md +24 -1
- package/docs/ko/intlayer_with_astro_lit.md +25 -1
- package/docs/ko/intlayer_with_astro_preact.md +26 -1
- package/docs/ko/intlayer_with_astro_react.md +26 -1
- package/docs/ko/intlayer_with_astro_solid.md +26 -1
- package/docs/ko/intlayer_with_astro_svelte.md +25 -1
- package/docs/ko/intlayer_with_astro_vue.md +25 -1
- package/docs/ko/intlayer_with_remix_3.md +22 -1
- package/docs/ko/self_hosting.md +411 -238
- package/docs/pl/benchmark/nextjs.md +19 -16
- package/docs/pl/benchmark/solid.md +26 -9
- package/docs/pl/benchmark/svelte.md +22 -7
- package/docs/pl/benchmark/tanstack.md +20 -16
- package/docs/pl/benchmark/vue.md +20 -11
- package/docs/pl/chrome_extension.md +130 -0
- package/docs/pl/cli/index.md +11 -1
- package/docs/pl/cli/infra.md +162 -0
- package/docs/pl/cli/init.md +24 -1
- package/docs/pl/cli/upgrade.md +125 -0
- package/docs/pl/dictionary/html.md +173 -5
- package/docs/pl/dictionary/markdown.md +263 -1
- package/docs/pl/intlayer_with_analog.md +23 -1
- package/docs/pl/intlayer_with_angular_19.md +24 -1
- package/docs/pl/intlayer_with_angular_21.md +24 -1
- package/docs/pl/intlayer_with_astro.md +24 -1
- package/docs/pl/intlayer_with_astro_lit.md +25 -1
- package/docs/pl/intlayer_with_astro_preact.md +26 -1
- package/docs/pl/intlayer_with_astro_react.md +26 -1
- package/docs/pl/intlayer_with_astro_solid.md +26 -1
- package/docs/pl/intlayer_with_astro_svelte.md +25 -1
- package/docs/pl/intlayer_with_astro_vue.md +25 -1
- package/docs/pl/intlayer_with_remix_3.md +22 -1
- package/docs/pl/self_hosting.md +408 -233
- package/docs/pt/benchmark/nextjs.md +19 -16
- package/docs/pt/benchmark/solid.md +26 -9
- package/docs/pt/benchmark/svelte.md +22 -7
- package/docs/pt/benchmark/tanstack.md +20 -16
- package/docs/pt/benchmark/vue.md +19 -10
- package/docs/pt/chrome_extension.md +130 -0
- package/docs/pt/cli/index.md +11 -1
- package/docs/pt/cli/infra.md +162 -0
- package/docs/pt/cli/init.md +24 -1
- package/docs/pt/cli/upgrade.md +125 -0
- package/docs/pt/dictionary/html.md +173 -5
- package/docs/pt/dictionary/markdown.md +263 -1
- package/docs/pt/intlayer_with_analog.md +23 -1
- package/docs/pt/intlayer_with_angular_19.md +24 -1
- package/docs/pt/intlayer_with_angular_21.md +24 -1
- package/docs/pt/intlayer_with_astro.md +24 -1
- package/docs/pt/intlayer_with_astro_lit.md +25 -1
- package/docs/pt/intlayer_with_astro_preact.md +26 -1
- package/docs/pt/intlayer_with_astro_react.md +26 -1
- package/docs/pt/intlayer_with_astro_solid.md +26 -1
- package/docs/pt/intlayer_with_astro_svelte.md +25 -1
- package/docs/pt/intlayer_with_astro_vue.md +25 -1
- package/docs/pt/intlayer_with_remix_3.md +22 -1
- package/docs/pt/self_hosting.md +399 -224
- package/docs/ru/benchmark/nextjs.md +19 -16
- package/docs/ru/benchmark/solid.md +26 -9
- package/docs/ru/benchmark/svelte.md +22 -7
- package/docs/ru/benchmark/tanstack.md +20 -16
- package/docs/ru/benchmark/vue.md +20 -11
- package/docs/ru/chrome_extension.md +130 -0
- package/docs/ru/cli/index.md +11 -1
- package/docs/ru/cli/infra.md +162 -0
- package/docs/ru/cli/init.md +24 -1
- package/docs/ru/cli/upgrade.md +125 -0
- package/docs/ru/dictionary/html.md +173 -5
- package/docs/ru/dictionary/markdown.md +263 -1
- package/docs/ru/intlayer_with_analog.md +23 -1
- package/docs/ru/intlayer_with_angular_19.md +24 -1
- package/docs/ru/intlayer_with_angular_21.md +24 -1
- package/docs/ru/intlayer_with_astro.md +24 -1
- package/docs/ru/intlayer_with_astro_lit.md +25 -1
- package/docs/ru/intlayer_with_astro_preact.md +26 -1
- package/docs/ru/intlayer_with_astro_react.md +26 -1
- package/docs/ru/intlayer_with_astro_solid.md +26 -1
- package/docs/ru/intlayer_with_astro_svelte.md +25 -1
- package/docs/ru/intlayer_with_astro_vue.md +25 -1
- package/docs/ru/intlayer_with_remix_3.md +22 -1
- package/docs/ru/self_hosting.md +403 -228
- package/docs/tr/benchmark/nextjs.md +19 -16
- package/docs/tr/benchmark/solid.md +26 -9
- package/docs/tr/benchmark/svelte.md +22 -7
- package/docs/tr/benchmark/tanstack.md +20 -16
- package/docs/tr/benchmark/vue.md +20 -11
- package/docs/tr/chrome_extension.md +130 -0
- package/docs/tr/cli/index.md +11 -1
- package/docs/tr/cli/infra.md +162 -0
- package/docs/tr/cli/init.md +24 -1
- package/docs/tr/cli/upgrade.md +125 -0
- package/docs/tr/dictionary/html.md +173 -5
- package/docs/tr/dictionary/markdown.md +263 -1
- package/docs/tr/intlayer_with_analog.md +23 -1
- package/docs/tr/intlayer_with_angular_19.md +24 -1
- package/docs/tr/intlayer_with_angular_21.md +24 -1
- package/docs/tr/intlayer_with_astro.md +24 -1
- package/docs/tr/intlayer_with_astro_lit.md +25 -1
- package/docs/tr/intlayer_with_astro_preact.md +26 -1
- package/docs/tr/intlayer_with_astro_react.md +26 -1
- package/docs/tr/intlayer_with_astro_solid.md +26 -1
- package/docs/tr/intlayer_with_astro_svelte.md +25 -1
- package/docs/tr/intlayer_with_astro_vue.md +25 -1
- package/docs/tr/intlayer_with_remix_3.md +22 -1
- package/docs/tr/self_hosting.md +410 -234
- package/docs/uk/benchmark/nextjs.md +19 -16
- package/docs/uk/benchmark/solid.md +26 -9
- package/docs/uk/benchmark/svelte.md +22 -7
- package/docs/uk/benchmark/tanstack.md +20 -16
- package/docs/uk/benchmark/vue.md +20 -11
- package/docs/uk/chrome_extension.md +130 -0
- package/docs/uk/cli/index.md +11 -1
- package/docs/uk/cli/infra.md +162 -0
- package/docs/uk/cli/init.md +24 -1
- package/docs/uk/cli/upgrade.md +125 -0
- package/docs/uk/dictionary/html.md +173 -5
- package/docs/uk/dictionary/markdown.md +263 -1
- package/docs/uk/intlayer_with_analog.md +23 -1
- package/docs/uk/intlayer_with_angular_19.md +24 -1
- package/docs/uk/intlayer_with_angular_21.md +24 -1
- package/docs/uk/intlayer_with_astro.md +24 -1
- package/docs/uk/intlayer_with_astro_lit.md +25 -1
- package/docs/uk/intlayer_with_astro_preact.md +26 -1
- package/docs/uk/intlayer_with_astro_react.md +26 -1
- package/docs/uk/intlayer_with_astro_solid.md +26 -1
- package/docs/uk/intlayer_with_astro_svelte.md +25 -1
- package/docs/uk/intlayer_with_astro_vue.md +25 -1
- package/docs/uk/intlayer_with_remix_3.md +22 -1
- package/docs/uk/self_hosting.md +413 -238
- package/docs/vi/benchmark/nextjs.md +19 -16
- package/docs/vi/benchmark/solid.md +26 -9
- package/docs/vi/benchmark/svelte.md +22 -7
- package/docs/vi/benchmark/tanstack.md +20 -16
- package/docs/vi/benchmark/vue.md +20 -11
- package/docs/vi/chrome_extension.md +130 -0
- package/docs/vi/cli/index.md +11 -1
- package/docs/vi/cli/infra.md +162 -0
- package/docs/vi/cli/init.md +24 -1
- package/docs/vi/cli/upgrade.md +125 -0
- package/docs/vi/dictionary/html.md +173 -5
- package/docs/vi/dictionary/markdown.md +263 -1
- package/docs/vi/intlayer_with_analog.md +23 -1
- package/docs/vi/intlayer_with_angular_19.md +24 -1
- package/docs/vi/intlayer_with_angular_21.md +24 -1
- package/docs/vi/intlayer_with_astro.md +24 -1
- package/docs/vi/intlayer_with_astro_lit.md +25 -1
- package/docs/vi/intlayer_with_astro_preact.md +26 -1
- package/docs/vi/intlayer_with_astro_react.md +26 -1
- package/docs/vi/intlayer_with_astro_solid.md +26 -1
- package/docs/vi/intlayer_with_astro_svelte.md +25 -1
- package/docs/vi/intlayer_with_astro_vue.md +25 -1
- package/docs/vi/intlayer_with_remix_3.md +22 -1
- package/docs/vi/self_hosting.md +408 -234
- package/docs/zh/benchmark/nextjs.md +19 -16
- package/docs/zh/benchmark/solid.md +26 -9
- package/docs/zh/benchmark/svelte.md +22 -7
- package/docs/zh/benchmark/tanstack.md +19 -15
- package/docs/zh/benchmark/vue.md +20 -11
- package/docs/zh/chrome_extension.md +130 -0
- package/docs/zh/cli/index.md +11 -1
- package/docs/zh/cli/infra.md +162 -0
- package/docs/zh/cli/init.md +24 -1
- package/docs/zh/cli/upgrade.md +125 -0
- package/docs/zh/dictionary/html.md +172 -5
- package/docs/zh/dictionary/markdown.md +262 -1
- package/docs/zh/intlayer_with_analog.md +23 -1
- package/docs/zh/intlayer_with_angular_19.md +24 -1
- package/docs/zh/intlayer_with_angular_21.md +24 -1
- package/docs/zh/intlayer_with_astro.md +24 -1
- package/docs/zh/intlayer_with_astro_lit.md +25 -1
- package/docs/zh/intlayer_with_astro_preact.md +26 -1
- package/docs/zh/intlayer_with_astro_react.md +26 -1
- package/docs/zh/intlayer_with_astro_solid.md +26 -1
- package/docs/zh/intlayer_with_astro_svelte.md +25 -1
- package/docs/zh/intlayer_with_astro_vue.md +25 -1
- package/docs/zh/intlayer_with_remix_3.md +22 -1
- package/docs/zh/self_hosting.md +410 -237
- package/legal/ar/privacy_notice.md +9 -3
- package/legal/de/privacy_notice.md +9 -3
- package/legal/en/privacy_notice.md +10 -3
- package/legal/en-GB/privacy_notice.md +9 -3
- package/legal/es/privacy_notice.md +9 -3
- package/legal/fr/privacy_notice.md +9 -3
- package/legal/hi/privacy_notice.md +9 -3
- package/legal/id/privacy_notice.md +9 -3
- package/legal/it/privacy_notice.md +9 -3
- package/legal/ja/privacy_notice.md +9 -3
- package/legal/ko/privacy_notice.md +9 -3
- package/legal/pl/privacy_notice.md +9 -3
- package/legal/pt/privacy_notice.md +9 -3
- package/legal/ru/privacy_notice.md +9 -3
- package/legal/tr/privacy_notice.md +9 -3
- package/legal/uk/privacy_notice.md +9 -3
- package/legal/vi/privacy_notice.md +9 -3
- package/legal/zh/privacy_notice.md +9 -3
- package/package.json +6 -6
- package/src/generated/blog.entry.ts +20 -0
- package/src/generated/docs.entry.ts +60 -40
- package/docs/ar/roadmap.md +0 -321
- package/docs/de/roadmap.md +0 -322
- package/docs/en/intlayer_with_astro_vanilla.md +0 -713
- package/docs/en/roadmap.md +0 -325
- package/docs/en-GB/roadmap.md +0 -322
- package/docs/es/roadmap.md +0 -322
- package/docs/fr/roadmap.md +0 -322
- package/docs/hi/roadmap.md +0 -322
- package/docs/id/roadmap.md +0 -325
- package/docs/it/roadmap.md +0 -322
- package/docs/ja/roadmap.md +0 -322
- package/docs/ko/roadmap.md +0 -322
- package/docs/pl/roadmap.md +0 -325
- package/docs/pt/roadmap.md +0 -322
- package/docs/ru/roadmap.md +0 -322
- package/docs/tr/roadmap.md +0 -325
- package/docs/uk/roadmap.md +0 -325
- package/docs/vi/roadmap.md +0 -325
- package/docs/zh/roadmap.md +0 -322
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-13
|
|
3
|
+
updatedAt: 2026-09-13
|
|
4
|
+
title: "vue-i18n vs Intlayer: Benchmark 2026"
|
|
5
|
+
description: vue-i18n và Intlayer được đo trên cùng một ứng dụng Vite + Vue 3. Kích thước thư viện, JavaScript mỗi trang, rò rỉ nội dung, kích thước component và độ phản ứng khi đổi locale, kèm giải thích các con số.
|
|
6
|
+
keywords:
|
|
7
|
+
- vue-i18n
|
|
8
|
+
- Intlayer
|
|
9
|
+
- Internationalization
|
|
10
|
+
- i18n
|
|
11
|
+
- Benchmark
|
|
12
|
+
- Bundle size
|
|
13
|
+
- Blog
|
|
14
|
+
- Vue
|
|
15
|
+
- Nuxt
|
|
16
|
+
- Vite
|
|
17
|
+
- JavaScript
|
|
18
|
+
slugs:
|
|
19
|
+
- blog
|
|
20
|
+
- vue-i18n-vs-intlayer-benchmark
|
|
21
|
+
author: aymericzip
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# vue-i18n VS Intlayer | Benchmark quốc tế hóa (i18n) cho Vue
|
|
25
|
+
|
|
26
|
+
`vue-i18n` là thư viện i18n tham chiếu cho Vue. Intlayer là một giải pháp thay thế dựa trên trình biên dịch, nội dung được giới hạn theo component, với tích hợp Vue (`vue-intlayer`). Chúng tôi đã so sánh [tính năng và trải nghiệm lập trình viên](https://intlayer.org/blog/vue-i18n-vs-intlayer) của cả hai. Bài viết này xem xét chi phí của mỗi thư viện sau khi ứng dụng được build.
|
|
27
|
+
|
|
28
|
+
Dữ liệu đến từ [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom), một bộ công cụ mã nguồn mở build cùng một ứng dụng với từng thư viện và ghi lại những gì trình duyệt thực sự tải xuống và thực thi.
|
|
29
|
+
|
|
30
|
+
<TOC/>
|
|
31
|
+
|
|
32
|
+
> **tl;dr**: Trên cùng một ứng dụng Vite + Vue 3, `vue-i18n` gửi **134,9 KB** JavaScript nén gzip mỗi trang so với **41,3 KB** cho ứng dụng không có i18n. Intlayer gửi **57,1 KB**. Riêng runtime của `vue-i18n` đã nặng **24,3 KB gzip** (gấp 6 lần 3,9 KB của Intlayer), mỗi trang mang theo **90% chuỗi của các trang khác**, và một component được biên dịch riêng lẻ kéo theo **196 KB** vì nó bị ràng buộc với cây thông điệp toàn cục. Adapter `@intlayer/vue-i18n` giữ nguyên API của `vue-i18n` và đo được **47,0 KB** mỗi trang.
|
|
33
|
+
|
|
34
|
+
## Tóm tắt
|
|
35
|
+
|
|
36
|
+
- **vue-i18n** - Thư viện i18n mặc định cho Vue 2 / Vue 3 và là lõi của `@nuxtjs/i18n`. Thông điệp kiểu ICU, khối `<i18n>` trong SFC, directive `v-t`, các formatter `d()` / `n()`, hệ sinh thái lớn. Thông điệp được đăng ký trên một instance toàn cục tại `createI18n()`; lazy loading theo locale là một pattern thủ công với `setLocaleMessage()`, và việc tách theo route là do bạn tự xây dựng.
|
|
37
|
+
- **Intlayer** - Mô hình nội dung lấy component làm trung tâm. Các từ điển `.content.ts` nằm cạnh component mà chúng phục vụ, một trình biên dịch lúc build (`vite-intlayer`) tree-shake và lazy-load chúng theo component và theo locale, các kiểu TypeScript nghiêm ngặt được sinh ra từ nội dung của bạn, và bản dịch thiếu sẽ gây lỗi lúc build. Đi kèm các helper cho router / SEO, Visual Editor / CMS và dịch có hỗ trợ AI.
|
|
38
|
+
|
|
39
|
+
| Thư viện | GitHub Stars | Tổng số commit | Commit gần nhất | Phiên bản đầu | Phiên bản NPM | Lượt tải NPM |
|
|
40
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
41
|
+
| `aymericzip/intlayer` | [](https://github.com/aymericzip/intlayer/stargazers) | [](https://github.com/aymericzip/intlayer/commits) | [](https://github.com/aymericzip/intlayer/commits) | Tháng 4 2024 | [](https://www.npmjs.com/package/intlayer) | [](https://www.npmjs.com/package/intlayer) |
|
|
42
|
+
| `intlify/vue-i18n` | [](https://github.com/intlify/vue-i18n/stargazers) | [](https://github.com/intlify/vue-i18n/commits) | [](https://github.com/intlify/vue-i18n/commits) | Tháng 12 2016 | [](https://www.npmjs.com/package/vue-i18n) | [](https://www.npmjs.com/package/vue-i18n) |
|
|
43
|
+
|
|
44
|
+
> Các huy hiệu tự động cập nhật. Ảnh chụp sẽ thay đổi theo thời gian.
|
|
45
|
+
|
|
46
|
+
## So sánh tính năng song song
|
|
47
|
+
|
|
48
|
+
| Tính năng | `vue-intlayer` (Intlayer) | `vue-i18n` |
|
|
49
|
+
| --------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
50
|
+
| **Bản dịch gần component** | ✅ Có, `.content.ts` đặt cùng chỗ với mỗi component | ✅ Qua khối SFC `<i18n>` (tùy chọn); catalog toàn cục là cách thiết lập phổ biến |
|
|
51
|
+
| **Tích hợp TypeScript** | ✅ Kiểu nghiêm ngặt tự động sinh từ nội dung | ✅ Typing tốt; an toàn khóa nghiêm ngặt cần typing schema và kỷ luật |
|
|
52
|
+
| **Phát hiện bản dịch thiếu** | ✅ Lỗi TypeScript + lỗi/cảnh báo lúc build | ⚠️ Fallback lúc runtime + cảnh báo console |
|
|
53
|
+
| **Nội dung phong phú (component / Markdown)** | ✅ Hỗ trợ trực tiếp | ⚠️ Nội suy component `<i18n-t>`; Markdown qua plugin bên ngoài |
|
|
54
|
+
| **Hỗ trợ ICU** | ⚠️ Đang phát triển | ✅ Có |
|
|
55
|
+
| **Định dạng (ngày, số, tiền tệ)** | ✅ Formatter dựa trên Intl | ✅ `d()` / `n()` với `datetimeFormats` / `numberFormats` |
|
|
56
|
+
| **Routing bản địa hóa** | ✅ Helper cho Vue Router / Nuxt, `getMultilingualUrls` | ⚠️ Không phải lõi (`@nuxtjs/i18n` hoặc thiết lập router tùy chỉnh) |
|
|
57
|
+
| **Helper SEO (hreflang, sitemap, robots)** | ✅ Helper tích hợp sẵn | ❌ Không phải lõi |
|
|
58
|
+
| **Tree-shaking (chỉ gửi nội dung được dùng)** | ✅ Theo component, theo locale, tự động bởi trình biên dịch | ⚠️ Thủ công: tách catalog, `setLocaleMessage()` theo route |
|
|
59
|
+
| **Lazy loading** | ✅ `importMode: 'dynamic'` (một dòng cấu hình) | ✅ `import()` thủ công + `setLocaleMessage()` |
|
|
60
|
+
| **Loại bỏ nội dung không dùng** | ✅ Từ điển không dùng bị loại bỏ lúc build | ❌ Không tích hợp sẵn |
|
|
61
|
+
| **Kiểm tra bản dịch thiếu (CLI / CI)** | ✅ `npx intlayer content test` | ⚠️ Bên thứ ba (`vue-i18n-extract`) |
|
|
62
|
+
| **Dịch bằng AI** | ✅ Tích hợp sẵn, dùng khóa nhà cung cấp của riêng bạn | ❌ Không |
|
|
63
|
+
| **Visual Editor / CMS** | ✅ Visual Editor miễn phí + CMS tùy chọn | ❌ Không (nền tảng bản địa hóa bên ngoài) |
|
|
64
|
+
| **MCP server & Agent Skills** | ✅ Có | ❌ Không |
|
|
65
|
+
| **Hệ sinh thái / cộng đồng** | ⚠️ Nhỏ hơn nhưng đang phát triển nhanh | ✅ Lớn và trưởng thành trong hệ sinh thái Vue |
|
|
66
|
+
|
|
67
|
+
## Benchmark
|
|
68
|
+
|
|
69
|
+
### Những gì được đo
|
|
70
|
+
|
|
71
|
+
Bộ [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) build **cùng một ứng dụng Vite + Vue 3** với từng thư viện: **10 trang** (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), **10 locale** (`en`, `fr`, `es`, `de`, `it`, `pt`, `zh`, `ja`, `ko`, `ru`), component giống hệt và nội dung giống hệt. Các trang được đo ở `en` và `fr`.
|
|
72
|
+
|
|
73
|
+
Cả hai thư viện được kiểm thử ở cấu hình **static**, cấu hình mà hầu hết dự án Vue triển khai: với `vue-i18n`, JSON của mọi locale được import và truyền vào `createI18n({ messages })`; với Intlayer, `importMode: 'static'` mặc định. Ở chế độ đó Intlayer cũng đóng gói mọi locale, nhưng trình biên dịch vẫn giới hạn nội dung **theo component**, nên một trang chỉ mang theo từ điển của các component mà nó render.
|
|
74
|
+
|
|
75
|
+
Với mỗi bản build, bộ công cụ ghi lại:
|
|
76
|
+
|
|
77
|
+
- **Lib size**: kích thước gzip của một component rỗng chỉ import thư viện i18n. Chi phí cố định của runtime.
|
|
78
|
+
- **Page JS**: JavaScript gzip tải xuống mỗi trang, tính trung bình trên tất cả các trang và locale.
|
|
79
|
+
- **Locale leak %**: tỷ lệ chuỗi đã dịch tìm thấy trong JS tải xuống thuộc về một locale mà người dùng **không** đang xem (lấy dấu vân tay trên `en` và `fr`, nên 50% nghĩa là "locale được đo còn lại hiện diện đầy đủ"; với 10 locale được đóng gói, lãng phí thực tế còn cao hơn).
|
|
80
|
+
- **Page leak %**: tỷ lệ chuỗi đã dịch tìm thấy trong JS tải xuống thuộc về một trang mà người dùng **không** đang ở.
|
|
81
|
+
- **Component avg**: kích thước gzip trung bình của mỗi component được biên dịch riêng lẻ. Cho thấy một component đơn lẻ kéo theo bao nhiêu runtime i18n và catalog.
|
|
82
|
+
- **E2E reactivity**: thời gian thực từ lúc chọn locale mới đến khi `html[lang]` được cập nhật trong DOM (Playwright, 5 lần lặp).
|
|
83
|
+
- **Page load**: `PerformanceNavigationTiming.duration`.
|
|
84
|
+
|
|
85
|
+
> Các con số dưới đây đến từ lần chạy ngày **2026-09-12** với `vue-i18n` 11.4.0 và `intlayer` 9.5.0 / 9.5.1. Ứng dụng kiểm thử được cố ý làm nhỏ (vài chục chuỗi mỗi locale), nên tỷ lệ rò rỉ mô tả một **mẫu hình**: chúng tăng theo nội dung của bạn trong khi chi phí runtime giữ nguyên.
|
|
86
|
+
|
|
87
|
+
### Kết quả trên Vite + Vue 3
|
|
88
|
+
|
|
89
|
+
| Thư viện | Chiến lược | Lib size (gz) | Lib size (min) | Page JS TB (gz) | Locale leak | Page leak | Component TB (gz) | Phản ứng E2E | Page load |
|
|
90
|
+
| ----------------------------- | ---------- | ------------: | -------------: | --------------: | ----------: | --------: | ----------------: | -----------: | --------: |
|
|
91
|
+
| **base** (không i18n) | - | 0,0 KB | 0,0 KB | 41,3 KB | 0,0% | - | 1,1 KB | 1,8 ms | 10,8 ms |
|
|
92
|
+
| `vue-i18n` | static | 24,3 KB | 83,2 KB | 134,9 KB | 50,0% | 90,0% | 196,0 KB | 2,8 ms | 13,6 ms |
|
|
93
|
+
| **`vue-intlayer`** | static | **3,9 KB** | **11,1 KB** | **57,1 KB** | 56,8% | **0,0%** | **7,7 KB** | **4,5 ms** | 13,8 ms |
|
|
94
|
+
| `@intlayer/vue-i18n` (compat) | static | 7,9 KB | 23,2 KB | 47,0 KB | 15,0% | 0,0% | 8,4 KB | 1,5 ms | 9,3 ms |
|
|
95
|
+
|
|
96
|
+
> Cột page-leak của ứng dụng base được để trống: không có thư viện i18n, việc lấy dấu vân tay bắt được các chuỗi hard-code trong các chunk dùng chung và con số không có ý nghĩa.
|
|
97
|
+
|
|
98
|
+
**Cách đọc**
|
|
99
|
+
|
|
100
|
+
- **Chi phí runtime.** `vue-i18n` là một trong những runtime nặng nhất toàn bộ benchmark: **24,3 KB gzip / 83,2 KB minified** cho một component rỗng chỉ import nó. `vue-intlayer` tốn 3,9 KB gzip. Khoảng cách đó phải trả trên mọi trang bất kể bạn có bao nhiêu chuỗi.
|
|
101
|
+
- **JavaScript mỗi trang.** Ứng dụng không có i18n nặng 41,3 KB. `vue-i18n` tăng gấp hơn ba lần lên **134,9 KB**; Intlayer dừng ở **57,1 KB**, +15,8 KB, phần lớn là mười locale được đóng gói (xem điểm tiếp theo).
|
|
102
|
+
- **Rò rỉ.** Với `createI18n({ messages: { en, fr, ... } })`, mọi trang gửi mọi locale và chuỗi của mọi trang: **50% rò rỉ locale** (trên hai locale được lấy dấu vân tay) và **90% rò rỉ trang**. Chế độ `static` của Intlayer cũng đóng gói mọi locale (do đó con số rò rỉ locale tương đương) nhưng có **0% rò rỉ trang**: một trang chỉ kéo từ điển của các component mà nó render. Chuyển sang `importMode: 'dynamic'` loại bỏ luôn rò rỉ locale; cấu hình đó không nằm trong lần chạy Vue này.
|
|
103
|
+
- **Kích thước component là nơi kiến trúc thể hiện rõ.** Một component gọi `useI18n()` biên dịch trung bình ra **196 KB**, vì `t()` bị ràng buộc với instance toàn cục chứa mọi thông điệp của mọi locale. Cùng component đó với `useIntlayer()` biên dịch ra **7,7 KB**: nó chỉ chạm tới từ điển của chính nó.
|
|
104
|
+
- **Độ phản ứng** không phải vấn đề với cả hai (2-5 ms). Hệ thống reactivity của Vue khiến việc đổi locale rất rẻ một khi thông điệp đã ở trong bộ nhớ.
|
|
105
|
+
- **`@intlayer/vue-i18n`**, adapter drop-in, giữ nguyên API của `vue-i18n` và đo được **47,0 KB mỗi trang** và **8,4 KB mỗi component**, với mã ứng dụng không thay đổi.
|
|
106
|
+
|
|
107
|
+
> Để tham khảo, cùng lần chạy đó đo `fluent-vue` ở mức 171,8 KB mỗi trang, 29,7 KB runtime và 217 KB mỗi component.
|
|
108
|
+
|
|
109
|
+
## Tại sao có khoảng cách? Instance toàn cục vs từ điển được biên dịch
|
|
110
|
+
|
|
111
|
+
`vue-i18n` là một runtime. `createI18n()` xây dựng một instance toàn cục chứa cây thông điệp cho mỗi locale; `useI18n()` ràng buộc mỗi component với nó; `t("footer.github")` tra khóa lúc render. Đây là điều giúp khối SFC `<i18n>`, `v-t` và tải thông điệp lúc runtime trở nên khả thi, và cũng là lý do đồ thị phụ thuộc của mọi component bao gồm toàn bộ cây:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
.
|
|
115
|
+
├── locales
|
|
116
|
+
│ ├── en.json
|
|
117
|
+
│ ├── fr.json
|
|
118
|
+
│ └── ... # một file mỗi locale, tất cả các trang bên trong
|
|
119
|
+
└── src
|
|
120
|
+
├── i18n.ts # createI18n({ messages: { en, fr, ... } })
|
|
121
|
+
├── main.ts
|
|
122
|
+
└── components
|
|
123
|
+
└── Footer.vue # const { t } = useI18n(); t("footer.github")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Tối ưu hóa nghĩa là **bạn** tách `en.json` thành các file theo route, **bạn** gọi `setLocaleMessage()` trong một router guard, và **bạn** giữ cho ánh xạ route-file luôn đúng khi component di chuyển. Runtime không thể làm điều đó cho bạn vì nó không biết component sẽ yêu cầu khóa nào.
|
|
127
|
+
|
|
128
|
+
Intlayer chuyển kiến thức đó sang lúc build. Nội dung được khai báo cạnh component, và `vite-intlayer` phân giải component nào import từ điển nào:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
.
|
|
132
|
+
├── intlayer.config.ts
|
|
133
|
+
└── src
|
|
134
|
+
├── main.ts # createApp(App).use(intlayer)
|
|
135
|
+
└── components
|
|
136
|
+
└── Footer
|
|
137
|
+
├── Footer.vue # useIntlayer("footer")
|
|
138
|
+
└── Footer.content.ts
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Trình biên dịch xuất ra, theo từng từ điển và từng locale, chính xác JSON mà component đó cần, và loại bỏ các từ điển không được import ở đâu cả. Giới hạn theo route là hệ quả của giới hạn theo component, không phải một nhiệm vụ.
|
|
142
|
+
|
|
143
|
+
> Để loại bỏ luôn các locale không dùng, đặt `dictionary.importMode: 'dynamic'` trong `intlayer.config.ts`. Xem [tài liệu tối ưu bundle](https://intlayer.org/doc/concept/bundle-optimization).
|
|
144
|
+
|
|
145
|
+
## Trải nghiệm lập trình viên
|
|
146
|
+
|
|
147
|
+
### Thiết lập
|
|
148
|
+
|
|
149
|
+
**vue-i18n**
|
|
150
|
+
|
|
151
|
+
```ts fileName="src/i18n.ts"
|
|
152
|
+
import { createI18n } from "vue-i18n";
|
|
153
|
+
import en from "../locales/en.json";
|
|
154
|
+
import fr from "../locales/fr.json";
|
|
155
|
+
|
|
156
|
+
export const i18n = createI18n({
|
|
157
|
+
legacy: false,
|
|
158
|
+
locale: "en",
|
|
159
|
+
fallbackLocale: "en",
|
|
160
|
+
messages: { en, fr },
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```ts fileName="src/main.ts"
|
|
165
|
+
import { createApp } from "vue";
|
|
166
|
+
import App from "./App.vue";
|
|
167
|
+
import router from "./router";
|
|
168
|
+
import { i18n } from "./i18n";
|
|
169
|
+
|
|
170
|
+
createApp(App).use(router).use(i18n).mount("#app");
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Intlayer**
|
|
174
|
+
|
|
175
|
+
```ts fileName="intlayer.config.ts"
|
|
176
|
+
import { type IntlayerConfig, Locales } from "intlayer";
|
|
177
|
+
|
|
178
|
+
const config: IntlayerConfig = {
|
|
179
|
+
internationalization: {
|
|
180
|
+
locales: [Locales.ENGLISH, Locales.FRENCH],
|
|
181
|
+
defaultLocale: Locales.ENGLISH,
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export default config;
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```ts fileName="vite.config.ts"
|
|
189
|
+
import { defineConfig } from "vite";
|
|
190
|
+
import vue from "@vitejs/plugin-vue";
|
|
191
|
+
import { intlayer } from "vite-intlayer";
|
|
192
|
+
|
|
193
|
+
export default defineConfig({
|
|
194
|
+
plugins: [intlayer(), vue()],
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```ts fileName="src/main.ts"
|
|
199
|
+
import { createApp } from "vue";
|
|
200
|
+
import { intlayer } from "vue-intlayer";
|
|
201
|
+
import App from "./App.vue";
|
|
202
|
+
import router from "./router";
|
|
203
|
+
|
|
204
|
+
createApp(App).use(intlayer).use(router).mount("#app");
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Component
|
|
208
|
+
|
|
209
|
+
**vue-i18n**
|
|
210
|
+
|
|
211
|
+
```json fileName="locales/en.json"
|
|
212
|
+
{
|
|
213
|
+
"counter": {
|
|
214
|
+
"label": "Counter",
|
|
215
|
+
"increment": "Increment"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
```vue fileName="src/components/Counter.vue"
|
|
221
|
+
<script setup lang="ts">
|
|
222
|
+
import { ref } from "vue";
|
|
223
|
+
import { useI18n } from "vue-i18n";
|
|
224
|
+
|
|
225
|
+
const { t, n } = useI18n();
|
|
226
|
+
const count = ref(0);
|
|
227
|
+
</script>
|
|
228
|
+
|
|
229
|
+
<template>
|
|
230
|
+
<div>
|
|
231
|
+
<p>{{ n(count) }}</p>
|
|
232
|
+
<button :aria-label="t('counter.label')" @click="count++">
|
|
233
|
+
{{ t("counter.increment") }}
|
|
234
|
+
</button>
|
|
235
|
+
</div>
|
|
236
|
+
</template>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
`t('counter.label')` chỉ là một chuỗi cho đến khi bạn tự định kiểu schema thông điệp; một lỗi gõ sẽ render ra khóa.
|
|
240
|
+
|
|
241
|
+
**Intlayer**
|
|
242
|
+
|
|
243
|
+
```ts fileName="src/components/Counter/Counter.content.ts"
|
|
244
|
+
import { t, type Dictionary } from "intlayer";
|
|
245
|
+
|
|
246
|
+
const counterContent = {
|
|
247
|
+
key: "counter",
|
|
248
|
+
content: {
|
|
249
|
+
label: t({ en: "Counter", fr: "Compteur" }),
|
|
250
|
+
increment: t({ en: "Increment", fr: "Incrémenter" }),
|
|
251
|
+
},
|
|
252
|
+
} satisfies Dictionary;
|
|
253
|
+
|
|
254
|
+
export default counterContent;
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```vue fileName="src/components/Counter/Counter.vue"
|
|
258
|
+
<script setup lang="ts">
|
|
259
|
+
import { ref } from "vue";
|
|
260
|
+
import { useIntlayer } from "vue-intlayer";
|
|
261
|
+
import { useNumber } from "vue-intlayer/format";
|
|
262
|
+
|
|
263
|
+
const { label, increment } = useIntlayer("counter");
|
|
264
|
+
const number = useNumber();
|
|
265
|
+
const count = ref(0);
|
|
266
|
+
</script>
|
|
267
|
+
|
|
268
|
+
<template>
|
|
269
|
+
<div>
|
|
270
|
+
<p>{{ number.value(count) }}</p>
|
|
271
|
+
<button :aria-label="label" @click="count++">
|
|
272
|
+
{{ increment }}
|
|
273
|
+
</button>
|
|
274
|
+
</div>
|
|
275
|
+
</template>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`label` và `increment` có kiểu; một lỗi gõ là lỗi TypeScript, thiếu giá trị tiếng Pháp là lỗi build.
|
|
279
|
+
|
|
280
|
+
### Lazy loading theo locale
|
|
281
|
+
|
|
282
|
+
**vue-i18n**
|
|
283
|
+
|
|
284
|
+
```ts fileName="src/i18n.ts"
|
|
285
|
+
import { nextTick } from "vue";
|
|
286
|
+
import { createI18n } from "vue-i18n";
|
|
287
|
+
|
|
288
|
+
export const i18n = createI18n({
|
|
289
|
+
legacy: false,
|
|
290
|
+
locale: "en",
|
|
291
|
+
fallbackLocale: "en",
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
export const loadLocaleMessages = async (locale: string) => {
|
|
295
|
+
const messages = await import(`../locales/${locale}.json`);
|
|
296
|
+
i18n.global.setLocaleMessage(locale, messages.default);
|
|
297
|
+
await nextTick();
|
|
298
|
+
i18n.global.locale.value = locale;
|
|
299
|
+
};
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Sau đó gọi `loadLocaleMessages()` từ một router guard, và tự tách `locales/{locale}.json` theo route nếu bạn muốn giới hạn theo trang.
|
|
303
|
+
|
|
304
|
+
**Intlayer**
|
|
305
|
+
|
|
306
|
+
```ts fileName="intlayer.config.ts"
|
|
307
|
+
const config: IntlayerConfig = {
|
|
308
|
+
// ...
|
|
309
|
+
dictionary: {
|
|
310
|
+
importMode: "dynamic",
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Giữ API của vue-i18n, nhận đầu ra của Intlayer
|
|
316
|
+
|
|
317
|
+
`@intlayer/vue-i18n` là một adapter drop-in: `useI18n()`, `t()`, `d()`, `n()`, nội suy `{name}` và `{0}`, số nhiều dạng pipe (`"car | cars"`), `v-t` và `i18n.global.locale` vẫn hoạt động, được phục vụ từ các từ điển Intlayer do `vite-intlayer` biên dịch.
|
|
318
|
+
|
|
319
|
+
```ts fileName="vite.config.ts"
|
|
320
|
+
import { defineConfig } from "vite";
|
|
321
|
+
import vue from "@vitejs/plugin-vue";
|
|
322
|
+
import vueI18nVitePlugin from "@intlayer/vue-i18n/plugin";
|
|
323
|
+
|
|
324
|
+
export default defineConfig({
|
|
325
|
+
plugins: [vue(), vueI18nVitePlugin()],
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Trong benchmark, bản build compat của cùng ứng dụng giảm từ **134,9 KB xuống 47,0 KB** mỗi trang và từ **196 KB xuống 8,4 KB** mỗi component, với các component không thay đổi. Các file `locales/{locale}.json` hiện có của bạn có thể tiếp tục là nguồn sự thật thông qua plugin đồng bộ JSON.
|
|
330
|
+
|
|
331
|
+
Xem [hướng dẫn di chuyển từ vue-i18n](https://intlayer.org/doc/migration/vue-i18n) và [tài liệu tương thích](https://intlayer.org/doc/compatibility/vue-i18n). Người dùng Nuxt có cùng lộ trình qua [tương thích `@nuxtjs/i18n`](https://intlayer.org/doc/compatibility/nuxtjs-i18n).
|
|
332
|
+
|
|
333
|
+
## Khi nào chọn cái nào?
|
|
334
|
+
|
|
335
|
+
- **Chọn vue-i18n** nếu bạn muốn cách tiếp cận Vue tiêu chuẩn, bạn dựa vào thông điệp ICU hoặc khối SFC `<i18n>`, bạn đã dùng `@nuxtjs/i18n`, hoặc một nền tảng dịch thuật yêu cầu JSON tập trung. Hãy dành thời gian tách catalog và lazy-load theo route nếu kích thước bundle quan trọng.
|
|
336
|
+
- **Chọn Intlayer** nếu bạn muốn **nội dung giới hạn theo component**, **TypeScript nghiêm ngặt**, **lỗi thiếu khóa lúc build**, **tree-shaking và lazy loading không tốn công**, và công cụ biên tập tích hợp sẵn (Visual Editor, CMS, dịch AI, MCP server). Đặc biệt phù hợp với các codebase Vue / Nuxt lớn, mô-đun hóa và các design system.
|
|
337
|
+
- **Chọn `@intlayer/vue-i18n`** nếu bạn đã dùng `vue-i18n` và muốn lợi ích về bundle mà không cần viết lại.
|
|
338
|
+
|
|
339
|
+
## Các so sánh liên quan
|
|
340
|
+
|
|
341
|
+
- [next-intl vs Intlayer](https://intlayer.org/blog/next-intl-vs-intlayer) (cùng benchmark)
|
|
342
|
+
- [i18next vs Intlayer](https://intlayer.org/blog/i18next-vs-intlayer) (cùng benchmark)
|
|
343
|
+
- [Lingui vs Intlayer](https://intlayer.org/blog/lingui-vs-intlayer) (cùng benchmark)
|
|
344
|
+
- [vue-i18n vs Intlayer (tính năng & DX)](https://intlayer.org/blog/vue-i18n-vs-intlayer)
|
|
345
|
+
- [vue-i18n đã lỗi thời?](https://intlayer.org/blog/is-vue-i18n-outdated)
|
|
346
|
+
|
|
347
|
+
## GitHub Stars
|
|
348
|
+
|
|
349
|
+
GitHub stars là chỉ báo mạnh về mức độ phổ biến của một dự án, sự tin tưởng của cộng đồng và tính phù hợp lâu dài. Dù không phải thước đo trực tiếp về chất lượng kỹ thuật, chúng phản ánh có bao nhiêu lập trình viên thấy dự án hữu ích, theo dõi tiến trình của nó và có khả năng áp dụng.
|
|
350
|
+
|
|
351
|
+
[](https://star-history.com/#intlify/vue-i18n&aymericzip/intlayer)
|
|
352
|
+
|
|
353
|
+
## Kết luận
|
|
354
|
+
|
|
355
|
+
`vue-i18n` trưởng thành, linh hoạt và tích hợp sâu với Vue. Benchmark cho thấy thiết kế ưu tiên runtime của nó tốn gì trên một bản build Vite: **runtime 24 KB gzip**, **134,9 KB mỗi trang** cho một ứng dụng chỉ nặng 41 KB khi không có i18n, **90% nội dung của trang khác** trên mọi trang, và các component mỗi cái lên tới **196 KB** vì chúng treo trên cây thông điệp toàn cục.
|
|
356
|
+
|
|
357
|
+
Intlayer chuyển công việc vào trình biên dịch. Từ điển theo component và loại bỏ nội dung chết là đầu ra của build, không phải quy ước. Trên cùng ứng dụng: **runtime 3,9 KB**, **57,1 KB mỗi trang**, **0% rò rỉ trang**, component **nhỏ hơn 25 lần**. Và nếu việc viết lại không khả thi, `@intlayer/vue-i18n` đi được phần lớn chặng đường mà không đụng đến component.
|
|
358
|
+
|
|
359
|
+
Toàn bộ dữ liệu thô, ứng dụng kiểm thử và script nằm trong [kho lưu trữ Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom). Hãy tự chạy thử.
|
|
360
|
+
|
|
361
|
+
Tham khảo [tài liệu 'Tại sao Intlayer?'](https://intlayer.org/doc/why) để biết thêm chi tiết.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2026-09-13
|
|
3
|
-
updatedAt: 2026-09-
|
|
3
|
+
updatedAt: 2026-09-22
|
|
4
4
|
title: "i18next vs @intlayer/i18next:相同的 API,截然不同的 Bundle"
|
|
5
5
|
description: 当 React 或 Next.js 应用保持其 i18next、react-i18next 和 next-i18next 调用不变,但改由 @intlayer/i18next 适配器提供服务时会发生什么变化。基于同一套代码测量的每页 JavaScript 体积、组件大小、文本泄漏与水合性能,以及适配器保留、忽略和无法替代的功能。
|
|
6
6
|
keywords:
|
|
@@ -28,6 +28,8 @@ author: aymericzip
|
|
|
28
28
|
|
|
29
29
|
# i18next VS @intlayer/i18next | 相同的 API,截然不同的 Bundle
|
|
30
30
|
|
|
31
|
+

|
|
32
|
+
|
|
31
33
|
`@intlayer/i18next`、`@intlayer/react-i18next` 和 `@intlayer/next-i18next` 是兼容适配器。它们暴露了你的代码已经在使用的 `i18next` API(`useTranslation`、`t()`、`<Trans>`、`i18n.changeLanguage()`、`getFixedT`、`serverSideTranslations` 等),并通过 Intlayer 编译好的字典来提供数据。组件不需要做任何更改,只是其底层的运行时发生了改变。
|
|
32
34
|
|
|
33
35
|
本文在同一个 Next.js 应用程序上对比了这种替换:一次使用 `next-i18next` 构建,另一次使用 `@intlayer/next-i18next` 构建。测试数据来源于 [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom)。如需对比作为独立库的 `i18next` 与 Intlayer,请阅读 [i18next vs Intlayer](https://intlayer.org/zh/blog/i18next-vs-intlayer)。本文则专注于:当你保持原有代码不变时,适配器带来了哪些实际变化。
|
|
@@ -109,6 +111,10 @@ const About = () => {
|
|
|
109
111
|
|
|
110
112
|
### Next.js 平台对比数据
|
|
111
113
|
|
|
114
|
+
选择您关注的指标和库:
|
|
115
|
+
|
|
116
|
+
<I18nBenchmark framework="nextjs" vertical/>
|
|
117
|
+
|
|
112
118
|
| 方案 | 加载策略 | Lib 体积 (gz) | 每页 JS 均值 (gz) | 语言泄漏率 | 跨页泄漏率 | 组件均值 (gz) | E2E 响应耗时 | 水合耗时 |
|
|
113
119
|
| ---------------------------- | -------------- | ------------: | ----------------: | ---------: | ---------: | ------------: | -----------: | ----------: |
|
|
114
120
|
| **base** (无 i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
|
|
@@ -129,10 +135,21 @@ const About = () => {
|
|
|
129
135
|
- **更迅捷的水合与语言切换。** 水合耗时从 15.6 ms 降至 **11.3 ms**(对比 `dynamic` 方案中后端请求阻塞关键渲染路径导致的 27.7 ms 提升尤为显著)。语言实时切换耗时也从 15-16 ms 缩减至 **11-12 ms**。
|
|
130
136
|
- **适配器不等于原生极致架构。** 原生的 `next-intlayer` 仅有 **141.3 KB**,仅比无任何国际化逻辑的基础应用多了 0.3 KB。适配器为了维持 `i18next` API 的兼容性(插值语法、复数与上下文后缀解析、`<Trans>` 标签树解析),在 Intlayer 核心之上保留了一层 9.4 KB 的兼容垫片。它是迈向现代化的无缝桥梁,而非终点。
|
|
131
137
|
|
|
138
|
+
<ClickToOpenIframe
|
|
139
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-nextjs.md"
|
|
140
|
+
width="100%"
|
|
141
|
+
height="600px"
|
|
142
|
+
style="border:none;"
|
|
143
|
+
/>
|
|
144
|
+
|
|
145
|
+
> 完整表格、各个库及每种策略,请参阅 [Next.js 基准测试报告](https://intlayer.org/zh/doc/benchmark/nextjs)。
|
|
146
|
+
|
|
132
147
|
> 本次评测暂未包含 Vite / TanStack Start 上的 `react-i18next` 适配器。有关 TanStack Start 的基准表现可参考 [i18next vs Intlayer](https://intlayer.org/zh/blog/i18next-vs-intlayer):每页 127-184 KB,后端异步加载下的语言切换延迟约为 123-185 ms。
|
|
133
148
|
|
|
134
149
|
## 性能巨幅提升的底层机理
|
|
135
150
|
|
|
151
|
+

|
|
152
|
+
|
|
136
153
|
业务 `components/` 目录没有改动一行代码,所有性能收益完全归结于 `useTranslation` 到底绑定在什么载体上。
|
|
137
154
|
|
|
138
155
|
**在 `i18next` 中**,组件必须挂载到全局实例上。凡是预加载进该实例的内容(`static` 下的全部语种,或 `dynamic` 下当前语种的全部字典),都能被任何一个调用 `useTranslation()` 的组件直接访问。打包工具无法对实例内部的数据进行细粒度拆分,运行时也无法预知组件渲染时会访问哪些键名。
|
|
@@ -149,6 +166,10 @@ const About = () => {
|
|
|
149
166
|
└── About.tsx # useTranslation(); t("about.title")
|
|
150
167
|
```
|
|
151
168
|
|
|
169
|
+
实例中包含的任何内容都会发送到每个页面,浪费在页面和语言两个维度上不断增长:
|
|
170
|
+
|
|
171
|
+

|
|
172
|
+
|
|
152
173
|
**在 `@intlayer/next-i18next` 中**,组件直接与精简字典绑定。`syncJSON` 将每个命名空间文件解析并独立封装为字典;编译优化通道将组件精准重定向为对其声明字典的直接导入,这让打包工具能够像处理普通 JS 模块一样,按照页面和语言维度进行 Tree-shaking 与按需代码分割。
|
|
153
174
|
|
|
154
175
|
```bash
|
|
@@ -297,26 +318,112 @@ export default defineConfig({
|
|
|
297
318
|
|
|
298
319
|
## 启动迁移前必须明确的技术边界
|
|
299
320
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
321
|
+
<AccordionGroup>
|
|
322
|
+
<Accordion header="后端和检测器不生效">
|
|
323
|
+
|
|
324
|
+
`i18n.use(HttpBackend)` 仅调用插件的 init,不执行其他任何操作。如果您的应用依赖于在运行时从 CMS 获取翻译,该流程已不复存在;请改用 [Intlayer CMS](https://intlayer.org/zh/doc/concept/cms) 或 `intlayer pull` / `push` 命令。语言检测由 Intlayer 的路由配置接管(URL 前缀、cookie、请求头)。
|
|
325
|
+
|
|
326
|
+
</Accordion>
|
|
327
|
+
<Accordion header="resources 被忽略,不进行合并">
|
|
328
|
+
|
|
329
|
+
与其他一些适配器不同,`@intlayer/i18next` 不使用内联 `resources` 作为回退。每个键必须存在于同步的字典中,`intlayer test` 会对此进行验证。
|
|
330
|
+
|
|
331
|
+
</Accordion>
|
|
332
|
+
<Accordion header="App Router 需要修改 provider">
|
|
333
|
+
|
|
334
|
+
仅需修改一个文件,如上所示。使用 `appWithTranslation` 的 Pages Router 无需任何更改。
|
|
335
|
+
|
|
336
|
+
</Accordion>
|
|
337
|
+
<Accordion header="不读取 next-i18next.config.js">
|
|
338
|
+
|
|
339
|
+
`localePath`、`fallbackLng`、`reloadOnPrerender` 等配置项均无对应项;语言和回退语言均来自 `intlayer.config.ts`。
|
|
340
|
+
|
|
341
|
+
</Accordion>
|
|
342
|
+
<Accordion header="适配器并非完全零成本">
|
|
343
|
+
|
|
344
|
+
相比 `next-intlayer`,它增加了 9.4 KB 的运行时以及每页 +9.4 KB 的体积。一旦所有组件都迁移到 `useIntlayer`,即可将其移除。
|
|
345
|
+
|
|
346
|
+
</Accordion>
|
|
347
|
+
</AccordionGroup>
|
|
305
348
|
|
|
306
349
|
## 选型决策指南
|
|
307
350
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
351
|
+
<AccordionGroup>
|
|
352
|
+
<Accordion header="继续使用 i18next">
|
|
353
|
+
|
|
354
|
+
您的应用依赖于运行时后端(在请求时由 CMS 提供的翻译)、插件生态系统,或者适配器未涵盖的非 React 目标环境。
|
|
355
|
+
|
|
356
|
+
</Accordion>
|
|
357
|
+
<Accordion header="使用 @intlayer/*">
|
|
358
|
+
|
|
359
|
+
您正在使用 `react-i18next` / `next-i18next`,希望在无需重写代码的前提下节省 68 KB、实现组件体积缩小 8 倍、0% 泄漏、类型化键和 CI 检查。这是现有 `i18next` 代码库的最佳过渡方案。
|
|
360
|
+
|
|
361
|
+
</Accordion>
|
|
362
|
+
<Accordion header="转向原生 (next-intlayer / react-intlayer)">
|
|
363
|
+
|
|
364
|
+
适用于新项目,或在适配器完成过渡任务之后。它具有最轻量的运行时(5.5 KB,每页仅增加 0.3 KB),并解锁同步 Server Components 和按组件划分的 `.content.ts` 文件。请从 [Intlayer 与 Next.js](https://intlayer.org/zh/doc/environment/nextjs) 或 [与 Vite 和 React](https://intlayer.org/zh/doc/environment/vite-and-react) 开始。
|
|
365
|
+
|
|
366
|
+
</Accordion>
|
|
367
|
+
</AccordionGroup>
|
|
368
|
+
|
|
369
|
+
## 常见问题解答
|
|
370
|
+
|
|
371
|
+
<FAQ>
|
|
372
|
+
|
|
373
|
+
<Question title="68 KB 的体积节省来自哪里?">
|
|
374
|
+
|
|
375
|
+
来自 `resources: { en, fr, ... }`。原生的 `next-i18next` 配置会在 `init()` 中导入每种语言的全部 JSON,因此每个页面都携带所有语言的每个命名空间:每页达到 **218.5 KB**。适配器从不打包整个区块;它仅在当前激活的语言下向每个组件提供其声明的字典。
|
|
376
|
+
|
|
377
|
+
</Question>
|
|
378
|
+
|
|
379
|
+
<Question title="我的 <Trans> 组件还能正常工作吗?">
|
|
380
|
+
|
|
381
|
+
可以,完全支持 `components`、数字标签 `<1>...</1>` 以及 `values`。同时支持 `{{interpolation}}`、`$t(key)` 嵌套、`key_one` / `key_other` 复数(由 `Intl.PluralRules` 计算)、上下文后缀以及 `returnObjects`。
|
|
382
|
+
|
|
383
|
+
</Question>
|
|
384
|
+
|
|
385
|
+
<Question title="如果我每种语言只使用一个 translation.json 怎么办?">
|
|
386
|
+
|
|
387
|
+
在 `syncJSON` 插件中设置 `splitKeys: false`。整个文件将保持为一个字典,普通的 `useTranslation()` 会继续针对其进行解析。
|
|
388
|
+
|
|
389
|
+
</Question>
|
|
390
|
+
|
|
391
|
+
<Question title="这是否等同于直接迁移到 Intlayer?">
|
|
392
|
+
|
|
393
|
+
不等同,它是过渡桥梁。适配器保留了 `i18next` 的 API,运行时开销为 9.4 KB;原生 `next-intlayer` 仅需 5.5 KB,并带来同步 Server Components 和同级放置的 `.content.ts` 文件。由于 JSON 和 `.content.ts` 字典可以并存,您可以逐个组件推进迁移。
|
|
394
|
+
|
|
395
|
+
</Question>
|
|
396
|
+
|
|
397
|
+
<Question title="翻译人员是否能沿用目前的工作流程?">
|
|
398
|
+
|
|
399
|
+
可以。`locales/{lng}/{ns}.json` 依然是唯一事实来源:`syncJSON` 以 i18next 方言读取它,并在 CLI 或 CMS 更新时将翻译写回。
|
|
400
|
+
|
|
401
|
+
</Question>
|
|
402
|
+
|
|
403
|
+
</FAQ>
|
|
311
404
|
|
|
312
405
|
## 相关对比与进阶文档
|
|
313
406
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
- [
|
|
317
|
-
- [
|
|
318
|
-
-
|
|
319
|
-
|
|
407
|
+
同系列适配器:
|
|
408
|
+
|
|
409
|
+
- [next-intl vs @intlayer/next-intl](https://intlayer.org/zh/blog/next-intl-vs-intlayer-next-intl)
|
|
410
|
+
- [Lingui vs @intlayer/lingui](https://intlayer.org/zh/blog/lingui-vs-intlayer-lingui)
|
|
411
|
+
- [vue-i18n vs @intlayer/vue-i18n](https://intlayer.org/zh/blog/vue-i18n-vs-intlayer-vue-i18n)
|
|
412
|
+
|
|
413
|
+
两两直接对比:
|
|
414
|
+
|
|
415
|
+
- [i18next vs Intlayer](https://intlayer.org/zh/blog/i18next-vs-intlayer), same benchmark
|
|
416
|
+
- [next-i18next vs next-intl vs Intlayer](https://intlayer.org/zh/blog/next-i18next-vs-next-intl-vs-intlayer)
|
|
417
|
+
- [react-i18next vs react-intl vs Intlayer](https://intlayer.org/zh/blog/react-i18next-vs-react-intl-vs-intlayer)
|
|
418
|
+
- [Is i18next outdated?](https://intlayer.org/zh/blog/is-i18next-outdated)
|
|
419
|
+
|
|
420
|
+
参考文档:
|
|
421
|
+
|
|
422
|
+
- Compat adapters: [i18next](https://intlayer.org/zh/doc/compatibility/i18next), [react-i18next](https://intlayer.org/zh/doc/compatibility/react-i18next), [next-i18next](https://intlayer.org/zh/doc/compatibility/next-i18next)
|
|
423
|
+
- Migration guides: [i18next](https://intlayer.org/zh/doc/migration/i18next), [react-i18next](https://intlayer.org/zh/doc/migration/react-i18next), [next-i18next](https://intlayer.org/zh/doc/migration/next-i18next)
|
|
424
|
+
- [Next.js benchmark report](https://intlayer.org/zh/doc/benchmark/nextjs) and [TanStack Start benchmark report](https://intlayer.org/zh/doc/benchmark/tanstack)
|
|
425
|
+
- [Bundle optimization](https://intlayer.org/zh/doc/concept/bundle-optimization) and [the Intlayer compiler](https://intlayer.org/zh/doc/compiler)
|
|
426
|
+
- [Visual Editor](https://intlayer.org/zh/doc/concept/editor), [CMS](https://intlayer.org/zh/doc/concept/cms) and [AI translation](https://intlayer.org/zh/doc/concept/auto-fill)
|
|
320
427
|
|
|
321
428
|
## 总结
|
|
322
429
|
|