From 47927d019e57b3ce4fd818d4d36c42c24ff0f85e Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Wed, 10 Jun 2026 13:38:51 -0700
Subject: [PATCH] Add feature interaction usage bucket telemetry (#5119)
Co-authored-by: Orca
---
config/scripts/localize-renderer-strings.mjs | 8 +-
src/main/ipc/telemetry.test.ts | 6 +
src/main/ipc/telemetry.ts | 5 +-
src/main/persistence.test.ts | 246 ++++++++++++++-
src/main/persistence.ts | 102 ++++--
.../src/components/CodexRestartChip.tsx | 12 +-
.../src/components/FirstLaunchBanner.tsx | 25 +-
.../src/components/GitHubItemDialog.tsx | 12 +
.../src/components/GitLabItemDialog.tsx | 295 ++++++++++++++----
.../src/components/JiraIssueWorkspace.tsx | 138 +++++---
.../LinearIssueMarkdownDescriptionEditor.tsx | 87 +++++-
.../src/components/LinearIssueTextEditor.tsx | 27 +-
.../src/components/LinearIssueWorkspace.tsx | 186 ++++++++---
.../src/components/LinearItemDrawer.tsx | 191 +++++++++---
.../components/NewWorkspaceComposerModal.tsx | 6 +-
src/renderer/src/components/QuickOpen.tsx | 56 +++-
.../src/components/SelectedTextCopyMenu.tsx | 3 +-
src/renderer/src/components/StarNagCard.tsx | 26 +-
src/renderer/src/components/TaskPage.tsx | 51 ++-
src/renderer/src/components/Terminal.tsx | 61 +++-
.../src/components/TerminalSearch.tsx | 12 +-
.../src/components/WorktreeJumpPalette.tsx | 26 +-
.../activity/ActivityPrototypePage.tsx | 172 ++++++++--
.../activity/ActivityTitlebarControls.tsx | 19 +-
.../src/components/agent/AgentCombobox.tsx | 28 +-
.../components/agent/AgentSettingsDialog.tsx | 10 +-
.../automations/AutomationCustomCronPanel.tsx | 25 +-
.../AutomationEditorDialogHeader.tsx | 48 ++-
.../AutomationMissedRunGraceField.tsx | 66 +++-
.../automations/AutomationPrecheckFields.tsx | 54 +++-
.../automations/AutomationRunHistory.tsx | 38 ++-
.../automations/AutomationRunPageFrame.tsx | 10 +-
.../automations/AutomationSchedulePicker.tsx | 49 ++-
.../automations/AutomationSessionField.tsx | 20 +-
.../automations/CreateFromPicker.tsx | 33 +-
.../ExternalAutomationManagers.tsx | 130 ++++++--
.../ExternalAutomationRunTable.tsx | 57 +++-
.../automations/HermesCronOutputView.tsx | 15 +-
.../automations/WorkspaceCombobox.tsx | 21 +-
.../external-automation-schedule-display.ts | 5 +-
.../components/browser-pane/BrowserFind.tsx | 19 +-
.../BrowserMobileDriverOverlay.tsx | 26 +-
.../components/browser-pane/BrowserPane.tsx | 6 +
.../browser-pane/GrabConfirmationSheet.tsx | 72 ++++-
.../browser-address-bar-suggestions.ts | 6 +-
.../src/components/confirmation-dialog.tsx | 6 +-
.../ContextualTourControl.tsx | 18 +-
.../ContextualTourOverlaySurface.tsx | 31 +-
.../ContextualTourProgressDots.tsx | 10 +-
.../contextual-tour-overlay-measurement.ts | 8 +-
.../DashboardAgentChildDisclosure.tsx | 10 +-
.../dashboard/DashboardAgentRowMessage.tsx | 11 +-
.../diff-comments/DiffCommentCard.tsx | 48 ++-
.../diff-comments/DiffCommentPopover.tsx | 15 +-
.../diff-comments/useDiffCommentDecorator.tsx | 5 +-
.../src/components/editor/ChangesModeView.tsx | 19 +-
.../components/editor/CodeBlockCopyButton.tsx | 8 +-
.../editor/CombinedDiffFileTree.tsx | 45 ++-
.../components/editor/CombinedDiffViewer.tsx | 157 ++++++++--
.../components/editor/ConflictComponents.tsx | 92 ++++--
.../editor/ConflictReviewFileTree.tsx | 20 +-
.../src/components/editor/CsvViewer.tsx | 12 +-
.../components/editor/DiffNotesSendMenu.tsx | 4 +-
.../src/components/editor/DiffSectionBody.tsx | 24 +-
.../components/editor/DiffSectionHeader.tsx | 2 +-
.../src/components/editor/EditorContent.tsx | 77 +++--
.../editor/EditorPanelMarkdownActionsMenu.tsx | 26 +-
.../components/editor/EditorPanelShell.tsx | 3 +-
.../components/editor/EditorViewToggle.tsx | 16 +-
.../src/components/editor/ImageDiffViewer.tsx | 7 +-
.../src/components/editor/ImageViewer.tsx | 18 +-
.../components/editor/ImageViewerPopup.tsx | 13 +-
.../src/components/editor/IpynbViewer.tsx | 104 ++++--
.../src/components/editor/MarkdownPreview.tsx | 129 ++++++--
.../editor/MarkdownTableOfContentsPanel.tsx | 79 ++++-
.../editor/MarkdownTemplatePicker.tsx | 35 ++-
.../src/components/editor/MermaidBlock.tsx | 5 +-
.../src/components/editor/MonacoEditor.tsx | 12 +-
.../editor/MonacoGutterContextMenu.tsx | 18 +-
.../src/components/editor/NotesSendMenu.tsx | 14 +-
.../src/components/editor/PdfFind.tsx | 15 +-
.../src/components/editor/PdfViewer.tsx | 16 +-
.../editor/ReviewNotesSendMenuContent.tsx | 35 ++-
.../editor/RichMarkdownAnnotationOverlay.tsx | 15 +-
.../editor/RichMarkdownCodeBlock.tsx | 131 ++++++--
.../editor/RichMarkdownDocLinkMenu.tsx | 23 +-
.../editor/RichMarkdownErrorBoundary.tsx | 15 +-
.../editor/RichMarkdownLinkBubble.tsx | 20 +-
.../editor/RichMarkdownReviewNoteLayer.tsx | 35 ++-
.../editor/RichMarkdownReviewRailActions.tsx | 48 ++-
.../editor/RichMarkdownSearchBar.tsx | 36 ++-
.../editor/RichMarkdownSlashMenu.tsx | 22 +-
.../components/editor/RichMarkdownToolbar.tsx | 34 +-
.../editor/UntitledFileRenameDialog.tsx | 42 ++-
.../editor/export-active-markdown.ts | 22 +-
.../components/editor/markdown-rich-mode.ts | 15 +-
.../rich-markdown-editor-click-routing.ts | 8 +-
.../editor/useContextualCopySetup.tsx | 3 +-
.../components/editor/useLocalImagePick.ts | 14 +-
.../editor/useRichMarkdownReviewData.ts | 5 +-
.../components/emulator-pane/EmulatorPane.tsx | 7 +-
.../emulator-pane/emulator-device-frame.tsx | 12 +-
.../emulator-pane/emulator-pane-toolbar.tsx | 51 ++-
.../emulator-screen-stream-content.tsx | 26 +-
.../emulator-unavailable-pane.tsx | 13 +-
.../use-emulator-frame-stream.ts | 8 +-
.../RecoverableRenderErrorBoundary.tsx | 17 +-
...ture-interaction-writer-boundaries.test.ts | 227 ++++++++++++++
.../feature-tips/CliFeatureTipVisual.tsx | 11 +-
.../feature-tips/CliSkillSetupTerminal.tsx | 42 ++-
.../CmdJPaletteFeatureTipVisual.tsx | 10 +-
.../feature-tips/FeatureTipActions.tsx | 3 +-
.../feature-tips/FeatureTipsModal.tsx | 73 ++++-
.../feature-wall/BrowserAnimatedVisual.tsx | 117 +++++--
.../feature-wall/BrowserUseSkillSetupCard.tsx | 10 +-
.../ComputerUseAnimatedVisual.tsx | 72 ++++-
.../feature-wall/EditorAnimatedVisual.tsx | 98 +++++-
.../feature-wall/FeatureTourWorkspaceCard.tsx | 8 +-
.../feature-wall/FeatureWallBody.tsx | 3 +-
.../feature-wall/FeatureWallModal.tsx | 13 +-
.../feature-wall/FeatureWallPreview.tsx | 6 +-
.../feature-wall/FeatureWallRail.tsx | 20 +-
.../FeatureWallSetupChecklist.tsx | 28 +-
.../FeatureWallSetupWorkflowActions.tsx | 77 ++++-
.../feature-wall/FeatureWallTourPanel.tsx | 6 +-
.../feature-wall/ReviewAnimatedVisual.tsx | 4 +-
.../ReviewNotesAnimatedVisual.tsx | 49 ++-
.../feature-wall/ReviewShipAnimatedVisual.tsx | 109 ++++++-
.../feature-wall/TasksAnimatedVisual.tsx | 42 ++-
.../feature-wall/WorkbenchAnimatedVisual.tsx | 160 ++++++++--
.../OrchestrationPage.tsx | 12 +-
.../UsageAccountsCard.tsx | 58 +++-
.../agents-orchestration/UsagePage.tsx | 62 +++-
.../orchestration-cards.tsx | 2 +-
.../feature-wall-usage-tracking.ts | 25 +-
.../review-animated-visual-notes-styles.tsx | 7 +-
.../review-animated-visual-pr-view-styles.tsx | 7 +-
.../review-animated-visual-shared.tsx | 21 +-
.../review-animated-visual-ship-styles.tsx | 7 +-
.../feature-wall/review-notes-diff-rows.tsx | 6 +-
.../FloatingTerminalIconContextMenu.tsx | 17 +-
.../FloatingTerminalOrchestrationDialog.tsx | 44 ++-
.../FloatingTerminalToggleButton.tsx | 23 +-
.../src/components/github-pr-merge-state.ts | 112 +++++--
.../github-project/ColumnResizeHandle.tsx | 5 +-
.../github-project/GhAuthErrorHelp.tsx | 95 +++++-
.../components/github-project/ProjectCell.tsx | 135 ++++++--
.../github-project/ProjectGroupHeader.tsx | 8 +-
.../github-project/ProjectItemSlugDialog.tsx | 14 +-
.../github-project/ProjectPicker.tsx | 101 ++++--
.../components/github-project/ProjectRow.tsx | 20 +-
.../github-project/ProjectViewList.tsx | 20 +-
.../github-project/ProjectViewWrapper.tsx | 140 +++++++--
.../slug-dialog/AssigneesEditor.tsx | 18 +-
.../github-project/slug-dialog/Comments.tsx | 31 +-
.../slug-dialog/LabelsEditor.tsx | 18 +-
.../slug-dialog/SlugDialogBody.tsx | 47 ++-
.../github/GitHubMarkdownComposer.tsx | 18 +-
.../components/github/IssueSourceSelector.tsx | 17 +-
.../components/github/PRFilterDropdowns.tsx | 23 +-
.../src/components/github/PRFilterPickers.tsx | 10 +-
.../components/github/PRFilterSections.tsx | 106 +++++--
.../github/github-rate-limit-display.tsx | 67 +++-
.../gitlab/gitlab-rate-limit-display.tsx | 50 ++-
.../src/components/linear-api-key-dialog.tsx | 47 ++-
.../src/components/linear-priority-icon.tsx | 15 +-
.../linear-project-view-surfaces.tsx | 251 ++++++++++++---
.../src/components/linear-scope-selector.tsx | 36 ++-
.../components/mobile/MobilePageToolbar.tsx | 12 +-
.../src/components/mobile/PhoneCarousel.tsx | 24 +-
.../components/mobile/mobile-platform-copy.ts | 10 +-
.../components/mobile/slides/HomeSlide.tsx | 112 +++++--
.../mobile/slides/TerminalSlide.tsx | 208 +++++++++---
.../mobile/slides/WorktreeListSlide.tsx | 35 ++-
.../new-workspace/SmartWorkspaceNameField.tsx | 148 +++++++--
.../onboarding/AgentFeatureSetupStep.tsx | 6 +-
.../onboarding/FeatureSetupChecklist.tsx | 27 +-
.../onboarding/FeatureSetupInlineTerminal.tsx | 15 +-
.../onboarding/IntegrationsStep.tsx | 121 +++++--
.../onboarding/NotificationStep.tsx | 79 ++++-
.../components/onboarding/OnboardingFlow.tsx | 68 ++--
.../onboarding/OnboardingFooter.tsx | 9 +-
.../OnboardingInlineCommandTerminal.tsx | 6 +-
.../OnboardingSkipConfirmationDialog.tsx | 10 +-
.../onboarding/OnboardingTourStep.tsx | 6 +-
.../src/components/pet/PetOverlay.tsx | 15 +-
src/renderer/src/components/pet/pet-models.ts | 6 +-
.../components/repo/NestedRepoChecklist.tsx | 14 +-
.../repo/NestedRepoScanLimitNotice.tsx | 17 +-
.../right-sidebar/BulkActionBar.tsx | 11 +-
.../components/right-sidebar/FileExplorer.tsx | 6 +-
.../FileExplorerBackgroundMenu.tsx | 12 +-
.../right-sidebar/FileExplorerRow.tsx | 108 +++++--
.../right-sidebar/FileExplorerToolbar.tsx | 45 ++-
.../right-sidebar/FileExplorerTreeStatus.tsx | 12 +-
.../right-sidebar/GitHistoryGraphSvg.tsx | 6 +-
.../right-sidebar/SearchFilters.tsx | 16 +-
.../components/right-sidebar/SearchHeader.tsx | 26 +-
.../right-sidebar/SearchResultItems.tsx | 12 +-
.../SourceControlTextGenerationDialog.tsx | 23 +-
.../right-sidebar/activity-bar-buttons.tsx | 7 +-
.../right-sidebar/checks-panel-empty-state.ts | 86 ++++-
.../right-sidebar/gitlab-mr-merge-state.ts | 56 +++-
.../right-panel-comment-composer.tsx | 58 +++-
...source-control-ai-commit-failure-launch.ts | 49 ++-
.../source-control-discard-confirmation.ts | 50 ++-
.../source-control-discard-dialog.tsx | 35 ++-
.../right-sidebar/use-source-control-ai.ts | 7 +-
.../right-sidebar/useFileDeletion.ts | 37 ++-
.../right-sidebar/useFileExplorerHandlers.ts | 14 +-
.../right-sidebar/useFileExplorerImport.ts | 16 +-
.../right-sidebar/useFileExplorerKeys.ts | 9 +-
.../settings/AgentLocationSetting.tsx | 54 +++-
.../settings/AgentSkillSetupPanel.tsx | 56 +++-
.../components/settings/AppIconSelector.tsx | 12 +-
.../settings/AutoRenameBranchPromptEditor.tsx | 65 +++-
.../src/components/settings/BaseRefPicker.tsx | 62 +++-
.../settings/BrowserDefaultZoomSetting.tsx | 24 +-
.../settings/BrowserHomePageSetting.tsx | 38 ++-
.../settings/BrowserUseComputerUseNotice.tsx | 19 +-
.../settings/BrowserUseEnableSwitch.tsx | 5 +-
.../settings/BrowserUseExamples.tsx | 38 ++-
.../settings/BrowserUseSkillStep.tsx | 10 +-
.../settings/CliSkillRuntimeSetup.tsx | 69 +++-
.../settings/FloatingWorkspacePane.tsx | 2 +
.../settings/GeneralEditorSettingsSection.tsx | 187 +++++++++--
.../GeneralNetworkSettingsSection.tsx | 72 ++++-
.../settings/GeneralSupportSection.tsx | 36 ++-
.../settings/GeneralUpdateSettingsSection.tsx | 119 +++++--
.../GeneralWorkspaceSettingsSection.tsx | 109 +++++--
.../settings/GhosttyImportModal.tsx | 75 ++++-
.../settings/HiddenExperimentalGroup.tsx | 30 +-
.../settings/KagiSessionLinkForm.tsx | 50 ++-
.../settings/KeybindingsFileActions.tsx | 73 ++++-
.../settings/ManageSessionKillDialog.tsx | 32 +-
.../components/settings/McpConfigFileRow.tsx | 7 +-
.../MobileEmulatorAgentControlRow.tsx | 70 ++++-
.../settings/MobileEmulatorExamples.tsx | 39 ++-
.../MobileNetworkInterfaceSection.tsx | 90 +++++-
.../settings/OpenAiTranscriptionKeyDialog.tsx | 50 ++-
.../OpenAiTranscriptionSettingsRow.tsx | 40 ++-
.../settings/OrchestrationExamplesDialog.tsx | 31 +-
.../settings/OrchestrationSetupCard.tsx | 10 +-
.../OrchestrationSkillAgentCoverage.tsx | 17 +-
.../OrchestrationSkillPromptDialog.tsx | 45 ++-
.../PrivacyDiagnosticBundleControls.tsx | 39 ++-
.../src/components/settings/PrivacyPane.tsx | 40 ++-
.../settings/RecentTabOrderControl.tsx | 23 +-
...RepositorySourceControlAiCustomCommand.tsx | 35 ++-
.../RepositorySourceControlAiEnablement.tsx | 43 ++-
...orySourceControlAiHostedReviewDefaults.tsx | 66 +++-
.../RepositorySourceControlAiSection.tsx | 39 ++-
.../settings/RuntimeAccessGrantList.tsx | 67 +++-
.../RuntimePairingGeneratedUrlRows.tsx | 6 +-
.../settings/ShortcutBindingRow.tsx | 61 +++-
.../settings/ShortcutFilterRail.tsx | 30 +-
.../components/settings/ShortcutRowsList.tsx | 6 +-
.../ShortcutTerminalPolicyControl.tsx | 34 +-
.../settings/SshDestructiveActionDialog.tsx | 3 +-
.../settings/SshPassphraseDialog.tsx | 68 +++-
.../src/components/settings/SshTargetCard.tsx | 62 +++-
.../settings/SshTargetDestructiveActions.tsx | 30 +-
.../src/components/settings/SshTargetForm.tsx | 109 +++++--
.../src/components/settings/TasksPane.tsx | 42 ++-
.../settings/TerminalFontSizeSetting.tsx | 21 +-
.../src/components/settings/UIZoomControl.tsx | 3 +-
.../settings/WorktreeSymlinksSection.tsx | 79 ++++-
.../settings/WslCliRegistration.tsx | 123 ++++++--
.../settings/jira-integration-card.tsx | 96 ++++--
.../setup-guide/SetupGuideModal.tsx | 24 +-
.../setup-guide/SetupGuideProgressRing.tsx | 6 +-
.../sidebar/AddProjectFromFolderDialog.tsx | 31 +-
.../components/sidebar/AddRepoCreateStep.tsx | 62 +++-
.../sidebar/AddRepoNestedImportStep.tsx | 69 +++-
.../components/sidebar/AddRepoRemoteStep.tsx | 59 +++-
.../sidebar/AddRepoServerStartStep.tsx | 118 +++++--
.../sidebar/AddRepoStepIndicator.tsx | 3 +-
.../sidebar/AutoRenameFailedDialog.tsx | 37 ++-
.../src/components/sidebar/CacheTimer.tsx | 6 +-
.../sidebar/CreateProjectLocationField.tsx | 47 ++-
.../sidebar/DeleteWorktreeDialogFooter.tsx | 4 +-
.../sidebar/DeleteWorktreeDirtyChangeHint.tsx | 6 +-
.../sidebar/DeleteWorktreeLineageNotice.tsx | 26 +-
.../DeleteWorktreeSkipConfirmOption.tsx | 6 +-
.../sidebar/DeleteWorktreeWarningPanels.tsx | 16 +-
.../ImportedWorktreesVisibilityLine.tsx | 53 +++-
.../components/sidebar/NonGitFolderDialog.tsx | 26 +-
.../sidebar/OrcaYamlTrustDialog.tsx | 65 +++-
.../components/sidebar/PendingWorktreeRow.tsx | 7 +-
.../sidebar/ProjectGroupDeleteDialog.tsx | 25 +-
.../sidebar/ProjectGroupNameDialog.tsx | 13 +-
.../components/sidebar/RemoteFileBrowser.tsx | 34 +-
.../components/sidebar/RemoveFolderDialog.tsx | 22 +-
.../ScrollToCurrentWorkspaceToolbarButton.tsx | 11 +-
.../sidebar/SetupGuideSidebarEntry.tsx | 13 +-
.../sidebar/SetupScriptPromptCardViews.tsx | 106 ++++++-
.../sidebar/SidebarFeedbackDialog.tsx | 86 ++++-
.../src/components/sidebar/SidebarFilter.tsx | 52 ++-
.../SidebarRepositoryFilterSection.tsx | 40 ++-
.../sidebar/SidebarSettingsHelpMenu.tsx | 75 ++++-
.../src/components/sidebar/SidebarToolbar.tsx | 10 +-
.../sidebar/SidebarWorkspaceFilterSection.tsx | 14 +-
.../sidebar/SshDisconnectedDialog.tsx | 35 ++-
.../src/components/sidebar/SshTargetRow.tsx | 5 +-
.../sidebar/WorkspaceKanbanCard.tsx | 2 +-
.../sidebar/WorkspaceKanbanDrawerHeader.tsx | 30 +-
.../sidebar/WorkspaceKanbanPinDropTarget.tsx | 11 +-
.../sidebar/WorkspaceKanbanSettingsMenu.tsx | 45 ++-
.../sidebar/WorkspaceKanbanStatusLane.tsx | 8 +-
.../components/sidebar/WorktreeCardAgents.tsx | 4 +-
.../WorktreeCardMetadataStatusBadges.tsx | 42 ++-
.../components/sidebar/WorktreeCardPorts.tsx | 82 ++++-
.../sidebar/WorktreeContextMenu.tsx | 97 ++++--
.../components/sidebar/WorktreeOpenInMenu.tsx | 45 ++-
.../sidebar/WorktreeTitleInlineRename.tsx | 20 +-
.../sidebar/WorktreeVisibilityDialog.tsx | 33 +-
.../sidebar/add-repo-local-start-actions.ts | 40 ++-
.../sidebar/delete-worktree-flow.ts | 76 +++--
.../sidebar/delete-worktree-toast.ts | 40 ++-
.../sidebar/remote-file-browser-helpers.ts | 36 ++-
.../sidebar/repo-header-create-state.ts | 35 ++-
.../sidebar/sidebar-project-drop.ts | 30 +-
.../components/sidebar/sleep-worktree-flow.ts | 10 +-
.../components/sidebar/useAddRepoCloneFlow.ts | 12 +-
.../sidebar/useAddRepoLocalFolderFlow.ts | 7 +-
.../sidebar/useAddRepoNestedImportFlow.ts | 28 +-
.../sidebar/useSidebarProjectDrop.ts | 41 ++-
.../sidebar/worktree-card-compact-agents.tsx | 22 +-
.../sidebar/worktree-list-groups.ts | 12 +-
.../src/components/skills/SkillsPage.tsx | 100 ++++--
.../stats/ClaudeUsageDailyChart.tsx | 48 ++-
.../components/stats/CodexUsageDailyChart.tsx | 43 ++-
.../src/components/stats/ShareUsageButton.tsx | 21 +-
.../src/components/stats/ShareUsageCard.tsx | 30 +-
.../components/stats/UsageOverviewPane.tsx | 81 ++++-
.../src/components/stats/share-card-utils.tsx | 53 +++-
.../components/stats/usage-overview-model.ts | 6 +-
.../status-bar/PetStatusSegment.tsx | 84 ++++-
.../status-bar/SshStatusSegment.tsx | 41 ++-
.../status-bar/StatusBarUsageEmptyCta.tsx | 49 ++-
.../status-bar/WorkspaceSpaceCompactPanel.tsx | 99 +++++-
.../status-bar/ports-status-popover-rows.tsx | 75 ++++-
.../src/components/status-bar/tooltip.tsx | 53 +++-
.../src/components/tab-bar/BrowserTab.tsx | 28 +-
.../src/components/tab-bar/EditorFileTab.tsx | 6 +-
.../tab-bar/EditorFileTabContextMenu.tsx | 50 ++-
.../components/tab-bar/RecentTabSwitcher.tsx | 8 +-
.../src/components/tab-bar/SortableTab.tsx | 16 +-
.../tab-bar/SortableTabContextMenu.tsx | 86 +++--
.../tab-bar/TabBarQuickCommandsButton.tsx | 98 +++++-
.../src/components/tab-bar/shell-icons.tsx | 6 +-
.../components/tab-group/TabGroupPanel.tsx | 40 ++-
.../terminal-pane/CloseTerminalDialog.tsx | 19 +-
.../terminal-pane/MobileDriverOverlay.tsx | 25 +-
.../TerminalAgentSessionForkDialog.tsx | 42 ++-
.../terminal-pane/TerminalContextMenu.tsx | 90 +++++-
.../terminal-pane/TerminalErrorToast.tsx | 23 +-
.../TerminalSessionStateSaveFailureDialog.tsx | 31 +-
.../osc52-clipboard-blocked-toast.ts | 47 +--
.../terminal-pane/stale-agent-row.ts | 16 +-
.../terminal-agent-session-fork.ts | 53 +++-
.../terminal-pane/terminal-drop-handler.ts | 46 ++-
.../TerminalQuickCommandActionToggle.tsx | 12 +-
.../TerminalQuickCommandAppendEnterSwitch.tsx | 18 +-
.../TerminalQuickCommandDialogFooter.tsx | 18 +-
.../TerminalQuickCommandLabelField.tsx | 12 +-
.../TerminalQuickCommandScopeField.tsx | 39 ++-
.../src/components/ui/color-picker.tsx | 16 +-
src/renderer/src/components/ui/dialog.tsx | 8 +-
.../src/components/ui/repo-multi-combobox.tsx | 31 +-
src/renderer/src/components/ui/sheet.tsx | 4 +-
.../src/components/ui/team-multi-combobox.tsx | 28 +-
.../workspace-space/WorkspaceSpacePage.tsx | 20 +-
.../WorktreeCreationPanel.tsx | 35 ++-
.../src/hooks/useAutomationDispatchEvents.ts | 20 +-
src/renderer/src/hooks/useGlobalFileDrop.ts | 21 +-
src/renderer/src/i18n/locales/es.json | 81 ++++-
src/renderer/src/i18n/locales/ko.json | 61 +++-
src/renderer/src/i18n/locales/zh.json | 61 +++-
.../src/lib/agent-skill-cli-prerequisite.ts | 61 +++-
src/renderer/src/lib/ensure-simulator-tab.ts | 6 +-
.../src/lib/fix-checks-agent-launch.ts | 63 +++-
.../lib/floating-workspace-tab-creation.ts | 2 +-
.../lib/launch-agent-background-session.ts | 7 +-
.../src/lib/launch-agent-in-new-tab.ts | 16 +-
.../src/lib/launch-work-item-direct-agent.ts | 6 +-
src/renderer/src/lib/local-path-open-guard.ts | 7 +-
.../src/lib/resume-sleeping-agent-session.ts | 7 +-
.../lib/source-control-agent-action-plan.ts | 40 ++-
.../src/lib/source-control-generation-plan.ts | 8 +-
src/renderer/src/lib/sparse-preset-draft.ts | 12 +-
...terminal-shortcut-capture-notification.tsx | 45 +--
.../src/lib/workspace-create-error-format.ts | 7 +-
src/renderer/src/main.tsx | 5 +-
src/renderer/src/store/slices/browser.test.ts | 16 +
src/renderer/src/store/slices/browser.ts | 6 +-
src/renderer/src/store/slices/editor.test.ts | 18 ++
src/renderer/src/store/slices/editor.ts | 30 +-
src/renderer/src/store/slices/repos.ts | 36 ++-
.../src/store/slices/sparse-presets.ts | 49 ++-
.../src/store/slices/store-test-helpers.ts | 4 +-
src/renderer/src/store/slices/ui.test.ts | 61 ++++
src/renderer/src/store/slices/ui.ts | 42 ++-
.../src/store/slices/workspace-cleanup.ts | 5 +-
src/renderer/src/web/WebConnect.tsx | 28 +-
src/renderer/src/web/main.tsx | 5 +-
src/renderer/src/web/web-preload-api.test.ts | 42 ++-
src/renderer/src/web/web-preload-api.ts | 9 +-
.../src/web/web-runtime-environment.ts | 2 +-
src/shared/constants.ts | 3 +-
src/shared/feature-interaction-catalog.ts | 162 ++++++++++
src/shared/feature-interaction-categories.ts | 79 +++++
.../feature-interaction-usage-buckets.ts | 69 ++++
src/shared/feature-interactions.test.ts | 91 +++++-
src/shared/feature-interactions.ts | 243 +++------------
src/shared/telemetry-events.test.ts | 109 +++++++
src/shared/telemetry-events.ts | 48 ++-
src/shared/types.ts | 7 +-
418 files changed, 13870 insertions(+), 3196 deletions(-)
create mode 100644 src/renderer/src/components/feature-interaction-writer-boundaries.test.ts
create mode 100644 src/shared/feature-interaction-catalog.ts
create mode 100644 src/shared/feature-interaction-categories.ts
create mode 100644 src/shared/feature-interaction-usage-buckets.ts
diff --git a/config/scripts/localize-renderer-strings.mjs b/config/scripts/localize-renderer-strings.mjs
index 34b01c7370c..459a16ee387 100644
--- a/config/scripts/localize-renderer-strings.mjs
+++ b/config/scripts/localize-renderer-strings.mjs
@@ -74,7 +74,9 @@ function editForCandidate(candidate, key, translation, sourceFile) {
}
function sourceKindForPath(filePath) {
- return filePath.endsWith('.tsx') || filePath.endsWith('.jsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS
+ return filePath.endsWith('.tsx') || filePath.endsWith('.jsx')
+ ? ts.ScriptKind.TSX
+ : ts.ScriptKind.TS
}
function findNodeByRange(sourceFile, start, end) {
@@ -201,7 +203,9 @@ async function collectCandidateFiles(root) {
for (const entry of entries) {
const fullPath = path.join(dir, entry.name)
if (entry.isDirectory()) {
- if (!['.git', 'assets', 'dist', 'node_modules', 'out', '__snapshots__'].includes(entry.name)) {
+ if (
+ !['.git', 'assets', 'dist', 'node_modules', 'out', '__snapshots__'].includes(entry.name)
+ ) {
stack.push(fullPath)
}
continue
diff --git a/src/main/ipc/telemetry.test.ts b/src/main/ipc/telemetry.test.ts
index 4d02a8d1df6..162ee86ba7a 100644
--- a/src/main/ipc/telemetry.test.ts
+++ b/src/main/ipc/telemetry.test.ts
@@ -160,6 +160,12 @@ describe('telemetry IPC handlers', () => {
registerWith({ installId: 'x', existedBeforeTelemetryRelease: false, optedIn: true })
const handler = handlers.get('telemetry:track')!
handler({}, 'app_starred_orca', { source: 'settings' })
+ handler({}, 'feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_1',
+ bucket_source: 'crossed_now'
+ })
expect(trackMock).not.toHaveBeenCalled()
expect(getCohortAtEmitMock).not.toHaveBeenCalled()
})
diff --git a/src/main/ipc/telemetry.ts b/src/main/ipc/telemetry.ts
index c5fe79b833d..a4faa9d7927 100644
--- a/src/main/ipc/telemetry.ts
+++ b/src/main/ipc/telemetry.ts
@@ -53,7 +53,10 @@ import type { OptInVia } from '../../shared/telemetry-events'
// mirrors how other core-handlers accept the store explicitly.
let storeRef: Store | null = null
-const MAIN_OWNED_TELEMETRY_EVENTS = new Set(['app_starred_orca'])
+const MAIN_OWNED_TELEMETRY_EVENTS = new Set([
+ 'app_starred_orca',
+ 'feature_interaction_usage_bucket_reached'
+])
/**
* Derive the `via` discriminator for a `telemetry:setOptIn` call from
diff --git a/src/main/persistence.test.ts b/src/main/persistence.test.ts
index 3dfe7ab4ec2..4f9f9b8179c 100644
--- a/src/main/persistence.test.ts
+++ b/src/main/persistence.test.ts
@@ -81,6 +81,11 @@ const WORKFLOW_DEFAULT_WORKSPACE_STATUSES = [
{ id: 'todo', label: 'Todo', color: 'neutral', icon: 'circle' }
]
+const { trackMock, getCohortAtEmitMock } = vi.hoisted(() => ({
+ trackMock: vi.fn(),
+ getCohortAtEmitMock: vi.fn()
+}))
+
vi.mock('electron', () => ({
app: {
getPath: () => testState.dir
@@ -102,6 +107,14 @@ vi.mock('./git/repo', () => ({
getGitUsername: vi.fn().mockReturnValue('testuser')
}))
+vi.mock('./telemetry/client', () => ({
+ track: trackMock
+}))
+
+vi.mock('./telemetry/cohort-classifier', () => ({
+ getCohortAtEmit: getCohortAtEmitMock
+}))
+
/** Reset modules and dynamically import Store so the data-file path picks up the current testState.dir */
async function createStore() {
vi.resetModules()
@@ -257,6 +270,9 @@ function makeBalancedLegacyPaneLayout(start: number, end: number): TerminalPaneL
describe('Store', () => {
beforeEach(() => {
testState.dir = mkdtempSync(join(tmpdir(), 'orca-test-'))
+ trackMock.mockReset()
+ getCohortAtEmitMock.mockReset()
+ getCohortAtEmitMock.mockReturnValue({ nth_repo_added: 2 })
})
afterEach(() => {
@@ -268,7 +284,7 @@ describe('Store', () => {
it('returns empty repos when no data file exists', async () => {
const store = await createStore()
expect(store.getRepos()).toEqual([])
- })
+ }, 15_000)
it('returns default settings when no data file exists', async () => {
const store = await createStore()
@@ -3037,6 +3053,61 @@ describe('Store', () => {
})
})
+ it('normalizes malformed main-owned feature telemetry bucket markers on read', async () => {
+ writeDataFile({
+ schemaVersion: 1,
+ repos: [],
+ worktreeMeta: {},
+ settings: {},
+ ui: {},
+ githubCache: { pr: {}, issue: {} },
+ workspaceSession: {},
+ featureInteractionTelemetryBuckets: {
+ tasks: 'count_2',
+ browser: 'count_4',
+ unknown: 'count_1'
+ }
+ })
+
+ const store = await createStore()
+ store.flush()
+
+ const persisted = readDataFile() as PersistedState
+ expect(persisted.featureInteractionTelemetryBuckets).toEqual({ tasks: 'count_2' })
+ })
+
+ it('does not expose or accept UI shadow writes for main-owned feature telemetry markers', async () => {
+ writeDataFile({
+ schemaVersion: 1,
+ repos: [],
+ worktreeMeta: {},
+ settings: {},
+ ui: {
+ featureInteractionTelemetryBuckets: { tasks: 'count_1000_plus' }
+ },
+ githubCache: { pr: {}, issue: {} },
+ workspaceSession: {},
+ featureInteractionTelemetryBuckets: { tasks: 'count_2' }
+ })
+
+ const store = await createStore()
+
+ expect('featureInteractionTelemetryBuckets' in (store.getUI() as Record)).toBe(
+ false
+ )
+
+ store.updateUI({
+ featureInteractionTelemetryBuckets: { tasks: 'count_500_999' }
+ } as never)
+ store.flush()
+
+ const persisted = readDataFile() as PersistedState & {
+ ui: Record
+ }
+ expect(persisted.featureInteractionTelemetryBuckets).toEqual({ tasks: 'count_2' })
+ expect(persisted.ui.featureInteractionTelemetryBuckets).toBeUndefined()
+ })
+
it('normalizes feature tip ids from direct UI writes', async () => {
const store = await createStore()
@@ -3068,6 +3139,179 @@ describe('Store', () => {
})
})
+ it('emits feature interaction telemetry only when a higher bucket is reached', async () => {
+ const store = await createStore()
+
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+ store.flush()
+
+ expect(trackMock).toHaveBeenCalledTimes(3)
+ expect(trackMock).toHaveBeenNthCalledWith(1, 'feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_1',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ expect(trackMock).toHaveBeenNthCalledWith(2, 'feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_2',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ expect(trackMock).toHaveBeenNthCalledWith(3, 'feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_3_4',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ expect((readDataFile() as PersistedState).featureInteractionTelemetryBuckets).toEqual({
+ tasks: 'count_3_4'
+ })
+ })
+
+ it('emits one observed-existing bucket for pre-rollout interaction counts', async () => {
+ const store = await createStore()
+ store.updateUI({
+ featureInteractions: {
+ tasks: { firstInteractedAt: 100, interactionCount: 137 }
+ }
+ })
+ trackMock.mockClear()
+
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+ store.flush()
+
+ expect(trackMock).toHaveBeenCalledTimes(1)
+ expect(trackMock).toHaveBeenCalledWith('feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_100_199',
+ bucket_source: 'observed_existing',
+ nth_repo_added: 2
+ })
+ expect((readDataFile() as PersistedState).featureInteractionTelemetryBuckets).toEqual({
+ tasks: 'count_100_199'
+ })
+ })
+
+ it('emits only the top-coded observed-existing bucket for pre-rollout power users', async () => {
+ const store = await createStore()
+ store.updateUI({
+ featureInteractions: {
+ tasks: { firstInteractedAt: 100, interactionCount: 1200 }
+ }
+ })
+ trackMock.mockClear()
+
+ store.recordFeatureInteraction('tasks')
+
+ expect(trackMock).toHaveBeenCalledTimes(1)
+ expect(trackMock).toHaveBeenCalledWith('feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_1000_plus',
+ bucket_source: 'observed_existing',
+ nth_repo_added: 2
+ })
+ })
+
+ it('emits high bucket crossings once and ignores same-range increments', async () => {
+ writeDataFile({
+ schemaVersion: 1,
+ repos: [],
+ worktreeMeta: {},
+ settings: {},
+ ui: {
+ featureInteractions: {
+ tasks: { firstInteractedAt: 100, interactionCount: 198 }
+ }
+ },
+ githubCache: { pr: {}, issue: {} },
+ workspaceSession: {},
+ featureInteractionTelemetryBuckets: { tasks: 'count_100_199' }
+ })
+ const store = await createStore()
+
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+
+ expect(trackMock).toHaveBeenCalledTimes(1)
+ expect(trackMock).toHaveBeenCalledWith('feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_200_499',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ })
+
+ it('does not emit for count 4 but emits the count_1000_plus crossing', async () => {
+ const store = await createStore()
+
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+ store.recordFeatureInteraction('tasks')
+ trackMock.mockClear()
+
+ store.recordFeatureInteraction('tasks')
+ expect(trackMock).not.toHaveBeenCalled()
+
+ writeDataFile({
+ schemaVersion: 1,
+ repos: [],
+ worktreeMeta: {},
+ settings: {},
+ ui: {
+ featureInteractions: {
+ tasks: { firstInteractedAt: 100, interactionCount: 999 }
+ }
+ },
+ githubCache: { pr: {}, issue: {} },
+ workspaceSession: {},
+ featureInteractionTelemetryBuckets: { tasks: 'count_500_999' }
+ })
+ const reloaded = await createStore()
+
+ reloaded.recordFeatureInteraction('tasks')
+ expect(trackMock).toHaveBeenCalledTimes(1)
+ expect(trackMock).toHaveBeenCalledWith('feature_interaction_usage_bucket_reached', {
+ feature_id: 'tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_1000_plus',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ })
+
+ it('dedupes against the persisted bucket marker', async () => {
+ writeDataFile({
+ schemaVersion: 1,
+ repos: [],
+ worktreeMeta: {},
+ settings: {},
+ ui: {
+ featureInteractions: {
+ tasks: { firstInteractedAt: 100, interactionCount: 100 }
+ }
+ },
+ githubCache: { pr: {}, issue: {} },
+ workspaceSession: {},
+ featureInteractionTelemetryBuckets: { tasks: 'count_100_199' }
+ })
+ const store = await createStore()
+
+ store.recordFeatureInteraction('tasks')
+
+ expect(trackMock).not.toHaveBeenCalled()
+ })
+
it('updateUI restores fixed card properties from direct UI writes', async () => {
const store = await createStore()
store.updateUI({ worktreeCardProperties: ['inline-agents'] })
diff --git a/src/main/persistence.ts b/src/main/persistence.ts
index 395049ca32b..71aeb870e83 100644
--- a/src/main/persistence.ts
+++ b/src/main/persistence.ts
@@ -94,7 +94,11 @@ import { normalizeTerminalShortcutPolicy } from '../shared/keybindings'
import { normalizeAppIconId } from '../shared/app-icon'
import { normalizeTerminalCustomThemes } from '../shared/terminal-custom-themes'
import {
+ compareFeatureInteractionUsageBuckets,
+ getFeatureInteractionCategory,
+ getFeatureInteractionUsageBucket,
normalizeFeatureInteractions,
+ normalizeFeatureInteractionTelemetryBuckets,
type FeatureInteractionId
} from '../shared/feature-interactions'
import { normalizeContextualTourIds } from '../shared/contextual-tours'
@@ -134,6 +138,8 @@ import {
migrateWorkspaceSessionTerminalScrollbackSnapshots,
readTerminalScrollbackSnapshotSync
} from './terminal-scrollback-snapshots'
+import { track } from './telemetry/client'
+import { getCohortAtEmit } from './telemetry/cohort-classifier'
function encrypt(plaintext: string): string {
if (!plaintext || !safeStorage.isEncryptionAvailable()) {
@@ -324,6 +330,21 @@ function mergeContextualTourSeenIds(
return [...merged]
}
+function stripMainOwnedTelemetryMarkerFromUI(
+ value: Partial | undefined
+): Partial {
+ if (!value || typeof value !== 'object') {
+ return {}
+ }
+ const { featureInteractionTelemetryBuckets: _reserved, ...ui } = value as Partial<
+ PersistedState['ui']
+ > & {
+ featureInteractionTelemetryBuckets?: unknown
+ }
+ void _reserved
+ return ui
+}
+
function normalizeSortBy(sortBy: unknown): PersistedState['ui']['sortBy'] {
if (
sortBy === 'smart' ||
@@ -1900,6 +1921,9 @@ export class Store {
result = {
...defaults,
...parsed,
+ featureInteractionTelemetryBuckets: normalizeFeatureInteractionTelemetryBuckets(
+ parsed.featureInteractionTelemetryBuckets
+ ),
projectGroups: normalizeProjectGroups(parsed.projectGroups),
worktreeLineageById: parsed.worktreeLineageById ?? {},
settings: {
@@ -2106,7 +2130,7 @@ export class Store {
}
return {
...defaults.ui,
- ...parsed.ui,
+ ...stripMainOwnedTelemetryMarkerFromUI(parsed.ui),
// Why: migrate once from the retired Appearance setting only
// when no explicit persisted chrome preference exists yet.
rightSidebarOpen,
@@ -3175,9 +3199,10 @@ export class Store {
// ── UI State ───────────────────────────────────────────────────────
getUI(): PersistedState['ui'] {
+ const uiState = stripMainOwnedTelemetryMarkerFromUI(this.state.ui)
return {
...getDefaultUIState(),
- ...this.state.ui,
+ ...uiState,
groupBy: normalizeGroupBy(this.state.ui?.groupBy),
sortBy: normalizeSortBy(this.state.ui?.sortBy),
projectOrderBy: normalizeProjectOrderBy(this.state.ui?.projectOrderBy),
@@ -3206,39 +3231,44 @@ export class Store {
}
updateUI(updates: Partial): void {
+ const sanitizedUpdates = stripMainOwnedTelemetryMarkerFromUI(updates)
+ const currentUI = {
+ ...getDefaultUIState(),
+ ...stripMainOwnedTelemetryMarkerFromUI(this.state.ui)
+ }
this.state.ui = {
- ...this.state.ui,
- ...updates,
- groupBy: updates.groupBy
- ? normalizeGroupBy(updates.groupBy)
+ ...currentUI,
+ ...sanitizedUpdates,
+ groupBy: sanitizedUpdates.groupBy
+ ? normalizeGroupBy(sanitizedUpdates.groupBy)
: normalizeGroupBy(this.state.ui?.groupBy),
- sortBy: updates.sortBy
- ? normalizeSortBy(updates.sortBy)
+ sortBy: sanitizedUpdates.sortBy
+ ? normalizeSortBy(sanitizedUpdates.sortBy)
: normalizeSortBy(this.state.ui?.sortBy),
projectOrderBy: updates.projectOrderBy
? normalizeProjectOrderBy(updates.projectOrderBy)
: normalizeProjectOrderBy(this.state.ui?.projectOrderBy),
rightSidebarTab:
- updates.rightSidebarTab !== undefined
- ? normalizeRightSidebarTab(updates.rightSidebarTab)
+ sanitizedUpdates.rightSidebarTab !== undefined
+ ? normalizeRightSidebarTab(sanitizedUpdates.rightSidebarTab)
: normalizeRightSidebarTab(this.state.ui?.rightSidebarTab),
worktreeCardProperties:
- updates.worktreeCardProperties !== undefined
- ? normalizeWorktreeCardProperties(updates.worktreeCardProperties)
+ sanitizedUpdates.worktreeCardProperties !== undefined
+ ? normalizeWorktreeCardProperties(sanitizedUpdates.worktreeCardProperties)
: normalizeWorktreeCardProperties(this.state.ui?.worktreeCardProperties),
agentActivityDisplayMode:
updates.agentActivityDisplayMode !== undefined
? normalizeAgentActivityDisplayMode(updates.agentActivityDisplayMode)
: normalizeAgentActivityDisplayMode(this.state.ui?.agentActivityDisplayMode),
workspaceStatuses:
- updates.workspaceStatuses !== undefined
- ? normalizeWorkspaceStatuses(updates.workspaceStatuses)
+ sanitizedUpdates.workspaceStatuses !== undefined
+ ? normalizeWorkspaceStatuses(sanitizedUpdates.workspaceStatuses)
: normalizeWorkspaceStatuses(this.state.ui?.workspaceStatuses),
workspaceBoardOpacity: clampWorkspaceBoardOpacity(
- updates.workspaceBoardOpacity ?? this.state.ui?.workspaceBoardOpacity
+ sanitizedUpdates.workspaceBoardOpacity ?? this.state.ui?.workspaceBoardOpacity
),
workspaceBoardColumnWidth: clampWorkspaceBoardColumnWidth(
- updates.workspaceBoardColumnWidth ?? this.state.ui?.workspaceBoardColumnWidth
+ sanitizedUpdates.workspaceBoardColumnWidth ?? this.state.ui?.workspaceBoardColumnWidth
),
browserDefaultZoomLevel: normalizeBrowserPageZoomLevel(
updates.browserDefaultZoomLevel ?? this.state.ui?.browserDefaultZoomLevel
@@ -3248,8 +3278,8 @@ export class Store {
? normalizeShowDotfilesByWorktree(updates.showDotfilesByWorktree)
: normalizeShowDotfilesByWorktree(this.state.ui?.showDotfilesByWorktree),
featureTipsSeenIds:
- updates.featureTipsSeenIds !== undefined
- ? normalizeFeatureTipIds(updates.featureTipsSeenIds)
+ sanitizedUpdates.featureTipsSeenIds !== undefined
+ ? normalizeFeatureTipIds(sanitizedUpdates.featureTipsSeenIds)
: normalizeFeatureTipIds(this.state.ui?.featureTipsSeenIds),
// Why: renderer and paired clients can mark different tours seen from
// stale UI snapshots; union them so completed tours stay suppressed.
@@ -3264,10 +3294,10 @@ export class Store {
// Merge instead of replacing so a stale renderer snapshot cannot erase
// runtime-only feature interactions.
featureInteractions:
- updates.featureInteractions !== undefined
+ sanitizedUpdates.featureInteractions !== undefined
? mergeFeatureInteractions(
this.state.ui?.featureInteractions,
- updates.featureInteractions
+ sanitizedUpdates.featureInteractions
)
: normalizeFeatureInteractions(this.state.ui?.featureInteractions)
}
@@ -3276,16 +3306,46 @@ export class Store {
recordFeatureInteraction(id: FeatureInteractionId): PersistedState['ui'] {
const featureInteractions = normalizeFeatureInteractions(this.state.ui?.featureInteractions)
+ const telemetryBuckets = normalizeFeatureInteractionTelemetryBuckets(
+ this.state.featureInteractionTelemetryBuckets
+ )
const existing = featureInteractions[id]
+ const previousCount = existing?.interactionCount ?? 0
+ const nextCount = previousCount + 1
+ const previousBucket = getFeatureInteractionUsageBucket(previousCount)
+ const nextBucket = getFeatureInteractionUsageBucket(nextCount)
+ const lastEmittedBucket = telemetryBuckets[id] ?? null
+ const shouldEmit =
+ nextBucket !== null &&
+ (lastEmittedBucket === null ||
+ compareFeatureInteractionUsageBuckets(nextBucket, lastEmittedBucket) > 0)
+
this.updateUI({
featureInteractions: {
...featureInteractions,
[id]: {
firstInteractedAt: existing?.firstInteractedAt ?? Date.now(),
- interactionCount: (existing?.interactionCount ?? 0) + 1
+ interactionCount: nextCount
}
}
})
+ this.state.featureInteractionTelemetryBuckets = shouldEmit
+ ? { ...telemetryBuckets, [id]: nextBucket }
+ : telemetryBuckets
+ this.scheduleSave()
+
+ if (shouldEmit) {
+ track('feature_interaction_usage_bucket_reached', {
+ feature_id: id,
+ feature_category: getFeatureInteractionCategory(id),
+ count_bucket: nextBucket,
+ bucket_source:
+ lastEmittedBucket === null && previousBucket !== null && previousBucket === nextBucket
+ ? 'observed_existing'
+ : 'crossed_now',
+ ...getCohortAtEmit()
+ })
+ }
return this.getUI()
}
diff --git a/src/renderer/src/components/CodexRestartChip.tsx b/src/renderer/src/components/CodexRestartChip.tsx
index 89c42cb2398..d2455f0c7e0 100644
--- a/src/renderer/src/components/CodexRestartChip.tsx
+++ b/src/renderer/src/components/CodexRestartChip.tsx
@@ -74,7 +74,11 @@ export default function CodexRestartChip({
- {translate("auto.components.CodexRestartChip.9263e75f49", "Codex is using the previous account")}
+ {translate(
+ 'auto.components.CodexRestartChip.9263e75f49',
+ 'Codex is using the previous account'
+ )}
+
- {translate("auto.components.CodexRestartChip.c72a5fb234", "Restart")}
+ {translate('auto.components.CodexRestartChip.c72a5fb234', 'Restart')}
+
dismissStaleWorktreePtyIds(staleWorktreePtyIds, clearCodexRestartNotice)}
className="rounded-md px-1.5 py-1 text-[11px] text-muted-foreground transition-colors hover:bg-accent/60 hover:text-foreground"
>
- {translate("auto.components.CodexRestartChip.9132779820", "Dismiss")}
+ {translate('auto.components.CodexRestartChip.9132779820', 'Dismiss')}
+
diff --git a/src/renderer/src/components/FirstLaunchBanner.tsx b/src/renderer/src/components/FirstLaunchBanner.tsx
index 9a44ed3a6ed..2237770e2f2 100644
--- a/src/renderer/src/components/FirstLaunchBanner.tsx
+++ b/src/renderer/src/components/FirstLaunchBanner.tsx
@@ -128,21 +128,30 @@ export function FirstLaunchBanner({
{/* Text column — title + body stack on the left, takes remaining
width so the action column never pushes copy into a wrap. */}
-
{translate("auto.components.FirstLaunchBanner.9784b4d7bc", "Help us decide what to build next")}
+
+ {translate(
+ 'auto.components.FirstLaunchBanner.9784b4d7bc',
+ 'Help us decide what to build next'
+ )}
+
- {translate("auto.components.FirstLaunchBanner.958d2cc31b", "Anonymous counts of which features you use help us prioritize what to build. No file contents, prompts, terminal output, or anything that identifies you. Change anytime in Settings -> Privacy & Telemetry.")}{' '}
+ {translate(
+ 'auto.components.FirstLaunchBanner.958d2cc31b',
+ 'Anonymous counts of which features you use help us prioritize what to build. No file contents, prompts, terminal output, or anything that identifies you. Change anytime in Settings -> Privacy & Telemetry.'
+ )}{' '}
void window.api.shell.openUrl(PRIVACY_URL)}
>
- {translate("auto.components.FirstLaunchBanner.d1deebb050", "Privacy policy")}
+ {translate('auto.components.FirstLaunchBanner.d1deebb050', 'Privacy policy')}
+
.
@@ -160,15 +169,17 @@ export function FirstLaunchBanner({
disabled={inFlight}
className="border-border/60 text-muted-foreground"
>
- {translate("auto.components.FirstLaunchBanner.fc5cc29955", "Opt out")}
+ {translate('auto.components.FirstLaunchBanner.fc5cc29955', 'Opt out')}
+
- {translate("auto.components.FirstLaunchBanner.94cc673726", "Got it")}
+ {translate('auto.components.FirstLaunchBanner.94cc673726', 'Got it')}
+
{/* aria-label says "Dismiss" — the action persists silent opt-in,
not just hides the UI. */}
{
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
patchWorkItem(item.id, { state: newState }, item.repoId)
patchProjectRowIfNeeded({ state: newState })
onMutated()
@@ -4594,6 +4601,7 @@ function GHEditSection({
patchProjectRowIfNeeded({ labels: newLabels })
},
onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
onMutated()
},
onRevert: () => {
@@ -4624,6 +4632,7 @@ function GHEditSection({
patchProjectRowIfNeeded({ labels: prevLabels })
},
onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
onMutated()
},
onError: (err) => toast.error(err)
@@ -4675,6 +4684,7 @@ function GHEditSection({
patchProjectRowIfNeeded({ assignees: prevAssignees })
},
onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
onMutated()
},
onError: (err) => toast.error(err)
@@ -4694,6 +4704,7 @@ function GHEditSection({
patchProjectRowIfNeeded({ assignees: newAssignees })
},
onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
onMutated()
},
onRevert: () => {
@@ -5798,6 +5809,7 @@ export default function GitHubItemDialog({
const appendOptimisticComment = useCallback(
(comment: PRComment) => {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
// Why: skip refreshDetails() — gh api --cache 60s returns stale data
// that overwrites the optimistic comment. The next dialog open (after
// cache expiry) will pick up the server-confirmed version.
diff --git a/src/renderer/src/components/GitLabItemDialog.tsx b/src/renderer/src/components/GitLabItemDialog.tsx
index 14a9cd95d76..efd9848a0df 100644
--- a/src/renderer/src/components/GitLabItemDialog.tsx
+++ b/src/renderer/src/components/GitLabItemDialog.tsx
@@ -31,6 +31,7 @@ import CommentMarkdown from '@/components/sidebar/CommentMarkdown'
import { isScreenSubmitShortcut } from '@/lib/screen-submit-shortcut'
import { useMountedRef } from '@/hooks/useMountedRef'
import { cn } from '@/lib/utils'
+import { useAppStore } from '@/store'
import type {
GitLabAssignableUser,
GitLabPipelineJob,
@@ -174,7 +175,8 @@ function CommentCard({
{comment.author}
{comment.isResolved ? (
- {translate("auto.components.GitLabItemDialog.f23ea85341", "resolved")}
+ {translate('auto.components.GitLabItemDialog.f23ea85341', 'resolved')}
+
) : null}
@@ -188,7 +190,9 @@ function CommentCard({
className="h-6"
>
{resolving ?
: null}
- {comment.isResolved ? translate("auto.components.GitLabItemDialog.65e784c1f1", "Reopen") : translate("auto.components.GitLabItemDialog.4168eb2c51", "Resolve")}
+ {comment.isResolved
+ ? translate('auto.components.GitLabItemDialog.65e784c1f1', 'Reopen')
+ : translate('auto.components.GitLabItemDialog.4168eb2c51', 'Resolve')}
) : null}
{comment.createdAt ? new Date(comment.createdAt).toLocaleDateString() : ''}
@@ -260,7 +264,8 @@ function PipelineJobRow({
className="h-6"
>
{retrying ?
: null}
- {translate("auto.components.GitLabItemDialog.fa3e042203", "Retry")}
+ {translate('auto.components.GitLabItemDialog.fa3e042203', 'Retry')}
+
) : null}
{job.webUrl ? (
void window.api.shell.openUrl(job.webUrl)}
- title={translate("auto.components.GitLabItemDialog.032ae1312b", "Open job in GitLab")}
+ title={translate('auto.components.GitLabItemDialog.032ae1312b', 'Open job in GitLab')}
>
@@ -278,19 +283,23 @@ function PipelineJobRow({
{expanded ? (
- {translate("auto.components.GitLabItemDialog.2f9b27f838", "Job log")}
+ {translate('auto.components.GitLabItemDialog.2f9b27f838', 'Job log')}
onToggleTrace(job)}>
- {translate("auto.components.GitLabItemDialog.028bde664e", "Hide")}
+ {translate('auto.components.GitLabItemDialog.028bde664e', 'Hide')}
+
{traceState?.loading ? (
- {translate("auto.components.GitLabItemDialog.d600c2619a", "Loading log")}
+ {translate('auto.components.GitLabItemDialog.d600c2619a', 'Loading log')}
+
) : traceState?.error ? (
{traceState.error}
) : (
- {traceState?.trace?.trim() ? traceState.trace : translate("auto.components.GitLabItemDialog.32f8bef818", "No log output.")}
+ {traceState?.trace?.trim()
+ ? traceState.trace
+ : translate('auto.components.GitLabItemDialog.32f8bef818', 'No log output.')}
)}
@@ -484,7 +493,7 @@ export default function GitLabItemDialog({
const nextBody = bodyDraft
const nextLabels = parseGitLabLabelDraft(labelDraft)
if (!nextTitle) {
- toast.error(translate("auto.components.GitLabItemDialog.98718490e4", "MR title is required."))
+ toast.error(translate('auto.components.GitLabItemDialog.98718490e4', 'MR title is required.'))
return
}
@@ -531,6 +540,7 @@ export default function GitLabItemDialog({
setTitleDraft('')
setBodyDraft('')
setLabelDraft('')
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
}
} else if (mountedRef.current) {
toast.error(res.error)
@@ -611,7 +621,11 @@ export default function GitLabItemDialog({
return
}
if (result.ok) {
- toast.success(translate("auto.components.GitLabItemDialog.f7cb495a12", "Retried {{value0}}", { value0: job.name }))
+ toast.success(
+ translate('auto.components.GitLabItemDialog.f7cb495a12', 'Retried {{value0}}', {
+ value0: job.name
+ })
+ )
if (result.job) {
setDetails((current) =>
current
@@ -646,7 +660,12 @@ export default function GitLabItemDialog({
.map((reviewer) => reviewer.id)
.filter((id): id is number => typeof id === 'number')
if (reviewerIds.length !== nextReviewers.length) {
- toast.error(translate("auto.components.GitLabItemDialog.ceaf7c30c7", "Reviewer id is unavailable for this GitLab user."))
+ toast.error(
+ translate(
+ 'auto.components.GitLabItemDialog.ceaf7c30c7',
+ 'Reviewer id is unavailable for this GitLab user.'
+ )
+ )
return
}
setReviewerUpdating(true)
@@ -668,6 +687,7 @@ export default function GitLabItemDialog({
setReviewerOptions((current) =>
current ? dedupeGitLabUsers([...current, ...result.reviewers]) : current
)
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
} else {
toast.error(result.error)
}
@@ -688,11 +708,21 @@ export default function GitLabItemDialog({
const line = Number.parseInt(inlineCommentLine, 10)
const body = inlineCommentBody.trim()
if (!file || !Number.isFinite(line) || line <= 0 || !body) {
- toast.error(translate("auto.components.GitLabItemDialog.00d0d25825", "File, line, and comment are required."))
+ toast.error(
+ translate(
+ 'auto.components.GitLabItemDialog.00d0d25825',
+ 'File, line, and comment are required.'
+ )
+ )
return
}
if (!details.baseSha || !details.startSha || !details.headSha) {
- toast.error(translate("auto.components.GitLabItemDialog.ffdd9a78e1", "MR diff refs are unavailable for inline comments."))
+ toast.error(
+ translate(
+ 'auto.components.GitLabItemDialog.ffdd9a78e1',
+ 'MR diff refs are unavailable for inline comments.'
+ )
+ )
return
}
setInlineCommentSubmitting(true)
@@ -719,7 +749,10 @@ export default function GitLabItemDialog({
current ? { ...current, comments: [...current.comments, result.comment] } : current
)
setInlineCommentBody('')
- toast.success(translate("auto.components.GitLabItemDialog.60c13320c4", "Inline comment added"))
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
+ toast.success(
+ translate('auto.components.GitLabItemDialog.60c13320c4', 'Inline comment added')
+ )
} else {
toast.error(result.error)
}
@@ -747,7 +780,12 @@ export default function GitLabItemDialog({
const res = await window.api.gl.closeMR({ repoPath, iid: item.number })
if (res.ok) {
if (mountedRef.current) {
- toast.success(translate("auto.components.GitLabItemDialog.9b11cd233f", "Closed MR !{{value0}}", { value0: item.number }))
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
+ toast.success(
+ translate('auto.components.GitLabItemDialog.9b11cd233f', 'Closed MR !{{value0}}', {
+ value0: item.number
+ })
+ )
handleRefresh()
}
} else {
@@ -771,7 +809,12 @@ export default function GitLabItemDialog({
const res = await window.api.gl.reopenMR({ repoPath, iid: item.number })
if (res.ok) {
if (mountedRef.current) {
- toast.success(translate("auto.components.GitLabItemDialog.865ea2703e", "Reopened MR !{{value0}}", { value0: item.number }))
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
+ toast.success(
+ translate('auto.components.GitLabItemDialog.865ea2703e', 'Reopened MR !{{value0}}', {
+ value0: item.number
+ })
+ )
handleRefresh()
}
} else {
@@ -795,7 +838,12 @@ export default function GitLabItemDialog({
const res = await window.api.gl.mergeMR({ repoPath, iid: item.number })
if (res.ok) {
if (mountedRef.current) {
- toast.success(translate("auto.components.GitLabItemDialog.e089f62594", "Merged MR !{{value0}}", { value0: item.number }))
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
+ toast.success(
+ translate('auto.components.GitLabItemDialog.e089f62594', 'Merged MR !{{value0}}', {
+ value0: item.number
+ })
+ )
handleRefresh()
}
} else {
@@ -828,6 +876,7 @@ export default function GitLabItemDialog({
setCommentDraftState((current) =>
current.itemId === itemId ? { itemId, value: '' } : current
)
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
handleRefresh()
}
} else {
@@ -867,6 +916,7 @@ export default function GitLabItemDialog({
}
: current
)
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
}
} else if (mountedRef.current) {
toast.error(res.error)
@@ -907,8 +957,14 @@ export default function GitLabItemDialog({
!open && onClose()}>
- {item ? visibleTitle : translate("auto.components.GitLabItemDialog.3a051b8ade", "Work item")}
- {translate("auto.components.GitLabItemDialog.30c97083c2", "GitLab work item detail")}
+
+ {item
+ ? visibleTitle
+ : translate('auto.components.GitLabItemDialog.3a051b8ade', 'Work item')}
+
+
+ {translate('auto.components.GitLabItemDialog.30c97083c2', 'GitLab work item detail')}
+
{item ? (
@@ -923,7 +979,12 @@ export default function GitLabItemDialog({
{item.number}
- {item.author ? {translate("auto.components.GitLabItemDialog.9bfb4a24d7", "by")}{item.author} : null}
+ {item.author ? (
+
+ {translate('auto.components.GitLabItemDialog.9bfb4a24d7', 'by')}
+ {item.author}
+
+ ) : null}
{visibleTitle}
@@ -944,7 +1005,7 @@ export default function GitLabItemDialog({
- {translate("auto.components.GitLabItemDialog.908d8d2a73", "Description")}
+
+ {translate('auto.components.GitLabItemDialog.908d8d2a73', 'Description')}
+
- {translate("auto.components.GitLabItemDialog.c996e2962c", "Conversation")}{details?.comments?.length ? (
+ {translate('auto.components.GitLabItemDialog.c996e2962c', 'Conversation')}
+ {details?.comments?.length ? (
{details.comments.length}
@@ -970,7 +1034,8 @@ export default function GitLabItemDialog({
{isMR ? (
- {translate("auto.components.GitLabItemDialog.be3d291837", "Files")}{details?.files?.length ? (
+ {translate('auto.components.GitLabItemDialog.be3d291837', 'Files')}
+ {details?.files?.length ? (
{details.files.length}
@@ -979,7 +1044,8 @@ export default function GitLabItemDialog({
) : null}
{isMR ? (
- {translate("auto.components.GitLabItemDialog.02cbe2de44", "Pipeline")}{details?.pipelineJobs?.length ? (
+ {translate('auto.components.GitLabItemDialog.02cbe2de44', 'Pipeline')}
+ {details?.pipelineJobs?.length ? (
{details.pipelineJobs.length}
@@ -1000,14 +1066,30 @@ export default function GitLabItemDialog({
-
{translate("auto.components.GitLabItemDialog.4f9313984d", "Reviewers")}
+
+ {translate('auto.components.GitLabItemDialog.4f9313984d', 'Reviewers')}
+
{approvalState ? (
{approvalState.approvalsLeft === 0
- ? translate("auto.components.GitLabItemDialog.22511537d2", "Approved")
- : translate("auto.components.GitLabItemDialog.40c56b95e2", "{{value0}} approval{{value1}} remaining", { value0: approvalState.approvalsLeft ?? 0, value1: approvalState.approvalsLeft === 1 ? '' : 's' })}
- {typeof approvalState.approvalsRequired === "number"
- ? translate("auto.components.GitLabItemDialog.00f3bab87b", " of {{value0}} required", { value0: approvalState.approvalsRequired })
+ ? translate(
+ 'auto.components.GitLabItemDialog.22511537d2',
+ 'Approved'
+ )
+ : translate(
+ 'auto.components.GitLabItemDialog.40c56b95e2',
+ '{{value0}} approval{{value1}} remaining',
+ {
+ value0: approvalState.approvalsLeft ?? 0,
+ value1: approvalState.approvalsLeft === 1 ? '' : 's'
+ }
+ )}
+ {typeof approvalState.approvalsRequired === 'number'
+ ? translate(
+ 'auto.components.GitLabItemDialog.00f3bab87b',
+ ' of {{value0}} required',
+ { value0: approvalState.approvalsRequired }
+ )
: ''}
) : null}
@@ -1022,7 +1104,8 @@ export default function GitLabItemDialog({
{reviewerOptionsLoading ? (
) : null}
- {translate("auto.components.GitLabItemDialog.cb55b0390f", "Manage")}
+ {translate('auto.components.GitLabItemDialog.cb55b0390f', 'Manage')}
+
{currentReviewers.length > 0 ? (
@@ -1043,14 +1126,23 @@ export default function GitLabItemDialog({
)
}
className="rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50"
- aria-label={translate("auto.components.GitLabItemDialog.1b19cdc510", "Remove reviewer {{value0}}", { value0: reviewer.username })}
+ aria-label={translate(
+ 'auto.components.GitLabItemDialog.1b19cdc510',
+ 'Remove reviewer {{value0}}',
+ { value0: reviewer.username }
+ )}
>
))
) : (
- {translate("auto.components.GitLabItemDialog.474b50d988", "No reviewers.")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.474b50d988',
+ 'No reviewers.'
+ )}
+
)}
{reviewerOptions ? (
@@ -1061,7 +1153,12 @@ export default function GitLabItemDialog({
onChange={(event) => setReviewerDraftId(event.target.value)}
className="h-8 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-xs text-foreground"
>
-
{translate("auto.components.GitLabItemDialog.05939e977d", "Add reviewer")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.05939e977d',
+ 'Add reviewer'
+ )}
+
{reviewerOptionRows.map((reviewer) => (
{reviewer.username}
@@ -1084,7 +1181,8 @@ export default function GitLabItemDialog({
{reviewerUpdating ? (
) : null}
- {translate("auto.components.GitLabItemDialog.7a2117129a", "Add")}
+ {translate('auto.components.GitLabItemDialog.7a2117129a', 'Add')}
+
) : null}
{approvalState?.rules.length ? (
@@ -1096,7 +1194,16 @@ export default function GitLabItemDialog({
>
{rule.name}
- {rule.approved ? translate("auto.components.GitLabItemDialog.22511537d2", "Approved") : translate("auto.components.GitLabItemDialog.6de8ce0cc6", "{{value0}} required", { value0: rule.approvalsRequired })}
+ {rule.approved
+ ? translate(
+ 'auto.components.GitLabItemDialog.22511537d2',
+ 'Approved'
+ )
+ : translate(
+ 'auto.components.GitLabItemDialog.6de8ce0cc6',
+ '{{value0}} required',
+ { value0: rule.approvalsRequired }
+ )}
))}
@@ -1112,7 +1219,8 @@ export default function GitLabItemDialog({
- {translate("auto.components.GitLabItemDialog.89f3f19368", "Title")}
+ {translate('auto.components.GitLabItemDialog.89f3f19368', 'Title')}
+
setTitleDraft(event.target.value)}
@@ -1122,7 +1230,8 @@ export default function GitLabItemDialog({
- {translate("auto.components.GitLabItemDialog.908d8d2a73", "Description")}
+ {translate('auto.components.GitLabItemDialog.908d8d2a73', 'Description')}
+
- {translate("auto.components.GitLabItemDialog.dde24ade55", "Labels")}
+ {translate('auto.components.GitLabItemDialog.dde24ade55', 'Labels')}
+
setLabelDraft(event.target.value)}
disabled={detailsSaving}
- placeholder={translate("auto.components.GitLabItemDialog.3c0b6ccca7", "bug, backend")}
+ placeholder={translate(
+ 'auto.components.GitLabItemDialog.3c0b6ccca7',
+ 'bug, backend'
+ )}
className="h-9 w-full rounded-md border border-input bg-transparent px-2.5 text-sm shadow-xs focus:border-ring focus:outline-none focus:ring-[3px] focus:ring-ring/50"
/>
{labelOptionsLoading || labelSuggestionOptions.length > 0 ? (
@@ -1146,7 +1259,11 @@ export default function GitLabItemDialog({
{labelOptionsLoading ? (
- {translate("auto.components.GitLabItemDialog.717b706849", "Loading labels")}
+ {translate(
+ 'auto.components.GitLabItemDialog.717b706849',
+ 'Loading labels'
+ )}
+
) : null}
{labelSuggestionOptions.map((label) => {
const selected = parseGitLabLabelDraft(labelDraft).some(
@@ -1184,7 +1301,8 @@ export default function GitLabItemDialog({
onClick={handleCancelDetailsEdit}
>
- {translate("auto.components.GitLabItemDialog.f72fad3b16", "Cancel")}
+ {translate('auto.components.GitLabItemDialog.f72fad3b16', 'Cancel')}
+
)}
- {translate("auto.components.GitLabItemDialog.93f79a3fc1", "Save")}
+ {translate('auto.components.GitLabItemDialog.93f79a3fc1', 'Save')}
+
) : details?.body ? (
@@ -1211,7 +1330,8 @@ export default function GitLabItemDialog({
className="gap-1.5"
>
- {translate("auto.components.GitLabItemDialog.da4174b00f", "Edit")}
+ {translate('auto.components.GitLabItemDialog.da4174b00f', 'Edit')}
+
) : null}
@@ -1228,10 +1348,16 @@ export default function GitLabItemDialog({
className="gap-1.5"
>
- {translate("auto.components.GitLabItemDialog.da4174b00f", "Edit")}
+ {translate('auto.components.GitLabItemDialog.da4174b00f', 'Edit')}
+
) : null}
- {translate("auto.components.GitLabItemDialog.14423484db", "No description.")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.14423484db',
+ 'No description.'
+ )}
+
)}
@@ -1254,7 +1380,9 @@ export default function GitLabItemDialog({
/>
))
) : (
- {translate("auto.components.GitLabItemDialog.85a8170279", "No comments yet.")}
+
+ {translate('auto.components.GitLabItemDialog.85a8170279', 'No comments yet.')}
+
)}
@@ -1273,7 +1401,9 @@ export default function GitLabItemDialog({
onChange={(event) => setInlineCommentFilePath(event.target.value)}
className="h-8 min-w-0 rounded-md border border-input bg-background px-2 text-xs text-foreground"
>
- {translate("auto.components.GitLabItemDialog.ceb08a733d", "File")}
+
+ {translate('auto.components.GitLabItemDialog.ceb08a733d', 'File')}
+
{details.files.map((file) => (
{file.path}
@@ -1284,7 +1414,10 @@ export default function GitLabItemDialog({
value={inlineCommentLine}
onChange={(event) => setInlineCommentLine(event.target.value)}
inputMode="numeric"
- placeholder={translate("auto.components.GitLabItemDialog.7a7204417f", "Line")}
+ placeholder={translate(
+ 'auto.components.GitLabItemDialog.7a7204417f',
+ 'Line'
+ )}
className="h-8 rounded-md border border-input bg-background px-2 text-xs text-foreground"
/>
@@ -1292,7 +1425,10 @@ export default function GitLabItemDialog({
value={inlineCommentBody}
onChange={(event) => setInlineCommentBody(event.target.value)}
rows={2}
- placeholder={translate("auto.components.GitLabItemDialog.21f8dde18a", "Inline comment")}
+ placeholder={translate(
+ 'auto.components.GitLabItemDialog.21f8dde18a',
+ 'Inline comment'
+ )}
className="mt-2 w-full resize-none rounded-md border border-input bg-background px-2.5 py-1.5 text-sm shadow-xs focus:border-ring focus:outline-none focus:ring-[3px] focus:ring-ring/50"
/>
@@ -1312,7 +1448,8 @@ export default function GitLabItemDialog({
) : (
)}
- {translate("auto.components.GitLabItemDialog.84012fa8fb", "Comment")}
+ {translate('auto.components.GitLabItemDialog.84012fa8fb', 'Comment')}
+
@@ -1328,7 +1465,11 @@ export default function GitLabItemDialog({
{file.oldPath ? (
- {translate("auto.components.GitLabItemDialog.a7eb4f4916", "from")}{file.oldPath}
+ {translate(
+ 'auto.components.GitLabItemDialog.a7eb4f4916',
+ 'from'
+ )}
+ {file.oldPath}
) : null}
@@ -1343,14 +1484,23 @@ export default function GitLabItemDialog({
) : (
- {translate("auto.components.GitLabItemDialog.007423f585", "Diff content unavailable.")}
+ {translate(
+ 'auto.components.GitLabItemDialog.007423f585',
+ 'Diff content unavailable.'
+ )}
+
)}
))}
>
) : (
- {translate("auto.components.GitLabItemDialog.808b1ca1ba", "No changed files.")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.808b1ca1ba',
+ 'No changed files.'
+ )}
+
)}
) : null}
@@ -1376,7 +1526,12 @@ export default function GitLabItemDialog({
))}
) : (
- {translate("auto.components.GitLabItemDialog.f11e3e7675", "No pipeline runs for this MR.")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.f11e3e7675',
+ 'No pipeline runs for this MR.'
+ )}
+
)}
) : null}
@@ -1390,7 +1545,11 @@ export default function GitLabItemDialog({
{command ? (
{command}
@@ -135,10 +145,12 @@ function InstallRgGuidance({
type="button"
onClick={handleCopy}
className="flex items-center gap-1 rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
- aria-label={translate("auto.components.QuickOpen.73b44e7bde", "Copy install command")}
+ aria-label={translate('auto.components.QuickOpen.73b44e7bde', 'Copy install command')}
>
{copied ? : }
- {copied ? translate("auto.components.QuickOpen.cf144856dc", "Copied") : translate("auto.components.QuickOpen.995be8ea22", "Copy")}
+ {copied
+ ? translate('auto.components.QuickOpen.cf144856dc', 'Copied')
+ : translate('auto.components.QuickOpen.995be8ea22', 'Copy')}
) : guidance ? (
@@ -218,13 +230,19 @@ export default function QuickOpen(): React.JSX.Element | null {
onOpenChange={handleOpenChange}
shouldFilter={false}
onCloseAutoFocus={handleCloseAutoFocus}
- title={translate("auto.components.QuickOpen.ec31e058f7", "Go to file")}
- description={translate("auto.components.QuickOpen.9e97f08d0f", "Search for a file to open")}
+ title={translate('auto.components.QuickOpen.ec31e058f7', 'Go to file')}
+ description={translate('auto.components.QuickOpen.9e97f08d0f', 'Search for a file to open')}
>
-
+
{loading ? (
- {translate("auto.components.QuickOpen.722a21e1a8", "Loading files...")}
+
+ {translate('auto.components.QuickOpen.722a21e1a8', 'Loading files...')}
+
) : loadError ? (
(() => {
const guidance = parseInstallRgGuidance(loadError)
@@ -241,7 +259,9 @@ export default function QuickOpen(): React.JSX.Element | null {
)
})()
) : filtered.length === 0 ? (
- {translate("auto.components.QuickOpen.74e2e1b3e4", "No matching files.")}
+
+ {translate('auto.components.QuickOpen.74e2e1b3e4', 'No matching files.')}
+
) : (
filtered.map((item) => {
const lastSlash = item.path.lastIndexOf('/')
@@ -266,17 +286,21 @@ export default function QuickOpen(): React.JSX.Element | null {
- {translate("auto.components.QuickOpen.250e5b2dfb", "Enter")}
- {translate("auto.components.QuickOpen.61b1c871a6", "Open")}
- {translate("auto.components.QuickOpen.95fccbae88", "Esc")}
- {translate("auto.components.QuickOpen.73b2c581f1", "Close")}
+ {translate('auto.components.QuickOpen.250e5b2dfb', 'Enter')}
+ {translate('auto.components.QuickOpen.61b1c871a6', 'Open')}
+ {translate('auto.components.QuickOpen.95fccbae88', 'Esc')}
+ {translate('auto.components.QuickOpen.73b2c581f1', 'Close')}
↑↓
- {translate("auto.components.QuickOpen.1dbd3f59ff", "Move")}
+ {translate('auto.components.QuickOpen.1dbd3f59ff', 'Move')}
{/* Accessibility: announce result count changes */}
- {deferredQuery.trim() ? translate("auto.components.QuickOpen.b227d88520", "{{value0}} files found", { value0: filtered.length }) : ''}
+ {deferredQuery.trim()
+ ? translate('auto.components.QuickOpen.b227d88520', '{{value0}} files found', {
+ value0: filtered.length
+ })
+ : ''}
)
diff --git a/src/renderer/src/components/SelectedTextCopyMenu.tsx b/src/renderer/src/components/SelectedTextCopyMenu.tsx
index 17ed6702588..d08acaf9d44 100644
--- a/src/renderer/src/components/SelectedTextCopyMenu.tsx
+++ b/src/renderer/src/components/SelectedTextCopyMenu.tsx
@@ -115,7 +115,8 @@ export function SelectedTextCopyMenu({
onClick={handleCopy}
>
- {translate("auto.components.SelectedTextCopyMenu.9b40d7b018", "Copy")}
+ {translate('auto.components.SelectedTextCopyMenu.9b40d7b018', 'Copy')}
+
,
document.body
)}
diff --git a/src/renderer/src/components/StarNagCard.tsx b/src/renderer/src/components/StarNagCard.tsx
index 7223a2f1009..f963269824e 100644
--- a/src/renderer/src/components/StarNagCard.tsx
+++ b/src/renderer/src/components/StarNagCard.tsx
@@ -101,25 +101,39 @@ export function StarNagCard(): React.JSX.Element | null {
- {translate("auto.components.StarNagCard.5f6df21046", "Enjoying Orca?")}
+ {translate('auto.components.StarNagCard.5f6df21046', 'Enjoying Orca?')}
+
- {translate("auto.components.StarNagCard.30c36231c1", "If Orca has saved you time, a GitHub star goes a long way. It helps other developers discover the project and keeps the team motivated to ship improvements.")}
+ {translate(
+ 'auto.components.StarNagCard.30c36231c1',
+ 'If Orca has saved you time, a GitHub star goes a long way. It helps other developers discover the project and keeps the team motivated to ship improvements.'
+ )}
+
{error ? (
- {translate("auto.components.StarNagCard.cf82170065", "Could not star the repo. Make sure")}{translate("auto.components.StarNagCard.cd8c34aac1", "gh")} {translate("auto.components.StarNagCard.92b0f9d921", "is authenticated and try again.")}
+ {translate(
+ 'auto.components.StarNagCard.cf82170065',
+ 'Could not star the repo. Make sure'
+ )}
+ {translate('auto.components.StarNagCard.cd8c34aac1', 'gh')}{' '}
+ {translate(
+ 'auto.components.StarNagCard.92b0f9d921',
+ 'is authenticated and try again.'
+ )}
+
) : null}
- {busy ? translate("auto.components.StarNagCard.af3c9bbb37", "Starring…") : translate("auto.components.StarNagCard.2d67b6c849", "Star on GitHub")}
+ {busy
+ ? translate('auto.components.StarNagCard.af3c9bbb37', 'Starring…')
+ : translate('auto.components.StarNagCard.2d67b6c849', 'Star on GitHub')}
diff --git a/src/renderer/src/components/TaskPage.tsx b/src/renderer/src/components/TaskPage.tsx
index f7f68eaf7ab..48a6ad87eb2 100644
--- a/src/renderer/src/components/TaskPage.tsx
+++ b/src/renderer/src/components/TaskPage.tsx
@@ -488,7 +488,9 @@ function LinearStateCell({
result.error ??
translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
})
.catch(() => {
if (reqId !== reqRef.current) {
@@ -904,7 +906,9 @@ function GHStatusCell({
typed.error ??
translate('auto.components.TaskPage.1c893195ac', 'Failed to update state')
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
})
.catch(() => {
if (reqId !== reqRef.current) {
@@ -1349,6 +1353,7 @@ function GHAssigneesCell({
} else {
throw new Error('No GitHub repository context available for this issue.')
}
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
} catch (err) {
patchWorkItem(item.id, { assignees: previousAssignees }, item.repoId)
toast.error(
@@ -1814,6 +1819,7 @@ function PRReviewCell({
setLocalReviewRequests(nextReviewRequests)
patchWorkItem(item.id, { reviewRequests: nextReviewRequests }, item.repoId)
setReviewerInput('')
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
} else {
toast.error(result.error)
}
@@ -2200,6 +2206,7 @@ function PRMergeCell({
prRepo: item.prRepo ?? null
})
if (result.ok) {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
toast.success(translate('auto.components.TaskPage.a161925adc', 'Pull request merged'))
onRefresh()
} else {
@@ -2227,6 +2234,7 @@ function PRMergeCell({
prRepo: item.prRepo ?? null
})
if (result.ok) {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
toast.success(
enabled
? translate('auto.components.TaskPage.fed317634c', 'Auto-merge enabled')
@@ -2850,12 +2858,15 @@ export default function TaskPage(): React.JSX.Element {
const openGitHubDetailPage = useCallback(
(item: GitHubWorkItem, initialTab: ItemDialogTab = 'conversation') => {
- openTaskPage({
- taskSource: 'github',
- preselectedRepoId: item.repoId,
- openGitHubWorkItem: item,
- openGitHubInitialTab: initialTab
- })
+ openTaskPage(
+ {
+ taskSource: 'github',
+ preselectedRepoId: item.repoId,
+ openGitHubWorkItem: item,
+ openGitHubInitialTab: initialTab
+ },
+ { recordTasksInteraction: false }
+ )
},
[openTaskPage]
)
@@ -3078,7 +3089,10 @@ export default function TaskPage(): React.JSX.Element {
const openLinearDetailPage = useCallback(
(issue: LinearIssue) => {
- openTaskPage({ taskSource: 'linear', openLinearIssue: issue })
+ openTaskPage(
+ { taskSource: 'linear', openLinearIssue: issue },
+ { recordTasksInteraction: false }
+ )
},
[openTaskPage]
)
@@ -4192,7 +4206,9 @@ export default function TaskPage(): React.JSX.Element {
result.error ??
translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
} catch {
patchLinearIssue(issue.id, { state: previousState })
patchScopedLinearIssue(issue.id, { state: previousState })
@@ -5229,6 +5245,7 @@ export default function TaskPage(): React.JSX.Element {
// the worktree appeared in the sidebar before the user had a chance
// to review it. The composer already owns the prefill flow. Telemetry
// attribution flows via `openComposerForItem` (sets telemetrySource).
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
openComposerForItem(item)
},
[openComposerForItem]
@@ -5260,7 +5277,9 @@ export default function TaskPage(): React.JSX.Element {
'Unable to open the workspace attached to this issue.'
)
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
},
[handleUseWorkItem]
)
@@ -5285,6 +5304,7 @@ export default function TaskPage(): React.JSX.Element {
const handleUseGitLabItem = useCallback(
(item: GitLabWorkItem): void => {
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
openComposerForGitLabItem(item)
},
[openComposerForGitLabItem]
@@ -5557,13 +5577,14 @@ export default function TaskPage(): React.JSX.Element {
setNewLinearIssueProjectId(null)
setNewLinearIssueLabelIds([])
setLinearRefreshNonce((n) => n + 1)
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
// Why: auto-select the new issue in the inline workspace so the user
// sees exactly what was filed, mirroring the GitHub create-issue flow.
void linearGetIssue(settings, result.id, newLinearIssueTargetTeam.workspaceId)
.then((full) => {
if (full) {
- openLinearDetailPage(full)
+ setSelectedLinearIssue(full, { allowOutsideList: true })
}
})
.catch(() => {})
@@ -5580,8 +5601,8 @@ export default function TaskPage(): React.JSX.Element {
newLinearIssueAssigneeId,
newLinearIssueProjectId,
newLinearIssueLabelIds,
- openLinearDetailPage,
selectedLinearProject,
+ setSelectedLinearIssue,
settings
])
@@ -6314,6 +6335,7 @@ export default function TaskPage(): React.JSX.Element {
// dialog pre-filled rather than yolo-creating the worktree, so the
// user can confirm name / agent / setup before the worktree lands in
// the sidebar. Telemetry attribution flows via openComposerForLinearItem.
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
openComposerForLinearItem(issue, renderedText)
},
[openComposerForLinearItem]
@@ -6503,7 +6525,10 @@ export default function TaskPage(): React.JSX.Element {
disabled={source.disabled}
onClick={() => {
taskSourceManuallyChangedRef.current = true
- openTaskPage({ taskSource: source.id })
+ openTaskPage(
+ { taskSource: source.id },
+ { recordTasksInteraction: false }
+ )
void updateSettings({ defaultTaskSource: source.id }).catch(() => {
toast.error(
translate(
@@ -8205,10 +8230,14 @@ export default function TaskPage(): React.JSX.Element {
role="button"
tabIndex={0}
key={item.id}
- onClick={() => setGitlabDialogItem(item)}
+ onClick={() => {
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
+ setGitlabDialogItem(item)
+ }}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
setGitlabDialogItem(item)
}
}}
diff --git a/src/renderer/src/components/Terminal.tsx b/src/renderer/src/components/Terminal.tsx
index 2cb006b52b0..889e03a7ae5 100644
--- a/src/renderer/src/components/Terminal.tsx
+++ b/src/renderer/src/components/Terminal.tsx
@@ -546,7 +546,12 @@ function Terminal(): React.JSX.Element | null {
releaseCloseDialogGuardAfterDebounce()
return
}
- toast.error(translate("auto.components.Terminal.a2a279b32a", "Save timed out or failed. Fix errors before closing."))
+ toast.error(
+ translate(
+ 'auto.components.Terminal.a2a279b32a',
+ 'Save timed out or failed. Fix errors before closing.'
+ )
+ )
setSaveDialogFileId(fileId)
// Why: a genuine timeout leaves the user back on the same dialog, so
// release the guard immediately — a new click here is a deliberate
@@ -861,7 +866,7 @@ function Terminal(): React.JSX.Element | null {
return
}
createBrowserTab(activeWorktreeId, defaultUrl, {
- title: translate("auto.components.Terminal.37da0d736f", "New Browser Tab"),
+ title: translate('auto.components.Terminal.37da0d736f', 'New Browser Tab'),
focusAddressBar: true
})
}, [
@@ -1292,7 +1297,12 @@ function Terminal(): React.JSX.Element | null {
if (floatingWorkspaceFocused) {
void createFloatingWorkspaceMarkdownTab(useAppStore.getState()).catch((err) => {
toast.error(
- err instanceof Error ? err.message : translate("auto.components.Terminal.f0600556b3", "Failed to create untitled markdown file.")
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.Terminal.f0600556b3',
+ 'Failed to create untitled markdown file.'
+ )
)
})
return
@@ -1806,11 +1816,12 @@ function Terminal(): React.JSX.Element | null {
})}
- {renderedActiveWorktreeId && activeTabType === "editor" && worktreeFiles.length > 0 && (
+ {renderedActiveWorktreeId && activeTabType === 'editor' && worktreeFiles.length > 0 && (
- {translate("auto.components.Terminal.5c1d2a32bb", "Loading editor...")}
+ {translate('auto.components.Terminal.5c1d2a32bb', 'Loading editor...')}
+
}
>
@@ -1830,20 +1841,32 @@ function Terminal(): React.JSX.Element | null {
>
- {translate("auto.components.Terminal.21295c6b8c", "Unsaved Changes")}
+
+ {translate('auto.components.Terminal.21295c6b8c', 'Unsaved Changes')}
+
{saveDialogFile
- ? translate("auto.components.Terminal.61ed600d29", "\"{{value0}}\" has unsaved changes. Do you want to save before closing?", { value0: basename(saveDialogFile.relativePath) })
- : translate("auto.components.Terminal.46e08bc5c8", "This file has unsaved changes.")}
+ ? translate(
+ 'auto.components.Terminal.61ed600d29',
+ '"{{value0}}" has unsaved changes. Do you want to save before closing?',
+ { value0: basename(saveDialogFile.relativePath) }
+ )
+ : translate(
+ 'auto.components.Terminal.46e08bc5c8',
+ 'This file has unsaved changes.'
+ )}
- {translate("auto.components.Terminal.f82e9f02df", "Cancel")}
+ {translate('auto.components.Terminal.f82e9f02df', 'Cancel')}
+
- {translate("auto.components.Terminal.0037b21794", "Don't Save")}
+ {translate('auto.components.Terminal.0037b21794', "Don't Save")}
+
- {translate("auto.components.Terminal.cd51e28d8b", "Save")}
+ {translate('auto.components.Terminal.cd51e28d8b', 'Save')}
+
@@ -1859,9 +1882,15 @@ function Terminal(): React.JSX.Element | null {
>
- {translate("auto.components.Terminal.2fa9c69ff3", "Close Window?")}
+
+ {translate('auto.components.Terminal.2fa9c69ff3', 'Close Window?')}
+
- {translate("auto.components.Terminal.7958465754", "There are local terminals with running processes. Close the window anyway?")}
+ {translate(
+ 'auto.components.Terminal.7958465754',
+ 'There are local terminals with running processes. Close the window anyway?'
+ )}
+
setWindowCloseDialogOpen(false)}
>
- {translate("auto.components.Terminal.f82e9f02df", "Cancel")}
+ {translate('auto.components.Terminal.f82e9f02df', 'Cancel')}
+
- {translate("auto.components.Terminal.73768427cf", "Close")}
+ {translate('auto.components.Terminal.73768427cf', 'Close')}
+
diff --git a/src/renderer/src/components/TerminalSearch.tsx b/src/renderer/src/components/TerminalSearch.tsx
index ff8f860ecdb..3832c431237 100644
--- a/src/renderer/src/components/TerminalSearch.tsx
+++ b/src/renderer/src/components/TerminalSearch.tsx
@@ -110,7 +110,7 @@ export default function TerminalSearch({
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
- placeholder={translate("auto.components.TerminalSearch.e07012f26e", "Search...")}
+ placeholder={translate('auto.components.TerminalSearch.e07012f26e', 'Search...')}
className="min-w-0 flex-1 border-none bg-transparent text-sm text-white outline-none placeholder:text-zinc-500"
/>
@@ -122,7 +122,7 @@ export default function TerminalSearch({
className={`flex size-6 shrink-0 items-center justify-center rounded ${
caseSensitive ? 'bg-zinc-700/50 text-blue-400' : 'text-zinc-400 hover:text-zinc-200'
}`}
- title={translate("auto.components.TerminalSearch.90c61387d9", "Case sensitive")}
+ title={translate('auto.components.TerminalSearch.90c61387d9', 'Case sensitive')}
>
@@ -135,7 +135,7 @@ export default function TerminalSearch({
className={`flex size-6 shrink-0 items-center justify-center rounded ${
regex ? 'bg-zinc-700/50 text-blue-400' : 'text-zinc-400 hover:text-zinc-200'
}`}
- title={translate("auto.components.TerminalSearch.42e466b9f1", "Regex")}
+ title={translate('auto.components.TerminalSearch.42e466b9f1', 'Regex')}
>
@@ -148,7 +148,7 @@ export default function TerminalSearch({
size="icon-xs"
onClick={findPrevious}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.TerminalSearch.0f3066256e", "Previous match")}
+ title={translate('auto.components.TerminalSearch.0f3066256e', 'Previous match')}
>
@@ -159,7 +159,7 @@ export default function TerminalSearch({
size="icon-xs"
onClick={findNext}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.TerminalSearch.7cb40c04eb", "Next match")}
+ title={translate('auto.components.TerminalSearch.7cb40c04eb', 'Next match')}
>
@@ -172,7 +172,7 @@ export default function TerminalSearch({
size="icon-xs"
onClick={onClose}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.TerminalSearch.db234b7519", "Close")}
+ title={translate('auto.components.TerminalSearch.db234b7519', 'Close')}
>
diff --git a/src/renderer/src/components/WorktreeJumpPalette.tsx b/src/renderer/src/components/WorktreeJumpPalette.tsx
index 9ea18fdbb50..80861bff424 100644
--- a/src/renderer/src/components/WorktreeJumpPalette.tsx
+++ b/src/renderer/src/components/WorktreeJumpPalette.tsx
@@ -255,6 +255,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
const openModal = useAppStore((s) => s.openModal)
const openSettingsPage = useAppStore((s) => s.openSettingsPage)
const openSettingsTarget = useAppStore((s) => s.openSettingsTarget)
+ const recordFeatureInteraction = useAppStore((s) => s.recordFeatureInteraction)
const worktreesByRepo = useAppStore((s) => s.worktreesByRepo)
const allWorktrees = useAllWorktrees()
const repos = useAppStore((s) => s.repos)
@@ -799,6 +800,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
useEffect(() => {
if (visible && !wasVisibleRef.current) {
+ recordFeatureInteraction('cmd-j')
createLookupGuard.invalidate()
activeGroupSnapshotRef.current = captureCmdJActiveGroupSnapshot(
useAppStore.getState(),
@@ -845,6 +847,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
activeWorktreeId,
browserTabsByWorktree,
createLookupGuard,
+ recordFeatureInteraction,
visible
])
@@ -953,12 +956,13 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
return
}
activateAndRevealWorktree(worktreeId)
+ recordFeatureInteraction('cmd-j-workspace-open')
skipRestoreFocusRef.current = true
closeModal()
setSelectedItemId('')
focusFallbackSurface()
},
- [closeModal, focusFallbackSurface]
+ [closeModal, focusFallbackSurface, recordFeatureInteraction]
)
const handleSelectBrowserPage = useCallback(
@@ -989,6 +993,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
const state = useAppStore.getState()
state.setActiveBrowserTab(workspace.id)
state.setActiveBrowserPage(workspace.id, pageId)
+ recordFeatureInteraction('cmd-j-browser-page-open')
skipRestoreFocusRef.current = true
closeModal()
setSelectedItemId('')
@@ -997,7 +1002,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
target: isBlankBrowserUrl(page.url) ? 'address-bar' : 'webview'
})
},
- [closeModal, requestBrowserFocus]
+ [closeModal, recordFeatureInteraction, requestBrowserFocus]
)
const handleSelectSimulatorTab = useCallback(
@@ -1046,8 +1051,9 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
setSelectedItemId('')
openSettingsTarget(target)
openSettingsPage()
+ recordFeatureInteraction('cmd-j-settings-open')
},
- [closeModal, openSettingsPage, openSettingsTarget]
+ [closeModal, openSettingsPage, openSettingsTarget, recordFeatureInteraction]
)
const handleSelectQuickAction = useCallback(
@@ -1059,10 +1065,16 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
void action.run(ctx).then((result) => {
if (result.status === 'unavailable') {
toast.error(getUnavailableQuickActionMessage(action.title, result.reason))
+ return
}
+ if (action.id === 'create-workspace') {
+ recordFeatureInteraction('cmd-j-create-workspace')
+ return
+ }
+ recordFeatureInteraction('cmd-j-quick-action')
})
},
- [buildQuickActionContext, closeModal]
+ [buildQuickActionContext, closeModal, recordFeatureInteraction]
)
const handleSelectItem = useCallback(
@@ -1099,6 +1111,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
typeof data.initialRepoId === 'string' ? data.initialRepoId : undefined
)
closeModal()
+ recordFeatureInteraction('cmd-j-create-workspace')
// Why: defer opening so Radix fully unmounts the palette's dialog before
// the composer modal mounts, avoiding focus churn between the two.
queueMicrotask(() =>
@@ -1122,6 +1135,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
if (activeMatch) {
closeModal()
activateAndRevealWorktree(activeMatch.id)
+ recordFeatureInteraction('cmd-j-workspace-open')
return
}
@@ -1141,6 +1155,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
// composer once the lookup returns.
const lookupToken = createLookupGuard.start()
preserveCreateLookupOnCloseRef.current = true
+ recordFeatureInteraction('cmd-j-create-workspace')
closeModal()
void window.api.gh
.workItemByOwnerRepo({
@@ -1199,6 +1214,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
if (activeMatch) {
closeModal()
activateAndRevealWorktree(activeMatch.id)
+ recordFeatureInteraction('cmd-j-workspace-open')
return
}
@@ -1213,6 +1229,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
prefetchCreateWorkspaceBaseForComposer(repoForLookup.id)
const lookupToken = createLookupGuard.start()
preserveCreateLookupOnCloseRef.current = true
+ recordFeatureInteraction('cmd-j-create-workspace')
closeModal()
void window.api.gh
.workItem({ repoPath: repoForLookup.path, repoId: repoForLookup.id, number: ghNumber })
@@ -1263,6 +1280,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
createWorktreeName,
openModal,
prefetchCreateWorkspaceBaseForComposer,
+ recordFeatureInteraction,
repoMap
])
diff --git a/src/renderer/src/components/activity/ActivityPrototypePage.tsx b/src/renderer/src/components/activity/ActivityPrototypePage.tsx
index 1720123c5ba..5d9f2e6ea4b 100644
--- a/src/renderer/src/components/activity/ActivityPrototypePage.tsx
+++ b/src/renderer/src/components/activity/ActivityPrototypePage.tsx
@@ -911,7 +911,13 @@ export function getActivityThreadGroup(
if (groupBy === 'project') {
return thread.repo
? { key: `project:${thread.repo.id}`, label: thread.repo.displayName }
- : { key: 'project:unknown', label: translate("auto.components.activity.ActivityPrototypePage.5651b216c6", "Unknown project") }
+ : {
+ key: 'project:unknown',
+ label: translate(
+ 'auto.components.activity.ActivityPrototypePage.5651b216c6',
+ 'Unknown project'
+ )
+ }
}
if (groupBy === 'worktree') {
return { key: `worktree:${thread.worktree.id}`, label: thread.worktree.displayName }
@@ -1162,7 +1168,10 @@ function ThreadRow({
{thread.unread ? (
) : (
@@ -1179,12 +1188,20 @@ function ThreadRow({
'hover:bg-accent/80 active:scale-95',
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'
)}
- aria-label={translate("auto.components.activity.ActivityPrototypePage.59b131fbd9", "Mark thread unread")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.59b131fbd9',
+ 'Mark thread unread'
+ )}
>
- {translate("auto.components.activity.ActivityPrototypePage.59b131fbd9", "Mark thread unread")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.59b131fbd9',
+ 'Mark thread unread'
+ )}
+
)}
@@ -1216,7 +1233,10 @@ function ThreadRow({
type="button"
variant="outline"
size="icon-xs"
- aria-label={translate("auto.components.activity.ActivityPrototypePage.4616ea39fd", "Jump to workspace")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.4616ea39fd',
+ 'Jump to workspace'
+ )}
onClick={(event) => {
event.stopPropagation()
onJump()
@@ -1226,7 +1246,12 @@ function ThreadRow({
- {translate("auto.components.activity.ActivityPrototypePage.4616ea39fd", "Jump to workspace")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.4616ea39fd',
+ 'Jump to workspace'
+ )}
+
) : null}
@@ -1615,7 +1640,10 @@ export default function ActivityPrototypePage(): React.JSX.Element {
setQuery(event.target.value)}
- placeholder={translate("auto.components.activity.ActivityPrototypePage.795cbf26e2", "Filter...")}
+ placeholder={translate(
+ 'auto.components.activity.ActivityPrototypePage.795cbf26e2',
+ 'Filter...'
+ )}
className="h-8 w-full pl-7 text-xs"
/>
@@ -1626,15 +1654,38 @@ export default function ActivityPrototypePage(): React.JSX.Element {
- {translate("auto.components.activity.ActivityPrototypePage.4a3986b200", "Status")}
- {translate("auto.components.activity.ActivityPrototypePage.8c3b621ddf", "Project")}
- {translate("auto.components.activity.ActivityPrototypePage.b29191b3e0", "Worktree")}
- {translate("auto.components.activity.ActivityPrototypePage.f6396e1f85", "Agent")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.4a3986b200',
+ 'Status'
+ )}
+
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.8c3b621ddf',
+ 'Project'
+ )}
+
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.b29191b3e0',
+ 'Worktree'
+ )}
+
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.f6396e1f85',
+ 'Agent'
+ )}
+
@@ -1650,12 +1701,20 @@ export default function ActivityPrototypePage(): React.JSX.Element {
? '!border-primary !bg-primary !text-primary-foreground shadow-xs ring-2 ring-primary/35 hover:!bg-primary/90 hover:!text-primary-foreground'
: 'text-muted-foreground hover:text-foreground'
)}
- aria-label={translate("auto.components.activity.ActivityPrototypePage.d1a88df9a8", "Show unread threads only")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.d1a88df9a8',
+ 'Show unread threads only'
+ )}
>
- {translate("auto.components.activity.ActivityPrototypePage.d1a88df9a8", "Show unread threads only")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.d1a88df9a8',
+ 'Show unread threads only'
+ )}
+
{/* Why (overflow menu): "Mark all read" is a low-frequency,
destructive-feeling action — parking it behind a `…` keeps
@@ -1671,13 +1730,21 @@ export default function ActivityPrototypePage(): React.JSX.Element {
variant="outline"
size="sm"
className="size-8 shrink-0 border-input bg-transparent p-0 text-muted-foreground shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-transparent dark:hover:bg-accent dark:hover:text-accent-foreground"
- aria-label={translate("auto.components.activity.ActivityPrototypePage.db8a1878b5", "Thread list options")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.db8a1878b5',
+ 'Thread list options'
+ )}
>
- {translate("auto.components.activity.ActivityPrototypePage.a472a14700", "More options")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.a472a14700',
+ 'More options'
+ )}
+
setCompactMode(checked === true)}
onSelect={(event) => event.preventDefault()}
>
- {translate("auto.components.activity.ActivityPrototypePage.f70e4bec47", "Compact mode")}
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.f70e4bec47',
+ 'Compact mode'
+ )}
+
markAllThreadsRead()}
disabled={!hasUnreadThreads}
>
- {translate("auto.components.activity.ActivityPrototypePage.023ff75afe", "Mark all read")}
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.023ff75afe',
+ 'Mark all read'
+ )}
+
{visibleThreadGroups.map((group) => (
-
+
{group.threads.map((thread) => (
- {translate("auto.components.activity.ActivityPrototypePage.7cd632006b", "No agent activity matches these filters.")}
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.7cd632006b',
+ 'No agent activity matches these filters.'
+ )}
+
) : null}
{storeData.worktreeMap.has(selectedThread.worktree.id)
- ? translate("auto.components.activity.ActivityPrototypePage.afdc2139a8", "Agent terminal closed. Open a new terminal in this workspace to continue.")
- : translate("auto.components.activity.ActivityPrototypePage.22b22034bc", "Standalone terminal unavailable in Activity.")}
+ ? translate(
+ 'auto.components.activity.ActivityPrototypePage.afdc2139a8',
+ 'Agent terminal closed. Open a new terminal in this workspace to continue.'
+ )
+ : translate(
+ 'auto.components.activity.ActivityPrototypePage.22b22034bc',
+ 'Standalone terminal unavailable in Activity.'
+ )}
)
}
@@ -1815,12 +1913,22 @@ export default function ActivityPrototypePage(): React.JSX.Element {
{visiblePortalUnavailable ? (
- {translate("auto.components.activity.ActivityPrototypePage.8de7c5beaa", "Terminal unavailable")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.8de7c5beaa',
+ 'Terminal unavailable'
+ )}
+
) : showTerminalLoadingLabel ? (
- {translate("auto.components.activity.ActivityPrototypePage.1b633f5c1e", "Connecting terminal...")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.1b633f5c1e',
+ 'Connecting terminal...'
+ )}
+
) : null}
@@ -1834,11 +1942,19 @@ export default function ActivityPrototypePage(): React.JSX.Element {
{visibleThreads.length === 0 ? (
<>
- {translate("auto.components.activity.ActivityPrototypePage.e3db9892f6", "No activity yet.")}>
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.e3db9892f6',
+ 'No activity yet.'
+ )}
+ >
) : (
<>
- {translate("auto.components.activity.ActivityPrototypePage.cf780197a1", "Select an agent to view its activity")}>
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.cf780197a1',
+ 'Select an agent to view its activity'
+ )}
+ >
)}
)}
diff --git a/src/renderer/src/components/activity/ActivityTitlebarControls.tsx b/src/renderer/src/components/activity/ActivityTitlebarControls.tsx
index 9516662e704..93ca4c65c1c 100644
--- a/src/renderer/src/components/activity/ActivityTitlebarControls.tsx
+++ b/src/renderer/src/components/activity/ActivityTitlebarControls.tsx
@@ -27,18 +27,29 @@ export function ActivityTitlebarControls(): React.JSX.Element {
variant="ghost"
size="icon-xs"
onClick={closeActivityPage}
- aria-label={translate("auto.components.activity.ActivityTitlebarControls.dc708f3eff", "Close agents")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityTitlebarControls.dc708f3eff',
+ 'Close agents'
+ )}
>
- {translate("auto.components.activity.ActivityTitlebarControls.dc708f3eff", "Close agents")}
+ {translate(
+ 'auto.components.activity.ActivityTitlebarControls.dc708f3eff',
+ 'Close agents'
+ )}
+
- {translate("auto.components.activity.ActivityTitlebarControls.d6a8de3934", "agents")}
+
+ {translate('auto.components.activity.ActivityTitlebarControls.d6a8de3934', 'agents')}
+
- {unreadCount} {translate("auto.components.activity.ActivityTitlebarControls.f915168c8e", "unread")}
+ {unreadCount}{' '}
+ {translate('auto.components.activity.ActivityTitlebarControls.f915168c8e', 'unread')}
+
)
diff --git a/src/renderer/src/components/agent/AgentCombobox.tsx b/src/renderer/src/components/agent/AgentCombobox.tsx
index ef8f492db4c..fb15e5722a5 100644
--- a/src/renderer/src/components/agent/AgentCombobox.tsx
+++ b/src/renderer/src/components/agent/AgentCombobox.tsx
@@ -102,7 +102,9 @@ function renderItem({
- {isDefault ? translate("auto.components.agent.AgentCombobox.1b0d6965fa", "Current default") : translate("auto.components.agent.AgentCombobox.9c6b59fe58", "Set as default")}
+ {isDefault
+ ? translate('auto.components.agent.AgentCombobox.1b0d6965fa', 'Current default')
+ : translate('auto.components.agent.AgentCombobox.9c6b59fe58', 'Set as default')}
@@ -286,7 +288,9 @@ export default function AgentCombobox({
) : (
- {translate("auto.components.agent.AgentCombobox.986f946354", "Blank Terminal")}
+
+ {translate('auto.components.agent.AgentCombobox.986f946354', 'Blank Terminal')}
+
)}
@@ -307,12 +311,20 @@ export default function AgentCombobox({
- {translate("auto.components.agent.AgentCombobox.579c768bde", "No agents match your search.")}
+
+ {translate(
+ 'auto.components.agent.AgentCombobox.579c768bde',
+ 'No agents match your search.'
+ )}
+
{blankMatchesQuery
? renderItem({
key: BLANK_VALUE,
@@ -322,7 +334,10 @@ export default function AgentCombobox({
onSelect: () => handleSelect(null),
onSetDefault: onSetDefault ? () => onSetDefault('blank') : undefined,
icon: ,
- label: translate("auto.components.agent.AgentCombobox.986f946354", "Blank Terminal")
+ label: translate(
+ 'auto.components.agent.AgentCombobox.986f946354',
+ 'Blank Terminal'
+ )
})
: null}
{filteredAgents.map((agent) =>
@@ -348,7 +363,8 @@ export default function AgentCombobox({
onMouseEnter={() => setCommandValue('')}
className="h-9 w-full justify-start rounded-none px-3 text-xs font-normal text-muted-foreground"
>
- {translate("auto.components.agent.AgentCombobox.19522e25ee", "Manage agents")}
+ {translate('auto.components.agent.AgentCombobox.19522e25ee', 'Manage agents')}
+
) : null}
diff --git a/src/renderer/src/components/agent/AgentSettingsDialog.tsx b/src/renderer/src/components/agent/AgentSettingsDialog.tsx
index 86e05aea296..dd33b771a92 100644
--- a/src/renderer/src/components/agent/AgentSettingsDialog.tsx
+++ b/src/renderer/src/components/agent/AgentSettingsDialog.tsx
@@ -34,9 +34,15 @@ export default function AgentSettingsDialog({
agents are detected. */}
- {translate("auto.components.agent.AgentSettingsDialog.fc0268e4ed", "Agents")}
+
+ {translate('auto.components.agent.AgentSettingsDialog.fc0268e4ed', 'Agents')}
+
- {translate("auto.components.agent.AgentSettingsDialog.50cdb57c03", "Manage AI agents, set a default, and customize commands.")}
+ {translate(
+ 'auto.components.agent.AgentSettingsDialog.50cdb57c03',
+ 'Manage AI agents, set a default, and customize commands.'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx b/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx
index 39c79c4a843..311d6bf4d98 100644
--- a/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx
+++ b/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx
@@ -17,10 +17,22 @@ export function getCronScheduleStatusLabel(
): { kind: 'empty' | 'invalid' | 'valid'; label: string } {
const trimmed = schedule.trim()
if (!trimmed) {
- return { kind: 'empty', label: translate("auto.components.automations.AutomationCustomCronPanel.968e66d686", "Enter a five-field cron.") }
+ return {
+ kind: 'empty',
+ label: translate(
+ 'auto.components.automations.AutomationCustomCronPanel.968e66d686',
+ 'Enter a five-field cron.'
+ )
+ }
}
if (!validateSchedule(trimmed)) {
- return { kind: 'invalid', label: translate("auto.components.automations.AutomationCustomCronPanel.e81a02d61b", "Enter a valid five-field cron before saving.") }
+ return {
+ kind: 'invalid',
+ label: translate(
+ 'auto.components.automations.AutomationCustomCronPanel.e81a02d61b',
+ 'Enter a valid five-field cron before saving.'
+ )
+ }
}
const formatted = formatAutomationSchedule(trimmed)
return { kind: 'valid', label: formatted === 'Custom schedule' ? 'Valid custom cron' : formatted }
@@ -50,7 +62,12 @@ export function AutomationCustomCronPanel({
return (
-
+
- {customScheduleStatus.kind === "invalid" ? (
+ {customScheduleStatus.kind === 'invalid' ? (
) : (
diff --git a/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx b/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx
index 6069d78abeb..b1712f5250c 100644
--- a/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx
+++ b/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx
@@ -69,17 +69,35 @@ export function AutomationEditorDialogHeader({
{isEditing
- ? translate("auto.components.automations.AutomationEditorDialogHeader.17086b48ee", "Edit automation")
+ ? translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.17086b48ee',
+ 'Edit automation'
+ )
: isEditingExternal
- ? translate("auto.components.automations.AutomationEditorDialogHeader.03142e7721", "Edit Hermes automation")
+ ? translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.03142e7721',
+ 'Edit Hermes automation'
+ )
: isHermesCreate
- ? translate("auto.components.automations.AutomationEditorDialogHeader.0a75e5e2fa", "Create Hermes automation")
- : translate("auto.components.automations.AutomationEditorDialogHeader.4133d33862", "Create automation")}
+ ? translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.0a75e5e2fa',
+ 'Create Hermes automation'
+ )
+ : translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.4133d33862',
+ 'Create automation'
+ )}
onDraftNameChange(event.target.value)}
/>
@@ -97,9 +115,17 @@ export function AutomationEditorDialogHeader({
className="grid grid-cols-2"
>
- {translate("auto.components.automations.AutomationEditorDialogHeader.6f309eef8d", "Orca")}
+ {translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.6f309eef8d',
+ 'Orca'
+ )}
+
- {translate("auto.components.automations.AutomationEditorDialogHeader.7e35393632", "Hermes")}
+ {translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.7e35393632',
+ 'Hermes'
+ )}
+
@@ -110,7 +136,11 @@ export function AutomationEditorDialogHeader({
className={pickerTriggerClassName}
>
- {translate("auto.components.automations.AutomationEditorDialogHeader.31f9253920", "Use template")}
+ {translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.31f9253920',
+ 'Use template'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx b/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx
index 86d15307993..01e68d038df 100644
--- a/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx
+++ b/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx
@@ -28,18 +28,29 @@ export function AutomationMissedRunGraceField({
- {translate("auto.components.automations.AutomationMissedRunGraceField.fc089e5fde", "Grace")}
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.fc089e5fde',
+ 'Grace'
+ )}
+
- {translate("auto.components.automations.AutomationMissedRunGraceField.3d70c185c8", "If Orca or the execution host was unavailable at the scheduled time, Orca runs one missed occurrence when it becomes available within this window. Older missed runs are skipped.")}
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.3d70c185c8',
+ 'If Orca or the execution host was unavailable at the scheduled time, Orca runs one missed occurrence when it becomes available within this window. Older missed runs are skipped.'
+ )}
+
}
@@ -55,13 +66,48 @@ export function AutomationMissedRunGraceField({
- {translate("auto.components.automations.AutomationMissedRunGraceField.529dc6c0b7", "No grace")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.e5ad263ae5", "30 minutes")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.521f77cd58", "1 hour")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.2dc9ee84d0", "3 hours")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.ba50e2a230", "12 hours")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.adbab51feb", "24 hours")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.0f4459e91d", "48 hours")}
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.529dc6c0b7',
+ 'No grace'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.e5ad263ae5',
+ '30 minutes'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.521f77cd58',
+ '1 hour'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.2dc9ee84d0',
+ '3 hours'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.ba50e2a230',
+ '12 hours'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.adbab51feb',
+ '24 hours'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.0f4459e91d',
+ '48 hours'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationPrecheckFields.tsx b/src/renderer/src/components/automations/AutomationPrecheckFields.tsx
index 8621ae0d435..07f3643b450 100644
--- a/src/renderer/src/components/automations/AutomationPrecheckFields.tsx
+++ b/src/renderer/src/components/automations/AutomationPrecheckFields.tsx
@@ -24,11 +24,19 @@ export function AutomationPrecheckFields({
}: AutomationPrecheckFieldsProps): React.JSX.Element {
return (
<>
-
+
onDraftChange((current) => ({
...current,
@@ -38,7 +46,12 @@ export function AutomationPrecheckFields({
className="min-h-[68px] w-full resize-none rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-xs outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30"
/>
-
+
- {translate("auto.components.automations.AutomationPrecheckFields.51e28cdad9", "30 sec")}
- {translate("auto.components.automations.AutomationPrecheckFields.c820119736", "1 min")}
- {translate("auto.components.automations.AutomationPrecheckFields.d84d3765fd", "2 min")}
- {translate("auto.components.automations.AutomationPrecheckFields.bf49585b3c", "5 min")}
- {translate("auto.components.automations.AutomationPrecheckFields.d2a2ac89ac", "10 min")}
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.51e28cdad9',
+ '30 sec'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.c820119736',
+ '1 min'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.d84d3765fd',
+ '2 min'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.bf49585b3c',
+ '5 min'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.d2a2ac89ac',
+ '10 min'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationRunHistory.tsx b/src/renderer/src/components/automations/AutomationRunHistory.tsx
index 90c3113f19c..be8a76dcd5e 100644
--- a/src/renderer/src/components/automations/AutomationRunHistory.tsx
+++ b/src/renderer/src/components/automations/AutomationRunHistory.tsx
@@ -48,16 +48,28 @@ export function AutomationRunHistory({
return (
-
{translate("auto.components.automations.AutomationRunHistory.53fc5f07ab", "Run history")}
+
+ {translate('auto.components.automations.AutomationRunHistory.53fc5f07ab', 'Run history')}
+
{runCountLabel}
-
{translate("auto.components.automations.AutomationRunHistory.8faaa00726", "Run")}
-
{translate("auto.components.automations.AutomationRunHistory.149c0b49c7", "Workspace")}
-
{translate("auto.components.automations.AutomationRunHistory.86a248187e", "Spend")}
-
{translate("auto.components.automations.AutomationRunHistory.13988187b3", "Tokens")}
-
{translate("auto.components.automations.AutomationRunHistory.9974a2b429", "Status")}
+
+ {translate('auto.components.automations.AutomationRunHistory.8faaa00726', 'Run')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.149c0b49c7', 'Workspace')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.86a248187e', 'Spend')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.13988187b3', 'Tokens')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.9974a2b429', 'Status')}
+
{runs.map((run) => {
@@ -115,9 +127,12 @@ export function AutomationRunHistory({
}
title={usageLabel}
>
- {run.usage?.status === "known"
+ {run.usage?.status === 'known'
? formatAutomationTokens(run.usage.totalTokens)
- : translate("auto.components.automations.AutomationRunHistory.a00e38d1a3", "n/a")}
+ : translate(
+ 'auto.components.automations.AutomationRunHistory.a00e38d1a3',
+ 'n/a'
+ )}
@@ -128,7 +143,12 @@ export function AutomationRunHistory({
)
})}
{runs.length === 0 ? (
- {translate("auto.components.automations.AutomationRunHistory.402651bfb6", "No runs yet.")}
+
+ {translate(
+ 'auto.components.automations.AutomationRunHistory.402651bfb6',
+ 'No runs yet.'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/automations/AutomationRunPageFrame.tsx b/src/renderer/src/components/automations/AutomationRunPageFrame.tsx
index dd7995f94bc..30c323d6dc8 100644
--- a/src/renderer/src/components/automations/AutomationRunPageFrame.tsx
+++ b/src/renderer/src/components/automations/AutomationRunPageFrame.tsx
@@ -34,7 +34,10 @@ export function AutomationRunPageFrame({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.automations.AutomationRunPageFrame.33741dd973", "Back to runs")}
+ aria-label={translate(
+ 'auto.components.automations.AutomationRunPageFrame.33741dd973',
+ 'Back to runs'
+ )}
onClick={onBack}
>
@@ -46,7 +49,10 @@ export function AutomationRunPageFrame({
{breadcrumbs.length > 0 ? (
{breadcrumbs.map((breadcrumb, index) => (
diff --git a/src/renderer/src/components/automations/AutomationSchedulePicker.tsx b/src/renderer/src/components/automations/AutomationSchedulePicker.tsx
index 1786770bfa5..eb203f9c36c 100644
--- a/src/renderer/src/components/automations/AutomationSchedulePicker.tsx
+++ b/src/renderer/src/components/automations/AutomationSchedulePicker.tsx
@@ -172,7 +172,12 @@ export function AutomationSchedulePicker({
className="popover-scroll-content scrollbar-sleek max-h-[var(--radix-popover-content-available-height)] w-[min(var(--radix-popover-trigger-width),calc(100vw-2rem))] min-w-[min(22rem,calc(100vw-2rem))] max-w-[calc(100vw-2rem)] overflow-y-auto p-3"
>
-
+
@@ -194,7 +199,7 @@ export function AutomationSchedulePicker({
- {draft.preset === "custom" ? (
+ {draft.preset === 'custom' ? (
) : (
<>
- {draft.preset === "weekly" ? (
-
+ {draft.preset === 'weekly' ? (
+
@@ -224,8 +234,13 @@ export function AutomationSchedulePicker({
) : null}
- {draft.preset === "hourly" ? (
-
+ {draft.preset === 'hourly' ? (
+
@@ -249,7 +264,12 @@ export function AutomationSchedulePicker({
) : (
-
+
@@ -286,7 +309,10 @@ export function AutomationSchedulePicker({
}
>
@@ -310,7 +336,10 @@ export function AutomationSchedulePicker({
}
>
diff --git a/src/renderer/src/components/automations/AutomationSessionField.tsx b/src/renderer/src/components/automations/AutomationSessionField.tsx
index 08f384ca8ce..b6aef00ebd8 100644
--- a/src/renderer/src/components/automations/AutomationSessionField.tsx
+++ b/src/renderer/src/components/automations/AutomationSessionField.tsx
@@ -21,18 +21,26 @@ export function AutomationSessionField({
- {translate("auto.components.automations.AutomationSessionField.5ad314118e", "Session")}
+ {translate('auto.components.automations.AutomationSessionField.5ad314118e', 'Session')}
+
- {translate("auto.components.automations.AutomationSessionField.b675112193", "Reuse sends future runs to the previous live automation session. If that session is gone, Orca starts a fresh one.")}
+ {translate(
+ 'auto.components.automations.AutomationSessionField.b675112193',
+ 'Reuse sends future runs to the previous live automation session. If that session is gone, Orca starts a fresh one.'
+ )}
+
}
@@ -55,9 +63,11 @@ export function AutomationSessionField({
className="grid w-full grid-cols-2"
>
- {translate("auto.components.automations.AutomationSessionField.c90888ee94", "Fresh")}
+ {translate('auto.components.automations.AutomationSessionField.c90888ee94', 'Fresh')}
+
- {translate("auto.components.automations.AutomationSessionField.f3c76dce51", "Reuse")}
+ {translate('auto.components.automations.AutomationSessionField.f3c76dce51', 'Reuse')}
+
)
diff --git a/src/renderer/src/components/automations/CreateFromPicker.tsx b/src/renderer/src/components/automations/CreateFromPicker.tsx
index 8bb63717e2f..8b89da1852b 100644
--- a/src/renderer/src/components/automations/CreateFromPicker.tsx
+++ b/src/renderer/src/components/automations/CreateFromPicker.tsx
@@ -176,7 +176,12 @@ export function CreateFromPicker({
className={cn('h-9 w-full justify-between px-3 text-sm font-normal', triggerClassName)}
>
- {translate("auto.components.automations.CreateFromPicker.dd3841b442", "Branch from")}
+
+ {translate(
+ 'auto.components.automations.CreateFromPicker.dd3841b442',
+ 'Branch from'
+ )}
+
{selectedLabel}
@@ -195,11 +200,22 @@ export function CreateFromPicker({
ref={setInputNode}
value={query}
onValueChange={setQuery}
- placeholder={translate("auto.components.automations.CreateFromPicker.f061f49e3f", "Search repo branches...")}
+ placeholder={translate(
+ 'auto.components.automations.CreateFromPicker.f061f49e3f',
+ 'Search repo branches...'
+ )}
/>
- {isSearching ? translate("auto.components.automations.CreateFromPicker.9ce96621f4", "Searching branches...") : translate("auto.components.automations.CreateFromPicker.79512f22a7", "No branches found.")}
+ {isSearching
+ ? translate(
+ 'auto.components.automations.CreateFromPicker.9ce96621f4',
+ 'Searching branches...'
+ )
+ : translate(
+ 'auto.components.automations.CreateFromPicker.79512f22a7',
+ 'No branches found.'
+ )}
- {effectiveDefault ? translate("auto.components.automations.CreateFromPicker.e53d306056", "{{value0}} (default)", { value0: effectiveDefault }) : translate("auto.components.automations.CreateFromPicker.ef6d762538", "Project default")}
+ {effectiveDefault
+ ? translate(
+ 'auto.components.automations.CreateFromPicker.e53d306056',
+ '{{value0}} (default)',
+ { value0: effectiveDefault }
+ )
+ : translate(
+ 'auto.components.automations.CreateFromPicker.ef6d762538',
+ 'Project default'
+ )}
{branchOptions
diff --git a/src/renderer/src/components/automations/ExternalAutomationManagers.tsx b/src/renderer/src/components/automations/ExternalAutomationManagers.tsx
index 378d9c9cfeb..e116564cbdd 100644
--- a/src/renderer/src/components/automations/ExternalAutomationManagers.tsx
+++ b/src/renderer/src/components/automations/ExternalAutomationManagers.tsx
@@ -111,10 +111,24 @@ export function ExternalAutomationManagers({
-
{translate("auto.components.automations.ExternalAutomationManagers.c6695e6fbd", "External automations")}
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.c6695e6fbd',
+ 'External automations'
+ )}
+
- {automationCount} {automationCount === 1 ? translate("auto.components.automations.ExternalAutomationManagers.701515f010", "automation") : translate("auto.components.automations.ExternalAutomationManagers.e2532150ed", "automations")}
+ {automationCount}{' '}
+ {automationCount === 1
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.701515f010',
+ 'automation'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.e2532150ed',
+ 'automations'
+ )}
@@ -127,9 +141,18 @@ export function ExternalAutomationManagers({
{getProviderLabel(manager)} / {getTargetKindLabel(manager)} ·{' '}
{manager.status === 'available'
? manager.canManage
- ? translate("auto.components.automations.ExternalAutomationManagers.0a2d4359a8", "Manageable")
- : translate("auto.components.automations.ExternalAutomationManagers.dbdcec22bd", "Read-only")
- : translate("auto.components.automations.ExternalAutomationManagers.92405f1431", "Unavailable")}
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.0a2d4359a8',
+ 'Manageable'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.dbdcec22bd',
+ 'Read-only'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.92405f1431',
+ 'Unavailable'
+ )}
{manager.error ? ` - ${manager.error}` : null}
@@ -149,19 +172,45 @@ export function ExternalAutomationManagers({
{job.name}
- {job.enabled ? translate("auto.components.automations.ExternalAutomationManagers.b3feba84c7", "Active") : translate("auto.components.automations.ExternalAutomationManagers.2b0adbce21", "Paused")}
+ {job.enabled
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.b3feba84c7',
+ 'Active'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.2b0adbce21',
+ 'Paused'
+ )}
{scheduleDisplay.label}
- {translate("auto.components.automations.ExternalAutomationManagers.20fd7a3a15", "next")} {formatExternalDate(job.nextRunAt, now)} · {getProviderLabel(manager)}{' '}
- / {manager.targetLabel}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.20fd7a3a15',
+ 'next'
+ )}{' '}
+ {formatExternalDate(job.nextRunAt, now)} · {getProviderLabel(manager)} /{' '}
+ {manager.targetLabel}
- {manager.provider === "hermes" ? (
+ {manager.provider === 'hermes' ? (
- {job.runCount} {job.runCount === 1 ? translate("auto.components.automations.ExternalAutomationManagers.8e9165af08", "run") : translate("auto.components.automations.ExternalAutomationManagers.e66091daf4", "runs")} {translate("auto.components.automations.ExternalAutomationManagers.844f1acb72", "found")}
+ {job.runCount}{' '}
+ {job.runCount === 1
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.8e9165af08',
+ 'run'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.e66091daf4',
+ 'runs'
+ )}{' '}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.844f1acb72',
+ 'found'
+ )}
+
) : null}
{job.promptPreview || job.lastError ? (
@@ -170,12 +219,19 @@ export function ExternalAutomationManagers({
) : null}
- {translate("auto.components.automations.ExternalAutomationManagers.5820648765", "Last")}{formatExternalDate(job.lastRunAt, now)}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.5820648765',
+ 'Last'
+ )}
+ {formatExternalDate(job.lastRunAt, now)}
{job.lastStatus ? ` · ${job.lastStatus}` : null}
onAction(manager, job, 'run')}
>
@@ -185,9 +241,12 @@ export function ExternalAutomationManagers({
)}
- {manager.provider === "hermes" ? (
+ {manager.provider === 'hermes' ? (
onEdit?.(manager, job)}
>
@@ -196,7 +255,15 @@ export function ExternalAutomationManagers({
) : null}
onAction(manager, job, job.enabled ? 'pause' : 'resume')}
@@ -211,7 +278,10 @@ export function ExternalAutomationManagers({
)}
onAction(manager, job, 'delete')}
@@ -223,7 +293,7 @@ export function ExternalAutomationManagers({
)}
- {manager.provider === "hermes" ? (
+ {manager.provider === 'hermes' ? (
- {translate("auto.components.automations.ExternalAutomationManagers.3d58d5b67d", "No")}{' '}
- {manager.provider === 'hermes' ? translate("auto.components.automations.ExternalAutomationManagers.766abf833c", "Hermes") : translate("auto.components.automations.ExternalAutomationManagers.5524365227", "OpenClaw")} {translate("auto.components.automations.ExternalAutomationManagers.6da3bfba4b", "automations found.")}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.3d58d5b67d',
+ 'No'
+ )}{' '}
+ {manager.provider === 'hermes'
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.766abf833c',
+ 'Hermes'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.5524365227',
+ 'OpenClaw'
+ )}{' '}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.6da3bfba4b',
+ 'automations found.'
+ )}
+
) : null}
))}
{managers.length === 0 ? (
- {translate("auto.components.automations.ExternalAutomationManagers.e02f970595", "No external automation managers found.")}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.e02f970595',
+ 'No external automation managers found.'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx b/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx
index ea9e9df6976..aa8ff9666c7 100644
--- a/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx
+++ b/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx
@@ -183,7 +183,9 @@ export function ExternalAutomationRunTable({
-
{translate("auto.components.automations.ExternalAutomationRunTable.2d4388a908", "Runs")}
+
+ {translate('auto.components.automations.ExternalAutomationRunTable.2d4388a908', 'Runs')}
+
{isLoading ?
: null}
{fetchError ? (
@@ -197,7 +199,13 @@ export function ExternalAutomationRunTable({
) : null}
- {totalCount} {totalCount === 1 ? translate("auto.components.automations.ExternalAutomationRunTable.872d032d05", "run") : translate("auto.components.automations.ExternalAutomationRunTable.d5527d8fe7", "runs")}
+ {totalCount}{' '}
+ {totalCount === 1
+ ? translate('auto.components.automations.ExternalAutomationRunTable.872d032d05', 'run')
+ : translate(
+ 'auto.components.automations.ExternalAutomationRunTable.d5527d8fe7',
+ 'runs'
+ )}
@@ -205,9 +213,24 @@ export function ExternalAutomationRunTable({
- {translate("auto.components.automations.ExternalAutomationRunTable.d4b34feb66", "Run time")}
- {translate("auto.components.automations.ExternalAutomationRunTable.a813df9808", "Preview")}
- {translate("auto.components.automations.ExternalAutomationRunTable.be551397ca", "Status")}
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationRunTable.d4b34feb66',
+ 'Run time'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationRunTable.a813df9808',
+ 'Preview'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationRunTable.be551397ca',
+ 'Status'
+ )}
+
{visibleRuns.map((run) => (
@@ -248,7 +271,15 @@ export function ExternalAutomationRunTable({
) : (
- {isLoading ? translate("auto.components.automations.ExternalAutomationRunTable.8ea934cacf", "Loading runs...") : translate("auto.components.automations.ExternalAutomationRunTable.9c080765ff", "No Hermes runs found yet.")}
+ {isLoading
+ ? translate(
+ 'auto.components.automations.ExternalAutomationRunTable.8ea934cacf',
+ 'Loading runs...'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationRunTable.9c080765ff',
+ 'No Hermes runs found yet.'
+ )}
)}
@@ -256,7 +287,9 @@ export function ExternalAutomationRunTable({
- {pageStart}-{pageEnd} {translate("auto.components.automations.ExternalAutomationRunTable.7475c0ce96", "of")}{totalCount}
+ {pageStart}-{pageEnd}{' '}
+ {translate('auto.components.automations.ExternalAutomationRunTable.7475c0ce96', 'of')}
+ {totalCount}
@@ -264,7 +297,10 @@ export function ExternalAutomationRunTable({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.automations.ExternalAutomationRunTable.52d468a0b8", "Previous run page")}
+ aria-label={translate(
+ 'auto.components.automations.ExternalAutomationRunTable.52d468a0b8',
+ 'Previous run page'
+ )}
disabled={page === 0 || isLoading}
onClick={() => handlePageChange(Math.max(0, page - 1))}
>
@@ -277,7 +313,10 @@ export function ExternalAutomationRunTable({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.automations.ExternalAutomationRunTable.0ba9c0a95c", "Next run page")}
+ aria-label={translate(
+ 'auto.components.automations.ExternalAutomationRunTable.0ba9c0a95c',
+ 'Next run page'
+ )}
disabled={page >= totalPages - 1 || isLoading}
onClick={() => handlePageChange(Math.min(totalPages - 1, page + 1))}
>
diff --git a/src/renderer/src/components/automations/HermesCronOutputView.tsx b/src/renderer/src/components/automations/HermesCronOutputView.tsx
index 0a31387e89d..4d8dabaea30 100644
--- a/src/renderer/src/components/automations/HermesCronOutputView.tsx
+++ b/src/renderer/src/components/automations/HermesCronOutputView.tsx
@@ -303,7 +303,10 @@ export function HermesCronOutputView({ content }: { content: string }): React.JS
) : null}
{errorSection ? (
-
+
+
- {selected?.displayName ?? translate("auto.components.automations.WorkspaceCombobox.66a0cd9628", "Select workspace")}
+ {selected?.displayName ??
+ translate(
+ 'auto.components.automations.WorkspaceCombobox.66a0cd9628',
+ 'Select workspace'
+ )}
@@ -89,9 +93,20 @@ export function WorkspaceCombobox({
}}
>
-
+
- {translate("auto.components.automations.WorkspaceCombobox.ee5b280eba", "No workspaces found.")}
+
+ {translate(
+ 'auto.components.automations.WorkspaceCombobox.ee5b280eba',
+ 'No workspaces found.'
+ )}
+
{worktrees.map((worktree) => (
setQuery(e.target.value)}
- placeholder={translate("auto.components.browser.pane.BrowserFind.636a69cd66", "Find in page...")}
+ placeholder={translate(
+ 'auto.components.browser.pane.BrowserFind.636a69cd66',
+ 'Find in page...'
+ )}
className="min-w-0 flex-1 border-none bg-transparent text-sm text-white outline-none placeholder:text-zinc-500"
/>
{query ? (
- {totalMatches > 0 ? translate("auto.components.browser.pane.BrowserFind.fc63f336aa", "{{value0}} of {{value1}}", { value0: activeMatch, value1: totalMatches }) : translate("auto.components.browser.pane.BrowserFind.7baca7b1b8", "No matches")}
+ {totalMatches > 0
+ ? translate(
+ 'auto.components.browser.pane.BrowserFind.fc63f336aa',
+ '{{value0}} of {{value1}}',
+ { value0: activeMatch, value1: totalMatches }
+ )
+ : translate('auto.components.browser.pane.BrowserFind.7baca7b1b8', 'No matches')}
) : null}
@@ -170,7 +179,7 @@ export default function BrowserFind({
size="icon-xs"
onClick={findPrevious}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.browser.pane.BrowserFind.ca7aebbd7f", "Previous match")}
+ title={translate('auto.components.browser.pane.BrowserFind.ca7aebbd7f', 'Previous match')}
>
@@ -181,7 +190,7 @@ export default function BrowserFind({
size="icon-xs"
onClick={findNext}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.browser.pane.BrowserFind.5c0c02ae76", "Next match")}
+ title={translate('auto.components.browser.pane.BrowserFind.5c0c02ae76', 'Next match')}
>
@@ -194,7 +203,7 @@ export default function BrowserFind({
size="icon-xs"
onClick={onClose}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.browser.pane.BrowserFind.c9d5f63fdc", "Close")}
+ title={translate('auto.components.browser.pane.BrowserFind.c9d5f63fdc', 'Close')}
>
diff --git a/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx b/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx
index 52e063f710e..4bb0bd4d4eb 100644
--- a/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx
@@ -53,15 +53,33 @@ export function BrowserMobileDriverOverlay({ driver, onTakeBack }: Props): React
●
- {translate("auto.components.browser.pane.BrowserMobileDriverOverlay.20539eca03", "Mobile is driving this browser")}
+
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.20539eca03',
+ 'Mobile is driving this browser'
+ )}
+
+
+
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.d9768ec642',
+ 'Browser input is paused'
+ )}
-
{translate("auto.components.browser.pane.BrowserMobileDriverOverlay.d9768ec642", "Browser input is paused")}
- {translate("auto.components.browser.pane.BrowserMobileDriverOverlay.f4ecd61552", "This tab is being controlled from your phone. Take back to use it on desktop.")}
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.f4ecd61552',
+ 'This tab is being controlled from your phone. Take back to use it on desktop.'
+ )}
+
{/* autoFocus puts keyboard users on the recovery action when the lock appears. */}
- {translate("auto.components.browser.pane.BrowserMobileDriverOverlay.a6914ee43f", "Take back")}
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.a6914ee43f',
+ 'Take back'
+ )}
+
diff --git a/src/renderer/src/components/browser-pane/BrowserPane.tsx b/src/renderer/src/components/browser-pane/BrowserPane.tsx
index 0491106e750..74ae96ee901 100644
--- a/src/renderer/src/components/browser-pane/BrowserPane.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserPane.tsx
@@ -4173,6 +4173,10 @@ function BrowserPagePane({
[annotationBannerSendModeId, annotationTraySendModeId, closeAgentSendPopoverTargetMode]
)
+ const handleBrowserAnnotationsSentToAgent = useCallback((): void => {
+ recordFeatureInteraction('browser-annotations-sent-to-agent')
+ }, [recordFeatureInteraction])
+
const handleClearBrowserAnnotations = useCallback((): void => {
if (browserAnnotationsRef.current.length === 0) {
return
@@ -4877,6 +4881,7 @@ function BrowserPagePane({
prompt={browserAnnotationsPrompt}
promptDelivery="submit-after-ready"
launchSource="notes_send"
+ onPromptDelivered={handleBrowserAnnotationsSentToAgent}
/>
@@ -5136,6 +5141,7 @@ function BrowserPagePane({
prompt={browserAnnotationsPrompt}
promptDelivery="submit-after-ready"
launchSource="notes_send"
+ onPromptDelivered={handleBrowserAnnotationsSentToAgent}
/>
diff --git a/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx b/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx
index 894153de538..855bed0b36b 100644
--- a/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx
+++ b/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx
@@ -128,9 +128,14 @@ export default function GrabConfirmationSheet({
- {translate("auto.components.browser.pane.GrabConfirmationSheet.f3575229df", "Grab")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.f3575229df', 'Grab')}
+
- {translate("auto.components.browser.pane.GrabConfirmationSheet.50f7114f99", "Review before attaching. Captured page context may include visible site content.")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.50f7114f99',
+ 'Review before attaching. Captured page context may include visible site content.'
+ )}
+
@@ -147,7 +152,10 @@ export default function GrabConfirmationSheet({
@@ -156,7 +164,11 @@ export default function GrabConfirmationSheet({
{/* Element summary */}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.a759d8f866", "Selected Element")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.a759d8f866',
+ 'Selected Element'
+ )}
+
@@ -164,14 +176,20 @@ export default function GrabConfirmationSheet({
{target.accessibility.role ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.d053db279d", "role=")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.d053db279d',
+ 'role='
+ )}
+
) : null}
{target.accessibility.accessibleName ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a", "\"")}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a", "\"")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a', '"')}
+
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a', '"')}
+
) : null}
@@ -185,10 +203,19 @@ export default function GrabConfirmationSheet({
{/* Page info */}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.9098b118ab", "Page")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.9098b118ab', 'Page')}
+
-
+
@@ -200,7 +227,8 @@ export default function GrabConfirmationSheet({
{target.htmlSnippet ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.7d1480fbf1", "HTML")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.7d1480fbf1', 'HTML')}
+
@@ -211,7 +239,11 @@ export default function GrabConfirmationSheet({
{nearbyText.length > 0 ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.effd75e330", "Nearby Context")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.effd75e330',
+ 'Nearby Context'
+ )}
+
{nearbyText.map((text, i) => (
@@ -229,18 +261,28 @@ export default function GrabConfirmationSheet({
{/* Actions */}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.87d97bdd6d", "Cancel")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.87d97bdd6d', 'Cancel')}
+
- {translate("auto.components.browser.pane.GrabConfirmationSheet.26fd87f4df", "Copy")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.26fd87f4df', 'Copy')}
+
{onCopyScreenshot ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.7095e98362", "Copy Screenshot")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.7095e98362',
+ 'Copy Screenshot'
+ )}
+
) : null}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.314a0aaa5b", "Attach to AI")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.314a0aaa5b',
+ 'Attach to AI'
+ )}
+
)
diff --git a/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts b/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts
index 137547cc9a4..6454b6b7c15 100644
--- a/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts
+++ b/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts
@@ -83,7 +83,11 @@ export function buildBrowserAddressBarSuggestions({
topAction = {
url: buildSearchUrl(trimmed, searchEngine, { kagiSessionLink }),
title: trimmed,
- subtitle: translate("auto.components.browser.pane.browser.address.bar.suggestions.87fcdd0da9", "{{value0}} Search", { value0: SEARCH_ENGINE_LABELS[searchEngine] }),
+ subtitle: translate(
+ 'auto.components.browser.pane.browser.address.bar.suggestions.87fcdd0da9',
+ '{{value0}} Search',
+ { value0: SEARCH_ENGINE_LABELS[searchEngine] }
+ ),
lastVisitedAt: 0,
visitCount: 0,
isSearch: true
diff --git a/src/renderer/src/components/confirmation-dialog.tsx b/src/renderer/src/components/confirmation-dialog.tsx
index 7d4c252a61b..f13285c4907 100644
--- a/src/renderer/src/components/confirmation-dialog.tsx
+++ b/src/renderer/src/components/confirmation-dialog.tsx
@@ -99,14 +99,16 @@ export function ConfirmationDialogProvider({
settleActiveRequest(false)}>
- {displayedRequest?.options.cancelLabel ?? translate("auto.components.confirmation.dialog.56f5c60e0c", "Cancel")}
+ {displayedRequest?.options.cancelLabel ??
+ translate('auto.components.confirmation.dialog.56f5c60e0c', 'Cancel')}
settleActiveRequest(true)}
>
- {displayedRequest?.options.confirmLabel ?? translate("auto.components.confirmation.dialog.8490e5d36a", "Confirm")}
+ {displayedRequest?.options.confirmLabel ??
+ translate('auto.components.confirmation.dialog.8490e5d36a', 'Confirm')}
diff --git a/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx b/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx
index f70ed09b557..d85d2c72ed6 100644
--- a/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx
+++ b/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx
@@ -36,15 +36,27 @@ function AutoRenameBranchFromWorkControl(): JSX.Element {
-
{translate("auto.components.contextual.tours.ContextualTourControl.731c5573df", "Auto-name from first message")}
+
+ {translate(
+ 'auto.components.contextual.tours.ContextualTourControl.731c5573df',
+ 'Auto-name from first message'
+ )}
+
- {translate("auto.components.contextual.tours.ContextualTourControl.02e8373219", "Auto-generates a new name when you leave this text box empty.")}
+ {translate(
+ 'auto.components.contextual.tours.ContextualTourControl.02e8373219',
+ 'Auto-generates a new name when you leave this text box empty.'
+ )}
+
{
toggleAutoRenameBranchFromWork({
enabled,
diff --git a/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx b/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx
index d3506cffb20..0fac9afccda 100644
--- a/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx
+++ b/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx
@@ -132,7 +132,17 @@ export function ContextualTourOverlaySurface({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={renderState.isLastStep ? translate("auto.components.contextual.tours.ContextualTourOverlaySurface.d974f32a83", "Dismiss tour") : translate("auto.components.contextual.tours.ContextualTourOverlaySurface.4f86e2a10b", "Skip tour")}
+ aria-label={
+ renderState.isLastStep
+ ? translate(
+ 'auto.components.contextual.tours.ContextualTourOverlaySurface.d974f32a83',
+ 'Dismiss tour'
+ )
+ : translate(
+ 'auto.components.contextual.tours.ContextualTourOverlaySurface.4f86e2a10b',
+ 'Skip tour'
+ )
+ }
onClick={() => onSkip(activeTourId)}
className="absolute right-2 top-2 text-muted-foreground hover:text-foreground"
>
@@ -150,9 +160,22 @@ export function ContextualTourOverlaySurface({
/>
{!renderState.isFirstStep ? (
-
+
- {translate("auto.components.contextual.tours.ContextualTourOverlaySurface.4a9568f773", "Back")}
+ {translate(
+ 'auto.components.contextual.tours.ContextualTourOverlaySurface.4a9568f773',
+ 'Back'
+ )}
+
) : null}
{renderState.secondaryAction ? (
{primaryAction.label}
- {primaryAction.kind === "next" && !renderState.isLastStep ? : null}
+ {primaryAction.kind === 'next' && !renderState.isLastStep ? : null}
) : null}
diff --git a/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx b/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx
index 88361ea22f9..b52cbb6fdf4 100644
--- a/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx
+++ b/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx
@@ -19,7 +19,11 @@ export function ContextualTourProgressDots({
aria-valuemin={1}
aria-valuemax={total}
aria-valuenow={current}
- aria-label={translate("auto.components.contextual.tours.ContextualTourProgressDots.dcd6e6b03e", "Step {{value0}} of {{value1}}", { value0: current, value1: total })}
+ aria-label={translate(
+ 'auto.components.contextual.tours.ContextualTourProgressDots.dcd6e6b03e',
+ 'Step {{value0}} of {{value1}}',
+ { value0: current, value1: total }
+ )}
>
{Array.from({ length: total }).map((_, index) => {
@@ -41,7 +45,9 @@ export function ContextualTourProgressDots({
})}
- {current} {translate("auto.components.contextual.tours.ContextualTourProgressDots.7734cb8ad3", "of")}{total}
+ {current}{' '}
+ {translate('auto.components.contextual.tours.ContextualTourProgressDots.7734cb8ad3', 'of')}
+ {total}
)
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts
index 79d786799b3..a807ade9fe4 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts
@@ -118,7 +118,13 @@ export function measureContextualTourOverlayRenderState(args: {
const sidebarAlreadyVisible =
activeStep.primaryAction?.kind === 'show-worktrees' && args.sidebarOpen
const primaryAction = sidebarAlreadyVisible
- ? ({ kind: 'next', label: translate("auto.components.contextual.tours.contextual.tour.overlay.measurement.38b3155418", "Next") } as const)
+ ? ({
+ kind: 'next',
+ label: translate(
+ 'auto.components.contextual.tours.contextual.tour.overlay.measurement.38b3155418',
+ 'Next'
+ )
+ } as const)
: activeStep.primaryAction
const secondaryAction = sidebarAlreadyVisible ? undefined : activeStep.secondaryAction
diff --git a/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx b/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx
index 8babffcdd50..82cd87fe47c 100644
--- a/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx
+++ b/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx
@@ -52,7 +52,15 @@ export function DashboardAgentChildDisclosure({
onMouseDown={stopMouseDown}
onKeyDown={stopKeyDown}
className="-ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-sm border border-sidebar-border/80 bg-sidebar text-foreground/80 shadow-xs hover:bg-sidebar-accent hover:text-foreground"
- aria-label={translate("auto.components.dashboard.DashboardAgentChildDisclosure.1b57ce9fa4", "{{value0}} {{value1}} child {{value2}}", { value0: childAgentsExpanded ? 'Hide' : 'Show', value1: childAgentCount, value2: childAgentCount === 1 ? 'agent' : 'agents' })}
+ aria-label={translate(
+ 'auto.components.dashboard.DashboardAgentChildDisclosure.1b57ce9fa4',
+ '{{value0}} {{value1}} child {{value2}}',
+ {
+ value0: childAgentsExpanded ? 'Hide' : 'Show',
+ value1: childAgentCount,
+ value2: childAgentCount === 1 ? 'agent' : 'agents'
+ }
+ )}
aria-expanded={childAgentsExpanded}
>
- {translate("auto.components.dashboard.DashboardAgentRowMessage.0a01046763", "interrupted")}
+ {translate(
+ 'auto.components.dashboard.DashboardAgentRowMessage.0a01046763',
+ 'interrupted'
+ )}
+
) : null}
{lastAssistantMessage ? (
{
ev.preventDefault()
ev.stopPropagation()
void window.api.shell.openUrl(url)
}}
>
- {translate("auto.components.diff.comments.DiffCommentCard.6978871a3d", "Open")}
+ {translate('auto.components.diff.comments.DiffCommentCard.6978871a3d', 'Open')}
+
{(onSubmitEdit || onDelete) && (
)}
@@ -178,8 +185,14 @@ export function DiffCommentCard({
{
ev.preventDefault()
ev.stopPropagation()
@@ -195,8 +208,14 @@ export function DiffCommentCard({
{
ev.preventDefault()
ev.stopPropagation()
@@ -249,14 +268,23 @@ export function DiffCommentCard({
/>
- {translate("auto.components.diff.comments.DiffCommentCard.0203bed775", "Cancel")}
+ {translate('auto.components.diff.comments.DiffCommentCard.0203bed775', 'Cancel')}
+
void handleSubmit()}
disabled={!canSubmit}
- title={submitting ? translate("auto.components.diff.comments.DiffCommentCard.bb0a55f856", "Saving…") : undefined}
+ title={
+ submitting
+ ? translate(
+ 'auto.components.diff.comments.DiffCommentCard.bb0a55f856',
+ 'Saving…'
+ )
+ : undefined
+ }
>
- {translate("auto.components.diff.comments.DiffCommentCard.109a791e7b", "Save")}
+ {translate('auto.components.diff.comments.DiffCommentCard.109a791e7b', 'Save')}
+
diff --git a/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx b/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
index dd9d631a73a..ebfd2cb7c52 100644
--- a/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
+++ b/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
@@ -130,8 +130,16 @@ export function DiffCommentPopover({
{title ??
(startLine && startLine !== lineNumber
- ? translate("auto.components.diff.comments.DiffCommentPopover.c845170b3b", "Lines {{value0}}-{{value1}}", { value0: startLine, value1: lineNumber })
- : translate("auto.components.diff.comments.DiffCommentPopover.e05063cfc1", "Line {{value0}}", { value0: lineNumber }))}
+ ? translate(
+ 'auto.components.diff.comments.DiffCommentPopover.c845170b3b',
+ 'Lines {{value0}}-{{value1}}',
+ { value0: startLine, value1: lineNumber }
+ )
+ : translate(
+ 'auto.components.diff.comments.DiffCommentPopover.e05063cfc1',
+ 'Line {{value0}}',
+ { value0: lineNumber }
+ ))}
- {translate("auto.components.diff.comments.DiffCommentPopover.2b3ce6d394", "Cancel")}
+ {translate('auto.components.diff.comments.DiffCommentPopover.2b3ce6d394', 'Cancel')}
+
- {translate("auto.components.editor.ChangesModeView.54e0035b15", "Loading diff...")}
+ {translate('auto.components.editor.ChangesModeView.54e0035b15', 'Loading diff...')}
+
)
}
if (dc.kind === 'binary') {
return (
-
{translate("auto.components.editor.ChangesModeView.7dffb0f563", "Binary file")}
+
+ {translate('auto.components.editor.ChangesModeView.7dffb0f563', 'Binary file')}
+
- {translate("auto.components.editor.ChangesModeView.052c184f24", "Text diff is unavailable for this file.")}
+ {translate(
+ 'auto.components.editor.ChangesModeView.052c184f24',
+ 'Text diff is unavailable for this file.'
+ )}
+
)
@@ -68,7 +75,11 @@ export function ChangesModeView({
{activeFile.conflict &&
}
{isIdentical && (
- {translate("auto.components.editor.ChangesModeView.ef25ae2d09", "No uncommitted changes.")}
+ {translate(
+ 'auto.components.editor.ChangesModeView.ef25ae2d09',
+ 'No uncommitted changes.'
+ )}
+
)}
{copied ? (
<>
- {translate("auto.components.editor.CodeBlockCopyButton.28921f5bf9", "Copied")}
+
+ {translate('auto.components.editor.CodeBlockCopyButton.28921f5bf9', 'Copied')}
+
>
) : (
diff --git a/src/renderer/src/components/editor/CombinedDiffFileTree.tsx b/src/renderer/src/components/editor/CombinedDiffFileTree.tsx
index f09c5378ed7..5a92bdae79e 100644
--- a/src/renderer/src/components/editor/CombinedDiffFileTree.tsx
+++ b/src/renderer/src/components/editor/CombinedDiffFileTree.tsx
@@ -171,12 +171,16 @@ export function CombinedDiffFileTree({
@@ -198,7 +205,10 @@ export function CombinedDiffFileTree({
type="button"
variant="outline"
size="icon-sm"
- aria-label={translate("auto.components.editor.CombinedDiffFileTree.cd0e0ed79e", "Filter diff files")}
+ aria-label={translate(
+ 'auto.components.editor.CombinedDiffFileTree.cd0e0ed79e',
+ 'Filter diff files'
+ )}
className={cn(activeFilterCount > 0 && 'border-foreground/30 text-foreground')}
>
@@ -206,7 +216,11 @@ export function CombinedDiffFileTree({
- {translate("auto.components.editor.CombinedDiffFileTree.c00020f081", "File extensions")}
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.c00020f081',
+ 'File extensions'
+ )}
+
{availableExtensions.map((extension) => {
const checked = !excludedExtensions.has(extension)
@@ -234,7 +248,12 @@ export function CombinedDiffFileTree({
- {translate("auto.components.editor.CombinedDiffFileTree.be119cb9d1", "Viewed files")}
+
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.be119cb9d1',
+ 'Viewed files'
+ )}
+
{activeFilterCount > 0 && (
- {translate("auto.components.editor.CombinedDiffFileTree.eafe1aeb53", "Reset filters")}
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.eafe1aeb53',
+ 'Reset filters'
+ )}
+
)}
@@ -252,8 +275,12 @@ export function CombinedDiffFileTree({
{filteredEntries.length === 0 ? (
- {translate("auto.components.editor.CombinedDiffFileTree.f984289373", "No files match the current filters.")}
- ) : mode === "uncommitted" ? (
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.f984289373',
+ 'No files match the current filters.'
+ )}
+
+ ) : mode === 'uncommitted' ? (
uncommittedGroups.map((group) => (
diff --git a/src/renderer/src/components/editor/CombinedDiffViewer.tsx b/src/renderer/src/components/editor/CombinedDiffViewer.tsx
index 734663e2c3f..a1050c648da 100644
--- a/src/renderer/src/components/editor/CombinedDiffViewer.tsx
+++ b/src/renderer/src/components/editor/CombinedDiffViewer.tsx
@@ -1219,7 +1219,12 @@ export default function CombinedDiffViewer({
if (ok) {
setClearNotesDialogOpen(false)
} else {
- toast.error(translate("auto.components.editor.CombinedDiffViewer.45cf23b418", "Failed to clear notes."))
+ toast.error(
+ translate(
+ 'auto.components.editor.CombinedDiffViewer.45cf23b418',
+ 'Failed to clear notes.'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -1269,9 +1274,17 @@ export default function CombinedDiffViewer({
- {translate("auto.components.editor.CombinedDiffViewer.820ec01f24", "Conflicted files are reviewed separately")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.820ec01f24',
+ 'Conflicted files are reviewed separately'
+ )}
+
- {translate("auto.components.editor.CombinedDiffViewer.eb5f40e49c", "This diff view excludes unresolved conflicts because the normal two-way diff pipeline is not conflict-safe.")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.eb5f40e49c',
+ 'This diff view excludes unresolved conflicts because the normal two-way diff pipeline is not conflict-safe.'
+ )}
+
{file.skippedConflicts!.map((entry) => entry.path).join(', ')}
@@ -1292,7 +1305,11 @@ export default function CombinedDiffViewer({
)
}
>
- {translate("auto.components.editor.CombinedDiffViewer.39f8007549", "Review conflicts")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.39f8007549',
+ 'Review conflicts'
+ )}
+
@@ -1305,7 +1322,11 @@ export default function CombinedDiffViewer({
{commitHeader}
- {translate("auto.components.editor.CombinedDiffViewer.fd8892b120", "No changes to display")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.fd8892b120',
+ 'No changes to display'
+ )}
+
)
}
@@ -1313,9 +1334,21 @@ export default function CombinedDiffViewer({
const skippedConflictNotice =
(file.skippedConflicts?.length ?? 0) > 0 ? (
-
{translate("auto.components.editor.CombinedDiffViewer.820ec01f24", "Conflicted files are reviewed separately")}
+
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.820ec01f24',
+ 'Conflicted files are reviewed separately'
+ )}
+
- {file.skippedConflicts!.length} {translate("auto.components.editor.CombinedDiffViewer.689b99f8ad", "unresolved conflict")}{file.skippedConflicts!.length === 1 ? '' : 's'} {translate("auto.components.editor.CombinedDiffViewer.39e73e7181", "were excluded from this diff view.")}
+ {file.skippedConflicts!.length}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.689b99f8ad', 'unresolved conflict')}
+ {file.skippedConflicts!.length === 1 ? '' : 's'}{' '}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.39e73e7181',
+ 'were excluded from this diff view.'
+ )}
+
- {translate("auto.components.editor.CombinedDiffViewer.39f8007549", "Review conflicts")}
+ {translate('auto.components.editor.CombinedDiffViewer.39f8007549', 'Review conflicts')}
+
) : null
@@ -1352,19 +1386,40 @@ export default function CombinedDiffViewer({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.CombinedDiffViewer.b6c3b84476", "Show file tree")}
+ aria-label={translate(
+ 'auto.components.editor.CombinedDiffViewer.b6c3b84476',
+ 'Show file tree'
+ )}
onClick={() => setFileTreeCollapsed(false)}
>
- {translate("auto.components.editor.CombinedDiffViewer.b6c3b84476", "Show file tree")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.b6c3b84476',
+ 'Show file tree'
+ )}
+
)}
- {sections.length} {translate("auto.components.editor.CombinedDiffViewer.7e7ca60816", "changed files")}{isBranchMode && branchCompare ? translate("auto.components.editor.CombinedDiffViewer.6094135eec", " vs {{value0}}", { value0: branchCompare.baseRef }) : ''}
- {isCommitMode && commitCompare ? translate("auto.components.editor.CombinedDiffViewer.724a13568d", " in {{value0}}", { value0: commitCompare.compareRef }) : ''}
+ {sections.length}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.7e7ca60816', 'changed files')}
+ {isBranchMode && branchCompare
+ ? translate(
+ 'auto.components.editor.CombinedDiffViewer.6094135eec',
+ ' vs {{value0}}',
+ { value0: branchCompare.baseRef }
+ )
+ : ''}
+ {isCommitMode && commitCompare
+ ? translate(
+ 'auto.components.editor.CombinedDiffViewer.724a13568d',
+ ' in {{value0}}',
+ { value0: commitCompare.compareRef }
+ )
+ : ''}
{diffCommentCount > 0 && (
@@ -1373,10 +1428,22 @@ export default function CombinedDiffViewer({
- {translate("auto.components.editor.CombinedDiffViewer.bb84b4c374", "AI notes")}
+
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.bb84b4c374',
+ 'AI notes'
+ )}
+
{diffCommentCount}
@@ -1409,22 +1476,32 @@ export default function CombinedDiffViewer({
className="text-xs text-muted-foreground hover:text-foreground transition-colors"
onClick={openAlternateDiff}
>
- {file.combinedAlternate.source === "combined-branch"
- ? translate("auto.components.editor.CombinedDiffViewer.3d909843bb", "Open Branch Diff")
- : translate("auto.components.editor.CombinedDiffViewer.982d14bfa5", "Open Uncommitted Diff")}
+ {file.combinedAlternate.source === 'combined-branch'
+ ? translate(
+ 'auto.components.editor.CombinedDiffViewer.3d909843bb',
+ 'Open Branch Diff'
+ )
+ : translate(
+ 'auto.components.editor.CombinedDiffViewer.982d14bfa5',
+ 'Open Uncommitted Diff'
+ )}
)}
setAllSectionsCollapsed(!allSectionsCollapsed)}
>
- {allSectionsCollapsed ? translate("auto.components.editor.CombinedDiffViewer.19c45cfdc0", "Expand All") : translate("auto.components.editor.CombinedDiffViewer.ea08dae15b", "Collapse All")}
+ {allSectionsCollapsed
+ ? translate('auto.components.editor.CombinedDiffViewer.19c45cfdc0', 'Expand All')
+ : translate('auto.components.editor.CombinedDiffViewer.ea08dae15b', 'Collapse All')}
- {sideBySide ? translate("auto.components.editor.CombinedDiffViewer.f786fd54e1", "Inline") : translate("auto.components.editor.CombinedDiffViewer.ec5053c7f5", "Side by Side")}
+ {sideBySide
+ ? translate('auto.components.editor.CombinedDiffViewer.f786fd54e1', 'Inline')
+ : translate('auto.components.editor.CombinedDiffViewer.ec5053c7f5', 'Side by Side')}
@@ -1538,9 +1615,20 @@ export default function CombinedDiffViewer({
>
- {translate("auto.components.editor.CombinedDiffViewer.948a5fd6c8", "Clear Notes")}
+
+ {translate('auto.components.editor.CombinedDiffViewer.948a5fd6c8', 'Clear Notes')}
+
- {translate("auto.components.editor.CombinedDiffViewer.84898c548d", "Clear")}{diffCommentCount} {diffCommentCount === 1 ? translate("auto.components.editor.CombinedDiffViewer.8ab3248fd8", "note") : translate("auto.components.editor.CombinedDiffViewer.0fb870a0fe", "notes")} {translate("auto.components.editor.CombinedDiffViewer.80a286d8f5", "from this worktree?")}
+ {translate('auto.components.editor.CombinedDiffViewer.84898c548d', 'Clear')}
+ {diffCommentCount}{' '}
+ {diffCommentCount === 1
+ ? translate('auto.components.editor.CombinedDiffViewer.8ab3248fd8', 'note')
+ : translate('auto.components.editor.CombinedDiffViewer.0fb870a0fe', 'notes')}{' '}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.80a286d8f5',
+ 'from this worktree?'
+ )}
+
setClearNotesDialogOpen(false)}
disabled={isClearingNotes}
>
- {translate("auto.components.editor.CombinedDiffViewer.0f806a2ab1", "Cancel")}
+ {translate('auto.components.editor.CombinedDiffViewer.0f806a2ab1', 'Cancel')}
+
- {translate("auto.components.editor.CombinedDiffViewer.948a5fd6c8", "Clear Notes")}
+ {translate('auto.components.editor.CombinedDiffViewer.948a5fd6c8', 'Clear Notes')}
+
@@ -1585,7 +1675,9 @@ function DiffNotesPreviewPopover({
- {translate("auto.components.editor.CombinedDiffViewer.bb84b4c374", "AI notes")}
+
+ {translate('auto.components.editor.CombinedDiffViewer.bb84b4c374', 'AI notes')}
+
{totalCount}
@@ -1600,7 +1692,8 @@ function DiffNotesPreviewPopover({
disabled={totalCount === 0}
>
{copied ? : }
- {translate("auto.components.editor.CombinedDiffViewer.88b70d0ef5", "Copy")}
+ {translate('auto.components.editor.CombinedDiffViewer.88b70d0ef5', 'Copy')}
+
- {translate("auto.components.editor.CombinedDiffViewer.84898c548d", "Clear")}
+ {translate('auto.components.editor.CombinedDiffViewer.84898c548d', 'Clear')}
+
@@ -1620,7 +1714,8 @@ function DiffNotesPreviewPopover({
{comment.filePath}
{comment.sentAt ? (
- {translate("auto.components.editor.CombinedDiffViewer.1da745c551", "Sent")}
+ {translate('auto.components.editor.CombinedDiffViewer.1da745c551', 'Sent')}
+
) : null}
{getDiffCommentLineLabel(comment, true)}
@@ -1633,7 +1728,13 @@ function DiffNotesPreviewPopover({
))}
{remainingCount > 0 && (
- {remainingCount} {translate("auto.components.editor.CombinedDiffViewer.e3b9a6ce02", "more")}{remainingCount === 1 ? translate("auto.components.editor.CombinedDiffViewer.8ab3248fd8", "note") : translate("auto.components.editor.CombinedDiffViewer.0fb870a0fe", "notes")} {translate("auto.components.editor.CombinedDiffViewer.35cc27aeb2", "in Source Control")}
+ {remainingCount}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.e3b9a6ce02', 'more')}
+ {remainingCount === 1
+ ? translate('auto.components.editor.CombinedDiffViewer.8ab3248fd8', 'note')
+ : translate('auto.components.editor.CombinedDiffViewer.0fb870a0fe', 'notes')}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.35cc27aeb2', 'in Source Control')}
+
)}
diff --git a/src/renderer/src/components/editor/ConflictComponents.tsx b/src/renderer/src/components/editor/ConflictComponents.tsx
index 23740ba2c9d..47c74ae88db 100644
--- a/src/renderer/src/components/editor/ConflictComponents.tsx
+++ b/src/renderer/src/components/editor/ConflictComponents.tsx
@@ -100,7 +100,9 @@ export function ConflictBanner({
)}
- {label} {translate("auto.components.editor.ConflictComponents.55d61a0ccd", "conflict ·")}{CONFLICT_KIND_LABELS[conflict.conflictKind]}
+ {label}{' '}
+ {translate('auto.components.editor.ConflictComponents.55d61a0ccd', 'conflict ·')}
+ {CONFLICT_KIND_LABELS[conflict.conflictKind]}
{conflictNavigation && conflictNavigation.total > 0 && (
@@ -116,14 +118,21 @@ export function ConflictBanner({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.ConflictComponents.41d9af2e7a", "Previous conflict")}
+ aria-label={translate(
+ 'auto.components.editor.ConflictComponents.41d9af2e7a',
+ 'Previous conflict'
+ )}
onClick={() => conflictNavigation.onJump('previous')}
>
- {translate("auto.components.editor.ConflictComponents.41d9af2e7a", "Previous conflict")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.41d9af2e7a',
+ 'Previous conflict'
+ )}
+
@@ -131,14 +140,18 @@ export function ConflictBanner({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.ConflictComponents.9c2901ef8a", "Next conflict")}
+ aria-label={translate(
+ 'auto.components.editor.ConflictComponents.9c2901ef8a',
+ 'Next conflict'
+ )}
onClick={() => conflictNavigation.onJump('next')}
>
- {translate("auto.components.editor.ConflictComponents.9c2901ef8a", "Next conflict")}
+ {translate('auto.components.editor.ConflictComponents.9c2901ef8a', 'Next conflict')}
+
)}
@@ -150,10 +163,17 @@ export function ConflictBanner({
list where it provides actionable guidance. */}
{!isUnresolved && (
- {translate("auto.components.editor.ConflictComponents.6e459867ad", "Session-local continuity state. Git is no longer reporting this file as unmerged.")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.6e459867ad',
+ 'Session-local continuity state. Git is no longer reporting this file as unmerged.'
+ )}
+
)}
{entry?.oldPath && (
- {translate("auto.components.editor.ConflictComponents.d5edd81755", "Renamed from")}{entry.oldPath}
+
+ {translate('auto.components.editor.ConflictComponents.d5edd81755', 'Renamed from')}
+ {entry.oldPath}
+
)}
)
@@ -172,7 +192,11 @@ export function ConflictPlaceholderView({ file }: { file: OpenFile }): React.JSX
{CONFLICT_KIND_LABELS[conflict.conflictKind]}
- {conflict.message ?? translate("auto.components.editor.ConflictComponents.da539359b6", "No working-tree file is available to edit for this conflict.")}
+ {conflict.message ??
+ translate(
+ 'auto.components.editor.ConflictComponents.da539359b6',
+ 'No working-tree file is available to edit for this conflict.'
+ )}
{conflict.guidance ?? CONFLICT_HINT_MAP[conflict.conflictKind]}
@@ -233,16 +257,27 @@ export function ConflictReviewPanel({
return (
-
{translate("auto.components.editor.ConflictComponents.992145ff5a", "All conflicts resolved")}
+
+ {translate(
+ 'auto.components.editor.ConflictComponents.992145ff5a',
+ 'All conflicts resolved'
+ )}
+
- {translate("auto.components.editor.ConflictComponents.31931dec46", "This review snapshot no longer has any live unresolved conflicts.")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.31931dec46',
+ 'This review snapshot no longer has any live unresolved conflicts.'
+ )}
+
- {translate("auto.components.editor.ConflictComponents.28e7db4a90", "Source Control")}
+ {translate('auto.components.editor.ConflictComponents.28e7db4a90', 'Source Control')}
+
- {translate("auto.components.editor.ConflictComponents.58ad5ad431", "Dismiss")}
+ {translate('auto.components.editor.ConflictComponents.58ad5ad431', 'Dismiss')}
+
@@ -268,34 +303,55 @@ export function ConflictReviewPanel({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.ConflictComponents.c8ca989aea", "Show file tree")}
+ aria-label={translate(
+ 'auto.components.editor.ConflictComponents.c8ca989aea',
+ 'Show file tree'
+ )}
onClick={() => setFileTreeCollapsed(false)}
>
- {translate("auto.components.editor.ConflictComponents.c8ca989aea", "Show file tree")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.c8ca989aea',
+ 'Show file tree'
+ )}
+
)}
- {unresolvedCount} {translate("auto.components.editor.ConflictComponents.4be41eaafc", "unresolved conflict")}{unresolvedCount === 1 ? '' : 's'}
+ {unresolvedCount}{' '}
+ {translate(
+ 'auto.components.editor.ConflictComponents.4be41eaafc',
+ 'unresolved conflict'
+ )}
+ {unresolvedCount === 1 ? '' : 's'}
·
- {translate("auto.components.editor.ConflictComponents.a1ce36f77d", "Snapshot captured at")}{snapshotTime}.
+ {translate(
+ 'auto.components.editor.ConflictComponents.a1ce36f77d',
+ 'Snapshot captured at'
+ )}
+ {snapshotTime}.
- {translate("auto.components.editor.ConflictComponents.90d576adb2", "Refresh")}
+ {translate('auto.components.editor.ConflictComponents.90d576adb2', 'Refresh')}
+
{selectedContent ?? (
- {translate("auto.components.editor.ConflictComponents.f338288514", "Loading conflict contents...")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.f338288514',
+ 'Loading conflict contents...'
+ )}
+
)}
diff --git a/src/renderer/src/components/editor/ConflictReviewFileTree.tsx b/src/renderer/src/components/editor/ConflictReviewFileTree.tsx
index 2a702ef0eee..f3e5e02c425 100644
--- a/src/renderer/src/components/editor/ConflictReviewFileTree.tsx
+++ b/src/renderer/src/components/editor/ConflictReviewFileTree.tsx
@@ -73,14 +73,18 @@ export function ConflictReviewFileTree({
- {translate("auto.components.editor.ConflictReviewFileTree.99496bab6e", "Files")}
+ {translate('auto.components.editor.ConflictReviewFileTree.99496bab6e', 'Files')}
+
{entries.length}
onCollapsedChange(true)}
>
@@ -90,7 +94,11 @@ export function ConflictReviewFileTree({
{rows.length === 0 ? (
- {translate("auto.components.editor.ConflictReviewFileTree.3449521a8c", "No conflicts in this snapshot.")}
+ {translate(
+ 'auto.components.editor.ConflictReviewFileTree.3449521a8c',
+ 'No conflicts in this snapshot.'
+ )}
+
) : (
rows.map((node) => (
- {isStillUnresolved ? translate("auto.components.editor.ConflictReviewFileTree.69d4e210bb", "Unresolved") : liveEntry ? translate("auto.components.editor.ConflictReviewFileTree.8528a5eaf5", "Resolved") : translate("auto.components.editor.ConflictReviewFileTree.496e28a932", "Gone")}
+ {isStillUnresolved
+ ? translate('auto.components.editor.ConflictReviewFileTree.69d4e210bb', 'Unresolved')
+ : liveEntry
+ ? translate('auto.components.editor.ConflictReviewFileTree.8528a5eaf5', 'Resolved')
+ : translate('auto.components.editor.ConflictReviewFileTree.496e28a932', 'Gone')}
)
diff --git a/src/renderer/src/components/editor/CsvViewer.tsx b/src/renderer/src/components/editor/CsvViewer.tsx
index b0db869d504..e424a98c938 100644
--- a/src/renderer/src/components/editor/CsvViewer.tsx
+++ b/src/renderer/src/components/editor/CsvViewer.tsx
@@ -92,7 +92,8 @@ export default function CsvViewer({ content, filePath }: CsvViewerProps): React.
if (parsed.rows.length === 0) {
return (
- {translate("auto.components.editor.CsvViewer.a233d55b77", "Empty file")}
+ {translate('auto.components.editor.CsvViewer.a233d55b77', 'Empty file')}
+
)
}
@@ -178,8 +179,13 @@ export default function CsvViewer({ content, filePath }: CsvViewerProps): React.
- {bodyRows.length.toLocaleString()} {translate("auto.components.editor.CsvViewer.ac31d2cd60", "rows")}
- {columnCount} {translate("auto.components.editor.CsvViewer.eedd0d37a7", "columns")}
+
+ {bodyRows.length.toLocaleString()}{' '}
+ {translate('auto.components.editor.CsvViewer.ac31d2cd60', 'rows')}
+
+
+ {columnCount} {translate('auto.components.editor.CsvViewer.eedd0d37a7', 'columns')}
+
)
diff --git a/src/renderer/src/components/editor/DiffNotesSendMenu.tsx b/src/renderer/src/components/editor/DiffNotesSendMenu.tsx
index 15985bec04f..32638d4faab 100644
--- a/src/renderer/src/components/editor/DiffNotesSendMenu.tsx
+++ b/src/renderer/src/components/editor/DiffNotesSendMenu.tsx
@@ -43,7 +43,7 @@ export function DiffNotesSendMenu({
const scopes = useMemo[]>(() => {
const allNotesScope = {
id: 'all',
- label: translate("auto.components.editor.DiffNotesSendMenu.8b87612461", "All unsent notes"),
+ label: translate('auto.components.editor.DiffNotesSendMenu.8b87612461', 'All unsent notes'),
notes: unsentNotes,
prompt: unsentPrompt
}
@@ -53,7 +53,7 @@ export function DiffNotesSendMenu({
return [
{
id: 'file',
- label: translate("auto.components.editor.DiffNotesSendMenu.f1aa04b5cf", "This file"),
+ label: translate('auto.components.editor.DiffNotesSendMenu.f1aa04b5cf', 'This file'),
notes: unsentFileNotes,
prompt: unsentFilePrompt
},
diff --git a/src/renderer/src/components/editor/DiffSectionBody.tsx b/src/renderer/src/components/editor/DiffSectionBody.tsx
index 2a472cac5fe..0010edc760e 100644
--- a/src/renderer/src/components/editor/DiffSectionBody.tsx
+++ b/src/renderer/src/components/editor/DiffSectionBody.tsx
@@ -85,7 +85,9 @@ export function DiffSectionBody({
{section.loading ? (
- {translate("auto.components.editor.DiffSectionBody.f5cf81cec2", "Loading diff...")}
+
+ {translate('auto.components.editor.DiffSectionBody.f5cf81cec2', 'Loading diff...')}
+
) : section.error ? (
@@ -104,7 +106,8 @@ export function DiffSectionBody({
}}
>
- {translate("auto.components.editor.DiffSectionBody.cef4cf0ff5", "Retry")}
+ {translate('auto.components.editor.DiffSectionBody.cef4cf0ff5', 'Retry')}
+
) : section.diffResult?.kind === 'binary' ? (
section.diffResult.isImage ? (
@@ -119,11 +122,22 @@ export function DiffSectionBody({
) : (
-
{translate("auto.components.editor.DiffSectionBody.35d6afb5be", "Binary file changed")}
+
+ {translate(
+ 'auto.components.editor.DiffSectionBody.35d6afb5be',
+ 'Binary file changed'
+ )}
+
{isBranchMode
- ? translate("auto.components.editor.DiffSectionBody.7ce8436458", "Text diff is unavailable for this file in branch compare.")
- : translate("auto.components.editor.DiffSectionBody.72f71f52eb", "Text diff is unavailable for this file.")}
+ ? translate(
+ 'auto.components.editor.DiffSectionBody.7ce8436458',
+ 'Text diff is unavailable for this file in branch compare.'
+ )
+ : translate(
+ 'auto.components.editor.DiffSectionBody.72f71f52eb',
+ 'Text diff is unavailable for this file.'
+ )}
diff --git a/src/renderer/src/components/editor/DiffSectionHeader.tsx b/src/renderer/src/components/editor/DiffSectionHeader.tsx
index b2529feba78..c69600a8b24 100644
--- a/src/renderer/src/components/editor/DiffSectionHeader.tsx
+++ b/src/renderer/src/components/editor/DiffSectionHeader.tsx
@@ -56,7 +56,7 @@ export function DiffSectionHeader({
console.error('Failed to copy diff path:', error)
})
}}
- title={translate("auto.components.editor.DiffSectionHeader.8915726e93", "Copy path")}
+ title={translate('auto.components.editor.DiffSectionHeader.8915726e93', 'Copy path')}
>
{path}
diff --git a/src/renderer/src/components/editor/EditorContent.tsx b/src/renderer/src/components/editor/EditorContent.tsx
index 8b1aed68ff4..1e572714926 100644
--- a/src/renderer/src/components/editor/EditorContent.tsx
+++ b/src/renderer/src/components/editor/EditorContent.tsx
@@ -81,11 +81,14 @@ function FileLoadErrorView({
-
{translate("auto.components.editor.EditorContent.39f018b052", "Unable to load file")}
+
+ {translate('auto.components.editor.EditorContent.39f018b052', 'Unable to load file')}
+
{message}
- {translate("auto.components.editor.EditorContent.2a512bb46a", "Retry")}
+ {translate('auto.components.editor.EditorContent.2a512bb46a', 'Retry')}
+
@@ -253,8 +256,10 @@ export function EditorContent({
conflictKind: entry.conflictKind,
conflictStatus: entry.conflictStatus,
conflictStatusSource: entry.conflictStatusSource,
- message:
- translate("auto.components.editor.EditorContent.8b1a605bae", "This file is in a conflict state, but no working-tree file is available to edit."),
+ message: translate(
+ 'auto.components.editor.EditorContent.8b1a605bae',
+ 'This file is in a conflict state, but no working-tree file is available to edit.'
+ ),
guidance: 'Resolve the conflict in Git or restore one side before reopening it.'
}
: {
@@ -477,7 +482,8 @@ export function EditorContent({
return (
- {translate("auto.components.editor.EditorContent.b2735221f5", "Loading...")}
+ {translate('auto.components.editor.EditorContent.b2735221f5', 'Loading...')}
+
)
}
@@ -506,7 +512,11 @@ export function EditorContent({
return (
- {translate("auto.components.editor.EditorContent.b9de81ba52", "Binary file — cannot display")}
+ {translate(
+ 'auto.components.editor.EditorContent.b9de81ba52',
+ 'Binary file — cannot display'
+ )}
+
)
}
@@ -650,7 +660,8 @@ export function EditorContent({
if (!fc) {
return (
- {translate("auto.components.editor.EditorContent.37a0e81fa6", "Loading preview...")}
+ {translate('auto.components.editor.EditorContent.37a0e81fa6', 'Loading preview...')}
+
)
}
if (fc.loadError) {
@@ -661,7 +672,11 @@ export function EditorContent({
if (fc.isBinary) {
return (
- {translate("auto.components.editor.EditorContent.8608ce4cb1", "Markdown preview is unavailable for binary files.")}
+ {translate(
+ 'auto.components.editor.EditorContent.8608ce4cb1',
+ 'Markdown preview is unavailable for binary files.'
+ )}
+
)
}
const previewSourceFileId = activeFile.markdownPreviewSourceFileId ?? activeFile.filePath
@@ -694,7 +709,8 @@ export function EditorContent({
if (!fc) {
return (
- {translate("auto.components.editor.EditorContent.b2735221f5", "Loading...")}
+ {translate('auto.components.editor.EditorContent.b2735221f5', 'Loading...')}
+
)
}
if (fc.loadError) {
@@ -710,7 +726,11 @@ export function EditorContent({
}
return (
- {translate("auto.components.editor.EditorContent.b9de81ba52", "Binary file — cannot display")}
+ {translate(
+ 'auto.components.editor.EditorContent.b9de81ba52',
+ 'Binary file — cannot display'
+ )}
+
)
}
if (isChangesMode) {
@@ -744,19 +764,19 @@ export function EditorContent({
{isMarkdown ? (
renderMarkdownContent(fc)
- ) : isMermaid && mdViewMode === "rich" ? (
+ ) : isMermaid && mdViewMode === 'rich' ? (
- ) : isCsv && mdViewMode === "rich" ? (
+ ) : isCsv && mdViewMode === 'rich' ? (
- ) : isNotebook && mdViewMode === "rich" ? (
+ ) : isNotebook && mdViewMode === 'rich' ? (
- {translate("auto.components.editor.EditorContent.c88c73a0d3", "Loading diff...")}
+ {translate('auto.components.editor.EditorContent.c88c73a0d3', 'Loading diff...')}
+
)
}
const isEditable = activeFile.diffSource === 'unstaged'
@@ -800,11 +821,19 @@ export function EditorContent({
return (
-
{translate("auto.components.editor.EditorContent.78541e254e", "Binary file changed")}
+
+ {translate('auto.components.editor.EditorContent.78541e254e', 'Binary file changed')}
+
- {activeFile.diffSource === "branch"
- ? translate("auto.components.editor.EditorContent.3c6e71df22", "Text diff is unavailable for this file in branch compare.")
- : translate("auto.components.editor.EditorContent.8a0898ae4c", "Text diff is unavailable for this file.")}
+ {activeFile.diffSource === 'branch'
+ ? translate(
+ 'auto.components.editor.EditorContent.3c6e71df22',
+ 'Text diff is unavailable for this file in branch compare.'
+ )
+ : translate(
+ 'auto.components.editor.EditorContent.8a0898ae4c',
+ 'Text diff is unavailable for this file.'
+ )}
@@ -819,7 +848,11 @@ export function EditorContent({
deletions simultaneously, so preview mode intentionally shows the
modified side of the diff. Source mode remains available for the
actual line-by-line comparison. */}
- {translate("auto.components.editor.EditorContent.9640d1d3db", "Previewing the modified version of this diff. Switch to source mode to inspect changes.")}
+ {translate(
+ 'auto.components.editor.EditorContent.9640d1d3db',
+ 'Previewing the modified version of this diff. Switch to source mode to inspect changes.'
+ )}
+
- {translate("auto.components.editor.EditorContent.e4b074749d", "Front Matter")}
- {translate("auto.components.editor.EditorContent.56dba34e1a", "(edit in source mode)")}
+ {translate('auto.components.editor.EditorContent.e4b074749d', 'Front Matter')}
+
+ {translate('auto.components.editor.EditorContent.56dba34e1a', '(edit in source mode)')}
+
{inner}
diff --git a/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx b/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx
index 2a84a561ec4..61f8128c894 100644
--- a/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx
+++ b/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx
@@ -39,8 +39,14 @@ export function EditorPanelMarkdownActionsMenu({
@@ -54,7 +60,15 @@ export function EditorPanelMarkdownActionsMenu({
onToggleMarkdownFrontmatter()
}}
>
- {markdownFrontmatterVisible ? translate("auto.components.editor.EditorPanelMarkdownActionsMenu.10c39d58c1", "Hide front matter") : translate("auto.components.editor.EditorPanelMarkdownActionsMenu.8c8b7f5ff5", "Show front matter")}
+ {markdownFrontmatterVisible
+ ? translate(
+ 'auto.components.editor.EditorPanelMarkdownActionsMenu.10c39d58c1',
+ 'Hide front matter'
+ )
+ : translate(
+ 'auto.components.editor.EditorPanelMarkdownActionsMenu.8c8b7f5ff5',
+ 'Show front matter'
+ )}
{hasViewModeToggle ? : null}
>
@@ -67,7 +81,11 @@ export function EditorPanelMarkdownActionsMenu({
disabled={mdViewMode === 'source'}
onSelect={onExportMarkdownToPdf}
>
- {translate("auto.components.editor.EditorPanelMarkdownActionsMenu.3e0ce48c24", "Export as PDF")}
+ {translate(
+ 'auto.components.editor.EditorPanelMarkdownActionsMenu.3e0ce48c24',
+ 'Export as PDF'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/editor/EditorPanelShell.tsx b/src/renderer/src/components/editor/EditorPanelShell.tsx
index cc2c84238ad..3eac493d120 100644
--- a/src/renderer/src/components/editor/EditorPanelShell.tsx
+++ b/src/renderer/src/components/editor/EditorPanelShell.tsx
@@ -185,6 +185,7 @@ export function EditorPanelShell({
function EditorLoadingFallback(): JSX.Element {
return (
- {translate("auto.components.editor.EditorPanelShell.e2c4dec350", "Loading editor...")}
+ {translate('auto.components.editor.EditorPanelShell.e2c4dec350', 'Loading editor...')}
+
)
}
diff --git a/src/renderer/src/components/editor/EditorViewToggle.tsx b/src/renderer/src/components/editor/EditorViewToggle.tsx
index 30228a07a23..82b07c3a224 100644
--- a/src/renderer/src/components/editor/EditorViewToggle.tsx
+++ b/src/renderer/src/components/editor/EditorViewToggle.tsx
@@ -27,29 +27,29 @@ type ViewModeMetadata = { label: string; icon: LucideIcon; title?: string }
const DEFAULT_VIEW_MODE_METADATA: Record = {
source: {
- label: translate("auto.components.editor.EditorViewToggle.4d6ccb7ba6", "Source"),
+ label: translate('auto.components.editor.EditorViewToggle.4d6ccb7ba6', 'Source'),
icon: Code
},
rich: {
- label: translate("auto.components.editor.EditorViewToggle.aff15f94f5", "Rich Editor"),
+ label: translate('auto.components.editor.EditorViewToggle.aff15f94f5', 'Rich Editor'),
icon: Pencil
},
preview: {
- label: translate("auto.components.editor.EditorViewToggle.0d193dc03c", "Preview"),
+ label: translate('auto.components.editor.EditorViewToggle.0d193dc03c', 'Preview'),
icon: Eye
},
edit: {
- label: translate("auto.components.editor.EditorViewToggle.ac3bb87913", "Edit"),
+ label: translate('auto.components.editor.EditorViewToggle.ac3bb87913', 'Edit'),
icon: FileText
},
changes: {
- label: translate("auto.components.editor.EditorViewToggle.4837f3f578", "Changes"),
+ label: translate('auto.components.editor.EditorViewToggle.4837f3f578', 'Changes'),
icon: GitCompareArrows,
// Why: "Changes" collides with the Source Control sidebar's "Branch
// Changes" section, which diffs against the base ref. This toggle shows
// uncommitted changes (working tree vs HEAD), so disambiguate in the
// hover title without repeating the button label.
- title: translate("auto.components.editor.EditorViewToggle.167f45888c", "Uncommitted changes")
+ title: translate('auto.components.editor.EditorViewToggle.167f45888c', 'Uncommitted changes')
}
}
@@ -58,14 +58,14 @@ const DEFAULT_VIEW_MODE_METADATA: Record =
// which we don't offer, so callers can override the per-mode presentation.
export const CSV_VIEW_MODE_METADATA: Partial> = {
rich: {
- label: translate("auto.components.editor.EditorViewToggle.e408aa9cd5", "Table"),
+ label: translate('auto.components.editor.EditorViewToggle.e408aa9cd5', 'Table'),
icon: TableIcon
}
}
export const NOTEBOOK_VIEW_MODE_METADATA: Partial> = {
rich: {
- label: translate("auto.components.editor.EditorViewToggle.b3410cd5e0", "Notebook"),
+ label: translate('auto.components.editor.EditorViewToggle.b3410cd5e0', 'Notebook'),
icon: NotebookText
}
}
diff --git a/src/renderer/src/components/editor/ImageDiffViewer.tsx b/src/renderer/src/components/editor/ImageDiffViewer.tsx
index 9a6634c9a79..2e021433967 100644
--- a/src/renderer/src/components/editor/ImageDiffViewer.tsx
+++ b/src/renderer/src/components/editor/ImageDiffViewer.tsx
@@ -42,7 +42,8 @@ function ImageDiffPane({
isIntrinsicLayout ? 'min-h-32' : 'flex-1'
)}
>
- {translate("auto.components.editor.ImageDiffViewer.fb0ae4f3c0", "No preview")}
+ {translate('auto.components.editor.ImageDiffViewer.fb0ae4f3c0', 'No preview')}
+
)
}
@@ -94,14 +95,14 @@ export default function ImageDiffViewer({
style={gridRowStyle}
>
- {translate("auto.components.editor.ImageViewer.d9d2944855", "Failed to load file preview")}
+
+ {translate(
+ 'auto.components.editor.ImageViewer.d9d2944855',
+ 'Failed to load file preview'
+ )}
+
{filename}
)
@@ -233,7 +238,8 @@ export default function ImageViewer({
isIntrinsicLayout ? 'min-h-64' : 'h-full'
)}
>
- {translate("auto.components.editor.ImageViewer.3ef9551ba2", "Loading preview...")}
+ {translate('auto.components.editor.ImageViewer.3ef9551ba2', 'Loading preview...')}
+
)
}
@@ -249,7 +255,7 @@ export default function ImageViewer({
: 'flex-1 overflow-auto scrollbar-editor'
)}
onClick={openPopup}
- title={translate("auto.components.editor.ImageViewer.77bfc9b35a", "Open image in popup")}
+ title={translate('auto.components.editor.ImageViewer.77bfc9b35a', 'Open image in popup')}
>
currentZoom / IMAGE_VIEWER_ZOOM_STEP)
}
disabled={inlineZoom <= MIN_IMAGE_VIEWER_ZOOM}
- title={translate("auto.components.editor.ImageViewer.be27304574", "Zoom out")}
+ title={translate('auto.components.editor.ImageViewer.be27304574', 'Zoom out')}
>
@@ -308,7 +314,7 @@ export default function ImageViewer({
className="rounded p-1 hover:bg-accent hover:text-foreground disabled:opacity-50"
onClick={() => applyInlineZoomChange(() => 1)}
disabled={inlineZoom === 1}
- title={translate("auto.components.editor.ImageViewer.6c89c73d9f", "Reset zoom")}
+ title={translate('auto.components.editor.ImageViewer.6c89c73d9f', 'Reset zoom')}
>
@@ -319,7 +325,7 @@ export default function ImageViewer({
applyInlineZoomChange((currentZoom) => currentZoom * IMAGE_VIEWER_ZOOM_STEP)
}
disabled={inlineZoom >= MAX_IMAGE_VIEWER_ZOOM}
- title={translate("auto.components.editor.ImageViewer.3c9217f5a6", "Zoom in")}
+ title={translate('auto.components.editor.ImageViewer.3c9217f5a6', 'Zoom in')}
>
diff --git a/src/renderer/src/components/editor/ImageViewerPopup.tsx b/src/renderer/src/components/editor/ImageViewerPopup.tsx
index 93107f1ac47..c5d4918cd4b 100644
--- a/src/renderer/src/components/editor/ImageViewerPopup.tsx
+++ b/src/renderer/src/components/editor/ImageViewerPopup.tsx
@@ -33,7 +33,12 @@ export default function ImageViewerPopup({
className="top-1/2 left-1/2 flex h-[80vh] w-[70vw] max-w-[70vw] -translate-x-1/2 -translate-y-1/2 flex-col gap-0 overflow-hidden border border-border/60 bg-background p-0 shadow-2xl sm:max-w-[70vw]"
>
{filename}
-
{translate("auto.components.editor.ImageViewerPopup.9e27b2ecaf", "Full-size image preview")}
+
+ {translate(
+ 'auto.components.editor.ImageViewerPopup.9e27b2ecaf',
+ 'Full-size image preview'
+ )}
+
{filename}
onOpenChange(false)}
>
- {translate("auto.components.editor.ImageViewerPopup.535f4e2b56", "Close")}
+ {translate('auto.components.editor.ImageViewerPopup.535f4e2b56', 'Close')}
-
{translate("auto.components.editor.ImageViewerPopup.0ef78475e7", "Press Esc to close")}
+
+ {translate('auto.components.editor.ImageViewerPopup.0ef78475e7', 'Press Esc to close')}
+
{zoomPercent}%
diff --git a/src/renderer/src/components/editor/IpynbViewer.tsx b/src/renderer/src/components/editor/IpynbViewer.tsx
index cbb4b8019d2..31abbc557e7 100644
--- a/src/renderer/src/components/editor/IpynbViewer.tsx
+++ b/src/renderer/src/components/editor/IpynbViewer.tsx
@@ -181,29 +181,56 @@ function NotebookCellHeader({
onChange={(event) => onKindChange(event.target.value as IpynbCellKind)}
className="h-7 rounded-md border border-input bg-background px-2 text-xs text-foreground"
>
-
{translate("auto.components.editor.IpynbViewer.7005960d73", "Code")}
-
{translate("auto.components.editor.IpynbViewer.1833dbbc43", "Markdown")}
-
{translate("auto.components.editor.IpynbViewer.3e4cbf15ea", "Raw")}
+
+ {translate('auto.components.editor.IpynbViewer.7005960d73', 'Code')}
+
+
+ {translate('auto.components.editor.IpynbViewer.1833dbbc43', 'Markdown')}
+
+
+ {translate('auto.components.editor.IpynbViewer.3e4cbf15ea', 'Raw')}
+
- {cell.kind === "code" ? (
-
+ {cell.kind === 'code' ? (
+
{running ? : }
) : null}
-
+
-
+
- onInsertAbove('code')}>
+ onInsertAbove('code')}
+ >
- onInsertBelow('code')}>
+ onInsertBelow('code')}
+ >
onInsertAbove('markdown')}
>
@@ -212,7 +239,10 @@ function NotebookCellHeader({
onInsertBelow('markdown')}
>
@@ -220,7 +250,10 @@ function NotebookCellHeader({
-
+
#{index + 1}
@@ -438,7 +471,7 @@ function OutputItem({ item }: { item: IpynbOutputItem }): React.JSX.Element | nu
})
return (
@@ -837,27 +875,35 @@ export default function IpynbViewer({
>
{filePath.split(/[/\\]/).pop()}
-
{notebook.cells.length} {translate("auto.components.editor.IpynbViewer.07e7d96612", "cells")}
+
+ {notebook.cells.length}{' '}
+ {translate('auto.components.editor.IpynbViewer.07e7d96612', 'cells')}
+
{notebook.language}
{notebook.kernelName ?
{notebook.kernelName} : null}
{runError ?
{runError} : null}
void saveNotebook()}
>
- {translate("auto.components.editor.IpynbViewer.329764e9fc", "BETA")}
- {translate("auto.components.editor.IpynbViewer.8c3b21369a", "nbformat")}{notebook.nbformat}
+ {translate('auto.components.editor.IpynbViewer.329764e9fc', 'BETA')}
+
+
+ {translate('auto.components.editor.IpynbViewer.8c3b21369a', 'nbformat')}
+ {notebook.nbformat}
+
{notebook.cells.length === 0 ? (
- {translate("auto.components.editor.IpynbViewer.d6f37a640b", "Empty notebook")}
+ {translate('auto.components.editor.IpynbViewer.d6f37a640b', 'Empty notebook')}
+
) : (
notebook.cells.map((cell, index) => {
const cellKey = getCellKey(cell, index)
@@ -883,7 +929,7 @@ export default function IpynbViewer({
onMoveDown={() => moveCell(index, 1)}
onDelete={() => deleteCell(index)}
/>
- {cell.kind === "markdown" ? (
+ {cell.kind === 'markdown' ? (
- ) : cell.kind === "code" ? (
+ ) : cell.kind === 'code' ? (
- {translate("auto.components.editor.IpynbViewer.9e06ae5d36", "Run Notebook Code?")}
+
+ {translate('auto.components.editor.IpynbViewer.9e06ae5d36', 'Run Notebook Code?')}
+
- {translate("auto.components.editor.IpynbViewer.10ed04a685", "Notebook cells execute local Python on this machine from the notebook folder. Only run cells from files you trust.")}
+ {translate(
+ 'auto.components.editor.IpynbViewer.10ed04a685',
+ 'Notebook cells execute local Python on this machine from the notebook folder. Only run cells from files you trust.'
+ )}
+
- {translate("auto.components.editor.IpynbViewer.7f0d7077c6", "Cancel")}
+ {translate('auto.components.editor.IpynbViewer.7f0d7077c6', 'Cancel')}
+
- {translate("auto.components.editor.IpynbViewer.859bf9fc21", "Run cell")}
+ {translate('auto.components.editor.IpynbViewer.859bf9fc21', 'Run cell')}
+
diff --git a/src/renderer/src/components/editor/MarkdownPreview.tsx b/src/renderer/src/components/editor/MarkdownPreview.tsx
index 92881542d4d..ea9d90350a6 100644
--- a/src/renderer/src/components/editor/MarkdownPreview.tsx
+++ b/src/renderer/src/components/editor/MarkdownPreview.tsx
@@ -595,7 +595,7 @@ export default function MarkdownPreview({
() => [
{
id: 'all',
- label: translate("auto.components.editor.MarkdownPreview.ddf087d12e", "All unsent notes"),
+ label: translate('auto.components.editor.MarkdownPreview.ddf087d12e', 'All unsent notes'),
notes: unsentMarkdownReviewNotes,
prompt: unsentMarkdownReviewPrompt
}
@@ -1035,8 +1035,8 @@ export default function MarkdownPreview({
{
event.preventDefault()
event.stopPropagation()
@@ -1081,10 +1081,26 @@ export default function MarkdownPreview({
type="button"
className="orca-diff-comment-pill-btn"
title={
- copiedReviewNoteId === comment.id ? translate("auto.components.editor.MarkdownPreview.94b520a96a", "Copied note") : translate("auto.components.editor.MarkdownPreview.f961e94057", "Copy note for agent")
+ copiedReviewNoteId === comment.id
+ ? translate(
+ 'auto.components.editor.MarkdownPreview.94b520a96a',
+ 'Copied note'
+ )
+ : translate(
+ 'auto.components.editor.MarkdownPreview.f961e94057',
+ 'Copy note for agent'
+ )
}
aria-label={
- copiedReviewNoteId === comment.id ? translate("auto.components.editor.MarkdownPreview.94b520a96a", "Copied note") : translate("auto.components.editor.MarkdownPreview.f961e94057", "Copy note for agent")
+ copiedReviewNoteId === comment.id
+ ? translate(
+ 'auto.components.editor.MarkdownPreview.94b520a96a',
+ 'Copied note'
+ )
+ : translate(
+ 'auto.components.editor.MarkdownPreview.f961e94057',
+ 'Copy note for agent'
+ )
}
onClick={(event) => {
event.preventDefault()
@@ -1264,7 +1280,11 @@ export default function MarkdownPreview({
void window.api.shell.pathExists(classified.absolutePath).then((exists) => {
if (!exists) {
toast.error(
- translate("auto.components.editor.MarkdownPreview.6c043947ae", "File not found: {{value0}}", { value0: classified.relativePath ?? classified.absolutePath })
+ translate(
+ 'auto.components.editor.MarkdownPreview.6c043947ae',
+ 'File not found: {{value0}}',
+ { value0: classified.relativePath ?? classified.absolutePath }
+ )
)
return
}
@@ -1356,11 +1376,23 @@ export default function MarkdownPreview({
absolutePath
)
if (stats.isDirectory) {
- toast.error(translate("auto.components.editor.MarkdownPreview.759463a221", "Cannot open directory: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate(
+ 'auto.components.editor.MarkdownPreview.759463a221',
+ 'Cannot open directory: {{value0}}',
+ { value0: relativePath }
+ )
+ )
return
}
} catch {
- toast.error(translate("auto.components.editor.MarkdownPreview.6c043947ae", "File not found: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate(
+ 'auto.components.editor.MarkdownPreview.6c043947ae',
+ 'File not found: {{value0}}',
+ { value0: relativePath }
+ )
+ )
return
}
@@ -1663,14 +1695,20 @@ export default function MarkdownPreview({
rootRef.current?.focus()
}
}}
- placeholder={translate("auto.components.editor.MarkdownPreview.517aea303b", "Find in preview")}
+ placeholder={translate(
+ 'auto.components.editor.MarkdownPreview.517aea303b',
+ 'Find in preview'
+ )}
className="markdown-preview-search-input h-7 !border-0 bg-transparent px-2 shadow-none focus-visible:!border-0 focus-visible:ring-0"
- aria-label={translate("auto.components.editor.MarkdownPreview.ec77985138", "Find in markdown preview")}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.ec77985138',
+ 'Find in markdown preview'
+ )}
/>
{query && matchCount === 0
- ? translate("auto.components.editor.MarkdownPreview.c5dc92cfe3", "No results")
+ ? translate('auto.components.editor.MarkdownPreview.c5dc92cfe3', 'No results')
: `${matchCount === 0 ? 0 : activeMatchIndex + 1}/${matchCount}`}
moveToMatch(-1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.MarkdownPreview.1febd97f5c", "Previous match")}
- aria-label={translate("auto.components.editor.MarkdownPreview.1febd97f5c", "Previous match")}
+ title={translate(
+ 'auto.components.editor.MarkdownPreview.1febd97f5c',
+ 'Previous match'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.1febd97f5c',
+ 'Previous match'
+ )}
className="markdown-preview-search-button"
>
@@ -1691,8 +1735,11 @@ export default function MarkdownPreview({
size="icon-xs"
onClick={() => moveToMatch(1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.MarkdownPreview.b42c41bd0d", "Next match")}
- aria-label={translate("auto.components.editor.MarkdownPreview.b42c41bd0d", "Next match")}
+ title={translate('auto.components.editor.MarkdownPreview.b42c41bd0d', 'Next match')}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.b42c41bd0d',
+ 'Next match'
+ )}
className="markdown-preview-search-button"
>
@@ -1703,8 +1750,11 @@ export default function MarkdownPreview({
variant="ghost"
size="icon-xs"
onClick={closeSearch}
- title={translate("auto.components.editor.MarkdownPreview.12052c639c", "Close search")}
- aria-label={translate("auto.components.editor.MarkdownPreview.12052c639c", "Close search")}
+ title={translate('auto.components.editor.MarkdownPreview.12052c639c', 'Close search')}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.12052c639c',
+ 'Close search'
+ )}
className="markdown-preview-search-button"
>
@@ -1723,11 +1773,19 @@ export default function MarkdownPreview({
}
}}
disabled={markdownReviewNotes.length === 0}
- title={translate("auto.components.editor.MarkdownPreview.0f9969a159", "Jump to first review note")}
- aria-label={translate("auto.components.editor.MarkdownPreview.0f9969a159", "Jump to first review note")}
+ title={translate(
+ 'auto.components.editor.MarkdownPreview.0f9969a159',
+ 'Jump to first review note'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.0f9969a159',
+ 'Jump to first review note'
+ )}
>
- {translate("auto.components.editor.MarkdownPreview.322afab6ff", "Review notes")}
+
+ {translate('auto.components.editor.MarkdownPreview.322afab6ff', 'Review notes')}
+
{markdownReviewNotes.length}
void handleCopyMarkdownReviewNotes()}
disabled={markdownReviewNotes.length === 0}
- title={translate("auto.components.editor.MarkdownPreview.bb629de58a", "Copy notes for agent")}
- aria-label={translate("auto.components.editor.MarkdownPreview.bb629de58a", "Copy notes for agent")}
+ title={translate(
+ 'auto.components.editor.MarkdownPreview.bb629de58a',
+ 'Copy notes for agent'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.bb629de58a',
+ 'Copy notes for agent'
+ )}
>
{reviewNotesCopied ? : }
@@ -1759,7 +1823,8 @@ export default function MarkdownPreview({
{frontMatter && frontmatterVisible ? (
- {translate("auto.components.editor.MarkdownPreview.2b2b31382c", "Front Matter")}
+ {translate('auto.components.editor.MarkdownPreview.2b2b31382c', 'Front Matter')}
+
{frontMatterInner}
@@ -1820,7 +1885,7 @@ function MarkdownSingleNoteSendMenu({
scopes={[
{
id: 'note',
- label: translate("auto.components.editor.MarkdownPreview.f37b98999e", "This note"),
+ label: translate('auto.components.editor.MarkdownPreview.f37b98999e', 'This note'),
notes: note.sentAt ? [] : [note],
prompt: formatMarkdownReviewNotes([note], content)
}
@@ -1876,11 +1941,16 @@ function MarkdownAnnotationComposer({
return (
event.stopPropagation()}>
-
{translate("auto.components.editor.MarkdownPreview.b1bfc04034", "Selected text")}
+
+ {translate('auto.components.editor.MarkdownPreview.b1bfc04034', 'Selected text')}
+
{
setBody(event.target.value)
@@ -1903,9 +1973,12 @@ function MarkdownAnnotationComposer({
/>
- {translate("auto.components.editor.MarkdownPreview.e4683f70c4", "Cancel")}
+ {translate('auto.components.editor.MarkdownPreview.e4683f70c4', 'Cancel')}
+
void submit()} disabled={submitting || !trimmed}>
- {submitting ? translate("auto.components.editor.MarkdownPreview.d652c87c91", "Saving…") : translate("auto.components.editor.MarkdownPreview.13f94d760c", "Add note")}
+ {submitting
+ ? translate('auto.components.editor.MarkdownPreview.d652c87c91', 'Saving…')
+ : translate('auto.components.editor.MarkdownPreview.13f94d760c', 'Add note')}
{!submitting && }
diff --git a/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx b/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx
index 445d5732536..678877de8bb 100644
--- a/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx
+++ b/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx
@@ -52,7 +52,19 @@ function MarkdownTocRow({
onToggleCollapsed(item.id)}
>
@@ -108,12 +120,30 @@ export function MarkdownTableOfContentsPanel({
}
return (
-
+
-
{translate("auto.components.editor.MarkdownTableOfContentsPanel.06357eea60", "Table of Contents")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.06357eea60',
+ 'Table of Contents'
+ )}
+
-
+
{TOC_LEVELS.map((level) => (
collapseToLevel(level)}
>
H{level}
@@ -135,8 +185,14 @@ export function MarkdownTableOfContentsPanel({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097", "Close table of contents")}
- title={translate("auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097", "Close table of contents")}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097',
+ 'Close table of contents'
+ )}
+ title={translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097',
+ 'Close table of contents'
+ )}
onClick={onClose}
>
@@ -156,7 +212,12 @@ export function MarkdownTableOfContentsPanel({
/>
))
) : (
- {translate("auto.components.editor.MarkdownTableOfContentsPanel.de3928b6e4", "No headings")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.de3928b6e4',
+ 'No headings'
+ )}
+
)}
diff --git a/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx b/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx
index 9387ffecd77..794f42d1861 100644
--- a/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx
+++ b/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx
@@ -53,13 +53,26 @@ export function MarkdownTemplatePicker(): JSX.Element {
resolveRequest({ type: 'cancel' })
}
}}
- title={translate("auto.components.editor.MarkdownTemplatePicker.1829437fce", "New Markdown")}
- description={translate("auto.components.editor.MarkdownTemplatePicker.7b458e0b7f", "Choose a Markdown template.")}
+ title={translate('auto.components.editor.MarkdownTemplatePicker.1829437fce', 'New Markdown')}
+ description={translate(
+ 'auto.components.editor.MarkdownTemplatePicker.7b458e0b7f',
+ 'Choose a Markdown template.'
+ )}
contentClassName="w-[520px]"
>
-
+
- {translate("auto.components.editor.MarkdownTemplatePicker.df667919ca", "No matching templates.")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTemplatePicker.df667919ca',
+ 'No matching templates.'
+ )}
+
- {translate("auto.components.editor.MarkdownTemplatePicker.6e2e6c04ad", "Blank Markdown")}
- {translate("auto.components.editor.MarkdownTemplatePicker.22cd94426f", "untitled.md")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTemplatePicker.6e2e6c04ad',
+ 'Blank Markdown'
+ )}
+
+
+ {translate(
+ 'auto.components.editor.MarkdownTemplatePicker.22cd94426f',
+ 'untitled.md'
+ )}
+
diff --git a/src/renderer/src/components/editor/MermaidBlock.tsx b/src/renderer/src/components/editor/MermaidBlock.tsx
index b798751b204..c85636e5399 100644
--- a/src/renderer/src/components/editor/MermaidBlock.tsx
+++ b/src/renderer/src/components/editor/MermaidBlock.tsx
@@ -84,7 +84,10 @@ export default function MermaidBlock({
if (error) {
return (
-
{translate("auto.components.editor.MermaidBlock.dcc132e691", "Diagram error:")}{error}
+
+ {translate('auto.components.editor.MermaidBlock.dcc132e691', 'Diagram error:')}
+ {error}
+
{content}
diff --git a/src/renderer/src/components/editor/MonacoEditor.tsx b/src/renderer/src/components/editor/MonacoEditor.tsx
index c3426cb4ca2..f3eed459f2c 100644
--- a/src/renderer/src/components/editor/MonacoEditor.tsx
+++ b/src/renderer/src/components/editor/MonacoEditor.tsx
@@ -382,7 +382,7 @@ export default function MonacoEditor({
)
const searchInFilesAction = editorInstance.addAction({
id: 'orca.searchInFiles',
- label: translate("auto.components.editor.MonacoEditor.fd68ae03b3", "Search in Files"),
+ label: translate('auto.components.editor.MonacoEditor.fd68ae03b3', 'Search in Files'),
contextMenuGroupId: 'navigation',
contextMenuOrder: 2,
run: () => {
@@ -751,8 +751,14 @@ export default function MonacoEditor({
top: Math.max(4, selectionAnnotationTarget.top - 22),
left: selectionAnnotationTarget.left ?? 4
}}
- title={translate("auto.components.editor.MonacoEditor.68cb83f4a7", "Add note on selected text")}
- aria-label={translate("auto.components.editor.MonacoEditor.68cb83f4a7", "Add note on selected text")}
+ title={translate(
+ 'auto.components.editor.MonacoEditor.68cb83f4a7',
+ 'Add note on selected text'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MonacoEditor.68cb83f4a7',
+ 'Add note on selected text'
+ )}
onMouseDown={(event) => {
event.preventDefault()
event.stopPropagation()
diff --git a/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx b/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx
index 4c184e41e89..81fc40367de 100644
--- a/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx
+++ b/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx
@@ -45,14 +45,22 @@ export function MonacoGutterContextMenu({
onSelect={() => window.api.ui.writeClipboardText(formatPathLineReference(filePath, line))}
>
- {translate("auto.components.editor.MonacoGutterContextMenu.4eaa991bde", "Copy Path to Line")}
+ {translate(
+ 'auto.components.editor.MonacoGutterContextMenu.4eaa991bde',
+ 'Copy Path to Line'
+ )}
+
window.api.ui.writeClipboardText(formatPathLineReference(relativePath, line))
}
>
- {translate("auto.components.editor.MonacoGutterContextMenu.2e0b1cdc05", "Copy Rel. Path to Line")}
+ {translate(
+ 'auto.components.editor.MonacoGutterContextMenu.2e0b1cdc05',
+ 'Copy Rel. Path to Line'
+ )}
+
{
const state = useAppStore.getState()
@@ -80,7 +88,11 @@ export function MonacoGutterContextMenu({
}}
>
- {translate("auto.components.editor.MonacoGutterContextMenu.7b57b1b468", "Copy Remote URL")}
+ {translate(
+ 'auto.components.editor.MonacoGutterContextMenu.7b57b1b468',
+ 'Copy Remote URL'
+ )}
+
)
diff --git a/src/renderer/src/components/editor/NotesSendMenu.tsx b/src/renderer/src/components/editor/NotesSendMenu.tsx
index 6c10280632c..823a001dd66 100644
--- a/src/renderer/src/components/editor/NotesSendMenu.tsx
+++ b/src/renderer/src/components/editor/NotesSendMenu.tsx
@@ -151,7 +151,15 @@ export function NotesSendMenu
({
)}
disabled={!hasDeliverableNotes}
title={hasDeliverableNotes ? ENABLED_SEND_TOOLTIP : disabledTooltip}
- aria-label={triggerLabel ? translate("auto.components.editor.NotesSendMenu.433928cd9f", "Send {{value0}} to an agent", { value0: triggerLabel }) : ENABLED_SEND_TOOLTIP}
+ aria-label={
+ triggerLabel
+ ? translate(
+ 'auto.components.editor.NotesSendMenu.433928cd9f',
+ 'Send {{value0}} to an agent',
+ { value0: triggerLabel }
+ )
+ : ENABLED_SEND_TOOLTIP
+ }
onMouseDown={(event) => event.stopPropagation()}
onClick={(event) => event.stopPropagation()}
>
@@ -184,7 +192,9 @@ export function NotesSendMenu({
>
{scopes.length > 1 ? (
<>
- {translate("auto.components.editor.NotesSendMenu.44dc5e60a6", "Send notes")}
+
+ {translate('auto.components.editor.NotesSendMenu.44dc5e60a6', 'Send notes')}
+
{scopes.map((scope) => (
setQuery(e.target.value)}
- placeholder={translate("auto.components.editor.PdfFind.2fc3ba0ea8", "Find in page...")}
+ placeholder={translate('auto.components.editor.PdfFind.2fc3ba0ea8', 'Find in page...')}
className="min-w-0 flex-1 border-none bg-transparent text-sm text-white outline-none placeholder:text-zinc-500"
/>
{query ? (
- {totalMatches > 0 ? translate("auto.components.editor.PdfFind.db56fcd6d2", "{{value0}} of {{value1}}", { value0: activeMatch, value1: totalMatches }) : translate("auto.components.editor.PdfFind.d080ab37d6", "No matches")}
+ {totalMatches > 0
+ ? translate('auto.components.editor.PdfFind.db56fcd6d2', '{{value0}} of {{value1}}', {
+ value0: activeMatch,
+ value1: totalMatches
+ })
+ : translate('auto.components.editor.PdfFind.d080ab37d6', 'No matches')}
) : null}
@@ -140,7 +145,7 @@ export default function PdfFind({
size="icon-xs"
onClick={findPrevious}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.editor.PdfFind.30de726ad0", "Previous match")}
+ title={translate('auto.components.editor.PdfFind.30de726ad0', 'Previous match')}
>
@@ -150,7 +155,7 @@ export default function PdfFind({
size="icon-xs"
onClick={findNext}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.editor.PdfFind.eeba2547a1", "Next match")}
+ title={translate('auto.components.editor.PdfFind.eeba2547a1', 'Next match')}
>
@@ -161,7 +166,7 @@ export default function PdfFind({
size="icon-xs"
onClick={onClose}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.editor.PdfFind.cd65b1d6b0", "Close")}
+ title={translate('auto.components.editor.PdfFind.cd65b1d6b0', 'Close')}
>
diff --git a/src/renderer/src/components/editor/PdfViewer.tsx b/src/renderer/src/components/editor/PdfViewer.tsx
index c5127775338..60495f7f837 100644
--- a/src/renderer/src/components/editor/PdfViewer.tsx
+++ b/src/renderer/src/components/editor/PdfViewer.tsx
@@ -216,7 +216,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
{filename}
- {translate("auto.components.editor.PdfViewer.3e98d500d2", "PDF preview")}
+ {translate('auto.components.editor.PdfViewer.3e98d500d2', 'PDF preview')}
)
@@ -252,7 +252,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
className="rounded p-1 hover:bg-accent hover:text-foreground disabled:opacity-50"
onClick={zoomOut}
disabled={scale <= MIN_SCALE}
- title={translate("auto.components.editor.PdfViewer.fa5d096b00", "Zoom out")}
+ title={translate('auto.components.editor.PdfViewer.fa5d096b00', 'Zoom out')}
>
@@ -260,7 +260,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
type="button"
className="rounded p-1 hover:bg-accent hover:text-foreground"
onClick={zoomReset}
- title={translate("auto.components.editor.PdfViewer.c0119616d6", "Fit to width")}
+ title={translate('auto.components.editor.PdfViewer.c0119616d6', 'Fit to width')}
>
@@ -269,7 +269,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
className="rounded p-1 hover:bg-accent hover:text-foreground disabled:opacity-50"
onClick={zoomIn}
disabled={scale >= MAX_SCALE}
- title={translate("auto.components.editor.PdfViewer.2b6eb1ccd6", "Zoom in")}
+ title={translate('auto.components.editor.PdfViewer.2b6eb1ccd6', 'Zoom in')}
>
@@ -279,14 +279,18 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
type="button"
className="rounded p-1 hover:bg-accent hover:text-foreground"
onClick={() => setFindOpen(true)}
- title={translate("auto.components.editor.PdfViewer.069ff59932", "Find in PDF ({{value0}})", { value0: findShortcutLabel })}
+ title={translate(
+ 'auto.components.editor.PdfViewer.069ff59932',
+ 'Find in PDF ({{value0}})',
+ { value0: findShortcutLabel }
+ )}
>
{filename}
-
{translate("auto.components.editor.PdfViewer.3e98d500d2", "PDF preview")}
+
{translate('auto.components.editor.PdfViewer.3e98d500d2', 'PDF preview')}
)
diff --git a/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx b/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx
index 3457908b326..572746cda2f 100644
--- a/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx
+++ b/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx
@@ -38,19 +38,34 @@ export function ReviewNotesSendMenuContent({
if (!hasPrompt || !canSendToActiveAgent) {
return
}
- const pending = toast.loading(translate("auto.components.editor.ReviewNotesSendMenuContent.50f7e753ea", "Sending notes to active agent..."))
+ const pending = toast.loading(
+ translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.50f7e753ea',
+ 'Sending notes to active agent...'
+ )
+ )
void sendNotesToActiveAgentSession({ worktreeId, prompt })
.then((result) => {
if (result.status === 'sent') {
onPromptDelivered?.()
- toast.success(translate("auto.components.editor.ReviewNotesSendMenuContent.bb9c69a0c9", "Notes sent to active agent."))
+ toast.success(
+ translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.bb9c69a0c9',
+ 'Notes sent to active agent.'
+ )
+ )
return
}
toast.message(activeAgentNotesSendFailureMessage(result.status))
})
.catch((error) => {
console.error('Failed to send notes to active agent:', error)
- toast.error(translate("auto.components.editor.ReviewNotesSendMenuContent.f5096c6e4e", "Could not send notes to the active agent."))
+ toast.error(
+ translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.f5096c6e4e',
+ 'Could not send notes to the active agent.'
+ )
+ )
})
.finally(() => {
toast.dismiss(pending)
@@ -59,16 +74,24 @@ export function ReviewNotesSendMenuContent({
return (
<>
- {translate("auto.components.editor.ReviewNotesSendMenuContent.03378aea75", "Send notes to")}
+
+ {translate('auto.components.editor.ReviewNotesSendMenuContent.03378aea75', 'Send notes to')}
+
- {translate("auto.components.editor.ReviewNotesSendMenuContent.e84705f223", "Active agent session")}
+ {translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.e84705f223',
+ 'Active agent session'
+ )}
+
- {translate("auto.components.editor.ReviewNotesSendMenuContent.a49800405b", "New agent")}
+
+ {translate('auto.components.editor.ReviewNotesSendMenuContent.a49800405b', 'New agent')}
+
{
event.preventDefault()
event.stopPropagation()
@@ -56,7 +62,10 @@ export function RichMarkdownAnnotationOverlay({
}
top={popover.top}
left={popover.left}
- title={translate("auto.components.editor.RichMarkdownAnnotationOverlay.069b5677b8", "Selected text")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownAnnotationOverlay.069b5677b8',
+ 'Selected text'
+ )}
onCancel={onCancelPopover}
onSubmit={onSubmit}
/>
diff --git a/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx b/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx
index 77652225b4f..8a6aad7db50 100644
--- a/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx
@@ -12,31 +12,103 @@ import { translate } from '@/i18n/i18n'
* this list is just for quick picking in the UI.
*/
const LANGUAGES = [
- { value: '', label: translate("auto.components.editor.RichMarkdownCodeBlock.13822cdfda", "Plain text") },
- { value: 'bash', label: translate("auto.components.editor.RichMarkdownCodeBlock.4227cf50fe", "Bash") },
+ {
+ value: '',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.13822cdfda', 'Plain text')
+ },
+ {
+ value: 'bash',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.4227cf50fe', 'Bash')
+ },
{ value: 'c', label: 'C' },
- { value: 'cpp', label: translate("auto.components.editor.RichMarkdownCodeBlock.4daed43ae3", "C++") },
- { value: 'css', label: translate("auto.components.editor.RichMarkdownCodeBlock.026653f21f", "CSS") },
- { value: 'diff', label: translate("auto.components.editor.RichMarkdownCodeBlock.bf6ee5caaa", "Diff") },
- { value: 'go', label: translate("auto.components.editor.RichMarkdownCodeBlock.edfcc64182", "Go") },
- { value: 'graphql', label: translate("auto.components.editor.RichMarkdownCodeBlock.706fd85738", "GraphQL") },
- { value: 'html', label: translate("auto.components.editor.RichMarkdownCodeBlock.8c4a3fa02d", "HTML") },
- { value: 'java', label: translate("auto.components.editor.RichMarkdownCodeBlock.36536ad539", "Java") },
- { value: 'javascript', label: translate("auto.components.editor.RichMarkdownCodeBlock.a209c57063", "JavaScript") },
- { value: 'json', label: translate("auto.components.editor.RichMarkdownCodeBlock.78eba32de4", "JSON") },
- { value: 'kotlin', label: translate("auto.components.editor.RichMarkdownCodeBlock.bcb236e2d8", "Kotlin") },
- { value: 'markdown', label: translate("auto.components.editor.RichMarkdownCodeBlock.983b9576b4", "Markdown") },
- { value: 'mermaid', label: translate("auto.components.editor.RichMarkdownCodeBlock.89d6cc14fb", "Mermaid") },
- { value: 'python', label: translate("auto.components.editor.RichMarkdownCodeBlock.2391f9cda9", "Python") },
- { value: 'ruby', label: translate("auto.components.editor.RichMarkdownCodeBlock.96182a2f64", "Ruby") },
- { value: 'rust', label: translate("auto.components.editor.RichMarkdownCodeBlock.e72e6b03f4", "Rust") },
- { value: 'scss', label: translate("auto.components.editor.RichMarkdownCodeBlock.5af8251002", "SCSS") },
- { value: 'shell', label: translate("auto.components.editor.RichMarkdownCodeBlock.d01f55be57", "Shell") },
- { value: 'sql', label: translate("auto.components.editor.RichMarkdownCodeBlock.3009f722b9", "SQL") },
- { value: 'swift', label: translate("auto.components.editor.RichMarkdownCodeBlock.9e384d48dc", "Swift") },
- { value: 'typescript', label: translate("auto.components.editor.RichMarkdownCodeBlock.88d777bc07", "TypeScript") },
- { value: 'xml', label: translate("auto.components.editor.RichMarkdownCodeBlock.5ef5605cb7", "XML") },
- { value: 'yaml', label: translate("auto.components.editor.RichMarkdownCodeBlock.74eab1d9b2", "YAML") }
+ {
+ value: 'cpp',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.4daed43ae3', 'C++')
+ },
+ {
+ value: 'css',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.026653f21f', 'CSS')
+ },
+ {
+ value: 'diff',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.bf6ee5caaa', 'Diff')
+ },
+ {
+ value: 'go',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.edfcc64182', 'Go')
+ },
+ {
+ value: 'graphql',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.706fd85738', 'GraphQL')
+ },
+ {
+ value: 'html',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.8c4a3fa02d', 'HTML')
+ },
+ {
+ value: 'java',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.36536ad539', 'Java')
+ },
+ {
+ value: 'javascript',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.a209c57063', 'JavaScript')
+ },
+ {
+ value: 'json',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.78eba32de4', 'JSON')
+ },
+ {
+ value: 'kotlin',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.bcb236e2d8', 'Kotlin')
+ },
+ {
+ value: 'markdown',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.983b9576b4', 'Markdown')
+ },
+ {
+ value: 'mermaid',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.89d6cc14fb', 'Mermaid')
+ },
+ {
+ value: 'python',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.2391f9cda9', 'Python')
+ },
+ {
+ value: 'ruby',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.96182a2f64', 'Ruby')
+ },
+ {
+ value: 'rust',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.e72e6b03f4', 'Rust')
+ },
+ {
+ value: 'scss',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.5af8251002', 'SCSS')
+ },
+ {
+ value: 'shell',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.d01f55be57', 'Shell')
+ },
+ {
+ value: 'sql',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.3009f722b9', 'SQL')
+ },
+ {
+ value: 'swift',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.9e384d48dc', 'Swift')
+ },
+ {
+ value: 'typescript',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.88d777bc07', 'TypeScript')
+ },
+ {
+ value: 'xml',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.5ef5605cb7', 'XML')
+ },
+ {
+ value: 'yaml',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.74eab1d9b2', 'YAML')
+ }
]
export function RichMarkdownCodeBlock({
@@ -128,13 +200,18 @@ export function RichMarkdownCodeBlock({
className="code-block-copy-btn"
contentEditable={false}
onClick={handleCopy}
- aria-label={translate("auto.components.editor.RichMarkdownCodeBlock.c72beafc0f", "Copy code")}
- title={translate("auto.components.editor.RichMarkdownCodeBlock.c72beafc0f", "Copy code")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownCodeBlock.c72beafc0f',
+ 'Copy code'
+ )}
+ title={translate('auto.components.editor.RichMarkdownCodeBlock.c72beafc0f', 'Copy code')}
>
{copied ? (
<>
- {translate("auto.components.editor.RichMarkdownCodeBlock.232d9ed853", "Copied")}
+
+ {translate('auto.components.editor.RichMarkdownCodeBlock.232d9ed853', 'Copied')}
+
>
) : (
diff --git a/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx b/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx
index ea548a5e4e6..d339f1e3da6 100644
--- a/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx
@@ -26,10 +26,18 @@ export function RichMarkdownDocLinkMenu({
className="rich-markdown-doc-link-menu"
style={{ left: menu.left, top: menu.top }}
role="listbox"
- aria-label={translate("auto.components.editor.RichMarkdownDocLinkMenu.0e8489bc11", "Markdown document links")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownDocLinkMenu.0e8489bc11',
+ 'Markdown document links'
+ )}
>
{rows.length === 0 ? (
- {translate("auto.components.editor.RichMarkdownDocLinkMenu.63ced7cb9b", "No documents found")}
+
+ {translate(
+ 'auto.components.editor.RichMarkdownDocLinkMenu.63ced7cb9b',
+ 'No documents found'
+ )}
+
) : (
rows.map((row, index) => {
const rowKey = row.kind === 'document' ? row.document.filePath : row.id
@@ -60,11 +68,18 @@ export function RichMarkdownDocLinkMenu({
)}
{overflow ? (
- {translate("auto.components.editor.RichMarkdownDocLinkMenu.2aaf7d9678", "Showing")}{rows.length} {translate("auto.components.editor.RichMarkdownDocLinkMenu.90c5f0e1e4", "of")}{totalMatches}
+ {translate('auto.components.editor.RichMarkdownDocLinkMenu.2aaf7d9678', 'Showing')}
+ {rows.length}{' '}
+ {translate('auto.components.editor.RichMarkdownDocLinkMenu.90c5f0e1e4', 'of')}
+ {totalMatches}
) : null}
- {translate("auto.components.editor.RichMarkdownDocLinkMenu.e17b987473", "↑↓ navigate ↵ select esc dismiss")}
+ {translate(
+ 'auto.components.editor.RichMarkdownDocLinkMenu.e17b987473',
+ '↑↓ navigate ↵ select esc dismiss'
+ )}
+
)
}
diff --git a/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx b/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx
index a26391f3f15..c99cc1a675b 100644
--- a/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx
@@ -55,14 +55,23 @@ export class RichMarkdownErrorBoundary extends React.Component {
return (
- {translate("auto.components.editor.RichMarkdownErrorBoundary.dfdf1cacd4", "The rich markdown editor hit an unexpected error and was reset to keep the rest of Orca responsive.")}
+ {translate(
+ 'auto.components.editor.RichMarkdownErrorBoundary.dfdf1cacd4',
+ 'The rich markdown editor hit an unexpected error and was reset to keep the rest of Orca responsive.'
+ )}
+
- {translate("auto.components.editor.RichMarkdownErrorBoundary.4a5de9f2f0", "Switch to source mode, or click retry to reload the rich view.")}
+ {translate(
+ 'auto.components.editor.RichMarkdownErrorBoundary.4a5de9f2f0',
+ 'Switch to source mode, or click retry to reload the rich view.'
+ )}
+
- {translate("auto.components.editor.RichMarkdownErrorBoundary.aad0998127", "Retry")}
+ {translate('auto.components.editor.RichMarkdownErrorBoundary.aad0998127', 'Retry')}
+
)
}
diff --git a/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx b/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx
index 801fefb3840..7a144d446d6 100644
--- a/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx
@@ -81,7 +81,10 @@ function LinkEditInput({
onCancel()
}
}}
- placeholder={translate("auto.components.editor.RichMarkdownLinkBubble.7b0b945fdc", "Paste or type a link…")}
+ placeholder={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.7b0b945fdc',
+ 'Paste or type a link…'
+ )}
className="rich-markdown-link-input"
/>
)
@@ -130,7 +133,10 @@ export function RichMarkdownLinkBubble({
type="button"
className="rich-markdown-link-button"
onClick={onOpen}
- title={translate("auto.components.editor.RichMarkdownLinkBubble.bfc813e909", "Open link")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.bfc813e909',
+ 'Open link'
+ )}
>
@@ -138,7 +144,10 @@ export function RichMarkdownLinkBubble({
type="button"
className="rich-markdown-link-button"
onClick={onEditStart}
- title={translate("auto.components.editor.RichMarkdownLinkBubble.cdfe166f6f", "Edit link")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.cdfe166f6f',
+ 'Edit link'
+ )}
>
@@ -146,7 +155,10 @@ export function RichMarkdownLinkBubble({
type="button"
className="rich-markdown-link-button"
onClick={onRemove}
- title={translate("auto.components.editor.RichMarkdownLinkBubble.1c99b726e0", "Remove link")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.1c99b726e0',
+ 'Remove link'
+ )}
>
diff --git a/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx b/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx
index 39d447e0f90..881cef3ff1d 100644
--- a/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx
@@ -49,7 +49,13 @@ export function RichMarkdownReviewNoteLayer({
onDelivered
}: RichMarkdownReviewNoteLayerProps): React.JSX.Element {
return (
-
+
{positions.map(({ comment, top }) => (
event.stopPropagation()}
onClick={(event) => {
@@ -105,7 +129,10 @@ export function RichMarkdownReviewNoteLayer({
scopes={[
{
id: 'note',
- label: translate("auto.components.editor.RichMarkdownReviewNoteLayer.f3ef92952b", "This note"),
+ label: translate(
+ 'auto.components.editor.RichMarkdownReviewNoteLayer.f3ef92952b',
+ 'This note'
+ ),
notes: comment.sentAt ? [] : [comment as MarkdownReviewNote],
prompt: formatMarkdownReviewNotes(
[comment as MarkdownReviewNote],
diff --git a/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx b/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx
index 922e889138c..4c0c058e88a 100644
--- a/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx
@@ -31,9 +31,29 @@ export function RichMarkdownReviewRailActions({
@@ -42,8 +62,28 @@ export function RichMarkdownReviewRailActions({
{notesCopied ? : }
diff --git a/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx b/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx
index 9aa31e1d133..aa985fdb8de 100644
--- a/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx
@@ -59,14 +59,20 @@ export function RichMarkdownSearchBar({
onClose()
}
}}
- placeholder={translate("auto.components.editor.RichMarkdownSearchBar.98b89276f3", "Find in rich editor")}
+ placeholder={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.98b89276f3',
+ 'Find in rich editor'
+ )}
className="rich-markdown-search-input h-7 !border-0 bg-transparent px-2 shadow-none focus-visible:!border-0 focus-visible:ring-0"
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.158c645829", "Find in rich markdown editor")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.158c645829',
+ 'Find in rich markdown editor'
+ )}
/>
{query && matchCount === 0
- ? translate("auto.components.editor.RichMarkdownSearchBar.a86958d508", "No results")
+ ? translate('auto.components.editor.RichMarkdownSearchBar.a86958d508', 'No results')
: `${matchCount === 0 ? 0 : activeMatchIndex + 1}/${matchCount}`}
onMoveToMatch(-1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.RichMarkdownSearchBar.32ae8d7d57", "Previous match")}
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.32ae8d7d57", "Previous match")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.32ae8d7d57',
+ 'Previous match'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.32ae8d7d57',
+ 'Previous match'
+ )}
className="rich-markdown-search-button"
>
@@ -89,8 +101,11 @@ export function RichMarkdownSearchBar({
onMouseDown={keepSearchFocus}
onClick={() => onMoveToMatch(1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.RichMarkdownSearchBar.f7bcecbe26", "Next match")}
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.f7bcecbe26", "Next match")}
+ title={translate('auto.components.editor.RichMarkdownSearchBar.f7bcecbe26', 'Next match')}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.f7bcecbe26',
+ 'Next match'
+ )}
className="rich-markdown-search-button"
>
@@ -102,8 +117,11 @@ export function RichMarkdownSearchBar({
size="icon-xs"
onMouseDown={keepSearchFocus}
onClick={onClose}
- title={translate("auto.components.editor.RichMarkdownSearchBar.de68b75bde", "Close search")}
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.de68b75bde", "Close search")}
+ title={translate('auto.components.editor.RichMarkdownSearchBar.de68b75bde', 'Close search')}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.de68b75bde',
+ 'Close search'
+ )}
className="rich-markdown-search-button"
>
diff --git a/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx b/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx
index c1d90169a0d..a3a1e5f7614 100644
--- a/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx
@@ -30,21 +30,35 @@ export function RichMarkdownSlashMenu({
className="rich-markdown-slash-menu"
style={{ left: slashMenu.left, top: slashMenu.top }}
role="dialog"
- aria-label={translate("auto.components.editor.RichMarkdownSlashMenu.2e0400b958", "Slash commands")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSlashMenu.2e0400b958',
+ 'Slash commands'
+ )}
>
event.preventDefault()}>
{filteredCommands.length === 0 ? (
-
{translate("auto.components.editor.RichMarkdownSlashMenu.82c6816ff8", "No blocks found")}
+
+ {translate(
+ 'auto.components.editor.RichMarkdownSlashMenu.82c6816ff8',
+ 'No blocks found'
+ )}
+
) : (
filteredCommands.map((command, index) => {
const showGroup = command.group !== currentGroup
diff --git a/src/renderer/src/components/editor/RichMarkdownToolbar.tsx b/src/renderer/src/components/editor/RichMarkdownToolbar.tsx
index 7dff6dc7168..7120a71db12 100644
--- a/src/renderer/src/components/editor/RichMarkdownToolbar.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownToolbar.tsx
@@ -34,28 +34,28 @@ export function RichMarkdownToolbar({
editor?.chain().focus().setParagraph().run()}
>
editor?.chain().focus().toggleHeading({ level: 1 }).run()}
>
editor?.chain().focus().toggleHeading({ level: 2 }).run()}
>
editor?.chain().focus().toggleHeading({ level: 3 }).run()}
>
@@ -63,21 +63,21 @@ export function RichMarkdownToolbar({
editor?.chain().focus().toggleBold().run()}
>
B
editor?.chain().focus().toggleItalic().run()}
>
I
editor?.chain().focus().toggleStrike().run()}
>
S
@@ -85,21 +85,21 @@ export function RichMarkdownToolbar({
editor?.chain().focus().toggleBulletList().run()}
>
editor?.chain().focus().toggleOrderedList().run()}
>
editor?.chain().focus().toggleTaskList().run()}
>
@@ -107,15 +107,23 @@ export function RichMarkdownToolbar({
editor?.chain().focus().toggleBlockquote().run()}
>
-
+
-
+
diff --git a/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx b/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx
index c1094969025..e9e6d9c018c 100644
--- a/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx
+++ b/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx
@@ -133,13 +133,21 @@ export function UntitledFileRenameDialog({
}}
>
- {translate("auto.components.editor.UntitledFileRenameDialog.674b046582", "Save as")}
+
+ {translate('auto.components.editor.UntitledFileRenameDialog.674b046582', 'Save as')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.e365f3c638", "Name your markdown file and pick a folder.")}
+ {translate(
+ 'auto.components.editor.UntitledFileRenameDialog.e365f3c638',
+ 'Name your markdown file and pick a folder.'
+ )}
+
-
{translate("auto.components.editor.UntitledFileRenameDialog.b6ed807cc6", "Name")}
+
+ {translate('auto.components.editor.UntitledFileRenameDialog.b6ed807cc6', 'Name')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.2d7d39dc63", ".md")}
+
+ {translate('auto.components.editor.UntitledFileRenameDialog.2d7d39dc63', '.md')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.30099dca46", "Folder")}
+ {translate('auto.components.editor.UntitledFileRenameDialog.30099dca46', 'Folder')}
+
void handleBrowse()}
title={
- disableBrowse ? translate("auto.components.editor.UntitledFileRenameDialog.5e7f0d8a80", "Folder picker unavailable for remote files") : translate("auto.components.editor.UntitledFileRenameDialog.725868c75d", "Browse folders")
+ disableBrowse
+ ? translate(
+ 'auto.components.editor.UntitledFileRenameDialog.5e7f0d8a80',
+ 'Folder picker unavailable for remote files'
+ )
+ : translate(
+ 'auto.components.editor.UntitledFileRenameDialog.725868c75d',
+ 'Browse folders'
+ )
}
>
@@ -198,9 +220,11 @@ export function UntitledFileRenameDialog({
{displayError &&
{displayError}
}
- {translate("auto.components.editor.UntitledFileRenameDialog.949711deb4", "Cancel")}
+ {translate('auto.components.editor.UntitledFileRenameDialog.949711deb4', 'Cancel')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.a7dd27b0bc", "Save")}
+ {translate('auto.components.editor.UntitledFileRenameDialog.a7dd27b0bc', 'Save')}
+
diff --git a/src/renderer/src/components/editor/export-active-markdown.ts b/src/renderer/src/components/editor/export-active-markdown.ts
index 6125e836ea2..eccc260b536 100644
--- a/src/renderer/src/components/editor/export-active-markdown.ts
+++ b/src/renderer/src/components/editor/export-active-markdown.ts
@@ -16,14 +16,23 @@ export async function exportActiveMarkdownToPdf(): Promise
{
return
}
- const toastId = toast.loading(translate("auto.components.editor.export.active.markdown.d4a901e0ad", "Exporting PDF..."))
+ const toastId = toast.loading(
+ translate('auto.components.editor.export.active.markdown.d4a901e0ad', 'Exporting PDF...')
+ )
try {
const result = await window.api.export.htmlToPdf({
html: payload.html,
title: payload.title
})
if (result.success) {
- toast.success(translate("auto.components.editor.export.active.markdown.51c4244904", "Exported to {{value0}}", { value0: result.filePath }), { id: toastId })
+ toast.success(
+ translate(
+ 'auto.components.editor.export.active.markdown.51c4244904',
+ 'Exported to {{value0}}',
+ { value0: result.filePath }
+ ),
+ { id: toastId }
+ )
return
}
if (result.cancelled) {
@@ -32,7 +41,14 @@ export async function exportActiveMarkdownToPdf(): Promise {
toast.dismiss(toastId)
return
}
- toast.error(result.error ?? translate("auto.components.editor.export.active.markdown.eda2cea3ad", "Failed to export PDF"), { id: toastId })
+ toast.error(
+ result.error ??
+ translate(
+ 'auto.components.editor.export.active.markdown.eda2cea3ad',
+ 'Failed to export PDF'
+ ),
+ { id: toastId }
+ )
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to export PDF'
toast.error(message, { id: toastId })
diff --git a/src/renderer/src/components/editor/markdown-rich-mode.ts b/src/renderer/src/components/editor/markdown-rich-mode.ts
index b22e2358d39..2cd1aebf7d0 100644
--- a/src/renderer/src/components/editor/markdown-rich-mode.ts
+++ b/src/renderer/src/components/editor/markdown-rich-mode.ts
@@ -17,7 +17,10 @@ type UnsupportedMatch = {
const UNSUPPORTED_PATTERNS: UnsupportedMatch[] = [
{
reason: 'html-or-jsx',
- message: translate("auto.components.editor.markdown.rich.mode.57128b73e1", "Editable only in code mode because this file contains HTML, JSX, or MDX."),
+ message: translate(
+ 'auto.components.editor.markdown.rich.mode.57128b73e1',
+ 'Editable only in code mode because this file contains HTML, JSX, or MDX.'
+ ),
// Why: the rich editor preserves common embedded markup via placeholder
// tokens before parsing, but any HTML shape that still fails round-trip
// must fall back instead of risking silent source corruption.
@@ -25,12 +28,18 @@ const UNSUPPORTED_PATTERNS: UnsupportedMatch[] = [
},
{
reason: 'reference-links',
- message: translate("auto.components.editor.markdown.rich.mode.2fd2b44073", "Editable only in code mode because this file contains reference-style links."),
+ message: translate(
+ 'auto.components.editor.markdown.rich.mode.2fd2b44073',
+ 'Editable only in code mode because this file contains reference-style links.'
+ ),
pattern: /^\[[^\]]+\]:\s+\S+/m
},
{
reason: 'footnotes',
- message: translate("auto.components.editor.markdown.rich.mode.7a8ce7c7da", "Editable only in code mode because this file contains footnotes."),
+ message: translate(
+ 'auto.components.editor.markdown.rich.mode.7a8ce7c7da',
+ 'Editable only in code mode because this file contains footnotes.'
+ ),
pattern: /^\[\^[^\]]+\]:\s+/m
}
]
diff --git a/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts b/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts
index 7258f7d1688..4df725b8b63 100644
--- a/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts
+++ b/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts
@@ -198,7 +198,13 @@ function openMarkdownLinkInClientOs({
if (classified.kind === 'markdown') {
void window.api.shell.pathExists(classified.absolutePath).then((exists) => {
if (!exists) {
- toast.error(translate("auto.components.editor.rich.markdown.editor.click.routing.2d5fb9335d", "File not found: {{value0}}", { value0: classified.relativePath }))
+ toast.error(
+ translate(
+ 'auto.components.editor.rich.markdown.editor.click.routing.2d5fb9335d',
+ 'File not found: {{value0}}',
+ { value0: classified.relativePath }
+ )
+ )
return
}
void window.api.shell.openFileUri(toFileUrlForOsEscape(classified.absolutePath))
diff --git a/src/renderer/src/components/editor/useContextualCopySetup.tsx b/src/renderer/src/components/editor/useContextualCopySetup.tsx
index 5b268650ba7..e115422f88b 100644
--- a/src/renderer/src/components/editor/useContextualCopySetup.tsx
+++ b/src/renderer/src/components/editor/useContextualCopySetup.tsx
@@ -35,7 +35,8 @@ export function useContextualCopySetup() {
className="pointer-events-none fixed z-50 rounded-md bg-foreground px-2 py-1 text-xs text-background shadow-sm"
style={{ left: copyToast.left, top: copyToast.top }}
>
- {translate("auto.components.editor.useContextualCopySetup.059bfb0d94", "Context copied")}
+ {translate('auto.components.editor.useContextualCopySetup.059bfb0d94', 'Context copied')}
+
) : null
return { setupCopy, toastNode }
diff --git a/src/renderer/src/components/editor/useLocalImagePick.ts b/src/renderer/src/components/editor/useLocalImagePick.ts
index fb8ed8db8c7..f04445e5301 100644
--- a/src/renderer/src/components/editor/useLocalImagePick.ts
+++ b/src/renderer/src/components/editor/useLocalImagePick.ts
@@ -37,7 +37,12 @@ export function useLocalImagePick(
if (settings?.activeRuntimeEnvironmentId?.trim() || connectionId) {
const worktreePath = getWorktreePath(worktreeId)
if (settings?.activeRuntimeEnvironmentId?.trim() && !worktreePath) {
- toast.error(translate("auto.components.editor.useLocalImagePick.91d835dc88", "Worktree path not available."))
+ toast.error(
+ translate(
+ 'auto.components.editor.useLocalImagePick.91d835dc88',
+ 'Worktree path not available.'
+ )
+ )
return
}
// Why: picked images are client-local files while remote markdown lives
@@ -55,7 +60,12 @@ export function useLocalImagePick(
)
const imported = results.find((result) => result.status === 'imported')
if (!imported) {
- toast.error(translate("auto.components.editor.useLocalImagePick.175cb8b8ce", "Failed to insert image."))
+ toast.error(
+ translate(
+ 'auto.components.editor.useLocalImagePick.175cb8b8ce',
+ 'Failed to insert image.'
+ )
+ )
return
}
editor
diff --git a/src/renderer/src/components/editor/useRichMarkdownReviewData.ts b/src/renderer/src/components/editor/useRichMarkdownReviewData.ts
index 66baa59cdb8..e0dc9286034 100644
--- a/src/renderer/src/components/editor/useRichMarkdownReviewData.ts
+++ b/src/renderer/src/components/editor/useRichMarkdownReviewData.ts
@@ -57,7 +57,10 @@ export function useRichMarkdownReviewData({
return [
{
id: 'all',
- label: translate("auto.components.editor.useRichMarkdownReviewData.f9d2acd6b0", "All unsent notes"),
+ label: translate(
+ 'auto.components.editor.useRichMarkdownReviewData.f9d2acd6b0',
+ 'All unsent notes'
+ ),
notes: unsentNotes,
prompt: formatMarkdownReviewNotes(unsentNotes, markdownReviewContent)
}
diff --git a/src/renderer/src/components/emulator-pane/EmulatorPane.tsx b/src/renderer/src/components/emulator-pane/EmulatorPane.tsx
index 8913b91a027..1b3499e827c 100644
--- a/src/renderer/src/components/emulator-pane/EmulatorPane.tsx
+++ b/src/renderer/src/components/emulator-pane/EmulatorPane.tsx
@@ -71,7 +71,12 @@ function EmulatorPaneContent({ tab, worktreeId, isActive = true }: EmulatorPaneP
{!isLive && !loading ? (
-
{translate("auto.components.emulator.pane.EmulatorPane.59b08fa031", "No emulator connected")}
+
+ {translate(
+ 'auto.components.emulator.pane.EmulatorPane.59b08fa031',
+ 'No emulator connected'
+ )}
+
) : null}
- {frameLayout?.kind === "phone" ? : null}
+ {frameLayout?.kind === 'phone' ? : null}
diff --git a/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx b/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx
index 3ede31d788f..764a9e579d7 100644
--- a/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx
+++ b/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx
@@ -65,7 +65,12 @@ export function EmulatorPaneToolbar({
disabled={loading || devices.length === 0}
>
-
+
{devices.map((d) => (
@@ -84,14 +89,23 @@ export function EmulatorPaneToolbar({
className="h-7 gap-1 px-2 text-xs"
onClick={onRotate}
disabled={!isLive || loading}
- aria-label={translate("auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a", "Rotate")}
+ aria-label={translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a',
+ 'Rotate'
+ )}
>
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a", "Rotate")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a',
+ 'Rotate'
+ )}
+
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a", "Rotate")}
+ {translate('auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a', 'Rotate')}
+
@@ -102,13 +116,17 @@ export function EmulatorPaneToolbar({
className="size-7"
onClick={onHome}
disabled={!isLive || loading}
- aria-label={translate("auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e", "Home")}
+ aria-label={translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e',
+ 'Home'
+ )}
>
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e", "Home")}
+ {translate('auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e', 'Home')}
+
{isLive ? (
@@ -120,13 +138,20 @@ export function EmulatorPaneToolbar({
className="size-7 text-muted-foreground hover:text-destructive"
onClick={onShutdown}
disabled={loading}
- aria-label={translate("auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356", "Shut down emulator")}
+ aria-label={translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356',
+ 'Shut down emulator'
+ )}
>
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356", "Shut down emulator")}
+ {translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356',
+ 'Shut down emulator'
+ )}
+
) : (
- {loading ? translate("auto.components.emulator.pane.emulator.pane.toolbar.868c0f2938", "Working…") : translate("auto.components.emulator.pane.emulator.pane.toolbar.81b3571a07", "Connect")}
+ {loading
+ ? translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.868c0f2938',
+ 'Working…'
+ )
+ : translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.81b3571a07',
+ 'Connect'
+ )}
)}
diff --git a/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx b/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx
index 5dad5751c72..426212484a1 100644
--- a/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx
+++ b/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx
@@ -44,7 +44,10 @@ export function EmulatorScreenStreamContent({
- {translate("auto.components.emulator.pane.emulator.screen.stream.content.5f818f12ab", "Connecting emulator…")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.screen.stream.content.5f818f12ab',
+ 'Connecting emulator…'
+ )}
+
>
) : displayError ? (
- {translate("auto.components.emulator.pane.emulator.screen.stream.content.36841af608", "Stream disconnected")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.screen.stream.content.36841af608',
+ 'Stream disconnected'
+ )}
+
) : (
- {translate("auto.components.emulator.pane.emulator.screen.stream.content.8b1a0d8694", "Emulator preview")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.screen.stream.content.8b1a0d8694',
+ 'Emulator preview'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx b/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx
index 96f06e6bdc8..5be35a7549c 100644
--- a/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx
+++ b/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx
@@ -5,9 +5,18 @@ export function EmulatorUnavailablePane() {
return (
-
{translate("auto.components.emulator.pane.emulator.unavailable.pane.b2c268a0b9", "Mobile Emulator is macOS only")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.unavailable.pane.b2c268a0b9',
+ 'Mobile Emulator is macOS only'
+ )}
+
- {translate("auto.components.emulator.pane.emulator.unavailable.pane.f630b9ca9f", "Mobile Emulator requires a Mac with Xcode and the iOS Simulator runtime. On Linux or Windows, use a physical device or a remote Mac build host.")}
+ {translate(
+ 'auto.components.emulator.pane.emulator.unavailable.pane.f630b9ca9f',
+ 'Mobile Emulator requires a Mac with Xcode and the iOS Simulator runtime. On Linux or Windows, use a physical device or a remote Mac build host.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts b/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts
index d29847e011f..367b37e6b37 100644
--- a/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts
+++ b/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts
@@ -47,7 +47,13 @@ export function useEmulatorFrameStream(
setState((current) =>
current.streamIdentity !== streamIdentity || current.frameUrl
? current
- : { ...current, error: translate("auto.components.emulator.pane.use.emulator.frame.stream.f1c0179002", "Stream is not producing frames.") }
+ : {
+ ...current,
+ error: translate(
+ 'auto.components.emulator.pane.use.emulator.frame.stream.f1c0179002',
+ 'Stream is not producing frames.'
+ )
+ }
)
}, FIRST_FRAME_TIMEOUT_MS)
diff --git a/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx b/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx
index b707d8c087a..afa7fbf3dc9 100644
--- a/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx
+++ b/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx
@@ -83,16 +83,27 @@ export class RecoverableRenderErrorBoundary extends React.Component
- {this.props.title ?? translate("auto.components.error.boundaries.RecoverableRenderErrorBoundary.ab855c11f4", "This part of Orca hit an error.")}
+ {this.props.title ??
+ translate(
+ 'auto.components.error.boundaries.RecoverableRenderErrorBoundary.ab855c11f4',
+ 'This part of Orca hit an error.'
+ )}
{this.props.description ??
- translate("auto.components.error.boundaries.RecoverableRenderErrorBoundary.34a189ae0f", "The rest of the app is still running. Retry this surface or switch away and come back.")}
+ translate(
+ 'auto.components.error.boundaries.RecoverableRenderErrorBoundary.34a189ae0f',
+ 'The rest of the app is still running. Retry this surface or switch away and come back.'
+ )}
- {translate("auto.components.error.boundaries.RecoverableRenderErrorBoundary.55001880db", "Retry")}
+ {translate(
+ 'auto.components.error.boundaries.RecoverableRenderErrorBoundary.55001880db',
+ 'Retry'
+ )}
+
)
}
diff --git a/src/renderer/src/components/feature-interaction-writer-boundaries.test.ts b/src/renderer/src/components/feature-interaction-writer-boundaries.test.ts
new file mode 100644
index 00000000000..4c0603355d3
--- /dev/null
+++ b/src/renderer/src/components/feature-interaction-writer-boundaries.test.ts
@@ -0,0 +1,227 @@
+import { readFileSync } from 'node:fs'
+import { join } from 'node:path'
+import { describe, expect, it } from 'vitest'
+
+const COMPONENT_ROOT = __dirname
+
+function componentSource(relativePath: string): string {
+ return readFileSync(join(COMPONENT_ROOT, relativePath), 'utf8')
+}
+
+function sourceBetween(source: string, startPattern: string, endPattern: string): string {
+ const start = source.indexOf(startPattern)
+ expect(start).toBeGreaterThanOrEqual(0)
+ const end = source.indexOf(endPattern, start + startPattern.length)
+ expect(end).toBeGreaterThan(start)
+ return source.slice(start, end)
+}
+
+function componentBodyBeforeRender(source: string, componentName: string): string {
+ return sourceBetween(source, `function ${componentName}`, '\n return (\n <')
+}
+
+describe('feature interaction writer boundaries', () => {
+ it('keeps Cmd+J feature writers in open/selection handlers, not query or navigation rendering', () => {
+ const source = componentSource('WorktreeJumpPalette.tsx')
+ const renderStart = source.lastIndexOf(' return (')
+ expect(renderStart).toBeGreaterThan(0)
+
+ const handlerSection = source.slice(0, renderStart)
+ const renderSection = source.slice(renderStart)
+
+ const cmdJWriterPattern = /recordFeatureInteraction\('cmd-j/g
+ const allCmdJWriterCount = source.match(cmdJWriterPattern)?.length ?? 0
+ expect(allCmdJWriterCount).toBeGreaterThanOrEqual(6)
+ expect(handlerSection.match(cmdJWriterPattern)?.length ?? 0).toBe(allCmdJWriterCount)
+ expect(renderSection).not.toContain("recordFeatureInteraction('cmd-j")
+ expect(
+ sourceBetween(source, 'const handleQueryChange', 'const cancelFallbackFocusFrames')
+ ).not.toContain("recordFeatureInteraction('cmd-j")
+ })
+
+ it('keeps task-provider writers off filters, tab switches, query edits, refresh, and pagination', () => {
+ const source = componentSource('TaskPage.tsx')
+ const providerWriter = /recordFeatureInteraction\('(github|gitlab|linear)-tasks'\)/
+
+ const passiveSections = [
+ sourceBetween(source, 'const handleRefreshGithubTasks', 'const [newIssueOpen'),
+ sourceBetween(
+ source,
+ 'const handleLoadNextPage',
+ 'useEffect(() => {\n if (!taskResumeApplied)'
+ ),
+ sourceBetween(source, 'const handleApplyTaskSearch', 'const handleSetDefaultTaskPreset'),
+ sourceBetween(source, 'const handleSelectGithubTaskKind', 'const handleResetGithubTaskSearch')
+ ]
+ for (const section of passiveSections) {
+ expect(section).not.toMatch(providerWriter)
+ }
+ })
+
+ it('records GitHub provider-depth for inline item mutation success paths', () => {
+ const source = componentSource('TaskPage.tsx')
+ const githubWriter = "recordFeatureInteraction('github-tasks')"
+ const mutationSections = [
+ sourceBetween(source, 'function GHAssigneesCell', 'const triggerContent ='),
+ sourceBetween(source, 'function PRReviewCell', 'const requestReviewer ='),
+ componentBodyBeforeRender(source, 'PRMergeCell'),
+ sourceBetween(
+ source,
+ 'const handleOpenOrUseGitHubWorkItem',
+ 'const openComposerForGitLabItem'
+ )
+ ]
+
+ for (const section of mutationSections) {
+ expect(section).toContain(githubWriter)
+ }
+ })
+
+ it('suppresses Tasks surface telemetry for in-page provider switches and detail opens', () => {
+ const source = componentSource('TaskPage.tsx')
+ const suppression = 'recordTasksInteraction: false'
+
+ const inPageNavigationSections = [
+ sourceBetween(source, 'const openGitHubDetailPage', 'const patchTaskPageWorkItemRows'),
+ sourceBetween(source, 'const openLinearDetailPage', 'const openRelatedLinearIssue'),
+ sourceBetween(source, 'taskSourceManuallyChangedRef.current = true', 'void updateSettings')
+ ]
+
+ for (const section of inPageNavigationSections) {
+ expect(section).toContain(suppression)
+ }
+ })
+
+ it('records Cmd+J create-workspace as its own destination, not a generic quick action', () => {
+ const source = componentSource('WorktreeJumpPalette.tsx')
+ const section = sourceBetween(source, 'const handleSelectQuickAction', 'const handleSelectItem')
+
+ expect(section).toContain("recordFeatureInteraction('cmd-j-create-workspace')")
+ expect(section).toContain("recordFeatureInteraction('cmd-j-quick-action')")
+ expect(section.indexOf("recordFeatureInteraction('cmd-j-create-workspace')")).toBeLessThan(
+ section.indexOf("recordFeatureInteraction('cmd-j-quick-action')")
+ )
+ expect(
+ sourceBetween(
+ section,
+ "if (action.id === 'create-workspace')",
+ "recordFeatureInteraction('cmd-j-quick-action')"
+ )
+ ).toContain('return')
+ })
+
+ it('records GitLab provider-depth for detail opens, workspace use, and dialog mutations', () => {
+ const taskPageSource = componentSource('TaskPage.tsx')
+ const dialogSource = componentSource('GitLabItemDialog.tsx')
+ const gitlabWriter = "recordFeatureInteraction('gitlab-tasks')"
+
+ expect(
+ sourceBetween(
+ taskPageSource,
+ '{displayedGitLabItems.map((item) => (',
+ '
{
+ const taskPageSource = componentSource('TaskPage.tsx')
+ const drawerSource = componentSource('LinearItemDrawer.tsx')
+ const linearWriter = "recordFeatureInteraction('linear-tasks')"
+
+ const taskPageSections = [
+ sourceBetween(taskPageSource, 'function LinearStateCell', 'return ('),
+ sourceBetween(
+ taskPageSource,
+ 'const handleLinearBoardDrop',
+ 'const toggleLinearDisplayProperty'
+ ),
+ sourceBetween(
+ taskPageSource,
+ 'const handleCreateNewLinearIssue',
+ 'const openComposerForLinearItem'
+ ),
+ sourceBetween(
+ taskPageSource,
+ 'const handleUseLinearItem',
+ 'const handleLinearWorkspaceChange'
+ )
+ ]
+ for (const section of taskPageSections) {
+ expect(section).toContain(linearWriter)
+ }
+
+ const drawerMutationSections = [
+ sourceBetween(drawerSource, 'const handleStateChange', 'const handlePriorityChange'),
+ sourceBetween(drawerSource, 'const handlePriorityChange', 'const handleEstimateChange'),
+ sourceBetween(drawerSource, 'const handleEstimateChange', 'const handleEstimateSubmit'),
+ sourceBetween(drawerSource, 'const handleAssigneeChange', 'const handleLabelToggle'),
+ sourceBetween(drawerSource, 'const handleLabelToggle', 'return ('),
+ sourceBetween(drawerSource, 'const handleSubmit = useCallback(async () => {', 'return (')
+ ]
+ for (const section of drawerMutationSections) {
+ expect(section).toContain(linearWriter)
+ }
+ })
+
+ it('records browser annotation agent handoff only from the prompt-delivered callback', () => {
+ const source = componentSource('browser-pane/BrowserPane.tsx')
+ expect(
+ source.match(/recordFeatureInteraction\('browser-annotations-sent-to-agent'\)/g)
+ ).toHaveLength(1)
+ expect(
+ sourceBetween(
+ source,
+ 'const handleBrowserAnnotationsSentToAgent',
+ 'const handleClearBrowserAnnotations'
+ )
+ ).toContain("recordFeatureInteraction('browser-annotations-sent-to-agent')")
+ expect(
+ sourceBetween(
+ source,
+ 'const handleCopyBrowserAnnotations',
+ 'const handleBrowserAnnotationsSentToAgent'
+ )
+ ).not.toContain("recordFeatureInteraction('browser-annotations-sent-to-agent')")
+ expect(
+ sourceBetween(
+ source,
+ 'const handleClearBrowserAnnotations',
+ 'const handleDeleteBrowserAnnotation'
+ )
+ ).not.toContain("recordFeatureInteraction('browser-annotations-sent-to-agent')")
+ })
+
+ it('records floating workspace hide only from explicit disable or hide actions', () => {
+ const allowedSources = [
+ componentSource('settings/FloatingWorkspacePane.tsx'),
+ componentSource('floating-terminal/FloatingTerminalIconContextMenu.tsx')
+ ].join('\n')
+ const passiveSources = [
+ componentSource('../App.tsx'),
+ componentSource('floating-terminal/FloatingTerminalPanel.tsx')
+ ].join('\n')
+
+ expect(
+ allowedSources.match(/recordFeatureInteraction\('floating-workspace-hidden'\)/g) ?? []
+ ).toHaveLength(2)
+ expect(passiveSources).not.toContain("recordFeatureInteraction('floating-workspace-hidden')")
+ })
+})
diff --git a/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx b/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx
index d97c5a7dafb..5197db2a559 100644
--- a/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx
+++ b/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx
@@ -64,7 +64,12 @@ export function CliFeatureTipVisual(): JSX.Element {
- ● {translate("auto.components.feature.tips.CliFeatureTipVisual.22e62f3bab", "Claude Code session started")}
+
●
+ {translate(
+ 'auto.components.feature.tips.CliFeatureTipVisual.22e62f3bab',
+ 'Claude Code session started'
+ )}
+
{CLI_AGENT_COMMANDS.map((command, index) => {
const isVisible = index < visibleCommandCount
const isCurrentLine = isVisible && index === visibleCommandCount - 1
@@ -73,7 +78,9 @@ export function CliFeatureTipVisual(): JSX.Element {
key={command}
className={`truncate ${isVisible ? 'animate-cli-tip-command-line' : 'invisible'}`}
>
- {translate("auto.components.feature.tips.CliFeatureTipVisual.badb4fc342", ">")}
+
+ {translate('auto.components.feature.tips.CliFeatureTipVisual.badb4fc342', '>')}
+
{command}
{isCurrentLine ? (
diff --git a/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx b/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx
index 287d4466608..b9e9f1fac88 100644
--- a/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx
+++ b/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx
@@ -10,9 +10,21 @@ export function CliSkillSetupTerminal(): React.JSX.Element {
const handleCopySkillCommand = async (): Promise => {
try {
await window.api.ui.writeClipboardText(ORCA_CLI_ORCHESTRATION_SKILL_INSTALL_COMMAND)
- toast.success(translate("auto.components.feature.tips.CliSkillSetupTerminal.b8ad063571", "Copied the skill install command."))
+ toast.success(
+ translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.b8ad063571',
+ 'Copied the skill install command.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.feature.tips.CliSkillSetupTerminal.6ff813fc1d", "Failed to copy skill command."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.6ff813fc1d',
+ 'Failed to copy skill command.'
+ )
+ )
}
}
@@ -29,20 +41,36 @@ export function CliSkillSetupTerminal(): React.JSX.Element {
size="icon-sm"
className="shrink-0"
onClick={() => void handleCopySkillCommand()}
- aria-label={translate("auto.components.feature.tips.CliSkillSetupTerminal.5eca672aac", "Copy skill install command")}
+ aria-label={translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.5eca672aac',
+ 'Copy skill install command'
+ )}
>
- {translate("auto.components.feature.tips.CliSkillSetupTerminal.5c3aee22c0", "Copy command")}
+ {translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.5c3aee22c0',
+ 'Copy command'
+ )}
+
{renderQuery}
- {!reducedMotion && (phase === 'open' || phase === "typing") ? (
+ {!reducedMotion && (phase === 'open' || phase === 'typing') ? (
) : null}
@@ -224,7 +224,7 @@ export function CmdJPaletteFeatureTipVisual(): JSX.Element {
className={`flex shrink-0 items-center gap-2.5 rounded-lg border border-transparent px-2.5 py-1.5 ${resultEnterClass}`}
>
- {result.status === "done" ? (
+ {result.status === 'done' ? (
) : (
// Why: yellow border spinner mirrors StatusIndicator's
@@ -255,7 +255,11 @@ export function CmdJPaletteFeatureTipVisual(): JSX.Element {
- {translate("auto.components.feature.tips.CmdJPaletteFeatureTipVisual.ab94e16d44", "Create worktree \"{{value0}}\"", { value0: renderQuery.trim() })}
+ {translate(
+ 'auto.components.feature.tips.CmdJPaletteFeatureTipVisual.ab94e16d44',
+ 'Create worktree "{{value0}}"',
+ { value0: renderQuery.trim() }
+ )}
) : null}
diff --git a/src/renderer/src/components/feature-tips/FeatureTipActions.tsx b/src/renderer/src/components/feature-tips/FeatureTipActions.tsx
index 56125568177..985732d2e50 100644
--- a/src/renderer/src/components/feature-tips/FeatureTipActions.tsx
+++ b/src/renderer/src/components/feature-tips/FeatureTipActions.tsx
@@ -30,7 +30,8 @@ export function FeatureTipActions({
<>
{showSkip ? (
- {translate("auto.components.feature.tips.FeatureTipActions.eb04abece8", "Maybe Later")}
+ {translate('auto.components.feature.tips.FeatureTipActions.eb04abece8', 'Maybe Later')}
+
) : null}
- {translate("auto.components.feature.tips.FeatureTipsModal.4795ac2d4a", "Try asking:")}
+
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.4795ac2d4a',
+ 'Try asking:'
+ )}
+
- {translate("auto.components.feature.tips.FeatureTipsModal.55846c7f95", "“Split this PR into two")}{translate("auto.components.feature.tips.FeatureTipsModal.27c567a89c", "worktrees")} {translate("auto.components.feature.tips.FeatureTipsModal.7fc6f02099", "and create PRs for each.”")}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.55846c7f95',
+ '“Split this PR into two'
+ )}
+
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.27c567a89c',
+ 'worktrees'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.7fc6f02099',
+ 'and create PRs for each.”'
+ )}
+
- {translate("auto.components.feature.tips.FeatureTipsModal.864e2db28f", "“When the agent in")}{translate("auto.components.feature.tips.FeatureTipsModal.298301b7a0", "worktree")} {translate("auto.components.feature.tips.FeatureTipsModal.3c6c478462", "X finishes, send it the review task.”")}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.864e2db28f',
+ '“When the agent in'
+ )}
+
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.298301b7a0',
+ 'worktree'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.3c6c478462',
+ 'X finishes, send it the review task.”'
+ )}
+
{skillTerminalOpen ? : null}
@@ -291,7 +345,8 @@ export default function FeatureTipsModal(): JSX.Element | null {
{skillTerminalOpen ? (
- {translate("auto.components.feature.tips.FeatureTipsModal.c169298e4d", "Done")}
+ {translate('auto.components.feature.tips.FeatureTipsModal.c169298e4d', 'Done')}
+
) : (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.4fa59ca545", "✓ Updated")}{' '}
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.4fa59ca545', '✓ Updated')}{' '}
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.051c97d15a", ".pp-card[data-card=\"starter\"] .pp-cta")}
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.051c97d15a',
+ '.pp-card[data-card="starter"] .pp-cta'
+ )}
+
>
)
},
@@ -152,7 +156,14 @@ const TERM_ENTRIES: readonly { entry: TermEntry; minPhase: Phase }[] = [
{
entry: {
kind: 'ok',
- html: <>{translate("auto.components.feature.wall.BrowserAnimatedVisual.eb88125c6f", "✓ Verified — Try free still works.")}>
+ html: (
+ <>
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.eb88125c6f',
+ '✓ Verified — Try free still works.'
+ )}
+ >
+ )
},
minPhase: 'verified'
}
@@ -496,10 +507,20 @@ export function BrowserAnimatedVisual(props: {
}
- title={translate("auto.components.feature.wall.BrowserAnimatedVisual.04096318ab", "Terminal 1")}
+ title={translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.04096318ab',
+ 'Terminal 1'
+ )}
/>
{browserTabVisible ? (
- } title={translate("auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf", "localhost:3000")} />
+ }
+ title={translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf',
+ 'localhost:3000'
+ )}
+ />
) : null}
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.0a2bd01c02", "New Browser Tab")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.0a2bd01c02',
+ 'New Browser Tab'
+ )}
+
{newBrowserShortcutLabel}
@@ -566,9 +592,22 @@ export function BrowserAnimatedVisual(props: {
) : (
<>
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf", "localhost:3000")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf',
+ 'localhost:3000'
+ )}
+
- {showSignup ? translate("auto.components.feature.wall.BrowserAnimatedVisual.f39be6ca14", "/signup") : translate("auto.components.feature.wall.BrowserAnimatedVisual.73bbb46073", "/pricing")}
+ {showSignup
+ ? translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.f39be6ca14',
+ '/signup'
+ )
+ : translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.73bbb46073',
+ '/pricing'
+ )}
>
)}
@@ -612,7 +651,11 @@ export function BrowserAnimatedVisual(props: {
style={{ left: annotateAnchor.left, top: annotateAnchor.top, width: 188 }}
>
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.d8856b604a", "div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta")}
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.d8856b604a',
+ 'div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta'
+ )}
+
{typedChars > 0 ? (
@@ -621,13 +664,21 @@ export function BrowserAnimatedVisual(props: {
>
) : (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.3d2352f94b", "Describe the change…")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.3d2352f94b',
+ 'Describe the change…'
+ )}
+
)}
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.6e4616d039", "Claude")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.6e4616d039',
+ 'Claude'
+ )}
+
{TERM_ENTRIES.map(({ entry, minPhase }, i) => (
@@ -683,7 +739,12 @@ export function BrowserAnimatedVisual(props: {
-
+
)
}
@@ -734,7 +795,10 @@ function TermEntryView(props: { entry: TermEntry }): JSX.Element {
if (entry.kind === 'prompt') {
return (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.f2034c4930", ">")} {entry.text}
+
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.f2034c4930', '>')}
+ {' '}
+ {entry.text}
)
}
@@ -742,7 +806,8 @@ function TermEntryView(props: { entry: TermEntry }): JSX.Element {
return (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.0ce7c24b4d", "Working…")}
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.0ce7c24b4d', 'Working…')}
+
)
}
if (entry.kind === 'ok') {
@@ -783,20 +848,29 @@ function PricingView(props: {
}): JSX.Element {
return (
<>
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.9e0f530390", "Pricing")}
+
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.9e0f530390', 'Pricing')}
+
>
)
@@ -805,7 +879,12 @@ function PricingView(props: {
function SignupView(): JSX.Element {
return (
-
{translate("auto.components.feature.wall.BrowserAnimatedVisual.46df009982", "Start your free trial")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.46df009982',
+ 'Start your free trial'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx b/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx
index b76be56f083..12fd9c5d359 100644
--- a/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx
+++ b/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx
@@ -26,8 +26,14 @@ export function BrowserUseSkillSetupCard(props: {
const setupPanel = (
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.9cddfe96b2", "Local app")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.9cddfe96b2',
+ 'Local app'
+ )}
+
@@ -100,7 +104,15 @@ export function ComputerUseAnimatedVisual(props: {
: 'border-border bg-muted/40 text-muted-foreground'
)}
>
- {verified ? translate("auto.components.feature.wall.ComputerUseAnimatedVisual.c11dda000b", "Approved") : translate("auto.components.feature.wall.ComputerUseAnimatedVisual.bdd5312213", "Pending")}
+ {verified
+ ? translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.c11dda000b',
+ 'Approved'
+ )
+ : translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.bdd5312213',
+ 'Pending'
+ )}
@@ -131,7 +143,15 @@ export function ComputerUseAnimatedVisual(props: {
phase === 'click' ? 'scale-[0.97]' : null
)}
>
- {clicked ? translate("auto.components.feature.wall.ComputerUseAnimatedVisual.3cc2df3671", "Done") : translate("auto.components.feature.wall.ComputerUseAnimatedVisual.9634d870d1", "Approve")}
+ {clicked
+ ? translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.3cc2df3671',
+ 'Done'
+ )
+ : translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.9634d870d1',
+ 'Approve'
+ )}
@@ -159,7 +179,12 @@ function AgentWorktreeTerminal(props: {
-
{translate("auto.components.feature.wall.ComputerUseAnimatedVisual.94787f01f8", "Claude Code")}
+
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.94787f01f8',
+ 'Claude Code'
+ )}
+
{WORKTREE_LABEL}
@@ -168,10 +193,20 @@ function AgentWorktreeTerminal(props: {
●
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.2adb561b44", "Claude Code session started")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.2adb561b44',
+ 'Claude Code session started'
+ )}
+
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.99a8624bcb", ">")}
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.79445f7512", "approve the note in my app")}
+
+ {translate('auto.components.feature.wall.ComputerUseAnimatedVisual.99a8624bcb', '>')}
+
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.79445f7512',
+ 'approve the note in my app'
+ )}
+
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.1719b28a81", "found \"Approve\"")}[#7]
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.1719b28a81',
+ 'found "Approve"'
+ )}
+ [#7]
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.6804cb356f", "click sent")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.6804cb356f',
+ 'click sent'
+ )}
+
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.f27676a92c", "status:")}{translate("auto.components.feature.wall.ComputerUseAnimatedVisual.d8401975b1", "approved")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.f27676a92c',
+ 'status:'
+ )}
+
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.d8401975b1',
+ 'approved'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx
index 1a240f3dda9..ff02e98bf82 100644
--- a/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx
@@ -604,7 +604,11 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
- {translate("auto.components.feature.wall.EditorAnimatedVisual.cda56c5915", "notes / launch-plan.md")}
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.cda56c5915',
+ 'notes / launch-plan.md'
+ )}
+
{/* Toolbar — visual-only, mirrors RichMarkdownToolbar.tsx button order. */}
@@ -624,7 +628,9 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
- {translate("auto.components.feature.wall.EditorAnimatedVisual.218503f9f3", "autosaved")}
+
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.218503f9f3', 'autosaved')}
+
@@ -635,13 +641,29 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
className="relative overflow-hidden bg-background px-6 pb-5 pt-4"
style={{ minHeight: 280 }}
>
- {translate("auto.components.feature.wall.EditorAnimatedVisual.5a55c00a81", "Launch plan")}
+
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.5a55c00a81', 'Launch plan')}
+
- {translate("auto.components.feature.wall.EditorAnimatedVisual.22ae7b4d9d", "A quick note for the team — pulling together what's left before we ship.")}
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.22ae7b4d9d',
+ "A quick note for the team — pulling together what's left before we ship."
+ )}
+
- {translate("auto.components.feature.wall.EditorAnimatedVisual.95f0c3a46f", "Smoke-test the install flow on a fresh machine.")}
- {translate("auto.components.feature.wall.EditorAnimatedVisual.4426aab46f", "Update the docs index once the new tile lands.")}
+
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.95f0c3a46f',
+ 'Smoke-test the install flow on a fresh machine.'
+ )}
+
+
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.4426aab46f',
+ 'Update the docs index once the new tile lands.'
+ )}
+
{/* Active line where the slash menu fires. The animation imperatively
mutates this node — typing a glyph, swapping role to h1, etc. */}
@@ -663,30 +685,62 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
data-slash-show="all"
className="px-2 pb-1 pt-1.5 text-[9.5px] font-bold uppercase tracking-[0.06em] text-muted-foreground"
>
- {translate("auto.components.feature.wall.EditorAnimatedVisual.1fb29ad710", "Headings")}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.1fb29ad710', 'Headings')}
+
{
rowH1Ref.current = el
}}
iconKey="h1"
- label={translate("auto.components.feature.wall.EditorAnimatedVisual.722170663a", "Heading 1")}
+ label={translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.722170663a',
+ 'Heading 1'
+ )}
shortcut="#"
/>
-
+
- {translate("auto.components.feature.wall.EditorAnimatedVisual.abbdeea15d", "Basic blocks")}
-
-
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.abbdeea15d',
+ 'Basic blocks'
+ )}
+
+
+
{
rowCodeRef.current = el
}}
iconKey="code"
- label={translate("auto.components.feature.wall.EditorAnimatedVisual.8268b2376b", "Code Block")}
+ label={translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.8268b2376b',
+ 'Code Block'
+ )}
shortcut="```"
/>
@@ -714,15 +768,25 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
WorkbenchAnimatedVisual so the workbench sub-steps share a footer
shape. */}
- {translate("auto.components.feature.wall.EditorAnimatedVisual.3fe42a1da0", "Type")}/ {translate("auto.components.feature.wall.EditorAnimatedVisual.8341391520", "for blocks ·")}{' '}
- {boldShortcutLabel} {translate("auto.components.feature.wall.EditorAnimatedVisual.8521536429", "bold ·")}{' '}
- {italicShortcutLabel} {translate("auto.components.feature.wall.EditorAnimatedVisual.7a763daf2f", "italic")}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.3fe42a1da0', 'Type')}
+ / {' '}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.8341391520', 'for blocks ·')}{' '}
+ {boldShortcutLabel} {' '}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.8521536429', 'bold ·')}{' '}
+ {italicShortcutLabel} {' '}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.7a763daf2f', 'italic')}
+
{/* Why: the imperative loop adds .slash-active and toggles
[data-cursor-ripple] state via [data-clicking]. We pin those
presentation rules here instead of TS so the React tree stays
declarative. */}
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx b/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx
index 4e64c143921..0004b27ef2c 100644
--- a/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx
@@ -26,7 +26,7 @@ export function FeatureTourWorkspaceCard({
)}
>
- {status === "working" ? (
+ {status === 'working' ? (
) : (
@@ -43,14 +43,14 @@ export function FeatureTourWorkspaceCard({
{agents.map((agent, idx) => (
- {agent.state === "working" ? (
+ {agent.state === 'working' ? (
) : (
)}
- {agent.kind === "claude" ? (
+ {agent.kind === 'claude' ? (
- ) : agent.kind === "codex" ? (
+ ) : agent.kind === 'codex' ? (
) : (
diff --git a/src/renderer/src/components/feature-wall/FeatureWallBody.tsx b/src/renderer/src/components/feature-wall/FeatureWallBody.tsx
index 1e4511ec7ba..0eb0314d89e 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallBody.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallBody.tsx
@@ -268,7 +268,8 @@ export function FeatureWallBody(props: {
>
<>
- {translate("auto.components.feature.wall.FeatureWallBody.25ec5356d6", "Setup")}
+ {translate('auto.components.feature.wall.FeatureWallBody.25ec5356d6', 'Setup')}
+
{settingContent}
>
diff --git a/src/renderer/src/components/feature-wall/FeatureWallModal.tsx b/src/renderer/src/components/feature-wall/FeatureWallModal.tsx
index d7b599c0222..215ce457643 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallModal.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallModal.tsx
@@ -35,11 +35,20 @@ export default function FeatureWallModal(): JSX.Element | null {
tabIndex={-1}
>
- {translate("auto.components.feature.wall.FeatureWallModal.3567e147c8", "Get to know Orca")}
+
+ {translate(
+ 'auto.components.feature.wall.FeatureWallModal.3567e147c8',
+ 'Get to know Orca'
+ )}
+
{/* Why: Radix requires a description for the dialog to be a11y-compliant,
but we don't want it visible - the rail and step copy already orient users. */}
- {translate("auto.components.feature.wall.FeatureWallModal.33dca8bbbe", "A short, workflow-by-workflow tour of Orca.")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallModal.33dca8bbbe',
+ 'A short, workflow-by-workflow tour of Orca.'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx b/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx
index cd75b437274..db9580d8dc5 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx
@@ -67,7 +67,11 @@ export function RelatedFeatures(props: {
return (
- {translate("auto.components.feature.wall.FeatureWallPreview.a666384798", "Also in this workflow")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallPreview.a666384798',
+ 'Also in this workflow'
+ )}
+
{items.map((tile) => (
diff --git a/src/renderer/src/components/feature-wall/FeatureWallRail.tsx b/src/renderer/src/components/feature-wall/FeatureWallRail.tsx
index 339aa3f7f76..e3224d8ed5d 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallRail.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallRail.tsx
@@ -56,7 +56,7 @@ export function FeatureWallRail(props: {
return (
{FEATURE_WALL_WORKFLOWS.map((workflow, index) => {
@@ -114,7 +114,14 @@ export function FeatureWallRail(props: {
? 'border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300'
: 'border-border bg-card text-muted-foreground'
)}
- aria-label={isDone ? translate("auto.components.feature.wall.FeatureWallRail.69ea857689", "Completed") : undefined}
+ aria-label={
+ isDone
+ ? translate(
+ 'auto.components.feature.wall.FeatureWallRail.69ea857689',
+ 'Completed'
+ )
+ : undefined
+ }
>
{isDone ?
: index + 1}
@@ -155,7 +162,14 @@ export function FeatureWallRail(props: {
? 'border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300'
: 'border-border bg-card text-muted-foreground'
)}
- aria-label={isStepDone ? translate("auto.components.feature.wall.FeatureWallRail.69ea857689", "Completed") : undefined}
+ aria-label={
+ isStepDone
+ ? translate(
+ 'auto.components.feature.wall.FeatureWallRail.69ea857689',
+ 'Completed'
+ )
+ : undefined
+ }
>
{isStepDone ?
: `${label}.`}
diff --git a/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx b/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
index ba36b57d3fc..260f6f4d060 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
@@ -253,7 +253,11 @@ function TaskSourcesAction(): React.JSX.Element {
}}
>
- {translate("auto.components.feature.wall.FeatureWallSetupChecklist.b1f1981c5e", "See tasks")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupChecklist.b1f1981c5e',
+ 'See tasks'
+ )}
+
)
@@ -296,7 +300,10 @@ export function FeatureWallSetupChecklist(
)}
>
- {activeDone ? translate("auto.components.feature.wall.FeatureWallSetupChecklist.13294d3405", "Done") : translate("auto.components.feature.wall.FeatureWallSetupChecklist.0235b268b2", "Not done yet")}
+ {activeDone
+ ? translate(
+ 'auto.components.feature.wall.FeatureWallSetupChecklist.13294d3405',
+ 'Done'
+ )
+ : translate(
+ 'auto.components.feature.wall.FeatureWallSetupChecklist.0235b268b2',
+ 'Not done yet'
+ )}
{activeStep.description}
- {activeStep.id === "split-terminal" ? (
+ {activeStep.id === 'split-terminal' ? (
diff --git a/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx b/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx
index 55c25aed83f..eeb7568ae8b 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx
@@ -46,7 +46,11 @@ export function AddReposAction(): React.JSX.Element {
return (
openModal('add-repo')}>
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.522cce9e33", "Add project")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.522cce9e33',
+ 'Add project'
+ )}
+
)
}
@@ -80,7 +84,11 @@ export function TwoAgentsAction(props: { done: boolean }): React.JSX.Element | n
return (
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77", "Try it out")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77',
+ 'Try it out'
+ )}
+
)
}
@@ -96,8 +104,21 @@ export function SplitTerminalShortcutHint(): React.JSX.Element {
return (
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.971775f639", "Split right with")}{splitRight} {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.29e64f111d", "or down with")}{' '}
- {splitDown} {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.364430eb3d", ", or right-click a pane and choose a split. Close the active pane with")}{closePane} .
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.971775f639',
+ 'Split right with'
+ )}
+ {splitRight} {' '}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.29e64f111d',
+ 'or down with'
+ )}{' '}
+ {splitDown}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.364430eb3d',
+ ', or right-click a pane and choose a split. Close the active pane with'
+ )}
+ {closePane} .
)
@@ -139,7 +160,11 @@ export function WorkspacesAction(props: { done: boolean }): React.JSX.Element |
}}
>
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77", "Try it out")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77',
+ 'Try it out'
+ )}
+
)
}
@@ -197,9 +222,19 @@ export function SetupScriptAction(): React.JSX.Element {
}
const updated = await updateRepo(repo.id, { hookSettings: nextHookSettings })
if (updated) {
- toast.success(translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.6299297dac", "Setup script saved"))
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.6299297dac',
+ 'Setup script saved'
+ )
+ )
} else {
- toast.error(translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.a7463915b6", "Failed to save setup script"))
+ toast.error(
+ translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.a7463915b6',
+ 'Failed to save setup script'
+ )
+ )
}
}, [repo, setupScript, updateRepo])
@@ -210,8 +245,14 @@ export function SetupScriptAction(): React.JSX.Element {
value={setupScript}
disabled={!canConfigure}
onChange={(event) => setSetupScript(event.target.value)}
- placeholder={translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.5c5b65044e", "pnpm install")}
- aria-label={translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.88469e926b", "Setup script")}
+ placeholder={translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.5c5b65044e',
+ 'pnpm install'
+ )}
+ aria-label={translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.88469e926b',
+ 'Setup script'
+ )}
className="font-mono text-sm"
/>
void handleSaveSetupScript()}
>
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.14327073cc", "Save")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.14327073cc',
+ 'Save'
+ )}
+
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.00078a6134", "View in settings")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.00078a6134',
+ 'View in settings'
+ )}
+
{!canConfigure ? (
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.486c2f4d8d", "Add a git project first, then configure the setup script for that repository.")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.486c2f4d8d',
+ 'Add a git project first, then configure the setup script for that repository.'
+ )}
+
) : null}
)
diff --git a/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx b/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx
index b0a1b14233e..93646baa2f8 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx
@@ -116,7 +116,11 @@ export function FeatureWallTourPanel(props: {
{props.activeStepCopy?.optional ? (
- {translate("auto.components.feature.wall.FeatureWallTourPanel.af7d622f6f", "Optional")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallTourPanel.af7d622f6f',
+ 'Optional'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx
index b9f1c60b1f6..c1e0f7ef36f 100644
--- a/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx
@@ -29,9 +29,9 @@ export function ReviewAnimatedVisual(props: {
transform: `translateX(-50%) scale(${scale})`
}}
>
- {activeStepId === "notes" ? (
+ {activeStepId === 'notes' ? (
- ) : activeStepId === "pr-view" ? (
+ ) : activeStepId === 'pr-view' ? (
) : (
diff --git a/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx
index 4835a78a5a5..24c8399761e 100644
--- a/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx
@@ -340,10 +340,19 @@ export function ReviewNotesAnimatedVisual(props: { reducedMotion: boolean }): JS
return (
-
{translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.1eee3a397e", "src/server/migrate.ts (diff)")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.1eee3a397e',
+ 'src/server/migrate.ts (diff)'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.5cb213f967", "AI notes")}{' '}
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.5cb213f967',
+ 'AI notes'
+ )}{' '}
0
@@ -372,26 +381,50 @@ export function ReviewNotesAnimatedVisual(props: { reducedMotion: boolean }): JS
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.a7a89d8f94", "Line")}?
+ {translate('auto.components.feature.wall.ReviewNotesAnimatedVisual.a7a89d8f94', 'Line')}
+ ?
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.271ea0cbf3", "Cancel")}
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.271ea0cbf3',
+ 'Cancel'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.ea4e45b71b", "Add note")}
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.ea4e45b71b',
+ 'Add note'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.294aaff104", "Send notes to")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.294aaff104',
+ 'Send notes to'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.09094f25e2", "Claude Code")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.09094f25e2',
+ 'Claude Code'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.5dbd27c4c2", "Codex")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.5dbd27c4c2',
+ 'Codex'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx
index 1faa973a240..0b2ef880ffa 100644
--- a/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx
@@ -256,7 +256,12 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.cd8a3a39d7", "3 commits ahead")}
+
{' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.cd8a3a39d7',
+ '3 commits ahead'
+ )}
+
@@ -264,18 +269,30 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
type="button"
className="ravs-sc-sparkle"
data-commit-sparkle
- aria-label={translate("auto.components.feature.wall.ReviewShipAnimatedVisual.d1a7f15876", "Generate commit message with AI")}
+ aria-label={translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.d1a7f15876',
+ 'Generate commit message with AI'
+ )}
>
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.7347fa5839", "Message")}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.7347fa5839',
+ 'Message'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.a079083a6c", "Commit")}
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.a079083a6c',
+ 'Commit'
+ )}
+
@@ -283,9 +300,18 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.e725000cd7", "Changes")}{SHIP_FILES.length}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.e725000cd7',
+ 'Changes'
+ )}
+ {SHIP_FILES.length}
+
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.ea0100dd15',
+ 'View all'
+ )}
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.ea0100dd15", "View all")}
{SHIP_FILES.map((name) => (
@@ -302,42 +328,91 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.c30cd930ff", "Create Pull Request")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.c30cd930ff',
+ 'Create Pull Request'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.ce7d5d3a18", "Base branch")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.ce7d5d3a18',
+ 'Base branch'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.3b9b96d6a6", "main")}
+
{' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.3b9b96d6a6',
+ 'main'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.54a093c52d", "Title")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.54a093c52d',
+ 'Title'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.07da9245cc", "Pull request title")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.07da9245cc',
+ 'Pull request title'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.3774b80eae", "Description")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.3774b80eae',
+ 'Description'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.bcd5cae3c4", "Pull request description")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.bcd5cae3c4',
+ 'Pull request description'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.62544e0852", "Cancel")}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.62544e0852',
+ 'Cancel'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.4d99496b8c", "Create PR")}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.4d99496b8c',
+ 'Create PR'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
index acc8db82670..73d711449be 100644
--- a/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
@@ -12,7 +12,15 @@ type Issue = {
title: string
}
-const ISSUES: readonly Issue[] = [{ number: 1842, title: translate("auto.components.feature.wall.TasksAnimatedVisual.b13375617e", "Worktree picker truncates names") }]
+const ISSUES: readonly Issue[] = [
+ {
+ number: 1842,
+ title: translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.b13375617e',
+ 'Worktree picker truncates names'
+ )
+ }
+]
type Phase =
| { kind: 'idle' }
@@ -245,7 +253,11 @@ export function TasksAnimatedVisual(props: { reducedMotion: boolean }): JSX.Elem
{!isActive ? (
- {translate("auto.components.feature.wall.TasksAnimatedVisual.4331c4d0f8", "Open")}
+ {translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.4331c4d0f8',
+ 'Open'
+ )}
+
) : (
- {translate("auto.components.feature.wall.TasksAnimatedVisual.b68c92fbdc", "Start workspace")}
+ {translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.b68c92fbdc',
+ 'Start workspace'
+ )}
+
)}
@@ -280,7 +296,17 @@ export function TasksAnimatedVisual(props: { reducedMotion: boolean }): JSX.Elem
) : (
)}
-
{workspaceCreating ? translate("auto.components.feature.wall.TasksAnimatedVisual.61ffda7601", "Creating workspace") : translate("auto.components.feature.wall.TasksAnimatedVisual.fe47c9c9e8", "Workspace ready")}
+
+ {workspaceCreating
+ ? translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.61ffda7601',
+ 'Creating workspace'
+ )
+ : translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.fe47c9c9e8',
+ 'Workspace ready'
+ )}
+
{workspaceIssue ? (
- {translate("auto.components.feature.wall.TasksAnimatedVisual.efba6f77eb", "Reading issue #")}{workspaceIssue.number}…
+ {translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.efba6f77eb',
+ 'Reading issue #'
+ )}
+ {workspaceIssue.number}…
@@ -319,7 +349,7 @@ export function TasksAnimatedVisual(props: { reducedMotion: boolean }): JSX.Elem
>
- {phase.kind === "pressing" ? : null}
+ {phase.kind === 'pressing' ? : null}
diff --git a/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx
index 26ec6e25b5f..a5c02d28afc 100644
--- a/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx
@@ -511,8 +511,21 @@ export function WorkbenchAnimatedVisual(props: {
/* Standalone keyboard hint stays inside the visual so the tour copy can
remain a single subheader line. */
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.0bc9ad0cd1", "Same pane:")}{splitRightShortcutLabel} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.a2b114dad0", "splits right ·")}{' '}
- {splitDownShortcutLabel} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.16877e038d", "splits down")}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.0bc9ad0cd1',
+ 'Same pane:'
+ )}
+ {splitRightShortcutLabel} {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.a2b114dad0',
+ 'splits right ·'
+ )}{' '}
+ {splitDownShortcutLabel} {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.16877e038d',
+ 'splits down'
+ )}
+
)}
)
@@ -526,18 +539,54 @@ function PlaywrightPane(props: {
<>
$
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.4371cc9931", "pnpm playwright test")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.4371cc9931',
+ 'pnpm playwright test'
+ )}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.0b20782e0f", "Running 12 tests using 4 workers")}
-
-
- 1 {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.defe550fe2", "login.spec.ts")} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.3261c6853b", "› can sign in")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.5c5cbd783f", "(1.2s)")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.0b20782e0f',
+ 'Running 12 tests using 4 workers'
+ )}
- 2 {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.623881d72e", "checkout.spec.ts")} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.944199e54a", "› cart total updates")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.7d9f1d5f7d", "(0.8s)")}
+ 1
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.defe550fe2',
+ 'login.spec.ts'
+ )}
+
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.3261c6853b',
+ '› can sign in'
+ )}
+
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.5c5cbd783f', '(1.2s)')}
+
+
+
+
+ 2
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.623881d72e',
+ 'checkout.spec.ts'
+ )}
+
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.944199e54a',
+ '› cart total updates'
+ )}
+
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.7d9f1d5f7d', '(0.8s)')}
+
@@ -554,30 +603,63 @@ function ClaudeChecklistPane(props: { reducedMotion: boolean }): JSX.Element {
<>
$
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.000106adfe", "claude")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.000106adfe', 'claude')}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a", "Claude Code session started")}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a',
+ 'Claude Code session started'
+ )}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97", ">")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.c0eb94125e", "review auth edge cases")}
-
- ✓
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.9923847785", "Read")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd", "src/auth/session.ts")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97', '>')}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.c0eb94125e',
+ 'review auth edge cases'
+ )}
✓
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.17cfdc3344", "Grep")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.0d93c298a7", "throw src/auth")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.9923847785', 'Read')}
+
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd',
+ 'src/auth/session.ts'
+ )}
+
+
+
+ ✓
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.17cfdc3344', 'Grep')}
+
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.0d93c298a7',
+ 'throw src/auth'
+ )}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.99f5224f1e", "Edit")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd", "src/auth/session.ts")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.99f5224f1e', 'Edit')}
+
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd',
+ 'src/auth/session.ts'
+ )}
+
>
)
@@ -666,7 +748,12 @@ function ContextMenu(props: {
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.e370fa8c2b", "Split Terminal Right")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.e370fa8c2b',
+ 'Split Terminal Right'
+ )}
+
{props.splitRightShortcutLabel}
@@ -675,7 +762,12 @@ function ContextMenu(props: {
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.ca2cfbf188", "Split Terminal Down")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.ca2cfbf188',
+ 'Split Terminal Down'
+ )}
+
{props.splitDownShortcutLabel}
@@ -729,7 +821,15 @@ function RightPaneScrollback(props: {
) : (
●
)}
- {props.isCodex ? translate("auto.components.feature.wall.WorkbenchAnimatedVisual.fc84f17fe7", "Codex session started") : translate("auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a", "Claude Code session started")}
+ {props.isCodex
+ ? translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.fc84f17fe7',
+ 'Codex session started'
+ )
+ : translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a',
+ 'Claude Code session started'
+ )}
)
}
@@ -737,7 +837,8 @@ function RightPaneScrollback(props: {
return (
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97", ">")}
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97', '>')}
+
{line.text}
)
@@ -746,7 +847,12 @@ function RightPaneScrollback(props: {
return (
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.633a91e358", "Thinking…")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.633a91e358',
+ 'Thinking…'
+ )}
+
)
}
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
index de119416ab6..0ef1cd631ef 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
@@ -320,10 +320,18 @@ export function OrchestrationPage(props: {
- {translate("auto.components.feature.wall.agents.orchestration.OrchestrationPage.30b509a467", "2 children")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.OrchestrationPage.30b509a467',
+ '2 children'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
index 87d1e84260d..a32fd8c38f9 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
@@ -71,7 +71,15 @@ function ProviderRow(props: {
) : (
)}
- {isAdding ? translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.945865332e", "Signing in") : translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.29d0653961", "Sign in")}
+ {isAdding
+ ? translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.945865332e',
+ 'Signing in'
+ )
+ : translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.29d0653961',
+ 'Sign in'
+ )}
)}
@@ -154,14 +162,25 @@ export function UsageAccountsCard(props: {
if (mountedRef.current) {
await onAccountStateChange?.()
if (mountedRef.current) {
- toast.success(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.9ddeb558f9", "Claude account added."))
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.9ddeb558f9',
+ 'Claude account added.'
+ )
+ )
}
}
} catch (error) {
if (mountedRef.current) {
- toast.error(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.4e71d72912", "Claude sign-in failed."), {
- description: String((error as Error)?.message ?? error)
- })
+ toast.error(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.4e71d72912',
+ 'Claude sign-in failed.'
+ ),
+ {
+ description: String((error as Error)?.message ?? error)
+ }
+ )
}
} finally {
if (mountedRef.current) {
@@ -184,14 +203,25 @@ export function UsageAccountsCard(props: {
if (mountedRef.current) {
await onAccountStateChange?.()
if (mountedRef.current) {
- toast.success(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.c7b90c140b", "Codex account added."))
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.c7b90c140b',
+ 'Codex account added.'
+ )
+ )
}
}
} catch (error) {
if (mountedRef.current) {
- toast.error(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.8919321417", "Codex sign-in failed."), {
- description: String((error as Error)?.message ?? error)
- })
+ toast.error(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.8919321417',
+ 'Codex sign-in failed.'
+ ),
+ {
+ description: String((error as Error)?.message ?? error)
+ }
+ )
}
} finally {
if (mountedRef.current) {
@@ -205,7 +235,10 @@ export function UsageAccountsCard(props: {
}
name="Claude"
- description={translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.d90d2e1f6d", "Track session and weekly usage.")}
+ description={translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.d90d2e1f6d',
+ 'Track session and weekly usage.'
+ )}
connected={claudeConnection.connected}
connectionLabel={claudeConnection.label}
isAdding={claudeAction === 'adding'}
@@ -214,7 +247,10 @@ export function UsageAccountsCard(props: {
}
name="Codex"
- description={translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.6986b36708", "Surface rate limits and swap accounts inline.")}
+ description={translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.6986b36708',
+ 'Surface rate limits and swap accounts inline.'
+ )}
connected={codexConnection.connected}
connectionLabel={codexConnection.label}
isAdding={codexAction === 'adding'}
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx
index 4842403242a..faac3d45669 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx
@@ -98,13 +98,26 @@ function Popover(props: {
-
{translate("auto.components.feature.wall.agents.orchestration.UsagePage.6a4b1d3c38", "Codex")}
-
{translate("auto.components.feature.wall.agents.orchestration.UsagePage.5e45fb1238", "Updated 1m ago")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.6a4b1d3c38',
+ 'Codex'
+ )}
+
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.5e45fb1238',
+ 'Updated 1m ago'
+ )}
+
{sessionResetText}}
/>
{translate("auto.components.feature.wall.agents.orchestration.UsagePage.05ce4ecdd3", "62% left")}}
- metaRight={{translate("auto.components.feature.wall.agents.orchestration.UsagePage.4dce5ca3aa", "Resets in 4d 3h")} }
+ metaLeft={
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.05ce4ecdd3',
+ '62% left'
+ )}
+
+ }
+ metaRight={
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.4dce5ca3aa',
+ 'Resets in 4d 3h'
+ )}
+
+ }
/>
- {translate("auto.components.feature.wall.agents.orchestration.UsagePage.277a9c65a9", "Codex Account")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.277a9c65a9',
+ 'Codex Account'
+ )}
+
- {translate("auto.components.feature.wall.agents.orchestration.UsagePage.be5a165875", "Switch to")}
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.be5a165875',
+ 'Switch to'
+ )}
+
- {translate("auto.components.feature.wall.agents.orchestration.UsagePage.64265cb295", "71% 5h")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.64265cb295',
+ '71% 5h'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx
index 4e435a7ef9f..69fb4cd816f 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx
@@ -83,7 +83,7 @@ export function AgentRow(props: {
width: 'var(--feature-wall-agent-status-box, 16px)'
}}
>
- {state === "working" ? (
+ {state === 'working' ? (
) : (
0) {
- return { connected: true, label: translate("auto.components.feature.wall.feature.wall.usage.tracking.00087eecb2", "Connected · {{value0}}", { value0: args.managedAccountCount }) }
+ return {
+ connected: true,
+ label: translate(
+ 'auto.components.feature.wall.feature.wall.usage.tracking.00087eecb2',
+ 'Connected · {{value0}}',
+ { value0: args.managedAccountCount }
+ )
+ }
}
if (hasFeatureWallProviderUsageTracking(args.provider)) {
- return { connected: true, label: translate("auto.components.feature.wall.feature.wall.usage.tracking.cc39a87288", "Connected · System default") }
+ return {
+ connected: true,
+ label: translate(
+ 'auto.components.feature.wall.feature.wall.usage.tracking.cc39a87288',
+ 'Connected · System default'
+ )
+ }
+ }
+ return {
+ connected: false,
+ label: translate(
+ 'auto.components.feature.wall.feature.wall.usage.tracking.b94ec70eda',
+ 'Tracking not set up'
+ )
}
- return { connected: false, label: translate("auto.components.feature.wall.feature.wall.usage.tracking.b94ec70eda", "Tracking not set up") }
}
export function hasFeatureWallUsageTracking(args: {
diff --git a/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx b/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx
index 30833664c4b..babac2445d6 100644
--- a/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx
+++ b/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx
@@ -7,6 +7,11 @@ import { translate } from '@/i18n/i18n'
// to keep each file under the per-file line-length lint cap.
export function ReviewNotesVisualStyles(): JSX.Element {
return (
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx b/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx
index fc9cef58f90..eab0088113a 100644
--- a/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx
+++ b/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx
@@ -5,6 +5,11 @@ import { translate } from '@/i18n/i18n'
// animation logic stays under the project max-lines lint cap.
export function ReviewPRViewVisualStyles(): JSX.Element {
return (
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx b/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx
index 25e583aee58..4690370c4d8 100644
--- a/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx
+++ b/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx
@@ -168,7 +168,15 @@ export function ChevDownIcon(): JSX.Element {
export function ClaudeLogo(): JSX.Element {
return (
-
+
+
{translate("auto.components.feature.wall.review.animated.visual.ship.styles.90cdcd2ecc", ".ravs-ship-root { position: absolute; inset: 0; } .ravs-ship-stack { position: absolute; inset: 0; display: grid; grid-template-columns: 232px minmax(0,1fr); gap: 14px; padding: 4px 2px; /* Why: cards size to their content rather than stretch to the parent's full height, so the two cards don't show empty space below their content. */ align-items: start; } /* Source Control mini-sidebar — ahead-count header, commit textarea + split Commit button, then a CHANGES section with file rows. The file rows are the surface the \"reading\" pulse animates over. */ .ravs-sc-card { display: flex; flex-direction: column; background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } /* Both card headers share the same fixed height so the SC card and PR dialog align across the top edge regardless of header content. */ .ravs-sc-header, .ravs-pr-head { height: 36px; box-sizing: border-box; } .ravs-sc-header { display: flex; align-items: center; justify-content: space-between; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-sc-ahead { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } .ravs-sc-ahead svg { color: var(--muted-foreground, #71717a); } .ravs-sc-commit-area { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; } .ravs-sc-textarea { position: relative; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); padding: 6px 26px 6px 8px; min-height: 56px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-sc-textarea .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-sc-sparkle { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; transition: color 160ms ease, background 160ms ease; } .ravs-sc-sparkle.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-sc-split { display: flex; align-items: stretch; } /* Why: Commit + Create PR are surrounding chrome — the violet AI affordances are the focal points. Render them as quiet secondary buttons so they don't compete with the sparkle/scan signals. */ .ravs-sc-split .ravs-primary { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 5px 10px; background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); font-size: 11px; font-weight: 500; border-radius: 6px 0 0 6px; border: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } .ravs-sc-split .ravs-chev { display: inline-flex; align-items: center; justify-content: center; width: 22px; background: var(--secondary, #f5f5f5); color: var(--muted-foreground, #71717a); border-radius: 0 6px 6px 0; border: 1px solid var(--border); border-left: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } /* Why: when AI has filled the commit message, tint the Commit button green to signal \"ready to commit\". Uses the same success-green family as the PR flash so the two beats rhyme. Mix is intentionally strong (~28%) — at 14% it disappeared next to the violet sparkle and PR flash, so users only saw the PR change color. */ .ravs-sc-split.is-ready .ravs-primary, .ravs-sc-split.is-ready .ravs-chev { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); transition: background 220ms ease, border-color 220ms ease, color 220ms ease; } .ravs-sc-split.is-ready .ravs-chev { border-left-color: rgba(34, 197, 94, 0.55); } .ravs-sc-changes-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-sc-changes-count { color: var(--foreground, #18181b); font-weight: 600; margin-left: 2px; } .ravs-sc-view-all { font-size: 10px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted-foreground, #71717a); } .ravs-sc-files { display: flex; flex-direction: column; padding: 2px 6px 8px; flex: 1; min-height: 0; overflow: hidden; } .ravs-sc-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 12px; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 4px; font-size: 11px; line-height: 1.35; color: var(--foreground, #18181b); position: relative; transition: background 220ms ease; } .ravs-sc-ficon { color: rgb(180 83 9); display: inline-flex; } .ravs-sc-fname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ravs-sc-fmark { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; text-align: right; color: rgb(180 83 9); } .ravs-sc-file.is-reading { background: color-mix(in srgb, rgb(139 92 246) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, rgb(139 92 246) 28%, transparent); } /* PR dialog — matches the .ravs-sc-card chrome (same border, radius, elevation) so the two cards read as one design language. */ .ravs-pr-dialog { background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 1px 2px rgba(24,24,27,0.04); display: flex; flex-direction: column; min-width: 0; overflow: hidden; } .ravs-pr-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-pr-title-text { font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } /* Icon-only AI-assist chip — mirrors .ravs-sc-sparkle so the affordance reads identically across both cards. */ .ravs-pr-gen-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; border: 0; cursor: pointer; transition: color 160ms ease, background 160ms ease; } .ravs-pr-gen-btn:hover { background: rgba(24,24,27,0.06); color: var(--foreground, #18181b); } .ravs-pr-gen-btn.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-pr-body { display: flex; flex-direction: column; gap: 8px; padding: 10px; } .ravs-pr-field { display: flex; flex-direction: column; gap: 4px; } .ravs-pr-field-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-pr-base { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 6px; font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground, #18181b); background: var(--editor-surface, var(--card)); align-self: flex-start; } .ravs-pr-base svg { color: var(--muted-foreground, #71717a); } .ravs-pr-input { position: relative; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); min-height: 28px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pr-input.is-body { min-height: 50px; font-size: 11px; line-height: 1.4; } .ravs-pr-input .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-pr-footer { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 2px; } .ravs-pr-btn { font-size: 11px; font-weight: 500; padding: 5px 10px; border-radius: 6px; line-height: 1; border: 1px solid transparent; outline: none; } .ravs-pr-btn:focus, .ravs-pr-btn:focus-visible { outline: none; } /* Cancel reads as a quiet ghost button so it doesn't compete with the affirmative Create PR action. */ .ravs-pr-btn.is-outline { background: transparent; color: var(--muted-foreground, #71717a); border-color: transparent; } .ravs-pr-btn.is-outline:hover { background: rgba(24,24,27,0.05); color: var(--foreground, #18181b); } /* Quiet secondary fill — see the .ravs-sc-split note above. The flash ring still uses success-green so the \"PR created\" beat reads. The Create-PR button is slightly larger than Cancel so the affirmative action remains the bigger target. */ .ravs-pr-btn.is-solid { background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); border-color: var(--border); font-size: 12px; padding: 7px 14px; transition: background 220ms ease, border-color 220ms ease, color 220ms ease, box-shadow 220ms ease; } .ravs-pr-btn.is-solid.is-ready { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); } .ravs-pr-btn.is-solid.is-flash { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.30); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }")}
+
)
}
diff --git a/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx b/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx
index 20f100cc444..c5c476a39d2 100644
--- a/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx
+++ b/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx
@@ -82,7 +82,11 @@ export function ReviewDiffRows(): JSX.Element {
- {translate("auto.components.feature.wall.review.notes.diff.rows.f621c734f8", "Note · line")}?
+ {translate(
+ 'auto.components.feature.wall.review.notes.diff.rows.f621c734f8',
+ 'Note · line'
+ )}
+ ?
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
index 302d7037ed1..8947efc01f3 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
@@ -42,13 +42,19 @@ export function FloatingTerminalIconContextMenu({
if (currentLocation === 'floating-button') {
return {
icon:
,
- label: translate("auto.components.floating.terminal.FloatingTerminalIconContextMenu.0ee79e0674", "Move to Status Bar"),
+ label: translate(
+ 'auto.components.floating.terminal.FloatingTerminalIconContextMenu.0ee79e0674',
+ 'Move to Status Bar'
+ ),
location: 'status-bar' as const
}
}
return {
icon:
,
- label: translate("auto.components.floating.terminal.FloatingTerminalIconContextMenu.763f5fa2c1", "Move to Floating Button"),
+ label: translate(
+ 'auto.components.floating.terminal.FloatingTerminalIconContextMenu.763f5fa2c1',
+ 'Move to Floating Button'
+ ),
location: 'floating-button' as const
}
}, [currentLocation])
@@ -105,11 +111,16 @@ export function FloatingTerminalIconContextMenu({
{
+ useAppStore.getState().recordFeatureInteraction('floating-workspace-hidden')
void updateSettings({ floatingTerminalEnabled: false })
}}
>
- {translate("auto.components.floating.terminal.FloatingTerminalIconContextMenu.8e7d775287", "Hide Floating Workspace")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalIconContextMenu.8e7d775287',
+ 'Hide Floating Workspace'
+ )}
+
>
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx
index af9efbac037..e16de1e41ef 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx
@@ -57,22 +57,52 @@ export function FloatingTerminalOrchestrationDialog({
{/* Why: the panel renders with hideHeader, so the modal owns the title
and status pill — avoiding a duplicate heading inside the modal. */}
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.543f325a14", "Enable orchestration")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.543f325a14',
+ 'Enable orchestration'
+ )}
+
{orchestrationSkillLoading && !orchestrationSkillDetected ? (
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.dfd021ce46", "Checking...")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.dfd021ce46',
+ 'Checking...'
+ )}
+
) : orchestrationSkillDetected ? (
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.630c0ac8c8", "Installed")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.630c0ac8c8',
+ 'Installed'
+ )}
+
) : (
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.05d7aabc20", "Not installed")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.05d7aabc20',
+ 'Not installed'
+ )}
+
)}
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.6f0aed26b8", "Install the Orca CLI and orchestration skill so agents can coordinate through Orca.")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.6f0aed26b8',
+ 'Install the Orca CLI and orchestration skill so agents can coordinate through Orca.'
+ )}
+
-
{translate("auto.components.floating.terminal.FloatingTerminalToggleButton.bfe7809a70", "{{value0}} floating workspace ({{value1}})", { value0: open ? 'Minimize' : 'Show', value1: shortcutLabel })}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalToggleButton.bfe7809a70',
+ '{{value0}} floating workspace ({{value1}})',
+ { value0: open ? 'Minimize' : 'Show', value1: shortcutLabel }
+ )}
+
)
diff --git a/src/renderer/src/components/github-pr-merge-state.ts b/src/renderer/src/components/github-pr-merge-state.ts
index 7c8f90318ba..071e0270550 100644
--- a/src/renderer/src/components/github-pr-merge-state.ts
+++ b/src/renderer/src/components/github-pr-merge-state.ts
@@ -58,58 +58,85 @@ export function presentGitHubPRMergeState(
: item.autoMergeEnabled === true
? {
kind: 'disable' as const,
- label: translate("auto.components.github.pr.merge.state.48d75ae118", "Disable auto-merge"),
- tooltip: translate("auto.components.github.pr.merge.state.62703b1dc4", "GitHub auto-merge is enabled for this pull request")
+ label: translate(
+ 'auto.components.github.pr.merge.state.48d75ae118',
+ 'Disable auto-merge'
+ ),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.62703b1dc4',
+ 'GitHub auto-merge is enabled for this pull request'
+ )
}
: item.mergeQueueRequired === true
? {
kind: 'enable' as const,
- label: translate("auto.components.github.pr.merge.state.b169f943e1", "Merge when ready"),
- tooltip: translate("auto.components.github.pr.merge.state.331ebe1170", "Add this pull request to the GitHub merge queue")
+ label: translate(
+ 'auto.components.github.pr.merge.state.b169f943e1',
+ 'Merge when ready'
+ ),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.331ebe1170',
+ 'Add this pull request to the GitHub merge queue'
+ )
}
: null
if (item.state === 'merged') {
return {
- label: translate("auto.components.github.pr.merge.state.83ecdbb4a6", "Merged"),
+ label: translate('auto.components.github.pr.merge.state.83ecdbb4a6', 'Merged'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.62eb8d39da", "This pull request is already merged"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.62eb8d39da',
+ 'This pull request is already merged'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.state === 'closed') {
return {
- label: translate("auto.components.github.pr.merge.state.4f976d3450", "Closed"),
+ label: translate('auto.components.github.pr.merge.state.4f976d3450', 'Closed'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.820fd21663", "This pull request is closed"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.820fd21663',
+ 'This pull request is closed'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.state === 'draft') {
return {
- label: translate("auto.components.github.pr.merge.state.ec8e2cebaa", "Draft"),
+ label: translate('auto.components.github.pr.merge.state.ec8e2cebaa', 'Draft'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.f03028e055", "This pull request is still a draft"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.f03028e055',
+ 'This pull request is still a draft'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.reviewDecision === 'REVIEW_REQUIRED') {
return {
- label: translate("auto.components.github.pr.merge.state.1f8eb81c0e", "Approval required"),
+ label: translate('auto.components.github.pr.merge.state.1f8eb81c0e', 'Approval required'),
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.a20db875ed", "GitHub requires review approval before this pull request can merge"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.a20db875ed',
+ 'GitHub requires review approval before this pull request can merge'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.reviewDecision === 'CHANGES_REQUESTED') {
return {
- label: translate("auto.components.github.pr.merge.state.c606463dc2", "Changes requested"),
+ label: translate('auto.components.github.pr.merge.state.c606463dc2', 'Changes requested'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.b289646bcd", "GitHub reports requested changes on this pull request"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.b289646bcd',
+ 'GitHub reports requested changes on this pull request'
+ ),
directMergeAvailable: false,
autoMergeAction
}
@@ -118,43 +145,58 @@ export function presentGitHubPRMergeState(
return {
label: item.autoMergeEnabled ? 'Auto-merge on' : 'Merge when ready',
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.35ec24bc43", "This base branch uses GitHub merge queue"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.35ec24bc43',
+ 'This base branch uses GitHub merge queue'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (!hasFullMergeMetadata(item)) {
return {
- label: translate("auto.components.github.pr.merge.state.bd4f27b50e", "Merge"),
+ label: translate('auto.components.github.pr.merge.state.bd4f27b50e', 'Merge'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.09896aad26", "Merge status is unavailable for this PR"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.09896aad26',
+ 'Merge status is unavailable for this PR'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.mergeable === 'CONFLICTING' || item.mergeStateStatus === 'DIRTY') {
return {
- label: translate("auto.components.github.pr.merge.state.7e8bbe3cd7", "Conflicts"),
+ label: translate('auto.components.github.pr.merge.state.7e8bbe3cd7', 'Conflicts'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.b37d45bca9", "GitHub reports merge conflicts"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.b37d45bca9',
+ 'GitHub reports merge conflicts'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.mergeStateStatus === 'BEHIND') {
return {
- label: translate("auto.components.github.pr.merge.state.039c072f94", "Behind"),
+ label: translate('auto.components.github.pr.merge.state.039c072f94', 'Behind'),
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.c614e2660a", "Update the branch before merging"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.c614e2660a',
+ 'Update the branch before merging'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.mergeStateStatus === 'BLOCKED') {
return {
- label: translate("auto.components.github.pr.merge.state.bf5e4c6c92", "Blocked"),
+ label: translate('auto.components.github.pr.merge.state.bf5e4c6c92', 'Blocked'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.1766eb46ba", "GitHub reports this pull request is blocked"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.1766eb46ba',
+ 'GitHub reports this pull request is blocked'
+ ),
directMergeAvailable: false,
autoMergeAction
}
@@ -164,15 +206,24 @@ export function presentGitHubPRMergeState(
const checkStatus =
checkState === 'failure'
? {
- label: translate("auto.components.github.pr.merge.state.87fa36ac83", "Checks failed"),
+ label: translate('auto.components.github.pr.merge.state.87fa36ac83', 'Checks failed'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.1432ecff30", "GitHub says this PR can merge, but some checks failed")
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.1432ecff30',
+ 'GitHub says this PR can merge, but some checks failed'
+ )
}
: checkState === 'pending'
? {
- label: translate("auto.components.github.pr.merge.state.4e2507176b", "Checks pending"),
+ label: translate(
+ 'auto.components.github.pr.merge.state.4e2507176b',
+ 'Checks pending'
+ ),
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.9bd983ce8f", "GitHub says this PR can merge, but checks are still running")
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.9bd983ce8f',
+ 'GitHub says this PR can merge, but checks are still running'
+ )
}
: null
return {
@@ -188,9 +239,12 @@ export function presentGitHubPRMergeState(
}
}
return {
- label: translate("auto.components.github.pr.merge.state.f958920f3a", "Checking"),
+ label: translate('auto.components.github.pr.merge.state.f958920f3a', 'Checking'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.a80132573b", "GitHub is still computing this pull request merge status"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.a80132573b',
+ 'GitHub is still computing this pull request merge status'
+ ),
directMergeAvailable: false,
autoMergeAction
}
diff --git a/src/renderer/src/components/github-project/ColumnResizeHandle.tsx b/src/renderer/src/components/github-project/ColumnResizeHandle.tsx
index bd1f70d27b3..cd7f6c95920 100644
--- a/src/renderer/src/components/github-project/ColumnResizeHandle.tsx
+++ b/src/renderer/src/components/github-project/ColumnResizeHandle.tsx
@@ -75,7 +75,10 @@ export default function ColumnResizeHandle({
ref={handleRef}
role="separator"
aria-orientation="vertical"
- aria-label={translate("auto.components.github.project.ColumnResizeHandle.1304289353", "Resize column")}
+ aria-label={translate(
+ 'auto.components.github.project.ColumnResizeHandle.1304289353',
+ 'Resize column'
+ )}
onMouseDown={(e) => {
if (e.button !== 0) {
return
diff --git a/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx b/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx
index bfc5e3bd4f2..9131094bdc7 100644
--- a/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx
+++ b/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx
@@ -40,12 +40,18 @@ function reloadOrcaRenderer(): void {
function findEnvVarCommand(varName: string): { label: string; command: string } {
if (IS_WINDOWS) {
return {
- label: translate("auto.components.github.project.GhAuthErrorHelp.df636f5886", "Check if it’s set (PowerShell)"),
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.df636f5886',
+ 'Check if it’s set (PowerShell)'
+ ),
command: `Get-ChildItem Env:${varName}`
}
}
return {
- label: translate("auto.components.github.project.GhAuthErrorHelp.ae43542893", "Find where it’s set"),
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.ae43542893',
+ 'Find where it’s set'
+ ),
command: `grep -RIn '${varName}' ~/.zshrc ~/.zshenv ~/.bashrc ~/.bash_profile ~/.profile ~/.config 2>/dev/null`
}
}
@@ -55,11 +61,20 @@ function unsetEnvVarCommand(varName: string): { label: string; command: string }
// Persistent removal at the user scope; the user still needs a fresh
// shell/Orca relaunch for the change to take effect.
return {
- label: translate("auto.components.github.project.GhAuthErrorHelp.fd17b3019f", "Unset (PowerShell, persistent)"),
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.fd17b3019f',
+ 'Unset (PowerShell, persistent)'
+ ),
command: `Remove-Item Env:${varName}; [Environment]::SetEnvironmentVariable('${varName}', $null, 'User')`
}
}
- return { label: translate("auto.components.github.project.GhAuthErrorHelp.891a7d4616", "Unset for this shell"), command: `unset ${varName}` }
+ return {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.891a7d4616',
+ 'Unset for this shell'
+ ),
+ command: `unset ${varName}`
+ }
}
function openExternal(url: string): void {
@@ -72,9 +87,13 @@ function openExternal(url: string): void {
async function copyToClipboard(text: string): Promise
{
try {
await window.api.ui.writeClipboardText(text)
- toast.success(translate("auto.components.github.project.GhAuthErrorHelp.224c9d0ae8", "Copied to clipboard"))
+ toast.success(
+ translate('auto.components.github.project.GhAuthErrorHelp.224c9d0ae8', 'Copied to clipboard')
+ )
} catch {
- toast.error(translate("auto.components.github.project.GhAuthErrorHelp.8a7f6bf5dc", "Failed to copy"))
+ toast.error(
+ translate('auto.components.github.project.GhAuthErrorHelp.8a7f6bf5dc', 'Failed to copy')
+ )
}
}
@@ -100,7 +119,13 @@ function buildRemediation(
return {
summary: errorMessage,
commands: [
- { label: translate("auto.components.github.project.GhAuthErrorHelp.b436c586d1", "Copy command"), command: kind === 'auth_required' ? LOGIN_CMD : REFRESH_CMD }
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.b436c586d1',
+ 'Copy command'
+ ),
+ command: kind === 'auth_required' ? LOGIN_CMD : REFRESH_CMD
+ }
]
}
}
@@ -110,7 +135,15 @@ function buildRemediation(
summary: 'GitHub CLI (`gh`) is not installed or not on PATH.',
detail:
'Orca uses `gh` to talk to GitHub Projects. Install it from cli.github.com, then sign in.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.9c2da6353b", "Copy login command"), command: LOGIN_CMD }],
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.9c2da6353b',
+ 'Copy login command'
+ ),
+ command: LOGIN_CMD
+ }
+ ],
docsUrl: 'https://cli.github.com/'
}
}
@@ -152,7 +185,15 @@ function buildRemediation(
if (kind === 'auth_required' || !active) {
return {
summary: 'You’re not signed in to GitHub via `gh`.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.9c2da6353b", "Copy login command"), command: LOGIN_CMD }]
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.9c2da6353b',
+ 'Copy login command'
+ ),
+ command: LOGIN_CMD
+ }
+ ]
}
}
@@ -166,7 +207,15 @@ function buildRemediation(
)} scope${diag.missingScopes.length === 1 ? '' : 's'} needed for GitHub Projects.`,
detail:
'Run the refresh command in a terminal. It will open a browser to authorize the new scopes, then come back here and reload.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.3fefeebde4", "Copy refresh command"), command: REFRESH_CMD }]
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.3fefeebde4',
+ 'Copy refresh command'
+ ),
+ command: REFRESH_CMD
+ }
+ ]
}
}
@@ -177,7 +226,15 @@ function buildRemediation(
summary: errorMessage,
detail:
'Your token has the required scopes but GitHub still denied access. If the project is in an org with SAML SSO, you must authorize this token for the org under Settings → Developer settings → Personal access tokens → Configure SSO.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.3fefeebde4", "Copy refresh command"), command: REFRESH_CMD }],
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.3fefeebde4',
+ 'Copy refresh command'
+ ),
+ command: REFRESH_CMD
+ }
+ ],
docsUrl:
'https://docs.github.com/en/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on'
}
@@ -233,7 +290,9 @@ export function GhAuthErrorHelp({
onClick={() => openExternal(docsUrl)}
className="inline-flex items-center gap-1 rounded border border-amber-500/30 px-1.5 py-0.5 text-[11px] hover:bg-amber-500/20"
>
- {translate("auto.components.github.project.GhAuthErrorHelp.baa006f9af", "Docs")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.baa006f9af', 'Docs')}
+
) : null}
{/* Why: after running the refresh command in a terminal, users need to
reload the renderer to pick up the new gh token state. */}
@@ -242,7 +301,9 @@ export function GhAuthErrorHelp({
onClick={reloadOrcaRenderer}
className="inline-flex items-center gap-1 rounded border border-amber-500/30 px-1.5 py-0.5 text-[11px] hover:bg-amber-500/20"
>
- {translate("auto.components.github.project.GhAuthErrorHelp.7e800068d8", "Reload")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.7e800068d8', 'Reload')}
+
)
@@ -266,12 +327,16 @@ export function GhAuthErrorHelp({
))}
{docsUrl ? (
openExternal(docsUrl)}>
- {translate("auto.components.github.project.GhAuthErrorHelp.baa006f9af", "Docs")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.baa006f9af', 'Docs')}
+
) : null}
{/* Why: after running the refresh command in a terminal, users need to
reload the renderer to pick up the new gh token state. */}
- {translate("auto.components.github.project.GhAuthErrorHelp.7e800068d8", "Reload")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.7e800068d8', 'Reload')}
+
)
diff --git a/src/renderer/src/components/github-project/ProjectCell.tsx b/src/renderer/src/components/github-project/ProjectCell.tsx
index afc1ee4d153..0f916be3ae7 100644
--- a/src/renderer/src/components/github-project/ProjectCell.tsx
+++ b/src/renderer/src/components/github-project/ProjectCell.tsx
@@ -112,7 +112,7 @@ export default function ProjectCell({
{
if (next === '') {
onEditField?.(field.id, null)
@@ -130,7 +130,10 @@ export default function ProjectCell({
value={num}
editable={editable && !isRedacted}
numeric
- placeholder={translate("auto.components.github.project.ProjectCell.bb7ebc11e3", "Add number")}
+ placeholder={translate(
+ 'auto.components.github.project.ProjectCell.bb7ebc11e3',
+ 'Add number'
+ )}
onCommit={(next) => {
if (next === '') {
onEditField?.(field.id, null)
@@ -194,7 +197,9 @@ function TitleCell({
return (
- {translate("auto.components.github.project.ProjectCell.af5d8c912a", "Restricted item")}
+
+ {translate('auto.components.github.project.ProjectCell.af5d8c912a', 'Restricted item')}
+
)
}
@@ -203,7 +208,7 @@ function TitleCell({
// already read as issues), so it's omitted.
const content = (
- {row.itemType === "PULL_REQUEST" ? (
+ {row.itemType === 'PULL_REQUEST' ? (
) : null}
{row.content.number != null ? (
@@ -245,10 +250,19 @@ function TypeCell({
}
const meta =
row.itemType === 'PULL_REQUEST'
- ? { Icon: GitPullRequest, label: translate("auto.components.github.project.ProjectCell.d0d0e13a5a", "PR") }
+ ? {
+ Icon: GitPullRequest,
+ label: translate('auto.components.github.project.ProjectCell.d0d0e13a5a', 'PR')
+ }
: row.itemType === 'DRAFT_ISSUE'
- ? { Icon: FileText, label: translate("auto.components.github.project.ProjectCell.6efdc0d920", "Draft") }
- : { Icon: Lock, label: translate("auto.components.github.project.ProjectCell.8d669084f6", "Restricted") }
+ ? {
+ Icon: FileText,
+ label: translate('auto.components.github.project.ProjectCell.6efdc0d920', 'Draft')
+ }
+ : {
+ Icon: Lock,
+ label: translate('auto.components.github.project.ProjectCell.8d669084f6', 'Restricted')
+ }
const { Icon, label } = meta
return (
@@ -325,7 +339,9 @@ function IssueTypeCell({
)
})()
) : (
- {translate("auto.components.github.project.ProjectCell.c5f949e489", "Issue")}
+
+ {translate('auto.components.github.project.ProjectCell.c5f949e489', 'Issue')}
+
)}
)
@@ -339,7 +355,10 @@ function IssueTypeCell({
{trigger}
@@ -347,12 +366,23 @@ function IssueTypeCell({
{!owner || !repo ? (
- {translate("auto.components.github.project.ProjectCell.54cac64427", "Row has no repo slug.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.54cac64427',
+ 'Row has no repo slug.'
+ )}
+
) : loading ? (
- {translate("auto.components.github.project.ProjectCell.2219e945ef", "Loading…")}
+
+ {translate('auto.components.github.project.ProjectCell.2219e945ef', 'Loading…')}
+
) : options.length === 0 ? (
- {translate("auto.components.github.project.ProjectCell.943b3dadc9", "This repo has no Issue Types.")}
+ {translate(
+ 'auto.components.github.project.ProjectCell.943b3dadc9',
+ 'This repo has no Issue Types.'
+ )}
+
) : (
options.map((t) => (
- {translate("auto.components.github.project.ProjectCell.ebde486e3c", "Clear")}
+ {translate('auto.components.github.project.ProjectCell.ebde486e3c', 'Clear')}
+
) : null}
@@ -441,7 +472,11 @@ function SingleSelectCell({
aria-label={field.name}
className="flex h-full w-full cursor-pointer items-center px-1 text-left"
>
- {label ?? }
+ {label ?? (
+
+ )}
@@ -470,7 +505,8 @@ function SingleSelectCell({
setOpen(false)
}}
>
- {translate("auto.components.github.project.ProjectCell.ebde486e3c", "Clear")}
+ {translate('auto.components.github.project.ProjectCell.ebde486e3c', 'Clear')}
+
)
@@ -509,13 +545,18 @@ function IterationCell({
aria-label={field.name}
className="flex h-full w-full cursor-pointer items-center px-1 text-left"
>
- {label ?? }
+ {label ?? (
+
+ )}
{completed.length > 0 ? (
- {translate("auto.components.github.project.ProjectCell.e17bb96881", "Completed")}
+ {translate('auto.components.github.project.ProjectCell.e17bb96881', 'Completed')}
+
) : null}
{completed.map((it) => (
0 ? (
- {translate("auto.components.github.project.ProjectCell.191905e20e", "Current & upcoming")}
+ {translate(
+ 'auto.components.github.project.ProjectCell.191905e20e',
+ 'Current & upcoming'
+ )}
+
) : null}
{active.map((it) => (
- {translate("auto.components.github.project.ProjectCell.ebde486e3c", "Clear")}
+ {translate('auto.components.github.project.ProjectCell.ebde486e3c', 'Clear')}
+
)
@@ -776,19 +822,33 @@ function AssigneesCell({
- {labelContent ?? }
+ {labelContent ?? (
+
+ )}
{!owner || !repo ? (
- {translate("auto.components.github.project.ProjectCell.54cac64427", "Row has no repo slug.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.54cac64427',
+ 'Row has no repo slug.'
+ )}
+
) : metadata.loading ? (
- {translate("auto.components.github.project.ProjectCell.2219e945ef", "Loading…")}
+
+ {translate('auto.components.github.project.ProjectCell.2219e945ef', 'Loading…')}
+
) : (
metadata.data.map((u) => {
const isOn = assignees.some((a) => a.login === u.login)
@@ -852,19 +912,38 @@ function LabelsCell({
- {labelContent ?? }
+ {labelContent ?? (
+
+ )}
{!owner || !repo ? (
- {translate("auto.components.github.project.ProjectCell.54cac64427", "Row has no repo slug.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.54cac64427',
+ 'Row has no repo slug.'
+ )}
+
) : metadata.loading ? (
- {translate("auto.components.github.project.ProjectCell.2219e945ef", "Loading…")}
+
+ {translate('auto.components.github.project.ProjectCell.2219e945ef', 'Loading…')}
+
) : metadata.data.length === 0 ? (
- {translate("auto.components.github.project.ProjectCell.4b5b871da8", "No labels in this repo.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.4b5b871da8',
+ 'No labels in this repo.'
+ )}
+
) : (
metadata.data.map((name) => {
const isOn = labels.some((l) => l.name === name)
diff --git a/src/renderer/src/components/github-project/ProjectGroupHeader.tsx b/src/renderer/src/components/github-project/ProjectGroupHeader.tsx
index 6c0eb1fdda9..c0856cb59a3 100644
--- a/src/renderer/src/components/github-project/ProjectGroupHeader.tsx
+++ b/src/renderer/src/components/github-project/ProjectGroupHeader.tsx
@@ -29,14 +29,18 @@ export default function ProjectGroupHeader({
)}
>
{expanded ? : }
- {group.label || translate("auto.components.github.project.ProjectGroupHeader.244c9e7d06", "All")}
+
+ {group.label ||
+ translate('auto.components.github.project.ProjectGroupHeader.244c9e7d06', 'All')}
+
{group.rows.length}
{dateRange ? {dateRange} : null}
{isCurrent ? (
- {translate("auto.components.github.project.ProjectGroupHeader.82a22d2079", "Current")}
+ {translate('auto.components.github.project.ProjectGroupHeader.82a22d2079', 'Current')}
+
) : null}
)
diff --git a/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx b/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx
index 7a858a8db98..51db853fc1b 100644
--- a/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx
+++ b/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx
@@ -34,10 +34,20 @@ export default function ProjectItemSlugDialog({
onOpenAutoFocus={(e) => e.preventDefault()}
>
- {translate("auto.components.github.project.ProjectItemSlugDialog.4450efea9c", "GitHub item")}
+
+ {translate(
+ 'auto.components.github.project.ProjectItemSlugDialog.4450efea9c',
+ 'GitHub item'
+ )}
+
- {translate("auto.components.github.project.ProjectItemSlugDialog.e55a5c4e68", "Project row preview.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectItemSlugDialog.e55a5c4e68',
+ 'Project row preview.'
+ )}
+
{projectOrigin ? : null}
diff --git a/src/renderer/src/components/github-project/ProjectPicker.tsx b/src/renderer/src/components/github-project/ProjectPicker.tsx
index ac38e60704e..c77ce48948e 100644
--- a/src/renderer/src/components/github-project/ProjectPicker.tsx
+++ b/src/renderer/src/components/github-project/ProjectPicker.tsx
@@ -304,7 +304,13 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
// a transport-level message so the user can retry or paste again.
if (mountedRef.current) {
setViewList([])
- toast.error(translate("auto.components.github.project.ProjectPicker.44b2c6326b", "Failed to load views: {{value0}}", { value0: err instanceof Error ? err.message : String(err) }))
+ toast.error(
+ translate(
+ 'auto.components.github.project.ProjectPicker.44b2c6326b',
+ 'Failed to load views: {{value0}}',
+ { value0: err instanceof Error ? err.message : String(err) }
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -407,7 +413,10 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
setQuery(e.target.value)}
- placeholder={translate("auto.components.github.project.ProjectPicker.f492e1b539", "Search projects")}
+ placeholder={translate(
+ 'auto.components.github.project.ProjectPicker.f492e1b539',
+ 'Search projects'
+ )}
className="h-8 pl-7 text-xs"
/>
@@ -418,7 +427,12 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
) : null}
{projectSettings.pinned.length > 0 ? (
-
+
{projectSettings.pinned.map((p) => {
const key = `${p.ownerType}:${p.owner}:${p.number}`
const knownGood = projectSettings.lastViewByProject[key]?.viewId != null
@@ -453,7 +467,12 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
) : null}
{projectSettings.recent.length > 0 ? (
-
+
{projectSettings.recent
.filter(
(r) =>
@@ -498,10 +517,27 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
})}
) : null}
-
+
{browseLoading ? (
- {translate("auto.components.github.project.ProjectPicker.7b6d39627e", "Loading…")}
+ {' '}
+ {translate(
+ 'auto.components.github.project.ProjectPicker.7b6d39627e',
+ 'Loading…'
+ )}
+
) : null}
{filteredBrowse.map((p) => (
- {translate("auto.components.github.project.ProjectPicker.fce99a24a7", "Add")}
+ {translate('auto.components.github.project.ProjectPicker.fce99a24a7', 'Add')}
+
{pasteError ? (
{pasteError}
@@ -603,13 +643,14 @@ function PickerRow({
className="text-[10px] text-muted-foreground hover:text-foreground"
onClick={onRemovePin}
>
- {translate("auto.components.github.project.ProjectPicker.5009ffc2f3", "Remove pin")}
+ {translate('auto.components.github.project.ProjectPicker.5009ffc2f3', 'Remove pin')}
+
) : null}
{canPin ? (
@@ -639,16 +680,26 @@ function ViewPickStep({
onClick={onBack}
className="text-xs text-muted-foreground hover:text-foreground"
>
- {translate("auto.components.github.project.ProjectPicker.a51b3337ab", "← Back")}
- {translate("auto.components.github.project.ProjectPicker.9bf55fa1e8", "Choose a view")}
+ {translate('auto.components.github.project.ProjectPicker.a51b3337ab', '← Back')}
+
+
+ {translate('auto.components.github.project.ProjectPicker.9bf55fa1e8', 'Choose a view')}
+
{loading ? (
- {translate("auto.components.github.project.ProjectPicker.72a05c04a6", "Loading views…")}
+
{' '}
+ {translate('auto.components.github.project.ProjectPicker.72a05c04a6', 'Loading views…')}
+
) : views.length === 0 ? (
- {translate("auto.components.github.project.ProjectPicker.9b36829267", "No views found.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectPicker.9b36829267',
+ 'No views found.'
+ )}
+
) : (
views.map((v) => {
const supported = v.layout === 'TABLE_LAYOUT'
@@ -665,11 +716,17 @@ function ViewPickStep({
>
{v.name}
- {v.layout === "TABLE_LAYOUT"
- ? translate("auto.components.github.project.ProjectPicker.1a2b8e512e", "Table")
- : v.layout === "BOARD_LAYOUT"
- ? translate("auto.components.github.project.ProjectPicker.d34ef9b554", "Board (unsupported)")
- : translate("auto.components.github.project.ProjectPicker.ab1a2c357d", "Roadmap (unsupported)")}
+ {v.layout === 'TABLE_LAYOUT'
+ ? translate('auto.components.github.project.ProjectPicker.1a2b8e512e', 'Table')
+ : v.layout === 'BOARD_LAYOUT'
+ ? translate(
+ 'auto.components.github.project.ProjectPicker.d34ef9b554',
+ 'Board (unsupported)'
+ )
+ : translate(
+ 'auto.components.github.project.ProjectPicker.ab1a2c357d',
+ 'Roadmap (unsupported)'
+ )}
)
@@ -706,7 +763,11 @@ function PartialFailuresBanner({
{summary}
- {translate("auto.components.github.project.ProjectPicker.96739284c3", "Paste a project URL below to reach missing ones.")}
+ {translate(
+ 'auto.components.github.project.ProjectPicker.96739284c3',
+ 'Paste a project URL below to reach missing ones.'
+ )}
+
diff --git a/src/renderer/src/components/github-project/ProjectRow.tsx b/src/renderer/src/components/github-project/ProjectRow.tsx
index 091e2ff1636..1513f275da9 100644
--- a/src/renderer/src/components/github-project/ProjectRow.tsx
+++ b/src/renderer/src/components/github-project/ProjectRow.tsx
@@ -118,28 +118,38 @@ export default function ProjectRow({
- {translate("auto.components.github.project.ProjectRow.e12be8b4d4", "Open in GitHub")}
+
+ {translate('auto.components.github.project.ProjectRow.e12be8b4d4', 'Open in GitHub')}
+
) : null}
- {!disabled && row.itemType !== "DRAFT_ISSUE" && row.content.number != null ? (
+ {!disabled && row.itemType !== 'DRAFT_ISSUE' && row.content.number != null ? (
- {translate("auto.components.github.project.ProjectRow.75b5d816e3", "Start work")}
+
+ {translate('auto.components.github.project.ProjectRow.75b5d816e3', 'Start work')}
+
) : null}
diff --git a/src/renderer/src/components/github-project/ProjectViewList.tsx b/src/renderer/src/components/github-project/ProjectViewList.tsx
index b24f47404c7..ebaaba0b7c4 100644
--- a/src/renderer/src/components/github-project/ProjectViewList.tsx
+++ b/src/renderer/src/components/github-project/ProjectViewList.tsx
@@ -180,7 +180,11 @@ export default function ProjectViewList({
if (table.rows.length === 0) {
return (
- {translate("auto.components.github.project.ProjectViewList.4f57d2e0b1", "No items match this view's filter.")}
+ {translate(
+ 'auto.components.github.project.ProjectViewList.4f57d2e0b1',
+ "No items match this view's filter."
+ )}
+
)
}
@@ -324,7 +328,11 @@ function ProjectHeaderRow({
'group flex min-w-0 flex-1 items-center gap-1 truncate text-left uppercase tracking-wide hover:text-foreground',
isActive && 'text-foreground'
)}
- aria-label={translate("auto.components.github.project.ProjectViewList.eddfc7a794", "Sort by {{value0}}", { value0: f.name })}
+ aria-label={translate(
+ 'auto.components.github.project.ProjectViewList.eddfc7a794',
+ 'Sort by {{value0}}',
+ { value0: f.name }
+ )}
>
{f.name}
@@ -359,7 +370,8 @@ function ProjectHeaderRow({
- {translate("auto.components.github.project.ProjectViewList.989f81dc2a", "Columns")}
+ {translate('auto.components.github.project.ProjectViewList.989f81dc2a', 'Columns')}
+
{availableFields.map((f) => {
// Why: TITLE is the only column that anchors the row's identity
// and click target — disallow hiding it so users can't end up
diff --git a/src/renderer/src/components/github-project/ProjectViewWrapper.tsx b/src/renderer/src/components/github-project/ProjectViewWrapper.tsx
index bde0fad35f3..d1c6dcd9a2e 100644
--- a/src/renderer/src/components/github-project/ProjectViewWrapper.tsx
+++ b/src/renderer/src/components/github-project/ProjectViewWrapper.tsx
@@ -344,7 +344,12 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
if (parentDroppedToasted.has(currentCacheKey)) {
return
}
- toast.message(translate("auto.components.github.project.ProjectViewWrapper.22df63c393", "Sub-issue data is unavailable for your token."))
+ toast.message(
+ translate(
+ 'auto.components.github.project.ProjectViewWrapper.22df63c393',
+ 'Sub-issue data is unavailable for your token.'
+ )
+ )
setParentDroppedToasted((prev) => {
const next = new Set(prev)
next.add(currentCacheKey)
@@ -675,7 +680,10 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
size="icon"
className="h-7 w-7"
onClick={() => void window.api.shell.openUrl(selectedViewUrl)}
- aria-label={translate("auto.components.github.project.ProjectViewWrapper.fd15491034", "Open view in GitHub")}
+ aria-label={translate(
+ 'auto.components.github.project.ProjectViewWrapper.fd15491034',
+ 'Open view in GitHub'
+ )}
>
@@ -706,8 +714,28 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
}}
disabled={loading}
aria-busy={loading}
- aria-label={loading ? translate("auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5", "Refreshing") : translate("auto.components.github.project.ProjectViewWrapper.71fb69926c", "Refresh")}
- title={loading ? translate("auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5", "Refreshing") : translate("auto.components.github.project.ProjectViewWrapper.71fb69926c", "Refresh")}
+ aria-label={
+ loading
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5',
+ 'Refreshing'
+ )
+ : translate(
+ 'auto.components.github.project.ProjectViewWrapper.71fb69926c',
+ 'Refresh'
+ )
+ }
+ title={
+ loading
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5',
+ 'Refreshing'
+ )
+ : translate(
+ 'auto.components.github.project.ProjectViewWrapper.71fb69926c',
+ 'Refresh'
+ )
+ }
>
@@ -732,7 +760,11 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
{!activeProject ? (
- {translate("auto.components.github.project.ProjectViewWrapper.512fc171d6", "Choose a project to get started.")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.512fc171d6',
+ 'Choose a project to get started.'
+ )}
+
) : loading && !table ? (
) : error ? (
@@ -809,16 +841,29 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
>
- {translate("auto.components.github.project.ProjectViewWrapper.7037c8f5f1", "Repository not in Orca")}
+
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.7037c8f5f1',
+ 'Repository not in Orca'
+ )}
+
{resolvedMissingRepoDialogs.repoNotInOrca
- ? translate("auto.components.github.project.ProjectViewWrapper.1850fceac8", "{{value0}}/{{value1}} isn't added to Orca. Add it to start work, or open in GitHub.", { value0: resolvedMissingRepoDialogs.repoNotInOrca.owner, value1: resolvedMissingRepoDialogs.repoNotInOrca.repo })
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.1850fceac8',
+ "{{value0}}/{{value1}} isn't added to Orca. Add it to start work, or open in GitHub.",
+ {
+ value0: resolvedMissingRepoDialogs.repoNotInOrca.owner,
+ value1: resolvedMissingRepoDialogs.repoNotInOrca.repo
+ }
+ )
: null}
setRepoNotInOrca(null)}>
- {translate("auto.components.github.project.ProjectViewWrapper.dffa899f36", "Cancel")}
+ {translate('auto.components.github.project.ProjectViewWrapper.dffa899f36', 'Cancel')}
+
{resolvedMissingRepoDialogs.repoNotInOrca?.url ? (
- {translate("auto.components.github.project.ProjectViewWrapper.23b87ba9f7", "Open in GitHub")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.23b87ba9f7',
+ 'Open in GitHub'
+ )}
+
) : null}
{
@@ -842,7 +891,11 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
await addRepoFromStore()
}}
>
- {translate("auto.components.github.project.ProjectViewWrapper.840c268665", "Add repo")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.840c268665',
+ 'Add repo'
+ )}
+
@@ -937,8 +990,22 @@ function ProjectSearchInput({
apply(value)
}
}}
- placeholder={viewFilter || translate("auto.components.github.project.ProjectViewWrapper.067119985c", "GitHub search, e.g. assignee:@me is:open")}
- title={viewFilter ? translate("auto.components.github.project.ProjectViewWrapper.c5bc7ec007", "View filter: {{value0}}", { value0: viewFilter }) : undefined}
+ placeholder={
+ viewFilter ||
+ translate(
+ 'auto.components.github.project.ProjectViewWrapper.067119985c',
+ 'GitHub search, e.g. assignee:@me is:open'
+ )
+ }
+ title={
+ viewFilter
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.c5bc7ec007',
+ 'View filter: {{value0}}',
+ { value0: viewFilter }
+ )
+ : undefined
+ }
className={cn(
'h-7 rounded-md border-border/50 bg-background pl-8 pr-7 text-[11px]',
dirty && 'border-amber-500/50'
@@ -947,7 +1014,10 @@ function ProjectSearchInput({
{value ? (
e.preventDefault()}
onClick={() => {
setValue('')
@@ -1001,7 +1071,11 @@ function ViewTabStrip({
title={
supported
? v.name
- : translate("auto.components.github.project.ProjectViewWrapper.2edf5e7e77", "{{value0}} — Orca doesn't support {{value1}} project views yet. File a feature request at {{value2}}.", { value0: v.name, value1: layoutLabel, value2: ORCA_FEATURE_REQUEST_URL })
+ : translate(
+ 'auto.components.github.project.ProjectViewWrapper.2edf5e7e77',
+ "{{value0}} — Orca doesn't support {{value1}} project views yet. File a feature request at {{value2}}.",
+ { value0: v.name, value1: layoutLabel, value2: ORCA_FEATURE_REQUEST_URL }
+ )
}
className={cn(
'inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-t-md border-x border-t px-3 py-1.5 text-xs',
@@ -1025,7 +1099,11 @@ function ViewTabStrip({
{tab}
@@ -1034,14 +1112,23 @@ function ViewTabStrip({
- {unsupportedMessage} {translate("auto.components.github.project.ProjectViewWrapper.1bf8c01c8b", "Switch to a Table view to work with this project in Orca.")}
+ {unsupportedMessage}{' '}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.1bf8c01c8b',
+ 'Switch to a Table view to work with this project in Orca.'
+ )}
+
void window.api.shell.openUrl(ORCA_FEATURE_REQUEST_URL)}
>
- {translate("auto.components.github.project.ProjectViewWrapper.4d2a77a119", "File feature request")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.4d2a77a119',
+ 'File feature request'
+ )}
+
@@ -1071,7 +1158,12 @@ function ErrorState({
error={error as GitHubProjectViewError & { type: 'auth_required' | 'scope_missing' }}
/>
- {translate("auto.components.github.project.ProjectViewWrapper.23b87ba9f7", "Open in GitHub")}
+ {' '}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.23b87ba9f7',
+ 'Open in GitHub'
+ )}
+
)
}
@@ -1090,7 +1182,12 @@ function ErrorState({
{copy}
- {translate("auto.components.github.project.ProjectViewWrapper.23b87ba9f7", "Open in GitHub")}
+ {' '}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.23b87ba9f7',
+ 'Open in GitHub'
+ )}
+
)
@@ -1105,7 +1202,10 @@ function ProjectTableSkeleton(): React.JSX.Element {
return (
diff --git a/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx b/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx
index cd8e870085e..1b9e3a2b028 100644
--- a/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx
@@ -38,12 +38,26 @@ export function AssigneesEditor({
disabled={disabled}
className="rounded-md border border-border/50 bg-muted/30 px-2 py-0.5 text-[11px] hover:bg-muted disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-muted/30"
>
- {translate("auto.components.github.project.slug.dialog.AssigneesEditor.98914e6b36", "Assignees:")}{selected.length === 0 ? translate("auto.components.github.project.slug.dialog.AssigneesEditor.94a4e6e4fa", "none") : selected.join(', ')}
+ {translate(
+ 'auto.components.github.project.slug.dialog.AssigneesEditor.98914e6b36',
+ 'Assignees:'
+ )}
+ {selected.length === 0
+ ? translate(
+ 'auto.components.github.project.slug.dialog.AssigneesEditor.94a4e6e4fa',
+ 'none'
+ )
+ : selected.join(', ')}
{metadata.loading ? (
- {translate("auto.components.github.project.slug.dialog.AssigneesEditor.529fec247b", "Loading…")}
+
+ {translate(
+ 'auto.components.github.project.slug.dialog.AssigneesEditor.529fec247b',
+ 'Loading…'
+ )}
+
) : (
metadata.data.map((u) => {
const isOn = selected.includes(u.login)
diff --git a/src/renderer/src/components/github-project/slug-dialog/Comments.tsx b/src/renderer/src/components/github-project/slug-dialog/Comments.tsx
index fa0cf56e55f..4a9186657e3 100644
--- a/src/renderer/src/components/github-project/slug-dialog/Comments.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/Comments.tsx
@@ -31,7 +31,12 @@ export function CommentsList({
return (
{comments.length === 0 ? (
-
{translate("auto.components.github.project.slug.dialog.Comments.5f104bf855", "No comments yet.")}
+
+ {translate(
+ 'auto.components.github.project.slug.dialog.Comments.5f104bf855',
+ 'No comments yet.'
+ )}
+
) : (
comments.map((c) => (
- {translate("auto.components.github.project.slug.dialog.Comments.8564f58542", "Edit")}
+ {translate('auto.components.github.project.slug.dialog.Comments.8564f58542', 'Edit')}
+
void onDelete()}>
- {translate("auto.components.github.project.slug.dialog.Comments.463d030ae4", "Delete")}
+ {translate('auto.components.github.project.slug.dialog.Comments.463d030ae4', 'Delete')}
+
{editing ? (
@@ -136,9 +143,14 @@ function CommentRow({
void onEdit(draft)
}}
>
- {translate("auto.components.github.project.slug.dialog.Comments.c3e829b4d9", "Save")}
+ {translate('auto.components.github.project.slug.dialog.Comments.c3e829b4d9', 'Save')}
+
setEditing(false)}>
- {translate("auto.components.github.project.slug.dialog.Comments.c0e576e96b", "Cancel")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.Comments.c0e576e96b',
+ 'Cancel'
+ )}
+
) : (
@@ -166,7 +178,10 @@ export function NewCommentForm({
setDraft(e.target.value)}
- placeholder={translate("auto.components.github.project.slug.dialog.Comments.1c95937c8b", "Write a comment…")}
+ placeholder={translate(
+ 'auto.components.github.project.slug.dialog.Comments.1c95937c8b',
+ 'Write a comment…'
+ )}
className="min-h-[80px] w-full rounded border border-border/50 bg-background p-2 text-sm"
/>
@@ -201,7 +216,9 @@ export function NewCommentForm({
}
}}
>
- {translate("auto.components.github.project.slug.dialog.Comments.fd5cccd138", "Comment")}
+ {' '}
+ {translate('auto.components.github.project.slug.dialog.Comments.fd5cccd138', 'Comment')}
+
)
diff --git a/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx b/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx
index 93ba5b11b6d..a2e64a8e968 100644
--- a/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx
@@ -29,12 +29,26 @@ export function LabelsEditor({
disabled={disabled}
className="rounded-md border border-border/50 bg-muted/30 px-2 py-0.5 text-[11px] hover:bg-muted disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-muted/30"
>
- {translate("auto.components.github.project.slug.dialog.LabelsEditor.a7b182fcda", "Labels:")}{selected.length === 0 ? translate("auto.components.github.project.slug.dialog.LabelsEditor.1a5366b5be", "none") : selected.join(', ')}
+ {translate(
+ 'auto.components.github.project.slug.dialog.LabelsEditor.a7b182fcda',
+ 'Labels:'
+ )}
+ {selected.length === 0
+ ? translate(
+ 'auto.components.github.project.slug.dialog.LabelsEditor.1a5366b5be',
+ 'none'
+ )
+ : selected.join(', ')}
{metadata.loading ? (
- {translate("auto.components.github.project.slug.dialog.LabelsEditor.34dd57d6c8", "Loading…")}
+
+ {translate(
+ 'auto.components.github.project.slug.dialog.LabelsEditor.34dd57d6c8',
+ 'Loading…'
+ )}
+
) : (
metadata.data.map((name) => {
const isOn = selected.includes(name)
diff --git a/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx b/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx
index 03cb01e86b3..29534bfdccb 100644
--- a/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx
@@ -165,7 +165,11 @@ export function SlugDialogBody({
setEditingTitle(true)
}}
>
- {title || translate("auto.components.github.project.slug.dialog.SlugDialogBody.7c302f8174", "Untitled")}
+ {title ||
+ translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.7c302f8174',
+ 'Untitled'
+ )}
)}
@@ -176,7 +180,10 @@ export function SlugDialogBody({
size="icon"
className="h-7 w-7"
onClick={() => void window.api.shell.openUrl(url)}
- aria-label={translate("auto.components.github.project.slug.dialog.SlugDialogBody.69caf40ae8", "Open in GitHub")}
+ aria-label={translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.69caf40ae8',
+ 'Open in GitHub'
+ )}
>
@@ -186,7 +193,10 @@ export function SlugDialogBody({
size="icon"
className="h-7 w-7"
onClick={onClose}
- aria-label={translate("auto.components.github.project.slug.dialog.SlugDialogBody.ae98897edf", "Close")}
+ aria-label={translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.ae98897edf',
+ 'Close'
+ )}
>
@@ -237,7 +247,12 @@ export function SlugDialogBody({
{loading && !details ? (
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.e4ef8281e9", "Loading…")}
+
{' '}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.e4ef8281e9',
+ 'Loading…'
+ )}
+
) : error ? (
{error}
) : details ? (
@@ -253,9 +268,17 @@ export function SlugDialogBody({
/>
void commitBody()}>
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.e64f6c3eff", "Save")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.e64f6c3eff',
+ 'Save'
+ )}
+
setEditingBody(false)}>
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.a91735d19f", "Cancel")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.a91735d19f',
+ 'Cancel'
+ )}
+
) : body ? (
@@ -280,12 +303,20 @@ export function SlugDialogBody({
setEditingBody(true)
}}
>
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.41169e41fb", "Add a description…")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.41169e41fb',
+ 'Add a description…'
+ )}
+
)}
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.598ad6a517", "Comments")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.598ad6a517',
+ 'Comments'
+ )}
+
- {translate("auto.components.github.GitHubMarkdownComposer.e3bd59143c", "Insert")}
+ {translate('auto.components.github.GitHubMarkdownComposer.e3bd59143c', 'Insert')}
+
setImageInputOpen(false)}>
- {translate("auto.components.github.GitHubMarkdownComposer.015b4e607d", "Cancel")}
+ {translate('auto.components.github.GitHubMarkdownComposer.015b4e607d', 'Cancel')}
+
) : null}
diff --git a/src/renderer/src/components/github/IssueSourceSelector.tsx b/src/renderer/src/components/github/IssueSourceSelector.tsx
index 54b58b506bb..e428d53f525 100644
--- a/src/renderer/src/components/github/IssueSourceSelector.tsx
+++ b/src/renderer/src/components/github/IssueSourceSelector.tsx
@@ -114,7 +114,10 @@ export default function IssueSourceSelector({
const group = (
- {density === "compact" ? 'U' : translate("auto.components.github.IssueSourceSelector.30b2c9df91", "Upstream")}
+ {density === 'compact'
+ ? 'U'
+ : translate('auto.components.github.IssueSourceSelector.30b2c9df91', 'Upstream')}
- {density === "compact" ? 'O' : translate("auto.components.github.IssueSourceSelector.51d1608920", "Origin")}
+ {density === 'compact'
+ ? 'O'
+ : translate('auto.components.github.IssueSourceSelector.51d1608920', 'Origin')}
)
@@ -171,8 +178,8 @@ export default function IssueSourceSelector({
{group}
- {translate("auto.components.github.IssueSourceSelector.d6aeb2012b", "Showing issues from")}{' '}
- {effective === "upstream" ? upstreamSlug : originSlug}
+ {translate('auto.components.github.IssueSourceSelector.d6aeb2012b', 'Showing issues from')}{' '}
+ {effective === 'upstream' ? upstreamSlug : originSlug}
)
diff --git a/src/renderer/src/components/github/PRFilterDropdowns.tsx b/src/renderer/src/components/github/PRFilterDropdowns.tsx
index 27030b626d5..c5cebb4ffd7 100644
--- a/src/renderer/src/components/github/PRFilterDropdowns.tsx
+++ b/src/renderer/src/components/github/PRFilterDropdowns.tsx
@@ -56,7 +56,11 @@ function ActivePill({
{value}
@@ -177,7 +181,8 @@ export default function PRFilterDropdowns({
)}
>
- {translate("auto.components.github.PRFilterDropdowns.79c54552f7", "Filters")}{activeCount > 0 ? (
+ {translate('auto.components.github.PRFilterDropdowns.79c54552f7', 'Filters')}
+ {activeCount > 0 ? (
{activeCount}
@@ -238,35 +243,39 @@ export default function PRFilterDropdowns({
{statusPillValue ? (
onChange({ state: 'open', draft: false })}
/>
) : null}
{parsed.author ? (
onChange({ author: null })}
/>
) : null}
{parsed.labels.length > 0 ? (
onChange({ labels: [] })}
/>
) : null}
{reviewerActive ? (
onChange({ reviewer: null })}
/>
) : null}
{parsed.assignee ? (
onChange({ assignee: null })}
/>
diff --git a/src/renderer/src/components/github/PRFilterPickers.tsx b/src/renderer/src/components/github/PRFilterPickers.tsx
index 2ddd7706f48..0d5c11af6d8 100644
--- a/src/renderer/src/components/github/PRFilterPickers.tsx
+++ b/src/renderer/src/components/github/PRFilterPickers.tsx
@@ -78,7 +78,9 @@ export function SingleSelectList({
onSelect={() => onSelect(trimmed)}
className="items-center gap-2 px-3 py-1.5 text-xs"
>
- {translate("auto.components.github.PRFilterPickers.2d1f58eda6", "Use")}
+
+ {translate('auto.components.github.PRFilterPickers.2d1f58eda6', 'Use')}
+
{trimmed}
) : null}
@@ -88,7 +90,8 @@ export function SingleSelectList({
onSelect={() => onSelect(null)}
className="gap-2 px-3 py-1.5 text-xs text-muted-foreground"
>
- {translate("auto.components.github.PRFilterPickers.472c12ae03", "Clear")}
+ {translate('auto.components.github.PRFilterPickers.472c12ae03', 'Clear')}
+
) : null}
{filtered.map((opt) => {
const isActive = opt.key === activeValue
@@ -162,7 +165,8 @@ export function MultiSelectList({
onSelect={() => onChange([])}
className="gap-2 px-3 py-1.5 text-xs text-muted-foreground"
>
- {translate("auto.components.github.PRFilterPickers.fdf387297c", "Clear (")}{selected.length})
+ {translate('auto.components.github.PRFilterPickers.fdf387297c', 'Clear (')}
+ {selected.length})
) : null}
{filtered.map((opt) => {
diff --git a/src/renderer/src/components/github/PRFilterSections.tsx b/src/renderer/src/components/github/PRFilterSections.tsx
index 176a631f424..59fc7634120 100644
--- a/src/renderer/src/components/github/PRFilterSections.tsx
+++ b/src/renderer/src/components/github/PRFilterSections.tsx
@@ -49,15 +49,36 @@ function StatusSection({
const states: { key: 'open' | 'closed' | 'merged' | 'all'; label: string }[] =
kind === 'prs'
? [
- { key: 'open', label: translate("auto.components.github.PRFilterSections.d78b60b5c2", "Open") },
- { key: 'closed', label: translate("auto.components.github.PRFilterSections.0fd3249e2e", "Closed") },
- { key: 'merged', label: translate("auto.components.github.PRFilterSections.bd162b7d5a", "Merged") },
- { key: 'all', label: translate("auto.components.github.PRFilterSections.2b2f019091", "Any state") }
+ {
+ key: 'open',
+ label: translate('auto.components.github.PRFilterSections.d78b60b5c2', 'Open')
+ },
+ {
+ key: 'closed',
+ label: translate('auto.components.github.PRFilterSections.0fd3249e2e', 'Closed')
+ },
+ {
+ key: 'merged',
+ label: translate('auto.components.github.PRFilterSections.bd162b7d5a', 'Merged')
+ },
+ {
+ key: 'all',
+ label: translate('auto.components.github.PRFilterSections.2b2f019091', 'Any state')
+ }
]
: [
- { key: 'open', label: translate("auto.components.github.PRFilterSections.d78b60b5c2", "Open") },
- { key: 'closed', label: translate("auto.components.github.PRFilterSections.0fd3249e2e", "Closed") },
- { key: 'all', label: translate("auto.components.github.PRFilterSections.2b2f019091", "Any state") }
+ {
+ key: 'open',
+ label: translate('auto.components.github.PRFilterSections.d78b60b5c2', 'Open')
+ },
+ {
+ key: 'closed',
+ label: translate('auto.components.github.PRFilterSections.0fd3249e2e', 'Closed')
+ },
+ {
+ key: 'all',
+ label: translate('auto.components.github.PRFilterSections.2b2f019091', 'Any state')
+ }
]
return (
@@ -74,11 +95,15 @@ function StatusSection({
)}
>
{s.label}
- {active ? {translate("auto.components.github.PRFilterSections.e0002f1eba", "selected")} : null}
+ {active ? (
+
+ {translate('auto.components.github.PRFilterSections.e0002f1eba', 'selected')}
+
+ ) : null}
)
})}
- {kind !== "prs" ? null : }
+ {kind !== 'prs' ? null : }
)
}
@@ -101,11 +126,15 @@ function DraftToggle({
parsed.draft && 'bg-muted/40 font-medium'
)}
>
- {translate("auto.components.github.PRFilterSections.b930de7194", "Draft only")}
+ {translate('auto.components.github.PRFilterSections.b930de7194', 'Draft only')}
{parsed.draft ? (
- {translate("auto.components.github.PRFilterSections.1e9b5244f2", "on")}
+
+ {translate('auto.components.github.PRFilterSections.1e9b5244f2', 'on')}
+
) : (
- {translate("auto.components.github.PRFilterSections.f0cf6dd591", "off")}
+
+ {translate('auto.components.github.PRFilterSections.f0cf6dd591', 'off')}
+
)}
>
@@ -140,11 +169,19 @@ export function SectionMenu({
}): React.JSX.Element {
const status = statusLabel(parsed)
const rows: { key: SectionKey; label: string; value: string | null }[] = [
- { key: 'status', label: translate("auto.components.github.PRFilterSections.764a0b4ce1", "Status"), value: status || null },
- { key: 'author', label: translate("auto.components.github.PRFilterSections.24754c44ad", "Author"), value: parsed.author },
+ {
+ key: 'status',
+ label: translate('auto.components.github.PRFilterSections.764a0b4ce1', 'Status'),
+ value: status || null
+ },
+ {
+ key: 'author',
+ label: translate('auto.components.github.PRFilterSections.24754c44ad', 'Author'),
+ value: parsed.author
+ },
{
key: 'label',
- label: translate("auto.components.github.PRFilterSections.b1d9fdea08", "Label"),
+ label: translate('auto.components.github.PRFilterSections.b1d9fdea08', 'Label'),
value:
parsed.labels.length === 0
? null
@@ -161,13 +198,18 @@ export function SectionMenu({
}
]
: []),
- { key: 'assignee', label: translate("auto.components.github.PRFilterSections.ea3416d646", "Assignee"), value: parsed.assignee }
+ {
+ key: 'assignee',
+ label: translate('auto.components.github.PRFilterSections.ea3416d646', 'Assignee'),
+ value: parsed.assignee
+ }
]
const subject = kind === 'prs' ? 'pull requests' : 'issues'
return (
- {translate("auto.components.github.PRFilterSections.8177eda37e", "Filter")}{subject}
+ {translate('auto.components.github.PRFilterSections.8177eda37e', 'Filter')}
+ {subject}
{rows.map((row) => (
- {translate("auto.components.github.PRFilterSections.30ebb6ca44", "Clear all filters")}
+ {translate('auto.components.github.PRFilterSections.30ebb6ca44', 'Clear all filters')}
+
>
) : null}
@@ -237,48 +280,49 @@ export function SectionDetail({
className="flex w-full items-center gap-1 border-b border-border px-3 py-1.5 text-[11px] text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
>
- {translate("auto.components.github.PRFilterSections.b69fa4fa20", "Back")}
- {section === "status" ? (
+ {translate('auto.components.github.PRFilterSections.b69fa4fa20', 'Back')}
+
+ {section === 'status' ? (
) : null}
- {section === "author" ? (
+ {section === 'author' ? (
}
onSelect={(value) => onSelect({ author: value })}
/>
) : null}
- {section === "assignee" ? (
+ {section === 'assignee' ? (
}
onSelect={(value) => onSelect({ assignee: value })}
/>
) : null}
- {section === "label" ? (
+ {section === 'label' ? (
onSelect({ labels: next })}
/>
) : null}
- {section === "reviewer" ? (
+ {section === 'reviewer' ? (
<>
- {translate("auto.components.github.PRFilterSections.94b42b0edf", "Review requested")}
+ {translate('auto.components.github.PRFilterSections.94b42b0edf', 'Review requested')}
+
setReviewerMode('reviewed-by')}
@@ -302,7 +347,8 @@ export function SectionDetail({
: 'text-muted-foreground hover:bg-muted/50'
)}
>
- {translate("auto.components.github.PRFilterSections.0103e1cb18", "Reviewed by")}
+ {translate('auto.components.github.PRFilterSections.0103e1cb18', 'Reviewed by')}
+
}
onSelect={(login) =>
diff --git a/src/renderer/src/components/github/github-rate-limit-display.tsx b/src/renderer/src/components/github/github-rate-limit-display.tsx
index c9f1cf6f5f3..4321aeeec04 100644
--- a/src/renderer/src/components/github/github-rate-limit-display.tsx
+++ b/src/renderer/src/components/github/github-rate-limit-display.tsx
@@ -18,9 +18,30 @@ type BucketMeta = {
}
const BUCKETS: BucketMeta[] = [
- { key: 'core', label: translate("auto.components.github.github.rate.limit.display.bb227706a6", "REST"), description: translate("auto.components.github.github.rate.limit.display.c392c749a6", "REST API") },
- { key: 'search', label: translate("auto.components.github.github.rate.limit.display.c377a4f06a", "Search"), description: translate("auto.components.github.github.rate.limit.display.1f2f28a4de", "Search API") },
- { key: 'graphql', label: translate("auto.components.github.github.rate.limit.display.1daf0f22a9", "GraphQL"), description: translate("auto.components.github.github.rate.limit.display.01f7323e58", "GraphQL API") }
+ {
+ key: 'core',
+ label: translate('auto.components.github.github.rate.limit.display.bb227706a6', 'REST'),
+ description: translate(
+ 'auto.components.github.github.rate.limit.display.c392c749a6',
+ 'REST API'
+ )
+ },
+ {
+ key: 'search',
+ label: translate('auto.components.github.github.rate.limit.display.c377a4f06a', 'Search'),
+ description: translate(
+ 'auto.components.github.github.rate.limit.display.1f2f28a4de',
+ 'Search API'
+ )
+ },
+ {
+ key: 'graphql',
+ label: translate('auto.components.github.github.rate.limit.display.1daf0f22a9', 'GraphQL'),
+ description: translate(
+ 'auto.components.github.github.rate.limit.display.01f7323e58',
+ 'GraphQL API'
+ )
+ }
]
export function formatGitHubRateLimitReset(resetAt: number): string {
@@ -127,7 +148,14 @@ function GitHubRateLimitRows({
tone === 'warn' && 'text-amber-700 dark:text-amber-300'
)}
>
- {v.remaining} {translate("auto.components.github.github.rate.limit.display.f42790d150", "of")}{v.limit} {translate("auto.components.github.github.rate.limit.display.6da1858354", "left · resets in")}{formatGitHubRateLimitReset(v.resetAt)}
+ {v.remaining}{' '}
+ {translate('auto.components.github.github.rate.limit.display.f42790d150', 'of')}
+ {v.limit}{' '}
+ {translate(
+ 'auto.components.github.github.rate.limit.display.6da1858354',
+ 'left · resets in'
+ )}
+ {formatGitHubRateLimitReset(v.resetAt)}
)
@@ -145,26 +173,47 @@ export function GitHubRateLimitPanel({ className }: { className?: string }): Rea
- {translate("auto.components.github.github.rate.limit.display.58c5f88216", "GitHub API Budget")}
+ {translate(
+ 'auto.components.github.github.rate.limit.display.58c5f88216',
+ 'GitHub API Budget'
+ )}
+
- {translate("auto.components.github.github.rate.limit.display.d5e5de9070", "Orca uses REST, Search, and GraphQL through the GitHub CLI.")}
+ {translate(
+ 'auto.components.github.github.rate.limit.display.d5e5de9070',
+ 'Orca uses REST, Search, and GraphQL through the GitHub CLI.'
+ )}
+
void refresh(true)}
disabled={isFetching}
className="inline-flex size-7 items-center justify-center rounded-md border border-border bg-secondary text-secondary-foreground transition hover:bg-accent disabled:opacity-50"
- aria-label={translate("auto.components.github.github.rate.limit.display.d12d3d6f33", "Refresh GitHub API budget")}
+ aria-label={translate(
+ 'auto.components.github.github.rate.limit.display.d12d3d6f33',
+ 'Refresh GitHub API budget'
+ )}
>
{hasError ? (
- {translate("auto.components.github.github.rate.limit.display.34973d4695", "GitHub API budget is unavailable.")}
+
+ {translate(
+ 'auto.components.github.github.rate.limit.display.34973d4695',
+ 'GitHub API budget is unavailable.'
+ )}
+
) : snapshot ? (
) : (
- {translate("auto.components.github.github.rate.limit.display.5509443543", "Loading GitHub API budget…")}
+
+ {translate(
+ 'auto.components.github.github.rate.limit.display.5509443543',
+ 'Loading GitHub API budget…'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx b/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx
index be12248d469..e477146fd1c 100644
--- a/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx
+++ b/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx
@@ -109,14 +109,20 @@ function GitLabRateLimitRows({
if (!rest) {
return (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.953f7c6062", "This GitLab host did not return rate-limit headers.")}
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.953f7c6062',
+ 'This GitLab host did not return rate-limit headers.'
+ )}
+
)
}
const tone = toneForGitLabBucket(rest.remaining, rest.limit)
return (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.0a891e8935", "REST API")}
+
+ {translate('auto.components.gitlab.gitlab.rate.limit.display.0a891e8935', 'REST API')}
+
- {rest.remaining} {translate("auto.components.gitlab.gitlab.rate.limit.display.ea8ad0bae8", "of")}{rest.limit} {translate("auto.components.gitlab.gitlab.rate.limit.display.3e2c982cfa", "left, resets in")}{' '}
+ {rest.remaining}{' '}
+ {translate('auto.components.gitlab.gitlab.rate.limit.display.ea8ad0bae8', 'of')}
+ {rest.limit}{' '}
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.3e2c982cfa',
+ 'left, resets in'
+ )}{' '}
{formatGitLabRateLimitReset(rest.resetAt)}
@@ -141,8 +153,17 @@ export function GitLabRateLimitPanel({ className }: { className?: string }): Rea
- {translate("auto.components.gitlab.gitlab.rate.limit.display.14e144f7a7", "GitLab API Budget")}
-
{translate("auto.components.gitlab.gitlab.rate.limit.display.2f9c16d6c3", "Orca uses REST through the GitLab CLI.")}
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.14e144f7a7',
+ 'GitLab API Budget'
+ )}
+
+
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.2f9c16d6c3',
+ 'Orca uses REST through the GitLab CLI.'
+ )}
+
void refresh(true)}
disabled={isFetching}
- aria-label={translate("auto.components.gitlab.gitlab.rate.limit.display.a2f68645ac", "Refresh GitLab API budget")}
+ aria-label={translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.a2f68645ac',
+ 'Refresh GitLab API budget'
+ )}
>
{hasError ? (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.a2d3d1fdde", "GitLab API budget is unavailable.")}
+
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.a2d3d1fdde',
+ 'GitLab API budget is unavailable.'
+ )}
+
) : snapshot ? (
) : (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.ebc0e8ecf1", "Loading GitLab API budget...")}
+
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.ebc0e8ecf1',
+ 'Loading GitLab API budget...'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/linear-api-key-dialog.tsx b/src/renderer/src/components/linear-api-key-dialog.tsx
index f884810c1fe..b9e94ba3bd0 100644
--- a/src/renderer/src/components/linear-api-key-dialog.tsx
+++ b/src/renderer/src/components/linear-api-key-dialog.tsx
@@ -139,12 +139,16 @@ export function LinearApiKeyDialog({
- {translate("auto.components.linear.api.key.dialog.7d498f653c", "Personal API key")}
+ {translate('auto.components.linear.api.key.dialog.7d498f653c', 'Personal API key')}
+
{
const nextDraft = event.target.value
@@ -166,15 +170,29 @@ export function LinearApiKeyDialog({
) : null}
- {translate("auto.components.linear.api.key.dialog.af52a6227f", "Create a Personal API key from Account > Security & Access.")}{' '}
+ {translate(
+ 'auto.components.linear.api.key.dialog.af52a6227f',
+ 'Create a Personal API key from Account > Security & Access.'
+ )}{' '}
{!workspace
- ? translate("auto.components.linear.api.key.dialog.c9889a09f8", "Use Linear to choose the intended workspace before creating the key.")
+ ? translate(
+ 'auto.components.linear.api.key.dialog.c9889a09f8',
+ 'Use Linear to choose the intended workspace before creating the key.'
+ )
: null}
- {translate("auto.components.linear.api.key.dialog.d56d3629f4", "Prefer full access when Orca should show every team the account can access in that workspace. Restricted keys only expose permitted teams, and private teams require the key owner to have access.")}
+ {translate(
+ 'auto.components.linear.api.key.dialog.d56d3629f4',
+ 'Prefer full access when Orca should show every team the account can access in that workspace. Restricted keys only expose permitted teams, and private teams require the key owner to have access.'
+ )}
+
- {translate("auto.components.linear.api.key.dialog.e3100b36b9", "If member API keys are blocked, ask a workspace admin to allow them from workspace API settings.")}
+ {translate(
+ 'auto.components.linear.api.key.dialog.e3100b36b9',
+ 'If member API keys are blocked, ask a workspace admin to allow them from workspace API settings.'
+ )}
+
window.api.shell.openUrl(personalKeyUrl)}
>
- {translate("auto.components.linear.api.key.dialog.dc7ccb0f7c", "Personal API keys")}
+ {translate('auto.components.linear.api.key.dialog.dc7ccb0f7c', 'Personal API keys')}
+
|
window.api.shell.openUrl(workspaceApiUrl)}
>
- {translate("auto.components.linear.api.key.dialog.e603ee9156", "Workspace API settings")}
+ {translate(
+ 'auto.components.linear.api.key.dialog.e603ee9156',
+ 'Workspace API settings'
+ )}
+
@@ -204,15 +227,17 @@ export function LinearApiKeyDialog({
onClick={() => onOpenChange(false)}
disabled={connectState === 'connecting'}
>
- {translate("auto.components.linear.api.key.dialog.f8f704a019", "Cancel")}
+ {translate('auto.components.linear.api.key.dialog.f8f704a019', 'Cancel')}
+
void handleConnect()}
disabled={!apiKeyDraft.trim() || connectState === 'connecting'}
>
- {connectState === "connecting" ? (
+ {connectState === 'connecting' ? (
<>
- {translate("auto.components.linear.api.key.dialog.834a52c084", "Verifying...")}>
+ {translate('auto.components.linear.api.key.dialog.834a52c084', 'Verifying...')}
+ >
) : (
submitLabel
)}
diff --git a/src/renderer/src/components/linear-priority-icon.tsx b/src/renderer/src/components/linear-priority-icon.tsx
index 70cb9f2aabe..ae9ebbb16a8 100644
--- a/src/renderer/src/components/linear-priority-icon.tsx
+++ b/src/renderer/src/components/linear-priority-icon.tsx
@@ -53,7 +53,10 @@ export function LinearPriorityIcon({
title={label}
>
!
- {translate("auto.components.linear.priority.icon.c43d3e065b", "Priority:")}{label}
+
+ {translate('auto.components.linear.priority.icon.c43d3e065b', 'Priority:')}
+ {label}
+
)
}
@@ -68,7 +71,10 @@ export function LinearPriorityIcon({
aria-hidden="true"
className="size-3 rounded-full border border-muted-foreground/55"
/>
- {translate("auto.components.linear.priority.icon.c43d3e065b", "Priority:")}{label}
+
+ {translate('auto.components.linear.priority.icon.c43d3e065b', 'Priority:')}
+ {label}
+
)
}
@@ -103,7 +109,10 @@ export function LinearPriorityIcon({
)
})}
- {translate("auto.components.linear.priority.icon.c43d3e065b", "Priority:")}{label}
+
+ {translate('auto.components.linear.priority.icon.c43d3e065b', 'Priority:')}
+ {label}
+
)
}
diff --git a/src/renderer/src/components/linear-project-view-surfaces.tsx b/src/renderer/src/components/linear-project-view-surfaces.tsx
index d070026f1d9..58970a8215a 100644
--- a/src/renderer/src/components/linear-project-view-surfaces.tsx
+++ b/src/renderer/src/components/linear-project-view-surfaces.tsx
@@ -192,8 +192,16 @@ export function LinearCollectionNotice({
{onLoadMore ? null : (
- {translate("auto.components.linear.project.view.surfaces.06b887d622", "Showing first")} {count} {label}
- {translate("auto.components.linear.project.view.surfaces.98730088a6", ". Search or open Linear for the full set.")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.06b887d622',
+ 'Showing first'
+ )}{' '}
+ {count} {label}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.98730088a6',
+ '. Search or open Linear for the full set.'
+ )}
+
)}
{onLoadMore ? (
- {translate("auto.components.linear.project.view.surfaces.93e1f6bfca", "Loading")}>
+ {translate('auto.components.linear.project.view.surfaces.93e1f6bfca', 'Loading')}
+ >
) : (
<>
{loadMoreLabel}
@@ -258,10 +267,26 @@ export function LinearProjectTable({
return (
- {hasError ? translate("auto.components.linear.project.view.surfaces.c9b6e9f90d", "Unable to load Linear projects") : translate("auto.components.linear.project.view.surfaces.a2f31c4cd6", "No Linear projects found")}
+ {hasError
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.c9b6e9f90d',
+ 'Unable to load Linear projects'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.a2f31c4cd6',
+ 'No Linear projects found'
+ )}
- {hasError ? translate("auto.components.linear.project.view.surfaces.f4c79cff5f", "Review the workspace error below, then refresh.") : translate("auto.components.linear.project.view.surfaces.30402d2c6e", "Try search or refresh.")}
+ {hasError
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.f4c79cff5f',
+ 'Review the workspace error below, then refresh.'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.30402d2c6e',
+ 'Try search or refresh.'
+ )}
)
@@ -317,21 +342,23 @@ export function LinearProjectTable({
- {textFromUnknown(projectLike.health) ?? translate("auto.components.linear.project.view.surfaces.8bbecb2510", "None")}
+ {textFromUnknown(projectLike.health) ??
+ translate('auto.components.linear.project.view.surfaces.8bbecb2510', 'None')}
{priorityLabel(projectLike.priority, projectLike.priorityLabel)}
- {textFromUnknown(projectLike.lead) ?? translate("auto.components.linear.project.view.surfaces.df4bd63c1d", "Unassigned")}
+ {textFromUnknown(projectLike.lead) ??
+ translate('auto.components.linear.project.view.surfaces.df4bd63c1d', 'Unassigned')}
{dateLabel(project.targetDate)}
- {typeof project.issueCount === "number"
+ {typeof project.issueCount === 'number'
? project.issueCount
- : typeof project.scope === "number"
+ : typeof project.scope === 'number'
? project.scope
: progress !== null
? `${progress}%`
@@ -348,13 +375,18 @@ export function LinearProjectTable({
event.stopPropagation()
onUseProjectIssues(project)
}}
- aria-label={translate("auto.components.linear.project.view.surfaces.7616c986c6", "Open {{value0}} issues", { value0: project.name })}
+ aria-label={translate(
+ 'auto.components.linear.project.view.surfaces.7616c986c6',
+ 'Open {{value0}} issues',
+ { value0: project.name }
+ )}
>
- {translate("auto.components.linear.project.view.surfaces.ee3d2caabd", "Issues")}
+ {translate('auto.components.linear.project.view.surfaces.ee3d2caabd', 'Issues')}
+
) : null}
@@ -366,13 +398,21 @@ export function LinearProjectTable({
event.stopPropagation()
onOpenProject(project)
}}
- aria-label={translate("auto.components.linear.project.view.surfaces.7616c986c6", "Open {{value0}} in Linear", { value0: project.name })}
+ aria-label={translate(
+ 'auto.components.linear.project.view.surfaces.7616c986c6',
+ 'Open {{value0}} in Linear',
+ { value0: project.name }
+ )}
>
- {translate("auto.components.linear.project.view.surfaces.aac9a4afc6", "Open in Linear")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.aac9a4afc6',
+ 'Open in Linear'
+ )}
+
@@ -415,12 +455,26 @@ export function LinearCustomViewTable({
return (
- {hasError ? translate("auto.components.linear.project.view.surfaces.c0a50f96a4", "Unable to load views") : translate("auto.components.linear.project.view.surfaces.ef90b21366", "No views found")}
+ {hasError
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.c0a50f96a4',
+ 'Unable to load views'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.ef90b21366',
+ 'No views found'
+ )}
{hasError
- ? translate("auto.components.linear.project.view.surfaces.f4c79cff5f", "Review the workspace error below, then refresh.")
- : translate("auto.components.linear.project.view.surfaces.9f0f51fd9e", "Create or save views in Linear, then refresh.")}
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.f4c79cff5f',
+ 'Review the workspace error below, then refresh.'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.9f0f51fd9e',
+ 'Create or save views in Linear, then refresh.'
+ )}
)
@@ -471,13 +525,18 @@ export function LinearCustomViewTable({
{view.model}
- {view.shared ? translate("auto.components.linear.project.view.surfaces.27d91cb1a6", "Shared") : translate("auto.components.linear.project.view.surfaces.f059181bd9", "Private")}
+ {view.shared
+ ? translate('auto.components.linear.project.view.surfaces.27d91cb1a6', 'Shared')
+ : translate('auto.components.linear.project.view.surfaces.f059181bd9', 'Private')}
- {textFromUnknown(view.owner ?? view.creator) ?? translate("auto.components.linear.project.view.surfaces.20b9d09b7d", "Unknown")}
+ {textFromUnknown(view.owner ?? view.creator) ??
+ translate('auto.components.linear.project.view.surfaces.20b9d09b7d', 'Unknown')}
- {view.updatedAt ? dateLabel(view.updatedAt) : translate("auto.components.linear.project.view.surfaces.20b9d09b7d", "Unknown")}
+ {view.updatedAt
+ ? dateLabel(view.updatedAt)
+ : translate('auto.components.linear.project.view.surfaces.20b9d09b7d', 'Unknown')}
@@ -489,13 +548,21 @@ export function LinearCustomViewTable({
event.stopPropagation()
onOpenView(view)
}}
- aria-label={translate("auto.components.linear.project.view.surfaces.7616c986c6", "Open {{value0}} in Linear", { value0: view.name })}
+ aria-label={translate(
+ 'auto.components.linear.project.view.surfaces.7616c986c6',
+ 'Open {{value0}} in Linear',
+ { value0: view.name }
+ )}
>
- {translate("auto.components.linear.project.view.surfaces.aac9a4afc6", "Open in Linear")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.aac9a4afc6',
+ 'Open in Linear'
+ )}
+
@@ -528,17 +595,33 @@ export function LinearProjectOverview({
-
+
- {project?.name ?? translate("auto.components.linear.project.view.surfaces.85607ff793", "Project")}
+ {project?.name ??
+ translate('auto.components.linear.project.view.surfaces.85607ff793', 'Project')}
{project?.workspaceName
- ? translate("auto.components.linear.project.view.surfaces.906b5e4cb8", "Linear / Projects / {{value0}}", { value0: project.workspaceName })
- : translate("auto.components.linear.project.view.surfaces.f2cc1e0ff6", "Linear / Projects")}
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.906b5e4cb8',
+ 'Linear / Projects / {{value0}}',
+ { value0: project.workspaceName }
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.f2cc1e0ff6',
+ 'Linear / Projects'
+ )}
@@ -551,7 +634,8 @@ export function LinearProjectOverview({
className="gap-1 border-border/50 bg-background/70"
>
- {translate("auto.components.linear.project.view.surfaces.ee3d2caabd", "Issues")}
+ {translate('auto.components.linear.project.view.surfaces.ee3d2caabd', 'Issues')}
+
) : null}
- {translate("auto.components.linear.project.view.surfaces.a9785c7158", "Refresh")}
+ {translate('auto.components.linear.project.view.surfaces.a9785c7158', 'Refresh')}
+
{project ? (
- {translate("auto.components.linear.project.view.surfaces.7b147907dc", "Linear")}
+ {translate('auto.components.linear.project.view.surfaces.7b147907dc', 'Linear')}
+
) : null}
@@ -602,41 +688,70 @@ export function LinearProjectOverview({
{body}
) : (
- {translate("auto.components.linear.project.view.surfaces.bb5664d456", "No project description.")}
+
+ {translate(
+ 'auto.components.linear.project.view.surfaces.bb5664d456',
+ 'No project description.'
+ )}
+
)}
{progress !== null ? (
- {translate("auto.components.linear.project.view.surfaces.563501f191", "Progress")}
+
+ {translate(
+ 'auto.components.linear.project.view.surfaces.563501f191',
+ 'Progress'
+ )}
+
{progress}%
- {typeof projectLike.scope === "number" ? (
+ {typeof projectLike.scope === 'number' ? (
- {projectLike.scope} {translate("auto.components.linear.project.view.surfaces.3ad562bdf4", "scoped issues")}
+ {projectLike.scope}{' '}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.3ad562bdf4',
+ 'scoped issues'
+ )}
+
) : null}
) : null}
{milestones.length > 0 || resources.length > 0 || latestUpdate ? (
- {translate("auto.components.linear.project.view.surfaces.5d99315fb8", "Planning")}
+
+ {translate(
+ 'auto.components.linear.project.view.surfaces.5d99315fb8',
+ 'Planning'
+ )}
+
}
- label={translate("auto.components.linear.project.view.surfaces.bb1405eff8", "Milestones")}
+ label={translate(
+ 'auto.components.linear.project.view.surfaces.bb1405eff8',
+ 'Milestones'
+ )}
items={milestones}
/>
}
- label={translate("auto.components.linear.project.view.surfaces.c8db98b73b", "Resources")}
+ label={translate(
+ 'auto.components.linear.project.view.surfaces.c8db98b73b',
+ 'Resources'
+ )}
items={resources}
/>
}
- label={translate("auto.components.linear.project.view.surfaces.0a6a5a7dd6", "Latest update")}
+ label={translate(
+ 'auto.components.linear.project.view.surfaces.0a6a5a7dd6',
+ 'Latest update'
+ )}
items={latestUpdate ? [latestUpdate] : []}
/>
@@ -646,37 +761,77 @@ export function LinearProjectOverview({
-
+
}
/>
}
/>
}
/>
-
-
-
+
+
+
) : (
- {translate("auto.components.linear.project.view.surfaces.e1fa97d21d", "Select a project to view its overview.")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.e1fa97d21d',
+ 'Select a project to view its overview.'
+ )}
+
)}
@@ -727,7 +882,9 @@ function MetadataList({
))}
) : (
- {translate("auto.components.linear.project.view.surfaces.8bbecb2510", "None")}
+
+ {translate('auto.components.linear.project.view.surfaces.8bbecb2510', 'None')}
+
)}
)
diff --git a/src/renderer/src/components/linear-scope-selector.tsx b/src/renderer/src/components/linear-scope-selector.tsx
index 24f155fb8fd..3cf4c4b1b2e 100644
--- a/src/renderer/src/components/linear-scope-selector.tsx
+++ b/src/renderer/src/components/linear-scope-selector.tsx
@@ -230,7 +230,10 @@ export function LinearScopeSelector({
1 ? (
- {translate("auto.components.linear.scope.selector.05baa5ae90", "Workspace")}
+ {translate('auto.components.linear.scope.selector.05baa5ae90', 'Workspace')}
+
{
@@ -254,7 +258,12 @@ export function LinearScopeSelector({
selectedWorkspaceId === 'all' ? 'opacity-70' : 'opacity-0'
)}
/>
- {translate("auto.components.linear.scope.selector.a14ce4df2b", "All workspaces")}
+
+ {translate(
+ 'auto.components.linear.scope.selector.a14ce4df2b',
+ 'All workspaces'
+ )}
+
{workspaces.map((workspace) => (
- {translate("auto.components.linear.scope.selector.e1ae6bebb0", "Teams")}
+ {translate('auto.components.linear.scope.selector.e1ae6bebb0', 'Teams')}
+
handleAllTeams()}
@@ -291,7 +301,9 @@ export function LinearScopeSelector({
allTeamsSelected || teamSelectionIsStickyAll ? 'opacity-70' : 'opacity-0'
)}
/>
- {translate("auto.components.linear.scope.selector.7783361266", "All teams")}
+
+ {translate('auto.components.linear.scope.selector.7783361266', 'All teams')}
+
{filteredTeams.length > 0 ? (
@@ -332,8 +344,14 @@ export function LinearScopeSelector({
) : (
{query.trim()
- ? translate("auto.components.linear.scope.selector.405b33c378", "No fetched teams match your search.")
- : translate("auto.components.linear.scope.selector.b3488fad3c", "No teams were fetched. Access can depend on key scope, private-team membership, archived teams, permissions, or a fetch failure.")}
+ ? translate(
+ 'auto.components.linear.scope.selector.405b33c378',
+ 'No fetched teams match your search.'
+ )
+ : translate(
+ 'auto.components.linear.scope.selector.b3488fad3c',
+ 'No teams were fetched. Access can depend on key scope, private-team membership, archived teams, permissions, or a fetch failure.'
+ )}
)}
@@ -348,7 +366,9 @@ export function LinearScopeSelector({
className="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-xs text-foreground transition hover:bg-accent hover:text-accent-foreground"
>
- {translate("auto.components.linear.scope.selector.91c8871dad", "Add team access")}
+
+ {translate('auto.components.linear.scope.selector.91c8871dad', 'Add team access')}
+
diff --git a/src/renderer/src/components/mobile/MobilePageToolbar.tsx b/src/renderer/src/components/mobile/MobilePageToolbar.tsx
index ee734c198e4..097b02919f7 100644
--- a/src/renderer/src/components/mobile/MobilePageToolbar.tsx
+++ b/src/renderer/src/components/mobile/MobilePageToolbar.tsx
@@ -23,13 +23,17 @@ export function MobilePageToolbar({
size="icon"
className="size-7 rounded-full"
onClick={onClose}
- aria-label={translate("auto.components.mobile.MobilePageToolbar.9883b58693", "Close Orca Mobile")}
+ aria-label={translate(
+ 'auto.components.mobile.MobilePageToolbar.9883b58693',
+ 'Close Orca Mobile'
+ )}
>
- {translate("auto.components.mobile.MobilePageToolbar.ad2284a9e2", "Close · Esc")}
+ {translate('auto.components.mobile.MobilePageToolbar.ad2284a9e2', 'Close · Esc')}
+
{showMobileButton ? : }
- {showMobileButton ? translate("auto.components.mobile.MobilePageToolbar.c669abcf8f", "Hide from sidebar") : translate("auto.components.mobile.MobilePageToolbar.fb5f28330e", "Show in sidebar")}
+ {showMobileButton
+ ? translate('auto.components.mobile.MobilePageToolbar.c669abcf8f', 'Hide from sidebar')
+ : translate('auto.components.mobile.MobilePageToolbar.fb5f28330e', 'Show in sidebar')}
)
diff --git a/src/renderer/src/components/mobile/PhoneCarousel.tsx b/src/renderer/src/components/mobile/PhoneCarousel.tsx
index 250a420a951..9d801d2e16d 100644
--- a/src/renderer/src/components/mobile/PhoneCarousel.tsx
+++ b/src/renderer/src/components/mobile/PhoneCarousel.tsx
@@ -114,13 +114,31 @@ export function PhoneCarousel(): React.JSX.Element {
return (
-
+
-
+
-
diff --git a/src/renderer/src/components/mobile/mobile-platform-copy.ts b/src/renderer/src/components/mobile/mobile-platform-copy.ts
index f63c4ce794d..e09bbbc1eee 100644
--- a/src/renderer/src/components/mobile/mobile-platform-copy.ts
+++ b/src/renderer/src/components/mobile/mobile-platform-copy.ts
@@ -6,12 +6,18 @@ export const PLATFORM_COPY: Record<
{ description: string; ctaLabel: string; url: string }
> = {
ios: {
- description: translate("auto.components.mobile.mobile.platform.copy.432db52b73", "Scan with your iPhone camera to open the App Store."),
+ description: translate(
+ 'auto.components.mobile.mobile.platform.copy.432db52b73',
+ 'Scan with your iPhone camera to open the App Store.'
+ ),
ctaLabel: 'Open App Store',
url: 'https://apps.apple.com/app/orca-ide/id6766130217'
},
android: {
- description: translate("auto.components.mobile.mobile.platform.copy.2a532d6fd7", "Scan with your Android camera to download the latest APK from GitHub Releases."),
+ description: translate(
+ 'auto.components.mobile.mobile.platform.copy.2a532d6fd7',
+ 'Scan with your Android camera to download the latest APK from GitHub Releases.'
+ ),
ctaLabel: 'Download APK',
url: 'https://github.com/stablyai/orca/releases/download/mobile-v0.0.12/app-release.apk'
}
diff --git a/src/renderer/src/components/mobile/slides/HomeSlide.tsx b/src/renderer/src/components/mobile/slides/HomeSlide.tsx
index e5a474e6d4d..0e02b6511f6 100644
--- a/src/renderer/src/components/mobile/slides/HomeSlide.tsx
+++ b/src/renderer/src/components/mobile/slides/HomeSlide.tsx
@@ -8,34 +8,63 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.5d94e8ddcc", "Orca")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.5d94e8ddcc', 'Orca')}
+
-
+
-
{translate("auto.components.mobile.slides.HomeSlide.c0e2e9dcd9", "Welcome back")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.c0e2e9dcd9', 'Welcome back')}
+
-
-
-
+
+
+
-
{translate("auto.components.mobile.slides.HomeSlide.2f1a1d10c4", "Desktops")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.2f1a1d10c4', 'Desktops')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.19c212e25e", "MacBook Pro")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.19c212e25e', 'MacBook Pro')}
+
- {translate("auto.components.mobile.slides.HomeSlide.0bc1881bc4", "Connected · 40 worktrees · 5 active")}
+
+ {translate(
+ 'auto.components.mobile.slides.HomeSlide.0bc1881bc4',
+ 'Connected · 40 worktrees · 5 active'
+ )}
+
@@ -47,10 +76,14 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
-
{translate("auto.components.mobile.slides.HomeSlide.091355da3d", "M1 Mini · home")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.091355da3d', 'M1 Mini · home')}
+
- {translate("auto.components.mobile.slides.HomeSlide.cf3f98fa3f", "Disconnected")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.cf3f98fa3f', 'Disconnected')}
+
@@ -59,16 +92,24 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.c791677f2f", "Resume")}
+ {translate('auto.components.mobile.slides.HomeSlide.c791677f2f', 'Resume')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.25d6e8a491", "feat/mobile-page")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.25d6e8a491', 'feat/mobile-page')}
+
- {translate("auto.components.mobile.slides.HomeSlide.d33d7a9c29", "orca · feat/mobile-page")}
+
+ {translate(
+ 'auto.components.mobile.slides.HomeSlide.d33d7a9c29',
+ 'orca · feat/mobile-page'
+ )}
+
@@ -77,16 +118,27 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.a4c3f7b7aa", "Tasks")}
+ {translate('auto.components.mobile.slides.HomeSlide.a4c3f7b7aa', 'Tasks')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.a4c3f7b7aa", "Tasks")}
-
{translate("auto.components.mobile.slides.HomeSlide.d047197480", "GitHub · Linear")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.a4c3f7b7aa', 'Tasks')}
+
+
+ {translate('auto.components.mobile.slides.HomeSlide.d047197480', 'GitHub · Linear')}
+
-
+
@@ -100,24 +152,30 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.0b00c98506", "Quick Actions")}
+ {translate('auto.components.mobile.slides.HomeSlide.0b00c98506', 'Quick Actions')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.4405f3c440", "Pair Desktop")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.4405f3c440', 'Pair Desktop')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.e27fdaee51", "New Workspace")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.e27fdaee51', 'New Workspace')}
+
- {translate("auto.components.mobile.slides.HomeSlide.8a350a4784", "Account usage")}
+ {translate('auto.components.mobile.slides.HomeSlide.8a350a4784', 'Account usage')}
+
}
@@ -163,8 +221,14 @@ function AccountRow({
diff --git a/src/renderer/src/components/mobile/slides/TerminalSlide.tsx b/src/renderer/src/components/mobile/slides/TerminalSlide.tsx
index 5de7cffed69..27714e4c7a9 100644
--- a/src/renderer/src/components/mobile/slides/TerminalSlide.tsx
+++ b/src/renderer/src/components/mobile/slides/TerminalSlide.tsx
@@ -4,32 +4,66 @@ export function TerminalSlide(): React.JSX.Element {
-
+
-
{translate("auto.components.mobile.slides.TerminalSlide.8432787c4e", "feat/mobile-page")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.8432787c4e',
+ 'feat/mobile-page'
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.8d6516312d", "2 terminals · claude active")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.8d6516312d',
+ '2 terminals · claude active'
+ )}
+
-
+
-
+
-
{translate("auto.components.mobile.slides.TerminalSlide.2c10d43745", "claude")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.2c10d43745', 'claude')}
+
- {translate("auto.components.mobile.slides.TerminalSlide.e4befee569", "shell")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.e4befee569', 'shell')}
+
- {translate("auto.components.mobile.slides.TerminalSlide.da121ba48d", "PLAN.md")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.da121ba48d', 'PLAN.md')}
+
@@ -39,60 +73,139 @@ export function TerminalSlide(): React.JSX.Element {
- {translate("auto.components.mobile.slides.TerminalSlide.2defc05141", "dev@mac")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.e0f98be657", "orca/feat-mobile-page")} {' '}
- $ {translate("auto.components.mobile.slides.TerminalSlide.2c10d43745", "claude")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.2defc05141', 'dev@mac')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.e0f98be657',
+ 'orca/feat-mobile-page'
+ )}
+ {' '}
+ $ {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.2c10d43745', 'claude')}
+
- ● {translate("auto.components.mobile.slides.TerminalSlide.80cc356591", "Read")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.336c0e070e", "mobile/orca-mobile-sidebar-mock-v3.html")}
+ ● {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.80cc356591', 'Read')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.336c0e070e',
+ 'mobile/orca-mobile-sidebar-mock-v3.html'
+ )}
+
{' '}
- {translate("auto.components.mobile.slides.TerminalSlide.fc83e0d5ef", "⎿ Read 2103 lines")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.fc83e0d5ef',
+ '⎿ Read 2103 lines'
+ )}
+
- ● {translate("auto.components.mobile.slides.TerminalSlide.6d4ebd5833", "Edit")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.336c0e070e", "mobile/orca-mobile-sidebar-mock-v3.html")}
+ ● {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.6d4ebd5833', 'Edit')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.336c0e070e',
+ 'mobile/orca-mobile-sidebar-mock-v3.html'
+ )}
+
{' '}
- {translate("auto.components.mobile.slides.TerminalSlide.d6d1041a1c", "⎿ Replaced pair-scan slide with terminal session")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.d6d1041a1c',
+ '⎿ Replaced pair-scan slide with terminal session'
+ )}
+
- ● {translate("auto.components.mobile.slides.TerminalSlide.21b67dfc92", "Bash")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.a6e7cdc688", "pnpm test --filter mobile")}
+ ● {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.21b67dfc92', 'Bash')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.a6e7cdc688',
+ 'pnpm test --filter mobile'
+ )}
+
{' '}
⎿
- {translate("auto.components.mobile.slides.TerminalSlide.1d448b69f7", "PASS")}
- {translate("auto.components.mobile.slides.TerminalSlide.d39445686a", "src/transport/host-store.test.ts")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.1d448b69f7', 'PASS')}
+
+
+ {' '}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.d39445686a',
+ 'src/transport/host-store.test.ts'
+ )}
+
{' '}
- {translate("auto.components.mobile.slides.TerminalSlide.1d448b69f7", "PASS")}
- {translate("auto.components.mobile.slides.TerminalSlide.4b3666f9a9", "src/cache/worktree-cache.test.ts")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.1d448b69f7', 'PASS')}
+
+
+ {' '}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.4b3666f9a9',
+ 'src/cache/worktree-cache.test.ts'
+ )}
+
{' '}
●
- {translate("auto.components.mobile.slides.TerminalSlide.3ce3e8c892", "14 passed, 1 skipped (1.8s)")}
+
+ {' '}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.3ce3e8c892',
+ '14 passed, 1 skipped (1.8s)'
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.e75112c834", "I've replaced the pair-scan slide with a high-fidelity")}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.e75112c834',
+ "I've replaced the pair-scan slide with a high-fidelity"
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.aa64b519c6", "terminal screen. Tokyonight palette, Menlo, real claude")}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.aa64b519c6',
+ 'terminal screen. Tokyonight palette, Menlo, real claude'
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.58a9ee6003", "tool-call formatting. Want me to add the diff next?")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.58a9ee6003',
+ 'tool-call formatting. Want me to add the diff next?'
+ )}
+
@@ -102,27 +215,52 @@ export function TerminalSlide(): React.JSX.Element {
-
+
-
{translate("auto.components.mobile.slides.TerminalSlide.fa22927f13", "Paste")}
-
{translate("auto.components.mobile.slides.TerminalSlide.4930eaaae7", "Esc")}
-
{translate("auto.components.mobile.slides.TerminalSlide.53ff909568", "Tab")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.fa22927f13', 'Paste')}
+
+
+ {translate('auto.components.mobile.slides.TerminalSlide.4930eaaae7', 'Esc')}
+
+
+ {translate('auto.components.mobile.slides.TerminalSlide.53ff909568', 'Tab')}
+
⌫
↑
↓
←
→
-
{translate("auto.components.mobile.slides.TerminalSlide.817090af40", "Ctrl+C")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.817090af40', 'Ctrl+C')}
+
-
{translate("auto.components.mobile.slides.TerminalSlide.29f2d13839", "Type a command…")}
-
+
+ {translate('auto.components.mobile.slides.TerminalSlide.29f2d13839', 'Type a command…')}
+
+
-
diff --git a/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx b/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx
index ab209993ad0..671be8c60b1 100644
--- a/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx
+++ b/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx
@@ -20,24 +20,39 @@ export function WorktreeListSlide({ tapping }: { tapping: boolean }): React.JSX.
-
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.b4271864bd", "MacBook Pro")}
+
+ {translate(
+ 'auto.components.mobile.slides.WorktreeListSlide.b4271864bd',
+ 'MacBook Pro'
+ )}
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.0e3e809a4b", "Filter")}
+ {translate('auto.components.mobile.slides.WorktreeListSlide.0e3e809a4b', 'Filter')}
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.17f9e0d226", "Recent")}
+ {translate('auto.components.mobile.slides.WorktreeListSlide.17f9e0d226', 'Recent')}
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.22971156df", "Repo")}
+ {translate('auto.components.mobile.slides.WorktreeListSlide.22971156df', 'Repo')}
+
@@ -54,7 +69,9 @@ export function WorktreeListSlide({ tapping }: { tapping: boolean }): React.JSX.
-
{translate("auto.components.mobile.slides.WorktreeListSlide.79a24ff530", "Pinned")}
+
+ {translate('auto.components.mobile.slides.WorktreeListSlide.79a24ff530', 'Pinned')}
+
3
@@ -95,7 +112,9 @@ export function WorktreeListSlide({ tapping }: { tapping: boolean }): React.JSX.
- {translate("auto.components.mobile.slides.WorktreeListSlide.357a519567", "Active")}
+
+ {translate('auto.components.mobile.slides.WorktreeListSlide.357a519567', 'Active')}
+
37
@@ -172,7 +191,7 @@ function WorktreeRow({
return (
- {indicator === "spinner" ? (
+ {indicator === 'spinner' ? (
) : (
diff --git a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
index 644935e5af0..b31edc93171 100644
--- a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
+++ b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
@@ -68,10 +68,22 @@ import { translate } from '@/i18n/i18n'
type MrStateFilter = 'opened' | 'merged' | 'closed' | 'all'
const MR_STATE_FILTERS: { id: MrStateFilter; label: string }[] = [
- { id: 'opened', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.622864b52a", "Open") },
- { id: 'merged', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.2319d87718", "Merged") },
- { id: 'closed', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.6fad211c66", "Closed") },
- { id: 'all', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.26824f60dd", "All") }
+ {
+ id: 'opened',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.622864b52a', 'Open')
+ },
+ {
+ id: 'merged',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.2319d87718', 'Merged')
+ },
+ {
+ id: 'closed',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.6fad211c66', 'Closed')
+ },
+ {
+ id: 'all',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.26824f60dd', 'All')
+ }
]
type RepoOption = ReturnType
['repos'][number]
@@ -111,20 +123,40 @@ const MODES: {
label: string
Icon: React.ComponentType<{ className?: string }>
}[] = [
- { id: 'smart', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.b3c60c2b7c", "Smart"), Icon: Sparkles },
- { id: 'github', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.0a180280bd", "GitHub"), Icon: Github },
+ {
+ id: 'smart',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.b3c60c2b7c', 'Smart'),
+ Icon: Sparkles
+ },
+ {
+ id: 'github',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.0a180280bd', 'GitHub'),
+ Icon: Github
+ },
{
id: 'linear',
- label: translate("auto.components.new.workspace.SmartWorkspaceNameField.7a47af0565", "Linear"),
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.7a47af0565', 'Linear'),
Icon: ({ className }: { className?: string }) => (
)
},
- { id: 'gitlab', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.2cfc6be192", "GitLab"), Icon: Gitlab },
- { id: 'branches', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.2e4c7c95fe", "Branch"), Icon: GitBranch },
- { id: 'text', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.6f07a18604", "Name"), Icon: CaseSensitive }
+ {
+ id: 'gitlab',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.2cfc6be192', 'GitLab'),
+ Icon: Gitlab
+ },
+ {
+ id: 'branches',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.2e4c7c95fe', 'Branch'),
+ Icon: GitBranch
+ },
+ {
+ id: 'text',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.6f07a18604', 'Name'),
+ Icon: CaseSensitive
+ }
]
type RowEntry = SmartWorkspaceSourceRow
@@ -989,13 +1021,20 @@ export default function SmartWorkspaceNameField({
size="icon-xs"
onClick={() => void window.api.shell.openUrl(selectedSource.url!)}
className="size-6 shrink-0 rounded-sm text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.new.workspace.SmartWorkspaceNameField.2c69728c2a", "Open link in browser")}
+ aria-label={translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.2c69728c2a',
+ 'Open link in browser'
+ )}
>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.370a1faf67", "Open in browser")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.370a1faf67',
+ 'Open in browser'
+ )}
+
) : null}
@@ -1006,13 +1045,20 @@ export default function SmartWorkspaceNameField({
size="icon-xs"
onClick={onClearSelectedSource}
className="size-6 shrink-0 rounded-sm text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.new.workspace.SmartWorkspaceNameField.7199ff19c7", "Clear selected source")}
+ aria-label={translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.7199ff19c7',
+ 'Clear selected source'
+ )}
>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.0c9e668e3a", "Clear")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.0c9e668e3a',
+ 'Clear'
+ )}
+
) : (
@@ -1110,7 +1156,7 @@ export default function SmartWorkspaceNameField({
}
}}
>
- {mode === "gitlab" ? (
+ {mode === 'gitlab' ? (
// Why: GitLab MR-state filter — Open / Merged / Closed / All —
// mirrors the gitlab.com merge-requests page tab strip so users
// arriving from the web UI find a familiar control.
@@ -1141,8 +1187,11 @@ export default function SmartWorkspaceNameField({
) : rows.length === 0 ? (
- {mode === "linear" && linearStatusChecked && !linearStatus.connected
- ? translate("auto.components.new.workspace.SmartWorkspaceNameField.3e8bb1176a", "Connect Linear in Settings to search issues.")
+ {mode === 'linear' && linearStatusChecked && !linearStatus.connected
+ ? translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.3e8bb1176a',
+ 'Connect Linear in Settings to search issues.'
+ )
: getSmartWorkspaceEmptyHint(mode)}
) : (
@@ -1170,23 +1219,57 @@ export default function SmartWorkspaceNameField({
>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.4bd98f1091", "Switch project?")}
+
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.4bd98f1091',
+ 'Switch project?'
+ )}
+
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.ad188067ae", "The GitHub URL points to")}{crossRepoPrompt?.link.slug.owner}/
- {crossRepoPrompt?.link.slug.repo}{translate("auto.components.new.workspace.SmartWorkspaceNameField.9ef1a7c4b0", ", which is different from the selected project.")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.ad188067ae',
+ 'The GitHub URL points to'
+ )}
+ {crossRepoPrompt?.link.slug.owner}/{crossRepoPrompt?.link.slug.repo}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.9ef1a7c4b0',
+ ', which is different from the selected project.'
+ )}
+
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.6859e2896c", "Cancel")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.6859e2896c',
+ 'Cancel'
+ )}
+
void handleUseCurrentRepo()}>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.eadf877af5", "Keep")}{selectedRepo?.displayName ?? translate("auto.components.new.workspace.SmartWorkspaceNameField.fda67f0b61", "current project")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.eadf877af5',
+ 'Keep'
+ )}
+ {selectedRepo?.displayName ??
+ translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.fda67f0b61',
+ 'current project'
+ )}
{crossRepoPrompt?.matchingRepo ? (
void acceptGitHubLink(crossRepoPrompt.matchingRepo!)}>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.a76fcb4fa0", "Switch to")}{crossRepoPrompt.matchingRepo.displayName}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.a76fcb4fa0',
+ 'Switch to'
+ )}
+ {crossRepoPrompt.matchingRepo.displayName}
) : (
- void handleAddMatchingRepo()}>{translate("auto.components.new.workspace.SmartWorkspaceNameField.e57c53727c", "Add project...")}
+ void handleAddMatchingRepo()}>
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.e57c53727c',
+ 'Add project...'
+ )}
+
)}
@@ -1253,13 +1336,26 @@ function RowLabel({ row }: { row: RowEntry }): React.JSX.Element {
if (row.kind === 'use-name') {
return (
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.b1a7d679ba", "Use")}{translate("auto.components.new.workspace.SmartWorkspaceNameField.34ca97bce3", "\"")}{row.name}{translate("auto.components.new.workspace.SmartWorkspaceNameField.766083a596", "\"")} {translate("auto.components.new.workspace.SmartWorkspaceNameField.a44229ce4d", "as workspace name")}
+ {translate('auto.components.new.workspace.SmartWorkspaceNameField.b1a7d679ba', 'Use')}
+
+ {translate('auto.components.new.workspace.SmartWorkspaceNameField.34ca97bce3', '"')}
+ {row.name}
+ {translate('auto.components.new.workspace.SmartWorkspaceNameField.766083a596', '"')}
+ {' '}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.a44229ce4d',
+ 'as workspace name'
+ )}
+
)
}
if (row.kind === 'create-branch') {
return (
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.2a0d535f69", "Create new branch")}{' '}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.2a0d535f69',
+ 'Create new branch'
+ )}{' '}
{row.name}
)
diff --git a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx
index 52d725173cb..3533b117f07 100644
--- a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx
+++ b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx
@@ -41,7 +41,11 @@ export function AgentFeatureSetupStep({
onClick={onStartFeatureSetup}
>
{setupBusyLabel ?
: null}
- {setupBusyLabel ?? translate("auto.components.onboarding.AgentFeatureSetupStep.97dcdc010f", "Enable capabilities")}
+ {setupBusyLabel ??
+ translate(
+ 'auto.components.onboarding.AgentFeatureSetupStep.97dcdc010f',
+ 'Enable capabilities'
+ )}
) : null}
diff --git a/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx b/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
index 98bbfaeada4..56e79fb2890 100644
--- a/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
+++ b/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
@@ -23,22 +23,37 @@ type FeatureSetupRow = {
const FEATURE_SETUP_ROWS: readonly FeatureSetupRow[] = [
{
id: 'browserUse',
- title: translate("auto.components.onboarding.FeatureSetupChecklist.ea85d9e628", "Agent Browser Use"),
- description: translate("auto.components.onboarding.FeatureSetupChecklist.01426f3a23", "Agents can navigate sites, inspect pages, and work through browser tasks."),
+ title: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.ea85d9e628',
+ 'Agent Browser Use'
+ ),
+ description: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.01426f3a23',
+ 'Agents can navigate sites, inspect pages, and work through browser tasks.'
+ ),
setupSummary: 'Enables browser use, prepares orca-cli, and leaves cookies for Settings.',
icon:
},
{
id: 'computerUse',
- title: translate("auto.components.onboarding.FeatureSetupChecklist.1ecfb490ac", "Computer Use"),
- description: translate("auto.components.onboarding.FeatureSetupChecklist.c5292c409d", "Agents can inspect app windows and operate local apps when you ask."),
+ title: translate('auto.components.onboarding.FeatureSetupChecklist.1ecfb490ac', 'Computer Use'),
+ description: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.c5292c409d',
+ 'Agents can inspect app windows and operate local apps when you ask.'
+ ),
setupSummary: 'Registers the Orca CLI, opens permissions, and prepares the skill.',
icon:
},
{
id: 'orchestration',
- title: translate("auto.components.onboarding.FeatureSetupChecklist.399cf885c0", "Agent Orchestration"),
- description: translate("auto.components.onboarding.FeatureSetupChecklist.77f74946f5", "Agents can message each other, take tasks, and coordinate handoffs."),
+ title: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.399cf885c0',
+ 'Agent Orchestration'
+ ),
+ description: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.77f74946f5',
+ 'Agents can message each other, take tasks, and coordinate handoffs.'
+ ),
setupSummary: 'Registers the Orca CLI, enables orchestration, and prepares the skill.',
icon:
}
diff --git a/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx b/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx
index fe208e5ffaa..e15c796d4bf 100644
--- a/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx
+++ b/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx
@@ -57,9 +57,18 @@ export function FeatureSetupInlineTerminal({
return (
-
{translate("auto.components.onboarding.IntegrationsStep.217beb0658", "GitHub")}
- {state === "connected" ? (
- {translate("auto.components.onboarding.IntegrationsStep.c91a5782f1", "Connected")}
- ) : state === "not-installed" ? (
- {translate("auto.components.onboarding.IntegrationsStep.5c115cb713", "CLI not installed")}
- ) : state === "not-authenticated" ? (
- {translate("auto.components.onboarding.IntegrationsStep.8405043962", "Sign in needed")}
+
+ {translate('auto.components.onboarding.IntegrationsStep.217beb0658', 'GitHub')}
+
+ {state === 'connected' ? (
+
+ {translate('auto.components.onboarding.IntegrationsStep.c91a5782f1', 'Connected')}
+
+ ) : state === 'not-installed' ? (
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.5c115cb713',
+ 'CLI not installed'
+ )}
+
+ ) : state === 'not-authenticated' ? (
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.8405043962',
+ 'Sign in needed'
+ )}
+
) : (
- {translate("auto.components.onboarding.IntegrationsStep.c1547656f0", "Checking…")}
+
+ {translate('auto.components.onboarding.IntegrationsStep.c1547656f0', 'Checking…')}
+
)}
- {translate("auto.components.onboarding.IntegrationsStep.50db38cf4b", "Pull requests, issues, and check status.")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.50db38cf4b',
+ 'Pull requests, issues, and check status.'
+ )}
+
- {state === "not-installed" ? (
+ {state === 'not-installed' ? (
window.api.shell.openUrl('https://cli.github.com')}
>
- {translate("auto.components.onboarding.IntegrationsStep.bd5d976fb2", "Install gh")}
+ {translate('auto.components.onboarding.IntegrationsStep.bd5d976fb2', 'Install gh')}
+
) : null}
- {state === "not-authenticated" ? (
+ {state === 'not-authenticated' ? (
setGithubTerminalOpen(true)}
>
- {githubTerminalOpen ? translate("auto.components.onboarding.IntegrationsStep.0b4a7d23ab", "Signing in") : translate("auto.components.onboarding.IntegrationsStep.d6e5dba05a", "Sign in")}
+ {githubTerminalOpen
+ ? translate('auto.components.onboarding.IntegrationsStep.0b4a7d23ab', 'Signing in')
+ : translate('auto.components.onboarding.IntegrationsStep.d6e5dba05a', 'Sign in')}
) : null}
- {state !== "connected" ? (
+ {state !== 'connected' ? (
void refreshPreflightStatus({ force: true })}
>
- {translate("auto.components.onboarding.IntegrationsStep.80e3ce0bc9", "Re-check")}
+ {translate('auto.components.onboarding.IntegrationsStep.80e3ce0bc9', 'Re-check')}
+
) : null}
- {state === "not-authenticated" && githubTerminalOpen ? (
+ {state === 'not-authenticated' && githubTerminalOpen ? (
) : null}
@@ -122,29 +155,52 @@ export function LinearRow(props: { compact?: boolean } = {}): React.JSX.Element
-
{translate("auto.components.onboarding.IntegrationsStep.27743304b1", "Linear")}
+
+ {translate('auto.components.onboarding.IntegrationsStep.27743304b1', 'Linear')}
+
{linearStatus.connected ? (
- {translate("auto.components.onboarding.IntegrationsStep.c91a5782f1", "Connected")}
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.c91a5782f1',
+ 'Connected'
+ )}
+
) : null}
{linearStatus.connected
- ? translate("auto.components.onboarding.IntegrationsStep.b08a6ac93c", "{{value0}} workspace{{value1}} linked. Add another workspace or replace a restricted key any time.", { value0: workspaceCount, value1: workspaceCount === 1 ? '' : 's' })
- : translate("auto.components.onboarding.IntegrationsStep.4983ae7433", "Add Linear access with a Personal API key. Full-access keys can show every team the key owner can access.")}
+ ? translate(
+ 'auto.components.onboarding.IntegrationsStep.b08a6ac93c',
+ '{{value0}} workspace{{value1}} linked. Add another workspace or replace a restricted key any time.',
+ { value0: workspaceCount, value1: workspaceCount === 1 ? '' : 's' }
+ )
+ : translate(
+ 'auto.components.onboarding.IntegrationsStep.4983ae7433',
+ 'Add Linear access with a Personal API key. Full-access keys can show every team the key owner can access.'
+ )}
{linearStatus.connected ? (
setDialogOpen(true)}>
- {translate("auto.components.onboarding.IntegrationsStep.dd9c186a8b", "Add workspace access")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.dd9c186a8b',
+ 'Add workspace access'
+ )}
+
) : (
setDialogOpen(true)}>
- {translate("auto.components.onboarding.IntegrationsStep.04ef416712", "Add Linear access")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.04ef416712',
+ 'Add Linear access'
+ )}
+
)}
{!linearStatus.connected ? (
void checkLinearConnection(true)}>
- {translate("auto.components.onboarding.IntegrationsStep.80e3ce0bc9", "Re-check")}
+ {translate('auto.components.onboarding.IntegrationsStep.80e3ce0bc9', 'Re-check')}
+
) : null}
@@ -190,9 +246,18 @@ export function IntegrationsStep(): React.JSX.Element {
- {translate("auto.components.onboarding.IntegrationsStep.3a3e360289", "More task sources")}
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.3a3e360289',
+ 'More task sources'
+ )}
+
- {translate("auto.components.onboarding.IntegrationsStep.277f30eb34", "Linear, GitLab, Bitbucket, Azure DevOps, Gitea, and Jira live in Settings > Integrations.")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.277f30eb34',
+ 'Linear, GitLab, Bitbucket, Azure DevOps, Gitea, and Jira live in Settings > Integrations.'
+ )}
+
diff --git a/src/renderer/src/components/onboarding/NotificationStep.tsx b/src/renderer/src/components/onboarding/NotificationStep.tsx
index 41b3d3412e4..afdfcd3c37e 100644
--- a/src/renderer/src/components/onboarding/NotificationStep.tsx
+++ b/src/renderer/src/components/onboarding/NotificationStep.tsx
@@ -118,7 +118,12 @@ export function NotificationStep({
})
if (!result.played) {
if (mountedRef.current) {
- toast.error(translate("auto.components.onboarding.NotificationStep.b6a994e36e", "Notification sound could not be played"))
+ toast.error(
+ translate(
+ 'auto.components.onboarding.NotificationStep.b6a994e36e',
+ 'Notification sound could not be played'
+ )
+ )
}
}
}
@@ -149,7 +154,12 @@ export function NotificationStep({
const handleSendTestNotification = async (): Promise => {
if (!notificationSettings) {
- toast.error(translate("auto.components.onboarding.NotificationStep.3cd5374e22", "Notification settings are still loading"))
+ toast.error(
+ translate(
+ 'auto.components.onboarding.NotificationStep.3cd5374e22',
+ 'Notification settings are still loading'
+ )
+ )
return
}
await sendNotificationSettingsTestNotification(notificationSettings, getCustomSoundVolume())
@@ -158,7 +168,11 @@ export function NotificationStep({
if (!notificationSettings) {
return (
- {translate("auto.components.onboarding.NotificationStep.e52aacf380", "Loading notification settings…")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.e52aacf380',
+ 'Loading notification settings…'
+ )}
+
)
}
@@ -175,9 +189,17 @@ export function NotificationStep({
- {translate("auto.components.onboarding.NotificationStep.d2dba86837", "Allow Orca in macOS")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.d2dba86837',
+ 'Allow Orca in macOS'
+ )}
+
- {translate("auto.components.onboarding.NotificationStep.aa36281b00", "Open System Settings and make sure Orca is allowed to send notifications.")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.aa36281b00',
+ 'Open System Settings and make sure Orca is allowed to send notifications.'
+ )}
+
void handleMacPermission()}
>
- {translate("auto.components.onboarding.NotificationStep.8124d085a6", "Open Mac Settings")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.8124d085a6',
+ 'Open Mac Settings'
+ )}
+
) : null}
-
{translate("auto.components.onboarding.NotificationStep.0af746e41f", "Choose a sound")}
+
+ {translate('auto.components.onboarding.NotificationStep.0af746e41f', 'Choose a sound')}
+
- {translate("auto.components.onboarding.NotificationStep.0fe570690c", "Pick the alert Orca plays after a desktop notification is delivered.")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.0fe570690c',
+ 'Pick the alert Orca plays after a desktop notification is delivered.'
+ )}
+
- {translate("auto.components.onboarding.NotificationStep.53aaffe49a", "Notification Sound")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.53aaffe49a',
+ 'Notification Sound'
+ )}
+
-
+
- {customPath ? translate("auto.components.onboarding.NotificationStep.ac80d97e02", "Change Custom File") : translate("auto.components.onboarding.NotificationStep.c0692baa52", "Choose Custom File")}
+
+ {customPath
+ ? translate(
+ 'auto.components.onboarding.NotificationStep.ac80d97e02',
+ 'Change Custom File'
+ )
+ : translate(
+ 'auto.components.onboarding.NotificationStep.c0692baa52',
+ 'Choose Custom File'
+ )}
+
@@ -242,7 +293,11 @@ export function NotificationStep({
onClick={() => void handleSendTestNotification()}
>
- {translate("auto.components.onboarding.NotificationStep.3bede04483", "Send Test Notification")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.3bede04483',
+ 'Send Test Notification'
+ )}
+
diff --git a/src/renderer/src/components/onboarding/OnboardingFlow.tsx b/src/renderer/src/components/onboarding/OnboardingFlow.tsx
index 28538494863..791cf11d624 100644
--- a/src/renderer/src/components/onboarding/OnboardingFlow.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingFlow.tsx
@@ -17,21 +17,41 @@ import { translate } from '@/i18n/i18n'
const stepCopy = {
agent: {
- title: translate("auto.components.onboarding.OnboardingFlow.198b148b3c", "Pick your default agent"),
- subtitle:
- translate("auto.components.onboarding.OnboardingFlow.322fc50a18", "Orca works with every CLI agent. Choose the one you'll reach for most. Switch any time.")
+ title: translate(
+ 'auto.components.onboarding.OnboardingFlow.198b148b3c',
+ 'Pick your default agent'
+ ),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.322fc50a18',
+ "Orca works with every CLI agent. Choose the one you'll reach for most. Switch any time."
+ )
},
theme: {
- title: translate("auto.components.onboarding.OnboardingFlow.f396db9f20", "Make it feel like home"),
- subtitle: translate("auto.components.onboarding.OnboardingFlow.04ae28d8ca", "Pick the look you want to stare at for hours.")
+ title: translate(
+ 'auto.components.onboarding.OnboardingFlow.f396db9f20',
+ 'Make it feel like home'
+ ),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.04ae28d8ca',
+ 'Pick the look you want to stare at for hours.'
+ )
},
notifications: {
- title: translate("auto.components.onboarding.OnboardingFlow.b054332836", "Set up notifications"),
- subtitle: translate("auto.components.onboarding.OnboardingFlow.ff92d15436", "Orca will notify you know when agents are done or need help.")
+ title: translate(
+ 'auto.components.onboarding.OnboardingFlow.b054332836',
+ 'Set up notifications'
+ ),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.ff92d15436',
+ 'Orca will notify you know when agents are done or need help.'
+ )
},
integrations: {
- title: translate("auto.components.onboarding.OnboardingFlow.ae3b00ca82", "Set up GitHub tasks"),
- subtitle: translate("auto.components.onboarding.OnboardingFlow.97c42cda00", "Install the GitHub CLI to:")
+ title: translate('auto.components.onboarding.OnboardingFlow.ae3b00ca82', 'Set up GitHub tasks'),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.97c42cda00',
+ 'Install the GitHub CLI to:'
+ )
}
} as const
@@ -137,7 +157,10 @@ export default function OnboardingFlow({
-
{translate("auto.components.onboarding.OnboardingFlow.a249f81538", "Orca")}
+
{translate('auto.components.onboarding.OnboardingFlow.a249f81538', 'Orca')}
@@ -176,7 +199,11 @@ export default function OnboardingFlow({
? 'w-6 bg-muted-foreground/70 hover:bg-foreground/80'
: 'w-6 bg-muted-foreground/25 hover:bg-muted-foreground/45'
)}
- aria-label={translate("auto.components.onboarding.OnboardingFlow.adaa0aa627", "Go to onboarding step {{value0}}: {{value1}}", { value0: visibleIdx + 1, value1: stepCopy[step.id].title })}
+ aria-label={translate(
+ 'auto.components.onboarding.OnboardingFlow.adaa0aa627',
+ 'Go to onboarding step {{value0}}: {{value1}}',
+ { value0: visibleIdx + 1, value1: stepCopy[step.id].title }
+ )}
aria-current={isActive ? 'step' : undefined}
onClick={() => flow.jumpToStep(realStepIndex)}
/>
@@ -189,7 +216,8 @@ export default function OnboardingFlow({
})}
- {flow.visibleStepIndex + 1} {translate("auto.components.onboarding.OnboardingFlow.4db04f2f57", "of")}{' '}
+ {flow.visibleStepIndex + 1}{' '}
+ {translate('auto.components.onboarding.OnboardingFlow.4db04f2f57', 'of')}{' '}
{flow.visibleSteps.length}
@@ -197,7 +225,11 @@ export default function OnboardingFlow({
{stepIndex === 0 && (
- {translate("auto.components.onboarding.OnboardingFlow.1b5e182e9f", "Welcome to Orca")}
+ {translate(
+ 'auto.components.onboarding.OnboardingFlow.1b5e182e9f',
+ 'Welcome to Orca'
+ )}
+
)}
{copy.title}
@@ -217,7 +249,7 @@ export default function OnboardingFlow({
cn('scrollbar-sleek overflow-y-auto pr-1', 'mt-10')
)}
>
- {currentStep.id === "agent" && (
+ {currentStep.id === 'agent' && (
)}
- {currentStep.id === "theme" && (
+ {currentStep.id === 'theme' && (
)}
- {currentStep.id === "notifications" && (
+ {currentStep.id === 'notifications' && (
)}
- {currentStep.id === "integrations" && }
+ {currentStep.id === 'integrations' && }
- {translate("auto.components.onboarding.OnboardingFooter.111d3f8d92", "Skip to project setup")}
+ {translate(
+ 'auto.components.onboarding.OnboardingFooter.111d3f8d92',
+ 'Skip to project setup'
+ )}
+
) : (
)}
@@ -46,7 +50,8 @@ export function OnboardingFooter({
onClick={onBack}
>
- {translate("auto.components.onboarding.OnboardingFooter.ba58547306", "Back")}
+ {translate('auto.components.onboarding.OnboardingFooter.ba58547306', 'Back')}
+
)}
{showPrimary && (
- {translate("auto.components.onboarding.OnboardingInlineCommandTerminal.4123609efd", "Starting terminal...")}
+ {translate(
+ 'auto.components.onboarding.OnboardingInlineCommandTerminal.4123609efd',
+ 'Starting terminal...'
+ )}
+
)}
diff --git a/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx b/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
index ba3a3270c34..4b7d2602ded 100644
--- a/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
@@ -10,8 +10,14 @@ import {
import { translate } from '@/i18n/i18n'
export const ONBOARDING_SKIP_CONFIRMATION_COPY = {
- title: translate("auto.components.onboarding.OnboardingSkipConfirmationDialog.e4726b2d50", "Skip onboarding?"),
- description: translate("auto.components.onboarding.OnboardingSkipConfirmationDialog.9f47f345a4", "It won't take long!"),
+ title: translate(
+ 'auto.components.onboarding.OnboardingSkipConfirmationDialog.e4726b2d50',
+ 'Skip onboarding?'
+ ),
+ description: translate(
+ 'auto.components.onboarding.OnboardingSkipConfirmationDialog.9f47f345a4',
+ "It won't take long!"
+ ),
skipLabel: 'Skip',
keepGoingLabel: 'No, keep going'
} as const
diff --git a/src/renderer/src/components/onboarding/OnboardingTourStep.tsx b/src/renderer/src/components/onboarding/OnboardingTourStep.tsx
index ca94b92431a..a9f2b43065b 100644
--- a/src/renderer/src/components/onboarding/OnboardingTourStep.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingTourStep.tsx
@@ -85,7 +85,8 @@ export function OnboardingTourStep({
disabled={Boolean(busyLabel)}
onClick={onExitTour}
>
- {translate("auto.components.onboarding.OnboardingTourStep.60c5576353", "Exit tour")}
+ {translate('auto.components.onboarding.OnboardingTourStep.60c5576353', 'Exit tour')}
+
}
/>
)
@@ -95,7 +96,8 @@ export function OnboardingTourStep({
- {translate("auto.components.onboarding.OnboardingTourStep.3f9586c043", "Take the tour")}
+ {translate('auto.components.onboarding.OnboardingTourStep.3f9586c043', 'Take the tour')}
+
)
diff --git a/src/renderer/src/components/pet/PetOverlay.tsx b/src/renderer/src/components/pet/PetOverlay.tsx
index 9d26bc6cd02..7dfc27c3781 100644
--- a/src/renderer/src/components/pet/PetOverlay.tsx
+++ b/src/renderer/src/components/pet/PetOverlay.tsx
@@ -68,7 +68,13 @@ function SpriteFrame({
const duration = Math.max(0.1, frames / Math.max(0.1, sprite.fps))
return (
<>
-
+
{sprite ? (
- {allSelected ? translate("auto.components.repo.NestedRepoChecklist.929734aea5", "Deselect all") : translate("auto.components.repo.NestedRepoChecklist.91b5bcadb6", "Select all")}
+ {allSelected
+ ? translate('auto.components.repo.NestedRepoChecklist.929734aea5', 'Deselect all')
+ : translate('auto.components.repo.NestedRepoChecklist.91b5bcadb6', 'Select all')}
- {selectedCount} {translate("auto.components.repo.NestedRepoChecklist.ea54c7bf8f", "of")} {total} {translate("auto.components.repo.NestedRepoChecklist.f7e1170567", "selected")}
+ {selectedCount} {translate('auto.components.repo.NestedRepoChecklist.ea54c7bf8f', 'of')}{' '}
+ {total} {translate('auto.components.repo.NestedRepoChecklist.f7e1170567', 'selected')}
+
)
}
diff --git a/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx b/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx
index 3f3856a0ed9..59066a6675b 100644
--- a/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx
+++ b/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx
@@ -31,12 +31,25 @@ export function NestedRepoScanLimitNotice({ scan }: { scan: NestedRepoScanResult
onFocusCapture={() => setDetailsOpen(true)}
onBlurCapture={() => setDetailsOpen(false)}
>
-
{scan.stopped ? translate("auto.components.repo.NestedRepoScanLimitNotice.03e9beab7b", "Scan stopped early.") : translate("auto.components.repo.NestedRepoScanLimitNotice.574eb5408b", "Showing partial scan results.")}
+
+ {scan.stopped
+ ? translate(
+ 'auto.components.repo.NestedRepoScanLimitNotice.03e9beab7b',
+ 'Scan stopped early.'
+ )
+ : translate(
+ 'auto.components.repo.NestedRepoScanLimitNotice.574eb5408b',
+ 'Showing partial scan results.'
+ )}
+
) : (
- {selectedCount} {translate("auto.components.right.sidebar.BulkActionBar.60ed678138", "selected")}
+
+ {selectedCount}{' '}
+ {translate('auto.components.right.sidebar.BulkActionBar.60ed678138', 'selected')}
+
)}
@@ -40,7 +43,8 @@ export function BulkActionBar({
disabled={isExecuting}
>
- {translate("auto.components.right.sidebar.BulkActionBar.ef5f5bd06e", "Stage (")}{stageableCount})
+ {translate('auto.components.right.sidebar.BulkActionBar.ef5f5bd06e', 'Stage (')}
+ {stageableCount})
)}
{unstageableCount > 0 && (
@@ -53,7 +57,8 @@ export function BulkActionBar({
disabled={isExecuting}
>
- {translate("auto.components.right.sidebar.BulkActionBar.79a9f5f712", "Unstage (")}{unstageableCount})
+ {translate('auto.components.right.sidebar.BulkActionBar.79a9f5f712', 'Unstage (')}
+ {unstageableCount})
)}
- {translate("auto.components.right.sidebar.FileExplorer.79b1537dd3", "Select a workspace to browse files")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorer.79b1537dd3',
+ 'Select a workspace to browse files'
+ )}
+
)
}
diff --git a/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx b/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx
index c4494c427af..c661dac8a50 100644
--- a/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx
+++ b/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx
@@ -50,10 +50,18 @@ export function FileExplorerBackgroundMenu({
>
onStartNew('file', worktreePath, 0)}>
- {translate("auto.components.right.sidebar.FileExplorerBackgroundMenu.21fe46ed36", "New File")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerBackgroundMenu.21fe46ed36',
+ 'New File'
+ )}
+
onStartNew('folder', worktreePath, 0)}>
- {translate("auto.components.right.sidebar.FileExplorerBackgroundMenu.3b5e2dcb8d", "New Folder")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerBackgroundMenu.3b5e2dcb8d',
+ 'New Folder'
+ )}
+
)
diff --git a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx
index a502cbadbf0..1b706415b4e 100644
--- a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx
+++ b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx
@@ -203,7 +203,7 @@ export function InlineInputRow({
style={{ paddingLeft: `${depth * 16 + 8}px` }}
>
- {inlineInput.type === "folder" ? (
+ {inlineInput.type === 'folder' ? (
) : (
@@ -319,16 +319,32 @@ export async function downloadRemoteFile(node: TreeNode, connectionId: string):
if (result.canceled) {
return
}
- toast.success(translate("auto.components.right.sidebar.FileExplorerRow.bce4d4e44f", "Downloaded '{{value0}}'", { value0: node.name }), {
- action: {
- label: translate("auto.components.right.sidebar.FileExplorerRow.1a3df04ae1", "Open"),
- onClick: () => {
- void window.api.shell.openPath(result.destinationPath)
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.FileExplorerRow.bce4d4e44f',
+ "Downloaded '{{value0}}'",
+ { value0: node.name }
+ ),
+ {
+ action: {
+ label: translate('auto.components.right.sidebar.FileExplorerRow.1a3df04ae1', 'Open'),
+ onClick: () => {
+ void window.api.shell.openPath(result.destinationPath)
+ }
}
}
- })
+ )
} catch (error) {
- toast.error(extractIpcErrorMessage(error, translate("auto.components.right.sidebar.FileExplorerRow.b3e288bf41", "Failed to download '{{value0}}'.", { value0: node.name })))
+ toast.error(
+ extractIpcErrorMessage(
+ error,
+ translate(
+ 'auto.components.right.sidebar.FileExplorerRow.b3e288bf41',
+ "Failed to download '{{value0}}'.",
+ { value0: node.name }
+ )
+ )
+ )
}
}
@@ -539,7 +555,10 @@ export function FileExplorerRow({
) : isIgnored ? (
@@ -553,41 +572,62 @@ export function FileExplorerRow({
>
onStartNew('file', targetDir, targetDepth)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.37c875d827", "New File")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.37c875d827', 'New File')}
+
onStartNew('folder', targetDir, targetDepth)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.f61af83316", "New Folder")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.f61af83316', 'New Folder')}
+
onCopyPaths('absolute')}>
- {selectionSize > 1 ? translate("auto.components.right.sidebar.FileExplorerRow.f9d7ca753d", "Copy Paths") : translate("auto.components.right.sidebar.FileExplorerRow.b5d436aa30", "Copy Path")}
- {copyPathShortcutLabel !== "Unassigned" ? (
+ {selectionSize > 1
+ ? translate('auto.components.right.sidebar.FileExplorerRow.f9d7ca753d', 'Copy Paths')
+ : translate('auto.components.right.sidebar.FileExplorerRow.b5d436aa30', 'Copy Path')}
+ {copyPathShortcutLabel !== 'Unassigned' ? (
{copyPathShortcutLabel}
) : null}
onCopyPaths('relative')}>
- {selectionSize > 1 ? translate("auto.components.right.sidebar.FileExplorerRow.42e10cbf57", "Copy Relative Paths") : translate("auto.components.right.sidebar.FileExplorerRow.66a29dde82", "Copy Relative Path")}
- {copyRelativePathShortcutLabel !== "Unassigned" ? (
+ {selectionSize > 1
+ ? translate(
+ 'auto.components.right.sidebar.FileExplorerRow.42e10cbf57',
+ 'Copy Relative Paths'
+ )
+ : translate(
+ 'auto.components.right.sidebar.FileExplorerRow.66a29dde82',
+ 'Copy Relative Path'
+ )}
+ {copyRelativePathShortcutLabel !== 'Unassigned' ? (
{copyRelativePathShortcutLabel}
) : null}
{!node.isDirectory && (
onDuplicate(node)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.0fec99bfd7", "Duplicate")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.0fec99bfd7', 'Duplicate')}
+
)}
{canAddAsProject && (
- {translate("auto.components.right.sidebar.FileExplorerRow.1bb9be455c", "Add as Project...")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.1bb9be455c',
+ 'Add as Project...'
+ )}
+
)}
{!node.isDirectory && activeWorktreeId && (
- {translate("auto.components.right.sidebar.FileExplorerRow.dd112c81d2", "Open in Orca Browser")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.dd112c81d2',
+ 'Open in Orca Browser'
+ )}
+
)}
- {!node.isDirectory && activeWorktreeId && detectLanguage(node.path) === "markdown" && (
+ {!node.isDirectory && activeWorktreeId && detectLanguage(node.path) === 'markdown' && (
openMarkdownPreview({
@@ -599,23 +639,35 @@ export function FileExplorerRow({
}
>
- {translate("auto.components.right.sidebar.FileExplorerRow.d87a4c42e1", "Open Markdown Preview")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.d87a4c42e1',
+ 'Open Markdown Preview'
+ )}
+
)}
{showRemoteDownloadAction && (
- {translate("auto.components.right.sidebar.FileExplorerRow.c2112579f6", "Download")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.c2112579f6', 'Download')}
)}
{shouldShowCollapseFolderAction(node, isExpanded) && (
- {translate("auto.components.right.sidebar.FileExplorerRow.d6a25618aa", "Collapse Folder")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.d6a25618aa',
+ 'Collapse Folder'
+ )}
+
)}
{shouldShowFindInFolderAction(node) && (
- {translate("auto.components.right.sidebar.FileExplorerRow.0df0e5abac", "Find in Folder")}{findInFolderShortcutLabel !== "Unassigned" ? (
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.0df0e5abac',
+ 'Find in Folder'
+ )}
+ {findInFolderShortcutLabel !== 'Unassigned' ? (
{findInFolderShortcutLabel}
) : null}
@@ -646,11 +698,17 @@ export function FileExplorerRow({
onStartRename(node)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.fc747429bf", "Rename")}{isMac ? '↩' : translate("auto.components.right.sidebar.FileExplorerRow.a06551beee", "Enter")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.fc747429bf', 'Rename')}
+
+ {isMac
+ ? '↩'
+ : translate('auto.components.right.sidebar.FileExplorerRow.a06551beee', 'Enter')}
+
- {translate("auto.components.right.sidebar.FileExplorerRow.addc01145f", "Delete")}{deleteShortcutLabel}
+ {translate('auto.components.right.sidebar.FileExplorerRow.addc01145f', 'Delete')}
+ {deleteShortcutLabel}
diff --git a/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx b/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx
index d9d1e77ea67..341b2e0a472 100644
--- a/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx
+++ b/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx
@@ -58,7 +58,10 @@ export function FileExplorerToolbar({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.right.sidebar.FileExplorerToolbar.6026b16950", "Collapse All")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.6026b16950',
+ 'Collapse All'
+ )}
disabled={!canCollapseAll}
onClick={onCollapseAll}
>
@@ -66,7 +69,11 @@ export function FileExplorerToolbar({
- {translate("auto.components.right.sidebar.FileExplorerToolbar.6026b16950", "Collapse All")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.6026b16950',
+ 'Collapse All'
+ )}
+
@@ -75,7 +82,10 @@ export function FileExplorerToolbar({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28", "Refresh Explorer")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28',
+ 'Refresh Explorer'
+ )}
disabled={refresh.isRefreshing}
onClick={refresh.handleRefresh}
>
@@ -87,7 +97,11 @@ export function FileExplorerToolbar({
- {translate("auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28", "Refresh Explorer")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28',
+ 'Refresh Explorer'
+ )}
+
@@ -98,24 +112,39 @@ export function FileExplorerToolbar({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d", "More Explorer Actions")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d',
+ 'More Explorer Actions'
+ )}
>
- {translate("auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d", "More Explorer Actions")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d',
+ 'More Explorer Actions'
+ )}
+
- {translate("auto.components.right.sidebar.FileExplorerToolbar.78f133232c", "Show Dotfiles")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.78f133232c',
+ 'Show Dotfiles'
+ )}
+
{showGitIgnoredFilesToggle ? (
- {translate("auto.components.right.sidebar.FileExplorerToolbar.d238264654", "Show Git Ignored Files")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.d238264654',
+ 'Show Git Ignored Files'
+ )}
+
) : null}
- {translate("auto.components.right.sidebar.FileExplorerTreeStatus.c76693e456", "Could not load files for this workspace:")}{error}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerTreeStatus.c76693e456',
+ 'Could not load files for this workspace:'
+ )}
+ {error}
)
}
@@ -32,7 +36,11 @@ export function FileExplorerTreeStatus({
if (isEmpty) {
return (
- {translate("auto.components.right.sidebar.FileExplorerTreeStatus.ce03835e1f", "No files in this workspace")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerTreeStatus.ce03835e1f',
+ 'No files in this workspace'
+ )}
+
)
}
diff --git a/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx b/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx
index 072806cddd0..6eea947b4c6 100644
--- a/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx
+++ b/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx
@@ -169,7 +169,7 @@ export function GitHistoryGraphSvg({
viewBox={`0 0 ${width} ${SWIMLANE_HEIGHT}`}
>
{paths}
- {viewModel.kind === "HEAD" && (
+ {viewModel.kind === 'HEAD' && (
<>
>
)}
- {!isBoundaryNode && viewModel.kind !== "HEAD" && isMergeNode && (
+ {!isBoundaryNode && viewModel.kind !== 'HEAD' && isMergeNode && (
<>
>
)}
- {!isBoundaryNode && viewModel.kind !== "HEAD" && !isMergeNode && (
+ {!isBoundaryNode && viewModel.kind !== 'HEAD' && !isMergeNode && (
)}
diff --git a/src/renderer/src/components/right-sidebar/SearchFilters.tsx b/src/renderer/src/components/right-sidebar/SearchFilters.tsx
index e7c9ef0a151..c12b248f6ec 100644
--- a/src/renderer/src/components/right-sidebar/SearchFilters.tsx
+++ b/src/renderer/src/components/right-sidebar/SearchFilters.tsx
@@ -22,12 +22,16 @@ export function SearchFilters({
- {translate("auto.components.right.sidebar.SearchFilters.a69ee1bd0e", "Files To Include")}
+ {translate('auto.components.right.sidebar.SearchFilters.a69ee1bd0e', 'Files To Include')}
+
onIncludeChange(e.target.value)}
spellCheck={false}
@@ -35,12 +39,16 @@ export function SearchFilters({
- {translate("auto.components.right.sidebar.SearchFilters.0a6412a895", "Files To Exclude")}
+ {translate('auto.components.right.sidebar.SearchFilters.0a6412a895', 'Files To Exclude')}
+
onExcludeChange(e.target.value)}
spellCheck={false}
diff --git a/src/renderer/src/components/right-sidebar/SearchHeader.tsx b/src/renderer/src/components/right-sidebar/SearchHeader.tsx
index a30d64eac4b..1d84adfc574 100644
--- a/src/renderer/src/components/right-sidebar/SearchHeader.tsx
+++ b/src/renderer/src/components/right-sidebar/SearchHeader.tsx
@@ -54,7 +54,7 @@ export function SearchHeader({
ref={inputRef}
type="text"
className="flex-1 bg-transparent text-xs py-1.5 outline-none text-foreground placeholder:text-muted-foreground/50 min-w-0"
- placeholder={translate("auto.components.right.sidebar.SearchHeader.693cbeadd0", "Search")}
+ placeholder={translate('auto.components.right.sidebar.SearchHeader.693cbeadd0', 'Search')}
value={query}
onChange={onQueryChange}
onKeyDown={onKeyDown}
@@ -74,13 +74,31 @@ export function SearchHeader({
)}
-
+
-
+
-
+
diff --git a/src/renderer/src/components/right-sidebar/SearchResultItems.tsx b/src/renderer/src/components/right-sidebar/SearchResultItems.tsx
index ce60f34336d..588c12a9611 100644
--- a/src/renderer/src/components/right-sidebar/SearchResultItems.tsx
+++ b/src/renderer/src/components/right-sidebar/SearchResultItems.tsx
@@ -105,7 +105,11 @@ export function FileResultRow({
onClick={() => window.api.ui.writeClipboardText(fileResult.relativePath)}
>
- {translate("auto.components.right.sidebar.SearchResultItems.3596b9668d", "Copy Path")}
+ {translate(
+ 'auto.components.right.sidebar.SearchResultItems.3596b9668d',
+ 'Copy Path'
+ )}
+
{/* Why: the row label intentionally truncates long parent paths to
@@ -200,7 +204,11 @@ export function MatchResultRow({
onClick={() => window.api.ui.writeClipboardText(`${relativePath}#L${match.line}`)}
>
- {translate("auto.components.right.sidebar.SearchResultItems.cc06595a3b", "Copy Line Path")}
+ {translate(
+ 'auto.components.right.sidebar.SearchResultItems.cc06595a3b',
+ 'Copy Line Path'
+ )}
+
)
diff --git a/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx b/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx
index 7ef7ab9c82f..f3bb32767ab 100644
--- a/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx
@@ -101,7 +101,13 @@ export function SourceControlTextGenerationDialog({
operation: actionId,
discoveryHostKey
})
- : { ok: false as const, error: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.d054d5e0a0", "Settings are not loaded.") },
+ : {
+ ok: false as const,
+ error: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.d054d5e0a0',
+ 'Settings are not loaded.'
+ )
+ },
[actionId, discoveryHostKey, repo, settings]
)
const baseParams = resolved.ok ? resolved.value.params : null
@@ -115,19 +121,28 @@ export function SourceControlTextGenerationDialog({
? [
{
target: { type: 'repo', repoId: repo.id },
- label: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.5959da1e4d", "Save for this repository only"),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.5959da1e4d',
+ 'Save for this repository only'
+ ),
successMessage: `Saved ${recipeLabel} for this repository.`
},
{
target: { type: 'global' },
- label: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.7f1ec309a4", "Save as default for all repositories"),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.7f1ec309a4',
+ 'Save as default for all repositories'
+ ),
successMessage: `Saved ${recipeLabel} as a global default.`
}
]
: [
{
target: { type: 'global' },
- label: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.c5b7fa7cb6", "Save as global default"),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.c5b7fa7cb6',
+ 'Save as global default'
+ ),
successMessage: `Saved ${recipeLabel} as a global default.`
}
]
diff --git a/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx b/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx
index 2769eb5c60a..d6fe74e71e6 100644
--- a/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx
+++ b/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx
@@ -57,7 +57,10 @@ export function TopActivityOverflowMenu({
'relative flex h-[36px] w-8 shrink-0 items-center justify-center text-muted-foreground/60 transition-colors hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
RIGHT_SIDEBAR_HEADER_NO_DRAG_CLASS_NAME
)}
- aria-label={translate("auto.components.right.sidebar.activity.bar.buttons.1fd284e931", "More sidebar tabs")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.activity.bar.buttons.1fd284e931',
+ 'More sidebar tabs'
+ )}
>
{hiddenChecksStatus && (
@@ -124,7 +127,7 @@ export function ActivityBarButton({
>
- {statusIndicator && statusIndicator !== "neutral" && (
+ {statusIndicator && statusIndicator !== 'neutral' && (
{onCancel && (
- {translate("auto.components.right.sidebar.right.panel.comment.composer.9bca633dee", "Cancel")}
+ {translate(
+ 'auto.components.right.sidebar.right.panel.comment.composer.9bca633dee',
+ 'Cancel'
+ )}
+
)}
@@ -236,7 +275,12 @@ export function RightPanelCommentComposer({
disabled={disabled || submitting || body.trim().length === 0}
onClick={() => void submit()}
>
- {submitting ? translate("auto.components.right.sidebar.right.panel.comment.composer.87aff03d63", "Sending...") : submitLabel}
+ {submitting
+ ? translate(
+ 'auto.components.right.sidebar.right.panel.comment.composer.87aff03d63',
+ 'Sending...'
+ )
+ : submitLabel}
diff --git a/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts b/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts
index effd60f344d..191c7544482 100644
--- a/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts
+++ b/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts
@@ -42,7 +42,12 @@ export async function launchCommitFailureAgentWithDefault({
}): Promise {
const connectionId = getConnectionId(activeWorktreeId) ?? sourceRepoConnectionId ?? null
if (connectionId === undefined) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.216f762bd7", "Unable to resolve the workspace connection."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.216f762bd7',
+ 'Unable to resolve the workspace connection.'
+ )
+ )
return false
}
@@ -59,7 +64,12 @@ export async function launchCommitFailureAgentWithDefault({
return false
}
if (!commitFailureRecoveryPrompt) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.4f4e0418a0", "Could not build the agent prompt."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.4f4e0418a0',
+ 'Could not build the agent prompt.'
+ )
+ )
return false
}
const prompt = buildCommitFailureAgentCommandInput({
@@ -68,7 +78,12 @@ export async function launchCommitFailureAgentWithDefault({
basePrompt: commitFailureRecoveryPrompt
})
if (!prompt) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.f2b47026e8", "Commit failure prompt is empty. Update Source Control AI settings."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.f2b47026e8',
+ 'Commit failure prompt is empty. Update Source Control AI settings.'
+ )
+ )
return false
}
@@ -82,7 +97,12 @@ export async function launchCommitFailureAgentWithDefault({
(!detectedAgents.includes(savedAgent) ||
!isTuiAgentEnabled(savedAgent, store.settings?.disabledTuiAgents))
) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.d481ab22f9", "Saved AI agent is unavailable. Use Customize launch to choose another agent."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.d481ab22f9',
+ 'Saved AI agent is unavailable. Use Customize launch to choose another agent.'
+ )
+ )
return false
}
const agent = pickSourceControlLaunchAgent({
@@ -92,7 +112,12 @@ export async function launchCommitFailureAgentWithDefault({
disabledAgents: store.settings?.disabledTuiAgents
})
if (!agent) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.9bbd9077a2", "No enabled AI agents. Configure agents in Settings."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.9bbd9077a2',
+ 'No enabled AI agents. Configure agents in Settings.'
+ )
+ )
return false
}
const result = launchAgentInNewTab({
@@ -106,13 +131,23 @@ export async function launchCommitFailureAgentWithDefault({
launchSource: 'source_control_recovery'
})
if (!result) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.5540ff50cc", "Could not build the agent launch command."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.5540ff50cc',
+ 'Could not build the agent launch command.'
+ )
+ )
return false
}
if (result.tabId) {
focusTerminalTabSurface(result.tabId)
}
- toast.success(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.a8b97d2318", "Started an AI agent for the commit failure."))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.a8b97d2318',
+ 'Started an AI agent for the commit failure.'
+ )
+ )
return true
}
diff --git a/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts b/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts
index 4ad03735794..ff020c434ec 100644
--- a/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts
+++ b/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts
@@ -18,24 +18,44 @@ export function getDiscardEntryConfirmationCopy(
// Orca's discard path removes the working-tree file in those cases.
if (entry.area === 'untracked' || entry.status === 'untracked' || entry.status === 'added') {
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.96c772bee9", "Delete \"{{value0}}\"?", { value0: name }),
- description: translate("auto.components.right.sidebar.source.control.discard.confirmation.d97bf697c9", "This will permanently delete this file. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.96c772bee9',
+ 'Delete "{{value0}}"?',
+ { value0: name }
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.d97bf697c9',
+ 'This will permanently delete this file. This cannot be undone.'
+ ),
confirmLabel: 'Delete'
}
}
if (entry.status === 'deleted') {
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.5c0bdbc4cb", "Restore \"{{value0}}\"?", { value0: name }),
- description:
- translate("auto.components.right.sidebar.source.control.discard.confirmation.40e9357b2a", "This will restore the file from HEAD and discard the deletion. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.5c0bdbc4cb',
+ 'Restore "{{value0}}"?',
+ { value0: name }
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.40e9357b2a',
+ 'This will restore the file from HEAD and discard the deletion. This cannot be undone.'
+ ),
confirmLabel: 'Restore'
}
}
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.d4df3a61df", "Discard changes to \"{{value0}}\"?", { value0: name }),
- description: translate("auto.components.right.sidebar.source.control.discard.confirmation.1426c2efff", "This will revert all changes to this file. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.d4df3a61df',
+ 'Discard changes to "{{value0}}"?',
+ { value0: name }
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.1426c2efff',
+ 'This will revert all changes to this file. This cannot be undone.'
+ ),
confirmLabel: 'Discard'
}
}
@@ -56,14 +76,22 @@ export function getDiscardAreaConfirmationCopy(
}
case 'staged':
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.5ddd8cac7f", "Discard all staged changes?"),
- description:
- translate("auto.components.right.sidebar.source.control.discard.confirmation.ddf36f291c", "This will unstage and revert all staged changes. Staged new files will be deleted. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.5ddd8cac7f',
+ 'Discard all staged changes?'
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.ddf36f291c',
+ 'This will unstage and revert all staged changes. Staged new files will be deleted. This cannot be undone.'
+ ),
confirmLabel: 'Discard all'
}
case 'unstaged':
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.2ae5a785b3", "Discard all unstaged changes?"),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.2ae5a785b3',
+ 'Discard all unstaged changes?'
+ ),
description:
count === 1
? 'This will revert the unstaged changes in 1 file. This cannot be undone.'
diff --git a/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx b/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx
index 0df1cfa58b8..6741a72ac55 100644
--- a/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx
+++ b/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx
@@ -72,15 +72,32 @@ export function SourceControlDiscardDialog({
>
- {pendingDiscardCopy?.title ?? translate("auto.components.right.sidebar.source.control.discard.dialog.1551c14668", "Discard changes?")}
+ {pendingDiscardCopy?.title ??
+ translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.1551c14668',
+ 'Discard changes?'
+ )}
- {pendingDiscardCopy?.description ?? translate("auto.components.right.sidebar.source.control.discard.dialog.0d2d88cba5", "This cannot be undone.")}
+ {pendingDiscardCopy?.description ??
+ translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.0d2d88cba5',
+ 'This cannot be undone.'
+ )}
{pendingDiscard?.kind === 'area' ? (
- {pendingDiscard.paths.length} {pendingDiscard.paths.length === 1 ? translate("auto.components.right.sidebar.source.control.discard.dialog.e7611dca35", "file") : translate("auto.components.right.sidebar.source.control.discard.dialog.42f89dd030", "files")}
+ {pendingDiscard.paths.length}{' '}
+ {pendingDiscard.paths.length === 1
+ ? translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.e7611dca35',
+ 'file'
+ )
+ : translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.42f89dd030',
+ 'files'
+ )}
) : pendingDiscard?.kind === 'entry' ? (
@@ -89,7 +106,11 @@ export function SourceControlDiscardDialog({
) : null}
- {translate("auto.components.right.sidebar.source.control.discard.dialog.3bc61dc989", "Cancel")}
+ {translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.3bc61dc989',
+ 'Cancel'
+ )}
+
- {pendingDiscardCopy?.confirmLabel ?? translate("auto.components.right.sidebar.source.control.discard.dialog.15efa778e3", "Discard")}
+ {pendingDiscardCopy?.confirmLabel ??
+ translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.15efa778e3',
+ 'Discard'
+ )}
diff --git a/src/renderer/src/components/right-sidebar/use-source-control-ai.ts b/src/renderer/src/components/right-sidebar/use-source-control-ai.ts
index 45d54f2a3b2..2f596283388 100644
--- a/src/renderer/src/components/right-sidebar/use-source-control-ai.ts
+++ b/src/renderer/src/components/right-sidebar/use-source-control-ai.ts
@@ -160,7 +160,12 @@ export function useSourceControlAi({
return
}
if (unresolvedConflicts.length === 0) {
- toast.message(translate("auto.components.right.sidebar.use.source.control.ai.cfafa92509", "No unresolved conflicts to send."))
+ toast.message(
+ translate(
+ 'auto.components.right.sidebar.use.source.control.ai.cfafa92509',
+ 'No unresolved conflicts to send.'
+ )
+ )
return
}
setResolveConflictsComposerOpen(true)
diff --git a/src/renderer/src/components/right-sidebar/useFileDeletion.ts b/src/renderer/src/components/right-sidebar/useFileDeletion.ts
index a01de54ad0a..f46a2f09e1a 100644
--- a/src/renderer/src/components/right-sidebar/useFileDeletion.ts
+++ b/src/renderer/src/components/right-sidebar/useFileDeletion.ts
@@ -84,9 +84,16 @@ export function useFileDeletion({
? `Permanently delete '${node.name}' and all its contents? This cannot be undone.`
: `Permanently delete '${node.name}'? This cannot be undone.`
const confirmed = await confirm({
- title: translate("auto.components.right.sidebar.useFileDeletion.d979a4fbb5", "Permanently delete '{{value0}}'?", { value0: node.name }),
+ title: translate(
+ 'auto.components.right.sidebar.useFileDeletion.d979a4fbb5',
+ "Permanently delete '{{value0}}'?",
+ { value0: node.name }
+ ),
description: message,
- confirmLabel: translate("auto.components.right.sidebar.useFileDeletion.92276aceb7", "Delete"),
+ confirmLabel: translate(
+ 'auto.components.right.sidebar.useFileDeletion.92276aceb7',
+ 'Delete'
+ ),
confirmVariant: 'destructive'
})
if (!confirmed) {
@@ -185,15 +192,35 @@ export function useFileDeletion({
// to reflect that so users aren't misled into thinking they can
// recover a remote file from a Trash/Recycle Bin that doesn't exist.
if (isRemote) {
- toast.success(translate("auto.components.right.sidebar.useFileDeletion.74727df633", "'{{value0}}' deleted", { value0: node.name }))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.useFileDeletion.74727df633',
+ "'{{value0}}' deleted",
+ { value0: node.name }
+ )
+ )
} else {
const destination = isWindows ? 'Recycle Bin' : 'Trash'
- toast.success(translate("auto.components.right.sidebar.useFileDeletion.96affe1302", "'{{value0}}' moved to {{value1}}", { value0: node.name, value1: destination }))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.useFileDeletion.96affe1302',
+ "'{{value0}}' moved to {{value1}}",
+ { value0: node.name, value1: destination }
+ )
+ )
}
return true
} catch (error) {
const action = isRemote ? 'delete' : isWindows ? 'move to Recycle Bin' : 'move to Trash'
- toast.error(error instanceof Error ? error.message : translate("auto.components.right.sidebar.useFileDeletion.72691dfebc", "Failed to {{value0}} '{{value1}}'.", { value0: action, value1: node.name }))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.right.sidebar.useFileDeletion.72691dfebc',
+ "Failed to {{value0}} '{{value1}}'.",
+ { value0: action, value1: node.name }
+ )
+ )
return false
} finally {
inFlightRef.current.delete(node.path)
diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts b/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts
index 29f400472e3..175b40b5766 100644
--- a/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts
+++ b/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts
@@ -75,7 +75,12 @@ export async function activateFileExplorerNode(args: {
try {
targetIsDirectory = (await statPath(node.path)).isDirectory
} catch {
- toast.error(translate("auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991", "Cannot open symlink target"))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991',
+ 'Cannot open symlink target'
+ )
+ )
return
}
if (targetIsDirectory) {
@@ -87,7 +92,12 @@ export async function activateFileExplorerNode(args: {
markPathAsDirectory(node.path)
toggleDir(activeWorktreeId, node.path)
} else {
- toast.error(translate("auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991", "Cannot open symlink target"))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991',
+ 'Cannot open symlink target'
+ )
+ )
}
return
}
diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts b/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts
index 7ca9f218923..2b314c536cf 100644
--- a/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts
+++ b/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts
@@ -91,10 +91,22 @@ export function useFileExplorerImport({
if (failed.length > 0) {
const noun = failed.length === 1 ? 'file' : 'files'
- toast.error(translate("auto.components.right.sidebar.useFileExplorerImport.132fd0e1e9", "Failed to import {{value0}} {{value1}}.", { value0: failed.length, value1: noun }))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerImport.132fd0e1e9',
+ 'Failed to import {{value0}} {{value1}}.',
+ { value0: failed.length, value1: noun }
+ )
+ )
} else if (skipped.length > 0 && imported.length === 0) {
const noun = skipped.length === 1 ? 'file' : 'files'
- toast.error(translate("auto.components.right.sidebar.useFileExplorerImport.25919b2050", "Skipped {{value0}} {{value1}}.", { value0: skipped.length, value1: noun }))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerImport.25919b2050',
+ 'Skipped {{value0}} {{value1}}.',
+ { value0: skipped.length, value1: noun }
+ )
+ )
}
} catch (err) {
toast.error(extractIpcErrorMessage(err, 'Failed to import files.'))
diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts b/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts
index 34a00120e58..c2105f78850 100644
--- a/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts
+++ b/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts
@@ -149,7 +149,14 @@ export function useFileExplorerKeys(opts: {
e.preventDefault()
const run = wantRedo ? redoFileExplorer() : undoFileExplorer()
void run.catch((err: unknown) => {
- toast.error(err instanceof Error ? err.message : translate("auto.components.right.sidebar.useFileExplorerKeys.8adb953095", "Operation failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.right.sidebar.useFileExplorerKeys.8adb953095',
+ 'Operation failed'
+ )
+ )
})
return
}
diff --git a/src/renderer/src/components/settings/AgentLocationSetting.tsx b/src/renderer/src/components/settings/AgentLocationSetting.tsx
index 124f39eda50..fa7d1c072f9 100644
--- a/src/renderer/src/components/settings/AgentLocationSetting.tsx
+++ b/src/renderer/src/components/settings/AgentLocationSetting.tsx
@@ -36,7 +36,10 @@ function getSelectedAgentRuntime(
settings.localAgentRuntime ?? (settings.terminalWindowsShell === 'wsl.exe' ? 'wsl' : 'host')
if (wslSupportedPlatform && configuredRuntime === 'wsl') {
if (!wslAvailable && !wslCapabilitiesLoading) {
- return { runtime: 'wsl', label: translate("auto.components.settings.AgentLocationSetting.43663b5e69", "WSL") }
+ return {
+ runtime: 'wsl',
+ label: translate('auto.components.settings.AgentLocationSetting.43663b5e69', 'WSL')
+ }
}
const configuredDistro =
settings.localAgentWslDistro?.trim() || settings.terminalWindowsWslDistro?.trim() || null
@@ -80,17 +83,30 @@ export function AgentLocationSetting({
return (
updateAgentLocation({ localAgentRuntime: value })}
equalWidth
@@ -100,14 +116,17 @@ export function AgentLocationSetting({
? [
{
value: 'wsl',
- label: translate("auto.components.settings.AgentLocationSetting.43663b5e69", "WSL"),
+ label: translate(
+ 'auto.components.settings.AgentLocationSetting.43663b5e69',
+ 'WSL'
+ ),
disabled: wslCapabilitiesLoading || !wslAvailable
} as const
]
: [])
]}
/>
- {wslSupportedPlatform && agentRuntime.runtime === "wsl" ? (
+ {wslSupportedPlatform && agentRuntime.runtime === 'wsl' ? (
@@ -120,11 +139,26 @@ export function AgentLocationSetting({
>
- {translate("auto.components.settings.AgentLocationSetting.92f4238f1a", "WSL default")}
+
+ {translate(
+ 'auto.components.settings.AgentLocationSetting.92f4238f1a',
+ 'WSL default'
+ )}
+
{wslDistros.map((distro) => (
{distro}
diff --git a/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx b/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx
index 35172b770a0..fca5d39fec5 100644
--- a/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx
+++ b/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx
@@ -132,9 +132,21 @@ export function AgentSkillSetupPanel({
const copyInstallCommand = async (): Promise => {
try {
await window.api.ui.writeClipboardText(command)
- toast.success(translate("auto.components.settings.AgentSkillSetupPanel.378ad26865", "Copied install command."))
+ toast.success(
+ translate(
+ 'auto.components.settings.AgentSkillSetupPanel.378ad26865',
+ 'Copied install command.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.AgentSkillSetupPanel.a31e2aa302", "Failed to copy install command."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.AgentSkillSetupPanel.a31e2aa302',
+ 'Failed to copy install command.'
+ )
+ )
}
}
@@ -173,7 +185,8 @@ export function AgentSkillSetupPanel({
disabled={loading}
>
- {translate("auto.components.settings.AgentSkillSetupPanel.c689392435", "Re-check")}
+ {translate('auto.components.settings.AgentSkillSetupPanel.c689392435', 'Re-check')}
+
) : null}
)
@@ -205,11 +218,26 @@ export function AgentSkillSetupPanel({
{title}
{loading && !installed ? (
- {translate("auto.components.settings.AgentSkillSetupPanel.68a468752e", "Checking...")}
+
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.68a468752e',
+ 'Checking...'
+ )}
+
) : installed ? (
- {translate("auto.components.settings.AgentSkillSetupPanel.9fcebceb2a", "Installed")}
+
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.9fcebceb2a',
+ 'Installed'
+ )}
+
) : (
- {translate("auto.components.settings.AgentSkillSetupPanel.5289300939", "Not installed")}
+
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.5289300939',
+ 'Not installed'
+ )}
+
)}
{error ? {error}
: null}
@@ -252,21 +280,31 @@ export function AgentSkillSetupPanel({
variant="ghost"
size="icon-sm"
className="shrink-0"
- aria-label={translate("auto.components.settings.AgentSkillSetupPanel.817d3f9f18", "Copy install command")}
+ aria-label={translate(
+ 'auto.components.settings.AgentSkillSetupPanel.817d3f9f18',
+ 'Copy install command'
+ )}
onClick={() => void copyInstallCommand()}
>
- {translate("auto.components.settings.AgentSkillSetupPanel.ed197f59a2", "Copy command")}
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.ed197f59a2',
+ 'Copy command'
+ )}
+
- onChange(getOffsetIcon(selected, -1))}>
+ onChange(getOffsetIcon(selected, -1))}
+ >
- onChange(getOffsetIcon(selected, 1))}>
+ onChange(getOffsetIcon(selected, 1))}
+ >
diff --git a/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx b/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx
index 84e3d34d9d5..2cf73e5436c 100644
--- a/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx
+++ b/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx
@@ -31,16 +31,25 @@ export function AutoRenameBranchPromptEditor({
// divide-y divider the way the model/prompt rows are spaced.
-
{translate("auto.components.settings.AutoRenameBranchPromptEditor.7d6176f506", "Prompt")}
+
+ {translate('auto.components.settings.AutoRenameBranchPromptEditor.7d6176f506', 'Prompt')}
+
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.2f5dc661fe", "Appended to Orca's")}{' '}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.2f5dc661fe',
+ "Appended to Orca's"
+ )}{' '}
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.182d419b97", "built-in branch-name prompt")}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.182d419b97',
+ 'built-in branch-name prompt'
+ )}
+
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.af2d9a2cc6", ". Orca generates only the final segment, like")}{' '}
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.ebb942a2ec", "fix-login-flow")}{translate("auto.components.settings.AutoRenameBranchPromptEditor.39278f4411", "; your branch prefix setting still applies.")}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.af2d9a2cc6',
+ '. Orca generates only the final segment, like'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.ebb942a2ec',
+ 'fix-login-flow'
+ )}
+
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.39278f4411',
+ '; your branch prefix setting still applies.'
+ )}
+
onDraftChange(event.target.value)}
- placeholder={translate("auto.components.settings.AutoRenameBranchPromptEditor.4416b25d29", "Prefer domain nouns from the task, avoid ticket IDs, and keep names reviewer-friendly.")}
+ placeholder={translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.4416b25d29',
+ 'Prefer domain nouns from the task, avoid ticket IDs, and keep names reviewer-friendly.'
+ )}
className="w-full resize-y rounded-md border border-border bg-background px-2 py-1.5 text-xs text-foreground outline-none placeholder:text-muted-foreground/70 focus-visible:ring-1 focus-visible:ring-ring"
/>
-
{dirty ? translate("auto.components.settings.AutoRenameBranchPromptEditor.0691753cf2", "Unsaved changes") : translate("auto.components.settings.AutoRenameBranchPromptEditor.af0831a590", "Saved")}
+
+ {dirty
+ ? translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.0691753cf2',
+ 'Unsaved changes'
+ )
+ : translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.af0831a590',
+ 'Saved'
+ )}
+
{dirty ? (
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.63121132c0", "Discard")}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.63121132c0',
+ 'Discard'
+ )}
+
) : null}
void onSave()}
disabled={!dirty || saving}
>
- {saving ? translate("auto.components.settings.AutoRenameBranchPromptEditor.54ac229ad4", "Saving...") : translate("auto.components.settings.AutoRenameBranchPromptEditor.5968112152", "Save")}
+ {saving
+ ? translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.54ac229ad4',
+ 'Saving...'
+ )
+ : translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.5968112152',
+ 'Save'
+ )}
diff --git a/src/renderer/src/components/settings/BaseRefPicker.tsx b/src/renderer/src/components/settings/BaseRefPicker.tsx
index b94bb4cad5f..6c0513e5dbe 100644
--- a/src/renderer/src/components/settings/BaseRefPicker.tsx
+++ b/src/renderer/src/components/settings/BaseRefPicker.tsx
@@ -116,14 +116,25 @@ export function BaseRefPicker({
- {effectiveBaseRef ?? translate("auto.components.settings.BaseRefPicker.ee110e1830", "No default base ref")}
+ {effectiveBaseRef ??
+ translate('auto.components.settings.BaseRefPicker.ee110e1830', 'No default base ref')}
{currentBaseRef
- ? translate("auto.components.settings.BaseRefPicker.2f3cda96f5", "Pinned for this repo")
+ ? translate(
+ 'auto.components.settings.BaseRefPicker.2f3cda96f5',
+ 'Pinned for this repo'
+ )
: defaultBaseRef
- ? translate("auto.components.settings.BaseRefPicker.086ce7f369", "Following primary branch ({{value0}})", { value0: defaultBaseRef })
- : translate("auto.components.settings.BaseRefPicker.9a14ec7400", "Pick a base branch below")}
+ ? translate(
+ 'auto.components.settings.BaseRefPicker.086ce7f369',
+ 'Following primary branch ({{value0}})',
+ { value0: defaultBaseRef }
+ )
+ : translate(
+ 'auto.components.settings.BaseRefPicker.9a14ec7400',
+ 'Pick a base branch below'
+ )}
{/* Why: passive hint that fork workflows have other remotes worth
searching (e.g. `upstream`). Host-agnostic and remote-name-agnostic
@@ -137,24 +148,48 @@ export function BaseRefPicker({
// whenever remoteCount>1, not a dynamic status update. aria-live would
// cause screen readers to re-announce it on every mount/repo switch.
- {translate("auto.components.settings.BaseRefPicker.a5c16712c1", "Multiple remotes detected. Type a remote name (e.g.")}{translate("auto.components.settings.BaseRefPicker.915ad97875", "upstream")}{translate("auto.components.settings.BaseRefPicker.80f7c82303", ") or a full ref (e.g.")}{translate("auto.components.settings.BaseRefPicker.b468f46726", "upstream/main")}{translate("auto.components.settings.BaseRefPicker.ade9a5bb03", ") to scope results.")}
+ {translate(
+ 'auto.components.settings.BaseRefPicker.a5c16712c1',
+ 'Multiple remotes detected. Type a remote name (e.g.'
+ )}
+
+ {translate('auto.components.settings.BaseRefPicker.915ad97875', 'upstream')}
+
+ {translate(
+ 'auto.components.settings.BaseRefPicker.80f7c82303',
+ ') or a full ref (e.g.'
+ )}
+
+ {translate('auto.components.settings.BaseRefPicker.b468f46726', 'upstream/main')}
+
+ {translate(
+ 'auto.components.settings.BaseRefPicker.ade9a5bb03',
+ ') to scope results.'
+ )}
+
) : null}
{onUsePrimary && (
- {translate("auto.components.settings.BaseRefPicker.773a5687a3", "Use Primary")}
+ {translate('auto.components.settings.BaseRefPicker.773a5687a3', 'Use Primary')}
+
)}
setBaseRefQuery(e.target.value)}
- placeholder={translate("auto.components.settings.BaseRefPicker.7db7fb87e5", "Search branches by name...")}
+ placeholder={translate(
+ 'auto.components.settings.BaseRefPicker.7db7fb87e5',
+ 'Search branches by name...'
+ )}
className="max-w-md"
/>
{isSearchingBaseRefs ? (
- {translate("auto.components.settings.BaseRefPicker.a4a9372eb2", "Searching branches...")}
+
+ {translate('auto.components.settings.BaseRefPicker.a4a9372eb2', 'Searching branches...')}
+
) : null}
{!isSearchingBaseRefs && baseRefQuery.trim().length >= 2 ? (
@@ -182,14 +217,21 @@ export function BaseRefPicker({
>
{ref}
{effectiveBaseRef === ref ? (
- {translate("auto.components.settings.BaseRefPicker.d166ff883d", "Current")}
+
+ {translate('auto.components.settings.BaseRefPicker.d166ff883d', 'Current')}
+
) : null}
))}
) : (
- {translate("auto.components.settings.BaseRefPicker.1b8e54151f", "No matching branches found.")}
+
+ {translate(
+ 'auto.components.settings.BaseRefPicker.1b8e54151f',
+ 'No matching branches found.'
+ )}
+
)
) : null}
diff --git a/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx b/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx
index b078f6d4188..6c7ef5c5b2a 100644
--- a/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx
+++ b/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx
@@ -21,14 +21,30 @@ export function BrowserDefaultZoomSetting({
return (
-
{translate("auto.components.settings.BrowserDefaultZoomSetting.265597101f", "Default Zoom")}
-
{translate("auto.components.settings.BrowserDefaultZoomSetting.bbeec087d3", "Applied to newly opened browser tabs.")}
+
+ {translate(
+ 'auto.components.settings.BrowserDefaultZoomSetting.265597101f',
+ 'Default Zoom'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.BrowserDefaultZoomSetting.bbeec087d3',
+ 'Applied to newly opened browser tabs.'
+ )}
+
onChange(Number(next))}>
diff --git a/src/renderer/src/components/settings/BrowserHomePageSetting.tsx b/src/renderer/src/components/settings/BrowserHomePageSetting.tsx
index c589ce204af..f0b25262ea6 100644
--- a/src/renderer/src/components/settings/BrowserHomePageSetting.tsx
+++ b/src/renderer/src/components/settings/BrowserHomePageSetting.tsx
@@ -20,15 +20,30 @@ export function BrowserHomePageSetting({
}: BrowserHomePageSettingProps): React.JSX.Element {
return (
-
{translate("auto.components.settings.BrowserHomePageSetting.70224e37b1", "Default Home Page")}
+
+ {translate(
+ 'auto.components.settings.BrowserHomePageSetting.70224e37b1',
+ 'Default Home Page'
+ )}
+
- {translate("auto.components.settings.BrowserHomePageSetting.6a37540f4b", "URL opened when creating a new browser tab. Leave empty to open a blank tab.")}
+ {translate(
+ 'auto.components.settings.BrowserHomePageSetting.6a37540f4b',
+ 'URL opened when creating a new browser tab. Leave empty to open a blank tab.'
+ )}
+
onChange(event.target.value)}
- placeholder={translate("auto.components.settings.BrowserHomePageSetting.37a30c5bfd", "https://google.com")}
+ placeholder={translate(
+ 'auto.components.settings.BrowserHomePageSetting.37a30c5bfd',
+ 'https://google.com'
+ )}
spellCheck={false}
autoCapitalize="none"
autoCorrect="off"
className="h-7 w-52 text-xs"
/>
- {translate("auto.components.settings.BrowserHomePageSetting.d4ddcd0056", "Save")}
+ {translate('auto.components.settings.BrowserHomePageSetting.d4ddcd0056', 'Save')}
+
)
diff --git a/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx b/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx
index 1d7d5bd3e24..c498caf9fef 100644
--- a/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx
+++ b/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx
@@ -11,9 +11,18 @@ export function BrowserUseComputerUseNotice({
-
{translate("auto.components.settings.BrowserUseComputerUseNotice.333984cf90", "Use an existing browser session")}
+
+ {translate(
+ 'auto.components.settings.BrowserUseComputerUseNotice.333984cf90',
+ 'Use an existing browser session'
+ )}
+
- {translate("auto.components.settings.BrowserUseComputerUseNotice.79209b37b9", "If cookie import is not the right fit, Computer Use can control local apps and may use existing logged-in browser sessions where applicable. Install the Computer Use skill; macOS also requires privacy permissions.")}
+ {translate(
+ 'auto.components.settings.BrowserUseComputerUseNotice.79209b37b9',
+ 'If cookie import is not the right fit, Computer Use can control local apps and may use existing logged-in browser sessions where applicable. Install the Computer Use skill; macOS also requires privacy permissions.'
+ )}
+
- {translate("auto.components.settings.BrowserUseComputerUseNotice.15b5e680ba", "Open Computer Use")}
+ {translate(
+ 'auto.components.settings.BrowserUseComputerUseNotice.15b5e680ba',
+ 'Open Computer Use'
+ )}
+
)
diff --git a/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx b/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx
index 36a965900ae..cbb4c3361b4 100644
--- a/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx
+++ b/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx
@@ -10,7 +10,10 @@ export function BrowserUseEnableSwitch({
{
try {
await window.api.ui.writeClipboardText(text)
- toast.success(translate("auto.components.settings.BrowserUseExamples.a602d43069", "Copied {{value0}}.", { value0: label }))
+ toast.success(
+ translate('auto.components.settings.BrowserUseExamples.a602d43069', 'Copied {{value0}}.', {
+ value0: label
+ })
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.BrowserUseExamples.5ec620ccc4", "Failed to copy."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate('auto.components.settings.BrowserUseExamples.5ec620ccc4', 'Failed to copy.')
+ )
}
}
@@ -24,10 +32,19 @@ export function BrowserUseExamples(): React.JSX.Element {
-
{translate("auto.components.settings.BrowserUseExamples.2a180694f7", "Try it — example prompts")}
+
+ {translate(
+ 'auto.components.settings.BrowserUseExamples.2a180694f7',
+ 'Try it — example prompts'
+ )}
+
- {translate("auto.components.settings.BrowserUseExamples.c5325e91f6", "Paste any of these into Claude Code, Codex, or another agent in a project where the skill is installed.")}
+ {translate(
+ 'auto.components.settings.BrowserUseExamples.c5325e91f6',
+ 'Paste any of these into Claude Code, Codex, or another agent in a project where the skill is installed.'
+ )}
+
- {updateStatus.state === 'idle' && translate("auto.components.settings.GeneralUpdateSettingsSection.d69a09b672", "Updates are checked automatically on launch.")}
- {updateStatus.state === 'checking' && translate("auto.components.settings.GeneralUpdateSettingsSection.31fd7150cf", "Checking for updates...")}
+ {updateStatus.state === 'idle' &&
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.d69a09b672',
+ 'Updates are checked automatically on launch.'
+ )}
+ {updateStatus.state === 'checking' &&
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.31fd7150cf',
+ 'Checking for updates...'
+ )}
{updateStatus.state === 'available' && (
<>
- {translate("auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc", "Version")}{updateStatus.version} {translate("auto.components.settings.GeneralUpdateSettingsSection.8311da27ba", "is available. Click \"Install Update\" to download and install it.")}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc',
+ 'Version'
+ )}
+ {updateStatus.version}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.8311da27ba',
+ 'is available. Click "Install Update" to download and install it.'
+ )}{' '}
- {translate("auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02", "Release notes")}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02',
+ 'Release notes'
+ )}
+
>
)}
- {updateStatus.state === 'not-available' && translate("auto.components.settings.GeneralUpdateSettingsSection.f40d88390d", "You’re on the latest version.")}
+ {updateStatus.state === 'not-available' &&
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.f40d88390d',
+ 'You’re on the latest version.'
+ )}
{updateStatus.state === 'downloading' &&
- translate("auto.components.settings.GeneralUpdateSettingsSection.2a48034c4c", "Downloading v{{value0}}... {{value1}}%", { value0: updateStatus.version, value1: updateStatus.percent })}
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.2a48034c4c',
+ 'Downloading v{{value0}}... {{value1}}%',
+ { value0: updateStatus.version, value1: updateStatus.percent }
+ )}
{updateStatus.state === 'downloaded' && (
<>
- {translate("auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc", "Version")}{updateStatus.version} {translate("auto.components.settings.GeneralUpdateSettingsSection.d89806cc89", "is ready to install.")}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc',
+ 'Version'
+ )}
+ {updateStatus.version}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.d89806cc89',
+ 'is ready to install.'
+ )}{' '}
- {translate("auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02", "Release notes")}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02',
+ 'Release notes'
+ )}
+
>
)}
{updateStatus.state === 'error' &&
@@ -159,8 +230,16 @@ export function GeneralUpdateSettingsSection(): React.JSX.Element {
// 'downloaded' state). Label accordingly so a download failure
// isn't mislabeled as a "check" failure. Mirrors UpdateCard.tsx.
(updateVersionRef.current
- ? translate("auto.components.settings.GeneralUpdateSettingsSection.b9ad70c30d", "Update error. {{value0}}", { value0: updateStatus.message })
- : translate("auto.components.settings.GeneralUpdateSettingsSection.bd79d412f0", "Update check failed. {{value0}}", { value0: updateStatus.message }))}
+ ? translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.b9ad70c30d',
+ 'Update error. {{value0}}',
+ { value0: updateStatus.message }
+ )
+ : translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.bd79d412f0',
+ 'Update check failed. {{value0}}',
+ { value0: updateStatus.message }
+ ))}
diff --git a/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx b/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx
index 0da472b900a..9686ac70781 100644
--- a/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx
+++ b/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx
@@ -28,17 +28,34 @@ export function GeneralWorkspaceSettingsSection({
return (
- {translate("auto.components.settings.GeneralWorkspaceSettingsSection.0e9fc0eadc", "Workspace Directory")}
+
+ {translate(
+ 'auto.components.settings.GeneralWorkspaceSettingsSection.0e9fc0eadc',
+ 'Workspace Directory'
+ )}
+
- {translate("auto.components.settings.GeneralWorkspaceSettingsSection.5567191a6e", "Browse")}
+ {translate(
+ 'auto.components.settings.GeneralWorkspaceSettingsSection.5567191a6e',
+ 'Browse'
+ )}
+
- {translate("auto.components.settings.GeneralWorkspaceSettingsSection.a246f5ce6f", "Root directory where workspace folders are created.")}
+ {translate(
+ 'auto.components.settings.GeneralWorkspaceSettingsSection.a246f5ce6f',
+ 'Root directory where workspace folders are created.'
+ )}
+
updateSettings({ nestWorkspaces: !settings.nestWorkspaces })}
/>
@@ -76,13 +113,25 @@ export function GeneralWorkspaceSettingsSection({
breaks that toast action even though this pane still renders fine. */}
updateSettings({
@@ -95,13 +144,25 @@ export function GeneralWorkspaceSettingsSection({
updateSettings({
@@ -118,8 +179,14 @@ export function GeneralWorkspaceSettingsSection({
className="scroll-mt-6"
>
- {translate("auto.components.settings.GhosttyImportModal.d2f33670a9", "Import from Ghostty")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.d2f33670a9',
+ 'Import from Ghostty'
+ )}
+
- {translate("auto.components.settings.GhosttyImportModal.2763b0c045", "Review the settings that will be imported from your Ghostty config.")}
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.2763b0c045',
+ 'Review the settings that will be imported from your Ghostty config.'
+ )}
+
{loading ? (
- {translate("auto.components.settings.GhosttyImportModal.023a52c1f7", "Loading preview…")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.023a52c1f7',
+ 'Loading preview…'
+ )}
+
) : preview == null ? null : preview.found ? (
{configPaths.length > 0 && !applied && (
- {configPaths.length === 1 ? translate("auto.components.settings.GhosttyImportModal.1f744a72f4", "Config") : translate("auto.components.settings.GhosttyImportModal.273e7e81fe", "Configs")}: {configPaths.join(', ')}
+ {configPaths.length === 1
+ ? translate('auto.components.settings.GhosttyImportModal.1f744a72f4', 'Config')
+ : translate('auto.components.settings.GhosttyImportModal.273e7e81fe', 'Configs')}
+ : {configPaths.join(', ')}
)}
{applied ? (
-
{translate("auto.components.settings.GhosttyImportModal.4466f4cdaa", "Import complete")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.4466f4cdaa',
+ 'Import complete'
+ )}
+
{Object.entries(preview.diff).map(([key, value]) => (
@@ -75,7 +97,12 @@ export function GhosttyImportModal({
) : hasChanges ? (
-
{translate("auto.components.settings.GhosttyImportModal.a4c5dec640", "Settings to update")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.a4c5dec640',
+ 'Settings to update'
+ )}
+
{Object.entries(preview.diff).map(([key, value]) => (
@@ -87,14 +114,23 @@ export function GhosttyImportModal({
) : (
- {translate("auto.components.settings.GhosttyImportModal.674b5ccd6b", "No new settings to import — your current settings already match.")}
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.674b5ccd6b',
+ 'No new settings to import — your current settings already match.'
+ )}
+
)}
{!applied && applyError &&
{applyError}
}
{!applied && preview.unsupportedKeys.length > 0 && (
-
{translate("auto.components.settings.GhosttyImportModal.b58d4c9051", "Unsupported keys")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.b58d4c9051',
+ 'Unsupported keys'
+ )}
+
{preview.unsupportedKeys.map((key) => (
@@ -108,17 +144,32 @@ export function GhosttyImportModal({
) : preview.error ? (
{preview.error}
) : (
- {translate("auto.components.settings.GhosttyImportModal.e4bda7ce6f", "No Ghostty config found on this system.")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.e4bda7ce6f',
+ 'No Ghostty config found on this system.'
+ )}
+
)}
{applied ? (
- onOpenChange(false)}>{translate("auto.components.settings.GhosttyImportModal.b7ddae600c", "Done")}
+ onOpenChange(false)}>
+ {translate('auto.components.settings.GhosttyImportModal.b7ddae600c', 'Done')}
+
) : (
<>
onOpenChange(false)}>
- {translate("auto.components.settings.GhosttyImportModal.f96688b6bc", "Cancel")}
- {hasChanges && void onApply()}>{translate("auto.components.settings.GhosttyImportModal.9d3e56ca36", "Apply Changes")} }
+ {translate('auto.components.settings.GhosttyImportModal.f96688b6bc', 'Cancel')}
+
+ {hasChanges && (
+ void onApply()}>
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.9d3e56ca36',
+ 'Apply Changes'
+ )}
+
+ )}
>
)}
diff --git a/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx b/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx
index ab778e0135e..bcf702c166a 100644
--- a/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx
+++ b/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx
@@ -10,20 +10,40 @@ export function HiddenExperimentalGroup(): React.JSX.Element {
- {translate("auto.components.settings.HiddenExperimentalGroup.3e9e827ca5", "Hidden experimental")}
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.3e9e827ca5',
+ 'Hidden experimental'
+ )}
+
- {translate("auto.components.settings.HiddenExperimentalGroup.232cf83de8", "Unlisted toggles for internal testing. Nothing here is supported.")}
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.232cf83de8',
+ 'Unlisted toggles for internal testing. Nothing here is supported.'
+ )}
+
-
{translate("auto.components.settings.HiddenExperimentalGroup.d0f914a528", "Placeholder toggle")}
+
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.d0f914a528',
+ 'Placeholder toggle'
+ )}
+
- {translate("auto.components.settings.HiddenExperimentalGroup.1014ddbfaf", "Does nothing today. Reserved as the first slot for hidden experimental options.")}
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.1014ddbfaf',
+ 'Does nothing today. Reserved as the first slot for hidden experimental options.'
+ )}
+
diff --git a/src/renderer/src/components/settings/KagiSessionLinkForm.tsx b/src/renderer/src/components/settings/KagiSessionLinkForm.tsx
index 2e5255fd7c0..d9ea1e1b4a2 100644
--- a/src/renderer/src/components/settings/KagiSessionLinkForm.tsx
+++ b/src/renderer/src/components/settings/KagiSessionLinkForm.tsx
@@ -50,17 +50,32 @@ export function KagiSessionLinkForm(): React.JSX.Element {
if (!trimmed) {
setBrowserKagiSessionLink(null)
setDraftState(createKagiSessionLinkDraftState(''))
- toast.success(translate("auto.components.settings.KagiSessionLinkForm.9f741627a7", "Kagi session link cleared."))
+ toast.success(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.9f741627a7',
+ 'Kagi session link cleared.'
+ )
+ )
return
}
const normalized = normalizeKagiSessionLink(trimmed)
if (!normalized) {
- toast.error(translate("auto.components.settings.KagiSessionLinkForm.0911d5fa4c", "Enter a Kagi private session link from https://kagi.com/search?token=..."))
+ toast.error(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.0911d5fa4c',
+ 'Enter a Kagi private session link from https://kagi.com/search?token=...'
+ )
+ )
return
}
setBrowserKagiSessionLink(normalized)
setDraftState(createKagiSessionLinkDraftState(normalized))
- toast.success(translate("auto.components.settings.KagiSessionLinkForm.3e5b7c6c25", "Kagi session link saved."))
+ toast.success(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.3e5b7c6c25',
+ 'Kagi session link saved.'
+ )
+ )
}
return (
@@ -72,22 +87,33 @@ export function KagiSessionLinkForm(): React.JSX.Element {
}}
>
- {translate("auto.components.settings.KagiSessionLinkForm.81409d9362", "Optional private session link for Kagi auth.")}
+ {translate(
+ 'auto.components.settings.KagiSessionLinkForm.81409d9362',
+ 'Optional private session link for Kagi auth.'
+ )}
+
setDraft(e.target.value)}
- placeholder={translate("auto.components.settings.KagiSessionLinkForm.e383683485", "https://kagi.com/search?token=...")}
+ placeholder={translate(
+ 'auto.components.settings.KagiSessionLinkForm.e383683485',
+ 'https://kagi.com/search?token=...'
+ )}
spellCheck={false}
autoCapitalize="none"
autoCorrect="off"
autoComplete="off"
- aria-label={translate("auto.components.settings.KagiSessionLinkForm.ff450194cd", "Kagi private session link")}
+ aria-label={translate(
+ 'auto.components.settings.KagiSessionLinkForm.ff450194cd',
+ 'Kagi private session link'
+ )}
className="h-7 w-72 text-xs"
/>
- {translate("auto.components.settings.KagiSessionLinkForm.d5c8b94c5b", "Save")}
+ {translate('auto.components.settings.KagiSessionLinkForm.d5c8b94c5b', 'Save')}
+
{browserKagiSessionLink ? (
{
setBrowserKagiSessionLink(null)
setDraftState(createKagiSessionLinkDraftState(''))
- toast.success(translate("auto.components.settings.KagiSessionLinkForm.9f741627a7", "Kagi session link cleared."))
+ toast.success(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.9f741627a7',
+ 'Kagi session link cleared.'
+ )
+ )
}}
>
- {translate("auto.components.settings.KagiSessionLinkForm.92f0b4e472", "Clear")}
+ {translate('auto.components.settings.KagiSessionLinkForm.92f0b4e472', 'Clear')}
+
) : null}
diff --git a/src/renderer/src/components/settings/KeybindingsFileActions.tsx b/src/renderer/src/components/settings/KeybindingsFileActions.tsx
index 41b9928634f..24a6a5116da 100644
--- a/src/renderer/src/components/settings/KeybindingsFileActions.tsx
+++ b/src/renderer/src/components/settings/KeybindingsFileActions.tsx
@@ -71,7 +71,12 @@ export function KeybindingsFileActions(): React.JSX.Element {
try {
const filePath = await prepareKeybindingsPath()
if (!filePath) {
- toast.error(translate("auto.components.settings.KeybindingsFileActions.cdf794f46d", "Keybindings file is not available."))
+ toast.error(
+ translate(
+ 'auto.components.settings.KeybindingsFileActions.cdf794f46d',
+ 'Keybindings file is not available.'
+ )
+ )
return
}
const existingFile = openFiles.find(
@@ -104,7 +109,14 @@ export function KeybindingsFileActions(): React.JSX.Element {
}
})
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.KeybindingsFileActions.dd532a01ce", "Failed to open keybindings in Orca."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.KeybindingsFileActions.dd532a01ce',
+ 'Failed to open keybindings in Orca.'
+ )
+ )
}
}
@@ -112,7 +124,12 @@ export function KeybindingsFileActions(): React.JSX.Element {
try {
const filePath = await prepareKeybindingsPath()
if (!filePath) {
- toast.error(translate("auto.components.settings.KeybindingsFileActions.cdf794f46d", "Keybindings file is not available."))
+ toast.error(
+ translate(
+ 'auto.components.settings.KeybindingsFileActions.cdf794f46d',
+ 'Keybindings file is not available.'
+ )
+ )
return
}
const result = await window.api.shell.openInExternalEditor(filePath, command)
@@ -120,7 +137,14 @@ export function KeybindingsFileActions(): React.JSX.Element {
toast.error(openFailureMessage(result.reason))
}
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.KeybindingsFileActions.c5886a31cc", "Failed to open external editor."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.KeybindingsFileActions.c5886a31cc',
+ 'Failed to open external editor.'
+ )
+ )
}
}
@@ -137,7 +161,11 @@ export function KeybindingsFileActions(): React.JSX.Element {
onClick={() => void editKeybindingsInOrca()}
>
- {translate("auto.components.settings.KeybindingsFileActions.1c2be2b2c6", "Edit File in Orca")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.1c2be2b2c6',
+ 'Edit File in Orca'
+ )}
+
@@ -153,20 +184,40 @@ export function KeybindingsFileActions(): React.JSX.Element {
void openKeybindingsFile()}>
- {translate("auto.components.settings.KeybindingsFileActions.98f1a23e1c", "Open with Default App")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.98f1a23e1c',
+ 'Open with Default App'
+ )}
+
void openKeybindingsInExternalEditor('code')}>
- {translate("auto.components.settings.KeybindingsFileActions.1637f64033", "Open in VS Code")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.1637f64033',
+ 'Open in VS Code'
+ )}
+
void openKeybindingsInExternalEditor('cursor')}>
- {translate("auto.components.settings.KeybindingsFileActions.9e24c0e858", "Open in Cursor")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.9e24c0e858',
+ 'Open in Cursor'
+ )}
+
void revealKeybindingsFile()}>
- {translate("auto.components.settings.KeybindingsFileActions.a8a8d6b9d3", "Reveal in File Manager")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.a8a8d6b9d3',
+ 'Reveal in File Manager'
+ )}
+
void reloadKeybindings()}>
- {translate("auto.components.settings.KeybindingsFileActions.abc49853fb", "Reload from Disk")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.abc49853fb',
+ 'Reload from Disk'
+ )}
+
diff --git a/src/renderer/src/components/settings/ManageSessionKillDialog.tsx b/src/renderer/src/components/settings/ManageSessionKillDialog.tsx
index e2375c4434e..56ddb9845ee 100644
--- a/src/renderer/src/components/settings/ManageSessionKillDialog.tsx
+++ b/src/renderer/src/components/settings/ManageSessionKillDialog.tsx
@@ -56,17 +56,39 @@ export function ManageSessionKillDialog({
{session ? (
<>
- {translate("auto.components.settings.ManageSessionKillDialog.87dcafc85c", "Kill this session?")}
+
+ {translate(
+ 'auto.components.settings.ManageSessionKillDialog.87dcafc85c',
+ 'Kill this session?'
+ )}
+
- {translate("auto.components.settings.ManageSessionKillDialog.8401328fed", "Force-quits")}{session.sessionId}
- {translate("auto.components.settings.ManageSessionKillDialog.ad9832aa26", ". Any unsaved work in that pane is lost. This can't be undone.")}
+ {translate(
+ 'auto.components.settings.ManageSessionKillDialog.8401328fed',
+ 'Force-quits'
+ )}
+ {session.sessionId}
+ {translate(
+ 'auto.components.settings.ManageSessionKillDialog.ad9832aa26',
+ ". Any unsaved work in that pane is lost. This can't be undone."
+ )}
+
- {translate("auto.components.settings.ManageSessionKillDialog.6bf4627168", "Cancel")}
+ {translate('auto.components.settings.ManageSessionKillDialog.6bf4627168', 'Cancel')}
+
{isBusy ? : null}
- {isBusy ? translate("auto.components.settings.ManageSessionKillDialog.d3dba51b15", "Killing…") : translate("auto.components.settings.ManageSessionKillDialog.0b0db4c68c", "Kill session")}
+ {isBusy
+ ? translate(
+ 'auto.components.settings.ManageSessionKillDialog.d3dba51b15',
+ 'Killing…'
+ )
+ : translate(
+ 'auto.components.settings.ManageSessionKillDialog.0b0db4c68c',
+ 'Kill session'
+ )}
>
diff --git a/src/renderer/src/components/settings/McpConfigFileRow.tsx b/src/renderer/src/components/settings/McpConfigFileRow.tsx
index 025a9b87af4..632d56fc366 100644
--- a/src/renderer/src/components/settings/McpConfigFileRow.tsx
+++ b/src/renderer/src/components/settings/McpConfigFileRow.tsx
@@ -53,7 +53,7 @@ export function McpConfigFileRow({ config, onOpen }: McpConfigFileRowProps): Rea
return (
- {config.status === "valid" && !config.readError ? (
+ {config.status === 'valid' && !config.readError ? (
) : (
@@ -73,7 +73,8 @@ export function McpConfigFileRow({ config, onOpen }: McpConfigFileRowProps): Rea
{config.exists ? (
onOpen(config)}>
- {translate("auto.components.settings.McpConfigFileRow.e720c139cd", "Open")}
+ {translate('auto.components.settings.McpConfigFileRow.e720c139cd', 'Open')}
+
) : null}
@@ -100,7 +101,7 @@ export function McpConfigFileRow({ config, onOpen }: McpConfigFileRowProps): Rea
{server.env && Object.keys(server.env).length > 0 ? (
- {translate("auto.components.settings.McpConfigFileRow.b145eb6009", "env:")}{' '}
+ {translate('auto.components.settings.McpConfigFileRow.b145eb6009', 'env:')}{' '}
{Object.entries(server.env)
.map(([key, value]) => `${key}=${value}`)
.join(', ')}
diff --git a/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx b/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx
index 9e825952318..9ab5f1532d2 100644
--- a/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx
+++ b/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx
@@ -64,7 +64,14 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
setCliInstallStatus(await window.api.cli.getInstallStatus())
} catch (error) {
if (mountedRef.current) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.MobileEmulatorAgentControlRow.1861982430", "Failed to load CLI status."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.1861982430',
+ 'Failed to load CLI status.'
+ )
+ )
}
setCliInstallStatus(null)
} finally {
@@ -90,7 +97,12 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
onStatusChange: setCliInstallStatus
})
if (mountedRef.current && isOrcaCliAvailableOnPath(next)) {
- toast.success(translate("auto.components.settings.MobileEmulatorAgentControlRow.cdeaed9e37", "Registered the Orca CLI in PATH."))
+ toast.success(
+ translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.cdeaed9e37',
+ 'Registered the Orca CLI in PATH.'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -103,9 +115,18 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
-
{translate("auto.components.settings.MobileEmulatorAgentControlRow.2a674aa810", "Agent Mobile Emulator Control")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.2a674aa810',
+ 'Agent Mobile Emulator Control'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.ff4b7e65d6", "Let coding agents control the active mobile emulator with Orca CLI commands.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.ff4b7e65d6',
+ 'Let coding agents control the active mobile emulator with Orca CLI commands.'
+ )}
+
-
{translate("auto.components.settings.MobileEmulatorAgentControlRow.4f2205f3b6", "Enable Orca CLI")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.4f2205f3b6',
+ 'Enable Orca CLI'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.2fef055608", "Registers the Orca CLI command so agents can control the active emulator from their shell.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.2fef055608',
+ 'Registers the Orca CLI command so agents can control the active emulator from their shell.'
+ )}
+
{cliInstallStatus?.commandPath && cliEnabled ? (
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.aaf62a3dd2", "Installed at")}{' '}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.aaf62a3dd2',
+ 'Installed at'
+ )}{' '}
{cliInstallStatus.commandPath}
) : null}
@@ -163,8 +196,14 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
-
{translate("auto.components.settings.MobileEmulatorAgentControlRow.c7f3fe0a6e", "Common emulator commands")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.c7f3fe0a6e',
+ 'Common emulator commands'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.8af7a8bc38", "Commands target the active emulator for the current worktree. Coordinates are normalized from 0..1.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.8af7a8bc38',
+ 'Commands target the active emulator for the current worktree. Coordinates are normalized from 0..1.'
+ )}
+
{EMULATOR_CLI_COMMANDS.map((command) => (
{
try {
await window.api.ui.writeClipboardText(prompt)
- toast.success(translate("auto.components.settings.MobileEmulatorExamples.2b077b5544", "Copied prompt."))
+ toast.success(
+ translate('auto.components.settings.MobileEmulatorExamples.2b077b5544', 'Copied prompt.')
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.MobileEmulatorExamples.1f608e7d60", "Failed to copy prompt."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.MobileEmulatorExamples.1f608e7d60',
+ 'Failed to copy prompt.'
+ )
+ )
}
}
@@ -35,10 +44,19 @@ export function MobileEmulatorExamples({
>
-
{translate("auto.components.settings.MobileEmulatorExamples.0820b3f84f", "Try it — example prompts")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorExamples.0820b3f84f',
+ 'Try it — example prompts'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorExamples.4daa95f25a", "Paste any of these into Claude Code, Codex, or another agent in a project where the Orca CLI skill is installed.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorExamples.4daa95f25a',
+ 'Paste any of these into Claude Code, Codex, or another agent in a project where the Orca CLI skill is installed.'
+ )}
+
{EMULATOR_EXAMPLE_PROMPTS.map((prompt) => (
- {translate("auto.components.settings.MobileEmulatorExamples.b525ff2b12", "\"")}{prompt}{translate("auto.components.settings.MobileEmulatorExamples.d151e25078", "\"")}
+ {translate('auto.components.settings.MobileEmulatorExamples.b525ff2b12', '"')}
+ {prompt}
+ {translate('auto.components.settings.MobileEmulatorExamples.d151e25078', '"')}
+
@@ -54,14 +75,18 @@ export function MobileEmulatorExamples({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.settings.MobileEmulatorExamples.c12b253997", "Copy example prompt")}
+ aria-label={translate(
+ 'auto.components.settings.MobileEmulatorExamples.c12b253997',
+ 'Copy example prompt'
+ )}
onClick={() => void copyPrompt(prompt)}
>
- {translate("auto.components.settings.MobileEmulatorExamples.edf13dd03b", "Copy")}
+ {translate('auto.components.settings.MobileEmulatorExamples.edf13dd03b', 'Copy')}
+
diff --git a/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx b/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx
index d72a167eb37..dff685415ef 100644
--- a/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx
+++ b/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx
@@ -37,15 +37,29 @@ export function MobileNetworkInterfaceSection({
- {translate("auto.components.settings.MobileNetworkInterfaceSection.406a35121c", "Network Interface")}
+
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.406a35121c',
+ 'Network Interface'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.d536b5e20d", "Choose which network address to advertise in the QR code. Use your LAN address for same-network pairing, or an overlay network address (Tailscale, ZeroTier) for cross-network access.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.d536b5e20d',
+ 'Choose which network address to advertise in the QR code. Use your LAN address for same-network pairing, or an overlay network address (Tailscale, ZeroTier) for cross-network access.'
+ )}
+
-
+
{networkInterfaces.map((iface) => (
@@ -65,14 +79,21 @@ export function MobileNetworkInterfaceSection({
size="icon-sm"
onClick={onRefreshNetworkInterfaces}
disabled={refreshingNetworkInterfaces}
- aria-label={translate("auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d", "Refresh network interfaces")}
+ aria-label={translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d',
+ 'Refresh network interfaces'
+ )}
className="text-muted-foreground"
>
- {translate("auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d", "Refresh network interfaces")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d',
+ 'Refresh network interfaces'
+ )}
+
)}
- {hasQrCode ? translate("auto.components.settings.MobileNetworkInterfaceSection.1e64659126", "Regenerate") : translate("auto.components.settings.MobileNetworkInterfaceSection.c541f67790", "Generate QR Code")}
+ {hasQrCode
+ ? translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.1e64659126',
+ 'Regenerate'
+ )
+ : translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.c541f67790',
+ 'Generate QR Code'
+ )}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.39fad211d9", "Connect outside your Wi-Fi with a tailnet")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.39fad211d9',
+ 'Connect outside your Wi-Fi with a tailnet'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.9fc5d203ff", "Orca Mobile connects directly to this computer. To use it away from the same local network, put your computer and phone on the same private overlay network, then generate the QR code with that network address selected.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.9fc5d203ff',
+ 'Orca Mobile connects directly to this computer. To use it away from the same local network, put your computer and phone on the same private overlay network, then generate the QR code with that network address selected.'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.51d29927eb", "Install")}{' '}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.51d29927eb',
+ 'Install'
+ )}{' '}
void window.api.shell.openUrl(TAILSCALE_DOWNLOAD_URL)}
className="inline-flex items-center gap-1 font-medium text-foreground underline-offset-2 hover:underline"
>
- {translate("auto.components.settings.MobileNetworkInterfaceSection.1dc87a7fbc", "Tailscale")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.1dc87a7fbc',
+ 'Tailscale'
+ )}
+
{' '}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.668016be7a", "on your computer and phone.")}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.1f7c26d36a", "Sign in to the same tailnet on both devices.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.668016be7a',
+ 'on your computer and phone.'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.87985ba6f5", "In this Network Interface menu, choose the Tailscale address, usually a 100.x.y.z IP.")}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.63d5e4ae1e", "Regenerate the QR code and scan it from the Orca mobile app.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.1f7c26d36a',
+ 'Sign in to the same tailnet on both devices.'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.87985ba6f5',
+ 'In this Network Interface menu, choose the Tailscale address, usually a 100.x.y.z IP.'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.63d5e4ae1e',
+ 'Regenerate the QR code and scan it from the Orca mobile app.'
+ )}
+
diff --git a/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx b/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx
index ace5250899d..660a42434bd 100644
--- a/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx
+++ b/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx
@@ -37,17 +37,41 @@ export function OpenAiTranscriptionKeyDialog({
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.439e91879e", "OpenAI Transcription")}
+
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.439e91879e',
+ 'OpenAI Transcription'
+ )}
+
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.07ed3e512e", "Audio is sent to OpenAI only when an OpenAI speech model is selected.")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.07ed3e512e',
+ 'Audio is sent to OpenAI only when an OpenAI speech model is selected.'
+ )}
+
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.16015322f9", "API Key")}
+
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.16015322f9',
+ 'API Key'
+ )}
+
onApiKeyDraftChange(event.target.value)}
onKeyDown={(event) => {
@@ -59,15 +83,27 @@ export function OpenAiTranscriptionKeyDialog({
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.d246b2bdb3", "Local runtime keys are stored in ~/.orca using Electron encrypted storage when available.")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.d246b2bdb3',
+ 'Local runtime keys are stored in ~/.orca using Electron encrypted storage when available.'
+ )}
+
{configured && (
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.07b26f2742", "Clear Key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.07b26f2742',
+ 'Clear Key'
+ )}
+
)}
{pending ? : null}
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.fa83512e48", "Save Key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.fa83512e48',
+ 'Save Key'
+ )}
+
diff --git a/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx b/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx
index ace152f53b2..7ea09a10f1f 100644
--- a/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx
+++ b/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx
@@ -21,26 +21,48 @@ export function OpenAiTranscriptionSettingsRow({
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.27e0cb656d", "OpenAI Transcription")}
+
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.27e0cb656d',
+ 'OpenAI Transcription'
+ )}
+
{configured && (
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.3b0ab3fc0b", "Connected")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.3b0ab3fc0b',
+ 'Connected'
+ )}
+
)}
{configured
- ? translate("auto.components.settings.OpenAiTranscriptionSettingsRow.b59b9b2b51", "API key configured for cloud speech-to-text models.")
- : translate("auto.components.settings.OpenAiTranscriptionSettingsRow.893790e13b", "Add an OpenAI API key before selecting cloud speech-to-text models.")}
+ ? translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.b59b9b2b51',
+ 'API key configured for cloud speech-to-text models.'
+ )
+ : translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.893790e13b',
+ 'Add an OpenAI API key before selecting cloud speech-to-text models.'
+ )}
{configured ? (
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.a622bc3b37", "Replace key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.a622bc3b37',
+ 'Replace key'
+ )}
+
@@ -49,7 +71,11 @@ export function OpenAiTranscriptionSettingsRow({
) : (
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.85c589cd61", "Add API key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.85c589cd61',
+ 'Add API key'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx b/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx
index 5e2b72d4514..af2484aae0d 100644
--- a/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx
+++ b/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx
@@ -51,9 +51,21 @@ export function OrchestrationExampleDialog(props: {
const copyPrompt = async (prompt: string): Promise => {
try {
await window.api.ui.writeClipboardText(prompt)
- toast.success(translate("auto.components.settings.OrchestrationExamplesDialog.80c6f2feb8", "Copied example prompt."))
+ toast.success(
+ translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.80c6f2feb8',
+ 'Copied example prompt.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.OrchestrationExamplesDialog.4e46da1889", "Failed to copy prompt."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.4e46da1889',
+ 'Failed to copy prompt.'
+ )
+ )
}
}
@@ -88,7 +100,11 @@ export function OrchestrationExampleDialog(props: {
variant="ghost"
size="icon-xs"
className="absolute top-2 right-2 shrink-0 opacity-70 transition-opacity group-hover:opacity-100"
- aria-label={translate("auto.components.settings.OrchestrationExamplesDialog.969cec9739", "Copy {{value0}} example prompt", { value0: example.title })}
+ aria-label={translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.969cec9739',
+ 'Copy {{value0}} example prompt',
+ { value0: example.title }
+ )}
onClick={() => void copyPrompt(example.prompt)}
>
@@ -98,10 +114,15 @@ export function OrchestrationExampleDialog(props: {
onOpenChange(false)}>
- {translate("auto.components.settings.OrchestrationExamplesDialog.9b4c004998", "Done")}
+ {translate('auto.components.settings.OrchestrationExamplesDialog.9b4c004998', 'Done')}
+
void copyPrompt(example.prompt)}>
- {translate("auto.components.settings.OrchestrationExamplesDialog.3d1aa105e3", "Copy prompt")}
+ {translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.3d1aa105e3',
+ 'Copy prompt'
+ )}
+
diff --git a/src/renderer/src/components/settings/OrchestrationSetupCard.tsx b/src/renderer/src/components/settings/OrchestrationSetupCard.tsx
index 52fc967ec84..2b9c8c4c054 100644
--- a/src/renderer/src/components/settings/OrchestrationSetupCard.tsx
+++ b/src/renderer/src/components/settings/OrchestrationSetupCard.tsx
@@ -19,8 +19,14 @@ export function OrchestrationSetupCard(props: {
const setupPanel = (
- {status.installed ? translate("auto.components.settings.OrchestrationSkillAgentCoverage.1e8f8d8fae", "Ready") : translate("auto.components.settings.OrchestrationSkillAgentCoverage.ffe13e36fb", "Missing")}
+ {status.installed
+ ? translate(
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.1e8f8d8fae',
+ 'Ready'
+ )
+ : translate(
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.ffe13e36fb',
+ 'Missing'
+ )}
)
@@ -89,7 +97,12 @@ export function OrchestrationSkillAgentCoverage(props: {
)}
>
-
{translate("auto.components.settings.OrchestrationSkillAgentCoverage.6dec5ce2d2", "Agent coverage")}
+
+ {translate(
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.6dec5ce2d2',
+ 'Agent coverage'
+ )}
+
{summary}
diff --git a/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx b/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx
index 1195b6b8ea3..c1c6f2feea4 100644
--- a/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx
+++ b/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx
@@ -21,9 +21,21 @@ export function OrchestrationSkillPromptDialog(props: {
const copyCommand = async (): Promise => {
try {
await window.api.ui.writeClipboardText(command)
- toast.success(translate("auto.components.settings.OrchestrationSkillPromptDialog.239bf9132b", "Copied install command."))
+ toast.success(
+ translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.239bf9132b',
+ 'Copied install command.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.OrchestrationSkillPromptDialog.d3dc559225", "Failed to copy install command."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.d3dc559225',
+ 'Failed to copy install command.'
+ )
+ )
}
}
@@ -33,9 +45,17 @@ export function OrchestrationSkillPromptDialog(props: {
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.2914abcfa2", "Install orchestration skill")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.2914abcfa2',
+ 'Install orchestration skill'
+ )}
+
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.b99f375eb2", "Run this command in a terminal to install the orchestration skill for your agents.")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.b99f375eb2',
+ 'Run this command in a terminal to install the orchestration skill for your agents.'
+ )}
+
@@ -49,7 +69,10 @@ export function OrchestrationSkillPromptDialog(props: {
variant="ghost"
size="icon-xs"
className="absolute top-2 right-2 shrink-0 opacity-70 transition-opacity group-hover:opacity-100"
- aria-label={translate("auto.components.settings.OrchestrationSkillPromptDialog.1bdce1911e", "Copy orchestration skill install command")}
+ aria-label={translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.1bdce1911e',
+ 'Copy orchestration skill install command'
+ )}
onClick={() => void copyCommand()}
>
@@ -59,10 +82,18 @@ export function OrchestrationSkillPromptDialog(props: {
onOpenChange(false)}>
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.35550f3b3b", "Done")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.35550f3b3b',
+ 'Done'
+ )}
+
void copyCommand()}>
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.f08d45293d", "Copy command")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.f08d45293d',
+ 'Copy command'
+ )}
+
diff --git a/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx b/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx
index 8cd6a480ef9..54af2be9a29 100644
--- a/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx
+++ b/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx
@@ -53,7 +53,11 @@ export function PrivacyDiagnosticBundleControls({
onClick={() => void onCopyTicket()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.2801d4ce22", "Copy ticket")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.2801d4ce22',
+ 'Copy ticket'
+ )}
+
void onDeleteUploadedBundle()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.7f14a1733c", "Delete bundle")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.7f14a1733c',
+ 'Delete bundle'
+ )}
+
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.2ae9a6b63e", "Done")}
+ {translate('auto.components.settings.PrivacyDiagnosticBundleControls.2ae9a6b63e', 'Done')}
+
>
)
}
@@ -79,13 +88,25 @@ export function PrivacyDiagnosticBundleControls({
onClick={() => void onOpenPreview()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.798b6f0be5", "Open preview")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.798b6f0be5',
+ 'Open preview'
+ )}
+
void onUpload()}>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.aca2c8a367", "Upload")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.aca2c8a367',
+ 'Upload'
+ )}
+
void onDiscard()}>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.a5acaffdb6", "Discard")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.a5acaffdb6',
+ 'Discard'
+ )}
+
>
)
}
@@ -98,7 +119,11 @@ export function PrivacyDiagnosticBundleControls({
onClick={() => void onCollect()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.dc8404a930", "Create preview")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.dc8404a930',
+ 'Create preview'
+ )}
+
)
}
diff --git a/src/renderer/src/components/settings/PrivacyPane.tsx b/src/renderer/src/components/settings/PrivacyPane.tsx
index a6a85a1ca60..f2334e8676e 100644
--- a/src/renderer/src/components/settings/PrivacyPane.tsx
+++ b/src/renderer/src/components/settings/PrivacyPane.tsx
@@ -89,23 +89,35 @@ export function PrivacyPane({ settings }: PrivacyPaneProps): React.JSX.Element {
- {translate("auto.components.settings.PrivacyPane.fe904ac984", "Share anonymous usage data")}
+
+ {translate(
+ 'auto.components.settings.PrivacyPane.fe904ac984',
+ 'Share anonymous usage data'
+ )}
+
- {translate("auto.components.settings.PrivacyPane.8bfdd23a88", "Help us figure out what to build next. Orca sends anonymous counts of which features you use and where things break.")}{' '}
+ {translate(
+ 'auto.components.settings.PrivacyPane.8bfdd23a88',
+ 'Help us figure out what to build next. Orca sends anonymous counts of which features you use and where things break.'
+ )}{' '}
void window.api.shell.openUrl(PRIVACY_URL)}
>
- {translate("auto.components.settings.PrivacyPane.77410e0566", "Privacy policy")}
+ {translate('auto.components.settings.PrivacyPane.77410e0566', 'Privacy policy')}
+
.
- {blocked.reason === "ci" ? (
- {translate("auto.components.settings.PrivacyPane.e3970bbbf5", "Telemetry is disabled because a CI environment variable is set. Unset it and restart.")}
+ {blocked.reason === 'ci' ? (
+
+ {translate(
+ 'auto.components.settings.PrivacyPane.e3970bbbf5',
+ 'Telemetry is disabled because a CI environment variable is set. Unset it and restart.'
+ )}
+
) : (
- {translate("auto.components.settings.PrivacyPane.79a0f3c16c", "Telemetry is disabled by the")}{' '}
+ {translate(
+ 'auto.components.settings.PrivacyPane.79a0f3c16c',
+ 'Telemetry is disabled by the'
+ )}{' '}
{envVarNameForReason(blocked.reason)}
{' '}
- {translate("auto.components.settings.PrivacyPane.36e0e2e63b", "environment variable. Unset it and restart to re-enable.")}
+ {translate(
+ 'auto.components.settings.PrivacyPane.36e0e2e63b',
+ 'environment variable. Unset it and restart to re-enable.'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/settings/RecentTabOrderControl.tsx b/src/renderer/src/components/settings/RecentTabOrderControl.tsx
index f4c45b1466d..84e54c617b5 100644
--- a/src/renderer/src/components/settings/RecentTabOrderControl.tsx
+++ b/src/renderer/src/components/settings/RecentTabOrderControl.tsx
@@ -16,13 +16,16 @@ export function RecentTabOrderControl({
}): React.JSX.Element {
return (
- {translate("auto.components.settings.RecentTabOrderControl.6e6a3fcc61", "Most recent")}
- {translate("auto.components.settings.RecentTabOrderControl.3b17c81ede", "Tab strip order")}
+
+ {translate(
+ 'auto.components.settings.RecentTabOrderControl.6e6a3fcc61',
+ 'Most recent'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RecentTabOrderControl.3b17c81ede',
+ 'Tab strip order'
+ )}
+
}
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx
index 2253db0d5cd..6a22472b2ee 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx
@@ -29,9 +29,18 @@ export function RepositorySourceControlAiCustomCommand({
-
{translate("auto.components.settings.RepositorySourceControlAiCustomCommand.ebffc5a28c", "Custom command")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.ebffc5a28c',
+ 'Custom command'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiCustomCommand.fbb77e122a", "Repo fallback for text actions that select Custom command.")}
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.fbb77e122a',
+ 'Repo fallback for text actions that select Custom command.'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiCustomCommand.e56668c291", "Use global")}
- {translate("auto.components.settings.RepositorySourceControlAiCustomCommand.0704dd55cd", "Repository command")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.e56668c291',
+ 'Use global'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.0704dd55cd',
+ 'Repository command'
+ )}
+
@@ -60,7 +79,13 @@ export function RepositorySourceControlAiCustomCommand({
const nextValue = event.target.value
onChange(nextValue === '' ? undefined : nextValue)
}}
- placeholder={source.customAgentCommand || translate("auto.components.settings.RepositorySourceControlAiCustomCommand.f9941f0caf", "e.g. ollama run llama3.1 {prompt}")}
+ placeholder={
+ source.customAgentCommand ||
+ translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.f9941f0caf',
+ 'e.g. ollama run llama3.1 {prompt}'
+ )
+ }
spellCheck={false}
className="h-8 font-mono text-xs"
/>
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx
index 66accb5d351..40befa958f2 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx
@@ -28,9 +28,27 @@ export function RepositorySourceControlAiEnablement({
return (
-
{translate("auto.components.settings.RepositorySourceControlAiEnablement.cf5959c834", "Source Control AI enabled")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.cf5959c834',
+ 'Source Control AI enabled'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.30ae6dcce8", "Global default is")}{source.enabled ? translate("auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2", "On") : translate("auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3", "Off")}.
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.30ae6dcce8',
+ 'Global default is'
+ )}
+ {source.enabled
+ ? translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2',
+ 'On'
+ )
+ : translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3',
+ 'Off'
+ )}
+ .
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.62511a575d", "Use global")}
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2", "On")}
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3", "Off")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.62511a575d',
+ 'Use global'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2',
+ 'On'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3',
+ 'Off'
+ )}
+
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
index 376c3f121f4..4a2e6aba53e 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
@@ -17,10 +17,34 @@ type RepositorySourceControlAiHostedReviewDefaultsProps = {
}
const HOSTED_REVIEW_DEFAULT_ROWS: { key: HostedReviewDefaultKey; label: string }[] = [
- { key: 'draft', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.981eae7e14", "Draft by default") },
- { key: 'useTemplate', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.d32b87e754", "Use review template when available") },
- { key: 'generateDetailsOnOpen', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.14f1eb99d0", "Generate details when opening Create PR") },
- { key: 'openAfterCreate', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.629ed8a9d3", "Open hosted review after creation") }
+ {
+ key: 'draft',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.981eae7e14',
+ 'Draft by default'
+ )
+ },
+ {
+ key: 'useTemplate',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.d32b87e754',
+ 'Use review template when available'
+ )
+ },
+ {
+ key: 'generateDetailsOnOpen',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.14f1eb99d0',
+ 'Generate details when opening Create PR'
+ )
+ },
+ {
+ key: 'openAfterCreate',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.629ed8a9d3',
+ 'Open hosted review after creation'
+ )
+ }
]
export function RepositorySourceControlAiHostedReviewDefaults({
@@ -30,7 +54,12 @@ export function RepositorySourceControlAiHostedReviewDefaults({
}: RepositorySourceControlAiHostedReviewDefaultsProps): React.JSX.Element {
return (
-
{translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.aa6ee4b7d6", "Hosted-review creation defaults")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.aa6ee4b7d6',
+ 'Hosted-review creation defaults'
+ )}
+
{HOSTED_REVIEW_DEFAULT_ROWS.map((row) => {
const inherited = source.prCreationDefaults?.[row.key] === true ? 'On' : 'Off'
@@ -42,7 +71,11 @@ export function RepositorySourceControlAiHostedReviewDefaults({
{row.label}
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.a68849a859", "Global default is")}{inherited}.
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.a68849a859',
+ 'Global default is'
+ )}
+ {inherited}.
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.ffc3b26b26", "Use global")}
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.777443bf89", "On")}
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.053ccfbf52", "Off")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.ffc3b26b26',
+ 'Use global'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.777443bf89',
+ 'On'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.053ccfbf52',
+ 'Off'
+ )}
+
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx
index 852ce8f1b1c..3dccec319e6 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx
@@ -296,14 +296,31 @@ export function RepositorySourceControlAiSection({
>
-
{translate("auto.components.settings.RepositorySourceControlAiSection.71b003b62b", "Source Control AI")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.71b003b62b',
+ 'Source Control AI'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiSection.8b8bc5913a", "Repository action recipes. Global settings are used until this repository customizes them.")}
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.8b8bc5913a',
+ 'Repository action recipes. Global settings are used until this repository customizes them.'
+ )}
+
{saveError ?
{saveError}
: null}
- {isDirty ? translate("auto.components.settings.RepositorySourceControlAiSection.e57dde9d93", "Unsaved changes") : translate("auto.components.settings.RepositorySourceControlAiSection.ccb07dd027", "Saved")}
+ {isDirty
+ ? translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.e57dde9d93',
+ 'Unsaved changes'
+ )
+ : translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.ccb07dd027',
+ 'Saved'
+ )}
{isDirty ? (
- {translate("auto.components.settings.RepositorySourceControlAiSection.67b3ff5467", "Discard")}
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.67b3ff5467',
+ 'Discard'
+ )}
+
) : null}
void saveDraft()}
disabled={!isDirty || isSaving}
>
- {isSaving ? translate("auto.components.settings.RepositorySourceControlAiSection.57e6e9d4b1", "Saving...") : translate("auto.components.settings.RepositorySourceControlAiSection.152268c295", "Save")}
+ {isSaving
+ ? translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.57e6e9d4b1',
+ 'Saving...'
+ )
+ : translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.152268c295',
+ 'Save'
+ )}
diff --git a/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx b/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx
index 16cd56e4742..82e4e4d8897 100644
--- a/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx
+++ b/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx
@@ -35,7 +35,12 @@ export function RuntimeAccessGrantList({
return (
-
{translate("auto.components.settings.RuntimeAccessGrantList.f031182867", "Shared Server Access")}
+
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.f031182867',
+ 'Shared Server Access'
+ )}
+
- {translate("auto.components.settings.RuntimeAccessGrantList.27cf8507ad", "Refresh shared access")}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.27cf8507ad',
+ 'Refresh shared access'
+ )}
+
{grants.length === 0 ? (
-
{translate("auto.components.settings.RuntimeAccessGrantList.fd83b94095", "No shared server access yet.")}
+
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.fd83b94095',
+ 'No shared server access yet.'
+ )}
+
) : (
{grants.map((grant) => {
@@ -70,14 +87,30 @@ export function RuntimeAccessGrantList({
{grant.name}
{isCurrent ? (
- {translate("auto.components.settings.RuntimeAccessGrantList.434e4a6af6", "Current link")}
+
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.434e4a6af6',
+ 'Current link'
+ )}
+
) : null}
- {translate("auto.components.settings.RuntimeAccessGrantList.87b16cd11d", "Created")}{formatAccessTimestamp(grant.createdAt)} ·{' '}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.87b16cd11d',
+ 'Created'
+ )}
+ {formatAccessTimestamp(grant.createdAt)} ·{' '}
{grant.lastSeenAt
- ? translate("auto.components.settings.RuntimeAccessGrantList.b18d1764ef", "Last used {{value0}}", { value0: formatAccessTimestamp(grant.lastSeenAt) })
- : translate("auto.components.settings.RuntimeAccessGrantList.df142657a5", "Not used yet")}
+ ? translate(
+ 'auto.components.settings.RuntimeAccessGrantList.b18d1764ef',
+ 'Last used {{value0}}',
+ { value0: formatAccessTimestamp(grant.lastSeenAt) }
+ )
+ : translate(
+ 'auto.components.settings.RuntimeAccessGrantList.df142657a5',
+ 'Not used yet'
+ )}
@@ -89,7 +122,11 @@ export function RuntimeAccessGrantList({
className="text-destructive hover:text-destructive shrink-0"
onClick={() => onRevoke(grant)}
disabled={isRevoking}
- aria-label={translate("auto.components.settings.RuntimeAccessGrantList.6f6d5188ed", "Revoke {{value0}}", { value0: grant.name })}
+ aria-label={translate(
+ 'auto.components.settings.RuntimeAccessGrantList.6f6d5188ed',
+ 'Revoke {{value0}}',
+ { value0: grant.name }
+ )}
>
{isRevoking ? (
@@ -99,7 +136,11 @@ export function RuntimeAccessGrantList({
- {translate("auto.components.settings.RuntimeAccessGrantList.68ec21309f", "Revoke access")}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.68ec21309f',
+ 'Revoke access'
+ )}
+
)
@@ -108,7 +149,11 @@ export function RuntimeAccessGrantList({
)}
{grants.length > 0 ? (
- {translate("auto.components.settings.RuntimeAccessGrantList.8b82879581", "Anyone with an active grant can connect until you revoke it. Revoking shared access disconnects active clients immediately.")}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.8b82879581',
+ 'Anyone with an active grant can connect until you revoke it. Revoking shared access disconnects active clients immediately.'
+ )}
+
) : null}
)
diff --git a/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx b/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx
index 281d53a3779..0e9186fd680 100644
--- a/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx
+++ b/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx
@@ -29,7 +29,11 @@ export function GeneratedUrlRow({
variant="ghost"
size="icon-xs"
onClick={onCopy}
- aria-label={translate("auto.components.settings.RuntimePairingGeneratedUrlRows.0495f68959", "Copy {{value0}}", { value0: label })}
+ aria-label={translate(
+ 'auto.components.settings.RuntimePairingGeneratedUrlRows.0495f68959',
+ 'Copy {{value0}}',
+ { value0: label }
+ )}
>
{copied ?
:
}
diff --git a/src/renderer/src/components/settings/ShortcutBindingRow.tsx b/src/renderer/src/components/settings/ShortcutBindingRow.tsx
index cbc14781458..fb1bc35b9bd 100644
--- a/src/renderer/src/components/settings/ShortcutBindingRow.tsx
+++ b/src/renderer/src/components/settings/ShortcutBindingRow.tsx
@@ -110,7 +110,11 @@ export function ShortcutBindingRow({
return (
@@ -119,7 +123,8 @@ export function ShortcutBindingRow({
{item.title}
{modified ? (
- {translate("auto.components.settings.ShortcutBindingRow.97dccee14e", "Modified")}
+ {translate('auto.components.settings.ShortcutBindingRow.97dccee14e', 'Modified')}
+
) : null}
{terminalStatus ? (
@@ -164,14 +169,22 @@ export function ShortcutBindingRow({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.settings.ShortcutBindingRow.4f2c9b2a05", "Reset {{value0}} to default", { value0: item.title })}
+ aria-label={translate(
+ 'auto.components.settings.ShortcutBindingRow.4f2c9b2a05',
+ 'Reset {{value0}} to default',
+ { value0: item.title }
+ )}
onClick={() => onReset(item.id)}
>
- {translate("auto.components.settings.ShortcutBindingRow.f75335b155", "Reset to default")}
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.f75335b155',
+ 'Reset to default'
+ )}
+
) : null}
@@ -181,14 +194,22 @@ export function ShortcutBindingRow({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-destructive"
- aria-label={translate("auto.components.settings.ShortcutBindingRow.3b62c142fa", "Disable {{value0}}", { value0: item.title })}
+ aria-label={translate(
+ 'auto.components.settings.ShortcutBindingRow.3b62c142fa',
+ 'Disable {{value0}}',
+ { value0: item.title }
+ )}
onClick={() => onDisable(item.id)}
>
- {translate("auto.components.settings.ShortcutBindingRow.9cdaaa3d8f", "Disable shortcut")}
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.9cdaaa3d8f',
+ 'Disable shortcut'
+ )}
+
) : null}
@@ -219,7 +240,12 @@ export function ShortcutBindingRow({
)}
>
{recording ? (
- {translate("auto.components.settings.ShortcutBindingRow.87381fd8f8", "Press keys…")}
+
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.87381fd8f8',
+ 'Press keys…'
+ )}
+
) : hasBinding ? (
{effective.map((binding) => (
@@ -229,12 +255,29 @@ export function ShortcutBindingRow({
) : (
- {translate("auto.components.settings.ShortcutBindingRow.4a4c2c9d32", "Add shortcut")}
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.4a4c2c9d32',
+ 'Add shortcut'
+ )}
+
)}
- {recording ? translate("auto.components.settings.ShortcutBindingRow.6a7848fdac", "Listening for shortcut") : hasBinding ? translate("auto.components.settings.ShortcutBindingRow.f6579be67b", "Change shortcut") : translate("auto.components.settings.ShortcutBindingRow.4a4c2c9d32", "Add shortcut")}
+ {recording
+ ? translate(
+ 'auto.components.settings.ShortcutBindingRow.6a7848fdac',
+ 'Listening for shortcut'
+ )
+ : hasBinding
+ ? translate(
+ 'auto.components.settings.ShortcutBindingRow.f6579be67b',
+ 'Change shortcut'
+ )
+ : translate(
+ 'auto.components.settings.ShortcutBindingRow.4a4c2c9d32',
+ 'Add shortcut'
+ )}
diff --git a/src/renderer/src/components/settings/ShortcutFilterRail.tsx b/src/renderer/src/components/settings/ShortcutFilterRail.tsx
index 9a8191d30d3..97a86badc96 100644
--- a/src/renderer/src/components/settings/ShortcutFilterRail.tsx
+++ b/src/renderer/src/components/settings/ShortcutFilterRail.tsx
@@ -34,7 +34,11 @@ const SHORTCUT_FILTER_LABELS: Record
= {
export function getShortcutSearchEntry(row: ShortcutRowModel): SettingsSearchEntry {
return {
title: row.item.title,
- description: translate("auto.components.settings.ShortcutFilterRail.1d5634ba31", "{{value0}} shortcut", { value0: row.groupTitle }),
+ description: translate(
+ 'auto.components.settings.ShortcutFilterRail.1d5634ba31',
+ '{{value0}} shortcut',
+ { value0: row.groupTitle }
+ ),
keywords: [...row.item.searchKeywords]
}
}
@@ -98,7 +102,8 @@ export function ShortcutFilterRail({
- {translate("auto.components.settings.ShortcutFilterRail.02dc7d4251", "Find shortcuts")}
+ {translate('auto.components.settings.ShortcutFilterRail.02dc7d4251', 'Find shortcuts')}
+
{visibleCount}/{totalCount}
@@ -109,7 +114,10 @@ export function ShortcutFilterRail({
id="shortcut-filter-search"
value={query}
onChange={(event) => onQueryChange(event.target.value)}
- placeholder={translate("auto.components.settings.ShortcutFilterRail.f733c4b89f", "Search command or keys")}
+ placeholder={translate(
+ 'auto.components.settings.ShortcutFilterRail.f733c4b89f',
+ 'Search command or keys'
+ )}
className="h-8 pl-8 pr-8 text-sm"
/>
{query ? (
@@ -117,7 +125,10 @@ export function ShortcutFilterRail({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.settings.ShortcutFilterRail.df8466f3fc", "Clear shortcut search")}
+ aria-label={translate(
+ 'auto.components.settings.ShortcutFilterRail.df8466f3fc',
+ 'Clear shortcut search'
+ )}
onClick={() => onQueryChange('')}
className="absolute top-1/2 right-1 -translate-y-1/2 text-muted-foreground"
>
@@ -127,9 +138,16 @@ export function ShortcutFilterRail({
-
+
- {translate("auto.components.settings.ShortcutFilterRail.28b63545bf", "Status")}
+ {translate('auto.components.settings.ShortcutFilterRail.28b63545bf', 'Status')}
+
{filters.map((option) => (
- {translate("auto.components.settings.ShortcutRowsList.4ce3cd24d9", "No shortcuts match those filters.")}
+ {translate(
+ 'auto.components.settings.ShortcutRowsList.4ce3cd24d9',
+ 'No shortcuts match those filters.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx b/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx
index 1772926ed2c..61bf22cabb8 100644
--- a/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx
+++ b/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx
@@ -19,14 +19,26 @@ export function ShortcutTerminalPolicyControl({
return (
- {translate("auto.components.settings.ShortcutTerminalPolicyControl.63308571d8", "Orca first")}
- {translate("auto.components.settings.ShortcutTerminalPolicyControl.0762983d13", "Terminal first")}
+
+ {translate(
+ 'auto.components.settings.ShortcutTerminalPolicyControl.63308571d8',
+ 'Orca first'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.ShortcutTerminalPolicyControl.0762983d13',
+ 'Terminal first'
+ )}
+
}
diff --git a/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx b/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx
index 973162924d7..a903c7f1d8c 100644
--- a/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx
+++ b/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx
@@ -57,7 +57,8 @@ export function SshDestructiveActionDialog({
onOpenChange(false)} disabled={isBusy}>
- {translate("auto.components.settings.SshDestructiveActionDialog.895b216267", "Cancel")}
+ {translate('auto.components.settings.SshDestructiveActionDialog.895b216267', 'Cancel')}
+
{isBusy ? : null}
{isBusy ? (busyLabel ?? actionLabel) : actionLabel}
diff --git a/src/renderer/src/components/settings/SshPassphraseDialog.tsx b/src/renderer/src/components/settings/SshPassphraseDialog.tsx
index 4943eaf5445..3f25f5d91e2 100644
--- a/src/renderer/src/components/settings/SshPassphraseDialog.tsx
+++ b/src/renderer/src/components/settings/SshPassphraseDialog.tsx
@@ -69,7 +69,14 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
await window.api.ssh.submitCredential({ requestId: request.requestId, value })
removeRequest(request.requestId)
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.settings.SshPassphraseDialog.b8e88fd0de", "Failed to submit SSH credential"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.b8e88fd0de',
+ 'Failed to submit SSH credential'
+ )
+ )
setSubmitting(false)
}
}, [request, value, removeRequest])
@@ -81,7 +88,14 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
await window.api.ssh.submitCredential({ requestId: request.requestId, value: null })
removeRequest(request.requestId)
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.settings.SshPassphraseDialog.c55f105262", "Failed to cancel SSH credential request"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.c55f105262',
+ 'Failed to cancel SSH credential request'
+ )
+ )
setSubmitting(false)
}
}
@@ -99,16 +113,29 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
- {isPassword ? translate("auto.components.settings.SshPassphraseDialog.106bd57f4a", "SSH Password") : translate("auto.components.settings.SshPassphraseDialog.1f3dde805d", "SSH Key Passphrase")}
+ {isPassword
+ ? translate('auto.components.settings.SshPassphraseDialog.106bd57f4a', 'SSH Password')
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.1f3dde805d',
+ 'SSH Key Passphrase'
+ )}
{isPassword ? (
<>
- {translate("auto.components.settings.SshPassphraseDialog.dbf9b6f2d0", "Enter the password for")}{label}
+ {translate(
+ 'auto.components.settings.SshPassphraseDialog.dbf9b6f2d0',
+ 'Enter the password for'
+ )}
+ {label}
>
) : (
<>
- {translate("auto.components.settings.SshPassphraseDialog.ce4fdf7914", "Enter the passphrase for")}{label}
+ {translate(
+ 'auto.components.settings.SshPassphraseDialog.ce4fdf7914',
+ 'Enter the passphrase for'
+ )}
+ {label}
>
)}
@@ -118,7 +145,17 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
htmlFor="ssh-credential-input"
className="text-[11px] font-medium text-muted-foreground mb-1 block"
>
- {isPassword ? translate("auto.components.settings.SshPassphraseDialog.cab3d5f5a5", "Password for {{value0}}", { value0: request.detail }) : translate("auto.components.settings.SshPassphraseDialog.8a349e3fac", "Passphrase for {{value0}}", { value0: request.detail })}
+ {isPassword
+ ? translate(
+ 'auto.components.settings.SshPassphraseDialog.cab3d5f5a5',
+ 'Password for {{value0}}',
+ { value0: request.detail }
+ )
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.8a349e3fac',
+ 'Passphrase for {{value0}}',
+ { value0: request.detail }
+ )}
@@ -144,9 +191,12 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
onClick={() => void handleCancel()}
disabled={submitting}
>
- {translate("auto.components.settings.SshPassphraseDialog.d5a234456f", "Cancel")}
+ {translate('auto.components.settings.SshPassphraseDialog.d5a234456f', 'Cancel')}
+
void handleSubmit()} disabled={!value || submitting}>
- {isPassword ? translate("auto.components.settings.SshPassphraseDialog.bec2c1318f", "Connect") : translate("auto.components.settings.SshPassphraseDialog.405066423c", "Unlock")}
+ {isPassword
+ ? translate('auto.components.settings.SshPassphraseDialog.bec2c1318f', 'Connect')
+ : translate('auto.components.settings.SshPassphraseDialog.405066423c', 'Unlock')}
diff --git a/src/renderer/src/components/settings/SshTargetCard.tsx b/src/renderer/src/components/settings/SshTargetCard.tsx
index 1c308793a7d..a41c560b571 100644
--- a/src/renderer/src/components/settings/SshTargetCard.tsx
+++ b/src/renderer/src/components/settings/SshTargetCard.tsx
@@ -29,7 +29,7 @@ export const STATUS_LABELS: Record = {
connected: 'Connected',
reconnecting: 'Reconnecting\u2026',
'reconnection-failed': 'Reconnection failed',
- error: translate("auto.components.settings.SshTargetCard.18968ede9e", "Error")
+ error: translate('auto.components.settings.SshTargetCard.18968ede9e', 'Error')
}
export function statusColor(status: SshConnectionStatus): string {
@@ -144,7 +144,17 @@ export function SshTargetCard({
onClick={handleTerminateSessions}
className="size-7 text-muted-foreground hover:text-red-400"
disabled={hasActionInFlight}
- aria-label={terminateInFlight ? translate("auto.components.settings.SshTargetCard.c77f1abfe3", "Ending remote terminals") : translate("auto.components.settings.SshTargetCard.da16e108e6", "End remote terminals")}
+ aria-label={
+ terminateInFlight
+ ? translate(
+ 'auto.components.settings.SshTargetCard.c77f1abfe3',
+ 'Ending remote terminals'
+ )
+ : translate(
+ 'auto.components.settings.SshTargetCard.da16e108e6',
+ 'End remote terminals'
+ )
+ }
>
{terminateInFlight ? (
@@ -154,7 +164,8 @@ export function SshTargetCard({
- {translate("auto.components.settings.SshTargetCard.da16e108e6", "End remote terminals")}
+ {translate('auto.components.settings.SshTargetCard.da16e108e6', 'End remote terminals')}
+
)
@@ -167,7 +178,14 @@ export function SshTargetCard({
onClick={handleResetRelay}
className="size-7 text-muted-foreground hover:text-red-400"
disabled={hasActionInFlight}
- aria-label={resetInFlight ? translate("auto.components.settings.SshTargetCard.97dea4e8cf", "Resetting remote relay") : translate("auto.components.settings.SshTargetCard.762a48c662", "Reset remote relay")}
+ aria-label={
+ resetInFlight
+ ? translate(
+ 'auto.components.settings.SshTargetCard.97dea4e8cf',
+ 'Resetting remote relay'
+ )
+ : translate('auto.components.settings.SshTargetCard.762a48c662', 'Reset remote relay')
+ }
>
{resetInFlight ? (
@@ -177,7 +195,8 @@ export function SshTargetCard({
- {translate("auto.components.settings.SshTargetCard.762a48c662", "Reset remote relay")}
+ {translate('auto.components.settings.SshTargetCard.762a48c662', 'Reset remote relay')}
+
)
@@ -193,13 +212,17 @@ export function SshTargetCard({
onClick={() => onEdit(target)}
className="size-7"
disabled={hasActionInFlight}
- aria-label={translate("auto.components.settings.SshTargetCard.3d8af2949f", "Edit target")}
+ aria-label={translate(
+ 'auto.components.settings.SshTargetCard.3d8af2949f',
+ 'Edit target'
+ )}
>
- {translate("auto.components.settings.SshTargetCard.3d8af2949f", "Edit target")}
+ {translate('auto.components.settings.SshTargetCard.3d8af2949f', 'Edit target')}
+
@@ -209,7 +232,11 @@ export function SshTargetCard({
onClick={() => onRemove(target.id)}
className="size-7 text-muted-foreground hover:text-red-400"
disabled={hasActionInFlight}
- aria-label={removeInFlight ? translate("auto.components.settings.SshTargetCard.3d21a22d0e", "Removing target") : translate("auto.components.settings.SshTargetCard.7f7b3d7ab4", "Remove target")}
+ aria-label={
+ removeInFlight
+ ? translate('auto.components.settings.SshTargetCard.3d21a22d0e', 'Removing target')
+ : translate('auto.components.settings.SshTargetCard.7f7b3d7ab4', 'Remove target')
+ }
>
{removeInFlight ? (
@@ -219,7 +246,8 @@ export function SshTargetCard({
- {translate("auto.components.settings.SshTargetCard.7f7b3d7ab4", "Remove target")}
+ {translate('auto.components.settings.SshTargetCard.7f7b3d7ab4', 'Remove target')}
+
)
@@ -247,7 +275,7 @@ export function SshTargetCard({
- {status === "connected" ? (
+ {status === 'connected' ? (
<>
{renderSecondaryIconActions(true)}
- {translate("auto.components.settings.SshTargetCard.4c86f30877", "Disconnect")}
+ {translate('auto.components.settings.SshTargetCard.4c86f30877', 'Disconnect')}
+
>
) : isSshTargetConnecting(status) ? (
<>
{renderSecondaryIconActions(false)}
- {translate("auto.components.settings.SshTargetCard.1810b51482", "Connecting")}
+ {translate('auto.components.settings.SshTargetCard.1810b51482', 'Connecting')}
+
>
) : (
<>
@@ -282,7 +312,8 @@ export function SshTargetCard({
) : (
)}
- {translate("auto.components.settings.SshTargetCard.0e53e9f8e8", "Test")}
+ {translate('auto.components.settings.SshTargetCard.0e53e9f8e8', 'Test')}
+
- {actionInFlight === "connect" ? (
+ {actionInFlight === 'connect' ? (
) : (
)}
- {translate("auto.components.settings.SshTargetCard.ec6543cee9", "Connect")}
+ {translate('auto.components.settings.SshTargetCard.ec6543cee9', 'Connect')}
+
>
)}
diff --git a/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx b/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx
index db9adf1279e..44aaaddb814 100644
--- a/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx
+++ b/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx
@@ -159,8 +159,14 @@ export function SshTargetDestructiveActions({
- {editingId ? translate("auto.components.settings.SshTargetForm.f2331ce599", "Edit SSH Target") : translate("auto.components.settings.SshTargetForm.29af933cd5", "New SSH Target")}
+
+ {editingId
+ ? translate('auto.components.settings.SshTargetForm.f2331ce599', 'Edit SSH Target')
+ : translate('auto.components.settings.SshTargetForm.29af933cd5', 'New SSH Target')}
+
- {translate("auto.components.settings.SshTargetForm.298de87a88", "Label")}
+ {translate('auto.components.settings.SshTargetForm.298de87a88', 'Label')}
onFormChange((f) => ({ ...f, label: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.b8dab0aa7b", "My Server")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.b8dab0aa7b',
+ 'My Server'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.ce370ce674", "Host or alias *")}
+
+ {translate('auto.components.settings.SshTargetForm.ce370ce674', 'Host or alias *')}
+
onFormChange((f) => ({ ...f, host: e.target.value }))}
onBlur={() => onFormChange(applyParsedSshHostInput)}
- placeholder={translate("auto.components.settings.SshTargetForm.2ee9bcd2e8", "server, deploy@server:2222, ssh://server")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.2ee9bcd2e8',
+ 'server, deploy@server:2222, ssh://server'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.dc1dc52aaa", "Username")}
+
+ {translate('auto.components.settings.SshTargetForm.dc1dc52aaa', 'Username')}
+
onFormChange((f) => ({ ...f, username: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.47e082bc17", "deploy")}
+ placeholder={translate('auto.components.settings.SshTargetForm.47e082bc17', 'deploy')}
/>
-
{translate("auto.components.settings.SshTargetForm.c94cfa634c", "Port")}
+
{translate('auto.components.settings.SshTargetForm.c94cfa634c', 'Port')}
- {translate("auto.components.settings.SshTargetForm.63c0c145c1", "Identity File")}
+ {translate('auto.components.settings.SshTargetForm.63c0c145c1', 'Identity File')}
+
onFormChange((f) => ({ ...f, identityFile: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.d6a5f2ee5c", "~/.ssh/id_ed25519 (leave empty for SSH agent)")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.d6a5f2ee5c',
+ '~/.ssh/id_ed25519 (leave empty for SSH agent)'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.cb91f6375c", "Optional. SSH agent is used by default.")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.cb91f6375c',
+ 'Optional. SSH agent is used by default.'
+ )}
+
-
{translate("auto.components.settings.SshTargetForm.c7d0e18ecb", "Proxy Command")}
+
+ {translate('auto.components.settings.SshTargetForm.c7d0e18ecb', 'Proxy Command')}
+
onFormChange((f) => ({ ...f, proxyCommand: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.f42d844544", "e.g. cloudflared access ssh --hostname %h")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.f42d844544',
+ 'e.g. cloudflared access ssh --hostname %h'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.3b01ca44a0", "Optional. Used for tunneling (e.g. Cloudflare Access, ProxyCommand).")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.3b01ca44a0',
+ 'Optional. Used for tunneling (e.g. Cloudflare Access, ProxyCommand).'
+ )}
+
-
{translate("auto.components.settings.SshTargetForm.b2ab248ded", "Jump Host")}
+
+ {translate('auto.components.settings.SshTargetForm.b2ab248ded', 'Jump Host')}
+
onFormChange((f) => ({ ...f, jumpHost: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.11bcb4507a", "bastion.example.com")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.11bcb4507a',
+ 'bastion.example.com'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.feae1d1e69", "Optional. Equivalent to ProxyJump / ssh -J.")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.feae1d1e69',
+ 'Optional. Equivalent to ProxyJump / ssh -J.'
+ )}
+
-
{translate("auto.components.settings.SshTargetForm.92f80edbfd", "Relay Grace Period (seconds)")}
+
+ {translate(
+ 'auto.components.settings.SshTargetForm.92f80edbfd',
+ 'Relay Grace Period (seconds)'
+ )}
+
- {translate("auto.components.settings.SshTargetForm.71fc546097", "Keep alive until reset")}
+
+ {translate(
+ 'auto.components.settings.SshTargetForm.71fc546097',
+ 'Keep alive until reset'
+ )}
+
- {translate("auto.components.settings.SshTargetForm.b574994adc", "Remote terminals stay available until you end them or reset the relay.")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.b574994adc',
+ 'Remote terminals stay available until you end them or reset the relay.'
+ )}
+
- {translate("auto.components.settings.SshTargetForm.137e88ce8d", "How long the relay keeps terminals alive after disconnect. Default: 10800 (3 hours). Maximum:")}{MAX_SSH_RELAY_GRACE_PERIOD_SECONDS} {translate("auto.components.settings.SshTargetForm.1b19b00e93", "(7 days).")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.137e88ce8d',
+ 'How long the relay keeps terminals alive after disconnect. Default: 10800 (3 hours). Maximum:'
+ )}
+ {MAX_SSH_RELAY_GRACE_PERIOD_SECONDS}{' '}
+ {translate('auto.components.settings.SshTargetForm.1b19b00e93', '(7 days).')}
+
- {editingId ? translate("auto.components.settings.SshTargetForm.a62b4cb39a", "Save Changes") : translate("auto.components.settings.SshTargetForm.9518545cb6", "Add Target")}
+ {editingId
+ ? translate('auto.components.settings.SshTargetForm.a62b4cb39a', 'Save Changes')
+ : translate('auto.components.settings.SshTargetForm.9518545cb6', 'Add Target')}
- {translate("auto.components.settings.SshTargetForm.fea9cb402e", "Cancel")}
+ {translate('auto.components.settings.SshTargetForm.fea9cb402e', 'Cancel')}
+
)
diff --git a/src/renderer/src/components/settings/TasksPane.tsx b/src/renderer/src/components/settings/TasksPane.tsx
index a3e1a9a69dd..2195201b112 100644
--- a/src/renderer/src/components/settings/TasksPane.tsx
+++ b/src/renderer/src/components/settings/TasksPane.tsx
@@ -26,26 +26,38 @@ const TASK_PROVIDER_OPTIONS: readonly {
}[] = [
{
id: 'github',
- label: translate("auto.components.settings.TasksPane.e14063e727", "GitHub"),
- description: translate("auto.components.settings.TasksPane.1db47236cd", "Show GitHub in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.e14063e727', 'GitHub'),
+ description: translate(
+ 'auto.components.settings.TasksPane.1db47236cd',
+ 'Show GitHub in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
},
{
id: 'gitlab',
- label: translate("auto.components.settings.TasksPane.7c5d7fdc20", "GitLab"),
- description: translate("auto.components.settings.TasksPane.dd67a1b6e1", "Show GitLab in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.7c5d7fdc20', 'GitLab'),
+ description: translate(
+ 'auto.components.settings.TasksPane.dd67a1b6e1',
+ 'Show GitLab in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
},
{
id: 'linear',
- label: translate("auto.components.settings.TasksPane.09ae2d7c51", "Linear"),
- description: translate("auto.components.settings.TasksPane.e4170c9615", "Show Linear in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.09ae2d7c51', 'Linear'),
+ description: translate(
+ 'auto.components.settings.TasksPane.e4170c9615',
+ 'Show Linear in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
},
{
id: 'jira',
- label: translate("auto.components.settings.TasksPane.6b23a34f6d", "Jira"),
- description: translate("auto.components.settings.TasksPane.8e1305fcc6", "Show Jira in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.6b23a34f6d', 'Jira'),
+ description: translate(
+ 'auto.components.settings.TasksPane.8e1305fcc6',
+ 'Show Jira in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
}
]
@@ -73,13 +85,19 @@ export function TasksPane({ settings, updateSettings }: TasksPaneProps): React.J
- {translate("auto.components.settings.TerminalFontSizeSetting.9b5252c85a", "px")}
+
+ {translate('auto.components.settings.TerminalFontSizeSetting.9b5252c85a', 'px')}
+
}
/>
diff --git a/src/renderer/src/components/settings/UIZoomControl.tsx b/src/renderer/src/components/settings/UIZoomControl.tsx
index 35c8b1b8bf2..eafee9b796b 100644
--- a/src/renderer/src/components/settings/UIZoomControl.tsx
+++ b/src/renderer/src/components/settings/UIZoomControl.tsx
@@ -50,7 +50,8 @@ export function UIZoomControl(): React.JSX.Element {
className="ml-1 gap-1.5"
>
- {translate("auto.components.settings.UIZoomControl.c2c64b24d0", "Reset")}
+ {translate('auto.components.settings.UIZoomControl.c2c64b24d0', 'Reset')}
+
)
}
diff --git a/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx b/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx
index 315d2448c78..821c35dd165 100644
--- a/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx
+++ b/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx
@@ -96,8 +96,14 @@ export function WorktreeSymlinksSection({
return (
-
{translate("auto.components.settings.WorktreeSymlinksSection.4755f120b6", "Worktree Symlinks")}
+
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.4755f120b6',
+ 'Worktree Symlinks'
+ )}
+
- {translate("auto.components.settings.WorktreeSymlinksSection.7ff265071d", "When a new worktree is created, each path listed here will be symlinked from the primary checkout.")}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.7ff265071d',
+ 'When a new worktree is created, each path listed here will be symlinked from the primary checkout.'
+ )}
+
- {translate("auto.components.settings.WorktreeSymlinksSection.241325302c", "Add Path")}
+ {translate('auto.components.settings.WorktreeSymlinksSection.241325302c', 'Add Path')}
+
- {translate("auto.components.settings.WorktreeSymlinksSection.ab40b8a5f1", "No matches. Keep typing to add a custom path.")}
+
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.ab40b8a5f1',
+ 'No matches. Keep typing to add a custom path.'
+ )}
+
{showLiteralItem ? (
- {translate("auto.components.settings.WorktreeSymlinksSection.b2429aeb31", "Add")}{' '}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.b2429aeb31',
+ 'Add'
+ )}{' '}
{queryTrimmed}
@@ -165,7 +192,11 @@ export function WorktreeSymlinksSection({
{entry.name}
{alreadyAdded ? (
- {translate("auto.components.settings.WorktreeSymlinksSection.ea06227efa", "added")}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.ea06227efa',
+ 'added'
+ )}
+
) : null}
)
@@ -178,7 +209,11 @@ export function WorktreeSymlinksSection({
{paths.length === 0 ? (
- {translate("auto.components.settings.WorktreeSymlinksSection.31ebab5403", "No symlink paths configured for this repository.")}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.31ebab5403',
+ 'No symlink paths configured for this repository.'
+ )}
+
) : (
@@ -187,9 +222,23 @@ export function WorktreeSymlinksSection({
-
{translate("auto.components.settings.WorktreeSymlinksSection.b814c618e2", "Linked paths")}
+
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.b814c618e2',
+ 'Linked paths'
+ )}
+
- {paths.length === 1 ? translate("auto.components.settings.WorktreeSymlinksSection.9ea912d811", "1 path") : translate("auto.components.settings.WorktreeSymlinksSection.d72ba8dc68", "{{value0}} paths", { value0: paths.length })}
+ {paths.length === 1
+ ? translate(
+ 'auto.components.settings.WorktreeSymlinksSection.9ea912d811',
+ '1 path'
+ )
+ : translate(
+ 'auto.components.settings.WorktreeSymlinksSection.d72ba8dc68',
+ '{{value0}} paths',
+ { value0: paths.length }
+ )}
@@ -204,7 +253,11 @@ export function WorktreeSymlinksSection({
size="icon-xs"
variant="ghost"
onClick={() => handleRemove(path)}
- aria-label={translate("auto.components.settings.WorktreeSymlinksSection.1c1e35b219", "Remove {{value0}}", { value0: path })}
+ aria-label={translate(
+ 'auto.components.settings.WorktreeSymlinksSection.1c1e35b219',
+ 'Remove {{value0}}',
+ { value0: path }
+ )}
className="size-4 shrink-0 rounded-sm"
>
diff --git a/src/renderer/src/components/settings/WslCliRegistration.tsx b/src/renderer/src/components/settings/WslCliRegistration.tsx
index ea0eacf0e47..9d23dbeca93 100644
--- a/src/renderer/src/components/settings/WslCliRegistration.tsx
+++ b/src/renderer/src/components/settings/WslCliRegistration.tsx
@@ -41,7 +41,14 @@ export function WslCliRegistration({
}
} catch (error) {
if (mountedRef.current) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.WslCliRegistration.26b4b3b00f", "Failed to load WSL CLI status."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.WslCliRegistration.26b4b3b00f',
+ 'Failed to load WSL CLI status.'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -73,11 +80,23 @@ export function WslCliRegistration({
}
setStatus(next)
setDialogOpen(false)
- toast.success(translate("auto.components.settings.WslCliRegistration.951536dda5", "Registered `{{value0}}` in WSL.", { value0: next.commandName }))
+ toast.success(
+ translate(
+ 'auto.components.settings.WslCliRegistration.951536dda5',
+ 'Registered `{{value0}}` in WSL.',
+ { value0: next.commandName }
+ )
+ )
} catch (error) {
if (mountedRef.current) {
toast.error(
- error instanceof Error ? error.message : translate("auto.components.settings.WslCliRegistration.6f91ad1333", "Failed to register `{{value0}}` in WSL.", { value0: commandName })
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.WslCliRegistration.6f91ad1333',
+ 'Failed to register `{{value0}}` in WSL.',
+ { value0: commandName }
+ )
)
}
} finally {
@@ -96,11 +115,23 @@ export function WslCliRegistration({
}
setStatus(next)
setDialogOpen(false)
- toast.success(translate("auto.components.settings.WslCliRegistration.89c7414cf5", "Removed `{{value0}}` from WSL.", { value0: next.commandName }))
+ toast.success(
+ translate(
+ 'auto.components.settings.WslCliRegistration.89c7414cf5',
+ 'Removed `{{value0}}` from WSL.',
+ { value0: next.commandName }
+ )
+ )
} catch (error) {
if (mountedRef.current) {
toast.error(
- error instanceof Error ? error.message : translate("auto.components.settings.WslCliRegistration.52d990420e", "Failed to remove `{{value0}}` from WSL.", { value0: commandName })
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.WslCliRegistration.52d990420e',
+ 'Failed to remove `{{value0}}` from WSL.',
+ { value0: commandName }
+ )
)
}
} finally {
@@ -115,11 +146,23 @@ export function WslCliRegistration({
-
{translate("auto.components.settings.WslCliRegistration.d9c6880dbd", "WSL shell command")}
+
+ {translate(
+ 'auto.components.settings.WslCliRegistration.d9c6880dbd',
+ 'WSL shell command'
+ )}
+
{loading
- ? translate("auto.components.settings.WslCliRegistration.0307677bb9", "Checking WSL CLI registration...")
- : (status?.detail ?? translate("auto.components.settings.WslCliRegistration.7aa456a460", "Register `orca-ide` in ~/.local/bin inside WSL."))}
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.0307677bb9',
+ 'Checking WSL CLI registration...'
+ )
+ : (status?.detail ??
+ translate(
+ 'auto.components.settings.WslCliRegistration.7aa456a460',
+ 'Register `orca-ide` in ~/.local/bin inside WSL.'
+ ))}
@@ -131,13 +174,17 @@ export function WslCliRegistration({
size="icon-xs"
onClick={() => void refreshStatus()}
disabled={loading || busyAction !== null}
- aria-label={translate("auto.components.settings.WslCliRegistration.ab6b022a5c", "Refresh WSL CLI status")}
+ aria-label={translate(
+ 'auto.components.settings.WslCliRegistration.ab6b022a5c',
+ 'Refresh WSL CLI status'
+ )}
>
- {translate("auto.components.settings.WslCliRegistration.9b6627522c", "Refresh")}
+ {translate('auto.components.settings.WslCliRegistration.9b6627522c', 'Refresh')}
+
- {translate("auto.components.settings.WslCliRegistration.554305956d", "Command path:")}{' '}
+ {translate('auto.components.settings.WslCliRegistration.554305956d', 'Command path:')}{' '}
{status.commandPath}
) : null}
- {status?.state === "stale" && status.currentTarget ? (
+ {status?.state === 'stale' && status.currentTarget ? (
- {translate("auto.components.settings.WslCliRegistration.1dbb0377d9", "Existing launcher target:")}{status.currentTarget}
+ {translate(
+ 'auto.components.settings.WslCliRegistration.1dbb0377d9',
+ 'Existing launcher target:'
+ )}
+ {status.currentTarget}
) : null}
@@ -177,18 +228,33 @@ export function WslCliRegistration({
{isEnabled
- ? translate("auto.components.settings.WslCliRegistration.61ac55278e", "Remove `{{value0}}` from WSL?", { value0: commandName })
- : translate("auto.components.settings.WslCliRegistration.e49688f67f", "Register `{{value0}}` in WSL?", { value0: commandName })}
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.61ac55278e',
+ 'Remove `{{value0}}` from WSL?',
+ { value0: commandName }
+ )
+ : translate(
+ 'auto.components.settings.WslCliRegistration.e49688f67f',
+ 'Register `{{value0}}` in WSL?',
+ { value0: commandName }
+ )}
{isEnabled
- ? translate("auto.components.settings.WslCliRegistration.d8216eb22e", "This removes the WSL shell command. Orca itself remains installed on Windows.")
- : translate("auto.components.settings.WslCliRegistration.7ee4e52b99", "Orca will register {{value0}} so the command works from WSL terminals.", { value0: status?.commandPath ?? commandName })}
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.d8216eb22e',
+ 'This removes the WSL shell command. Orca itself remains installed on Windows.'
+ )
+ : translate(
+ 'auto.components.settings.WslCliRegistration.7ee4e52b99',
+ 'Orca will register {{value0}} so the command works from WSL terminals.',
+ { value0: status?.commandPath ?? commandName }
+ )}
{status?.commandPath ? (
- {translate("auto.components.settings.WslCliRegistration.119fef6cd2", "Target path:")}{' '}
+ {translate('auto.components.settings.WslCliRegistration.119fef6cd2', 'Target path:')}{' '}
{status.commandPath}
) : null}
@@ -198,18 +264,25 @@ export function WslCliRegistration({
onClick={() => setDialogOpen(false)}
disabled={busyAction !== null}
>
- {translate("auto.components.settings.WslCliRegistration.c6f6f89d7c", "Cancel")}
+ {translate('auto.components.settings.WslCliRegistration.c6f6f89d7c', 'Cancel')}
+
void (isEnabled ? handleRemove() : handleInstall())}
disabled={busyAction !== null || !isSupported}
>
- {busyAction === "remove"
- ? translate("auto.components.settings.WslCliRegistration.4598b18464", "Removing...")
- : busyAction === "install"
- ? translate("auto.components.settings.WslCliRegistration.4c4a9178a3", "Registering...")
+ {busyAction === 'remove'
+ ? translate('auto.components.settings.WslCliRegistration.4598b18464', 'Removing...')
+ : busyAction === 'install'
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.4c4a9178a3',
+ 'Registering...'
+ )
: isEnabled
- ? translate("auto.components.settings.WslCliRegistration.f951f85196", "Remove")
- : translate("auto.components.settings.WslCliRegistration.290bfff3ab", "Register")}
+ ? translate('auto.components.settings.WslCliRegistration.f951f85196', 'Remove')
+ : translate(
+ 'auto.components.settings.WslCliRegistration.290bfff3ab',
+ 'Register'
+ )}
diff --git a/src/renderer/src/components/settings/jira-integration-card.tsx b/src/renderer/src/components/settings/jira-integration-card.tsx
index c4b63bc1911..9abdb29c210 100644
--- a/src/renderer/src/components/settings/jira-integration-card.tsx
+++ b/src/renderer/src/components/settings/jira-integration-card.tsx
@@ -132,26 +132,38 @@ export function JiraIntegrationCard(): React.JSX.Element {
-
{translate("auto.components.settings.jira.integration.card.09742875cd", "Jira")}
+
+ {translate('auto.components.settings.jira.integration.card.09742875cd', 'Jira')}
+
{jiraStatus.connected
- ? translate("auto.components.settings.jira.integration.card.74f3063026", "{{value0}} site{{value1}} connected", { value0: jiraSites.length, value1: jiraSites.length === 1 ? '' : 's' })
- : translate("auto.components.settings.jira.integration.card.9a9f8d4910", "Connect Jira Cloud to browse, create, and link issues.")}
+ ? translate(
+ 'auto.components.settings.jira.integration.card.74f3063026',
+ '{{value0}} site{{value1}} connected',
+ { value0: jiraSites.length, value1: jiraSites.length === 1 ? '' : 's' }
+ )
+ : translate(
+ 'auto.components.settings.jira.integration.card.9a9f8d4910',
+ 'Connect Jira Cloud to browse, create, and link issues.'
+ )}
{jiraStatus.connected ? (
- {translate("auto.components.settings.jira.integration.card.efaab83c5d", "Add site")}
+ {translate('auto.components.settings.jira.integration.card.efaab83c5d', 'Add site')}
+
- {translate("auto.components.settings.jira.integration.card.9bb34706ca", "Connected")}
+ {translate('auto.components.settings.jira.integration.card.9bb34706ca', 'Connected')}
+
) : (
- {translate("auto.components.settings.jira.integration.card.a28f417220", "Connect Jira")}
+ {translate('auto.components.settings.jira.integration.card.a28f417220', 'Connect Jira')}
+
)}
@@ -159,7 +171,10 @@ export function JiraIntegrationCard(): React.JSX.Element {
{
setSiteUrlDraft(e.target.value)
@@ -170,7 +185,10 @@ export function JiraIntegrationCard(): React.JSX.Element {
/>
{
setEmailDraft(e.target.value)
@@ -182,7 +200,10 @@ export function JiraIntegrationCard(): React.JSX.Element {
{
setApiTokenDraft(e.target.value)
@@ -205,7 +226,11 @@ export function JiraIntegrationCard(): React.JSX.Element {
}
>
- {translate("auto.components.settings.jira.integration.card.1666f8d562", "Create an Atlassian API token")}
+ {translate(
+ 'auto.components.settings.jira.integration.card.1666f8d562',
+ 'Create an Atlassian API token'
+ )}
+
- {translate("auto.components.settings.jira.integration.card.5936977fcd", "Cancel")}
+ {translate('auto.components.settings.jira.integration.card.5936977fcd', 'Cancel')}
+
- {connectState === "connecting" ? (
+ {connectState === 'connecting' ? (
<>
- {translate("auto.components.settings.jira.integration.card.d914d7ab70", "Verifying…")}>
- ) : formMode.kind === "update" ? (
- translate("auto.components.settings.jira.integration.card.33a8b261ee", "Update credentials")
+ {translate(
+ 'auto.components.settings.jira.integration.card.d914d7ab70',
+ 'Verifying…'
+ )}
+ >
+ ) : formMode.kind === 'update' ? (
+ translate(
+ 'auto.components.settings.jira.integration.card.33a8b261ee',
+ 'Update credentials'
+ )
) : (
- translate("auto.components.settings.jira.integration.card.2e8bb790fd", "Connect")
+ translate('auto.components.settings.jira.integration.card.2e8bb790fd', 'Connect')
)}
@@ -256,10 +289,14 @@ export function JiraIntegrationCard(): React.JSX.Element {
{site.siteUrl}
- {testResult?.state === "ok" ? (
+ {testResult?.state === 'ok' ? (
- {translate("auto.components.settings.jira.integration.card.ab350991b8", "Verified")}
+ {translate(
+ 'auto.components.settings.jira.integration.card.ab350991b8',
+ 'Verified'
+ )}
+
) : null}
{testResult?.state === 'error' ? (
@@ -276,16 +313,25 @@ export function JiraIntegrationCard(): React.JSX.Element {
{testing ? (
<>
- {translate("auto.components.settings.jira.integration.card.cec06a0f79", "Testing…")}>
+ {translate(
+ 'auto.components.settings.jira.integration.card.cec06a0f79',
+ 'Testing…'
+ )}
+ >
) : (
- translate("auto.components.settings.jira.integration.card.255bfe98ec", "Test")
+ translate('auto.components.settings.jira.integration.card.255bfe98ec', 'Test')
)}
openUpdateForm(site)}>
- {translate("auto.components.settings.jira.integration.card.eaffa454e9", "Update")}
+ {translate('auto.components.settings.jira.integration.card.eaffa454e9', 'Update')}
+
void handleDisconnect(site.id)}
- aria-label={translate("auto.components.settings.jira.integration.card.9046a20d4c", "Disconnect {{value0}}", { value0: getJiraSiteLabel(site) })}
+ aria-label={translate(
+ 'auto.components.settings.jira.integration.card.9046a20d4c',
+ 'Disconnect {{value0}}',
+ { value0: getJiraSiteLabel(site) }
+ )}
className="rounded-md p-1 text-muted-foreground/50 transition-colors hover:text-destructive"
>
@@ -294,7 +340,11 @@ export function JiraIntegrationCard(): React.JSX.Element {
)
})}
- {translate("auto.components.settings.jira.integration.card.8ff73fef62", "Jira tokens are encrypted by the active runtime and stored locally. Re-entering the same site URL and email replaces that site's API token.")}
+ {translate(
+ 'auto.components.settings.jira.integration.card.8ff73fef62',
+ "Jira tokens are encrypted by the active runtime and stored locally. Re-entering the same site URL and email replaces that site's API token."
+ )}
+
) : null}
diff --git a/src/renderer/src/components/setup-guide/SetupGuideModal.tsx b/src/renderer/src/components/setup-guide/SetupGuideModal.tsx
index 54bd89fe2cb..cda8292a8a1 100644
--- a/src/renderer/src/components/setup-guide/SetupGuideModal.tsx
+++ b/src/renderer/src/components/setup-guide/SetupGuideModal.tsx
@@ -124,7 +124,10 @@ export default function SetupGuideModal(): JSX.Element | null {
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.setup.guide.SetupGuideModal.f3b5ffb2a6", "Hide checklist from sidebar")}
+ aria-label={translate(
+ 'auto.components.setup.guide.SetupGuideModal.f3b5ffb2a6',
+ 'Hide checklist from sidebar'
+ )}
onClick={handleHideFromSidebar}
className="absolute right-10 top-3.5 text-muted-foreground"
>
@@ -132,11 +135,20 @@ export default function SetupGuideModal(): JSX.Element | null {
- {translate("auto.components.setup.guide.SetupGuideModal.28cf59fcb4", "This will hide the checklist from the sidebar")}
+ {translate(
+ 'auto.components.setup.guide.SetupGuideModal.28cf59fcb4',
+ 'This will hide the checklist from the sidebar'
+ )}
+
- {translate("auto.components.setup.guide.SetupGuideModal.48a9e5ef2d", "Getting started")}
+
+ {translate(
+ 'auto.components.setup.guide.SetupGuideModal.48a9e5ef2d',
+ 'Getting started'
+ )}
+
- {translate("auto.components.setup.guide.SetupGuideModal.3598a3ca0c", "Finish the core workflows that make Orca useful for parallel agent work.")}
+ {translate(
+ 'auto.components.setup.guide.SetupGuideModal.3598a3ca0c',
+ 'Finish the core workflows that make Orca useful for parallel agent work.'
+ )}
+
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c", "Add Project")}
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.046751dbfb", "Add this folder as a separate Orca project.")}
+
+ {translate(
+ 'auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c',
+ 'Add Project'
+ )}
+
+
+ {translate(
+ 'auto.components.sidebar.AddProjectFromFolderDialog.046751dbfb',
+ 'Add this folder as a separate Orca project.'
+ )}
+
{folderPath && (
@@ -171,14 +187,19 @@ const AddProjectFromFolderDialog = React.memo(function AddProjectFromFolderDialo
handleOpenChange(false)} disabled={isAdding}>
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.7726a16374", "Cancel")}
+ {translate('auto.components.sidebar.AddProjectFromFolderDialog.7726a16374', 'Cancel')}
+
{isAdding ? (
) : (
)}
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c", "Add Project")}
+ {translate(
+ 'auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c',
+ 'Add Project'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx b/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
index 1d612020148..204ef5bc410 100644
--- a/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
@@ -53,7 +53,12 @@ export function useCreateRepo(
if (useAppStore.getState().settings?.activeRuntimeEnvironmentId?.trim()) {
// Why: the native folder picker returns a client-local path. Runtime
// project creation needs an explicit server parent path.
- toast.error(translate("auto.components.sidebar.AddRepoCreateStep.875dda0995", "Enter a server parent path."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.AddRepoCreateStep.875dda0995',
+ 'Enter a server parent path.'
+ )
+ )
return
}
const gen = createGenRef.current
@@ -119,13 +124,22 @@ export function useCreateRepo(
useAppStore.setState({ repos: updated })
}
if (wasDeduped) {
- toast.info(translate("auto.components.sidebar.AddRepoCreateStep.2c12db1511", "Project already added"), {
- description: repo.displayName
- })
+ toast.info(
+ translate(
+ 'auto.components.sidebar.AddRepoCreateStep.2c12db1511',
+ 'Project already added'
+ ),
+ {
+ description: repo.displayName
+ }
+ )
} else {
- toast.success(translate("auto.components.sidebar.AddRepoCreateStep.5e97f0c4b9", "Project created"), {
- description: repo.displayName
- })
+ toast.success(
+ translate('auto.components.sidebar.AddRepoCreateStep.5e97f0c4b9', 'Project created'),
+ {
+ description: repo.displayName
+ }
+ )
}
if (isGitRepoKind(repo)) {
// Why: Git repos use the shared default-checkout completion path.
@@ -336,9 +350,15 @@ export function CreateStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoCreateStep.db9be12229", "Start a new project")}
+
+ {translate('auto.components.sidebar.AddRepoCreateStep.db9be12229', 'Start a new project')}
+
- {translate("auto.components.sidebar.AddRepoCreateStep.d877ece0d6", "Create a Git repository or a plain folder and open it in Orca.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.d877ece0d6',
+ 'Create a Git repository or a plain folder and open it in Orca.'
+ )}
+
{/* Why: DialogContent is a CSS grid; grid items default to min-width:auto
@@ -350,7 +370,10 @@ export function CreateStep({
onKindChange('git')}
onArrowNav={cycleKind}
icon={ }
- title={translate("auto.components.sidebar.AddRepoCreateStep.11fd2a7db8", "Git repository")}
+ title={translate(
+ 'auto.components.sidebar.AddRepoCreateStep.11fd2a7db8',
+ 'Git repository'
+ )}
caption="Initializes an empty Git repo"
/>
onKindChange('folder')}
onArrowNav={cycleKind}
icon={ }
- title={translate("auto.components.sidebar.AddRepoCreateStep.038729c107", "Folder")}
+ title={translate('auto.components.sidebar.AddRepoCreateStep.038729c107', 'Folder')}
caption="Create a new folder"
/>
@@ -381,12 +407,16 @@ export function CreateStep({
htmlFor="create-project-name"
className="text-[11px] font-medium text-muted-foreground block"
>
- {translate("auto.components.sidebar.AddRepoCreateStep.a8149a3a5a", "Name")}
+ {translate('auto.components.sidebar.AddRepoCreateStep.a8149a3a5a', 'Name')}
+
onNameChange(e.target.value)}
- placeholder={translate("auto.components.sidebar.AddRepoCreateStep.0ae45b8238", "my-project")}
+ placeholder={translate(
+ 'auto.components.sidebar.AddRepoCreateStep.0ae45b8238',
+ 'my-project'
+ )}
className="h-11 text-sm font-mono"
disabled={isCreating}
autoFocus
@@ -413,7 +443,9 @@ export function CreateStep({
)}
- {isCreating ? translate("auto.components.sidebar.AddRepoCreateStep.85085d74d2", "Creating…") : translate("auto.components.sidebar.AddRepoCreateStep.45b7c26034", "Create project")}
+ {isCreating
+ ? translate('auto.components.sidebar.AddRepoCreateStep.85085d74d2', 'Creating…')
+ : translate('auto.components.sidebar.AddRepoCreateStep.45b7c26034', 'Create project')}
>
diff --git a/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx b/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
index be5d363629c..e58c0aa51d8 100644
--- a/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
@@ -45,12 +45,24 @@ export function AddRepoNestedImportStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoNestedImportStep.8db50afe1a", "Import repositories from folder")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.8db50afe1a',
+ 'Import repositories from folder'
+ )}
+
{scanInProgress ?
: null}
- {scanInProgress ? translate("auto.components.sidebar.AddRepoNestedImportStep.220dd32d83", "Scanning...") : null}
- {translate("auto.components.sidebar.AddRepoNestedImportStep.4df0d08cc5", "Found")} {repoCountLabel} {translate("auto.components.sidebar.AddRepoNestedImportStep.5f857ba8e6", "in")}{' '}
+ {scanInProgress
+ ? translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.220dd32d83',
+ 'Scanning...'
+ )
+ : null}
+ {translate('auto.components.sidebar.AddRepoNestedImportStep.4df0d08cc5', 'Found')}{' '}
+ {repoCountLabel}{' '}
+ {translate('auto.components.sidebar.AddRepoNestedImportStep.5f857ba8e6', 'in')}{' '}
{scan.selectedPath}
@@ -75,26 +87,40 @@ export function AddRepoNestedImportStep({
- {translate("auto.components.sidebar.AddRepoNestedImportStep.40199ef7b3", "Group name")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.40199ef7b3',
+ 'Group name'
+ )}
+
- {translate("auto.components.sidebar.AddRepoNestedImportStep.b20bb7c24f", "Keeps these repos together in one group. Best for related repos like microservices.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.b20bb7c24f',
+ 'Keeps these repos together in one group. Best for related repos like microservices.'
+ )}
+
onGroupNameChange(event.target.value)}
disabled={isAdding || scanInProgress}
@@ -109,14 +135,23 @@ export function AddRepoNestedImportStep({
disabled={isAdding || scanInProgress || selectedPaths.size === 0}
variant={isFirstRepoImport ? 'default' : 'outline'}
>
- {isFirstRepoImport ? translate("auto.components.sidebar.AddRepoNestedImportStep.cf9d382ca1", "Import") : translate("auto.components.sidebar.AddRepoNestedImportStep.5b2e6fe3c8", "Import separately")}
+ {isFirstRepoImport
+ ? translate('auto.components.sidebar.AddRepoNestedImportStep.cf9d382ca1', 'Import')
+ : translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.5b2e6fe3c8',
+ 'Import separately'
+ )}
{!isFirstRepoImport ? (
onImport('group')}
disabled={isAdding || scanInProgress || selectedPaths.size === 0}
>
- {translate("auto.components.sidebar.AddRepoNestedImportStep.c157f31a95", "Import as group")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.c157f31a95',
+ 'Import as group'
+ )}
+
) : null}
@@ -137,8 +172,14 @@ function AddRepoNestedImportStopButton({
variant="ghost"
size="icon-xs"
className="group text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive focus-visible:ring-destructive/40"
- aria-label={translate("auto.components.sidebar.AddRepoNestedImportStep.2f8298f3c3", "Stop scan")}
- title={translate("auto.components.sidebar.AddRepoNestedImportStep.a32bef9516", "Stop scanning")}
+ aria-label={translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.2f8298f3c3',
+ 'Stop scan'
+ )}
+ title={translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.a32bef9516',
+ 'Stop scanning'
+ )}
onClick={onStopScan}
>
@@ -146,7 +187,11 @@ function AddRepoNestedImportStopButton({
- {translate("auto.components.sidebar.AddRepoNestedImportStep.496f68cf8c", "Scanning repositories. Click to stop.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.496f68cf8c',
+ 'Scanning repositories. Click to stop.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx b/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx
index 0c3fc6795ae..8332415fa2a 100644
--- a/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx
@@ -43,9 +43,18 @@ export function RemoteStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoRemoteStep.dd3ff65486", "Browse remote filesystem")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.dd3ff65486',
+ 'Browse remote filesystem'
+ )}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.007651bdf9", "Navigate to a directory and click Select to choose it.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.007651bdf9',
+ 'Navigate to a directory and click Select to choose it.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.91b93a90a4", "Open remote project")}
+
+ {translate('auto.components.sidebar.AddRepoRemoteStep.91b93a90a4', 'Open remote project')}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.80557be85a", "Choose a connected SSH target and enter the path to a Git repository.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.80557be85a',
+ 'Choose a connected SSH target and enter the path to a Git repository.'
+ )}
+
-
{translate("auto.components.sidebar.AddRepoRemoteStep.44637f43bd", "SSH target")}
+
+ {translate('auto.components.sidebar.AddRepoRemoteStep.44637f43bd', 'SSH target')}
+
{sshTargets.length === 0 ? (
-
{translate("auto.components.sidebar.AddRepoRemoteStep.df6fbcf880", "No SSH targets configured.")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.df6fbcf880',
+ 'No SSH targets configured.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.0416bde073", "Add in Settings")}
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.0416bde073',
+ 'Add in Settings'
+ )}
+
) : (
@@ -99,7 +125,9 @@ export function RemoteStep({
-
{translate("auto.components.sidebar.AddRepoRemoteStep.ef410aa881", "Remote path")}
+
+ {translate('auto.components.sidebar.AddRepoRemoteStep.ef410aa881', 'Remote path')}
+
@@ -135,12 +166,18 @@ export function RemoteStep({
disabled={!selectedTargetId || !remotePath.trim() || isAddingRemote}
className="w-full"
>
- {isAddingRemote ? translate("auto.components.sidebar.AddRepoRemoteStep.35831a7312", "Adding...") : translate("auto.components.sidebar.AddRepoRemoteStep.36d427bb66", "Add remote project")}
+ {isAddingRemote
+ ? translate('auto.components.sidebar.AddRepoRemoteStep.35831a7312', 'Adding...')
+ : translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.36d427bb66',
+ 'Add remote project'
+ )}
{isScanningNested ? (
- {translate("auto.components.sidebar.AddRepoRemoteStep.5b205b5281", "Stop scan")}
+ {translate('auto.components.sidebar.AddRepoRemoteStep.5b205b5281', 'Stop scan')}
+
) : null}
>
diff --git a/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx b/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx
index 2667032d3c3..98b2f01fee9 100644
--- a/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx
@@ -35,9 +35,18 @@ export function AddRepoServerPathStartStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d", "Browse server filesystem")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d',
+ 'Browse server filesystem'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.0f8aba944c", "Navigate to a directory and click Select to choose it.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.0f8aba944c',
+ 'Navigate to a directory and click Select to choose it.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.39bd249b3a", "Add a project")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.39bd249b3a',
+ 'Add a project'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.8efa930eb5", "Add another project from the selected runtime server.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.8efa930eb5',
+ 'Add another project from the selected runtime server.'
+ )}
+
setBrowsing(true)}
/>
@@ -94,7 +130,11 @@ export function AddRepoServerPathStartStep({
- {translate("auto.components.sidebar.AddRepoServerStartStep.6b9958492a", "Want to import many repos at once? Browse to the parent folder.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.6b9958492a',
+ 'Want to import many repos at once? Browse to the parent folder.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.438493f214", "Or enter a server path manually")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.438493f214',
+ 'Or enter a server path manually'
+ )}
+
>
)
@@ -112,9 +156,18 @@ export function AddRepoServerPathStartStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoServerStartStep.3d0c035483", "Open server project")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.3d0c035483',
+ 'Open server project'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.423b5d3d31", "Add a Git repository or folder that already exists on the selected runtime server.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.423b5d3d31',
+ 'Add a Git repository or folder that already exists on the selected runtime server.'
+ )}
+
@@ -123,13 +176,17 @@ export function AddRepoServerPathStartStep({
htmlFor="server-project-path"
className="block text-[11px] font-medium text-muted-foreground"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.867692f505", "Server path")}
+ {translate('auto.components.sidebar.AddRepoServerStartStep.867692f505', 'Server path')}
+
onServerPathChange(event.target.value)}
- placeholder={translate("auto.components.sidebar.AddRepoServerStartStep.92d25420a0", "/home/user/project")}
+ placeholder={translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.92d25420a0',
+ '/home/user/project'
+ )}
className="h-11 min-w-0 flex-1 font-mono text-sm"
disabled={isAddingServerPath}
autoFocus
@@ -144,13 +201,20 @@ export function AddRepoServerPathStartStep({
className="h-11 w-11 shrink-0"
onClick={() => setBrowsing(true)}
disabled={isAddingServerPath || !runtimeEnvironmentId}
- aria-label={translate("auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d", "Browse server filesystem")}
+ aria-label={translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d',
+ 'Browse server filesystem'
+ )}
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d", "Browse server filesystem")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d',
+ 'Browse server filesystem'
+ )}
+
@@ -160,14 +224,22 @@ export function AddRepoServerPathStartStep({
disabled={!serverPath.trim() || isAddingServerPath}
className="h-10"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.8da4d1a5be", "Add Git Project")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.8da4d1a5be',
+ 'Add Git Project'
+ )}
+
onAddServerPath('folder')}
disabled={!serverPath.trim() || isAddingServerPath}
variant="outline"
className="h-10"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.e1710bf831", "Open as Folder")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.e1710bf831',
+ 'Open as Folder'
+ )}
+
{isAddingServerPath && addProjectBusyLabel ? (
@@ -181,7 +253,11 @@ export function AddRepoServerPathStartStep({
disabled={isAddingServerPath}
className="mx-auto block rounded px-2 py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-default disabled:opacity-40"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.ae990c86a0", "Back to add options")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ae990c86a0',
+ 'Back to add options'
+ )}
+
>
)
diff --git a/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx b/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx
index 80337443f4a..514d4f6af1a 100644
--- a/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx
@@ -27,7 +27,8 @@ export function AddRepoStepIndicator({
onClick={onBack}
>
- {translate("auto.components.sidebar.AddRepoStepIndicator.3bb655c117", "Back")}
+ {translate('auto.components.sidebar.AddRepoStepIndicator.3bb655c117', 'Back')}
+
)
}
diff --git a/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx b/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx
index 3b386bf5227..12fddd8ee40 100644
--- a/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx
+++ b/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx
@@ -66,22 +66,46 @@ export function AutoRenameFailedDialog({
- {translate("auto.components.sidebar.AutoRenameFailedDialog.ca3b225195", "Branch auto-name failed")}
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.ca3b225195',
+ 'Branch auto-name failed'
+ )}
+
- {translate("auto.components.sidebar.AutoRenameFailedDialog.ff62a18580", "Orca couldn't generate a branch name for")}{' '}
- {worktreeName} {translate("auto.components.sidebar.AutoRenameFailedDialog.3afcad0497", "from the first agent message.")}
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.ff62a18580',
+ "Orca couldn't generate a branch name for"
+ )}{' '}
+
{worktreeName} {' '}
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.3afcad0497',
+ 'from the first agent message.'
+ )}
+
{/* Why: agent-CLI output is literal and often multi-line, so render it
verbatim (mono, wrapped) inside a height-capped scroll region. */}
-
{translate("auto.components.sidebar.AutoRenameFailedDialog.74fc00776f", "Error details")}
+
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.74fc00776f',
+ 'Error details'
+ )}
+
onOpenChange(false)}>
- {translate("auto.components.sidebar.AutoRenameFailedDialog.aed1623b1e", "Close")}
+ {translate('auto.components.sidebar.AutoRenameFailedDialog.aed1623b1e', 'Close')}
+
diff --git a/src/renderer/src/components/sidebar/CacheTimer.tsx b/src/renderer/src/components/sidebar/CacheTimer.tsx
index 4155f83b751..4baf4ecf805 100644
--- a/src/renderer/src/components/sidebar/CacheTimer.tsx
+++ b/src/renderer/src/components/sidebar/CacheTimer.tsx
@@ -65,7 +65,11 @@ export default function CacheTimer({
)}
>
- {expired ? translate("auto.components.sidebar.CacheTimer.07729cc155", "expired") : label}
+
+ {expired
+ ? translate('auto.components.sidebar.CacheTimer.07729cc155', 'expired')
+ : label}
+
diff --git a/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx b/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
index 463f07a1e0b..025045b7938 100644
--- a/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
+++ b/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
@@ -22,9 +22,18 @@ export function CreateProjectParentBrowser({
return (
<>
- {translate("auto.components.sidebar.CreateProjectLocationField.f520f83a97", "Browse server filesystem")}
+
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.f520f83a97',
+ 'Browse server filesystem'
+ )}
+
- {translate("auto.components.sidebar.CreateProjectLocationField.b589b77997", "Navigate to a directory and click Select to choose it.")}
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.b589b77997',
+ 'Navigate to a directory and click Select to choose it.'
+ )}
+
- {translate("auto.components.sidebar.CreateProjectLocationField.134e37f711", "Location")}
+
+ {translate('auto.components.sidebar.CreateProjectLocationField.134e37f711', 'Location')}
+
{manualParentEntry ? (
onParentChange(e.target.value)}
- placeholder={translate("auto.components.sidebar.CreateProjectLocationField.2a20a603a3", "/home/user/projects")}
+ placeholder={translate(
+ 'auto.components.sidebar.CreateProjectLocationField.2a20a603a3',
+ '/home/user/projects'
+ )}
className="h-11 min-w-0 flex-1 text-sm font-mono"
disabled={isCreating}
spellCheck={false}
@@ -81,13 +95,20 @@ export function CreateProjectLocationField({
className="h-11 w-11 shrink-0"
onClick={onBrowseServer}
disabled={isCreating || !runtimeEnvironmentId}
- aria-label={translate("auto.components.sidebar.CreateProjectLocationField.f520f83a97", "Browse server filesystem")}
+ aria-label={translate(
+ 'auto.components.sidebar.CreateProjectLocationField.f520f83a97',
+ 'Browse server filesystem'
+ )}
>
- {translate("auto.components.sidebar.CreateProjectLocationField.f520f83a97", "Browse server filesystem")}
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.f520f83a97',
+ 'Browse server filesystem'
+ )}
+
) : createParent ? (
@@ -103,10 +124,14 @@ export function CreateProjectLocationField({
onClick={onPickParent}
disabled={isCreating}
className="shrink-0 inline-flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:cursor-not-allowed"
- aria-label={translate("auto.components.sidebar.CreateProjectLocationField.afaf54f245", "Change parent folder")}
+ aria-label={translate(
+ 'auto.components.sidebar.CreateProjectLocationField.afaf54f245',
+ 'Change parent folder'
+ )}
>
- {translate("auto.components.sidebar.CreateProjectLocationField.632b456b1b", "Change")}
+ {translate('auto.components.sidebar.CreateProjectLocationField.632b456b1b', 'Change')}
+
) : (
- {translate("auto.components.sidebar.CreateProjectLocationField.95548e33bf", "Choose parent folder...")}
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.95548e33bf',
+ 'Choose parent folder...'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx
index 33fa7ab12bc..e77787f23ee 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx
@@ -43,7 +43,9 @@ export function DeleteWorktreeDialogFooter({
return (
<>
- {isMainWorktree ? translate("auto.components.sidebar.DeleteWorktreeDialogFooter.cf95e3b5bb", "Close") : translate("auto.components.sidebar.DeleteWorktreeDialogFooter.c0e972d726", "Cancel")}
+ {isMainWorktree
+ ? translate('auto.components.sidebar.DeleteWorktreeDialogFooter.cf95e3b5bb', 'Close')
+ : translate('auto.components.sidebar.DeleteWorktreeDialogFooter.c0e972d726', 'Cancel')}
{!isMainWorktree && (
- {translate("auto.components.sidebar.DeleteWorktreeDirtyChangeHint.8e2994ce28", "Deleting this workspace permanently removes these changes from disk.")}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeDirtyChangeHint.8e2994ce28',
+ 'Deleting this workspace permanently removes these changes from disk.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx
index cc44246147e..427b96308cc 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx
@@ -23,11 +23,23 @@ export function DeleteWorktreeLineageNotice({
-
{translate("auto.components.sidebar.DeleteWorktreeLineageNotice.a940f3c96e", "Child workspaces will be deleted")}
+
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.a940f3c96e',
+ 'Child workspaces will be deleted'
+ )}
+
{childWorkspaceCount === 1
- ? translate("auto.components.sidebar.DeleteWorktreeLineageNotice.66798cc6a2", "Deleting this workspace also deletes 1 child workspace.")
- : translate("auto.components.sidebar.DeleteWorktreeLineageNotice.29b98bf9cd", "Deleting this workspace also deletes {{value0}} child workspaces.", { value0: childWorkspaceCount })}
+ ? translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.66798cc6a2',
+ 'Deleting this workspace also deletes 1 child workspace.'
+ )
+ : translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.29b98bf9cd',
+ 'Deleting this workspace also deletes {{value0}} child workspaces.',
+ { value0: childWorkspaceCount }
+ )}
{/* Why: long nowrap paths can otherwise give this grid child an
intrinsic width wider than the modal. */}
@@ -42,7 +54,13 @@ export function DeleteWorktreeLineageNotice({
))}
{descendants.length > 4 ? (
-
+{descendants.length - 4} {translate("auto.components.sidebar.DeleteWorktreeLineageNotice.ad407c2d55", "more")}
+
+ +{descendants.length - 4}{' '}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.ad407c2d55',
+ 'more'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx
index 15f26de743f..67ca3a0ee21 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx
@@ -32,6 +32,10 @@ export function DeleteWorktreeSkipConfirmOption({
>
{dontAskAgain ?
: null}
- {translate("auto.components.sidebar.DeleteWorktreeSkipConfirmOption.29aefb7e52", "Don't ask again")}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeSkipConfirmOption.29aefb7e52',
+ "Don't ask again"
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx
index 9bb0b37e2f9..89b22f6c841 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx
@@ -18,7 +18,21 @@ export function DeleteWorktreeWarningPanels({
- {translate("auto.components.sidebar.DeleteWorktreeWarningPanels.e3be9eba15", "This is the")}{translate("auto.components.sidebar.DeleteWorktreeWarningPanels.c4f96a6e18", "main worktree")} {translate("auto.components.sidebar.DeleteWorktreeWarningPanels.026738155a", "(the original clone directory).")}{mainWorktreeBlocker}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeWarningPanels.e3be9eba15',
+ 'This is the'
+ )}
+
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeWarningPanels.c4f96a6e18',
+ 'main worktree'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeWarningPanels.026738155a',
+ '(the original clone directory).'
+ )}
+ {mainWorktreeBlocker}
diff --git a/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx b/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx
index 84c4c05a632..4699f98a395 100644
--- a/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx
+++ b/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx
@@ -130,7 +130,11 @@ export default function ImportedWorktreesVisibilityLine({
size="icon-xs"
disabled={pending}
aria-expanded={isExpanded}
- aria-label={translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.f54f2bec5d", "{{value0}} hidden worktrees for {{value1}}", { value0: isExpanded ? 'Collapse' : 'Expand', value1: repoDisplayName })}
+ aria-label={translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.f54f2bec5d',
+ '{{value0}} hidden worktrees for {{value1}}',
+ { value0: isExpanded ? 'Collapse' : 'Expand', value1: repoDisplayName }
+ )}
onClick={() => setIsExpanded((value) => !value)}
className="shrink-0 rounded-[4px] text-muted-foreground hover:bg-worktree-sidebar-accent hover:text-worktree-sidebar-accent-foreground"
>
@@ -166,7 +170,10 @@ export default function ImportedWorktreesVisibilityLine({
{isExpanded ? (
{visibleWorktreeGroups.map((group) => (
@@ -190,7 +197,11 @@ export default function ImportedWorktreesVisibilityLine({
{group.worktrees
.slice(
@@ -220,8 +231,15 @@ export default function ImportedWorktreesVisibilityLine({
className="h-6 justify-start px-0 text-[11px] font-normal text-muted-foreground hover:text-worktree-sidebar-accent-foreground"
>
{expandedGroupPathKeys.has(normalizeRuntimePathForComparison(group.path))
- ? translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.294de4aeb2", "Show fewer")
- : translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.5a9688802a", "Show {{value0}} more", { value0: group.worktrees.length - PREVIEW_LIMIT })}
+ ? translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.294de4aeb2',
+ 'Show fewer'
+ )
+ : translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.5a9688802a',
+ 'Show {{value0}} more',
+ { value0: group.worktrees.length - PREVIEW_LIMIT }
+ )}
) : null}
@@ -230,11 +248,20 @@ export default function ImportedWorktreesVisibilityLine({
))}
{remainingGroupCount > 0 ? (
- + {remainingGroupCount} {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.b2bc47c080", "more locations")}
+ + {remainingGroupCount}{' '}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.b2bc47c080',
+ 'more locations'
+ )}
+
) : null}
- {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.9f4f14e821", "Change this later from the project menu.")}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.9f4f14e821',
+ 'Change this later from the project menu.'
+ )}
+
{onKeepHidden ? (
- {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.ad99f4eea9", "Keep hidden")}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.ad99f4eea9',
+ 'Keep hidden'
+ )}
+
) : null}
{onShow ? (
- {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.b7a87dc32f", "Show in worktree list")}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.b7a87dc32f',
+ 'Show in worktree list'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx b/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx
index dbb21e0a436..1e9ef329da3 100644
--- a/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx
+++ b/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx
@@ -68,7 +68,14 @@ const NonGitFolderDialog = React.memo(function NonGitFolderDialog() {
} catch (err) {
// This code path calls addRemote directly (not through the store),
// so the store's toast handling does not apply.
- toast.error(err instanceof Error ? err.message : translate("auto.components.sidebar.NonGitFolderDialog.c49fb13492", "Failed to add remote folder"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.sidebar.NonGitFolderDialog.c49fb13492',
+ 'Failed to add remote folder'
+ )
+ )
}
})()
} else if (folderPath) {
@@ -90,9 +97,15 @@ const NonGitFolderDialog = React.memo(function NonGitFolderDialog() {
- {translate("auto.components.sidebar.NonGitFolderDialog.e52454b7f6", "Open as Folder")}
+
+ {translate('auto.components.sidebar.NonGitFolderDialog.e52454b7f6', 'Open as Folder')}
+
- {translate("auto.components.sidebar.NonGitFolderDialog.8fba4b8cbb", "This folder isn't a Git repository. You'll have the editor, terminal, and search, but Git-based features won't be available.")}
+ {translate(
+ 'auto.components.sidebar.NonGitFolderDialog.8fba4b8cbb',
+ "This folder isn't a Git repository. You'll have the editor, terminal, and search, but Git-based features won't be available."
+ )}
+
{folderPath && (
@@ -103,8 +116,11 @@ const NonGitFolderDialog = React.memo(function NonGitFolderDialog() {
handleOpenChange(false)}>
- {translate("auto.components.sidebar.NonGitFolderDialog.05b33a17a9", "Cancel")}
- {translate("auto.components.sidebar.NonGitFolderDialog.e52454b7f6", "Open as Folder")}
+ {translate('auto.components.sidebar.NonGitFolderDialog.05b33a17a9', 'Cancel')}
+
+
+ {translate('auto.components.sidebar.NonGitFolderDialog.e52454b7f6', 'Open as Folder')}
+
diff --git a/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx b/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx
index d24ccde4747..7b341a3ab15 100644
--- a/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx
+++ b/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx
@@ -104,19 +104,48 @@ const OrcaYamlTrustDialog = React.memo(function OrcaYamlTrustDialog() {
{previouslyApproved
- ? translate("auto.components.sidebar.OrcaYamlTrustDialog.02b0ede5ad", "{{value0}}'s {{value1}} changed — run the new version?", { value0: repoName, value1: SCRIPT_KIND_LABEL[scriptKind] })
- : translate("auto.components.sidebar.OrcaYamlTrustDialog.e4a51dc4b3", "Run {{value0}} from {{value1}}?", { value0: SCRIPT_KIND_LABEL[scriptKind], value1: repoName })}
+ ? translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.02b0ede5ad',
+ "{{value0}}'s {{value1}} changed — run the new version?",
+ { value0: repoName, value1: SCRIPT_KIND_LABEL[scriptKind] }
+ )
+ : translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.e4a51dc4b3',
+ 'Run {{value0}} from {{value1}}?',
+ { value0: SCRIPT_KIND_LABEL[scriptKind], value1: repoName }
+ )}
{previouslyApproved ? (
<>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b", "orca.yaml")} {translate("auto.components.sidebar.OrcaYamlTrustDialog.c55beddbf8", "changed since you last approved. Re-review before it runs")}{' '}
+
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b', 'orca.yaml')}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.c55beddbf8',
+ 'changed since you last approved. Re-review before it runs'
+ )}{' '}
{SCRIPT_KIND_TRIGGER[scriptKind]}.
>
) : (
<>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.aa3ffb33fb", "This repository's")}{translate("auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b", "orca.yaml")} {translate("auto.components.sidebar.OrcaYamlTrustDialog.831f2cd9f0", "runs on your machine")}{' '}
- {SCRIPT_KIND_TRIGGER[scriptKind]}{translate("auto.components.sidebar.OrcaYamlTrustDialog.bf800b7e04", ". Only run if you trust")}{repoName}.
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.aa3ffb33fb',
+ "This repository's"
+ )}
+
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b', 'orca.yaml')}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.831f2cd9f0',
+ 'runs on your machine'
+ )}{' '}
+ {SCRIPT_KIND_TRIGGER[scriptKind]}
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.bf800b7e04',
+ '. Only run if you trust'
+ )}
+ {repoName}.
>
)}
@@ -125,7 +154,17 @@ const OrcaYamlTrustDialog = React.memo(function OrcaYamlTrustDialog() {
{scriptContent && (
- {previouslyApproved ? translate("auto.components.sidebar.OrcaYamlTrustDialog.9e52effffd", "New {{value0}} script", { value0: scriptKind }) : translate("auto.components.sidebar.OrcaYamlTrustDialog.95bf974a1a", "{{value0}} script", { value0: scriptKind })}
+ {previouslyApproved
+ ? translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.9e52effffd',
+ 'New {{value0}} script',
+ { value0: scriptKind }
+ )
+ : translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.95bf974a1a',
+ '{{value0}} script',
+ { value0: scriptKind }
+ )}
{scriptContent}
@@ -147,14 +186,22 @@ const OrcaYamlTrustDialog = React.memo(function OrcaYamlTrustDialog() {
onChange={(event) => setAlwaysTrust(event.target.checked)}
/>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.531689199b", "Always trust")}{translate("auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b", "orca.yaml")} {translate("auto.components.sidebar.OrcaYamlTrustDialog.c494b3ccb1", "in")}{repoName}
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.531689199b', 'Always trust')}
+
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b', 'orca.yaml')}
+ {' '}
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.c494b3ccb1', 'in')}
+ {repoName}
resolveAndClose('skip')}>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.43b7bec4cd", "Don't run")}
- resolveAndClose('run')}>{translate("auto.components.sidebar.OrcaYamlTrustDialog.f3e2b868fb", "Run hooks")}
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.43b7bec4cd', "Don't run")}
+
+ resolveAndClose('run')}>
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.f3e2b868fb', 'Run hooks')}
+
diff --git a/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx b/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx
index 47b569bd558..38b66950e49 100644
--- a/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx
+++ b/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx
@@ -76,8 +76,11 @@ export function PendingWorktreeRow({
useAppStore.getState().removePendingWorktreeCreation(creationId)}
className={cn(
'mr-1 flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground transition-opacity hover:bg-sidebar-accent hover:text-foreground focus-visible:opacity-100',
diff --git a/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx b/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx
index c907be3d5a8..4dfeb1a6490 100644
--- a/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx
+++ b/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx
@@ -77,9 +77,20 @@ export function ProjectGroupDeleteDialog({
showCloseButton={false}
>
- {translate("auto.components.sidebar.ProjectGroupDeleteDialog.591f330288", "Delete Project Group")}
+
+ {translate(
+ 'auto.components.sidebar.ProjectGroupDeleteDialog.591f330288',
+ 'Delete Project Group'
+ )}
+
- {translate("auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0", "Delete")}{groupName} {translate("auto.components.sidebar.ProjectGroupDeleteDialog.9be10d49ea", "and ungroup its projects.")}
+ {translate('auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0', 'Delete')}
+ {groupName} {' '}
+ {translate(
+ 'auto.components.sidebar.ProjectGroupDeleteDialog.9be10d49ea',
+ 'and ungroup its projects.'
+ )}
+
onOpenChange(false)}
>
- {translate("auto.components.sidebar.ProjectGroupDeleteDialog.ca65b78f78", "Cancel")}
+ {translate('auto.components.sidebar.ProjectGroupDeleteDialog.ca65b78f78', 'Cancel')}
+
- {deleting ? translate("auto.components.sidebar.ProjectGroupDeleteDialog.2c14ce677a", "Deleting...") : translate("auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0", "Delete")}
+ {deleting
+ ? translate(
+ 'auto.components.sidebar.ProjectGroupDeleteDialog.2c14ce677a',
+ 'Deleting...'
+ )
+ : translate('auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0', 'Delete')}
diff --git a/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx b/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx
index 11ac3140394..e2cbc96db3f 100644
--- a/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx
+++ b/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx
@@ -95,7 +95,8 @@ export function ProjectGroupNameDialog({
- {translate("auto.components.sidebar.ProjectGroupNameDialog.83dfbc5313", "Group Name")}
+ {translate('auto.components.sidebar.ProjectGroupNameDialog.83dfbc5313', 'Group Name')}
+
onOpenChange(false)}
>
- {translate("auto.components.sidebar.ProjectGroupNameDialog.d99a034073", "Cancel")}
+ {translate('auto.components.sidebar.ProjectGroupNameDialog.d99a034073', 'Cancel')}
+
- {submitting ? translate("auto.components.sidebar.ProjectGroupNameDialog.4a64e78822", "Saving...") : confirmLabel}
+ {submitting
+ ? translate(
+ 'auto.components.sidebar.ProjectGroupNameDialog.4a64e78822',
+ 'Saving...'
+ )
+ : confirmLabel}
diff --git a/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx b/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx
index 465f68aa3e7..2abaebe4365 100644
--- a/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx
+++ b/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx
@@ -639,7 +639,10 @@ export function RemoteFileBrowser({
onChange={(e) => handleInputChange(e.target.value)}
onPaste={handleInputPaste}
onKeyDown={handleFilterKeyDown}
- placeholder={translate("auto.components.sidebar.RemoteFileBrowser.2300612806", "Type to filter or enter a path…")}
+ placeholder={translate(
+ 'auto.components.sidebar.RemoteFileBrowser.2300612806',
+ 'Type to filter or enter a path…'
+ )}
aria-invalid={!!preview?.error}
aria-describedby={preview?.error ? 'remote-file-browser-path-error' : undefined}
className={cn(
@@ -683,13 +686,24 @@ export function RemoteFileBrowser({
) : !isPreviewActive && entries.length === 0 ? (
-
{translate("auto.components.sidebar.RemoteFileBrowser.51001182e3", "Empty directory")}
+
+ {translate(
+ 'auto.components.sidebar.RemoteFileBrowser.51001182e3',
+ 'Empty directory'
+ )}
+
) : displayEntries.length === 0 && !preview?.error ? (
// Directory has contents; filter hides them all. Distinguishing
// filter emptiness from directory emptiness keeps copy accurate.
-
{translate("auto.components.sidebar.RemoteFileBrowser.00c4235c10", "No matches for '{{value0}}'", { value0: isPreviewActive ? preview!.filter : filter })}
+
+ {translate(
+ 'auto.components.sidebar.RemoteFileBrowser.00c4235c10',
+ "No matches for '{{value0}}'",
+ { value0: isPreviewActive ? preview!.filter : filter }
+ )}
+
) : (
displayEntries.map((entry) => {
@@ -730,11 +744,18 @@ export function RemoteFileBrowser({
className="block text-[10px] text-muted-foreground truncate w-full"
title={fileHint ? undefined : resolvedPath}
>
- {fileHint ? FILE_HINT_TEXT : translate("auto.components.sidebar.RemoteFileBrowser.971d85cc84", "Opens as a remote project · {{value0}}", { value0: resolvedPath })}
+ {fileHint
+ ? FILE_HINT_TEXT
+ : translate(
+ 'auto.components.sidebar.RemoteFileBrowser.971d85cc84',
+ 'Opens as a remote project · {{value0}}',
+ { value0: resolvedPath }
+ )}
- {translate("auto.components.sidebar.RemoteFileBrowser.f8b1deb1a4", "Cancel")}
+ {translate('auto.components.sidebar.RemoteFileBrowser.f8b1deb1a4', 'Cancel')}
+
- {translate("auto.components.sidebar.RemoteFileBrowser.9e060f5815", "Select folder")}
+ {translate('auto.components.sidebar.RemoteFileBrowser.9e060f5815', 'Select folder')}
+
)
diff --git a/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx b/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx
index 2f6e8d4502c..8e37ecf0aed 100644
--- a/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx
+++ b/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx
@@ -41,16 +41,28 @@ const RemoveFolderDialog = React.memo(function RemoveFolderDialog() {
- {translate("auto.components.sidebar.RemoveFolderDialog.b79b39d865", "Remove Project")}
+
+ {translate('auto.components.sidebar.RemoveFolderDialog.b79b39d865', 'Remove Project')}
+
- {translate("auto.components.sidebar.RemoveFolderDialog.e62415c3d0", "This only removes")}{' '}
- {displayName} {translate("auto.components.sidebar.RemoveFolderDialog.8c097ef04e", "from Orca. It is still on your disk.")}
+ {translate(
+ 'auto.components.sidebar.RemoveFolderDialog.e62415c3d0',
+ 'This only removes'
+ )}{' '}
+ {displayName} {' '}
+ {translate(
+ 'auto.components.sidebar.RemoveFolderDialog.8c097ef04e',
+ 'from Orca. It is still on your disk.'
+ )}
+
handleOpenChange(false)}>
- {translate("auto.components.sidebar.RemoveFolderDialog.d36883e046", "Cancel")}
+ {translate('auto.components.sidebar.RemoveFolderDialog.d36883e046', 'Cancel')}
+
- {translate("auto.components.sidebar.RemoveFolderDialog.4dc5b5065b", "Remove")}
+ {translate('auto.components.sidebar.RemoveFolderDialog.4dc5b5065b', 'Remove')}
+
diff --git a/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx b/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx
index 177a1b69d35..0ac1b3241b4 100644
--- a/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx
+++ b/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx
@@ -13,7 +13,10 @@ export function ScrollToCurrentWorkspaceToolbarButton(): React.JSX.Element {
variant="ghost"
size="icon-xs"
type="button"
- aria-label={translate("auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663", "Reveal active workspace")}
+ aria-label={translate(
+ 'auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663',
+ 'Reveal active workspace'
+ )}
onClick={requestScrollToCurrentWorkspaceReveal}
className="text-muted-foreground"
>
@@ -21,7 +24,11 @@ export function ScrollToCurrentWorkspaceToolbarButton(): React.JSX.Element {
- {translate("auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663", "Reveal active workspace")}
+ {translate(
+ 'auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663',
+ 'Reveal active workspace'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx b/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx
index 4dbba6d943e..7cbaf215812 100644
--- a/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx
+++ b/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx
@@ -92,14 +92,23 @@ export function SetupGuideSidebarEntry(): React.JSX.Element | null {
sizeClassName="size-4"
/>
- {translate("auto.components.sidebar.SetupGuideSidebarEntry.88d402b71d", "Onboarding checklist")}
+
+ {translate(
+ 'auto.components.sidebar.SetupGuideSidebarEntry.88d402b71d',
+ 'Onboarding checklist'
+ )}
+
- {translate("auto.components.sidebar.SetupGuideSidebarEntry.b0a7bfc34c", "Hide from sidebar")}
+ {translate(
+ 'auto.components.sidebar.SetupGuideSidebarEntry.b0a7bfc34c',
+ 'Hide from sidebar'
+ )}
+
)
diff --git a/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx b/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx
index 8f3428df6a5..810b468a859 100644
--- a/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx
+++ b/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx
@@ -17,7 +17,10 @@ function DismissButton({ onDismiss }: DismissButtonProps): React.JSX.Element {
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.sidebar.SetupScriptPromptCardViews.5bfd5c8779", "Dismiss setup scripts")}
+ aria-label={translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.5bfd5c8779',
+ 'Dismiss setup scripts'
+ )}
className="-mr-1 text-muted-foreground"
onClick={onDismiss}
>
@@ -25,7 +28,8 @@ function DismissButton({ onDismiss }: DismissButtonProps): React.JSX.Element {
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.822ff300ad", "Dismiss")}
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.822ff300ad', 'Dismiss')}
+
)
}
@@ -45,10 +49,17 @@ export function DetectedSetupPreview({
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.7275f674cc", "Detected setup")}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.7275f674cc',
+ 'Detected setup'
+ )}
+
onSetupChange(event.target.value)}
spellCheck={false}
rows={Math.min(Math.max(setup.split('\n').length, 2), 6)}
@@ -56,7 +67,11 @@ export function DetectedSetupPreview({
/>
{provenance ? (
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.d02e6a42b1", "Detected from")}{provenance}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.d02e6a42b1',
+ 'Detected from'
+ )}
+ {provenance}
) : null}
@@ -89,7 +104,9 @@ export function PackageManagerActions({
) : (
)}
-
{translate("auto.components.sidebar.SetupScriptPromptCardViews.ca4efcbc25", "Save")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.ca4efcbc25', 'Save')}
+
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.eefa756190", "Configure manually")}
+
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.eefa756190',
+ 'Configure manually'
+ )}
+
)
@@ -119,24 +141,65 @@ export function SetupScriptPromptBody({
candidateSource
}: SetupScriptPromptBodyProps): React.JSX.Element {
if (isInspectionError) {
- return <>{translate("auto.components.sidebar.SetupScriptPromptCardViews.0155fb9ed3", "Couldn't verify this repo's setup script right now.")}>
+ return (
+ <>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.0155fb9ed3',
+ "Couldn't verify this repo's setup script right now."
+ )}
+ >
+ )
}
if (sharedSetupIgnored) {
return (
<>
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.bb879db364", "This repo ignores shared")}{translate("auto.components.sidebar.SetupScriptPromptCardViews.8f6be51aa1", "orca.yaml")} {translate("auto.components.sidebar.SetupScriptPromptCardViews.660cdc17f8", "setup scripts. Add a local command, or change the source in Settings.")}>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.bb879db364',
+ 'This repo ignores shared'
+ )}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.8f6be51aa1', 'orca.yaml')}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.660cdc17f8',
+ 'setup scripts. Add a local command, or change the source in Settings.'
+ )}
+ >
)
}
if (isPackageManagerSuggestion) {
- return <>{translate("auto.components.sidebar.SetupScriptPromptCardViews.aef6c0a213", "Save the detected command to run it whenever Orca creates a worktree.")}>
+ return (
+ <>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.aef6c0a213',
+ 'Save the detected command to run it whenever Orca creates a worktree.'
+ )}
+ >
+ )
}
if (candidateSource) {
return (
<>
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.b56d1322f7", "Found a setup command in")}{candidateSource} {translate("auto.components.sidebar.SetupScriptPromptCardViews.8349e3fa4c", ". Save it to run for new worktrees.")}>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.b56d1322f7',
+ 'Found a setup command in'
+ )}
+ {candidateSource}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.8349e3fa4c',
+ '. Save it to run for new worktrees.'
+ )}
+ >
)
}
- return <>{translate("auto.components.sidebar.SetupScriptPromptCardViews.0a98169776", "Add a setup command to run when Orca creates new worktrees.")}>
+ return (
+ <>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.0a98169776',
+ 'Add a setup command to run when Orca creates new worktrees.'
+ )}
+ >
+ )
}
export type InspectionErrorActionsProps = {
@@ -158,7 +221,9 @@ export function InspectionErrorActions({
onClick={onRetry}
>
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.4a98f907ae", "Retry")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.4a98f907ae', 'Retry')}
+
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.31b8b01a45", "Settings")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.31b8b01a45', 'Settings')}
+
)
@@ -188,7 +255,9 @@ export function ConfigureOnlyAction({ onConfigure }: ConfigureOnlyActionProps):
onClick={onConfigure}
>
-
{translate("auto.components.sidebar.SetupScriptPromptCardViews.3933401d28", "Configure")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.3933401d28', 'Configure')}
+
)
}
@@ -216,7 +285,12 @@ export function SaveLocalSetupAction({
) : (
)}
-
{translate("auto.components.sidebar.SetupScriptPromptCardViews.96a7f4198c", "Save local setup")}
+
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.96a7f4198c',
+ 'Save local setup'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx b/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx
index afe8a38fc7d..0c9f194827c 100644
--- a/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx
+++ b/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx
@@ -93,7 +93,12 @@ export function SidebarFeedbackDialog({
const handleSubmit = async (): Promise
=> {
const trimmed = feedback.trim()
if (!trimmed) {
- toast.warning(translate("auto.components.sidebar.SidebarFeedbackDialog.a2fd890d9e", "Please enter feedback before submitting."))
+ toast.warning(
+ translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.a2fd890d9e',
+ 'Please enter feedback before submitting.'
+ )
+ )
return
}
@@ -117,14 +122,24 @@ export function SidebarFeedbackDialog({
}
if (mountedRef.current) {
- toast.success(translate("auto.components.sidebar.SidebarFeedbackDialog.7a46c228b8", "Thanks for the feedback."))
+ toast.success(
+ translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.7a46c228b8',
+ 'Thanks for the feedback.'
+ )
+ )
setFeedback('')
setSubmitAnonymously(false)
onOpenChange(false)
}
} catch (err) {
if (mountedRef.current) {
- toast.error(translate("auto.components.sidebar.SidebarFeedbackDialog.60b721e857", "Failed to submit feedback. Please try again."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.60b721e857',
+ 'Failed to submit feedback. Please try again.'
+ )
+ )
}
console.error('Failed to submit feedback:', err)
} finally {
@@ -138,13 +153,24 @@ export function SidebarFeedbackDialog({
- {translate("auto.components.sidebar.SidebarFeedbackDialog.0eb643f07f", "Send Feedback")}
+
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.0eb643f07f', 'Send Feedback')}
+
- {translate("auto.components.sidebar.SidebarFeedbackDialog.a828fa4aee", "Share what's working, what's broken, or what Orca should do next.")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.a828fa4aee',
+ "Share what's working, what's broken, or what Orca should do next."
+ )}
+
-
{translate("auto.components.sidebar.SidebarFeedbackDialog.9b33530b3d", "Other ways to reach us")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.9b33530b3d',
+ 'Other ways to reach us'
+ )}
+
openExternalUrl(GITHUB_ISSUES_URL)}
>
- {translate("auto.components.sidebar.SidebarFeedbackDialog.d245c4ef6c", "GitHub issues")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.d245c4ef6c',
+ 'GitHub issues'
+ )}
+
- {translate("auto.components.sidebar.SidebarFeedbackDialog.26108d3699", "Join Discord")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.26108d3699',
+ 'Join Discord'
+ )}
+
- {translate("auto.components.sidebar.SidebarFeedbackDialog.3460258a54", "Follow on X")}
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.3460258a54', 'Follow on X')}
+
@@ -187,7 +222,10 @@ export function SidebarFeedbackDialog({
autoFocus
value={feedback}
onChange={(event) => setFeedback(event.target.value)}
- placeholder={translate("auto.components.sidebar.SidebarFeedbackDialog.d46ddd66fc", "What could we improve?")}
+ placeholder={translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.d46ddd66fc',
+ 'What could we improve?'
+ )}
rows={7}
className="min-h-32 w-full rounded-md border border-border bg-background px-3 py-2 text-sm outline-none ring-offset-background placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
/>
@@ -196,7 +234,7 @@ export function SidebarFeedbackDialog({
{viewer ? (
- {translate("auto.components.sidebar.SidebarFeedbackDialog.c9e5ea0791", "GitHub:")}{' '}
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.c9e5ea0791', 'GitHub:')}{' '}
{viewer.login}
{viewer.email ? ` (${viewer.email})` : ''}
@@ -212,20 +250,36 @@ export function SidebarFeedbackDialog({
'accent-foreground'
)}
/>
- {translate("auto.components.sidebar.SidebarFeedbackDialog.5b120b9634", "Submit anonymously")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.5b120b9634',
+ 'Submit anonymously'
+ )}
+
) : isViewerLoading ? (
- {translate("auto.components.sidebar.SidebarFeedbackDialog.d20439c560", "Checking GitHub identity…")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.d20439c560',
+ 'Checking GitHub identity…'
+ )}
+
) : (
- {translate("auto.components.sidebar.SidebarFeedbackDialog.8de03e23c5", "Submit with your typed feedback only, or connect `gh` to include GitHub identity.")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.8de03e23c5',
+ 'Submit with your typed feedback only, or connect `gh` to include GitHub identity.'
+ )}
+
)}
onOpenChange(false)} disabled={isSubmitting}>
- {translate("auto.components.sidebar.SidebarFeedbackDialog.8bf619e4cf", "Cancel")}
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.8bf619e4cf', 'Cancel')}
+
void handleSubmit()} disabled={isSubmitting || !feedback.trim()}>
- {isSubmitting ? translate("auto.components.sidebar.SidebarFeedbackDialog.69969ba364", "Sending…") : translate("auto.components.sidebar.SidebarFeedbackDialog.f2e42e1307", "Send")}
+ {isSubmitting
+ ? translate('auto.components.sidebar.SidebarFeedbackDialog.69969ba364', 'Sending…')
+ : translate('auto.components.sidebar.SidebarFeedbackDialog.f2e42e1307', 'Send')}
diff --git a/src/renderer/src/components/sidebar/SidebarFilter.tsx b/src/renderer/src/components/sidebar/SidebarFilter.tsx
index 589c8bf8179..da811a736a7 100644
--- a/src/renderer/src/components/sidebar/SidebarFilter.tsx
+++ b/src/renderer/src/components/sidebar/SidebarFilter.tsx
@@ -120,7 +120,16 @@ const SidebarFilter = React.memo(function SidebarFilter({
size="icon-xs"
type="button"
aria-label={
- hasAnyFilter ? translate("auto.components.sidebar.SidebarFilter.75405270ed", "Edit filters ({{value0}} active)", { value0: activeFilterCount }) : translate("auto.components.sidebar.SidebarFilter.f506a1262a", "Filter workspaces")
+ hasAnyFilter
+ ? translate(
+ 'auto.components.sidebar.SidebarFilter.75405270ed',
+ 'Edit filters ({{value0}} active)',
+ { value0: activeFilterCount }
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarFilter.f506a1262a',
+ 'Filter workspaces'
+ )
}
className="relative text-muted-foreground"
data-workspace-board-preserve-open={preserveWorkspaceBoardOpen ? '' : undefined}
@@ -140,7 +149,9 @@ const SidebarFilter = React.memo(function SidebarFilter({
- {hasAnyFilter ? translate("auto.components.sidebar.SidebarFilter.ee240a39eb", "Edit filters") : translate("auto.components.sidebar.SidebarFilter.f506a1262a", "Filter workspaces")}
+ {hasAnyFilter
+ ? translate('auto.components.sidebar.SidebarFilter.ee240a39eb', 'Edit filters')
+ : translate('auto.components.sidebar.SidebarFilter.f506a1262a', 'Filter workspaces')}
}
- label={translate("auto.components.sidebar.SidebarFilter.638a2d221d", "Hide sleeping")}
+ label={translate('auto.components.sidebar.SidebarFilter.638a2d221d', 'Hide sleeping')}
checked={!showSleepingWorkspaces}
onChange={(hideSleeping) => setShowSleepingWorkspaces(!hideSleeping)}
/>
}
- label={translate("auto.components.sidebar.SidebarFilter.e5cb32a898", "Hide default branch")}
+ label={translate(
+ 'auto.components.sidebar.SidebarFilter.e5cb32a898',
+ 'Hide default branch'
+ )}
checked={hideDefaultBranchWorkspace}
onChange={setHideDefaultBranchWorkspace}
/>
@@ -168,7 +182,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
- {translate("auto.components.sidebar.SidebarFilter.5f7085a077", "Projects")}{hasRepoFilter && (
+ {translate('auto.components.sidebar.SidebarFilter.5f7085a077', 'Projects')}
+ {hasRepoFilter && (
· {selectedCount}
@@ -181,14 +196,16 @@ const SidebarFilter = React.memo(function SidebarFilter({
className="rounded-full px-2 py-0.5 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:opacity-40 disabled:hover:bg-transparent"
disabled={allSelected}
>
- {translate("auto.components.sidebar.SidebarFilter.139877b384", "Select all")}
+ {translate('auto.components.sidebar.SidebarFilter.139877b384', 'Select all')}
+
- {translate("auto.components.sidebar.SidebarFilter.779b7ba05d", "Clear")}
+ {translate('auto.components.sidebar.SidebarFilter.779b7ba05d', 'Clear')}
+
@@ -200,7 +217,10 @@ const SidebarFilter = React.memo(function SidebarFilter({
>
{
// Why: typing creates a new filtered list, so keyboard
@@ -214,7 +234,12 @@ const SidebarFilter = React.memo(function SidebarFilter({
iconClassName="h-3.5 w-3.5"
/>
- {translate("auto.components.sidebar.SidebarFilter.b9e8802e73", "No projects match")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarFilter.b9e8802e73',
+ 'No projects match'
+ )}
+
{filteredRepos.map((r) => {
const checked = selectedRepoIdSet.has(r.id)
return (
@@ -233,7 +258,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
{r.connectionId && (
- {translate("auto.components.sidebar.SidebarFilter.81ded53722", "SSH")}
+ {translate('auto.components.sidebar.SidebarFilter.81ded53722', 'SSH')}
+
)}
{checked && (
@@ -258,7 +284,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
onClick={clearAll}
className="rounded-[5px] px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.sidebar.SidebarFilter.92a23e6d07", "Reset filters")}
+ {translate('auto.components.sidebar.SidebarFilter.92a23e6d07', 'Reset filters')}
+
) : (
)}
@@ -268,7 +295,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
className="inline-flex items-center gap-1.5 rounded-[5px] px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.sidebar.SidebarFilter.e3b3898218", "Add project")}
+ {translate('auto.components.sidebar.SidebarFilter.e3b3898218', 'Add project')}
+
diff --git a/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx b/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx
index baf73b9d3a0..7c75d54f37f 100644
--- a/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx
+++ b/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx
@@ -149,7 +149,17 @@ const SidebarRepositoryFilterSection = React.memo(function SidebarRepositoryFilt
0 ? translate("auto.components.sidebar.SidebarRepositoryFilterSection.5a273fbfce", "Add project...") : translate("auto.components.sidebar.SidebarRepositoryFilterSection.83a820fa71", "Filter projects...")}
+ placeholder={
+ selectedRepos.length > 0
+ ? translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.5a273fbfce',
+ 'Add project...'
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.83a820fa71',
+ 'Filter projects...'
+ )
+ }
value={query}
onValueChange={setQuery}
onKeyDown={handleInputKeyDown}
@@ -159,7 +169,15 @@ const SidebarRepositoryFilterSection = React.memo(function SidebarRepositoryFilt
/>
- {hasRepoFilter ? translate("auto.components.sidebar.SidebarRepositoryFilterSection.bbbc6e8e3b", "No unselected projects match") : translate("auto.components.sidebar.SidebarRepositoryFilterSection.4815c70605", "No projects match")}
+ {hasRepoFilter
+ ? translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.bbbc6e8e3b',
+ 'No unselected projects match'
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.4815c70605',
+ 'No projects match'
+ )}
{availableRepos.map((repo) => (
- {translate("auto.components.sidebar.SidebarRepositoryFilterSection.2656053db4", "SSH")}
+ {translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.2656053db4',
+ 'SSH'
+ )}
+
)}
@@ -218,7 +240,11 @@ function SelectedProjectPills({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.sidebar.SidebarRepositoryFilterSection.f10ca29601", "Remove {{value0}} filter", { value0: repo.displayName })}
+ aria-label={translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.f10ca29601',
+ 'Remove {{value0}} filter',
+ { value0: repo.displayName }
+ )}
className="-mr-1 size-4 rounded-full text-muted-foreground hover:bg-muted hover:text-foreground"
onMouseDown={(event) => event.preventDefault()}
onClick={() => onRemoveProject(repo.id)}
@@ -243,7 +269,8 @@ function ProjectFilterHeader({
return (
- {translate("auto.components.sidebar.SidebarRepositoryFilterSection.7679f0c268", "Projects")}{hasRepoFilter && (
+ {translate('auto.components.sidebar.SidebarRepositoryFilterSection.7679f0c268', 'Projects')}
+ {hasRepoFilter && (
- {translate("auto.components.sidebar.SidebarRepositoryFilterSection.d3a9c4cea1", "Clear")}
+ {translate('auto.components.sidebar.SidebarRepositoryFilterSection.d3a9c4cea1', 'Clear')}
+
)
}
diff --git a/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx b/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx
index 994d8ce464b..54654aaf3bd 100644
--- a/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx
+++ b/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx
@@ -78,13 +78,21 @@ export function SidebarSettingsHelpMenu(): React.JSX.Element {
return
}
setIsRestartingOrca(true)
- toast.info(translate("auto.components.sidebar.SidebarSettingsHelpMenu.5161eef55d", "Restarting Orca…"))
+ toast.info(
+ translate('auto.components.sidebar.SidebarSettingsHelpMenu.5161eef55d', 'Restarting Orca…')
+ )
void window.api.app.restart().catch((error) => {
if (mountedRef.current) {
setIsRestartingOrca(false)
- toast.error(translate("auto.components.sidebar.SidebarSettingsHelpMenu.4e8f5710d3", "Couldn't restart Orca."), {
- description: error instanceof Error ? error.message : undefined
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.4e8f5710d3',
+ "Couldn't restart Orca."
+ ),
+ {
+ description: error instanceof Error ? error.message : undefined
+ }
+ )
}
})
}
@@ -109,7 +117,10 @@ export function SidebarSettingsHelpMenu(): React.JSX.Element {
variant="ghost"
size="icon-xs"
type="button"
- aria-label={translate("auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c", "Help")}
+ aria-label={translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c',
+ 'Help'
+ )}
className="text-muted-foreground"
onPointerDown={(event) => revealAdminOptions(event.altKey)}
onClick={(event) => revealAdminOptions(event.altKey)}
@@ -119,26 +130,52 @@ export function SidebarSettingsHelpMenu(): React.JSX.Element {
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c", "Help")}
+ {translate('auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c', 'Help')}
+
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.a428c25998", "Settings")}{settingsShortcut}
+ {translate('auto.components.sidebar.SidebarSettingsHelpMenu.a428c25998', 'Settings')}
+ {settingsShortcut}
setFeedbackOpen(true)}>
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.4cf5b868d7", "Send Feedback")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.4cf5b868d7',
+ 'Send Feedback'
+ )}
+
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.e565171a7c", "Keyboard Shortcuts")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.e565171a7c',
+ 'Keyboard Shortcuts'
+ )}
+
-
-
-
+
+
+
openExternalUrl(DISCORD_URL)}>
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.eb9884e55b", "Discord")}
+ {translate('auto.components.sidebar.SidebarSettingsHelpMenu.eb9884e55b', 'Discord')}
+
)}
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.29c56f30ee", "Check for Updates")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.29c56f30ee',
+ 'Check for Updates'
+ )}
+
{showAdminOptions ? (
<>
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.ad3d3ed7f1", "Restart Orca")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.ad3d3ed7f1',
+ 'Restart Orca'
+ )}
+
>
) : null}
diff --git a/src/renderer/src/components/sidebar/SidebarToolbar.tsx b/src/renderer/src/components/sidebar/SidebarToolbar.tsx
index 3895ad455d2..3d8e274c3c7 100644
--- a/src/renderer/src/components/sidebar/SidebarToolbar.tsx
+++ b/src/renderer/src/components/sidebar/SidebarToolbar.tsx
@@ -22,11 +22,17 @@ const SidebarToolbar = React.memo(function SidebarToolbar() {
className="gap-1.5 text-muted-foreground"
>
- {translate("auto.components.sidebar.SidebarToolbar.abc62b6328", "Add Project")}
+
+ {translate('auto.components.sidebar.SidebarToolbar.abc62b6328', 'Add Project')}
+
- {translate("auto.components.sidebar.SidebarToolbar.19e32d0e5f", "Open folder picker to add a project")}
+ {translate(
+ 'auto.components.sidebar.SidebarToolbar.19e32d0e5f',
+ 'Open folder picker to add a project'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx b/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx
index 742081cfcd0..8a2a492cddc 100644
--- a/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx
+++ b/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx
@@ -13,17 +13,25 @@ const SidebarWorkspaceFilterSection = React.memo(function SidebarWorkspaceFilter
return (
<>
- {translate("auto.components.sidebar.SidebarWorkspaceFilterSection.82594419ba", "Filters")}
+
+ {translate('auto.components.sidebar.SidebarWorkspaceFilterSection.82594419ba', 'Filters')}
+
}
- label={translate("auto.components.sidebar.SidebarWorkspaceFilterSection.ed1611b65b", "Hide sleeping")}
+ label={translate(
+ 'auto.components.sidebar.SidebarWorkspaceFilterSection.ed1611b65b',
+ 'Hide sleeping'
+ )}
checked={!showSleepingWorkspaces}
onChange={(hideSleeping) => setShowSleepingWorkspaces(!hideSleeping)}
/>
}
- label={translate("auto.components.sidebar.SidebarWorkspaceFilterSection.c3fa13dc2e", "Hide default branch")}
+ label={translate(
+ 'auto.components.sidebar.SidebarWorkspaceFilterSection.c3fa13dc2e',
+ 'Hide default branch'
+ )}
checked={hideDefaultBranchWorkspace}
onChange={setHideDefaultBranchWorkspace}
/>
diff --git a/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx b/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
index c5327ddee0b..77e745bc6ad 100644
--- a/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
+++ b/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
@@ -27,7 +27,10 @@ const STATUS_MESSAGES: Partial
> = {
disconnected: 'This remote repository is not connected.',
reconnecting: 'Reconnecting to the remote host...',
'reconnection-failed': 'Reconnection to the remote host failed.',
- error: translate("auto.components.sidebar.SshDisconnectedDialog.376bed88e5", "The connection to the remote host encountered an error."),
+ error: translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.376bed88e5',
+ 'The connection to the remote host encountered an error.'
+ ),
'auth-failed': 'Authentication to the remote host failed.'
}
@@ -53,7 +56,14 @@ export function SshDisconnectedDialog({
onOpenChange(false)
}
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.sidebar.SshDisconnectedDialog.656368f3a2", "Reconnection failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.656368f3a2',
+ 'Reconnection failed'
+ )
+ )
} finally {
if (mountedRef.current) {
setConnecting(false)
@@ -105,7 +115,15 @@ export function SshDisconnectedDialog({
) : (
)}
- {isConnecting ? translate("auto.components.sidebar.SshDisconnectedDialog.cb5938ae79", "Reconnecting...") : translate("auto.components.sidebar.SshDisconnectedDialog.11552bf786", "SSH Disconnected")}
+ {isConnecting
+ ? translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.cb5938ae79',
+ 'Reconnecting...'
+ )
+ : translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.11552bf786',
+ 'SSH Disconnected'
+ )}
{message}
@@ -129,15 +147,20 @@ export function SshDisconnectedDialog({
onClick={() => onOpenChange(false)}
disabled={isConnecting}
>
- {translate("auto.components.sidebar.SshDisconnectedDialog.89385db176", "Dismiss")}
+ {translate('auto.components.sidebar.SshDisconnectedDialog.89385db176', 'Dismiss')}
+
{showReconnect && (
void handleReconnect()} disabled={isConnecting}>
{isConnecting ? (
<>
- {translate("auto.components.sidebar.SshDisconnectedDialog.ca4a7892af", "Connecting...")}>
+ {translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.ca4a7892af',
+ 'Connecting...'
+ )}
+ >
) : (
- translate("auto.components.sidebar.SshDisconnectedDialog.4afcca1d24", "Reconnect")
+ translate('auto.components.sidebar.SshDisconnectedDialog.4afcca1d24', 'Reconnect')
)}
)}
diff --git a/src/renderer/src/components/sidebar/SshTargetRow.tsx b/src/renderer/src/components/sidebar/SshTargetRow.tsx
index 209d6c2c872..77a3bf955dc 100644
--- a/src/renderer/src/components/sidebar/SshTargetRow.tsx
+++ b/src/renderer/src/components/sidebar/SshTargetRow.tsx
@@ -96,9 +96,10 @@ export function SshTargetRow({
{isBusy ? (
<>
- {translate("auto.components.sidebar.SshTargetRow.4677394048", "Connecting…")}>
+ {translate('auto.components.sidebar.SshTargetRow.4677394048', 'Connecting…')}
+ >
) : (
- translate("auto.components.sidebar.SshTargetRow.75ad429b5d", "Connect")
+ translate('auto.components.sidebar.SshTargetRow.75ad429b5d', 'Connect')
)}
)}
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
index 9415240f83c..5df17c4a309 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
@@ -46,7 +46,7 @@ function WorkspaceKanbanCard({
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx
index 8be0c1a9171..70a91a20bf7 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx
@@ -36,14 +36,28 @@ export default function WorkspaceKanbanDrawerHeader({
<>
- {translate("auto.components.sidebar.WorkspaceKanbanDrawerHeader.c6a77ab0f4", "Workspace board")}
+
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanDrawerHeader.c6a77ab0f4',
+ 'Workspace board'
+ )}
+
{selectedCount > 1 ? (
- {selectedCount} {translate("auto.components.sidebar.WorkspaceKanbanDrawerHeader.81870af08f", "selected")}
+ {selectedCount}{' '}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanDrawerHeader.81870af08f',
+ 'selected'
+ )}
+
) : null}
- {translate("auto.components.sidebar.WorkspaceKanbanDrawerHeader.e1a34450fc", "Organize workspaces by status and open workspace cards.")}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanDrawerHeader.e1a34450fc',
+ 'Organize workspaces by status and open workspace cards.'
+ )}
+
@@ -62,7 +76,15 @@ export default function WorkspaceKanbanDrawerHeader({
onRemoveStatus={onRemoveStatus}
onAddStatus={onAddStatus}
/>
-
+
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx
index 657fe0c7bf5..d7e5aa21992 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx
@@ -26,8 +26,15 @@ export default function WorkspaceKanbanPinDropTarget({
onDragLeave={onDragLeave}
>
- {translate("auto.components.sidebar.WorkspaceKanbanPinDropTarget.8fae2d0862", "Pinned")}
- {translate("auto.components.sidebar.WorkspaceKanbanPinDropTarget.c30151c5ee", "Drop here to pin without changing status.")}
+
+ {translate('auto.components.sidebar.WorkspaceKanbanPinDropTarget.8fae2d0862', 'Pinned')}
+
+
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanPinDropTarget.c30151c5ee',
+ 'Drop here to pin without changing status.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx
index 46a61e2a9ce..bd435b5a237 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx
@@ -41,7 +41,10 @@ export default function WorkspaceKanbanSettingsMenu({
@@ -50,7 +53,11 @@ export default function WorkspaceKanbanSettingsMenu({
- {translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.34f03eb0de", "Board settings")}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.34f03eb0de',
+ 'Board settings'
+ )}
+
- {translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.395e541d5d", "Statuses")}
+
+ {translate('auto.components.sidebar.WorkspaceKanbanSettingsMenu.395e541d5d', 'Statuses')}
+
{workspaceStatuses.map((status, index) => {
const meta = getWorkspaceStatusVisualMeta(status)
@@ -88,7 +97,11 @@ export default function WorkspaceKanbanSettingsMenu({
}
}}
className="h-7 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-[12px] text-foreground outline-none focus-visible:ring-1 focus-visible:ring-ring"
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.8ce44af9a8", "Rename {{value0}}", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.8ce44af9a8',
+ 'Rename {{value0}}',
+ { value0: status.label }
+ )}
/>
onMoveStatus(status.id, -1)}
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0", "Move {{value0}} left", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0',
+ 'Move {{value0}} left',
+ { value0: status.label }
+ )}
>
@@ -113,7 +130,11 @@ export default function WorkspaceKanbanSettingsMenu({
className="size-7"
disabled={index === workspaceStatuses.length - 1}
onClick={() => onMoveStatus(status.id, 1)}
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0", "Move {{value0}} right", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0',
+ 'Move {{value0}} right',
+ { value0: status.label }
+ )}
>
@@ -124,7 +145,11 @@ export default function WorkspaceKanbanSettingsMenu({
className="size-7 text-muted-foreground hover:text-destructive"
disabled={workspaceStatuses.length <= 1}
onClick={() => onRemoveStatus(status.id)}
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.054cb50df7", "Remove {{value0}}", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.054cb50df7',
+ 'Remove {{value0}}',
+ { value0: status.label }
+ )}
>
@@ -140,7 +165,11 @@ export default function WorkspaceKanbanSettingsMenu({
onClick={onAddStatus}
>
- {translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.79eb990aa4", "Add status")}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.79eb990aa4',
+ 'Add status'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx
index 46e018bd445..aef39b12e1d 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx
@@ -101,7 +101,10 @@ export default function WorkspaceKanbanStatusLane({
data-workspace-board-column-resize-handle=""
role="separator"
aria-orientation="vertical"
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanStatusLane.3611d1ae7f", "Resize workspace board columns")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanStatusLane.3611d1ae7f',
+ 'Resize workspace board columns'
+ )}
aria-valuemin={WORKSPACE_BOARD_COLUMN_WIDTH_MIN}
aria-valuemax={WORKSPACE_BOARD_COLUMN_WIDTH_MAX}
aria-valuenow={columnWidth}
@@ -169,7 +172,8 @@ export default function WorkspaceKanbanStatusLane({
) : (
- {translate("auto.components.sidebar.WorkspaceKanbanStatusLane.8ad104642b", "Empty")}
+ {translate('auto.components.sidebar.WorkspaceKanbanStatusLane.8ad104642b', 'Empty')}
+
)}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx b/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx
index 0224f7ec27a..265ba436f40 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx
@@ -394,7 +394,7 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
onMouseDown={stopBubble}
onPointerDown={stopBubble}
role={hasLineage ? 'tree' : 'group'}
- aria-label={translate("auto.components.sidebar.WorktreeCardAgents.1b0a156717", "Agents")}
+ aria-label={translate('auto.components.sidebar.WorktreeCardAgents.1b0a156717', 'Agents')}
data-compact-agent-list="true"
>
{agents.length === 0 ? null : shouldUseSummaryRow ? (
@@ -436,7 +436,7 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
onMouseDown={stopBubble}
onPointerDown={stopBubble}
role={hasLineage ? 'tree' : 'group'}
- aria-label={translate("auto.components.sidebar.WorktreeCardAgents.1b0a156717", "Agents")}
+ aria-label={translate('auto.components.sidebar.WorktreeCardAgents.1b0a156717', 'Agents')}
>
{rootAgents.map((rootAgent) => renderAgentBranch(rootAgent))}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx b/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx
index 5dfc3d48a04..3cd3fece64c 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx
@@ -34,7 +34,10 @@ export function IssueStateBadge({ state }: { state: IssueInfo['state'] }): React
if (state === 'closed') {
return (
@@ -44,7 +47,10 @@ export function IssueStateBadge({ state }: { state: IssueInfo['state'] }): React
return (
@@ -67,7 +73,14 @@ export function LinearStateBadge({ stateName }: { stateName: string }): React.JS
: 'border-border bg-muted/30 text-muted-foreground'
return (
-
+
)
@@ -87,7 +100,10 @@ export function ReviewStateBadge({
if (state === 'merged') {
return (
@@ -98,7 +114,10 @@ export function ReviewStateBadge({
if (state === 'closed') {
return (
@@ -109,7 +128,11 @@ export function ReviewStateBadge({
if (state === 'draft') {
return (
@@ -119,10 +142,13 @@ export function ReviewStateBadge({
return (
- {label === "MR" ? : }
+ {label === 'MR' ? : }
)
}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx b/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx
index 091d23e1c2f..3545454a918 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx
@@ -41,7 +41,11 @@ export function WorktreeCardPortsTrigger({
{
event.stopPropagation()
recordFeatureInteraction('ports')
@@ -116,7 +120,13 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
openInOrcaBrowser: shouldOpenWorkspacePortInOrcaBrowser(settings)
}).then((result) => {
if (!result.ok) {
- toast.error(translate("auto.components.sidebar.WorktreeCardPorts.d1113f4660", "Failed to open browser"), { description: result.reason })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.WorktreeCardPorts.d1113f4660',
+ 'Failed to open browser'
+ ),
+ { description: result.reason }
+ )
}
})
},
@@ -136,7 +146,11 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
recordFeatureInteraction('ports')
const address = addressForPort(port)
void window.api.ui.writeClipboardText(address)
- toast.success(translate("auto.components.sidebar.WorktreeCardPorts.c89f290e25", "Copied {{value0}}", { value0: address }))
+ toast.success(
+ translate('auto.components.sidebar.WorktreeCardPorts.c89f290e25', 'Copied {{value0}}', {
+ value0: address
+ })
+ )
},
[port, recordFeatureInteraction]
)
@@ -158,16 +172,28 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
toast.error(result.reason)
return
}
- toast.success(translate("auto.components.sidebar.WorktreeCardPorts.5d1a5d51bb", "Stopped process on {{value0}}", { value0: port.port }))
+ toast.success(
+ translate(
+ 'auto.components.sidebar.WorktreeCardPorts.5d1a5d51bb',
+ 'Stopped process on {{value0}}',
+ { value0: port.port }
+ )
+ )
const refreshResult = await refreshWorkspacePortScanAfterStop({
runtimeTarget,
setWorkspacePortScan,
setWorkspacePortScanRefreshing
})
if (!refreshResult.ok) {
- toast.error(translate("auto.components.sidebar.WorktreeCardPorts.9950fe2d20", "Failed to refresh ports"), {
- description: refreshResult.reason
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.WorktreeCardPorts.9950fe2d20',
+ 'Failed to refresh ports'
+ ),
+ {
+ description: refreshResult.reason
+ }
+ )
}
}
void run()
@@ -206,13 +232,33 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
@@ -231,7 +277,9 @@ export function WorktreeCardPortsDetails({
recordFeatureInteraction('ports')
const ownerPort = ports[0]
if (!ownerPort || !goToWorkspacePortOwner(ownerPort)) {
- toast.error(translate("auto.components.sidebar.WorktreeCardPorts.3e5f66564e", "Workspace unavailable"))
+ toast.error(
+ translate('auto.components.sidebar.WorktreeCardPorts.3e5f66564e', 'Workspace unavailable')
+ )
}
},
[ports, recordFeatureInteraction]
@@ -245,9 +293,17 @@ export function WorktreeCardPortsDetails({
-
{translate("auto.components.sidebar.WorktreeCardPorts.3240f320d7", "Live Ports")}
+
+ {translate('auto.components.sidebar.WorktreeCardPorts.3240f320d7', 'Live Ports')}
+
-
+
{ports.length}
diff --git a/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx b/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
index b3d4a7c108e..665c7294612 100644
--- a/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
@@ -512,11 +512,14 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
/>
- {translate("auto.components.sidebar.WorktreeContextMenu.3350101edb", "Copy Path")}
+ {translate('auto.components.sidebar.WorktreeContextMenu.3350101edb', 'Copy Path')}
+
{worktree.isPinned ? : }
- {worktree.isPinned ? translate("auto.components.sidebar.WorktreeContextMenu.697d0f6e1b", "Unpin") : translate("auto.components.sidebar.WorktreeContextMenu.3baa7d6507", "Pin")}
+ {worktree.isPinned
+ ? translate('auto.components.sidebar.WorktreeContextMenu.697d0f6e1b', 'Unpin')
+ : translate('auto.components.sidebar.WorktreeContextMenu.3baa7d6507', 'Pin')}
{worktree.isUnread ? (
@@ -524,19 +527,32 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
) : (
)}
- {worktree.isUnread ? translate("auto.components.sidebar.WorktreeContextMenu.8dacff1fe0", "Mark Read") : translate("auto.components.sidebar.WorktreeContextMenu.f50603c6b2", "Mark Unread")}
+ {worktree.isUnread
+ ? translate('auto.components.sidebar.WorktreeContextMenu.8dacff1fe0', 'Mark Read')
+ : translate(
+ 'auto.components.sidebar.WorktreeContextMenu.f50603c6b2',
+ 'Mark Unread'
+ )}
{repo ? (
<>
- {translate("auto.components.sidebar.WorktreeContextMenu.503ec0f8e6", "New group from project")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.503ec0f8e6',
+ 'New group from project'
+ )}
+
{projectGroups.length > 0 ? (
- {translate("auto.components.sidebar.WorktreeContextMenu.76865d827f", "Move to group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.76865d827f',
+ 'Move to group'
+ )}
+
{projectGroups.map((group) => (
- {translate("auto.components.sidebar.WorktreeContextMenu.d35dfeae58", "Remove from group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.d35dfeae58',
+ 'Remove from group'
+ )}
+
) : null}
>
) : null}
@@ -563,12 +583,20 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{validParentWorktreeId && (
- {translate("auto.components.sidebar.WorktreeContextMenu.8d9cd19d09", "Open Parent Workspace")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.8d9cd19d09',
+ 'Open Parent Workspace'
+ )}
+
)}
{lineage && (
- {translate("auto.components.sidebar.WorktreeContextMenu.579b1a8e61", "Remove from Parent")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.579b1a8e61',
+ 'Remove from Parent'
+ )}
+
)}
>
@@ -580,7 +608,11 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{hasAnyContextLineage && (
- {translate("auto.components.sidebar.WorktreeContextMenu.579b1a8e61", "Remove from Parent")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.579b1a8e61',
+ 'Remove from Parent'
+ )}
+
)}
>
@@ -588,7 +620,15 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
- {isMultiContext ? translate("auto.components.sidebar.WorktreeContextMenu.56cde9e8e6", "Move Statuses To") : translate("auto.components.sidebar.WorktreeContextMenu.84cdbb7e30", "Move to Status")}
+ {isMultiContext
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.56cde9e8e6',
+ 'Move Statuses To'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeContextMenu.84cdbb7e30',
+ 'Move to Status'
+ )}
@@ -611,7 +651,8 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{!isMultiContext && (
- {translate("auto.components.sidebar.WorktreeContextMenu.439fa94d53", "Update")}
+ {translate('auto.components.sidebar.WorktreeContextMenu.439fa94d53', 'Update')}
+
)}
@@ -626,8 +667,14 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{isMultiContext
- ? translate("auto.components.sidebar.WorktreeContextMenu.7d190f7d2b", "Close all active panels in the selected workspaces to free up memory and CPU.")
- : translate("auto.components.sidebar.WorktreeContextMenu.0918b35e4f", "Close all active panels in this workspace to free up memory and CPU.")}
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.7d190f7d2b',
+ 'Close all active panels in the selected workspaces to free up memory and CPU.'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeContextMenu.0918b35e4f',
+ 'Close all active panels in this workspace to free up memory and CPU.'
+ )}
{/* Why: primary checkout rows remove the project from Orca instead of
@@ -644,25 +691,37 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
}
title={
!isMultiContext && worktree.isMainWorktree && !removesProject
- ? translate("auto.components.sidebar.WorktreeContextMenu.e091caab15", "The project could not be found")
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.e091caab15',
+ 'The project could not be found'
+ )
: undefined
}
>
{deletingContext
- ? translate("auto.components.sidebar.WorktreeContextMenu.b42391d8bf", "Deleting…")
+ ? translate('auto.components.sidebar.WorktreeContextMenu.b42391d8bf', 'Deleting…')
: isMultiContext
? deleteLabel
: removesProject
- ? translate("auto.components.sidebar.WorktreeContextMenu.f5ac91531d", "Remove Project from Orca")
- : translate("auto.components.sidebar.WorktreeContextMenu.f4475537d8", "Delete")}
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.f5ac91531d',
+ 'Remove Project from Orca'
+ )
+ : translate('auto.components.sidebar.WorktreeContextMenu.f4475537d8', 'Delete')}
- {entry.target === "file-manager" ? (
+ {entry.target === 'file-manager' ? (
) : entry.command ? (
@@ -162,7 +185,8 @@ export function WorktreeOpenInSubMenu({
- {translate("auto.components.sidebar.WorktreeOpenInMenu.8009ab69a6", "Open in")}
+ {translate('auto.components.sidebar.WorktreeOpenInMenu.8009ab69a6', 'Open in')}
+
- {translate("auto.components.sidebar.WorktreeOpenInMenu.1417fd8380", "Customize apps...")}
+ {translate('auto.components.sidebar.WorktreeOpenInMenu.1417fd8380', 'Customize apps...')}
+
)
diff --git a/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx b/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
index 2a8a1c4a975..06c2e12b0b6 100644
--- a/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
@@ -189,7 +189,14 @@ export function WorktreeTitleInlineRename({
}
} catch (err) {
if (mountedRef.current) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.sidebar.WorktreeTitleInlineRename.8df295a78d", "Failed to rename workspace."))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.sidebar.WorktreeTitleInlineRename.8df295a78d',
+ 'Failed to rename workspace.'
+ )
+ )
}
} finally {
savingRef.current = false
@@ -237,7 +244,10 @@ export function WorktreeTitleInlineRename({
value={value}
style={{ font: 'inherit' }}
disabled={saving}
- aria-label={translate("auto.components.sidebar.WorktreeTitleInlineRename.bff3bdd00c", "Rename workspace")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorktreeTitleInlineRename.bff3bdd00c',
+ 'Rename workspace'
+ )}
data-worktree-title-rename-input="true"
onChange={(event) => setValue(event.target.value)}
onBlur={() => void commitRename()}
@@ -273,7 +283,11 @@ export function WorktreeTitleInlineRename({
tabIndex={disabled ? undefined : 0}
>
{/* Why: visible text alone misses the unread state for assistive tech. */}
- {showUnreadEmphasis && {translate("auto.components.sidebar.WorktreeTitleInlineRename.2f42ae024f", "Unread:")} }
+ {showUnreadEmphasis && (
+
+ {translate('auto.components.sidebar.WorktreeTitleInlineRename.2f42ae024f', 'Unread:')}
+
+ )}
{displayName}
)
diff --git a/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx b/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx
index 94e9f24cf1d..e794250be77 100644
--- a/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx
@@ -62,7 +62,12 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
!open && closeModal()}>
- {translate("auto.components.sidebar.WorktreeVisibilityDialog.83a5ba8dd1", "Non-Orca worktrees")}
+
+ {translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.83a5ba8dd1',
+ 'Non-Orca worktrees'
+ )}
+
{repo.displayName}
@@ -72,12 +77,28 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
- {showOther ? translate("auto.components.sidebar.WorktreeVisibilityDialog.3e045d4cb8", "Shown in sidebar") : translate("auto.components.sidebar.WorktreeVisibilityDialog.5d02a5647f", "Hidden from sidebar")}
+ {showOther
+ ? translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.3e045d4cb8',
+ 'Shown in sidebar'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.5d02a5647f',
+ 'Hidden from sidebar'
+ )}
{showOther
- ? translate("auto.components.sidebar.WorktreeVisibilityDialog.8372e4bbd9", "{{value0}} currently shown", { value0: shownWorktreeLabel })
- : translate("auto.components.sidebar.WorktreeVisibilityDialog.25ddf19920", "{{value0}} available to import", { value0: hiddenWorktreeLabel })}
+ ? translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.8372e4bbd9',
+ '{{value0}} currently shown',
+ { value0: shownWorktreeLabel }
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.25ddf19920',
+ '{{value0}} available to import',
+ { value0: hiddenWorktreeLabel }
+ )}
- {showOther ? translate("auto.components.sidebar.WorktreeVisibilityDialog.759371df43", "Hide") : translate("auto.components.sidebar.WorktreeVisibilityDialog.f1f71b9f02", "Import")}
+ {showOther
+ ? translate('auto.components.sidebar.WorktreeVisibilityDialog.759371df43', 'Hide')
+ : translate('auto.components.sidebar.WorktreeVisibilityDialog.f1f71b9f02', 'Import')}
diff --git a/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts b/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
index 005b29940df..259b6b8f3b7 100644
--- a/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
+++ b/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
@@ -30,30 +30,54 @@ export function getAddRepoLocalStartActions({
const primaryAction = {
kind: 'browse' as const,
icon: FolderOpen,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.2281fdc8c7", "Browse folder"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.fb4fc5380e", "Local project, Git repo, or folder with many repos"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.2281fdc8c7',
+ 'Browse folder'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.fb4fc5380e',
+ 'Local project, Git repo, or folder with many repos'
+ ),
onClick: onBrowse
}
const remote = {
kind: 'remote' as const,
icon: Monitor,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.3d162cc76f", "Remote project"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.a6c20dca96", "Open a project from an SSH target"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.3d162cc76f',
+ 'Remote project'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.a6c20dca96',
+ 'Open a project from an SSH target'
+ ),
onClick: onOpenRemoteStep
}
const clone = {
kind: 'clone' as const,
icon: Globe,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.7edb8ebe24", "Clone from URL"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.5f9ffac036", "Clone a remote Git repository"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.7edb8ebe24',
+ 'Clone from URL'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.5f9ffac036',
+ 'Clone a remote Git repository'
+ ),
onClick: onOpenCloneStep
}
const create = {
kind: 'create' as const,
icon: Plus,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.c709860596", "Create new project"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.d72789705e", "Start from an empty folder"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.c709860596',
+ 'Create new project'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.d72789705e',
+ 'Start from an empty folder'
+ ),
onClick: onOpenCreateStep
}
diff --git a/src/renderer/src/components/sidebar/delete-worktree-flow.ts b/src/renderer/src/components/sidebar/delete-worktree-flow.ts
index 01426498eed..2195f48bd65 100644
--- a/src/renderer/src/components/sidebar/delete-worktree-flow.ts
+++ b/src/renderer/src/components/sidebar/delete-worktree-flow.ts
@@ -125,37 +125,58 @@ export function runWorktreeDeleteWithToast(
description: toastCopy.description,
duration: 10000,
cancel: {
- label: translate("auto.components.sidebar.delete.worktree.flow.7488ed8711", "View"),
+ label: translate('auto.components.sidebar.delete.worktree.flow.7488ed8711', 'View'),
onClick: () => viewWorktreeDiff(worktreeId)
},
action: canForceDelete
? {
- label: translate("auto.components.sidebar.delete.worktree.flow.2b20ce87b3", "Force Delete"),
+ label: translate(
+ 'auto.components.sidebar.delete.worktree.flow.2b20ce87b3',
+ 'Force Delete'
+ ),
onClick: () => {
useAppStore
.getState()
.removeWorktree(worktreeId, true)
.then((forceResult) => {
if (!forceResult.ok) {
- toast.error(translate("auto.components.sidebar.delete.worktree.flow.4f3876c0f5", "Force delete failed"), {
- description: forceResult.error,
- action: {
- label: translate("auto.components.sidebar.delete.worktree.flow.7488ed8711", "View"),
- onClick: () => viewWorktreeDiff(worktreeId)
+ toast.error(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.4f3876c0f5',
+ 'Force delete failed'
+ ),
+ {
+ description: forceResult.error,
+ action: {
+ label: translate(
+ 'auto.components.sidebar.delete.worktree.flow.7488ed8711',
+ 'View'
+ ),
+ onClick: () => viewWorktreeDiff(worktreeId)
+ }
}
- })
+ )
return
}
options.onForceDeleted?.(worktreeId)
})
.catch((err: unknown) => {
- toast.error(translate("auto.components.sidebar.delete.worktree.flow.ae57cbf6e4", "Failed to delete workspace"), {
- description: err instanceof Error ? err.message : String(err),
- action: {
- label: translate("auto.components.sidebar.delete.worktree.flow.7488ed8711", "View"),
- onClick: () => viewWorktreeDiff(worktreeId)
+ toast.error(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.ae57cbf6e4',
+ 'Failed to delete workspace'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err),
+ action: {
+ label: translate(
+ 'auto.components.sidebar.delete.worktree.flow.7488ed8711',
+ 'View'
+ ),
+ onClick: () => viewWorktreeDiff(worktreeId)
+ }
}
- })
+ )
})
}
}
@@ -164,9 +185,15 @@ export function runWorktreeDeleteWithToast(
return false
})
.catch((err: unknown) => {
- toast.error(translate("auto.components.sidebar.delete.worktree.flow.ae57cbf6e4", "Failed to delete workspace"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.ae57cbf6e4',
+ 'Failed to delete workspace'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
return false
})
}
@@ -227,9 +254,18 @@ export function runWorktreeBatchDelete(
.filter((worktree): worktree is Worktree => worktree != null && !worktree.isMainWorktree)
if (targets.length === 0) {
- toast.info(translate("auto.components.sidebar.delete.worktree.flow.7243145cd6", "No deletable workspaces selected"), {
- description: translate("auto.components.sidebar.delete.worktree.flow.b81b4e40ca", "Refresh Space and try again if the workspace list looks stale.")
- })
+ toast.info(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.7243145cd6',
+ 'No deletable workspaces selected'
+ ),
+ {
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.flow.b81b4e40ca',
+ 'Refresh Space and try again if the workspace list looks stale.'
+ )
+ }
+ )
return false
}
diff --git a/src/renderer/src/components/sidebar/delete-worktree-toast.ts b/src/renderer/src/components/sidebar/delete-worktree-toast.ts
index 4090c63c13e..9ae69262ac5 100644
--- a/src/renderer/src/components/sidebar/delete-worktree-toast.ts
+++ b/src/renderer/src/components/sidebar/delete-worktree-toast.ts
@@ -13,9 +13,15 @@ export function getDeleteWorktreeToastCopy(
if (canForceDelete) {
if (error.includes('Worktree is no longer registered with Git but its directory remains.')) {
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
- description:
- translate("auto.components.sidebar.delete.worktree.toast.0899ebdb28", "Git already forgot this workspace, but its directory is still on disk. Use Force Delete to remove the orphaned directory."),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.toast.0899ebdb28',
+ 'Git already forgot this workspace, but its directory is still on disk. Use Force Delete to remove the orphaned directory.'
+ ),
isDestructive: false
}
}
@@ -23,14 +29,28 @@ export function getDeleteWorktreeToastCopy(
error.includes('Worktree is no longer registered with Git and its directory is already gone.')
) {
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
- description: translate("auto.components.sidebar.delete.worktree.toast.905fc8efac", "Git already removed this workspace. Use Force Delete to clear it from Orca."),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.toast.905fc8efac',
+ 'Git already removed this workspace. Use Force Delete to clear it from Orca.'
+ ),
isDestructive: false
}
}
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
- description: translate("auto.components.sidebar.delete.worktree.toast.ead7b8ee15", "It has changed files. Use Force Delete to delete it anyway."),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.toast.ead7b8ee15',
+ 'It has changed files. Use Force Delete to delete it anyway.'
+ ),
// Why: git commonly refuses the first delete when the worktree still has
// modified or untracked files. Showing raw stderr in a destructive toast
// made a normal cleanup step look like an Orca bug, so this common case
@@ -40,7 +60,11 @@ export function getDeleteWorktreeToastCopy(
}
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
description: error,
isDestructive: true
}
diff --git a/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts b/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts
index 1e8c8be33ad..e11def20b50 100644
--- a/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts
+++ b/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts
@@ -179,7 +179,14 @@ export function resolveSegmentStep(
}
// Stop resolution: prefix-matching to a similarly-named folder here would
// silently bypass a real file the user pointed at.
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7", "{{value0}} isn't a directory in {{value1}}", { value0: segment, value1: basePath }) }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7',
+ "{{value0}} isn't a directory in {{value1}}",
+ { value0: segment, value1: basePath }
+ )
+ }
}
// Fall back to case-insensitive matching so segment resolution agrees with
// the case-insensitive filter input. Without this, typing `documents/`
@@ -192,7 +199,14 @@ export function resolveSegmentStep(
if (ciExact.isDirectory) {
return { type: 'descend', name: ciExact.name }
}
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7", "{{value0}} isn't a directory in {{value1}}", { value0: segment, value1: basePath }) }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7',
+ "{{value0}} isn't a directory in {{value1}}",
+ { value0: segment, value1: basePath }
+ )
+ }
}
const dirMatches = baseEntries.filter(
(e) => e.isDirectory && e.name.toLowerCase().startsWith(segLower)
@@ -201,7 +215,21 @@ export function resolveSegmentStep(
return { type: 'descend', name: dirMatches[0].name }
}
if (dirMatches.length > 1) {
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.be266af66c", "{{value0}} matches multiple directories in {{value1}}", { value0: segment, value1: basePath }) }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.be266af66c',
+ '{{value0}} matches multiple directories in {{value1}}',
+ { value0: segment, value1: basePath }
+ )
+ }
+ }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7',
+ "{{value0}} isn't a directory in {{value1}}",
+ { value0: segment, value1: basePath }
+ )
}
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7", "{{value0}} isn't a directory in {{value1}}", { value0: segment, value1: basePath }) }
}
diff --git a/src/renderer/src/components/sidebar/repo-header-create-state.ts b/src/renderer/src/components/sidebar/repo-header-create-state.ts
index 81c66217919..6b369f1e287 100644
--- a/src/renderer/src/components/sidebar/repo-header-create-state.ts
+++ b/src/renderer/src/components/sidebar/repo-header-create-state.ts
@@ -19,8 +19,16 @@ export function getRepoHeaderCreateState(input: {
if (!isGitRepoKind(input.repo)) {
return {
disabled: false,
- tooltip: translate("auto.components.sidebar.repo.header.create.state.62e71f2d5d", "Create workspace for {{value0}}", { value0: input.label }),
- ariaLabel: translate("auto.components.sidebar.repo.header.create.state.62e71f2d5d", "Create workspace for {{value0}}", { value0: input.label }),
+ tooltip: translate(
+ 'auto.components.sidebar.repo.header.create.state.62e71f2d5d',
+ 'Create workspace for {{value0}}',
+ { value0: input.label }
+ ),
+ ariaLabel: translate(
+ 'auto.components.sidebar.repo.header.create.state.62e71f2d5d',
+ 'Create workspace for {{value0}}',
+ { value0: input.label }
+ ),
requiresSshReconnect: false
}
}
@@ -32,16 +40,31 @@ export function getRepoHeaderCreateState(input: {
if (sshGate.selectedRepoRequiresConnection) {
return {
disabled: true,
- tooltip: translate("auto.components.sidebar.repo.header.create.state.6d022563a8", "Reconnect SSH target before creating workspaces"),
- ariaLabel: translate("auto.components.sidebar.repo.header.create.state.3a70acd808", "Reconnect SSH target before creating workspaces for {{value0}}", { value0: input.label }),
+ tooltip: translate(
+ 'auto.components.sidebar.repo.header.create.state.6d022563a8',
+ 'Reconnect SSH target before creating workspaces'
+ ),
+ ariaLabel: translate(
+ 'auto.components.sidebar.repo.header.create.state.3a70acd808',
+ 'Reconnect SSH target before creating workspaces for {{value0}}',
+ { value0: input.label }
+ ),
requiresSshReconnect: true
}
}
return {
disabled: false,
- tooltip: translate("auto.components.sidebar.repo.header.create.state.992cfbc44b", "Create new worktree for {{value0}}", { value0: input.label }),
- ariaLabel: translate("auto.components.sidebar.repo.header.create.state.992cfbc44b", "Create new worktree for {{value0}}", { value0: input.label }),
+ tooltip: translate(
+ 'auto.components.sidebar.repo.header.create.state.992cfbc44b',
+ 'Create new worktree for {{value0}}',
+ { value0: input.label }
+ ),
+ ariaLabel: translate(
+ 'auto.components.sidebar.repo.header.create.state.992cfbc44b',
+ 'Create new worktree for {{value0}}',
+ { value0: input.label }
+ ),
requiresSshReconnect: false
}
}
diff --git a/src/renderer/src/components/sidebar/sidebar-project-drop.ts b/src/renderer/src/components/sidebar/sidebar-project-drop.ts
index a1715d5edce..42c29ded37f 100644
--- a/src/renderer/src/components/sidebar/sidebar-project-drop.ts
+++ b/src/renderer/src/components/sidebar/sidebar-project-drop.ts
@@ -41,22 +41,40 @@ export function getSidebarProjectDropAffordance(args: {
return {
visible: true,
tone: 'busy',
- label: translate("auto.components.sidebar.sidebar.project.drop.18d3cf40e9", "Checking folder"),
- description: translate("auto.components.sidebar.sidebar.project.drop.d0f8943f8b", "Preparing the project add flow")
+ label: translate(
+ 'auto.components.sidebar.sidebar.project.drop.18d3cf40e9',
+ 'Checking folder'
+ ),
+ description: translate(
+ 'auto.components.sidebar.sidebar.project.drop.d0f8943f8b',
+ 'Preparing the project add flow'
+ )
}
}
if (args.remoteRuntimeActive) {
return {
visible: true,
tone: 'blocked',
- label: translate("auto.components.sidebar.sidebar.project.drop.e344666fb8", "Server runtime active"),
- description: translate("auto.components.sidebar.sidebar.project.drop.740e8d0d46", "Use Add Project for server paths")
+ label: translate(
+ 'auto.components.sidebar.sidebar.project.drop.e344666fb8',
+ 'Server runtime active'
+ ),
+ description: translate(
+ 'auto.components.sidebar.sidebar.project.drop.740e8d0d46',
+ 'Use Add Project for server paths'
+ )
}
}
return {
visible: true,
tone: 'ready',
- label: translate("auto.components.sidebar.sidebar.project.drop.ffc769ca29", "Drop folder to add project"),
- description: translate("auto.components.sidebar.sidebar.project.drop.669e12dd97", "Local folders and Git repositories")
+ label: translate(
+ 'auto.components.sidebar.sidebar.project.drop.ffc769ca29',
+ 'Drop folder to add project'
+ ),
+ description: translate(
+ 'auto.components.sidebar.sidebar.project.drop.669e12dd97',
+ 'Local folders and Git repositories'
+ )
}
}
diff --git a/src/renderer/src/components/sidebar/sleep-worktree-flow.ts b/src/renderer/src/components/sidebar/sleep-worktree-flow.ts
index adf181eee34..c6cee3f6288 100644
--- a/src/renderer/src/components/sidebar/sleep-worktree-flow.ts
+++ b/src/renderer/src/components/sidebar/sleep-worktree-flow.ts
@@ -144,7 +144,15 @@ export async function runSleepWorktrees(worktreeIds: readonly string[]): Promise
// otherwise continue — the active-worktree reset already happened so we
// don't leave the UI in a stale state.
toast.error(
- worktreeIds.length === 1 ? translate("auto.components.sidebar.sleep.worktree.flow.8bc3fc0671", "Failed to sleep workspace") : translate("auto.components.sidebar.sleep.worktree.flow.c460fecc4a", "Failed to sleep some workspaces"),
+ worktreeIds.length === 1
+ ? translate(
+ 'auto.components.sidebar.sleep.worktree.flow.8bc3fc0671',
+ 'Failed to sleep workspace'
+ )
+ : translate(
+ 'auto.components.sidebar.sleep.worktree.flow.c460fecc4a',
+ 'Failed to sleep some workspaces'
+ ),
{
description: errors.join('\n')
}
diff --git a/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts b/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts
index ba1dc380eea..44ff4b94b55 100644
--- a/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts
+++ b/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts
@@ -82,7 +82,12 @@ export function useAddRepoCloneFlow({
if (activeRuntimeEnvironmentId?.trim()) {
// Why: the native folder picker returns a client-local path. Runtime
// clone destinations must be typed as server paths.
- toast.error(translate("auto.components.sidebar.useAddRepoCloneFlow.0dc4d1b657", "Enter a server path for the clone destination."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useAddRepoCloneFlow.0dc4d1b657',
+ 'Enter a server path for the clone destination.'
+ )
+ )
return
}
const gen = cloneGenRef.current
@@ -124,7 +129,10 @@ export function useAddRepoCloneFlow({
if (gen !== cloneGenRef.current) {
return
}
- toast.success(translate("auto.components.sidebar.useAddRepoCloneFlow.4d0013cc93", "Repository cloned"), { description: repo.displayName })
+ toast.success(
+ translate('auto.components.sidebar.useAddRepoCloneFlow.4d0013cc93', 'Repository cloned'),
+ { description: repo.displayName }
+ )
// Why: eagerly upsert so step 2 finds the repo before the IPC event.
const state = useAppStore.getState()
const existingIdx = state.repos.findIndex((r) => r.id === repo.id)
diff --git a/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts b/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
index c9ea876afa7..6f3c8eeeb48 100644
--- a/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
+++ b/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
@@ -69,7 +69,12 @@ export function useAddRepoLocalFolderFlow({
const handleAddLocalPath = useCallback(
async (path: string, source: AddRepoExistingWorkspaceSource): Promise => {
if (activeRuntimeEnvironmentId?.trim()) {
- toast.error(translate("auto.components.sidebar.useAddRepoLocalFolderFlow.7ab10e4974", "Use a server path to add projects from a remote runtime."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useAddRepoLocalFolderFlow.7ab10e4974',
+ 'Use a server path to add projects from a remote runtime.'
+ )
+ )
closeModal()
return
}
diff --git a/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts b/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
index c2c03a37119..b71012d50bb 100644
--- a/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
+++ b/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
@@ -151,9 +151,15 @@ export function useAddRepoNestedImportFlow({
if (!firstRepoId) {
const firstFailure = result.projects.find((entry) => entry.status === 'failed')?.error
if (gen === nestedImportGenRef.current) {
- toast.error(translate("auto.components.sidebar.useAddRepoNestedImportFlow.1b33c5f090", "No repositories imported"), {
- description: firstFailure ?? undefined
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useAddRepoNestedImportFlow.1b33c5f090',
+ 'No repositories imported'
+ ),
+ {
+ description: firstFailure ?? undefined
+ }
+ )
}
return
}
@@ -166,9 +172,19 @@ export function useAddRepoNestedImportFlow({
return
}
if (result.failedCount > 0) {
- toast.warning(translate("auto.components.sidebar.useAddRepoNestedImportFlow.cbfbc7a797", "Some repositories could not be imported"), {
- description: translate("auto.components.sidebar.useAddRepoNestedImportFlow.680cac2c82", "{{value0}} failed", { value0: result.failedCount })
- })
+ toast.warning(
+ translate(
+ 'auto.components.sidebar.useAddRepoNestedImportFlow.cbfbc7a797',
+ 'Some repositories could not be imported'
+ ),
+ {
+ description: translate(
+ 'auto.components.sidebar.useAddRepoNestedImportFlow.680cac2c82',
+ '{{value0}} failed',
+ { value0: result.failedCount }
+ )
+ }
+ )
}
const repo = useAppStore.getState().repos.find((entry) => entry.id === firstRepoId)
if (repo) {
diff --git a/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts b/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts
index 0357cefad7f..2f0ba7539b2 100644
--- a/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts
+++ b/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts
@@ -53,13 +53,27 @@ export function useSidebarProjectDrop(): {
return
}
if (pathResolution.status === 'multiple') {
- toast.warning(translate("auto.components.sidebar.useSidebarProjectDrop.c0315153d1", "Drop one folder at a time."))
+ toast.warning(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.c0315153d1',
+ 'Drop one folder at a time.'
+ )
+ )
return
}
if (remoteRuntimeActive) {
- toast.error(translate("auto.components.sidebar.useSidebarProjectDrop.849ef13dc0", "Local folder drops are unavailable for server runtimes."), {
- description: translate("auto.components.sidebar.useSidebarProjectDrop.5ccb56c7be", "Use Add Project to enter a server path.")
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.849ef13dc0',
+ 'Local folder drops are unavailable for server runtimes.'
+ ),
+ {
+ description: translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.5ccb56c7be',
+ 'Use Add Project to enter a server path.'
+ )
+ }
+ )
return
}
@@ -71,15 +85,26 @@ export function useSidebarProjectDrop(): {
return
}
if (!stat.isDirectory) {
- toast.error(translate("auto.components.sidebar.useSidebarProjectDrop.451a4638db", "Drop a folder to add it as a project."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.451a4638db',
+ 'Drop a folder to add it as a project.'
+ )
+ )
return
}
openModal('add-repo', { droppedLocalPath: pathResolution.path })
} catch (error) {
if (mountedRef.current) {
- toast.error(translate("auto.components.sidebar.useSidebarProjectDrop.f34a286c0d", "Could not add dropped folder."), {
- description: error instanceof Error ? error.message : String(error)
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.f34a286c0d',
+ 'Could not add dropped folder.'
+ ),
+ {
+ description: error instanceof Error ? error.message : String(error)
+ }
+ )
}
} finally {
if (mountedRef.current) {
diff --git a/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx b/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx
index 3e5fbcb5281..a7cb8c2fdac 100644
--- a/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx
+++ b/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx
@@ -178,7 +178,17 @@ export function CompactAgentSummaryButton({
: 'border border-worktree-sidebar-border/70 bg-worktree-sidebar-accent/35'
)}
aria-label={
- expanded ? translate("auto.components.sidebar.worktree.card.compact.agents.0c1debfe84", "Collapse {{value0}}", { value0: subjectLabel }) : translate("auto.components.sidebar.worktree.card.compact.agents.289a1d2ca7", "Expand {{value0}}. {{value1}}", { value0: summary, value1: agentIdentitySummary })
+ expanded
+ ? translate(
+ 'auto.components.sidebar.worktree.card.compact.agents.0c1debfe84',
+ 'Collapse {{value0}}',
+ { value0: subjectLabel }
+ )
+ : translate(
+ 'auto.components.sidebar.worktree.card.compact.agents.289a1d2ca7',
+ 'Expand {{value0}}. {{value1}}',
+ { value0: summary, value1: agentIdentitySummary }
+ )
}
aria-expanded={expanded}
onClick={handleToggle}
@@ -298,7 +308,15 @@ export const CompactAgentRow = React.memo(function CompactAgentRow({
= {
done: {
- label: translate("auto.components.sidebar.worktree.list.groups.5076efc3d2", "Done"),
+ label: translate('auto.components.sidebar.worktree.list.groups.5076efc3d2', 'Done'),
icon: ConductorDoneIcon,
tone: 'text-[#c7a594]'
},
'in-review': {
- label: translate("auto.components.sidebar.worktree.list.groups.6798dc7c94", "In review"),
+ label: translate('auto.components.sidebar.worktree.list.groups.6798dc7c94', 'In review'),
icon: ConductorReviewIcon,
tone: 'text-[#16a34a]'
},
'in-progress': {
- label: translate("auto.components.sidebar.worktree.list.groups.7c2f009786", "In progress"),
+ label: translate('auto.components.sidebar.worktree.list.groups.7c2f009786', 'In progress'),
icon: ConductorProgressIcon,
tone: 'text-[#d4a300]'
},
closed: {
- label: translate("auto.components.sidebar.worktree.list.groups.682ed5d551", "Closed"),
+ label: translate('auto.components.sidebar.worktree.list.groups.682ed5d551', 'Closed'),
icon: CircleX,
tone: 'text-zinc-600 dark:text-zinc-300'
}
@@ -146,7 +146,7 @@ export function getProjectGroupHeaderKey(groupId: string | null): string {
export const PINNED_GROUP_KEY = 'pinned'
export const PINNED_GROUP_META = {
- label: translate("auto.components.sidebar.worktree.list.groups.4aeefc5996", "Pinned"),
+ label: translate('auto.components.sidebar.worktree.list.groups.4aeefc5996', 'Pinned'),
tone: 'text-foreground',
icon: Pin
} as const
@@ -154,7 +154,7 @@ export const PINNED_GROUP_META = {
export const ALL_GROUP_KEY = 'all'
export const ALL_GROUP_META = {
- label: translate("auto.components.sidebar.worktree.list.groups.0ed04075b8", "All"),
+ label: translate('auto.components.sidebar.worktree.list.groups.0ed04075b8', 'All'),
tone: 'text-foreground',
icon: List
} as const
diff --git a/src/renderer/src/components/skills/SkillsPage.tsx b/src/renderer/src/components/skills/SkillsPage.tsx
index 0be4ba4b569..302e16f4886 100644
--- a/src/renderer/src/components/skills/SkillsPage.tsx
+++ b/src/renderer/src/components/skills/SkillsPage.tsx
@@ -59,7 +59,9 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
const revealSkill = async (): Promise => {
const result = await window.api.shell.openInFileManager(skill.skillFilePath)
if (!result.ok) {
- toast.error(translate("auto.components.skills.SkillsPage.995fde8337", "Could not reveal skill file"))
+ toast.error(
+ translate('auto.components.skills.SkillsPage.995fde8337', 'Could not reveal skill file')
+ )
}
}
@@ -77,7 +79,9 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
variant={skill.installed ? 'secondary' : 'outline'}
className="h-5 text-[10px]"
>
- {skill.installed ? translate("auto.components.skills.SkillsPage.0c74e7ff34", "Local") : translate("auto.components.skills.SkillsPage.35b9a724a0", "Available")}
+ {skill.installed
+ ? translate('auto.components.skills.SkillsPage.0c74e7ff34', 'Local')
+ : translate('auto.components.skills.SkillsPage.35b9a724a0', 'Available')}
{sourceLabels[skill.sourceKind]}
@@ -88,7 +92,9 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
{skill.description}
) : (
- {translate("auto.components.skills.SkillsPage.9963dff6d3", "No description found.")}
+
+ {translate('auto.components.skills.SkillsPage.9963dff6d3', 'No description found.')}
+
)}
@@ -106,7 +112,8 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
- {translate("auto.components.skills.SkillsPage.dc4c3328ee", "Reveal file")}
+ {translate('auto.components.skills.SkillsPage.dc4c3328ee', 'Reveal file')}
+
@@ -154,18 +161,32 @@ function EmptyState({
)}
- {loading ? translate("auto.components.skills.SkillsPage.cd7893fbc1", "Scanning skills") : hasSkills ? translate("auto.components.skills.SkillsPage.6a62a0168c", "No matches") : translate("auto.components.skills.SkillsPage.4acd6d68ec", "No local skills found")}
+ {loading
+ ? translate('auto.components.skills.SkillsPage.cd7893fbc1', 'Scanning skills')
+ : hasSkills
+ ? translate('auto.components.skills.SkillsPage.6a62a0168c', 'No matches')
+ : translate(
+ 'auto.components.skills.SkillsPage.4acd6d68ec',
+ 'No local skills found'
+ )}
{hasSkills
- ? translate("auto.components.skills.SkillsPage.08a321a984", "Adjust the search or filters.")
- : translate("auto.components.skills.SkillsPage.ab5b777350", "Checked local home, repository, bundled, and plugin skill folders.")}
+ ? translate(
+ 'auto.components.skills.SkillsPage.08a321a984',
+ 'Adjust the search or filters.'
+ )
+ : translate(
+ 'auto.components.skills.SkillsPage.ab5b777350',
+ 'Checked local home, repository, bundled, and plugin skill folders.'
+ )}
{!loading ? (
- {translate("auto.components.skills.SkillsPage.cb142070b4", "Refresh")}
+ {translate('auto.components.skills.SkillsPage.cb142070b4', 'Refresh')}
+
) : null}
@@ -193,7 +214,9 @@ export default function SkillsPage(): React.JSX.Element {
} catch (error) {
console.error('Failed to discover skills:', error)
if (mountedRef.current) {
- toast.error(translate("auto.components.skills.SkillsPage.ea72d6185b", "Could not scan local skills"))
+ toast.error(
+ translate('auto.components.skills.SkillsPage.ea72d6185b', 'Could not scan local skills')
+ )
}
} finally {
if (mountedRef.current) {
@@ -259,16 +282,23 @@ export default function SkillsPage(): React.JSX.Element {
- {translate("auto.components.skills.SkillsPage.7e828fb2c6", "Back")}
+ {translate('auto.components.skills.SkillsPage.7e828fb2c6', 'Back')}
+
-
{translate("auto.components.skills.SkillsPage.f43ad6edf3", "Skills")}
- {translate("auto.components.skills.SkillsPage.b088e0785d", "Beta")}
+
+ {translate('auto.components.skills.SkillsPage.f43ad6edf3', 'Skills')}
+
+
+ {translate('auto.components.skills.SkillsPage.b088e0785d', 'Beta')}
+
- {pluralize(skills.length, 'skill')} {translate("auto.components.skills.SkillsPage.e46e162e2e", "from")}{pluralize(activeSourceCount, 'source')}
+ {pluralize(skills.length, 'skill')}{' '}
+ {translate('auto.components.skills.SkillsPage.e46e162e2e', 'from')}
+ {pluralize(activeSourceCount, 'source')}
@@ -281,7 +311,10 @@ export default function SkillsPage(): React.JSX.Element {
setFilters((next) => ({ ...next, query: event.target.value }))}
- placeholder={translate("auto.components.skills.SkillsPage.a68dee6a32", "Search skills")}
+ placeholder={translate(
+ 'auto.components.skills.SkillsPage.a68dee6a32',
+ 'Search skills'
+ )}
className="h-8 pl-8 text-sm"
/>
@@ -299,10 +332,18 @@ export default function SkillsPage(): React.JSX.Element {
- {translate("auto.components.skills.SkillsPage.39b6998ddb", "All providers")}
- {translate("auto.components.skills.SkillsPage.426be2aac6", "Codex")}
- {translate("auto.components.skills.SkillsPage.fb6bf60b52", "Claude")}
- {translate("auto.components.skills.SkillsPage.38e0951c3a", "Agent Skills")}
+
+ {translate('auto.components.skills.SkillsPage.39b6998ddb', 'All providers')}
+
+
+ {translate('auto.components.skills.SkillsPage.426be2aac6', 'Codex')}
+
+
+ {translate('auto.components.skills.SkillsPage.fb6bf60b52', 'Claude')}
+
+
+ {translate('auto.components.skills.SkillsPage.38e0951c3a', 'Agent Skills')}
+
- {translate("auto.components.skills.SkillsPage.0bc1379f4c", "All sources")}
- {translate("auto.components.skills.SkillsPage.571c5818c1", "Home")}
- {translate("auto.components.skills.SkillsPage.aa59462502", "Repository")}
- {translate("auto.components.skills.SkillsPage.4d177feabd", "Bundled")}
- {translate("auto.components.skills.SkillsPage.984405683f", "Plugin")}
+
+ {translate('auto.components.skills.SkillsPage.0bc1379f4c', 'All sources')}
+
+
+ {translate('auto.components.skills.SkillsPage.571c5818c1', 'Home')}
+
+
+ {translate('auto.components.skills.SkillsPage.aa59462502', 'Repository')}
+
+
+ {translate('auto.components.skills.SkillsPage.4d177feabd', 'Bundled')}
+
+
+ {translate('auto.components.skills.SkillsPage.984405683f', 'Plugin')}
+
- {translate("auto.components.skills.SkillsPage.cb142070b4", "Refresh")}
+ {translate('auto.components.skills.SkillsPage.cb142070b4', 'Refresh')}
+
diff --git a/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx b/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx
index 2bc458676a5..785c33f0faa 100644
--- a/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx
+++ b/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx
@@ -36,9 +36,15 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
return (
-
{translate("auto.components.stats.ClaudeUsageDailyChart.c9f7cd30e9", "Daily usage")}
+
+ {translate('auto.components.stats.ClaudeUsageDailyChart.c9f7cd30e9', 'Daily usage')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.059945f71d", "Input, output, cache read, and cache write totals by day.")}
+ {translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.059945f71d',
+ 'Input, output, cache read, and cache write totals by day.'
+ )}
+
{daily.slice(-10).map((entry) => {
@@ -46,23 +52,34 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
const segments = [
{
key: 'cache-write',
- label: translate("auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb", "Cache write"),
+ label: translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb',
+ 'Cache write'
+ ),
value: entry.cacheWriteTokens,
className: 'bg-fuchsia-500/70'
},
{
key: 'cache-read',
- label: translate("auto.components.stats.ClaudeUsageDailyChart.61c58f8976", "Cache read"),
+ label: translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.61c58f8976',
+ 'Cache read'
+ ),
value: entry.cacheReadTokens,
className: 'bg-amber-500/70'
},
{
key: 'output',
- label: translate("auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e", "Output"),
+ label: translate('auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e', 'Output'),
value: entry.outputTokens,
className: 'bg-emerald-500/80'
},
- { key: 'input', label: translate("auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b", "Input"), value: entry.inputTokens, className: 'bg-sky-500/80' }
+ {
+ key: 'input',
+ label: translate('auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b', 'Input'),
+ value: entry.inputTokens,
+ className: 'bg-sky-500/80'
+ }
]
return (
@@ -86,7 +103,12 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
{entry.day}
- {segment.label}: {segment.value.toLocaleString()} {translate("auto.components.stats.ClaudeUsageDailyChart.a7902d3c1d", "tokens")}
+ {segment.label}: {segment.value.toLocaleString()}{' '}
+ {translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.a7902d3c1d',
+ 'tokens'
+ )}
+
@@ -106,16 +128,20 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
- {translate("auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b", "Input")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b', 'Input')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e", "Output")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e', 'Output')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.61c58f8976", "Cache read")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.61c58f8976', 'Cache read')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb", "Cache write")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb', 'Cache write')}
+
)
diff --git a/src/renderer/src/components/stats/CodexUsageDailyChart.tsx b/src/renderer/src/components/stats/CodexUsageDailyChart.tsx
index 3d6fbcda4b4..3ac8b94dadb 100644
--- a/src/renderer/src/components/stats/CodexUsageDailyChart.tsx
+++ b/src/renderer/src/components/stats/CodexUsageDailyChart.tsx
@@ -32,34 +32,46 @@ export function CodexUsageDailyChart({ daily }: CodexUsageDailyChartProps): Reac
return (
-
{translate("auto.components.stats.CodexUsageDailyChart.609aa96e8b", "Daily usage")}
+
+ {translate('auto.components.stats.CodexUsageDailyChart.609aa96e8b', 'Daily usage')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.c756cda6a8", "Input, cached input, output, and reasoning totals by day.")}
+ {translate(
+ 'auto.components.stats.CodexUsageDailyChart.c756cda6a8',
+ 'Input, cached input, output, and reasoning totals by day.'
+ )}
+
{daily.slice(-10).map((entry) => {
const segments = [
{
key: 'input',
- label: translate("auto.components.stats.CodexUsageDailyChart.99a91d3143", "Input"),
+ label: translate('auto.components.stats.CodexUsageDailyChart.99a91d3143', 'Input'),
value: entry.inputTokens,
className: 'bg-sky-500/80'
},
{
key: 'output',
- label: translate("auto.components.stats.CodexUsageDailyChart.7b596a88b2", "Output"),
+ label: translate('auto.components.stats.CodexUsageDailyChart.7b596a88b2', 'Output'),
value: entry.outputTokens,
className: 'bg-emerald-500/80'
},
{
key: 'cached-input',
- label: translate("auto.components.stats.CodexUsageDailyChart.c646e1783c", "Cached input"),
+ label: translate(
+ 'auto.components.stats.CodexUsageDailyChart.c646e1783c',
+ 'Cached input'
+ ),
value: entry.cachedInputTokens,
className: 'bg-amber-500/70'
},
{
key: 'reasoning',
- label: translate("auto.components.stats.CodexUsageDailyChart.1e6f62d7e3", "Reasoning"),
+ label: translate(
+ 'auto.components.stats.CodexUsageDailyChart.1e6f62d7e3',
+ 'Reasoning'
+ ),
value: entry.reasoningOutputTokens,
className: 'bg-fuchsia-500/70'
}
@@ -86,7 +98,12 @@ export function CodexUsageDailyChart({ daily }: CodexUsageDailyChartProps): Reac
{entry.day}
- {segment.label}: {segment.value.toLocaleString()} {translate("auto.components.stats.CodexUsageDailyChart.e4bdcf0071", "tokens")}
+ {segment.label}: {segment.value.toLocaleString()}{' '}
+ {translate(
+ 'auto.components.stats.CodexUsageDailyChart.e4bdcf0071',
+ 'tokens'
+ )}
+
@@ -106,16 +123,20 @@ export function CodexUsageDailyChart({ daily }: CodexUsageDailyChartProps): Reac
- {translate("auto.components.stats.CodexUsageDailyChart.99a91d3143", "Input")}
+ {translate('auto.components.stats.CodexUsageDailyChart.99a91d3143', 'Input')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.7b596a88b2", "Output")}
+ {translate('auto.components.stats.CodexUsageDailyChart.7b596a88b2', 'Output')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.c646e1783c", "Cached input")}
+ {translate('auto.components.stats.CodexUsageDailyChart.c646e1783c', 'Cached input')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.1e6f62d7e3", "Reasoning")}
+ {translate('auto.components.stats.CodexUsageDailyChart.1e6f62d7e3', 'Reasoning')}
+
)
diff --git a/src/renderer/src/components/stats/ShareUsageButton.tsx b/src/renderer/src/components/stats/ShareUsageButton.tsx
index 44dcdb2a9cd..fe009152d43 100644
--- a/src/renderer/src/components/stats/ShareUsageButton.tsx
+++ b/src/renderer/src/components/stats/ShareUsageButton.tsx
@@ -126,19 +126,25 @@ export function ShareUsageButton(props: ShareUsageButtonProps): React.JSX.Elemen
ref={setShareButtonRef}
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.stats.ShareUsageButton.bce08eccb9", "Share usage")}
+ aria-label={translate(
+ 'auto.components.stats.ShareUsageButton.bce08eccb9',
+ 'Share usage'
+ )}
>
- {translate("auto.components.stats.ShareUsageButton.cecefa7c32", "Share")}
+ {translate('auto.components.stats.ShareUsageButton.cecefa7c32', 'Share')}
+
- {translate("auto.components.stats.ShareUsageButton.bce08eccb9", "Share usage")}
+
+ {translate('auto.components.stats.ShareUsageButton.bce08eccb9', 'Share usage')}
+
@@ -147,11 +153,13 @@ export function ShareUsageButton(props: ShareUsageButtonProps): React.JSX.Elemen
{copied ? (
<>
- {translate("auto.components.stats.ShareUsageButton.bd82c76a70", "Copied")}>
+ {translate('auto.components.stats.ShareUsageButton.bd82c76a70', 'Copied')}
+ >
) : (
<>
- {translate("auto.components.stats.ShareUsageButton.b295c1c75d", "Copy image")}>
+ {translate('auto.components.stats.ShareUsageButton.b295c1c75d', 'Copy image')}
+ >
)}
- {translate("auto.components.stats.ShareUsageButton.7d6b25323d", "Share on X")}
+ {translate('auto.components.stats.ShareUsageButton.7d6b25323d', 'Share on X')}
+
diff --git a/src/renderer/src/components/stats/ShareUsageCard.tsx b/src/renderer/src/components/stats/ShareUsageCard.tsx
index b82ffd20cde..cb6eb5c92bf 100644
--- a/src/renderer/src/components/stats/ShareUsageCard.tsx
+++ b/src/renderer/src/components/stats/ShareUsageCard.tsx
@@ -44,8 +44,14 @@ export const ShareUsageCard = forwardRef(
const turnsOrEvents =
provider === 'claude'
- ? { label: translate("auto.components.stats.ShareUsageCard.6adac63cfe", "turns"), count: (summary as ClaudeUsageSummary).turns }
- : { label: translate("auto.components.stats.ShareUsageCard.960324e9b8", "events"), count: (summary as CodexUsageSummary).events }
+ ? {
+ label: translate('auto.components.stats.ShareUsageCard.6adac63cfe', 'turns'),
+ count: (summary as ClaudeUsageSummary).turns
+ }
+ : {
+ label: translate('auto.components.stats.ShareUsageCard.960324e9b8', 'events'),
+ count: (summary as CodexUsageSummary).events
+ }
const providerLabel = provider === 'claude' ? 'Claude' : 'Codex'
@@ -106,9 +112,12 @@ function CardHeader(props: { providerLabel: string; range: string }): React.JSX.
- {translate("auto.components.stats.ShareUsageCard.0eb31e79ee", "Orca IDE")}
+ {translate('auto.components.stats.ShareUsageCard.0eb31e79ee', 'Orca IDE')}
+
- {props.providerLabel} {translate("auto.components.stats.ShareUsageCard.da62578d9d", "Usage")}
+ {props.providerLabel}{' '}
+ {translate('auto.components.stats.ShareUsageCard.da62578d9d', 'Usage')}
+
@@ -138,7 +147,7 @@ function StatsGrid(props: {
const cards = [
{
value: formatCost(props.summary.estimatedCostUsd ?? null),
- label: translate("auto.components.stats.ShareUsageCard.beb6f24f37", "Est. cost"),
+ label: translate('auto.components.stats.ShareUsageCard.beb6f24f37', 'Est. cost'),
bg: 'rgba(20, 71, 230, 0.1)',
border: '1px solid rgba(20, 71, 230, 0.2)',
valueColor: '#93b4ff',
@@ -146,7 +155,7 @@ function StatsGrid(props: {
},
{
value: formatTokens(props.totalTokens),
- label: translate("auto.components.stats.ShareUsageCard.2d9eb39264", "Total tokens"),
+ label: translate('auto.components.stats.ShareUsageCard.2d9eb39264', 'Total tokens'),
bg: 'rgba(255, 255, 255, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.06)',
valueColor: '#fafafa',
@@ -154,7 +163,7 @@ function StatsGrid(props: {
},
{
value: props.topModel,
- label: translate("auto.components.stats.ShareUsageCard.b760c0b622", "Top model"),
+ label: translate('auto.components.stats.ShareUsageCard.b760c0b622', 'Top model'),
bg: 'rgba(255, 255, 255, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.06)',
valueColor: '#fafafa',
@@ -218,11 +227,14 @@ function ChartHeader(props: {
textTransform: 'uppercase' as const
}}
>
- {translate("auto.components.stats.ShareUsageCard.66c83284cf", "Daily tokens")}
+ {translate('auto.components.stats.ShareUsageCard.66c83284cf', 'Daily tokens')}
+
- {props.sessions} {translate("auto.components.stats.ShareUsageCard.4a4c6c79a3", "sessions ·")}{props.turnsOrEvents.count} {props.turnsOrEvents.label}
+ {props.sessions}{' '}
+ {translate('auto.components.stats.ShareUsageCard.4a4c6c79a3', 'sessions ·')}
+ {props.turnsOrEvents.count} {props.turnsOrEvents.label}
diff --git a/src/renderer/src/components/stats/UsageOverviewPane.tsx b/src/renderer/src/components/stats/UsageOverviewPane.tsx
index a4fff2d6cf6..1f2080c995d 100644
--- a/src/renderer/src/components/stats/UsageOverviewPane.tsx
+++ b/src/renderer/src/components/stats/UsageOverviewPane.tsx
@@ -107,10 +107,17 @@ export function UsageOverviewPane(): React.JSX.Element {
-
{translate("auto.components.stats.UsageOverviewPane.c760c481c5", "Usage Overview")}
+
+ {translate('auto.components.stats.UsageOverviewPane.c760c481c5', 'Usage Overview')}
+
{formatUpdatedAt(overview.lastUpdatedAt)}
- {overview.hasPartialCost ? translate("auto.components.stats.UsageOverviewPane.55c910f4f1", "- some model prices are unavailable") : ''}
+ {overview.hasPartialCost
+ ? translate(
+ 'auto.components.stats.UsageOverviewPane.55c910f4f1',
+ '- some model prices are unavailable'
+ )
+ : ''}
@@ -120,13 +127,17 @@ export function UsageOverviewPane(): React.JSX.Element {
size="icon-xs"
onClick={handleRefresh}
disabled={!overview.hasAnyEnabledProvider || isScanning}
- aria-label={translate("auto.components.stats.UsageOverviewPane.e06d1baf5c", "Refresh usage overview")}
+ aria-label={translate(
+ 'auto.components.stats.UsageOverviewPane.e06d1baf5c',
+ 'Refresh usage overview'
+ )}
>
- {translate("auto.components.stats.UsageOverviewPane.ca6bc5fded", "Refresh")}
+ {translate('auto.components.stats.UsageOverviewPane.ca6bc5fded', 'Refresh')}
+
@@ -134,9 +145,18 @@ export function UsageOverviewPane(): React.JSX.Element {
-
{translate("auto.components.stats.UsageOverviewPane.49405ccc8d", "Start tracking tokens")}
+
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.49405ccc8d',
+ 'Start tracking tokens'
+ )}
+
- {translate("auto.components.stats.UsageOverviewPane.6c00c46815", "Enable a provider to scan local agent logs and build the combined token ledger.")}
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.6c00c46815',
+ 'Enable a provider to scan local agent logs and build the combined token ledger.'
+ )}
+
- {translate("auto.components.stats.UsageOverviewPane.0ea0cae435", "Enable Claude")}
+ {translate('auto.components.stats.UsageOverviewPane.0ea0cae435', 'Enable Claude')}
+
- {translate("auto.components.stats.UsageOverviewPane.2f1ee2878b", "Enable Codex")}
+ {translate('auto.components.stats.UsageOverviewPane.2f1ee2878b', 'Enable Codex')}
+
- {translate("auto.components.stats.UsageOverviewPane.2d13e57f72", "Enable OpenCode")}
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.2d13e57f72',
+ 'Enable OpenCode'
+ )}
+
@@ -172,22 +198,31 @@ export function UsageOverviewPane(): React.JSX.Element {
<>
}
/>
}
/>
}
/>
}
/>
@@ -195,7 +230,11 @@ export function UsageOverviewPane(): React.JSX.Element {
{!overview.hasAnyData ? (
- {translate("auto.components.stats.UsageOverviewPane.60002bb22f", "No local Claude, Codex, or OpenCode usage found yet. The overview will populate after the next agent session writes token logs.")}
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.60002bb22f',
+ 'No local Claude, Codex, or OpenCode usage found yet. The overview will populate after the next agent session writes token logs.'
+ )}
+
) : (
@@ -209,13 +248,21 @@ export function UsageOverviewPane(): React.JSX.Element {
-
{translate("auto.components.stats.UsageOverviewPane.33f7b043d2", "Providers")}
+
+ {translate('auto.components.stats.UsageOverviewPane.33f7b043d2', 'Providers')}
+
- {overview.enabledProviderCount} {translate("auto.components.stats.UsageOverviewPane.ecb0cd8a4c", "enabled -")}{overview.dataProviderCount} {translate("auto.components.stats.UsageOverviewPane.444585cb41", "with data")}
+ {overview.enabledProviderCount}{' '}
+ {translate('auto.components.stats.UsageOverviewPane.ecb0cd8a4c', 'enabled -')}
+ {overview.dataProviderCount}{' '}
+ {translate('auto.components.stats.UsageOverviewPane.444585cb41', 'with data')}
+
- {overview.sessions.toLocaleString()} {translate("auto.components.stats.UsageOverviewPane.22ed1b7669", "sessions")}
+ {overview.sessions.toLocaleString()}{' '}
+ {translate('auto.components.stats.UsageOverviewPane.22ed1b7669', 'sessions')}
+
{overview.providers.map((provider) => (
diff --git a/src/renderer/src/components/stats/share-card-utils.tsx b/src/renderer/src/components/stats/share-card-utils.tsx
index 07179bdbdc8..a63ba5e18ec 100644
--- a/src/renderer/src/components/stats/share-card-utils.tsx
+++ b/src/renderer/src/components/stats/share-card-utils.tsx
@@ -89,17 +89,41 @@ export function getDailySegments(
export function getLegendItems(provider: 'claude' | 'codex') {
if (provider === 'claude') {
return [
- { label: translate("auto.components.stats.share.card.utils.c2d7b23d57", "Input"), color: 'rgba(56, 189, 248, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.33d38e2177", "Output"), color: 'rgba(52, 211, 153, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.cc28cb965e", "Cache read"), color: 'rgba(251, 191, 36, 0.7)' },
- { label: translate("auto.components.stats.share.card.utils.9d166247ee", "Cache write"), color: 'rgba(217, 70, 239, 0.7)' }
+ {
+ label: translate('auto.components.stats.share.card.utils.c2d7b23d57', 'Input'),
+ color: 'rgba(56, 189, 248, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.33d38e2177', 'Output'),
+ color: 'rgba(52, 211, 153, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.cc28cb965e', 'Cache read'),
+ color: 'rgba(251, 191, 36, 0.7)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.9d166247ee', 'Cache write'),
+ color: 'rgba(217, 70, 239, 0.7)'
+ }
]
}
return [
- { label: translate("auto.components.stats.share.card.utils.c2d7b23d57", "Input"), color: 'rgba(56, 189, 248, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.33d38e2177", "Output"), color: 'rgba(52, 211, 153, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.4ee864629a", "Cached input"), color: 'rgba(251, 191, 36, 0.7)' },
- { label: translate("auto.components.stats.share.card.utils.7080aeaebb", "Reasoning"), color: 'rgba(217, 70, 239, 0.7)' }
+ {
+ label: translate('auto.components.stats.share.card.utils.c2d7b23d57', 'Input'),
+ color: 'rgba(56, 189, 248, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.33d38e2177', 'Output'),
+ color: 'rgba(52, 211, 153, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.4ee864629a', 'Cached input'),
+ color: 'rgba(251, 191, 36, 0.7)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.7080aeaebb', 'Reasoning'),
+ color: 'rgba(217, 70, 239, 0.7)'
+ }
]
}
@@ -168,10 +192,13 @@ export function CardFooter(props: {
>
- {formatTokens(props.summary.inputTokens)} {translate("auto.components.stats.share.card.utils.5d66fdd7c2", "input")}
+ {formatTokens(props.summary.inputTokens)} {' '}
+ {translate('auto.components.stats.share.card.utils.5d66fdd7c2', 'input')}
+
{formatTokens(props.summary.outputTokens)} {' '}
- {translate("auto.components.stats.share.card.utils.d864fc5f98", "output")}
+ {translate('auto.components.stats.share.card.utils.d864fc5f98', 'output')}
+
@@ -186,7 +213,11 @@ export function CardFooter(props: {
marginLeft: 5
}}
>
- {translate("auto.components.stats.share.card.utils.19f4b4dc75", "github.com/stablyai/orca")}
+ {translate(
+ 'auto.components.stats.share.card.utils.19f4b4dc75',
+ 'github.com/stablyai/orca'
+ )}
+
)
diff --git a/src/renderer/src/components/stats/usage-overview-model.ts b/src/renderer/src/components/stats/usage-overview-model.ts
index e8db99164d5..db419949825 100644
--- a/src/renderer/src/components/stats/usage-overview-model.ts
+++ b/src/renderer/src/components/stats/usage-overview-model.ts
@@ -136,7 +136,7 @@ function createClaudeProvider(input: UsageOverviewInput['claude']): UsageProvide
.map((entry) => entry.day)
return {
id: 'claude',
- label: translate("auto.components.stats.usage.overview.model.544d6d4c16", "Claude"),
+ label: translate('auto.components.stats.usage.overview.model.544d6d4c16', 'Claude'),
enabled: input.scanState?.enabled ?? false,
isScanning: input.scanState?.isScanning ?? false,
hasData: summary?.hasAnyClaudeData ?? input.scanState?.hasAnyClaudeData ?? false,
@@ -169,7 +169,7 @@ function createCodexProvider(input: UsageOverviewInput['codex']): UsageProviderO
.map((entry) => entry.day)
return {
id: 'codex',
- label: translate("auto.components.stats.usage.overview.model.eb220d193b", "Codex"),
+ label: translate('auto.components.stats.usage.overview.model.eb220d193b', 'Codex'),
enabled: input.scanState?.enabled ?? false,
isScanning: input.scanState?.isScanning ?? false,
hasData: summary?.hasAnyCodexData ?? input.scanState?.hasAnyCodexData ?? false,
@@ -197,7 +197,7 @@ function createOpenCodeProvider(input: UsageOverviewInput['opencode']): UsagePro
.map((entry) => entry.day)
return {
id: 'opencode',
- label: translate("auto.components.stats.usage.overview.model.bc474051e5", "OpenCode"),
+ label: translate('auto.components.stats.usage.overview.model.bc474051e5', 'OpenCode'),
enabled: input.scanState?.enabled ?? false,
isScanning: input.scanState?.isScanning ?? false,
hasData: summary?.hasAnyOpenCodeData ?? input.scanState?.hasAnyOpenCodeData ?? false,
diff --git a/src/renderer/src/components/status-bar/PetStatusSegment.tsx b/src/renderer/src/components/status-bar/PetStatusSegment.tsx
index bf816d22d04..b927e29351e 100644
--- a/src/renderer/src/components/status-bar/PetStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/PetStatusSegment.tsx
@@ -46,7 +46,12 @@ function PetStatusSegmentInner(): React.JSX.Element {
console.log('[pet-overlay] upload: click')
if (!window.api?.pet?.import) {
console.warn('[pet-overlay] upload: window.api.pet.import missing — restart Orca')
- toast.error(translate("auto.components.status.bar.PetStatusSegment.e6234bcc17", "Custom pet upload needs a full app restart (not just reload)."))
+ toast.error(
+ translate(
+ 'auto.components.status.bar.PetStatusSegment.e6234bcc17',
+ 'Custom pet upload needs a full app restart (not just reload).'
+ )
+ )
return
}
try {
@@ -62,13 +67,25 @@ function PetStatusSegmentInner(): React.JSX.Element {
setPetId(model.id)
} catch (error) {
console.error('[pet-overlay] upload: error', error)
- toast.error(error instanceof Error ? error.message : translate("auto.components.status.bar.PetStatusSegment.f395c9a685", "Failed to import file"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.status.bar.PetStatusSegment.f395c9a685',
+ 'Failed to import file'
+ )
+ )
}
}
const handleImportPetBundle = async (): Promise => {
if (!window.api?.pet?.importPetBundle) {
- toast.error(translate("auto.components.status.bar.PetStatusSegment.2021d4f6db", "Pet bundle import needs a full app restart (not just reload)."))
+ toast.error(
+ translate(
+ 'auto.components.status.bar.PetStatusSegment.2021d4f6db',
+ 'Pet bundle import needs a full app restart (not just reload).'
+ )
+ )
return
}
try {
@@ -83,7 +100,14 @@ function PetStatusSegmentInner(): React.JSX.Element {
setPetId(model.id)
} catch (error) {
console.error('[pet-overlay] pet bundle: error', error)
- toast.error(error instanceof Error ? error.message : translate("auto.components.status.bar.PetStatusSegment.cef0ab4636", "Failed to import pet bundle"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.status.bar.PetStatusSegment.cef0ab4636',
+ 'Failed to import pet bundle'
+ )
+ )
}
}
@@ -93,7 +117,10 @@ function PetStatusSegmentInner(): React.JSX.Element {
- {translate("auto.components.status.bar.PetStatusSegment.34c25dfe9c", "Pet")}
+
+ {translate('auto.components.status.bar.PetStatusSegment.34c25dfe9c', 'Pet')}
+
{
event.preventDefault()
setPetVisible(!petVisible)
}}
>
- {petVisible ? translate("auto.components.status.bar.PetStatusSegment.1fbc51cc77", "Hide pet") : translate("auto.components.status.bar.PetStatusSegment.6d0a8cd179", "Show pet")}
+ {petVisible
+ ? translate('auto.components.status.bar.PetStatusSegment.1fbc51cc77', 'Hide pet')
+ : translate('auto.components.status.bar.PetStatusSegment.6d0a8cd179', 'Show pet')}
{/* Why: in-menu range so users can resize the overlay without leaving
the dropdown — pet sprites can import larger than the default 180px
@@ -123,8 +154,13 @@ function PetStatusSegmentInner(): React.JSX.Element {
onKeyDown={(e) => e.stopPropagation()}
>
- {translate("auto.components.status.bar.PetStatusSegment.2f7bbaa457", "Size")}
- {petSize}{translate("auto.components.status.bar.PetStatusSegment.c6aa805b1b", "px")}
+
+ {translate('auto.components.status.bar.PetStatusSegment.2f7bbaa457', 'Size')}
+
+
+ {petSize}
+ {translate('auto.components.status.bar.PetStatusSegment.c6aa805b1b', 'px')}
+
setPetSize(Number(e.target.value))}
className="w-full"
- aria-label={translate("auto.components.status.bar.PetStatusSegment.b75484a01a", "Pet size")}
+ aria-label={translate(
+ 'auto.components.status.bar.PetStatusSegment.b75484a01a',
+ 'Pet size'
+ )}
/>
- {translate("auto.components.status.bar.PetStatusSegment.0608ad02a2", "Choose pet")}
+
+ {translate('auto.components.status.bar.PetStatusSegment.0608ad02a2', 'Choose pet')}
+
{/* Why: portal so the submenu escapes the parent Content's overflow
clipping — without this, the submenu opens inside the scroll
container and gets clipped. Matches the convention used in
@@ -185,7 +226,11 @@ function PetStatusSegmentInner(): React.JSX.Element {
{
event.stopPropagation()
event.preventDefault()
@@ -208,14 +253,22 @@ function PetStatusSegmentInner(): React.JSX.Element {
}}
>
- {translate("auto.components.status.bar.PetStatusSegment.59b5955621", "Upload your own…")}
+ {translate(
+ 'auto.components.status.bar.PetStatusSegment.59b5955621',
+ 'Upload your own…'
+ )}
+
{
void handleImportPetBundle()
}}
>
- {translate("auto.components.status.bar.PetStatusSegment.ed176ad68f", "Import .codex-pet bundle…")}
+ {translate(
+ 'auto.components.status.bar.PetStatusSegment.ed176ad68f',
+ 'Import .codex-pet bundle…'
+ )}
+
@@ -230,7 +283,8 @@ function PetStatusSegmentInner(): React.JSX.Element {
openSettingsPage()
}}
>
- {translate("auto.components.status.bar.PetStatusSegment.cd8c6c654c", "Pet settings…")}
+ {translate('auto.components.status.bar.PetStatusSegment.cd8c6c654c', 'Pet settings…')}
+
)
diff --git a/src/renderer/src/components/status-bar/SshStatusSegment.tsx b/src/renderer/src/components/status-bar/SshStatusSegment.tsx
index 329426f743c..9a959648c4d 100644
--- a/src/renderer/src/components/status-bar/SshStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/SshStatusSegment.tsx
@@ -126,7 +126,11 @@ function TargetRow({
await window.api.ssh.connect({ targetId })
recordFeatureInteraction('ssh')
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.status.bar.SshStatusSegment.2c29e2de68", "Connection failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate('auto.components.status.bar.SshStatusSegment.2c29e2de68', 'Connection failed')
+ )
} finally {
if (mountedRef.current) {
setBusy(false)
@@ -140,7 +144,11 @@ function TargetRow({
await window.api.ssh.disconnect({ targetId })
recordFeatureInteraction('ssh')
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.status.bar.SshStatusSegment.bf07aee59e", "Disconnect failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate('auto.components.status.bar.SshStatusSegment.bf07aee59e', 'Disconnect failed')
+ )
} finally {
if (mountedRef.current) {
setBusy(false)
@@ -157,9 +165,9 @@ function TargetRow({
{STATUS_LABELS[status]}
·
- {syncStatus?.phase === "pulling" || syncStatus?.phase === "pushing" ? (
+ {syncStatus?.phase === 'pulling' || syncStatus?.phase === 'pushing' ? (
- ) : syncStatus?.phase === "conflict" || syncStatus?.phase === 'error' ? (
+ ) : syncStatus?.phase === 'conflict' || syncStatus?.phase === 'error' ? (
) : (
@@ -176,14 +184,16 @@ function TargetRow({
onClick={() => void handleConnect()}
className="shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium text-foreground hover:bg-accent/70"
>
- {translate("auto.components.status.bar.SshStatusSegment.63f36455cc", "Connect")}
- ) : status === "connected" ? (
+ {translate('auto.components.status.bar.SshStatusSegment.63f36455cc', 'Connect')}
+
+ ) : status === 'connected' ? (
void handleDisconnect()}
className="shrink-0 rounded px-1.5 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/70 hover:text-foreground"
>
- {translate("auto.components.status.bar.SshStatusSegment.59b553e2aa", "Disconnect")}
+ {translate('auto.components.status.bar.SshStatusSegment.59b553e2aa', 'Disconnect')}
+
) : null}
)
@@ -243,7 +253,10 @@ export function SshStatusSegment({
{iconOnly ? (
@@ -266,16 +279,16 @@ export function SshStatusSegment({
) : anyConnecting ? (
- ) : overall === "connected" ? (
+ ) : overall === 'connected' ? (
- ) : overall === "partial" ? (
+ ) : overall === 'partial' ? (
) : (
)}
{!compact && (
- {translate("auto.components.status.bar.SshStatusSegment.d09ec41831", "SSH")}{' '}
+ {translate('auto.components.status.bar.SshStatusSegment.d09ec41831', 'SSH')}{' '}
{syncProblemLabel ?? overallLabel(overall)}
@@ -297,7 +310,8 @@ export function SshStatusSegment({
className="w-[min(20rem,calc(100vw-1rem))]"
>
- {translate("auto.components.status.bar.SshStatusSegment.6e8a9a4242", "SSH Connections")}
+ {translate('auto.components.status.bar.SshStatusSegment.6e8a9a4242', 'SSH Connections')}
+
{targets.map((t) => (
- {translate("auto.components.status.bar.SshStatusSegment.3ad70e0365", "Manage SSH…")}
+ {translate('auto.components.status.bar.SshStatusSegment.3ad70e0365', 'Manage SSH…')}
+
)
diff --git a/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx b/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx
index cd513384622..33b1adb6269 100644
--- a/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx
+++ b/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx
@@ -36,17 +36,30 @@ export function StatusBarUsageEmptyCta(): React.JSX.Element {
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.d663430cf9", "Connect an AI account to see usage")}
+
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.d663430cf9',
+ 'Connect an AI account to see usage'
+ )}
+
-
{translate("auto.components.status.bar.StatusBarUsageEmptyCta.84c3b15dca", "Agent usage limits")}
+
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.84c3b15dca',
+ 'Agent usage limits'
+ )}
+
{/* Why: permanently hide the teaching CTA — styling mirrors the
SetupGuideSidebarEntry hover-state icon (muted → foreground). */}
@@ -54,22 +67,38 @@ export function StatusBarUsageEmptyCta(): React.JSX.Element {
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.9a542f46c7", "Hide from status bar")}
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.9a542f46c7',
+ 'Hide from status bar'
+ )}
+
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.97957ad3a3", "Connect your AI provider accounts to see their usage in real time and easily switch between accounts.")}
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.97957ad3a3',
+ 'Connect your AI provider accounts to see their usage in real time and easily switch between accounts.'
+ )}
+
{/* Why: name the full provider set so the feature doesn't read as
support for just one agent. */}
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.caa0f39811", "Supports:")}
+
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.caa0f39811',
+ 'Supports:'
+ )}
+
@@ -83,7 +112,11 @@ export function StatusBarUsageEmptyCta(): React.JSX.Element {
onClick={handleOpenSettings}
className="mt-0.5 h-7 w-full text-xs"
>
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.828c764a79", "Connect an account")}
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.828c764a79',
+ 'Connect an account'
+ )}
+
diff --git a/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx b/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx
index 3839c9b498a..639ca8fb08f 100644
--- a/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx
+++ b/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx
@@ -40,20 +40,54 @@ export function WorkspaceSpaceCompactPanel({
- {translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.8ff597593d", "Space")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.8ff597593d',
+ 'Space'
+ )}
+
- {translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.c361440dc0", "Beta")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.c361440dc0',
+ 'Beta'
+ )}
+
{analysis
? isScanning
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.3d8d47ce77", "{{value0}} · last result kept", { value0: progressLabel ?? 'Scanning workspace sizes' })
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.3d8d47ce77',
+ '{{value0}} · last result kept',
+ { value0: progressLabel ?? 'Scanning workspace sizes' }
+ )
: analysis.unavailableWorktreeCount > 0
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457", "{{value0}} reclaimable · {{value1}} unavailable", { value0: formatBytes(analysis.reclaimableBytes), value1: analysis.unavailableWorktreeCount })
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457", "{{value0}} reclaimable · {{value1}} workspaces", { value0: formatBytes(analysis.reclaimableBytes), value1: analysis.scannedWorktreeCount })
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457',
+ '{{value0}} reclaimable · {{value1}} unavailable',
+ {
+ value0: formatBytes(analysis.reclaimableBytes),
+ value1: analysis.unavailableWorktreeCount
+ }
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457',
+ '{{value0}} reclaimable · {{value1}} workspaces',
+ {
+ value0: formatBytes(analysis.reclaimableBytes),
+ value1: analysis.scannedWorktreeCount
+ }
+ )
: isScanning
- ? (progressLabel ?? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.39786e3b73", "Scanning workspace sizes."))
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.0583c806ac", "Workspace disk usage is not scanned.")}
+ ? (progressLabel ??
+ translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.39786e3b73',
+ 'Scanning workspace sizes.'
+ ))
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.0583c806ac',
+ 'Workspace disk usage is not scanned.'
+ )}
@@ -67,7 +101,7 @@ export function WorkspaceSpaceCompactPanel({
className="w-24"
>
{isScanning ? (
- progress?.state === "cancelling" ? (
+ progress?.state === 'cancelling' ? (
) : (
@@ -76,34 +110,65 @@ export function WorkspaceSpaceCompactPanel({
)}
{isScanning
- ? progress?.state === "cancelling"
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.5691353a21", "Stopping")
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.2af2174d6d", "Cancel")
+ ? progress?.state === 'cancelling'
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.5691353a21',
+ 'Stopping'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.2af2174d6d',
+ 'Cancel'
+ )
: analysis
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.f5e1a84d79", "Refresh")
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.0582df6d2e", "Scan")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.f5e1a84d79',
+ 'Refresh'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.0582df6d2e',
+ 'Scan'
+ )}
- {translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.6a5dc3c61a", "Review")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.6a5dc3c61a',
+ 'Review'
+ )}
+
{analysis ? (
-
{translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.f4d2651498", "Scanned")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.f4d2651498',
+ 'Scanned'
+ )}
+
{formatBytes(analysis.totalSizeBytes)}
-
{translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.9be86c46a0", "Freeable")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.9be86c46a0',
+ 'Freeable'
+ )}
+
{formatBytes(analysis.reclaimableBytes)}
-
{translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.a471aa9c24", "Updated")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.a471aa9c24',
+ 'Updated'
+ )}
+
{getWorkspaceSpaceScanTimeLabel(analysis.scannedAt)}
diff --git a/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx b/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx
index d71f8127513..ccb52012710 100644
--- a/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx
+++ b/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx
@@ -96,7 +96,13 @@ export function PortRow({
openInOrcaBrowser
}).then((result) => {
if (!result.ok) {
- toast.error(translate("auto.components.status.bar.ports.status.popover.rows.b854ec9ff5", "Failed to open browser"), { description: result.reason })
+ toast.error(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.b854ec9ff5',
+ 'Failed to open browser'
+ ),
+ { description: result.reason }
+ )
}
})
},
@@ -117,7 +123,13 @@ export function PortRow({
recordFeatureInteraction('ports')
const address = addressForPort(port)
void window.api.ui.writeClipboardText(address)
- toast.success(translate("auto.components.status.bar.ports.status.popover.rows.480d8f2347", "Copied {{value0}}", { value0: address }))
+ toast.success(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.480d8f2347',
+ 'Copied {{value0}}',
+ { value0: address }
+ )
+ )
},
[port, recordFeatureInteraction]
)
@@ -139,16 +151,28 @@ export function PortRow({
toast.error(result.reason)
return
}
- toast.success(translate("auto.components.status.bar.ports.status.popover.rows.acdb6df590", "Stopped process on {{value0}}", { value0: port.port }))
+ toast.success(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.acdb6df590',
+ 'Stopped process on {{value0}}',
+ { value0: port.port }
+ )
+ )
const refreshResult = await refreshWorkspacePortScanAfterStop({
runtimeTarget,
setWorkspacePortScan,
setWorkspacePortScanRefreshing
})
if (!refreshResult.ok) {
- toast.error(translate("auto.components.status.bar.ports.status.popover.rows.e4a709548c", "Failed to refresh ports"), {
- description: refreshResult.reason
- })
+ toast.error(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.e4a709548c',
+ 'Failed to refresh ports'
+ ),
+ {
+ description: refreshResult.reason
+ }
+ )
}
}
void run()
@@ -180,13 +204,34 @@ export function PortRow({
@@ -211,7 +256,12 @@ export function WorkspaceGroupRows({
event.stopPropagation()
const ownerPort = group.ports[0]
if (!ownerPort || !goToWorkspacePortOwner(ownerPort)) {
- toast.error(translate("auto.components.status.bar.ports.status.popover.rows.f2b813345f", "Workspace unavailable"))
+ toast.error(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.f2b813345f',
+ 'Workspace unavailable'
+ )
+ )
}
},
[group.ports]
@@ -225,7 +275,10 @@ export function WorkspaceGroupRows({
diff --git a/src/renderer/src/components/status-bar/tooltip.tsx b/src/renderer/src/components/status-bar/tooltip.tsx
index d9bc5baa49f..6e720f88ce4 100644
--- a/src/renderer/src/components/status-bar/tooltip.tsx
+++ b/src/renderer/src/components/status-bar/tooltip.tsx
@@ -79,7 +79,12 @@ function ErrorMessage({
return (
- {stale ? translate("auto.components.status.bar.tooltip.a9a318b7a3", "Refresh failed — showing cached data") : translate("auto.components.status.bar.tooltip.7567cd1c6b", "Usage unavailable")}
+ {stale
+ ? translate(
+ 'auto.components.status.bar.tooltip.a9a318b7a3',
+ 'Refresh failed — showing cached data'
+ )
+ : translate('auto.components.status.bar.tooltip.7567cd1c6b', 'Usage unavailable')}
{message}
@@ -95,14 +100,29 @@ export function getWindowSections(
): { label: string; window: RateLimitWindow | null }[] {
if (p.buckets?.length) {
const bucketSections = p.buckets.map((b) => ({ label: b.name, window: b as RateLimitWindow }))
- return [...bucketSections, { label: translate("auto.components.status.bar.tooltip.252c096536", "Weekly"), window: p.weekly }]
+ return [
+ ...bucketSections,
+ {
+ label: translate('auto.components.status.bar.tooltip.252c096536', 'Weekly'),
+ window: p.weekly
+ }
+ ]
}
const sections: { label: string; window: RateLimitWindow | null }[] = [
- { label: translate("auto.components.status.bar.tooltip.94038ad2fa", "Session"), window: p.session },
- { label: translate("auto.components.status.bar.tooltip.252c096536", "Weekly"), window: p.weekly }
+ {
+ label: translate('auto.components.status.bar.tooltip.94038ad2fa', 'Session'),
+ window: p.session
+ },
+ {
+ label: translate('auto.components.status.bar.tooltip.252c096536', 'Weekly'),
+ window: p.weekly
+ }
]
if (p.monthly !== undefined && p.monthly !== null) {
- sections.push({ label: translate("auto.components.status.bar.tooltip.7f7f208060", "Monthly"), window: p.monthly })
+ sections.push({
+ label: translate('auto.components.status.bar.tooltip.7f7f208060', 'Monthly'),
+ window: p.monthly
+ })
}
return sections
}
@@ -144,7 +164,11 @@ export function ProviderPanel({
const emptyBarClass = inverted ? 'bg-background/20' : 'bg-muted'
if (!p) {
- return {translate("auto.components.status.bar.tooltip.6d6df77f41", "No data available")}
+ return (
+
+ {translate('auto.components.status.bar.tooltip.6d6df77f41', 'No data available')}
+
+ )
}
const name =
@@ -167,7 +191,9 @@ export function ProviderPanel({
{name}
-
{p.error ?? translate("auto.components.status.bar.tooltip.1292d4f2ee", "Unavailable")}
+
+ {p.error ?? translate('auto.components.status.bar.tooltip.1292d4f2ee', 'Unavailable')}
+
)
}
@@ -180,7 +206,13 @@ export function ProviderPanel({
{name}
-
+
)
@@ -211,7 +243,10 @@ export function ProviderPanel({
/>
- {leftPct}{translate("auto.components.status.bar.tooltip.cedb7b99e3", "% left")}
+
+ {leftPct}
+ {translate('auto.components.status.bar.tooltip.cedb7b99e3', '% left')}
+
{resetLabel && {resetLabel} }
diff --git a/src/renderer/src/components/tab-bar/BrowserTab.tsx b/src/renderer/src/components/tab-bar/BrowserTab.tsx
index 30e470aee22..cbf2aceabea 100644
--- a/src/renderer/src/components/tab-bar/BrowserTab.tsx
+++ b/src/renderer/src/components/tab-bar/BrowserTab.tsx
@@ -275,20 +275,25 @@ export default function BrowserTab({
>
onSplitGroup('up', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.96354ed249", "Split Up")}
+ {translate('auto.components.tab.bar.BrowserTab.96354ed249', 'Split Up')}
+
onSplitGroup('down', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.2186a8407c", "Split Down")}
+ {translate('auto.components.tab.bar.BrowserTab.2186a8407c', 'Split Down')}
+
onSplitGroup('left', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.7e8106899f", "Split Left")}
+ {translate('auto.components.tab.bar.BrowserTab.7e8106899f', 'Split Left')}
+
onSplitGroup('right', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.966feb9ad5", "Split Right")}
+ {translate('auto.components.tab.bar.BrowserTab.966feb9ad5', 'Split Right')}
+
- {translate("auto.components.tab.bar.BrowserTab.5d6e89891f", "Duplicate Tab")}
+ {translate('auto.components.tab.bar.BrowserTab.5d6e89891f', 'Duplicate Tab')}
+
{isPinned ? (
@@ -296,19 +301,24 @@ export default function BrowserTab({
) : (
)}
- {isPinned ? translate("auto.components.tab.bar.BrowserTab.c5aaee8c39", "Unpin Tab") : translate("auto.components.tab.bar.BrowserTab.911542656f", "Pin Tab")}
+ {isPinned
+ ? translate('auto.components.tab.bar.BrowserTab.c5aaee8c39', 'Unpin Tab')
+ : translate('auto.components.tab.bar.BrowserTab.911542656f', 'Pin Tab')}
!isPinned && onClose()} disabled={isPinned}>
- {translate("auto.components.tab.bar.BrowserTab.1611a1324b", "Close")}
+ {translate('auto.components.tab.bar.BrowserTab.1611a1324b', 'Close')}
+
- {translate("auto.components.tab.bar.BrowserTab.9dd880bd56", "Close Tabs To The Right")}
+ {translate('auto.components.tab.bar.BrowserTab.9dd880bd56', 'Close Tabs To The Right')}
+
void window.api.shell.openUrl(openInBrowserUrl)}
disabled={!isHttpUrl}
>
- {translate("auto.components.tab.bar.BrowserTab.6e0bc8f3a8", "Open In Browser")}
+ {translate('auto.components.tab.bar.BrowserTab.6e0bc8f3a8', 'Open In Browser')}
+
>
diff --git a/src/renderer/src/components/tab-bar/EditorFileTab.tsx b/src/renderer/src/components/tab-bar/EditorFileTab.tsx
index 5fa53c041cb..bbc737ec9ef 100644
--- a/src/renderer/src/components/tab-bar/EditorFileTab.tsx
+++ b/src/renderer/src/components/tab-bar/EditorFileTab.tsx
@@ -258,7 +258,11 @@ export default function EditorFileTab({
onSplitGroup('up', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.6b3efb106e", "Split Up")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.6b3efb106e', 'Split Up')}
+
onSplitGroup('down', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.1d04b1630b", "Split Down")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.1d04b1630b', 'Split Down')}
+
onSplitGroup('left', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.e3ff145b98", "Split Left")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.e3ff145b98', 'Split Left')}
+
onSplitGroup('right', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.f7c3d7d5af", "Split Right")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.f7c3d7d5af', 'Split Right')}
+
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.68cc610e7f", "Rename")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.68cc610e7f', 'Rename')}
+
{isPinned ? : }
- {isPinned ? translate("auto.components.tab.bar.EditorFileTabContextMenu.8e9d603a09", "Unpin Tab") : translate("auto.components.tab.bar.EditorFileTabContextMenu.fdd29eb669", "Pin Tab")}
+ {isPinned
+ ? translate('auto.components.tab.bar.EditorFileTabContextMenu.8e9d603a09', 'Unpin Tab')
+ : translate('auto.components.tab.bar.EditorFileTabContextMenu.fdd29eb669', 'Pin Tab')}
!isPinned && onClose()} disabled={isPinned}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.1ba8492c5b", "Close")}
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.ba1369dd24", "Close All Editor Tabs")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.1ba8492c5b', 'Close')}
+
+
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.ba1369dd24',
+ 'Close All Editor Tabs'
+ )}
+
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.e5ff31ccaf", "Close Tabs To The Right")}
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.e5ff31ccaf',
+ 'Close Tabs To The Right'
+ )}
+
{canShowMarkdownPreview ? (
<>
@@ -152,7 +169,11 @@ export function EditorFileTabContextMenu({
)
}}
>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.bfd5797ef4", "Open Markdown Preview")}
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.bfd5797ef4',
+ 'Open Markdown Preview'
+ )}
+
>
) : null}
@@ -162,14 +183,19 @@ export function EditorFileTabContextMenu({
}}
>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.5b85754786", "Copy Path")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.5b85754786', 'Copy Path')}
+
{
void window.api.ui.writeClipboardText(file.relativePath)
}}
>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.52ce4f4605", "Copy Relative Path")}
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.52ce4f4605',
+ 'Copy Relative Path'
+ )}
+
{
diff --git a/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx b/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx
index 2e2f37a9f93..85e47fe9fe2 100644
--- a/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx
+++ b/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx
@@ -147,10 +147,14 @@ export default function RecentTabSwitcher(): React.JSX.Element | null {
- {translate("auto.components.tab.bar.RecentTabSwitcher.329638ff6f", "Switch Tab")}
+ {translate('auto.components.tab.bar.RecentTabSwitcher.329638ff6f', 'Switch Tab')}
+
{switcher.items.map((item, index) => {
const selected = index === switcher.selectedIndex
diff --git a/src/renderer/src/components/tab-bar/SortableTab.tsx b/src/renderer/src/components/tab-bar/SortableTab.tsx
index c7c60ff95a6..94e4c9b5203 100644
--- a/src/renderer/src/components/tab-bar/SortableTab.tsx
+++ b/src/renderer/src/components/tab-bar/SortableTab.tsx
@@ -309,7 +309,11 @@ export default function SortableTab({
ref={setRenameInputElement}
data-tab-rename-input="true"
value={renameValue}
- aria-label={translate("auto.components.tab.bar.SortableTab.ab19f603eb", "Rename tab {{value0}}", { value0: tabTitle })}
+ aria-label={translate(
+ 'auto.components.tab.bar.SortableTab.ab19f603eb',
+ 'Rename tab {{value0}}',
+ { value0: tabTitle }
+ )}
onChange={(event) => setRenameValue(event.target.value)}
onBlur={commitRename}
onKeyDown={(event) => {
@@ -379,8 +383,8 @@ export default function SortableTab({
e.stopPropagation()
onToggleExpand(tab.id)
}}
- title={translate("auto.components.tab.bar.SortableTab.fdb2691425", "Collapse pane")}
- aria-label={translate("auto.components.tab.bar.SortableTab.fdb2691425", "Collapse pane")}
+ title={translate('auto.components.tab.bar.SortableTab.fdb2691425', 'Collapse pane')}
+ aria-label={translate('auto.components.tab.bar.SortableTab.fdb2691425', 'Collapse pane')}
>
@@ -397,7 +401,11 @@ export default function SortableTab({
// instead of bypassing the render layer by calling closeTab() on
// the store — a store-only assertion would pass even if this
// button had been accidentally unmounted.
- aria-label={translate("auto.components.tab.bar.SortableTab.6df69d9388", "Close tab {{value0}}", { value0: tabTitle })}
+ aria-label={translate(
+ 'auto.components.tab.bar.SortableTab.6df69d9388',
+ 'Close tab {{value0}}',
+ { value0: tabTitle }
+ )}
type="button"
data-tab-close-button="true"
onPointerDown={(e) => {
diff --git a/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx b/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx
index f17e028a667..9aca62ba847 100644
--- a/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx
+++ b/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx
@@ -10,16 +10,46 @@ import type { TerminalTab } from '../../../../shared/types'
import { translate } from '@/i18n/i18n'
const TAB_COLORS = [
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.20baa43c05", "None"), value: null },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.cb3eadefd2", "Blue"), value: '#3b82f6' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.c2d8b0991f", "Purple"), value: '#a855f7' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.03cf6dab1a", "Pink"), value: '#ec4899' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.620aec6729", "Red"), value: '#ef4444' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.a47629b3cf", "Orange"), value: '#f97316' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.69682e2ce4", "Yellow"), value: '#eab308' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.be905e9b0a", "Green"), value: '#22c55e' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.845576bed1", "Teal"), value: '#14b8a6' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.7703990447", "Gray"), value: '#9ca3af' }
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.20baa43c05', 'None'),
+ value: null
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.cb3eadefd2', 'Blue'),
+ value: '#3b82f6'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.c2d8b0991f', 'Purple'),
+ value: '#a855f7'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.03cf6dab1a', 'Pink'),
+ value: '#ec4899'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.620aec6729', 'Red'),
+ value: '#ef4444'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.a47629b3cf', 'Orange'),
+ value: '#f97316'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.69682e2ce4', 'Yellow'),
+ value: '#eab308'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.be905e9b0a', 'Green'),
+ value: '#22c55e'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.845576bed1', 'Teal'),
+ value: '#14b8a6'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.7703990447', 'Gray'),
+ value: '#9ca3af'
+ }
] as const
type SortableTabContextMenuProps = {
@@ -68,32 +98,48 @@ export function SortableTabContextMenu({
onSplitGroup('up', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.591f9b12c1", "Split Up")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.591f9b12c1', 'Split Up')}
+
onSplitGroup('down', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.af80ed83c1", "Split Down")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.af80ed83c1', 'Split Down')}
+
onSplitGroup('left', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.0ce4bae39d", "Split Left")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.0ce4bae39d', 'Split Left')}
+
onSplitGroup('right', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.21132389e9", "Split Right")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.21132389e9', 'Split Right')}
+
{isPinned ? : }
- {isPinned ? translate("auto.components.tab.bar.SortableTabContextMenu.417722e9c2", "Unpin Tab") : translate("auto.components.tab.bar.SortableTabContextMenu.60f958ec75", "Pin Tab")}
+ {isPinned
+ ? translate('auto.components.tab.bar.SortableTabContextMenu.417722e9c2', 'Unpin Tab')
+ : translate('auto.components.tab.bar.SortableTabContextMenu.60f958ec75', 'Pin Tab')}
!isPinned && onClose(tab.id)} disabled={isPinned}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.89359a36f7", "Close")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.89359a36f7', 'Close')}
+
onCloseOthers(tab.id)} disabled={tabCount <= 1}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.8d16f9cd30", "Close Others")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.8d16f9cd30', 'Close Others')}
+
onCloseToRight(tab.id)} disabled={!hasTabsToRight}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.c1ee099c7e", "Close Tabs To The Right")}
+ {translate(
+ 'auto.components.tab.bar.SortableTabContextMenu.c1ee099c7e',
+ 'Close Tabs To The Right'
+ )}
+
- {translate("auto.components.tab.bar.SortableTabContextMenu.2f697b3c31", "Change Title")}
+
+ {translate('auto.components.tab.bar.SortableTabContextMenu.2f697b3c31', 'Change Title')}
+
-
{translate("auto.components.tab.bar.SortableTabContextMenu.35e8892fd0", "Tab Color")}
+
+ {translate('auto.components.tab.bar.SortableTabContextMenu.35e8892fd0', 'Tab Color')}
+
{TAB_COLORS.map((color) => {
const isSelected = tab.color === color.value
diff --git a/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx b/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx
index 3826299e35e..173170a4330 100644
--- a/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx
+++ b/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx
@@ -125,9 +125,19 @@ export function TabBarQuickCommandsButton({
const handleDeleteCommand = async (command: TerminalQuickCommand): Promise
=> {
setMenuOpen(false)
const confirmed = await confirm({
- title: translate("auto.components.tab.bar.TabBarQuickCommandsButton.e8e1a52edb", "Delete \"{{value0}}\"?", { value0: command.label }),
- description: translate("auto.components.tab.bar.TabBarQuickCommandsButton.3220e2da27", "This quick command will be removed from your saved list."),
- confirmLabel: translate("auto.components.tab.bar.TabBarQuickCommandsButton.be8f0ff166", "Delete"),
+ title: translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.e8e1a52edb',
+ 'Delete "{{value0}}"?',
+ { value0: command.label }
+ ),
+ description: translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.3220e2da27',
+ 'This quick command will be removed from your saved list.'
+ ),
+ confirmLabel: translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.be8f0ff166',
+ 'Delete'
+ ),
confirmVariant: 'destructive'
})
if (!confirmed) {
@@ -160,14 +170,26 @@ export function TabBarQuickCommandsButton({
})
}
className="my-auto flex h-7 shrink-0 items-center gap-1 rounded-md px-1.5 text-muted-foreground hover:bg-accent/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
- aria-label={translate("auto.components.tab.bar.TabBarQuickCommandsButton.8f1e971966", "Add quick command")}
+ aria-label={translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.8f1e971966',
+ 'Add quick command'
+ )}
>
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831", "Add command")}
+
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831',
+ 'Add command'
+ )}
+
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.1d411fb6a5", "Save a quick command for this repo")}
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.1d411fb6a5',
+ 'Save a quick command for this repo'
+ )}
+
@@ -232,7 +258,11 @@ export function TabBarQuickCommandsButton({
void handleDeleteCommand(command)
}}
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-destructive"
- aria-label={translate("auto.components.tab.bar.TabBarQuickCommandsButton.196593b6a9", "Remove {{value0}}", { value0: command.label })}
+ aria-label={translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.196593b6a9',
+ 'Remove {{value0}}',
+ { value0: command.label }
+ )}
>
@@ -251,21 +281,45 @@ export function TabBarQuickCommandsButton({
disabled={!mostRecent}
className={cn(innerButtonBase, 'gap-1.5 rounded-l-md rounded-r-none px-1.5')}
aria-label={
- mostRecent ? translate("auto.components.tab.bar.TabBarQuickCommandsButton.b775303755", "Run quick command: {{value0}}", { value0: mostRecent.label }) : translate("auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc", "Run quick command")
+ mostRecent
+ ? translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.b775303755',
+ 'Run quick command: {{value0}}',
+ { value0: mostRecent.label }
+ )
+ : translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc',
+ 'Run quick command'
+ )
}
>
- {mostRecent?.label ?? translate("auto.components.tab.bar.TabBarQuickCommandsButton.7b1c9d6ae1", "Run")}
+ {mostRecent?.label ??
+ translate('auto.components.tab.bar.TabBarQuickCommandsButton.7b1c9d6ae1', 'Run')}
{mostRecent
? isTerminalAgentQuickCommand(mostRecent)
- ? translate("auto.components.tab.bar.TabBarQuickCommandsButton.77ac113df0", "Start {{value0}}: {{value1}}", { value0: getAgentLabel(mostRecent.agent), value1: getTerminalQuickCommandBody(mostRecent) })
- : translate("auto.components.tab.bar.TabBarQuickCommandsButton.37e1bb90ce", "Run: {{value0}}", { value0: getTerminalQuickCommandBody(mostRecent) })
- : translate("auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc", "Run quick command")}
+ ? translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.77ac113df0',
+ 'Start {{value0}}: {{value1}}',
+ {
+ value0: getAgentLabel(mostRecent.agent),
+ value1: getTerminalQuickCommandBody(mostRecent)
+ }
+ )
+ : translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.37e1bb90ce',
+ 'Run: {{value0}}',
+ { value0: getTerminalQuickCommandBody(mostRecent) }
+ )
+ : translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc',
+ 'Run quick command'
+ )}
@@ -276,7 +330,10 @@ export function TabBarQuickCommandsButton({
innerButtonBase,
'justify-center rounded-l-none rounded-r-md border-l border-border/60 px-1'
)}
- aria-label={translate("auto.components.tab.bar.TabBarQuickCommandsButton.b82e237a4b", "More quick commands")}
+ aria-label={translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.b82e237a4b',
+ 'More quick commands'
+ )}
>
@@ -290,7 +347,12 @@ export function TabBarQuickCommandsButton({
>
{totalVisible === 0 ? (
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.20bbd75896", "No commands")}
+
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.20bbd75896',
+ 'No commands'
+ )}
+
) : null}
{repoCommands.map(renderItem)}
{repoCommands.length > 0 && globalCommands.length > 0 ? (
@@ -311,7 +373,11 @@ export function TabBarQuickCommandsButton({
className="flex w-full items-center gap-2 rounded-[5px] px-2 py-1.5 text-[12px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831", "Add command")}
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831',
+ 'Add command'
+ )}
+
diff --git a/src/renderer/src/components/tab-bar/shell-icons.tsx b/src/renderer/src/components/tab-bar/shell-icons.tsx
index ab1469735b3..03930a5dfbe 100644
--- a/src/renderer/src/components/tab-bar/shell-icons.tsx
+++ b/src/renderer/src/components/tab-bar/shell-icons.tsx
@@ -73,7 +73,8 @@ function WslIcon({ size = 14 }: { size?: number }): React.JSX.Element {
fill="#1F1F1F"
fontFamily="system-ui, -apple-system, sans-serif"
>
- {translate("auto.components.tab.bar.shell.icons.e9b2e70613", "WSL")}
+ {translate('auto.components.tab.bar.shell.icons.e9b2e70613', 'WSL')}
+
)
}
@@ -97,7 +98,8 @@ function GitBashIcon({ size = 14 }: { size?: number }): React.JSX.Element {
fill="#ffffff"
fontFamily="system-ui, -apple-system, sans-serif"
>
- {translate("auto.components.tab.bar.shell.icons.d4ceaa227c", "Git")}
+ {translate('auto.components.tab.bar.shell.icons.d4ceaa227c', 'Git')}
+
)
}
diff --git a/src/renderer/src/components/tab-group/TabGroupPanel.tsx b/src/renderer/src/components/tab-group/TabGroupPanel.tsx
index bf54396e474..6b00012a20d 100644
--- a/src/renderer/src/components/tab-group/TabGroupPanel.tsx
+++ b/src/renderer/src/components/tab-group/TabGroupPanel.tsx
@@ -272,8 +272,14 @@ export default function TabGroupPanel({
{
event.stopPropagation()
}}
@@ -289,28 +295,32 @@ export default function TabGroupPanel({
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.ab1e2bff04", "Split Right")}
+ {translate('auto.components.tab.group.TabGroupPanel.ab1e2bff04', 'Split Right')}
+
{
commands.createSplitGroup('down')
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.4df2a06d36", "Split Down")}
+ {translate('auto.components.tab.group.TabGroupPanel.4df2a06d36', 'Split Down')}
+
{
commands.createSplitGroup('left')
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.30137df7d0", "Split Left")}
+ {translate('auto.components.tab.group.TabGroupPanel.30137df7d0', 'Split Left')}
+
{
commands.createSplitGroup('up')
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.0db2081805", "Split Up")}
+ {translate('auto.components.tab.group.TabGroupPanel.0db2081805', 'Split Up')}
+
{hasSplitGroups ? (
<>
@@ -321,7 +331,11 @@ export default function TabGroupPanel({
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.f7d6ce445e", "Close Group")}
+ {translate(
+ 'auto.components.tab.group.TabGroupPanel.f7d6ce445e',
+ 'Close Group'
+ )}
+
>
) : null}
@@ -366,16 +380,20 @@ export default function TabGroupPanel({
) : null}
{activeDropZone ? : null}
{activeTab &&
- activeTab.contentType !== "terminal" &&
- activeTab.contentType !== "browser" &&
- activeTab.contentType !== "simulator" && (
+ activeTab.contentType !== 'terminal' &&
+ activeTab.contentType !== 'browser' &&
+ activeTab.contentType !== 'simulator' && (
{/* Why: split groups render editor content inside a plain relative pane body
instead of the legacy flex column in Terminal.tsx. */}
- {translate("auto.components.tab.group.TabGroupPanel.814fb04c43", "Loading editor...")}
+ {translate(
+ 'auto.components.tab.group.TabGroupPanel.814fb04c43',
+ 'Loading editor...'
+ )}
+
}
>
diff --git a/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx b/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx
index 966245639a7..9ca464e8b60 100644
--- a/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx
+++ b/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx
@@ -29,15 +29,26 @@ export default function CloseTerminalDialog({
>
- {translate("auto.components.terminal.pane.CloseTerminalDialog.78b79d854d", "Close Terminal?")}
+
+ {translate(
+ 'auto.components.terminal.pane.CloseTerminalDialog.78b79d854d',
+ 'Close Terminal?'
+ )}
+
- {translate("auto.components.terminal.pane.CloseTerminalDialog.6b9a6975f8", "The terminal still has a running process. If you close the terminal, the process will be killed.")}
+ {translate(
+ 'auto.components.terminal.pane.CloseTerminalDialog.6b9a6975f8',
+ 'The terminal still has a running process. If you close the terminal, the process will be killed.'
+ )}
+
- {translate("auto.components.terminal.pane.CloseTerminalDialog.1d1a7a9c1f", "Cancel")}
+ {translate('auto.components.terminal.pane.CloseTerminalDialog.1d1a7a9c1f', 'Cancel')}
+
- {translate("auto.components.terminal.pane.CloseTerminalDialog.ebd2fa844d", "Close")}
+ {translate('auto.components.terminal.pane.CloseTerminalDialog.ebd2fa844d', 'Close')}
+
diff --git a/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx b/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx
index 2953674b7c8..80e950dd863 100644
--- a/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx
+++ b/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx
@@ -74,7 +74,10 @@ export function MobileDriverOverlay({
return (
{onCollapse && (
- {translate("auto.components.terminal.pane.MobileDriverOverlay.7cffad954c", "Collapse")}
+ {translate(
+ 'auto.components.terminal.pane.MobileDriverOverlay.7cffad954c',
+ 'Collapse'
+ )}
+
)}
{/* Focus is moved to this button only when no user input is active; see effect above. */}
- {translate("auto.components.terminal.pane.MobileDriverOverlay.c44659e09f", "Mobile driving")}
+ {translate(
+ 'auto.components.terminal.pane.MobileDriverOverlay.c44659e09f',
+ 'Mobile driving'
+ )}
+
- {translate("auto.components.terminal.pane.MobileDriverOverlay.c6460cf584", "Take back")}
+ {translate('auto.components.terminal.pane.MobileDriverOverlay.c6460cf584', 'Take back')}
+
)
}
diff --git a/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx b/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx
index e9afa311134..84148129289 100644
--- a/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx
@@ -73,27 +73,57 @@ export function TerminalAgentSessionForkDialog({
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.64e292e8e3", "Fork Agent Session")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.64e292e8e3',
+ 'Fork Agent Session'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.619b5a35d2", "Create a top-level workspace fork and start a fresh agent tab with captured context.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.619b5a35d2',
+ 'Create a top-level workspace fork and start a fresh agent tab with captured context.'
+ )}
+
-
{translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.620461df22", "Top-level fork")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.620461df22',
+ 'Top-level fork'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.0c8a8629b1", "The fork appears as its own workspace, not as a nested child. The new agent receives a bounded transcript as an editable draft.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.0c8a8629b1',
+ 'The fork appears as its own workspace, not as a nested child. The new agent receives a bounded transcript as an editable draft.'
+ )}
+
void handleCopyContext()}>
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.17fc841e59", "Copy context")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.17fc841e59',
+ 'Copy context'
+ )}
+
void handleStartFork()}>
- {busy ? translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.2b10412cfc", "Creating...") : translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.9d25de2920", "Create fork")}
+ {busy
+ ? translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.2b10412cfc',
+ 'Creating...'
+ )
+ : translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.9d25de2920',
+ 'Create fork'
+ )}
diff --git a/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx b/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx
index d421204c40a..9912a7bc0f6 100644
--- a/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx
@@ -118,7 +118,9 @@ export default function TerminalContextMenu({
)}
{command.label}
{!isTerminalAgentQuickCommand(command) && !command.appendEnter ? (
- {translate("auto.components.terminal.pane.TerminalContextMenu.c2f0b72b8d", "Insert")}
+
+ {translate('auto.components.terminal.pane.TerminalContextMenu.c2f0b72b8d', 'Insert')}
+
) : null}
)
@@ -169,16 +171,22 @@ export default function TerminalContextMenu({
>
- {translate("auto.components.terminal.pane.TerminalContextMenu.f3eeb1de13", "Copy")}{shortcuts.copy}
+ {translate('auto.components.terminal.pane.TerminalContextMenu.f3eeb1de13', 'Copy')}
+ {shortcuts.copy}
- {translate("auto.components.terminal.pane.TerminalContextMenu.0a917b591a", "Paste")}{shortcuts.paste}
+ {translate('auto.components.terminal.pane.TerminalContextMenu.0a917b591a', 'Paste')}
+ {shortcuts.paste}
- {translate("auto.components.terminal.pane.TerminalContextMenu.ec85df5914", "Quick Commands")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.ec85df5914',
+ 'Quick Commands'
+ )}
+
{hasQuickCommands ? (
<>
@@ -194,7 +202,12 @@ export default function TerminalContextMenu({
<>
{repoQuickCommands.length > 0 ? : null}
{repoQuickCommands.length > 0 ? (
- {translate("auto.components.terminal.pane.TerminalContextMenu.3ce594a4a0", "Global")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.3ce594a4a0',
+ 'Global'
+ )}
+
) : null}
{globalQuickCommands.map(renderQuickCommandItem)}
>
@@ -202,7 +215,11 @@ export default function TerminalContextMenu({
>
) : (
- {translate("auto.components.terminal.pane.TerminalContextMenu.9528a65ef8", "No quick commands")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.9528a65ef8',
+ 'No quick commands'
+ )}
+
)}
- {translate("auto.components.terminal.pane.TerminalContextMenu.0a82b0608c", "Add Quick Command…")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.0a82b0608c',
+ 'Add Quick Command…'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalContextMenu.8a7ddb8b8a", "Fork Agent Session…")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.8a7ddb8b8a',
+ 'Fork Agent Session…'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalContextMenu.20e565d865", "Split Terminal Right")}{shortcuts.splitRight}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.20e565d865',
+ 'Split Terminal Right'
+ )}
+ {shortcuts.splitRight}
- {translate("auto.components.terminal.pane.TerminalContextMenu.98bccf4fa2", "Split Terminal Down")}{shortcuts.splitDown}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.98bccf4fa2',
+ 'Split Terminal Down'
+ )}
+ {shortcuts.splitDown}
{canEqualizePaneSizes && (
- {translate("auto.components.terminal.pane.TerminalContextMenu.06c2b0f043", "Equalize Pane Sizes")}{showEqualizeShortcut ? (
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.06c2b0f043',
+ 'Equalize Pane Sizes'
+ )}
+ {showEqualizeShortcut ? (
{shortcuts.equalize}
) : null}
@@ -240,30 +277,51 @@ export default function TerminalContextMenu({
{canExpandPane && (
{menuPaneIsExpanded ? : }
- {menuPaneIsExpanded ? translate("auto.components.terminal.pane.TerminalContextMenu.df766809e0", "Collapse Pane") : translate("auto.components.terminal.pane.TerminalContextMenu.925f49f210", "Expand Pane")}
+ {menuPaneIsExpanded
+ ? translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.df766809e0',
+ 'Collapse Pane'
+ )
+ : translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.925f49f210',
+ 'Expand Pane'
+ )}
{shortcuts.expand}
)}
- {translate("auto.components.terminal.pane.TerminalContextMenu.39809d152f", "Set Title…")}
+ {translate('auto.components.terminal.pane.TerminalContextMenu.39809d152f', 'Set Title…')}
+
- {translate("auto.components.terminal.pane.TerminalContextMenu.2cf85a6a55", "Copy Pane ID")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.2cf85a6a55',
+ 'Copy Pane ID'
+ )}
+
{canClosePane && (
<>
- {translate("auto.components.terminal.pane.TerminalContextMenu.8c17d6786d", "Close Pane")}{shortcuts.close}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.8c17d6786d',
+ 'Close Pane'
+ )}
+ {shortcuts.close}
>
)}
- {translate("auto.components.terminal.pane.TerminalContextMenu.b4cdd9314e", "Clear Screen")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.b4cdd9314e',
+ 'Clear Screen'
+ )}
+
)
diff --git a/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx b/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx
index 7e1f6f226cf..a71cd881624 100644
--- a/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx
@@ -56,16 +56,27 @@ export function TerminalErrorToast({
{showDaemonRestart ? (
<>
{'\n'}
- {translate("auto.components.terminal.pane.TerminalErrorToast.cc6d997c65", "Restart the terminal daemon from here to clear stale daemon state.")}>
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.cc6d997c65',
+ 'Restart the terminal daemon from here to clear stale daemon state.'
+ )}
+ >
) : !ssh ? (
<>
{'\n'}
- {translate("auto.components.terminal.pane.TerminalErrorToast.5c8ce20be6", "If this persists, please")}{' '}
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.5c8ce20be6',
+ 'If this persists, please'
+ )}{' '}
- {translate("auto.components.terminal.pane.TerminalErrorToast.a7e2fd2699", "file an issue")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.a7e2fd2699',
+ 'file an issue'
+ )}
+
.
>
) : null}
@@ -86,7 +97,11 @@ export function TerminalErrorToast({
flexShrink: 0
}}
>
- {translate("auto.components.terminal.pane.TerminalErrorToast.e4aa243f8c", "Restart daemon")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.e4aa243f8c',
+ 'Restart daemon'
+ )}
+
) : null}
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.678c780a2c", "Disk space is unavailable")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.678c780a2c',
+ 'Disk space is unavailable'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.e2fcf07c0d", "Orca could not save this terminal session because local storage is full or not writable. Open the disk space analyzer to find workspace storage you can clean up.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.e2fcf07c0d',
+ 'Orca could not save this terminal session because local storage is full or not writable. Open the disk space analyzer to find workspace storage you can clean up.'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.38c282a2c4", "The analyzer opens directly from here. You can also open it later from the lower-left toolbox menu by choosing Space Analyzer.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.38c282a2c4',
+ 'The analyzer opens directly from here. You can also open it later from the lower-left toolbox menu by choosing Space Analyzer.'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.ae20d0ffc2", "Dismiss")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.ae20d0ffc2',
+ 'Dismiss'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.6bee0c8f17", "Open Disk Space Analyzer")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.6bee0c8f17',
+ 'Open Disk Space Analyzer'
+ )}
+
diff --git a/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts b/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts
index 8bc70b62211..127f40f7a99 100644
--- a/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts
+++ b/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts
@@ -11,24 +11,35 @@ export function showOsc52ClipboardBlockedToast(): void {
}
hasShownOsc52ClipboardBlockedToast = true
- toast.info(translate("auto.components.terminal.pane.osc52.clipboard.blocked.toast.89eaa3e80b", "Terminal clipboard write blocked"), {
- description:
- translate("auto.components.terminal.pane.osc52.clipboard.blocked.toast.7cf51f74fd", "Enable TUI clipboard writes in Terminal settings to copy from SSH, tmux, Neovim, or fzf."),
- duration: 12_000,
- action: {
- label: translate("auto.components.terminal.pane.osc52.clipboard.blocked.toast.97c98f1afe", "Open Setting"),
- onClick: () => {
- const store = useAppStore.getState()
- // Why: open the exact row instead of a generic Terminal page so the
- // remote-copy failure points to the setting named by the shell message.
- store.setSettingsSearchQuery('')
- store.openSettingsTarget({
- pane: 'terminal',
- repoId: null,
- sectionId: OSC52_CLIPBOARD_SETTING_ID
- })
- store.openSettingsPage()
+ toast.info(
+ translate(
+ 'auto.components.terminal.pane.osc52.clipboard.blocked.toast.89eaa3e80b',
+ 'Terminal clipboard write blocked'
+ ),
+ {
+ description: translate(
+ 'auto.components.terminal.pane.osc52.clipboard.blocked.toast.7cf51f74fd',
+ 'Enable TUI clipboard writes in Terminal settings to copy from SSH, tmux, Neovim, or fzf.'
+ ),
+ duration: 12_000,
+ action: {
+ label: translate(
+ 'auto.components.terminal.pane.osc52.clipboard.blocked.toast.97c98f1afe',
+ 'Open Setting'
+ ),
+ onClick: () => {
+ const store = useAppStore.getState()
+ // Why: open the exact row instead of a generic Terminal page so the
+ // remote-copy failure points to the setting named by the shell message.
+ store.setSettingsSearchQuery('')
+ store.openSettingsTarget({
+ pane: 'terminal',
+ repoId: null,
+ sectionId: OSC52_CLIPBOARD_SETTING_ID
+ })
+ store.openSettingsPage()
+ }
}
}
- })
+ )
}
diff --git a/src/renderer/src/components/terminal-pane/stale-agent-row.ts b/src/renderer/src/components/terminal-pane/stale-agent-row.ts
index acfcd5f5400..c08f176691e 100644
--- a/src/renderer/src/components/terminal-pane/stale-agent-row.ts
+++ b/src/renderer/src/components/terminal-pane/stale-agent-row.ts
@@ -10,9 +10,19 @@ export function dismissStaleAgentRowByKey(paneKey: string): void {
store.dropAgentStatus(paneKey)
store.dismissRetainedAgent(paneKey)
if (liveExisted || retainedExisted) {
- toast.info(translate("auto.components.terminal.pane.stale.agent.row.ad991ece5c", "Agent's pane is no longer available."), {
- id: translate("auto.components.terminal.pane.stale.agent.row.090d607412", "stale-agent-row-{{value0}}", { value0: paneKey })
- })
+ toast.info(
+ translate(
+ 'auto.components.terminal.pane.stale.agent.row.ad991ece5c',
+ "Agent's pane is no longer available."
+ ),
+ {
+ id: translate(
+ 'auto.components.terminal.pane.stale.agent.row.090d607412',
+ 'stale-agent-row-{{value0}}',
+ { value0: paneKey }
+ )
+ }
+ )
}
}
diff --git a/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts b/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
index cc41fc4f6e6..65c9ec93926 100644
--- a/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
+++ b/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
@@ -61,11 +61,23 @@ function getUsableForkBase(
async function copyForkContext(prompt: string, pane: ManagedPane): Promise {
try {
await window.api.ui.writeClipboardText(prompt)
- toast.message(translate("auto.components.terminal.pane.terminal.agent.session.fork.c00421d320", "Fork context copied. Launch an agent and paste it to start the fork."))
+ toast.message(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.c00421d320',
+ 'Fork context copied. Launch an agent and paste it to start the fork.'
+ )
+ )
pane.terminal.focus()
return true
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.terminal.pane.terminal.agent.session.fork.2317900211", "Failed to copy fork context."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.2317900211',
+ 'Failed to copy fork context.'
+ )
+ )
pane.terminal.focus()
return false
}
@@ -123,7 +135,12 @@ export function prepareAgentSessionForkFromPane({
})
if (!prompt) {
- toast.error(translate("auto.components.terminal.pane.terminal.agent.session.fork.046e8d853c", "No terminal context to fork"))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.046e8d853c',
+ 'No terminal context to fork'
+ )
+ )
pane.terminal.focus()
return null
}
@@ -146,13 +163,23 @@ export async function startAgentSessionFork(fork: PreparedAgentSessionFork): Pro
const store = useAppStore.getState()
const sourceWorktree = store.getKnownWorktreeById(fork.worktreeId)
if (!sourceWorktree) {
- toast.error(translate("auto.components.terminal.pane.terminal.agent.session.fork.f867385bb5", "Could not find the source workspace for this fork."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.f867385bb5',
+ 'Could not find the source workspace for this fork.'
+ )
+ )
return false
}
const sourceRepo = store.repos.find((repo) => repo.id === sourceWorktree.repoId)
const sourceBranch = getUsableForkBase(sourceWorktree, sourceRepo, fork.worktreeId)
if (!sourceBranch) {
- toast.error(translate("auto.components.terminal.pane.terminal.agent.session.fork.38e41edc6e", "This workspace cannot be forked into a git worktree."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.38e41edc6e',
+ 'This workspace cannot be forked into a git worktree.'
+ )
+ )
return false
}
const forkName = buildForkWorkspaceName(sourceWorktree.displayName || sourceBranch)
@@ -172,7 +199,14 @@ export async function startAgentSessionFork(fork: PreparedAgentSessionFork): Pro
fork.agent ?? undefined
)
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.terminal.pane.terminal.agent.session.fork.fd3d12a1e1", "Failed to create fork workspace."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.fd3d12a1e1',
+ 'Failed to create fork workspace.'
+ )
+ )
return false
}
const forkWorktreeId = created.worktree.id
@@ -204,7 +238,12 @@ export async function startAgentSessionFork(fork: PreparedAgentSessionFork): Pro
return copyAgentSessionForkContext(fork)
}
- toast.success(translate("auto.components.terminal.pane.terminal.agent.session.fork.88e34d00eb", "Top-level session fork opened in a new workspace"))
+ toast.success(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.88e34d00eb',
+ 'Top-level session fork opened in a new workspace'
+ )
+ )
return true
}
diff --git a/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts b/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts
index e86724203cc..966d4e0e9c1 100644
--- a/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts
+++ b/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts
@@ -69,7 +69,12 @@ export async function handleTerminalFileDrop(args: Args): Promise {
const activeRuntimeEnvironmentId = settings?.activeRuntimeEnvironmentId?.trim()
const worktreePath = resolveWorktreePath(worktreeId, cwd)
if (!worktreePath) {
- toast.error(translate("auto.components.terminal.pane.terminal.drop.handler.ce8248b835", "Worktree path not available."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.ce8248b835',
+ 'Worktree path not available.'
+ )
+ )
return
}
@@ -77,7 +82,11 @@ export async function handleTerminalFileDrop(args: Args): Promise {
const targetShell = getTerminalTargetShellForWorktreePath(worktreePath)
const destinationDir = joinRuntimeDropDir(worktreePath)
const pending = toast.loading(
- translate("auto.components.terminal.pane.terminal.drop.handler.29c031b49a", "Uploading {{value0}} file{{value1}} to runtime…", { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' })
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.29c031b49a',
+ 'Uploading {{value0}} file{{value1}} to runtime…',
+ { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' }
+ )
)
try {
const { results } = await importExternalPathsToRuntime(
@@ -117,7 +126,12 @@ export async function handleTerminalFileDrop(args: Args): Promise {
// silently paste local paths into a remote shell.
const connectionId = getConnectionId(worktreeId)
if (connectionId === undefined) {
- toast.error(translate("auto.components.terminal.pane.terminal.drop.handler.0c77693641", "Worktree not ready — try again in a moment."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.0c77693641',
+ 'Worktree not ready — try again in a moment.'
+ )
+ )
return
}
const isRemote = connectionId !== null
@@ -139,7 +153,11 @@ export async function handleTerminalFileDrop(args: Args): Promise {
}
const pending = toast.loading(
- translate("auto.components.terminal.pane.terminal.drop.handler.29c031b49a", "Uploading {{value0}} file{{value1}} to remote…", { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' })
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.29c031b49a',
+ 'Uploading {{value0}} file{{value1}} to remote…',
+ { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' }
+ )
)
try {
const { resolvedPaths, skipped, failed } = await window.api.fs.resolveDroppedPathsForAgent({
@@ -178,13 +196,27 @@ function reportUploadSkipsAndFailures(
const noun = skipped.length === 1 ? 'item' : 'items'
toast.message(
symlinkCount === skipped.length
- ? translate("auto.components.terminal.pane.terminal.drop.handler.53f015fd85", "Skipped {{value0}} symlink{{value1}}.", { value0: skipped.length, value1: skipped.length === 1 ? '' : 's' })
- : translate("auto.components.terminal.pane.terminal.drop.handler.53f015fd85", "Skipped {{value0}} {{value1}}.", { value0: skipped.length, value1: noun })
+ ? translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.53f015fd85',
+ 'Skipped {{value0}} symlink{{value1}}.',
+ { value0: skipped.length, value1: skipped.length === 1 ? '' : 's' }
+ )
+ : translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.53f015fd85',
+ 'Skipped {{value0}} {{value1}}.',
+ { value0: skipped.length, value1: noun }
+ )
)
}
if (failed.length > 0) {
const noun = failed.length === 1 ? 'file' : 'files'
- toast.error(translate("auto.components.terminal.pane.terminal.drop.handler.1e072f611e", "Failed to upload {{value0}} {{value1}}.", { value0: failed.length, value1: noun }))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.1e072f611e',
+ 'Failed to upload {{value0}} {{value1}}.',
+ { value0: failed.length, value1: noun }
+ )
+ )
}
}
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx
index 0cdd2a78dc1..85a008cd5f7 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx
@@ -25,9 +25,17 @@ export function TerminalQuickCommandActionToggle({
variant="outline"
>
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b5ea4d64f6", "Terminal Command")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b5ea4d64f6',
+ 'Terminal Command'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b0d58e37ed", "Agent Prompt")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b0d58e37ed',
+ 'Agent Prompt'
+ )}
+
)
}
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx
index 437948b7e69..ad45db4b08d 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx
@@ -11,15 +11,27 @@ export function TerminalQuickCommandAppendEnterSwitch({
return (
-
{translate("auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.5fa607d807", "Append Enter")}
+
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.5fa607d807',
+ 'Append Enter'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.c936c2d6d2", "Submit immediately instead of only inserting text.")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.c936c2d6d2',
+ 'Submit immediately instead of only inserting text.'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.28370f16b9", "Cancel")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.28370f16b9',
+ 'Cancel'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.2e2b958dfc", "Save")}{submitShortcutLabel}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.2e2b958dfc',
+ 'Save'
+ )}
+ {submitShortcutLabel}
)
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx
index e45d7bebeba..a337be4361e 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx
@@ -15,11 +15,19 @@ export function TerminalQuickCommandLabelField({
}: TerminalQuickCommandLabelFieldProps): React.JSX.Element {
return (
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.db17f1e41e", "Label")}
+
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.db17f1e41e',
+ 'Label'
+ )}
+
setDraft((current) => ({ ...current, label: event.target.value }))}
- placeholder={translate("auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.66ea254301", "Start dev server")}
+ placeholder={translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.66ea254301',
+ 'Start dev server'
+ )}
/>
)
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx
index 7a9f2ac8641..fe09ee6acb4 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx
@@ -49,7 +49,12 @@ export function TerminalQuickCommandScopeField({
}: TerminalQuickCommandScopeFieldProps): React.JSX.Element {
return (
-
{translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.c25cf350ef", "Scope")}
+
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.c25cf350ef',
+ 'Scope'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.b83efc79e2", "Global")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.b83efc79e2',
+ 'Global'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.3834d24243", "Project")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.3834d24243',
+ 'Project'
+ )}
+
- {selectedScope.type === "repo" && repos.length > 0 ? (
+ {selectedScope.type === 'repo' && repos.length > 0 ? (
@@ -112,7 +135,11 @@ export function TerminalQuickCommandScopeField({
{selectedRepoMissing ? (
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.2db6edede7", "Saving keeps the existing project scope unless you choose another.")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.2db6edede7',
+ 'Saving keeps the existing project scope unless you choose another.'
+ )}
+
) : null}
) : null}
diff --git a/src/renderer/src/components/ui/color-picker.tsx b/src/renderer/src/components/ui/color-picker.tsx
index a6dec56fe84..2ae3ba66d81 100644
--- a/src/renderer/src/components/ui/color-picker.tsx
+++ b/src/renderer/src/components/ui/color-picker.tsx
@@ -93,12 +93,18 @@ export function ColorPicker({
- {translate("auto.components.ui.color.picker.faa855a582", "Hex")}
+
+ {translate('auto.components.ui.color.picker.faa855a582', 'Hex')}
+
{swatchColor}
- {hasInvalidDraft ?
{translate("auto.components.ui.color.picker.ebcf6ba29e", "Invalid hex color.")}
: null}
+ {hasInvalidDraft ? (
+
+ {translate('auto.components.ui.color.picker.ebcf6ba29e', 'Invalid hex color.')}
+
+ ) : null}
diff --git a/src/renderer/src/components/ui/dialog.tsx b/src/renderer/src/components/ui/dialog.tsx
index 63b5434aac4..8b1badf9ab3 100644
--- a/src/renderer/src/components/ui/dialog.tsx
+++ b/src/renderer/src/components/ui/dialog.tsx
@@ -76,7 +76,9 @@ function DialogContent({
className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
-
{translate("auto.components.ui.dialog.f26c4baeda", "Close")}
+
+ {translate('auto.components.ui.dialog.f26c4baeda', 'Close')}
+
)}
@@ -111,7 +113,9 @@ function DialogFooter({
{children}
{showCloseButton && (
- {translate("auto.components.ui.dialog.f26c4baeda", "Close")}
+
+ {translate('auto.components.ui.dialog.f26c4baeda', 'Close')}
+
)}
diff --git a/src/renderer/src/components/ui/repo-multi-combobox.tsx b/src/renderer/src/components/ui/repo-multi-combobox.tsx
index 473bae28d70..0b89a5bda10 100644
--- a/src/renderer/src/components/ui/repo-multi-combobox.tsx
+++ b/src/renderer/src/components/ui/repo-multi-combobox.tsx
@@ -33,10 +33,18 @@ type RepoMultiComboboxProps = {
function renderTriggerLabel(repos: Repo[], selected: ReadonlySet): React.JSX.Element {
if (repos.length === 0) {
- return {translate("auto.components.ui.repo.multi.combobox.65a3dae41d", "No projects")}
+ return (
+
+ {translate('auto.components.ui.repo.multi.combobox.65a3dae41d', 'No projects')}
+
+ )
}
if (selected.size === repos.length) {
- return {translate("auto.components.ui.repo.multi.combobox.bfd8ce21c6", "All projects")}
+ return (
+
+ {translate('auto.components.ui.repo.multi.combobox.bfd8ce21c6', 'All projects')}
+
+ )
}
const selectedRepos = repos.filter((r) => selected.has(r.id))
const [first, second, ...rest] = selectedRepos
@@ -136,7 +144,10 @@ export default function RepoMultiCombobox({
- {translate("auto.components.ui.repo.multi.combobox.bfd8ce21c6", "All projects")}
+
+ {translate('auto.components.ui.repo.multi.combobox.bfd8ce21c6', 'All projects')}
+
- {translate("auto.components.ui.repo.multi.combobox.4471d4a1c0", "No projects match your search.")}
+
+ {translate(
+ 'auto.components.ui.repo.multi.combobox.4471d4a1c0',
+ 'No projects match your search.'
+ )}
+
{filteredRepos.map((repo) => {
const isSelected = selected.has(repo.id)
const isLastSelected = isSelected && selected.size <= 1
@@ -194,7 +212,8 @@ export default function RepoMultiCombobox({
{repo.connectionId && (
- {translate("auto.components.ui.repo.multi.combobox.286ce70256", "SSH")}
+ {translate('auto.components.ui.repo.multi.combobox.286ce70256', 'SSH')}
+
)}
{repo.path}
diff --git a/src/renderer/src/components/ui/sheet.tsx b/src/renderer/src/components/ui/sheet.tsx
index 161d2a25a75..0e722f1a4f5 100644
--- a/src/renderer/src/components/ui/sheet.tsx
+++ b/src/renderer/src/components/ui/sheet.tsx
@@ -104,7 +104,9 @@ function SheetContent({
className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
- {translate("auto.components.ui.sheet.1189e9fe0a", "Close")}
+
+ {translate('auto.components.ui.sheet.1189e9fe0a', 'Close')}
+
)}
diff --git a/src/renderer/src/components/ui/team-multi-combobox.tsx b/src/renderer/src/components/ui/team-multi-combobox.tsx
index 57ebfa47b7a..0007c389bc0 100644
--- a/src/renderer/src/components/ui/team-multi-combobox.tsx
+++ b/src/renderer/src/components/ui/team-multi-combobox.tsx
@@ -23,10 +23,18 @@ type TeamMultiComboboxProps = {
function renderTriggerLabel(teams: LinearTeam[], selected: ReadonlySet): React.JSX.Element {
if (teams.length === 0) {
- return {translate("auto.components.ui.team.multi.combobox.301f2a796e", "All teams")}
+ return (
+
+ {translate('auto.components.ui.team.multi.combobox.301f2a796e', 'All teams')}
+
+ )
}
if (selected.size === teams.length) {
- return {translate("auto.components.ui.team.multi.combobox.301f2a796e", "All teams")}
+ return (
+
+ {translate('auto.components.ui.team.multi.combobox.301f2a796e', 'All teams')}
+
+ )
}
const selectedTeams = teams.filter((t) => selected.has(t.id))
const [first, second, ...rest] = selectedTeams
@@ -120,7 +128,10 @@ export default function TeamMultiCombobox({
- {translate("auto.components.ui.team.multi.combobox.301f2a796e", "All teams")}
+
+ {translate('auto.components.ui.team.multi.combobox.301f2a796e', 'All teams')}
+
- {translate("auto.components.ui.team.multi.combobox.de83523bf9", "No teams match your search.")}
+
+ {translate(
+ 'auto.components.ui.team.multi.combobox.de83523bf9',
+ 'No teams match your search.'
+ )}
+
{filteredTeams.map((team) => {
const isSelected = selected.has(team.id)
const isLastSelected = isSelected && selected.size <= 1
diff --git a/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx b/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx
index 86faec53322..ccff6b69572 100644
--- a/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx
+++ b/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx
@@ -58,18 +58,30 @@ export default function WorkspaceSpacePage(): React.JSX.Element {
- {translate("auto.components.workspace.space.WorkspaceSpacePage.ecf72fdc3b", "Back")}
+ {translate('auto.components.workspace.space.WorkspaceSpacePage.ecf72fdc3b', 'Back')}
+
-
{translate("auto.components.workspace.space.WorkspaceSpacePage.45f6302dbc", "Space")}
- {translate("auto.components.workspace.space.WorkspaceSpacePage.e8d6ba11ab", "Beta")}
+
+ {translate(
+ 'auto.components.workspace.space.WorkspaceSpacePage.45f6302dbc',
+ 'Space'
+ )}
+
+
+ {translate('auto.components.workspace.space.WorkspaceSpacePage.e8d6ba11ab', 'Beta')}
+
- {translate("auto.components.workspace.space.WorkspaceSpacePage.8d0048e1cb", "Workspace disk usage and reclaimable worktree storage.")}
+ {translate(
+ 'auto.components.workspace.space.WorkspaceSpacePage.8d0048e1cb',
+ 'Workspace disk usage and reclaimable worktree storage.'
+ )}
+
diff --git a/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx b/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx
index 00d7598dc6d..ea10d9bccc8 100644
--- a/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx
+++ b/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx
@@ -45,8 +45,14 @@ export default function WorktreeCreationPanel({
{title}
@@ -61,9 +67,18 @@ export default function WorktreeCreationPanel({
{isError ? (
- {translate("auto.components.worktree.creation.WorktreeCreationPanel.ed2a664f8b", "Couldn’t create worktree")}
+
+ {translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.ed2a664f8b',
+ 'Couldn’t create worktree'
+ )}
+
- {entry.error ?? translate("auto.components.worktree.creation.WorktreeCreationPanel.767951265d", "Something went wrong while creating the worktree.")}
+ {entry.error ??
+ translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.767951265d',
+ 'Something went wrong while creating the worktree.'
+ )}
- {translate("auto.components.worktree.creation.WorktreeCreationPanel.34dd5ee38b", "Retry")}
+ {translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.34dd5ee38b',
+ 'Retry'
+ )}
+
- {translate("auto.components.worktree.creation.WorktreeCreationPanel.dabd226118", "Dismiss")}
+ {translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.dabd226118',
+ 'Dismiss'
+ )}
+
) : (
diff --git a/src/renderer/src/hooks/useAutomationDispatchEvents.ts b/src/renderer/src/hooks/useAutomationDispatchEvents.ts
index a4ef614ece4..cbc17bbf783 100644
--- a/src/renderer/src/hooks/useAutomationDispatchEvents.ts
+++ b/src/renderer/src/hooks/useAutomationDispatchEvents.ts
@@ -72,7 +72,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_unavailable',
workspaceId: run.workspaceId,
workspaceDisplayName: run.workspaceDisplayName ?? null,
- error: translate("auto.hooks.useAutomationDispatchEvents.386db94f3e", "The target project is no longer available.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.386db94f3e',
+ 'The target project is no longer available.'
+ )
})
return
}
@@ -87,7 +90,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_needs_interactive_auth',
workspaceId: dispatchWorkspaceId,
workspaceDisplayName: dispatchWorkspaceDisplayName,
- error: translate("auto.hooks.useAutomationDispatchEvents.16a21d6413", "SSH reconnect requires interactive credentials.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.16a21d6413',
+ 'SSH reconnect requires interactive credentials.'
+ )
})
return
}
@@ -117,7 +123,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_unavailable',
workspaceId: automation.workspaceId,
workspaceDisplayName: dispatchWorkspaceDisplayName,
- error: translate("auto.hooks.useAutomationDispatchEvents.59718b120b", "The target workspace is no longer available.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.59718b120b',
+ 'The target workspace is no longer available.'
+ )
})
return
}
@@ -170,7 +179,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_unavailable',
workspaceId: automation.workspaceId,
workspaceDisplayName: dispatchWorkspaceDisplayName,
- error: translate("auto.hooks.useAutomationDispatchEvents.59718b120b", "The target workspace is no longer available.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.59718b120b',
+ 'The target workspace is no longer available.'
+ )
})
return
}
diff --git a/src/renderer/src/hooks/useGlobalFileDrop.ts b/src/renderer/src/hooks/useGlobalFileDrop.ts
index 5b1ed3bd6ee..0d3039fbd44 100644
--- a/src/renderer/src/hooks/useGlobalFileDrop.ts
+++ b/src/renderer/src/hooks/useGlobalFileDrop.ts
@@ -41,7 +41,12 @@ export function useGlobalFileDrop(): void {
const runtimeEnvironmentId = dropSettings?.activeRuntimeEnvironmentId?.trim() || undefined
if (shouldUploadRemoteEditorFileDrop(dropSettings, connectionId)) {
if (!worktreePath) {
- toast.error(translate("auto.hooks.useGlobalFileDrop.245faa95b9", "No remote workspace path is available for dropped files."))
+ toast.error(
+ translate(
+ 'auto.hooks.useGlobalFileDrop.245faa95b9',
+ 'No remote workspace path is available for dropped files.'
+ )
+ )
return
}
void (async () => {
@@ -80,10 +85,20 @@ export function useGlobalFileDrop(): void {
)
}
if (results.some((result) => result.status !== 'imported')) {
- toast.error(translate("auto.hooks.useGlobalFileDrop.d720e2f855", "Some dropped files could not be uploaded."))
+ toast.error(
+ translate(
+ 'auto.hooks.useGlobalFileDrop.d720e2f855',
+ 'Some dropped files could not be uploaded.'
+ )
+ )
}
} catch {
- toast.error(translate("auto.hooks.useGlobalFileDrop.38c9f034ff", "Failed to upload dropped files."))
+ toast.error(
+ translate(
+ 'auto.hooks.useGlobalFileDrop.38c9f034ff',
+ 'Failed to upload dropped files.'
+ )
+ )
}
})()
return
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
index e3bf53d5413..429750daced 100644
--- a/src/renderer/src/i18n/locales/es.json
+++ b/src/renderer/src/i18n/locales/es.json
@@ -4901,12 +4901,12 @@
"95a0411b3e": "plantilla",
"175daba180": "Ejemplo",
"b20c5df6ca": "Agregue un archivo `orca.yaml` para habilitar los valores predeterminados de configuración, archivo o automatización de problemas compartidos para este repositorio. Plantilla de ejemplo:",
- "56f9a4a1d0": "Usando `orca.yaml`",
- "623e0c9f31": "No se pudo analizar `orca.yaml`",
- "5a67e4793d": "No se detectó `orca.yaml`",
- "07ba35bc68": "Comprueba la sangría bajo `scripts:`. Las claves de hook deben usar dos espacios y las líneas de comando deben usar cuatro.",
- "787ca433ef": "Define solo las claves compatibles: `scripts`, `setup`, `archive` y `issueCommand`.",
- "ecc73d9125": "Compara tu archivo con la plantilla funcional de abajo y copia esa estructura si es necesario.",
+ "56f9a4a1d0": "Using `orca.yaml`",
+ "623e0c9f31": "`orca.yaml` could not be parsed",
+ "5a67e4793d": "No `orca.yaml` detected",
+ "07ba35bc68": "Check the indentation under `scripts:`. Hook keys should use two spaces, and command lines should use four.",
+ "787ca433ef": "Define only the supported keys: `scripts`, `setup`, `archive`, and `issueCommand`.",
+ "ecc73d9125": "Compare your file against the working template below and copy that shape if needed.",
"925f9e0dc4": "texto-primer plano",
"0cc712b823": "El archivo de configuración principal existe en la raíz del repositorio, pero Orca aún no pudo analizar las definiciones de gancho admitidas.",
"c90b858573": "texto-ámbar-700 oscuro:texto-ámbar-300",
@@ -4948,13 +4948,7 @@
"2b6356e744": "Guardado",
"81057d5f71": "Ahorro...",
"da37d6f10e": "Copiar",
- "3149964b66": "copiado",
- "56f9a4a1d0": "Using `orca.yaml`",
- "623e0c9f31": "`orca.yaml` could not be parsed",
- "5a67e4793d": "No `orca.yaml` detected",
- "07ba35bc68": "Check the indentation under `scripts:`. Hook keys should use two spaces, and command lines should use four.",
- "787ca433ef": "Define only the supported keys: `scripts`, `setup`, `archive`, and `issueCommand`.",
- "ecc73d9125": "Compare your file against the working template below and copy that shape if needed."
+ "3149964b66": "copiado"
},
"RepositoryIconPicker": {
"2b7d27b93c": "Utilice el color del repositorio {{value0}}",
@@ -5211,7 +5205,11 @@
"fac59213fc": "Buscar temas integrados",
"cb330ef7f8": "de {{value0}}",
"c822571b2e": "coincidente con \"{{value0}}\"",
- "3119c012a5": "cadena"
+ "3119c012a5": "cadena",
+ "builtin_themes": "Built-in",
+ "imported_from": "Imported from {{value0}}",
+ "imported_themes": "Imported",
+ "search_terminal_themes": "Search terminal themes"
},
"SettingsSidebar": {
"e0900f83e7": "SSH",
@@ -5588,7 +5586,9 @@
"b739d2abfe": "Color divisor oscuro",
"7add204bd5": "Elija el tema del terminal utilizado en modo oscuro.",
"9499ad1dc4": "Tema oscuro",
- "f012172e21": "Elija el tema utilizado para los paneles de terminal en modo oscuro."
+ "f012172e21": "Elija el tema utilizado para los paneles de terminal en modo oscuro.",
+ "import_themes_title": "Import Themes",
+ "import_themes_description": "Imported themes are available in both the dark and light theme pickers."
},
"TerminalWindowSection": {
"1705318506": "color magenta ANSI",
@@ -7123,7 +7123,20 @@
"e989914ad6": "Familia de fuentes",
"33031c1465": "tamaño del texto",
"0fe0073f0c": "Tamaño de fuente de terminal predeterminado para nuevos paneles y actualizaciones en vivo.",
- "5930244899": "Tamaño de fuente"
+ "5930244899": "Tamaño de fuente",
+ "warp_import": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "keyword_warp": "warp",
+ "keyword_themes": "themes",
+ "keyword_yaml": "yaml"
+ },
+ "yaml_import": {
+ "title": "Import from YAML",
+ "description": "Import theme YAML files as Orca terminal themes.",
+ "keyword_yaml": "yaml",
+ "keyword_custom": "custom"
+ }
},
"windows": {
"search": {
@@ -7219,6 +7232,42 @@
"agent-generated-tab-title-copy": {
"19ad21615a": "Generar títulos de pestañas automáticamente",
"b036c7a409": "Derive nombres breves de pestañas estables a partir del primer mensaje de agente conocido. Los cambios de nombre manuales siempre ganan."
+ },
+ "WarpThemeImportModal": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "yaml_title": "Import theme YAML",
+ "yaml_description": "Import theme YAML files (Warp format) as Orca terminal themes.",
+ "yaml_no_themes_found": "No themes found in the selected files.",
+ "choose_file": "Choose File",
+ "choose_folder": "Choose Folder",
+ "loading": "Loading Warp themes...",
+ "found_theme_one": "Found 1 theme",
+ "found_theme_other": "Found {{value0}} themes",
+ "found_in_source": " in {{value0}}",
+ "clear_all": "Clear all",
+ "select_all": "Select all",
+ "colors_only": "Colors only",
+ "no_themes_found": "No custom Warp themes found.",
+ "builtin_themes_hint": "Warp's preloaded themes are part of the Warp app and can't be read from disk. Orca already includes most of them, like Dracula, Gruvbox, Solarized, and Tokyo Night.",
+ "choose_manually": "Choose a theme YAML file or folder to import manually.",
+ "skipped_files": "Skipped files",
+ "more_skipped_files": "{{value0}} more skipped files.",
+ "cancel": "Cancel",
+ "import_theme_one": "Import 1 Theme",
+ "import_theme_other": "Import {{value0}} Themes",
+ "import_themes": "Import Themes"
+ },
+ "useWarpThemeImport": {
+ "unknown_error": "Unknown error",
+ "imported_one": "Imported 1 theme",
+ "imported_other": "Imported {{value0}} themes",
+ "import_failed": "Failed to import themes",
+ "over_limit_one": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect 1 new theme and try again.",
+ "over_limit_other": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect {{value1}} new themes and try again."
+ },
+ "YamlThemeImportButton": {
+ "label": "Import from YAML"
}
},
"right": {
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 2270c43cb16..243637d8485 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -5190,7 +5190,11 @@
"fac59213fc": "내장 테마 검색",
"cb330ef7f8": "{{value0}} 중",
"c822571b2e": "\"{{value0}}\"과 일치",
- "3119c012a5": "문자열"
+ "3119c012a5": "문자열",
+ "builtin_themes": "Built-in",
+ "imported_from": "Imported from {{value0}}",
+ "imported_themes": "Imported",
+ "search_terminal_themes": "Search terminal themes"
},
"SettingsSidebar": {
"e0900f83e7": "SSH",
@@ -5567,7 +5571,9 @@
"b739d2abfe": "다크 디바이더 색상",
"7add204bd5": "다크 모드에서 사용되는 터미널 테마를 선택하세요.",
"9499ad1dc4": "어두운 테마",
- "f012172e21": "어두운 모드에서 터미널 패널에 사용되는 테마를 선택합니다."
+ "f012172e21": "어두운 모드에서 터미널 패널에 사용되는 테마를 선택합니다.",
+ "import_themes_title": "Import Themes",
+ "import_themes_description": "Imported themes are available in both the dark and light theme pickers."
},
"TerminalWindowSection": {
"1705318506": "ANSI 마젠타색",
@@ -7102,7 +7108,20 @@
"e989914ad6": "글꼴군",
"33031c1465": "텍스트 크기",
"0fe0073f0c": "새 창 및 라이브 업데이트의 기본 터미널 글꼴 크기입니다.",
- "5930244899": "글꼴 크기"
+ "5930244899": "글꼴 크기",
+ "warp_import": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "keyword_warp": "warp",
+ "keyword_themes": "themes",
+ "keyword_yaml": "yaml"
+ },
+ "yaml_import": {
+ "title": "Import from YAML",
+ "description": "Import theme YAML files as Orca terminal themes.",
+ "keyword_yaml": "yaml",
+ "keyword_custom": "custom"
+ }
},
"windows": {
"search": {
@@ -7213,6 +7232,42 @@
}
}
}
+ },
+ "WarpThemeImportModal": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "yaml_title": "Import theme YAML",
+ "yaml_description": "Import theme YAML files (Warp format) as Orca terminal themes.",
+ "yaml_no_themes_found": "No themes found in the selected files.",
+ "choose_file": "Choose File",
+ "choose_folder": "Choose Folder",
+ "loading": "Loading Warp themes...",
+ "found_theme_one": "Found 1 theme",
+ "found_theme_other": "Found {{value0}} themes",
+ "found_in_source": " in {{value0}}",
+ "clear_all": "Clear all",
+ "select_all": "Select all",
+ "colors_only": "Colors only",
+ "no_themes_found": "No custom Warp themes found.",
+ "builtin_themes_hint": "Warp's preloaded themes are part of the Warp app and can't be read from disk. Orca already includes most of them, like Dracula, Gruvbox, Solarized, and Tokyo Night.",
+ "choose_manually": "Choose a theme YAML file or folder to import manually.",
+ "skipped_files": "Skipped files",
+ "more_skipped_files": "{{value0}} more skipped files.",
+ "cancel": "Cancel",
+ "import_theme_one": "Import 1 Theme",
+ "import_theme_other": "Import {{value0}} Themes",
+ "import_themes": "Import Themes"
+ },
+ "useWarpThemeImport": {
+ "unknown_error": "Unknown error",
+ "imported_one": "Imported 1 theme",
+ "imported_other": "Imported {{value0}} themes",
+ "import_failed": "Failed to import themes",
+ "over_limit_one": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect 1 new theme and try again.",
+ "over_limit_other": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect {{value1}} new themes and try again."
+ },
+ "YamlThemeImportButton": {
+ "label": "Import from YAML"
}
},
"right": {
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index 61527811e59..cc3be1d6294 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -5190,7 +5190,11 @@
"fac59213fc": "搜索内置主题",
"cb330ef7f8": "{{value0}} 的",
"c822571b2e": "匹配“{{value0}}”",
- "3119c012a5": "字符串"
+ "3119c012a5": "字符串",
+ "builtin_themes": "Built-in",
+ "imported_from": "Imported from {{value0}}",
+ "imported_themes": "Imported",
+ "search_terminal_themes": "Search terminal themes"
},
"SettingsSidebar": {
"e0900f83e7": "SSH",
@@ -5567,7 +5571,9 @@
"b739d2abfe": "深色分隔线颜色",
"7add204bd5": "选择深色模式下使用的终端主题。",
"9499ad1dc4": "黑暗主题",
- "f012172e21": "选择深色模式下用于终端窗格的主题。"
+ "f012172e21": "选择深色模式下用于终端窗格的主题。",
+ "import_themes_title": "Import Themes",
+ "import_themes_description": "Imported themes are available in both the dark and light theme pickers."
},
"TerminalWindowSection": {
"1705318506": "ANSI 洋红色",
@@ -7102,7 +7108,20 @@
"e989914ad6": "字体家族",
"33031c1465": "文字大小",
"0fe0073f0c": "新窗格和实时更新的默认终端字体大小。",
- "5930244899": "字体大小"
+ "5930244899": "字体大小",
+ "warp_import": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "keyword_warp": "warp",
+ "keyword_themes": "themes",
+ "keyword_yaml": "yaml"
+ },
+ "yaml_import": {
+ "title": "Import from YAML",
+ "description": "Import theme YAML files as Orca terminal themes.",
+ "keyword_yaml": "yaml",
+ "keyword_custom": "custom"
+ }
},
"windows": {
"search": {
@@ -7213,6 +7232,42 @@
}
}
}
+ },
+ "WarpThemeImportModal": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "yaml_title": "Import theme YAML",
+ "yaml_description": "Import theme YAML files (Warp format) as Orca terminal themes.",
+ "yaml_no_themes_found": "No themes found in the selected files.",
+ "choose_file": "Choose File",
+ "choose_folder": "Choose Folder",
+ "loading": "Loading Warp themes...",
+ "found_theme_one": "Found 1 theme",
+ "found_theme_other": "Found {{value0}} themes",
+ "found_in_source": " in {{value0}}",
+ "clear_all": "Clear all",
+ "select_all": "Select all",
+ "colors_only": "Colors only",
+ "no_themes_found": "No custom Warp themes found.",
+ "builtin_themes_hint": "Warp's preloaded themes are part of the Warp app and can't be read from disk. Orca already includes most of them, like Dracula, Gruvbox, Solarized, and Tokyo Night.",
+ "choose_manually": "Choose a theme YAML file or folder to import manually.",
+ "skipped_files": "Skipped files",
+ "more_skipped_files": "{{value0}} more skipped files.",
+ "cancel": "Cancel",
+ "import_theme_one": "Import 1 Theme",
+ "import_theme_other": "Import {{value0}} Themes",
+ "import_themes": "Import Themes"
+ },
+ "useWarpThemeImport": {
+ "unknown_error": "Unknown error",
+ "imported_one": "Imported 1 theme",
+ "imported_other": "Imported {{value0}} themes",
+ "import_failed": "Failed to import themes",
+ "over_limit_one": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect 1 new theme and try again.",
+ "over_limit_other": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect {{value1}} new themes and try again."
+ },
+ "YamlThemeImportButton": {
+ "label": "Import from YAML"
}
},
"right": {
diff --git a/src/renderer/src/lib/agent-skill-cli-prerequisite.ts b/src/renderer/src/lib/agent-skill-cli-prerequisite.ts
index b4394f861cc..06dd6d76bc3 100644
--- a/src/renderer/src/lib/agent-skill-cli-prerequisite.ts
+++ b/src/renderer/src/lib/agent-skill-cli-prerequisite.ts
@@ -43,7 +43,14 @@ export async function ensureOrcaCliAvailableForAgentSkillTerminal({
return status
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.lib.agent.skill.cli.prerequisite.8d6eedf97e", "Failed to register the Orca CLI in PATH."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.lib.agent.skill.cli.prerequisite.8d6eedf97e',
+ 'Failed to register the Orca CLI in PATH.'
+ )
+ )
return null
}
}
@@ -64,25 +71,57 @@ function delay(ms: number): Promise
{
function showCliPrerequisiteWarning(status: CliInstallStatus): void {
if (!status.supported) {
- toast.warning(translate("auto.lib.agent.skill.cli.prerequisite.2db0bd7515", "Orca CLI registration is unavailable"), {
- description: status.detail ?? translate("auto.lib.agent.skill.cli.prerequisite.15cbedc3e3", "Install the Orca CLI before running agent skill setup.")
- })
+ toast.warning(
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.2db0bd7515',
+ 'Orca CLI registration is unavailable'
+ ),
+ {
+ description:
+ status.detail ??
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.15cbedc3e3',
+ 'Install the Orca CLI before running agent skill setup.'
+ )
+ }
+ )
return
}
if (status.state !== 'installed') {
- toast.warning(translate("auto.lib.agent.skill.cli.prerequisite.e99d7dc36f", "Orca CLI registration needs attention"), {
- description: status.detail ?? translate("auto.lib.agent.skill.cli.prerequisite.15cbedc3e3", "Install the Orca CLI before running agent skill setup.")
- })
+ toast.warning(
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.e99d7dc36f',
+ 'Orca CLI registration needs attention'
+ ),
+ {
+ description:
+ status.detail ??
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.15cbedc3e3',
+ 'Install the Orca CLI before running agent skill setup.'
+ )
+ }
+ )
return
}
if (!status.pathConfigured) {
// Why: the skill installer opens a real shell; agents only get the expected
// Orca affordances when that shell can resolve the Orca CLI command.
- toast.warning(translate("auto.lib.agent.skill.cli.prerequisite.79371593b0", "Orca CLI is not visible on PATH yet"), {
- description:
- status.detail ?? translate("auto.lib.agent.skill.cli.prerequisite.0f116999f1", "Restart your shell or add the Orca CLI directory to PATH before setup.")
- })
+ toast.warning(
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.79371593b0',
+ 'Orca CLI is not visible on PATH yet'
+ ),
+ {
+ description:
+ status.detail ??
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.0f116999f1',
+ 'Restart your shell or add the Orca CLI directory to PATH before setup.'
+ )
+ }
+ )
}
}
diff --git a/src/renderer/src/lib/ensure-simulator-tab.ts b/src/renderer/src/lib/ensure-simulator-tab.ts
index 5822ff6e938..7edeafb16bf 100644
--- a/src/renderer/src/lib/ensure-simulator-tab.ts
+++ b/src/renderer/src/lib/ensure-simulator-tab.ts
@@ -66,7 +66,7 @@ export function ensureSimulatorTab(
)
if (reusableRightGroupId) {
const tab = store.createUnifiedTab(worktreeId, 'simulator', {
- label: translate("auto.lib.ensure.simulator.tab.372d21d428", "Mobile Emulator"),
+ label: translate('auto.lib.ensure.simulator.tab.372d21d428', 'Mobile Emulator'),
targetGroupId: reusableRightGroupId,
activate: true
})
@@ -86,7 +86,7 @@ export function ensureSimulatorTab(
splitDirection: 'right'
},
{
- label: translate("auto.lib.ensure.simulator.tab.372d21d428", "Mobile Emulator"),
+ label: translate('auto.lib.ensure.simulator.tab.372d21d428', 'Mobile Emulator'),
activate: true
}
)
@@ -96,7 +96,7 @@ export function ensureSimulatorTab(
}
const tab = store.createUnifiedTab(worktreeId, 'simulator', {
- label: translate("auto.lib.ensure.simulator.tab.372d21d428", "Mobile Emulator"),
+ label: translate('auto.lib.ensure.simulator.tab.372d21d428', 'Mobile Emulator'),
targetGroupId: sourceGroupId,
activate: shouldSurface
})
diff --git a/src/renderer/src/lib/fix-checks-agent-launch.ts b/src/renderer/src/lib/fix-checks-agent-launch.ts
index c4e88a354e8..65db5771090 100644
--- a/src/renderer/src/lib/fix-checks-agent-launch.ts
+++ b/src/renderer/src/lib/fix-checks-agent-launch.ts
@@ -67,7 +67,12 @@ async function resolveSavedAgentOverride(
}
const detectedAgents = await detectAgentsForConnection(connectionId)
if (!isAgentAvailable(savedAgent, detectedAgents)) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.4c7f783a7a", "Saved checks agent is not available on this workspace host."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.4c7f783a7a',
+ 'Saved checks agent is not available on this workspace host.'
+ )
+ )
return { kind: 'blocked' }
}
return { kind: 'agent', agent: savedAgent }
@@ -84,7 +89,12 @@ async function pickExistingWorktreeAgent(
if (isAgentAvailable(savedAgent, detectedAgents)) {
return savedAgent
}
- toast.error(translate("auto.lib.fix.checks.agent.launch.4c7f783a7a", "Saved checks agent is not available on this workspace host."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.4c7f783a7a',
+ 'Saved checks agent is not available on this workspace host.'
+ )
+ )
return null
}
const settings = useAppStore.getState().settings
@@ -94,7 +104,12 @@ async function pickExistingWorktreeAgent(
disabledAgents: settings?.disabledTuiAgents
})
if (!agent) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.2ebf794906", "No enabled AI agent was detected on this workspace host."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.2ebf794906',
+ 'No enabled AI agent was detected on this workspace host.'
+ )
+ )
}
return agent
}
@@ -113,7 +128,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
{ basePrompt: args.basePrompt }
).trim()
if (!commandInput) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.9f00d7df0c", "Fix checks prompt is empty. Update Source Control AI settings."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.9f00d7df0c',
+ 'Fix checks prompt is empty. Update Source Control AI settings.'
+ )
+ )
return false
}
@@ -125,7 +145,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
if (targetWorktreeId) {
const targetWorktree = store.allWorktrees().find((worktree) => worktree.id === targetWorktreeId)
if (!targetWorktree) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.dfb4dd7c00", "Unable to find the workspace attached to these checks."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.dfb4dd7c00',
+ 'Unable to find the workspace attached to these checks.'
+ )
+ )
return false
}
const targetConnectionId = getConnectionId(targetWorktreeId) ?? repo?.connectionId ?? null
@@ -142,7 +167,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
worktreePath: targetWorktree.path
})
if (!launchPlatform) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.822bf52295", "Unable to resolve the workspace launch platform."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.822bf52295',
+ 'Unable to resolve the workspace launch platform.'
+ )
+ )
return false
}
const agentArgsPlan = planAgentCliArgsSuffix(
@@ -154,7 +184,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
return false
}
if (!activateAndRevealWorktree(targetWorktreeId)) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.03c1d61f83", "Unable to open the workspace attached to these checks."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.03c1d61f83',
+ 'Unable to open the workspace attached to these checks.'
+ )
+ )
return false
}
const result = launchAgentInNewTab({
@@ -168,7 +203,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
launchSource: args.launchSource
})
if (!result) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.fb6c294e85", "Could not build the agent launch command."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.fb6c294e85',
+ 'Could not build the agent launch command.'
+ )
+ )
return false
}
if (result.tabId) {
@@ -178,7 +218,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
}
if (!args.item || !args.openModalFallback) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.027228a06b", "Unable to find a workspace for these checks."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.027228a06b',
+ 'Unable to find a workspace for these checks.'
+ )
+ )
return false
}
diff --git a/src/renderer/src/lib/floating-workspace-tab-creation.ts b/src/renderer/src/lib/floating-workspace-tab-creation.ts
index 5b119df89c1..12814ca7813 100644
--- a/src/renderer/src/lib/floating-workspace-tab-creation.ts
+++ b/src/renderer/src/lib/floating-workspace-tab-creation.ts
@@ -69,7 +69,7 @@ export async function createFloatingWorkspaceBrowserTab(
}
return store.createBrowserTab(FLOATING_TERMINAL_WORKTREE_ID, url, {
- title: translate("auto.lib.floating.workspace.tab.creation.f3785eddc2", "New Browser Tab"),
+ title: translate('auto.lib.floating.workspace.tab.creation.f3785eddc2', 'New Browser Tab'),
focusAddressBar: true,
targetGroupId
})
diff --git a/src/renderer/src/lib/launch-agent-background-session.ts b/src/renderer/src/lib/launch-agent-background-session.ts
index 11fcadd8bf5..6128b354e0e 100644
--- a/src/renderer/src/lib/launch-agent-background-session.ts
+++ b/src/renderer/src/lib/launch-agent-background-session.ts
@@ -257,7 +257,12 @@ export async function launchAgentBackgroundSession(
agent,
submit: true,
onTimeout: () => {
- toast.message(translate("auto.lib.launch.agent.background.session.4ca0651d56", "Your automation prompt wasn't sent — open the workspace and paste it."))
+ toast.message(
+ translate(
+ 'auto.lib.launch.agent.background.session.4ca0651d56',
+ "Your automation prompt wasn't sent — open the workspace and paste it."
+ )
+ )
track('agent_error', {
error_class: 'paste_readiness_timeout',
agent_kind: tuiAgentToAgentKind(agent)
diff --git a/src/renderer/src/lib/launch-agent-in-new-tab.ts b/src/renderer/src/lib/launch-agent-in-new-tab.ts
index 33752db7bf6..7eacb32e70a 100644
--- a/src/renderer/src/lib/launch-agent-in-new-tab.ts
+++ b/src/renderer/src/lib/launch-agent-in-new-tab.ts
@@ -232,7 +232,13 @@ export function launchAgentInNewTab(args: LaunchAgentInNewTabArgs): LaunchAgentI
// exists; keep pruning stale local rows until the snapshot mirrors.
removeStaleLocalAgentTabsForWebHostLaunch(worktreeId)
if (!created) {
- toast.error(translate("auto.lib.launch.agent.in.new.tab.11cce5cc77", "Could not launch {{value0}} in a new terminal.", { value0: agent }))
+ toast.error(
+ translate(
+ 'auto.lib.launch.agent.in.new.tab.11cce5cc77',
+ 'Could not launch {{value0}} in a new terminal.',
+ { value0: agent }
+ )
+ )
return
}
store.setActiveTabType('terminal')
@@ -308,7 +314,13 @@ export function launchAgentInNewTab(args: LaunchAgentInNewTabArgs): LaunchAgentI
return
}
const label = submitPastedPrompt ? 'prompt' : 'notes'
- toast.message(translate("auto.lib.launch.agent.in.new.tab.a5a1f7033f", "Your {{value0}} wasn't sent — paste it once the agent is ready.", { value0: label }))
+ toast.message(
+ translate(
+ 'auto.lib.launch.agent.in.new.tab.a5a1f7033f',
+ "Your {{value0}} wasn't sent — paste it once the agent is ready.",
+ { value0: label }
+ )
+ )
track('agent_error', {
error_class: 'paste_readiness_timeout',
agent_kind: tuiAgentToAgentKind(agent)
diff --git a/src/renderer/src/lib/launch-work-item-direct-agent.ts b/src/renderer/src/lib/launch-work-item-direct-agent.ts
index 8e592b49346..065c093e95f 100644
--- a/src/renderer/src/lib/launch-work-item-direct-agent.ts
+++ b/src/renderer/src/lib/launch-work-item-direct-agent.ts
@@ -47,7 +47,11 @@ export async function pasteDirectWorkItemDraftWhenAgentReady(args: {
onTimeout: () => {
const label = submit ? 'prompt' : 'work item context'
toast.message(
- translate("auto.lib.launch.work.item.direct.agent.ceeeb509b5", "Agent took too long to start. The workspace is ready — paste the {{value0}} when the agent is idle.", { value0: label })
+ translate(
+ 'auto.lib.launch.work.item.direct.agent.ceeeb509b5',
+ 'Agent took too long to start. The workspace is ready — paste the {{value0}} when the agent is idle.',
+ { value0: label }
+ )
)
// Why: process-startup timeout has no v1 enum slot; the `unknown` slice
// on the dashboard is the trigger to add one.
diff --git a/src/renderer/src/lib/local-path-open-guard.ts b/src/renderer/src/lib/local-path-open-guard.ts
index 23b3ab959e1..7fed28d8e10 100644
--- a/src/renderer/src/lib/local-path-open-guard.ts
+++ b/src/renderer/src/lib/local-path-open-guard.ts
@@ -12,5 +12,10 @@ export function isLocalPathOpenBlocked(
export function showLocalPathOpenBlockedToast(): void {
// Why: local OS reveal/open actions receive client filesystem paths. Remote
// runtime and SSH paths belong to another machine, not this client.
- toast.error(translate("auto.lib.local.path.open.guard.edc1908653", "Opening remote paths in the local OS is not available."))
+ toast.error(
+ translate(
+ 'auto.lib.local.path.open.guard.edc1908653',
+ 'Opening remote paths in the local OS is not available.'
+ )
+ )
}
diff --git a/src/renderer/src/lib/resume-sleeping-agent-session.ts b/src/renderer/src/lib/resume-sleeping-agent-session.ts
index 3664eb99a12..585d41dd498 100644
--- a/src/renderer/src/lib/resume-sleeping-agent-session.ts
+++ b/src/renderer/src/lib/resume-sleeping-agent-session.ts
@@ -45,7 +45,12 @@ function launchSleepingAgentSession(record: SleepingAgentSessionRecord): boolean
platform: getResumeLaunchPlatform(record.worktreeId)
})
if (!startupPlan) {
- toast.error(translate("auto.lib.resume.sleeping.agent.session.f235f604fd", "This agent session cannot be resumed."))
+ toast.error(
+ translate(
+ 'auto.lib.resume.sleeping.agent.session.f235f604fd',
+ 'This agent session cannot be resumed.'
+ )
+ )
return false
}
diff --git a/src/renderer/src/lib/source-control-agent-action-plan.ts b/src/renderer/src/lib/source-control-agent-action-plan.ts
index 88af0afccf3..ca5ac2a54a6 100644
--- a/src/renderer/src/lib/source-control-agent-action-plan.ts
+++ b/src/renderer/src/lib/source-control-agent-action-plan.ts
@@ -39,18 +39,42 @@ export function planSourceControlAgentActionLaunch(args: {
}): SourceControlLaunchPlanResult {
const agent = args.agent
if (!agent) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.a7ac8717c7", "Choose an agent before starting.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.a7ac8717c7',
+ 'Choose an agent before starting.'
+ )
+ }
}
if (!isTuiAgentEnabled(agent, args.disabledAgents)) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.b96e091fc9", "The selected agent is disabled in Settings.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.b96e091fc9',
+ 'The selected agent is disabled in Settings.'
+ )
+ }
}
if (!args.detectedAgents.includes(agent)) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.8eb541cc83", "The selected agent was not detected on this workspace host.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.8eb541cc83',
+ 'The selected agent was not detected on this workspace host.'
+ )
+ }
}
const trimmedInput = args.commandInput.trim()
if (!trimmedInput) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.46f1a2c9bd", "Command input is empty.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.46f1a2c9bd',
+ 'Command input is empty.'
+ )
+ }
}
const cmdOverrides = args.cmdOverrides ?? {}
@@ -124,7 +148,13 @@ export function planSourceControlAgentActionLaunch(args: {
}
if (!startupPlan) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.3f0ea9aa0d", "Could not build the agent launch command.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.3f0ea9aa0d',
+ 'Could not build the agent launch command.'
+ )
+ }
}
const summary =
diff --git a/src/renderer/src/lib/source-control-generation-plan.ts b/src/renderer/src/lib/source-control-generation-plan.ts
index e3b5db94a57..2f76fd62927 100644
--- a/src/renderer/src/lib/source-control-generation-plan.ts
+++ b/src/renderer/src/lib/source-control-generation-plan.ts
@@ -60,7 +60,13 @@ export function planSourceControlTextGeneration(
)
: SYNTHETIC_BASE_PROMPTS[actionId]
if (!prompt.trim()) {
- return { ok: false, error: translate("auto.lib.source.control.generation.plan.dc480d5897", "Command input is empty.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.generation.plan.dc480d5897',
+ 'Command input is empty.'
+ )
+ }
}
const planned = planCommitMessageGeneration(params, prompt)
if (!planned.ok) {
diff --git a/src/renderer/src/lib/sparse-preset-draft.ts b/src/renderer/src/lib/sparse-preset-draft.ts
index 1e4d2db8a71..56c30f57986 100644
--- a/src/renderer/src/lib/sparse-preset-draft.ts
+++ b/src/renderer/src/lib/sparse-preset-draft.ts
@@ -16,7 +16,10 @@ export function parseSparsePresetDirectories(value: string): SparsePresetDirecto
if (rawEntries.some(isAbsoluteSparseDirectoryPath)) {
return {
directories: [],
- error: translate("auto.lib.sparse.preset.draft.5915a0a1f6", "Use repo-relative directories, not root, absolute paths, or parent segments.")
+ error: translate(
+ 'auto.lib.sparse.preset.draft.5915a0a1f6',
+ 'Use repo-relative directories, not root, absolute paths, or parent segments.'
+ )
}
}
@@ -25,14 +28,17 @@ export function parseSparsePresetDirectories(value: string): SparsePresetDirecto
if (directories.length === 0) {
return {
directories,
- error: translate("auto.lib.sparse.preset.draft.efc05d1820", "Add at least one directory.")
+ error: translate('auto.lib.sparse.preset.draft.efc05d1820', 'Add at least one directory.')
}
}
if (directories.some((entry) => entry === '.' || entry.split('/').includes('..'))) {
return {
directories: [],
- error: translate("auto.lib.sparse.preset.draft.5915a0a1f6", "Use repo-relative directories, not root, absolute paths, or parent segments.")
+ error: translate(
+ 'auto.lib.sparse.preset.draft.5915a0a1f6',
+ 'Use repo-relative directories, not root, absolute paths, or parent segments.'
+ )
}
}
diff --git a/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx b/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx
index 768a73820c4..0e1c9e04634 100644
--- a/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx
+++ b/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx
@@ -64,23 +64,32 @@ export function showTerminalShortcutCaptureNotification({
)
// Why: this toast stays up longer than normal, so keep it compact while still
// exposing the captured shortcut and the edit path.
- toast.message(translate("auto.lib.terminal.shortcut.capture.notification.141ad6c004", "Terminal shortcut handled"), {
- description: `${definition.title} (${bindingLabel})`,
- // Why: this is the user's one-time rebind path for a captured shortcut; it
- // needs enough reading time without becoming persistent chrome.
- duration: NOTICE_DURATION_MS,
- dismissible: true,
- className: '!w-[420px] !max-w-[calc(100vw-2rem)] !gap-2 !py-2 !pl-3 !pr-2',
- classNames: {
- content: 'min-w-0 flex-1 !gap-0.5',
- title: 'truncate !leading-5',
- description: 'truncate !leading-4',
- actionButton: '!h-7 !shrink-0 !rounded-md !px-2.5'
- },
- icon: ,
- action: {
- label: translate("auto.lib.terminal.shortcut.capture.notification.b0536028c9", "Open Shortcuts"),
- onClick: openShortcutSettings
+ toast.message(
+ translate(
+ 'auto.lib.terminal.shortcut.capture.notification.141ad6c004',
+ 'Terminal shortcut handled'
+ ),
+ {
+ description: `${definition.title} (${bindingLabel})`,
+ // Why: this is the user's one-time rebind path for a captured shortcut; it
+ // needs enough reading time without becoming persistent chrome.
+ duration: NOTICE_DURATION_MS,
+ dismissible: true,
+ className: '!w-[420px] !max-w-[calc(100vw-2rem)] !gap-2 !py-2 !pl-3 !pr-2',
+ classNames: {
+ content: 'min-w-0 flex-1 !gap-0.5',
+ title: 'truncate !leading-5',
+ description: 'truncate !leading-4',
+ actionButton: '!h-7 !shrink-0 !rounded-md !px-2.5'
+ },
+ icon: ,
+ action: {
+ label: translate(
+ 'auto.lib.terminal.shortcut.capture.notification.b0536028c9',
+ 'Open Shortcuts'
+ ),
+ onClick: openShortcutSettings
+ }
}
- })
+ )
}
diff --git a/src/renderer/src/lib/workspace-create-error-format.ts b/src/renderer/src/lib/workspace-create-error-format.ts
index 89ed71576b3..d33f0d066fe 100644
--- a/src/renderer/src/lib/workspace-create-error-format.ts
+++ b/src/renderer/src/lib/workspace-create-error-format.ts
@@ -12,8 +12,11 @@ export function formatWorkspaceCreateError(error: unknown): WorkspaceCreateError
if (message.toLowerCase().includes(MISSING_BASE_REF_ANCHOR)) {
return {
- title: translate("auto.lib.workspace.create.error.format.64555d0014", "No base branch found"),
- message: translate("auto.lib.workspace.create.error.format.37cf0bc991", "Orca could not resolve a usable base ref for this workspace."),
+ title: translate('auto.lib.workspace.create.error.format.64555d0014', 'No base branch found'),
+ message: translate(
+ 'auto.lib.workspace.create.error.format.37cf0bc991',
+ 'Orca could not resolve a usable base ref for this workspace.'
+ ),
help: 'Create an initial commit (for example on main), or select an existing branch in Create From, then try again.'
}
}
diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx
index e74ab1406e8..69e07a61aa0 100644
--- a/src/renderer/src/main.tsx
+++ b/src/renderer/src/main.tsx
@@ -41,7 +41,10 @@ createRoot(rootElement).render(
boundaryId="app.root"
surface="app-root"
title={translate('app.recoverableError.rootTitle', 'Orca hit a renderer error.')}
- description={translate('app.recoverableError.rootDescription', 'The app shell could not finish rendering. Retry to remount it, or relaunch Orca if the error persists.')}
+ description={translate(
+ 'app.recoverableError.rootDescription',
+ 'The app shell could not finish rendering. Retry to remount it, or relaunch Orca if the error persists.'
+ )}
>
diff --git a/src/renderer/src/store/slices/browser.test.ts b/src/renderer/src/store/slices/browser.test.ts
index 989a0d9b614..d07fa741299 100644
--- a/src/renderer/src/store/slices/browser.test.ts
+++ b/src/renderer/src/store/slices/browser.test.ts
@@ -38,6 +38,8 @@ function createTestStore() {
(...a) =>
({
settings: { activeRuntimeEnvironmentId: null } as AppState['settings'],
+ activeWorktreeId: 'wt-1',
+ browserDefaultUrl: 'about:blank',
unifiedTabsByWorktree: {},
tabBarOrderByWorktree: {},
tabsByWorktree: {},
@@ -49,6 +51,7 @@ function createTestStore() {
closeUnifiedTab: vi.fn(),
activateTab: vi.fn(),
setTabLabel: vi.fn(),
+ recordFeatureInteraction: vi.fn(),
...createBrowserSlice(...a)
}) as unknown as AppState
)
@@ -143,6 +146,19 @@ function makeAnnotation(pageId: string, id = 'annotation-1'): BrowserPageAnnotat
}
describe('createBrowserSlice annotations', () => {
+ it('records browser-tab-created only for the explicit new-tab action', async () => {
+ const store = createTestStore()
+
+ store.getState().createBrowserTab('wt-1', 'https://example.com')
+ expect(store.getState().recordFeatureInteraction).not.toHaveBeenCalledWith(
+ 'browser-tab-created'
+ )
+
+ await store.getState().openNewBrowserTabInActiveWorkspace('group-1')
+
+ expect(store.getState().recordFeatureInteraction).toHaveBeenCalledWith('browser-tab-created')
+ })
+
it('clears page annotations when the browser page URL changes', () => {
const store = createTestStore()
const tab = store.getState().createBrowserTab('wt-1', 'https://example.com')
diff --git a/src/renderer/src/store/slices/browser.ts b/src/renderer/src/store/slices/browser.ts
index c04bf89f9ff..19c4de9fb2a 100644
--- a/src/renderer/src/store/slices/browser.ts
+++ b/src/renderer/src/store/slices/browser.ts
@@ -298,7 +298,7 @@ function mirrorWorkspaceFromActivePage(
activePageId: null,
pageIds: pages.map((page) => page.id),
url: 'about:blank',
- title: translate("auto.store.slices.browser.08fc23631d", "Browser"),
+ title: translate('auto.store.slices.browser.08fc23631d', 'Browser'),
loading: false,
faviconUrl: null,
canGoBack: false,
@@ -542,13 +542,15 @@ export const createBrowserSlice: StateCreator =
url: defaultUrl,
targetGroupId: groupId
})
+ get().recordFeatureInteraction('browser-tab-created')
return
}
get().createBrowserTab(worktreeId, defaultUrl, {
- title: translate("auto.store.slices.browser.d175274b6d", "New Browser Tab"),
+ title: translate('auto.store.slices.browser.d175274b6d', 'New Browser Tab'),
focusAddressBar: true,
targetGroupId: groupId
})
+ get().recordFeatureInteraction('browser-tab-created')
},
closeBrowserTab: (tabId) => {
diff --git a/src/renderer/src/store/slices/editor.test.ts b/src/renderer/src/store/slices/editor.test.ts
index 13fc6b7d516..03b87fd3bed 100644
--- a/src/renderer/src/store/slices/editor.test.ts
+++ b/src/renderer/src/store/slices/editor.test.ts
@@ -34,6 +34,7 @@ function createEditorStore(): StoreApi {
browserTabsByWorktree: {},
activeBrowserTabId: null,
activeBrowserTabIdByWorktree: {},
+ recordFeatureInteraction: vi.fn(),
...createEditorSlice(...(args as Parameters))
})) as unknown as StoreApi
}
@@ -46,6 +47,7 @@ function createEditorTabsStore(): StoreApi {
browserTabsByWorktree: {},
activeBrowserTabId: null,
activeBrowserTabIdByWorktree: {},
+ recordFeatureInteraction: vi.fn(),
...createTabsSlice(...(args as Parameters)),
...createEditorSlice(...(args as Parameters))
})) as unknown as StoreApi
@@ -66,6 +68,22 @@ function ownedEditorFileId(
}
describe('createEditorSlice right sidebar state', () => {
+ it('does not record markdown-file-created when opening an existing markdown file', () => {
+ const store = createEditorStore()
+
+ store.getState().openFile({
+ filePath: '/repo/docs/existing.md',
+ relativePath: 'docs/existing.md',
+ worktreeId: 'wt-1',
+ language: 'markdown',
+ mode: 'edit'
+ })
+
+ expect(store.getState().recordFeatureInteraction).not.toHaveBeenCalledWith(
+ 'markdown-file-created'
+ )
+ })
+
it('right sidebar is closed by default', () => {
const store = createEditorStore()
expect(store.getState().rightSidebarOpen).toBe(false)
diff --git a/src/renderer/src/store/slices/editor.ts b/src/renderer/src/store/slices/editor.ts
index bb6bc010da1..8a70a8477d5 100644
--- a/src/renderer/src/store/slices/editor.ts
+++ b/src/renderer/src/store/slices/editor.ts
@@ -1705,6 +1705,7 @@ export const createEditorSlice: StateCreator = (s
return
}
get().openFile(fileInfo, { preview: false, targetGroupId: groupId })
+ get().recordFeatureInteraction('markdown-file-created')
} catch (err) {
toast.error(extractIpcErrorMessage(err, 'Failed to create untitled markdown file.'))
}
@@ -3679,11 +3680,19 @@ export const createEditorSlice: StateCreator = (s
try {
stats = await statRuntimePath(fileContext, target.absolutePath)
} catch {
- toast.error(translate("auto.store.slices.editor.f2e00db373", "File not found: {{value0}}", { value0: target.relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.f2e00db373', 'File not found: {{value0}}', {
+ value0: target.relativePath
+ })
+ )
return
}
if (stats.isDirectory) {
- toast.error(translate("auto.store.slices.editor.51f15c37d3", "Cannot open directory: {{value0}}", { value0: target.relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.51f15c37d3', 'Cannot open directory: {{value0}}', {
+ value0: target.relativePath
+ })
+ )
return
}
}
@@ -3716,11 +3725,19 @@ export const createEditorSlice: StateCreator = (s
try {
stats = await statRuntimePath(fileContext, absolutePath)
} catch {
- toast.error(translate("auto.store.slices.editor.f2e00db373", "File not found: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.f2e00db373', 'File not found: {{value0}}', {
+ value0: relativePath
+ })
+ )
return
}
if (stats.isDirectory) {
- toast.error(translate("auto.store.slices.editor.51f15c37d3", "Cannot open directory: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.51f15c37d3', 'Cannot open directory: {{value0}}', {
+ value0: relativePath
+ })
+ )
return
}
@@ -3988,7 +4005,10 @@ function toOpenConflictMetadata(entry: GitStatusEntry): OpenConflictMetadata | u
conflictKind: entry.conflictKind,
conflictStatus: entry.conflictStatus,
conflictStatusSource: entry.conflictStatusSource,
- message: translate("auto.store.slices.editor.dcb521ed29", "This file is in a conflict state, but no working-tree file is available to edit."),
+ message: translate(
+ 'auto.store.slices.editor.dcb521ed29',
+ 'This file is in a conflict state, but no working-tree file is available to edit.'
+ ),
guidance: 'Resolve the conflict in Git or restore one side before reopening it.'
}
}
diff --git a/src/renderer/src/store/slices/repos.ts b/src/renderer/src/store/slices/repos.ts
index 61618009e39..2488cd99081 100644
--- a/src/renderer/src/store/slices/repos.ts
+++ b/src/renderer/src/store/slices/repos.ts
@@ -285,9 +285,12 @@ export const createRepoSlice: StateCreator = (set,
return result
} catch (err) {
console.error('Failed to import nested repos:', err)
- toast.error(translate("auto.store.slices.repos.6d3318e813", "Failed to import repositories"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate('auto.store.slices.repos.6d3318e813', 'Failed to import repositories'),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
return null
}
},
@@ -453,18 +456,25 @@ export const createRepoSlice: StateCreator = (set,
return { repos: [...s.repos, repo] }
})
if (alreadyAdded) {
- toast.info(translate("auto.store.slices.repos.a8e4b3af5b", "Project already added"), { description: repo.displayName })
- } else {
- toast.success(isGitRepoKind(repo) ? translate("auto.store.slices.repos.8bb3ad7935", "Project added") : translate("auto.store.slices.repos.90d129b48b", "Folder added"), {
+ toast.info(translate('auto.store.slices.repos.a8e4b3af5b', 'Project already added'), {
description: repo.displayName
})
+ } else {
+ toast.success(
+ isGitRepoKind(repo)
+ ? translate('auto.store.slices.repos.8bb3ad7935', 'Project added')
+ : translate('auto.store.slices.repos.90d129b48b', 'Folder added'),
+ {
+ description: repo.displayName
+ }
+ )
}
return repo
} catch (err) {
console.error('Failed to add project:', err)
const message = err instanceof Error ? err.message : String(err)
const duration = ERROR_TOAST_DURATION
- toast.error(translate("auto.store.slices.repos.c6e022ddfc", "Failed to add project"), {
+ toast.error(translate('auto.store.slices.repos.c6e022ddfc', 'Failed to add project'), {
description: message,
duration
})
@@ -477,7 +487,12 @@ export const createRepoSlice: StateCreator = (set,
if (target.kind !== 'local') {
// Why: OS folder pickers return client-local paths. Remote environments
// need an explicit server path, which the Add Project dialog handles.
- toast.error(translate("auto.store.slices.repos.e649269645", "Use a server path to add projects from a remote runtime."))
+ toast.error(
+ translate(
+ 'auto.store.slices.repos.e649269645',
+ 'Use a server path to add projects from a remote runtime.'
+ )
+ )
return null
}
const path = await window.api.repos.pickFolder()
@@ -523,7 +538,10 @@ export const createRepoSlice: StateCreator = (set,
} catch (err) {
console.error('Failed to add folder:', err)
const message = err instanceof Error ? err.message : String(err)
- toast.error(translate("auto.store.slices.repos.b7e14472ae", "Failed to add folder"), { description: message, duration: ERROR_TOAST_DURATION })
+ toast.error(translate('auto.store.slices.repos.b7e14472ae', 'Failed to add folder'), {
+ description: message,
+ duration: ERROR_TOAST_DURATION
+ })
return null
}
},
diff --git a/src/renderer/src/store/slices/sparse-presets.ts b/src/renderer/src/store/slices/sparse-presets.ts
index 3c9a18a6e9a..5a111cad84d 100644
--- a/src/renderer/src/store/slices/sparse-presets.ts
+++ b/src/renderer/src/store/slices/sparse-presets.ts
@@ -74,10 +74,18 @@ export const createSparsePresetsSlice: StateCreator ({
sparsePresetsByRepo: { ...s.sparsePresetsByRepo, [repoId]: previous }
}))
const message = err instanceof Error ? err.message : String(err)
- toast.error(translate("auto.store.slices.sparse.presets.6ed7d6010a", "Failed to remove preset"), {
- description: message,
- duration: ERROR_TOAST_DURATION
- })
+ toast.error(
+ translate('auto.store.slices.sparse.presets.6ed7d6010a', 'Failed to remove preset'),
+ {
+ description: message,
+ duration: ERROR_TOAST_DURATION
+ }
+ )
// Why: settings UI keeps confirmation/edit state until persistence succeeds.
throw err
}
diff --git a/src/renderer/src/store/slices/store-test-helpers.ts b/src/renderer/src/store/slices/store-test-helpers.ts
index 77b60c8f5e9..e76a315529d 100644
--- a/src/renderer/src/store/slices/store-test-helpers.ts
+++ b/src/renderer/src/store/slices/store-test-helpers.ts
@@ -124,7 +124,7 @@ export function makeTab(
): TerminalTab {
return {
ptyId: null,
- title: translate("auto.store.slices.store.test.helpers.b9a8117c33", "Terminal 1"),
+ title: translate('auto.store.slices.store.test.helpers.b9a8117c33', 'Terminal 1'),
customTitle: null,
color: null,
sortOrder: 0,
@@ -156,7 +156,7 @@ export function makeUnifiedTab(
return {
entityId: overrides.id,
contentType: 'terminal',
- label: translate("auto.store.slices.store.test.helpers.b9a8117c33", "Terminal 1"),
+ label: translate('auto.store.slices.store.test.helpers.b9a8117c33', 'Terminal 1'),
customLabel: null,
color: null,
sortOrder: 0,
diff --git a/src/renderer/src/store/slices/ui.test.ts b/src/renderer/src/store/slices/ui.test.ts
index 074af763623..e6a6b1c609d 100644
--- a/src/renderer/src/store/slices/ui.test.ts
+++ b/src/renderer/src/store/slices/ui.test.ts
@@ -4,6 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { getDefaultUIState } from '../../../../shared/constants'
import type {
GitHubWorkItem,
+ LinearIssue,
PersistedUIState,
TerminalTab,
Worktree,
@@ -117,6 +118,26 @@ function makeGitHubWorkItem(overrides: Partial = {}): GitHubWork
}
}
+function makeLinearIssue(overrides: Partial = {}): LinearIssue {
+ return {
+ id: 'lin-1',
+ identifier: 'ORC-1',
+ title: 'Fix task flow',
+ url: 'https://linear.app/orca/issue/ORC-1/fix-task-flow',
+ state: { name: 'Todo', type: 'unstarted', color: '#999' },
+ priority: 0,
+ estimate: null,
+ assignee: null,
+ labels: [],
+ labelIds: [],
+ team: { id: 'team-1', name: 'Orca', key: 'ORC' },
+ workspaceId: 'workspace-1',
+ updatedAt: '2026-05-30T00:00:00.000Z',
+ createdAt: '2026-05-30T00:00:00.000Z',
+ ...overrides
+ } as LinearIssue
+}
+
function makePersistedUI(overrides: Partial = {}): PersistedUIState {
return {
...getDefaultUIState(),
@@ -1368,6 +1389,46 @@ describe('createUISlice page navigation history', () => {
expect(store.getState().worktreeNavHistoryIndex).toBe(0)
})
+ it('records provider-depth interactions for direct Tasks detail opens', () => {
+ const store = createUIStore()
+ const recordFeatureInteraction = vi.fn()
+ store.setState({ recordFeatureInteraction } as Partial)
+ const workItem = makeGitHubWorkItem()
+ const linearIssue = makeLinearIssue()
+
+ store.getState().openTaskPage({ taskSource: 'github', openGitHubWorkItem: workItem })
+ store.getState().openTaskPage({ taskSource: 'linear', openLinearIssue: linearIssue })
+
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('github-tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('linear-tasks')
+ })
+
+ it('can suppress the Tasks surface interaction for in-page provider navigation', () => {
+ const store = createUIStore()
+ const recordFeatureInteraction = vi.fn()
+ store.setState({ recordFeatureInteraction } as Partial)
+ const workItem = makeGitHubWorkItem()
+ const linearIssue = makeLinearIssue()
+
+ store
+ .getState()
+ .openTaskPage(
+ { taskSource: 'github', openGitHubWorkItem: workItem },
+ { recordTasksInteraction: false }
+ )
+ store
+ .getState()
+ .openTaskPage(
+ { taskSource: 'linear', openLinearIssue: linearIssue },
+ { recordTasksInteraction: false }
+ )
+
+ expect(recordFeatureInteraction).not.toHaveBeenCalledWith('tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('github-tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('linear-tasks')
+ })
+
it('skips the whole Tasks detail stack on close', () => {
const store = createUIStore()
const workItem = makeGitHubWorkItem()
diff --git a/src/renderer/src/store/slices/ui.ts b/src/renderer/src/store/slices/ui.ts
index 38c30e43fb5..4c90d1f0abe 100644
--- a/src/renderer/src/store/slices/ui.ts
+++ b/src/renderer/src/store/slices/ui.ts
@@ -634,7 +634,10 @@ export type UISlice = {
// Absent means "use the repo's effective base ref".
baseBranch?: string
} | null
- openTaskPage: (data?: UISlice['taskPageData']) => void
+ openTaskPage: (
+ data?: UISlice['taskPageData'],
+ options?: { recordTasksInteraction?: boolean }
+ ) => void
closeTaskPage: () => void
openActivityPage: () => void
closeActivityPage: () => void
@@ -693,6 +696,7 @@ export type UISlice = {
activeContextualTourSource: string | null
activeContextualTourSourceDetached: boolean
activeContextualTourWasFeaturePreviouslyInteracted: boolean
+ contextualTourNavigationInteractionSnapshot: Partial>
activeContextualTourSuppressed: boolean
contextualTourShownThisSession: boolean
contextualToursOnboardingVisible: boolean
@@ -1050,7 +1054,23 @@ export const createUISlice: StateCreator = (set, get)
taskResumeState: undefined,
githubTaskDrawerWorkItem: null,
newWorkspaceDraft: null,
- openTaskPage: (data = {}) => {
+ openTaskPage: (data = {}, options = {}) => {
+ if (options.recordTasksInteraction !== false) {
+ const wasTasksPreviouslyInteracted = hasFeatureInteraction(get().featureInteractions, 'tasks')
+ set((state) => ({
+ contextualTourNavigationInteractionSnapshot: {
+ ...state.contextualTourNavigationInteractionSnapshot,
+ tasks: wasTasksPreviouslyInteracted
+ }
+ }))
+ get().recordFeatureInteraction?.('tasks')
+ }
+ if (data.openGitHubWorkItem) {
+ get().recordFeatureInteraction?.('github-tasks')
+ }
+ if (data.openLinearIssue) {
+ get().recordFeatureInteraction?.('linear-tasks')
+ }
// Why: record a Tasks visit in the shared back/forward history so the
// titlebar Back/Forward buttons can return to Tasks. All task-source
// variants (github/linear presets) collapse to a single 'tasks' entry;
@@ -1389,6 +1409,7 @@ export const createUISlice: StateCreator = (set, get)
activeContextualTourSource: null,
activeContextualTourSourceDetached: false,
activeContextualTourWasFeaturePreviouslyInteracted: false,
+ contextualTourNavigationInteractionSnapshot: {},
activeContextualTourSuppressed: false,
contextualTourShownThisSession: false,
contextualToursOnboardingVisible: false,
@@ -1432,15 +1453,28 @@ export const createUISlice: StateCreator = (set, get)
targetExists: hasContextualTourTarget
})
if (decision.kind !== 'start') {
- return s
+ if (s.contextualTourNavigationInteractionSnapshot[id] === undefined) {
+ return s
+ }
+ const { [id]: _consumed, ...remainingNavigationSnapshot } =
+ s.contextualTourNavigationInteractionSnapshot
+ void _consumed
+ return { contextualTourNavigationInteractionSnapshot: remainingNavigationSnapshot }
}
+ const navigationSnapshot = s.contextualTourNavigationInteractionSnapshot[id]
+ const { [id]: _consumed, ...remainingNavigationSnapshot } =
+ s.contextualTourNavigationInteractionSnapshot
+ void _consumed
return {
activeContextualTourId: id,
activeContextualTourStepIndex: decision.stepIndex,
activeContextualTourSource: source,
activeContextualTourSourceDetached: false,
activeContextualTourWasFeaturePreviouslyInteracted:
- wasFeaturePreviouslyInteracted ?? hasFeatureInteraction(s.featureInteractions, id),
+ wasFeaturePreviouslyInteracted ??
+ navigationSnapshot ??
+ hasFeatureInteraction(s.featureInteractions, id),
+ contextualTourNavigationInteractionSnapshot: remainingNavigationSnapshot,
activeContextualTourSuppressed: false,
contextualTourShownThisSession: true,
lastCompletedContextualTourId: null
diff --git a/src/renderer/src/store/slices/workspace-cleanup.ts b/src/renderer/src/store/slices/workspace-cleanup.ts
index 9f3fb4e069d..159e0b50b40 100644
--- a/src/renderer/src/store/slices/workspace-cleanup.ts
+++ b/src/renderer/src/store/slices/workspace-cleanup.ts
@@ -398,7 +398,10 @@ async function preflightWorkspaceCleanupCandidate(
failure: {
worktreeId,
displayName: worktreeId,
- message: translate("auto.store.slices.workspace.cleanup.9d6e531da6", "Workspace no longer exists.")
+ message: translate(
+ 'auto.store.slices.workspace.cleanup.9d6e531da6',
+ 'Workspace no longer exists.'
+ )
}
}
}
diff --git a/src/renderer/src/web/WebConnect.tsx b/src/renderer/src/web/WebConnect.tsx
index 3d2bf010bcd..9a6709e04e1 100644
--- a/src/renderer/src/web/WebConnect.tsx
+++ b/src/renderer/src/web/WebConnect.tsx
@@ -78,14 +78,22 @@ export default function WebConnect({
-
{translate("auto.web.WebConnect.e3bcd082ac", "Connect to Orca")}
+
+ {translate('auto.web.WebConnect.e3bcd082ac', 'Connect to Orca')}
+
- {translate("auto.web.WebConnect.3affe7de3a", "Paste a pairing URL from an Orca server that this browser can reach.")}
+ {translate(
+ 'auto.web.WebConnect.3affe7de3a',
+ 'Paste a pairing URL from an Orca server that this browser can reach.'
+ )}
+
-
{translate("auto.web.WebConnect.cb4d287238", "Server name")}
+
+ {translate('auto.web.WebConnect.cb4d287238', 'Server name')}
+
-
{translate("auto.web.WebConnect.7a566540de", "Pairing URL or code")}
+
+ {translate('auto.web.WebConnect.7a566540de', 'Pairing URL or code')}
+
setPairingCode(event.target.value)}
- placeholder={translate("auto.web.WebConnect.27393856e4", "orca://pair?code=...")}
+ placeholder={translate('auto.web.WebConnect.27393856e4', 'orca://pair?code=...')}
autoComplete="off"
spellCheck={false}
/>
@@ -108,7 +118,7 @@ export default function WebConnect({
{parsedOffer && (
- {translate("auto.web.WebConnect.4a4c017be1", "Endpoint:")} {parsedOffer.endpoint}
+ {translate('auto.web.WebConnect.4a4c017be1', 'Endpoint:')} {parsedOffer.endpoint}
)}
@@ -121,7 +131,8 @@ export default function WebConnect({
- {translate("auto.web.WebConnect.2cf9e5a294", "Clear saved server")}
+ {translate('auto.web.WebConnect.2cf9e5a294', 'Clear saved server')}
+
void connect()}
@@ -133,7 +144,8 @@ export default function WebConnect({
) : (
)}
- {translate("auto.web.WebConnect.b411ec0069", "Connect")}
+ {translate('auto.web.WebConnect.b411ec0069', 'Connect')}
+
diff --git a/src/renderer/src/web/main.tsx b/src/renderer/src/web/main.tsx
index 30ad178b2cd..6ebb49937ea 100644
--- a/src/renderer/src/web/main.tsx
+++ b/src/renderer/src/web/main.tsx
@@ -58,7 +58,10 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
boundaryId="web.root"
surface="web-root"
title={translate('app.recoverableError.webTitle', 'Orca web hit a renderer error.')}
- description={translate('app.recoverableError.webDescription', 'Retry the web client or reconnect to the paired runtime.')}
+ description={translate(
+ 'app.recoverableError.webDescription',
+ 'Retry the web client or reconnect to the paired runtime.'
+ )}
>
diff --git a/src/renderer/src/web/web-preload-api.test.ts b/src/renderer/src/web/web-preload-api.test.ts
index 5ebce3603e9..b060df6b51b 100644
--- a/src/renderer/src/web/web-preload-api.test.ts
+++ b/src/renderer/src/web/web-preload-api.test.ts
@@ -159,7 +159,7 @@ describe('web keybindings preload API', () => {
bindings: null
})
expect(reset.overrides['worktree.palette']).toBeUndefined()
- })
+ }, 15_000)
it('rejects conflicts before mutating browser storage', async () => {
const { api } = await installApi('Linux')
@@ -782,6 +782,46 @@ describe('web UI preload API', () => {
expect(stored.contextualToursSeenIds).toEqual(['tasks', 'browser'])
})
+ it('does not keep a local shadow copy of main-owned feature telemetry markers', async () => {
+ vi.doMock('./web-runtime-client', () => ({
+ WebRuntimeClient: class {
+ call(method: string): Promise> {
+ return Promise.resolve({
+ id: method,
+ ok: true,
+ result: { ui: {} },
+ _meta: { runtimeId: 'runtime-1' }
+ })
+ }
+
+ close(): void {}
+ }
+ }))
+
+ const globals = installBrowserGlobals('Linux')
+ writeStoredRuntimeEnvironment(globals.storage)
+ globals.storage.setItem(
+ 'orca.web.ui.v1',
+ JSON.stringify({
+ featureInteractionTelemetryBuckets: { tasks: 'count_1000_plus' }
+ })
+ )
+ const { installWebPreloadApi } = await import('./web-preload-api')
+ installWebPreloadApi()
+
+ await globals.window.api.ui.set({
+ featureInteractionTelemetryBuckets: { tasks: 'count_500_999' }
+ } as never)
+ const ui = await globals.window.api.ui.get()
+ const stored = JSON.parse(globals.storage.getItem('orca.web.ui.v1') ?? '{}') as Record<
+ string,
+ unknown
+ >
+
+ expect('featureInteractionTelemetryBuckets' in (ui as Record)).toBe(false)
+ expect(stored.featureInteractionTelemetryBuckets).toBeUndefined()
+ })
+
it('union-merges local contextual tour seen ids when recordFeatureInteraction returns stale host state', async () => {
vi.doMock('./web-runtime-client', () => ({
WebRuntimeClient: class {
diff --git a/src/renderer/src/web/web-preload-api.ts b/src/renderer/src/web/web-preload-api.ts
index d99cf3b6473..099e95d39b6 100644
--- a/src/renderer/src/web/web-preload-api.ts
+++ b/src/renderer/src/web/web-preload-api.ts
@@ -2605,11 +2605,16 @@ function mergeWebUIState(
base: PersistedUIState,
updates: Partial
): PersistedUIState {
+ const { featureInteractionTelemetryBuckets: _reserved, ...safeUpdates } =
+ updates as Partial & {
+ featureInteractionTelemetryBuckets?: unknown
+ }
+ void _reserved
return {
...base,
- ...updates,
+ ...safeUpdates,
agentActivityDisplayMode: normalizeAgentActivityDisplayMode(
- updates.agentActivityDisplayMode ?? base.agentActivityDisplayMode
+ safeUpdates.agentActivityDisplayMode ?? base.agentActivityDisplayMode
)
}
}
diff --git a/src/renderer/src/web/web-runtime-environment.ts b/src/renderer/src/web/web-runtime-environment.ts
index 30b1fa72cf2..ea378cb8c90 100644
--- a/src/renderer/src/web/web-runtime-environment.ts
+++ b/src/renderer/src/web/web-runtime-environment.ts
@@ -58,7 +58,7 @@ export function createStoredWebRuntimeEnvironment(args: {
{
id: `ws-${id}`,
kind: 'websocket',
- label: translate("auto.web.web.runtime.environment.07f788de83", "WebSocket"),
+ label: translate('auto.web.web.runtime.environment.07f788de83', 'WebSocket'),
endpoint: args.offer.endpoint,
deviceToken: args.offer.deviceToken,
publicKeyB64: args.offer.publicKeyB64
diff --git a/src/shared/constants.ts b/src/shared/constants.ts
index 78d1c3e850f..4d330aa5823 100644
--- a/src/shared/constants.ts
+++ b/src/shared/constants.ts
@@ -391,7 +391,8 @@ export function getDefaultPersistedState(homedir: string): PersistedState {
legacyPaneKeyAliasEntries: [],
automations: [],
automationRuns: [],
- onboarding: getDefaultOnboardingState()
+ onboarding: getDefaultOnboardingState(),
+ featureInteractionTelemetryBuckets: {}
}
}
diff --git a/src/shared/feature-interaction-catalog.ts b/src/shared/feature-interaction-catalog.ts
new file mode 100644
index 00000000000..917a9295b65
--- /dev/null
+++ b/src/shared/feature-interaction-catalog.ts
@@ -0,0 +1,162 @@
+export type FeatureInteractionId =
+ | 'workspace-board'
+ | 'workspace-agent-sessions'
+ | 'workspace-board-actions'
+ | 'cmd-j'
+ | 'cmd-j-workspace-open'
+ | 'cmd-j-browser-page-open'
+ | 'cmd-j-settings-open'
+ | 'cmd-j-quick-action'
+ | 'cmd-j-create-workspace'
+ | 'browser'
+ | 'browser-tab-created'
+ | 'tasks'
+ | 'github-tasks'
+ | 'gitlab-tasks'
+ | 'linear-tasks'
+ | 'automations'
+ | 'automation-created'
+ | 'automation-run'
+ | 'browser-annotations'
+ | 'browser-annotations-sent-to-agent'
+ | 'browser-grab'
+ | 'markdown-file-created'
+ | 'workspace-creation'
+ | 'agent-browser-setup'
+ | 'agent-browser-use'
+ | 'agent-orchestration-setup'
+ | 'agent-orchestration'
+ | 'ai-commit-generation'
+ | 'ai-pr-generation'
+ | 'claude-account-switching'
+ | 'computer-use-setup'
+ | 'computer-use'
+ | 'codex-account-switching'
+ | 'cookie-import'
+ | 'floating-workspace'
+ | 'floating-workspace-hidden'
+ | 'mobile-pairing'
+ | 'notifications'
+ | 'ports'
+ | 'quick-commands'
+ | 'resource-manager'
+ | 'review-notes'
+ | 'ssh'
+ | 'terminal-pane-split'
+ | 'terminal-panes'
+ | 'terminal-tabs'
+ | 'tab-splits'
+ | 'usage-tracking'
+ | 'voice-dictation'
+ | 'workspace-cleanup'
+
+export type FeatureInteractionDefinition = {
+ id: FeatureInteractionId
+ /** The product action that counts as "the user has interacted with this feature." */
+ interaction: string
+}
+
+// Why: these ids become persisted product state; see
+// docs/reference/feature-discovery-interaction-tracking.md before changing them.
+export const FEATURE_INTERACTIONS = [
+ { id: 'workspace-board', interaction: 'workspace board opened' },
+ {
+ id: 'workspace-agent-sessions',
+ interaction: 'workspace agent-session surface opened'
+ },
+ {
+ id: 'workspace-board-actions',
+ interaction: 'workspace board card, lane, density, or status action used'
+ },
+ { id: 'cmd-j', interaction: 'Cmd+J palette opened' },
+ { id: 'cmd-j-workspace-open', interaction: 'workspace opened from Cmd+J' },
+ { id: 'cmd-j-browser-page-open', interaction: 'browser page opened from Cmd+J' },
+ { id: 'cmd-j-settings-open', interaction: 'settings opened from Cmd+J' },
+ { id: 'cmd-j-quick-action', interaction: 'quick action run from Cmd+J' },
+ { id: 'cmd-j-create-workspace', interaction: 'workspace creation started from Cmd+J' },
+ { id: 'browser', interaction: 'in-app browser opened' },
+ { id: 'browser-tab-created', interaction: 'browser tab explicitly created' },
+ { id: 'tasks', interaction: 'Tasks page opened' },
+ { id: 'github-tasks', interaction: 'GitHub task item workflow used' },
+ { id: 'gitlab-tasks', interaction: 'GitLab task item workflow used' },
+ { id: 'linear-tasks', interaction: 'Linear task item workflow used' },
+ { id: 'automations', interaction: 'Automations page opened' },
+ { id: 'automation-created', interaction: 'automation created' },
+ { id: 'automation-run', interaction: 'automation run queued' },
+ { id: 'browser-annotations', interaction: 'browser annotation added, copied, or cleared' },
+ {
+ id: 'browser-annotations-sent-to-agent',
+ interaction: 'browser annotations sent to an agent'
+ },
+ { id: 'browser-grab', interaction: 'browser element grab or screenshot used' },
+ { id: 'markdown-file-created', interaction: 'untitled markdown file explicitly created' },
+ { id: 'workspace-creation', interaction: 'workspace creation flow opened' },
+ { id: 'agent-browser-setup', interaction: 'Agent Browser Use setup enabled or opened' },
+ { id: 'agent-browser-use', interaction: 'agent browser runtime method used' },
+ {
+ id: 'agent-orchestration-setup',
+ interaction: 'Agent Orchestration setup enabled or opened'
+ },
+ { id: 'agent-orchestration', interaction: 'agent orchestration runtime method used' },
+ {
+ id: 'ai-commit-generation',
+ interaction: 'AI commit message generation enabled or used'
+ },
+ { id: 'ai-pr-generation', interaction: 'AI pull request generation used' },
+ {
+ id: 'claude-account-switching',
+ interaction: 'Claude managed account added, selected, reauthenticated, or removed'
+ },
+ {
+ id: 'computer-use-setup',
+ interaction: 'Computer Use setup or permission flow opened'
+ },
+ { id: 'computer-use', interaction: 'computer-use runtime method used' },
+ {
+ id: 'codex-account-switching',
+ interaction: 'Codex managed account added, selected, reauthenticated, or removed'
+ },
+ { id: 'cookie-import', interaction: 'browser cookies imported or cleared' },
+ { id: 'floating-workspace', interaction: 'Floating Workspace opened or configured' },
+ {
+ id: 'floating-workspace-hidden',
+ interaction: 'Floating Workspace explicitly hidden or disabled'
+ },
+ { id: 'mobile-pairing', interaction: 'mobile pairing enabled or QR code generated' },
+ { id: 'notifications', interaction: 'desktop notifications enabled or tested' },
+ { id: 'ports', interaction: 'Ports popover opened, configured, or port action used' },
+ { id: 'quick-commands', interaction: 'terminal quick command created or edited' },
+ { id: 'resource-manager', interaction: 'Resource Manager opened or configured' },
+ { id: 'review-notes', interaction: 'review note added or sent to an agent' },
+ {
+ id: 'ssh',
+ interaction: 'SSH target added, imported, tested, connected, disconnected, or configured'
+ },
+ {
+ id: 'terminal-pane-split',
+ interaction: 'terminal pane split from the split-pane command'
+ },
+ {
+ id: 'terminal-panes',
+ interaction: 'terminal/editor/browser pane created, resized, or merged'
+ },
+ {
+ id: 'terminal-tabs',
+ interaction: 'workspace tab created, moved, reordered, pinned, renamed, recolored, or closed'
+ },
+ { id: 'tab-splits', interaction: 'workspace tab split into another pane' },
+ {
+ id: 'usage-tracking',
+ interaction: 'Stats & Usage or provider usage details opened or configured'
+ },
+ { id: 'voice-dictation', interaction: 'dictation session started' },
+ {
+ id: 'workspace-cleanup',
+ interaction: 'workspace disk space scan, review, or cleanup action used'
+ }
+] as const satisfies readonly FeatureInteractionDefinition[]
+
+export const FEATURE_INTERACTION_IDS = FEATURE_INTERACTIONS.map((feature) => feature.id) as [
+ FeatureInteractionId,
+ ...FeatureInteractionId[]
+]
diff --git a/src/shared/feature-interaction-categories.ts b/src/shared/feature-interaction-categories.ts
new file mode 100644
index 00000000000..72b05ceca7e
--- /dev/null
+++ b/src/shared/feature-interaction-categories.ts
@@ -0,0 +1,79 @@
+import type { FeatureInteractionId } from './feature-interaction-catalog'
+
+export const FEATURE_INTERACTION_CATEGORIES = [
+ 'workspace',
+ 'agent',
+ 'browser',
+ 'launcher',
+ 'task_management',
+ 'notes',
+ 'review',
+ 'setup',
+ 'settings',
+ 'automation',
+ 'terminal',
+ 'collaboration',
+ 'resource_management',
+ 'voice',
+ 'source_control'
+] as const
+export type FeatureInteractionCategory = (typeof FEATURE_INTERACTION_CATEGORIES)[number]
+
+export const FEATURE_INTERACTION_CATEGORY_BY_ID = {
+ 'workspace-board': 'workspace',
+ 'workspace-agent-sessions': 'workspace',
+ 'workspace-board-actions': 'workspace',
+ 'cmd-j': 'launcher',
+ 'cmd-j-workspace-open': 'launcher',
+ 'cmd-j-browser-page-open': 'launcher',
+ 'cmd-j-settings-open': 'launcher',
+ 'cmd-j-quick-action': 'launcher',
+ 'cmd-j-create-workspace': 'launcher',
+ browser: 'browser',
+ 'browser-tab-created': 'browser',
+ tasks: 'task_management',
+ 'github-tasks': 'task_management',
+ 'gitlab-tasks': 'task_management',
+ 'linear-tasks': 'task_management',
+ automations: 'automation',
+ 'automation-created': 'automation',
+ 'automation-run': 'automation',
+ 'browser-annotations': 'browser',
+ 'browser-annotations-sent-to-agent': 'browser',
+ 'browser-grab': 'browser',
+ 'markdown-file-created': 'notes',
+ 'workspace-creation': 'workspace',
+ 'agent-browser-setup': 'setup',
+ 'agent-browser-use': 'agent',
+ 'agent-orchestration-setup': 'setup',
+ 'agent-orchestration': 'collaboration',
+ 'ai-commit-generation': 'source_control',
+ 'ai-pr-generation': 'source_control',
+ 'claude-account-switching': 'settings',
+ 'computer-use-setup': 'setup',
+ 'computer-use': 'agent',
+ 'codex-account-switching': 'settings',
+ 'cookie-import': 'browser',
+ 'floating-workspace': 'workspace',
+ 'floating-workspace-hidden': 'workspace',
+ 'mobile-pairing': 'collaboration',
+ notifications: 'settings',
+ ports: 'resource_management',
+ 'quick-commands': 'launcher',
+ 'resource-manager': 'resource_management',
+ 'review-notes': 'review',
+ ssh: 'setup',
+ 'terminal-pane-split': 'terminal',
+ 'terminal-panes': 'terminal',
+ 'terminal-tabs': 'terminal',
+ 'tab-splits': 'terminal',
+ 'usage-tracking': 'settings',
+ 'voice-dictation': 'voice',
+ 'workspace-cleanup': 'workspace'
+} as const satisfies Record
+
+export function getFeatureInteractionCategory(
+ id: FeatureInteractionId
+): FeatureInteractionCategory {
+ return FEATURE_INTERACTION_CATEGORY_BY_ID[id]
+}
diff --git a/src/shared/feature-interaction-usage-buckets.ts b/src/shared/feature-interaction-usage-buckets.ts
new file mode 100644
index 00000000000..692eacadcfe
--- /dev/null
+++ b/src/shared/feature-interaction-usage-buckets.ts
@@ -0,0 +1,69 @@
+export const FEATURE_INTERACTION_USAGE_BUCKETS = [
+ 'count_1',
+ 'count_2',
+ 'count_3_4',
+ 'count_5_9',
+ 'count_10_19',
+ 'count_20_49',
+ 'count_50_99',
+ 'count_100_199',
+ 'count_200_499',
+ 'count_500_999',
+ 'count_1000_plus'
+] as const
+export type FeatureInteractionUsageBucket = (typeof FEATURE_INTERACTION_USAGE_BUCKETS)[number]
+
+export const FEATURE_INTERACTION_USAGE_BUCKET_SPECS = [
+ { bucket: 'count_1', min: 1 },
+ { bucket: 'count_2', min: 2 },
+ { bucket: 'count_3_4', min: 3 },
+ { bucket: 'count_5_9', min: 5 },
+ { bucket: 'count_10_19', min: 10 },
+ { bucket: 'count_20_49', min: 20 },
+ { bucket: 'count_50_99', min: 50 },
+ { bucket: 'count_100_199', min: 100 },
+ { bucket: 'count_200_499', min: 200 },
+ { bucket: 'count_500_999', min: 500 },
+ { bucket: 'count_1000_plus', min: 1000 }
+] as const satisfies readonly {
+ bucket: FeatureInteractionUsageBucket
+ min: number
+}[]
+
+const FEATURE_INTERACTION_USAGE_BUCKET_INDEX = new Map(
+ FEATURE_INTERACTION_USAGE_BUCKETS.map((bucket, index) => [bucket, index])
+)
+
+export function getFeatureInteractionUsageBucket(
+ count: number
+): FeatureInteractionUsageBucket | null {
+ if (!Number.isInteger(count) || count <= 0) {
+ return null
+ }
+ let bucket: FeatureInteractionUsageBucket | null = null
+ for (const spec of FEATURE_INTERACTION_USAGE_BUCKET_SPECS) {
+ if (count >= spec.min) {
+ bucket = spec.bucket
+ }
+ }
+ return bucket
+}
+
+export function compareFeatureInteractionUsageBuckets(
+ a: FeatureInteractionUsageBucket,
+ b: FeatureInteractionUsageBucket
+): number {
+ return (
+ (FEATURE_INTERACTION_USAGE_BUCKET_INDEX.get(a) ?? -1) -
+ (FEATURE_INTERACTION_USAGE_BUCKET_INDEX.get(b) ?? -1)
+ )
+}
+
+export function isFeatureInteractionUsageBucket(
+ value: unknown
+): value is FeatureInteractionUsageBucket {
+ return (
+ typeof value === 'string' &&
+ FEATURE_INTERACTION_USAGE_BUCKETS.includes(value as FeatureInteractionUsageBucket)
+ )
+}
diff --git a/src/shared/feature-interactions.test.ts b/src/shared/feature-interactions.test.ts
index ba9987280db..3778f979925 100644
--- a/src/shared/feature-interactions.test.ts
+++ b/src/shared/feature-interactions.test.ts
@@ -3,7 +3,12 @@ import { join, relative } from 'node:path'
import { describe, expect, it } from 'vitest'
import {
FEATURE_INTERACTIONS,
+ FEATURE_INTERACTION_CATEGORIES,
+ FEATURE_INTERACTION_CATEGORY_BY_ID,
+ FEATURE_INTERACTION_USAGE_BUCKETS,
+ getFeatureInteractionUsageBucket,
hasFeatureInteraction,
+ normalizeFeatureInteractionTelemetryBuckets,
normalizeFeatureInteractions,
type FeatureInteractionId
} from './feature-interactions'
@@ -29,13 +34,25 @@ describe('feature interactions', () => {
'workspace-board',
'workspace-agent-sessions',
'workspace-board-actions',
+ 'cmd-j',
+ 'cmd-j-workspace-open',
+ 'cmd-j-browser-page-open',
+ 'cmd-j-settings-open',
+ 'cmd-j-quick-action',
+ 'cmd-j-create-workspace',
'browser',
+ 'browser-tab-created',
'tasks',
+ 'github-tasks',
+ 'gitlab-tasks',
+ 'linear-tasks',
'automations',
'automation-created',
'automation-run',
'browser-annotations',
+ 'browser-annotations-sent-to-agent',
'browser-grab',
+ 'markdown-file-created',
'workspace-creation',
'agent-browser-setup',
'agent-browser-use',
@@ -49,6 +66,7 @@ describe('feature interactions', () => {
'codex-account-switching',
'cookie-import',
'floating-workspace',
+ 'floating-workspace-hidden',
'mobile-pairing',
'notifications',
'ports',
@@ -105,6 +123,77 @@ describe('feature interactions', () => {
).toBe(false)
})
+ it('maps interaction counts to the exact top-coded telemetry buckets', () => {
+ expect(FEATURE_INTERACTION_USAGE_BUCKETS).toEqual([
+ 'count_1',
+ 'count_2',
+ 'count_3_4',
+ 'count_5_9',
+ 'count_10_19',
+ 'count_20_49',
+ 'count_50_99',
+ 'count_100_199',
+ 'count_200_499',
+ 'count_500_999',
+ 'count_1000_plus'
+ ])
+ expect(getFeatureInteractionUsageBucket(0)).toBeNull()
+ expect(getFeatureInteractionUsageBucket(1)).toBe('count_1')
+ expect(getFeatureInteractionUsageBucket(2)).toBe('count_2')
+ expect(getFeatureInteractionUsageBucket(3)).toBe('count_3_4')
+ expect(getFeatureInteractionUsageBucket(4)).toBe('count_3_4')
+ expect(getFeatureInteractionUsageBucket(5)).toBe('count_5_9')
+ expect(getFeatureInteractionUsageBucket(999)).toBe('count_500_999')
+ expect(getFeatureInteractionUsageBucket(1000)).toBe('count_1000_plus')
+ expect(getFeatureInteractionUsageBucket(1001)).toBe('count_1000_plus')
+ })
+
+ it('covers every feature id with a telemetry category', () => {
+ expect(FEATURE_INTERACTION_CATEGORIES).toEqual([
+ 'workspace',
+ 'agent',
+ 'browser',
+ 'launcher',
+ 'task_management',
+ 'notes',
+ 'review',
+ 'setup',
+ 'settings',
+ 'automation',
+ 'terminal',
+ 'collaboration',
+ 'resource_management',
+ 'voice',
+ 'source_control'
+ ])
+ expect(Object.keys(FEATURE_INTERACTION_CATEGORY_BY_ID).sort()).toEqual(
+ FEATURE_INTERACTIONS.map((feature) => feature.id).sort()
+ )
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID.tasks).toBe('task_management')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['github-tasks']).toBe('task_management')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['markdown-file-created']).toBe('notes')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['agent-browser-setup']).toBe('setup')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['terminal-tabs']).toBe('terminal')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['voice-dictation']).toBe('voice')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['ai-commit-generation']).toBe('source_control')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['resource-manager']).toBe('resource_management')
+ })
+
+ it('normalizes persisted telemetry bucket markers by removing unknown ids and buckets', () => {
+ expect(
+ normalizeFeatureInteractionTelemetryBuckets({
+ tasks: 'count_1',
+ browser: 'count_1000_plus',
+ automations: 'count_4',
+ unknown: 'count_1',
+ 'voice-dictation': null
+ })
+ ).toEqual({
+ tasks: 'count_1',
+ browser: 'count_1000_plus'
+ })
+ })
+
it('keeps every catalog id wired to a production writer', () => {
const productionText = collectProductionSourceText()
const missingWriters = FEATURE_INTERACTIONS.map((feature) => feature.id).filter((id) => {
@@ -122,7 +211,7 @@ describe('feature interactions', () => {
})
expect(missingWriters).toEqual([])
- })
+ }, 15_000)
})
function collectProductionSourceText(): string {
diff --git a/src/shared/feature-interactions.ts b/src/shared/feature-interactions.ts
index 45abcea76be..fb995bc5e5e 100644
--- a/src/shared/feature-interactions.ts
+++ b/src/shared/feature-interactions.ts
@@ -1,47 +1,29 @@
-export type FeatureInteractionId =
- | 'workspace-board'
- | 'workspace-agent-sessions'
- | 'workspace-board-actions'
- | 'browser'
- | 'tasks'
- | 'automations'
- | 'automation-created'
- | 'automation-run'
- | 'browser-annotations'
- | 'browser-grab'
- | 'workspace-creation'
- | 'agent-browser-setup'
- | 'agent-browser-use'
- | 'agent-orchestration-setup'
- | 'agent-orchestration'
- | 'ai-commit-generation'
- | 'ai-pr-generation'
- | 'claude-account-switching'
- | 'computer-use-setup'
- | 'computer-use'
- | 'codex-account-switching'
- | 'cookie-import'
- | 'floating-workspace'
- | 'mobile-pairing'
- | 'notifications'
- | 'ports'
- | 'quick-commands'
- | 'resource-manager'
- | 'review-notes'
- | 'ssh'
- | 'terminal-pane-split'
- | 'terminal-panes'
- | 'terminal-tabs'
- | 'tab-splits'
- | 'usage-tracking'
- | 'voice-dictation'
- | 'workspace-cleanup'
+import { FEATURE_INTERACTION_IDS, type FeatureInteractionId } from './feature-interaction-catalog'
+import {
+ isFeatureInteractionUsageBucket,
+ type FeatureInteractionUsageBucket
+} from './feature-interaction-usage-buckets'
-export type FeatureInteractionDefinition = {
- id: FeatureInteractionId
- /** The product action that counts as "the user has interacted with this feature." */
- interaction: string
-}
+export {
+ FEATURE_INTERACTIONS,
+ FEATURE_INTERACTION_IDS,
+ type FeatureInteractionDefinition,
+ type FeatureInteractionId
+} from './feature-interaction-catalog'
+export {
+ FEATURE_INTERACTION_CATEGORIES,
+ FEATURE_INTERACTION_CATEGORY_BY_ID,
+ getFeatureInteractionCategory,
+ type FeatureInteractionCategory
+} from './feature-interaction-categories'
+export {
+ compareFeatureInteractionUsageBuckets,
+ FEATURE_INTERACTION_USAGE_BUCKETS,
+ FEATURE_INTERACTION_USAGE_BUCKET_SPECS,
+ getFeatureInteractionUsageBucket,
+ isFeatureInteractionUsageBucket,
+ type FeatureInteractionUsageBucket
+} from './feature-interaction-usage-buckets'
export type FeatureInteractionRecord = {
/** Unix timestamp in milliseconds for the first local interaction. */
@@ -54,160 +36,9 @@ export type FeatureInteractionState = Partial<
Record
>
-// Why: these ids become persisted product state; see
-// docs/reference/feature-discovery-interaction-tracking.md before changing them.
-export const FEATURE_INTERACTIONS = [
- {
- id: 'workspace-board',
- interaction: 'workspace board opened'
- },
- {
- id: 'workspace-agent-sessions',
- interaction: 'workspace agent-session surface opened'
- },
- {
- id: 'workspace-board-actions',
- interaction: 'workspace board card, lane, density, or status action used'
- },
- {
- id: 'browser',
- interaction: 'in-app browser opened'
- },
- {
- id: 'tasks',
- interaction: 'Tasks page opened'
- },
- {
- id: 'automations',
- interaction: 'Automations page opened'
- },
- {
- id: 'automation-created',
- interaction: 'automation created'
- },
- {
- id: 'automation-run',
- interaction: 'automation run queued'
- },
- {
- id: 'browser-annotations',
- interaction: 'browser annotation added, copied, or cleared'
- },
- {
- id: 'browser-grab',
- interaction: 'browser element grab or screenshot used'
- },
- {
- id: 'workspace-creation',
- interaction: 'workspace creation flow opened'
- },
- {
- id: 'agent-browser-setup',
- interaction: 'Agent Browser Use setup enabled or opened'
- },
- {
- id: 'agent-browser-use',
- interaction: 'agent browser runtime method used'
- },
- {
- id: 'agent-orchestration-setup',
- interaction: 'Agent Orchestration setup enabled or opened'
- },
- {
- id: 'agent-orchestration',
- interaction: 'agent orchestration runtime method used'
- },
- {
- id: 'ai-commit-generation',
- interaction: 'AI commit message generation enabled or used'
- },
- {
- id: 'ai-pr-generation',
- interaction: 'AI pull request generation used'
- },
- {
- id: 'claude-account-switching',
- interaction: 'Claude managed account added, selected, reauthenticated, or removed'
- },
- {
- id: 'computer-use-setup',
- interaction: 'Computer Use setup or permission flow opened'
- },
- {
- id: 'computer-use',
- interaction: 'computer-use runtime method used'
- },
- {
- id: 'codex-account-switching',
- interaction: 'Codex managed account added, selected, reauthenticated, or removed'
- },
- {
- id: 'cookie-import',
- interaction: 'browser cookies imported or cleared'
- },
- {
- id: 'floating-workspace',
- interaction: 'Floating Workspace opened or configured'
- },
- {
- id: 'mobile-pairing',
- interaction: 'mobile pairing enabled or QR code generated'
- },
- {
- id: 'notifications',
- interaction: 'desktop notifications enabled or tested'
- },
- {
- id: 'ports',
- interaction: 'Ports popover opened, configured, or port action used'
- },
- {
- id: 'quick-commands',
- interaction: 'terminal quick command created or edited'
- },
- {
- id: 'resource-manager',
- interaction: 'Resource Manager opened or configured'
- },
- {
- id: 'review-notes',
- interaction: 'review note added or sent to an agent'
- },
- {
- id: 'ssh',
- interaction: 'SSH target added, imported, tested, connected, disconnected, or configured'
- },
- {
- id: 'terminal-pane-split',
- interaction: 'terminal pane split from the split-pane command'
- },
- {
- id: 'terminal-panes',
- interaction: 'terminal/editor/browser pane created, resized, or merged'
- },
- {
- id: 'terminal-tabs',
- interaction: 'workspace tab created, moved, reordered, pinned, renamed, recolored, or closed'
- },
- {
- id: 'tab-splits',
- interaction: 'workspace tab split into another pane'
- },
- {
- id: 'usage-tracking',
- interaction: 'Stats & Usage or provider usage details opened or configured'
- },
- {
- id: 'voice-dictation',
- interaction: 'dictation session started'
- },
- {
- id: 'workspace-cleanup',
- interaction: 'workspace disk space scan, review, or cleanup action used'
- }
-] as const satisfies readonly FeatureInteractionDefinition[]
-
-export const FEATURE_INTERACTION_IDS = FEATURE_INTERACTIONS.map((feature) => feature.id)
+export type FeatureInteractionTelemetryBucketState = Partial<
+ Record
+>
export function isFeatureInteractionId(value: unknown): value is FeatureInteractionId {
return (
@@ -222,6 +53,24 @@ export function hasFeatureInteraction(
return normalizeFeatureInteractionRecord(state?.[id]) !== null
}
+export function normalizeFeatureInteractionTelemetryBuckets(
+ value: unknown
+): FeatureInteractionTelemetryBucketState {
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
+ return {}
+ }
+
+ const input = value as Record
+ const out: FeatureInteractionTelemetryBucketState = {}
+ for (const id of FEATURE_INTERACTION_IDS) {
+ const bucket = input[id]
+ if (isFeatureInteractionUsageBucket(bucket)) {
+ out[id] = bucket
+ }
+ }
+ return out
+}
+
export function normalizeFeatureInteractions(value: unknown): FeatureInteractionState {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
return {}
diff --git a/src/shared/telemetry-events.test.ts b/src/shared/telemetry-events.test.ts
index 4f33fa39c5e..9d32a1bff30 100644
--- a/src/shared/telemetry-events.test.ts
+++ b/src/shared/telemetry-events.test.ts
@@ -12,11 +12,120 @@ import {
agentKindSchema,
errorClassSchema,
eventSchemas,
+ isCohortExtendedEvent,
SETTINGS_CHANGED_WHITELIST,
settingsChangedKeySchema
} from './telemetry-events'
+import { FEATURE_INTERACTION_IDS, getFeatureInteractionCategory } from './feature-interactions'
import { appStarSourceSchema } from './gh-star-source'
+describe('feature_interaction_usage_bucket_reached schema', () => {
+ it('accepts a valid bucket payload', () => {
+ const parsed = eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ feature_id: 'browser-tab-created',
+ feature_category: 'browser',
+ count_bucket: 'count_3_4',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ expect(parsed.success).toBe(true)
+ })
+
+ it('is in the runtime cohort-injection roster', () => {
+ expect(isCohortExtendedEvent('feature_interaction_usage_bucket_reached')).toBe(true)
+ })
+
+ it('keeps the feature id enum in sync with the catalog', () => {
+ const schema = eventSchemas.feature_interaction_usage_bucket_reached
+ for (const feature_id of FEATURE_INTERACTION_IDS) {
+ expect(
+ schema.safeParse({
+ feature_id,
+ feature_category: getFeatureInteractionCategory(feature_id),
+ count_bucket: 'count_1',
+ bucket_source: 'crossed_now'
+ }).success
+ ).toBe(true)
+ }
+ })
+
+ it('rejects unknown enum values and mismatched categories', () => {
+ const valid = {
+ feature_id: 'github-tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_1',
+ bucket_source: 'observed_existing'
+ }
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ feature_id: 'unknown-feature'
+ }).success
+ ).toBe(false)
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ feature_category: 'browser'
+ }).success
+ ).toBe(false)
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ count_bucket: 'count_4'
+ }).success
+ ).toBe(false)
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ bucket_source: 'renderer'
+ }).success
+ ).toBe(false)
+ })
+
+ it('rejects raw privacy fields via .strict()', () => {
+ const rawFields = [
+ 'prompt',
+ 'command',
+ 'path',
+ 'repo',
+ 'branch',
+ 'url',
+ 'hostname',
+ 'error',
+ 'text',
+ 'query',
+ 'result_label',
+ 'workspace_name',
+ 'setting_name',
+ 'target_id',
+ 'annotation_text',
+ 'dom_snippet',
+ 'screenshot',
+ 'page_title',
+ 'trusted_directory',
+ 'trigger_x',
+ 'trigger_y',
+ 'focus_state',
+ 'minimize_state',
+ 'audio',
+ 'transcript',
+ 'model',
+ 'device',
+ 'error_detail'
+ ]
+ for (const field of rawFields) {
+ const parsed = eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ feature_id: 'browser-annotations-sent-to-agent',
+ feature_category: 'browser',
+ count_bucket: 'count_1',
+ bucket_source: 'crossed_now',
+ [field]: 'raw'
+ })
+ expect(parsed.success).toBe(false)
+ }
+ })
+})
+
describe('app_starred_orca schema', () => {
it('accepts every declared app star source', () => {
for (const source of appStarSourceSchema.options) {
diff --git a/src/shared/telemetry-events.ts b/src/shared/telemetry-events.ts
index bff2794fb0e..1203e21d357 100644
--- a/src/shared/telemetry-events.ts
+++ b/src/shared/telemetry-events.ts
@@ -25,6 +25,12 @@ import {
TERMINAL_PANE_SPLIT_SOURCES
} from './feature-education-telemetry'
import { FEATURE_WALL_SETUP_STEP_IDS } from './feature-wall-setup-steps'
+import {
+ FEATURE_INTERACTION_CATEGORIES,
+ FEATURE_INTERACTION_IDS,
+ FEATURE_INTERACTION_USAGE_BUCKETS,
+ getFeatureInteractionCategory
+} from './feature-interactions'
import { SETUP_SCRIPT_IMPORT_PROVIDERS } from './setup-script-import-providers'
import { WORKSPACE_SOURCE_VALUES, type WorkspaceSource } from './workspace-source'
import { appStarSourceSchema } from './gh-star-source'
@@ -301,6 +307,27 @@ const nthRepoAddedSchema = z.number().int().nonnegative().optional()
const appOpenedSchema = z.object({ nth_repo_added: nthRepoAddedSchema }).strict()
+export const featureInteractionIdSchema = z.enum(FEATURE_INTERACTION_IDS)
+export const featureInteractionCategorySchema = z.enum(FEATURE_INTERACTION_CATEGORIES)
+export const featureInteractionUsageBucketSchema = z.enum(FEATURE_INTERACTION_USAGE_BUCKETS)
+export const featureInteractionUsageBucketSourceSchema = z.enum([
+ 'crossed_now',
+ 'observed_existing'
+])
+const featureInteractionUsageBucketReachedSchema = z
+ .object({
+ feature_id: featureInteractionIdSchema,
+ feature_category: featureInteractionCategorySchema,
+ count_bucket: featureInteractionUsageBucketSchema,
+ bucket_source: featureInteractionUsageBucketSourceSchema,
+ nth_repo_added: nthRepoAddedSchema
+ })
+ .strict()
+ .refine((value) => getFeatureInteractionCategory(value.feature_id) === value.feature_category, {
+ message: 'feature_category must match feature_id',
+ path: ['feature_category']
+ })
+
const repoAddedSchema = z
// Why: `is_git_repo` is the real git-vs-folder signal, sourced from git
// detection at the add point. It moved here from `onboarding_completed`
@@ -1255,6 +1282,7 @@ const terminalPaneSplitSchema = z
export const eventSchemas = {
app_opened: appOpenedSchema,
app_starred_orca: appStarredOrcaSchema,
+ feature_interaction_usage_bucket_reached: featureInteractionUsageBucketReachedSchema,
repo_added: repoAddedSchema,
add_repo_setup_step_action: addRepoSetupStepActionEventSchema,
@@ -1335,10 +1363,27 @@ export type EventProps = EventMap[N]
// Safely skips non-`ZodObject` schemas (e.g. a future `z.discriminatedUnion`
// or `z.union`) — those have no `.shape`, and probing `key in undefined`
// would throw at module load and take the telemetry module down on import.
+function eventSchemaShape(schema: z.ZodTypeAny): z.ZodRawShape | null {
+ if (schema instanceof z.ZodObject) {
+ return schema.shape
+ }
+
+ const shapeBearingSchema = schema as { shape?: unknown }
+ // Why: refined object schemas may still expose `.shape` even if a Zod
+ // version stops preserving `instanceof ZodObject` through refinement.
+ if (shapeBearingSchema.shape && typeof shapeBearingSchema.shape === 'object') {
+ return shapeBearingSchema.shape as z.ZodRawShape
+ }
+ return null
+}
+
function eventsWithShapeKey(key: string): ReadonlySet {
return new Set(
(Object.entries(eventSchemas) as [EventName, z.ZodTypeAny][])
- .filter(([, schema]) => schema instanceof z.ZodObject && key in schema.shape)
+ .filter(([, schema]) => {
+ const shape = eventSchemaShape(schema)
+ return shape !== null && key in shape
+ })
.map(([name]) => name)
)
}
@@ -1363,6 +1408,7 @@ export const COHORT_EXTENDED: readonly EventName[] = Array.from(COHORT_EXTENDED_
type _CohortExtendedRoster =
| 'app_opened'
| 'app_starred_orca'
+ | 'feature_interaction_usage_bucket_reached'
| 'repo_added'
| 'add_repo_setup_step_action'
| 'add_repo_existing_workspaces_detected'
diff --git a/src/shared/types.ts b/src/shared/types.ts
index 2957a78084a..dec39ee090d 100644
--- a/src/shared/types.ts
+++ b/src/shared/types.ts
@@ -14,7 +14,10 @@ import type { GitLabProjectSettings } from './gitlab-types'
import type { TaskProvider } from './task-providers'
import type { FeatureTipId } from './feature-tips'
import type { ContextualTourId } from './contextual-tours'
-import type { FeatureInteractionState } from './feature-interactions'
+import type {
+ FeatureInteractionState,
+ FeatureInteractionTelemetryBucketState
+} from './feature-interactions'
import type { GitBranchChangeStatus } from './git-status-types'
import type { KeybindingOverrides, TerminalShortcutPolicy } from './keybindings'
import type { RepoIcon } from './repo-icon'
@@ -2880,6 +2883,8 @@ export type PersistedState = {
automations: Automation[]
automationRuns: AutomationRun[]
onboarding: OnboardingState
+ /** Main-owned telemetry de-dupe marker; never exposed through PersistedUIState. */
+ featureInteractionTelemetryBuckets?: FeatureInteractionTelemetryBucketState
}
// ─── Filesystem ─────────────────────────────────────────────