Complete statical parsing of withExtraLanguages
This commit is contained in:
parent
10d4da9fbf
commit
c07af8491c
@ -1,6 +1,6 @@
|
||||
import { type ThemeType, FALLBACK_LANGUAGE_TAG } from "../../shared/constants";
|
||||
import { crawl } from "../../tools/crawl";
|
||||
import { join as pathJoin } from "path";
|
||||
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||
import { symToStr } from "tsafe/symToStr";
|
||||
import * as recast from "recast";
|
||||
import * as babelParser from "@babel/parser";
|
||||
@ -11,6 +11,7 @@ import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPa
|
||||
import * as fs from "fs";
|
||||
import { assert } from "tsafe/assert";
|
||||
import type { BuildContext } from "../../shared/buildContext";
|
||||
import { getAbsoluteAndInOsFormatPath } from "../../tools/getAbsoluteAndInOsFormatPath";
|
||||
|
||||
export type BuildContextLike = {
|
||||
themeNames: string[];
|
||||
@ -112,20 +113,7 @@ export function generateMessageProperties(params: {
|
||||
if (i18nTsFilePath === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const root: recast.types.ASTNode = recast.parse(
|
||||
fs.readFileSync(i18nTsFilePath).toString("utf8"),
|
||||
{
|
||||
parser: {
|
||||
parse: (code: string) =>
|
||||
babelParser.parse(code, {
|
||||
sourceType: "module",
|
||||
plugins: ["typescript"]
|
||||
}),
|
||||
generator: babelGenerate,
|
||||
types: babelTypes
|
||||
}
|
||||
}
|
||||
);
|
||||
const root = recastParseTs(i18nTsFilePath);
|
||||
return root;
|
||||
})();
|
||||
|
||||
@ -136,7 +124,10 @@ export function generateMessageProperties(params: {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let out: Record<string, { label: string; path: string }> = {};
|
||||
let extraLanguageEntryByLanguageTag: Record<
|
||||
string,
|
||||
{ label: string; path: string }
|
||||
> = {};
|
||||
|
||||
recast.visit(i18nTsRoot, {
|
||||
visitCallExpression: function (path) {
|
||||
@ -225,7 +216,10 @@ export function generateMessageProperties(params: {
|
||||
});
|
||||
|
||||
if (label && pathStr) {
|
||||
out[lang] = { label, path: pathStr };
|
||||
extraLanguageEntryByLanguageTag[lang] = {
|
||||
label,
|
||||
path: pathStr
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -239,9 +233,69 @@ export function generateMessageProperties(params: {
|
||||
}
|
||||
});
|
||||
|
||||
console.log(out);
|
||||
const messages_defaultSet_by_languageTag_notInDefaultSet = Object.fromEntries(
|
||||
Object.entries(extraLanguageEntryByLanguageTag).map(
|
||||
([languageTag, { path: relativePathWithoutExt }]) => [
|
||||
languageTag,
|
||||
(() => {
|
||||
const filePath = getAbsoluteAndInOsFormatPath({
|
||||
pathIsh: relativePathWithoutExt.endsWith(".ts")
|
||||
? relativePathWithoutExt
|
||||
: `${relativePathWithoutExt}.ts`,
|
||||
cwd: pathDirname(i18nTsFilePath)
|
||||
});
|
||||
|
||||
return {};
|
||||
const root = recastParseTs(filePath);
|
||||
|
||||
let declarationCode: string | undefined = "";
|
||||
|
||||
recast.visit(root, {
|
||||
visitVariableDeclarator: function (path) {
|
||||
const node = path.node;
|
||||
|
||||
// Check if the variable name is 'messages'
|
||||
if (
|
||||
node.id.type === "Identifier" &&
|
||||
node.id.name === "messages"
|
||||
) {
|
||||
// Ensure there is an initializer
|
||||
if (node.init) {
|
||||
// Generate code from the initializer, preserving comments
|
||||
declarationCode = recast
|
||||
.print(node.init)
|
||||
.code.replace(/}.*$/, "}");
|
||||
}
|
||||
return false; // Stop traversing this path
|
||||
}
|
||||
|
||||
this.traverse(path); // Continue traversing other paths
|
||||
}
|
||||
});
|
||||
|
||||
assert(
|
||||
declarationCode !== undefined,
|
||||
`${filePath} does not contain a 'messages' variable declaration`
|
||||
);
|
||||
|
||||
let messages: Record<string, string> = {};
|
||||
|
||||
try {
|
||||
eval(`${symToStr({ messages })} = ${declarationCode};`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`The declaration of 'message' in ${filePath} cannot be statically evaluated: ${declarationCode}`
|
||||
);
|
||||
}
|
||||
|
||||
return messages;
|
||||
})()
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
console.log(messages_defaultSet_by_languageTag_notInDefaultSet);
|
||||
|
||||
return messages_defaultSet_by_languageTag_notInDefaultSet;
|
||||
})();
|
||||
|
||||
const messages_defaultSet_by_languageTag = {
|
||||
@ -294,12 +348,8 @@ export function generateMessageProperties(params: {
|
||||
} catch {
|
||||
console.warn(
|
||||
[
|
||||
"WARNING: Make sure the messageBundle your provided as argument of createUseI18n can be statically evaluated.",
|
||||
"This is important because we need to put your i18n messages in messages_*.properties files",
|
||||
"or they won't be available server side.",
|
||||
"\n",
|
||||
"The following code could not be evaluated:",
|
||||
"\n",
|
||||
"WARNING: The argument of withCustomTranslations can't be statically evaluated!",
|
||||
"This needs to be fixed refer to the documentation: https://docs.keycloakify.dev/i18n",
|
||||
firstArgumentCode
|
||||
].join(" ")
|
||||
);
|
||||
@ -376,3 +426,17 @@ export function generateMessageProperties(params: {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function recastParseTs(filePath: string): recast.types.ASTNode {
|
||||
return recast.parse(fs.readFileSync(filePath).toString("utf8"), {
|
||||
parser: {
|
||||
parse: (code: string) =>
|
||||
babelParser.parse(code, {
|
||||
sourceType: "module",
|
||||
plugins: ["typescript"]
|
||||
}),
|
||||
generator: babelGenerate,
|
||||
types: babelTypes
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user