intor 2.3.4 → 2.3.5

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.
Files changed (312) hide show
  1. package/README.md +75 -6
  2. package/dist/{export → core/export}/server/index.js +1 -1
  3. package/dist/core/src/server/shared/logger/global-logger-pool.js +16 -0
  4. package/dist/core/src/server/shared/messages/global-messages-pool.js +27 -0
  5. package/dist/{src → next/src}/adapters/next/navigation/link.js +6 -3
  6. package/dist/{src → next/src}/adapters/next/navigation/redirect.js +5 -5
  7. package/dist/{src → next/src}/adapters/next/navigation/use-pathname.js +1 -6
  8. package/dist/{src → next/src}/adapters/next/navigation/use-router.js +6 -3
  9. package/dist/next/src/client/react/contexts/translator/context.js +3 -0
  10. package/dist/next/src/client/react/contexts/translator-runtime/context.js +3 -0
  11. package/dist/{src → next/src}/client/react/navigation/use-navigation-strategy.js +1 -6
  12. package/dist/next/src/client/react/navigation/use-navigation-target.js +20 -0
  13. package/dist/next/src/config/constants/cache.constants.js +7 -0
  14. package/dist/next/src/server/messages/load-local-messages/load-local-messages.js +93 -0
  15. package/dist/next/src/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +78 -0
  16. package/dist/next/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +88 -0
  17. package/dist/next/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/json-reader.js +12 -0
  18. package/dist/next/src/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/nest-object-from-path.js +21 -0
  19. package/dist/next/src/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +31 -0
  20. package/dist/next/src/server/messages/load-messages.js +77 -0
  21. package/dist/next/src/server/messages/load-remote-messages/fetch-locale-messages/fetch-locale-messages.js +55 -0
  22. package/dist/next/src/server/messages/load-remote-messages/fetch-locale-messages/utils/build-search-params.js +25 -0
  23. package/dist/next/src/server/messages/load-remote-messages/load-remote-messages.js +110 -0
  24. package/dist/next/src/server/messages/shared/utils/is-valid-messages.js +36 -0
  25. package/dist/next/src/server/shared/logger/get-logger.js +39 -0
  26. package/dist/next/src/server/translator/get-translator.js +35 -0
  27. package/dist/next/src/shared/constants/prefix-placeholder.js +4 -0
  28. package/dist/next/src/shared/utils/deep-merge.js +36 -0
  29. package/dist/next/src/shared/utils/normalizers/normalize-cache-key.js +45 -0
  30. package/dist/next/src/shared/utils/normalizers/normalize-pathname.js +43 -0
  31. package/dist/next/src/shared/utils/pathname/get-unprefixed-pathname.js +39 -0
  32. package/dist/next/src/shared/utils/pathname/locale-prefix-pathname.js +38 -0
  33. package/dist/next/src/shared/utils/pathname/localize-pathname.js +36 -0
  34. package/dist/next/src/shared/utils/pathname/standardize-pathname.js +30 -0
  35. package/dist/{export → react/export}/react/index.js +13 -5
  36. package/dist/react/src/client/react/contexts/messages/context.js +5 -0
  37. package/dist/react/src/client/react/contexts/translator/context.js +5 -0
  38. package/dist/{src → react/src}/client/react/contexts/translator/provider.js +2 -2
  39. package/dist/react/src/client/react/contexts/translator-runtime/context.js +5 -0
  40. package/dist/react/src/client/react/render/create-react-renderer.js +36 -0
  41. package/dist/react/src/client/react/render/render-rich-message-react.js +22 -0
  42. package/dist/react/src/client/react/translator/create-t-rich.js +23 -0
  43. package/dist/react/src/client/react/translator/t.js +15 -0
  44. package/dist/{src → react/src}/client/react/translator/use-translator.js +4 -2
  45. package/dist/react/src/client/shared/utils/build-cookie-string.js +30 -0
  46. package/dist/react/src/client/shared/utils/locale/set-locale-cookie-browser.js +18 -0
  47. package/dist/react/src/config/constants/cache.constants.js +7 -0
  48. package/dist/react/src/server/messages/load-remote-messages/fetch-locale-messages/fetch-locale-messages.js +55 -0
  49. package/dist/react/src/server/messages/load-remote-messages/fetch-locale-messages/utils/build-search-params.js +25 -0
  50. package/dist/react/src/server/messages/load-remote-messages/load-remote-messages.js +110 -0
  51. package/dist/react/src/server/messages/shared/utils/is-valid-messages.js +36 -0
  52. package/dist/react/src/server/shared/logger/get-logger.js +39 -0
  53. package/dist/react/src/server/shared/logger/global-logger-pool.js +8 -0
  54. package/dist/react/src/server/shared/messages/global-messages-pool.js +10 -0
  55. package/dist/react/src/shared/utils/deep-merge.js +36 -0
  56. package/dist/react/src/shared/utils/normalizers/normalize-cache-key.js +45 -0
  57. package/dist/react/src/shared/utils/normalizers/normalize-locale.js +59 -0
  58. package/dist/types/export/internal/index.d.ts +1 -0
  59. package/dist/types/export/react/index.d.ts +1 -0
  60. package/dist/{export → types/export}/server/index.d.ts +1 -1
  61. package/dist/{src → types/src}/adapters/next/server/get-translator.d.ts +2 -5
  62. package/dist/types/src/client/react/contexts/index.d.ts +6 -0
  63. package/dist/types/src/client/react/index.d.ts +4 -0
  64. package/dist/{src → types/src}/client/react/navigation/use-navigation-target.d.ts +1 -1
  65. package/dist/types/src/client/react/render/create-react-renderer.d.ts +17 -0
  66. package/dist/types/src/client/react/render/index.d.ts +2 -0
  67. package/dist/types/src/client/react/render/render-rich-message-react.d.ts +13 -0
  68. package/dist/types/src/client/react/render/types.d.ts +17 -0
  69. package/dist/types/src/client/react/translator/create-t-rich.d.ts +15 -0
  70. package/dist/types/src/client/react/translator/index.d.ts +2 -0
  71. package/dist/types/src/client/react/translator/t.d.ts +27 -0
  72. package/dist/types/src/client/react/translator/translator-instance.d.ts +12 -0
  73. package/dist/types/src/client/react/translator/use-translator.d.ts +8 -0
  74. package/dist/types/src/client/shared/types/index.d.ts +1 -0
  75. package/dist/types/src/client/shared/types/translator-instance.d.ts +11 -0
  76. package/dist/{src → types/src}/server/index.d.ts +1 -1
  77. package/dist/{src → types/src}/server/shared/messages/global-messages-pool.d.ts +8 -1
  78. package/dist/{src → types/src}/server/translator/get-translator.d.ts +0 -4
  79. package/dist/{src → types/src}/shared/types/index.d.ts +1 -1
  80. package/dist/types/src/shared/types/translator-instance.d.ts +27 -0
  81. package/package.json +24 -22
  82. package/dist/export/internal/index.d.ts +0 -1
  83. package/dist/export/react/index.d.ts +0 -1
  84. package/dist/src/client/react/index.d.ts +0 -5
  85. package/dist/src/client/react/navigation/use-navigation-target.js +0 -27
  86. package/dist/src/client/react/translator/use-translator.d.ts +0 -12
  87. package/dist/src/shared/types/translator-instance.d.ts +0 -31
  88. /package/dist/{export → core/export}/config/index.js +0 -0
  89. /package/dist/{export → core/export}/index.js +0 -0
  90. /package/dist/{src → core/src}/config/constants/cache.constants.js +0 -0
  91. /package/dist/{src → core/src}/config/constants/cookie.constants.js +0 -0
  92. /package/dist/{src → core/src}/config/constants/routing.constants.js +0 -0
  93. /package/dist/{src → core/src}/config/define-intor-config.js +0 -0
  94. /package/dist/{src → core/src}/config/resolvers/resolve-cache-options.js +0 -0
  95. /package/dist/{src → core/src}/config/resolvers/resolve-cookie-options.js +0 -0
  96. /package/dist/{src → core/src}/config/resolvers/resolve-fallback-locales.js +0 -0
  97. /package/dist/{src → core/src}/config/resolvers/resolve-routing-options.js +0 -0
  98. /package/dist/{src → core/src}/config/validators/validate-default-locale.js +0 -0
  99. /package/dist/{src → core/src}/config/validators/validate-supported-locales.js +0 -0
  100. /package/dist/{src → core/src}/server/helpers/local-messages-from-url.js +0 -0
  101. /package/dist/{src → core/src}/server/intor/intor.js +0 -0
  102. /package/dist/{src → core/src}/server/messages/load-local-messages/load-local-messages.js +0 -0
  103. /package/dist/{src → core/src}/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.js +0 -0
  104. /package/dist/{src → core/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.js +0 -0
  105. /package/dist/{src → core/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/json-reader.js +0 -0
  106. /package/dist/{src → core/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/nest-object-from-path.js +0 -0
  107. /package/dist/{src → core/src}/server/messages/load-local-messages/read-locale-messages/read-locale-messages.js +0 -0
  108. /package/dist/{src → core/src}/server/messages/load-messages.js +0 -0
  109. /package/dist/{src → core/src}/server/messages/load-remote-messages/fetch-locale-messages/fetch-locale-messages.js +0 -0
  110. /package/dist/{src → core/src}/server/messages/load-remote-messages/fetch-locale-messages/utils/build-search-params.js +0 -0
  111. /package/dist/{src → core/src}/server/messages/load-remote-messages/load-remote-messages.js +0 -0
  112. /package/dist/{src → core/src}/server/messages/shared/utils/is-valid-messages.js +0 -0
  113. /package/dist/{src → core/src}/server/shared/logger/get-logger.js +0 -0
  114. /package/dist/{src → core/src}/server/translator/get-translator.js +0 -0
  115. /package/dist/{src → core/src}/shared/constants/prefix-placeholder.js +0 -0
  116. /package/dist/{src → core/src}/shared/error/intor-error.js +0 -0
  117. /package/dist/{src → core/src}/shared/utils/deep-merge.js +0 -0
  118. /package/dist/{src → core/src}/shared/utils/normalizers/normalize-cache-key.js +0 -0
  119. /package/dist/{src → core/src}/shared/utils/normalizers/normalize-pathname.js +0 -0
  120. /package/dist/{src → core/src}/shared/utils/pathname/get-unprefixed-pathname.js +0 -0
  121. /package/dist/{src → core/src}/shared/utils/pathname/locale-prefix-pathname.js +0 -0
  122. /package/dist/{src → core/src}/shared/utils/pathname/localize-pathname.js +0 -0
  123. /package/dist/{src → core/src}/shared/utils/pathname/standardize-pathname.js +0 -0
  124. /package/dist/{export → next/export}/next/index.js +0 -0
  125. /package/dist/{export → next/export}/next/proxy/index.js +0 -0
  126. /package/dist/{export → next/export}/next/server/index.js +0 -0
  127. /package/dist/{src → next/src}/adapters/next/proxy/intor-proxy.js +0 -0
  128. /package/dist/{src → next/src}/adapters/next/proxy/utils/set-locale-cookie-edge.js +0 -0
  129. /package/dist/{src → next/src}/adapters/next/server/get-locale.js +0 -0
  130. /package/dist/{src → next/src}/adapters/next/server/get-translator.js +0 -0
  131. /package/dist/{src/client/react/contexts/messages → next/src/client/react/contexts/config}/context.js +0 -0
  132. /package/dist/{src/client/react/contexts/translator-runtime → next/src/client/react/contexts/locale}/context.js +0 -0
  133. /package/dist/{src/client/react/contexts/translator → next/src/client/react/contexts/messages}/context.js +0 -0
  134. /package/dist/{src → next/src}/client/shared/utils/build-cookie-string.js +0 -0
  135. /package/dist/{src → next/src}/client/shared/utils/locale/set-locale-cookie-browser.js +0 -0
  136. /package/dist/{src → next/src}/routing/locale/resolve-locale.js +0 -0
  137. /package/dist/{src → next/src}/routing/pathname/resolve-pathname.js +0 -0
  138. /package/dist/{src → next/src}/routing/pathname/strategies/all.js +0 -0
  139. /package/dist/{src → next/src}/routing/pathname/strategies/except-default.js +0 -0
  140. /package/dist/{src → next/src}/routing/pathname/strategies/none.js +0 -0
  141. /package/dist/{src → next/src}/routing/resolve-navigation-target.js +0 -0
  142. /package/dist/{src → next/src}/routing/resolve-routing.js +0 -0
  143. /package/dist/{src → next/src}/server/shared/logger/global-logger-pool.js +0 -0
  144. /package/dist/{src → next/src}/server/shared/messages/global-messages-pool.js +0 -0
  145. /package/dist/{src → next/src}/shared/utils/is-external-destination.js +0 -0
  146. /package/dist/{src → next/src}/shared/utils/locale/get-locale-from-accept-language.js +0 -0
  147. /package/dist/{src → next/src}/shared/utils/locale/get-locale-from-host.js +0 -0
  148. /package/dist/{src → next/src}/shared/utils/locale/get-locale-from-pathname.js +0 -0
  149. /package/dist/{src → next/src}/shared/utils/locale/get-locale-from-query.js +0 -0
  150. /package/dist/{src → next/src}/shared/utils/normalizers/normalize-locale.js +0 -0
  151. /package/dist/{src → react/src}/client/helpers/get-client-locale.js +0 -0
  152. /package/dist/{src → react/src}/client/react/contexts/config/context.js +0 -0
  153. /package/dist/{src → react/src}/client/react/contexts/config/hook.js +0 -0
  154. /package/dist/{src → react/src}/client/react/contexts/config/provider.js +0 -0
  155. /package/dist/{src → react/src}/client/react/contexts/intor-provider/intor-provider.js +0 -0
  156. /package/dist/{src → react/src}/client/react/contexts/locale/context.js +0 -0
  157. /package/dist/{src → react/src}/client/react/contexts/locale/hook.js +0 -0
  158. /package/dist/{src → react/src}/client/react/contexts/locale/provider.js +0 -0
  159. /package/dist/{src → react/src}/client/react/contexts/locale/utils/change-locale.js +0 -0
  160. /package/dist/{src → react/src}/client/react/contexts/messages/hook.js +0 -0
  161. /package/dist/{src → react/src}/client/react/contexts/messages/provider.js +0 -0
  162. /package/dist/{src → react/src}/client/react/contexts/messages/utils/use-refetch-messages.js +0 -0
  163. /package/dist/{src → react/src}/client/react/contexts/translator/hook.js +0 -0
  164. /package/dist/{src → react/src}/client/react/contexts/translator-runtime/hook.js +0 -0
  165. /package/dist/{src → react/src}/client/react/contexts/translator-runtime/provider.js +0 -0
  166. /package/dist/{src → react/src}/client/shared/utils/locale/detect-browser-locale.js +0 -0
  167. /package/dist/{src → react/src}/client/shared/utils/locale/get-locale-cookie-browser.js +0 -0
  168. /package/dist/{src → react/src}/client/shared/utils/locale/set-document-locale.js +0 -0
  169. /package/dist/{export → types/export}/config/index.d.ts +0 -0
  170. /package/dist/{export → types/export}/index.d.ts +0 -0
  171. /package/dist/{export → types/export}/next/index.d.ts +0 -0
  172. /package/dist/{export → types/export}/next/proxy/index.d.ts +0 -0
  173. /package/dist/{export → types/export}/next/server/index.d.ts +0 -0
  174. /package/dist/{src → types/src}/adapters/next/navigation/index.d.ts +0 -0
  175. /package/dist/{src → types/src}/adapters/next/navigation/link.d.ts +0 -0
  176. /package/dist/{src → types/src}/adapters/next/navigation/redirect.d.ts +0 -0
  177. /package/dist/{src → types/src}/adapters/next/navigation/use-pathname.d.ts +0 -0
  178. /package/dist/{src → types/src}/adapters/next/navigation/use-router.d.ts +0 -0
  179. /package/dist/{src → types/src}/adapters/next/proxy/index.d.ts +0 -0
  180. /package/dist/{src → types/src}/adapters/next/proxy/intor-proxy.d.ts +0 -0
  181. /package/dist/{src → types/src}/adapters/next/proxy/utils/set-locale-cookie-edge.d.ts +0 -0
  182. /package/dist/{src → types/src}/adapters/next/server/get-locale.d.ts +0 -0
  183. /package/dist/{src → types/src}/adapters/next/server/index.d.ts +0 -0
  184. /package/dist/{src → types/src}/client/helpers/get-client-locale.d.ts +0 -0
  185. /package/dist/{src → types/src}/client/helpers/index.d.ts +0 -0
  186. /package/dist/{src → types/src}/client/react/contexts/config/context.d.ts +0 -0
  187. /package/dist/{src → types/src}/client/react/contexts/config/hook.d.ts +0 -0
  188. /package/dist/{src → types/src}/client/react/contexts/config/index.d.ts +0 -0
  189. /package/dist/{src → types/src}/client/react/contexts/config/provider.d.ts +0 -0
  190. /package/dist/{src → types/src}/client/react/contexts/config/types.d.ts +0 -0
  191. /package/dist/{src → types/src}/client/react/contexts/intor-provider/index.d.ts +0 -0
  192. /package/dist/{src → types/src}/client/react/contexts/intor-provider/intor-provider.d.ts +0 -0
  193. /package/dist/{src → types/src}/client/react/contexts/intor-provider/types.d.ts +0 -0
  194. /package/dist/{src → types/src}/client/react/contexts/locale/context.d.ts +0 -0
  195. /package/dist/{src → types/src}/client/react/contexts/locale/hook.d.ts +0 -0
  196. /package/dist/{src → types/src}/client/react/contexts/locale/index.d.ts +0 -0
  197. /package/dist/{src → types/src}/client/react/contexts/locale/provider.d.ts +0 -0
  198. /package/dist/{src → types/src}/client/react/contexts/locale/types.d.ts +0 -0
  199. /package/dist/{src → types/src}/client/react/contexts/locale/utils/change-locale.d.ts +0 -0
  200. /package/dist/{src → types/src}/client/react/contexts/messages/context.d.ts +0 -0
  201. /package/dist/{src → types/src}/client/react/contexts/messages/hook.d.ts +0 -0
  202. /package/dist/{src → types/src}/client/react/contexts/messages/index.d.ts +0 -0
  203. /package/dist/{src → types/src}/client/react/contexts/messages/provider.d.ts +0 -0
  204. /package/dist/{src → types/src}/client/react/contexts/messages/types.d.ts +0 -0
  205. /package/dist/{src → types/src}/client/react/contexts/messages/utils/use-refetch-messages.d.ts +0 -0
  206. /package/dist/{src → types/src}/client/react/contexts/translator/context.d.ts +0 -0
  207. /package/dist/{src → types/src}/client/react/contexts/translator/hook.d.ts +0 -0
  208. /package/dist/{src → types/src}/client/react/contexts/translator/index.d.ts +0 -0
  209. /package/dist/{src → types/src}/client/react/contexts/translator/provider.d.ts +0 -0
  210. /package/dist/{src → types/src}/client/react/contexts/translator/types.d.ts +0 -0
  211. /package/dist/{src → types/src}/client/react/contexts/translator-runtime/context.d.ts +0 -0
  212. /package/dist/{src → types/src}/client/react/contexts/translator-runtime/hook.d.ts +0 -0
  213. /package/dist/{src → types/src}/client/react/contexts/translator-runtime/index.d.ts +0 -0
  214. /package/dist/{src → types/src}/client/react/contexts/translator-runtime/provider.d.ts +0 -0
  215. /package/dist/{src → types/src}/client/react/contexts/translator-runtime/types.d.ts +0 -0
  216. /package/dist/{src → types/src}/client/react/navigation/index.d.ts +0 -0
  217. /package/dist/{src → types/src}/client/react/navigation/use-navigation-strategy.d.ts +0 -0
  218. /package/dist/{src → types/src}/client/shared/utils/build-cookie-string.d.ts +0 -0
  219. /package/dist/{src → types/src}/client/shared/utils/index.d.ts +0 -0
  220. /package/dist/{src → types/src}/client/shared/utils/locale/detect-browser-locale.d.ts +0 -0
  221. /package/dist/{src → types/src}/client/shared/utils/locale/get-locale-cookie-browser.d.ts +0 -0
  222. /package/dist/{src → types/src}/client/shared/utils/locale/index.d.ts +0 -0
  223. /package/dist/{src → types/src}/client/shared/utils/locale/set-document-locale.d.ts +0 -0
  224. /package/dist/{src → types/src}/client/shared/utils/locale/set-locale-cookie-browser.d.ts +0 -0
  225. /package/dist/{src → types/src}/config/constants/cache.constants.d.ts +0 -0
  226. /package/dist/{src → types/src}/config/constants/cookie.constants.d.ts +0 -0
  227. /package/dist/{src → types/src}/config/constants/routing.constants.d.ts +0 -0
  228. /package/dist/{src → types/src}/config/define-intor-config.d.ts +0 -0
  229. /package/dist/{src → types/src}/config/index.d.ts +0 -0
  230. /package/dist/{src → types/src}/config/resolvers/resolve-cache-options.d.ts +0 -0
  231. /package/dist/{src → types/src}/config/resolvers/resolve-cookie-options.d.ts +0 -0
  232. /package/dist/{src → types/src}/config/resolvers/resolve-fallback-locales.d.ts +0 -0
  233. /package/dist/{src → types/src}/config/resolvers/resolve-routing-options.d.ts +0 -0
  234. /package/dist/{src → types/src}/config/types/cache.types.d.ts +0 -0
  235. /package/dist/{src → types/src}/config/types/cookie.types.d.ts +0 -0
  236. /package/dist/{src → types/src}/config/types/intor-config.types.d.ts +0 -0
  237. /package/dist/{src → types/src}/config/types/loader.types.d.ts +0 -0
  238. /package/dist/{src → types/src}/config/types/logger.types.d.ts +0 -0
  239. /package/dist/{src → types/src}/config/types/routing.types.d.ts +0 -0
  240. /package/dist/{src → types/src}/config/types/translator.types.d.ts +0 -0
  241. /package/dist/{src → types/src}/config/validators/validate-default-locale.d.ts +0 -0
  242. /package/dist/{src → types/src}/config/validators/validate-supported-locales.d.ts +0 -0
  243. /package/dist/{src → types/src}/routing/index.d.ts +0 -0
  244. /package/dist/{src → types/src}/routing/locale/index.d.ts +0 -0
  245. /package/dist/{src → types/src}/routing/locale/resolve-locale.d.ts +0 -0
  246. /package/dist/{src → types/src}/routing/locale/types.d.ts +0 -0
  247. /package/dist/{src → types/src}/routing/pathname/index.d.ts +0 -0
  248. /package/dist/{src → types/src}/routing/pathname/resolve-pathname.d.ts +0 -0
  249. /package/dist/{src → types/src}/routing/pathname/strategies/all.d.ts +0 -0
  250. /package/dist/{src → types/src}/routing/pathname/strategies/except-default.d.ts +0 -0
  251. /package/dist/{src → types/src}/routing/pathname/strategies/index.d.ts +0 -0
  252. /package/dist/{src → types/src}/routing/pathname/strategies/none.d.ts +0 -0
  253. /package/dist/{src → types/src}/routing/pathname/types.d.ts +0 -0
  254. /package/dist/{src → types/src}/routing/resolve-navigation-target.d.ts +0 -0
  255. /package/dist/{src → types/src}/routing/resolve-routing.d.ts +0 -0
  256. /package/dist/{src → types/src}/server/helpers/index.d.ts +0 -0
  257. /package/dist/{src → types/src}/server/helpers/local-messages-from-url.d.ts +0 -0
  258. /package/dist/{src → types/src}/server/intor/index.d.ts +0 -0
  259. /package/dist/{src → types/src}/server/intor/intor.d.ts +0 -0
  260. /package/dist/{src → types/src}/server/intor/types.d.ts +0 -0
  261. /package/dist/{src → types/src}/server/messages/index.d.ts +0 -0
  262. /package/dist/{src → types/src}/server/messages/load-local-messages/index.d.ts +0 -0
  263. /package/dist/{src → types/src}/server/messages/load-local-messages/load-local-messages.d.ts +0 -0
  264. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/collect-file-entries/collect-file-entries.d.ts +0 -0
  265. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/collect-file-entries/index.d.ts +0 -0
  266. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/collect-file-entries/types.d.ts +0 -0
  267. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/index.d.ts +0 -0
  268. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/index.d.ts +0 -0
  269. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/parse-file-entries.d.ts +0 -0
  270. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/types.d.ts +0 -0
  271. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/json-reader.d.ts +0 -0
  272. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/parse-file-entries/utils/nest-object-from-path.d.ts +0 -0
  273. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/read-locale-messages.d.ts +0 -0
  274. /package/dist/{src → types/src}/server/messages/load-local-messages/read-locale-messages/types.d.ts +0 -0
  275. /package/dist/{src → types/src}/server/messages/load-local-messages/types.d.ts +0 -0
  276. /package/dist/{src → types/src}/server/messages/load-messages.d.ts +0 -0
  277. /package/dist/{src → types/src}/server/messages/load-remote-messages/fetch-locale-messages/fetch-locale-messages.d.ts +0 -0
  278. /package/dist/{src → types/src}/server/messages/load-remote-messages/fetch-locale-messages/index.d.ts +0 -0
  279. /package/dist/{src → types/src}/server/messages/load-remote-messages/fetch-locale-messages/types.d.ts +0 -0
  280. /package/dist/{src → types/src}/server/messages/load-remote-messages/fetch-locale-messages/utils/build-search-params.d.ts +0 -0
  281. /package/dist/{src → types/src}/server/messages/load-remote-messages/index.d.ts +0 -0
  282. /package/dist/{src → types/src}/server/messages/load-remote-messages/load-remote-messages.d.ts +0 -0
  283. /package/dist/{src → types/src}/server/messages/load-remote-messages/types.d.ts +0 -0
  284. /package/dist/{src → types/src}/server/messages/shared/types.d.ts +0 -0
  285. /package/dist/{src → types/src}/server/messages/shared/utils/is-valid-messages.d.ts +0 -0
  286. /package/dist/{src → types/src}/server/messages/types.d.ts +0 -0
  287. /package/dist/{src → types/src}/server/shared/logger/get-logger.d.ts +0 -0
  288. /package/dist/{src → types/src}/server/shared/logger/global-logger-pool.d.ts +0 -0
  289. /package/dist/{src → types/src}/server/translator/index.d.ts +0 -0
  290. /package/dist/{src → types/src}/shared/constants/index.d.ts +0 -0
  291. /package/dist/{src → types/src}/shared/constants/prefix-placeholder.d.ts +0 -0
  292. /package/dist/{src → types/src}/shared/error/index.d.ts +0 -0
  293. /package/dist/{src → types/src}/shared/error/intor-error.d.ts +0 -0
  294. /package/dist/{src → types/src}/shared/types/generated.d.ts +0 -0
  295. /package/dist/{src → types/src}/shared/types/routing.d.ts +0 -0
  296. /package/dist/{src → types/src}/shared/utils/deep-merge.d.ts +0 -0
  297. /package/dist/{src → types/src}/shared/utils/index.d.ts +0 -0
  298. /package/dist/{src → types/src}/shared/utils/is-external-destination.d.ts +0 -0
  299. /package/dist/{src → types/src}/shared/utils/locale/get-locale-from-accept-language.d.ts +0 -0
  300. /package/dist/{src → types/src}/shared/utils/locale/get-locale-from-host.d.ts +0 -0
  301. /package/dist/{src → types/src}/shared/utils/locale/get-locale-from-pathname.d.ts +0 -0
  302. /package/dist/{src → types/src}/shared/utils/locale/get-locale-from-query.d.ts +0 -0
  303. /package/dist/{src → types/src}/shared/utils/locale/index.d.ts +0 -0
  304. /package/dist/{src → types/src}/shared/utils/normalizers/index.d.ts +0 -0
  305. /package/dist/{src → types/src}/shared/utils/normalizers/normalize-cache-key.d.ts +0 -0
  306. /package/dist/{src → types/src}/shared/utils/normalizers/normalize-locale.d.ts +0 -0
  307. /package/dist/{src → types/src}/shared/utils/normalizers/normalize-pathname.d.ts +0 -0
  308. /package/dist/{src → types/src}/shared/utils/pathname/get-unprefixed-pathname.d.ts +0 -0
  309. /package/dist/{src → types/src}/shared/utils/pathname/index.d.ts +0 -0
  310. /package/dist/{src → types/src}/shared/utils/pathname/locale-prefix-pathname.d.ts +0 -0
  311. /package/dist/{src → types/src}/shared/utils/pathname/localize-pathname.d.ts +0 -0
  312. /package/dist/{src → types/src}/shared/utils/pathname/standardize-pathname.d.ts +0 -0
@@ -0,0 +1,77 @@
1
+ import { loadLocalMessages } from './load-local-messages/load-local-messages.js';
2
+ import { loadRemoteMessages } from './load-remote-messages/load-remote-messages.js';
3
+ import { getLogger } from '../shared/logger/get-logger.js';
4
+
5
+ /**
6
+ * Load locale messages based on the resolved Intor configuration.
7
+ *
8
+ * This function acts as a thin orchestration layer that:
9
+ *
10
+ * - Selects the appropriate message loader (local or remote)
11
+ * - Applies fallback locale resolution
12
+ * - Delegates caching and concurrency behavior to the underlying loader
13
+ *
14
+ * It does not perform message normalization or transformation itself.
15
+ */
16
+ const loadMessages = async ({ config, locale, extraOptions: { exts, messagesReader } = {}, allowCacheWrite = false, }) => {
17
+ const baseLogger = getLogger({ id: config.id, ...config.logger });
18
+ const logger = baseLogger.child({ scope: "load-messages" });
19
+ // Guard: no loader configured
20
+ if (!config.loader) {
21
+ logger.warn("No loader options have been configured in the current config.");
22
+ return;
23
+ }
24
+ const { type, concurrency, rootDir, namespaces } = config.loader;
25
+ const fallbackLocales = config.fallbackLocales[locale] || [];
26
+ logger.info(`Loading messages for locale "${locale}".`);
27
+ logger.trace("Starting to load messages with runtime context.", {
28
+ loaderType: type,
29
+ locale,
30
+ fallbackLocales,
31
+ namespaces: namespaces && namespaces.length > 0 ? [...namespaces] : "[ALL]",
32
+ cache: config.cache,
33
+ concurrency: concurrency ?? 10,
34
+ });
35
+ let loadedMessages;
36
+ // --- loader type: local
37
+ if (type === "local") {
38
+ loadedMessages = await loadLocalMessages({
39
+ locale,
40
+ fallbackLocales,
41
+ namespaces,
42
+ rootDir,
43
+ extraOptions: {
44
+ concurrency,
45
+ cacheOptions: config.cache,
46
+ loggerOptions: { id: config.id, ...config.logger },
47
+ exts,
48
+ messagesReader,
49
+ },
50
+ allowCacheWrite,
51
+ });
52
+ }
53
+ // --- loader type: remote
54
+ else if (type === "remote") {
55
+ // Fetch messages from remote
56
+ loadedMessages = await loadRemoteMessages({
57
+ locale,
58
+ fallbackLocales,
59
+ namespaces,
60
+ rootDir,
61
+ remoteUrl: config.loader.remoteUrl,
62
+ remoteHeaders: config.loader.remoteHeaders,
63
+ extraOptions: {
64
+ cacheOptions: config.cache,
65
+ loggerOptions: { id: config.id, ...config.logger },
66
+ },
67
+ allowCacheWrite,
68
+ });
69
+ }
70
+ // No messages found
71
+ if (!loadedMessages || Object.keys(loadedMessages).length === 0) {
72
+ logger.warn("No messages found.", { locale, fallbackLocales, namespaces });
73
+ }
74
+ return loadedMessages;
75
+ };
76
+
77
+ export { loadMessages };
@@ -0,0 +1,55 @@
1
+ import { isValidMessages } from '../../shared/utils/is-valid-messages.js';
2
+ import { getLogger } from '../../../shared/logger/get-logger.js';
3
+
4
+ /**
5
+ * Fetches locale messages from a remote API.
6
+ *
7
+ * - Validates that the returned JSON matches the expected `NamespaceMessages` structure.
8
+ * - Uses `fetch` with `no-store` cache to always get fresh data.
9
+ */
10
+ const fetchLocaleMessages = async ({ remoteUrl, remoteHeaders, searchParams, locale, extraOptions: { loggerOptions } = {}, signal, }) => {
11
+ const baseLogger = getLogger({ ...loggerOptions });
12
+ const logger = baseLogger.child({ scope: "fetch-locale-messages" });
13
+ try {
14
+ const params = new URLSearchParams(searchParams);
15
+ params.append("locale", locale);
16
+ const url = `${remoteUrl}?${params.toString()}`;
17
+ // Headers
18
+ const headers = {
19
+ "Content-Type": "application/json",
20
+ ...remoteHeaders,
21
+ };
22
+ // Fetch
23
+ const response = await fetch(url, {
24
+ method: "GET",
25
+ headers,
26
+ cache: "no-store",
27
+ signal,
28
+ });
29
+ if (!response.ok) {
30
+ throw new Error(`HTTP error ${response.status} ${response.statusText}`);
31
+ }
32
+ // Parse JSON body
33
+ const data = (await response.json());
34
+ // Validate messages structure
35
+ if (!isValidMessages(data[locale])) {
36
+ throw new Error("JSON file does not match NamespaceMessages structure");
37
+ }
38
+ return data;
39
+ }
40
+ catch (error) {
41
+ if (error instanceof Error && error.name === "AbortError") {
42
+ logger.debug("Fetching locale messages aborted.", { locale, remoteUrl });
43
+ return;
44
+ }
45
+ logger.warn("Fetching locale messages failed.", {
46
+ locale,
47
+ remoteUrl,
48
+ searchParams: decodeURIComponent(searchParams.toString()),
49
+ error,
50
+ });
51
+ return;
52
+ }
53
+ };
54
+
55
+ export { fetchLocaleMessages };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Build URLSearchParams from an object.
3
+ * Supports string or string[] values. Ignores undefined/null.
4
+ */
5
+ const buildSearchParams = (params) => {
6
+ const searchParams = new URLSearchParams();
7
+ const appendParam = (key, value) => {
8
+ if (value === undefined || value === null)
9
+ return;
10
+ if (Array.isArray(value) && value.length === 0)
11
+ return;
12
+ if (Array.isArray(value)) {
13
+ value.forEach((v) => v && searchParams.append(key, v));
14
+ }
15
+ else {
16
+ searchParams.append(key, value);
17
+ }
18
+ };
19
+ Object.entries(params).forEach(([key, value]) => {
20
+ appendParam(key, value);
21
+ });
22
+ return searchParams;
23
+ };
24
+
25
+ export { buildSearchParams };
@@ -0,0 +1,110 @@
1
+ import { DEFAULT_CACHE_OPTIONS } from '../../../config/constants/cache.constants.js';
2
+ import { fetchLocaleMessages } from './fetch-locale-messages/fetch-locale-messages.js';
3
+ import { buildSearchParams } from './fetch-locale-messages/utils/build-search-params.js';
4
+ import { getLogger } from '../../shared/logger/get-logger.js';
5
+ import { getGlobalMessagesPool } from '../../shared/messages/global-messages-pool.js';
6
+ import { normalizeCacheKey } from '../../../shared/utils/normalizers/normalize-cache-key.js';
7
+
8
+ /**
9
+ * Load locale messages from a remote API.
10
+ *
11
+ * This function acts as the orchestration layer for remote message loading.
12
+ * It is responsible for:
13
+ *
14
+ * - Resolving fallback locales in order
15
+ * - Coordinating cache read / write behavior
16
+ * - Respecting abort signals across the entire async flow
17
+ *
18
+ * Network fetching and data validation are delegated to lower-level utilities.
19
+ */
20
+ const loadRemoteMessages = async ({ pool = getGlobalMessagesPool(), rootDir, locale, fallbackLocales, namespaces, remoteUrl, remoteHeaders, extraOptions: { cacheOptions = DEFAULT_CACHE_OPTIONS, loggerOptions = { id: "default" }, } = {}, allowCacheWrite = false, signal, }) => {
21
+ const baseLogger = getLogger({ ...loggerOptions });
22
+ const logger = baseLogger.child({ scope: "load-remote-messages" });
23
+ // Abort early if the request has already been cancelled
24
+ if (signal?.aborted) {
25
+ logger.debug("Remote message loading aborted before fetch.");
26
+ return;
27
+ }
28
+ const start = performance.now();
29
+ logger.debug("Loading remote messages.", { remoteUrl });
30
+ // --- Cache key
31
+ const cacheKey = normalizeCacheKey([
32
+ loggerOptions.id,
33
+ "loaderType:remote",
34
+ rootDir,
35
+ locale,
36
+ (fallbackLocales ?? []).toSorted().join(","),
37
+ (namespaces ?? []).toSorted().join(","),
38
+ ]);
39
+ // --- Cache read --------------------------------------------------
40
+ if (cacheOptions.enabled && cacheKey) {
41
+ const cached = await pool?.get(cacheKey);
42
+ if (signal?.aborted) {
43
+ logger.debug("Remote message loading aborted after cache read.");
44
+ return;
45
+ }
46
+ if (cached) {
47
+ logger.debug("Messages cache hit.", { key: cacheKey });
48
+ return cached;
49
+ }
50
+ }
51
+ const candidateLocales = [locale, ...(fallbackLocales || [])];
52
+ let messages;
53
+ // Try each candidate locale in order and stop at the first successful result
54
+ for (let i = 0; i < candidateLocales.length; i++) {
55
+ const candidateLocale = candidateLocales[i];
56
+ const isLast = i === candidateLocales.length - 1;
57
+ try {
58
+ const fetched = await fetchLocaleMessages({
59
+ remoteUrl,
60
+ remoteHeaders,
61
+ locale: candidateLocale,
62
+ searchParams: buildSearchParams({ rootDir, namespaces }),
63
+ extraOptions: { loggerOptions },
64
+ signal,
65
+ });
66
+ // Stop at the first locale that yields non-empty messages
67
+ if (fetched && Object.values(fetched[candidateLocale] || {}).length > 0) {
68
+ messages = fetched;
69
+ break;
70
+ }
71
+ }
72
+ catch (error) {
73
+ if (error instanceof Error && error.name === "AbortError") {
74
+ logger.debug("Remote message loading aborted.");
75
+ return;
76
+ }
77
+ if (isLast) {
78
+ logger.warn("Failed to load messages for all candidate locales.", {
79
+ locale,
80
+ fallbackLocales,
81
+ });
82
+ }
83
+ else {
84
+ logger.warn(`Failed to fetch locale messages for "${candidateLocale}", trying next fallback.`);
85
+ }
86
+ logger.trace("Remote fetch error detail.", {
87
+ locale: candidateLocale,
88
+ error,
89
+ });
90
+ }
91
+ }
92
+ // --- Cache write --------------------------------------------------
93
+ if (cacheOptions.enabled && allowCacheWrite && cacheKey && messages) {
94
+ if (signal?.aborted) {
95
+ logger.debug("Remote message loading aborted before cache write.");
96
+ return;
97
+ }
98
+ await pool?.set(cacheKey, messages, cacheOptions.ttl);
99
+ }
100
+ // Final success log with resolved locale and timing
101
+ if (messages) {
102
+ logger.trace("Finished loading remote messages.", {
103
+ loadedLocale: messages ? Object.keys(messages)[0] : undefined,
104
+ duration: `${Math.round(performance.now() - start)} ms`,
105
+ });
106
+ }
107
+ return messages;
108
+ };
109
+
110
+ export { loadRemoteMessages };
@@ -0,0 +1,36 @@
1
+ /** Check if a value is a plain object (not null, not array) */
2
+ function isPlainObject(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ /**
6
+ * Check if a value is a valid **Messages** object.
7
+ *
8
+ * - Uses an iterative approach to avoid stack overflow with deeply nested objects.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * isValidMessages({ en: { hello: "Hello" } }) // true
13
+ * isValidMessages({ en: { count: 5 } }) // false
14
+ * ```
15
+ */
16
+ function isValidMessages(value) {
17
+ if (!isPlainObject(value))
18
+ return false;
19
+ const stack = [value];
20
+ while (stack.length > 0) {
21
+ const current = stack.pop();
22
+ for (const v of Object.values(current)) {
23
+ if (typeof v === "string")
24
+ continue;
25
+ if (isPlainObject(v)) {
26
+ stack.push(v);
27
+ }
28
+ else {
29
+ return false;
30
+ }
31
+ }
32
+ }
33
+ return true;
34
+ }
35
+
36
+ export { isPlainObject, isValidMessages };
@@ -0,0 +1,39 @@
1
+ import { logry } from 'logry';
2
+ import { getGlobalLoggerPool } from './global-logger-pool.js';
3
+
4
+ const DEFAULT_FORMAT_CONFIG = {
5
+ timestamp: { withDate: false },
6
+ };
7
+ const DEFAULT_RENDER_CONFIG = {
8
+ timestamp: {},
9
+ id: { visible: true, prefix: "<", suffix: ">" },
10
+ meta: { lineBreaksAfter: 1 },
11
+ };
12
+ /**
13
+ * Get a shared logger instance by id.
14
+ * - Safe across hot reloads
15
+ * - Prevents unbounded memory usage via soft LRU
16
+ */
17
+ function getLogger({ id = "default", formatConfig, renderConfig, preset, ...options }) {
18
+ const pool = getGlobalLoggerPool();
19
+ let logger = pool.get(id);
20
+ if (!logger) {
21
+ logger = logry({
22
+ id,
23
+ formatConfig: !formatConfig && !preset ? DEFAULT_FORMAT_CONFIG : formatConfig,
24
+ renderConfig: !renderConfig && !preset ? DEFAULT_RENDER_CONFIG : renderConfig,
25
+ preset,
26
+ ...options,
27
+ });
28
+ pool.set(id, logger);
29
+ // Soft LRU: keep pool size under control
30
+ if (pool.size > 1000) {
31
+ const keys = [...pool.keys()];
32
+ for (const key of keys.slice(0, 200))
33
+ pool.delete(key);
34
+ }
35
+ }
36
+ return logger;
37
+ }
38
+
39
+ export { getLogger };
@@ -0,0 +1,35 @@
1
+ import { Translator } from 'intor-translator';
2
+ import { loadMessages } from '../messages/load-messages.js';
3
+
4
+ // Implementation
5
+ async function getTranslator(options) {
6
+ const { config, locale, preKey } = options;
7
+ const messages = await loadMessages({
8
+ config,
9
+ locale,
10
+ extraOptions: options.extraOptions,
11
+ });
12
+ // Create a Translator instance
13
+ const translator = new Translator({
14
+ locale,
15
+ messages,
16
+ fallbackLocales: config.fallbackLocales,
17
+ loadingMessage: config.translator?.loadingMessage,
18
+ placeholder: config.translator?.placeholder,
19
+ handlers: options.handlers,
20
+ plugins: options.plugins,
21
+ });
22
+ const props = { messages, locale };
23
+ const scoped = translator.scoped(preKey);
24
+ return {
25
+ ...props,
26
+ hasKey: preKey ? scoped.hasKey : translator.hasKey,
27
+ t: preKey ? scoped.t : translator.t,
28
+ // NOTE:
29
+ // Return type is fully validated by overload signatures.
30
+ // Assertion here is intentional due to TS inference limitations.
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ };
33
+ }
34
+
35
+ export { getTranslator };
@@ -0,0 +1,4 @@
1
+ // Default prefix placeholder
2
+ const PREFIX_PLACEHOLDER = "{locale}";
3
+
4
+ export { PREFIX_PLACEHOLDER };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Deeply merges two objects.
3
+ * - Nested objects → merged recursively
4
+ * - Array / primitive → b overwrites a
5
+ */
6
+ const deepMerge = (a, b) => {
7
+ if (!a && !b)
8
+ return undefined;
9
+ if (!a)
10
+ return b;
11
+ if (!b)
12
+ return a;
13
+ const result = { ...a };
14
+ for (const key in b) {
15
+ if (Object.prototype.hasOwnProperty.call(b, key)) {
16
+ const av = a[key];
17
+ const bv = b[key];
18
+ if (av &&
19
+ bv &&
20
+ typeof av === "object" &&
21
+ typeof bv === "object" &&
22
+ !Array.isArray(av) &&
23
+ !Array.isArray(bv)) {
24
+ // recursive merge
25
+ result[key] = deepMerge(av, bv);
26
+ }
27
+ else {
28
+ // overwrite with primitive or array
29
+ result[key] = bv;
30
+ }
31
+ }
32
+ }
33
+ return result;
34
+ };
35
+
36
+ export { deepMerge };
@@ -0,0 +1,45 @@
1
+ const CACHE_KEY_DELIMITER = "|";
2
+ const sanitize = (k) => k
3
+ .replaceAll(/[\u200B-\u200D\uFEFF]/g, "")
4
+ .replaceAll(/[\r\n]/g, "")
5
+ .trim();
6
+ /**
7
+ * Normalizes a value into a stable cache key string.
8
+ *
9
+ * - Supports primitive values and structured array keys.
10
+ * - Produces deterministic output suitable for cache identifiers.
11
+ *
12
+ * Notes:
13
+ * - `null`, `undefined`, or empty arrays return `null`.
14
+ * - Special tokens are used for boolean, null, and undefined values
15
+ * to preserve semantic differences.
16
+ */
17
+ const normalizeCacheKey = (key, delimiter = CACHE_KEY_DELIMITER) => {
18
+ // Treat nullish values as "no cache key"
19
+ if (key === null || key === undefined)
20
+ return null;
21
+ if (Array.isArray(key)) {
22
+ // Empty array produces no meaningful cache key
23
+ if (key.length === 0)
24
+ return null;
25
+ const normalized = key.map((k) => {
26
+ // Preserve semantic differences for special values
27
+ if (k === null)
28
+ return "__null";
29
+ if (k === undefined)
30
+ return "__undefined";
31
+ if (typeof k === "boolean")
32
+ return k ? "__true" : "__false";
33
+ return sanitize(String(k));
34
+ });
35
+ // Join segments into a single deterministic cache key
36
+ return normalized.join(delimiter);
37
+ }
38
+ // Normalize boolean primitives explicitly
39
+ if (typeof key === "boolean")
40
+ return key ? "__true" : "__false";
41
+ // Fallback: stringify primitive values
42
+ return String(key);
43
+ };
44
+
45
+ export { normalizeCacheKey };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Normalize a raw pathname string to ensure consistent formatting.
3
+ *
4
+ * - Trims leading and trailing whitespace (code points ≤ 32).
5
+ * - Collapses consecutive slashes into a single slash.
6
+ * - Ensures a single leading slash and removes redundant trailing slashes.
7
+ * - Optionally removes the leading slash.
8
+ * - Avoids intermediate array allocations for performance.
9
+ */
10
+ const normalizePathname = (rawPathname, options = {}) => {
11
+ const length = rawPathname.length;
12
+ let start = 0;
13
+ let end = length - 1;
14
+ // Trim leading whitespace
15
+ while (start <= end && (rawPathname.codePointAt(start) ?? 0) <= 32)
16
+ start++;
17
+ // Trim trailing whitespace
18
+ while (end >= start && (rawPathname.codePointAt(end) ?? 0) <= 32)
19
+ end--;
20
+ if (start > end)
21
+ return "/"; // Only whitespace
22
+ let result = "";
23
+ let hasSlash = false;
24
+ for (let i = start; i <= end; i++) {
25
+ const char = rawPathname[i];
26
+ if (char === "/") {
27
+ if (!hasSlash) {
28
+ hasSlash = true;
29
+ }
30
+ }
31
+ else {
32
+ result += hasSlash || result === "" ? "/" + char : char;
33
+ hasSlash = false;
34
+ }
35
+ }
36
+ // If the result has a leading slash and we want to remove it, do so
37
+ if (options.removeLeadingSlash && result.startsWith("/")) {
38
+ result = result.slice(1);
39
+ }
40
+ return result || "/";
41
+ };
42
+
43
+ export { normalizePathname };
@@ -0,0 +1,39 @@
1
+ import { normalizePathname } from '../normalizers/normalize-pathname.js';
2
+
3
+ /**
4
+ * Returns a canonical, locale-agnostic pathname.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * // config.supportedLocales: ["en-US"]
9
+ * // config.routing.basePath: "/app"
10
+ * // config.routing.prefix: "all"
11
+ * getUnprefixedPathname(config, "/app/en-US/about" );
12
+ * // => "/about"
13
+ *```
14
+ */
15
+ function getUnprefixedPathname(config, rawPathname) {
16
+ const { routing, supportedLocales } = config;
17
+ const { basePath } = routing;
18
+ // 1. Normalize pathname
19
+ const normalizedPathname = normalizePathname(rawPathname);
20
+ // 2. Strip basePath
21
+ let prefixedPathname = normalizedPathname;
22
+ if (basePath && normalizedPathname === basePath) {
23
+ prefixedPathname = "/";
24
+ }
25
+ else if (basePath && normalizedPathname.startsWith(basePath + "/")) {
26
+ prefixedPathname = normalizedPathname.slice(basePath.length);
27
+ }
28
+ // 3. Detect locale segment
29
+ const firstSegment = prefixedPathname.split("/").find(Boolean);
30
+ const locale = firstSegment && supportedLocales.includes(firstSegment)
31
+ ? firstSegment
32
+ : undefined;
33
+ // 4. Strip locale segment
34
+ return locale
35
+ ? prefixedPathname.slice(locale.length + 1) || "/"
36
+ : prefixedPathname;
37
+ }
38
+
39
+ export { getUnprefixedPathname };
@@ -0,0 +1,38 @@
1
+ import { PREFIX_PLACEHOLDER } from '../../constants/prefix-placeholder.js';
2
+ import { normalizePathname } from '../normalizers/normalize-pathname.js';
3
+
4
+ /**
5
+ * Applies routing prefix strategy by resolving the locale placeholder.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * // config.routing.prefix: "all"
10
+ * localePrefixPathname({ config, pathname: "/app/{locale}/about", locale: "en-US" });
11
+ * // => /app/en-US/about
12
+ *
13
+ * // config.routing.prefix: "none"
14
+ * localePrefixPathname({ config, pathname: "/app/{locale}/about", locale: "en-US" });
15
+ * // => /app/about
16
+ * ```
17
+ */
18
+ const localePrefixPathname = (config, standardizedPathname, locale) => {
19
+ const { routing } = config;
20
+ const { prefix } = routing;
21
+ if (prefix !== "none" && !locale) {
22
+ throw new Error('No locale when using prefix "all", "except-default"');
23
+ }
24
+ // prefix: "all"
25
+ if (prefix === "all") {
26
+ return normalizePathname(standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale));
27
+ }
28
+ // prefix: "except-default"
29
+ if (prefix === "except-default") {
30
+ return locale === config.defaultLocale
31
+ ? normalizePathname(standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, ""))
32
+ : normalizePathname(standardizedPathname.replaceAll(PREFIX_PLACEHOLDER, locale));
33
+ }
34
+ // prefix: "none"
35
+ return normalizePathname(standardizedPathname.replaceAll(`/${PREFIX_PLACEHOLDER}`, ""));
36
+ };
37
+
38
+ export { localePrefixPathname };
@@ -0,0 +1,36 @@
1
+ import { getUnprefixedPathname } from './get-unprefixed-pathname.js';
2
+ import { localePrefixPathname } from './locale-prefix-pathname.js';
3
+ import { standardizePathname } from './standardize-pathname.js';
4
+
5
+ /**
6
+ * Localizes a pathname by composing canonicalization,
7
+ * standardization, and locale prefix strategies.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // config.supportedLocales: ["en-US"]
12
+ * // config.routing.basePath: "/app"
13
+ * // config.routing.prefix: "all"
14
+ * localePrefixPathname({ config, pathname: "/app/en-US/about", locale: "en-US" });
15
+ * // => {
16
+ * // unprefixedPathname: '/about',
17
+ * // standardizedPathname: '/app/{locale}/about',
18
+ * // localizedPathname: '/app/en-US/about'
19
+ * // }
20
+ * ```
21
+ */
22
+ const localizePathname = (config, rawPathname, locale) => {
23
+ // 1. Canonicalize: extract basePath and strip locale
24
+ const unprefixedPathname = getUnprefixedPathname(config, rawPathname);
25
+ // 2. Standardize: build a pathname with locale placeholder
26
+ const standardizedPathname = standardizePathname(config, unprefixedPathname);
27
+ // 3. Apply strategy: resolve locale prefix based on routing rules
28
+ const localizedPathname = localePrefixPathname(config, standardizedPathname, locale);
29
+ return {
30
+ unprefixedPathname,
31
+ standardizedPathname,
32
+ localizedPathname,
33
+ };
34
+ };
35
+
36
+ export { localizePathname };
@@ -0,0 +1,30 @@
1
+ import { PREFIX_PLACEHOLDER } from '../../constants/prefix-placeholder.js';
2
+ import { normalizePathname } from '../normalizers/normalize-pathname.js';
3
+
4
+ /**
5
+ * Standardizes a canonical pathname by applying the base path
6
+ * and injecting the locale placeholder.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // routing.basePath: "/app",
11
+ * standardizePathname({ config, pathname: "/cms" });
12
+ * // => "/app/{locale}/cms"
13
+ * ```
14
+ */
15
+ const standardizePathname = (config, unprefixedPathname) => {
16
+ const { routing } = config;
17
+ const { basePath } = routing;
18
+ // Normalize each segment before join to avoid redundant slashes
19
+ const parts = [
20
+ normalizePathname(basePath),
21
+ PREFIX_PLACEHOLDER,
22
+ normalizePathname(unprefixedPathname),
23
+ ];
24
+ // Avoid double slashes between segments
25
+ const standardizedPathname = parts.join("/").replaceAll(/\/{2,}/g, "/");
26
+ // Final normalization to ensure leading slash, no trailing
27
+ return normalizePathname(standardizedPathname);
28
+ };
29
+
30
+ export { standardizePathname };