feat: Delete .roo/rules-{mode} folder when custom mode is deleted (#5210) (#5317)

* feat: Add folder deletion when custom mode is deleted (#5210)

* fix: address PR feedback - fix Korean translation typo and add missing German translation

* fix: use os.homedir() instead of vscode.env.userHome

* fix: use dynamic home directory in webview tests for cross-platform compatibility

* fix: normalize path separators in tests for Windows compatibility

* feat: implement DeleteModeDialog component for mode deletion confirmation

* fix: use ref to store current modeToDelete value for consistent state handling

* feat: add error handling for rules folder deletion and localize error messages

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

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

* Update src/i18n/locales/zh-CN/common.json

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

* fix: remove redundant rulesFolderExists from deleteCustomModeCheck response

* fix: update webviewMessageHandler tests to match fs import style

---------

Co-authored-by: Daniel Riccio <ricciodaniel98@gmail.com>
Co-authored-by: Daniel <57051444+daniel-lxs@users.noreply.github.com>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
Hannes Rudolph 2025-07-03 11:00:07 -06:00 committed by GitHub
parent 7e8c1d71a4
commit 329690cf54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 797 additions and 43 deletions

View file

@ -14,8 +14,82 @@ const mockGetModels = getModels as Mock<typeof getModels>
const mockClineProvider = {
getState: vi.fn(),
postMessageToWebview: vi.fn(),
customModesManager: {
getCustomModes: vi.fn(),
deleteCustomMode: vi.fn(),
},
context: {
extensionPath: "/mock/extension/path",
globalStorageUri: { fsPath: "/mock/global/storage" },
},
contextProxy: {
context: {
extensionPath: "/mock/extension/path",
globalStorageUri: { fsPath: "/mock/global/storage" },
},
setValue: vi.fn(),
},
log: vi.fn(),
postStateToWebview: vi.fn(),
} as unknown as ClineProvider
import { t } from "../../../i18n"
vi.mock("vscode", () => ({
window: {
showInformationMessage: vi.fn(),
showErrorMessage: vi.fn(),
},
workspace: {
workspaceFolders: [{ uri: { fsPath: "/mock/workspace" } }],
},
}))
vi.mock("../../../i18n", () => ({
t: vi.fn((key: string, args?: Record<string, any>) => {
// For the delete confirmation with rules, we need to return the interpolated string
if (key === "common:confirmation.delete_custom_mode_with_rules" && args) {
return `Are you sure you want to delete this ${args.scope} mode?\n\nThis will also delete the associated rules folder at:\n${args.rulesFolderPath}`
}
// Return the translated value for "Yes"
if (key === "common:answers.yes") {
return "Yes"
}
// Return the translated value for "Cancel"
if (key === "common:answers.cancel") {
return "Cancel"
}
return key
}),
}))
vi.mock("fs/promises", () => {
const mockRm = vi.fn().mockResolvedValue(undefined)
const mockMkdir = vi.fn().mockResolvedValue(undefined)
return {
default: {
rm: mockRm,
mkdir: mockMkdir,
},
rm: mockRm,
mkdir: mockMkdir,
}
})
import * as vscode from "vscode"
import * as fs from "fs/promises"
import * as os from "os"
import * as path from "path"
import * as fsUtils from "../../../utils/fs"
import { getWorkspacePath } from "../../../utils/path"
import { ensureSettingsDirectoryExists } from "../../../utils/globalContext"
import type { ModeConfig } from "@roo-code/types"
vi.mock("../../../utils/fs")
vi.mock("../../../utils/path")
vi.mock("../../../utils/globalContext")
describe("webviewMessageHandler - requestRouterModels", () => {
beforeEach(() => {
vi.clearAllMocks()
@ -295,3 +369,116 @@ describe("webviewMessageHandler - requestRouterModels", () => {
})
})
})
describe("webviewMessageHandler - deleteCustomMode", () => {
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(getWorkspacePath).mockReturnValue("/mock/workspace")
vi.mocked(vscode.window.showErrorMessage).mockResolvedValue(undefined)
vi.mocked(ensureSettingsDirectoryExists).mockResolvedValue("/mock/global/storage/.roo")
})
it("should delete a project mode and its rules folder", async () => {
const slug = "test-project-mode"
const rulesFolderPath = path.join("/mock/workspace", ".roo", `rules-${slug}`)
vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([
{
name: "Test Project Mode",
slug,
roleDefinition: "Test Role",
groups: [],
source: "project",
} as ModeConfig,
])
vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(true)
vi.mocked(mockClineProvider.customModesManager.deleteCustomMode).mockResolvedValue(undefined)
await webviewMessageHandler(mockClineProvider, { type: "deleteCustomMode", slug })
// The confirmation dialog is now handled in the webview, so we don't expect showInformationMessage to be called
expect(vscode.window.showInformationMessage).not.toHaveBeenCalled()
expect(mockClineProvider.customModesManager.deleteCustomMode).toHaveBeenCalledWith(slug)
expect(fs.rm).toHaveBeenCalledWith(rulesFolderPath, { recursive: true, force: true })
})
it("should delete a global mode and its rules folder", async () => {
const slug = "test-global-mode"
const homeDir = os.homedir()
const rulesFolderPath = path.join(homeDir, ".roo", `rules-${slug}`)
vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([
{
name: "Test Global Mode",
slug,
roleDefinition: "Test Role",
groups: [],
source: "global",
} as ModeConfig,
])
vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(true)
vi.mocked(mockClineProvider.customModesManager.deleteCustomMode).mockResolvedValue(undefined)
await webviewMessageHandler(mockClineProvider, { type: "deleteCustomMode", slug })
// The confirmation dialog is now handled in the webview, so we don't expect showInformationMessage to be called
expect(vscode.window.showInformationMessage).not.toHaveBeenCalled()
expect(mockClineProvider.customModesManager.deleteCustomMode).toHaveBeenCalledWith(slug)
expect(fs.rm).toHaveBeenCalledWith(rulesFolderPath, { recursive: true, force: true })
})
it("should only delete the mode when rules folder does not exist", async () => {
const slug = "test-mode-no-rules"
vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([
{
name: "Test Mode No Rules",
slug,
roleDefinition: "Test Role",
groups: [],
source: "project",
} as ModeConfig,
])
vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(false)
vi.mocked(mockClineProvider.customModesManager.deleteCustomMode).mockResolvedValue(undefined)
await webviewMessageHandler(mockClineProvider, { type: "deleteCustomMode", slug })
// The confirmation dialog is now handled in the webview, so we don't expect showInformationMessage to be called
expect(vscode.window.showInformationMessage).not.toHaveBeenCalled()
expect(mockClineProvider.customModesManager.deleteCustomMode).toHaveBeenCalledWith(slug)
expect(fs.rm).not.toHaveBeenCalled()
})
it("should handle errors when deleting rules folder", async () => {
const slug = "test-mode-error"
const rulesFolderPath = path.join("/mock/workspace", ".roo", `rules-${slug}`)
const error = new Error("Permission denied")
vi.mocked(mockClineProvider.customModesManager.getCustomModes).mockResolvedValue([
{
name: "Test Mode Error",
slug,
roleDefinition: "Test Role",
groups: [],
source: "project",
} as ModeConfig,
])
vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(true)
vi.mocked(mockClineProvider.customModesManager.deleteCustomMode).mockResolvedValue(undefined)
vi.mocked(fs.rm).mockRejectedValue(error)
await webviewMessageHandler(mockClineProvider, { type: "deleteCustomMode", slug })
expect(mockClineProvider.customModesManager.deleteCustomMode).toHaveBeenCalledWith(slug)
expect(fs.rm).toHaveBeenCalledWith(rulesFolderPath, { recursive: true, force: true })
// Verify error message is shown to the user
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith(
t("common:errors.delete_rules_folder_failed", {
rulesFolderPath,
error: error.message,
}),
)
// No error response is sent anymore - we just continue with deletion
expect(mockClineProvider.postMessageToWebview).not.toHaveBeenCalled()
})
})

View file

@ -1,5 +1,6 @@
import { safeWriteJson } from "../../utils/safeWriteJson"
import * as path from "path"
import * as os from "os"
import * as fs from "fs/promises"
import pWaitFor from "p-wait-for"
import * as vscode from "vscode"
@ -35,6 +36,7 @@ import { getVsCodeLmModels } from "../../api/providers/vscode-lm"
import { openMention } from "../mentions"
import { TelemetrySetting } from "../../shared/TelemetrySetting"
import { getWorkspacePath } from "../../utils/path"
import { ensureSettingsDirectoryExists } from "../../utils/globalContext"
import { Mode, defaultModeSlug } from "../../shared/modes"
import { getModels, flushModels } from "../../api/providers/fetchers/modelCache"
import { GetModelsOptions } from "../../shared/api"
@ -1494,17 +1496,66 @@ export const webviewMessageHandler = async (
break
case "deleteCustomMode":
if (message.slug) {
const answer = await vscode.window.showInformationMessage(
t("common:confirmation.delete_custom_mode"),
{ modal: true },
t("common:answers.yes"),
)
// Get the mode details to determine source and rules folder path
const customModes = await provider.customModesManager.getCustomModes()
const modeToDelete = customModes.find((mode) => mode.slug === message.slug)
if (answer !== t("common:answers.yes")) {
if (!modeToDelete) {
break
}
// Determine the scope based on source (project or global)
const scope = modeToDelete.source || "global"
// Determine the rules folder path
let rulesFolderPath: string
if (scope === "project") {
const workspacePath = getWorkspacePath()
if (workspacePath) {
rulesFolderPath = path.join(workspacePath, ".roo", `rules-${message.slug}`)
} else {
rulesFolderPath = path.join(".roo", `rules-${message.slug}`)
}
} else {
// Global scope - use OS home directory
const homeDir = os.homedir()
rulesFolderPath = path.join(homeDir, ".roo", `rules-${message.slug}`)
}
// Check if the rules folder exists
const rulesFolderExists = await fileExistsAtPath(rulesFolderPath)
// If this is a check request, send back the folder info
if (message.checkOnly) {
await provider.postMessageToWebview({
type: "deleteCustomModeCheck",
slug: message.slug,
rulesFolderPath: rulesFolderExists ? rulesFolderPath : undefined,
})
break
}
// Delete the mode
await provider.customModesManager.deleteCustomMode(message.slug)
// Delete the rules folder if it exists
if (rulesFolderExists) {
try {
await fs.rm(rulesFolderPath, { recursive: true, force: true })
provider.log(`Deleted rules folder for mode ${message.slug}: ${rulesFolderPath}`)
} catch (error) {
provider.log(`Failed to delete rules folder for mode ${message.slug}: ${error}`)
// Notify the user about the failure
vscode.window.showErrorMessage(
t("common:errors.delete_rules_folder_failed", {
rulesFolderPath,
error: error instanceof Error ? error.message : String(error),
}),
)
// Continue with mode deletion even if folder deletion fails
}
}
// Switch back to default mode after deletion
await updateGlobalState("mode", defaultModeSlug)
await provider.postStateToWebview()

View file

@ -21,7 +21,7 @@
"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_custom_mode_with_rules": "Esteu segur que voleu suprimir aquest mode {scope}?\n\nAixò també suprimirà la carpeta de regles associada a:\n{rulesFolderPath}",
"delete_message": "Què vols eliminar?",
"just_this_message": "Només aquest missatge",
"this_and_subsequent": "Aquest i tots els missatges posteriors"
@ -74,6 +74,7 @@
"share_auth_required": "Es requereix autenticació. Si us plau, inicia sessió per compartir tasques.",
"share_not_enabled": "La compartició de tasques no està habilitada per a aquesta organització.",
"share_task_not_found": "Tasca no trobada o accés denegat.",
"delete_rules_folder_failed": "Error en eliminar la carpeta de regles: {{rulesFolderPath}}. Error: {{error}}",
"claudeCode": {
"processExited": "El procés Claude Code ha sortit amb codi {{exitCode}}.",
"errorOutput": "Sortida d'error: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Error en restablir els modes personalitzats: {{error}}",
"modeNotFound": "Error d'escriptura: Mode no trobat",
"noWorkspaceForProject": "No s'ha trobat cap carpeta d'espai de treball per al mode específic del projecte"
},
"scope": {
"project": "projecte",
"global": "global"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Has d'estar autenticat amb el compte de Roo Code Cloud de la teva organització.",
"verification_failed": "No s'ha pogut verificar l'autenticació de l'organització."
}
},
"prompts": {
"deleteMode": {
"title": "Suprimeix el mode personalitzat",
"description": "Esteu segur que voleu suprimir aquest mode {{scope}}? Això també suprimirà la carpeta de regles associada a: {{rulesFolderPath}}",
"descriptionNoRules": "Esteu segur que voleu suprimir aquest mode personalitzat?",
"cancel": "Cancel·la",
"confirm": "Suprimeix"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "Möchtest du wirklich alle Zustände und geheimen Speicher in der Erweiterung zurücksetzen? Dies kann nicht rückgängig gemacht werden.",
"delete_config_profile": "Möchtest du dieses Konfigurationsprofil wirklich löschen?",
"delete_custom_mode": "Möchtest du diesen benutzerdefinierten Modus wirklich löschen?",
"delete_custom_mode_with_rules": "Bist du sicher, dass du diesen {scope}-Modus löschen möchtest?\n\nDadurch wird auch der zugehörige Regelordner unter folgender Adresse gelöscht:\n{rulesFolderPath}",
"delete_message": "Was möchtest du löschen?",
"just_this_message": "Nur diese Nachricht",
"this_and_subsequent": "Diese und alle nachfolgenden Nachrichten"
@ -71,6 +71,7 @@
"share_not_enabled": "Aufgabenfreigabe ist für diese Organisation nicht aktiviert.",
"share_task_not_found": "Aufgabe nicht gefunden oder Zugriff verweigert.",
"mode_import_failed": "Fehler beim Importieren des Modus: {{error}}",
"delete_rules_folder_failed": "Fehler beim Löschen des Regelordners: {{rulesFolderPath}}. Fehler: {{error}}",
"claudeCode": {
"processExited": "Claude Code Prozess wurde mit Code {{exitCode}} beendet.",
"errorOutput": "Fehlerausgabe: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Fehler beim Zurücksetzen der benutzerdefinierten Modi: {{error}}",
"modeNotFound": "Schreibfehler: Modus nicht gefunden",
"noWorkspaceForProject": "Kein Arbeitsbereich-Ordner für projektspezifischen Modus gefunden"
},
"scope": {
"project": "projekt",
"global": "global"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Du musst mit dem Roo Code Cloud-Konto deiner Organisation authentifiziert sein.",
"verification_failed": "Die Organisationsauthentifizierung konnte nicht verifiziert werden."
}
},
"prompts": {
"deleteMode": {
"title": "Benutzerdefinierten Modus löschen",
"description": "Bist du sicher, dass du diesen {{scope}}-Modus löschen möchtest? Dadurch wird auch der zugehörige Regelordner unter {{rulesFolderPath}} gelöscht",
"descriptionNoRules": "Bist du sicher, dass du diesen benutzerdefinierten Modus löschen möchtest?",
"cancel": "Abbrechen",
"confirm": "Löschen"
}
}
}

View file

@ -17,7 +17,7 @@
"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_custom_mode_with_rules": "Are you sure you want to delete this {scope} mode?\n\nThis will also delete the associated rules folder at:\n{rulesFolderPath}",
"delete_message": "What would you like to delete?",
"just_this_message": "Just this message",
"this_and_subsequent": "This and all subsequent messages"
@ -71,6 +71,7 @@
"share_not_enabled": "Task sharing is not enabled for this organization.",
"share_task_not_found": "Task not found or access denied.",
"mode_import_failed": "Failed to import mode: {{error}}",
"delete_rules_folder_failed": "Failed to delete rules folder: {{rulesFolderPath}}. Error: {{error}}",
"claudeCode": {
"processExited": "Claude Code process exited with code {{exitCode}}.",
"errorOutput": "Error output: {{output}}",
@ -133,6 +134,10 @@
"resetFailed": "Failed to reset custom modes: {{error}}",
"modeNotFound": "Write error: Mode not found",
"noWorkspaceForProject": "No workspace folder found for project-specific mode"
},
"scope": {
"project": "project",
"global": "global"
}
},
"mdm": {
@ -141,5 +146,14 @@
"organization_mismatch": "You must be authenticated with your organization's Roo Code Cloud account.",
"verification_failed": "Unable to verify organization authentication."
}
},
"prompts": {
"deleteMode": {
"title": "Delete Custom Mode",
"description": "Are you sure you want to delete this {{scope}} mode? This will also delete the associated rules folder at: {{rulesFolderPath}}",
"descriptionNoRules": "Are you sure you want to delete this custom mode?",
"cancel": "Cancel",
"confirm": "Delete"
}
}
}

View file

@ -17,7 +17,7 @@
"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_custom_mode_with_rules": "¿Estás seguro de que quieres eliminar este modo {scope}?\n\nEsto también eliminará la carpeta de reglas asociada en:\n{rulesFolderPath}",
"delete_message": "¿Qué deseas eliminar?",
"just_this_message": "Solo este mensaje",
"this_and_subsequent": "Este y todos los mensajes posteriores"
@ -71,6 +71,7 @@
"share_not_enabled": "La compartición de tareas no está habilitada para esta organización.",
"share_task_not_found": "Tarea no encontrada o acceso denegado.",
"mode_import_failed": "Error al importar el modo: {{error}}",
"delete_rules_folder_failed": "Error al eliminar la carpeta de reglas: {{rulesFolderPath}}. Error: {{error}}",
"claudeCode": {
"processExited": "El proceso de Claude Code terminó con código {{exitCode}}.",
"errorOutput": "Salida de error: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Error al restablecer modos personalizados: {{error}}",
"modeNotFound": "Error de escritura: Modo no encontrado",
"noWorkspaceForProject": "No se encontró carpeta de espacio de trabajo para modo específico del proyecto"
},
"scope": {
"project": "proyecto",
"global": "global"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Debes estar autenticado con la cuenta de Roo Code Cloud de tu organización.",
"verification_failed": "No se pudo verificar la autenticación de la organización."
}
},
"prompts": {
"deleteMode": {
"title": "Eliminar modo personalizado",
"description": "¿Estás seguro de que quieres eliminar este modo {{scope}}? Esto también eliminará la carpeta de reglas asociada en: {{rulesFolderPath}}",
"descriptionNoRules": "¿Estás seguro de que quieres eliminar este modo personalizado?",
"cancel": "Cancelar",
"confirm": "Eliminar"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "Êtes-vous sûr de vouloir réinitialiser le global state et le stockage de secrets de l'extension ? Cette action est irréversible.",
"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_custom_mode_with_rules": "Êtes-vous sûr de vouloir supprimer ce mode {scope} ?\n\nCela supprimera également le dossier de règles associé à l'adresse :\n{rulesFolderPath}",
"delete_message": "Que souhaitez-vous supprimer ?",
"just_this_message": "Uniquement ce message",
"this_and_subsequent": "Ce message et tous les messages suivants"
@ -71,6 +71,7 @@
"share_not_enabled": "Le partage de tâches n'est pas activé pour cette organisation.",
"share_task_not_found": "Tâche non trouvée ou accès refusé.",
"mode_import_failed": "Échec de l'importation du mode : {{error}}",
"delete_rules_folder_failed": "Échec de la suppression du dossier de règles : {{rulesFolderPath}}. Erreur : {{error}}",
"claudeCode": {
"processExited": "Le processus Claude Code s'est terminé avec le code {{exitCode}}.",
"errorOutput": "Sortie d'erreur : {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Échec de la réinitialisation des modes personnalisés : {{error}}",
"modeNotFound": "Erreur d'écriture : Mode non trouvé",
"noWorkspaceForProject": "Aucun dossier d'espace de travail trouvé pour le mode spécifique au projet"
},
"scope": {
"project": "projet",
"global": "global"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Vous devez être authentifié avec le compte Roo Code Cloud de votre organisation.",
"verification_failed": "Impossible de vérifier l'authentification de l'organisation."
}
},
"prompts": {
"deleteMode": {
"title": "Supprimer le mode personnalisé",
"description": "Êtes-vous sûr de vouloir supprimer ce mode {{scope}} ? Cela supprimera également le dossier de règles associé à l'adresse : {{rulesFolderPath}}",
"descriptionNoRules": "Êtes-vous sûr de vouloir supprimer ce mode personnalisé ?",
"cancel": "Annuler",
"confirm": "Supprimer"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "क्या आप वाकई एक्सटेंशन में सभी स्टेट और गुप्त स्टोरेज रीसेट करना चाहते हैं? इसे पूर्ववत नहीं किया जा सकता है।",
"delete_config_profile": "क्या आप वाकई इस कॉन्फ़िगरेशन प्रोफ़ाइल को हटाना चाहते हैं?",
"delete_custom_mode": "क्या आप वाकई इस कस्टम मोड को हटाना चाहते हैं?",
"delete_custom_mode_with_rules": "क्या आप वाकई इस {scope} मोड को हटाना चाहते हैं?\n\nयह संबंधित नियम फ़ोल्डर को भी यहाँ हटा देगा:\n{rulesFolderPath}",
"delete_message": "आप क्या हटाना चाहते हैं?",
"just_this_message": "सिर्फ यह संदेश",
"this_and_subsequent": "यह और सभी बाद के संदेश"
@ -71,6 +71,7 @@
"share_not_enabled": "इस संगठन के लिए कार्य साझाकरण सक्षम नहीं है।",
"share_task_not_found": "कार्य नहीं मिला या पहुंच अस्वीकृत।",
"mode_import_failed": "मोड आयात करने में विफल: {{error}}",
"delete_rules_folder_failed": "नियम फ़ोल्डर हटाने में विफल: {{rulesFolderPath}}। त्रुटि: {{error}}",
"claudeCode": {
"processExited": "Claude Code प्रक्रिया कोड {{exitCode}} के साथ समाप्त हुई।",
"errorOutput": "त्रुटि आउटपुट: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "कस्टम मोड रीसेट विफल: {{error}}",
"modeNotFound": "लेखन त्रुटि: मोड नहीं मिला",
"noWorkspaceForProject": "प्रोजेक्ट-विशिष्ट मोड के लिए वर्कस्पेस फ़ोल्डर नहीं मिला"
},
"scope": {
"project": "परियोजना",
"global": "वैश्विक"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "आपको अपने संगठन के Roo Code Cloud खाते से प्रमाणित होना होगा।",
"verification_failed": "संगठन प्रमाणीकरण सत्यापित करने में असमर्थ।"
}
},
"prompts": {
"deleteMode": {
"title": "कस्टम मोड हटाएं",
"description": "क्या आप वाकई इस {{scope}} मोड को हटाना चाहते हैं? यह संबंधित नियम फ़ोल्डर को भी {{rulesFolderPath}} पर हटा देगा",
"descriptionNoRules": "क्या आप वाकई इस कस्टम मोड को हटाना चाहते हैं?",
"cancel": "रद्द करें",
"confirm": "हटाएं"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "Apakah kamu yakin ingin mereset semua state dan secret storage di ekstensi? Ini tidak dapat dibatalkan.",
"delete_config_profile": "Apakah kamu yakin ingin menghapus profil konfigurasi ini?",
"delete_custom_mode": "Apakah kamu yakin ingin menghapus mode kustom ini?",
"delete_custom_mode_with_rules": "Anda yakin ingin menghapus mode {scope} ini?\n\nIni juga akan menghapus folder aturan terkait di:\n{rulesFolderPath}",
"delete_message": "Apa yang ingin kamu hapus?",
"just_this_message": "Hanya pesan ini",
"this_and_subsequent": "Ini dan semua pesan selanjutnya"
@ -71,6 +71,7 @@
"share_not_enabled": "Berbagi tugas tidak diaktifkan untuk organisasi ini.",
"share_task_not_found": "Tugas tidak ditemukan atau akses ditolak.",
"mode_import_failed": "Gagal mengimpor mode: {{error}}",
"delete_rules_folder_failed": "Gagal menghapus folder aturan: {{rulesFolderPath}}. Error: {{error}}",
"claudeCode": {
"processExited": "Proses Claude Code keluar dengan kode {{exitCode}}.",
"errorOutput": "Output error: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Gagal mereset mode kustom: {{error}}",
"modeNotFound": "Kesalahan tulis: Mode tidak ditemukan",
"noWorkspaceForProject": "Tidak ditemukan folder workspace untuk mode khusus proyek"
},
"scope": {
"project": "proyek",
"global": "global"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Kamu harus diautentikasi dengan akun Roo Code Cloud organisasi kamu.",
"verification_failed": "Tidak dapat memverifikasi autentikasi organisasi."
}
},
"prompts": {
"deleteMode": {
"title": "Hapus Mode Kustom",
"description": "Anda yakin ingin menghapus mode {{scope}} ini? Ini juga akan menghapus folder aturan terkait di: {{rulesFolderPath}}",
"descriptionNoRules": "Anda yakin ingin menghapus mode kustom ini?",
"cancel": "Batal",
"confirm": "Hapus"
}
}
}

View file

@ -17,7 +17,7 @@
"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_custom_mode_with_rules": "Sei sicuro di voler eliminare questa modalità {scope}?\n\nQuesto eliminerà anche la cartella delle regole associata in:\n{rulesFolderPath}",
"delete_message": "Cosa desideri eliminare?",
"just_this_message": "Solo questo messaggio",
"this_and_subsequent": "Questo e tutti i messaggi successivi"
@ -71,6 +71,7 @@
"share_not_enabled": "La condivisione delle attività non è abilitata per questa organizzazione.",
"share_task_not_found": "Attività non trovata o accesso negato.",
"mode_import_failed": "Importazione della modalità non riuscita: {{error}}",
"delete_rules_folder_failed": "Impossibile eliminare la cartella delle regole: {{rulesFolderPath}}. Errore: {{error}}",
"claudeCode": {
"processExited": "Il processo Claude Code è terminato con codice {{exitCode}}.",
"errorOutput": "Output di errore: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Reset modalità personalizzate fallito: {{error}}",
"modeNotFound": "Errore di scrittura: Modalità non trovata",
"noWorkspaceForProject": "Nessuna cartella workspace trovata per la modalità specifica del progetto"
},
"scope": {
"project": "progetto",
"global": "globale"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Devi essere autenticato con l'account Roo Code Cloud della tua organizzazione.",
"verification_failed": "Impossibile verificare l'autenticazione dell'organizzazione."
}
},
"prompts": {
"deleteMode": {
"title": "Elimina Modalità Personalizzata",
"description": "Sei sicuro di voler eliminare questa modalità {{scope}}? Questo eliminerà anche la cartella delle regole associata a: {{rulesFolderPath}}",
"descriptionNoRules": "Sei sicuro di voler eliminare questa modalità personalizzata?",
"cancel": "Annulla",
"confirm": "Elimina"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "拡張機能のすべての状態とシークレットストレージをリセットしてもよろしいですか?この操作は元に戻せません。",
"delete_config_profile": "この設定プロファイルを削除してもよろしいですか?",
"delete_custom_mode": "このカスタムモードを削除してもよろしいですか?",
"delete_custom_mode_with_rules": "この{scope}モードを削除してもよろしいですか?\n\nこれにより、関連するルールフォルダも次の場所で削除されます:\n{rulesFolderPath}",
"delete_message": "何を削除しますか?",
"just_this_message": "このメッセージのみ",
"this_and_subsequent": "これ以降のすべてのメッセージ"
@ -70,7 +70,8 @@
"share_auth_required": "認証が必要です。タスクを共有するにはサインインしてください。",
"share_not_enabled": "この組織ではタスク共有が有効になっていません。",
"share_task_not_found": "タスクが見つからないか、アクセスが拒否されました。",
"mode_import_failed": "モードのインポートに失敗しました: {{error}}",
"mode_import_failed": "モードのインポートに失敗しました:{{error}}",
"delete_rules_folder_failed": "ルールフォルダの削除に失敗しました:{{rulesFolderPath}}。エラー:{{error}}",
"claudeCode": {
"processExited": "Claude Code プロセスがコード {{exitCode}} で終了しました。",
"errorOutput": "エラー出力:{{output}}",
@ -144,6 +145,10 @@
"resetFailed": "カスタムモードのリセットに失敗しました:{{error}}",
"modeNotFound": "書き込みエラー:モードが見つかりません",
"noWorkspaceForProject": "プロジェクト固有モード用のワークスペースフォルダーが見つかりません"
},
"scope": {
"project": "プロジェクト",
"global": "グローバル"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "組織の Roo Code Cloud アカウントで認証する必要があります。",
"verification_failed": "組織認証の確認ができませんでした。"
}
},
"prompts": {
"deleteMode": {
"title": "カスタムモードの削除",
"description": "この{{scope}}モードを削除してもよろしいですか?これにより、関連するルールフォルダーも{{rulesFolderPath}}で削除されます",
"descriptionNoRules": "このカスタムモードを削除してもよろしいですか?",
"cancel": "キャンセル",
"confirm": "削除"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "확장 프로그램의 모든 상태와 보안 저장소를 재설정하시겠습니까? 이 작업은 취소할 수 없습니다.",
"delete_config_profile": "이 구성 프로필을 삭제하시겠습니까?",
"delete_custom_mode": "이 사용자 지정 모드를 삭제하시겠습니까?",
"delete_custom_mode_with_rules": "이 {scope} 모드를 삭제하시겠습니까?\n\n이렇게 하면 연결된 규칙 폴더도 다음 위치에서 삭제됩니다:\n{rulesFolderPath}",
"delete_message": "무엇을 삭제하시겠습니까?",
"just_this_message": "이 메시지만",
"this_and_subsequent": "이 메시지와 모든 후속 메시지"
@ -71,6 +71,7 @@
"share_not_enabled": "이 조직에서는 작업 공유가 활성화되지 않았습니다.",
"share_task_not_found": "작업을 찾을 수 없거나 액세스가 거부되었습니다.",
"mode_import_failed": "모드 가져오기 실패: {{error}}",
"delete_rules_folder_failed": "규칙 폴더 삭제 실패: {{rulesFolderPath}}. 오류: {{error}}",
"claudeCode": {
"processExited": "Claude Code 프로세스가 코드 {{exitCode}}로 종료되었습니다.",
"errorOutput": "오류 출력: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "사용자 정의 모드 재설정 실패: {{error}}",
"modeNotFound": "쓰기 오류: 모드를 찾을 수 없습니다",
"noWorkspaceForProject": "프로젝트별 모드용 작업 공간 폴더를 찾을 수 없습니다"
},
"scope": {
"project": "프로젝트",
"global": "글로벌"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "조직의 Roo Code Cloud 계정으로 인증해야 합니다.",
"verification_failed": "조직 인증을 확인할 수 없습니다."
}
},
"prompts": {
"deleteMode": {
"title": "사용자 정의 모드 삭제",
"description": "이 {{scope}} 모드를 삭제하시겠습니까? 이렇게 하면 {{rulesFolderPath}}의 관련 규칙 폴더도 삭제됩니다.",
"descriptionNoRules": "이 사용자 정의 모드를 삭제하시겠습니까?",
"cancel": "취소",
"confirm": "삭제"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "Weet je zeker dat je alle status en geheime opslag in de extensie wilt resetten? Dit kan niet ongedaan worden gemaakt.",
"delete_config_profile": "Weet je zeker dat je dit configuratieprofiel wilt verwijderen?",
"delete_custom_mode": "Weet je zeker dat je deze aangepaste modus wilt verwijderen?",
"delete_custom_mode_with_rules": "Weet je zeker dat je deze {scope}-modus wilt verwijderen?\n\nDit verwijdert ook de bijbehorende regelsmap op:\n{rulesFolderPath}",
"delete_message": "Wat wil je verwijderen?",
"just_this_message": "Alleen dit bericht",
"this_and_subsequent": "Dit en alle volgende berichten"
@ -71,6 +71,7 @@
"share_not_enabled": "Taken delen is niet ingeschakeld voor deze organisatie.",
"share_task_not_found": "Taak niet gevonden of toegang geweigerd.",
"mode_import_failed": "Importeren van modus mislukt: {{error}}",
"delete_rules_folder_failed": "Kan regelmap niet verwijderen: {{rulesFolderPath}}. Fout: {{error}}",
"claudeCode": {
"processExited": "Claude Code proces beëindigd met code {{exitCode}}.",
"errorOutput": "Foutuitvoer: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Aangepaste modi resetten mislukt: {{error}}",
"modeNotFound": "Schrijffout: Modus niet gevonden",
"noWorkspaceForProject": "Geen workspace map gevonden voor projectspecifieke modus"
},
"scope": {
"project": "project",
"global": "globaal"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Je moet geauthenticeerd zijn met het Roo Code Cloud-account van je organisatie.",
"verification_failed": "Kan organisatie-authenticatie niet verifiëren."
}
},
"prompts": {
"deleteMode": {
"title": "Aangepaste modus verwijderen",
"description": "Weet je zeker dat je deze {{scope}}-modus wilt verwijderen? Dit zal ook de bijbehorende regelsmap op {{rulesFolderPath}} verwijderen",
"descriptionNoRules": "Weet je zeker dat je deze aangepaste modus wilt verwijderen?",
"cancel": "Annuleren",
"confirm": "Verwijderen"
}
}
}

View file

@ -17,7 +17,7 @@
"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_custom_mode_with_rules": "Czy na pewno chcesz usunąć ten tryb {scope}?\n\nSpowoduje to również usunięcie powiązanego folderu reguł pod adresem:\n{rulesFolderPath}",
"delete_message": "Co chcesz usunąć?",
"just_this_message": "Tylko tę wiadomość",
"this_and_subsequent": "Tę i wszystkie kolejne wiadomości"
@ -71,6 +71,7 @@
"share_not_enabled": "Udostępnianie zadań nie jest włączone dla tej organizacji.",
"share_task_not_found": "Zadanie nie znalezione lub dostęp odmówiony.",
"mode_import_failed": "Import trybu nie powiódł się: {{error}}",
"delete_rules_folder_failed": "Nie udało się usunąć folderu reguł: {{rulesFolderPath}}. Błąd: {{error}}",
"claudeCode": {
"processExited": "Proces Claude Code zakończył się kodem {{exitCode}}.",
"errorOutput": "Wyjście błędu: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Resetowanie trybów niestandardowych nie powiodło się: {{error}}",
"modeNotFound": "Błąd zapisu: Tryb nie został znaleziony",
"noWorkspaceForProject": "Nie znaleziono folderu obszaru roboczego dla trybu specyficznego dla projektu"
},
"scope": {
"project": "projekt",
"global": "globalny"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Musisz być uwierzytelniony kontem Roo Code Cloud swojej organizacji.",
"verification_failed": "Nie można zweryfikować uwierzytelnienia organizacji."
}
},
"prompts": {
"deleteMode": {
"title": "Usuń tryb niestandardowy",
"description": "Czy na pewno chcesz usunąć ten tryb {{scope}}? Spowoduje to również usunięcie powiązanego folderu z regułami w {{rulesFolderPath}}",
"descriptionNoRules": "Czy na pewno chcesz usunąć ten tryb niestandardowy?",
"cancel": "Anuluj",
"confirm": "Usuń"
}
}
}

View file

@ -21,7 +21,7 @@
"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_custom_mode_with_rules": "Tem certeza de que deseja excluir este modo {scope}?\n\nIsso também excluirá a pasta de regras associada em:\n{rulesFolderPath}",
"delete_message": "O que você gostaria de excluir?",
"just_this_message": "Apenas esta mensagem",
"this_and_subsequent": "Esta e todas as mensagens subsequentes"
@ -75,6 +75,7 @@
"share_not_enabled": "O compartilhamento de tarefas não está habilitado para esta organização.",
"share_task_not_found": "Tarefa não encontrada ou acesso negado.",
"mode_import_failed": "Falha ao importar o modo: {{error}}",
"delete_rules_folder_failed": "Falha ao excluir pasta de regras: {{rulesFolderPath}}. Erro: {{error}}",
"claudeCode": {
"processExited": "O processo Claude Code saiu com código {{exitCode}}.",
"errorOutput": "Saída de erro: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Falha ao redefinir modos personalizados: {{error}}",
"modeNotFound": "Erro de escrita: Modo não encontrado",
"noWorkspaceForProject": "Nenhuma pasta de workspace encontrada para modo específico do projeto"
},
"scope": {
"project": "projeto",
"global": "global"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Você deve estar autenticado com a conta Roo Code Cloud da sua organização.",
"verification_failed": "Não foi possível verificar a autenticação da organização."
}
},
"prompts": {
"deleteMode": {
"title": "Excluir Modo Personalizado",
"description": "Tem certeza de que deseja excluir este modo {{scope}}? Isso também excluirá a pasta de regras associada em: {{rulesFolderPath}}",
"descriptionNoRules": "Tem certeza de que deseja excluir este modo personalizado?",
"cancel": "Cancelar",
"confirm": "Excluir"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "Вы уверены, что хотите сбросить все состояние и секретное хранилище в расширении? Это действие нельзя отменить.",
"delete_config_profile": "Вы уверены, что хотите удалить этот профиль конфигурации?",
"delete_custom_mode": "Вы уверены, что хотите удалить этот пользовательский режим?",
"delete_custom_mode_with_rules": "Вы уверены, что хотите удалить этот режим {scope}?\n\nЭто также приведет к удалению соответствующей папки правил по адресу:\n{rulesFolderPath}",
"delete_message": "Что вы хотите удалить?",
"just_this_message": "Только это сообщение",
"this_and_subsequent": "Это и все последующие сообщения"
@ -71,6 +71,7 @@
"share_not_enabled": "Совместный доступ к задачам не включен для этой организации.",
"share_task_not_found": "Задача не найдена или доступ запрещен.",
"mode_import_failed": "Не удалось импортировать режим: {{error}}",
"delete_rules_folder_failed": "Не удалось удалить папку правил: {{rulesFolderPath}}. Ошибка: {{error}}",
"claudeCode": {
"processExited": "Процесс Claude Code завершился с кодом {{exitCode}}.",
"errorOutput": "Вывод ошибки: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Не удалось сбросить пользовательские режимы: {{error}}",
"modeNotFound": "Ошибка записи: Режим не найден",
"noWorkspaceForProject": "Не найдена папка рабочего пространства для режима, специфичного для проекта"
},
"scope": {
"project": "проект",
"global": "глобальный"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Вы должны быть аутентифицированы с учетной записью Roo Code Cloud вашей организации.",
"verification_failed": "Не удается проверить аутентификацию организации."
}
},
"prompts": {
"deleteMode": {
"title": "Удалить пользовательский режим",
"description": "Вы уверены, что хотите удалить этот режим {{scope}}? Это также удалит связанную папку правил по адресу: {{rulesFolderPath}}",
"descriptionNoRules": "Вы уверены, что хотите удалить этот пользовательский режим?",
"cancel": "Отмена",
"confirm": "Удалить"
}
}
}

View file

@ -17,7 +17,7 @@
"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_custom_mode_with_rules": "Bu {scope} modunu silmek istediğinizden emin misiniz?\n\nBu işlem, ilişkili kurallar klasörünü de şu konumdan silecektir:\n{rulesFolderPath}",
"delete_message": "Neyi silmek istersiniz?",
"just_this_message": "Sadece bu mesajı",
"this_and_subsequent": "Bu ve sonraki tüm mesajları"
@ -71,6 +71,7 @@
"share_not_enabled": "Bu kuruluş için görev paylaşımı etkinleştirilmemiş.",
"share_task_not_found": "Görev bulunamadı veya erişim reddedildi.",
"mode_import_failed": "Mod içe aktarılamadı: {{error}}",
"delete_rules_folder_failed": "Kurallar klasörü silinemedi: {{rulesFolderPath}}. Hata: {{error}}",
"claudeCode": {
"processExited": "Claude Code işlemi {{exitCode}} koduyla çıktı.",
"errorOutput": "Hata çıktısı: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Özel modları sıfırlama başarısız: {{error}}",
"modeNotFound": "Yazma hatası: Mod bulunamadı",
"noWorkspaceForProject": "Proje özel modu için çalışma alanı klasörü bulunamadı"
},
"scope": {
"project": "proje",
"global": "küresel"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "Kuruluşunuzun Roo Code Cloud hesabıyla kimlik doğrulaması yapmalısınız.",
"verification_failed": "Kuruluş kimlik doğrulaması doğrulanamıyor."
}
},
"prompts": {
"deleteMode": {
"title": "Özel Modu Sil",
"description": "Bu {{scope}} modunu silmek istediğinizden emin misiniz? Bu, {{rulesFolderPath}} adresindeki ilişkili kurallar klasörünü de silecektir",
"descriptionNoRules": "Bu özel modu silmek istediğinizden emin misiniz?",
"cancel": "İptal",
"confirm": "Sil"
}
}
}

View file

@ -17,7 +17,7 @@
"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_custom_mode_with_rules": "Bạn có chắc chắn muốn xóa chế độ {scope} này không?\n\nThao tác này cũng sẽ xóa thư mục quy tắc liên quan tại:\n{rulesFolderPath}",
"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"
@ -71,6 +71,7 @@
"share_not_enabled": "Chia sẻ nhiệm vụ không được bật cho tổ chức này.",
"share_task_not_found": "Không tìm thấy nhiệm vụ hoặc truy cập bị từ chối.",
"mode_import_failed": "Nhập chế độ thất bại: {{error}}",
"delete_rules_folder_failed": "Không thể xóa thư mục quy tắc: {{rulesFolderPath}}. Lỗi: {{error}}",
"claudeCode": {
"processExited": "Tiến trình Claude Code thoát với mã {{exitCode}}.",
"errorOutput": "Đầu ra lỗi: {{output}}",
@ -144,6 +145,10 @@
"resetFailed": "Đặt lại chế độ tùy chỉnh thất bại: {{error}}",
"modeNotFound": "Lỗi ghi: Không tìm thấy chế độ",
"noWorkspaceForProject": "Không tìm thấy thư mục workspace cho chế độ dành riêng cho dự án"
},
"scope": {
"project": "dự án",
"global": "toàn cầu"
}
},
"mdm": {
@ -152,5 +157,21 @@
"organization_mismatch": "Bạn phải được xác thực bằng tài khoản Roo Code Cloud của tổ chức.",
"verification_failed": "Không thể xác minh xác thực tổ chức."
}
},
"prompts": {
"deleteMode": {
"title": "Xóa chế độ tùy chỉnh",
"description": "Bạn có chắc chắn muốn xóa chế độ {{scope}} này không? Thao tác này cũng θα xóa thư mục quy tắc liên quan tại {{rulesFolderPath}}",
"translations": {
"title": "Xóa chế độ",
"description": "Bạn có chắc chắn muốn xóa chế độ này không?",
"deleteMessage": "Chỉ chế độ này",
"rulesFolderMessage": "Thư mục quy tắc cũng sẽ bị xóa nếu tồn tại.",
"deleteConfirmation": "Chắc chắn xóa chế độ này?"
},
"descriptionNoRules": "Bạn có chắc chắn muốn xóa chế độ tùy chỉnh này không?",
"cancel": "Hủy",
"confirm": "Xóa"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "您确定要重置扩展中的所有状态和密钥存储吗?此操作无法撤消。",
"delete_config_profile": "您确定要删除此配置文件吗?",
"delete_custom_mode": "您确定要删除此自定义模式吗?",
"delete_custom_mode_with_rules": "您确定要删除此 {scope} 模式吗?\n\n这也将删除位于以下位置的关联规则文件夹\n{rulesFolderPath}",
"delete_message": "您想删除什么?",
"just_this_message": "仅此消息",
"this_and_subsequent": "此消息及所有后续消息"
@ -76,6 +76,7 @@
"share_not_enabled": "此组织未启用任务分享功能。",
"share_task_not_found": "未找到任务或访问被拒绝。",
"mode_import_failed": "导入模式失败:{{error}}",
"delete_rules_folder_failed": "删除规则文件夹失败:{{rulesFolderPath}}。错误:{{error}}",
"claudeCode": {
"processExited": "Claude Code 进程退出,退出码:{{exitCode}}。",
"errorOutput": "错误输出:{{output}}",
@ -149,6 +150,10 @@
"resetFailed": "重置自定义模式失败:{{error}}",
"modeNotFound": "写入错误:未找到模式",
"noWorkspaceForProject": "未找到项目特定模式的工作区文件夹"
},
"scope": {
"project": "项目",
"global": "全局"
}
},
"mdm": {
@ -157,5 +162,14 @@
"organization_mismatch": "您必须使用组织的 Roo Code Cloud 账户进行身份验证。",
"verification_failed": "无法验证组织身份验证。"
}
},
"prompts": {
"deleteMode": {
"title": "删除自定义模式",
"description": "您确定要删除此 {{scope}} 模式吗?这也将删除位于 {{rulesFolderPath}} 的关联规则文件夹",
"descriptionNoRules": "您确定要删除此自定义模式吗?",
"cancel": "取消",
"confirm": "删除"
}
}
}

View file

@ -17,7 +17,7 @@
"confirmation": {
"reset_state": "您確定要重設擴充套件中的所有狀態和金鑰儲存嗎?此操作無法復原。",
"delete_config_profile": "您確定要刪除此設定檔案嗎?",
"delete_custom_mode": "您確定要刪除此自訂模式嗎?",
"delete_custom_mode_with_rules": "您確定要刪除此 {scope} 模式嗎?\n\n這也將刪除位於以下位置的關聯規則資料夾\n{rulesFolderPath}",
"delete_message": "您想刪除哪些內容?",
"just_this_message": "僅這則訊息",
"this_and_subsequent": "這則訊息及所有後續訊息"
@ -70,6 +70,7 @@
"share_auth_required": "需要身份驗證。請登入以分享工作。",
"share_not_enabled": "此組織未啟用工作分享功能。",
"share_task_not_found": "未找到工作或存取被拒絕。",
"delete_rules_folder_failed": "刪除規則資料夾失敗: {{rulesFolderPath}}。錯誤: {{error}}",
"claudeCode": {
"processExited": "Claude Code 程序退出,退出碼:{{exitCode}}。",
"errorOutput": "錯誤輸出:{{output}}",
@ -144,6 +145,10 @@
"resetFailed": "重設自訂模式失敗:{{error}}",
"modeNotFound": "寫入錯誤:未找到模式",
"noWorkspaceForProject": "未找到專案特定模式的工作區資料夾"
},
"scope": {
"project": "專案",
"global": "全域"
}
},
"mdm": {
@ -152,5 +157,14 @@
"organization_mismatch": "您必須使用組織的 Roo Code Cloud 帳戶進行身份驗證。",
"verification_failed": "無法驗證組織身份驗證。"
}
},
"prompts": {
"deleteMode": {
"title": "刪除自訂模式",
"description": "您確定要刪除此 {{scope}} 模式嗎?這也將刪除位於 {{rulesFolderPath}} 的關聯規則資料夾",
"descriptionNoRules": "您確定要刪除此自訂模式嗎?",
"cancel": "取消",
"confirm": "刪除"
}
}
}

View file

@ -76,6 +76,7 @@ export interface ExtensionMessage {
| "exportModeResult"
| "importModeResult"
| "checkRulesDirectoryResult"
| "deleteCustomModeCheck"
| "currentCheckpointUpdated"
| "showHumanRelayDialog"
| "humanRelayResponse"
@ -152,6 +153,7 @@ export interface ExtensionMessage {
marketplaceItems?: MarketplaceItem[]
marketplaceInstalledMetadata?: MarketplaceInstalledMetadata
visibility?: ShareVisibility
rulesFolderPath?: string
}
export type ExtensionState = Pick<

View file

@ -222,6 +222,7 @@ export interface WebviewMessage {
config?: Record<string, any> // Add config to the payload
visibility?: ShareVisibility // For share visibility
hasContent?: boolean // For checkRulesDirectoryResult
checkOnly?: boolean // For deleteCustomMode check
}
export const checkoutDiffPayloadSchema = z.object({

View file

@ -0,0 +1,56 @@
import React from "react"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@src/components/ui"
interface DeleteModeDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
modeToDelete: {
slug: string
name: string
source?: string
rulesFolderPath?: string
} | null
onConfirm: () => void
}
export const DeleteModeDialog: React.FC<DeleteModeDialogProps> = ({ open, onOpenChange, modeToDelete, onConfirm }) => {
const { t } = useAppTranslation()
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t("prompts:deleteMode.title")}</AlertDialogTitle>
<AlertDialogDescription>
{modeToDelete && (
<>
{t("prompts:deleteMode.message", { modeName: modeToDelete.name })}
{modeToDelete.rulesFolderPath && (
<div className="mt-2">
{t("prompts:deleteMode.rulesFolder", {
folderPath: modeToDelete.rulesFolderPath,
})}
</div>
)}
</>
)}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t("prompts:deleteMode.cancel")}</AlertDialogCancel>
<AlertDialogAction onClick={onConfirm}>{t("prompts:deleteMode.confirm")}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}

View file

@ -47,6 +47,7 @@ import {
Input,
StandardTooltip,
} from "@src/components/ui"
import { DeleteModeDialog } from "@src/components/modes/DeleteModeDialog"
// Get all available groups that should show in prompts view
const availableGroups = (Object.keys(TOOL_GROUPS) as ToolGroup[]).filter((group) => !TOOL_GROUPS[group].alwaysAvailable)
@ -96,6 +97,13 @@ const ModesView = ({ onDone }: ModesViewProps) => {
const [isImporting, setIsImporting] = useState(false)
const [showImportDialog, setShowImportDialog] = useState(false)
const [hasRulesToExport, setHasRulesToExport] = useState<Record<string, boolean>>({})
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
const [modeToDelete, setModeToDelete] = useState<{
slug: string
name: string
source?: string
rulesFolderPath?: string
} | null>(null)
// State for mode selection popover and search
const [open, setOpen] = useState(false)
@ -408,6 +416,14 @@ const ModesView = ({ onDone }: ModesViewProps) => {
return () => document.removeEventListener("click", handleClickOutside)
}, [showConfigMenu])
// Use a ref to store the current modeToDelete value
const modeToDeleteRef = useRef(modeToDelete)
// Update the ref whenever modeToDelete changes
useEffect(() => {
modeToDeleteRef.current = modeToDelete
}, [modeToDelete])
useEffect(() => {
const handler = (event: MessageEvent) => {
const message = event.data
@ -439,12 +455,23 @@ const ModesView = ({ onDone }: ModesViewProps) => {
...prev,
[message.slug]: message.hasContent,
}))
} else if (message.type === "deleteCustomModeCheck") {
// Handle the check response
// Use the ref to get the current modeToDelete value
const currentModeToDelete = modeToDeleteRef.current
if (message.slug && currentModeToDelete && currentModeToDelete.slug === message.slug) {
setModeToDelete({
...currentModeToDelete,
rulesFolderPath: message.rulesFolderPath,
})
setShowDeleteConfirm(true)
}
}
}
window.addEventListener("message", handler)
return () => window.removeEventListener("message", handler)
}, [])
}, []) // Empty dependency array - only register once
const handleAgentReset = (
modeSlug: string,
@ -699,10 +726,20 @@ const ModesView = ({ onDone }: ModesViewProps) => {
variant="ghost"
size="icon"
onClick={() => {
vscode.postMessage({
type: "deleteCustomMode",
slug: visualMode,
})
const customMode = findModeBySlug(visualMode, customModes)
if (customMode) {
setModeToDelete({
slug: customMode.slug,
name: customMode.name,
source: customMode.source || "global",
})
// First check if rules folder exists
vscode.postMessage({
type: "deleteCustomMode",
slug: customMode.slug,
checkOnly: true,
})
}
}}>
<span className="codicon codicon-trash"></span>
</Button>
@ -1541,6 +1578,23 @@ const ModesView = ({ onDone }: ModesViewProps) => {
</div>
</div>
)}
{/* Delete Mode Confirmation Dialog */}
<DeleteModeDialog
open={showDeleteConfirm}
onOpenChange={setShowDeleteConfirm}
modeToDelete={modeToDelete}
onConfirm={() => {
if (modeToDelete) {
vscode.postMessage({
type: "deleteCustomMode",
slug: modeToDelete.slug,
})
setShowDeleteConfirm(false)
setModeToDelete(null)
}
}}
/>
</Tab>
)
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Eliminar mode"
},
"allFiles": "tots els fitxers"
"allFiles": "tots els fitxers",
"deleteMode": {
"title": "Suprimeix el mode",
"message": "Estàs segur que vols suprimir el mode \"{{modeName}}\"?",
"rulesFolder": "Aquest mode té una carpeta de regles a {{folderPath}} que també se suprimirà.",
"descriptionNoRules": "Esteu segur que voleu suprimir aquest mode personalitzat?",
"confirm": "Suprimeix",
"cancel": "Cancel·la"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Modus löschen"
},
"allFiles": "alle Dateien"
"allFiles": "alle Dateien",
"deleteMode": {
"title": "Modus löschen",
"message": "Möchten Sie den Modus \"{{modeName}}\" wirklich löschen?",
"rulesFolder": "Dieser Modus hat einen Regelordner unter {{folderPath}}, der ebenfalls gelöscht wird.",
"descriptionNoRules": "Möchten Sie diesen benutzerdefinierten Modus wirklich löschen?",
"confirm": "Löschen",
"cancel": "Abbrechen"
}
}

View file

@ -187,5 +187,13 @@
},
"deleteMode": "Delete mode"
},
"allFiles": "all files"
"allFiles": "all files",
"deleteMode": {
"title": "Delete Mode",
"message": "Are you sure you want to delete the mode \"{{modeName}}\"?",
"rulesFolder": "This mode has a rules folder at {{folderPath}} that will also be deleted.",
"descriptionNoRules": "Are you sure you want to delete this custom mode?",
"confirm": "Delete",
"cancel": "Cancel"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Eliminar modo"
},
"allFiles": "todos los archivos"
"allFiles": "todos los archivos",
"deleteMode": {
"title": "Eliminar modo",
"message": "¿Estás seguro de que quieres eliminar el modo \"{{modeName}}\"?",
"rulesFolder": "Este modo tiene una carpeta de reglas en {{folderPath}} que también se eliminará.",
"descriptionNoRules": "¿Estás seguro de que quieres eliminar este modo personalizado?",
"confirm": "Eliminar",
"cancel": "Cancelar"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Supprimer le mode"
},
"allFiles": "tous les fichiers"
"allFiles": "tous les fichiers",
"deleteMode": {
"title": "Supprimer le mode",
"message": "Êtes-vous sûr de vouloir supprimer le mode \"{{modeName}}\" ?",
"rulesFolder": "Ce mode a un dossier de règles à {{folderPath}} qui sera également supprimé.",
"descriptionNoRules": "Êtes-vous sûr de vouloir supprimer ce mode personnalisé ?",
"confirm": "Supprimer",
"cancel": "Annuler"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "मोड हटाएँ"
},
"allFiles": "सभी फाइलें"
"allFiles": "सभी फाइलें",
"deleteMode": {
"title": "मोड हटाएं",
"message": "क्या आप वाकई मोड \"{{modeName}}\" को हटाना चाहते हैं?",
"rulesFolder": "इस मोड में {{folderPath}} पर एक नियम फ़ोल्डर है जिसे भी हटा दिया जाएगा।",
"descriptionNoRules": "क्या आप वाकई इस कस्टम मोड को हटाना चाहते हैं?",
"confirm": "हटाएं",
"cancel": "रद्द करें"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Hapus mode"
},
"allFiles": "semua file"
"allFiles": "semua file",
"deleteMode": {
"title": "Hapus Mode",
"message": "Anda yakin ingin menghapus mode \"{{modeName}}\"?",
"rulesFolder": "Mode ini memiliki folder aturan di {{folderPath}} yang juga akan dihapus.",
"descriptionNoRules": "Apakah Anda yakin ingin menghapus mode kustom ini?",
"confirm": "Hapus",
"cancel": "Batal"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Elimina modalità"
},
"allFiles": "tutti i file"
"allFiles": "tutti i file",
"deleteMode": {
"title": "Elimina modalità",
"message": "Sei sicuro di voler eliminare la modalità \"{{modeName}}\"?",
"rulesFolder": "Questa modalità ha una cartella di regole in {{folderPath}} che verrà eliminata.",
"descriptionNoRules": "Sei sicuro di voler eliminare questa modalità personalizzata?",
"confirm": "Elimina",
"cancel": "Annulla"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "モードを削除"
},
"allFiles": "すべてのファイル"
"allFiles": "すべてのファイル",
"deleteMode": {
"title": "モードを削除",
"message": "モード「{{modeName}}」を削除してもよろしいですか?",
"rulesFolder": "このモードには{{folderPath}}にルールフォルダがあり、それも削除されます。",
"descriptionNoRules": "このカスタムモードを削除してもよろしいですか?",
"confirm": "削除",
"cancel": "キャンセル"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "모드 삭제"
},
"allFiles": "모든 파일"
"allFiles": "모든 파일",
"deleteMode": {
"title": "모드 삭제",
"message": "\"{{modeName}}\" 모드를 삭제하시겠습니까?",
"rulesFolder": "이 모드에는 {{folderPath}}에 규칙 폴더가 있으며 함께 삭제됩니다.",
"descriptionNoRules": "이 사용자 정의 모드를 삭제하시겠습니까?",
"confirm": "삭제",
"cancel": "취소"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Modus verwijderen"
},
"allFiles": "alle bestanden"
"allFiles": "alle bestanden",
"deleteMode": {
"title": "Modus verwijderen",
"message": "Weet je zeker dat je de modus \"{{modeName}}\" wilt verwijderen?",
"rulesFolder": "Deze modus heeft een regelmap op {{folderPath}} die ook wordt verwijderd.",
"descriptionNoRules": "Weet je zeker dat je deze aangepaste modus wilt verwijderen?",
"confirm": "Verwijderen",
"cancel": "Annuleren"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Usuń tryb"
},
"allFiles": "wszystkie pliki"
"allFiles": "wszystkie pliki",
"deleteMode": {
"title": "Usuń tryb",
"message": "Czy na pewno chcesz usunąć tryb \"{{modeName}}\"?",
"rulesFolder": "Ten tryb ma folder z regułami w {{folderPath}}, który również zostanie usunięty.",
"descriptionNoRules": "Czy na pewno chcesz usunąć ten niestandardowy tryb?",
"confirm": "Usuń",
"cancel": "Anuluj"
}
}

View file

@ -188,5 +188,13 @@
},
"deleteMode": "Excluir modo"
},
"allFiles": "todos os arquivos"
"allFiles": "todos os arquivos",
"deleteMode": {
"title": "Excluir Modo",
"message": "Tem certeza de que deseja excluir o modo \"{{modeName}}\"?",
"rulesFolder": "Este modo tem uma pasta de regras em {{folderPath}} que também será excluída.",
"descriptionNoRules": "Tem certeza de que deseja excluir este modo personalizado?",
"confirm": "Excluir",
"cancel": "Cancelar"
}
}

View file

@ -188,5 +188,13 @@
"allFiles": "все файлы",
"advanced": {
"title": "Дополнительно"
},
"deleteMode": {
"title": "Удалить режим",
"message": "Вы уверены, что хотите удалить режим \"{{modeName}}\"?",
"rulesFolder": "У этого режима есть папка правил по адресу {{folderPath}}, которая также будет удалена.",
"descriptionNoRules": "Вы уверены, что хотите удалить этот пользовательский режим?",
"confirm": "Удалить",
"cancel": "Отмена"
}
}

View file

@ -188,5 +188,13 @@
"allFiles": "tüm dosyalar",
"advanced": {
"title": "Gelişmiş"
},
"deleteMode": {
"title": "Modu Sil",
"message": "\"{{modeName}}\" modunu silmek istediğinizden emin misiniz?",
"rulesFolder": "Bu modun {{folderPath}} konumunda bir kurallar klasörü var ve bu da silinecek.",
"descriptionNoRules": "Bu özel modu silmek istediğinizden emin misiniz?",
"confirm": "Sil",
"cancel": "İptal"
}
}

View file

@ -188,5 +188,13 @@
"allFiles": "tất cả các tệp",
"advanced": {
"title": "Nâng cao"
},
"deleteMode": {
"title": "Xóa chế độ",
"message": "Bạn có chắc chắn muốn xóa chế độ \"{{modeName}}\" không?",
"rulesFolder": "Chế độ này có một thư mục quy tắc tại {{folderPath}} cũng sẽ bị xóa.",
"descriptionNoRules": "Bạn có chắc chắn muốn xóa chế độ tùy chỉnh này không?",
"confirm": "Xóa",
"cancel": "Hủy"
}
}

View file

@ -188,5 +188,13 @@
"allFiles": "所有文件",
"advanced": {
"title": "高级"
},
"deleteMode": {
"title": "删除模式",
"message": "您确定要删除\"{{modeName}}\"模式吗?",
"rulesFolder": "此模式在 {{folderPath}} 有一个规则文件夹,该文件夹也将被删除。",
"descriptionNoRules": "您确定要删除此自定义模式吗?",
"confirm": "删除",
"cancel": "取消"
}
}

View file

@ -188,5 +188,13 @@
"allFiles": "所有檔案",
"advanced": {
"title": "進階"
},
"deleteMode": {
"title": "刪除模式",
"message": "您確定要刪除「{{modeName}}」模式嗎?",
"rulesFolder": "此模式在 {{folderPath}} 有一個規則資料夾,該資料夾也將被刪除。",
"descriptionNoRules": "您確定要刪除此自訂模式嗎?",
"confirm": "刪除",
"cancel": "取消"
}
}