From 4c5421a7af894d380398b91ed6c06929e62d1117 Mon Sep 17 00:00:00 2001 From: ChangeHow Date: Thu, 30 Jul 2026 11:10:59 +0800 Subject: [PATCH] feat(ui): redesign shortcut settings --- .../openchamber/KeyboardShortcutsSettings.tsx | 396 +++++------------- .../openchamber/ShortcutRecordingDialog.tsx | 209 +++++++++ packages/ui/src/components/ui/HelpDialog.tsx | 105 +++-- .../ui/src/lib/i18n/messages/en.settings.ts | 22 +- .../ui/src/lib/i18n/messages/es.settings.ts | 22 +- .../ui/src/lib/i18n/messages/fr.settings.ts | 22 +- .../ui/src/lib/i18n/messages/ja.settings.ts | 22 +- .../ui/src/lib/i18n/messages/ko.settings.ts | 22 +- .../ui/src/lib/i18n/messages/pl.settings.ts | 23 +- .../src/lib/i18n/messages/pt-BR.settings.ts | 22 +- .../ui/src/lib/i18n/messages/uk.settings.ts | 22 +- .../src/lib/i18n/messages/zh-CN.settings.ts | 22 +- .../src/lib/i18n/messages/zh-TW.settings.ts | 22 +- 13 files changed, 583 insertions(+), 348 deletions(-) create mode 100644 packages/ui/src/components/sections/openchamber/ShortcutRecordingDialog.tsx diff --git a/packages/ui/src/components/sections/openchamber/KeyboardShortcutsSettings.tsx b/packages/ui/src/components/sections/openchamber/KeyboardShortcutsSettings.tsx index 1956615c..9f83af25 100644 --- a/packages/ui/src/components/sections/openchamber/KeyboardShortcutsSettings.tsx +++ b/packages/ui/src/components/sections/openchamber/KeyboardShortcutsSettings.tsx @@ -1,12 +1,7 @@ import React from 'react'; import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; -import { - SettingsSection, - SettingsFieldRow, -} from '@/components/sections/shared/SettingsSection'; +import { SettingsFieldRow, SettingsSection } from '@/components/sections/shared/SettingsSection'; import { useUIStore } from '@/stores/useUIStore'; -import { cn } from '@/lib/utils'; import { updateDesktopSettings } from '@/lib/persistence'; import { isVSCodeRuntime } from '@/lib/desktop'; import { @@ -14,314 +9,133 @@ import { getCustomizableShortcutActions, getEffectiveShortcutCombo, getEffectiveShortcutPrefix, - isRiskyBrowserShortcut, - keyToShortcutToken, - normalizeCombo, + getShortcutCategory, UNASSIGNED_SHORTCUT, + type ShortcutAction, + type ShortcutActionId, + type ShortcutCategory, type ShortcutCombo, } from '@/lib/shortcuts'; import { useI18n } from '@/lib/i18n'; +import { ShortcutRecordingDialog } from './ShortcutRecordingDialog'; -const MODIFIER_KEYS = new Set(['shift', 'control', 'alt', 'meta']); - -const keyboardEventToCombo = (event: React.KeyboardEvent): ShortcutCombo | null => { - if (MODIFIER_KEYS.has(event.key.toLowerCase())) { - return null; - } - - const parts: string[] = []; - - if (event.metaKey || event.ctrlKey) { - parts.push('mod'); - } - if (event.shiftKey) { - parts.push('shift'); - } - if (event.altKey) { - parts.push('alt'); - } - - const keyToken = keyToShortcutToken(event.key); - if (!keyToken) { - return null; - } - - parts.push(keyToken); - return normalizeCombo(parts.join('+')); -}; - -// Prefix capture for chord-style shortcuts (e.g. "switch context panel -// surface"): a bare modifier press is accepted so the prefix can be just the -// primary modifier (default) or a modifier + key chord like `mod+p`. -const keyboardEventToPrefixCombo = (event: React.KeyboardEvent): ShortcutCombo | null => { - const parts: string[] = []; - - if (event.metaKey || event.ctrlKey) { - parts.push('mod'); - } - if (event.shiftKey) { - parts.push('shift'); - } - if (event.altKey) { - parts.push('alt'); - } - - if (MODIFIER_KEYS.has(event.key.toLowerCase())) { - return parts.length > 0 ? normalizeCombo(parts.join('+')) : null; - } - - const keyToken = keyToShortcutToken(event.key); - if (!keyToken) { - return null; - } - - parts.push(keyToken); - return parts.length > 0 ? normalizeCombo(parts.join('+')) : null; -}; +const CATEGORIES: ShortcutCategory[] = ['session', 'models', 'panels', 'navigation', 'application']; export const KeyboardShortcutsSettings: React.FC = () => { const { t } = useI18n(); - const tUnsafe = React.useCallback((key: string) => t(key as Parameters[0]), [t]); + const tUnsafe = (key: string) => t(key as Parameters[0]); const shortcutOverrides = useUIStore((state) => state.shortcutOverrides); const setShortcutOverride = useUIStore((state) => state.setShortcutOverride); const clearShortcutOverride = useUIStore((state) => state.clearShortcutOverride); const resetAllShortcutOverrides = useUIStore((state) => state.resetAllShortcutOverrides); + const [editingAction, setEditingAction] = React.useState(null); const actions = React.useMemo(() => { const all = getCustomizableShortcutActions(); - if (!isVSCodeRuntime()) { - return all; - } - return all.filter((action) => action.id !== 'toggle_prompt_navigator'); + return isVSCodeRuntime() ? all.filter((action) => action.id !== 'toggle_prompt_navigator') : all; }, []); - const actionLabel = React.useCallback((id: string, fallbackLabel: string): string => { - const key = `settings.openchamber.keyboardShortcuts.action.${id}.label`; + const actionLabel = (action: ShortcutAction): string => { + const key = `settings.openchamber.keyboardShortcuts.action.${action.id}.label`; const translated = tUnsafe(key); - return translated === key ? fallbackLabel : translated; - }, [tUnsafe]); - - const [capturingActionId, setCapturingActionId] = React.useState(null); - const [draftByAction, setDraftByAction] = React.useState>({}); - const [errorText, setErrorText] = React.useState(''); - const [warningText, setWarningText] = React.useState(''); - const [pendingOverwrite, setPendingOverwrite] = React.useState<{ - actionId: string; - combo: ShortcutCombo; - conflictActionId: string; - } | null>(null); - - const persistShortcutOverrides = React.useCallback((nextOverrides: Record) => { + return translated === key ? action.label : translated; + }; + const persist = (nextOverrides: Record) => { void updateDesktopSettings({ shortcutOverrides: nextOverrides }); - }, []); - - const findConflict = React.useCallback((actionId: string, combo: ShortcutCombo): string | null => { - const normalized = normalizeCombo(combo); - for (const action of actions) { - if (action.id === actionId) { - continue; - } - const existing = getEffectiveShortcutCombo(action.id, shortcutOverrides); - if (normalizeCombo(existing) === normalized) { - return action.id; - } - } - return null; - }, [actions, shortcutOverrides]); - - const saveCombo = React.useCallback((actionId: string, combo: ShortcutCombo) => { - const normalized = normalizeCombo(combo); - const conflictActionId = findConflict(actionId, normalized); - if (conflictActionId) { - setPendingOverwrite({ actionId, combo: normalized, conflictActionId }); - setErrorText(''); - return; - } - - const nextOverrides = { ...shortcutOverrides, [actionId]: normalized }; - setShortcutOverride(actionId, normalized); - persistShortcutOverrides(nextOverrides); - setPendingOverwrite(null); - setErrorText(''); - setWarningText(isRiskyBrowserShortcut(normalized) ? t('settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut') : ''); - setDraftByAction((current) => { - const rest = { ...current }; - delete rest[actionId]; - return rest; - }); - }, [findConflict, persistShortcutOverrides, setShortcutOverride, shortcutOverrides, t]); - - const confirmOverwrite = React.useCallback(() => { - if (!pendingOverwrite) { - return; - } - - const nextOverrides = { - ...shortcutOverrides, - [pendingOverwrite.conflictActionId]: UNASSIGNED_SHORTCUT, - [pendingOverwrite.actionId]: pendingOverwrite.combo, - }; - setShortcutOverride(pendingOverwrite.conflictActionId, UNASSIGNED_SHORTCUT); - setShortcutOverride(pendingOverwrite.actionId, pendingOverwrite.combo); - persistShortcutOverrides(nextOverrides); - setPendingOverwrite(null); - setErrorText(''); - setWarningText(isRiskyBrowserShortcut(pendingOverwrite.combo) ? t('settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut') : ''); - setDraftByAction((current) => { - const rest = { ...current }; - delete rest[pendingOverwrite.actionId]; - return rest; - }); - }, [pendingOverwrite, persistShortcutOverrides, setShortcutOverride, shortcutOverrides, t]); - - const resetOne = React.useCallback((actionId: string) => { + }; + const save = ( + actionId: ShortcutActionId, + combo: ShortcutCombo, + replaceActionId?: ShortcutActionId, + ) => { + const nextOverrides = { ...shortcutOverrides, [actionId]: combo }; + if (replaceActionId) nextOverrides[replaceActionId] = UNASSIGNED_SHORTCUT; + setShortcutOverride(actionId, combo); + if (replaceActionId) setShortcutOverride(replaceActionId, UNASSIGNED_SHORTCUT); + persist(nextOverrides); + }; + const resetOne = (actionId: ShortcutActionId) => { const nextOverrides = { ...shortcutOverrides }; delete nextOverrides[actionId]; clearShortcutOverride(actionId); - persistShortcutOverrides(nextOverrides); - setDraftByAction((current) => { - const rest = { ...current }; - delete rest[actionId]; - return rest; - }); - setPendingOverwrite(null); - setErrorText(''); - setWarningText(''); - }, [clearShortcutOverride, persistShortcutOverrides, shortcutOverrides]); + persist(nextOverrides); + }; + const shortcutDisplay = (action: ShortcutAction): string => { + const isSurfaceSwitch = action.id === 'switch_context_surface'; + const combo = isSurfaceSwitch + ? getEffectiveShortcutPrefix(action.id, shortcutOverrides) + : getEffectiveShortcutCombo(action.id, shortcutOverrides); + const formatted = formatShortcutForDisplay( + combo, + t('settings.openchamber.keyboardShortcuts.unassigned'), + ); + return isSurfaceSwitch && combo && combo !== UNASSIGNED_SHORTCUT + ? `${formatted}${t('settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix')}` + : formatted; + }; return ( - { - resetAllShortcutOverrides(); - persistShortcutOverrides({}); - setDraftByAction({}); - setPendingOverwrite(null); - setErrorText(''); - setWarningText(''); - }} - > - {t('settings.openchamber.keyboardShortcuts.actions.resetAll')} - - )} - > - {(errorText || warningText || pendingOverwrite) && ( -
- {pendingOverwrite && ( -
- - {t('settings.openchamber.keyboardShortcuts.overwritePrompt')} - -
- - -
+ <> + {CATEGORIES.map((category, categoryIndex) => { + const categoryActions = actions.filter((action) => getShortcutCategory(action) === category); + if (categoryActions.length === 0) return null; + return ( + { + resetAllShortcutOverrides(); + persist({}); + }}> + {t('settings.openchamber.keyboardShortcuts.actions.resetAll')} + + ) : undefined} + > +
+ {categoryActions.map((action) => ( + + + {shortcutDisplay(action)} + + + + + ))}
- )} - {errorText && ( -
- {errorText} -
- )} - {warningText && ( -
- {warningText} -
- )} -
- )} - -
- {actions.map((action, index) => { - const isSurfaceSwitch = action.id === 'switch_context_surface'; - const effective = isSurfaceSwitch - ? getEffectiveShortcutPrefix(action.id, shortcutOverrides) - : getEffectiveShortcutCombo(action.id, shortcutOverrides); - const draft = draftByAction[action.id]; - const displayCombo = draft ?? effective; - const hasDraft = typeof draft === 'string' && normalizeCombo(draft) !== normalizeCombo(effective); - const isUnassignedDisplay = displayCombo === '' || normalizeCombo(displayCombo) === UNASSIGNED_SHORTCUT; - const displayValue = capturingActionId === action.id - ? t('settings.openchamber.keyboardShortcuts.field.pressKeys') - : isSurfaceSwitch && !isUnassignedDisplay - ? `${formatShortcutForDisplay(displayCombo)}${t('settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix')}` - : formatShortcutForDisplay(displayCombo); - - return ( -
0 && "border-t border-border/40")}> - - { - setCapturingActionId(action.id); - setErrorText(''); - }} - onBlur={() => { - if (capturingActionId === action.id) { - setCapturingActionId(null); - } - }} - onKeyDown={(event) => { - event.preventDefault(); - event.stopPropagation(); - - if (event.key === 'Escape') { - setCapturingActionId(null); - return; - } - - const combo = isSurfaceSwitch ? keyboardEventToPrefixCombo(event) : keyboardEventToCombo(event); - if (!combo) { - return; - } - - setDraftByAction((current) => ({ - ...current, - [action.id]: combo, - })); - setCapturingActionId(null); - setPendingOverwrite(null); - setErrorText(''); - }} - className="h-7 w-40 min-w-0 typography-ui-label text-center" - /> - - - -
- ); - })} -
- + + ); + })} + { + if (!open) setEditingAction(null); + }} + /> + ); }; diff --git a/packages/ui/src/components/sections/openchamber/ShortcutRecordingDialog.tsx b/packages/ui/src/components/sections/openchamber/ShortcutRecordingDialog.tsx new file mode 100644 index 00000000..c36a599b --- /dev/null +++ b/packages/ui/src/components/sections/openchamber/ShortcutRecordingDialog.tsx @@ -0,0 +1,209 @@ +import React from 'react'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { + formatShortcutForDisplay, + getEffectiveShortcutCombo, + getEffectiveShortcutPrefix, + getShortcutConflict, + isRiskyBrowserShortcut, + keyToShortcutToken, + normalizeCombo, + type ShortcutAction, + type ShortcutActionId, + type ShortcutCombo, +} from '@/lib/shortcuts'; +import { useI18n } from '@/lib/i18n'; + +const MODIFIER_KEYS = new Set(['shift', 'control', 'alt', 'meta']); + +interface ShortcutRecordingDialogProps { + action: ShortcutAction | null; + actions: ReadonlyArray; + overrides: Record; + actionLabel: (action: ShortcutAction) => string; + onSave: ( + actionId: ShortcutActionId, + combo: ShortcutCombo, + replaceActionId?: ShortcutActionId, + ) => void; + onOpenChange: (open: boolean) => void; +} + +function keyboardEventToCombo(event: React.KeyboardEvent): ShortcutCombo | null { + if (MODIFIER_KEYS.has(event.key.toLowerCase())) return null; + + const key = keyToShortcutToken(event.key); + if (!key) return null; + + const parts: string[] = []; + if (event.metaKey || event.ctrlKey) parts.push('mod'); + if (event.shiftKey) parts.push('shift'); + if (event.altKey) parts.push('alt'); + parts.push(key); + return normalizeCombo(parts.join('+')); +} + +function modifierKeyUpToCombo(event: React.KeyboardEvent): ShortcutCombo | null { + const key = event.key.toLowerCase(); + if (!MODIFIER_KEYS.has(key)) return null; + + const parts: string[] = []; + if (event.metaKey || event.ctrlKey || key === 'meta' || key === 'control') parts.push('mod'); + if (event.shiftKey || key === 'shift') parts.push('shift'); + if (event.altKey || key === 'alt') parts.push('alt'); + return parts.length > 0 ? normalizeCombo(parts.join('+')) : null; +} + +export const ShortcutRecordingDialog: React.FC = ({ + action, + actions, + overrides, + actionLabel, + onSave, + onOpenChange, +}) => { + const { t } = useI18n(); + const [chords, setChords] = React.useState([]); + const recordingRef = React.useRef(null); + + React.useEffect(() => { + if (!action) return; + setChords([]); + }, [action]); + + const combo = normalizeCombo(chords.join(' ')); + const conflicts = React.useMemo(() => { + if (!action || !combo) return []; + const result: Array<{ action: ShortcutAction; kind: 'exact' | 'prefix' }> = []; + for (const candidate of actions) { + if (candidate.id === action.id) continue; + const candidateCombo = candidate.id === 'switch_context_surface' + ? getEffectiveShortcutPrefix(candidate.id, overrides) + : getEffectiveShortcutCombo(candidate.id, overrides); + const kind = getShortcutConflict(combo, candidateCombo); + if (kind) result.push({ action: candidate, kind }); + } + return result; + }, [action, actions, combo, overrides]); + const prefixConflict = conflicts.find((conflict) => conflict.kind === 'prefix'); + const exactConflict = conflicts.find((conflict) => conflict.kind === 'exact'); + + const close = () => onOpenChange(false); + + return ( + + + + + {action + ? t('settings.openchamber.keyboardShortcuts.dialog.title', { + action: actionLabel(action), + }) + : ''} + + {t('settings.openchamber.keyboardShortcuts.dialog.instructions')} + + +
{ + event.preventDefault(); + event.stopPropagation(); + + if (event.key === 'Escape') { + close(); + return; + } + if (event.key === 'Backspace') { + setChords((current) => current.slice(0, -1)); + return; + } + + const chord = keyboardEventToCombo(event); + if (chord) { + setChords((current) => action?.id === 'switch_context_surface' + ? [chord] + : current.length < 2 ? [...current, chord] : current); + } + }} + onKeyUp={(event) => { + if (action?.id !== 'switch_context_surface' || chords.length > 0) return; + const combo = modifierKeyUpToCombo(event); + if (!combo) return; + event.preventDefault(); + event.stopPropagation(); + setChords([combo]); + }} + > + {[0, 1].map((index) => ( +
+ + {t(index === 0 + ? 'settings.openchamber.keyboardShortcuts.dialog.firstChord' + : 'settings.openchamber.keyboardShortcuts.dialog.secondChord')} + + + {chords[index] + ? formatShortcutForDisplay(chords[index]) + : t('settings.openchamber.keyboardShortcuts.dialog.recording')} + +
+ ))} + {prefixConflict ? ( +

+ {t('settings.openchamber.keyboardShortcuts.error.prefixConflict', { action: actionLabel(prefixConflict.action) })} +

+ ) : null} + {exactConflict && !prefixConflict ? ( +

+ {t('settings.openchamber.keyboardShortcuts.error.exactConflict', { action: actionLabel(exactConflict.action) })} +

+ ) : null} + {combo && isRiskyBrowserShortcut(combo) ? ( +

+ {t('settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut')} +

+ ) : null} +
+ + + + {exactConflict && !prefixConflict ? ( + + ) : ( + + )} + +
+
+ ); +}; diff --git a/packages/ui/src/components/ui/HelpDialog.tsx b/packages/ui/src/components/ui/HelpDialog.tsx index 6ed250ea..b1ac15b4 100644 --- a/packages/ui/src/components/ui/HelpDialog.tsx +++ b/packages/ui/src/components/ui/HelpDialog.tsx @@ -13,13 +13,14 @@ import { getShortcutAction, getModifierLabel, formatShortcutForDisplay, + type ShortcutActionId, } from "@/lib/shortcuts"; import { useI18n, type I18nKey } from "@/lib/i18n"; import { isVSCodeRuntime } from "@/lib/desktop"; import type { IconName } from "@/components/icon/icons"; type ShortcutItem = { - id?: string; + id?: ShortcutActionId; keys: string | string[]; descriptionKey: I18nKey; icon: IconName | null; @@ -30,9 +31,14 @@ type ShortcutSection = { items: ShortcutItem[]; }; -const renderShortcut = (id: string, fallbackCombo: string, overrides: Record) => { +const renderShortcut = ( + id: ShortcutActionId, + fallbackCombo: string, + overrides: Record, + unassignedLabel: string, +) => { const action = getShortcutAction(id); - return action ? formatShortcutForDisplay(getEffectiveShortcutCombo(id, overrides)) : fallbackCombo; + return action ? formatShortcutForDisplay(getEffectiveShortcutCombo(id, overrides), unassignedLabel) : fallbackCombo; }; export const HelpDialog: React.FC = () => { @@ -121,6 +127,18 @@ export const HelpDialog: React.FC = () => { icon: "git-branch", keys: '', }, + { + id: 'open_draft_project_picker', + descriptionKey: 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label', + icon: 'folder', + keys: '', + }, + { + id: 'open_draft_worktree_picker', + descriptionKey: 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label', + icon: 'git-branch', + keys: '', + }, { id: 'focus_input', descriptionKey: "helpDialog.item.focusChatInput", icon: "text", keys: '' }, { id: 'toggle_prompt_navigator', @@ -214,7 +232,7 @@ export const HelpDialog: React.FC = () => { ]; return ( - + @@ -237,40 +255,48 @@ export const HelpDialog: React.FC = () => { {section.items .filter((shortcut) => !(isVSCode && shortcut.id === 'toggle_prompt_navigator')) .map((shortcut) => { - const displayKeys = shortcut.id - ? renderShortcut(shortcut.id, Array.isArray(shortcut.keys) ? shortcut.keys[0] : shortcut.keys, shortcutOverrides) - : (Array.isArray(shortcut.keys) ? shortcut.keys : shortcut.keys.split(" / ")); + const fallbackKeys = Array.isArray(shortcut.keys) + ? shortcut.keys[0] + : shortcut.keys; + const displayKeys = shortcut.id + ? renderShortcut( + shortcut.id, + fallbackKeys, + shortcutOverrides, + t('settings.openchamber.keyboardShortcuts.unassigned'), + ) + : (Array.isArray(shortcut.keys) ? shortcut.keys : shortcut.keys.split(" / ")); - return ( -
-
- {shortcut.icon && ( - - )} - - {t(shortcut.descriptionKey)} - + return ( +
+
+ {shortcut.icon && ( + + )} + + {t(shortcut.descriptionKey)} + +
+
+ {(Array.isArray(displayKeys) ? displayKeys : [displayKeys]).map((keyCombo: string, i: number) => ( + + {i > 0 && ( + + {t('helpDialog.keyCombiner.or')} + + )} + + {keyCombo} + + + ))} +
-
- {(Array.isArray(displayKeys) ? displayKeys : [displayKeys]).map((keyCombo: string, i: number) => ( - - {i > 0 && ( - - {t('helpDialog.keyCombiner.or')} - - )} - - {keyCombo} - - - ))} -
-
- ); - })} + ); + })}
))} @@ -284,7 +310,12 @@ export const HelpDialog: React.FC = () => {
  • • {t('helpDialog.proTips.commandPalette', { - shortcut: renderShortcut('open_command_palette', `${mod} P`, shortcutOverrides), + shortcut: renderShortcut( + 'open_command_palette', + `${mod} P`, + shortcutOverrides, + t('settings.openchamber.keyboardShortcuts.unassigned'), + ), })}
  • diff --git a/packages/ui/src/lib/i18n/messages/en.settings.ts b/packages/ui/src/lib/i18n/messages/en.settings.ts index c021f305..1772694f 100644 --- a/packages/ui/src/lib/i18n/messages/en.settings.ts +++ b/packages/ui/src/lib/i18n/messages/en.settings.ts @@ -1096,7 +1096,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.overwritePrompt': 'This combo is already used by another shortcut. Overwrite and clear that other mapping?', 'settings.openchamber.keyboardShortcuts.field.pressKeys': 'Press keys...', 'settings.openchamber.keyboardShortcuts.error.captureFirst': 'Capture a shortcut first.', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'This shortcut can conflict with browser defaults. It is still saved.', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'This shortcut can conflict with browser defaults. You can still save it.', 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': 'Go to line (files editor)', 'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': 'Open command palette', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': 'Focus input', @@ -1125,7 +1125,25 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.expand_input.label': 'Expand input', 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': 'Open conversation timeline', 'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label': 'Toggle prompt navigator', - 'settings.projects.sidebar.total': 'Total {count}', + 'settings.openchamber.keyboardShortcuts.category.session': 'Session Controls', + 'settings.openchamber.keyboardShortcuts.category.models': 'Models & Agents', + 'settings.openchamber.keyboardShortcuts.category.panels': 'Panels & Tools', + 'settings.openchamber.keyboardShortcuts.category.navigation': 'Navigation', + 'settings.openchamber.keyboardShortcuts.category.application': 'Application', + 'settings.openchamber.keyboardShortcuts.actions.edit': 'Edit', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': 'Replace and Save', + 'settings.openchamber.keyboardShortcuts.dialog.title': 'Edit {action}', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': 'Press up to two key combinations. Press Backspace to remove the last one.', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': 'First combination', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': 'Second combination', + 'settings.openchamber.keyboardShortcuts.dialog.recording': 'Press keys…', + 'settings.openchamber.keyboardShortcuts.unassigned': 'Unassigned', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': 'This conflicts with the sequence used by {action}. Choose a different combination.', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': 'This combination is already used by {action}.', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Open draft project picker', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Open draft worktree picker', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Voice input', + 'settings.projects.sidebar.total': 'Total {count}', 'settings.projects.sidebar.actions.addProject': 'Add project', 'settings.projects.page.empty.noProjects': 'No projects available.', 'settings.projects.page.title.default': 'Project Settings', diff --git a/packages/ui/src/lib/i18n/messages/es.settings.ts b/packages/ui/src/lib/i18n/messages/es.settings.ts index 74db714b..5ee1ebb0 100644 --- a/packages/ui/src/lib/i18n/messages/es.settings.ts +++ b/packages/ui/src/lib/i18n/messages/es.settings.ts @@ -1063,7 +1063,7 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.overwritePrompt": "Esta combinación ya está usada por otro atajo. ¿Sobrescribir y limpiar esa otra asignación?", "settings.openchamber.keyboardShortcuts.field.pressKeys": "Pulsa las teclas...", "settings.openchamber.keyboardShortcuts.error.captureFirst": "Captura un atajo primero.", - "settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut": "Este atajo puede entrar en conflicto con los predeterminados del navegador. Todavía se guarda.", + "settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut": "Este atajo puede entrar en conflicto con los predeterminados del navegador. Aun así, puedes guardarlo.", "settings.openchamber.keyboardShortcuts.action.open_go_to_line.label": "Ir a línea (editor de archivos)", "settings.openchamber.keyboardShortcuts.action.open_command_palette.label": "Abrir paleta de comandos", "settings.openchamber.keyboardShortcuts.action.focus_input.label": "Enfocar entrada", @@ -1092,7 +1092,25 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.action.expand_input.label": "Expandir entrada", "settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label": "Abrir línea de tiempo de conversación", "settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label": "Mostrar u ocultar navegador de prompts", - "settings.projects.sidebar.total": "Total {count}", + "settings.openchamber.keyboardShortcuts.category.session": "Controles de sesión", + "settings.openchamber.keyboardShortcuts.category.models": "Modelos y agentes", + "settings.openchamber.keyboardShortcuts.category.panels": "Paneles y herramientas", + "settings.openchamber.keyboardShortcuts.category.navigation": "Navegación", + "settings.openchamber.keyboardShortcuts.category.application": "Aplicación", + "settings.openchamber.keyboardShortcuts.actions.edit": "Editar", + "settings.openchamber.keyboardShortcuts.actions.replaceAndSave": "Reemplazar y guardar", + "settings.openchamber.keyboardShortcuts.dialog.title": "Editar {action}", + "settings.openchamber.keyboardShortcuts.dialog.instructions": "Pulse hasta dos combinaciones de teclas. Pulse Retroceso para quitar la última.", + "settings.openchamber.keyboardShortcuts.dialog.firstChord": "Primera combinación", + "settings.openchamber.keyboardShortcuts.dialog.secondChord": "Segunda combinación", + "settings.openchamber.keyboardShortcuts.dialog.recording": "Pulse las teclas…", + "settings.openchamber.keyboardShortcuts.unassigned": "Sin asignar", + "settings.openchamber.keyboardShortcuts.error.prefixConflict": "Esto entra en conflicto con la secuencia usada por {action}. Elija otra combinación.", + "settings.openchamber.keyboardShortcuts.error.exactConflict": "Esta combinación ya la usa {action}.", + "settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Abrir selector de proyecto de borrador", + "settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Abrir selector de árbol de trabajo de borrador", + "settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Entrada de voz", + "settings.projects.sidebar.total": "Total {count}", "settings.projects.sidebar.actions.addProject": "Añadir proyecto", "settings.projects.page.empty.noProjects": "No hay proyectos disponibles.", "settings.projects.page.title.default": "Configuración del proyecto", diff --git a/packages/ui/src/lib/i18n/messages/fr.settings.ts b/packages/ui/src/lib/i18n/messages/fr.settings.ts index f0c98448..46e8f21f 100644 --- a/packages/ui/src/lib/i18n/messages/fr.settings.ts +++ b/packages/ui/src/lib/i18n/messages/fr.settings.ts @@ -984,7 +984,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.overwritePrompt': 'Ce combo est déjà utilisé par un autre raccourci. Écraser et effacer cet autre mappage ?', 'settings.openchamber.keyboardShortcuts.field.pressKeys': 'Appuyez sur les touches...', 'settings.openchamber.keyboardShortcuts.error.captureFirst': 'Capturez d\'abord un raccourci.', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'Ce raccourci peut entrer en conflit avec les paramètres par défaut du navigateur. Il est toujours sauvegardé.', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'Ce raccourci peut entrer en conflit avec les paramètres par défaut du navigateur. Vous pouvez tout de même l’enregistrer.', 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': 'Aller à la ligne (éditeur de fichiers)', 'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': 'Ouvrir la palette de commandes', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': 'Entrée de mise au point', @@ -1013,7 +1013,25 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.expand_input.label': 'Développer l\'entrée', 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': 'Chronologie de la conversation ouverte', 'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label': 'Afficher ou masquer le navigateur de prompts', - 'settings.projects.sidebar.total': 'Total {count}', + 'settings.openchamber.keyboardShortcuts.category.session': 'Commandes de session', + 'settings.openchamber.keyboardShortcuts.category.models': 'Modèles et agents', + 'settings.openchamber.keyboardShortcuts.category.panels': 'Panneaux et outils', + 'settings.openchamber.keyboardShortcuts.category.navigation': 'Navigation', + 'settings.openchamber.keyboardShortcuts.category.application': 'Application', + 'settings.openchamber.keyboardShortcuts.actions.edit': 'Modifier', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': 'Remplacer et enregistrer', + 'settings.openchamber.keyboardShortcuts.dialog.title': 'Modifier {action}', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': 'Appuyez sur deux combinaisons de touches au maximum. Appuyez sur Retour arrière pour supprimer la dernière.', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': 'Première combinaison', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': 'Deuxième combinaison', + 'settings.openchamber.keyboardShortcuts.dialog.recording': 'Appuyez sur les touches…', + 'settings.openchamber.keyboardShortcuts.unassigned': 'Non attribué', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': 'Cela entre en conflit avec la séquence utilisée par {action}. Choisissez une autre combinaison.', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': 'Cette combinaison est déjà utilisée par {action}.', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Ouvrir le sélecteur de projet de brouillon', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Ouvrir le sélecteur de worktree de brouillon', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Saisie vocale', + 'settings.projects.sidebar.total': 'Total {count}', 'settings.projects.sidebar.actions.addProject': 'Ajouter un projet', 'settings.projects.page.empty.noProjects': 'Aucun projet disponible.', 'settings.projects.page.title.default': 'Paramètres du projet', diff --git a/packages/ui/src/lib/i18n/messages/ja.settings.ts b/packages/ui/src/lib/i18n/messages/ja.settings.ts index 0c82f734..a02f3cc2 100644 --- a/packages/ui/src/lib/i18n/messages/ja.settings.ts +++ b/packages/ui/src/lib/i18n/messages/ja.settings.ts @@ -1096,7 +1096,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.overwritePrompt': 'このキーコンボは別のショートカットで既に使用されています。上書きしてそのマッピングをクリアしますか?', 'settings.openchamber.keyboardShortcuts.field.pressKeys': 'キーを押してください...', 'settings.openchamber.keyboardShortcuts.error.captureFirst': '最初にショートカットを設定してください。', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'このショートカットはブラウザのデフォルトと競合する可能性があります。それでも保存されます。', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'このショートカットはブラウザのデフォルトと競合する可能性がありますが、そのまま保存できます。', 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': '指定行に移動(ファイルエディター)', 'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': 'コマンドパレットを開く', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': '入力をフォーカス', @@ -1125,7 +1125,25 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.open_model_selector.label': 'モデルセレクターを開く', 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': '会話タイムラインを開く', 'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label': 'プロンプトナビゲーターの表示切替', - 'settings.projects.sidebar.total': '合計 {count}', + 'settings.openchamber.keyboardShortcuts.category.session': 'セッション操作', + 'settings.openchamber.keyboardShortcuts.category.models': 'モデルとエージェント', + 'settings.openchamber.keyboardShortcuts.category.panels': 'パネルとツール', + 'settings.openchamber.keyboardShortcuts.category.navigation': 'ナビゲーション', + 'settings.openchamber.keyboardShortcuts.category.application': 'アプリケーション', + 'settings.openchamber.keyboardShortcuts.actions.edit': '編集', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': '置き換えて保存', + 'settings.openchamber.keyboardShortcuts.dialog.title': '{action} を編集', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': 'キーの組み合わせを最大2つ入力できます。Backspace で最後の組み合わせを削除します。', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': '最初の組み合わせ', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': '2番目の組み合わせ', + 'settings.openchamber.keyboardShortcuts.dialog.recording': 'キーを押してください…', + 'settings.openchamber.keyboardShortcuts.unassigned': '未割り当て', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': '{action} のシーケンスと競合しています。別の組み合わせを選択してください。', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': 'この組み合わせは {action} で使用されています。', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '下書きプロジェクト選択を開く', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '下書きワークツリー選択を開く', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '音声入力', + 'settings.projects.sidebar.total': '合計 {count}', 'settings.projects.sidebar.actions.addProject': 'プロジェクトを追加', 'settings.projects.page.empty.noProjects': '利用可能なプロジェクトがありません。', 'settings.projects.page.title.default': 'プロジェクト設定', diff --git a/packages/ui/src/lib/i18n/messages/ko.settings.ts b/packages/ui/src/lib/i18n/messages/ko.settings.ts index aa53cbfd..a56696cf 100644 --- a/packages/ui/src/lib/i18n/messages/ko.settings.ts +++ b/packages/ui/src/lib/i18n/messages/ko.settings.ts @@ -1063,7 +1063,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.overwritePrompt': '이 조합은 이미 다른 단축키에서 사용 중입니다. 덮어쓰고 기존 매핑을 지울까요?', 'settings.openchamber.keyboardShortcuts.field.pressKeys': '키를 누르세요...', 'settings.openchamber.keyboardShortcuts.error.captureFirst': '먼저 단축키를 입력하세요.', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': '이 단축키는 브라우저 기본값과 충돌할 수 있습니다. 그래도 저장됩니다.', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': '이 단축키는 브라우저 기본값과 충돌할 수 있지만 그래도 저장할 수 있습니다.', 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': '줄로 이동(파일 편집기)', 'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': '명령 팔레트 열기', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': '입력에 포커스', @@ -1092,7 +1092,25 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.expand_input.label': '입력 확장', 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': '대화 타임라인 열기', 'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label': '프롬프트 탐색기 표시/숨기기', - 'settings.projects.sidebar.total': '총 {count}개', + 'settings.openchamber.keyboardShortcuts.category.session': '세션 제어', + 'settings.openchamber.keyboardShortcuts.category.models': '모델 및 에이전트', + 'settings.openchamber.keyboardShortcuts.category.panels': '패널 및 도구', + 'settings.openchamber.keyboardShortcuts.category.navigation': '탐색', + 'settings.openchamber.keyboardShortcuts.category.application': '애플리케이션', + 'settings.openchamber.keyboardShortcuts.actions.edit': '편집', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': '바꾸고 저장', + 'settings.openchamber.keyboardShortcuts.dialog.title': '{action} 편집', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': '키 조합을 최대 두 개까지 누르세요. Backspace를 누르면 마지막 조합이 삭제됩니다.', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': '첫 번째 조합', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': '두 번째 조합', + 'settings.openchamber.keyboardShortcuts.dialog.recording': '키를 누르세요…', + 'settings.openchamber.keyboardShortcuts.unassigned': '할당되지 않음', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': '{action}에서 사용하는 시퀀스와 충돌합니다. 다른 조합을 선택하세요.', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': '이 조합은 이미 {action}에서 사용합니다.', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '초안 프로젝트 선택기 열기', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '초안 워크트리 선택기 열기', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '음성 입력', + 'settings.projects.sidebar.total': '총 {count}개', 'settings.projects.sidebar.actions.addProject': '프로젝트 추가', 'settings.projects.page.empty.noProjects': '사용 가능한 프로젝트가 없습니다.', 'settings.projects.page.title.default': '프로젝트 설정', diff --git a/packages/ui/src/lib/i18n/messages/pl.settings.ts b/packages/ui/src/lib/i18n/messages/pl.settings.ts index aa3af5d6..ee8c127b 100644 --- a/packages/ui/src/lib/i18n/messages/pl.settings.ts +++ b/packages/ui/src/lib/i18n/messages/pl.settings.ts @@ -838,7 +838,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.overwritePrompt': 'Ta kombinacja jest już używana przez inny skrót. Nadpisać i wyczyścić to inne przypisanie?', 'settings.openchamber.keyboardShortcuts.title': 'Skróty klawiszowe', 'settings.openchamber.keyboardShortcuts.tooltip': 'Przechwyć nową kombinację klawiszy, zapisz ją, a przypisania zostaną natychmiast zaktualizowane.', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'Ten skrót może kolidować z domyślnymi skrótami przeglądarki. Został jednak zapisany.', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': 'Ten skrót może kolidować z domyślnymi skrótami przeglądarki. Nadal możesz go zapisać.', 'settings.openchamber.opencodeCli.actions.browse': 'Przeglądaj', 'settings.openchamber.opencodeCli.actions.browseAria': 'Przeglądaj ścieżkę do pliku binarnego OpenCode', 'settings.openchamber.opencodeCli.actions.restartingOpenCode': 'Restartowanie OpenCode...', @@ -1360,7 +1360,26 @@ export const settingsDict = { 'settings.projects.page.toast.removeIconFailed': 'Nie udało się usunąć ikony projektu', 'settings.projects.page.toast.uploadIconFailed': 'Nie udało się przesłać ikony projektu', 'settings.projects.sidebar.actions.addProject': 'Dodaj projekt', - 'settings.projects.sidebar.total': 'Suma: {count}', + 'settings.openchamber.keyboardShortcuts.category.session': 'Sterowanie sesją', + 'settings.openchamber.keyboardShortcuts.category.models': 'Modele i agenci', + 'settings.openchamber.keyboardShortcuts.category.panels': 'Panele i narzędzia', + 'settings.openchamber.keyboardShortcuts.category.navigation': 'Nawigacja', + 'settings.openchamber.keyboardShortcuts.category.application': 'Aplikacja', + 'settings.openchamber.keyboardShortcuts.actions.edit': 'Edytuj', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': 'Zastąp i zapisz', + 'settings.openchamber.keyboardShortcuts.dialog.title': 'Edytuj: {action}', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': 'Naciśnij maksymalnie dwie kombinacje klawiszy. Naciśnij Backspace, aby usunąć ostatnią.', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': 'Pierwsza kombinacja', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': 'Druga kombinacja', + 'settings.openchamber.keyboardShortcuts.dialog.recording': 'Naciśnij klawisze…', + 'settings.openchamber.keyboardShortcuts.unassigned': 'Nieprzypisany', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': 'To koliduje z sekwencją używaną przez {action}. Wybierz inną kombinację.', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': 'Ta kombinacja jest już używana przez {action}.', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Otwórz wybór projektu szkicu', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Otwórz wybór worktree szkicu', + 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': 'Otwórz oś czasu rozmowy', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Wprowadzanie głosowe', + 'settings.projects.sidebar.total': 'Suma: {count}', 'settings.providers.page.actions.complete': 'Zakończ', 'settings.providers.page.actions.continue': 'Kontynuuj', 'settings.providers.page.actions.cancel': 'Anuluj', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts b/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts index c321f233..d54be549 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts @@ -1063,7 +1063,7 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.overwritePrompt": "Esta combinação já está sendo usada por outro atalho. Sobrescrever e limpar essa outra atribuição?", "settings.openchamber.keyboardShortcuts.field.pressKeys": "Pressione as teclas...", "settings.openchamber.keyboardShortcuts.error.captureFirst": "Captura um atalho primeiro.", - "settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut": "Este atalho pode entrar em conflito com os padrões do navegador. Ainda assim, ele será salvo.", + "settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut": "Este atalho pode entrar em conflito com os padrões do navegador. Ainda assim, você pode salvá-lo.", "settings.openchamber.keyboardShortcuts.action.open_go_to_line.label": "Ir para linha (editor de arquivos)", "settings.openchamber.keyboardShortcuts.action.open_command_palette.label": "Abrir paleta de comandos", "settings.openchamber.keyboardShortcuts.action.focus_input.label": "Focar entrada", @@ -1092,7 +1092,25 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.action.expand_input.label": "Expandir entrada", "settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label": "Abrir linha do tempo da conversa", "settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label": "Mostrar ou ocultar navegador de prompts", - "settings.projects.sidebar.total": "Total {count}", + "settings.openchamber.keyboardShortcuts.category.session": "Controles de sessão", + "settings.openchamber.keyboardShortcuts.category.models": "Modelos e agentes", + "settings.openchamber.keyboardShortcuts.category.panels": "Painéis e ferramentas", + "settings.openchamber.keyboardShortcuts.category.navigation": "Navegação", + "settings.openchamber.keyboardShortcuts.category.application": "Aplicação", + "settings.openchamber.keyboardShortcuts.actions.edit": "Editar", + "settings.openchamber.keyboardShortcuts.actions.replaceAndSave": "Substituir e salvar", + "settings.openchamber.keyboardShortcuts.dialog.title": "Editar {action}", + "settings.openchamber.keyboardShortcuts.dialog.instructions": "Pressione até duas combinações de teclas. Pressione Backspace para remover a última.", + "settings.openchamber.keyboardShortcuts.dialog.firstChord": "Primeira combinação", + "settings.openchamber.keyboardShortcuts.dialog.secondChord": "Segunda combinação", + "settings.openchamber.keyboardShortcuts.dialog.recording": "Pressione as teclas…", + "settings.openchamber.keyboardShortcuts.unassigned": "Não atribuído", + "settings.openchamber.keyboardShortcuts.error.prefixConflict": "Isto entra em conflito com a sequência usada por {action}. Escolha outra combinação.", + "settings.openchamber.keyboardShortcuts.error.exactConflict": "Esta combinação já é usada por {action}.", + "settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Abrir seletor de projeto do rascunho", + "settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Abrir seletor de worktree do rascunho", + "settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Entrada por voz", + "settings.projects.sidebar.total": "Total {count}", "settings.projects.sidebar.actions.addProject": "Adicionar projeto", "settings.projects.page.empty.noProjects": "Não há projetos disponíveis.", "settings.projects.page.title.default": "Configurações do projeto", diff --git a/packages/ui/src/lib/i18n/messages/uk.settings.ts b/packages/ui/src/lib/i18n/messages/uk.settings.ts index c5afd784..62ecc7b0 100644 --- a/packages/ui/src/lib/i18n/messages/uk.settings.ts +++ b/packages/ui/src/lib/i18n/messages/uk.settings.ts @@ -1063,7 +1063,7 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.overwritePrompt": "Ця комбінація вже використовується іншою комбінацією клавіш. Перезаписати та очистити інше зіставлення?", "settings.openchamber.keyboardShortcuts.field.pressKeys": "Натисніть клавіші...", "settings.openchamber.keyboardShortcuts.error.captureFirst": "Спочатку запишіть комбінацію клавіш.", - "settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut": "Ця комбінація клавіш може конфліктувати зі стандартними скороченнями браузера. Її все одно збережено.", + "settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut": "Ця комбінація клавіш може конфліктувати зі стандартними скороченнями браузера. Ви все одно можете її зберегти.", "settings.openchamber.keyboardShortcuts.action.open_go_to_line.label": "Перейти до рядка (редактор файлів)", "settings.openchamber.keyboardShortcuts.action.open_command_palette.label": "Відкрити палітру команд", "settings.openchamber.keyboardShortcuts.action.focus_input.label": "Фокус на полі вводу", @@ -1092,7 +1092,25 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.action.expand_input.label": "Розгорнути введення", "settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label": "Відкрити хронологію розмови", "settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label": "Показати або приховати навігатор промптів", - "settings.projects.sidebar.total": "Усього {count}", + "settings.openchamber.keyboardShortcuts.category.session": "Керування сесією", + "settings.openchamber.keyboardShortcuts.category.models": "Моделі й агенти", + "settings.openchamber.keyboardShortcuts.category.panels": "Панелі та інструменти", + "settings.openchamber.keyboardShortcuts.category.navigation": "Навігація", + "settings.openchamber.keyboardShortcuts.category.application": "Застосунок", + "settings.openchamber.keyboardShortcuts.actions.edit": "Редагувати", + "settings.openchamber.keyboardShortcuts.actions.replaceAndSave": "Замінити й зберегти", + "settings.openchamber.keyboardShortcuts.dialog.title": "Редагувати {action}", + "settings.openchamber.keyboardShortcuts.dialog.instructions": "Натисніть до двох комбінацій клавіш. Натисніть Backspace, щоб видалити останню.", + "settings.openchamber.keyboardShortcuts.dialog.firstChord": "Перша комбінація", + "settings.openchamber.keyboardShortcuts.dialog.secondChord": "Друга комбінація", + "settings.openchamber.keyboardShortcuts.dialog.recording": "Натисніть клавіші…", + "settings.openchamber.keyboardShortcuts.unassigned": "Не призначено", + "settings.openchamber.keyboardShortcuts.error.prefixConflict": "Це конфліктує з послідовністю, яку використовує {action}. Виберіть іншу комбінацію.", + "settings.openchamber.keyboardShortcuts.error.exactConflict": "Цю комбінацію вже використовує {action}.", + "settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Відкрити вибір проєкту чернетки", + "settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Відкрити вибір worktree чернетки", + "settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Голосове введення", + "settings.projects.sidebar.total": "Усього {count}", "settings.projects.sidebar.actions.addProject": "Додати проєкт", "settings.projects.page.empty.noProjects": "Немає доступних проєктів.", "settings.projects.page.title.default": "Параметри проєкту", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts b/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts index 2d111132..ae6cc3b1 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts @@ -1063,7 +1063,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.overwritePrompt': '该组合已被其他快捷键使用。是否覆盖并清除原映射?', 'settings.openchamber.keyboardShortcuts.field.pressKeys': '按下按键...', 'settings.openchamber.keyboardShortcuts.error.captureFirst': '请先录入一个快捷键。', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': '该快捷键可能与浏览器默认快捷键冲突,但仍已保存。', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': '该快捷键可能与浏览器默认快捷键冲突,但仍可保存。', 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': '跳转到行(文件编辑器)', 'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': '打开命令面板', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': '聚焦输入框', @@ -1092,7 +1092,25 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.expand_input.label': '展开输入框', 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': '打开对话时间线', 'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label': '显示或隐藏提示词导航', - 'settings.projects.sidebar.total': '总计 {count}', + 'settings.openchamber.keyboardShortcuts.category.session': '会话控制', + 'settings.openchamber.keyboardShortcuts.category.models': '模型和智能体', + 'settings.openchamber.keyboardShortcuts.category.panels': '面板和工具', + 'settings.openchamber.keyboardShortcuts.category.navigation': '导航', + 'settings.openchamber.keyboardShortcuts.category.application': '应用程序', + 'settings.openchamber.keyboardShortcuts.actions.edit': '编辑', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': '替换并保存', + 'settings.openchamber.keyboardShortcuts.dialog.title': '编辑{action}', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': '最多按下两个按键组合。按 Backspace 删除最后一个。', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': '第一个组合', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': '第二个组合', + 'settings.openchamber.keyboardShortcuts.dialog.recording': '按下按键…', + 'settings.openchamber.keyboardShortcuts.unassigned': '未分配', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': '这与 {action} 使用的序列冲突。请选择其他组合。', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': '此组合已被 {action} 使用。', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '打开草稿项目选择器', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '打开草稿工作树选择器', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '语音输入', + 'settings.projects.sidebar.total': '总计 {count}', 'settings.projects.sidebar.actions.addProject': '添加项目', 'settings.projects.page.empty.noProjects': '暂无项目。', 'settings.projects.page.title.default': '项目设置', diff --git a/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts b/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts index 4118c83d..a5b3d6ad 100644 --- a/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts +++ b/packages/ui/src/lib/i18n/messages/zh-TW.settings.ts @@ -970,7 +970,7 @@ 'settings.openchamber.keyboardShortcuts.overwritePrompt': '該組合已被其他快速鍵使用。是否覆寫並清除原對應?', 'settings.openchamber.keyboardShortcuts.field.pressKeys': '按下按鍵...', 'settings.openchamber.keyboardShortcuts.error.captureFirst': '請先錄入一個快速鍵。', - 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': '該快速鍵可能與瀏覽器預設快速鍵衝突,但仍已儲存。', + 'settings.openchamber.keyboardShortcuts.warning.riskyBrowserShortcut': '該快速鍵可能與瀏覽器預設快速鍵衝突,但仍可儲存。', 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': '跳轉到行(檔案編輯器)', 'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': '開啟命令面板', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': '聚焦輸入方塊', @@ -999,7 +999,25 @@ 'settings.openchamber.keyboardShortcuts.action.expand_input.label': '展開輸入方塊', 'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': '開啟對話時間軸', 'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label': '顯示或隱藏提示詞導覽', - 'settings.projects.sidebar.total': '總計 {count}', + 'settings.openchamber.keyboardShortcuts.category.session': '工作階段控制', + 'settings.openchamber.keyboardShortcuts.category.models': '模型與代理', + 'settings.openchamber.keyboardShortcuts.category.panels': '面板與工具', + 'settings.openchamber.keyboardShortcuts.category.navigation': '導覽', + 'settings.openchamber.keyboardShortcuts.category.application': '應用程式', + 'settings.openchamber.keyboardShortcuts.actions.edit': '編輯', + 'settings.openchamber.keyboardShortcuts.actions.replaceAndSave': '取代並儲存', + 'settings.openchamber.keyboardShortcuts.dialog.title': '編輯 {action}', + 'settings.openchamber.keyboardShortcuts.dialog.instructions': '最多按下兩個按鍵組合。按 Backspace 可刪除最後一個。', + 'settings.openchamber.keyboardShortcuts.dialog.firstChord': '第一個組合', + 'settings.openchamber.keyboardShortcuts.dialog.secondChord': '第二個組合', + 'settings.openchamber.keyboardShortcuts.dialog.recording': '按下按鍵…', + 'settings.openchamber.keyboardShortcuts.unassigned': '未指派', + 'settings.openchamber.keyboardShortcuts.error.prefixConflict': '這與 {action} 使用的序列衝突。請選擇其他組合。', + 'settings.openchamber.keyboardShortcuts.error.exactConflict': '此組合已由 {action} 使用。', + 'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '開啟草稿專案選擇器', + 'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '開啟草稿 worktree 選擇器', + 'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '語音輸入', + 'settings.projects.sidebar.total': '總計 {count}', 'settings.projects.sidebar.actions.addProject': '新增專案', 'settings.projects.page.empty.noProjects': '暫無專案。', 'settings.projects.page.title.default': '專案設定',