From 252702326b7eb7bba984f4965df40bc2cc1c1b33 Mon Sep 17 00:00:00 2001 From: Hannes Rudolph Date: Mon, 8 Dec 2025 10:08:08 -0700 Subject: [PATCH 1/3] feat: add slash commands support to marketplace - Add 'command' type to marketplace item schema with content and argumentHint - Implement command detection in MarketplaceManager for project and global directories - Add fetchCommands() to RemoteConfigLoader for API integration - Add installCommand() and removeCommand() to SimpleInstaller - Add 'Slash Commands' tab to marketplace UI with 3-tab navigation - Update install modal and item card components for command type - Add translations for all 18 locales - Include comprehensive test coverage for new functionality --- packages/types/src/marketplace.ts | 13 ++- .../marketplace/MarketplaceManager.ts | 28 +++++ .../marketplace/RemoteConfigLoader.ts | 38 ++++++- src/services/marketplace/SimpleInstaller.ts | 49 +++++++++ .../__tests__/RemoteConfigLoader.spec.ts | 92 ++++++++++++++-- .../__tests__/SimpleInstaller.spec.ts | 103 ++++++++++++++++++ .../marketplace/MarketplaceListView.tsx | 6 +- .../marketplace/MarketplaceView.tsx | 24 +++- .../MarketplaceViewStateManager.ts | 2 +- .../MarketplaceViewStateManager.spec.ts | 41 +++++++ .../components/MarketplaceInstallModal.tsx | 20 ++-- .../components/MarketplaceItemCard.tsx | 7 +- .../src/i18n/locales/ca/marketplace.json | 15 ++- .../src/i18n/locales/de/marketplace.json | 19 +++- .../src/i18n/locales/en/marketplace.json | 15 ++- .../src/i18n/locales/es/marketplace.json | 15 ++- .../src/i18n/locales/fr/marketplace.json | 15 ++- .../src/i18n/locales/hi/marketplace.json | 15 ++- .../src/i18n/locales/id/marketplace.json | 15 ++- .../src/i18n/locales/it/marketplace.json | 15 ++- .../src/i18n/locales/ja/marketplace.json | 15 ++- .../src/i18n/locales/ko/marketplace.json | 15 ++- .../src/i18n/locales/nl/marketplace.json | 15 ++- .../src/i18n/locales/pl/marketplace.json | 19 +++- .../src/i18n/locales/pt-BR/marketplace.json | 15 ++- .../src/i18n/locales/ru/marketplace.json | 15 ++- .../src/i18n/locales/tr/marketplace.json | 15 ++- .../src/i18n/locales/vi/marketplace.json | 15 ++- .../src/i18n/locales/zh-CN/marketplace.json | 15 ++- .../src/i18n/locales/zh-TW/marketplace.json | 15 ++- 30 files changed, 612 insertions(+), 89 deletions(-) diff --git a/packages/types/src/marketplace.ts b/packages/types/src/marketplace.ts index f2821e1b742..22dcfeba7fe 100644 --- a/packages/types/src/marketplace.ts +++ b/packages/types/src/marketplace.ts @@ -27,7 +27,7 @@ export type McpInstallationMethod = z.infer /** * Component type validation */ -export const marketplaceItemTypeSchema = z.enum(["mode", "mcp"] as const) +export const marketplaceItemTypeSchema = z.enum(["mode", "mcp", "command"] as const) export type MarketplaceItemType = z.infer @@ -61,6 +61,13 @@ export const mcpMarketplaceItemSchema = baseMarketplaceItemSchema.extend({ export type McpMarketplaceItem = z.infer +export const commandMarketplaceItemSchema = baseMarketplaceItemSchema.extend({ + content: z.string().min(1), // Markdown content for slash command + argumentHint: z.string().optional(), +}) + +export type CommandMarketplaceItem = z.infer + /** * Unified marketplace item schema using discriminated union */ @@ -73,6 +80,10 @@ export const marketplaceItemSchema = z.discriminatedUnion("type", [ mcpMarketplaceItemSchema.extend({ type: z.literal("mcp"), }), + // Command marketplace item + commandMarketplaceItemSchema.extend({ + type: z.literal("command"), + }), ]) export type MarketplaceItem = z.infer diff --git a/src/services/marketplace/MarketplaceManager.ts b/src/services/marketplace/MarketplaceManager.ts index dfde5600b9a..231793f61fa 100644 --- a/src/services/marketplace/MarketplaceManager.ts +++ b/src/services/marketplace/MarketplaceManager.ts @@ -284,6 +284,20 @@ export class MarketplaceManager { } catch (error) { // File doesn't exist or can't be read, skip } + + // Check commands in .roo/commands + const projectCommandsDir = path.join(workspaceFolder.uri.fsPath, ".roo", "commands") + try { + const entries = await fs.readdir(projectCommandsDir, { withFileTypes: true }) + for (const entry of entries) { + if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) { + const commandName = entry.name.slice(0, -3) + metadata[commandName] = { type: "command" } + } + } + } catch (error) { + // Directory doesn't exist or can't be read, skip + } } catch (error) { console.error("Error checking project installations:", error) } @@ -329,6 +343,20 @@ export class MarketplaceManager { } catch (error) { // File doesn't exist or can't be read, skip } + + // Check global commands + const globalCommandsDir = path.join(globalSettingsPath, "commands") + try { + const entries = await fs.readdir(globalCommandsDir, { withFileTypes: true }) + for (const entry of entries) { + if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) { + const commandName = entry.name.slice(0, -3) + metadata[commandName] = { type: "command" } + } + } + } catch (error) { + // Directory doesn't exist or can't be read, skip + } } catch (error) { console.error("Error checking global installations:", error) } diff --git a/src/services/marketplace/RemoteConfigLoader.ts b/src/services/marketplace/RemoteConfigLoader.ts index b5851ae854d..a44d7b0b783 100644 --- a/src/services/marketplace/RemoteConfigLoader.ts +++ b/src/services/marketplace/RemoteConfigLoader.ts @@ -3,10 +3,11 @@ import * as yaml from "yaml" import { z } from "zod" import { - type MarketplaceItem, - type MarketplaceItemType, + commandMarketplaceItemSchema, modeMarketplaceItemSchema, mcpMarketplaceItemSchema, + type MarketplaceItem, + type MarketplaceItemType, } from "@roo-code/types" import { getRooCodeApiUrl } from "@roo-code/cloud" @@ -18,6 +19,10 @@ const mcpMarketplaceResponse = z.object({ items: z.array(mcpMarketplaceItemSchema), }) +const commandMarketplaceResponse = z.object({ + items: z.array(commandMarketplaceItemSchema), +}) + export class RemoteConfigLoader { private apiBaseUrl: string private cache: Map = new Map() @@ -32,10 +37,11 @@ export class RemoteConfigLoader { const modesPromise = this.fetchModes() const mcpsPromise = hideMarketplaceMcps ? Promise.resolve([]) : this.fetchMcps() + const commandsPromise = this.fetchCommands() - const [modes, mcps] = await Promise.all([modesPromise, mcpsPromise]) + const [modes, mcps, commands] = await Promise.all([modesPromise, mcpsPromise, commandsPromise]) - items.push(...modes, ...mcps) + items.push(...modes, ...mcps, ...commands) return items } @@ -83,6 +89,30 @@ export class RemoteConfigLoader { return items } + private async fetchCommands(): Promise { + const cacheKey = "commands" + const cached = this.getFromCache(cacheKey) + + if (cached) { + return cached + } + + const data = await this.fetchWithRetry(`${this.apiBaseUrl}/api/marketplace/commands`) + + // The commands endpoint returns Markdown list (yaml frontmatter + markdown body per item) + // The test server sample is plain Markdown with YAML frontmatter; parse as plain text list. + const yamlData = yaml.parse(data) + const validated = commandMarketplaceResponse.parse(yamlData) + + const items: MarketplaceItem[] = validated.items.map((item) => ({ + type: "command" as const, + ...item, + })) + + this.setCache(cacheKey, items) + return items + } + private async fetchWithRetry(url: string, maxRetries = 3): Promise { let lastError: Error diff --git a/src/services/marketplace/SimpleInstaller.ts b/src/services/marketplace/SimpleInstaller.ts index be002e2f1d5..9d4467fda7c 100644 --- a/src/services/marketplace/SimpleInstaller.ts +++ b/src/services/marketplace/SimpleInstaller.ts @@ -6,6 +6,7 @@ import type { MarketplaceItem, MarketplaceItemType, InstallMarketplaceItemOption import { GlobalFileNames } from "../../shared/globalFileNames" import { ensureSettingsDirectoryExists } from "../../utils/globalContext" import type { CustomModesManager } from "../../core/config/CustomModesManager" +import { getGlobalRooDirectory, getProjectRooDirectoryForCwd } from "../roo-config" export interface InstallOptions extends InstallMarketplaceItemOptions { target: "project" | "global" @@ -26,11 +27,30 @@ export class SimpleInstaller { return await this.installMode(item, target) case "mcp": return await this.installMcp(item, target, options) + case "command": + return await this.installCommand(item, target) default: throw new Error(`Unsupported item type: ${(item as any).type}`) } } + private async installCommand( + item: MarketplaceItem, + target: "project" | "global", + ): Promise<{ filePath: string; line?: number }> { + if (!item.content || Array.isArray(item.content)) { + throw new Error("Command item missing content") + } + + const dirPath = await this.getCommandDirPath(target) + await fs.mkdir(dirPath, { recursive: true }) + + const filePath = path.join(dirPath, `${item.id}.md`) + await fs.writeFile(filePath, item.content, "utf-8") + + return { filePath } + } + private async installMode( item: MarketplaceItem, target: "project" | "global", @@ -288,11 +308,28 @@ export class SimpleInstaller { case "mcp": await this.removeMcp(item, target) break + case "command": + await this.removeCommand(item, target) + break default: throw new Error(`Unsupported item type: ${(item as any).type}`) } } + private async removeCommand(item: MarketplaceItem, target: "project" | "global"): Promise { + const dirPath = await this.getCommandDirPath(target) + const filePath = path.join(dirPath, `${item.id}.md`) + + try { + await fs.unlink(filePath) + } catch (error: any) { + if (error.code === "ENOENT") { + return + } + throw error + } + } + private async removeMode(item: MarketplaceItem, target: "project" | "global"): Promise { if (!this.customModesManager) { throw new Error("CustomModesManager is not available") @@ -381,4 +418,16 @@ export class SimpleInstaller { return path.join(globalSettingsPath, GlobalFileNames.mcpSettings) } } + + private async getCommandDirPath(target: "project" | "global"): Promise { + if (target === "project") { + const workspaceFolder = vscode.workspace.workspaceFolders?.[0] + if (!workspaceFolder) { + throw new Error("No workspace folder found") + } + return path.join(getProjectRooDirectoryForCwd(workspaceFolder.uri.fsPath), "commands") + } + + return path.join(getGlobalRooDirectory(), "commands") + } } diff --git a/src/services/marketplace/__tests__/RemoteConfigLoader.spec.ts b/src/services/marketplace/__tests__/RemoteConfigLoader.spec.ts index 61740ab5fbd..32a046455f8 100644 --- a/src/services/marketplace/__tests__/RemoteConfigLoader.spec.ts +++ b/src/services/marketplace/__tests__/RemoteConfigLoader.spec.ts @@ -24,7 +24,7 @@ describe("RemoteConfigLoader", () => { }) describe("loadAllItems", () => { - it("should fetch and combine modes and MCPs from API", async () => { + it("should fetch and combine modes, MCPs, and commands from API", async () => { const mockModesYaml = `items: - id: "test-mode" name: "Test Mode" @@ -38,6 +38,13 @@ describe("RemoteConfigLoader", () => { url: "https://github.com/test/test-mcp" content: '{"command": "test"}'` + const mockCommandsYaml = `items: + - id: "explain" + name: "Explain" + description: "Get a detailed explanation" + author: "@roo" + content: "# Explain\\n\\nExplain the following: {args}"` + mockedAxios.get.mockImplementation((url: string) => { if (url.includes("/modes")) { return Promise.resolve({ data: mockModesYaml }) @@ -45,12 +52,15 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: mockMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: mockCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) const items = await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) + expect(mockedAxios.get).toHaveBeenCalledTimes(3) expect(mockedAxios.get).toHaveBeenCalledWith( "https://test.api.com/api/marketplace/modes", expect.objectContaining({ @@ -71,8 +81,18 @@ describe("RemoteConfigLoader", () => { }, }), ) + expect(mockedAxios.get).toHaveBeenCalledWith( + "https://test.api.com/api/marketplace/commands", + expect.objectContaining({ + timeout: 10000, + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }), + ) - expect(items).toHaveLength(2) + expect(items).toHaveLength(3) expect(items[0]).toEqual({ type: "mode", id: "test-mode", @@ -88,6 +108,14 @@ describe("RemoteConfigLoader", () => { url: "https://github.com/test/test-mcp", content: '{"command": "test"}', }) + expect(items[2]).toEqual({ + type: "command", + id: "explain", + name: "Explain", + description: "Get a detailed explanation", + author: "@roo", + content: "# Explain\n\nExplain the following: {args}", + }) }) it("should use cache on subsequent calls", async () => { @@ -104,6 +132,8 @@ describe("RemoteConfigLoader", () => { url: "https://github.com/test/test-mcp" content: "test content"` + const mockCommandsYaml = `items: []` + mockedAxios.get.mockImplementation((url: string) => { if (url.includes("/modes")) { return Promise.resolve({ data: mockModesYaml }) @@ -111,16 +141,19 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: mockMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: mockCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) // First call - should hit API const items1 = await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) + expect(mockedAxios.get).toHaveBeenCalledTimes(3) // Second call - should use cache const items2 = await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) // Still 2, not 4 + expect(mockedAxios.get).toHaveBeenCalledTimes(3) // Still 3, not 6 expect(items1).toEqual(items2) }) @@ -133,6 +166,7 @@ describe("RemoteConfigLoader", () => { content: "test content"` const mockMcpsYaml = `items: []` + const mockCommandsYaml = `items: []` // Mock modes endpoint to fail twice then succeed let modesCallCount = 0 @@ -147,6 +181,9 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: mockMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: mockCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) @@ -185,6 +222,8 @@ describe("RemoteConfigLoader", () => { url: "https://github.com/test/test-mcp" content: "test content"` + const validCommandsYaml = `items: []` + mockedAxios.get.mockImplementation((url: string) => { if (url.includes("/modes")) { return Promise.resolve({ data: invalidModesYaml }) @@ -192,6 +231,9 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: validMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: validCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) @@ -215,6 +257,13 @@ describe("RemoteConfigLoader", () => { url: "https://github.com/test/test-mcp" content: "test content"` + const mockCommandsYaml = `items: + - id: "target-command" + name: "Target Command" + description: "The command we want" + author: "@roo" + content: "# Command content"` + mockedAxios.get.mockImplementation((url: string) => { if (url.includes("/modes")) { return Promise.resolve({ data: mockModesYaml }) @@ -222,11 +271,15 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: mockMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: mockCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) const modeItem = await loader.getItem("target-mode", "mode" as MarketplaceItemType) const mcpItem = await loader.getItem("target-mcp", "mcp" as MarketplaceItemType) + const commandItem = await loader.getItem("target-command", "command" as MarketplaceItemType) const notFound = await loader.getItem("nonexistent", "mode" as MarketplaceItemType) expect(modeItem).toEqual({ @@ -246,6 +299,15 @@ describe("RemoteConfigLoader", () => { content: "test content", }) + expect(commandItem).toEqual({ + type: "command", + id: "target-command", + name: "Target Command", + description: "The command we want", + author: "@roo", + content: "# Command content", + }) + expect(notFound).toBeNull() }) }) @@ -259,6 +321,7 @@ describe("RemoteConfigLoader", () => { content: "test content"` const mockMcpsYaml = `items: []` + const mockCommandsYaml = `items: []` mockedAxios.get.mockImplementation((url: string) => { if (url.includes("/modes")) { @@ -267,23 +330,26 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: mockMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: mockCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) // First call await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) + expect(mockedAxios.get).toHaveBeenCalledTimes(3) // Second call - should use cache await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) + expect(mockedAxios.get).toHaveBeenCalledTimes(3) // Clear cache loader.clearCache() // Third call - should hit API again await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(4) + expect(mockedAxios.get).toHaveBeenCalledTimes(6) }) }) @@ -296,6 +362,7 @@ describe("RemoteConfigLoader", () => { content: "test content"` const mockMcpsYaml = `items: []` + const mockCommandsYaml = `items: []` mockedAxios.get.mockImplementation((url: string) => { if (url.includes("/modes")) { @@ -304,6 +371,9 @@ describe("RemoteConfigLoader", () => { if (url.includes("/mcps")) { return Promise.resolve({ data: mockMcpsYaml }) } + if (url.includes("/commands")) { + return Promise.resolve({ data: mockCommandsYaml }) + } return Promise.reject(new Error("Unknown URL")) }) @@ -315,18 +385,18 @@ describe("RemoteConfigLoader", () => { // First call await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) + expect(mockedAxios.get).toHaveBeenCalledTimes(3) // Second call immediately - should use cache await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(2) + expect(mockedAxios.get).toHaveBeenCalledTimes(3) // Advance time by 6 minutes (360,000 ms) currentTime += 6 * 60 * 1000 // Third call - cache should be expired await loader.loadAllItems() - expect(mockedAxios.get).toHaveBeenCalledTimes(4) + expect(mockedAxios.get).toHaveBeenCalledTimes(6) // Restore original Date.now Date.now = originalDateNow diff --git a/src/services/marketplace/__tests__/SimpleInstaller.spec.ts b/src/services/marketplace/__tests__/SimpleInstaller.spec.ts index 94684056d47..08a0c234432 100644 --- a/src/services/marketplace/__tests__/SimpleInstaller.spec.ts +++ b/src/services/marketplace/__tests__/SimpleInstaller.spec.ts @@ -15,6 +15,7 @@ vi.mock("fs/promises", () => ({ writeFile: vi.fn(), mkdir: vi.fn(), rm: vi.fn(), + unlink: vi.fn(), })) vi.mock("os") vi.mock("vscode", () => ({ @@ -346,4 +347,106 @@ describe("SimpleInstaller", () => { ) }) }) + + describe("installCommand", () => { + const mockCommandItem: MarketplaceItem = { + id: "explain", + name: "Explain", + description: "Get a detailed explanation of code, concepts, or errors", + type: "command", + content: `--- +description: "Get a detailed explanation of code, concepts, or errors" +argument-hint: "" +--- + +# Explain Request + +Please provide a comprehensive explanation of the following: + +**Input:** {args}`, + } + + it("should install command to project .roo/commands/ directory", async () => { + mockFs.writeFile.mockResolvedValueOnce(undefined as any) + + const result = await installer.installItem(mockCommandItem, { target: "project" }) + + expect(result.filePath).toBe(path.join("/test/workspace", ".roo", "commands", "explain.md")) + expect(mockFs.mkdir).toHaveBeenCalledWith(expect.stringContaining(path.join(".roo", "commands")), { + recursive: true, + }) + expect(mockFs.writeFile).toHaveBeenCalledWith(result.filePath, mockCommandItem.content, "utf-8") + }) + + it("should install command to global commands directory", async () => { + mockFs.writeFile.mockResolvedValueOnce(undefined as any) + + const result = await installer.installItem(mockCommandItem, { target: "global" }) + + expect(result.filePath).toContain("commands") + expect(result.filePath).toContain("explain.md") + expect(mockFs.mkdir).toHaveBeenCalledWith(expect.any(String), { recursive: true }) + expect(mockFs.writeFile).toHaveBeenCalledWith(result.filePath, mockCommandItem.content, "utf-8") + }) + + it("should throw error for missing content", async () => { + const noContentCommand: MarketplaceItem = { + ...mockCommandItem, + content: undefined as any, + } + + await expect(installer.installItem(noContentCommand, { target: "project" })).rejects.toThrow( + "Command item missing content", + ) + }) + + it("should throw error for array content in command", async () => { + const arrayContentCommand: MarketplaceItem = { + ...mockCommandItem, + content: ["content1", "content2"] as any, + } + + await expect(installer.installItem(arrayContentCommand, { target: "project" })).rejects.toThrow( + "Command item missing content", + ) + }) + }) + + describe("removeCommand", () => { + const mockCommandItem: MarketplaceItem = { + id: "explain", + name: "Explain", + description: "Get a detailed explanation of code, concepts, or errors", + type: "command", + content: "# Explain\n\nContent here", + } + + it("should remove command file from project directory", async () => { + mockFs.unlink.mockResolvedValueOnce(undefined as any) + + await installer.removeItem(mockCommandItem, { target: "project" }) + + expect(mockFs.unlink).toHaveBeenCalledWith( + expect.stringContaining(path.join(".roo", "commands", "explain.md")), + ) + }) + + it("should not throw error if command file does not exist", async () => { + const notFoundError = new Error("File not found") as any + notFoundError.code = "ENOENT" + mockFs.unlink.mockRejectedValueOnce(notFoundError) + + await expect(installer.removeItem(mockCommandItem, { target: "project" })).resolves.not.toThrow() + }) + + it("should throw error for other file system errors", async () => { + const permissionError = new Error("Permission denied") as any + permissionError.code = "EPERM" + mockFs.unlink.mockRejectedValueOnce(permissionError) + + await expect(installer.removeItem(mockCommandItem, { target: "project" })).rejects.toThrow( + "Permission denied", + ) + }) + }) }) diff --git a/webview-ui/src/components/marketplace/MarketplaceListView.tsx b/webview-ui/src/components/marketplace/MarketplaceListView.tsx index c3c497ccfed..760445d17b0 100644 --- a/webview-ui/src/components/marketplace/MarketplaceListView.tsx +++ b/webview-ui/src/components/marketplace/MarketplaceListView.tsx @@ -16,7 +16,7 @@ export interface MarketplaceListViewProps { stateManager: MarketplaceViewStateManager allTags: string[] filteredTags: string[] - filterByType?: "mcp" | "mode" + filterByType?: "mcp" | "mode" | "command" } export function MarketplaceListView({ stateManager, allTags, filteredTags, filterByType }: MarketplaceListViewProps) { @@ -48,7 +48,9 @@ export function MarketplaceListView({ stateManager, allTags, filteredTags, filte ? t("marketplace:filters.search.placeholderMcp") : filterByType === "mode" ? t("marketplace:filters.search.placeholderMode") - : t("marketplace:filters.search.placeholder") + : filterByType === "command" + ? t("marketplace:filters.search.placeholderCommand") + : t("marketplace:filters.search.placeholder") } value={state.filters.search} onChange={(e) => diff --git a/webview-ui/src/components/marketplace/MarketplaceView.tsx b/webview-ui/src/components/marketplace/MarketplaceView.tsx index 0d66be48afd..4acc0115e5b 100644 --- a/webview-ui/src/components/marketplace/MarketplaceView.tsx +++ b/webview-ui/src/components/marketplace/MarketplaceView.tsx @@ -13,7 +13,7 @@ import { ExtensionStateContext } from "@/context/ExtensionStateContext" interface MarketplaceViewProps { onDone?: () => void stateManager: MarketplaceViewStateManager - targetTab?: "mcp" | "mode" + targetTab?: "mcp" | "mode" | "command" } export function MarketplaceView({ stateManager, onDone, targetTab }: MarketplaceViewProps) { const { t } = useAppTranslation() @@ -43,7 +43,7 @@ export function MarketplaceView({ stateManager, onDone, targetTab }: Marketplace }, [state.allItems, hasReceivedInitialState]) useEffect(() => { - if (targetTab && (targetTab === "mcp" || targetTab === "mode")) { + if (targetTab && (targetTab === "mcp" || targetTab === "mode" || targetTab === "command")) { manager.transition({ type: "SET_ACTIVE_TAB", payload: { tab: targetTab } }) } }, [targetTab, manager]) @@ -117,10 +117,11 @@ export function MarketplaceView({ stateManager, onDone, targetTab }: Marketplace
@@ -130,6 +131,13 @@ export function MarketplaceView({ stateManager, onDone, targetTab }: Marketplace onClick={() => manager.transition({ type: "SET_ACTIVE_TAB", payload: { tab: "mcp" } })}> MCP +
@@ -365,11 +369,13 @@ export const MarketplaceInstallModal: React.FC = ( - + {item.type !== "command" && ( + + )} ) : ( <> diff --git a/webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx b/webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx index e4bbdbcfde6..822191c4e20 100644 --- a/webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx +++ b/webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx @@ -68,6 +68,7 @@ export const MarketplaceItemCard: React.FC = ({ item, const labels: Partial> = { mode: t("marketplace:filters.type.mode"), mcp: t("marketplace:filters.type.mcpServer"), + command: t("marketplace:filters.type.slashCommand"), } return labels[item.type] ?? "N/A" }, [item.type, t]) @@ -210,7 +211,9 @@ export const MarketplaceItemCard: React.FC = ({ item, {item.type === "mode" ? t("marketplace:removeConfirm.mode.title") - : t("marketplace:removeConfirm.mcp.title")} + : item.type === "command" + ? t("marketplace:removeConfirm.command.title") + : t("marketplace:removeConfirm.mcp.title")} {item.type === "mode" ? ( @@ -220,6 +223,8 @@ export const MarketplaceItemCard: React.FC = ({ item, {t("marketplace:removeConfirm.mode.rulesWarning")} + ) : item.type === "command" ? ( + t("marketplace:removeConfirm.command.message", { commandName: item.name }) ) : ( t("marketplace:removeConfirm.mcp.message", { mcpName: item.name }) )} diff --git a/webview-ui/src/i18n/locales/ca/marketplace.json b/webview-ui/src/i18n/locales/ca/marketplace.json index cd4612ae36e..17cbe0a19fb 100644 --- a/webview-ui/src/i18n/locales/ca/marketplace.json +++ b/webview-ui/src/i18n/locales/ca/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Instal·lat", "settings": "Configuració", - "browse": "Navegar" + "browse": "Navegar", + "slashCommands": "Comandes Slash" }, "done": "Fet", "refresh": "Actualitzar", @@ -11,7 +12,8 @@ "search": { "placeholder": "Cercar elements del marketplace...", "placeholderMcp": "Cercar MCPs...", - "placeholderMode": "Cercar modes..." + "placeholderMode": "Cercar modes...", + "placeholderCommand": "Cercar comandes Slash..." }, "installed": { "label": "Filtra per estat", @@ -23,7 +25,8 @@ "label": "Filtrar per tipus:", "all": "Tots els tipus", "mode": "Mode", - "mcpServer": "Servidor MCP" + "mcpServer": "Servidor MCP", + "slashCommand": "Comanda Slash" }, "sort": { "label": "Ordenar per:", @@ -91,6 +94,7 @@ "title": "Instal·lar {{name}}", "titleMode": "Instal·lar mode {{name}}", "titleMcp": "Instal·lar MCP {{name}}", + "titleCommand": "Instal·lar la comanda Slash {{name}}", "scope": "Àmbit d'instal·lació", "project": "Projecte (espai de treball actual)", "global": "Global (tots els espais de treball)", @@ -103,6 +107,7 @@ "installed": "Instal·lat amb èxit!", "whatNextMcp": "Ara pots configurar i utilitzar aquest servidor MCP. Feu clic a la icona MCP de la barra lateral per canviar de pestanya.", "whatNextMode": "Ara pots utilitzar aquest mode. Feu clic a la icona Modes de la barra lateral per canviar de pestanya.", + "whatNextCommand": "Ara pots utilitzar aquesta comanda slash escrivint /{{name}} al xat.", "done": "Fet", "goToMcp": "Anar a la pestanya MCP", "goToModes": "Anar a la configuració de Modes", @@ -149,6 +154,10 @@ "title": "Eliminar el servidor MCP", "message": "Estàs segur que vols eliminar el servidor MCP \"{{mcpName}}\"?" }, + "command": { + "title": "Eliminar comanda Slash", + "message": "Estàs segur que vols eliminar la comanda slash \"{{commandName}}\"?" + }, "cancel": "Cancel·lar", "confirm": "Eliminar" }, diff --git a/webview-ui/src/i18n/locales/de/marketplace.json b/webview-ui/src/i18n/locales/de/marketplace.json index 545e86bc910..06826d3d1ca 100644 --- a/webview-ui/src/i18n/locales/de/marketplace.json +++ b/webview-ui/src/i18n/locales/de/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Installiert", "settings": "Einstellungen", - "browse": "Durchsuchen" + "browse": "Durchsuchen", + "slashCommands": "Slash Commands" }, "done": "Fertig", "refresh": "Aktualisieren", @@ -11,7 +12,8 @@ "search": { "placeholder": "Marketplace-Elemente durchsuchen...", "placeholderMcp": "MCPs durchsuchen...", - "placeholderMode": "Modi durchsuchen..." + "placeholderMode": "Modi durchsuchen...", + "placeholderCommand": "Slash Commands durchsuchen..." }, "installed": { "label": "Nach Status filtern", @@ -23,7 +25,8 @@ "label": "Nach Typ filtern:", "all": "Alle Typen", "mode": "Modus", - "mcpServer": "MCP-Server" + "mcpServer": "MCP-Server", + "slashCommand": "Slash Command" }, "sort": { "label": "Sortieren nach:", @@ -91,6 +94,7 @@ "title": "{{name}} installieren", "titleMode": "{{name}} Modus installieren", "titleMcp": "{{name}} MCP installieren", + "titleCommand": "{{name}} Slash Command installieren", "scope": "Installationsbereich", "project": "Projekt (aktueller Arbeitsbereich)", "global": "Global (alle Arbeitsbereiche)", @@ -103,6 +107,7 @@ "installed": "Erfolgreich installiert!", "whatNextMcp": "Du kannst diesen MCP-Server jetzt konfigurieren und verwenden. Klicke auf das MCP-Symbol in der Seitenleiste, um die Tabs zu wechseln.", "whatNextMode": "Du kannst diesen Modus jetzt verwenden. Klicke auf das Modi-Symbol in der Seitenleiste, um die Tabs zu wechseln.", + "whatNextCommand": "Du kannst diesen Slash Command jetzt verwenden, indem du /{{name}} im Chat eingibst.", "done": "Fertig", "goToMcp": "Zum MCP-Tab gehen", "goToModes": "Zu den Modi-Einstellungen gehen", @@ -142,12 +147,16 @@ "removeConfirm": { "mode": { "title": "Modus entfernen", - "message": "Bist du sicher, dass du den Modus „{{modeName}}“ entfernen möchtest?", + "message": "Bist du sicher, dass du den Modus \"{{modeName}}\" entfernen möchtest?", "rulesWarning": "Dadurch werden auch alle zugehörigen Regeldateien für diesen Modus entfernt." }, "mcp": { "title": "MCP-Server entfernen", - "message": "Bist du sicher, dass du den MCP-Server „{{mcpName}}“ entfernen möchtest?" + "message": "Bist du sicher, dass du den MCP-Server \"{{mcpName}}\" entfernen möchtest?" + }, + "command": { + "title": "Slash Command entfernen", + "message": "Bist du sicher, dass du den Slash Command \"{{commandName}}\" entfernen möchtest?" }, "cancel": "Abbrechen", "confirm": "Entfernen" diff --git a/webview-ui/src/i18n/locales/en/marketplace.json b/webview-ui/src/i18n/locales/en/marketplace.json index dae9dd26116..b3f1ac3b27b 100644 --- a/webview-ui/src/i18n/locales/en/marketplace.json +++ b/webview-ui/src/i18n/locales/en/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Installed", "settings": "Settings", - "browse": "Browse" + "browse": "Browse", + "slashCommands": "Slash Commands" }, "done": "Done", "refresh": "Refresh", @@ -11,7 +12,8 @@ "search": { "placeholder": "Search marketplace items...", "placeholderMcp": "Search MCPs...", - "placeholderMode": "Search Modes..." + "placeholderMode": "Search Modes...", + "placeholderCommand": "Search Slash Commands..." }, "installed": { "label": "Filter by status", @@ -23,7 +25,8 @@ "label": "Filter by type:", "all": "All types", "mode": "Mode", - "mcpServer": "MCP Server" + "mcpServer": "MCP Server", + "slashCommand": "Slash Command" }, "sort": { "label": "Sort by:", @@ -89,6 +92,7 @@ "title": "Install {{name}}", "titleMode": "Install {{name}} Mode", "titleMcp": "Install {{name}} MCP", + "titleCommand": "Install {{name}} Slash Command", "scope": "Installation Scope", "project": "Project (current workspace)", "global": "Global (all workspaces)", @@ -102,6 +106,7 @@ "installed": "Successfully installed!", "whatNextMcp": "You can now configure and use this MCP server. Click the MCP icon in the sidebar to switch tabs.", "whatNextMode": "You can now use this mode. Click the Modes icon in the sidebar to switch tabs.", + "whatNextCommand": "You can now use this slash command by typing /{{name}} in the chat.", "done": "Done", "goToMcp": "Go to MCP Tab", "goToModes": "Go to Modes Settings", @@ -147,6 +152,10 @@ "title": "Remove MCP Server", "message": "Are you sure you want to remove the MCP server \"{{mcpName}}\"?" }, + "command": { + "title": "Remove Slash Command", + "message": "Are you sure you want to remove the slash command \"{{commandName}}\"?" + }, "cancel": "Cancel", "confirm": "Remove" }, diff --git a/webview-ui/src/i18n/locales/es/marketplace.json b/webview-ui/src/i18n/locales/es/marketplace.json index 2d4b257c93f..af5a0cdd13f 100644 --- a/webview-ui/src/i18n/locales/es/marketplace.json +++ b/webview-ui/src/i18n/locales/es/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Instalado", "settings": "Configuración", - "browse": "Explorar" + "browse": "Explorar", + "slashCommands": "Comandos Slash" }, "done": "Hecho", "refresh": "Actualizar", @@ -11,7 +12,8 @@ "search": { "placeholder": "Buscar elementos del marketplace...", "placeholderMcp": "Buscar MCPs...", - "placeholderMode": "Buscar modos..." + "placeholderMode": "Buscar modos...", + "placeholderCommand": "Buscar comandos Slash..." }, "installed": { "label": "Filtrar por estado", @@ -23,7 +25,8 @@ "label": "Filtrar por tipo:", "all": "Todos los tipos", "mode": "Modo", - "mcpServer": "Servidor MCP" + "mcpServer": "Servidor MCP", + "slashCommand": "Comando Slash" }, "sort": { "label": "Ordenar por:", @@ -91,6 +94,7 @@ "title": "Instalar {{name}}", "titleMode": "Instalar modo {{name}}", "titleMcp": "Instalar MCP {{name}}", + "titleCommand": "Instalar comando Slash {{name}}", "scope": "Ámbito de instalación", "project": "Proyecto (espacio de trabajo actual)", "global": "Global (todos los espacios de trabajo)", @@ -103,6 +107,7 @@ "installed": "¡Instalado exitosamente!", "whatNextMcp": "Ahora puedes configurar y usar este servidor MCP. Haz clic en el icono MCP en la barra lateral para cambiar de pestaña.", "whatNextMode": "Ahora puedes usar este modo. Haz clic en el icono Modos en la barra lateral para cambiar de pestaña.", + "whatNextCommand": "Ahora puedes usar este comando slash escribiendo /{{name}} en el chat.", "done": "Hecho", "goToMcp": "Ir a la pestaña MCP", "goToModes": "Ir a la configuración de Modos", @@ -149,6 +154,10 @@ "title": "Eliminar servidor MCP", "message": "¿Estás seguro de que quieres eliminar el servidor MCP \"{{mcpName}}\"?" }, + "command": { + "title": "Eliminar comando Slash", + "message": "¿Estás seguro de que quieres eliminar el comando slash \"{{commandName}}\"?" + }, "cancel": "Cancelar", "confirm": "Eliminar" }, diff --git a/webview-ui/src/i18n/locales/fr/marketplace.json b/webview-ui/src/i18n/locales/fr/marketplace.json index aa0ce5b718d..8d488a13a23 100644 --- a/webview-ui/src/i18n/locales/fr/marketplace.json +++ b/webview-ui/src/i18n/locales/fr/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Installé", "settings": "Paramètres", - "browse": "Parcourir" + "browse": "Parcourir", + "slashCommands": "Commandes Slash" }, "done": "Terminé", "refresh": "Actualiser", @@ -11,7 +12,8 @@ "search": { "placeholder": "Rechercher des éléments du marketplace...", "placeholderMcp": "Rechercher des MCPs...", - "placeholderMode": "Rechercher des modes..." + "placeholderMode": "Rechercher des modes...", + "placeholderCommand": "Rechercher des commandes Slash..." }, "installed": { "label": "Filtrer par statut", @@ -23,7 +25,8 @@ "label": "Filtrer par type :", "all": "Tous les types", "mode": "Mode", - "mcpServer": "Serveur MCP" + "mcpServer": "Serveur MCP", + "slashCommand": "Commande Slash" }, "sort": { "label": "Trier par :", @@ -91,6 +94,7 @@ "title": "Installer {{name}}", "titleMode": "Installer le mode {{name}}", "titleMcp": "Installer le MCP {{name}}", + "titleCommand": "Installer la commande Slash {{name}}", "scope": "Portée d'installation", "project": "Projet (espace de travail actuel)", "global": "Global (tous les espaces de travail)", @@ -103,6 +107,7 @@ "installed": "Installé avec succès !", "whatNextMcp": "Vous pouvez maintenant configurer et utiliser ce serveur MCP. Cliquez sur l'icône MCP dans la barre latérale pour changer d'onglet.", "whatNextMode": "Vous pouvez maintenant utiliser ce mode. Cliquez sur l'icône Modes dans la barre latérale pour changer d'onglet.", + "whatNextCommand": "Tu peux maintenant utiliser cette commande slash en tapant /{{name}} dans le chat.", "done": "Terminé", "goToMcp": "Aller à l'onglet MCP", "goToModes": "Aller aux paramètres des Modes", @@ -149,6 +154,10 @@ "title": "Supprimer le serveur MCP", "message": "Êtes-vous sûr de vouloir supprimer le serveur MCP « {{mcpName}} » ?" }, + "command": { + "title": "Supprimer la commande Slash", + "message": "Es-tu sûr de vouloir supprimer la commande slash \"{{commandName}}\" ?" + }, "cancel": "Annuler", "confirm": "Supprimer" }, diff --git a/webview-ui/src/i18n/locales/hi/marketplace.json b/webview-ui/src/i18n/locales/hi/marketplace.json index f50ca8b701e..50c60f3ffcf 100644 --- a/webview-ui/src/i18n/locales/hi/marketplace.json +++ b/webview-ui/src/i18n/locales/hi/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "इंस्टॉल किया गया", "settings": "सेटिंग्स", - "browse": "ब्राउज़ करें" + "browse": "ब्राउज़ करें", + "slashCommands": "Slash Commands" }, "done": "पूर्ण", "refresh": "रिफ्रेश करें", @@ -11,7 +12,8 @@ "search": { "placeholder": "Marketplace आइटम खोजें...", "placeholderMcp": "MCP खोजें...", - "placeholderMode": "मोड खोजें..." + "placeholderMode": "मोड खोजें...", + "placeholderCommand": "Slash Commands खोजें..." }, "installed": { "label": "स्थिति के अनुसार फ़िल्टर करें", @@ -23,7 +25,8 @@ "label": "प्रकार के अनुसार फ़िल्टर करें:", "all": "सभी प्रकार", "mode": "मोड", - "mcpServer": "MCP सर्वर" + "mcpServer": "MCP सर्वर", + "slashCommand": "Slash Command" }, "sort": { "label": "इसके अनुसार क्रमबद्ध करें:", @@ -89,6 +92,7 @@ "title": "{{name}} इंस्टॉल करें", "titleMode": "{{name}} मोड इंस्टॉल करें", "titleMcp": "{{name}} MCP इंस्टॉल करें", + "titleCommand": "{{name}} Slash Command इंस्टॉल करें", "scope": "इंस्टॉलेशन स्कोप", "project": "प्रोजेक्ट (वर्तमान वर्कस्पेस)", "global": "ग्लोबल (सभी वर्कस्पेस)", @@ -101,6 +105,7 @@ "installed": "सफलतापूर्वक इंस्टॉल किया गया!", "whatNextMcp": "अब आप इस MCP सर्वर को कॉन्फ़िगर और उपयोग कर सकते हैं। टैब स्विच करने के लिए साइडबार में MCP आइकन पर क्लिक करें।", "whatNextMode": "अब आप इस मोड का उपयोग कर सकते हैं। टैब स्विच करने के लिए साइडबार में मोड आइकन पर क्लिक करें।", + "whatNextCommand": "अब तुम चैट में /{{name}} टाइप करके इस slash command का उपयोग कर सकते हो।", "done": "पूर्ण", "goToMcp": "MCP टैब पर जाएं", "goToModes": "मोड सेटिंग्स पर जाएं", @@ -147,6 +152,10 @@ "title": "MCP सर्वर हटाएं", "message": "क्या आप वाकई MCP सर्वर \"{{mcpName}}\" को हटाना चाहते हैं?" }, + "command": { + "title": "Slash Command हटाएं", + "message": "क्या तुम निश्चित हो कि तुम \"{{commandName}}\" slash command को हटाना चाहते हो?" + }, "cancel": "रद्द करें", "confirm": "हटाएं" }, diff --git a/webview-ui/src/i18n/locales/id/marketplace.json b/webview-ui/src/i18n/locales/id/marketplace.json index f91a75ebbe2..76ea4b975c0 100644 --- a/webview-ui/src/i18n/locales/id/marketplace.json +++ b/webview-ui/src/i18n/locales/id/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Terinstal", "settings": "Pengaturan", - "browse": "Jelajahi" + "browse": "Jelajahi", + "slashCommands": "Perintah Slash" }, "done": "Selesai", "refresh": "Refresh", @@ -11,7 +12,8 @@ "search": { "placeholder": "Cari item marketplace...", "placeholderMcp": "Cari MCP...", - "placeholderMode": "Cari Mode..." + "placeholderMode": "Cari Mode...", + "placeholderCommand": "Cari perintah Slash..." }, "installed": { "label": "Filter berdasarkan status", @@ -23,7 +25,8 @@ "label": "Filter berdasarkan tipe:", "all": "Semua tipe", "mode": "Mode", - "mcpServer": "Server MCP" + "mcpServer": "Server MCP", + "slashCommand": "Perintah Slash" }, "sort": { "label": "Urutkan berdasarkan:", @@ -89,6 +92,7 @@ "title": "Instal {{name}}", "titleMode": "Instal Mode {{name}}", "titleMcp": "Instal MCP {{name}}", + "titleCommand": "Pasang Perintah Slash {{name}}", "scope": "Cakupan Instalasi", "project": "Proyek (workspace saat ini)", "global": "Global (semua workspace)", @@ -102,6 +106,7 @@ "installed": "Berhasil diinstal!", "whatNextMcp": "Anda sekarang dapat mengkonfigurasi dan menggunakan server MCP ini. Klik ikon MCP di sidebar untuk beralih tab.", "whatNextMode": "Anda sekarang dapat menggunakan mode ini. Klik ikon Mode di sidebar untuk beralih tab.", + "whatNextCommand": "Kamu sekarang bisa menggunakan perintah slash ini dengan mengetik /{{name}} di chat.", "done": "Selesai", "goToMcp": "Ke Tab MCP", "goToModes": "Ke Pengaturan Mode", @@ -147,6 +152,10 @@ "title": "Hapus Server MCP", "message": "Apakah Anda yakin ingin menghapus server MCP \"{{mcpName}}\"?" }, + "command": { + "title": "Hapus Perintah Slash", + "message": "Apakah Anda yakin ingin menghapus perintah slash \"{{commandName}}\"?" + }, "cancel": "Batal", "confirm": "Hapus" }, diff --git a/webview-ui/src/i18n/locales/it/marketplace.json b/webview-ui/src/i18n/locales/it/marketplace.json index 3c132848664..ba30de7caac 100644 --- a/webview-ui/src/i18n/locales/it/marketplace.json +++ b/webview-ui/src/i18n/locales/it/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Installati", "settings": "Impostazioni", - "browse": "Sfoglia" + "browse": "Sfoglia", + "slashCommands": "Comandi Slash" }, "done": "Fatto", "refresh": "Aggiorna", @@ -11,7 +12,8 @@ "search": { "placeholder": "Cerca elementi del Marketplace...", "placeholderMcp": "Cerca MCP...", - "placeholderMode": "Cerca modalità..." + "placeholderMode": "Cerca modalità...", + "placeholderCommand": "Cerca comandi Slash..." }, "installed": { "label": "Filtra per stato", @@ -23,7 +25,8 @@ "label": "Filtra per tipo:", "all": "Tutti i tipi", "mode": "Modalità", - "mcpServer": "Server MCP" + "mcpServer": "Server MCP", + "slashCommand": "Comando Slash" }, "sort": { "label": "Ordina per:", @@ -89,6 +92,7 @@ "title": "Installa {{name}}", "titleMode": "Installa modalità {{name}}", "titleMcp": "Installa MCP {{name}}", + "titleCommand": "Installa comando Slash {{name}}", "scope": "Ambito di installazione", "project": "Progetto (area di lavoro corrente)", "global": "Globale (tutte le aree di lavoro)", @@ -101,6 +105,7 @@ "installed": "Installato con successo!", "whatNextMcp": "Ora puoi configurare e utilizzare questo server MCP. Clicca sull'icona MCP nella barra laterale per cambiare scheda.", "whatNextMode": "Ora puoi utilizzare questa modalità. Clicca sull'icona delle modalità nella barra laterale per cambiare scheda.", + "whatNextCommand": "Ora puoi usare questo comando slash digitando /{{name}} nella chat.", "done": "Fatto", "goToMcp": "Vai alla scheda MCP", "goToModes": "Vai alle impostazioni Modalità", @@ -147,6 +152,10 @@ "title": "Rimuovi server MCP", "message": "Sei sicuro di voler rimuovere il server MCP \"{{mcpName}}\"?" }, + "command": { + "title": "Rimuovi comando Slash", + "message": "Sei sicuro di voler rimuovere il comando slash \"{{commandName}}\"?" + }, "cancel": "Annulla", "confirm": "Rimuovi" }, diff --git a/webview-ui/src/i18n/locales/ja/marketplace.json b/webview-ui/src/i18n/locales/ja/marketplace.json index 6a2ac9f9541..ac1477ccd0f 100644 --- a/webview-ui/src/i18n/locales/ja/marketplace.json +++ b/webview-ui/src/i18n/locales/ja/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "インストール済み", "settings": "設定", - "browse": "参照" + "browse": "参照", + "slashCommands": "スラッシュコマンド" }, "done": "完了", "refresh": "更新", @@ -11,7 +12,8 @@ "search": { "placeholder": "Marketplaceアイテムを検索...", "placeholderMcp": "MCPを検索...", - "placeholderMode": "モードを検索..." + "placeholderMode": "モードを検索...", + "placeholderCommand": "スラッシュコマンドを検索..." }, "installed": { "label": "ステータスで絞り込む", @@ -23,7 +25,8 @@ "label": "タイプでフィルター:", "all": "すべてのタイプ", "mode": "モード", - "mcpServer": "MCPサーバー" + "mcpServer": "MCPサーバー", + "slashCommand": "スラッシュコマンド" }, "sort": { "label": "並び順:", @@ -89,6 +92,7 @@ "title": "{{name}}をインストール", "titleMode": "{{name}}モードをインストール", "titleMcp": "{{name}} MCPをインストール", + "titleCommand": "{{name}}スラッシュコマンドをインストール", "scope": "インストール範囲", "project": "プロジェクト(現在のワークスペース)", "global": "グローバル(すべてのワークスペース)", @@ -101,6 +105,7 @@ "installed": "正常にインストールされました!", "whatNextMcp": "このMCPサーバーを設定して使用できるようになりました。サイドバーのMCPアイコンをクリックしてタブを切り替えてください。", "whatNextMode": "このモードを使用できるようになりました。サイドバーのモードアイコンをクリックしてタブを切り替えてください。", + "whatNextCommand": "チャットで /{{name}} と入力することで、このスラッシュコマンドを使用できるようになりました。", "done": "完了", "goToMcp": "MCPタブに移動", "goToModes": "モード設定に移動", @@ -147,6 +152,10 @@ "title": "MCPサーバーを削除", "message": "MCPサーバー「{{mcpName}}」を本当に削除しますか?" }, + "command": { + "title": "スラッシュコマンドを削除", + "message": "スラッシュコマンド「{{commandName}}」を削除してもよろしいですか?" + }, "cancel": "キャンセル", "confirm": "削除" }, diff --git a/webview-ui/src/i18n/locales/ko/marketplace.json b/webview-ui/src/i18n/locales/ko/marketplace.json index fd7d91c10e1..e1d8fabadef 100644 --- a/webview-ui/src/i18n/locales/ko/marketplace.json +++ b/webview-ui/src/i18n/locales/ko/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "설치됨", "settings": "설정", - "browse": "찾아보기" + "browse": "찾아보기", + "slashCommands": "슬래시 명령어" }, "done": "완료", "refresh": "새로고침", @@ -11,7 +12,8 @@ "search": { "placeholder": "Marketplace 아이템 검색...", "placeholderMcp": "MCP 검색...", - "placeholderMode": "모드 검색..." + "placeholderMode": "모드 검색...", + "placeholderCommand": "슬래시 명령어 검색..." }, "installed": { "label": "상태별로 필터링", @@ -23,7 +25,8 @@ "label": "유형별 필터:", "all": "모든 유형", "mode": "모드", - "mcpServer": "MCP 서버" + "mcpServer": "MCP 서버", + "slashCommand": "슬래시 명령어" }, "sort": { "label": "정렬 기준:", @@ -89,6 +92,7 @@ "title": "{{name}} 설치", "titleMode": "{{name}} 모드 설치", "titleMcp": "{{name}} MCP 설치", + "titleCommand": "{{name}} 슬래시 명령어 설치", "scope": "설치 범위", "project": "프로젝트 (현재 워크스페이스)", "global": "전역 (모든 워크스페이스)", @@ -101,6 +105,7 @@ "installed": "성공적으로 설치되었습니다!", "whatNextMcp": "이제 이 MCP 서버를 설정하고 사용할 수 있습니다. 사이드바의 MCP 아이콘을 클릭하여 탭을 전환하세요.", "whatNextMode": "이제 이 모드를 사용할 수 있습니다. 사이드바의 모드 아이콘을 클릭하여 탭을 전환하세요.", + "whatNextCommand": "이제 채팅에서 /{{name}}을 입력하여 이 슬래시 명령어를 사용할 수 있습니다.", "done": "완료", "goToMcp": "MCP 탭으로 이동", "goToModes": "모드 설정으로 이동", @@ -147,6 +152,10 @@ "title": "MCP 서버 제거", "message": "정말로 '{{mcpName}}' MCP 서버를 제거하시겠습니까?" }, + "command": { + "title": "슬래시 명령어 제거", + "message": "슬래시 명령어 \"{{commandName}}\"을 제거하시겠습니까?" + }, "cancel": "취소", "confirm": "제거" }, diff --git a/webview-ui/src/i18n/locales/nl/marketplace.json b/webview-ui/src/i18n/locales/nl/marketplace.json index b94c6294401..292c7aa4993 100644 --- a/webview-ui/src/i18n/locales/nl/marketplace.json +++ b/webview-ui/src/i18n/locales/nl/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Geïnstalleerd", "settings": "Instellingen", - "browse": "Bladeren" + "browse": "Bladeren", + "slashCommands": "Slash-commando's" }, "done": "Gereed", "refresh": "Vernieuwen", @@ -11,7 +12,8 @@ "search": { "placeholder": "Marketplace-items zoeken...", "placeholderMcp": "MCP's zoeken...", - "placeholderMode": "Modi zoeken..." + "placeholderMode": "Modi zoeken...", + "placeholderCommand": "Zoek slash-commando's..." }, "installed": { "label": "Filteren op status", @@ -23,7 +25,8 @@ "label": "Filteren op type:", "all": "Alle types", "mode": "Modus", - "mcpServer": "MCP-server" + "mcpServer": "MCP-server", + "slashCommand": "Slash-commando" }, "sort": { "label": "Sorteren op:", @@ -89,6 +92,7 @@ "title": "{{name}} installeren", "titleMode": "{{name}} modus installeren", "titleMcp": "{{name}} MCP installeren", + "titleCommand": "Slash-commando {{name}} installeren", "scope": "Installatiebereik", "project": "Project (huidige werkruimte)", "global": "Globaal (alle werkruimtes)", @@ -101,6 +105,7 @@ "installed": "Succesvol geïnstalleerd!", "whatNextMcp": "Je kunt deze MCP-server nu configureren en gebruiken. Klik op het MCP-pictogram in de zijbalk om van tabblad te wisselen.", "whatNextMode": "Je kunt deze modus nu gebruiken. Klik op het modi-pictogram in de zijbalk om van tabblad te wisselen.", + "whatNextCommand": "Je kunt dit slash-commando nu gebruiken door /{{name}} in de chat te typen.", "done": "Gereed", "goToMcp": "Ga naar MCP-tabblad", "goToModes": "Ga naar Modi-instellingen", @@ -147,6 +152,10 @@ "title": "MCP-server verwijderen", "message": "Weet je zeker dat je de MCP-server \"{{mcpName}}\" wilt verwijderen?" }, + "command": { + "title": "Slash-commando verwijderen", + "message": "Weet je zeker dat je het slash-commando \"{{commandName}}\" wilt verwijderen?" + }, "cancel": "Annuleren", "confirm": "Verwijderen" }, diff --git a/webview-ui/src/i18n/locales/pl/marketplace.json b/webview-ui/src/i18n/locales/pl/marketplace.json index d48dc34429c..e56c86ff80a 100644 --- a/webview-ui/src/i18n/locales/pl/marketplace.json +++ b/webview-ui/src/i18n/locales/pl/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Zainstalowane", "settings": "Ustawienia", - "browse": "Przeglądaj" + "browse": "Przeglądaj", + "slashCommands": "Polecenia Slash" }, "done": "Gotowe", "refresh": "Odśwież", @@ -11,7 +12,8 @@ "search": { "placeholder": "Szukaj elementów marketplace...", "placeholderMcp": "Szukaj MCPs...", - "placeholderMode": "Szukaj trybów..." + "placeholderMode": "Szukaj trybów...", + "placeholderCommand": "Szukaj poleceń Slash..." }, "installed": { "label": "Filtruj według statusu", @@ -23,7 +25,8 @@ "label": "Filtruj według typu:", "all": "Wszystkie typy", "mode": "Tryb", - "mcpServer": "Serwer MCP" + "mcpServer": "Serwer MCP", + "slashCommand": "Polecenie Slash" }, "sort": { "label": "Sortuj według:", @@ -89,6 +92,7 @@ "title": "Zainstaluj {{name}}", "titleMode": "Zainstaluj tryb {{name}}", "titleMcp": "Zainstaluj MCP {{name}}", + "titleCommand": "Zainstaluj polecenie Slash {{name}}", "scope": "Zakres instalacji", "project": "Projekt (bieżący obszar roboczy)", "global": "Globalnie (wszystkie obszary robocze)", @@ -101,6 +105,7 @@ "installed": "Zainstalowano pomyślnie!", "whatNextMcp": "Możesz teraz skonfigurować i używać tego serwera MCP. Kliknij ikonę MCP na pasku bocznym, aby przełączyć zakładki.", "whatNextMode": "Możesz teraz używać tego trybu. Kliknij ikonę Tryby na pasku bocznym, aby przełączyć zakładki.", + "whatNextCommand": "Możesz teraz używać tego polecenia slash, wpisując /{{name}} w czacie.", "done": "Gotowe", "goToMcp": "Przejdź do zakładki MCP", "goToModes": "Przejdź do ustawień Trybów", @@ -140,12 +145,16 @@ "removeConfirm": { "mode": { "title": "Usuń tryb", - "message": "Czy na pewno chcesz usunąć tryb „{{modeName}}”?", + "message": "Czy na pewno chcesz usunąć tryb \"{{modeName}}\"?", "rulesWarning": "Spowoduje to również usunięcie wszelkich powiązanych plików reguł dla tego trybu." }, "mcp": { "title": "Usuń serwer MCP", - "message": "Czy na pewno chcesz usunąć serwer MCP „{{mcpName}}”?" + "message": "Czy na pewno chcesz usunąć serwer MCP \"{{mcpName}}\"?" + }, + "command": { + "title": "Usuń polecenie Slash", + "message": "Czy na pewno chcesz usunąć polecenie slash \"{{commandName}}\"?" }, "cancel": "Anuluj", "confirm": "Usuń" diff --git a/webview-ui/src/i18n/locales/pt-BR/marketplace.json b/webview-ui/src/i18n/locales/pt-BR/marketplace.json index 80e47572506..511763e827a 100644 --- a/webview-ui/src/i18n/locales/pt-BR/marketplace.json +++ b/webview-ui/src/i18n/locales/pt-BR/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Instalado", "settings": "Configurações", - "browse": "Navegar" + "browse": "Navegar", + "slashCommands": "Comandos Slash" }, "done": "Concluído", "refresh": "Atualizar", @@ -11,7 +12,8 @@ "search": { "placeholder": "Buscar itens do marketplace...", "placeholderMcp": "Buscar MCPs...", - "placeholderMode": "Buscar modos..." + "placeholderMode": "Buscar modos...", + "placeholderCommand": "Buscar comandos Slash..." }, "installed": { "label": "Filtrar por status", @@ -23,7 +25,8 @@ "label": "Filtrar por tipo:", "all": "Todos os tipos", "mode": "Modo", - "mcpServer": "Servidor MCP" + "mcpServer": "Servidor MCP", + "slashCommand": "Comando Slash" }, "sort": { "label": "Ordenar por:", @@ -89,6 +92,7 @@ "title": "Instalar {{name}}", "titleMode": "Instalar modo {{name}}", "titleMcp": "Instalar MCP {{name}}", + "titleCommand": "Instalar comando Slash {{name}}", "scope": "Escopo da instalação", "project": "Projeto (workspace atual)", "global": "Global (todos os workspaces)", @@ -101,6 +105,7 @@ "installed": "Instalado com sucesso!", "whatNextMcp": "Agora você pode configurar e usar este servidor MCP. Clique no ícone MCP na barra lateral para trocar de aba.", "whatNextMode": "Agora você pode usar este modo. Clique no ícone Modos na barra lateral para trocar de aba.", + "whatNextCommand": "Agora você pode usar este comando slash digitando /{{name}} no chat.", "done": "Concluído", "goToMcp": "Ir para aba MCP", "goToModes": "Ir para configurações de Modos", @@ -147,6 +152,10 @@ "title": "Remover Servidor MCP", "message": "Tem certeza de que deseja remover o servidor MCP \"{{mcpName}}\"?" }, + "command": { + "title": "Remover comando Slash", + "message": "Tem certeza de que deseja remover o comando slash \"{{commandName}}\"?" + }, "cancel": "Cancelar", "confirm": "Remover" }, diff --git a/webview-ui/src/i18n/locales/ru/marketplace.json b/webview-ui/src/i18n/locales/ru/marketplace.json index 6c054a6b22e..95e95eed432 100644 --- a/webview-ui/src/i18n/locales/ru/marketplace.json +++ b/webview-ui/src/i18n/locales/ru/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Установлено", "settings": "Настройки", - "browse": "Обзор" + "browse": "Обзор", + "slashCommands": "Slash-команды" }, "done": "Готово", "refresh": "Обновить", @@ -11,7 +12,8 @@ "search": { "placeholder": "Поиск элементов marketplace...", "placeholderMcp": "Поиск MCPs...", - "placeholderMode": "Поиск режимов..." + "placeholderMode": "Поиск режимов...", + "placeholderCommand": "Искать Slash-команды..." }, "installed": { "label": "Фильтр по статусу", @@ -23,7 +25,8 @@ "label": "Фильтр по типу:", "all": "Все типы", "mode": "Режим", - "mcpServer": "MCP сервер" + "mcpServer": "MCP сервер", + "slashCommand": "Slash-команда" }, "sort": { "label": "Сортировать по:", @@ -89,6 +92,7 @@ "title": "Установить {{name}}", "titleMode": "Установить режим {{name}}", "titleMcp": "Установить MCP {{name}}", + "titleCommand": "Установить Slash-команду {{name}}", "scope": "Область установки", "project": "Проект (текущая рабочая область)", "global": "Глобально (все рабочие области)", @@ -101,6 +105,7 @@ "installed": "Успешно установлено!", "whatNextMcp": "Теперь вы можете настроить и использовать этот MCP сервер. Нажмите на иконку MCP в боковой панели для переключения вкладок.", "whatNextMode": "Теперь вы можете использовать этот режим. Нажмите на иконку Режимы в боковой панели для переключения вкладок.", + "whatNextCommand": "Теперь ты можешь использовать эту slash-команду, набрав /{{name}} в чате.", "done": "Готово", "goToMcp": "Перейти во вкладку MCP", "goToModes": "Перейти в настройки Режимов", @@ -147,6 +152,10 @@ "title": "Удалить сервер MCP", "message": "Вы уверены, что хотите удалить сервер MCP «{{mcpName}}»?" }, + "command": { + "title": "Удалить Slash-команду", + "message": "Ты уверен, что хочешь удалить slash-команду \"{{commandName}}\"?" + }, "cancel": "Отмена", "confirm": "Удалить" }, diff --git a/webview-ui/src/i18n/locales/tr/marketplace.json b/webview-ui/src/i18n/locales/tr/marketplace.json index 5b5a83a204a..59790448fcf 100644 --- a/webview-ui/src/i18n/locales/tr/marketplace.json +++ b/webview-ui/src/i18n/locales/tr/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Yüklü", "settings": "Ayarlar", - "browse": "Gözat" + "browse": "Gözat", + "slashCommands": "Slash Komutları" }, "done": "Tamamlandı", "refresh": "Yenile", @@ -11,7 +12,8 @@ "search": { "placeholder": "Marketplace öğelerini ara...", "placeholderMcp": "MCP'leri ara...", - "placeholderMode": "Modları ara..." + "placeholderMode": "Modları ara...", + "placeholderCommand": "Slash komutlarını ara..." }, "installed": { "label": "Duruma göre filtrele", @@ -23,7 +25,8 @@ "label": "Türe göre filtrele:", "all": "Tüm türler", "mode": "Mod", - "mcpServer": "MCP Sunucusu" + "mcpServer": "MCP Sunucusu", + "slashCommand": "Slash Komutu" }, "sort": { "label": "Sırala:", @@ -89,6 +92,7 @@ "title": "{{name}} Yükle", "titleMode": "{{name}} Modunu Yükle", "titleMcp": "{{name}} MCP'sini Yükle", + "titleCommand": "{{name}} Slash Komutunu Yükle", "scope": "Yükleme Kapsamı", "project": "Proje (mevcut çalışma alanı)", "global": "Global (tüm çalışma alanları)", @@ -101,6 +105,7 @@ "installed": "Başarıyla yüklendi!", "whatNextMcp": "Artık bu MCP sunucusunu yapılandırabilir ve kullanabilirsiniz. Sekmeleri değiştirmek için kenar çubuğundaki MCP simgesine tıklayın.", "whatNextMode": "Artık bu modu kullanabilirsiniz. Sekmeleri değiştirmek için kenar çubuğundaki Modlar simgesine tıklayın.", + "whatNextCommand": "Artık sohbette /{{name}} yazarak bu slash komutunu kullanabilirsin.", "done": "Tamamlandı", "goToMcp": "MCP Sekmesine Git", "goToModes": "Modlar Ayarlarına Git", @@ -147,6 +152,10 @@ "title": "MCP Sunucusunu Kaldır", "message": "\"{{mcpName}}\" MCP sunucusunu kaldırmak istediğinizden emin misiniz?" }, + "command": { + "title": "Slash Komutunu Kaldır", + "message": "\"{{commandName}}\" slash komutunu kaldırmak istediğine emin misin?" + }, "cancel": "İptal", "confirm": "Kaldır" }, diff --git a/webview-ui/src/i18n/locales/vi/marketplace.json b/webview-ui/src/i18n/locales/vi/marketplace.json index 29283bbfa28..8671841c693 100644 --- a/webview-ui/src/i18n/locales/vi/marketplace.json +++ b/webview-ui/src/i18n/locales/vi/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "Đã cài đặt", "settings": "Cài đặt", - "browse": "Duyệt" + "browse": "Duyệt", + "slashCommands": "Lệnh Slash" }, "done": "Hoàn thành", "refresh": "Làm mới", @@ -11,7 +12,8 @@ "search": { "placeholder": "Tìm kiếm các mục marketplace...", "placeholderMcp": "Tìm kiếm MCP...", - "placeholderMode": "Tìm kiếm Chế độ..." + "placeholderMode": "Tìm kiếm Chế độ...", + "placeholderCommand": "Tìm kiếm lệnh Slash..." }, "installed": { "label": "Lọc theo trạng thái", @@ -23,7 +25,8 @@ "label": "Lọc theo loại:", "all": "Tất cả loại", "mode": "Chế độ", - "mcpServer": "Máy chủ MCP" + "mcpServer": "Máy chủ MCP", + "slashCommand": "Lệnh Slash" }, "sort": { "label": "Sắp xếp theo:", @@ -89,6 +92,7 @@ "title": "Cài đặt {{name}}", "titleMode": "Cài đặt Chế độ {{name}}", "titleMcp": "Cài đặt MCP {{name}}", + "titleCommand": "Cài đặt lệnh Slash {{name}}", "scope": "Phạm vi cài đặt", "project": "Dự án (không gian làm việc hiện tại)", "global": "Toàn cục (tất cả không gian làm việc)", @@ -101,6 +105,7 @@ "installed": "Cài đặt thành công!", "whatNextMcp": "Bây giờ bạn có thể cấu hình và sử dụng máy chủ MCP này. Nhấp vào biểu tượng MCP trong thanh bên để chuyển tab.", "whatNextMode": "Bây giờ bạn có thể sử dụng chế độ này. Nhấp vào biểu tượng Chế độ trong thanh bên để chuyển tab.", + "whatNextCommand": "Bây giờ bạn có thể sử dụng lệnh slash này bằng cách gõ /{{name}} trong trò chuyện.", "done": "Hoàn thành", "goToMcp": "Đi đến Tab MCP", "goToModes": "Đi đến Cài đặt Chế độ", @@ -147,6 +152,10 @@ "title": "Xóa máy chủ MCP", "message": "Bạn có chắc chắn muốn xóa máy chủ MCP \"{{mcpName}}\" không?" }, + "command": { + "title": "Xóa lệnh Slash", + "message": "Bạn có chắc chắn muốn xóa lệnh slash \"{{commandName}}\" không?" + }, "cancel": "Hủy", "confirm": "Xóa" }, diff --git a/webview-ui/src/i18n/locales/zh-CN/marketplace.json b/webview-ui/src/i18n/locales/zh-CN/marketplace.json index 34e2099aa53..43415c0b3da 100644 --- a/webview-ui/src/i18n/locales/zh-CN/marketplace.json +++ b/webview-ui/src/i18n/locales/zh-CN/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "已安装", "settings": "设置", - "browse": "浏览" + "browse": "浏览", + "slashCommands": "Slash 命令" }, "done": "完成", "refresh": "刷新", @@ -11,7 +12,8 @@ "search": { "placeholder": "搜索 Marketplace 项目...", "placeholderMcp": "搜索 MCP...", - "placeholderMode": "搜索模式..." + "placeholderMode": "搜索模式...", + "placeholderCommand": "搜索 Slash 命令..." }, "installed": { "label": "按状态筛选", @@ -23,7 +25,8 @@ "label": "按类型筛选:", "all": "所有类型", "mode": "模式", - "mcpServer": "MCP 服务" + "mcpServer": "MCP 服务", + "slashCommand": "Slash 命令" }, "sort": { "label": "排序方式:", @@ -89,6 +92,7 @@ "title": "安装 {{name}}", "titleMode": "安装 {{name}} 模式", "titleMcp": "安装 {{name}} MCP", + "titleCommand": "安装 {{name}} Slash 命令", "scope": "安装范围", "project": "项目(当前工作区)", "global": "全局(所有工作区)", @@ -101,6 +105,7 @@ "installed": "安装成功!", "whatNextMcp": "现在您可以配置和使用此 MCP 服务。点击侧边栏中的 MCP 图标切换标签页。", "whatNextMode": "现在您可以使用此模式。点击侧边栏中的模式图标切换标签页。", + "whatNextCommand": "你现在可以在聊天中输入 /{{name}} 来使用这个 slash 命令。", "done": "完成", "goToMcp": "转到 MCP 标签页", "goToModes": "转到模式设置", @@ -147,6 +152,10 @@ "title": "删除 MCP 服务器", "message": "您确定要删除 MCP 服务器\"{{mcpName}}\"吗?" }, + "command": { + "title": "移除 Slash 命令", + "message": "确定要移除 slash 命令\"{{commandName}}\"吗?" + }, "cancel": "取消", "confirm": "删除" }, diff --git a/webview-ui/src/i18n/locales/zh-TW/marketplace.json b/webview-ui/src/i18n/locales/zh-TW/marketplace.json index a358c6efdd4..16e97ba2924 100644 --- a/webview-ui/src/i18n/locales/zh-TW/marketplace.json +++ b/webview-ui/src/i18n/locales/zh-TW/marketplace.json @@ -3,7 +3,8 @@ "tabs": { "installed": "已安裝", "settings": "設定", - "browse": "瀏覽" + "browse": "瀏覽", + "slashCommands": "Slash 指令" }, "done": "完成", "refresh": "重新整理", @@ -11,7 +12,8 @@ "search": { "placeholder": "搜尋市集項目...", "placeholderMcp": "搜尋 MCP...", - "placeholderMode": "搜尋模式..." + "placeholderMode": "搜尋模式...", + "placeholderCommand": "搜尋 Slash 指令..." }, "installed": { "label": "按狀態篩選", @@ -23,7 +25,8 @@ "label": "依類型篩選:", "all": "所有類型", "mode": "模式", - "mcpServer": "MCP 伺服器" + "mcpServer": "MCP 伺服器", + "slashCommand": "Slash 指令" }, "sort": { "label": "排序方式:", @@ -89,6 +92,7 @@ "title": "安裝 {{name}}", "titleMode": "安裝 {{name}} 模式", "titleMcp": "安裝 {{name}} MCP", + "titleCommand": "安裝 {{name}} Slash 指令", "scope": "安裝範圍", "project": "專案(目前工作區)", "global": "全域(所有工作區)", @@ -102,6 +106,7 @@ "installed": "安裝成功!", "whatNextMcp": "您現在可以設定和使用此 MCP 伺服器。點選側邊欄的 MCP 圖示來切換分頁。", "whatNextMode": "您現在可以使用此模式。點選側邊欄的模式圖示來切換分頁。", + "whatNextCommand": "你現在可以在聊天中輸入 /{{name}} 來使用這個 slash 指令。", "done": "完成", "goToMcp": "前往 MCP 分頁", "goToModes": "前往模式設定", @@ -147,6 +152,10 @@ "title": "移除 MCP 伺服器", "message": "您確定要移除 MCP 伺服器「{{mcpName}}」嗎?" }, + "command": { + "title": "移除 Slash 指令", + "message": "確定要移除 slash 指令「{{commandName}}」嗎?" + }, "cancel": "取消", "confirm": "移除" }, From 774c095d5b8c91efa7086525f16d543a549e6753 Mon Sep 17 00:00:00 2001 From: Hannes Rudolph Date: Mon, 8 Dec 2025 10:27:25 -0700 Subject: [PATCH 2/3] fix: use correct global commands path and add missing i18n parameter - MarketplaceManager: Use getGlobalRooDirectory() instead of extension settings path for global commands detection, matching SimpleInstaller behavior - MarketplaceInstallModal: Pass name parameter to whatNextCommand translation --- src/services/marketplace/MarketplaceManager.ts | 3 ++- .../marketplace/components/MarketplaceInstallModal.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/services/marketplace/MarketplaceManager.ts b/src/services/marketplace/MarketplaceManager.ts index 231793f61fa..c192f60f716 100644 --- a/src/services/marketplace/MarketplaceManager.ts +++ b/src/services/marketplace/MarketplaceManager.ts @@ -12,6 +12,7 @@ import { GlobalFileNames } from "../../shared/globalFileNames" import { ensureSettingsDirectoryExists } from "../../utils/globalContext" import { t } from "../../i18n" import type { CustomModesManager } from "../../core/config/CustomModesManager" +import { getGlobalRooDirectory } from "../roo-config" import { RemoteConfigLoader } from "./RemoteConfigLoader" import { SimpleInstaller } from "./SimpleInstaller" @@ -345,7 +346,7 @@ export class MarketplaceManager { } // Check global commands - const globalCommandsDir = path.join(globalSettingsPath, "commands") + const globalCommandsDir = path.join(getGlobalRooDirectory(), "commands") try { const entries = await fs.readdir(globalCommandsDir, { withFileTypes: true }) for (const entry of entries) { diff --git a/webview-ui/src/components/marketplace/components/MarketplaceInstallModal.tsx b/webview-ui/src/components/marketplace/components/MarketplaceInstallModal.tsx index d7ef844f370..96237ed54fd 100644 --- a/webview-ui/src/components/marketplace/components/MarketplaceInstallModal.tsx +++ b/webview-ui/src/components/marketplace/components/MarketplaceInstallModal.tsx @@ -246,7 +246,7 @@ export const MarketplaceInstallModal: React.FC = ( {item.type === "mcp" ? t("marketplace:install.whatNextMcp") : item.type === "command" - ? t("marketplace:install.whatNextCommand") + ? t("marketplace:install.whatNextCommand", { name: item.id }) : t("marketplace:install.whatNextMode")}

From 0b9214c1f6366166e088a524af6b275eb38deaf6 Mon Sep 17 00:00:00 2001 From: Hannes Rudolph Date: Mon, 8 Dec 2025 10:52:03 -0700 Subject: [PATCH 3/3] fix: address i18n consistency issues in ca, ru, zh-TW locales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Capitalize 'Slash' consistently in Catalan message - Use formal 'Вы/хотите' instead of informal 'Ты/хочешь' in Russian - Use formal '您' instead of informal '你' in Traditional Chinese - Capitalize 'Slash' consistently in Traditional Chinese messages --- webview-ui/src/i18n/locales/ca/marketplace.json | 2 +- webview-ui/src/i18n/locales/ru/marketplace.json | 2 +- webview-ui/src/i18n/locales/zh-TW/marketplace.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/i18n/locales/ca/marketplace.json b/webview-ui/src/i18n/locales/ca/marketplace.json index 17cbe0a19fb..cacd0b98502 100644 --- a/webview-ui/src/i18n/locales/ca/marketplace.json +++ b/webview-ui/src/i18n/locales/ca/marketplace.json @@ -156,7 +156,7 @@ }, "command": { "title": "Eliminar comanda Slash", - "message": "Estàs segur que vols eliminar la comanda slash \"{{commandName}}\"?" + "message": "Estàs segur que vols eliminar la comanda Slash \"{{commandName}}\"?" }, "cancel": "Cancel·lar", "confirm": "Eliminar" diff --git a/webview-ui/src/i18n/locales/ru/marketplace.json b/webview-ui/src/i18n/locales/ru/marketplace.json index 95e95eed432..5c63830d4d0 100644 --- a/webview-ui/src/i18n/locales/ru/marketplace.json +++ b/webview-ui/src/i18n/locales/ru/marketplace.json @@ -154,7 +154,7 @@ }, "command": { "title": "Удалить Slash-команду", - "message": "Ты уверен, что хочешь удалить slash-команду \"{{commandName}}\"?" + "message": "Вы уверены, что хотите удалить Slash-команду \"{{commandName}}\"?" }, "cancel": "Отмена", "confirm": "Удалить" diff --git a/webview-ui/src/i18n/locales/zh-TW/marketplace.json b/webview-ui/src/i18n/locales/zh-TW/marketplace.json index 16e97ba2924..b790692c70e 100644 --- a/webview-ui/src/i18n/locales/zh-TW/marketplace.json +++ b/webview-ui/src/i18n/locales/zh-TW/marketplace.json @@ -106,7 +106,7 @@ "installed": "安裝成功!", "whatNextMcp": "您現在可以設定和使用此 MCP 伺服器。點選側邊欄的 MCP 圖示來切換分頁。", "whatNextMode": "您現在可以使用此模式。點選側邊欄的模式圖示來切換分頁。", - "whatNextCommand": "你現在可以在聊天中輸入 /{{name}} 來使用這個 slash 指令。", + "whatNextCommand": "您現在可以在聊天中輸入 /{{name}} 來使用這個 Slash 指令。", "done": "完成", "goToMcp": "前往 MCP 分頁", "goToModes": "前往模式設定", @@ -154,7 +154,7 @@ }, "command": { "title": "移除 Slash 指令", - "message": "確定要移除 slash 指令「{{commandName}}」嗎?" + "message": "您確定要移除 Slash 指令「{{commandName}}」嗎?" }, "cancel": "取消", "confirm": "移除"