@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
package/README.md
CHANGED
|
@@ -328,4 +328,4 @@ Contribute on [GitHub](https://github.com/aymericzip/intlayer), [GitLab](https:/
|
|
|
328
328
|
|
|
329
329
|
If you like Intlayer, give us a ⭐ on GitHub. It helps others discover the project! [See why GitHub Stars matter](https://github.com/aymericzip/intlayer/blob/main/CONTRIBUTING.md#why-github-stars-matter-).
|
|
330
330
|
|
|
331
|
-
[](https://
|
|
331
|
+
[](https://star-history.com/#aymericzip/intlayer&Date)
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-13
|
|
3
|
+
updatedAt: 2026-09-13
|
|
4
|
+
title: "مقارنة i18next مقابل @intlayer/i18next: نفس واجهة البرمجة (API)، وحزمة برمجية مختلفة تماماً"
|
|
5
|
+
description: "ما الذي يتغير عندما يحتفظ تطبيق React أو Next.js باستدعاءات i18next و react-i18next و next-i18next ولكنه يخدمها من خلال محولات @intlayer/i18next. قياسات حجم JavaScript لكل صفحة، وحجم المكونات، وتسريب النصوص، والترطيب على نفس الشيفرة البرمجية."
|
|
6
|
+
keywords:
|
|
7
|
+
- i18next
|
|
8
|
+
- react-i18next
|
|
9
|
+
- next-i18next
|
|
10
|
+
- "@intlayer/i18next"
|
|
11
|
+
- "@intlayer/react-i18next"
|
|
12
|
+
- "@intlayer/next-i18next"
|
|
13
|
+
- Intlayer
|
|
14
|
+
- محول التوافق
|
|
15
|
+
- هجرة
|
|
16
|
+
- تدويل
|
|
17
|
+
- i18n
|
|
18
|
+
- اختبار الأداء
|
|
19
|
+
- حجم الحزمة
|
|
20
|
+
- مدونة
|
|
21
|
+
- Next.js
|
|
22
|
+
- React
|
|
23
|
+
slugs:
|
|
24
|
+
- blog
|
|
25
|
+
- i18next-vs-intlayer-i18next
|
|
26
|
+
author: aymericzip
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
# مقارنة i18next مقابل @intlayer/i18next | نفس واجهة البرمجة (API)، وحزمة برمجية مختلفة تماماً
|
|
30
|
+
|
|
31
|
+
تُعد `@intlayer/i18next` و `@intlayer/react-i18next` و `@intlayer/next-i18next` محولات توافقية. إنها توفر نفس واجهة برمجة التطبيقات (API) الخاصة بـ `i18next` التي تستخدمها بالفعل في شيفرتك البرمجية (`useTranslation`، `t()`، `<Trans>`، `i18n.changeLanguage()`، `getFixedT`، `serverSideTranslations`...) وتقدمها من خلال قواميس مبنية ومترجمة بواسطة Intlayer. المكونات لا تتغير إطلاقاً، بل إن بيئة التشغيل الأساسية تحتها هي التي تتغير.
|
|
32
|
+
|
|
33
|
+
يقيس هذا المقال ذلك الاستبدال على نفس تطبيق Next.js، حيث تم بناؤه مرة باستخدام `next-i18next` ومرة أخرى باستخدام `@intlayer/next-i18next`. الأرقام مأخوذة من مشروع [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom). للمقارنة بين `i18next` و Intlayer كمكتبات مستقلة، يرجى قراءة [مقارنة i18next مقابل Intlayer](https://intlayer.org/ar/blog/i18next-vs-intlayer). أما هذا المقال، فيركز على ما يغيره المحول عندما تحتفظ بشيفرتك البرمجية كما هي.
|
|
34
|
+
|
|
35
|
+
<TOC/>
|
|
36
|
+
|
|
37
|
+
> **ملخص سريع (tl;dr)**: في نفس تطبيق Next.js، أدى استبدال `next-i18next` بـ `@intlayer/next-i18next` إلى خفض حجم JavaScript المضغوط (gzip) لكل صفحة من **218.5 كيلوبايت إلى 150.7 كيلوبايت** (في التكوين الأولي البسيط) وتفوق على تكوين `next-i18next` المحسّن بالكامل (163.4 كيلوبايت) بفارق **12.7 كيلوبايت**. وانخفض متوسط حجم المكون من **78.5 كيلوبايت إلى 9.7 كيلوبايت**، وتراجع تسريب نصوص الصفحات غير المعروضة من **~90% إلى 0%**، وانخفض وقت الترطيب (hydration) من **15.6 مللي ثانية إلى 11.3 مللي ثانية**، وتراجع حجم بيئة التشغيل من **19.7 كيلوبايت إلى 9.4 كيلوبايت**. لم يتم تعديل أي مكون؛ تم تعديل ملف مزود واحد فقط. يتم قبول إضافات `i18next` (مثل الخلفيات وكواشف اللغة) ولكنها لا تفعل شيئاً: لا يوجد شيء إضافي ليتم تحميله أو اكتشافه في وقت التشغيل.
|
|
38
|
+
|
|
39
|
+
## ما هو `@intlayer/i18next`
|
|
40
|
+
|
|
41
|
+
`i18next` هي بيئة تشغيل runtime. تقوم الدالة `i18n.init({ resources })` أو إضافة الواجهة الخلفية بتحميل ملفات `locales/{lng}/{ns}.json` في كائن عام (global instance)؛ وتقوم `useTranslation("about")` بربط المكون به؛ وتقوم `t("title")` بالبحث عن المفتاح أثناء التصيير. تقع على عاتقك مسؤولية ضبط وإدارة مساحات الأسماء والتحميل الكسول وقوائم مساحات الأسماء لكل صفحة وسلامة الأنواع.
|
|
42
|
+
|
|
43
|
+
تحافظ المحولات على نفس واجهة البرمجة وتستبدل الكائن العام:
|
|
44
|
+
|
|
45
|
+
1. **الأسماء المستعارة للاستيراد (Import Aliasing).** تقوم `createNextI18nPlugin()` من حزمة `@intlayer/next-i18next/plugin` (أو `withI18next`) بتغليف `withIntlayer` وإضافة أسماء مستعارة لـ Webpack / Turbopack بحيث يتم توجيه استيرادات `next-i18next` و `react-i18next` و `i18next` إلى نظيراتها في `@intlayer/*`. وفي Vite، تؤدي `reactI18nextVitePlugin()` من حزمة `@intlayer/react-i18next/plugin` نفس الغرض. لا حاجة لتغيير أي عبارة استيراد.
|
|
46
|
+
2. **اعتماد JSON كمصدر وحيد للحقيقة.** يقرأ ملحق `syncJSON` ملفاتك الحالية `locales/{lng}/{ns}.json` مع إعداد `format: "i18next"` (بحيث يتم تحليل `{{name}}` وتداخل `$t()` وصيغ `_one` / `_other` وسياقات النصوص بدقة) ويكتب الترجمات مرة أخرى عندما تقوم واجهة الأوامر CLI أو نظام إدارة المحتوى CMS بتحديثها.
|
|
47
|
+
3. **الربط عند نقطة الاستدعاء.** تقوم مرحلة التحسين في Intlayer بإعادة كتابة `useTranslation("about")` لتصبح استدعاءً يستلم مباشرة قاموس `about` في اللغة النشطة. يتوقف المكون تماماً عن الوصول إلى المخزن العام.
|
|
48
|
+
|
|
49
|
+
```tsx fileName="components/About.tsx"
|
|
50
|
+
// الشيفرة البرمجية الخاصة بك، بدون أي تغيير
|
|
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="ما يخرجه المترجم (صيغة مبسطة)"
|
|
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
|
+
هذه الإعادة في الكتابة هي المسؤولة عن تقليص حجم المكونات والقضاء التام على تسريب نصوص الصفحات في النتائج التالية.
|
|
70
|
+
|
|
71
|
+
## ما تحتفظ به المحولات، وما تتجاهله، وما لا يمكنها استبداله
|
|
72
|
+
|
|
73
|
+
| واجهة برمجة `i18next` | مع حزم `@intlayer/*` |
|
|
74
|
+
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `useTranslation("ns")`, `useTranslation("ns", { keyPrefix })` | ✅ تم الاحتفاظ بها. مرتبطة بقاموس `ns` وقت البناء؛ ومفحوصة الأنواع وفق محتواك |
|
|
76
|
+
| `t("key", { name })`, `{{interpolation}}`, تداخل `$t(key)` | ✅ تم الاحتفاظ بها |
|
|
77
|
+
| صيغ الجمع `key_one` / `key_other`, سياق `key_male`, `returnObjects` | ✅ تم الاحتفاظ بها. تُحسب صيغ الجمع باستخدام `Intl.PluralRules` |
|
|
78
|
+
| `<Trans>` مع `components`، والوسوم المرقمة `<1>...</1>`، و `values` | ✅ تم الاحتفاظ بها |
|
|
79
|
+
| `withTranslation`, `Translation`, `I18nContext` | ✅ تم الاحتفاظ بها |
|
|
80
|
+
| `i18n.changeLanguage()`, `i18n.language`, `i18n.dir()`, `on("languageChanged")` | ✅ تم الاحتفاظ بها. تقود `changeLanguage` لغة Intlayer |
|
|
81
|
+
| `getFixedT(lng, ns, keyPrefix)`, `i18n.exists()`, `hasLoadedNamespace()` | ✅ تم الاحتفاظ بها |
|
|
82
|
+
| `i18n.use(Backend).use(LanguageDetector).init({...})` | ⚠️ تقوم `use()` باستدعاء `init` للملحق ثم تنتهي؛ لا يوجد شيء لتحميله أو اكتشافه في الخلفيات |
|
|
83
|
+
| `init({ resources })`, `addResourceBundle()` | ⚠️ يتم **تجاهل** `resources` مع إظهار تحذير في بيئة التطوير؛ احذف استيرادات JSON للحصول على فوائد تصغير الحزمة |
|
|
84
|
+
| `I18nextProvider i18n={i18n}` | ⚠️ تقوم بتصيير `IntlayerProvider`؛ ويتم تجاهل خاصية `i18n`. في App Router، مرر اللغة مباشرة (انظر أدناه) |
|
|
85
|
+
| `serverSideTranslations(locale, ["common"])` (next-i18next) | ⚠️ تعيد الهيكل المتوقع ولا تقوم بتحميل أي شيء. آمنة للإبقاء، وآمنة للحذف |
|
|
86
|
+
| `appWithTranslation(App)` (next-i18next) | ✅ تم الاحتفاظ بها |
|
|
87
|
+
| `next-i18next.config.js` | ⚠️ لا يتم قراءتها. يتم ضبط اللغات في ملف `intlayer.config.ts` |
|
|
88
|
+
| استدعاء `useTranslation()` البسيط بدون مساحة أسماء | ✅ يعمل بالاعتماد على قاموس `translation` الكامل للملف (`splitKeys: false`) |
|
|
89
|
+
|
|
90
|
+
## اختبار الأداء المقارن
|
|
91
|
+
|
|
92
|
+
### ما تم قياسه
|
|
93
|
+
|
|
94
|
+
تقوم حزمة [Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom) ببناء **نفس التطبيق تماماً** في كل إعداد: **10 صفحات** (الرئيسية، من نحن، المدونة، الوظائف، اتصل بنا، الأسئلة الشائعة، الأسعار، المنتجات، الإعدادات، الفريق)، و **10 لغات** (`en`, `fr`, `es`, `de`, `it`, `pt`, `zh`, `ja`, `ko`, `ru`)، ومكونات ومحتوى متطابق تماماً. تم قياس الصفحات في اللغتين الإنجليزية والفرنسية.
|
|
95
|
+
|
|
96
|
+
تم اختبار `next-i18next` عبر أربع استراتيجيات تحميل، بدءاً من استيراد ملفات JSON لجميع اللغات مباشرة في `resources` (`static`) إلى تقسيم مساحات الأسماء لكل مسار مع التحميل الكسول عبر واجهة خلفية (`scoped-dynamic`). بينما تم بناء المحول على **نفس مكونات الإعداد الأولي البسيط**، مع تعديل ملفات `next.config.ts` و `intlayer.config.ts` وملف المزود فقط. لا يحتاج المحول إلى تقسيم يدوي: يتولى المترجم تخصيص نطاق المحتوى لكل مكون تلقائياً.
|
|
97
|
+
|
|
98
|
+
سجل الاختبار لكل بناء:
|
|
99
|
+
|
|
100
|
+
- **حجم المكتبة**: حجم gzip لمكون فارغ يستورد مكتبة i18n فقط.
|
|
101
|
+
- **حجم JS لكل صفحة**: متوسط ملفات JavaScript المنزلة لكل صفحة عبر جميع اللغات والصفحات (gzip).
|
|
102
|
+
- **نسبة تسريب اللغات**: نسبة السلاسل النصية المترجمة في ملف JS المنزّل والتي تنتمي إلى لغة **لا** يشاهدها المستخدم حالياً.
|
|
103
|
+
- **نسبة تسريب الصفحات**: نسبة السلاسل النصية المترجمة في ملف JS المنزّل والتي تنتمي إلى صفحة **لا** يتواجد فيها المستخدم حالياً.
|
|
104
|
+
- **متوسط حجم المكون**: متوسط حجم gzip لكل مكون تم تجميعه بشكل معزول.
|
|
105
|
+
- **تفاعلية E2E**: الوقت الفعلي المستغرق بين اختيار لغة جديدة وتحديث سمة `html[lang]` في صفحة الويب (Playwright، عبر 5 تكرارات).
|
|
106
|
+
- **الترطيب (Hydration)**: المدة الزمنية لمرحلة ترطيب React.
|
|
107
|
+
|
|
108
|
+
> الأرقام أدناه مأخوذة من اختبار أُجري بتاريخ **12-09-2026** باستخدام `next-i18next` 16.3.0 (`react-i18next` 17.0.13, `i18next` 26.4.2) و `@intlayer/next-i18next` 9.5.1. تم تصميم تطبيق الاختبار عمداً ليكون صغيراً، لذا فإن نسب التسريب توضح **نمطاً سلوكياً**: تتسع هذه النسب مع نمو محتوى تطبيقك، في حين تبقى التكلفة الثابتة لبيئة التشغيل مستقرة.
|
|
109
|
+
|
|
110
|
+
### النتائج على Next.js
|
|
111
|
+
|
|
112
|
+
| الإعداد | الاستراتيجية | حجم المكتبة (gz) | متوسط JS للصفحة (gz) | تسريب اللغات | تسريب الصفحات | متوسط المكون (gz) | تفاعلية E2E | الترطيب |
|
|
113
|
+
| ---------------------------- | -------------- | ---------------: | -------------------: | -----------: | ------------: | ----------------: | ----------: | ----------: |
|
|
114
|
+
| **الأساس** (بدون 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` (الأصلي) | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
|
|
122
|
+
| `next-intlayer` (الأصلي) | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
|
|
123
|
+
|
|
124
|
+
**قراءة البيانات وتحليلها**
|
|
125
|
+
|
|
126
|
+
- **توفير 68 كيلوبايت لكل صفحة مقارنة بالإعداد البسيط.** يقوم الإعداد البسيط `resources: { en, fr, ... }` بإرسال جميع اللغات وجميع مساحات الأسماء في كل صفحة ليصل إلى **218.5 كيلوبايت**. أما بناء نفس المكونات باستخدام المحول فيصل إلى **150.7 كيلوبايت**. كما يتفوق على أفضل تكوين مخصص لـ `next-i18next` (163.4 كيلوبايت) بفارق 12.7 كيلوبايت، لأن بيئة تشغيل `i18next` وحدها تزن 19.7 كيلوبايت مقابل 9.4 كيلوبايت للمحول.
|
|
127
|
+
- **تراجع التسريب إلى 0% دون لمس أي مكون.** ترسل جميع إعدادات `next-i18next` (باستثناء الإعداد المقسم يدوياً بالكامل) ما يقارب 90% من نصوص الصفحات الأخرى غير المطلوبة. ونمط `dynamic` أسوأ مما يبدو: فهو لا يقضي على تسريب الصفحات ويضيف **50% تسريب لغات**، لأن الواجهة الخلفية الخاصة باللغة ما زالت تسحب كامل مساحة الأسماء `translation`. يبلغ المحول نسبة 0% / 0% انطلاقاً من الشيفرة الأصلية مباشرة.
|
|
128
|
+
- **مكونات أصغر بمقدار 8 أضعاف.** يزن المكون المعتمد على `useTranslation()` والمبني بمفرده متوسط **78.5 كيلوبايت** عند تضمين `resources`، و **26-27 كيلوبايت** مع الواجهة الخلفية، نظراً لارتباط `t` بالمخزن العام. ومع المحول، ينخفض متوسط الحجم إلى **9.7 كيلوبايت**.
|
|
129
|
+
- **ترطيب أسرع وتبديل لغات أكثر سلاسة.** انخفض وقت الترطيب من 15.6 مللي ثانية إلى **11.3 مللي ثانية** (ومن 27.7 مللي ثانية في نمط `dynamic` حيث يعيق جلب البيانات المسار الحرج). وتحسن وقت تبديل اللغة من 15-16 مللي ثانية إلى **11-12 مللي ثانية**.
|
|
130
|
+
- **المحول ليس هو بيئة التشغيل الأصلية.** تبلغ حزمة `next-intlayer` الأصلية **141.3 كيلوبايت** (+0.3 كيلوبايت فقط فوق التطبيق الأساسي الخالي من اللغات). بينما يحمل المحول طبقة توافق واجهة `i18next` فوق نواة Intlayer ليضيف 9.4 كيلوبايت لكل صفحة مقارنة بالنسخة الأصلية. المحول هو جسر عبور مريح، وليس المحطة النهائية.
|
|
131
|
+
|
|
132
|
+
> لم يكن محول `react-i18next` على Vite / TanStack Start جزءاً من هذا الاختبار المحدد. يمكن الاطلاع على قياسات `react-i18next` على TanStack Start في مقال [i18next vs Intlayer](https://intlayer.org/ar/blog/i18next-vs-intlayer).
|
|
133
|
+
|
|
134
|
+
## لماذا تتحسن هذه المؤشرات
|
|
135
|
+
|
|
136
|
+
لم تتغير أي شيفرة داخل مجلد `components/`، وبالتالي فإن كل هذه المكاسب ناتجة عن الكيان الذي ترتبط به الدالة `useTranslation`.
|
|
137
|
+
|
|
138
|
+
**مع `i18next`**، يتم الربط مع الكائن العام. كل ما يتم تحميله فيه (جميع اللغات في `static`، ومساحة الأسماء الكاملة للغة في `dynamic`) يصبح في متناول أي مكون يستدعي `useTranslation()`. ولا يستطيع مجمع الحزم تقسيم الملفات إلى وحدات أصغر مما يحتفظ به الكائن، كما تعجز بيئة التشغيل عن التنبؤ بالمفاتيح المطلوبة أثناء التصيير.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
.
|
|
142
|
+
├── next-i18next.config.js
|
|
143
|
+
├── public/locales
|
|
144
|
+
│ ├── en/translation.json # نصوص كافة الصفحات مجتمعة
|
|
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
|
+
**مع `@intlayer/next-i18next`**، يتم الربط مباشرة بالقاموس. يقوم ملحق `syncJSON` بتحويل كل ملف مساحة أسماء إلى قاموس مخصص؛ وتمرر مرحلة التحسين للمكون القاموس المعني مباشرة في صورة استيراد يستطيع مجمع الحزم تتبعه وتقسيمه لكل صفحة ولكل لغة بدقة.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
.
|
|
156
|
+
├── intlayer.config.ts # syncJSON({ format: "i18next", source: ... })
|
|
157
|
+
├── public/locales
|
|
158
|
+
│ ├── en/translation.json # بدون تغيير، يظل المصدر الحقيقي
|
|
159
|
+
│ └── fr/translation.json
|
|
160
|
+
├── .intlayer/ # مولد تلقائياً: قاموس لكل مساحة أسماء ولكل لغة
|
|
161
|
+
└── components
|
|
162
|
+
├── AppProviders.tsx # <IntlayerClientProvider locale={locale}>
|
|
163
|
+
└── About.tsx # useTranslation(); t("about.title") ← دون تغيير
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
يتحول ملف `i18n/i18n.ts` واستيراد `resources` إلى شيفرة ميتة يتم التخلص منها تلقائياً. وهذا ما يوفر 68 كيلوبايت كاملة.
|
|
167
|
+
|
|
168
|
+
## الهجرة في ثلاث خطوات
|
|
169
|
+
|
|
170
|
+
<Steps>
|
|
171
|
+
<Step number={1} title="التثبيت">
|
|
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
|
+
يكتشف الأمر وجود `i18next` / `react-i18next` / `next-i18next`، ويثبت `intlayer` وحزمة إطار العمل المعنية (`next-intlayer` أو `react-intlayer`) ومحول `@intlayer/*` المناسب مع ملحق `@intlayer/sync-json-plugin`، ويجهز إعدادات `intlayer.config.ts`. احتفظ بالحزم الأصلية مثبتة لديك، لأنها توفر تعريفات TypeScript وتعمل كاعتماديات نظيرة.
|
|
190
|
+
|
|
191
|
+
</Step>
|
|
192
|
+
<Step number={2} title="توجيه Intlayer إلى ملفات الترجمة الحالية">
|
|
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
|
+
// نمط i18next: يدعم {{name}} و $t(key) وصيغ الجمع _one / _other والسياق
|
|
210
|
+
format: "i18next",
|
|
211
|
+
// ملف لكل مساحة أسماء: `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
|
+
إذا كنت تمتلك ملفاً واحداً باسم `translation.json` لكل لغة (مساحة الأسماء الافتراضية في i18next)، فقم بتعيين `splitKeys: false` بحيث يظل الملف بأكمله قاموساً واحداً وتستمر استدعاءات `useTranslation()` المباشرة في العمل دون مشاكل.
|
|
222
|
+
|
|
223
|
+
</Step>
|
|
224
|
+
<Step number={3} title="إضافة الملحق">
|
|
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
|
+
في بنية App Router، تستقبل مكونات العميل اللغة من جزء المسار `[locale]`. لا يستقبل `I18nextProvider` الخاص بالمحول خاصية اللغة، لذا قم باستبداله لمرة واحدة فقط في ملف المزود الرئيسي:
|
|
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
|
+
جميع المكونات الموجودة تحته تستمر في استدعاء `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()` ملحق `vite-intlayer` وتنشئ الأسماء المستعارة لـ `react-i18next` و `i18next`. للمشاريع غير المعتمدة على React، تقوم `i18nextVitePlugin()` من حزمة `@intlayer/i18next/plugin` بتعيين الاسم المستعار لـ `i18next` بمفردها.
|
|
273
|
+
|
|
274
|
+
</Tab>
|
|
275
|
+
</Tabs>
|
|
276
|
+
|
|
277
|
+
</Step>
|
|
278
|
+
</Steps>
|
|
279
|
+
|
|
280
|
+
### ما يمكنك حذفه بعد الانتهاء
|
|
281
|
+
|
|
282
|
+
| الملف / النمط | السبب |
|
|
283
|
+
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
|
|
284
|
+
| `resources: { en, fr, ... }` واستيرادات JSON | يتم تجاهلها بواسطة المحول؛ ومن هنا جاءت إزالة الـ 68 كيلوبايت الفائضة |
|
|
285
|
+
| `i18next-http-backend`, `i18next-resources-to-backend` | لم يعد هناك شيء لجلبه في وقت التشغيل عبر الشبكة |
|
|
286
|
+
| `i18next-browser-languagedetector` | أصبح اكتشاف اللغة يدار عبر توجيه Intlayer (بادئة الرابط، ملفات تعريف الارتباط، الترويسة) |
|
|
287
|
+
| استدعاء `serverSideTranslations()` في `getStaticProps` | يعيد كائناً فارغاً؛ وجوده غير ضار لكنه غير ضروري |
|
|
288
|
+
| `next-i18next.config.js` | لا يتم قراءته؛ تُدار اللغات مركزياً في `intlayer.config.ts` |
|
|
289
|
+
| قوائم `ns: [...]` المحددة لكل صفحة | يحدد المترجم مساحات الأسماء المطلوبة لكل مكون تلقائياً |
|
|
290
|
+
|
|
291
|
+
### ما تكسبه بجانب تقليص الحجم
|
|
292
|
+
|
|
293
|
+
- **مفاتيح محكمة الأنواع.** يتم ربط `useTranslation("about")` بالأنواع البرمجية الخاصة بالقاموس `about`؛ واستخدام مفتاح غير موجود مثل `t("does.not.exist")` يولد خطأ TypeScript فوري أثناء التطوير بدلاً من إعادة نص المفتاح كخطأ صامت.
|
|
294
|
+
- **أوامر الفحص `npx intlayer test`** التي توقف عمليات الـ CI عند وجود مفتاح مفقود في أي لغة. ويتولى أمر **`npx intlayer fill`** ترجمة المفاتيح الناقصة باستخدام مفتاح الذكاء الاصطناعي الخاص بك (OpenAI, Anthropic, Mistral, Gemini...) وكتابتها في ملفات `locales/{lng}/{ns}.json`.
|
|
295
|
+
- **محرر بصري ونظام CMS** يعملان على نفس ملفات JSON، مما يتيح للمترجمين التعديل عبر واجهة مستخدم مباشرة مع تحديث ملفات Git تلقائياً.
|
|
296
|
+
- **هجرة تدريجية نحو ملفات `.content.ts`.** يمكن لأي مكون أن ينتقل بمفرده من `useTranslation("about")` إلى `useIntlayer("about")` بملف محتوى مجاور له، مع تعايش ملفات JSON و `.content.ts` معاً بانسجام.
|
|
297
|
+
|
|
298
|
+
## قيود يجب معرفتها قبل البدء
|
|
299
|
+
|
|
300
|
+
- **الواجهات الخلفية والكواشف غير فعالة.** تستدعي `i18n.use(HttpBackend)` دالة `init` الخاصة بالملحق فقط. وإذا كان تطبيقك يعتمد على جلب الترجمات في وقت الطلب من نظام CMS خارجي، فإن هذا المسار يتوقف؛ استخدم بدلاً من ذلك نظام Intlayer CMS أو أوامر `intlayer pull` / `push`.
|
|
301
|
+
- **يتم تجاهل `resources` بدلاً من دمجها.** على عكس بعض المحولات السطحية، لا يستخدم `@intlayer/i18next` كائن `resources` المضمن كحل احتياطي. يجب أن يتواجد كل مفتاح في القواميس المتزامنة فعلياً، وهو ما يؤكده أمر `intlayer test`.
|
|
302
|
+
- **يحتاج App Router إلى تعديل ملف المزود.** ملف واحد فقط، كما هو موضح أعلاه. بينما لا يتطلب Pages Router مع `appWithTranslation` أي تعديل.
|
|
303
|
+
- **لا يتم قراءة `next-i18next.config.js`.** خيارات مثل `localePath` و `fallbackLng` و `reloadOnPrerender` تتوقف عن العمل؛ وتُدار اللغات والبدائل حصرياً داخل `intlayer.config.ts`.
|
|
304
|
+
- **المحول ليس مجانياً تماماً من حيث الحجم.** يزن المحول 9.4 كيلوبايت وقت التشغيل ويضيف +9.4 كيلوبايت لكل صفحة مقارنة بنواة `next-intlayer` الصافية. وبمجرد تحويل جميع المكونات إلى `useIntlayer`، يمكنك حذفه تماماً.
|
|
305
|
+
|
|
306
|
+
## متى تستخدم كل خيار؟
|
|
307
|
+
|
|
308
|
+
- **ابقَ على `i18next`**: إذا كان تطبيقك يعتمد بالضرورة على واجهات خلفية لجلب النصوص وقت الطلب عبر الشبكة، أو على منظومة إضافات مخصصة، أو على بيئة عمل خارج نطاق React لا تدعمها المحولات.
|
|
309
|
+
- **استخدم `@intlayer/*`**: إذا كنت تستخدم `react-i18next` / `next-i18next` وتريد خفض 68 كيلوبايت، وتصغير المكونات 8 مرات، والقضاء على التسريب بنسبة 0%، والحصول على أمان الأنواع واختبارات الـ CI دون الحاجة لإعادة كتابة مكوناتك. هذا هو الخيار الأمثل للمشاريع القائمة.
|
|
310
|
+
- **انتقل إلى البنية الأصلية (`next-intlayer` / `react-intlayer`)**: للمشاريع الجديدة، أو بمجرد استقرارك بعد مرحلة المحول. إنها الخيار الأخف على الإطلاق (5.5 كيلوبايت، و+0.3 كيلوبايت فقط لكل صفحة) وتتيح المكونات السيرفرية المتزامنة وملفات `.content.ts` لكل مكون.
|
|
311
|
+
|
|
312
|
+
## مقارنات ذات صلة
|
|
313
|
+
|
|
314
|
+
- [i18next vs Intlayer](https://intlayer.org/ar/blog/i18next-vs-intlayer) (مقارنة المكتبات على نفس مقياس الأداء)
|
|
315
|
+
- [next-intl vs @intlayer/next-intl](https://intlayer.org/ar/blog/next-intl-vs-intlayer-next-intl) (نفس سلسلة المحولات)
|
|
316
|
+
- [Lingui vs @intlayer/lingui](https://intlayer.org/ar/blog/lingui-vs-intlayer-lingui) (نفس سلسلة المحولات)
|
|
317
|
+
- [vue-i18n vs @intlayer/vue-i18n](https://intlayer.org/ar/blog/vue-i18n-vs-intlayer-vue-i18n) (نفس سلسلة المحولات)
|
|
318
|
+
- أدلة الهجرة: [i18next](https://intlayer.org/ar/doc/migration/i18next), [react-i18next](https://intlayer.org/ar/doc/migration/react-i18next), [next-i18next](https://intlayer.org/ar/doc/migration/next-i18next)
|
|
319
|
+
- مراجع المحولات التوافقية: [i18next](https://intlayer.org/ar/doc/compatibility/i18next), [react-i18next](https://intlayer.org/ar/doc/compatibility/react-i18next), [next-i18next](https://intlayer.org/ar/doc/compatibility/next-i18next)
|
|
320
|
+
|
|
321
|
+
## الخاتمة
|
|
322
|
+
|
|
323
|
+
يعد `i18next` أثقل بيئة تشغيل في اختبار الأداء هذا، وتقوم المحولات بالتخلص من معظم وزنه الزائد دون أن تطلب منك التخلي عن واجهة البرمجة التي اعتدت عليها. في نفس تطبيق Next.js، يعني ذلك **توفير 68 كيلوبايت لكل صفحة** مقارنة بالإعداد البسيط، و **12.7 كيلوبايت أقل** من أفضل إعداد محسّن يدوياً، مع **مكونات أصغر بـ 8 مرات**، و **0% تسريب نصوص**، و **تحسن الترطيب بـ 4 مللي ثانية**، مقابل ملف إعدادات وسطر ملحق وتعديل بسيط لملف المزود.
|
|
324
|
+
|
|
325
|
+
جميع البيانات الأولية والتطبيقات الاختبارية والبرمجيات النصية متوفرة في [مستودع Benchmark Bloom](https://github.com/intlayer-org/benchmark-bloom). يمكنك مراجعتها واختبارها بنفسك.
|
|
326
|
+
|
|
327
|
+
راجع توثيق [لماذا Intlayer؟](https://intlayer.org/ar/doc/why) لمزيد من التفاصيل.
|