@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.
- package/LICENSE.md +201 -0
- package/README.md +192 -0
- package/build/_virtual/rolldown_runtime.cjs +29 -0
- package/build/_virtual/rolldown_runtime.mjs +7 -0
- package/build/index.cjs +0 -0
- package/build/index.d.cts +2 -0
- package/build/index.d.mts +2 -0
- package/build/index.mjs +1 -0
- package/build/metadata/manager.cjs +131 -0
- package/build/metadata/manager.mjs +123 -0
- package/build/metadata/manager.mjs.map +1 -0
- package/build/plugin/build-translator.cjs +198 -0
- package/build/plugin/build-translator.mjs +196 -0
- package/build/plugin/build-translator.mjs.map +1 -0
- package/build/plugin/cleanup.cjs +20 -0
- package/build/plugin/cleanup.mjs +20 -0
- package/build/plugin/cleanup.mjs.map +1 -0
- package/build/plugin/next-compiler-loader.cjs +41 -0
- package/build/plugin/next-compiler-loader.d.cts +12 -0
- package/build/plugin/next-compiler-loader.d.cts.map +1 -0
- package/build/plugin/next-compiler-loader.d.mts +13 -0
- package/build/plugin/next-compiler-loader.d.mts.map +1 -0
- package/build/plugin/next-compiler-loader.mjs +42 -0
- package/build/plugin/next-compiler-loader.mjs.map +1 -0
- package/build/plugin/next-config-loader.cjs +13 -0
- package/build/plugin/next-config-loader.d.cts +8 -0
- package/build/plugin/next-config-loader.d.cts.map +1 -0
- package/build/plugin/next-config-loader.d.mts +9 -0
- package/build/plugin/next-config-loader.d.mts.map +1 -0
- package/build/plugin/next-config-loader.mjs +14 -0
- package/build/plugin/next-config-loader.mjs.map +1 -0
- package/build/plugin/next-locale-client-loader.cjs +9 -0
- package/build/plugin/next-locale-client-loader.d.cts +8 -0
- package/build/plugin/next-locale-client-loader.d.cts.map +1 -0
- package/build/plugin/next-locale-client-loader.d.mts +9 -0
- package/build/plugin/next-locale-client-loader.d.mts.map +1 -0
- package/build/plugin/next-locale-client-loader.mjs +10 -0
- package/build/plugin/next-locale-client-loader.mjs.map +1 -0
- package/build/plugin/next-locale-server-loader.cjs +9 -0
- package/build/plugin/next-locale-server-loader.d.cts +8 -0
- package/build/plugin/next-locale-server-loader.d.cts.map +1 -0
- package/build/plugin/next-locale-server-loader.d.mts +9 -0
- package/build/plugin/next-locale-server-loader.d.mts.map +1 -0
- package/build/plugin/next-locale-server-loader.mjs +10 -0
- package/build/plugin/next-locale-server-loader.mjs.map +1 -0
- package/build/plugin/next.cjs +220 -0
- package/build/plugin/next.d.cts +9 -0
- package/build/plugin/next.d.cts.map +1 -0
- package/build/plugin/next.d.mts +9 -0
- package/build/plugin/next.d.mts.map +1 -0
- package/build/plugin/next.mjs +222 -0
- package/build/plugin/next.mjs.map +1 -0
- package/build/plugin/transform/babel-compat.cjs +13 -0
- package/build/plugin/transform/babel-compat.mjs +10 -0
- package/build/plugin/transform/babel-compat.mjs.map +1 -0
- package/build/plugin/transform/index.cjs +44 -0
- package/build/plugin/transform/index.mjs +42 -0
- package/build/plugin/transform/index.mjs.map +1 -0
- package/build/plugin/transform/metadata.cjs +142 -0
- package/build/plugin/transform/metadata.mjs +141 -0
- package/build/plugin/transform/metadata.mjs.map +1 -0
- package/build/plugin/transform/parse-override.cjs +145 -0
- package/build/plugin/transform/parse-override.mjs +144 -0
- package/build/plugin/transform/parse-override.mjs.map +1 -0
- package/build/plugin/transform/process-file.cjs +391 -0
- package/build/plugin/transform/process-file.mjs +390 -0
- package/build/plugin/transform/process-file.mjs.map +1 -0
- package/build/plugin/transform/use-i18n.cjs +8 -0
- package/build/plugin/transform/use-i18n.mjs +7 -0
- package/build/plugin/transform/use-i18n.mjs.map +1 -0
- package/build/plugin/transform/utils.cjs +205 -0
- package/build/plugin/transform/utils.mjs +192 -0
- package/build/plugin/transform/utils.mjs.map +1 -0
- package/build/plugin/unplugin.cjs +188 -0
- package/build/plugin/unplugin.d.cts +8 -0
- package/build/plugin/unplugin.d.cts.map +1 -0
- package/build/plugin/unplugin.d.mts +8 -0
- package/build/plugin/unplugin.d.mts.map +1 -0
- package/build/plugin/unplugin.mjs +186 -0
- package/build/plugin/unplugin.mjs.map +1 -0
- package/build/plugin/vite.cjs +28 -0
- package/build/plugin/vite.d.cts +9 -0
- package/build/plugin/vite.d.cts.map +1 -0
- package/build/plugin/vite.d.mts +9 -0
- package/build/plugin/vite.d.mts.map +1 -0
- package/build/plugin/vite.mjs +29 -0
- package/build/plugin/vite.mjs.map +1 -0
- package/build/plugin/webpack.cjs +27 -0
- package/build/plugin/webpack.d.cts +8 -0
- package/build/plugin/webpack.d.cts.map +1 -0
- package/build/plugin/webpack.d.mts +8 -0
- package/build/plugin/webpack.d.mts.map +1 -0
- package/build/plugin/webpack.mjs +28 -0
- package/build/plugin/webpack.mjs.map +1 -0
- package/build/react/client/index.cjs +9 -0
- package/build/react/client/index.d.cts +5 -0
- package/build/react/client/index.d.mts +5 -0
- package/build/react/client/index.mjs +6 -0
- package/build/react/client/useTranslation.cjs +71 -0
- package/build/react/client/useTranslation.d.cts +42 -0
- package/build/react/client/useTranslation.d.cts.map +1 -0
- package/build/react/client/useTranslation.d.mts +42 -0
- package/build/react/client/useTranslation.d.mts.map +1 -0
- package/build/react/client/useTranslation.mjs +71 -0
- package/build/react/client/useTranslation.mjs.map +1 -0
- package/build/react/next/client.cjs +25 -0
- package/build/react/next/client.d.cts +9 -0
- package/build/react/next/client.d.cts.map +1 -0
- package/build/react/next/client.d.mts +9 -0
- package/build/react/next/client.d.mts.map +1 -0
- package/build/react/next/client.mjs +24 -0
- package/build/react/next/client.mjs.map +1 -0
- package/build/react/next/cookie-locale-resolver.cjs +29 -0
- package/build/react/next/cookie-locale-resolver.d.cts +33 -0
- package/build/react/next/cookie-locale-resolver.d.cts.map +1 -0
- package/build/react/next/cookie-locale-resolver.d.mts +33 -0
- package/build/react/next/cookie-locale-resolver.d.mts.map +1 -0
- package/build/react/next/cookie-locale-resolver.mjs +29 -0
- package/build/react/next/cookie-locale-resolver.mjs.map +1 -0
- package/build/react/next/server.cjs +21 -0
- package/build/react/next/server.d.cts +13 -0
- package/build/react/next/server.d.cts.map +1 -0
- package/build/react/next/server.d.mts +14 -0
- package/build/react/next/server.d.mts.map +1 -0
- package/build/react/next/server.mjs +20 -0
- package/build/react/next/server.mjs.map +1 -0
- package/build/react/server/ServerLingoProvider.cjs +19 -0
- package/build/react/server/ServerLingoProvider.d.cts +12 -0
- package/build/react/server/ServerLingoProvider.d.cts.map +1 -0
- package/build/react/server/ServerLingoProvider.d.mts +12 -0
- package/build/react/server/ServerLingoProvider.d.mts.map +1 -0
- package/build/react/server/ServerLingoProvider.mjs +19 -0
- package/build/react/server/ServerLingoProvider.mjs.map +1 -0
- package/build/react/server/index.cjs +7 -0
- package/build/react/server/index.d.cts +4 -0
- package/build/react/server/index.d.mts +4 -0
- package/build/react/server/index.mjs +5 -0
- package/build/react/server/useTranslation.cjs +60 -0
- package/build/react/server/useTranslation.d.cts +36 -0
- package/build/react/server/useTranslation.d.cts.map +1 -0
- package/build/react/server/useTranslation.d.mts +36 -0
- package/build/react/server/useTranslation.d.mts.map +1 -0
- package/build/react/server/useTranslation.mjs +60 -0
- package/build/react/server/useTranslation.mjs.map +1 -0
- package/build/react/server-only/index.cjs +42 -0
- package/build/react/server-only/index.d.cts +38 -0
- package/build/react/server-only/index.d.cts.map +1 -0
- package/build/react/server-only/index.d.mts +38 -0
- package/build/react/server-only/index.d.mts.map +1 -0
- package/build/react/server-only/index.mjs +42 -0
- package/build/react/server-only/index.mjs.map +1 -0
- package/build/react/server-only/translations.cjs +85 -0
- package/build/react/server-only/translations.mjs +85 -0
- package/build/react/server-only/translations.mjs.map +1 -0
- package/build/react/shared/LingoContext.cjs +14 -0
- package/build/react/shared/LingoContext.d.cts +41 -0
- package/build/react/shared/LingoContext.d.cts.map +1 -0
- package/build/react/shared/LingoContext.d.mts +41 -0
- package/build/react/shared/LingoContext.d.mts.map +1 -0
- package/build/react/shared/LingoContext.mjs +13 -0
- package/build/react/shared/LingoContext.mjs.map +1 -0
- package/build/react/shared/LingoProvider.cjs +274 -0
- package/build/react/shared/LingoProvider.d.cts +76 -0
- package/build/react/shared/LingoProvider.d.cts.map +1 -0
- package/build/react/shared/LingoProvider.d.mts +76 -0
- package/build/react/shared/LingoProvider.d.mts.map +1 -0
- package/build/react/shared/LingoProvider.mjs +274 -0
- package/build/react/shared/LingoProvider.mjs.map +1 -0
- package/build/react/shared/LocaleSwitcher.cjs +61 -0
- package/build/react/shared/LocaleSwitcher.d.cts +71 -0
- package/build/react/shared/LocaleSwitcher.d.cts.map +1 -0
- package/build/react/shared/LocaleSwitcher.d.mts +71 -0
- package/build/react/shared/LocaleSwitcher.d.mts.map +1 -0
- package/build/react/shared/LocaleSwitcher.mjs +61 -0
- package/build/react/shared/LocaleSwitcher.mjs.map +1 -0
- package/build/react/shared/render-rich-text.cjs +55 -0
- package/build/react/shared/render-rich-text.d.cts +17 -0
- package/build/react/shared/render-rich-text.d.cts.map +1 -0
- package/build/react/shared/render-rich-text.d.mts +17 -0
- package/build/react/shared/render-rich-text.d.mts.map +1 -0
- package/build/react/shared/render-rich-text.mjs +54 -0
- package/build/react/shared/render-rich-text.mjs.map +1 -0
- package/build/react/shared/utils.cjs +34 -0
- package/build/react/shared/utils.mjs +35 -0
- package/build/react/shared/utils.mjs.map +1 -0
- package/build/react/types.d.cts +16 -0
- package/build/react/types.d.cts.map +1 -0
- package/build/react/types.d.mts +16 -0
- package/build/react/types.d.mts.map +1 -0
- package/build/translation-server/logger.cjs +37 -0
- package/build/translation-server/logger.mjs +37 -0
- package/build/translation-server/logger.mjs.map +1 -0
- package/build/translation-server/translation-server.cjs +547 -0
- package/build/translation-server/translation-server.mjs +544 -0
- package/build/translation-server/translation-server.mjs.map +1 -0
- package/build/translation-server/ws-events.cjs +15 -0
- package/build/translation-server/ws-events.mjs +15 -0
- package/build/translation-server/ws-events.mjs.map +1 -0
- package/build/translators/api.cjs +12 -0
- package/build/translators/api.mjs +12 -0
- package/build/translators/api.mjs.map +1 -0
- package/build/translators/cache-factory.cjs +26 -0
- package/build/translators/cache-factory.mjs +27 -0
- package/build/translators/cache-factory.mjs.map +1 -0
- package/build/translators/lingo/model-factory.cjs +179 -0
- package/build/translators/lingo/model-factory.mjs +174 -0
- package/build/translators/lingo/model-factory.mjs.map +1 -0
- package/build/translators/lingo/prompt.cjs +43 -0
- package/build/translators/lingo/prompt.mjs +43 -0
- package/build/translators/lingo/prompt.mjs.map +1 -0
- package/build/translators/lingo/service.cjs +152 -0
- package/build/translators/lingo/service.mjs +152 -0
- package/build/translators/lingo/service.mjs.map +1 -0
- package/build/translators/lingo/shots.cjs +28 -0
- package/build/translators/lingo/shots.mjs +28 -0
- package/build/translators/lingo/shots.mjs.map +1 -0
- package/build/translators/local-cache.cjs +115 -0
- package/build/translators/local-cache.mjs +113 -0
- package/build/translators/local-cache.mjs.map +1 -0
- package/build/translators/parse-xml.cjs +109 -0
- package/build/translators/parse-xml.mjs +108 -0
- package/build/translators/parse-xml.mjs.map +1 -0
- package/build/translators/pluralization/icu-validator.cjs +36 -0
- package/build/translators/pluralization/icu-validator.mjs +36 -0
- package/build/translators/pluralization/icu-validator.mjs.map +1 -0
- package/build/translators/pluralization/pattern-detector.cjs +25 -0
- package/build/translators/pluralization/pattern-detector.mjs +25 -0
- package/build/translators/pluralization/pattern-detector.mjs.map +1 -0
- package/build/translators/pluralization/prompt.cjs +98 -0
- package/build/translators/pluralization/prompt.mjs +98 -0
- package/build/translators/pluralization/prompt.mjs.map +1 -0
- package/build/translators/pluralization/service.cjs +247 -0
- package/build/translators/pluralization/service.mjs +247 -0
- package/build/translators/pluralization/service.mjs.map +1 -0
- package/build/translators/pluralization/shots.cjs +53 -0
- package/build/translators/pluralization/shots.mjs +53 -0
- package/build/translators/pluralization/shots.mjs.map +1 -0
- package/build/translators/pluralization/types.d.cts +17 -0
- package/build/translators/pluralization/types.d.cts.map +1 -0
- package/build/translators/pluralization/types.d.mts +17 -0
- package/build/translators/pluralization/types.d.mts.map +1 -0
- package/build/translators/pseudotranslator/index.cjs +129 -0
- package/build/translators/pseudotranslator/index.mjs +129 -0
- package/build/translators/pseudotranslator/index.mjs.map +1 -0
- package/build/translators/translation-service.cjs +182 -0
- package/build/translators/translation-service.mjs +183 -0
- package/build/translators/translation-service.mjs.map +1 -0
- package/build/translators/translator-factory.cjs +49 -0
- package/build/translators/translator-factory.mjs +50 -0
- package/build/translators/translator-factory.mjs.map +1 -0
- package/build/types.d.cts +161 -0
- package/build/types.d.cts.map +1 -0
- package/build/types.d.mts +161 -0
- package/build/types.d.mts.map +1 -0
- package/build/utils/config-factory.cjs +58 -0
- package/build/utils/config-factory.mjs +58 -0
- package/build/utils/config-factory.mjs.map +1 -0
- package/build/utils/hash.cjs +17 -0
- package/build/utils/hash.mjs +16 -0
- package/build/utils/hash.mjs.map +1 -0
- package/build/utils/is-valid-locale.cjs +14 -0
- package/build/utils/is-valid-locale.mjs +14 -0
- package/build/utils/is-valid-locale.mjs.map +1 -0
- package/build/utils/logger.cjs +51 -0
- package/build/utils/logger.mjs +50 -0
- package/build/utils/logger.mjs.map +1 -0
- package/build/utils/path-helpers.cjs +49 -0
- package/build/utils/path-helpers.mjs +47 -0
- package/build/utils/path-helpers.mjs.map +1 -0
- package/build/utils/timeout.cjs +42 -0
- package/build/utils/timeout.mjs +41 -0
- package/build/utils/timeout.mjs.map +1 -0
- package/build/virtual/code-generator.cjs +54 -0
- package/build/virtual/code-generator.mjs +53 -0
- package/build/virtual/code-generator.mjs.map +1 -0
- package/build/virtual/config.cjs +10 -0
- package/build/virtual/config.d.cts +9 -0
- package/build/virtual/config.d.cts.map +1 -0
- package/build/virtual/config.d.mts +9 -0
- package/build/virtual/config.d.mts.map +1 -0
- package/build/virtual/config.mjs +8 -0
- package/build/virtual/config.mjs.map +1 -0
- package/build/virtual/locale/client.cjs +23 -0
- package/build/virtual/locale/client.d.cts +19 -0
- package/build/virtual/locale/client.d.cts.map +1 -0
- package/build/virtual/locale/client.d.mts +19 -0
- package/build/virtual/locale/client.d.mts.map +1 -0
- package/build/virtual/locale/client.mjs +22 -0
- package/build/virtual/locale/client.mjs.map +1 -0
- package/build/virtual/locale/server.cjs +13 -0
- package/build/virtual/locale/server.d.cts +13 -0
- package/build/virtual/locale/server.d.cts.map +1 -0
- package/build/virtual/locale/server.d.mts +13 -0
- package/build/virtual/locale/server.d.mts.map +1 -0
- package/build/virtual/locale/server.mjs +13 -0
- package/build/virtual/locale/server.mjs.map +1 -0
- package/build/widget/lingo-dev-widget.cjs +228 -0
- package/build/widget/lingo-dev-widget.mjs +229 -0
- package/build/widget/lingo-dev-widget.mjs.map +1 -0
- 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
|