فهرست منبع

Extension-side internationalization (#1757)

* Extension-side internationalization

* Update script

* Cleaner esbuild

* Turn off debugging

* PR feedback

* Update src/i18n/locales/en/common.json

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Update src/i18n/locales/ca/common.json

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Matt Rubens 9 ماه پیش
والد
کامیت
38655825d4

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
.roomodes


+ 1 - 0
.vscodeignore

@@ -28,6 +28,7 @@ demo.gif
 .roomodes
 cline_docs/**
 coverage/**
+locales/**
 
 # Ignore all webview-ui files except the build directory (https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/hello-world-react-cra/.vscodeignore)
 webview-ui/src/**

+ 107 - 0
esbuild.js

@@ -63,6 +63,103 @@ const copyWasmFiles = {
 	},
 }
 
+// Simple function to copy locale files
+function copyLocaleFiles() {
+	const srcDir = path.join(__dirname, "src", "i18n", "locales")
+	const destDir = path.join(__dirname, "dist", "i18n", "locales")
+	const outDir = path.join(__dirname, "out", "i18n", "locales")
+
+	// Ensure source directory exists before proceeding
+	if (!fs.existsSync(srcDir)) {
+		console.warn(`Source locales directory does not exist: ${srcDir}`)
+		return // Exit early if source directory doesn't exist
+	}
+
+	// Create destination directories
+	fs.mkdirSync(destDir, { recursive: true })
+	try {
+		fs.mkdirSync(outDir, { recursive: true })
+	} catch (e) {}
+
+	// Function to copy directory recursively
+	function copyDir(src, dest) {
+		const entries = fs.readdirSync(src, { withFileTypes: true })
+
+		for (const entry of entries) {
+			const srcPath = path.join(src, entry.name)
+			const destPath = path.join(dest, entry.name)
+
+			if (entry.isDirectory()) {
+				// Create directory and copy contents
+				fs.mkdirSync(destPath, { recursive: true })
+				copyDir(srcPath, destPath)
+			} else {
+				// Copy the file
+				fs.copyFileSync(srcPath, destPath)
+			}
+		}
+	}
+
+	// Copy files to dist directory
+	copyDir(srcDir, destDir)
+	console.log("Copied locale files to dist/i18n/locales")
+
+	// Copy to out directory for debugging
+	try {
+		copyDir(srcDir, outDir)
+		console.log("Copied locale files to out/i18n/locales")
+	} catch (e) {
+		console.warn("Could not copy to out directory:", e.message)
+	}
+}
+
+// Set up file watcher if in watch mode
+function setupLocaleWatcher() {
+	if (!watch) return
+
+	const localesDir = path.join(__dirname, "src", "i18n", "locales")
+
+	// Ensure the locales directory exists before setting up watcher
+	if (!fs.existsSync(localesDir)) {
+		console.warn(`Cannot set up watcher: Source locales directory does not exist: ${localesDir}`)
+		return
+	}
+
+	console.log(`Setting up watcher for locale files in ${localesDir}`)
+
+	// Use a debounce mechanism
+	let debounceTimer = null
+	const debouncedCopy = () => {
+		if (debounceTimer) clearTimeout(debounceTimer)
+		debounceTimer = setTimeout(() => {
+			console.log("Locale files changed, copying...")
+			copyLocaleFiles()
+		}, 300) // Wait 300ms after last change before copying
+	}
+
+	// Watch the locales directory
+	try {
+		fs.watch(localesDir, { recursive: true }, (eventType, filename) => {
+			if (filename && filename.endsWith(".json")) {
+				console.log(`Locale file ${filename} changed, triggering copy...`)
+				debouncedCopy()
+			}
+		})
+		console.log("Watcher for locale files is set up")
+	} catch (error) {
+		console.error(`Error setting up watcher for ${localesDir}:`, error.message)
+	}
+}
+
+const copyLocalesFiles = {
+	name: "copy-locales-files",
+	setup(build) {
+		build.onEnd(() => {
+			copyLocaleFiles()
+		})
+	},
+}
+
 const extensionConfig = {
 	bundle: true,
 	minify: production,
@@ -70,6 +167,7 @@ const extensionConfig = {
 	logLevel: "silent",
 	plugins: [
 		copyWasmFiles,
+		copyLocalesFiles,
 		/* add to the end of plugins array */
 		esbuildProblemMatcherPlugin,
 		{
@@ -91,8 +189,17 @@ const extensionConfig = {
 
 async function main() {
 	const extensionCtx = await esbuild.context(extensionConfig)
+
 	if (watch) {
+		// Start the esbuild watcher
 		await extensionCtx.watch()
+
+		// Copy and watch locale files
+		console.log("Copying locale files initially...")
+		copyLocaleFiles()
+
+		// Set up the watcher for locale files
+		setupLocaleWatcher()
 	} else {
 		await extensionCtx.rebuild()
 		await extensionCtx.dispose()

+ 0 - 1
package-lock.json

@@ -12547,7 +12547,6 @@
 			"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
 			"integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
 			"dev": true,
-			"license": "MIT",
 			"dependencies": {
 				"ansi-styles": "^3.2.1",
 				"chalk": "^2.4.1",

+ 1 - 0
package.json

@@ -345,6 +345,7 @@
 		"fastest-levenshtein": "^1.0.16",
 		"get-folder-size": "^5.0.0",
 		"globby": "^14.0.2",
+		"i18next": "^24.2.2",
 		"isbinaryfile": "^5.0.2",
 		"js-tiktoken": "^1.0.19",
 		"mammoth": "^1.8.0",

+ 144 - 99
scripts/find-missing-translations.js

@@ -7,6 +7,7 @@
  * Options:
  *   --locale=<locale>   Only check a specific locale (e.g. --locale=fr)
  *   --file=<file>       Only check a specific file (e.g. --file=chat.json)
+ *   --area=<area>       Only check a specific area (core, webview, or both)
  *   --help              Show this help message
  */
 
@@ -14,16 +15,26 @@ const fs = require("fs")
 const path = require("path")
 
 // Process 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
-}, {})
+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]
+		} else if (arg.startsWith("--area=")) {
+			acc.area = arg.split("=")[1]
+			// Validate area value
+			if (!["core", "webview", "both"].includes(acc.area)) {
+				console.error(`Error: Invalid area '${acc.area}'. Must be 'core', 'webview', or 'both'.`)
+				process.exit(1)
+			}
+		}
+		return acc
+	},
+	{ area: "both" },
+) // Default to checking both areas
 
 // Show help if requested
 if (args.help) {
@@ -33,22 +44,32 @@ Find Missing Translations
 A utility script to identify missing translations across locale files.
 Compares non-English locale files to the English ones to find any missing keys.
 
-Usage: 
+Usage:
   node scripts/find-missing-translations.js [options]
 
 Options:
   --locale=<locale>   Only check a specific locale (e.g. --locale=fr)
   --file=<file>       Only check a specific file (e.g. --file=chat.json)
+  --area=<area>       Only check a specific area (core, webview, or both)
+                      'core' = Backend (src/i18n/locales)
+                      'webview' = Frontend UI (webview-ui/src/i18n/locales)
+                      'both' = Check both areas (default)
   --help              Show this help message
 
 Output:
-  - Generates a report of missing translations
+  - Generates a report of missing translations for each area
   `)
 	process.exit(0)
 }
 
-// Path to the locales directory
-const LOCALES_DIR = path.join(__dirname, "../webview-ui/src/i18n/locales")
+// Paths to the locales directories
+const LOCALES_DIRS = {
+	core: path.join(__dirname, "../src/i18n/locales"),
+	webview: path.join(__dirname, "../webview-ui/src/i18n/locales"),
+}
+
+// Determine which areas to check based on args
+const areasToCheck = args.area === "both" ? ["core", "webview"] : [args.area]
 
 // Recursively find all keys in an object
 function findKeys(obj, parentKey = "") {
@@ -84,125 +105,149 @@ function getValueAtPath(obj, path) {
 	return current
 }
 
-// Main function to find missing translations
-function findMissingTranslations() {
-	try {
-		// Get all locale directories (or filter to the specified locale)
-		const allLocales = fs.readdirSync(LOCALES_DIR).filter((item) => {
-			const stats = fs.statSync(path.join(LOCALES_DIR, item))
-			return stats.isDirectory() && item !== "en" // Exclude English as it's our source
-		})
+// Function to check translations for a specific area
+function checkAreaTranslations(area) {
+	const LOCALES_DIR = LOCALES_DIRS[area]
 
-		// Filter to the specified locale if provided
-		const locales = args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales
+	// Get all locale directories (or filter to the specified locale)
+	const allLocales = fs.readdirSync(LOCALES_DIR).filter((item) => {
+		const stats = fs.statSync(path.join(LOCALES_DIR, item))
+		return stats.isDirectory() && item !== "en" // Exclude English as it's our source
+	})
 
-		if (args.locale && locales.length === 0) {
-			console.error(`Error: Locale '${args.locale}' not found in ${LOCALES_DIR}`)
-			process.exit(1)
-		}
+	// Filter to the specified locale if provided
+	const locales = args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales
 
-		console.log(`Checking ${locales.length} non-English locale(s): ${locales.join(", ")}`)
+	if (args.locale && locales.length === 0) {
+		console.error(`Error: Locale '${args.locale}' not found in ${LOCALES_DIR}`)
+		process.exit(1)
+	}
 
-		// Get all English JSON files
-		const englishDir = path.join(LOCALES_DIR, "en")
-		let englishFiles = fs.readdirSync(englishDir).filter((file) => file.endsWith(".json") && !file.startsWith("."))
+	console.log(
+		`\n${area === "core" ? "BACKEND" : "FRONTEND"} - Checking ${locales.length} non-English locale(s): ${locales.join(", ")}`,
+	)
 
-		// Filter to the specified file if provided
-		if (args.file) {
-			if (!englishFiles.includes(args.file)) {
-				console.error(`Error: File '${args.file}' not found in ${englishDir}`)
-				process.exit(1)
-			}
-			englishFiles = englishFiles.filter((file) => file === args.file)
+	// Get all English JSON files
+	const englishDir = path.join(LOCALES_DIR, "en")
+	let englishFiles = fs.readdirSync(englishDir).filter((file) => file.endsWith(".json") && !file.startsWith("."))
+
+	// Filter to the specified file if provided
+	if (args.file) {
+		if (!englishFiles.includes(args.file)) {
+			console.error(`Error: File '${args.file}' not found in ${englishDir}`)
+			process.exit(1)
 		}
+		englishFiles = englishFiles.filter((file) => file === args.file)
+	}
 
-		// Load file contents
-		const englishFileContents = englishFiles.map((file) => ({
-			name: file,
-			content: JSON.parse(fs.readFileSync(path.join(englishDir, file), "utf8")),
-		}))
+	// Load file contents
+	const englishFileContents = englishFiles.map((file) => ({
+		name: file,
+		content: JSON.parse(fs.readFileSync(path.join(englishDir, file), "utf8")),
+	}))
 
-		console.log(
-			`Checking ${englishFileContents.length} translation file(s): ${englishFileContents.map((f) => f.name).join(", ")}`,
-		)
+	console.log(
+		`Checking ${englishFileContents.length} translation file(s): ${englishFileContents.map((f) => f.name).join(", ")}`,
+	)
 
-		// Results object to store missing translations
-		const missingTranslations = {}
+	// Results object to store missing translations
+	const missingTranslations = {}
 
-		// For each locale, check for missing translations
-		for (const locale of locales) {
-			missingTranslations[locale] = {}
+	// For each locale, check for missing translations
+	for (const locale of locales) {
+		missingTranslations[locale] = {}
 
-			for (const { name, content: englishContent } of englishFileContents) {
-				const localeFilePath = path.join(LOCALES_DIR, locale, name)
+		for (const { name, content: englishContent } of englishFileContents) {
+			const localeFilePath = path.join(LOCALES_DIR, locale, name)
 
-				// Check if the file exists in the locale
-				if (!fs.existsSync(localeFilePath)) {
-					missingTranslations[locale][name] = { file: "File is missing entirely" }
-					continue
-				}
+			// Check if the file exists in the locale
+			if (!fs.existsSync(localeFilePath)) {
+				missingTranslations[locale][name] = { file: "File is missing entirely" }
+				continue
+			}
 
-				// Load the locale file
-				const localeContent = JSON.parse(fs.readFileSync(localeFilePath, "utf8"))
+			// Load the locale file
+			const localeContent = JSON.parse(fs.readFileSync(localeFilePath, "utf8"))
 
-				// Find all keys in the English file
-				const englishKeys = findKeys(englishContent)
+			// Find all keys in the English file
+			const englishKeys = findKeys(englishContent)
 
-				// Check for missing keys in the locale file
-				const missingKeys = []
+			// Check for missing keys in the locale file
+			const missingKeys = []
 
-				for (const key of englishKeys) {
-					const englishValue = getValueAtPath(englishContent, key)
-					const localeValue = getValueAtPath(localeContent, key)
+			for (const key of englishKeys) {
+				const englishValue = getValueAtPath(englishContent, key)
+				const localeValue = getValueAtPath(localeContent, key)
 
-					if (localeValue === undefined) {
-						missingKeys.push({
-							key,
-							englishValue,
-						})
-					}
+				if (localeValue === undefined) {
+					missingKeys.push({
+						key,
+						englishValue,
+					})
 				}
+			}
 
-				if (missingKeys.length > 0) {
-					missingTranslations[locale][name] = missingKeys
-				}
+			if (missingKeys.length > 0) {
+				missingTranslations[locale][name] = missingKeys
 			}
 		}
+	}
+
+	return { missingTranslations, hasMissingTranslations: outputResults(missingTranslations, area) }
+}
 
-		// Output results
-		let hasMissingTranslations = false
+// Function to output results for an area
+function outputResults(missingTranslations, area) {
+	let hasMissingTranslations = false
 
-		console.log("\nMissing Translations Report:\n")
+	console.log(`\n${area === "core" ? "BACKEND" : "FRONTEND"} Missing Translations Report:\n`)
 
-		for (const [locale, files] of Object.entries(missingTranslations)) {
-			if (Object.keys(files).length === 0) {
-				console.log(`✅ ${locale}: No missing translations`)
+	for (const [locale, files] of Object.entries(missingTranslations)) {
+		if (Object.keys(files).length === 0) {
+			console.log(`✅ ${locale}: No missing translations`)
+			continue
+		}
+
+		hasMissingTranslations = true
+		console.log(`📝 ${locale}:`)
+
+		for (const [fileName, missingItems] of Object.entries(files)) {
+			if (missingItems.file) {
+				console.log(`  - ${fileName}: ${missingItems.file}`)
 				continue
 			}
 
-			hasMissingTranslations = true
-			console.log(`📝 ${locale}:`)
+			console.log(`  - ${fileName}: ${missingItems.length} missing translations`)
 
-			for (const [fileName, missingItems] of Object.entries(files)) {
-				if (missingItems.file) {
-					console.log(`  - ${fileName}: ${missingItems.file}`)
-					continue
-				}
+			for (const { key, englishValue } of missingItems) {
+				console.log(`      ${key}: "${englishValue}"`)
+			}
+		}
 
-				console.log(`  - ${fileName}: ${missingItems.length} missing translations`)
+		console.log("")
+	}
 
-				for (const { key, englishValue } of missingItems) {
-					console.log(`      ${key}: "${englishValue}"`)
-				}
-			}
+	return hasMissingTranslations
+}
+
+// Main function to find missing translations
+function findMissingTranslations() {
+	try {
+		console.log("Starting translation check...")
+
+		let anyAreaMissingTranslations = false
 
-			console.log("")
+		// Check each requested area
+		for (const area of areasToCheck) {
+			const { hasMissingTranslations } = checkAreaTranslations(area)
+			anyAreaMissingTranslations = anyAreaMissingTranslations || hasMissingTranslations
 		}
 
-		if (!hasMissingTranslations) {
-			console.log("\n✅ All translations are complete!")
+		// Summary
+		if (!anyAreaMissingTranslations) {
+			console.log("\n✅ All translations are complete across all checked areas!")
 		} else {
-			console.log("✏️  To add missing translations:")
+			console.log("\n✏️  To add missing translations:")
 			console.log("1. Add the missing keys to the corresponding locale files")
 			console.log("2. Translate the English values to the appropriate language")
 			console.log("3. Run this script again to verify all translations are complete")

+ 2 - 1
src/activate/registerTerminalActions.ts

@@ -1,6 +1,7 @@
 import * as vscode from "vscode"
 import { ClineProvider } from "../core/webview/ClineProvider"
 import { Terminal } from "../integrations/terminal/Terminal"
+import { t } from "../i18n"
 
 const TERMINAL_COMMAND_IDS = {
 	ADD_TO_CONTEXT: "roo-cline.terminalAddToContext",
@@ -37,7 +38,7 @@ const registerTerminalAction = (
 			}
 
 			if (!content) {
-				vscode.window.showWarningMessage("No terminal content selected")
+				vscode.window.showWarningMessage(t("common:warnings.no_terminal_content"))
 				return
 			}
 

+ 46 - 47
src/core/webview/ClineProvider.ts

@@ -8,6 +8,7 @@ import pWaitFor from "p-wait-for"
 import * as path from "path"
 import * as vscode from "vscode"
 
+import { changeLanguage, t } from "../../i18n"
 import { setPanel } from "../../activate/registerCommands"
 import { ApiConfiguration, ApiProvider, ModelInfo, API_CONFIG_KEYS } from "../../shared/api"
 import { findLast } from "../../shared/array"
@@ -137,7 +138,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 		const state = await this.getState()
 
 		if (!state || typeof state.mode !== "string") {
-			throw new Error("Error failed to retrieve current mode from state.")
+			throw new Error(t("common:errors.retrieve_current_mode"))
 		}
 	}
 
@@ -564,9 +565,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 		try {
 			await axios.get(`http://${localServerUrl}`)
 		} catch (error) {
-			vscode.window.showErrorMessage(
-				"Local development server is not running, HMR will not work. Please run 'npm run dev' before launching the extension to enable HMR.",
-			)
+			vscode.window.showErrorMessage(t("common:errors.hmr_not_running"))
 
 			return this.getHtmlContent(webview)
 		}
@@ -976,7 +975,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 						break
 					case "clearTask":
 						// clear task resets the current session and allows for a new task to be started, if this session is a subtask - it allows the parent task to be resumed
-						await this.finishSubTask(`Task error: It was stopped and canceled by the user.`)
+						await this.finishSubTask(t("common:tasks.canceled"))
 						await this.postStateToWebview()
 						break
 					case "didShowAnnouncement":
@@ -1153,13 +1152,13 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							try {
 								await pWaitFor(() => this.getCurrentCline()?.isInitialized === true, { timeout: 3_000 })
 							} catch (error) {
-								vscode.window.showErrorMessage("Timed out when attempting to restore checkpoint.")
+								vscode.window.showErrorMessage(t("common:errors.checkpoint_timeout"))
 							}
 
 							try {
 								await this.getCurrentCline()?.checkpointRestore(result.data)
 							} catch (error) {
-								vscode.window.showErrorMessage("Failed to restore checkpoint.")
+								vscode.window.showErrorMessage(t("common:errors.checkpoint_failed"))
 							}
 						}
 
@@ -1184,7 +1183,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 					}
 					case "openProjectMcpSettings": {
 						if (!vscode.workspace.workspaceFolders?.length) {
-							vscode.window.showErrorMessage("Please open a project folder first")
+							vscode.window.showErrorMessage(t("common:errors.no_workspace"))
 							return
 						}
 
@@ -1200,7 +1199,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							}
 							await openFile(mcpPath)
 						} catch (error) {
-							vscode.window.showErrorMessage(`Failed to create or open .roo/mcp.json: ${error}`)
+							vscode.window.showErrorMessage(t("common:errors.create_mcp_json", { error }))
 						}
 						break
 					}
@@ -1478,7 +1477,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							this.outputChannel.appendLine(
 								`Error update support prompt: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 							)
-							vscode.window.showErrorMessage("Failed to update support prompt")
+							vscode.window.showErrorMessage(t("common:errors.update_support_prompt"))
 						}
 						break
 					case "resetSupportPrompt":
@@ -1502,7 +1501,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							this.outputChannel.appendLine(
 								`Error reset support prompt: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 							)
-							vscode.window.showErrorMessage("Failed to reset support prompt")
+							vscode.window.showErrorMessage(t("common:errors.reset_support_prompt"))
 						}
 						break
 					case "updatePrompt":
@@ -1533,13 +1532,14 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 						break
 					case "deleteMessage": {
 						const answer = await vscode.window.showInformationMessage(
-							"What would you like to delete?",
+							t("common:confirmation.delete_message"),
 							{ modal: true },
-							"Just this message",
-							"This and all subsequent messages",
+							t("common:confirmation.just_this_message"),
+							t("common:confirmation.this_and_subsequent"),
 						)
 						if (
-							(answer === "Just this message" || answer === "This and all subsequent messages") &&
+							(answer === t("common:confirmation.just_this_message") ||
+								answer === t("common:confirmation.this_and_subsequent")) &&
 							this.getCurrentCline() &&
 							typeof message.value === "number" &&
 							message.value
@@ -1556,7 +1556,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							if (messageIndex !== -1) {
 								const { historyItem } = await this.getTaskWithId(this.getCurrentCline()!.taskId)
 
-								if (answer === "Just this message") {
+								if (answer === t("common:confirmation.just_this_message")) {
 									// Find the next user message first
 									const nextUserMessage = this.getCurrentCline()!
 										.clineMessages.slice(messageIndex + 1)
@@ -1603,7 +1603,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 											)
 										}
 									}
-								} else if (answer === "This and all subsequent messages") {
+								} else if (answer === t("common:confirmation.this_and_subsequent")) {
 									// Delete this message and all that follow
 									await this.getCurrentCline()!.overwriteClineMessages(
 										this.getCurrentCline()!.clineMessages.slice(0, messageIndex),
@@ -1642,6 +1642,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 						await this.postStateToWebview()
 						break
 					case "language":
+						changeLanguage(message.text ?? "en")
 						await this.updateGlobalState("language", message.text)
 						await this.postStateToWebview()
 						break
@@ -1704,7 +1705,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error enhancing prompt: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to enhance prompt")
+								vscode.window.showErrorMessage(t("common:errors.enhance_prompt"))
 								await this.postMessageToWebview({
 									type: "enhancedPrompt",
 								})
@@ -1724,7 +1725,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							this.outputChannel.appendLine(
 								`Error getting system prompt:  ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 							)
-							vscode.window.showErrorMessage("Failed to get system prompt")
+							vscode.window.showErrorMessage(t("common:errors.get_system_prompt"))
 						}
 						break
 					case "copySystemPrompt":
@@ -1732,12 +1733,12 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							const systemPrompt = await generateSystemPrompt(message)
 
 							await vscode.env.clipboard.writeText(systemPrompt)
-							await vscode.window.showInformationMessage("System prompt successfully copied to clipboard")
+							await vscode.window.showInformationMessage(t("common:info.clipboard_copy"))
 						} catch (error) {
 							this.outputChannel.appendLine(
 								`Error getting system prompt:  ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 							)
-							vscode.window.showErrorMessage("Failed to get system prompt")
+							vscode.window.showErrorMessage(t("common:errors.get_system_prompt"))
 						}
 						break
 					case "searchCommits": {
@@ -1753,7 +1754,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error searching commits: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to search commits")
+								vscode.window.showErrorMessage(t("common:errors.search_commits"))
 							}
 						}
 						break
@@ -1768,7 +1769,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error save api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to save api configuration")
+								vscode.window.showErrorMessage(t("common:errors.save_api_config"))
 							}
 						}
 						break
@@ -1789,7 +1790,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error create new api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to create api configuration")
+								vscode.window.showErrorMessage(t("common:errors.create_api_config"))
 							}
 						}
 						break
@@ -1818,7 +1819,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error rename api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to rename api configuration")
+								vscode.window.showErrorMessage(t("common:errors.rename_api_config"))
 							}
 						}
 						break
@@ -1839,19 +1840,19 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error load api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to load api configuration")
+								vscode.window.showErrorMessage(t("common:errors.load_api_config"))
 							}
 						}
 						break
 					case "deleteApiConfiguration":
 						if (message.text) {
 							const answer = await vscode.window.showInformationMessage(
-								"Are you sure you want to delete this configuration profile?",
+								t("common:confirmation.delete_config_profile"),
 								{ modal: true },
-								"Yes",
+								t("common:answers.yes"),
 							)
 
-							if (answer !== "Yes") {
+							if (answer !== t("common:answers.yes")) {
 								break
 							}
 
@@ -1877,7 +1878,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Error delete api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to delete api configuration")
+								vscode.window.showErrorMessage(t("common:errors.delete_api_config"))
 							}
 						}
 						break
@@ -1890,7 +1891,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 							this.outputChannel.appendLine(
 								`Error get list api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 							)
-							vscode.window.showErrorMessage("Failed to get list api configuration")
+							vscode.window.showErrorMessage(t("common:errors.list_api_config"))
 						}
 						break
 					case "updateExperimental": {
@@ -1924,7 +1925,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 								this.outputChannel.appendLine(
 									`Failed to update timeout for ${message.serverName}: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
 								)
-								vscode.window.showErrorMessage("Failed to update server timeout")
+								vscode.window.showErrorMessage(t("common:errors.update_server_timeout"))
 							}
 						}
 						break
@@ -1941,12 +1942,12 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 					case "deleteCustomMode":
 						if (message.slug) {
 							const answer = await vscode.window.showInformationMessage(
-								"Are you sure you want to delete this custom mode?",
+								t("common:confirmation.delete_custom_mode"),
 								{ modal: true },
-								"Yes",
+								t("common:answers.yes"),
 							)
 
-							if (answer !== "Yes") {
+							if (answer !== t("common:answers.yes")) {
 								break
 							}
 
@@ -2319,12 +2320,12 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 			} catch (error) {
 				if (error.message === "TASK_FILES_MISSING") {
 					const response = await vscode.window.showWarningMessage(
-						"This task's files are missing. Would you like to remove it from the task list?",
-						"Remove",
-						"Keep",
+						t("common:warnings.missing_task_files"),
+						t("common:answers.remove"),
+						t("common:answers.keep"),
 					)
 
-					if (response === "Remove") {
+					if (response === t("common:answers.remove")) {
 						await this.deleteTaskFromState(id)
 						await this.postStateToWebview()
 					}
@@ -2345,14 +2346,14 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 	// this function deletes a task from task hidtory, and deletes it's checkpoints and delete the task folder
 	async deleteTaskWithId(id: string) {
 		try {
-			// Try to get the task directory full path
+			// get the task directory full path
 			const { taskDirPath } = await this.getTaskWithId(id)
 
 			// remove task from stack if it's the current task
 			if (id === this.getCurrentCline()?.taskId) {
 				// if we found the taskid to delete - call finish to abort this task and allow a new task to be started,
 				// if we are deleting a subtask and parent task is still waiting for subtask to finish - it allows the parent to resume (this case should neve exist)
-				await this.finishSubTask(`Task failure: It was stopped and deleted by the user.`)
+				await this.finishSubTask(t("common:tasks.deleted"))
 			}
 
 			// delete task from the task history state
@@ -2725,12 +2726,12 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 
 	async resetState() {
 		const answer = await vscode.window.showInformationMessage(
-			"Are you sure you want to reset all state and secret storage in the extension? This cannot be undone.",
+			t("common:confirmation.reset_state"),
 			{ modal: true },
-			"Yes",
+			t("common:answers.yes"),
 		)
 
-		if (answer !== "Yes") {
+		if (answer !== t("common:answers.yes")) {
 			return
 		}
 
@@ -2835,9 +2836,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 
 			const removedCount = history.length - validTasks.length
 			if (removedCount > 0) {
-				await vscode.window.showInformationMessage(
-					`Cleaned up ${removedCount} task(s) with missing files from history.`,
-				)
+				await vscode.window.showInformationMessage(t("common:info.history_cleanup", { count: removedCount }))
 			}
 		}
 	}

+ 5 - 0
src/extension.ts

@@ -13,6 +13,7 @@ try {
 
 import "./utils/path" // Necessary to have access to String.prototype.toPosix.
 
+import { initializeI18n } from "./i18n"
 import { ClineProvider } from "./core/webview/ClineProvider"
 import { CodeActionProvider } from "./core/CodeActionProvider"
 import { DIFF_VIEW_URI_SCHEME } from "./integrations/editor/DiffViewProvider"
@@ -22,6 +23,7 @@ import { TerminalRegistry } from "./integrations/terminal/TerminalRegistry"
 import { API } from "./exports/api"
 
 import { handleUri, registerCommands, registerCodeActions, registerTerminalActions } from "./activate"
+import { formatLanguage } from "./shared/language"
 
 /**
  * Built using https://github.com/microsoft/vscode-webview-ui-toolkit
@@ -45,6 +47,9 @@ export function activate(context: vscode.ExtensionContext) {
 	// Initialize telemetry service after environment variables are loaded.
 	telemetryService.initialize()
 
+	// Initialize i18n for internationalization support
+	initializeI18n(context.globalState.get("language") ?? formatLanguage(vscode.env.language))
+
 	// Initialize terminal shell execution handlers.
 	TerminalRegistry.initialize()
 

+ 41 - 0
src/i18n/index.ts

@@ -0,0 +1,41 @@
+import i18next from "./setup"
+
+/**
+ * Initialize i18next with the specified language
+ *
+ * @param language The language code to use
+ */
+export function initializeI18n(language: string): void {
+	i18next.changeLanguage(language)
+}
+
+/**
+ * Get the current language
+ *
+ * @returns The current language code
+ */
+export function getCurrentLanguage(): string {
+	return i18next.language
+}
+
+/**
+ * Change the current language
+ *
+ * @param language The language code to change to
+ */
+export function changeLanguage(language: string): void {
+	i18next.changeLanguage(language)
+}
+
+/**
+ * Translate a string using i18next
+ *
+ * @param key The translation key, can use namespace with colon, e.g. "common:welcome"
+ * @param options Options for interpolation or pluralization
+ * @returns The translated string
+ */
+export function t(key: string, options?: Record<string, any>): string {
+	return i18next.t(key, options)
+}
+
+export default i18next

+ 77 - 0
src/i18n/locales/ca/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Tot un equip de desenvolupadors d'IA al teu editor."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "M",
+		"billion_suffix": "MM"
+	},
+	"welcome": "Benvingut/da, {{name}}! Tens {{count}} notificacions.",
+	"items": {
+		"zero": "Cap element",
+		"one": "Un element",
+		"other": "{{count}} elements"
+	},
+	"confirmation": {
+		"reset_state": "Estàs segur que vols restablir tots els estats i emmagatzematge secret a l'extensió? Això no es pot desfer.",
+		"delete_config_profile": "Estàs segur que vols eliminar aquest perfil de configuració?",
+		"delete_custom_mode": "Estàs segur que vols eliminar aquest mode personalitzat?",
+		"delete_message": "Què vols eliminar?",
+		"just_this_message": "Només aquest missatge",
+		"this_and_subsequent": "Aquest i tots els missatges posteriors"
+	},
+	"errors": {
+		"invalid_mcp_config": "Format de configuració MCP del projecte no vàlid",
+		"invalid_mcp_settings_format": "Format JSON de configuració MCP no vàlid. Si us plau, assegura't que la teva configuració segueix el format JSON correcte.",
+		"invalid_mcp_settings_syntax": "Format JSON de configuració MCP no vàlid. Si us plau, comprova si hi ha errors de sintaxi al teu fitxer de configuració.",
+		"invalid_mcp_settings_validation": "Format de configuració MCP no vàlid: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Ha fallat la inicialització del servidor MCP del projecte: {{error}}",
+		"invalid_data_uri": "Format d'URI de dades no vàlid",
+		"checkpoint_timeout": "S'ha esgotat el temps en intentar restaurar el punt de control.",
+		"checkpoint_failed": "Ha fallat la restauració del punt de control.",
+		"no_workspace": "Si us plau, obre primer una carpeta de projecte",
+		"update_support_prompt": "Ha fallat l'actualització del missatge de suport",
+		"reset_support_prompt": "Ha fallat el restabliment del missatge de suport",
+		"enhance_prompt": "Ha fallat la millora del missatge",
+		"get_system_prompt": "Ha fallat l'obtenció del missatge del sistema",
+		"search_commits": "Ha fallat la cerca de commits",
+		"save_api_config": "Ha fallat el desament de la configuració de l'API",
+		"create_api_config": "Ha fallat la creació de la configuració de l'API",
+		"rename_api_config": "Ha fallat el canvi de nom de la configuració de l'API",
+		"load_api_config": "Ha fallat la càrrega de la configuració de l'API",
+		"delete_api_config": "Ha fallat l'eliminació de la configuració de l'API",
+		"list_api_config": "Ha fallat l'obtenció de la llista de configuracions de l'API",
+		"update_server_timeout": "Ha fallat l'actualització del temps d'espera del servidor",
+		"create_mcp_json": "Ha fallat la creació o obertura de .roo/mcp.json: {{error}}",
+		"hmr_not_running": "El servidor de desenvolupament local no està executant-se, l'HMR no funcionarà. Si us plau, executa 'npm run dev' abans de llançar l'extensió per habilitar l'HMR.",
+		"retrieve_current_mode": "Error en recuperar el mode actual de l'estat.",
+		"failed_delete_repo": "Ha fallat l'eliminació del repositori o branca associada: {{error}}",
+		"failed_remove_directory": "Ha fallat l'eliminació del directori de tasques: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "No s'ha seleccionat contingut de terminal",
+		"missing_task_files": "Els fitxers d'aquesta tasca falten. Vols eliminar-la de la llista de tasques?"
+	},
+	"info": {
+		"no_changes": "No s'han trobat canvis.",
+		"clipboard_copy": "Missatge del sistema copiat correctament al portapapers",
+		"history_cleanup": "S'han netejat {{count}} tasques amb fitxers que falten de l'historial.",
+		"mcp_server_restarting": "Reiniciant el servidor MCP {{serverName}}...",
+		"mcp_server_connected": "Servidor MCP {{serverName}} connectat",
+		"mcp_server_deleted": "Servidor MCP eliminat: {{serverName}}",
+		"mcp_server_not_found": "Servidor \"{{serverName}}\" no trobat a la configuració"
+	},
+	"answers": {
+		"yes": "Sí",
+		"no": "No",
+		"cancel": "Cancel·lar",
+		"remove": "Eliminar",
+		"keep": "Mantenir"
+	},
+	"tasks": {
+		"canceled": "Error de tasca: Ha estat aturada i cancel·lada per l'usuari.",
+		"deleted": "Fallada de tasca: Ha estat aturada i eliminada per l'usuari."
+	}
+}

+ 77 - 0
src/i18n/locales/de/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Ein komplettes Entwicklerteam mit KI in deinem Editor."
+	},
+	"number_format": {
+		"thousand_suffix": "T",
+		"million_suffix": "Mio.",
+		"billion_suffix": "Mrd."
+	},
+	"welcome": "Willkommen, {{name}}! Du hast {{count}} Benachrichtigungen.",
+	"items": {
+		"zero": "Keine Elemente",
+		"one": "Ein Element",
+		"other": "{{count}} Elemente"
+	},
+	"confirmation": {
+		"reset_state": "Möchten Sie wirklich alle Zustände und geheimen Speicher in der Erweiterung zurücksetzen? Dies kann nicht rückgängig gemacht werden.",
+		"delete_config_profile": "Möchten Sie dieses Konfigurationsprofil wirklich löschen?",
+		"delete_custom_mode": "Möchten Sie diesen benutzerdefinierten Modus wirklich löschen?",
+		"delete_message": "Was möchten Sie löschen?",
+		"just_this_message": "Nur diese Nachricht",
+		"this_and_subsequent": "Diese und alle nachfolgenden Nachrichten"
+	},
+	"errors": {
+		"invalid_mcp_config": "Ungültiges MCP-Projekt-Konfigurationsformat",
+		"invalid_mcp_settings_format": "Ungültiges MCP-Einstellungen-JSON-Format. Bitte stellen Sie sicher, dass Ihre Einstellungen dem korrekten JSON-Format entsprechen.",
+		"invalid_mcp_settings_syntax": "Ungültiges MCP-Einstellungen-JSON-Format. Bitte überprüfen Sie Ihre Einstellungsdatei auf Syntaxfehler.",
+		"invalid_mcp_settings_validation": "Ungültiges MCP-Einstellungen-Format: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Fehler beim Initialisieren des Projekt-MCP-Servers: {{error}}",
+		"invalid_data_uri": "Ungültiges Daten-URI-Format",
+		"checkpoint_timeout": "Zeitüberschreitung beim Versuch, den Checkpoint wiederherzustellen.",
+		"checkpoint_failed": "Fehler beim Wiederherstellen des Checkpoints.",
+		"no_workspace": "Bitte öffnen Sie zuerst einen Projektordner",
+		"update_support_prompt": "Fehler beim Aktualisieren der Support-Nachricht",
+		"reset_support_prompt": "Fehler beim Zurücksetzen der Support-Nachricht",
+		"enhance_prompt": "Fehler beim Verbessern der Nachricht",
+		"get_system_prompt": "Fehler beim Abrufen der Systemnachricht",
+		"search_commits": "Fehler beim Suchen von Commits",
+		"save_api_config": "Fehler beim Speichern der API-Konfiguration",
+		"create_api_config": "Fehler beim Erstellen der API-Konfiguration",
+		"rename_api_config": "Fehler beim Umbenennen der API-Konfiguration",
+		"load_api_config": "Fehler beim Laden der API-Konfiguration",
+		"delete_api_config": "Fehler beim Löschen der API-Konfiguration",
+		"list_api_config": "Fehler beim Abrufen der API-Konfigurationsliste",
+		"update_server_timeout": "Fehler beim Aktualisieren des Server-Timeouts",
+		"create_mcp_json": "Fehler beim Erstellen oder Öffnen von .roo/mcp.json: {{error}}",
+		"hmr_not_running": "Der lokale Entwicklungsserver läuft nicht, HMR wird nicht funktionieren. Bitte führen Sie 'npm run dev' vor dem Start der Erweiterung aus, um HMR zu aktivieren.",
+		"retrieve_current_mode": "Fehler beim Abrufen des aktuellen Modus aus dem Zustand.",
+		"failed_delete_repo": "Fehler beim Löschen des zugehörigen Shadow-Repositorys oder -Zweigs: {{error}}",
+		"failed_remove_directory": "Fehler beim Entfernen des Aufgabenverzeichnisses: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Kein Terminal-Inhalt ausgewählt",
+		"missing_task_files": "Die Dateien dieser Aufgabe fehlen. Möchten Sie sie aus der Aufgabenliste entfernen?"
+	},
+	"info": {
+		"no_changes": "Keine Änderungen gefunden.",
+		"clipboard_copy": "Systemnachricht erfolgreich in die Zwischenablage kopiert",
+		"history_cleanup": "{{count}} Aufgabe(n) mit fehlenden Dateien aus dem Verlauf bereinigt.",
+		"mcp_server_restarting": "MCP-Server {{serverName}} wird neu gestartet...",
+		"mcp_server_connected": "MCP-Server {{serverName}} verbunden",
+		"mcp_server_deleted": "MCP-Server gelöscht: {{serverName}}",
+		"mcp_server_not_found": "Server \"{{serverName}}\" nicht in der Konfiguration gefunden"
+	},
+	"answers": {
+		"yes": "Ja",
+		"no": "Nein",
+		"cancel": "Abbrechen",
+		"remove": "Entfernen",
+		"keep": "Behalten"
+	},
+	"tasks": {
+		"canceled": "Aufgabenfehler: Sie wurde vom Benutzer gestoppt und abgebrochen.",
+		"deleted": "Aufgabenfehler: Sie wurde vom Benutzer gestoppt und gelöscht."
+	}
+}

+ 77 - 0
src/i18n/locales/en/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "A whole dev team of AI agents in your editor."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "m",
+		"billion_suffix": "b"
+	},
+	"welcome": "Welcome, {{name}}! You have {{count}} notifications.",
+	"items": {
+		"zero": "No items",
+		"one": "One item",
+		"other": "{{count}} items"
+	},
+	"confirmation": {
+		"reset_state": "Are you sure you want to reset all state and secret storage in the extension? This cannot be undone.",
+		"delete_config_profile": "Are you sure you want to delete this configuration profile?",
+		"delete_custom_mode": "Are you sure you want to delete this custom mode?",
+		"delete_message": "What would you like to delete?",
+		"just_this_message": "Just this message",
+		"this_and_subsequent": "This and all subsequent messages"
+	},
+	"errors": {
+		"invalid_mcp_config": "Invalid project MCP configuration format",
+		"invalid_mcp_settings_format": "Invalid MCP settings JSON format. Please ensure your settings follow the correct JSON format.",
+		"invalid_mcp_settings_syntax": "Invalid MCP settings JSON format. Please check your settings file for syntax errors.",
+		"invalid_mcp_settings_validation": "Invalid MCP settings format: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Failed to initialize project MCP server: {{error}}",
+		"invalid_data_uri": "Invalid data URI format",
+		"checkpoint_timeout": "Timed out when attempting to restore checkpoint.",
+		"checkpoint_failed": "Failed to restore checkpoint.",
+		"no_workspace": "Please open a project folder first",
+		"update_support_prompt": "Failed to update support prompt",
+		"reset_support_prompt": "Failed to reset support prompt",
+		"enhance_prompt": "Failed to enhance prompt",
+		"get_system_prompt": "Failed to get system prompt",
+		"search_commits": "Failed to search commits",
+		"save_api_config": "Failed to save api configuration",
+		"create_api_config": "Failed to create api configuration",
+		"rename_api_config": "Failed to rename api configuration",
+		"load_api_config": "Failed to load api configuration",
+		"delete_api_config": "Failed to delete api configuration",
+		"list_api_config": "Failed to get list api configuration",
+		"update_server_timeout": "Failed to update server timeout",
+		"create_mcp_json": "Failed to create or open .roo/mcp.json: {{error}}",
+		"hmr_not_running": "Local development server is not running, HMR will not work. Please run 'npm run dev' before launching the extension to enable HMR.",
+		"retrieve_current_mode": "Error: failed to retrieve current mode from state.",
+		"failed_delete_repo": "Failed to delete associated shadow repository or branch: {{error}}",
+		"failed_remove_directory": "Failed to remove task directory: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "No terminal content selected",
+		"missing_task_files": "This task's files are missing. Would you like to remove it from the task list?"
+	},
+	"info": {
+		"no_changes": "No changes found.",
+		"clipboard_copy": "System prompt successfully copied to clipboard",
+		"history_cleanup": "Cleaned up {{count}} task(s) with missing files from history.",
+		"mcp_server_restarting": "Restarting {{serverName}} MCP server...",
+		"mcp_server_connected": "{{serverName}} MCP server connected",
+		"mcp_server_deleted": "Deleted MCP server: {{serverName}}",
+		"mcp_server_not_found": "Server \"{{serverName}}\" not found in configuration"
+	},
+	"answers": {
+		"yes": "Yes",
+		"no": "No",
+		"cancel": "Cancel",
+		"remove": "Remove",
+		"keep": "Keep"
+	},
+	"tasks": {
+		"canceled": "Task error: It was stopped and canceled by the user.",
+		"deleted": "Task failure: It was stopped and deleted by the user."
+	}
+}

+ 77 - 0
src/i18n/locales/es/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Un equipo completo de desarrolladores con IA en tu editor."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "m",
+		"billion_suffix": "b"
+	},
+	"welcome": "¡Bienvenido, {{name}}! Tienes {{count}} notificaciones.",
+	"items": {
+		"zero": "Sin elementos",
+		"one": "Un elemento",
+		"other": "{{count}} elementos"
+	},
+	"confirmation": {
+		"reset_state": "¿Estás seguro de que deseas restablecer todo el estado y el almacenamiento secreto en la extensión? Esta acción no se puede deshacer.",
+		"delete_config_profile": "¿Estás seguro de que deseas eliminar este perfil de configuración?",
+		"delete_custom_mode": "¿Estás seguro de que deseas eliminar este modo personalizado?",
+		"delete_message": "¿Qué deseas eliminar?",
+		"just_this_message": "Solo este mensaje",
+		"this_and_subsequent": "Este y todos los mensajes posteriores"
+	},
+	"errors": {
+		"invalid_mcp_config": "Formato de configuración MCP del proyecto no válido",
+		"invalid_mcp_settings_format": "Formato JSON de la configuración MCP no válido. Asegúrate de que tus ajustes sigan el formato JSON correcto.",
+		"invalid_mcp_settings_syntax": "Formato JSON de la configuración MCP no válido. Verifica si hay errores de sintaxis en tu archivo de configuración.",
+		"invalid_mcp_settings_validation": "Formato de configuración MCP no válido: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Error al inicializar el servidor MCP del proyecto: {{error}}",
+		"invalid_data_uri": "Formato de URI de datos no válido",
+		"checkpoint_timeout": "Se agotó el tiempo al intentar restaurar el punto de control.",
+		"checkpoint_failed": "Error al restaurar el punto de control.",
+		"no_workspace": "Por favor, abre primero una carpeta de proyecto",
+		"update_support_prompt": "Error al actualizar el mensaje de soporte",
+		"reset_support_prompt": "Error al restablecer el mensaje de soporte",
+		"enhance_prompt": "Error al mejorar el mensaje",
+		"get_system_prompt": "Error al obtener el mensaje del sistema",
+		"search_commits": "Error al buscar commits",
+		"save_api_config": "Error al guardar la configuración de API",
+		"create_api_config": "Error al crear la configuración de API",
+		"rename_api_config": "Error al renombrar la configuración de API",
+		"load_api_config": "Error al cargar la configuración de API",
+		"delete_api_config": "Error al eliminar la configuración de API",
+		"list_api_config": "Error al obtener la lista de configuraciones de API",
+		"update_server_timeout": "Error al actualizar el tiempo de espera del servidor",
+		"create_mcp_json": "Error al crear o abrir .roo/mcp.json: {{error}}",
+		"hmr_not_running": "El servidor de desarrollo local no está en ejecución, HMR no funcionará. Por favor, ejecuta 'npm run dev' antes de lanzar la extensión para habilitar HMR.",
+		"retrieve_current_mode": "Error al recuperar el modo actual del estado.",
+		"failed_delete_repo": "Error al eliminar el repositorio o rama asociada: {{error}}",
+		"failed_remove_directory": "Error al eliminar el directorio de tareas: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "No hay contenido de terminal seleccionado",
+		"missing_task_files": "Los archivos de esta tarea faltan. ¿Deseas eliminarla de la lista de tareas?"
+	},
+	"info": {
+		"no_changes": "No se encontraron cambios.",
+		"clipboard_copy": "Mensaje del sistema copiado correctamente al portapapeles",
+		"history_cleanup": "Se limpiaron {{count}} tarea(s) con archivos faltantes del historial.",
+		"mcp_server_restarting": "Reiniciando el servidor MCP {{serverName}}...",
+		"mcp_server_connected": "Servidor MCP {{serverName}} conectado",
+		"mcp_server_deleted": "Servidor MCP eliminado: {{serverName}}",
+		"mcp_server_not_found": "Servidor \"{{serverName}}\" no encontrado en la configuración"
+	},
+	"answers": {
+		"yes": "Sí",
+		"no": "No",
+		"cancel": "Cancelar",
+		"remove": "Eliminar",
+		"keep": "Mantener"
+	},
+	"tasks": {
+		"canceled": "Error de tarea: Fue detenida y cancelada por el usuario.",
+		"deleted": "Fallo de tarea: Fue detenida y eliminada por el usuario."
+	}
+}

+ 77 - 0
src/i18n/locales/fr/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Une équipe complète de développeurs IA dans votre éditeur."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "M",
+		"billion_suffix": "Md"
+	},
+	"welcome": "Bienvenue, {{name}} ! Vous avez {{count}} notifications.",
+	"items": {
+		"zero": "Aucun élément",
+		"one": "Un élément",
+		"other": "{{count}} éléments"
+	},
+	"confirmation": {
+		"reset_state": "Êtes-vous sûr de vouloir réinitialiser tous les états et le stockage secret dans l'extension ? Cette action ne peut pas être annulée.",
+		"delete_config_profile": "Êtes-vous sûr de vouloir supprimer ce profil de configuration ?",
+		"delete_custom_mode": "Êtes-vous sûr de vouloir supprimer ce mode personnalisé ?",
+		"delete_message": "Que souhaitez-vous supprimer ?",
+		"just_this_message": "Uniquement ce message",
+		"this_and_subsequent": "Ce message et tous les messages suivants"
+	},
+	"errors": {
+		"invalid_mcp_config": "Format de configuration MCP du projet non valide",
+		"invalid_mcp_settings_format": "Format JSON des paramètres MCP non valide. Veuillez vous assurer que vos paramètres suivent le format JSON correct.",
+		"invalid_mcp_settings_syntax": "Format JSON des paramètres MCP non valide. Veuillez vérifier les erreurs de syntaxe dans votre fichier de paramètres.",
+		"invalid_mcp_settings_validation": "Format de paramètres MCP non valide : {{errorMessages}}",
+		"failed_initialize_project_mcp": "Échec de l'initialisation du serveur MCP du projet : {{error}}",
+		"invalid_data_uri": "Format d'URI de données non valide",
+		"checkpoint_timeout": "Délai d'expiration lors de la restauration du point de contrôle.",
+		"checkpoint_failed": "Échec de la restauration du point de contrôle.",
+		"no_workspace": "Veuillez d'abord ouvrir un dossier de projet",
+		"update_support_prompt": "Erreur lors de la mise à jour du message de support",
+		"reset_support_prompt": "Erreur lors de la réinitialisation du message de support",
+		"enhance_prompt": "Erreur lors de l'amélioration du message",
+		"get_system_prompt": "Erreur lors de l'obtention du message système",
+		"search_commits": "Erreur lors de la recherche des commits",
+		"save_api_config": "Erreur lors de l'enregistrement de la configuration API",
+		"create_api_config": "Erreur lors de la création de la configuration API",
+		"rename_api_config": "Erreur lors du renommage de la configuration API",
+		"load_api_config": "Erreur lors du chargement de la configuration API",
+		"delete_api_config": "Erreur lors de la suppression de la configuration API",
+		"list_api_config": "Erreur lors de l'obtention de la liste des configurations API",
+		"update_server_timeout": "Erreur lors de la mise à jour du délai d'attente du serveur",
+		"create_mcp_json": "Échec de la création ou de l'ouverture de .roo/mcp.json : {{error}}",
+		"hmr_not_running": "Le serveur de développement local n'est pas en cours d'exécution, HMR ne fonctionnera pas. Veuillez exécuter 'npm run dev' avant de lancer l'extension pour activer HMR.",
+		"retrieve_current_mode": "Erreur lors de la récupération du mode actuel à partir de l'état.",
+		"failed_delete_repo": "Échec de la suppression du référentiel ou de la branche associée : {{error}}",
+		"failed_remove_directory": "Échec de la suppression du répertoire de tâches : {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Aucun contenu de terminal sélectionné",
+		"missing_task_files": "Les fichiers de cette tâche sont manquants. Souhaitez-vous la supprimer de la liste des tâches ?"
+	},
+	"info": {
+		"no_changes": "Aucun changement trouvé.",
+		"clipboard_copy": "Message système copié avec succès dans le presse-papiers",
+		"history_cleanup": "{{count}} tâche(s) avec des fichiers manquants ont été nettoyées de l'historique.",
+		"mcp_server_restarting": "Redémarrage du serveur MCP {{serverName}}...",
+		"mcp_server_connected": "Serveur MCP {{serverName}} connecté",
+		"mcp_server_deleted": "Serveur MCP supprimé : {{serverName}}",
+		"mcp_server_not_found": "Serveur \"{{serverName}}\" introuvable dans la configuration"
+	},
+	"answers": {
+		"yes": "Oui",
+		"no": "Non",
+		"cancel": "Annuler",
+		"remove": "Supprimer",
+		"keep": "Conserver"
+	},
+	"tasks": {
+		"canceled": "Erreur de tâche : Elle a été arrêtée et annulée par l'utilisateur.",
+		"deleted": "Échec de la tâche : Elle a été arrêtée et supprimée par l'utilisateur."
+	}
+}

+ 77 - 0
src/i18n/locales/hi/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "आपके एडिटर में AI डेवलपर्स की पूरी टीम।"
+	},
+	"number_format": {
+		"thousand_suffix": "हज़ार",
+		"million_suffix": "लाख",
+		"billion_suffix": "अरब"
+	},
+	"welcome": "स्वागत है, {{name}}! आपके पास {{count}} सूचनाएँ हैं।",
+	"items": {
+		"zero": "कोई आइटम नहीं",
+		"one": "एक आइटम",
+		"other": "{{count}} आइटम"
+	},
+	"confirmation": {
+		"reset_state": "क्या आप वाकई एक्सटेंशन में सभी स्टेट और गुप्त स्टोरेज रीसेट करना चाहते हैं? इसे पूर्ववत नहीं किया जा सकता है।",
+		"delete_config_profile": "क्या आप वाकई इस कॉन्फ़िगरेशन प्रोफ़ाइल को हटाना चाहते हैं?",
+		"delete_custom_mode": "क्या आप वाकई इस कस्टम मोड को हटाना चाहते हैं?",
+		"delete_message": "आप क्या हटाना चाहते हैं?",
+		"just_this_message": "सिर्फ यह संदेश",
+		"this_and_subsequent": "यह और सभी बाद के संदेश"
+	},
+	"errors": {
+		"invalid_mcp_config": "अमान्य प्रोजेक्ट MCP कॉन्फ़िगरेशन फॉर्मेट",
+		"invalid_mcp_settings_format": "अमान्य MCP सेटिंग्स JSON फॉर्मेट। कृपया सुनिश्चित करें कि आपकी सेटिंग्स सही JSON फॉर्मेट का पालन करती हैं।",
+		"invalid_mcp_settings_syntax": "अमान्य MCP सेटिंग्स JSON फॉर्मेट। कृपया अपनी सेटिंग्स फ़ाइल में सिंटैक्स त्रुटियों की जांच करें।",
+		"invalid_mcp_settings_validation": "अमान्य MCP सेटिंग्स फॉर्मेट: {{errorMessages}}",
+		"failed_initialize_project_mcp": "प्रोजेक्ट MCP सर्वर को प्रारंभ करने में विफल: {{error}}",
+		"invalid_data_uri": "अमान्य डेटा URI फॉर्मेट",
+		"checkpoint_timeout": "चेकपॉइंट को पुनर्स्थापित करने का प्रयास करते समय टाइमआउट हो गया।",
+		"checkpoint_failed": "चेकपॉइंट पुनर्स्थापित करने में विफल।",
+		"no_workspace": "कृपया पहले प्रोजेक्ट फ़ोल्डर खोलें",
+		"update_support_prompt": "सपोर्ट प्रॉम्प्ट अपडेट करने में विफल",
+		"reset_support_prompt": "सपोर्ट प्रॉम्प्ट रीसेट करने में विफल",
+		"enhance_prompt": "प्रॉम्प्ट को बेहतर बनाने में विफल",
+		"get_system_prompt": "सिस्टम प्रॉम्प्ट प्राप्त करने में विफल",
+		"search_commits": "कमिट्स खोजने में विफल",
+		"save_api_config": "API कॉन्फ़िगरेशन सहेजने में विफल",
+		"create_api_config": "API कॉन्फ़िगरेशन बनाने में विफल",
+		"rename_api_config": "API कॉन्फ़िगरेशन का नाम बदलने में विफल",
+		"load_api_config": "API कॉन्फ़िगरेशन लोड करने में विफल",
+		"delete_api_config": "API कॉन्फ़िगरेशन हटाने में विफल",
+		"list_api_config": "API कॉन्फ़िगरेशन की सूची प्राप्त करने में विफल",
+		"update_server_timeout": "सर्वर टाइमआउट अपडेट करने में विफल",
+		"create_mcp_json": ".roo/mcp.json बनाने या खोलने में विफल: {{error}}",
+		"hmr_not_running": "स्थानीय विकास सर्वर चल नहीं रहा है, HMR काम नहीं करेगा। कृपया HMR सक्षम करने के लिए एक्सटेंशन लॉन्च करने से पहले 'npm run dev' चलाएँ।",
+		"retrieve_current_mode": "स्टेट से वर्तमान मोड प्राप्त करने में त्रुटि।",
+		"failed_delete_repo": "संबंधित शैडो रिपॉजिटरी या ब्रांच हटाने में विफल: {{error}}",
+		"failed_remove_directory": "टास्क डायरेक्टरी हटाने में विफल: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "कोई टर्मिनल सामग्री चयनित नहीं",
+		"missing_task_files": "इस टास्क की फाइलें गायब हैं। क्या आप इसे टास्क सूची से हटाना चाहते हैं?"
+	},
+	"info": {
+		"no_changes": "कोई परिवर्तन नहीं मिला।",
+		"clipboard_copy": "सिस्टम प्रॉम्प्ट क्लिपबोर्ड पर सफलतापूर्वक कॉपी किया गया",
+		"history_cleanup": "इतिहास से गायब फाइलों वाले {{count}} टास्क साफ किए गए।",
+		"mcp_server_restarting": "{{serverName}} MCP सर्वर पुनः प्रारंभ हो रहा है...",
+		"mcp_server_connected": "{{serverName}} MCP सर्वर कनेक्टेड",
+		"mcp_server_deleted": "MCP सर्वर हटाया गया: {{serverName}}",
+		"mcp_server_not_found": "सर्वर \"{{serverName}}\" कॉन्फ़िगरेशन में नहीं मिला"
+	},
+	"answers": {
+		"yes": "हां",
+		"no": "नहीं",
+		"cancel": "रद्द करें",
+		"remove": "हटाएं",
+		"keep": "रखें"
+	},
+	"tasks": {
+		"canceled": "टास्क त्रुटि: इसे उपयोगकर्ता द्वारा रोका और रद्द किया गया था।",
+		"deleted": "टास्क विफलता: इसे उपयोगकर्ता द्वारा रोका और हटाया गया था।"
+	}
+}

+ 77 - 0
src/i18n/locales/it/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Un intero team di sviluppatori AI nel tuo editor."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "mln",
+		"billion_suffix": "mld"
+	},
+	"welcome": "Benvenuto, {{name}}! Hai {{count}} notifiche.",
+	"items": {
+		"zero": "Nessun elemento",
+		"one": "Un elemento",
+		"other": "{{count}} elementi"
+	},
+	"confirmation": {
+		"reset_state": "Sei sicuro di voler reimpostare tutti gli stati e l'archiviazione segreta nell'estensione? Questa azione non può essere annullata.",
+		"delete_config_profile": "Sei sicuro di voler eliminare questo profilo di configurazione?",
+		"delete_custom_mode": "Sei sicuro di voler eliminare questa modalità personalizzata?",
+		"delete_message": "Cosa desideri eliminare?",
+		"just_this_message": "Solo questo messaggio",
+		"this_and_subsequent": "Questo e tutti i messaggi successivi"
+	},
+	"errors": {
+		"invalid_mcp_config": "Formato di configurazione MCP del progetto non valido",
+		"invalid_mcp_settings_format": "Formato JSON delle impostazioni MCP non valido. Assicurati che le tue impostazioni seguano il formato JSON corretto.",
+		"invalid_mcp_settings_syntax": "Formato JSON delle impostazioni MCP non valido. Verifica gli errori di sintassi nel tuo file delle impostazioni.",
+		"invalid_mcp_settings_validation": "Formato delle impostazioni MCP non valido: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Impossibile inizializzare il server MCP del progetto: {{error}}",
+		"invalid_data_uri": "Formato URI dati non valido",
+		"checkpoint_timeout": "Timeout durante il tentativo di ripristinare il checkpoint.",
+		"checkpoint_failed": "Impossibile ripristinare il checkpoint.",
+		"no_workspace": "Per favore, apri prima una cartella di progetto",
+		"update_support_prompt": "Errore durante l'aggiornamento del messaggio di supporto",
+		"reset_support_prompt": "Errore durante il ripristino del messaggio di supporto",
+		"enhance_prompt": "Errore durante il miglioramento del messaggio",
+		"get_system_prompt": "Errore durante l'ottenimento del messaggio di sistema",
+		"search_commits": "Errore durante la ricerca dei commit",
+		"save_api_config": "Errore durante il salvataggio della configurazione API",
+		"create_api_config": "Errore durante la creazione della configurazione API",
+		"rename_api_config": "Errore durante la ridenominazione della configurazione API",
+		"load_api_config": "Errore durante il caricamento della configurazione API",
+		"delete_api_config": "Errore durante l'eliminazione della configurazione API",
+		"list_api_config": "Errore durante l'ottenimento dell'elenco delle configurazioni API",
+		"update_server_timeout": "Errore durante l'aggiornamento del timeout del server",
+		"create_mcp_json": "Impossibile creare o aprire .roo/mcp.json: {{error}}",
+		"hmr_not_running": "Il server di sviluppo locale non è in esecuzione, l'HMR non funzionerà. Esegui 'npm run dev' prima di avviare l'estensione per abilitare l'HMR.",
+		"retrieve_current_mode": "Errore durante il recupero della modalità corrente dallo stato.",
+		"failed_delete_repo": "Impossibile eliminare il repository o il ramo associato: {{error}}",
+		"failed_remove_directory": "Impossibile rimuovere la directory delle attività: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Nessun contenuto del terminale selezionato",
+		"missing_task_files": "I file di questa attività sono mancanti. Vuoi rimuoverla dall'elenco delle attività?"
+	},
+	"info": {
+		"no_changes": "Nessuna modifica trovata.",
+		"clipboard_copy": "Messaggio di sistema copiato con successo negli appunti",
+		"history_cleanup": "Pulite {{count}} attività con file mancanti dalla cronologia.",
+		"mcp_server_restarting": "Riavvio del server MCP {{serverName}}...",
+		"mcp_server_connected": "Server MCP {{serverName}} connesso",
+		"mcp_server_deleted": "Server MCP eliminato: {{serverName}}",
+		"mcp_server_not_found": "Server \"{{serverName}}\" non trovato nella configurazione"
+	},
+	"answers": {
+		"yes": "Sì",
+		"no": "No",
+		"cancel": "Annulla",
+		"remove": "Rimuovi",
+		"keep": "Mantieni"
+	},
+	"tasks": {
+		"canceled": "Errore attività: È stata interrotta e annullata dall'utente.",
+		"deleted": "Fallimento attività: È stata interrotta ed eliminata dall'utente."
+	}
+}

+ 77 - 0
src/i18n/locales/ja/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "エディター内のAIデベロッパーチーム全体。"
+	},
+	"number_format": {
+		"thousand_suffix": "千",
+		"million_suffix": "百万",
+		"billion_suffix": "十億"
+	},
+	"welcome": "ようこそ、{{name}}さん!{{count}}件の通知があります。",
+	"items": {
+		"zero": "アイテムなし",
+		"one": "1つのアイテム",
+		"other": "{{count}}個のアイテム"
+	},
+	"confirmation": {
+		"reset_state": "拡張機能のすべての状態とシークレットストレージをリセットしてもよろしいですか?この操作は元に戻せません。",
+		"delete_config_profile": "この設定プロファイルを削除してもよろしいですか?",
+		"delete_custom_mode": "このカスタムモードを削除してもよろしいですか?",
+		"delete_message": "何を削除しますか?",
+		"just_this_message": "このメッセージのみ",
+		"this_and_subsequent": "これ以降のすべてのメッセージ"
+	},
+	"errors": {
+		"invalid_mcp_config": "プロジェクトMCP設定フォーマットが無効です",
+		"invalid_mcp_settings_format": "MCP設定のJSONフォーマットが無効です。設定が正しいJSONフォーマットに従っていることを確認してください。",
+		"invalid_mcp_settings_syntax": "MCP設定のJSONフォーマットが無効です。設定ファイルの構文エラーを確認してください。",
+		"invalid_mcp_settings_validation": "MCP設定フォーマットが無効です:{{errorMessages}}",
+		"failed_initialize_project_mcp": "プロジェクトMCPサーバーの初期化に失敗しました:{{error}}",
+		"invalid_data_uri": "データURIフォーマットが無効です",
+		"checkpoint_timeout": "チェックポイントの復元を試みる際にタイムアウトしました。",
+		"checkpoint_failed": "チェックポイントの復元に失敗しました。",
+		"no_workspace": "まずプロジェクトフォルダを開いてください",
+		"update_support_prompt": "サポートメッセージの更新に失敗しました",
+		"reset_support_prompt": "サポートメッセージのリセットに失敗しました",
+		"enhance_prompt": "メッセージの強化に失敗しました",
+		"get_system_prompt": "システムメッセージの取得に失敗しました",
+		"search_commits": "コミットの検索に失敗しました",
+		"save_api_config": "API設定の保存に失敗しました",
+		"create_api_config": "API設定の作成に失敗しました",
+		"rename_api_config": "API設定の名前変更に失敗しました",
+		"load_api_config": "API設定の読み込みに失敗しました",
+		"delete_api_config": "API設定の削除に失敗しました",
+		"list_api_config": "API設定リストの取得に失敗しました",
+		"update_server_timeout": "サーバータイムアウトの更新に失敗しました",
+		"create_mcp_json": ".roo/mcp.jsonの作成または開くことに失敗しました:{{error}}",
+		"hmr_not_running": "ローカル開発サーバーが実行されていないため、HMRは機能しません。HMRを有効にするには、拡張機能を起動する前に'npm run dev'を実行してください。",
+		"retrieve_current_mode": "現在のモードを状態から取得する際にエラーが発生しました。",
+		"failed_delete_repo": "関連するシャドウリポジトリまたはブランチの削除に失敗しました:{{error}}",
+		"failed_remove_directory": "タスクディレクトリの削除に失敗しました:{{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "選択されたターミナルコンテンツがありません",
+		"missing_task_files": "このタスクのファイルが見つかりません。タスクリストから削除しますか?"
+	},
+	"info": {
+		"no_changes": "変更は見つかりませんでした。",
+		"clipboard_copy": "システムメッセージがクリップボードに正常にコピーされました",
+		"history_cleanup": "履歴から不足ファイルのある{{count}}個のタスクをクリーンアップしました。",
+		"mcp_server_restarting": "MCPサーバー{{serverName}}を再起動中...",
+		"mcp_server_connected": "MCPサーバー{{serverName}}が接続されました",
+		"mcp_server_deleted": "MCPサーバーが削除されました:{{serverName}}",
+		"mcp_server_not_found": "サーバー\"{{serverName}}\"が設定内に見つかりません"
+	},
+	"answers": {
+		"yes": "はい",
+		"no": "いいえ",
+		"cancel": "キャンセル",
+		"remove": "削除",
+		"keep": "保持"
+	},
+	"tasks": {
+		"canceled": "タスクエラー:ユーザーによって停止およびキャンセルされました。",
+		"deleted": "タスク失敗:ユーザーによって停止および削除されました。"
+	}
+}

+ 77 - 0
src/i18n/locales/ko/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "에디터 내에서 동작하는 AI 개발팀 전체입니다."
+	},
+	"number_format": {
+		"thousand_suffix": "천",
+		"million_suffix": "백만",
+		"billion_suffix": "십억"
+	},
+	"welcome": "안녕하세요, {{name}}님! {{count}}개의 알림이 있습니다.",
+	"items": {
+		"zero": "항목 없음",
+		"one": "1개 항목",
+		"other": "{{count}}개 항목"
+	},
+	"confirmation": {
+		"reset_state": "확장 프로그램의 모든 상태와 보안 저장소를 재설정하시겠습니까? 이 작업은 취소할 수 없습니다.",
+		"delete_config_profile": "이 구성 프로필을 삭제하시겠습니까?",
+		"delete_custom_mode": "이 사용자 지정 모드를 삭제하시겠습니까?",
+		"delete_message": "무엇을 삭제하시겠습니까?",
+		"just_this_message": "이 메시지만",
+		"this_and_subsequent": "이 메시지와 모든 후속 메시지"
+	},
+	"errors": {
+		"invalid_mcp_config": "잘못된 프로젝트 MCP 구성 형식",
+		"invalid_mcp_settings_format": "잘못된 MCP 설정 JSON 형식입니다. 설정이 올바른 JSON 형식을 따르는지 확인하세요.",
+		"invalid_mcp_settings_syntax": "잘못된 MCP 설정 JSON 형식입니다. 설정 파일의 구문 오류를 확인하세요.",
+		"invalid_mcp_settings_validation": "잘못된 MCP 설정 형식: {{errorMessages}}",
+		"failed_initialize_project_mcp": "프로젝트 MCP 서버 초기화 실패: {{error}}",
+		"invalid_data_uri": "잘못된 데이터 URI 형식",
+		"checkpoint_timeout": "체크포인트 복원을 시도하는 중 시간 초과되었습니다.",
+		"checkpoint_failed": "체크포인트 복원에 실패했습니다.",
+		"no_workspace": "먼저 프로젝트 폴더를 열어주세요",
+		"update_support_prompt": "지원 프롬프트 업데이트에 실패했습니다",
+		"reset_support_prompt": "지원 프롬프트 재설정에 실패했습니다",
+		"enhance_prompt": "프롬프트 향상에 실패했습니다",
+		"get_system_prompt": "시스템 프롬프트 가져오기에 실패했습니다",
+		"search_commits": "커밋 검색에 실패했습니다",
+		"save_api_config": "API 구성 저장에 실패했습니다",
+		"create_api_config": "API 구성 생성에 실패했습니다",
+		"rename_api_config": "API 구성 이름 변경에 실패했습니다",
+		"load_api_config": "API 구성 로드에 실패했습니다",
+		"delete_api_config": "API 구성 삭제에 실패했습니다",
+		"list_api_config": "API 구성 목록 가져오기에 실패했습니다",
+		"update_server_timeout": "서버 타임아웃 업데이트에 실패했습니다",
+		"create_mcp_json": ".roo/mcp.json 생성 또는 열기 실패: {{error}}",
+		"hmr_not_running": "로컬 개발 서버가 실행되고 있지 않아 HMR이 작동하지 않습니다. HMR을 활성화하려면 확장 프로그램을 실행하기 전에 'npm run dev'를 실행하세요.",
+		"retrieve_current_mode": "상태에서 현재 모드를 검색하는 데 오류가 발생했습니다.",
+		"failed_delete_repo": "관련 shadow 저장소 또는 브랜치 삭제 실패: {{error}}",
+		"failed_remove_directory": "작업 디렉토리 제거 실패: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "선택된 터미널 내용이 없습니다",
+		"missing_task_files": "이 작업의 파일이 누락되었습니다. 작업 목록에서 제거하시겠습니까?"
+	},
+	"info": {
+		"no_changes": "변경 사항이 없습니다.",
+		"clipboard_copy": "시스템 프롬프트가 클립보드에 성공적으로 복사되었습니다",
+		"history_cleanup": "이력에서 파일이 누락된 {{count}}개의 작업을 정리했습니다.",
+		"mcp_server_restarting": "{{serverName}} MCP 서버를 재시작하는 중...",
+		"mcp_server_connected": "{{serverName}} MCP 서버 연결됨",
+		"mcp_server_deleted": "MCP 서버 삭제됨: {{serverName}}",
+		"mcp_server_not_found": "구성에서 서버 \"{{serverName}}\"을(를) 찾을 수 없습니다"
+	},
+	"answers": {
+		"yes": "예",
+		"no": "아니오",
+		"cancel": "취소",
+		"remove": "제거",
+		"keep": "유지"
+	},
+	"tasks": {
+		"canceled": "작업 오류: 사용자에 의해 중지 및 취소되었습니다.",
+		"deleted": "작업 실패: 사용자에 의해 중지 및 삭제되었습니다."
+	}
+}

+ 77 - 0
src/i18n/locales/pl/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Cały zespół programistów AI w Twoim edytorze."
+	},
+	"number_format": {
+		"thousand_suffix": "tys.",
+		"million_suffix": "mln",
+		"billion_suffix": "mld"
+	},
+	"welcome": "Witaj, {{name}}! Masz {{count}} powiadomień.",
+	"items": {
+		"zero": "Brak elementów",
+		"one": "Jeden element",
+		"other": "{{count}} elementów"
+	},
+	"confirmation": {
+		"reset_state": "Czy na pewno chcesz zresetować wszystkie stany i tajne magazyny w rozszerzeniu? Tej operacji nie można cofnąć.",
+		"delete_config_profile": "Czy na pewno chcesz usunąć ten profil konfiguracyjny?",
+		"delete_custom_mode": "Czy na pewno chcesz usunąć ten niestandardowy tryb?",
+		"delete_message": "Co chcesz usunąć?",
+		"just_this_message": "Tylko tę wiadomość",
+		"this_and_subsequent": "Tę i wszystkie kolejne wiadomości"
+	},
+	"errors": {
+		"invalid_mcp_config": "Nieprawidłowy format konfiguracji MCP projektu",
+		"invalid_mcp_settings_format": "Nieprawidłowy format JSON ustawień MCP. Upewnij się, że Twoje ustawienia są zgodne z poprawnym formatem JSON.",
+		"invalid_mcp_settings_syntax": "Nieprawidłowy format JSON ustawień MCP. Sprawdź, czy w pliku ustawień nie ma błędów składniowych.",
+		"invalid_mcp_settings_validation": "Nieprawidłowy format ustawień MCP: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Nie udało się zainicjować serwera MCP projektu: {{error}}",
+		"invalid_data_uri": "Nieprawidłowy format URI danych",
+		"checkpoint_timeout": "Upłynął limit czasu podczas próby przywrócenia punktu kontrolnego.",
+		"checkpoint_failed": "Nie udało się przywrócić punktu kontrolnego.",
+		"no_workspace": "Najpierw otwórz folder projektu",
+		"update_support_prompt": "Nie udało się zaktualizować komunikatu wsparcia",
+		"reset_support_prompt": "Nie udało się zresetować komunikatu wsparcia",
+		"enhance_prompt": "Nie udało się ulepszyć komunikatu",
+		"get_system_prompt": "Nie udało się pobrać komunikatu systemowego",
+		"search_commits": "Nie udało się wyszukać commitów",
+		"save_api_config": "Nie udało się zapisać konfiguracji API",
+		"create_api_config": "Nie udało się utworzyć konfiguracji API",
+		"rename_api_config": "Nie udało się zmienić nazwy konfiguracji API",
+		"load_api_config": "Nie udało się załadować konfiguracji API",
+		"delete_api_config": "Nie udało się usunąć konfiguracji API",
+		"list_api_config": "Nie udało się pobrać listy konfiguracji API",
+		"update_server_timeout": "Nie udało się zaktualizować limitu czasu serwera",
+		"create_mcp_json": "Nie udało się utworzyć lub otworzyć .roo/mcp.json: {{error}}",
+		"hmr_not_running": "Lokalny serwer deweloperski nie jest uruchomiony, HMR nie będzie działać. Uruchom 'npm run dev' przed uruchomieniem rozszerzenia, aby włączyć HMR.",
+		"retrieve_current_mode": "Błąd podczas pobierania bieżącego trybu ze stanu.",
+		"failed_delete_repo": "Nie udało się usunąć powiązanego repozytorium lub gałęzi pomocniczej: {{error}}",
+		"failed_remove_directory": "Nie udało się usunąć katalogu zadania: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Nie wybrano zawartości terminala",
+		"missing_task_files": "Pliki tego zadania są brakujące. Czy chcesz usunąć je z listy zadań?"
+	},
+	"info": {
+		"no_changes": "Nie znaleziono zmian.",
+		"clipboard_copy": "Komunikat systemowy został pomyślnie skopiowany do schowka",
+		"history_cleanup": "Wyczyszczono {{count}} zadań z brakującymi plikami z historii.",
+		"mcp_server_restarting": "Ponowne uruchamianie serwera MCP {{serverName}}...",
+		"mcp_server_connected": "Serwer MCP {{serverName}} połączony",
+		"mcp_server_deleted": "Usunięto serwer MCP: {{serverName}}",
+		"mcp_server_not_found": "Serwer \"{{serverName}}\" nie znaleziony w konfiguracji"
+	},
+	"answers": {
+		"yes": "Tak",
+		"no": "Nie",
+		"cancel": "Anuluj",
+		"remove": "Usuń",
+		"keep": "Zachowaj"
+	},
+	"tasks": {
+		"canceled": "Błąd zadania: Zostało zatrzymane i anulowane przez użytkownika.",
+		"deleted": "Niepowodzenie zadania: Zostało zatrzymane i usunięte przez użytkownika."
+	}
+}

+ 77 - 0
src/i18n/locales/pt-BR/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Uma equipe completa de desenvolvedores com IA em seu editor."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "mi",
+		"billion_suffix": "bi"
+	},
+	"welcome": "Bem-vindo(a), {{name}}! Você tem {{count}} notificações.",
+	"items": {
+		"zero": "Nenhum item",
+		"one": "Um item",
+		"other": "{{count}} itens"
+	},
+	"confirmation": {
+		"reset_state": "Tem certeza de que deseja redefinir todo o estado e armazenamento secreto na extensão? Isso não pode ser desfeito.",
+		"delete_config_profile": "Tem certeza de que deseja excluir este perfil de configuração?",
+		"delete_custom_mode": "Tem certeza de que deseja excluir este modo personalizado?",
+		"delete_message": "O que você gostaria de excluir?",
+		"just_this_message": "Apenas esta mensagem",
+		"this_and_subsequent": "Esta e todas as mensagens subsequentes"
+	},
+	"errors": {
+		"invalid_mcp_config": "Formato de configuração MCP do projeto inválido",
+		"invalid_mcp_settings_format": "Formato JSON das configurações MCP inválido. Por favor, verifique se suas configurações seguem o formato JSON correto.",
+		"invalid_mcp_settings_syntax": "Formato JSON das configurações MCP inválido. Por favor, verifique se há erros de sintaxe no seu arquivo de configurações.",
+		"invalid_mcp_settings_validation": "Formato de configurações MCP inválido: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Falha ao inicializar o servidor MCP do projeto: {{error}}",
+		"invalid_data_uri": "Formato de URI de dados inválido",
+		"checkpoint_timeout": "Tempo esgotado ao tentar restaurar o ponto de verificação.",
+		"checkpoint_failed": "Falha ao restaurar o ponto de verificação.",
+		"no_workspace": "Por favor, abra primeiro uma pasta de projeto",
+		"update_support_prompt": "Falha ao atualizar o prompt de suporte",
+		"reset_support_prompt": "Falha ao redefinir o prompt de suporte",
+		"enhance_prompt": "Falha ao aprimorar o prompt",
+		"get_system_prompt": "Falha ao obter o prompt do sistema",
+		"search_commits": "Falha ao pesquisar commits",
+		"save_api_config": "Falha ao salvar a configuração da API",
+		"create_api_config": "Falha ao criar a configuração da API",
+		"rename_api_config": "Falha ao renomear a configuração da API",
+		"load_api_config": "Falha ao carregar a configuração da API",
+		"delete_api_config": "Falha ao excluir a configuração da API",
+		"list_api_config": "Falha ao obter a lista de configurações da API",
+		"update_server_timeout": "Falha ao atualizar o tempo limite do servidor",
+		"create_mcp_json": "Falha ao criar ou abrir .roo/mcp.json: {{error}}",
+		"hmr_not_running": "O servidor de desenvolvimento local não está em execução, o HMR não funcionará. Por favor, execute 'npm run dev' antes de iniciar a extensão para habilitar o HMR.",
+		"retrieve_current_mode": "Erro ao recuperar o modo atual do estado.",
+		"failed_delete_repo": "Falha ao excluir o repositório ou ramificação associada: {{error}}",
+		"failed_remove_directory": "Falha ao remover o diretório de tarefas: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Nenhum conteúdo do terminal selecionado",
+		"missing_task_files": "Os arquivos desta tarefa estão faltando. Deseja removê-la da lista de tarefas?"
+	},
+	"info": {
+		"no_changes": "Nenhuma alteração encontrada.",
+		"clipboard_copy": "Prompt do sistema copiado com sucesso para a área de transferência",
+		"history_cleanup": "{{count}} tarefa(s) com arquivos ausentes foram limpas do histórico.",
+		"mcp_server_restarting": "Reiniciando o servidor MCP {{serverName}}...",
+		"mcp_server_connected": "Servidor MCP {{serverName}} conectado",
+		"mcp_server_deleted": "Servidor MCP excluído: {{serverName}}",
+		"mcp_server_not_found": "Servidor \"{{serverName}}\" não encontrado na configuração"
+	},
+	"answers": {
+		"yes": "Sim",
+		"no": "Não",
+		"cancel": "Cancelar",
+		"remove": "Remover",
+		"keep": "Manter"
+	},
+	"tasks": {
+		"canceled": "Erro na tarefa: Foi interrompida e cancelada pelo usuário.",
+		"deleted": "Falha na tarefa: Foi interrompida e excluída pelo usuário."
+	}
+}

+ 77 - 0
src/i18n/locales/tr/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Düzenleyicinizde tam bir AI geliştirici ekibi."
+	},
+	"number_format": {
+		"thousand_suffix": "B",
+		"million_suffix": "M",
+		"billion_suffix": "Mr"
+	},
+	"welcome": "Hoş geldiniz, {{name}}! {{count}} bildiriminiz var.",
+	"items": {
+		"zero": "Öğe yok",
+		"one": "Bir öğe",
+		"other": "{{count}} öğe"
+	},
+	"confirmation": {
+		"reset_state": "Uzantıdaki tüm durumları ve gizli depolamayı sıfırlamak istediğinizden emin misiniz? Bu işlem geri alınamaz.",
+		"delete_config_profile": "Bu yapılandırma profilini silmek istediğinizden emin misiniz?",
+		"delete_custom_mode": "Bu özel modu silmek istediğinizden emin misiniz?",
+		"delete_message": "Neyi silmek istersiniz?",
+		"just_this_message": "Sadece bu mesajı",
+		"this_and_subsequent": "Bu ve sonraki tüm mesajları"
+	},
+	"errors": {
+		"invalid_mcp_config": "Geçersiz proje MCP yapılandırma formatı",
+		"invalid_mcp_settings_format": "Geçersiz MCP ayarları JSON formatı. Lütfen ayarlarınızın doğru JSON formatını takip ettiğinden emin olun.",
+		"invalid_mcp_settings_syntax": "Geçersiz MCP ayarları JSON formatı. Lütfen ayarlar dosyanızda sözdizimi hatalarını kontrol edin.",
+		"invalid_mcp_settings_validation": "Geçersiz MCP ayarları formatı: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Proje MCP sunucusu başlatılamadı: {{error}}",
+		"invalid_data_uri": "Geçersiz veri URI formatı",
+		"checkpoint_timeout": "Kontrol noktasını geri yüklemeye çalışırken zaman aşımına uğradı.",
+		"checkpoint_failed": "Kontrol noktası geri yüklenemedi.",
+		"no_workspace": "Lütfen önce bir proje klasörü açın",
+		"update_support_prompt": "Destek istemi güncellenemedi",
+		"reset_support_prompt": "Destek istemi sıfırlanamadı",
+		"enhance_prompt": "İstem geliştirilemedi",
+		"get_system_prompt": "Sistem istemi alınamadı",
+		"search_commits": "Taahhütler aranamadı",
+		"save_api_config": "API yapılandırması kaydedilemedi",
+		"create_api_config": "API yapılandırması oluşturulamadı",
+		"rename_api_config": "API yapılandırmasının adı değiştirilemedi",
+		"load_api_config": "API yapılandırması yüklenemedi",
+		"delete_api_config": "API yapılandırması silinemedi",
+		"list_api_config": "API yapılandırma listesi alınamadı",
+		"update_server_timeout": "Sunucu zaman aşımı güncellenemedi",
+		"create_mcp_json": ".roo/mcp.json oluşturulamadı veya açılamadı: {{error}}",
+		"hmr_not_running": "Yerel geliştirme sunucusu çalışmıyor, HMR çalışmayacak. HMR'yi etkinleştirmek için uzantıyı başlatmadan önce lütfen 'npm run dev' komutunu çalıştırın.",
+		"retrieve_current_mode": "Mevcut mod durumdan alınırken hata oluştu.",
+		"failed_delete_repo": "İlişkili gölge depo veya dal silinemedi: {{error}}",
+		"failed_remove_directory": "Görev dizini kaldırılamadı: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Seçili terminal içeriği yok",
+		"missing_task_files": "Bu görevin dosyaları eksik. Görev listesinden kaldırmak istiyor musunuz?"
+	},
+	"info": {
+		"no_changes": "Değişiklik bulunamadı.",
+		"clipboard_copy": "Sistem istemi panoya başarıyla kopyalandı",
+		"history_cleanup": "Geçmişten eksik dosyaları olan {{count}} görev temizlendi.",
+		"mcp_server_restarting": "{{serverName}} MCP sunucusu yeniden başlatılıyor...",
+		"mcp_server_connected": "{{serverName}} MCP sunucusu bağlandı",
+		"mcp_server_deleted": "MCP sunucusu silindi: {{serverName}}",
+		"mcp_server_not_found": "Yapılandırmada \"{{serverName}}\" sunucusu bulunamadı"
+	},
+	"answers": {
+		"yes": "Evet",
+		"no": "Hayır",
+		"cancel": "İptal",
+		"remove": "Kaldır",
+		"keep": "Koru"
+	},
+	"tasks": {
+		"canceled": "Görev hatası: Kullanıcı tarafından durduruldu ve iptal edildi.",
+		"deleted": "Görev başarısız: Kullanıcı tarafından durduruldu ve silindi."
+	}
+}

+ 77 - 0
src/i18n/locales/vi/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "Toàn bộ đội ngũ phát triển AI trong trình soạn thảo của bạn."
+	},
+	"number_format": {
+		"thousand_suffix": "k",
+		"million_suffix": "tr",
+		"billion_suffix": "tỷ"
+	},
+	"welcome": "Chào mừng, {{name}}! Bạn có {{count}} thông báo.",
+	"items": {
+		"zero": "Không có mục nào",
+		"one": "Một mục",
+		"other": "{{count}} mục"
+	},
+	"confirmation": {
+		"reset_state": "Bạn có chắc chắn muốn đặt lại tất cả trạng thái và lưu trữ bí mật trong tiện ích mở rộng không? Hành động này không thể hoàn tác.",
+		"delete_config_profile": "Bạn có chắc chắn muốn xóa hồ sơ cấu hình này không?",
+		"delete_custom_mode": "Bạn có chắc chắn muốn xóa chế độ tùy chỉnh này không?",
+		"delete_message": "Bạn muốn xóa gì?",
+		"just_this_message": "Chỉ tin nhắn này",
+		"this_and_subsequent": "Tin nhắn này và tất cả tin nhắn tiếp theo"
+	},
+	"errors": {
+		"invalid_mcp_config": "Định dạng cấu hình MCP dự án không hợp lệ",
+		"invalid_mcp_settings_format": "Định dạng JSON của cài đặt MCP không hợp lệ. Vui lòng đảm bảo cài đặt của bạn tuân theo định dạng JSON chính xác.",
+		"invalid_mcp_settings_syntax": "Định dạng JSON của cài đặt MCP không hợp lệ. Vui lòng kiểm tra lỗi cú pháp trong tệp cài đặt của bạn.",
+		"invalid_mcp_settings_validation": "Định dạng cài đặt MCP không hợp lệ: {{errorMessages}}",
+		"failed_initialize_project_mcp": "Không thể khởi tạo máy chủ MCP của dự án: {{error}}",
+		"invalid_data_uri": "Định dạng URI dữ liệu không hợp lệ",
+		"checkpoint_timeout": "Đã hết thời gian khi cố gắng khôi phục điểm kiểm tra.",
+		"checkpoint_failed": "Không thể khôi phục điểm kiểm tra.",
+		"no_workspace": "Vui lòng mở thư mục dự án trước",
+		"update_support_prompt": "Không thể cập nhật lời nhắc hỗ trợ",
+		"reset_support_prompt": "Không thể đặt lại lời nhắc hỗ trợ",
+		"enhance_prompt": "Không thể nâng cao lời nhắc",
+		"get_system_prompt": "Không thể lấy lời nhắc hệ thống",
+		"search_commits": "Không thể tìm kiếm các commit",
+		"save_api_config": "Không thể lưu cấu hình API",
+		"create_api_config": "Không thể tạo cấu hình API",
+		"rename_api_config": "Không thể đổi tên cấu hình API",
+		"load_api_config": "Không thể tải cấu hình API",
+		"delete_api_config": "Không thể xóa cấu hình API",
+		"list_api_config": "Không thể lấy danh sách cấu hình API",
+		"update_server_timeout": "Không thể cập nhật thời gian chờ máy chủ",
+		"create_mcp_json": "Không thể tạo hoặc mở .roo/mcp.json: {{error}}",
+		"hmr_not_running": "Máy chủ phát triển cục bộ không chạy, HMR sẽ không hoạt động. Vui lòng chạy 'npm run dev' trước khi khởi chạy tiện ích mở rộng để bật HMR.",
+		"retrieve_current_mode": "Lỗi không thể truy xuất chế độ hiện tại từ trạng thái.",
+		"failed_delete_repo": "Không thể xóa kho lưu trữ hoặc nhánh liên quan: {{error}}",
+		"failed_remove_directory": "Không thể xóa thư mục nhiệm vụ: {{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "Không có nội dung terminal được chọn",
+		"missing_task_files": "Các tệp của nhiệm vụ này bị thiếu. Bạn có muốn xóa nó khỏi danh sách nhiệm vụ không?"
+	},
+	"info": {
+		"no_changes": "Không tìm thấy thay đổi nào.",
+		"clipboard_copy": "Lời nhắc hệ thống đã được sao chép thành công vào clipboard",
+		"history_cleanup": "Đã dọn dẹp {{count}} nhiệm vụ có tệp bị thiếu khỏi lịch sử.",
+		"mcp_server_restarting": "Đang khởi động lại máy chủ MCP {{serverName}}...",
+		"mcp_server_connected": "Máy chủ MCP {{serverName}} đã kết nối",
+		"mcp_server_deleted": "Đã xóa máy chủ MCP: {{serverName}}",
+		"mcp_server_not_found": "Không tìm thấy máy chủ \"{{serverName}}\" trong cấu hình"
+	},
+	"answers": {
+		"yes": "Có",
+		"no": "Không",
+		"cancel": "Hủy",
+		"remove": "Xóa",
+		"keep": "Giữ"
+	},
+	"tasks": {
+		"canceled": "Lỗi nhiệm vụ: Nó đã bị dừng và hủy bởi người dùng.",
+		"deleted": "Nhiệm vụ thất bại: Nó đã bị dừng và xóa bởi người dùng."
+	}
+}

+ 77 - 0
src/i18n/locales/zh-CN/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "您编辑器中的完整AI开发团队。"
+	},
+	"number_format": {
+		"thousand_suffix": "千",
+		"million_suffix": "百万",
+		"billion_suffix": "十亿"
+	},
+	"welcome": "欢迎,{{name}}!您有 {{count}} 条通知。",
+	"items": {
+		"zero": "没有项目",
+		"one": "1个项目",
+		"other": "{{count}}个项目"
+	},
+	"confirmation": {
+		"reset_state": "您确定要重置扩展中的所有状态和密钥存储吗?此操作无法撤消。",
+		"delete_config_profile": "您确定要删除此配置文件吗?",
+		"delete_custom_mode": "您确定要删除此自定义模式吗?",
+		"delete_message": "您想删除什么?",
+		"just_this_message": "仅此消息",
+		"this_and_subsequent": "此消息及所有后续消息"
+	},
+	"errors": {
+		"invalid_mcp_config": "项目MCP配置格式无效",
+		"invalid_mcp_settings_format": "MCP设置JSON格式无效。请确保您的设置遵循正确的JSON格式。",
+		"invalid_mcp_settings_syntax": "MCP设置JSON格式无效。请检查您的设置文件是否有语法错误。",
+		"invalid_mcp_settings_validation": "MCP设置格式无效:{{errorMessages}}",
+		"failed_initialize_project_mcp": "初始化项目MCP服务器失败:{{error}}",
+		"invalid_data_uri": "数据URI格式无效",
+		"checkpoint_timeout": "尝试恢复检查点时超时。",
+		"checkpoint_failed": "恢复检查点失败。",
+		"no_workspace": "请先打开项目文件夹",
+		"update_support_prompt": "更新支持消息失败",
+		"reset_support_prompt": "重置支持消息失败",
+		"enhance_prompt": "增强消息失败",
+		"get_system_prompt": "获取系统消息失败",
+		"search_commits": "搜索提交失败",
+		"save_api_config": "保存API配置失败",
+		"create_api_config": "创建API配置失败",
+		"rename_api_config": "重命名API配置失败",
+		"load_api_config": "加载API配置失败",
+		"delete_api_config": "删除API配置失败",
+		"list_api_config": "获取API配置列表失败",
+		"update_server_timeout": "更新服务器超时设置失败",
+		"create_mcp_json": "创建或打开 .roo/mcp.json 失败:{{error}}",
+		"hmr_not_running": "本地开发服务器未运行,HMR将不起作用。请在启动扩展前运行'npm run dev'以启用HMR。",
+		"retrieve_current_mode": "从状态中检索当前模式失败。",
+		"failed_delete_repo": "删除关联的影子仓库或分支失败:{{error}}",
+		"failed_remove_directory": "删除任务目录失败:{{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "没有选择终端内容",
+		"missing_task_files": "此任务的文件丢失。您想从任务列表中删除它吗?"
+	},
+	"info": {
+		"no_changes": "未找到更改。",
+		"clipboard_copy": "系统消息已成功复制到剪贴板",
+		"history_cleanup": "已从历史记录中清理{{count}}个缺少文件的任务。",
+		"mcp_server_restarting": "正在重启{{serverName}}MCP服务器...",
+		"mcp_server_connected": "{{serverName}}MCP服务器已连接",
+		"mcp_server_deleted": "已删除MCP服务器:{{serverName}}",
+		"mcp_server_not_found": "在配置中未找到服务器\"{{serverName}}\""
+	},
+	"answers": {
+		"yes": "是",
+		"no": "否",
+		"cancel": "取消",
+		"remove": "删除",
+		"keep": "保留"
+	},
+	"tasks": {
+		"canceled": "任务错误:它已被用户停止并取消。",
+		"deleted": "任务失败:它已被用户停止并删除。"
+	}
+}

+ 77 - 0
src/i18n/locales/zh-TW/common.json

@@ -0,0 +1,77 @@
+{
+	"extension": {
+		"name": "Roo Code",
+		"description": "您編輯器中的完整AI開發團隊。"
+	},
+	"number_format": {
+		"thousand_suffix": "千",
+		"million_suffix": "百萬",
+		"billion_suffix": "十億"
+	},
+	"welcome": "歡迎,{{name}}!您有 {{count}} 條通知。",
+	"items": {
+		"zero": "沒有項目",
+		"one": "1個項目",
+		"other": "{{count}}個項目"
+	},
+	"confirmation": {
+		"reset_state": "您確定要重置擴展中的所有狀態和密鑰存儲嗎?此操作無法撤消。",
+		"delete_config_profile": "您確定要刪除此配置文件嗎?",
+		"delete_custom_mode": "您確定要刪除此自定義模式嗎?",
+		"delete_message": "您想刪除什麼?",
+		"just_this_message": "僅此消息",
+		"this_and_subsequent": "此消息及所有後續消息"
+	},
+	"errors": {
+		"invalid_mcp_config": "項目MCP配置格式無效",
+		"invalid_mcp_settings_format": "MCP設置JSON格式無效。請確保您的設置遵循正確的JSON格式。",
+		"invalid_mcp_settings_syntax": "MCP設置JSON格式無效。請檢查您的設置文件是否有語法錯誤。",
+		"invalid_mcp_settings_validation": "MCP設置格式無效:{{errorMessages}}",
+		"failed_initialize_project_mcp": "初始化項目MCP服務器失敗:{{error}}",
+		"invalid_data_uri": "數據URI格式無效",
+		"checkpoint_timeout": "嘗試恢復檢查點時超時。",
+		"checkpoint_failed": "恢復檢查點失敗。",
+		"no_workspace": "請先打開項目文件夾",
+		"update_support_prompt": "更新支持消息失敗",
+		"reset_support_prompt": "重置支持消息失敗",
+		"enhance_prompt": "增強消息失敗",
+		"get_system_prompt": "獲取系統消息失敗",
+		"search_commits": "搜索提交失敗",
+		"save_api_config": "保存API配置失敗",
+		"create_api_config": "創建API配置失敗",
+		"rename_api_config": "重命名API配置失敗",
+		"load_api_config": "加載API配置失敗",
+		"delete_api_config": "刪除API配置失敗",
+		"list_api_config": "獲取API配置列表失敗",
+		"update_server_timeout": "更新服務器超時設置失敗",
+		"create_mcp_json": "創建或打開 .roo/mcp.json 失敗:{{error}}",
+		"hmr_not_running": "本地開發服務器未運行,HMR將不起作用。請在啟動擴展前運行'npm run dev'以啟用HMR。",
+		"retrieve_current_mode": "從狀態中檢索當前模式失敗。",
+		"failed_delete_repo": "刪除關聯的影子倉庫或分支失敗:{{error}}",
+		"failed_remove_directory": "刪除任務目錄失敗:{{error}}"
+	},
+	"warnings": {
+		"no_terminal_content": "沒有選擇終端內容",
+		"missing_task_files": "此任務的文件丟失。您想從任務列表中刪除它嗎?"
+	},
+	"info": {
+		"no_changes": "未找到更改。",
+		"clipboard_copy": "系統消息已成功複製到剪貼板",
+		"history_cleanup": "已從歷史記錄中清理{{count}}個缺少文件的任務。",
+		"mcp_server_restarting": "正在重啟{{serverName}}MCP服務器...",
+		"mcp_server_connected": "{{serverName}}MCP服務器已連接",
+		"mcp_server_deleted": "已刪除MCP服務器:{{serverName}}",
+		"mcp_server_not_found": "在配置中未找到服務器\"{{serverName}}\""
+	},
+	"answers": {
+		"yes": "是",
+		"no": "否",
+		"cancel": "取消",
+		"remove": "刪除",
+		"keep": "保留"
+	},
+	"tasks": {
+		"canceled": "任務錯誤:它已被用戶停止並取消。",
+		"deleted": "任務失敗:它已被用戶停止並刪除。"
+	}
+}

+ 85 - 0
src/i18n/setup.ts

@@ -0,0 +1,85 @@
+import i18next from "i18next"
+
+// Build translations object
+const translations: Record<string, Record<string, any>> = {}
+
+// Determine if running in test environment (jest)
+const isTestEnv = process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== undefined
+
+// Detect environment - browser vs Node.js
+const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined"
+
+// Define interface for VSCode extension process
+interface VSCodeProcess extends NodeJS.Process {
+	resourcesPath?: string
+}
+
+// Type cast process to custom interface with resourcesPath
+const vscodeProcess = process as VSCodeProcess
+
+// Load translations based on environment
+if (!isTestEnv) {
+	try {
+		// Dynamic imports to avoid browser compatibility issues
+		const fs = require("fs")
+		const path = require("path")
+
+		const localesDir = path.join(__dirname, "i18n", "locales")
+
+		try {
+			// Find all language directories
+			const languageDirs = fs.readdirSync(localesDir, { withFileTypes: true })
+
+			const languages = languageDirs
+				.filter((dirent: { isDirectory: () => boolean }) => dirent.isDirectory())
+				.map((dirent: { name: string }) => dirent.name)
+
+			// Process each language
+			languages.forEach((language: string) => {
+				const langPath = path.join(localesDir, language)
+
+				// Find all JSON files in the language directory
+				const files = fs.readdirSync(langPath).filter((file: string) => file.endsWith(".json"))
+
+				// Initialize language in translations object
+				if (!translations[language]) {
+					translations[language] = {}
+				}
+
+				// Process each namespace file
+				files.forEach((file: string) => {
+					const namespace = path.basename(file, ".json")
+					const filePath = path.join(langPath, file)
+
+					try {
+						// Read and parse the JSON file
+						const content = fs.readFileSync(filePath, "utf8")
+						translations[language][namespace] = JSON.parse(content)
+						console.log(`Successfully loaded '${language}/${namespace}' translations`)
+					} catch (error) {
+						console.error(`Error loading translation file ${filePath}:`, error)
+					}
+				})
+			})
+
+			console.log(`Loaded translations for languages: ${Object.keys(translations).join(", ")}`)
+		} catch (dirError) {
+			console.error(`Error processing directory ${localesDir}:`, dirError)
+		}
+	} catch (error) {
+		console.error("Error loading translations:", error)
+	}
+}
+
+// Initialize i18next with configuration
+i18next.init({
+	lng: "en",
+	fallbackLng: "en",
+	debug: false,
+	resources: translations,
+	interpolation: {
+		escapeValue: false,
+	},
+})
+
+export default i18next

+ 13 - 12
src/services/mcp/McpHub.ts

@@ -16,6 +16,7 @@ import * as fs from "fs/promises"
 import * as path from "path"
 import * as vscode from "vscode"
 import { z } from "zod"
+import { t } from "../../i18n"
 
 import { ClineProvider } from "../../core/webview/ClineProvider"
 import { GlobalFileNames } from "../../shared/globalFileNames"
@@ -285,8 +286,7 @@ export class McpHub {
 			vscode.workspace.onDidSaveTextDocument(async (document) => {
 				if (arePathsEqual(document.uri.fsPath, settingsPath)) {
 					const content = await fs.readFile(settingsPath, "utf-8")
-					const errorMessage =
-						"Invalid MCP settings JSON format. Please ensure your settings follow the correct JSON format."
+					const errorMessage = t("common:errors.invalid_mcp_settings_format")
 					let config: any
 					try {
 						config = JSON.parse(content)
@@ -299,7 +299,9 @@ export class McpHub {
 						const errorMessages = result.error.errors
 							.map((err) => `${err.path.join(".")}: ${err.message}`)
 							.join("\n")
-						vscode.window.showErrorMessage(`Invalid MCP settings format: ${errorMessages}`)
+						vscode.window.showErrorMessage(
+							t("common:errors.invalid_mcp_settings_validation", { errorMessages }),
+						)
 						return
 					}
 					try {
@@ -323,8 +325,7 @@ export class McpHub {
 			try {
 				config = JSON.parse(content)
 			} catch (parseError) {
-				const errorMessage =
-					"Invalid MCP settings JSON format. Please check your settings file for syntax errors."
+				const errorMessage = t("common:errors.invalid_mcp_settings_syntax")
 				console.error(errorMessage, parseError)
 				vscode.window.showErrorMessage(errorMessage)
 				return
@@ -340,7 +341,7 @@ export class McpHub {
 					.map((err) => `${err.path.join(".")}: ${err.message}`)
 					.join("\n")
 				console.error("Invalid MCP settings format:", errorMessages)
-				vscode.window.showErrorMessage(`Invalid MCP settings format: ${errorMessages}`)
+				vscode.window.showErrorMessage(t("common:errors.invalid_mcp_settings_validation", { errorMessages }))
 
 				// Still try to connect with the raw config, but show warnings
 				try {
@@ -386,7 +387,7 @@ export class McpHub {
 			// Validate configuration structure
 			const result = McpSettingsSchema.safeParse(config)
 			if (!result.success) {
-				vscode.window.showErrorMessage("Invalid project MCP configuration format")
+				vscode.window.showErrorMessage(t("common:errors.invalid_mcp_config"))
 				return
 			}
 
@@ -394,7 +395,7 @@ export class McpHub {
 			await this.updateServerConnections(result.data.mcpServers || {}, "project")
 		} catch (error) {
 			console.error("Failed to initialize project MCP servers:", error)
-			vscode.window.showErrorMessage(`Failed to initialize project MCP server: ${error}`)
+			vscode.window.showErrorMessage(t("common:errors.failed_initialize_project_mcp", { error }))
 		}
 	}
 
@@ -718,7 +719,7 @@ export class McpHub {
 		const connection = this.connections.find((conn) => conn.server.name === serverName)
 		const config = connection?.server.config
 		if (config) {
-			vscode.window.showInformationMessage(`Restarting ${serverName} MCP server...`)
+			vscode.window.showInformationMessage(t("common:info.mcp_server_restarting", { serverName }))
 			connection.server.status = "connecting"
 			connection.server.error = "" // Clear any previous error messages
 			await this.notifyWebviewOfServerChanges()
@@ -735,7 +736,7 @@ export class McpHub {
 
 					// Try to connect again using validated config and preserve the original source
 					await this.connectToServer(serverName, validatedConfig, source)
-					vscode.window.showInformationMessage(`${serverName} MCP server connected`)
+					vscode.window.showInformationMessage(t("common:info.mcp_server_connected", { serverName }))
 				} catch (validationError) {
 					this.showErrorMessage(`Invalid configuration for MCP server "${serverName}"`, validationError)
 				}
@@ -969,9 +970,9 @@ export class McpHub {
 					await this.updateServerConnections(config.mcpServers)
 				}
 
-				vscode.window.showInformationMessage(`Deleted MCP server: ${serverName}`)
+				vscode.window.showInformationMessage(t("common:info.mcp_server_deleted", { serverName }))
 			} else {
-				vscode.window.showWarningMessage(`Server "${serverName}" not found in configuration`)
+				vscode.window.showWarningMessage(t("common:info.mcp_server_not_found", { serverName }))
 			}
 		} catch (error) {
 			this.showErrorMessage(`Failed to delete MCP server ${serverName}`, error)

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است