Skip to content

Commit 66d8cbd

Browse files
committed
fix(i18n): use JSON transport for rate limit wait message
Changed the rate limit wait countdown from a hardcoded English string to a structured JSON payload for i18n-safe transport. The frontend ChatRow component now parses the JSON to extract the seconds value, enabling proper internationalization through the existing rateLimitWait translation key.
1 parent a77b429 commit 66d8cbd

File tree

4 files changed

+18
-13
lines changed

4 files changed

+18
-13
lines changed

src/core/task/Task.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3685,15 +3685,16 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
36853685
)
36863686

36873687
// Only show the countdown UX on the first attempt. Retry flows have their own delay messaging.
3688-
if (rateLimitDelay > 0 && retryAttempt === 0) {
3689-
for (let i = rateLimitDelay; i > 0; i--) {
3690-
const delayMessage = `Rate limiting for ${i} seconds...`
3691-
await this.say("api_req_rate_limit_wait", delayMessage, undefined, true)
3692-
await delay(1000)
3688+
if (rateLimitDelay > 0 && retryAttempt === 0) {
3689+
for (let i = rateLimitDelay; i > 0; i--) {
3690+
// Send structured JSON data for i18n-safe transport
3691+
const delayMessage = JSON.stringify({ seconds: i })
3692+
await this.say("api_req_rate_limit_wait", delayMessage, undefined, true)
3693+
await delay(1000)
3694+
}
3695+
// Finalize the partial message so the UI doesn't keep rendering an in-progress spinner.
3696+
await this.say("api_req_rate_limit_wait", undefined, undefined, false)
36933697
}
3694-
// Finalize the partial message so the UI doesn't keep rendering an in-progress spinner.
3695-
await this.say("api_req_rate_limit_wait", undefined, undefined, false)
3696-
}
36973698
}
36983699

36993700
public async *attemptApiRequest(

src/core/task/__tests__/Task.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,10 +1071,10 @@ describe("Cline", () => {
10711071
expect(mockDelay).toHaveBeenCalledTimes(mockApiConfig.rateLimitSeconds)
10721072
expect(mockDelay).toHaveBeenCalledWith(1000)
10731073

1074-
// Verify we used the non-error rate-limit wait message type
1074+
// Verify we used the non-error rate-limit wait message type (JSON format)
10751075
expect(saySpy).toHaveBeenCalledWith(
10761076
"api_req_rate_limit_wait",
1077-
expect.stringContaining("Rate limiting for"),
1077+
expect.stringMatching(/\{"seconds":\d+\}/),
10781078
undefined,
10791079
true,
10801080
)

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,8 +1183,12 @@ export const ChatRowContent = ({
11831183

11841184
const waitSeconds = (() => {
11851185
if (!message.text) return undefined
1186-
const match = message.text.match(/Rate limiting for (\d+) seconds\.{3}/)
1187-
return match ? Number(match[1]) : undefined
1186+
try {
1187+
const data = JSON.parse(message.text)
1188+
return typeof data.seconds === "number" ? data.seconds : undefined
1189+
} catch {
1190+
return undefined
1191+
}
11881192
})()
11891193

11901194
return (

webview-ui/src/components/chat/__tests__/ChatRow.rate-limit-wait.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe("ChatRow - rate limit wait", () => {
4848
say: "api_req_rate_limit_wait",
4949
ts: Date.now(),
5050
partial: true,
51-
text: "Rate limiting for 1 seconds...",
51+
text: JSON.stringify({ seconds: 1 }),
5252
}
5353

5454
renderChatRow(message)

0 commit comments

Comments
 (0)