@intlayer/docs 9.5.3 → 9.5.4
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 +8 -8
- package/blog/ar/history_of_i18n.md +54 -54
- package/blog/ar/how_to_pick_react_i18n_library.md +548 -0
- package/blog/ar/how_to_pick_solid_i18n_library.md +438 -0
- package/blog/ar/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/ar/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/ar/is_i18next_outdated.md +5 -1
- package/blog/ar/is_next-intl_outdated.md +5 -1
- package/blog/ar/is_vue-i18n_outdated.md +7 -1
- package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +8 -4
- package/blog/ar/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ar/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/de/history_of_i18n.md +54 -54
- package/blog/de/how_to_pick_react_i18n_library.md +548 -0
- package/blog/de/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/de/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/de/how_to_pick_vue_i18n_library.md +448 -0
- package/blog/de/is_i18next_outdated.md +5 -1
- package/blog/de/is_next-intl_outdated.md +5 -1
- package/blog/de/is_vue-i18n_outdated.md +7 -1
- package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/de/per-component_vs_centralized_i18n.md +9 -4
- package/blog/de/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/en/history_of_i18n.md +54 -54
- package/blog/en/how_to_pick_react_i18n_library.md +542 -0
- package/blog/en/how_to_pick_solid_i18n_library.md +438 -0
- package/blog/en/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/en/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/en/is_i18next_outdated.md +5 -1
- package/blog/en/is_next-intl_outdated.md +5 -1
- package/blog/en/is_vue-i18n_outdated.md +7 -1
- package/blog/en/list_i18n_technologies/frameworks/react-router.md +2 -3
- package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/en/per-component_vs_centralized_i18n.md +9 -4
- package/blog/en/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/en-GB/history_of_i18n.md +54 -54
- package/blog/en-GB/how_to_pick_react_i18n_library.md +542 -0
- package/blog/en-GB/how_to_pick_solid_i18n_library.md +438 -0
- package/blog/en-GB/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/en-GB/how_to_pick_vue_i18n_library.md +448 -0
- package/blog/en-GB/is_i18next_outdated.md +5 -1
- package/blog/en-GB/is_next-intl_outdated.md +5 -1
- package/blog/en-GB/is_vue-i18n_outdated.md +7 -1
- package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/en-GB/per-component_vs_centralized_i18n.md +9 -4
- package/blog/en-GB/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/es/history_of_i18n.md +54 -54
- package/blog/es/how_to_pick_react_i18n_library.md +542 -0
- package/blog/es/how_to_pick_solid_i18n_library.md +446 -0
- package/blog/es/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/es/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/es/is_i18next_outdated.md +5 -1
- package/blog/es/is_next-intl_outdated.md +5 -1
- package/blog/es/is_vue-i18n_outdated.md +7 -1
- package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/es/per-component_vs_centralized_i18n.md +9 -4
- package/blog/es/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/fr/history_of_i18n.md +54 -54
- package/blog/fr/how_to_pick_react_i18n_library.md +542 -0
- package/blog/fr/how_to_pick_solid_i18n_library.md +438 -0
- package/blog/fr/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/fr/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/fr/is_i18next_outdated.md +5 -1
- package/blog/fr/is_next-intl_outdated.md +5 -1
- package/blog/fr/is_vue-i18n_outdated.md +7 -1
- package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/fr/per-component_vs_centralized_i18n.md +9 -4
- package/blog/fr/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/hi/history_of_i18n.md +54 -54
- package/blog/hi/how_to_pick_react_i18n_library.md +548 -0
- package/blog/hi/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/hi/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/hi/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/hi/is_i18next_outdated.md +5 -1
- package/blog/hi/is_next-intl_outdated.md +5 -1
- package/blog/hi/is_vue-i18n_outdated.md +7 -1
- package/blog/hi/next-i18next_vs_next-intl_vs_intlayer.md +8 -4
- package/blog/hi/per-component_vs_centralized_i18n.md +9 -4
- package/blog/hi/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/id/history_of_i18n.md +54 -54
- package/blog/id/how_to_pick_react_i18n_library.md +548 -0
- package/blog/id/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/id/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/id/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/id/is_i18next_outdated.md +5 -1
- package/blog/id/is_next-intl_outdated.md +5 -1
- package/blog/id/is_vue-i18n_outdated.md +7 -1
- package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/id/per-component_vs_centralized_i18n.md +9 -4
- package/blog/id/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/it/history_of_i18n.md +54 -54
- package/blog/it/how_to_pick_react_i18n_library.md +549 -0
- package/blog/it/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/it/how_to_pick_svelte_i18n_library.md +455 -0
- package/blog/it/how_to_pick_vue_i18n_library.md +449 -0
- package/blog/it/is_i18next_outdated.md +5 -1
- package/blog/it/is_next-intl_outdated.md +5 -1
- package/blog/it/is_vue-i18n_outdated.md +7 -1
- package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/it/per-component_vs_centralized_i18n.md +9 -4
- package/blog/it/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/ja/history_of_i18n.md +54 -54
- package/blog/ja/how_to_pick_react_i18n_library.md +542 -0
- package/blog/ja/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/ja/how_to_pick_svelte_i18n_library.md +457 -0
- package/blog/ja/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/ja/is_i18next_outdated.md +5 -1
- package/blog/ja/is_next-intl_outdated.md +5 -1
- package/blog/ja/is_vue-i18n_outdated.md +7 -1
- package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/ja/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ja/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/ko/history_of_i18n.md +54 -54
- package/blog/ko/how_to_pick_react_i18n_library.md +548 -0
- package/blog/ko/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/ko/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/ko/how_to_pick_vue_i18n_library.md +448 -0
- package/blog/ko/is_i18next_outdated.md +5 -1
- package/blog/ko/is_next-intl_outdated.md +5 -1
- package/blog/ko/is_vue-i18n_outdated.md +7 -1
- package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/ko/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ko/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/pl/history_of_i18n.md +54 -54
- package/blog/pl/how_to_pick_react_i18n_library.md +549 -0
- package/blog/pl/how_to_pick_solid_i18n_library.md +438 -0
- package/blog/pl/how_to_pick_svelte_i18n_library.md +460 -0
- package/blog/pl/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/pl/is_i18next_outdated.md +5 -1
- package/blog/pl/is_next-intl_outdated.md +5 -1
- package/blog/pl/is_vue-i18n_outdated.md +7 -1
- package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/pl/per-component_vs_centralized_i18n.md +9 -4
- package/blog/pl/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/pt/history_of_i18n.md +54 -54
- package/blog/pt/how_to_pick_react_i18n_library.md +549 -0
- package/blog/pt/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/pt/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/pt/how_to_pick_vue_i18n_library.md +448 -0
- package/blog/pt/is_i18next_outdated.md +5 -1
- package/blog/pt/is_next-intl_outdated.md +5 -1
- package/blog/pt/is_vue-i18n_outdated.md +7 -1
- package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/pt/per-component_vs_centralized_i18n.md +9 -4
- package/blog/pt/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/ru/history_of_i18n.md +54 -54
- package/blog/ru/how_to_pick_react_i18n_library.md +553 -0
- package/blog/ru/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/ru/how_to_pick_svelte_i18n_library.md +459 -0
- package/blog/ru/how_to_pick_vue_i18n_library.md +453 -0
- package/blog/ru/is_i18next_outdated.md +5 -1
- package/blog/ru/is_next-intl_outdated.md +5 -1
- package/blog/ru/is_vue-i18n_outdated.md +7 -1
- package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +8 -4
- package/blog/ru/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ru/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/tr/history_of_i18n.md +54 -54
- package/blog/tr/how_to_pick_react_i18n_library.md +548 -0
- package/blog/tr/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/tr/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/tr/how_to_pick_vue_i18n_library.md +448 -0
- package/blog/tr/is_i18next_outdated.md +5 -1
- package/blog/tr/is_next-intl_outdated.md +5 -1
- package/blog/tr/is_vue-i18n_outdated.md +7 -1
- package/blog/tr/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/tr/per-component_vs_centralized_i18n.md +9 -4
- package/blog/tr/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/uk/history_of_i18n.md +54 -54
- package/blog/uk/how_to_pick_react_i18n_library.md +542 -0
- package/blog/uk/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/uk/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/uk/how_to_pick_vue_i18n_library.md +443 -0
- package/blog/uk/is_i18next_outdated.md +5 -1
- package/blog/uk/is_next-intl_outdated.md +5 -1
- package/blog/uk/is_vue-i18n_outdated.md +7 -1
- package/blog/uk/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/uk/per-component_vs_centralized_i18n.md +9 -4
- package/blog/uk/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/vi/history_of_i18n.md +54 -54
- package/blog/vi/how_to_pick_react_i18n_library.md +548 -0
- package/blog/vi/how_to_pick_solid_i18n_library.md +438 -0
- package/blog/vi/how_to_pick_svelte_i18n_library.md +448 -0
- package/blog/vi/how_to_pick_vue_i18n_library.md +442 -0
- package/blog/vi/is_i18next_outdated.md +5 -1
- package/blog/vi/is_next-intl_outdated.md +5 -1
- package/blog/vi/is_vue-i18n_outdated.md +7 -1
- package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/vi/per-component_vs_centralized_i18n.md +9 -4
- package/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/blog/zh/history_of_i18n.md +54 -54
- package/blog/zh/how_to_pick_react_i18n_library.md +548 -0
- package/blog/zh/how_to_pick_solid_i18n_library.md +451 -0
- package/blog/zh/how_to_pick_svelte_i18n_library.md +454 -0
- package/blog/zh/how_to_pick_vue_i18n_library.md +448 -0
- package/blog/zh/is_i18next_outdated.md +5 -1
- package/blog/zh/is_next-intl_outdated.md +5 -1
- package/blog/zh/is_vue-i18n_outdated.md +7 -1
- package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +9 -5
- package/blog/zh/per-component_vs_centralized_i18n.md +9 -4
- package/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- package/dist/cjs/generated/blog.entry.cjs +80 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/esm/generated/blog.entry.mjs +80 -0
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/types/generated/blog.entry.d.ts +4 -0
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/docs/ar/bundle_optimization.md +5 -1
- package/docs/ar/how_works_intlayer.md +2 -2
- package/docs/ar/interest_of_intlayer.md +6 -6
- package/docs/ar/intlayer_CMS.md +1 -1
- package/docs/ar/intlayer_with_adonisjs.md +1 -1
- package/docs/ar/intlayer_with_analog.md +1 -1
- package/docs/ar/intlayer_with_angular_19.md +1 -1
- package/docs/ar/intlayer_with_angular_21.md +1 -1
- package/docs/ar/intlayer_with_astro.md +1 -1
- package/docs/ar/intlayer_with_astro_lit.md +1 -1
- package/docs/ar/intlayer_with_astro_preact.md +1 -1
- package/docs/ar/intlayer_with_astro_react.md +1 -1
- package/docs/ar/intlayer_with_astro_solid.md +1 -1
- package/docs/ar/intlayer_with_astro_svelte.md +1 -1
- package/docs/ar/intlayer_with_astro_vanilla.md +1 -1
- package/docs/ar/intlayer_with_astro_vue.md +1 -1
- package/docs/ar/intlayer_with_create_react_app.md +1 -1
- package/docs/ar/intlayer_with_express.md +1 -1
- package/docs/ar/intlayer_with_hono.md +1 -1
- package/docs/ar/intlayer_with_nestjs.md +1 -1
- package/docs/ar/intlayer_with_nextjs_14.md +1 -1
- package/docs/ar/intlayer_with_nextjs_15.md +1 -1
- package/docs/ar/intlayer_with_nextjs_16.md +1 -1
- package/docs/ar/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/ar/intlayer_with_react_router_v7.md +1 -1
- package/docs/ar/intlayer_with_vite+preact.md +1 -1
- package/docs/ar/intlayer_with_vite+react.md +1 -1
- package/docs/ar/intlayer_with_vite+vue.md +1 -1
- package/docs/ar/introduction.md +0 -1
- package/docs/ar/readme.md +8 -8
- package/docs/bn/bundle_optimization.md +5 -1
- package/docs/bn/interest_of_intlayer.md +21 -21
- package/docs/bn/intlayer_CMS.md +1 -1
- package/docs/bn/intlayer_with_angular_21.md +1 -1
- package/docs/bn/intlayer_with_hono.md +1 -1
- package/docs/bn/introduction.md +0 -1
- package/docs/cs/bundle_optimization.md +5 -1
- package/docs/cs/interest_of_intlayer.md +6 -6
- package/docs/cs/intlayer_with_angular_21.md +1 -1
- package/docs/cs/intlayer_with_hono.md +1 -1
- package/docs/cs/introduction.md +0 -1
- package/docs/de/bundle_optimization.md +5 -1
- package/docs/de/how_works_intlayer.md +2 -2
- package/docs/de/interest_of_intlayer.md +6 -6
- package/docs/de/intlayer_CMS.md +1 -1
- package/docs/de/intlayer_with_adonisjs.md +1 -1
- package/docs/de/intlayer_with_analog.md +1 -1
- package/docs/de/intlayer_with_angular_19.md +1 -1
- package/docs/de/intlayer_with_angular_21.md +1 -1
- package/docs/de/intlayer_with_astro.md +1 -1
- package/docs/de/intlayer_with_astro_lit.md +1 -1
- package/docs/de/intlayer_with_astro_preact.md +1 -1
- package/docs/de/intlayer_with_astro_react.md +1 -1
- package/docs/de/intlayer_with_astro_solid.md +1 -1
- package/docs/de/intlayer_with_astro_svelte.md +1 -1
- package/docs/de/intlayer_with_astro_vanilla.md +1 -1
- package/docs/de/intlayer_with_astro_vue.md +1 -1
- package/docs/de/intlayer_with_create_react_app.md +1 -1
- package/docs/de/intlayer_with_express.md +1 -1
- package/docs/de/intlayer_with_hono.md +1 -1
- package/docs/de/intlayer_with_nestjs.md +1 -1
- package/docs/de/intlayer_with_nextjs_14.md +1 -1
- package/docs/de/intlayer_with_nextjs_15.md +1 -1
- package/docs/de/intlayer_with_nextjs_16.md +1 -1
- package/docs/de/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/de/intlayer_with_vite+preact.md +1 -1
- package/docs/de/intlayer_with_vite+react.md +1 -1
- package/docs/de/intlayer_with_vite+vue.md +1 -1
- package/docs/de/introduction.md +0 -1
- package/docs/de/readme.md +8 -8
- package/docs/en/bundle_optimization.md +5 -1
- package/docs/en/how_works_intlayer.md +2 -2
- package/docs/en/interest_of_intlayer.md +6 -6
- package/docs/en/intlayer_CMS.md +1 -1
- package/docs/en/intlayer_with_adonisjs.md +1 -1
- package/docs/en/intlayer_with_analog.md +1 -1
- package/docs/en/intlayer_with_angular_19.md +1 -1
- package/docs/en/intlayer_with_angular_21.md +1 -1
- package/docs/en/intlayer_with_astro.md +1 -1
- package/docs/en/intlayer_with_astro_lit.md +1 -1
- package/docs/en/intlayer_with_astro_preact.md +1 -1
- package/docs/en/intlayer_with_astro_react.md +1 -1
- package/docs/en/intlayer_with_astro_solid.md +1 -1
- package/docs/en/intlayer_with_astro_svelte.md +1 -1
- package/docs/en/intlayer_with_astro_vanilla.md +1 -1
- package/docs/en/intlayer_with_astro_vue.md +1 -1
- package/docs/en/intlayer_with_create_react_app.md +1 -1
- package/docs/en/intlayer_with_express.md +1 -1
- package/docs/en/intlayer_with_hono.md +1 -1
- package/docs/en/intlayer_with_nestjs.md +1 -1
- package/docs/en/intlayer_with_nextjs_14.md +1 -1
- package/docs/en/intlayer_with_nextjs_15.md +1 -1
- package/docs/en/intlayer_with_nextjs_16.md +1 -1
- package/docs/en/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/en/intlayer_with_vite+preact.md +1 -1
- package/docs/en/intlayer_with_vite+react.md +1 -1
- package/docs/en/intlayer_with_vite+vue.md +1 -1
- package/docs/en/introduction.md +0 -1
- package/docs/en/readme.md +8 -8
- package/docs/en-GB/bundle_optimization.md +5 -1
- package/docs/en-GB/how_works_intlayer.md +2 -2
- package/docs/en-GB/interest_of_intlayer.md +6 -6
- package/docs/en-GB/intlayer_CMS.md +1 -1
- package/docs/en-GB/intlayer_with_adonisjs.md +1 -1
- package/docs/en-GB/intlayer_with_analog.md +1 -1
- package/docs/en-GB/intlayer_with_angular_19.md +1 -1
- package/docs/en-GB/intlayer_with_angular_21.md +1 -1
- package/docs/en-GB/intlayer_with_astro.md +1 -1
- package/docs/en-GB/intlayer_with_astro_lit.md +1 -1
- package/docs/en-GB/intlayer_with_astro_preact.md +1 -1
- package/docs/en-GB/intlayer_with_astro_react.md +1 -1
- package/docs/en-GB/intlayer_with_astro_solid.md +1 -1
- package/docs/en-GB/intlayer_with_astro_svelte.md +1 -1
- package/docs/en-GB/intlayer_with_astro_vanilla.md +1 -1
- package/docs/en-GB/intlayer_with_astro_vue.md +1 -1
- package/docs/en-GB/intlayer_with_create_react_app.md +1 -1
- package/docs/en-GB/intlayer_with_express.md +1 -1
- package/docs/en-GB/intlayer_with_hono.md +1 -1
- package/docs/en-GB/intlayer_with_nestjs.md +1 -1
- package/docs/en-GB/intlayer_with_nextjs_14.md +1 -1
- package/docs/en-GB/intlayer_with_nextjs_15.md +1 -1
- package/docs/en-GB/intlayer_with_nextjs_16.md +1 -1
- package/docs/en-GB/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/en-GB/intlayer_with_vite+preact.md +1 -1
- package/docs/en-GB/intlayer_with_vite+react.md +1 -1
- package/docs/en-GB/intlayer_with_vite+vue.md +1 -1
- package/docs/en-GB/introduction.md +0 -1
- package/docs/en-GB/readme.md +8 -8
- package/docs/es/bundle_optimization.md +5 -1
- package/docs/es/how_works_intlayer.md +2 -2
- package/docs/es/interest_of_intlayer.md +6 -6
- package/docs/es/intlayer_CMS.md +1 -1
- package/docs/es/intlayer_with_adonisjs.md +1 -1
- package/docs/es/intlayer_with_analog.md +1 -1
- package/docs/es/intlayer_with_angular_19.md +1 -1
- package/docs/es/intlayer_with_angular_21.md +1 -1
- package/docs/es/intlayer_with_astro.md +1 -1
- package/docs/es/intlayer_with_astro_lit.md +1 -1
- package/docs/es/intlayer_with_astro_preact.md +1 -1
- package/docs/es/intlayer_with_astro_react.md +1 -1
- package/docs/es/intlayer_with_astro_solid.md +1 -1
- package/docs/es/intlayer_with_astro_svelte.md +1 -1
- package/docs/es/intlayer_with_astro_vanilla.md +1 -1
- package/docs/es/intlayer_with_astro_vue.md +1 -1
- package/docs/es/intlayer_with_create_react_app.md +1 -1
- package/docs/es/intlayer_with_express.md +1 -1
- package/docs/es/intlayer_with_hono.md +1 -1
- package/docs/es/intlayer_with_nestjs.md +1 -1
- package/docs/es/intlayer_with_nextjs_14.md +1 -1
- package/docs/es/intlayer_with_nextjs_15.md +1 -1
- package/docs/es/intlayer_with_nextjs_16.md +1 -1
- package/docs/es/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/es/intlayer_with_vite+preact.md +1 -1
- package/docs/es/intlayer_with_vite+react.md +1 -1
- package/docs/es/intlayer_with_vite+vue.md +1 -1
- package/docs/es/introduction.md +0 -1
- package/docs/es/readme.md +8 -8
- package/docs/fr/bundle_optimization.md +5 -1
- package/docs/fr/how_works_intlayer.md +2 -2
- package/docs/fr/interest_of_intlayer.md +6 -6
- package/docs/fr/intlayer_CMS.md +1 -1
- package/docs/fr/intlayer_with_adonisjs.md +1 -1
- package/docs/fr/intlayer_with_analog.md +1 -1
- package/docs/fr/intlayer_with_angular_19.md +1 -1
- package/docs/fr/intlayer_with_angular_21.md +1 -1
- package/docs/fr/intlayer_with_astro.md +1 -1
- package/docs/fr/intlayer_with_astro_lit.md +1 -1
- package/docs/fr/intlayer_with_astro_preact.md +1 -1
- package/docs/fr/intlayer_with_astro_react.md +1 -1
- package/docs/fr/intlayer_with_astro_solid.md +1 -1
- package/docs/fr/intlayer_with_astro_svelte.md +1 -1
- package/docs/fr/intlayer_with_astro_vanilla.md +1 -1
- package/docs/fr/intlayer_with_astro_vue.md +1 -1
- package/docs/fr/intlayer_with_create_react_app.md +1 -1
- package/docs/fr/intlayer_with_express.md +1 -1
- package/docs/fr/intlayer_with_hono.md +1 -1
- package/docs/fr/intlayer_with_nestjs.md +1 -1
- package/docs/fr/intlayer_with_nextjs_14.md +1 -1
- package/docs/fr/intlayer_with_nextjs_15.md +1 -1
- package/docs/fr/intlayer_with_nextjs_16.md +1 -1
- package/docs/fr/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/fr/intlayer_with_react_router_v7.md +2 -2
- package/docs/fr/intlayer_with_vite+preact.md +1 -1
- package/docs/fr/intlayer_with_vite+react.md +1 -1
- package/docs/fr/intlayer_with_vite+vue.md +1 -1
- package/docs/fr/introduction.md +0 -1
- package/docs/fr/readme.md +8 -8
- package/docs/hi/bundle_optimization.md +5 -1
- package/docs/hi/how_works_intlayer.md +2 -2
- package/docs/hi/interest_of_intlayer.md +6 -6
- package/docs/hi/intlayer_CMS.md +1 -1
- package/docs/hi/intlayer_with_adonisjs.md +1 -1
- package/docs/hi/intlayer_with_analog.md +1 -1
- package/docs/hi/intlayer_with_angular_19.md +1 -1
- package/docs/hi/intlayer_with_angular_21.md +1 -1
- package/docs/hi/intlayer_with_astro.md +1 -1
- package/docs/hi/intlayer_with_astro_lit.md +1 -1
- package/docs/hi/intlayer_with_astro_preact.md +1 -1
- package/docs/hi/intlayer_with_astro_react.md +1 -1
- package/docs/hi/intlayer_with_astro_solid.md +1 -1
- package/docs/hi/intlayer_with_astro_svelte.md +1 -1
- package/docs/hi/intlayer_with_astro_vanilla.md +1 -1
- package/docs/hi/intlayer_with_astro_vue.md +1 -1
- package/docs/hi/intlayer_with_create_react_app.md +1 -1
- package/docs/hi/intlayer_with_express.md +1 -1
- package/docs/hi/intlayer_with_hono.md +1 -1
- package/docs/hi/intlayer_with_nestjs.md +1 -1
- package/docs/hi/intlayer_with_nextjs_14.md +1 -1
- package/docs/hi/intlayer_with_nextjs_15.md +1 -1
- package/docs/hi/intlayer_with_nextjs_16.md +1 -1
- package/docs/hi/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/hi/intlayer_with_react_router_v7.md +1 -1
- package/docs/hi/intlayer_with_vite+preact.md +1 -1
- package/docs/hi/intlayer_with_vite+react.md +1 -1
- package/docs/hi/intlayer_with_vite+vue.md +1 -1
- package/docs/hi/introduction.md +0 -1
- package/docs/hi/readme.md +8 -8
- package/docs/id/bundle_optimization.md +5 -1
- package/docs/id/how_works_intlayer.md +2 -2
- package/docs/id/interest_of_intlayer.md +6 -6
- package/docs/id/intlayer_CMS.md +1 -1
- package/docs/id/intlayer_with_adonisjs.md +1 -1
- package/docs/id/intlayer_with_analog.md +1 -1
- package/docs/id/intlayer_with_angular_19.md +1 -1
- package/docs/id/intlayer_with_angular_21.md +1 -1
- package/docs/id/intlayer_with_astro.md +1 -1
- package/docs/id/intlayer_with_astro_lit.md +1 -1
- package/docs/id/intlayer_with_astro_preact.md +1 -1
- package/docs/id/intlayer_with_astro_react.md +1 -1
- package/docs/id/intlayer_with_astro_solid.md +1 -1
- package/docs/id/intlayer_with_astro_svelte.md +1 -1
- package/docs/id/intlayer_with_astro_vanilla.md +1 -1
- package/docs/id/intlayer_with_astro_vue.md +1 -1
- package/docs/id/intlayer_with_create_react_app.md +1 -1
- package/docs/id/intlayer_with_express.md +1 -1
- package/docs/id/intlayer_with_hono.md +1 -1
- package/docs/id/intlayer_with_nestjs.md +1 -1
- package/docs/id/intlayer_with_nextjs_14.md +1 -1
- package/docs/id/intlayer_with_nextjs_15.md +1 -1
- package/docs/id/intlayer_with_nextjs_16.md +1 -1
- package/docs/id/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/id/intlayer_with_react_router_v7.md +1 -1
- package/docs/id/intlayer_with_vite+preact.md +1 -1
- package/docs/id/intlayer_with_vite+react.md +1 -1
- package/docs/id/intlayer_with_vite+vue.md +1 -1
- package/docs/id/introduction.md +0 -1
- package/docs/id/readme.md +8 -8
- package/docs/it/bundle_optimization.md +5 -1
- package/docs/it/how_works_intlayer.md +2 -2
- package/docs/it/interest_of_intlayer.md +6 -6
- package/docs/it/intlayer_CMS.md +1 -1
- package/docs/it/intlayer_with_adonisjs.md +1 -1
- package/docs/it/intlayer_with_analog.md +1 -1
- package/docs/it/intlayer_with_angular_19.md +1 -1
- package/docs/it/intlayer_with_angular_21.md +1 -1
- package/docs/it/intlayer_with_astro.md +1 -1
- package/docs/it/intlayer_with_astro_lit.md +1 -1
- package/docs/it/intlayer_with_astro_preact.md +1 -1
- package/docs/it/intlayer_with_astro_react.md +1 -1
- package/docs/it/intlayer_with_astro_solid.md +1 -1
- package/docs/it/intlayer_with_astro_svelte.md +1 -1
- package/docs/it/intlayer_with_astro_vanilla.md +1 -1
- package/docs/it/intlayer_with_astro_vue.md +1 -1
- package/docs/it/intlayer_with_create_react_app.md +1 -1
- package/docs/it/intlayer_with_express.md +1 -1
- package/docs/it/intlayer_with_hono.md +1 -1
- package/docs/it/intlayer_with_nestjs.md +1 -1
- package/docs/it/intlayer_with_nextjs_14.md +1 -1
- package/docs/it/intlayer_with_nextjs_15.md +1 -1
- package/docs/it/intlayer_with_nextjs_16.md +1 -1
- package/docs/it/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/it/intlayer_with_react_router_v7.md +2 -2
- package/docs/it/intlayer_with_vite+preact.md +1 -1
- package/docs/it/intlayer_with_vite+react.md +1 -1
- package/docs/it/intlayer_with_vite+vue.md +1 -1
- package/docs/it/introduction.md +0 -1
- package/docs/it/readme.md +8 -8
- package/docs/ja/bundle_optimization.md +5 -1
- package/docs/ja/how_works_intlayer.md +2 -2
- package/docs/ja/interest_of_intlayer.md +6 -6
- package/docs/ja/intlayer_CMS.md +1 -1
- package/docs/ja/intlayer_with_adonisjs.md +1 -1
- package/docs/ja/intlayer_with_analog.md +1 -1
- package/docs/ja/intlayer_with_angular_19.md +1 -1
- package/docs/ja/intlayer_with_angular_21.md +1 -1
- package/docs/ja/intlayer_with_astro.md +1 -1
- package/docs/ja/intlayer_with_astro_lit.md +1 -1
- package/docs/ja/intlayer_with_astro_preact.md +1 -1
- package/docs/ja/intlayer_with_astro_react.md +1 -1
- package/docs/ja/intlayer_with_astro_solid.md +1 -1
- package/docs/ja/intlayer_with_astro_svelte.md +1 -1
- package/docs/ja/intlayer_with_astro_vanilla.md +1 -1
- package/docs/ja/intlayer_with_astro_vue.md +1 -1
- package/docs/ja/intlayer_with_create_react_app.md +1 -1
- package/docs/ja/intlayer_with_express.md +1 -1
- package/docs/ja/intlayer_with_hono.md +1 -1
- package/docs/ja/intlayer_with_nestjs.md +1 -1
- package/docs/ja/intlayer_with_nextjs_14.md +1 -1
- package/docs/ja/intlayer_with_nextjs_15.md +1 -1
- package/docs/ja/intlayer_with_nextjs_16.md +1 -1
- package/docs/ja/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/ja/intlayer_with_vite+preact.md +1 -1
- package/docs/ja/intlayer_with_vite+react.md +1 -1
- package/docs/ja/intlayer_with_vite+vue.md +1 -1
- package/docs/ja/introduction.md +0 -1
- package/docs/ja/readme.md +8 -8
- package/docs/ko/bundle_optimization.md +5 -1
- package/docs/ko/how_works_intlayer.md +2 -2
- package/docs/ko/interest_of_intlayer.md +6 -6
- package/docs/ko/intlayer_CMS.md +1 -1
- package/docs/ko/intlayer_with_adonisjs.md +1 -1
- package/docs/ko/intlayer_with_analog.md +1 -1
- package/docs/ko/intlayer_with_angular_19.md +1 -1
- package/docs/ko/intlayer_with_angular_21.md +1 -1
- package/docs/ko/intlayer_with_astro.md +1 -1
- package/docs/ko/intlayer_with_astro_lit.md +1 -1
- package/docs/ko/intlayer_with_astro_preact.md +1 -1
- package/docs/ko/intlayer_with_astro_react.md +1 -1
- package/docs/ko/intlayer_with_astro_solid.md +1 -1
- package/docs/ko/intlayer_with_astro_svelte.md +1 -1
- package/docs/ko/intlayer_with_astro_vanilla.md +1 -1
- package/docs/ko/intlayer_with_astro_vue.md +1 -1
- package/docs/ko/intlayer_with_create_react_app.md +1 -1
- package/docs/ko/intlayer_with_express.md +1 -1
- package/docs/ko/intlayer_with_hono.md +1 -1
- package/docs/ko/intlayer_with_nestjs.md +1 -1
- package/docs/ko/intlayer_with_nextjs_14.md +1 -1
- package/docs/ko/intlayer_with_nextjs_15.md +1 -1
- package/docs/ko/intlayer_with_nextjs_16.md +1 -1
- package/docs/ko/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/ko/intlayer_with_react_router_v7.md +2 -2
- package/docs/ko/intlayer_with_vite+preact.md +1 -1
- package/docs/ko/intlayer_with_vite+react.md +1 -1
- package/docs/ko/intlayer_with_vite+vue.md +1 -1
- package/docs/ko/introduction.md +0 -1
- package/docs/ko/readme.md +8 -8
- package/docs/nl/bundle_optimization.md +5 -1
- package/docs/nl/interest_of_intlayer.md +6 -6
- package/docs/nl/intlayer_with_angular_21.md +1 -1
- package/docs/nl/intlayer_with_hono.md +1 -1
- package/docs/nl/introduction.md +0 -1
- package/docs/pl/bundle_optimization.md +5 -1
- package/docs/pl/how_works_intlayer.md +2 -2
- package/docs/pl/interest_of_intlayer.md +6 -6
- package/docs/pl/intlayer_CMS.md +1 -1
- package/docs/pl/intlayer_with_adonisjs.md +1 -1
- package/docs/pl/intlayer_with_analog.md +1 -1
- package/docs/pl/intlayer_with_angular_19.md +1 -1
- package/docs/pl/intlayer_with_angular_21.md +1 -1
- package/docs/pl/intlayer_with_astro.md +1 -1
- package/docs/pl/intlayer_with_astro_lit.md +1 -1
- package/docs/pl/intlayer_with_astro_preact.md +1 -1
- package/docs/pl/intlayer_with_astro_react.md +1 -1
- package/docs/pl/intlayer_with_astro_solid.md +1 -1
- package/docs/pl/intlayer_with_astro_svelte.md +1 -1
- package/docs/pl/intlayer_with_astro_vanilla.md +1 -1
- package/docs/pl/intlayer_with_astro_vue.md +1 -1
- package/docs/pl/intlayer_with_create_react_app.md +1 -1
- package/docs/pl/intlayer_with_express.md +1 -1
- package/docs/pl/intlayer_with_hono.md +1 -1
- package/docs/pl/intlayer_with_nestjs.md +1 -1
- package/docs/pl/intlayer_with_nextjs_14.md +1 -1
- package/docs/pl/intlayer_with_nextjs_15.md +1 -1
- package/docs/pl/intlayer_with_nextjs_16.md +1 -1
- package/docs/pl/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/pl/intlayer_with_react_router_v7.md +2 -2
- package/docs/pl/intlayer_with_vite+preact.md +1 -1
- package/docs/pl/intlayer_with_vite+react.md +1 -1
- package/docs/pl/intlayer_with_vite+vue.md +1 -1
- package/docs/pl/introduction.md +0 -1
- package/docs/pl/readme.md +8 -8
- package/docs/pt/bundle_optimization.md +5 -1
- package/docs/pt/how_works_intlayer.md +2 -2
- package/docs/pt/interest_of_intlayer.md +6 -6
- package/docs/pt/intlayer_CMS.md +1 -1
- package/docs/pt/intlayer_with_adonisjs.md +1 -1
- package/docs/pt/intlayer_with_analog.md +1 -1
- package/docs/pt/intlayer_with_angular_19.md +1 -1
- package/docs/pt/intlayer_with_angular_21.md +1 -1
- package/docs/pt/intlayer_with_astro.md +1 -1
- package/docs/pt/intlayer_with_astro_lit.md +1 -1
- package/docs/pt/intlayer_with_astro_preact.md +1 -1
- package/docs/pt/intlayer_with_astro_react.md +1 -1
- package/docs/pt/intlayer_with_astro_solid.md +1 -1
- package/docs/pt/intlayer_with_astro_svelte.md +1 -1
- package/docs/pt/intlayer_with_astro_vanilla.md +1 -1
- package/docs/pt/intlayer_with_astro_vue.md +1 -1
- package/docs/pt/intlayer_with_create_react_app.md +1 -1
- package/docs/pt/intlayer_with_express.md +1 -1
- package/docs/pt/intlayer_with_hono.md +1 -1
- package/docs/pt/intlayer_with_nestjs.md +1 -1
- package/docs/pt/intlayer_with_nextjs_14.md +1 -1
- package/docs/pt/intlayer_with_nextjs_15.md +1 -1
- package/docs/pt/intlayer_with_nextjs_16.md +1 -1
- package/docs/pt/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/pt/intlayer_with_react_router_v7.md +2 -2
- package/docs/pt/intlayer_with_vite+preact.md +1 -1
- package/docs/pt/intlayer_with_vite+react.md +1 -1
- package/docs/pt/intlayer_with_vite+vue.md +1 -1
- package/docs/pt/introduction.md +0 -1
- package/docs/pt/readme.md +8 -8
- package/docs/ru/bundle_optimization.md +5 -1
- package/docs/ru/how_works_intlayer.md +2 -2
- package/docs/ru/interest_of_intlayer.md +6 -6
- package/docs/ru/intlayer_CMS.md +1 -1
- package/docs/ru/intlayer_with_adonisjs.md +1 -1
- package/docs/ru/intlayer_with_analog.md +1 -1
- package/docs/ru/intlayer_with_angular_19.md +1 -1
- package/docs/ru/intlayer_with_angular_21.md +1 -1
- package/docs/ru/intlayer_with_astro.md +1 -1
- package/docs/ru/intlayer_with_astro_lit.md +1 -1
- package/docs/ru/intlayer_with_astro_preact.md +1 -1
- package/docs/ru/intlayer_with_astro_react.md +1 -1
- package/docs/ru/intlayer_with_astro_solid.md +1 -1
- package/docs/ru/intlayer_with_astro_svelte.md +1 -1
- package/docs/ru/intlayer_with_astro_vanilla.md +1 -1
- package/docs/ru/intlayer_with_astro_vue.md +1 -1
- package/docs/ru/intlayer_with_create_react_app.md +1 -1
- package/docs/ru/intlayer_with_express.md +1 -1
- package/docs/ru/intlayer_with_hono.md +1 -1
- package/docs/ru/intlayer_with_nestjs.md +1 -1
- package/docs/ru/intlayer_with_nextjs_14.md +1 -1
- package/docs/ru/intlayer_with_nextjs_15.md +1 -1
- package/docs/ru/intlayer_with_nextjs_16.md +1 -1
- package/docs/ru/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/ru/intlayer_with_react_router_v7.md +2 -2
- package/docs/ru/intlayer_with_vite+preact.md +1 -1
- package/docs/ru/intlayer_with_vite+react.md +1 -1
- package/docs/ru/intlayer_with_vite+vue.md +1 -1
- package/docs/ru/introduction.md +0 -1
- package/docs/ru/readme.md +8 -8
- package/docs/tr/bundle_optimization.md +5 -1
- package/docs/tr/how_works_intlayer.md +2 -2
- package/docs/tr/interest_of_intlayer.md +6 -6
- package/docs/tr/intlayer_CMS.md +1 -1
- package/docs/tr/intlayer_with_adonisjs.md +1 -1
- package/docs/tr/intlayer_with_analog.md +1 -1
- package/docs/tr/intlayer_with_angular_19.md +1 -1
- package/docs/tr/intlayer_with_angular_21.md +1 -1
- package/docs/tr/intlayer_with_astro.md +1 -1
- package/docs/tr/intlayer_with_astro_lit.md +1 -1
- package/docs/tr/intlayer_with_astro_preact.md +1 -1
- package/docs/tr/intlayer_with_astro_react.md +1 -1
- package/docs/tr/intlayer_with_astro_solid.md +1 -1
- package/docs/tr/intlayer_with_astro_svelte.md +1 -1
- package/docs/tr/intlayer_with_astro_vanilla.md +1 -1
- package/docs/tr/intlayer_with_astro_vue.md +1 -1
- package/docs/tr/intlayer_with_create_react_app.md +1 -1
- package/docs/tr/intlayer_with_express.md +1 -1
- package/docs/tr/intlayer_with_hono.md +1 -1
- package/docs/tr/intlayer_with_nestjs.md +1 -1
- package/docs/tr/intlayer_with_nextjs_14.md +1 -1
- package/docs/tr/intlayer_with_nextjs_15.md +1 -1
- package/docs/tr/intlayer_with_nextjs_16.md +1 -1
- package/docs/tr/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/tr/intlayer_with_react_router_v7.md +1 -1
- package/docs/tr/intlayer_with_vite+preact.md +1 -1
- package/docs/tr/intlayer_with_vite+react.md +1 -1
- package/docs/tr/intlayer_with_vite+vue.md +1 -1
- package/docs/tr/introduction.md +0 -1
- package/docs/tr/readme.md +8 -8
- package/docs/uk/bundle_optimization.md +5 -1
- package/docs/uk/how_works_intlayer.md +2 -2
- package/docs/uk/interest_of_intlayer.md +6 -6
- package/docs/uk/intlayer_CMS.md +1 -1
- package/docs/uk/intlayer_with_adonisjs.md +1 -1
- package/docs/uk/intlayer_with_analog.md +1 -1
- package/docs/uk/intlayer_with_angular_19.md +1 -1
- package/docs/uk/intlayer_with_angular_21.md +1 -1
- package/docs/uk/intlayer_with_astro.md +1 -1
- package/docs/uk/intlayer_with_astro_lit.md +1 -1
- package/docs/uk/intlayer_with_astro_preact.md +1 -1
- package/docs/uk/intlayer_with_astro_react.md +1 -1
- package/docs/uk/intlayer_with_astro_solid.md +1 -1
- package/docs/uk/intlayer_with_astro_svelte.md +1 -1
- package/docs/uk/intlayer_with_astro_vanilla.md +1 -1
- package/docs/uk/intlayer_with_astro_vue.md +1 -1
- package/docs/uk/intlayer_with_create_react_app.md +1 -1
- package/docs/uk/intlayer_with_express.md +1 -1
- package/docs/uk/intlayer_with_hono.md +1 -1
- package/docs/uk/intlayer_with_nestjs.md +1 -1
- package/docs/uk/intlayer_with_nextjs_14.md +1 -1
- package/docs/uk/intlayer_with_nextjs_15.md +1 -1
- package/docs/uk/intlayer_with_nextjs_16.md +1 -1
- package/docs/uk/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/uk/intlayer_with_react_router_v7.md +1 -1
- package/docs/uk/intlayer_with_vite+preact.md +1 -1
- package/docs/uk/intlayer_with_vite+react.md +1 -1
- package/docs/uk/intlayer_with_vite+vue.md +1 -1
- package/docs/uk/introduction.md +0 -1
- package/docs/uk/readme.md +8 -8
- package/docs/ur/bundle_optimization.md +5 -1
- package/docs/ur/interest_of_intlayer.md +6 -6
- package/docs/ur/intlayer_with_angular_21.md +1 -1
- package/docs/ur/intlayer_with_hono.md +1 -1
- package/docs/ur/introduction.md +0 -1
- package/docs/vi/bundle_optimization.md +5 -1
- package/docs/vi/how_works_intlayer.md +2 -2
- package/docs/vi/interest_of_intlayer.md +6 -6
- package/docs/vi/intlayer_CMS.md +1 -1
- package/docs/vi/intlayer_with_adonisjs.md +1 -1
- package/docs/vi/intlayer_with_analog.md +1 -1
- package/docs/vi/intlayer_with_angular_19.md +1 -1
- package/docs/vi/intlayer_with_angular_21.md +1 -1
- package/docs/vi/intlayer_with_astro.md +1 -1
- package/docs/vi/intlayer_with_astro_lit.md +1 -1
- package/docs/vi/intlayer_with_astro_preact.md +1 -1
- package/docs/vi/intlayer_with_astro_react.md +1 -1
- package/docs/vi/intlayer_with_astro_solid.md +1 -1
- package/docs/vi/intlayer_with_astro_svelte.md +1 -1
- package/docs/vi/intlayer_with_astro_vanilla.md +1 -1
- package/docs/vi/intlayer_with_astro_vue.md +1 -1
- package/docs/vi/intlayer_with_create_react_app.md +1 -1
- package/docs/vi/intlayer_with_express.md +1 -1
- package/docs/vi/intlayer_with_hono.md +1 -1
- package/docs/vi/intlayer_with_nestjs.md +1 -1
- package/docs/vi/intlayer_with_nextjs_14.md +1 -1
- package/docs/vi/intlayer_with_nextjs_15.md +1 -1
- package/docs/vi/intlayer_with_nextjs_16.md +1 -1
- package/docs/vi/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/vi/intlayer_with_vite+preact.md +1 -1
- package/docs/vi/intlayer_with_vite+react.md +1 -1
- package/docs/vi/intlayer_with_vite+vue.md +1 -1
- package/docs/vi/introduction.md +0 -1
- package/docs/vi/readme.md +8 -8
- package/docs/zh/bundle_optimization.md +5 -1
- package/docs/zh/how_works_intlayer.md +2 -2
- package/docs/zh/interest_of_intlayer.md +6 -6
- package/docs/zh/intlayer_CMS.md +1 -1
- package/docs/zh/intlayer_with_adonisjs.md +1 -1
- package/docs/zh/intlayer_with_analog.md +1 -1
- package/docs/zh/intlayer_with_angular_19.md +1 -1
- package/docs/zh/intlayer_with_angular_21.md +1 -1
- package/docs/zh/intlayer_with_astro.md +1 -1
- package/docs/zh/intlayer_with_astro_lit.md +1 -1
- package/docs/zh/intlayer_with_astro_preact.md +1 -1
- package/docs/zh/intlayer_with_astro_react.md +1 -1
- package/docs/zh/intlayer_with_astro_solid.md +1 -1
- package/docs/zh/intlayer_with_astro_svelte.md +1 -1
- package/docs/zh/intlayer_with_astro_vanilla.md +1 -1
- package/docs/zh/intlayer_with_astro_vue.md +1 -1
- package/docs/zh/intlayer_with_create_react_app.md +1 -1
- package/docs/zh/intlayer_with_express.md +1 -1
- package/docs/zh/intlayer_with_hono.md +1 -1
- package/docs/zh/intlayer_with_nestjs.md +1 -1
- package/docs/zh/intlayer_with_nextjs_14.md +1 -1
- package/docs/zh/intlayer_with_nextjs_15.md +1 -1
- package/docs/zh/intlayer_with_nextjs_16.md +1 -1
- package/docs/zh/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/zh/intlayer_with_react_router_v7.md +2 -2
- package/docs/zh/intlayer_with_vite+preact.md +1 -1
- package/docs/zh/intlayer_with_vite+react.md +1 -1
- package/docs/zh/intlayer_with_vite+vue.md +1 -1
- package/docs/zh/introduction.md +0 -1
- package/docs/zh/readme.md +8 -8
- package/docs/zh-TW/bundle_optimization.md +5 -1
- package/docs/zh-TW/interest_of_intlayer.md +6 -6
- package/docs/zh-TW/intlayer_with_angular_21.md +1 -1
- package/docs/zh-TW/introduction.md +0 -1
- package/package.json +8 -7
- package/src/generated/blog.entry.ts +80 -0
- package/blog/en/___per-component_vs_centralized_i18n.md +0 -255
- package/blog/pl/___per-component_vs_centralized_i18n.md +0 -100
- package/docs/en/benchmark/___NOTE.md +0 -101
- package/docs/en/benchmark/___nextjs.md +0 -197
- package/docs/en/benchmark/___solid.md +0 -12
- package/docs/en/benchmark/___svelte.md +0 -16
- package/docs/en/benchmark/___tanstack.md +0 -190
- package/docs/en/benchmark/___vue.md +0 -7
- package/docs/pl/benchmark/___NOTE.md +0 -101
- package/docs/pl/benchmark/___nextjs.md +0 -198
- package/docs/pl/benchmark/___solid.md +0 -36
- package/docs/pl/benchmark/___svelte.md +0 -36
- package/docs/pl/benchmark/___tanstack.md +0 -36
- package/docs/pl/benchmark/___vue.md +0 -36
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-16
|
|
3
|
+
updatedAt: 2026-09-16
|
|
4
|
+
title: "Cách chọn đúng thư viện React i18n năm 2026"
|
|
5
|
+
description: Hướng dẫn ra quyết định cho việc quốc tế hóa (i18n) React. Những câu hỏi cần trả lời trước khi so sánh react-i18next, react-intl, Lingui, use-intl, Paraglide và Intlayer, cùng chi phí của từng lựa chọn về bundle size, typing và bảo trì.
|
|
6
|
+
keywords:
|
|
7
|
+
- react i18n
|
|
8
|
+
- react internationalization
|
|
9
|
+
- react-i18next
|
|
10
|
+
- react-intl
|
|
11
|
+
- Lingui
|
|
12
|
+
- use-intl
|
|
13
|
+
- Paraglide
|
|
14
|
+
- Intlayer
|
|
15
|
+
- so sánh thư viện i18n
|
|
16
|
+
slugs:
|
|
17
|
+
- blog
|
|
18
|
+
- how-to-pick-react-i18n-library
|
|
19
|
+
author: aymericzip
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Cách chọn đúng thư viện React i18n
|
|
23
|
+
|
|
24
|
+
React không đi kèm primitive i18n nào. Thư viện bạn chọn ngay từ ngày đầu tiên sẽ quyết định cách các bản dịch được lưu trữ, cách chúng được nạp vào bundle, và bạn sẽ phải tự xử lý bao nhiêu công việc trong vài năm tiếp theo. Hầu hết các đội ngũ lựa chọn dựa trên mức độ phổ biến, rồi sau đó mới nhận ra sự đánh đổi khi ứng dụng chạm mốc 2.000 key.
|
|
25
|
+
|
|
26
|
+
Hướng dẫn này tiếp cận theo hướng ngược lại: hãy trả lời vài câu hỏi về dự án của bạn trước, sau đó đối chiếu các câu trả lời với những thư viện phù hợp. Hướng dẫn tập trung vào React thuần (Vite, React Router, TanStack Start). Next.js có những ràng buộc riêng, được đề cập trong [bài so sánh Next.js](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md).
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
## Mục lục
|
|
31
|
+
|
|
32
|
+
<TOC/>
|
|
33
|
+
|
|
34
|
+
## Sáu câu hỏi cần trả lời trước khi so sánh các thư viện
|
|
35
|
+
|
|
36
|
+
Bảng so sánh tính năng sẽ vô nghĩa nếu bạn không biết tiêu chí nào thực sự quan trọng với mình. Hãy xem xét các câu hỏi này trước.
|
|
37
|
+
|
|
38
|
+
1. **Ứng dụng được render như thế nào?** Chỉ SPA, SSR kèm hydration, hay React Server Components. Các hook dựa trên Context hoạt động ở mọi nơi trong SPA. Với RSC, một hook sẽ buộc mọi component render văn bản phải dùng `"use client"`, vì vậy bạn cũng sẽ cần một API phía server.
|
|
39
|
+
2. **Ai là người viết bản dịch?** Developer, đội ngũ nội bộ dùng TMS, agency bàn giao file ICU, hay một AI pipeline. Yếu tố này quyết định định dạng catalog nhiều hơn bất kỳ chi tiết API nào.
|
|
40
|
+
3. **Có bao nhiêu locale và trang?** Hai locale và năm trang có thể nạp toàn bộ nội dung cùng lúc. Nhưng mười locale và năm mươi route thì không thể, và chiến lược tải dữ liệu (loading strategy) sẽ trở thành chi phí chính.
|
|
41
|
+
4. **Bạn có cần type cho các key không?** Lỗi chính tả trong `t("checkout.totl")` vẫn biên dịch bình thường trong mọi thư viện dùng key trừ khi bạn tự cấu hình type. Hãy quyết định xem điều đó có chấp nhận được hay không.
|
|
42
|
+
5. **Chuỗi chứa những nội dung gì?** Văn bản thuần túy, số nhiều (plurals), hay các câu có chèn `<Link>` ở giữa. Rich content chính là nơi mà hầu hết các API trở nên cồng kềnh.
|
|
43
|
+
6. **Vòng đời dự án kéo dài bao lâu?** Một bản prototype ba tháng và một sản phẩm phát triển năm năm không cần cùng một mức độ công cụ build (build tooling).
|
|
44
|
+
|
|
45
|
+
Hãy ghi lại các câu trả lời. Mọi phân tích bên dưới đều sẽ đối chiếu lại với chúng.
|
|
46
|
+
|
|
47
|
+
## Bức tranh toàn cảnh qua một hình ảnh
|
|
48
|
+
|
|
49
|
+
Mười lăm năm phát triển của JavaScript i18n gói gọn trong bốn làn sóng kiến trúc, và các thư viện React bạn đang so sánh đến từ những làn sóng khác nhau.
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
<AccordionGroup>
|
|
54
|
+
<Accordion header="Runtime dictionary (2011 đến 2017): i18next, react-intl">
|
|
55
|
+
|
|
56
|
+
Các catalog JSON được nạp vào bộ nhớ, tra cứu `t("a.b")` tại runtime, cú pháp ICU hoặc cú pháp tùy chỉnh được phân tích trong trình duyệt. Hệ sinh thái lớn nhất, runtime nặng nhất, type safety là tùy chọn (opt-in).
|
|
57
|
+
|
|
58
|
+
</Accordion>
|
|
59
|
+
<Accordion header="Compile-time macro (2018 đến 2021): Lingui, typesafe-i18n">
|
|
60
|
+
|
|
61
|
+
Message được trích xuất khi build, biên dịch thành các catalog tinh gọn, có kiểu dữ liệu cho tham số. Đổi lấy bundle nhỏ hơn bằng một bước build bổ sung (`extract`, `compile`).
|
|
62
|
+
|
|
63
|
+
</Accordion>
|
|
64
|
+
<Accordion header="Server-first (2022 đến 2024): use-intl / next-intl">
|
|
65
|
+
|
|
66
|
+
Được thiết kế xoay quanh SSR và Server Components. Render trên server, chỉ hydrate những gì client thực sự cần. Vẫn dựa trên key và tập trung (centralized).
|
|
67
|
+
|
|
68
|
+
</Accordion>
|
|
69
|
+
<Accordion header="Trình biên dịch và colocated content (2024 đến 2026): Paraglide, Intlayer, wuchale">
|
|
70
|
+
|
|
71
|
+
Nội dung được biên dịch thành các hàm hỗ trợ tree-shaking hoặc dictionary riêng cho từng component. Type được tự động tạo, thiếu bản dịch sẽ làm dừng quá trình build, và dịch thuật AI chạy trực tiếp từ CLI.
|
|
72
|
+
|
|
73
|
+
</Accordion>
|
|
74
|
+
</AccordionGroup>
|
|
75
|
+
|
|
76
|
+
Bài viết [lịch sử JavaScript i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/history_of_i18n.md) giải thích chi tiết cách mỗi làn sóng giải quyết các vấn đề của làn sóng trước đó.
|
|
77
|
+
|
|
78
|
+
## Quyết định quan trọng nhất: nơi lưu trữ nội dung và thời điểm tải
|
|
79
|
+
|
|
80
|
+
Mọi thư viện React i18n đều có cấu trúc tương tự nhau: một store, một provider, một hook. Bất kể thứ gì provider nhận vào đều sẽ nằm trong client bundle hoặc trong hydration payload. Vì vậy, hai lựa chọn mang tính cấu trúc là:
|
|
81
|
+
|
|
82
|
+
- **Nội dung tập trung (centralized) hay phân phạm vi (scoped).** Một file `en.json` cho toàn bộ ứng dụng, hoặc một file khai báo riêng cho từng component (hoặc theo namespace).
|
|
83
|
+
- **Static import hay dynamic import.** Toàn bộ được đóng gói ngay khi khởi động, hoặc chỉ tải locale và route đang hoạt động theo nhu cầu.
|
|
84
|
+
|
|
85
|
+
Biểu đồ dưới đây ước tính payload cho một ứng dụng giả định từ 1 đến 10 trang, được dịch sang 1 đến 10 locale, với khoảng 30 KB văn bản trên mỗi trang.
|
|
86
|
+
|
|
87
|
+

|
|
88
|
+
|
|
89
|
+
Nội dung tập trung với static import sẽ tăng theo cả hai trục: 10 trang nhân với 10 locale là 300 KB văn bản trên mỗi trang. Dynamic import loại bỏ trục locale. Phân phạm vi (scoping) loại bỏ trục trang. Chỉ khi kết hợp cả hai thì dung lượng mới giữ nguyên không đổi.
|
|
90
|
+
|
|
91
|
+
Đây không phải là đặc tính của thư viện, mà là vấn đề kỷ luật kiến trúc. `react-i18next` có thể được phân vùng bằng namespace và backend tải lười (lazy backends). `use-intl` có thể được tách theo từng route. Nhưng không có gì ép buộc điều đó, và một `<Button>` dùng chung gọi `t("common:cta")` sẽ âm thầm biến `common` thành dependency của mọi route. Bản [benchmark](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/benchmark/index.md) đo lường điều này dưới dạng "rò rỉ từ các route khác" và "rò rỉ từ các locale khác", và đây là nguyên nhân chính tạo nên sự chênh lệch giữa các thư viện.
|
|
92
|
+
|
|
93
|
+
Nếu câu trả lời của bạn cho câu hỏi 3 là "nhiều locale, nhiều trang", hãy cân nhắc phần này hơn bất kỳ sở thích API nào. Bài viết [i18n theo từng component so với tập trung](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/per-component_vs_centralized_i18n.md) sẽ phân tích sâu hơn về khía cạnh bảo trì của cùng lựa chọn này.
|
|
94
|
+
|
|
95
|
+
## Các ứng cử viên
|
|
96
|
+
|
|
97
|
+
Kích thước thư viện được lấy từ [bài benchmark trên TanStack Start](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/benchmark/tanstack.md): provider kèm hook trong một component trống, sau khi bundling, tree-shaking và minification, với 10 trang và 10 locale. Nội dung được đo lường riêng biệt.
|
|
98
|
+
|
|
99
|
+
| Thư viện | Làn sóng | Mô hình nội dung | An toàn kiểu | Định dạng message | Kích thước thư viện |
|
|
100
|
+
| :---------------------- | :-------------- | :--------------------------------------------- | :----------------------------------- | :---------------------------- | :------------------------------------------------- |
|
|
101
|
+
| `react-i18next` | Runtime | JSON tập trung, namespace | 2/5 — Tùy chọn (`CustomTypeOptions`) | i18next (hậu tố số nhiều) | ~18.4 kB |
|
|
102
|
+
| `react-intl` (FormatJS) | Runtime | JSON tập trung, ICU | 2/5 — Tùy chọn (trích xuất + union) | ICU | ~15.3 kB |
|
|
103
|
+
| `use-intl` | Server-first | JSON tập trung, ICU | 2/5 — Tùy chọn (declaration merging) | ICU | ~14.1 kB |
|
|
104
|
+
| `@tolgee/react` | Runtime | Tập trung, chỉnh sửa trực tiếp (in-context) | 1/5 — Không | ICU | ~11.1 kB |
|
|
105
|
+
| Lingui | Macro | Văn bản nguồn trong code, catalog đã biên dịch | 2/5 — Tốt, từ trình biên dịch | ICU qua macro | ~11.8 kB |
|
|
106
|
+
| Paraglide | Trình biên dịch | Dự án inlang, sinh ra các hàm | 3.5/5 — Tự động tạo | Riêng | Gần như bằng 0 (do mã được sinh ra trong codebase) |
|
|
107
|
+
| Intlayer | Trình biên dịch | `.content.ts` theo từng component | 5/5 — Tự động tạo, bật mặc định | Intlayer (+ ICU, i18next, PO) | ~5.0 kB |
|
|
108
|
+
|
|
109
|
+
> Các con số là ảnh chụp nhanh tại các phiên bản benchmark và có thể thay đổi theo các bản phát hành. Hãy chạy benchmark trên chính ứng dụng của bạn trước khi đưa ra quyết định chỉ dựa vào kích thước.
|
|
110
|
+
> An toàn kiểu: 5/5 nghĩa là khóa, tham số và mọi locale đều được kiểm tra mà không cần thiết lập thủ công, bao gồm cả trình định dạng URL và các helper.
|
|
111
|
+
|
|
112
|
+
Có hai điều bảng so sánh không thể hiện. `Paraglide` hầu như không có dung lượng thư viện vì nó sinh mã trực tiếp vào repo của bạn, đồng nghĩa với việc cần thêm bước sinh lại mã trước mỗi lần commit và tiềm ẩn nguy cơ merge conflict trên các file được sinh ra. Còn `Intlayer` yêu cầu một plugin bundler (`vite-intlayer` hoặc tương đương), do đó không thể chạy trong môi trường không có bước build (no-build setup).
|
|
113
|
+
|
|
114
|
+
## Đối chiếu câu trả lời của bạn với thư viện phù hợp
|
|
115
|
+
|
|
116
|
+
<AccordionGroup>
|
|
117
|
+
<Accordion header="Bản prototype, đội ngũ nhỏ, ít locale">
|
|
118
|
+
|
|
119
|
+
Hãy chọn giải pháp đơn giản nhất hoạt động được và đừng đầu tư quá mức. `react-i18next` với một file JSON duy nhất cho mỗi locale là đủ tốt, và cả một thập kỷ câu trả lời trên Stack Overflow sẽ giúp bạn tiết kiệm thời gian. Bỏ qua namespace cho đến khi bạn thực sự cần. Nếu bản prototype trở thành một sản phẩm chính thức, hãy lên kế hoạch chuyển đổi sang nội dung phân phạm vi (scoped content), [adapter tương thích react-i18next](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/compat/react-i18next.md) sẽ giúp quá trình đó diễn ra từng bước một.
|
|
120
|
+
|
|
121
|
+
</Accordion>
|
|
122
|
+
<Accordion header="Bản dịch đến từ agency hoặc một TMS hỗ trợ ICU">
|
|
123
|
+
|
|
124
|
+
Định dạng catalog đã được định sẵn cho bạn. `react-intl` hỗ trợ ICU nguyên bản và bộ công cụ trích xuất của FormatJS được xây dựng riêng cho pipeline đó. `use-intl` cũng đọc được định dạng ICU. Trong khi đó, `react-i18next` cần plugin ICU, nếu không sẽ phải dùng các key số nhiều riêng. Khả năng hỗ trợ ICU của Intlayer hiện vẫn ở mức một phần, vì vậy nếu bạn đang nhận các chuỗi ICU hôm nay, hãy coi đó là rào cản cho đến khi tính năng này được hỗ trợ đầy đủ.
|
|
125
|
+
|
|
126
|
+
</Accordion>
|
|
127
|
+
<Accordion header="Ứng dụng lớn, nhiều route, cần tối ưu dung lượng bundle">
|
|
128
|
+
|
|
129
|
+
Nên ưu tiên scoped content và dynamic loading theo mặc định, thay vì chỉ dựa vào quy ước. `Lingui` và `Paraglide` đạt được điều này thông qua quá trình biên dịch. Intlayer đạt được thông qua khai báo theo từng component, và compiler chỉ xuất ra những gì route đó render. Với `react-i18next` hoặc `use-intl`, hãy lên kế hoạch về namespace và chiến lược lazy-loading ngay từ ngày đầu và kiểm soát chặt chẽ trong code review, vì các công cụ sẽ không tự động làm điều đó thay bạn.
|
|
130
|
+
|
|
131
|
+
</Accordion>
|
|
132
|
+
<Accordion header="Type safety là yêu cầu bắt buộc">
|
|
133
|
+
|
|
134
|
+
Mọi thư viện dựa trên key đều có thể thêm type, nhưng hầu như không có thư viện nào bật sẵn mặc định. Nếu bạn không muốn duy trì declaration merging vốn rất phức tạp khi kết hợp với các namespace tải lười, hãy chọn một thư viện mà type được sinh tự động từ nội dung: `Lingui`, `Paraglide`, hoặc Intlayer. Bài viết [phát hiện bản dịch còn thiếu](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/detecting_missing_translations.md) sẽ so sánh những gì mỗi thư viện có thể bắt được trong thời gian build.
|
|
135
|
+
|
|
136
|
+
</Accordion>
|
|
137
|
+
<Accordion header="Nhiều nội dung phức tạp: markdown, link lồng trong câu, component riêng theo locale">
|
|
138
|
+
|
|
139
|
+
Các node rich content là nơi hàm `t()` trả về chuỗi văn bản bộc lộ hạn chế. `react-i18next` và `Lingui` có `<Trans>`, `react-intl` có các thẻ rich text, và tất cả chúng đều phức tạp hơn so với trường hợp chuỗi thông thường. Các node nội dung của Intlayer chấp nhận trực tiếp JSX, markdown và các object lồng nhau, mang lại sự tiện lợi vượt trội nếu nội dung của bạn không chỉ đơn thuần là các nhãn UI.
|
|
140
|
+
|
|
141
|
+
</Accordion>
|
|
142
|
+
<Accordion header="Bản dịch do AI tạo ra và developer review">
|
|
143
|
+
|
|
144
|
+
Khi đó, một file JSON tập trung không còn là yêu cầu bắt buộc, vì không cần import vào TMS. Nội dung đồng vị trí (colocated content) kết hợp với CLI tự động điền các locale còn thiếu là con đường ngắn nhất. Lệnh `fill` của Intlayer chạy với API key của chính bạn (OpenAI, Anthropic, Mistral, Gemini) và chỉ dịch những nội dung có thay đổi. Paraglide và Tolgee cung cấp các giải pháp tương đương dạng hosted với các gói dịch vụ riêng.
|
|
145
|
+
|
|
146
|
+
</Accordion>
|
|
147
|
+
<Accordion header="Bạn có thể chuyển sang Next.js App Router sau này">
|
|
148
|
+
|
|
149
|
+
React Context không thể vượt qua ranh giới giữa server và client. Các thư viện chỉ xây dựng dựa trên client hook (`react-i18next`, `react-intl`) sẽ cần một API server song song ngay khi bạn áp dụng RSC. `use-intl` (dưới dạng `next-intl`) và Intlayer (dưới dạng `next-intlayer`) đã có sẵn sự phân chia đó. Hãy đọc [bài viết về Next.js i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/list_i18n_technologies/frameworks/nextjs.md) trước khi chuẩn hóa một mô hình.
|
|
150
|
+
|
|
151
|
+
</Accordion>
|
|
152
|
+
</AccordionGroup>
|
|
153
|
+
|
|
154
|
+
## Những điểm hạn chế của từng thư viện
|
|
155
|
+
|
|
156
|
+
Những hạn chế thực tế, bởi vì lựa chọn nào cũng có điểm trừ.
|
|
157
|
+
|
|
158
|
+
- **`react-i18next`**: thư viện nặng nhất trong danh sách, định dạng số nhiều riêng, type safety cần bạn tự cấu hình và duy trì, các dead key tích tụ âm thầm theo thời gian.
|
|
159
|
+
- **`react-intl`**: DX dài dòng (`useIntl()` rồi `formatMessage({ id })`), instance toàn cục gắn với nhiều node.
|
|
160
|
+
- **`use-intl`**: dễ bắt đầu nhưng khó tối ưu. Việc kết hợp namespace, dynamic loading và type làm chậm tốc độ phát triển khá nhiều.
|
|
161
|
+
- **`Lingui`**: cần thêm bước build `extract` / `compile`, nhiều cú pháp chồng chéo (`t()`, tagged template, `i18n.t()`, `<Trans>`) gây bối rối cho cả lập trình viên lẫn trợ lý AI.
|
|
162
|
+
- **`Paraglide`**: sinh các file mã nguồn trực tiếp vào repo, tree-shaking không có tác dụng trong bài benchmark React, và locale được đọc từ bộ lưu trữ trên mỗi node thay vì từ một store.
|
|
163
|
+
- **`Tolgee`**: không có type cho key, quá trình làm quen ban đầu khó hơn, điểm mạnh lớn nhất là khả năng chỉnh sửa trực tiếp trong ngữ cảnh (in-context editing).
|
|
164
|
+
- **`Intlayer`**: bắt buộc dùng plugin build, hệ sinh thái nhỏ hơn, hỗ trợ ICU ở mức một phần, nội dung phân tán khắp codebase theo thiết kế nên việc xuất một file JSON duy nhất cho biên dịch viên cần công cụ hỗ trợ.
|
|
165
|
+
- **`gt-react`, `lingo.dev`**: không được khuyến nghị trong benchmark: lỗi hạn ngạch (quota) khi build, phụ thuộc nhà cung cấp (vendor lock-in), và các vấn đề phản ứng dữ liệu (reactivity) đòi hỏi phải ép provider re-render.
|
|
166
|
+
|
|
167
|
+
## Mã nguồn thực tế trông như thế nào
|
|
168
|
+
|
|
169
|
+
Cùng một component, phần tóm tắt giỏ hàng gồm tiêu đề và dạng số nhiều, được viết bằng từng ứng cử viên. Điểm thú vị không nằm ở chính component, mà ở vị trí lưu trữ nội dung và những gì trình kiểm tra kiểu dữ liệu (type checker) nhận biết được về nó.
|
|
170
|
+
|
|
171
|
+
<Tabs defaultTab="react-i18next">
|
|
172
|
+
<Tab label="react-i18next" value="react-i18next">
|
|
173
|
+
|
|
174
|
+
<Tabs group="locale">
|
|
175
|
+
<Tab value="en" label="Tiếng Anh">
|
|
176
|
+
|
|
177
|
+
```json fileName="public/locales/en/cart.json"
|
|
178
|
+
{
|
|
179
|
+
"title": "Your cart",
|
|
180
|
+
"items_one": "{{count}} item",
|
|
181
|
+
"items_other": "{{count}} items"
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
</Tab>
|
|
186
|
+
<Tab value="fr" label="Tiếng Pháp">
|
|
187
|
+
|
|
188
|
+
```json fileName="public/locales/fr/cart.json"
|
|
189
|
+
{
|
|
190
|
+
"title": "Votre panier",
|
|
191
|
+
"items_one": "{{count}} article",
|
|
192
|
+
"items_other": "{{count}} articles"
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
</Tab>
|
|
197
|
+
<Tab value="es" label="Tiếng Tây Ban Nha">
|
|
198
|
+
|
|
199
|
+
```json fileName="public/locales/es/cart.json"
|
|
200
|
+
{
|
|
201
|
+
"title": "Tu carrito",
|
|
202
|
+
"items_one": "{{count}} artículo",
|
|
203
|
+
"items_other": "{{count}} artículos"
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
</Tab>
|
|
208
|
+
</Tabs>
|
|
209
|
+
|
|
210
|
+
```tsx fileName="src/components/CartSummary.tsx"
|
|
211
|
+
import type { FC } from "react";
|
|
212
|
+
import { useTranslation } from "react-i18next";
|
|
213
|
+
|
|
214
|
+
export const CartSummary: FC<{ count: number }> = ({ count }) => {
|
|
215
|
+
const { t } = useTranslation("cart");
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<section>
|
|
219
|
+
<h2>{t("title")}</h2>
|
|
220
|
+
<p>{t("items", { count })}</p>
|
|
221
|
+
</section>
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Dạng số nhiều là các hậu tố key được phân giải qua `Intl.PluralRules`. `t` có kiểu `(key: string) => string` trừ khi bạn khai báo `CustomTypeOptions`, vì vậy `t("titel")` vẫn biên dịch bình thường.
|
|
227
|
+
|
|
228
|
+
</Tab>
|
|
229
|
+
<Tab label="react-intl" value="react-intl">
|
|
230
|
+
|
|
231
|
+
<Tabs group="locale">
|
|
232
|
+
<Tab value="en" label="Tiếng Anh">
|
|
233
|
+
|
|
234
|
+
```json fileName="src/locales/en.json"
|
|
235
|
+
{
|
|
236
|
+
"cart.title": "Your cart",
|
|
237
|
+
"cart.items": "{count, plural, one {# item} other {# items}}"
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
</Tab>
|
|
242
|
+
<Tab value="fr" label="Tiếng Pháp">
|
|
243
|
+
|
|
244
|
+
```json fileName="src/locales/fr.json"
|
|
245
|
+
{
|
|
246
|
+
"cart.title": "Votre panier",
|
|
247
|
+
"cart.items": "{count, plural, one {# article} other {# articles}}"
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
</Tab>
|
|
252
|
+
<Tab value="es" label="Tiếng Tây Ban Nha">
|
|
253
|
+
|
|
254
|
+
```json fileName="src/locales/es.json"
|
|
255
|
+
{
|
|
256
|
+
"cart.title": "Tu carrito",
|
|
257
|
+
"cart.items": "{count, plural, one {# artículo} other {# artículos}}"
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
</Tab>
|
|
262
|
+
</Tabs>
|
|
263
|
+
|
|
264
|
+
```tsx fileName="src/components/CartSummary.tsx"
|
|
265
|
+
import type { FC } from "react";
|
|
266
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
267
|
+
|
|
268
|
+
export const CartSummary: FC<{ count: number }> = ({ count }) => {
|
|
269
|
+
const intl = useIntl();
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<section>
|
|
273
|
+
<h2>
|
|
274
|
+
<FormattedMessage id="cart.title" />
|
|
275
|
+
</h2>
|
|
276
|
+
<p>{intl.formatMessage({ id: "cart.items" }, { count })}</p>
|
|
277
|
+
</section>
|
|
278
|
+
);
|
|
279
|
+
};
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Sử dụng ICU toàn diện, đây cũng là định dạng mà hầu hết các nền tảng TMS xuất ra. Type cho `id` có được nhờ bước trích xuất của `formatjs` kết hợp với một union được sinh ra, chứ không có sẵn mặc định.
|
|
283
|
+
|
|
284
|
+
</Tab>
|
|
285
|
+
<Tab label="use-intl" value="use-intl">
|
|
286
|
+
|
|
287
|
+
<Tabs group="locale">
|
|
288
|
+
<Tab value="en" label="Tiếng Anh">
|
|
289
|
+
|
|
290
|
+
```json fileName="messages/en.json"
|
|
291
|
+
{
|
|
292
|
+
"Cart": {
|
|
293
|
+
"title": "Your cart",
|
|
294
|
+
"items": "{count, plural, one {# item} other {# items}}"
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
</Tab>
|
|
300
|
+
<Tab value="fr" label="Tiếng Pháp">
|
|
301
|
+
|
|
302
|
+
```json fileName="messages/fr.json"
|
|
303
|
+
{
|
|
304
|
+
"Cart": {
|
|
305
|
+
"title": "Votre panier",
|
|
306
|
+
"items": "{count, plural, one {# article} other {# articles}}"
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
</Tab>
|
|
312
|
+
<Tab value="es" label="Tiếng Tây Ban Nha">
|
|
313
|
+
|
|
314
|
+
```json fileName="messages/es.json"
|
|
315
|
+
{
|
|
316
|
+
"Cart": {
|
|
317
|
+
"title": "Tu carrito",
|
|
318
|
+
"items": "{count, plural, one {# artículo} other {# artículos}}"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
</Tab>
|
|
324
|
+
</Tabs>
|
|
325
|
+
|
|
326
|
+
```tsx fileName="src/components/CartSummary.tsx"
|
|
327
|
+
import type { FC } from "react";
|
|
328
|
+
import { useTranslations } from "use-intl";
|
|
329
|
+
|
|
330
|
+
export const CartSummary: FC<{ count: number }> = ({ count }) => {
|
|
331
|
+
const t = useTranslations("Cart");
|
|
332
|
+
|
|
333
|
+
return (
|
|
334
|
+
<section>
|
|
335
|
+
<h2>{t("title")}</h2>
|
|
336
|
+
<p>{t("items", { count })}</p>
|
|
337
|
+
</section>
|
|
338
|
+
);
|
|
339
|
+
};
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Cấu trúc tương tự như `next-intl` nhưng không có các binding của Next.js. Các key được định kiểu sau khi bạn mở rộng `AppConfig` với kiểu dữ liệu của message; việc phân chia namespace do bạn tự quản lý.
|
|
343
|
+
|
|
344
|
+
</Tab>
|
|
345
|
+
<Tab label="Lingui" value="lingui">
|
|
346
|
+
|
|
347
|
+
```po fileName="src/locales/fr/messages.po"
|
|
348
|
+
msgid "Your cart"
|
|
349
|
+
msgstr "Votre panier"
|
|
350
|
+
|
|
351
|
+
msgid "{count, plural, one {# item} other {# items}}"
|
|
352
|
+
msgstr "{count, plural, one {# article} other {# articles}}"
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
```tsx fileName="src/components/CartSummary.tsx"
|
|
356
|
+
import type { FC } from "react";
|
|
357
|
+
import { Plural, Trans } from "@lingui/react/macro";
|
|
358
|
+
|
|
359
|
+
export const CartSummary: FC<{ count: number }> = ({ count }) => (
|
|
360
|
+
<section>
|
|
361
|
+
<h2>
|
|
362
|
+
<Trans>Your cart</Trans>
|
|
363
|
+
</h2>
|
|
364
|
+
<p>
|
|
365
|
+
<Plural value={count} one="# item" other="# items" />
|
|
366
|
+
</p>
|
|
367
|
+
</section>
|
|
368
|
+
);
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Ngôn ngữ nguồn nằm ngay trong component; các locale khác nằm trong các file `.po` dưới dạng id băm (hash) sau khi chạy `lingui extract`. Nếu quên chạy `extract` hoặc `compile`, ứng dụng sẽ âm thầm fallback về tiếng Anh.
|
|
372
|
+
|
|
373
|
+
</Tab>
|
|
374
|
+
<Tab label="Paraglide" value="paraglide">
|
|
375
|
+
|
|
376
|
+
<Tabs group="locale">
|
|
377
|
+
<Tab value="en" label="Tiếng Anh">
|
|
378
|
+
|
|
379
|
+
```json fileName="messages/en.json"
|
|
380
|
+
{
|
|
381
|
+
"cart_title": "Your cart",
|
|
382
|
+
"cart_items": "{count} items"
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
</Tab>
|
|
387
|
+
<Tab value="fr" label="Tiếng Pháp">
|
|
388
|
+
|
|
389
|
+
```json fileName="messages/fr.json"
|
|
390
|
+
{
|
|
391
|
+
"cart_title": "Votre panier",
|
|
392
|
+
"cart_items": "{count} articles"
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
</Tab>
|
|
397
|
+
<Tab value="es" label="Tiếng Tây Ban Nha">
|
|
398
|
+
|
|
399
|
+
```json fileName="messages/es.json"
|
|
400
|
+
{
|
|
401
|
+
"cart_title": "Tu carrito",
|
|
402
|
+
"cart_items": "{count} artículos"
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
</Tab>
|
|
407
|
+
</Tabs>
|
|
408
|
+
|
|
409
|
+
```tsx fileName="src/components/CartSummary.tsx"
|
|
410
|
+
import type { FC } from "react";
|
|
411
|
+
import { m } from "../paraglide/messages.js";
|
|
412
|
+
|
|
413
|
+
export const CartSummary: FC<{ count: number }> = ({ count }) => (
|
|
414
|
+
<section>
|
|
415
|
+
<h2>{m.cart_title()}</h2>
|
|
416
|
+
<p>{m.cart_items({ count })}</p>
|
|
417
|
+
</section>
|
|
418
|
+
);
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Mỗi message là một hàm được sinh tự động và có kiểu dữ liệu, do đó một key bị thiếu sẽ là lỗi import. Thư mục `paraglide/` được sinh trực tiếp vào repo của bạn và được tạo lại mỗi khi có thay đổi.
|
|
422
|
+
|
|
423
|
+
</Tab>
|
|
424
|
+
<Tab label="Intlayer" value="intlayer">
|
|
425
|
+
|
|
426
|
+
```ts fileName="src/components/cartSummary.content.ts"
|
|
427
|
+
import { plural, t, type Dictionary } from "intlayer";
|
|
428
|
+
|
|
429
|
+
const cartSummaryContent = {
|
|
430
|
+
key: "cart-summary",
|
|
431
|
+
content: {
|
|
432
|
+
title: t({
|
|
433
|
+
vi: "Giỏ hàng của bạn",
|
|
434
|
+
en: "Your cart",
|
|
435
|
+
fr: "Votre panier",
|
|
436
|
+
es: "Tu carrito",
|
|
437
|
+
}),
|
|
438
|
+
items: t({
|
|
439
|
+
vi: plural({ one: "{{count}} sản phẩm", other: "{{count}} sản phẩm" }),
|
|
440
|
+
en: plural({ one: "{{count}} item", other: "{{count}} items" }),
|
|
441
|
+
fr: plural({ one: "{{count}} article", other: "{{count}} articles" }),
|
|
442
|
+
es: plural({ one: "{{count}} artículo", other: "{{count}} artículos" }),
|
|
443
|
+
}),
|
|
444
|
+
},
|
|
445
|
+
} satisfies Dictionary;
|
|
446
|
+
|
|
447
|
+
export default cartSummaryContent;
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
```tsx fileName="src/components/CartSummary.tsx"
|
|
451
|
+
import type { FC } from "react";
|
|
452
|
+
import { useIntlayer } from "react-intlayer";
|
|
453
|
+
|
|
454
|
+
export const CartSummary: FC<{ count: number }> = ({ count }) => {
|
|
455
|
+
const { title, items } = useIntlayer("cart-summary");
|
|
456
|
+
|
|
457
|
+
return (
|
|
458
|
+
<section>
|
|
459
|
+
<h2>{title}</h2>
|
|
460
|
+
<p>{items(count)}</p>
|
|
461
|
+
</section>
|
|
462
|
+
);
|
|
463
|
+
};
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Tất cả các locale nằm trong một file duy nhất đặt cạnh component. Type được sinh ra khi build, nên `title` có thể tự động hoàn thành và lỗi chính tả sẽ làm fail lệnh `tsc` mà không cần declaration merging. Xóa thư mục component cũng đồng nghĩa với việc xóa sạch các chuỗi liên quan.
|
|
467
|
+
|
|
468
|
+
</Tab>
|
|
469
|
+
</Tabs>
|
|
470
|
+
|
|
471
|
+
Bạn đã đang sử dụng `react-i18next`, `react-intl` hoặc `Lingui`? Các adapter tương thích ([react-i18next](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/compat/react-i18next.md), [react-intl](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/compat/react-intl.md), [Lingui](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/compat/lingui.md)) sẽ tạo alias cho các import ở cấp độ bundler, giúp API hiện tại tiếp tục hoạt động trong khi bạn chuyển đổi từng component một. [Hướng dẫn chuyển đổi](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/migration_from_react-i18next_to_intlayer.md) sẽ hướng dẫn các phần còn lại.
|
|
472
|
+
|
|
473
|
+
## Trước khi bạn đưa ra quyết định
|
|
474
|
+
|
|
475
|
+
Bảng tính năng cho bạn biết thư viện làm được gì hôm nay. Những điểm dưới đây sẽ cho bạn biết trải nghiệm sử dụng nó lâu dài sẽ như thế nào.
|
|
476
|
+
|
|
477
|
+
**Kiểm tra mức độ hoạt động của repository.**
|
|
478
|
+
|
|
479
|
+
Commits, thời gian phản hồi issue, và liệu bản minor release gần nhất có phải trong năm nay hay không. Một thiết kế tốt nhưng không có người duy trì sẽ sớm trở thành một gánh nặng cần di chuyển mã nguồn sau này.
|
|
480
|
+
|
|
481
|
+
**Đừng chọn chỉ dựa vào lượt tải trên npm.**
|
|
482
|
+
|
|
483
|
+
Thư viện có lượt tải nhiều nhất là thư viện ra mắt đầu tiên, chứ không hẳn là thư viện phù hợp nhất cho một codebase React năm 2026. Lượt tải phản ánh lịch sử, không phản ánh mức độ tương thích.
|
|
484
|
+
|
|
485
|
+

|
|
486
|
+
|
|
487
|
+
**Hãy hỏi ai là người trả tiền cho maintainer, và họ kinh doanh cái gì.**
|
|
488
|
+
|
|
489
|
+
`i18next` được hậu thuẫn bởi Locize. `next-intl` / `use-intl`, `vue-i18n`, `svelte-i18n` và Lingui được tài trợ bởi Crowdin. Tolgee, Paraglide (inlang) và Intlayer đều vận hành nền tảng riêng của họ. Một nhà cung cấp có doanh thu đến từ dịch vụ lưu trữ bản dịch (hosted translation) sẽ có rất ít động lực để cung cấp dịch vụ dịch thuật miễn phí ngay trong chuỗi công cụ của bạn. Intlayer là thư viện duy nhất trong số này cung cấp tính năng dịch thuật bằng AI qua CLI bằng API key của chính bạn, cùng một CMS có thể tự host (self-host).
|
|
490
|
+
|
|
491
|
+
**Thư viện đã sẵn sàng cho AI agent chưa?**
|
|
492
|
+
|
|
493
|
+
Các agent hiện nay vẫn gặp khó khăn với i18n: chúng quên locale, tự tạo ra key lạ, và trộn lẫn các cú pháp message. Thư viện có cung cấp [Agent Skills](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/agent_skills.md) hay [MCP server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/mcp_server.md) để agent có thể liệt kê, điền và kiểm thử nội dung không? Và việc tải nội dung có được tối ưu hóa theo mặc định hay không, hay hàng quý vẫn phải có người rà soát lại namespace và lazy import?
|
|
494
|
+
|
|
495
|
+
**Tính an toàn kiểu dữ liệu (type safety) có sẵn ngay từ đầu.**
|
|
496
|
+
|
|
497
|
+
Không phải kiểu "có thể định kiểu với cấu hình bổ sung", mà là "một key sai sẽ làm fail `tsc` ngay trên bản cài đặt mới tinh". Hãy kiểm tra điều gì xảy ra với một key không tồn tại, và với một locale bị thiếu một bản dịch.
|
|
498
|
+
|
|
499
|
+
**Phát hiện nội dung không sử dụng.**
|
|
500
|
+
|
|
501
|
+
Các catalog chỉ có xu hướng phình to ra. Quá trình build của Intlayer sẽ loại bỏ các trường không dùng và ghi log lại (`build.purge`). Paraglide đạt được điều này nhờ kiến trúc, vì một hàm message không được gọi sẽ bị loại bỏ qua tree-shaking. Tất cả các thư viện còn lại đều để việc dọn dẹp cho bạn tự xử lý.
|
|
502
|
+
|
|
503
|
+
**Trải nghiệm lập trình viên (Developer Experience).**
|
|
504
|
+
|
|
505
|
+
Thời gian thiết lập đến chuỗi dịch đầu tiên, một [LSP](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/lsp.md) hoặc [tiện ích mở rộng VS Code](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/vs_code_extension.md) hiển thị bản dịch khi hover và nhảy đến phần khai báo, một [CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/cli/index.md) để fill, test và push, một [trình biên dịch](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/compiler.md) hoặc trình trích xuất lấy các chuỗi hard-code ra khỏi component để bạn không phải quản lý từng chuỗi theo từng khóa, cùng phương thức cho người không phải lập trình viên chỉnh sửa nội dung ([visual editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_visual_editor.md) hoặc [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_CMS.md)) mà không cần tạo pull request.
|
|
506
|
+
|
|
507
|
+
## Câu hỏi thường gặp
|
|
508
|
+
|
|
509
|
+
<FAQ>
|
|
510
|
+
|
|
511
|
+
<Question title="react-i18next có còn là lựa chọn mặc định tốt trong năm 2026 không?">
|
|
512
|
+
|
|
513
|
+
Có, đối với hầu hết các đội ngũ. Thư viện này sở hữu hệ sinh thái lớn nhất và lượng câu trả lời phong phú nhất trên internet. Chi phí của nó rất rõ ràng và có thể dự đoán được: runtime nặng nhất, định dạng số nhiều tùy chỉnh, cùng với type safety và scoping mà bạn phải tự thiết lập và duy trì.
|
|
514
|
+
|
|
515
|
+
</Question>
|
|
516
|
+
|
|
517
|
+
<Question title="Tôi có cần một thư viện dựa trên trình biên dịch không?">
|
|
518
|
+
|
|
519
|
+
Chỉ khi dung lượng bundle, type được sinh tự động hoặc kiểm tra thiếu key khi build nằm trong các yêu cầu của bạn. Đối với một ứng dụng nhỏ có hai locale, một thư viện runtime sẽ đơn giản hơn. Bài viết [trình biên dịch so với i18n khai báo](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/compiler_vs_declarative_i18n.md) giải thích những gì trình biên dịch mang lại và những điểm có thể gặp trục trặc.
|
|
520
|
+
|
|
521
|
+
</Question>
|
|
522
|
+
|
|
523
|
+
<Question title="Tôi có thể đổi thư viện sau này mà không cần viết lại mọi component không?">
|
|
524
|
+
|
|
525
|
+
Một phần. Các thư viện dựa trên key chia sẻ cấu trúc đủ tương đồng để một adapter tương thích có thể tạo alias từ API này sang API khác, đó là cách các adapter của Intlayer hoạt động. Định dạng message (ICU so với i18next so với helper) không tự động chuyển đổi, vì vậy phần số nhiều và nội suy (interpolation) sẽ là phần bạn cần chỉnh sửa.
|
|
526
|
+
|
|
527
|
+
</Question>
|
|
528
|
+
|
|
529
|
+
<Question title="Lựa chọn thư viện có ảnh hưởng đến SEO không?">
|
|
530
|
+
|
|
531
|
+
Ảnh hưởng gián tiếp. Những gì công cụ tìm kiếm (crawler) nhìn thấy được quyết định bởi routing, `hreflang`, `<html lang>` và việc văn bản có nằm trong HTML được render phía server hay không. Một số thư viện cung cấp các helper cho việc đó, hầu hết để bạn tự xử lý. Xem [hướng dẫn hreflang](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/hreflang_guide_multilingual_seo.md).
|
|
532
|
+
|
|
533
|
+
</Question>
|
|
534
|
+
|
|
535
|
+
</FAQ>
|
|
536
|
+
|
|
537
|
+
## Đọc thêm
|
|
538
|
+
|
|
539
|
+
- [Benchmark các thư viện i18n: kích thước bundle, rò rỉ và thời gian chuyển đổi locale](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/benchmark/index.md) và [báo cáo TanStack Start](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/benchmark/tanstack.md)
|
|
540
|
+
- [React i18n: mô hình provider hoạt động như thế nào và chi phí ra sao](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/list_i18n_technologies/frameworks/react.md)
|
|
541
|
+
- [react-i18next so với react-intl so với Intlayer, so sánh từng tính năng](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md)
|
|
542
|
+
- [next-i18next so với next-intl so với Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md)
|
|
543
|
+
- [Lịch sử của JavaScript i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/history_of_i18n.md)
|
|
544
|
+
- [Trình biên dịch so với i18n khai báo](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/compiler_vs_declarative_i18n.md)
|
|
545
|
+
- [i18n theo từng component so với tập trung](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/per-component_vs_centralized_i18n.md)
|
|
546
|
+
- [Cách tối ưu hóa bundle hoạt động trong thời gian build](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/bundle_optimization.md)
|
|
547
|
+
- [Thiết lập i18n trong ứng dụng Vite + React](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_with_vite+react.md)
|
|
548
|
+
- Hướng dẫn tương tự cho [Vue](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/how_to_pick_vue_i18n_library.md), [Svelte](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/how_to_pick_svelte_i18n_library.md) và [Solid](https://github.com/aymericzip/intlayer/blob/main/docs/blog/vi/how_to_pick_solid_i18n_library.md)
|