7 changed files with 324 additions and 10969 deletions
@ -0,0 +1,85 @@ |
|||
const findInFiles = require("find-in-files"); |
|||
const _ = require("lodash"); |
|||
const fs = require("fs/promises"); |
|||
const JSON5 = require("json5"); |
|||
|
|||
// Extract translations from $t() functions in the source code and add the missing translations to all language files in src/languages/*.js
|
|||
async function extractTranslations() { |
|||
// Load all es6 module translation files into a commonJS process
|
|||
const languageList = {}; |
|||
const filesNames = await fs.readdir("src/languages"); |
|||
for (let fileName of filesNames) { |
|||
if (fileName.endsWith("js") && fileName !== "index.js") { |
|||
const content = (await fs.readFile("src/languages/" + fileName)).toString("utf-8"); |
|||
const json = content.replace("export default {", "{").replace("};", "}"); |
|||
languageList[fileName.split(".")[0]] = JSON5.parse(json); |
|||
} |
|||
} |
|||
|
|||
const en = languageList.en; |
|||
|
|||
// Search the source code for usages of $t()
|
|||
const results = await findInFiles.find({ |
|||
term: "\\$t\\(([^)]+?)\\)", |
|||
flags: "g", |
|||
}, "./src", "\\.(vue|js)"); |
|||
|
|||
const englishExtracted = []; |
|||
|
|||
// Make a list of all the found strings
|
|||
const warnings = []; |
|||
Object.values(results).map(result => { |
|||
result.matches.map(match => { |
|||
const functionParams = match.substring(3, match.length - 1).trim(); |
|||
const firstChar = functionParams[0]; |
|||
if (!["\"", "'"].includes(firstChar)) { |
|||
// Variable => cannot extract => output warning
|
|||
warnings.push("Cannot extract non string values in " + match); |
|||
} else { |
|||
// Actual string
|
|||
const content = _.trim(functionParams.split(firstChar)[1], "\"' "); |
|||
englishExtracted.push(content); |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
// Update all languages with the missing strings
|
|||
for (let extractedTranslation of englishExtracted) { |
|||
for (let langDict of Object.values(languageList)) { |
|||
if (!Object.keys(langDict).includes(extractedTranslation)) { |
|||
langDict[extractedTranslation] = extractedTranslation; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Check for translations in other language files that are not in the english file and delete them
|
|||
const englishKeys = Object.keys(en); |
|||
for (let langName of Object.keys(languageList)) { |
|||
if (langName !== "en") { |
|||
const langKeys = Object.keys(languageList[langName]); |
|||
const unusedKeys = _.without(langKeys, ...englishKeys); |
|||
if (unusedKeys.length) { |
|||
warnings.push(`Language file ${langName} contains keys that are not used: ["${unusedKeys.join("\", \"")}"]`); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// console.log(languageList, warnings);
|
|||
|
|||
for (let langName of Object.keys(languageList)) { |
|||
const translationsString = JSON5.stringify(languageList[langName], { |
|||
quote: "\"", |
|||
space: 4, |
|||
}) |
|||
.replace(/"$/m, "\","); // Add comma to the last line
|
|||
await fs.writeFile(`./src/languages/${_.kebabCase(langName)}.js`, `export default ${translationsString};\n`); |
|||
} |
|||
|
|||
if (warnings.length) { |
|||
console.log("Extraction successful with warnings: \n\t" + warnings.join("\n\t")); |
|||
} else { |
|||
console.log("Extraction successful"); |
|||
} |
|||
} |
|||
|
|||
extractTranslations(); |
File diff suppressed because it is too large
Loading…
Reference in new issue