diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index fbfc732b..2d0d9b37 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -91,6 +91,7 @@ import { useGitBranchName } from './hooks/useGitBranchName.js'; import { useExtensionUpdates } from './hooks/useExtensionUpdates.js'; import { ShellFocusContext } from './contexts/ShellFocusContext.js'; import { useQuitConfirmation } from './hooks/useQuitConfirmation.js'; +import { t } from '../i18n/index.js'; import { useWelcomeBack } from './hooks/useWelcomeBack.js'; import { useDialogClose } from './hooks/useDialogClose.js'; import { type VisionSwitchOutcome } from './components/ModelSwitchDialog.js'; @@ -372,14 +373,14 @@ export const AppContainer = (props: AppContainerProps) => { // Handle Qwen OAuth timeout const handleQwenAuthTimeout = useCallback(() => { - onAuthError('Qwen OAuth authentication timed out. Please try again.'); + onAuthError(t('Qwen OAuth authentication timed out. Please try again.')); cancelQwenAuth(); setAuthState(AuthState.Updating); }, [onAuthError, cancelQwenAuth, setAuthState]); // Handle Qwen OAuth cancel const handleQwenAuthCancel = useCallback(() => { - onAuthError('Qwen OAuth authentication cancelled.'); + onAuthError(t('Qwen OAuth authentication cancelled.')); cancelQwenAuth(); setAuthState(AuthState.Updating); }, [onAuthError, cancelQwenAuth, setAuthState]); @@ -401,7 +402,13 @@ export const AppContainer = (props: AppContainerProps) => { settings.merged.security?.auth.selectedType ) { onAuthError( - `Authentication is enforced to be ${settings.merged.security?.auth.enforcedType}, but you are currently using ${settings.merged.security?.auth.selectedType}.`, + t( + 'Authentication is enforced to be {{enforcedType}}, but you are currently using {{currentType}}.', + { + enforcedType: settings.merged.security?.auth.enforcedType, + currentType: settings.merged.security?.auth.selectedType, + }, + ), ); } else if ( settings.merged.security?.auth?.selectedType && diff --git a/packages/cli/src/ui/auth/AuthDialog.tsx b/packages/cli/src/ui/auth/AuthDialog.tsx index 9d9baa89..61463bc0 100644 --- a/packages/cli/src/ui/auth/AuthDialog.tsx +++ b/packages/cli/src/ui/auth/AuthDialog.tsx @@ -14,6 +14,7 @@ import { Colors } from '../colors.js'; import { useKeypress } from '../hooks/useKeypress.js'; import { OpenAIKeyPrompt } from '../components/OpenAIKeyPrompt.js'; import { RadioButtonSelect } from '../components/shared/RadioButtonSelect.js'; +import { t } from '../../i18n/index.js'; interface AuthDialogProps { onSelect: ( @@ -53,10 +54,14 @@ export function AuthDialog({ const items = [ { key: AuthType.QWEN_OAUTH, - label: 'Qwen OAuth', + label: t('Qwen OAuth'), value: AuthType.QWEN_OAUTH, }, - { key: AuthType.USE_OPENAI, label: 'OpenAI', value: AuthType.USE_OPENAI }, + { + key: AuthType.USE_OPENAI, + label: t('OpenAI'), + value: AuthType.USE_OPENAI, + }, ]; const initialAuthIndex = Math.max( @@ -107,7 +112,9 @@ export function AuthDialog({ const handleOpenAIKeyCancel = () => { setShowOpenAIKeyPrompt(false); - setErrorMessage('OpenAI API key is required to use OpenAI authentication.'); + setErrorMessage( + t('OpenAI API key is required to use OpenAI authentication.'), + ); }; useKeypress( @@ -125,7 +132,9 @@ export function AuthDialog({ if (settings.merged.security?.auth?.selectedType === undefined) { // Prevent exiting if no auth method is set setErrorMessage( - 'You must select an auth method to proceed. Press Ctrl+C again to exit.', + t( + 'You must select an auth method to proceed. Press Ctrl+C again to exit.', + ), ); return; } @@ -165,9 +174,9 @@ export function AuthDialog({ padding={1} width="100%" > - Get started + {t('Get started')} - How would you like to authenticate for this project? + {t('How would you like to authenticate for this project?')} )} - (Use Enter to Set Auth) + {t('(Use Enter to Set Auth)')} - Terms of Services and Privacy Notice for Qwen Code + {t('Terms of Services and Privacy Notice for Qwen Code')} diff --git a/packages/cli/src/ui/auth/useAuth.ts b/packages/cli/src/ui/auth/useAuth.ts index e761043d..34e484b4 100644 --- a/packages/cli/src/ui/auth/useAuth.ts +++ b/packages/cli/src/ui/auth/useAuth.ts @@ -13,6 +13,7 @@ import { } from '@qwen-code/qwen-code-core'; import { AuthState } from '../types.js'; import { validateAuthMethod } from '../../config/auth.js'; +import { t } from '../../i18n/index.js'; export function validateAuthMethodWithSettings( authType: AuthType, @@ -20,7 +21,13 @@ export function validateAuthMethodWithSettings( ): string | null { const enforcedType = settings.merged.security?.auth?.enforcedType; if (enforcedType && enforcedType !== authType) { - return `Authentication is enforced to be ${enforcedType}, but you are currently using ${authType}.`; + return t( + 'Authentication is enforced to be {{enforcedType}}, but you are currently using {{currentType}}.', + { + enforcedType, + currentType: authType, + }, + ); } if (settings.merged.security?.auth?.useExternal) { return null; @@ -76,7 +83,11 @@ export const useAuthCommand = (settings: LoadedSettings, config: Config) => { setAuthError(null); setAuthState(AuthState.Authenticated); } catch (e) { - onAuthError(`Failed to login. Message: ${getErrorMessage(e)}`); + onAuthError( + t('Failed to login. Message: {{message}}', { + message: getErrorMessage(e), + }), + ); } finally { setIsAuthenticating(false); } diff --git a/packages/cli/src/ui/commands/aboutCommand.ts b/packages/cli/src/ui/commands/aboutCommand.ts index 0f35db92..800b2b00 100644 --- a/packages/cli/src/ui/commands/aboutCommand.ts +++ b/packages/cli/src/ui/commands/aboutCommand.ts @@ -8,10 +8,13 @@ import type { SlashCommand } from './types.js'; import { CommandKind } from './types.js'; import { MessageType, type HistoryItemAbout } from '../types.js'; import { getExtendedSystemInfo } from '../../utils/systemInfo.js'; +import { t } from '../../i18n/index.js'; export const aboutCommand: SlashCommand = { name: 'about', - description: 'show version info', + get description() { + return t('show version info'); + }, kind: CommandKind.BUILT_IN, action: async (context) => { const systemInfo = await getExtendedSystemInfo(context); diff --git a/packages/cli/src/ui/commands/agentsCommand.ts b/packages/cli/src/ui/commands/agentsCommand.ts index ccb5997a..02fed007 100644 --- a/packages/cli/src/ui/commands/agentsCommand.ts +++ b/packages/cli/src/ui/commands/agentsCommand.ts @@ -9,15 +9,20 @@ import { type SlashCommand, type OpenDialogActionReturn, } from './types.js'; +import { t } from '../../i18n/index.js'; export const agentsCommand: SlashCommand = { name: 'agents', - description: 'Manage subagents for specialized task delegation.', + get description() { + return t('Manage subagents for specialized task delegation.'); + }, kind: CommandKind.BUILT_IN, subCommands: [ { name: 'manage', - description: 'Manage existing subagents (view, edit, delete).', + get description() { + return t('Manage existing subagents (view, edit, delete).'); + }, kind: CommandKind.BUILT_IN, action: (): OpenDialogActionReturn => ({ type: 'dialog', @@ -26,7 +31,9 @@ export const agentsCommand: SlashCommand = { }, { name: 'create', - description: 'Create a new subagent with guided setup.', + get description() { + return t('Create a new subagent with guided setup.'); + }, kind: CommandKind.BUILT_IN, action: (): OpenDialogActionReturn => ({ type: 'dialog', diff --git a/packages/cli/src/ui/commands/authCommand.ts b/packages/cli/src/ui/commands/authCommand.ts index 5ba3088c..9caee464 100644 --- a/packages/cli/src/ui/commands/authCommand.ts +++ b/packages/cli/src/ui/commands/authCommand.ts @@ -6,10 +6,13 @@ import type { OpenDialogActionReturn, SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const authCommand: SlashCommand = { name: 'auth', - description: 'change the auth method', + get description() { + return t('change the auth method'); + }, kind: CommandKind.BUILT_IN, action: (_context, _args): OpenDialogActionReturn => ({ type: 'dialog', diff --git a/packages/cli/src/ui/commands/bugCommand.ts b/packages/cli/src/ui/commands/bugCommand.ts index 869024b5..14cf3759 100644 --- a/packages/cli/src/ui/commands/bugCommand.ts +++ b/packages/cli/src/ui/commands/bugCommand.ts @@ -16,10 +16,13 @@ import { getSystemInfoFields, getFieldValue, } from '../../utils/systemInfoFields.js'; +import { t } from '../../i18n/index.js'; export const bugCommand: SlashCommand = { name: 'bug', - description: 'submit a bug report', + get description() { + return t('submit a bug report'); + }, kind: CommandKind.BUILT_IN, action: async (context: CommandContext, args?: string): Promise => { const bugDescription = (args || '').trim(); diff --git a/packages/cli/src/ui/commands/clearCommand.ts b/packages/cli/src/ui/commands/clearCommand.ts index 4c6405c0..8beed859 100644 --- a/packages/cli/src/ui/commands/clearCommand.ts +++ b/packages/cli/src/ui/commands/clearCommand.ts @@ -7,21 +7,24 @@ import { uiTelemetryService } from '@qwen-code/qwen-code-core'; import type { SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const clearCommand: SlashCommand = { name: 'clear', - description: 'clear the screen and conversation history', + get description() { + return t('clear the screen and conversation history'); + }, kind: CommandKind.BUILT_IN, action: async (context, _args) => { const geminiClient = context.services.config?.getGeminiClient(); if (geminiClient) { - context.ui.setDebugMessage('Clearing terminal and resetting chat.'); + context.ui.setDebugMessage(t('Clearing terminal and resetting chat.')); // If resetChat fails, the exception will propagate and halt the command, // which is the correct behavior to signal a failure to the user. await geminiClient.resetChat(); } else { - context.ui.setDebugMessage('Clearing terminal.'); + context.ui.setDebugMessage(t('Clearing terminal.')); } uiTelemetryService.setLastPromptTokenCount(0); diff --git a/packages/cli/src/ui/commands/compressCommand.ts b/packages/cli/src/ui/commands/compressCommand.ts index 45dc6a46..399bfa61 100644 --- a/packages/cli/src/ui/commands/compressCommand.ts +++ b/packages/cli/src/ui/commands/compressCommand.ts @@ -8,11 +8,14 @@ import type { HistoryItemCompression } from '../types.js'; import { MessageType } from '../types.js'; import type { SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const compressCommand: SlashCommand = { name: 'compress', altNames: ['summarize'], - description: 'Compresses the context by replacing it with a summary.', + get description() { + return t('Compresses the context by replacing it with a summary.'); + }, kind: CommandKind.BUILT_IN, action: async (context) => { const { ui } = context; @@ -20,7 +23,7 @@ export const compressCommand: SlashCommand = { ui.addItem( { type: MessageType.ERROR, - text: 'Already compressing, wait for previous request to complete', + text: t('Already compressing, wait for previous request to complete'), }, Date.now(), ); @@ -60,7 +63,7 @@ export const compressCommand: SlashCommand = { ui.addItem( { type: MessageType.ERROR, - text: 'Failed to compress chat history.', + text: t('Failed to compress chat history.'), }, Date.now(), ); @@ -69,9 +72,9 @@ export const compressCommand: SlashCommand = { ui.addItem( { type: MessageType.ERROR, - text: `Failed to compress chat history: ${ - e instanceof Error ? e.message : String(e) - }`, + text: t('Failed to compress chat history: {{error}}', { + error: e instanceof Error ? e.message : String(e), + }), }, Date.now(), ); diff --git a/packages/cli/src/ui/commands/copyCommand.ts b/packages/cli/src/ui/commands/copyCommand.ts index 99115491..3b79dd48 100644 --- a/packages/cli/src/ui/commands/copyCommand.ts +++ b/packages/cli/src/ui/commands/copyCommand.ts @@ -7,10 +7,13 @@ import { copyToClipboard } from '../utils/commandUtils.js'; import type { SlashCommand, SlashCommandActionReturn } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const copyCommand: SlashCommand = { name: 'copy', - description: 'Copy the last result or code snippet to clipboard', + get description() { + return t('Copy the last result or code snippet to clipboard'); + }, kind: CommandKind.BUILT_IN, action: async (context, _args): Promise => { const chat = await context.services.config?.getGeminiClient()?.getChat(); diff --git a/packages/cli/src/ui/commands/directoryCommand.tsx b/packages/cli/src/ui/commands/directoryCommand.tsx index cc8970d0..60dfcd3b 100644 --- a/packages/cli/src/ui/commands/directoryCommand.tsx +++ b/packages/cli/src/ui/commands/directoryCommand.tsx @@ -10,6 +10,7 @@ import { MessageType } from '../types.js'; import * as os from 'node:os'; import * as path from 'node:path'; import { loadServerHierarchicalMemory } from '@qwen-code/qwen-code-core'; +import { t } from '../../i18n/index.js'; export function expandHomeDir(p: string): string { if (!p) { @@ -27,13 +28,18 @@ export function expandHomeDir(p: string): string { export const directoryCommand: SlashCommand = { name: 'directory', altNames: ['dir'], - description: 'Manage workspace directories', + get description() { + return t('Manage workspace directories'); + }, kind: CommandKind.BUILT_IN, subCommands: [ { name: 'add', - description: - 'Add directories to the workspace. Use comma to separate multiple paths', + get description() { + return t( + 'Add directories to the workspace. Use comma to separate multiple paths', + ); + }, kind: CommandKind.BUILT_IN, action: async (context: CommandContext, args: string) => { const { @@ -150,7 +156,9 @@ export const directoryCommand: SlashCommand = { }, { name: 'show', - description: 'Show all directories in the workspace', + get description() { + return t('Show all directories in the workspace'); + }, kind: CommandKind.BUILT_IN, action: async (context: CommandContext) => { const { diff --git a/packages/cli/src/ui/commands/docsCommand.ts b/packages/cli/src/ui/commands/docsCommand.ts index 109aaab7..8fc01836 100644 --- a/packages/cli/src/ui/commands/docsCommand.ts +++ b/packages/cli/src/ui/commands/docsCommand.ts @@ -12,19 +12,28 @@ import { CommandKind, } from './types.js'; import { MessageType } from '../types.js'; +import { t, getCurrentLanguage } from '../../i18n/index.js'; export const docsCommand: SlashCommand = { name: 'docs', - description: 'open full Qwen Code documentation in your browser', + get description() { + return t('open full Qwen Code documentation in your browser'); + }, kind: CommandKind.BUILT_IN, action: async (context: CommandContext): Promise => { - const docsUrl = 'https://qwenlm.github.io/qwen-code-docs/en'; + const langPath = getCurrentLanguage()?.startsWith('zh') ? 'zh' : 'en'; + const docsUrl = `https://qwenlm.github.io/qwen-code-docs/${langPath}`; if (process.env['SANDBOX'] && process.env['SANDBOX'] !== 'sandbox-exec') { context.ui.addItem( { type: MessageType.INFO, - text: `Please open the following URL in your browser to view the documentation:\n${docsUrl}`, + text: t( + 'Please open the following URL in your browser to view the documentation:\n{{url}}', + { + url: docsUrl, + }, + ), }, Date.now(), ); @@ -32,7 +41,9 @@ export const docsCommand: SlashCommand = { context.ui.addItem( { type: MessageType.INFO, - text: `Opening documentation in your browser: ${docsUrl}`, + text: t('Opening documentation in your browser: {{url}}', { + url: docsUrl, + }), }, Date.now(), ); diff --git a/packages/cli/src/ui/commands/editorCommand.ts b/packages/cli/src/ui/commands/editorCommand.ts index 5b5c4c5d..f39cbdbc 100644 --- a/packages/cli/src/ui/commands/editorCommand.ts +++ b/packages/cli/src/ui/commands/editorCommand.ts @@ -9,10 +9,13 @@ import { type OpenDialogActionReturn, type SlashCommand, } from './types.js'; +import { t } from '../../i18n/index.js'; export const editorCommand: SlashCommand = { name: 'editor', - description: 'set external editor preference', + get description() { + return t('set external editor preference'); + }, kind: CommandKind.BUILT_IN, action: (): OpenDialogActionReturn => ({ type: 'dialog', diff --git a/packages/cli/src/ui/commands/helpCommand.ts b/packages/cli/src/ui/commands/helpCommand.ts index 4731efc5..c4772ea0 100644 --- a/packages/cli/src/ui/commands/helpCommand.ts +++ b/packages/cli/src/ui/commands/helpCommand.ts @@ -7,12 +7,15 @@ import type { SlashCommand } from './types.js'; import { CommandKind } from './types.js'; import { MessageType, type HistoryItemHelp } from '../types.js'; +import { t } from '../../i18n/index.js'; export const helpCommand: SlashCommand = { name: 'help', altNames: ['?'], kind: CommandKind.BUILT_IN, - description: 'for help on Qwen Code', + get description() { + return t('for help on Qwen Code'); + }, action: async (context) => { const helpItem: Omit = { type: MessageType.HELP, diff --git a/packages/cli/src/ui/commands/initCommand.ts b/packages/cli/src/ui/commands/initCommand.ts index 0777be8e..16c98dff 100644 --- a/packages/cli/src/ui/commands/initCommand.ts +++ b/packages/cli/src/ui/commands/initCommand.ts @@ -15,10 +15,13 @@ import { getCurrentGeminiMdFilename } from '@qwen-code/qwen-code-core'; import { CommandKind } from './types.js'; import { Text } from 'ink'; import React from 'react'; +import { t } from '../../i18n/index.js'; export const initCommand: SlashCommand = { name: 'init', - description: 'Analyzes the project and creates a tailored QWEN.md file.', + get description() { + return t('Analyzes the project and creates a tailored QWEN.md file.'); + }, kind: CommandKind.BUILT_IN, action: async ( context: CommandContext, @@ -28,7 +31,7 @@ export const initCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: 'Configuration not available.', + content: t('Configuration not available.'), }; } const targetDir = context.services.config.getTargetDir(); diff --git a/packages/cli/src/ui/commands/languageCommand.ts b/packages/cli/src/ui/commands/languageCommand.ts index aabaa2ec..eee70b98 100644 --- a/packages/cli/src/ui/commands/languageCommand.ts +++ b/packages/cli/src/ui/commands/languageCommand.ts @@ -115,10 +115,18 @@ async function setUiLanguage( // Reload commands to update their descriptions with the new language context.ui.reloadCommands(); + // Map language codes to friendly display names + const langDisplayNames: Record = { + zh: '中文(zh-CN)', + en: 'English(en-US)', + }; + return { type: 'message', messageType: 'info', - content: t('UI language changed to {{lang}}', { lang }), + content: t('UI language changed to {{lang}}', { + lang: langDisplayNames[lang], + }), }; } diff --git a/packages/cli/src/ui/commands/mcpCommand.ts b/packages/cli/src/ui/commands/mcpCommand.ts index 2521e10c..f0e66829 100644 --- a/packages/cli/src/ui/commands/mcpCommand.ts +++ b/packages/cli/src/ui/commands/mcpCommand.ts @@ -24,10 +24,13 @@ import { } from '@qwen-code/qwen-code-core'; import { appEvents, AppEvent } from '../../utils/events.js'; import { MessageType, type HistoryItemMcpStatus } from '../types.js'; +import { t } from '../../i18n/index.js'; const authCommand: SlashCommand = { name: 'auth', - description: 'Authenticate with an OAuth-enabled MCP server', + get description() { + return t('Authenticate with an OAuth-enabled MCP server'); + }, kind: CommandKind.BUILT_IN, action: async ( context: CommandContext, @@ -40,7 +43,7 @@ const authCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: 'Config not loaded.', + content: t('Config not loaded.'), }; } @@ -56,14 +59,14 @@ const authCommand: SlashCommand = { return { type: 'message', messageType: 'info', - content: 'No MCP servers configured with OAuth authentication.', + content: t('No MCP servers configured with OAuth authentication.'), }; } return { type: 'message', messageType: 'info', - content: `MCP servers with OAuth authentication:\n${oauthServers.map((s) => ` - ${s}`).join('\n')}\n\nUse /mcp auth to authenticate.`, + content: `${t('MCP servers with OAuth authentication:')}\n${oauthServers.map((s) => ` - ${s}`).join('\n')}\n\n${t('Use /mcp auth to authenticate.')}`, }; } @@ -72,7 +75,7 @@ const authCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: `MCP server '${serverName}' not found.`, + content: t("MCP server '{{name}}' not found.", { name: serverName }), }; } @@ -111,7 +114,12 @@ const authCommand: SlashCommand = { context.ui.addItem( { type: 'info', - text: `✅ Successfully authenticated with MCP server '${serverName}'!`, + text: t( + "Successfully authenticated and refreshed tools for '{{name}}'.", + { + name: serverName, + }, + ), }, Date.now(), ); @@ -122,7 +130,9 @@ const authCommand: SlashCommand = { context.ui.addItem( { type: 'info', - text: `Re-discovering tools from '${serverName}'...`, + text: t("Re-discovering tools from '{{name}}'...", { + name: serverName, + }), }, Date.now(), ); @@ -140,13 +150,24 @@ const authCommand: SlashCommand = { return { type: 'message', messageType: 'info', - content: `Successfully authenticated and refreshed tools for '${serverName}'.`, + content: t( + "Successfully authenticated and refreshed tools for '{{name}}'.", + { + name: serverName, + }, + ), }; } catch (error) { return { type: 'message', messageType: 'error', - content: `Failed to authenticate with MCP server '${serverName}': ${getErrorMessage(error)}`, + content: t( + "Failed to authenticate with MCP server '{{name}}': {{error}}", + { + name: serverName, + error: getErrorMessage(error), + }, + ), }; } finally { appEvents.removeListener(AppEvent.OauthDisplayMessage, displayListener); @@ -165,7 +186,9 @@ const authCommand: SlashCommand = { const listCommand: SlashCommand = { name: 'list', - description: 'List configured MCP servers and tools', + get description() { + return t('List configured MCP servers and tools'); + }, kind: CommandKind.BUILT_IN, action: async ( context: CommandContext, @@ -176,7 +199,7 @@ const listCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: 'Config not loaded.', + content: t('Config not loaded.'), }; } @@ -276,7 +299,9 @@ const listCommand: SlashCommand = { const refreshCommand: SlashCommand = { name: 'refresh', - description: 'Restarts MCP servers.', + get description() { + return t('Restarts MCP servers.'); + }, kind: CommandKind.BUILT_IN, action: async ( context: CommandContext, @@ -286,7 +311,7 @@ const refreshCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: 'Config not loaded.', + content: t('Config not loaded.'), }; } @@ -324,8 +349,11 @@ const refreshCommand: SlashCommand = { export const mcpCommand: SlashCommand = { name: 'mcp', - description: - 'list configured MCP servers and tools, or authenticate with OAuth-enabled servers', + get description() { + return t( + 'list configured MCP servers and tools, or authenticate with OAuth-enabled servers', + ); + }, kind: CommandKind.BUILT_IN, subCommands: [listCommand, authCommand, refreshCommand], // Default action when no subcommand is provided diff --git a/packages/cli/src/ui/commands/permissionsCommand.ts b/packages/cli/src/ui/commands/permissionsCommand.ts index 60ef3884..2b6a7c34 100644 --- a/packages/cli/src/ui/commands/permissionsCommand.ts +++ b/packages/cli/src/ui/commands/permissionsCommand.ts @@ -6,10 +6,13 @@ import type { OpenDialogActionReturn, SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const permissionsCommand: SlashCommand = { name: 'permissions', - description: 'Manage folder trust settings', + get description() { + return t('Manage folder trust settings'); + }, kind: CommandKind.BUILT_IN, action: (): OpenDialogActionReturn => ({ type: 'dialog', diff --git a/packages/cli/src/ui/commands/quitCommand.ts b/packages/cli/src/ui/commands/quitCommand.ts index 3e175d9c..fc9683c9 100644 --- a/packages/cli/src/ui/commands/quitCommand.ts +++ b/packages/cli/src/ui/commands/quitCommand.ts @@ -6,10 +6,13 @@ import { formatDuration } from '../utils/formatters.js'; import { CommandKind, type SlashCommand } from './types.js'; +import { t } from '../../i18n/index.js'; export const quitConfirmCommand: SlashCommand = { name: 'quit-confirm', - description: 'Show quit confirmation dialog', + get description() { + return t('Show quit confirmation dialog'); + }, kind: CommandKind.BUILT_IN, action: (context) => { const now = Date.now(); @@ -37,7 +40,9 @@ export const quitConfirmCommand: SlashCommand = { export const quitCommand: SlashCommand = { name: 'quit', altNames: ['exit'], - description: 'exit the cli', + get description() { + return t('exit the cli'); + }, kind: CommandKind.BUILT_IN, action: (context) => { const now = Date.now(); diff --git a/packages/cli/src/ui/commands/settingsCommand.ts b/packages/cli/src/ui/commands/settingsCommand.ts index 4a3665f1..f7052f19 100644 --- a/packages/cli/src/ui/commands/settingsCommand.ts +++ b/packages/cli/src/ui/commands/settingsCommand.ts @@ -6,10 +6,13 @@ import type { OpenDialogActionReturn, SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const settingsCommand: SlashCommand = { name: 'settings', - description: 'View and edit Qwen Code settings', + get description() { + return t('View and edit Qwen Code settings'); + }, kind: CommandKind.BUILT_IN, action: (_context, _args): OpenDialogActionReturn => ({ type: 'dialog', diff --git a/packages/cli/src/ui/commands/setupGithubCommand.ts b/packages/cli/src/ui/commands/setupGithubCommand.ts index 46b46cba..378f1101 100644 --- a/packages/cli/src/ui/commands/setupGithubCommand.ts +++ b/packages/cli/src/ui/commands/setupGithubCommand.ts @@ -20,6 +20,7 @@ import { import type { SlashCommand, SlashCommandActionReturn } from './types.js'; import { CommandKind } from './types.js'; import { getUrlOpenCommand } from '../../ui/utils/commandUtils.js'; +import { t } from '../../i18n/index.js'; export const GITHUB_WORKFLOW_PATHS = [ 'gemini-dispatch/gemini-dispatch.yml', @@ -91,7 +92,9 @@ export async function updateGitignore(gitRepoRoot: string): Promise { export const setupGithubCommand: SlashCommand = { name: 'setup-github', - description: 'Set up GitHub Actions', + get description() { + return t('Set up GitHub Actions'); + }, kind: CommandKind.BUILT_IN, action: async ( context: CommandContext, diff --git a/packages/cli/src/ui/commands/statsCommand.ts b/packages/cli/src/ui/commands/statsCommand.ts index 1fe628ab..5248ca43 100644 --- a/packages/cli/src/ui/commands/statsCommand.ts +++ b/packages/cli/src/ui/commands/statsCommand.ts @@ -12,11 +12,14 @@ import { type SlashCommand, CommandKind, } from './types.js'; +import { t } from '../../i18n/index.js'; export const statsCommand: SlashCommand = { name: 'stats', altNames: ['usage'], - description: 'check session stats. Usage: /stats [model|tools]', + get description() { + return t('check session stats. Usage: /stats [model|tools]'); + }, kind: CommandKind.BUILT_IN, action: (context: CommandContext) => { const now = new Date(); @@ -43,7 +46,9 @@ export const statsCommand: SlashCommand = { subCommands: [ { name: 'model', - description: 'Show model-specific usage statistics.', + get description() { + return t('Show model-specific usage statistics.'); + }, kind: CommandKind.BUILT_IN, action: (context: CommandContext) => { context.ui.addItem( @@ -56,7 +61,9 @@ export const statsCommand: SlashCommand = { }, { name: 'tools', - description: 'Show tool-specific usage statistics.', + get description() { + return t('Show tool-specific usage statistics.'); + }, kind: CommandKind.BUILT_IN, action: (context: CommandContext) => { context.ui.addItem( diff --git a/packages/cli/src/ui/commands/summaryCommand.ts b/packages/cli/src/ui/commands/summaryCommand.ts index 7c666a04..5d943e8e 100644 --- a/packages/cli/src/ui/commands/summaryCommand.ts +++ b/packages/cli/src/ui/commands/summaryCommand.ts @@ -13,11 +13,15 @@ import { } from './types.js'; import { getProjectSummaryPrompt } from '@qwen-code/qwen-code-core'; import type { HistoryItemSummary } from '../types.js'; +import { t } from '../../i18n/index.js'; export const summaryCommand: SlashCommand = { name: 'summary', - description: - 'Generate a project summary and save it to .qwen/PROJECT_SUMMARY.md', + get description() { + return t( + 'Generate a project summary and save it to .qwen/PROJECT_SUMMARY.md', + ); + }, kind: CommandKind.BUILT_IN, action: async (context): Promise => { const { config } = context.services; @@ -26,7 +30,7 @@ export const summaryCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: 'Config not loaded.', + content: t('Config not loaded.'), }; } @@ -35,7 +39,7 @@ export const summaryCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: 'No chat client available to generate summary.', + content: t('No chat client available to generate summary.'), }; } @@ -44,15 +48,18 @@ export const summaryCommand: SlashCommand = { ui.addItem( { type: 'error' as const, - text: 'Already generating summary, wait for previous request to complete', + text: t( + 'Already generating summary, wait for previous request to complete', + ), }, Date.now(), ); return { type: 'message', messageType: 'error', - content: + content: t( 'Already generating summary, wait for previous request to complete', + ), }; } @@ -65,7 +72,7 @@ export const summaryCommand: SlashCommand = { return { type: 'message', messageType: 'info', - content: 'No conversation found to summarize.', + content: t('No conversation found to summarize.'), }; } @@ -171,9 +178,12 @@ export const summaryCommand: SlashCommand = { ui.addItem( { type: 'error' as const, - text: `❌ Failed to generate project context summary: ${ - error instanceof Error ? error.message : String(error) - }`, + text: `❌ ${t( + 'Failed to generate project context summary: {{error}}', + { + error: error instanceof Error ? error.message : String(error), + }, + )}`, }, Date.now(), ); @@ -181,9 +191,9 @@ export const summaryCommand: SlashCommand = { return { type: 'message', messageType: 'error', - content: `Failed to generate project context summary: ${ - error instanceof Error ? error.message : String(error) - }`, + content: t('Failed to generate project context summary: {{error}}', { + error: error instanceof Error ? error.message : String(error), + }), }; } }, diff --git a/packages/cli/src/ui/commands/themeCommand.ts b/packages/cli/src/ui/commands/themeCommand.ts index 585c84f9..fd366366 100644 --- a/packages/cli/src/ui/commands/themeCommand.ts +++ b/packages/cli/src/ui/commands/themeCommand.ts @@ -6,10 +6,13 @@ import type { OpenDialogActionReturn, SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const themeCommand: SlashCommand = { name: 'theme', - description: 'change the theme', + get description() { + return t('change the theme'); + }, kind: CommandKind.BUILT_IN, action: (_context, _args): OpenDialogActionReturn => ({ type: 'dialog', diff --git a/packages/cli/src/ui/commands/toolsCommand.ts b/packages/cli/src/ui/commands/toolsCommand.ts index 4378c450..4bd97e3e 100644 --- a/packages/cli/src/ui/commands/toolsCommand.ts +++ b/packages/cli/src/ui/commands/toolsCommand.ts @@ -10,10 +10,13 @@ import { CommandKind, } from './types.js'; import { MessageType, type HistoryItemToolsList } from '../types.js'; +import { t } from '../../i18n/index.js'; export const toolsCommand: SlashCommand = { name: 'tools', - description: 'list available Qwen Code tools. Usage: /tools [desc]', + get description() { + return t('list available Qwen Code tools. Usage: /tools [desc]'); + }, kind: CommandKind.BUILT_IN, action: async (context: CommandContext, args?: string): Promise => { const subCommand = args?.trim(); @@ -29,7 +32,7 @@ export const toolsCommand: SlashCommand = { context.ui.addItem( { type: MessageType.ERROR, - text: 'Could not retrieve tool registry.', + text: t('Could not retrieve tool registry.'), }, Date.now(), ); diff --git a/packages/cli/src/ui/commands/vimCommand.ts b/packages/cli/src/ui/commands/vimCommand.ts index b398cc48..8f3dc6bd 100644 --- a/packages/cli/src/ui/commands/vimCommand.ts +++ b/packages/cli/src/ui/commands/vimCommand.ts @@ -6,10 +6,13 @@ import type { SlashCommand } from './types.js'; import { CommandKind } from './types.js'; +import { t } from '../../i18n/index.js'; export const vimCommand: SlashCommand = { name: 'vim', - description: 'toggle vim mode on/off', + get description() { + return t('toggle vim mode on/off'); + }, kind: CommandKind.BUILT_IN, action: async (context, _args) => { const newVimState = await context.ui.toggleVimEnabled(); diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx index 4e255983..1b51227a 100644 --- a/packages/cli/src/ui/components/Composer.tsx +++ b/packages/cli/src/ui/components/Composer.tsx @@ -26,6 +26,7 @@ import { useSettings } from '../contexts/SettingsContext.js'; import { ApprovalMode } from '@qwen-code/qwen-code-core'; import { StreamingState } from '../types.js'; import { ConfigInitDisplay } from '../components/ConfigInitDisplay.js'; +import { t } from '../../i18n/index.js'; export const Composer = () => { const config = useConfig(); @@ -86,14 +87,16 @@ export const Composer = () => { )} {uiState.ctrlCPressedOnce ? ( - Press Ctrl+C again to exit. + {t('Press Ctrl+C again to exit.')} ) : uiState.ctrlDPressedOnce ? ( - Press Ctrl+D again to exit. + {t('Press Ctrl+D again to exit.')} ) : uiState.showEscapePrompt ? ( - Press Esc again to clear. + + {t('Press Esc again to clear.')} + ) : ( !settings.merged.ui?.hideContextSummary && ( { isEmbeddedShellFocused={uiState.embeddedShellFocused} placeholder={ vimEnabled - ? " Press 'i' for INSERT mode and 'Esc' for NORMAL mode." - : ' Type your message or @path/to/file' + ? ' ' + t("Press 'i' for INSERT mode and 'Esc' for NORMAL mode.") + : ' ' + t('Type your message or @path/to/file') } /> )} diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index f33700d8..96926629 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -89,7 +89,7 @@ export const InputPrompt: React.FC = ({ config, slashCommands, commandContext, - placeholder = ' Type your message or @path/to/file', + placeholder, focus = true, inputWidth, suggestionsWidth, diff --git a/packages/cli/src/ui/components/ProQuotaDialog.tsx b/packages/cli/src/ui/components/ProQuotaDialog.tsx index 0f3c4a55..cc9bd5f8 100644 --- a/packages/cli/src/ui/components/ProQuotaDialog.tsx +++ b/packages/cli/src/ui/components/ProQuotaDialog.tsx @@ -8,6 +8,7 @@ import type React from 'react'; import { Box, Text } from 'ink'; import { RadioButtonSelect } from './shared/RadioButtonSelect.js'; import { theme } from '../semantic-colors.js'; +import { t } from '../../i18n/index.js'; interface ProQuotaDialogProps { failedModel: string; @@ -22,12 +23,12 @@ export function ProQuotaDialog({ }: ProQuotaDialogProps): React.JSX.Element { const items = [ { - label: 'Change auth (executes the /auth command)', + label: t('Change auth (executes the /auth command)'), value: 'auth' as const, key: 'auth', }, { - label: `Continue with ${fallbackModel}`, + label: t('Continue with {{model}}', { model: fallbackModel }), value: 'continue' as const, key: 'continue', }, @@ -40,7 +41,7 @@ export function ProQuotaDialog({ return ( - Pro quota limit reached for {failedModel}. + {t('Pro quota limit reached for {{model}}.', { model: failedModel })} = ({ const options: Array> = [ { key: 'quit', - label: 'Quit immediately (/quit)', + label: t('Quit immediately (/quit)'), value: QuitChoice.QUIT, }, { key: 'summary-and-quit', - label: 'Generate summary and quit (/summary)', + label: t('Generate summary and quit (/summary)'), value: QuitChoice.SUMMARY_AND_QUIT, }, { key: 'save-and-quit', - label: 'Save conversation and quit (/chat save)', + label: t('Save conversation and quit (/chat save)'), value: QuitChoice.SAVE_AND_QUIT, }, { key: 'cancel', - label: 'Cancel (stay in application)', + label: t('Cancel (stay in application)'), value: QuitChoice.CANCEL, }, ]; @@ -69,7 +70,7 @@ export const QuitConfirmationDialog: React.FC = ({ marginLeft={1} > - What would you like to do before exiting? + {t('What would you like to do before exiting?')} diff --git a/packages/cli/src/ui/components/QwenOAuthProgress.tsx b/packages/cli/src/ui/components/QwenOAuthProgress.tsx index 685cb107..56cb9933 100644 --- a/packages/cli/src/ui/components/QwenOAuthProgress.tsx +++ b/packages/cli/src/ui/components/QwenOAuthProgress.tsx @@ -13,6 +13,7 @@ import qrcode from 'qrcode-terminal'; import { Colors } from '../colors.js'; import type { DeviceAuthorizationInfo } from '../hooks/useQwenAuth.js'; import { useKeypress } from '../hooks/useKeypress.js'; +import { t } from '../../i18n/index.js'; interface QwenOAuthProgressProps { onTimeout: () => void; @@ -52,11 +53,11 @@ function QrCodeDisplay({ width="100%" > - Qwen OAuth Authentication + {t('Qwen OAuth Authentication')} - Please visit this URL to authorize: + {t('Please visit this URL to authorize:')} @@ -66,7 +67,7 @@ function QrCodeDisplay({ - Or scan the QR code below: + {t('Or scan the QR code below:')} @@ -103,15 +104,18 @@ function StatusDisplay({ > - Waiting for authorization{dots} + {t('Waiting for authorization')} + {dots} - Time remaining: {formatTime(timeRemaining)} + {t('Time remaining:')} {formatTime(timeRemaining)} + + + {t('(Press ESC or CTRL+C to cancel)')} - (Press ESC or CTRL+C to cancel) ); @@ -215,19 +219,24 @@ export function QwenOAuthProgress({ width="100%" > - Qwen OAuth Authentication Timeout + {t('Qwen OAuth Authentication Timeout')} {authMessage || - `OAuth token expired (over ${defaultTimeout} seconds). Please select authentication method again.`} + t( + 'OAuth token expired (over {{seconds}} seconds). Please select authentication method again.', + { + seconds: defaultTimeout.toString(), + }, + )} - Press any key to return to authentication type selection. + {t('Press any key to return to authentication type selection.')} @@ -246,16 +255,17 @@ export function QwenOAuthProgress({ > - Waiting for Qwen OAuth authentication... + + {t('Waiting for Qwen OAuth authentication...')} - Time remaining: {Math.floor(timeRemaining / 60)}: + {t('Time remaining:')} {Math.floor(timeRemaining / 60)}: {(timeRemaining % 60).toString().padStart(2, '0')} - (Press ESC or CTRL+C to cancel) + {t('(Press ESC or CTRL+C to cancel)')} diff --git a/packages/cli/src/ui/components/SessionSummaryDisplay.tsx b/packages/cli/src/ui/components/SessionSummaryDisplay.tsx index d4a0a11d..c8d79e0e 100644 --- a/packages/cli/src/ui/components/SessionSummaryDisplay.tsx +++ b/packages/cli/src/ui/components/SessionSummaryDisplay.tsx @@ -6,6 +6,7 @@ import type React from 'react'; import { StatsDisplay } from './StatsDisplay.js'; +import { t } from '../../i18n/index.js'; interface SessionSummaryDisplayProps { duration: string; @@ -14,5 +15,8 @@ interface SessionSummaryDisplayProps { export const SessionSummaryDisplay: React.FC = ({ duration, }) => ( - + ); diff --git a/packages/cli/src/ui/components/ShellConfirmationDialog.tsx b/packages/cli/src/ui/components/ShellConfirmationDialog.tsx index f2ab61b0..d83bf9bc 100644 --- a/packages/cli/src/ui/components/ShellConfirmationDialog.tsx +++ b/packages/cli/src/ui/components/ShellConfirmationDialog.tsx @@ -12,6 +12,7 @@ import { RenderInline } from '../utils/InlineMarkdownRenderer.js'; import type { RadioSelectItem } from './shared/RadioButtonSelect.js'; import { RadioButtonSelect } from './shared/RadioButtonSelect.js'; import { useKeypress } from '../hooks/useKeypress.js'; +import { t } from '../../i18n/index.js'; export interface ShellConfirmationRequest { commands: string[]; @@ -51,17 +52,17 @@ export const ShellConfirmationDialog: React.FC< const options: Array> = [ { - label: 'Yes, allow once', + label: t('Yes, allow once'), value: ToolConfirmationOutcome.ProceedOnce, key: 'Yes, allow once', }, { - label: 'Yes, allow always for this session', + label: t('Yes, allow always for this session'), value: ToolConfirmationOutcome.ProceedAlways, key: 'Yes, allow always for this session', }, { - label: 'No (esc)', + label: t('No (esc)'), value: ToolConfirmationOutcome.Cancel, key: 'No (esc)', }, @@ -78,10 +79,10 @@ export const ShellConfirmationDialog: React.FC< > - Shell Command Execution + {t('Shell Command Execution')} - A custom command wants to run the following shell commands: + {t('A custom command wants to run the following shell commands:')} - Do you want to proceed? + {t('Do you want to proceed?')} diff --git a/packages/cli/src/ui/components/StatsDisplay.tsx b/packages/cli/src/ui/components/StatsDisplay.tsx index 8c7bacd7..a6511942 100644 --- a/packages/cli/src/ui/components/StatsDisplay.tsx +++ b/packages/cli/src/ui/components/StatsDisplay.tsx @@ -19,6 +19,7 @@ import { USER_AGREEMENT_RATE_MEDIUM, } from '../utils/displayUtils.js'; import { computeSessionStats } from '../utils/computeStats.js'; +import { t } from '../../i18n/index.js'; // A more flexible and powerful StatRow component interface StatRowProps { @@ -85,22 +86,22 @@ const ModelUsageTable: React.FC<{ - Model Usage + {t('Model Usage')} - Reqs + {t('Reqs')} - Input Tokens + {t('Input Tokens')} - Output Tokens + {t('Output Tokens')} @@ -141,13 +142,14 @@ const ModelUsageTable: React.FC<{ {cacheEfficiency > 0 && ( - Savings Highlight:{' '} + {t('Savings Highlight:')}{' '} {totalCachedTokens.toLocaleString()} ({cacheEfficiency.toFixed(1)} - %) of input tokens were served from the cache, reducing costs. + %){' '} + {t('of input tokens were served from the cache, reducing costs.')} - » Tip: For a full token breakdown, run `/stats model`. + » {t('Tip: For a full token breakdown, run `/stats model`.')} )} @@ -199,7 +201,7 @@ export const StatsDisplay: React.FC = ({ } return ( - Session Stats + {t('Session Stats')} ); }; @@ -215,33 +217,33 @@ export const StatsDisplay: React.FC = ({ {renderTitle()} -
- +
+ {stats.sessionId} - + {tools.totalCalls} ({' '} ✓ {tools.totalSuccess}{' '} x {tools.totalFail} ) - + {computed.successRate.toFixed(1)}% {computed.totalDecisions > 0 && ( - + {computed.agreementRate.toFixed(1)}%{' '} - ({computed.totalDecisions} reviewed) + ({computed.totalDecisions} {t('reviewed')}) )} {files && (files.totalLinesAdded > 0 || files.totalLinesRemoved > 0) && ( - + +{files.totalLinesAdded} @@ -254,16 +256,16 @@ export const StatsDisplay: React.FC = ({ )}
-
- +
+ {duration} - + {formatDuration(computed.agentActiveTime)} - + {formatDuration(computed.totalApiTime)}{' '} @@ -271,7 +273,7 @@ export const StatsDisplay: React.FC = ({ - + {formatDuration(computed.totalToolTime)}{' '} diff --git a/packages/cli/src/ui/components/Tips.tsx b/packages/cli/src/ui/components/Tips.tsx index 810d57ef..c8537b55 100644 --- a/packages/cli/src/ui/components/Tips.tsx +++ b/packages/cli/src/ui/components/Tips.tsx @@ -8,6 +8,7 @@ import type React from 'react'; import { Box, Text } from 'ink'; import { theme } from '../semantic-colors.js'; import { type Config } from '@qwen-code/qwen-code-core'; +import { t } from '../../i18n/index.js'; interface TipsProps { config: Config; @@ -17,12 +18,12 @@ export const Tips: React.FC = ({ config }) => { const geminiMdFileCount = config.getGeminiMdFileCount(); return ( - Tips for getting started: + {t('Tips for getting started:')} - 1. Ask questions, edit files, or run commands. + {t('1. Ask questions, edit files, or run commands.')} - 2. Be specific for the best results. + {t('2. Be specific for the best results.')} {geminiMdFileCount === 0 && ( @@ -30,7 +31,7 @@ export const Tips: React.FC = ({ config }) => { QWEN.md {' '} - files to customize your interactions with Qwen Code. + {t('files to customize your interactions with Qwen Code.')} )} @@ -38,7 +39,7 @@ export const Tips: React.FC = ({ config }) => { /help {' '} - for more information. + {t('for more information.')} ); diff --git a/packages/cli/src/ui/components/WelcomeBackDialog.tsx b/packages/cli/src/ui/components/WelcomeBackDialog.tsx index d16a2d8c..5ce5de31 100644 --- a/packages/cli/src/ui/components/WelcomeBackDialog.tsx +++ b/packages/cli/src/ui/components/WelcomeBackDialog.tsx @@ -12,6 +12,7 @@ import { type RadioSelectItem, } from './shared/RadioButtonSelect.js'; import { useKeypress } from '../hooks/useKeypress.js'; +import { t } from '../../i18n/index.js'; interface WelcomeBackDialogProps { welcomeBackInfo: ProjectSummaryInfo; @@ -36,12 +37,12 @@ export function WelcomeBackDialog({ const options: Array> = [ { key: 'restart', - label: 'Start new chat session', + label: t('Start new chat session'), value: 'restart', }, { key: 'continue', - label: 'Continue previous conversation', + label: t('Continue previous conversation'), value: 'continue', }, ]; @@ -67,7 +68,9 @@ export function WelcomeBackDialog({ > - 👋 Welcome back! (Last updated: {timeAgo}) + {t('👋 Welcome back! (Last updated: {{timeAgo}})', { + timeAgo: timeAgo || '', + })} @@ -75,7 +78,7 @@ export function WelcomeBackDialog({ {goalContent && ( - 🎯 Overall Goal: + {t('🎯 Overall Goal:')} {goalContent} @@ -87,19 +90,25 @@ export function WelcomeBackDialog({ {totalTasks > 0 && ( - 📋 Current Plan: + 📋 {t('Current Plan:')} - Progress: {doneCount}/{totalTasks} tasks completed - {inProgressCount > 0 && `, ${inProgressCount} in progress`} + {t('Progress: {{done}}/{{total}} tasks completed', { + done: String(doneCount), + total: String(totalTasks), + })} + {inProgressCount > 0 && + t(', {{inProgress}} in progress', { + inProgress: String(inProgressCount), + })} {pendingTasks.length > 0 && ( - Pending Tasks: + {t('Pending Tasks:')} {pendingTasks.map((task: string, index: number) => ( @@ -113,8 +122,8 @@ export function WelcomeBackDialog({ {/* Action Selection */} - What would you like to do? - Choose how to proceed with your session: + {t('What would you like to do?')} + {t('Choose how to proceed with your session:')}