diff --git a/packages/cli/src/i18n/locales/en.js b/packages/cli/src/i18n/locales/en.js index 0898da3e..dce43bcb 100644 --- a/packages/cli/src/i18n/locales/en.js +++ b/packages/cli/src/i18n/locales/en.js @@ -95,12 +95,146 @@ export default { 'Show quit confirmation dialog': 'Show quit confirmation dialog', 'Copy the last result or code snippet to clipboard': 'Copy the last result or code snippet to clipboard', + + // ============================================================================ + // Commands - Agents + // ============================================================================ 'Manage subagents for specialized task delegation.': 'Manage subagents for specialized task delegation.', 'Manage existing subagents (view, edit, delete).': 'Manage existing subagents (view, edit, delete).', 'Create a new subagent with guided setup.': 'Create a new subagent with guided setup.', + + // ============================================================================ + // Agents - Management Dialog + // ============================================================================ + Agents: 'Agents', + 'Choose Action': 'Choose Action', + 'Edit {{name}}': 'Edit {{name}}', + 'Edit Tools: {{name}}': 'Edit Tools: {{name}}', + 'Edit Color: {{name}}': 'Edit Color: {{name}}', + 'Delete {{name}}': 'Delete {{name}}', + 'Unknown Step': 'Unknown Step', + 'Esc to close': 'Esc to close', + 'Enter to select, ↑↓ to navigate, Esc to close': + 'Enter to select, ↑↓ to navigate, Esc to close', + 'Esc to go back': 'Esc to go back', + 'Enter to confirm, Esc to cancel': 'Enter to confirm, Esc to cancel', + 'Enter to select, ↑↓ to navigate, Esc to go back': + 'Enter to select, ↑↓ to navigate, Esc to go back', + 'Invalid step: {{step}}': 'Invalid step: {{step}}', + 'No subagents found.': 'No subagents found.', + "Use '/agents create' to create your first subagent.": + "Use '/agents create' to create your first subagent.", + '(built-in)': '(built-in)', + '(overridden by project level agent)': '(overridden by project level agent)', + 'Project Level ({{path}})': 'Project Level ({{path}})', + 'User Level ({{path}})': 'User Level ({{path}})', + 'Built-in Agents': 'Built-in Agents', + 'Using: {{count}} agents': 'Using: {{count}} agents', + 'View Agent': 'View Agent', + 'Edit Agent': 'Edit Agent', + 'Delete Agent': 'Delete Agent', + Back: 'Back', + 'No agent selected': 'No agent selected', + 'File Path: ': 'File Path: ', + 'Tools: ': 'Tools: ', + 'Color: ': 'Color: ', + 'Description:': 'Description:', + 'System Prompt:': 'System Prompt:', + 'Open in editor': 'Open in editor', + 'Edit tools': 'Edit tools', + 'Edit color': 'Edit color', + '❌ Error:': '❌ Error:', + 'Are you sure you want to delete agent "{{name}}"?': + 'Are you sure you want to delete agent "{{name}}"?', + // ============================================================================ + // Agents - Creation Wizard + // ============================================================================ + 'Project Level (.qwen/agents/)': 'Project Level (.qwen/agents/)', + 'User Level (~/.qwen/agents/)': 'User Level (~/.qwen/agents/)', + '✅ Subagent Created Successfully!': '✅ Subagent Created Successfully!', + 'Subagent "{{name}}" has been saved to {{level}} level.': + 'Subagent "{{name}}" has been saved to {{level}} level.', + 'Name: ': 'Name: ', + 'Location: ': 'Location: ', + '❌ Error saving subagent:': '❌ Error saving subagent:', + 'Warnings:': 'Warnings:', + 'Name "{{name}}" already exists at {{level}} level - will overwrite existing subagent': + 'Name "{{name}}" already exists at {{level}} level - will overwrite existing subagent', + 'Name "{{name}}" exists at user level - project level will take precedence': + 'Name "{{name}}" exists at user level - project level will take precedence', + 'Name "{{name}}" exists at project level - existing subagent will take precedence': + 'Name "{{name}}" exists at project level - existing subagent will take precedence', + 'Description is over {{length}} characters': + 'Description is over {{length}} characters', + 'System prompt is over {{length}} characters': + 'System prompt is over {{length}} characters', + // Agents - Creation Wizard Steps + 'Step {{n}}: Choose Location': 'Step {{n}}: Choose Location', + 'Step {{n}}: Choose Generation Method': + 'Step {{n}}: Choose Generation Method', + 'Generate with Qwen Code (Recommended)': + 'Generate with Qwen Code (Recommended)', + 'Manual Creation': 'Manual Creation', + 'Describe what this subagent should do and when it should be used. (Be comprehensive for best results)': + 'Describe what this subagent should do and when it should be used. (Be comprehensive for best results)', + 'e.g., Expert code reviewer that reviews code based on best practices...': + 'e.g., Expert code reviewer that reviews code based on best practices...', + 'Generating subagent configuration...': + 'Generating subagent configuration...', + 'Failed to generate subagent: {{error}}': + 'Failed to generate subagent: {{error}}', + 'Step {{n}}: Describe Your Subagent': 'Step {{n}}: Describe Your Subagent', + 'Step {{n}}: Enter Subagent Name': 'Step {{n}}: Enter Subagent Name', + 'Step {{n}}: Enter System Prompt': 'Step {{n}}: Enter System Prompt', + 'Step {{n}}: Enter Description': 'Step {{n}}: Enter Description', + // Agents - Tool Selection + 'Step {{n}}: Select Tools': 'Step {{n}}: Select Tools', + 'All Tools (Default)': 'All Tools (Default)', + 'All Tools': 'All Tools', + 'Read-only Tools': 'Read-only Tools', + 'Read & Edit Tools': 'Read & Edit Tools', + 'Read & Edit & Execution Tools': 'Read & Edit & Execution Tools', + 'All tools selected, including MCP tools': + 'All tools selected, including MCP tools', + 'Selected tools:': 'Selected tools:', + 'Read-only tools:': 'Read-only tools:', + 'Edit tools:': 'Edit tools:', + 'Execution tools:': 'Execution tools:', + 'Step {{n}}: Choose Background Color': 'Step {{n}}: Choose Background Color', + 'Step {{n}}: Confirm and Save': 'Step {{n}}: Confirm and Save', + // Agents - Navigation & Instructions + 'Esc to cancel': 'Esc to cancel', + 'Press Enter to save, e to save and edit, Esc to go back': + 'Press Enter to save, e to save and edit, Esc to go back', + 'Press Enter to continue, {{navigation}}Esc to {{action}}': + 'Press Enter to continue, {{navigation}}Esc to {{action}}', + cancel: 'cancel', + 'go back': 'go back', + '↑↓ to navigate, ': '↑↓ to navigate, ', + 'Enter a clear, unique name for this subagent.': + 'Enter a clear, unique name for this subagent.', + 'e.g., Code Reviewer': 'e.g., Code Reviewer', + 'Name cannot be empty.': 'Name cannot be empty.', + "Write the system prompt that defines this subagent's behavior. Be comprehensive for best results.": + "Write the system prompt that defines this subagent's behavior. Be comprehensive for best results.", + 'e.g., You are an expert code reviewer...': + 'e.g., You are an expert code reviewer...', + 'System prompt cannot be empty.': 'System prompt cannot be empty.', + 'Describe when and how this subagent should be used.': + 'Describe when and how this subagent should be used.', + 'e.g., Reviews code for best practices and potential bugs.': + 'e.g., Reviews code for best practices and potential bugs.', + 'Description cannot be empty.': 'Description cannot be empty.', + 'Failed to launch editor: {{error}}': 'Failed to launch editor: {{error}}', + 'Failed to save and edit subagent: {{error}}': + 'Failed to save and edit subagent: {{error}}', + + // ============================================================================ + // Commands - General (continued) + // ============================================================================ 'View and edit Qwen Code settings': 'View and edit Qwen Code settings', 'toggle vim mode on/off': 'toggle vim mode on/off', 'check session stats. Usage: /stats [model|tools]': @@ -247,6 +381,9 @@ export default { 'Workspace approval mode exists and takes priority. User-level change will have no effect.', '(Use Enter to select, Tab to change focus)': '(Use Enter to select, Tab to change focus)', + 'Apply To': 'Apply To', + 'User Settings': 'User Settings', + 'Workspace Settings': 'Workspace Settings', // ============================================================================ // Commands - Memory diff --git a/packages/cli/src/i18n/locales/zh.js b/packages/cli/src/i18n/locales/zh.js index 5967e72a..539a012a 100644 --- a/packages/cli/src/i18n/locales/zh.js +++ b/packages/cli/src/i18n/locales/zh.js @@ -93,11 +93,139 @@ export default { 'Show quit confirmation dialog': '显示退出确认对话框', 'Copy the last result or code snippet to clipboard': '将最后的结果或代码片段复制到剪贴板', + + // ============================================================================ + // Commands - Agents + // ============================================================================ 'Manage subagents for specialized task delegation.': '管理用于专门任务委派的子代理', 'Manage existing subagents (view, edit, delete).': '管理现有子代理(查看、编辑、删除)', 'Create a new subagent with guided setup.': '通过引导式设置创建新的子代理', + + // ============================================================================ + // Agents - Management Dialog + // ============================================================================ + Agents: '代理', + 'Choose Action': '选择操作', + 'Edit {{name}}': '编辑 {{name}}', + 'Edit Tools: {{name}}': '编辑工具: {{name}}', + 'Edit Color: {{name}}': '编辑颜色: {{name}}', + 'Delete {{name}}': '删除 {{name}}', + 'Unknown Step': '未知步骤', + 'Esc to close': '按 Esc 关闭', + 'Enter to select, ↑↓ to navigate, Esc to close': + 'Enter 选择,↑↓ 导航,Esc 关闭', + 'Esc to go back': '按 Esc 返回', + 'Enter to confirm, Esc to cancel': 'Enter 确认,Esc 取消', + 'Enter to select, ↑↓ to navigate, Esc to go back': + 'Enter 选择,↑↓ 导航,Esc 返回', + 'Invalid step: {{step}}': '无效步骤: {{step}}', + 'No subagents found.': '未找到子代理。', + "Use '/agents create' to create your first subagent.": + "使用 '/agents create' 创建您的第一个子代理。", + '(built-in)': '(内置)', + '(overridden by project level agent)': '(已被项目级代理覆盖)', + 'Project Level ({{path}})': '项目级 ({{path}})', + 'User Level ({{path}})': '用户级 ({{path}})', + 'Built-in Agents': '内置代理', + 'Using: {{count}} agents': '使用中: {{count}} 个代理', + 'View Agent': '查看代理', + 'Edit Agent': '编辑代理', + 'Delete Agent': '删除代理', + Back: '返回', + 'No agent selected': '未选择代理', + 'File Path: ': '文件路径: ', + 'Tools: ': '工具: ', + 'Color: ': '颜色: ', + 'Description:': '描述:', + 'System Prompt:': '系统提示:', + 'Open in editor': '在编辑器中打开', + 'Edit tools': '编辑工具', + 'Edit color': '编辑颜色', + '❌ Error:': '❌ 错误:', + 'Are you sure you want to delete agent "{{name}}"?': + '您确定要删除代理 "{{name}}" 吗?', + // ============================================================================ + // Agents - Creation Wizard + // ============================================================================ + 'Project Level (.qwen/agents/)': '项目级 (.qwen/agents/)', + 'User Level (~/.qwen/agents/)': '用户级 (~/.qwen/agents/)', + '✅ Subagent Created Successfully!': '✅ 子代理创建成功!', + 'Subagent "{{name}}" has been saved to {{level}} level.': + '子代理 "{{name}}" 已保存到 {{level}} 级别。', + 'Name: ': '名称: ', + 'Location: ': '位置: ', + '❌ Error saving subagent:': '❌ 保存子代理时出错:', + 'Warnings:': '警告:', + 'Name "{{name}}" already exists at {{level}} level - will overwrite existing subagent': + '名称 "{{name}}" 在 {{level}} 级别已存在 - 将覆盖现有子代理', + 'Name "{{name}}" exists at user level - project level will take precedence': + '名称 "{{name}}" 在用户级别存在 - 项目级别将优先', + 'Name "{{name}}" exists at project level - existing subagent will take precedence': + '名称 "{{name}}" 在项目级别存在 - 现有子代理将优先', + 'Description is over {{length}} characters': '描述超过 {{length}} 个字符', + 'System prompt is over {{length}} characters': + '系统提示超过 {{length}} 个字符', + // Agents - Creation Wizard Steps + 'Step {{n}}: Choose Location': '步骤 {{n}}: 选择位置', + 'Step {{n}}: Choose Generation Method': '步骤 {{n}}: 选择生成方式', + 'Generate with Qwen Code (Recommended)': '使用 Qwen Code 生成(推荐)', + 'Manual Creation': '手动创建', + 'Describe what this subagent should do and when it should be used. (Be comprehensive for best results)': + '描述此子代理应该做什么以及何时使用它。(为了获得最佳效果,请全面描述)', + 'e.g., Expert code reviewer that reviews code based on best practices...': + '例如:专业的代码审查员,根据最佳实践审查代码...', + 'Generating subagent configuration...': '正在生成子代理配置...', + 'Failed to generate subagent: {{error}}': '生成子代理失败: {{error}}', + 'Step {{n}}: Describe Your Subagent': '步骤 {{n}}: 描述您的子代理', + 'Step {{n}}: Enter Subagent Name': '步骤 {{n}}: 输入子代理名称', + 'Step {{n}}: Enter System Prompt': '步骤 {{n}}: 输入系统提示', + 'Step {{n}}: Enter Description': '步骤 {{n}}: 输入描述', + // Agents - Tool Selection + 'Step {{n}}: Select Tools': '步骤 {{n}}: 选择工具', + 'All Tools (Default)': '所有工具(默认)', + 'All Tools': '所有工具', + 'Read-only Tools': '只读工具', + 'Read & Edit Tools': '读取和编辑工具', + 'Read & Edit & Execution Tools': '读取、编辑和执行工具', + 'All tools selected, including MCP tools': '已选择所有工具,包括 MCP 工具', + 'Selected tools:': '已选择的工具:', + 'Read-only tools:': '只读工具:', + 'Edit tools:': '编辑工具:', + 'Execution tools:': '执行工具:', + 'Step {{n}}: Choose Background Color': '步骤 {{n}}: 选择背景颜色', + 'Step {{n}}: Confirm and Save': '步骤 {{n}}: 确认并保存', + // Agents - Navigation & Instructions + 'Esc to cancel': '按 Esc 取消', + 'Press Enter to save, e to save and edit, Esc to go back': + '按 Enter 保存,e 保存并编辑,Esc 返回', + 'Press Enter to continue, {{navigation}}Esc to {{action}}': + '按 Enter 继续,{{navigation}}Esc {{action}}', + cancel: '取消', + 'go back': '返回', + '↑↓ to navigate, ': '↑↓ 导航,', + 'Enter a clear, unique name for this subagent.': + '为此子代理输入一个清晰、唯一的名称。', + 'e.g., Code Reviewer': '例如:代码审查员', + 'Name cannot be empty.': '名称不能为空。', + "Write the system prompt that defines this subagent's behavior. Be comprehensive for best results.": + '编写定义此子代理行为的系统提示。为了获得最佳效果,请全面描述。', + 'e.g., You are an expert code reviewer...': + '例如:您是一位专业的代码审查员...', + 'System prompt cannot be empty.': '系统提示不能为空。', + 'Describe when and how this subagent should be used.': + '描述何时以及如何使用此子代理。', + 'e.g., Reviews code for best practices and potential bugs.': + '例如:审查代码以查找最佳实践和潜在错误。', + 'Description cannot be empty.': '描述不能为空。', + 'Failed to launch editor: {{error}}': '启动编辑器失败: {{error}}', + 'Failed to save and edit subagent: {{error}}': + '保存并编辑子代理失败: {{error}}', + + // ============================================================================ + // Commands - General (continued) + // ============================================================================ 'View and edit Qwen Code settings': '查看和编辑 Qwen Code 设置', 'toggle vim mode on/off': '切换 vim 模式开关', 'check session stats. Usage: /stats [model|tools]': @@ -232,6 +360,9 @@ export default { '工作区审批模式已存在并具有优先级。用户级别的更改将无效。', '(Use Enter to select, Tab to change focus)': '(使用 Enter 选择,Tab 切换焦点)', + 'Apply To': '应用于', + 'User Settings': '用户设置', + 'Workspace Settings': '工作区设置', // ============================================================================ // Commands - Memory @@ -454,7 +585,7 @@ export default { // ============================================================================ 'Get started': '开始使用', 'How would you like to authenticate for this project?': - '您想如何为此项目进行认证?', + '您希望如何为此项目进行身份验证?', 'OpenAI API key is required to use OpenAI authentication.': '使用 OpenAI 认证需要 OpenAI API 密钥', 'You must select an auth method to proceed. Press Ctrl+C again to exit.': @@ -462,8 +593,8 @@ export default { '(Use Enter to Set Auth)': '(使用 Enter 设置认证)', 'Terms of Services and Privacy Notice for Qwen Code': 'Qwen Code 的服务条款和隐私声明', - 'Qwen OAuth': 'Qwen OAuth', - OpenAI: 'OpenAI', + 'Qwen OAuth': 'Qwen OAuth (推荐)', + OpenAI: 'OpenAI (兼容 API)', 'Failed to login. Message: {{message}}': '登录失败。消息:{{message}}', 'Authentication is enforced to be {{enforcedType}}, but you are currently using {{currentType}}.': '认证方式被强制设置为 {{enforcedType}},但您当前使用的是 {{currentType}}', diff --git a/packages/cli/src/ui/components/EditorSettingsDialog.tsx b/packages/cli/src/ui/components/EditorSettingsDialog.tsx index d81ffad6..6926bf41 100644 --- a/packages/cli/src/ui/components/EditorSettingsDialog.tsx +++ b/packages/cli/src/ui/components/EditorSettingsDialog.tsx @@ -19,6 +19,7 @@ import { SettingScope } from '../../config/settings.js'; import type { EditorType } from '@qwen-code/qwen-code-core'; import { isEditorAvailable } from '@qwen-code/qwen-code-core'; import { useKeypress } from '../hooks/useKeypress.js'; +import { t } from '../../i18n/index.js'; interface EditorDialogProps { onSelect: (editorType: EditorType | undefined, scope: SettingScope) => void; @@ -66,12 +67,16 @@ export function EditorSettingsDialog({ const scopeItems = [ { - label: 'User Settings', + get label() { + return t('User Settings'); + }, value: SettingScope.User, key: SettingScope.User, }, { - label: 'Workspace Settings', + get label() { + return t('Workspace Settings'); + }, value: SettingScope.Workspace, key: SettingScope.Workspace, }, @@ -145,7 +150,8 @@ export function EditorSettingsDialog({ - {focusedSection === 'scope' ? '> ' : ' '}Apply To + {focusedSection === 'scope' ? '> ' : ' '} + {t('Apply To')} ({ ...item, + label: t(item.label), key: item.value, })); @@ -40,7 +42,8 @@ export function ScopeSelector({ return ( - {isFocused ? '> ' : ' '}Apply To + {isFocused ? '> ' : ' '} + {t('Apply To')} void; @@ -90,25 +91,25 @@ export function AgentCreationWizard({ const n = state.currentStep; switch (kind) { case 'LOCATION': - return `Step ${n}: Choose Location`; + return t('Step {{n}}: Choose Location', { n: n.toString() }); case 'GEN_METHOD': - return `Step ${n}: Choose Generation Method`; + return t('Step {{n}}: Choose Generation Method', { n: n.toString() }); case 'LLM_DESC': - return `Step ${n}: Describe Your Subagent`; + return t('Step {{n}}: Describe Your Subagent', { n: n.toString() }); case 'MANUAL_NAME': - return `Step ${n}: Enter Subagent Name`; + return t('Step {{n}}: Enter Subagent Name', { n: n.toString() }); case 'MANUAL_PROMPT': - return `Step ${n}: Enter System Prompt`; + return t('Step {{n}}: Enter System Prompt', { n: n.toString() }); case 'MANUAL_DESC': - return `Step ${n}: Enter Description`; + return t('Step {{n}}: Enter Description', { n: n.toString() }); case 'TOOLS': - return `Step ${n}: Select Tools`; + return t('Step {{n}}: Select Tools', { n: n.toString() }); case 'COLOR': - return `Step ${n}: Choose Background Color`; + return t('Step {{n}}: Choose Background Color', { n: n.toString() }); case 'FINAL': - return `Step ${n}: Confirm and Save`; + return t('Step {{n}}: Confirm and Save', { n: n.toString() }); default: - return 'Unknown Step'; + return t('Unknown Step'); } }; @@ -163,11 +164,11 @@ export function AgentCreationWizard({ // Special case: During generation in description input step, only show cancel option const kind = getStepKind(state.generationMethod, state.currentStep); if (kind === 'LLM_DESC' && state.isGenerating) { - return 'Esc to cancel'; + return t('Esc to cancel'); } if (getStepKind(state.generationMethod, state.currentStep) === 'FINAL') { - return 'Press Enter to save, e to save and edit, Esc to go back'; + return t('Press Enter to save, e to save and edit, Esc to go back'); } // Steps that have ↑↓ navigation (RadioButtonSelect components) @@ -177,14 +178,17 @@ export function AgentCreationWizard({ kindForNav === 'GEN_METHOD' || kindForNav === 'TOOLS' || kindForNav === 'COLOR'; - const navigationPart = hasNavigation ? '↑↓ to navigate, ' : ''; + const navigationPart = hasNavigation ? t('↑↓ to navigate, ') : ''; const escAction = state.currentStep === WIZARD_STEPS.LOCATION_SELECTION - ? 'cancel' - : 'go back'; + ? t('cancel') + : t('go back'); - return `Press Enter to continue, ${navigationPart}Esc to ${escAction}`; + return t('Press Enter to continue, {{navigation}}Esc to {{action}}', { + navigation: navigationPart, + action: escAction, + }); }; return ( @@ -210,16 +214,16 @@ export function AgentCreationWizard({ state={state} dispatch={dispatch} onNext={handleNext} - description="Enter a clear, unique name for this subagent." - placeholder="e.g., Code Reviewer" + description={t('Enter a clear, unique name for this subagent.')} + placeholder={t('e.g., Code Reviewer')} height={1} initialText={state.generatedName} - onChange={(t) => { - const value = t; // keep raw, trim later when validating + onChange={(text) => { + const value = text; // keep raw, trim later when validating dispatch({ type: 'SET_GENERATED_NAME', name: value }); }} - validate={(t) => - t.trim().length === 0 ? 'Name cannot be empty.' : null + validate={(text) => + text.trim().length === 0 ? t('Name cannot be empty.') : null } /> ); @@ -230,18 +234,22 @@ export function AgentCreationWizard({ state={state} dispatch={dispatch} onNext={handleNext} - description="Write the system prompt that defines this subagent's behavior. Be comprehensive for best results." - placeholder="e.g., You are an expert code reviewer..." + description={t( + "Write the system prompt that defines this subagent's behavior. Be comprehensive for best results.", + )} + placeholder={t('e.g., You are an expert code reviewer...')} height={10} initialText={state.generatedSystemPrompt} - onChange={(t) => { + onChange={(text) => { dispatch({ type: 'SET_GENERATED_SYSTEM_PROMPT', - systemPrompt: t, + systemPrompt: text, }); }} - validate={(t) => - t.trim().length === 0 ? 'System prompt cannot be empty.' : null + validate={(text) => + text.trim().length === 0 + ? t('System prompt cannot be empty.') + : null } /> ); @@ -252,15 +260,24 @@ export function AgentCreationWizard({ state={state} dispatch={dispatch} onNext={handleNext} - description="Describe when and how this subagent should be used." - placeholder="e.g., Reviews code for best practices and potential bugs." + description={t( + 'Describe when and how this subagent should be used.', + )} + placeholder={t( + 'e.g., Reviews code for best practices and potential bugs.', + )} height={6} initialText={state.generatedDescription} - onChange={(t) => { - dispatch({ type: 'SET_GENERATED_DESCRIPTION', description: t }); + onChange={(text) => { + dispatch({ + type: 'SET_GENERATED_DESCRIPTION', + description: text, + }); }} - validate={(t) => - t.trim().length === 0 ? 'Description cannot be empty.' : null + validate={(text) => + text.trim().length === 0 + ? t('Description cannot be empty.') + : null } /> ); @@ -292,7 +309,9 @@ export function AgentCreationWizard({ return ( - Invalid step: {state.currentStep} + {t('Invalid step: {{step}}', { + step: state.currentStep.toString(), + })} ); diff --git a/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx b/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx index 9a8cd81a..f9174b66 100644 --- a/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx +++ b/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx @@ -15,6 +15,7 @@ import { theme } from '../../../semantic-colors.js'; import { shouldShowColor, getColorForDisplay } from '../utils.js'; import { useLaunchEditor } from '../../../hooks/useLaunchEditor.js'; import { useKeypress } from '../../../hooks/useKeypress.js'; +import { t } from '../../../../i18n/index.js'; /** * Step 6: Final confirmation and actions. @@ -62,15 +63,24 @@ export function CreationSummary({ if (conflictLevel === targetLevel) { allWarnings.push( - `Name "${state.generatedName}" already exists at ${conflictLevel} level - will overwrite existing subagent`, + t( + 'Name "{{name}}" already exists at {{level}} level - will overwrite existing subagent', + { name: state.generatedName, level: conflictLevel }, + ), ); } else if (targetLevel === 'project') { allWarnings.push( - `Name "${state.generatedName}" exists at user level - project level will take precedence`, + t( + 'Name "{{name}}" exists at user level - project level will take precedence', + { name: state.generatedName }, + ), ); } else { allWarnings.push( - `Name "${state.generatedName}" exists at project level - existing subagent will take precedence`, + t( + 'Name "{{name}}" exists at project level - existing subagent will take precedence', + { name: state.generatedName }, + ), ); } } @@ -83,12 +93,16 @@ export function CreationSummary({ // Check length warnings if (state.generatedDescription.length > 300) { allWarnings.push( - `Description is over ${state.generatedDescription.length} characters`, + t('Description is over {{length}} characters', { + length: state.generatedDescription.length.toString(), + }), ); } if (state.generatedSystemPrompt.length > 10000) { allWarnings.push( - `System prompt is over ${state.generatedSystemPrompt.length} characters`, + t('System prompt is over {{length}} characters', { + length: state.generatedSystemPrompt.length.toString(), + }), ); } @@ -181,7 +195,9 @@ export function CreationSummary({ showSuccessAndClose(); } catch (error) { setSaveError( - `Failed to save and edit subagent: ${error instanceof Error ? error.message : 'Unknown error'}`, + t('Failed to save and edit subagent: {{error}}', { + error: error instanceof Error ? error.message : 'Unknown error', + }), ); } }, [ @@ -215,13 +231,15 @@ export function CreationSummary({ - ✅ Subagent Created Successfully! + {t('✅ Subagent Created Successfully!')} - Subagent "{state.generatedName}" has been saved to{' '} - {state.location} level. + {t('Subagent "{{name}}" has been saved to {{level}} level.', { + name: state.generatedName, + level: state.location, + })} @@ -232,35 +250,35 @@ export function CreationSummary({ - Name: + {t('Name: ')} {state.generatedName} - Location: + {t('Location: ')} {state.location === 'project' - ? 'Project Level (.qwen/agents/)' - : 'User Level (~/.qwen/agents/)'} + ? t('Project Level (.qwen/agents/)') + : t('User Level (~/.qwen/agents/)')} - Tools: + {t('Tools: ')} {toolsDisplay} {shouldShowColor(state.color) && ( - Color: + {t('Color: ')} {state.color} )} - Description: + {t('Description:')} @@ -269,7 +287,7 @@ export function CreationSummary({ - System Prompt: + {t('System Prompt:')} @@ -281,7 +299,7 @@ export function CreationSummary({ {saveError && ( - ❌ Error saving subagent: + {t('❌ Error saving subagent:')} @@ -294,7 +312,7 @@ export function CreationSummary({ {warnings.length > 0 && ( - Warnings: + {t('Warnings:')} {warnings.map((warning, index) => ( diff --git a/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx b/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx index d81cafb2..4e7f4491 100644 --- a/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx +++ b/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx @@ -14,6 +14,7 @@ import { useKeypress, type Key } from '../../../hooks/useKeypress.js'; import { keyMatchers, Command } from '../../../keyMatchers.js'; import { theme } from '../../../semantic-colors.js'; import { TextInput } from '../../shared/TextInput.js'; +import { t } from '../../../../i18n/index.js'; /** * Step 3: Description input with LLM generation. @@ -103,7 +104,9 @@ export function DescriptionInput({ dispatch({ type: 'SET_VALIDATION_ERRORS', errors: [ - `Failed to generate subagent: ${error instanceof Error ? error.message : 'Unknown error'}`, + t('Failed to generate subagent: {{error}}', { + error: error instanceof Error ? error.message : 'Unknown error', + }), ], }); } @@ -135,15 +138,17 @@ export function DescriptionInput({ isActive: state.isGenerating, }); - const placeholder = - 'e.g., Expert code reviewer that reviews code based on best practices...'; + const placeholder = t( + 'e.g., Expert code reviewer that reviews code based on best practices...', + ); return ( - Describe what this subagent should do and when it should be used. (Be - comprehensive for best results) + {t( + 'Describe what this subagent should do and when it should be used. (Be comprehensive for best results)', + )} @@ -153,7 +158,7 @@ export function DescriptionInput({ - Generating subagent configuration... + {t('Generating subagent configuration...')} ) : ( diff --git a/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx b/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx index 0018e8bd..b7f111e6 100644 --- a/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx @@ -7,6 +7,7 @@ import { Box } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; import type { WizardStepProps } from '../types.js'; +import { t } from '../../../../i18n/index.js'; interface GenerationOption { label: string; @@ -15,11 +16,15 @@ interface GenerationOption { const generationOptions: GenerationOption[] = [ { - label: 'Generate with Qwen Code (Recommended)', + get label() { + return t('Generate with Qwen Code (Recommended)'); + }, value: 'qwen', }, { - label: 'Manual Creation', + get label() { + return t('Manual Creation'); + }, value: 'manual', }, ]; diff --git a/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx b/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx index 51601730..aad81c3a 100644 --- a/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx @@ -7,6 +7,7 @@ import { Box } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; import type { WizardStepProps } from '../types.js'; +import { t } from '../../../../i18n/index.js'; interface LocationOption { label: string; @@ -15,11 +16,15 @@ interface LocationOption { const locationOptions: LocationOption[] = [ { - label: 'Project Level (.qwen/agents/)', + get label() { + return t('Project Level (.qwen/agents/)'); + }, value: 'project', }, { - label: 'User Level (~/.qwen/agents/)', + get label() { + return t('User Level (~/.qwen/agents/)'); + }, value: 'user', }, ]; diff --git a/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx b/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx index ccea5b61..547e14ed 100644 --- a/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx @@ -10,6 +10,7 @@ import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; import type { ToolCategory } from '../types.js'; import { Kind, type Config } from '@qwen-code/qwen-code-core'; import { theme } from '../../../semantic-colors.js'; +import { t } from '../../../../i18n/index.js'; interface ToolOption { label: string; @@ -45,7 +46,7 @@ export function ToolSelector({ toolCategories: [ { id: 'all', - name: 'All Tools (Default)', + name: t('All Tools (Default)'), tools: [], }, ], @@ -89,22 +90,22 @@ export function ToolSelector({ const toolCategories = [ { id: 'all', - name: 'All Tools', + name: t('All Tools'), tools: [], }, { id: 'read', - name: 'Read-only Tools', + name: t('Read-only Tools'), tools: readTools, }, { id: 'edit', - name: 'Read & Edit Tools', + name: t('Read & Edit Tools'), tools: [...readTools, ...editTools], }, { id: 'execute', - name: 'Read & Edit & Execution Tools', + name: t('Read & Edit & Execution Tools'), tools: [...readTools, ...editTools, ...executeTools], }, ].filter((category) => category.id === 'all' || category.tools.length > 0); @@ -202,11 +203,11 @@ export function ToolSelector({ {currentCategory.id === 'all' ? ( - All tools selected, including MCP tools + {t('All tools selected, including MCP tools')} ) : currentCategory.tools.length > 0 ? ( <> - Selected tools: + {t('Selected tools:')} {(() => { // Filter the already categorized tools to show only those in current category @@ -224,17 +225,19 @@ export function ToolSelector({ <> {categoryReadTools.length > 0 && ( - • Read-only tools: {categoryReadTools.join(', ')} + • {t('Read-only tools:')}{' '} + {categoryReadTools.join(', ')} )} {categoryEditTools.length > 0 && ( - • Edit tools: {categoryEditTools.join(', ')} + • {t('Edit tools:')} {categoryEditTools.join(', ')} )} {categoryExecuteTools.length > 0 && ( - • Execution tools: {categoryExecuteTools.join(', ')} + • {t('Execution tools:')}{' '} + {categoryExecuteTools.join(', ')} )} diff --git a/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx b/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx index c0a6b5a9..28393d08 100644 --- a/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx @@ -9,6 +9,7 @@ import { Box } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; import { MANAGEMENT_STEPS } from '../types.js'; import { type SubagentConfig } from '@qwen-code/qwen-code-core'; +import { t } from '../../../../i18n/index.js'; interface ActionSelectionStepProps { selectedAgent: SubagentConfig | null; @@ -27,10 +28,34 @@ export const ActionSelectionStep = ({ // Filter actions based on whether the agent is built-in const allActions = [ - { key: 'view', label: 'View Agent', value: 'view' as const }, - { key: 'edit', label: 'Edit Agent', value: 'edit' as const }, - { key: 'delete', label: 'Delete Agent', value: 'delete' as const }, - { key: 'back', label: 'Back', value: 'back' as const }, + { + key: 'view', + get label() { + return t('View Agent'); + }, + value: 'view' as const, + }, + { + key: 'edit', + get label() { + return t('Edit Agent'); + }, + value: 'edit' as const, + }, + { + key: 'delete', + get label() { + return t('Delete Agent'); + }, + value: 'delete' as const, + }, + { + key: 'back', + get label() { + return t('Back'); + }, + value: 'back' as const, + }, ]; const actions = selectedAgent?.isBuiltin diff --git a/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx index 245d348e..77cfa47d 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx @@ -9,6 +9,7 @@ import { type SubagentConfig } from '@qwen-code/qwen-code-core'; import type { StepNavigationProps } from '../types.js'; import { theme } from '../../../semantic-colors.js'; import { useKeypress } from '../../../hooks/useKeypress.js'; +import { t } from '../../../../i18n/index.js'; interface AgentDeleteStepProps extends StepNavigationProps { selectedAgent: SubagentConfig | null; @@ -41,7 +42,7 @@ export function AgentDeleteStep({ if (!selectedAgent) { return ( - No agent selected + {t('No agent selected')} ); } @@ -49,8 +50,9 @@ export function AgentDeleteStep({ return ( - Are you sure you want to delete agent “{selectedAgent.name} - ”? + {t('Are you sure you want to delete agent "{{name}}"?', { + name: selectedAgent.name, + })} ); diff --git a/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx index 4037dff1..ab1cd2a9 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx @@ -11,6 +11,7 @@ import { MANAGEMENT_STEPS } from '../types.js'; import { theme } from '../../../semantic-colors.js'; import { useLaunchEditor } from '../../../hooks/useLaunchEditor.js'; import { type SubagentConfig } from '@qwen-code/qwen-code-core'; +import { t } from '../../../../i18n/index.js'; interface EditOption { id: string; @@ -20,15 +21,21 @@ interface EditOption { const editOptions: EditOption[] = [ { id: 'editor', - label: 'Open in editor', + get label() { + return t('Open in editor'); + }, }, { id: 'tools', - label: 'Edit tools', + get label() { + return t('Edit tools'); + }, }, { id: 'color', - label: 'Edit color', + get label() { + return t('Edit color'); + }, }, ]; @@ -65,7 +72,9 @@ export function EditOptionsStep({ await launchEditor(selectedAgent?.filePath); } catch (err) { setError( - `Failed to launch editor: ${err instanceof Error ? err.message : 'Unknown error'}`, + t('Failed to launch editor: {{error}}', { + error: err instanceof Error ? err.message : 'Unknown error', + }), ); } } else if (selectedValue === 'tools') { @@ -98,7 +107,7 @@ export function EditOptionsStep({ {error && ( - ❌ Error: + {t('❌ Error:')} diff --git a/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx index 73076163..613ac87e 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx @@ -9,6 +9,7 @@ import { Box, Text } from 'ink'; import { theme } from '../../../semantic-colors.js'; import { useKeypress } from '../../../hooks/useKeypress.js'; import { type SubagentConfig } from '@qwen-code/qwen-code-core'; +import { t } from '../../../../i18n/index.js'; interface NavigationState { currentBlock: 'project' | 'user' | 'builtin'; @@ -205,9 +206,9 @@ export const AgentSelectionStep = ({ if (availableAgents.length === 0) { return ( - No subagents found. + {t('No subagents found.')} - Use '/agents create' to create your first subagent. + {t("Use '/agents create' to create your first subagent.")} ); @@ -237,7 +238,7 @@ export const AgentSelectionStep = ({ {agent.isBuiltin && ( {' '} - (built-in) + {t('(built-in)')} )} {agent.level === 'user' && projectNames.has(agent.name) && ( @@ -245,7 +246,7 @@ export const AgentSelectionStep = ({ color={isSelected ? theme.status.warning : theme.text.secondary} > {' '} - (overridden by project level agent) + {t('(overridden by project level agent)')} )} @@ -265,7 +266,9 @@ export const AgentSelectionStep = ({ {projectAgents.length > 0 && ( - Project Level ({projectAgents[0].filePath.replace(/\/[^/]+$/, '')}) + {t('Project Level ({{path}})', { + path: projectAgents[0].filePath.replace(/\/[^/]+$/, ''), + })} {projectAgents.map((agent, index) => { @@ -285,7 +288,9 @@ export const AgentSelectionStep = ({ marginBottom={builtinAgents.length > 0 ? 1 : 0} > - User Level ({userAgents[0].filePath.replace(/\/[^/]+$/, '')}) + {t('User Level ({{path}})', { + path: userAgents[0].filePath.replace(/\/[^/]+$/, ''), + })} {userAgents.map((agent, index) => { @@ -302,7 +307,7 @@ export const AgentSelectionStep = ({ {builtinAgents.length > 0 && ( - Built-in Agents + {t('Built-in Agents')} {builtinAgents.map((agent, index) => { @@ -321,7 +326,9 @@ export const AgentSelectionStep = ({ builtinAgents.length > 0) && ( - Using: {enabledAgentsCount} agents + {t('Using: {{count}} agents', { + count: enabledAgentsCount.toString(), + })} )} diff --git a/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx index 8f5fd2dd..ee2fd366 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx @@ -8,6 +8,7 @@ import { Box, Text } from 'ink'; import { theme } from '../../../semantic-colors.js'; import { shouldShowColor, getColorForDisplay } from '../utils.js'; import { type SubagentConfig } from '@qwen-code/qwen-code-core'; +import { t } from '../../../../i18n/index.js'; interface AgentViewerStepProps { selectedAgent: SubagentConfig | null; @@ -17,7 +18,7 @@ export const AgentViewerStep = ({ selectedAgent }: AgentViewerStepProps) => { if (!selectedAgent) { return ( - No agent selected + {t('No agent selected')} ); } @@ -30,31 +31,31 @@ export const AgentViewerStep = ({ selectedAgent }: AgentViewerStepProps) => { - File Path: + {t('File Path: ')} {agent.filePath} - Tools: + {t('Tools: ')} {toolsDisplay} {shouldShowColor(agent.color) && ( - Color: + {t('Color: ')} {agent.color} )} - Description: + {t('Description:')} {agent.description} - System Prompt: + {t('System Prompt:')} {agent.systemPrompt} diff --git a/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx b/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx index 5a775001..f496d6bc 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx @@ -18,6 +18,7 @@ import { theme } from '../../../semantic-colors.js'; import { getColorForDisplay, shouldShowColor } from '../utils.js'; import type { SubagentConfig, Config } from '@qwen-code/qwen-code-core'; import { useKeypress } from '../../../hooks/useKeypress.js'; +import { t } from '../../../../i18n/index.js'; interface AgentsManagerDialogProps { onClose: () => void; @@ -143,21 +144,21 @@ export function AgentsManagerDialog({ const getStepHeaderText = () => { switch (currentStep) { case MANAGEMENT_STEPS.AGENT_SELECTION: - return 'Agents'; + return t('Agents'); case MANAGEMENT_STEPS.ACTION_SELECTION: - return 'Choose Action'; + return t('Choose Action'); case MANAGEMENT_STEPS.AGENT_VIEWER: return selectedAgent?.name; case MANAGEMENT_STEPS.EDIT_OPTIONS: - return `Edit ${selectedAgent?.name}`; + return t('Edit {{name}}', { name: selectedAgent?.name || '' }); case MANAGEMENT_STEPS.EDIT_TOOLS: - return `Edit Tools: ${selectedAgent?.name}`; + return t('Edit Tools: {{name}}', { name: selectedAgent?.name || '' }); case MANAGEMENT_STEPS.EDIT_COLOR: - return `Edit Color: ${selectedAgent?.name}`; + return t('Edit Color: {{name}}', { name: selectedAgent?.name || '' }); case MANAGEMENT_STEPS.DELETE_CONFIRMATION: - return `Delete ${selectedAgent?.name}`; + return t('Delete {{name}}', { name: selectedAgent?.name || '' }); default: - return 'Unknown Step'; + return t('Unknown Step'); } }; @@ -183,20 +184,20 @@ export function AgentsManagerDialog({ const getNavigationInstructions = () => { if (currentStep === MANAGEMENT_STEPS.AGENT_SELECTION) { if (availableAgents.length === 0) { - return 'Esc to close'; + return t('Esc to close'); } - return 'Enter to select, ↑↓ to navigate, Esc to close'; + return t('Enter to select, ↑↓ to navigate, Esc to close'); } if (currentStep === MANAGEMENT_STEPS.AGENT_VIEWER) { - return 'Esc to go back'; + return t('Esc to go back'); } if (currentStep === MANAGEMENT_STEPS.DELETE_CONFIRMATION) { - return 'Enter to confirm, Esc to cancel'; + return t('Enter to confirm, Esc to cancel'); } - return 'Enter to select, ↑↓ to navigate, Esc to go back'; + return t('Enter to select, ↑↓ to navigate, Esc to go back'); }; return ( @@ -295,7 +296,9 @@ export function AgentsManagerDialog({ default: return ( - Invalid step: {currentStep} + + {t('Invalid step: {{step}}', { step: currentStep })} + ); }