From 11b89efca907047f3df54a43fe513b947b80c65e Mon Sep 17 00:00:00 2001 From: austinpower1258 Date: Fri, 29 May 2026 22:32:33 -0700 Subject: [PATCH 1/2] Add "Send Ctrl-F to Terminal" passthrough action (force-stop CC agents) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #4993: inside a cmux-managed Claude Code session, CC only exposes force-stop as a TUI keybinding ("press Ctrl-F twice"). The maintainer framing is the durable one: any ctrl-chord a TUI reads off the raw tty is one keystroke-capture handler away from being swallowed, so the fix is a non-keyboard stop path rather than patching one binding. This adds a single shared action that delivers a faithfully Ghostty-encoded Ctrl-F to the focused terminal's PTY, bypassing cmux's shortcut/menu/ responder layers entirely. Encoding goes through the existing named-key path (`sendNamedKey("ctrl-f")`) so it respects the surface's current keyboard mode, matching a real keystroke. Invoke it twice to force-stop. Altitude: the general raw-key passthrough already exists on the CLI (`send_key `); a key picker is wrong ergonomics for a quick GUI force-stop, so the GUI surfaces expose the concrete Ctrl-F chord while the socket command stays general. Default shortcut is unbound (binding plain Ctrl-F would be self-referential); users opt in via Settings. Shared model path: TabManager.sendCtrlFToFocusedTerminal(), wired to every entrypoint — customizable KeyboardShortcutSettings action, command palette, Find menu item, cmux.json shortcuts.bindings (auto), and `send_key ctrl-f` (now an explicit named case + help text). Docs derive from the single cmux-shortcuts.ts source; strings localized en/ja. Tests: behavioral guards that the ctrl-f chord stays recognized/deliverable (TerminalSurface.sendNamedKey) and that NamedKeySendResult.accepted maps delivery correctly. A red-first regression test does not apply: the byte encoding already worked generically; the defect was the missing non-keyboard affordance, which is GUI/menu/palette wiring exercised at integration level. Co-Authored-By: Claude Opus 4.8 --- Resources/Localizable.xcstrings | 51 +++++++++++++++++++ Sources/AppDelegate.swift | 13 +++++ ...ntentView+RightSidebarCommandPalette.swift | 2 + Sources/ContentView.swift | 17 +++++++ Sources/GhosttyTerminalView.swift | 14 +++++ Sources/KeyboardShortcutContext.swift | 2 +- Sources/KeyboardShortcutSettings.swift | 9 ++++ Sources/TabManager.swift | 27 ++++++++++ Sources/TerminalController.swift | 2 +- Sources/cmuxApp.swift | 12 +++++ cmuxTests/TerminalAndGhosttyTests.swift | 38 ++++++++++++++ web/data/cmux-shortcuts.ts | 9 ++++ 12 files changed, 194 insertions(+), 2 deletions(-) diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index e0521100c8..612a3e5921 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -155872,6 +155872,57 @@ } } }, + "command.terminalSendCtrlF.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Send Ctrl-F to Terminal" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ターミナルにCtrl-Fを送信" + } + } + } + }, + "menu.find.sendCtrlFToTerminal": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Send Ctrl-F to Terminal" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ターミナルにCtrl-Fを送信" + } + } + } + }, + "shortcut.sendCtrlFToTerminal.label": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Send Ctrl-F to Terminal" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ターミナルにCtrl-Fを送信" + } + } + } + }, "shortcut.attachTextBoxFile.label": { "extractionState": "manual", "localizations": { diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index c107647e46..fcecc89207 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -12666,6 +12666,19 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent return handled } + if matchConfiguredShortcut(event: event, action: .sendCtrlFToTerminal) { + let routedManager = preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager + let handled = routedManager?.sendCtrlFToFocusedTerminal() ?? false +#if DEBUG + cmuxDebugLog( + "shortcut.action name=sendCtrlFToTerminal handled=\(handled ? 1 : 0) " + + "\(debugShortcutRouteSnapshot(event: event))" + ) +#endif + // Only consume when a focused terminal actually received the chord. + return handled + } + // Workspace navigation: Cmd+Ctrl+] / Cmd+Ctrl+[ if matchConfiguredShortcut(event: event, action: .nextSidebarTab) { #if DEBUG diff --git a/Sources/ContentView+RightSidebarCommandPalette.swift b/Sources/ContentView+RightSidebarCommandPalette.swift index 5aeb654510..665d796ad8 100644 --- a/Sources/ContentView+RightSidebarCommandPalette.swift +++ b/Sources/ContentView+RightSidebarCommandPalette.swift @@ -77,6 +77,8 @@ extension ContentView { return .focusTextBoxInput case "palette.terminalAttachTextBoxFile": return .attachTextBoxFile + case "palette.terminalSendCtrlF": + return .sendCtrlFToTerminal case "palette.toggleSplitZoom": return .toggleSplitZoom case "palette.equalizeSplits": diff --git a/Sources/ContentView.swift b/Sources/ContentView.swift index 35efd3db0e..f296bc70c5 100644 --- a/Sources/ContentView.swift +++ b/Sources/ContentView.swift @@ -7402,6 +7402,18 @@ struct ContentView: View { when: { $0.bool(CommandPaletteContextKeys.panelIsTerminal) } ) ) + contributions.append( + CommandPaletteCommandContribution( + commandId: "palette.terminalSendCtrlF", + title: constant(String(localized: "command.terminalSendCtrlF.title", defaultValue: "Send Ctrl-F to Terminal")), + subtitle: terminalPanelSubtitle, + keywords: [ + "terminal", "ctrl", "control", "f", "send", "key", "passthrough", + "force", "stop", "agent", "agents", "claude", "code", "hung", "background", "watchdog", "kill", + ], + when: { $0.bool(CommandPaletteContextKeys.panelIsTerminal) } + ) + ) contributions.append( CommandPaletteCommandContribution( commandId: "palette.terminalSplitRight", @@ -8107,6 +8119,11 @@ struct ContentView: View { NSSound.beep() } } + registry.register(commandId: "palette.terminalSendCtrlF") { + if !tabManager.sendCtrlFToFocusedTerminal() { + NSSound.beep() + } + } registry.register(commandId: "palette.terminalSplitRight") { if !executeConfiguredAction(id: CmuxSurfaceTabBarBuiltInAction.splitRight.configID) { tabManager.createSplit(direction: .right) diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index 80a82ceb65..8aefb971b9 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -5236,6 +5236,17 @@ final class TerminalSurface: Identifiable, ObservableObject { case inputQueueFull case surfaceUnavailable case processExited + + /// Whether the named key was delivered to the surface or queued for an + /// imminently-started surface. `false` means the key never reached the PTY. + var accepted: Bool { + switch self { + case .sent, .queued: + return true + case .unknownKey, .inputQueueFull, .surfaceUnavailable, .processExited: + return false + } + } } enum InputSendResult: Equatable { @@ -7081,6 +7092,9 @@ final class TerminalSurface: Identifiable, ObservableObject { return PendingKeyEvent(keycode: UInt32(kVK_ANSI_C), mods: GHOSTTY_MODS_CTRL, label: normalized) case "ctrl-d", "ctrl+d", "eof": return PendingKeyEvent(keycode: UInt32(kVK_ANSI_D), mods: GHOSTTY_MODS_CTRL, label: normalized) + case "ctrl-f", "ctrl+f": + // Force-stop chord for embedded TUIs (e.g. Claude Code's "Ctrl-F twice"). + return PendingKeyEvent(keycode: UInt32(kVK_ANSI_F), mods: GHOSTTY_MODS_CTRL, label: normalized) case "ctrl-z", "ctrl+z", "sigtstp": return PendingKeyEvent(keycode: UInt32(kVK_ANSI_Z), mods: GHOSTTY_MODS_CTRL, label: normalized) case "ctrl-\\", "ctrl+\\", "sigquit": diff --git a/Sources/KeyboardShortcutContext.swift b/Sources/KeyboardShortcutContext.swift index 43e9d3f484..39e4fafd1f 100644 --- a/Sources/KeyboardShortcutContext.swift +++ b/Sources/KeyboardShortcutContext.swift @@ -51,7 +51,7 @@ extension KeyboardShortcutSettings.Action { switch self { case .switchRightSidebarToFiles, .switchRightSidebarToFind, .switchRightSidebarToSessions, .switchRightSidebarToFeed, .switchRightSidebarToDock: return .rightSidebarFocus - case .renameTab, .renameWorkspace: + case .renameTab, .renameWorkspace, .sendCtrlFToTerminal: return .nonBrowserPanel case .browserBack, .browserForward, .browserReload, .toggleBrowserDeveloperTools, .showBrowserJavaScriptConsole, .browserZoomIn, .browserZoomOut, .browserZoomReset: diff --git a/Sources/KeyboardShortcutSettings.swift b/Sources/KeyboardShortcutSettings.swift index ca12a0f1f3..544657744a 100644 --- a/Sources/KeyboardShortcutSettings.swift +++ b/Sources/KeyboardShortcutSettings.swift @@ -112,6 +112,7 @@ enum KeyboardShortcutSettings { case toggleTerminalCopyMode case focusTextBoxInput case attachTextBoxFile + case sendCtrlFToTerminal // Panes / splits case focusLeft @@ -201,6 +202,7 @@ enum KeyboardShortcutSettings { case .toggleTerminalCopyMode: return String(localized: "shortcut.toggleTerminalCopyMode.label", defaultValue: "Toggle Terminal Copy Mode") case .focusTextBoxInput: return String(localized: "shortcut.focusTextBoxInput.label", defaultValue: "Focus TextBox Input") case .attachTextBoxFile: return String(localized: "shortcut.attachTextBoxFile.label", defaultValue: "Attach File to TextBox Input") + case .sendCtrlFToTerminal: return String(localized: "shortcut.sendCtrlFToTerminal.label", defaultValue: "Send Ctrl-F to Terminal") case .focusLeft: return String(localized: "shortcut.focusPaneLeft.label", defaultValue: "Focus Pane Left") case .focusRight: return String(localized: "shortcut.focusPaneRight.label", defaultValue: "Focus Pane Right") case .focusUp: return String(localized: "shortcut.focusPaneUp.label", defaultValue: "Focus Pane Up") @@ -377,6 +379,13 @@ enum KeyboardShortcutSettings { return StoredShortcut(key: "a", command: true, shift: true, option: false, control: false) case .attachTextBoxFile: return StoredShortcut(key: "a", command: true, shift: true, option: true, control: false) + case .sendCtrlFToTerminal: + // Unbound by default: this is a deliberate escape hatch for forwarding a + // control chord (e.g. Claude Code's Ctrl-F force-stop) to the focused + // terminal. Binding it to plain Ctrl-F would be self-referential, so users + // opt in via Settings; it stays reachable through the command palette and + // the `send_key ctrl-f` socket command. + return .unbound case .selectWorkspaceByNumber: return StoredShortcut(key: "1", command: true, shift: false, option: false, control: false) case .toggleRightSidebar: diff --git a/Sources/TabManager.swift b/Sources/TabManager.swift index 179c78c63c..f7a24480d0 100644 --- a/Sources/TabManager.swift +++ b/Sources/TabManager.swift @@ -2543,6 +2543,33 @@ class TabManager: ObservableObject { return panel.surface.toggleKeyboardCopyMode() } + /// Forwards a single Ctrl-F (`^F`) key press to the focused terminal surface, + /// faithfully encoded through Ghostty so it matches whatever the running TUI + /// would receive from a real keystroke. + /// + /// This is the non-keyboard escape hatch for control chords that a focused TUI + /// reads off the raw tty. The motivating case is Claude Code's force-stop, which + /// is only exposed as "press Ctrl-F twice"; invoke this action twice to deliver + /// it. Delivery bypasses cmux's shortcut/menu/responder layers entirely. + /// + /// - Returns: `true` when the chord was sent or queued for the focused terminal, + /// `false` when no terminal panel is focused. + @discardableResult + func sendCtrlFToFocusedTerminal() -> Bool { + guard let panel = selectedTerminalPanel else { return false } + let result = panel.sendNamedKeyResult("ctrl-f") + if result == .sent { + panel.surface.forceRefresh(reason: "tabManager.sendCtrlFToFocusedTerminal") + } +#if DEBUG + cmuxDebugLog( + "terminal.sendCtrlF workspace=\(panel.workspaceId.uuidString.prefix(5)) " + + "panel=\(panel.id.uuidString.prefix(5)) result=\(result)" + ) +#endif + return result.accepted + } + @discardableResult func toggleFocusedTerminalTextBox() -> Bool { guard let panel = selectedTerminalPanel else { return false } diff --git a/Sources/TerminalController.swift b/Sources/TerminalController.swift index a4b6ffd82f..fa769da944 100644 --- a/Sources/TerminalController.swift +++ b/Sources/TerminalController.swift @@ -17002,7 +17002,7 @@ class TerminalController { Input commands: send - Send text to current terminal - send_key - Send special key (ctrl-c, ctrl-d, enter, tab, escape) + send_key - Send special key (ctrl-c, ctrl-d, ctrl-f, enter, tab, escape) send_surface - Send text to a specific terminal send_key_surface - Send special key to a specific terminal read_screen [id|idx] [--scrollback] [--lines N] - Read terminal text (plain text) diff --git a/Sources/cmuxApp.swift b/Sources/cmuxApp.swift index b48a549075..c94dd300bd 100644 --- a/Sources/cmuxApp.swift +++ b/Sources/cmuxApp.swift @@ -664,6 +664,18 @@ struct cmuxApp: App { activeTabManager.searchSelection() } .disabled(!(activeTabManager.canUseSelectionForFind)) + + Divider() + + splitCommandButton(title: String(localized: "menu.find.sendCtrlFToTerminal", defaultValue: "Send Ctrl-F to Terminal"), shortcut: menuShortcut(for: .sendCtrlFToTerminal)) { + // Restore focus to the terminal if the right sidebar grabbed it, then + // forward a faithfully-encoded Ctrl-F (e.g. Claude Code force-stop). + restoreFindTargetFocus() + if !activeTabManager.sendCtrlFToFocusedTerminal() { + NSSound.beep() + } + } + .disabled(activeTabManager.selectedTerminalPanel == nil) } } diff --git a/cmuxTests/TerminalAndGhosttyTests.swift b/cmuxTests/TerminalAndGhosttyTests.swift index ef7b6d6e49..4b45eefe56 100644 --- a/cmuxTests/TerminalAndGhosttyTests.swift +++ b/cmuxTests/TerminalAndGhosttyTests.swift @@ -1145,6 +1145,44 @@ final class TerminalOffscreenStartupTests: XCTestCase { XCTAssertEqual(pending.bytes, 0) } + func testSendNamedKeyRecognizesCtrlFForceStopChord() { + // Claude Code (and other raw-tty TUIs) only expose force-stop as a Ctrl-F + // keybinding. cmux must be able to deliver that chord to the focused terminal + // via a non-keyboard path, so the named-key layer has to recognize "ctrl-f". + // A recognized-but-undeliverable key returns `.surfaceUnavailable` on a closed + // surface, whereas an unrecognized key returns `.unknownKey`. + let panel = TerminalPanel(workspaceId: UUID()) + panel.surface.releaseSurfaceForTesting() + panel.surface.beginPortalCloseLifecycle(reason: "test.closed") + + XCTAssertEqual( + panel.surface.sendNamedKey("ctrl-f"), + .surfaceUnavailable, + "ctrl-f must be a recognized control chord so it can be forwarded to the focused terminal." + ) + XCTAssertEqual( + panel.surface.sendNamedKey("ctrl+f"), + .surfaceUnavailable, + "The ctrl+f alias must resolve identically to ctrl-f." + ) + XCTAssertEqual( + panel.surface.sendNamedKey("ctrl-thisisnotakey"), + .unknownKey, + "An unrecognized chord must surface as .unknownKey, proving the ctrl-f result is meaningful." + ) + } + + func testNamedKeySendResultAcceptedReflectsDelivery() { + // `sendCtrlFToFocusedTerminal()` reports success from this flag, so delivery and + // failure cases must map correctly. + XCTAssertTrue(TerminalSurface.NamedKeySendResult.sent.accepted) + XCTAssertTrue(TerminalSurface.NamedKeySendResult.queued.accepted) + XCTAssertFalse(TerminalSurface.NamedKeySendResult.unknownKey.accepted) + XCTAssertFalse(TerminalSurface.NamedKeySendResult.inputQueueFull.accepted) + XCTAssertFalse(TerminalSurface.NamedKeySendResult.surfaceUnavailable.accepted) + XCTAssertFalse(TerminalSurface.NamedKeySendResult.processExited.accepted) + } + func testDaemonSendWorkspaceQueuesColdControlInputInsteadOfReportingDroppedOK() throws { let previousManager = TerminalController.shared.activeTabManagerForCallerNotification() let manager = TabManager() diff --git a/web/data/cmux-shortcuts.ts b/web/data/cmux-shortcuts.ts index 8ea5222536..20c1d8b4a7 100644 --- a/web/data/cmux-shortcuts.ts +++ b/web/data/cmux-shortcuts.ts @@ -134,6 +134,15 @@ export const shortcutCategories: ShortcutCategory[] = [ { id: "toggleTerminalCopyMode", combos: [["⌘", "⇧", "M"]], description: { en: "Toggle terminal copy mode", ja: "ターミナルコピーモードを切り替え" } }, { id: "focusTextBoxInput", combos: [["⌘", "⇧", "A"]], description: { en: "Switch focus between terminal and TextBox input", ja: "ターミナルとTextBox入力のフォーカスを切り替え" } }, { id: "attachTextBoxFile", combos: [["⌥", "⌘", "⇧", "A"]], description: { en: "Attach file to TextBox input", ja: "TextBox入力にファイルを添付" } }, + { + id: "sendCtrlFToTerminal", + combos: [], + description: { en: "Send Ctrl-F to terminal", ja: "ターミナルにCtrl-Fを送信" }, + note: { + en: "unbound by default; forwards Ctrl-F to the focused terminal (Claude Code: invoke twice to force-stop hung background agents)", + ja: "デフォルトでは未割り当て。フォーカス中のターミナルにCtrl-Fを転送(Claude Code: 2回実行で停止しないバックグラウンドエージェントを強制停止)", + }, + }, { id: "saveFilePreview", combos: [["⌘", "S"]], From fb798df6c13ec3e909572f19e5bbd0da71c49a3e Mon Sep 17 00:00:00 2001 From: austinpower1258 Date: Sat, 30 May 2026 16:31:18 -0700 Subject: [PATCH 2/2] Localize Ctrl-F passthrough strings for all catalog locales CodeRabbit/Greptile flagged that the three new string keys (command.terminalSendCtrlF.title, menu.find.sendCtrlFToTerminal, shortcut.sendCtrlFToTerminal.label) only had en/ja while every other entry in Localizable.xcstrings carries all 20 catalog locales. Expand each to the full locale set, matching the file convention: en + ja translated, the other 18 locales seeded with the English value and state=needs_review (the same placeholder pattern existing untranslated entries use). Co-Authored-By: Claude Opus 4.8 --- Resources/Localizable.xcstrings | 324 ++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index 612a3e5921..2c6024a641 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -155875,51 +155875,375 @@ "command.terminalSendCtrlF.title": { "extractionState": "manual", "localizations": { + "ar": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "bs": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "da": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "de": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, "en": { "stringUnit": { "state": "translated", "value": "Send Ctrl-F to Terminal" } }, + "es": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "fr": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "it": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, "ja": { "stringUnit": { "state": "translated", "value": "ターミナルにCtrl-Fを送信" } + }, + "km": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "ko": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "nb": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "pl": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "pt-BR": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "ru": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "th": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "tr": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "uk": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } } } }, "menu.find.sendCtrlFToTerminal": { "extractionState": "manual", "localizations": { + "ar": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "bs": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "da": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "de": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, "en": { "stringUnit": { "state": "translated", "value": "Send Ctrl-F to Terminal" } }, + "es": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "fr": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "it": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, "ja": { "stringUnit": { "state": "translated", "value": "ターミナルにCtrl-Fを送信" } + }, + "km": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "ko": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "nb": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "pl": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "pt-BR": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "ru": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "th": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "tr": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "uk": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } } } }, "shortcut.sendCtrlFToTerminal.label": { "extractionState": "manual", "localizations": { + "ar": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "bs": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "da": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "de": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, "en": { "stringUnit": { "state": "translated", "value": "Send Ctrl-F to Terminal" } }, + "es": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "fr": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "it": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, "ja": { "stringUnit": { "state": "translated", "value": "ターミナルにCtrl-Fを送信" } + }, + "km": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "ko": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "nb": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "pl": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "pt-BR": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "ru": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "th": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "tr": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "uk": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "needs_review", + "value": "Send Ctrl-F to Terminal" + } } } },