-
{translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.6e3f5223c5", "Explorer")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.6e3f5223c5',
+ 'Explorer'
+ )}
+
@@ -327,38 +157,89 @@ export function ReviewPRViewAnimatedVisual(props: { reducedMotion: boolean }): J
#2351
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.dfe313e0c9", "OPEN")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.dfe313e0c9',
+ 'OPEN'
+ )}
+
+
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.0aab7ab84a',
+ 'Add local diagnostics error tracking'
+ )}
-
{translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.0aab7ab84a", "Add local diagnostics error tracking")}
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.2f37142229", "Squash and merge")}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.2f37142229',
+ 'Squash and merge'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.9a097cae12", "1 pending")}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.9a097cae12',
+ '1 pending'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.d340c052fb", "verify")}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.d340c052fb',
+ 'verify'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.d340c052fb", "verify")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.d340c052fb',
+ 'verify'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.8ed213397c", "Running")}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.8ed213397c',
+ 'Running'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.2ef0b97954", "typecheck")}
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.ca36f7b27c", "Passed")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.2ef0b97954',
+ 'typecheck'
+ )}
+
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.ca36f7b27c',
+ 'Passed'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.25f6838e43", "lint")}
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.ca36f7b27c", "Passed")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.25f6838e43',
+ 'lint'
+ )}
+
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.ca36f7b27c',
+ 'Passed'
+ )}
+
@@ -366,15 +247,43 @@ export function ReviewPRViewAnimatedVisual(props: { reducedMotion: boolean }): J
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.7a8b896e11", "Comments")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.7a8b896e11',
+ 'Comments'
+ )}
+
- 0 {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.fb1a856b6d", "open")}
+ 0 {' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.fb1a856b6d',
+ 'open'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.71828fba75", "Can we include the failing command in the diagnostic payload?")}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.71828fba75',
+ 'Can we include the failing command in the diagnostic payload?'
+ )}
+
- {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.6f4c2d7cb7", "Add a coverage case for")}{translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.c2062da7ec", "stderr")} {translate("auto.components.feature.wall.ReviewPRViewAnimatedVisual.7c2808ecff", "truncation before merge.")}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.6f4c2d7cb7',
+ 'Add a coverage case for'
+ )}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.c2062da7ec',
+ 'stderr'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.7c2808ecff',
+ 'truncation before merge.'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
index 73d711449be..af04080f4de 100644
--- a/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
@@ -15,10 +15,12 @@ type Issue = {
const ISSUES: readonly Issue[] = [
{
number: 1842,
- title: translate(
- 'auto.components.feature.wall.TasksAnimatedVisual.b13375617e',
- 'Worktree picker truncates names'
- )
+ get title() {
+ return translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.b13375617e',
+ 'Worktree picker truncates names'
+ )
+ }
}
]
diff --git a/src/renderer/src/components/feature-wall/feature-tour-preview-copy.ts b/src/renderer/src/components/feature-wall/feature-tour-preview-copy.ts
new file mode 100644
index 00000000000..1aa0dc8abbc
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/feature-tour-preview-copy.ts
@@ -0,0 +1,109 @@
+import { translate } from '@/i18n/i18n'
+
+type FrameId = 1 | 2 | 3 | 4
+
+export type FeatureTourPreviewFrameCopy = {
+ id: FrameId
+ title: string
+ caption: string
+}
+
+export const FEATURE_TOUR_PREVIEW_COPY: readonly FeatureTourPreviewFrameCopy[] = [
+ {
+ id: 1,
+ get title() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.56a0271428',
+ 'Isolated workspaces'
+ )
+ },
+ get caption() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.47f16ecf34',
+ 'Ship several things at once. Each workspace keeps its branch, terminal, and agent activity together.'
+ )
+ }
+ },
+ {
+ id: 2,
+ get title() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.e44269e97d',
+ 'Agent orchestration'
+ )
+ },
+ get caption() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.70aa182266',
+ 'Hand off a goal and walk away. A coordinator agent fans out and ships parallel PRs.'
+ )
+ }
+ },
+ {
+ id: 3,
+ get title() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.ef737dcee1',
+ 'GitHub & Linear tasks'
+ )
+ },
+ get caption() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.f10c14dd9d',
+ 'Skip the tab-switching. Pick from your GitHub or Linear backlog and start a workspace in one click.'
+ )
+ }
+ },
+ {
+ id: 4,
+ get title() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.1aa8a9a24a',
+ 'Splittable terminal'
+ )
+ },
+ get caption() {
+ return translate(
+ 'auto.components.feature.wall.FeatureTourPreview.5d6ee181b6',
+ 'Open any workspace to return to its terminal, then split panes for tests, logs, and agents.'
+ )
+ }
+ }
+]
+
+export type FeatureTourOrchestrationChildAgent = 'claude' | 'codex' | 'opencode-go'
+
+export const FEATURE_TOUR_ORCHESTRATION_CHILDREN: readonly {
+ key: 'top' | 'mid' | 'bot'
+ position: string
+ label: string
+ agent: FeatureTourOrchestrationChildAgent
+}[] = [
+ // Why: card vertical centers anchor to 18% / 50% / 82% — the same Y
+ // endpoints the dashed SVG paths terminate at — so the connectors land on
+ // each card's center regardless of card height.
+ {
+ key: 'top',
+ position: 'top-[18%] -translate-y-1/2',
+ get label() {
+ return translate('auto.components.feature.wall.FeatureTourPreview.b1f17bcc74', 'PR 1/3')
+ },
+ agent: 'claude'
+ },
+ {
+ key: 'mid',
+ position: 'top-1/2 -translate-y-1/2',
+ get label() {
+ return translate('auto.components.feature.wall.FeatureTourPreview.cfdfd4d6b4', 'PR 2/3')
+ },
+ agent: 'codex'
+ },
+ {
+ key: 'bot',
+ position: 'top-[82%] -translate-y-1/2',
+ get label() {
+ return translate('auto.components.feature.wall.FeatureTourPreview.ec4a73f5e6', 'PR 3/3')
+ },
+ agent: 'opencode-go'
+ }
+]
diff --git a/src/renderer/src/components/feature-wall/review-pr-view-animation.ts b/src/renderer/src/components/feature-wall/review-pr-view-animation.ts
new file mode 100644
index 00000000000..bda794340f9
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/review-pr-view-animation.ts
@@ -0,0 +1,261 @@
+import { useEffect } from 'react'
+import type { RefObject } from 'react'
+import { translate } from '@/i18n/i18n'
+
+function getReviewPrAnimatedStatusCopy(): {
+ pendingLabel: string
+ verifyLabel: string
+ runningLabel: string
+ checksPassedLabel: string
+ checksCountLabel: string
+ passedLabel: string
+} {
+ return {
+ pendingLabel: translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.9a097cae12',
+ '1 pending'
+ ),
+ verifyLabel: translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.d340c052fb',
+ 'verify'
+ ),
+ runningLabel: translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.8ed213397c',
+ 'Running'
+ ),
+ checksPassedLabel: translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.a6c8b9e32f',
+ 'Checks passed'
+ ),
+ checksCountLabel: translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.f4d5e1a7b2',
+ '3 checks'
+ ),
+ passedLabel: translate(
+ 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.ca36f7b27c',
+ 'Passed'
+ )
+ }
+}
+
+function moveCursor(
+ root: HTMLElement,
+ cursor: HTMLElement,
+ anchor: HTMLElement,
+ ox = 0,
+ oy = 0
+): void {
+ const rootRect = root.getBoundingClientRect()
+ const anchorRect = anchor.getBoundingClientRect()
+ cursor.style.transform = `translate(${anchorRect.left - rootRect.left + ox}px, ${
+ anchorRect.top - rootRect.top + oy
+ }px)`
+}
+
+export function useReviewPrViewAnimation(
+ rootRef: RefObject
,
+ reducedMotion: boolean
+): void {
+ useEffect(() => {
+ const root = rootRef.current
+ if (!root) {
+ return
+ }
+
+ const sidebarPeek = root.querySelector('[data-checks-sidebar-peek]')
+ const prCard = root.querySelector('[data-pr-view-card]')
+ const cursor = root.querySelector('[data-cursor]')
+ const explorerTab = root.querySelector('[data-explorer-tab]')
+ const checksTab = root.querySelector('[data-checks-tab]')
+ const checksTooltip = root.querySelector('[data-checks-tooltip]')
+ const checksBlock = root.querySelector('[data-checks-block]')
+ const commentsBlock = root.querySelector('[data-comments-block]')
+ const comments = Array.from(root.querySelectorAll('[data-comment-card]'))
+ const commentsCount = root.querySelector('[data-comments-count]')
+ const checkSummary = root.querySelector('[data-check-summary]')
+ const checkSummaryLabel = root.querySelector('[data-check-summary-label]')
+ const checkSummaryMeta = root.querySelector('[data-check-summary-meta]')
+ const verifyRow = root.querySelector('[data-check-row="verify"]')
+ const verifyState = root.querySelector('[data-check-verify-state]')
+ const mergeBtn = root.querySelector('[data-merge-btn]')
+ if (
+ !sidebarPeek ||
+ !prCard ||
+ !cursor ||
+ !explorerTab ||
+ !checksTab ||
+ !checksTooltip ||
+ !checksBlock ||
+ !commentsBlock ||
+ !commentsCount ||
+ !checkSummary ||
+ !checkSummaryLabel ||
+ !checkSummaryMeta ||
+ !verifyRow ||
+ !verifyState ||
+ !mergeBtn
+ ) {
+ return
+ }
+
+ const rootEl: HTMLDivElement = root
+ const sidebarPeekEl: HTMLDivElement = sidebarPeek
+ const prCardEl: HTMLDivElement = prCard
+ const cursorEl: HTMLDivElement = cursor
+ const explorerTabEl: HTMLSpanElement = explorerTab
+ const checksTabEl: HTMLSpanElement = checksTab
+ const checksTooltipEl: HTMLSpanElement = checksTooltip
+ const checksBlockEl: HTMLDivElement = checksBlock
+ const commentsBlockEl: HTMLDivElement = commentsBlock
+ const commentsCountEl: HTMLSpanElement = commentsCount
+ const checkSummaryEl: HTMLDivElement = checkSummary
+ const checkSummaryLabelEl: HTMLSpanElement = checkSummaryLabel
+ const checkSummaryMetaEl: HTMLSpanElement = checkSummaryMeta
+ const verifyRowEl: HTMLDivElement = verifyRow
+ const verifyStateEl: HTMLSpanElement = verifyState
+ const mergeBtnEl: HTMLButtonElement = mergeBtn
+
+ let cancelled = false
+ const timers: number[] = []
+ const wait = (ms: number): Promise =>
+ new Promise((resolve) => {
+ const id = window.setTimeout(() => resolve(), ms)
+ timers.push(id)
+ })
+
+ function resetState(): void {
+ sidebarPeekEl.classList.add('is-visible')
+ sidebarPeekEl.classList.remove('is-hiding')
+ prCardEl.classList.remove('is-visible')
+ explorerTabEl.classList.add('is-active')
+ checksTabEl.classList.remove('is-active', 'is-hovered')
+ checksTooltipEl.classList.remove('is-visible')
+ cursorEl.classList.remove('is-visible', 'is-clicking')
+ cursorEl.style.transition = 'none'
+ cursorEl.style.transform = 'translate(-30px, 220px)'
+ void cursorEl.offsetWidth
+ cursorEl.style.transition = ''
+ checksBlockEl.classList.remove('is-visible')
+ commentsBlockEl.classList.remove('is-visible')
+ comments.forEach((el) => el.classList.remove('is-visible'))
+ commentsCountEl.textContent = '0'
+ checkSummaryEl.classList.remove('is-done')
+ const copy = getReviewPrAnimatedStatusCopy()
+ checkSummaryLabelEl.textContent = copy.pendingLabel
+ checkSummaryMetaEl.textContent = copy.verifyLabel
+ verifyRowEl.classList.remove('is-done')
+ verifyStateEl.textContent = copy.runningLabel
+ mergeBtnEl.classList.remove('is-ready')
+ }
+
+ function showFinalState(): void {
+ resetState()
+ sidebarPeekEl.classList.add('is-hiding')
+ prCardEl.classList.add('is-visible')
+ checksBlockEl.classList.add('is-visible')
+ commentsBlockEl.classList.add('is-visible')
+ comments.forEach((el) => el.classList.add('is-visible'))
+ commentsCountEl.textContent = String(comments.length)
+ checkSummaryEl.classList.add('is-done')
+ const copy = getReviewPrAnimatedStatusCopy()
+ checkSummaryLabelEl.textContent = copy.checksPassedLabel
+ checkSummaryMetaEl.textContent = copy.checksCountLabel
+ verifyRowEl.classList.add('is-done')
+ verifyStateEl.textContent = copy.passedLabel
+ mergeBtnEl.classList.add('is-ready')
+ cursorEl.classList.remove('is-visible')
+ }
+
+ if (reducedMotion) {
+ showFinalState()
+ return
+ }
+
+ async function loop(): Promise {
+ while (!cancelled) {
+ resetState()
+ await wait(420)
+ if (cancelled) {
+ return
+ }
+
+ cursorEl.classList.add('is-visible')
+ moveCursor(rootEl, cursorEl, checksTabEl, 5, 6)
+ checksTabEl.classList.add('is-hovered')
+ await wait(260)
+ if (cancelled) {
+ return
+ }
+ checksTooltipEl.classList.add('is-visible')
+ await wait(1300)
+ if (cancelled) {
+ return
+ }
+
+ cursorEl.classList.add('is-clicking')
+ await wait(220)
+ if (cancelled) {
+ return
+ }
+ cursorEl.classList.remove('is-clicking')
+ checksTooltipEl.classList.remove('is-visible')
+ checksTabEl.classList.remove('is-hovered')
+ explorerTabEl.classList.remove('is-active')
+ checksTabEl.classList.add('is-active')
+ await wait(420)
+ if (cancelled) {
+ return
+ }
+
+ sidebarPeekEl.classList.add('is-hiding')
+ prCardEl.classList.add('is-visible')
+ cursorEl.classList.remove('is-visible')
+ await wait(560)
+ if (cancelled) {
+ return
+ }
+
+ checksBlockEl.classList.add('is-visible')
+ await wait(1050)
+ if (cancelled) {
+ return
+ }
+
+ verifyRowEl.classList.add('is-done')
+ const copy = getReviewPrAnimatedStatusCopy()
+ verifyStateEl.textContent = copy.passedLabel
+ checkSummaryEl.classList.add('is-done')
+ checkSummaryLabelEl.textContent = copy.checksPassedLabel
+ checkSummaryMetaEl.textContent = copy.checksCountLabel
+ mergeBtnEl.classList.add('is-ready')
+
+ await wait(560)
+ if (cancelled) {
+ return
+ }
+ commentsBlockEl.classList.add('is-visible')
+ await wait(260)
+ if (cancelled) {
+ return
+ }
+
+ for (let i = 0; i < comments.length; i++) {
+ comments[i]?.classList.add('is-visible')
+ commentsCountEl.textContent = String(i + 1)
+ await wait(520)
+ if (cancelled) {
+ return
+ }
+ }
+
+ await wait(2900)
+ }
+ }
+
+ void loop()
+ return () => {
+ cancelled = true
+ timers.forEach((timer) => window.clearTimeout(timer))
+ }
+ }, [reducedMotion, rootRef])
+}
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 4321aeeec04..e40fb04c62a 100644
--- a/src/renderer/src/components/github/github-rate-limit-display.tsx
+++ b/src/renderer/src/components/github/github-rate-limit-display.tsx
@@ -20,27 +20,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'
- )
+ get label() {
+ return translate('auto.components.github.github.rate.limit.display.bb227706a6', 'REST')
+ },
+ get description() {
+ return 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'
- )
+ get label() {
+ return translate('auto.components.github.github.rate.limit.display.c377a4f06a', 'Search')
+ },
+ get description() {
+ return 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'
- )
+ get label() {
+ return translate('auto.components.github.github.rate.limit.display.1daf0f22a9', 'GraphQL')
+ },
+ get description() {
+ return translate('auto.components.github.github.rate.limit.display.01f7323e58', 'GraphQL API')
+ }
}
]
diff --git a/src/renderer/src/components/mobile/mobile-platform-copy.ts b/src/renderer/src/components/mobile/mobile-platform-copy.ts
index e09bbbc1eee..dec968086b0 100644
--- a/src/renderer/src/components/mobile/mobile-platform-copy.ts
+++ b/src/renderer/src/components/mobile/mobile-platform-copy.ts
@@ -6,18 +6,22 @@ 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.'
- ),
+ get description() {
+ return 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.'
- ),
+ get description() {
+ return 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/new-workspace/SmartWorkspaceNameField.tsx b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
index 8cbd8bd41d2..38ca4ff3348 100644
--- a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
+++ b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
@@ -11,13 +11,11 @@ import {
GitBranchPlus,
GitMerge,
GitPullRequest,
- Github,
- Gitlab,
LoaderCircle,
Search,
- Sparkles,
X
} from 'lucide-react'
+import { useTranslation } from 'react-i18next'
import { useShallow } from 'zustand/react/shallow'
import { Command, CommandGroup, CommandItem, CommandList } from '@/components/ui/command'
import { Button } from '@/components/ui/button'
@@ -63,29 +61,11 @@ import type {
} from '../../../../shared/types'
import { resolveSmartWorkspaceCommandValue } from './smart-workspace-command-value'
import { translate } from '@/i18n/i18n'
-
-// Why: GitLab MR list filter — Open / Merged / Closed / All — replaces
-// GitHub's search-DSL on the GitLab tab per the agreed scope.
-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')
- }
-]
+import {
+ getMrStateFilters,
+ getSmartWorkspaceNameModes,
+ type MrStateFilter
+} from './smart-workspace-localized-options'
type RepoOption = ReturnType['repos'][number]
@@ -120,47 +100,6 @@ export type SmartWorkspaceNameSelection = {
const SEARCH_DEBOUNCE_MS = 200
const RESULT_LIMIT = 12
-const MODES: {
- id: SmartNameMode
- 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: '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
- }
-]
-
type RowEntry = SmartWorkspaceSourceRow
export default function SmartWorkspaceNameField({
@@ -182,6 +121,9 @@ export default function SmartWorkspaceNameField({
textOnly = false,
branchesEnabled = true
}: SmartWorkspaceNameFieldProps): React.JSX.Element {
+ // Why: tab/filter labels use the lightweight translate() helper; subscribing
+ // here makes them refresh even when language changes don't remount the field.
+ useTranslation()
const {
addRepo,
checkLinearConnection,
@@ -257,25 +199,22 @@ export default function SmartWorkspaceNameField({
)
const gitlabAvailable = availableTaskProviders.includes('gitlab')
const linearAvailable = availableTaskProviders.includes('linear')
- const availableModes = useMemo(
- () =>
- MODES.filter((item) => {
- if (textOnly) {
- return item.id === 'text'
- }
- if (item.id === 'gitlab') {
- return gitlabAvailable
- }
- if (item.id === 'linear') {
- return linearAvailable
- }
- if (item.id === 'branches') {
- return branchesEnabled
- }
- return true
- }),
- [branchesEnabled, gitlabAvailable, linearAvailable, textOnly]
- )
+ const availableModes = getSmartWorkspaceNameModes().filter((item) => {
+ if (textOnly) {
+ return item.id === 'text'
+ }
+ if (item.id === 'gitlab') {
+ return gitlabAvailable
+ }
+ if (item.id === 'linear') {
+ return linearAvailable
+ }
+ if (item.id === 'branches') {
+ return branchesEnabled
+ }
+ return true
+ })
+ const mrStateFilters = getMrStateFilters()
const selectedSourceFocusKey = selectedSource
? `${selectedSource.kind}:${selectedSource.label}:${selectedSource.url ?? ''}`
@@ -1181,7 +1120,7 @@ export default function SmartWorkspaceNameField({
className="flex shrink-0 items-center gap-1 border-b border-border/40 px-2 py-1.5"
onMouseDown={(e) => e.preventDefault()}
>
- {MR_STATE_FILTERS.map(({ id, label }) => (
+ {mrStateFilters.map(({ id, label }) => (
{
+ beforeEach(async () => {
+ await i18n.changeLanguage('en')
+ })
+
+ it('refreshes create-workspace source tabs when the UI language changes', async () => {
+ expect(getSmartWorkspaceNameModes().map((mode) => mode.label)).toEqual([
+ 'Smart',
+ 'GitHub',
+ 'Linear',
+ 'GitLab',
+ 'Branch',
+ 'Name'
+ ])
+
+ await i18n.changeLanguage('zh')
+
+ expect(getSmartWorkspaceNameModes().map((mode) => mode.label)).toEqual([
+ '聪明的',
+ 'GitHub',
+ 'Linear',
+ 'GitLab',
+ '分支',
+ '姓名'
+ ])
+
+ await i18n.changeLanguage('en')
+
+ expect(getSmartWorkspaceNameModes().map((mode) => mode.label)).toEqual([
+ 'Smart',
+ 'GitHub',
+ 'Linear',
+ 'GitLab',
+ 'Branch',
+ 'Name'
+ ])
+ })
+
+ it('refreshes GitLab state filters when the UI language changes', async () => {
+ expect(getMrStateFilters().map((filter) => filter.label)).toEqual([
+ 'Open',
+ 'Merged',
+ 'Closed',
+ 'All'
+ ])
+
+ await i18n.changeLanguage('zh')
+
+ expect(getMrStateFilters().map((filter) => filter.label)).toEqual([
+ '进行中',
+ '合并',
+ '已关闭',
+ '全部'
+ ])
+ })
+})
diff --git a/src/renderer/src/components/new-workspace/smart-workspace-localized-options.tsx b/src/renderer/src/components/new-workspace/smart-workspace-localized-options.tsx
new file mode 100644
index 00000000000..553fc696f7e
--- /dev/null
+++ b/src/renderer/src/components/new-workspace/smart-workspace-localized-options.tsx
@@ -0,0 +1,89 @@
+import type React from 'react'
+import { CaseSensitive, GitBranch, Github, Gitlab, Sparkles } from 'lucide-react'
+
+import { translate } from '@/i18n/i18n'
+import type { SmartNameMode } from './smart-workspace-source-results'
+
+export type MrStateFilter = 'opened' | 'merged' | 'closed' | 'all'
+
+export type SmartWorkspaceNameModeOption = {
+ id: SmartNameMode
+ label: string
+ Icon: React.ComponentType<{ className?: string }>
+}
+
+function LinearModeIcon({ className }: { className?: string }): React.JSX.Element {
+ return (
+
+
+
+ )
+}
+
+export function getMrStateFilters(): { id: MrStateFilter; label: string }[] {
+ return [
+ {
+ 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')
+ }
+ ]
+}
+
+export function getSmartWorkspaceNameModes(): SmartWorkspaceNameModeOption[] {
+ return [
+ {
+ 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'
+ ),
+ Icon: LinearModeIcon
+ },
+ {
+ 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
+ }
+ ]
+}
diff --git a/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx b/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
index 56e79fb2890..66b1285401e 100644
--- a/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
+++ b/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
@@ -23,37 +23,52 @@ 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.'
- ),
+ get title() {
+ return translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.ea85d9e628',
+ 'Agent Browser Use'
+ )
+ },
+ get description() {
+ return 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.'
- ),
+ get title() {
+ return translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.1ecfb490ac',
+ 'Computer Use'
+ )
+ },
+ get description() {
+ return 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.'
- ),
+ get title() {
+ return translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.399cf885c0',
+ 'Agent Orchestration'
+ )
+ },
+ get description() {
+ return 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/OnboardingFlow.tsx b/src/renderer/src/components/onboarding/OnboardingFlow.tsx
index 791cf11d624..2605ebd7369 100644
--- a/src/renderer/src/components/onboarding/OnboardingFlow.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingFlow.tsx
@@ -17,41 +17,60 @@ 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."
- )
+ get title() {
+ return translate(
+ 'auto.components.onboarding.OnboardingFlow.198b148b3c',
+ 'Pick your default agent'
+ )
+ },
+ get subtitle() {
+ return 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.'
- )
+ get title() {
+ return translate(
+ 'auto.components.onboarding.OnboardingFlow.f396db9f20',
+ 'Make it feel like home'
+ )
+ },
+ get subtitle() {
+ return 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.'
- )
+ get title() {
+ return translate(
+ 'auto.components.onboarding.OnboardingFlow.b054332836',
+ 'Set up notifications'
+ )
+ },
+ get subtitle() {
+ return translate(
+ 'auto.components.onboarding.OnboardingFlow.ff92d15436',
+ 'Orca will notify you 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:'
- )
+ get title() {
+ return translate(
+ 'auto.components.onboarding.OnboardingFlow.ae3b00ca82',
+ 'Set up GitHub tasks'
+ )
+ },
+ get subtitle() {
+ return translate(
+ 'auto.components.onboarding.OnboardingFlow.97c42cda00',
+ 'Install the GitHub CLI to:'
+ )
+ }
}
} as const
diff --git a/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx b/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
index 4b7d2602ded..1a721a6d774 100644
--- a/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
@@ -10,14 +10,18 @@ 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!"
- ),
+ get title() {
+ return translate(
+ 'auto.components.onboarding.OnboardingSkipConfirmationDialog.e4726b2d50',
+ 'Skip onboarding?'
+ )
+ },
+ get description() {
+ return 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/pet/pet-models.ts b/src/renderer/src/components/pet/pet-models.ts
index cf81da698df..1e7e1471335 100644
--- a/src/renderer/src/components/pet/pet-models.ts
+++ b/src/renderer/src/components/pet/pet-models.ts
@@ -21,17 +21,23 @@ export type BundledPet = {
export const BUNDLED_PETS: readonly BundledPet[] = [
{
id: DEFAULT_PET_ID,
- label: translate('auto.components.pet.pet.models.2528586aa7', 'Claudino'),
+ get label() {
+ return translate('auto.components.pet.pet.models.2528586aa7', 'Claudino')
+ },
url: claudeUrl
},
{
id: OPENCODE_PET_ID,
- label: translate('auto.components.pet.pet.models.a84d5677ff', 'OpenCode'),
+ get label() {
+ return translate('auto.components.pet.pet.models.a84d5677ff', 'OpenCode')
+ },
url: opencodeUrl
},
{
id: GREMLIN_PET_ID,
- label: translate('auto.components.pet.pet.models.7433516faf', 'Gremlin'),
+ get label() {
+ return translate('auto.components.pet.pet.models.7433516faf', 'Gremlin')
+ },
url: gremlinUrl
}
] as const
diff --git a/src/renderer/src/components/settings/ComputerUsePane.tsx b/src/renderer/src/components/settings/ComputerUsePane.tsx
index 22e8306262d..281a6e769ee 100644
--- a/src/renderer/src/components/settings/ComputerUsePane.tsx
+++ b/src/renderer/src/components/settings/ComputerUsePane.tsx
@@ -42,20 +42,28 @@ type PermissionDefinition = {
const PERMISSIONS: PermissionDefinition[] = [
{
id: 'accessibility',
- label: translate('auto.components.settings.ComputerUsePane.6b5a2cd3a5', 'Accessibility'),
- description: translate(
- 'auto.components.settings.ComputerUsePane.4d03dec2d0',
- 'Read app interface trees and perform requested actions.'
- ),
+ get label() {
+ return translate('auto.components.settings.ComputerUsePane.6b5a2cd3a5', 'Accessibility')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.ComputerUsePane.4d03dec2d0',
+ 'Read app interface trees and perform requested actions.'
+ )
+ },
icon:
},
{
id: 'screenshots',
- label: translate('auto.components.settings.ComputerUsePane.07bbe4c4cb', 'Screenshots'),
- description: translate(
- 'auto.components.settings.ComputerUsePane.0c9a33f468',
- 'Capture app windows so agents can inspect visual state.'
- ),
+ get label() {
+ return translate('auto.components.settings.ComputerUsePane.07bbe4c4cb', 'Screenshots')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.ComputerUsePane.0c9a33f468',
+ 'Capture app windows so agents can inspect visual state.'
+ )
+ },
icon:
}
]
diff --git a/src/renderer/src/components/settings/DeveloperPermissionsPane.tsx b/src/renderer/src/components/settings/DeveloperPermissionsPane.tsx
index 523426e5462..e3ec17351c9 100644
--- a/src/renderer/src/components/settings/DeveloperPermissionsPane.tsx
+++ b/src/renderer/src/components/settings/DeveloperPermissionsPane.tsx
@@ -34,103 +34,142 @@ type PermissionDefinition = {
const PERMISSIONS: PermissionDefinition[] = [
{
id: 'microphone',
- label: translate('auto.components.settings.DeveloperPermissionsPane.16381e040a', 'Microphone'),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.cc8151d9fa',
- 'Voice input, transcription, audio recording, sox, ffmpeg, and Whisper CLIs.'
- ),
+ get label() {
+ return translate('auto.components.settings.DeveloperPermissionsPane.16381e040a', 'Microphone')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.cc8151d9fa',
+ 'Voice input, transcription, audio recording, sox, ffmpeg, and Whisper CLIs.'
+ )
+ },
actionLabel: 'Request',
icon:
},
{
id: 'camera',
- label: translate('auto.components.settings.DeveloperPermissionsPane.e5b5f3d6b9', 'Camera'),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.550cfa3750',
- 'Webcam capture and camera-driven local test apps.'
- ),
+ get label() {
+ return translate('auto.components.settings.DeveloperPermissionsPane.e5b5f3d6b9', 'Camera')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.550cfa3750',
+ 'Webcam capture and camera-driven local test apps.'
+ )
+ },
actionLabel: 'Request',
icon:
},
{
id: 'screen',
- label: translate(
- 'auto.components.settings.DeveloperPermissionsPane.f24f31a884',
- 'Screen Recording'
- ),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.0639db5496',
- 'Screenshot, visual automation, and UI inspection tools.'
- ),
+ get label() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.f24f31a884',
+ 'Screen Recording'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.0639db5496',
+ 'Screenshot, visual automation, and UI inspection tools.'
+ )
+ },
actionLabel: 'Open Settings',
icon:
},
{
id: 'accessibility',
- label: translate(
- 'auto.components.settings.DeveloperPermissionsPane.5b2f22ca2d',
- 'Accessibility'
- ),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.9f35980756',
- 'Keystroke injection, window control, and UI automation tools.'
- ),
+ get label() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.5b2f22ca2d',
+ 'Accessibility'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.9f35980756',
+ 'Keystroke injection, window control, and UI automation tools.'
+ )
+ },
actionLabel: 'Request',
icon:
},
{
id: 'full-disk-access',
- label: translate(
- 'auto.components.settings.DeveloperPermissionsPane.c566bca278',
- 'Full Disk Access'
- ),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.7ca17b62c8',
- 'Persistent access to protected folders from terminal sessions.'
- ),
+ get label() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.c566bca278',
+ 'Full Disk Access'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.7ca17b62c8',
+ 'Persistent access to protected folders from terminal sessions.'
+ )
+ },
actionLabel: 'Open Settings',
icon:
},
{
id: 'automation',
- label: translate('auto.components.settings.DeveloperPermissionsPane.e119f0d66b', 'Automation'),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.4a73f5217a',
- 'Apple Events for scripts that control other local apps.'
- ),
+ get label() {
+ return translate('auto.components.settings.DeveloperPermissionsPane.e119f0d66b', 'Automation')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.4a73f5217a',
+ 'Apple Events for scripts that control other local apps.'
+ )
+ },
actionLabel: 'Trigger Prompt',
icon:
},
{
id: 'local-network',
- label: translate(
- 'auto.components.settings.DeveloperPermissionsPane.e7bb06007c',
- 'Local Network'
- ),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.f903bf20b5',
- 'Discovery and access for development servers on your network.'
- ),
+ get label() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.e7bb06007c',
+ 'Local Network'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.f903bf20b5',
+ 'Discovery and access for development servers on your network.'
+ )
+ },
actionLabel: 'Trigger Prompt',
icon:
},
{
id: 'usb',
- label: translate('auto.components.settings.DeveloperPermissionsPane.bf51e4a542', 'USB Devices'),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.dfbc12c8c8',
- 'Hardware debugging and device tools that talk to USB devices.'
- ),
+ get label() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.bf51e4a542',
+ 'USB Devices'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.dfbc12c8c8',
+ 'Hardware debugging and device tools that talk to USB devices.'
+ )
+ },
actionLabel: 'Open Settings',
icon:
},
{
id: 'bluetooth',
- label: translate('auto.components.settings.DeveloperPermissionsPane.b2210b1b4f', 'Bluetooth'),
- description: translate(
- 'auto.components.settings.DeveloperPermissionsPane.4cfaa7e98a',
- 'Bluetooth device tools and local hardware experiments.'
- ),
+ get label() {
+ return translate('auto.components.settings.DeveloperPermissionsPane.b2210b1b4f', 'Bluetooth')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.DeveloperPermissionsPane.4cfaa7e98a',
+ 'Bluetooth device tools and local hardware experiments.'
+ )
+ },
actionLabel: 'Open Settings',
icon:
}
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
index 4a2e6aba53e..7d620ee7ace 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
@@ -19,31 +19,39 @@ type RepositorySourceControlAiHostedReviewDefaultsProps = {
const HOSTED_REVIEW_DEFAULT_ROWS: { key: HostedReviewDefaultKey; label: string }[] = [
{
key: 'draft',
- label: translate(
- 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.981eae7e14',
- 'Draft by default'
- )
+ get label() {
+ return translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.981eae7e14',
+ 'Draft by default'
+ )
+ }
},
{
key: 'useTemplate',
- label: translate(
- 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.d32b87e754',
- 'Use review template when available'
- )
+ get label() {
+ return 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'
- )
+ get label() {
+ return 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'
- )
+ get label() {
+ return translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.629ed8a9d3',
+ 'Open hosted review after creation'
+ )
+ }
}
]
diff --git a/src/renderer/src/components/settings/Settings.tsx b/src/renderer/src/components/settings/Settings.tsx
index 7b5ef155881..cc4d57cd6d0 100644
--- a/src/renderer/src/components/settings/Settings.tsx
+++ b/src/renderer/src/components/settings/Settings.tsx
@@ -89,29 +89,51 @@ import { translate } from '@/i18n/i18n'
const SETTINGS_NAV_GROUPS = [
{
id: 'capabilities',
- title: translate('auto.components.settings.Settings.23c6874fdf', 'AI Capabilities')
+ get title() {
+ return translate('auto.components.settings.Settings.23c6874fdf', 'AI Capabilities')
+ }
+ },
+ {
+ id: 'setup',
+ get title() {
+ return translate('auto.components.settings.Settings.9abb9be3bc', 'Set Up')
+ }
},
- { id: 'setup', title: translate('auto.components.settings.Settings.9abb9be3bc', 'Set Up') },
{
id: 'workflows',
- title: translate('auto.components.settings.Settings.e1578cd4bc', 'Workflows')
+ get title() {
+ return translate('auto.components.settings.Settings.e1578cd4bc', 'Workflows')
+ }
},
{
id: 'interface',
- title: translate('auto.components.settings.Settings.8bd117d669', 'Interface')
+ get title() {
+ return translate('auto.components.settings.Settings.8bd117d669', 'Interface')
+ }
},
{
id: 'remote',
- title: translate('auto.components.settings.Settings.23931df7e8', 'Remote Access')
+ get title() {
+ return translate('auto.components.settings.Settings.23931df7e8', 'Remote Access')
+ }
},
{
id: 'security',
- title: translate('auto.components.settings.Settings.084d8fac5b', 'Privacy & Security')
+ get title() {
+ return translate('auto.components.settings.Settings.084d8fac5b', 'Privacy & Security')
+ }
+ },
+ {
+ id: 'advanced',
+ get title() {
+ return translate('auto.components.settings.Settings.1c87f8d024', 'Advanced')
+ }
},
- { id: 'advanced', title: translate('auto.components.settings.Settings.1c87f8d024', 'Advanced') },
{
id: 'experimental',
- title: translate('auto.components.settings.Settings.8b017f2506', 'Experimental')
+ get title() {
+ return translate('auto.components.settings.Settings.8b017f2506', 'Experimental')
+ }
}
] as const
diff --git a/src/renderer/src/components/settings/SourceControlAiActionRecipeDefaults.tsx b/src/renderer/src/components/settings/SourceControlAiActionRecipeDefaults.tsx
index efd9db8fba2..c54390e2a8d 100644
--- a/src/renderer/src/components/settings/SourceControlAiActionRecipeDefaults.tsx
+++ b/src/renderer/src/components/settings/SourceControlAiActionRecipeDefaults.tsx
@@ -29,36 +29,51 @@ type SourceControlAiActionRecipeDefaultsProps = {
}
const ACTION_RECIPES_SEARCH_ENTRY = {
- title: translate(
- 'auto.components.settings.SourceControlAiActionRecipeDefaults.a79c567194',
- 'Action recipes'
- ),
- description: translate(
- 'auto.components.settings.SourceControlAiActionRecipeDefaults.cf01d41bce',
- 'Agent, CLI arguments, and command template used by each Source Control AI button.'
- ),
- keywords: [
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.926d58e87f', 'agent'),
- translate(
- 'auto.components.settings.SourceControlAiActionRecipeDefaults.db9bd75d10',
- 'arguments'
- ),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.2576299196', 'args'),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.673369fe0c', 'cli'),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.d74fdc776c', 'command'),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.eb7e8f3b39', 'model'),
- translate(
- 'auto.components.settings.SourceControlAiActionRecipeDefaults.2037c78a6f',
- 'template'
- ),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.cb67b938c5', 'fix'),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.06a9dab64d', 'checks'),
- translate('auto.components.settings.SourceControlAiActionRecipeDefaults.e5b24893ba', 'commit'),
- translate(
- 'auto.components.settings.SourceControlAiActionRecipeDefaults.7ab1437a12',
- 'pull request'
+ get title() {
+ return translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.a79c567194',
+ 'Action recipes'
)
- ]
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.cf01d41bce',
+ 'Agent, CLI arguments, and command template used by each Source Control AI button.'
+ )
+ },
+ get keywords() {
+ return [
+ translate('auto.components.settings.SourceControlAiActionRecipeDefaults.926d58e87f', 'agent'),
+ translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.db9bd75d10',
+ 'arguments'
+ ),
+ translate('auto.components.settings.SourceControlAiActionRecipeDefaults.2576299196', 'args'),
+ translate('auto.components.settings.SourceControlAiActionRecipeDefaults.673369fe0c', 'cli'),
+ translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.d74fdc776c',
+ 'command'
+ ),
+ translate('auto.components.settings.SourceControlAiActionRecipeDefaults.eb7e8f3b39', 'model'),
+ translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.2037c78a6f',
+ 'template'
+ ),
+ translate('auto.components.settings.SourceControlAiActionRecipeDefaults.cb67b938c5', 'fix'),
+ translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.06a9dab64d',
+ 'checks'
+ ),
+ translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.e5b24893ba',
+ 'commit'
+ ),
+ translate(
+ 'auto.components.settings.SourceControlAiActionRecipeDefaults.7ab1437a12',
+ 'pull request'
+ )
+ ]
+ }
}
export function SourceControlAiActionRecipeDefaults({
@@ -127,19 +142,7 @@ export function SourceControlAiActionRecipeDefaults({
diff --git a/src/renderer/src/components/settings/SshTargetCard.tsx b/src/renderer/src/components/settings/SshTargetCard.tsx
index a41c560b571..d61d16143a1 100644
--- a/src/renderer/src/components/settings/SshTargetCard.tsx
+++ b/src/renderer/src/components/settings/SshTargetCard.tsx
@@ -29,7 +29,9 @@ export const STATUS_LABELS: Record
= {
connected: 'Connected',
reconnecting: 'Reconnecting\u2026',
'reconnection-failed': 'Reconnection failed',
- error: translate('auto.components.settings.SshTargetCard.18968ede9e', 'Error')
+ get error() {
+ return translate('auto.components.settings.SshTargetCard.18968ede9e', 'Error')
+ }
}
export function statusColor(status: SshConnectionStatus): string {
diff --git a/src/renderer/src/components/settings/TasksPane.tsx b/src/renderer/src/components/settings/TasksPane.tsx
index 2195201b112..c95383a013b 100644
--- a/src/renderer/src/components/settings/TasksPane.tsx
+++ b/src/renderer/src/components/settings/TasksPane.tsx
@@ -26,38 +26,54 @@ 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.'
- ),
+ get label() {
+ return translate('auto.components.settings.TasksPane.e14063e727', 'GitHub')
+ },
+ get description() {
+ return 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.'
- ),
+ get label() {
+ return translate('auto.components.settings.TasksPane.7c5d7fdc20', 'GitLab')
+ },
+ get description() {
+ return 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.'
- ),
+ get label() {
+ return translate('auto.components.settings.TasksPane.09ae2d7c51', 'Linear')
+ },
+ get description() {
+ return 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.'
- ),
+ get label() {
+ return translate('auto.components.settings.TasksPane.6b23a34f6d', 'Jira')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TasksPane.8e1305fcc6',
+ 'Show Jira in the Tasks source picker and sidebar shortcuts.'
+ )
+ },
Icon: ({ className }) =>
}
]
diff --git a/src/renderer/src/components/settings/TerminalWindowSection.tsx b/src/renderer/src/components/settings/TerminalWindowSection.tsx
index 928ccce0eab..79deff85d0c 100644
--- a/src/renderer/src/components/settings/TerminalWindowSection.tsx
+++ b/src/renderer/src/components/settings/TerminalWindowSection.tsx
@@ -19,57 +19,339 @@ const COLOR_OVERRIDE_GROUPS: {
keys: { key: keyof TerminalColorOverrides; label: string; description: string }[]
}[] = [
{
- label: translate("auto.components.settings.TerminalWindowSection.cf37ff69f6", "Base"),
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.cf37ff69f6', 'Base')
+ },
keys: [
- { key: 'foreground', label: translate("auto.components.settings.TerminalWindowSection.79f6bfb76e", "Foreground"), description: translate("auto.components.settings.TerminalWindowSection.026a0b8013", "Main text color") },
- { key: 'background', label: translate("auto.components.settings.TerminalWindowSection.cc1b2ffeb2", "Background"), description: translate("auto.components.settings.TerminalWindowSection.da64e8f4c1", "Terminal background color") },
- { key: 'cursor', label: translate("auto.components.settings.TerminalWindowSection.c9e1fdf42f", "Cursor"), description: translate("auto.components.settings.TerminalWindowSection.cd0700762b", "Cursor color") },
+ {
+ key: 'foreground',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.79f6bfb76e',
+ 'Foreground'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.026a0b8013',
+ 'Main text color'
+ )
+ }
+ },
+ {
+ key: 'background',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.cc1b2ffeb2',
+ 'Background'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.da64e8f4c1',
+ 'Terminal background color'
+ )
+ }
+ },
+ {
+ key: 'cursor',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.c9e1fdf42f', 'Cursor')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.cd0700762b',
+ 'Cursor color'
+ )
+ }
+ },
{
key: 'cursorAccent',
- label: translate("auto.components.settings.TerminalWindowSection.a2d9f095a7", "Cursor Text"),
- description: translate("auto.components.settings.TerminalWindowSection.7f4063076c", "Color of text under the cursor (block cursor)")
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.a2d9f095a7',
+ 'Cursor Text'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.7f4063076c',
+ 'Color of text under the cursor (block cursor)'
+ )
+ }
},
{
key: 'selectionBackground',
- label: translate("auto.components.settings.TerminalWindowSection.40c3cfd30a", "Selection Background"),
- description: translate("auto.components.settings.TerminalWindowSection.74d8555f85", "Background color of selected text")
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.40c3cfd30a',
+ 'Selection Background'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.74d8555f85',
+ 'Background color of selected text'
+ )
+ }
},
{
key: 'selectionForeground',
- label: translate("auto.components.settings.TerminalWindowSection.8b450b5305", "Selection Foreground"),
- description: translate("auto.components.settings.TerminalWindowSection.b2c0857c49", "Text color of selected text")
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.8b450b5305',
+ 'Selection Foreground'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.b2c0857c49',
+ 'Text color of selected text'
+ )
+ }
},
{
key: 'bold',
- label: translate("auto.components.settings.TerminalWindowSection.862e463f7f", "Bold Text"),
- description: translate("auto.components.settings.TerminalWindowSection.fb8c6f1967", "Color for bold text. Falls back to the normal color if not set.")
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.862e463f7f', 'Bold Text')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.fb8c6f1967',
+ 'Color for bold text. Falls back to the normal color if not set.'
+ )
+ }
}
]
},
{
- label: translate("auto.components.settings.TerminalWindowSection.68e9f07de0", "ANSI Normal"),
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.68e9f07de0', 'ANSI Normal')
+ },
keys: [
- { key: 'black', label: translate("auto.components.settings.TerminalWindowSection.adfdee23cb", "Black"), description: translate("auto.components.settings.TerminalWindowSection.cf4437a2f7", "ANSI black color") },
- { key: 'red', label: translate("auto.components.settings.TerminalWindowSection.3a78f30b50", "Red"), description: translate("auto.components.settings.TerminalWindowSection.b41270f5ca", "ANSI red color") },
- { key: 'green', label: translate("auto.components.settings.TerminalWindowSection.8f2092b315", "Green"), description: translate("auto.components.settings.TerminalWindowSection.8a673d4206", "ANSI green color") },
- { key: 'yellow', label: translate("auto.components.settings.TerminalWindowSection.bb516de873", "Yellow"), description: translate("auto.components.settings.TerminalWindowSection.09c1c6b096", "ANSI yellow color") },
- { key: 'blue', label: translate("auto.components.settings.TerminalWindowSection.292a4c7316", "Blue"), description: translate("auto.components.settings.TerminalWindowSection.9635a71c51", "ANSI blue color") },
- { key: 'magenta', label: translate("auto.components.settings.TerminalWindowSection.d5e92fcd94", "Magenta"), description: translate("auto.components.settings.TerminalWindowSection.1705318506", "ANSI magenta color") },
- { key: 'cyan', label: translate("auto.components.settings.TerminalWindowSection.fb8bb4eb1f", "Cyan"), description: translate("auto.components.settings.TerminalWindowSection.bd4c759327", "ANSI cyan color") },
- { key: 'white', label: translate("auto.components.settings.TerminalWindowSection.0cb4459fb8", "White"), description: translate("auto.components.settings.TerminalWindowSection.28846b1ca6", "ANSI white color") }
+ {
+ key: 'black',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.adfdee23cb', 'Black')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.cf4437a2f7',
+ 'ANSI black color'
+ )
+ }
+ },
+ {
+ key: 'red',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.3a78f30b50', 'Red')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.b41270f5ca',
+ 'ANSI red color'
+ )
+ }
+ },
+ {
+ key: 'green',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.8f2092b315', 'Green')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.8a673d4206',
+ 'ANSI green color'
+ )
+ }
+ },
+ {
+ key: 'yellow',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.bb516de873', 'Yellow')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.09c1c6b096',
+ 'ANSI yellow color'
+ )
+ }
+ },
+ {
+ key: 'blue',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.292a4c7316', 'Blue')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.9635a71c51',
+ 'ANSI blue color'
+ )
+ }
+ },
+ {
+ key: 'magenta',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.d5e92fcd94', 'Magenta')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.1705318506',
+ 'ANSI magenta color'
+ )
+ }
+ },
+ {
+ key: 'cyan',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.fb8bb4eb1f', 'Cyan')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.bd4c759327',
+ 'ANSI cyan color'
+ )
+ }
+ },
+ {
+ key: 'white',
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.0cb4459fb8', 'White')
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.28846b1ca6',
+ 'ANSI white color'
+ )
+ }
+ }
]
},
{
- label: translate("auto.components.settings.TerminalWindowSection.1be593d3e8", "ANSI Bright"),
+ get label() {
+ return translate('auto.components.settings.TerminalWindowSection.1be593d3e8', 'ANSI Bright')
+ },
keys: [
- { key: 'brightBlack', label: translate("auto.components.settings.TerminalWindowSection.260d69ce9a", "Bright Black"), description: translate("auto.components.settings.TerminalWindowSection.f30c492769", "ANSI bright black color") },
- { key: 'brightRed', label: translate("auto.components.settings.TerminalWindowSection.32b1b6acd7", "Bright Red"), description: translate("auto.components.settings.TerminalWindowSection.667de68863", "ANSI bright red color") },
- { key: 'brightGreen', label: translate("auto.components.settings.TerminalWindowSection.7dafd57730", "Bright Green"), description: translate("auto.components.settings.TerminalWindowSection.0ffb02f921", "ANSI bright green color") },
- { key: 'brightYellow', label: translate("auto.components.settings.TerminalWindowSection.936a326be3", "Bright Yellow"), description: translate("auto.components.settings.TerminalWindowSection.e2ef5f4ab7", "ANSI bright yellow color") },
- { key: 'brightBlue', label: translate("auto.components.settings.TerminalWindowSection.66820332fa", "Bright Blue"), description: translate("auto.components.settings.TerminalWindowSection.bef6c0f6bf", "ANSI bright blue color") },
- { key: 'brightMagenta', label: translate("auto.components.settings.TerminalWindowSection.e56e7d6ea0", "Bright Magenta"), description: translate("auto.components.settings.TerminalWindowSection.fe4d89ef85", "ANSI bright magenta color") },
- { key: 'brightCyan', label: translate("auto.components.settings.TerminalWindowSection.f94adc4113", "Bright Cyan"), description: translate("auto.components.settings.TerminalWindowSection.1601140f03", "ANSI bright cyan color") },
- { key: 'brightWhite', label: translate("auto.components.settings.TerminalWindowSection.16948119cb", "Bright White"), description: translate("auto.components.settings.TerminalWindowSection.42e01a6055", "ANSI bright white color") }
+ {
+ key: 'brightBlack',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.260d69ce9a',
+ 'Bright Black'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.f30c492769',
+ 'ANSI bright black color'
+ )
+ }
+ },
+ {
+ key: 'brightRed',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.32b1b6acd7',
+ 'Bright Red'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.667de68863',
+ 'ANSI bright red color'
+ )
+ }
+ },
+ {
+ key: 'brightGreen',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.7dafd57730',
+ 'Bright Green'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.0ffb02f921',
+ 'ANSI bright green color'
+ )
+ }
+ },
+ {
+ key: 'brightYellow',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.936a326be3',
+ 'Bright Yellow'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.e2ef5f4ab7',
+ 'ANSI bright yellow color'
+ )
+ }
+ },
+ {
+ key: 'brightBlue',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.66820332fa',
+ 'Bright Blue'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.bef6c0f6bf',
+ 'ANSI bright blue color'
+ )
+ }
+ },
+ {
+ key: 'brightMagenta',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.e56e7d6ea0',
+ 'Bright Magenta'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.fe4d89ef85',
+ 'ANSI bright magenta color'
+ )
+ }
+ },
+ {
+ key: 'brightCyan',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.f94adc4113',
+ 'Bright Cyan'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.1601140f03',
+ 'ANSI bright cyan color'
+ )
+ }
+ },
+ {
+ key: 'brightWhite',
+ get label() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.16948119cb',
+ 'Bright White'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.settings.TerminalWindowSection.42e01a6055',
+ 'ANSI bright white color'
+ )
+ }
+ }
]
}
]
@@ -106,18 +388,37 @@ export function TerminalWindowSection({
return (
-
{translate("auto.components.settings.TerminalWindowSection.b96ba13ed1", "Window")}
-
{translate("auto.components.settings.TerminalWindowSection.00eaa6b881", "Window appearance and background settings.")}
+
+ {translate('auto.components.settings.TerminalWindowSection.b96ba13ed1', 'Window')}
+
+
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.00eaa6b881',
+ 'Window appearance and background settings.'
+ )}
+
-
{translate("auto.components.settings.TerminalWindowSection.2b82242f43", "Window Blur")}
+
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.2b82242f43',
+ 'Window Blur'
+ )}
+
- {translate("auto.components.settings.TerminalWindowSection.97950bb087", "Apply background blur to the terminal window. Requires restart.")}
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.97950bb087',
+ 'Apply background blur to the terminal window. Requires restart.'
+ )}
+
- {translate("auto.components.settings.TerminalWindowSection.c65bb9ce63", "Restart required")}
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.c65bb9ce63',
+ 'Restart required'
+ )}
+
- {translate("auto.components.settings.TerminalWindowSection.53ce336e15", "Restart Orca to apply the window blur change.")}
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.53ce336e15',
+ 'Restart Orca to apply the window blur change.'
+ )}
+
void handleRelaunch()}
>
- {relaunchingBlur ? translate("auto.components.settings.TerminalWindowSection.907131d741", "Restarting…") : translate("auto.components.settings.TerminalWindowSection.8abdab9f7c", "Restart now")}
+ {relaunchingBlur
+ ? translate(
+ 'auto.components.settings.TerminalWindowSection.907131d741',
+ 'Restarting…'
+ )
+ : translate(
+ 'auto.components.settings.TerminalWindowSection.8abdab9f7c',
+ 'Restart now'
+ )}
) : null}
-
{translate("auto.components.settings.TerminalWindowSection.3530908ef9", "Hide Mouse While Typing")}
+
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.3530908ef9',
+ 'Hide Mouse While Typing'
+ )}
+
- {translate("auto.components.settings.TerminalWindowSection.1d1920dc8a", "Hide the mouse cursor when typing in the terminal.")}
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.1d1920dc8a',
+ 'Hide the mouse cursor when typing in the terminal.'
+ )}
+
@@ -263,7 +640,11 @@ export function TerminalWindowSection({
▶
- {translate("auto.components.settings.TerminalWindowSection.63f8d9336e", "Color Overrides")}
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.63f8d9336e',
+ 'Color Overrides'
+ )}
+
updateSettings({ terminalColorOverrides: undefined })}
>
- {translate("auto.components.settings.TerminalWindowSection.03c855d15f", "Reset all color overrides")}
+ {translate(
+ 'auto.components.settings.TerminalWindowSection.03c855d15f',
+ 'Reset all color overrides'
+ )}
+
diff --git a/src/renderer/src/components/settings/mobile-auto-restore-options.ts b/src/renderer/src/components/settings/mobile-auto-restore-options.ts
index 4c4c70c3962..f0659d70835 100644
--- a/src/renderer/src/components/settings/mobile-auto-restore-options.ts
+++ b/src/renderer/src/components/settings/mobile-auto-restore-options.ts
@@ -3,25 +3,33 @@ import { translate } from '@/i18n/i18n'
export const AUTO_RESTORE_FIT_OPTIONS: { value: string; label: string; ms: number | null }[] = [
{
value: 'indefinite',
- label: translate(
- 'auto.components.settings.MobilePane.aa1263e881',
- 'Keep at phone size (default)'
- ),
+ get label() {
+ return translate(
+ 'auto.components.settings.MobilePane.aa1263e881',
+ 'Keep at phone size (default)'
+ )
+ },
ms: null
},
{
value: '60s',
- label: translate('auto.components.settings.MobilePane.c474aa09d8', 'After 1 minute'),
+ get label() {
+ return translate('auto.components.settings.MobilePane.c474aa09d8', 'After 1 minute')
+ },
ms: 60_000
},
{
value: '5m',
- label: translate('auto.components.settings.MobilePane.d4ba07d914', 'After 5 minutes'),
+ get label() {
+ return translate('auto.components.settings.MobilePane.d4ba07d914', 'After 5 minutes')
+ },
ms: 5 * 60_000
},
{
value: '30m',
- label: translate('auto.components.settings.MobilePane.ff865419dc', 'After 30 minutes'),
+ get label() {
+ return translate('auto.components.settings.MobilePane.ff865419dc', 'After 30 minutes')
+ },
ms: 30 * 60_000
}
]
diff --git a/src/renderer/src/components/sidebar/SidebarWorkspaceOptionsMenu.tsx b/src/renderer/src/components/sidebar/SidebarWorkspaceOptionsMenu.tsx
index 5a02d8724f7..92687be2efd 100644
--- a/src/renderer/src/components/sidebar/SidebarWorkspaceOptionsMenu.tsx
+++ b/src/renderer/src/components/sidebar/SidebarWorkspaceOptionsMenu.tsx
@@ -29,53 +29,195 @@ type SidebarWorkspaceOptionsMenuProps = {
}
const GROUP_BY_OPTIONS = [
- { id: 'none', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.c2c7a45cda", "None") },
- { id: 'workspace-status', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.e029a2d775", "Status") },
- { id: 'pr-status', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.0f9b959b31", "PR") },
- { id: 'repo', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.2170d553cf", "Project") }
+ {
+ id: 'none',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.c2c7a45cda', 'None')
+ }
+ },
+ {
+ id: 'workspace-status',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.e029a2d775', 'Status')
+ }
+ },
+ {
+ id: 'pr-status',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.0f9b959b31', 'PR')
+ }
+ },
+ {
+ id: 'repo',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.2170d553cf', 'Project')
+ }
+ }
] as const
const CARD_LAYOUT_OPTIONS = [
- { id: 'detailed', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.cc17bd443b", "Detailed") },
- { id: 'compact', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.25105b28cb", "Compact") }
+ {
+ id: 'detailed',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.cc17bd443b', 'Detailed')
+ }
+ },
+ {
+ id: 'compact',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.25105b28cb', 'Compact')
+ }
+ }
] as const
const PROPERTY_OPTIONS: { id: WorktreeCardProperty; label: string }[] = [
- { id: 'issue', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.91dfc653e8", "GitHub ticket") },
- { id: 'linear-issue', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.ca4d3c522e", "Linear issue") },
- { id: 'pr', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.b8dcc6f321", "PR/MR link") },
- { id: 'comment', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.26c71e536c", "Notes") },
- { id: 'ports', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.b64d8bcca0", "Ports") },
+ {
+ id: 'issue',
+ get label() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.91dfc653e8',
+ 'GitHub ticket'
+ )
+ }
+ },
+ {
+ id: 'linear-issue',
+ get label() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.ca4d3c522e',
+ 'Linear issue'
+ )
+ }
+ },
+ {
+ id: 'pr',
+ get label() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.b8dcc6f321',
+ 'PR/MR link'
+ )
+ }
+ },
+ {
+ id: 'comment',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.26c71e536c', 'Notes')
+ }
+ },
+ {
+ id: 'ports',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.b64d8bcca0', 'Ports')
+ }
+ },
// Why: toggles the inline "Agent activity" list rendered below each
// workspace card body (see WorktreeCard -> WorktreeCardAgents). Off hides
// the list; there is no alternate surface.
- { id: 'inline-agents', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.d7084e8bc8", "Agent activity") }
+ {
+ id: 'inline-agents',
+ get label() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.d7084e8bc8',
+ 'Agent activity'
+ )
+ }
+ }
]
const AGENT_ACTIVITY_DISPLAY_OPTIONS: { id: AgentActivityDisplayMode; label: string }[] = [
- { id: 'compact', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.25105b28cb", "Compact") },
- { id: 'full', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.2a81e07366", "Full list") }
+ {
+ id: 'compact',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.25105b28cb', 'Compact')
+ }
+ },
+ {
+ id: 'full',
+ get label() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.2a81e07366',
+ 'Full list'
+ )
+ }
+ }
]
const SORT_OPTIONS = [
- { id: 'name', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.3728165cdd", "Name"), description: null },
+ {
+ id: 'name',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.3728165cdd', 'Name')
+ },
+ description: null
+ },
{
id: 'smart',
- label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.503462f2b4", "Agent Activity"),
- description: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.b759bb87ee", "Agents that need attention, then most recent activity.")
+ get label() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.503462f2b4',
+ 'Agent Activity'
+ )
+ },
+ get description() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.b759bb87ee',
+ 'Agents that need attention, then most recent activity.'
+ )
+ }
+ },
+ {
+ id: 'recent',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.b451c8b162', 'Recent')
+ },
+ description: null
+ },
+ {
+ id: 'repo',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.2170d553cf', 'Project')
+ },
+ description: null
},
- { id: 'recent', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.b451c8b162", "Recent"), description: null },
- { id: 'repo', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.2170d553cf", "Project"), description: null },
{
id: 'manual',
- label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.7b316bdd51", "Manual"),
- description: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.7153d07485", "Drag workspaces to arrange them within each group.")
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.7b316bdd51', 'Manual')
+ },
+ get description() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.7153d07485',
+ 'Drag workspaces to arrange them within each group.'
+ )
+ }
}
] as const
const PROJECT_ORDER_OPTIONS = [
- { id: 'manual', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.7b316bdd51", "Manual"), description: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.6664282a7b", "Drag projects to arrange them") },
- { id: 'recent', label: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.b451c8b162", "Recent"), description: translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.af9249c505", "Most recent workspace activity") }
+ {
+ id: 'manual',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.7b316bdd51', 'Manual')
+ },
+ get description() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.6664282a7b',
+ 'Drag projects to arrange them'
+ )
+ }
+ },
+ {
+ id: 'recent',
+ get label() {
+ return translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.b451c8b162', 'Recent')
+ },
+ get description() {
+ return translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.af9249c505',
+ 'Most recent workspace activity'
+ )
+ }
+ }
] as const
const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsMenu({
@@ -148,8 +290,15 @@ const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsM
className="relative text-muted-foreground"
aria-label={
hasAnyFilter
- ? translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.bc96dbd041", "Workspace options ({{value0}} active)", { value0: activeFilterLabel })
- : translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.9919ae1082", "Workspace options")
+ ? translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.bc96dbd041',
+ 'Workspace options ({{value0}} active)',
+ { value0: activeFilterLabel }
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.9919ae1082',
+ 'Workspace options'
+ )
}
data-workspace-board-preserve-open={preserveWorkspaceBoardOpen ? '' : undefined}
>
@@ -168,7 +317,16 @@ const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsM
- {hasAnyFilter ? translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.bc96dbd041", "Workspace options ({{value0}})", { value0: activeFilterLabel }) : translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.9919ae1082", "Workspace options")}
+ {hasAnyFilter
+ ? translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.bc96dbd041',
+ 'Workspace options ({{value0}})',
+ { value0: activeFilterLabel }
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.9919ae1082',
+ 'Workspace options'
+ )}
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.dc0bb670bc", "Group by")}
+
+ {translate('auto.components.sidebar.SidebarWorkspaceOptionsMenu.dc0bb670bc', 'Group by')}
+
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.7bada3b1ab", "Sort by")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.7bada3b1ab',
+ 'Sort by'
+ )}
+
{sortLabel}
@@ -250,11 +415,16 @@ const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsM
{/* Why: project order only has a visible effect when grouping by
project; hide it in none/status/PR modes to avoid a dead control. */}
- {groupBy === "repo" && (
+ {groupBy === 'repo' && (
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.09faabd875", "Project order")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.09faabd875',
+ 'Project order'
+ )}
+
{projectOrderLabel}
@@ -292,7 +462,12 @@ const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsM
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.320b675c9a", "Card layout")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.320b675c9a',
+ 'Card layout'
+ )}
+
{cardLayoutLabel}
@@ -326,9 +501,19 @@ const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsM
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.ba87080fb7", "Show properties")}
- {cardLayout === "compact" ? (
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.3d4b9c4997", "Hover")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.ba87080fb7',
+ 'Show properties'
+ )}
+
+ {cardLayout === 'compact' ? (
+
+ {translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.3d4b9c4997',
+ 'Hover'
+ )}
+
) : visiblePropertyCount > 0 ? (
{visiblePropertyCount}
@@ -352,7 +537,11 @@ const SidebarWorkspaceOptionsMenu = React.memo(function SidebarWorkspaceOptionsM
))}
- {translate("auto.components.sidebar.SidebarWorkspaceOptionsMenu.95c9754653", "Agent activity layout")}
+ {translate(
+ 'auto.components.sidebar.SidebarWorkspaceOptionsMenu.95c9754653',
+ 'Agent activity layout'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx b/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
index 77e745bc6ad..21fa58d026d 100644
--- a/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
+++ b/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
@@ -24,14 +24,36 @@ type SshDisconnectedDialogProps = {
}
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.'
- ),
- 'auth-failed': 'Authentication to the remote host failed.'
+ get disconnected() {
+ return translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.disconnected',
+ 'This remote repository is not connected.'
+ )
+ },
+ get reconnecting() {
+ return translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.reconnecting',
+ 'Reconnecting to the remote host...'
+ )
+ },
+ get 'reconnection-failed'() {
+ return translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.reconnectionFailed',
+ 'Reconnection to the remote host failed.'
+ )
+ },
+ get error() {
+ return translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.376bed88e5',
+ 'The connection to the remote host encountered an error.'
+ )
+ },
+ get 'auth-failed'() {
+ return translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.authFailed',
+ 'Authentication to the remote host failed.'
+ )
+ }
}
function isReconnectable(status: SshConnectionStatus): boolean {
@@ -76,9 +98,21 @@ export function SshDisconnectedDialog({
status === 'connecting' ||
status === 'deploying-relay' ||
status === 'reconnecting'
+ const reconnectingMessage =
+ STATUS_MESSAGES.reconnecting ??
+ translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.reconnecting',
+ 'Reconnecting to the remote host...'
+ )
+ const disconnectedMessage =
+ STATUS_MESSAGES.disconnected ??
+ translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.disconnected',
+ 'This remote repository is not connected.'
+ )
const message = isConnecting
- ? 'Reconnecting to the remote host...'
- : (STATUS_MESSAGES[status] ?? 'This remote repository is not connected.')
+ ? reconnectingMessage
+ : (STATUS_MESSAGES[status] ?? disconnectedMessage)
const showReconnect = isReconnectable(status)
useEffect(() => {
diff --git a/src/renderer/src/components/sidebar/worktree-list-groups.ts b/src/renderer/src/components/sidebar/worktree-list-groups.ts
index 9312f06859a..3cde58e13d8 100644
--- a/src/renderer/src/components/sidebar/worktree-list-groups.ts
+++ b/src/renderer/src/components/sidebar/worktree-list-groups.ts
@@ -128,22 +128,30 @@ export const PR_GROUP_META: Record<
}
> = {
done: {
- label: translate('auto.components.sidebar.worktree.list.groups.5076efc3d2', 'Done'),
+ get label() {
+ return 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'),
+ get label() {
+ return 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'),
+ get label() {
+ return 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'),
+ get label() {
+ return translate('auto.components.sidebar.worktree.list.groups.682ed5d551', 'Closed')
+ },
icon: CircleX,
tone: 'text-zinc-600 dark:text-zinc-300'
}
@@ -161,7 +169,9 @@ 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'),
+ get label() {
+ return translate('auto.components.sidebar.worktree.list.groups.4aeefc5996', 'Pinned')
+ },
tone: 'text-foreground',
icon: Pin
} as const
@@ -169,7 +179,9 @@ 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'),
+ get label() {
+ return translate('auto.components.sidebar.worktree.list.groups.0ed04075b8', 'All')
+ },
tone: 'text-foreground',
icon: List
} as const
diff --git a/src/renderer/src/components/stats/ClaudeUsageDetails.tsx b/src/renderer/src/components/stats/ClaudeUsageDetails.tsx
new file mode 100644
index 00000000000..186616f323e
--- /dev/null
+++ b/src/renderer/src/components/stats/ClaudeUsageDetails.tsx
@@ -0,0 +1,172 @@
+import type {
+ ClaudeUsageBreakdownRow,
+ ClaudeUsageDailyPoint,
+ ClaudeUsageSessionRow,
+ ClaudeUsageSummary
+} from '../../../../shared/claude-usage-types'
+import { ClaudeUsageDailyChart } from './ClaudeUsageDailyChart'
+import { translate } from '@/i18n/i18n'
+
+type ClaudeUsageDetailsProps = {
+ daily: ClaudeUsageDailyPoint[]
+ formatTokens: (value: number) => string
+ modelBreakdown: ClaudeUsageBreakdownRow[]
+ projectBreakdown: ClaudeUsageBreakdownRow[]
+ recentSessions: ClaudeUsageSessionRow[]
+ summary: ClaudeUsageSummary | null | undefined
+}
+
+function formatSessionTime(timestamp: string): string {
+ const parsed = new Date(timestamp)
+ if (Number.isNaN(parsed.getTime())) {
+ return timestamp
+ }
+ return parsed.toLocaleString(undefined, {
+ month: 'short',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: '2-digit'
+ })
+}
+
+export function ClaudeUsageDetails({
+ daily,
+ formatTokens,
+ modelBreakdown,
+ projectBreakdown,
+ recentSessions,
+ summary
+}: ClaudeUsageDetailsProps): React.JSX.Element {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.7e76c84153', 'Recent sessions')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.abfc4a4943', 'Cache reuse rate:')}{' '}
+ {summary?.cacheReuseRate !== null && summary?.cacheReuseRate !== undefined
+ ? `${Math.round(summary.cacheReuseRate * 100)}%`
+ : translate('auto.components.stats.ClaudeUsagePane.7765a4c3e1', 'n/a')}
+
+
+
+
+
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.01476891c7', 'Last active')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.c17bed0416', 'Project')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.1afc25eb06', 'Model')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.0f03975d59', 'Turns')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.faf3444859', 'Input')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.a8b7487ff7', 'Output')}
+
+
+ {translate('auto.components.stats.ClaudeUsagePane.21ea00bfa8', 'Cache')}
+
+
+
+
+ {recentSessions.map((row) => (
+
+
+ {formatSessionTime(row.lastActiveAt)}
+
+ {row.projectLabel}
+
+ {row.model ??
+ translate('auto.components.stats.ClaudeUsagePane.cfe2282ffa', 'Unknown')}
+
+ {row.turns}
+
+ {formatTokens(row.inputTokens)}
+
+
+ {formatTokens(row.outputTokens)}
+
+
+ {formatTokens(row.cacheReadTokens + row.cacheWriteTokens)}
+
+
+ ))}
+
+
+
+
+ >
+ )
+}
+
+function ClaudeUsageBreakdownSection({
+ formatTokens,
+ label,
+ rows,
+ topLabel,
+ topValue
+}: {
+ formatTokens: (value: number) => string
+ label: string
+ rows: ClaudeUsageBreakdownRow[]
+ topLabel: string
+ topValue: string | null | undefined
+}): React.JSX.Element {
+ return (
+
+
+
{label}
+
+ {topLabel}{' '}
+ {topValue ?? translate('auto.components.stats.ClaudeUsagePane.7765a4c3e1', 'n/a')}
+
+
+
+ {rows.slice(0, 5).map((row) => (
+
+
+ {row.label}
+
+ {formatTokens(row.inputTokens + row.outputTokens)}
+
+
+
+ {row.sessions}{' '}
+ {translate('auto.components.stats.ClaudeUsagePane.02a046792e', 'sessions •')}{' '}
+ {row.turns} {translate('auto.components.stats.ClaudeUsagePane.32176e1d44', 'turns')}
+
+
+ ))}
+
+
+ )
+}
diff --git a/src/renderer/src/components/stats/ClaudeUsagePane.tsx b/src/renderer/src/components/stats/ClaudeUsagePane.tsx
index 0beae4aada1..1f2377cd527 100644
--- a/src/renderer/src/components/stats/ClaudeUsagePane.tsx
+++ b/src/renderer/src/components/stats/ClaudeUsagePane.tsx
@@ -23,9 +23,8 @@ import {
DropdownMenuTrigger
} from '../ui/dropdown-menu'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
-import { ClaudeUsageDailyChart } from './ClaudeUsageDailyChart'
+import { ClaudeUsageDetails } from './ClaudeUsageDetails'
import { ClaudeUsageLoadingState } from './ClaudeUsageLoadingState'
-import { ClaudeUsageRecentSessionsTable } from './ClaudeUsageRecentSessionsTable'
import { ShareUsageButton } from './ShareUsageButton'
import { StatCard } from './StatCard'
import { formatCost, formatTokens, formatUpdatedAt } from './usage-formatters'
@@ -35,18 +34,30 @@ const RANGE_OPTIONS: ClaudeUsageRange[] = ['7d', '30d', '90d', 'all']
const SCOPE_OPTIONS: { value: ClaudeUsageScope; label: string }[] = [
{
value: 'orca',
- label: translate('auto.components.stats.ClaudeUsagePane.4f8368c272', 'Orca worktrees only')
+ get label() {
+ return translate('auto.components.stats.ClaudeUsagePane.4f8368c272', 'Orca worktrees only')
+ }
},
{
value: 'all',
- label: translate('auto.components.stats.ClaudeUsagePane.5ce4842c2c', 'All local Claude usage')
+ get label() {
+ return translate('auto.components.stats.ClaudeUsagePane.5ce4842c2c', 'All local Claude usage')
+ }
}
]
const RANGE_LABELS: Record = {
- '7d': 'Last 7 days',
- '30d': 'Last 30 days',
- '90d': 'Last 90 days',
- all: 'All time'
+ get '7d'() {
+ return translate('auto.components.stats.ClaudeUsagePane.rangeLast7Days', 'Last 7 days')
+ },
+ get '30d'() {
+ return translate('auto.components.stats.ClaudeUsagePane.rangeLast30Days', 'Last 30 days')
+ },
+ get '90d'() {
+ return translate('auto.components.stats.ClaudeUsagePane.rangeLast90Days', 'Last 90 days')
+ },
+ get all() {
+ return translate('auto.components.stats.ClaudeUsagePane.rangeAllTime', 'All time')
+ }
}
export function ClaudeUsagePane(): React.JSX.Element {
@@ -311,73 +322,14 @@ export function ClaudeUsagePane(): React.JSX.Element {
)}
-
-
-
-
-
-
- {translate('auto.components.stats.ClaudeUsagePane.0f394c24e3', 'By model')}
-
-
- {translate('auto.components.stats.ClaudeUsagePane.c3fdbc5474', 'Top model:')}{' '}
- {summary?.topModel ??
- translate('auto.components.stats.ClaudeUsagePane.7765a4c3e1', 'n/a')}
-
-
-
- {modelBreakdown.slice(0, 5).map((row) => (
-
-
- {row.label}
-
- {formatTokens(row.inputTokens + row.outputTokens)}
-
-
-
- {row.sessions}{' '}
- {translate('auto.components.stats.ClaudeUsagePane.02a046792e', 'sessions •')}{' '}
- {row.turns}{' '}
- {translate('auto.components.stats.ClaudeUsagePane.32176e1d44', 'turns')}
-
-
- ))}
-
-
-
-
-
-
- {translate('auto.components.stats.ClaudeUsagePane.7dc9e5613b', 'By project')}
-
-
- {translate('auto.components.stats.ClaudeUsagePane.f97435845c', 'Top project:')}{' '}
- {summary?.topProject ??
- translate('auto.components.stats.ClaudeUsagePane.7765a4c3e1', 'n/a')}
-
-
-
- {projectBreakdown.slice(0, 5).map((row) => (
-
-
- {row.label}
-
- {formatTokens(row.inputTokens + row.outputTokens)}
-
-
-
- {row.sessions}{' '}
- {translate('auto.components.stats.ClaudeUsagePane.02a046792e', 'sessions •')}{' '}
- {row.turns}{' '}
- {translate('auto.components.stats.ClaudeUsagePane.32176e1d44', 'turns')}
-
-
- ))}
-
-
-
-
-
+
>
)}
diff --git a/src/renderer/src/components/stats/CodexUsageDetails.tsx b/src/renderer/src/components/stats/CodexUsageDetails.tsx
new file mode 100644
index 00000000000..bd1d459ce9e
--- /dev/null
+++ b/src/renderer/src/components/stats/CodexUsageDetails.tsx
@@ -0,0 +1,183 @@
+import type {
+ CodexUsageBreakdownRow,
+ CodexUsageDailyPoint,
+ CodexUsageSessionRow,
+ CodexUsageSummary
+} from '../../../../shared/codex-usage-types'
+import { CodexUsageDailyChart } from './CodexUsageDailyChart'
+import { translate } from '@/i18n/i18n'
+
+type CodexUsageDetailsProps = {
+ daily: CodexUsageDailyPoint[]
+ formatTokens: (value: number) => string
+ modelBreakdown: CodexUsageBreakdownRow[]
+ projectBreakdown: CodexUsageBreakdownRow[]
+ recentSessions: CodexUsageSessionRow[]
+ summary: CodexUsageSummary | null | undefined
+}
+
+function formatSessionTime(timestamp: string): string {
+ const parsed = new Date(timestamp)
+ if (Number.isNaN(parsed.getTime())) {
+ return timestamp
+ }
+ return parsed.toLocaleString(undefined, {
+ month: 'short',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: '2-digit'
+ })
+}
+
+export function CodexUsageDetails({
+ daily,
+ formatTokens,
+ modelBreakdown,
+ projectBreakdown,
+ recentSessions,
+ summary
+}: CodexUsageDetailsProps): React.JSX.Element {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {translate('auto.components.stats.CodexUsagePane.0cb0983c07', 'Recent sessions')}
+
+
+ {translate(
+ 'auto.components.stats.CodexUsagePane.0bd8655475',
+ 'Most recent local Codex sessions in this scope.'
+ )}
+
+
+
+
+
+
+
+ {translate('auto.components.stats.CodexUsagePane.0c36b100be', 'Last active')}
+
+
+ {translate('auto.components.stats.CodexUsagePane.1a65900aea', 'Project')}
+
+
+ {translate('auto.components.stats.CodexUsagePane.c2478bcc3c', 'Model')}
+
+
+ {translate('auto.components.stats.CodexUsagePane.bd0822ca47', 'Events')}
+
+
+ {translate('auto.components.stats.CodexUsagePane.3acc582214', 'Input')}
+
+
+ {translate('auto.components.stats.CodexUsagePane.bbd20344b8', 'Output')}
+
+
+ {translate('auto.components.stats.CodexUsagePane.e0b988599d', 'Total')}
+
+
+
+
+ {recentSessions.map((row) => (
+
+
+ {formatSessionTime(row.lastActiveAt)}
+
+ {row.projectLabel}
+
+ {row.model ??
+ translate('auto.components.stats.CodexUsagePane.bf6cf2d4dd', 'Unknown')}
+ {row.hasInferredPricing ? ' *' : ''}
+
+ {row.events}
+
+ {formatTokens(row.inputTokens)}
+
+
+ {formatTokens(row.outputTokens)}
+
+
+ {formatTokens(row.totalTokens)}
+
+
+ ))}
+
+
+
+
+ >
+ )
+}
+
+function CodexUsageBreakdownSection({
+ formatTokens,
+ label,
+ rows,
+ showInferredPricing,
+ topLabel,
+ topValue
+}: {
+ formatTokens: (value: number) => string
+ label: string
+ rows: CodexUsageBreakdownRow[]
+ showInferredPricing: boolean
+ topLabel: string
+ topValue: string | null | undefined
+}): React.JSX.Element {
+ return (
+
+
+
{label}
+
+ {topLabel}{' '}
+ {topValue ?? translate('auto.components.stats.CodexUsagePane.ae255c3dba', 'n/a')}
+
+
+
+ {rows.slice(0, 5).map((row) => (
+
+
+ {row.label}
+
+ {formatTokens(row.totalTokens)}
+
+
+
+ {row.sessions}{' '}
+ {translate('auto.components.stats.CodexUsagePane.bf1bf2f674', 'sessions •')}{' '}
+ {row.events} {translate('auto.components.stats.CodexUsagePane.79a69522a5', 'events')}
+ {showInferredPricing && row.hasInferredPricing
+ ? ` ${translate(
+ 'auto.components.stats.CodexUsagePane.247c93ca92',
+ '• inferred pricing'
+ )}`
+ : ''}
+
+
+ ))}
+
+
+ )
+}
diff --git a/src/renderer/src/components/stats/CodexUsagePane.tsx b/src/renderer/src/components/stats/CodexUsagePane.tsx
index 8df30ccba81..0d848cdedf2 100644
--- a/src/renderer/src/components/stats/CodexUsagePane.tsx
+++ b/src/renderer/src/components/stats/CodexUsagePane.tsx
@@ -23,8 +23,7 @@ import {
} from '../ui/dropdown-menu'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { ClaudeUsageLoadingState } from './ClaudeUsageLoadingState'
-import { CodexUsageDailyChart } from './CodexUsageDailyChart'
-import { CodexUsageRecentSessionsTable } from './CodexUsageRecentSessionsTable'
+import { CodexUsageDetails } from './CodexUsageDetails'
import { ShareUsageButton } from './ShareUsageButton'
import { StatCard } from './StatCard'
import { formatCost, formatTokens, formatUpdatedAt } from './usage-formatters'
@@ -34,18 +33,30 @@ const RANGE_OPTIONS: CodexUsageRange[] = ['7d', '30d', '90d', 'all']
const SCOPE_OPTIONS: { value: CodexUsageScope; label: string }[] = [
{
value: 'orca',
- label: translate('auto.components.stats.CodexUsagePane.201766b754', 'Orca worktrees only')
+ get label() {
+ return translate('auto.components.stats.CodexUsagePane.201766b754', 'Orca worktrees only')
+ }
},
{
value: 'all',
- label: translate('auto.components.stats.CodexUsagePane.4fe8820098', 'All local Codex usage')
+ get label() {
+ return translate('auto.components.stats.CodexUsagePane.4fe8820098', 'All local Codex usage')
+ }
}
]
const RANGE_LABELS: Record = {
- '7d': 'Last 7 days',
- '30d': 'Last 30 days',
- '90d': 'Last 90 days',
- all: 'All time'
+ get '7d'() {
+ return translate('auto.components.stats.CodexUsagePane.rangeLast7Days', 'Last 7 days')
+ },
+ get '30d'() {
+ return translate('auto.components.stats.CodexUsagePane.rangeLast30Days', 'Last 30 days')
+ },
+ get '90d'() {
+ return translate('auto.components.stats.CodexUsagePane.rangeLast90Days', 'Last 90 days')
+ },
+ get all() {
+ return translate('auto.components.stats.CodexUsagePane.rangeAllTime', 'All time')
+ }
}
export function CodexUsagePane(): React.JSX.Element {
@@ -292,76 +303,14 @@ export function CodexUsagePane(): React.JSX.Element {
)}
-
-
-
-
-
-
- {translate('auto.components.stats.CodexUsagePane.5a0d1d69cd', 'By model')}
-
-
- {translate('auto.components.stats.CodexUsagePane.95d2d89285', 'Top model:')}{' '}
- {summary?.topModel ??
- translate('auto.components.stats.CodexUsagePane.ae255c3dba', 'n/a')}
-
-
-
- {modelBreakdown.slice(0, 5).map((row) => (
-
-
- {row.label}
-
- {formatTokens(row.totalTokens)}
-
-
-
- {row.sessions}{' '}
- {translate('auto.components.stats.CodexUsagePane.bf1bf2f674', 'sessions •')}{' '}
- {row.events}{' '}
- {translate('auto.components.stats.CodexUsagePane.79a69522a5', 'events')}
- {row.hasInferredPricing
- ? ` ${translate('auto.components.stats.CodexUsagePane.247c93ca92', '• inferred pricing')}`
- : ''}
-
-
- ))}
-
-
-
-
-
-
- {translate('auto.components.stats.CodexUsagePane.b98718aaab', 'By project')}
-
-
- {translate('auto.components.stats.CodexUsagePane.829ee743f2', 'Top project:')}{' '}
- {summary?.topProject ??
- translate('auto.components.stats.CodexUsagePane.ae255c3dba', 'n/a')}
-
-
-
- {projectBreakdown.slice(0, 5).map((row) => (
-
-
- {row.label}
-
- {formatTokens(row.totalTokens)}
-
-
-
- {row.sessions}{' '}
- {translate('auto.components.stats.CodexUsagePane.bf1bf2f674', 'sessions •')}{' '}
- {row.events}{' '}
- {translate('auto.components.stats.CodexUsagePane.79a69522a5', 'events')}
-
-
- ))}
-
-
-
-
-
+
>
)}
diff --git a/src/renderer/src/components/stats/OpenCodeUsageDetails.tsx b/src/renderer/src/components/stats/OpenCodeUsageDetails.tsx
new file mode 100644
index 00000000000..48a70c02e96
--- /dev/null
+++ b/src/renderer/src/components/stats/OpenCodeUsageDetails.tsx
@@ -0,0 +1,186 @@
+import type {
+ OpenCodeUsageBreakdownRow,
+ OpenCodeUsageDailyPoint,
+ OpenCodeUsageSessionRow,
+ OpenCodeUsageSummary
+} from '../../../../shared/opencode-usage-types'
+import { CodexUsageDailyChart } from './CodexUsageDailyChart'
+import { translate } from '@/i18n/i18n'
+
+type OpenCodeUsageDetailsProps = {
+ daily: OpenCodeUsageDailyPoint[]
+ formatCost: (value: number | null) => string
+ formatTokens: (value: number) => string
+ modelBreakdown: OpenCodeUsageBreakdownRow[]
+ projectBreakdown: OpenCodeUsageBreakdownRow[]
+ recentSessions: OpenCodeUsageSessionRow[]
+ summary: OpenCodeUsageSummary | null | undefined
+}
+
+function formatSessionTime(timestamp: string): string {
+ const parsed = new Date(timestamp)
+ if (Number.isNaN(parsed.getTime())) {
+ return timestamp
+ }
+ return parsed.toLocaleString(undefined, {
+ month: 'short',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: '2-digit'
+ })
+}
+
+export function OpenCodeUsageDetails({
+ daily,
+ formatCost,
+ formatTokens,
+ modelBreakdown,
+ projectBreakdown,
+ recentSessions,
+ summary
+}: OpenCodeUsageDetailsProps): React.JSX.Element {
+ return (
+ <>
+
+ >
+ )
+}
+
+function OpenCodeUsageBreakdownSection({
+ formatCost,
+ formatTokens,
+ label,
+ rows,
+ showCost,
+ topLabel,
+ topValue
+}: {
+ formatCost: (value: number | null) => string
+ formatTokens: (value: number) => string
+ label: string
+ rows: OpenCodeUsageBreakdownRow[]
+ showCost: boolean
+ topLabel: string
+ topValue: string | null | undefined
+}): React.JSX.Element {
+ return (
+
+ )
+}
diff --git a/src/renderer/src/components/stats/OpenCodeUsagePane.tsx b/src/renderer/src/components/stats/OpenCodeUsagePane.tsx
index 721cc3e3fae..1bcee66ef6d 100644
--- a/src/renderer/src/components/stats/OpenCodeUsagePane.tsx
+++ b/src/renderer/src/components/stats/OpenCodeUsagePane.tsx
@@ -26,8 +26,7 @@ import {
} from '../ui/dropdown-menu'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { ClaudeUsageLoadingState } from './ClaudeUsageLoadingState'
-import { CodexUsageDailyChart } from './CodexUsageDailyChart'
-import { OpenCodeUsageRecentSessionsTable } from './OpenCodeUsageRecentSessionsTable'
+import { OpenCodeUsageDetails } from './OpenCodeUsageDetails'
import { StatCard } from './StatCard'
import { formatCost, formatTokens, formatUpdatedAt } from './usage-formatters'
import { translate } from '@/i18n/i18n'
@@ -36,21 +35,33 @@ const RANGE_OPTIONS: OpenCodeUsageRange[] = ['7d', '30d', '90d', 'all']
const SCOPE_OPTIONS: { value: OpenCodeUsageScope; label: string }[] = [
{
value: 'orca',
- label: translate('auto.components.stats.OpenCodeUsagePane.e04c58327c', 'Orca worktrees only')
+ get label() {
+ return translate('auto.components.stats.OpenCodeUsagePane.e04c58327c', 'Orca worktrees only')
+ }
},
{
value: 'all',
- label: translate(
- 'auto.components.stats.OpenCodeUsagePane.144a6050e9',
- 'All local OpenCode usage'
- )
+ get label() {
+ return translate(
+ 'auto.components.stats.OpenCodeUsagePane.144a6050e9',
+ 'All local OpenCode usage'
+ )
+ }
}
]
const RANGE_LABELS: Record