@intlayer/docs 9.5.2 → 9.5.4-canary.0
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 +9 -9
- 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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ar/i18next_vs_intlayer.md +445 -0
- package/blog/ar/is_i18next_outdated.md +6 -2
- package/blog/ar/is_next-intl_outdated.md +6 -2
- package/blog/ar/is_vue-i18n_outdated.md +8 -2
- 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 +9 -5
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ar/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/de/i18next_vs_intlayer.md +445 -0
- package/blog/de/is_i18next_outdated.md +6 -2
- package/blog/de/is_next-intl_outdated.md +6 -2
- package/blog/de/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/de/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/en/i18next_vs_intlayer.md +445 -0
- package/blog/en/is_i18next_outdated.md +6 -2
- package/blog/en/is_next-intl_outdated.md +6 -2
- package/blog/en/is_vue-i18n_outdated.md +8 -2
- package/blog/en/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/en/lingui_vs_intlayer.md +381 -0
- package/blog/en/list_i18n_technologies/frameworks/react-router.md +2 -3
- package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/en/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/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 +6 -2
- package/blog/en-GB/is_next-intl_outdated.md +6 -2
- package/blog/en-GB/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/en-GB/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/es/i18next_vs_intlayer.md +445 -0
- package/blog/es/is_i18next_outdated.md +6 -2
- package/blog/es/is_next-intl_outdated.md +6 -2
- package/blog/es/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/es/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/fr/i18next_vs_intlayer.md +445 -0
- package/blog/fr/is_i18next_outdated.md +6 -2
- package/blog/fr/is_next-intl_outdated.md +6 -2
- package/blog/fr/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/fr/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/hi/i18next_vs_intlayer.md +445 -0
- package/blog/hi/is_i18next_outdated.md +6 -2
- package/blog/hi/is_next-intl_outdated.md +6 -2
- package/blog/hi/is_vue-i18n_outdated.md +8 -2
- package/blog/hi/lingui_vs_intlayer-lingui.md +304 -0
- package/blog/hi/lingui_vs_intlayer.md +381 -0
- package/blog/hi/next-i18next_vs_next-intl_vs_intlayer.md +8 -4
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/hi/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/id/i18next_vs_intlayer.md +445 -0
- package/blog/id/is_i18next_outdated.md +6 -2
- package/blog/id/is_next-intl_outdated.md +6 -2
- package/blog/id/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/id/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/it/i18next_vs_intlayer.md +445 -0
- package/blog/it/is_i18next_outdated.md +6 -2
- package/blog/it/is_next-intl_outdated.md +6 -2
- package/blog/it/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/it/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ja/i18next_vs_intlayer.md +447 -0
- package/blog/ja/is_i18next_outdated.md +6 -2
- package/blog/ja/is_next-intl_outdated.md +6 -2
- package/blog/ja/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ja/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ko/i18next_vs_intlayer.md +447 -0
- package/blog/ko/is_i18next_outdated.md +6 -2
- package/blog/ko/is_next-intl_outdated.md +6 -2
- package/blog/ko/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ko/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/pl/i18next_vs_intlayer.md +445 -0
- package/blog/pl/is_i18next_outdated.md +6 -2
- package/blog/pl/is_next-intl_outdated.md +6 -2
- package/blog/pl/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/pl/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/pt/i18next_vs_intlayer.md +445 -0
- package/blog/pt/is_i18next_outdated.md +6 -2
- package/blog/pt/is_next-intl_outdated.md +6 -2
- package/blog/pt/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/pt/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/ru/i18next_vs_intlayer.md +445 -0
- package/blog/ru/is_i18next_outdated.md +6 -2
- package/blog/ru/is_next-intl_outdated.md +6 -2
- package/blog/ru/is_vue-i18n_outdated.md +8 -2
- 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 +9 -5
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/ru/react-i18next_vs_react-intl_vs_intlayer.md +5 -1
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/tr/i18next_vs_intlayer.md +445 -0
- package/blog/tr/is_i18next_outdated.md +6 -2
- package/blog/tr/is_next-intl_outdated.md +6 -2
- package/blog/tr/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/tr/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/uk/i18next_vs_intlayer.md +445 -0
- package/blog/uk/is_i18next_outdated.md +6 -2
- package/blog/uk/is_next-intl_outdated.md +6 -2
- package/blog/uk/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/uk/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/vi/i18next_vs_intlayer.md +445 -0
- package/blog/vi/is_i18next_outdated.md +6 -2
- package/blog/vi/is_next-intl_outdated.md +6 -2
- package/blog/vi/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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/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/i18next_vs_intlayer-i18next.md +327 -0
- package/blog/zh/i18next_vs_intlayer.md +445 -0
- package/blog/zh/is_i18next_outdated.md +6 -2
- package/blog/zh/is_next-intl_outdated.md +6 -2
- package/blog/zh/is_vue-i18n_outdated.md +8 -2
- 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 +10 -6
- 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/per-component_vs_centralized_i18n.md +9 -4
- package/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md +6 -2
- 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 +240 -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/cjs/index.cjs +1 -1
- package/dist/esm/generated/blog.entry.mjs +240 -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/esm/index.mjs +1 -1
- package/dist/types/generated/blog.entry.d.ts +12 -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/bundle_optimization.md +5 -1
- package/docs/ar/how_works_intlayer.md +2 -2
- package/docs/ar/interest_of_intlayer.md +7 -7
- 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 +22 -22
- 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 +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/de/how_works_intlayer.md +2 -2
- package/docs/de/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/en/how_works_intlayer.md +2 -2
- package/docs/en/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/en-GB/how_works_intlayer.md +2 -2
- package/docs/en-GB/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/es/how_works_intlayer.md +2 -2
- package/docs/es/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/fr/how_works_intlayer.md +2 -2
- package/docs/fr/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/hi/how_works_intlayer.md +2 -2
- package/docs/hi/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/id/how_works_intlayer.md +2 -2
- package/docs/id/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/it/how_works_intlayer.md +2 -2
- package/docs/it/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/ja/how_works_intlayer.md +2 -2
- package/docs/ja/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/ko/how_works_intlayer.md +2 -2
- package/docs/ko/interest_of_intlayer.md +7 -7
- 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 +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/pl/how_works_intlayer.md +2 -2
- package/docs/pl/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/pt/how_works_intlayer.md +2 -2
- package/docs/pt/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/ru/how_works_intlayer.md +2 -2
- package/docs/ru/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/tr/how_works_intlayer.md +2 -2
- package/docs/tr/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/uk/how_works_intlayer.md +2 -2
- package/docs/uk/interest_of_intlayer.md +7 -7
- 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 +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/vi/how_works_intlayer.md +2 -2
- package/docs/vi/interest_of_intlayer.md +7 -7
- 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/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/bundle_optimization.md +5 -1
- package/docs/zh/how_works_intlayer.md +2 -2
- package/docs/zh/interest_of_intlayer.md +7 -7
- 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 +7 -7
- package/docs/zh-TW/intlayer_with_angular_21.md +1 -1
- package/docs/zh-TW/introduction.md +0 -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 +8 -7
- package/src/generated/blog.entry.ts +240 -0
- package/src/generated/frequentQuestions.entry.ts +20 -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: "如何在 2026 年选择合适的 React i18n 库"
|
|
5
|
+
description: "React 国际化选型指南。在对比 react-i18next、react-intl、Lingui、use-intl、Paraglide 和 Intlayer 之前需要回答的关键问题,以及各方案在 bundle size、类型支持和维护成本方面的权衡。"
|
|
6
|
+
keywords:
|
|
7
|
+
- React i18n
|
|
8
|
+
- React 国际化
|
|
9
|
+
- react-i18next
|
|
10
|
+
- react-intl
|
|
11
|
+
- Lingui
|
|
12
|
+
- use-intl
|
|
13
|
+
- Paraglide
|
|
14
|
+
- Intlayer
|
|
15
|
+
- i18n 库对比
|
|
16
|
+
slugs:
|
|
17
|
+
- blog
|
|
18
|
+
- how-to-pick-react-i18n-library
|
|
19
|
+
author: aymericzip
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# 如何选择合适的 React i18n 库
|
|
23
|
+
|
|
24
|
+
React 本身并没有提供内置的 i18n 原语。你在项目第一天选择的库,将决定翻译如何存储、如何打包进 bundle,以及未来几年需要承担多少维护工作。大多数团队通常根据流行度来选型,随后在翻译键达到 2,000 个时才发现各种妥协与限制。
|
|
25
|
+
|
|
26
|
+
本指南采用另一种思路:先回答关于你项目的几个核心问题,然后将答案映射到最契合的库。本文重点关注纯 React 生态(Vite、React Router、TanStack Start)。Next.js 有其专属的约束,已在 [Next.js 对比文章](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md) 中详细介绍。
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
## 目录
|
|
31
|
+
|
|
32
|
+
<TOC/>
|
|
33
|
+
|
|
34
|
+
## 在对比各库之前需要回答的 6 个问题
|
|
35
|
+
|
|
36
|
+
如果不清楚哪些指标对你最重要,功能对比表格就毫无意义。请先梳理以下问题:
|
|
37
|
+
|
|
38
|
+
1. **应用采用何种渲染方式?** 纯 SPA、带 hydration 的 SSR,还是 React Server Components。基于 Context 的 Hook 在 SPA 中处处适用;但在 RSC 中,Hook 会强制要求渲染文本的每个组件都加上 `"use client"`,因此你还需要服务端 API。
|
|
39
|
+
2. **谁来编写翻译?** 开发者、使用 TMS 的内部团队、交付 ICU 文件的翻译公司,还是 AI 自动化流程。这比任何 API 细节都更能决定翻译目录的格式。
|
|
40
|
+
3. **有多少个语言环境和页面?** 2 个语言环境和 5 个页面完全可以一次性打包所有内容;10 个语言环境和 50 个路由则无法承受,加载策略将成为核心成本。
|
|
41
|
+
4. **翻译键是否需要强类型约束?** 在所有基于键的库中,`t("checkout.totl")` 中的拼写错误都能通过编译,除非你手动配置类型。评估团队是否能接受这一点。
|
|
42
|
+
5. **文案包含哪些内容?** 纯文本、复数形式,还是中间嵌入 `<Link>` 的复杂句子。富文本内容往往是多数 API 变得臃肿的地方。
|
|
43
|
+
6. **项目的生命周期有多长?** 一个 3 个月的原型项目和一个维护 5 年的产品,对构建工具链的需求完全不同。
|
|
44
|
+
|
|
45
|
+
写下你的答案,后文的所有分析都将围绕它们展开。
|
|
46
|
+
|
|
47
|
+
## 一图看懂技术演进版图
|
|
48
|
+
|
|
49
|
+
十五年的 JavaScript i18n 发展史可以归纳为四波架构浪潮,而你所对比的 React 库正来自于不同的阶段。
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
<AccordionGroup>
|
|
54
|
+
<Accordion header="运行时字典(2011 至 2017 年):i18next, react-intl">
|
|
55
|
+
|
|
56
|
+
在内存中加载 JSON 目录,运行时查找 `t("a.b")`,并在浏览器中解析 ICU 或自定义语法。生态最庞大,运行时最重,类型支持为 opt-in(可选配置)。
|
|
57
|
+
|
|
58
|
+
</Accordion>
|
|
59
|
+
<Accordion header="编译时宏(2018 至 2021 年):Lingui, typesafe-i18n">
|
|
60
|
+
|
|
61
|
+
在构建时提取文案并编译为紧凑目录,提供类型化参数。通过增加额外的构建步骤(`extract`、`compile`)换取更小的 bundle 体积。
|
|
62
|
+
|
|
63
|
+
</Accordion>
|
|
64
|
+
<Accordion header="服务端优先(2022 至 2024 年):use-intl / next-intl">
|
|
65
|
+
|
|
66
|
+
围绕 SSR 和 Server Components 设计。在服务端完成渲染,客户端仅 hydrate 必需的内容。本质上仍然基于键且集中管理。
|
|
67
|
+
|
|
68
|
+
</Accordion>
|
|
69
|
+
<Accordion header="编译器与同构/就近内容管理(2024 至 2026 年):Paraglide, Intlayer, wuchale">
|
|
70
|
+
|
|
71
|
+
文案被编译为支持 tree-shaking 的函数或按组件划分的字典。类型自动生成,缺失翻译直接中断构建,并通过 CLI 执行 AI 翻译。
|
|
72
|
+
|
|
73
|
+
</Accordion>
|
|
74
|
+
</AccordionGroup>
|
|
75
|
+
|
|
76
|
+
[JavaScript i18n 历史](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/history_of_i18n.md) 详细探讨了每一波浪潮是如何解决前一波痛点的。
|
|
77
|
+
|
|
78
|
+
## 最关键的抉择:内容存放在哪里以及何时加载
|
|
79
|
+
|
|
80
|
+
所有 React i18n 库都具备相似的结构:一个 store、一个 provider、一个 hook。Provider 接收的任何内容最终都会进入客户端 bundle 或 hydration payload 中。因此,两个根本性的架构选择是:
|
|
81
|
+
|
|
82
|
+
- **集中式还是局部作用域内容:** 整个应用共用一个 `en.json`,还是每个组件(或每个 namespace)独立声明。
|
|
83
|
+
- **静态导入还是动态导入:** 启动时打包所有内容,还是按需获取当前语言环境与路由的内容。
|
|
84
|
+
|
|
85
|
+
下图估算了包含 1 到 10 个页面、翻译成 1 到 10 个语言环境、每页约 30 KB 文本的理论应用 payload:
|
|
86
|
+
|
|
87
|
+

|
|
88
|
+
|
|
89
|
+
采用静态导入的集中式内容会随着两个维度同时膨胀:10 个页面乘以 10 个语言环境,意味着每个页面都要加载 300 KB 的文本。动态导入消除了语言维度的膨胀,组件级作用域消除了页面维度的膨胀,只有两者结合才能让体积保持平稳。
|
|
90
|
+
|
|
91
|
+
这不仅是库的特性,更关乎工程规范。`react-i18next` 可以通过 namespace 和 lazy backend 实现作用域划分,`use-intl` 也可以按路由拆分。但工具链本身并不会强制执行,一个通用的 `<Button>` 如果调用了 `t("common:cta")`,就会悄悄让 `common` 成为所有路由的依赖。[基准测试](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/benchmark/index.md) 将这种现象衡量为“其他路由泄漏”和“其他语言泄漏”,这也是各库之间体积差距的主要来源。
|
|
92
|
+
|
|
93
|
+
如果你对第 3 个问题的答案是“多语言、多页面”,请将本节作为核心考量。[按组件 vs 集中式 i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/per-component_vs_centralized_i18n.md) 一文深入分析了这一选择在维护层面的影响。
|
|
94
|
+
|
|
95
|
+
## 候选方案一览
|
|
96
|
+
|
|
97
|
+
各库的体积数据来源于 [TanStack Start 基准测试](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/benchmark/tanstack.md):空组件中的 provider 加上 hook,在经过打包、tree-shaking 和压缩后的体积(基于 10 个页面和 10 个语言环境)。内容体积单独计算。
|
|
98
|
+
|
|
99
|
+
| 库 | 演进浪潮 | 内容模型 | 类型安全 | 消息格式 | 库体积 |
|
|
100
|
+
| :---------------------- | :--------- | :-------------------------------------- | :--------------------------------- | :---------------------------- | :--------------------------------- |
|
|
101
|
+
| `react-i18next` | 运行时 | 集中式 JSON,namespaces | 2/5 — Opt-in (`CustomTypeOptions`) | i18next (后缀复数) | ~18.4 kB |
|
|
102
|
+
| `react-intl` (FormatJS) | 运行时 | 集中式 JSON,ICU | 2/5 — Opt-in (提取 + union) | ICU | ~15.3 kB |
|
|
103
|
+
| `use-intl` | 服务端优先 | 集中式 JSON,ICU | 2/5 — Opt-in (declaration merging) | ICU | ~14.1 kB |
|
|
104
|
+
| `@tolgee/react` | 运行时 | 集中式,上下文内可视化编辑 (in-context) | 1/5 — 无 | ICU | ~11.1 kB |
|
|
105
|
+
| Lingui | 宏 | 代码内源码文本,编译后目录 | 2/5 — 良好,由编译器生成 | 基于宏的 ICU | ~11.8 kB |
|
|
106
|
+
| Paraglide | 编译器 | inlang 项目,生成函数 | 3.5/5 — 自动生成 | 自研格式 | 接近于零(因为代码生成到代码库中) |
|
|
107
|
+
| Intlayer | 编译器 | 单组件 `.content.ts` 声明 | 5/5 — 自动生成,默认开启 | Intlayer (+ ICU, i18next, PO) | ~5.0 kB |
|
|
108
|
+
|
|
109
|
+
> 数据为基准测试特定版本时的快照,会随版本更新而变动。在仅凭体积做决定前,建议在自己的应用中运行基准测试。
|
|
110
|
+
> 类型安全:5/5 表示键、参数和每个语言环境均无需手动配置即可得到校验,包括 URL 格式化工具与辅助函数。
|
|
111
|
+
|
|
112
|
+
表格中未体现的两点细节:`Paraglide` 本身体积接近于零,是因为它将代码直接生成到你的代码库中,这意味着每次 commit 前都需要重新生成,并且生成的文件可能产生 merge conflict;而 `Intlayer` 依赖打包工具插件(`vite-intlayer` 或等效插件),因此无法在无需构建工具(no-build)的环境中运行。
|
|
113
|
+
|
|
114
|
+
## 根据你的答案匹配合适的库
|
|
115
|
+
|
|
116
|
+
<AccordionGroup>
|
|
117
|
+
<Accordion header="原型开发、小型团队、少量语言环境">
|
|
118
|
+
|
|
119
|
+
选择最简单能用的方案,避免过度投入。`react-i18next` 配合每个语言一个单独的 JSON 文件即可满足需求,Stack Overflow 上十年的积累能帮你节省大量时间。在真正需要前无需引入 namespaces。如果原型后续演进为正式产品,可以规划迁移到作用域隔离的内容管理;[react-i18next 兼容适配器](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/compat/react-i18next.md) 支持渐进式迁移。
|
|
120
|
+
|
|
121
|
+
</Accordion>
|
|
122
|
+
<Accordion header="翻译来自支持 ICU 的翻译机构或 TMS">
|
|
123
|
+
|
|
124
|
+
翻译目录格式已经预先确定。`react-intl` 原生支持 ICU,FormatJS 的提取工具专为该流程构建。`use-intl` 同样读取 ICU。`react-i18next` 则需要安装 ICU 插件,否则只能使用自有的复数键规则。Intlayer 的 ICU 支持仍在完善中,如果你当前依赖 ICU 字符串,建议将其作为关键考量项。
|
|
125
|
+
|
|
126
|
+
</Accordion>
|
|
127
|
+
<Accordion header="大型应用、众多路由、严格关注 bundle 预算">
|
|
128
|
+
|
|
129
|
+
优先默认采用作用域隔离内容与动态加载,而不是依赖开发约定。`Lingui` 和 `Paraglide` 通过编译实现这一点。Intlayer 通过按组件声明实现,编译器仅打包当前路由渲染的内容。如果选用 `react-i18next` 或 `use-intl`,必须在第一天规划好 namespace 和懒加载策略并在 code review 中严格把关,因为工具链不会自动拦截违规引入。
|
|
130
|
+
|
|
131
|
+
</Accordion>
|
|
132
|
+
<Accordion header="类型安全不可妥协">
|
|
133
|
+
|
|
134
|
+
所有基于键的库都可以配置类型,但几乎没有哪个是默认启用的。如果你不想维护在懒加载 namespaces 下脆弱的 declaration merging,请选择能从内容自动生成类型的库:`Lingui`、`Paraglide` 或 Intlayer。[检测缺失翻译](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/detecting_missing_translations.md) 一文对比了各工具在构建时能捕获的错误类型。
|
|
135
|
+
|
|
136
|
+
</Accordion>
|
|
137
|
+
<Accordion header="包含大量富文本内容:markdown、句子中嵌入链接、按语言定制组件">
|
|
138
|
+
|
|
139
|
+
富文本节点是 `t()` 返回字符串模式的短板所在。`react-i18next` 和 `Lingui` 提供了 `<Trans>`,`react-intl` 提供了富文本标签,这些处理方式都比普通字符串更繁琐。Intlayer 的内容节点可直接接收 JSX、markdown 和嵌套对象,如果内容不仅限于简单 UI 标签,这种方式更为契合。
|
|
140
|
+
|
|
141
|
+
</Accordion>
|
|
142
|
+
<Accordion header="翻译由 AI 生成、开发者审核">
|
|
143
|
+
|
|
144
|
+
集中式 JSON 不再是刚需,因为无需导入到传统 TMS 中。代码就近放置的内容(colocated content)加上自动填充缺失语言的 CLI 是更高效的路径。Intlayer 的 `fill` 命令直接使用你自己的 API key(OpenAI、Anthropic、Mistral、Gemini),并且只翻译变更的内容。Paraglide 和 Tolgee 则提供了对应的托管版商业方案。
|
|
145
|
+
|
|
146
|
+
</Accordion>
|
|
147
|
+
<Accordion header="未来可能迁移至 Next.js App Router">
|
|
148
|
+
|
|
149
|
+
React context 无法跨越服务端/客户端边界。仅依赖客户端 Hook 构建的库(`react-i18next`、`react-intl`)在引入 RSC 时需要配套的服务端 API。`use-intl`(作为 `next-intl`)和 Intlayer(作为 `next-intlayer`)已经实现了这种架构拆分。在统一规范前,建议阅读 [Next.js i18n 指南](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/list_i18n_technologies/frameworks/nextjs.md)。
|
|
150
|
+
|
|
151
|
+
</Accordion>
|
|
152
|
+
</AccordionGroup>
|
|
153
|
+
|
|
154
|
+
## 各个库的局限性
|
|
155
|
+
|
|
156
|
+
客观分析每个方案都存在的局限:
|
|
157
|
+
|
|
158
|
+
- **`react-i18next`**:同类中最重,自研的复数格式,类型需手动配置与维护,废弃的无用键容易在无感知中堆积。
|
|
159
|
+
- **`react-intl`**:DX 较为繁琐(先 `useIntl()` 再 `formatMessage({ id })`),全局实例绑定了较多节点。
|
|
160
|
+
- **`use-intl`**:上手简单,优化困难。Namespaces、动态加载与类型结合使用时会显著拖慢开发节奏。
|
|
161
|
+
- **`Lingui`**:需要额外的 `extract` / `compile` 构建步骤,多种并存的语法(`t()`、标签模板、`i18n.t()`、`<Trans>`)容易让开发者和 AI 助手产生混淆。
|
|
162
|
+
- **`Paraglide`**:在仓库中生成大量代码文件,在 React 基准测试中 tree-shaking 未充分生效,且语言环境直接从 storage 读取而非统一 store。
|
|
163
|
+
- **`Tolgee`**:缺乏键类型支持,上手门槛较高,核心卖点在上下文内可视化编辑。
|
|
164
|
+
- **`Intlayer`**:必须依赖构建插件,生态相对较新,ICU 支持尚不完整,内容天然分散在代码库中,若需为外部翻译人员导出单个全量 JSON 需要借助工具。
|
|
165
|
+
- **`gt-react`, `lingo.dev`**:在基准测试中表现欠佳:构建时容易出现配额错误、厂商锁定风险,以及需要强制刷新 provider 的响应性问题。
|
|
166
|
+
|
|
167
|
+
## 代码示例对比
|
|
168
|
+
|
|
169
|
+
以同一个组件(包含标题和复数统计的购物车摘要)为例,展示各个候选方案的实现。重点不仅在于组件代码,更在于内容如何存储以及类型检查器对内容的感知能力。
|
|
170
|
+
|
|
171
|
+
<Tabs defaultTab="react-i18next">
|
|
172
|
+
<Tab label="react-i18next" value="react-i18next">
|
|
173
|
+
|
|
174
|
+
<Tabs group="locale">
|
|
175
|
+
<Tab value="en" label="英语">
|
|
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="法语">
|
|
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="西班牙语">
|
|
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
|
+
复数是基于 `Intl.PluralRules` 解析的后缀键。除非声明了 `CustomTypeOptions`,否则 `t` 的类型签名仅为 `(key: string) => string`,`t("titel")` 也能通过编译。
|
|
227
|
+
|
|
228
|
+
</Tab>
|
|
229
|
+
<Tab label="react-intl" value="react-intl">
|
|
230
|
+
|
|
231
|
+
<Tabs group="locale">
|
|
232
|
+
<Tab value="en" label="英语">
|
|
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="法语">
|
|
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="西班牙语">
|
|
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
|
+
端到端采用 ICU 格式,这也是大多数 TMS 平台导出的标准格式。`id` 上的类型来自于 `formatjs` 提取步骤和生成的 union 类型,并非开箱即用。
|
|
283
|
+
|
|
284
|
+
</Tab>
|
|
285
|
+
<Tab label="use-intl" value="use-intl">
|
|
286
|
+
|
|
287
|
+
<Tabs group="locale">
|
|
288
|
+
<Tab value="en" label="英语">
|
|
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="法语">
|
|
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="西班牙语">
|
|
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
|
+
结构与 `next-intl` 一致,但移除了 Next.js 专属绑定。使用 messages 类型扩展 `AppConfig` 后可获得键类型支持;namespaces 的拆分需要开发者自行规划。
|
|
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
|
+
源语言直接编写在组件中;其他语言在执行 `lingui extract` 后存放于带哈希 id 的 `.po` 文件中。如果遗漏了 `extract` 或 `compile`,会静默回退到英文。
|
|
372
|
+
|
|
373
|
+
</Tab>
|
|
374
|
+
<Tab label="Paraglide" value="paraglide">
|
|
375
|
+
|
|
376
|
+
<Tabs group="locale">
|
|
377
|
+
<Tab value="en" label="英语">
|
|
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="法语">
|
|
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="西班牙语">
|
|
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
|
+
每条消息都是自动生成的类型化函数,因此缺失键会直接触发导入错误。`paraglide/` 目录直接生成在项目中,并在每次修改时重新生成。
|
|
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
|
+
zh: "购物车",
|
|
434
|
+
en: "Your cart",
|
|
435
|
+
fr: "Votre panier",
|
|
436
|
+
es: "Tu carrito",
|
|
437
|
+
}),
|
|
438
|
+
items: t({
|
|
439
|
+
zh: plural({ one: "{{count}} 件商品", other: "{{count}} 件商品" }),
|
|
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
|
+
所有语言环境集中在组件同级的单个文件中。类型在构建时自动生成,`title` 具备自动补全,拼写错误无需 declaration merging 即可在 `tsc` 中报错。删除组件目录即可同步删除对应文案。
|
|
467
|
+
|
|
468
|
+
</Tab>
|
|
469
|
+
</Tabs>
|
|
470
|
+
|
|
471
|
+
如果已经在使用 `react-i18next`、`react-intl` 或 `Lingui`,兼容适配器([react-i18next](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/compat/react-i18next.md)、[react-intl](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/compat/react-intl.md)、[Lingui](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/compat/lingui.md))会在打包工具层面设置别名,让你在逐个迁移组件的同时保持现有 API 正常工作。[迁移指南](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/migration_from_react-i18next_to_intlayer.md) 涵盖了其余迁移步骤。
|
|
472
|
+
|
|
473
|
+
## 最终决定前的自查清单
|
|
474
|
+
|
|
475
|
+
功能清单仅说明库当前能做什么,以下几点则决定了长期维护的实际体验。
|
|
476
|
+
|
|
477
|
+
**检查仓库活跃度。**
|
|
478
|
+
|
|
479
|
+
关注 commit 频率、issue 响应速度,以及最近的小版本更新是否发生在今年。一个设计精良但缺乏维护的库,意味着未来不可避免的重构与迁移。
|
|
480
|
+
|
|
481
|
+
**不要单纯依据 npm 下载量做决定。**
|
|
482
|
+
|
|
483
|
+
安装量最大的往往是最早发布的库,而不一定是最适合 2026 年 React 代码库的方案。下载量衡量的是历史沉淀,而不是当下的契合度。
|
|
484
|
+
|
|
485
|
+

|
|
486
|
+
|
|
487
|
+
**了解维护者的资金来源和商业模式。**
|
|
488
|
+
|
|
489
|
+
`i18next` 背后有 Locize 支持;`next-intl` / `use-intl`、`vue-i18n`、`svelte-i18n` 和 Lingui 由 Crowdin 支持;Tolgee、Paraglide (inlang) 和 Intlayer 则运营着各自的平台。靠托管翻译盈利的商业公司,通常缺乏动力在你的本地工具链内提供完全免费的翻译能力。Intlayer 是其中唯一支持直接通过 CLI 调用自带 API key(OpenAI、Anthropic、Mistral、Gemini)执行 AI 翻译并提供可私有化部署 CMS 的方案。
|
|
490
|
+
|
|
491
|
+
**是否具备 AI Agent 就绪能力?**
|
|
492
|
+
|
|
493
|
+
目前的 AI Agent 在处理 i18n 时仍容易出错:遗漏语言、凭空捏造键名、混淆消息语法。该库是否提供了 [Agent Skills](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/agent_skills.md) 或 [MCP server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/mcp_server.md),以便 Agent 可以列出、填充和测试文案?内容加载策略是开箱即优化的,还是需要每季度人工审核 namespaces 和懒加载导入?
|
|
494
|
+
|
|
495
|
+
**开箱即用的类型安全。**
|
|
496
|
+
|
|
497
|
+
关注的不是“通过额外配置能否支持类型”,而是“在全新安装后输入错误键名能否直接导致 `tsc` 报错”。测试访问不存在的键或某一语言缺少某条翻译时的行为表现。
|
|
498
|
+
|
|
499
|
+
**废弃与未引用内容的检测。**
|
|
500
|
+
|
|
501
|
+
翻译目录往往只增不减。Intlayer 构建时会自动清除未使用的字段并输出日志(`build.purge`)。Paraglide 依托架构天然支持,未被调用的消息函数会被 tree-shake 剔除。其他方案则需要开发者手动清理。
|
|
502
|
+
|
|
503
|
+
**开发者体验 (DX)。**
|
|
504
|
+
|
|
505
|
+
从零配置到渲染出第一条翻译字符串所需的时间、显示悬停翻译并支持跳转到声明的 [LSP](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/lsp.md) 或 [VS Code 插件](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/vs_code_extension.md)、用于填充、测试和推送的 [CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/cli/index.md)、能把组件中硬编码的字符串提取出来、免去逐个键维护的[编译器](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/compiler.md)或提取工具,以及非开发人员无需提交 PR 即可编辑文案的渠道([可视化编辑器](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/intlayer_visual_editor.md) 或 [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/intlayer_CMS.md))。
|
|
506
|
+
|
|
507
|
+
## 常见问题解答
|
|
508
|
+
|
|
509
|
+
<FAQ>
|
|
510
|
+
|
|
511
|
+
<Question title="react-i18next 在 2026 年依然是稳妥的默认选项吗?">
|
|
512
|
+
|
|
513
|
+
对于大多数团队而言依然如此。它拥有最庞大的生态系统和最丰富的在线解决方案。它的成本真实存在但可预期:最大的运行时开销、自定义的复数格式,以及需要团队自行配置和维护的类型安全与作用域隔离。
|
|
514
|
+
|
|
515
|
+
</Question>
|
|
516
|
+
|
|
517
|
+
<Question title="我需要基于编译器的库吗?">
|
|
518
|
+
|
|
519
|
+
只有当 bundle 体积、生成的类型或构建时缺失键检查是核心诉求时才需要。对于仅有两种语言的小型应用,运行时方案更为简单。[编译器 vs 声明式 i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/compiler_vs_declarative_i18n.md) 一文解析了编译器的优势以及可能存在的边界问题。
|
|
520
|
+
|
|
521
|
+
</Question>
|
|
522
|
+
|
|
523
|
+
<Question title="以后能否在不重写每个组件的前提下更换库?">
|
|
524
|
+
|
|
525
|
+
部分可以。基于键的库具有相似的 API 结构,可以通过兼容适配器将一个 API 别名映射到另一个 API(如 Intlayer 适配器的实现方式)。但消息格式(ICU、i18next、辅助函数)无法自动转换,因此复数和插值语法部分需要手动调整。
|
|
526
|
+
|
|
527
|
+
</Question>
|
|
528
|
+
|
|
529
|
+
<Question title="库的选择会影响 SEO 吗?">
|
|
530
|
+
|
|
531
|
+
会产生间接影响。搜索引擎爬虫获取的内容由路由设计、`hreflang`、`<html lang>` 以及文本是否包含在服务端渲染的 HTML 中决定。部分库提供了相关辅助工具,大多数则需要开发者自行处理。详情参见 [hreflang 指南](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/hreflang_guide_multilingual_seo.md)。
|
|
532
|
+
|
|
533
|
+
</Question>
|
|
534
|
+
|
|
535
|
+
</FAQ>
|
|
536
|
+
|
|
537
|
+
## 延伸阅读
|
|
538
|
+
|
|
539
|
+
- [i18n 库基准测试:bundle 大小、泄漏与语言切换耗时](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/benchmark/index.md) 及 [TanStack Start 评测报告](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/benchmark/tanstack.md)
|
|
540
|
+
- [React i18n:Provider 模式的工作原理及性能开销](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/list_i18n_technologies/frameworks/react.md)
|
|
541
|
+
- [react-i18next vs react-intl vs Intlayer 全方位特性对比](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md)
|
|
542
|
+
- [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md)
|
|
543
|
+
- [JavaScript i18n 发展史](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/history_of_i18n.md)
|
|
544
|
+
- [编译器 vs 声明式 i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/compiler_vs_declarative_i18n.md)
|
|
545
|
+
- [按组件管理 vs 集中式 i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/per-component_vs_centralized_i18n.md)
|
|
546
|
+
- [构建时 bundle 优化机制](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/bundle_optimization.md)
|
|
547
|
+
- [在 Vite + React 应用中配置 i18n](https://github.com/aymericzip/intlayer/blob/main/docs/docs/zh/intlayer_with_vite+react.md)
|
|
548
|
+
- 对应指南:[Vue](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/how_to_pick_vue_i18n_library.md)、[Svelte](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/how_to_pick_svelte_i18n_library.md) 与 [Solid](https://github.com/aymericzip/intlayer/blob/main/docs/blog/zh/how_to_pick_solid_i18n_library.md)
|