mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 00:02:23 +00:00
fix(terminal): localize the right-click menu and the search bar (#401)
The terminal's own context menu was the last surface still speaking hardcoded English in a three-locale app — 14 literals, while the tab and switcher menus route every item through t(). The search bar had three more, and its Previous / Next / Close buttons were icon-only with no tooltip at all. It also spoke a fourth vocabulary for one action: "Maximize Pane" for ToggleMaximizePane, which the menu bar, the palette and Keybindings all call "Zoom Pane". "Close Pane" is likewise "Close Pane / Tab" everywhere else, and it is the accurate name — the action closes the tab when the pane is the last one. Adds AppMenuSplitLeft / AppMenuSplitUp and SearchFind / SearchMatchCase / SearchUseRegex across en, zh and ja. The fork submenu now takes its title from the locale table instead of tty7-core's fork_label(), which is a capability probe in a crate that has no locale table. Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,7 @@ use gpui_component::{
|
||||
};
|
||||
|
||||
use super::view::TerminalView;
|
||||
use crate::ui::i18n::{L10nKey, t};
|
||||
|
||||
const MAX_MATCHES: usize = 10_000;
|
||||
|
||||
@@ -55,7 +56,7 @@ impl TerminalView {
|
||||
.unwrap_or_else(|| self.search_last_query.clone());
|
||||
let input = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.placeholder("Find")
|
||||
.placeholder(t(L10nKey::SearchFind))
|
||||
.default_value(seed)
|
||||
});
|
||||
let subs = vec![cx.subscribe_in(&input, window, Self::on_search_event)];
|
||||
@@ -288,7 +289,7 @@ impl TerminalView {
|
||||
.ghost()
|
||||
.small()
|
||||
.selected(case_on)
|
||||
.tooltip("Match case")
|
||||
.tooltip(t(L10nKey::SearchMatchCase))
|
||||
.on_click(cx.listener(|this, _, _window, cx| {
|
||||
this.toggle_search_case(cx);
|
||||
}));
|
||||
@@ -297,7 +298,7 @@ impl TerminalView {
|
||||
.ghost()
|
||||
.small()
|
||||
.selected(regex_on)
|
||||
.tooltip("Use regular expression")
|
||||
.tooltip(t(L10nKey::SearchUseRegex))
|
||||
.on_click(cx.listener(|this, _, _window, cx| {
|
||||
this.toggle_search_regex(cx);
|
||||
}));
|
||||
@@ -308,6 +309,7 @@ impl TerminalView {
|
||||
.icon(IconName::ChevronUp)
|
||||
.ghost()
|
||||
.small()
|
||||
.tooltip(t(L10nKey::AppMenuFindPrevious))
|
||||
.disabled(!has_matches)
|
||||
.on_click(cx.listener(|this, _, _window, cx| {
|
||||
this.step_match(Direction::Left, cx);
|
||||
@@ -316,6 +318,7 @@ impl TerminalView {
|
||||
.icon(IconName::ChevronDown)
|
||||
.ghost()
|
||||
.small()
|
||||
.tooltip(t(L10nKey::AppMenuFindNext))
|
||||
.disabled(!has_matches)
|
||||
.on_click(cx.listener(|this, _, _window, cx| {
|
||||
this.step_match(Direction::Right, cx);
|
||||
@@ -324,6 +327,7 @@ impl TerminalView {
|
||||
.icon(IconName::Close)
|
||||
.ghost()
|
||||
.small()
|
||||
.tooltip(t(L10nKey::Close))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.close_search(window, cx);
|
||||
}));
|
||||
|
||||
+43
-25
@@ -5062,57 +5062,75 @@ impl Render for TerminalView {
|
||||
.menu_element_with_disabled(
|
||||
Box::new(CopyText),
|
||||
!has_selection,
|
||||
menu_row_with_hint("Copy", Some("secondary-c")),
|
||||
menu_row_with_hint(t(L10nKey::AppMenuCopy), Some("secondary-c")),
|
||||
)
|
||||
.menu_element_with_disabled(
|
||||
Box::new(CutText),
|
||||
!has_selection,
|
||||
menu_row_with_hint("Cut", Some("secondary-x")),
|
||||
menu_row_with_hint(t(L10nKey::AppMenuCut), Some("secondary-x")),
|
||||
)
|
||||
.menu_element(
|
||||
Box::new(PasteText),
|
||||
menu_row_with_hint("Paste", Some("secondary-v")),
|
||||
menu_row_with_hint(t(L10nKey::AppMenuPaste), Some("secondary-v")),
|
||||
)
|
||||
.menu_element(
|
||||
Box::new(SelectAll),
|
||||
menu_row_with_hint("Select All", mac_only("secondary-a")),
|
||||
menu_row_with_hint(t(L10nKey::AppMenuSelectAll), mac_only("secondary-a")),
|
||||
)
|
||||
.separator()
|
||||
.menu("Find…", Box::new(FindInTerminal))
|
||||
.menu("Clear", Box::new(ClearScrollback));
|
||||
.menu(t(L10nKey::AppMenuFind), Box::new(FindInTerminal))
|
||||
.menu(
|
||||
t(L10nKey::AppMenuClearScrollback),
|
||||
Box::new(ClearScrollback),
|
||||
);
|
||||
|
||||
let view = menu_view.read(cx);
|
||||
let fork_label = view.agent().and_then(|a| a.fork_label());
|
||||
let can_fork = fork_label.is_some()
|
||||
// `fork_label` is tty7-core's capability probe, and core has no
|
||||
// locale table — take the answer, not its English wording.
|
||||
let can_fork = view.agent().and_then(|a| a.fork_label()).is_some();
|
||||
let fork_ready = can_fork
|
||||
&& view.remote_context().is_none()
|
||||
&& view.agent_session().is_some_and(|s| s.session_id.is_some());
|
||||
|
||||
let menu = match fork_label {
|
||||
Some(label) if can_fork => {
|
||||
let menu = match (can_fork, fork_ready) {
|
||||
(true, true) => {
|
||||
let focus = menu_focus.clone();
|
||||
menu.separator()
|
||||
.submenu(label, window, cx, move |submenu, _window, _cx| {
|
||||
menu.separator().submenu(
|
||||
t(L10nKey::AppMenuForkSession),
|
||||
window,
|
||||
cx,
|
||||
move |submenu, _window, _cx| {
|
||||
submenu
|
||||
.action_context(focus.clone())
|
||||
.menu("Split Right", Box::new(ForkAgentSessionRight))
|
||||
.menu("Split Left", Box::new(ForkAgentSessionLeft))
|
||||
.menu("Split Down", Box::new(ForkAgentSessionDown))
|
||||
.menu("Split Up", Box::new(ForkAgentSessionUp))
|
||||
})
|
||||
.menu(
|
||||
t(L10nKey::AppMenuSplitRight),
|
||||
Box::new(ForkAgentSessionRight),
|
||||
)
|
||||
.menu(
|
||||
t(L10nKey::AppMenuSplitLeft),
|
||||
Box::new(ForkAgentSessionLeft),
|
||||
)
|
||||
.menu(
|
||||
t(L10nKey::AppMenuSplitDown),
|
||||
Box::new(ForkAgentSessionDown),
|
||||
)
|
||||
.menu(t(L10nKey::AppMenuSplitUp), Box::new(ForkAgentSessionUp))
|
||||
},
|
||||
)
|
||||
}
|
||||
Some(label) => menu
|
||||
(true, false) => menu
|
||||
.separator()
|
||||
.item(PopupMenuItem::new(label).disabled(true)),
|
||||
None => menu,
|
||||
.item(PopupMenuItem::new(t(L10nKey::AppMenuForkSession)).disabled(true)),
|
||||
(false, _) => menu,
|
||||
};
|
||||
|
||||
menu.separator()
|
||||
.menu("Split Right", Box::new(SplitRight))
|
||||
.menu("Split Down", Box::new(SplitDown))
|
||||
.menu("Maximize Pane", Box::new(ToggleMaximizePane))
|
||||
.menu(t(L10nKey::AppMenuSplitRight), Box::new(SplitRight))
|
||||
.menu(t(L10nKey::AppMenuSplitDown), Box::new(SplitDown))
|
||||
.menu(t(L10nKey::AppMenuZoomPane), Box::new(ToggleMaximizePane))
|
||||
.separator()
|
||||
.menu("New Tab", Box::new(NewTab))
|
||||
.menu("Close Pane", Box::new(CloseActiveTab))
|
||||
.menu(t(L10nKey::AppMenuNewTab), Box::new(NewTab))
|
||||
.menu(t(L10nKey::AppMenuClosePaneTab), Box::new(CloseActiveTab))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
L10nKey::Search => "Search",
|
||||
L10nKey::SearchWorkspacesAndMachines => "Search workspaces, tabs and machines",
|
||||
L10nKey::SearchFonts => "Search fonts…",
|
||||
L10nKey::SearchFind => "Find",
|
||||
L10nKey::SearchMatchCase => "Match case",
|
||||
L10nKey::SearchUseRegex => "Use regular expression",
|
||||
L10nKey::NewFolderName => "New folder name",
|
||||
L10nKey::NewFileName => "New file name",
|
||||
L10nKey::HomeNewTab => "New Tab",
|
||||
@@ -1208,7 +1211,9 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
L10nKey::AppMenuNewWorkspace => "New Workspace",
|
||||
L10nKey::AppMenuNewWorktreeTab => "New Worktree Tab",
|
||||
L10nKey::AppMenuSplitRight => "Split Right",
|
||||
L10nKey::AppMenuSplitLeft => "Split Left",
|
||||
L10nKey::AppMenuSplitDown => "Split Down",
|
||||
L10nKey::AppMenuSplitUp => "Split Up",
|
||||
L10nKey::AppMenuRenameTab => "Rename Tab…",
|
||||
L10nKey::AppMenuCopyWorkingDirectory => "Copy Working Directory",
|
||||
L10nKey::AppMenuCopySessionId => "Copy Session ID",
|
||||
|
||||
@@ -12,6 +12,9 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::Search => "検索",
|
||||
L10nKey::SearchWorkspacesAndMachines => "ワークスペース、タブ、マシンを検索",
|
||||
L10nKey::SearchFonts => "フォントを検索…",
|
||||
L10nKey::SearchFind => "検索",
|
||||
L10nKey::SearchMatchCase => "大文字と小文字を区別",
|
||||
L10nKey::SearchUseRegex => "正規表現を使用",
|
||||
L10nKey::NewFolderName => "新しいフォルダ名",
|
||||
L10nKey::NewFileName => "新しいファイル名",
|
||||
L10nKey::HomeNewTab => "新規タブ",
|
||||
@@ -1251,7 +1254,9 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::AppMenuNewWorkspace => "新規ワークスペース",
|
||||
L10nKey::AppMenuNewWorktreeTab => "新規ワークツリータブ",
|
||||
L10nKey::AppMenuSplitRight => "右に分割",
|
||||
L10nKey::AppMenuSplitLeft => "左に分割",
|
||||
L10nKey::AppMenuSplitDown => "下に分割",
|
||||
L10nKey::AppMenuSplitUp => "上に分割",
|
||||
L10nKey::AppMenuRenameTab => "タブの名前を変更…",
|
||||
L10nKey::AppMenuCopyWorkingDirectory => "作業ディレクトリをコピー",
|
||||
L10nKey::AppMenuCopySessionId => "セッション ID をコピー",
|
||||
|
||||
@@ -63,6 +63,9 @@ pub enum L10nKey {
|
||||
Search,
|
||||
SearchWorkspacesAndMachines,
|
||||
SearchFonts,
|
||||
SearchFind,
|
||||
SearchMatchCase,
|
||||
SearchUseRegex,
|
||||
NewFolderName,
|
||||
NewFileName,
|
||||
HomeNewTab,
|
||||
@@ -685,7 +688,9 @@ pub enum L10nKey {
|
||||
AppMenuNewWorkspace,
|
||||
AppMenuNewWorktreeTab,
|
||||
AppMenuSplitRight,
|
||||
AppMenuSplitLeft,
|
||||
AppMenuSplitDown,
|
||||
AppMenuSplitUp,
|
||||
AppMenuRenameTab,
|
||||
AppMenuCopyWorkingDirectory,
|
||||
AppMenuCopySessionId,
|
||||
@@ -1104,6 +1109,9 @@ mod tests {
|
||||
L10nKey::Search,
|
||||
L10nKey::SearchWorkspacesAndMachines,
|
||||
L10nKey::SearchFonts,
|
||||
L10nKey::SearchFind,
|
||||
L10nKey::SearchMatchCase,
|
||||
L10nKey::SearchUseRegex,
|
||||
L10nKey::NewFolderName,
|
||||
L10nKey::NewFileName,
|
||||
L10nKey::HomeNewTab,
|
||||
@@ -1701,7 +1709,9 @@ mod tests {
|
||||
L10nKey::AppMenuNewWorkspace,
|
||||
L10nKey::AppMenuNewWorktreeTab,
|
||||
L10nKey::AppMenuSplitRight,
|
||||
L10nKey::AppMenuSplitLeft,
|
||||
L10nKey::AppMenuSplitDown,
|
||||
L10nKey::AppMenuSplitUp,
|
||||
L10nKey::AppMenuRenameTab,
|
||||
L10nKey::AppMenuCopyWorkingDirectory,
|
||||
L10nKey::AppMenuCopySessionId,
|
||||
|
||||
@@ -12,6 +12,9 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::Search => "搜索",
|
||||
L10nKey::SearchWorkspacesAndMachines => "搜索工作区、标签页与机器",
|
||||
L10nKey::SearchFonts => "搜索字体…",
|
||||
L10nKey::SearchFind => "查找",
|
||||
L10nKey::SearchMatchCase => "区分大小写",
|
||||
L10nKey::SearchUseRegex => "使用正则表达式",
|
||||
L10nKey::NewFolderName => "新文件夹名",
|
||||
L10nKey::NewFileName => "新文件名",
|
||||
L10nKey::HomeNewTab => "新标签页",
|
||||
@@ -1151,7 +1154,9 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::AppMenuNewWorkspace => "新工作区",
|
||||
L10nKey::AppMenuNewWorktreeTab => "新 worktree 标签页",
|
||||
L10nKey::AppMenuSplitRight => "向右分屏",
|
||||
L10nKey::AppMenuSplitLeft => "向左分屏",
|
||||
L10nKey::AppMenuSplitDown => "向下分屏",
|
||||
L10nKey::AppMenuSplitUp => "向上分屏",
|
||||
L10nKey::AppMenuRenameTab => "重命名标签页…",
|
||||
L10nKey::AppMenuCopyWorkingDirectory => "复制工作目录",
|
||||
L10nKey::AppMenuCopySessionId => "复制会话 ID",
|
||||
|
||||
Reference in New Issue
Block a user