@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
|
@@ -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: Đo kiểm và So sánh chi tiết năm 2026"
|
|
5
5
|
description: "Đo lường react-i18next và next-i18next so với Intlayer trên Next.js và TanStack Start. Kích thước bundle, rò rỉ nội dung, tốc độ phản hồi khi chuyển ngôn ngữ và trải nghiệm lập trình viên."
|
|
6
6
|
keywords:
|
|
@@ -25,6 +25,8 @@ author: aymericzip
|
|
|
25
25
|
|
|
26
26
|
# i18next VS Intlayer | Đo kiểm đa ngôn ngữ (i18n) cho React & Next.js
|
|
27
27
|
|
|
28
|
+

|
|
29
|
+
|
|
28
30
|
`i18next` là framework i18n phổ biến nhất trong hệ sinh thái JavaScript. Thông qua `react-i18next` và `next-i18next`, nó đang vận hành phần lớn các ứng dụng React và Next.js. Intlayer là một giải pháp thay thế hiện đại dựa trên trình biên dịch và cô lập phạm vi theo từng component.
|
|
29
31
|
|
|
30
32
|
Bài viết này so sánh hai giải pháp dựa trên số liệu đo lường thực tế thay vì danh sách tính năng đơn thuần. Các số liệu được trích xuất từ [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) - một bộ đo lường nguồn mở xây dựng cùng một ứng dụng mẫu trên từng thư viện và ghi nhận chính xác những gì trình duyệt tải về.
|
|
@@ -99,6 +101,10 @@ Các chỉ số đo lường:
|
|
|
99
101
|
|
|
100
102
|
### Kết quả trên Next.js (`next-i18next`)
|
|
101
103
|
|
|
104
|
+
Chọn các chỉ số và thư viện bạn quan tâm:
|
|
105
|
+
|
|
106
|
+
<I18nBenchmark framework="nextjs" vertical/>
|
|
107
|
+
|
|
102
108
|
| Thư viện | Chiến lược | Dung lượng Lib (gz) | JS TB mỗi trang (gz) | Rò rỉ ngôn ngữ | Rò rỉ trang | Kích thước TB Comp (gz) | Phản hồi E2E | Thời gian Hydrate |
|
|
103
109
|
| -------------------------------------- | -------------- | ------------------: | -------------------: | -------------: | ----------: | ----------------------: | -----------: | ----------------: |
|
|
104
110
|
| **base** (không i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
|
|
@@ -119,6 +125,15 @@ Các chỉ số đo lường:
|
|
|
119
125
|
- **Kích thước từng component**: Một component gọi `useTranslation()` được đóng gói trong khoảng 26 đến 79 KB; trong khi component tương đương dùng `useIntlayer()` chỉ nặng 6.9 KB.
|
|
120
126
|
- **Độ trễ khi hydrate**: Thời gian hydrate tăng vọt lên 27.7 ms ở cấu hình `dynamic` do thực thể i18next cần khởi tạo và nạp backend tại client trước khi React có thể hoàn tất quá trình hydrate.
|
|
121
127
|
|
|
128
|
+
<ClickToOpenIframe
|
|
129
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-nextjs.md"
|
|
130
|
+
width="100%"
|
|
131
|
+
height="600px"
|
|
132
|
+
style="border:none;"
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
> Bảng đầy đủ, từng thư viện và từng chiến lược, trong [báo cáo benchmark Next.js](https://intlayer.org/vi/doc/benchmark/nextjs).
|
|
136
|
+
|
|
122
137
|
### Kết quả trên TanStack Start (`react-i18next`)
|
|
123
138
|
|
|
124
139
|
Cùng ứng dụng kiểm thử trên nền tảng TanStack Start sử dụng trực tiếp `react-i18next` nhằm loại bỏ các yếu tố can thiệp riêng của Next.js:
|
|
@@ -141,8 +156,19 @@ Cùng ứng dụng kiểm thử trên nền tảng TanStack Start sử dụng tr
|
|
|
141
156
|
- Chế độ `static` của Intlayer đã mặc định đạt **0% rò rỉ trang** vì nó chỉ đóng gói các từ điển được import bởi component của trang đó. Bật `importMode: 'dynamic'` sẽ triệt tiêu hoàn toàn rò rỉ ngôn ngữ.
|
|
142
157
|
- **Kích thước component**: 24-27 KB ở `react-i18next` so với 6-8 KB ở Intlayer. `useTranslation()` luôn gắn chặt từng component với instance i18next toàn cục.
|
|
143
158
|
|
|
159
|
+
<ClickToOpenIframe
|
|
160
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-tanstack.md"
|
|
161
|
+
width="100%"
|
|
162
|
+
height="600px"
|
|
163
|
+
style="border:none;"
|
|
164
|
+
/>
|
|
165
|
+
|
|
166
|
+
> Bảng đầy đủ trong [báo cáo benchmark TanStack Start](https://intlayer.org/vi/doc/benchmark/tanstack).
|
|
167
|
+
|
|
144
168
|
## Nguyên nhân của sự chênh lệch: Global Instance vs Từ điển biên dịch
|
|
145
169
|
|
|
170
|
+

|
|
171
|
+
|
|
146
172
|
`i18next` được xây dựng từ năm 2012 theo hướng runtime: một instance toàn cục nắm giữ kho tài nguyên, các plugin mở rộng nó và hàm `t()` tìm khóa khi render. Thiết kế này đem lại tính linh hoạt cao nhưng tạo ra gánh nặng lớn về dung lượng:
|
|
147
173
|
|
|
148
174
|
```bash
|
|
@@ -166,7 +192,13 @@ Cùng ứng dụng kiểm thử trên nền tảng TanStack Start sử dụng tr
|
|
|
166
192
|
└── page.tsx # phải tự biết rằng trang này cần ["common", "about"]
|
|
167
193
|
```
|
|
168
194
|
|
|
169
|
-
Instance toàn cục không thể biết trước component sẽ gọi những khóa nào; vì vậy nó buộc phải lưu trữ toàn bộ các namespace được chỉ định nạp. Muốn tối ưu, **bạn** phải chia nhỏ danh mục, **bạn** phải liệt kê các namespace cần thiết cho từng trang, và **bạn** phải duy trì danh sách này khi component di chuyển.
|
|
195
|
+
Instance toàn cục không thể biết trước component sẽ gọi những khóa nào; vì vậy nó buộc phải lưu trữ toàn bộ các namespace được chỉ định nạp. Muốn tối ưu, **bạn** phải chia nhỏ danh mục, **bạn** phải liệt kê các namespace cần thiết cho từng trang, và **bạn** phải duy trì danh sách này khi component di chuyển.
|
|
196
|
+
|
|
197
|
+
Chi phí gia tăng đồng thời trên hai trục, trang và ngôn ngữ:
|
|
198
|
+
|
|
199
|
+

|
|
200
|
+
|
|
201
|
+
Đúng như [ghi chú benchmark](https://github.com/intlayer-org/benchmark-bloom/blob/main/report/NOTE.md) đã chỉ ra: "Vừa duy trì an toàn kiểu dữ liệu vừa quản lý đúng namespace cho từng trang thực sự là một cơn ác mộng".
|
|
170
202
|
|
|
171
203
|
Intlayer loại bỏ hoàn toàn instance toàn cục. Nội dung được khai báo ngay cạnh component và trình biên dịch sẽ giải quyết cây phụ thuộc vào lúc build:
|
|
172
204
|
|
|
@@ -193,7 +225,8 @@ Intlayer loại bỏ hoàn toàn instance toàn cục. Nội dung được khai
|
|
|
193
225
|
|
|
194
226
|
### Khởi tạo cấu hình
|
|
195
227
|
|
|
196
|
-
|
|
228
|
+
<Tabs defaultTab="intlayer" group="techno">
|
|
229
|
+
<Tab label="next-i18next" value="i18next">
|
|
197
230
|
|
|
198
231
|
```ts fileName="src/app/i18n/server.ts"
|
|
199
232
|
import { createInstance } from "i18next";
|
|
@@ -228,7 +261,8 @@ export const initI18next = async (
|
|
|
228
261
|
|
|
229
262
|
Bên cạnh đó, bạn phải viết thêm `I18nProvider` ở phía client, khai báo `generateStaticParams` và quản lý mảng `namespaces` trên từng trang.
|
|
230
263
|
|
|
231
|
-
|
|
264
|
+
</Tab>
|
|
265
|
+
<Tab label="Intlayer" value="intlayer">
|
|
232
266
|
|
|
233
267
|
```ts fileName="intlayer.config.ts"
|
|
234
268
|
import { type IntlayerConfig, Locales } from "intlayer";
|
|
@@ -264,9 +298,13 @@ const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
|
|
|
264
298
|
export default LocaleLayout;
|
|
265
299
|
```
|
|
266
300
|
|
|
301
|
+
</Tab>
|
|
302
|
+
</Tabs>
|
|
303
|
+
|
|
267
304
|
### Component phía Client
|
|
268
305
|
|
|
269
|
-
|
|
306
|
+
<Tabs defaultTab="intlayer" group="techno">
|
|
307
|
+
<Tab label="react-i18next" value="i18next">
|
|
270
308
|
|
|
271
309
|
```json fileName="src/locales/en/about.json"
|
|
272
310
|
{
|
|
@@ -304,7 +342,8 @@ export const Counter = () => {
|
|
|
304
342
|
|
|
305
343
|
> Trang hiển thị component này bắt buộc phải nạp namespace `about`, và `t("counter.label")` sẽ chỉ là chuỗi thông thường nếu chưa mở rộng `CustomTypeOptions`.
|
|
306
344
|
|
|
307
|
-
|
|
345
|
+
</Tab>
|
|
346
|
+
<Tab label="Intlayer" value="intlayer">
|
|
308
347
|
|
|
309
348
|
```ts fileName="src/components/Counter/index.content.ts"
|
|
310
349
|
import { t, type Dictionary } from "intlayer";
|
|
@@ -345,9 +384,13 @@ export const Counter = () => {
|
|
|
345
384
|
|
|
346
385
|
`label` và `increment` đều được kiểm tra kiểu dữ liệu nghiêm ngặt; gõ sai tên sẽ báo lỗi TypeScript ngay lập tức, và nếu thiếu bản dịch tiếng Pháp thì quá trình build sẽ bị dừng lại.
|
|
347
386
|
|
|
387
|
+
</Tab>
|
|
388
|
+
</Tabs>
|
|
389
|
+
|
|
348
390
|
### Component phía Server đồng bộ
|
|
349
391
|
|
|
350
|
-
|
|
392
|
+
<Tabs defaultTab="intlayer" group="techno">
|
|
393
|
+
<Tab label="next-i18next" value="i18next">
|
|
351
394
|
|
|
352
395
|
```tsx fileName="src/components/ServerCounter.tsx"
|
|
353
396
|
type ServerCounterProps = {
|
|
@@ -366,7 +409,8 @@ export const ServerCounter = ({ t, locale, count }: ServerCounterProps) => (
|
|
|
366
409
|
|
|
367
410
|
Trang cha phải gọi `i18n.getFixedT(locale, "about")` rồi truyền `t` và `locale` xuống dưới dạng props.
|
|
368
411
|
|
|
369
|
-
|
|
412
|
+
</Tab>
|
|
413
|
+
<Tab label="Intlayer" value="intlayer">
|
|
370
414
|
|
|
371
415
|
```tsx fileName="src/components/ServerCounter.tsx"
|
|
372
416
|
import { useIntlayer } from "next-intlayer/server";
|
|
@@ -385,6 +429,9 @@ export const ServerCounter = ({ count }: { count: number }) => {
|
|
|
385
429
|
};
|
|
386
430
|
```
|
|
387
431
|
|
|
432
|
+
</Tab>
|
|
433
|
+
</Tabs>
|
|
434
|
+
|
|
388
435
|
## Giữ nguyên API của i18next, nhận ngay hiệu năng của Intlayer
|
|
389
436
|
|
|
390
437
|
Bạn không cần phải viết lại toàn bộ component để đạt được kết quả benchmark trên. `@intlayer/i18next`, `@intlayer/react-i18next` và `@intlayer/next-i18next` đóng vai trò là các adapter tương thích trực tiếp: các lệnh gọi `useTranslation`, `t()`, `<Trans>`, xử lý số nhiều và ngữ cảnh vẫn hoạt động bình thường, được vận hành bởi các từ điển do trình biên dịch Intlayer cung cấp.
|
|
@@ -415,18 +462,85 @@ Xem hướng dẫn chuyển đổi: [i18next](https://intlayer.org/vi/doc/migrat
|
|
|
415
462
|
|
|
416
463
|
## Khi nào nên chọn giải pháp nào?
|
|
417
464
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
465
|
+
<AccordionGroup>
|
|
466
|
+
<Accordion header="Chọn i18next">
|
|
467
|
+
|
|
468
|
+
Nếu bạn phụ thuộc chặt chẽ vào hệ sinh thái plugin (bộ nhận diện đặc thù, backend chuyên biệt, ICU, Locize), cần bản địa hóa ở cả ngoài React (Node services, vanilla JS, các framework khác), đội ngũ của bạn đã rất thành thạo, hoặc nền tảng dịch thuật bắt buộc định dạng `locales/{lng}/{ns}.json`. Hãy dành thời gian để quản lý namespace và bản đồ route nếu hiệu năng là ưu tiên hàng đầu.
|
|
469
|
+
|
|
470
|
+
</Accordion>
|
|
471
|
+
<Accordion header="Chọn Intlayer">
|
|
472
|
+
|
|
473
|
+
Bạn mong muốn **nội dung theo phạm vi component**, **TypeScript nghiêm ngặt**, **phát hiện thiếu khóa trong thời gian build**, **tree-shaking và lazy loading không tốn công sức**, chuyển đổi ngôn ngữ tức thì, server component đồng bộ và các công cụ biên tập tích hợp sẵn ([Visual Editor](https://intlayer.org/vi/doc/concept/editor), [CMS](https://intlayer.org/vi/doc/concept/cms), [dịch thuật AI](https://intlayer.org/vi/doc/concept/auto-fill), [MCP server](https://intlayer.org/vi/doc/mcp-server)). Đặc biệt phù hợp cho các codebase dạng module quy mô lớn và design system.
|
|
474
|
+
|
|
475
|
+
</Accordion>
|
|
476
|
+
<Accordion header="Chọn adapter @intlayer/*-i18next">
|
|
477
|
+
|
|
478
|
+
Bạn đã sử dụng i18next và muốn tối ưu dung lượng bundle cùng độ phản hồi mà không cần viết lại component. Các tệp `locales/{lng}/{ns}.json` hiện tại vẫn là nguồn chân lý duy nhất. Được đo lường song song trong [i18next vs @intlayer/i18next](https://intlayer.org/vi/blog/i18next-vs-intlayer-i18next).
|
|
479
|
+
|
|
480
|
+
</Accordion>
|
|
481
|
+
</AccordionGroup>
|
|
482
|
+
|
|
483
|
+
## FAQ (Câu hỏi thường gặp)
|
|
484
|
+
|
|
485
|
+
<FAQ>
|
|
486
|
+
|
|
487
|
+
<Question title="Tại sao i18next lại nặng hơn nhiều so với các thư viện khác?">
|
|
488
|
+
|
|
489
|
+
Nó được thiết kế như một runtime độc lập với framework: một global instance, một pipeline plugin, một kho lưu trữ tài nguyên, một bộ phân giải khóa. Sự linh hoạt đó được biên dịch vào từng bundle. Một component rỗng chỉ import thư viện đã tốn **19.7 KB gzip** với `next-i18next` so với **5.5 KB** của `next-intlayer`, và chi phí đó phải trả trên mọi trang bất kể nội dung của bạn nặng bao nhiêu.
|
|
490
|
+
|
|
491
|
+
</Question>
|
|
492
|
+
|
|
493
|
+
<Question title="Lazy loading với backend có giải quyết được vấn đề không?">
|
|
494
|
+
|
|
495
|
+
Nó giảm dung lượng byte, nhưng không giải quyết được độ trễ. Chuyển sang `i18next-resources-to-backend` tiết kiệm ~49 KB mỗi trang nhưng lại thêm một round-trip mạng khi chuyển đổi ngôn ngữ: **123 ms** trong cấu hình `dynamic` và **185 ms** trong `scoped-static`, so với **3-4 ms** của Intlayer. Thời gian hydration cũng tăng lên 27.7 ms vì instance phải phân giải backend trước khi React có thể hydrate.
|
|
496
|
+
|
|
497
|
+
</Question>
|
|
498
|
+
|
|
499
|
+
<Question title="Tôi có thể đạt 0% rò rỉ nội dung với i18next không?">
|
|
500
|
+
|
|
501
|
+
Có, với `scoped-dynamic`: một namespace cho mỗi route, một backend tài nguyên và một bảng ánh xạ trang - namespace bạn tự quản lý thủ công. Kích thước trang đạt 163.4 KB trên Next.js, vẫn cao hơn **+22 KB** so với 141.3 KB của Intlayer vốn không cần bất kỳ cấu hình nào. Xem [tối ưu hóa bundle](https://intlayer.org/vi/doc/concept/bundle-optimization).
|
|
502
|
+
|
|
503
|
+
</Question>
|
|
504
|
+
|
|
505
|
+
<Question title="Tôi có phải viết lại các component để di chuyển không?">
|
|
506
|
+
|
|
507
|
+
Không. `@intlayer/i18next`, `@intlayer/react-i18next` và `@intlayer/next-i18next` giữ nguyên `useTranslation`, `t()`, `<Trans>`, `{{interpolation}}`, các dạng số nhiều `_one` / `_other`, hậu tố ngữ cảnh và `returnObjects`. Chỉ một dòng plugin trong `next.config.ts` hoặc `vite.config.ts`. Chi tiết từng bước trong [hướng dẫn di chuyển next-i18next](https://intlayer.org/vi/doc/migration/next-i18next).
|
|
508
|
+
|
|
509
|
+
</Question>
|
|
510
|
+
|
|
511
|
+
<Question title="Điều gì xảy ra với các plugin i18next của tôi?">
|
|
512
|
+
|
|
513
|
+
Các backend và plugin phát hiện ngôn ngữ vẫn được chấp nhận nhưng ở trạng thái bất hoạt: không còn gì để tải hoặc phát hiện trong thời gian chạy. Việc phát hiện ngôn ngữ trở thành cấu hình định tuyến của Intlayer (tiền tố URL, cookie, header). Nếu ứng dụng của bạn lấy bản dịch từ CMS tại thời điểm yêu cầu, hãy sử dụng [Intlayer CMS](https://intlayer.org/vi/doc/concept/cms) hoặc lệnh `intlayer pull` / `push` thay thế.
|
|
514
|
+
|
|
515
|
+
</Question>
|
|
516
|
+
|
|
517
|
+
</FAQ>
|
|
421
518
|
|
|
422
519
|
## Các bài so sánh liên quan
|
|
423
520
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
- [
|
|
521
|
+
Cùng benchmark, các thư viện khác:
|
|
522
|
+
|
|
523
|
+
- [next-intl vs Intlayer](https://intlayer.org/vi/blog/next-intl-vs-intlayer)
|
|
524
|
+
- [Lingui vs Intlayer](https://intlayer.org/vi/blog/lingui-vs-intlayer)
|
|
525
|
+
- [vue-i18n vs Intlayer benchmark](https://intlayer.org/vi/blog/vue-i18n-vs-intlayer-benchmark)
|
|
427
526
|
- [next-i18next vs next-intl vs Intlayer](https://intlayer.org/vi/blog/next-i18next-vs-next-intl-vs-intlayer)
|
|
428
527
|
- [react-i18next vs react-intl vs Intlayer](https://intlayer.org/vi/blog/react-i18next-vs-react-intl-vs-intlayer)
|
|
528
|
+
|
|
529
|
+
Tìm hiểu sâu hơn về i18next:
|
|
530
|
+
|
|
531
|
+
- [i18next vs @intlayer/i18next](https://intlayer.org/vi/blog/i18next-vs-intlayer-i18next), đo lường adapter trên cùng một ứng dụng
|
|
429
532
|
- [i18next có bị lỗi thời không?](https://intlayer.org/vi/blog/is-i18next-outdated)
|
|
533
|
+
- [Sử dụng Intlayer với i18next](https://intlayer.org/vi/blog/intlayer-with-i18next) và [với react-i18next](https://intlayer.org/vi/blog/intlayer-with-react-i18next)
|
|
534
|
+
- [Cách quốc tế hóa ứng dụng Next.js với next-i18next](https://intlayer.org/vi/blog/nextjs-internationalization-using-next-i18next)
|
|
535
|
+
|
|
536
|
+
Tài liệu tham khảo:
|
|
537
|
+
|
|
538
|
+
- [Báo cáo benchmark Next.js](https://intlayer.org/vi/doc/benchmark/nextjs) và [báo cáo benchmark TanStack Start](https://intlayer.org/vi/doc/benchmark/tanstack)
|
|
539
|
+
- Adapter tương thích: [i18next](https://intlayer.org/vi/doc/compatibility/i18next), [react-i18next](https://intlayer.org/vi/doc/compatibility/react-i18next), [next-i18next](https://intlayer.org/vi/doc/compatibility/next-i18next)
|
|
540
|
+
- Hướng dẫn di chuyển: [i18next](https://intlayer.org/vi/doc/migration/i18next), [react-i18next](https://intlayer.org/vi/doc/migration/react-i18next), [next-i18next](https://intlayer.org/vi/doc/migration/next-i18next)
|
|
541
|
+
- [Tối ưu hóa bundle](https://intlayer.org/vi/doc/concept/bundle-optimization) và [trình biên dịch Intlayer](https://intlayer.org/vi/doc/compiler)
|
|
542
|
+
- [i18n theo component vs i18n tập trung](https://intlayer.org/vi/blog/per-component-vs-centralized-i18n)
|
|
543
|
+
- [i18n dựa trên compiler vs khai báo](https://intlayer.org/vi/blog/compiler-vs-declarative-i18n)
|
|
430
544
|
|
|
431
545
|
## Lượt gắn sao trên GitHub
|
|
432
546
|
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-23
|
|
3
|
+
updatedAt: 2026-09-23
|
|
4
|
+
title: Intlayer có nhẹ hơn Paraglide không?
|
|
5
|
+
description: Paraglide trông gần như miễn phí trong các bài kiểm chuẩn i18n vì mã nguồn của nó được tạo trực tiếp vào kho lưu trữ của bạn. Cùng tìm hiểu xem dung lượng đó thực sự đi đâu, tại sao việc đọc locale trên từng nút lại gây tốn tài nguyên và cách tải động của Intlayer chỉ gửi một ngôn ngữ thay vì tất cả.
|
|
6
|
+
keywords:
|
|
7
|
+
- Paraglide
|
|
8
|
+
- Intlayer
|
|
9
|
+
- Quốc tế hóa
|
|
10
|
+
- i18n
|
|
11
|
+
- Bundle size
|
|
12
|
+
- Tree shaking
|
|
13
|
+
- Benchmark
|
|
14
|
+
- Blog
|
|
15
|
+
slugs:
|
|
16
|
+
- blog
|
|
17
|
+
- is-intlayer-lighter-than-paraglide
|
|
18
|
+
author: aymericzip
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Intlayer có nhẹ hơn Paraglide không?
|
|
22
|
+
|
|
23
|
+
Có.
|
|
24
|
+
|
|
25
|
+
`Paraglide` nổi tiếng là giải pháp i18n nhẹ nhất hiện nay, và thoạt nhìn bảng [benchmark](https://intlayer.org/vi/doc/benchmark/tanstack) cũng đồng tình với điều đó: kích thước thư viện của nó gần như bằng không. Tuy nhiên, kích thước thư viện bằng không không đồng nghĩa với việc không có byte nào được gửi đến trình duyệt. Nó chỉ có nghĩa là các byte đó nằm ở một nơi mà chỉ số này không quét tới.
|
|
26
|
+
|
|
27
|
+
<TOC/>
|
|
28
|
+
|
|
29
|
+
## Những điểm cốt lõi
|
|
30
|
+
|
|
31
|
+
**Kích thước thư viện bị ẩn đi chứ không hề biến mất:**
|
|
32
|
+
|
|
33
|
+
Paraglide tạo runtime và các hàm thông điệp ngay trong codebase của bạn. Đoạn mã đó vẫn được gửi tới trình duyệt, nhưng được tính là mã của _chính bạn_, chứ không phải của thư viện.
|
|
34
|
+
|
|
35
|
+
**Không có provider không phải là một món hời miễn phí:**
|
|
36
|
+
|
|
37
|
+
Mỗi lần gọi `m.my_key()` đều tự giải quyết locale độc lập, đọc cookie hoặc bộ nhớ lưu trữ cho từng node được render, thay vì đọc một lần duy nhất từ context.
|
|
38
|
+
|
|
39
|
+
**Không có cơ chế tải động (Dynamic Loading):**
|
|
40
|
+
|
|
41
|
+
Paraglide import tất cả ngôn ngữ của một thông điệp vào client bundle. Ngược lại, Intlayer với `importMode: 'dynamic'` hoặc `'fetch'` chỉ tải duy nhất ngôn ngữ đang được hiển thị.
|
|
42
|
+
|
|
43
|
+
**Tree shaking không được đảm bảo:**
|
|
44
|
+
|
|
45
|
+
Trong một số bài kiểm tra hiệu năng của chúng tôi, tính năng tree shaking được quảng cáo của Paraglide đã không hoạt động. Hãy kiểm tra bundle thực tế của bạn.
|
|
46
|
+
|
|
47
|
+
## Dung lượng của Paraglide thực sự nằm ở đâu?
|
|
48
|
+
|
|
49
|
+
Trong các báo cáo kiểm chuẩn, chỉ số "kích thước thư viện" đo lường provider và các hook của mỗi thư viện i18n bên trong một component rỗng, trước khi có bất kỳ nội dung nào được thêm vào.
|
|
50
|
+
|
|
51
|
+
| Thư viện (TanStack Start) | Dung lượng lib (gz) | Dung lượng lib (min) |
|
|
52
|
+
| ----------------------------- | ------------------- | -------------------- |
|
|
53
|
+
| `@inlang/paraglide-js@2.15.1` | 1.8 KB | 4.5 KB |
|
|
54
|
+
| `react-intlayer@9.5.1` | 5.0 KB | 15.2 KB |
|
|
55
|
+
|
|
56
|
+
Nếu chỉ nhìn riêng số liệu này, Paraglide dường như chiến thắng. Nhưng Paraglide là một trình biên dịch: nó đọc các tệp `messages/*.json` và tạo một thư mục `paraglide/` trong kho mã của bạn, chứa tệp `runtime.js` (phát hiện ngôn ngữ, chiến lược cookie và storage, bản địa hóa URL) cùng một hàm JavaScript cho mỗi thông điệp.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
src/paraglide/
|
|
60
|
+
├── runtime.js # phát hiện locale, chiến lược, helper URL
|
|
61
|
+
├── server.js
|
|
62
|
+
├── messages.js # re-export tất cả thông điệp
|
|
63
|
+
└── messages/
|
|
64
|
+
├── _index.js
|
|
65
|
+
├── en.js
|
|
66
|
+
└── fr.js
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Vì mã này nằm trong thư mục `src/` và bạn import nó qua đường dẫn tương đối, bundler sẽ tính nó vào ứng dụng của bạn chứ không phải một gói trong `node_modules`. Cột kích thước thư viện hiển thị gần như bằng không, trong khi logic tương tự vẫn được chuyển vào bundle trang của bạn.
|
|
70
|
+
|
|
71
|
+
Việc tự động sinh mã không phải là ý tưởng tồi: runtime được sinh ra chỉ bao gồm logic mà cấu hình của bạn yêu cầu (chiến lược tiền tố, cookie so với local storage, v.v.). Intlayer đạt được kết quả tương tự theo cách khác, bằng cách chèn các biến môi trường vào thời điểm build để bundler tự động loại bỏ các nhánh mã không được sử dụng. Cả hai giải pháp đều nhẹ hơn từ 3 đến 10 lần so với `i18next` hoặc `next-intl`.
|
|
72
|
+
|
|
73
|
+
Vì vậy, so sánh công bằng không nằm ở kích thước thư viện. Đó là **lượng JavaScript thực sự được gửi trên mỗi trang**.
|
|
74
|
+
|
|
75
|
+
## Dung lượng trang thực tế qua đo đạc
|
|
76
|
+
|
|
77
|
+
Ứng dụng TanStack Start, 10 trang, đo trên các route `en` và `fr`, nén bằng gzip:
|
|
78
|
+
|
|
79
|
+
| Cấu hình | JS trang TB (gz) | So với gốc | Rò rỉ locale | Rò rỉ trang khác |
|
|
80
|
+
| ---------------------------------- | ---------------- | ----------- | ------------ | ---------------- |
|
|
81
|
+
| Gốc (không i18n) | 111.0 KB | - | 0.0% | 0.0% |
|
|
82
|
+
| `paraglide` (mọi chiến lược) | 125.1 KB | +14.1 KB | 49.7% | 0.0% |
|
|
83
|
+
| `intlayer` (`importMode: static`) | 125.8 KB | +14.8 KB | 50.0% | 0.0% |
|
|
84
|
+
| `intlayer` (`importMode: dynamic`) | **118.6 KB** | **+7.6 KB** | **0.0%** | **0.0%** |
|
|
85
|
+
|
|
86
|
+
Next.js 16 App Router, cùng ứng dụng:
|
|
87
|
+
|
|
88
|
+
| Cấu hình | JS trang TB (gz) | So với gốc |
|
|
89
|
+
| ---------------- | ---------------- | ----------- |
|
|
90
|
+
| Gốc (không i18n) | 141.0 KB | - |
|
|
91
|
+
| `paraglide-next` | 155.3 KB | +14.3 KB |
|
|
92
|
+
| `next-intlayer` | **141.3 KB** | **+0.3 KB** |
|
|
93
|
+
|
|
94
|
+
<I18nBenchmark framework="tanstack" vertical/>
|
|
95
|
+
|
|
96
|
+
> Dữ liệu đầy đủ có trong [báo cáo benchmark TanStack Start](https://intlayer.org/vi/doc/benchmark/tanstack) và [báo cáo benchmark Next.js](https://intlayer.org/vi/doc/benchmark/nextjs). Từng bundle có thể được kiểm tra tại [kho lưu trữ benchmark](https://github.com/intlayer-org/benchmark-i18n).
|
|
97
|
+
|
|
98
|
+
Hai điểm nổi bật rõ ràng:
|
|
99
|
+
|
|
100
|
+
- Ở chế độ `static`, Intlayer gửi lượng nội dung gần như tương đương Paraglide (125.8 KB so với 125.1 KB). Điều này hoàn toàn dễ hiểu: cả hai đều bao gồm mọi ngôn ngữ của các thông điệp mà trang sử dụng.
|
|
101
|
+
- Paraglide giữ nguyên kích thước 125.1 KB dù áp dụng bất kỳ chiến lược nào, bởi vì nó không hỗ trợ chế độ tải động. Mỗi hàng trong bảng trên tương đương với chế độ tĩnh.
|
|
102
|
+
|
|
103
|
+
## Không có Provider: Ý tưởng tưởng chừng tốt nhưng không phải
|
|
104
|
+
|
|
105
|
+
Paraglide không cần provider. Bạn import một thông điệp và gọi nó:
|
|
106
|
+
|
|
107
|
+
```tsx fileName="Hero.tsx"
|
|
108
|
+
import { m } from "../paraglide/messages.js";
|
|
109
|
+
|
|
110
|
+
export const Hero = () => (
|
|
111
|
+
<section>
|
|
112
|
+
<h1>{m.hero_title()}</h1>
|
|
113
|
+
<p>{m.hero_description()}</p>
|
|
114
|
+
<button>{m.hero_cta()}</button>
|
|
115
|
+
</section>
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Không context, không wrapper, không hook. Nhìn qua có vẻ đơn giản hơn. Nhưng thông tin ngôn ngữ vẫn phải được lấy từ một nơi nào đó. Mỗi hàm thông điệp được tạo ra trông gần giống thế này (dạng rút gọn):
|
|
120
|
+
|
|
121
|
+
```js fileName="paraglide/messages/_index.js"
|
|
122
|
+
export const hero_title = (inputs = {}, options = {}) => {
|
|
123
|
+
const locale = options.locale ?? getLocale(); // được xử lý mỗi lần hàm được gọi
|
|
124
|
+
|
|
125
|
+
if (locale === "en") return en.hero_title(inputs);
|
|
126
|
+
if (locale === "fr") return fr.hero_title(inputs);
|
|
127
|
+
// ...mỗi ngôn ngữ một nhánh
|
|
128
|
+
};
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Và hàm `getLocale()` duyệt qua các chiến lược đã cấu hình (cookie, local storage, URL, locale mặc định) để tìm ngôn ngữ hiện tại. Do đó, mỗi node văn bản bạn render (`<>{m.my_key()}</>`) đều tự thực hiện việc giải quyết locale riêng, bao gồm cả thao tác đọc `document.cookie` trong trình duyệt. Một trang có 200 chuỗi dịch sẽ thực hiện giải quyết locale 200 lần trong mỗi lượt render, và lặp lại liên tục sau mỗi lần re-render.
|
|
132
|
+
|
|
133
|
+
Một thư viện dùng provider chỉ đọc locale **một lần duy nhất**, lưu vào context (hoặc signal, hoặc store), và mỗi node chỉ việc đọc giá trị đã có sẵn trong bộ nhớ. Provider chỉ tốn vài trăm byte. Bỏ qua provider sẽ làm hao tốn chu kỳ CPU trong mỗi lần render, và điều này thể hiện rõ ràng trong bài benchmark: thời gian tải trang và tốc độ chuyển đổi ngôn ngữ của Paraglide luôn xếp sau Intlayer trên TanStack Start (thời gian tải trang 22.1 ms so với 14.6 ms, độ phản hồi E2E 4.3 ms so với 3.2 ms).
|
|
134
|
+
|
|
135
|
+
## Trải nghiệm lập trình viên (DX)
|
|
136
|
+
|
|
137
|
+
Nguồn dữ liệu gốc của Paraglide là JSON, nhưng bạn không bao giờ import trực tiếp tệp JSON. Bạn import tệp `.js` được tạo ra:
|
|
138
|
+
|
|
139
|
+
<Tabs defaultTab="intlayer" group="techno">
|
|
140
|
+
<Tab label="Paraglide" value="paraglide">
|
|
141
|
+
|
|
142
|
+
```json fileName="messages/en.json"
|
|
143
|
+
{
|
|
144
|
+
"hero_title": "Ship your app in every language"
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```json fileName="messages/vi.json"
|
|
149
|
+
{
|
|
150
|
+
"hero_title": "Phát hành ứng dụng của bạn bằng mọi ngôn ngữ"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```tsx fileName="Hero.tsx"
|
|
155
|
+
// Chỉ tồn tại sau khi trình biên dịch tạo lại từ JSON
|
|
156
|
+
import { m } from "../paraglide/messages.js";
|
|
157
|
+
|
|
158
|
+
export const Hero = () => <h1>{m.hero_title()}</h1>;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
</Tab>
|
|
162
|
+
<Tab label="Intlayer" value="intlayer">
|
|
163
|
+
|
|
164
|
+
```ts fileName="Hero.content.ts"
|
|
165
|
+
import { t, type Dictionary } from "intlayer";
|
|
166
|
+
|
|
167
|
+
export default {
|
|
168
|
+
key: "hero",
|
|
169
|
+
content: {
|
|
170
|
+
title: t({
|
|
171
|
+
vi: "Phát hành ứng dụng của bạn bằng mọi ngôn ngữ",
|
|
172
|
+
en: "Ship your app in every language",
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
} satisfies Dictionary;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```tsx fileName="Hero.tsx"
|
|
179
|
+
import { useIntlayer } from "react-intlayer";
|
|
180
|
+
|
|
181
|
+
export const Hero = () => {
|
|
182
|
+
const { title } = useIntlayer("hero");
|
|
183
|
+
|
|
184
|
+
return <h1>{title}</h1>;
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
</Tab>
|
|
189
|
+
</Tabs>
|
|
190
|
+
|
|
191
|
+
Quy trình phát triển này mang lại những bất tiện:
|
|
192
|
+
|
|
193
|
+
- Mỗi thay đổi đối với tệp JSON đều yêu cầu tạo lại mã trước khi import có thể nhận diện hoặc type được cập nhật.
|
|
194
|
+
- Thư mục sinh ra `paraglide/` hoặc phải được commit lên git (gây ra xung đột merge trên các tệp sinh tự động ở mọi PR chỉnh sửa nội dung), hoặc bị bỏ qua (đòi hỏi bước biên dịch trước mỗi lần kiểm tra type, test và chạy CI).
|
|
195
|
+
- Mọi chuỗi văn bản đều biến thành lời gọi hàm. Các hằng số trở thành `m.key()` ở khắp mọi nơi, ngay cả ở những vị trí chỉ cần một giá trị tĩnh đơn thuần.
|
|
196
|
+
|
|
197
|
+
## Tree Shaking: Hãy kiểm tra bundle của bạn
|
|
198
|
+
|
|
199
|
+
Lời hứa hẹn lớn nhất của Paraglide là các thông điệp không dùng đến sẽ được loại bỏ thông qua tree shaking, vì mỗi thông điệp là một export độc lập. Trong thử nghiệm với Svelte + Vite, tính năng này hoạt động đúng như quảng cáo.
|
|
200
|
+
|
|
201
|
+
Nhưng trong các môi trường khác thì không như vậy. Trong lần thử nghiệm trên [Next.js](https://intlayer.org/vi/doc/benchmark/nextjs), các trang của Paraglide nặng hơn ứng dụng gốc tới 14 KB, trong khi `next-intlayer` chỉ thêm 0.3 KB. Các bài đo trước đó trên TanStack Start cũng cho thấy thông điệp từ những trang khác bị kéo vào bundle của route hiện tại.
|
|
202
|
+
|
|
203
|
+
Tree shaking phụ thuộc chặt chẽ vào bundler (Turbopack, Rolldown, Rollup), cách thức import thông điệp (`import { m }` so với `import * as m`) và khả năng phân tích tác dụng phụ (side-effects). Nếu bạn chọn Paraglide vì kích thước nhỏ gọn, hãy mở công cụ phân tích bundle và kiểm tra xem điều đó có thực sự đúng với ứng dụng của bạn hay không.
|
|
204
|
+
|
|
205
|
+
## Không có cơ chế tải động
|
|
206
|
+
|
|
207
|
+
Đây là giới hạn về mặt kiến trúc. Paraglide không có cách nào để tải từng ngôn ngữ một: mỗi hàm thông điệp đều import tĩnh phần triển khai của từng ngôn ngữ, do đó toàn bộ ngôn ngữ đều kết thúc trong client bundle của bạn.
|
|
208
|
+
|
|
209
|
+
Với 2 ngôn ngữ, bạn đã lãng phí một nửa dữ liệu dịch thuật, khớp với mức ~50% rò rỉ locale được đo lường ở trên. Với 10 ngôn ngữ, con số lãng phí lên tới 90%. Với 30 ngôn ngữ, con số này là 97%.
|
|
210
|
+
|
|
211
|
+
Chuyển sang tải động cũng không thể giải quyết triệt để: với mỗi thông điệp là một hàm riêng biệt, việc lazy load từng hàm sẽ tạo ra hàng nghìn request qua mạng.
|
|
212
|
+
|
|
213
|
+
Intlayer cho phép bạn linh hoạt lựa chọn theo phạm vi toàn cục hoặc trên từng từ điển:
|
|
214
|
+
|
|
215
|
+
```ts fileName="intlayer.config.ts"
|
|
216
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
217
|
+
|
|
218
|
+
const config: IntlayerConfig = {
|
|
219
|
+
internationalization: {
|
|
220
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
221
|
+
defaultLocale: Locales.ENGLISH,
|
|
222
|
+
},
|
|
223
|
+
dictionary: {
|
|
224
|
+
importMode: "dynamic", // 'static' | 'dynamic' | 'fetch'
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export default config;
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| `importMode` | Dữ liệu được gửi tới client | So sánh với Paraglide |
|
|
232
|
+
| ------------ | ------------------------------------------------------------ | -------------------------------- |
|
|
233
|
+
| `static` | Tất cả ngôn ngữ của các từ điển trang đang sử dụng | Về lý thuyết cùng dung lượng |
|
|
234
|
+
| `dynamic` | Chỉ ngôn ngữ hiện tại, tải theo cơ chế lazy cho từng từ điển | **Nhẹ hơn N lần** với N ngôn ngữ |
|
|
235
|
+
| `fetch` | Chỉ ngôn ngữ hiện tại, lấy trực tiếp qua Live Sync API | **Nhẹ hơn N lần** với N ngôn ngữ |
|
|
236
|
+
|
|
237
|
+
Nhờ [chuyển đổi trong quá trình build](https://intlayer.org/vi/doc/concept/bundle-optimization) và chế độ `importMode: 'static'`, Intlayer về mặt lý thuyết tải lượng nội dung hoàn toàn giống với Paraglide. Với `'dynamic'` hoặc `'fetch'`, nó chỉ tải những gì ngôn ngữ hiện tại cần: đối với ứng dụng có N ngôn ngữ, dung lượng dịch thuật nhẹ hơn N lần so với Paraglide.
|
|
238
|
+
|
|
239
|
+
## Những trường hợp Paraglide vẫn phù hợp
|
|
240
|
+
|
|
241
|
+
<AccordionGroup>
|
|
242
|
+
<Accordion header="Svelte + Vite với số lượng ít ngôn ngữ">
|
|
243
|
+
|
|
244
|
+
Nếu hệ thống của bạn dùng Svelte với Vite và bạn chỉ hỗ trợ 2 đến 3 ngôn ngữ, tree shaking hoạt động hiệu quả như mong đợi và chi phí tăng thêm cho các ngôn ngữ khác vẫn ở mức nhỏ.
|
|
245
|
+
|
|
246
|
+
</Accordion>
|
|
247
|
+
<Accordion header="Quy trình làm việc có sẵn với inlang">
|
|
248
|
+
|
|
249
|
+
Nếu đội ngũ của bạn đã sử dụng hệ sinh thái inlang (Fink, Sherlock, plugin định dạng thông điệp), Paraglide sẽ tích hợp một cách tự nhiên.
|
|
250
|
+
|
|
251
|
+
</Accordion>
|
|
252
|
+
</AccordionGroup>
|
|
253
|
+
|
|
254
|
+
## Trải nghiệm trực tiếp trên ứng dụng của bạn
|
|
255
|
+
|
|
256
|
+
Kiểm tra dung lượng và hiện tượng rò rỉ ngôn ngữ trên ứng dụng đang chạy thực tế với công cụ miễn phí [i18n SEO Scanner](https://intlayer.org/i18n-seo-scanner):
|
|
257
|
+
|
|
258
|
+
<ClickToOpenIframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
259
|
+
|
|
260
|
+
Cài đặt Intlayer:
|
|
261
|
+
|
|
262
|
+
```bash packageManager="npm"
|
|
263
|
+
npx intlayer init --interactive
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
```bash packageManager="pnpm"
|
|
267
|
+
pnpm dlx intlayer init --interactive
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```bash packageManager="yarn"
|
|
271
|
+
yarn dlx intlayer init --interactive
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```bash packageManager="bun"
|
|
275
|
+
bunx intlayer init --interactive
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Đọc thêm
|
|
279
|
+
|
|
280
|
+
- [Benchmark i18n TanStack Start](https://intlayer.org/vi/doc/benchmark/tanstack)
|
|
281
|
+
- [Benchmark i18n Next.js](https://intlayer.org/vi/doc/benchmark/nextjs)
|
|
282
|
+
- [Tối ưu hóa Bundle và `importMode`](https://intlayer.org/vi/doc/concept/bundle-optimization)
|
|
283
|
+
- [Cách chọn thư viện i18n phù hợp cho React](https://intlayer.org/vi/blog/how-to-pick-react-i18n-library)
|
|
284
|
+
- [Lợi ích của quốc tế hóa dựa trên trình biên dịch](https://intlayer.org/vi/blog/compiler-vs-declarative-i18n)
|