diff --git a/src/integrations/terminal/Terminal.ts b/src/integrations/terminal/Terminal.ts index 8bf2072f3d..bfeae3e8f8 100644 --- a/src/integrations/terminal/Terminal.ts +++ b/src/integrations/terminal/Terminal.ts @@ -157,6 +157,12 @@ export class Terminal extends BaseTerminal { // VTE must be disabled because it prevents the prompt command from executing // See https://wiki.gnome.org/Apps/Terminal/VTE VTE_VERSION: "0", + + // Ensure UTF-8 encoding for proper Unicode character display + // This fixes issues with non-ASCII characters (Cyrillic, Chinese, Hindi, etc.) + // being displayed as "?" or diamond symbols in terminal output + LANG: "en_US.UTF-8", + LC_ALL: "en_US.UTF-8", } // Set Oh My Zsh shell integration if enabled diff --git a/src/integrations/terminal/TerminalProcess.ts b/src/integrations/terminal/TerminalProcess.ts index eb0424fe8d..fe45f2f427 100644 --- a/src/integrations/terminal/TerminalProcess.ts +++ b/src/integrations/terminal/TerminalProcess.ts @@ -114,9 +114,21 @@ export class TerminalProcess extends BaseTerminalProcess { (defaultWindowsShellProfile === null || (defaultWindowsShellProfile as string)?.toLowerCase().includes("powershell")) - if (isPowerShell) { - let commandToExecute = command + let commandToExecute = command + + // On Windows, prepend chcp 65001 to set UTF-8 code page for proper Unicode support + // This fixes issues with non-ASCII characters being displayed as "?" or diamond symbols + if (process.platform === "win32") { + if (isPowerShell) { + // PowerShell syntax: use semicolon to chain commands and redirect output to null + commandToExecute = `chcp 65001 > $null ; ${command}` + } else { + // CMD syntax: use && to chain commands and redirect output to nul + commandToExecute = `chcp 65001 > nul && ${command}` + } + } + if (isPowerShell) { // Only add the PowerShell counter workaround if enabled if (Terminal.getPowershellCounter()) { commandToExecute += ` ; "(Roo/PS Workaround: ${this.terminal.cmdCounter++})" > $null` @@ -126,12 +138,10 @@ export class TerminalProcess extends BaseTerminalProcess { if (Terminal.getCommandDelay() > 0) { commandToExecute += ` ; start-sleep -milliseconds ${Terminal.getCommandDelay()}` } - - terminal.shellIntegration.executeCommand(commandToExecute) - } else { - terminal.shellIntegration.executeCommand(command) } + terminal.shellIntegration.executeCommand(commandToExecute) + this.isHot = true // Wait for stream to be available diff --git a/src/integrations/terminal/__tests__/TerminalRegistry.spec.ts b/src/integrations/terminal/__tests__/TerminalRegistry.spec.ts index d3912caf47..657433f23a 100644 --- a/src/integrations/terminal/__tests__/TerminalRegistry.spec.ts +++ b/src/integrations/terminal/__tests__/TerminalRegistry.spec.ts @@ -48,6 +48,8 @@ describe("TerminalRegistry", () => { PAGER, VTE_VERSION: "0", PROMPT_EOL_MARK: "", + LANG: "en_US.UTF-8", + LC_ALL: "en_US.UTF-8", }, }) }) @@ -69,6 +71,8 @@ describe("TerminalRegistry", () => { PROMPT_COMMAND: "sleep 0.05", VTE_VERSION: "0", PROMPT_EOL_MARK: "", + LANG: "en_US.UTF-8", + LC_ALL: "en_US.UTF-8", }, }) } finally { @@ -91,6 +95,8 @@ describe("TerminalRegistry", () => { VTE_VERSION: "0", PROMPT_EOL_MARK: "", ITERM_SHELL_INTEGRATION_INSTALLED: "Yes", + LANG: "en_US.UTF-8", + LC_ALL: "en_US.UTF-8", }, }) } finally { @@ -112,6 +118,8 @@ describe("TerminalRegistry", () => { VTE_VERSION: "0", PROMPT_EOL_MARK: "", POWERLEVEL9K_TERM_SHELL_INTEGRATION: "true", + LANG: "en_US.UTF-8", + LC_ALL: "en_US.UTF-8", }, }) } finally {