From 8410c55bf1d92cf6efd13000dff187298f674e52 Mon Sep 17 00:00:00 2001 From: Tobias Zimmermann Date: Sun, 14 Jul 2024 14:33:44 +0200 Subject: [PATCH] adding context by grepping the source code --- package.json | 2 ++ src/translate/index.ts | 6 ++++ src/translate/translationOptions.ts | 5 +++ src/utils/findContext.ts | 32 ++++++++++++++++++ yarn.lock | 51 +++++++++++++++++++---------- 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 src/utils/findContext.ts diff --git a/package.json b/package.json index 1480a9d..f1962a1 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "license": "MIT", "dependencies": { + "app-root-path": "3.1.0", "cli-progress": "^3.12.0", "colors": "^1.4.0", "commander": "^11.0.0", @@ -25,6 +26,7 @@ "scripts": { "build": "tsc", "test:translate": "tsc && node dist/index.js translate -b src/test/en-US.json -l de-DE de-CH fr-FR sk-SK en_US -i de-DE ", + "test:translate:context": "tsc && node dist/index.js translate -c -C -b src/test/en.json -l de-DE -i de-DE ", "test:translate:withprefix": "tsc && node dist/index.js translate -b src/test/message-en.json -l de-DE de-CH fr-FR sk-SK -i de-DE", "test:stale": "tsc && node dist/index.js remove-stale -b src/test/en-US.json -l de-DE de-CH sk-SK fr-FR", "test:stale:withprefix": "tsc && node dist/index.js remove-stale -b src/test/message-en.json -l de-DE de-CH sk-SK fr-FR", diff --git a/src/translate/index.ts b/src/translate/index.ts index fa5d4e5..a97a4b0 100644 --- a/src/translate/index.ts +++ b/src/translate/index.ts @@ -9,6 +9,7 @@ import retrieveBase from "./retrieveBase"; import { TranslationOptions } from "./translationOptions"; import { localizeFileSchema, validateBase } from "./validateBase"; import outputFilename from "./outputFilename"; +import findContext from "../utils/findContext"; export default async function translate(this: Command) { const options = this.opts(); @@ -16,6 +17,10 @@ export default async function translate(this: Command) { console.log(`\tBase: ${options.base}`); console.log(`\tOutput: ${outputDir(options.base ?? "", options.output)}`); console.log(`\tLocales: ${options.locales.join(", ")}`); + if (options.withContext) + console.log(`\tWith context: ${options.withContext}`); + if (options.compiledI18n) + console.log(`\tCompiled i18n: ${options.compiledI18n}`); console.log( `\tLocales informal: ${options.informalLocales.length === 0 ? "none" @@ -161,6 +166,7 @@ export default async function translate(this: Command) { : undefined, tagHandling: "xml", ignoreTags: ["x"], + context: options.withContext ? await findContext(source) : undefined, } ); if (plural === "flat") { diff --git a/src/translate/translationOptions.ts b/src/translate/translationOptions.ts index 8711a66..e997c16 100644 --- a/src/translate/translationOptions.ts +++ b/src/translate/translationOptions.ts @@ -5,6 +5,7 @@ export type TranslationOptions = { output?: string; locales: string[]; base?: string; + withContext?: boolean; informalLocales: string[]; compiledI18n: boolean; }; @@ -16,6 +17,10 @@ export function appendTranslationOption(command: Command) { "-o, --output ", "The output folder path. If none is given, the base folder is used." ) + .option( + "-C,--with-context", + "If you want to use the source code as the translation context. This will take much longer as it's grepping the source code.", + ) .option( "-l, --locales [value...]", "Locales to translate to. For example de-DE,fr-FR. If none is given, no translation will happen.", diff --git a/src/utils/findContext.ts b/src/utils/findContext.ts new file mode 100644 index 0000000..7d1cd5b --- /dev/null +++ b/src/utils/findContext.ts @@ -0,0 +1,32 @@ +const exec = require("child_process").exec; +const appRoot = require("app-root-path"); + +export default async function findContext( + keyword: string +): Promise { + const appRootPath = appRoot.toString(); + keyword = keyword.replace(/\{\$.*\}/g, ".*"); + const command = `grep -B 20 -A 20 -r -E "(_|\\$localize)\\\`(${keyword})\\\`" ${appRootPath} --exclude-dir={node_modules,build,coverage,dist} --no-filename`; + + return new Promise((resolve, reject) => { + try { + const files = exec(command); + let context: string = ""; + files.stdout.on("data", (data: string) => { + const file = data; + if (file) { + context += file; + } + }); + files.stdout.on("error", (error: string) => { + reject(error); + }); + files.stdout.on("end", () => { + resolve(context); + }); + } catch (error) { + console.error("some weird error was happening", error); + resolve(undefined); + } + }); +} diff --git a/yarn.lock b/yarn.lock index f3964f1..ac7cb8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,27 +14,39 @@ resolved "https://registry.yarnpkg.com/@types/figlet/-/figlet-1.5.6.tgz#fd6e71c48ffa83953aaf401c8ff179c2a5fabc9f" integrity sha512-AOdn9cKJGXpqfHeif16xeGMwWefB4nsOyxkdRMpc+PEP3nUxzu3psJfIqhjrCNW4Sejt5i6rISWmEwK0sw03mA== -"@types/node@*", "@types/node@>=12.0", "@types/node@^20.8.2": +"@types/node@*", "@types/node@^20.8.2": version "20.8.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.2.tgz#d76fb80d87d0d8abfe334fc6d292e83e5524efc4" integrity sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w== +"@types/node@>=12.0": + version "20.14.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" + integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== + dependencies: + undici-types "~5.26.4" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +app-root-path@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.1.0.tgz#5971a2fc12ba170369a7a1ef018c71e6e47c2e86" + integrity sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -"axios@>=0.21.2 <1.2.0 || >=1.2.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.1.tgz#76550d644bf0a2d469a01f9244db6753208397d7" - integrity sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g== +axios@^1.6.4: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -63,12 +75,12 @@ commander@^11.0.0: integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== deepl-node@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/deepl-node/-/deepl-node-1.10.2.tgz#35d8af9b54b5a1026685bfbe9f7f7667599f1c12" - integrity sha512-MWif2j54Cb0284FFNO8hJSGB2W9xfF0dfRICYicVtfM2FF1ClSU7Fqdf4ct27i5H9YLe32PLvbcwxVaaT+BiQQ== + version "1.13.0" + resolved "https://registry.yarnpkg.com/deepl-node/-/deepl-node-1.13.0.tgz#a4426e5fb7e2f025bc807c99d4eeea47d5addf37" + integrity sha512-pm8Al5B+/fRHiIKoreoSmv2RlXidF18+CznhtLILiYcj3EbxZpIhxWO8cgXCCsCTrUDMAbScIl8CuH3AqLPpGg== dependencies: "@types/node" ">=12.0" - axios ">=0.21.2 <1.2.0 || >=1.2.1" + axios "^1.6.4" form-data "^3.0.0" loglevel ">=1.6.2" @@ -87,10 +99,10 @@ figlet@^1.6.0: resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.6.0.tgz#812050fa9f01043b4d44ddeb11f20fb268fa4b93" integrity sha512-31EQGhCEITv6+hi2ORRPyn3bulaV9Fl4xOdR169cBzH/n1UqcxsiSB/noo6SJdD7Kfb1Ljit+IgR1USvF/XbdA== -follow-redirects@^1.15.0: - version "1.15.3" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" - integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== form-data@^3.0.0: version "3.0.1" @@ -116,9 +128,9 @@ is-fullwidth-code-point@^3.0.0: integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== loglevel@>=1.6.2: - version "1.8.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" - integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== + version "1.9.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" + integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== mime-db@1.52.0: version "1.52.0" @@ -163,6 +175,11 @@ typescript@^5.2.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + zod@^3.22.4: version "3.22.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"