Localize tab context menu and alert strings (#1998)

* Pre-launch app for browser UI test on headless CI runners

XCUIApplication.launch() blocks ~60s then fails on headless WarpBuild
runners because foreground activation requires a GUI login session.

Apply the same pre-launch strategy used for the display resolution test:
- CI shell launches the app with env vars before running xcodebuild
- Test detects pre-launched app via manifest, uses activate() instead of
  launch() to avoid killing and relaunching the app
- Falls back to clicking the window for focus via accessibility framework

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Revert "Pre-launch app for browser UI test on headless CI runners"

This reverts commit a540e2fd99aaa1395b91a8d50caa797cdd7551b8.

* Localize tab context menu and alert strings

Replace hardcoded English strings in tab rename/move alert dialogs
with String(localized:defaultValue:) calls. Add 10 new localization
keys to Localizable.xcstrings with translations for all 18 supported
languages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Localize move-failure alert strings

Address CodeRabbit review: localize remaining hardcoded strings
in the move-failure alert dialog (Move Failed, error message, OK button).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: austinpower1258 <austinwang115@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: anthhub <anthhub@163.com>
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
Lawrence Chen 2026-03-31 04:15:40 -07:00 committed by GitHub
parent cfac18b501
commit 02e5ef9455
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 1483 additions and 14 deletions

File diff suppressed because it is too large Load diff

View file

@ -9697,15 +9697,15 @@ final class Workspace: Identifiable, ObservableObject {
let panel = panels[panelId] else { return }
let alert = NSAlert()
alert.messageText = "Rename Tab"
alert.informativeText = "Enter a custom name for this tab."
alert.messageText = String(localized: "alert.renameTab.title", defaultValue: "Rename Tab")
alert.informativeText = String(localized: "alert.renameTab.message", defaultValue: "Enter a custom name for this tab.")
let currentTitle = panelCustomTitles[panelId] ?? panelTitles[panelId] ?? panel.displayTitle
let input = NSTextField(string: currentTitle)
input.placeholderString = "Tab name"
input.placeholderString = String(localized: "alert.renameTab.placeholder", defaultValue: "Tab name")
input.frame = NSRect(x: 0, y: 0, width: 240, height: 22)
alert.accessoryView = input
alert.addButton(withTitle: "Rename")
alert.addButton(withTitle: "Cancel")
alert.addButton(withTitle: String(localized: "alert.renameTab.rename", defaultValue: "Rename"))
alert.addButton(withTitle: String(localized: "alert.cancel", defaultValue: "Cancel"))
let alertWindow = alert.window
alertWindow.initialFirstResponder = input
DispatchQueue.main.async {
@ -9734,24 +9734,24 @@ final class Workspace: Identifiable, ObservableObject {
)
var options: [(title: String, destination: PanelMoveDestination)] = [
("New Workspace in Current Window", .newWorkspaceInCurrentWindow),
("Selected Workspace in New Window", .selectedWorkspaceInNewWindow),
(String(localized: "alert.moveTab.newWorkspaceInCurrentWindow", defaultValue: "New Workspace in Current Window"), .newWorkspaceInCurrentWindow),
(String(localized: "alert.moveTab.selectedWorkspaceInNewWindow", defaultValue: "Selected Workspace in New Window"), .selectedWorkspaceInNewWindow),
]
options.append(contentsOf: workspaceTargets.map { target in
(target.label, .existingWorkspace(target.workspaceId))
})
let alert = NSAlert()
alert.messageText = "Move Tab"
alert.informativeText = "Choose a destination for this tab."
alert.messageText = String(localized: "alert.moveTab.title", defaultValue: "Move Tab")
alert.informativeText = String(localized: "alert.moveTab.message", defaultValue: "Choose a destination for this tab.")
let popup = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 320, height: 26), pullsDown: false)
for option in options {
popup.addItem(withTitle: option.title)
}
popup.selectItem(at: 0)
alert.accessoryView = popup
alert.addButton(withTitle: "Move")
alert.addButton(withTitle: "Cancel")
alert.addButton(withTitle: String(localized: "alert.moveTab.move", defaultValue: "Move"))
alert.addButton(withTitle: String(localized: "alert.cancel", defaultValue: "Cancel"))
guard alert.runModal() == .alertFirstButtonReturn else { return }
let selectedIndex = max(0, min(popup.indexOfSelectedItem, options.count - 1))
@ -9797,9 +9797,9 @@ final class Workspace: Identifiable, ObservableObject {
if !moved {
let failure = NSAlert()
failure.alertStyle = .warning
failure.messageText = "Move Failed"
failure.informativeText = "cmux could not move this tab to the selected destination."
failure.addButton(withTitle: "OK")
failure.messageText = String(localized: "alert.moveTab.failed.title", defaultValue: "Move Failed")
failure.informativeText = String(localized: "alert.moveTab.failed.message", defaultValue: "cmux could not move this tab to the selected destination.")
failure.addButton(withTitle: String(localized: "alert.ok", defaultValue: "OK"))
_ = failure.runModal()
}
}