Skip to content

Commit 7459ac5

Browse files
authored
Merge pull request #1751 from RooVetGit/i18n_more_chat
More chat i18n
2 parents 69cc6c1 + 7bedb02 commit 7459ac5

File tree

26 files changed

+1849
-424
lines changed

26 files changed

+1849
-424
lines changed

.roomodes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"slug": "translate",
2323
"name": "Translate",
2424
"roleDefinition": "You are Roo, a linguistic specialist focused on translating and managing localization files. Your responsibility is to help maintain and update translation files for the application, ensuring consistency and accuracy across all language resources.",
25-
"customInstructions": "When internationalizing and translating content:\n\n# Translation Style and Tone\n- Maintain a direct and concise style that mirrors the tone of the original text\n- Carefully account for colloquialisms and idiomatic expressions in both source and target languages\n- Aim for culturally relevant and meaningful translations rather than literal translations\n- Adapt the formality level to match the original content (whether formal or informal)\n- Preserve the personality and voice of the original content\n- Use natural-sounding language that feels native to speakers of the target language\n- Don't translate the word \"token\" as it means something specific in English that all languages will understand\n\n# Technical Implementation\n- Use namespaces to organize translations logically\n- Handle pluralization using i18next's built-in capabilities\n- Implement proper interpolation for variables using {{variable}} syntax\n- Don't include defaultValue. The `en` translations are the fallback.\n- Always use apply_diff instead of write_to_file when editing existing translation files as it's much faster and more reliable\n- When using apply_diff, make sure to carefully identify the exact JSON structure to edit to avoid syntax errors\n- Always use the Trans component for text with embedded components\n\n# Quality Assurance\n- Maintain consistent terminology across all translations\n- Respect the JSON structure of translation files\n- Watch for placeholders and preserve them in translations\n- Be mindful of text length in UI elements when translating to languages that might require more characters\n- Use context-aware translations when the same string has different meanings\n- Always validate your translation work by running the missing translations script:\n ```\n node scripts/find-missing-translations.js\n ```\n- Before completing any translation task, ensure there are no missing translations by running the script with the target locale(s):\n ```\n node scripts/find-missing-translations.js --locale=<locale-code>\n ```\n- Address any missing translations identified by the script to ensure complete coverage across all locales\n\n# Supported Languages\n- Localize all strings into the following locale files: ca, de, en, es, fr, hi, it, ja, ko, pl, pt-BR, tr, vi, zh-CN, zh-TW\n- The translation files are under webview-ui/src/i18n/locales/",
25+
"customInstructions": "When internationalizing and translating content:\n\n# Translation Style and Tone\n- Maintain a direct and concise style that mirrors the tone of the original text\n- Carefully account for colloquialisms and idiomatic expressions in both source and target languages\n- Aim for culturally relevant and meaningful translations rather than literal translations\n- Adapt the formality level to match the original content (whether formal or informal)\n- Preserve the personality and voice of the original content\n- Use natural-sounding language that feels native to speakers of the target language\n- Don't translate the word \"token\" as it means something specific in English that all languages will understand\n\n# Technical Implementation\n- Use namespaces to organize translations logically\n- Handle pluralization using i18next's built-in capabilities\n- Implement proper interpolation for variables using {{variable}} syntax\n- Don't include defaultValue. The `en` translations are the fallback.\n- Always use apply_diff instead of write_to_file when editing existing translation files as it's much faster and more reliable\n- When using apply_diff, make sure to carefully identify the exact JSON structure to edit to avoid syntax errors\n- Always use the Trans component for text with embedded components\n- Internationalize and add English strings first, and then ask the user to confirm the approach before translating into all other languages\n\n# Quality Assurance\n- Maintain consistent terminology across all translations\n- Respect the JSON structure of translation files\n- Watch for placeholders and preserve them in translations\n- Be mindful of text length in UI elements when translating to languages that might require more characters\n- Use context-aware translations when the same string has different meanings\n- Always validate your translation work by running the missing translations script:\n ```\n node scripts/find-missing-translations.js\n ```\n- Before completing any translation task, ensure there are no missing translations by running the script with the target locale(s):\n ```\n node scripts/find-missing-translations.js --locale=<locale-code>\n ```\n- Address any missing translations identified by the script to ensure complete coverage across all locales\n\n# Supported Languages\n- Localize all strings into the following locale files: ca, de, en, es, fr, hi, it, ja, ko, pl, pt-BR, tr, vi, zh-CN, zh-TW\n- The translation files are under webview-ui/src/i18n/locales/",
2626
"groups": [
2727
"read",
2828
"command",

scripts/find-missing-translations.js

100644100755
File mode changed.

src/core/Cline.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3692,12 +3692,13 @@ export class Cline extends EventEmitter<ClineEvents> {
36923692
customModePrompts,
36933693
experiments = {} as Record<ExperimentId, boolean>,
36943694
customInstructions: globalCustomInstructions,
3695+
language,
36953696
} = (await this.providerRef.deref()?.getState()) ?? {}
36963697
const currentMode = mode ?? defaultModeSlug
36973698
const modeDetails = await getFullModeDetails(currentMode, customModes, customModePrompts, {
36983699
cwd,
36993700
globalCustomInstructions,
3700-
language: formatLanguage(vscode.env.language),
3701+
language: language ?? formatLanguage(vscode.env.language),
37013702
})
37023703
details += `\n\n# Current Mode\n`
37033704
details += `<slug>${currentMode}</slug>\n`

src/core/prompts/system.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ async function generatePrompt(
4141
diffEnabled?: boolean,
4242
experiments?: Record<string, boolean>,
4343
enableMcpServerCreation?: boolean,
44+
language?: string,
4445
rooIgnoreInstructions?: string,
4546
): Promise<string> {
4647
if (!context) {
@@ -90,7 +91,7 @@ ${getSystemInfoSection(cwd, mode, customModeConfigs)}
9091
9192
${getObjectiveSection()}
9293
93-
${await addCustomInstructions(promptComponent?.customInstructions || modeConfig.customInstructions || "", globalCustomInstructions || "", cwd, mode, { language: formatLanguage(vscode.env.language), rooIgnoreInstructions })}`
94+
${await addCustomInstructions(promptComponent?.customInstructions || modeConfig.customInstructions || "", globalCustomInstructions || "", cwd, mode, { language: language ?? formatLanguage(vscode.env.language), rooIgnoreInstructions })}`
9495

9596
return basePrompt
9697
}
@@ -109,6 +110,7 @@ export const SYSTEM_PROMPT = async (
109110
diffEnabled?: boolean,
110111
experiments?: Record<string, boolean>,
111112
enableMcpServerCreation?: boolean,
113+
language?: string,
112114
rooIgnoreInstructions?: string,
113115
): Promise<string> => {
114116
if (!context) {
@@ -139,7 +141,7 @@ export const SYSTEM_PROMPT = async (
139141
globalCustomInstructions || "",
140142
cwd,
141143
mode,
142-
{ language: formatLanguage(vscode.env.language), rooIgnoreInstructions },
144+
{ language: language ?? formatLanguage(vscode.env.language), rooIgnoreInstructions },
143145
)
144146
// For file-based prompts, don't include the tool sections
145147
return `${roleDefinition}
@@ -166,6 +168,7 @@ ${customInstructions}`
166168
diffEnabled,
167169
experiments,
168170
enableMcpServerCreation,
171+
language,
169172
rooIgnoreInstructions,
170173
)
171174
}

src/core/webview/ClineProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2545,7 +2545,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
25452545
writeDelayMs: stateValues.writeDelayMs ?? 1000,
25462546
terminalOutputLineLimit: stateValues.terminalOutputLineLimit ?? 500,
25472547
mode: stateValues.mode ?? defaultModeSlug,
2548-
language: stateValues.language || formatLanguage(vscode.env.language),
2548+
language: stateValues.language ?? formatLanguage(vscode.env.language),
25492549
mcpEnabled: stateValues.mcpEnabled ?? true,
25502550
enableMcpServerCreation: stateValues.enableMcpServerCreation ?? true,
25512551
alwaysApproveResubmit: stateValues.alwaysApproveResubmit ?? false,

webview-ui/src/__tests__/ContextWindowProgress.test.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ describe("ContextWindowProgress", () => {
6868
})
6969

7070
// Check for basic elements
71-
expect(screen.getByText("Context Window:")).toBeInTheDocument()
72-
expect(screen.getByText("1000")).toBeInTheDocument() // contextTokens
71+
expect(screen.getByTestId("context-window-label")).toBeInTheDocument()
72+
expect(screen.getByTestId("context-tokens-count")).toHaveTextContent("1000") // contextTokens
7373
// The actual context window might be different than what we pass in
7474
// due to the mock returning a default value from the API config
75-
expect(screen.getByText(/(4000|128000)/)).toBeInTheDocument() // contextWindow
75+
expect(screen.getByTestId("context-window-size")).toHaveTextContent(/(4000|128000)/) // contextWindow
7676
})
7777

7878
test("handles zero context window gracefully", () => {
@@ -83,8 +83,8 @@ describe("ContextWindowProgress", () => {
8383

8484
// In the current implementation, the component is still displayed with zero values
8585
// rather than being hidden completely
86-
expect(screen.getByText("Context Window:")).toBeInTheDocument()
87-
expect(screen.getByText("0")).toBeInTheDocument()
86+
expect(screen.getByTestId("context-window-label")).toBeInTheDocument()
87+
expect(screen.getByTestId("context-tokens-count")).toHaveTextContent("0")
8888
})
8989

9090
test("handles edge cases with negative values", () => {
@@ -94,9 +94,9 @@ describe("ContextWindowProgress", () => {
9494
})
9595

9696
// Should show 0 instead of -100
97-
expect(screen.getByText("0")).toBeInTheDocument()
97+
expect(screen.getByTestId("context-tokens-count")).toHaveTextContent("0")
9898
// The actual context window might be different than what we pass in
99-
expect(screen.getByText(/(4000|128000)/)).toBeInTheDocument()
99+
expect(screen.getByTestId("context-window-size")).toHaveTextContent(/(4000|128000)/)
100100
})
101101

102102
test("calculates percentages correctly", () => {
@@ -107,15 +107,18 @@ describe("ContextWindowProgress", () => {
107107
contextTokens,
108108
contextWindow,
109109
})
110-
111-
// Instead of checking the exact style, verify the title attribute
112-
// which contains information about the percentage of tokens used
113-
const tokenUsageDiv = screen.getByTitle(/Tokens used:/, { exact: false })
110+
// Instead of checking the title attribute, verify the data-test-id
111+
// which identifies the element containing info about the percentage of tokens used
112+
const tokenUsageDiv = screen.getByTestId("context-tokens-used")
114113
expect(tokenUsageDiv).toBeInTheDocument()
115114

115+
// Just verify that the element has a title attribute (the actual text is translated and may vary)
116+
expect(tokenUsageDiv).toHaveAttribute("title")
117+
116118
// We can't reliably test computed styles in JSDOM, so we'll just check
117119
// that the component appears to be working correctly by checking for expected elements
118-
expect(screen.getByText("Context Window:")).toBeInTheDocument()
120+
expect(screen.getByTestId("context-window-label")).toBeInTheDocument()
121+
expect(screen.getByTestId("context-tokens-count")).toHaveTextContent("1000")
119122
expect(screen.getByText("1000")).toBeInTheDocument()
120123
})
121124
})

0 commit comments

Comments
 (0)