@intlayer/docs 7.0.6 → 7.0.8-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/blog/ar/i18n_using_next-i18next.md +1068 -0
- package/blog/ar/i18n_using_next-intl.md +768 -0
- package/blog/ar/intlayer_with_react-intl.md +0 -4
- package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +5 -4
- package/blog/de/i18n_using_next-i18next.md +1107 -0
- package/blog/de/i18n_using_next-intl.md +760 -0
- package/blog/de/intlayer_with_react-intl.md +0 -4
- package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/en/i18n_using_next-i18next.md +1073 -0
- package/blog/en/i18n_using_next-intl.md +757 -0
- package/blog/en/intlayer_with_i18next.md +71 -8
- package/blog/en/intlayer_with_next-i18next.md +71 -8
- package/blog/en/intlayer_with_next-intl.md +71 -8
- package/blog/en/intlayer_with_react-i18next.md +69 -8
- package/blog/en/intlayer_with_react-intl.md +68 -9
- package/blog/en/intlayer_with_vue-i18n.md +68 -7
- package/blog/en/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
- package/blog/en/vue-i18n_vs_intlayer.md +2 -0
- package/blog/en-GB/i18n_using_next-i18next.md +1074 -0
- package/blog/en-GB/i18n_using_next-intl.md +757 -0
- package/blog/en-GB/intlayer_with_i18next.md +15 -6
- package/blog/en-GB/intlayer_with_next-i18next.md +16 -6
- package/blog/en-GB/intlayer_with_next-intl.md +16 -6
- package/blog/en-GB/intlayer_with_react-i18next.md +16 -7
- package/blog/en-GB/intlayer_with_react-intl.md +14 -9
- package/blog/en-GB/intlayer_with_vue-i18n.md +16 -7
- package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/en-GB/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
- package/blog/en-GB/vue-i18n_vs_intlayer.md +2 -0
- package/blog/es/i18n_using_next-i18next.md +1066 -0
- package/blog/es/i18n_using_next-intl.md +757 -0
- package/blog/es/intlayer_with_react-intl.md +0 -4
- package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/fr/i18n_using_next-i18next.md +1078 -0
- package/blog/fr/i18n_using_next-intl.md +759 -0
- package/blog/fr/intlayer_with_react-intl.md +0 -4
- package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/hi/i18n_using_next-i18next.md +1068 -0
- package/blog/hi/i18n_using_next-intl.md +758 -0
- package/blog/hi/intlayer_with_react-intl.md +0 -4
- package/blog/hi/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/id/i18n_using_next-i18next.md +1078 -0
- package/blog/id/i18n_using_next-intl.md +757 -0
- package/blog/id/index.md +69 -0
- package/blog/id/internationalization_and_SEO.md +364 -0
- package/blog/id/intlayer_with_react-intl.md +0 -4
- package/blog/id/list_i18n_technologies/CMS/drupal.md +143 -0
- package/blog/id/list_i18n_technologies/CMS/wix.md +167 -0
- package/blog/id/list_i18n_technologies/CMS/wordpress.md +188 -0
- package/blog/id/list_i18n_technologies/frameworks/angular.md +125 -0
- package/blog/id/list_i18n_technologies/frameworks/flutter.md +150 -0
- package/blog/id/list_i18n_technologies/frameworks/react-native.md +217 -0
- package/blog/id/list_i18n_technologies/frameworks/react.md +155 -0
- package/blog/id/list_i18n_technologies/frameworks/svelte.md +131 -0
- package/blog/id/list_i18n_technologies/frameworks/vue.md +130 -0
- package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +1500 -0
- package/blog/id/nextjs-multilingual-seo-comparison.md +361 -0
- package/blog/id/rag_powered_documentation_assistant.md +288 -0
- package/blog/id/react-i18next_vs_react-intl_vs_intlayer.md +164 -0
- package/blog/id/vue-i18n_vs_intlayer.md +278 -0
- package/blog/id/what_is_internationalization.md +166 -0
- package/blog/it/i18n_using_next-i18next.md +1078 -0
- package/blog/it/i18n_using_next-intl.md +758 -0
- package/blog/it/intlayer_with_react-intl.md +0 -4
- package/blog/it/react-i18next_vs_react-intl_vs_intlayer.md +4 -0
- package/blog/it/vue-i18n_vs_intlayer.md +2 -0
- package/blog/ja/i18n_using_next-i18next.md +1078 -0
- package/blog/ja/i18n_using_next-intl.md +758 -0
- package/blog/ja/intlayer_with_react-intl.md +0 -4
- package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/ko/i18n_using_next-i18next.md +1075 -0
- package/blog/ko/i18n_using_next-intl.md +759 -0
- package/blog/ko/intlayer_with_react-intl.md +0 -4
- package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/pl/i18n_using_next-i18next.md +1078 -0
- package/blog/pl/i18n_using_next-intl.md +758 -0
- package/blog/pl/index.md +69 -0
- package/blog/pl/internationalization_and_SEO.md +363 -0
- package/blog/pl/intlayer_with_react-intl.md +0 -4
- package/blog/pl/list_i18n_technologies/CMS/drupal.md +143 -0
- package/blog/pl/list_i18n_technologies/CMS/wix.md +167 -0
- package/blog/pl/list_i18n_technologies/CMS/wordpress.md +196 -0
- package/blog/pl/list_i18n_technologies/frameworks/angular.md +125 -0
- package/blog/pl/list_i18n_technologies/frameworks/flutter.md +151 -0
- package/blog/pl/list_i18n_technologies/frameworks/react-native.md +217 -0
- package/blog/pl/list_i18n_technologies/frameworks/react.md +155 -0
- package/blog/pl/list_i18n_technologies/frameworks/svelte.md +131 -0
- package/blog/pl/list_i18n_technologies/frameworks/vue.md +130 -0
- package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +1501 -0
- package/blog/pl/nextjs-multilingual-seo-comparison.md +362 -0
- package/blog/pl/rag_powered_documentation_assistant.md +288 -0
- package/blog/pl/react-i18next_vs_react-intl_vs_intlayer.md +164 -0
- package/blog/pl/vue-i18n_vs_intlayer.md +278 -0
- package/blog/pl/what_is_internationalization.md +167 -0
- package/blog/pt/i18n_using_next-i18next.md +1067 -0
- package/blog/pt/i18n_using_next-intl.md +760 -0
- package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/ru/i18n_using_next-i18next.md +1106 -0
- package/blog/ru/i18n_using_next-intl.md +759 -0
- package/blog/ru/intlayer_with_react-intl.md +0 -4
- package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/tr/i18n_using_next-i18next.md +1078 -0
- package/blog/tr/i18n_using_next-intl.md +760 -0
- package/blog/tr/intlayer_with_react-intl.md +0 -4
- package/blog/tr/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/tr/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
- package/blog/tr/vue-i18n_vs_intlayer.md +2 -0
- package/blog/vi/i18n_using_next-i18next.md +1080 -0
- package/blog/vi/i18n_using_next-intl.md +758 -0
- package/blog/vi/index.md +69 -0
- package/blog/vi/internationalization_and_SEO.md +363 -0
- package/blog/vi/intlayer_with_react-intl.md +0 -4
- package/blog/vi/list_i18n_technologies/CMS/drupal.md +143 -0
- package/blog/vi/list_i18n_technologies/CMS/wix.md +167 -0
- package/blog/vi/list_i18n_technologies/CMS/wordpress.md +188 -0
- package/blog/vi/list_i18n_technologies/frameworks/angular.md +125 -0
- package/blog/vi/list_i18n_technologies/frameworks/flutter.md +150 -0
- package/blog/vi/list_i18n_technologies/frameworks/react-native.md +217 -0
- package/blog/vi/list_i18n_technologies/frameworks/react.md +155 -0
- package/blog/vi/list_i18n_technologies/frameworks/svelte.md +131 -0
- package/blog/vi/list_i18n_technologies/frameworks/vue.md +130 -0
- package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +1520 -0
- package/blog/vi/nextjs-multilingual-seo-comparison.md +362 -0
- package/blog/vi/rag_powered_documentation_assistant.md +288 -0
- package/blog/vi/react-i18next_vs_react-intl_vs_intlayer.md +164 -0
- package/blog/vi/vue-i18n_vs_intlayer.md +278 -0
- package/blog/vi/what_is_internationalization.md +168 -0
- package/blog/zh/i18n_using_next-i18next.md +1105 -0
- package/blog/zh/i18n_using_next-intl.md +758 -0
- package/blog/zh/intlayer_with_react-intl.md +0 -4
- package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
- package/blog/zh/react-i18next_vs_react-intl_vs_intlayer.md +2 -0
- package/dist/cjs/common.cjs +0 -4
- package/dist/cjs/common.cjs.map +1 -1
- package/dist/cjs/generated/blog.entry.cjs +38 -6
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +0 -6
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +0 -6
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +0 -6
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +38 -0
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/types/generated/blog.entry.d.ts +2 -0
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/docs/ar/component_i18n.md +1 -1
- package/docs/ar/configuration.md +6 -0
- package/docs/ar/intlayer_cli.md +8 -3
- package/docs/ar/intlayer_with_next-i18next.md +619 -0
- package/docs/ar/intlayer_with_next-intl.md +446 -0
- package/docs/ar/intlayer_with_nextjs_16.md +21 -0
- package/docs/ar/intlayer_with_tanstack.md +4 -0
- package/docs/ar/intlayer_with_vite+react.md +4 -0
- package/docs/de/component_i18n.md +1 -1
- package/docs/de/configuration.md +6 -0
- package/docs/de/intlayer_cli.md +8 -3
- package/docs/de/intlayer_with_next-i18next.md +627 -0
- package/docs/de/intlayer_with_next-intl.md +451 -0
- package/docs/de/intlayer_with_nextjs_16.md +21 -0
- package/docs/de/intlayer_with_tanstack.md +4 -0
- package/docs/de/intlayer_with_vite+react.md +4 -0
- package/docs/en/component_i18n.md +1 -1
- package/docs/en/intlayer_cli.md +8 -1
- package/docs/en/intlayer_with_astro.md +10 -2
- package/docs/en/intlayer_with_create_react_app.md +8 -0
- package/docs/en/intlayer_with_lynx+react.md +8 -0
- package/docs/en/intlayer_with_nestjs.md +10 -0
- package/docs/en/intlayer_with_nextjs_14.md +10 -2
- package/docs/en/intlayer_with_nextjs_15.md +21 -4
- package/docs/en/intlayer_with_nextjs_16.md +17 -0
- package/docs/en/intlayer_with_nuxt.md +8 -0
- package/docs/en/intlayer_with_react_native+expo.md +10 -2
- package/docs/en/intlayer_with_react_router_v7.md +8 -0
- package/docs/en/intlayer_with_tanstack.md +10 -0
- package/docs/en/intlayer_with_vite+preact.md +10 -2
- package/docs/en/intlayer_with_vite+react.md +21 -4
- package/docs/en/intlayer_with_vite+vue.md +10 -2
- package/docs/en-GB/component_i18n.md +1 -1
- package/docs/en-GB/configuration.md +6 -0
- package/docs/en-GB/intlayer_cli.md +8 -3
- package/docs/en-GB/intlayer_with_angular.md +4 -4
- package/docs/en-GB/intlayer_with_express.md +4 -4
- package/docs/en-GB/intlayer_with_lynx+react.md +12 -12
- package/{blog/en/_intlayer_with_next-i18next.md → docs/en-GB/intlayer_with_next-i18next.md} +241 -42
- package/{blog/en/_intlayer_with_next-intl.md → docs/en-GB/intlayer_with_next-intl.md} +144 -29
- package/docs/en-GB/intlayer_with_nextjs_16.md +21 -0
- package/docs/en-GB/intlayer_with_tanstack.md +5 -1
- package/docs/en-GB/intlayer_with_vite+react.md +4 -0
- package/docs/en-GB/packages/next-intlayer/t.md +2 -2
- package/docs/es/component_i18n.md +1 -1
- package/docs/es/configuration.md +6 -0
- package/docs/es/intlayer_cli.md +8 -3
- package/docs/es/intlayer_with_next-i18next.md +628 -0
- package/docs/es/intlayer_with_next-intl.md +446 -0
- package/docs/es/intlayer_with_nextjs_16.md +21 -0
- package/docs/es/intlayer_with_tanstack.md +4 -0
- package/docs/es/intlayer_with_vite+react.md +4 -0
- package/docs/fr/configuration.md +6 -0
- package/docs/fr/intlayer_cli.md +8 -3
- package/docs/fr/intlayer_with_next-i18next.md +628 -0
- package/docs/fr/intlayer_with_next-intl.md +446 -0
- package/docs/fr/intlayer_with_nextjs_16.md +23 -2
- package/docs/fr/intlayer_with_tanstack.md +4 -0
- package/docs/fr/intlayer_with_vite+react.md +4 -0
- package/docs/hi/component_i18n.md +1 -1
- package/docs/hi/configuration.md +6 -0
- package/docs/hi/intlayer_cli.md +8 -0
- package/docs/hi/intlayer_with_next-i18next.md +628 -0
- package/docs/hi/intlayer_with_next-intl.md +446 -0
- package/docs/hi/intlayer_with_nextjs_16.md +21 -0
- package/docs/hi/intlayer_with_tanstack.md +4 -0
- package/docs/hi/intlayer_with_vite+react.md +4 -0
- package/docs/id/CI_CD.md +198 -0
- package/docs/id/autoFill.md +284 -0
- package/docs/id/component_i18n.md +186 -0
- package/docs/id/configuration.md +710 -0
- package/docs/id/dictionary/condition.md +231 -0
- package/docs/id/dictionary/content_file.md +1092 -0
- package/docs/id/dictionary/enumeration.md +245 -0
- package/docs/id/dictionary/file.md +237 -0
- package/docs/id/dictionary/function_fetching.md +214 -0
- package/docs/id/dictionary/gender.md +273 -0
- package/docs/id/dictionary/insertion.md +192 -0
- package/docs/id/dictionary/markdown.md +381 -0
- package/docs/id/dictionary/nesting.md +273 -0
- package/docs/id/dictionary/translation.md +310 -0
- package/docs/id/formatters.md +596 -0
- package/docs/id/how_works_intlayer.md +256 -0
- package/docs/id/index.md +176 -0
- package/docs/id/interest_of_intlayer.md +293 -0
- package/docs/id/intlayer_CMS.md +549 -0
- package/docs/id/intlayer_cli.md +850 -0
- package/docs/id/intlayer_visual_editor.md +288 -0
- package/docs/id/intlayer_with_angular.md +694 -0
- package/docs/id/intlayer_with_astro.md +252 -0
- package/docs/id/intlayer_with_create_react_app.md +1233 -0
- package/docs/id/intlayer_with_express.md +411 -0
- package/docs/id/intlayer_with_lynx+react.md +518 -0
- package/docs/id/intlayer_with_nestjs.md +272 -0
- package/docs/id/intlayer_with_next-i18next.md +628 -0
- package/docs/id/intlayer_with_next-intl.md +446 -0
- package/docs/id/intlayer_with_nextjs_14.md +1617 -0
- package/docs/id/intlayer_with_nextjs_15.md +1698 -0
- package/docs/id/intlayer_with_nextjs_16.md +21 -0
- package/docs/id/intlayer_with_nextjs_page_router.md +1478 -0
- package/docs/id/intlayer_with_nuxt.md +808 -0
- package/docs/id/intlayer_with_react_native+expo.md +699 -0
- package/docs/id/intlayer_with_react_router_v7.md +496 -0
- package/docs/id/intlayer_with_tanstack.md +564 -0
- package/docs/id/intlayer_with_vite+preact.md +1737 -0
- package/docs/id/intlayer_with_vite+react.md +1413 -0
- package/docs/id/intlayer_with_vite+solid.md +289 -0
- package/docs/id/intlayer_with_vite+svelte.md +289 -0
- package/docs/id/intlayer_with_vite+vue.md +1088 -0
- package/docs/id/introduction.md +218 -0
- package/docs/id/locale_mapper.md +242 -0
- package/docs/id/mcp_server.md +211 -0
- package/docs/id/packages/express-intlayer/t.md +458 -0
- package/docs/id/packages/intlayer/getConfiguration.md +145 -0
- package/docs/id/packages/intlayer/getEnumeration.md +159 -0
- package/docs/id/packages/intlayer/getHTMLTextDir.md +122 -0
- package/docs/id/packages/intlayer/getLocaleLang.md +81 -0
- package/docs/id/packages/intlayer/getLocaleName.md +119 -0
- package/docs/id/packages/intlayer/getLocalizedUrl.md +309 -0
- package/docs/id/packages/intlayer/getMultilingualUrls.md +223 -0
- package/docs/id/packages/intlayer/getPathWithoutLocale.md +75 -0
- package/docs/id/packages/intlayer/getTranslation.md +190 -0
- package/docs/id/packages/intlayer/getTranslationContent.md +188 -0
- package/docs/id/packages/next-intlayer/t.md +352 -0
- package/docs/id/packages/next-intlayer/useDictionary.md +271 -0
- package/docs/id/packages/next-intlayer/useIntlayer.md +264 -0
- package/docs/id/packages/next-intlayer/useLocale.md +166 -0
- package/docs/id/packages/react-intlayer/t.md +303 -0
- package/docs/id/packages/react-intlayer/useDictionary.md +287 -0
- package/docs/id/packages/react-intlayer/useI18n.md +267 -0
- package/docs/id/packages/react-intlayer/useIntlayer.md +254 -0
- package/docs/id/packages/react-intlayer/useLocale.md +210 -0
- package/docs/id/per_locale_file.md +323 -0
- package/docs/id/readme.md +261 -0
- package/docs/id/releases/v6.md +305 -0
- package/docs/id/roadmap.md +362 -0
- package/docs/id/testing.md +202 -0
- package/docs/id/vs_code_extension.md +126 -0
- package/docs/it/component_i18n.md +1 -1
- package/docs/it/configuration.md +6 -0
- package/docs/it/intlayer_cli.md +8 -3
- package/docs/it/intlayer_with_next-i18next.md +628 -0
- package/docs/it/intlayer_with_next-intl.md +446 -0
- package/docs/it/intlayer_with_nextjs_16.md +21 -0
- package/docs/it/intlayer_with_tanstack.md +4 -0
- package/docs/it/intlayer_with_vite+react.md +4 -0
- package/docs/ja/component_i18n.md +1 -1
- package/docs/ja/configuration.md +6 -0
- package/docs/ja/intlayer_cli.md +8 -3
- package/docs/ja/intlayer_with_next-i18next.md +627 -0
- package/docs/ja/intlayer_with_next-intl.md +446 -0
- package/docs/ja/intlayer_with_nextjs_16.md +21 -0
- package/docs/ja/intlayer_with_tanstack.md +4 -0
- package/docs/ja/intlayer_with_vite+react.md +4 -0
- package/docs/ko/configuration.md +6 -0
- package/docs/ko/intlayer_cli.md +8 -3
- package/docs/ko/intlayer_with_next-i18next.md +627 -0
- package/docs/ko/intlayer_with_next-intl.md +446 -0
- package/docs/ko/intlayer_with_nextjs_16.md +21 -0
- package/docs/ko/intlayer_with_tanstack.md +4 -0
- package/docs/ko/intlayer_with_vite+react.md +4 -0
- package/docs/pl/CI_CD.md +198 -0
- package/docs/pl/autoFill.md +284 -0
- package/docs/pl/component_i18n.md +186 -0
- package/docs/pl/configuration.md +710 -0
- package/docs/pl/dictionary/condition.md +232 -0
- package/docs/pl/dictionary/content_file.md +1130 -0
- package/docs/pl/dictionary/enumeration.md +245 -0
- package/docs/pl/dictionary/file.md +234 -0
- package/docs/pl/dictionary/function_fetching.md +214 -0
- package/docs/pl/dictionary/gender.md +276 -0
- package/docs/pl/dictionary/insertion.md +188 -0
- package/docs/pl/dictionary/markdown.md +408 -0
- package/docs/pl/dictionary/nesting.md +273 -0
- package/docs/pl/dictionary/translation.md +310 -0
- package/docs/pl/formatters.md +596 -0
- package/docs/pl/how_works_intlayer.md +256 -0
- package/docs/pl/index.md +176 -0
- package/docs/pl/interest_of_intlayer.md +291 -0
- package/docs/pl/intlayer_CMS.md +549 -0
- package/docs/pl/intlayer_cli.md +857 -0
- package/docs/pl/intlayer_visual_editor.md +288 -0
- package/docs/pl/intlayer_with_angular.md +690 -0
- package/docs/pl/intlayer_with_astro.md +280 -0
- package/docs/pl/intlayer_with_create_react_app.md +1235 -0
- package/docs/pl/intlayer_with_express.md +411 -0
- package/docs/pl/intlayer_with_lynx+react.md +518 -0
- package/docs/pl/intlayer_with_nestjs.md +272 -0
- package/docs/pl/intlayer_with_next-i18next.md +628 -0
- package/docs/pl/intlayer_with_next-intl.md +446 -0
- package/docs/pl/intlayer_with_nextjs_14.md +1594 -0
- package/docs/pl/intlayer_with_nextjs_15.md +1701 -0
- package/docs/pl/intlayer_with_nextjs_16.md +21 -0
- package/docs/pl/intlayer_with_nextjs_page_router.md +1513 -0
- package/docs/pl/intlayer_with_nuxt.md +885 -0
- package/docs/pl/intlayer_with_react_native+expo.md +698 -0
- package/docs/pl/intlayer_with_react_router_v7.md +503 -0
- package/docs/pl/intlayer_with_tanstack.md +562 -0
- package/docs/pl/intlayer_with_vite+preact.md +1736 -0
- package/docs/pl/intlayer_with_vite+react.md +1438 -0
- package/docs/pl/intlayer_with_vite+solid.md +290 -0
- package/docs/pl/intlayer_with_vite+svelte.md +289 -0
- package/docs/pl/intlayer_with_vite+vue.md +1116 -0
- package/docs/pl/introduction.md +209 -0
- package/docs/pl/locale_mapper.md +242 -0
- package/docs/pl/mcp_server.md +211 -0
- package/docs/pl/packages/express-intlayer/t.md +458 -0
- package/docs/pl/packages/intlayer/getConfiguration.md +146 -0
- package/docs/pl/packages/intlayer/getEnumeration.md +160 -0
- package/docs/pl/packages/intlayer/getHTMLTextDir.md +121 -0
- package/docs/pl/packages/intlayer/getLocaleLang.md +81 -0
- package/docs/pl/packages/intlayer/getLocaleName.md +118 -0
- package/docs/pl/packages/intlayer/getLocalizedUrl.md +300 -0
- package/docs/pl/packages/intlayer/getMultilingualUrls.md +221 -0
- package/docs/pl/packages/intlayer/getPathWithoutLocale.md +75 -0
- package/docs/pl/packages/intlayer/getTranslation.md +190 -0
- package/docs/pl/packages/intlayer/getTranslationContent.md +189 -0
- package/docs/pl/packages/next-intlayer/t.md +353 -0
- package/docs/pl/packages/next-intlayer/useDictionary.md +270 -0
- package/docs/pl/packages/next-intlayer/useIntlayer.md +263 -0
- package/docs/pl/packages/next-intlayer/useLocale.md +166 -0
- package/docs/pl/packages/react-intlayer/t.md +303 -0
- package/docs/pl/packages/react-intlayer/useDictionary.md +289 -0
- package/docs/pl/packages/react-intlayer/useI18n.md +249 -0
- package/docs/pl/packages/react-intlayer/useIntlayer.md +256 -0
- package/docs/pl/packages/react-intlayer/useLocale.md +210 -0
- package/docs/pl/per_locale_file.md +321 -0
- package/docs/pl/readme.md +261 -0
- package/docs/pl/releases/v6.md +305 -0
- package/docs/pl/roadmap.md +362 -0
- package/docs/pl/testing.md +202 -0
- package/docs/pl/vs_code_extension.md +126 -0
- package/docs/pt/component_i18n.md +1 -1
- package/docs/pt/configuration.md +6 -0
- package/docs/pt/intlayer_cli.md +8 -3
- package/docs/pt/intlayer_with_next-i18next.md +627 -0
- package/docs/pt/intlayer_with_next-intl.md +446 -0
- package/docs/pt/intlayer_with_nextjs_16.md +21 -0
- package/docs/pt/intlayer_with_tanstack.md +4 -0
- package/docs/pt/intlayer_with_vite+react.md +4 -0
- package/docs/ru/component_i18n.md +1 -1
- package/docs/ru/configuration.md +6 -0
- package/docs/ru/intlayer_cli.md +301 -22
- package/docs/ru/intlayer_with_next-i18next.md +629 -0
- package/docs/ru/intlayer_with_next-intl.md +448 -0
- package/docs/ru/intlayer_with_nextjs_16.md +21 -0
- package/docs/ru/intlayer_with_tanstack.md +4 -0
- package/docs/ru/intlayer_with_vite+react.md +4 -0
- package/docs/tr/component_i18n.md +1 -1
- package/docs/tr/configuration.md +6 -0
- package/docs/tr/intlayer_cli.md +8 -0
- package/docs/tr/intlayer_with_next-i18next.md +627 -0
- package/docs/tr/intlayer_with_next-intl.md +446 -0
- package/docs/tr/intlayer_with_nextjs_16.md +21 -0
- package/docs/tr/intlayer_with_tanstack.md +4 -0
- package/docs/tr/intlayer_with_vite+react.md +4 -0
- package/docs/vi/CI_CD.md +198 -0
- package/docs/vi/autoFill.md +284 -0
- package/docs/vi/component_i18n.md +186 -0
- package/docs/vi/configuration.md +710 -0
- package/docs/vi/dictionary/condition.md +237 -0
- package/docs/vi/dictionary/content_file.md +1115 -0
- package/docs/vi/dictionary/enumeration.md +255 -0
- package/docs/vi/dictionary/file.md +234 -0
- package/docs/vi/dictionary/function_fetching.md +212 -0
- package/docs/vi/dictionary/gender.md +275 -0
- package/docs/vi/dictionary/insertion.md +191 -0
- package/docs/vi/dictionary/markdown.md +381 -0
- package/docs/vi/dictionary/nesting.md +273 -0
- package/docs/vi/dictionary/translation.md +309 -0
- package/docs/vi/formatters.md +595 -0
- package/docs/vi/how_works_intlayer.md +256 -0
- package/docs/vi/index.md +174 -0
- package/docs/vi/interest_of_intlayer.md +292 -0
- package/docs/vi/intlayer_CMS.md +549 -0
- package/docs/vi/intlayer_cli.md +850 -0
- package/docs/vi/intlayer_visual_editor.md +288 -0
- package/docs/vi/intlayer_with_angular.md +692 -0
- package/docs/vi/intlayer_with_astro.md +252 -0
- package/docs/vi/intlayer_with_create_react_app.md +1230 -0
- package/docs/vi/intlayer_with_express.md +409 -0
- package/docs/vi/intlayer_with_lynx+react.md +520 -0
- package/docs/vi/intlayer_with_nestjs.md +272 -0
- package/docs/vi/intlayer_with_next-i18next.md +628 -0
- package/docs/vi/intlayer_with_next-intl.md +446 -0
- package/docs/vi/intlayer_with_nextjs_14.md +1584 -0
- package/docs/vi/intlayer_with_nextjs_15.md +1738 -0
- package/docs/vi/intlayer_with_nextjs_16.md +21 -0
- package/docs/vi/intlayer_with_nextjs_page_router.md +1504 -0
- package/docs/vi/intlayer_with_nuxt.md +821 -0
- package/docs/vi/intlayer_with_react_native+expo.md +700 -0
- package/docs/vi/intlayer_with_react_router_v7.md +498 -0
- package/docs/vi/intlayer_with_tanstack.md +562 -0
- package/docs/vi/intlayer_with_vite+preact.md +1722 -0
- package/docs/vi/intlayer_with_vite+react.md +1407 -0
- package/docs/vi/intlayer_with_vite+solid.md +287 -0
- package/docs/vi/intlayer_with_vite+svelte.md +289 -0
- package/docs/vi/intlayer_with_vite+vue.md +1071 -0
- package/docs/vi/introduction.md +215 -0
- package/docs/vi/locale_mapper.md +242 -0
- package/docs/vi/mcp_server.md +211 -0
- package/docs/vi/packages/express-intlayer/t.md +457 -0
- package/docs/vi/packages/intlayer/getConfiguration.md +145 -0
- package/docs/vi/packages/intlayer/getEnumeration.md +162 -0
- package/docs/vi/packages/intlayer/getHTMLTextDir.md +121 -0
- package/docs/vi/packages/intlayer/getLocaleLang.md +81 -0
- package/docs/vi/packages/intlayer/getLocaleName.md +129 -0
- package/docs/vi/packages/intlayer/getLocalizedUrl.md +309 -0
- package/docs/vi/packages/intlayer/getMultilingualUrls.md +221 -0
- package/docs/vi/packages/intlayer/getPathWithoutLocale.md +75 -0
- package/docs/vi/packages/intlayer/getTranslation.md +201 -0
- package/docs/vi/packages/intlayer/getTranslationContent.md +188 -0
- package/docs/vi/packages/next-intlayer/t.md +352 -0
- package/docs/vi/packages/next-intlayer/useDictionary.md +273 -0
- package/docs/vi/packages/next-intlayer/useIntlayer.md +264 -0
- package/docs/vi/packages/next-intlayer/useLocale.md +166 -0
- package/docs/vi/packages/react-intlayer/t.md +304 -0
- package/docs/vi/packages/react-intlayer/useDictionary.md +288 -0
- package/docs/vi/packages/react-intlayer/useI18n.md +295 -0
- package/docs/vi/packages/react-intlayer/useIntlayer.md +256 -0
- package/docs/vi/packages/react-intlayer/useLocale.md +210 -0
- package/docs/vi/per_locale_file.md +326 -0
- package/docs/vi/readme.md +261 -0
- package/docs/vi/releases/v6.md +305 -0
- package/docs/vi/roadmap.md +346 -0
- package/docs/vi/testing.md +202 -0
- package/docs/vi/vs_code_extension.md +126 -0
- package/docs/zh/configuration.md +6 -0
- package/docs/zh/intlayer_cli.md +8 -3
- package/docs/zh/intlayer_with_next-i18next.md +628 -0
- package/docs/zh/intlayer_with_next-intl.md +448 -0
- package/docs/zh/intlayer_with_nextjs_16.md +21 -0
- package/docs/zh/intlayer_with_tanstack.md +4 -0
- package/docs/zh/intlayer_with_vite+react.md +4 -0
- package/frequent_questions/ar/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/ar/array_as_content_declaration.md +1 -2
- package/frequent_questions/ar/build_dictionaries.md +1 -2
- package/frequent_questions/ar/build_error_CI_CD.md +1 -2
- package/frequent_questions/ar/bun_set_up.md +1 -2
- package/frequent_questions/ar/customized_locale_list.md +1 -2
- package/frequent_questions/ar/domain_routing.md +1 -2
- package/frequent_questions/ar/esbuild_error.md +1 -2
- package/frequent_questions/ar/get_locale_cookie.md +1 -2
- package/frequent_questions/ar/intlayer_command_undefined.md +1 -2
- package/frequent_questions/ar/locale_incorect_in_url.md +1 -2
- package/frequent_questions/ar/static_rendering.md +1 -3
- package/frequent_questions/ar/translated_path_url.md +1 -2
- package/frequent_questions/ar/unknown_command.md +1 -2
- package/frequent_questions/de/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/de/array_as_content_declaration.md +1 -2
- package/frequent_questions/de/build_dictionaries.md +1 -2
- package/frequent_questions/de/build_error_CI_CD.md +1 -2
- package/frequent_questions/de/bun_set_up.md +1 -2
- package/frequent_questions/de/customized_locale_list.md +1 -2
- package/frequent_questions/de/domain_routing.md +1 -2
- package/frequent_questions/de/esbuild_error.md +1 -2
- package/frequent_questions/de/get_locale_cookie.md +1 -2
- package/frequent_questions/de/intlayer_command_undefined.md +1 -2
- package/frequent_questions/de/locale_incorect_in_url.md +1 -2
- package/frequent_questions/de/static_rendering.md +1 -3
- package/frequent_questions/de/translated_path_url.md +1 -2
- package/frequent_questions/de/unknown_command.md +1 -2
- package/frequent_questions/en/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/en/array_as_content_declaration.md +1 -2
- package/frequent_questions/en/build_dictionaries.md +1 -2
- package/frequent_questions/en/build_error_CI_CD.md +1 -2
- package/frequent_questions/en/bun_set_up.md +1 -2
- package/frequent_questions/en/customized_locale_list.md +1 -2
- package/frequent_questions/en/domain_routing.md +1 -2
- package/frequent_questions/en/esbuild_error.md +1 -2
- package/frequent_questions/en/get_locale_cookie.md +1 -2
- package/frequent_questions/en/intlayer_command_undefined.md +1 -2
- package/frequent_questions/en/locale_incorect_in_url.md +1 -2
- package/frequent_questions/en/static_rendering.md +1 -3
- package/frequent_questions/en/translated_path_url.md +1 -2
- package/frequent_questions/en/unknown_command.md +1 -2
- package/frequent_questions/en-GB/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/en-GB/array_as_content_declaration.md +1 -2
- package/frequent_questions/en-GB/build_dictionaries.md +1 -2
- package/frequent_questions/en-GB/build_error_CI_CD.md +1 -2
- package/frequent_questions/en-GB/bun_set_up.md +1 -2
- package/frequent_questions/en-GB/customized_locale_list.md +1 -2
- package/frequent_questions/en-GB/domain_routing.md +1 -2
- package/frequent_questions/en-GB/esbuild_error.md +1 -2
- package/frequent_questions/en-GB/get_locale_cookie.md +1 -2
- package/frequent_questions/en-GB/intlayer_command_undefined.md +1 -2
- package/frequent_questions/en-GB/locale_incorect_in_url.md +1 -2
- package/frequent_questions/en-GB/static_rendering.md +1 -3
- package/frequent_questions/en-GB/translated_path_url.md +1 -2
- package/frequent_questions/en-GB/unknown_command.md +1 -2
- package/frequent_questions/es/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/es/array_as_content_declaration.md +1 -2
- package/frequent_questions/es/build_dictionaries.md +1 -2
- package/frequent_questions/es/build_error_CI_CD.md +1 -2
- package/frequent_questions/es/bun_set_up.md +1 -2
- package/frequent_questions/es/customized_locale_list.md +1 -2
- package/frequent_questions/es/domain_routing.md +1 -2
- package/frequent_questions/es/esbuild_error.md +1 -2
- package/frequent_questions/es/get_locale_cookie.md +1 -2
- package/frequent_questions/es/intlayer_command_undefined.md +1 -2
- package/frequent_questions/es/locale_incorect_in_url.md +1 -2
- package/frequent_questions/es/static_rendering.md +1 -3
- package/frequent_questions/es/translated_path_url.md +1 -2
- package/frequent_questions/es/unknown_command.md +1 -2
- package/frequent_questions/fr/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/fr/array_as_content_declaration.md +1 -2
- package/frequent_questions/fr/build_dictionaries.md +1 -2
- package/frequent_questions/fr/build_error_CI_CD.md +1 -2
- package/frequent_questions/fr/bun_set_up.md +1 -2
- package/frequent_questions/fr/customized_locale_list.md +1 -2
- package/frequent_questions/fr/domain_routing.md +1 -2
- package/frequent_questions/fr/esbuild_error.md +1 -2
- package/frequent_questions/fr/get_locale_cookie.md +1 -2
- package/frequent_questions/fr/intlayer_command_undefined.md +1 -2
- package/frequent_questions/fr/locale_incorect_in_url.md +1 -2
- package/frequent_questions/fr/static_rendering.md +1 -3
- package/frequent_questions/fr/translated_path_url.md +1 -2
- package/frequent_questions/fr/unknown_command.md +1 -2
- package/frequent_questions/hi/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/hi/array_as_content_declaration.md +1 -2
- package/frequent_questions/hi/build_dictionaries.md +1 -2
- package/frequent_questions/hi/build_error_CI_CD.md +1 -2
- package/frequent_questions/hi/bun_set_up.md +1 -2
- package/frequent_questions/hi/customized_locale_list.md +1 -2
- package/frequent_questions/hi/domain_routing.md +1 -2
- package/frequent_questions/hi/esbuild_error.md +1 -2
- package/frequent_questions/hi/get_locale_cookie.md +1 -2
- package/frequent_questions/hi/intlayer_command_undefined.md +1 -2
- package/frequent_questions/hi/locale_incorect_in_url.md +1 -2
- package/frequent_questions/hi/static_rendering.md +1 -3
- package/frequent_questions/hi/translated_path_url.md +1 -2
- package/frequent_questions/hi/unknown_command.md +1 -2
- package/frequent_questions/id/SSR_Next_no_[locale].md +104 -0
- package/frequent_questions/id/array_as_content_declaration.md +71 -0
- package/frequent_questions/id/build_dictionaries.md +58 -0
- package/frequent_questions/id/build_error_CI_CD.md +74 -0
- package/frequent_questions/id/bun_set_up.md +53 -0
- package/frequent_questions/id/customized_locale_list.md +64 -0
- package/frequent_questions/id/domain_routing.md +113 -0
- package/frequent_questions/id/esbuild_error.md +29 -0
- package/frequent_questions/id/get_locale_cookie.md +142 -0
- package/frequent_questions/id/intlayer_command_undefined.md +155 -0
- package/frequent_questions/id/locale_incorect_in_url.md +73 -0
- package/frequent_questions/id/static_rendering.md +44 -0
- package/frequent_questions/id/translated_path_url.md +55 -0
- package/frequent_questions/id/unknown_command.md +97 -0
- package/frequent_questions/it/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/it/array_as_content_declaration.md +1 -2
- package/frequent_questions/it/build_dictionaries.md +1 -2
- package/frequent_questions/it/build_error_CI_CD.md +1 -2
- package/frequent_questions/it/bun_set_up.md +1 -2
- package/frequent_questions/it/customized_locale_list.md +1 -2
- package/frequent_questions/it/domain_routing.md +1 -2
- package/frequent_questions/it/esbuild_error.md +1 -2
- package/frequent_questions/it/get_locale_cookie.md +1 -2
- package/frequent_questions/it/intlayer_command_undefined.md +1 -2
- package/frequent_questions/it/locale_incorect_in_url.md +1 -2
- package/frequent_questions/it/static_rendering.md +1 -3
- package/frequent_questions/it/translated_path_url.md +1 -2
- package/frequent_questions/it/unknown_command.md +1 -2
- package/frequent_questions/ja/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/ja/array_as_content_declaration.md +1 -2
- package/frequent_questions/ja/build_dictionaries.md +1 -2
- package/frequent_questions/ja/build_error_CI_CD.md +1 -2
- package/frequent_questions/ja/bun_set_up.md +1 -2
- package/frequent_questions/ja/customized_locale_list.md +1 -2
- package/frequent_questions/ja/domain_routing.md +1 -2
- package/frequent_questions/ja/esbuild_error.md +1 -2
- package/frequent_questions/ja/get_locale_cookie.md +1 -2
- package/frequent_questions/ja/intlayer_command_undefined.md +1 -2
- package/frequent_questions/ja/locale_incorect_in_url.md +1 -2
- package/frequent_questions/ja/static_rendering.md +1 -3
- package/frequent_questions/ja/translated_path_url.md +1 -2
- package/frequent_questions/ja/unknown_command.md +1 -2
- package/frequent_questions/ko/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/ko/array_as_content_declaration.md +1 -2
- package/frequent_questions/ko/build_dictionaries.md +1 -2
- package/frequent_questions/ko/build_error_CI_CD.md +1 -2
- package/frequent_questions/ko/bun_set_up.md +1 -2
- package/frequent_questions/ko/customized_locale_list.md +1 -2
- package/frequent_questions/ko/domain_routing.md +1 -2
- package/frequent_questions/ko/esbuild_error.md +1 -2
- package/frequent_questions/ko/get_locale_cookie.md +1 -2
- package/frequent_questions/ko/intlayer_command_undefined.md +1 -2
- package/frequent_questions/ko/locale_incorect_in_url.md +1 -2
- package/frequent_questions/ko/static_rendering.md +1 -3
- package/frequent_questions/ko/translated_path_url.md +1 -2
- package/frequent_questions/ko/unknown_command.md +1 -2
- package/frequent_questions/pl/SSR_Next_no_[locale].md +104 -0
- package/frequent_questions/pl/array_as_content_declaration.md +71 -0
- package/frequent_questions/pl/build_dictionaries.md +58 -0
- package/frequent_questions/pl/build_error_CI_CD.md +74 -0
- package/frequent_questions/pl/bun_set_up.md +54 -0
- package/frequent_questions/pl/customized_locale_list.md +64 -0
- package/frequent_questions/pl/domain_routing.md +113 -0
- package/frequent_questions/pl/esbuild_error.md +29 -0
- package/frequent_questions/pl/get_locale_cookie.md +142 -0
- package/frequent_questions/pl/intlayer_command_undefined.md +155 -0
- package/frequent_questions/pl/locale_incorect_in_url.md +73 -0
- package/frequent_questions/pl/static_rendering.md +44 -0
- package/frequent_questions/pl/translated_path_url.md +55 -0
- package/frequent_questions/pl/unknown_command.md +97 -0
- package/frequent_questions/pt/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/pt/array_as_content_declaration.md +1 -2
- package/frequent_questions/pt/build_dictionaries.md +1 -2
- package/frequent_questions/pt/build_error_CI_CD.md +1 -2
- package/frequent_questions/pt/bun_set_up.md +1 -2
- package/frequent_questions/pt/customized_locale_list.md +1 -2
- package/frequent_questions/pt/domain_routing.md +1 -2
- package/frequent_questions/pt/esbuild_error.md +1 -2
- package/frequent_questions/pt/get_locale_cookie.md +1 -2
- package/frequent_questions/pt/intlayer_command_undefined.md +1 -2
- package/frequent_questions/pt/locale_incorect_in_url.md +1 -2
- package/frequent_questions/pt/static_rendering.md +1 -3
- package/frequent_questions/pt/translated_path_url.md +1 -2
- package/frequent_questions/pt/unknown_command.md +1 -2
- package/frequent_questions/ru/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/ru/array_as_content_declaration.md +1 -2
- package/frequent_questions/ru/build_dictionaries.md +1 -2
- package/frequent_questions/ru/build_error_CI_CD.md +1 -2
- package/frequent_questions/ru/bun_set_up.md +1 -2
- package/frequent_questions/ru/customized_locale_list.md +1 -2
- package/frequent_questions/ru/domain_routing.md +1 -2
- package/frequent_questions/ru/esbuild_error.md +1 -2
- package/frequent_questions/ru/get_locale_cookie.md +1 -2
- package/frequent_questions/ru/intlayer_command_undefined.md +1 -2
- package/frequent_questions/ru/locale_incorect_in_url.md +1 -2
- package/frequent_questions/ru/static_rendering.md +1 -2
- package/frequent_questions/ru/translated_path_url.md +1 -2
- package/frequent_questions/ru/unknown_command.md +1 -2
- package/frequent_questions/tr/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/tr/array_as_content_declaration.md +1 -2
- package/frequent_questions/tr/build_dictionaries.md +1 -2
- package/frequent_questions/tr/build_error_CI_CD.md +1 -2
- package/frequent_questions/tr/bun_set_up.md +1 -2
- package/frequent_questions/tr/customized_locale_list.md +1 -2
- package/frequent_questions/tr/domain_routing.md +1 -2
- package/frequent_questions/tr/esbuild_error.md +1 -2
- package/frequent_questions/tr/get_locale_cookie.md +1 -2
- package/frequent_questions/tr/intlayer_command_undefined.md +1 -2
- package/frequent_questions/tr/locale_incorect_in_url.md +1 -2
- package/frequent_questions/tr/static_rendering.md +1 -2
- package/frequent_questions/tr/translated_path_url.md +1 -2
- package/frequent_questions/tr/unknown_command.md +1 -2
- package/frequent_questions/vi/SSR_Next_no_[locale].md +106 -0
- package/frequent_questions/vi/array_as_content_declaration.md +71 -0
- package/frequent_questions/vi/build_dictionaries.md +58 -0
- package/frequent_questions/vi/build_error_CI_CD.md +74 -0
- package/frequent_questions/vi/bun_set_up.md +53 -0
- package/frequent_questions/vi/customized_locale_list.md +64 -0
- package/frequent_questions/vi/domain_routing.md +113 -0
- package/frequent_questions/vi/esbuild_error.md +29 -0
- package/frequent_questions/vi/get_locale_cookie.md +142 -0
- package/frequent_questions/vi/intlayer_command_undefined.md +155 -0
- package/frequent_questions/vi/locale_incorect_in_url.md +73 -0
- package/frequent_questions/vi/static_rendering.md +44 -0
- package/frequent_questions/vi/translated_path_url.md +55 -0
- package/frequent_questions/vi/unknown_command.md +97 -0
- package/frequent_questions/zh/SSR_Next_no_[locale].md +1 -2
- package/frequent_questions/zh/array_as_content_declaration.md +1 -2
- package/frequent_questions/zh/build_dictionaries.md +1 -2
- package/frequent_questions/zh/build_error_CI_CD.md +1 -2
- package/frequent_questions/zh/bun_set_up.md +1 -2
- package/frequent_questions/zh/customized_locale_list.md +1 -2
- package/frequent_questions/zh/domain_routing.md +1 -2
- package/frequent_questions/zh/esbuild_error.md +1 -2
- package/frequent_questions/zh/get_locale_cookie.md +1 -2
- package/frequent_questions/zh/intlayer_command_undefined.md +1 -2
- package/frequent_questions/zh/locale_incorect_in_url.md +1 -2
- package/frequent_questions/zh/static_rendering.md +1 -3
- package/frequent_questions/zh/translated_path_url.md +1 -2
- package/frequent_questions/zh/unknown_command.md +1 -2
- package/legal/id/privacy_notice.md +83 -0
- package/legal/id/terms_of_service.md +55 -0
- package/legal/pl/privacy_notice.md +83 -0
- package/legal/pl/terms_of_service.md +55 -0
- package/legal/vi/privacy_notice.md +83 -0
- package/legal/vi/terms_of_service.md +55 -0
- package/package.json +19 -18
- package/src/generated/blog.entry.ts +38 -0
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-11-01
|
|
3
|
+
updatedAt: 2025-11-01
|
|
4
|
+
title: next-intl을 사용하여 Next.js 애플리케이션을 국제화하는 방법
|
|
5
|
+
description: next-intl으로 i18n 설정하기: 다국어 Next.js 앱을 위한 모범 사례와 SEO 팁, 국제화, 콘텐츠 구성 및 기술 설정을 다룹니다.
|
|
6
|
+
slugs:
|
|
7
|
+
- blog
|
|
8
|
+
- nextjs-internationalization-using-next-intl
|
|
9
|
+
applicationTemplate: https://github.com/aymericzip/next-intl-template
|
|
10
|
+
history:
|
|
11
|
+
- version: 7.0.0
|
|
12
|
+
date: 2025-11-01
|
|
13
|
+
changes: 초기 버전
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# 2025년에 next-intl을 사용하여 Next.js 애플리케이션을 국제화하는 방법
|
|
17
|
+
|
|
18
|
+
## 목차
|
|
19
|
+
|
|
20
|
+
<TOC/>
|
|
21
|
+
|
|
22
|
+
## next-intl이란?
|
|
23
|
+
|
|
24
|
+
**next-intl**은 Next.js App Router를 위해 특별히 설계된 인기 있는 국제화(i18n) 라이브러리입니다. 뛰어난 TypeScript 지원과 내장 최적화를 제공하여 다국어 Next.js 애플리케이션을 원활하게 구축할 수 있습니다.
|
|
25
|
+
|
|
26
|
+
> 원하신다면 [next-i18next 가이드](https://github.com/aymericzip/intlayer/blob/main/docs/blog/ko/i18n_using_next-i18next.md)를 참고하거나, 직접 [Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_with_next-intl.md)를 사용할 수도 있습니다.
|
|
27
|
+
|
|
28
|
+
> 비교 내용은 [next-i18next vs next-intl vs Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md)에서 확인하세요.
|
|
29
|
+
|
|
30
|
+
## 따라야 할 모범 사례
|
|
31
|
+
|
|
32
|
+
구현에 들어가기 전에, 다음과 같은 모범 사례를 따라야 합니다:
|
|
33
|
+
|
|
34
|
+
- **HTML `lang` 및 `dir` 속성 설정**
|
|
35
|
+
레이아웃에서 `getLocaleDirection(locale)`를 사용하여 `dir`을 계산하고, 올바른 접근성과 SEO를 위해 `<html lang={locale} dir={dir}>`를 설정하세요.
|
|
36
|
+
- **네임스페이스별 메시지 분리**
|
|
37
|
+
로케일과 네임스페이스별로 JSON 파일을 구성하여 (예: `common.json`, `about.json`) 필요한 것만 로드하도록 하세요.
|
|
38
|
+
- **클라이언트 페이로드 최소화**
|
|
39
|
+
페이지에서 `NextIntlClientProvider`에 필요한 네임스페이스만 전송하세요 (예: `pick(messages, ['common', 'about'])`).
|
|
40
|
+
- **정적 페이지 선호**
|
|
41
|
+
성능과 SEO 향상을 위해 가능한 한 정적 페이지를 사용하세요.
|
|
42
|
+
- **서버 컴포넌트에서의 i18n**
|
|
43
|
+
|
|
44
|
+
서버 컴포넌트는 페이지나 `client`로 표시되지 않은 모든 컴포넌트처럼 정적이며 빌드 시 미리 렌더링할 수 있습니다. 따라서 번역 함수를 props로 전달해야 합니다.
|
|
45
|
+
|
|
46
|
+
- **TypeScript 타입 설정**
|
|
47
|
+
애플리케이션 전반에 걸쳐 타입 안전성을 보장하기 위해 로케일에 대한 타입을 설정하세요.
|
|
48
|
+
- **리디렉션을 위한 프록시**
|
|
49
|
+
로케일 감지와 라우팅을 처리하고 사용자를 적절한 로케일 접두사가 붙은 URL로 리디렉션하기 위해 프록시를 사용하세요.
|
|
50
|
+
- **메타데이터, 사이트맵, robots.txt의 국제화**
|
|
51
|
+
Next.js에서 제공하는 `generateMetadata` 함수를 사용하여 메타데이터, 사이트맵, robots.txt를 국제화하여 모든 로케일에서 검색 엔진이 더 잘 인식하도록 하세요.
|
|
52
|
+
- **링크 현지화**
|
|
53
|
+
`Link` 컴포넌트를 사용하여 링크를 현지화하고 사용자를 적절한 로케일 접두사가 붙은 URL로 리디렉션하세요. 이는 모든 로케일에서 페이지의 검색 가능성을 보장하는 데 중요합니다.
|
|
54
|
+
- **테스트 및 번역 자동화**
|
|
55
|
+
테스트와 번역 자동화는 다국어 애플리케이션을 유지 관리하는 데 소요되는 시간을 줄이는 데 도움이 됩니다.
|
|
56
|
+
|
|
57
|
+
> 국제화 및 SEO에 대해 알아야 할 모든 내용을 정리한 문서를 참고하세요: [next-intl과 함께하는 국제화(i18n)](https://github.com/aymericzip/intlayer/blob/main/docs/blog/ko/internationalization_and_SEO.md).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Next.js 애플리케이션에서 next-intl 설정 단계별 가이드
|
|
62
|
+
|
|
63
|
+
<iframe
|
|
64
|
+
src="https://stackblitz.com/github/aymericzip/next-intl-template?embed=1&ctl=1&file=src/i18n.ts"
|
|
65
|
+
className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
|
|
66
|
+
title="Demo CodeSandbox - Intlayer를 사용하여 애플리케이션을 국제화하는 방법"
|
|
67
|
+
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
|
68
|
+
loading="lazy"
|
|
69
|
+
|
|
70
|
+
> GitHub에서 [애플리케이션 템플릿](https://github.com/aymericzip/next-intl-template)을 참조하세요.
|
|
71
|
+
|
|
72
|
+
다음은 우리가 생성할 프로젝트 구조입니다:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
.
|
|
76
|
+
├── global.ts
|
|
77
|
+
├── locales
|
|
78
|
+
│ ├── en
|
|
79
|
+
│ │ ├── common.json
|
|
80
|
+
│ │ └── about.json
|
|
81
|
+
│ ├── fr
|
|
82
|
+
│ │ ├── common.json
|
|
83
|
+
│ │ └── about.json
|
|
84
|
+
│ └── es
|
|
85
|
+
│ ├── common.json
|
|
86
|
+
│ └── about.json
|
|
87
|
+
└── src # Src는 선택 사항입니다
|
|
88
|
+
├── proxy.ts
|
|
89
|
+
├── app
|
|
90
|
+
│ ├── i18n.ts
|
|
91
|
+
│ └── [locale]
|
|
92
|
+
│ ├── layout.tsx
|
|
93
|
+
│ ├── (home) # / (홈 리소스로 모든 페이지를 오염시키지 않기 위한 라우트 그룹)
|
|
94
|
+
│ │ ├── layout.tsx
|
|
95
|
+
│ │ └── page.tsx
|
|
96
|
+
│ └── about # /about
|
|
97
|
+
│ ├── layout.tsx
|
|
98
|
+
│ └── page.tsx
|
|
99
|
+
└── components
|
|
100
|
+
├── ClientComponent.tsx
|
|
101
|
+
└── ServerComponent.tsx
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 1단계: 의존성 설치
|
|
105
|
+
|
|
106
|
+
npm을 사용하여 필요한 패키지를 설치하세요:
|
|
107
|
+
|
|
108
|
+
```bash packageManager="npm"
|
|
109
|
+
npm install next-intl
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```bash packageManager="pnpm"
|
|
113
|
+
pnpm add next-intl
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```bash packageManager="yarn"
|
|
117
|
+
yarn add next-intl
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- **next-intl**: Next.js App Router용 핵심 국제화 라이브러리로, 번역 관리를 위한 훅, 서버 함수, 클라이언트 프로바이더를 제공합니다.
|
|
121
|
+
|
|
122
|
+
### 2단계: 프로젝트 구성
|
|
123
|
+
|
|
124
|
+
지원하는 로케일을 정의하고 next-intl의 요청 구성을 설정하는 구성 파일을 만드세요. 이 파일은 i18n 설정의 단일 진실 소스로 작동하며 애플리케이션 전반에 걸쳐 타입 안전성을 보장합니다.
|
|
125
|
+
|
|
126
|
+
로케일 구성을 중앙 집중화하면 불일치를 방지하고 향후 로케일을 추가하거나 제거하기가 더 쉬워집니다. `getRequestConfig` 함수는 모든 요청 시 실행되며 각 페이지에 필요한 번역만 로드하여 코드 분할을 가능하게 하고 번들 크기를 줄입니다.
|
|
127
|
+
|
|
128
|
+
```tsx fileName="src/i18n.ts"
|
|
129
|
+
import { notFound } from "next/navigation";
|
|
130
|
+
import createMiddleware from "next-intl/middleware";
|
|
131
|
+
import { createNavigation } from "next-intl/navigation";
|
|
132
|
+
|
|
133
|
+
// 타입 안전성을 갖춘 지원 로케일 정의
|
|
134
|
+
export const locales = ["en", "fr", "es"] as const;
|
|
135
|
+
export type Locale = (typeof locales)[number];
|
|
136
|
+
export const defaultLocale: Locale = "en";
|
|
137
|
+
|
|
138
|
+
export function isRTL(locale: Locale | (string & {})) {
|
|
139
|
+
return /^(ar|fa|he|iw|ur|ps|sd|ug|yi|ckb|ku)(-|$)/i.test(locale);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 코드 분할을 가능하게 하기 위해 로케일별로 메시지를 동적으로 로드합니다
|
|
143
|
+
// Promise.all은 더 나은 성능을 위해 네임스페이스를 병렬로 로드합니다
|
|
144
|
+
async function loadMessages(locale: Locale) {
|
|
145
|
+
// 레이아웃/페이지에서 필요한 네임스페이스만 로드합니다
|
|
146
|
+
const [common, home, about] = await Promise.all([
|
|
147
|
+
import(`../locales/${locale}/common.json`).then((m) => m.default),
|
|
148
|
+
import(`../locales/${locale}/home.json`).then((m) => m.default),
|
|
149
|
+
import(`../locales/${locale}/about.json`).then((m) => m.default),
|
|
150
|
+
// ... 향후 JSON 파일은 여기에 추가해야 합니다
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
return { common, home, about } as const;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 지역화된 URL을 생성하는 헬퍼 함수 (예: /about vs /fr/about)
|
|
157
|
+
export function localizedPath(locale: string, path: string) {
|
|
158
|
+
return locale === defaultLocale ? path : `/${locale}${path}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// getRequestConfig는 모든 요청 시 실행되며 서버 컴포넌트에 메시지를 제공합니다
|
|
162
|
+
// next-intl이 Next.js의 서버 사이드 렌더링에 연결되는 부분입니다
|
|
163
|
+
export default async function getRequestConfig({
|
|
164
|
+
requestLocale,
|
|
165
|
+
}: {
|
|
166
|
+
requestLocale: Promise<string | undefined>;
|
|
167
|
+
}) {
|
|
168
|
+
const requested: Locale = ((await requestLocale) as Locale) ?? defaultLocale;
|
|
169
|
+
|
|
170
|
+
if (!locales.includes(requested)) notFound();
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
locale: requested,
|
|
174
|
+
messages: await loadMessages(requested),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function getCookie(locale: Locale) {
|
|
179
|
+
return [
|
|
180
|
+
`NEXT_LOCALE=${locale}`,
|
|
181
|
+
"Path=/",
|
|
182
|
+
`Max-Age=${60 * 60 * 24 * 365}`, // 1년
|
|
183
|
+
"SameSite=Lax",
|
|
184
|
+
].join("; ");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const routingOptions = {
|
|
188
|
+
locales,
|
|
189
|
+
defaultLocale,
|
|
190
|
+
localePrefix: "as-needed", // /en/... 경로를 /...로 변경
|
|
191
|
+
// 선택 사항: 지역화된 경로명
|
|
192
|
+
// pathnames: {
|
|
193
|
+
// '/': '/',
|
|
194
|
+
// '/about': {en: '/about', fr: '/a-propos', es: '/acerca-de'},
|
|
195
|
+
// '/blog/[slug]': '/blog/[slug]'
|
|
196
|
+
// }
|
|
197
|
+
// localeDetection: true, // 쿠키로 인한 "/" -> "/en" 리디렉션 방지
|
|
198
|
+
} as const;
|
|
199
|
+
|
|
200
|
+
export const { Link, redirect, usePathname, useRouter, getPathname } =
|
|
201
|
+
createNavigation(routingOptions);
|
|
202
|
+
|
|
203
|
+
export const proxy = createMiddleware(routingOptions);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 3단계: 동적 로케일 라우트 정의
|
|
207
|
+
|
|
208
|
+
앱 폴더에 `[locale]` 디렉토리를 생성하여 로케일 기반 동적 라우팅을 설정하세요. 이를 통해 Next.js는 각 로케일이 URL 세그먼트가 되는 로케일 기반 라우팅을 처리할 수 있습니다 (예: `/en/about`, `/fr/about`).
|
|
209
|
+
|
|
210
|
+
동적 라우트를 사용하면 Next.js가 빌드 시 모든 로케일에 대해 정적 페이지를 생성할 수 있어 성능과 SEO가 향상됩니다. 레이아웃 컴포넌트는 로케일에 따라 HTML의 `lang` 및 `dir` 속성을 설정하는데, 이는 접근성과 검색 엔진 이해에 매우 중요합니다.
|
|
211
|
+
|
|
212
|
+
```tsx fileName="src/app/[locale]/layout.tsx"
|
|
213
|
+
import type { ReactNode } from "react";
|
|
214
|
+
import { locales } from "@/i18n";
|
|
215
|
+
import { getLocaleDirection, setRequestLocale } from "next-intl/server";
|
|
216
|
+
|
|
217
|
+
// 빌드 시 모든 로케일에 대해 정적 페이지를 미리 생성 (SSG)
|
|
218
|
+
// 이는 성능과 SEO를 향상시킵니다
|
|
219
|
+
export function generateStaticParams() {
|
|
220
|
+
return locales.map((locale) => ({ locale }));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export default function LocaleLayout({
|
|
224
|
+
children,
|
|
225
|
+
params,
|
|
226
|
+
}: {
|
|
227
|
+
children: ReactNode;
|
|
228
|
+
params: Promise<{ locale: string }>;
|
|
229
|
+
}) {
|
|
230
|
+
// Next.js App Router에서 params는 Promise입니다 (await 가능)
|
|
231
|
+
// 이를 통해 동적 라우트 세그먼트를 비동기적으로 해결할 수 있습니다
|
|
232
|
+
const { locale } = await params;
|
|
233
|
+
|
|
234
|
+
// 중요: setRequestLocale은 next-intl에 이 요청에 사용할 로케일을 알려줍니다
|
|
235
|
+
// 이것이 없으면 getTranslations()가 서버 컴포넌트에서 사용할 로케일을 알 수 없습니다
|
|
236
|
+
setRequestLocale(locale);
|
|
237
|
+
|
|
238
|
+
// 올바른 HTML 렌더링을 위해 텍스트 방향(LTR/RTL)을 가져옵니다
|
|
239
|
+
const dir = getLocaleDirection(locale);
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<html lang={locale} dir={dir}>
|
|
243
|
+
<body>{children}</body>
|
|
244
|
+
</html>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
```tsx fileName="src/app/[locale]/about/page.tsx"
|
|
251
|
+
import { getTranslations, getMessages, getFormatter } from "next-intl/server";
|
|
252
|
+
import { NextIntlClientProvider } from "next-intl";
|
|
253
|
+
import pick from "lodash/pick";
|
|
254
|
+
import ServerComponent from "@/components/ServerComponent";
|
|
255
|
+
import ClientComponent from "@/components/ClientComponent";
|
|
256
|
+
|
|
257
|
+
export default async function AboutPage({
|
|
258
|
+
params,
|
|
259
|
+
}: {
|
|
260
|
+
params: Promise<{ locale: string }>;
|
|
261
|
+
}) {
|
|
262
|
+
const { locale } = await params;
|
|
263
|
+
|
|
264
|
+
// 메시지는 서버 측에서 로드됩니다. 클라이언트에는 필요한 것만 전달하세요.
|
|
265
|
+
// 이렇게 하면 브라우저로 전송되는 자바스크립트 번들이 최소화됩니다.
|
|
266
|
+
const messages = await getMessages();
|
|
267
|
+
const clientMessages = pick(messages, ["common", "about"]);
|
|
268
|
+
|
|
269
|
+
// 엄격히 서버 측에서만 사용하는 번역/포맷팅
|
|
270
|
+
// 이들은 서버에서 실행되며 컴포넌트에 props로 전달될 수 있습니다
|
|
271
|
+
const tAbout = await getTranslations("about");
|
|
272
|
+
const tCounter = await getTranslations("about.counter");
|
|
273
|
+
const format = await getFormatter();
|
|
274
|
+
|
|
275
|
+
const initialFormattedCount = format.number(0);
|
|
276
|
+
|
|
277
|
+
return (
|
|
278
|
+
// NextIntlClientProvider는 클라이언트 컴포넌트에서 번역을 사용할 수 있게 합니다
|
|
279
|
+
// 클라이언트 컴포넌트가 실제로 사용하는 네임스페이스만 전달하세요
|
|
280
|
+
<NextIntlClientProvider locale={locale} messages={clientMessages}>
|
|
281
|
+
<main>
|
|
282
|
+
<h1>{tAbout("title")}</h1>
|
|
283
|
+
<ClientComponent />
|
|
284
|
+
<ServerComponent
|
|
285
|
+
formattedCount={initialFormattedCount}
|
|
286
|
+
label={tCounter("label")}
|
|
287
|
+
increment={tCounter("increment")}
|
|
288
|
+
/>
|
|
289
|
+
</main>
|
|
290
|
+
</NextIntlClientProvider>
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 4단계: 번역 파일 생성하기
|
|
296
|
+
|
|
297
|
+
각 로케일과 네임스페이스별로 JSON 파일을 생성하세요. 이 구조는 번역을 논리적으로 구성하고 각 페이지에 필요한 번역만 로드할 수 있게 해줍니다.
|
|
298
|
+
|
|
299
|
+
네임스페이스별로 번역을 구성하는 것(e.g., `common.json`, `about.json`)은 코드 분할을 가능하게 하며 번들 크기를 줄여줍니다. 이렇게 하면 각 페이지에 필요한 번역만 로드하여 성능을 향상시킬 수 있습니다.
|
|
300
|
+
|
|
301
|
+
```json fileName="locales/en/common.json"
|
|
302
|
+
{
|
|
303
|
+
"welcome": "Welcome",
|
|
304
|
+
"greeting": "Hello, world!"
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
```json fileName="locales/fr/common.json"
|
|
309
|
+
{
|
|
310
|
+
"welcome": "Bienvenue",
|
|
311
|
+
"greeting": "Bonjour le monde!"
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
```json fileName="locales/en/about.json"
|
|
316
|
+
{
|
|
317
|
+
"title": "About",
|
|
318
|
+
"description": "About page description",
|
|
319
|
+
"counter": {
|
|
320
|
+
"label": "Counter",
|
|
321
|
+
"increment": "Increment"
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
```json fileName="locales/fr/about.json"
|
|
327
|
+
{
|
|
328
|
+
"title": "À propos",
|
|
329
|
+
"description": "Description de la page À propos",
|
|
330
|
+
"counter": {
|
|
331
|
+
"label": "Compteur",
|
|
332
|
+
"increment": "Incrémenter"
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### 5단계: 페이지에서 번역 활용하기
|
|
338
|
+
|
|
339
|
+
서버에서 번역을 로드하고 이를 서버 및 클라이언트 컴포넌트 모두에 전달하는 페이지 컴포넌트를 만드세요. 이렇게 하면 렌더링 전에 번역이 로드되어 콘텐츠 깜박임을 방지할 수 있습니다.
|
|
340
|
+
|
|
341
|
+
서버 측에서 번역을 로드하면 SEO가 향상되고 FOUC(번역되지 않은 콘텐츠 깜박임)를 방지할 수 있습니다. `pick`을 사용하여 필요한 네임스페이스만 클라이언트 프로바이더에 전달함으로써 브라우저에 전송되는 자바스크립트 번들 크기를 최소화합니다.
|
|
342
|
+
|
|
343
|
+
```tsx fileName="src/app/[locale]/about/page.tsx"
|
|
344
|
+
import { getTranslations, getMessages, getFormatter } from "next-intl/server";
|
|
345
|
+
import { NextIntlClientProvider } from "next-intl";
|
|
346
|
+
import pick from "lodash/pick";
|
|
347
|
+
import ServerComponent from "@/components/ServerComponent";
|
|
348
|
+
import ClientComponent from "@/components/ClientComponent";
|
|
349
|
+
|
|
350
|
+
export default async function AboutPage({
|
|
351
|
+
params,
|
|
352
|
+
}: {
|
|
353
|
+
params: Promise<{ locale: string }>;
|
|
354
|
+
}) {
|
|
355
|
+
const { locale } = await params;
|
|
356
|
+
|
|
357
|
+
// 메시지는 서버 측에서 로드됩니다. 클라이언트에는 필요한 것만 전달하세요.
|
|
358
|
+
// 이렇게 하면 브라우저로 전송되는 JavaScript 번들이 최소화됩니다.
|
|
359
|
+
const messages = await getMessages();
|
|
360
|
+
const clientMessages = pick(messages, ["common", "about"]);
|
|
361
|
+
|
|
362
|
+
// 엄격히 서버 측 번역/포맷팅
|
|
363
|
+
// 이들은 서버에서 실행되며 컴포넌트에 props로 전달될 수 있습니다
|
|
364
|
+
const tAbout = await getTranslations("about");
|
|
365
|
+
const tCounter = await getTranslations("about.counter");
|
|
366
|
+
const format = await getFormatter();
|
|
367
|
+
|
|
368
|
+
const initialFormattedCount = format.number(0);
|
|
369
|
+
|
|
370
|
+
return (
|
|
371
|
+
// NextIntlClientProvider는 클라이언트 컴포넌트에서 번역을 사용할 수 있게 합니다.
|
|
372
|
+
// 클라이언트 컴포넌트가 실제로 사용하는 네임스페이스만 전달하세요.
|
|
373
|
+
<NextIntlClientProvider locale={locale} messages={clientMessages}>
|
|
374
|
+
<main>
|
|
375
|
+
<h1>{tAbout("title")}</h1>
|
|
376
|
+
<ClientComponent />
|
|
377
|
+
<ServerComponent
|
|
378
|
+
formattedCount={initialFormattedCount}
|
|
379
|
+
label={tCounter("label")}
|
|
380
|
+
increment={tCounter("increment")}
|
|
381
|
+
/>
|
|
382
|
+
</main>
|
|
383
|
+
</NextIntlClientProvider>
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### 6단계: 클라이언트 컴포넌트에서 번역 사용하기
|
|
389
|
+
|
|
390
|
+
클라이언트 컴포넌트는 `useTranslations` 및 `useFormatter` 훅을 사용하여 번역 및 포맷팅 기능에 접근할 수 있습니다. 이 훅들은 `NextIntlClientProvider` 컨텍스트에서 값을 읽어옵니다.
|
|
391
|
+
|
|
392
|
+
클라이언트 컴포넌트는 번역에 접근하기 위해 React 훅이 필요합니다. `useTranslations`와 `useFormatter` 훅은 next-intl과 원활하게 통합되며, 로케일이 변경될 때 반응형 업데이트를 제공합니다.
|
|
393
|
+
|
|
394
|
+
> 페이지의 클라이언트 메시지에 필요한 네임스페이스를 추가하는 것을 잊지 마세요 (클라이언트 컴포넌트가 실제로 필요로 하는 네임스페이스만 포함하세요).
|
|
395
|
+
|
|
396
|
+
```tsx fileName="src/components/ClientComponent.tsx"
|
|
397
|
+
"use client";
|
|
398
|
+
|
|
399
|
+
import React, { useState } from "react";
|
|
400
|
+
import { useTranslations, useFormatter } from "next-intl";
|
|
401
|
+
|
|
402
|
+
const ClientComponent = () => {
|
|
403
|
+
// 중첩된 객체에 직접 범위를 지정
|
|
404
|
+
// useTranslations/useFormatter는 NextIntlClientProvider 컨텍스트에서 읽는 훅입니다.
|
|
405
|
+
// 이 훅들은 컴포넌트가 NextIntlClientProvider로 감싸져 있을 때만 작동합니다.
|
|
406
|
+
const t = useTranslations("about.counter");
|
|
407
|
+
const format = useFormatter();
|
|
408
|
+
const [count, setCount] = useState(0);
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
<div>
|
|
412
|
+
<p>{format.number(count)}</p>
|
|
413
|
+
<button
|
|
414
|
+
aria-label={t("label")}
|
|
415
|
+
onClick={() => setCount((count) => count + 1)}
|
|
416
|
+
>
|
|
417
|
+
{t("increment")}
|
|
418
|
+
</button>
|
|
419
|
+
</div>
|
|
420
|
+
);
|
|
421
|
+
};
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### 7단계: 서버 컴포넌트에서 번역 사용하기
|
|
425
|
+
|
|
426
|
+
서버 컴포넌트는 React 훅을 사용할 수 없으므로, 부모 컴포넌트로부터 props를 통해 번역과 포매터를 전달받습니다. 이 방법은 서버 컴포넌트를 동기적으로 유지하며 클라이언트 컴포넌트 내부에 중첩될 수 있게 합니다.
|
|
427
|
+
|
|
428
|
+
클라이언트 경계 내에 중첩될 수 있는 서버 컴포넌트는 동기적이어야 합니다. 번역된 문자열과 포맷된 값을 props로 전달함으로써 비동기 작업을 피하고 올바른 렌더링을 보장합니다. 부모 페이지 컴포넌트에서 번역과 포맷을 미리 계산하세요.
|
|
429
|
+
|
|
430
|
+
```tsx fileName="src/components/ServerComponent.tsx"
|
|
431
|
+
// 클라이언트 컴포넌트 내에 중첩된 서버 컴포넌트는 동기적이어야 합니다
|
|
432
|
+
// React는 서버/클라이언트 경계 간에 비동기 함수를 직렬화할 수 없습니다
|
|
433
|
+
// 해결책: 부모에서 번역/포맷을 미리 계산하고 props로 전달
|
|
434
|
+
type ServerComponentProps = {
|
|
435
|
+
formattedCount: string; // 포맷된 카운트 문자열
|
|
436
|
+
label: string; // 버튼 라벨
|
|
437
|
+
increment: string; // 증가 텍스트
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
const ServerComponent = ({
|
|
441
|
+
formattedCount,
|
|
442
|
+
label,
|
|
443
|
+
increment,
|
|
444
|
+
}: ServerComponentProps) => {
|
|
445
|
+
return (
|
|
446
|
+
<div>
|
|
447
|
+
<p>{formattedCount}</p>
|
|
448
|
+
<button aria-label={label}>{increment}</button>
|
|
449
|
+
</div>
|
|
450
|
+
);
|
|
451
|
+
};
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
> 페이지나 레이아웃에서 `next-intl/server`의 `getTranslations`와 `getFormatter`를 사용하여 번역과 포맷팅을 미리 계산한 후, 이를 props로 서버 컴포넌트에 전달하세요.
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
### (선택 사항) 8단계: 콘텐츠의 언어 변경하기
|
|
459
|
+
|
|
460
|
+
next-intl을 사용하여 콘텐츠의 언어를 변경하려면, 동일한 경로명을 가리키면서 로케일을 전환하는 로케일 인식 링크를 렌더링하세요. 프로바이더가 URL을 자동으로 재작성하므로 현재 경로만 지정하면 됩니다.
|
|
461
|
+
|
|
462
|
+
```tsx fileName="src/components/LocaleSwitcher.tsx"
|
|
463
|
+
"use client";
|
|
464
|
+
|
|
465
|
+
import Link from "next/link";
|
|
466
|
+
import { usePathname } from "next/navigation";
|
|
467
|
+
import { useLocale } from "next-intl";
|
|
468
|
+
import { defaultLocale, getCookie, type Locale, locales } from "@/i18n";
|
|
469
|
+
|
|
470
|
+
const getLocaleLabel = (locale: Locale): string => {
|
|
471
|
+
try {
|
|
472
|
+
const displayNames = new Intl.DisplayNames([locale], { type: "language" });
|
|
473
|
+
return displayNames.of(locale) ?? locale.toUpperCase();
|
|
474
|
+
} catch {
|
|
475
|
+
return locale.toUpperCase();
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const localeFlags: Record<Locale, string> = {
|
|
480
|
+
en: "🇬🇧",
|
|
481
|
+
fr: "🇫🇷",
|
|
482
|
+
es: "🇪🇸",
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
export default function LocaleSwitcher() {
|
|
486
|
+
const activeLocale = useLocale();
|
|
487
|
+
const pathname = usePathname();
|
|
488
|
+
|
|
489
|
+
// 경로에서 로케일 접두사를 제거하여 기본 경로를 가져옵니다
|
|
490
|
+
const getBasePath = (path: string) => {
|
|
491
|
+
for (const locale of locales) {
|
|
492
|
+
if (path.startsWith(`/${locale}`)) {
|
|
493
|
+
return path.slice(locale.length + 1) || "/";
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return path;
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
const basePath = getBasePath(pathname);
|
|
500
|
+
|
|
501
|
+
return (
|
|
502
|
+
<nav aria-label="언어 선택기">
|
|
503
|
+
<div>
|
|
504
|
+
{(locales as readonly Locale[]).map((locale) => {
|
|
505
|
+
const isActive = locale === activeLocale;
|
|
506
|
+
// 기본 로케일인지 여부에 따라 href를 생성합니다
|
|
507
|
+
const href =
|
|
508
|
+
locale === defaultLocale ? basePath : `/${locale}${basePath}`;
|
|
509
|
+
return (
|
|
510
|
+
<Link
|
|
511
|
+
key={locale}
|
|
512
|
+
href={href}
|
|
513
|
+
aria-current={isActive ? "page" : undefined}
|
|
514
|
+
onClick={() => {
|
|
515
|
+
document.cookie = getCookie(locale);
|
|
516
|
+
}}
|
|
517
|
+
>
|
|
518
|
+
<span>{localeFlags[locale]}</span>
|
|
519
|
+
<span>{getLocaleLabel(locale)}</span>
|
|
520
|
+
<span>{locale.toUpperCase()}</span>
|
|
521
|
+
</Link>
|
|
522
|
+
);
|
|
523
|
+
})}
|
|
524
|
+
</div>
|
|
525
|
+
</nav>
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### (선택 사항) 9단계: 현지화된 Link 컴포넌트 사용하기
|
|
531
|
+
|
|
532
|
+
`next-intl`은 활성 로케일을 자동으로 적용하는 현지화된 링크 컴포넌트를 포함하는 서브패키지 `next-intl/navigation`을 제공합니다. 우리는 이미 `@/i18n` 파일에서 이를 추출해 두었으므로 다음과 같이 사용할 수 있습니다:
|
|
533
|
+
|
|
534
|
+
```tsx fileName="src/components/MyComponent.tsx"
|
|
535
|
+
import { Link } from "@/i18n";
|
|
536
|
+
|
|
537
|
+
return <Link href="/about">t("about.title")</Link>;
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### (선택 사항) 10단계: 서버 액션 내에서 활성 로케일 접근하기
|
|
541
|
+
|
|
542
|
+
서버 액션은 `next-intl/server`를 사용하여 현재 로케일을 읽을 수 있습니다. 이는 현지화된 이메일을 보내거나 제출된 데이터와 함께 언어 선호도를 저장하는 데 유용합니다.
|
|
543
|
+
|
|
544
|
+
```ts fileName="src/app/actions/get-current-locale.ts"
|
|
545
|
+
"use server";
|
|
546
|
+
|
|
547
|
+
import { getLocale } from "next-intl/server";
|
|
548
|
+
|
|
549
|
+
export async function getCurrentLocale() {
|
|
550
|
+
return getLocale();
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export async function handleContactForm(formData: FormData) {
|
|
554
|
+
const locale = await getCurrentLocale();
|
|
555
|
+
|
|
556
|
+
// 템플릿, 분석 레이블 등을 선택하기 위해 locale을 사용합니다.
|
|
557
|
+
console.log(`locale ${locale}에서 받은 연락처 양식`);
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
> `getLocale`는 `next-intl` 프록시가 설정한 locale을 읽기 때문에 서버 어디서나 작동합니다: Route Handlers, Server Actions, 그리고 edge functions.
|
|
562
|
+
|
|
563
|
+
### (선택 사항) 11단계: 메타데이터 국제화하기
|
|
564
|
+
|
|
565
|
+
콘텐츠 번역도 중요하지만, 국제화의 주요 목표는 웹사이트를 전 세계에 더 잘 보이게 만드는 것입니다. I18n은 적절한 SEO를 통해 웹사이트 가시성을 향상시키는 놀라운 수단입니다.
|
|
566
|
+
|
|
567
|
+
적절하게 국제화된 메타데이터는 검색 엔진이 페이지에서 어떤 언어가 사용 가능한지 이해하는 데 도움을 줍니다. 여기에는 hreflang 메타 태그 설정, 제목과 설명 번역, 각 로케일에 대해 정규화된 URL이 올바르게 설정되었는지 확인하는 작업이 포함됩니다.
|
|
568
|
+
|
|
569
|
+
```tsx fileName="src/app/[locale]/about/layout.tsx"
|
|
570
|
+
import type { Metadata } from "next";
|
|
571
|
+
import { locales, defaultLocale, localizedPath } from "@/i18n";
|
|
572
|
+
import { getTranslations } from "next-intl/server";
|
|
573
|
+
|
|
574
|
+
// generateMetadata는 각 로케일마다 실행되어 SEO 친화적인 메타데이터를 생성합니다
|
|
575
|
+
// 이것은 검색 엔진이 대체 언어 버전을 이해하는 데 도움을 줍니다.
|
|
576
|
+
export async function generateMetadata({
|
|
577
|
+
params,
|
|
578
|
+
}: {
|
|
579
|
+
params: { locale: string };
|
|
580
|
+
}): Promise<Metadata> {
|
|
581
|
+
const { locale } = params;
|
|
582
|
+
const t = await getTranslations({ locale, namespace: "about" });
|
|
583
|
+
|
|
584
|
+
const url = "/about";
|
|
585
|
+
const languages = Object.fromEntries(
|
|
586
|
+
locales.map((locale) => [locale, localizedPath(locale, url)])
|
|
587
|
+
);
|
|
588
|
+
|
|
589
|
+
return {
|
|
590
|
+
title: t("title"),
|
|
591
|
+
description: t("description"),
|
|
592
|
+
alternates: {
|
|
593
|
+
canonical: localizedPath(locale, url),
|
|
594
|
+
languages: { ...languages, "x-default": url },
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// ... 페이지 나머지 코드
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### (선택 사항) 12단계: 사이트맵 국제화하기
|
|
603
|
+
|
|
604
|
+
모든 로케일 버전의 페이지를 포함하는 사이트맵을 생성하세요. 이는 검색 엔진이 모든 언어 버전의 콘텐츠를 발견하고 색인화하는 데 도움이 됩니다.
|
|
605
|
+
|
|
606
|
+
적절하게 국제화된 사이트맵은 검색 엔진이 모든 언어 버전의 페이지를 찾고 색인화할 수 있도록 보장합니다. 이는 국제 검색 결과에서 가시성을 향상시킵니다.
|
|
607
|
+
|
|
608
|
+
```tsx fileName="src/app/sitemap.ts"
|
|
609
|
+
import type { MetadataRoute } from "next";
|
|
610
|
+
import { defaultLocale, locales } from "@/i18n";
|
|
611
|
+
|
|
612
|
+
const origin = "https://example.com";
|
|
613
|
+
|
|
614
|
+
const formatterLocalizedPath = (locale: string, path: string) =>
|
|
615
|
+
locale === defaultLocale ? `${origin}${path}` : `${origin}/${locale}${path}`;
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* 모든 로케일과 해당 로컬라이즈된 경로의 맵을 가져옵니다.
|
|
619
|
+
*
|
|
620
|
+
* 예시 출력:
|
|
621
|
+
* {
|
|
622
|
+
* "en": "https://example.com",
|
|
623
|
+
* "fr": "https://example.com/fr",
|
|
624
|
+
* "es": "https://example.com/es",
|
|
625
|
+
* "x-default": "https://example.com"
|
|
626
|
+
* }
|
|
627
|
+
*/
|
|
628
|
+
const getLocalizedMap = (path: string) =>
|
|
629
|
+
Object.fromEntries([
|
|
630
|
+
...locales.map((locale) => [locale, formatterLocalizedPath(locale, path)]),
|
|
631
|
+
["x-default", formatterLocalizedPath(defaultLocale, path)],
|
|
632
|
+
]);
|
|
633
|
+
|
|
634
|
+
// 더 나은 SEO를 위해 모든 로케일 변형을 포함하는 사이트맵 생성
|
|
635
|
+
// alternates 필드는 검색 엔진에 언어 버전을 알립니다
|
|
636
|
+
export default function sitemap(): MetadataRoute.Sitemap {
|
|
637
|
+
return [
|
|
638
|
+
{
|
|
639
|
+
url: formatterLocalizedPath(defaultLocale, "/"),
|
|
640
|
+
lastModified: new Date(),
|
|
641
|
+
changeFrequency: "monthly",
|
|
642
|
+
priority: 1.0,
|
|
643
|
+
alternates: { languages: getLocalizedMap("/") },
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
url: formatterLocalizedPath(defaultLocale, "/about"),
|
|
647
|
+
lastModified: new Date(),
|
|
648
|
+
changeFrequency: "monthly",
|
|
649
|
+
priority: 0.7,
|
|
650
|
+
alternates: { languages: getLocalizedMap("/about") },
|
|
651
|
+
},
|
|
652
|
+
];
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### (선택 사항) 13단계: robots.txt 국제화하기
|
|
657
|
+
|
|
658
|
+
보호된 경로의 모든 로케일 버전을 적절히 처리하는 robots.txt 파일을 만드세요. 이를 통해 검색 엔진이 어떤 언어로든 관리자(admin)나 대시보드 페이지를 인덱싱하지 않도록 할 수 있습니다.
|
|
659
|
+
|
|
660
|
+
모든 로케일에 대해 robots.txt를 올바르게 구성하면, 각 로케일별로 경로가 다를 때 민감한 페이지가 검색 엔진에 인덱싱되는 것을 방지할 수 있습니다.
|
|
661
|
+
|
|
662
|
+
```tsx fileName="src/app/robots.ts"
|
|
663
|
+
import type { MetadataRoute } from "next";
|
|
664
|
+
import { locales, defaultLocale } from "@/i18n";
|
|
665
|
+
|
|
666
|
+
const origin = "https://example.com";
|
|
667
|
+
// 모든 로케일에 대한 경로 생성 (예: /admin, /fr/admin, /es/admin)
|
|
668
|
+
const withAllLocales = (path: string) => [
|
|
669
|
+
path,
|
|
670
|
+
...locales
|
|
671
|
+
.filter((locale) => locale !== defaultLocale)
|
|
672
|
+
.map((locale) => "/" + locale + path),
|
|
673
|
+
];
|
|
674
|
+
|
|
675
|
+
export default function robots(): MetadataRoute.Robots {
|
|
676
|
+
const disallow = [
|
|
677
|
+
...withAllLocales("/dashboard"),
|
|
678
|
+
...withAllLocales("/admin"),
|
|
679
|
+
];
|
|
680
|
+
|
|
681
|
+
return {
|
|
682
|
+
rules: { userAgent: "*", allow: ["/"], disallow },
|
|
683
|
+
host: origin,
|
|
684
|
+
sitemap: origin + "/sitemap.xml",
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### (선택 사항) 14단계: 로케일 라우팅을 위한 프록시 설정
|
|
690
|
+
|
|
691
|
+
사용자의 선호 로케일을 자동으로 감지하고 적절한 로케일 접두사가 붙은 URL로 리디렉션하는 프록시를 만드세요. next-intl은 이를 자동으로 처리하는 편리한 프록시 함수를 제공합니다.
|
|
692
|
+
|
|
693
|
+
프록시는 사용자가 사이트를 방문할 때 자동으로 선호하는 언어로 리디렉션되도록 보장합니다. 또한 사용자의 선호도를 저장하여 향후 방문 시 사용자 경험을 향상시킵니다.
|
|
694
|
+
|
|
695
|
+
```ts fileName="src/proxy.ts"
|
|
696
|
+
import { proxy } from "@/i18n";
|
|
697
|
+
|
|
698
|
+
// 미들웨어는 라우트 이전에 실행되어 로케일 감지 및 라우팅을 처리합니다.
|
|
699
|
+
// localeDetection: true는 Accept-Language 헤더를 사용하여 로케일을 자동 감지합니다.
|
|
700
|
+
export default proxy;
|
|
701
|
+
|
|
702
|
+
export const config = {
|
|
703
|
+
// API, Next 내부, 정적 자산은 건너뜁니다.
|
|
704
|
+
// 정규식: api, _next로 시작하거나 점(.)이 포함된 경로(파일)를 제외한 모든 경로와 매칭됩니다.
|
|
705
|
+
matcher: ["/((?!api|_next|.*\\..*).*)"],
|
|
706
|
+
};
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
### (선택 사항) 15단계: 로케일에 대한 TypeScript 타입 설정
|
|
710
|
+
|
|
711
|
+
TypeScript 설정은 키에 대한 자동완성과 타입 안전성을 제공하는 데 도움이 됩니다.
|
|
712
|
+
|
|
713
|
+
프로젝트 루트에 global.ts 파일을 생성하고 다음 코드를 추가할 수 있습니다:
|
|
714
|
+
|
|
715
|
+
```ts fileName="global.ts"
|
|
716
|
+
import type { locales } from "@/i18n";
|
|
717
|
+
|
|
718
|
+
type Messages = {
|
|
719
|
+
common: typeof import("./locales/en/common.json");
|
|
720
|
+
home: typeof import("./locales/en/home.json");
|
|
721
|
+
about: typeof import("./locales/en/about.json");
|
|
722
|
+
// ... 향후 JSON 파일도 여기에 추가해야 합니다
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
declare module "next-intl" {
|
|
726
|
+
interface AppConfig {
|
|
727
|
+
Locale: (typeof locales)[number];
|
|
728
|
+
Messages: Messages;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
이 코드는 모듈 확장(Module Augmentation)을 사용하여 locales와 messages를 next-intl의 AppConfig 타입에 추가합니다.
|
|
734
|
+
|
|
735
|
+
### (선택 사항) 15단계: Intlayer를 사용하여 번역 자동화하기
|
|
736
|
+
|
|
737
|
+
Intlayer는 애플리케이션의 현지화 과정을 지원하기 위해 설계된 **무료**이자 **오픈 소스** 라이브러리입니다. next-intl이 번역 로딩과 관리를 담당하는 반면, Intlayer는 번역 워크플로우를 자동화하는 데 도움을 줍니다.
|
|
738
|
+
|
|
739
|
+
번역을 수동으로 관리하는 것은 시간 소모가 크고 오류가 발생하기 쉽습니다. Intlayer는 번역 테스트, 생성 및 관리를 자동화하여 시간을 절약하고 애플리케이션 전반에 걸쳐 일관성을 보장합니다.
|
|
740
|
+
|
|
741
|
+
Intlayer는 다음을 가능하게 합니다:
|
|
742
|
+
|
|
743
|
+
- **코드베이스 내 원하는 위치에 콘텐츠 선언하기**
|
|
744
|
+
Intlayer는 `.content.{ts|js|json}` 파일을 사용하여 코드베이스 내 원하는 위치에 콘텐츠를 선언할 수 있게 합니다. 이를 통해 콘텐츠를 더 잘 조직할 수 있으며, 코드베이스의 가독성과 유지보수성을 향상시킵니다.
|
|
745
|
+
|
|
746
|
+
- **누락된 번역 테스트하기**
|
|
747
|
+
Intlayer는 CI/CD 파이프라인이나 단위 테스트에 통합할 수 있는 테스트 기능을 제공합니다. [번역 테스트](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/testing.md)에 대해 자세히 알아보세요.
|
|
748
|
+
|
|
749
|
+
- **번역 자동화**
|
|
750
|
+
Intlayer는 번역을 자동화할 수 있는 CLI와 VSCode 확장 기능을 제공합니다. 이는 CI/CD 파이프라인에 통합할 수 있습니다. [번역 자동화](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_cli.md)에 대해 자세히 알아보세요.
|
|
751
|
+
사용자는 **자신의 API 키와 원하는 AI 제공자를 사용할 수 있습니다**. 또한 상황에 맞는 번역을 제공하므로, [내용 채우기](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/autoFill.md)를 참고하세요.
|
|
752
|
+
|
|
753
|
+
- **외부 콘텐츠 연결**
|
|
754
|
+
Intlayer는 외부 콘텐츠 관리 시스템(CMS)에 콘텐츠를 연결할 수 있도록 합니다. 이를 최적화된 방식으로 가져와 JSON 리소스에 삽입할 수 있습니다. [외부 콘텐츠 가져오기](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/function_fetching.md)에서 자세히 알아보세요.
|
|
755
|
+
|
|
756
|
+
- **비주얼 에디터**
|
|
757
|
+
Intlayer는 비주얼 에디터를 사용하여 콘텐츠를 편집할 수 있는 무료 비주얼 에디터를 제공합니다. [번역 비주얼 편집](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_visual_editor.md)에서 자세히 알아보세요.
|
|
758
|
+
|
|
759
|
+
그리고 더 많은 기능들이 있습니다. Intlayer가 제공하는 모든 기능을 확인하려면 [Intlayer의 관심사 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/interest_of_intlayer.md)를 참조하세요.
|