From e9779a3d2fda07eda47a3210f5d137f32ba91495 Mon Sep 17 00:00:00 2001 From: Nybkox Date: Thu, 20 Feb 2025 11:22:01 +0100 Subject: [PATCH] feat: add add-missing command to translations cli --- common/translations-cli/addMissing.js | 43 +++++++++++++++++++++++ common/translations-cli/helpers.js | 45 ++++++++++++++++++++++++ common/translations-cli/program.js | 49 ++++++++++++++++++++++++--- package.json | 5 +-- 4 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 common/translations-cli/addMissing.js diff --git a/common/translations-cli/addMissing.js b/common/translations-cli/addMissing.js new file mode 100644 index 000000000..f3e2fbf29 --- /dev/null +++ b/common/translations-cli/addMissing.js @@ -0,0 +1,43 @@ +//@ts-check +const { getDefaultTranslations, getLanguageTranslations } = require('./helpers'); + +/** + * @param {string} language + */ +function getMissingTranslations(language) { + const source = getDefaultTranslations(); + /** @type {Record} */ + let target; + + try { + target = getLanguageTranslations(language); + } catch { + console.log(`Language ${language} not found, creating a new one`); + target = {}; + } + + let added = 0; + let removed = 0; + + for (const key in source) { + if (!target[key]) { + target[key] = `*** ${source[key]}`; + added++; + } + } + + for (const key in target) { + if (!source[key]) { + delete target[key]; + removed++; + } + } + + const newLength = Object.keys(target).length; + + return { result: target, stats: { added, removed, newLength } }; +} + +module.exports = { + getMissingTranslations, +}; diff --git a/common/translations-cli/helpers.js b/common/translations-cli/helpers.js index 512e330be..3bcc9180f 100644 --- a/common/translations-cli/helpers.js +++ b/common/translations-cli/helpers.js @@ -122,6 +122,46 @@ const getTranslationChanges = (existingTranslations, newTranslations) => { return { added, removed, updated }; }; +const defaultLanguage = 'en-US'; + +function getDefaultTranslations() { + return getLanguageTranslations(defaultLanguage); +} + +/** + * @param {string} language + * + * @returns {Record} + */ +function getLanguageTranslations(language) { + const file = resolveFile(`translations/${language}.json`); + const content = fs.readFileSync(file, 'utf-8'); + + return JSON.parse(content); +} + +/** + * @param {string} language + * @param {Record} translations + */ +function setLanguageTranslations(language, translations) { + const file = resolveFile(`translations/${language}.json`); + fs.writeFileSync(file, JSON.stringify(translations, null, 2)); +} + +function getAllLanguages() { + const dir = resolveFile('translations'); + + const files = fs.readdirSync(dir); + const languages = files.filter(file => file.endsWith('.json')).map(file => file.replace('.json', '')); + + return languages; +} + +function getAllNonDefaultLanguages() { + return getAllLanguages().filter(language => language !== defaultLanguage); +} + module.exports = { hasValidExtension, getFiles, @@ -131,4 +171,9 @@ module.exports = { resolveExtensions, ensureFileDirExists, getTranslationChanges, + getDefaultTranslations, + getLanguageTranslations, + setLanguageTranslations, + getAllLanguages, + getAllNonDefaultLanguages, }; diff --git a/common/translations-cli/program.js b/common/translations-cli/program.js index 15ba3a2ac..c12532abf 100644 --- a/common/translations-cli/program.js +++ b/common/translations-cli/program.js @@ -7,15 +7,18 @@ const { resolveFile, ensureFileDirExists, getTranslationChanges, + setLanguageTranslations, + getAllNonDefaultLanguages, } = require('./helpers'); const { extractAllTranslations } = require('./extract'); +const { getMissingTranslations } = require('./addMissing'); /** - * @typedef {{ extensions: string[], directories: string[], outputFile: string}} Config - * @typedef {Config & { verbose?: boolean }} Options + * @typedef {{ extensions: string[], directories: string[], outputFile: string}} ExtractConfig + * @typedef {ExtractConfig & { verbose?: boolean }} ExtractOptions */ -/** @type {Config} */ +/** @type {ExtractConfig} */ const defaultConfig = { extensions: ['.js', '.ts', '.svelte'], directories: ['app', 'packages/web'], @@ -31,7 +34,7 @@ program .option('-e, --extensions ', 'file extensions to process', defaultConfig.extensions) .option('-o, --outputFile ', 'output file path', defaultConfig.outputFile) .option('-v, --verbose', 'verbose mode') - .action(async (/** @type {Options} */ options) => { + .action(async (/** @type {ExtractOptions} */ options) => { try { const { directories, extensions, outputFile, verbose } = options; @@ -86,4 +89,42 @@ program } }); +const ALL_LANGUAGES = 'all'; + +/** + * @param {string} target + */ +function addMissingTranslations(target) { + console.log(`Adding missing keys for language: ${target}`); + const { result, stats } = getMissingTranslations(target); + console.log(`Added: ${stats.added}, Removed: ${stats.removed}, Total: ${stats.newLength}`); + setLanguageTranslations(target, result); + console.log(`New translations for ${target} were saved.`); +} + +program + .command('add-missing') + .description('Add missing keys for a langauge to the translation file') + .option('-t, --target ', 'language to add missing translations to', ALL_LANGUAGES) + .action(options => { + try { + const { target } = options; + const languages = getAllNonDefaultLanguages(); + + if (target === ALL_LANGUAGES) { + console.log('Adding missing keys for all languages\n'); + for (const language of languages) { + addMissingTranslations(language); + console.log(); + } + } else { + addMissingTranslations(target); + } + } catch (error) { + console.error(error); + console.error('Error during add-missing:', error.message); + process.exit(1); + } + }); + module.exports = { program }; diff --git a/package.json b/package.json index 85f3d8e2c..4671457a4 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,9 @@ "postinstall": "yarn resetPackagedPlugins && yarn build:lib && patch-package && yarn build:plugins:frontend", "dbgate-serve": "node packages/dbgate/bin/dbgate-serve.js", "workflows": "node common/processWorkflows.js", - "cy:open": "cd e2e-tests && yarn cy:open" - "translations:extract": "node common/translations-cli/index.js extract" + "cy:open": "cd e2e-tests && yarn cy:open", + "translations:extract": "node common/translations-cli/index.js extract", + "translations:add-missing": "node common/translations-cli/index.js add-missing" }, "dependencies": { "concurrently": "^5.1.0",