mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
* Parallel tasks * Handle null [x]ModelInfo types, recover from settings schema parse errors (#2064) * Require exactly node v20.18.1 (#2065) * Get rid of runner and all CJS stuff * Add an activation command for other extensions (#2073) Since VS Code provides no actionEvents that trigger when a specific extension activates, extensions can't activate only once Roo is activated and ready. This commit introduces a new roo-cline.activationCompleted command and fires it at the very end of extension activation. Other extensions that use Roo's exported APIs can now activate when they see this event. Co-authored-by: Greg Taylor <gregtaylor@netflix.com> * Update bug_report.yml (#1994) * Update bug_report.yml * Update bug_report.yml --------- Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com> * Fix mention file name is not fully displayed (#2026) Fixed path leading character handling to preserve language characters and remove specific punctuation marks * In-Editor Browser Improvements (#1601) * Browser Automation Improvements * Added multi-tab remote Chrome support * Added support for hover * Properly caching remote browser host in global state * Cleanup functions * Updated for changes after merge * Added www. exception for common tabs * Update src/core/webview/ClineProvider.ts * Revert README changes --------- Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com> * Add missing awaits on refactored tools (#2078) * More progress * Added Gemini 2.5 Pro model to GCP Vertex AI Provider (#2079) * More progress * Display info about partial reads in chat row (#2080) * More progress * Update contributors list (#2023) docs: update contributors list [skip ci] Co-authored-by: mrubens <mrubens@users.noreply.github.com> * More progress * Handle multiple API pages worth of contributors (#2088) * Update contributors list (#2089) docs: update contributors list [skip ci] Co-authored-by: mrubens <mrubens@users.noreply.github.com> * Refactor/cline.ts/list files (#2067) * "Refactor list_files tool to separate module (#2057)" * Await --------- Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com> * Remove switch from tools (#2091) * HandleError returns a promise * Remove unnecessary switch from tools * Fix a type in the listFiles tool (#2092) * Move write_to_file to a tool file (#2093) * Move apply_diff to a tool file (#2094) * Move insert_content to a tool file (#2095) * Move search_and_replace to a tool file (#2096) * Move list_code_definition_names to a tool file (#2097) * Move search_files to a tool file (#2098) * Move browser_action to a tool file (#2099) * Move execute_command to a tool file (#2100) * Move use_mcp_tool and access_mcp_resource to tool files (#2101) * Move new_task, switch_mode, attempt_completion, and ask_followup_question to tool files (#2102) * Do a little code cleanup now that tools are refactored out (#2103) * Clean up the way we compute the current diff strategy (#2049) * Clean up the way we compute the current diff strategy * Add changeset * i18n Add translations for task pinning and unpinning (#2109) Signed-off-by: feifei <liuyansheng1121@gmail.com> * Remove the ask promise error (#2107) * Remove the ask promise error * Send start_time along with checkpoints and use it to position in the messages * Link to the settings page from the auto approve toolbar (#2111) * Link to provider docs from the API options (#2112) * Revert "Remove the ask promise error" (#2117) Revert "Remove the ask promise error (#2107)" This reverts commit712ca71ee0. * Parse the retry out of the gemini 429 response (#2118) * Fix Gemini command escaping (#2120) * Fix switching profiles to ensure only the selected profile is switche… (#2119) Fix switching profiles to ensure only the selected profile is switched for all modes, and optimize certain i18n keys. Signed-off-by: feifei <liuyansheng1121@gmail.com> * Tweaks to support prompt line number format (#2121) * Remove the ask promise error (#2123) * Stronger typing * Added Gemini 2.5 Pro model to GCP Vertex AI Provider (#2079) * Display info about partial reads in chat row (#2080) * Update contributors list (#2023) docs: update contributors list [skip ci] Co-authored-by: mrubens <mrubens@users.noreply.github.com> * Handle multiple API pages worth of contributors (#2088) * Update contributors list (#2089) docs: update contributors list [skip ci] Co-authored-by: mrubens <mrubens@users.noreply.github.com> * Refactor/cline.ts/list files (#2067) * "Refactor list_files tool to separate module (#2057)" * Await --------- Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com> * Remove switch from tools (#2091) * HandleError returns a promise * Remove unnecessary switch from tools * Fix a type in the listFiles tool (#2092) * Move write_to_file to a tool file (#2093) * Move apply_diff to a tool file (#2094) * Move insert_content to a tool file (#2095) * Move search_and_replace to a tool file (#2096) * Move list_code_definition_names to a tool file (#2097) * Move search_files to a tool file (#2098) * Move browser_action to a tool file (#2099) * Move execute_command to a tool file (#2100) * Move use_mcp_tool and access_mcp_resource to tool files (#2101) * Move new_task, switch_mode, attempt_completion, and ask_followup_question to tool files (#2102) * Do a little code cleanup now that tools are refactored out (#2103) * Clean up the way we compute the current diff strategy (#2049) * Clean up the way we compute the current diff strategy * Add changeset * i18n Add translations for task pinning and unpinning (#2109) Signed-off-by: feifei <liuyansheng1121@gmail.com> * Remove the ask promise error (#2107) * Remove the ask promise error * Send start_time along with checkpoints and use it to position in the messages * Link to the settings page from the auto approve toolbar (#2111) * Link to provider docs from the API options (#2112) * Revert "Remove the ask promise error" (#2117) Revert "Remove the ask promise error (#2107)" This reverts commit712ca71ee0. * Parse the retry out of the gemini 429 response (#2118) * Fix Gemini command escaping (#2120) * Fix switching profiles to ensure only the selected profile is switche… (#2119) Fix switching profiles to ensure only the selected profile is switched for all modes, and optimize certain i18n keys. Signed-off-by: feifei <liuyansheng1121@gmail.com> * Tweaks to support prompt line number format (#2121) * Remove the ask promise error (#2123) * Pass along pid and ppid * Revert "Remove the ask promise error" (#2126) Revert "Remove the ask promise error (#2123)" This reverts commitb788aa1ec4. --------- Signed-off-by: feifei <liuyansheng1121@gmail.com> Co-authored-by: Greg Taylor <gtaylor@users.noreply.github.com> Co-authored-by: Greg Taylor <gregtaylor@netflix.com> Co-authored-by: Hannes Rudolph <hrudolph@gmail.com> Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com> Co-authored-by: aheizi <aheizi@outlook.com> Co-authored-by: Afshawn Lotfi <6283745+afshawnlotfi@users.noreply.github.com> Co-authored-by: Nico Bihan <nicolas.bihan@wellsky.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Bhavesh Ramburn <nitrogen@gmail.com> Co-authored-by: feifei <46489071+feifei325@users.noreply.github.com>
204 lines
5.5 KiB
JavaScript
204 lines
5.5 KiB
JavaScript
const fs = require("fs")
|
|
const path = require("path")
|
|
|
|
// Parse command-line arguments
|
|
const args = process.argv.slice(2).reduce((acc, arg) => {
|
|
if (arg === "--help") {
|
|
acc.help = true
|
|
} else if (arg.startsWith("--locale=")) {
|
|
acc.locale = arg.split("=")[1]
|
|
} else if (arg.startsWith("--file=")) {
|
|
acc.file = arg.split("=")[1]
|
|
}
|
|
return acc
|
|
}, {})
|
|
|
|
// Display help information
|
|
if (args.help) {
|
|
console.log(`
|
|
Find missing i18n translations
|
|
|
|
A useful script to identify whether the i18n keys used in component files exist in all language files.
|
|
|
|
Usage:
|
|
node scripts/find-missing-i18n-key.js [options]
|
|
|
|
Options:
|
|
--locale=<locale> Only check a specific language (e.g., --locale=de)
|
|
--file=<file> Only check a specific file (e.g., --file=chat.json)
|
|
--help Display help information
|
|
|
|
Output:
|
|
- Generate a report of missing translations
|
|
`)
|
|
process.exit(0)
|
|
}
|
|
|
|
// Directories to traverse and their corresponding locales
|
|
const DIRS = {
|
|
components: {
|
|
path: path.join(__dirname, "../webview-ui/src/components"),
|
|
localesDir: path.join(__dirname, "../webview-ui/src/i18n/locales"),
|
|
},
|
|
src: {
|
|
path: path.join(__dirname, "../src"),
|
|
localesDir: path.join(__dirname, "../src/i18n/locales"),
|
|
},
|
|
}
|
|
|
|
// Regular expressions to match i18n keys
|
|
const i18nPatterns = [
|
|
/{t\("([^"]+)"\)}/g, // Match {t("key")} format
|
|
/i18nKey="([^"]+)"/g, // Match i18nKey="key" format
|
|
/t\("([a-zA-Z][a-zA-Z0-9_]*[:.][a-zA-Z0-9_.]+)"\)/g, // Match t("key") format, where key contains a colon or dot
|
|
]
|
|
|
|
// Get all language directories for a specific locales directory
|
|
function getLocaleDirs(localesDir) {
|
|
try {
|
|
const allLocales = fs.readdirSync(localesDir).filter((file) => {
|
|
const stats = fs.statSync(path.join(localesDir, file))
|
|
return stats.isDirectory() // Do not exclude any language directories
|
|
})
|
|
|
|
// Filter to a specific language if specified
|
|
return args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales
|
|
} catch (error) {
|
|
if (error.code === "ENOENT") {
|
|
console.warn(`Warning: Locales directory not found: ${localesDir}`)
|
|
return []
|
|
}
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// Get the value from JSON by path
|
|
function getValueByPath(obj, path) {
|
|
const parts = path.split(".")
|
|
let current = obj
|
|
|
|
for (const part of parts) {
|
|
if (current === undefined || current === null) {
|
|
return undefined
|
|
}
|
|
current = current[part]
|
|
}
|
|
|
|
return current
|
|
}
|
|
|
|
// Check if the key exists in all language files, return a list of missing language files
|
|
function checkKeyInLocales(key, localeDirs, localesDir) {
|
|
const [file, ...pathParts] = key.split(":")
|
|
const jsonPath = pathParts.join(".")
|
|
|
|
const missingLocales = []
|
|
|
|
localeDirs.forEach((locale) => {
|
|
const filePath = path.join(localesDir, locale, `${file}.json`)
|
|
if (!fs.existsSync(filePath)) {
|
|
missingLocales.push(`${locale}/${file}.json`)
|
|
return
|
|
}
|
|
|
|
const json = JSON.parse(fs.readFileSync(filePath, "utf8"))
|
|
if (getValueByPath(json, jsonPath) === undefined) {
|
|
missingLocales.push(`${locale}/${file}.json`)
|
|
}
|
|
})
|
|
|
|
return missingLocales
|
|
}
|
|
|
|
// Recursively traverse the directory
|
|
function findMissingI18nKeys() {
|
|
const results = []
|
|
|
|
function walk(dir, baseDir, localeDirs, localesDir) {
|
|
const files = fs.readdirSync(dir)
|
|
|
|
for (const file of files) {
|
|
const filePath = path.join(dir, file)
|
|
const stat = fs.statSync(filePath)
|
|
|
|
// Exclude test files and __mocks__ directory
|
|
if (filePath.includes(".test.") || filePath.includes("__mocks__")) continue
|
|
|
|
if (stat.isDirectory()) {
|
|
walk(filePath, baseDir, localeDirs, localesDir) // Recursively traverse subdirectories
|
|
} else if (stat.isFile() && [".ts", ".tsx", ".js", ".jsx"].includes(path.extname(filePath))) {
|
|
const content = fs.readFileSync(filePath, "utf8")
|
|
|
|
// Match all i18n keys
|
|
for (const pattern of i18nPatterns) {
|
|
let match
|
|
while ((match = pattern.exec(content)) !== null) {
|
|
const key = match[1]
|
|
const missingLocales = checkKeyInLocales(key, localeDirs, localesDir)
|
|
if (missingLocales.length > 0) {
|
|
results.push({
|
|
key,
|
|
missingLocales,
|
|
file: path.relative(baseDir, filePath),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Walk through all directories
|
|
Object.entries(DIRS).forEach(([name, config]) => {
|
|
const localeDirs = getLocaleDirs(config.localesDir)
|
|
if (localeDirs.length > 0) {
|
|
console.log(`\nChecking ${name} directory with ${localeDirs.length} languages: ${localeDirs.join(", ")}`)
|
|
walk(config.path, config.path, localeDirs, config.localesDir)
|
|
}
|
|
})
|
|
|
|
return results
|
|
}
|
|
|
|
// Execute and output the results
|
|
function main() {
|
|
try {
|
|
if (args.locale) {
|
|
// Check if the specified locale exists in any of the locales directories
|
|
const localeExists = Object.values(DIRS).some((config) => {
|
|
const localeDirs = getLocaleDirs(config.localesDir)
|
|
return localeDirs.includes(args.locale)
|
|
})
|
|
|
|
if (!localeExists) {
|
|
console.error(`Error: Language '${args.locale}' not found in any locales directory`)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
const missingKeys = findMissingI18nKeys()
|
|
|
|
if (missingKeys.length === 0) {
|
|
console.log("\n✅ All i18n keys are present!")
|
|
return
|
|
}
|
|
|
|
console.log("\nMissing i18n keys:\n")
|
|
missingKeys.forEach(({ key, missingLocales, file }) => {
|
|
console.log(`File: ${file}`)
|
|
console.log(`Key: ${key}`)
|
|
console.log("Missing in:")
|
|
missingLocales.forEach((file) => console.log(` - ${file}`))
|
|
console.log("-------------------")
|
|
})
|
|
|
|
// Exit code 1 indicates missing keys
|
|
process.exit(1)
|
|
} catch (error) {
|
|
console.error("Error:", error.message)
|
|
console.error(error.stack)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
main()
|