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:')}