intor 2.3.8 → 2.3.9
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 +0 -79
- package/dist/core/export/index.js +5 -2
- package/dist/core/export/server/index.js +5 -1
- package/dist/core/src/config/constants/cookie.js +1 -1
- package/dist/core/src/config/constants/routing.js +7 -2
- package/dist/core/src/config/resolvers/resolve-routing-options.js +20 -0
- package/dist/core/src/core/error/intor-error.js +3 -1
- package/dist/core/src/{core/utils → routing}/pathname/get-unprefixed-pathname.js +4 -1
- package/dist/{react/src/core/utils → core/src/routing}/pathname/locale-prefix-pathname.js +6 -4
- package/dist/{react/src/core/utils → core/src/routing}/pathname/localize-pathname.js +2 -2
- package/dist/core/src/{core/utils → routing}/pathname/standardize-pathname.js +5 -2
- package/dist/core/src/server/helpers/get-translator.js +27 -0
- package/dist/core/src/server/helpers/local-messages-from-url.js +1 -2
- package/dist/core/src/server/intor/intor.js +18 -35
- package/dist/core/src/server/messages/load-local-messages/load-local-messages.js +32 -19
- package/dist/core/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +17 -9
- package/dist/core/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +31 -24
- package/dist/core/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +21 -10
- package/dist/core/src/server/messages/load-messages.js +17 -21
- package/dist/core/src/server/runtime/create-intor-runtime.js +52 -0
- package/dist/core/src/server/translator/create-translator.js +40 -0
- package/dist/express/export/express/index.js +2 -0
- package/dist/express/src/adapters/express/helpers/get-translator.js +23 -0
- package/dist/express/src/adapters/express/middleware/create-intor.js +60 -0
- package/dist/express/src/core/constants/headers.js +7 -0
- package/dist/express/src/core/constants/prefix-placeholder.js +4 -0
- package/dist/express/src/core/error/intor-error.js +23 -0
- package/dist/express/src/core/logger/get-logger.js +39 -0
- package/dist/express/src/core/logger/global-logger-pool.js +8 -0
- package/dist/express/src/core/messages/global-messages-pool.js +10 -0
- package/dist/express/src/core/messages/load-remote-messages/fetch-locale-messages/fetch-locale-messages.js +55 -0
- package/dist/express/src/core/messages/load-remote-messages/fetch-locale-messages/utils/build-search-params.js +25 -0
- package/dist/express/src/core/messages/load-remote-messages/load-remote-messages.js +108 -0
- package/dist/express/src/core/messages/utils/is-valid-messages.js +36 -0
- package/dist/express/src/core/utils/deep-merge.js +31 -0
- package/dist/express/src/core/utils/normalizers/normalize-cache-key.js +45 -0
- package/dist/express/src/core/utils/normalizers/normalize-locale.js +59 -0
- package/dist/express/src/core/utils/normalizers/normalize-pathname.js +43 -0
- package/dist/express/src/core/utils/normalizers/normalize-query.js +25 -0
- package/dist/express/src/core/utils/resolve-loader-options.js +25 -0
- package/dist/express/src/routing/inbound/resolve-inbound.js +46 -0
- package/dist/{next/src/routing/pathname → express/src/routing/inbound/resolve-pathname}/resolve-pathname.js +5 -9
- package/dist/{next/src/core/utils → express/src/routing}/locale/get-locale-from-accept-language.js +4 -1
- package/dist/{next/src/core/utils → express/src/routing}/locale/get-locale-from-host.js +4 -1
- package/dist/{next/src/core/utils → express/src/routing}/locale/get-locale-from-pathname.js +4 -1
- package/dist/{next/src/core/utils → express/src/routing}/locale/get-locale-from-query.js +5 -2
- package/dist/{next/src/core/utils → express/src/routing}/pathname/get-unprefixed-pathname.js +4 -1
- package/dist/{core/src/core/utils → express/src/routing}/pathname/locale-prefix-pathname.js +6 -4
- package/dist/{next/src/core/utils → express/src/routing}/pathname/localize-pathname.js +2 -2
- package/dist/{next/src/core/utils → express/src/routing}/pathname/standardize-pathname.js +5 -2
- package/dist/express/src/server/helpers/get-translator.js +27 -0
- package/dist/express/src/server/messages/load-local-messages/load-local-messages.js +106 -0
- package/dist/express/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +88 -0
- package/dist/express/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +94 -0
- package/dist/express/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/json-reader.js +12 -0
- package/dist/express/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/nest-object-from-path.js +21 -0
- package/dist/express/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +42 -0
- package/dist/express/src/server/messages/load-messages.js +79 -0
- package/dist/express/src/server/runtime/create-intor-runtime.js +52 -0
- package/dist/express/src/server/translator/create-translator.js +40 -0
- package/dist/next/export/next/proxy/index.js +1 -1
- package/dist/next/export/next/server/index.js +2 -0
- package/dist/next/src/adapters/next/navigation/link.js +15 -17
- package/dist/next/src/adapters/next/navigation/redirect.js +8 -9
- package/dist/next/src/adapters/next/navigation/use-pathname.js +8 -15
- package/dist/next/src/adapters/next/navigation/use-router.js +24 -26
- package/dist/next/src/adapters/next/proxy/intor-proxy.js +16 -20
- package/dist/next/src/adapters/next/server/get-locale.js +7 -16
- package/dist/next/src/adapters/next/server/get-pathname.js +28 -0
- package/dist/next/src/adapters/next/server/get-translator.js +9 -10
- package/dist/next/src/adapters/next/server/intor.js +25 -0
- package/dist/next/src/core/constants/headers.js +7 -0
- package/dist/next/src/core/error/intor-error.js +16 -2
- package/dist/next/src/core/utils/normalizers/normalize-query.js +25 -0
- package/dist/next/src/routing/inbound/resolve-inbound.js +46 -0
- package/dist/next/src/routing/inbound/resolve-locale/resolve-locale.js +32 -0
- package/dist/next/src/routing/inbound/resolve-pathname/resolve-pathname.js +52 -0
- package/dist/next/src/routing/inbound/resolve-pathname/strategies/all.js +23 -0
- package/dist/next/src/routing/inbound/resolve-pathname/strategies/except-default.js +33 -0
- package/dist/next/src/routing/inbound/resolve-pathname/strategies/none.js +14 -0
- package/dist/next/src/routing/locale/get-locale-from-accept-language.js +48 -0
- package/dist/next/src/routing/locale/get-locale-from-host.js +34 -0
- package/dist/next/src/routing/locale/get-locale-from-pathname.js +55 -0
- package/dist/next/src/routing/locale/get-locale-from-query.js +36 -0
- package/dist/{react/src/core/utils → next/src/routing}/pathname/get-unprefixed-pathname.js +4 -1
- package/dist/next/src/{core/utils → routing}/pathname/locale-prefix-pathname.js +6 -4
- package/dist/{core/src/core/utils → next/src/routing}/pathname/localize-pathname.js +2 -2
- package/dist/{react/src/core/utils → next/src/routing}/pathname/standardize-pathname.js +5 -2
- package/dist/next/src/server/helpers/get-translator.js +27 -0
- package/dist/next/src/server/intor/intor.js +36 -0
- package/dist/next/src/server/messages/load-local-messages/load-local-messages.js +32 -19
- package/dist/next/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +17 -9
- package/dist/next/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +31 -24
- package/dist/next/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +21 -10
- package/dist/next/src/server/messages/load-messages.js +17 -21
- package/dist/next/src/server/runtime/create-intor-runtime.js +52 -0
- package/dist/next/src/server/translator/create-translator.js +40 -0
- package/dist/react/export/react/index.js +2 -3
- package/dist/react/src/client/react/helpers/use-load-messages.js +1 -1
- package/dist/react/src/client/react/navigation/use-resolve-navigation.js +16 -0
- package/dist/react/src/client/react/provider/effects/use-locale-effects.js +26 -3
- package/dist/react/src/client/react/provider/intor-provider.js +2 -2
- package/dist/react/src/client/{helpers → shared/helpers}/get-client-locale.js +4 -4
- package/dist/react/src/client/shared/utils/locale/set-locale-cookie-browser.js +0 -3
- package/dist/react/src/core/error/intor-error.js +3 -1
- package/dist/react/src/policies/shoud-full-reload.js +14 -0
- package/dist/react/src/policies/should-persist-on-first-visit.js +8 -0
- package/dist/react/src/policies/should-persist.js +8 -0
- package/dist/react/src/routing/navigation/decide-strategy.js +17 -0
- package/dist/react/src/routing/navigation/derive-target.js +58 -0
- package/dist/react/src/routing/navigation/resolve-navigation.js +25 -0
- package/dist/react/src/routing/navigation/utils/derive-host-destination.js +13 -0
- package/dist/react/src/routing/navigation/utils/derive-query-destination.js +11 -0
- package/dist/react/src/routing/pathname/get-unprefixed-pathname.js +42 -0
- package/dist/react/src/routing/pathname/locale-prefix-pathname.js +40 -0
- package/dist/react/src/routing/pathname/localize-pathname.js +36 -0
- package/dist/react/src/routing/pathname/standardize-pathname.js +33 -0
- package/dist/svelte/export/svelte/index.js +2 -5
- package/dist/{vue/src/client → svelte/src/client/shared}/helpers/get-client-locale.js +4 -4
- package/dist/svelte/src/client/shared/utils/locale/set-locale-cookie-browser.js +0 -3
- package/dist/svelte/src/client/svelte/helpers/create-messages.js +44 -0
- package/dist/svelte/src/client/svelte/render/create-svelte-renderer.js +34 -0
- package/dist/svelte/src/client/svelte/render/render-rich-message-svelte.js +20 -0
- package/dist/svelte/src/client/svelte/render/utils/escape-html.js +10 -0
- package/dist/svelte/src/client/svelte/render/utils/render-attributes.js +15 -0
- package/dist/svelte/src/client/svelte/runtime/create-intor-api.js +25 -0
- package/dist/svelte/src/client/svelte/runtime/create-intor.js +9 -6
- package/dist/svelte/src/client/svelte/runtime/effects/locale-effects.js +27 -11
- package/dist/svelte/src/core/error/intor-error.js +3 -1
- package/dist/svelte/src/policies/should-persist-on-first-visit.js +8 -0
- package/dist/svelte/src/policies/should-persist.js +8 -0
- package/dist/types/export/express/index.d.ts +1 -0
- package/dist/types/export/index.d.ts +4 -2
- package/dist/types/export/next/proxy/index.d.ts +1 -1
- package/dist/types/export/next/server/index.d.ts +1 -1
- package/dist/types/export/react/index.d.ts +1 -3
- package/dist/types/export/svelte/index.d.ts +1 -1
- package/dist/types/src/adapters/express/global.d.ts +20 -0
- package/dist/types/src/adapters/express/helpers/get-translator.d.ts +18 -0
- package/dist/types/src/adapters/express/helpers/index.d.ts +1 -0
- package/dist/types/src/adapters/express/index.d.ts +3 -0
- package/dist/types/src/adapters/express/middleware/create-intor.d.ts +14 -0
- package/dist/types/src/adapters/express/middleware/index.d.ts +1 -0
- package/dist/types/src/adapters/next/navigation/link.d.ts +6 -9
- package/dist/types/src/adapters/next/navigation/redirect.d.ts +6 -9
- package/dist/types/src/adapters/next/navigation/use-pathname.d.ts +8 -11
- package/dist/types/src/adapters/next/navigation/use-router.d.ts +4 -5
- package/dist/types/src/adapters/next/proxy/intor-proxy.d.ts +4 -7
- package/dist/types/src/adapters/next/server/get-locale.d.ts +4 -1
- package/dist/types/src/adapters/next/server/get-pathname.d.ts +16 -0
- package/dist/types/src/adapters/next/server/get-translator.d.ts +8 -5
- package/dist/types/src/adapters/next/server/index.d.ts +2 -0
- package/dist/types/src/adapters/next/server/intor.d.ts +12 -0
- package/dist/types/src/client/react/helpers/use-load-messages.d.ts +6 -5
- package/dist/types/src/client/react/index.d.ts +2 -2
- package/dist/types/src/client/react/navigation/index.d.ts +1 -2
- package/dist/types/src/client/react/navigation/use-resolve-navigation.d.ts +7 -0
- package/dist/types/src/client/react/provider/intor-provider.d.ts +1 -1
- package/dist/types/src/client/react/provider/types.d.ts +6 -7
- package/dist/types/src/client/react/provider/use-intor.d.ts +2 -1
- package/dist/types/src/client/{helpers → shared/helpers}/get-client-locale.d.ts +1 -1
- package/dist/types/src/client/shared/types/bootstrap.d.ts +2 -2
- package/dist/types/src/client/svelte/helpers/create-messages.d.ts +6 -5
- package/dist/types/src/client/svelte/index.d.ts +2 -2
- package/dist/types/src/client/svelte/render/create-svelte-renderer.d.ts +14 -0
- package/dist/types/src/client/svelte/render/index.d.ts +2 -0
- package/dist/types/src/client/svelte/render/render-rich-message-svelte.d.ts +11 -0
- package/dist/types/src/client/svelte/render/types.d.ts +14 -0
- package/dist/types/src/client/svelte/render/utils/escape-html.d.ts +1 -0
- package/dist/types/src/client/svelte/render/utils/render-attributes.d.ts +3 -0
- package/dist/types/src/client/svelte/runtime/create-intor-api.d.ts +13 -0
- package/dist/types/src/client/svelte/runtime/create-intor.d.ts +2 -12
- package/dist/types/src/client/svelte/runtime/effects/locale-effects.d.ts +0 -8
- package/dist/types/src/client/svelte/runtime/index.d.ts +1 -0
- package/dist/types/src/client/svelte/runtime/types.d.ts +25 -4
- package/dist/types/src/client/vue/helpers/use-load-messages.d.ts +6 -5
- package/dist/types/src/client/vue/index.d.ts +1 -1
- package/dist/types/src/client/vue/provider/inject.d.ts +3 -2
- package/dist/types/src/client/vue/provider/types.d.ts +6 -7
- package/dist/types/src/client/vue/render/index.d.ts +1 -1
- package/dist/types/src/config/types/cookie.d.ts +3 -3
- package/dist/types/src/config/types/routing.d.ts +72 -19
- package/dist/types/src/core/constants/headers.d.ts +5 -0
- package/dist/types/src/core/constants/index.d.ts +1 -0
- package/dist/types/src/core/error/intor-error.d.ts +2 -1
- package/dist/types/src/core/index.d.ts +4 -4
- package/dist/types/src/core/messages/index.d.ts +1 -1
- package/dist/types/src/core/messages/types.d.ts +9 -0
- package/dist/types/src/core/types/index.d.ts +1 -1
- package/dist/types/src/core/types/routing.d.ts +40 -3
- package/dist/types/src/core/utils/index.d.ts +1 -3
- package/dist/types/src/core/utils/normalizers/index.d.ts +1 -0
- package/dist/types/src/core/utils/normalizers/normalize-query.d.ts +15 -0
- package/dist/types/src/policies/index.d.ts +2 -0
- package/dist/types/src/policies/shoud-full-reload.d.ts +5 -0
- package/dist/types/src/policies/should-persist-on-first-visit.d.ts +4 -0
- package/dist/types/src/policies/should-persist.d.ts +7 -0
- package/dist/types/src/routing/inbound/index.d.ts +1 -0
- package/dist/types/src/routing/inbound/resolve-inbound.d.ts +28 -0
- package/dist/types/src/routing/inbound/resolve-locale/index.d.ts +1 -0
- package/dist/types/src/routing/{locale → inbound/resolve-locale}/resolve-locale.d.ts +1 -1
- package/dist/types/src/routing/{locale → inbound/resolve-locale}/types.d.ts +1 -5
- package/dist/types/src/routing/inbound/resolve-pathname/index.d.ts +1 -0
- package/dist/types/src/routing/{pathname → inbound/resolve-pathname}/resolve-pathname.d.ts +2 -2
- package/dist/types/src/routing/{pathname → inbound/resolve-pathname}/strategies/all.d.ts +1 -1
- package/dist/types/src/routing/{pathname → inbound/resolve-pathname}/strategies/except-default.d.ts +1 -1
- package/dist/types/src/routing/{pathname → inbound/resolve-pathname}/types.d.ts +1 -1
- package/dist/types/src/routing/index.d.ts +4 -3
- package/dist/types/src/{core/utils → routing}/locale/get-locale-from-accept-language.d.ts +2 -2
- package/dist/types/src/{core/utils → routing}/locale/get-locale-from-host.d.ts +1 -1
- package/dist/types/src/{core/utils → routing}/locale/get-locale-from-pathname.d.ts +1 -1
- package/dist/types/src/{core/utils → routing}/locale/get-locale-from-query.d.ts +1 -1
- package/dist/types/src/routing/locale/index.d.ts +4 -1
- package/dist/types/src/routing/navigation/decide-strategy.d.ts +17 -0
- package/dist/types/src/routing/navigation/derive-target.d.ts +17 -0
- package/dist/types/src/routing/navigation/index.d.ts +1 -0
- package/dist/types/src/routing/navigation/resolve-navigation.d.ts +22 -0
- package/dist/types/src/routing/navigation/utils/derive-host-destination.d.ts +6 -0
- package/dist/types/src/routing/navigation/utils/derive-query-destination.d.ts +6 -0
- package/dist/types/src/{core/utils → routing}/pathname/get-unprefixed-pathname.d.ts +1 -1
- package/dist/types/src/routing/pathname/index.d.ts +1 -1
- package/dist/types/src/{core/utils → routing}/pathname/locale-prefix-pathname.d.ts +1 -1
- package/dist/types/src/routing/pathname/localize-pathname.d.ts +45 -0
- package/dist/types/src/{core/utils → routing}/pathname/standardize-pathname.d.ts +1 -1
- package/dist/types/src/server/helpers/get-translator.d.ts +19 -0
- package/dist/types/src/server/helpers/index.d.ts +1 -0
- package/dist/types/src/server/helpers/local-messages-from-url.d.ts +2 -12
- package/dist/types/src/server/index.d.ts +2 -2
- package/dist/types/src/server/intor/intor.d.ts +7 -16
- package/dist/types/src/server/intor/types.d.ts +3 -4
- package/dist/types/src/server/messages/load-local-messages/load-local-messages.d.ts +7 -7
- package/dist/types/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.d.ts +4 -4
- package/dist/types/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/types.d.ts +2 -4
- package/dist/types/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.d.ts +11 -13
- package/dist/types/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/types.d.ts +2 -4
- package/dist/types/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.d.ts +8 -5
- package/dist/types/src/server/messages/load-local-messages/read-locale-messages/types.d.ts +3 -6
- package/dist/types/src/server/messages/load-local-messages/types.d.ts +2 -3
- package/dist/types/src/server/messages/load-messages.d.ts +9 -7
- package/dist/types/src/server/messages/types.d.ts +4 -11
- package/dist/types/src/server/runtime/create-intor-runtime.d.ts +13 -0
- package/dist/types/src/server/runtime/index.d.ts +2 -0
- package/dist/types/src/server/runtime/types.d.ts +27 -0
- package/dist/types/src/server/translator/create-translator.d.ts +28 -0
- package/dist/types/src/server/translator/index.d.ts +1 -1
- package/dist/vue/export/vue/index.js +1 -1
- package/dist/{svelte/src/client → vue/src/client/shared}/helpers/get-client-locale.js +4 -4
- package/dist/vue/src/client/shared/utils/locale/set-locale-cookie-browser.js +0 -3
- package/dist/vue/src/client/vue/helpers/use-load-messages.js +5 -5
- package/dist/vue/src/client/vue/provider/effects/use-locale-effects.js +27 -4
- package/dist/vue/src/client/vue/provider/intor-provider.js +4 -6
- package/dist/vue/src/client/vue/translator/create-t-rich.js +1 -1
- package/dist/vue/src/core/error/intor-error.js +3 -1
- package/dist/vue/src/policies/should-persist-on-first-visit.js +8 -0
- package/dist/vue/src/policies/should-persist.js +8 -0
- package/package.json +9 -11
- package/dist/core/export/config/index.js +0 -3
- package/dist/core/src/server/translator/get-translator.js +0 -30
- package/dist/next/src/adapters/next/proxy/utils/set-locale-cookie-edge.js +0 -19
- package/dist/next/src/routing/resolve-routing.js +0 -41
- package/dist/next/src/server/translator/get-translator.js +0 -30
- package/dist/react/src/client/react/navigation/use-navigation-strategy.js +0 -36
- package/dist/react/src/client/react/navigation/use-navigation-target.js +0 -23
- package/dist/react/src/routing/resolve-navigation-target.js +0 -31
- package/dist/types/export/config/index.d.ts +0 -1
- package/dist/types/src/adapters/next/proxy/utils/set-locale-cookie-edge.d.ts +0 -13
- package/dist/types/src/client/react/navigation/use-navigation-strategy.d.ts +0 -22
- package/dist/types/src/client/react/navigation/use-navigation-target.d.ts +0 -12
- package/dist/types/src/core/utils/locale/index.d.ts +0 -4
- package/dist/types/src/core/utils/pathname/index.d.ts +0 -1
- package/dist/types/src/core/utils/pathname/localize-pathname.d.ts +0 -23
- package/dist/types/src/routing/resolve-navigation-target.d.ts +0 -20
- package/dist/types/src/routing/resolve-routing.d.ts +0 -30
- package/dist/types/src/server/translator/get-translator.d.ts +0 -21
- /package/dist/{next/src/routing/locale → express/src/routing/inbound/resolve-locale}/resolve-locale.js +0 -0
- /package/dist/{next/src/routing/pathname → express/src/routing/inbound/resolve-pathname}/strategies/all.js +0 -0
- /package/dist/{next/src/routing/pathname → express/src/routing/inbound/resolve-pathname}/strategies/except-default.js +0 -0
- /package/dist/{next/src/routing/pathname → express/src/routing/inbound/resolve-pathname}/strategies/none.js +0 -0
- /package/dist/types/src/client/{helpers → shared/helpers}/index.d.ts +0 -0
- /package/dist/types/src/client/vue/render/{render-rich-message-react.d.ts → render-rich-message-vue.d.ts} +0 -0
- /package/dist/types/src/routing/{pathname → inbound/resolve-pathname}/strategies/index.d.ts +0 -0
- /package/dist/types/src/routing/{pathname → inbound/resolve-pathname}/strategies/none.d.ts +0 -0
- /package/dist/vue/src/client/vue/render/{render-rich-message-react.js → render-rich-message-vue.js} +0 -0
package/README.md
CHANGED
|
@@ -21,82 +21,3 @@ Fast to start, easy to extend, and free from the usual i18n heaviness.
|
|
|
21
21
|
#### 🍳 Cooking the Intor v2 docs, crafting them to perfection...
|
|
22
22
|
|
|
23
23
|
</div>
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
Intor separates language translation from semantic rendering.
|
|
28
|
-
ICU operates at the text-translation layer, while semantic tags
|
|
29
|
-
are parsed and rendered in a dedicated AST-based rendering phase.
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
┌──────────────────────────────────────────────┐
|
|
33
|
-
│ Application │
|
|
34
|
-
│ │
|
|
35
|
-
│ t() / tRich() / <T /> │
|
|
36
|
-
└───────────────────────────┬──────────────────┘
|
|
37
|
-
│
|
|
38
|
-
▼
|
|
39
|
-
┌──────────────────────────────────────────────┐
|
|
40
|
-
│ Translator (Language / Semantic) │
|
|
41
|
-
│ intor-translator │
|
|
42
|
-
│ │
|
|
43
|
-
│ Responsibilities: │
|
|
44
|
-
│ - Resolve message key │
|
|
45
|
-
│ - Locale resolution & fallback │
|
|
46
|
-
│ - Message loading │
|
|
47
|
-
│ - Text-level interpolation │
|
|
48
|
-
│ • {name}, {count} │
|
|
49
|
-
│ • plural / select │
|
|
50
|
-
│ • ICU MessageFormat (optional) │
|
|
51
|
-
│ (ignoreTag: true) │
|
|
52
|
-
│ │
|
|
53
|
-
│ Output: │
|
|
54
|
-
│ - Translated string │
|
|
55
|
-
│ - May still contain <semantic tags> │
|
|
56
|
-
└───────────────────────────┬──────────────────┘
|
|
57
|
-
│
|
|
58
|
-
▼
|
|
59
|
-
┌──────────────────────────────────────────────┐
|
|
60
|
-
│ Semantic Parsing & AST Construction │
|
|
61
|
-
│ │
|
|
62
|
-
│ Responsibilities: │
|
|
63
|
-
│ - Tokenize semantic tags │
|
|
64
|
-
│ • <b>, <link>, <Component> │
|
|
65
|
-
│ - Build semantic AST │
|
|
66
|
-
│ • TextNode │
|
|
67
|
-
│ • TagNode │
|
|
68
|
-
│ │
|
|
69
|
-
│ Note: │
|
|
70
|
-
│ - Independent from ICU / formatter │
|
|
71
|
-
│ - Pure semantic structure │
|
|
72
|
-
└───────────────────────────┬──────────────────┘
|
|
73
|
-
│
|
|
74
|
-
▼
|
|
75
|
-
┌──────────────────────────────────────────────┐
|
|
76
|
-
│ Semantic Rendering (Renderer) │
|
|
77
|
-
│ │
|
|
78
|
-
│ Responsibilities: │
|
|
79
|
-
│ - Traverse semantic AST │
|
|
80
|
-
│ - Render TextNode │
|
|
81
|
-
│ - Render TagNode │
|
|
82
|
-
│ │
|
|
83
|
-
│ Renderer decides output type: │
|
|
84
|
-
│ - string │
|
|
85
|
-
│ - ReactNode │
|
|
86
|
-
│ - Vue / Svelte nodes │
|
|
87
|
-
│ - Markdown / CLI output │
|
|
88
|
-
│ │
|
|
89
|
-
│ Optional extensions: │
|
|
90
|
-
│ - Custom tag renderers │
|
|
91
|
-
│ - Rich components │
|
|
92
|
-
└───────────────────────────┬──────────────────┘
|
|
93
|
-
│
|
|
94
|
-
▼
|
|
95
|
-
┌──────────────────────────────────────────────┐
|
|
96
|
-
│ Final Output │
|
|
97
|
-
│ │
|
|
98
|
-
│ - Rendered rich content │
|
|
99
|
-
│ - Framework-specific result │
|
|
100
|
-
│ │
|
|
101
|
-
└──────────────────────────────────────────────┘
|
|
102
|
-
```
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export { PREFIX_PLACEHOLDER } from '../src/core/constants/prefix-placeholder.js';
|
|
2
2
|
export { IntorError, IntorErrorCode } from '../src/core/error/intor-error.js';
|
|
3
3
|
export { deepMerge } from '../src/core/utils/deep-merge.js';
|
|
4
|
-
export { localizePathname } from '../src/core/utils/pathname/localize-pathname.js';
|
|
5
4
|
import 'logry';
|
|
6
5
|
export { clearLoggerPool } from '../src/core/logger/global-logger-pool.js';
|
|
7
6
|
export { isValidMessages } from '../src/core/messages/utils/is-valid-messages.js';
|
|
8
7
|
export { clearMessagesPool, setGlobalMessagesPool } from '../src/core/messages/global-messages-pool.js';
|
|
9
|
-
|
|
8
|
+
export { defineIntorConfig } from '../src/config/define-intor-config.js';
|
|
9
|
+
import '../src/config/constants/cookie.js';
|
|
10
|
+
import '../src/config/constants/cache.js';
|
|
11
|
+
export { localizePathname } from '../src/routing/pathname/localize-pathname.js';
|
|
12
|
+
export { Translator } from 'intor-translator';
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export { intor } from '../../src/server/intor/intor.js';
|
|
2
2
|
export { loadMessages } from '../../src/server/messages/load-messages.js';
|
|
3
|
-
|
|
3
|
+
import 'intor-translator';
|
|
4
|
+
import '../../src/core/error/intor-error.js';
|
|
5
|
+
import 'logry';
|
|
6
|
+
import 'keyv';
|
|
7
|
+
export { getTranslator } from '../../src/server/helpers/get-translator.js';
|
|
4
8
|
export { loadMessagesFromUrl } from '../../src/server/helpers/local-messages-from-url.js';
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
const DEFAULT_ROUTING_OPTIONS = {
|
|
3
3
|
locale: {
|
|
4
4
|
sources: ["path", "query", "cookie", "detected"],
|
|
5
|
-
|
|
5
|
+
query: { key: "locale" },
|
|
6
|
+
},
|
|
7
|
+
navigation: {
|
|
8
|
+
carrier: "path",
|
|
9
|
+
path: { prefix: "none" },
|
|
10
|
+
query: { key: "locale" },
|
|
11
|
+
host: { map: {} },
|
|
6
12
|
},
|
|
7
|
-
prefix: "none",
|
|
8
13
|
firstVisit: {
|
|
9
14
|
localeSource: "browser",
|
|
10
15
|
redirect: true,
|
|
@@ -13,6 +13,26 @@ const resolveRoutingOptions = (routing = {}) => {
|
|
|
13
13
|
locale: {
|
|
14
14
|
...DEFAULT_ROUTING_OPTIONS.locale,
|
|
15
15
|
...routing.locale,
|
|
16
|
+
query: {
|
|
17
|
+
...DEFAULT_ROUTING_OPTIONS.locale.query,
|
|
18
|
+
...routing.locale?.query,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
navigation: {
|
|
22
|
+
...DEFAULT_ROUTING_OPTIONS.navigation,
|
|
23
|
+
...routing.navigation,
|
|
24
|
+
path: {
|
|
25
|
+
...DEFAULT_ROUTING_OPTIONS.navigation.path,
|
|
26
|
+
...routing.navigation?.path,
|
|
27
|
+
},
|
|
28
|
+
query: {
|
|
29
|
+
...DEFAULT_ROUTING_OPTIONS.navigation.query,
|
|
30
|
+
...routing.navigation?.query,
|
|
31
|
+
},
|
|
32
|
+
host: {
|
|
33
|
+
...DEFAULT_ROUTING_OPTIONS.navigation.host,
|
|
34
|
+
...routing.navigation?.host,
|
|
35
|
+
},
|
|
16
36
|
},
|
|
17
37
|
firstVisit: {
|
|
18
38
|
...DEFAULT_ROUTING_OPTIONS.firstVisit,
|
|
@@ -12,10 +12,12 @@ class IntorError extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
var IntorErrorCode;
|
|
14
14
|
(function (IntorErrorCode) {
|
|
15
|
-
//
|
|
15
|
+
// config
|
|
16
16
|
IntorErrorCode["MISSING_SUPPORTED_LOCALES"] = "INTOR_MISSING_SUPPORTED_LOCALES";
|
|
17
17
|
IntorErrorCode["MISSING_DEFAULT_LOCALE"] = "INTOR_MISSING_DEFAULT_LOCALE";
|
|
18
18
|
IntorErrorCode["UNSUPPORTED_DEFAULT_LOCALE"] = "INTOR_UNSUPPORTED_DEFAULT_LOCALE";
|
|
19
|
+
// runtime
|
|
20
|
+
IntorErrorCode["RUNTIME_NOT_INITIALIZED"] = "INTOR_RUNTIME_NOT_INITIALIZED";
|
|
19
21
|
})(IntorErrorCode || (IntorErrorCode = {}));
|
|
20
22
|
|
|
21
23
|
export { IntorError, IntorErrorCode };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import '../../core/error/intor-error.js';
|
|
2
|
+
import { normalizePathname } from '../../core/utils/normalizers/normalize-pathname.js';
|
|
3
|
+
import 'logry';
|
|
4
|
+
import 'keyv';
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* Returns a canonical, locale-agnostic pathname.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { PREFIX_PLACEHOLDER } from '../../constants/prefix-placeholder.js';
|
|
2
|
-
import
|
|
1
|
+
import { PREFIX_PLACEHOLDER } from '../../core/constants/prefix-placeholder.js';
|
|
2
|
+
import '../../core/error/intor-error.js';
|
|
3
|
+
import { normalizePathname } from '../../core/utils/normalizers/normalize-pathname.js';
|
|
4
|
+
import 'logry';
|
|
5
|
+
import 'keyv';
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* Applies routing prefix strategy by resolving the locale placeholder.
|
|
@@ -16,8 +19,7 @@ import { normalizePathname } from '../normalizers/normalize-pathname.js';
|
|
|
16
19
|
* ```
|
|
17
20
|
*/
|
|
18
21
|
const localePrefixPathname = (config, standardizedPathname, locale) => {
|
|
19
|
-
const {
|
|
20
|
-
const { prefix } = routing;
|
|
22
|
+
const { prefix } = config.routing.navigation.path;
|
|
21
23
|
if (prefix !== "none" && !locale) {
|
|
22
24
|
throw new Error('No locale when using prefix "all", "except-default"');
|
|
23
25
|
}
|
|
@@ -25,11 +25,11 @@ const localizePathname = (config, rawPathname, locale) => {
|
|
|
25
25
|
// 2. Standardize: build a pathname with locale placeholder
|
|
26
26
|
const standardizedPathname = standardizePathname(config, unprefixedPathname);
|
|
27
27
|
// 3. Apply strategy: resolve locale prefix based on routing rules
|
|
28
|
-
const
|
|
28
|
+
const pathname = localePrefixPathname(config, standardizedPathname, locale);
|
|
29
29
|
return {
|
|
30
|
+
pathname,
|
|
30
31
|
unprefixedPathname,
|
|
31
32
|
standardizedPathname,
|
|
32
|
-
localizedPathname,
|
|
33
33
|
};
|
|
34
34
|
};
|
|
35
35
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { PREFIX_PLACEHOLDER } from '../../constants/prefix-placeholder.js';
|
|
2
|
-
import
|
|
1
|
+
import { PREFIX_PLACEHOLDER } from '../../core/constants/prefix-placeholder.js';
|
|
2
|
+
import '../../core/error/intor-error.js';
|
|
3
|
+
import { normalizePathname } from '../../core/utils/normalizers/normalize-pathname.js';
|
|
4
|
+
import 'logry';
|
|
5
|
+
import 'keyv';
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* Standardizes a canonical pathname by applying the base path
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createIntorRuntime } from '../runtime/create-intor-runtime.js';
|
|
2
|
+
|
|
3
|
+
// Implementation
|
|
4
|
+
async function getTranslator(config, params) {
|
|
5
|
+
const { readOptions, allowCacheWrite, preKey, handlers, plugins } = params;
|
|
6
|
+
const locale = params.locale;
|
|
7
|
+
// Create runtime (request-scoped, no cache write)
|
|
8
|
+
const runtime = createIntorRuntime(config, {
|
|
9
|
+
readOptions,
|
|
10
|
+
allowCacheWrite,
|
|
11
|
+
});
|
|
12
|
+
// Ensure messages & create translator snapshot
|
|
13
|
+
await runtime.ensureMessages(locale);
|
|
14
|
+
const translator = runtime.translator(locale, {
|
|
15
|
+
preKey,
|
|
16
|
+
plugins,
|
|
17
|
+
handlers,
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
messages: translator.messages,
|
|
21
|
+
locale,
|
|
22
|
+
hasKey: translator.hasKey,
|
|
23
|
+
t: translator.t,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { getTranslator };
|
|
@@ -42,8 +42,7 @@ async function loadMessagesFromUrl(url, options) {
|
|
|
42
42
|
namespaces,
|
|
43
43
|
fallbackLocales,
|
|
44
44
|
concurrency: options?.concurrency,
|
|
45
|
-
|
|
46
|
-
messagesReader: options?.messagesReader,
|
|
45
|
+
readOptions: options?.readOptions,
|
|
47
46
|
pool: options?.pool,
|
|
48
47
|
cacheOptions: options?.cacheOptions || { enabled: false, ttl: 0 },
|
|
49
48
|
allowCacheWrite: options?.allowCacheWrite,
|
|
@@ -1,53 +1,36 @@
|
|
|
1
1
|
import '../../core/error/intor-error.js';
|
|
2
|
-
import { deepMerge } from '../../core/utils/deep-merge.js';
|
|
3
|
-
import { resolveLoaderOptions } from '../../core/utils/resolve-loader-options.js';
|
|
4
2
|
import { getLogger } from '../../core/logger/get-logger.js';
|
|
5
3
|
import 'keyv';
|
|
6
|
-
import {
|
|
4
|
+
import { createIntorRuntime } from '../runtime/create-intor-runtime.js';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
|
-
*
|
|
7
|
+
* Initializes Intor for the current execution context.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - Resolves the initial locale using a provided locale resolver
|
|
14
|
-
* - Loads locale messages if the message loader is enabled
|
|
15
|
-
* - Returns a fully-initialized Intor result
|
|
16
|
-
*
|
|
17
|
-
* This function does not perform routing decisions itself.
|
|
18
|
-
* Locale resolution is delegated to the provided `getLocale` implementation.
|
|
9
|
+
* Provides server-side bootstrap logic for SSR-based
|
|
10
|
+
* full-stack frameworks.
|
|
19
11
|
*/
|
|
20
|
-
|
|
12
|
+
async function intor(config, localeOrResolver, options) {
|
|
21
13
|
const baseLogger = getLogger(config.logger);
|
|
22
14
|
const logger = baseLogger.child({ scope: "intor" });
|
|
23
15
|
logger.info("Start Intor initialization.");
|
|
24
|
-
//
|
|
25
|
-
const
|
|
16
|
+
// Create runtime (request-scoped)
|
|
17
|
+
const runtime = createIntorRuntime(config, options);
|
|
18
|
+
// Resolve locale
|
|
19
|
+
const isLocaleFunction = typeof localeOrResolver === "function";
|
|
26
20
|
const locale = isLocaleFunction
|
|
27
|
-
? await
|
|
28
|
-
:
|
|
29
|
-
const source = typeof
|
|
21
|
+
? await localeOrResolver(config)
|
|
22
|
+
: localeOrResolver || config.defaultLocale;
|
|
23
|
+
const source = typeof localeOrResolver === "function" ? "resolver" : "static";
|
|
30
24
|
logger.debug(`Initial locale resolved as "${locale}" via "${source}".`);
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
if (loader) {
|
|
35
|
-
loadedMessages = await loadMessages({
|
|
36
|
-
config,
|
|
37
|
-
locale,
|
|
38
|
-
extraOptions: {
|
|
39
|
-
exts: loadMessagesOptions.exts,
|
|
40
|
-
messagesReader: loadMessagesOptions.messagesReader,
|
|
41
|
-
},
|
|
42
|
-
allowCacheWrite: true, // Intor is the primary cache writer during initialization.
|
|
43
|
-
});
|
|
44
|
-
}
|
|
25
|
+
// Ensure messages & create translator snapshot
|
|
26
|
+
await runtime.ensureMessages(locale);
|
|
27
|
+
const translator = runtime.translator(locale);
|
|
45
28
|
logger.info("Intor initialized.");
|
|
46
29
|
return {
|
|
47
30
|
config,
|
|
48
|
-
|
|
49
|
-
|
|
31
|
+
locale,
|
|
32
|
+
messages: translator.messages,
|
|
50
33
|
};
|
|
51
|
-
}
|
|
34
|
+
}
|
|
52
35
|
|
|
53
36
|
export { intor };
|
|
@@ -9,16 +9,16 @@ import { readLocaleMessages } from './read-locale-messages/read-locale-messages.
|
|
|
9
9
|
/**
|
|
10
10
|
* Load locale messages from the local file system.
|
|
11
11
|
*
|
|
12
|
-
* This function
|
|
13
|
-
* It
|
|
12
|
+
* This function serves as the orchestration layer for local message loading.
|
|
13
|
+
* It coordinates:
|
|
14
14
|
*
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
15
|
+
* - Locale resolution with fallbacks
|
|
16
|
+
* - Cache read / write behavior
|
|
17
|
+
* - Concurrency control for file system access
|
|
18
18
|
*
|
|
19
|
-
* File
|
|
19
|
+
* File traversal, parsing, and validation are delegated to lower-level utilities.
|
|
20
20
|
*/
|
|
21
|
-
const loadLocalMessages = async ({ locale, fallbackLocales, namespaces, rootDir = "messages", concurrency = 10,
|
|
21
|
+
const loadLocalMessages = async ({ locale, fallbackLocales, namespaces, rootDir = "messages", concurrency = 10, readOptions, pool = getGlobalMessagesPool(), cacheOptions, allowCacheWrite = false, loggerOptions, }) => {
|
|
22
22
|
const baseLogger = getLogger(loggerOptions);
|
|
23
23
|
const logger = baseLogger.child({ scope: "load-local-messages" });
|
|
24
24
|
const start = performance.now();
|
|
@@ -26,7 +26,9 @@ const loadLocalMessages = async ({ locale, fallbackLocales, namespaces, rootDir
|
|
|
26
26
|
rootDir,
|
|
27
27
|
resolvedRootDir: path.resolve(process.cwd(), rootDir),
|
|
28
28
|
});
|
|
29
|
-
//
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Cache key resolution
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
30
32
|
const cacheKey = normalizeCacheKey([
|
|
31
33
|
loggerOptions.id,
|
|
32
34
|
"loaderType:local",
|
|
@@ -35,18 +37,24 @@ const loadLocalMessages = async ({ locale, fallbackLocales, namespaces, rootDir
|
|
|
35
37
|
(fallbackLocales || []).toSorted().join(","),
|
|
36
38
|
(namespaces || []).toSorted().join(","),
|
|
37
39
|
]);
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Cache read
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
if (cacheOptions.enabled) {
|
|
44
|
+
if (cacheKey) {
|
|
45
|
+
const cached = await pool?.get(cacheKey);
|
|
46
|
+
if (cached) {
|
|
47
|
+
logger.debug("Messages cache hit.", { key: cacheKey });
|
|
48
|
+
return cached;
|
|
49
|
+
}
|
|
44
50
|
}
|
|
45
51
|
}
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Resolve locale messages with ordered fallback strategy
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
46
55
|
const limit = pLimit(concurrency);
|
|
47
56
|
const candidateLocales = [locale, ...(fallbackLocales || [])];
|
|
48
57
|
let messages;
|
|
49
|
-
// Try each candidate locale in order and stop at the first successful result
|
|
50
58
|
for (let i = 0; i < candidateLocales.length; i++) {
|
|
51
59
|
const candidateLocale = candidateLocales[i];
|
|
52
60
|
const isLast = i === candidateLocales.length - 1;
|
|
@@ -56,7 +64,8 @@ const loadLocalMessages = async ({ locale, fallbackLocales, namespaces, rootDir
|
|
|
56
64
|
namespaces,
|
|
57
65
|
rootDir,
|
|
58
66
|
limit,
|
|
59
|
-
|
|
67
|
+
readOptions,
|
|
68
|
+
loggerOptions,
|
|
60
69
|
});
|
|
61
70
|
// Stop at the first locale that yields non-empty messages
|
|
62
71
|
if (Object.values(result[candidateLocale] || {}).length > 0) {
|
|
@@ -76,9 +85,13 @@ const loadLocalMessages = async ({ locale, fallbackLocales, namespaces, rootDir
|
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Cache write (explicitly permitted)
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
if (cacheOptions.enabled && allowCacheWrite) {
|
|
92
|
+
if (cacheKey && messages) {
|
|
93
|
+
await pool?.set(cacheKey, messages, cacheOptions.ttl);
|
|
94
|
+
}
|
|
82
95
|
}
|
|
83
96
|
// Final success log with resolved locale and timing
|
|
84
97
|
if (messages) {
|
|
@@ -5,10 +5,10 @@ import { getLogger } from '../../../../../core/logger/get-logger.js';
|
|
|
5
5
|
import 'keyv';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Recursively collects
|
|
8
|
+
* Recursively collects message file metadata under a given locale root.
|
|
9
9
|
*
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
10
|
+
* - Traverses directories and collects matching message files
|
|
11
|
+
* - Supports filtering by file extensions and optional namespaces
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* ```ts
|
|
@@ -21,12 +21,15 @@ import 'keyv';
|
|
|
21
21
|
* }, ... ];
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
async function collectFileEntries({ readdir = fs.readdir, namespaces, rootDir, limit,
|
|
24
|
+
async function collectFileEntries({ readdir = fs.readdir, namespaces, rootDir, limit, exts = [".json"], loggerOptions, }) {
|
|
25
25
|
const baseLogger = getLogger(loggerOptions);
|
|
26
26
|
const logger = baseLogger.child({ scope: "collect-file-entries" });
|
|
27
27
|
const fileEntries = [];
|
|
28
|
+
// Recursive directory walk
|
|
28
29
|
const walk = async (currentDir) => {
|
|
29
|
-
//
|
|
30
|
+
// -------------------------------------------------------------------------
|
|
31
|
+
// Read directory entries
|
|
32
|
+
// -------------------------------------------------------------------------
|
|
30
33
|
let entries = [];
|
|
31
34
|
try {
|
|
32
35
|
entries = await readdir(currentDir, { withFileTypes: true });
|
|
@@ -37,17 +40,22 @@ async function collectFileEntries({ readdir = fs.readdir, namespaces, rootDir, l
|
|
|
37
40
|
});
|
|
38
41
|
return;
|
|
39
42
|
}
|
|
40
|
-
//
|
|
43
|
+
// -------------------------------------------------------------------------
|
|
44
|
+
// Process entries (files & sub-directories)
|
|
45
|
+
// -------------------------------------------------------------------------
|
|
41
46
|
const tasks = entries.map((entry) => limit(async () => {
|
|
42
47
|
const fullPath = path.join(currentDir, entry.name);
|
|
43
|
-
//
|
|
48
|
+
// Recurse into sub-directories
|
|
44
49
|
if (entry.isDirectory()) {
|
|
45
50
|
await walk(fullPath);
|
|
46
51
|
return;
|
|
47
52
|
}
|
|
48
|
-
//
|
|
53
|
+
// Skip unsupported file extensions
|
|
49
54
|
if (!exts.some((ext) => entry.name.endsWith(ext)))
|
|
50
55
|
return;
|
|
56
|
+
// ---------------------------------------------------------------------
|
|
57
|
+
// Resolve file entry
|
|
58
|
+
// ---------------------------------------------------------------------
|
|
51
59
|
const relativePath = path.relative(rootDir, fullPath);
|
|
52
60
|
const ext = path.extname(relativePath);
|
|
53
61
|
const withoutExt = relativePath.slice(0, -ext.length);
|
|
@@ -55,7 +63,7 @@ async function collectFileEntries({ readdir = fs.readdir, namespaces, rootDir, l
|
|
|
55
63
|
const namespace = segments.at(0);
|
|
56
64
|
if (!namespace)
|
|
57
65
|
return;
|
|
58
|
-
//
|
|
66
|
+
// Apply namespace filter (always allow "index")
|
|
59
67
|
if (namespaces && namespace !== "index") {
|
|
60
68
|
if (!namespaces.includes(namespace))
|
|
61
69
|
return;
|
|
@@ -8,12 +8,12 @@ import { jsonReader } from './utils/json-reader.js';
|
|
|
8
8
|
import { nestObjectFromPath } from './utils/nest-object-from-path.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Parse locale message files
|
|
11
|
+
* Parse locale message files into a unified Messages object (single-locale).
|
|
12
12
|
*
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
13
|
+
* - Reads JSON or custom formats (via `messagesReader`)
|
|
14
|
+
* - Validates message structure
|
|
15
15
|
* - Builds nested objects based on file path segments
|
|
16
|
-
* - Deep-merges entries
|
|
16
|
+
* - Deep-merges entries by namespace
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```plain
|
|
@@ -24,42 +24,47 @@ import { nestObjectFromPath } from './utils/nest-object-from-path.js';
|
|
|
24
24
|
* - en/auth/verify.json = { d: "D" }
|
|
25
25
|
*```
|
|
26
26
|
|
|
27
|
-
* The final return value is a
|
|
27
|
+
* The final return value is a `Messages` object:
|
|
28
28
|
* ```ts
|
|
29
29
|
* {
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* verify: { d: "D" },
|
|
36
|
-
* },
|
|
30
|
+
* a: "A",
|
|
31
|
+
* ui: { b: "B" },
|
|
32
|
+
* auth: {
|
|
33
|
+
* c: "C",
|
|
34
|
+
* verify: { d: "D" },
|
|
37
35
|
* },
|
|
38
36
|
* }
|
|
39
37
|
* ```
|
|
40
38
|
*/
|
|
41
|
-
async function parseFileEntries({ fileEntries, limit,
|
|
39
|
+
async function parseFileEntries({ fileEntries, limit, messagesReader, loggerOptions, }) {
|
|
42
40
|
const baseLogger = getLogger(loggerOptions);
|
|
43
41
|
const logger = baseLogger.child({ scope: "parse-file-entries" });
|
|
44
42
|
// Read and parse all file entries
|
|
45
43
|
const parsedFileEntries = [];
|
|
46
44
|
const tasks = fileEntries.map(({ namespace, segments, basename, fullPath, relativePath }) => limit(async () => {
|
|
47
45
|
try {
|
|
48
|
-
|
|
46
|
+
// -------------------------------------------------------------------
|
|
47
|
+
// Read and validate file content
|
|
48
|
+
// -------------------------------------------------------------------
|
|
49
49
|
const ext = path.extname(fullPath);
|
|
50
|
-
|
|
51
|
-
const json = ext !== ".json" && messagesReader
|
|
50
|
+
const raw = ext !== ".json" && messagesReader
|
|
52
51
|
? await messagesReader(fullPath)
|
|
53
52
|
: await jsonReader(fullPath);
|
|
54
53
|
// Validate messages structure
|
|
55
|
-
if (!isValidMessages(
|
|
56
|
-
throw new Error("
|
|
54
|
+
if (!isValidMessages(raw)) {
|
|
55
|
+
throw new Error("Parsed content does not match expected Messages structure");
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
// -------------------------------------------------------------------
|
|
58
|
+
// Build nested message object from path segments
|
|
59
|
+
// -------------------------------------------------------------------
|
|
60
|
+
const segmentsWithoutNamespace = segments.slice(1);
|
|
61
|
+
const isIndexFile = basename === "index";
|
|
62
|
+
const keyPath = isIndexFile
|
|
63
|
+
? segmentsWithoutNamespace.slice(0, -1)
|
|
64
|
+
: segmentsWithoutNamespace;
|
|
60
65
|
// Nest the parsed content based on the path segments
|
|
61
|
-
const
|
|
62
|
-
parsedFileEntries.push({ namespace, messages:
|
|
66
|
+
const nestedMessages = nestObjectFromPath(keyPath, raw);
|
|
67
|
+
parsedFileEntries.push({ namespace, messages: nestedMessages });
|
|
63
68
|
logger.trace(`Parsed message file: ${relativePath}`);
|
|
64
69
|
}
|
|
65
70
|
catch (error) {
|
|
@@ -70,10 +75,12 @@ async function parseFileEntries({ fileEntries, limit, extraOptions: { messagesRe
|
|
|
70
75
|
}
|
|
71
76
|
}));
|
|
72
77
|
await Promise.all(tasks);
|
|
73
|
-
//
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Merge parsed entries by namespace
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
74
81
|
const result = {};
|
|
75
82
|
for (const { namespace, messages } of parsedFileEntries) {
|
|
76
|
-
//
|
|
83
|
+
// Root-level namespace (e.g. [locale]/index.json)
|
|
77
84
|
if (namespace === "index") {
|
|
78
85
|
Object.assign(result, deepMerge(result, messages));
|
|
79
86
|
}
|