@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,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-13
|
|
3
|
+
updatedAt: 2026-09-13
|
|
4
|
+
title: "i18next vs @intlayer/i18next: To samo API, inny bundle"
|
|
5
|
+
description: "Co się zmienia, gdy aplikacja React lub Next.js zachowuje wywołania i18next, react-i18next i next-i18next, ale obsługuje je za pośrednictwem adapterów @intlayer/i18next. JavaScript na stronę, rozmiar komponentów, wycieki i hydratacja zmierzone na tym samym kodzie, a także co adaptery zachowują, ignorują i czego nie mogą zastąpić."
|
|
6
|
+
keywords:
|
|
7
|
+
- i18next
|
|
8
|
+
- react-i18next
|
|
9
|
+
- next-i18next
|
|
10
|
+
- "@intlayer/i18next"
|
|
11
|
+
- "@intlayer/react-i18next"
|
|
12
|
+
- "@intlayer/next-i18next"
|
|
13
|
+
- Intlayer
|
|
14
|
+
- Adapter kompatybilności
|
|
15
|
+
- Migracja
|
|
16
|
+
- Internacjonalizacja
|
|
17
|
+
- i18n
|
|
18
|
+
- Benchmark
|
|
19
|
+
- Rozmiar bundle
|
|
20
|
+
- Blog
|
|
21
|
+
- Next.js
|
|
22
|
+
- React
|
|
23
|
+
slugs:
|
|
24
|
+
- blog
|
|
25
|
+
- i18next-vs-intlayer-i18next
|
|
26
|
+
author: aymericzip
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
# i18next VS @intlayer/i18next | To samo API, inny bundle
|
|
30
|
+
|
|
31
|
+
`@intlayer/i18next`, `@intlayer/react-i18next` i `@intlayer/next-i18next` to adaptery kompatybilności. Udostępniają API `i18next`, którego Twój kod już używa (`useTranslation`, `t()`, `<Trans>`, `i18n.changeLanguage()`, `getFixedT`, `serverSideTranslations`...) i obsługują je ze słowników skompilowanych przez Intlayer. Komponenty się nie zmieniają. Zmienia się runtime pod nimi.
|
|
32
|
+
|
|
33
|
+
Ten artykuł mierzy tę zamianę na tej samej aplikacji Next.js, zbudowanej raz z `next-i18next`, a raz z `@intlayer/next-i18next`. Liczby pochodzą z [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom). Aby porównać `i18next` i Intlayer jako biblioteki, przeczytaj [i18next vs Intlayer](https://intlayer.org/pl/blog/i18next-vs-intlayer). Ten artykuł dotyczy tego, co zmienia adapter, gdy zachowujesz swój kod bez zmian.
|
|
34
|
+
|
|
35
|
+
<TOC/>
|
|
36
|
+
|
|
37
|
+
> **tl;dr**: W tej samej aplikacji Next.js zastąpienie `next-i18next` przez `@intlayer/next-i18next` zmniejszyło ilość kodu JavaScript na stronę z **218.5 KB do 150.7 KB** gzip (konfiguracja naiwna) i pokonało w pełni zoptymalizowaną konfigurację `next-i18next` (163.4 KB) o **12.7 KB**. Średni komponent zmniejszył się z **78.5 KB do 9.7 KB**, wyciek ciągów znaków z obcych stron z **~90% do 0%**, hydratacja z **15.6 ms do 11.3 ms**, a runtime z **19.7 KB do 9.4 KB**. Żaden komponent nie był modyfikowany; zmieniono jeden plik dostawcy (provider). Wtyczki `i18next` (backendy, detektory języka) są akceptowane, ale nic nie robią: w środowisku wykonawczym nie ma już nic do załadowania ani wykrycia.
|
|
38
|
+
|
|
39
|
+
## Czym jest `@intlayer/i18next`
|
|
40
|
+
|
|
41
|
+
`i18next` to środowisko wykonawcze (runtime). `i18n.init({ resources })` lub wtyczka backendu ładuje `locales/{lng}/{ns}.json` do globalnej instancji; `useTranslation("about")` subskrybuje do niej komponent; `t("title")` wyszukuje klucz podczas renderowania. Przestrzenie nazw (namespaces), leniwe ładowanie (lazy loading), listy przestrzeni nazw na stronę i bezpieczeństwo typów pozostają w Twojej gestii do skonfigurowania i utrzymania.
|
|
42
|
+
|
|
43
|
+
Adaptery zachowują API i zastępują instancję:
|
|
44
|
+
|
|
45
|
+
1. **Aliasy importów.** `createNextI18nPlugin()` z `@intlayer/next-i18next/plugin` (lub `withI18next`) opakowuje `withIntlayer` i dodaje aliasy Webpack / Turbopack, dzięki czemu `next-i18next`, `react-i18next` i `i18next` wskazują na ich odpowiedniki `@intlayer/*`. W Vite `reactI18nextVitePlugin()` z `@intlayer/react-i18next/plugin` robi to samo. Żaden import nie jest zmieniany.
|
|
46
|
+
2. **JSON jako źródło prawdy.** Wtyczka `syncJSON` odczytuje istniejące pliki `locales/{lng}/{ns}.json` z `format: "i18next"` (dzięki czemu `{{name}}`, zagnieżdżanie `$t()`, sufiksy `_one` / `_other` oraz konteksty są poprawnie parsowane) i zapisuje tłumaczenia z powrotem, gdy CLI lub CMS je zaktualizuje.
|
|
47
|
+
3. **Wiązanie w miejscu wywołania (call-site binding).** Krok optymalizacji Intlayer przepisuje `useTranslation("about")` na wywołanie, które otrzymuje słownik `about` bezpośrednio, w aktywnym języku. Komponent przestaje odwoływać się do globalnego magazynu.
|
|
48
|
+
|
|
49
|
+
```tsx fileName="components/About.tsx"
|
|
50
|
+
// Twój kod, bez zmian
|
|
51
|
+
import { useTranslation } from "react-i18next";
|
|
52
|
+
|
|
53
|
+
const About = () => {
|
|
54
|
+
const { t } = useTranslation("about");
|
|
55
|
+
return <h1>{t("title")}</h1>;
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```tsx fileName="Co generuje kompilator (uproszczone)"
|
|
60
|
+
import _dicHash_about from "../.intlayer/dictionaries/about.mjs";
|
|
61
|
+
import { useDictionary as useTranslation } from "@intlayer/react-i18next";
|
|
62
|
+
|
|
63
|
+
const About = () => {
|
|
64
|
+
const { t } = useTranslation(_dicHash_about);
|
|
65
|
+
return <h1>{t("title")}</h1>;
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
To przepisanie wpływa bezpośrednio na kolumny rozmiaru komponentów i wycieków stron poniżej.
|
|
70
|
+
|
|
71
|
+
## Co adaptery zachowują, ignorują i czego nie zastępują
|
|
72
|
+
|
|
73
|
+
| API `i18next` | Z `@intlayer/*` |
|
|
74
|
+
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `useTranslation("ns")`, `useTranslation("ns", { keyPrefix })` | ✅ Zachowane. Powiązane ze słownikiem `ns` w czasie budowania; klucze typowane na podstawie zawartości |
|
|
76
|
+
| `t("key", { name })`, `{{interpolation}}`, zagnieżdżanie `$t(key)` | ✅ Zachowane |
|
|
77
|
+
| Liczba mnoga `key_one` / `key_other`, kontekst `key_male`, `returnObjects` | ✅ Zachowane. Liczby mnogie ewaluowane za pomocą `Intl.PluralRules` |
|
|
78
|
+
| `<Trans>` z `components`, numerowane tagi `<1>...</1>`, `values` | ✅ Zachowane |
|
|
79
|
+
| `withTranslation`, `Translation`, `I18nContext` | ✅ Zachowane |
|
|
80
|
+
| `i18n.changeLanguage()`, `i18n.language`, `i18n.dir()`, `on("languageChanged")` | ✅ Zachowane. `changeLanguage` steruje językiem Intlayer |
|
|
81
|
+
| `getFixedT(lng, ns, keyPrefix)`, `i18n.exists()`, `hasLoadedNamespace()` | ✅ Zachowane |
|
|
82
|
+
| `i18n.use(Backend).use(LanguageDetector).init({...})` | ⚠️ `use()` wywołuje `init` wtyczki i zwraca wynik; backendy i detektory nie mają nic do załadowania ani wykrycia |
|
|
83
|
+
| `init({ resources })`, `addResourceBundle()` | ⚠️ `resources` jest **ignorowane** z ostrzeżeniem dev; usuń importy JSON, aby uzyskać korzyści w bundle |
|
|
84
|
+
| `I18nextProvider i18n={i18n}` | ⚠️ Renderuje `IntlayerProvider`; właściwość `i18n` jest ignorowana. W App Router przekaż locale (patrz poniżej) |
|
|
85
|
+
| `serverSideTranslations(locale, ["common"])` (next-i18next) | ⚠️ Zwraca oczekiwany kształt i niczego nie ładuje. Bezpieczne do pozostawienia lub usunięcia |
|
|
86
|
+
| `appWithTranslation(App)` (next-i18next) | ✅ Zachowane |
|
|
87
|
+
| `next-i18next.config.js` | ⚠️ Nieodczytywane. Języki pochodzą z `intlayer.config.ts` |
|
|
88
|
+
| Zwykłe `useTranslation()` bez przestrzeni nazw | ✅ Działa względem słownika `translation` dla całego pliku (`splitKeys: false`) |
|
|
89
|
+
|
|
90
|
+
## Benchmark
|
|
91
|
+
|
|
92
|
+
### Co mierzono
|
|
93
|
+
|
|
94
|
+
Zestaw [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) buduje **tę samą aplikację** w każdej konfiguracji: **10 stron** (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), **10 języków** (`en`, `fr`, `es`, `de`, `it`, `pt`, `zh`, `ja`, `ko`, `ru`), identyczne komponenty i identyczna zawartość. Strony są mierzone w `en` i `fr`.
|
|
95
|
+
|
|
96
|
+
`next-i18next` zbudowano w czterech strategiach ładowania, od importu JSON każdego języka do `resources` (`static`) po jedną przestrzeń nazw na trasę, ładowaną leniwie przez backend (`scoped-dynamic`). Adapter zbudowano na **tych samych komponentach co konfigurację naiwną**, ze zmienionymi plikami `next.config.ts`, `intlayer.config.ts` oraz plikiem providera. Nie ma wariantu "scoped": kompilator sam ogranicza zasięg zawartości na komponent.
|
|
97
|
+
|
|
98
|
+
Dla każdego buildu zestaw rejestruje:
|
|
99
|
+
|
|
100
|
+
- **Lib size**: rozmiar gzip pustego komponentu, który importuje tylko bibliotekę i18n.
|
|
101
|
+
- **Page JS**: pobrany JavaScript gzip na stronę, uśredniony dla wszystkich stron i języków.
|
|
102
|
+
- **Locale leak %**: udział przetłumaczonych ciągów w pobranym JS należących do języka, którego użytkownik **nie** przegląda.
|
|
103
|
+
- **Page leak %**: udział przetłumaczonych ciągów w pobranym JS należących do strony, na której użytkownik **nie** przebywa.
|
|
104
|
+
- **Component avg**: średni rozmiar gzip każdego komponentu skompilowanego w izolacji.
|
|
105
|
+
- **E2E reactivity**: rzeczywisty czas między wyborem nowego języka a aktualizacją `html[lang]` w DOM (Playwright, 5 iteracji).
|
|
106
|
+
- **Hydration**: czas trwania fazy hydratacji React.
|
|
107
|
+
|
|
108
|
+
> Poniższe liczby pochodzą z uruchomienia z dnia **2026-09-12** z `next-i18next` 16.3.0 (`react-i18next` 17.0.13, `i18next` 26.4.2) oraz `@intlayer/next-i18next` 9.5.1. Aplikacja testowa jest celowo niewielka (kilkadziesiąt ciągów na język), więc wartości procentowe wycieków opisują **wzorzec**: rosną one wraz z zawartością, podczas gdy koszt runtime pozostaje stały.
|
|
109
|
+
|
|
110
|
+
### Wyniki w Next.js
|
|
111
|
+
|
|
112
|
+
| Konfiguracja | Strategia | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Hydration |
|
|
113
|
+
| ---------------------------- | -------------- | ------------: | ---------------: | ----------: | --------: | -----------------: | -------------: | ----------: |
|
|
114
|
+
| **base** (brak i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
|
|
115
|
+
| `next-i18next` | static | 19.7 KB | 218.5 KB | 0.0% | 89.8% | 78.5 KB | 16.4 ms | 15.6 ms |
|
|
116
|
+
| `next-i18next` | dynamic | 19.7 KB | 169.5 KB | 50.0% | 89.8% | 26.1 KB | 15.4 ms | 27.7 ms |
|
|
117
|
+
| `next-i18next` | scoped-static | 19.7 KB | 220.1 KB | 0.0% | 89.8% | 78.9 KB | 16.4 ms | 14.7 ms |
|
|
118
|
+
| `next-i18next` | scoped-dynamic | 19.7 KB | 163.4 KB | 0.0% | 0.0% | 27.1 KB | 15.9 ms | 15.1 ms |
|
|
119
|
+
| **`@intlayer/next-i18next`** | static | **9.4 KB** | **150.7 KB** | **0.0%** | **0.0%** | **9.7 KB** | **10.7 ms** | **11.3 ms** |
|
|
120
|
+
| **`@intlayer/next-i18next`** | dynamic | **9.4 KB** | **150.7 KB** | **0.0%** | **0.0%** | **9.7 KB** | **11.9 ms** | **10.6 ms** |
|
|
121
|
+
| `next-intlayer` (natywny) | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
|
|
122
|
+
| `next-intlayer` (natywny) | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
|
|
123
|
+
|
|
124
|
+
**Jak to interpretować**
|
|
125
|
+
|
|
126
|
+
- **68 KB mniej na stronę względem konfiguracji naiwnej.** `resources: { en, fr, ... }` wysyła każdy język i każdą przestrzeń nazw na każdej stronie: **218.5 KB**. Build adaptera dla tych samych komponentów osiąga **150.7 KB**. Pokonuje również najlepszą konfigurację `next-i18next` (163.4 KB, jedna przestrzeń nazw na trasę, ładowana leniwie) o 12.7 KB, ponieważ sam runtime `i18next` waży 19.7 KB w porównaniu do 9.4 KB.
|
|
127
|
+
- **Wyciek spada do 0% bez dotykania jakiegokolwiek komponentu.** Każda konfiguracja `next-i18next` z wyjątkiem w pełni wyizolowanej (scoped) wysyła ~90% ciągów z obcych stron. Wiersz `dynamic` wygląda gorzej niż w teorii: wcale nie eliminuje wycieku stron i dodaje **50% wycieku języków**, ponieważ backend dla danego języka nadal pobiera całą przestrzeń nazw `translation`. Adapter osiąga 0% / 0% z poziomu naiwnego kodu.
|
|
128
|
+
- **Komponenty: 8-krotnie mniejsze.** Komponent `useTranslation()` skompilowany w izolacji waży średnio **78.5 KB** przy wbudowanych `resources` oraz **26-27 KB** z backendem, ponieważ `t` jest powiązane z globalnym magazynem. Z adapterem osiąga średnio **9.7 KB**.
|
|
129
|
+
- **Hydratacja i przełączanie są szybsze.** Hydratacja przyspiesza z 15.6 ms do **11.3 ms** (oraz z 27.7 ms w konfiguracji `dynamic`, gdzie pobieranie z backendu znajduje się na ścieżce krytycznej). Przełączanie języka przyspiesza z 15-16 ms do **11-12 ms**.
|
|
130
|
+
- **Adapter to nie natywny runtime.** `next-intlayer` osiąga **141.3 KB**, czyli +0.3 KB względem bazowej aplikacji. Adapter wnosi powierzchnię API `i18next` (dialekt interpolacji, rozwiązywanie sufiksów liczby mnogiej i kontekstu, parsowanie tagów `<Trans>`) na wierzchu rdzenia Intlayer: 9.4 KB i +9.4 KB na stronę ponad natywną implementację. To pomost, a nie ostateczny cel.
|
|
131
|
+
|
|
132
|
+
> Adapter `react-i18next` w Vite / TanStack Start nie brał udziału w tym uruchomieniu. Wartość bazowa `react-i18next` w TanStack Start znajduje się w [i18next vs Intlayer](https://intlayer.org/pl/blog/i18next-vs-intlayer): 127-184 KB na stronę i 123-185 ms przełączania języka przy leniwym backendzie.
|
|
133
|
+
|
|
134
|
+
## Dlaczego liczby się zmieniają
|
|
135
|
+
|
|
136
|
+
W katalogu `components/` nic się nie zmieniło, więc zyski wynikają z tego, z czym powiązane jest `useTranslation`.
|
|
137
|
+
|
|
138
|
+
**W przypadku `i18next`** powiązaniem jest instancja globalna. Cokolwiek zostało do niej załadowane (wszystkie języki w `static`, cała przestrzeń nazw aktywnego języka w `dynamic`), jest dostępne z każdego komponentu wywołującego `useTranslation()`. Bundler nie może dokonać podziału poniżej tego, co zawiera instancja, a runtime nie może wiedzieć, o które klucze zapyta komponent.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
.
|
|
142
|
+
├── next-i18next.config.js
|
|
143
|
+
├── public/locales
|
|
144
|
+
│ ├── en/translation.json # ciągi znaków dla każdej strony
|
|
145
|
+
│ └── fr/translation.json
|
|
146
|
+
├── i18n/i18n.ts # i18n.use(initReactI18next).init({ resources })
|
|
147
|
+
└── components
|
|
148
|
+
├── AppProviders.tsx # <I18nextProvider i18n={i18n}>
|
|
149
|
+
└── About.tsx # useTranslation(); t("about.title")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**W przypadku `@intlayer/next-i18next`** powiązaniem jest słownik. `syncJSON` przekształca każdy plik przestrzeni nazw w słownik; krok optymalizacji przekazuje komponentowi słownik, do którego się odwołuje, jako import, który bundler może śledzić i dzielić według stron i języków.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
.
|
|
156
|
+
├── intlayer.config.ts # syncJSON({ format: "i18next", source: ... })
|
|
157
|
+
├── public/locales
|
|
158
|
+
│ ├── en/translation.json # bez zmian, nadal źródło prawdy
|
|
159
|
+
│ └── fr/translation.json
|
|
160
|
+
├── .intlayer/ # wygenerowane: jeden słownik na przestrzeń nazw, na język
|
|
161
|
+
└── components
|
|
162
|
+
├── AppProviders.tsx # <IntlayerClientProvider locale={locale}>
|
|
163
|
+
└── About.tsx # useTranslation(); t("about.title") ← bez zmian
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`i18n/i18n.ts` i jego import `resources` stają się martwym kodem. To właśnie te 68 KB.
|
|
167
|
+
|
|
168
|
+
## Migracja w trzech krokach
|
|
169
|
+
|
|
170
|
+
<Steps>
|
|
171
|
+
<Step number={1} title="Instalacja">
|
|
172
|
+
|
|
173
|
+
```bash packageManager="npm"
|
|
174
|
+
npx intlayer init --interactive
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```bash packageManager="pnpm"
|
|
178
|
+
pnpm dlx intlayer init --interactive
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```bash packageManager="yarn"
|
|
182
|
+
yarn dlx intlayer init --interactive
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```bash packageManager="bun"
|
|
186
|
+
bunx intlayer init --interactive
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Polecenie wykrywa `i18next` / `react-i18next` / `next-i18next`, instaluje `intlayer`, pakiet frameworka (`next-intlayer` lub `react-intlayer`), pasujący adapter `@intlayer/*` oraz `@intlayer/sync-json-plugin`, a także wstępnie konfiguruje `intlayer.config.ts`. Zachowaj zainstalowane oryginalne pakiety: są to peer dependencies i dostarczają typy.
|
|
190
|
+
|
|
191
|
+
</Step>
|
|
192
|
+
<Step number={2} title="Wskaż Intlayer pliki językowe">
|
|
193
|
+
|
|
194
|
+
```ts fileName="intlayer.config.ts"
|
|
195
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
196
|
+
import { syncJSON } from "@intlayer/sync-json-plugin";
|
|
197
|
+
|
|
198
|
+
const config: IntlayerConfig = {
|
|
199
|
+
internationalization: {
|
|
200
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
201
|
+
defaultLocale: Locales.ENGLISH,
|
|
202
|
+
},
|
|
203
|
+
dictionary: {
|
|
204
|
+
importMode: "dynamic",
|
|
205
|
+
format: "i18next",
|
|
206
|
+
},
|
|
207
|
+
plugins: [
|
|
208
|
+
syncJSON({
|
|
209
|
+
// Dialekt i18next: {{name}}, $t(key), key_one / key_other, key_male
|
|
210
|
+
format: "i18next",
|
|
211
|
+
// Jeden plik na przestrzeń nazw: `useTranslation("about")` → about.json
|
|
212
|
+
source: ({ locale, key }) => `./public/locales/${locale}/${key}.json`,
|
|
213
|
+
location: "public/locales",
|
|
214
|
+
}),
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
export default config;
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Jeśli masz pojedynczy plik `translation.json` na język (domyślna przestrzeń nazw w i18next), ustaw `splitKeys: false`, aby cały plik pozostał jednym słownikiem i zwykłe `useTranslation()` nadal działało.
|
|
222
|
+
|
|
223
|
+
</Step>
|
|
224
|
+
<Step number={3} title="Dodaj wtyczkę">
|
|
225
|
+
|
|
226
|
+
<Tabs>
|
|
227
|
+
<Tab label="Next.js">
|
|
228
|
+
|
|
229
|
+
```ts fileName="next.config.ts"
|
|
230
|
+
import type { NextConfig } from "next";
|
|
231
|
+
import { withI18next } from "@intlayer/next-i18next/plugin";
|
|
232
|
+
|
|
233
|
+
const nextConfig: NextConfig = {};
|
|
234
|
+
|
|
235
|
+
export default withI18next(nextConfig);
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
W App Router komponenty klienckie pobierają swój język z segmentu `[locale]`. Komponent `I18nextProvider` adaptera nie przyjmuje parametru locale, więc zastąp go raz w pliku providera:
|
|
239
|
+
|
|
240
|
+
```tsx fileName="components/AppProviders.tsx"
|
|
241
|
+
"use client";
|
|
242
|
+
|
|
243
|
+
import { IntlayerClientProvider } from "next-intlayer";
|
|
244
|
+
import type { LocalesValues } from "intlayer";
|
|
245
|
+
|
|
246
|
+
export const AppProviders = ({
|
|
247
|
+
locale,
|
|
248
|
+
children,
|
|
249
|
+
}: {
|
|
250
|
+
locale: LocalesValues;
|
|
251
|
+
children: React.ReactNode;
|
|
252
|
+
}) => (
|
|
253
|
+
<IntlayerClientProvider locale={locale}>{children}</IntlayerClientProvider>
|
|
254
|
+
);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Każdy komponent poniżej nadal wywołuje `useTranslation()`.
|
|
258
|
+
|
|
259
|
+
</Tab>
|
|
260
|
+
<Tab label="Vite / TanStack Start">
|
|
261
|
+
|
|
262
|
+
```ts fileName="vite.config.ts"
|
|
263
|
+
import { defineConfig } from "vite";
|
|
264
|
+
import react from "@vitejs/plugin-react";
|
|
265
|
+
import { reactI18nextVitePlugin } from "@intlayer/react-i18next/plugin";
|
|
266
|
+
|
|
267
|
+
export default defineConfig({
|
|
268
|
+
plugins: [react(), reactI18nextVitePlugin()],
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`reactI18nextVitePlugin()` opakowuje `vite-intlayer` i tworzy aliasy dla `react-i18next` i `i18next`. W projekcie bez React `i18nextVitePlugin()` z `@intlayer/i18next/plugin` tworzy alias dla samego `i18next`.
|
|
273
|
+
|
|
274
|
+
</Tab>
|
|
275
|
+
</Tabs>
|
|
276
|
+
|
|
277
|
+
</Step>
|
|
278
|
+
</Steps>
|
|
279
|
+
|
|
280
|
+
### Co można potem usunąć
|
|
281
|
+
|
|
282
|
+
| Plik / wzorzec | Dlaczego |
|
|
283
|
+
| ------------------------------------------------------ | ----------------------------------------------------------------------------------- |
|
|
284
|
+
| `resources: { en, fr, ... }` i importy JSON | Ignorowane przez adapter. To tutaj znajdowało się 68 KB |
|
|
285
|
+
| `i18next-http-backend`, `i18next-resources-to-backend` | Brak danych do pobierania w środowisku wykonawczym |
|
|
286
|
+
| `i18next-browser-languagedetector` | Wykrywanie języka to konfiguracja routingu Intlayer (prefiks URL, cookie, nagłówek) |
|
|
287
|
+
| `serverSideTranslations()` w `getStaticProps` | Zwraca pustą strukturę; nieszkodliwe, ale martwe |
|
|
288
|
+
| `next-i18next.config.js` | Nieodczytywane. Języki znajdują się w `intlayer.config.ts` |
|
|
289
|
+
| Listy `ns: [...]` per strona | Kompilator dobiera przestrzenie nazw na komponent |
|
|
290
|
+
|
|
291
|
+
### Co zyskujesz poza zaoszczędzonymi bajtami
|
|
292
|
+
|
|
293
|
+
- **Typowane klucze.** `useTranslation("about")` jest typowane względem skompilowanego słownika `about`; `t("does.not.exist")` powoduje błąd TypeScript zamiast zwróconego ciągu klucza.
|
|
294
|
+
- **`npx intlayer test`** kończy się błędem w CI w przypadku brakującego klucza w dowolnym języku. **`npx intlayer fill`** tłumaczy brakujące klucze za pomocą Twojego klucza dostawcy (OpenAI, Anthropic, Mistral, Gemini...) i zapisuje je z powrotem do `locales/{lng}/{ns}.json`.
|
|
295
|
+
- **Wizualny Edytor i CMS** operują na tym samym JSON, dzięki czemu tłumacze edytują treści przez interfejs użytkownika, a pliki są aktualizowane.
|
|
296
|
+
- **Stopniowe przejście na `.content.ts`.** Dowolny komponent może przełączyć się z `useTranslation("about")` na `useIntlayer("about")` z plikiem zawartości zlokalizowanym obok komponentu. Słowniki JSON i `.content.ts` współistnieją.
|
|
297
|
+
|
|
298
|
+
## Ograniczenia, które warto znać przed rozpoczęciem
|
|
299
|
+
|
|
300
|
+
- **Backendy i detektory są nieaktywne.** `i18n.use(HttpBackend)` wywołuje `init` wtyczki i nic więcej. Jeśli Twoja aplikacja polegała na pobieraniu tłumaczeń z CMS w czasie wykonywania, ten mechanizm już nie działa; użyj CMS Intlayer lub poleceń `intlayer pull` / `push`.
|
|
301
|
+
- **`resources` jest ignorowane, a nie scalane.** W przeciwieństwie do niektórych innych adapterów, `@intlayer/i18next` nie używa wbudowanych `resources` jako mechanizmu fallback. Każdy klucz musi istnieć w zsynchronizowanych słownikach, co weryfikuje `intlayer test`.
|
|
302
|
+
- **App Router wymaga edycji providera.** Jeden plik, pokazany powyżej. Pages Router z `appWithTranslation` nie wymaga żadnych zmian.
|
|
303
|
+
- **`next-i18next.config.js` nie jest odczytywany.** `localePath`, `fallbackLng`, `reloadOnPrerender` i pokrewne nie mają odpowiedników; języki i fallback pochodzą z `intlayer.config.ts`.
|
|
304
|
+
- **Adapter nie jest darmowy.** 9.4 KB runtime i +9.4 KB na stronę względem `next-intlayer`. Gdy każdy komponent przejdzie na `useIntlayer`, można go usunąć.
|
|
305
|
+
|
|
306
|
+
## Kiedy używać którego rozwiązania?
|
|
307
|
+
|
|
308
|
+
- **Pozostań przy `i18next`**, jeśli Twoja aplikacja zależy od backendów czasu wykonywania (tłumaczenia serwowane przez CMS w momencie żądania), od ekosystemu wtyczek lub od środowiska innego niż React, którego adaptery nie obsługują.
|
|
309
|
+
- **Użyj `@intlayer/*`**, jeśli używasz `react-i18next` / `next-i18next` i zależy Ci na zaoszczędzeniu 68 KB, 8-krotnie mniejszych komponentach, 0% wycieków, typowanych kluczach i testach w CI bez konieczności przepisywania kodu. To idealny punkt wyjścia dla istniejącej bazy kodu `i18next`.
|
|
310
|
+
- **Wybierz rozwiązanie natywne (`next-intlayer` / `react-intlayer`)** dla nowych projektów lub gdy adapter spełnił już swoje zadanie. Jest najlżejszy z całej trójki (5.5 KB, +0.3 KB na stronę) i odblokowuje synchroniczne komponenty serwerowe oraz pliki `.content.ts` powiązane z komponentami.
|
|
311
|
+
|
|
312
|
+
## Powiązane porównania
|
|
313
|
+
|
|
314
|
+
- [i18next vs Intlayer](https://intlayer.org/pl/blog/i18next-vs-intlayer) (biblioteki, ten sam benchmark)
|
|
315
|
+
- [next-intl vs @intlayer/next-intl](https://intlayer.org/pl/blog/next-intl-vs-intlayer-next-intl) (ta sama seria adapterów)
|
|
316
|
+
- [Lingui vs @intlayer/lingui](https://intlayer.org/pl/blog/lingui-vs-intlayer-lingui) (ta sama seria adapterów)
|
|
317
|
+
- [vue-i18n vs @intlayer/vue-i18n](https://intlayer.org/pl/blog/vue-i18n-vs-intlayer-vue-i18n) (ta sama seria adapterów)
|
|
318
|
+
- Przewodniki migracji: [i18next](https://intlayer.org/pl/doc/migration/i18next), [react-i18next](https://intlayer.org/pl/doc/migration/react-i18next), [next-i18next](https://intlayer.org/pl/doc/migration/next-i18next)
|
|
319
|
+
- Dokumentacja adapterów kompatybilności: [i18next](https://intlayer.org/pl/doc/compatibility/i18next), [react-i18next](https://intlayer.org/pl/doc/compatibility/react-i18next), [next-i18next](https://intlayer.org/pl/doc/compatibility/next-i18next)
|
|
320
|
+
|
|
321
|
+
## Podsumowanie
|
|
322
|
+
|
|
323
|
+
`i18next` to najcięższy runtime w tym benchmarku, a adaptery usuwają większość z niego bez konieczności rezygnacji z jego API. Na tej samej aplikacji Next.js oznacza to **68 KB mniej na stronę** niż w konfiguracji naiwnej, **12.7 KB mniej** niż w najlepiej zoptymalizowanej ręcznie, **8x mniejsze komponenty**, **0% wycieków** oraz **4 ms szybszą hydratację**, w zamian za plik konfiguracyjny, jedną linijkę wtyczki i zmianę w jednym providerze. Backendy i detektory stają się operacjami no-op, `resources` jest ignorowane zamiast scalane, a natywny runtime `next-intlayer` pozostaje o kolejne 9 KB lżejszy.
|
|
324
|
+
|
|
325
|
+
Wszystkie surowe dane, aplikacje testowe i skrypty znajdują się w [repozytorium Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom). Uruchom je samodzielnie.
|
|
326
|
+
|
|
327
|
+
Więcej szczegółów znajdziesz w dokumentacji [Dlaczego Intlayer?](https://intlayer.org/pl/doc/why).
|