diff --git a/crates/tui/src/localization.rs b/crates/tui/src/localization.rs index 7cba0b4a..e0c30cea 100644 --- a/crates/tui/src/localization.rs +++ b/crates/tui/src/localization.rs @@ -455,6 +455,32 @@ pub enum MessageId { OnboardTipsLine4, OnboardTipsFooterEnter, OnboardTipsFooterAction, + // Context menu. + CtxMenuTitle, + CtxMenuCopySelection, + CtxMenuCopySelectionDesc, + CtxMenuOpenSelection, + CtxMenuOpenSelectionDesc, + CtxMenuClearSelection, + CtxMenuOpenDetails, + CtxMenuCopyMessage, + CtxMenuCopyMessageDesc, + CtxMenuOpenInEditor, + CtxMenuOpenInEditorDesc, + CtxMenuShowCell, + CtxMenuShowCellDesc, + CtxMenuHideCell, + CtxMenuHideCellDesc, + CtxMenuShowHidden, + CtxMenuShowHiddenDesc, + CtxMenuPaste, + CtxMenuPasteDesc, + CtxMenuCmdPalette, + CtxMenuCmdPaletteDesc, + CtxMenuContextInspector, + CtxMenuContextInspectorDesc, + CtxMenuHelp, + CtxMenuHelpDesc, } #[allow(dead_code)] @@ -690,6 +716,32 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[ MessageId::OnboardTipsLine4, MessageId::OnboardTipsFooterEnter, MessageId::OnboardTipsFooterAction, + // Context menu. + MessageId::CtxMenuTitle, + MessageId::CtxMenuCopySelection, + MessageId::CtxMenuCopySelectionDesc, + MessageId::CtxMenuOpenSelection, + MessageId::CtxMenuOpenSelectionDesc, + MessageId::CtxMenuClearSelection, + MessageId::CtxMenuOpenDetails, + MessageId::CtxMenuCopyMessage, + MessageId::CtxMenuCopyMessageDesc, + MessageId::CtxMenuOpenInEditor, + MessageId::CtxMenuOpenInEditorDesc, + MessageId::CtxMenuShowCell, + MessageId::CtxMenuShowCellDesc, + MessageId::CtxMenuHideCell, + MessageId::CtxMenuHideCellDesc, + MessageId::CtxMenuShowHidden, + MessageId::CtxMenuShowHiddenDesc, + MessageId::CtxMenuPaste, + MessageId::CtxMenuPasteDesc, + MessageId::CtxMenuCmdPalette, + MessageId::CtxMenuCmdPaletteDesc, + MessageId::CtxMenuContextInspector, + MessageId::CtxMenuContextInspectorDesc, + MessageId::CtxMenuHelp, + MessageId::CtxMenuHelpDesc, ]; pub fn tr(locale: Locale, id: MessageId) -> &'static str { @@ -1218,6 +1270,32 @@ fn english(id: MessageId) -> &'static str { } MessageId::OnboardTipsFooterEnter => "Press Enter", MessageId::OnboardTipsFooterAction => " to open the workspace", + // Context menu. + MessageId::CtxMenuTitle => " Right click ", + MessageId::CtxMenuCopySelection => "Copy selection", + MessageId::CtxMenuCopySelectionDesc => "write selected transcript text", + MessageId::CtxMenuOpenSelection => "Open selection", + MessageId::CtxMenuOpenSelectionDesc => "show selected text in pager", + MessageId::CtxMenuClearSelection => "Clear selection", + MessageId::CtxMenuOpenDetails => "Open details", + MessageId::CtxMenuCopyMessage => "Copy message", + MessageId::CtxMenuCopyMessageDesc => "write clicked transcript cell", + MessageId::CtxMenuOpenInEditor => "Open in editor", + MessageId::CtxMenuOpenInEditorDesc => "open file:line in $EDITOR", + MessageId::CtxMenuShowCell => "Show cell", + MessageId::CtxMenuShowCellDesc => "unhide this transcript cell", + MessageId::CtxMenuHideCell => "Hide cell", + MessageId::CtxMenuHideCellDesc => "collapse this transcript cell", + MessageId::CtxMenuShowHidden => "Show hidden", + MessageId::CtxMenuShowHiddenDesc => "unhide all collapsed cells", + MessageId::CtxMenuPaste => "Paste", + MessageId::CtxMenuPasteDesc => "insert clipboard into composer", + MessageId::CtxMenuCmdPalette => "Command palette", + MessageId::CtxMenuCmdPaletteDesc => "commands, skills, and tools", + MessageId::CtxMenuContextInspector => "Context inspector", + MessageId::CtxMenuContextInspectorDesc => "active context and cache hints", + MessageId::CtxMenuHelp => "Help", + MessageId::CtxMenuHelpDesc => "keybindings and commands", } } @@ -1606,6 +1684,32 @@ fn japanese(id: MessageId) -> Option<&'static str> { } MessageId::OnboardTipsFooterEnter => "Enter を押す", MessageId::OnboardTipsFooterAction => " とワークスペースが開きます", + // Context menu. + MessageId::CtxMenuTitle => " 右クリック ", + MessageId::CtxMenuCopySelection => "選択をコピー", + MessageId::CtxMenuCopySelectionDesc => "選択したトランスクリプトのテキストを書き込む", + MessageId::CtxMenuOpenSelection => "選択を開く", + MessageId::CtxMenuOpenSelectionDesc => "選択したテキストをページャで表示", + MessageId::CtxMenuClearSelection => "選択を解除", + MessageId::CtxMenuOpenDetails => "詳細を開く", + MessageId::CtxMenuCopyMessage => "メッセージをコピー", + MessageId::CtxMenuCopyMessageDesc => "クリックしたトランスクリプトセルを書き込む", + MessageId::CtxMenuOpenInEditor => "エディタで開く", + MessageId::CtxMenuOpenInEditorDesc => "$EDITOR で file:line を開く", + MessageId::CtxMenuShowCell => "セルを表示", + MessageId::CtxMenuShowCellDesc => "このトランスクリプトセルを再表示", + MessageId::CtxMenuHideCell => "セルを隠す", + MessageId::CtxMenuHideCellDesc => "このトランスクリプトセルを折りたたむ", + MessageId::CtxMenuShowHidden => "非表示を表示", + MessageId::CtxMenuShowHiddenDesc => "すべての折りたたまれたセルを再表示", + MessageId::CtxMenuPaste => "貼り付け", + MessageId::CtxMenuPasteDesc => "クリップボードをコンポーザに挿入", + MessageId::CtxMenuCmdPalette => "コマンドパレット", + MessageId::CtxMenuCmdPaletteDesc => "コマンド、スキル、ツール", + MessageId::CtxMenuContextInspector => "コンテキストインスペクタ", + MessageId::CtxMenuContextInspectorDesc => "アクティブなコンテキストとキャッシュヒント", + MessageId::CtxMenuHelp => "ヘルプ", + MessageId::CtxMenuHelpDesc => "キー操作とコマンド", }) } @@ -1914,6 +2018,32 @@ fn chinese_simplified(id: MessageId) -> Option<&'static str> { MessageId::OnboardTipsLine4 => "Ctrl+R 恢复历史会话,Esc 退出当前输入或弹层。", MessageId::OnboardTipsFooterEnter => "按 Enter", MessageId::OnboardTipsFooterAction => " 进入工作区", + // Context menu. + MessageId::CtxMenuTitle => " 右键菜单 ", + MessageId::CtxMenuCopySelection => "复制所选", + MessageId::CtxMenuCopySelectionDesc => "将选中的记录区域文本写入剪贴板", + MessageId::CtxMenuOpenSelection => "打开所选", + MessageId::CtxMenuOpenSelectionDesc => "在翻阅器中查看选中文本", + MessageId::CtxMenuClearSelection => "清除选择", + MessageId::CtxMenuOpenDetails => "打开详情", + MessageId::CtxMenuCopyMessage => "复制消息", + MessageId::CtxMenuCopyMessageDesc => "将点击的记录条目写入剪贴板", + MessageId::CtxMenuOpenInEditor => "在编辑器中打开", + MessageId::CtxMenuOpenInEditorDesc => "在 $EDITOR 中打开 file:line", + MessageId::CtxMenuShowCell => "显示条目", + MessageId::CtxMenuShowCellDesc => "取消隐藏此记录条目", + MessageId::CtxMenuHideCell => "隐藏条目", + MessageId::CtxMenuHideCellDesc => "折叠此记录条目", + MessageId::CtxMenuShowHidden => "显示已隐藏", + MessageId::CtxMenuShowHiddenDesc => "取消隐藏所有已折叠条目", + MessageId::CtxMenuPaste => "粘贴", + MessageId::CtxMenuPasteDesc => "将剪贴板插入输入框", + MessageId::CtxMenuCmdPalette => "命令面板", + MessageId::CtxMenuCmdPaletteDesc => "命令、技能和工具", + MessageId::CtxMenuContextInspector => "上下文检查器", + MessageId::CtxMenuContextInspectorDesc => "活动上下文和缓存提示", + MessageId::CtxMenuHelp => "帮助", + MessageId::CtxMenuHelpDesc => "快捷键和命令", }) } @@ -2302,6 +2432,32 @@ fn portuguese_brazil(id: MessageId) -> Option<&'static str> { } MessageId::OnboardTipsFooterEnter => "Pressione Enter", MessageId::OnboardTipsFooterAction => " para abrir o workspace", + // Context menu. + MessageId::CtxMenuTitle => " Clique direito ", + MessageId::CtxMenuCopySelection => "Copiar seleção", + MessageId::CtxMenuCopySelectionDesc => "copiar texto selecionado da transcrição", + MessageId::CtxMenuOpenSelection => "Abrir seleção", + MessageId::CtxMenuOpenSelectionDesc => "mostrar texto selecionado no visualizador", + MessageId::CtxMenuClearSelection => "Limpar seleção", + MessageId::CtxMenuOpenDetails => "Abrir detalhes", + MessageId::CtxMenuCopyMessage => "Copiar mensagem", + MessageId::CtxMenuCopyMessageDesc => "copiar célula da transcrição clicada", + MessageId::CtxMenuOpenInEditor => "Abrir no editor", + MessageId::CtxMenuOpenInEditorDesc => "abrir file:line no $EDITOR", + MessageId::CtxMenuShowCell => "Mostrar célula", + MessageId::CtxMenuShowCellDesc => "reexibir esta célula da transcrição", + MessageId::CtxMenuHideCell => "Ocultar célula", + MessageId::CtxMenuHideCellDesc => "recolher esta célula da transcrição", + MessageId::CtxMenuShowHidden => "Mostrar ocultas", + MessageId::CtxMenuShowHiddenDesc => "reexibir todas as células recolhidas", + MessageId::CtxMenuPaste => "Colar", + MessageId::CtxMenuPasteDesc => "inserir área de transferência no compositor", + MessageId::CtxMenuCmdPalette => "Paleta de comandos", + MessageId::CtxMenuCmdPaletteDesc => "comandos, habilidades e ferramentas", + MessageId::CtxMenuContextInspector => "Inspetor de contexto", + MessageId::CtxMenuContextInspectorDesc => "contexto ativo e dicas de cache", + MessageId::CtxMenuHelp => "Ajuda", + MessageId::CtxMenuHelpDesc => "atalhos de teclado e comandos", }) } @@ -2696,6 +2852,32 @@ fn spanish_latin_america(id: MessageId) -> Option<&'static str> { } MessageId::OnboardTipsFooterEnter => "Presiona Enter", MessageId::OnboardTipsFooterAction => " para abrir el workspace", + // Context menu. + MessageId::CtxMenuTitle => " Clic derecho ", + MessageId::CtxMenuCopySelection => "Copiar selección", + MessageId::CtxMenuCopySelectionDesc => "copiar texto seleccionado de la transcripción", + MessageId::CtxMenuOpenSelection => "Abrir selección", + MessageId::CtxMenuOpenSelectionDesc => "mostrar texto seleccionado en el visor", + MessageId::CtxMenuClearSelection => "Limpiar selección", + MessageId::CtxMenuOpenDetails => "Abrir detalles", + MessageId::CtxMenuCopyMessage => "Copiar mensaje", + MessageId::CtxMenuCopyMessageDesc => "copiar celda de transcripción seleccionada", + MessageId::CtxMenuOpenInEditor => "Abrir en editor", + MessageId::CtxMenuOpenInEditorDesc => "abrir file:line en $EDITOR", + MessageId::CtxMenuShowCell => "Mostrar celda", + MessageId::CtxMenuShowCellDesc => "volver a mostrar esta celda de transcripción", + MessageId::CtxMenuHideCell => "Ocultar celda", + MessageId::CtxMenuHideCellDesc => "colapsar esta celda de transcripción", + MessageId::CtxMenuShowHidden => "Mostrar ocultas", + MessageId::CtxMenuShowHiddenDesc => "volver a mostrar todas las celdas colapsadas", + MessageId::CtxMenuPaste => "Pegar", + MessageId::CtxMenuPasteDesc => "insertar portapapeles en el compositor", + MessageId::CtxMenuCmdPalette => "Paleta de comandos", + MessageId::CtxMenuCmdPaletteDesc => "comandos, habilidades y herramientas", + MessageId::CtxMenuContextInspector => "Inspector de contexto", + MessageId::CtxMenuContextInspectorDesc => "contexto activo y sugerencias de caché", + MessageId::CtxMenuHelp => "Ayuda", + MessageId::CtxMenuHelpDesc => "atajos de teclado y comandos", }) } diff --git a/crates/tui/src/tui/context_menu.rs b/crates/tui/src/tui/context_menu.rs index e897577c..20543551 100644 --- a/crates/tui/src/tui/context_menu.rs +++ b/crates/tui/src/tui/context_menu.rs @@ -28,16 +28,18 @@ pub struct ContextMenuView { column: u16, row: u16, last_rect: Cell>, + title: String, } impl ContextMenuView { - pub fn new(entries: Vec, column: u16, row: u16) -> Self { + pub fn new(entries: Vec, column: u16, row: u16, title: String) -> Self { Self { entries, selected: 0, column, row, last_rect: Cell::new(None), + title, } } @@ -199,7 +201,7 @@ impl ModalView for ContextMenuView { .collect::>(); let block = Block::default() - .title(" Right click ") + .title(self.title.as_str()) .borders(Borders::ALL) .border_style(Style::default().fg(palette::DEEPSEEK_SKY)) .style(Style::default().bg(palette::SURFACE_ELEVATED)) @@ -256,6 +258,7 @@ mod tests { ], 5, 5, + " Right click ".to_string(), ); view.handle_key(KeyEvent::new(KeyCode::Down, KeyModifiers::NONE)); @@ -271,7 +274,12 @@ mod tests { #[test] fn menu_clamps_to_render_area() { - let view = ContextMenuView::new(vec![entry("Paste", ContextMenuAction::Paste)], 200, 80); + let view = ContextMenuView::new( + vec![entry("Paste", ContextMenuAction::Paste)], + 200, + 80, + " Right click ".to_string(), + ); let rect = view.menu_rect(Rect { x: 0, @@ -293,6 +301,7 @@ mod tests { ], 2, 2, + " Right click ".to_string(), ); let area = Rect { x: 0, diff --git a/crates/tui/src/tui/mouse_ui.rs b/crates/tui/src/tui/mouse_ui.rs index a22b2b61..8d742b87 100644 --- a/crates/tui/src/tui/mouse_ui.rs +++ b/crates/tui/src/tui/mouse_ui.rs @@ -5,6 +5,7 @@ use ratatui::layout::Rect; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; +use crate::localization::MessageId; use crate::tui::app::App; use crate::tui::command_palette::{ CommandPaletteView, build_entries as build_command_palette_entries, @@ -434,8 +435,13 @@ pub(crate) fn open_context_menu(app: &mut App, mouse: MouseEvent) { if entries.is_empty() { return; } - app.view_stack - .push(ContextMenuView::new(entries, mouse.column, mouse.row)); + let title = app.tr(MessageId::CtxMenuTitle).to_string(); + app.view_stack.push(ContextMenuView::new( + entries, + mouse.column, + mouse.row, + title, + )); app.needs_redraw = true; } @@ -444,17 +450,17 @@ pub(crate) fn build_context_menu_entries(app: &App, mouse: MouseEvent) -> Vec Vec Vec