@intlayer/docs 9.5.2 → 9.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/blog/ar/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ar/i18next_vs_intlayer.md +445 -0
- package/blog/ar/is_i18next_outdated.md +1 -1
- package/blog/ar/is_next-intl_outdated.md +1 -1
- package/blog/ar/is_vue-i18n_outdated.md +1 -1
- package/blog/ar/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/ar/lingui_vs_intlayer.md +381 -0
- package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ar/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/ar/next-intl_vs_intlayer.md +397 -0
- package/blog/ar/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/ar/vue-i18n_vs_intlayer-vue-i18n.md +286 -0
- package/blog/ar/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/de/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/de/i18next_vs_intlayer.md +445 -0
- package/blog/de/is_i18next_outdated.md +1 -1
- package/blog/de/is_next-intl_outdated.md +1 -1
- package/blog/de/is_vue-i18n_outdated.md +1 -1
- package/blog/de/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/de/lingui_vs_intlayer.md +381 -0
- package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/de/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/de/next-intl_vs_intlayer.md +415 -0
- package/blog/de/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/de/vue-i18n_vs_intlayer_benchmark.md +355 -0
- package/blog/en/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/en/i18next_vs_intlayer.md +445 -0
- package/blog/en/is_i18next_outdated.md +1 -1
- package/blog/en/is_next-intl_outdated.md +1 -1
- package/blog/en/is_vue-i18n_outdated.md +1 -1
- package/blog/en/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/en/lingui_vs_intlayer.md +381 -0
- package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/en/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/en/next-intl_vs_intlayer.md +415 -0
- package/blog/en/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/en/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/en/vue-i18n_vs_intlayer.md +1 -1
- package/blog/en/vue-i18n_vs_intlayer_benchmark.md +361 -0
- package/blog/en-GB/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/en-GB/i18next_vs_intlayer.md +445 -0
- package/blog/en-GB/is_i18next_outdated.md +1 -1
- package/blog/en-GB/is_next-intl_outdated.md +1 -1
- package/blog/en-GB/is_vue-i18n_outdated.md +1 -1
- package/blog/en-GB/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/en-GB/lingui_vs_intlayer.md +381 -0
- package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/en-GB/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/en-GB/next-intl_vs_intlayer.md +415 -0
- package/blog/en-GB/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/en-GB/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/en-GB/vue-i18n_vs_intlayer.md +1 -1
- package/blog/en-GB/vue-i18n_vs_intlayer_benchmark.md +245 -0
- package/blog/es/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/es/i18next_vs_intlayer.md +445 -0
- package/blog/es/is_i18next_outdated.md +1 -1
- package/blog/es/is_next-intl_outdated.md +1 -1
- package/blog/es/is_vue-i18n_outdated.md +1 -1
- package/blog/es/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/es/lingui_vs_intlayer.md +381 -0
- package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/es/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/es/next-intl_vs_intlayer.md +417 -0
- package/blog/es/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/es/vue-i18n_vs_intlayer_benchmark.md +363 -0
- package/blog/fr/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/fr/i18next_vs_intlayer.md +445 -0
- package/blog/fr/is_i18next_outdated.md +1 -1
- package/blog/fr/is_next-intl_outdated.md +1 -1
- package/blog/fr/is_vue-i18n_outdated.md +1 -1
- package/blog/fr/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/fr/lingui_vs_intlayer.md +381 -0
- package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/fr/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/fr/next-intl_vs_intlayer.md +417 -0
- package/blog/fr/vue-i18n_vs_intlayer-vue-i18n.md +287 -0
- package/blog/fr/vue-i18n_vs_intlayer_benchmark.md +39 -0
- package/blog/hi/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/hi/i18next_vs_intlayer.md +445 -0
- package/blog/hi/is_i18next_outdated.md +1 -1
- package/blog/hi/is_next-intl_outdated.md +1 -1
- package/blog/hi/is_vue-i18n_outdated.md +1 -1
- package/blog/hi/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/hi/lingui_vs_intlayer.md +381 -0
- package/blog/hi/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/hi/next-intl_vs_intlayer.md +397 -0
- package/blog/hi/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/hi/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/hi/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/id/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/id/i18next_vs_intlayer.md +445 -0
- package/blog/id/is_i18next_outdated.md +1 -1
- package/blog/id/is_next-intl_outdated.md +1 -1
- package/blog/id/is_vue-i18n_outdated.md +1 -1
- package/blog/id/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/id/lingui_vs_intlayer.md +381 -0
- package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/id/next-intl_vs_intlayer-next-intl.md +310 -0
- package/blog/id/next-intl_vs_intlayer.md +397 -0
- package/blog/id/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/id/vue-i18n_vs_intlayer-vue-i18n.md +36 -0
- package/blog/id/vue-i18n_vs_intlayer.md +1 -1
- package/blog/id/vue-i18n_vs_intlayer_benchmark.md +41 -0
- package/blog/it/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/it/i18next_vs_intlayer.md +445 -0
- package/blog/it/is_i18next_outdated.md +1 -1
- package/blog/it/is_next-intl_outdated.md +1 -1
- package/blog/it/is_vue-i18n_outdated.md +1 -1
- package/blog/it/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/it/lingui_vs_intlayer.md +381 -0
- package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/it/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/it/next-intl_vs_intlayer.md +418 -0
- package/blog/it/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/it/vue-i18n_vs_intlayer_benchmark.md +34 -0
- package/blog/ja/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ja/i18next_vs_intlayer.md +447 -0
- package/blog/ja/is_i18next_outdated.md +1 -1
- package/blog/ja/is_next-intl_outdated.md +1 -1
- package/blog/ja/is_vue-i18n_outdated.md +1 -1
- package/blog/ja/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/ja/lingui_vs_intlayer.md +381 -0
- package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ja/next-intl_vs_intlayer-next-intl.md +310 -0
- package/blog/ja/next-intl_vs_intlayer.md +422 -0
- package/blog/ja/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/ja/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/ja/vue-i18n_vs_intlayer.md +1 -1
- package/blog/ja/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/ko/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ko/i18next_vs_intlayer.md +447 -0
- package/blog/ko/is_i18next_outdated.md +1 -1
- package/blog/ko/is_next-intl_outdated.md +1 -1
- package/blog/ko/is_vue-i18n_outdated.md +1 -1
- package/blog/ko/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/ko/lingui_vs_intlayer.md +381 -0
- package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ko/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/ko/next-intl_vs_intlayer.md +397 -0
- package/blog/ko/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/ko/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/ko/vue-i18n_vs_intlayer.md +1 -1
- package/blog/ko/vue-i18n_vs_intlayer_benchmark.md +366 -0
- package/blog/pl/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/pl/i18next_vs_intlayer.md +445 -0
- package/blog/pl/is_i18next_outdated.md +1 -1
- package/blog/pl/is_next-intl_outdated.md +1 -1
- package/blog/pl/is_vue-i18n_outdated.md +1 -1
- package/blog/pl/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/pl/lingui_vs_intlayer.md +381 -0
- package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/pl/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/pl/next-intl_vs_intlayer.md +397 -0
- package/blog/pl/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/pl/vue-i18n_vs_intlayer-vue-i18n.md +289 -0
- package/blog/pl/vue-i18n_vs_intlayer.md +1 -1
- package/blog/pl/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/pt/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/pt/i18next_vs_intlayer.md +445 -0
- package/blog/pt/is_i18next_outdated.md +1 -1
- package/blog/pt/is_next-intl_outdated.md +1 -1
- package/blog/pt/is_vue-i18n_outdated.md +1 -1
- package/blog/pt/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/pt/lingui_vs_intlayer.md +381 -0
- package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/pt/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/pt/next-intl_vs_intlayer.md +411 -0
- package/blog/pt/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/pt/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/ru/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ru/i18next_vs_intlayer.md +445 -0
- package/blog/ru/is_i18next_outdated.md +1 -1
- package/blog/ru/is_next-intl_outdated.md +1 -1
- package/blog/ru/is_vue-i18n_outdated.md +1 -1
- package/blog/ru/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/ru/lingui_vs_intlayer.md +381 -0
- package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ru/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/ru/next-intl_vs_intlayer.md +417 -0
- package/blog/ru/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/ru/vue-i18n_vs_intlayer_benchmark.md +54 -0
- package/blog/tr/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/tr/i18next_vs_intlayer.md +445 -0
- package/blog/tr/is_i18next_outdated.md +1 -1
- package/blog/tr/is_next-intl_outdated.md +1 -1
- package/blog/tr/is_vue-i18n_outdated.md +1 -1
- package/blog/tr/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/tr/lingui_vs_intlayer.md +381 -0
- package/blog/tr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/tr/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/tr/next-intl_vs_intlayer.md +397 -0
- package/blog/tr/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/tr/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/tr/vue-i18n_vs_intlayer.md +1 -1
- package/blog/tr/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/uk/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/uk/i18next_vs_intlayer.md +445 -0
- package/blog/uk/is_i18next_outdated.md +1 -1
- package/blog/uk/is_next-intl_outdated.md +1 -1
- package/blog/uk/is_vue-i18n_outdated.md +1 -1
- package/blog/uk/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/uk/lingui_vs_intlayer.md +381 -0
- package/blog/uk/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/uk/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/uk/next-intl_vs_intlayer.md +397 -0
- package/blog/uk/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/uk/vue-i18n_vs_intlayer-vue-i18n.md +270 -0
- package/blog/uk/vue-i18n_vs_intlayer.md +1 -1
- package/blog/uk/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/vi/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/vi/i18next_vs_intlayer.md +445 -0
- package/blog/vi/is_i18next_outdated.md +1 -1
- package/blog/vi/is_next-intl_outdated.md +1 -1
- package/blog/vi/is_vue-i18n_outdated.md +1 -1
- package/blog/vi/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/vi/lingui_vs_intlayer.md +381 -0
- package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/vi/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/vi/next-intl_vs_intlayer.md +397 -0
- package/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/vi/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/vi/vue-i18n_vs_intlayer.md +1 -1
- package/blog/vi/vue-i18n_vs_intlayer_benchmark.md +0 -0
- package/blog/zh/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/zh/i18next_vs_intlayer.md +445 -0
- package/blog/zh/is_i18next_outdated.md +1 -1
- package/blog/zh/is_next-intl_outdated.md +1 -1
- package/blog/zh/is_vue-i18n_outdated.md +1 -1
- package/blog/zh/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/zh/lingui_vs_intlayer.md +381 -0
- package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/zh/next-intl_vs_intlayer-next-intl.md +309 -0
- package/blog/zh/next-intl_vs_intlayer.md +422 -0
- package/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md +1 -1
- package/blog/zh/vue-i18n_vs_intlayer-vue-i18n.md +288 -0
- package/blog/zh/vue-i18n_vs_intlayer.md +1 -1
- package/blog/zh/vue-i18n_vs_intlayer_benchmark.md +30 -0
- package/dist/cjs/generated/blog.entry.cjs +160 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +20 -0
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +160 -0
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs +20 -0
- package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
- package/dist/types/generated/blog.entry.d.ts +8 -0
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/dist/types/generated/frequentQuestions.entry.d.ts +1 -0
- package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -1
- package/docs/ar/benchmark/nextjs.md +1 -1
- package/docs/ar/benchmark/solid.md +1 -1
- package/docs/ar/benchmark/svelte.md +1 -1
- package/docs/ar/benchmark/tanstack.md +1 -1
- package/docs/ar/benchmark/vue.md +1 -1
- package/docs/ar/interest_of_intlayer.md +1 -1
- package/docs/bn/interest_of_intlayer.md +1 -1
- package/docs/cs/interest_of_intlayer.md +1 -1
- package/docs/de/benchmark/nextjs.md +1 -1
- package/docs/de/benchmark/solid.md +1 -1
- package/docs/de/benchmark/svelte.md +1 -1
- package/docs/de/benchmark/tanstack.md +1 -1
- package/docs/de/benchmark/vue.md +1 -1
- package/docs/de/interest_of_intlayer.md +1 -1
- package/docs/en/benchmark/nextjs.md +1 -1
- package/docs/en/benchmark/solid.md +1 -1
- package/docs/en/benchmark/svelte.md +1 -1
- package/docs/en/benchmark/tanstack.md +1 -1
- package/docs/en/benchmark/vue.md +1 -1
- package/docs/en/interest_of_intlayer.md +1 -1
- package/docs/en-GB/benchmark/nextjs.md +1 -1
- package/docs/en-GB/benchmark/solid.md +1 -1
- package/docs/en-GB/benchmark/svelte.md +1 -1
- package/docs/en-GB/benchmark/tanstack.md +1 -1
- package/docs/en-GB/benchmark/vue.md +1 -1
- package/docs/en-GB/interest_of_intlayer.md +1 -1
- package/docs/es/benchmark/nextjs.md +1 -1
- package/docs/es/benchmark/solid.md +1 -1
- package/docs/es/benchmark/svelte.md +1 -1
- package/docs/es/benchmark/tanstack.md +1 -1
- package/docs/es/benchmark/vue.md +1 -1
- package/docs/es/interest_of_intlayer.md +1 -1
- package/docs/fr/benchmark/nextjs.md +1 -1
- package/docs/fr/benchmark/solid.md +1 -1
- package/docs/fr/benchmark/svelte.md +1 -1
- package/docs/fr/benchmark/tanstack.md +1 -1
- package/docs/fr/benchmark/vue.md +1 -1
- package/docs/fr/interest_of_intlayer.md +1 -1
- package/docs/hi/benchmark/nextjs.md +1 -1
- package/docs/hi/benchmark/solid.md +1 -1
- package/docs/hi/benchmark/svelte.md +1 -1
- package/docs/hi/benchmark/tanstack.md +1 -1
- package/docs/hi/benchmark/vue.md +1 -1
- package/docs/hi/interest_of_intlayer.md +1 -1
- package/docs/id/benchmark/nextjs.md +1 -1
- package/docs/id/benchmark/solid.md +1 -1
- package/docs/id/benchmark/svelte.md +1 -1
- package/docs/id/benchmark/tanstack.md +1 -1
- package/docs/id/benchmark/vue.md +1 -1
- package/docs/id/interest_of_intlayer.md +1 -1
- package/docs/it/benchmark/nextjs.md +1 -1
- package/docs/it/benchmark/solid.md +1 -1
- package/docs/it/benchmark/svelte.md +1 -1
- package/docs/it/benchmark/tanstack.md +1 -1
- package/docs/it/benchmark/vue.md +1 -1
- package/docs/it/interest_of_intlayer.md +1 -1
- package/docs/ja/benchmark/nextjs.md +1 -1
- package/docs/ja/benchmark/solid.md +1 -1
- package/docs/ja/benchmark/svelte.md +1 -1
- package/docs/ja/benchmark/tanstack.md +1 -1
- package/docs/ja/benchmark/vue.md +1 -1
- package/docs/ja/interest_of_intlayer.md +1 -1
- package/docs/ko/benchmark/nextjs.md +1 -1
- package/docs/ko/benchmark/solid.md +1 -1
- package/docs/ko/benchmark/svelte.md +1 -1
- package/docs/ko/benchmark/tanstack.md +1 -1
- package/docs/ko/benchmark/vue.md +1 -1
- package/docs/ko/interest_of_intlayer.md +1 -1
- package/docs/nl/interest_of_intlayer.md +1 -1
- package/docs/pl/benchmark/nextjs.md +1 -1
- package/docs/pl/benchmark/solid.md +1 -1
- package/docs/pl/benchmark/svelte.md +1 -1
- package/docs/pl/benchmark/tanstack.md +1 -1
- package/docs/pl/benchmark/vue.md +1 -1
- package/docs/pl/interest_of_intlayer.md +1 -1
- package/docs/pt/benchmark/nextjs.md +1 -1
- package/docs/pt/benchmark/solid.md +1 -1
- package/docs/pt/benchmark/svelte.md +1 -1
- package/docs/pt/benchmark/tanstack.md +1 -1
- package/docs/pt/benchmark/vue.md +1 -1
- package/docs/pt/interest_of_intlayer.md +1 -1
- package/docs/ru/benchmark/nextjs.md +1 -1
- package/docs/ru/benchmark/solid.md +1 -1
- package/docs/ru/benchmark/svelte.md +1 -1
- package/docs/ru/benchmark/tanstack.md +1 -1
- package/docs/ru/benchmark/vue.md +1 -1
- package/docs/ru/interest_of_intlayer.md +1 -1
- package/docs/tr/benchmark/nextjs.md +1 -1
- package/docs/tr/benchmark/solid.md +1 -1
- package/docs/tr/benchmark/svelte.md +1 -1
- package/docs/tr/benchmark/tanstack.md +1 -1
- package/docs/tr/benchmark/vue.md +1 -1
- package/docs/tr/interest_of_intlayer.md +1 -1
- package/docs/uk/benchmark/nextjs.md +1 -1
- package/docs/uk/benchmark/solid.md +1 -1
- package/docs/uk/benchmark/svelte.md +1 -1
- package/docs/uk/benchmark/tanstack.md +1 -1
- package/docs/uk/benchmark/vue.md +1 -1
- package/docs/uk/interest_of_intlayer.md +1 -1
- package/docs/ur/interest_of_intlayer.md +1 -1
- package/docs/vi/benchmark/nextjs.md +1 -1
- package/docs/vi/benchmark/solid.md +1 -1
- package/docs/vi/benchmark/svelte.md +1 -1
- package/docs/vi/benchmark/tanstack.md +1 -1
- package/docs/vi/benchmark/vue.md +1 -1
- package/docs/vi/interest_of_intlayer.md +1 -1
- package/docs/zh/benchmark/nextjs.md +1 -1
- package/docs/zh/benchmark/solid.md +1 -1
- package/docs/zh/benchmark/svelte.md +1 -1
- package/docs/zh/benchmark/tanstack.md +1 -1
- package/docs/zh/benchmark/vue.md +1 -1
- package/docs/zh/interest_of_intlayer.md +1 -1
- package/docs/zh-TW/interest_of_intlayer.md +1 -1
- package/frequent_questions/ar/claude_code_token_consumption.md +152 -0
- package/frequent_questions/de/claude_code_token_consumption.md +152 -0
- package/frequent_questions/en/claude_code_token_consumption.md +152 -0
- package/frequent_questions/en-GB/claude_code_token_consumption.md +152 -0
- package/frequent_questions/es/claude_code_token_consumption.md +152 -0
- package/frequent_questions/fr/claude_code_token_consumption.md +152 -0
- package/frequent_questions/hi/claude_code_token_consumption.md +152 -0
- package/frequent_questions/id/claude_code_token_consumption.md +152 -0
- package/frequent_questions/it/claude_code_token_consumption.md +152 -0
- package/frequent_questions/ja/claude_code_token_consumption.md +152 -0
- package/frequent_questions/ko/claude_code_token_consumption.md +152 -0
- package/frequent_questions/pl/claude_code_token_consumption.md +152 -0
- package/frequent_questions/pt/claude_code_token_consumption.md +152 -0
- package/frequent_questions/ru/claude_code_token_consumption.md +152 -0
- package/frequent_questions/tr/claude_code_token_consumption.md +152 -0
- package/frequent_questions/uk/claude_code_token_consumption.md +152 -0
- package/frequent_questions/vi/claude_code_token_consumption.md +152 -0
- package/frequent_questions/zh/claude_code_token_consumption.md +152 -0
- package/package.json +6 -6
- package/src/generated/blog.entry.ts +160 -0
- package/src/generated/frequentQuestions.entry.ts +20 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-13
|
|
3
|
+
updatedAt: 2026-09-13
|
|
4
|
+
title: "i18next vs Intlayer: Benchmark e confronto 2026"
|
|
5
|
+
description: "react-i18next e next-i18next misurati rispetto a Intlayer su Next.js e TanStack Start. Dimensioni del bundle, dispersione dei contenuti, reattività al cambio lingua ed esperienza di sviluppo."
|
|
6
|
+
keywords:
|
|
7
|
+
- i18next
|
|
8
|
+
- react-i18next
|
|
9
|
+
- next-i18next
|
|
10
|
+
- Intlayer
|
|
11
|
+
- Internazionalizzazione
|
|
12
|
+
- i18n
|
|
13
|
+
- Benchmark
|
|
14
|
+
- Dimensioni bundle
|
|
15
|
+
- Blog
|
|
16
|
+
- Next.js
|
|
17
|
+
- TanStack Start
|
|
18
|
+
- JavaScript
|
|
19
|
+
- React
|
|
20
|
+
slugs:
|
|
21
|
+
- blog
|
|
22
|
+
- i18next-vs-intlayer
|
|
23
|
+
author: aymericzip
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# i18next VS Intlayer | Benchmark di internazionalizzazione (i18n) per React e Next.js
|
|
27
|
+
|
|
28
|
+
`i18next` è il framework di i18n più diffuso nell'ecosistema JavaScript. Attraverso `react-i18next` e `next-i18next`, alimenta un'ampia quota di applicazioni React e Next.js. Intlayer è un'alternativa basata su compilatore e con ambito per componente.
|
|
29
|
+
|
|
30
|
+
Questo articolo li mette a confronto attraverso misurazioni concrete anziché elenchi di funzionalità. I dati provengono da [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom), una suite open source che compila la stessa applicazione con ciascuna libreria e registra ciò che il browser scarica effettivamente.
|
|
31
|
+
|
|
32
|
+
<TOC/>
|
|
33
|
+
|
|
34
|
+
> **tl;dr**: `i18next` è il runtime più pesante del benchmark: **+77 KB gzip per pagina** su Next.js nella configurazione standard (naive), **+22 KB** dopo l'ottimizzazione completa con namespace e lazy loading. Intlayer aggiunge appena **+0.3 KB**. Ogni configurazione di `i18next`, tranne quella completamente isolata (scoped), include **~90% di stringhe di pagine non visitate**; Intlayer ne include lo **0%** per impostazione predefinita. Il cambio di lingua con backend caricato in modalità lazy ha richiesto **123-185 ms** con `react-i18next` contro **3-4 ms** con Intlayer. L'adattatore `@intlayer/next-i18next` conserva l'API di `i18next` e si attesta a **150.7 KB** per pagina rispetto ai **218.5 KB** dell'originale.
|
|
35
|
+
|
|
36
|
+
## In sintesi
|
|
37
|
+
|
|
38
|
+
- **i18next / react-i18next / next-i18next** - Maturo, ricco di plugin e indipendente dal framework. Namespace, rilevatori di lingua, backend, ICU tramite plugin, `<Trans>` per contenuti avanzati. I contenuti sono centralizzati in `locales/{lng}/{ns}.json`. Potente, ma ogni ottimizzazione (divisione in namespace, caricamento per pagina, sicurezza dei tipi) richiede configurazioni manuali a carico dello sviluppatore.
|
|
39
|
+
- **Intlayer** - Modello incentrato sui componenti. I dizionari `.content.ts` risiedono accanto al componente a cui sono destinati, un compilatore in fase di build applica tree-shaking e lazy loading per componente e per lingua, tipi TypeScript rigorosi vengono generati automaticamente dai contenuti e le traduzioni mancanti bloccano la compilazione. Include middleware, helper SEO, un editor visuale / CMS e traduzione assistita da IA.
|
|
40
|
+
|
|
41
|
+
| Libreria | Stelle GitHub | Commit totali | Ultimo commit | Prima versione | Versione NPM | Download NPM |
|
|
42
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| `aymericzip/intlayer` | [](https://github.com/aymericzip/intlayer/stargazers) | [](https://github.com/aymericzip/intlayer/commits) | [](https://github.com/aymericzip/intlayer/commits) | Aprile 2024 | [](https://www.npmjs.com/package/intlayer) | [](https://www.npmjs.com/package/intlayer) |
|
|
44
|
+
| `i18next/i18next` | [](https://github.com/i18next/i18next/stargazers) | [](https://github.com/i18next/i18next/commits) | [](https://github.com/i18next/i18next/commits) | Gennaio 2012 | [](https://www.npmjs.com/package/i18next) | [](https://www.npmjs.com/package/i18next) |
|
|
45
|
+
| `i18next/react-i18next` | [](https://github.com/i18next/react-i18next/stargazers) | [](https://github.com/i18next/react-i18next/commits) | [](https://github.com/i18next/react-i18next/commits) | Dicembre 2015 | [](https://www.npmjs.com/package/react-i18next) | [](https://www.npmjs.com/package/react-i18next) |
|
|
46
|
+
| `i18next/next-i18next` | [](https://github.com/i18next/next-i18next/stargazers) | [](https://github.com/i18next/next-i18next/commits) | [](https://github.com/i18next/next-i18next/commits) | Novembre 2018 | [](https://www.npmjs.com/package/next-i18next) | [](https://www.npmjs.com/package/next-i18next) |
|
|
47
|
+
|
|
48
|
+
> I badge si aggiornano automaticamente. Le metriche variano nel tempo.
|
|
49
|
+
|
|
50
|
+
## Confronto delle caratteristiche
|
|
51
|
+
|
|
52
|
+
| Caratteristica | Intlayer (`react-intlayer` / `next-intlayer`) | i18next (`react-i18next` / `next-i18next`) |
|
|
53
|
+
| ---------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
54
|
+
| **Traduzioni vicine ai componenti** | ✅ Sì, `.content.ts` posizionato accanto a ogni componente | ❌ No, cartella centralizzata `locales/{lng}/{ns}.json` |
|
|
55
|
+
| **Integrazione con TypeScript** | ✅ Tipi rigorosi generati in automatico dai contenuti | ⚠️ Base; richiede estensione manuale di `CustomTypeOptions` e tipizzazione |
|
|
56
|
+
| **Rilevamento traduzioni mancanti** | ✅ Errore TypeScript + errore/avviso in fase di compilazione | ⚠️ Fallback a runtime (`saveMissing`, restituzione della chiave) |
|
|
57
|
+
| **Contenuti avanzati (JSX / Markdown)** | ✅ Supporto nativo | ⚠️ `<Trans>` con segnaposto indicizzati |
|
|
58
|
+
| **Supporto ICU** | ⚠️ In lavorazione | ⚠️ Tramite plugin (`i18next-icu`) |
|
|
59
|
+
| **Pluralizzazione** | ✅ Modelli basati su enumerazioni | ✅ Suffissi `_one` / `_other` (Intl.PluralRules) |
|
|
60
|
+
| **Formattazione (date, numeri, valute)** | ✅ `useNumber`, `useDate`, ... (Intl integrato) | ⚠️ Formattatori di interpolazione o chiamate manuali a `Intl.*` |
|
|
61
|
+
| **Routing localizzato e middleware** | ✅ Proxy/middleware integrato, `getMultilingualUrls` | ⚠️ Non nativo; richiede middleware personalizzato o di terze parti |
|
|
62
|
+
| **Helper SEO (hreflang, sitemap, robots)** | ✅ Helper integrati | ❌ Manuale |
|
|
63
|
+
| **Componenti server sincroni** | ✅ `useIntlayer` da `next-intlayer/server` utilizzabile in ogni server component | ⚠️ `getFixedT` a livello di pagina, poi `t` passato come prop |
|
|
64
|
+
| **Tree-shaking (carica solo contenuti usati)** | ✅ Per componente, per lingua, automatizzato dal compilatore | ⚠️ Manuale: namespace + lista `ns` per pagina + backend |
|
|
65
|
+
| **Lazy loading** | ✅ `importMode: 'dynamic'` (una riga di configurazione) | ✅ Tramite plugin backend (`i18next-resources-to-backend`, `i18next-http-backend`) |
|
|
66
|
+
| **Eliminazione contenuti inutilizzati** | ✅ I dizionari orfani vengono scartati in fase di compilazione | ❌ Non integrato |
|
|
67
|
+
| **Test traduzioni mancanti (CLI / CI)** | ✅ `npx intlayer content test` | ⚠️ `i18next-parser` / strumenti di terze parti |
|
|
68
|
+
| **Traduzione assistita da IA** | ✅ Integrata, utilizza le tue chiavi API | ❌ No (Locize è un servizio a pagamento separato) |
|
|
69
|
+
| **Editor Visuale / CMS** | ✅ Editor Visuale gratuito + CMS opzionale | ❌ No (Locize / piattaforme esterne) |
|
|
70
|
+
| **Server MCP e Agent Skills** | ✅ Sì | ❌ No |
|
|
71
|
+
| **Ecosistema e community** | ⚠️ Più recente ma in rapida espansione | ✅ Il più esteso e consolidato |
|
|
72
|
+
|
|
73
|
+
## Il benchmark
|
|
74
|
+
|
|
75
|
+
### Cosa è stato misurato
|
|
76
|
+
|
|
77
|
+
La suite [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) costruisce **la medesima applicazione** con ciascuna libreria: **10 pagine** (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), **10 lingue** (`en`, `fr`, `es`, `de`, `it`, `pt`, `zh`, `ja`, `ko`, `ru`), componenti e contenuti identici. Le pagine sono misurate in `en` e `fr`. Ogni libreria viene testata con un massimo di quattro **strategie di caricamento**:
|
|
78
|
+
|
|
79
|
+
| Strategia | Descrizione | Casi d'uso tipici |
|
|
80
|
+
| ------------------ | ----------------------------------------------------------------------------------------- | -------------------------------------------------- |
|
|
81
|
+
| **static** | Tutte le lingue e pagine raggruppate (`resources` incorporate in `init()`) | Prototipi veloci, codice generato da IA |
|
|
82
|
+
| **dynamic** | Solo la lingua attiva viene caricata via backend, ma tutti i namespace contemporaneamente | La maggior parte dei progetti |
|
|
83
|
+
| **scoped-static** | Un namespace per percorso, tutti inclusi in anticipo | Raro |
|
|
84
|
+
| **scoped-dynamic** | Un namespace per percorso + lazy loading tramite backend. Solo pagina e lingua correnti | Applicazioni con vincoli di performance stringenti |
|
|
85
|
+
|
|
86
|
+
Intlayer non necessita di una variante "scoped": il compilatore suddivide i contenuti **per componente** in modo del tutto automatico, per cui le righe `static` e `dynamic` sono già ottimizzate.
|
|
87
|
+
|
|
88
|
+
Per ciascuna build, la suite registra:
|
|
89
|
+
|
|
90
|
+
- **Lib size**: dimensione gzip di un componente vuoto che importa esclusivamente la libreria i18n.
|
|
91
|
+
- **Page JS**: JavaScript gzip scaricato per pagina, mediato su tutte le pagine e lingue.
|
|
92
|
+
- **Locale leak %**: percentuale di stringhe tradotte nel JS scaricato appartenenti a una lingua che l'utente **non** sta visualizzando.
|
|
93
|
+
- **Page leak %**: percentuale di stringhe tradotte nel JS scaricato appartenenti a pagine in cui l'utente **non** si trova.
|
|
94
|
+
- **Component avg**: dimensione media gzip di ciascun componente compilato isolatamente.
|
|
95
|
+
- **E2E reactivity**: intervallo reale tra la selezione di una nuova lingua e l'aggiornamento di `html[lang]` nel DOM (Playwright, 5 iterazioni).
|
|
96
|
+
- **Hydration**: durata della fase di idratazione di React.
|
|
97
|
+
|
|
98
|
+
> I dati seguenti si riferiscono al test del **2026-09-12** con `next-i18next` 16.3.0, `react-i18next` 17.0.13 e `intlayer` 9.5.1. L'applicazione di test è volutamente contenuta (poche decine di stringhe per lingua), pertanto le percentuali di dispersione mostrano un **modello**: crescono insieme ai contenuti mentre il costo del runtime rimane costante.
|
|
99
|
+
|
|
100
|
+
### Risultati su Next.js (`next-i18next`)
|
|
101
|
+
|
|
102
|
+
| Libreria | Strategia | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | Reattività E2E | Hydration |
|
|
103
|
+
| --------------------------------- | -------------- | ------------: | ---------------: | ----------: | --------: | -----------------: | -------------: | --------: |
|
|
104
|
+
| **base** (senza i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
|
|
105
|
+
| `next-i18next` | static | 19.7 KB | 218.5 KB | 0.0% | 89.8% | 78.5 KB | 16.4 ms | 15.6 ms |
|
|
106
|
+
| `next-i18next` | dynamic | 19.7 KB | 169.5 KB | 50.0% | 89.8% | 26.1 KB | 15.4 ms | 27.7 ms |
|
|
107
|
+
| `next-i18next` | scoped-static | 19.7 KB | 220.1 KB | 0.0% | 89.8% | 78.9 KB | 16.4 ms | 14.7 ms |
|
|
108
|
+
| `next-i18next` | scoped-dynamic | 19.7 KB | 163.4 KB | 0.0% | 0.0% | 27.1 KB | 15.9 ms | 15.1 ms |
|
|
109
|
+
| **`next-intlayer`** | static | **5.5 KB** | **141.3 KB** | **0.0%** | **0.0%** | **8.5 KB** | **15.5 ms** | 16.9 ms |
|
|
110
|
+
| **`next-intlayer`** | dynamic | **5.5 KB** | **141.3 KB** | **0.0%** | **0.0%** | **6.9 KB** | **15.3 ms** | 15.9 ms |
|
|
111
|
+
| `@intlayer/next-i18next` (compat) | static | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 10.7 ms | 11.3 ms |
|
|
112
|
+
| `@intlayer/next-i18next` (compat) | dynamic | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 11.9 ms | 10.6 ms |
|
|
113
|
+
|
|
114
|
+
**Come interpretare i dati**
|
|
115
|
+
|
|
116
|
+
- **Costo del runtime.** Il core di `i18next` abbinato a `react-i18next` è il runtime più consistente: **19.7 KB gzip** per un componente vuoto, rispetto ai 5.5 KB di `next-intlayer`.
|
|
117
|
+
- **La configurazione base è onerosa.** Incorporare `resources` in `init()` produce **218.5 KB per pagina**, +77.5 KB rispetto all'applicazione priva di i18n. Ogni pagina include tutti i namespace.
|
|
118
|
+
- **Ottimizzare richiede lavoro.** Passare a un backend (`dynamic`) risparmia 49 KB ma disperde ancora il **90% delle stringhe di altre pagine** e, in questo scenario, la metà delle stringhe appartiene alla lingua errata. Aggiungere la divisione per namespace su ogni route (`scoped-dynamic`) raggiunge lo 0% di dispersione a **163.4 KB**, rimanendo comunque **+22.4 KB per pagina** sopra Intlayer (141.3 KB), che non ha richiesto alcuna configurazione speciale.
|
|
119
|
+
- **Dimensioni dei componenti.** Un componente con `useTranslation()` compila tra i 26 e i 79 KB; lo stesso componente con `useIntlayer()` si attesta a 6.9 KB.
|
|
120
|
+
- **L'idratazione** sale a 27.7 ms nella configurazione `dynamic`: l'istanza i18next si inizializza e risolve il proprio backend sul client prima che React possa idratare la pagina.
|
|
121
|
+
|
|
122
|
+
### Risultati su TanStack Start (`react-i18next`)
|
|
123
|
+
|
|
124
|
+
Stessa applicazione di prova su TanStack Start con `react-i18next` puro, isolando la comparazione dalle specificità di Next.js.
|
|
125
|
+
|
|
126
|
+
| Libreria | Strategia | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | Reattività E2E | Hydration |
|
|
127
|
+
| ------------------ | -------------- | ------------: | ---------------: | ----------: | --------: | -----------------: | -------------: | --------: |
|
|
128
|
+
| **base** (no i18n) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms | 21.6 ms |
|
|
129
|
+
| `react-i18next` | static | 18.4 KB | 180.3 KB | 50.0% | 89.8% | 24.3 KB | 12.9 ms | 85.1 ms |
|
|
130
|
+
| `react-i18next` | dynamic | 18.4 KB | 136.4 KB | 23.1% | 89.8% | 24.8 KB | 123.1 ms | 32.9 ms |
|
|
131
|
+
| `react-i18next` | scoped-static | 18.4 KB | 184.2 KB | 50.7% | 89.8% | 25.3 KB | 185.1 ms | 25.2 ms |
|
|
132
|
+
| `react-i18next` | scoped-dynamic | 18.4 KB | 127.2 KB | 0.0% | 0.0% | 26.7 KB | 17.6 ms | 11.3 ms |
|
|
133
|
+
| **`intlayer`** | static | **5.0 KB** | **125.8 KB** | 50.0% | **0.0%** | **8.1 KB** | **3.2 ms** | 11.5 ms |
|
|
134
|
+
| **`intlayer`** | dynamic | **5.0 KB** | **118.6 KB** | **0.0%** | **0.0%** | **6.3 KB** | **3.6 ms** | 14.1 ms |
|
|
135
|
+
|
|
136
|
+
**Come interpretare i dati**
|
|
137
|
+
|
|
138
|
+
- L'app `react-i18next` di base trasmette **+69 KB per pagina** rispetto all'applicazione senza i18n, e l'idratazione impiega **85 ms** (4 volte il valore di base) perché l'albero completo delle risorse viene elaborato e registrato sul client prima del rendering iniziale.
|
|
139
|
+
- **Il cambio di lingua rende evidente la latenza del lazy loading.** Quando le risorse vengono caricate al bisogno, il cambio lingua comporta una chiamata di rete prima dell'aggiornamento di `html[lang]`: **123 ms** in `dynamic`, **185 ms** in `scoped-static`. Intlayer aggiorna il DOM in **3-4 ms** in entrambe le modalità: la modifica è istantanea e non dipende da richieste di rete.
|
|
140
|
+
- L'assetto interamente ottimizzato `scoped-dynamic` tocca lo 0% di dispersione a 127.2 KB, rimanendo comunque **+8.6 KB** sopra la riga `dynamic` di Intlayer, e ha richiesto una mappatura route-namespace, un backend di risorse e confini Suspense dedicati.
|
|
141
|
+
- La riga `static` di Intlayer ha già **0% di dispersione di pagina** poiché vengono inclusi solo i dizionari importati dai componenti effettivi della pagina. Abilitando `importMode: 'dynamic'` si azzera anche la dispersione linguistica.
|
|
142
|
+
- **Dimensioni componenti**: 24-27 KB con `react-i18next` contro 6-8 KB con Intlayer. `useTranslation()` vincola ogni componente all'istanza globale di i18next.
|
|
143
|
+
|
|
144
|
+
## Origine del divario: Istanza globale vs dizionari compilati
|
|
145
|
+
|
|
146
|
+
`i18next` è nato nel 2012 come runtime: un'istanza globale mantiene un archivio di risorse, i plugin la espandono e `t()` ricerca le chiavi a runtime. Tale architettura garantisce grande versatilità (qualsiasi framework, backend e formato), ma introduce inevitabilmente overhead:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
.
|
|
150
|
+
├── i18n.ts # createInstance().use(...).use(...).init({...})
|
|
151
|
+
└── src
|
|
152
|
+
├── locales
|
|
153
|
+
│ ├── en
|
|
154
|
+
│ │ ├── common.json
|
|
155
|
+
│ │ ├── home.json
|
|
156
|
+
│ │ └── about.json
|
|
157
|
+
│ └── fr
|
|
158
|
+
│ ├── common.json
|
|
159
|
+
│ ├── home.json
|
|
160
|
+
│ └── about.json
|
|
161
|
+
├── components
|
|
162
|
+
│ └── Counter.tsx # useTranslation("about") + t("counter.label")
|
|
163
|
+
└── app
|
|
164
|
+
└── [locale]
|
|
165
|
+
└── about
|
|
166
|
+
└── page.tsx # deve sapere che necessita di ["common", "about"]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
L'istanza non può anticipare le chiavi richieste da un componente. Ottimizzare significa che **tu** devi suddividere i file in namespace, **tu** devi elencare i namespace richiesti da ogni pagina e **tu** devi mantenere allineata la lista quando i componenti vengono spostati. Come riportato nelle [note del benchmark](https://github.com/intlayer-org/benchmark-bloom/blob/main/report/NOTE.md): "mantenere la sicurezza dei tipi e sapere esattamente quale namespace includere su quale pagina è un incubo".
|
|
170
|
+
|
|
171
|
+
Intlayer elimina l'istanza globale. I contenuti sono dichiarati accanto al componente e il compilatore risolve il grafico delle dipendenze durante il build:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
.
|
|
175
|
+
├── intlayer.config.ts
|
|
176
|
+
└── src
|
|
177
|
+
├── components
|
|
178
|
+
│ └── Counter
|
|
179
|
+
│ ├── index.tsx # useIntlayer("counter")
|
|
180
|
+
│ └── index.content.ts
|
|
181
|
+
└── app
|
|
182
|
+
└── [locale]
|
|
183
|
+
└── about
|
|
184
|
+
├── page.tsx
|
|
185
|
+
└── page.content.ts
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`@intlayer/swc` / `@intlayer/babel` analizza quale componente importa quale dizionario, impacchetta esclusivamente quelli utili per la lingua corrente e scarta il resto. Il pattern "scoped-dynamic" diventa il risultato naturale del build anziché un onere manuale.
|
|
189
|
+
|
|
190
|
+
> Per ottenere i parametri della riga `dynamic`, imposta `dictionary.importMode: 'dynamic'` in `intlayer.config.ts`. Consulta la [guida all'ottimizzazione del bundle](https://intlayer.org/it/doc/concept/bundle-optimization).
|
|
191
|
+
|
|
192
|
+
## Esperienza di sviluppo
|
|
193
|
+
|
|
194
|
+
### Configurazione
|
|
195
|
+
|
|
196
|
+
**next-i18next (App Router)**
|
|
197
|
+
|
|
198
|
+
```ts fileName="src/app/i18n/server.ts"
|
|
199
|
+
import { createInstance } from "i18next";
|
|
200
|
+
import { initReactI18next } from "react-i18next/initReactI18next";
|
|
201
|
+
import resourcesToBackend from "i18next-resources-to-backend";
|
|
202
|
+
import { defaultLocale } from "@/i18n.config";
|
|
203
|
+
|
|
204
|
+
const backend = resourcesToBackend(
|
|
205
|
+
(locale: string, namespace: string) =>
|
|
206
|
+
import(`../../locales/${locale}/${namespace}.json`)
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
export const initI18next = async (
|
|
210
|
+
locale: string,
|
|
211
|
+
namespaces: string[] = ["common"]
|
|
212
|
+
) => {
|
|
213
|
+
const i18n = createInstance();
|
|
214
|
+
await i18n
|
|
215
|
+
.use(initReactI18next)
|
|
216
|
+
.use(backend)
|
|
217
|
+
.init({
|
|
218
|
+
lng: locale,
|
|
219
|
+
fallbackLng: defaultLocale,
|
|
220
|
+
ns: namespaces,
|
|
221
|
+
defaultNS: "common",
|
|
222
|
+
interpolation: { escapeValue: false },
|
|
223
|
+
react: { useSuspense: false },
|
|
224
|
+
});
|
|
225
|
+
return i18n;
|
|
226
|
+
};
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
A questo si aggiunge un `I18nProvider` client che reinizializza l'istanza con le medesime opzioni, `generateStaticParams` e un elenco `namespaces` per ciascuna pagina.
|
|
230
|
+
|
|
231
|
+
**Intlayer**
|
|
232
|
+
|
|
233
|
+
```ts fileName="intlayer.config.ts"
|
|
234
|
+
import { type IntlayerConfig, Locales } from "intlayer";
|
|
235
|
+
|
|
236
|
+
const config: IntlayerConfig = {
|
|
237
|
+
internationalization: {
|
|
238
|
+
locales: [Locales.ENGLISH, Locales.FRENCH],
|
|
239
|
+
defaultLocale: Locales.ENGLISH,
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export default config;
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
```tsx fileName="src/app/[locale]/layout.tsx"
|
|
247
|
+
import { getHTMLTextDir } from "intlayer";
|
|
248
|
+
import { IntlayerClientProvider, type NextLayoutIntlayer } from "next-intlayer";
|
|
249
|
+
|
|
250
|
+
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
|
|
251
|
+
const { locale } = await params;
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
255
|
+
<body>
|
|
256
|
+
<IntlayerClientProvider locale={locale}>
|
|
257
|
+
{children}
|
|
258
|
+
</IntlayerClientProvider>
|
|
259
|
+
</body>
|
|
260
|
+
</html>
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export default LocaleLayout;
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Componente client
|
|
268
|
+
|
|
269
|
+
**react-i18next**
|
|
270
|
+
|
|
271
|
+
```json fileName="src/locales/en/about.json"
|
|
272
|
+
{
|
|
273
|
+
"counter": {
|
|
274
|
+
"label": "Counter",
|
|
275
|
+
"increment": "Increment"
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
```tsx fileName="src/components/Counter.tsx"
|
|
281
|
+
"use client";
|
|
282
|
+
|
|
283
|
+
import { useState } from "react";
|
|
284
|
+
import { useTranslation } from "react-i18next";
|
|
285
|
+
|
|
286
|
+
export const Counter = () => {
|
|
287
|
+
const { t, i18n } = useTranslation("about");
|
|
288
|
+
const [count, setCount] = useState(0);
|
|
289
|
+
const numberFormat = new Intl.NumberFormat(i18n.language);
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<div>
|
|
293
|
+
<p>{numberFormat.format(count)}</p>
|
|
294
|
+
<button
|
|
295
|
+
aria-label={t("counter.label")}
|
|
296
|
+
onClick={() => setCount((c) => c + 1)}
|
|
297
|
+
>
|
|
298
|
+
{t("counter.increment")}
|
|
299
|
+
</button>
|
|
300
|
+
</div>
|
|
301
|
+
);
|
|
302
|
+
};
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
> La pagina che renderizza questo componente deve caricare il namespace `about`, e `t("counter.label")` rimane una stringa semplice finché non si estende `CustomTypeOptions`.
|
|
306
|
+
|
|
307
|
+
**Intlayer**
|
|
308
|
+
|
|
309
|
+
```ts fileName="src/components/Counter/index.content.ts"
|
|
310
|
+
import { t, type Dictionary } from "intlayer";
|
|
311
|
+
|
|
312
|
+
const counterContent = {
|
|
313
|
+
key: "counter",
|
|
314
|
+
content: {
|
|
315
|
+
label: t({ en: "Counter", fr: "Compteur" }),
|
|
316
|
+
increment: t({ en: "Increment", fr: "Incrémenter" }),
|
|
317
|
+
},
|
|
318
|
+
} satisfies Dictionary;
|
|
319
|
+
|
|
320
|
+
export default counterContent;
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
```tsx fileName="src/components/Counter/index.tsx"
|
|
324
|
+
"use client";
|
|
325
|
+
|
|
326
|
+
import { useState } from "react";
|
|
327
|
+
import { useIntlayer } from "next-intlayer";
|
|
328
|
+
import { useNumber } from "next-intlayer/format";
|
|
329
|
+
|
|
330
|
+
export const Counter = () => {
|
|
331
|
+
const { label, increment } = useIntlayer("counter");
|
|
332
|
+
const number = useNumber();
|
|
333
|
+
const [count, setCount] = useState(0);
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<div>
|
|
337
|
+
<p>{number(count)}</p>
|
|
338
|
+
<button aria-label={label} onClick={() => setCount((c) => c + 1)}>
|
|
339
|
+
{increment}
|
|
340
|
+
</button>
|
|
341
|
+
</div>
|
|
342
|
+
);
|
|
343
|
+
};
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
`label` e `increment` sono tipizzati rigorosamente: ogni errore di battitura genera un errore TypeScript e una traduzione mancante blocca la compilazione.
|
|
347
|
+
|
|
348
|
+
### Componente server sincrono
|
|
349
|
+
|
|
350
|
+
**next-i18next**
|
|
351
|
+
|
|
352
|
+
```tsx fileName="src/components/ServerCounter.tsx"
|
|
353
|
+
type ServerCounterProps = {
|
|
354
|
+
t: (key: string) => string;
|
|
355
|
+
locale: string;
|
|
356
|
+
count: number;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export const ServerCounter = ({ t, locale, count }: ServerCounterProps) => (
|
|
360
|
+
<div>
|
|
361
|
+
<p>{new Intl.NumberFormat(locale).format(count)}</p>
|
|
362
|
+
<button aria-label={t("counter.label")}>{t("counter.increment")}</button>
|
|
363
|
+
</div>
|
|
364
|
+
);
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
La pagina invoca `i18n.getFixedT(locale, "about")` e trasmette `t` e `locale` verso il basso tramite props.
|
|
368
|
+
|
|
369
|
+
**Intlayer**
|
|
370
|
+
|
|
371
|
+
```tsx fileName="src/components/ServerCounter.tsx"
|
|
372
|
+
import { useIntlayer } from "next-intlayer/server";
|
|
373
|
+
import { useNumber } from "next-intlayer/server/format";
|
|
374
|
+
|
|
375
|
+
export const ServerCounter = ({ count }: { count: number }) => {
|
|
376
|
+
const { label, increment } = useIntlayer("counter");
|
|
377
|
+
const number = useNumber();
|
|
378
|
+
|
|
379
|
+
return (
|
|
380
|
+
<div>
|
|
381
|
+
<p>{number(count)}</p>
|
|
382
|
+
<button aria-label={label}>{increment}</button>
|
|
383
|
+
</div>
|
|
384
|
+
);
|
|
385
|
+
};
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Conserva l'API di i18next, sfrutta le prestazioni di Intlayer
|
|
389
|
+
|
|
390
|
+
Non serve riscrivere i componenti per beneficiare dei numeri del benchmark. `@intlayer/i18next`, `@intlayer/react-i18next` e `@intlayer/next-i18next` sono adattatori compatibili pronti all'uso: `useTranslation`, `t()`, `<Trans>`, `{{interpolation}}`, plurali `_one` / `_other`, suffissi di contesto e `returnObjects` continuano a funzionare, erogati tramite i dizionari compilati da Intlayer.
|
|
391
|
+
|
|
392
|
+
```ts fileName="next.config.ts"
|
|
393
|
+
import type { NextConfig } from "next";
|
|
394
|
+
import { createNextI18nPlugin } from "@intlayer/next-i18next/plugin";
|
|
395
|
+
|
|
396
|
+
const withIntlayer = createNextI18nPlugin();
|
|
397
|
+
|
|
398
|
+
const nextConfig: NextConfig = {};
|
|
399
|
+
|
|
400
|
+
export default withIntlayer(nextConfig);
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
```ts fileName="vite.config.ts"
|
|
404
|
+
import { defineConfig } from "vite";
|
|
405
|
+
import { reactI18nextVitePlugin } from "@intlayer/react-i18next/plugin";
|
|
406
|
+
|
|
407
|
+
export default defineConfig({
|
|
408
|
+
plugins: [reactI18nextVitePlugin()],
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Nel benchmark, la versione con adattatore della medesima app Next.js è passata da **218.5 KB a 150.7 KB** per pagina, da **78.5 KB a 9.7 KB** per componente, da **~90% di dispersione a 0%**, e l'idratazione da 15.6 ms a 11.3 ms, senza alterare il codice dell'applicazione. I file esistenti `locales/{lng}/{ns}.json` possono rimanere la sorgente primaria dei dati tramite il plugin di sincronizzazione JSON.
|
|
413
|
+
|
|
414
|
+
Consulta le guide di migrazione: [i18next](https://intlayer.org/it/doc/migration/i18next), [react-i18next](https://intlayer.org/it/doc/migration/react-i18next), [next-i18next](https://intlayer.org/it/doc/migration/next-i18next).
|
|
415
|
+
|
|
416
|
+
## Quando scegliere quale soluzione?
|
|
417
|
+
|
|
418
|
+
- **Scegli i18next** se necessiti del suo ecosistema di plugin (rilevatori, backend, ICU, Locize), se gestisci la localizzazione anche fuori da React (servizi Node, vanilla JS, altri framework), se il tuo team ha già consolidata esperienza o se una piattaforma di traduzione richiede `locales/{lng}/{ns}.json`. Considera il tempo necessario per organizzare i namespace, configurare un backend e mantenere aggiornata la mappa delle route se le performance sono critiche.
|
|
419
|
+
- **Scegli Intlayer** se desideri **contenuti integrati a livello di componente**, **TypeScript rigoroso**, **errori in fase di build per chiavi mancanti**, **tree-shaking e lazy loading a costo zero**, cambio lingua istantaneo, componenti server sincroni e strumenti editoriali integrati (editor visuale, CMS, traduzione con IA, server MCP). Ideale per codebase modulari e design system.
|
|
420
|
+
- **Scegli gli adattatori `@intlayer/*-i18next`** se utilizzi già i18next e vuoi ottenere vantaggi immediati su bundle e reattività senza riscrivere i componenti.
|
|
421
|
+
|
|
422
|
+
## Confronti correlati
|
|
423
|
+
|
|
424
|
+
- [next-intl vs Intlayer](https://intlayer.org/it/blog/next-intl-vs-intlayer) (stesso benchmark)
|
|
425
|
+
- [Lingui vs Intlayer](https://intlayer.org/it/blog/lingui-vs-intlayer) (stesso benchmark)
|
|
426
|
+
- [vue-i18n vs Intlayer benchmark](https://intlayer.org/it/blog/vue-i18n-vs-intlayer-benchmark) (stesso benchmark)
|
|
427
|
+
- [next-i18next vs next-intl vs Intlayer](https://intlayer.org/it/blog/next-i18next-vs-next-intl-vs-intlayer)
|
|
428
|
+
- [react-i18next vs react-intl vs Intlayer](https://intlayer.org/it/blog/react-i18next-vs-react-intl-vs-intlayer)
|
|
429
|
+
- [i18next è superato?](https://intlayer.org/it/blog/is-i18next-outdated)
|
|
430
|
+
|
|
431
|
+
## Stelle su GitHub
|
|
432
|
+
|
|
433
|
+
Le stelle su GitHub rispecchiano la popolarità, la fiducia della community e la rilevanza a lungo termine di un progetto. Pur non misurando direttamente la qualità tecnica, mostrano quanti sviluppatori apprezzano il progetto, ne seguono gli aggiornamenti e intendono adottarlo.
|
|
434
|
+
|
|
435
|
+
[](https://star-history.com/#i18next/i18next&i18next/react-i18next&i18next/next-i18next&aymericzip/intlayer)
|
|
436
|
+
|
|
437
|
+
## Conclusione
|
|
438
|
+
|
|
439
|
+
`i18next` ha meritato il proprio ruolo di riferimento: funziona ovunque, dispone di plugin per ogni esigenza ed è supportato da oltre un decennio. Il benchmark dimostra tuttavia il costo di un'architettura focalizzata sul runtime. Il setup comunemente adottato aggiunge **+70-77 KB gzip per pagina**, disperde **~90% dei contenuti di altre pagine** e richiede **più di 100 ms** per un cambio lingua con lazy loading. Raggiungere lo 0% di dispersione è possibile, ma impone un backend, un namespace per route e un mapping manuale continuo, rimanendo comunque **+9-22 KB** sopra Intlayer.
|
|
440
|
+
|
|
441
|
+
Intlayer delega questo lavoro al compilatore. Dizionari per componente, lazy loading per lingua ed eliminazione dei contenuti orfani sono artefatti del build anziché convenzioni da gestire manualmente. Sulla stessa applicazione: **+0.3 KB per pagina**, **0% di dispersione**, componenti **da 3 a 10 volte più leggeri** e cambio lingua in **3-4 ms**.
|
|
442
|
+
|
|
443
|
+
Tutti i dati grezzi, le applicazioni di prova e gli script sono consultabili nel [repository Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom). Puoi verificarli direttamente.
|
|
444
|
+
|
|
445
|
+
Per ulteriori dettagli consulta il documento ['Perché Intlayer?'](https://intlayer.org/it/doc/why).
|
|
@@ -70,7 +70,7 @@ Attività negli ultimi 12 mesi:
|
|
|
70
70
|
| `i18next` core | 2.626 | **259** | Piccoli aggiornamenti |
|
|
71
71
|
| Intlayer | 7.156 | **4.343** | Compilatore, tooling IDE e motore IA |
|
|
72
72
|
|
|
73
|
-
[](https://
|
|
73
|
+
[](https://star-history.com/#i18next/i18next&i18next/react-i18next&i18next/next-i18next&aymericzip/intlayer)
|
|
74
74
|
|
|
75
75
|
Una libreria snella può essere solida e affidabile. Ma gli strumenti di i18n progrediscono costantemente: i bundler odierni eliminano i testi inutilizzati durante il build, gli LLM traducono direttamente in CI e gli editor si affidano a server di linguaggio (LSP) e agenti IA. L'architettura puramente a runtime di i18next limita queste possibilità.
|
|
76
76
|
|
|
@@ -66,7 +66,7 @@ Attività negli ultimi 12 mesi:
|
|
|
66
66
|
- `amannn/next-intl`: **187 commit** (aggiornamenti di dipendenze e piccole correzioni).
|
|
67
67
|
- `aymericzip/intlayer`: **4.343 commit** (sviluppo attivo su compilatori, estensioni IDE, server MCP e motori di traduzione).
|
|
68
68
|
|
|
69
|
-
[](https://
|
|
69
|
+
[](https://star-history.com/#amannn/next-intl&aymericzip/intlayer)
|
|
70
70
|
|
|
71
71
|
Una libreria matura può risultare stabile. Tuttavia, l'i18n frontend si è trasformata: i compilatori escludono i testi superflui in fase di build, i modelli LLM automatizzano le traduzioni in CI e gli ambienti di sviluppo sfruttano Language Server (LSP) e agenti intelligenti. Un'architettura basata sul runtime difficilmente recepisce tali vantaggi.
|
|
72
72
|
|
|
@@ -64,7 +64,7 @@ Attività negli ultimi 12 mesi:
|
|
|
64
64
|
- `intlify/vue-i18n`: **259 commit** (manutenzione ordinaria per Vue 3 e Nuxt).
|
|
65
65
|
- `aymericzip/intlayer`: **4.343 commit** (ottimizzazioni di compilazione, integrazioni LSP e supporto ad agenti IA).
|
|
66
66
|
|
|
67
|
-
[](https://
|
|
67
|
+
[](https://star-history.com/#intlify/vue-i18n&aymericzip/intlayer)
|
|
68
68
|
|
|
69
69
|
Una libreria matura assicura affidabilità. Tuttavia le architetture odierne impiegano trasformazioni AST al build, eliminazione di codice morto e automazione con IA. Un'impostazione incentrata unicamente sul runtime fa fatica ad adottare questi paradigmi.
|
|
70
70
|
|