@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 против Intlayer: бенчмарк и сравнение 2026"
|
|
5
5
|
description: "react-i18next и next-i18next в сравнении с Intlayer на Next.js и TanStack Start. Размер bundle, утечки контента, скорость переключения локали и опыт разработчика."
|
|
6
6
|
keywords:
|
|
@@ -25,6 +25,8 @@ author: aymericzip
|
|
|
25
25
|
|
|
26
26
|
# i18next против Intlayer | Бенчмарк интернационализации (i18n) для React и Next.js
|
|
27
27
|
|
|
28
|
+

|
|
29
|
+
|
|
28
30
|
`i18next` - самый распространенный i18n-фреймворк в экосистеме JavaScript. Через `react-i18next` и `next-i18next` он используется в огромном количестве приложений на React и Next.js. Intlayer представляет собой альтернативу на основе компилятора с изолированной областью видимости для каждого компонента.
|
|
29
31
|
|
|
30
32
|
В этой статье они сравниваются на основе реальных замеров, а не списков возможностей. Данные взяты из [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) - открытого набора тестов, собирающего одно и то же приложение на каждой библиотеке и фиксирующего то, что браузер фактически загружает по сети.
|
|
@@ -99,6 +101,10 @@ author: aymericzip
|
|
|
99
101
|
|
|
100
102
|
### Результаты на Next.js (`next-i18next`)
|
|
101
103
|
|
|
104
|
+
Выберите интересующие вас метрики и библиотеки:
|
|
105
|
+
|
|
106
|
+
<I18nBenchmark framework="nextjs" vertical/>
|
|
107
|
+
|
|
102
108
|
| Библиотека | Стратегия | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E-реактивность | Гидратация |
|
|
103
109
|
| --------------------------------- | -------------- | ------------: | ---------------: | ----------: | --------: | -----------------: | ---------------: | ---------: |
|
|
104
110
|
| **base** (без i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
|
|
@@ -119,6 +125,15 @@ author: aymericzip
|
|
|
119
125
|
- **Размер компонентов.** Компонент с вызовом `useTranslation()` компилируется в 26-79 KB; тот же компонент с `useIntlayer()` весит 6.9 KB.
|
|
120
126
|
- **Гидратация** возрастает до 27.7 ms в варианте `dynamic`: экземпляр i18next инициализируется и запрашивает бэкенд на стороне клиента до того, как React завершит гидратацию.
|
|
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
|
+
> Полная таблица, каждая библиотека и каждая стратегия, в [отчете о бенчмарке Next.js](https://intlayer.org/ru/doc/benchmark/nextjs).
|
|
136
|
+
|
|
122
137
|
### Результаты на TanStack Start (`react-i18next`)
|
|
123
138
|
|
|
124
139
|
То же приложение на TanStack Start со стандартным `react-i18next`, что исключает специфику Next.js из сравнения.
|
|
@@ -141,8 +156,19 @@ author: aymericzip
|
|
|
141
156
|
- Строка `static` у Intlayer уже дает **0% утечки страниц**, так как в сборку входят только словари, импортированные компонентами этой страницы. Включение `importMode: 'dynamic'` устраняет и утечку языков.
|
|
142
157
|
- **Размер компонентов**: 24-27 KB на компонент в `react-i18next` против 6-8 KB в Intlayer. `useTranslation()` связывает каждый компонент с глобальным экземпляром i18next.
|
|
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
|
+
> Полная таблица в [отчете о бенчмарке TanStack Start](https://intlayer.org/ru/doc/benchmark/tanstack).
|
|
167
|
+
|
|
144
168
|
## Причина различий: глобальный экземпляр против скомпилированных словарей
|
|
145
169
|
|
|
170
|
+

|
|
171
|
+
|
|
146
172
|
`i18next` был создан в 2012 году как runtime: глобальный объект содержит хранилище ресурсов, плагины расширяют его возможности, а `t()` ищет ключи при рендере. Это обеспечивает гибкость (любой фреймворк, бэкенд и формат), но ведет к утяжелению:
|
|
147
173
|
|
|
148
174
|
```bash
|
|
@@ -166,7 +192,13 @@ author: aymericzip
|
|
|
166
192
|
└── page.tsx # должна знать, что нужны ["common", "about"]
|
|
167
193
|
```
|
|
168
194
|
|
|
169
|
-
Экземпляр не может знать заранее, какие ключи понадобятся компоненту, поэтому держит в памяти все загруженные пространства имен. Оптимизация означает, что **вы** делите каталоги, **вы** перечисляете пространства имен для каждой страницы и **вы** вручную обновляете этот список при перемещении компонентов.
|
|
195
|
+
Экземпляр не может знать заранее, какие ключи понадобятся компоненту, поэтому держит в памяти все загруженные пространства имен. Оптимизация означает, что **вы** делите каталоги, **вы** перечисляете пространства имен для каждой страницы и **вы** вручную обновляете этот список при перемещении компонентов.
|
|
196
|
+
|
|
197
|
+
Издержки растут сразу по двум осям, страницам и локалям:
|
|
198
|
+
|
|
199
|
+

|
|
200
|
+
|
|
201
|
+
Как отмечено в [заметках бенчмарка](https://github.com/intlayer-org/benchmark-bloom/blob/main/report/NOTE.md): "поддерживать типобезопасность и точно знать, какое пространство имен подключить к странице - это сущий кошмар".
|
|
170
202
|
|
|
171
203
|
Intlayer отказывается от глобального экземпляра. Контент объявляется рядом с компонентом, а компилятор строит граф зависимостей при сборке:
|
|
172
204
|
|
|
@@ -193,7 +225,8 @@ Intlayer отказывается от глобального экземпляр
|
|
|
193
225
|
|
|
194
226
|
### Настройка
|
|
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
|
Дополнительно требуется клиентский `I18nProvider`, воссоздающий экземпляр с теми же параметрами, `generateStaticParams` и список `namespaces` на каждой странице.
|
|
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
|
### Клиентский компонент
|
|
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
|
> Страница, отображающая этот компонент, обязана загрузить пространство имен `about`, а `t("counter.label")` будет обычной строкой без строгой типизации, если не дополнить интерфейс `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` и `increment` строго типизированы: опечатка в имени вызовет ошибку TypeScript, а отсутствие французского текста остановит сборку.
|
|
347
386
|
|
|
387
|
+
</Tab>
|
|
388
|
+
</Tabs>
|
|
389
|
+
|
|
348
390
|
### Синхронный серверный компонент
|
|
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
|
Страница вызывает `i18n.getFixedT(locale, "about")` и пробрасывает `t` и `locale` вниз через 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
|
## Сохраните API i18next, получите производительность Intlayer
|
|
389
436
|
|
|
390
437
|
Вам не нужно переписывать компоненты, чтобы получить показатели из бенчмарка выше. `@intlayer/i18next`, `@intlayer/react-i18next` и `@intlayer/next-i18next` являются готовыми адаптерами: `useTranslation`, `t()`, `<Trans>`, `{{interpolation}}`, формы множественного числа `_one` / `_other`, суффиксы контекста и `returnObjects` продолжают работать, получая данные из скомпилированных словарей Intlayer.
|
|
@@ -415,18 +462,85 @@ export default defineConfig({
|
|
|
415
462
|
|
|
416
463
|
## Что и когда выбирать?
|
|
417
464
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
465
|
+
<AccordionGroup>
|
|
466
|
+
<Accordion header="Выбрать i18next">
|
|
467
|
+
|
|
468
|
+
Если вам необходима его экосистема плагинов (детекторы, бэкенды, ICU, Locize), вы локализуете решения вне React (сервисы Node, чистый JS, другие фреймворки), у команды уже есть практический опыт или переводческая платформа ожидает формат `locales/{lng}/{ns}.json`. Заложите время на организацию пространств имен, настройку бэкенда и ручную поддержку карты маршрутов, если важна скорость.
|
|
469
|
+
|
|
470
|
+
</Accordion>
|
|
471
|
+
<Accordion header="Выбрать Intlayer">
|
|
472
|
+
|
|
473
|
+
Вам нужен **контент на уровне компонентов**, **строгий TypeScript**, **ошибки отсутствующих ключей во время сборки**, **tree-shaking и lazy loading без усилий**, мгновенное переключение языка, синхронные серверные компоненты и встроенные инструменты для редактирования ([Визуальный редактор](https://intlayer.org/ru/doc/concept/editor), [CMS](https://intlayer.org/ru/doc/concept/cms), [ИИ-перевод](https://intlayer.org/ru/doc/concept/auto-fill), [MCP-сервер](https://intlayer.org/ru/doc/mcp-server)). Особенно актуально для крупных модульных кодовых баз и дизайн-систем.
|
|
474
|
+
|
|
475
|
+
</Accordion>
|
|
476
|
+
<Accordion header="Выбрать адаптеры @intlayer/*-i18next">
|
|
477
|
+
|
|
478
|
+
Вы уже используете i18next и хотите получить преимущества в размере бандла и реактивности без переписывания компонентов. Ваши файлы `locales/{lng}/{ns}.json` остаются источником истины. Измерено бок о бок в [i18next против @intlayer/i18next](https://intlayer.org/ru/blog/i18next-vs-intlayer-i18next).
|
|
479
|
+
|
|
480
|
+
</Accordion>
|
|
481
|
+
</AccordionGroup>
|
|
482
|
+
|
|
483
|
+
## Часто задаваемые вопросы (FAQ)
|
|
484
|
+
|
|
485
|
+
<FAQ>
|
|
486
|
+
|
|
487
|
+
<Question title="Почему i18next намного тяжелее других библиотек?">
|
|
488
|
+
|
|
489
|
+
Он проектировался как агностичный к фреймворкам runtime: глобальный экземпляр, пайплайн плагинов, хранилище ресурсов, резолвер ключей. Эта гибкость компилируется в каждый бандл. Пустой компонент, импортирующий только библиотеку, весит **19.7 KB gzip** с `next-i18next` против **5.5 KB** с `next-intlayer`, и эта цена платится на каждой странице, независимо от объема контента.
|
|
490
|
+
|
|
491
|
+
</Question>
|
|
492
|
+
|
|
493
|
+
<Question title="Помогает ли ленивая загрузка с бэкендом?">
|
|
494
|
+
|
|
495
|
+
Она решает проблему байтов, но не задержки. Переход на `i18next-resources-to-backend` экономит ~49 KB на страницу, но добавляет сетевой запрос при переключении локали: **123 мс** в конфигурации `dynamic` и **185 мс** в `scoped-static` против **3-4 мс** у Intlayer. Гидратация также увеличивается до 27.7 мс, так как инстанс резолвит бэкенд до гидратации React.
|
|
496
|
+
|
|
497
|
+
</Question>
|
|
498
|
+
|
|
499
|
+
<Question title="Можно ли достичь 0% утечек с i18next?">
|
|
500
|
+
|
|
501
|
+
Да, с `scoped-dynamic`: один неймспейс на маршрут, бэкенд ресурсов и карта соответствия страниц неймспейсам, поддерживаемая вручную. Это дает 163.4 KB на страницу в Next.js, все еще на **+22 KB** больше, чем у Intlayer (141.3 KB), которому не требовалась ручная настройка. См. [оптимизацию бандла](https://intlayer.org/ru/doc/concept/bundle-optimization).
|
|
502
|
+
|
|
503
|
+
</Question>
|
|
504
|
+
|
|
505
|
+
<Question title="Нужно ли переписывать компоненты для миграции?">
|
|
506
|
+
|
|
507
|
+
Нет. `@intlayer/i18next`, `@intlayer/react-i18next` и `@intlayer/next-i18next` сохраняют `useTranslation`, `t()`, `<Trans>`, `{{interpolation}}`, формы множественного числа `_one` / `_other`, контекстные суффиксы и `returnObjects`. Всего одна строчка плагина в `next.config.ts` или `vite.config.ts`. Пошагово в [руководстве по миграции с next-i18next](https://intlayer.org/ru/doc/migration/next-i18next).
|
|
508
|
+
|
|
509
|
+
</Question>
|
|
510
|
+
|
|
511
|
+
<Question title="Что происходит с моими плагинами i18next?">
|
|
512
|
+
|
|
513
|
+
Бэкенды и детекторы языка принимаются, но остаются неактивными: в рантайме больше нечего загружать или определять. Определение языка становится конфигурацией маршрутизации Intlayer (префикс URL, cookie, заголовок). Если ваше приложение получает переводы из CMS во время запроса, используйте [Intlayer CMS](https://intlayer.org/ru/doc/concept/cms) или `intlayer pull` / `push`.
|
|
514
|
+
|
|
515
|
+
</Question>
|
|
516
|
+
|
|
517
|
+
</FAQ>
|
|
421
518
|
|
|
422
519
|
## Похожие сравнения
|
|
423
520
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
- [
|
|
427
|
-
- [
|
|
428
|
-
- [
|
|
521
|
+
Тот же бенчмарк, другие библиотеки:
|
|
522
|
+
|
|
523
|
+
- [next-intl vs Intlayer](https://intlayer.org/ru/blog/next-intl-vs-intlayer)
|
|
524
|
+
- [Lingui vs Intlayer](https://intlayer.org/ru/blog/lingui-vs-intlayer)
|
|
525
|
+
- [vue-i18n vs Intlayer benchmark](https://intlayer.org/ru/blog/vue-i18n-vs-intlayer-benchmark)
|
|
526
|
+
- [next-i18next vs next-intl vs Intlayer](https://intlayer.org/ru/blog/next-i18next-vs-next-intl-vs-intlayer)
|
|
527
|
+
- [react-i18next vs react-intl vs Intlayer](https://intlayer.org/ru/blog/react-i18next-vs-react-intl-vs-intlayer)
|
|
528
|
+
|
|
529
|
+
Подробнее об i18next:
|
|
530
|
+
|
|
531
|
+
- [i18next против @intlayer/i18next](https://intlayer.org/ru/blog/i18next-vs-intlayer-i18next), адаптеры измерены на одном приложении
|
|
429
532
|
- [Устарел ли i18next?](https://intlayer.org/ru/blog/is-i18next-outdated)
|
|
533
|
+
- [Использование Intlayer с i18next](https://intlayer.org/ru/blog/intlayer-with-i18next) и [с react-i18next](https://intlayer.org/ru/blog/intlayer-with-react-i18next)
|
|
534
|
+
- [Как интернационализировать приложение Next.js с помощью next-i18next](https://intlayer.org/ru/blog/nextjs-internationalization-using-next-i18next)
|
|
535
|
+
|
|
536
|
+
Справочная документация:
|
|
537
|
+
|
|
538
|
+
- [Отчет о бенчмарке Next.js](https://intlayer.org/ru/doc/benchmark/nextjs) и [отчет о бенчмарке TanStack Start](https://intlayer.org/ru/doc/benchmark/tanstack)
|
|
539
|
+
- Адаптеры совместимости: [i18next](https://intlayer.org/ru/doc/compatibility/i18next), [react-i18next](https://intlayer.org/ru/doc/compatibility/react-i18next), [next-i18next](https://intlayer.org/ru/doc/compatibility/next-i18next)
|
|
540
|
+
- Руководства по миграции: [i18next](https://intlayer.org/ru/doc/migration/i18next), [react-i18next](https://intlayer.org/ru/doc/migration/react-i18next), [next-i18next](https://intlayer.org/ru/doc/migration/next-i18next)
|
|
541
|
+
- [Оптимизация бандла](https://intlayer.org/ru/doc/concept/bundle-optimization) и [компилятор Intlayer](https://intlayer.org/ru/doc/compiler)
|
|
542
|
+
- [Компонентная i18n против централизованной](https://intlayer.org/ru/blog/per-component-vs-centralized-i18n)
|
|
543
|
+
- [Компиляторная i18n против декларативной](https://intlayer.org/ru/blog/compiler-vs-declarative-i18n)
|
|
430
544
|
|
|
431
545
|
## Звезды на GitHub
|
|
432
546
|
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-23
|
|
3
|
+
updatedAt: 2026-09-23
|
|
4
|
+
title: Intlayer легче, чем Paraglide?
|
|
5
|
+
description: Paraglide кажется практически невесомым в бенчмарках i18n, поскольку его код генерируется прямо в ваш репозиторий. Разбираемся, куда на самом деле уходит этот вес, почему чтение локали для каждого узла обходится дорого и как динамическая загрузка Intlayer отправляет одну локаль вместо всех.
|
|
6
|
+
keywords:
|
|
7
|
+
- Paraglide
|
|
8
|
+
- Intlayer
|
|
9
|
+
- Интернационализация
|
|
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 легче, чем Paraglide?
|
|
22
|
+
|
|
23
|
+
Да.
|
|
24
|
+
|
|
25
|
+
У `Paraglide` сложилась отличная репутация самого легкого решения для i18n, и на первый взгляд [бенчмарк](https://intlayer.org/ru/doc/benchmark/tanstack) с этим согласен: размер его библиотеки близок к нулю. Однако нулевой размер библиотеки вовсе не означает нулевое количество отправленных байтов. Это лишь говорит о том, что байты находятся там, куда эта метрика не заглядывает.
|
|
26
|
+
|
|
27
|
+
<TOC/>
|
|
28
|
+
|
|
29
|
+
## Ключевые выводы
|
|
30
|
+
|
|
31
|
+
**Размер библиотеки скрыт, а не устранен:**
|
|
32
|
+
|
|
33
|
+
Paraglide генерирует рантайм и функции сообщений непосредственно в вашу кодовую базу. Этот код отправляется в браузер, но учитывается как _ваш_ код, а не код библиотеки.
|
|
34
|
+
|
|
35
|
+
**Отсутствие провайдера - это не бесплатный выигрыш:**
|
|
36
|
+
|
|
37
|
+
Каждый вызов `m.my_key()` самостоятельно определяет локаль, считывая cookie или хранилище для каждого отрисованного узла, вместо того чтобы прочитать ее один раз из контекста.
|
|
38
|
+
|
|
39
|
+
**Нет динамической загрузки:**
|
|
40
|
+
|
|
41
|
+
Paraglide импортирует все локали сообщения в клиентский бандл. Intlayer с `importMode: 'dynamic'` или `'fetch'` загружает только ту локаль, которая сейчас отображается.
|
|
42
|
+
|
|
43
|
+
**Tree shaking не гарантирован:**
|
|
44
|
+
|
|
45
|
+
В некоторых наших тестах заявленный Paraglide tree shaking не сработал. Обязательно проверьте собственный бандл.
|
|
46
|
+
|
|
47
|
+
## Куда уходит вес Paraglide?
|
|
48
|
+
|
|
49
|
+
В отчетах бенчмарков метрика «размер библиотеки» измеряет провайдер и хуки каждой библиотеки i18n в пустом компоненте, до добавления какого-либо контента.
|
|
50
|
+
|
|
51
|
+
| Библиотека (TanStack Start) | Размер либы (gz) | Размер либы (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
|
+
В отрыве от контекста Paraglide выигрывает. Но Paraglide - это компилятор: он читает ваши файлы `messages/*.json` и записывает папку `paraglide/` в ваш репозиторий. Она содержит `runtime.js` (определение локали, стратегии cookie и storage, локализация URL) и по одной JavaScript-функции на каждое сообщение.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
src/paraglide/
|
|
60
|
+
├── runtime.js # определение локали, стратегии, URL-хелперы
|
|
61
|
+
├── server.js
|
|
62
|
+
├── messages.js # реэкспорт всех сообщений
|
|
63
|
+
└── messages/
|
|
64
|
+
├── _index.js
|
|
65
|
+
├── en.js
|
|
66
|
+
└── fr.js
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Поскольку этот код находится в папке `src/` и вы импортируете его по относительному пути, сборщик приписывает его вашему приложению, а не пакету из `node_modules`. Колонка размера библиотеки почти ничего не показывает, хотя та же самая логика по-прежнему отправляется в бандле вашей страницы.
|
|
70
|
+
|
|
71
|
+
Генерация кода сама по себе неплоха: сгенерированный рантайм содержит только ту логику, которая нужна вашей конфигурации (стратегия префиксов, cookie или local storage и т. д.). Intlayer достигает того же результата иначе, внедряя переменные окружения на этапе сборки, благодаря чему бандлер удаляет ветви кода, не используемые вашей конфигурацией. Оба подхода оказываются в 3–10 раз легче, чем `i18next` или `next-intl`.
|
|
72
|
+
|
|
73
|
+
Поэтому честное сравнение - это не размер библиотеки. Это **JavaScript, фактически отправляемый на каждую страницу**.
|
|
74
|
+
|
|
75
|
+
## Измеренный вес страницы
|
|
76
|
+
|
|
77
|
+
Приложение TanStack Start, 10 страниц, измерения на маршрутах `en` и `fr`, сжатие gzip:
|
|
78
|
+
|
|
79
|
+
| Конфигурация | Средний JS стр (gz) | Выше базы | Утечка локали | Утечка других страниц |
|
|
80
|
+
| ---------------------------------- | ------------------- | ----------- | ------------- | --------------------- |
|
|
81
|
+
| Базовая (без i18n) | 111.0 KB | - | 0.0% | 0.0% |
|
|
82
|
+
| `paraglide` (любая стратегия) | 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, то же приложение:
|
|
87
|
+
|
|
88
|
+
| Конфигурация | Средний JS стр (gz) | Выше базы |
|
|
89
|
+
| ------------------ | ------------------- | ----------- |
|
|
90
|
+
| Базовая (без 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
|
+
> Полные данные приведены в [отчете о бенчмарке TanStack Start](https://intlayer.org/ru/doc/benchmark/tanstack) и в [отчете о бенчмарке Next.js](https://intlayer.org/ru/doc/benchmark/nextjs). Каждый бандл можно изучить в [репозитории бенчмарка](https://github.com/intlayer-org/benchmark-i18n).
|
|
97
|
+
|
|
98
|
+
Два момента бросаются в глаза:
|
|
99
|
+
|
|
100
|
+
- В режиме `static` Intlayer отправляет практически тот же объем данных, что и Paraglide (125.8 KB против 125.1 KB). Это ожидаемо: оба включают все локали сообщений, используемых страницей.
|
|
101
|
+
- Paraglide остается на уровне 125.1 KB при любой стратегии, поскольку в нем нет динамического режима. Каждая строка в таблице выше соответствует статической конфигурации.
|
|
102
|
+
|
|
103
|
+
## Отсутствие Provider: идея, кажущаяся хорошей лишь на первый взгляд
|
|
104
|
+
|
|
105
|
+
У Paraglide нет провайдера. Вы импортируете сообщение и вызываете его:
|
|
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
|
+
Ни контекста, ни обертки, ни хука. Это кажется проще. Но локаль все равно нужно откуда-то получать. Каждая сгенерированная функция сообщения выглядит приблизительно так (упрощенно):
|
|
120
|
+
|
|
121
|
+
```js fileName="paraglide/messages/_index.js"
|
|
122
|
+
export const hero_title = (inputs = {}, options = {}) => {
|
|
123
|
+
const locale = options.locale ?? getLocale(); // вычисляется при каждом вызове
|
|
124
|
+
|
|
125
|
+
if (locale === "en") return en.hero_title(inputs);
|
|
126
|
+
if (locale === "fr") return fr.hero_title(inputs);
|
|
127
|
+
// ...по одной ветке на каждую локаль
|
|
128
|
+
};
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
А `getLocale()` проходит по всем настроенным стратегиям (cookie, local storage, URL, базовая локаль), чтобы определить текущую локаль. Таким образом, каждый отрисовываемый текстовый узел (`<>{m.my_key()}</>`) выполняет собственное определение локали, включая чтение `document.cookie` в браузере. Страница с 200 переведенными строками вычисляет локаль 200 раз за один рендер, и затем повторно при каждом перерендере.
|
|
132
|
+
|
|
133
|
+
Библиотека с провайдером считывает локаль **один раз**, сохраняет ее в контексте (или сигнале, или сторе), и каждый узел читает значение, уже находящееся в оперативной памяти. Провайдер весит всего несколько сотен байт. Отказ от него нагружает процессор при каждом рендере, что наглядно отражается в бенчмарке: время загрузки страницы и скорость смены языка у Paraglide стабильно уступают Intlayer на TanStack Start (22.1 мс против 14.6 мс при загрузке страницы, 4.3 мс против 3.2 мс при реактивности E2E).
|
|
134
|
+
|
|
135
|
+
## Удобство разработки (DX)
|
|
136
|
+
|
|
137
|
+
Источником истины для Paraglide является JSON, но вы никогда не импортируете сам JSON. Вы импортируете сгенерированный файл `.js`:
|
|
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/ru.json"
|
|
149
|
+
{
|
|
150
|
+
"hero_title": "Публикуйте ваше приложение на всех языках"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```tsx fileName="Hero.tsx"
|
|
155
|
+
// Существует только после перегенерации компилятором из 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
|
+
ru: "Публикуйте ваше приложение на всех языках",
|
|
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
|
+
Такой рабочий процесс влечет за собой издержки:
|
|
192
|
+
|
|
193
|
+
- Любое изменение в файле JSON требует перегенерации, прежде чем импорт заработает или обновятся типы.
|
|
194
|
+
- Сгенерированную папку `paraglide/` приходится либо коммитить в репозиторий (что приводит к конфликтам слияния при каждом PR с правками текста), либо добавлять в игнорируемые файлы (что требует шага генерации перед каждой проверкой типов, тестом и задачей CI).
|
|
195
|
+
- Каждая строка превращается в вызов функции. Константы становятся `m.key()` абсолютно везде, даже там, где подошло бы обычное статическое значение.
|
|
196
|
+
|
|
197
|
+
## Tree Shaking: проверьте свой бандл
|
|
198
|
+
|
|
199
|
+
Главное обещание Paraglide заключается в том, что неиспользуемые сообщения удаляются с помощью tree shaking, поскольку каждое сообщение является отдельным экспортом. В бенчмарке Svelte + Vite это работает именно так, как заявлено.
|
|
200
|
+
|
|
201
|
+
В других окружениях этого не произошло. В нашем тесте на [Next.js](https://intlayer.org/ru/doc/benchmark/nextjs) страницы Paraglide весят на 14 KB больше базового приложения, тогда как `next-intlayer` добавляет лишь 0.3 KB. Предыдущие тесты на TanStack Start также показали, что сообщения с других страниц попадали в бандл текущего маршрута.
|
|
202
|
+
|
|
203
|
+
Tree shaking зависит от вашего сборщика (Turbopack, Rolldown, Rollup), способа импорта сообщений (`import { m }` против `import * as m`) и анализа сайд-эффектов. Если вы выбираете Paraglide из-за размера, откройте анализатор бандла и убедитесь, что это действительно работает в вашем приложении.
|
|
204
|
+
|
|
205
|
+
## Нет динамической загрузки
|
|
206
|
+
|
|
207
|
+
Это фундаментальное структурное ограничение. В Paraglide нет способа загружать по одной локали за раз: каждая функция сообщения статически импортирует реализацию каждого языка, поэтому абсолютно все языки попадают в ваш клиентский бандл.
|
|
208
|
+
|
|
209
|
+
При 2 языках половина трафика на переводы тратится впустую, что соответствует утечке локали около ~50%, измеренной выше. При 10 языках бесполезны 90% объема. При 30 языках - 97%.
|
|
210
|
+
|
|
211
|
+
Переход на динамическую загрузку также не решил бы проблему: при наличии отдельной функции на каждое сообщение ленивая загрузка каждой из них привела бы к тысячам сетевых запросов.
|
|
212
|
+
|
|
213
|
+
Intlayer позволяет выбирать стратегию как глобально, так и для каждого словаря отдельно:
|
|
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` | Что отправляется клиенту | vs. Paraglide |
|
|
232
|
+
| ------------ | ------------------------------------------------------------ | -------------------------------- |
|
|
233
|
+
| `static` | Все локали словарей, которые использует страница | Теоретически тот же объем |
|
|
234
|
+
| `dynamic` | Только активная локаль, ленивая загрузка для каждого словаря | **В N раз меньше** при N локалях |
|
|
235
|
+
| `fetch` | Только активная локаль, получаемая через Live Sync API | **В N раз меньше** при N локалях |
|
|
236
|
+
|
|
237
|
+
Благодаря [трансформации на этапе сборки](https://intlayer.org/ru/doc/concept/bundle-optimization) и режиму `importMode: 'static'`, Intlayer теоретически загружает ровно тот же объем данных, что и Paraglide. А в режимах `'dynamic'` или `'fetch'` он загружает только то, что требуется текущей локали: для приложения на N языках объем передаваемых переводов оказывается в N раз меньше, чем у Paraglide.
|
|
238
|
+
|
|
239
|
+
## Где Paraglide все еще уместен
|
|
240
|
+
|
|
241
|
+
<AccordionGroup>
|
|
242
|
+
<Accordion header="Svelte + Vite с небольшим количеством языков">
|
|
243
|
+
|
|
244
|
+
Если ваш стек - это Svelte с Vite и вы поддерживаете два или три языка, tree shaking работает как заявлено, а накладные расходы на лишние локали остаются незначительными.
|
|
245
|
+
|
|
246
|
+
</Accordion>
|
|
247
|
+
<Accordion header="Существующий рабочий процесс с inlang">
|
|
248
|
+
|
|
249
|
+
Если ваша команда уже использует экосистему inlang (Fink, Sherlock, плагины форматов сообщений), Paraglide нативно интегрируется в этот процесс.
|
|
250
|
+
|
|
251
|
+
</Accordion>
|
|
252
|
+
</AccordionGroup>
|
|
253
|
+
|
|
254
|
+
## Проверьте на своем приложении
|
|
255
|
+
|
|
256
|
+
Проверьте объем бандла и утечки локалей вашего рабочего приложения с помощью бесплатного инструмента [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
|
+
Установка 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
|
+
## Дополнительные материалы
|
|
279
|
+
|
|
280
|
+
- [Бенчмарк i18n в TanStack Start](https://intlayer.org/ru/doc/benchmark/tanstack)
|
|
281
|
+
- [Бенчмарк i18n в Next.js](https://intlayer.org/ru/doc/benchmark/nextjs)
|
|
282
|
+
- [Оптимизация бандла и `importMode`](https://intlayer.org/ru/doc/concept/bundle-optimization)
|
|
283
|
+
- [Как выбрать библиотеку i18n для React](https://intlayer.org/ru/blog/how-to-pick-react-i18n-library)
|
|
284
|
+
- [Аргументы в пользу компиляторного подхода к интернационализации](https://intlayer.org/ru/blog/compiler-vs-declarative-i18n)
|