@lingo.dev/compiler 0.1.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 (300) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +192 -0
  3. package/build/_virtual/rolldown_runtime.cjs +29 -0
  4. package/build/_virtual/rolldown_runtime.mjs +7 -0
  5. package/build/index.cjs +0 -0
  6. package/build/index.d.cts +2 -0
  7. package/build/index.d.mts +2 -0
  8. package/build/index.mjs +1 -0
  9. package/build/metadata/manager.cjs +131 -0
  10. package/build/metadata/manager.mjs +123 -0
  11. package/build/metadata/manager.mjs.map +1 -0
  12. package/build/plugin/build-translator.cjs +198 -0
  13. package/build/plugin/build-translator.mjs +196 -0
  14. package/build/plugin/build-translator.mjs.map +1 -0
  15. package/build/plugin/cleanup.cjs +20 -0
  16. package/build/plugin/cleanup.mjs +20 -0
  17. package/build/plugin/cleanup.mjs.map +1 -0
  18. package/build/plugin/next-compiler-loader.cjs +41 -0
  19. package/build/plugin/next-compiler-loader.d.cts +12 -0
  20. package/build/plugin/next-compiler-loader.d.cts.map +1 -0
  21. package/build/plugin/next-compiler-loader.d.mts +13 -0
  22. package/build/plugin/next-compiler-loader.d.mts.map +1 -0
  23. package/build/plugin/next-compiler-loader.mjs +42 -0
  24. package/build/plugin/next-compiler-loader.mjs.map +1 -0
  25. package/build/plugin/next-config-loader.cjs +13 -0
  26. package/build/plugin/next-config-loader.d.cts +8 -0
  27. package/build/plugin/next-config-loader.d.cts.map +1 -0
  28. package/build/plugin/next-config-loader.d.mts +9 -0
  29. package/build/plugin/next-config-loader.d.mts.map +1 -0
  30. package/build/plugin/next-config-loader.mjs +14 -0
  31. package/build/plugin/next-config-loader.mjs.map +1 -0
  32. package/build/plugin/next-locale-client-loader.cjs +9 -0
  33. package/build/plugin/next-locale-client-loader.d.cts +8 -0
  34. package/build/plugin/next-locale-client-loader.d.cts.map +1 -0
  35. package/build/plugin/next-locale-client-loader.d.mts +9 -0
  36. package/build/plugin/next-locale-client-loader.d.mts.map +1 -0
  37. package/build/plugin/next-locale-client-loader.mjs +10 -0
  38. package/build/plugin/next-locale-client-loader.mjs.map +1 -0
  39. package/build/plugin/next-locale-server-loader.cjs +9 -0
  40. package/build/plugin/next-locale-server-loader.d.cts +8 -0
  41. package/build/plugin/next-locale-server-loader.d.cts.map +1 -0
  42. package/build/plugin/next-locale-server-loader.d.mts +9 -0
  43. package/build/plugin/next-locale-server-loader.d.mts.map +1 -0
  44. package/build/plugin/next-locale-server-loader.mjs +10 -0
  45. package/build/plugin/next-locale-server-loader.mjs.map +1 -0
  46. package/build/plugin/next.cjs +220 -0
  47. package/build/plugin/next.d.cts +9 -0
  48. package/build/plugin/next.d.cts.map +1 -0
  49. package/build/plugin/next.d.mts +9 -0
  50. package/build/plugin/next.d.mts.map +1 -0
  51. package/build/plugin/next.mjs +222 -0
  52. package/build/plugin/next.mjs.map +1 -0
  53. package/build/plugin/transform/babel-compat.cjs +13 -0
  54. package/build/plugin/transform/babel-compat.mjs +10 -0
  55. package/build/plugin/transform/babel-compat.mjs.map +1 -0
  56. package/build/plugin/transform/index.cjs +44 -0
  57. package/build/plugin/transform/index.mjs +42 -0
  58. package/build/plugin/transform/index.mjs.map +1 -0
  59. package/build/plugin/transform/metadata.cjs +142 -0
  60. package/build/plugin/transform/metadata.mjs +141 -0
  61. package/build/plugin/transform/metadata.mjs.map +1 -0
  62. package/build/plugin/transform/parse-override.cjs +145 -0
  63. package/build/plugin/transform/parse-override.mjs +144 -0
  64. package/build/plugin/transform/parse-override.mjs.map +1 -0
  65. package/build/plugin/transform/process-file.cjs +391 -0
  66. package/build/plugin/transform/process-file.mjs +390 -0
  67. package/build/plugin/transform/process-file.mjs.map +1 -0
  68. package/build/plugin/transform/use-i18n.cjs +8 -0
  69. package/build/plugin/transform/use-i18n.mjs +7 -0
  70. package/build/plugin/transform/use-i18n.mjs.map +1 -0
  71. package/build/plugin/transform/utils.cjs +205 -0
  72. package/build/plugin/transform/utils.mjs +192 -0
  73. package/build/plugin/transform/utils.mjs.map +1 -0
  74. package/build/plugin/unplugin.cjs +188 -0
  75. package/build/plugin/unplugin.d.cts +8 -0
  76. package/build/plugin/unplugin.d.cts.map +1 -0
  77. package/build/plugin/unplugin.d.mts +8 -0
  78. package/build/plugin/unplugin.d.mts.map +1 -0
  79. package/build/plugin/unplugin.mjs +186 -0
  80. package/build/plugin/unplugin.mjs.map +1 -0
  81. package/build/plugin/vite.cjs +28 -0
  82. package/build/plugin/vite.d.cts +9 -0
  83. package/build/plugin/vite.d.cts.map +1 -0
  84. package/build/plugin/vite.d.mts +9 -0
  85. package/build/plugin/vite.d.mts.map +1 -0
  86. package/build/plugin/vite.mjs +29 -0
  87. package/build/plugin/vite.mjs.map +1 -0
  88. package/build/plugin/webpack.cjs +27 -0
  89. package/build/plugin/webpack.d.cts +8 -0
  90. package/build/plugin/webpack.d.cts.map +1 -0
  91. package/build/plugin/webpack.d.mts +8 -0
  92. package/build/plugin/webpack.d.mts.map +1 -0
  93. package/build/plugin/webpack.mjs +28 -0
  94. package/build/plugin/webpack.mjs.map +1 -0
  95. package/build/react/client/index.cjs +9 -0
  96. package/build/react/client/index.d.cts +5 -0
  97. package/build/react/client/index.d.mts +5 -0
  98. package/build/react/client/index.mjs +6 -0
  99. package/build/react/client/useTranslation.cjs +71 -0
  100. package/build/react/client/useTranslation.d.cts +42 -0
  101. package/build/react/client/useTranslation.d.cts.map +1 -0
  102. package/build/react/client/useTranslation.d.mts +42 -0
  103. package/build/react/client/useTranslation.d.mts.map +1 -0
  104. package/build/react/client/useTranslation.mjs +71 -0
  105. package/build/react/client/useTranslation.mjs.map +1 -0
  106. package/build/react/next/client.cjs +25 -0
  107. package/build/react/next/client.d.cts +9 -0
  108. package/build/react/next/client.d.cts.map +1 -0
  109. package/build/react/next/client.d.mts +9 -0
  110. package/build/react/next/client.d.mts.map +1 -0
  111. package/build/react/next/client.mjs +24 -0
  112. package/build/react/next/client.mjs.map +1 -0
  113. package/build/react/next/cookie-locale-resolver.cjs +29 -0
  114. package/build/react/next/cookie-locale-resolver.d.cts +33 -0
  115. package/build/react/next/cookie-locale-resolver.d.cts.map +1 -0
  116. package/build/react/next/cookie-locale-resolver.d.mts +33 -0
  117. package/build/react/next/cookie-locale-resolver.d.mts.map +1 -0
  118. package/build/react/next/cookie-locale-resolver.mjs +29 -0
  119. package/build/react/next/cookie-locale-resolver.mjs.map +1 -0
  120. package/build/react/next/server.cjs +21 -0
  121. package/build/react/next/server.d.cts +13 -0
  122. package/build/react/next/server.d.cts.map +1 -0
  123. package/build/react/next/server.d.mts +14 -0
  124. package/build/react/next/server.d.mts.map +1 -0
  125. package/build/react/next/server.mjs +20 -0
  126. package/build/react/next/server.mjs.map +1 -0
  127. package/build/react/server/ServerLingoProvider.cjs +19 -0
  128. package/build/react/server/ServerLingoProvider.d.cts +12 -0
  129. package/build/react/server/ServerLingoProvider.d.cts.map +1 -0
  130. package/build/react/server/ServerLingoProvider.d.mts +12 -0
  131. package/build/react/server/ServerLingoProvider.d.mts.map +1 -0
  132. package/build/react/server/ServerLingoProvider.mjs +19 -0
  133. package/build/react/server/ServerLingoProvider.mjs.map +1 -0
  134. package/build/react/server/index.cjs +7 -0
  135. package/build/react/server/index.d.cts +4 -0
  136. package/build/react/server/index.d.mts +4 -0
  137. package/build/react/server/index.mjs +5 -0
  138. package/build/react/server/useTranslation.cjs +60 -0
  139. package/build/react/server/useTranslation.d.cts +36 -0
  140. package/build/react/server/useTranslation.d.cts.map +1 -0
  141. package/build/react/server/useTranslation.d.mts +36 -0
  142. package/build/react/server/useTranslation.d.mts.map +1 -0
  143. package/build/react/server/useTranslation.mjs +60 -0
  144. package/build/react/server/useTranslation.mjs.map +1 -0
  145. package/build/react/server-only/index.cjs +42 -0
  146. package/build/react/server-only/index.d.cts +38 -0
  147. package/build/react/server-only/index.d.cts.map +1 -0
  148. package/build/react/server-only/index.d.mts +38 -0
  149. package/build/react/server-only/index.d.mts.map +1 -0
  150. package/build/react/server-only/index.mjs +42 -0
  151. package/build/react/server-only/index.mjs.map +1 -0
  152. package/build/react/server-only/translations.cjs +85 -0
  153. package/build/react/server-only/translations.mjs +85 -0
  154. package/build/react/server-only/translations.mjs.map +1 -0
  155. package/build/react/shared/LingoContext.cjs +14 -0
  156. package/build/react/shared/LingoContext.d.cts +41 -0
  157. package/build/react/shared/LingoContext.d.cts.map +1 -0
  158. package/build/react/shared/LingoContext.d.mts +41 -0
  159. package/build/react/shared/LingoContext.d.mts.map +1 -0
  160. package/build/react/shared/LingoContext.mjs +13 -0
  161. package/build/react/shared/LingoContext.mjs.map +1 -0
  162. package/build/react/shared/LingoProvider.cjs +274 -0
  163. package/build/react/shared/LingoProvider.d.cts +76 -0
  164. package/build/react/shared/LingoProvider.d.cts.map +1 -0
  165. package/build/react/shared/LingoProvider.d.mts +76 -0
  166. package/build/react/shared/LingoProvider.d.mts.map +1 -0
  167. package/build/react/shared/LingoProvider.mjs +274 -0
  168. package/build/react/shared/LingoProvider.mjs.map +1 -0
  169. package/build/react/shared/LocaleSwitcher.cjs +61 -0
  170. package/build/react/shared/LocaleSwitcher.d.cts +71 -0
  171. package/build/react/shared/LocaleSwitcher.d.cts.map +1 -0
  172. package/build/react/shared/LocaleSwitcher.d.mts +71 -0
  173. package/build/react/shared/LocaleSwitcher.d.mts.map +1 -0
  174. package/build/react/shared/LocaleSwitcher.mjs +61 -0
  175. package/build/react/shared/LocaleSwitcher.mjs.map +1 -0
  176. package/build/react/shared/render-rich-text.cjs +55 -0
  177. package/build/react/shared/render-rich-text.d.cts +17 -0
  178. package/build/react/shared/render-rich-text.d.cts.map +1 -0
  179. package/build/react/shared/render-rich-text.d.mts +17 -0
  180. package/build/react/shared/render-rich-text.d.mts.map +1 -0
  181. package/build/react/shared/render-rich-text.mjs +54 -0
  182. package/build/react/shared/render-rich-text.mjs.map +1 -0
  183. package/build/react/shared/utils.cjs +34 -0
  184. package/build/react/shared/utils.mjs +35 -0
  185. package/build/react/shared/utils.mjs.map +1 -0
  186. package/build/react/types.d.cts +16 -0
  187. package/build/react/types.d.cts.map +1 -0
  188. package/build/react/types.d.mts +16 -0
  189. package/build/react/types.d.mts.map +1 -0
  190. package/build/translation-server/logger.cjs +37 -0
  191. package/build/translation-server/logger.mjs +37 -0
  192. package/build/translation-server/logger.mjs.map +1 -0
  193. package/build/translation-server/translation-server.cjs +547 -0
  194. package/build/translation-server/translation-server.mjs +544 -0
  195. package/build/translation-server/translation-server.mjs.map +1 -0
  196. package/build/translation-server/ws-events.cjs +15 -0
  197. package/build/translation-server/ws-events.mjs +15 -0
  198. package/build/translation-server/ws-events.mjs.map +1 -0
  199. package/build/translators/api.cjs +12 -0
  200. package/build/translators/api.mjs +12 -0
  201. package/build/translators/api.mjs.map +1 -0
  202. package/build/translators/cache-factory.cjs +26 -0
  203. package/build/translators/cache-factory.mjs +27 -0
  204. package/build/translators/cache-factory.mjs.map +1 -0
  205. package/build/translators/lingo/model-factory.cjs +179 -0
  206. package/build/translators/lingo/model-factory.mjs +174 -0
  207. package/build/translators/lingo/model-factory.mjs.map +1 -0
  208. package/build/translators/lingo/prompt.cjs +43 -0
  209. package/build/translators/lingo/prompt.mjs +43 -0
  210. package/build/translators/lingo/prompt.mjs.map +1 -0
  211. package/build/translators/lingo/service.cjs +152 -0
  212. package/build/translators/lingo/service.mjs +152 -0
  213. package/build/translators/lingo/service.mjs.map +1 -0
  214. package/build/translators/lingo/shots.cjs +28 -0
  215. package/build/translators/lingo/shots.mjs +28 -0
  216. package/build/translators/lingo/shots.mjs.map +1 -0
  217. package/build/translators/local-cache.cjs +115 -0
  218. package/build/translators/local-cache.mjs +113 -0
  219. package/build/translators/local-cache.mjs.map +1 -0
  220. package/build/translators/parse-xml.cjs +109 -0
  221. package/build/translators/parse-xml.mjs +108 -0
  222. package/build/translators/parse-xml.mjs.map +1 -0
  223. package/build/translators/pluralization/icu-validator.cjs +36 -0
  224. package/build/translators/pluralization/icu-validator.mjs +36 -0
  225. package/build/translators/pluralization/icu-validator.mjs.map +1 -0
  226. package/build/translators/pluralization/pattern-detector.cjs +25 -0
  227. package/build/translators/pluralization/pattern-detector.mjs +25 -0
  228. package/build/translators/pluralization/pattern-detector.mjs.map +1 -0
  229. package/build/translators/pluralization/prompt.cjs +98 -0
  230. package/build/translators/pluralization/prompt.mjs +98 -0
  231. package/build/translators/pluralization/prompt.mjs.map +1 -0
  232. package/build/translators/pluralization/service.cjs +247 -0
  233. package/build/translators/pluralization/service.mjs +247 -0
  234. package/build/translators/pluralization/service.mjs.map +1 -0
  235. package/build/translators/pluralization/shots.cjs +53 -0
  236. package/build/translators/pluralization/shots.mjs +53 -0
  237. package/build/translators/pluralization/shots.mjs.map +1 -0
  238. package/build/translators/pluralization/types.d.cts +17 -0
  239. package/build/translators/pluralization/types.d.cts.map +1 -0
  240. package/build/translators/pluralization/types.d.mts +17 -0
  241. package/build/translators/pluralization/types.d.mts.map +1 -0
  242. package/build/translators/pseudotranslator/index.cjs +129 -0
  243. package/build/translators/pseudotranslator/index.mjs +129 -0
  244. package/build/translators/pseudotranslator/index.mjs.map +1 -0
  245. package/build/translators/translation-service.cjs +182 -0
  246. package/build/translators/translation-service.mjs +183 -0
  247. package/build/translators/translation-service.mjs.map +1 -0
  248. package/build/translators/translator-factory.cjs +49 -0
  249. package/build/translators/translator-factory.mjs +50 -0
  250. package/build/translators/translator-factory.mjs.map +1 -0
  251. package/build/types.d.cts +161 -0
  252. package/build/types.d.cts.map +1 -0
  253. package/build/types.d.mts +161 -0
  254. package/build/types.d.mts.map +1 -0
  255. package/build/utils/config-factory.cjs +58 -0
  256. package/build/utils/config-factory.mjs +58 -0
  257. package/build/utils/config-factory.mjs.map +1 -0
  258. package/build/utils/hash.cjs +17 -0
  259. package/build/utils/hash.mjs +16 -0
  260. package/build/utils/hash.mjs.map +1 -0
  261. package/build/utils/is-valid-locale.cjs +14 -0
  262. package/build/utils/is-valid-locale.mjs +14 -0
  263. package/build/utils/is-valid-locale.mjs.map +1 -0
  264. package/build/utils/logger.cjs +51 -0
  265. package/build/utils/logger.mjs +50 -0
  266. package/build/utils/logger.mjs.map +1 -0
  267. package/build/utils/path-helpers.cjs +49 -0
  268. package/build/utils/path-helpers.mjs +47 -0
  269. package/build/utils/path-helpers.mjs.map +1 -0
  270. package/build/utils/timeout.cjs +42 -0
  271. package/build/utils/timeout.mjs +41 -0
  272. package/build/utils/timeout.mjs.map +1 -0
  273. package/build/virtual/code-generator.cjs +54 -0
  274. package/build/virtual/code-generator.mjs +53 -0
  275. package/build/virtual/code-generator.mjs.map +1 -0
  276. package/build/virtual/config.cjs +10 -0
  277. package/build/virtual/config.d.cts +9 -0
  278. package/build/virtual/config.d.cts.map +1 -0
  279. package/build/virtual/config.d.mts +9 -0
  280. package/build/virtual/config.d.mts.map +1 -0
  281. package/build/virtual/config.mjs +8 -0
  282. package/build/virtual/config.mjs.map +1 -0
  283. package/build/virtual/locale/client.cjs +23 -0
  284. package/build/virtual/locale/client.d.cts +19 -0
  285. package/build/virtual/locale/client.d.cts.map +1 -0
  286. package/build/virtual/locale/client.d.mts +19 -0
  287. package/build/virtual/locale/client.d.mts.map +1 -0
  288. package/build/virtual/locale/client.mjs +22 -0
  289. package/build/virtual/locale/client.mjs.map +1 -0
  290. package/build/virtual/locale/server.cjs +13 -0
  291. package/build/virtual/locale/server.d.cts +13 -0
  292. package/build/virtual/locale/server.d.cts.map +1 -0
  293. package/build/virtual/locale/server.d.mts +13 -0
  294. package/build/virtual/locale/server.d.mts.map +1 -0
  295. package/build/virtual/locale/server.mjs +13 -0
  296. package/build/virtual/locale/server.mjs.map +1 -0
  297. package/build/widget/lingo-dev-widget.cjs +228 -0
  298. package/build/widget/lingo-dev-widget.mjs +229 -0
  299. package/build/widget/lingo-dev-widget.mjs.map +1 -0
  300. package/package.json +189 -0
@@ -0,0 +1,222 @@
1
+ import { __require } from "../_virtual/rolldown_runtime.mjs";
2
+ import { logger } from "../utils/logger.mjs";
3
+ import { createLingoConfig } from "../utils/config-factory.mjs";
4
+ import { cleanupExistingMetadata, getMetadataPath } from "../metadata/manager.mjs";
5
+ import { startOrGetTranslationServer } from "../translation-server/translation-server.mjs";
6
+ import { processBuildTranslations } from "./build-translator.mjs";
7
+ import { registerCleanupOnCurrentProcess } from "./cleanup.mjs";
8
+ import { useI18nRegex } from "./transform/use-i18n.mjs";
9
+
10
+ //#region src/plugin/next.ts
11
+ function loaders({ lingoConfig, metadataFilePath, translationServerUrl }) {
12
+ const common = {
13
+ sourceRoot: lingoConfig.sourceRoot,
14
+ lingoDir: lingoConfig.lingoDir,
15
+ sourceLocale: lingoConfig.sourceLocale
16
+ };
17
+ const compilerLoader = {
18
+ loader: "@lingo.dev/compiler/next-compiler-loader",
19
+ options: {
20
+ ...common,
21
+ useDirective: lingoConfig.useDirective,
22
+ metadataFilePath
23
+ }
24
+ };
25
+ const configLoader = {
26
+ loader: "@lingo.dev/compiler/next-config-loader",
27
+ options: {
28
+ ...common,
29
+ dev: {
30
+ translationServerUrl,
31
+ ...lingoConfig.dev
32
+ }
33
+ }
34
+ };
35
+ const localeServerLoader = {
36
+ loader: "@lingo.dev/compiler/next-locale-server-loader",
37
+ options: {
38
+ ...common,
39
+ localePersistence: lingoConfig.localePersistence
40
+ }
41
+ };
42
+ const localeClientLoader = {
43
+ loader: "@lingo.dev/compiler/next-locale-client-loader",
44
+ options: {
45
+ ...common,
46
+ localePersistence: lingoConfig.localePersistence
47
+ }
48
+ };
49
+ return {
50
+ compiler: {
51
+ turbopack: {
52
+ pattern: "*.{tsx,jsx}",
53
+ config: {
54
+ condition: { content: lingoConfig.useDirective ? useI18nRegex : void 0 },
55
+ loaders: [compilerLoader]
56
+ }
57
+ },
58
+ webpack: {
59
+ enforce: "pre",
60
+ test: /\.(tsx|jsx)$/i,
61
+ exclude: /node_modules/,
62
+ use: [compilerLoader]
63
+ }
64
+ },
65
+ devConfig: translationServerUrl ? {
66
+ turbopack: {
67
+ pattern: "**/virtual/config.mjs",
68
+ config: { loaders: [configLoader] }
69
+ },
70
+ webpack: {
71
+ enforce: "pre",
72
+ test: /virtual\/config\.mjs$/i,
73
+ use: [configLoader]
74
+ }
75
+ } : {},
76
+ localeServer: {
77
+ turbopack: {
78
+ pattern: "**/virtual/locale/server.mjs",
79
+ config: { loaders: [localeServerLoader] }
80
+ },
81
+ webpack: {
82
+ enforce: "pre",
83
+ test: /virtual\/locale[\\/]server\.mjs$/i,
84
+ use: [localeServerLoader]
85
+ }
86
+ },
87
+ localeClient: {
88
+ turbopack: {
89
+ pattern: "**/virtual/locale/client.mjs",
90
+ config: { loaders: [localeClientLoader] }
91
+ },
92
+ webpack: {
93
+ enforce: "pre",
94
+ test: /virtual\/locale[\\/]client\.mjs$/i,
95
+ use: [localeClientLoader]
96
+ }
97
+ }
98
+ };
99
+ }
100
+ /**
101
+ * Check if Next.js supports stable turbopack config (Next.js 16+)
102
+ */
103
+ function hasStableTurboConfig() {
104
+ try {
105
+ const nextPackage = __require("next/package.json");
106
+ return parseInt(nextPackage.version.split(".")[0], 10) >= 16;
107
+ } catch {
108
+ return false;
109
+ }
110
+ }
111
+ function getTurbopackConfig(userConfig) {
112
+ return (hasStableTurboConfig() ? userConfig?.turbopack?.rules : userConfig?.experimental?.turbo) || {};
113
+ }
114
+ /**
115
+ * Merge Turbopack rules without mutating original
116
+ */
117
+ function mergeTurbopackRules(existingRules, newRules) {
118
+ const mergedRules = { ...existingRules };
119
+ for (const newRule of newRules) {
120
+ if (!newRule) continue;
121
+ const { pattern, config } = newRule;
122
+ if (mergedRules[pattern]) if (Array.isArray(mergedRules[pattern])) mergedRules[pattern] = [...mergedRules[pattern], config];
123
+ else mergedRules[pattern] = [mergedRules[pattern], config];
124
+ else mergedRules[pattern] = config;
125
+ }
126
+ return mergedRules;
127
+ }
128
+ function isMainRunner() {
129
+ return !process.env.NEXT_PRIVATE_BUILD_WORKER && !process.env.IS_NEXT_WORKER && !process.env.NEXT_PRIVATE_WORKER;
130
+ }
131
+ async function withLingo(nextConfig = {}, lingoOptions) {
132
+ const lingoConfig = createLingoConfig(lingoOptions);
133
+ let metadataFilePath = getMetadataPath(lingoConfig);
134
+ const isDev = lingoConfig.environment === "development";
135
+ logger.debug(`Initializing Lingo.dev compiler. Is dev mode: ${isDev}. Is main runner: ${isMainRunner()}`);
136
+ if (isDev && !process.env.LINGO_TRANSLATION_SERVER_URL) {
137
+ const translationServer = await startOrGetTranslationServer({
138
+ startPort: lingoConfig.dev.translationServerStartPort,
139
+ onError: (err) => {
140
+ logger.error("Translation server error:", err);
141
+ },
142
+ onReady: (port) => {
143
+ logger.info(`Translation server started successfully on port: ${port}`);
144
+ },
145
+ config: lingoConfig
146
+ });
147
+ process.env.LINGO_TRANSLATION_SERVER_URL = translationServer.url;
148
+ if (translationServer.server) registerCleanupOnCurrentProcess({ asyncCleanup: async () => {
149
+ await translationServer.server.stop();
150
+ } });
151
+ }
152
+ const translationServerUrl = process.env.LINGO_TRANSLATION_SERVER_URL;
153
+ if (isMainRunner()) {
154
+ cleanupExistingMetadata(metadataFilePath);
155
+ registerCleanupOnCurrentProcess({ cleanup: () => {
156
+ cleanupExistingMetadata(metadataFilePath);
157
+ } });
158
+ }
159
+ const existingTurbopackConfig = getTurbopackConfig(nextConfig);
160
+ let mergedRules = mergeTurbopackRules(existingTurbopackConfig.rules ?? {}, Object.values(loaders({
161
+ lingoConfig,
162
+ metadataFilePath,
163
+ translationServerUrl
164
+ })).map((rules) => rules.turbopack));
165
+ const mergedResolveAlias = { ...existingTurbopackConfig.resolveAlias };
166
+ let turbopackConfig;
167
+ if (hasStableTurboConfig()) turbopackConfig = { turbopack: {
168
+ ...nextConfig.turbopack,
169
+ rules: mergedRules,
170
+ resolveAlias: mergedResolveAlias
171
+ } };
172
+ else turbopackConfig = { experimental: {
173
+ ...nextConfig.experimental,
174
+ turbo: {
175
+ ...nextConfig.experimental?.turbo,
176
+ rules: mergedRules,
177
+ resolveAlias: mergedResolveAlias
178
+ }
179
+ } };
180
+ const runAfterProductionCompile = async ({ distDir, projectDir }) => {
181
+ if (typeof nextConfig.compiler?.runAfterProductionCompile === "function") await nextConfig.compiler.runAfterProductionCompile({
182
+ distDir,
183
+ projectDir
184
+ });
185
+ logger.info("Running post-build translation generation...");
186
+ logger.info(`Build mode: Using metadata file: ${metadataFilePath}`);
187
+ try {
188
+ await processBuildTranslations({
189
+ config: lingoConfig,
190
+ publicOutputPath: distDir,
191
+ metadataFilePath
192
+ });
193
+ } catch (error) {
194
+ logger.error("Translation generation failed:", error);
195
+ throw error;
196
+ }
197
+ };
198
+ const webpack = (config, options) => {
199
+ let modifiedConfig = config;
200
+ if (typeof nextConfig.webpack === "function") modifiedConfig = nextConfig.webpack(config, options);
201
+ const lingoRules = Object.values(loaders({
202
+ lingoConfig,
203
+ metadataFilePath,
204
+ translationServerUrl
205
+ })).map((rules) => rules.webpack).filter(Boolean);
206
+ modifiedConfig.module.rules.unshift(...lingoRules);
207
+ return modifiedConfig;
208
+ };
209
+ return {
210
+ ...nextConfig,
211
+ ...turbopackConfig,
212
+ compiler: {
213
+ ...nextConfig.compiler,
214
+ runAfterProductionCompile
215
+ },
216
+ webpack
217
+ };
218
+ }
219
+
220
+ //#endregion
221
+ export { withLingo };
222
+ //# sourceMappingURL=next.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.mjs","names":["turbopackConfig: Partial<NextConfig>","webpack: NextJsWebpackConfig"],"sources":["../../src/plugin/next.ts"],"sourcesContent":["import type { NextConfig } from \"next\";\nimport type {\n NextJsWebpackConfig,\n TurbopackOptions,\n WebpackConfigContext,\n} from \"next/dist/server/config-shared\";\nimport { createLingoConfig } from \"../utils/config-factory\";\nimport { logger } from \"../utils/logger\";\nimport type { LingoConfig, PartialLingoConfig } from \"../types\";\nimport { processBuildTranslations } from \"./build-translator\";\nimport { startOrGetTranslationServer } from \"../translation-server/translation-server\";\nimport { cleanupExistingMetadata, getMetadataPath } from \"../metadata/manager\";\nimport { registerCleanupOnCurrentProcess } from \"./cleanup\";\nimport { useI18nRegex } from \"./transform/use-i18n\";\n\nexport type LingoNextPluginOptions = PartialLingoConfig;\n\ntype RuleKey = \"compiler\" | \"devConfig\" | \"localeServer\" | \"localeClient\";\n\nfunction loaders({\n lingoConfig,\n metadataFilePath,\n translationServerUrl,\n}: {\n lingoConfig: LingoConfig;\n metadataFilePath: string;\n translationServerUrl?: string;\n}): Record<RuleKey, { turbopack?: any; webpack?: any }> {\n const common = {\n sourceRoot: lingoConfig.sourceRoot,\n lingoDir: lingoConfig.lingoDir,\n sourceLocale: lingoConfig.sourceLocale,\n };\n\n // TODO (AleksandrSl 14/12/2025): Type options.\n const compilerLoader = {\n loader: \"@lingo.dev/compiler/next-compiler-loader\",\n options: {\n ...common,\n useDirective: lingoConfig.useDirective,\n metadataFilePath,\n },\n };\n\n const configLoader = {\n loader: \"@lingo.dev/compiler/next-config-loader\",\n options: {\n ...common,\n dev: {\n translationServerUrl,\n ...lingoConfig.dev,\n },\n },\n };\n const localeServerLoader = {\n loader: \"@lingo.dev/compiler/next-locale-server-loader\",\n options: {\n ...common,\n localePersistence: lingoConfig.localePersistence,\n },\n };\n\n const localeClientLoader = {\n loader: \"@lingo.dev/compiler/next-locale-client-loader\",\n options: {\n ...common,\n localePersistence: lingoConfig.localePersistence,\n },\n };\n\n return {\n compiler: {\n turbopack: {\n pattern: \"*.{tsx,jsx}\",\n config: {\n condition: {\n content: lingoConfig.useDirective ? useI18nRegex : undefined,\n },\n loaders: [compilerLoader],\n },\n },\n webpack: {\n enforce: \"pre\",\n test: /\\.(tsx|jsx)$/i,\n exclude: /node_modules/,\n use: [compilerLoader],\n },\n },\n\n devConfig: translationServerUrl\n ? {\n turbopack: {\n pattern: \"**/virtual/config.mjs\",\n config: {\n loaders: [configLoader],\n },\n },\n webpack: {\n enforce: \"pre\",\n test: /virtual\\/config\\.mjs$/i,\n use: [configLoader],\n },\n }\n : {},\n\n localeServer: {\n turbopack: {\n pattern: \"**/virtual/locale/server.mjs\",\n config: {\n loaders: [localeServerLoader],\n },\n },\n webpack: {\n enforce: \"pre\",\n test: /virtual\\/locale[\\\\/]server\\.mjs$/i,\n use: [localeServerLoader],\n },\n },\n\n localeClient: {\n turbopack: {\n pattern: \"**/virtual/locale/client.mjs\",\n config: {\n loaders: [localeClientLoader],\n },\n },\n webpack: {\n enforce: \"pre\",\n test: /virtual\\/locale[\\\\/]client\\.mjs$/i,\n use: [localeClientLoader],\n },\n },\n };\n}\n\n/**\n * Check if Next.js supports stable turbopack config (Next.js 16+)\n */\nfunction hasStableTurboConfig(): boolean {\n try {\n const nextPackage = require(\"next/package.json\");\n const majorVersion = parseInt(nextPackage.version.split(\".\")[0], 10);\n return majorVersion >= 16;\n } catch {\n return false;\n }\n}\n\nfunction getTurbopackConfig(userConfig: NextConfig): TurbopackOptions {\n return (\n (hasStableTurboConfig()\n ? userConfig?.turbopack?.rules\n : // @ts-expect-error - experimental.turbo for Next.js <16\n userConfig?.experimental?.turbo) || {}\n );\n}\n\n/**\n * Merge Turbopack rules without mutating original\n */\nfunction mergeTurbopackRules(\n existingRules: Record<string, any>,\n newRules: ({ pattern: string; config: any } | undefined)[],\n): Record<string, any> {\n const mergedRules = { ...existingRules };\n\n for (const newRule of newRules) {\n if (!newRule) continue;\n const { pattern, config } = newRule;\n\n if (mergedRules[pattern]) {\n if (Array.isArray(mergedRules[pattern])) {\n mergedRules[pattern] = [...mergedRules[pattern], config];\n } else {\n mergedRules[pattern] = [mergedRules[pattern], config];\n }\n } else {\n mergedRules[pattern] = config;\n }\n }\n\n return mergedRules;\n}\n\n// Next read config several times. Once in the main runner,\n// and ~ twice in the build workers which cannot get the config otherwise, because it's not serializable.\n// Workers start in separate processed by get most of the env from the main loader\nfunction isMainRunner() {\n return (\n !process.env.NEXT_PRIVATE_BUILD_WORKER &&\n !process.env.IS_NEXT_WORKER &&\n !process.env.NEXT_PRIVATE_WORKER\n );\n}\n\nexport async function withLingo(\n nextConfig: NextConfig = {},\n lingoOptions: LingoNextPluginOptions,\n): Promise<NextConfig> {\n const lingoConfig = createLingoConfig(lingoOptions);\n let metadataFilePath = getMetadataPath(lingoConfig);\n const isDev = lingoConfig.environment === \"development\";\n\n logger.debug(\n `Initializing Lingo.dev compiler. Is dev mode: ${isDev}. Is main runner: ${isMainRunner()}`,\n );\n\n // TODO (AleksandrSl 12/12/2025): Add API keys validation too, so we can log it nicely.\n\n // Try to start up the translation server once.\n // We have two barriers, a simple one here and a more complex one inside the startTranslationServer which doesn't start the server if it can find one running.\n // We do not use isMainRunner here, because we need to start the server as early as possible, so the loaders get the translation server url. The main runner in dev mode runs after a dev server process is started.\n if (isDev && !process.env.LINGO_TRANSLATION_SERVER_URL) {\n const translationServer = await startOrGetTranslationServer({\n startPort: lingoConfig.dev.translationServerStartPort,\n onError: (err) => {\n logger.error(\"Translation server error:\", err);\n },\n onReady: (port) => {\n logger.info(`Translation server started successfully on port: ${port}`);\n },\n config: lingoConfig,\n });\n process.env.LINGO_TRANSLATION_SERVER_URL = translationServer.url;\n if (translationServer.server) {\n // We start the server in the same process, so we should be fine without any sync cleanup. Server should be killed with the process.\n registerCleanupOnCurrentProcess({\n asyncCleanup: async () => {\n await translationServer.server.stop();\n },\n });\n }\n }\n\n const translationServerUrl = process.env.LINGO_TRANSLATION_SERVER_URL;\n\n if (isMainRunner()) {\n // We need to cleaup the file only once, to avoid having extra translation introduced into the build, or old translation to pile up.\n cleanupExistingMetadata(metadataFilePath);\n\n registerCleanupOnCurrentProcess({\n cleanup: () => {\n cleanupExistingMetadata(metadataFilePath);\n },\n });\n }\n\n const existingTurbopackConfig = getTurbopackConfig(nextConfig);\n let mergedRules = mergeTurbopackRules(\n existingTurbopackConfig.rules ?? {},\n Object.values(\n loaders({ lingoConfig, metadataFilePath, translationServerUrl }),\n ).map((rules) => rules.turbopack),\n );\n\n const existingResolveAlias = existingTurbopackConfig.resolveAlias;\n const mergedResolveAlias = {\n ...existingResolveAlias,\n // TODO (AleksandrSl 08/12/2025): Describe what have to be done to support custom resolvers\n };\n\n let turbopackConfig: Partial<NextConfig>;\n if (hasStableTurboConfig()) {\n turbopackConfig = {\n turbopack: {\n ...nextConfig.turbopack, // Preserve existing turbopack options\n rules: mergedRules,\n resolveAlias: mergedResolveAlias,\n },\n };\n } else {\n turbopackConfig = {\n experimental: {\n ...nextConfig.experimental, // Preserve ALL experimental options\n // @ts-expect-error - turbo for Next.js <16\n turbo: {\n // @ts-expect-error - turbo for Next.js <16\n ...nextConfig.experimental?.turbo, // Preserve existing turbo options\n rules: mergedRules,\n resolveAlias: mergedResolveAlias,\n },\n },\n };\n }\n\n const runAfterProductionCompile = async ({\n distDir,\n projectDir,\n }: {\n distDir: string;\n projectDir: string;\n }) => {\n if (typeof nextConfig.compiler?.runAfterProductionCompile === \"function\") {\n await nextConfig.compiler.runAfterProductionCompile({\n distDir,\n projectDir,\n });\n }\n\n logger.info(\"Running post-build translation generation...\");\n logger.info(`Build mode: Using metadata file: ${metadataFilePath}`);\n\n try {\n await processBuildTranslations({\n config: lingoConfig,\n publicOutputPath: distDir,\n metadataFilePath,\n });\n } catch (error) {\n logger.error(\"Translation generation failed:\", error);\n throw error;\n }\n };\n\n const webpack: NextJsWebpackConfig = (\n config: any,\n options: WebpackConfigContext,\n ) => {\n // Apply user's webpack config first if it exists\n let modifiedConfig = config;\n if (typeof nextConfig.webpack === \"function\") {\n modifiedConfig = nextConfig.webpack(config, options);\n }\n\n const lingoRules = Object.values(\n loaders({ lingoConfig, metadataFilePath, translationServerUrl }),\n )\n .map((rules) => rules.webpack)\n .filter(Boolean);\n\n // I tried using plugin from unplugin, but with all the loaders stuff it works poorly.\n // Failing with weird errors which appear on the later compilations, probably something with the cache and virtual modules\n modifiedConfig.module.rules.unshift(...lingoRules);\n\n return modifiedConfig;\n };\n\n return {\n ...nextConfig,\n ...turbopackConfig,\n compiler: {\n ...nextConfig.compiler,\n runAfterProductionCompile,\n },\n webpack,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ let _babel_traverse = require("@babel/traverse");
3
+ _babel_traverse = require_rolldown_runtime.__toESM(_babel_traverse);
4
+ let _babel_generator = require("@babel/generator");
5
+ _babel_generator = require_rolldown_runtime.__toESM(_babel_generator);
6
+
7
+ //#region src/plugin/transform/babel-compat.ts
8
+ const traverse = _babel_traverse.default.default ?? _babel_traverse.default;
9
+ const generate = _babel_generator.default.default ?? _babel_generator.default;
10
+
11
+ //#endregion
12
+ exports.generate = generate;
13
+ exports.traverse = traverse;
@@ -0,0 +1,10 @@
1
+ import traverseDefault from "@babel/traverse";
2
+ import generateDefault from "@babel/generator";
3
+
4
+ //#region src/plugin/transform/babel-compat.ts
5
+ const traverse = traverseDefault.default ?? traverseDefault;
6
+ const generate = generateDefault.default ?? generateDefault;
7
+
8
+ //#endregion
9
+ export { generate, traverse };
10
+ //# sourceMappingURL=babel-compat.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"babel-compat.mjs","names":["traverse: typeof traverseDefault","generate: typeof generateDefault"],"sources":["../../../src/plugin/transform/babel-compat.ts"],"sourcesContent":["import traverseDefault from \"@babel/traverse\";\nimport generateDefault from \"@babel/generator\";\n\n// Handle ESM/CJS interop - these packages may export differently\nconst traverse: typeof traverseDefault =\n // @ts-expect-error - Handle both default and named exports\n traverseDefault.default ?? traverseDefault;\nconst generate: typeof generateDefault =\n // @ts-expect-error - Handle both default and named exports\n generateDefault.default ?? generateDefault;\n\nexport { traverse, generate };\n"],"mappings":";;;;AAIA,MAAMA,WAEJ,gBAAgB,WAAW;AAC7B,MAAMC,WAEJ,gBAAgB,WAAW"}
@@ -0,0 +1,44 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_logger = require('../../utils/logger.cjs');
3
+ const require_babel_compat = require('./babel-compat.cjs');
4
+ const require_process_file = require('./process-file.cjs');
5
+ let path = require("path");
6
+ path = require_rolldown_runtime.__toESM(path);
7
+ let _babel_parser = require("@babel/parser");
8
+ _babel_parser = require_rolldown_runtime.__toESM(_babel_parser);
9
+
10
+ //#region src/plugin/transform/index.ts
11
+ /**
12
+ * Transform component code to inject translation calls
13
+ */
14
+ function transformComponent({ code, filePath, config }) {
15
+ const relativeFilePath = path.default.relative(path.default.resolve(config.sourceRoot), filePath).split(path.default.sep).join("/");
16
+ try {
17
+ const ast = _babel_parser.parse(code, {
18
+ sourceType: "module",
19
+ plugins: ["jsx", "typescript"]
20
+ });
21
+ require_logger.logger.debug(`Transforming ${filePath}`);
22
+ const translationEntries = require_process_file.processFile(ast, {
23
+ relativeFilePath,
24
+ needsDirective: config.useDirective
25
+ });
26
+ const output = require_babel_compat.generate(ast, { sourceMaps: true }, code);
27
+ require_logger.logger.debug(`Transformed ${filePath}. Code: ${output.code}`);
28
+ return {
29
+ code: output.code,
30
+ map: output.map,
31
+ newEntries: translationEntries,
32
+ transformed: translationEntries.length > 0
33
+ };
34
+ } catch (error) {
35
+ require_logger.logger.error(`Failed to transform ${filePath}:`, error);
36
+ return {
37
+ code,
38
+ transformed: false
39
+ };
40
+ }
41
+ }
42
+
43
+ //#endregion
44
+ exports.transformComponent = transformComponent;
@@ -0,0 +1,42 @@
1
+ import { logger } from "../../utils/logger.mjs";
2
+ import { generate } from "./babel-compat.mjs";
3
+ import { processFile } from "./process-file.mjs";
4
+ import path from "path";
5
+ import * as parser from "@babel/parser";
6
+
7
+ //#region src/plugin/transform/index.ts
8
+ /**
9
+ * Transform component code to inject translation calls
10
+ */
11
+ function transformComponent({ code, filePath, config }) {
12
+ const relativeFilePath = path.relative(path.resolve(config.sourceRoot), filePath).split(path.sep).join("/");
13
+ try {
14
+ const ast = parser.parse(code, {
15
+ sourceType: "module",
16
+ plugins: ["jsx", "typescript"]
17
+ });
18
+ logger.debug(`Transforming ${filePath}`);
19
+ const translationEntries = processFile(ast, {
20
+ relativeFilePath,
21
+ needsDirective: config.useDirective
22
+ });
23
+ const output = generate(ast, { sourceMaps: true }, code);
24
+ logger.debug(`Transformed ${filePath}. Code: ${output.code}`);
25
+ return {
26
+ code: output.code,
27
+ map: output.map,
28
+ newEntries: translationEntries,
29
+ transformed: translationEntries.length > 0
30
+ };
31
+ } catch (error) {
32
+ logger.error(`Failed to transform ${filePath}:`, error);
33
+ return {
34
+ code,
35
+ transformed: false
36
+ };
37
+ }
38
+ }
39
+
40
+ //#endregion
41
+ export { transformComponent };
42
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/transform/index.ts"],"sourcesContent":["import * as parser from \"@babel/parser\";\nimport path from \"path\";\nimport type { LingoConfig, TranslationEntry } from \"../../types\";\nimport { processFile } from \"./process-file\";\nimport { logger } from \"../../utils/logger\";\nimport { generate } from \"./babel-compat\";\n\nexport interface TransformResult {\n code: string;\n map?: any;\n newEntries?: TranslationEntry[];\n transformed: boolean;\n}\n\nexport interface BabelTransformOptions {\n code: string;\n filePath: string;\n config: LingoConfig;\n}\n\n/**\n * Transform component code to inject translation calls\n */\nexport function transformComponent({\n code,\n filePath,\n config,\n}: BabelTransformOptions): TransformResult {\n // Get relative file path for consistent hashing\n const relativeFilePath = path\n .relative(path.resolve(config.sourceRoot), filePath)\n .split(path.sep)\n // '/' is used as a cross-platform path separator\n .join(\"/\");\n\n try {\n const ast = parser.parse(code, {\n sourceType: \"module\",\n plugins: [\"jsx\", \"typescript\"],\n });\n\n logger.debug(`Transforming ${filePath}`);\n\n const translationEntries = processFile(ast, {\n relativeFilePath,\n needsDirective: config.useDirective,\n });\n\n const output = generate(\n ast,\n {\n sourceMaps: true,\n },\n code,\n );\n\n logger.debug(`Transformed ${filePath}. Code: ${output.code}`);\n\n return {\n code: output.code,\n map: output.map,\n newEntries: translationEntries,\n transformed: translationEntries.length > 0,\n };\n } catch (error) {\n // TODO (AleksandrSl 08/12/2025): Should also log the message\n logger.error(`Failed to transform ${filePath}:`, error);\n // Return original code on error\n return {\n code,\n transformed: false,\n };\n }\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,mBAAmB,EACjC,MACA,UACA,UACyC;CAEzC,MAAM,mBAAmB,KACtB,SAAS,KAAK,QAAQ,OAAO,WAAW,EAAE,SAAS,CACnD,MAAM,KAAK,IAAI,CAEf,KAAK,IAAI;AAEZ,KAAI;EACF,MAAM,MAAM,OAAO,MAAM,MAAM;GAC7B,YAAY;GACZ,SAAS,CAAC,OAAO,aAAa;GAC/B,CAAC;AAEF,SAAO,MAAM,gBAAgB,WAAW;EAExC,MAAM,qBAAqB,YAAY,KAAK;GAC1C;GACA,gBAAgB,OAAO;GACxB,CAAC;EAEF,MAAM,SAAS,SACb,KACA,EACE,YAAY,MACb,EACD,KACD;AAED,SAAO,MAAM,eAAe,SAAS,UAAU,OAAO,OAAO;AAE7D,SAAO;GACL,MAAM,OAAO;GACb,KAAK,OAAO;GACZ,YAAY;GACZ,aAAa,mBAAmB,SAAS;GAC1C;UACM,OAAO;AAEd,SAAO,MAAM,uBAAuB,SAAS,IAAI,MAAM;AAEvD,SAAO;GACL;GACA,aAAa;GACd"}
@@ -0,0 +1,142 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_utils = require('./utils.cjs');
3
+ let _babel_types = require("@babel/types");
4
+ _babel_types = require_rolldown_runtime.__toESM(_babel_types);
5
+
6
+ //#region src/plugin/transform/metadata.ts
7
+ /**
8
+ * Transforms Next.js metadata object to use t() calls. See https://nextjs.org/docs/app/getting-started/metadata-and-og-images for docs on next metadata.
9
+ */
10
+ /**
11
+ * Whitelist of metadata fields that should be translated.
12
+ * Other fields (like technical configurations, URLs, etc.) are left unchanged.
13
+ */
14
+ const TRANSLATABLE_METADATA_FIELDS = new Set([
15
+ "title",
16
+ "description",
17
+ "title.template",
18
+ "title.default",
19
+ "openGraph.title",
20
+ "openGraph.description",
21
+ "openGraph.images[*].alt",
22
+ "twitter.title",
23
+ "twitter.description",
24
+ "twitter.images[*].alt",
25
+ "appleWebApp.title"
26
+ ]);
27
+ const NEXT_METADATA_EXPORT_NAME = "metadata";
28
+ const NEXT_GENERATE_METADATA_FUNCTION_NAME = "generateMetadata";
29
+ /**
30
+ * Check if a field path matches a pattern with array indices.
31
+ * For example: "openGraph.images[0].alt" matches "openGraph.images[*].alt"
32
+ */
33
+ function matchesArrayPattern(fieldPath, pattern) {
34
+ return fieldPath.replace(/\[\d+]/g, "[*]") === pattern;
35
+ }
36
+ /**
37
+ * Check if a metadata field path should be translated
38
+ */
39
+ function isTranslatableMetadataField(fieldPath) {
40
+ if (TRANSLATABLE_METADATA_FIELDS.has(fieldPath)) return true;
41
+ for (const pattern of TRANSLATABLE_METADATA_FIELDS) if (pattern.includes("[*]") && matchesArrayPattern(fieldPath, pattern)) return true;
42
+ return false;
43
+ }
44
+ function isNextGenerateMetadataFunction(path) {
45
+ if (path.node.id?.name === NEXT_GENERATE_METADATA_FUNCTION_NAME) {
46
+ const parent = path.parent;
47
+ if (parent.type === "ExportNamedDeclaration" || parent.type === "Program") return true;
48
+ }
49
+ }
50
+ function getNextMetadataObjectOrNull(path) {
51
+ const declaration = path.node.declaration;
52
+ if (!declaration || declaration.type !== "VariableDeclaration") return null;
53
+ const declarator = declaration.declarations[0];
54
+ if (!declarator || declarator.id.type !== "Identifier") return null;
55
+ if (declarator.id.name === NEXT_METADATA_EXPORT_NAME && declarator.init) return declarator.init;
56
+ }
57
+ /**
58
+ * Recursively transforms metadata object properties to use t() calls
59
+ */
60
+ function transformMetadataObject(objectExpression, state, entries, parentPath = "") {
61
+ for (const prop of objectExpression.properties) {
62
+ if (prop.type !== "ObjectProperty") continue;
63
+ let keyName = null;
64
+ if (prop.key.type === "Identifier") keyName = prop.key.name;
65
+ else if (prop.key.type === "StringLiteral") keyName = prop.key.value;
66
+ if (!keyName) continue;
67
+ const fieldPath = parentPath ? `${parentPath}.${keyName}` : keyName;
68
+ const shouldTranslate = isTranslatableMetadataField(fieldPath);
69
+ if (prop.value.type === "StringLiteral" && shouldTranslate) {
70
+ const text = prop.value.value;
71
+ const entry = require_utils.createTranslationEntry("metadata", text, { fieldPath }, state.filePath, prop.value.loc?.start.line, prop.value.loc?.start.column);
72
+ entries.push(entry);
73
+ prop.value = _babel_types.callExpression(_babel_types.identifier("t"), [_babel_types.stringLiteral(entry.hash), _babel_types.stringLiteral(text)]);
74
+ } else if (prop.value.type === "TemplateLiteral" && shouldTranslate) {
75
+ if (prop.value.expressions.length === 0 && prop.value.quasis.length === 1) {
76
+ const staticValue = prop.value.quasis[0].value.cooked;
77
+ if (staticValue) {
78
+ const entry = require_utils.createTranslationEntry("metadata", staticValue, { fieldPath }, state.filePath, prop.value.loc?.start.line, prop.value.loc?.start.column);
79
+ entries.push(entry);
80
+ prop.value = _babel_types.callExpression(_babel_types.identifier("t"), [_babel_types.stringLiteral(entry.hash), _babel_types.stringLiteral(staticValue)]);
81
+ }
82
+ }
83
+ } else if (prop.value.type === "ObjectExpression") transformMetadataObject(prop.value, state, entries, fieldPath);
84
+ else if (prop.value.type === "ArrayExpression") prop.value.elements.forEach((element, index) => {
85
+ if (element && element.type === "ObjectExpression") transformMetadataObject(element, state, entries, `${fieldPath}[${index}]`);
86
+ });
87
+ }
88
+ }
89
+ /**
90
+ * Transform existing generateMetadata function to add translations
91
+ */
92
+ function transformMetadataFunction(path, state) {
93
+ const body = path.get("body");
94
+ if (!body.isBlockStatement()) return null;
95
+ let metadataReturn = void 0;
96
+ body.traverse({ ReturnStatement(returnPath) {
97
+ if (!metadataReturn) metadataReturn = returnPath;
98
+ } });
99
+ if (!(0, _babel_types.isReturnStatement)(metadataReturn) || !metadataReturn.node.argument) return null;
100
+ if (!(0, _babel_types.isObjectExpression)(metadataReturn.node.argument)) return null;
101
+ const entries = [];
102
+ const metadataObject = metadataReturn.node.argument;
103
+ transformMetadataObject(metadataObject, state, entries);
104
+ if (entries.length === 0) return null;
105
+ if (!path.node.async) path.node.async = true;
106
+ const serverCall = require_utils.constructServerTranslationHookCall({ hashes: entries.map((e) => e.hash) });
107
+ body.node.body.unshift(serverCall);
108
+ return {
109
+ needsAsyncImport: true,
110
+ newEntries: entries
111
+ };
112
+ }
113
+ /**
114
+ * Process static metadata export
115
+ * Only converts to function if there are translatable strings
116
+ */
117
+ function processNextStaticMetadata(path, state) {
118
+ const metadataObject = getNextMetadataObjectOrNull(path);
119
+ if (!metadataObject || metadataObject.type !== "ObjectExpression") return null;
120
+ const clonedObject = _babel_types.cloneNode(metadataObject, true);
121
+ const entries = [];
122
+ transformMetadataObject(clonedObject, state, entries);
123
+ if (entries.length === 0) return null;
124
+ const serverCall = require_utils.constructServerTranslationHookCall({ hashes: entries.map((e) => e.hash) });
125
+ const generateMetadataFunction = _babel_types.functionDeclaration(_babel_types.identifier(NEXT_GENERATE_METADATA_FUNCTION_NAME), [], _babel_types.blockStatement([serverCall, _babel_types.returnStatement(clonedObject)]), false, true);
126
+ path.replaceWith(_babel_types.exportNamedDeclaration(generateMetadataFunction, []));
127
+ path.skip();
128
+ return {
129
+ needsAsyncImport: true,
130
+ newEntries: entries
131
+ };
132
+ }
133
+ function processNextDynamicMetadata(path, state) {
134
+ if (!isNextGenerateMetadataFunction(path)) return null;
135
+ const newState = transformMetadataFunction(path, state);
136
+ path.skip();
137
+ return newState;
138
+ }
139
+
140
+ //#endregion
141
+ exports.processNextDynamicMetadata = processNextDynamicMetadata;
142
+ exports.processNextStaticMetadata = processNextStaticMetadata;
@@ -0,0 +1,141 @@
1
+ import { constructServerTranslationHookCall, createTranslationEntry } from "./utils.mjs";
2
+ import * as t from "@babel/types";
3
+ import { isObjectExpression, isReturnStatement } from "@babel/types";
4
+
5
+ //#region src/plugin/transform/metadata.ts
6
+ /**
7
+ * Transforms Next.js metadata object to use t() calls. See https://nextjs.org/docs/app/getting-started/metadata-and-og-images for docs on next metadata.
8
+ */
9
+ /**
10
+ * Whitelist of metadata fields that should be translated.
11
+ * Other fields (like technical configurations, URLs, etc.) are left unchanged.
12
+ */
13
+ const TRANSLATABLE_METADATA_FIELDS = new Set([
14
+ "title",
15
+ "description",
16
+ "title.template",
17
+ "title.default",
18
+ "openGraph.title",
19
+ "openGraph.description",
20
+ "openGraph.images[*].alt",
21
+ "twitter.title",
22
+ "twitter.description",
23
+ "twitter.images[*].alt",
24
+ "appleWebApp.title"
25
+ ]);
26
+ const NEXT_METADATA_EXPORT_NAME = "metadata";
27
+ const NEXT_GENERATE_METADATA_FUNCTION_NAME = "generateMetadata";
28
+ /**
29
+ * Check if a field path matches a pattern with array indices.
30
+ * For example: "openGraph.images[0].alt" matches "openGraph.images[*].alt"
31
+ */
32
+ function matchesArrayPattern(fieldPath, pattern) {
33
+ return fieldPath.replace(/\[\d+]/g, "[*]") === pattern;
34
+ }
35
+ /**
36
+ * Check if a metadata field path should be translated
37
+ */
38
+ function isTranslatableMetadataField(fieldPath) {
39
+ if (TRANSLATABLE_METADATA_FIELDS.has(fieldPath)) return true;
40
+ for (const pattern of TRANSLATABLE_METADATA_FIELDS) if (pattern.includes("[*]") && matchesArrayPattern(fieldPath, pattern)) return true;
41
+ return false;
42
+ }
43
+ function isNextGenerateMetadataFunction(path) {
44
+ if (path.node.id?.name === NEXT_GENERATE_METADATA_FUNCTION_NAME) {
45
+ const parent = path.parent;
46
+ if (parent.type === "ExportNamedDeclaration" || parent.type === "Program") return true;
47
+ }
48
+ }
49
+ function getNextMetadataObjectOrNull(path) {
50
+ const declaration = path.node.declaration;
51
+ if (!declaration || declaration.type !== "VariableDeclaration") return null;
52
+ const declarator = declaration.declarations[0];
53
+ if (!declarator || declarator.id.type !== "Identifier") return null;
54
+ if (declarator.id.name === NEXT_METADATA_EXPORT_NAME && declarator.init) return declarator.init;
55
+ }
56
+ /**
57
+ * Recursively transforms metadata object properties to use t() calls
58
+ */
59
+ function transformMetadataObject(objectExpression, state, entries, parentPath = "") {
60
+ for (const prop of objectExpression.properties) {
61
+ if (prop.type !== "ObjectProperty") continue;
62
+ let keyName = null;
63
+ if (prop.key.type === "Identifier") keyName = prop.key.name;
64
+ else if (prop.key.type === "StringLiteral") keyName = prop.key.value;
65
+ if (!keyName) continue;
66
+ const fieldPath = parentPath ? `${parentPath}.${keyName}` : keyName;
67
+ const shouldTranslate = isTranslatableMetadataField(fieldPath);
68
+ if (prop.value.type === "StringLiteral" && shouldTranslate) {
69
+ const text = prop.value.value;
70
+ const entry = createTranslationEntry("metadata", text, { fieldPath }, state.filePath, prop.value.loc?.start.line, prop.value.loc?.start.column);
71
+ entries.push(entry);
72
+ prop.value = t.callExpression(t.identifier("t"), [t.stringLiteral(entry.hash), t.stringLiteral(text)]);
73
+ } else if (prop.value.type === "TemplateLiteral" && shouldTranslate) {
74
+ if (prop.value.expressions.length === 0 && prop.value.quasis.length === 1) {
75
+ const staticValue = prop.value.quasis[0].value.cooked;
76
+ if (staticValue) {
77
+ const entry = createTranslationEntry("metadata", staticValue, { fieldPath }, state.filePath, prop.value.loc?.start.line, prop.value.loc?.start.column);
78
+ entries.push(entry);
79
+ prop.value = t.callExpression(t.identifier("t"), [t.stringLiteral(entry.hash), t.stringLiteral(staticValue)]);
80
+ }
81
+ }
82
+ } else if (prop.value.type === "ObjectExpression") transformMetadataObject(prop.value, state, entries, fieldPath);
83
+ else if (prop.value.type === "ArrayExpression") prop.value.elements.forEach((element, index) => {
84
+ if (element && element.type === "ObjectExpression") transformMetadataObject(element, state, entries, `${fieldPath}[${index}]`);
85
+ });
86
+ }
87
+ }
88
+ /**
89
+ * Transform existing generateMetadata function to add translations
90
+ */
91
+ function transformMetadataFunction(path, state) {
92
+ const body = path.get("body");
93
+ if (!body.isBlockStatement()) return null;
94
+ let metadataReturn = void 0;
95
+ body.traverse({ ReturnStatement(returnPath) {
96
+ if (!metadataReturn) metadataReturn = returnPath;
97
+ } });
98
+ if (!isReturnStatement(metadataReturn) || !metadataReturn.node.argument) return null;
99
+ if (!isObjectExpression(metadataReturn.node.argument)) return null;
100
+ const entries = [];
101
+ const metadataObject = metadataReturn.node.argument;
102
+ transformMetadataObject(metadataObject, state, entries);
103
+ if (entries.length === 0) return null;
104
+ if (!path.node.async) path.node.async = true;
105
+ const serverCall = constructServerTranslationHookCall({ hashes: entries.map((e) => e.hash) });
106
+ body.node.body.unshift(serverCall);
107
+ return {
108
+ needsAsyncImport: true,
109
+ newEntries: entries
110
+ };
111
+ }
112
+ /**
113
+ * Process static metadata export
114
+ * Only converts to function if there are translatable strings
115
+ */
116
+ function processNextStaticMetadata(path, state) {
117
+ const metadataObject = getNextMetadataObjectOrNull(path);
118
+ if (!metadataObject || metadataObject.type !== "ObjectExpression") return null;
119
+ const clonedObject = t.cloneNode(metadataObject, true);
120
+ const entries = [];
121
+ transformMetadataObject(clonedObject, state, entries);
122
+ if (entries.length === 0) return null;
123
+ const serverCall = constructServerTranslationHookCall({ hashes: entries.map((e) => e.hash) });
124
+ const generateMetadataFunction = t.functionDeclaration(t.identifier(NEXT_GENERATE_METADATA_FUNCTION_NAME), [], t.blockStatement([serverCall, t.returnStatement(clonedObject)]), false, true);
125
+ path.replaceWith(t.exportNamedDeclaration(generateMetadataFunction, []));
126
+ path.skip();
127
+ return {
128
+ needsAsyncImport: true,
129
+ newEntries: entries
130
+ };
131
+ }
132
+ function processNextDynamicMetadata(path, state) {
133
+ if (!isNextGenerateMetadataFunction(path)) return null;
134
+ const newState = transformMetadataFunction(path, state);
135
+ path.skip();
136
+ return newState;
137
+ }
138
+
139
+ //#endregion
140
+ export { processNextDynamicMetadata, processNextStaticMetadata };
141
+ //# sourceMappingURL=metadata.mjs.map