@intlayer/docs 7.2.3 → 7.3.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 +2 -0
- package/blog/ar/compiler_vs_declarative_i18n.md +138 -0
- package/blog/ar/intlayer_with_next-i18next.md +0 -1
- package/blog/ar/intlayer_with_vue-i18n.md +0 -1
- package/blog/de/compiler_vs_declarative_i18n.md +138 -0
- package/blog/de/intlayer_with_next-i18next.md +0 -1
- package/blog/de/intlayer_with_vue-i18n.md +0 -1
- package/blog/en/compiler_vs_declarative_i18n.md +138 -0
- package/blog/en/i18n_using_next-i18next.md +1 -1
- package/blog/en/i18n_using_next-intl.md +1 -1
- package/blog/en/intlayer_with_i18next.md +1 -1
- package/blog/en/intlayer_with_next-i18next.md +1 -2
- package/blog/en/intlayer_with_next-intl.md +1 -1
- package/blog/en/intlayer_with_react-i18next.md +1 -1
- package/blog/en/intlayer_with_react-intl.md +1 -1
- package/blog/en/intlayer_with_vue-i18n.md +1 -2
- package/blog/en-GB/compiler_vs_declarative_i18n.md +138 -0
- package/blog/en-GB/intlayer_with_next-i18next.md +0 -1
- package/blog/en-GB/intlayer_with_vue-i18n.md +0 -1
- package/blog/es/compiler_vs_declarative_i18n.md +138 -0
- package/blog/es/intlayer_with_next-i18next.md +0 -1
- package/blog/es/intlayer_with_vue-i18n.md +0 -1
- package/blog/fr/compiler_vs_declarative_i18n.md +138 -0
- package/blog/fr/intlayer_with_next-i18next.md +0 -1
- package/blog/fr/intlayer_with_vue-i18n.md +0 -1
- package/blog/hi/compiler_vs_declarative_i18n.md +138 -0
- package/blog/hi/intlayer_with_next-i18next.md +0 -1
- package/blog/hi/intlayer_with_vue-i18n.md +0 -1
- package/blog/id/compiler_vs_declarative_i18n.md +138 -0
- package/blog/id/intlayer_with_next-i18next.md +0 -1
- package/blog/id/intlayer_with_vue-i18n.md +0 -1
- package/blog/it/compiler_vs_declarative_i18n.md +138 -0
- package/blog/it/intlayer_with_next-i18next.md +0 -1
- package/blog/it/intlayer_with_vue-i18n.md +0 -1
- package/blog/ja/compiler_vs_declarative_i18n.md +138 -0
- package/blog/ja/intlayer_with_next-i18next.md +0 -1
- package/blog/ja/intlayer_with_vue-i18n.md +0 -1
- package/blog/ko/compiler_vs_declarative_i18n.md +138 -0
- package/blog/ko/intlayer_with_next-i18next.md +0 -1
- package/blog/ko/intlayer_with_vue-i18n.md +0 -1
- package/blog/pl/compiler_vs_declarative_i18n.md +138 -0
- package/blog/pl/intlayer_with_next-i18next.md +0 -1
- package/blog/pl/intlayer_with_vue-i18n.md +0 -1
- package/blog/pt/compiler_vs_declarative_i18n.md +138 -0
- package/blog/pt/intlayer_with_next-i18next.md +0 -1
- package/blog/pt/intlayer_with_vue-i18n.md +0 -1
- package/blog/ru/compiler_vs_declarative_i18n.md +138 -0
- package/blog/ru/intlayer_with_next-i18next.md +0 -1
- package/blog/ru/intlayer_with_vue-i18n.md +0 -1
- package/blog/tr/compiler_vs_declarative_i18n.md +138 -0
- package/blog/tr/intlayer_with_next-i18next.md +0 -1
- package/blog/tr/intlayer_with_vue-i18n.md +0 -1
- package/blog/vi/compiler_vs_declarative_i18n.md +138 -0
- package/blog/vi/intlayer_with_next-i18next.md +0 -1
- package/blog/vi/intlayer_with_vue-i18n.md +0 -1
- package/blog/zh/compiler_vs_declarative_i18n.md +138 -0
- package/blog/zh/intlayer_with_next-i18next.md +0 -1
- package/blog/zh/intlayer_with_vue-i18n.md +0 -1
- package/dist/cjs/generated/blog.entry.cjs +19 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +323 -19
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +19 -0
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +323 -19
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/blog.entry.d.ts +1 -0
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +17 -1
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/cli/build.md +64 -0
- package/docs/ar/cli/configuration.md +63 -0
- package/docs/ar/cli/debug.md +46 -0
- package/docs/ar/cli/doc-review.md +43 -0
- package/docs/ar/cli/doc-translate.md +132 -0
- package/docs/ar/cli/editor.md +28 -0
- package/docs/ar/cli/fill.md +130 -0
- package/docs/ar/cli/index.md +163 -0
- package/docs/ar/cli/list.md +53 -0
- package/docs/ar/cli/live.md +41 -0
- package/docs/ar/cli/pull.md +78 -0
- package/docs/ar/cli/push.md +98 -0
- package/docs/ar/cli/sdk.md +67 -0
- package/docs/ar/cli/test.md +76 -0
- package/docs/ar/cli/transform.md +65 -0
- package/docs/ar/cli/version.md +24 -0
- package/docs/ar/cli/watch.md +37 -0
- package/docs/ar/packages/intlayer/getPrefix.md +210 -0
- package/docs/de/cli/build.md +64 -0
- package/docs/de/cli/configuration.md +63 -0
- package/docs/de/cli/debug.md +46 -0
- package/docs/de/cli/doc-review.md +43 -0
- package/docs/de/cli/doc-translate.md +132 -0
- package/docs/de/cli/editor.md +28 -0
- package/docs/de/cli/fill.md +130 -0
- package/docs/de/cli/index.md +163 -0
- package/docs/de/cli/list.md +53 -0
- package/docs/de/cli/live.md +41 -0
- package/docs/de/cli/pull.md +78 -0
- package/docs/de/cli/push.md +98 -0
- package/docs/de/cli/sdk.md +67 -0
- package/docs/de/cli/test.md +76 -0
- package/docs/de/cli/transform.md +65 -0
- package/docs/de/cli/version.md +24 -0
- package/docs/de/cli/watch.md +37 -0
- package/docs/de/packages/intlayer/getPrefix.md +213 -0
- package/docs/en/CI_CD.md +2 -2
- package/docs/en/autoFill.md +24 -2
- package/docs/en/cli/build.md +64 -0
- package/docs/en/cli/configuration.md +63 -0
- package/docs/en/cli/debug.md +46 -0
- package/docs/en/cli/doc-review.md +43 -0
- package/docs/en/cli/doc-translate.md +132 -0
- package/docs/en/cli/editor.md +28 -0
- package/docs/en/cli/fill.md +130 -0
- package/docs/en/cli/index.md +163 -0
- package/docs/en/cli/list.md +53 -0
- package/docs/en/cli/live.md +41 -0
- package/docs/en/cli/pull.md +78 -0
- package/docs/en/cli/push.md +98 -0
- package/docs/en/cli/sdk.md +67 -0
- package/docs/en/cli/test.md +76 -0
- package/docs/en/cli/transform.md +65 -0
- package/docs/en/cli/version.md +24 -0
- package/docs/en/cli/watch.md +37 -0
- package/docs/en/dictionary/condition.md +1 -1
- package/docs/en/dictionary/enumeration.md +1 -1
- package/docs/en/dictionary/file.md +1 -1
- package/docs/en/dictionary/gender.md +1 -1
- package/docs/en/dictionary/insertion.md +1 -1
- package/docs/en/dictionary/markdown.md +1 -1
- package/docs/en/dictionary/nesting.md +1 -1
- package/docs/en/index.md +1 -1
- package/docs/en/intlayer_with_angular.md +1 -1
- package/docs/en/intlayer_with_astro.md +1 -1
- package/docs/en/intlayer_with_create_react_app.md +1 -1
- package/docs/en/intlayer_with_lynx+react.md +1 -1
- package/docs/en/intlayer_with_next-i18next.md +1 -1
- package/docs/en/intlayer_with_next-intl.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_nuxt.md +1 -1
- package/docs/en/intlayer_with_react_native+expo.md +1 -1
- package/docs/en/intlayer_with_react_router_v7.md +1 -1
- package/docs/en/intlayer_with_tanstack.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+solid.md +1 -1
- package/docs/en/intlayer_with_vite+svelte.md +1 -1
- package/docs/en/intlayer_with_vite+vue.md +1 -1
- package/docs/en/introduction.md +1 -1
- package/docs/en/mcp_server.md +1 -2
- package/docs/en/per_locale_file.md +1 -1
- package/docs/en/plugins/sync-json.md +1 -1
- package/docs/en/releases/v6.md +2 -2
- package/docs/en/roadmap.md +1 -1
- package/docs/en-GB/cli/build.md +64 -0
- package/docs/en-GB/cli/configuration.md +63 -0
- package/docs/en-GB/cli/debug.md +46 -0
- package/docs/en-GB/cli/doc-review.md +43 -0
- package/docs/en-GB/cli/doc-translate.md +132 -0
- package/docs/en-GB/cli/editor.md +28 -0
- package/docs/en-GB/cli/fill.md +130 -0
- package/docs/en-GB/cli/index.md +163 -0
- package/docs/en-GB/cli/list.md +53 -0
- package/docs/en-GB/cli/live.md +41 -0
- package/docs/en-GB/cli/pull.md +78 -0
- package/docs/en-GB/cli/push.md +98 -0
- package/docs/en-GB/cli/sdk.md +67 -0
- package/docs/en-GB/cli/test.md +100 -0
- package/docs/en-GB/cli/transform.md +65 -0
- package/docs/en-GB/cli/version.md +24 -0
- package/docs/en-GB/cli/watch.md +37 -0
- package/docs/en-GB/dictionary/condition.md +1 -1
- package/docs/en-GB/dictionary/markdown.md +1 -1
- package/docs/en-GB/dictionary/nesting.md +1 -1
- package/docs/en-GB/intlayer_with_nextjs_14.md +1 -1
- package/docs/en-GB/intlayer_with_react_native+expo.md +1 -1
- package/docs/en-GB/packages/intlayer/getPrefix.md +213 -0
- package/docs/es/cli/build.md +64 -0
- package/docs/es/cli/configuration.md +63 -0
- package/docs/es/cli/debug.md +46 -0
- package/docs/es/cli/doc-review.md +43 -0
- package/docs/es/cli/doc-translate.md +132 -0
- package/docs/es/cli/editor.md +28 -0
- package/docs/es/cli/fill.md +130 -0
- package/docs/es/cli/index.md +163 -0
- package/docs/es/cli/list.md +53 -0
- package/docs/es/cli/live.md +41 -0
- package/docs/es/cli/pull.md +78 -0
- package/docs/es/cli/push.md +98 -0
- package/docs/es/cli/sdk.md +67 -0
- package/docs/es/cli/test.md +76 -0
- package/docs/es/cli/transform.md +65 -0
- package/docs/es/cli/version.md +24 -0
- package/docs/es/cli/watch.md +37 -0
- package/docs/es/packages/intlayer/getPrefix.md +213 -0
- package/docs/fr/cli/build.md +64 -0
- package/docs/fr/cli/configuration.md +63 -0
- package/docs/fr/cli/debug.md +46 -0
- package/docs/fr/cli/doc-review.md +43 -0
- package/docs/fr/cli/doc-translate.md +132 -0
- package/docs/fr/cli/editor.md +28 -0
- package/docs/fr/cli/fill.md +130 -0
- package/docs/fr/cli/index.md +163 -0
- package/docs/fr/cli/list.md +53 -0
- package/docs/fr/cli/live.md +41 -0
- package/docs/fr/cli/pull.md +78 -0
- package/docs/fr/cli/push.md +98 -0
- package/docs/fr/cli/sdk.md +67 -0
- package/docs/fr/cli/test.md +76 -0
- package/docs/fr/cli/transform.md +65 -0
- package/docs/fr/cli/version.md +24 -0
- package/docs/fr/cli/watch.md +37 -0
- package/docs/fr/packages/intlayer/getPrefix.md +213 -0
- package/docs/hi/cli/build.md +64 -0
- package/docs/hi/cli/configuration.md +63 -0
- package/docs/hi/cli/debug.md +46 -0
- package/docs/hi/cli/doc-review.md +43 -0
- package/docs/hi/cli/doc-translate.md +132 -0
- package/docs/hi/cli/editor.md +28 -0
- package/docs/hi/cli/fill.md +130 -0
- package/docs/hi/cli/index.md +163 -0
- package/docs/hi/cli/list.md +53 -0
- package/docs/hi/cli/live.md +41 -0
- package/docs/hi/cli/pull.md +78 -0
- package/docs/hi/cli/push.md +98 -0
- package/docs/hi/cli/sdk.md +67 -0
- package/docs/hi/cli/test.md +76 -0
- package/docs/hi/cli/transform.md +65 -0
- package/docs/hi/cli/version.md +24 -0
- package/docs/hi/cli/watch.md +37 -0
- package/docs/hi/intlayer_with_tanstack.md +1 -1
- package/docs/hi/intlayer_with_vite+solid.md +1 -1
- package/docs/hi/packages/intlayer/getPrefix.md +217 -0
- package/docs/id/cli/build.md +64 -0
- package/docs/id/cli/configuration.md +62 -0
- package/docs/id/cli/debug.md +46 -0
- package/docs/id/cli/doc-review.md +43 -0
- package/docs/id/cli/doc-translate.md +132 -0
- package/docs/id/cli/editor.md +28 -0
- package/docs/id/cli/fill.md +130 -0
- package/docs/id/cli/index.md +163 -0
- package/docs/id/cli/list.md +53 -0
- package/docs/id/cli/live.md +41 -0
- package/docs/id/cli/pull.md +78 -0
- package/docs/id/cli/push.md +98 -0
- package/docs/id/cli/sdk.md +67 -0
- package/docs/id/cli/test.md +76 -0
- package/docs/id/cli/transform.md +65 -0
- package/docs/id/cli/version.md +24 -0
- package/docs/id/cli/watch.md +37 -0
- package/docs/id/packages/intlayer/getPrefix.md +210 -0
- package/docs/it/cli/build.md +64 -0
- package/docs/it/cli/configuration.md +63 -0
- package/docs/it/cli/debug.md +46 -0
- package/docs/it/cli/doc-review.md +43 -0
- package/docs/it/cli/doc-translate.md +132 -0
- package/docs/it/cli/editor.md +28 -0
- package/docs/it/cli/fill.md +130 -0
- package/docs/it/cli/index.md +158 -0
- package/docs/it/cli/list.md +53 -0
- package/docs/it/cli/live.md +41 -0
- package/docs/it/cli/pull.md +78 -0
- package/docs/it/cli/push.md +98 -0
- package/docs/it/cli/sdk.md +67 -0
- package/docs/it/cli/test.md +76 -0
- package/docs/it/cli/transform.md +65 -0
- package/docs/it/cli/version.md +24 -0
- package/docs/it/cli/watch.md +39 -0
- package/docs/it/packages/intlayer/getPrefix.md +211 -0
- package/docs/ja/cli/build.md +78 -0
- package/docs/ja/cli/configuration.md +63 -0
- package/docs/ja/cli/debug.md +46 -0
- package/docs/ja/cli/doc-review.md +43 -0
- package/docs/ja/cli/doc-translate.md +132 -0
- package/docs/ja/cli/editor.md +28 -0
- package/docs/ja/cli/fill.md +130 -0
- package/docs/ja/cli/index.md +163 -0
- package/docs/ja/cli/list.md +53 -0
- package/docs/ja/cli/live.md +41 -0
- package/docs/ja/cli/pull.md +78 -0
- package/docs/ja/cli/push.md +113 -0
- package/docs/ja/cli/sdk.md +67 -0
- package/docs/ja/cli/test.md +76 -0
- package/docs/ja/cli/transform.md +65 -0
- package/docs/ja/cli/version.md +24 -0
- package/docs/ja/cli/watch.md +37 -0
- package/docs/ja/packages/intlayer/getPrefix.md +212 -0
- package/docs/ko/cli/build.md +64 -0
- package/docs/ko/cli/configuration.md +63 -0
- package/docs/ko/cli/debug.md +46 -0
- package/docs/ko/cli/doc-review.md +43 -0
- package/docs/ko/cli/doc-translate.md +132 -0
- package/docs/ko/cli/editor.md +28 -0
- package/docs/ko/cli/fill.md +130 -0
- package/docs/ko/cli/index.md +163 -0
- package/docs/ko/cli/list.md +53 -0
- package/docs/ko/cli/live.md +41 -0
- package/docs/ko/cli/pull.md +78 -0
- package/docs/ko/cli/push.md +113 -0
- package/docs/ko/cli/sdk.md +67 -0
- package/docs/ko/cli/test.md +76 -0
- package/docs/ko/cli/transform.md +65 -0
- package/docs/ko/cli/version.md +24 -0
- package/docs/ko/cli/watch.md +37 -0
- package/docs/ko/packages/intlayer/getPrefix.md +213 -0
- package/docs/pl/cli/build.md +64 -0
- package/docs/pl/cli/configuration.md +63 -0
- package/docs/pl/cli/debug.md +46 -0
- package/docs/pl/cli/doc-review.md +43 -0
- package/docs/pl/cli/doc-translate.md +132 -0
- package/docs/pl/cli/editor.md +28 -0
- package/docs/pl/cli/fill.md +130 -0
- package/docs/pl/cli/index.md +163 -0
- package/docs/pl/cli/list.md +53 -0
- package/docs/pl/cli/live.md +41 -0
- package/docs/pl/cli/pull.md +78 -0
- package/docs/pl/cli/push.md +98 -0
- package/docs/pl/cli/sdk.md +67 -0
- package/docs/pl/cli/test.md +76 -0
- package/docs/pl/cli/transform.md +65 -0
- package/docs/pl/cli/version.md +24 -0
- package/docs/pl/cli/watch.md +39 -0
- package/docs/pl/packages/intlayer/getPrefix.md +217 -0
- package/docs/pt/cli/build.md +64 -0
- package/docs/pt/cli/configuration.md +63 -0
- package/docs/pt/cli/debug.md +46 -0
- package/docs/pt/cli/doc-review.md +43 -0
- package/docs/pt/cli/doc-translate.md +132 -0
- package/docs/pt/cli/editor.md +28 -0
- package/docs/pt/cli/fill.md +130 -0
- package/docs/pt/cli/index.md +163 -0
- package/docs/pt/cli/list.md +53 -0
- package/docs/pt/cli/live.md +41 -0
- package/docs/pt/cli/pull.md +78 -0
- package/docs/pt/cli/push.md +98 -0
- package/docs/pt/cli/sdk.md +67 -0
- package/docs/pt/cli/test.md +76 -0
- package/docs/pt/cli/transform.md +65 -0
- package/docs/pt/cli/version.md +24 -0
- package/docs/pt/cli/watch.md +39 -0
- package/docs/pt/packages/intlayer/getPrefix.md +217 -0
- package/docs/ru/cli/build.md +64 -0
- package/docs/ru/cli/configuration.md +63 -0
- package/docs/ru/cli/debug.md +46 -0
- package/docs/ru/cli/doc-review.md +43 -0
- package/docs/ru/cli/doc-translate.md +132 -0
- package/docs/ru/cli/editor.md +28 -0
- package/docs/ru/cli/fill.md +130 -0
- package/docs/ru/cli/index.md +163 -0
- package/docs/ru/cli/list.md +53 -0
- package/docs/ru/cli/live.md +41 -0
- package/docs/ru/cli/pull.md +78 -0
- package/docs/ru/cli/push.md +98 -0
- package/docs/ru/cli/sdk.md +67 -0
- package/docs/ru/cli/test.md +76 -0
- package/docs/ru/cli/transform.md +65 -0
- package/docs/ru/cli/version.md +24 -0
- package/docs/ru/cli/watch.md +39 -0
- package/docs/ru/packages/intlayer/getPrefix.md +213 -0
- package/docs/tr/CI_CD.md +2 -2
- package/docs/tr/cli/build.md +64 -0
- package/docs/tr/cli/configuration.md +63 -0
- package/docs/tr/cli/debug.md +46 -0
- package/docs/tr/cli/doc-review.md +43 -0
- package/docs/tr/cli/doc-translate.md +132 -0
- package/docs/tr/cli/editor.md +28 -0
- package/docs/tr/cli/fill.md +130 -0
- package/docs/tr/cli/index.md +163 -0
- package/docs/tr/cli/list.md +53 -0
- package/docs/tr/cli/live.md +41 -0
- package/docs/tr/cli/pull.md +78 -0
- package/docs/tr/cli/push.md +98 -0
- package/docs/tr/cli/sdk.md +67 -0
- package/docs/tr/cli/test.md +76 -0
- package/docs/tr/cli/transform.md +65 -0
- package/docs/tr/cli/version.md +24 -0
- package/docs/tr/cli/watch.md +39 -0
- package/docs/tr/dictionary/condition.md +1 -1
- package/docs/tr/dictionary/enumeration.md +1 -1
- package/docs/tr/dictionary/file.md +1 -1
- package/docs/tr/dictionary/gender.md +1 -1
- package/docs/tr/dictionary/insertion.md +1 -1
- package/docs/tr/dictionary/markdown.md +1 -1
- package/docs/tr/dictionary/nesting.md +1 -1
- package/docs/tr/index.md +1 -1
- package/docs/tr/intlayer_with_angular.md +1 -1
- package/docs/tr/intlayer_with_create_react_app.md +1 -1
- package/docs/tr/intlayer_with_lynx+react.md +1 -1
- package/docs/tr/intlayer_with_nextjs_15.md +1 -1
- package/docs/tr/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/tr/intlayer_with_nuxt.md +1 -1
- package/docs/tr/intlayer_with_react_native+expo.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+solid.md +1 -1
- package/docs/tr/intlayer_with_vite+vue.md +1 -1
- package/docs/tr/introduction.md +1 -1
- package/docs/tr/mcp_server.md +1 -1
- package/docs/tr/packages/intlayer/getPrefix.md +213 -0
- package/docs/tr/per_locale_file.md +1 -1
- package/docs/tr/roadmap.md +1 -1
- package/docs/vi/cli/build.md +64 -0
- package/docs/vi/cli/configuration.md +63 -0
- package/docs/vi/cli/debug.md +46 -0
- package/docs/vi/cli/doc-review.md +43 -0
- package/docs/vi/cli/doc-translate.md +132 -0
- package/docs/vi/cli/editor.md +28 -0
- package/docs/vi/cli/fill.md +130 -0
- package/docs/vi/cli/index.md +163 -0
- package/docs/vi/cli/list.md +53 -0
- package/docs/vi/cli/live.md +41 -0
- package/docs/vi/cli/pull.md +78 -0
- package/docs/vi/cli/push.md +98 -0
- package/docs/vi/cli/sdk.md +67 -0
- package/docs/vi/cli/test.md +76 -0
- package/docs/vi/cli/transform.md +65 -0
- package/docs/vi/cli/version.md +24 -0
- package/docs/vi/cli/watch.md +37 -0
- package/docs/vi/packages/intlayer/getPrefix.md +213 -0
- package/docs/zh/cli/build.md +64 -0
- package/docs/zh/cli/configuration.md +63 -0
- package/docs/zh/cli/debug.md +46 -0
- package/docs/zh/cli/doc-review.md +43 -0
- package/docs/zh/cli/doc-translate.md +132 -0
- package/docs/zh/cli/editor.md +28 -0
- package/docs/zh/cli/fill.md +130 -0
- package/docs/zh/cli/index.md +168 -0
- package/docs/zh/cli/list.md +53 -0
- package/docs/zh/cli/live.md +41 -0
- package/docs/zh/cli/pull.md +78 -0
- package/docs/zh/cli/push.md +113 -0
- package/docs/zh/cli/sdk.md +67 -0
- package/docs/zh/cli/test.md +76 -0
- package/docs/zh/cli/transform.md +65 -0
- package/docs/zh/cli/version.md +24 -0
- package/docs/zh/cli/watch.md +37 -0
- package/docs/zh/packages/intlayer/getPrefix.md +213 -0
- package/package.json +9 -9
- package/src/generated/blog.entry.ts +19 -0
- package/src/generated/docs.entry.ts +323 -19
- package/docs/ar/intlayer_cli.md +0 -614
- package/docs/de/intlayer_cli.md +0 -615
- package/docs/en/intlayer_cli.md +0 -897
- package/docs/en-GB/intlayer_cli.md +0 -615
- package/docs/es/intlayer_cli.md +0 -614
- package/docs/fr/intlayer_cli.md +0 -614
- package/docs/hi/intlayer_cli.md +0 -616
- package/docs/id/intlayer_cli.md +0 -886
- package/docs/it/intlayer_cli.md +0 -610
- package/docs/ja/intlayer_cli.md +0 -616
- package/docs/ko/intlayer_cli.md +0 -614
- package/docs/pl/intlayer_cli.md +0 -893
- package/docs/pt/intlayer_cli.md +0 -615
- package/docs/ru/intlayer_cli.md +0 -885
- package/docs/tr/intlayer_cli.md +0 -614
- package/docs/vi/intlayer_cli.md +0 -886
- package/docs/zh/intlayer_cli.md +0 -613
|
@@ -176,7 +176,6 @@ export default config;
|
|
|
176
176
|
```plaintext fileName=".gitignore"
|
|
177
177
|
# Intlayer द्वारा जनरेट की गई फ़ाइलों को अनदेखा करें
|
|
178
178
|
.intlayer
|
|
179
|
-
intl
|
|
180
179
|
```
|
|
181
180
|
|
|
182
181
|
ये फ़ाइलें बिल्ड प्रक्रिया के दौरान स्वचालित रूप से पुनः उत्पन्न होती हैं और इन्हें आपके रिपॉजिटरी में कमिट करने की आवश्यकता नहीं है।
|
|
@@ -166,7 +166,6 @@ export default config;
|
|
|
166
166
|
```plaintext fileName=".gitignore"
|
|
167
167
|
# Intlayer द्वारा जनरेट की गई फ़ाइलों को अनदेखा करें
|
|
168
168
|
.intlayer
|
|
169
|
-
intl
|
|
170
169
|
```
|
|
171
170
|
|
|
172
171
|
ये फ़ाइलें बिल्ड प्रक्रिया के दौरान स्वचालित रूप से पुनः उत्पन्न होती हैं और इन्हें आपके रिपॉजिटरी में कमिट करने की आवश्यकता नहीं है।
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-11-24
|
|
3
|
+
updatedAt: 2025-11-24
|
|
4
|
+
title: Compiler vs. Deklaratif i18n
|
|
5
|
+
description: Menjelajahi pertukaran arsitektural antara internasionalisasi berbasis compiler "ajaib" dan manajemen konten deklaratif yang eksplisit.
|
|
6
|
+
keywords:
|
|
7
|
+
- Intlayer
|
|
8
|
+
- Internasionalisasi
|
|
9
|
+
- Blog
|
|
10
|
+
- Next.js
|
|
11
|
+
- JavaScript
|
|
12
|
+
- React
|
|
13
|
+
- i18n
|
|
14
|
+
- Compiler
|
|
15
|
+
- Deklaratif
|
|
16
|
+
slugs:
|
|
17
|
+
- compiler-vs-declarative-i18n
|
|
18
|
+
- blog
|
|
19
|
+
- i18n
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Argumen Mendukung dan Menentang i18n Berbasis Compiler
|
|
23
|
+
|
|
24
|
+
Jika Anda telah membangun aplikasi web selama lebih dari satu dekade, Anda tahu bahwa Internasionalisasi (i18n) selalu menjadi titik gesekan. Ini sering menjadi tugas yang tidak ada yang ingin lakukan—mengekstrak string, mengelola file JSON, dan memikirkan aturan pluralisasi.
|
|
25
|
+
|
|
26
|
+
Baru-baru ini, gelombang baru alat i18n "berbasis Compiler" telah muncul, menjanjikan untuk menghilangkan rasa sakit ini. Janjinya menggoda: **Cukup tulis teks di komponen Anda, dan biarkan alat build yang mengurus sisanya.** Tidak perlu kunci, tidak perlu impor, hanya keajaiban.
|
|
27
|
+
|
|
28
|
+
Namun seperti semua abstraksi dalam rekayasa perangkat lunak, keajaiban datang dengan harga.
|
|
29
|
+
|
|
30
|
+
Dalam posting blog ini, kita akan mengeksplorasi pergeseran dari perpustakaan deklaratif ke pendekatan berbasis compiler, utang arsitektural tersembunyi yang mereka perkenalkan, dan mengapa cara "membosankan" mungkin masih menjadi cara terbaik untuk aplikasi profesional.
|
|
31
|
+
|
|
32
|
+
## Sejarah Singkat Terjemahan
|
|
33
|
+
|
|
34
|
+
Untuk memahami di mana kita berada, kita harus melihat kembali dari mana kita memulai.
|
|
35
|
+
|
|
36
|
+
Sekitar tahun 2011–2012, lanskap JavaScript sangat berbeda. Bundler seperti yang kita kenal sekarang (Webpack, Vite) belum ada atau masih dalam tahap awal. Kita menggabungkan skrip langsung di browser. Pada era ini, perpustakaan seperti **i18next** lahir.
|
|
37
|
+
|
|
38
|
+
Mereka memecahkan masalah dengan satu-satunya cara yang mungkin saat itu: **Kamus Runtime**. Anda memuat objek JSON besar ke dalam memori, dan sebuah fungsi mencari kunci secara langsung saat runtime. Ini dapat diandalkan, eksplisit, dan bekerja di mana saja.
|
|
39
|
+
|
|
40
|
+
Maju ke hari ini. Kita memiliki compiler yang kuat (SWC, bundler berbasis Rust) yang dapat mengurai Abstract Syntax Trees (AST) dalam hitungan milidetik. Kekuatan ini melahirkan ide baru: _Mengapa kita harus mengelola kunci secara manual? Mengapa compiler tidak langsung melihat teks "Hello World" dan menggantinya untuk kita?_
|
|
41
|
+
|
|
42
|
+
Dengan demikian, i18n berbasis Compiler lahir.
|
|
43
|
+
|
|
44
|
+
## Daya Tarik Compiler (Pendekatan "Ajaib")
|
|
45
|
+
|
|
46
|
+
Ada alasan mengapa pendekatan baru ini sedang tren. Bagi seorang developer, pengalamannya terasa luar biasa.
|
|
47
|
+
|
|
48
|
+
### 1. Kecepatan dan "Aliran"
|
|
49
|
+
|
|
50
|
+
Saat Anda sedang fokus, berhenti untuk memikirkan nama variabel (`home_hero_title_v2`) akan memutus aliran kerja Anda. Dengan pendekatan compiler, Anda mengetik `<p>Welcome back</p>` dan terus melanjutkan. Hambatannya nol.
|
|
51
|
+
|
|
52
|
+
### 2. Misi Penyelamatan Warisan
|
|
53
|
+
|
|
54
|
+
Bayangkan mewarisi codebase besar dengan 5.000 komponen dan tanpa terjemahan sama sekali. Memasang sistem berbasis kunci manual pada ini adalah mimpi buruk yang memakan waktu berbulan-bulan. Alat berbasis compiler bertindak sebagai strategi penyelamatan, langsung mengekstrak ribuan string tanpa Anda perlu menyentuh satu file pun secara manual.
|
|
55
|
+
|
|
56
|
+
### 3. Era AI
|
|
57
|
+
|
|
58
|
+
Ini adalah manfaat modern yang tidak boleh kita abaikan. Asisten pengkodean AI (seperti Copilot atau ChatGPT) secara alami menghasilkan JSX/HTML standar. Mereka tidak mengetahui skema kunci terjemahan spesifik Anda.
|
|
59
|
+
|
|
60
|
+
- **Deklaratif:** Anda harus menulis ulang output AI untuk mengganti teks dengan kunci.
|
|
61
|
+
- **Compiler:** Anda cukup menyalin-tempel kode AI, dan itu langsung bekerja.
|
|
62
|
+
|
|
63
|
+
## Pemeriksaan Realitas: Mengapa "Ajaib" Itu Berbahaya
|
|
64
|
+
|
|
65
|
+
Meskipun "ajaib" itu menarik, abstraksi tersebut bisa bocor. Mengandalkan alat build untuk memahami niat manusia memperkenalkan kerentanan arsitektural.
|
|
66
|
+
|
|
67
|
+
### 1. Kerentanan Heuristik (Permainan Tebak-tebakan)
|
|
68
|
+
|
|
69
|
+
Compiler harus menebak mana yang konten dan mana yang kode.
|
|
70
|
+
|
|
71
|
+
- Apakah `className="active"` diterjemahkan? Itu adalah string.
|
|
72
|
+
- Apakah `status="pending"` diterjemahkan?
|
|
73
|
+
- Apakah `<MyComponent errorMessage="An error occurred" />` diterjemahkan?
|
|
74
|
+
- Apakah ID produk seperti `"AX-99"` diterjemahkan?
|
|
75
|
+
|
|
76
|
+
Anda pada akhirnya harus "berjuang" dengan compiler, menambahkan komentar khusus (seperti `// ignore-translation`) untuk mencegahnya merusak logika aplikasi Anda.
|
|
77
|
+
|
|
78
|
+
### 2. Batas Keras Data Dinamis
|
|
79
|
+
|
|
80
|
+
Ekstraksi compiler bergantung pada **analisis statis**. Compiler harus melihat string literal dalam kode Anda untuk menghasilkan ID yang stabil.
|
|
81
|
+
Jika API Anda mengembalikan string kode error seperti `server_error`, Anda tidak bisa menerjemahkannya dengan compiler karena compiler tidak mengetahui string tersebut ada saat build time. Anda terpaksa membangun sistem "runtime-only" sekunder hanya untuk data dinamis.
|
|
82
|
+
|
|
83
|
+
### 3. "Ledakan Chunk" dan Air Terjun Jaringan
|
|
84
|
+
|
|
85
|
+
Untuk memungkinkan tree-shaking, alat compiler sering membagi terjemahan per komponen.
|
|
86
|
+
|
|
87
|
+
- **Konsekuensinya:** Satu tampilan halaman dengan 50 komponen kecil mungkin memicu **50 permintaan HTTP terpisah** untuk fragmen terjemahan kecil. Bahkan dengan HTTP/2, ini menciptakan waterfall jaringan yang membuat aplikasi Anda terasa lambat dibandingkan memuat satu bundel bahasa yang dioptimalkan.
|
|
88
|
+
|
|
89
|
+
### 4. Beban Kinerja Runtime
|
|
90
|
+
|
|
91
|
+
Untuk membuat terjemahan bersifat reaktif (sehingga mereka langsung diperbarui saat Anda mengganti bahasa), compiler sering menyuntikkan hooks manajemen state ke _setiap_ komponen.
|
|
92
|
+
|
|
93
|
+
- **Biayanya:** Jika Anda merender daftar dengan 5.000 item, Anda menginisialisasi 5.000 hook `useState` dan `useEffect` hanya untuk teks. Ini menghabiskan memori dan siklus CPU yang sebenarnya bisa dihemat oleh pustaka deklaratif (yang biasanya menggunakan satu penyedia Context).
|
|
94
|
+
|
|
95
|
+
## Perangkap: Vendor Lock-in
|
|
96
|
+
|
|
97
|
+
Ini mungkin aspek paling berbahaya dari i18n berbasis compiler.
|
|
98
|
+
|
|
99
|
+
Dalam pustaka deklaratif, kode sumber Anda mengandung maksud yang eksplisit. Anda memiliki kunci-kuncinya. Jika Anda mengganti pustaka, Anda hanya perlu mengubah impor.
|
|
100
|
+
|
|
101
|
+
Dalam pendekatan berbasis compiler, **kode sumber Anda hanyalah teks bahasa Inggris.** "Logika terjemahan" hanya ada di dalam konfigurasi plugin build.
|
|
102
|
+
Jika perpustakaan itu berhenti dipelihara, atau jika Anda merasa sudah tidak cocok lagi, Anda akan terjebak. Anda tidak bisa dengan mudah "eject" karena Anda tidak memiliki kunci terjemahan sama sekali di kode sumber Anda. Anda harus menulis ulang seluruh aplikasi secara manual untuk bermigrasi.
|
|
103
|
+
|
|
104
|
+
## Sisi Lain: Risiko dari Pendekatan Deklaratif
|
|
105
|
+
|
|
106
|
+
Untuk adilnya, cara deklaratif tradisional juga tidak sempurna. Ia memiliki serangkaian "jebakan" tersendiri.
|
|
107
|
+
|
|
108
|
+
1. **Namespace Hell:** Anda sering harus mengelola secara manual file JSON mana yang akan dimuat (`common.json`, `dashboard.json`, `footer.json`). Jika Anda lupa satu, pengguna akan melihat kunci mentah.
|
|
109
|
+
2. **Over-fetching:** Tanpa konfigurasi yang hati-hati, sangat mudah secara tidak sengaja memuat _semua_ kunci terjemahan Anda untuk _semua_ halaman pada pemuatan awal, yang membuat ukuran bundle membengkak.
|
|
110
|
+
3. **Sync Drift:** Umum terjadi kunci tetap ada di file JSON jauh setelah komponen yang menggunakannya dihapus. File terjemahan Anda tumbuh tanpa batas, dipenuhi dengan "kunci zombie."
|
|
111
|
+
|
|
112
|
+
## Jalan Tengah Intlayer
|
|
113
|
+
|
|
114
|
+
Di sinilah alat seperti **Intlayer** mencoba berinovasi. Intlayer memahami bahwa meskipun compiler itu kuat, sihir implisit itu berbahaya.
|
|
115
|
+
|
|
116
|
+
Intlayer menawarkan **perintah `transform`** yang unik. Alih-alih hanya melakukan sihir di langkah build tersembunyi, ia sebenarnya dapat **menulis ulang kode komponen Anda**. Ia memindai teks Anda dan menggantinya dengan deklarasi konten eksplisit di dalam codebase Anda.
|
|
117
|
+
|
|
118
|
+
Ini memberi Anda yang terbaik dari kedua dunia:
|
|
119
|
+
|
|
120
|
+
1. **Granularitas:** Anda menjaga terjemahan tetap dekat dengan komponen Anda (meningkatkan modularitas dan tree-shaking).
|
|
121
|
+
2. **Keamanan:** Terjemahan menjadi kode eksplisit, bukan sihir tersembunyi saat build-time.
|
|
122
|
+
3. **Tanpa Lock-in:** Karena kode diubah menjadi struktur deklaratif standar dalam repo Anda, Anda tidak menyembunyikan logika dalam plugin webpack.
|
|
123
|
+
|
|
124
|
+
## Kesimpulan
|
|
125
|
+
|
|
126
|
+
Jadi, mana yang harus Anda pilih?
|
|
127
|
+
|
|
128
|
+
**Jika Anda seorang Junior Developer, Solo Founder, atau sedang membangun MVP:**
|
|
129
|
+
Pendekatan berbasis compiler adalah pilihan yang valid. Ini memungkinkan Anda bergerak sangat cepat. Anda tidak perlu khawatir tentang struktur file atau kunci. Anda hanya membangun. Hutang teknis adalah masalah untuk "Anda di Masa Depan."
|
|
130
|
+
|
|
131
|
+
**Jika Anda membangun Aplikasi Profesional, Tingkat Enterprise:**
|
|
132
|
+
Sihir umumnya adalah ide buruk. Anda membutuhkan kontrol.
|
|
133
|
+
|
|
134
|
+
- Anda perlu menangani data dinamis dari backend.
|
|
135
|
+
- Anda perlu memastikan performa pada perangkat kelas bawah (menghindari ledakan hook).
|
|
136
|
+
- Anda perlu memastikan Anda tidak terkunci pada alat build tertentu selamanya.
|
|
137
|
+
|
|
138
|
+
Untuk aplikasi profesional, **Manajemen Konten Deklaratif** (seperti Intlayer atau pustaka yang sudah mapan) tetap menjadi standar emas. Ini memisahkan kekhawatiran Anda, menjaga arsitektur Anda tetap bersih, dan memastikan kemampuan aplikasi Anda untuk berbicara dalam berbagai bahasa tidak bergantung pada compiler "kotak hitam" yang menebak niat Anda.
|
|
@@ -176,7 +176,6 @@ Kecualikan file yang dihasilkan dari kontrol versi:
|
|
|
176
176
|
```plaintext fileName=".gitignore"
|
|
177
177
|
# Abaikan file yang dihasilkan oleh Intlayer
|
|
178
178
|
.intlayer
|
|
179
|
-
intl
|
|
180
179
|
```
|
|
181
180
|
|
|
182
181
|
File-file ini secara otomatis dihasilkan ulang selama proses build dan tidak perlu dikomit ke repositori Anda.
|
|
@@ -166,7 +166,6 @@ Kecualikan file yang dihasilkan dari kontrol versi:
|
|
|
166
166
|
```plaintext fileName=".gitignore"
|
|
167
167
|
# Abaikan file yang dihasilkan oleh Intlayer
|
|
168
168
|
.intlayer
|
|
169
|
-
intl
|
|
170
169
|
```
|
|
171
170
|
|
|
172
171
|
File-file ini secara otomatis dibuat ulang selama proses build dan tidak perlu dikomit ke repositori Anda.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-11-24
|
|
3
|
+
updatedAt: 2025-11-24
|
|
4
|
+
title: Compilatore vs. i18n Dichiarativo
|
|
5
|
+
description: Esplorazione dei compromessi architetturali tra l'internazionalizzazione "magica" basata su compilatore e la gestione esplicita e dichiarativa dei contenuti.
|
|
6
|
+
keywords:
|
|
7
|
+
- Intlayer
|
|
8
|
+
- Internazionalizzazione
|
|
9
|
+
- Blog
|
|
10
|
+
- Next.js
|
|
11
|
+
- JavaScript
|
|
12
|
+
- React
|
|
13
|
+
- i18n
|
|
14
|
+
- Compilatore
|
|
15
|
+
- Dichiarativo
|
|
16
|
+
slugs:
|
|
17
|
+
- compiler-vs-declarative-i18n
|
|
18
|
+
- blog
|
|
19
|
+
- i18n
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Argomenti a favore e contro l'i18n basata su compilatore
|
|
23
|
+
|
|
24
|
+
Se sviluppi applicazioni web da più di un decennio, sai che l'Internazionalizzazione (i18n) è sempre stata un punto critico. Spesso è il compito che nessuno vuole fare: estrarre stringhe, gestire file JSON e preoccuparsi delle regole di pluralizzazione.
|
|
25
|
+
|
|
26
|
+
Recentemente, è emersa una nuova ondata di strumenti i18n "basati su compilatore", promettendo di far sparire questo fastidio. Il messaggio è seducente: **Basta scrivere il testo nei tuoi componenti e lasciare che lo strumento di build gestisca il resto.** Niente chiavi, niente importazioni, solo magia.
|
|
27
|
+
|
|
28
|
+
Ma come per tutte le astrazioni nell'ingegneria del software, la magia ha un prezzo.
|
|
29
|
+
|
|
30
|
+
In questo post del blog, esploreremo il passaggio dalle librerie dichiarative agli approcci basati su compilatore, i debiti architetturali nascosti che introducono e perché il modo "noioso" potrebbe ancora essere il migliore per applicazioni professionali.
|
|
31
|
+
|
|
32
|
+
## Una breve storia della traduzione
|
|
33
|
+
|
|
34
|
+
Per capire dove siamo, dobbiamo guardare indietro a dove siamo partiti.
|
|
35
|
+
|
|
36
|
+
Intorno al 2011–2012, il panorama JavaScript era molto diverso. I bundler come li conosciamo oggi (Webpack, Vite) non esistevano o erano alle prime armi. Incollavamo gli script direttamente nel browser. In quell'epoca nacquero librerie come **i18next**.
|
|
37
|
+
|
|
38
|
+
Risolvevano il problema nel modo unico possibile all'epoca: **Dizionari a runtime**. Caricavi un enorme oggetto JSON in memoria, e una funzione cercava le chiavi al volo. Era affidabile, esplicito e funzionava ovunque.
|
|
39
|
+
|
|
40
|
+
Avanzando fino a oggi, abbiamo potenti compilatori (SWC, bundler basati su Rust) che possono analizzare Abstract Syntax Trees (AST) in millisecondi. Questa potenza ha dato vita a una nuova idea: _Perché gestiamo manualmente le chiavi? Perché il compilatore non può semplicemente vedere il testo "Hello World" e sostituirlo per noi?_
|
|
41
|
+
|
|
42
|
+
Così è nato l'i18n basato su compilatore.
|
|
43
|
+
|
|
44
|
+
## Il Fascino del Compilatore (L'Approccio "Magico")
|
|
45
|
+
|
|
46
|
+
C'è un motivo per cui questo nuovo approccio è di tendenza. Per uno sviluppatore, l'esperienza è incredibile.
|
|
47
|
+
|
|
48
|
+
### 1. Velocità e "Flow"
|
|
49
|
+
|
|
50
|
+
Quando sei nel flusso, fermarti a pensare a un nome di variabile (`home_hero_title_v2`) interrompe il tuo flusso. Con un approccio basato sul compilatore, digiti `<p>Welcome back</p>` e continui. L'attrito è zero.
|
|
51
|
+
|
|
52
|
+
### 2. La Missione di Salvataggio del Legacy
|
|
53
|
+
|
|
54
|
+
Immagina di ereditare una codebase enorme con 5.000 componenti e zero traduzioni. Retrofitare questo con un sistema manuale basato su chiavi è un incubo che dura mesi. Uno strumento basato su compilatore agisce come una strategia di salvataggio, estraendo istantaneamente migliaia di stringhe senza che tu debba toccare manualmente un singolo file.
|
|
55
|
+
|
|
56
|
+
### 3. L'Era dell'AI
|
|
57
|
+
|
|
58
|
+
Questo è un vantaggio moderno che non dovremmo trascurare. Gli assistenti di codifica AI (come Copilot o ChatGPT) generano naturalmente JSX/HTML standard. Non conoscono il tuo schema specifico di chiavi di traduzione.
|
|
59
|
+
|
|
60
|
+
- **Dichiarativo:** Devi riscrivere l'output dell'AI per sostituire il testo con le chiavi.
|
|
61
|
+
- **Compilatore:** Copi e incolli il codice dell'AI, e funziona semplicemente.
|
|
62
|
+
|
|
63
|
+
## Il Controllo della Realtà: Perché la "Magia" è Pericolosa
|
|
64
|
+
|
|
65
|
+
Sebbene la "magia" sia attraente, l'astrazione perde colpi. Affidarsi a uno strumento di build per comprendere l'intento umano introduce fragilità architetturali.
|
|
66
|
+
|
|
67
|
+
### 1. Fragilità Euristica (Il Gioco delle Ipotesi)
|
|
68
|
+
|
|
69
|
+
Il compilatore deve indovinare cosa è contenuto e cosa è codice.
|
|
70
|
+
|
|
71
|
+
- `className="active"` viene tradotto? È una stringa.
|
|
72
|
+
- `status="pending"` viene tradotto?
|
|
73
|
+
- `<MyComponent errorMessage="An error occurred" />` viene tradotto?
|
|
74
|
+
- Un ID prodotto come `"AX-99"` viene tradotto?
|
|
75
|
+
|
|
76
|
+
Inevitabilmente finisci per "combattere" con il compilatore, aggiungendo commenti specifici (come `// ignore-translation`) per evitare che rompa la logica della tua applicazione.
|
|
77
|
+
|
|
78
|
+
### 2. Il Limite Rigido dei Dati Dinamici
|
|
79
|
+
|
|
80
|
+
L'estrazione del compilatore si basa sull'**analisi statica**. Deve vedere la stringa letterale nel tuo codice per generare un ID stabile.
|
|
81
|
+
Se la tua API restituisce una stringa di codice errore come `server_error`, non puoi tradurla con un compilatore perché il compilatore non conosce quella stringa al momento della build. Sei costretto a costruire un sistema secondario "solo a runtime" solo per i dati dinamici.
|
|
82
|
+
|
|
83
|
+
### 3. "Esplosione di Chunk" e Cascate di Rete
|
|
84
|
+
|
|
85
|
+
Per consentire il tree-shaking, gli strumenti del compilatore spesso suddividono le traduzioni per componente.
|
|
86
|
+
|
|
87
|
+
- **La conseguenza:** Una singola visualizzazione di pagina con 50 piccoli componenti potrebbe generare **50 richieste HTTP separate** per minuscoli frammenti di traduzione. Anche con HTTP/2, questo crea un effetto "network waterfall" che rende la tua applicazione lenta rispetto al caricamento di un singolo bundle linguistico ottimizzato.
|
|
88
|
+
|
|
89
|
+
### 4. Sovraccarico delle Prestazioni a Runtime
|
|
90
|
+
|
|
91
|
+
Per rendere le traduzioni reattive (in modo che si aggiornino istantaneamente quando cambi lingua), il compilatore spesso inietta hook di gestione dello stato in _ogni_ componente.
|
|
92
|
+
|
|
93
|
+
- **Il costo:** Se renderizzi una lista di 5.000 elementi, stai inizializzando 5.000 hook `useState` e `useEffect` solo per il testo. Questo consuma memoria e cicli CPU che le librerie dichiarative (che tipicamente usano un singolo provider Context) risparmiano.
|
|
94
|
+
|
|
95
|
+
## La trappola: Vendor Lock-in
|
|
96
|
+
|
|
97
|
+
Questo è probabilmente l'aspetto più pericoloso dell'i18n basato su compilatori.
|
|
98
|
+
|
|
99
|
+
In una libreria dichiarativa, il tuo codice sorgente contiene un intento esplicito. Possiedi le chiavi. Se cambi libreria, devi solo modificare l'import.
|
|
100
|
+
|
|
101
|
+
In un approccio basato su compilatori, **il tuo codice sorgente è solo testo in inglese.** La "logica di traduzione" esiste solo all'interno della configurazione del plugin di build.
|
|
102
|
+
Se quella libreria smette di essere mantenuta, o se la superi, rimani bloccato. Non puoi "espellere" facilmente perché non hai chiavi di traduzione nel tuo codice sorgente. Dovresti riscrivere manualmente l'intera applicazione per migrare.
|
|
103
|
+
|
|
104
|
+
## L'altro lato: rischi dell'approccio dichiarativo
|
|
105
|
+
|
|
106
|
+
Per essere onesti, il modo dichiarativo tradizionale non è perfetto nemmeno. Ha i suoi "tranelli".
|
|
107
|
+
|
|
108
|
+
1. **Inferno dei namespace:** Spesso devi gestire manualmente quali file JSON caricare (`common.json`, `dashboard.json`, `footer.json`). Se ne dimentichi uno, l'utente vede le chiavi raw.
|
|
109
|
+
2. **Over-fetching:** Senza una configurazione attenta, è molto facile caricare accidentalmente _tutte_ le tue chiavi di traduzione per _tutte_ le pagine al caricamento iniziale, gonfiando la dimensione del bundle.
|
|
110
|
+
3. **Deriva di sincronizzazione:** È comune che le chiavi rimangano nel file JSON molto tempo dopo che il componente che le utilizzava è stato eliminato. I tuoi file di traduzione crescono indefinitamente, pieni di "chiavi zombie".
|
|
111
|
+
|
|
112
|
+
## La via di mezzo di Intlayer
|
|
113
|
+
|
|
114
|
+
È qui che strumenti come **Intlayer** cercano di innovare. Intlayer comprende che, sebbene i compilatori siano potenti, la magia implicita è pericolosa.
|
|
115
|
+
|
|
116
|
+
Intlayer offre un comando unico **`transform`**. Invece di fare solo magia nel passaggio di build nascosto, può effettivamente **riscrivere il codice del tuo componente**. Scansiona il tuo testo e lo sostituisce con dichiarazioni di contenuto esplicite nel tuo codebase.
|
|
117
|
+
|
|
118
|
+
Questo ti offre il meglio di entrambi i mondi:
|
|
119
|
+
|
|
120
|
+
1. **Granularità:** Mantieni le tue traduzioni vicine ai tuoi componenti (migliorando modularità e tree-shaking).
|
|
121
|
+
2. **Sicurezza:** La traduzione diventa codice esplicito, non una magia nascosta al momento della build.
|
|
122
|
+
3. **Nessun Lock-in:** Poiché il codice viene trasformato in una struttura dichiarativa standard all'interno del tuo repository, non stai nascondendo la logica in un plugin di webpack.
|
|
123
|
+
|
|
124
|
+
## Conclusione
|
|
125
|
+
|
|
126
|
+
Quindi, quale dovresti scegliere?
|
|
127
|
+
|
|
128
|
+
**Se sei uno Sviluppatore Junior, un Fondatore Solitario o stai costruendo un MVP:**
|
|
129
|
+
L'approccio basato sul compilatore è una scelta valida. Ti permette di muoverti incredibilmente velocemente. Non devi preoccuparti delle strutture dei file o delle chiavi. Devi solo costruire. Il debito tecnico è un problema per il "Te Futuro".
|
|
130
|
+
|
|
131
|
+
**Se stai costruendo un'Applicazione Professionale di livello Enterprise:**
|
|
132
|
+
La magia è generalmente una cattiva idea. Hai bisogno di controllo.
|
|
133
|
+
|
|
134
|
+
- Devi gestire dati dinamici provenienti dai backend.
|
|
135
|
+
- Devi garantire le prestazioni su dispositivi di fascia bassa (evitando esplosioni di hook).
|
|
136
|
+
- Devi assicurarti di non rimanere vincolato per sempre a uno specifico strumento di build.
|
|
137
|
+
|
|
138
|
+
Per le applicazioni professionali, la **Gestione Contenuti Dichiarativa** (come Intlayer o librerie consolidate) rimane lo standard d'eccellenza. Essa separa le tue preoccupazioni, mantiene pulita l'architettura e garantisce che la capacità della tua applicazione di supportare più lingue non dipenda da un compilatore "scatola nera" che indovina le tue intenzioni.
|
|
@@ -176,7 +176,6 @@ Escludi i file generati dal controllo di versione:
|
|
|
176
176
|
```plaintext fileName=".gitignore"
|
|
177
177
|
# Ignora i file generati da Intlayer
|
|
178
178
|
.intlayer
|
|
179
|
-
intl
|
|
180
179
|
```
|
|
181
180
|
|
|
182
181
|
Questi file vengono rigenerati automaticamente durante il processo di build e non devono essere aggiunti al tuo repository.
|
|
@@ -166,7 +166,6 @@ Escludi i file generati dal controllo di versione:
|
|
|
166
166
|
```plaintext fileName=".gitignore"
|
|
167
167
|
# Ignora i file generati da Intlayer
|
|
168
168
|
.intlayer
|
|
169
|
-
intl
|
|
170
169
|
```
|
|
171
170
|
|
|
172
171
|
Questi file vengono rigenerati automaticamente durante il processo di build e non devono essere aggiunti al tuo repository.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-11-24
|
|
3
|
+
updatedAt: 2025-11-24
|
|
4
|
+
title: コンパイラー型 vs 宣言型 i18n
|
|
5
|
+
description: 「マジック」なコンパイラー型国際化と明示的な宣言型コンテンツ管理のアーキテクチャ上のトレードオフを探る。
|
|
6
|
+
keywords:
|
|
7
|
+
- Intlayer
|
|
8
|
+
- 国際化
|
|
9
|
+
- ブログ
|
|
10
|
+
- Next.js
|
|
11
|
+
- JavaScript
|
|
12
|
+
- React
|
|
13
|
+
- i18n
|
|
14
|
+
- コンパイラー
|
|
15
|
+
- 宣言型
|
|
16
|
+
slugs:
|
|
17
|
+
- compiler-vs-declarative-i18n
|
|
18
|
+
- blog
|
|
19
|
+
- i18n
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# コンパイラー型i18nの賛否
|
|
23
|
+
|
|
24
|
+
もし10年以上ウェブアプリケーションを開発してきたなら、国際化(i18n)が常に摩擦点であったことをご存知でしょう。文字列の抽出、JSONファイルの管理、複数形ルールの扱いなど、誰もやりたがらない作業であることが多いのです。
|
|
25
|
+
|
|
26
|
+
最近、「コンパイラー型」i18nツールの新しい波が登場し、この苦痛を解消すると約束しています。魅力的な提案はこうです:**コンポーネント内にテキストを書くだけで、ビルドツールが残りを処理してくれる。** キーもインポートも不要、ただのマジックです。
|
|
27
|
+
|
|
28
|
+
しかし、ソフトウェア工学におけるすべての抽象化と同様に、マジックには代償が伴います。
|
|
29
|
+
|
|
30
|
+
このブログ記事では、宣言型ライブラリからコンパイラー型アプローチへの移行、彼らがもたらす隠れたアーキテクチャ的負債、そしてなぜ「退屈な」方法がプロフェッショナルなアプリケーションにとって依然として最良の方法であるかを探ります。
|
|
31
|
+
|
|
32
|
+
## 翻訳の簡単な歴史
|
|
33
|
+
|
|
34
|
+
今の状況を理解するためには、出発点を振り返る必要があります。
|
|
35
|
+
|
|
36
|
+
2011年から2012年頃、JavaScriptの状況は大きく異なっていました。現在私たちが知っているようなバンドラー(WebpackやVite)は存在しなかったか、まだ初期段階にありました。ブラウザ上でスクリプトをつなぎ合わせていた時代です。この時代に、**i18next**のようなライブラリが誕生しました。
|
|
37
|
+
|
|
38
|
+
彼らは当時可能な唯一の方法で問題を解決しました:**ランタイム辞書**です。巨大なJSONオブジェクトをメモリに読み込み、関数がその場でキーを検索する仕組みでした。これは信頼性が高く、明示的で、どこでも動作しました。
|
|
39
|
+
|
|
40
|
+
そして現在に至ります。私たちはミリ秒単位で抽象構文木(AST)を解析できる強力なコンパイラ(SWCやRustベースのバンドラー)を持っています。この力が新しいアイデアを生み出しました:_なぜ私たちは手動でキーを管理しているのか?なぜコンパイラが「Hello World」というテキストを見て、それを置き換えてくれないのか?_
|
|
41
|
+
|
|
42
|
+
こうして、コンパイラベースのi18nが誕生しました。
|
|
43
|
+
|
|
44
|
+
## コンパイラの魅力(「マジック」アプローチ)
|
|
45
|
+
|
|
46
|
+
この新しいアプローチがトレンドになっている理由があります。開発者にとって、その体験は驚くべきものです。
|
|
47
|
+
|
|
48
|
+
### 1. スピードと「フロー」
|
|
49
|
+
|
|
50
|
+
集中しているときに、変数名(`home_hero_title_v2`)を考えるために立ち止まると、フローが途切れてしまいます。コンパイラアプローチでは、`<p>Welcome back</p>` とタイプしてそのまま進めます。摩擦はゼロです。
|
|
51
|
+
|
|
52
|
+
### 2. レガシー救出ミッション
|
|
53
|
+
|
|
54
|
+
5,000のコンポーネントがある巨大なコードベースを引き継ぎ、翻訳が一切ないと想像してください。手動のキー管理システムでこれを後付けするのは数ヶ月に及ぶ悪夢です。コンパイラベースのツールは救出戦略として機能し、手動でファイルに触れることなく数千の文字列を瞬時に抽出します。
|
|
55
|
+
|
|
56
|
+
### 3. AI時代
|
|
57
|
+
|
|
58
|
+
これは見逃せない現代的な利点です。AIコーディングアシスタント(CopilotやChatGPTのようなもの)は、標準的なJSX/HTMLを自然に生成します。彼らはあなたの特定の翻訳キーのスキーマを知りません。
|
|
59
|
+
|
|
60
|
+
- **宣言的(Declarative):** AIの出力をテキストからキーに置き換えるために書き直す必要があります。
|
|
61
|
+
- **コンパイラ(Compiler):** AIのコードをコピー&ペーストするだけで、そのまま動作します。
|
|
62
|
+
|
|
63
|
+
## 現実の確認:なぜ「マジック」は危険なのか
|
|
64
|
+
|
|
65
|
+
「マジック」は魅力的ですが、その抽象化は漏れが生じます。ビルドツールに人間の意図を理解させることに依存すると、アーキテクチャの脆弱性が生まれます。
|
|
66
|
+
|
|
67
|
+
### 1. ヒューリスティックの脆弱性(推測ゲーム)
|
|
68
|
+
|
|
69
|
+
コンパイラは何がコンテンツで何がコードかを推測しなければなりません。
|
|
70
|
+
|
|
71
|
+
- `className="active"` は翻訳されますか?これは文字列です。
|
|
72
|
+
- `status="pending"` は翻訳されますか?
|
|
73
|
+
- `<MyComponent errorMessage="An error occurred" />` は翻訳されますか?
|
|
74
|
+
- `"AX-99"` のような製品IDは翻訳されますか?
|
|
75
|
+
|
|
76
|
+
最終的には、コンパイラと「戦う」ことになり、アプリケーションのロジックを壊さないように特定のコメント(例:`// ignore-translation`)を追加することになります。
|
|
77
|
+
|
|
78
|
+
### 2. 動的データのハードリミット
|
|
79
|
+
|
|
80
|
+
コンパイラの抽出は**静的解析**に依存しています。安定したIDを生成するためには、コード内にリテラル文字列が存在している必要があります。
|
|
81
|
+
もしAPIが `server_error` のようなエラーコード文字列を返す場合、コンパイラはビルド時にその文字列の存在を認識できないため、翻訳できません。動的データ用に「ランタイム専用」の二次的なシステムを構築せざるを得ません。
|
|
82
|
+
|
|
83
|
+
### 3. 「チャンク爆発」とネットワークウォーターフォール
|
|
84
|
+
|
|
85
|
+
ツリーシェイキングを可能にするために、コンパイラツールはしばしばコンポーネントごとに翻訳を分割します。
|
|
86
|
+
|
|
87
|
+
- **結果:** 50個の小さなコンポーネントがある単一のページビューで、**50回の別々のHTTPリクエスト**が小さな翻訳断片に対して発生する可能性があります。HTTP/2を使用していても、これはネットワークのウォーターフォールを生み出し、単一の最適化された言語バンドルを読み込む場合と比べて、アプリケーションの動作が遅く感じられます。
|
|
88
|
+
|
|
89
|
+
### 4. ランタイムのパフォーマンスオーバーヘッド
|
|
90
|
+
|
|
91
|
+
翻訳をリアクティブに(言語を切り替えたときに即座に更新されるように)するために、コンパイラはしばしば*すべての*コンポーネントに状態管理フックを注入します。
|
|
92
|
+
|
|
93
|
+
- **コスト:** もし5,000件のアイテムのリストをレンダリングすると、テキストのためだけに5,000個の `useState` と `useEffect` フックを初期化することになります。これは、宣言的ライブラリ(通常は単一のContextプロバイダーを使用)が節約するメモリとCPUサイクルを消費します。
|
|
94
|
+
|
|
95
|
+
## トラップ:ベンダーロックイン
|
|
96
|
+
|
|
97
|
+
これはおそらく、コンパイラベースのi18nで最も危険な側面です。
|
|
98
|
+
|
|
99
|
+
宣言的ライブラリでは、ソースコードに明確な意図が含まれています。キーはあなたが所有しています。ライブラリを切り替える場合は、インポートを変更するだけです。
|
|
100
|
+
|
|
101
|
+
コンパイラベースのアプローチでは、**ソースコードは単なる英語のテキストです。** 「翻訳ロジック」はビルドプラグインの設定内にのみ存在します。
|
|
102
|
+
もしそのライブラリのメンテナンスが停止したり、ライブラリの機能を超えてしまった場合、あなたは行き詰まります。ソースコードに翻訳キーが一切存在しないため、「イジェクト」することは簡単ではありません。移行するには、アプリケーション全体を手動で書き直す必要があります。
|
|
103
|
+
|
|
104
|
+
## もう一方の側面:宣言的アプローチのリスク
|
|
105
|
+
|
|
106
|
+
公平を期すために言うと、従来の宣言的な方法も完璧ではありません。独自の「落とし穴」が存在します。
|
|
107
|
+
|
|
108
|
+
1. **ネームスペース地獄:** どのJSONファイルを読み込むか(`common.json`、`dashboard.json`、`footer.json`など)を手動で管理する必要がよくあります。もし一つでも忘れると、ユーザーは生のキーを目にすることになります。
|
|
109
|
+
2. **過剰フェッチ:** 注意深く設定しないと、初回ロード時にすべてのページのすべての翻訳キーを誤って読み込んでしまい、バンドルサイズが膨れ上がることが非常に簡単に起こります。
|
|
110
|
+
3. **同期のズレ(Sync Drift):** コンポーネントが削除された後も、そのコンポーネントで使われていたキーがJSONファイルに残り続けることがよくあります。翻訳ファイルは無限に増え続け、「ゾンビキー」で溢れてしまいます。
|
|
111
|
+
|
|
112
|
+
## Intlayerの中間的アプローチ
|
|
113
|
+
|
|
114
|
+
ここで、**Intlayer**のようなツールが革新を試みています。Intlayerは、コンパイラが強力である一方で、暗黙のマジックは危険であることを理解しています。
|
|
115
|
+
|
|
116
|
+
Intlayerは独自の**`transform`コマンド**を提供します。隠れたビルドステップで単にマジックを行うのではなく、実際に**コンポーネントのコードを書き換える**ことができます。テキストをスキャンし、コードベース内で明示的なコンテンツ宣言に置き換えます。
|
|
117
|
+
|
|
118
|
+
これにより、両方の利点を得られます:
|
|
119
|
+
|
|
120
|
+
1. **粒度(Granularity):** 翻訳をコンポーネントの近くに保持できるため(モジュール性とツリーシェイキングが向上します)。
|
|
121
|
+
2. **安全性:** 翻訳は隠れたビルド時のマジックではなく、明示的なコードになります。
|
|
122
|
+
3. **ロックインなし:** コードがリポジトリ内で標準的な宣言的構造に変換されるため、webpackプラグイン内にロジックを隠すことはありません。
|
|
123
|
+
|
|
124
|
+
## 結論
|
|
125
|
+
|
|
126
|
+
では、どちらを選ぶべきでしょうか?
|
|
127
|
+
|
|
128
|
+
**もしあなたがジュニア開発者、ソロ創業者、またはMVPを構築している場合:**
|
|
129
|
+
コンパイラベースのアプローチは有効な選択肢です。非常に速く開発を進めることができます。ファイル構造やキーについて心配する必要はありません。ただビルドすれば良いのです。技術的負債は「未来のあなた」の問題です。
|
|
130
|
+
|
|
131
|
+
**もしあなたがプロフェッショナルなエンタープライズグレードのアプリケーションを構築している場合:**
|
|
132
|
+
マジックは一般的に悪い考えです。コントロールが必要です。
|
|
133
|
+
|
|
134
|
+
- バックエンドからの動的データを扱う必要があります。
|
|
135
|
+
- 低スペックデバイスでのパフォーマンスを確保する必要があります(フックの爆発を避けるため)。
|
|
136
|
+
- 特定のビルドツールに永遠にロックインされないようにする必要があります。
|
|
137
|
+
|
|
138
|
+
プロフェッショナルなアプリケーションの場合、**宣言的コンテンツ管理**(Intlayerや確立されたライブラリのようなもの)が依然としてゴールドスタンダードです。これにより関心事が分離され、アーキテクチャがクリーンに保たれ、アプリケーションが複数言語を扱う能力が「ブラックボックス」コンパイラの推測に依存しないことが保証されます。
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-11-24
|
|
3
|
+
updatedAt: 2025-11-24
|
|
4
|
+
title: 컴파일러 기반 i18n 대 선언적 i18n
|
|
5
|
+
description: "매직" 컴파일러 기반 국제화와 명시적 선언적 콘텐츠 관리 간의 아키텍처적 트레이드오프 탐구.
|
|
6
|
+
keywords:
|
|
7
|
+
- Intlayer
|
|
8
|
+
- 국제화
|
|
9
|
+
- 블로그
|
|
10
|
+
- Next.js
|
|
11
|
+
- JavaScript
|
|
12
|
+
- React
|
|
13
|
+
- i18n
|
|
14
|
+
- 컴파일러
|
|
15
|
+
- 선언적
|
|
16
|
+
slugs:
|
|
17
|
+
- compiler-vs-declarative-i18n
|
|
18
|
+
- blog
|
|
19
|
+
- i18n
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# 컴파일러 기반 i18n에 대한 찬반 논쟁
|
|
23
|
+
|
|
24
|
+
10년 이상 웹 애플리케이션을 개발해왔다면, 국제화(i18n)가 항상 마찰 지점이었음을 알 것입니다. 문자열 추출, JSON 파일 관리, 복수형 규칙 처리 등 아무도 하고 싶어 하지 않는 작업인 경우가 많습니다.
|
|
25
|
+
|
|
26
|
+
최근에 "컴파일러 기반" i18n 도구의 새로운 물결이 등장하여 이 고통을 사라지게 하겠다고 약속하고 있습니다. 그 제안은 매력적입니다: **컴포넌트에 텍스트만 작성하면 빌드 도구가 나머지를 처리해줍니다.** 키도, 임포트도 없이, 그저 마법처럼요.
|
|
27
|
+
|
|
28
|
+
하지만 소프트웨어 공학의 모든 추상화가 그렇듯, 마법에는 대가가 따릅니다.
|
|
29
|
+
|
|
30
|
+
이 블로그 글에서는 선언적 라이브러리에서 컴파일러 기반 접근법으로의 전환, 그들이 도입하는 숨겨진 아키텍처 부채, 그리고 왜 "지루한" 방식이 여전히 전문 애플리케이션에 가장 좋은 방법일 수 있는지 탐구할 것입니다.
|
|
31
|
+
|
|
32
|
+
## 번역의 간략한 역사
|
|
33
|
+
|
|
34
|
+
우리가 현재 어디에 있는지 이해하려면, 우리가 어디서 시작했는지 돌아봐야 합니다.
|
|
35
|
+
|
|
36
|
+
2011년에서 2012년경, JavaScript 환경은 지금과 매우 달랐습니다. 우리가 알고 있는 번들러들(Webpack, Vite)은 존재하지 않았거나 초기 단계에 불과했습니다. 우리는 브라우저에서 스크립트를 붙여서 사용하고 있었습니다. 이 시기에 **i18next**와 같은 라이브러리가 탄생했습니다.
|
|
37
|
+
|
|
38
|
+
이들은 당시 가능한 유일한 방법으로 문제를 해결했습니다: **런타임 사전(Runtime Dictionaries)**. 거대한 JSON 객체를 메모리에 로드하고, 함수가 실행 중에 키를 찾아내는 방식이었습니다. 이는 신뢰할 수 있고 명확하며 어디서나 작동했습니다.
|
|
39
|
+
|
|
40
|
+
오늘날로 빠르게 넘어가 보면, 우리는 밀리초 단위로 추상 구문 트리(AST)를 파싱할 수 있는 강력한 컴파일러들(SWC, Rust 기반 번들러)을 갖추고 있습니다. 이 강력한 기술은 새로운 아이디어를 탄생시켰습니다: _왜 우리가 수동으로 키를 관리해야 할까? 컴파일러가 "Hello World"라는 텍스트를 보고 바로 교체해주면 안 될까?_
|
|
41
|
+
|
|
42
|
+
이렇게 해서 컴파일러 기반 i18n이 탄생했습니다.
|
|
43
|
+
|
|
44
|
+
## 컴파일러의 매력 (일명 "마법" 접근법)
|
|
45
|
+
|
|
46
|
+
이 새로운 접근법이 유행하는 데는 이유가 있습니다. 개발자 입장에서 경험이 놀랍도록 좋기 때문입니다.
|
|
47
|
+
|
|
48
|
+
### 1. 속도와 "흐름"
|
|
49
|
+
|
|
50
|
+
작업에 몰입해 있을 때 변수 이름(`home_hero_title_v2`)을 생각하느라 멈추면 흐름이 끊깁니다. 컴파일러 접근법에서는 `<p>Welcome back</p>`를 입력하고 계속 진행할 수 있습니다. 마찰이 전혀 없습니다.
|
|
51
|
+
|
|
52
|
+
### 2. 레거시 구조 구출 작전
|
|
53
|
+
|
|
54
|
+
5,000개의 컴포넌트가 있지만 번역이 전혀 없는 거대한 코드베이스를 상속받았다고 상상해 보세요. 수동 키 기반 시스템으로 이를 개조하는 것은 몇 달이 걸리는 악몽 같은 작업입니다. 컴파일러 기반 도구는 구출 전략으로 작동하여, 단 한 파일도 수동으로 건드리지 않고 수천 개의 문자열을 즉시 추출합니다.
|
|
55
|
+
|
|
56
|
+
### 3. AI 시대
|
|
57
|
+
|
|
58
|
+
이것은 우리가 간과해서는 안 될 현대적인 이점입니다. AI 코딩 어시스턴트(예: Copilot 또는 ChatGPT)는 자연스럽게 표준 JSX/HTML을 생성합니다. 이들은 여러분의 특정 번역 키 스키마를 알지 못합니다.
|
|
59
|
+
|
|
60
|
+
- **선언적 방식(Declarative):** AI의 출력을 텍스트에서 키로 교체하기 위해 다시 작성해야 합니다.
|
|
61
|
+
- **컴파일러 방식(Compiler):** AI의 코드를 복사-붙여넣기만 하면 바로 작동합니다.
|
|
62
|
+
|
|
63
|
+
## 현실 점검: 왜 "마법"이 위험한가
|
|
64
|
+
|
|
65
|
+
"마법"은 매력적이지만, 추상화가 새어나갑니다. 빌드 도구가 인간의 의도를 이해하도록 의존하는 것은 아키텍처적 취약성을 초래합니다.
|
|
66
|
+
|
|
67
|
+
### 1. 휴리스틱 취약성 (추측 게임)
|
|
68
|
+
|
|
69
|
+
컴파일러는 무엇이 콘텐츠이고 무엇이 코드인지 추측해야 합니다.
|
|
70
|
+
|
|
71
|
+
- `className="active"`는 번역되나요? 이것은 문자열입니다.
|
|
72
|
+
- `status="pending"`는 번역되나요?
|
|
73
|
+
- `<MyComponent errorMessage="An error occurred" />`가 번역되나요?
|
|
74
|
+
- `"AX-99"`와 같은 제품 ID가 번역되나요?
|
|
75
|
+
|
|
76
|
+
결국 컴파일러와 "싸우게" 되며, 애플리케이션 로직이 깨지지 않도록 특정 주석(예: `// ignore-translation`)을 추가하게 됩니다.
|
|
77
|
+
|
|
78
|
+
### 2. 동적 데이터의 한계
|
|
79
|
+
|
|
80
|
+
컴파일러 추출은 **정적 분석**에 의존합니다. 안정적인 ID를 생성하려면 코드 내에 리터럴 문자열이 보여야 합니다.
|
|
81
|
+
API가 `server_error`와 같은 에러 코드 문자열을 반환하면, 컴파일러가 빌드 시점에 해당 문자열이 존재하는지 알지 못하기 때문에 번역할 수 없습니다. 동적 데이터 전용의 별도 "런타임 전용" 시스템을 구축해야만 합니다.
|
|
82
|
+
|
|
83
|
+
### 3. "청크 폭발"과 네트워크 워터폴
|
|
84
|
+
|
|
85
|
+
트리 쉐이킹을 허용하기 위해, 컴파일러 도구는 종종 컴포넌트별로 번역을 분할합니다.
|
|
86
|
+
|
|
87
|
+
- **결과:** 50개의 작은 컴포넌트가 있는 단일 페이지 뷰는 작은 번역 조각에 대해 **50개의 별도 HTTP 요청**을 발생시킬 수 있습니다. HTTP/2를 사용하더라도, 이는 네트워크 워터폴을 생성하여 단일 최적화된 언어 번들을 로드하는 것보다 애플리케이션이 느리게 느껴지게 만듭니다.
|
|
88
|
+
|
|
89
|
+
### 4. 런타임 성능 오버헤드
|
|
90
|
+
|
|
91
|
+
번역을 반응형으로 만들어(언어를 전환할 때 즉시 업데이트되도록) 컴파일러는 종종 _모든_ 컴포넌트에 상태 관리 훅을 주입합니다.
|
|
92
|
+
|
|
93
|
+
- **비용:** 5,000개의 아이템 리스트를 렌더링하면, 텍스트를 위해 5,000개의 `useState`와 `useEffect` 훅을 초기화하게 됩니다. 이는 선언형 라이브러리(일반적으로 단일 Context 프로바이더를 사용하는)가 절약하는 메모리와 CPU 사이클을 낭비하는 셈입니다.
|
|
94
|
+
|
|
95
|
+
## 함정: 공급업체 종속성 (Vendor Lock-in)
|
|
96
|
+
|
|
97
|
+
이는 컴파일러 기반 i18n에서 가장 위험한 측면이라고 할 수 있습니다.
|
|
98
|
+
|
|
99
|
+
선언형 라이브러리에서는 소스 코드에 명확한 의도가 포함되어 있습니다. 키를 직접 소유합니다. 라이브러리를 변경할 때는 단순히 import만 바꾸면 됩니다.
|
|
100
|
+
|
|
101
|
+
컴파일러 기반 접근법에서는 **소스 코드가 단지 영어 텍스트일 뿐입니다.** "번역 로직"은 빌드 플러그인의 설정 안에만 존재합니다.
|
|
102
|
+
만약 그 라이브러리가 더 이상 유지되지 않거나, 사용자가 그 라이브러리를 벗어나고 싶어도, 당신은 꼼짝할 수 없습니다. 소스 코드에 번역 키가 전혀 없기 때문에 쉽게 "eject"할 수 없습니다. 마이그레이션을 위해 애플리케이션 전체를 수동으로 다시 작성해야 할 것입니다.
|
|
103
|
+
|
|
104
|
+
## 다른 측면: 선언적 접근 방식의 위험
|
|
105
|
+
|
|
106
|
+
공정하게 말하면, 전통적인 선언적 방식도 완벽하지 않습니다. 자체적인 "함정"이 존재합니다.
|
|
107
|
+
|
|
108
|
+
1. **네임스페이스 지옥:** 어떤 JSON 파일을 로드할지 (`common.json`, `dashboard.json`, `footer.json`) 수동으로 관리해야 하는 경우가 많습니다. 하나라도 잊으면 사용자는 원시 키를 보게 됩니다.
|
|
109
|
+
2. **과도한 페칭:** 신중한 설정 없이 초기 로드 시 모든 페이지의 모든 번역 키를 실수로 불러와 번들 크기가 불필요하게 커질 수 있습니다.
|
|
110
|
+
3. **동기화 이탈(Sync Drift):** 컴포넌트가 삭제된 후에도 해당 키가 JSON 파일에 남아 있는 경우가 흔합니다. 이로 인해 번역 파일이 무한히 커지며 "좀비 키"로 가득 차게 됩니다.
|
|
111
|
+
|
|
112
|
+
## Intlayer의 중간 지점
|
|
113
|
+
|
|
114
|
+
이것이 바로 **Intlayer**와 같은 도구들이 혁신을 시도하는 부분입니다. Intlayer는 컴파일러가 강력하지만, 암묵적인 마법은 위험하다는 점을 이해합니다.
|
|
115
|
+
|
|
116
|
+
Intlayer는 독특한 **`transform` 명령어**를 제공합니다. 숨겨진 빌드 단계에서 마법처럼 처리하는 대신, 실제로 **컴포넌트 코드를 재작성**할 수 있습니다. 텍스트를 스캔하여 코드베이스 내에서 명시적인 콘텐츠 선언으로 대체합니다.
|
|
117
|
+
|
|
118
|
+
이로써 두 세계의 장점을 모두 누릴 수 있습니다:
|
|
119
|
+
|
|
120
|
+
1. **세분성(Granularity):** 번역을 컴포넌트 가까이에 유지하여 모듈화와 트리 쉐이킹(tree-shaking)을 개선합니다.
|
|
121
|
+
2. **안전성:** 번역이 숨겨진 빌드 타임 마법이 아니라 명시적인 코드가 됩니다.
|
|
122
|
+
3. **락인 방지:** 코드가 리포지토리 내에서 표준 선언적 구조로 변환되기 때문에 webpack 플러그인에 로직을 숨기지 않습니다.
|
|
123
|
+
|
|
124
|
+
## 결론
|
|
125
|
+
|
|
126
|
+
그렇다면 어떤 방식을 선택해야 할까요?
|
|
127
|
+
|
|
128
|
+
**당신이 주니어 개발자이거나, 1인 창업자이거나, MVP를 만들고 있다면:**
|
|
129
|
+
컴파일러 기반 접근법도 유효한 선택입니다. 매우 빠르게 개발할 수 있습니다. 파일 구조나 키에 대해 걱정할 필요가 없습니다. 그냥 개발하면 됩니다. 기술 부채는 "미래의 당신"이 해결할 문제입니다.
|
|
130
|
+
|
|
131
|
+
**당신이 전문적이고 엔터프라이즈급 애플리케이션을 개발 중이라면:**
|
|
132
|
+
마법 같은 접근법은 일반적으로 좋지 않습니다. 제어가 필요합니다.
|
|
133
|
+
|
|
134
|
+
- 백엔드에서 오는 동적 데이터를 처리해야 합니다.
|
|
135
|
+
- 저사양 기기에서의 성능을 보장해야 합니다 (hook 폭발 방지).
|
|
136
|
+
- 특정 빌드 도구에 영원히 종속되지 않도록 해야 합니다.
|
|
137
|
+
|
|
138
|
+
전문적인 애플리케이션의 경우, **선언적 콘텐츠 관리**(Intlayer나 검증된 라이브러리와 같은)는 여전히 최고의 표준입니다. 이는 관심사를 분리하고 아키텍처를 깔끔하게 유지하며, 애플리케이션이 여러 언어를 지원하는 능력이 "블랙박스" 컴파일러가 의도를 추측하는 것에 의존하지 않도록 보장합니다.
|