Skip to content

Commit b446b1d

Browse files
committed
fix: internationalize hardcoded error messages
- Added new error message keys to English locale files (tools.json and common.json) - Replaced hardcoded 'Roo tried to use' messages with i18n calls - Replaced other hardcoded error messages in say('error') calls - Updated test mocks to handle new i18n keys - Affected files: - Task.ts: Lines 1058, 2140 - writeToFileTool.ts: Line 148 - askFollowupQuestionTool.ts: Line 51 - applyDiffTool.ts: Line 86 - searchAndReplaceTool.ts: Lines 140, 159 - insertContentTool.ts: Line 90 - presentAssistantMessage.ts: Line 318 - useMcpToolTool.spec.ts: Test mock update This change ensures all error messages can be properly translated to the 17+ languages supported by Roo Code.
1 parent 2e99d5b commit b446b1d

File tree

10 files changed

+56
-22
lines changed

10 files changed

+56
-22
lines changed

src/core/assistant-message/presentAssistantMessage.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { Task } from "../task/Task"
3535
import { codebaseSearchTool } from "../tools/codebaseSearchTool"
3636
import { experiments, EXPERIMENT_IDS } from "../../shared/experiments"
3737
import { applyDiffToolLegacy } from "../tools/applyDiffTool"
38+
import { t } from "../../i18n"
3839

3940
/**
4041
* Processes and presents assistant message content to the user interface.
@@ -316,7 +317,10 @@ export async function presentAssistantMessage(cline: Task) {
316317

317318
await cline.say(
318319
"error",
319-
`Error ${action}:\n${error.message ?? JSON.stringify(serializeError(error), null, 2)}`,
320+
t("tools:errors.toolExecutionError", {
321+
action,
322+
error: error.message ?? JSON.stringify(serializeError(error), null, 2),
323+
}),
320324
)
321325

322326
pushToolResult(formatResponse.toolError(errorString))

src/core/task/Task.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,12 +1053,17 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
10531053
}
10541054

10551055
async sayAndCreateMissingParamError(toolName: ToolName, paramName: string, relPath?: string) {
1056-
await this.say(
1057-
"error",
1058-
`Roo tried to use ${toolName}${
1059-
relPath ? ` for '${relPath.toPosix()}'` : ""
1060-
} without value for required parameter '${paramName}'. Retrying...`,
1061-
)
1056+
const errorMessage = relPath
1057+
? t("tools:errors.missingRequiredParameter.withPath", {
1058+
toolName,
1059+
relPath: relPath.toPosix(),
1060+
paramName,
1061+
})
1062+
: t("tools:errors.missingRequiredParameter.withoutPath", {
1063+
toolName,
1064+
paramName,
1065+
})
1066+
await this.say("error", errorMessage)
10621067
return formatResponse.toolError(formatResponse.missingToolParameterError(paramName))
10631068
}
10641069

@@ -2135,10 +2140,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
21352140
// If there's no assistant_responses, that means we got no text
21362141
// or tool_use content blocks from API which we should assume is
21372142
// an error.
2138-
await this.say(
2139-
"error",
2140-
"Unexpected API Response: The language model did not provide any assistant messages. This may indicate an issue with the API or the model's output.",
2141-
)
2143+
await this.say("error", t("common:errors.unexpectedApiResponse"))
21422144

21432145
await this.addToApiConversationHistory({
21442146
role: "assistant",

src/core/tools/__tests__/useMcpToolTool.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ vi.mock("../../prompts/responses", () => ({
1515

1616
vi.mock("../../../i18n", () => ({
1717
t: vi.fn((key: string, params?: any) => {
18+
// Handle the new tools error messages
19+
if (key === "tools:errors.missingRequiredParameter.withPath" && params) {
20+
return `Roo tried to use ${params.toolName} for '${params.relPath}' without value for required parameter '${params.paramName}'. Retrying...`
21+
}
22+
if (key === "tools:errors.missingRequiredParameter.withoutPath" && params) {
23+
return `Roo tried to use ${params.toolName} without value for required parameter '${params.paramName}'. Retrying...`
24+
}
1825
if (key === "mcp:errors.invalidJsonArgument" && params?.toolName) {
1926
return `Roo tried to use ${params.toolName} with an invalid JSON argument. Retrying...`
2027
}

src/core/tools/applyDiffTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { fileExistsAtPath } from "../../utils/fs"
1313
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
1414
import { unescapeHtmlEntities } from "../../utils/text-normalization"
1515
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
16+
import { t } from "../../i18n"
1617

1718
export async function applyDiffToolLegacy(
1819
cline: Task,
@@ -82,7 +83,7 @@ export async function applyDiffToolLegacy(
8283
if (!fileExists) {
8384
cline.consecutiveMistakeCount++
8485
cline.recordToolError("apply_diff")
85-
const formattedError = `File does not exist at path: ${absolutePath}\n\n<error_details>\nThe specified file could not be found. Please verify the file path and try again.\n</error_details>`
86+
const formattedError = t("tools:errors.fileNotFound", { path: absolutePath })
8687
await cline.say("error", formattedError)
8788
pushToolResult(formattedError)
8889
return

src/core/tools/askFollowupQuestionTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Task } from "../task/Task"
22
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
33
import { formatResponse } from "../prompts/responses"
44
import { parseXml } from "../../utils/xml"
5+
import { t } from "../../i18n"
56

67
export async function askFollowupQuestionTool(
78
cline: Task,
@@ -48,7 +49,7 @@ export async function askFollowupQuestionTool(
4849
} catch (error) {
4950
cline.consecutiveMistakeCount++
5051
cline.recordToolError("ask_followup_question")
51-
await cline.say("error", `Failed to parse operations: ${error.message}`)
52+
await cline.say("error", t("tools:errors.parseOperationsFailed", { error: error.message }))
5253
pushToolResult(formatResponse.toolError("Invalid operations xml format"))
5354
return
5455
}

src/core/tools/insertContentTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { fileExistsAtPath } from "../../utils/fs"
1212
import { insertGroups } from "../diff/insert-groups"
1313
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
1414
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
15+
import { t } from "../../i18n"
1516

1617
export async function insertContentTool(
1718
cline: Task,
@@ -86,7 +87,7 @@ export async function insertContentTool(
8687
if (lineNumber > 1) {
8788
cline.consecutiveMistakeCount++
8889
cline.recordToolError("insert_content")
89-
const formattedError = `Cannot insert content at line ${lineNumber} into a non-existent file. For new files, 'line' must be 0 (to append) or 1 (to insert at the beginning).`
90+
const formattedError = t("tools:errors.insertContentNewFile", { lineNumber })
9091
await cline.say("error", formattedError)
9192
pushToolResult(formattedError)
9293
return

src/core/tools/searchAndReplaceTool.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { fileExistsAtPath } from "../../utils/fs"
1313
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
1414
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
1515
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
16+
import { t } from "../../i18n"
1617

1718
/**
1819
* Tool for performing search and replace operations on files
@@ -135,7 +136,7 @@ export async function searchAndReplaceTool(
135136
cline.consecutiveMistakeCount++
136137
cline.recordToolError("search_and_replace")
137138
const formattedError = formatResponse.toolError(
138-
`File does not exist at path: ${absolutePath}\nThe specified file could not be found. Please verify the file path and try again.`,
139+
t("tools:errors.fileNotFoundSimple", { path: absolutePath }),
139140
)
140141
await cline.say("error", formattedError)
141142
pushToolResult(formattedError)
@@ -152,9 +153,10 @@ export async function searchAndReplaceTool(
152153
} catch (error) {
153154
cline.consecutiveMistakeCount++
154155
cline.recordToolError("search_and_replace")
155-
const errorMessage = `Error reading file: ${absolutePath}\nFailed to read the file content: ${
156-
error instanceof Error ? error.message : String(error)
157-
}\nPlease verify file permissions and try again.`
156+
const errorMessage = t("tools:errors.fileReadError", {
157+
path: absolutePath,
158+
error: error instanceof Error ? error.message : String(error),
159+
})
158160
const formattedError = formatResponse.toolError(errorMessage)
159161
await cline.say("error", formattedError)
160162
pushToolResult(formattedError)

src/core/tools/writeToFileTool.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { detectCodeOmission } from "../../integrations/editor/detect-omission"
1616
import { unescapeHtmlEntities } from "../../utils/text-normalization"
1717
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
1818
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
19+
import { t } from "../../i18n"
1920

2021
export async function writeToFileTool(
2122
cline: Task,
@@ -145,9 +146,10 @@ export async function writeToFileTool(
145146
// Use more specific error message for line_count that provides guidance based on the situation
146147
await cline.say(
147148
"error",
148-
`Roo tried to use write_to_file${
149-
relPath ? ` for '${relPath.toPosix()}'` : ""
150-
} but the required parameter 'line_count' was missing or truncated after ${actualLineCount} lines of content were written. Retrying...`,
149+
t("tools:errors.lineCountMissing", {
150+
relPath: relPath ? ` for '${relPath.toPosix()}'` : "",
151+
actualLineCount,
152+
}),
151153
)
152154

153155
pushToolResult(

src/i18n/locales/en/common.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@
103103
},
104104
"roo": {
105105
"authenticationRequired": "Roo provider requires cloud authentication. Please sign in to Roo Code Cloud."
106-
}
106+
},
107+
"unexpectedApiResponse": "Unexpected API Response: The language model did not provide any assistant messages. This may indicate an issue with the API or the model's output."
107108
},
108109
"warnings": {
109110
"no_terminal_content": "No terminal content selected",

src/i18n/locales/en/tools.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,18 @@
1414
"errors": {
1515
"policy_restriction": "Failed to create new task due to policy restrictions."
1616
}
17+
},
18+
"errors": {
19+
"missingRequiredParameter": {
20+
"withPath": "Roo tried to use {{toolName}} for '{{relPath}}' without value for required parameter '{{paramName}}'. Retrying...",
21+
"withoutPath": "Roo tried to use {{toolName}} without value for required parameter '{{paramName}}'. Retrying..."
22+
},
23+
"lineCountMissing": "Roo tried to use write_to_file{{relPath}} but the required parameter 'line_count' was missing or truncated after {{actualLineCount}} lines of content were written. Retrying...",
24+
"parseOperationsFailed": "Failed to parse operations: {{error}}",
25+
"fileNotFound": "File does not exist at path: {{path}}\n\n<error_details>\nThe specified file could not be found. Please verify the file path and try again.\n</error_details>",
26+
"fileNotFoundSimple": "File does not exist at path: {{path}}\nThe specified file could not be found. Please verify the file path and try again.",
27+
"fileReadError": "Error reading file: {{path}}\nFailed to read the file content: {{error}}\nPlease verify file permissions and try again.",
28+
"insertContentNewFile": "Cannot insert content at line {{lineNumber}} into a non-existent file. For new files, 'line' must be 0 (to append) or 1 (to insert at the beginning).",
29+
"toolExecutionError": "Error {{action}}:\n{{error}}"
1730
}
1831
}

0 commit comments

Comments
 (0)