mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-09 17:19:02 +00:00
fix(web-shell): localize remaining hardcoded UI strings (#5189)
Route the last few hardcoded English strings in web-shell through the existing useI18n()/t() layer and add matching en / zh-CN keys: - close-button tooltips across 9 dialogs - the history-search label, placeholder and key hint in the editor - icon-button aria-labels (toast dismiss, thinking toggle, sub-agent stream toggle), which also improves screen-reader support No new i18n infrastructure; follows the existing pattern used by the same components. Co-authored-by: qingyu <qingyu@taobao.com> Co-authored-by: 易良 <1204183885@qq.com>
This commit is contained in:
parent
ccf1e5672f
commit
6fbcf802a8
13 changed files with 33 additions and 17 deletions
|
|
@ -1934,18 +1934,18 @@ export const Editor = forwardRef<EditorHandle, EditorProps>(function Editor(
|
|||
{searchMode && (
|
||||
<div ref={searchUiRef}>
|
||||
<div className={styles.searchBar}>
|
||||
<span className={styles.searchLabel}>reverse-i-search:</span>
|
||||
<span className={styles.searchLabel}>
|
||||
{t('editor.searchLabel')}
|
||||
</span>
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
className={styles.searchInput}
|
||||
value={searchQuery}
|
||||
onChange={handleSearchInput}
|
||||
onKeyDown={handleSearchKeyDown}
|
||||
placeholder="type to search..."
|
||||
placeholder={t('editor.searchPlaceholder')}
|
||||
/>
|
||||
<span className={styles.searchHint}>
|
||||
ctrl+r next · tab accept · enter send · esc cancel
|
||||
</span>
|
||||
<span className={styles.searchHint}>{t('editor.searchHint')}</span>
|
||||
</div>
|
||||
{searchMatches.length > 0 && (
|
||||
<div className={styles.searchResults}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useEffect } from 'react';
|
||||
import { useI18n } from '../i18n';
|
||||
import styles from './ToastHost.module.css';
|
||||
|
||||
export type ToastTone = 'info' | 'warning' | 'error' | 'success';
|
||||
|
|
@ -44,6 +45,7 @@ function ToastItem({
|
|||
onDismiss: (id: string) => void;
|
||||
autoDismissMs: number;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
useEffect(() => {
|
||||
const timer = window.setTimeout(() => onDismiss(toast.id), autoDismissMs);
|
||||
return () => window.clearTimeout(timer);
|
||||
|
|
@ -56,8 +58,8 @@ function ToastItem({
|
|||
type="button"
|
||||
className={styles.close}
|
||||
onClick={() => onDismiss(toast.id)}
|
||||
aria-label="Dismiss notification"
|
||||
title="Dismiss"
|
||||
aria-label={t('toast.dismiss')}
|
||||
title={t('toast.dismissShort')}
|
||||
>
|
||||
x
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export function ApprovalModeDialog({
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ export function DeleteSessionDialog({
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ export function HelpDialog({ commands, onClose }: HelpDialogProps) {
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ export function McpDialog({ onClose }: McpDialogProps) {
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ export function MemoryDialog({
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ export function ReleaseSessionDialog({
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ export function ResumeDialog({ onSelect, onClose }: ResumeDialogProps) {
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export function SkillsDialog({ onClose }: SkillsDialogProps) {
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export function ThemeDialog({
|
|||
<button
|
||||
className={dp('resume-picker-close')}
|
||||
onClick={onClose}
|
||||
title="Close"
|
||||
title={t('common.close')}
|
||||
>
|
||||
ESC
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from 'react';
|
||||
import type { ACPToolCall } from '../../../adapters/types';
|
||||
import { useWebShellCustomization } from '../../../customization';
|
||||
import { useI18n } from '../../../i18n';
|
||||
// Circular import with ToolGroup (agents render tool rows; agent tool
|
||||
// rows render SubAgentPanel). Safe only while both modules dereference
|
||||
// each other's exports at render time — never in top-level code.
|
||||
|
|
@ -159,6 +160,7 @@ type SubAgentTab = 'result' | 'tools';
|
|||
*/
|
||||
function SubAgentStream({ text }: { text: string }) {
|
||||
const { compactThinking } = useWebShellCustomization();
|
||||
const { t } = useI18n();
|
||||
const [streamExpanded, setStreamExpanded] = useState(false);
|
||||
const [overflowing, setOverflowing] = useState(false);
|
||||
const streamRef = useRef<HTMLPreElement>(null);
|
||||
|
|
@ -199,7 +201,7 @@ function SubAgentStream({ text }: { text: string }) {
|
|||
className={styles.expandToggle}
|
||||
onClick={() => setStreamExpanded((v) => !v)}
|
||||
aria-expanded={streamExpanded}
|
||||
aria-label="Toggle agent stream details"
|
||||
aria-label={t('subagent.toggleStream')}
|
||||
>
|
||||
{streamExpanded ? '▲' : '▼'}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ const EN: Messages = {
|
|||
'agent.view': 'View',
|
||||
'agents.closed': 'Agents panel closed.',
|
||||
'agents.title': 'Agents',
|
||||
'subagent.toggleStream': 'Toggle agent stream details',
|
||||
'toast.dismiss': 'Dismiss notification',
|
||||
'toast.dismissShort': 'Dismiss',
|
||||
'insight.ready': 'Insight report generated successfully!',
|
||||
'request.cancelled': 'Request cancelled.',
|
||||
'approval.execQuestion': (v) => `Allow execution of: '${v?.tool ?? ''}'?`,
|
||||
|
|
@ -306,6 +309,9 @@ const EN: Messages = {
|
|||
'editor.noHistory': 'No matching history',
|
||||
'editor.placeholder': 'Type a message or @ file path',
|
||||
'editor.processing': 'Processing. New messages will be queued.',
|
||||
'editor.searchHint': 'ctrl+r next · tab accept · enter send · esc cancel',
|
||||
'editor.searchLabel': 'reverse-i-search:',
|
||||
'editor.searchPlaceholder': 'type to search...',
|
||||
'error.unsupportedTheme':
|
||||
'Unsupported theme. Use /theme light or /theme dark.',
|
||||
'queue.cleared': 'Queued messages cleared',
|
||||
|
|
@ -1020,6 +1026,9 @@ const ZH: Messages = {
|
|||
'agent.view': '查看',
|
||||
'agents.closed': '智能体面板已关闭。',
|
||||
'agents.title': '智能体',
|
||||
'subagent.toggleStream': '展开/收起子智能体详情',
|
||||
'toast.dismiss': '关闭通知',
|
||||
'toast.dismissShort': '关闭',
|
||||
'insight.ready': 'Insight 报告已生成!',
|
||||
'request.cancelled': '请求已取消。',
|
||||
'approval.execQuestion': (v) => `允许执行:'${v?.tool ?? ''}'?`,
|
||||
|
|
@ -1151,6 +1160,9 @@ const ZH: Messages = {
|
|||
'editor.noHistory': '没有匹配的历史记录',
|
||||
'editor.placeholder': '输入消息或 @ 文件路径',
|
||||
'editor.processing': '处理中。新消息会进入队列。',
|
||||
'editor.searchHint': 'ctrl+r 下一条 · tab 采纳 · enter 发送 · esc 取消',
|
||||
'editor.searchLabel': '历史搜索:',
|
||||
'editor.searchPlaceholder': '输入以搜索…',
|
||||
'error.unsupportedTheme':
|
||||
'不支持该主题。请使用 /theme light 或 /theme dark。',
|
||||
'queue.cleared': '已清空排队消息',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue