@intlayer/next-intl 8.12.5-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +330 -0
  2. package/dist/cjs/_virtual/_rolldown/runtime.cjs +29 -0
  3. package/dist/cjs/client/NextIntlClientProvider.cjs +28 -0
  4. package/dist/cjs/client/NextIntlClientProvider.cjs.map +1 -0
  5. package/dist/cjs/client/helpers.cjs +66 -0
  6. package/dist/cjs/client/helpers.cjs.map +1 -0
  7. package/dist/cjs/client/index.cjs +19 -0
  8. package/dist/cjs/client/useLocale.cjs +18 -0
  9. package/dist/cjs/client/useLocale.cjs.map +1 -0
  10. package/dist/cjs/client/useTranslations.cjs +39 -0
  11. package/dist/cjs/client/useTranslations.cjs.map +1 -0
  12. package/dist/cjs/createFormatter.cjs +59 -0
  13. package/dist/cjs/createFormatter.cjs.map +1 -0
  14. package/dist/cjs/createTranslator.cjs +111 -0
  15. package/dist/cjs/createTranslator.cjs.map +1 -0
  16. package/dist/cjs/getDictionary.cjs +45 -0
  17. package/dist/cjs/getDictionary.cjs.map +1 -0
  18. package/dist/cjs/getDictionaryDynamic.cjs +35 -0
  19. package/dist/cjs/getDictionaryDynamic.cjs.map +1 -0
  20. package/dist/cjs/getTranslationsDictionary.cjs +31 -0
  21. package/dist/cjs/getTranslationsDictionary.cjs.map +1 -0
  22. package/dist/cjs/getTranslationsDictionaryDynamic.cjs +27 -0
  23. package/dist/cjs/getTranslationsDictionaryDynamic.cjs.map +1 -0
  24. package/dist/cjs/hasLocale.cjs +25 -0
  25. package/dist/cjs/hasLocale.cjs.map +1 -0
  26. package/dist/cjs/index.cjs +23 -0
  27. package/dist/cjs/middleware.cjs +37 -0
  28. package/dist/cjs/middleware.cjs.map +1 -0
  29. package/dist/cjs/navigation/Link.cjs +30 -0
  30. package/dist/cjs/navigation/Link.cjs.map +1 -0
  31. package/dist/cjs/navigation/createNavigation.cjs +40 -0
  32. package/dist/cjs/navigation/createNavigation.cjs.map +1 -0
  33. package/dist/cjs/navigation/hooks.cjs +42 -0
  34. package/dist/cjs/navigation/hooks.cjs.map +1 -0
  35. package/dist/cjs/navigation/index.cjs +10 -0
  36. package/dist/cjs/navigation/localizeHref.cjs +26 -0
  37. package/dist/cjs/navigation/localizeHref.cjs.map +1 -0
  38. package/dist/cjs/package.cjs +122 -0
  39. package/dist/cjs/package.cjs.map +1 -0
  40. package/dist/cjs/plugin/index.cjs +163 -0
  41. package/dist/cjs/plugin/index.cjs.map +1 -0
  42. package/dist/cjs/routing.cjs +30 -0
  43. package/dist/cjs/routing.cjs.map +1 -0
  44. package/dist/cjs/server/getLocale.cjs +13 -0
  45. package/dist/cjs/server/getLocale.cjs.map +1 -0
  46. package/dist/cjs/server/getMessages.cjs +30 -0
  47. package/dist/cjs/server/getMessages.cjs.map +1 -0
  48. package/dist/cjs/server/getTranslations.cjs +45 -0
  49. package/dist/cjs/server/getTranslations.cjs.map +1 -0
  50. package/dist/cjs/server/helpers.cjs +28 -0
  51. package/dist/cjs/server/helpers.cjs.map +1 -0
  52. package/dist/cjs/server/index.cjs +18 -0
  53. package/dist/cjs/server/setLocale.cjs +38 -0
  54. package/dist/cjs/server/setLocale.cjs.map +1 -0
  55. package/dist/cjs/useDictionary.cjs +45 -0
  56. package/dist/cjs/useDictionary.cjs.map +1 -0
  57. package/dist/cjs/useDictionaryDynamic.cjs +37 -0
  58. package/dist/cjs/useDictionaryDynamic.cjs.map +1 -0
  59. package/dist/cjs/useTranslationsDictionary.cjs +37 -0
  60. package/dist/cjs/useTranslationsDictionary.cjs.map +1 -0
  61. package/dist/cjs/useTranslationsDictionaryDynamic.cjs +29 -0
  62. package/dist/cjs/useTranslationsDictionaryDynamic.cjs.map +1 -0
  63. package/dist/esm/_virtual/_rolldown/runtime.mjs +8 -0
  64. package/dist/esm/client/NextIntlClientProvider.mjs +26 -0
  65. package/dist/esm/client/NextIntlClientProvider.mjs.map +1 -0
  66. package/dist/esm/client/helpers.mjs +59 -0
  67. package/dist/esm/client/helpers.mjs.map +1 -0
  68. package/dist/esm/client/index.mjs +8 -0
  69. package/dist/esm/client/useLocale.mjs +16 -0
  70. package/dist/esm/client/useLocale.mjs.map +1 -0
  71. package/dist/esm/client/useTranslations.mjs +37 -0
  72. package/dist/esm/client/useTranslations.mjs.map +1 -0
  73. package/dist/esm/createFormatter.mjs +57 -0
  74. package/dist/esm/createFormatter.mjs.map +1 -0
  75. package/dist/esm/createTranslator.mjs +108 -0
  76. package/dist/esm/createTranslator.mjs.map +1 -0
  77. package/dist/esm/getDictionary.mjs +43 -0
  78. package/dist/esm/getDictionary.mjs.map +1 -0
  79. package/dist/esm/getDictionaryDynamic.mjs +33 -0
  80. package/dist/esm/getDictionaryDynamic.mjs.map +1 -0
  81. package/dist/esm/getTranslationsDictionary.mjs +29 -0
  82. package/dist/esm/getTranslationsDictionary.mjs.map +1 -0
  83. package/dist/esm/getTranslationsDictionaryDynamic.mjs +25 -0
  84. package/dist/esm/getTranslationsDictionaryDynamic.mjs.map +1 -0
  85. package/dist/esm/hasLocale.mjs +23 -0
  86. package/dist/esm/hasLocale.mjs.map +1 -0
  87. package/dist/esm/index.mjs +10 -0
  88. package/dist/esm/middleware.mjs +34 -0
  89. package/dist/esm/middleware.mjs.map +1 -0
  90. package/dist/esm/navigation/Link.mjs +27 -0
  91. package/dist/esm/navigation/Link.mjs.map +1 -0
  92. package/dist/esm/navigation/createNavigation.mjs +37 -0
  93. package/dist/esm/navigation/createNavigation.mjs.map +1 -0
  94. package/dist/esm/navigation/hooks.mjs +39 -0
  95. package/dist/esm/navigation/hooks.mjs.map +1 -0
  96. package/dist/esm/navigation/index.mjs +5 -0
  97. package/dist/esm/navigation/localizeHref.mjs +24 -0
  98. package/dist/esm/navigation/localizeHref.mjs.map +1 -0
  99. package/dist/esm/package.mjs +119 -0
  100. package/dist/esm/package.mjs.map +1 -0
  101. package/dist/esm/plugin/index.mjs +159 -0
  102. package/dist/esm/plugin/index.mjs.map +1 -0
  103. package/dist/esm/routing.mjs +28 -0
  104. package/dist/esm/routing.mjs.map +1 -0
  105. package/dist/esm/server/getLocale.mjs +11 -0
  106. package/dist/esm/server/getLocale.mjs.map +1 -0
  107. package/dist/esm/server/getMessages.mjs +28 -0
  108. package/dist/esm/server/getMessages.mjs.map +1 -0
  109. package/dist/esm/server/getTranslations.mjs +44 -0
  110. package/dist/esm/server/getTranslations.mjs.map +1 -0
  111. package/dist/esm/server/helpers.mjs +25 -0
  112. package/dist/esm/server/helpers.mjs.map +1 -0
  113. package/dist/esm/server/index.mjs +9 -0
  114. package/dist/esm/server/setLocale.mjs +36 -0
  115. package/dist/esm/server/setLocale.mjs.map +1 -0
  116. package/dist/esm/useDictionary.mjs +43 -0
  117. package/dist/esm/useDictionary.mjs.map +1 -0
  118. package/dist/esm/useDictionaryDynamic.mjs +35 -0
  119. package/dist/esm/useDictionaryDynamic.mjs.map +1 -0
  120. package/dist/esm/useTranslationsDictionary.mjs +35 -0
  121. package/dist/esm/useTranslationsDictionary.mjs.map +1 -0
  122. package/dist/esm/useTranslationsDictionaryDynamic.mjs +27 -0
  123. package/dist/esm/useTranslationsDictionaryDynamic.mjs.map +1 -0
  124. package/dist/types/client/NextIntlClientProvider.d.ts +28 -0
  125. package/dist/types/client/NextIntlClientProvider.d.ts.map +1 -0
  126. package/dist/types/client/helpers.d.ts +45 -0
  127. package/dist/types/client/helpers.d.ts.map +1 -0
  128. package/dist/types/client/index.d.ts +7 -0
  129. package/dist/types/client/useLocale.d.ts +10 -0
  130. package/dist/types/client/useLocale.d.ts.map +1 -0
  131. package/dist/types/client/useTranslations.d.ts +74 -0
  132. package/dist/types/client/useTranslations.d.ts.map +1 -0
  133. package/dist/types/createFormatter.d.ts +15 -0
  134. package/dist/types/createFormatter.d.ts.map +1 -0
  135. package/dist/types/createTranslator.d.ts +40 -0
  136. package/dist/types/createTranslator.d.ts.map +1 -0
  137. package/dist/types/getDictionary.d.ts +23 -0
  138. package/dist/types/getDictionary.d.ts.map +1 -0
  139. package/dist/types/getDictionaryDynamic.d.ts +15 -0
  140. package/dist/types/getDictionaryDynamic.d.ts.map +1 -0
  141. package/dist/types/getTranslationsDictionary.d.ts +15 -0
  142. package/dist/types/getTranslationsDictionary.d.ts.map +1 -0
  143. package/dist/types/getTranslationsDictionaryDynamic.d.ts +12 -0
  144. package/dist/types/getTranslationsDictionaryDynamic.d.ts.map +1 -0
  145. package/dist/types/hasLocale.d.ts +20 -0
  146. package/dist/types/hasLocale.d.ts.map +1 -0
  147. package/dist/types/index.d.ts +9 -0
  148. package/dist/types/middleware.d.ts +22 -0
  149. package/dist/types/middleware.d.ts.map +1 -0
  150. package/dist/types/navigation/Link.d.ts +29 -0
  151. package/dist/types/navigation/Link.d.ts.map +1 -0
  152. package/dist/types/navigation/createNavigation.d.ts +21 -0
  153. package/dist/types/navigation/createNavigation.d.ts.map +1 -0
  154. package/dist/types/navigation/hooks.d.ts +33 -0
  155. package/dist/types/navigation/hooks.d.ts.map +1 -0
  156. package/dist/types/navigation/index.d.ts +5 -0
  157. package/dist/types/navigation/localizeHref.d.ts +23 -0
  158. package/dist/types/navigation/localizeHref.d.ts.map +1 -0
  159. package/dist/types/plugin/index.d.ts +12 -0
  160. package/dist/types/plugin/index.d.ts.map +1 -0
  161. package/dist/types/routing.d.ts +28 -0
  162. package/dist/types/routing.d.ts.map +1 -0
  163. package/dist/types/server/getLocale.d.ts +10 -0
  164. package/dist/types/server/getLocale.d.ts.map +1 -0
  165. package/dist/types/server/getMessages.d.ts +22 -0
  166. package/dist/types/server/getMessages.d.ts.map +1 -0
  167. package/dist/types/server/getTranslations.d.ts +85 -0
  168. package/dist/types/server/getTranslations.d.ts.map +1 -0
  169. package/dist/types/server/helpers.d.ts +21 -0
  170. package/dist/types/server/helpers.d.ts.map +1 -0
  171. package/dist/types/server/index.d.ts +8 -0
  172. package/dist/types/server/setLocale.d.ts +21 -0
  173. package/dist/types/server/setLocale.d.ts.map +1 -0
  174. package/dist/types/useDictionary.d.ts +22 -0
  175. package/dist/types/useDictionary.d.ts.map +1 -0
  176. package/dist/types/useDictionaryDynamic.d.ts +15 -0
  177. package/dist/types/useDictionaryDynamic.d.ts.map +1 -0
  178. package/dist/types/useTranslationsDictionary.d.ts +19 -0
  179. package/dist/types/useTranslationsDictionary.d.ts.map +1 -0
  180. package/dist/types/useTranslationsDictionaryDynamic.d.ts +12 -0
  181. package/dist/types/useTranslationsDictionaryDynamic.d.ts.map +1 -0
  182. package/package.json +142 -0
@@ -0,0 +1,29 @@
1
+ import { getDictionary } from "next-intlayer/server";
2
+
3
+ //#region src/getTranslationsDictionary.ts
4
+ /**
5
+ * Dictionary-accepting variant of `getTranslations`.
6
+ *
7
+ * Used internally by the SWC optimization: instead of looking up the dictionary
8
+ * at runtime by key, the SWC plugin pre-imports the dictionary JSON at build time
9
+ * and passes it directly here. This enables tree-shaking of unused locale content.
10
+ */
11
+ const getTranslationsDictionary = async (dictionary, namespacePrefix) => {
12
+ const content = getDictionary(dictionary);
13
+ return (lookup, params) => {
14
+ const lookupKey = namespacePrefix ? `${namespacePrefix}.${String(lookup)}` : String(lookup);
15
+ const parts = lookupKey.split(".");
16
+ let current = content;
17
+ for (const part of parts) {
18
+ if (current == null) break;
19
+ current = current[part];
20
+ }
21
+ const str = String(current ?? lookupKey);
22
+ if (!params) return str;
23
+ return str.replace(/\{(\w+)\}/g, (_, k) => params[k] != null ? String(params[k]) : `{${k}}`);
24
+ };
25
+ };
26
+
27
+ //#endregion
28
+ export { getTranslationsDictionary };
29
+ //# sourceMappingURL=getTranslationsDictionary.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTranslationsDictionary.mjs","names":[],"sources":["../../src/getTranslationsDictionary.ts"],"sourcesContent":["import type { ValidDotPathsFor } from '@intlayer/core/transpiler';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getDictionary } from 'next-intlayer/server';\n\n/**\n * Dictionary-accepting variant of `getTranslations`.\n *\n * Used internally by the SWC optimization: instead of looking up the dictionary\n * at runtime by key, the SWC plugin pre-imports the dictionary JSON at build time\n * and passes it directly here. This enables tree-shaking of unused locale content.\n */\nexport const getTranslationsDictionary = async <T extends Dictionary>(\n dictionary: T,\n namespacePrefix?: string\n) => {\n const content = getDictionary(dictionary);\n\n return <P extends ValidDotPathsFor<any>>(\n lookup: P,\n params?: Record<string, unknown>\n ): string => {\n const lookupKey = namespacePrefix\n ? `${namespacePrefix}.${String(lookup)}`\n : String(lookup);\n const parts = lookupKey.split('.');\n let current: any = content;\n for (const part of parts) {\n if (current == null) break;\n current = current[part];\n }\n const str = String(current ?? lookupKey);\n if (!params) return str;\n return str.replace(/\\{(\\w+)\\}/g, (_, k) =>\n params[k] != null ? String(params[k]) : `{${k}}`\n );\n };\n};\n"],"mappings":";;;;;;;;;;AAWA,MAAa,4BAA4B,OACvC,YACA,oBACG;CACH,MAAM,UAAU,cAAc,WAAW;AAEzC,SACE,QACA,WACW;EACX,MAAM,YAAY,kBACd,GAAG,gBAAgB,GAAG,OAAO,OAAO,KACpC,OAAO,OAAO;EAClB,MAAM,QAAQ,UAAU,MAAM,IAAI;EAClC,IAAI,UAAe;AACnB,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,WAAW,KAAM;AACrB,aAAU,QAAQ;;EAEpB,MAAM,MAAM,OAAO,WAAW,UAAU;AACxC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,IAAI,QAAQ,eAAe,GAAG,MACnC,OAAO,MAAM,OAAO,OAAO,OAAO,GAAG,GAAG,IAAI,EAAE,GAC/C"}
@@ -0,0 +1,25 @@
1
+ import { getDictionaryDynamic } from "next-intlayer/server";
2
+
3
+ //#region src/getTranslationsDictionaryDynamic.ts
4
+ /**
5
+ * Dynamic dictionary-accepting variant of `getTranslations`.
6
+ */
7
+ const getTranslationsDictionaryDynamic = async (dictionaryPromise, key, namespacePrefix) => {
8
+ const content = await getDictionaryDynamic(dictionaryPromise, key);
9
+ return (lookup, params) => {
10
+ const lookupKey = namespacePrefix ? `${namespacePrefix}.${String(lookup)}` : String(lookup);
11
+ const parts = lookupKey.split(".");
12
+ let current = content;
13
+ for (const part of parts) {
14
+ if (current == null) break;
15
+ current = current[part];
16
+ }
17
+ const str = String(current ?? lookupKey);
18
+ if (!params) return str;
19
+ return str.replace(/\{(\w+)\}/g, (_, k) => params[k] != null ? String(params[k]) : `{${k}}`);
20
+ };
21
+ };
22
+
23
+ //#endregion
24
+ export { getTranslationsDictionaryDynamic };
25
+ //# sourceMappingURL=getTranslationsDictionaryDynamic.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTranslationsDictionaryDynamic.mjs","names":[],"sources":["../../src/getTranslationsDictionaryDynamic.ts"],"sourcesContent":["import type { ValidDotPathsFor } from '@intlayer/core/transpiler';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { StrictModeLocaleMap } from '@intlayer/types/module_augmentation';\nimport { getDictionaryDynamic } from 'next-intlayer/server';\n\n/**\n * Dynamic dictionary-accepting variant of `getTranslations`.\n */\nexport const getTranslationsDictionaryDynamic = async <\n const T extends Dictionary,\n const K extends string,\n>(\n dictionaryPromise: StrictModeLocaleMap<() => Promise<T>>,\n key: K,\n namespacePrefix?: string\n) => {\n const content = await getDictionaryDynamic<T, any>(\n dictionaryPromise,\n key as any\n );\n\n return <P extends ValidDotPathsFor<any>>(\n lookup: P,\n params?: Record<string, unknown>\n ): string => {\n const lookupKey = namespacePrefix\n ? `${namespacePrefix}.${String(lookup)}`\n : String(lookup);\n const parts = lookupKey.split('.');\n let current: any = content;\n for (const part of parts) {\n if (current == null) break;\n current = current[part];\n }\n const str = String(current ?? lookupKey);\n if (!params) return str;\n return str.replace(/\\{(\\w+)\\}/g, (_, k) =>\n params[k] != null ? String(params[k]) : `{${k}}`\n );\n };\n};\n"],"mappings":";;;;;;AAQA,MAAa,mCAAmC,OAI9C,mBACA,KACA,oBACG;CACH,MAAM,UAAU,MAAM,qBACpB,mBACA,IACD;AAED,SACE,QACA,WACW;EACX,MAAM,YAAY,kBACd,GAAG,gBAAgB,GAAG,OAAO,OAAO,KACpC,OAAO,OAAO;EAClB,MAAM,QAAQ,UAAU,MAAM,IAAI;EAClC,IAAI,UAAe;AACnB,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,WAAW,KAAM;AACrB,aAAU,QAAQ;;EAEpB,MAAM,MAAM,OAAO,WAAW,UAAU;AACxC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,IAAI,QAAQ,eAAe,GAAG,MACnC,OAAO,MAAM,OAAO,OAAO,OAAO,GAAG,GAAG,IAAI,EAAE,GAC/C"}
@@ -0,0 +1,23 @@
1
+ import { internationalization } from "@intlayer/config/built";
2
+
3
+ //#region src/hasLocale.ts
4
+ /**
5
+ * Drop-in for next-intl's `hasLocale`.
6
+ *
7
+ * Checks that a locale candidate is part of the given locales list (or, when
8
+ * the list is read from routing, the locales configured in intlayer).
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { routing } from '@/i18n/routing';
13
+ *
14
+ * if (hasLocale(routing.locales, requested)) { … }
15
+ * ```
16
+ */
17
+ const hasLocale = ((locales, candidate) => {
18
+ return (locales ?? internationalization?.locales?.map(String) ?? []).includes(candidate);
19
+ });
20
+
21
+ //#endregion
22
+ export { hasLocale };
23
+ //# sourceMappingURL=hasLocale.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hasLocale.mjs","names":[],"sources":["../../src/hasLocale.ts"],"sourcesContent":["import { internationalization } from '@intlayer/config/built';\nimport type { hasLocale as _hasLocale } from 'next-intl';\n\n/**\n * Drop-in for next-intl's `hasLocale`.\n *\n * Checks that a locale candidate is part of the given locales list (or, when\n * the list is read from routing, the locales configured in intlayer).\n *\n * @example\n * ```ts\n * import { routing } from '@/i18n/routing';\n *\n * if (hasLocale(routing.locales, requested)) { … }\n * ```\n */\nexport const hasLocale: typeof _hasLocale = ((\n locales: readonly string[],\n candidate: string | undefined | null\n): boolean => {\n const availableLocales =\n locales ?? internationalization?.locales?.map(String) ?? [];\n return availableLocales.includes(candidate as string);\n}) as typeof _hasLocale;\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAa,cACX,SACA,cACY;AAGZ,SADE,WAAW,sBAAsB,SAAS,IAAI,OAAO,IAAI,EAAE,EACrC,SAAS,UAAoB"}
@@ -0,0 +1,10 @@
1
+ import { defineRouting } from "./routing.mjs";
2
+ import { hasLocale } from "./hasLocale.mjs";
3
+ import { useDictionaryDynamic } from "./useDictionaryDynamic.mjs";
4
+ import { useDictionary } from "./useDictionary.mjs";
5
+ import { IntlProvider, useExtracted, useFormatter, useMessages, useNow, useTimeZone } from "./client/helpers.mjs";
6
+ import { NextIntlClientProvider } from "./client/NextIntlClientProvider.mjs";
7
+ import { useLocale } from "./client/useLocale.mjs";
8
+ import { useTranslations } from "./client/useTranslations.mjs";
9
+
10
+ export { IntlProvider, NextIntlClientProvider, defineRouting, hasLocale, useDictionary, useDictionaryDynamic, useExtracted, useFormatter, useLocale, useMessages, useNow, useTimeZone, useTranslations };
@@ -0,0 +1,34 @@
1
+ import { intlayerMiddleware } from "next-intlayer/middleware";
2
+
3
+ //#region src/middleware.ts
4
+ /**
5
+ * Drop-in replacement for next-intl's `createMiddleware`.
6
+ *
7
+ * Returns Intlayer's proxy/middleware, which handles locale detection and
8
+ * routing from the Intlayer configuration. The `routing` argument is accepted
9
+ * for API compatibility but ignored — locales come from `intlayer.config`.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // proxy.ts (or middleware.ts on Next <= 15)
14
+ * import createMiddleware from 'next-intl/middleware';
15
+ * export default createMiddleware(routing);
16
+ * export const config = { matcher: ['/((?!api|_next|.*\\..*).*)'] };
17
+ * ```
18
+ */
19
+ const createMiddleware = (_routing) => (request, event) => {
20
+ const response = intlayerMiddleware(request, event);
21
+ if (response) {
22
+ const resolvedLocale = response.headers.get("x-intlayer-locale");
23
+ if (resolvedLocale) response.cookies.set("NEXT_LOCALE", resolvedLocale, {
24
+ path: "/",
25
+ sameSite: "lax",
26
+ maxAge: 3600 * 24 * 365
27
+ });
28
+ }
29
+ return response;
30
+ };
31
+
32
+ //#endregion
33
+ export { createMiddleware, createMiddleware as default };
34
+ //# sourceMappingURL=middleware.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.mjs","names":[],"sources":["../../src/middleware.ts"],"sourcesContent":["import type { NextFetchEvent, NextRequest } from 'next/server';\nimport type _createMiddleware from 'next-intl/middleware';\nimport { intlayerMiddleware } from 'next-intlayer/middleware';\n\n/**\n * Drop-in replacement for next-intl's `createMiddleware`.\n *\n * Returns Intlayer's proxy/middleware, which handles locale detection and\n * routing from the Intlayer configuration. The `routing` argument is accepted\n * for API compatibility but ignored — locales come from `intlayer.config`.\n *\n * @example\n * ```ts\n * // proxy.ts (or middleware.ts on Next <= 15)\n * import createMiddleware from 'next-intl/middleware';\n * export default createMiddleware(routing);\n * export const config = { matcher: ['/((?!api|_next|.*\\\\..*).*)'] };\n * ```\n */\nexport const createMiddleware: typeof _createMiddleware =\n (_routing?: unknown) => (request: NextRequest, event?: NextFetchEvent) => {\n const response = intlayerMiddleware(request, event);\n\n if (response) {\n // Intlayer middleware writes the resolved locale to the x-intlayer-locale header\n // We read it and explicitly set the NEXT_LOCALE cookie to maintain compatibility with next-intl\n const resolvedLocale = response.headers.get('x-intlayer-locale');\n if (resolvedLocale) {\n response.cookies.set('NEXT_LOCALE', resolvedLocale, {\n path: '/',\n sameSite: 'lax',\n maxAge: 60 * 60 * 24 * 365,\n });\n }\n }\n\n return response;\n };\n\nexport default createMiddleware;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,MAAa,oBACV,cAAwB,SAAsB,UAA2B;CACxE,MAAM,WAAW,mBAAmB,SAAS,MAAM;AAEnD,KAAI,UAAU;EAGZ,MAAM,iBAAiB,SAAS,QAAQ,IAAI,oBAAoB;AAChE,MAAI,eACF,UAAS,QAAQ,IAAI,eAAe,gBAAgB;GAClD,MAAM;GACN,UAAU;GACV,QAAQ,OAAU,KAAK;GACxB,CAAC;;AAIN,QAAO"}
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+
3
+ import { localizeHref } from "./localizeHref.mjs";
4
+ import { useLocale } from "next-intlayer";
5
+ import { forwardRef } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ import NextLink from "next/link";
8
+
9
+ //#region src/navigation/Link.tsx
10
+ /**
11
+ * Drop-in for the `Link` returned by next-intl's `createNavigation`. Prefixes
12
+ * `href` with the active locale (or the `locale` prop) before delegating to
13
+ * `next/link`.
14
+ */
15
+ const Link = forwardRef(({ href, locale, ...rest }, ref) => {
16
+ const { locale: currentLocale } = useLocale();
17
+ return /* @__PURE__ */ jsx(NextLink, {
18
+ ref,
19
+ href: localizeHref(href, locale ?? currentLocale),
20
+ ...rest
21
+ });
22
+ });
23
+ Link.displayName = "Link";
24
+
25
+ //#endregion
26
+ export { Link };
27
+ //# sourceMappingURL=Link.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.mjs","names":[],"sources":["../../../src/navigation/Link.tsx"],"sourcesContent":["'use client';\n\nimport NextLink from 'next/link';\nimport { useLocale } from 'next-intlayer';\nimport { type ComponentPropsWithoutRef, forwardRef, type Ref } from 'react';\nimport { localizeHref, type NextIntlHref } from './localizeHref';\n\n/**\n * Props for the compat `Link`: identical to `next/link` except `href` accepts a\n * `next-intl` href and an optional `locale` overrides the current one.\n */\nexport type LinkProps = Omit<\n ComponentPropsWithoutRef<typeof NextLink>,\n 'href' | 'locale'\n> & {\n href: NextIntlHref;\n locale?: string;\n};\n\n/**\n * Drop-in for the `Link` returned by next-intl's `createNavigation`. Prefixes\n * `href` with the active locale (or the `locale` prop) before delegating to\n * `next/link`.\n */\nexport const Link = forwardRef(\n ({ href, locale, ...rest }: LinkProps, ref: Ref<HTMLAnchorElement>) => {\n const { locale: currentLocale } = useLocale();\n const targetLocale = locale ?? (currentLocale as string);\n\n return (\n <NextLink ref={ref} href={localizeHref(href, targetLocale)} {...rest} />\n );\n }\n);\n\nLink.displayName = 'Link';\n"],"mappings":";;;;;;;;;;;;;;AAwBA,MAAa,OAAO,YACjB,EAAE,MAAM,QAAQ,GAAG,QAAmB,QAAgC;CACrE,MAAM,EAAE,QAAQ,kBAAkB,WAAW;AAG7C,QACE,oBAAC,UAAD;EAAe;EAAK,MAAM,aAAa,MAHpB,UAAW,cAG4B;EAAE,GAAI;EAAQ;EAG7E;AAED,KAAK,cAAc"}
@@ -0,0 +1,37 @@
1
+ import { localizeHref } from "./localizeHref.mjs";
2
+ import { Link } from "./Link.mjs";
3
+ import { usePathname as usePathname$1, useRouter as useRouter$1 } from "./hooks.mjs";
4
+ import { permanentRedirect, redirect } from "next/navigation";
5
+
6
+ //#region src/navigation/createNavigation.ts
7
+ /**
8
+ * Drop-in replacement for next-intl's `createNavigation`.
9
+ *
10
+ * Returns locale-aware navigation APIs (`Link`, `usePathname`, `useRouter`,
11
+ * `getPathname`, `redirect`, `permanentRedirect`) backed by Intlayer's routing
12
+ * configuration. The `routing` argument is accepted for API compatibility;
13
+ * locales come from the Intlayer configuration.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * export const { Link, redirect, usePathname, useRouter, getPathname } =
18
+ * createNavigation();
19
+ * ```
20
+ */
21
+ const createNavigation = (_routing) => {
22
+ const getPathname = ({ href, locale }) => localizeHref(href, locale);
23
+ const redirect$1 = ({ href, locale }, type) => redirect(localizeHref(href, locale), type);
24
+ const permanentRedirect$1 = ({ href, locale }, type) => permanentRedirect(localizeHref(href, locale), type);
25
+ return {
26
+ Link,
27
+ usePathname: usePathname$1,
28
+ useRouter: useRouter$1,
29
+ getPathname,
30
+ redirect: redirect$1,
31
+ permanentRedirect: permanentRedirect$1
32
+ };
33
+ };
34
+
35
+ //#endregion
36
+ export { createNavigation, createNavigation as default };
37
+ //# sourceMappingURL=createNavigation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createNavigation.mjs","names":["redirect","nextRedirect","permanentRedirect","nextPermanentRedirect"],"sources":["../../../src/navigation/createNavigation.ts"],"sourcesContent":["import {\n permanentRedirect as nextPermanentRedirect,\n redirect as nextRedirect,\n} from 'next/navigation';\nimport type { createNavigation as _createNavigation } from 'next-intl/navigation';\nimport { usePathname, useRouter } from './hooks';\nimport { Link } from './Link';\nimport { localizeHref, type NextIntlHref } from './localizeHref';\n\n/** Arguments shared by `getPathname`, `redirect` and `permanentRedirect`. */\ntype LocalizedHrefArgs = { href: NextIntlHref; locale: string };\n\n/** The optional `RedirectType` accepted by `next/navigation`'s redirect APIs. */\ntype RedirectTypeArg = Parameters<typeof nextRedirect>[1];\n\n/**\n * Drop-in replacement for next-intl's `createNavigation`.\n *\n * Returns locale-aware navigation APIs (`Link`, `usePathname`, `useRouter`,\n * `getPathname`, `redirect`, `permanentRedirect`) backed by Intlayer's routing\n * configuration. The `routing` argument is accepted for API compatibility;\n * locales come from the Intlayer configuration.\n *\n * @example\n * ```ts\n * export const { Link, redirect, usePathname, useRouter, getPathname } =\n * createNavigation();\n * ```\n */\nexport const createNavigation: typeof _createNavigation = (\n _routing?: unknown\n) => {\n const getPathname = ({ href, locale }: LocalizedHrefArgs): string =>\n localizeHref(href, locale);\n\n const redirect = (\n { href, locale }: LocalizedHrefArgs,\n type?: RedirectTypeArg\n ) => nextRedirect(localizeHref(href, locale), type);\n\n const permanentRedirect = (\n { href, locale }: LocalizedHrefArgs,\n type?: RedirectTypeArg\n ) => nextPermanentRedirect(localizeHref(href, locale), type);\n\n return {\n Link: Link as ReturnType<typeof _createNavigation>['Link'],\n usePathname,\n useRouter,\n getPathname,\n redirect,\n permanentRedirect,\n } as ReturnType<typeof _createNavigation>;\n};\n\nexport default createNavigation;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,oBACX,aACG;CACH,MAAM,eAAe,EAAE,MAAM,aAC3B,aAAa,MAAM,OAAO;CAE5B,MAAMA,cACJ,EAAE,MAAM,UACR,SACGC,SAAa,aAAa,MAAM,OAAO,EAAE,KAAK;CAEnD,MAAMC,uBACJ,EAAE,MAAM,UACR,SACGC,kBAAsB,aAAa,MAAM,OAAO,EAAE,KAAK;AAE5D,QAAO;EACC;EACN;EACA;EACA;EACA;EACA;EACD"}
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+
3
+ import { localizeHref } from "./localizeHref.mjs";
4
+ import { useLocale } from "next-intlayer";
5
+ import { usePathname as usePathname$1, useRouter as useRouter$1 } from "next/navigation";
6
+
7
+ //#region src/navigation/hooks.ts
8
+ /**
9
+ * Drop-in for the `usePathname` returned by next-intl's `createNavigation`.
10
+ * Returns the current pathname with the locale prefix stripped.
11
+ */
12
+ const usePathname = () => {
13
+ const pathname = usePathname$1();
14
+ const { locale } = useLocale();
15
+ const prefix = `/${locale}`;
16
+ if (pathname === prefix) return "/";
17
+ if (pathname.startsWith(`${prefix}/`)) return pathname.slice(prefix.length);
18
+ return pathname;
19
+ };
20
+ /**
21
+ * Drop-in for the `useRouter` returned by next-intl's `createNavigation`.
22
+ * Wraps the Next.js router so `push`/`replace`/`prefetch` localize their href
23
+ * (honouring an optional `locale` option) before navigating.
24
+ */
25
+ const useRouter = () => {
26
+ const router = useRouter$1();
27
+ const { locale: currentLocale } = useLocale();
28
+ const localize = (href, locale) => localizeHref(href, locale ?? currentLocale);
29
+ return {
30
+ ...router,
31
+ push: (href, options) => router.push(localize(href, options?.locale), options),
32
+ replace: (href, options) => router.replace(localize(href, options?.locale), options),
33
+ prefetch: (href, options) => router.prefetch(localize(href, options?.locale))
34
+ };
35
+ };
36
+
37
+ //#endregion
38
+ export { usePathname, useRouter };
39
+ //# sourceMappingURL=hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.mjs","names":["useNextPathname","useNextRouter"],"sources":["../../../src/navigation/hooks.ts"],"sourcesContent":["'use client';\n\nimport {\n usePathname as useNextPathname,\n useRouter as useNextRouter,\n} from 'next/navigation';\nimport { useLocale } from 'next-intlayer';\nimport { localizeHref, type NextIntlHref } from './localizeHref';\n\n/**\n * Options accepted by the locale-aware router methods: the standard Next.js\n * navigate options plus an optional target `locale`.\n */\ntype NavigateOptions = { locale?: string } & Record<string, unknown>;\n\n/**\n * Drop-in for the `usePathname` returned by next-intl's `createNavigation`.\n * Returns the current pathname with the locale prefix stripped.\n */\nexport const usePathname = (): string => {\n const pathname = useNextPathname();\n const { locale } = useLocale();\n const prefix = `/${locale}`;\n\n if (pathname === prefix) return '/';\n if (pathname.startsWith(`${prefix}/`)) return pathname.slice(prefix.length);\n return pathname;\n};\n\n/**\n * Drop-in for the `useRouter` returned by next-intl's `createNavigation`.\n * Wraps the Next.js router so `push`/`replace`/`prefetch` localize their href\n * (honouring an optional `locale` option) before navigating.\n */\nexport const useRouter = () => {\n const router = useNextRouter();\n const { locale: currentLocale } = useLocale();\n\n const localize = (href: NextIntlHref, locale?: string): string =>\n localizeHref(href, locale ?? (currentLocale as string));\n\n return {\n ...router,\n push: (href: NextIntlHref, options?: NavigateOptions) =>\n router.push(\n localize(href, options?.locale),\n options as Parameters<typeof router.push>[1]\n ),\n replace: (href: NextIntlHref, options?: NavigateOptions) =>\n router.replace(\n localize(href, options?.locale),\n options as Parameters<typeof router.replace>[1]\n ),\n prefetch: (href: NextIntlHref, options?: NavigateOptions) =>\n router.prefetch(localize(href, options?.locale)),\n };\n};\n"],"mappings":";;;;;;;;;;;AAmBA,MAAa,oBAA4B;CACvC,MAAM,WAAWA,eAAiB;CAClC,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,SAAS,IAAI;AAEnB,KAAI,aAAa,OAAQ,QAAO;AAChC,KAAI,SAAS,WAAW,GAAG,OAAO,GAAG,CAAE,QAAO,SAAS,MAAM,OAAO,OAAO;AAC3E,QAAO;;;;;;;AAQT,MAAa,kBAAkB;CAC7B,MAAM,SAASC,aAAe;CAC9B,MAAM,EAAE,QAAQ,kBAAkB,WAAW;CAE7C,MAAM,YAAY,MAAoB,WACpC,aAAa,MAAM,UAAW,cAAyB;AAEzD,QAAO;EACL,GAAG;EACH,OAAO,MAAoB,YACzB,OAAO,KACL,SAAS,MAAM,SAAS,OAAO,EAC/B,QACD;EACH,UAAU,MAAoB,YAC5B,OAAO,QACL,SAAS,MAAM,SAAS,OAAO,EAC/B,QACD;EACH,WAAW,MAAoB,YAC7B,OAAO,SAAS,SAAS,MAAM,SAAS,OAAO,CAAC;EACnD"}
@@ -0,0 +1,5 @@
1
+ import { Link } from "./Link.mjs";
2
+ import { usePathname, useRouter } from "./hooks.mjs";
3
+ import { createNavigation } from "./createNavigation.mjs";
4
+
5
+ export { Link, createNavigation, createNavigation as default, usePathname, useRouter };
@@ -0,0 +1,24 @@
1
+ import { getLocalizedUrl } from "@intlayer/core/localization";
2
+
3
+ //#region src/navigation/localizeHref.ts
4
+ /**
5
+ * Prefix a `next-intl` href with the given locale using Intlayer's
6
+ * `getLocalizedUrl`, preserving any query parameters.
7
+ *
8
+ * @param href - The target href (string or `{ pathname, query }`).
9
+ * @param locale - The locale to localize the href for.
10
+ * @returns The localized URL string.
11
+ */
12
+ const localizeHref = (href, locale) => {
13
+ const localizedPathname = getLocalizedUrl(typeof href === "string" ? href : href.pathname, locale);
14
+ if (typeof href === "string" || !href.query) return localizedPathname;
15
+ const searchParams = new URLSearchParams();
16
+ for (const [key, value] of Object.entries(href.query)) if (Array.isArray(value)) for (const entry of value) searchParams.append(key, String(entry));
17
+ else searchParams.append(key, String(value));
18
+ const queryString = searchParams.toString();
19
+ return queryString ? `${localizedPathname}?${queryString}` : localizedPathname;
20
+ };
21
+
22
+ //#endregion
23
+ export { localizeHref };
24
+ //# sourceMappingURL=localizeHref.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localizeHref.mjs","names":[],"sources":["../../../src/navigation/localizeHref.ts"],"sourcesContent":["import { getLocalizedUrl } from '@intlayer/core/localization';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\n\n/**\n * A `next-intl` navigation href: either a pathname string or an object with a\n * `pathname` and optional `query`. The `pathnames` (typed routes) feature is\n * accepted for API compatibility but not interpolated.\n */\nexport type NextIntlHref =\n | string\n | {\n pathname: string;\n query?: Record<string, string | number | (string | number)[]>;\n params?: Record<string, string | number | (string | number)[]>;\n };\n\n/**\n * Prefix a `next-intl` href with the given locale using Intlayer's\n * `getLocalizedUrl`, preserving any query parameters.\n *\n * @param href - The target href (string or `{ pathname, query }`).\n * @param locale - The locale to localize the href for.\n * @returns The localized URL string.\n */\nexport const localizeHref = (href: NextIntlHref, locale: string): string => {\n const pathname = typeof href === 'string' ? href : href.pathname;\n const localizedPathname = getLocalizedUrl(pathname, locale as LocalesValues);\n\n if (typeof href === 'string' || !href.query) {\n return localizedPathname;\n }\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(href.query)) {\n if (Array.isArray(value)) {\n for (const entry of value) {\n searchParams.append(key, String(entry));\n }\n } else {\n searchParams.append(key, String(value));\n }\n }\n\n const queryString = searchParams.toString();\n return queryString\n ? `${localizedPathname}?${queryString}`\n : localizedPathname;\n};\n"],"mappings":";;;;;;;;;;;AAwBA,MAAa,gBAAgB,MAAoB,WAA2B;CAE1E,MAAM,oBAAoB,gBADT,OAAO,SAAS,WAAW,OAAO,KAAK,UACJ,OAAwB;AAE5E,KAAI,OAAO,SAAS,YAAY,CAAC,KAAK,MACpC,QAAO;CAGT,MAAM,eAAe,IAAI,iBAAiB;AAC1C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,MAAM,CACnD,KAAI,MAAM,QAAQ,MAAM,CACtB,MAAK,MAAM,SAAS,MAClB,cAAa,OAAO,KAAK,OAAO,MAAM,CAAC;KAGzC,cAAa,OAAO,KAAK,OAAO,MAAM,CAAC;CAI3C,MAAM,cAAc,aAAa,UAAU;AAC3C,QAAO,cACH,GAAG,kBAAkB,GAAG,gBACxB"}
@@ -0,0 +1,119 @@
1
+ import { __commonJSMin } from "./_virtual/_rolldown/runtime.mjs";
2
+
3
+ //#region package.json
4
+ var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5
+ module.exports = {
6
+ "name": "@intlayer/next-intl",
7
+ "version": "8.12.2",
8
+ "private": false,
9
+ "description": "next-intl API adapter for intlayer — useTranslations, useLocale, getTranslations, getLocale, NextIntlClientProvider backed by next-intlayer",
10
+ "keywords": [
11
+ "intlayer",
12
+ "next-intl",
13
+ "next.js",
14
+ "react",
15
+ "i18n",
16
+ "adapter",
17
+ "compatibility"
18
+ ],
19
+ "homepage": "https://intlayer.org",
20
+ "bugs": { "url": "https://github.com/aymericzip/intlayer/issues" },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/aymericzip/intlayer.git"
24
+ },
25
+ "license": "Apache-2.0",
26
+ "author": {
27
+ "name": "Aymeric PINEAU",
28
+ "url": "https://github.com/aymericzip"
29
+ },
30
+ "contributors": [{
31
+ "name": "Aymeric Pineau",
32
+ "email": "ay.pineau@gmail.com",
33
+ "url": "https://github.com/aymericzip"
34
+ }],
35
+ "sideEffects": false,
36
+ "exports": {
37
+ ".": {
38
+ "types": "./dist/types/index.d.ts",
39
+ "require": "./dist/cjs/index.cjs",
40
+ "import": "./dist/esm/index.mjs"
41
+ },
42
+ "./server": {
43
+ "types": "./dist/types/server/index.d.ts",
44
+ "require": "./dist/cjs/server/index.cjs",
45
+ "import": "./dist/esm/server/index.mjs"
46
+ },
47
+ "./routing": {
48
+ "types": "./dist/types/routing.d.ts",
49
+ "require": "./dist/cjs/routing.cjs",
50
+ "import": "./dist/esm/routing.mjs"
51
+ },
52
+ "./plugin": {
53
+ "types": "./dist/types/plugin/index.d.ts",
54
+ "require": "./dist/cjs/plugin/index.cjs",
55
+ "import": "./dist/esm/plugin/index.mjs"
56
+ },
57
+ "./package.json": "./package.json"
58
+ },
59
+ "main": "dist/cjs/index.cjs",
60
+ "module": "dist/esm/index.mjs",
61
+ "types": "dist/types/index.d.ts",
62
+ "typesVersions": { "*": {
63
+ "server": ["./dist/types/server/index.d.ts"],
64
+ "routing": ["./dist/types/routing.d.ts"],
65
+ "plugin": ["./dist/types/plugin/index.d.ts"]
66
+ } },
67
+ "files": ["./dist", "./package.json"],
68
+ "scripts": {
69
+ "build": "bun --bun tsdown --config tsdown.config.ts",
70
+ "build:ci": "bun --bun tsdown --config tsdown.config.ts",
71
+ "clean": "bun --bun rimraf ./dist .turbo",
72
+ "dev": "bun --bun tsdown --config tsdown.config.ts --watch",
73
+ "format": "bun --bun biome format . --check",
74
+ "format:fix": "bun --bun biome format --write .",
75
+ "lint": "bun --bun biome lint .",
76
+ "lint:fix": "bun --bun biome lint --write .",
77
+ "prepublish": "cp -f ../../../README.md ./README.md",
78
+ "publish": "bun publish || true",
79
+ "publish:canary": "bun publish --access public --tag canary || true",
80
+ "publish:latest": "bun publish --access public --tag latest || true",
81
+ "test": "bun --bun vitest run",
82
+ "test:watch": "bun --bun vitest",
83
+ "typecheck": "tsc --noEmit --project tsconfig.types.json"
84
+ },
85
+ "dependencies": {
86
+ "@intlayer/config": "workspace:*",
87
+ "@intlayer/core": "workspace:*",
88
+ "@intlayer/dictionaries-entry": "workspace:*",
89
+ "@intlayer/types": "workspace:*",
90
+ "next-intlayer": "workspace:*",
91
+ "react-intlayer": "workspace:*"
92
+ },
93
+ "devDependencies": {
94
+ "@types/node": "25.9.2",
95
+ "@types/react": "19.2.17",
96
+ "@utils/ts-config": "workspace:*",
97
+ "@utils/ts-config-types": "workspace:*",
98
+ "@utils/tsdown-config": "workspace:*",
99
+ "next-intl": "4.13.0",
100
+ "rimraf": "6.1.3",
101
+ "tsdown": "0.21.10",
102
+ "typescript": "6.0.3",
103
+ "vitest": "4.1.8"
104
+ },
105
+ "peerDependencies": {
106
+ "next": ">=14.0.0",
107
+ "next-intl": ">=3.0.0",
108
+ "react": ">=16.0.0",
109
+ "react-dom": ">=16.0.0"
110
+ },
111
+ "engines": { "node": ">=14.18" }
112
+ };
113
+ }));
114
+
115
+ //#endregion
116
+ export default require_package();
117
+
118
+ export { require_package };
119
+ //# sourceMappingURL=package.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.mjs","names":[],"sources":["../../package.json"],"sourcesContent":[""],"mappings":""}
@@ -0,0 +1,159 @@
1
+ import { withIntlayer } from "next-intlayer/server";
2
+ import * as ANSIColors from "@intlayer/config/colors";
3
+ import { colorize, getAppLogger } from "@intlayer/config/logger";
4
+ import { createRequire } from "node:module";
5
+ import { dirname, join, relative, resolve, sep } from "node:path";
6
+ import { runOnce } from "@intlayer/chokidar/utils";
7
+ import { getConfiguration } from "@intlayer/config/node";
8
+
9
+ //#region src/plugin/index.ts
10
+ /**
11
+ * `require` that works in both the CJS and ESM builds of this plugin.
12
+ * `import.meta.url` is rewritten to the module path in the CJS output by the
13
+ * bundler, so `createRequire` resolves correctly in either format.
14
+ */
15
+ const compatRequire = createRequire(import.meta.url);
16
+ /**
17
+ * Maps each original `next-intl` import specifier to the `@intlayer/next-intl`
18
+ * specifier that should serve it instead.
19
+ */
20
+ const ALIAS_ENTRIES = [
21
+ {
22
+ request: "next-intl/server",
23
+ replacement: "@intlayer/next-intl/server"
24
+ },
25
+ {
26
+ request: "next-intl/routing",
27
+ replacement: "@intlayer/next-intl/routing"
28
+ },
29
+ {
30
+ request: "next-intl/navigation",
31
+ replacement: "@intlayer/next-intl/navigation"
32
+ },
33
+ {
34
+ request: "next-intl/middleware",
35
+ replacement: "@intlayer/next-intl/middleware"
36
+ },
37
+ {
38
+ request: "next-intl",
39
+ replacement: "@intlayer/next-intl"
40
+ }
41
+ ];
42
+ /**
43
+ * Split a package specifier into its package name and export subpath.
44
+ *
45
+ * @param specifier - e.g. `@intlayer/next-intl/server` or `next-intl`.
46
+ * @returns `{ packageName, exportKey }` where `exportKey` is the `exports` map
47
+ * key (`.` for the package root).
48
+ */
49
+ const splitSpecifier = (specifier) => {
50
+ const segments = specifier.split("/");
51
+ const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? specifier;
52
+ const subpath = specifier.slice(packageName?.length);
53
+ return {
54
+ packageName,
55
+ exportKey: subpath === "" ? "." : `.${subpath}`
56
+ };
57
+ };
58
+ /**
59
+ * Resolve the absolute path of a package export, preferring the ESM (`import`)
60
+ * condition so Turbopack and modern bundlers load the `.mjs` build (which keeps
61
+ * the `"use client"` directives) rather than the CommonJS fallback.
62
+ *
63
+ * Both Turbopack and webpack ignore alias values that are bare package
64
+ * specifiers, so the aliases must point at real files.
65
+ *
66
+ * @param specifier - Package specifier, e.g. `@intlayer/next-intl/server`.
67
+ * @returns Absolute path to the resolved module file.
68
+ */
69
+ const resolveEsmPath = (specifier) => {
70
+ const { packageName, exportKey } = splitSpecifier(specifier);
71
+ const packageJson = compatRequire(`${packageName}/package.json`);
72
+ const packageDir = dirname(compatRequire.resolve(`${packageName}/package.json`));
73
+ const exportEntry = packageJson.exports?.[exportKey];
74
+ const relativeFile = typeof exportEntry === "string" ? exportEntry : exportEntry?.import ?? exportEntry?.require ?? exportEntry?.default;
75
+ if (!relativeFile) return compatRequire.resolve(specifier);
76
+ return resolve(packageDir, relativeFile);
77
+ };
78
+ /**
79
+ * Format an absolute path as a project-root-relative specifier (prefixed with
80
+ * `./` and using forward slashes). Turbopack only honours `resolveAlias` values
81
+ * that are project-root-relative paths — bare specifiers are ignored and
82
+ * absolute paths are misread as root-relative. Mirrors `withIntlayer`'s
83
+ * Turbopack alias formatter.
84
+ *
85
+ * @param absolutePath - Absolute path to the target module file.
86
+ * @returns Relative specifier such as `./node_modules/@intlayer/next-intl/...`.
87
+ */
88
+ const toTurbopackAlias = (absolutePath) => `./${relative(process.cwd(), absolutePath).split(sep).join("/")}`;
89
+ const NEXT_INTL_SWC_CALLERS = [{
90
+ callerName: "useTranslations",
91
+ importSources: ["next-intl", "@intlayer/next-intl"],
92
+ namespaceArgIndex: 0,
93
+ staticReplacement: "useDictionary",
94
+ dynamicReplacement: "useDictionaryDynamic"
95
+ }, {
96
+ callerName: "getTranslations",
97
+ importSources: ["next-intl/server", "@intlayer/next-intl/server"],
98
+ namespaceArgIndex: 0,
99
+ staticReplacement: "getDictionary",
100
+ dynamicReplacement: "getDictionaryDynamic"
101
+ }];
102
+ /**
103
+ * A Next.js plugin for next-intl compat that wraps next-intlayer's plugin
104
+ * and configures resolve aliases so `next-intl` imports are served by
105
+ * `@intlayer/next-intl`.
106
+ */
107
+ const createNextIntlPlugin = (_i18nPath) => {
108
+ return async (nextConfig = {}) => {
109
+ const intlayerConfig = getConfiguration();
110
+ const appLogger = getAppLogger(intlayerConfig);
111
+ runOnce(join(intlayerConfig?.system?.baseDir ?? process.cwd(), ".intlayer", "cache", "intlayer-issues-invitation.lock"), () => {
112
+ appLogger([colorize("Please report any issues you met on GitHub:", ANSIColors.GREY), colorize("https://github.com/aymericzip/intlayer/issues", ANSIColors.GREY_LIGHT)]);
113
+ }, { cacheTimeoutMs: 1e3 * 60 * 60 });
114
+ const customWebpack = nextConfig.webpack;
115
+ const resolvedTargets = ALIAS_ENTRIES.map(({ request, replacement }) => ({
116
+ request,
117
+ absolutePath: resolveEsmPath(replacement)
118
+ }));
119
+ const webpackAlias = Object.fromEntries(resolvedTargets.map(({ request, absolutePath }) => [request, absolutePath]));
120
+ const turboAlias = Object.fromEntries(resolvedTargets.map(({ request, absolutePath }) => [request, toTurbopackAlias(absolutePath)]));
121
+ const aliasConfig = { webpack: (config, options) => {
122
+ config.resolve.alias = {
123
+ ...config.resolve.alias,
124
+ ...webpackAlias
125
+ };
126
+ if (typeof customWebpack === "function") return customWebpack(config, options);
127
+ return config;
128
+ } };
129
+ const mergedConfig = {
130
+ ...nextConfig,
131
+ ...aliasConfig,
132
+ turbopack: {
133
+ ...nextConfig.turbopack ?? {},
134
+ resolveAlias: {
135
+ ...nextConfig.turbopack?.resolveAlias ?? {},
136
+ ...turboAlias
137
+ }
138
+ }
139
+ };
140
+ let hasUserDefinedStorage = false;
141
+ try {
142
+ hasUserDefinedStorage = !!(intlayerConfig?.routing && "storage" in intlayerConfig.routing && intlayerConfig.routing.storage !== void 0);
143
+ } catch {}
144
+ return withIntlayer(mergedConfig, hasUserDefinedStorage ? { swcExtraCallers: NEXT_INTL_SWC_CALLERS } : {
145
+ override: { routing: { storage: [{
146
+ type: "cookie",
147
+ name: "NEXT_LOCALE"
148
+ }, {
149
+ type: "header",
150
+ name: "x-intlayer-locale"
151
+ }] } },
152
+ swcExtraCallers: NEXT_INTL_SWC_CALLERS
153
+ });
154
+ };
155
+ };
156
+
157
+ //#endregion
158
+ export { createNextIntlPlugin, createNextIntlPlugin as default };
159
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport { runOnce } from '@intlayer/chokidar/utils';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport type { NextConfig } from 'next';\nimport { withIntlayer } from 'next-intlayer/server';\n\n/**\n * `require` that works in both the CJS and ESM builds of this plugin.\n * `import.meta.url` is rewritten to the module path in the CJS output by the\n * bundler, so `createRequire` resolves correctly in either format.\n */\nconst compatRequire = createRequire(import.meta.url);\n\n/**\n * Maps each original `next-intl` import specifier to the `@intlayer/next-intl`\n * specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-intl/server', replacement: '@intlayer/next-intl/server' },\n { request: 'next-intl/routing', replacement: '@intlayer/next-intl/routing' },\n {\n request: 'next-intl/navigation',\n replacement: '@intlayer/next-intl/navigation',\n },\n {\n request: 'next-intl/middleware',\n replacement: '@intlayer/next-intl/middleware',\n },\n { request: 'next-intl', replacement: '@intlayer/next-intl' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/next-intl/server` or `next-intl`.\n * @returns `{ packageName, exportKey }` where `exportKey` is the `exports` map\n * key (`.` for the package root).\n */\nconst splitSpecifier = (\n specifier: string\n): { packageName: string; exportKey: string } => {\n const segments = specifier.split('/');\n const packageName = specifier.startsWith('@')\n ? segments.slice(0, 2).join('/')\n : (segments[0] ?? specifier);\n const subpath = specifier.slice(packageName?.length);\n return { packageName, exportKey: subpath === '' ? '.' : `.${subpath}` };\n};\n\n/**\n * Resolve the absolute path of a package export, preferring the ESM (`import`)\n * condition so Turbopack and modern bundlers load the `.mjs` build (which keeps\n * the `\"use client\"` directives) rather than the CommonJS fallback.\n *\n * Both Turbopack and webpack ignore alias values that are bare package\n * specifiers, so the aliases must point at real files.\n *\n * @param specifier - Package specifier, e.g. `@intlayer/next-intl/server`.\n * @returns Absolute path to the resolved module file.\n */\nconst resolveEsmPath = (specifier: string): string => {\n const { packageName, exportKey } = splitSpecifier(specifier);\n const packageJson = compatRequire(`${packageName}/package.json`) as {\n exports?: Record<\n string,\n string | { import?: string; require?: string; default?: string }\n >;\n };\n const packageDir = dirname(\n compatRequire.resolve(`${packageName}/package.json`)\n );\n\n const exportEntry = packageJson.exports?.[exportKey];\n const relativeFile =\n typeof exportEntry === 'string'\n ? exportEntry\n : (exportEntry?.import ?? exportEntry?.require ?? exportEntry?.default);\n\n // Fall back to Node resolution if the exports map is unexpected.\n if (!relativeFile) return compatRequire.resolve(specifier);\n\n return resolve(packageDir, relativeFile);\n};\n\n/**\n * Format an absolute path as a project-root-relative specifier (prefixed with\n * `./` and using forward slashes). Turbopack only honours `resolveAlias` values\n * that are project-root-relative paths — bare specifiers are ignored and\n * absolute paths are misread as root-relative. Mirrors `withIntlayer`'s\n * Turbopack alias formatter.\n *\n * @param absolutePath - Absolute path to the target module file.\n * @returns Relative specifier such as `./node_modules/@intlayer/next-intl/...`.\n */\nconst toTurbopackAlias = (absolutePath: string): string =>\n `./${relative(process.cwd(), absolutePath).split(sep).join('/')}`;\n\nconst NEXT_INTL_SWC_CALLERS = [\n {\n callerName: 'useTranslations',\n importSources: ['next-intl', '@intlayer/next-intl'],\n namespaceArgIndex: 0,\n staticReplacement: 'useDictionary',\n dynamicReplacement: 'useDictionaryDynamic',\n },\n {\n callerName: 'getTranslations',\n importSources: ['next-intl/server', '@intlayer/next-intl/server'],\n namespaceArgIndex: 0,\n staticReplacement: 'getDictionary',\n dynamicReplacement: 'getDictionaryDynamic',\n },\n];\n\n/**\n * A Next.js plugin for next-intl compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-intl` imports are served by\n * `@intlayer/next-intl`.\n */\nexport const createNextIntlPlugin = (_i18nPath?: string) => {\n return async (nextConfig: NextConfig = {}): Promise<NextConfig> => {\n const intlayerConfig = getConfiguration();\n const appLogger = getAppLogger(intlayerConfig);\n\n runOnce(\n join(\n intlayerConfig?.system?.baseDir ?? process.cwd(),\n '.intlayer',\n 'cache',\n 'intlayer-issues-invitation.lock'\n ),\n () => {\n appLogger([\n colorize(\n 'Please report any issues you met on GitHub:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://github.com/aymericzip/intlayer/issues',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n },\n {\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n }\n );\n\n const customWebpack = nextConfig.webpack;\n\n const resolvedTargets = ALIAS_ENTRIES.map(({ request, replacement }) => ({\n request,\n absolutePath: resolveEsmPath(replacement),\n }));\n\n // Webpack resolves aliases from absolute paths.\n const webpackAlias = Object.fromEntries(\n resolvedTargets.map(({ request, absolutePath }) => [\n request,\n absolutePath,\n ])\n );\n\n // Turbopack only honours project-root-relative `./` paths.\n const turboAlias = Object.fromEntries(\n resolvedTargets.map(({ request, absolutePath }) => [\n request,\n toTurbopackAlias(absolutePath),\n ])\n );\n\n const aliasConfig = {\n webpack: (config: any, options: any) => {\n config.resolve.alias = {\n ...config.resolve.alias,\n ...webpackAlias,\n };\n\n if (typeof customWebpack === 'function') {\n return customWebpack(config, options);\n }\n return config;\n },\n };\n\n const mergedConfig: NextConfig = {\n ...nextConfig,\n ...aliasConfig,\n turbopack: {\n ...(nextConfig.turbopack ?? {}),\n resolveAlias: {\n ...(nextConfig.turbopack?.resolveAlias ?? {}),\n ...turboAlias,\n },\n },\n };\n\n // Only inject the NEXT_LOCALE cookie default when the user has not\n // configured their own routing.storage in intlayer.config.ts.\n // This lets users override via intlayer.config.ts while keeping\n // next-intl compatibility (NEXT_LOCALE) as the default.\n let hasUserDefinedStorage = false;\n try {\n hasUserDefinedStorage = !!(\n intlayerConfig?.routing &&\n 'storage' in intlayerConfig.routing &&\n intlayerConfig.routing.storage !== undefined\n );\n } catch {\n // If the config file cannot be read, fall back to the NEXT_LOCALE default.\n }\n\n const configOptions = hasUserDefinedStorage\n ? { swcExtraCallers: NEXT_INTL_SWC_CALLERS }\n : {\n override: {\n routing: {\n storage: [\n { type: 'cookie' as const, name: 'NEXT_LOCALE' },\n { type: 'header' as const, name: 'x-intlayer-locale' },\n ],\n },\n },\n swcExtraCallers: NEXT_INTL_SWC_CALLERS,\n };\n\n return withIntlayer(mergedConfig, configOptions);\n };\n};\n\nexport default createNextIntlPlugin;\n"],"mappings":";;;;;;;;;;;;;;AAcA,MAAM,gBAAgB,cAAc,OAAO,KAAK,IAAI;;;;;AAMpD,MAAM,gBAA4D;CAChE;EAAE,SAAS;EAAoB,aAAa;EAA8B;CAC1E;EAAE,SAAS;EAAqB,aAAa;EAA+B;CAC5E;EACE,SAAS;EACT,aAAa;EACd;CACD;EACE,SAAS;EACT,aAAa;EACd;CACD;EAAE,SAAS;EAAa,aAAa;EAAuB;CAC7D;;;;;;;;AASD,MAAM,kBACJ,cAC+C;CAC/C,MAAM,WAAW,UAAU,MAAM,IAAI;CACrC,MAAM,cAAc,UAAU,WAAW,IAAI,GACzC,SAAS,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,GAC7B,SAAS,MAAM;CACpB,MAAM,UAAU,UAAU,MAAM,aAAa,OAAO;AACpD,QAAO;EAAE;EAAa,WAAW,YAAY,KAAK,MAAM,IAAI;EAAW;;;;;;;;;;;;;AAczE,MAAM,kBAAkB,cAA8B;CACpD,MAAM,EAAE,aAAa,cAAc,eAAe,UAAU;CAC5D,MAAM,cAAc,cAAc,GAAG,YAAY,eAAe;CAMhE,MAAM,aAAa,QACjB,cAAc,QAAQ,GAAG,YAAY,eAAe,CACrD;CAED,MAAM,cAAc,YAAY,UAAU;CAC1C,MAAM,eACJ,OAAO,gBAAgB,WACnB,cACC,aAAa,UAAU,aAAa,WAAW,aAAa;AAGnE,KAAI,CAAC,aAAc,QAAO,cAAc,QAAQ,UAAU;AAE1D,QAAO,QAAQ,YAAY,aAAa;;;;;;;;;;;;AAa1C,MAAM,oBAAoB,iBACxB,KAAK,SAAS,QAAQ,KAAK,EAAE,aAAa,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI;AAEjE,MAAM,wBAAwB,CAC5B;CACE,YAAY;CACZ,eAAe,CAAC,aAAa,sBAAsB;CACnD,mBAAmB;CACnB,mBAAmB;CACnB,oBAAoB;CACrB,EACD;CACE,YAAY;CACZ,eAAe,CAAC,oBAAoB,6BAA6B;CACjE,mBAAmB;CACnB,mBAAmB;CACnB,oBAAoB;CACrB,CACF;;;;;;AAOD,MAAa,wBAAwB,cAAuB;AAC1D,QAAO,OAAO,aAAyB,EAAE,KAA0B;EACjE,MAAM,iBAAiB,kBAAkB;EACzC,MAAM,YAAY,aAAa,eAAe;AAE9C,UACE,KACE,gBAAgB,QAAQ,WAAW,QAAQ,KAAK,EAChD,aACA,SACA,kCACD,QACK;AACJ,aAAU,CACR,SACE,+CACA,WAAW,KACZ,EACD,SACE,iDACA,WAAW,WACZ,CACF,CAAC;KAEJ,EACE,gBAAgB,MAAO,KAAK,IAC7B,CACF;EAED,MAAM,gBAAgB,WAAW;EAEjC,MAAM,kBAAkB,cAAc,KAAK,EAAE,SAAS,mBAAmB;GACvE;GACA,cAAc,eAAe,YAAY;GAC1C,EAAE;EAGH,MAAM,eAAe,OAAO,YAC1B,gBAAgB,KAAK,EAAE,SAAS,mBAAmB,CACjD,SACA,aACD,CAAC,CACH;EAGD,MAAM,aAAa,OAAO,YACxB,gBAAgB,KAAK,EAAE,SAAS,mBAAmB,CACjD,SACA,iBAAiB,aAAa,CAC/B,CAAC,CACH;EAED,MAAM,cAAc,EAClB,UAAU,QAAa,YAAiB;AACtC,UAAO,QAAQ,QAAQ;IACrB,GAAG,OAAO,QAAQ;IAClB,GAAG;IACJ;AAED,OAAI,OAAO,kBAAkB,WAC3B,QAAO,cAAc,QAAQ,QAAQ;AAEvC,UAAO;KAEV;EAED,MAAM,eAA2B;GAC/B,GAAG;GACH,GAAG;GACH,WAAW;IACT,GAAI,WAAW,aAAa,EAAE;IAC9B,cAAc;KACZ,GAAI,WAAW,WAAW,gBAAgB,EAAE;KAC5C,GAAG;KACJ;IACF;GACF;EAMD,IAAI,wBAAwB;AAC5B,MAAI;AACF,2BAAwB,CAAC,EACvB,gBAAgB,WAChB,aAAa,eAAe,WAC5B,eAAe,QAAQ,YAAY;UAE/B;AAkBR,SAAO,aAAa,cAdE,wBAClB,EAAE,iBAAiB,uBAAuB,GAC1C;GACE,UAAU,EACR,SAAS,EACP,SAAS,CACP;IAAE,MAAM;IAAmB,MAAM;IAAe,EAChD;IAAE,MAAM;IAAmB,MAAM;IAAqB,CACvD,EACF,EACF;GACD,iBAAiB;GAClB,CAE2C"}