From 280db4a1a62199c78484d44f549ced11ec352c7e Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 17:30:49 -0400
Subject: [PATCH 001/165] Resume agents after PTY cold restore (#5045)
Co-authored-by: Orca
---
.../terminal-pane/pty-connection.test.ts | 95 +++++++++++++++
.../terminal-pane/pty-connection.ts | 112 +++++++++++++-----
2 files changed, 178 insertions(+), 29 deletions(-)
diff --git a/src/renderer/src/components/terminal-pane/pty-connection.test.ts b/src/renderer/src/components/terminal-pane/pty-connection.test.ts
index c7da1a7314d..56a26406d8f 100644
--- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts
+++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts
@@ -65,6 +65,7 @@ type StoreState = {
suppressWhenFocused?: boolean
customSoundPath?: string | null
}
+ agentCmdOverrides?: Record
} | null
codexRestartNoticeByPtyId: Record<
string,
@@ -2850,6 +2851,100 @@ describe('connectPanePty', () => {
expect(window.api.pty.ackColdRestore).toHaveBeenCalledWith('tab-pty')
})
+ it('resumes the provider agent session when daemon reattach cold-restores a fresh shell', async () => {
+ const { connectPanePty } = await import('./pty-connection')
+ const transport = createMockTransport('fresh-pty')
+ transport.connect.mockImplementation(async ({ sessionId }: { sessionId?: string }) => {
+ if (sessionId) {
+ return {
+ id: 'fresh-pty',
+ coldRestore: { scrollback: 'cold-payload', cwd: '/tmp/wt-1' }
+ }
+ }
+ return 'fresh-pty'
+ })
+ transportFactoryQueue.push(transport)
+ const paneKey = makePaneKey('tab-1', LEAF_1)
+ mockStoreState = {
+ ...mockStoreState,
+ tabsByWorktree: {
+ 'wt-1': [{ id: 'tab-1', ptyId: 'lost-pty' }]
+ },
+ settings: {
+ ...mockStoreState.settings,
+ agentCmdOverrides: {}
+ },
+ agentStatusByPaneKey: {
+ [paneKey]: {
+ state: 'working',
+ prompt: 'finish the task',
+ agentType: 'codex',
+ paneKey,
+ updatedAt: 1,
+ stateStartedAt: 1,
+ stateHistory: [],
+ providerSession: { key: 'session_id', id: 'codex-session-1' }
+ }
+ }
+ } as StoreState
+
+ const pane = createPane(1)
+ const manager = createManager(1)
+ const deps = createDeps({
+ restoredLeafId: LEAF_1,
+ restoredPtyIdByLeafId: { [LEAF_1]: 'lost-pty' }
+ })
+
+ connectPanePty(pane as never, manager as never, deps as never)
+ await flushAsyncTicks(20)
+ await new Promise((resolve) => setTimeout(resolve, 70))
+
+ expect(pane.terminal.write).toHaveBeenCalledWith('cold-payload', expect.any(Function))
+ expect(transport.sendInput).toHaveBeenCalledWith("codex 'resume' 'codex-session-1'\r")
+ })
+
+ it('does not resume the provider session when daemon reattach returns a live snapshot', async () => {
+ const { connectPanePty } = await import('./pty-connection')
+ const transport = createMockTransport('tab-pty')
+ transport.connect.mockImplementation(async ({ sessionId }: { sessionId?: string }) => {
+ if (sessionId) {
+ return { id: sessionId, snapshot: 'live-snapshot' }
+ }
+ return null
+ })
+ transportFactoryQueue.push(transport)
+ const paneKey = makePaneKey('tab-1', LEAF_1)
+ mockStoreState = {
+ ...mockStoreState,
+ agentStatusByPaneKey: {
+ [paneKey]: {
+ state: 'working',
+ prompt: 'finish the task',
+ agentType: 'codex',
+ paneKey,
+ updatedAt: 1,
+ stateStartedAt: 1,
+ stateHistory: [],
+ providerSession: { key: 'session_id', id: 'codex-session-1' }
+ }
+ }
+ } as StoreState
+
+ const pane = createPane(1)
+ const manager = createManager(1)
+ const deps = createDeps({
+ restoredLeafId: LEAF_1,
+ restoredPtyIdByLeafId: { [LEAF_1]: 'tab-pty' }
+ })
+
+ connectPanePty(pane as never, manager as never, deps as never)
+ await flushAsyncTicks(20)
+ await new Promise((resolve) => setTimeout(resolve, 70))
+
+ expect(pane.terminal.write).toHaveBeenCalledWith('live-snapshot', expect.any(Function))
+ expect(transport.sendInput).not.toHaveBeenCalled()
+ })
+
it('keeps non-visible local PTY bytes on the live xterm path for release', async () => {
const pendingTimeouts: (() => void)[] = []
const originalSetTimeout = globalThis.setTimeout
diff --git a/src/renderer/src/components/terminal-pane/pty-connection.ts b/src/renderer/src/components/terminal-pane/pty-connection.ts
index 25322d0c398..8778c102758 100644
--- a/src/renderer/src/components/terminal-pane/pty-connection.ts
+++ b/src/renderer/src/components/terminal-pane/pty-connection.ts
@@ -81,6 +81,13 @@ import {
cancelScheduledHiddenOutputRestore,
scheduleHiddenOutputRestore
} from './hidden-output-restore-scheduler'
+import { CLIENT_PLATFORM } from '@/lib/new-workspace'
+import { buildAgentResumeStartupPlan } from '@/lib/tui-agent-startup'
+import {
+ isResumableTuiAgent,
+ normalizeAgentProviderSession
+} from '../../../../shared/agent-session-resume'
+import { isWslUncPath } from '../../../../shared/wsl-paths'
const pendingSpawnByPaneKey = new Map>()
const SSH_SESSION_EXPIRED_ERROR = 'SSH_SESSION_EXPIRED'
@@ -1749,6 +1756,70 @@ export function connectPanePty(
// stay renderer-delivered so xterm can apply bracketed-paste semantics.
let pendingStartupCommand =
shouldDeliverStartupViaTerminalPaste || connectionId ? (paneStartup?.command ?? null) : null
+ const getColdRestoreAgentResumePlatform = (): NodeJS.Platform => {
+ if (connectionId || (worktree?.path && isWslUncPath(worktree.path))) {
+ return 'linux'
+ }
+ return CLIENT_PLATFORM
+ }
+ const prepareColdRestoreAgentResumeCommand = (): boolean => {
+ if (pendingStartupCommand) {
+ return false
+ }
+ const entry = useAppStore.getState().agentStatusByPaneKey[cacheKey]
+ if (!entry || entry.state === 'done' || !isResumableTuiAgent(entry.agentType)) {
+ return false
+ }
+ const providerSession = normalizeAgentProviderSession(entry.providerSession)
+ if (!providerSession) {
+ return false
+ }
+ const startupPlan = buildAgentResumeStartupPlan({
+ agent: entry.agentType,
+ providerSession,
+ cmdOverrides: useAppStore.getState().settings?.agentCmdOverrides ?? {},
+ platform: getColdRestoreAgentResumePlatform()
+ })
+ if (!startupPlan) {
+ return false
+ }
+ // Why: cold restore means the PTY process is gone but the agent provider
+ // session is still resumable, so the replacement shell must launch it.
+ pendingStartupCommand = startupPlan.launchCommand
+ return true
+ }
+ const schedulePendingStartupCommandDelivery = (): void => {
+ if (!pendingStartupCommand) {
+ return
+ }
+ if (startupInjectTimer !== null) {
+ clearTimeout(startupInjectTimer)
+ }
+ startupInjectTimer = setTimeout(() => {
+ startupInjectTimer = null
+ void (async () => {
+ const command = pendingStartupCommand
+ if (!command || disposed) {
+ return
+ }
+ if (shouldDeliverStartupViaTerminalPaste) {
+ await waitForTerminalOutputParsed(pane.terminal)
+ }
+ if (pendingStartupCommand !== command || disposed) {
+ return
+ }
+ if (shouldDeliverStartupViaTerminalPaste) {
+ // Why: this mode must pass through xterm so bracketed-paste
+ // wrapping is applied before the submit Enter.
+ pasteTerminalText(pane.terminal, command)
+ transport.sendInput('\r')
+ } else {
+ transport.sendInput(`${command}\r`)
+ }
+ pendingStartupCommand = null
+ })()
+ }, 50)
+ }
const startFreshSpawn = (): void => {
// Why: pre-signal the main process so its cooperation gate suppresses
@@ -2553,35 +2624,7 @@ export function connectPanePty(
writePtyOutputToXterm(data, foreground)
}
- if (pendingStartupCommand) {
- if (startupInjectTimer !== null) {
- clearTimeout(startupInjectTimer)
- }
- startupInjectTimer = setTimeout(() => {
- startupInjectTimer = null
- void (async () => {
- const command = pendingStartupCommand
- if (!command || disposed) {
- return
- }
- if (shouldDeliverStartupViaTerminalPaste) {
- await waitForTerminalOutputParsed(pane.terminal)
- }
- if (pendingStartupCommand !== command || disposed) {
- return
- }
- if (shouldDeliverStartupViaTerminalPaste) {
- // Why: this mode must pass through xterm so bracketed-paste
- // wrapping is applied before the submit Enter.
- pasteTerminalText(pane.terminal, command)
- transport.sendInput('\r')
- } else {
- transport.sendInput(`${command}\r`)
- }
- pendingStartupCommand = null
- })()
- }, 50)
- }
+ schedulePendingStartupCommandDelivery()
}
unregisterE2ePtyDataInjection = registerE2eTerminalPtyDataInjection(cacheKey, (data, meta) => {
if (!disposed) {
@@ -2615,6 +2658,7 @@ export function connectPanePty(
if (staleSessionId) {
deps.clearTabPtyId(deps.tabId, staleSessionId)
}
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
return
}
@@ -2626,6 +2670,7 @@ export function connectPanePty(
// Why: SSH sleep/reconnect can invalidate the relay-held PTY while
// leaving the tab mounted. Replace the dead lease in-place instead of
// stranding the pane behind a stale expired-session overlay.
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
return
}
@@ -2696,6 +2741,9 @@ export function connectPanePty(
if (!isRemoteRuntimePtyId(ptyId)) {
window.api.pty.ackColdRestore(ptyId)
}
+ if (prepareColdRestoreAgentResumeCommand()) {
+ schedulePendingStartupCommandDelivery()
+ }
}
// Why: when a mobile-fit override is active, skip sending desktop dims
// to the PTY — the PTY is already at phone dimensions and must stay there.
@@ -2916,6 +2964,7 @@ export function connectPanePty(
}
deps.syncPanePtyLayoutBinding(pane.id, null)
deps.clearTabPtyId(deps.tabId, pendingSessionId)
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
return
}
@@ -2939,9 +2988,11 @@ export function connectPanePty(
if (isSshSessionExpiredError(err)) {
deps.syncPanePtyLayoutBinding(pane.id, null)
deps.clearTabPtyId(deps.tabId, pendingSessionId)
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
return
}
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
})
} else {
@@ -3042,6 +3093,7 @@ export function connectPanePty(
}
deps.syncPanePtyLayoutBinding(pane.id, null)
deps.clearTabPtyId(deps.tabId, deferredReattachSessionId)
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
return
}
@@ -3070,10 +3122,12 @@ export function connectPanePty(
deps.syncPanePtyLayoutBinding(pane.id, null)
deps.clearTabPtyId(deps.tabId, deferredReattachSessionId)
if (connectionId && isSshSessionExpiredError(err)) {
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
return
}
reportError(message)
+ prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
})
} else if (detachedRemoteLeafPtyId || detachedLivePtyId) {
From fe85ec673fb924d7e32cd942375eef8c0f0afb42 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 9 Jun 2026 22:36:31 +0000
Subject: [PATCH 002/165] release: v1.4.55-rc.0 [rc-slot:2026-06-09-15]
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 28b46fdda71..76cc845fc73 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca",
- "version": "1.4.54",
+ "version": "1.4.55-rc.0",
"description": "Next-gen IDE for parallel agentic development",
"homepage": "https://github.com/stablyai/orca",
"author": "stablyai",
From 9c199a5b8535b379b972f26b5df1cd9fe28e24ca Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 18:47:15 -0400
Subject: [PATCH 003/165] Fix status bar usage separator entity (#5053)
Co-authored-by: Orca
---
.../src/components/status-bar/StatusBar.tsx | 20 ++++---------------
src/renderer/src/i18n/locales/en.json | 4 ++--
2 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/src/renderer/src/components/status-bar/StatusBar.tsx b/src/renderer/src/components/status-bar/StatusBar.tsx
index 07e1f7274a3..b6ca7b795c0 100644
--- a/src/renderer/src/components/status-bar/StatusBar.tsx
+++ b/src/renderer/src/components/status-bar/StatusBar.tsx
@@ -1031,9 +1031,7 @@ function ProviderSegment({
return (
-
- {translate('auto.components.status.bar.StatusBar.2483c60695', '···')}
-
+ ···
)
}
@@ -1043,9 +1041,7 @@ function ProviderSegment({
return (
-
- {translate('auto.components.status.bar.StatusBar.2483c60695', '···')}
-
+ ···
)
}
@@ -1082,11 +1078,7 @@ function ProviderSegment({
const left = Math.max(0, Math.round(100 - bucket.usedPercent))
return (
- {i > 0 && (
-
- {translate('auto.components.status.bar.StatusBar.4dff061aab', '·')}
-
- )}
+ {i > 0 && · }
{bucket.name} {left}%
@@ -1108,11 +1100,7 @@ function ProviderSegment({
{p.session && (
)}
- {p.session && p.weekly && (
-
- {translate('auto.components.status.bar.StatusBar.4dff061aab', '·')}
-
- )}
+ {p.session && p.weekly && · }
{p.weekly && }
{isStale && }
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index 655e8e6e4e3..e76ced64938 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -2459,8 +2459,8 @@
"7657e3db9c": "Codex Account",
"38b5647724": "Codex usage runtime",
"ba55303942": "Open Codex details and account switcher",
- "4dff061aab": "·",
- "2483c60695": "···",
+ "4dff061aab": "·",
+ "2483c60695": "···",
"c35af53b73": "Sign in",
"f19a63e7cd": "Sign in to see usage",
"5c938d39ac": "% wk",
From 7d666fafab29acbca83aec15ae72d2fe33727cfb Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 18:53:39 -0400
Subject: [PATCH 004/165] Fix terminal read for blank TUI tails (#5050)
Co-authored-by: Orca
---
src/cli/index.test.ts | 36 ++++++++
src/main/daemon/headless-emulator.ts | 9 ++
src/main/runtime/orca-runtime.test.ts | 128 ++++++++++++++++++++++++++
src/main/runtime/orca-runtime.ts | 93 ++++++++++++++++++-
4 files changed, 264 insertions(+), 2 deletions(-)
diff --git a/src/cli/index.test.ts b/src/cli/index.test.ts
index ab476b4e03a..deb5472b784 100644
--- a/src/cli/index.test.ts
+++ b/src/cli/index.test.ts
@@ -1348,6 +1348,42 @@ describe('orca cli worktree awareness', () => {
})
})
+ it('prints terminal.read fallback screen lines in json mode', async () => {
+ queueFixtures(
+ callMock,
+ okFixture('req_terminal_read', {
+ terminal: {
+ handle: 'term_worker',
+ status: 'running',
+ tail: ['Claude Code', 'Checking files', 'Waiting for input'],
+ truncated: false,
+ limited: true,
+ oldestCursor: '0',
+ nextCursor: '3000',
+ latestCursor: '3000',
+ returnedLineCount: 3
+ }
+ })
+ )
+ const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
+
+ await main(
+ ['terminal', 'read', '--terminal', 'term_worker', '--limit', '120', '--json'],
+ '/tmp/repo'
+ )
+
+ expect(callMock).toHaveBeenCalledWith('terminal.read', {
+ terminal: 'term_worker',
+ limit: 120
+ })
+ const printed = JSON.parse(String(logSpy.mock.calls[0]?.[0]))
+ expect(printed.result.terminal.tail).toEqual([
+ 'Claude Code',
+ 'Checking files',
+ 'Waiting for input'
+ ])
+ })
+
it('keeps interactive Codex startup commands backgrounded unless focus is explicit', async () => {
queueFixtures(
callMock,
diff --git a/src/main/daemon/headless-emulator.ts b/src/main/daemon/headless-emulator.ts
index db891419ce2..fa9231fac1a 100644
--- a/src/main/daemon/headless-emulator.ts
+++ b/src/main/daemon/headless-emulator.ts
@@ -152,6 +152,15 @@ export class HeadlessEmulator {
return this.terminal.buffer.active.type === 'alternate'
}
+ getVisibleLines(): string[] {
+ const buffer = this.terminal.buffer.active
+ const lines: string[] = []
+ for (let row = buffer.viewportY; row < buffer.viewportY + this.terminal.rows; row += 1) {
+ lines.push(buffer.getLine(row)?.translateToString(true) ?? '')
+ }
+ return lines
+ }
+
getCwd(): string | null {
return this.cwd
}
diff --git a/src/main/runtime/orca-runtime.test.ts b/src/main/runtime/orca-runtime.test.ts
index e4557abce91..6a08ce06039 100644
--- a/src/main/runtime/orca-runtime.test.ts
+++ b/src/main/runtime/orca-runtime.test.ts
@@ -48,6 +48,9 @@ import { registerSshGitProvider, unregisterSshGitProvider } from '../providers/s
import { DEFAULT_REPO_BADGE_COLOR, getDefaultWorkspaceSession } from '../../shared/constants'
import { advertisedUrlWatcher } from '../ports/advertised-url-watcher'
import { makePaneKey } from '../../shared/stable-pane-id'
+import { RpcDispatcher } from './rpc/dispatcher'
+import type { RpcRequest } from './rpc/core'
+import { TERMINAL_METHODS } from './rpc/methods/terminal'
const electronMocks = vi.hoisted(() => {
type Listener = (...args: unknown[]) => void
@@ -620,6 +623,10 @@ function createRuntime(): OrcaRuntimeService {
return new OrcaRuntimeService(store)
}
+function makeRpcRequest(method: string, params?: unknown): RpcRequest {
+ return { id: 'req-1', authToken: 'tok', method, params }
+}
+
function makeWorktreeMeta(overrides: Partial = {}): WorktreeMeta {
return {
displayName: '',
@@ -5389,6 +5396,127 @@ describe('OrcaRuntimeService', () => {
expect(shiftCallCount).toBe(0)
})
+ it('falls back to renderer visible screen when uncursored TUI tail is blank', async () => {
+ const serializeBuffer = vi.fn().mockResolvedValue({
+ data: '\x1b[?1049hClaude Code\r\nWorking on fix\r\nTool: Read\r\n',
+ cols: 80,
+ rows: 24
+ })
+ const runtime = new OrcaRuntimeService(store)
+ runtime.setPtyController({
+ write: () => true,
+ kill: () => true,
+ getForegroundProcess: async () => null,
+ hasRendererSerializer: () => true,
+ serializeBuffer
+ })
+ syncSinglePty(runtime)
+
+ const [terminal] = (await runtime.listTerminals()).terminals
+ runtime.onPtyData('pty-1', `${Array.from({ length: 3000 }, () => ' ').join('\n')}\n`, 100)
+
+ const read = await runtime.readTerminal(terminal.handle)
+
+ expect(read.tail).toEqual(['Claude Code', 'Working on fix', 'Tool: Read'])
+ expect(serializeBuffer).toHaveBeenCalledWith('pty-1', {
+ scrollbackRows: 0,
+ altScreenForcesZeroRows: false
+ })
+ })
+
+ it('returns renderer visible screen lines through terminal.read RPC JSON result', async () => {
+ const serializeBuffer = vi.fn().mockResolvedValue({
+ data: '\x1b[?1049hClaude Code\r\nChecking files\r\nWaiting for input\r\n',
+ cols: 80,
+ rows: 24
+ })
+ const runtime = new OrcaRuntimeService(store)
+ runtime.setPtyController({
+ write: () => true,
+ kill: () => true,
+ getForegroundProcess: async () => null,
+ hasRendererSerializer: () => true,
+ serializeBuffer
+ })
+ syncSinglePty(runtime)
+
+ const [terminal] = (await runtime.listTerminals()).terminals
+ runtime.onPtyData('pty-1', `${Array.from({ length: 3000 }, () => '').join('\n')}\n`, 100)
+ const dispatcher = new RpcDispatcher({ runtime, methods: TERMINAL_METHODS })
+
+ const response = await dispatcher.dispatch(
+ makeRpcRequest('terminal.read', { terminal: terminal.handle })
+ )
+
+ expect(response.ok).toBe(true)
+ if (!response.ok) {
+ throw new Error(response.error.message)
+ }
+ expect(response.result).toMatchObject({
+ terminal: {
+ handle: terminal.handle,
+ status: 'running',
+ tail: ['Claude Code', 'Checking files', 'Waiting for input']
+ }
+ })
+ })
+
+ it('does not use renderer visible-screen fallback for cursor transcript reads', async () => {
+ const serializeBuffer = vi.fn().mockResolvedValue({
+ data: 'Visible TUI\n',
+ cols: 80,
+ rows: 24
+ })
+ const runtime = new OrcaRuntimeService(store)
+ runtime.setPtyController({
+ write: () => true,
+ kill: () => true,
+ getForegroundProcess: async () => null,
+ hasRendererSerializer: () => true,
+ serializeBuffer
+ })
+ syncSinglePty(runtime)
+
+ const [terminal] = (await runtime.listTerminals()).terminals
+ runtime.onPtyData('pty-1', ' \n', 100)
+
+ const read = await runtime.readTerminal(terminal.handle, { cursor: 0 })
+
+ expect(read.tail).toEqual([''])
+ expect(serializeBuffer).not.toHaveBeenCalledWith('pty-1', {
+ scrollbackRows: 0,
+ altScreenForcesZeroRows: false
+ })
+ })
+
+ it('does not use renderer visible-screen fallback for a short blank shell tail', async () => {
+ const serializeBuffer = vi.fn().mockResolvedValue({
+ data: 'shell prompt\n',
+ cols: 80,
+ rows: 24
+ })
+ const runtime = new OrcaRuntimeService(store)
+ runtime.setPtyController({
+ write: () => true,
+ kill: () => true,
+ getForegroundProcess: async () => null,
+ hasRendererSerializer: () => true,
+ serializeBuffer
+ })
+ syncSinglePty(runtime)
+
+ const [terminal] = (await runtime.listTerminals()).terminals
+ runtime.onPtyData('pty-1', '\n\n', 100)
+
+ const read = await runtime.readTerminal(terminal.handle)
+
+ expect(read.tail).toEqual(['', ''])
+ expect(serializeBuffer).not.toHaveBeenCalledWith('pty-1', {
+ scrollbackRows: 0,
+ altScreenForcesZeroRows: false
+ })
+ })
+
it('trims oversized terminal output bursts without per-line array shifts', async () => {
const shiftSpy = vi.spyOn(Array.prototype, 'shift')
const lines = Array.from({ length: 5000 }, (_, index) => `line-${index}`)
diff --git a/src/main/runtime/orca-runtime.ts b/src/main/runtime/orca-runtime.ts
index c91bf182956..fce1fdb2720 100644
--- a/src/main/runtime/orca-runtime.ts
+++ b/src/main/runtime/orca-runtime.ts
@@ -3825,6 +3825,59 @@ export class OrcaRuntimeService {
return rendererSnapshot ? { ...rendererSnapshot, source: 'renderer' } : null
}
+ private async withVisibleSnapshotFallback(
+ ptyId: string,
+ read: RuntimeTerminalRead,
+ opts: { cursor?: number; limit?: number } = {}
+ ): Promise {
+ if (!shouldFallbackToVisibleTerminalSnapshot(read, opts)) {
+ return read
+ }
+ const lines = await this.readRendererVisibleSnapshotLines(ptyId)
+ if (lines.length === 0) {
+ return read
+ }
+ return buildVisibleSnapshotReadFallback(read, lines, opts.limit)
+ }
+
+ private async readRendererVisibleSnapshotLines(ptyId: string): Promise {
+ const controller = this.ptyController
+ if (!controller?.serializeBuffer) {
+ return []
+ }
+ if (controller.hasRendererSerializer && !controller.hasRendererSerializer(ptyId)) {
+ return []
+ }
+ try {
+ // Why: raw PTY tails can be whitespace-only while a full-screen TUI is
+ // visibly nonblank in renderer xterm. Ask the renderer for the active
+ // screen instead of reusing the headless transcript path.
+ const snapshot = await controller.serializeBuffer(ptyId, {
+ scrollbackRows: 0,
+ altScreenForcesZeroRows: false
+ })
+ if (!snapshot || snapshot.data.length === 0) {
+ return []
+ }
+ const emulator = new HeadlessEmulator({
+ cols: snapshot.cols,
+ rows: snapshot.rows,
+ scrollback: 0
+ })
+ try {
+ await emulator.write(snapshot.data)
+ return emulator
+ .getVisibleLines()
+ .map((line) => line.trimEnd())
+ .filter((line) => line.trim().length > 0)
+ } finally {
+ emulator.dispose()
+ }
+ } catch {
+ return []
+ }
+ }
+
private async serializeHeadlessTerminalBuffer(
ptyId: string,
opts: { scrollbackRows?: number; includeEmpty?: boolean } = {}
@@ -5930,7 +5983,8 @@ export class OrcaRuntimeService {
): Promise {
const pty = this.getLivePtyForHandle(handle)
if (pty) {
- return this.readPtyTerminal(handle, pty.pty, opts)
+ const read = this.readPtyTerminal(handle, pty.pty, opts)
+ return this.withVisibleSnapshotFallback(pty.pty.ptyId, read, opts)
}
const { leaf } = this.getLiveLeafForHandle(handle)
@@ -5944,7 +5998,7 @@ export class OrcaRuntimeService {
cursor: opts.cursor,
limit: opts.limit
})
- return read
+ return leaf.ptyId ? this.withVisibleSnapshotFallback(leaf.ptyId, read, opts) : read
}
async sendTerminal(
@@ -15388,6 +15442,41 @@ function readTerminalTail(args: {
}
}
+function shouldFallbackToVisibleTerminalSnapshot(
+ read: RuntimeTerminalRead,
+ opts: { cursor?: number; limit?: number }
+): boolean {
+ if (typeof opts.cursor === 'number') {
+ return false
+ }
+ if (read.tail.length === 0) {
+ return false
+ }
+ const hasSubstantialBlankTail =
+ read.limited === true || read.truncated || read.tail.length >= DEFAULT_TERMINAL_READ_LIMIT
+ return hasSubstantialBlankTail && read.tail.every((line) => line.trim().length === 0)
+}
+
+function buildVisibleSnapshotReadFallback(
+ read: RuntimeTerminalRead,
+ visibleLines: string[],
+ limit: number | undefined
+): RuntimeTerminalRead {
+ const lineLimit = terminalReadLimit(limit, DEFAULT_TERMINAL_READ_LIMIT)
+ const lineBoundedTail = visibleLines.slice(-lineLimit)
+ const charBoundedTail = trimTerminalPreviewToCharacterBudget(
+ lineBoundedTail,
+ MAX_TERMINAL_PREVIEW_CHARS
+ )
+ return {
+ ...read,
+ tail: charBoundedTail.tail,
+ limited:
+ read.limited || lineBoundedTail.length < visibleLines.length || charBoundedTail.limited,
+ returnedLineCount: charBoundedTail.tail.length
+ }
+}
+
function getTerminalState(leaf: RuntimeLeafRecord): RuntimeTerminalState {
if (leaf.connected) {
return 'running'
From d09a7fa28b2728a28bdf399fecea3c3abdfbbfdc Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 18:59:17 -0400
Subject: [PATCH 005/165] Add Simplified Chinese, Korean, and Japanese UI
localization (#5046)
---
.gitignore | 5 +
config/scripts/bootstrap-locale-catalog.mjs | 196 +
config/scripts/bootstrap-zh-catalog.mjs | 12 +
.../codemod-settings-search-keywords.mjs | 58 +
config/scripts/locale-ja-phrase-fixes.mjs | 242 +
config/scripts/locale-ja-value-overrides.mjs | 155 +
config/scripts/locale-key-overrides.mjs | 594 +
config/scripts/locale-ko-key-overrides.mjs | 158 +
.../scripts/locale-ko-phrase-fixes-round5.mjs | 60 +
config/scripts/locale-ko-phrase-fixes.mjs | 71 +
config/scripts/locale-ko-value-overrides.mjs | 231 +
config/scripts/locale-phrase-fixes.mjs | 379 +
.../locale-search-keyword-overrides.mjs | 257 +
...cale-translation-policy-ko-round5.test.mjs | 86 +
...cale-translation-policy.ja-round5.test.mjs | 104 +
config/scripts/locale-translation-policy.mjs | 328 +
.../locale-translation-policy.test.mjs | 586 +
...cale-translation-policy.zh-round5.test.mjs | 88 +
config/scripts/locale-value-overrides.mjs | 513 +
.../scripts/locale-zh-phrase-fixes-round5.mjs | 57 +
config/scripts/locale-zh-value-overrides.mjs | 191 +
config/scripts/repair-locale-catalog.mjs | 75 +
.../scripts/verify-localization-catalog.mjs | 108 +-
package.json | 5 +
src/main/i18n/main-i18n.ts | 12 +
.../AgentCapabilitiesSetupAction.tsx | 81 +-
.../components/feature-wall/KeepAwakeCard.tsx | 12 +-
.../agent-capability-setup-status.ts | 66 +-
.../components/settings/AgentAwakeSetting.tsx | 11 +-
.../components/settings/AgentsPane.test.tsx | 15 +-
.../src/components/settings/AgentsPane.tsx | 18 +-
.../settings/AppearancePane.test.tsx | 77 +-
.../components/settings/AppearancePane.tsx | 34 +-
.../settings/MobileEmulatorSettingsPane.tsx | 11 +-
.../src/components/settings/Settings.tsx | 314 +-
.../components/settings/SettingsSidebar.tsx | 43 +-
.../components/settings/accounts-search.ts | 130 +-
.../components/settings/advanced-search.ts | 40 +-
.../components/settings/agent-awake-copy.ts | 42 +-
.../agent-generated-tab-title-copy.ts | 50 +-
.../settings/agent-status-hooks-copy.ts | 55 +-
.../src/components/settings/agents-search.ts | 83 +-
.../components/settings/appearance-search.ts | 166 +-
.../settings/appearance-status-bar-search.ts | 179 +-
.../settings/auto-rename-branch-search.ts | 91 +-
.../src/components/settings/browser-search.ts | 105 +-
.../components/settings/browser-use-search.ts | 116 +-
.../settings/commit-message-ai-search.ts | 151 +-
.../settings/computer-use-search.ts | 28 +-
.../settings/developer-permissions-search.ts | 121 +-
.../settings/experimental-search.ts | 185 +-
.../settings/floating-workspace-search.ts | 51 +-
.../settings/general-editor-search.ts | 61 +-
.../src/components/settings/general-search.ts | 196 +-
.../src/components/settings/git-search.ts | 68 +-
.../src/components/settings/input-search.ts | 26 +-
.../settings/integrations-search.ts | 158 +-
.../settings/mobile-emulator-search.ts | 136 +-
.../components/settings/mobile-pane-search.ts | 100 +-
.../settings/mobile-settings-search.ts | 53 +-
.../settings/notifications-search.ts | 135 +-
.../settings/orchestration-search.ts | 70 +-
.../src/components/settings/privacy-search.ts | 80 +-
.../settings/quick-commands-search.ts | 67 +-
.../repository-git-author-search-entries.ts | 74 +
.../repository-git-hooks-search-entries.ts | 169 +
.../repository-git-worktree-search-entries.ts | 136 +
.../components/settings/repository-search.ts | 245 +-
.../settings/runtime-environments-search.ts | 96 +-
.../settings/settings-search-keywords.test.ts | 53 +
.../settings/settings-search-keywords.ts | 50 +
.../components/settings/shortcuts-search.ts | 25 +-
.../src/components/settings/ssh-search.ts | 39 +-
.../src/components/settings/tasks-search.ts | 21 +-
.../terminal-advanced-platform-search.ts | 82 +-
.../settings/terminal-clipboard-search.ts | 106 +-
.../terminal-pane-appearance-search.ts | 27 +-
.../settings/terminal-theme-search.ts | 42 +-
.../settings/terminal-typography-search.ts | 120 +-
.../settings/terminal-window-setup-search.ts | 122 +-
.../settings/terminal-windows-search.ts | 171 +-
.../components/settings/voice-pane-search.ts | 71 +-
src/renderer/src/i18n/i18n.ts | 12 +
src/renderer/src/i18n/locales/en.json | 68 +-
src/renderer/src/i18n/locales/ja.json | 9804 +++++++++++++++++
src/renderer/src/i18n/locales/ko.json | 9804 +++++++++++++++++
src/renderer/src/i18n/locales/zh.json | 9804 +++++++++++++++++
src/renderer/src/i18n/supported-languages.ts | 26 +-
src/shared/ui-language.test.ts | 25 +
src/shared/ui-language.ts | 20 +-
src/shared/ui-locale.test.ts | 55 +-
src/shared/ui-locale.ts | 33 +-
92 files changed, 37841 insertions(+), 1455 deletions(-)
create mode 100644 config/scripts/bootstrap-locale-catalog.mjs
create mode 100644 config/scripts/bootstrap-zh-catalog.mjs
create mode 100644 config/scripts/codemod-settings-search-keywords.mjs
create mode 100644 config/scripts/locale-ja-phrase-fixes.mjs
create mode 100644 config/scripts/locale-ja-value-overrides.mjs
create mode 100644 config/scripts/locale-key-overrides.mjs
create mode 100644 config/scripts/locale-ko-key-overrides.mjs
create mode 100644 config/scripts/locale-ko-phrase-fixes-round5.mjs
create mode 100644 config/scripts/locale-ko-phrase-fixes.mjs
create mode 100644 config/scripts/locale-ko-value-overrides.mjs
create mode 100644 config/scripts/locale-phrase-fixes.mjs
create mode 100644 config/scripts/locale-search-keyword-overrides.mjs
create mode 100644 config/scripts/locale-translation-policy-ko-round5.test.mjs
create mode 100644 config/scripts/locale-translation-policy.ja-round5.test.mjs
create mode 100644 config/scripts/locale-translation-policy.mjs
create mode 100644 config/scripts/locale-translation-policy.test.mjs
create mode 100644 config/scripts/locale-translation-policy.zh-round5.test.mjs
create mode 100644 config/scripts/locale-value-overrides.mjs
create mode 100644 config/scripts/locale-zh-phrase-fixes-round5.mjs
create mode 100644 config/scripts/locale-zh-value-overrides.mjs
create mode 100644 config/scripts/repair-locale-catalog.mjs
create mode 100644 src/renderer/src/components/settings/repository-git-author-search-entries.ts
create mode 100644 src/renderer/src/components/settings/repository-git-hooks-search-entries.ts
create mode 100644 src/renderer/src/components/settings/repository-git-worktree-search-entries.ts
create mode 100644 src/renderer/src/components/settings/settings-search-keywords.test.ts
create mode 100644 src/renderer/src/components/settings/settings-search-keywords.ts
create mode 100644 src/renderer/src/i18n/locales/ja.json
create mode 100644 src/renderer/src/i18n/locales/ko.json
create mode 100644 src/renderer/src/i18n/locales/zh.json
create mode 100644 src/shared/ui-language.test.ts
diff --git a/.gitignore b/.gitignore
index 4417cda3eae..c87bcacb82b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,3 +105,8 @@ playwright-report/
# Agent hook runtime endpoints (machine-local secrets)
/agent-hooks/
validation-screenshots/
+
+# Localization bootstrap cache (regenerated by bootstrap:*-catalog)
+src/renderer/src/i18n/locales/.zh-catalog-cache.json
+src/renderer/src/i18n/locales/.ko-catalog-cache.json
+src/renderer/src/i18n/locales/.ja-catalog-cache.json
diff --git a/config/scripts/bootstrap-locale-catalog.mjs b/config/scripts/bootstrap-locale-catalog.mjs
new file mode 100644
index 00000000000..d7f15c6bc8a
--- /dev/null
+++ b/config/scripts/bootstrap-locale-catalog.mjs
@@ -0,0 +1,196 @@
+import fs from 'node:fs/promises'
+import path from 'node:path'
+import process from 'node:process'
+import { pathToFileURL } from 'node:url'
+
+import {
+ collectStringLeaves,
+ repairCatalog,
+ repairTranslatedValue,
+ setLeaf,
+ shouldPreserveEnglishValue
+} from './locale-translation-policy.mjs'
+
+const PLACEHOLDER_RE = /\{\{[^}]+\}\}/g
+const LOCALES_DIR = path.join('src', 'renderer', 'src', 'i18n', 'locales')
+
+const LOCALE_CONFIG = {
+ zh: {
+ targetLanguage: 'zh-CN',
+ displayName: 'Simplified Chinese',
+ cacheFile: '.zh-catalog-cache.json'
+ },
+ ko: {
+ targetLanguage: 'ko',
+ displayName: 'Korean',
+ cacheFile: '.ko-catalog-cache.json'
+ },
+ ja: {
+ targetLanguage: 'ja',
+ displayName: 'Japanese',
+ cacheFile: '.ja-catalog-cache.json'
+ }
+}
+
+function protectPlaceholders(text) {
+ const tokens = []
+ const protectedText = text.replace(PLACEHOLDER_RE, (match) => {
+ const token = `__PH${tokens.length}__`
+ tokens.push(match)
+ return token
+ })
+ return { protectedText, tokens }
+}
+
+function restorePlaceholders(text, tokens) {
+ let result = text
+ for (let index = 0; index < tokens.length; index += 1) {
+ const patterns = [`__PH${index}__`, `__ PH ${index} __`, `__PH ${index}__`, `__ PH${index}__`]
+ for (const pattern of patterns) {
+ result = result.replaceAll(pattern, tokens[index])
+ }
+ }
+ return result
+}
+
+function shouldSkipTranslation(text) {
+ return shouldPreserveEnglishValue(text)
+}
+
+async function translateText(text, targetLanguage) {
+ const url = new URL('https://translate.googleapis.com/translate_a/single')
+ url.searchParams.set('client', 'gtx')
+ url.searchParams.set('sl', 'en')
+ url.searchParams.set('tl', targetLanguage)
+ url.searchParams.set('dt', 't')
+ url.searchParams.set('q', text)
+
+ let lastError
+ for (let attempt = 0; attempt < 5; attempt += 1) {
+ try {
+ const response = await fetch(url)
+ if (!response.ok) {
+ throw new Error(`Translation request failed with status ${response.status}`)
+ }
+ const payload = await response.json()
+ return payload[0].map((part) => part[0]).join('')
+ } catch (error) {
+ lastError = error
+ await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)))
+ }
+ }
+ throw lastError
+}
+
+async function mapWithConcurrency(items, concurrency, mapper) {
+ const results = Array.from({ length: items.length })
+ let nextIndex = 0
+
+ async function worker() {
+ while (nextIndex < items.length) {
+ const currentIndex = nextIndex
+ nextIndex += 1
+ results[currentIndex] = await mapper(items[currentIndex], currentIndex)
+ }
+ }
+
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()))
+ return results
+}
+
+async function loadCache(cachePath) {
+ try {
+ const raw = JSON.parse(await fs.readFile(cachePath, 'utf8'))
+ return new Map(Object.entries(raw))
+ } catch {
+ return new Map()
+ }
+}
+
+async function saveCache(cachePath, cache) {
+ const raw = Object.fromEntries(cache.entries())
+ await fs.writeFile(cachePath, `${JSON.stringify(raw, null, 2)}\n`, 'utf8')
+}
+
+function parseLocaleArg(argv) {
+ const localeFlagIndex = argv.indexOf('--locale')
+ if (localeFlagIndex !== -1 && argv[localeFlagIndex + 1]) {
+ return argv[localeFlagIndex + 1]
+ }
+ return argv[2]
+}
+
+export async function main(root = process.cwd(), locale = parseLocaleArg(process.argv)) {
+ const config = LOCALE_CONFIG[locale]
+ if (!config) {
+ console.error(
+ `Unsupported locale "${locale}". Supported: ${Object.keys(LOCALE_CONFIG).join(', ')}`
+ )
+ return 1
+ }
+
+ const enPath = path.join(root, LOCALES_DIR, 'en.json')
+ const localePath = path.join(root, LOCALES_DIR, `${locale}.json`)
+ const cachePath = path.join(root, LOCALES_DIR, config.cacheFile)
+ const enCatalog = JSON.parse(await fs.readFile(enPath, 'utf8'))
+ const localeCatalog = structuredClone(enCatalog)
+ const leaves = collectStringLeaves(enCatalog)
+ const uniqueValues = [...new Set(leaves.map((leaf) => leaf.value))]
+ const cache = await loadCache(cachePath)
+ const toTranslate = uniqueValues.filter(
+ (value) => !shouldSkipTranslation(value) && !cache.has(value)
+ )
+
+ console.log(
+ `Translating ${toTranslate.length} unique strings to ${config.displayName} (${cache.size} cached)...`
+ )
+
+ let completed = 0
+ await mapWithConcurrency(toTranslate, 2, async (value) => {
+ completed += 1
+ if (completed % 25 === 0) {
+ console.log(` ${completed}/${toTranslate.length}`)
+ await saveCache(cachePath, cache)
+ }
+ const { protectedText, tokens } = protectPlaceholders(value)
+ const translated = await translateText(protectedText, config.targetLanguage)
+ const restored = restorePlaceholders(translated, tokens)
+ cache.set(
+ value,
+ repairTranslatedValue({ key: '', enValue: value, localeValue: restored, locale })
+ )
+ await new Promise((resolve) => setTimeout(resolve, 200))
+ })
+
+ for (const value of uniqueValues) {
+ if (shouldSkipTranslation(value) && !cache.has(value)) {
+ cache.set(value, value)
+ }
+ }
+
+ await saveCache(cachePath, cache)
+
+ for (const leaf of leaves) {
+ const cached = cache.get(leaf.value) ?? leaf.value
+ setLeaf(
+ localeCatalog,
+ leaf.key,
+ repairTranslatedValue({
+ key: leaf.key,
+ enValue: leaf.value,
+ localeValue: cached,
+ locale
+ })
+ )
+ }
+
+ repairCatalog(enCatalog, localeCatalog, locale)
+
+ await fs.writeFile(localePath, `${JSON.stringify(localeCatalog, null, 2)}\n`, 'utf8')
+ console.log(`Wrote ${localePath}`)
+ return 0
+}
+
+if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
+ process.exit(await main())
+}
diff --git a/config/scripts/bootstrap-zh-catalog.mjs b/config/scripts/bootstrap-zh-catalog.mjs
new file mode 100644
index 00000000000..609c310e977
--- /dev/null
+++ b/config/scripts/bootstrap-zh-catalog.mjs
@@ -0,0 +1,12 @@
+import process from 'node:process'
+import { pathToFileURL } from 'node:url'
+
+import { main as bootstrapLocaleCatalog } from './bootstrap-locale-catalog.mjs'
+
+export async function main(root = process.cwd()) {
+ return bootstrapLocaleCatalog(root, 'zh')
+}
+
+if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
+ process.exit(await main())
+}
diff --git a/config/scripts/codemod-settings-search-keywords.mjs b/config/scripts/codemod-settings-search-keywords.mjs
new file mode 100644
index 00000000000..3d44832e2b4
--- /dev/null
+++ b/config/scripts/codemod-settings-search-keywords.mjs
@@ -0,0 +1,58 @@
+import fs from 'node:fs/promises'
+import path from 'node:path'
+
+const SETTINGS_DIR = path.join('src', 'renderer', 'src', 'components', 'settings')
+const IMPORT_LINE = "import { translateSearchKeyword } from './settings-search-keywords'"
+
+function transformKeywordsBlock(block) {
+ return block.replace(
+ /(? {
+ const transformedBody = transformKeywordsBlock(body)
+ return transformedBody === body ? match : `keywords: [${transformedBody}]`
+ })
+
+ if (next === content) {
+ return content
+ }
+
+ if (!next.includes(IMPORT_LINE)) {
+ const i18nImport = "import { translate } from '@/i18n/i18n'"
+ next = next.includes(i18nImport)
+ ? next.replace(i18nImport, `${i18nImport}\n${IMPORT_LINE}`)
+ : `${IMPORT_LINE}\n${next}`
+ }
+
+ return next
+}
+
+async function main() {
+ const entries = await fs.readdir(SETTINGS_DIR)
+ const files = entries
+ .filter((name) => name.endsWith('-search.ts'))
+ .map((name) => path.join(SETTINGS_DIR, name))
+
+ let changed = 0
+ for (const filePath of files) {
+ const original = await fs.readFile(filePath, 'utf8')
+ const updated = transformFile(original)
+ if (updated !== original) {
+ await fs.writeFile(filePath, updated, 'utf8')
+ changed += 1
+ console.log(`Updated ${filePath}`)
+ }
+ }
+
+ console.log(`Codemod complete (${changed} files).`)
+}
+
+await main()
diff --git a/config/scripts/locale-ja-phrase-fixes.mjs b/config/scripts/locale-ja-phrase-fixes.mjs
new file mode 100644
index 00000000000..cb77ebacdcf
--- /dev/null
+++ b/config/scripts/locale-ja-phrase-fixes.mjs
@@ -0,0 +1,242 @@
+// Japanese phrase fixes from high-visibility UI audit rounds 1–4.
+// Why: keep locale-phrase-fixes.mjs under max-lines while preserving repair coverage.
+export const JA_PHRASE_FIXES = [
+ { pattern: /解雇/g, replacement: '閉じる', whenEnIncludes: 'Dismiss' },
+ { pattern: /却下/g, replacement: '閉じる', whenEnIncludes: 'Dismiss' },
+ { pattern: /代理人/g, replacement: 'エージェント', whenEnIncludes: 'agent' },
+ { pattern: /支店/g, replacement: 'ブランチ', whenEnIncludes: 'ranch' },
+ { pattern: /港(?!口)/g, replacement: 'ポート', whenEnIncludes: 'ort' },
+ { pattern: /会議/g, replacement: 'セッション', whenEnIncludes: 'session' },
+ { pattern: /広報/g, replacement: 'PR', whenEnIncludes: 'PR' },
+ { pattern: /端末/g, replacement: 'ターミナル', whenEnIncludes: 'erminal' },
+ { pattern: /シャチ:\/\//g, replacement: 'orca://', whenEnIncludes: 'orca://' },
+ { pattern: /線形/g, replacement: 'Linear', whenEnIncludes: 'Linear' },
+ { pattern: /不和/g, replacement: 'Discord', whenEnIncludes: 'Discord' },
+ { pattern: /爽やか/g, replacement: '更新中', whenEnIncludes: 'Refreshing' },
+ { pattern: /殺害/g, replacement: '終了中', whenEnIncludes: 'Killing' },
+ { pattern: /殺す/g, replacement: '強制終了', whenEnIncludes: 'Kill' },
+ { pattern: /皆殺し/g, replacement: 'すべて終了', whenEnIncludes: 'kill all' },
+ { pattern: /崩壊させる/g, replacement: '折りたたむ', whenEnIncludes: 'Collapse Orca' },
+ { pattern: /崩壊/g, replacement: '折りたたむ', whenEnIncludes: 'Collapse' },
+ { pattern: /一般的な/g, replacement: '一般', whenEnIncludes: 'General' },
+ { pattern: /高度な/g, replacement: '詳細設定', whenEnIncludes: 'Advanced' },
+ { pattern: /実験的(?!機能)/g, replacement: '実験的機能', whenEnIncludes: 'Experimental' },
+ {
+ pattern: /コンピュータの使用/g,
+ replacement: 'コンピュータ操作',
+ whenEnIncludes: 'Computer Use'
+ },
+ { pattern: /検索設定/g, replacement: '設定を検索', whenEnIncludes: 'Search settings' },
+ { pattern: /検索スキル/g, replacement: 'スキルを検索', whenEnIncludes: 'Search skills' },
+ { pattern: /検索ブロック/g, replacement: 'ブロックを検索', whenEnIncludes: 'Search blocks' },
+ { pattern: /暗い/g, replacement: 'ダーク', whenEnIncludes: 'Dark' },
+ { pattern: /もう一度やり直してください/g, replacement: '再試行', whenEnIncludes: 'Try Again' },
+ {
+ pattern: /今すぐ再起動してください/g,
+ replacement: '今すぐ再起動',
+ whenEnIncludes: 'Restart now'
+ },
+ { pattern: /待っている/g, replacement: '待機中', whenEnIncludes: 'Waiting' },
+ {
+ pattern: /眠っているのを隠す/g,
+ replacement: 'スリープ中を非表示',
+ whenEnIncludes: 'Hide sleeping'
+ },
+ { pattern: /インタフェース/g, replacement: 'インターフェース', whenEnIncludes: 'Interface' },
+ { pattern: /統合/g, replacement: '連携', whenEnIncludes: 'Integration' },
+ {
+ pattern: /統合しました/g,
+ replacement: 'マージしました',
+ whenEnIncludes: 'Merged MR'
+ },
+ {
+ pattern: /統合されています/g,
+ replacement: 'マージされています',
+ whenEnIncludes: 'already merged'
+ },
+ { pattern: /再起動します/g, replacement: '再起動', whenEnIncludes: 'Restart Orca' },
+ { pattern: /オウムガイ/g, replacement: 'Nautilus', whenEnIncludes: 'Nautilus' },
+ {
+ pattern: /Kim サブスクリプション/g,
+ replacement: 'Kimi サブスクリプション',
+ whenEnIncludes: 'Kimi subscription'
+ },
+ { pattern: /空き状況/g, replacement: '利用可否', whenEnIncludes: 'availability' },
+ { pattern: /指示/g, replacement: 'コマンド', whenEnIncludes: 'Command' },
+ { pattern: /弦/g, replacement: '文字列', whenEnIncludes: 'string' },
+ { pattern: /新しい/g, replacement: '新規', whenEnIncludes: 'New' },
+ {
+ pattern: /Open Linearタスク/g,
+ replacement: 'Linear タスクを開く',
+ whenEnIncludes: 'Open Linear tasks'
+ },
+ { pattern: /小切手/g, replacement: 'チェック', whenEnIncludes: 'checks' },
+ { pattern: /査読者/g, replacement: 'レビュアー', whenEnIncludes: 'reviewer' },
+ { pattern: /レビュー担当者/g, replacement: 'レビュアー', whenEnIncludes: 'reviewer' },
+ { pattern: /電話機/g, replacement: 'スマートフォン', whenEnIncludes: 'phone' },
+ {
+ pattern: /壊れたチェック/g,
+ replacement: '失敗したチェック',
+ whenEnIncludes: 'broken check'
+ },
+ {
+ pattern: /コンピューターの使用/g,
+ replacement: 'コンピュータ操作',
+ whenEnIncludes: 'Computer Use'
+ },
+ {
+ pattern: /コンピューター使用/g,
+ replacement: 'コンピュータ操作',
+ whenEnIncludes: 'Computer Use'
+ },
+ { pattern: /携帯電話/g, replacement: 'スマートフォン', whenEnIncludes: 'phone' },
+ {
+ pattern: /実験的機能な/g,
+ replacement: '実験的機能',
+ whenEnIncludes: 'experimental'
+ },
+ { pattern: /ジラ/g, replacement: 'Jira', whenEnIncludes: 'Jira' },
+ { pattern: /ジラ/g, replacement: 'Jira', whenEnIncludes: 'jira' },
+ { pattern: /Linear問題/g, replacement: 'Linear イシュー', whenEnIncludes: 'Linear issue' },
+ { pattern: /Linearの問題/g, replacement: 'Linear イシュー', whenEnIncludes: 'Linear issue' },
+ { pattern: /Jira の問題/g, replacement: 'Jira イシュー', whenEnIncludes: 'Jira issue' },
+ {
+ pattern: /一般的なアクション/g,
+ replacement: 'よく使うアクション',
+ whenEnIncludes: 'common actions'
+ },
+ { pattern: /Jira 課題/g, replacement: 'Jira イシュー', whenEnIncludes: 'issue' },
+ { pattern: /GitHub の課題/g, replacement: 'GitHub イシュー', whenEnIncludes: 'issue' },
+ { pattern: /サブ課題/g, replacement: 'サブイシュー', whenEnIncludes: 'sub-issue' },
+ { pattern: /課題タイプ/g, replacement: 'イシュータイプ', whenEnIncludes: 'issue' },
+ { pattern: /課題セット/g, replacement: 'イシューセット', whenEnIncludes: 'issue' },
+ { pattern: /課題から/g, replacement: 'イシューから', whenEnIncludes: 'issue' },
+ { pattern: /課題に/g, replacement: 'イシューに', whenEnIncludes: 'issue' },
+ { pattern: /課題を/g, replacement: 'イシューを', whenEnIncludes: 'issue' },
+ { pattern: /課題の/g, replacement: 'イシューの', whenEnIncludes: 'issue' },
+ { pattern: /GitHub の問題/g, replacement: 'GitHub イシュー', whenEnIncludes: 'issue' },
+ { pattern: /GitLab の問題/g, replacement: 'GitLab イシュー', whenEnIncludes: 'issue' },
+ {
+ pattern: /問題ワークスペース/g,
+ replacement: 'イシューワークスペース',
+ whenEnIncludes: 'issue'
+ },
+ { pattern: /問題元/g, replacement: 'イシューソース', whenEnIncludes: 'issue' },
+ { pattern: /問題識別子/g, replacement: 'イシュー識別子', whenEnIncludes: 'issue' },
+ { pattern: /問題タイプ/g, replacement: 'イシュータイプ', whenEnIncludes: 'issue' },
+ { pattern: /問題の種類/g, replacement: 'イシューの種類', whenEnIncludes: 'issue' },
+ { pattern: /問題の説明/g, replacement: 'イシューの説明', whenEnIncludes: 'issue' },
+ { pattern: /問題の URL/g, replacement: 'イシューの URL', whenEnIncludes: 'issue' },
+ { pattern: /問題番号/g, replacement: 'イシュー番号', whenEnIncludes: 'issue' },
+ { pattern: /問題ソース/g, replacement: 'イシューソース', whenEnIncludes: 'issue' },
+ { pattern: /問題自動化/g, replacement: 'イシュー自動化', whenEnIncludes: 'issue' },
+ { pattern: /問題コマンド/g, replacement: 'イシューコマンド', whenEnIncludes: 'issue' },
+ { pattern: /サブ問題/g, replacement: 'サブイシュー', whenEnIncludes: 'sub-issue' },
+ { pattern: /新規問題/g, replacement: '新規イシュー', whenEnIncludes: 'issue' },
+ { pattern: /GH問題/g, replacement: 'GH イシュー', whenEnIncludes: 'issue' },
+ { pattern: /問題 #/g, replacement: 'イシュー #', whenEnIncludes: 'issue' },
+ { pattern: /問題を表示/g, replacement: 'イシューを表示', whenEnIncludes: 'view issues' },
+ { pattern: /問題を検索/g, replacement: 'イシューを検索', whenEnIncludes: 'issue' },
+ { pattern: /問題を編集/g, replacement: 'イシューを編集', whenEnIncludes: 'issue' },
+ { pattern: /問題を提出/g, replacement: 'イシューを登録', whenEnIncludes: 'file an issue' },
+ { pattern: /問題の作成/g, replacement: 'イシューの作成', whenEnIncludes: 'issue' },
+ { pattern: /問題を更新/g, replacement: 'イシューを更新', whenEnIncludes: 'issue' },
+ { pattern: /問題を読み込/g, replacement: 'イシューを読み込', whenEnIncludes: 'issue' },
+ { pattern: /問題を作成/g, replacement: 'イシューを作成', whenEnIncludes: 'issue' },
+ { pattern: /問題を開く/g, replacement: 'イシューを開く', whenEnIncludes: 'issue' },
+ { pattern: /問題に関連/g, replacement: 'イシューに関連', whenEnIncludes: 'issue' },
+ { pattern: /問題には/g, replacement: 'イシューには', whenEnIncludes: 'issue' },
+ {
+ pattern: /問題を表示しています/g,
+ replacement: 'イシューを表示しています',
+ whenEnIncludes: 'issue'
+ },
+ {
+ pattern: /選択した問題を/g,
+ replacement: '選択したイシューを',
+ whenEnIncludes: 'selected issue'
+ },
+ {
+ pattern: /プロジェクトの問題/g,
+ replacement: 'プロジェクトのイシュー',
+ whenEnIncludes: 'project issues'
+ },
+ {
+ pattern: /フェッチされた問題/g,
+ replacement: '取得済みイシュー',
+ whenEnIncludes: 'fetched issues'
+ },
+ {
+ pattern: /割り当てられた問題/g,
+ replacement: '割り当てられたイシュー',
+ whenEnIncludes: 'assigned issues'
+ },
+ { pattern: /一致する問題/g, replacement: '一致するイシュー', whenEnIncludes: 'issues match' },
+ {
+ pattern: /範囲が限定された問題/g,
+ replacement: 'スコープされたイシュー',
+ whenEnIncludes: 'scoped issues'
+ },
+ { pattern: /GitHubの問題/g, replacement: 'GitHub イシュー', whenEnIncludes: 'GitHub issues' },
+ { pattern: /ドラフト_問題/g, replacement: 'DRAFT_ISSUE', whenEnIncludes: 'DRAFT_ISSUE' },
+ { pattern: /、問題、/g, replacement: '、イシュー、', whenEnIncludes: 'issues' },
+ { pattern: /PR、問題/g, replacement: 'PR、イシュー', whenEnIncludes: 'issues' },
+ { pattern: /GitHub 発行/g, replacement: 'GitHub イシュー', whenEnIncludes: 'issue' },
+ { pattern: /github発行/g, replacement: 'github イシュー', whenEnIncludes: 'issue' },
+ { pattern: /発行コマンド/g, replacement: 'イシューコマンド', whenEnIncludes: 'issue' },
+ { pattern: /発行自動化/g, replacement: 'イシュー自動化', whenEnIncludes: 'issue' },
+ { pattern: /サブ発行/g, replacement: 'サブイシュー', whenEnIncludes: 'sub-issue' },
+ { pattern: /発行元/g, replacement: 'イシューソース', whenEnIncludes: 'Issue source' },
+ { pattern: /、発行、/g, replacement: '、イシュー、', whenEnIncludes: 'issues' },
+ { pattern: /プルリクエスト/g, replacement: 'PR', whenEnIncludes: 'pull request' },
+ { pattern: /プル リクエスト/g, replacement: 'PR', whenEnIncludes: 'pull request' },
+ { pattern: /プルリクエスト/g, replacement: 'PR', whenEnIncludes: 'PR' },
+ { pattern: /プル リクエスト/g, replacement: 'PR', whenEnIncludes: 'PR' },
+ { pattern: /電話プレビュー/g, replacement: 'スマートフォンプレビュー', whenEnIncludes: 'phone' },
+ { pattern: /電話モード/g, replacement: 'スマートフォンモード', whenEnIncludes: 'phone' },
+ { pattern: /電話サイズ/g, replacement: 'スマートフォンサイズ', whenEnIncludes: 'phone' },
+ {
+ pattern: /コンピュータと電話/g,
+ replacement: 'コンピューターとスマートフォン',
+ whenEnIncludes: 'phone'
+ },
+ { pattern: /前の問題/g, replacement: 'フロントマター', whenEnIncludes: 'Front Matter' },
+ { pattern: /ブランチの発行/g, replacement: 'ブランチを公開', whenEnIncludes: 'Publish Branch' },
+ { pattern: /ボタン/g, replacement: 'ボタン', whenEnIncludes: 'button' },
+ {
+ pattern: /レビューが要求されました/g,
+ replacement: 'レビュー依頼済み',
+ whenEnIncludes: 'Review requested'
+ },
+ // Round 5: inline/launch/action homographs, MR phrases, concise UI prompts.
+ { pattern: /列をなして/g, replacement: 'インライン', whenEnIncludes: 'Inline' },
+ { pattern: /列をなして/g, replacement: 'インライン', whenEnIncludes: 'inline' },
+ { pattern: /打ち上げ/g, replacement: '起動', whenEnIncludes: 'Launch' },
+ { pattern: /打ち上げ/g, replacement: '起動', whenEnIncludes: 'launch' },
+ { pattern: /遊ぶ/g, replacement: 'Play', whenEnIncludes: 'Play' },
+ { pattern: /指揮者/g, replacement: 'Conductor', whenEnIncludes: 'Conductor' },
+ { pattern: /マージリクエスト/g, replacement: 'MR', whenEnIncludes: 'merge request' },
+ { pattern: /マージ リクエスト/g, replacement: 'MR', whenEnIncludes: 'merge request' },
+ { pattern: /レビュー者/g, replacement: 'レビュアー', whenEnIncludes: 'Reviewed by' },
+ { pattern: /肩書き/g, replacement: 'タイトル', whenEnIncludes: 'title is required' },
+ { pattern: /見直しが必要/g, replacement: 'レビュー待ち', whenEnIncludes: 'Needs review' },
+ {
+ pattern: /実用的な問題/g,
+ replacement: '対応が必要なイシュー',
+ whenEnIncludes: 'actionable issues'
+ },
+ { pattern: /アクションレシピ/g, replacement: '操作レシピ', whenEnIncludes: 'Action recipes' },
+ { pattern: /クイックアクション/g, replacement: 'クイック操作', whenEnIncludes: 'Quick Actions' },
+ { pattern: /さらなるアクション/g, replacement: 'その他の操作', whenEnIncludes: 'More actions' },
+ {
+ pattern: /その他の PR アクション/g,
+ replacement: 'その他の PR 操作',
+ whenEnIncludes: 'More PR actions'
+ },
+ { pattern: /アクション/g, replacement: '操作', whenEnIncludes: 'action' },
+ { pattern: /を選択してください/g, replacement: 'を選択', whenEnIncludes: 'Select' },
+ { pattern: /を選択してください/g, replacement: 'を選択', whenEnIncludes: 'Choose' },
+ { pattern: /入力してください/g, replacement: '入力', whenEnIncludes: 'Enter' },
+ { pattern: /追加してください/g, replacement: '追加', whenEnIncludes: 'Add' },
+ { pattern: /試してください/g, replacement: '試す', whenEnIncludes: 'Try' }
+]
diff --git a/config/scripts/locale-ja-value-overrides.mjs b/config/scripts/locale-ja-value-overrides.mjs
new file mode 100644
index 00000000000..36615c939cb
--- /dev/null
+++ b/config/scripts/locale-ja-value-overrides.mjs
@@ -0,0 +1,155 @@
+// Japanese value overrides from high-visibility UI audit rounds 1–4.
+// Why: keep locale-value-overrides.mjs under max-lines while preserving exact-match repairs.
+export const JA_VALUE_OVERRIDES = {
+ 'Retry loading presets': 'プリセットの読み込みを再試行',
+ 'Retry Download': 'ダウンロードを再試行',
+ 'Enter a reviewer': 'レビュアーを入力',
+ 'Choose folder': 'フォルダーを選択',
+ 'Choose pet': 'ペットを選択',
+ 'Choose a sound': 'サウンドを選択',
+ 'Pick your default agent': 'デフォルトのエージェントを選択',
+ 'Complete {{artifact_url}}': '{{artifact_url}} を完了',
+ 'Control terminals and agents from your phone.':
+ 'スマートフォンからターミナルとエージェントを操作',
+ 'Add reviewer': 'レビュアーを追加',
+ Reviewer: 'レビュアー',
+ Reviewers: 'レビュアー',
+ 'Fix broken checks': '失敗したチェックを修正',
+ 'No broken checks to fix.': '修正が必要な失敗したチェックはありません',
+ 'Started an AI agent for the broken checks.':
+ '失敗したチェックに対して AI エージェントを開始しました。',
+ 'Failed to start an AI agent for the broken checks: {{value0}}':
+ '失敗したチェックのため AI エージェントを開始できませんでした: {{value0}}',
+ 'Checks unavailable': 'チェックは利用できません',
+ 'Checks pending': '保留中のチェック',
+ checks: 'チェック',
+ 'Add Project': 'プロジェクトを追加',
+ 'Add label': 'ラベルを追加',
+ 'Select Team': 'チームを選択',
+ 'Choose project': 'プロジェクトを選択',
+ 'Add number': '番号を追加',
+ 'Add text': 'テキストを追加',
+ MR: 'MR',
+ mr: 'MR',
+ Gitea: 'Gitea',
+ gitea: 'Gitea',
+ glab: 'glab',
+ 'GitHub Integration': 'GitHub 連携',
+ 'GitLab Integration': 'GitLab 連携',
+ 'Bitbucket Integration': 'Bitbucket 連携',
+ 'Azure DevOps Integration': 'Azure DevOps 連携',
+ 'Gitea Integration': 'Gitea 連携',
+ 'Jira Integration': 'Jira 連携',
+ 'Linear Integration': 'Linear 連携',
+ 'Hide Jira': 'Jira を非表示',
+ 'Linear issue': 'Linear イシュー',
+ 'Linear issues': 'Linear イシュー',
+ 'New Linear issue': '新規 Linear イシュー',
+ 'Jira issue': 'Jira イシュー',
+ 'Jira issues': 'Jira イシュー',
+ 'New Jira issue': '新規 Jira イシュー',
+ 'No Linear issues found': 'Linear イシューが見つかりません',
+ 'Unable to load Linear issues': 'Linear イシューを読み込めません',
+ 'No Jira issues found': 'Jira イシューが見つかりません',
+ issue: 'イシュー',
+ issues: 'イシュー',
+ Issues: 'イシュー',
+ 'Common emulator commands': 'よく使うエミュレータコマンド',
+ 'Pull request': 'PR',
+ 'pull request': 'PR',
+ 'Pull request merged': 'PR がマージされました',
+ 'Pull request reopened': 'PR が再オープンされました',
+ 'Pull request closed': 'PR がクローズされました',
+ 'Preview and edit the selected GitHub issue or pull request.':
+ '選択した GitHub イシューまたは PR をプレビュー・編集します。',
+ 'view issues': 'イシューを表示',
+ 'Review requested': 'レビュー依頼済み',
+ 'Request reviewer {{value0}}': 'レビュアーをリクエスト {{value0}}',
+ 'Unrequest reviewer {{value0}}': 'レビュアーのリクエストを取り消す {{value0}}',
+ 'Phone preview': 'スマートフォンプレビュー',
+ 'Switch to phone mode': 'スマートフォンモードに切り替え',
+ phone: 'スマートフォン',
+ 'Front Matter': 'フロントマター',
+ 'Publish Branch': 'ブランチを公開',
+ 'Issue source': 'イシューソース',
+ 'Sub-issue data is unavailable for your token.':
+ 'トークンではサブイシューデータを利用できません。',
+ 'Start workspace from issue': 'イシューからワークスペースを開始',
+ 'Install the GitHub CLI to enable pull requests, issues, and checks.':
+ 'GitHub CLI をインストールして PR、イシュー、チェックを有効にします。',
+ 'Search GitHub issues...': 'GitHub イシューを検索...',
+ 'file an issue': 'イシューを登録',
+ sending: '送信中',
+ 'Pull requests, issues, and checks via the': 'PR、イシュー、チェックは',
+ 'Pull requests, issues, and check status.': 'PR、イシュー、チェックの状態。',
+ 'Pull requests and build statuses': 'PR とビルドステータス',
+ 'Pull requests and commit statuses for detected repositories':
+ '検出されたリポジトリの PR とコミットステータス',
+ 'Keep at phone size (default)': 'スマートフォンサイズを維持(デフォルト)',
+ // Round 5: inline/launch/action homographs, MR/review status chips, concise prompts.
+ Inline: 'インライン',
+ inline: 'インライン',
+ Launch: '起動',
+ 'Launch:': '起動:',
+ 'Launch plan': '起動プラン',
+ 'Launch agent': 'エージェントを起動',
+ 'Launch {{value0}} in a new terminal': '新規ターミナルで {{value0}} を起動',
+ Play: 'Play',
+ Action: '操作',
+ Actions: '操作',
+ action: '操作',
+ 'More actions': 'その他の操作',
+ 'Quick Actions': 'クイック操作',
+ 'Actions & Settings': '操作と設定',
+ 'More PR actions': 'その他の PR 操作',
+ 'More PR workspace actions': 'PR ワークスペースのその他の操作',
+ 'More issue workspace actions': 'イシューワークスペースのその他の操作',
+ 'More {{value0}} actions': 'その他の {{value0}} 操作',
+ 'More Explorer Actions': 'エクスプローラーのその他の操作',
+ 'More comment actions': 'その他のコメント操作',
+ 'More note actions': 'その他のメモ操作',
+ 'More commit and remote actions': 'コミットおよびリモート操作',
+ 'More {{value0}} and remote actions': 'その他の {{value0}} とリモート操作',
+ 'Pane Actions': 'ペインの操作',
+ 'Project actions': 'プロジェクトの操作',
+ 'Project actions for {{value0}}': '{{value0}} のプロジェクト操作',
+ 'Group actions for {{value0}}': '{{value0}} のグループ操作',
+ 'Action recipes': '操作レシピ',
+ 'merge request': 'MR',
+ MergeRequest: 'MR',
+ 'Reviewed by': 'レビュアー',
+ 'MR title is required.': 'MR タイトルは必須です。',
+ 'Conductor Progress': 'Conductor 進捗',
+ 'Conductor Review': 'Conductor レビュー',
+ 'Conductor Done': 'Conductor 完了',
+ Blocked: 'ブロック中',
+ 'Needs review': 'レビュー待ち',
+ 'font features': 'フォント特性',
+ 'Merge requests, issues, todos, and pipelines via the': 'MR、イシュー、ToDo、パイプラインは',
+ 'Install the GitLab CLI to enable merge requests, issues, and pipelines.':
+ 'GitLab CLI をインストールして MR、イシュー、パイプラインを有効にします。',
+ 'This merge request is still a draft': 'この MR はまだ下書きです',
+ 'This merge request is closed': 'この MR はクローズされています',
+ 'This merge request is already merged': 'この MR はすでにマージされています',
+ 'Add a project first': 'まずプロジェクトを追加',
+ 'Pick a base branch below': '以下のベースブランチを選択',
+ 'Choose floating workspace directory': 'フローティング ワークスペース ディレクトリを選択',
+ 'Enter passphrase': 'パスフレーズを入力',
+ 'Enter password': 'パスワードを入力',
+ 'Enter the passphrase for': 'のパスフレーズを入力',
+ 'Enter the password for': 'のパスワードを入力',
+ 'Choose a view': 'ビューを選択',
+ 'Select one project to open in GitHub': 'GitHub で開くプロジェクトを 1 つ選択',
+ 'Select one GitHub project to open in GitHub': 'GitHub で開く GitHub プロジェクトを 1 つ選択',
+ 'Select one Linear team to open in Linear': 'Linear で開く Linear チームを 1 つ選択',
+ 'Select a workspace to view checks': 'チェックを表示するワークスペースを選択',
+ 'Select a workspace to browse files': 'ファイルを参照するワークスペースを選択',
+ 'Select a workspace to search': '検索するワークスペースを選択',
+ 'Select a workspace to view changes': '変更を表示するワークスペースを選択',
+ 'Choose agent to fix commit failure': 'コミット失敗を修正するエージェントを選択',
+ 'Choose an agent for this commit failure': 'このコミット失敗に対するエージェントを選択',
+ 'Enter a commit message to commit': 'コミットメッセージを入力してコミット',
+ 'Choose parent folder...': '親フォルダーを選択...',
+ 'Check for stuck work, stale generated files, failing validation, and anything that needs human attention. Report only actionable issues.':
+ 'スタックした作業、古い生成ファイル、検証の失敗、および人間の対応が必要なものがないか確認してください。対応が必要なイシューのみを報告してください。'
+}
diff --git a/config/scripts/locale-key-overrides.mjs b/config/scripts/locale-key-overrides.mjs
new file mode 100644
index 00000000000..eeb60e93039
--- /dev/null
+++ b/config/scripts/locale-key-overrides.mjs
@@ -0,0 +1,594 @@
+import { KO_KEY_OVERRIDES } from './locale-ko-key-overrides.mjs'
+
+// Key-specific overrides from high-visibility UI audit (P0/P1/P2).
+// Why: some fixes depend on full key context, not English value alone.
+export const LOCALE_KEY_OVERRIDES = {
+ 'menu.reportCrash': { ko: '크래시 신고...', zh: '报告崩溃...', ja: 'クラッシュを報告...' },
+ 'menu.showMobileButton': {
+ ko: 'Orca 모바일 버튼 표시',
+ zh: '显示 Orca Mobile 按钮',
+ ja: 'Orca モバイル ボタンを表示'
+ },
+ 'menu.toggleLeftSidebar': {
+ ko: '왼쪽 사이드바 표시/숨기기',
+ zh: '显示/隐藏左侧边栏',
+ ja: '左サイドバーの表示/非表示'
+ },
+ 'menu.toggleRightSidebar': {
+ ko: '오른쪽 사이드바 표시/숨기기',
+ zh: '显示/隐藏右侧边栏',
+ ja: '右サイドバーの表示/非表示'
+ },
+ 'menu.openWorktreePalette': {
+ ko: '워크트리 팔레트 열기',
+ zh: '打开工作树面板',
+ ja: 'ワークツリーパレットを開く'
+ },
+ 'menu.exploreOrca': { ko: 'Orca 둘러보기', zh: '探索 Orca', ja: 'Orca を探索' },
+ 'worktreeJumpPalette.matchLabel.issue': { ko: '이슈', zh: '议题', ja: 'イシュー' },
+ 'worktreeJumpPalette.matchLabel.comment': { ko: '댓글', zh: '评论', ja: 'コメント' },
+ 'auto.hooks.useSettingsNavigationMetadata.13241992bd': {
+ ko: '일반',
+ zh: '通用',
+ ja: '一般'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.93d88d20bf': {
+ ko: '외관',
+ zh: '外观',
+ ja: '外観'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.1cd25673df': {
+ ko: '모바일',
+ zh: '移动端',
+ ja: 'モバイル'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.6a50cdcd7c': {
+ ko: '음성',
+ zh: '语音',
+ ja: '音声'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.580a04cd81': {
+ ko: '고급',
+ zh: '高级',
+ ja: '詳細設定'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.225071c560': {
+ ko: '실험적',
+ zh: '实验性',
+ ja: '実験的機能'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.b35e92364b': {
+ ko: '컴퓨터 사용',
+ zh: '计算机控制',
+ ja: 'コンピュータ操作'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.94295ebfb3': {
+ ko: '단축키',
+ zh: '快捷键',
+ ja: 'ショートカット'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.ded9e9032f': {
+ ko: '온보딩 체크리스트',
+ zh: '入门清单',
+ ja: 'オンボーディングチェックリスト'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.3618579df6': {
+ ko: '개인정보 및 텔레메트리',
+ zh: '隐私与遥测',
+ ja: 'プライバシーとテレメトリ'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.65b19f5bde': {
+ ko: '플로팅 워크스페이스',
+ zh: '浮动工作区',
+ ja: 'フローティングワークスペース'
+ },
+ 'auto.hooks.useSettingsNavigationMetadata.2b043783ef': {
+ ko: '연동',
+ zh: '集成',
+ ja: '連携'
+ },
+ 'auto.components.settings.Settings.9abb9be3bc': {
+ ko: '설정 시작',
+ zh: '初始设置',
+ ja: 'セットアップ'
+ },
+ 'auto.components.settings.SettingsSidebar.dbceaa8840': {
+ ko: '설정 검색',
+ zh: '搜索设置',
+ ja: '設定を検索'
+ },
+ 'auto.components.settings.SettingsSidebar.60f8a673a7': {
+ ko: '앱으로 돌아가기',
+ zh: '返回应用',
+ ja: 'アプリに戻る'
+ },
+ 'auto.components.settings.SettingsSidebar.82db1b7de4': {
+ ko: '온보딩 체크리스트, {{value0}}/{{value1}} 완료. 설정 가이드 보기.',
+ zh: '入门清单,已完成 {{value0}}/{{value1}}。显示设置指南。',
+ ja: 'オンボーディングチェックリスト、{{value0}}/{{value1}} 完了。セットアップガイドを表示。'
+ },
+ 'auto.components.settings.ShortcutFilterRail.02dc7d4251': {
+ ko: '바로가기 검색',
+ zh: '搜索快捷键',
+ ja: 'ショートカットを検索'
+ },
+ 'auto.components.settings.ShortcutBindingRow.6a7848fdac': {
+ ko: '단축키 입력 대기 중',
+ zh: '正在录制快捷键',
+ ja: 'ショートカットを記録中'
+ },
+ 'auto.components.FirstLaunchBanner.fc5cc29955': {
+ ko: '거부',
+ zh: '退出',
+ ja: 'オプトアウト'
+ },
+ 'auto.components.FirstLaunchBanner.94cc673726': {
+ ko: '확인',
+ zh: '知道了',
+ ja: '了解'
+ },
+ 'auto.components.GitHubItemDialog.55962099bc': {
+ ko: '이 이슈를 열었습니다',
+ zh: '创建了此议题',
+ ja: 'このイシューを作成しました'
+ },
+ 'auto.components.GitHubItemDialog.726db41722': {
+ ko: '워크스페이스 열기',
+ zh: '打开工作区',
+ ja: 'ワークスペースを開く'
+ },
+ 'auto.components.GitHubItemDialog.a459866967': {
+ ko: 'PR에 연결된 워크스페이스 재개',
+ zh: '恢复关联 PR 的工作区',
+ ja: 'PR に紐づくワークスペースを再開'
+ },
+ 'auto.components.PullRequestItemDialog.67d881244c': {
+ ko: 'PR에 연결된 워크스페이스 재개',
+ zh: '恢复关联 PR 的工作区',
+ ja: 'PR に紐づくワークスペースを再開'
+ },
+ 'auto.components.GitHubItemDialog.ab050dffec': {
+ ko: '닫힘',
+ zh: '已关闭',
+ ja: 'クローズ'
+ },
+ 'auto.components.GitHubItemDialog.dc1ca081a8': {
+ ko: '진행 중',
+ zh: '进行中',
+ ja: 'オープン'
+ },
+ 'auto.components.tab.bar.TabBarCreateEntry.b27864279e': {
+ ko: '에이전트 실행',
+ zh: '启动代理',
+ ja: 'エージェントを起動'
+ },
+ 'auto.components.sidebar.SidebarNav.c39ab10000': {
+ ko: 'Linear 작업 열기',
+ zh: '打开 Linear 任务',
+ ja: 'Linear タスクを開く'
+ },
+ 'auto.components.sidebar.SidebarNav.c86d83b5c3': {
+ ko: '새로 만들기',
+ zh: '新建',
+ ja: '新規'
+ },
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.eb9884e55b': {
+ ko: 'Discord',
+ zh: 'Discord',
+ ja: 'Discord'
+ },
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.ad3d3ed7f1': {
+ ko: 'Orca 재시작',
+ zh: '重启 Orca',
+ ja: 'Orca を再起動'
+ },
+ 'auto.components.sidebar.workspace.status.5f9ca31a84': {
+ ko: '대기 중',
+ zh: '等待中',
+ ja: '待機中'
+ },
+ 'auto.components.sidebar.SidebarWorkspaceFilterSection.ed1611b65b': {
+ ko: '슬립 중인 항목 숨기기',
+ zh: '隐藏休眠项',
+ ja: 'スリープ中を非表示'
+ },
+ 'auto.components.status.bar.ResourceUsageStatusSegment.4bb076fa89': {
+ ko: '강제 종료',
+ zh: '强制结束',
+ ja: '強制終了'
+ },
+ 'auto.components.status.bar.ResourceUsageStatusSegment.41ae4fa725': {
+ ko: '종료 중…',
+ zh: '正在结束…',
+ ja: '終了中…'
+ },
+ 'auto.components.status.bar.ResourceUsageStatusSegment.53dd5560ae': {
+ ko: 'Orca 접기',
+ zh: '折叠 Orca',
+ ja: 'Orca を折りたたむ'
+ },
+ 'auto.components.settings.ManageSessionsSection.a06ababda0': {
+ ko: '모두 강제 종료',
+ zh: '全部强制结束',
+ ja: 'すべて強制終了'
+ },
+ 'auto.components.settings.ManageSessionKillDialog.d3dba51b15': {
+ ko: '종료 중…',
+ zh: '正在结束…',
+ ja: '終了中…'
+ },
+ 'auto.components.settings.terminal.search.920573d65b': {
+ ko: '모두 종료',
+ zh: '全部结束',
+ ja: 'すべて終了'
+ },
+ 'auto.components.settings.AgentsPane.2e45ca29b6': {
+ ko: '명령',
+ zh: '命令',
+ ja: 'コマンド'
+ },
+ 'auto.components.settings.AgentsPane.1c9a9679ec': {
+ ko: '{{value0}} 사용 가능 여부',
+ zh: '{{value0}} 可用性',
+ ja: '{{value0}} の利用可否'
+ },
+ 'auto.components.settings.AgentsPane.ed3e110e61': {
+ ko: '감지됨',
+ zh: '已检测',
+ ja: '検出済み'
+ },
+ 'auto.components.settings.AgentsPane.e8da2af684': {
+ ko: '설치 가능',
+ zh: '可安装',
+ ja: 'インストール可能'
+ },
+ 'auto.components.settings.AppearancePane.7d26ccabe8': {
+ ko: '다크',
+ zh: '深色',
+ ja: 'ダーク'
+ },
+ 'auto.components.settings.BrowserUsePane.de9b2f32f3': {
+ ko: '활성화',
+ zh: '启用',
+ ja: '有効化'
+ },
+ 'auto.components.settings.GeneralSupportSection.73b327e793': {
+ ko: '다시 시도',
+ zh: '重试',
+ ja: '再試行'
+ },
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.2801d4ce22': {
+ ko: '티켓 복사',
+ zh: '复制工单',
+ ja: 'チケットをコピー'
+ },
+ 'auto.components.settings.ComputerUsePane.4b65070096': {
+ ko: 'darwin',
+ zh: 'darwin',
+ ja: 'darwin'
+ },
+ 'auto.components.settings.ComputerUsePane.bf51e4a542': {
+ ko: 'USB 장치',
+ zh: 'USB 设备',
+ ja: 'USB デバイス'
+ },
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.ffe13e36fb': {
+ ko: '누락',
+ zh: '缺失',
+ ja: '不足'
+ },
+ 'auto.components.settings.GitPane.eec3995dc6': {
+ ko: 'Git AI Author',
+ zh: 'Git AI Author',
+ ja: 'Git AI Author'
+ },
+ 'auto.components.settings.AutoRenameBranchFromWorkSetting.1626524572': {
+ ko: 'Nautilus',
+ zh: 'Nautilus',
+ ja: 'Nautilus'
+ },
+ 'auto.components.settings.Settings.8bd117d669': {
+ ko: '인터페이스',
+ zh: '界面',
+ ja: 'インターフェース'
+ },
+ 'auto.components.settings.SettingsThemePicker.9119fb2268': {
+ ko: '현재',
+ zh: '当前',
+ ja: '現在'
+ },
+ 'auto.components.settings.SettingsThemePicker.4e11f87ca6': {
+ ko: '표시 중',
+ zh: '显示中',
+ ja: '表示中'
+ },
+ 'auto.components.skills.SkillsPage.a68dee6a32': {
+ ko: '스킬 검색',
+ zh: '搜索技能',
+ ja: 'スキルを検索'
+ },
+ 'auto.components.editor.RichMarkdownSlashMenu.550189b06c': {
+ ko: '블록 검색',
+ zh: '搜索块',
+ ja: 'ブロックを検索'
+ },
+ 'auto.components.TaskPage.eec0c5c079': {
+ ko: 'Linear 이슈 검색...',
+ zh: '搜索 Linear 议题...',
+ ja: 'Linear イシューを検索...'
+ },
+ 'auto.web.WebConnect.e3bcd082ac': {
+ ko: 'Orca에 연결',
+ zh: '连接到 Orca',
+ ja: 'Orca に接続'
+ },
+ 'auto.App.caea5b51b9': {
+ ko: '지금 재시작',
+ zh: '立即重启',
+ ja: '今すぐ再起動'
+ },
+ 'auto.App.9f0152563e': { ko: '모바일', zh: '移动端', ja: 'モバイル' },
+ 'auto.App.ca6c6eece7': { ko: '스킬', zh: '技能', ja: 'スキル' },
+ 'auto.App.62ca9895a7': { ko: '스페이스', zh: '空间', ja: 'スペース' },
+ 'settings.appearance.statusBar.kimiToggleDescription': {
+ ko: '활성 워크스페이스의 Kimi 구독 사용량을 표시합니다.',
+ zh: 'Kimi 订阅',
+ ja: 'Kimi サブスクリプション'
+ },
+ 'auto.components.mobile.MobileHero.cd4e5e816f': {
+ ko: '주머니 속의 워크스페이스.',
+ zh: '您的工作区就在您的口袋里。',
+ ja: 'ワークスペースをポケットに。'
+ },
+ 'auto.components.GitHubItemDialog.dbe5e2448e': {
+ ko: 'PR이 병합되었습니다',
+ zh: '拉取请求已合并',
+ ja: 'PR がマージされました'
+ },
+ 'auto.components.PullRequestPage.c57873d721': {
+ ko: 'PR이 병합되었습니다',
+ zh: '拉取请求已合并',
+ ja: 'PR がマージされました'
+ },
+ 'auto.components.TaskPage.a161925adc': {
+ ko: 'PR이 병합되었습니다',
+ zh: '拉取请求已合并',
+ ja: 'PR がマージされました'
+ },
+ 'auto.components.JiraIssueWorkspace.857bd2f88f': {
+ ko: '선택한 이슈를 미리보기하고, 편집하고, 작업을 시작하세요.',
+ zh: '预览、编辑并从选定的议题开始工作。',
+ ja: '選択したイシューをプレビュー・編集し、そこから作業を開始します。'
+ },
+ 'auto.components.LinearIssueWorkspace.ad5dec37b7': {
+ ko: '선택한 이슈를 미리보기하고, 편집하고, 작업을 시작하세요.',
+ zh: '预览、编辑并从选定的议题开始工作。',
+ ja: '選択したイシューをプレビュー・編集し、そこから作業を開始します。'
+ },
+ 'auto.components.TaskPage.67662ade50': {
+ ko: '프로젝트 이슈',
+ zh: '项目议题',
+ ja: 'プロジェクトのイシュー'
+ },
+ 'auto.components.TaskPage.618107fab3': {
+ ko: '선택한 팀과 일치하는 가져온 이슈가 없습니다',
+ zh: '没有获取到与所选团队匹配的议题',
+ ja: '選択したチームと一致する取得済みイシューはありません'
+ },
+ 'auto.components.TaskPage.1e1b2ad8f2': {
+ ko: '이 이슈를 등록하기 전에 프로젝트 워크스페이스에서 팀을 선택하세요.',
+ zh: '在提交此议题之前,请从项目工作区选择一个团队。',
+ ja: 'このイシューを登録する前に、プロジェクトワークスペースからチームを選択してください。'
+ },
+ 'auto.components.TaskPage.d079be2dc8': {
+ ko: '할당된 이슈가 없습니다. 검색해 보세요.',
+ zh: '没有分配的议题。请尝试搜索。',
+ ja: '割り当てられたイシューはありません。検索してみてください。'
+ },
+ 'auto.components.TaskPage.94d900518d': {
+ ko: '선택한 프리셋과 일치하는 이슈가 없습니다.',
+ zh: '没有与所选预设匹配的议题。',
+ ja: '選択したプリセットに一致するイシューはありません。'
+ },
+ 'auto.components.github.project.ProjectCell.ffeff79861': {
+ ko: 'PULL_REQUEST',
+ zh: 'PULL_REQUEST',
+ ja: 'PULL_REQUEST'
+ },
+ 'auto.components.github.project.ProjectRow.c3b81ddea2': {
+ ko: 'DRAFT_ISSUE',
+ zh: 'DRAFT_ISSUE',
+ ja: 'DRAFT_ISSUE'
+ },
+ 'auto.components.linear.project.view.surfaces.3ad562bdf4': {
+ ko: '범위가 지정된 이슈',
+ zh: '范围议题',
+ ja: 'スコープされたイシュー'
+ },
+ 'auto.components.linear.project.view.surfaces.7616c986c6': {
+ ko: '{{value0}} 이슈 열기',
+ zh: '打开 {{value0}} 议题',
+ ja: '{{value0}} イシューを開く'
+ },
+ 'auto.components.sidebar.SidebarFeedbackDialog.d245c4ef6c': {
+ ko: 'GitHub 이슈',
+ zh: 'GitHub 议题',
+ ja: 'GitHub イシュー'
+ },
+ 'auto.components.settings.CommitMessageAiPane.4f722a5f53': {
+ ko: '사용자 지정 명령을 선택하는 커밋 메시지, PR 및 브랜치 이름 레시피에서 사용됩니다. 사용',
+ zh: '由选择自定义命令的提交消息、拉取请求和分支名称配方使用。使用',
+ ja: 'カスタムコマンドを選択するコミットメッセージ、PR、ブランチ名のレシピで使用されます。使用'
+ },
+ 'auto.components.settings.AgentsPane.9bccf48906': {
+ ko: '에이전트 위치',
+ zh: '代理位置',
+ ja: 'エージェントの場所'
+ },
+ 'auto.components.skills.SkillsPage.38e0951c3a': {
+ ko: '에이전트 스킬',
+ zh: '代理技能',
+ ja: 'エージェントのスキル'
+ },
+ 'auto.components.sidebar.SidebarNav.e518f544b1': {
+ ko: '감지된 에이전트 없음',
+ zh: '未检测到代理',
+ ja: 'エージェントが検出されません'
+ },
+ 'auto.components.onboarding.OnboardingFlow.04ae28d8ca': {
+ ko: '몇 시간 내내 보고 싶은 테마를 선택하세요.',
+ zh: '选择你想盯着看几个小时的主题。',
+ ja: '何時間も眺めていたくなるテーマを選んでください。'
+ },
+ 'auto.components.GitLabItemDialog.e089f62594': {
+ ko: 'MR !{{value0}}을(를) 병합했습니다.',
+ zh: '合并 MR !{{value0}}',
+ ja: 'MR をマージしました !{{value0}}'
+ },
+ 'auto.components.right.sidebar.source.control.primary.action.3d5dccef0b': {
+ ko: '커밋할 것이 없습니다. PR은 이미 병합되었습니다.',
+ zh: '没有可提交的内容。PR 已合并。',
+ ja: 'コミットするものはありません。PR はすでにマージされています。'
+ },
+ 'auto.components.settings.integrations.search.16a486a49d': {
+ ko: 'Linear에 연결해 이슈를 탐색하고 연결합니다.',
+ zh: '连接 Linear 以浏览和链接议题。',
+ ja: 'Linear に接続してイシューを参照し、リンクします。'
+ },
+ 'menu.showTitlebarAppName': {
+ ko: '제목 표시줄 앱 이름 표시',
+ zh: '显示标题栏应用名称',
+ ja: 'タイトルバーのアプリ名を表示'
+ },
+ 'auto.App.e81217c1b7': {
+ ko: '앱 이름 숨기기',
+ zh: '隐藏应用名称',
+ ja: 'アプリ名を非表示'
+ },
+ 'auto.components.settings.ExperimentalPane.0277901cf7': {
+ ko: '완료된 에이전트, 차단 질문, 읽지 않은 상태 및 작업 트리 생성 이벤트에 대한 스레드 작업 트리 피드가 있는 에이전트 항목을 왼쪽 사이드바에 추가합니다. 실험적 — 이벤트 모델과 UI가 변경될 수 있습니다.',
+ zh: '将代理条目添加到左侧边栏,其中包含已完成代理、阻塞待办、未读状态和工作树创建事件的线程工作树提要。实验性——事件模型和 UI 可能会改变。',
+ ja: '完了したエージェント、ブロック中の質問、未読状態、ワークツリー作成イベントのスレッドワークツリーフィード付きエージェント項目を左サイドバーに追加します。実験的 — イベントモデルと UI は変更される場合があります。'
+ },
+ 'auto.lib.fix.checks.agent.launch.9f00d7df0c': {
+ ko: '검사 프롬프트가 비어 있습니다. 소스 제어 AI 설정을 업데이트하세요.',
+ zh: '检查提示为空。请更新源代码管理 AI 设置。',
+ ja: 'チェック プロンプトが空です。ソース管理 AI 設定を更新してください。'
+ },
+ 'auto.components.TaskPage.d0e3c8f933': {
+ ko: '일치하는 GitHub 작업이 없습니다',
+ zh: '没有匹配的 GitHub 工作项',
+ ja: '一致する GitHub 作業がありません'
+ },
+ 'auto.components.TaskPage.2af3ab5c58': {
+ ko: 'Linear에서 열 팀을 하나 선택하세요',
+ zh: '选择一个团队在 Linear 中打开',
+ ja: 'Linear で開くチームを 1 つ選択'
+ },
+ 'auto.components.TaskPage.8964184a8b': {
+ ko: 'Linear 새로고침',
+ zh: '刷新 Linear',
+ ja: 'Linear を更新'
+ },
+ 'auto.components.TaskPage.6775c05483': {
+ ko: 'Linear 상태를 업데이트할 수 없습니다',
+ zh: '无法更新 Linear 状态',
+ ja: 'Linear の状態を更新できません'
+ },
+ 'auto.components.TaskPage.25ff84769a': {
+ ko: '이 Linear 컨텍스트와 일치하는 이슈가 없습니다.',
+ zh: '没有议题与此 Linear 上下文匹配。',
+ ja: 'この Linear コンテキストに一致するイシューはありません。'
+ },
+ 'auto.components.settings.IntegrationsPane.33ae9730a8': {
+ ko: 'Linear 액세스를 추가해 이슈를 탐색하고 연결합니다.',
+ zh: '添加 Linear 访问以浏览和链接议题。',
+ ja: 'Linear アクセスを追加してイシューを参照し、リンクします。'
+ },
+ 'auto.components.GitHubItemDialog.3ab6ac0fc8': {
+ ko: '선택한 GitHub 이슈 또는 PR을 미리보기하고 편집합니다.',
+ zh: '预览并编辑选定的 GitHub 议题或拉取请求。',
+ ja: '選択した GitHub イシューまたは PR をプレビュー・編集します。'
+ },
+ 'auto.components.GitHubItemDialog.8c45901789': {
+ ko: '리뷰어 요청 {{value0}}',
+ zh: '请求评审人 {{value0}}',
+ ja: 'レビュアーをリクエスト {{value0}}'
+ },
+ 'auto.components.GitHubItemDialog.fedc09eeb9': {
+ ko: '리뷰 요청 취소 {{value0}}',
+ zh: '取消请求评审人 {{value0}}',
+ ja: 'レビュアーのリクエストを取り消す {{value0}}'
+ },
+ 'auto.components.TaskPage.be8cf68d9f': {
+ ko: '이슈 보기',
+ zh: '查看议题',
+ ja: 'イシューを表示'
+ },
+ 'auto.components.mobile.MobilePage.e17393c6a3': {
+ ko: '전화 미리보기',
+ zh: '手机预览',
+ ja: 'スマートフォンプレビュー'
+ },
+ 'auto.components.editor.EditorContent.e4b074749d': {
+ ko: '머리말',
+ zh: '前线事项',
+ ja: 'フロントマター'
+ },
+ 'auto.components.editor.MarkdownPreview.2b2b31382c': {
+ ko: '머리말',
+ zh: '前线事项',
+ ja: 'フロントマター'
+ },
+ 'auto.components.settings.IntegrationsPane.c0c8575e05': {
+ ko: 'PR, 이슈 및 검사를 활성화하려면 GitHub CLI를 설치하세요.',
+ zh: '安装 GitHub CLI 以启用拉取请求、议题和检查。',
+ ja: 'GitHub CLI をインストールして PR、イシュー、チェックを有効にします。'
+ },
+ 'auto.components.dashboard.DashboardAgentRow.92a7017987': {
+ ko: '전송 중',
+ zh: '发送',
+ ja: '送信中'
+ },
+ 'auto.components.github.pr.merge.state.bf5e4c6c92': {
+ ko: '차단됨',
+ zh: '已阻塞',
+ ja: 'ブロック中'
+ },
+ 'auto.components.sidebar.workspace.status.93ac840dcb': {
+ ko: '차단됨',
+ zh: '已阻塞',
+ ja: 'ブロック中'
+ },
+ 'auto.components.sidebar.workspace.status.6c1efa2cf8': {
+ ko: '검토 중',
+ zh: '评审中',
+ ja: 'レビュー中'
+ },
+ 'auto.components.sidebar.workspace.status.409528031f': {
+ ko: '검토',
+ zh: '评审',
+ ja: 'レビュー'
+ },
+ 'auto.components.UpdateCard.actionBadge': {
+ ko: '작업',
+ zh: '操作',
+ ja: '操作'
+ },
+ 'auto.components.settings.GitPane.b559bf9899': {
+ ko: '예: feature',
+ zh: '例如 feature',
+ ja: '例: feature'
+ },
+ 'auto.components.mobile.slides.TerminalSlide.985373052e': {
+ ko: '휴대폰 모드로 전환',
+ zh: '切换到手机模式',
+ ja: 'スマートフォンモードに切り替え'
+ },
+ 'auto.components.GitHubItemDialog.a341343303': {
+ ko: '리뷰 댓글이 추가되었습니다.',
+ zh: '已添加评审评论。',
+ ja: 'レビューコメントを追加しました。'
+ },
+ ...KO_KEY_OVERRIDES
+}
diff --git a/config/scripts/locale-ko-key-overrides.mjs b/config/scripts/locale-ko-key-overrides.mjs
new file mode 100644
index 00000000000..579f4c128e1
--- /dev/null
+++ b/config/scripts/locale-ko-key-overrides.mjs
@@ -0,0 +1,158 @@
+// Korean key overrides from high-visibility UI audit round 4.
+export const KO_KEY_OVERRIDES = {
+ 'auto.hooks.useSettingsNavigationMetadata.40d80bad8a': {
+ ko: '베타',
+ zh: '测试版',
+ ja: 'ベータ'
+ },
+ 'auto.components.settings.integrations.search.c450244ad7': {
+ ko: '연동',
+ zh: '集成',
+ ja: '連携'
+ },
+ 'auto.components.settings.integrations.search.e1263dd748': {
+ ko: 'Jira',
+ zh: 'Jira',
+ ja: 'Jira'
+ },
+ 'auto.components.settings.integrations.search.581844769a': {
+ ko: 'MR',
+ zh: 'MR',
+ ja: 'MR'
+ },
+ 'auto.components.settings.integrations.search.129fc59aa8': {
+ ko: 'Gitea',
+ zh: 'Gitea',
+ ja: 'Gitea'
+ },
+ 'auto.components.settings.integrations.search.03a7b275be': {
+ ko: 'ADO',
+ zh: 'ADO',
+ ja: 'ADO'
+ },
+ 'auto.components.settings.integrations.search.f16e41cc72': {
+ ko: 'GitHub 연동',
+ zh: 'GitHub 集成',
+ ja: 'GitHub 連携'
+ },
+ 'auto.components.settings.integrations.search.b50b71ef9d': {
+ ko: 'GitLab 연동',
+ zh: 'GitLab 集成',
+ ja: 'GitLab 連携'
+ },
+ 'auto.components.settings.integrations.search.aab86d64e5': {
+ ko: 'Gitea 연동',
+ zh: 'Gitea 集成',
+ ja: 'Gitea 連携'
+ },
+ 'auto.components.settings.integrations.search.617603509b': {
+ ko: 'Jira 연동',
+ zh: 'Jira 集成',
+ ja: 'Jira 連携'
+ },
+ 'auto.components.settings.integrations.search.af6611fa6e': {
+ ko: 'Azure DevOps 연동',
+ zh: 'Azure DevOps 集成',
+ ja: 'Azure DevOps 連携'
+ },
+ 'auto.components.settings.integrations.search.67a2a0e868': {
+ ko: 'Bitbucket 연동',
+ zh: 'Bitbucket 集成',
+ ja: 'Bitbucket 連携'
+ },
+ 'auto.components.settings.integrations.search.b027b4b318': {
+ ko: 'Linear 연동',
+ zh: 'Linear 集成',
+ ja: 'Linear 連携'
+ },
+ 'auto.components.settings.integrations.search.b79c21bd42': {
+ ko: 'GitHub',
+ zh: 'GitHub',
+ ja: 'GitHub'
+ },
+ 'auto.components.settings.integrations.search.b40cbe5de4': {
+ ko: 'glab',
+ zh: 'glab',
+ ja: 'glab'
+ },
+ 'auto.components.settings.integrations.search.20540996ef': {
+ ko: '자격 증명',
+ zh: '凭据',
+ ja: '認証情報'
+ },
+ 'auto.components.skills.SkillsPage.b088e0785d': {
+ ko: '베타',
+ zh: '测试版',
+ ja: 'ベータ'
+ },
+ 'auto.components.workspace.space.WorkspaceSpacePage.e8d6ba11ab': {
+ ko: '베타',
+ zh: '测试版',
+ ja: 'ベータ'
+ },
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.c361440dc0': {
+ ko: '베타',
+ zh: '测试版',
+ ja: 'ベータ'
+ },
+ 'auto.components.github.PRFilterDropdowns.19bb6f115f': {
+ ko: 'reviewed-by',
+ zh: 'reviewed-by',
+ ja: 'reviewed-by'
+ },
+ 'auto.components.TaskPage.9cd11ba218': {
+ ko: 'Jira',
+ zh: 'Jira',
+ ja: 'Jira'
+ },
+ 'auto.components.settings.TasksPane.6b23a34f6d': {
+ ko: 'Jira',
+ zh: 'Jira',
+ ja: 'Jira'
+ },
+ 'auto.components.settings.jira.integration.card.09742875cd': {
+ ko: 'Jira',
+ zh: 'Jira',
+ ja: 'Jira'
+ },
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.1b18868569': {
+ ko: '리뷰 필요',
+ zh: '待评审',
+ ja: 'レビュー待ち'
+ },
+ 'auto.components.onboarding.OnboardingFlow.a5e5da02f7': {
+ ko: '연동',
+ zh: '集成',
+ ja: '連携'
+ },
+ 'auto.components.GitLabItemDialog.4168eb2c51': {
+ ko: '해결',
+ zh: '解决',
+ ja: '解決'
+ },
+ 'auto.components.sidebar.workspace.status.6c1efa2cf8': {
+ ko: '리뷰 중',
+ zh: '评审中',
+ ja: 'レビュー中'
+ },
+ 'auto.components.sidebar.workspace.status.409528031f': {
+ ko: '리뷰',
+ zh: '评审',
+ ja: 'レビュー'
+ },
+ 'auto.components.sidebar.workspace.status.caebe3c10f': {
+ ko: 'Conductor 리뷰',
+ zh: 'Conductor 评审',
+ ja: 'Conductor レビュー'
+ },
+ 'auto.components.sidebar.workspace.list.groups.6798dc7c94': {
+ ko: '리뷰 중',
+ zh: '评审中',
+ ja: 'レビュー中'
+ },
+ 'auto.components.TaskPage.524f095d55': {
+ ko: '리뷰 필요',
+ zh: '待评审',
+ ja: 'レビュー待ち'
+ }
+}
diff --git a/config/scripts/locale-ko-phrase-fixes-round5.mjs b/config/scripts/locale-ko-phrase-fixes-round5.mjs
new file mode 100644
index 00000000000..14412ee20af
--- /dev/null
+++ b/config/scripts/locale-ko-phrase-fixes-round5.mjs
@@ -0,0 +1,60 @@
+// Korean phrase fixes from high-visibility UI audit round 5.
+export const KO_PHRASE_FIXES_ROUND5 = [
+ { pattern: /검토 필요/g, replacement: '리뷰 필요', whenEnIncludes: 'Needs review' },
+ { pattern: /검토 중/g, replacement: '리뷰 중', whenEnIncludes: 'In review' },
+ {
+ pattern: /마크다운 검토 노트/g,
+ replacement: '마크다운 리뷰 노트',
+ whenEnIncludes: 'Markdown Review Notes'
+ },
+ { pattern: /충돌 검토/g, replacement: '충돌 리뷰', whenEnIncludes: 'Review conflicts' },
+ { pattern: /메모 검토/g, replacement: '리뷰 노트', whenEnIncludes: 'Review notes' },
+ { pattern: /검토 스냅샷/g, replacement: '리뷰 스냅샷', whenEnIncludes: 'review snapshot' },
+ { pattern: /검토를 위해/g, replacement: '리뷰를 위해', whenEnIncludes: 'for review' },
+ { pattern: /검토 작업/g, replacement: '리뷰 작업', whenEnIncludes: 'review task' },
+ { pattern: /지휘자 검토/g, replacement: 'Conductor 리뷰', whenEnIncludes: 'Conductor Review' },
+ { pattern: /다시 검토/g, replacement: '재리뷰', whenEnIncludes: 'Re-review' },
+ { pattern: /검토하고/g, replacement: '리뷰하고', whenEnIncludes: 'Review and' },
+ { pattern: /검토합니다/g, replacement: '리뷰합니다', whenEnIncludes: 'Review the' },
+ { pattern: /검토하세요/g, replacement: '리뷰하세요', whenEnIncludes: 'Review recent' },
+ { pattern: /반복 검토/g, replacement: '반복 리뷰', whenEnIncludes: 'Recurring review' },
+ {
+ pattern: /출시 준비 검토/g,
+ replacement: '출시 준비 리뷰',
+ whenEnIncludes: 'Release readiness review'
+ },
+ {
+ pattern: /일일 변화 검토/g,
+ replacement: '일일 변경 리뷰',
+ whenEnIncludes: 'Daily change review'
+ },
+ { pattern: /점검과 검토/g, replacement: '체크 및 리뷰', whenEnIncludes: 'checks and review' },
+ { pattern: /별도로 검토/g, replacement: '별도로 리뷰', whenEnIncludes: 'reviewed separately' },
+ {
+ pattern: /변경 사항을 검토/g,
+ replacement: '변경 사항을 리뷰',
+ whenEnIncludes: 'review changes'
+ },
+ { pattern: /소스\/인증 검토/g, replacement: 'src/auth 리뷰', whenEnIncludes: 'review src/auth' },
+ {
+ pattern: /인증 예외 사례 검토/g,
+ replacement: '인증 예외 사례 리뷰',
+ whenEnIncludes: 'review auth edge cases'
+ },
+ {
+ pattern: /실행 가능한 문제만/g,
+ replacement: '실행 가능한 이슈만',
+ whenEnIncludes: 'actionable issues'
+ },
+ { pattern: /설정 > 통합/g, replacement: '설정 > 연동', whenEnIncludes: 'Integrations' },
+ { pattern: /Orca 기술/g, replacement: 'Orca 스킬', whenEnIncludes: 'Orca skill' },
+ { pattern: /확인하다 #/g, replacement: '체크 #', whenEnIncludes: 'check #' },
+ { pattern: /제출하다\./g, replacement: '제출.', whenEnIncludes: 'to submit.' },
+ { pattern: /추적하다/g, replacement: '추적', whenEnIncludes: 'trace' },
+ { pattern: /시작하다:/g, replacement: '실행:', whenEnIncludes: 'Launch:' },
+ { pattern: /시작하다/g, replacement: '실행', whenEnIncludes: 'Launch' },
+ { pattern: /표시하다/g, replacement: '표시', whenEnIncludes: 'display' },
+ { pattern: /구성하다/g, replacement: '작성', whenEnIncludes: 'compose' },
+ { pattern: /유지하다/g, replacement: '유지', whenEnIncludes: 'Keep' },
+ { pattern: /확인하다/g, replacement: '검증', whenEnIncludes: 'verify' }
+]
diff --git a/config/scripts/locale-ko-phrase-fixes.mjs b/config/scripts/locale-ko-phrase-fixes.mjs
new file mode 100644
index 00000000000..621da9689d1
--- /dev/null
+++ b/config/scripts/locale-ko-phrase-fixes.mjs
@@ -0,0 +1,71 @@
+import { KO_PHRASE_FIXES_ROUND5 } from './locale-ko-phrase-fixes-round5.mjs'
+
+// Korean phrase fixes from high-visibility UI audit round 4.
+export const KO_PHRASE_FIXES_ROUND4 = [
+ { pattern: /일반적인/g, replacement: '일반', whenEnIncludes: 'common' },
+ { pattern: /검토자/g, replacement: '리뷰어', whenEnIncludes: 'Reviewer' },
+ {
+ pattern: /검토자 친화적/g,
+ replacement: '리뷰어 친화적',
+ whenEnIncludes: 'reviewer-friendly'
+ },
+ { pattern: /호스팅 검토/g, replacement: '호스팅 PR', whenEnIncludes: 'hosted review' },
+ { pattern: /호스팅된 검토/g, replacement: '호스팅 PR', whenEnIncludes: 'hosted review' },
+ { pattern: /Git AI 작성자/g, replacement: 'Git AI Author', whenEnIncludes: 'Git AI Author' },
+ { pattern: /지테아/g, replacement: 'Gitea', whenEnIncludes: 'Gitea' },
+ { pattern: /기테아/g, replacement: 'Gitea', whenEnIncludes: 'gitea' },
+ {
+ pattern: /보고된 확인이/g,
+ replacement: '보고된 체크가',
+ whenEnIncludes: 'reported checks'
+ },
+ { pattern: /보고된 확인/g, replacement: '보고된 체크', whenEnIncludes: 'reported checks' },
+ { pattern: /에이전트 기술/g, replacement: '에이전트 스킬', whenEnIncludes: 'agent skill' },
+ { pattern: /오케스트레이션 기술/g, replacement: '오케스트레이션 스킬', whenEnIncludes: 'skill' },
+ { pattern: /컴퓨터 사용 기술/g, replacement: 'Computer Use 스킬', whenEnIncludes: 'skill' },
+ { pattern: /브라우저 사용 기술/g, replacement: 'Browser Use 스킬', whenEnIncludes: 'skill' },
+ { pattern: /Orca CLI 기술/g, replacement: 'Orca CLI 스킬', whenEnIncludes: 'skill' },
+ { pattern: /CLI 및 기술/g, replacement: 'CLI 및 스킬', whenEnIncludes: 'skill' },
+ { pattern: /로컬 기술/g, replacement: '로컬 스킬', whenEnIncludes: 'skill' },
+ { pattern: /스캐닝 기술/g, replacement: '스킬 스캔 중', whenEnIncludes: 'Scanning skills' },
+ { pattern: /맹세하다/g, replacement: 'OAuth', whenEnIncludes: 'oauth' },
+ { pattern: /해결하다/g, replacement: '해결', whenEnIncludes: 'Resolve' },
+ { pattern: /회신하다/g, replacement: '회신', whenEnIncludes: 'Reply' },
+ { pattern: /답장하다/g, replacement: '답장', whenEnIncludes: 'Reply' },
+ { pattern: /관리하다/g, replacement: '관리', whenEnIncludes: 'Manage' },
+ { pattern: /인용하다/g, replacement: '인용', whenEnIncludes: 'Quote' },
+ { pattern: /저장하다/g, replacement: '저장', whenEnIncludes: 'Save' },
+ { pattern: /확인하다/g, replacement: '확인', whenEnIncludes: 'Confirm' },
+ { pattern: /이동하다/g, replacement: '이동', whenEnIncludes: 'Move' },
+ { pattern: /입력하다/g, replacement: '입력', whenEnIncludes: 'Enter' },
+ { pattern: /재개하다/g, replacement: '재개', whenEnIncludes: 'Resume' },
+ { pattern: /등록하다/g, replacement: '등록', whenEnIncludes: 'Register' },
+ { pattern: /생성하다/g, replacement: '생성', whenEnIncludes: 'Create' },
+ { pattern: /다시 시작하다/g, replacement: '다시 시작', whenEnIncludes: 'Restart' },
+ { pattern: /차단하다/g, replacement: '차단', whenEnIncludes: 'Block' },
+ { pattern: /복제하다/g, replacement: '복제', whenEnIncludes: 'Duplicate' },
+ { pattern: /복원하다/g, replacement: '복원', whenEnIncludes: 'Restore' },
+ { pattern: /구성하다/g, replacement: '구성', whenEnIncludes: 'Configure' },
+ { pattern: /집중하다/g, replacement: '집중', whenEnIncludes: 'Focus' },
+ { pattern: /시작하다/g, replacement: '시작', whenEnIncludes: 'Start' },
+ { pattern: /일하다/g, replacement: '작업', whenEnIncludes: 'Work' },
+ { pattern: /표시하다/g, replacement: '표시', whenEnIncludes: 'Show' },
+ { pattern: /통과하다/g, replacement: '통과', whenEnIncludes: 'Pass' },
+ { pattern: /유지하다/g, replacement: '유지', whenEnIncludes: 'Maintain' },
+ { pattern: /승인하다/g, replacement: '승인', whenEnIncludes: 'Approve' },
+ { pattern: /지원하다/g, replacement: '지원', whenEnIncludes: 'Support' },
+ { pattern: /추적하다/g, replacement: '추적', whenEnIncludes: 'Track' },
+ { pattern: /공유하다/g, replacement: '공유', whenEnIncludes: 'Share' },
+ { pattern: /개방하다/g, replacement: '열기', whenEnIncludes: 'Open' },
+ { pattern: /재인증하다/g, replacement: '재인증', whenEnIncludes: 'Re-authenticate' },
+ { pattern: /설립하다/g, replacement: '발견됨', whenEnIncludes: 'Found' },
+ { pattern: /밀어서 말하다/g, replacement: '누르고 말하기', whenEnIncludes: 'push to talk' },
+ { pattern: /검토 필요/g, replacement: '리뷰 필요', whenEnIncludes: 'Review needed' },
+ { pattern: /검토가 필요하다/g, replacement: '리뷰가 필요함', whenEnIncludes: 'Review needed' },
+ {
+ pattern: /다음과 같은 기술/g,
+ replacement: '다음과 같은 스킬',
+ whenEnIncludes: 'Supports skills'
+ },
+ ...KO_PHRASE_FIXES_ROUND5
+]
diff --git a/config/scripts/locale-ko-value-overrides.mjs b/config/scripts/locale-ko-value-overrides.mjs
new file mode 100644
index 00000000000..bec3eb2e7d8
--- /dev/null
+++ b/config/scripts/locale-ko-value-overrides.mjs
@@ -0,0 +1,231 @@
+// Korean value overrides from high-visibility UI audit rounds 2–4.
+// Why: keep locale-value-overrides.mjs under max-lines while preserving exact-match repairs.
+export const KO_VALUE_OVERRIDES = {
+ issue: '이슈',
+ issues: '이슈',
+ Issues: '이슈',
+ 'view issues': '이슈 보기',
+ 'project issues': '프로젝트 이슈',
+ 'Start workspace from issue': '이슈에서 워크스페이스 시작',
+ 'Jira issue': 'Jira 이슈',
+ 'Close Jira issue preview': 'Jira 이슈 미리보기 닫기',
+ 'file an issue': '이슈 등록',
+ 'Reading issue #': '이슈 # 읽는 중',
+ 'Issue source': '이슈 소스',
+ 'Removing…': '제거 중…',
+ 'Removing...': '제거 중...',
+ pulling: '가져오는 중',
+ lint: 'lint',
+ simulator: '시뮬레이터',
+ Rerun: '재실행',
+ 'Check reruns requested': '검사 재실행 요청됨',
+ 'Request reviewer {{value0}}': '리뷰어 요청 {{value0}}',
+ 'Unrequest reviewer {{value0}}': '리뷰 요청 취소 {{value0}}',
+ 'Review requested': '리뷰 요청됨',
+ 'merge request': 'MR',
+ MergeRequest: 'MR',
+ partial: '부분 연결',
+ 'Assign issue': '이슈 할당',
+ 'Edit issue': '이슈 편집',
+ 'Copy issue identifier': '이슈 식별자 복사',
+ 'Issue description formatting': '이슈 설명 형식',
+ 'More issue workspace actions': '추가 이슈 워크스페이스 작업',
+ 'updated the issue ·': '이슈를 업데이트했습니다 ·',
+ 'Showing issues from': '다음에서 이슈 표시',
+ 'No fetched issues match the selected teams': '선택한 팀과 일치하는 가져온 이슈가 없습니다.',
+ 'Failed to save issue-source preference': '이슈 소스 환경설정을 저장하지 못했습니다.',
+ 'No issues match this Linear context.': '이 Linear 컨텍스트와 일치하는 이슈가 없습니다.',
+ 'No issues match the selected preset.': '선택한 사전 설정과 일치하는 이슈가 없습니다.',
+ 'No GitLab issues match this filter.': '이 필터와 일치하는 GitLab 이슈가 없습니다.',
+ 'Failed to create issue.': '이슈를 생성하지 못했습니다.',
+ 'This repo has no Issue Types.': '이 저장소에는 이슈 유형이 없습니다.',
+ 'scoped issues': '범위가 지정된 이슈',
+ 'Open {{value0}} issues': '{{value0}} 이슈 열기',
+ 'Issue #{{value0}}': '이슈 #{{value0}}',
+ 'Linked issue #{{value0}}': '연결된 이슈 #{{value0}}',
+ 'Issue # or GitHub URL': '이슈 # 또는 GitHub URL',
+ 'Add Orca attribution to commits, PRs, and issues.': '커밋, PR 및 이슈에 Orca 속성을 추가합니다.',
+ 'Paste an issue URL, or enter a number. Leave blank to remove the link.':
+ '이슈 URL을 붙여넣거나 숫자를 입력하세요. 링크를 제거하려면 비워두세요.',
+ 'Connect Linear in Settings to search issues.': '이슈를 검색하려면 설정에서 Linear를 연결하세요.',
+ 'Add Linear access to browse and link issues.':
+ '이슈를 탐색하고 연결하려면 Linear 액세스를 추가하세요.',
+ "Couldn't load issues from": '다음에서 이슈를 로드할 수 없습니다.',
+ 'Select a team from the project workspace before filing this issue.':
+ '이 이슈를 제출하기 전에 프로젝트 워크스페이스에서 팀을 선택하세요.',
+ 'Issue has no repo slug.': '이슈에 저장소 슬러그가 없습니다.',
+ 'Install the GitLab CLI to enable merge requests, issues, and pipelines.':
+ 'MR, 이슈 및 파이프라인을 활성화하려면 GitLab CLI를 설치하세요.',
+ 'Install the GitHub CLI to enable pull requests, issues, and checks.':
+ 'PR, 이슈 및 검사를 활성화하려면 GitHub CLI를 설치하세요.',
+ 'Pull requests, issues, and checks via the': 'PR, 이슈 및 검사는 다음을 통해 이루어집니다.',
+ 'Merge requests, issues, todos, and pipelines via the':
+ '다음을 통해 MR, 이슈, 할 일, 파이프라인을 병합합니다.',
+ 'Orca uses the GitHub CLI (gh) to show pull requests, issues, and checks.':
+ 'Orca는 GitHub CLI(gh)를 사용하여 PR, 이슈 및 검사를 표시합니다.',
+ 'Shared hook and issue-automation defaults are defined in the repo and available to everyone who uses it.':
+ '공유 후크 및 이슈 자동화 기본값은 저장소에 정의되어 있으며 이를 사용하는 모든 사람이 사용할 수 있습니다.',
+ DRAFT_ISSUE: 'DRAFT_ISSUE',
+ Reviewer: '리뷰어',
+ Reviewers: '리뷰어',
+ Review: '리뷰',
+ Resolve: '해결',
+ Reply: '회신',
+ Manage: '관리',
+ Quote: '인용',
+ Confirm: '확인',
+ Enter: '입력',
+ Move: '이동',
+ Resume: '재개',
+ Register: '등록',
+ Restart: '다시 시작',
+ Block: '차단',
+ Duplicate: '복제',
+ Restore: '복원',
+ Configure: '구성',
+ Focus: '집중',
+ Start: '시작',
+ Work: '작업',
+ Show: '표시',
+ Pass: '통과',
+ Maintain: '유지',
+ Approve: '승인',
+ Support: '지원',
+ Track: '추적',
+ Share: '공유',
+ 'Re-authenticate': '재인증',
+ Skills: '스킬',
+ skill: '스킬',
+ Gitea: 'Gitea',
+ gitea: 'Gitea',
+ glab: 'glab',
+ gh: 'gh',
+ oauth: 'OAuth',
+ ado: 'ADO',
+ github: 'GitHub',
+ gitlab: 'gitlab',
+ atlassian: 'Atlassian',
+ jira: 'Jira',
+ Jira: 'Jira',
+ integrations: '연동',
+ mr: 'MR',
+ integration: '연동',
+ credentials: '자격 증명',
+ 'push to talk': '누르고 말하기',
+ 'Start work': '작업 시작',
+ Found: '발견됨',
+ found: '발견됨',
+ 'Review needed': '리뷰 필요',
+ 'need review': '리뷰 필요',
+ check: '확인',
+ generate: '생성',
+ reauthenticate: '재인증',
+ wrk: '작업',
+ 'Reviewed by': '리뷰어',
+ 'Review from': '리뷰 출처',
+ 'Review comment added.': '리뷰 댓글이 추가되었습니다.',
+ 'Agent skills': '에이전트 스킬',
+ 'Agent Skills': '에이전트 스킬',
+ 'Agent skill': '에이전트 스킬',
+ 'Scanning skills': '스킬 스캔 중',
+ 'No local skills found': '로컬 스킬을 찾을 수 없습니다.',
+ 'Browser Use skill': 'Browser Use 스킬',
+ 'Computer Use skill': 'Computer Use 스킬',
+ 'CLI skill': 'CLI 스킬',
+ 'Orca CLI skill': 'Orca CLI 스킬',
+ 'No checks reported yet': '아직 보고된 체크가 없습니다.',
+ 'This pull request has no reported checks yet': '이 PR에는 아직 보고된 체크가 없습니다.',
+ 'Keyboard shortcuts for common actions.': '일반 작업에 대한 키보드 단축키입니다.',
+ 'Common emulator commands': '일반 에뮬레이터 명령',
+ 'GitHub Integration': 'GitHub 연동',
+ 'GitLab Integration': 'GitLab 연동',
+ 'Bitbucket Integration': 'Bitbucket 연동',
+ 'Azure DevOps Integration': 'Azure DevOps 연동',
+ 'Gitea Integration': 'Gitea 연동',
+ 'Jira Integration': 'Jira 연동',
+ 'Linear Integration': 'Linear 연동',
+ 'hosted review': '호스팅 PR',
+ 'Hosted review operation in progress…': '호스팅 PR 작업 진행 중…',
+ 'Open hosted review after creation': '생성 후 호스팅 PR 열기',
+ 'Reviewer id is unavailable for this GitLab user.':
+ '이 GitLab 사용자의 리뷰어 ID를 사용할 수 없습니다.',
+ 'You have unsaved Git AI Author changes. Leaving will discard them.':
+ '저장되지 않은 Git AI Author 변경사항이 있습니다. 떠나면 폐기됩니다.',
+ 'Discard unsaved Git AI Author changes?':
+ '저장되지 않은 Git AI Author 변경사항을 삭제하시겠습니까?',
+ 'Branch naming, base refs, attribution, and Git AI Author.':
+ '브랜치 이름 지정, 기본 참조, 속성 및 Git AI Author.',
+ 'Used by repositories that inherit global hosted-review defaults.':
+ '전역 호스팅 PR 기본값을 상속하는 저장소에서 사용됩니다.',
+ 'Defaults used when the hosted-review composer opens.':
+ '호스팅 PR 작성기가 열릴 때 사용되는 기본값입니다.',
+ 'Run hosted-review detail generation once when the composer opens.':
+ '작성기가 열리면 호스팅 PR 세부 정보 생성을 한 번 실행합니다.',
+ 'Checks require a Git branch and hosted review context':
+ '검사에는 Git 브랜치 및 호스팅 PR 컨텍스트가 필요합니다.',
+ 'Start an agent from failed hosted-review checks.':
+ '실패한 호스팅 PR 체크에서 에이전트를 시작합니다.',
+ 'Start an agent for local or hosted-review merge conflicts.':
+ '로컬 또는 호스팅 PR 병합 충돌에 대한 에이전트를 시작합니다.',
+ 'Review the workspace error below, then refresh.':
+ '아래 워크스페이스 오류를 확인한 후 새로고침하세요.',
+ 'Review inactive workspaces before deleting their local files and Orca state.':
+ '로컬 파일과 Orca 상태를 삭제하기 전에 비활성 워크스페이스를 확인하세요.',
+ 'Review inactive workspaces (': '비활성 워크스페이스 확인(',
+ 'Review the settings that will be imported from your Ghostty config.':
+ 'Ghostty 구성에서 가져올 설정을 확인하세요.',
+ 'GitHub requires review approval before this pull request can merge':
+ '이 PR을 병합하려면 GitHub에서 리뷰 승인이 필요합니다.',
+ 'Prefer domain nouns from the task, avoid ticket IDs, and keep names reviewer-friendly.':
+ '작업에서 도메인 명사를 선호하고, 티켓 ID를 피하고, 리뷰어 친화적인 이름을 유지하세요.',
+ 'Enable AI author': 'AI author 활성화',
+ 'AI author': 'AI author',
+ 'This pull request has no reported checks yet.': '이 PR에는 아직 보고된 체크가 없습니다.',
+ 'Needs review': '리뷰 필요',
+ 'In review': '리뷰 중',
+ 'Conductor Review': 'Conductor 리뷰',
+ 'Markdown Review Notes': '마크다운 리뷰 노트',
+ 'Review conflicts': '충돌 리뷰',
+ 'Review notes': '리뷰 노트',
+ 'Daily change review': '일일 변경 리뷰',
+ 'Release readiness review': '출시 준비 리뷰',
+ 'Recurring review': '반복 리뷰',
+ 'review src/auth': 'src/auth 리뷰',
+ 'review auth edge cases': '인증 예외 사례 리뷰',
+ Launch: '실행',
+ 'Launch:': '실행:',
+ launch: '실행',
+ trace: '추적',
+ display: '표시',
+ compose: '작성',
+ verify: '검증',
+ Keep: '유지',
+ 'check #': '체크 #',
+ 'to submit.': '제출.',
+ 'Install the Orca skill so agents know to use the Orca CLI.':
+ '에이전트가 Orca CLI를 사용하도록 Orca 스킬을 설치하세요.',
+ 'Linear, GitLab, Bitbucket, Azure DevOps, Gitea, and Jira live in Settings > Integrations.':
+ 'Linear, GitLab, Bitbucket, Azure DevOps, Gitea 및 Jira는 설정 > 연동에 있습니다.',
+ 'changed since you last approved. Re-review before it runs':
+ '마지막으로 승인한 이후 변경되었습니다. 실행하기 전에 재리뷰하세요.',
+ 'Review and edit the full command input before starting an agent.':
+ '에이전트를 시작하기 전에 전체 명령 입력을 리뷰하고 편집하세요.',
+ 'Create a {{value0}} to start checks and review.':
+ '체크와 리뷰를 시작하려면 {{value0}}을(를) 만드세요.',
+ "Control Orca from your phone. Check on agents, review changes, and kick off tasks while you're away from your desk.":
+ '휴대폰에서 Orca를 제어하세요. 자리를 비운 동안 에이전트를 확인하고, 변경 사항을 리뷰하고, 작업을 시작하세요.',
+ 'Skill command copied and inserted below for review.':
+ '리뷰를 위해 스킬 명령을 아래에 복사하여 삽입했습니다.',
+ 'X finishes, send it the review task.”': 'X가 끝나면 리뷰 작업을 보냅니다.”',
+ 'Conflicted files are reviewed separately': '충돌하는 파일은 별도로 리뷰됩니다.',
+ 'This review snapshot no longer has any live unresolved conflicts.':
+ '이 리뷰 스냅샷에는 더 이상 실시간으로 해결되지 않은 충돌이 없습니다.',
+ 'Review before attaching. Captured page context may include visible site content.':
+ '첨부하기 전에 리뷰하세요. 캡처된 페이지 컨텍스트에는 눈에 보이는 사이트 콘텐츠가 포함될 수 있습니다.',
+ 'Review the repository health. Check dependency updates, failing tests, lint/typecheck status, and risky open changes. Summarize findings and suggest the next action.':
+ '저장소 상태를 리뷰합니다. 종속성 업데이트, 실패한 테스트, lint/typecheck 상태, 위험한 공개 변경 사항을 확인하세요. 조사 결과를 요약하고 다음 조치를 제안합니다.',
+ 'Review recent changes in this workspace. Focus on correctness risks, UX regressions, missing tests, and follow-up tasks. Keep the report short and actionable.':
+ '이 워크스페이스의 최근 변경사항을 리뷰하세요. 정확성 위험, UX 회귀, 누락된 테스트 및 후속 작업에 중점을 둡니다. 보고서를 짧고 실행 가능하게 유지하세요.',
+ 'Check for stuck work, stale generated files, failing validation, and anything that needs human attention. Report only actionable issues.':
+ '작업 중단, 오래 생성된 파일, 유효성 검사 실패 및 사람의 주의가 필요한 모든 사항을 확인하세요. 실행 가능한 이슈만 보고하세요.'
+}
diff --git a/config/scripts/locale-phrase-fixes.mjs b/config/scripts/locale-phrase-fixes.mjs
new file mode 100644
index 00000000000..f8660a76883
--- /dev/null
+++ b/config/scripts/locale-phrase-fixes.mjs
@@ -0,0 +1,379 @@
+import { KO_PHRASE_FIXES_ROUND4 } from './locale-ko-phrase-fixes.mjs'
+import { ZH_PHRASE_FIXES_ROUND5 } from './locale-zh-phrase-fixes-round5.mjs'
+
+import { JA_PHRASE_FIXES } from './locale-ja-phrase-fixes.mjs'
+
+export const LOCALE_PHRASE_FIXES = {
+ ko: [
+ { pattern: /해고하다/g, replacement: '닫기', whenEnIncludes: 'Dismiss' },
+ { pattern: /선택 과목/g, replacement: '선택 사항', whenEnIncludes: 'Optional' },
+ { pattern: /상담원/g, replacement: '에이전트', whenEnIncludes: 'agent' },
+ { pattern: /상담사/g, replacement: '에이전트', whenEnIncludes: 'agent' },
+ { pattern: /지점/g, replacement: '브랜치', whenEnIncludes: 'ranch' },
+ { pattern: /분기/g, replacement: '브랜치', whenEnIncludes: 'ranch' },
+ { pattern: /나뭇가지/g, replacement: '브랜치', whenEnIncludes: 'ranch' },
+ { pattern: /홍보/g, replacement: 'PR', whenEnIncludes: 'PR' },
+ { pattern: /선형/g, replacement: 'Linear', whenEnIncludes: 'Linear' },
+ { pattern: /관현악법/g, replacement: '오케스트레이션', whenEnIncludes: 'Orchestration' },
+ { pattern: /자치령 대표/g, replacement: '에이전트', whenEnIncludes: 'Agents' },
+ { pattern: /찾다\.\.\./g, replacement: '검색...', whenEnIncludes: 'Search' },
+ { pattern: /찾다/g, replacement: '검색', whenEnIncludes: 'Search' },
+ { pattern: /구하다/g, replacement: '저장', whenEnIncludes: 'Save' },
+ { pattern: /설치하다/g, replacement: '설치', whenEnIncludes: 'Install' },
+ { pattern: /장애가 있는/g, replacement: '비활성', whenEnIncludes: 'Disabled' },
+ { pattern: /준비가 된/g, replacement: '준비됨', whenEnIncludes: 'Ready' },
+ { pattern: /다시 놓기/g, replacement: '재설정', whenEnIncludes: 'Reset' },
+ { pattern: /새로 고치다/g, replacement: '새로고침', whenEnIncludes: 'Refresh' },
+ { pattern: /분명한/g, replacement: '지우기', whenEnIncludes: 'Clear' },
+ { pattern: /할 수 있게 하다/g, replacement: '활성화', whenEnIncludes: 'Enable' },
+ { pattern: /갈등/g, replacement: '충돌', whenEnIncludes: 'conflict' },
+ { pattern: /절약/g, replacement: '저장', whenEnIncludes: 'Saving' },
+ { pattern: /이동하는/g, replacement: '모바일', whenEnIncludes: 'Mobile' },
+ { pattern: /체크 무늬/g, replacement: '검사', whenEnIncludes: 'Checks' },
+ { pattern: /양수인/g, replacement: '담당자', whenEnIncludes: 'assignee' },
+ { pattern: /논평/g, replacement: '댓글', whenEnIncludes: 'Comment' },
+ {
+ pattern: /이력서 작업공간/g,
+ replacement: '워크스페이스',
+ whenEnIncludes: 'Resume workspace'
+ },
+ {
+ pattern: /이력서 워크스페이스/g,
+ replacement: '워크스페이스',
+ whenEnIncludes: 'Resume workspace'
+ },
+ {
+ pattern: /PR에 첨부된 이력서/g,
+ replacement: 'PR에 연결된',
+ whenEnIncludes: 'Resume workspace attached to PR'
+ },
+ { pattern: /부동/g, replacement: '플로팅', whenEnIncludes: 'Floating' },
+ { pattern: /합격/g, replacement: '통과', whenEnIncludes: 'passing' },
+ { pattern: /작업공간/g, replacement: '워크스페이스', whenEnIncludes: 'workspace' },
+ { pattern: /작업 공간/g, replacement: '워크스페이스', whenEnIncludes: 'workspace' },
+ { pattern: /보다/g, replacement: '보기', whenEnIncludes: 'View' },
+ { pattern: /다시 해 보다/g, replacement: '다시 시도', whenEnIncludes: 'Retry' },
+ { pattern: /버리다/g, replacement: '버리기', whenEnIncludes: 'Discard' },
+ { pattern: /일반적인/g, replacement: '일반', whenEnIncludes: 'General' },
+ { pattern: /모습/g, replacement: '외관', whenEnIncludes: 'Appearance' },
+ { pattern: /목소리/g, replacement: '음성', whenEnIncludes: 'Voice' },
+ { pattern: /원격 측정/g, replacement: '텔레메트리', whenEnIncludes: 'Telemetry' },
+ { pattern: /충돌 신고/g, replacement: '크래시 신고', whenEnIncludes: 'Crash' },
+ { pattern: /충돌 보고서/g, replacement: '크래시 보고서', whenEnIncludes: 'crash report' },
+ { pattern: /충돌 세부/g, replacement: '크래시 세부', whenEnIncludes: 'crash' },
+ { pattern: /워크스페이스이/g, replacement: '워크스페이스가', whenEnIncludes: 'workspace' },
+ { pattern: /워크스페이스을/g, replacement: '워크스페이스를', whenEnIncludes: 'workspace' },
+ { pattern: /워크스페이스은/g, replacement: '워크스페이스는', whenEnIncludes: 'workspace' },
+ { pattern: /워크스페이스으로/g, replacement: '워크스페이스로', whenEnIncludes: 'workspace' },
+ { pattern: /작업 영역/g, replacement: '워크스페이스', whenEnIncludes: 'workspace' },
+ { pattern: /새로 고치는 중/g, replacement: '새로고침 중', whenEnIncludes: 'refresh' },
+ { pattern: /새로 고치지/g, replacement: '새로고침하지', whenEnIncludes: 'refresh' },
+ { pattern: /새로 고치는/g, replacement: '새로고침', whenEnIncludes: 'Refreshing' },
+ { pattern: /새로 고치고/g, replacement: '새로고침하고', whenEnIncludes: 'refresh' },
+ { pattern: /새로 고치/g, replacement: '새로고침', whenEnIncludes: 'Refresh' },
+ { pattern: /GitHub 문제/g, replacement: 'GitHub 이슈', whenEnIncludes: 'issue' },
+ { pattern: /미리 보는/g, replacement: '미리보기', whenEnIncludes: 'Preview' },
+ { pattern: /미리 보고/g, replacement: '미리보기하고', whenEnIncludes: 'Preview' },
+ { pattern: /풀 리퀘스트/g, replacement: 'PR', whenEnIncludes: 'pull request' },
+ { pattern: /풀 요청/g, replacement: 'PR', whenEnIncludes: 'pull request' },
+ { pattern: /풀 요청/g, replacement: 'PR', whenEnIncludes: 'pull-request' },
+ { pattern: /하위 문제/g, replacement: '하위 이슈', whenEnIncludes: 'sub-issue' },
+ { pattern: /어린이들/g, replacement: '하위', whenEnIncludes: 'children' },
+ { pattern: /어린이/g, replacement: '하위', whenEnIncludes: 'child' },
+ { pattern: /배상/g, replacement: '전송 중', whenEnIncludes: 'sending' },
+ { pattern: /보내다/g, replacement: '보내기', whenEnIncludes: 'Send' },
+ { pattern: /파견/g, replacement: '디스패치', whenEnIncludes: 'dispatch' },
+ { pattern: /이 호를/g, replacement: '이 이슈를', whenEnIncludes: 'opened this issue' },
+ { pattern: /문제를 열/g, replacement: '이슈를 열', whenEnIncludes: 'opened this issue' },
+ { pattern: /전시/g, replacement: '표시 중', whenEnIncludes: 'Showing' },
+ { pattern: /현재의/g, replacement: '현재', whenEnIncludes: 'Current' },
+ { pattern: /강제삭제/g, replacement: '강제 삭제', whenEnIncludes: 'Force Delete' },
+ { pattern: /끈/g, replacement: '문자열', whenEnIncludes: 'string' },
+ { pattern: /나뉘다/g, replacement: '분할', whenEnIncludes: 'split' },
+ { pattern: /제1터미널/g, replacement: '터미널 1', whenEnIncludes: 'Terminal 1' },
+ { pattern: /알았어요/g, replacement: '확인', whenEnIncludes: 'Got it' },
+ { pattern: /선택 해제/g, replacement: '거부', whenEnIncludes: 'Opt out' },
+ { pattern: /사이드바 전환/g, replacement: '사이드바 표시/숨기기', whenEnIncludes: 'Toggle' },
+ { pattern: /Jira 문제/g, replacement: 'Jira 이슈', whenEnIncludes: 'issue' },
+ { pattern: /GitLab 문제/g, replacement: 'GitLab 이슈', whenEnIncludes: 'issue' },
+ { pattern: /문제 소스/g, replacement: '이슈 소스', whenEnIncludes: 'issue source' },
+ { pattern: /문제 #/g, replacement: '이슈 #', whenEnIncludes: 'issue' },
+ { pattern: /문제에서/g, replacement: '이슈에서', whenEnIncludes: 'from issue' },
+ { pattern: /프로젝트 문제/g, replacement: '프로젝트 이슈', whenEnIncludes: 'project issues' },
+ { pattern: /할당된 문제/g, replacement: '할당된 이슈', whenEnIncludes: 'assigned issue' },
+ { pattern: /문제 보기/g, replacement: '이슈 보기', whenEnIncludes: 'view issues' },
+ { pattern: /문제를 제기하다/g, replacement: '이슈 등록', whenEnIncludes: 'file an issue' },
+ { pattern: /읽기 문제 #/g, replacement: '이슈 # 읽는 중', whenEnIncludes: 'Reading issue' },
+ { pattern: /병합 요청/g, replacement: 'MR', whenEnIncludes: 'merge request' },
+ { pattern: /병합요청/g, replacement: 'MR', whenEnIncludes: 'MergeRequest' },
+ { pattern: /풀이/g, replacement: '제거 중', whenEnIncludes: 'Removing' },
+ { pattern: /풀 중/g, replacement: '가져오는 중', whenEnIncludes: 'pulling' },
+ { pattern: /보풀/g, replacement: 'lint', whenEnIncludes: 'lint' },
+ { pattern: /모의 실험 장치/g, replacement: '시뮬레이터', whenEnIncludes: 'simulator' },
+ { pattern: /재방송/g, replacement: '재실행', whenEnIncludes: 'Rerun' },
+ {
+ pattern: /재방송 요청 확인/g,
+ replacement: '검사 재실행 요청됨',
+ whenEnIncludes: 'Check reruns'
+ },
+ { pattern: /요청 검토자/g, replacement: '리뷰어 요청', whenEnIncludes: 'Request reviewer' },
+ {
+ pattern: /요청 취소 검토자/g,
+ replacement: '리뷰 요청 취소',
+ whenEnIncludes: 'Unrequest reviewer'
+ },
+ { pattern: /검토가 요청됨/g, replacement: '리뷰 요청됨', whenEnIncludes: 'Review requested' },
+ { pattern: /문제 소스/g, replacement: '이슈 소스', whenEnIncludes: 'issue-source' },
+ { pattern: /PR, 문제/g, replacement: 'PR, 이슈', whenEnIncludes: 'issues' },
+ { pattern: /, 문제,/g, replacement: ', 이슈,', whenEnIncludes: 'issues' },
+ { pattern: /및 문제/g, replacement: '및 이슈', whenEnIncludes: 'issues' },
+ { pattern: /문제 자동화/g, replacement: '이슈 자동화', whenEnIncludes: 'issue-automation' },
+ ...KO_PHRASE_FIXES_ROUND4
+ ],
+ zh: [
+ { pattern: /客服人员/g, replacement: '代理', whenEnIncludes: 'agent' },
+ { pattern: /会议/g, replacement: '会话', whenEnIncludes: 'session' },
+ { pattern: /港口/g, replacement: '端口', whenEnIncludes: 'ort' },
+ { pattern: /公关/g, replacement: 'PR', whenEnIncludes: 'PR' },
+ { pattern: /虎鲸:\/\//g, replacement: 'orca://', whenEnIncludes: 'orca://' },
+ { pattern: /代理商/g, replacement: '代理', whenEnIncludes: 'agent' },
+ { pattern: /智能体/g, replacement: '代理', whenEnIncludes: 'agent' },
+ { pattern: /分支机构/g, replacement: '分支', whenEnIncludes: 'ranch' },
+ { pattern: /座席/g, replacement: '代理', whenEnIncludes: 'agent' },
+ { pattern: /汽车/g, replacement: '自动', whenEnIncludes: 'Auto' },
+ { pattern: /清爽/g, replacement: '刷新中', whenEnIncludes: 'Refreshing' },
+ { pattern: /瓦斯尔/g, replacement: 'WSL', whenEnIncludes: 'wsl' },
+ { pattern: /细绳/g, replacement: '字符串', whenEnIncludes: 'string' },
+ { pattern: /在职的/g, replacement: '处理中', whenEnIncludes: 'Working' },
+ { pattern: /编曲/g, replacement: '编排', whenEnIncludes: 'Orchestration' },
+ { pattern: /复印门票/g, replacement: '复制工单', whenEnIncludes: 'Copy ticket' },
+ { pattern: /达尔文/g, replacement: 'darwin', whenEnIncludes: 'darwin' },
+ { pattern: /外貌/g, replacement: '外观', whenEnIncludes: 'Appearance' },
+ { pattern: /一般的/g, replacement: '通用', whenEnIncludes: 'General' },
+ { pattern: /先进的/g, replacement: '高级', whenEnIncludes: 'Advanced' },
+ { pattern: /实验性的/g, replacement: '实验性', whenEnIncludes: 'Experimental' },
+ { pattern: /移动的/g, replacement: '移动端', whenEnIncludes: 'Mobile' },
+ { pattern: /嗓音/g, replacement: '语音', whenEnIncludes: 'Voice' },
+ { pattern: /电脑使用/g, replacement: '计算机控制', whenEnIncludes: 'Computer Use' },
+ { pattern: /快捷方式/g, replacement: '快捷键', whenEnIncludes: 'Shortcuts' },
+ { pattern: /入职清单/g, replacement: '入门清单', whenEnIncludes: 'Onboarding checklist' },
+ { pattern: /发射代理/g, replacement: '启动代理', whenEnIncludes: 'Launch agent' },
+ { pattern: /地位/g, replacement: '状态', whenEnIncludes: 'Status' },
+ { pattern: /受让人/g, replacement: '负责人', whenEnIncludes: 'assignee' },
+ { pattern: /开放工作区/g, replacement: '打开工作区', whenEnIncludes: 'Open workspace' },
+ { pattern: /工作空间/g, replacement: '工作区', whenEnIncludes: 'Workspace' },
+ { pattern: /丢失的/g, replacement: '缺失', whenEnIncludes: 'Missing' },
+ {
+ pattern: /聆听捷径/g,
+ replacement: '正在录制快捷键',
+ whenEnIncludes: 'Listening for shortcut'
+ },
+ { pattern: /寻找捷径/g, replacement: '搜索快捷键', whenEnIncludes: 'Find shortcuts' },
+ { pattern: /连接到Orca/g, replacement: '连接到 Orca', whenEnIncludes: 'Connect to Orca' },
+ {
+ pattern: /开始使用Orca/g,
+ replacement: '开始使用 Orca',
+ whenEnIncludes: 'get started with Orca'
+ },
+ { pattern: /本机桌面/g, replacement: '原生桌面', whenEnIncludes: 'Native desktop' },
+ { pattern: /当前的/g, replacement: '当前', whenEnIncludes: 'Current' },
+ { pattern: /返回应用程序/g, replacement: '返回应用', whenEnIncludes: 'Back to app' },
+ { pattern: /可以安装/g, replacement: '可安装', whenEnIncludes: 'Available to install' },
+ { pattern: /未已检测/g, replacement: '未检测到', whenEnIncludes: 'detected' },
+ { pattern: /(? {
+ it('fixes Korean round 5 review, integration, and search keyword regressions', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.409528031f',
+ enValue: 'Review',
+ localeValue: '검토',
+ locale: 'ko'
+ })
+ ).toBe('리뷰')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.6c1efa2cf8',
+ enValue: 'In review',
+ localeValue: '검토 중',
+ locale: 'ko'
+ })
+ ).toBe('리뷰 중')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.524f095d55',
+ enValue: 'Needs review',
+ localeValue: '검토 필요',
+ locale: 'ko'
+ })
+ ).toBe('리뷰 필요')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.onboarding.IntegrationsStep.277f30eb34',
+ enValue:
+ 'Linear, GitLab, Bitbucket, Azure DevOps, Gitea, and Jira live in Settings > Integrations.',
+ localeValue:
+ 'Linear, GitLab, Bitbucket, Azure DevOps, Gitea 및 Jira는 설정 > 통합에 있습니다.',
+ locale: 'ko'
+ })
+ ).toBe('Linear, GitLab, Bitbucket, Azure DevOps, Gitea 및 Jira는 설정 > 연동에 있습니다.')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.general.search.244e3fb4c8',
+ enValue: 'Install the Orca skill so agents know to use the Orca CLI.',
+ localeValue: '에이전트가 Orca CLI 사용 방법을 알 수 있도록 Orca 기술을 설치합니다.',
+ locale: 'ko'
+ })
+ ).toBe('에이전트가 Orca CLI를 사용하도록 Orca 스킬을 설치하세요.')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.editor.MarkdownPreview.322afab6ff',
+ enValue: 'Review notes',
+ localeValue: '메모 검토',
+ locale: 'ko'
+ })
+ ).toBe('리뷰 노트')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.right.sidebar.source.control.repo.icon.ecf63ec3ef',
+ enValue: 'Launch',
+ localeValue: '시작하다',
+ locale: 'ko'
+ })
+ ).toBe('실행')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.485609c4f2',
+ enValue: 'check #',
+ localeValue: '확인하다 #',
+ locale: 'ko'
+ })
+ ).toBe('체크 #')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.lib.automation.templates.maintenance.prompt',
+ enValue:
+ 'Check for stuck work, stale generated files, failing validation, and anything that needs human attention. Report only actionable issues.',
+ localeValue:
+ '작업 중단, 오래 생성된 파일, 유효성 검사 실패 및 사람의 주의가 필요한 모든 사항을 확인하세요. 실행 가능한 문제만 보고하세요.',
+ locale: 'ko'
+ })
+ ).toBe(
+ '작업 중단, 오래 생성된 파일, 유효성 검사 실패 및 사람의 주의가 필요한 모든 사항을 확인하세요. 실행 가능한 이슈만 보고하세요.'
+ )
+ })
+})
diff --git a/config/scripts/locale-translation-policy.ja-round5.test.mjs b/config/scripts/locale-translation-policy.ja-round5.test.mjs
new file mode 100644
index 00000000000..26423e8ec86
--- /dev/null
+++ b/config/scripts/locale-translation-policy.ja-round5.test.mjs
@@ -0,0 +1,104 @@
+import { describe, expect, it } from 'vitest'
+
+import { repairTranslatedValue } from './locale-translation-policy.mjs'
+
+describe('locale-translation-policy ja round 5', () => {
+ it('fixes inline, launch, action, MR, and status chip regressions', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.6e43a16435',
+ enValue: 'Inline',
+ localeValue: '列をなして',
+ locale: 'ja'
+ })
+ ).toBe('インライン')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.repo.repo.icon.ecf63ec3ef',
+ enValue: 'Launch',
+ localeValue: '打ち上げ',
+ locale: 'ja'
+ })
+ ).toBe('起動')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.2c19d1db33',
+ enValue: 'Play',
+ localeValue: '遊ぶ',
+ locale: 'ja'
+ })
+ ).toBe('Play')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.8396825a14',
+ enValue: 'Action',
+ localeValue: 'アクション',
+ locale: 'ja'
+ })
+ ).toBe('操作')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.456b8512da',
+ enValue: 'MergeRequest',
+ localeValue: 'マージリクエスト',
+ locale: 'ja'
+ })
+ ).toBe('MR')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.github.PRFilterDropdowns.7f1ba66c3e',
+ enValue: 'Reviewed by',
+ localeValue: 'レビュー者',
+ locale: 'ja'
+ })
+ ).toBe('レビュアー')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.caebe3c10f',
+ enValue: 'Conductor Review',
+ localeValue: '指揮者のレビュー',
+ locale: 'ja'
+ })
+ ).toBe('Conductor レビュー')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.github.pr.merge.state.bf5e4c6c92',
+ enValue: 'Blocked',
+ localeValue: 'ブロック',
+ locale: 'ja'
+ })
+ ).toBe('ブロック中')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.IntegrationsPane.027440e1cb',
+ enValue: 'Merge requests, issues, todos, and pipelines via the',
+ localeValue: 'リクエスト、イシュー、ToDo、パイプラインをマージします。',
+ locale: 'ja'
+ })
+ ).toBe('MR、イシュー、ToDo、パイプラインは')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitLabItemDialog.98718490e4',
+ enValue: 'MR title is required.',
+ localeValue: 'MRの肩書きは必須です。',
+ locale: 'ja'
+ })
+ ).toBe('MR タイトルは必須です。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.terminal.search.d5e6c7fab1',
+ enValue: 'font features',
+ localeValue: 'フォントの特徴',
+ locale: 'ja'
+ })
+ ).toBe('フォント特性')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.f05d237049',
+ enValue: 'Add a project first',
+ localeValue: 'まずプロジェクトを追加してください',
+ locale: 'ja'
+ })
+ ).toBe('まずプロジェクトを追加')
+ })
+})
diff --git a/config/scripts/locale-translation-policy.mjs b/config/scripts/locale-translation-policy.mjs
new file mode 100644
index 00000000000..e639f116850
--- /dev/null
+++ b/config/scripts/locale-translation-policy.mjs
@@ -0,0 +1,328 @@
+import { LOCALE_KEY_OVERRIDES } from './locale-key-overrides.mjs'
+import { LOCALE_PHRASE_FIXES } from './locale-phrase-fixes.mjs'
+import { SEARCH_KEYWORD_OVERRIDES } from './locale-search-keyword-overrides.mjs'
+import { LOCALE_VALUE_OVERRIDES } from './locale-value-overrides.mjs'
+
+export { LOCALE_KEY_OVERRIDES } from './locale-key-overrides.mjs'
+export { LOCALE_PHRASE_FIXES } from './locale-phrase-fixes.mjs'
+export { SEARCH_KEYWORD_OVERRIDES } from './locale-search-keyword-overrides.mjs'
+export { LOCALE_VALUE_OVERRIDES } from './locale-value-overrides.mjs'
+
+const AGENT_CATALOG_PREFIX = 'auto.lib.agent.catalog.'
+const OPEN_IN_APP_CATALOG_PREFIX = 'auto.lib.open.in.app.catalog.'
+
+// Why: product names and agent labels stay Latin — MT reads them as common words (Codex→copy, Gemini→zodiac).
+export const ENGLISH_ONLY_KEY_PREFIXES = [AGENT_CATALOG_PREFIX, OPEN_IN_APP_CATALOG_PREFIX]
+
+export const NEVER_TRANSLATE_VALUES = new Set([
+ 'Aider',
+ 'Amp',
+ 'Antigravity',
+ 'Auggie',
+ 'Autohand Code',
+ 'Charm',
+ 'Claude',
+ 'Claude Agent Teams',
+ 'Cline',
+ 'Codebuff',
+ 'Codex',
+ 'Command Code',
+ 'Continue',
+ 'Cursor',
+ 'Droid',
+ 'Gemini',
+ 'GitHub Copilot',
+ 'Goose',
+ 'Grok',
+ 'Hermes',
+ 'Kilocode',
+ 'Kimi',
+ 'Kiro',
+ 'Linear',
+ 'Mistral Vibe',
+ 'OMP',
+ 'OpenClaude',
+ 'OpenClaw',
+ 'OpenCode',
+ 'Orca',
+ 'Pi',
+ 'PostHog',
+ 'Qwen Code',
+ 'Rovo Dev',
+ 'VS Code',
+ 'Zed',
+ 'codex',
+ 'gemini',
+ 'claude',
+ 'gh',
+ 'idle',
+ 'anthropic',
+ 'Discord',
+ 'WSL',
+ 'wsl',
+ 'darwin',
+ 'Nautilus',
+ 'GitHub',
+ 'Beta'
+])
+
+export const BRAND_MISTRANSLATIONS = {
+ ko: {
+ Codex: ['사본', '코덱스'],
+ Gemini: ['쌍둥이자리'],
+ Claude: ['클로드'],
+ Grok: ['그록'],
+ Orca: ['오르카', '범고래'],
+ Cursor: ['커서'],
+ OpenCode: ['오픈코드'],
+ OpenClaw: ['오픈클로'],
+ OpenClaude: ['오픈클로드'],
+ Antigravity: ['반중력'],
+ Continue: ['계속하다'],
+ Charm: ['매력'],
+ Goose: ['거위'],
+ Pi: ['파이'],
+ 'GitHub Copilot': ['GitHub 코파일럿', '코파일럿'],
+ Discord: ['디스코드'],
+ Linear: ['선형']
+ },
+ zh: {
+ Codex: ['法典'],
+ Gemini: ['双子座'],
+ Claude: ['克洛德', '克劳德'],
+ Grok: ['格罗克'],
+ Orca: ['虎鲸', '逆戟鲸'],
+ Cursor: ['光标'],
+ OpenCode: ['开放代码'],
+ OpenClaw: ['开爪'],
+ OpenClaude: ['开放克劳德'],
+ Antigravity: ['反重力'],
+ Continue: ['继续'],
+ Charm: ['魅力'],
+ Goose: ['鹅'],
+ Pi: ['圆周率'],
+ Droid: ['机器人'],
+ 'GitHub Copilot': ['GitHub 副驾驶', '副驾驶'],
+ Linear: ['线性', '线形'],
+ Jira: ['吉拉']
+ },
+ ja: {
+ Codex: ['法典', 'コーデックス'],
+ Gemini: ['双子座'],
+ Claude: ['クロード'],
+ Grok: ['グロック'],
+ Orca: ['シャチ', '逆戟鲸', 'オルカ'],
+ Cursor: ['カーソル'],
+ OpenCode: ['オープンコード', 'オープン・コード'],
+ OpenClaw: ['オープンクロー'],
+ OpenClaude: ['オープンクロード'],
+ Antigravity: ['反重力'],
+ Continue: ['続ける', '続行'],
+ Charm: ['魅力'],
+ Goose: ['ガチョウ', '雁'],
+ Pi: ['円周率'],
+ Droid: ['ロボット', 'ドロイド'],
+ 'GitHub Copilot': ['GitHub コパイロット', 'コパイロット'],
+ Discord: ['不和'],
+ Linear: ['線形']
+ }
+}
+
+export const NATIVE_PICKER_LABELS = {
+ zh: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語' },
+ ko: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語' },
+ ja: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語' }
+}
+
+export function isEnglishOnlyKey(key) {
+ return ENGLISH_ONLY_KEY_PREFIXES.some((prefix) => key.startsWith(prefix))
+}
+
+export function shouldPreserveEnglishValue(enValue, key = '') {
+ if (!enValue?.trim()) {
+ return true
+ }
+ if (/^https?:\/\//.test(enValue) || enValue.startsWith('orca://')) {
+ return true
+ }
+ if (isEnglishOnlyKey(key)) {
+ return true
+ }
+ return NEVER_TRANSLATE_VALUES.has(enValue)
+}
+
+function applyBrandMistranslationFixes(enValue, localeValue, locale) {
+ let result = localeValue
+ const mistranslations = BRAND_MISTRANSLATIONS[locale] ?? {}
+
+ for (const [brand, wrongForms] of Object.entries(mistranslations)) {
+ if (!enValue.includes(brand)) {
+ continue
+ }
+ if (result.includes(brand)) {
+ continue
+ }
+ for (const wrong of wrongForms) {
+ if (!result.includes(wrong)) {
+ continue
+ }
+ // Why: "Copy identifier" legitimately uses 사본/复制 — only swap when English names the brand.
+ if (brand === 'Codex' && /\bCopy\b/i.test(enValue)) {
+ continue
+ }
+ result = result.replaceAll(wrong, brand)
+ }
+ }
+
+ return result
+}
+
+function applyPhraseFixes(enValue, localeValue, locale) {
+ let result = localeValue
+ for (const fix of LOCALE_PHRASE_FIXES[locale] ?? []) {
+ if (!enValue.toLowerCase().includes(fix.whenEnIncludes.toLowerCase())) {
+ continue
+ }
+ result = result.replace(fix.pattern, fix.replacement)
+ }
+ return result
+}
+
+export function repairTranslatedValue({ key, enValue, localeValue, locale }) {
+ const keyOverride = LOCALE_KEY_OVERRIDES[key]?.[locale]
+ if (keyOverride) {
+ return keyOverride
+ }
+
+ if (shouldPreserveEnglishValue(enValue, key)) {
+ return enValue
+ }
+
+ const override = LOCALE_VALUE_OVERRIDES[locale]?.[enValue]
+ if (override) {
+ return override
+ }
+
+ if (key.includes('.search.')) {
+ const searchOverride = SEARCH_KEYWORD_OVERRIDES[locale]?.[enValue]
+ if (searchOverride) {
+ return searchOverride
+ }
+ }
+
+ let result = localeValue
+ result = applyBrandMistranslationFixes(enValue, result, locale)
+ result = applyPhraseFixes(enValue, result, locale)
+
+ if (enValue.includes('orca://')) {
+ result = result.replace(/虎鲸:\/\//g, 'orca://')
+ }
+
+ if (enValue === 'Orca' || enValue.startsWith('Orca ')) {
+ result = result
+ .replaceAll('虎鲸', 'Orca')
+ .replaceAll('逆戟鲸', 'Orca')
+ .replaceAll('シャチ', 'Orca')
+ }
+
+ if (enValue.includes('orca://')) {
+ result = result.replace(/シャチ:\/\//g, 'orca://')
+ }
+
+ return result
+}
+
+export function collectStringLeaves(value, prefix = '', leaves = []) {
+ if (typeof value === 'string') {
+ leaves.push({ key: prefix, value })
+ return leaves
+ }
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
+ return leaves
+ }
+ for (const [key, child] of Object.entries(value)) {
+ collectStringLeaves(child, prefix ? `${prefix}.${key}` : key, leaves)
+ }
+ return leaves
+}
+
+export function setLeaf(catalog, key, translatedValue) {
+ const parts = key.split('.')
+ let cursor = catalog
+ for (let index = 0; index < parts.length - 1; index += 1) {
+ cursor = cursor[parts[index]]
+ }
+ cursor[parts.at(-1)] = translatedValue
+}
+
+export function repairCatalog(enCatalog, localeCatalog, locale) {
+ const leaves = collectStringLeaves(enCatalog)
+ let repaired = 0
+
+ for (const leaf of leaves) {
+ const current = leaf.key.split('.').reduce((cursor, part) => cursor?.[part], localeCatalog)
+ const next = repairTranslatedValue({
+ key: leaf.key,
+ enValue: leaf.value,
+ localeValue: current,
+ locale
+ })
+ if (next !== current) {
+ setLeaf(localeCatalog, leaf.key, next)
+ repaired += 1
+ }
+ }
+
+ if (localeCatalog.settings?.appearance?.language) {
+ for (const [labelKey, label] of Object.entries(NATIVE_PICKER_LABELS[locale] ?? {})) {
+ if (localeCatalog.settings.appearance.language[labelKey] !== label) {
+ localeCatalog.settings.appearance.language[labelKey] = label
+ repaired += 1
+ }
+ }
+ }
+
+ if (localeCatalog.menu) {
+ if (locale === 'zh') {
+ if (localeCatalog.menu.exploreOrca !== '探索 Orca') {
+ localeCatalog.menu.exploreOrca = '探索 Orca'
+ repaired += 1
+ }
+ if (localeCatalog.menu.gettingStarted !== 'Orca 入门') {
+ localeCatalog.menu.gettingStarted = 'Orca 入门'
+ repaired += 1
+ }
+ }
+ if (locale === 'ko') {
+ if (localeCatalog.menu.exploreOrca !== 'Orca 둘러보기') {
+ localeCatalog.menu.exploreOrca = 'Orca 둘러보기'
+ repaired += 1
+ }
+ if (localeCatalog.menu.gettingStarted !== 'Orca 시작하기') {
+ localeCatalog.menu.gettingStarted = 'Orca 시작하기'
+ repaired += 1
+ }
+ }
+ }
+
+ return repaired
+}
+
+export function repairCacheMap(cache, locale) {
+ let repaired = 0
+ for (const [enValue, translated] of cache.entries()) {
+ const next = shouldPreserveEnglishValue(enValue)
+ ? enValue
+ : repairTranslatedValue({
+ key: '',
+ enValue,
+ localeValue: translated,
+ locale
+ })
+ if (next !== translated) {
+ cache.set(enValue, next)
+ repaired += 1
+ }
+ }
+ return repaired
+}
diff --git a/config/scripts/locale-translation-policy.test.mjs b/config/scripts/locale-translation-policy.test.mjs
new file mode 100644
index 00000000000..31ab69fd1cb
--- /dev/null
+++ b/config/scripts/locale-translation-policy.test.mjs
@@ -0,0 +1,586 @@
+import { describe, expect, it } from 'vitest'
+
+import { repairTranslatedValue, shouldPreserveEnglishValue } from './locale-translation-policy.mjs'
+
+describe('locale-translation-policy', () => {
+ it('keeps agent catalog labels in English', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.lib.agent.catalog.760bc6883d',
+ enValue: 'Codex',
+ localeValue: '사본',
+ locale: 'ko'
+ })
+ ).toBe('Codex')
+ })
+
+ it('does not break Copy identifier when fixing Codex', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.example',
+ enValue: 'Copy identifier',
+ localeValue: '사본 식별자',
+ locale: 'ko'
+ })
+ ).toBe('사본 식별자')
+ })
+
+ it('fixes Dismiss homograph in Korean', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.store.slices.worktrees.889487d8bb',
+ enValue: 'Dismiss',
+ localeValue: '해고하다',
+ locale: 'ko'
+ })
+ ).toBe('닫기')
+ })
+
+ it('fixes Gemini zodiac mistranslation in Chinese catalog', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.lib.agent.catalog.12e6baa4f7',
+ enValue: 'Gemini',
+ localeValue: '双子座',
+ locale: 'zh'
+ })
+ ).toBe('Gemini')
+ })
+
+ it('preserves orca URL scheme in Chinese', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.web.WebConnect.27393856e4',
+ enValue: 'orca://pair?code=...',
+ localeValue: '虎鲸://pair?code=...',
+ locale: 'zh'
+ })
+ ).toBe('orca://pair?code=...')
+ })
+
+ it('skips machine translation for standalone brands', () => {
+ expect(shouldPreserveEnglishValue('Codex')).toBe(true)
+ expect(shouldPreserveEnglishValue('Codex', 'auto.stats.StatsPane.7d26110cea')).toBe(true)
+ expect(shouldPreserveEnglishValue('Show Codex usage')).toBe(false)
+ })
+
+ it('fixes high-visibility homograph mistranslations', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.AgentsPane.c9b33eb5c0',
+ enValue: 'Refreshing…',
+ localeValue: '爽やか…',
+ locale: 'ja'
+ })
+ ).toBe('更新中…')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.28986b3747',
+ enValue: 'Started an AI agent for the broken checks.',
+ localeValue: '壊れた小切手に対して AI エージェントを開始しました。',
+ locale: 'ja'
+ })
+ ).toBe('失敗したチェックに対して AI エージェントを開始しました。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.hooks.useSettingsNavigationMetadata.95a1886d94',
+ enValue: 'Control terminals and agents from your phone.',
+ localeValue: '電話機からターミナルとエージェントを制御します。',
+ locale: 'ja'
+ })
+ ).toBe('スマートフォンからターミナルとエージェントを操作')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.934add88b6',
+ enValue: 'Reviewer',
+ localeValue: '査読者',
+ locale: 'ja'
+ })
+ ).toBe('レビュアー')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.AgentsPane.92033495ff',
+ enValue: 'Auto',
+ localeValue: '汽车',
+ locale: 'zh'
+ })
+ ).toBe('自动')
+ expect(
+ repairTranslatedValue({
+ key: 'menu.reportCrash',
+ enValue: 'Report Crash...',
+ localeValue: '충돌 신고...',
+ locale: 'ko'
+ })
+ ).toBe('크래시 신고...')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.App.722d03aa62',
+ enValue: 'The crash report dialog hit an error.',
+ localeValue: '충돌 보고서 대화 상자에 오류가 발생했습니다.',
+ locale: 'ko'
+ })
+ ).toBe('크래시 보고서 대화 상자에 오류가 발생했습니다.')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.dashboard.DashboardAgentRow.912e136cd9',
+ enValue: 'Send',
+ localeValue: '보내다',
+ locale: 'ko'
+ })
+ ).toBe('보내기')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.orchestration.search.ca54c69806',
+ enValue: 'DAG',
+ localeValue: '가리비',
+ locale: 'ko'
+ })
+ ).toBe('DAG')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.CliSection.068552b191',
+ enValue: 'Removing…',
+ localeValue: '풀이…',
+ locale: 'ko'
+ })
+ ).toBe('제거 중…')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.status.bar.SshStatusSegment.63a2b965f6',
+ enValue: 'pulling',
+ localeValue: '풀 중',
+ locale: 'ko'
+ })
+ ).toBe('가져오는 중')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.be8cf68d9f',
+ enValue: 'view issues',
+ localeValue: '문제 보기',
+ locale: 'ko'
+ })
+ ).toBe('이슈 보기')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.8c45901789',
+ enValue: 'Request reviewer {{value0}}',
+ localeValue: '요청 검토자 {{value0}}',
+ locale: 'ko'
+ })
+ ).toBe('리뷰어 요청 {{value0}}')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.feature.wall.ReviewPRViewAnimatedVisual.25f6838e43',
+ enValue: 'lint',
+ localeValue: '보풀',
+ locale: 'ko'
+ })
+ ).toBe('lint')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitLabItemDialog.4168eb2c51',
+ enValue: 'Resolve',
+ localeValue: '해결하다',
+ locale: 'ko'
+ })
+ ).toBe('해결')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.934add88b6',
+ enValue: 'Reviewer',
+ localeValue: '검토자',
+ locale: 'ko'
+ })
+ ).toBe('리뷰어')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.skills.SkillsPage.f43ad6edf3',
+ enValue: 'Skills',
+ localeValue: '기술',
+ locale: 'ko'
+ })
+ ).toBe('스킬')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.581844769a',
+ enValue: 'mr',
+ localeValue: '~ 씨',
+ locale: 'ko'
+ })
+ ).toBe('MR')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.e1263dd748',
+ enValue: 'jira',
+ localeValue: '지라',
+ locale: 'ko'
+ })
+ ).toBe('Jira')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.aab86d64e5',
+ enValue: 'Gitea Integration',
+ localeValue: '지테아 통합',
+ locale: 'ko'
+ })
+ ).toBe('Gitea 연동')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.hooks.useSettingsNavigationMetadata.2b043783ef',
+ enValue: 'Integrations',
+ localeValue: '통합',
+ locale: 'ko'
+ })
+ ).toBe('연동')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.e52bed9264',
+ enValue: 'No checks reported yet',
+ localeValue: '아직 보고된 검사가 없습니다.',
+ locale: 'ko'
+ })
+ ).toBe('아직 보고된 체크가 없습니다.')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.right.sidebar.source.control.primary.action.7aad2c0240',
+ enValue: 'Hosted review operation in progress…',
+ localeValue: '호스팅 검토 작업 진행 중…',
+ locale: 'ko'
+ })
+ ).toBe('호스팅 PR 작업 진행 중…')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.933deaf732',
+ enValue: 'oauth',
+ localeValue: '맹세하다',
+ locale: 'ko'
+ })
+ ).toBe('OAuth')
+ })
+
+ it('fixes Chinese detected-state and skill terminology regressions', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.SidebarNav.e518f544b1',
+ enValue: 'No agents detected',
+ localeValue: '未已检测代理',
+ locale: 'zh'
+ })
+ ).toBe('未检测到代理')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.skills.SkillsPage.38e0951c3a',
+ enValue: 'Agent Skills',
+ localeValue: '代理技巧',
+ locale: 'zh'
+ })
+ ).toBe('代理技能')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.appearance.search.9ae151b26b',
+ enValue: 'linear',
+ localeValue: '线性',
+ locale: 'zh'
+ })
+ ).toBe('Linear')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.JiraIssueWorkspace.ef21405c6d',
+ enValue: 'Jira issue',
+ localeValue: '吉拉问题',
+ locale: 'zh'
+ })
+ ).toBe('Jira 议题')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.dbe5e2448e',
+ enValue: 'Pull request merged',
+ localeValue: '合并请求请求',
+ locale: 'zh'
+ })
+ ).toBe('拉取请求已合并')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.3ab6ac0fc8',
+ enValue: 'Preview and edit the selected GitHub issue or pull request.',
+ localeValue: '预览并编辑选定的 GitHub 问题或拉取请求。',
+ locale: 'zh'
+ })
+ ).toBe('预览并编辑选定的 GitHub 议题或拉取请求。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.LinearIssueWorkspace.0190b760c1',
+ enValue: 'Open on Linear',
+ localeValue: 'Linear打开',
+ locale: 'zh'
+ })
+ ).toBe('在 Linear 中打开')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.d0e3c8f933',
+ enValue: 'No matching GitHub work',
+ localeValue: '没有匹配的 GitHub 作品',
+ locale: 'zh'
+ })
+ ).toBe('没有匹配的 GitHub 工作项')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.hooks.useSettingsNavigationMetadata.4a728cd56b',
+ enValue: 'New features that are still taking shape. Give them a try.',
+ localeValue: '仍在形成的新特征。尝试一下。',
+ locale: 'zh'
+ })
+ ).toBe('仍在形成的新功能。尝试一下。')
+ })
+
+ it('fixes Japanese integration, merge, and search keyword regressions', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.f16e41cc72',
+ enValue: 'GitHub Integration',
+ localeValue: 'GitHubの統合',
+ locale: 'ja'
+ })
+ ).toBe('GitHub 連携')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitLabItemDialog.e089f62594',
+ enValue: 'Merged MR !{{value0}}',
+ localeValue: 'MR を統合しました !{{value0}}',
+ locale: 'ja'
+ })
+ ).toBe('MR をマージしました !{{value0}}')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.right.sidebar.source.control.primary.action.3d5dccef0b',
+ enValue: 'Nothing to commit. PR is already merged.',
+ localeValue: 'コミットするものは何もありません。 PR はすでに統合されています。',
+ locale: 'ja'
+ })
+ ).toBe('コミットするものはありません。PR はすでにマージされています。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.581844769a',
+ enValue: 'mr',
+ localeValue: '氏',
+ locale: 'ja'
+ })
+ ).toBe('MR')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.e1263dd748',
+ enValue: 'jira',
+ localeValue: 'ジラ',
+ locale: 'ja'
+ })
+ ).toBe('Jira')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.terminal.advanced.search.b7c2cee442',
+ enValue: 'experimental',
+ localeValue: '実験的機能な',
+ locale: 'ja'
+ })
+ ).toBe('実験的機能')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.ef21405c6d',
+ enValue: 'Jira issue',
+ localeValue: 'Jira の問題',
+ locale: 'ja'
+ })
+ ).toBe('Jira イシュー')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.mobile.MobileHero.668016be7a',
+ enValue: 'on your computer and phone.',
+ localeValue: 'コンピューターと携帯電話で。',
+ locale: 'ja'
+ })
+ ).toBe('コンピューターとスマートフォンで。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.3ab6ac0fc8',
+ enValue: 'Preview and edit the selected GitHub issue or pull request.',
+ localeValue: '選択した GitHub の課題またはプル リクエストをプレビューおよび編集します。',
+ locale: 'ja'
+ })
+ ).toBe('選択した GitHub イシューまたは PR をプレビュー・編集します。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.a2495e4784',
+ enValue: 'Pull request',
+ localeValue: 'プルリクエスト',
+ locale: 'ja'
+ })
+ ).toBe('PR')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.TaskPage.be8cf68d9f',
+ enValue: 'view issues',
+ localeValue: '問題を表示する',
+ locale: 'ja'
+ })
+ ).toBe('イシューを表示')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.editor.EditorContent.e4b074749d',
+ enValue: 'Front Matter',
+ localeValue: '前の問題',
+ locale: 'ja'
+ })
+ ).toBe('フロントマター')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.IntegrationsPane.c0c8575e05',
+ enValue: 'Install the GitHub CLI to enable pull requests, issues, and checks.',
+ localeValue:
+ 'GitHub CLI をインストールして、プル リクエスト、発行、チェックを有効にします。',
+ locale: 'ja'
+ })
+ ).toBe('GitHub CLI をインストールして PR、イシュー、チェックを有効にします。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.mobile.MobilePage.e17393c6a3',
+ enValue: 'Phone preview',
+ localeValue: '電話プレビュー',
+ locale: 'ja'
+ })
+ ).toBe('スマートフォンプレビュー')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.8c45901789',
+ enValue: 'Request reviewer {{value0}}',
+ localeValue: 'レビュアー {{value0}} をリクエスト',
+ locale: 'ja'
+ })
+ ).toBe('レビュアーをリクエスト {{value0}}')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.appearance.search.5e5b8878bf',
+ enValue: 'phone',
+ localeValue: '電話',
+ locale: 'ja'
+ })
+ ).toBe('スマートフォン')
+ })
+
+ it('fixes Chinese round 4 phone, review, PR, and status chip regressions', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.appearance.search.5e5b8878bf',
+ enValue: 'phone',
+ localeValue: '电话',
+ locale: 'zh'
+ })
+ ).toBe('手机')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.mobile.slides.TerminalSlide.985373052e',
+ enValue: 'Switch to phone mode',
+ localeValue: '切换到电话模式',
+ locale: 'zh'
+ })
+ ).toBe('切换到手机模式')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.GitPane.b559bf9899',
+ enValue: 'e.g. feature',
+ localeValue: '例如特征',
+ locale: 'zh'
+ })
+ ).toBe('例如 feature')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.terminal.search.d5e6c7fab1',
+ enValue: 'font features',
+ localeValue: '字体特征',
+ locale: 'zh'
+ })
+ ).toBe('字体特性')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.934add88b6',
+ enValue: 'Reviewer',
+ localeValue: '审稿人',
+ locale: 'zh'
+ })
+ ).toBe('评审人')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.a341343303',
+ enValue: 'Review comment added.',
+ localeValue: '添加了评论评论。',
+ locale: 'zh'
+ })
+ ).toBe('已添加评审评论。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.6e43a16435',
+ enValue: 'Inline',
+ localeValue: '排队',
+ locale: 'zh'
+ })
+ ).toBe('内联')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.github.pr.merge.state.bf5e4c6c92',
+ enValue: 'Blocked',
+ localeValue: '被阻止',
+ locale: 'zh'
+ })
+ ).toBe('已阻塞')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.6c1efa2cf8',
+ enValue: 'In review',
+ localeValue: '审核中',
+ locale: 'zh'
+ })
+ ).toBe('评审中')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.sidebar.workspace.status.2c19d1db33',
+ enValue: 'Play',
+ localeValue: '玩',
+ locale: 'zh'
+ })
+ ).toBe('Play')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.1bc0bdbb5e',
+ enValue: 'Launch:',
+ localeValue: '发射:',
+ locale: 'zh'
+ })
+ ).toBe('启动:')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.UpdateCard.actionBadge',
+ enValue: 'Action',
+ localeValue: '行动',
+ locale: 'zh'
+ })
+ ).toBe('操作')
+ })
+
+ it('applies search keyword overrides for settings search synonyms', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.appearance.search.262fe1d24f',
+ enValue: 'dark',
+ localeValue: '어두운',
+ locale: 'ko'
+ })
+ ).toBe('다크')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.appearance.search.24094af355',
+ enValue: 'font',
+ localeValue: '세례반',
+ locale: 'ko'
+ })
+ ).toBe('폰트')
+ })
+})
diff --git a/config/scripts/locale-translation-policy.zh-round5.test.mjs b/config/scripts/locale-translation-policy.zh-round5.test.mjs
new file mode 100644
index 00000000000..7fd05c8d4f1
--- /dev/null
+++ b/config/scripts/locale-translation-policy.zh-round5.test.mjs
@@ -0,0 +1,88 @@
+import { describe, expect, it } from 'vitest'
+
+import { repairTranslatedValue } from './locale-translation-policy.mjs'
+
+describe('locale-translation-policy zh round 5', () => {
+ it('fixes brand spacing, hosted review, and Orca Mobile regressions', () => {
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.stats.ShareUsageCard.0eb31e79ee',
+ enValue: 'Orca IDE',
+ localeValue: 'Orca集成开发环境',
+ locale: 'zh'
+ })
+ ).toBe('Orca IDE')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.ShortcutsPane.2a0e8aeccf',
+ enValue: 'Orca first',
+ localeValue: 'Orca第一',
+ locale: 'zh'
+ })
+ ).toBe('Orca 优先')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.CommitMessageAiPane.2dafc7646e',
+ enValue: 'Hosted-review creation defaults',
+ localeValue: '托管审阅创建默认值',
+ locale: 'zh'
+ })
+ ).toBe('托管评审创建默认值')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.AccountsPane.3180536c7a',
+ enValue: 'Codex Accounts',
+ localeValue: 'Codex账户',
+ locale: 'zh'
+ })
+ ).toBe('Codex 账户')
+ expect(
+ repairTranslatedValue({
+ key: 'menu.showMobileButton',
+ enValue: 'Show Orca Mobile Button',
+ localeValue: '显示 Orca 移动按钮',
+ locale: 'zh'
+ })
+ ).toBe('显示 Orca Mobile 按钮')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.GitPane.e02ea23a32',
+ enValue: 'Orca Attribution',
+ localeValue: 'Orca归属',
+ locale: 'zh'
+ })
+ ).toBe('Orca 归因')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.hooks.useSettingsNavigationMetadata.ab4b21b58e',
+ enValue: 'Branch naming, base refs, attribution, and Git AI Author.',
+ localeValue: '分支命名、基本引用、归属和 Git AI 作者。',
+ locale: 'zh'
+ })
+ ).toBe('分支命名、基础引用、归因和 Git AI Author。')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.1b18868569',
+ enValue: 'need review',
+ localeValue: '待审阅',
+ locale: 'zh'
+ })
+ ).toBe('待评审')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.GitHubItemDialog.ec5c4b3ab2',
+ enValue: 'Reopen PR',
+ localeValue: '重新开放PR',
+ locale: 'zh'
+ })
+ ).toBe('重新打开 PR')
+ expect(
+ repairTranslatedValue({
+ key: 'auto.components.settings.integrations.search.a5e5da02f7',
+ enValue: 'integration',
+ localeValue: '一体化',
+ locale: 'zh'
+ })
+ ).toBe('集成')
+ })
+})
diff --git a/config/scripts/locale-value-overrides.mjs b/config/scripts/locale-value-overrides.mjs
new file mode 100644
index 00000000000..9ba8fe01142
--- /dev/null
+++ b/config/scripts/locale-value-overrides.mjs
@@ -0,0 +1,513 @@
+import { JA_VALUE_OVERRIDES } from './locale-ja-value-overrides.mjs'
+import { KO_VALUE_OVERRIDES } from './locale-ko-value-overrides.mjs'
+import { ZH_VALUE_OVERRIDES } from './locale-zh-value-overrides.mjs'
+
+export const LOCALE_VALUE_OVERRIDES = {
+ ko: {
+ Save: '저장',
+ Close: '닫기',
+ Connect: '연결',
+ Edit: '편집',
+ Add: '추가',
+ Create: '생성',
+ Delete: '삭제',
+ Install: '설치',
+ Remove: '제거',
+ Refresh: '새로고침',
+ Reset: '재설정',
+ Enable: '활성화',
+ Disabled: '비활성',
+ Ready: '준비됨',
+ Select: '선택',
+ Clear: '지우기',
+ Back: '뒤로',
+ Reopen: '다시 열기',
+ Closed: '닫힘',
+ Agents: '에이전트',
+ agents: '에이전트',
+ orchestration: '오케스트레이션',
+ conflict: '충돌',
+ Disconnect: '연결 해제',
+ Cancel: '취소',
+ Copy: '복사',
+ Done: '완료',
+ Next: '다음',
+ Beta: '베타',
+ Dismiss: '닫기',
+ Optional: '선택 사항',
+ Ports: '포트',
+ Active: '활성',
+ 'Dismiss agent': '에이전트 닫기',
+ 'Codex Usage': 'Codex 사용량',
+ 'Claude Usage': 'Claude 사용량',
+ 'Gemini Usage': 'Gemini 사용량',
+ 'Force Delete Branch': '브랜치 강제 삭제',
+ 'Time agents worked': '에이전트 작업 시간',
+ PR: 'PR',
+ Installed: '설치됨',
+ 'Not installed': '설치되지 않음',
+ Checking: '확인 중',
+ 'Checking...': '확인 중...',
+ Connected: '연결됨',
+ Search: '검색',
+ 'Search...': '검색...',
+ 'Saving...': '저장 중...',
+ 'Report Crash...': '크래시 신고...',
+ Mobile: '모바일',
+ Checks: '검사',
+ Assignees: '담당자',
+ Assignee: '담당자',
+ assignee: '담당자',
+ '+ Assignee': '+ 담당자',
+ Assign: '할당',
+ Passed: '통과',
+ Collapse: '접기',
+ Comment: '댓글',
+ View: '보기',
+ General: '일반',
+ Appearance: '외관',
+ Voice: '음성',
+ 'Floating Workspace': '플로팅 워크스페이스',
+ Discard: '버리기',
+ Retry: '다시 시도',
+ 'Search settings': '설정 검색',
+ 'Find shortcuts': '바로가기 검색',
+ 'Opt out': '거부',
+ 'Got it': '확인',
+ 'Force Delete': '강제 삭제',
+ Current: '현재',
+ Showing: '표시 중',
+ 'Quick Commands': '빠른 명령어',
+ string: '문자열',
+ Refreshing: '새로고침 중',
+ 'Refreshing…': '새로고침 중…',
+ Issue: '이슈',
+ 'Privacy & Telemetry': '개인정보 및 텔레메트리',
+ Experimental: '실험적',
+ Advanced: '고급',
+ 'Computer Use': '컴퓨터 사용',
+ Shortcuts: '단축키',
+ 'Onboarding checklist': '온보딩 체크리스트',
+ Integrations: '연동',
+ split: '분할',
+ space: '스페이스',
+ mobile: '모바일',
+ skills: '스킬',
+ detected: '감지됨',
+ 'Toggle Left Sidebar': '왼쪽 사이드바 표시/숨기기',
+ 'Toggle Right Sidebar': '오른쪽 사이드바 표시/숨기기',
+ 'Open Worktree Palette': '워크트리 팔레트 열기',
+ 'Back to app': '앱으로 돌아가기',
+ 'Terminal 1': '터미널 1',
+ 'Enable floating workspace': '플로팅 워크스페이스 활성화',
+ 'Resume workspace': '워크스페이스 재개',
+ 'Resume workspace attached to PR': 'PR에 연결된 워크스페이스 재개',
+ 'Open workspace': '워크스페이스 열기',
+ 'Search Linear issues...': 'Linear 이슈 검색...',
+ 'Search Linear projects...': 'Linear 프로젝트 검색...',
+ 'Launch agent': '에이전트 실행',
+ 'Git AI Author': 'Git AI Author',
+ 'Copy ticket': '티켓 복사',
+ 'Try Again': '다시 시도',
+ 'Restart now': '지금 재시작',
+ 'Restart Orca': 'Orca 재시작',
+ 'Hide sleeping': '슬립 중인 항목 숨기기',
+ 'Open Linear tasks': 'Linear 작업 열기',
+ New: '새로 만들기',
+ Waiting: '대기 중',
+ Missing: '누락',
+ 'Listening for shortcut': '단축키 입력 대기 중',
+ 'Connect to Orca': 'Orca에 연결',
+ 'USB Devices': 'USB 장치',
+ 'Available to install': '설치 가능',
+ Workspace: '워크스페이스',
+ Status: '상태',
+ 'Orchestration skill': '오케스트레이션 스킬',
+ 'Set Up': '설정 시작',
+ Auto: '자동',
+ 'Working...': '작업 중...',
+ Command: '명령',
+ Dark: '다크',
+ Interface: '인터페이스',
+ Kill: '강제 종료',
+ 'Killing…': '종료 중…',
+ 'Kill all': '모두 강제 종료',
+ 'kill all': '모두 종료',
+ 'Collapse Orca': 'Orca 접기',
+ 'Search skills': '스킬 검색',
+ 'Search blocks': '블록 검색',
+ teams: '팀',
+ passing: '통과',
+ 'opened this issue': '이 이슈를 열었습니다',
+ 'Join Discord': 'Discord 참여',
+ Send: '보내기',
+ 'Sending…': '전송 중…',
+ 'Sending...': '전송 중...',
+ sending: '전송 중',
+ 'Pull request': 'PR',
+ child: '하위',
+ children: '하위',
+ eligible: '전송 가능',
+ dispatch: '디스패치',
+ coordinator: '코디네이터',
+ worker: '워커',
+ DAG: 'DAG',
+ examples: '예시',
+ Timer: '타이머',
+ ...KO_VALUE_OVERRIDES
+ },
+ zh: {
+ Save: '保存',
+ Close: '关闭',
+ Connect: '连接',
+ Edit: '编辑',
+ Add: '添加',
+ Create: '创建',
+ Delete: '删除',
+ Install: '安装',
+ Remove: '移除',
+ Refresh: '刷新',
+ Reset: '重置',
+ Enable: '启用',
+ Disabled: '已禁用',
+ Ready: '就绪',
+ Select: '选择',
+ Clear: '清除',
+ Back: '返回',
+ Reopen: '重新打开',
+ Closed: '已关闭',
+ Agents: '代理',
+ agents: '代理',
+ orchestration: '编排',
+ conflict: '冲突',
+ Disconnect: '断开连接',
+ Cancel: '取消',
+ Copy: '复制',
+ Done: '完成',
+ Next: '下一步',
+ Beta: '测试版',
+ Dismiss: '关闭',
+ Optional: '可选',
+ Ports: '端口',
+ Active: '当前',
+ 'Dismiss agent': '关闭代理',
+ 'Codex Usage': 'Codex 使用情况',
+ 'Claude Usage': 'Claude 使用情况',
+ 'Gemini Usage': 'Gemini 使用情况',
+ 'Force Delete Branch': '强制删除分支',
+ 'Time agents worked': '代理工作时间',
+ PR: 'PR',
+ linear: 'Linear',
+ jira: 'Jira',
+ Custom: '自定义',
+ 'Terminal 1': '终端 1',
+ Starter: '入门版',
+ Turns: '轮次',
+ 'Recent sessions': '最近的会话',
+ Installed: '已安装',
+ 'Not installed': '未安装',
+ Checking: '检查中',
+ 'Checking...': '检查中...',
+ Connected: '已连接',
+ Search: '搜索',
+ 'Search...': '搜索...',
+ 'Saving...': '保存中...',
+ 'Report Crash...': '报告崩溃...',
+ Mobile: '移动端',
+ Checks: '检查项',
+ Assignees: '负责人',
+ Assignee: '负责人',
+ assignee: '负责人',
+ '+ Assignee': '+ 负责人',
+ Assign: '分配',
+ Passed: '通过',
+ Collapse: '折叠',
+ Comment: '评论',
+ View: '查看',
+ General: '通用',
+ Appearance: '外观',
+ Voice: '语音',
+ 'Floating Workspace': '浮动工作区',
+ Discard: '放弃',
+ Retry: '重试',
+ 'Search settings': '搜索设置',
+ 'Find shortcuts': '搜索快捷键',
+ 'Opt out': '退出',
+ 'Got it': '知道了',
+ 'Force Delete': '强制删除',
+ Current: '当前',
+ Showing: '显示中',
+ 'Quick Commands': '快捷命令',
+ string: '字符串',
+ Refreshing: '刷新中',
+ 'Refreshing…': '刷新中…',
+ Issue: '议题',
+ 'Privacy & Telemetry': '隐私与遥测',
+ Experimental: '实验性',
+ Advanced: '高级',
+ 'Computer Use': '计算机控制',
+ Shortcuts: '快捷键',
+ 'Onboarding checklist': '入门清单',
+ Integrations: '集成',
+ split: '拆分',
+ space: '空间',
+ mobile: '移动端',
+ skills: '技能',
+ detected: '已检测',
+ 'Toggle Left Sidebar': '显示/隐藏左侧边栏',
+ 'Toggle Right Sidebar': '显示/隐藏右侧边栏',
+ 'Open Worktree Palette': '打开工作树面板',
+ 'Back to app': '返回应用',
+ 'Enable floating workspace': '启用浮动工作区',
+ 'Resume workspace': '恢复工作区',
+ 'Resume workspace attached to PR': '恢复关联 PR 的工作区',
+ 'Open workspace': '打开工作区',
+ 'Search Linear issues...': '搜索 Linear 议题...',
+ 'Search Linear projects...': '搜索 Linear 项目...',
+ 'Launch agent': '启动代理',
+ 'Git AI Author': 'Git AI Author',
+ 'Copy ticket': '复制工单',
+ 'Try Again': '重试',
+ 'Restart now': '立即重启',
+ 'Restart Orca': '重启 Orca',
+ 'Hide sleeping': '隐藏休眠项',
+ 'Open Linear tasks': '打开 Linear 任务',
+ New: '新建',
+ Waiting: '等待中',
+ Missing: '缺失',
+ 'Listening for shortcut': '正在录制快捷键',
+ 'Connect to Orca': '连接到 Orca',
+ 'USB Devices': 'USB 设备',
+ 'Available to install': '可安装',
+ Workspace: '工作区',
+ Status: '状态',
+ 'Orchestration skill': '编排技能',
+ 'Set Up': '初始设置',
+ Auto: '自动',
+ 'Working...': '处理中...',
+ Command: '命令',
+ Dark: '深色',
+ Interface: '界面',
+ Kill: '强制结束',
+ 'Killing…': '正在结束…',
+ 'Kill all': '全部强制结束',
+ 'kill all': '全部结束',
+ 'Collapse Orca': '折叠 Orca',
+ 'Search skills': '搜索技能',
+ 'Search blocks': '搜索块',
+ teams: '团队',
+ passing: '通过',
+ 'opened this issue': '创建了此议题',
+ Open: '进行中',
+ 'Join Discord': '加入 Discord',
+ 'Pull request merged': '拉取请求已合并',
+ 'Agent Skills': '代理技能',
+ 'Agent skills': '代理技能',
+ 'Agent skill': '代理技能',
+ 'Browser Use skill': '浏览器使用技能',
+ 'Install Browser Use Skill': '安装浏览器使用技能',
+ 'Scanning skills': '正在扫描技能',
+ 'Agent location': '代理位置',
+ Location: '位置',
+ 'Account Location': '账户位置',
+ 'Run location': '运行位置',
+ 'more locations': '更多位置',
+ 'No agents detected': '未检测到代理',
+ 'No external ports detected': '未检测到外部端口',
+ 'No workspace ports detected': '未检测到工作区端口',
+ 'No local ports detected': '未检测到本地端口',
+ 'No ports detected': '未检测到端口',
+ 'No speech detected.': '未检测到语音。',
+ 'No enabled AI agent was detected on this workspace host.':
+ '此工作区主机上未检测到已启用的 AI 代理。',
+ 'The selected agent was not detected on this workspace host.':
+ '此工作区主机上未检测到所选代理。',
+ 'No agents detected on your PATH. Pick one to install later, or continue with a blank terminal.':
+ 'PATH 中未检测到代理。可选择一个稍后安装,或使用空白终端继续。',
+ 'Jira issue': 'Jira 议题',
+ 'New Jira issue': '新建 Jira 议题',
+ 'Open in Jira': '在 Jira 中打开',
+ 'Hide Jira': '隐藏 Jira',
+ 'Connect Jira': '连接 Jira',
+ 'Jira Integration': 'Jira 集成',
+ 'Failed to resolve PR head.': '无法解析 PR 头引用。',
+ 'Failed to resolve PR base.': '无法解析 PR 基础引用。',
+ 'Linear issue': 'Linear 议题',
+ 'Linear issues': 'Linear 议题',
+ 'New Linear issue': '新建 Linear 议题',
+ 'Jira issues': 'Jira 议题',
+ 'Close Linear issue preview': '关闭 Linear 议题预览',
+ 'No Linear issues found': '未找到 Linear 议题',
+ 'Unable to load Linear issues': '无法加载 Linear 议题',
+ 'Preview and edit the selected Linear issue.': '预览并编辑选定的 Linear 议题。',
+ 'Browse and start work on your assigned Linear issues directly from here.':
+ '直接从这里浏览并开始处理分配给您的 Linear 议题。',
+ issue: '议题',
+ issues: '议题',
+ Issues: '议题',
+ 'No matching GitHub work': '没有匹配的 GitHub 工作项',
+ 'Open on Linear': '在 Linear 中打开',
+ 'Open in Linear': '在 Linear 中打开',
+ 'Copy Linear URL': '复制 Linear URL',
+ 'New Linear project': '新建 Linear 项目',
+ 'Add Linear access': '添加 Linear 访问',
+ 'Select one team to open in Linear': '选择一个团队在 Linear 中打开',
+ "Couldn't load issues from": '无法加载议题,来源',
+ 'Reading issue #': '阅读议题 #',
+ 'Connect Linear in Settings to search issues.': '在设置中连接 Linear 以搜索议题。',
+ 'Show Titlebar App Name': '显示标题栏应用名称',
+ 'Hide App Name': '隐藏应用名称',
+ 'Refresh Linear': '刷新 Linear',
+ 'Failed to update Linear state': '无法更新 Linear 状态',
+ 'Add Linear access to browse and link issues.': '添加 Linear 访问以浏览和链接议题。',
+ 'No issues match this Linear context.': '没有议题与此 Linear 上下文匹配。',
+ 'Fix checks prompt is empty. Update Source Control AI settings.':
+ '检查提示为空。请更新源代码管理 AI 设置。',
+ Question: '疑问',
+ ...ZH_VALUE_OVERRIDES
+ },
+ ja: {
+ Save: '保存',
+ Close: '閉じる',
+ Connect: '接続',
+ Edit: '編集',
+ Add: '追加',
+ Create: '作成',
+ Delete: '削除',
+ Install: 'インストール',
+ Remove: '削除',
+ Refresh: '更新',
+ Reset: 'リセット',
+ Enable: '有効化',
+ Disabled: '無効',
+ Ready: '準備完了',
+ Select: '選択',
+ Clear: 'クリア',
+ Back: '戻る',
+ Reopen: '再度開く',
+ Closed: 'クローズ',
+ Agents: 'エージェント',
+ agents: 'エージェント',
+ orchestration: 'オーケストレーション',
+ conflict: 'コンフリクト',
+ Disconnect: '切断',
+ Cancel: 'キャンセル',
+ Copy: 'コピー',
+ Done: '完了',
+ Next: '次へ',
+ Beta: 'ベータ',
+ Dismiss: '閉じる',
+ Optional: '任意',
+ Ports: 'ポート',
+ Active: 'アクティブ',
+ 'Dismiss agent': 'エージェントを閉じる',
+ 'Codex Usage': 'Codex 使用量',
+ 'Claude Usage': 'Claude 使用量',
+ 'Gemini Usage': 'Gemini 使用量',
+ 'Force Delete Branch': 'ブランチを強制削除',
+ 'Time agents worked': 'エージェント作業時間',
+ PR: 'PR',
+ Custom: 'カスタム',
+ 'Terminal 1': 'ターミナル 1',
+ Starter: 'スターター',
+ Turns: 'ターン',
+ 'Recent sessions': '最近のセッション',
+ Installed: 'インストール済み',
+ 'Not installed': '未インストール',
+ Checking: '確認中',
+ 'Checking...': '確認中...',
+ Connected: '接続済み',
+ Search: '検索',
+ 'Search...': '検索...',
+ 'Saving...': '保存中...',
+ 'Report Crash...': 'クラッシュを報告...',
+ Mobile: 'モバイル',
+ Checks: 'チェック',
+ Assignees: '担当者',
+ Assignee: '担当者',
+ assignee: '担当者',
+ '+ Assignee': '+ 担当者',
+ Assign: '割り当て',
+ Passed: '通過',
+ Collapse: '折りたたむ',
+ Comment: 'コメント',
+ View: '表示',
+ General: '一般',
+ Appearance: '外観',
+ Voice: '音声',
+ 'Floating Workspace': 'フローティングワークスペース',
+ Discard: '破棄',
+ Retry: '再試行',
+ 'Search settings': '設定を検索',
+ 'Find shortcuts': 'ショートカットを検索',
+ 'Opt out': 'オプトアウト',
+ 'Got it': '了解',
+ 'Force Delete': '強制削除',
+ Current: '現在',
+ Showing: '表示中',
+ 'Quick Commands': 'クイックコマンド',
+ string: '文字列',
+ Refreshing: '更新中',
+ 'Refreshing…': '更新中…',
+ Issue: 'イシュー',
+ 'Privacy & Telemetry': 'プライバシーとテレメトリ',
+ Experimental: '実験的機能',
+ Advanced: '詳細設定',
+ 'Computer Use': 'コンピュータ操作',
+ Shortcuts: 'ショートカット',
+ 'Onboarding checklist': 'オンボーディングチェックリスト',
+ Integrations: '連携',
+ split: '分割',
+ space: 'スペース',
+ mobile: 'モバイル',
+ skills: 'スキル',
+ detected: '検出済み',
+ 'Toggle Left Sidebar': '左サイドバーの表示/非表示',
+ 'Toggle Right Sidebar': '右サイドバーの表示/非表示',
+ 'Open Worktree Palette': 'ワークツリーパレットを開く',
+ 'Back to app': 'アプリに戻る',
+ 'Enable floating workspace': 'フローティングワークスペースを有効化',
+ 'Resume workspace': 'ワークスペースを再開',
+ 'Resume workspace attached to PR': 'PR に紐づくワークスペースを再開',
+ 'Open workspace': 'ワークスペースを開く',
+ 'Search Linear issues...': 'Linear イシューを検索...',
+ 'Search Linear projects...': 'Linear プロジェクトを検索...',
+ 'Launch agent': 'エージェントを起動',
+ 'Git AI Author': 'Git AI Author',
+ 'Copy ticket': 'チケットをコピー',
+ 'Try Again': '再試行',
+ 'Restart now': '今すぐ再起動',
+ 'Restart Orca': 'Orca を再起動',
+ 'Hide sleeping': 'スリープ中を非表示',
+ 'Open Linear tasks': 'Linear タスクを開く',
+ New: '新規',
+ Waiting: '待機中',
+ Missing: '不足',
+ 'Listening for shortcut': 'ショートカットを記録中',
+ 'Connect to Orca': 'Orca に接続',
+ 'USB Devices': 'USB デバイス',
+ 'Available to install': 'インストール可能',
+ Workspace: 'ワークスペース',
+ Status: '状態',
+ 'Orchestration skill': 'オーケストレーションスキル',
+ 'Set Up': 'セットアップ',
+ Auto: '自動',
+ 'Working...': '処理中...',
+ Command: 'コマンド',
+ Dark: 'ダーク',
+ Interface: 'インターフェース',
+ Kill: '強制終了',
+ 'Killing…': '終了中…',
+ 'Kill all': 'すべて強制終了',
+ 'kill all': 'すべて終了',
+ 'Collapse Orca': 'Orca を折りたたむ',
+ 'Search skills': 'スキルを検索',
+ 'Search blocks': 'ブロックを検索',
+ teams: 'チーム',
+ passing: '合格',
+ 'opened this issue': 'このイシューを作成しました',
+ Open: 'オープン',
+ 'Join Discord': 'Discord に参加',
+ ...JA_VALUE_OVERRIDES
+ }
+}
diff --git a/config/scripts/locale-zh-phrase-fixes-round5.mjs b/config/scripts/locale-zh-phrase-fixes-round5.mjs
new file mode 100644
index 00000000000..1aa117395e8
--- /dev/null
+++ b/config/scripts/locale-zh-phrase-fixes-round5.mjs
@@ -0,0 +1,57 @@
+// Chinese phrase fixes from high-visibility UI audit round 5.
+export const ZH_PHRASE_FIXES_ROUND5 = [
+ { pattern: /Orca集成开发环境/g, replacement: 'Orca IDE', whenEnIncludes: 'Orca IDE' },
+ { pattern: /Orca第一/g, replacement: 'Orca 优先', whenEnIncludes: 'Orca first' },
+ { pattern: /Orca移动/g, replacement: 'Orca Mobile', whenEnIncludes: 'Orca Mobile' },
+ { pattern: /Orca归属/g, replacement: 'Orca 归因', whenEnIncludes: 'Orca Attribution' },
+ { pattern: /Orca标志/g, replacement: 'Orca 标志', whenEnIncludes: 'Orca logo' },
+ { pattern: /喜欢Orca/g, replacement: '喜欢 Orca', whenEnIncludes: 'Enjoying Orca' },
+ { pattern: /认识Orca/g, replacement: '了解 Orca', whenEnIncludes: 'Get to know Orca' },
+ { pattern: /支持Orca/g, replacement: '支持 Orca', whenEnIncludes: 'Support Orca' },
+ { pattern: /展开Orca/g, replacement: '展开 Orca', whenEnIncludes: 'Expand Orca' },
+ { pattern: /来自Orca/g, replacement: '来自 Orca', whenEnIncludes: 'from Orca' },
+ {
+ pattern: /正在重新启动Orca/g,
+ replacement: '正在重启 Orca',
+ whenEnIncludes: 'Restarting Orca'
+ },
+ { pattern: /Orca([\u4e00-\u9fff])/g, replacement: 'Orca $1', whenEnIncludes: 'Orca' },
+ { pattern: /Linear([\u4e00-\u9fff])/g, replacement: 'Linear $1', whenEnIncludes: 'Linear' },
+ { pattern: /Codex([\u4e00-\u9fff])/g, replacement: 'Codex $1', whenEnIncludes: 'Codex' },
+ { pattern: /Claude([\u4e00-\u9fff])/g, replacement: 'Claude $1', whenEnIncludes: 'Claude' },
+ { pattern: /Claude代码/g, replacement: 'Claude Code', whenEnIncludes: 'Claude Code' },
+ { pattern: /GitHub 和Linear/g, replacement: 'GitHub 和 Linear', whenEnIncludes: 'Linear tasks' },
+ { pattern: /托管审阅/g, replacement: '托管评审', whenEnIncludes: 'hosted-review' },
+ { pattern: /托管审阅/g, replacement: '托管评审', whenEnIncludes: 'Hosted-review' },
+ { pattern: /审阅笔记/g, replacement: '评审笔记', whenEnIncludes: 'review note' },
+ { pattern: /审阅任务/g, replacement: '评审任务', whenEnIncludes: 'review task' },
+ { pattern: /待审阅/g, replacement: '待评审', whenEnIncludes: 'need review' },
+ { pattern: /重新审核/g, replacement: '重新评审', whenEnIncludes: 'Re-review' },
+ { pattern: /依赖项审核/g, replacement: '依赖项审计', whenEnIncludes: 'dependency audit' },
+ { pattern: /Git AI 作者/g, replacement: 'Git AI Author', whenEnIncludes: 'Git AI Author' },
+ { pattern: /基本引用/g, replacement: '基础引用', whenEnIncludes: 'base ref' },
+ { pattern: /重新开放PR/g, replacement: '重新打开 PR', whenEnIncludes: 'Reopen PR' },
+ { pattern: /重新开放/g, replacement: '重新打开', whenEnIncludes: 'reopen' },
+ { pattern: /受限制的钥匙/g, replacement: '受限制的密钥', whenEnIncludes: 'restricted keys' },
+ { pattern: /更换钥匙/g, replacement: '更换密钥', whenEnIncludes: 'Replace key' },
+ {
+ pattern: /根据所看到的内容采取行动/g,
+ replacement: '根据所看到的内容执行操作',
+ whenEnIncludes: 'act on what they see'
+ },
+ {
+ pattern: /建议下一步行动/g,
+ replacement: '建议下一步操作',
+ whenEnIncludes: 'suggest next actions'
+ },
+ {
+ pattern: /可操作的问题/g,
+ replacement: '需处理的问题',
+ whenEnIncludes: 'actionable issues'
+ },
+ {
+ pattern: /显示 Orca 移动按钮/g,
+ replacement: '显示 Orca Mobile 按钮',
+ whenEnIncludes: 'Show Orca Mobile Button'
+ }
+]
diff --git a/config/scripts/locale-zh-value-overrides.mjs b/config/scripts/locale-zh-value-overrides.mjs
new file mode 100644
index 00000000000..375c4a1ed39
--- /dev/null
+++ b/config/scripts/locale-zh-value-overrides.mjs
@@ -0,0 +1,191 @@
+// Chinese value overrides from high-visibility UI audit rounds 4–5.
+// Why: keep locale-value-overrides.mjs under max-lines while preserving exact-match repairs.
+export const ZH_VALUE_OVERRIDES = {
+ phone: '手机',
+ 'Switch to phone mode': '切换到手机模式',
+ 'e.g. feature': '例如 feature',
+ 'font features': '字体特性',
+ Launch: '启动',
+ 'Launch:': '启动:',
+ launcher: '启动器',
+ launch: '启动',
+ Reviewer: '评审人',
+ Reviewers: '评审人',
+ reviewer: '评审人',
+ review: '评审',
+ Review: '评审',
+ 'No matching reviewers.': '没有匹配的评审人。',
+ 'Request up to 15 reviewers': '最多请求 15 名评审人',
+ 'No reviewers requested.': '未请求评审人',
+ 'Remove reviewer {{value0}}': '移除评审人 {{value0}}',
+ 'Loading reviewers': '正在加载评审人',
+ 'Request reviewer {{value0}}': '请求评审人 {{value0}}',
+ 'Unrequest reviewer {{value0}}': '取消请求评审人 {{value0}}',
+ 'Failed to remove reviewer': '移除评审人失败',
+ 'Reviewers removed': '已移除评审人',
+ 'Reviewer removed': '已移除评审人',
+ 'Failed to request reviewer': '请求评审人失败',
+ 'Reviewers requested': '已请求评审',
+ 'Reviewer requested': '已请求评审',
+ 'You can request up to 15 reviewers': '最多可请求 15 名评审人',
+ 'Enter a reviewer': '输入评审人',
+ 'Add reviewer': '添加评审人',
+ 'No reviewers.': '没有评审人',
+ 'Open the PR details to view current reviewers.': '打开 PR 详情以查看当前评审人。',
+ 'Review comment added.': '已添加评审评论。',
+ 'Needs review': '待评审',
+ 'need review': '待评审',
+ 'In review': '评审中',
+ 'Review requested': '已请求评审',
+ 'Review conflicts': '评审冲突',
+ 'Markdown Review Notes': 'Markdown 评审笔记',
+ 'Reviewed by': '评审人',
+ 'Review from': '评审来自',
+ 'Reviewer id is unavailable for this GitLab user.': '此 GitLab 用户无法获取评审人 ID。',
+ 'Create a {{value0}} to start checks and review.': '创建 {{value0}} 以开始检查和评审。',
+ 'Conflicted files are reviewed separately': '冲突文件单独评审',
+ 'This review snapshot no longer has any live unresolved conflicts.':
+ '此评审快照不再有任何未解决的实时冲突。',
+ 'Skill command copied and inserted below for review.': '技能命令已复制并插入到下方以供评审。',
+ 'Release readiness review': '发布就绪评审',
+ 'Recurring review': '定期评审',
+ Completed: '已完成',
+ Inline: '内联',
+ thread: '帖子串',
+ destructive: 'destructive',
+ sheet: 'sheet',
+ page: 'page',
+ Annotation: '批注',
+ 'check #': '检查 #',
+ by: '由',
+ 'files viewed': '已查看文件',
+ 'comment L': 'comment L',
+ 'Note · line': '注释 · 行',
+ 'Copy Path to Line': '复制路径到行',
+ 'Copy Rel. Path to Line': '复制相对路径到行',
+ Action: '操作',
+ Actions: '操作',
+ action: '操作',
+ actions: '操作',
+ 'More actions': '更多操作',
+ 'More PR actions': '更多 PR 操作',
+ 'More PR workspace actions': '更多 PR 工作区操作',
+ 'Group actions for {{value0}}': '{{value0}} 的分组操作',
+ 'No blocking PR action': '没有阻塞 PR 操作',
+ 'Quick actions': '快捷操作',
+ 'action recipes': '操作方案',
+ 'Repository action recipes. Global settings are used until this repository customizes them.':
+ '仓库操作方案。在此仓库自定义之前,将使用全局设置。',
+ 'Adds action recipes for Source Control commit, pull request, branch-name, and fix actions.':
+ '为源代码管理的提交、拉取请求、分支命名和修复操作添加操作方案。',
+ Play: 'Play',
+ Flag: 'Flag',
+ Zinc: 'Zinc',
+ Rose: 'Rose',
+ Emerald: 'Emerald',
+ Amber: 'Amber',
+ Violet: 'Violet',
+ Sky: 'Sky',
+ Blue: 'Blue',
+ Neutral: 'Neutral',
+ Dashed: '虚线',
+ Dot: '圆点',
+ Circle: '圆形',
+ Progress: '进度',
+ Alert: '警报',
+ Paused: '已暂停',
+ 'In progress': '进行中',
+ Done: '完成',
+ 'Conductor Progress': 'Conductor 进度',
+ 'Conductor Review': 'Conductor 评审',
+ 'Conductor Done': 'Conductor 完成',
+ 'GitHub reports this pull request is blocked': 'GitHub 报告此拉取请求已被阻塞',
+ 'GitHub requires review approval before this pull request can merge':
+ 'GitHub 需要评审批准才能合并此拉取请求',
+ 'Used by repositories that inherit global hosted-review defaults.':
+ '由继承全局托管评审默认值的仓库使用。',
+ 'Use review template when available': '可用时使用评审模板',
+ 'Create hosted reviews as drafts unless changed in the composer.':
+ '除非在编辑器中更改,否则将托管评审创建为草稿。',
+ 'Start an agent from failed hosted-review checks.': '从失败的托管评审检查中启动代理。',
+ 'Checks require a Git branch and hosted review context': '检查需要 Git 分支和托管评审上下文',
+ 'Resolve Review Conflicts With AI': '使用 AI 解决评审冲突',
+ 'Hosted review operation in progress…': '托管评审操作进行中…',
+ 'Hosted review creation defaults': '托管评审创建默认值',
+ 'Open hosted review after creation': '创建后打开托管评审',
+ 'Hosted review creation defaults used when the hosted review editor opens.':
+ '打开托管评审编辑器时使用的托管评审创建默认值。',
+ 'Run hosted review detail generation once when the editor opens.':
+ '编辑器打开时运行一次托管评审详情生成。',
+ 'Show local Markdown review notes controls in rich editor mode.':
+ '在富文本编辑器模式下显示本地 Markdown 评审笔记控件。',
+ 'Orca IDE': 'Orca IDE',
+ 'Orca first': 'Orca 优先',
+ 'Orca Mobile': 'Orca Mobile',
+ 'Orca logo': 'Orca 标志',
+ 'Enjoying Orca?': '喜欢 Orca 吗?',
+ 'Get to know Orca': '了解 Orca',
+ 'Expand Orca': '展开 Orca',
+ 'Support Orca': '支持 Orca',
+ 'Restarting Orca…': '正在重启 Orca…',
+ 'Orca Attribution': 'Orca 归因',
+ 'Show Orca Mobile Button': '显示 Orca Mobile 按钮',
+ 'Codex Accounts': 'Codex 账户',
+ 'Codex Account': 'Codex 账户',
+ 'Active Codex Account': '活跃 Codex 账户',
+ 'Claude Accounts': 'Claude 账户',
+ 'Remove Claude Account?': '删除 Claude 账户?',
+ 'Claude account updated.': 'Claude 账户已更新。',
+ 'Claude account update failed.': 'Claude 账户更新失败。',
+ 'Could not load Claude accounts.': '无法加载 Claude 账户。',
+ 'Claude sign-in failed.': 'Claude 登录失败。',
+ 'Claude account added.': '已添加 Claude 账户。',
+ 'Claude Code session started': 'Claude Code 会话已开始',
+ 'Codex session started': 'Codex 会话已开始',
+ 'Enable Codex': '启用 Codex',
+ 'Most recent local Codex sessions in this scope.': '此范围内最近的本地 Codex 会话。',
+ 'Hosted-review creation defaults': '托管评审创建默认值',
+ 'Defaults used when the hosted-review composer opens.': '打开托管评审编辑器时使用的默认值。',
+ 'Run hosted-review detail generation once when the composer opens.':
+ '编辑器打开时运行一次托管评审详情生成。',
+ 'Show local markdown review note controls in rich editor mode.':
+ '在富文本编辑器模式下显示本地 Markdown 评审笔记控件。',
+ 'Start an agent for local or hosted-review merge conflicts.':
+ '启动用于解决本地或托管评审合并冲突的代理。',
+ 'changed since you last approved. Re-review before it runs':
+ '自您上次批准以来已发生变化。运行前请重新评审',
+ 'Run the weekly dependency audit and summarize risky changes.':
+ '每周运行依赖项审计并总结有风险的更改。',
+ "Give agents direct access to Orca's browser so they can test pages, capture screenshots, and act on what they see.":
+ '让代理直接访问 Orca 的浏览器,以便测试页面、捕获屏幕截图并根据所见内容执行操作。',
+ 'X finishes, send it the review task.”': 'X 完成后,把评审任务发给它。”',
+ 'Branch naming, base refs, attribution, and Git AI Author.':
+ '分支命名、基础引用、归因和 Git AI Author。',
+ 'You have unsaved Git AI Author changes. Leaving will discard them.':
+ '您有未保存的 Git AI Author 更改。离开将丢弃它们。',
+ 'Discard unsaved Git AI Author changes?': '放弃未保存的 Git AI Author 更改?',
+ 'Create a Linear project for the selected team.': '为所选团队创建 Linear 项目。',
+ 'Linear task mode': 'Linear 任务模式',
+ 'Failed to switch Linear workspace.': '无法切换 Linear 工作区。',
+ 'Linear project is missing workspace context.': 'Linear 项目缺少工作区上下文。',
+ 'No Linear projects found': '未找到 Linear 项目',
+ 'Unable to load Linear projects': '无法加载 Linear 项目',
+ 'Change Linear state from {{value0}}': '将 Linear 状态从 {{value0}} 更改为',
+ 'GitHub & Linear tasks': 'GitHub 和 Linear 任务',
+ 'Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.':
+ '每个已连接的 Linear 工作区都有一个由活动运行时存储的密钥。全权限密钥可覆盖密钥所有者可访问的所有团队;受限密钥可随时更换。',
+ 'Show Linear in the Tasks source picker and sidebar shortcuts.':
+ '在任务源选择器和侧边栏快捷方式中显示 Linear。',
+ 'Optional account switching for Claude while preserving shared chat context.':
+ 'Claude 的可选账户切换,同时保留共享聊天上下文。',
+ 'Countdown timer showing time until prompt cache expires (Claude agents).':
+ '显示提示词缓存到期倒计时的计时器(Claude 代理)。',
+ 'Claude caches your conversation to reduce costs. When idle too long the cache expires and the next message resends full context at higher cost. This shows a countdown so you know when to resume.':
+ 'Claude 会缓存对话以降低成本。空闲过久后缓存会过期,下一条消息将以更高成本重新发送完整上下文。此倒计时可帮助您了解何时继续。',
+ 'from Orca. It is still on your disk.': '来自 Orca。它仍保留在您的磁盘上。',
+ 'Pull request reopened': '拉取请求已重新打开',
+ 'Reopen PR': '重新打开 PR',
+ 'Reopened MR !{{value0}}': '已重新打开 MR !{{value0}}',
+ reopen: '重新打开',
+ 'Replace key': '更换密钥'
+}
diff --git a/config/scripts/repair-locale-catalog.mjs b/config/scripts/repair-locale-catalog.mjs
new file mode 100644
index 00000000000..70e84f8d4ad
--- /dev/null
+++ b/config/scripts/repair-locale-catalog.mjs
@@ -0,0 +1,75 @@
+import fs from 'node:fs/promises'
+import path from 'node:path'
+import process from 'node:process'
+import { pathToFileURL } from 'node:url'
+
+import { repairCacheMap, repairCatalog } from './locale-translation-policy.mjs'
+
+const LOCALES_DIR = path.join('src', 'renderer', 'src', 'i18n', 'locales')
+
+const LOCALE_CACHE_FILES = {
+ ko: '.ko-catalog-cache.json',
+ zh: '.zh-catalog-cache.json',
+ ja: '.ja-catalog-cache.json'
+}
+
+function parseLocaleArg(argv) {
+ const localeFlagIndex = argv.indexOf('--locale')
+ if (localeFlagIndex !== -1 && argv[localeFlagIndex + 1]) {
+ return argv[localeFlagIndex + 1]
+ }
+ return undefined
+}
+
+async function loadCache(cachePath) {
+ try {
+ const raw = JSON.parse(await fs.readFile(cachePath, 'utf8'))
+ return new Map(Object.entries(raw))
+ } catch {
+ return new Map()
+ }
+}
+
+async function saveCache(cachePath, cache) {
+ const raw = Object.fromEntries([...cache.entries()].sort(([a], [b]) => a.localeCompare(b)))
+ await fs.writeFile(cachePath, `${JSON.stringify(raw, null, 2)}\n`, 'utf8')
+}
+
+export async function repairLocale(root, locale) {
+ const enPath = path.join(root, LOCALES_DIR, 'en.json')
+ const localePath = path.join(root, LOCALES_DIR, `${locale}.json`)
+ const cachePath = path.join(root, LOCALES_DIR, LOCALE_CACHE_FILES[locale])
+
+ const enCatalog = JSON.parse(await fs.readFile(enPath, 'utf8'))
+ const localeCatalog = JSON.parse(await fs.readFile(localePath, 'utf8'))
+ const cache = await loadCache(cachePath)
+
+ const catalogRepairs = repairCatalog(enCatalog, localeCatalog, locale)
+ const cacheRepairs = repairCacheMap(cache, locale)
+
+ await fs.writeFile(localePath, `${JSON.stringify(localeCatalog, null, 2)}\n`, 'utf8')
+ await saveCache(cachePath, cache)
+
+ console.log(`Repaired ${locale}.json (${catalogRepairs} leaf updates)`)
+ console.log(`Repaired ${LOCALE_CACHE_FILES[locale]} (${cacheRepairs} cache updates)`)
+ return { catalogRepairs, cacheRepairs }
+}
+
+export async function main(root = process.cwd(), locale = parseLocaleArg(process.argv)) {
+ const locales = locale ? [locale] : ['ko', 'zh', 'ja']
+ const unsupported = locales.filter((code) => !LOCALE_CACHE_FILES[code])
+ if (unsupported.length > 0) {
+ console.error(`Unsupported locale(s): ${unsupported.join(', ')}`)
+ return 1
+ }
+
+ for (const code of locales) {
+ await repairLocale(root, code)
+ }
+
+ return 0
+}
+
+if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
+ process.exit(await main())
+}
diff --git a/config/scripts/verify-localization-catalog.mjs b/config/scripts/verify-localization-catalog.mjs
index 4efb9eda137..ed67d13176d 100644
--- a/config/scripts/verify-localization-catalog.mjs
+++ b/config/scripts/verify-localization-catalog.mjs
@@ -8,6 +8,7 @@ import ts from 'typescript'
const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts'])
const SKIP_PATH_PARTS = new Set(['.git', 'dist', 'node_modules', 'out', '__snapshots__', 'assets'])
const LOCALIZATION_FUNCTION_NAMES = new Set(['t', 'translate', 'translateMain'])
+const PLACEHOLDER_RE = /\{\{[^}]+\}\}/g
function normalizePath(root, filePath) {
return path.relative(root, filePath).split(path.sep).join('/')
@@ -121,8 +122,92 @@ function formatMissingReferences(missing) {
.join('\n')
}
+function formatMissingKeys(label, keys) {
+ return keys.map((key) => `${label}: ${key}`).join('\n')
+}
+
+function collectInterpolationVariables(value) {
+ if (typeof value === 'string') {
+ const matches = value.match(PLACEHOLDER_RE) ?? []
+ return [...matches].sort()
+ }
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
+ return []
+ }
+ return Object.values(value).flatMap((child) => collectInterpolationVariables(child))
+}
+
+function flattenCatalogEntries(value, prefix = '', entries = new Map()) {
+ if (typeof value === 'string') {
+ entries.set(prefix, value)
+ return entries
+ }
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
+ return entries
+ }
+ for (const [key, child] of Object.entries(value)) {
+ flattenCatalogEntries(child, prefix ? `${prefix}.${key}` : key, entries)
+ }
+ return entries
+}
+
+function verifyLocaleParity(enCatalog, localeName, localeCatalog) {
+ const enEntries = flattenCatalogEntries(enCatalog)
+ const localeEntries = flattenCatalogEntries(localeCatalog)
+ const missingInLocale = [...enEntries.keys()].filter((key) => !localeEntries.has(key))
+ const extraInLocale = [...localeEntries.keys()].filter((key) => !enEntries.has(key))
+ const interpolationMismatches = []
+
+ for (const key of enEntries.keys()) {
+ if (!localeEntries.has(key)) {
+ continue
+ }
+ const enVariables = collectInterpolationVariables(enEntries.get(key))
+ const localeVariables = collectInterpolationVariables(localeEntries.get(key))
+ if (enVariables.join('|') !== localeVariables.join('|')) {
+ interpolationMismatches.push(key)
+ }
+ }
+
+ if (
+ missingInLocale.length > 0 ||
+ extraInLocale.length > 0 ||
+ interpolationMismatches.length > 0
+ ) {
+ console.error(`Locale catalog parity failed for ${localeName}.json.`)
+ if (missingInLocale.length > 0) {
+ console.error('')
+ console.error(formatMissingKeys('missing', missingInLocale.slice(0, 20)))
+ if (missingInLocale.length > 20) {
+ console.error(`...and ${missingInLocale.length - 20} more missing keys`)
+ }
+ }
+ if (extraInLocale.length > 0) {
+ console.error('')
+ console.error(formatMissingKeys('extra', extraInLocale.slice(0, 20)))
+ if (extraInLocale.length > 20) {
+ console.error(`...and ${extraInLocale.length - 20} more extra keys`)
+ }
+ }
+ if (interpolationMismatches.length > 0) {
+ console.error('')
+ console.error(
+ formatMissingKeys('interpolation mismatch', interpolationMismatches.slice(0, 20))
+ )
+ if (interpolationMismatches.length > 20) {
+ console.error(`...and ${interpolationMismatches.length - 20} more interpolation mismatches`)
+ }
+ }
+ return 1
+ }
+
+ console.log(`Verified locale parity for ${localeName}.json (${localeEntries.size} keys).`)
+ return 0
+}
+
export async function main(root = process.cwd()) {
- const catalogPath = path.join(root, 'src', 'renderer', 'src', 'i18n', 'locales', 'en.json')
+ const localesDir = path.join(root, 'src', 'renderer', 'src', 'i18n', 'locales')
+ const catalogPath = path.join(localesDir, 'en.json')
const catalog = JSON.parse(await fs.readFile(catalogPath, 'utf8'))
const catalogKeys = new Set(flattenCatalogKeys(catalog))
const sourceRoots = [path.join(root, 'src', 'renderer', 'src'), path.join(root, 'src', 'main')]
@@ -146,6 +231,27 @@ export async function main(root = process.cwd()) {
}
console.log(`Verified ${references.length} localization key references against en.json.`)
+
+ const localeFiles = (await fs.readdir(localesDir))
+ .filter(
+ (fileName) =>
+ fileName.endsWith('.json') &&
+ fileName !== 'en.json' &&
+ !fileName.startsWith('.') &&
+ !fileName.includes('-catalog-cache')
+ )
+ .sort()
+
+ for (const fileName of localeFiles) {
+ const localeName = fileName.replace(/\.json$/, '')
+ const localeCatalogPath = path.join(localesDir, fileName)
+ const localeCatalog = JSON.parse(await fs.readFile(localeCatalogPath, 'utf8'))
+ const exitCode = verifyLocaleParity(catalog, localeName, localeCatalog)
+ if (exitCode !== 0) {
+ return exitCode
+ }
+ }
+
return 0
}
diff --git a/package.json b/package.json
index 76cc845fc73..cf31766093a 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,11 @@
"verify:computer-native": "node config/scripts/verify-computer-native.mjs",
"verify:cli-bin": "node config/scripts/verify-cli-bin.mjs",
"verify:localization-catalog": "node config/scripts/verify-localization-catalog.mjs",
+ "bootstrap:locale-catalog": "node config/scripts/bootstrap-locale-catalog.mjs",
+ "bootstrap:zh-catalog": "node config/scripts/bootstrap-zh-catalog.mjs",
+ "bootstrap:ko-catalog": "node config/scripts/bootstrap-locale-catalog.mjs --locale ko",
+ "bootstrap:ja-catalog": "node config/scripts/bootstrap-locale-catalog.mjs --locale ja",
+ "repair:locale-catalog": "node config/scripts/repair-locale-catalog.mjs",
"verify:localization-coverage": "node config/scripts/audit-localization-coverage.mjs --check",
"audit:localization": "node config/scripts/audit-localization-coverage.mjs",
"build:cli": "tsc -p config/tsconfig.cli.json --outDir out --composite false --incremental false && node config/scripts/verify-cli-bin.mjs --fix-executable && node config/scripts/install-dev-cli.mjs",
diff --git a/src/main/i18n/main-i18n.ts b/src/main/i18n/main-i18n.ts
index d7d438f8c84..bcc56fc1eb6 100644
--- a/src/main/i18n/main-i18n.ts
+++ b/src/main/i18n/main-i18n.ts
@@ -2,6 +2,9 @@ import { app } from 'electron'
import i18next, { type i18n as I18nInstance, type TOptions } from 'i18next'
import en from '../../renderer/src/i18n/locales/en.json'
+import ja from '../../renderer/src/i18n/locales/ja.json'
+import ko from '../../renderer/src/i18n/locales/ko.json'
+import zh from '../../renderer/src/i18n/locales/zh.json'
import { isPseudoLocalizationLocale, pseudoLocalizeString } from '../../shared/pseudo-localization'
import { DEFAULT_UI_LOCALE, resolveUiLocale, type SupportedUiLocale } from '../../shared/ui-locale'
import { UI_LANGUAGE_SYSTEM, type UiLanguage } from '../../shared/ui-language'
@@ -26,6 +29,15 @@ export async function ensureMainI18n(): Promise {
resources: {
en: {
translation: en
+ },
+ zh: {
+ translation: zh
+ },
+ ko: {
+ translation: ko
+ },
+ ja: {
+ translation: ja
}
},
interpolation: {
diff --git a/src/renderer/src/components/feature-wall/AgentCapabilitiesSetupAction.tsx b/src/renderer/src/components/feature-wall/AgentCapabilitiesSetupAction.tsx
index df919cdc45e..2e79dc2bb2c 100644
--- a/src/renderer/src/components/feature-wall/AgentCapabilitiesSetupAction.tsx
+++ b/src/renderer/src/components/feature-wall/AgentCapabilitiesSetupAction.tsx
@@ -76,17 +76,37 @@ export function AgentCapabilitiesSetupAction(props: {
}
const firstWarning = result.warnings[0]
if (firstWarning) {
- toast.warning(translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.1aa657d8f4", "Some capability setup needs attention"), {
- description: firstWarning.message
- })
+ toast.warning(
+ translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.1aa657d8f4',
+ 'Some capability setup needs attention'
+ ),
+ {
+ description: firstWarning.message
+ }
+ )
}
if (result.skillCommandsCopied) {
- toast.success(translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.c605f51f2b", "Capability setup ready"), {
- description: translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.3a59452a67", "Skill command copied and inserted below for review.")
- })
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.c605f51f2b',
+ 'Capability setup ready'
+ ),
+ {
+ description: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.3a59452a67',
+ 'Skill command copied and inserted below for review.'
+ )
+ }
+ )
}
if (result.computerUsePermissionsOpened) {
- toast.message(translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.e9eb197e12", "Opened Computer Use permissions"))
+ toast.message(
+ translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.e9eb197e12',
+ 'Opened Computer Use permissions'
+ )
+ )
}
if (result.skillInstallCommand) {
setFeatureSetupCommandSelection(featureSetup)
@@ -122,23 +142,38 @@ type AgentCapabilitySetupRow = {
const AGENT_CAPABILITY_SETUP_ROWS: readonly AgentCapabilitySetupRow[] = [
{
id: 'orchestration',
- title: translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.ac07f8887f", "Agent Orchestration"),
- description:
- translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.c61c91e642", "Let agents coordinate through Orca to keep large, multi-step tasks moving to completion."),
+ title: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.ac07f8887f',
+ 'Agent Orchestration'
+ ),
+ description: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.c61c91e642',
+ 'Let agents coordinate through Orca to keep large, multi-step tasks moving to completion.'
+ ),
icon:
},
{
id: 'browserUse',
- title: translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.e638da007a", "Agent Browser Use"),
- description:
- translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.5e8fe5a72d", "Give agents direct access to Orca's browser so they can test pages, capture screenshots, and act on what they see."),
+ title: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.e638da007a',
+ 'Agent Browser Use'
+ ),
+ description: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.5e8fe5a72d',
+ "Give agents direct access to Orca's browser so they can test pages, capture screenshots, and act on what they see."
+ ),
icon:
},
{
id: 'computerUse',
- title: translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.362a07517d", "Computer Use"),
- description:
- translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.1b51644c2d", "Let agents control the desktop, moving the cursor, clicking, and typing in any app."),
+ title: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.362a07517d',
+ 'Computer Use'
+ ),
+ description: translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.1b51644c2d',
+ 'Let agents control the desktop, moving the cursor, clicking, and typing in any app.'
+ ),
icon:
}
]
@@ -176,7 +211,11 @@ function AgentCapabilitySetupControls(props: {
) : (
)}
- {props.setupBusyLabel ?? translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.c89534cbe9", "Install CLI & Skills")}
+ {props.setupBusyLabel ??
+ translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.c89534cbe9',
+ 'Install CLI & Skills'
+ )}
) : null}
@@ -260,8 +299,12 @@ function AgentCapabilityStatusNote(props: {
return (
- {translate("auto.components.feature.wall.AgentCapabilitiesSetupAction.b8dc9dd8a2", "Installed")}
- {props.status.label !== "Installed" ? (
+ {translate(
+ 'auto.components.feature.wall.AgentCapabilitiesSetupAction.b8dc9dd8a2',
+ 'Installed'
+ )}
+
+ {props.status.tone !== 'ready' ? (
-
- {AGENT_AWAKE_TITLE}
-
+
{title}
- {translate("auto.components.feature.wall.KeepAwakeCard.209713d3c7", "Optional")}
+ {translate('auto.components.feature.wall.KeepAwakeCard.209713d3c7', 'Optional')}
+
{getAgentAwakeDescription()}
@@ -27,7 +27,7 @@ export function KeepAwakeCard(props: {
updateSettings({ keepComputerAwakeWhileAgentsRun: !enabled })}
className={cn(
diff --git a/src/renderer/src/components/feature-wall/agent-capability-setup-status.ts b/src/renderer/src/components/feature-wall/agent-capability-setup-status.ts
index 5c16d7ba889..75606684b1e 100644
--- a/src/renderer/src/components/feature-wall/agent-capability-setup-status.ts
+++ b/src/renderer/src/components/feature-wall/agent-capability-setup-status.ts
@@ -128,15 +128,40 @@ function getSkillInstallStatus(skill: {
error: string | null
}): AgentCapabilityInstallStatus {
if (skill.loading) {
- return { label: translate("auto.components.feature.wall.agent.capability.setup.status.9b33e7fb13", "Checking install"), tone: 'checking' }
+ return {
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.9b33e7fb13',
+ 'Checking install'
+ ),
+ tone: 'checking'
+ }
}
if (skill.error) {
- return { label: translate("auto.components.feature.wall.agent.capability.setup.status.aa8e143a2f", "Could not check install"), tone: 'error' }
+ return {
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.aa8e143a2f',
+ 'Could not check install'
+ ),
+ tone: 'error'
+ }
}
if (skill.installed) {
- return { label: translate("auto.components.feature.wall.agent.capability.setup.status.8eccfcb314", "Installed"), tone: 'ready', installed: true }
+ return {
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.8eccfcb314',
+ 'Installed'
+ ),
+ tone: 'ready',
+ installed: true
+ }
+ }
+ return {
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.aae94eeb52',
+ 'Click Install CLI & Skills'
+ ),
+ tone: 'pending'
}
- return { label: translate("auto.components.feature.wall.agent.capability.setup.status.aae94eeb52", "Click Install CLI & Skills"), tone: 'pending' }
}
function getComputerUseInstallStatus(
@@ -156,26 +181,49 @@ function getComputerUseInstallStatus(
return skillStatus
}
if (permissions.checking) {
- return { label: translate("auto.components.feature.wall.agent.capability.setup.status.5c9293e51a", "checking app access"), tone: 'checking', installed: true }
+ return {
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.5c9293e51a',
+ 'checking app access'
+ ),
+ tone: 'checking',
+ installed: true
+ }
}
if (permissions.unavailableReason) {
return {
label:
permissions.unavailableReason === 'web_client'
- ? 'open Orca Desktop on this Mac'
- : 'Unavailable in this build',
+ ? translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.4c8e1f92a7',
+ 'open Orca Desktop on this Mac'
+ )
+ : translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.6d2b0a84e1',
+ 'Unavailable in this build'
+ ),
tone: 'pending',
installed: true
}
}
if (!permissions.ready) {
return {
- label: translate("auto.components.feature.wall.agent.capability.setup.status.21d4f79c93", "click Install CLI & Skills to open macOS access settings"),
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.21d4f79c93',
+ 'click Install CLI & Skills to open macOS access settings'
+ ),
tone: 'pending',
installed: true
}
}
- return { label: translate("auto.components.feature.wall.agent.capability.setup.status.8eccfcb314", "Installed"), tone: 'ready', installed: true }
+ return {
+ label: translate(
+ 'auto.components.feature.wall.agent.capability.setup.status.8eccfcb314',
+ 'Installed'
+ ),
+ tone: 'ready',
+ installed: true
+ }
}
function useComputerUsePermissionStatus(enabled: boolean): {
diff --git a/src/renderer/src/components/settings/AgentAwakeSetting.tsx b/src/renderer/src/components/settings/AgentAwakeSetting.tsx
index a7ac76e53a0..66e56c32aa2 100644
--- a/src/renderer/src/components/settings/AgentAwakeSetting.tsx
+++ b/src/renderer/src/components/settings/AgentAwakeSetting.tsx
@@ -1,9 +1,9 @@
import type { GlobalSettings } from '../../../../shared/types'
import { Label } from '../ui/label'
import {
- AGENT_AWAKE_TITLE,
getAgentAwakeDescription,
- getAgentAwakeSearchKeywords
+ getAgentAwakeSearchKeywords,
+ getAgentAwakeTitle
} from './agent-awake-copy'
import { SearchableSetting } from './SearchableSetting'
@@ -16,18 +16,19 @@ export function AgentAwakeSetting({
settings,
updateSettings
}: AgentAwakeSettingProps): React.JSX.Element {
+ const title = getAgentAwakeTitle()
const description = getAgentAwakeDescription()
return (
-
{AGENT_AWAKE_TITLE}
+
{title}
{description}
{/* Why: this button is read directly from the React element tree by tests
@@ -36,7 +37,7 @@ export function AgentAwakeSetting({
updateSettings({
diff --git a/src/renderer/src/components/settings/AgentsPane.test.tsx b/src/renderer/src/components/settings/AgentsPane.test.tsx
index 3c6b032b48c..4a65bc68e7c 100644
--- a/src/renderer/src/components/settings/AgentsPane.test.tsx
+++ b/src/renderer/src/components/settings/AgentsPane.test.tsx
@@ -7,9 +7,9 @@ import { getDefaultSettings } from '../../../../shared/constants'
import type { GlobalSettings, TuiAgent } from '../../../../shared/types'
import { AGENT_CATALOG } from '@/lib/agent-catalog'
import { useAppStore } from '../../store'
-import { AGENT_GENERATED_TAB_TITLES_TITLE } from './agent-generated-tab-title-copy'
-import { AGENT_STATUS_HOOKS_TITLE } from './agent-status-hooks-copy'
-import { getAgentAwakeDescription } from './agent-awake-copy'
+import { getAgentGeneratedTabTitlesTitle } from './agent-generated-tab-title-copy'
+import { getAgentStatusHooksTitle } from './agent-status-hooks-copy'
+import { getAgentAwakeDescription, getAgentAwakeTitle } from './agent-awake-copy'
import { AgentAwakeSetting } from './AgentAwakeSetting'
import {
AgentAvailabilityControl,
@@ -182,8 +182,9 @@ describe('AgentsPane', () => {
updateSettings
})
- const keepAwakeSwitch = findSwitch(element, 'Keep computer awake while agents are working')
- expect(keepAwakeSwitch.props['aria-label']).toBe('Keep computer awake while agents are working')
+ const keepAwakeTitle = getAgentAwakeTitle()
+ const keepAwakeSwitch = findSwitch(element, keepAwakeTitle)
+ expect(keepAwakeSwitch.props['aria-label']).toBe(keepAwakeTitle)
expect(keepAwakeSwitch.props['aria-checked']).toBe(false)
const onClick = keepAwakeSwitch.props.onClick as () => void
@@ -204,7 +205,7 @@ describe('AgentsPane', () => {
updateSettings
})
- const statusSwitch = findSwitchRow(element, AGENT_STATUS_HOOKS_TITLE)
+ const statusSwitch = findSwitchRow(element, getAgentStatusHooksTitle())
expect(statusSwitch.props.checked).toBe(true)
const onChange = statusSwitch.props.onChange as () => void
@@ -225,7 +226,7 @@ describe('AgentsPane', () => {
updateSettings
})
- const generatedTitleSwitch = findSwitchRow(element, AGENT_GENERATED_TAB_TITLES_TITLE)
+ const generatedTitleSwitch = findSwitchRow(element, getAgentGeneratedTabTitlesTitle())
expect(generatedTitleSwitch.props.checked).toBe(false)
const onChange = generatedTitleSwitch.props.onChange as () => void
diff --git a/src/renderer/src/components/settings/AgentsPane.tsx b/src/renderer/src/components/settings/AgentsPane.tsx
index 06f4dd32eef..234565bf4d5 100644
--- a/src/renderer/src/components/settings/AgentsPane.tsx
+++ b/src/renderer/src/components/settings/AgentsPane.tsx
@@ -12,11 +12,11 @@ import { Input } from '../ui/input'
import { cn } from '@/lib/utils'
import { AgentAwakeSetting } from './AgentAwakeSetting'
import {
- AGENT_GENERATED_TAB_TITLES_DESCRIPTION,
- AGENT_GENERATED_TAB_TITLES_TITLE
+ getAgentGeneratedTabTitlesDescription,
+ getAgentGeneratedTabTitlesTitle
} from './agent-generated-tab-title-copy'
import { AgentLocationSetting } from './AgentLocationSetting'
-import { AGENT_STATUS_HOOKS_DESCRIPTION, AGENT_STATUS_HOOKS_TITLE } from './agent-status-hooks-copy'
+import { getAgentStatusHooksDescription, getAgentStatusHooksTitle } from './agent-status-hooks-copy'
import {
SettingsBadge,
SettingsSegmentedControl,
@@ -646,15 +646,15 @@ export function AgentStatusHooksSetting({
return (
updateSettings({
agentStatusHooksEnabled: !enabled
})
}
- ariaLabel={AGENT_STATUS_HOOKS_TITLE}
+ ariaLabel={getAgentStatusHooksTitle()}
/>
)
@@ -668,15 +668,15 @@ export function AgentGeneratedTabTitlesSetting({
return (
updateSettings({
tabAutoGenerateTitle: !enabled
})
}
- ariaLabel={AGENT_GENERATED_TAB_TITLES_TITLE}
+ ariaLabel={getAgentGeneratedTabTitlesTitle()}
/>
)
diff --git a/src/renderer/src/components/settings/AppearancePane.test.tsx b/src/renderer/src/components/settings/AppearancePane.test.tsx
index 8c7467a2f11..7691b292ac7 100644
--- a/src/renderer/src/components/settings/AppearancePane.test.tsx
+++ b/src/renderer/src/components/settings/AppearancePane.test.tsx
@@ -33,6 +33,57 @@ vi.mock('./TerminalAppearanceSection', () => ({
TerminalAppearanceSection: () => null
}))
+vi.mock('../ui/select', async () => {
+ const React = await import('react')
+
+ const SelectContext = React.createContext<{
+ onValueChange?: (value: string) => void
+ }>({})
+
+ return {
+ Select: ({
+ value,
+ onValueChange,
+ children
+ }: {
+ value: string
+ onValueChange: (value: string) => void
+ children: React.ReactNode
+ }) => {
+ const contextValue = React.useMemo(() => ({ onValueChange }), [onValueChange])
+ return (
+
+
+ {children}
+
+
+ )
+ },
+ SelectTrigger: ({ children, ...props }: React.ComponentProps<'button'> & { size?: string }) => (
+
+ {children}
+
+ ),
+ SelectValue: () => null,
+ SelectContent: ({ children }: { children: React.ReactNode }) => (
+ {children}
+ ),
+ SelectItem: ({ value, children }: { value: string; children: React.ReactNode }) => {
+ const { onValueChange } = React.useContext(SelectContext)
+ return (
+ onValueChange?.(value)}
+ >
+ {children}
+
+ )
+ }
+ }
+})
+
import { AppearancePane } from './AppearancePane'
const mountedRoots: Root[] = []
@@ -92,8 +143,7 @@ describe('AppearancePane', () => {
mocks.state.settingsSearchQuery = 'automations'
})
- // Re-enable when SHOW_UI_LANGUAGE_SETTING is true (second locale shipped).
- it.skip('renders the language selector with system and english options', async () => {
+ it('renders the language dropdown with system, english, chinese, korean, and japanese options', async () => {
mocks.state.settingsSearchQuery = 'language'
const updateSettings = vi.fn()
const settings = {
@@ -102,25 +152,26 @@ describe('AppearancePane', () => {
}
const container = await renderAppearancePane(settings, updateSettings)
- const languageControl = container.querySelector(
- '[role="radiogroup"][aria-label="Language"]'
+ const languageTrigger = container.querySelector(
+ '[data-slot="select-trigger"][aria-label="Language"]'
+ )
+ const chineseOption = container.querySelector(
+ '[data-slot="select-item"][data-value="zh"]'
)
- expect(languageControl).not.toBeNull()
+ expect(languageTrigger).not.toBeNull()
+ expect(chineseOption).not.toBeNull()
expect(container.textContent).toContain('System')
expect(container.textContent).toContain('English')
-
- const englishOption = Array.from(
- languageControl?.querySelectorAll('button') ?? []
- ).find((button) => button.textContent?.includes('English'))
-
- expect(englishOption).toBeDefined()
+ expect(container.textContent).toContain('中文(简体)')
+ expect(container.textContent).toContain('한국어')
+ expect(container.textContent).toContain('日本語')
await act(async () => {
- englishOption?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
+ chineseOption?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
})
- expect(updateSettings).toHaveBeenCalledWith({ uiLanguage: 'en' })
+ expect(updateSettings).toHaveBeenCalledWith({ uiLanguage: 'zh' })
})
it('restores the Automations sidebar button from the sidebar settings switch', async () => {
diff --git a/src/renderer/src/components/settings/AppearancePane.tsx b/src/renderer/src/components/settings/AppearancePane.tsx
index 18ce1f32039..b3ec84bdca2 100644
--- a/src/renderer/src/components/settings/AppearancePane.tsx
+++ b/src/renderer/src/components/settings/AppearancePane.tsx
@@ -5,6 +5,7 @@ import type React from 'react'
import type { GlobalSettings } from '../../../../shared/types'
import { Separator } from '../ui/separator'
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'
import { UIZoomControl } from './UIZoomControl'
import { SearchableSetting } from './SearchableSetting'
import { matchesSettingsSearch } from './settings-search'
@@ -38,8 +39,13 @@ import { getTerminalAppearanceSearchEntries } from './terminal-search'
import { TerminalAppearanceSection } from './TerminalAppearanceSection'
import type { UseGhosttyImportReturn } from './useGhosttyImport'
import { AppIconSelector } from './AppIconSelector'
-import { SHOW_UI_LANGUAGE_SETTING, UI_LANGUAGE_CHOICES } from '@/i18n/supported-languages'
+import {
+ getUiLanguageChoiceLabel,
+ SHOW_UI_LANGUAGE_SETTING,
+ UI_LANGUAGE_CHOICES
+} from '@/i18n/supported-languages'
import { translate } from '@/i18n/i18n'
+import type { UiLanguage } from '../../../../shared/ui-language'
export { getAppearancePaneSearchEntries }
type AppearancePaneProps = {
@@ -165,15 +171,25 @@ export function AppearancePane({
'Choose the language used by the Orca interface.'
)}
control={
- updateSettings({ uiLanguage: value })}
- options={UI_LANGUAGE_CHOICES.map((choice) => ({
- value: choice.value,
- label: translate(choice.labelKey, choice.value === 'en' ? 'English' : 'System')
- }))}
- />
+ onValueChange={(value) => updateSettings({ uiLanguage: value as UiLanguage })}
+ >
+
+
+
+
+ {UI_LANGUAGE_CHOICES.map((choice) => (
+
+ {getUiLanguageChoiceLabel(choice, translate)}
+
+ ))}
+
+
}
/>
diff --git a/src/renderer/src/components/settings/MobileEmulatorSettingsPane.tsx b/src/renderer/src/components/settings/MobileEmulatorSettingsPane.tsx
index 6d53f03810c..c8dc0221acb 100644
--- a/src/renderer/src/components/settings/MobileEmulatorSettingsPane.tsx
+++ b/src/renderer/src/components/settings/MobileEmulatorSettingsPane.tsx
@@ -40,12 +40,17 @@ const SIMULATOR_STATE_SUFFIX_RE =
function statusText(availability: EmulatorAvailability | null, enabled: boolean): string {
if (!enabled) {
- return 'Disabled'
+ return translate('auto.components.settings.MobileEmulatorSettingsPane.a4f1c82d90', 'Disabled')
}
if (!availability) {
- return 'Checking'
+ return translate(
+ 'auto.components.settings.MobileEmulatorSettingsPane.b5e2d93e01',
+ 'Checking...'
+ )
}
- return availability.available ? 'Ready' : 'Needs setup'
+ return availability.available
+ ? translate('auto.components.settings.MobileEmulatorSettingsPane.c6f3ea4f12', 'Ready')
+ : translate('auto.components.settings.MobileEmulatorSettingsPane.d704fb5023', 'Needs setup')
}
function statusBadgeClassName(availability: EmulatorAvailability | null, enabled: boolean): string {
diff --git a/src/renderer/src/components/settings/Settings.tsx b/src/renderer/src/components/settings/Settings.tsx
index f4db1d13b18..1fa6703d4b1 100644
--- a/src/renderer/src/components/settings/Settings.tsx
+++ b/src/renderer/src/components/settings/Settings.tsx
@@ -86,14 +86,32 @@ import {
import { translate } from '@/i18n/i18n'
const SETTINGS_NAV_GROUPS = [
- { id: 'capabilities', title: translate("auto.components.settings.Settings.23c6874fdf", "AI Capabilities") },
- { id: 'setup', title: translate("auto.components.settings.Settings.9abb9be3bc", "Set Up") },
- { id: 'workflows', title: translate("auto.components.settings.Settings.e1578cd4bc", "Workflows") },
- { id: 'interface', title: translate("auto.components.settings.Settings.8bd117d669", "Interface") },
- { id: 'remote', title: translate("auto.components.settings.Settings.23931df7e8", "Remote Access") },
- { id: 'security', title: translate("auto.components.settings.Settings.084d8fac5b", "Privacy & Security") },
- { id: 'advanced', title: translate("auto.components.settings.Settings.1c87f8d024", "Advanced") },
- { id: 'experimental', title: translate("auto.components.settings.Settings.8b017f2506", "Experimental") }
+ {
+ id: 'capabilities',
+ title: translate('auto.components.settings.Settings.23c6874fdf', 'AI Capabilities')
+ },
+ { id: 'setup', title: translate('auto.components.settings.Settings.9abb9be3bc', 'Set Up') },
+ {
+ id: 'workflows',
+ title: translate('auto.components.settings.Settings.e1578cd4bc', 'Workflows')
+ },
+ {
+ id: 'interface',
+ title: translate('auto.components.settings.Settings.8bd117d669', 'Interface')
+ },
+ {
+ id: 'remote',
+ title: translate('auto.components.settings.Settings.23931df7e8', 'Remote Access')
+ },
+ {
+ id: 'security',
+ title: translate('auto.components.settings.Settings.084d8fac5b', 'Privacy & Security')
+ },
+ { id: 'advanced', title: translate('auto.components.settings.Settings.1c87f8d024', 'Advanced') },
+ {
+ id: 'experimental',
+ title: translate('auto.components.settings.Settings.8b017f2506', 'Experimental')
+ }
] as const
const SHORTCUTS_ESCAPE_CONFIRM_TOAST_ID = 'shortcuts-escape-confirm'
@@ -309,9 +327,15 @@ function Settings(): React.JSX.Element {
return true
}
const shouldDiscard = await confirm({
- title: translate("auto.components.settings.Settings.17bdee4ff1", "Discard unsaved Git AI Author changes?"),
- description: translate("auto.components.settings.Settings.43b68e10f0", "You have unsaved Git AI Author changes. Leaving will discard them."),
- confirmLabel: translate("auto.components.settings.Settings.65358016ea", "Discard"),
+ title: translate(
+ 'auto.components.settings.Settings.17bdee4ff1',
+ 'Discard unsaved Git AI Author changes?'
+ ),
+ description: translate(
+ 'auto.components.settings.Settings.43b68e10f0',
+ 'You have unsaved Git AI Author changes. Leaving will discard them.'
+ ),
+ confirmLabel: translate('auto.components.settings.Settings.65358016ea', 'Discard'),
confirmVariant: 'destructive'
})
if (shouldDiscard) {
@@ -401,11 +425,17 @@ function Settings(): React.JSX.Element {
return
}
shortcutsEscapeConfirmUntilRef.current = now + SHORTCUTS_ESCAPE_CONFIRM_WINDOW_MS
- toast.info(translate("auto.components.settings.Settings.acc7bbdefd", "Press ESC again to exit settings"), {
- id: SHORTCUTS_ESCAPE_CONFIRM_TOAST_ID,
- duration: SHORTCUTS_ESCAPE_CONFIRM_WINDOW_MS,
- className: 'whitespace-nowrap'
- })
+ toast.info(
+ translate(
+ 'auto.components.settings.Settings.acc7bbdefd',
+ 'Press ESC again to exit settings'
+ ),
+ {
+ id: SHORTCUTS_ESCAPE_CONFIRM_TOAST_ID,
+ duration: SHORTCUTS_ESCAPE_CONFIRM_WINDOW_MS,
+ className: 'whitespace-nowrap'
+ }
+ )
return
}
void closeSettingsPageWithPromptGuard()
@@ -857,7 +887,8 @@ function Settings(): React.JSX.Element {
className="settings-view-shell flex min-h-0 flex-1 overflow-hidden bg-background"
>
- {translate("auto.components.settings.Settings.c7ad095d96", "Loading settings...")}
+ {translate('auto.components.settings.Settings.c7ad095d96', 'Loading settings...')}
+
)
}
@@ -919,13 +950,22 @@ function Settings(): React.JSX.Element {
>
{visibleNavSections.length === 0 ? (
- {translate("auto.components.settings.Settings.3c88ec55d6", "No settings found for \"")}{settingsSearchQuery.trim()}{translate("auto.components.settings.Settings.add3b97ee6", "\"")}
+ {translate(
+ 'auto.components.settings.Settings.3c88ec55d6',
+ 'No settings found for "'
+ )}
+ {settingsSearchQuery.trim()}
+ {translate('auto.components.settings.Settings.add3b97ee6', '"')}
+
) : (
{isSectionMounted('agents') ? (
@@ -942,9 +982,18 @@ function Settings(): React.JSX.Element {
{isSectionMounted('accounts') ? (
@@ -961,8 +1010,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('orchestration') ? : null}
@@ -972,8 +1024,14 @@ function Settings(): React.JSX.Element {
<>
{isSectionMounted('computer-use') ? : null}
@@ -981,8 +1039,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('voice') ? (
@@ -994,8 +1055,14 @@ function Settings(): React.JSX.Element {
@@ -1004,8 +1071,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('general') ? (
@@ -1021,8 +1091,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('integrations') ? : null}
@@ -1030,8 +1103,14 @@ function Settings(): React.JSX.Element {
@@ -1061,8 +1140,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('tasks') ? (
@@ -1072,8 +1154,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('terminal') ? (
@@ -1094,8 +1179,14 @@ function Settings(): React.JSX.Element {
{isSectionMounted('quick-commands') ? (
@@ -1110,8 +1201,11 @@ function Settings(): React.JSX.Element {
{showDesktopOnlySettings ? (
{isSectionMounted('browser') ? (
@@ -1127,8 +1221,14 @@ function Settings(): React.JSX.Element {
{showDesktopOnlySettings && isMac ? (
{isSectionMounted('mobile-emulator') ? (
@@ -1142,8 +1242,14 @@ function Settings(): React.JSX.Element {
{isSectionMounted('floating-workspace') ? (
@@ -1153,8 +1259,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('appearance') ? (
@@ -1174,8 +1283,14 @@ function Settings(): React.JSX.Element {
@@ -1184,8 +1299,14 @@ function Settings(): React.JSX.Element {
{showDesktopOnlySettings ? (
{isSectionMounted('notifications') ? (
@@ -1196,8 +1317,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('stats') ? : null}
@@ -1222,12 +1349,21 @@ function Settings(): React.JSX.Element {
@@ -1245,8 +1381,11 @@ function Settings(): React.JSX.Element {
<>
{isSectionMounted('ssh') ? : null}
@@ -1254,9 +1393,12 @@ function Settings(): React.JSX.Element {
{isSectionMounted('mobile') ? (
@@ -1269,8 +1411,14 @@ function Settings(): React.JSX.Element {
{showDesktopOnlySettings && isMac ? (
{isSectionMounted('developer-permissions') ? (
@@ -1281,8 +1429,14 @@ function Settings(): React.JSX.Element {
{isSectionMounted('privacy') ? : null}
@@ -1291,8 +1445,11 @@ function Settings(): React.JSX.Element {
{showDesktopOnlySettings ? (
{isSectionMounted('advanced') ? (
@@ -1303,8 +1460,11 @@ function Settings(): React.JSX.Element {
{isSectionMounted('experimental') ? (
@@ -1324,7 +1484,11 @@ function Settings(): React.JSX.Element {
{{value0}}", { value0: repo.displayName })}
+ title={translate(
+ 'auto.components.settings.Settings.3bf149e873',
+ 'Project Settings > {{value0}}',
+ { value0: repo.displayName }
+ )}
description={repo.path}
searchEntries={getSectionSearchEntries(repoSectionId)}
>
diff --git a/src/renderer/src/components/settings/SettingsSidebar.tsx b/src/renderer/src/components/settings/SettingsSidebar.tsx
index f609f67447a..6fa13381a67 100644
--- a/src/renderer/src/components/settings/SettingsSidebar.tsx
+++ b/src/renderer/src/components/settings/SettingsSidebar.tsx
@@ -75,7 +75,11 @@ function SettingsSetupGuideNavRow({
onSelect({
metaKey: event.metaKey,
@@ -98,7 +102,9 @@ function SettingsSetupGuideNavRow({
tooltipLabel={`${progress.doneCount}/${progress.total} complete`}
/>
- {translate("auto.components.settings.SettingsSidebar.6503182299", "Onboarding checklist")}
+
+ {translate('auto.components.settings.SettingsSidebar.6503182299', 'Onboarding checklist')}
+
)
@@ -132,11 +138,14 @@ export function SettingsSidebar({
const installStatusLabel = (status: SettingsNavInstallStatus): string => {
switch (status) {
case 'install':
- return 'Not installed'
+ return translate(
+ 'auto.components.settings.AgentSkillSetupPanel.5289300939',
+ 'Not installed'
+ )
case 'installed':
- return 'Installed'
+ return translate('auto.components.settings.AgentSkillSetupPanel.9fcebceb2a', 'Installed')
case 'checking':
- return 'Checking'
+ return translate('auto.components.settings.AgentSkillSetupPanel.68a468752e', 'Checking...')
}
}
const installStatusClassName = (status: SettingsNavInstallStatus): string =>
@@ -159,7 +168,8 @@ export function SettingsSidebar({
className="w-full justify-start gap-2 text-[13px] text-muted-foreground"
>
- {translate("auto.components.settings.SettingsSidebar.60f8a673a7", "Back to app")}
+ {translate('auto.components.settings.SettingsSidebar.60f8a673a7', 'Back to app')}
+
@@ -169,7 +179,10 @@ export function SettingsSidebar({
ref={searchInputRef}
value={searchQuery}
onChange={(event) => onSearchChange(event.target.value)}
- placeholder={translate("auto.components.settings.SettingsSidebar.dbceaa8840", "Search settings")}
+ placeholder={translate(
+ 'auto.components.settings.SettingsSidebar.dbceaa8840',
+ 'Search settings'
+ )}
className="pl-9 pr-14 text-[13px]"
/>
{searchQuery === '' ? (
@@ -239,7 +252,8 @@ export function SettingsSidebar({
- {translate("auto.components.settings.SettingsSidebar.5c9669ff9c", "Projects")}
+ {translate('auto.components.settings.SettingsSidebar.5c9669ff9c', 'Projects')}
+
{repoSections.length > 0 ? (
@@ -272,7 +286,8 @@ export function SettingsSidebar({
{section.isRemote && (
- {translate("auto.components.settings.SettingsSidebar.e0900f83e7", "SSH")}
+ {translate('auto.components.settings.SettingsSidebar.e0900f83e7', 'SSH')}
+
)}
)
@@ -280,7 +295,15 @@ export function SettingsSidebar({
) : (
- {hasRepos ? translate("auto.components.settings.SettingsSidebar.3e483e256b", "No matching project settings.") : translate("auto.components.settings.SettingsSidebar.df38d612b7", "No projects added yet.")}
+ {hasRepos
+ ? translate(
+ 'auto.components.settings.SettingsSidebar.3e483e256b',
+ 'No matching project settings.'
+ )
+ : translate(
+ 'auto.components.settings.SettingsSidebar.df38d612b7',
+ 'No projects added yet.'
+ )}
)}
diff --git a/src/renderer/src/components/settings/accounts-search.ts b/src/renderer/src/components/settings/accounts-search.ts
index 1bf9d775939..1d4e1564553 100644
--- a/src/renderer/src/components/settings/accounts-search.ts
+++ b/src/renderer/src/components/settings/accounts-search.ts
@@ -1,5 +1,6 @@
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getAccountsLocationSearchEntries = createLocalizedCatalog(() => [
@@ -10,13 +11,13 @@ export const getAccountsLocationSearchEntries = createLocalizedCatalog(() => [
'Choose whether provider accounts are inspected and added on this device or in WSL.'
),
keywords: [
- translate('auto.components.settings.accounts.search.06662af91e', 'account'),
- translate('auto.components.settings.accounts.search.593720c17f', 'location'),
- translate('auto.components.settings.accounts.search.bdbd1e668e', 'windows'),
- translate('auto.components.settings.accounts.search.0b4d948eb5', 'wsl'),
- translate('auto.components.settings.accounts.search.488a7e9206', 'linux'),
- translate('auto.components.settings.accounts.search.9f70aa706c', 'provider'),
- translate('auto.components.settings.accounts.search.e02c136ad0', 'auth')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.06662af91e', 'account'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.593720c17f', 'location'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.bdbd1e668e', 'windows'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.0b4d948eb5', 'wsl'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.488a7e9206', 'linux'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.9f70aa706c', 'provider'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.e02c136ad0', 'auth')
]
}
])
@@ -29,13 +30,16 @@ export const getAccountsClaudeSearchEntries = createLocalizedCatalog(() => [
'Optional account switching for Claude while preserving shared chat context.'
),
keywords: [
- translate('auto.components.settings.accounts.search.e14049e1a8', 'claude'),
- translate('auto.components.settings.accounts.search.06662af91e', 'account'),
- translate('auto.components.settings.accounts.search.5b3f18ef4a', 'switch'),
- translate('auto.components.settings.accounts.search.8b06729e0f', 'active'),
- translate('auto.components.settings.accounts.search.86edc96bc9', 'status bar'),
- translate('auto.components.settings.accounts.search.c759741d77', 'quota'),
- translate('auto.components.settings.accounts.search.f2d666a886', 'optional')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.e14049e1a8', 'claude'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.06662af91e', 'account'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.5b3f18ef4a', 'switch'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.8b06729e0f', 'active'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.86edc96bc9',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.c759741d77', 'quota'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.f2d666a886', 'optional')
]
}
])
@@ -48,15 +52,27 @@ export const getAccountsCodexSearchEntries = createLocalizedCatalog(() => [
'Optional account switching for Codex and live rate limit fetching.'
),
keywords: [
- translate('auto.components.settings.accounts.search.70d1b8def5', 'codex'),
- translate('auto.components.settings.accounts.search.06662af91e', 'account'),
- translate('auto.components.settings.accounts.search.e949b08ffb', 'rate limit'),
- translate('auto.components.settings.accounts.search.86edc96bc9', 'status bar'),
- translate('auto.components.settings.accounts.search.c759741d77', 'quota'),
- translate('auto.components.settings.accounts.search.f2d666a886', 'optional'),
- translate('auto.components.settings.accounts.search.77e32a2ad3', 'reauthenticate'),
- translate('auto.components.settings.accounts.search.02c438bc7b', 'expired'),
- translate('auto.components.settings.accounts.search.042885c07c', 'out of date')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.70d1b8def5', 'codex'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.06662af91e', 'account'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.e949b08ffb',
+ 'rate limit'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.86edc96bc9',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.c759741d77', 'quota'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.f2d666a886', 'optional'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.77e32a2ad3',
+ 'reauthenticate'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.02c438bc7b', 'expired'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.042885c07c',
+ 'out of date'
+ )
]
},
{
@@ -66,13 +82,16 @@ export const getAccountsCodexSearchEntries = createLocalizedCatalog(() => [
'Choose which optional saved Codex account powers live quota reads.'
),
keywords: [
- translate('auto.components.settings.accounts.search.70d1b8def5', 'codex'),
- translate('auto.components.settings.accounts.search.06662af91e', 'account'),
- translate('auto.components.settings.accounts.search.5b3f18ef4a', 'switch'),
- translate('auto.components.settings.accounts.search.8b06729e0f', 'active'),
- translate('auto.components.settings.accounts.search.86edc96bc9', 'status bar'),
- translate('auto.components.settings.accounts.search.f2d666a886', 'optional'),
- translate('auto.components.settings.accounts.search.35b461d817', 'sign in')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.70d1b8def5', 'codex'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.06662af91e', 'account'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.5b3f18ef4a', 'switch'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.8b06729e0f', 'active'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.86edc96bc9',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.f2d666a886', 'optional'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.35b461d817', 'sign in')
]
}
])
@@ -88,13 +107,22 @@ export const getAccountsGeminiSearchEntries = createLocalizedCatalog(() => [
'Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google.'
),
keywords: [
- translate('auto.components.settings.accounts.search.e8e1ff3887', 'gemini'),
- translate('auto.components.settings.accounts.search.8630464352', 'cli'),
- translate('auto.components.settings.accounts.search.933deaf732', 'oauth'),
- translate('auto.components.settings.accounts.search.7118d2f908', 'credentials'),
- translate('auto.components.settings.accounts.search.b7c2cee442', 'experimental'),
- translate('auto.components.settings.accounts.search.e949b08ffb', 'rate limit'),
- translate('auto.components.settings.accounts.search.86edc96bc9', 'status bar')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.e8e1ff3887', 'gemini'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.8630464352', 'cli'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.933deaf732', 'oauth'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.7118d2f908',
+ 'credentials'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.b7c2cee442',
+ 'experimental'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.e949b08ffb',
+ 'rate limit'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.86edc96bc9', 'status bar')
]
}
])
@@ -110,11 +138,14 @@ export const getAccountsOpencodeSearchEntries = createLocalizedCatalog(() => [
'Paste your opencode.ai session cookie for rate limit fetching.'
),
keywords: [
- translate('auto.components.settings.accounts.search.8dcbef1856', 'opencode'),
- translate('auto.components.settings.accounts.search.61f7d1fcbe', 'cookie'),
- translate('auto.components.settings.accounts.search.9c4e40cf6b', 'session'),
- translate('auto.components.settings.accounts.search.e949b08ffb', 'rate limit'),
- translate('auto.components.settings.accounts.search.86edc96bc9', 'status bar')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.8dcbef1856', 'opencode'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.61f7d1fcbe', 'cookie'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.9c4e40cf6b', 'session'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.e949b08ffb',
+ 'rate limit'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.86edc96bc9', 'status bar')
]
},
{
@@ -127,12 +158,15 @@ export const getAccountsOpencodeSearchEntries = createLocalizedCatalog(() => [
'Optional workspace ID override if the automatic lookup fails.'
),
keywords: [
- translate('auto.components.settings.accounts.search.8dcbef1856', 'opencode'),
- translate('auto.components.settings.accounts.search.be8b621bdc', 'workspace'),
- translate('auto.components.settings.accounts.search.421c6be25e', 'id'),
- translate('auto.components.settings.accounts.search.7e67d7d1b6', 'wrk'),
- translate('auto.components.settings.accounts.search.e949b08ffb', 'rate limit'),
- translate('auto.components.settings.accounts.search.86edc96bc9', 'status bar')
+ ...translateSearchKeyword('auto.components.settings.accounts.search.8dcbef1856', 'opencode'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.be8b621bdc', 'workspace'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.421c6be25e', 'id'),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.7e67d7d1b6', 'wrk'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.accounts.search.e949b08ffb',
+ 'rate limit'
+ ),
+ ...translateSearchKeyword('auto.components.settings.accounts.search.86edc96bc9', 'status bar')
]
}
])
diff --git a/src/renderer/src/components/settings/advanced-search.ts b/src/renderer/src/components/settings/advanced-search.ts
index dd89337a070..85ab96ffdaf 100644
--- a/src/renderer/src/components/settings/advanced-search.ts
+++ b/src/renderer/src/components/settings/advanced-search.ts
@@ -1,6 +1,7 @@
import type { SettingsSearchEntry } from './settings-search'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
export const getAdvancedPaneSearchEntries = createLocalizedCatalog((): SettingsSearchEntry[] => [
{
@@ -13,21 +14,30 @@ export const getAdvancedPaneSearchEntries = createLocalizedCatalog((): SettingsS
'Use HTTP/1.1 for Electron networking when HTTP/2 fails behind a proxy.'
),
keywords: [
- translate('auto.components.settings.advanced.search.e04e9db503', 'advanced'),
- translate('auto.components.settings.advanced.search.2b4d26d11e', 'networking'),
- translate('auto.components.settings.advanced.search.4d44352eea', 'network'),
- translate('auto.components.settings.advanced.search.48a1c8f534', 'http'),
- translate('auto.components.settings.advanced.search.4b4ae4345a', 'http2'),
- translate('auto.components.settings.advanced.search.a0f71bd909', 'http/2'),
- translate('auto.components.settings.advanced.search.f8ff125ebe', 'http1'),
- translate('auto.components.settings.advanced.search.621233008b', 'http/1.1'),
- translate('auto.components.settings.advanced.search.65bf6af262', 'compatibility'),
- translate('auto.components.settings.advanced.search.f98a60af11', 'proxy'),
- translate('auto.components.settings.advanced.search.4383251647', 'vpn'),
- translate('auto.components.settings.advanced.search.79e0947e95', 'support'),
- translate('auto.components.settings.advanced.search.6576fce4d2', 'troubleshooting'),
- translate('auto.components.settings.advanced.search.e61ed8ab33', 'updates'),
- translate('auto.components.settings.advanced.search.a7002e1ac4', 'updater')
+ ...translateSearchKeyword('auto.components.settings.advanced.search.e04e9db503', 'advanced'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.advanced.search.2b4d26d11e',
+ 'networking'
+ ),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.4d44352eea', 'network'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.48a1c8f534', 'http'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.4b4ae4345a', 'http2'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.a0f71bd909', 'http/2'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.f8ff125ebe', 'http1'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.621233008b', 'http/1.1'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.advanced.search.65bf6af262',
+ 'compatibility'
+ ),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.f98a60af11', 'proxy'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.4383251647', 'vpn'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.79e0947e95', 'support'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.advanced.search.6576fce4d2',
+ 'troubleshooting'
+ ),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.e61ed8ab33', 'updates'),
+ ...translateSearchKeyword('auto.components.settings.advanced.search.a7002e1ac4', 'updater')
]
}
])
diff --git a/src/renderer/src/components/settings/agent-awake-copy.ts b/src/renderer/src/components/settings/agent-awake-copy.ts
index 5eebc51d6a2..10d629b58d1 100644
--- a/src/renderer/src/components/settings/agent-awake-copy.ts
+++ b/src/renderer/src/components/settings/agent-awake-copy.ts
@@ -1,18 +1,50 @@
-export const AGENT_AWAKE_TITLE = 'Keep computer awake while agents are working'
+import { translate } from '@/i18n/i18n'
+import { searchKeywords } from './settings-search-keywords'
+
+const AGENT_AWAKE_TITLE_KEY = 'auto.components.settings.agent-awake-copy.e5995ce268'
+const AGENT_AWAKE_DESCRIPTION_WINDOWS_KEY = 'auto.components.settings.agent-awake-copy.95d3031db2'
+const AGENT_AWAKE_DESCRIPTION_DEFAULT_KEY = 'auto.components.settings.agent-awake-copy.a42f6fbdd8'
+
+export function getAgentAwakeTitle(): string {
+ return translate(AGENT_AWAKE_TITLE_KEY, 'Keep computer awake while agents are working')
+}
export function getAgentAwakeDescription(
userAgent = typeof navigator === 'undefined' ? '' : navigator.userAgent
): string {
if (userAgent.includes('Windows')) {
- return "Keeps this computer and display awake while agents are working. Lid-close behavior follows this device's power settings."
+ return translate(
+ AGENT_AWAKE_DESCRIPTION_WINDOWS_KEY,
+ "Keeps this computer and display awake while agents are working. Lid-close behavior follows this device's power settings."
+ )
}
- return 'Keeps this computer and display awake while agents are working. Orca also asks this device to stay awake when the lid is closed, subject to its power policy.'
+ return translate(
+ AGENT_AWAKE_DESCRIPTION_DEFAULT_KEY,
+ 'Keeps this computer and display awake while agents are working. Orca also asks this device to stay awake when the lid is closed, subject to its power policy.'
+ )
}
export function getAgentAwakeSearchKeywords(
userAgent = typeof navigator === 'undefined' ? '' : navigator.userAgent
): string[] {
- const keywords = ['awake', 'sleep', 'power', 'agent', 'running', 'working', 'lid', 'display']
- return userAgent.includes('Linux') ? [...keywords, 'linux'] : keywords
+ const keywords = searchKeywords([
+ { key: 'auto.components.settings.agents.search.66b6b82eb4', fallback: 'awake' },
+ { key: 'auto.components.settings.agents.search.dbc8aca6b0', fallback: 'sleep' },
+ { key: 'auto.components.settings.agents.search.845ad9128a', fallback: 'power' },
+ { key: 'auto.components.settings.agents.search.96ba2373b6', fallback: 'agent' },
+ { key: 'auto.components.settings.agents.search.48f84d10f1', fallback: 'running' },
+ { key: 'auto.components.settings.agents.search.affbf130f6', fallback: 'working' },
+ { key: 'auto.components.settings.agents.search.0d1c334987', fallback: 'lid' },
+ { key: 'auto.components.settings.agents.search.ff8de8a2ad', fallback: 'display' }
+ ])
+
+ return userAgent.includes('Linux')
+ ? [
+ ...keywords,
+ ...searchKeywords([
+ { key: 'auto.components.settings.agents.search.f622b8eb2a', fallback: 'linux' }
+ ])
+ ]
+ : keywords
}
diff --git a/src/renderer/src/components/settings/agent-generated-tab-title-copy.ts b/src/renderer/src/components/settings/agent-generated-tab-title-copy.ts
index 7c1756578c5..89bf57b43dd 100644
--- a/src/renderer/src/components/settings/agent-generated-tab-title-copy.ts
+++ b/src/renderer/src/components/settings/agent-generated-tab-title-copy.ts
@@ -1,19 +1,35 @@
-export const AGENT_GENERATED_TAB_TITLES_TITLE = 'Auto-generate tab titles'
+import { translate } from '@/i18n/i18n'
+import { searchKeywords } from './settings-search-keywords'
-export const AGENT_GENERATED_TAB_TITLES_DESCRIPTION =
- 'Derive short stable tab names from the first known agent prompt. Manual renames always win.'
+const AGENT_GENERATED_TAB_TITLES_TITLE_KEY =
+ 'auto.components.settings.agent-generated-tab-title-copy.19ad21615a'
+const AGENT_GENERATED_TAB_TITLES_DESCRIPTION_KEY =
+ 'auto.components.settings.agent-generated-tab-title-copy.b036c7a409'
-export const AGENT_GENERATED_TAB_TITLES_SEARCH_KEYWORDS = [
- 'agent',
- 'tab',
- 'title',
- 'generated title',
- 'name',
- 'generated',
- 'auto',
- 'prompt',
- 'rename',
- 'stable',
- 'session',
- 'stable session'
-]
+export function getAgentGeneratedTabTitlesTitle(): string {
+ return translate(AGENT_GENERATED_TAB_TITLES_TITLE_KEY, 'Auto-generate tab titles')
+}
+
+export function getAgentGeneratedTabTitlesDescription(): string {
+ return translate(
+ AGENT_GENERATED_TAB_TITLES_DESCRIPTION_KEY,
+ 'Derive short stable tab names from the first known agent prompt. Manual renames always win.'
+ )
+}
+
+export function getAgentGeneratedTabTitlesSearchKeywords(): string[] {
+ return searchKeywords([
+ { key: 'auto.components.settings.agents.search.96ba2373b6', fallback: 'agent' },
+ { key: 'auto.components.settings.agents.search.be7ea3553b', fallback: 'tab' },
+ { key: 'auto.components.settings.agents.search.6956646a1e', fallback: 'title' },
+ { key: 'auto.components.settings.agents.search.32836788b0', fallback: 'generated title' },
+ { key: 'auto.components.settings.agents.search.966890236d', fallback: 'name' },
+ { key: 'auto.components.settings.agents.search.848dcae8d3', fallback: 'generated' },
+ { key: 'auto.components.settings.agents.search.52115d0d7c', fallback: 'auto' },
+ { key: 'auto.components.settings.agents.search.c64059f50d', fallback: 'prompt' },
+ { key: 'auto.components.settings.agents.search.5784ae8c43', fallback: 'rename' },
+ { key: 'auto.components.settings.agents.search.8a17fd6026', fallback: 'stable' },
+ { key: 'auto.components.settings.agents.search.a79d266f71', fallback: 'session' },
+ { key: 'auto.components.settings.agents.search.afbf35be68', fallback: 'stable session' }
+ ])
+}
diff --git a/src/renderer/src/components/settings/agent-status-hooks-copy.ts b/src/renderer/src/components/settings/agent-status-hooks-copy.ts
index 45b103086d7..5cc48822f53 100644
--- a/src/renderer/src/components/settings/agent-status-hooks-copy.ts
+++ b/src/renderer/src/components/settings/agent-status-hooks-copy.ts
@@ -1,18 +1,41 @@
-export const AGENT_STATUS_HOOKS_TITLE = 'Agent status hooks'
+import { translate } from '@/i18n/i18n'
+import { searchKeywords } from './settings-search-keywords'
-export const AGENT_STATUS_HOOKS_DESCRIPTION =
- 'Shows working, waiting, and done states in Orca. Turn off to remove Orca-managed hooks and stop reinstalling them.'
+const AGENT_STATUS_HOOKS_TITLE_KEY = 'auto.components.settings.agent-status-hooks-copy.7707c15abb'
+const AGENT_STATUS_HOOKS_DESCRIPTION_KEY =
+ 'auto.components.settings.agent-status-hooks-copy.a68a642835'
-export const AGENT_STATUS_HOOKS_SEARCH_KEYWORDS = [
- 'hooks',
- 'status',
- 'working',
- 'waiting',
- 'done',
- 'remove',
- 'restore',
- 'settings',
- 'config',
- 'claude',
- 'codex'
-]
+export function getAgentStatusHooksTitle(): string {
+ return translate(AGENT_STATUS_HOOKS_TITLE_KEY, 'Agent status hooks')
+}
+
+export function getAgentStatusHooksDescription(): string {
+ return translate(
+ AGENT_STATUS_HOOKS_DESCRIPTION_KEY,
+ 'Shows working, waiting, and done states in Orca. Turn off to remove Orca-managed hooks and stop reinstalling them.'
+ )
+}
+
+export function getAgentStatusHooksSearchKeywords(): string[] {
+ return searchKeywords([
+ { key: 'auto.components.settings.agents.search.0d752916f8', fallback: 'hooks' },
+ { key: 'auto.components.settings.agents.search.6984d4291a', fallback: 'status' },
+ { key: 'auto.components.settings.agents.search.affbf130f6', fallback: 'working' },
+ { key: 'auto.components.settings.agents.search.13b20636a6', fallback: 'waiting' },
+ { key: 'auto.components.settings.agents.search.8599603496', fallback: 'done' },
+ { key: 'auto.components.settings.agents.search.ea71995548', fallback: 'remove' },
+ { key: 'auto.components.settings.agents.search.c1317fe641', fallback: 'restore' },
+ { key: 'auto.components.settings.agents.search.5963143e00', fallback: 'settings' },
+ { key: 'auto.components.settings.agents.search.042c551bc5', fallback: 'config' },
+ {
+ key: 'auto.components.settings.agents.search.f412abbba5',
+ fallback: 'claude',
+ englishOnly: true
+ },
+ {
+ key: 'auto.components.settings.agents.search.5ded38b843',
+ fallback: 'codex',
+ englishOnly: true
+ }
+ ])
+}
diff --git a/src/renderer/src/components/settings/agents-search.ts b/src/renderer/src/components/settings/agents-search.ts
index 83760e8f657..878568faefd 100644
--- a/src/renderer/src/components/settings/agents-search.ts
+++ b/src/renderer/src/components/settings/agents-search.ts
@@ -1,45 +1,48 @@
import { getAgentCatalog } from '@/lib/agent-catalog'
import {
- AGENT_AWAKE_TITLE,
getAgentAwakeDescription,
- getAgentAwakeSearchKeywords
+ getAgentAwakeSearchKeywords,
+ getAgentAwakeTitle
} from './agent-awake-copy'
import {
- AGENT_GENERATED_TAB_TITLES_DESCRIPTION,
- AGENT_GENERATED_TAB_TITLES_SEARCH_KEYWORDS,
- AGENT_GENERATED_TAB_TITLES_TITLE
+ getAgentGeneratedTabTitlesDescription,
+ getAgentGeneratedTabTitlesSearchKeywords,
+ getAgentGeneratedTabTitlesTitle
} from './agent-generated-tab-title-copy'
import {
- AGENT_STATUS_HOOKS_DESCRIPTION,
- AGENT_STATUS_HOOKS_SEARCH_KEYWORDS,
- AGENT_STATUS_HOOKS_TITLE
+ getAgentStatusHooksDescription,
+ getAgentStatusHooksSearchKeywords,
+ getAgentStatusHooksTitle
} from './agent-status-hooks-copy'
import { translate } from '@/i18n/i18n'
+import { searchKeywords, translateSearchKeyword, uniqueKeywords } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
-const AGENT_SETTINGS_KEYWORDS = buildAgentSettingsKeywords()
-
function buildAgentSettingsKeywords(): string[] {
- const keywords = [
- 'agent',
- 'default',
- 'command',
- 'override',
- 'install',
- 'detected',
- 'enable',
- 'disable',
- 'hide',
- 'show',
- 'github'
- ]
+ const keywords = searchKeywords([
+ { key: 'auto.components.settings.agents.search.96ba2373b6', fallback: 'agent' },
+ { key: 'auto.components.settings.agents.search.d8f3a8b8a0', fallback: 'default' },
+ { key: 'auto.components.settings.agents.search.167daeb5e9', fallback: 'command' },
+ { key: 'auto.components.settings.agents.search.be59907510', fallback: 'override' },
+ { key: 'auto.components.settings.agents.search.a6d594c17d', fallback: 'install' },
+ { key: 'auto.components.settings.agents.search.f2932bf22b', fallback: 'detected' },
+ { key: 'auto.components.settings.agents.search.2afd3b5858', fallback: 'enable' },
+ { key: 'auto.components.settings.agents.search.60393e1b17', fallback: 'disable' },
+ { key: 'auto.components.settings.agents.search.2e188c771c', fallback: 'hide' },
+ { key: 'auto.components.settings.agents.search.87fffe6c20', fallback: 'show' },
+ {
+ key: 'auto.components.settings.agents.search.e2b7c0dcd7',
+ fallback: 'github',
+ englishOnly: true
+ }
+ ])
for (const agent of getAgentCatalog()) {
keywords.push(...expandAgentSearchText(agent.id), ...expandAgentSearchText(agent.label))
keywords.push(...expandAgentSearchText(agent.cmd))
}
- return [...new Set(keywords)]
+ return uniqueKeywords(keywords)
}
function expandAgentSearchText(value: string): string[] {
@@ -58,7 +61,7 @@ export const getAgentsPaneSearchEntries = createLocalizedCatalog(() => [
'auto.components.settings.agents.search.01926b9d8c',
'Configure AI coding agents, default agent, and command overrides.'
),
- keywords: AGENT_SETTINGS_KEYWORDS
+ keywords: buildAgentSettingsKeywords()
},
{
title: translate('auto.components.settings.agents.search.ef804b7337', 'Agent Location'),
@@ -67,28 +70,28 @@ export const getAgentsPaneSearchEntries = createLocalizedCatalog(() => [
'Choose whether installed agents are detected on this device or in WSL.'
),
keywords: [
- translate('auto.components.settings.agents.search.96ba2373b6', 'agent'),
- translate('auto.components.settings.agents.search.d2952dfd74', 'location'),
- translate('auto.components.settings.agents.search.77c02fa3c3', 'windows'),
- translate('auto.components.settings.agents.search.d608654c03', 'wsl'),
- translate('auto.components.settings.agents.search.f622b8eb2a', 'linux'),
- translate('auto.components.settings.agents.search.839e82c81f', 'detect'),
- translate('auto.components.settings.agents.search.2814401339', 'installed'),
- translate('auto.components.settings.agents.search.719f53350c', 'path')
+ ...translateSearchKeyword('auto.components.settings.agents.search.96ba2373b6', 'agent'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.d2952dfd74', 'location'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.77c02fa3c3', 'windows'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.d608654c03', 'wsl'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.f622b8eb2a', 'linux'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.839e82c81f', 'detect'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.2814401339', 'installed'),
+ ...translateSearchKeyword('auto.components.settings.agents.search.719f53350c', 'path')
]
},
{
- title: AGENT_STATUS_HOOKS_TITLE,
- description: AGENT_STATUS_HOOKS_DESCRIPTION,
- keywords: AGENT_STATUS_HOOKS_SEARCH_KEYWORDS
+ title: getAgentStatusHooksTitle(),
+ description: getAgentStatusHooksDescription(),
+ keywords: getAgentStatusHooksSearchKeywords()
},
{
- title: AGENT_GENERATED_TAB_TITLES_TITLE,
- description: AGENT_GENERATED_TAB_TITLES_DESCRIPTION,
- keywords: AGENT_GENERATED_TAB_TITLES_SEARCH_KEYWORDS
+ title: getAgentGeneratedTabTitlesTitle(),
+ description: getAgentGeneratedTabTitlesDescription(),
+ keywords: getAgentGeneratedTabTitlesSearchKeywords()
},
{
- title: AGENT_AWAKE_TITLE,
+ title: getAgentAwakeTitle(),
description: getAgentAwakeDescription(),
keywords: getAgentAwakeSearchKeywords()
}
diff --git a/src/renderer/src/components/settings/appearance-search.ts b/src/renderer/src/components/settings/appearance-search.ts
index 275b4ed8526..7e08e412ac5 100644
--- a/src/renderer/src/components/settings/appearance-search.ts
+++ b/src/renderer/src/components/settings/appearance-search.ts
@@ -2,6 +2,7 @@ import type { SettingsSearchEntry } from './settings-search'
import { getTerminalAppearanceSearchEntries } from './terminal-search'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { SHOW_UI_LANGUAGE_SETTING } from '@/i18n/supported-languages'
import { getStatusBarToggles } from './appearance-status-bar-search'
@@ -15,9 +16,9 @@ export const getThemeEntries = createLocalizedCatalog((): SettingsSearchEntry[]
'Choose how Orca looks in the app window.'
),
keywords: [
- translate('auto.components.settings.appearance.search.262fe1d24f', 'dark'),
- translate('auto.components.settings.appearance.search.44d873fd18', 'light'),
- translate('auto.components.settings.appearance.search.3a9b69d734', 'system')
+ ...translateSearchKeyword('auto.components.settings.appearance.search.262fe1d24f', 'dark'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.44d873fd18', 'light'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.3a9b69d734', 'system')
]
}
])
@@ -30,16 +31,25 @@ export const getLanguageEntries = createLocalizedCatalog((): SettingsSearchEntry
'Choose the language used by the Orca interface.'
),
keywords: [
- translate('settings.appearance.language.title', 'Language'),
- translate(
+ ...translateSearchKeyword('settings.appearance.language.title', 'Language'),
+ ...translateSearchKeyword(
'settings.appearance.language.description',
'Choose the language used by the Orca interface.'
),
- translate('settings.appearance.language.system', 'System'),
- translate('settings.appearance.language.english', 'English'),
- translate('auto.components.settings.appearance.search.language.locale', 'locale'),
- translate('auto.components.settings.appearance.search.language.i18n', 'i18n'),
- translate('auto.components.settings.appearance.search.language.translation', 'translation')
+ ...translateSearchKeyword('settings.appearance.language.system', 'System'),
+ ...translateSearchKeyword('settings.appearance.language.english', 'English'),
+ ...translateSearchKeyword('settings.appearance.language.chinese', '中文(简体)'),
+ ...translateSearchKeyword('settings.appearance.language.korean', '한국어'),
+ ...translateSearchKeyword('settings.appearance.language.japanese', '日本語'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.language.locale',
+ 'locale'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.language.i18n', 'i18n'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.language.translation',
+ 'translation'
+ )
]
}
])
@@ -52,9 +62,9 @@ export const getZoomEntries = createLocalizedCatalog((): SettingsSearchEntry[] =
'Scale the entire application interface.'
),
keywords: [
- translate('auto.components.settings.appearance.search.3ae5de6101', 'zoom'),
- translate('auto.components.settings.appearance.search.0952091186', 'scale'),
- translate('auto.components.settings.appearance.search.0c83659f48', 'shortcut')
+ ...translateSearchKeyword('auto.components.settings.appearance.search.3ae5de6101', 'zoom'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.0952091186', 'scale'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.0c83659f48', 'shortcut')
]
}
])
@@ -67,14 +77,23 @@ export const getTypographyEntries = createLocalizedCatalog((): SettingsSearchEnt
'Choose the font used by the Orca interface.'
),
keywords: [
- translate('auto.components.settings.appearance.search.24094af355', 'font'),
- translate('auto.components.settings.appearance.search.a0e09aed9c', 'typeface'),
- translate('auto.components.settings.appearance.search.8b36fb3f64', 'typography'),
- translate('auto.components.settings.appearance.search.fab91464dd', 'ide'),
- translate('auto.components.settings.appearance.search.1f2880a9d5', 'orca'),
- translate('auto.components.settings.appearance.search.5095258df2', 'interface'),
- translate('auto.components.settings.appearance.search.36e006efc1', 'app'),
- translate('auto.components.settings.appearance.search.2f12e1aa3a', 'ui')
+ ...translateSearchKeyword('auto.components.settings.appearance.search.24094af355', 'font'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.a0e09aed9c',
+ 'typeface'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.8b36fb3f64',
+ 'typography'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.fab91464dd', 'ide'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.1f2880a9d5', 'orca'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.5095258df2',
+ 'interface'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.36e006efc1', 'app'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.2f12e1aa3a', 'ui')
]
}
])
@@ -90,12 +109,18 @@ export const getLayoutEntries = createLocalizedCatalog((): SettingsSearchEntry[]
'Dim files matched by .gitignore in the file explorer.'
),
keywords: [
- translate('auto.components.settings.appearance.search.bce3ac317a', 'git'),
- translate('auto.components.settings.appearance.search.08c86bf58e', 'gitignore'),
- translate('auto.components.settings.appearance.search.9f2df826ac', 'ignored'),
- translate('auto.components.settings.appearance.search.c1bca1885a', 'file explorer'),
- translate('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
- translate('auto.components.settings.appearance.search.648eeada79', 'hide')
+ ...translateSearchKeyword('auto.components.settings.appearance.search.bce3ac317a', 'git'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.08c86bf58e',
+ 'gitignore'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.9f2df826ac', 'ignored'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.c1bca1885a',
+ 'file explorer'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.648eeada79', 'hide')
]
}
])
@@ -108,11 +133,14 @@ export const getTitlebarEntries = createLocalizedCatalog((): SettingsSearchEntry
'Show Orca in the titlebar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.bed343b03e', 'titlebar'),
- translate('auto.components.settings.appearance.search.1f2880a9d5', 'orca'),
- translate('auto.components.settings.appearance.search.36e006efc1', 'app'),
- translate('auto.components.settings.appearance.search.51f957ce39', 'name'),
- translate('auto.components.settings.appearance.search.a895d0f938', 'brand')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.bed343b03e',
+ 'titlebar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.1f2880a9d5', 'orca'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.36e006efc1', 'app'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.51f957ce39', 'name'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.a895d0f938', 'brand')
]
}
])
@@ -133,13 +161,13 @@ export const getSidebarEntries = createLocalizedCatalog((): SettingsSearchEntry[
'Show the Tasks button at the top of the left sidebar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.0d5a74b606', 'tasks'),
- translate('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
- translate('auto.components.settings.appearance.search.6cf5f54ce1', 'button'),
- translate('auto.components.settings.appearance.search.648eeada79', 'hide'),
- translate('auto.components.settings.appearance.search.ac79fe4a04', 'show'),
- translate('auto.components.settings.appearance.search.2ee4810f38', 'github'),
- translate('auto.components.settings.appearance.search.6b846424cc', 'linear')
+ ...translateSearchKeyword('auto.components.settings.appearance.search.0d5a74b606', 'tasks'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.6cf5f54ce1', 'button'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.648eeada79', 'hide'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.ac79fe4a04', 'show'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.2ee4810f38', 'github'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.6b846424cc', 'linear')
]
},
{
@@ -152,13 +180,22 @@ export const getSidebarEntries = createLocalizedCatalog((): SettingsSearchEntry[
'Show the Automations button at the top of the left sidebar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.b186f3cefb', 'automations'),
- translate('auto.components.settings.appearance.search.58f4e22fa2', 'automation'),
- translate('auto.components.settings.appearance.search.4c920ab2d1', 'schedule'),
- translate('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
- translate('auto.components.settings.appearance.search.6cf5f54ce1', 'button'),
- translate('auto.components.settings.appearance.search.648eeada79', 'hide'),
- translate('auto.components.settings.appearance.search.ac79fe4a04', 'show')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.b186f3cefb',
+ 'automations'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.58f4e22fa2',
+ 'automation'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.4c920ab2d1',
+ 'schedule'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.6cf5f54ce1', 'button'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.648eeada79', 'hide'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.ac79fe4a04', 'show')
]
},
{
@@ -171,13 +208,13 @@ export const getSidebarEntries = createLocalizedCatalog((): SettingsSearchEntry[
'Show the Orca Mobile button at the top of the left sidebar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.74618577c7', 'mobile'),
- translate('auto.components.settings.appearance.search.5e5b8878bf', 'phone'),
- translate('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
- translate('auto.components.settings.appearance.search.6cf5f54ce1', 'button'),
- translate('auto.components.settings.appearance.search.648eeada79', 'hide'),
- translate('auto.components.settings.appearance.search.ac79fe4a04', 'show'),
- translate('auto.components.settings.appearance.search.839fb1e3ed', 'toolbox')
+ ...translateSearchKeyword('auto.components.settings.appearance.search.74618577c7', 'mobile'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.5e5b8878bf', 'phone'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.5bff6a2ef0', 'sidebar'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.6cf5f54ce1', 'button'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.648eeada79', 'hide'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.ac79fe4a04', 'show'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.839fb1e3ed', 'toolbox')
]
}
])
@@ -190,13 +227,22 @@ export const getAppIconEntries = createLocalizedCatalog((): SettingsSearchEntry[
'Choose the app icon shown in the Dock and window switcher.'
),
keywords: [
- translate('auto.components.settings.appearance.search.2cfb3420c0', 'app icon'),
- translate('auto.components.settings.appearance.search.1f2880a9d5', 'orca'),
- translate('auto.components.settings.appearance.search.d18b54ca90', 'dock'),
- translate('auto.components.settings.appearance.search.e5bc35d59e', 'window'),
- translate('auto.components.settings.appearance.search.651f35b2c6', 'switcher'),
- translate('auto.components.settings.appearance.search.f586abfa35', 'blue'),
- translate('auto.components.settings.appearance.search.468448bba4', 'watercolor')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.2cfb3420c0',
+ 'app icon'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.1f2880a9d5', 'orca'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.d18b54ca90', 'dock'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.e5bc35d59e', 'window'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.651f35b2c6',
+ 'switcher'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.f586abfa35', 'blue'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.468448bba4',
+ 'watercolor'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/appearance-status-bar-search.ts b/src/renderer/src/components/settings/appearance-status-bar-search.ts
index 4ab7586a453..088e015d385 100644
--- a/src/renderer/src/components/settings/appearance-status-bar-search.ts
+++ b/src/renderer/src/components/settings/appearance-status-bar-search.ts
@@ -1,6 +1,7 @@
import type { StatusBarItem } from '../../../../shared/types'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
export const getStatusBarToggles = createLocalizedCatalog(
(): readonly {
@@ -18,12 +19,24 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show Claude token and cost usage in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.c9fe3a7876', 'claude'),
- translate('auto.components.settings.appearance.search.00a028f25f', 'usage'),
- translate('auto.components.settings.appearance.search.afbb6a3767', 'tokens'),
- translate('auto.components.settings.appearance.search.edbf0f63a0', 'cost'),
- translate('auto.components.settings.appearance.search.dea0a9a665', 'anthropic')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.c9fe3a7876',
+ 'claude'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.00a028f25f', 'usage'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.afbb6a3767',
+ 'tokens'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.edbf0f63a0', 'cost'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.dea0a9a665',
+ 'anthropic'
+ )
],
toggleDescription: translate(
'settings.appearance.statusBar.claudeToggleDescription',
@@ -38,12 +51,18 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show Codex token and cost usage in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.8dfd676c28', 'codex'),
- translate('auto.components.settings.appearance.search.00a028f25f', 'usage'),
- translate('auto.components.settings.appearance.search.afbb6a3767', 'tokens'),
- translate('auto.components.settings.appearance.search.edbf0f63a0', 'cost'),
- translate('auto.components.settings.appearance.search.97957e374e', 'openai')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.8dfd676c28', 'codex'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.00a028f25f', 'usage'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.afbb6a3767',
+ 'tokens'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.edbf0f63a0', 'cost'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.97957e374e', 'openai')
],
toggleDescription: translate(
'settings.appearance.statusBar.codexToggleDescription',
@@ -58,12 +77,21 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show Gemini token and cost usage in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.2804a920ad', 'gemini'),
- translate('auto.components.settings.appearance.search.00a028f25f', 'usage'),
- translate('auto.components.settings.appearance.search.afbb6a3767', 'tokens'),
- translate('auto.components.settings.appearance.search.edbf0f63a0', 'cost'),
- translate('auto.components.settings.appearance.search.51b0ccd6a2', 'google')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.2804a920ad',
+ 'gemini'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.00a028f25f', 'usage'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.afbb6a3767',
+ 'tokens'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.edbf0f63a0', 'cost'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.51b0ccd6a2', 'google')
],
toggleDescription: translate(
'settings.appearance.statusBar.geminiToggleDescription',
@@ -81,12 +109,24 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show OpenCode Go token and cost usage in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.a9d56852eb', 'opencode'),
- translate('auto.components.settings.appearance.search.d77537b580', 'opencode-go'),
- translate('auto.components.settings.appearance.search.00a028f25f', 'usage'),
- translate('auto.components.settings.appearance.search.afbb6a3767', 'tokens'),
- translate('auto.components.settings.appearance.search.edbf0f63a0', 'cost')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.a9d56852eb',
+ 'opencode'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.d77537b580',
+ 'opencode-go'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.00a028f25f', 'usage'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.afbb6a3767',
+ 'tokens'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.edbf0f63a0', 'cost')
],
toggleDescription: translate(
'settings.appearance.statusBar.opencodeGoToggleDescription',
@@ -101,11 +141,20 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show Kimi subscription usage in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.40e5c3c285', 'kimi'),
- translate('auto.components.settings.appearance.search.00a028f25f', 'usage'),
- translate('auto.components.settings.appearance.search.de586def95', 'subscription'),
- translate('auto.components.settings.appearance.search.35565867cb', 'moonshot')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.40e5c3c285', 'kimi'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.00a028f25f', 'usage'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.de586def95',
+ 'subscription'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.35565867cb',
+ 'moonshot'
+ )
],
toggleDescription: translate(
'settings.appearance.statusBar.kimiToggleDescription',
@@ -120,11 +169,20 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show the active SSH connection status in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.6ecad74eb3', 'ssh'),
- translate('auto.components.settings.appearance.search.a278406ed5', 'remote'),
- translate('auto.components.settings.appearance.search.f4997e0f8a', 'connection'),
- translate('auto.components.settings.appearance.search.fe192b060e', 'host')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.6ecad74eb3', 'ssh'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.a278406ed5',
+ 'remote'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.f4997e0f8a',
+ 'connection'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.fe192b060e', 'host')
],
toggleDescription: translate(
'settings.appearance.statusBar.sshToggleDescription',
@@ -139,14 +197,29 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show CPU, memory, terminal sessions, and workspace disk usage in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.c690a15849', 'resource'),
- translate('auto.components.settings.appearance.search.9c4d5f0894', 'manager'),
- translate('auto.components.settings.appearance.search.4355f18ac6', 'memory'),
- translate('auto.components.settings.appearance.search.4ddbde4999', 'cpu'),
- translate('auto.components.settings.appearance.search.96b4fb0064', 'terminal'),
- translate('auto.components.settings.appearance.search.90bdc043ea', 'disk'),
- translate('auto.components.settings.appearance.search.cb1cc62cf8', 'space')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.c690a15849',
+ 'resource'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.9c4d5f0894',
+ 'manager'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.4355f18ac6',
+ 'memory'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.4ddbde4999', 'cpu'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.96b4fb0064',
+ 'terminal'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.90bdc043ea', 'disk'),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.cb1cc62cf8', 'space')
],
toggleDescription: translate(
'settings.appearance.statusBar.resourceUsageToggleDescription',
@@ -161,11 +234,23 @@ export const getStatusBarToggles = createLocalizedCatalog(
'Show live workspace ports in the status bar.'
),
keywords: [
- translate('auto.components.settings.appearance.search.896eb53fd4', 'status bar'),
- translate('auto.components.settings.appearance.search.006e67b279', 'ports'),
- translate('auto.components.settings.appearance.search.46d21eef62', 'localhost'),
- translate('auto.components.settings.appearance.search.43cfba3b95', 'server'),
- translate('auto.components.settings.appearance.search.dc02c8759d', 'workspace')
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.896eb53fd4',
+ 'status bar'
+ ),
+ ...translateSearchKeyword('auto.components.settings.appearance.search.006e67b279', 'ports'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.46d21eef62',
+ 'localhost'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.43cfba3b95',
+ 'server'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.appearance.search.dc02c8759d',
+ 'workspace'
+ )
],
toggleDescription: translate(
'settings.appearance.statusBar.portsToggleDescription',
diff --git a/src/renderer/src/components/settings/auto-rename-branch-search.ts b/src/renderer/src/components/settings/auto-rename-branch-search.ts
index 5d21b89a22e..74fb9331773 100644
--- a/src/renderer/src/components/settings/auto-rename-branch-search.ts
+++ b/src/renderer/src/components/settings/auto-rename-branch-search.ts
@@ -1,5 +1,6 @@
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getAutoRenameBranchParentSearchEntry = createLocalizedCatalog(
@@ -13,17 +14,50 @@ export const getAutoRenameBranchParentSearchEntry = createLocalizedCatalog(
'Rename the auto-generated branch based on the work once an agent starts.'
),
keywords: [
- translate('auto.components.settings.auto.rename.branch.search.9319bd9827', 'branch'),
- translate('auto.components.settings.auto.rename.branch.search.55a1860e47', 'rename'),
- translate('auto.components.settings.auto.rename.branch.search.7803423877', 'auto'),
- translate('auto.components.settings.auto.rename.branch.search.f0acf64301', 'creature name'),
- translate('auto.components.settings.auto.rename.branch.search.3ef3cbe98c', 'agent'),
- translate('auto.components.settings.auto.rename.branch.search.40d21f2efc', 'prompt'),
- translate('auto.components.settings.auto.rename.branch.search.10485c4fc5', 'command'),
- translate('auto.components.settings.auto.rename.branch.search.7adefcdd94', 'template'),
- translate('auto.components.settings.auto.rename.branch.search.ed677944cc', 'worktree'),
- translate('auto.components.settings.auto.rename.branch.search.a482f6a423', 'slug'),
- translate('auto.components.settings.auto.rename.branch.search.f41833025e', 'generate')
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.9319bd9827',
+ 'branch'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.55a1860e47',
+ 'rename'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.7803423877',
+ 'auto'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.f0acf64301',
+ 'creature name'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.3ef3cbe98c',
+ 'agent'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.40d21f2efc',
+ 'prompt'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.10485c4fc5',
+ 'command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.7adefcdd94',
+ 'template'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.ed677944cc',
+ 'worktree'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.a482f6a423',
+ 'slug'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.f41833025e',
+ 'generate'
+ )
]
})
)
@@ -39,13 +73,34 @@ export const getAutoRenameBranchAdvancedSearchEntries = createLocalizedCatalog((
'Agent command template used when generating branch names.'
),
keywords: [
- translate('auto.components.settings.auto.rename.branch.search.40d21f2efc', 'prompt'),
- translate('auto.components.settings.auto.rename.branch.search.502aa57681', 'instructions'),
- translate('auto.components.settings.auto.rename.branch.search.50139297e6', 'built-in prompt'),
- translate('auto.components.settings.auto.rename.branch.search.10485c4fc5', 'command'),
- translate('auto.components.settings.auto.rename.branch.search.7adefcdd94', 'template'),
- translate('auto.components.settings.auto.rename.branch.search.a482f6a423', 'slug'),
- translate('auto.components.settings.auto.rename.branch.search.0971762141', 'kebab-case')
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.40d21f2efc',
+ 'prompt'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.502aa57681',
+ 'instructions'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.50139297e6',
+ 'built-in prompt'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.10485c4fc5',
+ 'command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.7adefcdd94',
+ 'template'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.a482f6a423',
+ 'slug'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.auto.rename.branch.search.0971762141',
+ 'kebab-case'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/browser-search.ts b/src/renderer/src/components/settings/browser-search.ts
index f798c519c3b..7235dbb9ec9 100644
--- a/src/renderer/src/components/settings/browser-search.ts
+++ b/src/renderer/src/components/settings/browser-search.ts
@@ -1,5 +1,6 @@
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
type BrowserShortcutPlatform = {
isMac: boolean
@@ -30,14 +31,14 @@ export function getBrowserPaneSearchEntries(
'URL opened when creating a new browser tab. Leave empty to open a blank tab.'
),
keywords: [
- translate('auto.components.settings.browser.search.2d2d995c58', 'browser'),
- translate('auto.components.settings.browser.search.291f480a5e', 'home'),
- translate('auto.components.settings.browser.search.0dbb1eaf4e', 'homepage'),
- translate('auto.components.settings.browser.search.5448f4097b', 'default'),
- translate('auto.components.settings.browser.search.4fda4fb066', 'url'),
- translate('auto.components.settings.browser.search.483a0eb5e0', 'new tab'),
- translate('auto.components.settings.browser.search.5164c47e31', 'blank'),
- translate('auto.components.settings.browser.search.4596a52cf7', 'landing')
+ ...translateSearchKeyword('auto.components.settings.browser.search.2d2d995c58', 'browser'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.291f480a5e', 'home'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.0dbb1eaf4e', 'homepage'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.5448f4097b', 'default'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.4fda4fb066', 'url'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.483a0eb5e0', 'new tab'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.5164c47e31', 'blank'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.4596a52cf7', 'landing')
]
},
{
@@ -50,18 +51,21 @@ export function getBrowserPaneSearchEntries(
'Search engine used when typing non-URL text in the address bar.'
),
keywords: [
- translate('auto.components.settings.browser.search.2d2d995c58', 'browser'),
- translate('auto.components.settings.browser.search.16bd69cd82', 'search'),
- translate('auto.components.settings.browser.search.72b4b89970', 'engine'),
- translate('auto.components.settings.browser.search.8a489aab8d', 'google'),
- translate('auto.components.settings.browser.search.1f8153acfb', 'duckduckgo'),
- translate('auto.components.settings.browser.search.ad40e75d13', 'bing'),
- translate('auto.components.settings.browser.search.e1c2a57f07', 'kagi'),
- translate('auto.components.settings.browser.search.66dd641a47', 'session'),
- translate('auto.components.settings.browser.search.0732ebe6fb', 'private'),
- translate('auto.components.settings.browser.search.3538b3aaeb', 'token'),
- translate('auto.components.settings.browser.search.8b8ed06e4b', 'omnibox'),
- translate('auto.components.settings.browser.search.0bb34eacc9', 'query')
+ ...translateSearchKeyword('auto.components.settings.browser.search.2d2d995c58', 'browser'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.16bd69cd82', 'search'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.72b4b89970', 'engine'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.8a489aab8d', 'google'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.search.1f8153acfb',
+ 'duckduckgo'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.search.ad40e75d13', 'bing'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.e1c2a57f07', 'kagi'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.66dd641a47', 'session'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.0732ebe6fb', 'private'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.3538b3aaeb', 'token'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.8b8ed06e4b', 'omnibox'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.0bb34eacc9', 'query')
]
},
{
@@ -71,29 +75,38 @@ export function getBrowserPaneSearchEntries(
'Zoom level applied to newly opened browser tabs.'
),
keywords: [
- translate('auto.components.settings.browser.search.2d2d995c58', 'browser'),
- translate('auto.components.settings.browser.search.4a98ed195f', 'zoom'),
- translate('auto.components.settings.browser.search.54f4ea55f7', 'scale'),
- translate('auto.components.settings.browser.search.5448f4097b', 'default'),
- translate('auto.components.settings.browser.search.726f2a8556', 'page zoom'),
- translate('auto.components.settings.browser.search.483a0eb5e0', 'new tab'),
- translate('auto.components.settings.browser.search.95944898e0', 'percentage')
+ ...translateSearchKeyword('auto.components.settings.browser.search.2d2d995c58', 'browser'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.4a98ed195f', 'zoom'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.54f4ea55f7', 'scale'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.5448f4097b', 'default'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.search.726f2a8556',
+ 'page zoom'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.search.483a0eb5e0', 'new tab'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.search.95944898e0',
+ 'percentage'
+ )
]
},
{
title: translate('auto.components.settings.browser.search.5cb082b3e3', 'Link Routing'),
description: getBrowserLinkRoutingDescription(platform),
keywords: [
- translate('auto.components.settings.browser.search.2d2d995c58', 'browser'),
- translate('auto.components.settings.browser.search.44d14df30d', 'preview'),
- translate('auto.components.settings.browser.search.bea27bac4b', 'links'),
- translate('auto.components.settings.browser.search.82ba1c80ea', 'localhost'),
- translate('auto.components.settings.browser.search.72c58f7792', 'webview'),
- translate('auto.components.settings.browser.search.90425d313c', 'shift'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.2d2d995c58', 'browser'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.44d14df30d', 'preview'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.bea27bac4b', 'links'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.search.82ba1c80ea',
+ 'localhost'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.search.72c58f7792', 'webview'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.90425d313c', 'shift'),
platform.isMac ? 'cmd' : 'ctrl',
- translate('auto.components.settings.browser.search.68d1db8929', 'markdown'),
- translate('auto.components.settings.browser.search.8dd4805991', 'file'),
- translate('auto.components.settings.browser.search.a7a07d5415', 'editor')
+ ...translateSearchKeyword('auto.components.settings.browser.search.68d1db8929', 'markdown'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.8dd4805991', 'file'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.a7a07d5415', 'editor')
]
},
{
@@ -103,16 +116,16 @@ export function getBrowserPaneSearchEntries(
'Import cookies from Chrome, Edge, or other browsers to use existing logins inside Orca.'
),
keywords: [
- translate('auto.components.settings.browser.search.2d2d995c58', 'browser'),
- translate('auto.components.settings.browser.search.29193a51d5', 'cookies'),
- translate('auto.components.settings.browser.search.66dd641a47', 'session'),
- translate('auto.components.settings.browser.search.2e7f951773', 'import'),
- translate('auto.components.settings.browser.search.3910a41f32', 'auth'),
- translate('auto.components.settings.browser.search.854ef6ce83', 'login'),
- translate('auto.components.settings.browser.search.75a0d435b7', 'chrome'),
- translate('auto.components.settings.browser.search.533a253deb', 'edge'),
- translate('auto.components.settings.browser.search.1c1e097985', 'arc'),
- translate('auto.components.settings.browser.search.7539f6336c', 'profile')
+ ...translateSearchKeyword('auto.components.settings.browser.search.2d2d995c58', 'browser'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.29193a51d5', 'cookies'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.66dd641a47', 'session'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.2e7f951773', 'import'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.3910a41f32', 'auth'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.854ef6ce83', 'login'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.75a0d435b7', 'chrome'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.533a253deb', 'edge'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.1c1e097985', 'arc'),
+ ...translateSearchKeyword('auto.components.settings.browser.search.7539f6336c', 'profile')
]
}
]
diff --git a/src/renderer/src/components/settings/browser-use-search.ts b/src/renderer/src/components/settings/browser-use-search.ts
index a4bc512c308..ee48211ac0c 100644
--- a/src/renderer/src/components/settings/browser-use-search.ts
+++ b/src/renderer/src/components/settings/browser-use-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getBrowserUsePaneSearchEntries = createLocalizedCatalog(() => [
@@ -9,14 +10,20 @@ export const getBrowserUsePaneSearchEntries = createLocalizedCatalog(() => [
'Register the Orca CLI so agents can drive the browser.'
),
keywords: [
- translate('auto.components.settings.browser.use.search.ba4eb53b72', 'browser use'),
- translate('auto.components.settings.browser.use.search.85fab5e12c', 'cli'),
- translate('auto.components.settings.browser.use.search.ff05cbc344', 'orca'),
- translate('auto.components.settings.browser.use.search.30c74aaa1f', 'path'),
- translate('auto.components.settings.browser.use.search.3ffafc9b95', 'command'),
- translate('auto.components.settings.browser.use.search.7e0dcb257a', 'shell'),
- translate('auto.components.settings.browser.use.search.034c5e8d7f', 'enable'),
- translate('auto.components.settings.browser.use.search.e56c7b55c9', 'setup')
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.ba4eb53b72',
+ 'browser use'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.85fab5e12c', 'cli'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.ff05cbc344', 'orca'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.30c74aaa1f', 'path'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.3ffafc9b95',
+ 'command'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.7e0dcb257a', 'shell'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.034c5e8d7f', 'enable'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.e56c7b55c9', 'setup')
]
},
{
@@ -29,14 +36,29 @@ export const getBrowserUsePaneSearchEntries = createLocalizedCatalog(() => [
"Install the Browser Use skill so agents can operate Orca's browser."
),
keywords: [
- translate('auto.components.settings.browser.use.search.ba4eb53b72', 'browser use'),
- translate('auto.components.settings.browser.use.search.a2d489263e', 'skill'),
- translate('auto.components.settings.browser.use.search.9d97446873', 'agent'),
- translate('auto.components.settings.browser.use.search.e5a784bc54', 'install'),
- translate('auto.components.settings.browser.use.search.f5b8fdddf5', 'orca-cli'),
- translate('auto.components.settings.browser.use.search.6ea88e5206', 'npx'),
- translate('auto.components.settings.browser.use.search.a57c2172dc', 'agent-browser'),
- translate('auto.components.settings.browser.use.search.cee44fb442', 'automation')
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.ba4eb53b72',
+ 'browser use'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.a2d489263e', 'skill'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.9d97446873', 'agent'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.e5a784bc54',
+ 'install'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.f5b8fdddf5',
+ 'orca-cli'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.6ea88e5206', 'npx'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.a57c2172dc',
+ 'agent-browser'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.cee44fb442',
+ 'automation'
+ )
]
},
{
@@ -49,22 +71,52 @@ export const getBrowserUsePaneSearchEntries = createLocalizedCatalog(() => [
'Import cookies from Chrome, Edge, or other browsers so agents can reuse your logins.'
),
keywords: [
- translate('auto.components.settings.browser.use.search.ba4eb53b72', 'browser use'),
- translate('auto.components.settings.browser.use.search.fb8178824f', 'cookies'),
- translate('auto.components.settings.browser.use.search.02837ee497', 'session'),
- translate('auto.components.settings.browser.use.search.d5ad1f7aad', 'import'),
- translate('auto.components.settings.browser.use.search.48557f639c', 'login'),
- translate('auto.components.settings.browser.use.search.96ce3d2de2', 'auth'),
- translate('auto.components.settings.browser.use.search.088e7a9012', 'chrome'),
- translate('auto.components.settings.browser.use.search.2e1b09897b', 'edge'),
- translate('auto.components.settings.browser.use.search.ab349a2dd0', 'arc'),
- translate('auto.components.settings.browser.use.search.20c1323d1e', 'computer use'),
- translate('auto.components.settings.browser.use.search.63a66da648', 'system browser'),
- translate('auto.components.settings.browser.use.search.62e2a790c0', 'existing session'),
- translate('auto.components.settings.browser.use.search.59968bb9b4', 'authenticated browser'),
- translate('auto.components.settings.browser.use.search.22fb801af8', 'chrome profile'),
- translate('auto.components.settings.browser.use.search.d5afa54d21', 'edge profile'),
- translate('auto.components.settings.browser.use.search.3f4c559deb', 'arc profile')
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.ba4eb53b72',
+ 'browser use'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.fb8178824f',
+ 'cookies'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.02837ee497',
+ 'session'
+ ),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.d5ad1f7aad', 'import'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.48557f639c', 'login'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.96ce3d2de2', 'auth'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.088e7a9012', 'chrome'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.2e1b09897b', 'edge'),
+ ...translateSearchKeyword('auto.components.settings.browser.use.search.ab349a2dd0', 'arc'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.20c1323d1e',
+ 'computer use'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.63a66da648',
+ 'system browser'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.62e2a790c0',
+ 'existing session'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.59968bb9b4',
+ 'authenticated browser'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.22fb801af8',
+ 'chrome profile'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.d5afa54d21',
+ 'edge profile'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.browser.use.search.3f4c559deb',
+ 'arc profile'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/commit-message-ai-search.ts b/src/renderer/src/components/settings/commit-message-ai-search.ts
index 168ec72b457..8ec0d820c0d 100644
--- a/src/renderer/src/components/settings/commit-message-ai-search.ts
+++ b/src/renderer/src/components/settings/commit-message-ai-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getCommitMessageAiPaneSearchEntries = createLocalizedCatalog(() => [
@@ -12,15 +13,42 @@ export const getCommitMessageAiPaneSearchEntries = createLocalizedCatalog(() =>
'Adds action recipes for Source Control commit, pull request, branch-name, and fix actions.'
),
keywords: [
- translate('auto.components.settings.commit.message.ai.search.c33cb1b982', 'ai'),
- translate('auto.components.settings.commit.message.ai.search.127d512e75', 'commit'),
- translate('auto.components.settings.commit.message.ai.search.93e5210da8', 'message'),
- translate('auto.components.settings.commit.message.ai.search.8e9cc598d7', 'generate'),
- translate('auto.components.settings.commit.message.ai.search.3766941527', 'agent'),
- translate('auto.components.settings.commit.message.ai.search.f121bec167', 'claude'),
- translate('auto.components.settings.commit.message.ai.search.542e1a00a7', 'codex'),
- translate('auto.components.settings.commit.message.ai.search.82109d627d', 'source control'),
- translate('auto.components.settings.commit.message.ai.search.ee14a9e9f7', 'enabled')
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.c33cb1b982',
+ 'ai'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.127d512e75',
+ 'commit'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.93e5210da8',
+ 'message'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.8e9cc598d7',
+ 'generate'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.3766941527',
+ 'agent'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.f121bec167',
+ 'claude'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.542e1a00a7',
+ 'codex'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.82109d627d',
+ 'source control'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.ee14a9e9f7',
+ 'enabled'
+ )
]
},
{
@@ -33,21 +61,66 @@ export const getCommitMessageAiPaneSearchEntries = createLocalizedCatalog(() =>
'Agent, CLI arguments, and command template used by each Source Control AI button.'
),
keywords: [
- translate('auto.components.settings.commit.message.ai.search.3766941527', 'agent'),
- translate('auto.components.settings.commit.message.ai.search.0f29331fed', 'arguments'),
- translate('auto.components.settings.commit.message.ai.search.61117e57f3', 'args'),
- translate('auto.components.settings.commit.message.ai.search.57c851a68c', 'cli'),
- translate('auto.components.settings.commit.message.ai.search.f4731b22bf', 'command'),
- translate('auto.components.settings.commit.message.ai.search.8e0bcc5d99', 'model'),
- translate('auto.components.settings.commit.message.ai.search.b7d50da4d8', 'template'),
- translate('auto.components.settings.commit.message.ai.search.402f101af8', 'prompt'),
- translate('auto.components.settings.commit.message.ai.search.37c65bbb44', 'fix'),
- translate('auto.components.settings.commit.message.ai.search.c46e665f7e', 'checks'),
- translate('auto.components.settings.commit.message.ai.search.53e8504fb2', 'ci'),
- translate('auto.components.settings.commit.message.ai.search.d22a6459e4', 'conflicts'),
- translate('auto.components.settings.commit.message.ai.search.127d512e75', 'commit'),
- translate('auto.components.settings.commit.message.ai.search.110be48b81', 'pull request'),
- translate('auto.components.settings.commit.message.ai.search.d32936bb2a', 'branch')
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.3766941527',
+ 'agent'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.0f29331fed',
+ 'arguments'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.61117e57f3',
+ 'args'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.57c851a68c',
+ 'cli'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.f4731b22bf',
+ 'command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.8e0bcc5d99',
+ 'model'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.b7d50da4d8',
+ 'template'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.402f101af8',
+ 'prompt'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.37c65bbb44',
+ 'fix'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.c46e665f7e',
+ 'checks'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.53e8504fb2',
+ 'ci'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.d22a6459e4',
+ 'conflicts'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.127d512e75',
+ 'commit'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.110be48b81',
+ 'pull request'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.d32936bb2a',
+ 'branch'
+ )
]
},
{
@@ -60,12 +133,30 @@ export const getCommitMessageAiPaneSearchEntries = createLocalizedCatalog(() =>
'Defaults used when the Create PR composer opens.'
),
keywords: [
- translate('auto.components.settings.commit.message.ai.search.110be48b81', 'pull request'),
- translate('auto.components.settings.commit.message.ai.search.b261c88609', 'pr'),
- translate('auto.components.settings.commit.message.ai.search.7e264b926b', 'draft'),
- translate('auto.components.settings.commit.message.ai.search.b7d50da4d8', 'template'),
- translate('auto.components.settings.commit.message.ai.search.8e9cc598d7', 'generate'),
- translate('auto.components.settings.commit.message.ai.search.181cdb0637', 'open')
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.110be48b81',
+ 'pull request'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.b261c88609',
+ 'pr'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.7e264b926b',
+ 'draft'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.b7d50da4d8',
+ 'template'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.8e9cc598d7',
+ 'generate'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.commit.message.ai.search.181cdb0637',
+ 'open'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/computer-use-search.ts b/src/renderer/src/components/settings/computer-use-search.ts
index 5a51a5e3172..1dc154c6287 100644
--- a/src/renderer/src/components/settings/computer-use-search.ts
+++ b/src/renderer/src/components/settings/computer-use-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getComputerUsePaneSearchEntries = createLocalizedCatalog(() => [
@@ -9,12 +10,27 @@ export const getComputerUsePaneSearchEntries = createLocalizedCatalog(() => [
'Allow agents to inspect screenshots and operate local apps when you ask.'
),
keywords: [
- translate('auto.components.settings.computer.use.search.fefb452f5b', 'computer use'),
- translate('auto.components.settings.computer.use.search.82f01c2d2c', 'accessibility'),
- translate('auto.components.settings.computer.use.search.26c1290d83', 'screen recording'),
- translate('auto.components.settings.computer.use.search.e27f8bafbf', 'screenshot'),
- translate('auto.components.settings.computer.use.search.798be54d7e', 'automation'),
- translate('auto.components.settings.computer.use.search.6e88da3508', 'skill')
+ ...translateSearchKeyword(
+ 'auto.components.settings.computer.use.search.fefb452f5b',
+ 'computer use'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.computer.use.search.82f01c2d2c',
+ 'accessibility'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.computer.use.search.26c1290d83',
+ 'screen recording'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.computer.use.search.e27f8bafbf',
+ 'screenshot'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.computer.use.search.798be54d7e',
+ 'automation'
+ ),
+ ...translateSearchKeyword('auto.components.settings.computer.use.search.6e88da3508', 'skill')
]
}
])
diff --git a/src/renderer/src/components/settings/developer-permissions-search.ts b/src/renderer/src/components/settings/developer-permissions-search.ts
index 2e348af055c..92f1a8e202f 100644
--- a/src/renderer/src/components/settings/developer-permissions-search.ts
+++ b/src/renderer/src/components/settings/developer-permissions-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getDeveloperPermissionsPaneSearchEntries = createLocalizedCatalog(() => [
@@ -12,10 +13,22 @@ export const getDeveloperPermissionsPaneSearchEntries = createLocalizedCatalog((
'macOS permissions for terminal-launched developer tools.'
),
keywords: [
- translate('auto.components.settings.developer.permissions.search.a98aa11a9c', 'permissions'),
- translate('auto.components.settings.developer.permissions.search.2270ccff3f', 'privacy'),
- translate('auto.components.settings.developer.permissions.search.0c13b249e3', 'tcc'),
- translate('auto.components.settings.developer.permissions.search.6db4fca386', 'macos'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.a98aa11a9c',
+ 'permissions'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.2270ccff3f',
+ 'privacy'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.0c13b249e3',
+ 'tcc'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.6db4fca386',
+ 'macos'
+ ),
translate(
'auto.components.settings.developer.permissions.search.4e225e7c56',
'developer tools'
@@ -32,14 +45,38 @@ export const getDeveloperPermissionsPaneSearchEntries = createLocalizedCatalog((
'Allow voice, transcription, webcam, and media capture tools.'
),
keywords: [
- translate('auto.components.settings.developer.permissions.search.ed7c12bdb4', 'microphone'),
- translate('auto.components.settings.developer.permissions.search.259b829b84', 'camera'),
- translate('auto.components.settings.developer.permissions.search.af122938a3', 'voice'),
- translate('auto.components.settings.developer.permissions.search.b192432ef0', 'audio'),
- translate('auto.components.settings.developer.permissions.search.a765112513', 'video'),
- translate('auto.components.settings.developer.permissions.search.f061f08b7b', 'sox'),
- translate('auto.components.settings.developer.permissions.search.1e6e27b202', 'ffmpeg'),
- translate('auto.components.settings.developer.permissions.search.00e954319e', 'whisper')
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.ed7c12bdb4',
+ 'microphone'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.259b829b84',
+ 'camera'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.af122938a3',
+ 'voice'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.b192432ef0',
+ 'audio'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.a765112513',
+ 'video'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.f061f08b7b',
+ 'sox'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.1e6e27b202',
+ 'ffmpeg'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.00e954319e',
+ 'whisper'
+ )
]
},
{
@@ -60,9 +97,18 @@ export const getDeveloperPermissionsPaneSearchEntries = createLocalizedCatalog((
'auto.components.settings.developer.permissions.search.08f8039ca9',
'accessibility'
),
- translate('auto.components.settings.developer.permissions.search.0a467b750e', 'screenshot'),
- translate('auto.components.settings.developer.permissions.search.5610022e1e', 'automation'),
- translate('auto.components.settings.developer.permissions.search.7f145a3984', 'window')
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.0a467b750e',
+ 'screenshot'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.5610022e1e',
+ 'automation'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.7f145a3984',
+ 'window'
+ )
]
},
{
@@ -79,10 +125,22 @@ export const getDeveloperPermissionsPaneSearchEntries = createLocalizedCatalog((
'auto.components.settings.developer.permissions.search.c10e36cbd1',
'full disk access'
),
- translate('auto.components.settings.developer.permissions.search.4438f81bfa', 'documents'),
- translate('auto.components.settings.developer.permissions.search.a0c19119fb', 'downloads'),
- translate('auto.components.settings.developer.permissions.search.ce07159ff5', 'desktop'),
- translate('auto.components.settings.developer.permissions.search.3e0131e45d', 'icloud')
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.4438f81bfa',
+ 'documents'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.a0c19119fb',
+ 'downloads'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.ce07159ff5',
+ 'desktop'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.3e0131e45d',
+ 'icloud'
+ )
]
},
{
@@ -99,11 +157,26 @@ export const getDeveloperPermissionsPaneSearchEntries = createLocalizedCatalog((
'auto.components.settings.developer.permissions.search.fa3239cd42',
'local network'
),
- translate('auto.components.settings.developer.permissions.search.c4a4a02ea4', 'usb'),
- translate('auto.components.settings.developer.permissions.search.e3fbc48083', 'bluetooth'),
- translate('auto.components.settings.developer.permissions.search.78a10b826f', 'bonjour'),
- translate('auto.components.settings.developer.permissions.search.11653d3f42', 'mdns'),
- translate('auto.components.settings.developer.permissions.search.6c82846f66', 'device')
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.c4a4a02ea4',
+ 'usb'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.e3fbc48083',
+ 'bluetooth'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.78a10b826f',
+ 'bonjour'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.11653d3f42',
+ 'mdns'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.developer.permissions.search.6c82846f66',
+ 'device'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/experimental-search.ts b/src/renderer/src/components/settings/experimental-search.ts
index 75f94234b2e..893fd5b5321 100644
--- a/src/renderer/src/components/settings/experimental-search.ts
+++ b/src/renderer/src/components/settings/experimental-search.ts
@@ -1,6 +1,7 @@
import type { SettingsSearchEntry } from './settings-search'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
export const getExperimentalPaneSearchEntries = createLocalizedCatalog(
(): SettingsSearchEntry[] => [
@@ -11,14 +12,35 @@ export const getExperimentalPaneSearchEntries = createLocalizedCatalog(
'Floating animated pet in the bottom-right corner.'
),
keywords: [
- translate('auto.components.settings.experimental.search.0d24759f14', 'experimental'),
- translate('auto.components.settings.experimental.search.051203d37c', 'pet'),
- translate('auto.components.settings.experimental.search.b54cea709b', 'sidekick'),
- translate('auto.components.settings.experimental.search.2a33975d72', 'mascot'),
- translate('auto.components.settings.experimental.search.9f5609bfb8', 'overlay'),
- translate('auto.components.settings.experimental.search.65df471ab2', 'animated'),
- translate('auto.components.settings.experimental.search.791fefc0b0', 'corner'),
- translate('auto.components.settings.experimental.search.9af7a518db', 'character')
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.0d24759f14',
+ 'experimental'
+ ),
+ ...translateSearchKeyword('auto.components.settings.experimental.search.051203d37c', 'pet'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.b54cea709b',
+ 'sidekick'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.2a33975d72',
+ 'mascot'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.9f5609bfb8',
+ 'overlay'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.65df471ab2',
+ 'animated'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.791fefc0b0',
+ 'corner'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.9af7a518db',
+ 'character'
+ )
]
},
{
@@ -28,16 +50,46 @@ export const getExperimentalPaneSearchEntries = createLocalizedCatalog(
'Threaded left-sidebar feed for agent completions and blocking states.'
),
keywords: [
- translate('auto.components.settings.experimental.search.0d24759f14', 'experimental'),
- translate('auto.components.settings.experimental.search.fa72e71f05', 'agents'),
- translate('auto.components.settings.experimental.search.92a9357d1f', 'agents view'),
- translate('auto.components.settings.experimental.search.244a0ecd3d', 'activity'),
- translate('auto.components.settings.experimental.search.d01b3882ba', 'notifications'),
- translate('auto.components.settings.experimental.search.10b52f79c1', 'worktrees'),
- translate('auto.components.settings.experimental.search.ca5d1f3f46', 'timeline'),
- translate('auto.components.settings.experimental.search.7b79081695', 'unread'),
- translate('auto.components.settings.experimental.search.8facf10138', 'bell'),
- translate('auto.components.settings.experimental.search.fe5688b761', 'sidebar')
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.0d24759f14',
+ 'experimental'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.fa72e71f05',
+ 'agents'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.92a9357d1f',
+ 'agents view'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.244a0ecd3d',
+ 'activity'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.d01b3882ba',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.10b52f79c1',
+ 'worktrees'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.ca5d1f3f46',
+ 'timeline'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.7b79081695',
+ 'unread'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.8facf10138',
+ 'bell'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.fe5688b761',
+ 'sidebar'
+ )
]
},
{
@@ -50,16 +102,46 @@ export const getExperimentalPaneSearchEntries = createLocalizedCatalog(
'Persistent pane highlight for terminal bell and agent-completion events.'
),
keywords: [
- translate('auto.components.settings.experimental.search.0d24759f14', 'experimental'),
- translate('auto.components.settings.experimental.search.9bb3bd5098', 'terminal'),
- translate('auto.components.settings.experimental.search.01567f19ca', 'attention'),
- translate('auto.components.settings.experimental.search.268e99d957', 'highlight'),
- translate('auto.components.settings.experimental.search.edc49480a1', 'pane'),
- translate('auto.components.settings.experimental.search.8facf10138', 'bell'),
- translate('auto.components.settings.experimental.search.7695fd30e9', 'notification'),
- translate('auto.components.settings.experimental.search.5f067ba0f9', 'agent'),
- translate('auto.components.settings.experimental.search.f10d307468', 'completion'),
- translate('auto.components.settings.experimental.search.7b79081695', 'unread')
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.0d24759f14',
+ 'experimental'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.9bb3bd5098',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.01567f19ca',
+ 'attention'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.268e99d957',
+ 'highlight'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.edc49480a1',
+ 'pane'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.8facf10138',
+ 'bell'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.7695fd30e9',
+ 'notification'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.5f067ba0f9',
+ 'agent'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.f10d307468',
+ 'completion'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.7b79081695',
+ 'unread'
+ )
]
},
{
@@ -72,16 +154,43 @@ export const getExperimentalPaneSearchEntries = createLocalizedCatalog(
'Automatically symlink configured files or folders into newly created worktrees so shared state (envs, caches, installs) stays connected.'
),
keywords: [
- translate('auto.components.settings.experimental.search.0d24759f14', 'experimental'),
- translate('auto.components.settings.experimental.search.d23ae13990', 'worktree'),
- translate('auto.components.settings.experimental.search.10b52f79c1', 'worktrees'),
- translate('auto.components.settings.experimental.search.c387565812', 'symlink'),
- translate('auto.components.settings.experimental.search.bff1ff7768', 'symlinks'),
- translate('auto.components.settings.experimental.search.3028f0bd3a', 'link'),
- translate('auto.components.settings.experimental.search.f082788cfe', 'links'),
- translate('auto.components.settings.experimental.search.3021571c30', 'shared'),
- translate('auto.components.settings.experimental.search.4ad605f222', 'env'),
- translate('auto.components.settings.experimental.search.44c7f209d5', 'node_modules')
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.0d24759f14',
+ 'experimental'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.d23ae13990',
+ 'worktree'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.10b52f79c1',
+ 'worktrees'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.c387565812',
+ 'symlink'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.bff1ff7768',
+ 'symlinks'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.3028f0bd3a',
+ 'link'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.f082788cfe',
+ 'links'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.3021571c30',
+ 'shared'
+ ),
+ ...translateSearchKeyword('auto.components.settings.experimental.search.4ad605f222', 'env'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.experimental.search.44c7f209d5',
+ 'node_modules'
+ )
]
}
]
diff --git a/src/renderer/src/components/settings/floating-workspace-search.ts b/src/renderer/src/components/settings/floating-workspace-search.ts
index 9b8ee7aeb89..9ca0dca43f6 100644
--- a/src/renderer/src/components/settings/floating-workspace-search.ts
+++ b/src/renderer/src/components/settings/floating-workspace-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getFloatingWorkspaceSearchEntries = createLocalizedCatalog(() => [
@@ -20,20 +21,50 @@ export const getFloatingWorkspaceSearchEntries = createLocalizedCatalog(() => [
'auto.components.settings.floating.workspace.search.6f183fa1b9',
'floating terminal'
),
- translate('auto.components.settings.floating.workspace.search.ebeedb2f6a', 'quick terminal'),
- translate('auto.components.settings.floating.workspace.search.2b5efa55c9', 'global'),
- translate('auto.components.settings.floating.workspace.search.6410fe83d8', 'terminal'),
- translate('auto.components.settings.floating.workspace.search.49db74a92d', 'browser'),
- translate('auto.components.settings.floating.workspace.search.884e5e6132', 'markdown'),
- translate('auto.components.settings.floating.workspace.search.156ffeee08', 'note'),
- translate('auto.components.settings.floating.workspace.search.52db6e3baf', 'notes'),
- translate('auto.components.settings.floating.workspace.search.a38bfc3f77', 'quick panel'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.ebeedb2f6a',
+ 'quick terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.2b5efa55c9',
+ 'global'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.6410fe83d8',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.49db74a92d',
+ 'browser'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.884e5e6132',
+ 'markdown'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.156ffeee08',
+ 'note'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.52db6e3baf',
+ 'notes'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.a38bfc3f77',
+ 'quick panel'
+ ),
translate(
'auto.components.settings.floating.workspace.search.6765b85e48',
'launch directory'
),
- translate('auto.components.settings.floating.workspace.search.a452146574', 'toggle button'),
- translate('auto.components.settings.floating.workspace.search.94f4d013c8', 'status bar')
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.a452146574',
+ 'toggle button'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.floating.workspace.search.94f4d013c8',
+ 'status bar'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/general-editor-search.ts b/src/renderer/src/components/settings/general-editor-search.ts
index 135005f01fa..0a13d7c5dd8 100644
--- a/src/renderer/src/components/settings/general-editor-search.ts
+++ b/src/renderer/src/components/settings/general-editor-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
@@ -9,8 +10,8 @@ export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
'Save editor and editable diff changes automatically after a short pause.'
),
keywords: [
- translate('auto.components.settings.general.search.86f54575c7', 'autosave'),
- translate('auto.components.settings.general.search.4469b6fa4e', 'save')
+ ...translateSearchKeyword('auto.components.settings.general.search.86f54575c7', 'autosave'),
+ ...translateSearchKeyword('auto.components.settings.general.search.4469b6fa4e', 'save')
]
},
{
@@ -20,9 +21,12 @@ export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
'How long Orca waits after your last edit before saving automatically.'
),
keywords: [
- translate('auto.components.settings.general.search.86f54575c7', 'autosave'),
- translate('auto.components.settings.general.search.146728ac2c', 'delay'),
- translate('auto.components.settings.general.search.b2799ba622', 'milliseconds')
+ ...translateSearchKeyword('auto.components.settings.general.search.86f54575c7', 'autosave'),
+ ...translateSearchKeyword('auto.components.settings.general.search.146728ac2c', 'delay'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.b2799ba622',
+ 'milliseconds'
+ )
]
},
{
@@ -32,11 +36,14 @@ export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
'Preferred presentation format for showing git diffs by default.'
),
keywords: [
- translate('auto.components.settings.general.search.3b5733573e', 'diff'),
- translate('auto.components.settings.general.search.2b463f0bf9', 'view'),
- translate('auto.components.settings.general.search.0a5fa65926', 'inline'),
- translate('auto.components.settings.general.search.233f7e2f37', 'side-by-side'),
- translate('auto.components.settings.general.search.be24c7cd67', 'split')
+ ...translateSearchKeyword('auto.components.settings.general.search.3b5733573e', 'diff'),
+ ...translateSearchKeyword('auto.components.settings.general.search.2b463f0bf9', 'view'),
+ ...translateSearchKeyword('auto.components.settings.general.search.0a5fa65926', 'inline'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.233f7e2f37',
+ 'side-by-side'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.be24c7cd67', 'split')
]
},
{
@@ -49,11 +56,14 @@ export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
'Show or hide the file tree when opening combined diff views.'
),
keywords: [
- translate('auto.components.settings.general.search.3b5733573e', 'diff'),
- translate('auto.components.settings.general.search.2f42852568', 'tree'),
- translate('auto.components.settings.general.search.0a02059549', 'file tree'),
- translate('auto.components.settings.general.search.973ed6bfbf', 'combined diff'),
- translate('auto.components.settings.general.search.19baae651b', 'sidebar')
+ ...translateSearchKeyword('auto.components.settings.general.search.3b5733573e', 'diff'),
+ ...translateSearchKeyword('auto.components.settings.general.search.2f42852568', 'tree'),
+ ...translateSearchKeyword('auto.components.settings.general.search.0a02059549', 'file tree'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.973ed6bfbf',
+ 'combined diff'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.19baae651b', 'sidebar')
]
},
{
@@ -63,10 +73,10 @@ export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
'Show the minimap overview when editing a file.'
),
keywords: [
- translate('auto.components.settings.general.search.9c72990db8', 'minimap'),
- translate('auto.components.settings.general.search.e3919429c0', 'overview'),
- translate('auto.components.settings.general.search.3ca5ab78a5', 'code'),
- translate('auto.components.settings.general.search.a0014961ae', 'scroll')
+ ...translateSearchKeyword('auto.components.settings.general.search.9c72990db8', 'minimap'),
+ ...translateSearchKeyword('auto.components.settings.general.search.e3919429c0', 'overview'),
+ ...translateSearchKeyword('auto.components.settings.general.search.3ca5ab78a5', 'code'),
+ ...translateSearchKeyword('auto.components.settings.general.search.a0014961ae', 'scroll')
]
},
{
@@ -76,11 +86,14 @@ export const getGeneralEditorSearchEntries = createLocalizedCatalog(() => [
'Show local markdown review note controls in rich editor mode.'
),
keywords: [
- translate('auto.components.settings.general.search.d05f629d2c', 'markdown'),
- translate('auto.components.settings.general.search.4dd5684836', 'review'),
- translate('auto.components.settings.general.search.1ff67ba40c', 'notes'),
- translate('auto.components.settings.general.search.22572e99c1', 'annotations'),
- translate('auto.components.settings.general.search.baa263d6d8', 'agents')
+ ...translateSearchKeyword('auto.components.settings.general.search.d05f629d2c', 'markdown'),
+ ...translateSearchKeyword('auto.components.settings.general.search.4dd5684836', 'review'),
+ ...translateSearchKeyword('auto.components.settings.general.search.1ff67ba40c', 'notes'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.22572e99c1',
+ 'annotations'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.baa263d6d8', 'agents')
]
}
])
diff --git a/src/renderer/src/components/settings/general-search.ts b/src/renderer/src/components/settings/general-search.ts
index 5b994a77e3d..993ee0d82e9 100644
--- a/src/renderer/src/components/settings/general-search.ts
+++ b/src/renderer/src/components/settings/general-search.ts
@@ -1,6 +1,7 @@
import type { SettingsSearchEntry } from './settings-search'
import { getGeneralEditorSearchEntries } from './general-editor-search'
import { translate } from '@/i18n/i18n'
+import { searchKeywords, translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export { getGeneralEditorSearchEntries } from './general-editor-search'
@@ -13,10 +14,10 @@ export const getGeneralWorkspaceSearchEntries = createLocalizedCatalog(() => [
'Root directory where workspace folders are created.'
),
keywords: [
- translate('auto.components.settings.general.search.7baf524b04', 'workspace'),
- translate('auto.components.settings.general.search.7887a2c262', 'folder'),
- translate('auto.components.settings.general.search.fb4f338a3d', 'path'),
- translate('auto.components.settings.general.search.df10666259', 'worktree')
+ ...translateSearchKeyword('auto.components.settings.general.search.7baf524b04', 'workspace'),
+ ...translateSearchKeyword('auto.components.settings.general.search.7887a2c262', 'folder'),
+ ...translateSearchKeyword('auto.components.settings.general.search.fb4f338a3d', 'path'),
+ ...translateSearchKeyword('auto.components.settings.general.search.df10666259', 'worktree')
]
},
{
@@ -26,9 +27,9 @@ export const getGeneralWorkspaceSearchEntries = createLocalizedCatalog(() => [
'Create workspaces inside a repo-named subfolder.'
),
keywords: [
- translate('auto.components.settings.general.search.ec5049e510', 'nested'),
- translate('auto.components.settings.general.search.9bde064915', 'subfolder'),
- translate('auto.components.settings.general.search.93f6ec5e70', 'directory')
+ ...translateSearchKeyword('auto.components.settings.general.search.ec5049e510', 'nested'),
+ ...translateSearchKeyword('auto.components.settings.general.search.9bde064915', 'subfolder'),
+ ...translateSearchKeyword('auto.components.settings.general.search.93f6ec5e70', 'directory')
]
},
{
@@ -41,12 +42,12 @@ export const getGeneralWorkspaceSearchEntries = createLocalizedCatalog(() => [
'Show a confirmation dialog before deleting a workspace.'
),
keywords: [
- translate('auto.components.settings.general.search.84c67d0108', 'delete'),
- translate('auto.components.settings.general.search.df10666259', 'worktree'),
- translate('auto.components.settings.general.search.9f8558233a', 'confirm'),
- translate('auto.components.settings.general.search.ca86dd6e27', 'dialog'),
- translate('auto.components.settings.general.search.7e9b556873', 'skip'),
- translate('auto.components.settings.general.search.0efc9d96ad', 'prompt')
+ ...translateSearchKeyword('auto.components.settings.general.search.84c67d0108', 'delete'),
+ ...translateSearchKeyword('auto.components.settings.general.search.df10666259', 'worktree'),
+ ...translateSearchKeyword('auto.components.settings.general.search.9f8558233a', 'confirm'),
+ ...translateSearchKeyword('auto.components.settings.general.search.ca86dd6e27', 'dialog'),
+ ...translateSearchKeyword('auto.components.settings.general.search.7e9b556873', 'skip'),
+ ...translateSearchKeyword('auto.components.settings.general.search.0efc9d96ad', 'prompt')
]
},
{
@@ -59,12 +60,12 @@ export const getGeneralWorkspaceSearchEntries = createLocalizedCatalog(() => [
'Show a confirmation dialog before deleting an automation and its run history.'
),
keywords: [
- translate('auto.components.settings.general.search.84c67d0108', 'delete'),
- translate('auto.components.settings.general.search.7edf4f69e2', 'automation'),
- translate('auto.components.settings.general.search.9f8558233a', 'confirm'),
- translate('auto.components.settings.general.search.ca86dd6e27', 'dialog'),
- translate('auto.components.settings.general.search.7e9b556873', 'skip'),
- translate('auto.components.settings.general.search.0efc9d96ad', 'prompt')
+ ...translateSearchKeyword('auto.components.settings.general.search.84c67d0108', 'delete'),
+ ...translateSearchKeyword('auto.components.settings.general.search.7edf4f69e2', 'automation'),
+ ...translateSearchKeyword('auto.components.settings.general.search.9f8558233a', 'confirm'),
+ ...translateSearchKeyword('auto.components.settings.general.search.ca86dd6e27', 'dialog'),
+ ...translateSearchKeyword('auto.components.settings.general.search.7e9b556873', 'skip'),
+ ...translateSearchKeyword('auto.components.settings.general.search.0efc9d96ad', 'prompt')
]
},
{
@@ -74,16 +75,19 @@ export const getGeneralWorkspaceSearchEntries = createLocalizedCatalog(() => [
"Choose apps available from a workspace's Open in menu."
),
keywords: [
- translate('auto.components.settings.general.search.b8093e9a93', 'open in'),
- translate('auto.components.settings.general.search.5a9df5566f', 'open menu'),
- translate('auto.components.settings.general.search.e1ee631696', 'editor'),
- translate('auto.components.settings.general.search.8fb00fcd05', 'launcher'),
- translate('auto.components.settings.general.search.0cb3d94f00', 'cursor'),
- translate('auto.components.settings.general.search.ebf8f056b5', 'zed'),
- translate('auto.components.settings.general.search.dbeb1f348e', 'command'),
- translate('auto.components.settings.general.search.68d03d9980', 'vscode'),
- translate('auto.components.settings.general.search.c9d9636f24', 'finder'),
- translate('auto.components.settings.general.search.6c2ce8457c', 'file explorer')
+ ...translateSearchKeyword('auto.components.settings.general.search.b8093e9a93', 'open in'),
+ ...translateSearchKeyword('auto.components.settings.general.search.5a9df5566f', 'open menu'),
+ ...translateSearchKeyword('auto.components.settings.general.search.e1ee631696', 'editor'),
+ ...translateSearchKeyword('auto.components.settings.general.search.8fb00fcd05', 'launcher'),
+ ...translateSearchKeyword('auto.components.settings.general.search.0cb3d94f00', 'cursor'),
+ ...translateSearchKeyword('auto.components.settings.general.search.ebf8f056b5', 'zed'),
+ ...translateSearchKeyword('auto.components.settings.general.search.dbeb1f348e', 'command'),
+ ...translateSearchKeyword('auto.components.settings.general.search.68d03d9980', 'vscode'),
+ ...translateSearchKeyword('auto.components.settings.general.search.c9d9636f24', 'finder'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.6c2ce8457c',
+ 'file explorer'
+ )
]
}
])
@@ -96,12 +100,15 @@ export const getGeneralNetworkSearchEntries = createLocalizedCatalog(() => [
'Proxy URL for Orca network requests and local terminal children.'
),
keywords: [
- translate('auto.components.settings.general.search.20b711ac9e', 'proxy'),
- translate('auto.components.settings.general.search.8f03d44672', 'http_proxy'),
- translate('auto.components.settings.general.search.b9096a44cf', 'https_proxy'),
- translate('auto.components.settings.general.search.c56cb6f1c2', 'network'),
- translate('auto.components.settings.general.search.9da6c875e5', 'dock'),
- translate('auto.components.settings.general.search.e55d62dfa4', 'launchpad')
+ ...translateSearchKeyword('auto.components.settings.general.search.20b711ac9e', 'proxy'),
+ ...translateSearchKeyword('auto.components.settings.general.search.8f03d44672', 'http_proxy'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.b9096a44cf',
+ 'https_proxy'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.c56cb6f1c2', 'network'),
+ ...translateSearchKeyword('auto.components.settings.general.search.9da6c875e5', 'dock'),
+ ...translateSearchKeyword('auto.components.settings.general.search.e55d62dfa4', 'launchpad')
]
},
{
@@ -111,11 +118,11 @@ export const getGeneralNetworkSearchEntries = createLocalizedCatalog(() => [
'Hosts that should bypass the configured HTTP proxy.'
),
keywords: [
- translate('auto.components.settings.general.search.20b711ac9e', 'proxy'),
- translate('auto.components.settings.general.search.3a73054565', 'bypass'),
- translate('auto.components.settings.general.search.91a46caafc', 'no_proxy'),
- translate('auto.components.settings.general.search.3566fce83f', 'localhost'),
- translate('auto.components.settings.general.search.c56cb6f1c2', 'network')
+ ...translateSearchKeyword('auto.components.settings.general.search.20b711ac9e', 'proxy'),
+ ...translateSearchKeyword('auto.components.settings.general.search.3a73054565', 'bypass'),
+ ...translateSearchKeyword('auto.components.settings.general.search.91a46caafc', 'no_proxy'),
+ ...translateSearchKeyword('auto.components.settings.general.search.3566fce83f', 'localhost'),
+ ...translateSearchKeyword('auto.components.settings.general.search.c56cb6f1c2', 'network')
]
}
])
@@ -128,14 +135,17 @@ export const getGeneralNavigationSearchEntries = createLocalizedCatalog(() => [
'Recent or tab strip.'
),
keywords: [
- translate('auto.components.settings.general.search.ca812803ea', 'recent tab order'),
- translate('auto.components.settings.general.search.2a254b725e', 'tab'),
- translate('auto.components.settings.general.search.fe62b3f09f', 'ctrl'),
- translate('auto.components.settings.general.search.750420dd9a', 'control'),
- translate('auto.components.settings.general.search.54ba13831a', 'recent'),
- translate('auto.components.settings.general.search.12ecc640a8', 'mru'),
- translate('auto.components.settings.general.search.f8f0ac213a', 'sequential'),
- translate('auto.components.settings.general.search.fb84767421', 'switch')
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.ca812803ea',
+ 'recent tab order'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.2a254b725e', 'tab'),
+ ...translateSearchKeyword('auto.components.settings.general.search.fe62b3f09f', 'ctrl'),
+ ...translateSearchKeyword('auto.components.settings.general.search.750420dd9a', 'control'),
+ ...translateSearchKeyword('auto.components.settings.general.search.54ba13831a', 'recent'),
+ ...translateSearchKeyword('auto.components.settings.general.search.12ecc640a8', 'mru'),
+ ...translateSearchKeyword('auto.components.settings.general.search.f8f0ac213a', 'sequential'),
+ ...translateSearchKeyword('auto.components.settings.general.search.fb84767421', 'switch')
]
}
])
@@ -148,13 +158,21 @@ export const getGeneralCliSearchEntries = createLocalizedCatalog(() => [
'Register or remove the Orca CLI command.'
),
keywords: [
- translate('auto.components.settings.general.search.924a660a78', 'cli'),
- translate('auto.components.settings.general.search.fb4f338a3d', 'path'),
- translate('auto.components.settings.general.search.88d3df9ce9', 'terminal'),
- translate('auto.components.settings.general.search.dbeb1f348e', 'command'),
- translate('auto.components.settings.general.search.0a00691c06', 'shell command')
+ ...translateSearchKeyword('auto.components.settings.general.search.924a660a78', 'cli'),
+ ...translateSearchKeyword('auto.components.settings.general.search.fb4f338a3d', 'path'),
+ ...translateSearchKeyword('auto.components.settings.general.search.88d3df9ce9', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.general.search.dbeb1f348e', 'command'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.0a00691c06',
+ 'shell command'
+ )
],
- cmdJKeywords: ['cli', 'path', 'command', 'shell command'],
+ cmdJKeywords: searchKeywords([
+ { key: 'auto.components.settings.general.search.924a660a78', fallback: 'cli' },
+ { key: 'auto.components.settings.general.search.fb4f338a3d', fallback: 'path' },
+ { key: 'auto.components.settings.general.search.dbeb1f348e', fallback: 'command' },
+ { key: 'auto.components.settings.general.search.0a00691c06', fallback: 'shell command' }
+ ]),
targetSectionId: 'cli'
},
{
@@ -164,9 +182,9 @@ export const getGeneralCliSearchEntries = createLocalizedCatalog(() => [
'Install the Orca skill so agents know to use the Orca CLI.'
),
keywords: [
- translate('auto.components.settings.general.search.bda108e66c', 'skill'),
- translate('auto.components.settings.general.search.baa263d6d8', 'agents'),
- translate('auto.components.settings.general.search.6382fe9724', 'npx')
+ ...translateSearchKeyword('auto.components.settings.general.search.bda108e66c', 'skill'),
+ ...translateSearchKeyword('auto.components.settings.general.search.baa263d6d8', 'agents'),
+ ...translateSearchKeyword('auto.components.settings.general.search.6382fe9724', 'npx')
]
}
])
@@ -179,10 +197,13 @@ export const getGeneralUpdateSearchEntries = createLocalizedCatalog(() => [
'Check for app updates and install a newer Orca version.'
),
keywords: [
- translate('auto.components.settings.general.search.f89a94773c', 'update'),
- translate('auto.components.settings.general.search.9e86ccd05c', 'version'),
- translate('auto.components.settings.general.search.c9d8c1ce66', 'release notes'),
- translate('auto.components.settings.general.search.e49e739a59', 'download')
+ ...translateSearchKeyword('auto.components.settings.general.search.f89a94773c', 'update'),
+ ...translateSearchKeyword('auto.components.settings.general.search.9e86ccd05c', 'version'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.c9d8c1ce66',
+ 'release notes'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.e49e739a59', 'download')
]
}
])
@@ -195,13 +216,13 @@ export const getGeneralCacheTimerSearchEntries = createLocalizedCatalog(() => [
'Countdown timer showing time until prompt cache expires (Claude agents).'
),
keywords: [
- translate('auto.components.settings.general.search.b2601a778c', 'cache'),
- translate('auto.components.settings.general.search.939b80f5fd', 'timer'),
- translate('auto.components.settings.general.search.0efc9d96ad', 'prompt'),
- translate('auto.components.settings.general.search.585beac3f8', 'ttl'),
- translate('auto.components.settings.general.search.95b63edde7', 'claude'),
- translate('auto.components.settings.general.search.660528b048', 'cost'),
- translate('auto.components.settings.general.search.3462308bd3', 'tokens')
+ ...translateSearchKeyword('auto.components.settings.general.search.b2601a778c', 'cache'),
+ ...translateSearchKeyword('auto.components.settings.general.search.939b80f5fd', 'timer'),
+ ...translateSearchKeyword('auto.components.settings.general.search.0efc9d96ad', 'prompt'),
+ ...translateSearchKeyword('auto.components.settings.general.search.585beac3f8', 'ttl'),
+ ...translateSearchKeyword('auto.components.settings.general.search.95b63edde7', 'claude'),
+ ...translateSearchKeyword('auto.components.settings.general.search.660528b048', 'cost'),
+ ...translateSearchKeyword('auto.components.settings.general.search.3462308bd3', 'tokens')
]
}
])
@@ -214,19 +235,22 @@ export const getGeneralAgentSearchEntries = createLocalizedCatalog(() => [
'Pre-select an AI coding agent in the new-workspace composer.'
),
keywords: [
- translate('auto.components.settings.general.search.8ea37a05bc', 'agent'),
- translate('auto.components.settings.general.search.41c2f9a025', 'default'),
- translate('auto.components.settings.general.search.95b63edde7', 'claude'),
- translate('auto.components.settings.general.search.aea7d2cccb', 'openclaude'),
- translate('auto.components.settings.general.search.5baf51c4d9', 'open claude'),
- translate('auto.components.settings.general.search.27d9b996ba', 'codex'),
- translate('auto.components.settings.general.search.882c4896fd', 'opencode'),
- translate('auto.components.settings.general.search.9b0bc30160', 'pi'),
- translate('auto.components.settings.general.search.5fdf1dc2d1', 'omp'),
- translate('auto.components.settings.general.search.3c30fe2d51', 'gemini'),
- translate('auto.components.settings.general.search.f472e97440', 'aider'),
- translate('auto.components.settings.general.search.5d9ba08673', 'copilot'),
- translate('auto.components.settings.general.search.c61b14be7c', 'grok')
+ ...translateSearchKeyword('auto.components.settings.general.search.8ea37a05bc', 'agent'),
+ ...translateSearchKeyword('auto.components.settings.general.search.41c2f9a025', 'default'),
+ ...translateSearchKeyword('auto.components.settings.general.search.95b63edde7', 'claude'),
+ ...translateSearchKeyword('auto.components.settings.general.search.aea7d2cccb', 'openclaude'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.general.search.5baf51c4d9',
+ 'open claude'
+ ),
+ ...translateSearchKeyword('auto.components.settings.general.search.27d9b996ba', 'codex'),
+ ...translateSearchKeyword('auto.components.settings.general.search.882c4896fd', 'opencode'),
+ ...translateSearchKeyword('auto.components.settings.general.search.9b0bc30160', 'pi'),
+ ...translateSearchKeyword('auto.components.settings.general.search.5fdf1dc2d1', 'omp'),
+ ...translateSearchKeyword('auto.components.settings.general.search.3c30fe2d51', 'gemini'),
+ ...translateSearchKeyword('auto.components.settings.general.search.f472e97440', 'aider'),
+ ...translateSearchKeyword('auto.components.settings.general.search.5d9ba08673', 'copilot'),
+ ...translateSearchKeyword('auto.components.settings.general.search.c61b14be7c', 'grok')
]
}
])
@@ -239,11 +263,11 @@ export const getGeneralSupportSearchEntries = createLocalizedCatalog(() => [
'Support the project with a GitHub star via the gh CLI.'
),
keywords: [
- translate('auto.components.settings.general.search.e4fb4516d0', 'star'),
- translate('auto.components.settings.general.search.06ea5a69a6', 'github'),
- translate('auto.components.settings.general.search.b65665703a', 'support'),
- translate('auto.components.settings.general.search.e6b01c8e30', 'feedback'),
- translate('auto.components.settings.general.search.bdfb6dc21b', 'like')
+ ...translateSearchKeyword('auto.components.settings.general.search.e4fb4516d0', 'star'),
+ ...translateSearchKeyword('auto.components.settings.general.search.06ea5a69a6', 'github'),
+ ...translateSearchKeyword('auto.components.settings.general.search.b65665703a', 'support'),
+ ...translateSearchKeyword('auto.components.settings.general.search.e6b01c8e30', 'feedback'),
+ ...translateSearchKeyword('auto.components.settings.general.search.bdfb6dc21b', 'like')
]
}
])
diff --git a/src/renderer/src/components/settings/git-search.ts b/src/renderer/src/components/settings/git-search.ts
index fa8283185fa..f3d7b5e66cb 100644
--- a/src/renderer/src/components/settings/git-search.ts
+++ b/src/renderer/src/components/settings/git-search.ts
@@ -1,5 +1,6 @@
import { getAutoRenameBranchSearchEntries } from './auto-rename-branch-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getGitPaneSearchEntries = createLocalizedCatalog(() => [
@@ -10,9 +11,9 @@ export const getGitPaneSearchEntries = createLocalizedCatalog(() => [
'Prefix added to branch names when creating worktrees.'
),
keywords: [
- translate('auto.components.settings.git.search.f83c8937c4', 'branch naming'),
- translate('auto.components.settings.git.search.1d2fae1fa2', 'git username'),
- translate('auto.components.settings.git.search.769ddd7f81', 'custom')
+ ...translateSearchKeyword('auto.components.settings.git.search.f83c8937c4', 'branch naming'),
+ ...translateSearchKeyword('auto.components.settings.git.search.1d2fae1fa2', 'git username'),
+ ...translateSearchKeyword('auto.components.settings.git.search.769ddd7f81', 'custom')
]
},
{
@@ -25,18 +26,21 @@ export const getGitPaneSearchEntries = createLocalizedCatalog(() => [
'When you create a workspace, Orca refreshes the remote base and safely fast-forwards your matching local branch, such as main or master. This keeps commands like git diff main...HEAD from comparing against stale history. Orca skips the update if that branch has uncommitted changes or local-only commits.'
),
keywords: [
- translate('auto.components.settings.git.search.e3e9adde59', 'main'),
- translate('auto.components.settings.git.search.28192e3a63', 'master'),
- translate('auto.components.settings.git.search.564942ffc5', 'origin/main'),
- translate('auto.components.settings.git.search.6ee3cfff02', 'git diff'),
- translate('auto.components.settings.git.search.c41e345153', 'behind main'),
- translate('auto.components.settings.git.search.0849b571fe', 'up to date'),
- translate('auto.components.settings.git.search.d9f70d51a0', 'stale main'),
- translate('auto.components.settings.git.search.ab0e22c9f6', 'refresh local main'),
- translate('auto.components.settings.git.search.de06e9d105', 'base ref'),
- translate('auto.components.settings.git.search.bae91effdd', 'fresh base'),
- translate('auto.components.settings.git.search.0c75583ca9', 'safely'),
- translate('auto.components.settings.git.search.035134fcd9', 'worktree')
+ ...translateSearchKeyword('auto.components.settings.git.search.e3e9adde59', 'main'),
+ ...translateSearchKeyword('auto.components.settings.git.search.28192e3a63', 'master'),
+ ...translateSearchKeyword('auto.components.settings.git.search.564942ffc5', 'origin/main'),
+ ...translateSearchKeyword('auto.components.settings.git.search.6ee3cfff02', 'git diff'),
+ ...translateSearchKeyword('auto.components.settings.git.search.c41e345153', 'behind main'),
+ ...translateSearchKeyword('auto.components.settings.git.search.0849b571fe', 'up to date'),
+ ...translateSearchKeyword('auto.components.settings.git.search.d9f70d51a0', 'stale main'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.git.search.ab0e22c9f6',
+ 'refresh local main'
+ ),
+ ...translateSearchKeyword('auto.components.settings.git.search.de06e9d105', 'base ref'),
+ ...translateSearchKeyword('auto.components.settings.git.search.bae91effdd', 'fresh base'),
+ ...translateSearchKeyword('auto.components.settings.git.search.0c75583ca9', 'safely'),
+ ...translateSearchKeyword('auto.components.settings.git.search.035134fcd9', 'worktree')
]
},
...getAutoRenameBranchSearchEntries(),
@@ -47,11 +51,11 @@ export const getGitPaneSearchEntries = createLocalizedCatalog(() => [
'Current GitHub CLI REST, Search, and GraphQL rate limits.'
),
keywords: [
- translate('auto.components.settings.git.search.d088806071', 'github'),
- translate('auto.components.settings.git.search.16f53f7323', 'gh'),
- translate('auto.components.settings.git.search.65b69d9f80', 'graphql'),
- translate('auto.components.settings.git.search.b7e52124c7', 'rate limit'),
- translate('auto.components.settings.git.search.40f9b815fd', 'api budget')
+ ...translateSearchKeyword('auto.components.settings.git.search.d088806071', 'github'),
+ ...translateSearchKeyword('auto.components.settings.git.search.16f53f7323', 'gh'),
+ ...translateSearchKeyword('auto.components.settings.git.search.65b69d9f80', 'graphql'),
+ ...translateSearchKeyword('auto.components.settings.git.search.b7e52124c7', 'rate limit'),
+ ...translateSearchKeyword('auto.components.settings.git.search.40f9b815fd', 'api budget')
]
},
{
@@ -61,10 +65,10 @@ export const getGitPaneSearchEntries = createLocalizedCatalog(() => [
'Current GitLab CLI REST rate-limit headers when available.'
),
keywords: [
- translate('auto.components.settings.git.search.4808f065b3', 'gitlab'),
- translate('auto.components.settings.git.search.ead733645f', 'glab'),
- translate('auto.components.settings.git.search.b7e52124c7', 'rate limit'),
- translate('auto.components.settings.git.search.40f9b815fd', 'api budget')
+ ...translateSearchKeyword('auto.components.settings.git.search.4808f065b3', 'gitlab'),
+ ...translateSearchKeyword('auto.components.settings.git.search.ead733645f', 'glab'),
+ ...translateSearchKeyword('auto.components.settings.git.search.b7e52124c7', 'rate limit'),
+ ...translateSearchKeyword('auto.components.settings.git.search.40f9b815fd', 'api budget')
]
},
{
@@ -74,14 +78,14 @@ export const getGitPaneSearchEntries = createLocalizedCatalog(() => [
'Add Orca attribution to commits, PRs, and issues.'
),
keywords: [
- translate('auto.components.settings.git.search.d088806071', 'github'),
- translate('auto.components.settings.git.search.16f53f7323', 'gh'),
- translate('auto.components.settings.git.search.6bdea421bb', 'pr'),
- translate('auto.components.settings.git.search.af0a144bfb', 'issue'),
- translate('auto.components.settings.git.search.61f9f5d1fc', 'co-author'),
- translate('auto.components.settings.git.search.8461c908ae', 'coauthored'),
- translate('auto.components.settings.git.search.1b93c1143c', 'attribution'),
- translate('auto.components.settings.git.search.61eab13403', 'orca')
+ ...translateSearchKeyword('auto.components.settings.git.search.d088806071', 'github'),
+ ...translateSearchKeyword('auto.components.settings.git.search.16f53f7323', 'gh'),
+ ...translateSearchKeyword('auto.components.settings.git.search.6bdea421bb', 'pr'),
+ ...translateSearchKeyword('auto.components.settings.git.search.af0a144bfb', 'issue'),
+ ...translateSearchKeyword('auto.components.settings.git.search.61f9f5d1fc', 'co-author'),
+ ...translateSearchKeyword('auto.components.settings.git.search.8461c908ae', 'coauthored'),
+ ...translateSearchKeyword('auto.components.settings.git.search.1b93c1143c', 'attribution'),
+ ...translateSearchKeyword('auto.components.settings.git.search.61eab13403', 'orca')
]
}
])
diff --git a/src/renderer/src/components/settings/input-search.ts b/src/renderer/src/components/settings/input-search.ts
index 21d781079db..f756d0aedad 100644
--- a/src/renderer/src/components/settings/input-search.ts
+++ b/src/renderer/src/components/settings/input-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getInputPaneSearchEntries = createLocalizedCatalog(() => [
@@ -12,17 +13,20 @@ export const getInputPaneSearchEntries = createLocalizedCatalog(() => [
'Enabled by default on Linux and macOS. Linux uses the system selection clipboard; other platforms use a private buffer.'
),
keywords: [
- translate('auto.components.settings.input.search.b51d47ceb7', 'input'),
- translate('auto.components.settings.input.search.e25165320e', 'editing'),
- translate('auto.components.settings.input.search.e5cd0e7a46', 'selection'),
- translate('auto.components.settings.input.search.de51e18ee9', 'primary selection'),
- translate('auto.components.settings.input.search.31ba58c8ae', 'middle click'),
- translate('auto.components.settings.input.search.5fb84ba77f', 'middle mouse'),
- translate('auto.components.settings.input.search.c4440c3986', 'paste'),
- translate('auto.components.settings.input.search.7059cfb00a', 'clipboard'),
- translate('auto.components.settings.input.search.71905435dd', 'x11'),
- translate('auto.components.settings.input.search.26c83b06c5', 'linux'),
- translate('auto.components.settings.input.search.886597d6b3', 'macos')
+ ...translateSearchKeyword('auto.components.settings.input.search.b51d47ceb7', 'input'),
+ ...translateSearchKeyword('auto.components.settings.input.search.e25165320e', 'editing'),
+ ...translateSearchKeyword('auto.components.settings.input.search.e5cd0e7a46', 'selection'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.input.search.de51e18ee9',
+ 'primary selection'
+ ),
+ ...translateSearchKeyword('auto.components.settings.input.search.31ba58c8ae', 'middle click'),
+ ...translateSearchKeyword('auto.components.settings.input.search.5fb84ba77f', 'middle mouse'),
+ ...translateSearchKeyword('auto.components.settings.input.search.c4440c3986', 'paste'),
+ ...translateSearchKeyword('auto.components.settings.input.search.7059cfb00a', 'clipboard'),
+ ...translateSearchKeyword('auto.components.settings.input.search.71905435dd', 'x11'),
+ ...translateSearchKeyword('auto.components.settings.input.search.26c83b06c5', 'linux'),
+ ...translateSearchKeyword('auto.components.settings.input.search.886597d6b3', 'macos')
]
}
])
diff --git a/src/renderer/src/components/settings/integrations-search.ts b/src/renderer/src/components/settings/integrations-search.ts
index 2430c8b6ac9..2a742728c3c 100644
--- a/src/renderer/src/components/settings/integrations-search.ts
+++ b/src/renderer/src/components/settings/integrations-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
@@ -12,9 +13,15 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'GitHub authentication via the gh CLI.'
),
keywords: [
- translate('auto.components.settings.integrations.search.b79c21bd42', 'github'),
- translate('auto.components.settings.integrations.search.41ccade05c', 'gh'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration')
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.b79c21bd42',
+ 'github'
+ ),
+ ...translateSearchKeyword('auto.components.settings.integrations.search.41ccade05c', 'gh'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ )
]
},
{
@@ -27,11 +34,20 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'GitLab authentication via the glab CLI.'
),
keywords: [
- translate('auto.components.settings.integrations.search.b939695c69', 'gitlab'),
- translate('auto.components.settings.integrations.search.b40cbe5de4', 'glab'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration'),
- translate('auto.components.settings.integrations.search.581844769a', 'mr'),
- translate('auto.components.settings.integrations.search.371ee914d2', 'merge request')
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.b939695c69',
+ 'gitlab'
+ ),
+ ...translateSearchKeyword('auto.components.settings.integrations.search.b40cbe5de4', 'glab'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ ),
+ ...translateSearchKeyword('auto.components.settings.integrations.search.581844769a', 'mr'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.371ee914d2',
+ 'merge request'
+ )
]
},
{
@@ -44,10 +60,22 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'Bitbucket Cloud authentication via API token environment variables.'
),
keywords: [
- translate('auto.components.settings.integrations.search.50d20817f7', 'bitbucket'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration'),
- translate('auto.components.settings.integrations.search.8c568d761c', 'pull request'),
- translate('auto.components.settings.integrations.search.2ec2bd328c', 'api token')
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.50d20817f7',
+ 'bitbucket'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.8c568d761c',
+ 'pull request'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.2ec2bd328c',
+ 'api token'
+ )
]
},
{
@@ -60,12 +88,27 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'Azure DevOps Repos authentication via token environment variables.'
),
keywords: [
- translate('auto.components.settings.integrations.search.b38b5d27f1', 'azure devops'),
- translate('auto.components.settings.integrations.search.ed63380247', 'azure repos'),
- translate('auto.components.settings.integrations.search.03a7b275be', 'ado'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration'),
- translate('auto.components.settings.integrations.search.8c568d761c', 'pull request'),
- translate('auto.components.settings.integrations.search.2ec2bd328c', 'api token')
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.b38b5d27f1',
+ 'azure devops'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.ed63380247',
+ 'azure repos'
+ ),
+ ...translateSearchKeyword('auto.components.settings.integrations.search.03a7b275be', 'ado'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.8c568d761c',
+ 'pull request'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.2ec2bd328c',
+ 'api token'
+ )
]
},
{
@@ -78,11 +121,23 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'Gitea authentication via API token environment variables.'
),
keywords: [
- translate('auto.components.settings.integrations.search.129fc59aa8', 'gitea'),
- translate('auto.components.settings.integrations.search.33180e8c10', 'self-hosted'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration'),
- translate('auto.components.settings.integrations.search.8c568d761c', 'pull request'),
- translate('auto.components.settings.integrations.search.2ec2bd328c', 'api token')
+ ...translateSearchKeyword('auto.components.settings.integrations.search.129fc59aa8', 'gitea'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.33180e8c10',
+ 'self-hosted'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.8c568d761c',
+ 'pull request'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.2ec2bd328c',
+ 'api token'
+ )
]
},
{
@@ -92,13 +147,31 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'Connect Jira Cloud or update Jira API token credentials.'
),
keywords: [
- translate('auto.components.settings.integrations.search.e1263dd748', 'jira'),
- translate('auto.components.settings.integrations.search.7345b7c3e6', 'atlassian'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration'),
- translate('auto.components.settings.integrations.search.2ec2bd328c', 'api token'),
- translate('auto.components.settings.integrations.search.20540996ef', 'credentials'),
- translate('auto.components.settings.integrations.search.3c3d3d8ffa', 'connect'),
- translate('auto.components.settings.integrations.search.a626990bd2', 'disconnect')
+ ...translateSearchKeyword('auto.components.settings.integrations.search.e1263dd748', 'jira'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.7345b7c3e6',
+ 'atlassian'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.2ec2bd328c',
+ 'api token'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.20540996ef',
+ 'credentials'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.3c3d3d8ffa',
+ 'connect'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.a626990bd2',
+ 'disconnect'
+ )
]
},
{
@@ -111,11 +184,26 @@ export const getIntegrationsPaneSearchEntries = createLocalizedCatalog(() => [
'Connect Linear to browse and link issues.'
),
keywords: [
- translate('auto.components.settings.integrations.search.7319e3015b', 'linear'),
- translate('auto.components.settings.integrations.search.c450244ad7', 'integration'),
- translate('auto.components.settings.integrations.search.faa0b5a0d9', 'api key'),
- translate('auto.components.settings.integrations.search.3c3d3d8ffa', 'connect'),
- translate('auto.components.settings.integrations.search.a626990bd2', 'disconnect')
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.7319e3015b',
+ 'linear'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.c450244ad7',
+ 'integration'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.faa0b5a0d9',
+ 'api key'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.3c3d3d8ffa',
+ 'connect'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.integrations.search.a626990bd2',
+ 'disconnect'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/mobile-emulator-search.ts b/src/renderer/src/components/settings/mobile-emulator-search.ts
index 1eb184f4753..5d0fd5a1014 100644
--- a/src/renderer/src/components/settings/mobile-emulator-search.ts
+++ b/src/renderer/src/components/settings/mobile-emulator-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getMobileEmulatorSearchEntries = createLocalizedCatalog(() => [
@@ -12,19 +13,58 @@ export const getMobileEmulatorSearchEntries = createLocalizedCatalog(() => [
'Configure mobile emulator support for Orca and coding agents.'
),
keywords: [
- translate('auto.components.settings.mobile.emulator.search.25159de808', 'mobile emulator'),
- translate('auto.components.settings.mobile.emulator.search.c5eca29310', 'ios simulator'),
- translate('auto.components.settings.mobile.emulator.search.2d67f708ce', 'simulator'),
- translate('auto.components.settings.mobile.emulator.search.6b6407dc1f', 'emulator'),
- translate('auto.components.settings.mobile.emulator.search.49727355a3', 'iphone'),
- translate('auto.components.settings.mobile.emulator.search.bec7231663', 'ipad'),
- translate('auto.components.settings.mobile.emulator.search.7c5a8a2bee', 'xcode'),
- translate('auto.components.settings.mobile.emulator.search.84e5706975', 'serve-sim'),
- translate('auto.components.settings.mobile.emulator.search.d4b7833894', 'orca cli'),
- translate('auto.components.settings.mobile.emulator.search.9353854ff3', 'orca emulator'),
- translate('auto.components.settings.mobile.emulator.search.ac0a985873', 'emulator skill'),
- translate('auto.components.settings.mobile.emulator.search.1ad6fb6230', 'default device'),
- translate('auto.components.settings.mobile.emulator.search.b8ddd13195', 'agent emulator')
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.25159de808',
+ 'mobile emulator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.c5eca29310',
+ 'ios simulator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.2d67f708ce',
+ 'simulator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.6b6407dc1f',
+ 'emulator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.49727355a3',
+ 'iphone'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.bec7231663',
+ 'ipad'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.7c5a8a2bee',
+ 'xcode'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.84e5706975',
+ 'serve-sim'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.d4b7833894',
+ 'orca cli'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.9353854ff3',
+ 'orca emulator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.ac0a985873',
+ 'emulator skill'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.1ad6fb6230',
+ 'default device'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.b8ddd13195',
+ 'agent emulator'
+ )
]
},
{
@@ -37,11 +77,26 @@ export const getMobileEmulatorSearchEntries = createLocalizedCatalog(() => [
'Choose which emulator device Orca opens by default.'
),
keywords: [
- translate('auto.components.settings.mobile.emulator.search.ab4814f3c5', 'default simulator'),
- translate('auto.components.settings.mobile.emulator.search.1dc8c52ffa', 'default iphone'),
- translate('auto.components.settings.mobile.emulator.search.ec3c4043fd', 'default ipad'),
- translate('auto.components.settings.mobile.emulator.search.25d7bfbcd4', 'udid'),
- translate('auto.components.settings.mobile.emulator.search.04c5f5d901', 'device')
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.ab4814f3c5',
+ 'default simulator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.1dc8c52ffa',
+ 'default iphone'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.ec3c4043fd',
+ 'default ipad'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.25d7bfbcd4',
+ 'udid'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.04c5f5d901',
+ 'device'
+ )
]
},
{
@@ -54,14 +109,26 @@ export const getMobileEmulatorSearchEntries = createLocalizedCatalog(() => [
'Check whether Xcode, simctl, serve-sim, and emulator devices are ready.'
),
keywords: [
- translate('auto.components.settings.mobile.emulator.search.42bfab45d8', 'availability'),
- translate('auto.components.settings.mobile.emulator.search.3211e7acf9', 'xcrun'),
- translate('auto.components.settings.mobile.emulator.search.7650063d17', 'simctl'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.42bfab45d8',
+ 'availability'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.3211e7acf9',
+ 'xcrun'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.7650063d17',
+ 'simctl'
+ ),
translate(
'auto.components.settings.mobile.emulator.search.27397fe8e9',
'xcode command line tools'
),
- translate('auto.components.settings.mobile.emulator.search.8ef0f08d36', 'runtime')
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.8ef0f08d36',
+ 'runtime'
+ )
]
},
{
@@ -74,11 +141,26 @@ export const getMobileEmulatorSearchEntries = createLocalizedCatalog(() => [
'Use Orca CLI commands to list, attach, tap, and type into a mobile emulator.'
),
keywords: [
- translate('auto.components.settings.mobile.emulator.search.f8b871d655', 'agent cli'),
- translate('auto.components.settings.mobile.emulator.search.6f728f1456', 'emulator tap'),
- translate('auto.components.settings.mobile.emulator.search.64494f03c3', 'emulator attach'),
- translate('auto.components.settings.mobile.emulator.search.bbe4267416', 'emulator type'),
- translate('auto.components.settings.mobile.emulator.search.2bb2e09225', 'mobile skill')
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.f8b871d655',
+ 'agent cli'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.6f728f1456',
+ 'emulator tap'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.64494f03c3',
+ 'emulator attach'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.bbe4267416',
+ 'emulator type'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.emulator.search.2bb2e09225',
+ 'mobile skill'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/mobile-pane-search.ts b/src/renderer/src/components/settings/mobile-pane-search.ts
index a6d3498f212..669a22a5ce9 100644
--- a/src/renderer/src/components/settings/mobile-pane-search.ts
+++ b/src/renderer/src/components/settings/mobile-pane-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getMobilePaneSearchEntries = createLocalizedCatalog(() => [
@@ -9,12 +10,12 @@ export const getMobilePaneSearchEntries = createLocalizedCatalog(() => [
'Pair a mobile device by scanning a QR code.'
),
keywords: [
- translate('auto.components.settings.mobile.pane.search.6db86f445f', 'mobile'),
- translate('auto.components.settings.mobile.pane.search.3c1807a81a', 'qr'),
- translate('auto.components.settings.mobile.pane.search.4a0c826f3d', 'code'),
- translate('auto.components.settings.mobile.pane.search.e518cbd61c', 'pair'),
- translate('auto.components.settings.mobile.pane.search.ad08035c5f', 'phone'),
- translate('auto.components.settings.mobile.pane.search.2128a21096', 'scan')
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.6db86f445f', 'mobile'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.3c1807a81a', 'qr'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.4a0c826f3d', 'code'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.e518cbd61c', 'pair'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.ad08035c5f', 'phone'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.2128a21096', 'scan')
]
},
{
@@ -24,11 +25,17 @@ export const getMobilePaneSearchEntries = createLocalizedCatalog(() => [
'Manage paired mobile devices.'
),
keywords: [
- translate('auto.components.settings.mobile.pane.search.6db86f445f', 'mobile'),
- translate('auto.components.settings.mobile.pane.search.82783d9b71', 'devices'),
- translate('auto.components.settings.mobile.pane.search.905c65a308', 'revoke'),
- translate('auto.components.settings.mobile.pane.search.5e8fda4d7f', 'paired'),
- translate('auto.components.settings.mobile.pane.search.7d01f93ec0', 'connected')
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.6db86f445f', 'mobile'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.82783d9b71',
+ 'devices'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.905c65a308', 'revoke'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.5e8fda4d7f', 'paired'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.7d01f93ec0',
+ 'connected'
+ )
]
},
{
@@ -38,17 +45,35 @@ export const getMobilePaneSearchEntries = createLocalizedCatalog(() => [
'Choose which network address to use for mobile pairing.'
),
keywords: [
- translate('auto.components.settings.mobile.pane.search.7b37c2e557', 'network'),
- translate('auto.components.settings.mobile.pane.search.a023683767', 'interface'),
- translate('auto.components.settings.mobile.pane.search.c690e3ee38', 'tailscale'),
- translate('auto.components.settings.mobile.pane.search.16bff559a0', 'tailnet'),
- translate('auto.components.settings.mobile.pane.search.87711f4b8f', 'vpn'),
- translate('auto.components.settings.mobile.pane.search.d0c89bc4a9', 'overlay'),
- translate('auto.components.settings.mobile.pane.search.1f70d63998', 'ip'),
- translate('auto.components.settings.mobile.pane.search.dd6e671aa9', 'address'),
- translate('auto.components.settings.mobile.pane.search.1802188b5d', 'wifi'),
- translate('auto.components.settings.mobile.pane.search.70f505f3c3', 'lan'),
- translate('auto.components.settings.mobile.pane.search.126afc5dbd', 'remote')
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.7b37c2e557',
+ 'network'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.a023683767',
+ 'interface'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.c690e3ee38',
+ 'tailscale'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.16bff559a0',
+ 'tailnet'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.87711f4b8f', 'vpn'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.d0c89bc4a9',
+ 'overlay'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.1f70d63998', 'ip'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.dd6e671aa9',
+ 'address'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.1802188b5d', 'wifi'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.70f505f3c3', 'lan'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.126afc5dbd', 'remote')
]
},
{
@@ -61,17 +86,26 @@ export const getMobilePaneSearchEntries = createLocalizedCatalog(() => [
'Choose what happens to terminals you were viewing on mobile after you close the app or switch away.'
),
keywords: [
- translate('auto.components.settings.mobile.pane.search.6db86f445f', 'mobile'),
- translate('auto.components.settings.mobile.pane.search.b34ad5b3a7', 'terminal'),
- translate('auto.components.settings.mobile.pane.search.6cd2bfdb0e', 'restore'),
- translate('auto.components.settings.mobile.pane.search.ad08035c5f', 'phone'),
- translate('auto.components.settings.mobile.pane.search.fadcbfdd99', 'fit'),
- translate('auto.components.settings.mobile.pane.search.356c31d6dc', 'width'),
- translate('auto.components.settings.mobile.pane.search.aa3f736042', 'resize'),
- translate('auto.components.settings.mobile.pane.search.8015fd9523', 'hold'),
- translate('auto.components.settings.mobile.pane.search.3a5e31e84b', 'leave'),
- translate('auto.components.settings.mobile.pane.search.9e16be01d6', 'background'),
- translate('auto.components.settings.mobile.pane.search.dbccde3a60', 'close')
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.6db86f445f', 'mobile'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.b34ad5b3a7',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.6cd2bfdb0e',
+ 'restore'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.ad08035c5f', 'phone'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.fadcbfdd99', 'fit'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.356c31d6dc', 'width'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.aa3f736042', 'resize'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.8015fd9523', 'hold'),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.3a5e31e84b', 'leave'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.pane.search.9e16be01d6',
+ 'background'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.pane.search.dbccde3a60', 'close')
]
}
])
diff --git a/src/renderer/src/components/settings/mobile-settings-search.ts b/src/renderer/src/components/settings/mobile-settings-search.ts
index f410d34c76d..25ef67e808b 100644
--- a/src/renderer/src/components/settings/mobile-settings-search.ts
+++ b/src/renderer/src/components/settings/mobile-settings-search.ts
@@ -1,6 +1,7 @@
import type { SettingsSearchEntry } from './settings-search'
import { getMobilePaneSearchEntries } from './mobile-pane-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getMobileEnableSearchEntry = createLocalizedCatalog(
@@ -11,17 +12,47 @@ export const getMobileEnableSearchEntry = createLocalizedCatalog(
'Control terminals and agents from your phone.'
),
keywords: [
- translate('auto.components.settings.mobile.settings.search.f213400800', 'mobile'),
- translate('auto.components.settings.mobile.settings.search.f4ed142753', 'phone'),
- translate('auto.components.settings.mobile.settings.search.cf2c93b479', 'pair'),
- translate('auto.components.settings.mobile.settings.search.87816d1c59', 'qr'),
- translate('auto.components.settings.mobile.settings.search.59b1d75fd1', 'code'),
- translate('auto.components.settings.mobile.settings.search.0b7e585cb9', 'scan'),
- translate('auto.components.settings.mobile.settings.search.7e801801ac', 'remote'),
- translate('auto.components.settings.mobile.settings.search.a7eececc1d', 'android'),
- translate('auto.components.settings.mobile.settings.search.6bfa001752', 'apk'),
- translate('auto.components.settings.mobile.settings.search.8d4ba0ef09', 'beta'),
- translate('auto.components.settings.mobile.settings.search.b730ff7049', 'experimental')
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.f213400800',
+ 'mobile'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.f4ed142753',
+ 'phone'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.cf2c93b479',
+ 'pair'
+ ),
+ ...translateSearchKeyword('auto.components.settings.mobile.settings.search.87816d1c59', 'qr'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.59b1d75fd1',
+ 'code'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.0b7e585cb9',
+ 'scan'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.7e801801ac',
+ 'remote'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.a7eececc1d',
+ 'android'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.6bfa001752',
+ 'apk'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.8d4ba0ef09',
+ 'beta'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.mobile.settings.search.b730ff7049',
+ 'experimental'
+ )
]
})
)
diff --git a/src/renderer/src/components/settings/notifications-search.ts b/src/renderer/src/components/settings/notifications-search.ts
index 33197c0ce42..ebe769f5a66 100644
--- a/src/renderer/src/components/settings/notifications-search.ts
+++ b/src/renderer/src/components/settings/notifications-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
@@ -12,10 +13,22 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Master switch for Orca desktop notifications.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.51ae2183e1', 'desktop'),
- translate('auto.components.settings.notifications.search.72539aede4', 'system'),
- translate('auto.components.settings.notifications.search.adbc3a0fcf', 'native')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.51ae2183e1',
+ 'desktop'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.72539aede4',
+ 'system'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.adbc3a0fcf',
+ 'native'
+ )
]
},
{
@@ -28,11 +41,20 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Notify when a coding agent transitions from working to idle.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.7fa07e9600', 'agent'),
- translate('auto.components.settings.notifications.search.5f7472d3fb', 'complete'),
- translate('auto.components.settings.notifications.search.dd9d3e5f0f', 'idle'),
- translate('auto.components.settings.notifications.search.193e1f107c', 'task')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.7fa07e9600',
+ 'agent'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.5f7472d3fb',
+ 'complete'
+ ),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.dd9d3e5f0f', 'idle'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.193e1f107c', 'task')
]
},
{
@@ -42,10 +64,19 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Notify when a background terminal emits a bell character.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.c638ae989d', 'terminal'),
- translate('auto.components.settings.notifications.search.ae0487f8fd', 'bell'),
- translate('auto.components.settings.notifications.search.a2ab73b325', 'attention')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.c638ae989d',
+ 'terminal'
+ ),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.ae0487f8fd', 'bell'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.a2ab73b325',
+ 'attention'
+ )
]
},
{
@@ -58,10 +89,22 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Avoid notifying when Orca is focused on the active worktree.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.a4c3b29a3c', 'focused'),
- translate('auto.components.settings.notifications.search.fa60d8e4ab', 'suppress'),
- translate('auto.components.settings.notifications.search.4ada6bfde9', 'filtering')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.a4c3b29a3c',
+ 'focused'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.fa60d8e4ab',
+ 'suppress'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.4ada6bfde9',
+ 'filtering'
+ )
]
},
{
@@ -74,17 +117,26 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Choose the built-in, system, or local audio file Orca plays for desktop notifications.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.dc7d7c07cd', 'sound'),
- translate('auto.components.settings.notifications.search.6e08f78315', 'audio'),
- translate('auto.components.settings.notifications.search.5362074f19', 'mp3'),
- translate('auto.components.settings.notifications.search.57e34a31cd', 'wav'),
- translate('auto.components.settings.notifications.search.d16ae23645', 'ogg'),
- translate('auto.components.settings.notifications.search.6ecb8418cb', 'm4a'),
- translate('auto.components.settings.notifications.search.722face52f', 'aac'),
- translate('auto.components.settings.notifications.search.079c29aeb5', 'flac'),
- translate('auto.components.settings.notifications.search.3014ad1b8f', 'ding'),
- translate('auto.components.settings.notifications.search.ef86a782cc', 'bong')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.dc7d7c07cd',
+ 'sound'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.6e08f78315',
+ 'audio'
+ ),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.5362074f19', 'mp3'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.57e34a31cd', 'wav'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.d16ae23645', 'ogg'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.6ecb8418cb', 'm4a'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.722face52f', 'aac'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.079c29aeb5', 'flac'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.3014ad1b8f', 'ding'),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.ef86a782cc', 'bong')
]
},
{
@@ -97,10 +149,22 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Playback volume for non-system notification sounds.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.dc7d7c07cd', 'sound'),
- translate('auto.components.settings.notifications.search.d58b64dddf', 'volume'),
- translate('auto.components.settings.notifications.search.ecdeff4993', 'loudness')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.dc7d7c07cd',
+ 'sound'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.d58b64dddf',
+ 'volume'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ecdeff4993',
+ 'loudness'
+ )
]
},
{
@@ -113,8 +177,11 @@ export const getNotificationsPaneSearchEntries = createLocalizedCatalog(() => [
'Trigger a sample desktop notification using the native delivery path.'
),
keywords: [
- translate('auto.components.settings.notifications.search.ca8faa40d7', 'notifications'),
- translate('auto.components.settings.notifications.search.aa288005c3', 'test')
+ ...translateSearchKeyword(
+ 'auto.components.settings.notifications.search.ca8faa40d7',
+ 'notifications'
+ ),
+ ...translateSearchKeyword('auto.components.settings.notifications.search.aa288005c3', 'test')
]
}
])
diff --git a/src/renderer/src/components/settings/orchestration-search.ts b/src/renderer/src/components/settings/orchestration-search.ts
index 9ce5999e3e4..a9d22636030 100644
--- a/src/renderer/src/components/settings/orchestration-search.ts
+++ b/src/renderer/src/components/settings/orchestration-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getOrchestrationPaneSearchEntries = createLocalizedCatalog(() => [
@@ -12,21 +13,60 @@ export const getOrchestrationPaneSearchEntries = createLocalizedCatalog(() => [
'Coordinate multiple coding agents via messaging, task DAGs, dispatch, and decision gates.'
),
keywords: [
- translate('auto.components.settings.orchestration.search.a7f76b4ca7', 'orchestration'),
- translate('auto.components.settings.orchestration.search.d86705ba77', 'multi-agent'),
- translate('auto.components.settings.orchestration.search.13ba5c6cbd', 'agents'),
- translate('auto.components.settings.orchestration.search.91fc8ab7e5', 'coordination'),
- translate('auto.components.settings.orchestration.search.9a5ebdca31', 'messaging'),
- translate('auto.components.settings.orchestration.search.eee028ae14', 'dispatch'),
- translate('auto.components.settings.orchestration.search.7ad948b714', 'task'),
- translate('auto.components.settings.orchestration.search.ca54c69806', 'DAG'),
- translate('auto.components.settings.orchestration.search.741dfc03fa', 'worker'),
- translate('auto.components.settings.orchestration.search.21c28ccdf7', 'coordinator'),
- translate('auto.components.settings.orchestration.search.32c5098e7b', 'claude'),
- translate('auto.components.settings.orchestration.search.f278fd04db', 'codex'),
- translate('auto.components.settings.orchestration.search.08c65b12a2', 'examples'),
- translate('auto.components.settings.orchestration.search.c766a01978', 'handoff'),
- translate('auto.components.settings.orchestration.search.f5d39af41e', 'child agents')
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.a7f76b4ca7',
+ 'orchestration'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.d86705ba77',
+ 'multi-agent'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.13ba5c6cbd',
+ 'agents'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.91fc8ab7e5',
+ 'coordination'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.9a5ebdca31',
+ 'messaging'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.eee028ae14',
+ 'dispatch'
+ ),
+ ...translateSearchKeyword('auto.components.settings.orchestration.search.7ad948b714', 'task'),
+ ...translateSearchKeyword('auto.components.settings.orchestration.search.ca54c69806', 'DAG'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.741dfc03fa',
+ 'worker'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.21c28ccdf7',
+ 'coordinator'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.32c5098e7b',
+ 'claude'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.f278fd04db',
+ 'codex'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.08c65b12a2',
+ 'examples'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.c766a01978',
+ 'handoff'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.orchestration.search.f5d39af41e',
+ 'child agents'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/privacy-search.ts b/src/renderer/src/components/settings/privacy-search.ts
index 8c2a7a2eca9..ab74dab968c 100644
--- a/src/renderer/src/components/settings/privacy-search.ts
+++ b/src/renderer/src/components/settings/privacy-search.ts
@@ -3,6 +3,7 @@
// terminal-search.ts, etc.) and keep Settings.tsx imports uniform.
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getPrivacyPaneSearchEntries = createLocalizedCatalog(() => [
@@ -13,15 +14,15 @@ export const getPrivacyPaneSearchEntries = createLocalizedCatalog(() => [
'Anonymous product usage data, diagnostics, and telemetry controls.'
),
keywords: [
- translate('auto.components.settings.privacy.search.10124159f1', 'privacy'),
- translate('auto.components.settings.privacy.search.77d3180def', 'telemetry'),
- translate('auto.components.settings.privacy.search.4104f6f0f3', 'analytics'),
- translate('auto.components.settings.privacy.search.79c319948b', 'usage'),
- translate('auto.components.settings.privacy.search.b021b9cb81', 'anonymous'),
- translate('auto.components.settings.privacy.search.3922051573', 'data'),
- translate('auto.components.settings.privacy.search.2b5a5c312f', 'posthog'),
- translate('auto.components.settings.privacy.search.27a27b2f63', 'opt out'),
- translate('auto.components.settings.privacy.search.4d4bb76bf4', 'opt in')
+ ...translateSearchKeyword('auto.components.settings.privacy.search.10124159f1', 'privacy'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.77d3180def', 'telemetry'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.4104f6f0f3', 'analytics'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.79c319948b', 'usage'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.b021b9cb81', 'anonymous'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.3922051573', 'data'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.2b5a5c312f', 'posthog'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.27a27b2f63', 'opt out'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.4d4bb76bf4', 'opt in')
]
},
{
@@ -34,12 +35,12 @@ export const getPrivacyPaneSearchEntries = createLocalizedCatalog(() => [
'Help improve Orca by sending anonymous feature-usage events.'
),
keywords: [
- translate('auto.components.settings.privacy.search.77d3180def', 'telemetry'),
- translate('auto.components.settings.privacy.search.79c319948b', 'usage'),
- translate('auto.components.settings.privacy.search.b021b9cb81', 'anonymous'),
- translate('auto.components.settings.privacy.search.4d4bb76bf4', 'opt in'),
- translate('auto.components.settings.privacy.search.27a27b2f63', 'opt out'),
- translate('auto.components.settings.privacy.search.ead1deded2', 'share')
+ ...translateSearchKeyword('auto.components.settings.privacy.search.77d3180def', 'telemetry'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.79c319948b', 'usage'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.b021b9cb81', 'anonymous'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.4d4bb76bf4', 'opt in'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.27a27b2f63', 'opt out'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.ead1deded2', 'share')
]
},
{
@@ -49,12 +50,18 @@ export const getPrivacyPaneSearchEntries = createLocalizedCatalog(() => [
'Trace files and OTLP export controls.'
),
keywords: [
- translate('auto.components.settings.privacy.search.c0494ff48a', 'diagnostics'),
- translate('auto.components.settings.privacy.search.40de3c2f19', 'trace'),
- translate('auto.components.settings.privacy.search.685c68a81f', 'logs'),
- translate('auto.components.settings.privacy.search.9ea93ce3d6', 'otlp'),
- translate('auto.components.settings.privacy.search.4a583f3a2f', 'opentelemetry'),
- translate('auto.components.settings.privacy.search.1686c07fee', 'support')
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.c0494ff48a',
+ 'diagnostics'
+ ),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.40de3c2f19', 'trace'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.685c68a81f', 'logs'),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.9ea93ce3d6', 'otlp'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.4a583f3a2f',
+ 'opentelemetry'
+ ),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.1686c07fee', 'support')
]
},
{
@@ -67,14 +74,29 @@ export const getPrivacyPaneSearchEntries = createLocalizedCatalog(() => [
'Environment variables that disable telemetry transmission.'
),
keywords: [
- translate('auto.components.settings.privacy.search.83a6cd79b3', 'do not track'),
- translate('auto.components.settings.privacy.search.058550f6bc', 'do_not_track'),
- translate('auto.components.settings.privacy.search.69637f4dc4', 'orca_telemetry_disabled'),
- translate('auto.components.settings.privacy.search.5854a5c752', 'ci'),
- translate('auto.components.settings.privacy.search.664f1a8984', 'continuous integration'),
- translate('auto.components.settings.privacy.search.94e04427f6', 'env'),
- translate('auto.components.settings.privacy.search.d8191ae5ca', 'environment variable'),
- translate('auto.components.settings.privacy.search.e8bc614a18', 'disable')
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.83a6cd79b3',
+ 'do not track'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.058550f6bc',
+ 'do_not_track'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.69637f4dc4',
+ 'orca_telemetry_disabled'
+ ),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.5854a5c752', 'ci'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.664f1a8984',
+ 'continuous integration'
+ ),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.94e04427f6', 'env'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.privacy.search.d8191ae5ca',
+ 'environment variable'
+ ),
+ ...translateSearchKeyword('auto.components.settings.privacy.search.e8bc614a18', 'disable')
]
}
])
diff --git a/src/renderer/src/components/settings/quick-commands-search.ts b/src/renderer/src/components/settings/quick-commands-search.ts
index 8d28f3cdf65..5aaa4b4bf29 100644
--- a/src/renderer/src/components/settings/quick-commands-search.ts
+++ b/src/renderer/src/components/settings/quick-commands-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getQuickCommandsPaneSearchEntries = createLocalizedCatalog(() => [
@@ -9,21 +10,57 @@ export const getQuickCommandsPaneSearchEntries = createLocalizedCatalog(() => [
'Saved terminal commands that can be launched from any terminal, scoped globally or to a specific project.'
),
keywords: [
- translate('auto.components.settings.quick.commands.search.236d4cfac8', 'quick'),
- translate('auto.components.settings.quick.commands.search.fecb031823', 'command'),
- translate('auto.components.settings.quick.commands.search.cfffa6cdb6', 'commands'),
- translate('auto.components.settings.quick.commands.search.0073cf8ce9', 'terminal'),
- translate('auto.components.settings.quick.commands.search.d07d130849', 'shortcut'),
- translate('auto.components.settings.quick.commands.search.a26ecdb77b', 'snippet'),
- translate('auto.components.settings.quick.commands.search.8bf43c2dad', 'global'),
- translate('auto.components.settings.quick.commands.search.f58b92a48f', 'project'),
- translate('auto.components.settings.quick.commands.search.89d2a9ad9f', 'repo'),
- translate('auto.components.settings.quick.commands.search.1c5bdcd0f2', 'repository'),
- translate('auto.components.settings.quick.commands.search.2d8aff42be', 'run'),
- translate('auto.components.settings.quick.commands.search.0b78c4a165', 'launch'),
- translate('auto.components.settings.quick.commands.search.b949a7c0a0', 'pnpm'),
- translate('auto.components.settings.quick.commands.search.b86c727100', 'npm'),
- translate('auto.components.settings.quick.commands.search.3c316e6ef8', 'yarn')
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.236d4cfac8',
+ 'quick'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.fecb031823',
+ 'command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.cfffa6cdb6',
+ 'commands'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.0073cf8ce9',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.d07d130849',
+ 'shortcut'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.a26ecdb77b',
+ 'snippet'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.8bf43c2dad',
+ 'global'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.f58b92a48f',
+ 'project'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.89d2a9ad9f',
+ 'repo'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.1c5bdcd0f2',
+ 'repository'
+ ),
+ ...translateSearchKeyword('auto.components.settings.quick.commands.search.2d8aff42be', 'run'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.0b78c4a165',
+ 'launch'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.quick.commands.search.b949a7c0a0',
+ 'pnpm'
+ ),
+ ...translateSearchKeyword('auto.components.settings.quick.commands.search.b86c727100', 'npm'),
+ ...translateSearchKeyword('auto.components.settings.quick.commands.search.3c316e6ef8', 'yarn')
]
}
])
diff --git a/src/renderer/src/components/settings/repository-git-author-search-entries.ts b/src/renderer/src/components/settings/repository-git-author-search-entries.ts
new file mode 100644
index 00000000000..eb202d55209
--- /dev/null
+++ b/src/renderer/src/components/settings/repository-git-author-search-entries.ts
@@ -0,0 +1,74 @@
+import type { Repo } from '../../../../shared/types'
+import type { SettingsSearchEntry } from './settings-search'
+import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
+
+export function getRepositoryGitAuthorSearchEntries(repo: Repo): SettingsSearchEntry[] {
+ return [
+ {
+ title: translate('auto.components.settings.repository.search.eec3995dc6', 'Git AI Author'),
+ description: translate(
+ 'auto.components.settings.repository.search.6cc5c65e64',
+ 'Project-specific git generation overrides.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.a47f51127e',
+ 'source control'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.cfad7ce5f3', 'ai'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.eec39b3de6',
+ 'commit message'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.5ff7fe1ade',
+ 'pull request'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.8068d8d0f1', 'pr'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.917dce844a',
+ 'branch name'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.130d76dc16',
+ 'rename'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.fa3131f223', 'model'),
+ ...translateSearchKeyword('auto.components.settings.repository.search.fff8834983', 'prompt')
+ ]
+ },
+ {
+ title: translate('auto.components.settings.repository.search.31bd0a2420', 'MCP Configs'),
+ description: translate(
+ 'auto.components.settings.repository.search.3c31801626',
+ 'Inspect project-level MCP server config files.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword('auto.components.settings.repository.search.343f0a508c', 'mcp'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.16dc7a4637',
+ 'model context protocol'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.e760e3fae7',
+ '.mcp.json'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.26f42fe773',
+ '.cursor/mcp.json'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.db11b337c4',
+ '.claude.json'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.d73fb47b45',
+ '.claude/mcp.json'
+ )
+ ]
+ }
+ ]
+}
diff --git a/src/renderer/src/components/settings/repository-git-hooks-search-entries.ts b/src/renderer/src/components/settings/repository-git-hooks-search-entries.ts
new file mode 100644
index 00000000000..96146826bd7
--- /dev/null
+++ b/src/renderer/src/components/settings/repository-git-hooks-search-entries.ts
@@ -0,0 +1,169 @@
+import type { Repo } from '../../../../shared/types'
+import type { SettingsSearchEntry } from './settings-search'
+import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
+
+export function getRepositoryGitHooksSearchEntries(repo: Repo): SettingsSearchEntry[] {
+ return [
+ {
+ title: translate('auto.components.settings.repository.search.b79df26937', 'Setup Script'),
+ description: translate(
+ 'auto.components.settings.repository.search.baaf70bb37',
+ 'Local and shared scripts that run after a new worktree is created.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword('auto.components.settings.repository.search.8655e3387b', 'hooks'),
+ ...translateSearchKeyword('auto.components.settings.repository.search.5590388dfa', 'setup'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.a31b43a7f8',
+ 'setup script'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.491b05d6e6',
+ 'setup command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.6b80f7d3c8',
+ 'local settings scripts'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.9cad92fe77',
+ 'orca.yaml hooks'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.bf460fded8', 'yaml')
+ ]
+ },
+ {
+ title: translate('auto.components.settings.repository.search.bce0ca23c6', 'Archive Script'),
+ description: translate(
+ 'auto.components.settings.repository.search.acd1157f0c',
+ 'Local and shared scripts that run before a worktree is archived.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword('auto.components.settings.repository.search.8655e3387b', 'hooks'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.4c17787d7b',
+ 'archive'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.fbfd2386e8',
+ 'archive script'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.a1a4c51d58',
+ 'archive command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.6b80f7d3c8',
+ 'local settings scripts'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.9cad92fe77',
+ 'orca.yaml hooks'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.bf460fded8', 'yaml')
+ ]
+ },
+ {
+ title: translate('auto.components.settings.repository.search.cc11699c3d', 'Advanced'),
+ description: translate(
+ 'auto.components.settings.repository.search.d141897c90',
+ 'Command source and orca.yaml details.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.19f58d6d89',
+ 'advanced'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.ed269fad69',
+ 'command source'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.0432d2fb7c', 'local'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.603c68b68c',
+ 'orca.yaml'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.fcb8fa8144',
+ 'shared'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.1d90a6cfbb', 'both'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.f1e1bfa89f',
+ 'source'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.5e9445bbfd',
+ 'authoritative'
+ )
+ ]
+ },
+ {
+ title: translate(
+ 'auto.components.settings.repository.search.cdfe398068',
+ 'When to Run Setup'
+ ),
+ description: translate(
+ 'auto.components.settings.repository.search.c00a549e03',
+ 'Choose the default behavior when a setup script is available.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.f9d84b7971',
+ 'setup run policy'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.80c490b012', 'ask'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.a69c5cbe90',
+ 'run by default'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.c5e8bdbcbb',
+ 'skip by default'
+ )
+ ]
+ },
+ {
+ title: translate(
+ 'auto.components.settings.repository.search.d86ea12d16',
+ 'Custom GitHub Issue Command'
+ ),
+ description: translate(
+ 'auto.components.settings.repository.search.d42d1e49c0',
+ 'File-based linked-issue command configured via orca.yaml and optional local override.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.2011a6a4f2',
+ 'github issue command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.66b584bd6c',
+ 'issue command'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.ec70364df2',
+ 'workflow'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.9dc60d7f6d',
+ 'github'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.603c68b68c',
+ 'orca.yaml'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.bc7e504b8e',
+ '.orca/issue-command'
+ )
+ ]
+ }
+ ]
+}
diff --git a/src/renderer/src/components/settings/repository-git-worktree-search-entries.ts b/src/renderer/src/components/settings/repository-git-worktree-search-entries.ts
new file mode 100644
index 00000000000..26a77fe3e02
--- /dev/null
+++ b/src/renderer/src/components/settings/repository-git-worktree-search-entries.ts
@@ -0,0 +1,136 @@
+import type { Repo } from '../../../../shared/types'
+import type { SettingsSearchEntry } from './settings-search'
+import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
+
+export function getRepositoryGitWorktreeSearchEntries(repo: Repo): SettingsSearchEntry[] {
+ return [
+ {
+ title: translate(
+ 'auto.components.settings.repository.search.094adbe930',
+ 'Default Worktree Base'
+ ),
+ description: translate(
+ 'auto.components.settings.repository.search.f571081ec4',
+ 'Default base branch or ref when creating worktrees.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.f41cef5083',
+ 'base ref'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.9811f3d152', 'branch')
+ ]
+ },
+ {
+ title: translate(
+ 'auto.components.settings.repository.search.443d127b5a',
+ 'Worktree Location'
+ ),
+ description: translate(
+ 'auto.components.settings.repository.search.cd33a5525e',
+ 'Project-specific directory for new worktrees.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.f3e6dee5fe',
+ 'worktree path'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.a325a89dff',
+ 'workspace path'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.1ff4f12c0c',
+ 'directory'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.58d8bca414',
+ 'relative'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.4733ec2395',
+ '../worktrees'
+ )
+ ]
+ },
+ {
+ title: translate(
+ 'auto.components.settings.repository.search.1f0f20bbb6',
+ 'Sparse Checkout Presets'
+ ),
+ description: translate(
+ 'auto.components.settings.repository.search.90a331fd68',
+ 'Saved directory sets for sparse worktree creation.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.4f3c0230c2',
+ 'sparse'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.aa42616e3d',
+ 'checkout'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.095fca94fe',
+ 'preset'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.9f5ae26ccd',
+ 'presets'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.1ff4f12c0c',
+ 'directory'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.4e2529722c',
+ 'directories'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.4b9a18a56d',
+ 'monorepo'
+ )
+ ]
+ },
+ {
+ title: translate(
+ 'auto.components.settings.repository.search.01b3377ebc',
+ 'Worktree Symlinks'
+ ),
+ description: translate(
+ 'auto.components.settings.repository.search.ed885e589f',
+ 'Paths to symlink from the primary checkout into newly created worktrees.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.c06adcf136',
+ 'symlink'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.7e228fc439',
+ 'symlinks'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.f1c53f2820',
+ 'worktree'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.3c180a251c', 'link'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.fcb8fa8144',
+ 'shared'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.0a3a582794', 'env'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.84da7fa2d7',
+ 'node_modules'
+ )
+ ]
+ }
+ ]
+}
diff --git a/src/renderer/src/components/settings/repository-search.ts b/src/renderer/src/components/settings/repository-search.ts
index 793f3c28193..9373206c438 100644
--- a/src/renderer/src/components/settings/repository-search.ts
+++ b/src/renderer/src/components/settings/repository-search.ts
@@ -2,185 +2,92 @@ import type { Repo } from '../../../../shared/types'
import { isFolderRepo } from '../../../../shared/repo-kind'
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
+import { getRepositoryGitAuthorSearchEntries } from './repository-git-author-search-entries'
+import { getRepositoryGitHooksSearchEntries } from './repository-git-hooks-search-entries'
+import { getRepositoryGitWorktreeSearchEntries } from './repository-git-worktree-search-entries'
export function getRepositoryPaneSearchEntries(repo: Repo): SettingsSearchEntry[] {
const isFolder = isFolderRepo(repo)
return [
{
- title: translate("auto.components.settings.repository.search.7e1e456a95", "Display Name"),
- description: translate("auto.components.settings.repository.search.883aad2801", "Project-specific display details for the sidebar and tabs."),
- keywords: [repo.displayName, repo.path, translate("auto.components.settings.repository.search.92af66c7ce", "project name"), translate("auto.components.settings.repository.search.cd73b976d7", "repository name")]
- },
- {
- title: translate("auto.components.settings.repository.search.b24f00294a", "Project Icon"),
- description: translate("auto.components.settings.repository.search.a1f3a2bd47", "Project icon and color used in the sidebar and tabs."),
+ title: translate('auto.components.settings.repository.search.7e1e456a95', 'Display Name'),
+ description: translate(
+ 'auto.components.settings.repository.search.883aad2801',
+ 'Project-specific display details for the sidebar and tabs.'
+ ),
keywords: [
repo.displayName,
- translate("auto.components.settings.repository.search.6438a94c63", "project icon"),
- translate("auto.components.settings.repository.search.b2546efab5", "repository icon"),
- translate("auto.components.settings.repository.search.8d045419b1", "color"),
- translate("auto.components.settings.repository.search.6d8de2f090", "hex"),
- translate("auto.components.settings.repository.search.c1075178cf", "badge"),
- translate("auto.components.settings.repository.search.cb4b4de666", "avatar"),
- translate("auto.components.settings.repository.search.9dc60d7f6d", "github"),
- translate("auto.components.settings.repository.search.1e73e840ff", "emoji"),
- translate("auto.components.settings.repository.search.27733eb6c1", "favicon")
+ repo.path,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.92af66c7ce',
+ 'project name'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.cd73b976d7',
+ 'repository name'
+ )
+ ]
+ },
+ {
+ title: translate('auto.components.settings.repository.search.b24f00294a', 'Project Icon'),
+ description: translate(
+ 'auto.components.settings.repository.search.a1f3a2bd47',
+ 'Project icon and color used in the sidebar and tabs.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.6438a94c63',
+ 'project icon'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.b2546efab5',
+ 'repository icon'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.8d045419b1', 'color'),
+ ...translateSearchKeyword('auto.components.settings.repository.search.6d8de2f090', 'hex'),
+ ...translateSearchKeyword('auto.components.settings.repository.search.c1075178cf', 'badge'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.cb4b4de666',
+ 'avatar'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.9dc60d7f6d',
+ 'github'
+ ),
+ ...translateSearchKeyword('auto.components.settings.repository.search.1e73e840ff', 'emoji'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.27733eb6c1',
+ 'favicon'
+ )
+ ]
+ },
+ ...(isFolder ? [] : getRepositoryGitWorktreeSearchEntries(repo)),
+ {
+ title: translate('auto.components.settings.repository.search.c5266c2c9d', 'Remove Project'),
+ description: translate(
+ 'auto.components.settings.repository.search.c86478c3d8',
+ 'Remove this project from Orca.'
+ ),
+ keywords: [
+ repo.displayName,
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.3067595d82',
+ 'delete'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.6469de5368',
+ 'project'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.repository.search.cc876ca5f2',
+ 'repository'
+ )
]
},
...(isFolder
? []
- : [
- {
- title: translate("auto.components.settings.repository.search.094adbe930", "Default Worktree Base"),
- description: translate("auto.components.settings.repository.search.f571081ec4", "Default base branch or ref when creating worktrees."),
- keywords: [repo.displayName, translate("auto.components.settings.repository.search.f41cef5083", "base ref"), translate("auto.components.settings.repository.search.9811f3d152", "branch")]
- },
- {
- title: translate("auto.components.settings.repository.search.443d127b5a", "Worktree Location"),
- description: translate("auto.components.settings.repository.search.cd33a5525e", "Project-specific directory for new worktrees."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.f3e6dee5fe", "worktree path"),
- translate("auto.components.settings.repository.search.a325a89dff", "workspace path"),
- translate("auto.components.settings.repository.search.1ff4f12c0c", "directory"),
- translate("auto.components.settings.repository.search.58d8bca414", "relative"),
- translate("auto.components.settings.repository.search.4733ec2395", "../worktrees")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.1f0f20bbb6", "Sparse Checkout Presets"),
- description: translate("auto.components.settings.repository.search.90a331fd68", "Saved directory sets for sparse worktree creation."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.4f3c0230c2", "sparse"),
- translate("auto.components.settings.repository.search.aa42616e3d", "checkout"),
- translate("auto.components.settings.repository.search.095fca94fe", "preset"),
- translate("auto.components.settings.repository.search.9f5ae26ccd", "presets"),
- translate("auto.components.settings.repository.search.1ff4f12c0c", "directory"),
- translate("auto.components.settings.repository.search.4e2529722c", "directories"),
- translate("auto.components.settings.repository.search.4b9a18a56d", "monorepo")
- ]
- }
- ]),
- {
- title: translate("auto.components.settings.repository.search.c5266c2c9d", "Remove Project"),
- description: translate("auto.components.settings.repository.search.c86478c3d8", "Remove this project from Orca."),
- keywords: [repo.displayName, translate("auto.components.settings.repository.search.3067595d82", "delete"), translate("auto.components.settings.repository.search.6469de5368", "project"), translate("auto.components.settings.repository.search.cc876ca5f2", "repository")]
- },
- ...(isFolder
- ? []
- : [
- {
- title: translate("auto.components.settings.repository.search.eec3995dc6", "Git AI Author"),
- description: translate("auto.components.settings.repository.search.6cc5c65e64", "Project-specific git generation overrides."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.a47f51127e", "source control"),
- translate("auto.components.settings.repository.search.cfad7ce5f3", "ai"),
- translate("auto.components.settings.repository.search.eec39b3de6", "commit message"),
- translate("auto.components.settings.repository.search.5ff7fe1ade", "pull request"),
- translate("auto.components.settings.repository.search.8068d8d0f1", "pr"),
- translate("auto.components.settings.repository.search.917dce844a", "branch name"),
- translate("auto.components.settings.repository.search.130d76dc16", "rename"),
- translate("auto.components.settings.repository.search.fa3131f223", "model"),
- translate("auto.components.settings.repository.search.fff8834983", "prompt")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.01b3377ebc", "Worktree Symlinks"),
- description: translate("auto.components.settings.repository.search.ed885e589f", "Paths to symlink from the primary checkout into newly created worktrees."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.c06adcf136", "symlink"),
- translate("auto.components.settings.repository.search.7e228fc439", "symlinks"),
- translate("auto.components.settings.repository.search.f1c53f2820", "worktree"),
- translate("auto.components.settings.repository.search.3c180a251c", "link"),
- translate("auto.components.settings.repository.search.fcb8fa8144", "shared"),
- translate("auto.components.settings.repository.search.0a3a582794", "env"),
- translate("auto.components.settings.repository.search.84da7fa2d7", "node_modules")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.31bd0a2420", "MCP Configs"),
- description: translate("auto.components.settings.repository.search.3c31801626", "Inspect project-level MCP server config files."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.343f0a508c", "mcp"),
- translate("auto.components.settings.repository.search.16dc7a4637", "model context protocol"),
- translate("auto.components.settings.repository.search.e760e3fae7", ".mcp.json"),
- translate("auto.components.settings.repository.search.26f42fe773", ".cursor/mcp.json"),
- translate("auto.components.settings.repository.search.db11b337c4", ".claude.json"),
- translate("auto.components.settings.repository.search.d73fb47b45", ".claude/mcp.json")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.b79df26937", "Setup Script"),
- description: translate("auto.components.settings.repository.search.baaf70bb37", "Local and shared scripts that run after a new worktree is created."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.8655e3387b", "hooks"),
- translate("auto.components.settings.repository.search.5590388dfa", "setup"),
- translate("auto.components.settings.repository.search.a31b43a7f8", "setup script"),
- translate("auto.components.settings.repository.search.491b05d6e6", "setup command"),
- translate("auto.components.settings.repository.search.6b80f7d3c8", "local settings scripts"),
- translate("auto.components.settings.repository.search.9cad92fe77", "orca.yaml hooks"),
- translate("auto.components.settings.repository.search.bf460fded8", "yaml")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.bce0ca23c6", "Archive Script"),
- description: translate("auto.components.settings.repository.search.acd1157f0c", "Local and shared scripts that run before a worktree is archived."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.8655e3387b", "hooks"),
- translate("auto.components.settings.repository.search.4c17787d7b", "archive"),
- translate("auto.components.settings.repository.search.fbfd2386e8", "archive script"),
- translate("auto.components.settings.repository.search.a1a4c51d58", "archive command"),
- translate("auto.components.settings.repository.search.6b80f7d3c8", "local settings scripts"),
- translate("auto.components.settings.repository.search.9cad92fe77", "orca.yaml hooks"),
- translate("auto.components.settings.repository.search.bf460fded8", "yaml")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.cc11699c3d", "Advanced"),
- description: translate("auto.components.settings.repository.search.d141897c90", "Command source and orca.yaml details."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.19f58d6d89", "advanced"),
- translate("auto.components.settings.repository.search.ed269fad69", "command source"),
- translate("auto.components.settings.repository.search.0432d2fb7c", "local"),
- translate("auto.components.settings.repository.search.603c68b68c", "orca.yaml"),
- translate("auto.components.settings.repository.search.fcb8fa8144", "shared"),
- translate("auto.components.settings.repository.search.1d90a6cfbb", "both"),
- translate("auto.components.settings.repository.search.f1e1bfa89f", "source"),
- translate("auto.components.settings.repository.search.5e9445bbfd", "authoritative")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.cdfe398068", "When to Run Setup"),
- description: translate("auto.components.settings.repository.search.c00a549e03", "Choose the default behavior when a setup script is available."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.f9d84b7971", "setup run policy"),
- translate("auto.components.settings.repository.search.80c490b012", "ask"),
- translate("auto.components.settings.repository.search.a69c5cbe90", "run by default"),
- translate("auto.components.settings.repository.search.c5e8bdbcbb", "skip by default")
- ]
- },
- {
- title: translate("auto.components.settings.repository.search.d86ea12d16", "Custom GitHub Issue Command"),
- description:
- translate("auto.components.settings.repository.search.d42d1e49c0", "File-based linked-issue command configured via orca.yaml and optional local override."),
- keywords: [
- repo.displayName,
- translate("auto.components.settings.repository.search.2011a6a4f2", "github issue command"),
- translate("auto.components.settings.repository.search.66b584bd6c", "issue command"),
- translate("auto.components.settings.repository.search.ec70364df2", "workflow"),
- translate("auto.components.settings.repository.search.9dc60d7f6d", "github"),
- translate("auto.components.settings.repository.search.603c68b68c", "orca.yaml"),
- translate("auto.components.settings.repository.search.bc7e504b8e", ".orca/issue-command")
- ]
- }
- ])
+ : [...getRepositoryGitAuthorSearchEntries(repo), ...getRepositoryGitHooksSearchEntries(repo)])
]
}
diff --git a/src/renderer/src/components/settings/runtime-environments-search.ts b/src/renderer/src/components/settings/runtime-environments-search.ts
index 3ebf3f712de..050c812ebd5 100644
--- a/src/renderer/src/components/settings/runtime-environments-search.ts
+++ b/src/renderer/src/components/settings/runtime-environments-search.ts
@@ -1,5 +1,6 @@
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getRuntimeEnvironmentsSearchEntry = createLocalizedCatalog(
@@ -13,17 +14,50 @@ export const getRuntimeEnvironmentsSearchEntry = createLocalizedCatalog(
'Choose local desktop, add a saved remote Orca server, or generate a pairing URL.'
),
keywords: [
- translate('auto.components.settings.runtime.environments.search.d198440ce3', 'runtime'),
- translate('auto.components.settings.runtime.environments.search.ebd5369acf', 'environment'),
- translate('auto.components.settings.runtime.environments.search.09568ccc65', 'server'),
- translate('auto.components.settings.runtime.environments.search.d760866285', 'client'),
- translate('auto.components.settings.runtime.environments.search.5cd7dca3b8', 'remote'),
- translate('auto.components.settings.runtime.environments.search.104f4d7dbd', 'pairing'),
- translate('auto.components.settings.runtime.environments.search.81444c4102', 'pairing url'),
- translate('auto.components.settings.runtime.environments.search.f1575f1e09', 'web client'),
- translate('auto.components.settings.runtime.environments.search.45501ff2c3', 'cloud'),
- translate('auto.components.settings.runtime.environments.search.772e3b4753', 'vm'),
- translate('auto.components.settings.runtime.environments.search.c6e5a03aa0', 'dev box')
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.d198440ce3',
+ 'runtime'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.ebd5369acf',
+ 'environment'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.09568ccc65',
+ 'server'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.d760866285',
+ 'client'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.5cd7dca3b8',
+ 'remote'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.104f4d7dbd',
+ 'pairing'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.81444c4102',
+ 'pairing url'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.f1575f1e09',
+ 'web client'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.45501ff2c3',
+ 'cloud'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.772e3b4753',
+ 'vm'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.c6e5a03aa0',
+ 'dev box'
+ )
]
})
)
@@ -39,14 +73,38 @@ export const getWebRuntimeEnvironmentsSearchEntry = createLocalizedCatalog(
'Connect this browser to a saved Orca server.'
),
keywords: [
- translate('auto.components.settings.runtime.environments.search.d198440ce3', 'runtime'),
- translate('auto.components.settings.runtime.environments.search.ebd5369acf', 'environment'),
- translate('auto.components.settings.runtime.environments.search.09568ccc65', 'server'),
- translate('auto.components.settings.runtime.environments.search.d760866285', 'client'),
- translate('auto.components.settings.runtime.environments.search.5cd7dca3b8', 'remote'),
- translate('auto.components.settings.runtime.environments.search.2bd988d041', 'pairing code'),
- translate('auto.components.settings.runtime.environments.search.45501ff2c3', 'cloud'),
- translate('auto.components.settings.runtime.environments.search.772e3b4753', 'vm')
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.d198440ce3',
+ 'runtime'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.ebd5369acf',
+ 'environment'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.09568ccc65',
+ 'server'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.d760866285',
+ 'client'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.5cd7dca3b8',
+ 'remote'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.2bd988d041',
+ 'pairing code'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.45501ff2c3',
+ 'cloud'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.runtime.environments.search.772e3b4753',
+ 'vm'
+ )
]
})
)
diff --git a/src/renderer/src/components/settings/settings-search-keywords.test.ts b/src/renderer/src/components/settings/settings-search-keywords.test.ts
new file mode 100644
index 00000000000..c3257564154
--- /dev/null
+++ b/src/renderer/src/components/settings/settings-search-keywords.test.ts
@@ -0,0 +1,53 @@
+import { beforeEach, describe, expect, it } from 'vitest'
+
+import { i18n } from '@/i18n/i18n'
+import { searchKeywords, translateSearchKeyword } from './settings-search-keywords'
+
+describe('settings-search-keywords', () => {
+ beforeEach(async () => {
+ await i18n.changeLanguage('en')
+ })
+
+ it('returns only localized text in English UI', async () => {
+ await i18n.changeLanguage('en')
+ expect(translateSearchKeyword('settings.appearance.language.title', 'Language')).toEqual([
+ 'Language'
+ ])
+ })
+
+ it('keeps English fallback and aliases in localized UI', async () => {
+ await i18n.changeLanguage('ko')
+ expect(
+ translateSearchKeyword('settings.appearance.language.title', 'Language', {
+ aliases: ['locale']
+ })
+ ).toEqual(['언어', 'Language', 'locale'])
+ })
+
+ it('supports english-only keyword specs for brands', async () => {
+ await i18n.changeLanguage('ko')
+ expect(searchKeywords([{ key: 'unused', fallback: 'github', englishOnly: true }])).toEqual([
+ 'github'
+ ])
+ })
+
+ it('deduplicates repeated keyword variants', () => {
+ expect(searchKeywords(['terminal', 'terminal', { key: 'k', fallback: 'terminal' }])).toEqual([
+ 'terminal'
+ ])
+ })
+
+ it('indexes localized agent search synonyms in Korean UI', async () => {
+ await i18n.changeLanguage('ko')
+ expect(
+ searchKeywords([
+ { key: 'auto.components.settings.agents.search.66b6b82eb4', fallback: 'awake' }
+ ])
+ ).toEqual(['깨어 있음', 'awake'])
+ expect(
+ searchKeywords([
+ { key: 'auto.components.settings.agents.search.2afd3b5858', fallback: 'enable' }
+ ])
+ ).toEqual(['활성화', 'enable'])
+ })
+})
diff --git a/src/renderer/src/components/settings/settings-search-keywords.ts b/src/renderer/src/components/settings/settings-search-keywords.ts
new file mode 100644
index 00000000000..d9ee3003375
--- /dev/null
+++ b/src/renderer/src/components/settings/settings-search-keywords.ts
@@ -0,0 +1,50 @@
+import { i18n } from '@/i18n/i18n'
+import { translate } from '@/i18n/i18n'
+
+export type SearchKeywordSpec = {
+ key: string
+ fallback: string
+ /** Extra English aliases kept when UI is localized (brands, acronyms). */
+ aliases?: string[]
+ /** When true, only the fallback/aliases are indexed — no localized variant. */
+ englishOnly?: boolean
+}
+
+// Why: settings search should match localized copy and English aliases devs still type.
+export function translateSearchKeyword(
+ key: string,
+ fallback: string,
+ options?: Omit
+): string[] {
+ if (options?.englishOnly || i18n.language === 'en') {
+ return uniqueKeywords([fallback, ...(options?.aliases ?? [])])
+ }
+
+ const localized = translate(key, fallback)
+ return uniqueKeywords([localized, fallback, ...(options?.aliases ?? [])])
+}
+
+export function searchKeywords(terms: (string | SearchKeywordSpec)[]): string[] {
+ return uniqueKeywords(
+ terms.flatMap((term) => {
+ if (typeof term === 'string') {
+ return [term]
+ }
+ return translateSearchKeyword(term.key, term.fallback, term)
+ })
+ )
+}
+
+export function uniqueKeywords(values: string[]): string[] {
+ const seen = new Set()
+ const result: string[] = []
+ for (const value of values) {
+ const trimmed = value.trim()
+ if (!trimmed || seen.has(trimmed)) {
+ continue
+ }
+ seen.add(trimmed)
+ result.push(trimmed)
+ }
+ return result
+}
diff --git a/src/renderer/src/components/settings/shortcuts-search.ts b/src/renderer/src/components/settings/shortcuts-search.ts
index 9e7dbc28c62..21cc4f98d6d 100644
--- a/src/renderer/src/components/settings/shortcuts-search.ts
+++ b/src/renderer/src/components/settings/shortcuts-search.ts
@@ -1,6 +1,7 @@
import { KEYBINDING_DEFINITIONS } from '../../../../shared/keybindings'
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalShortcutPolicySearchEntry = createLocalizedCatalog(
@@ -14,15 +15,21 @@ export const getTerminalShortcutPolicySearchEntry = createLocalizedCatalog(
'Choose whether Orca or the focused terminal wins when shortcuts overlap.'
),
keywords: [
- translate('auto.components.settings.shortcuts.search.ca6a0c2df7', 'shortcut'),
- translate('auto.components.settings.shortcuts.search.0ecba9aa5f', 'keyboard'),
- translate('auto.components.settings.shortcuts.search.7e3fc707aa', 'terminal'),
- translate('auto.components.settings.shortcuts.search.7f1b38f59a', 'tui'),
- translate('auto.components.settings.shortcuts.search.f1adebbe8c', 'shell'),
- translate('auto.components.settings.shortcuts.search.0f8cb15582', 'agent'),
- translate('auto.components.settings.shortcuts.search.0ecfc47434', 'conflict'),
- translate('auto.components.settings.shortcuts.search.afda131738', 'orca first'),
- translate('auto.components.settings.shortcuts.search.4811a8264a', 'terminal first')
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.ca6a0c2df7', 'shortcut'),
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.0ecba9aa5f', 'keyboard'),
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.7e3fc707aa', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.7f1b38f59a', 'tui'),
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.f1adebbe8c', 'shell'),
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.0f8cb15582', 'agent'),
+ ...translateSearchKeyword('auto.components.settings.shortcuts.search.0ecfc47434', 'conflict'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.shortcuts.search.afda131738',
+ 'orca first'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.shortcuts.search.4811a8264a',
+ 'terminal first'
+ )
]
})
)
diff --git a/src/renderer/src/components/settings/ssh-search.ts b/src/renderer/src/components/settings/ssh-search.ts
index de7287e16e6..0985e906443 100644
--- a/src/renderer/src/components/settings/ssh-search.ts
+++ b/src/renderer/src/components/settings/ssh-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getSshPaneSearchEntries = createLocalizedCatalog(() => [
@@ -9,11 +10,11 @@ export const getSshPaneSearchEntries = createLocalizedCatalog(() => [
'Manage remote SSH targets.'
),
keywords: [
- translate('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
- translate('auto.components.settings.ssh.search.d4bcd497c7', 'remote'),
- translate('auto.components.settings.ssh.search.f9493b80c0', 'server'),
- translate('auto.components.settings.ssh.search.237b391f7c', 'connection'),
- translate('auto.components.settings.ssh.search.8fb1cc87cc', 'host')
+ ...translateSearchKeyword('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.d4bcd497c7', 'remote'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.f9493b80c0', 'server'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.237b391f7c', 'connection'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.8fb1cc87cc', 'host')
]
},
{
@@ -23,12 +24,12 @@ export const getSshPaneSearchEntries = createLocalizedCatalog(() => [
'Add a new remote SSH target.'
),
keywords: [
- translate('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
- translate('auto.components.settings.ssh.search.f7b6383aec', 'add'),
- translate('auto.components.settings.ssh.search.00d1fda01a', 'new'),
- translate('auto.components.settings.ssh.search.09395490af', 'target'),
- translate('auto.components.settings.ssh.search.8fb1cc87cc', 'host'),
- translate('auto.components.settings.ssh.search.f9493b80c0', 'server')
+ ...translateSearchKeyword('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.f7b6383aec', 'add'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.00d1fda01a', 'new'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.09395490af', 'target'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.8fb1cc87cc', 'host'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.f9493b80c0', 'server')
]
},
{
@@ -38,10 +39,10 @@ export const getSshPaneSearchEntries = createLocalizedCatalog(() => [
'Import hosts from ~/.ssh/config.'
),
keywords: [
- translate('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
- translate('auto.components.settings.ssh.search.3b12e064a4', 'import'),
- translate('auto.components.settings.ssh.search.5220501141', 'config'),
- translate('auto.components.settings.ssh.search.2cd40ba0d0', 'hosts')
+ ...translateSearchKeyword('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.3b12e064a4', 'import'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.5220501141', 'config'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.2cd40ba0d0', 'hosts')
]
},
{
@@ -51,10 +52,10 @@ export const getSshPaneSearchEntries = createLocalizedCatalog(() => [
'Test connectivity to an SSH target.'
),
keywords: [
- translate('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
- translate('auto.components.settings.ssh.search.8cb870b109', 'test'),
- translate('auto.components.settings.ssh.search.237b391f7c', 'connection'),
- translate('auto.components.settings.ssh.search.d41f296f64', 'ping')
+ ...translateSearchKeyword('auto.components.settings.ssh.search.7efd17e816', 'ssh'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.8cb870b109', 'test'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.237b391f7c', 'connection'),
+ ...translateSearchKeyword('auto.components.settings.ssh.search.d41f296f64', 'ping')
]
}
])
diff --git a/src/renderer/src/components/settings/tasks-search.ts b/src/renderer/src/components/settings/tasks-search.ts
index c9fe44cf211..0f5dd9a1a20 100644
--- a/src/renderer/src/components/settings/tasks-search.ts
+++ b/src/renderer/src/components/settings/tasks-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTasksPaneSearchEntries = createLocalizedCatalog(() => [
@@ -9,16 +10,16 @@ export const getTasksPaneSearchEntries = createLocalizedCatalog(() => [
'Choose which task providers appear in the Tasks page and sidebar shortcuts.'
),
keywords: [
- translate('auto.components.settings.tasks.search.2ec54bee51', 'tasks'),
- translate('auto.components.settings.tasks.search.cf0e3e0c2f', 'provider'),
- translate('auto.components.settings.tasks.search.3d81c26d78', 'source'),
- translate('auto.components.settings.tasks.search.c10ac2125e', 'github'),
- translate('auto.components.settings.tasks.search.11f001cdd4', 'gitlab'),
- translate('auto.components.settings.tasks.search.412ec3c702', 'linear'),
- translate('auto.components.settings.tasks.search.5430396e11', 'jira'),
- translate('auto.components.settings.tasks.search.604d8e4089', 'atlassian'),
- translate('auto.components.settings.tasks.search.44083ae418', 'display'),
- translate('auto.components.settings.tasks.search.58cda6f9c0', 'hide')
+ ...translateSearchKeyword('auto.components.settings.tasks.search.2ec54bee51', 'tasks'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.cf0e3e0c2f', 'provider'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.3d81c26d78', 'source'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.c10ac2125e', 'github'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.11f001cdd4', 'gitlab'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.412ec3c702', 'linear'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.5430396e11', 'jira'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.604d8e4089', 'atlassian'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.44083ae418', 'display'),
+ ...translateSearchKeyword('auto.components.settings.tasks.search.58cda6f9c0', 'hide')
]
}
])
diff --git a/src/renderer/src/components/settings/terminal-advanced-platform-search.ts b/src/renderer/src/components/settings/terminal-advanced-platform-search.ts
index b8ee29c632f..ae99099c91b 100644
--- a/src/renderer/src/components/settings/terminal-advanced-platform-search.ts
+++ b/src/renderer/src/components/settings/terminal-advanced-platform-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalAdvancedSearchEntries = createLocalizedCatalog(() => [
@@ -9,10 +10,13 @@ export const getTerminalAdvancedSearchEntries = createLocalizedCatalog(() => [
'Maximum terminal scrollback buffer size.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.cde233f5da', 'scrollback'),
- translate('auto.components.settings.terminal.search.fffdff40a7', 'buffer'),
- translate('auto.components.settings.terminal.search.56fff3d113', 'memory')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.cde233f5da',
+ 'scrollback'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.fffdff40a7', 'buffer'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.56fff3d113', 'memory')
]
},
{
@@ -22,11 +26,14 @@ export const getTerminalAdvancedSearchEntries = createLocalizedCatalog(() => [
'Characters treated as word boundaries for double-click selection.'
),
keywords: [
- translate('auto.components.settings.terminal.search.7286cd2566', 'word'),
- translate('auto.components.settings.terminal.search.d4aeafac10', 'separator'),
- translate('auto.components.settings.terminal.search.4ed3e239a8', 'boundary'),
- translate('auto.components.settings.terminal.search.d2a366c7f9', 'double-click'),
- translate('auto.components.settings.terminal.search.affb14efd4', 'selection')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7286cd2566', 'word'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d4aeafac10', 'separator'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.4ed3e239a8', 'boundary'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.d2a366c7f9',
+ 'double-click'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.affb14efd4', 'selection')
]
}
])
@@ -39,19 +46,22 @@ export const getTerminalMacOptionSearchEntries = createLocalizedCatalog(() => [
"Controls whether the macOS Option key sends Alt/Esc sequences or composes characters. Mirrors Ghostty's macos-option-as-alt."
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.b37edfc65a', 'option'),
- translate('auto.components.settings.terminal.search.c4427dc5ff', 'alt'),
- translate('auto.components.settings.terminal.search.38f1b4f4cb', 'key'),
- translate('auto.components.settings.terminal.search.7ace5beec9', 'meta'),
- translate('auto.components.settings.terminal.search.983d45cf4c', 'compose'),
- translate('auto.components.settings.terminal.search.1ab57a0fbd', 'mac'),
- translate('auto.components.settings.terminal.search.d8d6f7a3c5', 'macos'),
- translate('auto.components.settings.terminal.search.abaa24752d', 'keyboard'),
- translate('auto.components.settings.terminal.search.dd4f6cb541', 'german'),
- translate('auto.components.settings.terminal.search.b3b94cfcb5', 'international'),
- translate('auto.components.settings.terminal.search.fae142a354', 'readline'),
- translate('auto.components.settings.terminal.search.82b63d07fe', 'ghostty')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b37edfc65a', 'option'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.c4427dc5ff', 'alt'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.38f1b4f4cb', 'key'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7ace5beec9', 'meta'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.983d45cf4c', 'compose'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.1ab57a0fbd', 'mac'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d8d6f7a3c5', 'macos'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.abaa24752d', 'keyboard'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.dd4f6cb541', 'german'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.b3b94cfcb5',
+ 'international'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.fae142a354', 'readline'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.82b63d07fe', 'ghostty')
]
}
])
@@ -67,15 +77,15 @@ export const getTerminalMacYenSearchEntries = createLocalizedCatalog(() => [
'Controls whether pressing the JIS Yen (¥) key sends a backslash (\\) instead.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.9c35f56625', 'yen'),
- translate('auto.components.settings.terminal.search.98059d0944', 'backslash'),
- translate('auto.components.settings.terminal.search.24f7977756', 'japanese'),
- translate('auto.components.settings.terminal.search.abaa24752d', 'keyboard'),
- translate('auto.components.settings.terminal.search.1ab57a0fbd', 'mac'),
- translate('auto.components.settings.terminal.search.d8d6f7a3c5', 'macos'),
- translate('auto.components.settings.terminal.search.b495dc6a9f', 'jis'),
- translate('auto.components.settings.terminal.search.4cec42dbf7', 'intl')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.9c35f56625', 'yen'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.98059d0944', 'backslash'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.24f7977756', 'japanese'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.abaa24752d', 'keyboard'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.1ab57a0fbd', 'mac'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d8d6f7a3c5', 'macos'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b495dc6a9f', 'jis'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.4cec42dbf7', 'intl')
]
}
])
@@ -88,11 +98,11 @@ export const getTerminalGhosttyImportSearchEntries = createLocalizedCatalog(() =
'One-time import of supported Ghostty terminal settings.'
),
keywords: [
- translate('auto.components.settings.terminal.search.82b63d07fe', 'ghostty'),
- translate('auto.components.settings.terminal.search.fd752b3cac', 'import'),
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.2ade3ea490', 'config'),
- translate('auto.components.settings.terminal.search.10f9fb6fea', 'settings')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.82b63d07fe', 'ghostty'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.fd752b3cac', 'import'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.2ade3ea490', 'config'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.10f9fb6fea', 'settings')
]
}
])
diff --git a/src/renderer/src/components/settings/terminal-clipboard-search.ts b/src/renderer/src/components/settings/terminal-clipboard-search.ts
index 6010e4d66a5..3b378e211b5 100644
--- a/src/renderer/src/components/settings/terminal-clipboard-search.ts
+++ b/src/renderer/src/components/settings/terminal-clipboard-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalClipboardSearchEntries = createLocalizedCatalog(() => [
@@ -12,16 +13,46 @@ export const getTerminalClipboardSearchEntries = createLocalizedCatalog(() => [
'Automatically copy terminal selections to the clipboard as soon as a selection is made.'
),
keywords: [
- translate('auto.components.settings.terminal.clipboard.search.10d73e22d3', 'clipboard'),
- translate('auto.components.settings.terminal.clipboard.search.a38508c419', 'copy'),
- translate('auto.components.settings.terminal.clipboard.search.797fdfe4ca', 'select'),
- translate('auto.components.settings.terminal.clipboard.search.c38c18be15', 'selection'),
- translate('auto.components.settings.terminal.clipboard.search.664789b73a', 'auto'),
- translate('auto.components.settings.terminal.clipboard.search.e87c6d776d', 'automatic'),
- translate('auto.components.settings.terminal.clipboard.search.737cef6de1', 'x11'),
- translate('auto.components.settings.terminal.clipboard.search.cf83ac3dbd', 'linux'),
- translate('auto.components.settings.terminal.clipboard.search.4043e294d2', 'gnome'),
- translate('auto.components.settings.terminal.clipboard.search.5fb3512e8c', 'paste')
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.10d73e22d3',
+ 'clipboard'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.a38508c419',
+ 'copy'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.797fdfe4ca',
+ 'select'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.c38c18be15',
+ 'selection'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.664789b73a',
+ 'auto'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.e87c6d776d',
+ 'automatic'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.737cef6de1',
+ 'x11'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.cf83ac3dbd',
+ 'linux'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.4043e294d2',
+ 'gnome'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.5fb3512e8c',
+ 'paste'
+ )
]
},
{
@@ -34,17 +65,50 @@ export const getTerminalClipboardSearchEntries = createLocalizedCatalog(() => [
'Let programs in the terminal copy to the system clipboard through OSC 52, including over SSH.'
),
keywords: [
- translate('auto.components.settings.terminal.clipboard.search.62d1208b90', 'osc 52'),
- translate('auto.components.settings.terminal.clipboard.search.9dfc125cd3', 'osc52'),
- translate('auto.components.settings.terminal.clipboard.search.10d73e22d3', 'clipboard'),
- translate('auto.components.settings.terminal.clipboard.search.5ffcd13c90', 'tmux'),
- translate('auto.components.settings.terminal.clipboard.search.2061d8db1a', 'neovim'),
- translate('auto.components.settings.terminal.clipboard.search.64533e30cc', 'nvim'),
- translate('auto.components.settings.terminal.clipboard.search.9fda309db9', 'fzf'),
- translate('auto.components.settings.terminal.clipboard.search.043b32faa1', 'ssh'),
- translate('auto.components.settings.terminal.clipboard.search.d106f44fb4', 'remote'),
- translate('auto.components.settings.terminal.clipboard.search.a38508c419', 'copy'),
- translate('auto.components.settings.terminal.clipboard.search.5fb3512e8c', 'paste')
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.62d1208b90',
+ 'osc 52'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.9dfc125cd3',
+ 'osc52'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.10d73e22d3',
+ 'clipboard'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.5ffcd13c90',
+ 'tmux'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.2061d8db1a',
+ 'neovim'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.64533e30cc',
+ 'nvim'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.9fda309db9',
+ 'fzf'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.043b32faa1',
+ 'ssh'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.d106f44fb4',
+ 'remote'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.a38508c419',
+ 'copy'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.clipboard.search.5fb3512e8c',
+ 'paste'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/terminal-pane-appearance-search.ts b/src/renderer/src/components/settings/terminal-pane-appearance-search.ts
index 675ea82451d..b20c146a233 100644
--- a/src/renderer/src/components/settings/terminal-pane-appearance-search.ts
+++ b/src/renderer/src/components/settings/terminal-pane-appearance-search.ts
@@ -1,5 +1,6 @@
import { getTerminalClipboardSearchEntries } from './terminal-clipboard-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalPaneAppearanceSearchEntries = createLocalizedCatalog(() => [
@@ -13,9 +14,9 @@ export const getTerminalPaneAppearanceSearchEntries = createLocalizedCatalog(()
'Opacity applied to panes that are not currently active.'
),
keywords: [
- translate('auto.components.settings.terminal.search.846a7a1204', 'pane'),
- translate('auto.components.settings.terminal.search.46d99ef4bb', 'opacity'),
- translate('auto.components.settings.terminal.search.6c4c85ba43', 'dimming')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.846a7a1204', 'pane'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.46d99ef4bb', 'opacity'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6c4c85ba43', 'dimming')
]
},
{
@@ -25,9 +26,9 @@ export const getTerminalPaneAppearanceSearchEntries = createLocalizedCatalog(()
'Thickness of the pane divider line.'
),
keywords: [
- translate('auto.components.settings.terminal.search.846a7a1204', 'pane'),
- translate('auto.components.settings.terminal.search.781f49d942', 'divider'),
- translate('auto.components.settings.terminal.search.f637a7dee9', 'thickness')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.846a7a1204', 'pane'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.781f49d942', 'divider'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f637a7dee9', 'thickness')
]
}
])
@@ -40,13 +41,13 @@ export const getTerminalPaneInteractionSearchEntries = createLocalizedCatalog(()
"Hovering a terminal pane activates it without needing to click. Mirrors Ghostty's focus-follows-mouse setting. Selections and window switching stay safe."
),
keywords: [
- translate('auto.components.settings.terminal.search.f5d1e3d472', 'focus'),
- translate('auto.components.settings.terminal.search.b5116e7b12', 'follows'),
- translate('auto.components.settings.terminal.search.ea364ce6e4', 'mouse'),
- translate('auto.components.settings.terminal.search.d1fa00a9cb', 'hover'),
- translate('auto.components.settings.terminal.search.846a7a1204', 'pane'),
- translate('auto.components.settings.terminal.search.82b63d07fe', 'ghostty'),
- translate('auto.components.settings.terminal.search.f036794286', 'active')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f5d1e3d472', 'focus'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b5116e7b12', 'follows'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.ea364ce6e4', 'mouse'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d1fa00a9cb', 'hover'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.846a7a1204', 'pane'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.82b63d07fe', 'ghostty'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f036794286', 'active')
]
},
...getTerminalClipboardSearchEntries()
diff --git a/src/renderer/src/components/settings/terminal-theme-search.ts b/src/renderer/src/components/settings/terminal-theme-search.ts
index fbcc1d6ce97..fa2395005f8 100644
--- a/src/renderer/src/components/settings/terminal-theme-search.ts
+++ b/src/renderer/src/components/settings/terminal-theme-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalDarkThemeSearchEntries = createLocalizedCatalog(() => [
@@ -9,10 +10,10 @@ export const getTerminalDarkThemeSearchEntries = createLocalizedCatalog(() => [
'Choose the terminal theme used in dark mode.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.0ce176909a', 'theme'),
- translate('auto.components.settings.terminal.search.f785374072', 'dark'),
- translate('auto.components.settings.terminal.search.7718d70356', 'preview')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.0ce176909a', 'theme'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f785374072', 'dark'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7718d70356', 'preview')
]
},
{
@@ -22,10 +23,10 @@ export const getTerminalDarkThemeSearchEntries = createLocalizedCatalog(() => [
'Controls the split divider line between panes in dark mode.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.781f49d942', 'divider'),
- translate('auto.components.settings.terminal.search.f785374072', 'dark'),
- translate('auto.components.settings.terminal.search.674b7c8436', 'color')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.781f49d942', 'divider'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f785374072', 'dark'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.674b7c8436', 'color')
]
}
])
@@ -41,9 +42,12 @@ export const getTerminalLightThemeSearchEntries = createLocalizedCatalog(() => [
'When disabled, light mode reuses the dark terminal theme.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.da864e6cec', 'light mode'),
- translate('auto.components.settings.terminal.search.0ce176909a', 'theme')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.da864e6cec',
+ 'light mode'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.0ce176909a', 'theme')
]
},
{
@@ -53,10 +57,10 @@ export const getTerminalLightThemeSearchEntries = createLocalizedCatalog(() => [
'Choose the theme used when Orca is in light mode.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.0ce176909a', 'theme'),
- translate('auto.components.settings.terminal.search.411229c636', 'light'),
- translate('auto.components.settings.terminal.search.7718d70356', 'preview')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.0ce176909a', 'theme'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.411229c636', 'light'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7718d70356', 'preview')
]
},
{
@@ -66,10 +70,10 @@ export const getTerminalLightThemeSearchEntries = createLocalizedCatalog(() => [
'Controls the split divider line between panes in light mode.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.781f49d942', 'divider'),
- translate('auto.components.settings.terminal.search.411229c636', 'light'),
- translate('auto.components.settings.terminal.search.674b7c8436', 'color')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.781f49d942', 'divider'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.411229c636', 'light'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.674b7c8436', 'color')
]
}
])
diff --git a/src/renderer/src/components/settings/terminal-typography-search.ts b/src/renderer/src/components/settings/terminal-typography-search.ts
index 53e29fc6f6f..ed04dcc07be 100644
--- a/src/renderer/src/components/settings/terminal-typography-search.ts
+++ b/src/renderer/src/components/settings/terminal-typography-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalTypographySearchEntries = createLocalizedCatalog(() => [
@@ -9,9 +10,12 @@ export const getTerminalTypographySearchEntries = createLocalizedCatalog(() => [
'Default terminal font size for new panes and live updates.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.103cdb862f', 'typography'),
- translate('auto.components.settings.terminal.search.33031c1465', 'text size')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.103cdb862f',
+ 'typography'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.33031c1465', 'text size')
]
},
{
@@ -21,9 +25,12 @@ export const getTerminalTypographySearchEntries = createLocalizedCatalog(() => [
'Default terminal font family for new panes and live updates.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.103cdb862f', 'typography'),
- translate('auto.components.settings.terminal.search.b0bb76ae6b', 'font')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.103cdb862f',
+ 'typography'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b0bb76ae6b', 'font')
]
},
{
@@ -33,9 +40,12 @@ export const getTerminalTypographySearchEntries = createLocalizedCatalog(() => [
'Controls the terminal text font weight.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.103cdb862f', 'typography'),
- translate('auto.components.settings.terminal.search.20ce287cc6', 'weight')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.103cdb862f',
+ 'typography'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.20ce287cc6', 'weight')
]
},
{
@@ -45,10 +55,16 @@ export const getTerminalTypographySearchEntries = createLocalizedCatalog(() => [
'Controls the terminal line height multiplier.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.103cdb862f', 'typography'),
- translate('auto.components.settings.terminal.search.7341e3d00e', 'line height'),
- translate('auto.components.settings.terminal.search.b2f52cb96c', 'spacing')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.103cdb862f',
+ 'typography'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.7341e3d00e',
+ 'line height'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b2f52cb96c', 'spacing')
]
},
{
@@ -58,16 +74,28 @@ export const getTerminalTypographySearchEntries = createLocalizedCatalog(() => [
'Render programming ligatures (e.g. => → ≠ ≥) for fonts that ship them. "Auto" enables ligatures only for known ligature fonts (Fira Code, JetBrains Mono, Cascadia Code, Iosevka, etc.).'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.103cdb862f', 'typography'),
- translate('auto.components.settings.terminal.search.afc8d5f790', 'ligatures'),
- translate('auto.components.settings.terminal.search.7ab424c4d3', 'ligature'),
- translate('auto.components.settings.terminal.search.7f7640c29e', 'fira code'),
- translate('auto.components.settings.terminal.search.35c2311a33', 'jetbrains mono'),
- translate('auto.components.settings.terminal.search.e3aeea308e', 'cascadia code'),
- translate('auto.components.settings.terminal.search.6ded6297fe', 'iosevka'),
- translate('auto.components.settings.terminal.search.a16224d16a', 'calt'),
- translate('auto.components.settings.terminal.search.d5e6c7fab1', 'font features')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.103cdb862f',
+ 'typography'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.afc8d5f790', 'ligatures'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7ab424c4d3', 'ligature'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7f7640c29e', 'fira code'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.35c2311a33',
+ 'jetbrains mono'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.e3aeea308e',
+ 'cascadia code'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6ded6297fe', 'iosevka'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.a16224d16a', 'calt'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.d5e6c7fab1',
+ 'font features'
+ )
]
}
])
@@ -80,14 +108,17 @@ export const getTerminalRenderingSearchEntries = createLocalizedCatalog(() => [
'Controls whether the terminal uses xterm.js WebGL rendering. Auto tries WebGL when the renderer is supported, with conservative fallback for software or unknown GPU renderers.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.db82cb13b0', 'gpu'),
- translate('auto.components.settings.terminal.search.4b4e80d850', 'acceleration'),
- translate('auto.components.settings.terminal.search.6cddc858ba', 'webgl'),
- translate('auto.components.settings.terminal.search.fffa9ab980', 'renderer'),
- translate('auto.components.settings.terminal.search.bc7ae1f7c0', 'rendering'),
- translate('auto.components.settings.terminal.search.7d924d870d', 'graphics'),
- translate('auto.components.settings.terminal.search.1abcf4d7de', 'linux')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.db82cb13b0', 'gpu'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.4b4e80d850',
+ 'acceleration'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6cddc858ba', 'webgl'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.fffa9ab980', 'renderer'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.bc7ae1f7c0', 'rendering'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7d924d870d', 'graphics'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.1abcf4d7de', 'linux')
]
}
])
@@ -100,11 +131,11 @@ export const getTerminalCursorSearchEntries = createLocalizedCatalog(() => [
'Default cursor appearance for Orca terminal panes.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor'),
- translate('auto.components.settings.terminal.search.a6e9dcc829', 'bar'),
- translate('auto.components.settings.terminal.search.015c82349f', 'block'),
- translate('auto.components.settings.terminal.search.eefd1d8332', 'underline')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.a6e9dcc829', 'bar'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.015c82349f', 'block'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.eefd1d8332', 'underline')
]
},
{
@@ -114,9 +145,9 @@ export const getTerminalCursorSearchEntries = createLocalizedCatalog(() => [
'Uses the blinking variant of the selected cursor shape.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor'),
- translate('auto.components.settings.terminal.search.25f606d9e5', 'blink')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.25f606d9e5', 'blink')
]
},
{
@@ -126,10 +157,13 @@ export const getTerminalCursorSearchEntries = createLocalizedCatalog(() => [
'Opacity of the terminal cursor.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor'),
- translate('auto.components.settings.terminal.search.46d99ef4bb', 'opacity'),
- translate('auto.components.settings.terminal.search.4f7f8f28ca', 'transparency')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.46d99ef4bb', 'opacity'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.4f7f8f28ca',
+ 'transparency'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/terminal-window-setup-search.ts b/src/renderer/src/components/settings/terminal-window-setup-search.ts
index a0ad500b359..31877d088b1 100644
--- a/src/renderer/src/components/settings/terminal-window-setup-search.ts
+++ b/src/renderer/src/components/settings/terminal-window-setup-search.ts
@@ -1,4 +1,5 @@
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getManageSessionsSearchEntries = createLocalizedCatalog(() => [
@@ -9,20 +10,23 @@ export const getManageSessionsSearchEntries = createLocalizedCatalog(() => [
'Recover from frozen terminals by killing sessions, clearing saved scrollback, or restarting the daemon.'
),
keywords: [
- translate('auto.components.settings.terminal.search.f35400f7e8', 'daemon'),
- translate('auto.components.settings.terminal.search.9f2dda133c', 'pty'),
- translate('auto.components.settings.terminal.search.d802a578bf', 'sessions'),
- translate('auto.components.settings.terminal.search.a8d2784214', 'manage'),
- translate('auto.components.settings.terminal.search.a3e5297c10', 'kill'),
- translate('auto.components.settings.terminal.search.920573d65b', 'kill all'),
- translate('auto.components.settings.terminal.search.456da64d4d', 'clear'),
- translate('auto.components.settings.terminal.search.3982d88725', 'history'),
- translate('auto.components.settings.terminal.search.cde233f5da', 'scrollback'),
- translate('auto.components.settings.terminal.search.6892fb1019', 'restart'),
- translate('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
- translate('auto.components.settings.terminal.search.0a05629060', 'recover'),
- translate('auto.components.settings.terminal.search.88561b3499', 'frozen'),
- translate('auto.components.settings.terminal.search.d4daf4f612', 'unfreeze')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f35400f7e8', 'daemon'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.9f2dda133c', 'pty'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d802a578bf', 'sessions'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.a8d2784214', 'manage'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.a3e5297c10', 'kill'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.920573d65b', 'kill all'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.456da64d4d', 'clear'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.3982d88725', 'history'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.cde233f5da',
+ 'scrollback'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6892fb1019', 'restart'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f66a7cf715', 'terminal'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.0a05629060', 'recover'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.88561b3499', 'frozen'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d4daf4f612', 'unfreeze')
]
}
])
@@ -35,10 +39,16 @@ export const getTerminalWindowSearchEntries = createLocalizedCatalog(() => [
'Controls the transparency of the terminal background.'
),
keywords: [
- translate('auto.components.settings.terminal.search.46d99ef4bb', 'opacity'),
- translate('auto.components.settings.terminal.search.4f7f8f28ca', 'transparency'),
- translate('auto.components.settings.terminal.search.f6dd9ff606', 'background'),
- translate('auto.components.settings.terminal.search.7db59c4738', 'alpha')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.46d99ef4bb', 'opacity'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.4f7f8f28ca',
+ 'transparency'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.f6dd9ff606',
+ 'background'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7db59c4738', 'alpha')
]
},
{
@@ -48,11 +58,17 @@ export const getTerminalWindowSearchEntries = createLocalizedCatalog(() => [
'Apply background blur to the terminal window. Requires restart.'
),
keywords: [
- translate('auto.components.settings.terminal.search.0838b3717b', 'window'),
- translate('auto.components.settings.terminal.search.71eb45e293', 'blur'),
- translate('auto.components.settings.terminal.search.f6dd9ff606', 'background'),
- translate('auto.components.settings.terminal.search.4f7f8f28ca', 'transparency'),
- translate('auto.components.settings.terminal.search.6c2f9f05c8', 'vibrancy')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.0838b3717b', 'window'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.71eb45e293', 'blur'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.f6dd9ff606',
+ 'background'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.4f7f8f28ca',
+ 'transparency'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6c2f9f05c8', 'vibrancy')
]
},
{
@@ -62,10 +78,13 @@ export const getTerminalWindowSearchEntries = createLocalizedCatalog(() => [
'Horizontal padding around the terminal grid in pixels.'
),
keywords: [
- translate('auto.components.settings.terminal.search.e8baf0d12c', 'padding'),
- translate('auto.components.settings.terminal.search.54a9b3725b', 'horizontal'),
- translate('auto.components.settings.terminal.search.b2f52cb96c', 'spacing'),
- translate('auto.components.settings.terminal.search.f25d948664', 'margin')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.e8baf0d12c', 'padding'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.54a9b3725b',
+ 'horizontal'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b2f52cb96c', 'spacing'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f25d948664', 'margin')
]
},
{
@@ -75,10 +94,10 @@ export const getTerminalWindowSearchEntries = createLocalizedCatalog(() => [
'Vertical padding around the terminal grid in pixels.'
),
keywords: [
- translate('auto.components.settings.terminal.search.e8baf0d12c', 'padding'),
- translate('auto.components.settings.terminal.search.18ce996647', 'vertical'),
- translate('auto.components.settings.terminal.search.b2f52cb96c', 'spacing'),
- translate('auto.components.settings.terminal.search.f25d948664', 'margin')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.e8baf0d12c', 'padding'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.18ce996647', 'vertical'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b2f52cb96c', 'spacing'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f25d948664', 'margin')
]
},
{
@@ -91,10 +110,10 @@ export const getTerminalWindowSearchEntries = createLocalizedCatalog(() => [
'Hide the mouse cursor when typing in the terminal.'
),
keywords: [
- translate('auto.components.settings.terminal.search.ea364ce6e4', 'mouse'),
- translate('auto.components.settings.terminal.search.ee611ae238', 'hide'),
- translate('auto.components.settings.terminal.search.34fe1af39d', 'typing'),
- translate('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.ea364ce6e4', 'mouse'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.ee611ae238', 'hide'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.34fe1af39d', 'typing'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6eaf7ee0e4', 'cursor')
]
},
{
@@ -104,11 +123,11 @@ export const getTerminalWindowSearchEntries = createLocalizedCatalog(() => [
'Override individual terminal colors.'
),
keywords: [
- translate('auto.components.settings.terminal.search.674b7c8436', 'color'),
- translate('auto.components.settings.terminal.search.d8bd6182b8', 'override'),
- translate('auto.components.settings.terminal.search.11fd3fbcf2', 'ansi'),
- translate('auto.components.settings.terminal.search.4ba8623632', 'palette'),
- translate('auto.components.settings.terminal.search.0ce176909a', 'theme')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.674b7c8436', 'color'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.d8bd6182b8', 'override'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.11fd3fbcf2', 'ansi'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.4ba8623632', 'palette'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.0ce176909a', 'theme')
]
}
])
@@ -124,16 +143,19 @@ export const getTerminalSetupScriptSearchEntries = createLocalizedCatalog(() =>
"Where the repository setup script runs when a new workspace is created: a vertical split (default), a horizontal split, or a background tab titled 'Setup'."
),
keywords: [
- translate('auto.components.settings.terminal.search.4529806908', 'setup'),
- translate('auto.components.settings.terminal.search.6b659fff2a', 'script'),
- translate('auto.components.settings.terminal.search.7a48c7715b', 'workspace'),
- translate('auto.components.settings.terminal.search.de7bc1d5f5', 'split'),
- translate('auto.components.settings.terminal.search.54a9b3725b', 'horizontal'),
- translate('auto.components.settings.terminal.search.18ce996647', 'vertical'),
- translate('auto.components.settings.terminal.search.f44643328e', 'tab'),
- translate('auto.components.settings.terminal.search.fd6c24313d', 'new'),
- translate('auto.components.settings.terminal.search.b872de3926', 'location'),
- translate('auto.components.settings.terminal.search.c047f398cc', 'launch')
+ ...translateSearchKeyword('auto.components.settings.terminal.search.4529806908', 'setup'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.6b659fff2a', 'script'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.7a48c7715b', 'workspace'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.de7bc1d5f5', 'split'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.search.54a9b3725b',
+ 'horizontal'
+ ),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.18ce996647', 'vertical'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.f44643328e', 'tab'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.fd6c24313d', 'new'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.b872de3926', 'location'),
+ ...translateSearchKeyword('auto.components.settings.terminal.search.c047f398cc', 'launch')
]
}
])
diff --git a/src/renderer/src/components/settings/terminal-windows-search.ts b/src/renderer/src/components/settings/terminal-windows-search.ts
index 30400997181..c2192ae8dee 100644
--- a/src/renderer/src/components/settings/terminal-windows-search.ts
+++ b/src/renderer/src/components/settings/terminal-windows-search.ts
@@ -1,5 +1,6 @@
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getTerminalWindowsShellSearchEntry = createLocalizedCatalog(() => [
@@ -13,19 +14,58 @@ export const getTerminalWindowsShellSearchEntry = createLocalizedCatalog(() => [
'Choose the default shell for new terminal panes on Windows.'
),
keywords: [
- translate('auto.components.settings.terminal.windows.search.e7d2793b03', 'terminal'),
- translate('auto.components.settings.terminal.windows.search.28ff08ed35', 'windows'),
- translate('auto.components.settings.terminal.windows.search.7c7056940a', 'shell'),
- translate('auto.components.settings.terminal.windows.search.2d99cd91be', 'powershell'),
- translate('auto.components.settings.terminal.windows.search.6cd20b9e64', 'cmd'),
- translate('auto.components.settings.terminal.windows.search.12519edb5d', 'command prompt'),
- translate('auto.components.settings.terminal.windows.search.04994f6929', 'default'),
- translate('auto.components.settings.terminal.windows.search.591912177b', 'git bash'),
- translate('auto.components.settings.terminal.windows.search.6e3adf4cba', 'wsl'),
- translate('auto.components.settings.terminal.windows.search.02c772582a', 'linux'),
- translate('auto.components.settings.terminal.windows.search.5a2db98d23', 'bash'),
- translate('auto.components.settings.terminal.windows.search.07ec155fb6', 'bash.exe'),
- translate('auto.components.settings.terminal.windows.search.4ee2579c32', 'ubuntu')
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.e7d2793b03',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.28ff08ed35',
+ 'windows'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.7c7056940a',
+ 'shell'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.2d99cd91be',
+ 'powershell'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.6cd20b9e64',
+ 'cmd'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.12519edb5d',
+ 'command prompt'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.04994f6929',
+ 'default'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.591912177b',
+ 'git bash'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.6e3adf4cba',
+ 'wsl'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.02c772582a',
+ 'linux'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.5a2db98d23',
+ 'bash'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.07ec155fb6',
+ 'bash.exe'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.4ee2579c32',
+ 'ubuntu'
+ )
]
}
])
@@ -41,17 +81,38 @@ export const getTerminalWindowsPowershellImplementationSearchEntry = createLocal
'Choose whether the PowerShell shell option launches Windows PowerShell or PowerShell 7+ for new terminal panes.'
),
keywords: [
- translate('auto.components.settings.terminal.windows.search.e7d2793b03', 'terminal'),
- translate('auto.components.settings.terminal.windows.search.28ff08ed35', 'windows'),
- translate('auto.components.settings.terminal.windows.search.2d99cd91be', 'powershell'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.e7d2793b03',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.28ff08ed35',
+ 'windows'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.2d99cd91be',
+ 'powershell'
+ ),
translate(
'auto.components.settings.terminal.windows.search.f9162f0b8e',
'windows powershell'
),
- translate('auto.components.settings.terminal.windows.search.768613e483', 'powershell 7'),
- translate('auto.components.settings.terminal.windows.search.d414022016', 'pwsh'),
- translate('auto.components.settings.terminal.windows.search.4af2f7526e', 'version'),
- translate('auto.components.settings.terminal.windows.search.d57f870938', 'advanced')
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.768613e483',
+ 'powershell 7'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.d414022016',
+ 'pwsh'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.4af2f7526e',
+ 'version'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.d57f870938',
+ 'advanced'
+ )
]
}
])
@@ -67,15 +128,42 @@ export const getTerminalWindowsWslDistroSearchEntry = createLocalizedCatalog(()
'Choose which WSL distribution new WSL terminals and local agent scans use.'
),
keywords: [
- translate('auto.components.settings.terminal.windows.search.e7d2793b03', 'terminal'),
- translate('auto.components.settings.terminal.windows.search.28ff08ed35', 'windows'),
- translate('auto.components.settings.terminal.windows.search.6e3adf4cba', 'wsl'),
- translate('auto.components.settings.terminal.windows.search.02c772582a', 'linux'),
- translate('auto.components.settings.terminal.windows.search.2b4a340ce0', 'distribution'),
- translate('auto.components.settings.terminal.windows.search.5074ad8b5f', 'distro'),
- translate('auto.components.settings.terminal.windows.search.4ee2579c32', 'ubuntu'),
- translate('auto.components.settings.terminal.windows.search.fc564eadaf', 'debian'),
- translate('auto.components.settings.terminal.windows.search.04994f6929', 'default')
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.e7d2793b03',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.28ff08ed35',
+ 'windows'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.6e3adf4cba',
+ 'wsl'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.02c772582a',
+ 'linux'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.2b4a340ce0',
+ 'distribution'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.5074ad8b5f',
+ 'distro'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.4ee2579c32',
+ 'ubuntu'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.fc564eadaf',
+ 'debian'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.04994f6929',
+ 'default'
+ )
]
}
])
@@ -91,11 +179,26 @@ export const getTerminalRightClickToPasteSearchEntry = createLocalizedCatalog(()
'On Windows, right-click pastes the clipboard into the terminal. Use Ctrl+right-click to open the context menu.'
),
keywords: [
- translate('auto.components.settings.terminal.windows.search.e7d2793b03', 'terminal'),
- translate('auto.components.settings.terminal.windows.search.28ff08ed35', 'windows'),
- translate('auto.components.settings.terminal.windows.search.e55186fe2b', 'right click'),
- translate('auto.components.settings.terminal.windows.search.fcfa53920b', 'paste'),
- translate('auto.components.settings.terminal.windows.search.4d09141a42', 'context menu')
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.e7d2793b03',
+ 'terminal'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.28ff08ed35',
+ 'windows'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.e55186fe2b',
+ 'right click'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.fcfa53920b',
+ 'paste'
+ ),
+ ...translateSearchKeyword(
+ 'auto.components.settings.terminal.windows.search.4d09141a42',
+ 'context menu'
+ )
]
}
])
diff --git a/src/renderer/src/components/settings/voice-pane-search.ts b/src/renderer/src/components/settings/voice-pane-search.ts
index f1a442720d6..4568f65d7bd 100644
--- a/src/renderer/src/components/settings/voice-pane-search.ts
+++ b/src/renderer/src/components/settings/voice-pane-search.ts
@@ -1,5 +1,6 @@
import type { SettingsSearchEntry } from './settings-search'
import { translate } from '@/i18n/i18n'
+import { translateSearchKeyword } from './settings-search-keywords'
import { createLocalizedCatalog } from '@/i18n/localized-catalog'
export const getOpenaiTranscriptionSearchEntry = createLocalizedCatalog(
@@ -13,13 +14,16 @@ export const getOpenaiTranscriptionSearchEntry = createLocalizedCatalog(
'Configure the OpenAI API key used for cloud speech-to-text models.'
),
keywords: [
- translate('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
- translate('auto.components.settings.voice.pane.search.3d8b853963', 'speech'),
- translate('auto.components.settings.voice.pane.search.10d45a9fce', 'stt'),
- translate('auto.components.settings.voice.pane.search.04c25a6fb0', 'openai'),
- translate('auto.components.settings.voice.pane.search.2d206de105', 'api key'),
- translate('auto.components.settings.voice.pane.search.f6e0dfa61c', 'cloud'),
- translate('auto.components.settings.voice.pane.search.322d457a0d', 'transcription')
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.3d8b853963', 'speech'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.10d45a9fce', 'stt'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.04c25a6fb0', 'openai'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.2d206de105', 'api key'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.f6e0dfa61c', 'cloud'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.voice.pane.search.322d457a0d',
+ 'transcription'
+ )
]
})
)
@@ -35,11 +39,17 @@ export const getVoicePaneSearchEntries = createLocalizedCatalog(() => [
'Master toggle for voice dictation features.'
),
keywords: [
- translate('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
- translate('auto.components.settings.voice.pane.search.089d31a45b', 'dictation'),
- translate('auto.components.settings.voice.pane.search.3d8b853963', 'speech'),
- translate('auto.components.settings.voice.pane.search.e360027a65', 'microphone'),
- translate('auto.components.settings.voice.pane.search.10d45a9fce', 'stt')
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.voice.pane.search.089d31a45b',
+ 'dictation'
+ ),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.3d8b853963', 'speech'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.voice.pane.search.e360027a65',
+ 'microphone'
+ ),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.10d45a9fce', 'stt')
]
},
{
@@ -49,12 +59,18 @@ export const getVoicePaneSearchEntries = createLocalizedCatalog(() => [
'Toggle or hold-to-talk dictation behavior.'
),
keywords: [
- translate('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
- translate('auto.components.settings.voice.pane.search.089d31a45b', 'dictation'),
- translate('auto.components.settings.voice.pane.search.d86f5600da', 'mode'),
- translate('auto.components.settings.voice.pane.search.6fa48bcd41', 'toggle'),
- translate('auto.components.settings.voice.pane.search.064a9bd94a', 'hold'),
- translate('auto.components.settings.voice.pane.search.931b1a9e53', 'push to talk')
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.voice.pane.search.089d31a45b',
+ 'dictation'
+ ),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.d86f5600da', 'mode'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.6fa48bcd41', 'toggle'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.064a9bd94a', 'hold'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.voice.pane.search.931b1a9e53',
+ 'push to talk'
+ )
]
},
getOpenaiTranscriptionSearchEntry(),
@@ -65,14 +81,17 @@ export const getVoicePaneSearchEntries = createLocalizedCatalog(() => [
'Select a local or cloud speech-to-text model to use for dictation.'
),
keywords: [
- translate('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
- translate('auto.components.settings.voice.pane.search.080202facb', 'model'),
- translate('auto.components.settings.voice.pane.search.3d8b853963', 'speech'),
- translate('auto.components.settings.voice.pane.search.10d45a9fce', 'stt'),
- translate('auto.components.settings.voice.pane.search.b9dee49cd7', 'download'),
- translate('auto.components.settings.voice.pane.search.04c25a6fb0', 'openai'),
- translate('auto.components.settings.voice.pane.search.2d206de105', 'api key'),
- translate('auto.components.settings.voice.pane.search.f6e0dfa61c', 'cloud')
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.7640ed9848', 'voice'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.080202facb', 'model'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.3d8b853963', 'speech'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.10d45a9fce', 'stt'),
+ ...translateSearchKeyword(
+ 'auto.components.settings.voice.pane.search.b9dee49cd7',
+ 'download'
+ ),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.04c25a6fb0', 'openai'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.2d206de105', 'api key'),
+ ...translateSearchKeyword('auto.components.settings.voice.pane.search.f6e0dfa61c', 'cloud')
]
}
])
diff --git a/src/renderer/src/i18n/i18n.ts b/src/renderer/src/i18n/i18n.ts
index a63c5290021..63b96dca68a 100644
--- a/src/renderer/src/i18n/i18n.ts
+++ b/src/renderer/src/i18n/i18n.ts
@@ -2,6 +2,9 @@ import i18next, { type i18n as I18nInstance, type TOptions } from 'i18next'
import { initReactI18next } from 'react-i18next'
import en from './locales/en.json'
+import ja from './locales/ja.json'
+import ko from './locales/ko.json'
+import zh from './locales/zh.json'
import { isPseudoLocalizationLocale, pseudoLocalizeString } from './pseudo-localization'
import { DEFAULT_LOCALE, resolveUiLocale } from './supported-languages'
import type { UiLanguage } from '../../../shared/ui-language'
@@ -14,6 +17,15 @@ void i18n.use(initReactI18next).init({
resources: {
en: {
translation: en
+ },
+ zh: {
+ translation: zh
+ },
+ ko: {
+ translation: ko
+ },
+ ja: {
+ translation: ja
}
},
interpolation: {
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index e76ced64938..3d82c034bd5 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -13,7 +13,10 @@
"title": "Language",
"description": "Choose the language used by the Orca interface.",
"system": "System",
- "english": "English"
+ "english": "English",
+ "chinese": "中文(简体)",
+ "korean": "한국어",
+ "japanese": "日本語"
},
"statusBar": {
"claudeToggleDescription": "Show Claude token and cost usage for the active workspace.",
@@ -4572,7 +4575,11 @@
"f9af91ea26": "Shows the New Mobile Emulator action and allows agents to attach to the active emulator.",
"700ddbf9b1": "Enable Mobile Emulator",
"bc39d0f115": "Configure mobile emulator support for Orca and coding agents.",
- "6593c9ddd3": "Mobile Emulator"
+ "6593c9ddd3": "Mobile Emulator",
+ "a4f1c82d90": "Disabled",
+ "b5e2d93e01": "Checking...",
+ "c6f3ea4f12": "Ready",
+ "d704fb5023": "Needs setup"
},
"MobileNetworkInterfaceSection": {
"63d5e4ae1e": "Regenerate the QR code and scan it from the Orca mobile app.",
@@ -5732,7 +5739,45 @@
"cbdd7f3b9e": "Choose whether installed agents are detected on this device or in WSL.",
"ef804b7337": "Agent Location",
"01926b9d8c": "Configure AI coding agents, default agent, and command overrides.",
- "bb9ad95777": "Agents"
+ "bb9ad95777": "Agents",
+ "d8f3a8b8a0": "default",
+ "167daeb5e9": "command",
+ "be59907510": "override",
+ "a6d594c17d": "install",
+ "f2932bf22b": "detected",
+ "2afd3b5858": "enable",
+ "60393e1b17": "disable",
+ "2e188c771c": "hide",
+ "87fffe6c20": "show",
+ "e2b7c0dcd7": "github",
+ "66b6b82eb4": "awake",
+ "dbc8aca6b0": "sleep",
+ "845ad9128a": "power",
+ "48f84d10f1": "running",
+ "affbf130f6": "working",
+ "0d1c334987": "lid",
+ "ff8de8a2ad": "display",
+ "0d752916f8": "hooks",
+ "6984d4291a": "status",
+ "13b20636a6": "waiting",
+ "8599603496": "done",
+ "ea71995548": "remove",
+ "c1317fe641": "restore",
+ "5963143e00": "settings",
+ "042c551bc5": "config",
+ "f412abbba5": "claude",
+ "5ded38b843": "codex",
+ "be7ea3553b": "tab",
+ "6956646a1e": "title",
+ "32836788b0": "generated title",
+ "966890236d": "name",
+ "848dcae8d3": "generated",
+ "52115d0d7c": "auto",
+ "c64059f50d": "prompt",
+ "5784ae8c43": "rename",
+ "8a17fd6026": "stable",
+ "a79d266f71": "session",
+ "afbf35be68": "stable session"
}
},
"appearance": {
@@ -7081,6 +7126,19 @@
}
}
}
+ },
+ "agent-awake-copy": {
+ "e5995ce268": "Keep computer awake while agents are working",
+ "95d3031db2": "Keeps this computer and display awake while agents are working. Lid-close behavior follows this device's power settings.",
+ "a42f6fbdd8": "Keeps this computer and display awake while agents are working. Orca also asks this device to stay awake when the lid is closed, subject to its power policy."
+ },
+ "agent-status-hooks-copy": {
+ "7707c15abb": "Agent status hooks",
+ "a68a642835": "Shows working, waiting, and done states in Orca. Turn off to remove Orca-managed hooks and stop reinstalling them."
+ },
+ "agent-generated-tab-title-copy": {
+ "19ad21615a": "Auto-generate tab titles",
+ "b036c7a409": "Derive short stable tab names from the first known agent prompt. Manual renames always win."
}
},
"right": {
@@ -8476,7 +8534,9 @@
"5c9293e51a": "checking app access",
"aae94eeb52": "Click Install CLI & Skills",
"aa8e143a2f": "Could not check install",
- "9b33e7fb13": "Checking install"
+ "9b33e7fb13": "Checking install",
+ "4c8e1f92a7": "open Orca Desktop on this Mac",
+ "6d2b0a84e1": "Unavailable in this build"
}
}
}
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
new file mode 100644
index 00000000000..dfdae89d5a7
--- /dev/null
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -0,0 +1,9804 @@
+{
+ "app": {
+ "recoverableError": {
+ "rootTitle": "Orca でレンダラー エラーが発生しました。",
+ "rootDescription": "アプリ シェルはレンダリングを完了できませんでした。再マウントを再試行するか、エラーが解決しない場合は Orca を再起動してください。",
+ "webTitle": "Orca Web でレンダラー エラーが発生しました。",
+ "webDescription": "Web クライアントを再試行するか、ペアリングされたランタイムに再接続します。"
+ }
+ },
+ "settings": {
+ "appearance": {
+ "language": {
+ "title": "言語",
+ "description": "Orca インターフェイスで使用される言語を選択します。",
+ "system": "システム",
+ "english": "English",
+ "chinese": "中文(简体)",
+ "korean": "한국어",
+ "japanese": "日本語"
+ },
+ "statusBar": {
+ "claudeToggleDescription": "アクティブなワークスペースのClaude トークンとコストの使用状況を表示します。",
+ "codexToggleDescription": "アクティブなワークスペースの Codex トークンとコストの使用状況を表示します。",
+ "geminiToggleDescription": "アクティブなワークスペースの Gemini トークンとコストの使用状況を表示します。",
+ "opencodeGoToggleDescription": "アクティブなワークスペースの OpenCode Go トークンと使用コストを表示します。",
+ "kimiToggleDescription": "Kimi サブスクリプション",
+ "sshToggleDescription": "アクティブな SSH 接続を表示します。 SSH ターゲットが設定された場合にのみ表示されます。",
+ "resourceUsageToggleDescription": "リソースマネージャーを表示します。これをクリックすると、CPU、メモリ、セッション、デーモン コントロール、およびワークスペース ディスク スキャンが行われます。",
+ "portsToggleDescription": "ライブワークスペースポートを表示します。ワークスペーススコープのポートと外部リスナーの場合はこれをクリックします。"
+ }
+ }
+ },
+ "menu": {
+ "checkForUpdates": "アップデートを確認...",
+ "settings": "設定",
+ "exploreOrca": "Orca を探索",
+ "gettingStarted": "Orca を使い始める",
+ "reportCrash": "クラッシュを報告...",
+ "exportPdf": "PDF としてエクスポート...",
+ "file": "ファイル",
+ "exit": "終了",
+ "edit": "編集",
+ "appearance": "外観",
+ "toggleLeftSidebar": "左サイドバーの表示/非表示",
+ "toggleRightSidebar": "右サイドバーの表示/非表示",
+ "showStatusBar": "ステータスバーを表示",
+ "showTasksButton": "タスクボタンを表示",
+ "showAutomationsButton": "オートメーションボタンを表示",
+ "showMobileButton": "Orca モバイル ボタンを表示",
+ "showTitlebarAppName": "タイトルバーのアプリ名を表示",
+ "view": "表示",
+ "reload": "リロード",
+ "forceReload": "強制リロード",
+ "resetSize": "サイズをリセット",
+ "zoomIn": "ズームイン",
+ "zoomOut": "ズームアウト",
+ "openWorktreePalette": "ワークツリーパレットを開く",
+ "window": "ウィンドウ",
+ "help": "ヘルプ"
+ },
+ "worktreeJumpPalette": {
+ "matchLabel": {
+ "comment": "コメント",
+ "issue": "イシュー",
+ "port": "ポート",
+ "pr": "PR"
+ }
+ },
+ "auto": {
+ "App": {
+ "221a95ba38": "オンボーディングを再試行するか、オンボーディングを閉じてアプリで続行します。",
+ "f02d37278a": "オンボーディングでエラーが発生しました。",
+ "acd66311dc": "まだ診断が必要な場合は、再試行後に [ヘルプ] メニューを使用してください。",
+ "722d03aa62": "クラッシュレポートダイアログでエラーが発生しました。",
+ "8a023cea1f": "ステータス バーを再試行してコントロールを再マウントします。",
+ "2e8ff36f94": "ステータスバーにエラーが発生しました。",
+ "7cbfbf622f": "フローティング ワークスペースを再試行するか、閉じてから再度開きます。",
+ "1b3024bcd6": "フローティング ワークスペースでエラーが発生しました。",
+ "8d1e160ed1": "サイドバーを再試行するか、タブを切り替えてこのサーフェスを再読み込みしてください。",
+ "ed6b168d00": "右側のサイドバーでエラーが発生しました。",
+ "03a14f6b5b": "ページを再試行するか、別の Orca サーフェスに移動します。",
+ "b7a714db1e": "このページでエラーが発生しました。",
+ "98d4ea2823": "このワークスペースでは、ターミナル、ブラウザ、またはエディタのレンダリングに失敗しました。再マウントを再試行してください。",
+ "5a9519aef0": "ワークスペースワークベンチでエラーが発生しました。",
+ "cba0fafda5": "アクティブなページは開いたままになります。リストを再試行するか、ビューを切り替えます。",
+ "1468601e7b": "ワークスペース リストでエラーが発生しました。",
+ "bdc71dddc9": "アクティブなワークスペースは開いたままになります。リストを再試行するか、ビューを切り替えます。",
+ "c1cf0b0e4a": "ペインを折りたたむ",
+ "8504ddf267": "アプリはまだ実行中です。シェルを再試行するか、メニューを使用してクラッシュの詳細を報告します。",
+ "df1d56bf87": "ワークスペース シェルでエラーが発生しました。",
+ "9e0b441a91": "右サイドバーを切り替えます",
+ "e81217c1b7": "アプリ名を非表示",
+ "5096cbbc86": "Orca",
+ "8b0b8eb54f": "アプリケーションメニュー",
+ "caea5b51b9": "今すぐ再起動",
+ "0a9e810705": "変更は再起動するまで保存されません。以前のタブはディスク上に安全に保存されています。",
+ "12e77cf12b": "セッションの復元に失敗しました",
+ "332dbfa497": "ワークスペースがアップロードされました",
+ "e960d18540": "閉じる",
+ "c9d6f98459": "最大化",
+ "66f0a552e5": "復元",
+ "bbb7f90669": "最小化",
+ "d54e66004c": "ターミナル",
+ "9f0152563e": "モバイル",
+ "62ca9895a7": "スペース",
+ "844eb0f4f4": "アクティビティ",
+ "3443924e91": "自動化",
+ "4f08ae8311": "タスク",
+ "ca6c6eece7": "スキル",
+ "1b9d9d065f": "設定",
+ "c184e056de": "右サイドバーを切り替えます ({{value0}})",
+ "f7aa73e785": "進む ({{value0}})",
+ "cf9099fe98": "進む",
+ "fe21e8f6f5": "戻る ({{value0}})",
+ "064bd07810": "戻る",
+ "ce37cf5279": "サイドバーの切り替え ({{value0}})",
+ "e4b9e7dff7": "サイドバーの切り替え"
+ },
+ "web": {
+ "WebConnect": {
+ "b411ec0069": "接続",
+ "2cf9e5a294": "保存済みサーバーをクリア",
+ "4a4c017be1": "エンドポイント:",
+ "27393856e4": "orca://pair?code=...",
+ "7a566540de": "ペアリング URL またはコード",
+ "cb4d287238": "サーバー名",
+ "3affe7de3a": "このブラウザが到達できる Orca サーバーからペアリング URL を貼り付けます。",
+ "e3bcd082ac": "Orca に接続"
+ },
+ "web": {
+ "preload": {
+ "api": {
+ "31bfe8ae1a": "Web クライアントでは使用できません。",
+ "67ec964791": "Cookie のインポートは Web クライアントでは使用できません。",
+ "275a776357": "ホバー抽出は Web クライアントでは使用できません。",
+ "8dfcb7a351": "選択したスクリーンショットは Web クライアントでは使用できません。",
+ "31bea294d5": "グラブ モードは Web クライアントでは使用できません。",
+ "b8a1618172": "PRの詳細の生成は、Web クライアントでは使用できません。",
+ "e57c82d276": "コミット メッセージ モデルの検出は、Web クライアントでは使用できません。",
+ "9fc90740b6": "コミット メッセージの生成は、Web クライアントでは使用できません。",
+ "52bee9d8a0": "競合するカスタム ショートカットは無視されました: {{value0}}。",
+ "32f15bdb0f": "不明なプラットフォーム「{{value0}}」は無視されました。",
+ "0a69fcd8bc": "プラットフォームは、darwin、linux、または win32 セクションを持つオブジェクトである必要があります。",
+ "10898045f3": "「{{value0}}」のショートカットは無視されました: 文字列配列を使用してください。",
+ "36761d9604": "不明なキーバインド 操作「{{value0}}」は無視されました。",
+ "d2e43e426a": "{{value0}} はオブジェクトでなければなりません。",
+ "fb290366b2": "ウェブでは利用できません。"
+ }
+ },
+ "runtime": {
+ "environment": {
+ "07f788de83": "ウェブソケット"
+ }
+ }
+ }
+ },
+ "store": {
+ "slices": {
+ "browser": {
+ "d175274b6d": "新規ブラウザタブ",
+ "08fc23631d": "ブラウザ"
+ },
+ "editor": {
+ "dcb521ed29": "このファイルは競合状態にありますが、編集できる作業ツリー ファイルがありません。",
+ "51f15c37d3": "ディレクトリを開けません: {{value0}}",
+ "f2e00db373": "ファイルが見つかりません: {{value0}}"
+ },
+ "github": {
+ "f129c42773": "GitHub は新規コメントを返しませんでした。",
+ "683a21264b": "行には所有者/リポジトリ/番号がありません。",
+ "83f9b126ad": "イシュータイプはイシューにのみ設定できます。",
+ "f963485d37": "行が見つかりません",
+ "a967f23983": "プロジェクトビューがロードされていません",
+ "87020f6605": "行には所有者/リポジトリ/番号がありません - 基になるアイテムにパッチを適用できません",
+ "d49ef4b944": "イシューソースの設定を保存できませんでした"
+ },
+ "sparse": {
+ "presets": {
+ "ef13e994e6": "プリセットは保存する前にロードする必要があります。",
+ "6ed7d6010a": "プリセットの削除に失敗しました",
+ "ee434d7941": "プリセットが削除されました",
+ "c96b770172": "プリセットの保存に失敗しました",
+ "811be06b57": "プリセットの更新に失敗しました",
+ "0696d13e56": "プリセットが保存されました",
+ "e10f097822": "プリセットが更新されました"
+ }
+ },
+ "store": {
+ "test": {
+ "helpers": {
+ "b9a8117c33": "ターミナル 1"
+ }
+ }
+ },
+ "workspace": {
+ "cleanup": {
+ "9d6e531da6": "ワークスペースはもう存在しません。"
+ }
+ },
+ "worktrees": {
+ "5a58e03a26": "「{{value0}}」を削除しました。",
+ "d1d78a7baa": "Git はブランチ \"{{value0}}\"{{value1}} を安全に削除できなかったため、Orca はローカル コミットの損失を避けるためにブランチを保持しました。",
+ "4e6496f3d2": "{{value0}} は削除され、ブランチは保持されます",
+ "e50495aae6": "ブランチを強制削除",
+ "889487d8bb": "閉じる",
+ "f4503ca505": "[設定] > [Git] を開いて、もう一度試す。",
+ "34a03a6565": "{{value0}} を最新の状態に保つ",
+ "fa9299a66f": "新規ワークツリーは最新ですが、ローカル {{value0}} は {{value1}} {{value2}} 遅れています。 AI の差分では最近のコミットが失われる可能性があります。",
+ "14bc053a47": "ローカル {{value0}} は更新されませんでした",
+ "4a18052018": "ローカル {{value0}} は {{value1}} の後ろにあります",
+ "903b51c2ed": "ワークスペースは {{value0}} から作成されましたが、{{value2}} のため Orca はローカル {{value1}} を早送りできませんでした",
+ "0216895fb5": "ブランチの削除に失敗しました",
+ "19db0085fb": "ローカルブランチが削除されました",
+ "2b0afc7f14": "ローカル {{value0}} を最新の状態に維持できませんでした",
+ "670864ab52": "ローカル {{value0}} を最新の状態に保つ"
+ },
+ "repos": {
+ "b7e14472ae": "フォルダーの追加に失敗しました",
+ "e649269645": "サーバー パスを使用して、リモート ランタイムからプロジェクトを追加します。",
+ "c6e022ddfc": "プロジェクトの追加に失敗しました",
+ "90d129b48b": "フォルダーが追加されました",
+ "8bb3ad7935": "プロジェクトを追加しました",
+ "a8e4b3af5b": "プロジェクトはすでに追加されています",
+ "6d3318e813": "リポジトリのインポートに失敗しました"
+ },
+ "settings": {
+ "e12dab333b": "サーバーの切り替えに失敗しました",
+ "faa8fb83dd": "サーバーを切り替える前に、未保存のエディター タブを保存するか閉じてください。"
+ },
+ "ui": {
+ "66e3bd7ce6": "{{value0}} に送信されました",
+ "53883b7bc3": "{{value0}} に送信できませんでした"
+ }
+ }
+ },
+ "lib": {
+ "agent": {
+ "catalog": {
+ "5dff448636": "OpenClaw",
+ "8a9ba743cc": "Hermes",
+ "4e63c7b956": "Rovo Dev",
+ "bee242fe3d": "Qwen Code",
+ "ca73055bd0": "Mistral Vibe",
+ "28810273af": "Kimi",
+ "739a930554": "Droid",
+ "667c104cff": "Cursor",
+ "9e2a9bb87b": "Continue",
+ "6f8056a565": "Command Code",
+ "4238b771b5": "Codebuff",
+ "cbaf0c2e0b": "Cline",
+ "1f8a19e9ad": "Autohand Code",
+ "5e8eff11b3": "Auggie",
+ "9477377a2a": "Charm",
+ "e0247254f2": "Kiro",
+ "918ba4ffed": "Kilocode",
+ "c73c573939": "Amp",
+ "8da11d876c": "Goose",
+ "b32627f09b": "Aider",
+ "691dd11789": "Antigravity",
+ "12e6baa4f7": "Gemini",
+ "09973b4d84": "OMP",
+ "302934c5d9": "Pi",
+ "e7a4ca5103": "OpenCode",
+ "706b0fe68b": "GitHub Copilot",
+ "0baad2d5d2": "Grok",
+ "760bc6883d": "Codex",
+ "a5fc0cb622": "OpenClaude",
+ "bf53f09bf8": "Claude Agent Teams",
+ "0708ed89f1": "Claude"
+ },
+ "skill": {
+ "cli": {
+ "prerequisite": {
+ "79371593b0": "Orca CLI はまだ PATH に表示されません",
+ "e99d7dc36f": "Orca CLI 登録には注意が必要です",
+ "2db0bd7515": "Orca CLI 登録は利用できません",
+ "8d6eedf97e": "Orca CLI を PATH に登録できませんでした。",
+ "0f116999f1": "セットアップ前にシェルを再起動するか、Orca CLI ディレクトリを PATH に追加します。",
+ "15cbedc3e3": "エージェント スキル セットアップを実行する前に、Orca CLI をインストールします。"
+ }
+ }
+ }
+ },
+ "ensure": {
+ "simulator": {
+ "tab": {
+ "372d21d428": "モバイルエミュレータ"
+ }
+ }
+ },
+ "fix": {
+ "checks": {
+ "agent": {
+ "launch": {
+ "027228a06b": "これらのチェックのためのワークスペースが見つかりません。",
+ "fb6c294e85": "エージェント起動コマンドを構築できませんでした。",
+ "03c1d61f83": "これらのチェックに関連付けられたワークスペースを開けません。",
+ "822bf52295": "ワークスペース起動プラットフォームを解決できません。",
+ "dfb4dd7c00": "これらのチェックに関連付けられたワークスペースが見つかりません。",
+ "9f00d7df0c": "チェック プロンプトが空です。ソース管理 AI 設定を更新してください。",
+ "2ebf794906": "このワークスペース ホストでは有効な AI エージェントが検出されませんでした。",
+ "4c7f783a7a": "保存されたチェック エージェントは、このワークスペース ホストでは使用できません。"
+ }
+ }
+ }
+ },
+ "floating": {
+ "workspace": {
+ "tab": {
+ "creation": {
+ "f3785eddc2": "新規ブラウザタブ"
+ }
+ }
+ }
+ },
+ "launch": {
+ "agent": {
+ "in": {
+ "new": {
+ "tab": {
+ "11cce5cc77": "新規ターミナルで {{value0}} を起動できませんでした。",
+ "a5a1f7033f": "{{value0}} は送信されませんでした。エージェントの準備ができたら、それを貼り付けてください。"
+ }
+ }
+ },
+ "background": {
+ "session": {
+ "4ca0651d56": "自動化プロンプトは送信されませんでした。ワークスペースを開いて貼り付けてください。"
+ }
+ }
+ },
+ "work": {
+ "item": {
+ "direct": {
+ "3de6371df3": "エージェント起動コマンドを構築できませんでした。",
+ "67e103dd60": "ワークスペースは作成されましたが、アクティブ化できませんでした。",
+ "19c7683acf": "選択したエージェントは、作成されたワークスペースでは使用できません。",
+ "8bc45efdbc": "PR ヘッドを解決できませんでした。",
+ "agent": {
+ "ceeeb509b5": "エージェントの起動に時間がかかりすぎました。ワークスペースの準備ができました。エージェントがアイドル状態のときに {{value0}} を貼り付けます。"
+ }
+ }
+ }
+ }
+ },
+ "local": {
+ "path": {
+ "open": {
+ "guard": {
+ "edc1908653": "ローカル OS でリモート パスを開くことはできません。"
+ }
+ }
+ }
+ },
+ "open": {
+ "in": {
+ "app": {
+ "catalog": {
+ "f8b8ca2711": "Zed",
+ "d62b12e98a": "Cursor",
+ "173553f73a": "VS Code"
+ }
+ }
+ }
+ },
+ "orchestration": {
+ "usage": {
+ "examples": {
+ "f91fe27f2a": "大きな変更を小さな PR に分割する",
+ "9e37a5b1b3": "独立した作業を並行して実行する",
+ "bddc4c09b8": "段階的なワークフローを実行する",
+ "ab0e9803b7": "別のワークツリーにハンドオフ",
+ "5e0d489fe1": "アクティブなタスクを引き渡す"
+ }
+ }
+ },
+ "pr": {
+ "comment": {
+ "audience": {
+ "64deee36a9": "ボット",
+ "a7150a17bc": "人間",
+ "27ce73211c": "全て",
+ "empty": {
+ "bot": "ボットのコメントはありません。",
+ "human": "人間的なコメントはありません。",
+ "all": "コメントはまだありません。"
+ }
+ }
+ }
+ },
+ "resume": {
+ "sleeping": {
+ "agent": {
+ "session": {
+ "f235f604fd": "このエージェント セッションは再開できません。"
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "agent": {
+ "action": {
+ "plan": {
+ "3f0ea9aa0d": "エージェント起動コマンドを構築できませんでした。",
+ "46f1a2c9bd": "コマンド入力が空です。",
+ "8eb541cc83": "選択したエージェントはこのワークスペース ホストで検出されませんでした。",
+ "b96e091fc9": "選択したエージェントは設定で無効になっています。",
+ "a7ac8717c7": "開始する前にエージェントを選択。"
+ }
+ }
+ },
+ "generation": {
+ "plan": {
+ "dc480d5897": "コマンド入力が空です。"
+ }
+ }
+ }
+ },
+ "sparse": {
+ "preset": {
+ "draft": {
+ "5915a0a1f6": "ルート、絶対パス、親セグメントではなく、リポジトリ相対ディレクトリを使用してください。",
+ "efc05d1820": "少なくとも 1 つのディレクトリを追加します。"
+ }
+ }
+ },
+ "terminal": {
+ "shortcut": {
+ "capture": {
+ "notification": {
+ "b0536028c9": "ショートカットを開く",
+ "141ad6c004": "ターミナルショートカットの処理",
+ "0ab0cd001a": "サイズ 4 テキストミュート前景"
+ }
+ }
+ }
+ },
+ "workspace": {
+ "create": {
+ "error": {
+ "format": {
+ "37cf0bc991": "Orca は、このワークスペースの使用可能な基本参照を解決できませんでした。",
+ "64555d0014": "ベースブランチが見つかりません"
+ }
+ }
+ }
+ },
+ "worktree": {
+ "palette": {
+ "search": {
+ "9ccec2316b": "イシュー",
+ "ca40ffcbec": "PR",
+ "0b01ff98d2": "ポート",
+ "7d732521ec": "コメント"
+ }
+ }
+ }
+ },
+ "hooks": {
+ "useAutomationDispatchEvents": {
+ "59718b120b": "ターゲット ワークスペースは使用できなくなりました。",
+ "16a21d6413": "SSH の再接続には対話型の認証情報が必要です。",
+ "386db94f3e": "対象のプロジェクトは利用できなくなりました。"
+ },
+ "useComposerState": {
+ "7eb3f44ff7": "選択したエージェントは無効になっています。作成する前に、有効なエージェントを選択。",
+ "b2ead86962": "PR ベースを解決できませんでした。",
+ "a9ff236145": "一部の添付ファイルをアップロードできませんでした。",
+ "3db83fc58a": "添付ファイルに使用できるリモート プロジェクト パスがありません。",
+ "ba6cb77082": "プロジェクトへの接続に失敗しました。"
+ },
+ "useGlobalFileDrop": {
+ "38c9f034ff": "ドロップされたファイルのアップロードに失敗しました。",
+ "d720e2f855": "ドロップされた一部のファイルはアップロードできませんでした。",
+ "245faa95b9": "ドロップされたファイルに使用できるリモート ワークスペース パスがありません。"
+ },
+ "useIpcEvents": {
+ "0e3cf53060": "ブラウザタブ {{value0}} が見つかりません",
+ "a8d2bf8e9e": "閉じるためのアクティブなブラウザ タブがありません",
+ "291c8ed902": "リモート ランタイムがアクティブな間はブラウザ タブは使用できません",
+ "f45fa2b03c": "リモート ランタイムがアクティブな間はブラウザ プロファイルを使用できません",
+ "f000b2ff76": "アクティブなワークツリーがありません",
+ "56d3ec4203": "無題のマークダウン ファイルの作成に失敗しました。",
+ "f6300deb8b": "新規ブラウザタブ",
+ "7a64b31991": "リモート ランタイムがアクティブな間は、ローカルターミナルの作成は利用できません",
+ "60428567b4": "リモート ランタイムがアクティブな間はローカルターミナルの公開は利用できません",
+ "f8aaf2bde3": "ワークスペースがアップロードされました",
+ "2fe88c2e06": "リモートワークスペースの同期は利用できません",
+ "2ec42e1c52": "リモートワークスペースはまだありません",
+ "88214a785b": "ワークスペースの同期はローカル セッションのハイドレーションを待機し、タイムアウトになりました",
+ "4f78ba5885": "ワークスペースが同期されました"
+ },
+ "useSettingsNavigationMetadata": {
+ "4a728cd56b": "まだ形になりつつある新機能。試してみてください。",
+ "225071c560": "実験的機能",
+ "e338c507c1": "トラブルシューティングのための低レベルの互換性設定。",
+ "580a04cd81": "詳細設定",
+ "8400cfe1c1": "匿名の使用状況データとテレメトリ制御。",
+ "3618579df6": "プライバシーとテレメトリ",
+ "65ec7d1968": "ターミナルで起動される開発者ツールの macOS プライバシー アクセス。",
+ "d91ae31fbd": "macOS のアクセス許可",
+ "95a1886d94": "スマートフォンからターミナルとエージェントを操作",
+ "1cd25673df": "モバイル",
+ "31e57d1c70": "ファイル、ターミナル、git 用のリモート SSH ホスト。",
+ "94a5afe910": "SSHホスト",
+ "40d80bad8a": "ベータ",
+ "de0c2907a1": "リモート Orca サーバー",
+ "b351014180": "Orca の統計と Claude、Codex、OpenCode の使用状況分析。",
+ "d72a58b5b9": "統計と使用状況",
+ "dcd0d9b74f": "よく使う操作のキーボード ショートカット。",
+ "94295ebfb3": "ショートカット",
+ "7682607591": "エージェントおよびターミナルイベントのネイティブ デスクトップ通知。",
+ "2eece16ad1": "通知",
+ "1f452cbd4c": "選択と編集の動作。",
+ "0c6ee88a5f": "入力と編集",
+ "b11a5a48a2": "テーマ、ズーム、アプリとターミナルの外観、サイドバー、ステータス バー。",
+ "93d88d20bf": "外観",
+ "2d0659f6f0": "グローバルターミナル、ブラウザ、およびマークダウンタブ。",
+ "65b19f5bde": "フローティングワークスペース",
+ "3d65d3f1b9": "Orca およびコーディング エージェントのモバイル エミュレーターのサポートを構成します。",
+ "1e761cff2b": "モバイルエミュレータ",
+ "e815fd01bd": "ホーム ページ、リンク ルーティング、およびセッション Cookie。",
+ "8c197f74a1": "ブラウザ",
+ "42ae40842f": "グローバルまたはプロジェクトごとにスコープ設定された、保存されたターミナル コマンド。",
+ "3fc3db144f": "クイックコマンド",
+ "c33bfd664c": "シェル、レンダラ、セッション、およびターミナルの動作。",
+ "a9fb10afca": "ターミナル",
+ "5235c215ca": "「タスク」ページとサイドバーに表示するタスクプロバイダーを選択します。",
+ "85f4fd7710": "タスクソース",
+ "ab4b21b58e": "ブランチの名前、基本参照、帰属、および Git AI 作成者。",
+ "09607cb0fe": "Git とソース管理",
+ "33a5e1d597": "GitHub、GitLab、Linear、およびソース ホスティング サービスを接続します。",
+ "2b043783ef": "連携",
+ "2cd4ea75da": "ワークスペースのデフォルト、アプリのセットアップ、メンテナンス。",
+ "13241992bd": "一般",
+ "724c440e72": "はじめる",
+ "0505d0df29": "Orcaを始めましょう",
+ "ea0b1bc7b8": "セットアップガイド",
+ "17005c73d4": "セットアップとマイルストーンの手順については、オンボーディング チェックリストを開いてください。",
+ "ded9e9032f": "オンボーディングチェックリスト",
+ "5f32ac08f3": "コア Orca ワークフローのオンボーディング チェックリストを完了します。",
+ "8ac3de82f5": "オンデバイスモデルを使用したローカルの音声からテキストへのディクテーション。",
+ "6a50cdcd7c": "音声",
+ "0059bd17f3": "エージェントがコンピュータ上の任意のアプリを制御できるようにします。",
+ "b35e92364b": "コンピュータ操作",
+ "cd50cec5d7": "Orca を通じて複数のコーディング エージェントを調整します。",
+ "58a868e8e4": "オーケストレーション",
+ "7c79d3b7bf": "任意",
+ "b1c2f8b0ac": "Claude、Codex、Gemini、OpenCode Go のオプションのアカウント切り替え。",
+ "f70ac54d38": "AI プロバイダー アカウント",
+ "4121f7a0a2": "AI エージェントを管理し、デフォルトを設定し、コマンドをカスタマイズします。",
+ "b49abbd2f7": "エージェント"
+ }
+ },
+ "components": {
+ "CodexRestartChip": {
+ "9132779820": "閉じる",
+ "c72a5fb234": "再起動",
+ "9263e75f49": "Codex は前のアカウントを使用しています"
+ },
+ "FirstLaunchBanner": {
+ "b9e1b966c7": "通知を閉じる",
+ "94cc673726": "了解",
+ "fc5cc29955": "オプトアウト",
+ "d1deebb050": "プライバシーポリシー",
+ "958d2cc31b": "使用している機能を匿名でカウントすることは、何を構築するかを優先するのに役立ちます。ファイルの内容、プロンプト、ターミナル出力など、あなたを特定するものは何もありません。 [設定] -> [プライバシーとテレメトリ]でいつでも変更できます。",
+ "9784b4d7bc": "次に何を構築するかを決定するのにご協力ください",
+ "fcbee32f08": "テレメトリ通知"
+ },
+ "GitHubItemDialog": {
+ "3ab6ac0fc8": "選択した GitHub イシューまたは PR をプレビュー・編集します。",
+ "3cd5ae5b7b": "ファイルは変更されませんでした。",
+ "999b5ad7d9": "ファイル",
+ "4bd1f5b055": "チェック",
+ "e30a5470c9": "会話",
+ "474c59b4b3": "閉じる・Esc",
+ "45af57999b": "プレビューを閉じる",
+ "3fdf777817": "GitHub で開く",
+ "c43fe79ee0": "GitHub リンクをコピーする",
+ "0caac1a18f": "PR からワークスペースを開始する",
+ "8223320f8d": "更新されました",
+ "10ef1afb8e": "· 更新されました",
+ "55962099bc": "このイシューを作成しました",
+ "0ab4664a8b": "イシューからワークスペースを開始",
+ "36182aa57f": "新規ワークスペースを開始する",
+ "fe6ff12dc2": "イシューワークスペースのその他の操作",
+ "726db41722": "ワークスペースを開く",
+ "84855fedd0": "イシューに添付されたワークスペースを開く",
+ "b7bf31b8de": "表示された状態を GitHub と同期できませんでした。",
+ "c0253318d6": "このPRの表示状態を同期できません。",
+ "5fea151559": "GitHub リンクのコピーに失敗しました",
+ "2e77dc2053": "GitHub リンクがコピーされました",
+ "2ef631437e": "このイシューに関連付けられたワークスペースを開けません。",
+ "bf43425540": "コメント",
+ "0a73f59e85": "コメントを送信",
+ "c5c117270e": "コメントを追加…",
+ "082515176a": "コメントの追加に失敗しました",
+ "c6f37a563d": "+ 担当者",
+ "f41ec96c13": "+ ラベル",
+ "ab050dffec": "クローズ",
+ "dc1ca081a8": "オープン",
+ "2e4d806c92": "ワークスペース",
+ "886a64b081": "まだありません",
+ "4ba0132f37": "ラベルを編集する",
+ "217e55d87c": "ラベル",
+ "c67de9e2fe": "誰も割り当てられていません",
+ "76adcf5fe2": "担当者の編集",
+ "83ac703dda": "担当者",
+ "00ccdf9b5a": "状態",
+ "2aa9acdf34": "GitHub でラベルを編集する",
+ "d23bbb6416": "{{value0}} はスキップされました",
+ "18f80e1329": "{{value0}} 保留中",
+ "b1ac991806": "{{value0}} は失敗しました",
+ "311d0cee55": "{{value0}} 通過",
+ "e52bed9264": "まだチェックは報告されていません",
+ "90020cc1f3": "このPRにはまだチェックが報告されていません。",
+ "ecffebc251": "チェックが見つかりませんでした",
+ "5dddefdf58": "GitHub で開く",
+ "744197c84d": "このチェックではインライン出力は使用できません。",
+ "08d072664d": "求人",
+ "96d8f36798": "注釈",
+ "485609c4f2": "チェック #",
+ "0f478f5efa": "完了",
+ "4812814bc8": "開始しました",
+ "9c3ba11a05": "状態:",
+ "934d87ab96": "チェックの詳細を読み込んでいます…",
+ "71c11aff84": "すべてのチェックを再実行します",
+ "e31651a224": "失敗したチェックを再実行する",
+ "1b56e28faa": "再実行",
+ "f4b1292569": "これらのチェックでデフォルトの AI エージェントを開始します",
+ "9a1004fc76": "リフレッシュチェック",
+ "03e542fcfe": "失敗したチェックのため AI エージェントを開始できませんでした: {{value0}}",
+ "28986b3747": "失敗したチェックに対して AI エージェントを開始しました。",
+ "1690fd7f4a": "修正が必要な失敗したチェックはありません",
+ "9e7c221b8d": "チェックの再実行に失敗しました",
+ "e463ec935f": "リクエストされた再実行をチェックする",
+ "ddafe851e1": "チェックの再実行が要求されました",
+ "0bbdc673c1": "チェックの更新に失敗しました",
+ "e7007aa1d8": "リポジトリ パスがないとチェックを更新できません。",
+ "675bc0d638": "キャンセル",
+ "a18f669c7a": "{{value0}} {{value1}} 反応{{value2}}",
+ "53fe19aefc": "GitHub マージ ボックスを開く",
+ "a2495e4784": "PR",
+ "ce360fc318": "自動マージを無効にできませんでした",
+ "825a8fb8cd": "自動マージを有効にできませんでした",
+ "4b390bd50d": "自動マージが無効になっています",
+ "a35ea5a0f6": "自動マージが有効になっています",
+ "aba792c8b3": "PRのマージに失敗しました",
+ "dbe5e2448e": "PR がマージされました",
+ "a27ee5ca1a": "これにより、GitHub 上のPRが更新されます。",
+ "03d7216d62": "{{value0}} PR #{{value1}}?",
+ "e9b7cb7d17": "{{value0}} PR に失敗しました",
+ "bd3b4492a0": "PR が再オープンされました",
+ "9f88657c4e": "PR がクローズされました",
+ "b6f1b7adbd": "これにより、GitHub でPRが再開されます。",
+ "de45fedf7b": "これにより、GitHub 上のPRが閉じられます。",
+ "5a94f3d0e9": "コメントはまだありません。",
+ "1506916c09": "コメント",
+ "9b9cb55994": "説明はありません。",
+ "52b20b56f7": "説明",
+ "4d555d3796": "説明の編集",
+ "9df4e74bdf": "保存",
+ "0ae387d8ca": "による",
+ "228e2f59d3": "解決済み",
+ "a154ec5224": "GitHub でコメントを開く",
+ "bca8eb39ac": "コメントに返信",
+ "68cb993d61": "解決済み",
+ "10f4ff5be8": "返信が投稿されました。",
+ "745c9089ec": "リポジトリ パスがないと返信できません。",
+ "58c73cb0d8": "説明の更新に失敗しました。",
+ "5221548274": "説明が更新されました。",
+ "06c06e58ba": "以下の行をさらに表示",
+ "307c98e8e3": "上に {{value0}} 行をさらに表示",
+ "5664681624": "上の行をさらに表示",
+ "b1574e8ac2": "コードコンテキストをリセットする",
+ "d43736d09c": "コードコンテキストコントロール",
+ "bd7be7b1fd": "コメントL",
+ "db61d76cd5": "コードコンテキストを読み込み中…",
+ "f2d02cdf8c": "閲覧したファイル",
+ "1257d1435d": "ファイルツリーを表示",
+ "a341343303": "レビューコメントを追加しました。",
+ "d1fa2cf888": "PR ヘッドの SHA がないとコメントできません。",
+ "829674460a": "PR コミット SHA が欠落しているため、差分は利用できません。",
+ "af924014f8": "閲覧済み",
+ "2d89a38d9d": "{{value0}} {{value1}} 表示",
+ "70e84e3d0b": "一致するレビュアーがいません。",
+ "1ffce94a8b": "他のみんな",
+ "c2b21818e1": "提案",
+ "a98433e73d": "読み込み中...",
+ "b0b7344684": "最大 15 人のレビュアーをリクエストする",
+ "934add88b6": "レビュアー",
+ "bb42774171": "ユーザーを入力または選択します",
+ "36f9ac4a47": "レビュアーはリクエストされていません。",
+ "8b15a5e91c": "レビュアー {{value0}} を削除",
+ "6a45771d47": "レビュアーの読み込み中",
+ "dc8a092c57": "レビュアー",
+ "e3243d9376": "最近これらのファイルを編集しました",
+ "8c45901789": "レビュアーをリクエスト {{value0}}",
+ "fedc09eeb9": "レビュアーのリクエストを取り消す {{value0}}",
+ "73487fb975": "レビュアーを削除できませんでした",
+ "2e69540652": "レビュアーが削除されました",
+ "69515bff81": "レビュアーが削除されました",
+ "b4af16bf43": "このPRに使用できるリポジトリ コンテキストがありません。",
+ "c42d942b75": "レビュアーのリクエストに失敗しました",
+ "c016e4bac3": "レビュアーからのリクエスト",
+ "ea985e657f": "レビュアーがリクエストしました",
+ "12e761610e": "最大 15 人のレビュアーをリクエストできます",
+ "94ab23a9f9": "レビュアーを入力",
+ "3853476a97": "GitHub アイテム",
+ "68796dafa0": "PR",
+ "b1157c78ff": "シート",
+ "038b3d39b1": "コピーされました",
+ "04539beb48": "イシュー",
+ "773ff70035": "未知",
+ "3e544d966d": "イシュー",
+ "88fd82474d": "ページ",
+ "e517b4d641": "閉まっている",
+ "d0a05e73f5": "コンパクト",
+ "7d42606f66": "注釈",
+ "2511f44bb7": "失敗したチェックを修正",
+ "9157d48ddb": "修正チェック",
+ "06482d6190": "修正ワークスペースを自動的に作成できません。",
+ "f64dd90102": "返事",
+ "5752c25aff": "投稿中…",
+ "ec5c4b3ab2": "PR再開",
+ "21860b58d0": "PRを閉じる",
+ "5932578f51": "マージには登録済みのローカル リポジトリが必要です",
+ "ce8a85d209": "デフォルト",
+ "924c2fe05e": "破壊的な",
+ "e2bf3e41a9": "コメント",
+ "28d0d3374f": "糸",
+ "080d071d48": "@{{value0}} に返信",
+ "86f809e2ce": "このレビュー スレッドに返信する",
+ "136542c9ba": ":L{{value0}}",
+ "283699bc82": "返信の投稿に失敗しました。",
+ "d1c0dad471": "-L{{value0}}",
+ "31770bef03": "サイドバイサイド",
+ "6e43a16435": "インライン",
+ "d00a0a7f8f": "すべて折りたたむ",
+ "3c19ec3069": "すべて展開",
+ "b0b09778c8": "レビューコメントの追加に失敗しました。",
+ "16c1abe76c": "閲覧済みとしてマークする",
+ "ba8e329d92": "閲覧済みのマークを外す",
+ "3f79ffc8b7": "PR の詳細を開いて、現在のレビュアーを表示します。"
+ },
+ "GitLabItemDialog": {
+ "65e784c1f1": "再度開く",
+ "a199eb364b": "閉じる",
+ "16b3412570": "マージ",
+ "131865e231": "ワークスペースの作成",
+ "f2e64d1c20": "GitLab で開く",
+ "84012fa8fb": "コメント",
+ "c08e1d5a57": "{{value0}}{{value1}} にコメントしてください…",
+ "f11e3e7675": "この MR ではパイプラインは実行されません。",
+ "808b1ca1ba": "変更されたファイルはありません。",
+ "007423f585": "差分コンテンツは利用できません。",
+ "a7eb4f4916": "から",
+ "21f8dde18a": "インラインコメント",
+ "7a7204417f": "ライン",
+ "ceb08a733d": "ファイル",
+ "85a8170279": "コメントはまだありません。",
+ "14423484db": "説明はありません。",
+ "da4174b00f": "編集",
+ "93f79a3fc1": "保存",
+ "f72fad3b16": "キャンセル",
+ "717b706849": "ラベルをロードしています",
+ "3c0b6ccca7": "バグ、バックエンド",
+ "dde24ade55": "ラベル",
+ "908d8d2a73": "説明",
+ "89f3f19368": "タイトル",
+ "7a2117129a": "追加",
+ "05939e977d": "レビュアーを追加",
+ "474b50d988": "レビュアーはいません。",
+ "1b19cdc510": "レビュアー {{value0}} を削除",
+ "cb55b0390f": "管理",
+ "4f9313984d": "レビュアー",
+ "02cbe2de44": "パイプライン",
+ "be3d291837": "ファイル",
+ "c996e2962c": "会話",
+ "b3c156dd51": "更新",
+ "9bfb4a24d7": "による",
+ "30c97083c2": "GitLab 作業項目の詳細",
+ "e089f62594": "MR をマージしました !{{value0}}",
+ "865ea2703e": "MR を再開しました !{{value0}}",
+ "9b11cd233f": "MR を終了しました !{{value0}}",
+ "60c13320c4": "インラインコメントが追加されました",
+ "ffdd9a78e1": "MR diff ref はインライン コメントでは使用できません。",
+ "00d0d25825": "ファイル、行、コメントは必須です。",
+ "ceaf7c30c7": "この GitLab ユーザーはレビュアー ID を利用できません。",
+ "f7cb495a12": "{{value0}}を再試行しました",
+ "98718490e4": "MR タイトルは必須です。",
+ "d600c2619a": "ログの読み込み中",
+ "028bde664e": "隠れる",
+ "2f9b27f838": "ジョブログ",
+ "032ae1312b": "GitLab で求人を開く",
+ "fa3e042203": "再試行",
+ "f23ea85341": "解決済み",
+ "4186685c78": "再開する",
+ "cae2712a23": "閉じる",
+ "881e522e04": "マージ",
+ "6de8ce0cc6": "{{value0}}は必須です",
+ "22511537d2": "承認された",
+ "00f3bab87b": "{{value0}} 個が必要です",
+ "11384f99aa": "番号",
+ "40c56b95e2": "{{value0}} 承認{{value1}} 残り",
+ "3a051b8ade": "作業項目",
+ "32f8bef818": "ログは出力されません。",
+ "4168eb2c51": "解決"
+ },
+ "JiraIssueWorkspace": {
+ "b0b92666c9": "コメント",
+ "a585fd204e": "Jira コメントを追加...",
+ "2441be6f9f": "ワークスペースの開始",
+ "9178090e26": "コメントはまだありません。",
+ "5cd09beaf9": "再試行",
+ "9a980b06b9": "コメント",
+ "c4889a47e4": "説明はありません。",
+ "0f3c07a901": "バックエンド、バグ",
+ "aee97b6913": "ラベル",
+ "444865b4a8": "タイトル",
+ "0b6b5646ed": "未割り当て",
+ "51bed73f88": "優先順位なし",
+ "7a96985ca0": "閉じる",
+ "76513c7898": "Jira イシューのプレビューを閉じる",
+ "857bd2f88f": "選択したイシューをプレビュー・編集し、そこから作業を開始します。",
+ "0cc62bd690": "プロンプトのコピー",
+ "80efa101c5": "提案されたブランチ名をコピーします",
+ "38839801e8": "キーをコピーする",
+ "779bb91ee0": "URLをコピー",
+ "69da9a208c": "Jira で開く",
+ "fa132c8aed": "コメントの追加に失敗しました。",
+ "ea21952aa3": "Jira イシューを更新できませんでした。",
+ "6c41a9bcea": "{{value0}} のコピーに失敗しました",
+ "2ff69a3545": "{{value0}} がコピーされました",
+ "666cfdd835": "未知",
+ "9ebee71962": "ラベル",
+ "def3d0e824": "タイトル",
+ "b8e2079d96": "担当者",
+ "54649eaeab": "+ 担当者",
+ "2a829a2f00": "優先度",
+ "693be070d0": "遷移",
+ "ef21405c6d": "Jira イシュー"
+ },
+ "Landing": {
+ "76a95f7f47": "作成",
+ "f05d237049": "まずプロジェクトを追加",
+ "f9eaa9e12d": "プロジェクトを追加",
+ "6ca6ff404e": "ORCA",
+ "520304a067": "Orcaのロゴ",
+ "ce44fad849": "依存関係が欠落している",
+ "c1cf168479": "隠れる",
+ "00cee697c1": "ターミナルで「gh auth login」を実行して、GitHub アカウントに接続します。",
+ "9f96d018b7": "GitHub CLI が認証されていません",
+ "73e1ad4282": "Orca は、GitHub CLI (gh) を使用して、PR、イシュー、チェックを表示します。",
+ "5beaef5f9e": "GitHub CLIがインストールされていません",
+ "b673e7cf1b": "Git は、Git プロジェクト、ソース管理、およびワークスペース管理に必要です。",
+ "e5b7296d9d": "Gitがインストールされていない",
+ "cd21242762": "プロジェクトを追加して開始します。",
+ "9c00bd4adf": "開始するには、サイドバーからワークスペースを選択します。",
+ "16e9e3df89": "星付き",
+ "0d0ace8861": "GitHub でスターを付ける",
+ "ec43b38ba7": "GitHub でスターを獲得"
+ },
+ "LinearIssueMarkdownDescriptionEditor": {
+ "d9c47069ef": "マークダウン",
+ "a7301a11f3": "保存",
+ "632096eb1c": "リンク",
+ "340160f4e8": "リンクを削除する",
+ "9eaf02ac01": "引用",
+ "e2a0267c8c": "チェックリスト",
+ "d6b2f3d35b": "番号付きリスト",
+ "c82917e06e": "箇条書きリスト",
+ "ad1869bd54": "インラインコード",
+ "28fd951b83": "ストライク",
+ "5666b4493d": "イタリック",
+ "caa88f50d0": "大胆な",
+ "dddaa7a0a6": "見出し2",
+ "e3f741d258": "見出し1",
+ "68a41d5665": "本文",
+ "7c52151156": "イシューの説明の形式",
+ "5c16ec8f14": "リンクURL",
+ "4f2fddc2b7": "説明はありません。"
+ },
+ "LinearIssueTextEditor": {
+ "947ba2d6f4": "保存する",
+ "04d73b72dc": "号名",
+ "e8ff595db3": "{{value0}} を更新できませんでした",
+ "1e08a1ec80": "タイトルは必須です",
+ "00fa439dc7": "タイトル",
+ "75294b07d1": "説明"
+ },
+ "LinearIssueWorkspace": {
+ "ad5dec37b7": "選択したイシューをプレビュー・編集し、そこから作業を開始します。",
+ "c23e79e5c0": "操作",
+ "b0eac92d85": "再試行",
+ "fabbd3f974": "イシューを更新しました ·",
+ "543970c87a": "アクティビティ",
+ "df4c86ed12": "閉じる",
+ "7a4997d8bb": "Linear イシューのプレビューを閉じる",
+ "e1e0a9bca9": "ワークスペースの開始",
+ "30a7f56c0a": "イシューからワークスペースを開始",
+ "30c1242f3a": "識別子のコピー",
+ "9e3c49beb8": "イシュー識別子のコピー",
+ "9a9a884236": "URLをコピー",
+ "97c19a84f1": "Linear URL をコピー",
+ "f63ef94ea8": "イシュー",
+ "f6c6381593": "プロンプトのコピー",
+ "5d670ec8dc": "提案されたブランチ名をコピーします",
+ "937ba6ad9a": "プロジェクトをロードしています",
+ "db3f269d98": "プロジェクトを検索する",
+ "b51276c8d6": "プロジェクト",
+ "8b5b593053": "プロジェクトの更新に失敗しました",
+ "f9d4ef9807": "プロジェクトが更新されました",
+ "38b80780c2": "プロジェクトのロードに失敗しました",
+ "42589845bc": "作成",
+ "c182e02de5": "サブ号のタイトル",
+ "8c55d6696a": "サブイシューを追加する",
+ "b25e453c9d": "サブイシューの作成に失敗しました",
+ "aeed19d003": "{{value0}} を作成しました",
+ "9a1317cdd3": "サブイシューのロードに失敗しました",
+ "9bcbaa2737": "{{value0}} のコピーに失敗しました",
+ "7835483c43": "{{value0}} がコピーされました",
+ "61f424f8ca": "Linear イシュー",
+ "ca8778c124": "未知",
+ "8a33c85e9c": "誰か",
+ "f5a6b38a14": "シート",
+ "65239a714b": "Linear",
+ "af6e02c44a": "ページ",
+ "76ffd3c937": "追加するプロジェクトを検索します。",
+ "c11b4e3cc2": "プロジェクトが見つかりませんでした。",
+ "519c3587f3": "プロジェクトに追加"
+ },
+ "LinearItemDrawer": {
+ "04008e6c46": "イシューからワークスペースを開始",
+ "a4fcc57522": "コメントはまだありません。",
+ "fde849b2b6": "コメント",
+ "9dc54172db": "閉じる・Esc",
+ "0190b760c1": "Linearで開く",
+ "04a442f796": "選択したLinear イシューをプレビューして編集します。",
+ "d369841269": "コメントを送信",
+ "2fcff829a8": "コメントを追加…",
+ "2820f0f0f0": "コメントを残してください...",
+ "6ab35eafd5": "コメントの追加に失敗しました",
+ "367f828482": "ラベルが見つかりません",
+ "cddd9b04a7": "ラベルをロードしています",
+ "23886c7eec": "ラベルを追加",
+ "7f7b89b631": "ラベル: {{value0}}",
+ "b2376d0179": "メンバーをロード中",
+ "866316f22c": "未割り当て",
+ "b5675b0694": "保存",
+ "ceeb8c6153": "クリア",
+ "fbb90300e2": "カスタム見積り",
+ "780ea6ed89": "州が見つかりません",
+ "59b6cd3706": "ロード状態",
+ "64bfffc4dd": "ラベル",
+ "dd304de85a": "プロパティ",
+ "0be31fef8e": "推定値は負でない整数でなければなりません",
+ "48e17e8cbd": "未知",
+ "858d0630da": "プレビューを閉じる",
+ "39883467f4": "Linear イシュー",
+ "fda549766e": "コメントするには{{value0}}",
+ "d71cd3003e": "+ 担当者"
+ },
+ "NewWorkspaceComposerCard": {
+ "cbb47ee0dc": "ローカル Git プロジェクトでのみ使用できます。",
+ "d861de981b": "まばらなチェックアウト",
+ "090cfedeb4": "メモを書く",
+ "f8728aa4f9": "注記",
+ "0ee17638fe": "ワークスペース名",
+ "2688050e4b": "名前",
+ "f0470c7383": "詳細設定",
+ "ba64270bdb": "エージェントを構成する",
+ "ab63f25397": "エージェント設定を開く",
+ "01d1e8f601": "エージェント",
+ "0c5d6a479c": "[オプション]",
+ "b5a0796911": "接続",
+ "dccd26d4e4": "プロジェクトを選択",
+ "d6b0a96f32": "プロジェクトの追加",
+ "969a8bff66": "プロジェクト",
+ "23bb365554": "orca.yaml",
+ "a239038146": "SSH接続エラー",
+ "9a70e4859e": "このワークスペースを作成する前にセットアップを実行するかどうかを選択します。",
+ "803b7fe72f": "セットアップ構成を確認しています...",
+ "92e34f0311": "ローカル設定",
+ "326a578923": "orca.yaml + ローカル",
+ "2132b670da": "両方",
+ "0e587e31fb": "ヤムル",
+ "ac3748dcda": "名前または「作成元」",
+ "f660aa1454": "接続中",
+ "7711ad5122": "ローカルセットアップコマンド",
+ "e5db1b0419": "組み合わせセットアップコマンド",
+ "addProjectBeforeWorkspace": "ワークスペースを作成する前にプロジェクトを追加します。"
+ },
+ "NewWorkspaceComposerModal": {
+ "fa90f739a5": "ワークスペースを作成する前に、プロジェクト、ワークスペース名、およびエージェントを選択します。"
+ },
+ "PullRequestPage": {
+ "2560588245": "レビュアーのリクエストに失敗しました",
+ "3450247584": "コメント",
+ "6ad2c1ab9c": "ファイルは変更されませんでした。",
+ "4d18310d55": "ファイルが変更されました",
+ "94d95cf1f7": "チェック",
+ "9e8d45700e": "会話",
+ "e6996f4024": "· 更新されました",
+ "00b7b82329": "ヘッドブランチ",
+ "e1f3641bfd": "から",
+ "c44b70352b": "ベースブランチ",
+ "b0e80f083d": "に合併したい",
+ "8ecda455a0": "GitHub で開く",
+ "1a2570e18e": "新規ワークスペースを開始する",
+ "57c13a5aa4": "PR ワークスペースのその他の操作",
+ "25690a3855": "PR からワークスペースを開始する",
+ "a459866967": "PR に紐づくワークスペースを再開",
+ "347034903a": "GitHub リンクをコピーする",
+ "5a01ca7253": "表示された状態を GitHub と同期できませんでした。",
+ "996a1897d2": "このPRの表示状態を同期できません。",
+ "e0b15c793f": "GitHub リンクのコピーに失敗しました",
+ "992e799227": "GitHub リンクがコピーされました",
+ "61bfc81ada": "このPRに添付されたワークスペースを開けません。",
+ "161d91ef02": "コメントを送信",
+ "d2030fc8cd": "コメントを追加…",
+ "1208347ac0": "コメントの追加に失敗しました",
+ "61452f2143": "イシューからワークスペースを開始",
+ "14c9fc70ed": "+ 担当者",
+ "bc215fea4d": "+ ラベル",
+ "b936cc51a4": "クローズ",
+ "7b8f6bf6d8": "オープン",
+ "e6ad0a8d06": "{{value0}} はスキップされました",
+ "88267924d5": "{{value0}} 保留中",
+ "ae2a34c7b8": "{{value0}} は失敗しました",
+ "7c5035931a": "{{value0}} 通過",
+ "a18d01cda3": "まだチェックは報告されていません",
+ "3912daf310": "このPRにはまだチェックが報告されていません。",
+ "45877f5089": "チェックが見つかりませんでした",
+ "85e62c5266": "失敗したチェックに対して AI エージェントを開始しました。",
+ "ddfd42f460": "エージェントを選択し、起動前に完全なコマンド入力を編集します。",
+ "a053bdd082": "AI で失敗したチェックを修正する",
+ "1b14d0a69c": "GitHub で開く",
+ "1550675e5f": "このチェックではインライン出力は使用できません。",
+ "7720c9c3f5": "求人",
+ "8432d17901": "注釈",
+ "f01bf79a79": "チェック #",
+ "000f90afcf": "完了",
+ "76551b1161": "開始しました",
+ "662bc2998d": "状態:",
+ "d8e82b7f15": "チェックの詳細を読み込んでいます…",
+ "54cddd1858": "すべてのチェックを再実行します",
+ "68605516dd": "失敗したチェックを再実行する",
+ "522d9353e1": "再実行",
+ "0fa8b8faec": "これらのチェックでデフォルトの AI エージェントを開始します",
+ "5d0f42766d": "リフレッシュチェック",
+ "98583589c6": "失敗したチェックのため AI エージェントを開始できませんでした: {{value0}}",
+ "51c65c0265": "修正が必要な失敗したチェックはありません",
+ "788a782bb0": "チェックの再実行に失敗しました",
+ "18f2af42ac": "リクエストされた再実行をチェックする",
+ "5963a6a852": "チェックの再実行が要求されました",
+ "246b2c6456": "チェックの更新に失敗しました",
+ "c057f2fcb0": "リポジトリ パスがないとチェックを更新できません。",
+ "6591b1fa82": "キャンセル",
+ "42c36d9166": "{{value0}} {{value1}} 反応{{value2}}",
+ "7df8d5fc60": "GitHub マージ ボックスを開く",
+ "1939d0f663": "PR",
+ "973ef2fac9": "自動マージを無効にできませんでした",
+ "d31f4b508c": "自動マージを有効にできませんでした",
+ "0f5821b035": "自動マージが無効になっています",
+ "5edbe7eefa": "自動マージが有効になっています",
+ "aae645d36d": "PRのマージに失敗しました",
+ "c57873d721": "PR がマージされました",
+ "a63b3c159c": "これにより、GitHub 上のPRが更新されます。",
+ "eec3706a6a": "{{value0}} PR #{{value1}}?",
+ "b8c6cbb8c4": "{{value0}} PR に失敗しました",
+ "710e47aa06": "PR が再オープンされました",
+ "7aa3b5f706": "PR がクローズされました",
+ "3d77438c92": "これにより、GitHub でPRが再開されます。",
+ "5a65651096": "これにより、GitHub 上のPRが閉じられます。",
+ "d2d589556c": "コメントはまだありません。",
+ "3463d10a63": "コメント",
+ "c8ea6c7c4c": "説明はありません。",
+ "778683ec84": "説明",
+ "da9aaa8bcf": "説明の編集",
+ "4a337ac05f": "保存",
+ "169a93b29a": "更新されました",
+ "3c891789f6": "による",
+ "f4fe47c2bb": "解決済み",
+ "0ac19bb52e": "GitHub でコメントを開く",
+ "d6c6679de7": "コメントに返信",
+ "76b2a0ac5b": "解決済み",
+ "11505c7a71": "返信が投稿されました。",
+ "6885c619e7": "リポジトリ パスがないと返信できません。",
+ "d94810f652": "説明の更新に失敗しました。",
+ "9b4190dc98": "説明が更新されました。",
+ "51ed0cf38b": "以下の行をさらに表示",
+ "e295a78c11": "上に {{value0}} 行をさらに表示",
+ "c9de94b07a": "上の行をさらに表示",
+ "5f3e293517": "コードコンテキストをリセットする",
+ "85d119be40": "コードコンテキストコントロール",
+ "791ddede19": "コメントL",
+ "4b960e5978": "コードコンテキストを読み込み中…",
+ "89e80af1c7": "閲覧したファイル",
+ "319cf2d54b": "ファイルツリーを表示",
+ "eff839f438": "レビューコメント追加しました。",
+ "d8c3ba91c4": "PR ヘッドの SHA がないとコメントできません。",
+ "74660bd80b": "PR コミット SHA が欠落しているため、差分は利用できません。",
+ "2e528e1c2d": "閲覧済み",
+ "ff84e1f54c": "{{value0}} {{value1}} 表示",
+ "5ad00c7a0e": "一致するレビュアーがいません。",
+ "2760fa29a4": "他のみんな",
+ "828f045847": "提案",
+ "57750f4a8c": "読み込み中...",
+ "805cb72cd4": "最大 15 人のレビュアーをリクエストする",
+ "a04c137bb7": "レビュアー",
+ "3bde131f49": "ユーザーを入力または選択します",
+ "d10b6d5209": "レビュアーはリクエストされていません。",
+ "ae9a38fd4a": "レビュアー {{value0}} を削除",
+ "acbd110867": "レビュアーの読み込み中",
+ "00d3be6bcd": "レビュアー",
+ "f4a4b3fd9f": "最近これらのファイルを編集しました",
+ "41d275d3ec": "レビュアーをリクエスト {{value0}}",
+ "36b514a457": "レビュアーのリクエストを取り消す {{value0}}",
+ "c798fa0ec7": "レビュアーを削除できませんでした",
+ "1e6d089420": "レビュアーが削除されました",
+ "2c1d93da43": "レビュアーが削除されました",
+ "1ae11c905c": "このPRに使用できるリポジトリ コンテキストがありません。",
+ "102d3d177f": "レビュアーからのリクエスト",
+ "03282ff3b9": "レビュアーがリクエストしました",
+ "8f369a6b6b": "最大 15 人のレビュアーをリクエストできます",
+ "dace0d1a9f": "レビュアーを入力",
+ "77d9388fb0": "未知",
+ "c9e7094a7b": "ワークスペースを再開",
+ "3b6886b2ee": "コピーされました",
+ "b6bda618cf": "コンパクト",
+ "35a0573f41": "注釈",
+ "61a8c69a33": "ページ",
+ "a4541fd3db": "失敗したチェックを修正",
+ "c808db1dd1": "修正チェック",
+ "c4c02ea23e": "修正ワークスペースを自動的に作成できません。",
+ "f119e5f5ef": "返事",
+ "894cfd884b": "投稿中…",
+ "9d5425918e": "PR再開",
+ "96d013ed28": "PRを閉じる",
+ "d65f70786e": "閉まっている",
+ "eca289e593": "マージには登録済みのローカル リポジトリが必要です",
+ "6568ae8ece": "デフォルト",
+ "19f19560d5": "破壊的な",
+ "aae99c6c04": "PR",
+ "e01e34f5fa": "コメント",
+ "345b68254c": "糸",
+ "31a7b202f2": "@{{value0}} に返信",
+ "408e634fbb": "このレビュー スレッドに返信する",
+ "34b9f7c264": ":L{{value0}}",
+ "5821aab360": "返信の投稿に失敗しました。",
+ "84fc40769a": "-L{{value0}}",
+ "1378d79e83": "サイドバイサイド",
+ "e5f4a24f78": "インライン",
+ "dd94111c18": "すべて折りたたむ",
+ "eb722a5a8c": "すべて展開",
+ "19628e058d": "レビューコメントの追加に失敗しました。",
+ "50b8fb290f": "閲覧済みとしてマークする",
+ "2b4fdb880c": "閲覧済みのマークを外す",
+ "56ec6eafb7": "PR の詳細を開いて、現在のレビュアーを表示します。"
+ },
+ "QuickOpen": {
+ "1dbd3f59ff": "動く",
+ "73b2c581f1": "閉じる",
+ "95fccbae88": "ESC",
+ "61b1c871a6": "オープン",
+ "250e5b2dfb": "入力",
+ "74e2e1b3e4": "一致するファイルはありません。",
+ "722a21e1a8": "ファイルをロード中...",
+ "1cb6ef47b7": "ファイルに移動...",
+ "9e97f08d0f": "開くファイルを検索する",
+ "ec31e058f7": "ファイルに移動",
+ "73b44e7bde": "インストールコマンドのコピー",
+ "1cf8561ab4": "リモートで、gitignore 対応の高速リストを有効にします。",
+ "5d80dc39bb": "リップレップ",
+ "2ca749c15d": "インストール",
+ "4725b0e931": "クイック オープン スキャンが大きすぎます (",
+ "b227d88520": "{{value0}} ファイルが見つかりました",
+ "995be8ea22": "コピー",
+ "cf144856dc": "コピーされました"
+ },
+ "SelectedTextCopyMenu": {
+ "9b40d7b018": "コピー"
+ },
+ "StarNagCard": {
+ "92b0f9d921": "認証されているので、再試行してください。",
+ "cd8c34aac1": "gh",
+ "cf82170065": "リポジトリにスターを付けることができませんでした。確認する",
+ "30c36231c1": "Orca のおかげで時間を節約できたなら、GitHub のスターは大いに役立ちます。これは、他の開発者がプロジェクトを発見するのに役立ち、チームの改善を出荷する意欲を維持します。",
+ "b5e685e4d9": "閉じる",
+ "5f6df21046": "Orcaを楽しんでいますか?",
+ "2d67b6c849": "GitHub でスターを付ける",
+ "af3c9bbb37": "主演…"
+ },
+ "TaskPage": {
+ "513cddfa7a": "確認中…",
+ "ff69a30681": "キャンセル",
+ "2abe22ef76": "トークンは OS キーチェーンを介して暗号化され、ローカルに保存されます。",
+ "246c2b3dd3": "アトラシアンのアカウント設定",
+ "59c14d34a2": "でトークンを作成します",
+ "b95623e93f": "アトラシアン API トークン",
+ "68df347677": "you@example.com",
+ "163df31e0e": "https://example.atlassian.net",
+ "33fc2bcb30": "Jira Cloud サイト URL、Atlassian メール、API トークンを使用してイシューを参照します。",
+ "60f806ce99": "Jira サイトに接続する",
+ "8ff6fdc368": "作成…",
+ "fc0d8a1fa4": "提出する。",
+ "919a20dd5b": "{{value0}}と入力",
+ "56cdb413a2": "カンマ区切りの値",
+ "1f0fce91e3": "{{value0}} を選択",
+ "cbcdcbe244": "必要な Jira フィールドを読み込み中…",
+ "34d97ca682": "どうしたの?",
+ "f161bf9ede": "説明 (オプション)",
+ "578f730c16": "短い要約",
+ "16cba35bee": "タイトル",
+ "ae592fee62": "イシューの種類",
+ "7d63e2626e": "読み込み中...",
+ "93c57f15e5": "プロジェクトが見つかりませんでした。",
+ "cfb56a7868": "プロジェクトを検索...",
+ "00022ec0ba": "プロジェクト",
+ "0c11ca0b6d": "新規 Jira イシュー",
+ "d0ca4aa1d0": "ラベル",
+ "1742eafc14": "プロジェクトがありません",
+ "69591944e7": "低い",
+ "7fd59c18d8": "中くらい",
+ "345b169f1f": "高い",
+ "f373ab1a4f": "緊急",
+ "713179dfdc": "優先順位なし",
+ "c8d5bec5f7": "優先度",
+ "42a9160321": "未割り当て",
+ "d2a876ca53": "担当者",
+ "154b0fa623": "状態",
+ "9bc8aea407": "説明を追加...",
+ "d9151fd4e9": "号名",
+ "4f3cb99f41": "チームを切り替える",
+ "c11105dac5": "新刊",
+ "1b59a07674": "作成...",
+ "cf72580c04": "説明を書いたり、プロジェクトの概要を書いたり、アイデアを集めたり...",
+ "2ea1c701b6": "対象日",
+ "7da41c9225": "ターゲット",
+ "09623359b9": "開始日",
+ "7d08e8be0f": "始める",
+ "af9e877f30": "ラベルなし",
+ "d6cda23ef1": "メンバー",
+ "cfaadb6b22": "リードなし",
+ "34da8ac06c": "鉛",
+ "579f98afcd": "短い要約を追加...",
+ "ecbcc83140": "プロジェクト名",
+ "b6795e65fd": "閉じる",
+ "a98cbe7664": "チーム",
+ "02f67c0d09": "新規プロジェクト",
+ "bdebffcbfe": "選択したチームのLinear プロジェクトを作成します。",
+ "1361275ec3": "新規Linearプロジェクト",
+ "7f3f7b4c18": "説明 (オプション、マークダウン)",
+ "9f2b4c03a6": "提出する",
+ "d3d0998b7d": "GitHub の新規イシュー",
+ "d1e243795c": "イシュー",
+ "be8cf68d9f": "イシューを表示",
+ "67662ade50": "プロジェクトのイシュー",
+ "6244a02f46": "Linearで開く",
+ "606a85c774": "オープン",
+ "5e8061b088": "{{value0}} {{value1}} からワークスペースを開始します",
+ "592a55611b": "さらにチームを選択するか更新してみてください。チーム フィルターは、現在取得されているイシューセットに適用されます。",
+ "618107fab3": "選択したチームと一致する取得済みイシューはありません",
+ "903c7af49f": "Linear イシューが見つかりません",
+ "5ed38a49e5": "以下のワークスペース エラーを確認し、更新してください。",
+ "cc8795e07c": "Linear イシューを読み込めません",
+ "f362667d55": "更新されました",
+ "b1eaa18ace": "イシュー",
+ "37e7ee311e": "鍵",
+ "b7bae28b6a": "示されている",
+ "a26a48252e": "表示プロパティ",
+ "5d2d835467": "注文",
+ "5659da12fc": "グループ化",
+ "9c57663908": "表示",
+ "af377b13b1": "{{value0}} ビュー",
+ "d47248df4d": "Linearビューモード",
+ "f397d513e3": "戻る",
+ "b39fe6511d": "プロジェクト",
+ "8675cd6188": "Linear",
+ "733b8f2421": "Linear / ビュー",
+ "bc06ed0fb0": "ビューに戻る",
+ "3cb855080f": "ビュー",
+ "b4e10f096e": "所有者",
+ "a04fe7ba73": "可視性",
+ "0aa8525950": "モデル",
+ "dfc0c79bd8": "イシュー",
+ "8a07f21e76": "健康",
+ "851017590d": "Linearアクセスを追加",
+ "228b25028f": "ここから直接、割り当てられたLinear イシューを参照して作業を開始できます。",
+ "6d56559467": "Linear アカウントを接続する",
+ "eee68073b2": "Jira で開く",
+ "9497f2787c": "ワークスペースの開始",
+ "eba87f2edb": "Jira イシューが見つかりません",
+ "63b2abd3aa": "Jira イシュー",
+ "e7115334aa": "Jira を非表示",
+ "83bce6be5c": "Jira に接続する",
+ "b518ae6307": "ここから直接、Jira イシューを参照、編集、作成し、作業を開始できます。",
+ "a150c59da7": "Jira サイトに接続する",
+ "bcdc1330b2": "GitLab で開く",
+ "00b7ffb952": "タイプ / 状態",
+ "eb10c32872": "ID",
+ "e9b6955dcd": "イシュー #{{value0}}",
+ "a0544fb653": "ミスター!{{value0}}",
+ "8396825a14": "操作",
+ "c1d1600362": "ブラウザで開く",
+ "b6329379ca": "新規ワークスペースを開始する",
+ "054bf695cc": "下書き",
+ "285bc21dc5": "クエリを変更するかクリアします。",
+ "d0e3c8f933": "一致する GitHub 作業がありません",
+ "5b6b2af943": "再試行中…",
+ "0c0de0fc0e": "からのイシューを読み込めませんでした",
+ "d1766fd62d": "プロジェクトのロードに失敗しました",
+ "7762f4b03a": "の",
+ "443f7dd928": "マージ",
+ "a7396b05c6": "チェック",
+ "f6fa3c97d0": "レビュアー",
+ "8aba10579d": "担当者",
+ "5eccb3c841": "タイトル/コンテキスト",
+ "d4c2830063": "GitLab 作業項目を更新する",
+ "c679af7ad9": "Todo を更新する",
+ "dfd72673e7": "プロジェクトの選択を保存できませんでした。",
+ "b797bdd7c3": "検索をクリア",
+ "99c2755218": "Jira JQL、例:プロジェクト = ABC AND statusCategory != 完了",
+ "2ff9fd71fd": "Jira イシューを更新する",
+ "0b65d3fb2c": "Linear プロジェクトを検索...",
+ "eec0c5c079": "Linear イシューを検索...",
+ "8964184a8b": "Linear を更新",
+ "3feb524d42": "新規 Linear イシュー",
+ "0cbf7e5cf3": "Linearタスクモード",
+ "ff53631e6f": "GitHub の作業を更新する",
+ "6ffa6be99f": "GitHub の作業を更新しています",
+ "b15ceb409d": "GitHub イシューを検索...",
+ "eee4df4c66": "GitHub PR を検索...",
+ "e592d99051": "すべての Jira サイト",
+ "d09b7631b7": "Jira サイトの切り替えに失敗しました。",
+ "8029e2bd4d": "Linear で開く Linear チームを 1 つ選択",
+ "609532fae7": "デフォルトのタスクソースを保存できませんでした。",
+ "4826fd1ad8": "閉じる・Esc",
+ "1a06219d5c": "タスクを閉じる",
+ "3f594861a5": "チーム選択を保存できませんでした。",
+ "d0d570b306": "Linearワークスペースの切り替えに失敗しました。",
+ "cb98f0350c": "{{value0}} を作成しました",
+ "1e1b2ad8f2": "このイシューを登録する前に、プロジェクトワークスペースからチームを選択してください。",
+ "3ca9b424a3": "プロジェクトの作成に失敗しました。",
+ "3f9604efc7": "解決済みのイシュー #{{value0}}",
+ "585dba2989": "このイシューに関連付けられたワークスペースを開けません。",
+ "534a9c6017": "このPRに添付されたワークスペースを開けません。",
+ "fe380f306c": "デフォルトのタスクビューを保存できませんでした。",
+ "af2a8371de": "Jira イシュータイプをロードできませんでした。",
+ "6775c05483": "Linear の状態を更新できません",
+ "745ae567d4": "「{{value0}}」は {{value1}} では使用できません",
+ "669e419d65": "Linear ビューにワークスペース コンテキストがありません。",
+ "cba2a2b7fb": "Linear プロジェクトにワークスペース コンテキストがありません。",
+ "f4374519ae": "優先するイシューソース (アップストリーム) は {{value0}} 用に構成されなくなりました。原点を使用します。",
+ "e9139db03f": "{{value0}} を非表示にできませんでした。",
+ "b73717af92": "次へ",
+ "0c8df28045": "次のページ",
+ "ae859c816b": "ページ{{value0}}",
+ "cd171f3391": "...",
+ "297a805b64": "前の",
+ "6cd6b3ae6a": "前のページへ",
+ "e65757a338": "ページネーション",
+ "37d60046e3": "GitHub マージ ボックスを開く",
+ "1a9ea003dc": "自動マージを無効にできませんでした",
+ "a3318684bc": "自動マージを有効にできませんでした",
+ "a5bf86defe": "自動マージが無効になっています",
+ "fed317634c": "自動マージが有効になっています",
+ "88f478cdef": "PRのマージに失敗しました",
+ "a161925adc": "PR がマージされました",
+ "0506a78337": "これにより、GitHub 上のPRが更新されます。",
+ "844dc193c7": "{{value0}} PR #{{value1}}?",
+ "995dd6af9b": "PR チェックを開く",
+ "8a22eb3f7b": "一致するレビュアーがいません。",
+ "67755a83a1": "他のみんな",
+ "3ace2e6bcf": "提案",
+ "0eacf48491": "読み込み中…",
+ "0b9b04f4b5": "ユーザーを入力または選択します",
+ "62c7bd789f": "最大 15 人のレビュアーをリクエストする",
+ "5d4fd69a6a": "このPRで最近アクティブになった",
+ "ed1daeb49a": "レビュアーを削除できませんでした",
+ "837bb901ec": "レビュアーが削除されました",
+ "f9191d1714": "レビュアーが削除されました",
+ "dc67f69962": "レビュアーのリクエストに失敗しました",
+ "8f06dbb9e5": "レビュアーがリクエストしました",
+ "969e26577c": "最大 15 人のレビュアーをリクエストできます",
+ "d00571d9b1": "レビュアーを入力",
+ "edf4bc4135": "割り当て可能なユーザーがいません。",
+ "53e002d895": "イシューにはリポジトリのスラッグがありません。",
+ "7f94eb6395": "イシューの割り当て",
+ "bb63046423": "{{value0}} に割り当てられました",
+ "ca63694b4c": "担当者の更新に失敗しました。",
+ "b36f4bf9de": "ラベルはありません。",
+ "5ebff3a0aa": "なし",
+ "d09bf34db7": "クローズ",
+ "1c893195ac": "状態の更新に失敗しました",
+ "afc68824ff": "州が見つかりません",
+ "cc13109b5d": "ロード状態",
+ "d45a910c4a": "Linear状態を {{value0}} から変更します",
+ "d8a517ad89": "識別子",
+ "50387522d7": "グループ化なし",
+ "d747aed72f": "ボード",
+ "a6f7e93d7f": "リスト",
+ "e78ec261ed": "ビュー",
+ "727069bee5": "プロジェクト",
+ "137e2a8a01": "PR",
+ "18451e99df": "完了",
+ "4b6e40e42c": "すべてオープン",
+ "bd9965df51": "報告済み",
+ "1301d376f1": "割り当て済み",
+ "9cd11ba218": "Jira",
+ "11a828abf8": "GitLab",
+ "acef77f7ca": "GitHub",
+ "524f095d55": "レビュー待ち",
+ "7698af5263": "私の",
+ "94f0339621": "私に割り当てられました",
+ "c2268a9982": "全て",
+ "37a82eaaf8": "合併しました",
+ "887efe9140": "接続",
+ "a70153f583": "接続する",
+ "6459faa8b3": "エラー",
+ "e15ba2d2eb": "イシューの作成",
+ "3b11c8e8fc": "配列",
+ "e178c0a953": "イシューを作成する前に Jira プロジェクトを選択します。",
+ "0f7b0d964a": "{{value0}} で新規イシューを作成します。",
+ "eff9800d4b": "{{value0}} ラベル{{value1}}",
+ "d7f16d0e32": "チームを選択",
+ "5301ca0f20": "プロジェクトの作成",
+ "7719d8daa9": "{{value0}} メンバー{{value1}}",
+ "5af6f0ae5b": "チームを選択",
+ "cfb730b73e": "イシュー",
+ "3659f9792a": "ボード",
+ "d079be2dc8": "割り当てられたイシューはありません。検索してみてください。",
+ "2bdefbcac3": "別の検索クエリを試す。",
+ "25ff84769a": "この Linear コンテキストに一致するイシューはありません。",
+ "cbce2bc9cd": "なし",
+ "51411113df": "リスト",
+ "60f68a2ef4": "Linear イシュー",
+ "b2007ba885": "プロジェクト",
+ "6edf402e11": "概要",
+ "9ae151b26b": "Linear",
+ "94d900518d": "選択したプリセットに一致するイシューはありません。",
+ "f51e254d35": "別の JQL クエリを試す。",
+ "4645a7814f": "Jira",
+ "e224d76876": "MR",
+ "bbec4717ee": "MR",
+ "d6d08c1650": "プロジェクトを選択して、GitLab の作業項目を表示します。",
+ "f294c500ef": "このフィルターに一致する GitLab 作業はありません。",
+ "cd7dc432a3": "このフィルターに一致する GitLab MR はありません。",
+ "171b7739d8": "夫人",
+ "a9f256ecea": "このフィルターに一致する GitLab イシューはありません。",
+ "2007e14d95": "gitlab",
+ "456b8512da": "MR",
+ "03da966159": "GitLab に対して認証できるようにプロジェクトを選択します。",
+ "d591aac6ae": "保留中の ToDo はありません。皆さんももう追いつきました!",
+ "33a4bd7f5c": "やるべきこと",
+ "66ae7330f6": "その他の操作",
+ "93d5f21fc1": "PR",
+ "e104fa3d3d": "イシューからワークスペースを開始",
+ "2193a99ec1": "イシューに添付されたワークスペースを開く",
+ "7deb9e59a5": "その他の PR 操作",
+ "7753652524": "再開する",
+ "e4b29c5bcf": "PR からワークスペースを開始する",
+ "67d881244c": "PR に紐づくワークスペースを再開",
+ "6430594b18": "作者不明",
+ "7799ad9ab6": "下書き",
+ "0bfbf62f75": "再試行",
+ "38139edb52": "github",
+ "31f81cc334": "GitHub の作業を更新しています…",
+ "3d93316bb0": "PRs",
+ "937b29fa35": "アイテム",
+ "bc46d8204e": "GitHub で開くプロジェクトを 1 つ選択",
+ "d1132848f8": "GitHub で開く GitHub プロジェクトを 1 つ選択",
+ "2af3ab5c58": "Linear で開くチームを 1 つ選択",
+ "aec5feeb69": "Jira イシューの作成に失敗しました。",
+ "7437e340b4": "イシューの作成に失敗しました。",
+ "9e03c17847": "PR の詳細を開いて、現在のレビュアーを表示します。",
+ "3b7f34282f": "閉まっている"
+ },
+ "Terminal": {
+ "73768427cf": "閉じる",
+ "f82e9f02df": "キャンセル",
+ "7958465754": "プロセスが実行されているローカルターミナルがあります。とにかく窓を閉めますか?",
+ "2fa9c69ff3": "ウィンドウを閉じますか?",
+ "cd51e28d8b": "保存",
+ "0037b21794": "保存しないでください",
+ "21295c6b8c": "未保存の変更",
+ "5c1d2a32bb": "エディターを読み込み中...",
+ "f0600556b3": "無題のマークダウン ファイルの作成に失敗しました。",
+ "37da0d736f": "新規ブラウザタブ",
+ "a2a279b32a": "保存がタイムアウトしたか失敗しました。閉じる前にエラーを修正してください。",
+ "46e08bc5c8": "このファイルには保存されていない変更が含まれています。",
+ "61ed600d29": "「{{value0}}」には未保存の変更があります。閉じる前に保存しますか?",
+ "cdc9ac4b2d": "エディタ"
+ },
+ "TerminalSearch": {
+ "db234b7519": "閉じる",
+ "7cb40c04eb": "次の試合",
+ "0f3066256e": "前回の試合",
+ "42e466b9f1": "正規表現",
+ "90c61387d9": "大文字と小文字を区別",
+ "e07012f26e": "検索..."
+ },
+ "UpdateCard": {
+ "68b235d264": "再起動してアップデートする",
+ "02d4b8a6b9": "ダウンロードされます。準備ができたら再起動します。",
+ "93794ea932": "Orca v{{value0}} をダウンロードしています。",
+ "8acbdd3961": "ステータスバーに最小化する",
+ "17412483da": "インストール可能",
+ "47126bcf57": "手動でダウンロードする",
+ "3553a8672f": "最後のエラー",
+ "90559b14e3": "これにより、再起動後にプロセス全体の Electron ネットワーク スイッチがオンになります。 HTTP/2 アップデートのダウンロードを拒否する企業の VPN またはプロキシに使用します。",
+ "6e45bfa2e0": "ダウンロード中...",
+ "558842597d": "アップデートをダウンロード中",
+ "f58b5c57a6": "新規:",
+ "ec8fe71cfc": "アップデート",
+ "44324ef542": "リリースノート",
+ "fdd4a364fa": "セッションは中断されません。",
+ "c4890662e9": "準備ができています。",
+ "318d3b4bc7": "更新を閉じる",
+ "9abc59f814": "利用可能なアップデート",
+ "aad383aecc": "リリースノート全文を読む",
+ "ccd8b0a793": "前回の更新以降、さらに多くの",
+ "b1d867f4fb": "アップデート中にターミナル セッションが中断されることはありません。",
+ "09a55c39b5": "インストール中...",
+ "ea2a41adbe": "最新バージョンを使用しています。",
+ "ba5ffc949c": "アップデートをチェックしています...",
+ "2c2d3e03ca": "再試行",
+ "4cf109845a": "更新エラー",
+ "6b0085010d": "再確認",
+ "48565a32bc": "ダウンロードを再試行",
+ "933c6fdf5b": "有効にして再起動",
+ "1339b82cee": "HTTP/2 ダウンロードがブロックされました",
+ "7274ef6e59": "ヒントを閉じる",
+ "a726967bd3": "閉じる",
+ "d5253b54af": "エラー",
+ "7ffc08506e": "チェック",
+ "522df222b9": "スピナー"
+ },
+ "WorktreeJumpPalette": {
+ "ac037cfac2": "動く",
+ "75499e01d9": "閉じる",
+ "66b5a67bee": "ESC",
+ "45def60329": "オープン",
+ "f65d992a11": "入力",
+ "c5081f2814": "現在のワークツリー",
+ "52404f8096": "現在のタブ",
+ "739bda980c": "主要な",
+ "556e7232ca": "現在",
+ "684e8d7bc2": "最近のワークツリーと開いているタブを収集します。",
+ "ff908adfe9": "ジャンプターゲットをロード中",
+ "1ebe225fee": "ワークツリー、設定、タブ、操作を検索します...",
+ "4e4ff044d5": "ワークツリー、設定、タブ、操作を検索する",
+ "4ee378034d": "にジャンプします...",
+ "f7fda8d562": "まず、ワークツリーを作成するか、Orca でタブを開きます。",
+ "1628fd7dfa": "アクティブなワークツリー、設定、操作、または開いているタブがありません",
+ "b781ae05e3": "入力してワークツリー、設定、タブ、操作を検索します。",
+ "f60f8730be": "他に切り替えるワークツリーがない",
+ "c4afa68159": "ワークツリー、設定、操作、ページ タイトル、エミュレータ、URL、PR、またはポートを試す。",
+ "dbd9d87eec": "検索に一致する結果はありません",
+ "2c38630a01": "ワークスペースはもう存在しません",
+ "7726ce9970": "「モバイルエミュレータ」タブは存在しません",
+ "d7d496a451": "ブラウザページはもう存在しません",
+ "50a1d11d5b": "開いているタブ",
+ "088d66d980": "操作と設定",
+ "dabd819ca1": "すべての {{value0}} ワークツリーを表示するには、次のように入力します。",
+ "20af998bff": "{{value0}}アイテムが利用可能{{value1}}",
+ "bb72c08e63": "{{value0}} の結果が見つかりました{{value1}}",
+ "34c8fbb46e": "SSHリモート",
+ "63c2be1914": "SSHが切断されました",
+ "95be6587d3": "ワークツリー「{{value0}}」を作成する",
+ "worktreesHeader": "ワークツリー",
+ "recentWorktreesHeader": "最近のワークツリー",
+ "settingsBadge": "設定",
+ "actionBadge": "操作"
+ },
+ "github": {
+ "pr": {
+ "merge": {
+ "state": {
+ "a80132573b": "GitHub はまだこのPRのマージ ステータスを計算中です",
+ "f958920f3a": "確認中",
+ "9bd983ce8f": "GitHub によると、この PR はマージ可能ですが、チェックはまだ実行中です",
+ "4e2507176b": "保留中のチェック",
+ "1432ecff30": "GitHub は、この PR はマージできると言っていますが、一部のチェックが失敗しました",
+ "87fa36ac83": "チェックに失敗しました",
+ "1766eb46ba": "GitHub がこのPRがブロックされていると報告しています",
+ "bf5e4c6c92": "ブロック中",
+ "c614e2660a": "マージする前にブランチを更新する",
+ "039c072f94": "後ろに",
+ "b37d45bca9": "GitHub がマージ競合を報告",
+ "7e8bbe3cd7": "紛争",
+ "09896aad26": "この PR ではマージ ステータスを利用できません",
+ "bd4f27b50e": "マージ",
+ "35ec24bc43": "このベース ブランチは GitHub マージ キューを使用します",
+ "b289646bcd": "GitHub は、このPRで要求された変更を報告します",
+ "c606463dc2": "変更要求",
+ "a20db875ed": "このPRをマージするには、GitHub でレビューの承認が必要です",
+ "1f8eb81c0e": "承認が必要です",
+ "f03028e055": "このPRはまだドラフトです",
+ "ec8e2cebaa": "下書き",
+ "820fd21663": "このPRは終了しました",
+ "4f976d3450": "クローズ",
+ "62eb8d39da": "このPRはすでにマージされています",
+ "83ecdbb4a6": "合併しました",
+ "331ebe1170": "このPRを GitHub マージ キューに追加します",
+ "b169f943e1": "準備ができたらマージ",
+ "62703b1dc4": "このPRでは GitHub 自動マージが有効になっています",
+ "48d75ae118": "自動マージを無効にする"
+ }
+ }
+ },
+ "project": {
+ "ColumnResizeHandle": {
+ "1304289353": "列のサイズを変更する"
+ },
+ "GhAuthErrorHelp": {
+ "7e800068d8": "リロード",
+ "baa006f9af": "ドキュメント",
+ "3fefeebde4": "コピー・リフレッシュ・コマンド",
+ "9c2da6353b": "ログインコマンドのコピー",
+ "b436c586d1": "コピーコマンド",
+ "8a7f6bf5dc": "コピーに失敗しました",
+ "224c9d0ae8": "クリップボードにコピーされました",
+ "891a7d4616": "このシェルの設定を解除する",
+ "fd17b3019f": "設定解除 (PowerShell、永続的)",
+ "ae43542893": "設置場所を探す",
+ "df636f5886": "設定されているかどうかを確認する (PowerShell)"
+ },
+ "ProjectCell": {
+ "4b5b871da8": "このリポジトリにはラベルがありません。",
+ "2219e945ef": "読み込み中…",
+ "54cac64427": "行にはリポジトリスラッグがありません。",
+ "8ae56a88a6": "ラベル",
+ "f7cdb78efb": "担当者",
+ "ebde486e3c": "クリア",
+ "191905e20e": "現在および今後の予定",
+ "e17bb96881": "完了",
+ "943b3dadc9": "このリポジトリにはイシュータイプがありません。",
+ "c7b059cf07": "イシューの種類",
+ "c5f949e489": "イシュー",
+ "8d669084f6": "制限付き",
+ "6efdc0d920": "下書き",
+ "d0d0e13a5a": "PR",
+ "af5d8c912a": "制限事項",
+ "bb7ebc11e3": "番号を追加",
+ "9cb1a0c984": "テキストを追加",
+ "2e26a06c70": "ラベルを追加",
+ "36341ffc66": "割り当て",
+ "e369bf4fec": "選択",
+ "ffeff79861": "PULL_REQUEST"
+ },
+ "ProjectGroupHeader": {
+ "82a22d2079": "現在",
+ "244c9e7d06": "全て"
+ },
+ "ProjectItemSlugDialog": {
+ "e55a5c4e68": "プロジェクト行のプレビュー。",
+ "4450efea9c": "GitHub アイテム"
+ },
+ "ProjectPicker": {
+ "96739284c3": "不足しているプロジェクトにアクセスするには、以下のプロジェクト URL を貼り付けてください。",
+ "9b36829267": "ビューが見つかりませんでした。",
+ "72a05c04a6": "ビューを読み込み中…",
+ "9bf55fa1e8": "ビューを選択",
+ "a51b3337ab": "← 戻る",
+ "8ab5447c64": "ピン",
+ "5009ffc2f3": "ピンを外す",
+ "fce99a24a7": "追加",
+ "5113ecc298": "URL または所有者/番号で追加",
+ "7b6d39627e": "読み込み中…",
+ "b787682111": "すべて閲覧する",
+ "ba0ab9a117": "すべて閲覧する (読み込み中…)",
+ "b3044b7a25": "最近の",
+ "707843206c": "固定された",
+ "f492e1b539": "プロジェクトを検索する",
+ "44b2c6326b": "ビューのロードに失敗しました: {{value0}}",
+ "ab1a2c357d": "ロードマップ (未サポート)",
+ "d34ef9b554": "ボード(未サポート)",
+ "43a88ae574": "ボード_レイアウト",
+ "1a2b8e512e": "テーブル",
+ "cafb908f34": "テーブルレイアウト"
+ },
+ "ProjectRow": {
+ "75b5d816e3": "仕事を始める",
+ "e12be8b4d4": "GitHub で開く",
+ "c3b81ddea2": "DRAFT_ISSUE"
+ },
+ "ProjectViewList": {
+ "989f81dc2a": "コラム",
+ "f949f5b2b7": "列を構成する",
+ "eddfc7a794": "{{value0}} で並べ替え",
+ "4f57d2e0b1": "このビューのフィルターに一致する項目はありません。"
+ },
+ "ProjectViewWrapper": {
+ "463f1205c0": "プロジェクトビューをロードしています",
+ "23b87ba9f7": "GitHub で開く",
+ "4d2a77a119": "ファイル機能リクエスト",
+ "1bf8c01c8b": "Orca でこのプロジェクトを操作するには、テーブル ビューに切り替えます。",
+ "55de4fb57a": "{{value0}}。 {{value1}} {{value2}} に機能リクエストを提出します。",
+ "2edf5e7e77": "{{value0}} — Orca はまだ {{value1}} プロジェクト ビューをサポートしていません。 {{value2}} に機能リクエストを提出してください。",
+ "7245c3d7ac": "検索をクリア",
+ "c5bc7ec007": "フィルターを表示: {{value0}}",
+ "840c268665": "リポジトリを追加",
+ "dffa899f36": "キャンセル",
+ "7037c8f5f1": "Orca にリポジトリがありません",
+ "512fc171d6": "開始するにはプロジェクトを選択。",
+ "71fb69926c": "更新",
+ "a8fa0d2bf5": "更新中",
+ "fd15491034": "GitHub でビューを開く",
+ "22df63c393": "トークンではサブイシューデータを利用できません。",
+ "067119985c": "GitHub 検索、例:担当者:@me は:開いています",
+ "1850fceac8": "{{value0}}/{{value1}} は Orca に追加されません。これを追加して作業を開始するか、GitHub で開きます。"
+ },
+ "slug": {
+ "dialog": {
+ "AssigneesEditor": {
+ "529fec247b": "読み込み中…",
+ "98914e6b36": "譲受人:",
+ "94a4e6e4fa": "なし"
+ },
+ "Comments": {
+ "fd5cccd138": "コメント",
+ "1c95937c8b": "コメントを書いて…",
+ "c0e576e96b": "キャンセル",
+ "c3e829b4d9": "保存",
+ "463d030ae4": "削除",
+ "8564f58542": "編集",
+ "5f104bf855": "コメントはまだありません。"
+ },
+ "LabelsEditor": {
+ "34dd57d6c8": "読み込み中…",
+ "a7b182fcda": "ラベル:",
+ "1a5366b5be": "なし"
+ },
+ "SlugDialogBody": {
+ "598ad6a517": "コメント",
+ "41169e41fb": "説明を追加…",
+ "a91735d19f": "キャンセル",
+ "e64f6c3eff": "保存",
+ "e4ef8281e9": "読み込み中…",
+ "ae98897edf": "閉じる",
+ "69caf40ae8": "GitHub で開く",
+ "7c302f8174": "無題"
+ }
+ }
+ }
+ },
+ "GitHubMarkdownComposer": {
+ "015b4e607d": "キャンセル",
+ "e3bd59143c": "入れる",
+ "f24783f470": "https://...",
+ "ec6310b731": "http:// または https:// 画像 URL を使用します。"
+ },
+ "IssueSourceSelector": {
+ "d6aeb2012b": "からのイシューを表示しています",
+ "787c970baf": "イシューソース",
+ "643d7e9496": "上流",
+ "51d1608920": "起源",
+ "cdc9bd64fa": "コンパクト",
+ "30b2c9df91": "上流"
+ },
+ "PRFilterDropdowns": {
+ "979be3cf6b": "担当者",
+ "b27b7e526c": "からのレビュー",
+ "7f1ba66c3e": "レビュアー",
+ "9d0f2eda6d": "ラベル",
+ "01f3f3d161": "著者",
+ "13b3ac0a84": "状態",
+ "79c54552f7": "フィルター",
+ "8a2ffbf9b3": "{{value0}} フィルターを削除します",
+ "19bb6f115f": "reviewed-by"
+ },
+ "PRFilterPickers": {
+ "fdf387297c": "クリア (",
+ "472c12ae03": "クリア",
+ "2d1f58eda6": "使用"
+ },
+ "PRFilterSections": {
+ "a00830d3f7": "ユーザーがいません",
+ "0103e1cb18": "レビュアー",
+ "94b42b0edf": "レビュー依頼済み",
+ "de26e2eb06": "ラベルなし",
+ "458ea3602b": "著者がいません",
+ "b69fa4fa20": "戻る",
+ "30ebb6ca44": "すべてのフィルターをクリア",
+ "8177eda37e": "フィルター",
+ "ea3416d646": "担当者",
+ "b1d9fdea08": "ラベル",
+ "24754c44ad": "著者",
+ "764a0b4ce1": "状態",
+ "f0cf6dd591": "オフ",
+ "1e9b5244f2": "の上",
+ "b930de7194": "ドラフトのみ",
+ "e0002f1eba": "選択された",
+ "2b2f019091": "どの州でも",
+ "0fd3249e2e": "クローズ",
+ "d78b60b5c2": "オープン",
+ "bd162b7d5a": "合併しました",
+ "2e639b84fa": "レビュアー",
+ "712c5abdbf": "ラベル",
+ "4e50c7bc03": "担当者",
+ "7bf3a6e5ac": "著者",
+ "66256a73b3": "状態",
+ "3ce4d5e96e": "PRs"
+ },
+ "github": {
+ "rate": {
+ "limit": {
+ "display": {
+ "5509443543": "GitHub API 予算を読み込み中…",
+ "34973d4695": "GitHub API の予算が利用できません。",
+ "d12d3d6f33": "GitHub API 予算を更新する",
+ "d5e5de9070": "Orca は、GitHub CLI を通じて REST、Search、GraphQL を使用します。",
+ "58c5f88216": "GitHub API の予算",
+ "6da1858354": "左 · リセット",
+ "f42790d150": "の",
+ "01f7323e58": "グラフQL API",
+ "1daf0f22a9": "グラフQL",
+ "1f2f28a4de": "検索API",
+ "c377a4f06a": "検索",
+ "c392c749a6": "REST API",
+ "bb227706a6": "休む"
+ }
+ }
+ }
+ }
+ },
+ "linear": {
+ "api": {
+ "key": {
+ "dialog": {
+ "834a52c084": "確認中...",
+ "f8f704a019": "キャンセル",
+ "e603ee9156": "ワークスペースAPIの設定",
+ "dc7ccb0f7c": "個人用 API キー",
+ "e3100b36b9": "メンバー API キーがブロックされている場合は、ワークスペース管理者にワークスペース API 設定から許可するよう依頼してください。",
+ "d56d3629f4": "Orca がそのワークスペース内でアカウントがアクセスできるすべてのチームを表示する必要がある場合は、フルアクセスを優先します。制限付きキーは許可されたチームのみを公開し、プライベート チームはキー所有者にアクセス権を必要とします。",
+ "af52a6227f": "[アカウント] > [セキュリティとアクセス] から個人 API キーを作成します。",
+ "edec49dfae": "lin_api_...",
+ "7d498f653c": "個人用APIキー",
+ "57a66522c8": "接続する",
+ "c9889a09f8": "キーを作成する前に、[Linear] を使用して目的のワークスペースを選択します。",
+ "e689a4d0a6": "エラー"
+ }
+ }
+ },
+ "priority": {
+ "icon": {
+ "c43d3e065b": "優先度:"
+ }
+ },
+ "project": {
+ "view": {
+ "surfaces": {
+ "8bbecb2510": "なし",
+ "e1fa97d21d": "プロジェクトを選択してその概要を表示します。",
+ "1748d3b9af": "ラベル",
+ "65bda65159": "メンバー",
+ "c5f79616c3": "チーム",
+ "25a2196732": "ターゲット",
+ "3fb6473111": "始める",
+ "111bef9aa8": "鉛",
+ "3be47aed6f": "優先度",
+ "f5ef24cf46": "健康",
+ "9ddb58edbd": "状態",
+ "0a6a5a7dd6": "最新のアップデート",
+ "c8db98b73b": "リソース",
+ "bb1405eff8": "マイルストーン",
+ "5d99315fb8": "企画",
+ "3ad562bdf4": "スコープされたイシュー",
+ "563501f191": "進捗",
+ "bb5664d456": "プロジェクトの説明はありません。",
+ "7b147907dc": "Linear",
+ "a9785c7158": "更新",
+ "ee3d2caabd": "イシュー",
+ "5f79bc76b0": "プロジェクトに戻る",
+ "aac9a4afc6": "Linearで開く",
+ "7616c986c6": "{{value0}} イシューを開く",
+ "93e1f6bfca": "読み込み中",
+ "98730088a6": "。フルセットについては、Linear を検索するか開きます。",
+ "06b887d622": "最初に表示しています",
+ "2c4b1c2c08": "番号",
+ "f2cc1e0ff6": "Linear / プロジェクト",
+ "906b5e4cb8": "Linear / プロジェクト / {{value0}}",
+ "85607ff793": "プロジェクト",
+ "20b9d09b7d": "未知",
+ "f059181bd9": "プライベート",
+ "27d91cb1a6": "共有",
+ "9f0f51fd9e": "Linearでビューを作成または保存し、更新します。",
+ "f4c79cff5f": "以下のワークスペース エラーを確認し、更新してください。",
+ "ef90b21366": "ビューが見つかりませんでした",
+ "c0a50f96a4": "ビューをロードできません",
+ "df4bd63c1d": "未割り当て",
+ "30402d2c6e": "検索または更新してみてください。",
+ "a2f31c4cd6": "Linear プロジェクトが見つかりません",
+ "c9b6e9f90d": "Linear プロジェクトをロードできません"
+ }
+ }
+ },
+ "scope": {
+ "selector": {
+ "91c8871dad": "チームアクセスを追加",
+ "7783361266": "全チーム",
+ "e1ae6bebb0": "チーム",
+ "a14ce4df2b": "すべてのワークスペース",
+ "05baa5ae90": "ワークスペース",
+ "89f6580dbf": "チームを検索...",
+ "b3488fad3c": "チームはフェッチされませんでした。アクセスは、キーのスコープ、プライベート チームのメンバーシップ、アーカイブされたチーム、権限、またはフェッチの失敗によって異なります。",
+ "405b33c378": "検索に一致する取得チームはありません。"
+ }
+ }
+ },
+ "notification": {
+ "sound": {
+ "options": {
+ "e38b0a2e68": "ビープ",
+ "0acd3d384e": "カタカタ",
+ "79919c832d": "丁",
+ "2b44847d8d": "ブロップ",
+ "020826ef17": "ソナー",
+ "588c90487d": "ブリップ",
+ "1e4b81d892": "ドスン",
+ "86af8d938c": "ボン",
+ "80f7cc95b3": "ツートーン",
+ "017abebfa6": "システムのデフォルト"
+ }
+ }
+ },
+ "worktree": {
+ "creation": {
+ "WorktreeCreationPanel": {
+ "dabd226118": "閉じる",
+ "34dd5ee38b": "再試行",
+ "ed2a664f8b": "ワークツリーを作成できませんでした",
+ "a3346fc6ed": "ワークツリーの作成をキャンセルする",
+ "532aea14ce": "キャンセル",
+ "767951265d": "ワークツリーの作成中に問題が発生しました。"
+ }
+ }
+ },
+ "workspace": {
+ "space": {
+ "WorkspaceSpacePage": {
+ "8d0048e1cb": "ワークスペースのディスク使用量と再利用可能なワークツリー ストレージ。",
+ "e8d6ba11ab": "ベータ",
+ "45f6302dbc": "スペース",
+ "ecf72fdc3b": "戻る"
+ }
+ },
+ "cleanup": {
+ "WorkspaceCleanupDialog": {
+ "3828408538": "{{value0}} を削除",
+ "352f15d6fc": "最後にアクティブだった",
+ "cbf2f664e2": "削除",
+ "b6bae1eed1": "キャンセル",
+ "592fbab446": "最も古いアクティビティ順に並べ替え",
+ "dba753e94f": "削除する",
+ "38ca0b1400": "これにより、ローカル ファイルが完全に削除されます。これを元に戻すことはできません。",
+ "c4f4782c02": "提案されません",
+ "0a2e3c7cba": "レビュー",
+ "e97e4580c7": "汚い",
+ "9623a5107d": "プッシュされていないコミット",
+ "e8b3741ff7": "無視されました",
+ "a9957007eb": "{{value0}} を無視する",
+ "1bffc07ba7": "{{value0}} を見る",
+ "bef0adef9b": "ブランチ",
+ "0b1766738a": "リポ",
+ "bbb1ab6a6f": "{{value0}} を選択",
+ "d1094dd529": "レビュー待ち",
+ "4b93a235d8": "提案された",
+ "f68d538c63": "このクリーンアップ セットにはワークスペースがありません。",
+ "4719327c9c": "クリーンアップの提案はすべて無視されます。",
+ "a19040cd67": "選択したリポジトリに一致する非アクティブなワークスペースはありません。",
+ "97c772c4fe": "チェックしたリポジトリに非アクティブなワークスペースは見つかりませんでした。",
+ "d3eef9463d": "削除する非アクティブなワークスペースはありません。",
+ "aaee139eab": "無視された提案を復元する",
+ "06cf78521e": "{{value0}} ですべてを選択",
+ "73690b0031": "{{value0}} のすべての選択を解除します",
+ "b771c92598": "選択したものを削除",
+ "37ab28277e": "提案されていない",
+ "1b18868569": "レビュー待ち",
+ "b299f201b9": "安全に取り外し可能",
+ "2b31bf68de": "非アクティブな",
+ "ac5ba84cc1": "選択された",
+ "8b74d4ea6e": "ワークツリーと git 状態をスキャンし、削除を提案する前に、開いているタブ、ターミナル、ライブ エージェント、およびリモートの可用性シグナルを組み合わせます。",
+ "7eee951968": "作業場の安全性の確認",
+ "191f0bc98e": "閉じる",
+ "7ae2ad30f4": "更新",
+ "e0b5a4deaa": "ローカル ファイルと Orca 状態を削除する前に、非アクティブなワークスペースを確認してください。",
+ "b2c1331844": "非アクティブなワークスペースの削除",
+ "41d594d01e": "{{value0}} ワークスペース{{value1}} を削除できませんでした",
+ "0f00612b6d": "{{value0}} ワークスペース{{value1}} を削除しました",
+ "7f451a3e2c": "クリーンアップの提案を無視できませんでした",
+ "662b8ec3f8": "ワークスペースのクリーンアップ スキャンに失敗しました",
+ "bc43c37faf": "隠れた",
+ "0c6672f5e3": "クリーンアップの提案が無視されました",
+ "fc49f79434": "混合された",
+ "2ddbd6fe8a": "チェック済み"
+ }
+ }
+ },
+ "ui": {
+ "color": {
+ "picker": {
+ "ebcf6ba29e": "無効な 16 進数の色です。",
+ "faa855a582": "16進数",
+ "1cec618bcc": "{{value0}} ピッカー"
+ }
+ },
+ "dialog": {
+ "f26c4baeda": "閉じる"
+ },
+ "repo": {
+ "multi": {
+ "combobox": {
+ "286ce70256": "SSH",
+ "4471d4a1c0": "検索に一致するプロジェクトはありません。",
+ "bfd8ce21c6": "すべてのプロジェクト",
+ "a58a0cd100": "プロジェクトを検索...",
+ "65a3dae41d": "プロジェクトがありません"
+ }
+ }
+ },
+ "sheet": {
+ "1189e9fe0a": "閉じる"
+ },
+ "team": {
+ "multi": {
+ "combobox": {
+ "de83523bf9": "検索に一致するチームはありません。",
+ "301f2a796e": "全チーム",
+ "18ec58881e": "チームを検索..."
+ }
+ }
+ }
+ },
+ "terminal": {
+ "quick": {
+ "commands": {
+ "TerminalQuickCommandActionToggle": {
+ "b0d58e37ed": "エージェントプロンプト",
+ "b5ea4d64f6": "ターミナルコマンド"
+ },
+ "TerminalQuickCommandAppendEnterSwitch": {
+ "e4e5fed3b3": "追加を切り替え Enter",
+ "c936c2d6d2": "テキストを挿入するだけでなく、すぐに送信してください。",
+ "5fa607d807": "追加 Enter"
+ },
+ "TerminalQuickCommandDialog": {
+ "925b8e0f6e": "詳細設定",
+ "97e96cc027": "/ゴール",
+ "e604bd40d6": "スキル、ファイル パス、および組み込みコマンドをサポートします。",
+ "79af0c0841": "npm 実行開発",
+ "577a342c7d": "エージェントにこのワークスペースを調査するよう依頼します",
+ "026cfb232a": "プロンプトコマンドをサポートしていません",
+ "346d409ab2": "エージェントを選択",
+ "0adba8fa0c": "エージェント",
+ "ec8f081919": "操作",
+ "ed04233b3e": "ターミナルコマンドまたはエージェント プロンプトを保存して、すぐにアクセスできるようにします。",
+ "ca414324ee": "コマンドテキスト",
+ "dc921c17ee": "プロンプト",
+ "5b3f634a55": "クイックコマンドを追加",
+ "f9b184fc16": "クイックコマンドの編集",
+ "6751598542": "編集"
+ },
+ "TerminalQuickCommandDialogFooter": {
+ "2e2b958dfc": "保存",
+ "8dff838dea": "保存 ({{value0}})",
+ "28370f16b9": "キャンセル"
+ },
+ "TerminalQuickCommandLabelField": {
+ "66ea254301": "開発サーバーを起動する",
+ "db17f1e41e": "ラベル"
+ },
+ "TerminalQuickCommandScopeField": {
+ "2db6edede7": "別のプロジェクトを選択しない限り、保存すると既存のプロジェクト スコープが保持されます。",
+ "2496523a6f": "プロジェクトを選択",
+ "2264edd5d3": "リストにないプロジェクト",
+ "3834d24243": "プロジェクト",
+ "b83efc79e2": "グローバル",
+ "c25cf350ef": "範囲",
+ "f0631e4999": "リポジトリ"
+ }
+ }
+ },
+ "pane": {
+ "CloseTerminalDialog": {
+ "ebd2fa844d": "閉じる",
+ "1d1a7a9c1f": "キャンセル",
+ "6b9a6975f8": "ターミナルにはまだ実行中のプロセスがあります。ターミナルを閉じるとプロセスが強制終了されます。",
+ "78b79d854d": "ターミナルを閉じますか?"
+ },
+ "MobileDriverOverlay": {
+ "c6460cf584": "取り戻す",
+ "c44659e09f": "移動運転",
+ "7cffad954c": "折りたたむ",
+ "3eed73394f": "キーボードが一時停止しています",
+ "faa367dc74": "このターミナルはモバイル アプリに合わせたサイズになっています"
+ },
+ "TerminalAgentSessionForkDialog": {
+ "17fc841e59": "コンテキストをコピーする",
+ "0c8a8629b1": "フォークは、ネストされた子としてではなく、独自のワークスペースとして表示されます。新規エージェントは、編集可能なドラフトとして制限されたトランスクリプトを受け取ります。",
+ "620461df22": "トップレベルのフォーク",
+ "619b5a35d2": "最上位のワークスペース フォークを作成し、キャプチャされたコンテキストを使用して新しいエージェント タブを開始します。",
+ "64e292e8e3": "エージェントセッションをフォークする",
+ "9d25de2920": "フォークの作成",
+ "2b10412cfc": "作成..."
+ },
+ "TerminalContextMenu": {
+ "b4cdd9314e": "クリアスクリーン",
+ "8c17d6786d": "ペインを閉じる",
+ "2cf85a6a55": "ペインIDのコピー",
+ "39809d152f": "タイトルを設定…",
+ "06c2b0f043": "ペインのサイズを均等化する",
+ "98bccf4fa2": "スプリットターミナルダウン",
+ "20e565d865": "分割端子右",
+ "8a7ddb8b8a": "エージェントセッションをフォーク…",
+ "0a82b0608c": "クイックコマンドを追加…",
+ "9528a65ef8": "クイックコマンドはありません",
+ "3ce594a4a0": "グローバル",
+ "ec85df5914": "クイックコマンド",
+ "0a917b591a": "ペースト",
+ "f3eeb1de13": "コピー",
+ "c2f0b72b8d": "入れる",
+ "925f49f210": "ペインを展開する",
+ "df766809e0": "ペインを折りたたむ"
+ },
+ "TerminalErrorToast": {
+ "e4aa243f8c": "デーモンを再起動します",
+ "a7e2fd2699": "イシューを登録",
+ "5c8ce20be6": "この状態が続く場合は、",
+ "cc6d997c65": "ここからターミナル デーモンを再起動して、古いデーモン状態をクリアします。"
+ },
+ "TerminalPane": {
+ "ac112e9036": "タイトルを削除",
+ "f984ab2a30": "ペインのタイトルを削除: {{value0}}",
+ "cc5a2dc706": "編集ペインのタイトル: {{value0}}",
+ "7dbbfcbecc": "ペインのタイトル"
+ },
+ "TerminalSessionStateSaveFailureDialog": {
+ "6bee0c8f17": "ディスクスペースアナライザーを開く",
+ "ae20d0ffc2": "閉じる",
+ "38c282a2c4": "アナライザーはここから直接開きます。後で左下のツールボックス メニューから [Space Analyzer] を選択して開くこともできます。",
+ "e2fcf07c0d": "ローカル ストレージがいっぱいか書き込みできないため、Orca はこのターミナル セッションを保存できませんでした。ディスク容量アナライザーを開いて、クリーンアップできるワークスペース ストレージを見つけます。",
+ "678c780a2c": "ディスク容量が利用できません"
+ },
+ "osc52": {
+ "clipboard": {
+ "blocked": {
+ "toast": {
+ "97c98f1afe": "設定を開く",
+ "7cf51f74fd": "SSH、tmux、Neovim、または fzf からコピーするには、ターミナル設定で TUI クリップボードへの書き込みを有効にします。",
+ "89eaa3e80b": "ターミナルのクリップボードへの書き込みがブロックされました"
+ }
+ }
+ }
+ },
+ "stale": {
+ "agent": {
+ "row": {
+ "ad991ece5c": "エージェントのペインは使用できなくなりました。",
+ "090d607412": "古いエージェント行-{{value0}}"
+ }
+ }
+ },
+ "terminal": {
+ "agent": {
+ "session": {
+ "fork": {
+ "2317900211": "フォークコンテキストのコピーに失敗しました。",
+ "88e34d00eb": "新規ワークスペースで開かれたトップレベルのセッション フォーク",
+ "fd3d12a1e1": "フォークワークスペースの作成に失敗しました。",
+ "38e41edc6e": "このワークスペースを git ワークツリーにフォークすることはできません。",
+ "f867385bb5": "このフォークのソース ワークスペースが見つかりませんでした。",
+ "046e8d853c": "フォークするターミナルコンテキストがありません",
+ "c00421d320": "フォークコンテキストがコピーされました。エージェントを起動し、貼り付けてフォークを開始します。"
+ }
+ }
+ },
+ "drop": {
+ "handler": {
+ "1e072f611e": "{{value0}} {{value1}} のアップロードに失敗しました。",
+ "53f015fd85": "{{value0}} シンボリックリンク{{value1}} をスキップしました。",
+ "29c031b49a": "{{value0}} ファイル{{value1}} をランタイムにアップロードしています…",
+ "0c77693641": "ワークツリーの準備ができていません - しばらくしてからもう一度お試しください。",
+ "ce8248b835": "ワークツリーのパスが使用できません。"
+ }
+ }
+ },
+ "use": {
+ "terminal": {
+ "pane": {
+ "context": {
+ "menu": {
+ "a29b9faa01": "ペイン ID がコピーされました"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tab": {
+ "group": {
+ "TabGroupPanel": {
+ "814fb04c43": "エディターを読み込み中...",
+ "f7d6ce445e": "グループを閉じる",
+ "0db2081805": "スプリットアップ",
+ "30137df7d0": "左に分割",
+ "4df2a06d36": "スプリットダウン",
+ "ab1e2bff04": "右に分割",
+ "9acaf92093": "ペインの操作",
+ "1bce81dba6": "シミュレータ",
+ "1ff1c77616": "ブラウザ",
+ "586d2ac445": "ターミナル"
+ }
+ },
+ "bar": {
+ "BrowserTab": {
+ "6e0bc8f3a8": "ブラウザで開く",
+ "9dd880bd56": "右側のタブを閉じる",
+ "1611a1324b": "閉じる",
+ "5d6e89891f": "タブの複製",
+ "966feb9ad5": "右に分割",
+ "7e8106899f": "左に分割",
+ "2186a8407c": "スプリットダウン",
+ "96354ed249": "スプリットアップ",
+ "911542656f": "ピンタブ",
+ "c5aaee8c39": "タブの固定を解除する"
+ },
+ "EditorFileTab": {
+ "3da7445c84": "ファイル {{value0}} の名前を変更します"
+ },
+ "EditorFileTabContextMenu": {
+ "52ce4f4605": "相対パスをコピー",
+ "5b85754786": "パスのコピー",
+ "bfd5797ef4": "マークダウンプレビューを開く",
+ "e5ff31ccaf": "右側のタブを閉じる",
+ "ba1369dd24": "すべてのエディターのタブを閉じる",
+ "1ba8492c5b": "閉じる",
+ "68cc610e7f": "名前を変更する",
+ "f7c3d7d5af": "右に分割",
+ "e3ff145b98": "左に分割",
+ "1d04b1630b": "スプリットダウン",
+ "6b3efb106e": "スプリットアップ",
+ "fdd29eb669": "ピンタブ",
+ "8e9d603a09": "タブの固定を解除する"
+ },
+ "QuickLaunchButton": {
+ "348a04c1ad": "エージェント設定…",
+ "ec2adf093e": "新規ターミナルで {{value0}} を起動",
+ "465e432ef1": "{{value0}} の起動コマンドを構築できませんでした。",
+ "e518f544b1": "エージェントが検出されませんでした",
+ "8dea9b5cdf": "有効なエージェントがありません"
+ },
+ "RecentTabSwitcher": {
+ "329638ff6f": "タブの切り替え",
+ "07ad4cd0b7": "タブを切り替える"
+ },
+ "SortableTab": {
+ "ab19f603eb": "タブ {{value0}} の名前を変更します",
+ "6df69d9388": "タブ {{value0}} を閉じる",
+ "fdb2691425": "ペインを折りたたむ"
+ },
+ "SortableTabContextMenu": {
+ "35e8892fd0": "タブの色",
+ "2f697b3c31": "タイトルの変更",
+ "c1ee099c7e": "右側のタブを閉じる",
+ "8d16f9cd30": "その他を閉じる",
+ "89359a36f7": "閉じる",
+ "21132389e9": "右に分割",
+ "0ce4bae39d": "左に分割",
+ "af80ed83c1": "スプリットダウン",
+ "591f9b12c1": "スプリットアップ",
+ "7703990447": "グレー",
+ "845576bed1": "ティール",
+ "be905e9b0a": "緑",
+ "69682e2ce4": "黄色",
+ "a47629b3cf": "オレンジ",
+ "620aec6729": "赤",
+ "03cf6dab1a": "ピンク",
+ "c2d8b0991f": "紫",
+ "cb3eadefd2": "青",
+ "20baa43c05": "なし",
+ "60f958ec75": "ピンタブ",
+ "417722e9c2": "タブの固定を解除する"
+ },
+ "TabBar": {
+ "b1a132357f": "新規タブ",
+ "4f327c8b3d": "マークダウンを開く...",
+ "3d5d6c960d": "新規マークダウン",
+ "fd2b42aaa3": "新規モバイルエミュレータ",
+ "aea43b5748": "既存のエミュレータタブを開きます。",
+ "b426bb2615": "モバイルエミュレータに移動",
+ "4833fb2cbe": "新規ブラウザタブ",
+ "d364f3c8d4": "新規ターミナル",
+ "7c1313d237": "新規ターミナル:",
+ "d1afac112b": "WSL",
+ "efb33546ff": "Git Bash",
+ "1a8af49530": "CMDプロンプト",
+ "2148f65e04": "パワーシェル",
+ "ab589350e5": "{{value0}} の起動コマンドを構築できませんでした。"
+ },
+ "TabBarCreateEntry": {
+ "d62d63b807": "ファイルの作成",
+ "25dc1cd653": "ファイルを開く",
+ "7cdf8ee0c8": "URLを開く",
+ "b27864279e": "エージェントを起動",
+ "39676a184c": "任意のファイル、URL、エージェントなどを開きます..."
+ },
+ "TabBarQuickCommandsButton": {
+ "a2c7a33831": "コマンドの追加",
+ "20bbd75896": "コマンドはありません",
+ "b82e237a4b": "よりクイックなコマンド",
+ "85482c57bc": "クイックコマンドを実行する",
+ "b775303755": "クイック コマンドを実行します: {{value0}}",
+ "196593b6a9": "{{value0}} を削除",
+ "15529ede69": "{{value0}}を編集",
+ "1d411fb6a5": "このリポジトリのクイック コマンドを保存します",
+ "8f1e971966": "クイックコマンドを追加",
+ "3220e2da27": "このクイック コマンドは保存されたリストから削除されます。",
+ "e8e1a52edb": "「{{value0}}」を削除しますか?",
+ "37e1bb90ce": "実行: {{value0}}",
+ "77ac113df0": "{{value0}} を開始: {{value1}}",
+ "7b1c9d6ae1": "走る",
+ "c781f992e4": "破壊的な",
+ "be8f0ff166": "削除"
+ },
+ "shell": {
+ "icons": {
+ "d4ceaa227c": "Git",
+ "e9b2e70613": "WSL"
+ }
+ },
+ "tab": {
+ "create": {
+ "entry": {
+ "classifier": {
+ "42e6262ae9": "利用可能な操作はありません。",
+ "097a982ee0": "ファイルをロード中...",
+ "5a9c83c04b": "任意のファイル、URL、エージェントなどを開きます...",
+ "90eb94dc48": "http:// または https:// URL を入力します。",
+ "5553b283ce": "URL またはファイル パスを入力します。"
+ }
+ }
+ }
+ }
+ }
+ },
+ "status": {
+ "bar": {
+ "PetStatusSegment": {
+ "3668339495": "{{value0}} を削除",
+ "cd8c6c654c": "ペット設定…",
+ "ed176ad68f": ".codex-pet バンドルをインポートします…",
+ "59b5955621": "自分のものをアップロードしてください…",
+ "0608ad02a2": "ペットを選択",
+ "b75484a01a": "ペットのサイズ",
+ "c6aa805b1b": "ピクセル",
+ "2f7bbaa457": "サイズ",
+ "34c25dfe9c": "ペット",
+ "aec479308a": "ペットメニュー",
+ "cef0ab4636": "ペットバンドルのインポートに失敗しました",
+ "2021d4f6db": "ペット バンドルのインポートには、(リロードだけでなく) アプリを完全に再起動する必要があります。",
+ "f395c9a685": "ファイルのインポートに失敗しました",
+ "e6234bcc17": "カスタム ペットのアップロードには、(リロードだけでなく) アプリを完全に再起動する必要があります。",
+ "6d0a8cd179": "ペットを見せる",
+ "1fbc51cc77": "ペットを隠す"
+ },
+ "PortsStatusSegment": {
+ "4ebf90c12e": "外部ポートが検出されませんでした",
+ "7dac3ecc9d": "外部ポート",
+ "95495019ed": "ポートスキャンは使用できません",
+ "a8e4bdb412": "· {{value0}} 外部",
+ "9aa11005bf": "ワークスペース・",
+ "c22ea609fd": "ポート",
+ "a11ed266ce": "ワークスペース",
+ "ca41be2802": "ポート —",
+ "b8bc3e420a": "ポート、{{value0}} ワークスペース {{value1}}",
+ "3a87d54dfb": "ワークスペースポートが検出されませんでした",
+ "c174bbbfed": "ワークスペースポートをスキャンしています...",
+ "8caaa86e9a": "ポート",
+ "45834a9ace": "ポート"
+ },
+ "ResourceUsageStatusSegment": {
+ "946d9f94d0": "キャンセル",
+ "67c4ecda49": "このターミナルを強制終了します。ペイン内の保存されていない作業はすべて失われます。これを元に戻すことはできません。",
+ "4bb076fa89": "強制終了",
+ "996295bff2": "孤立したターミナル",
+ "92924a14e3": "非アクティブなワークスペースを確認する (",
+ "27a74f91f0": "現在何も実行されていません",
+ "1b24a32d3a": "メモリ",
+ "298f4be7f2": "CPU",
+ "2aa2de6cb9": "名前",
+ "30ff2c3c31": "孤児",
+ "6449a95c78": "Orca が追跡するプロセスがこのマシンの物理 RAM にどれだけの量を配置しているか。",
+ "e7ccce7e87": "システムRAMの",
+ "9e2525c89f": "Orca が保持する常駐メモリと各ワークツリーのターミナル下のプロセス。",
+ "1fedf94eae": "合計の CPU 負荷。 100% を超える値は、複数のコアが同時に動作していることを意味します。",
+ "e7cf14ec78": "ターミナルセッションは利用できません。リストは古い可能性があります。",
+ "93b0de3c21": "再起動",
+ "f85af9cda6": "リソースのスナップショットとターミナルセッションは利用できません。",
+ "f8e0d794b4": "デーモンが応答していません",
+ "bd19fd7a59": "すべてのセッションを強制終了します",
+ "c9382662bb": "デーモンを再起動します",
+ "59f178fe11": "{{value0}}、デーモンに到達できません",
+ "21cacb16d1": "· リモート",
+ "73a3fd68a9": "リポジトリを折りたたむ",
+ "b12e31dfcb": "リポジトリを拡張する",
+ "d659d71d2d": "ワークスペース {{value0}} を再開します",
+ "bbcd9b7b85": "ワークスペースを折りたたむ",
+ "c4a8968bdd": "ワークスペースを拡張する",
+ "b10695d6ce": "セッションを強制終了する",
+ "288a4dd177": "Orca",
+ "53dd5560ae": "Orca を折りたたむ",
+ "e419d27083": "Orcaを展開する",
+ "41ae4fa725": "終了中…",
+ "138b99bd80": "このセッション",
+ "888dad8c55": "読み込み中…",
+ "56b6888304": "ランタイム サーバーではローカル リソースの使用量が非表示になります。",
+ "14ff448686": "ランタイムサーバーでは使用できません",
+ "6d9793d4bc": "リソースマネージャー - ターミナル",
+ "6a822b06a7": "リソースマネージャー",
+ "ca95d077db": "デーモンに到達できません",
+ "a82253b458": "ワークスペースを削除します。",
+ "946724a70a": "メインワークスペースは削除できません。",
+ "16bc3c998a": "ワークスペース {{value0}} を削除",
+ "0f9e50eb07": "他の",
+ "d406915b78": "レンダラー",
+ "81cd37af99": "主要"
+ },
+ "SshStatusSegment": {
+ "3ad70e0365": "SSHを管理…",
+ "6e8a9a4242": "SSH接続",
+ "d09ec41831": "SSH",
+ "fdc57e9970": "SSH接続状態",
+ "59b553e2aa": "切断",
+ "63f36455cc": "接続",
+ "bf07aee59e": "切断に失敗しました",
+ "2c29e2de68": "接続に失敗しました",
+ "bc5a3fd41a": "部分的",
+ "3d0128b105": "接続されています",
+ "fd9a3c600e": "エラー",
+ "fbb3f9f05e": "コンフリクト",
+ "95e4ff5b4b": "押す",
+ "63a2b965f6": "引っ張る"
+ },
+ "StatusBar": {
+ "9659e38343": "ポート",
+ "d1e1a7a6bf": "リソースマネージャー",
+ "24ac89df1a": "SSHステータス",
+ "5e59007df4": "Kimi 使用量",
+ "8c86cd77b0": "OpenCode Go の使用法",
+ "c1df0d67ec": "Gemini 使用量",
+ "c0909c686e": "Codex 使用量",
+ "3885eb74d8": "Claude 使用量",
+ "c8857b40f7": "使用状況データを更新する",
+ "75ded02687": "アカウントを管理…",
+ "ff0fbe9311": "アクティブ",
+ "7657e3db9c": "Codexアカウント",
+ "38b5647724": "Codex使用ランタイム",
+ "ba55303942": "Codex の詳細とアカウント切り替えを開く",
+ "4dff061aab": "·",
+ "2483c60695": "・・・",
+ "c35af53b73": "サインイン",
+ "f19a63e7cd": "サインインして使用状況を確認する",
+ "5c938d39ac": "%週",
+ "d79c3362c4": "% 5時間",
+ "8295903d17": "切り替え後に古い会話を続ける前に、ライブ Claude ターミナルを再起動します。",
+ "c98ea88392": "他のアカウントはありません",
+ "9332ba8684": "に切り替えます",
+ "d450654fa2": "Claudeアカウント",
+ "11e2354daf": "Claude使用ランタイム",
+ "3dd7ddfae1": "Claudeの詳細とアカウント切り替えを開く",
+ "59c6e7b4e0": "表示されているセッションが再開されます。他のものは、ワークツリーがアクティブになると再起動します。",
+ "c676918adc": "システムのデフォルト",
+ "3325d996cb": "リフレッシュレートの制限",
+ "fda8146810": "Kimiの使用状況の詳細を開く",
+ "629251f4b6": "OpenCode Go の使用状況の詳細を開く",
+ "d2375976eb": "Gemini の使用状況の詳細を開く",
+ "3d79122c3f": "kimi",
+ "d7a0668acc": "opencode-go",
+ "68efc0345c": "gemini",
+ "76b06d4da5": "claude",
+ "a28a5dd9b1": "エラー",
+ "cd9d7b40ff": "{{value0}} セッションを再起動します",
+ "6cd6650b4c": "セッションを再開する",
+ "1446d0d8a0": "{{value0}} Codex セッションはまだ古いアカウントにあります。",
+ "605901a495": "1 Codex セッションはまだ古いアカウントにあります"
+ },
+ "StatusBarUsageEmptyCta": {
+ "828c764a79": "アカウントを接続する",
+ "caa0f39811": "サポート:",
+ "97957ad3a3": "AI プロバイダー アカウントに接続すると、その使用状況をリアルタイムで確認し、アカウント間を簡単に切り替えることができます。",
+ "9a542f46c7": "ステータスバーから隠す",
+ "84c3b15dca": "エージェントの使用制限",
+ "d663430cf9": "AI アカウントに接続して使用状況を確認する"
+ },
+ "UpdateStatusSegment": {
+ "5cd13105a3": "アップデートに失敗しました。クリックして展開します。",
+ "2201df6987": "更新に失敗しました — クリックして詳細を表示します",
+ "8533c12c3c": "アップデートに失敗しました",
+ "962404f68e": "アップデートをインストールする準備ができました。クリックして展開します。",
+ "248ee5d8ef": "Orca v{{value0}} ダウンロード中… {{value1}}%",
+ "57a29c3b0e": "アップデートの準備ができました",
+ "fd1d3b3a1d": "アップデートのダウンロード、{{value0}} パーセント。クリックして展開します。"
+ },
+ "WorkspaceSpaceCompactPanel": {
+ "a471aa9c24": "更新されました",
+ "9be86c46a0": "無料可能",
+ "f4d2651498": "スキャン済み",
+ "6a5dc3c61a": "レビュー",
+ "c361440dc0": "ベータ",
+ "8ff597593d": "スペース",
+ "0582df6d2e": "スキャン",
+ "f5e1a84d79": "更新",
+ "2af2174d6d": "キャンセル",
+ "5691353a21": "停止中",
+ "2837dc7c72": "キャンセルする",
+ "0583c806ac": "ワークスペースのディスク使用量はスキャンされません。",
+ "39786e3b73": "ワークスペースのサイズをスキャンしています。",
+ "bef4dc0457": "{{value0}} は回収可能ですが、{{value1}} は利用できません",
+ "3d8d47ce77": "{{value0}} · 最後の結果が保持される"
+ },
+ "WorkspaceSpaceManagerPanel": {
+ "2965415393": "強制削除に失敗しました",
+ "e031e93219": "一致するワークスペースがありません。",
+ "a02d84d2d2": "ワークスペースのスキャン。このページから離れても構いません。",
+ "be37293b10": "州",
+ "33aef3e9cc": "サイズ",
+ "81f14d9924": "リポジトリ",
+ "e4aebea158": "ワークスペース",
+ "1d0f8300d1": "表示されている削除可能なワークスペースを選択します",
+ "697d60c456": "表示されている選択範囲をクリアします",
+ "81aaf1de65": "削除可能なワークスペースのみを表示",
+ "d7ac56452e": "アクティビティ",
+ "243287ac60": "名前",
+ "6f8f6a6b04": "ワークスペースのフィルタリング",
+ "5caccea440": "選択したものを削除",
+ "e4a12c455b": "クリア",
+ "0cb1501ccf": "回収可能な",
+ "65402b7192": "選択された",
+ "43171f3e60": "ワークスペース",
+ "83f1a0a932": "回収可能",
+ "09960d86bd": "スキャン済み",
+ "1cc6cd4c0f": "ワークスペース",
+ "02b27c2230": "ワークスペース",
+ "63efebe0e6": "{{value0}} {{value1}} がスペースから削除されました。",
+ "eee5240810": "ワークスペースが削除されました",
+ "9afc97f9a3": "ワークスペースが削除されました",
+ "792a214457": "ワークスペースの削除",
+ "a998501630": "力",
+ "9155381019": "まばらな",
+ "f39d291997": "選択",
+ "16988df079": "ファイルが見つかりませんでした。",
+ "b25c2c1086": "最上位の項目",
+ "d3f9c69ddc": "ズーム",
+ "ef890d31b9": "全て",
+ "c28643d3da": "ワークスペースに移動",
+ "66870929fb": "イシュー",
+ "fb2069acb7": "レビュー",
+ "b9b4a3a25d": "ブランチ",
+ "c432278ec7": "エディタバッファ",
+ "0bc756efaf": "Git の変更",
+ "e9528a89b3": "端子",
+ "a8d9e0de79": "エージェント",
+ "d384a4ce9f": "決定の削除",
+ "7d7745bb8f": "削除できます",
+ "720870a18e": "保持: リンク済み",
+ "cbc343a7a8": "保持: 使用中",
+ "2055bc6a5a": "保持: 未保存の編集内容",
+ "ec7b076a75": "保持: git はチェックされていません",
+ "7ab8d7e2d7": "保持: 変更されたファイル",
+ "7f7895514e": "維持: アクティブ",
+ "2b501ee391": "キープ: メイン",
+ "39801484e0": "失敗した",
+ "33653dbac2": "削除中",
+ "52b629eb84": "更新されました",
+ "e91dd2a9ae": "スキャンを実行してワークスペースのサイズを検査します。",
+ "61e25239da": "スキャンから利用できるワークスペース行はありませんでした。",
+ "8194a4fb29": "ワークスペースのサイズが収集される前にスキャンが失敗しました。",
+ "b2f82ed5ae": "削除可能",
+ "20a4204dce": "最後に成功した結果は引き続き表示されます。",
+ "8c7c57fbf8": "スキャン",
+ "508673bac0": "更新",
+ "8dc9ddac8a": "キャンセル",
+ "1fce91d1b9": "停止中",
+ "d254f04097": "キャンセルする",
+ "265d956765": "{{value0}}。このページから離れても構いません。",
+ "d595295d7d": "{{value0}} は、リンクされたワークツリーから再利用できます。",
+ "34174bd83d": "{{value0}}。このページから離れても構いません。最後の結果は表示されたままになります。",
+ "433bb7f595": "わかりました",
+ "0ba046fbc5": "スキャンに失敗しました。",
+ "5c6d25720c": "検査するワークスペースを選択します。",
+ "c5135e7e4a": "ワークスペースのサイズをスキャンしています。このページから離れても構いません。",
+ "0990a63160": "スキャンされたワークスペースのサイズはまだありません。",
+ "977bdf9a36": "表示するトップレベルの項目はありません。",
+ "131662ac65": "{{value0}} オープン"
+ },
+ "ports": {
+ "status": {
+ "popover": {
+ "rows": {
+ "a49ea79246": "ワークツリーに移動",
+ "f2b813345f": "ワークスペースが利用できません",
+ "0e72c8d9fb": "プロセスの停止",
+ "536d48a5dc": "{{value0}}をコピー",
+ "085f4f0334": "ブラウザで開く",
+ "e4a709548c": "ポートの更新に失敗しました",
+ "acdb6df590": "{{value0}} でプロセスを停止しました",
+ "480d8f2347": "{{value0}} をコピーしました",
+ "b854ec9ff5": "ブラウザを開けませんでした"
+ }
+ }
+ }
+ },
+ "tooltip": {
+ "cedb7b99e3": "% 左",
+ "6d6df77f41": "利用可能なデータがありません",
+ "7f7f208060": "毎月",
+ "252c096536": "毎週",
+ "94038ad2fa": "セッション",
+ "2c35eca8d4": "使用状況を取得できません",
+ "1292d4f2ee": "利用不可",
+ "7567cd1c6b": "使用不可",
+ "a9a318b7a3": "更新に失敗しました - キャッシュされたデータが表示されています"
+ }
+ }
+ },
+ "stats": {
+ "ClaudeUsageDailyChart": {
+ "2a6360c7cb": "キャッシュ書き込み",
+ "61c58f8976": "キャッシュ読み取り",
+ "7d2efeff5e": "出力",
+ "d7fb787e6b": "入力",
+ "a7902d3c1d": "トークン",
+ "059945f71d": "日別の入力、出力、キャッシュ読み取り、およびキャッシュ書き込みの合計。",
+ "c9f7cd30e9": "毎日の使用量"
+ },
+ "ClaudeUsagePane": {
+ "21ea00bfa8": "キャッシュ",
+ "a8b7487ff7": "出力",
+ "faf3444859": "入力",
+ "0f03975d59": "ターン",
+ "1afc25eb06": "モデル",
+ "c17bed0416": "プロジェクト",
+ "01476891c7": "最後にアクティブだった",
+ "abfc4a4943": "キャッシュ再利用率:",
+ "7e76c84153": "最近のセッション",
+ "32176e1d44": "ターン",
+ "02a046792e": "セッション •",
+ "f97435845c": "トッププロジェクト:",
+ "7dc9e5613b": "プロジェクト別",
+ "c3fdbc5474": "最上位モデル:",
+ "0f394c24e3": "モデル別",
+ "51ae85fa00": "キャッシュの再利用率は、キャッシュ読み取りトークン / (入力トークン + キャッシュ読み取りトークン) として計算されます。",
+ "b26d4ddb58": "EST(東部基準時。 API相当コスト",
+ "0f3e696ca9": "セッション/ターン",
+ "8cc23be4a3": "ゼロキャッシュ読み取りターン",
+ "1634c4f404": "キャッシュ再利用率",
+ "b786fb4a70": "キャッシュ書き込み",
+ "268cf0af51": "キャッシュ読み取り",
+ "2b8a2f14aa": "出力トークン",
+ "ea71fae8fc": "入力トークン",
+ "7dde9331fd": "このスコープに対するローカル Claudeの使用法はまだ見つかりません。",
+ "424cd50412": "Claudeの使用状況分析を有効にする",
+ "8d18bbb771": "更新",
+ "c5b9b344d0": "リフレッシュClaudeの使用法",
+ "505be9aac4": "範囲",
+ "f61cffb9c8": "範囲",
+ "dd29209b21": "フィルター",
+ "e9bf9fce0e": "Claudeの使用オプション",
+ "6afacbee37": "Claudeの使用状況追跡",
+ "0cb1a36d7d": "ローカルのClaude使用ログを読み取り、トークン、モデル、セッションの統計を表示します。",
+ "5ce4842c2c": "すべてのローカル Claudeの使用法",
+ "4f8368c272": "Orca ワークツリーのみ",
+ "cfe2282ffa": "未知",
+ "7765a4c3e1": "該当なし",
+ "2d41fd45c6": "• 最終スキャン エラー: {{value0}}"
+ },
+ "CodexUsageDailyChart": {
+ "1e6f62d7e3": "推論",
+ "c646e1783c": "キャッシュされた入力",
+ "7b596a88b2": "出力",
+ "99a91d3143": "入力",
+ "e4bdcf0071": "トークン",
+ "c756cda6a8": "入力、キャッシュされた入力、出力、および推論の日ごとの合計。",
+ "609aa96e8b": "毎日の使用量"
+ },
+ "CodexUsagePane": {
+ "e0b988599d": "合計",
+ "bbd20344b8": "出力",
+ "3acc582214": "入力",
+ "bd0822ca47": "イベント",
+ "c2478bcc3c": "モデル",
+ "1a65900aea": "プロジェクト",
+ "0c36b100be": "最後にアクティブだった",
+ "0bd8655475": "このスコープ内の最新のローカル Codex セッション。",
+ "0cb0983c07": "最近のセッション",
+ "79a69522a5": "イベント",
+ "bf1bf2f674": "セッション •",
+ "829ee743f2": "トッププロジェクト:",
+ "b98718aaab": "プロジェクト別",
+ "95d2d89285": "最上位モデル:",
+ "5a0d1d69cd": "モデル別",
+ "94ac1f1ee7": "見やすくするために推論トークンが表示されていますが、コストはキャッシュされていない入力、キャッシュされた入力、および出力からのみ計算されます。",
+ "1a18fbd56b": "EST(東部基準時。 API相当コスト",
+ "907b31865f": "セッション/イベント",
+ "6e18146e9b": "推論出力",
+ "a9ac0f423a": "キャッシュされた入力",
+ "5d8eba87bd": "出力トークン",
+ "e365eaa6fd": "入力トークン",
+ "4c865393b4": "このスコープに対するローカル Codex の使用法はまだ見つかりません。",
+ "f7c1affbd5": "Codex の使用状況分析を有効にする",
+ "3022cda443": "更新",
+ "ec4d270e2c": "Codexの使用法を更新する",
+ "89162e019b": "範囲",
+ "6d68e8399a": "範囲",
+ "1af1a39b2f": "フィルター",
+ "70b5b8581f": "Codexの使用オプション",
+ "408210470c": "Codex使用状況の追跡",
+ "13badcd8f2": "ローカルの Codex 使用ログを読み取り、トークン、モデル、セッションの統計を表示します。",
+ "4fe8820098": "すべてのローカル Codexの使用法",
+ "201766b754": "Orca ワークツリーのみ",
+ "bf6cf2d4dd": "未知",
+ "ae255c3dba": "該当なし",
+ "247c93ca92": "• 推定価格",
+ "8a6655f7a2": "• 最終スキャン エラー: {{value0}}"
+ },
+ "OpenCodeUsagePane": {
+ "349f7c3f5c": "合計",
+ "dfc4513657": "出力",
+ "0f2f266c9d": "入力",
+ "d416f5cf92": "イベント",
+ "08c78441b7": "モデル",
+ "a4738de041": "プロジェクト",
+ "d97bdf6e27": "最後にアクティブだった",
+ "81817a641a": "このスコープ内の最新のローカル OpenCode セッション。",
+ "4799177b1c": "最近のセッション",
+ "1e5d410df0": "イベント",
+ "bc0cb89901": "セッション •",
+ "048ffe4d65": "トッププロジェクト:",
+ "0f0a1684bb": "プロジェクト別",
+ "a15206a63a": "最上位モデル:",
+ "040c044d39": "モデル別",
+ "e5bb23d85e": "コストは、アシスタント メッセージが記録したときにローカル OpenCode データベースから取得されます。",
+ "15c34d4b08": "記録コスト",
+ "7e9433469a": "セッション/イベント",
+ "5a65d68b77": "推論出力",
+ "603504ee3b": "キャッシュされた入力",
+ "7aa4d8ce35": "出力トークン",
+ "d637a892ed": "入力トークン",
+ "bb6363e08c": "このスコープではローカル OpenCode の使用法がまだ見つかりません。",
+ "f04131b3be": "OpenCode の使用状況分析を有効にする",
+ "603cd138dc": "更新",
+ "bed558df0b": "OpenCode の使用法を更新する",
+ "b5ed5c9fd0": "範囲",
+ "40d283c837": "範囲",
+ "01583b30aa": "フィルター",
+ "230d6de108": "OpenCode の使用オプション",
+ "bea80ceae0": "OpenCode の使用状況の追跡",
+ "b8b3522436": "ローカルの OpenCode 使用ログを読み取り、トークン、モデル、セッションの統計を表示します。",
+ "144a6050e9": "すべてのローカル OpenCode の使用法",
+ "e04c58327c": "Orca ワークツリーのみ",
+ "362231082f": "未知",
+ "8095a63426": "該当なし",
+ "6cc7782458": "• 最終スキャン エラー: {{value0}}"
+ },
+ "ShareUsageButton": {
+ "7d6b25323d": "Xで共有する",
+ "b295c1c75d": "画像をコピーする",
+ "bd82c76a70": "コピーされました",
+ "bce08eccb9": "共有の使用状況",
+ "cecefa7c32": "共有"
+ },
+ "ShareUsageCard": {
+ "4a4c6c79a3": "セッション ·",
+ "66c83284cf": "デイリートークン",
+ "b760c0b622": "最上位モデル",
+ "2d9eb39264": "総トークン数",
+ "beb6f24f37": "EST(東部基準時。料金",
+ "da62578d9d": "使用法",
+ "0eb31e79ee": "OrcaIDE",
+ "960324e9b8": "イベント",
+ "6adac63cfe": "ターン"
+ },
+ "StatsPane": {
+ "42d3e0bdf7": "使用状況分析プロバイダー: {{value0}}",
+ "c79f073d4c": "使用状況分析",
+ "a58aba506f": "作成された PR",
+ "1c96f433e2": "エージェント作業時間",
+ "9dbec9e675": "エージェントが生成されました",
+ "73ed07859c": "最初のエージェントを起動して追跡を開始します",
+ "1e696db2f6": "OpenCode",
+ "7d26110cea": "Codex",
+ "85457c02fe": "Claude",
+ "b2cf4310ce": "概要",
+ "908c470587": "codex",
+ "eb6a066185": "claude",
+ "eee19cfade": "概要"
+ },
+ "UsageOverviewPane": {
+ "22ed1b7669": "セッション",
+ "444585cb41": "データ付き",
+ "ecb0cd8a4c": "有効 -",
+ "33f7b043d2": "プロバイダー",
+ "60002bb22f": "ローカルの Claude、Codex、または OpenCode の使用法はまだ見つかりません。概要は、次のエージェント セッションがトークン ログを書き込んだ後に表示されます。",
+ "70f36452d4": "キャッシュシェア",
+ "327603fe8b": "アクティブ日数",
+ "0eaf937335": "EST(東部基準時。料金",
+ "3887b94ce5": "総トークン数",
+ "2d13e57f72": "OpenCodeを有効にする",
+ "2f1ee2878b": "Codexを有効にする",
+ "0ea0cae435": "Claudeを有効にする",
+ "6c00c46815": "プロバイダーがローカル エージェント ログをスキャンし、結合されたトークン台帳を構築できるようにします。",
+ "49405ccc8d": "トークンの追跡を開始する",
+ "ca6bc5fded": "更新",
+ "e06d1baf5c": "リフレッシュの使用法の概要",
+ "c760c481c5": "使用方法の概要",
+ "55c910f4f1": "- 一部のモデルの価格は利用できません"
+ },
+ "share": {
+ "card": {
+ "utils": {
+ "19f4b4dc75": "github.com/stableai/orca",
+ "d864fc5f98": "出力",
+ "5d66fdd7c2": "入力",
+ "7080aeaebb": "推論",
+ "4ee864629a": "キャッシュされた入力",
+ "33d38e2177": "出力",
+ "c2d7b23d57": "入力",
+ "9d166247ee": "キャッシュ書き込み",
+ "cc28cb965e": "キャッシュ読み取り"
+ }
+ }
+ },
+ "stats": {
+ "search": {
+ "cb6a9f0334": "キャッシュ",
+ "eaf251e183": "トークン",
+ "6953af58e6": "opencode",
+ "b77826fca3": "codex",
+ "e9dc37d889": "claude",
+ "8efeae0b22": "トラッキング",
+ "5acbe1fdf2": "時間",
+ "ef8bbf7739": "PRs",
+ "ce8533f02e": "エージェント",
+ "0bba8ca244": "統計",
+ "0e2a0b6431": "使用法",
+ "372debfac0": "統計",
+ "26bb901fcd": "Orca の統計に加え、Claude、Codex、OpenCode の使用状況分析、トークン、キャッシュ、モデル、セッションを組み合わせたもの。",
+ "cb2430ae6a": "統計と使用状況"
+ }
+ },
+ "usage": {
+ "overview": {
+ "model": {
+ "bc474051e5": "OpenCode",
+ "eb220d193b": "Codex",
+ "544d6d4c16": "Claude"
+ },
+ "sections": {
+ "9564a3b21b": "セッション -",
+ "32330a6e66": "{{value0}}: {{value1}} トークン",
+ "57d1448ef8": "有効化",
+ "f6df0d7d6d": "もっと",
+ "1dd166c920": "少ない",
+ "52d9221dc0": "最近のトークンアクティビティのヒートマップ",
+ "c424eb3f8e": "最高:",
+ "f28ff1f852": "最近のClaude、Codex、および OpenCode トークン アクティビティの組み合わせ。",
+ "69e2b50427": "毎日の強度",
+ "3a795542fa": "組み合わせたトークンミックス",
+ "e65084cb4b": "推論",
+ "3bc4a01b24": "有効なプロバイダー間で結合された入力、出力、およびキャッシュ トークン。",
+ "4ff104da47": "トークンミックス",
+ "0015facc1f": "キャッシュ",
+ "7f270458af": "出力",
+ "9365b14a4e": "新規入力",
+ "3de9bf87fc": "まだモデルがありません"
+ }
+ }
+ }
+ },
+ "sparse": {
+ "SparseCheckoutPresetSelect": {
+ "c4ac80151d": "新規プリセット",
+ "7c3275d307": "{{value0}}を編集",
+ "c7f9b3f0c1": "オフ",
+ "8b12c0850a": "保存",
+ "de8fce5854": "キャンセル",
+ "ddbcaef7be": "src/レンダラーパッケージ/ui",
+ "0e9ad9c798": "ディレクトリ",
+ "064c1e2d12": "レンダラUI",
+ "b3a500c623": "名前",
+ "16223dde6a": "プリセットをロードする",
+ "a683a4bc8e": "プリセットの読み込みを再試行",
+ "14952d451e": "{{value0}} ディレクトリ",
+ "e9283eb171": "1 ディレクトリ",
+ "69c020eddc": "プリセットの編集",
+ "bd6cec2056": "新規"
+ }
+ },
+ "source": {
+ "control": {
+ "SourceControlActionVariableChips": {
+ "1b77798d5f": "変数",
+ "6b921a0ac2": "例",
+ "4bf6d88039": "(空の)"
+ }
+ }
+ },
+ "skills": {
+ "SkillsPage": {
+ "cb142070b4": "更新",
+ "984405683f": "プラグイン",
+ "4d177feabd": "同梱",
+ "aa59462502": "リポジトリ",
+ "571c5818c1": "家",
+ "0bc1379f4c": "すべてのソース",
+ "38e0951c3a": "エージェントのスキル",
+ "fb6bf60b52": "Claude",
+ "426be2aac6": "Codex",
+ "39b6998ddb": "すべてのプロバイダー",
+ "a68dee6a32": "スキルを検索",
+ "e46e162e2e": "から",
+ "b088e0785d": "ベータ",
+ "f43ad6edf3": "スキル",
+ "7e828fb2c6": "戻る",
+ "ea72d6185b": "ローカルスキルをスキャンできませんでした",
+ "dc4c3328ee": "ファイルを公開する",
+ "9963dff6d3": "説明が見つかりませんでした。",
+ "995fde8337": "スキルファイルを公開できませんでした",
+ "ab5b777350": "ローカル ホーム、リポジトリ、バンドル、プラグイン スキル フォルダを確認しました。",
+ "08a321a984": "検索またはフィルターを調整します。",
+ "4acd6d68ec": "ローカルスキルが見つかりません",
+ "6a62a0168c": "一致しません",
+ "cd7893fbc1": "スキャンスキル",
+ "35b9a724a0": "利用可能",
+ "0c74e7ff34": "地元"
+ }
+ },
+ "sidebar": {
+ "AddProjectFromFolderDialog": {
+ "7d1f51678c": "プロジェクトを追加",
+ "7726a16374": "キャンセル",
+ "046751dbfb": "このフォルダーを別の Orca プロジェクトとして追加します。",
+ "e643b30398": "リモートプロジェクトが追加されました"
+ },
+ "AddRepoCreateStep": {
+ "0ae45b8238": "私のプロジェクト",
+ "a8149a3a5a": "名前",
+ "038729c107": "フォルダ",
+ "11fd2a7db8": "Gitリポジトリ",
+ "180e9b5e48": "プロジェクトの種類",
+ "d877ece0d6": "Git リポジトリまたはプレーン フォルダーを作成し、Orca で開きます。",
+ "db9be12229": "新規プロジェクトを開始する",
+ "5e97f0c4b9": "プロジェクトが作成されました",
+ "2c12db1511": "プロジェクトはすでに追加されています",
+ "875dda0995": "サーバーの親パスを入力します。",
+ "45b7c26034": "プロジェクトの作成",
+ "85085d74d2": "作成…"
+ },
+ "AddRepoNestedImportStep": {
+ "496f68cf8c": "リポジトリをスキャンしています。クリックして停止します。",
+ "a32bef9516": "スキャンを停止する",
+ "2f8298f3c3": "スキャンの停止",
+ "c157f31a95": "グループとしてインポート",
+ "40199ef7b3": "グループ名",
+ "b20bb7c24f": "これらのリポジトリを 1 つのグループにまとめます。マイクロサービスなどの関連リポジトリに最適です。",
+ "787412361a": "グループ名とは何ですか?",
+ "5f857ba8e6": "で",
+ "4df0d08cc5": "見つかった",
+ "8db50afe1a": "フォルダーからリポジトリをインポートする",
+ "5b2e6fe3c8": "個別にインポート",
+ "cf9d382ca1": "輸入",
+ "220dd32d83": "走査..."
+ },
+ "AddRepoRemoteStep": {
+ "5b205b5281": "スキャンの停止",
+ "6680289908": "/ホーム/ユーザー/プロジェクト",
+ "ef410aa881": "リモートパス",
+ "0416bde073": "設定を追加",
+ "df6fbcf880": "SSH ターゲットが構成されていません。",
+ "44637f43bd": "SSHターゲット",
+ "80557be85a": "接続されている SSH ターゲットを選択し、Git リポジトリへのパスを入力します。",
+ "91b93a90a4": "リモートプロジェクトを開く",
+ "007651bdf9": "ディレクトリに移動し、「選択」をクリックして選択します。",
+ "dd3ff65486": "リモートファイルシステムを参照する",
+ "36d427bb66": "リモートプロジェクトを追加",
+ "35831a7312": "追加中..."
+ },
+ "AddRepoServerStartStep": {
+ "ae990c86a0": "オプションの追加に戻る",
+ "e1710bf831": "フォルダーとして開く",
+ "8da4d1a5be": "Gitプロジェクトの追加",
+ "ac66a3ed2d": "サーバーのファイルシステムを参照する",
+ "92d25420a0": "/ホーム/ユーザー/プロジェクト",
+ "867692f505": "サーバーパス",
+ "423b5d3d31": "選択したランタイム サーバーに既に存在する Git リポジトリまたはフォルダーを追加します。",
+ "3d0c035483": "サーバープロジェクトを開く",
+ "438493f214": "またはサーバーのパスを手動で入力します",
+ "6b9958492a": "一度に多くのリポジトリをインポートしたいですか?親フォルダーを参照します。",
+ "d40d751517": "新規リポジトリまたはフォルダー",
+ "a81ffa0a99": "サーバー上に作成する",
+ "a2ea37d549": "リモート Git リポジトリ",
+ "47759c9491": "URLからクローンを作成する",
+ "516187414c": "既存のプロジェクトまたはフォルダー",
+ "0adf083af7": "サーバーを参照する",
+ "8efa930eb5": "選択したランタイム サーバーから別のプロジェクトを追加します。",
+ "39bd249b3a": "プロジェクトを追加する",
+ "0f8aba944c": "ディレクトリに移動し、「選択」をクリックして選択します。"
+ },
+ "AddRepoStartSteps": {
+ "f3c96237ae": "または…から追加します",
+ "acf895cb42": "Orca の使用を開始するには、プロジェクトを追加します。",
+ "d13757911c": "プロジェクトを追加する",
+ "d301db1c9a": "リポジトリをスキャンしています。クリックして停止します。",
+ "69ea7f8dc4": "スキャンを停止する",
+ "9906cae183": "スキャンの停止"
+ },
+ "AddRepoStepIndicator": {
+ "3bb655c117": "戻る"
+ },
+ "AddRepoSteps": {
+ "569326d9cc": "フォルダーを選択",
+ "a93ef169b5": "サーバーのファイルシステムを参照する",
+ "2ce3f6edf8": "/パス/宛先/宛先",
+ "04a4c4e84a": "クローンの場所",
+ "b698a4a29d": "https://github.com/user/repo.git",
+ "3d4acbe693": "Git URL",
+ "5b2ea674b1": "Git URL を入力し、クローンを作成する場所を選択します。",
+ "c05f88a31f": "URLからクローンを作成する",
+ "fe8e629fe3": "ディレクトリに移動し、「選択」をクリックして選択します。",
+ "df8b0e6c22": "リモートプロジェクトが追加されました",
+ "3e64e8a70d": "接続に失敗しました",
+ "32a7256d85": "クローン",
+ "69f5b5380d": "クローン作成中..."
+ },
+ "AutoRenameFailedDialog": {
+ "aed1623b1e": "閉じる",
+ "eab8b45238": "コピーエラー",
+ "a23b22d16f": "コピーされました",
+ "74fc00776f": "エラーの詳細",
+ "3afcad0497": "最初のエージェントメッセージから。",
+ "ff62a18580": "Orca はブランチ名を生成できませんでした",
+ "ca3b225195": "ブランチの自動名前付けに失敗しました"
+ },
+ "CreateProjectLocationField": {
+ "95548e33bf": "親フォルダーを選択...",
+ "632b456b1b": "変化",
+ "afaf54f245": "親フォルダーを変更する",
+ "f520f83a97": "サーバーのファイルシステムを参照する",
+ "2a20a603a3": "/ホーム/ユーザー/プロジェクト",
+ "134e37f711": "位置",
+ "b589b77997": "ディレクトリに移動し、「選択」をクリックして選択します。"
+ },
+ "DeleteWorktreeDialog": {
+ "ff2a74ac0e": "そして",
+ "91492c9ad6": "削除",
+ "4f6750ca7b": "ワークスペースの削除に失敗しました",
+ "42e610d6cf": "強制削除に失敗しました",
+ "5cc1a6701c": "設定を開く",
+ "2b56b35f53": "これは設定で変更できます。",
+ "dd3a45bbbd": "次回からはこの確認は省略させていただきます。",
+ "fc23c4cbdf": "ワークスペースの削除",
+ "86f0ae1257": "ワークスペースの削除"
+ },
+ "DeleteWorktreeDirtyChangeHint": {
+ "8e2994ce28": "このワークスペースを削除すると、これらの変更がディスクから完全に削除されます。"
+ },
+ "DeleteWorktreeLineageNotice": {
+ "ad407c2d55": "もっと",
+ "a940f3c96e": "子ワークスペースは削除されます",
+ "29b98bf9cd": "このワークスペースを削除すると、{{value0}} 子ワークスペースも削除されます。",
+ "66798cc6a2": "このワークスペースを削除すると、子ワークスペースも 1 つ削除されます。"
+ },
+ "DeleteWorktreeSkipConfirmOption": {
+ "29aefb7e52": "二度と聞かないでください"
+ },
+ "DeleteWorktreeWarningPanels": {
+ "026738155a": "(元のクローン ディレクトリ)。",
+ "c4f96a6e18": "メインワークツリー",
+ "e3be9eba15": "これは、"
+ },
+ "ImportedWorktreesVisibilityLine": {
+ "b7a87dc32f": "ワークツリーリストに表示",
+ "ad99f4eea9": "隠しておく",
+ "9f4f14e821": "これは後でプロジェクト メニューから変更します。",
+ "b2bc47c080": "さらに多くの場所",
+ "b47ba1a9d2": "{{value0}} プレビュー",
+ "2251d41ebb": "非表示のワークツリー グループ",
+ "f54f2bec5d": "{{value0}} {{value1}} の非表示ワークツリー",
+ "5a9688802a": "{{value0}} をもっと見る",
+ "294de4aeb2": "表示数を減らす"
+ },
+ "NonGitFolderDialog": {
+ "e52454b7f6": "フォルダーとして開く",
+ "05b33a17a9": "キャンセル",
+ "8fba4b8cbb": "このフォルダーは Git リポジトリではありません。エディター、ターミナル、検索は利用できますが、Git ベースの機能は利用できません。",
+ "c49fb13492": "リモートフォルダーの追加に失敗しました"
+ },
+ "OrcaYamlTrustDialog": {
+ "f3e2b868fb": "フックを実行する",
+ "43b7bec4cd": "走らないで",
+ "c494b3ccb1": "で",
+ "79afc6772b": "orca.yaml",
+ "531689199b": "常に信頼する",
+ "bf800b7e04": "。信頼できる場合のみ実行してください",
+ "831f2cd9f0": "あなたのマシン上で動作します",
+ "aa3ffb33fb": "このリポジトリの",
+ "c55beddbf8": "最後に承認してから変更されました。実行前に再確認する",
+ "95bf974a1a": "{{value0}} スクリプト",
+ "9e52effffd": "新規{{value0}}スクリプト",
+ "e4a51dc4b3": "{{value1}} から {{value0}} を実行しますか?",
+ "02b0ede5ad": "{{value0}} の {{value1}} が変更されました — 新規バージョンを実行しますか?"
+ },
+ "PendingWorktreeRow": {
+ "af21e953d1": "ワークツリーの作成をキャンセルする",
+ "188f6922a0": "キャンセル"
+ },
+ "ProjectGroupDeleteDialog": {
+ "ca65b78f78": "キャンセル",
+ "9be10d49ea": "そしてプロジェクトのグループ化を解除します。",
+ "69f5cb97d0": "削除",
+ "591f330288": "プロジェクトグループの削除",
+ "2c14ce677a": "削除中..."
+ },
+ "ProjectGroupNameDialog": {
+ "d99a034073": "キャンセル",
+ "83dfbc5313": "グループ名",
+ "4a64e78822": "保存中..."
+ },
+ "RemoteFileBrowser": {
+ "2300612806": "フィルタリングするために入力するか、パスを入力します…",
+ "9e060f5815": "フォルダを選択",
+ "f8b1deb1a4": "キャンセル",
+ "51001182e3": "空のディレクトリ",
+ "971d85cc84": "リモート プロジェクトとして開きます · {{value0}}",
+ "00c4235c10": "「{{value0}}」に一致するものはありません"
+ },
+ "RemoveFolderDialog": {
+ "4dc5b5065b": "削除",
+ "d36883e046": "キャンセル",
+ "8c097ef04e": "Orcaから。それはまだディスク上にあります。",
+ "e62415c3d0": "これは削除するだけです",
+ "b79b39d865": "プロジェクトの削除"
+ },
+ "ScrollToCurrentWorkspaceToolbarButton": {
+ "23989bb663": "アクティブなワークスペースを表示する"
+ },
+ "SetupGuideSidebarEntry": {
+ "b0a7bfc34c": "サイドバーから隠す",
+ "88d402b71d": "オンボーディングチェックリスト"
+ },
+ "SetupScriptPromptCard": {
+ "ff1e819a11": "セットアップスクリプトを追加する",
+ "70715947fb": "セットアップ スクリプトを空にすることはできません",
+ "888b83bf78": "セットアップ スクリプトの保存に失敗しました",
+ "a49196d538": "Orca が新規ワークツリーを作成するときに実行されます。",
+ "d9f2db2738": "プロジェクトの設定",
+ "a5bb8c5135": "これに保存されました",
+ "dcaa645da5": "わかりました"
+ },
+ "SetupScriptPromptCardViews": {
+ "96a7f4198c": "ローカル設定を保存する",
+ "3933401d28": "設定する",
+ "31b8b01a45": "設定",
+ "4a98f907ae": "再試行",
+ "0a98169776": "Orca が新規ワークツリーを作成するときに実行するセットアップ コマンドを追加します。",
+ "8349e3fa4c": "。新規ワークツリーに対して実行するために保存します。",
+ "b56d1322f7": "セットアップコマンドが見つかりました",
+ "aef6c0a213": "Orca がワークツリーを作成するたびに実行できるように、検出されたコマンドを保存します。",
+ "660cdc17f8": "セットアップスクリプト。ローカル コマンドを追加するか、設定でソースを変更します。",
+ "8f6be51aa1": "orca.yaml",
+ "bb879db364": "このリポジトリは共有を無視します",
+ "0155fb9ed3": "現在、このリポジトリのセットアップ スクリプトを確認できませんでした。",
+ "eefa756190": "手動で構成する",
+ "ca4efcbc25": "保存",
+ "d02e6a42b1": "から検出されました",
+ "fdbc6cb064": "検出されたセットアップ スクリプト",
+ "7275f674cc": "検出されたセットアップ",
+ "822ff300ad": "閉じる",
+ "5bfd5c8779": "セットアップスクリプトを閉じる"
+ },
+ "SidebarFeedbackDialog": {
+ "8bf619e4cf": "キャンセル",
+ "8de03e23c5": "入力したフィードバックのみを送信するか、「gh」に接続して GitHub ID を含めます。",
+ "d20439c560": "GitHub ID を確認しています…",
+ "5b120b9634": "匿名で送信",
+ "c9e5ea0791": "GitHub:",
+ "d46ddd66fc": "何を改善できるでしょうか?",
+ "3460258a54": "Xをフォロー",
+ "26108d3699": "Discord に参加",
+ "d245c4ef6c": "GitHub イシュー",
+ "9b33530b3d": "その他の連絡方法",
+ "a828fa4aee": "何が機能しているのか、何が壊れているのか、Orca が次に何をすべきかを共有します。",
+ "0eb643f07f": "フィードバックを送信する",
+ "60b721e857": "フィードバックの送信に失敗しました。もう一度試す。",
+ "7a46c228b8": "フィードバックありがとうございます。",
+ "a2fd890d9e": "送信する前にフィードバックを入力。",
+ "f2e42e1307": "送信",
+ "69969ba364": "送信中…"
+ },
+ "SidebarFilter": {
+ "e3b3898218": "プロジェクトの追加",
+ "92a23e6d07": "フィルターをリセットする",
+ "81ded53722": "SSH",
+ "b9e8802e73": "一致するプロジェクトはありません",
+ "779b7ba05d": "クリア",
+ "139877b384": "すべて選択",
+ "5f7085a077": "プロジェクト",
+ "e5cb32a898": "デフォルトのブランチを非表示にする",
+ "638a2d221d": "スリープ中を非表示",
+ "f506a1262a": "ワークスペースのフィルタリング",
+ "75405270ed": "フィルターの編集 ({{value0}} がアクティブ)",
+ "489d1c8c9f": "プロジェクトを検索...",
+ "ee240a39eb": "フィルターの編集"
+ },
+ "SidebarHeader": {
+ "92154beb7e": "新規ワークスペース",
+ "49f62c5665": "ワークスペースボード",
+ "5c9c7c16aa": "プロジェクトを追加してワークスペースを作成する",
+ "ca6f729da2": "新規ワークスペース ({{value0}})",
+ "a30e34eb5c": "ワークスペースボードを閉じる"
+ },
+ "SidebarNav": {
+ "80611a8b10": "検索",
+ "0c3395fd32": "ワークツリーとブラウザタブを検索する",
+ "c86d83b5c3": "新規",
+ "1b5c41caee": "Orcaモバイル",
+ "9c95e1ce91": "エージェント",
+ "f323383e9a": "自動化",
+ "e7ad3c540d": "Jira タスクを開く",
+ "c39ab10000": "Linear タスクを開く",
+ "196c1b5362": "GitLab タスクを開く",
+ "0ccba862b8": "GitHub タスクを開く",
+ "fee535205b": "タスク",
+ "d599269755": "サイドバーから隠す"
+ },
+ "SidebarRepositoryFilterSection": {
+ "d3a9c4cea1": "クリア",
+ "7679f0c268": "プロジェクト",
+ "f10ca29601": "{{value0}} フィルターを削除します",
+ "2656053db4": "SSH",
+ "83a820fa71": "プロジェクトをフィルタリング...",
+ "5a273fbfce": "プロジェクトを追加...",
+ "4815c70605": "一致するプロジェクトはありません",
+ "bbbc6e8e3b": "選択されていないプロジェクトは一致しません"
+ },
+ "SidebarSettingsHelpMenu": {
+ "ad3d3ed7f1": "Orca を再起動",
+ "29c56f30ee": "アップデートをチェックする",
+ "eb9884e55b": "Discord",
+ "5687ab246a": "GitHub",
+ "5f83d86d92": "変更履歴",
+ "cdc87f897e": "ドキュメント",
+ "e565171a7c": "キーボードショートカット",
+ "4cf5b868d7": "フィードバックを送信する",
+ "a428c25998": "設定",
+ "2991a0106c": "ヘルプ",
+ "4e8f5710d3": "Orca を再起動できませんでした。",
+ "5161eef55d": "Orca を再起動しています…",
+ "d396773ef0": "チェック中"
+ },
+ "SidebarToolbar": {
+ "19e32d0e5f": "フォルダーピッカーを開いてプロジェクトを追加します",
+ "abc62b6328": "プロジェクトを追加"
+ },
+ "SidebarWorkspaceFilterSection": {
+ "c3fa13dc2e": "デフォルトのブランチを非表示にする",
+ "ed1611b65b": "スリープ中を非表示",
+ "82594419ba": "フィルター"
+ },
+ "SidebarWorkspaceOptionsMenu": {
+ "95c9754653": "エージェントアクティビティのレイアウト",
+ "3d4b9c4997": "ホバー",
+ "ba87080fb7": "プロパティを表示する",
+ "320b675c9a": "カードのレイアウト",
+ "09faabd875": "プロジェクトの順序",
+ "7bada3b1ab": "並べ替え",
+ "dc0bb670bc": "グループ化",
+ "9919ae1082": "ワークスペースのオプション",
+ "bc96dbd041": "ワークスペース オプション ({{value0}})",
+ "af9249c505": "最新のワークスペースアクティビティ",
+ "b451c8b162": "最近の",
+ "6664282a7b": "プロジェクトをドラッグして配置します",
+ "7b316bdd51": "マニュアル",
+ "7153d07485": "ワークスペースをドラッグして、各グループ内に配置します。",
+ "2170d553cf": "プロジェクト",
+ "b759bb87ee": "注意が必要なエージェント、次に最新のアクティビティ。",
+ "503462f2b4": "エージェントのアクティビティ",
+ "3728165cdd": "名前",
+ "2a81e07366": "完全なリスト",
+ "25105b28cb": "コンパクト",
+ "d7084e8bc8": "エージェントのアクティビティ",
+ "b64d8bcca0": "ポート",
+ "26c71e536c": "注意事項",
+ "b8dcc6f321": "PR/MRリンク",
+ "ca4d3c522e": "Linear イシュー",
+ "91dfc653e8": "GitHub チケット",
+ "cc17bd443b": "詳細",
+ "0f9b959b31": "PR",
+ "e029a2d775": "状態",
+ "c2c7a45cda": "なし",
+ "680043342f": "コンパクト",
+ "c7591b6014": "リポジトリ"
+ },
+ "SshDisconnectedDialog": {
+ "ca4a7892af": "接続中...",
+ "89385db176": "閉じる",
+ "656368f3a2": "再接続に失敗しました",
+ "376bed88e5": "リモート ホストへの接続でエラーが発生しました。",
+ "4afcca1d24": "再接続",
+ "11552bf786": "SSHが切断されました",
+ "cb5938ae79": "再接続中..."
+ },
+ "SshTargetRow": {
+ "4677394048": "接続中…",
+ "75ad429b5d": "接続"
+ },
+ "WorkspaceKanbanCard": {
+ "cefae8983e": "固定された"
+ },
+ "WorkspaceKanbanDrawerHeader": {
+ "f369f5c5a3": "閉じる",
+ "e1a34450fc": "ワークスペースをステータスごとに整理し、ワークスペース カードを開きます。",
+ "81870af08f": "選択された",
+ "c6a77ab0f4": "ワークスペースボード"
+ },
+ "WorkspaceKanbanPinDropTarget": {
+ "c30151c5ee": "ここにドロップすると、ステータスを変更せずにピンを固定できます。",
+ "8fae2d0862": "固定された"
+ },
+ "WorkspaceKanbanSettingsMenu": {
+ "79eb990aa4": "ステータスの追加",
+ "054cb50df7": "{{value0}} を削除",
+ "b45b350eb0": "{{value0}} を左に移動",
+ "8ce44af9a8": "{{value0}} の名前を変更",
+ "395e541d5d": "ステータス",
+ "34f03eb0de": "ボードの設定",
+ "26cbc92150": "ワークスペースボードの設定"
+ },
+ "WorkspaceKanbanStatusLane": {
+ "8ad104642b": "空の",
+ "3611d1ae7f": "ワークスペースボードの列のサイズを変更する"
+ },
+ "WorkspaceStatusAppearancePopover": {
+ "514be2f569": "{{value0}} の色を {{value1}} に設定します",
+ "8be427206b": "アイコン",
+ "2ac106f6b2": "色",
+ "74b1413279": "外観",
+ "ccbd1e2c69": "{{value0}} の外観をカスタマイズする"
+ },
+ "WorktreeCard": {
+ "a88c92d0e3": "すでに存在します。",
+ "6f09f58541": "ワークスペースの削除",
+ "0777de5970": "プライマリ ワークツリー (元のクローン ディレクトリ)",
+ "0f33af979b": "部分的なチェックアウト。これらのパスの外にあるファイルはディスク上にありません。",
+ "4f964d5e8c": "まばらな",
+ "7d517f82e2": "主要な",
+ "c6833b5187": "最初のエージェントメッセージから名前が変更されます",
+ "f62a3dadbc": "名前変更が保留中",
+ "4eba2ea99e": "自動名前付けに失敗しました。クリックすると詳細が表示されます。",
+ "74522ee457": "名前の変更に失敗しました",
+ "02e19349f4": "名前の自動変更に失敗しました: 表示エラー",
+ "691ccfd622": "削除中…",
+ "35ccfe2475": "プロジェクト{{value0}}",
+ "1d66d84f0b": "文字列",
+ "57eaa61b55": "子ワークスペースを非表示にする",
+ "8cb634cda6": "子ワークスペースを表示する",
+ "01f45d3d8a": "サイドバー",
+ "93aebe4529": "フォルダ",
+ "0d224eff10": "プライマリワークツリー",
+ "ca74db7550": "SSH経由のリモートプロジェクト",
+ "021538e1d1": "SSHが切断されました"
+ },
+ "WorktreeCardAgents": {
+ "1b0a156717": "エージェント"
+ },
+ "WorktreeCardMeta": {
+ "3e65e11cc6": "ワークスペースのメタデータ",
+ "c7fa72ead0": "メモを編集する",
+ "93cbea12c2": "注意事項",
+ "eace1d2cf6": "中性",
+ "dbe2d18972": "その他の {{value0}} 操作",
+ "ae76907ca6": "{{value0}} のリンクを解除",
+ "ad25c3ff05": "{{value0}} で見る",
+ "2c67730e07": "Orcaでオープン",
+ "e42941631a": "Linearで見る",
+ "5e982e6128": "Linear {{value0}}",
+ "807b13b9ec": "イシューを編集する",
+ "b22f058067": "GitHub で見る",
+ "e97d8f2876": "イシュー #{{value0}}",
+ "3ea2702e62": "リンク済み {{value0}} #{{value1}}",
+ "b105fd3057": "リンクLinear {{value0}}",
+ "3f2649eeb8": "リンクされたイシュー #{{value0}}",
+ "fe075cb851": "ワークスペースのメモ"
+ },
+ "WorktreeCardMetadataStatusBadges": {
+ "fe188062a1": "状態: オープン",
+ "2931b42b09": "状態: ドラフト {{value0}}",
+ "e888362def": "状態: 閉店",
+ "f394b3e86e": "状態: 結合済み",
+ "af2b07bda5": "状態: {{value0}}",
+ "29df45afa2": "MR"
+ },
+ "WorktreeCardPorts": {
+ "34f733dda2": "ワークツリーに移動",
+ "3240f320d7": "ライブポート",
+ "3e5f66564e": "ワークスペースが利用できません",
+ "2f854442ff": "プロセスの停止",
+ "c8067a829a": "{{value0}}をコピー",
+ "33bc7d7495": "ブラウザで開く",
+ "9950fe2d20": "ポートの更新に失敗しました",
+ "5d1a5d51bb": "{{value0}} でプロセスを停止しました",
+ "c89f290e25": "{{value0}} をコピーしました",
+ "d1113f4660": "ブラウザを開けませんでした",
+ "fed49903c9": "{{value0}} ライブ {{value1}}"
+ },
+ "WorktreeContextMenu": {
+ "c39c37676a": "グループを作成し、このプロジェクトをそのグループに移動します。",
+ "6664418e98": "新規プロジェクトグループ",
+ "e091caab15": "プロジェクトが見つかりませんでした",
+ "439fa94d53": "アップデート",
+ "579b1a8e61": "親から削除",
+ "8d9cd19d09": "親ワークスペースを開く",
+ "d35dfeae58": "グループから削除",
+ "76865d827f": "グループに移動",
+ "503ec0f8e6": "プロジェクトからの新規グループ",
+ "3350101edb": "パスのコピー",
+ "f4475537d8": "削除",
+ "f5ac91531d": "Orca からプロジェクトを削除",
+ "b42391d8bf": "削除中…",
+ "0918b35e4f": "このワークスペース内のアクティブなパネルをすべて閉じて、メモリと CPU を解放します。",
+ "7d190f7d2b": "選択したワークスペース内のアクティブなパネルをすべて閉じて、メモリと CPU を解放します。",
+ "84cdbb7e30": "ステータスに移動",
+ "56cde9e8e6": "ステータスの移動先",
+ "f50603c6b2": "未読としてマークする",
+ "8dacff1fe0": "既読マークを付ける",
+ "3baa7d6507": "ピン",
+ "697d0f6e1b": "固定を解除する"
+ },
+ "WorktreeList": {
+ "d880ea0744": "グループを作成し、このプロジェクトをそのグループに移動します。",
+ "bc1460beb3": "サイドバーに表示されるグループ名を更新します。",
+ "13757c053c": "新規プロジェクトグループ",
+ "f9dc6cc5d3": "プロジェクトグループの名前を変更",
+ "370c6a55dd": "フィルターをクリアする",
+ "b7acbf038b": "ワークスペースが見つかりません",
+ "0c6ee14f23": "子供",
+ "5fc9d1891b": "削除中…",
+ "c83968f87f": "プロジェクトの削除",
+ "64e55f7f01": "グループから削除",
+ "4a08fb55f2": "グループに移動",
+ "cbfd565f83": "プロジェクトからの新規グループ",
+ "e82d3589a1": "プロジェクトアイコンの変更",
+ "2cdffbc728": "プロジェクト設定",
+ "2ef41bf9a7": "プロジェクトの操作",
+ "609633a9e6": "{{value0}} のプロジェクト操作",
+ "902115cdbe": "グループの削除",
+ "4d7b73658c": "グループ名の変更",
+ "79465e9034": "{{value0}} のグループ操作",
+ "bfbedc547b": "ワークツリー",
+ "45fbfe0335": "名前を変更する",
+ "ebc5c7dcef": "子ワークスペースを非表示にする",
+ "84a2238242": "子ワークスペースを表示する",
+ "045a8aed48": "子供たち",
+ "2ca6e29a3c": "リポジトリ",
+ "bb85cd86ba": "{{value0}} のワークスペースを作成する"
+ },
+ "WorktreeMetaDialog": {
+ "3db0a2a593": "キャンセル",
+ "b48c271d39": "保存するには、Shift+Enter を押して新規行を入力します。",
+ "7f0be5e9a6": "**マークダウン** - 太字、リスト、「コード」、リンクをサポートします。 Enterを押すか、",
+ "030d484fc0": "このワークツリーに関するメモ...",
+ "9c1d1e9b71": "コメント",
+ "5ae06f40fd": "PRの URL を貼り付けるか、番号を入力します。リンクを削除するには空白のままにします。",
+ "077a4f7b5c": "PR 番号または GitHub URL",
+ "1b91db7e14": "GH PR",
+ "7c454be4c5": "イシューの URL を貼り付けるか、番号を入力します。リンクを削除するには空白のままにします。",
+ "029ea5ec57": "GitHub イシューを開く",
+ "741279e7b7": "イシュー番号または GitHub URL",
+ "645fa4a0fd": "GH イシュー",
+ "459ad7f650": "サイドバーに表示される名前のみが変更され、ディスク上のフォルダーは変わりません。ブランチ名またはフォルダー名を使用する場合は、空白のままにします。",
+ "7f21e0464f": "カスタム表示名...",
+ "ad5e4e514f": "表示名",
+ "65770ad0f0": "このワークスペースの GitHub リンクとメモを編集します。",
+ "382fd11a3e": "ワークツリーの詳細の編集",
+ "2174f17011": "保存",
+ "61d6f612cf": "保存中..."
+ },
+ "WorktreeOpenInMenu": {
+ "1417fd8380": "アプリをカスタマイズ...",
+ "8009ab69a6": "で開く",
+ "bd0e8159f8": "このマシン上のエディター コマンドまたはファイル マネージャーの構成を確認してください。",
+ "9a5381eb09": "ワークスペースフォルダーを開けませんでした。",
+ "0bed8727db": "移動または削除された可能性があります。ワークスペースを更新するか、Orca からワークスペースを削除します。",
+ "3921d3d9a5": "ワークスペースフォルダーが見つかりませんでした。",
+ "f387af445b": "ワークスペース パスは有効なローカル パスではありません。",
+ "3ec372b664": "ファイルマネージャー"
+ },
+ "WorktreeTitleInlineRename": {
+ "2f42ae024f": "未読:",
+ "bff3bdd00c": "ワークスペースの名前を変更する",
+ "8df295a78d": "ワークスペースの名前を変更できませんでした。"
+ },
+ "WorktreeVisibilityDialog": {
+ "83a5ba8dd1": "Orca 以外のワークツリー",
+ "f1f71b9f02": "輸入",
+ "759371df43": "隠れる",
+ "25ddf19920": "{{value0}} をインポートできます",
+ "8372e4bbd9": "現在表示されている{{value0}}",
+ "5d02a5647f": "サイドバーから非表示",
+ "3e045d4cb8": "サイドバーに表示"
+ },
+ "add": {
+ "repo": {
+ "local": {
+ "start": {
+ "actions": {
+ "d72789705e": "空のフォルダーから開始する",
+ "c709860596": "新規プロジェクトを作成する",
+ "5f9ffac036": "リモート Git リポジトリのクローンを作成する",
+ "7edb8ebe24": "URLからクローンを作成する",
+ "a6c20dca96": "SSH ターゲットからプロジェクトを開く",
+ "3d162cc76f": "リモートプロジェクト",
+ "fb4fc5380e": "ローカル プロジェクト、Git リポジトリ、または多数のリポジトリを含むフォルダー",
+ "2281fdc8c7": "フォルダを参照する"
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "worktree": {
+ "flow": {
+ "b81b4e40ca": "ワークスペースのリストが古い場合は、スペースを更新して再試行してください。",
+ "7243145cd6": "削除可能なワークスペースが選択されていません",
+ "ae57cbf6e4": "ワークスペースの削除に失敗しました",
+ "7488ed8711": "表示",
+ "2b20ce87b3": "強制削除",
+ "4f3876c0f5": "強制削除に失敗しました"
+ },
+ "toast": {
+ "1d0fa5c0a5": "ワークスペース {{value0}} の削除に失敗しました",
+ "ead7b8ee15": "ファイルが変更されました。とにかく削除するには、強制削除を使用してください。",
+ "905fc8efac": "Git はこのワークスペースをすでに削除しています。 Orca から削除するには、強制削除を使用します。",
+ "0899ebdb28": "Git はすでにこのワークスペースを忘れていますが、そのディレクトリはまだディスク上にあります。孤立したディレクトリを削除するには、強制削除を使用します。"
+ }
+ }
+ },
+ "remote": {
+ "file": {
+ "browser": {
+ "helpers": {
+ "4dbd72a7d7": "{{value0}} は {{value1}} のディレクトリではありません",
+ "be266af66c": "{{value0}} は {{value1}} の複数のディレクトリと一致します"
+ }
+ }
+ }
+ },
+ "repo": {
+ "header": {
+ "create": {
+ "state": {
+ "992cfbc44b": "{{value0}} の新規ワークツリーを作成します",
+ "3a70acd808": "{{value0}} のワークスペースを作成する前に SSH ターゲットを再接続してください",
+ "6d022563a8": "ワークスペースを作成する前に SSH ターゲットを再接続します",
+ "62e71f2d5d": "{{value0}} のワークスペースを作成する"
+ }
+ }
+ }
+ },
+ "sidebar": {
+ "project": {
+ "drop": {
+ "669e12dd97": "ローカルフォルダーとGitリポジトリ",
+ "ffc769ca29": "フォルダーをドロップしてプロジェクトを追加します",
+ "740e8d0d46": "サーバーパスには「プロジェクトの追加」を使用します",
+ "e344666fb8": "サーバーランタイムがアクティブです",
+ "d0f8943f8b": "プロジェクト追加フローの準備",
+ "18d3cf40e9": "フォルダを確認中"
+ }
+ }
+ },
+ "sleep": {
+ "worktree": {
+ "flow": {
+ "c460fecc4a": "一部のワークスペースのスリープに失敗しました",
+ "8bc3fc0671": "ワークスペースのスリープに失敗しました"
+ }
+ }
+ },
+ "useAddRepoCloneFlow": {
+ "4d0013cc93": "リポジトリのクローンが作成されました",
+ "0dc4d1b657": "クローン先のサーバー パスを入力します。"
+ },
+ "useAddRepoLocalFolderFlow": {
+ "7ab10e4974": "サーバー パスを使用して、リモート ランタイムからプロジェクトを追加します。"
+ },
+ "useAddRepoNestedImportFlow": {
+ "680cac2c82": "{{value0}} は失敗しました",
+ "cbfbc7a797": "一部のリポジトリをインポートできませんでした",
+ "1b33c5f090": "リポジトリがインポートされていません"
+ },
+ "useSidebarProjectDrop": {
+ "f34a286c0d": "ドロップされたフォルダーを追加できませんでした。",
+ "451a4638db": "フォルダーをドロップしてプロジェクトとして追加します。",
+ "5ccb56c7be": "[プロジェクトの追加] を使用してサーバー パスを入力します。",
+ "849ef13dc0": "ローカル フォルダーのドロップはサーバー ランタイムでは使用できません。",
+ "c0315153d1": "一度に 1 つのフォルダーをドロップします。"
+ },
+ "workspace": {
+ "status": {
+ "cb387159f6": "進行中",
+ "6c1efa2cf8": "レビュー中",
+ "6b8285b8dd": "完了",
+ "93ac840dcb": "ブロック中",
+ "2c19d1db33": "Play",
+ "111db162bf": "一時停止中",
+ "642da473f2": "アラート",
+ "6380517b10": "フラグ",
+ "251c817bdd": "タイマー",
+ "409528031f": "レビュー",
+ "5f9ca31a84": "待機中",
+ "821d156f54": "破線",
+ "226d1e7773": "進捗",
+ "a702bc08d4": "ドット",
+ "b4a7101fe1": "丸",
+ "1a9383112b": "Conductor 進捗",
+ "caebe3c10f": "Conductor レビュー",
+ "895f381714": "Conductor 完了",
+ "caabd5ca85": "亜鉛",
+ "7adb43ecf0": "薔薇",
+ "ddf25b6262": "エメラルド",
+ "7cebab6d4a": "アンバー",
+ "1b81da243a": "バイオレット",
+ "6437a8c253": "空",
+ "fc3b92756c": "青",
+ "52e3c6e2a4": "中性"
+ }
+ },
+ "worktree": {
+ "card": {
+ "compact": {
+ "agents": {
+ "a128d7006b": "{{value0}} {{value1}} 子 {{value2}}",
+ "289a1d2ca7": "{{value0}} を展開します。 {{value1}}",
+ "0c1debfe84": "{{value0}} を折りたたむ"
+ }
+ }
+ },
+ "list": {
+ "groups": {
+ "0ed04075b8": "全て",
+ "4aeefc5996": "固定された",
+ "682ed5d551": "クローズ",
+ "7c2f009786": "進行中",
+ "6798dc7c94": "レビュー中",
+ "5076efc3d2": "完了"
+ }
+ }
+ },
+ "CacheTimer": {
+ "07729cc155": "期限切れ"
+ },
+ "DeleteWorktreeDialogFooter": {
+ "c0e972d726": "キャンセル",
+ "cf95e3b5bb": "閉じる"
+ },
+ "index": {
+ "b826a98b6f": "忙しい"
+ }
+ },
+ "shared": {
+ "useDaemonActions": {
+ "01af244097": "キャンセル",
+ "28c8e53176": "これにより、すべてのワークスペースで実行中のすべてのターミナル ペインが強制終了されます。これらのセッションで保存されていない作業内容は失われます。デーモン自体は実行を継続し、新規ターミナルをすぐに開くことができます。これを元に戻すことはできません。",
+ "1bbea41a77": "すべてのターミナルセッションを強制終了しますか?",
+ "01d6b7c64e": "実行中のすべてのターミナル ペインを強制終了し、デーモン プロセスを再起動します。ペインには「プロセスが終了しました」と表示され、すぐに再度開くことができます。以前のアプリ バージョンのレガシー プロトコル セッションは保持されます。これを元に戻すことはできません。",
+ "922548bc66": "ターミナルデーモンを再起動しますか?",
+ "2b4efdc162": "セッションを強制終了できませんでした。",
+ "d18f3005c2": "{{value0}} セッション{{value1}} は終了を拒否しました。",
+ "baad8cd651": "実行中のセッションはありません。",
+ "fe2ab66d45": "{{value1}} セッション中 {{value0}} を強制終了しました。 {{value2}} は退出を拒否しました。",
+ "d762b41f41": "再起動に失敗しました。",
+ "b5954e12d3": "再起動に失敗しました - ログを確認してください。",
+ "0e9da1b98e": "デーモンが再起動されました。"
+ }
+ },
+ "setup": {
+ "guide": {
+ "SetupGuideModal": {
+ "3598a3ca0c": "Orca を並行エージェント作業に活用するためのコア ワークフローを完了します。",
+ "48a9e5ef2d": "はじめる",
+ "28cf59fcb4": "これにより、サイドバーからチェックリストが非表示になります",
+ "f3b5ffb2a6": "サイドバーからチェックリストを非表示にする"
+ },
+ "SetupGuideProgressRing": {
+ "dac3a4724a": "{{value0}}/{{value1}} のセットアップ手順が完了しました"
+ }
+ }
+ },
+ "settings": {
+ "AccountsPane": {
+ "c2d2751587": "アカウントの削除",
+ "dbb9626ed1": "キャンセル",
+ "854ebbcc45": "Orca は、この保存されたアカウントの管理対象Claude認証を削除します。現在アクティブな場合、Orca はシステムのデフォルトのClaude ログインに戻ります。",
+ "63843e37e2": "Claudeアカウントを削除しますか?",
+ "99c8f9e498": "Orca は、この保存されたアカウントの管理対象 Codex ホームを削除します。現在アクティブな場合、Orca はシステムのデフォルトの Codex ログインに戻ります。",
+ "0d47394635": "Codex アカウントを削除しますか?",
+ "ae3b21eb6c": "opencode.ai/workspace/wrk_…/go",
+ "51c9104e13": "opencode.ai にログインした後、URL でこれを見つけます (例:",
+ "b398b834c9": "クリア",
+ "a122332371": "wrk_… (自動検索の場合は空白のままにします)",
+ "dbdb0b0bd8": "ワークスペースIDのオーバーライド",
+ "d70a5287a4": "自動検索が失敗した場合は、オプションのワークスペース ID をオーバーライドします。",
+ "02cb127710": "OpenCode Go ワークスペース ID",
+ "7ce0e1907c": ")。ブラウザの DevTools → Network → opencode.ai request → Cookie ヘッダーで見つけます。 OpenCode Go 認証は Web ベースであり、Windows および WSL ターミナル間で共有されます。",
+ "8951c5309f": "auth=Fe26.2**…",
+ "338820326a": ") または完全な Cookie ヘッダー (例:",
+ "922b51e02d": "Fe26.2**…",
+ "0023cc336e": "生のトークン値 (例:",
+ "a7e38affcd": "Fe26.2**…トークンまたはauth=Fe26.2**…ヘッダー",
+ "67e3c33670": "OpenCode Go セッション Cookie",
+ "b2b1aa936d": "レート制限を取得するために、opencode.ai セッション Cookie を貼り付けます。",
+ "36223200ac": "OpenCode Go セッション Cookie",
+ "ea631977b5": "OpenCode Go プロバイダー設定を構成します。",
+ "4ac10b4d08": "OpenCode Go",
+ "d708749337": "。これは、Orca ではなく、Gemini CLI アプリに発行された認証情報を使用します。 Google が CLI を更新すると壊れる可能性があります。ご自身の責任でご使用ください。",
+ "c2aee76420": "ローカルの Gemini CLI インストールから OAuth 認証情報を抽出して、Google で認証します。",
+ "96f3649526": "Gemini CLI 認証情報を使用する (実験的機能)",
+ "d676c41fc6": "ローカルの Gemini CLI インストールから OAuth 認証情報を抽出して、Google で認証します。これは、Orca ではなく、Gemini CLI アプリに発行された認証情報を使用します。 Google が CLI を更新すると壊れる可能性があります。ご自身の責任でご使用ください。",
+ "0c7f915b01": "Gemini CLI 認証情報を使用する",
+ "973741a871": "Gemini プロバイダー設定を構成します。",
+ "0c64dc2a64": "Gemini",
+ "db209ee572": "削除",
+ "8a0f870153": "再認証",
+ "3d245ef7d9": "Codex はこのサインインが古いと報告しました",
+ "589eba1eee": "再認証が必要です",
+ "e74831fb6b": "アクティブ",
+ "d46f735a85": "。ここで追加するまで、Orca はその環境のシステムのデフォルトの Codex ログインを使用します。",
+ "b4c9450319": "管理対象の Codex アカウントがありません",
+ "93c47b333a": "サインインが必要です",
+ "f2a265f8c7": "システムのデフォルト",
+ "b0e948a4f9": "アカウントの追加",
+ "5568bb6d5c": "アカウント。そこに新規アカウントが追加されます。",
+ "c0a52abfc5": "表示中",
+ "94d351af4a": "アカウント",
+ "d0d53b7eb0": "Orca がライブ レート制限の取得に使用する Codex アカウントを管理します。",
+ "3180536c7a": "Codexアカウント",
+ "340d6f7a85": "各アカウントは、Orca で独自のローカル サインイン コンテキストを保持します。アカウント認証はこのデバイスに残ります。",
+ "cedfab35ab": "オプション。 Orca は通常の Codex ログインを使用できます。 Orca で素早く切り替えたい場合にのみアカウントを追加。",
+ "ef91cfa06b": "Codex",
+ "dea08560b4": "。ここで追加するまで、Orca はその環境のシステムのデフォルトのClaude ログインを使用します。",
+ "3fe7862418": "管理対象の Claude アカウントはありません",
+ "3455cf43fa": "Claudeのログイン。",
+ "fcc4093fc1": "現在の {{value0}} Codex ログインを使用します。",
+ "79e484c3b2": "共有Claude認証ファイル用のオプションのアカウント スイッチャー。",
+ "8bbfd74556": "Claude・アカウント",
+ "72b36ea174": "オプション。 Orca は通常の Claude ログインを使用できます。チャット セッションを移動せずにすばやく切り替えたい場合にのみアカウントを追加。",
+ "26ef4b55be": "Claude",
+ "2743cdc0af": "Claudeアカウントの更新に失敗しました。",
+ "b15ce90870": "{{value0}} -> {{value1}}。古いセッションを続行する前に、ライブ Claude ターミナルを再起動します。",
+ "f921d32606": "Claudeアカウントが更新されました。",
+ "5bf8764953": "Codex アカウントの更新に失敗しました。",
+ "2358ac71d2": "WSLのデフォルト",
+ "ad47a33f72": "WSLの読み込み中",
+ "8619f9afa9": "WSL",
+ "46cf7e7495": "アカウントの場所",
+ "0b4591ff93": "どのローカル環境を検査するか、および新規管理対象の Claude アカウントと Codex アカウントを追加する場所を選択します。",
+ "0c67a2a1aa": "このマシンでは WSL を利用できません。",
+ "2cd197025c": "プロバイダー アカウントを検査し、{{value0}} または WSL で追加するかどうかを選択します。",
+ "f54b4fbd71": "アカウントの場所",
+ "9107406589": "Claudeアカウントをロードできませんでした。",
+ "b8c2905c2b": "Codex アカウントをロードできませんでした。",
+ "fd62f37c24": "Codex は、この {{value0}} ログインが古いと報告しました。",
+ "b10cb4f696": "追加する",
+ "e4a28e8894": "Codex は、{{value0}} ログインには新たなサインインが必要であると報告しました。新規 Codex セッションを開始する前に、再度サインインします。",
+ "75ca9b718e": "Codex は、アクティブなアカウントには新たにサインインする必要があると報告しました。新規 Codex セッションを開始する前に、再認証してください。",
+ "b11078a9c2": "wsl"
+ },
+ "AdvancedPane": {
+ "40b29e0bf3": "再起動",
+ "87a2cb2ac8": "Orca は起動時にこのネットワーク モードを適用します。",
+ "89958d7edf": "再起動が必要です",
+ "b3ad629640": "企業の VPN またはプロキシが HTTP/2 プロトコル エラーにより更新のダウンロードを中断する場合にのみ使用します。再起動後はすべての Electron ネットワークに影響します。",
+ "6627e75c92": "HTTP/1.1の互換性について説明する",
+ "e9506d3377": "HTTP/1.1 互換性",
+ "8b7a8df299": "サポートのトラブルシューティングのための低レベルの回避策。",
+ "8d8d8ac599": "互換性"
+ },
+ "AgentLocationSetting": {
+ "92f4238f1a": "WSLのデフォルト",
+ "fc806485ae": "WSLの読み込み中",
+ "43663b5e69": "WSL",
+ "9bccf48906": "エージェントの所在地",
+ "d00949e59b": "{{value0}} からインストールされているエージェントを表示します。更新すると、その環境で PATH が再チェックされます。",
+ "c7c516946f": "このマシンでは WSL を利用できません。",
+ "f97b986b7f": "wsl"
+ },
+ "AgentSkillSetupPanel": {
+ "0b810ec59f": "Enter を押してインストール コマンドを実行します。",
+ "ed197f59a2": "コピーコマンド",
+ "817d3f9f18": "インストールコマンドのコピー",
+ "5289300939": "未インストール",
+ "9fcebceb2a": "インストール済み",
+ "68a468752e": "確認中...",
+ "c689392435": "再確認",
+ "a31e2aa302": "インストールコマンドのコピーに失敗しました。",
+ "378ad26865": "インストールコマンドをコピーしました。"
+ },
+ "AgentsPane": {
+ "d83834f5e6": "インストールされているエージェントを検出しています…",
+ "024bd95089": "エージェント",
+ "e8da2af684": "インストール可能",
+ "ed3e110e61": "検出済み",
+ "02e0143be5": "インストール済み",
+ "110b74b022": "エージェントなし (空白のターミナル)",
+ "92033495ff": "自動",
+ "9b175d0f5e": "新規ワークスペースを開くときに事前に選択されたエージェント。",
+ "385212c7a1": "デフォルトのエージェント",
+ "f9f127d664": "このエージェントの起動に使用されるバイナリ パスまたは名前をオーバーライドします。",
+ "f95b5c79b8": "インストール",
+ "fe4d630c94": "ドキュメント",
+ "8dc0192e48": "無効",
+ "df123171d1": "未インストール",
+ "c8794e622e": "検出されました",
+ "5200dac9da": "リセット",
+ "2e45ca29b6": "コマンド",
+ "d4d2a45d63": "有効",
+ "1c9a9679ec": "{{value0}} の利用可否",
+ "0d9e293a02": "更新",
+ "c9b33eb5c0": "更新中…",
+ "13647f9f80": "シェルの PATH を再読み取り、インストールされているエージェントを再検出します",
+ "dc4a2ffdc0": "展開コマンドのオーバーライド",
+ "cea7d97be1": "コマンドのオーバーライドを折りたたむ",
+ "db9e9e5887": "カスタマイズコマンド",
+ "959b67385b": "デフォルトを設定する",
+ "24e032fa34": "デフォルト",
+ "5f986a9b92": "デフォルトとして設定",
+ "d7625cf8b2": "デフォルトエージェント"
+ },
+ "AppIconSelector": {
+ "d5a112dc9b": "次へのアイコン",
+ "415fa76f64": "選択したアプリのアイコン",
+ "5f5142a62a": "前のアイコン"
+ },
+ "AppearancePane": {
+ "3057983501": "未割り当て",
+ "0cd9b8228f": "Dock とウィンドウのスイッチャーに表示されるアプリのアイコンを選択します。",
+ "ca1590d42f": "アプリアイコン",
+ "61d842eca0": "Orca Mobile のショートカットをサイドバーに表示します。ツールボックスから引き続き利用できます。",
+ "9da1020447": "Orca モバイル ボタンを表示",
+ "5db6ba961f": "左側のサイドバーの上部に Orca Mobile ボタンを表示します。",
+ "fa882a3e6b": "左側のサイドバーの上部に [オートメーション] ボタンを表示します。",
+ "511f270ebb": "オートメーションボタンを表示",
+ "661942ab7f": "左側のサイドバーの上部に「タスク」ボタンを表示します。",
+ "cf81907069": "タスクボタンを表示",
+ "dc29f3cc0d": "サイドバー",
+ "ea943d0db0": "ウィンドウの下部に表示されるインジケーターを選択します。ステータス バーを右クリックして同じ切り替えを行うこともできます。",
+ "3e4175e5c6": "ステータスバー",
+ "2df8f79aa5": "タイトルバーに Orca を表示します。",
+ "9868f39007": "タイトルバー アプリ名",
+ "4de76f6902": "アプリケーションのタイトルバーに表示される内容を制御します。",
+ "6a272ca553": "タイトルバー",
+ "e9f2ca5582": "オフにすると、.gitignore に一致するファイルがファイル エクスプローラーから非表示になります。",
+ "0fafabcf35": "Git で無視されたファイルを表示する",
+ "75f07ab60c": "ファイル エクスプローラーで .gitignore に一致するファイルを表示します。",
+ "d496901cd0": "ファイルエクスプローラー",
+ "42554f615f": "Orca インターフェイスで使用されるフォントを選択します。",
+ "102d6b5f9b": "IDE フォント",
+ "ef89200c1f": "ターミナルペインにないとき。",
+ "f687711a9b": "アプリケーションインターフェイス全体をスケーリングします。使用",
+ "5e6d7aba8d": "UIズーム",
+ "622e1c3465": "アプリケーションインターフェイス全体をスケーリングします。",
+ "fd89b5487c": "ライト",
+ "7d26ccabe8": "ダーク",
+ "fb0e0b4453": "システム",
+ "932ff1fbff": "テーマ",
+ "0f28e7b30c": "アプリ ウィンドウで Orca がどのように見えるかを選択します。"
+ },
+ "AutoRenameBranchFromWorkSetting": {
+ "1626524572": "Nautilus",
+ "0de9fda203": "破棄",
+ "c71770c455": "{ベースプロンプト}",
+ "f19a56498d": ";ブランチプレフィックス設定は引き続き適用されます。",
+ "800edb1e54": "ログインフローの修正",
+ "5d569f5199": "。 Orca は次のような最後のセグメントのみを生成します。",
+ "570817d126": "そして",
+ "56580dcf60": "。参考にすることもできます",
+ "9c9b54e4ea": "組み込みのブランチ名プロンプト",
+ "69bf4830c2": "Orcaも含めて",
+ "9241b59bf5": "使用",
+ "a869d0edd8": "ブランチ名コマンドテンプレート",
+ "e784ea62dc": "詳細設定",
+ "d9b65054ef": ") をタスクを要約した短い名前にします。 Orca 自身が名前を付けたブランチのみが名前変更され、プッシュされた後は名前が変更されません。",
+ "12ea4a408d": "エージェントが新規ワークスペースで作業を開始すると、Orca は自動生成されたブランチの名前を変更します (例:",
+ "ef787db0e3": "ブランチ名の自動変更",
+ "6a051586d2": "エージェントが起動したら、作業に基づいて自動生成されたブランチの名前を変更します。",
+ "ec3e0c388e": "保存",
+ "cfd82406dd": "保存中...",
+ "40e7be7850": "保存されました",
+ "7c7e34a66d": "未保存の変更",
+ "a4fa380b67": "{アシスタントメッセージ}",
+ "2ee2779c05": "{最初のプロンプト}"
+ },
+ "AutoRenameBranchPromptEditor": {
+ "63121132c0": "破棄",
+ "4416b25d29": "タスクのドメイン名詞を優先し、チケット ID を避け、レビュー担当者が理解しやすい名前を保ちます。",
+ "39278f4411": ";ブランチプレフィックス設定は引き続き適用されます。",
+ "ebb942a2ec": "ログインフローの修正",
+ "af2d9a2cc6": "。 Orca は次のような最後のセグメントのみを生成します。",
+ "182d419b97": "組み込みのブランチ名プロンプト",
+ "2f5dc661fe": "Orcaに追加されました",
+ "7d6176f506": "プロンプト",
+ "5968112152": "保存",
+ "54ac229ad4": "保存中...",
+ "af0831a590": "保存されました",
+ "0691753cf2": "未保存の変更"
+ },
+ "BaseRefPicker": {
+ "1b8e54151f": "一致するブランチが見つかりませんでした。",
+ "d166ff883d": "現在",
+ "a4a9372eb2": "ブランチを検索中...",
+ "7db7fb87e5": "ブランチを名前で検索...",
+ "773a5687a3": "プライマリを使用",
+ "ade9a5bb03": ") 結果の範囲を指定します。",
+ "b468f46726": "上流/メイン",
+ "80f7c82303": ") または完全な参照 (例:",
+ "915ad97875": "上流",
+ "a5c16712c1": "複数のリモコンが検出されました。リモート名を入力します (例:",
+ "9a14ec7400": "以下のベースブランチを選択",
+ "086ce7f369": "次のプライマリ ブランチ ({{value0}})",
+ "2f3cda96f5": "このリポジトリに固定されています",
+ "ee110e1830": "デフォルトの基本参照はありません"
+ },
+ "BrowserDefaultZoomSetting": {
+ "2622126877": "新しく開いたブラウザー タブに適用されるズーム レベル。",
+ "bbeec087d3": "新しく開いたブラウザー タブに適用されます。",
+ "265597101f": "デフォルトのズーム"
+ },
+ "BrowserHomePageSetting": {
+ "d4ddcd0056": "保存",
+ "37a30c5bfd": "https://google.com",
+ "c6cbd1c105": "ホームページが保存されました。",
+ "6a37540f4b": "新規ブラウザ タブを作成するときに開かれる URL。空白のタブを開くには、空白のままにします。",
+ "70224e37b1": "デフォルトのホームページ"
+ },
+ "BrowserPane": {
+ "81ff774667": "キャンセル",
+ "7d4c0a2aa4": "プロファイル名",
+ "612f7f6861": "プロファイルの作成に失敗しました。",
+ "8f22b7580d": "プロファイル「{{value0}}」が作成されました。",
+ "8481ee0331": "新規ブラウザプロファイル",
+ "6f2584b39e": "プロファイルの追加",
+ "e4aaf8051b": "ツールバーのメニュー。",
+ "cd47bc9622": "新規ブラウザタブのデフォルトプロファイルを選択します。 Cookie をインポートし、タブごとにプロファイルを切り替えます。",
+ "2d66a6efb5": "セッションとクッキー",
+ "aa1074bfe9": "ブラウザーのプロファイルを管理し、Chrome、Edge、Comet、またはその他のブラウザーから Cookie をインポートします。",
+ "113cd2dc9b": "セッションとクッキー",
+ "d3eb69c0aa": "リンクルーティング",
+ "3e46903ad4": "アドレスバーに URL 以外のテキストを入力するときに使用されます。",
+ "0d9c987f21": "デフォルトの検索エンジン",
+ "7b225c78f5": "アドレスバーに URL 以外のテキストを入力するときに使用される検索エンジン。",
+ "64898ecdab": "作成",
+ "7b649a578a": "作成…",
+ "4399c77caa": "デフォルト",
+ "4af9a17947": "かぎ"
+ },
+ "BrowserProfileRow": {
+ "8e636cae25": "プロファイル「{{value0}}」が削除されました。",
+ "2d4bea7f35": "デフォルトの Cookie がクリアされました。",
+ "ebb78dfd6f": "ファイルから…",
+ "7df818977e": "から",
+ "cdec84552f": "Cookieのインポート",
+ "796d846483": "Cookie はインポートされません",
+ "c29648fe5b": "アクティブ",
+ "d420c43729": "{{value0}} Cookie を {{value1}}{{value2}} から {{value3}} にインポートしました。"
+ },
+ "BrowserUseComputerUseNotice": {
+ "15b5e680ba": "Open Computer Use",
+ "79209b37b9": "Cookie のインポートが適切でない場合、コンピュータ操作はローカル アプリを制御し、該当する場合は既存のログイン ブラウザー セッションを使用することがあります。コンピュータ操作スキルをインストールします。 macOS ではプライバシー許可も必要です。",
+ "333984cf90": "既存のブラウザセッションを使用する"
+ },
+ "BrowserUseEnableSwitch": {
+ "aea3f45349": "エージェントブラウザの使用を有効にする"
+ },
+ "BrowserUseExamples": {
+ "1199258ace": "コピー",
+ "1188e56af4": "プロンプトの例をコピーする",
+ "b84807f228": "」",
+ "59722f31b4": "」",
+ "c5325e91f6": "これらのいずれかを、スキルがインストールされているプロジェクトの Claude Code、Codex、または別のエージェントに貼り付けます。",
+ "2a180694f7": "試してみてください — プロンプトの例",
+ "5ec620ccc4": "コピーに失敗しました。",
+ "a602d43069": "{{value0}} をコピーしました。"
+ },
+ "BrowserUsePane": {
+ "be6df68384": "ファイルから…",
+ "e44c5d681e": "から",
+ "67d9a53f47": "個別のログインのプロファイルを管理する",
+ "112f70adc4": "最後にインポートされたのは",
+ "72d4815523": "既存のログインを Orca に取り込み、エージェントが認証されたページにアクセスできるようにします。デフォルトのプロファイルにインポートします。",
+ "2eb906706c": "ブラウザの Cookie をインポートする",
+ "af8c83ed61": "Chrome、Edge、またはその他のブラウザから Cookie をインポートすると、エージェントがログインを再利用できるようになります。",
+ "68ea76eb71": "ブラウザをインストールする スキルを使用すると、エージェントが Orca のブラウザを操作できるようになります。",
+ "2d6ead9ab2": "ブラウザ使用スキルをインストールする",
+ "e9f3f3b488": "設置場所",
+ "9fca1f7f5d": "Orca CLI コマンドを登録して、エージェントがシェルからブラウザを調整できるようにします。",
+ "c6065d205d": "Orca CLI を有効にする",
+ "c79eff0213": "エージェントがブラウザを操作できるように Orca CLI を登録します。",
+ "702488a5f7": "コーディング エージェントがログイン情報を使用してこのブラウザを操作できるようにします。以下の 3 つの手順を完了します。",
+ "b8a1f2d84d": "エージェントブラウザの使用",
+ "96b91c6349": "コーディング エージェントがログイン情報を使用してこのブラウザを操作できるようにします。",
+ "2ea4617e3a": "{{value1}}{{value2}} から {{value0}} クッキーをインポートしました。",
+ "721aee31b4": "Orca CLIをPATHに登録しました。",
+ "180a9abf3a": "CLI ステータスのロードに失敗しました。",
+ "2ccfc9cff8": "輸入",
+ "0462565413": "逆輸入",
+ "de9b2f32f3": "有効化",
+ "ad8cb0ee22": "パスを修正する",
+ "0289434ed6": "有効",
+ "8b3054dac7": "登録中..."
+ },
+ "BrowserUseSkillStep": {
+ "0871b6998d": "エージェントが Orca のブラウザでページに移動して確認できるようにします。",
+ "459e24eebc": "ブラウザ使用スキル"
+ },
+ "CliSection": {
+ "8671e406f0": "キャンセル",
+ "a4aafe46e3": "ターゲットパス:",
+ "e8012c03a1": "エージェントが Orca ワークスペース、ターミナル、進捗コマンドを使用できるようにします。",
+ "6053cf736c": "CLIスキル",
+ "36a6f919ba": "エージェントに Orca 対応のワークスペース、ターミナル、および進行状況のワークフローを提供します。",
+ "04873eea3e": "エージェントのスキル",
+ "7f2747f7dd": "現在、このシェルの PATH には表示されません。",
+ "b0c310ab46": "既存のランチャーターゲット:",
+ "15eaad0d31": "コマンドパス:",
+ "5dae812f50": "更新",
+ "52e640f3a0": "CLI ステータスを更新する",
+ "38edbb5721": "シェルコマンド",
+ "6930feda9e": "ターミナルから Orca を使用してアプリを開き、ワークツリーを管理し、Orca ターミナルと対話します。",
+ "c5c0f2641d": "Orca CLI",
+ "d77352f2df": "PATH から {{value0}} を削除できませんでした。",
+ "af5540930c": "PATH から {{value0}} を削除しました。",
+ "a2b13efa94": "`{{value0}}`をPATHに登録できませんでした。",
+ "9cbcd31338": "`{{value0}}`をPATHに登録しました。",
+ "7baec27029": "CLI ステータスのロードに失敗しました。",
+ "d00df2e397": "登録する",
+ "9a5f8a4568": "削除",
+ "b0fca411a0": "登録中…",
+ "4c7e3e4c5f": "インストール",
+ "068552b191": "削除中…",
+ "8d96213669": "削除",
+ "aa6536977e": "Orca は {{value0}} を登録するため、コマンドはターミナルから機能します。",
+ "a030816e3e": "これにより、シェル コマンドのシンボリックリンクが削除されます。 Orca 自体はインストールされたままです。",
+ "fa87db3d6e": "`{{value0}}`をPATHに登録しますか?",
+ "14444243ba": "PATH から {{value0}} を削除しますか?",
+ "5d432fe44d": "インストールされています",
+ "8a9b784c60": "古い",
+ "d363e5929b": "CLI の登録を確認しています…"
+ },
+ "CliSkillRuntimeSetup": {
+ "04325573f8": "WSL",
+ "a58ba464ad": "スキルの場所",
+ "0ed08febc5": "WSLシェルコマンドの登録に失敗しました。",
+ "3728a94fb6": "WSLシェルコマンドには注意が必要です",
+ "775a4cfbb8": "WSLシェルコマンドの登録は利用できません",
+ "c47127f222": "WSLのデフォルト",
+ "0c9f3cf9da": "Orca がグローバル エージェント スキルをチェックしてインストールする場所を選択します。",
+ "f00d6aa9b5": "このマシンでは WSL を利用できません。",
+ "7c776ff9d8": "wsl",
+ "fc0fcf72fd": "スキルセットアップ前にWSLシェルコマンドを登録してください。"
+ },
+ "CommitMessageAiPane": {
+ "841ed9884a": "ソース管理 AI をカスタマイズしていないリポジトリによって使用されます。",
+ "ad66ff886d": "ソース管理 AI のデフォルト",
+ "347094560b": "グローバルなホストレビューのデフォルトを継承するリポジトリによって使用されます。",
+ "2dafc7646e": "ホスト型レビュー作成のデフォルト",
+ "e9d46a544d": "ホストされたレビュー コンポーザーが開くときに使用されるデフォルト。",
+ "b125eabffa": "送信後、作成されたホストされたレビューをブラウザで開きます。",
+ "7662715213": "作成後にホストされたレビューを開く",
+ "b27b0809f3": "コンポーザーが開いたときに、ホストされたレビューの詳細生成を 1 回実行します。",
+ "d5f0de6309": "「PR の作成」を開くときに詳細を生成する",
+ "6278c0ce43": "説明が設定されていない場合は、リポジトリ PR テンプレートを優先します。",
+ "d8b6764d79": "利用可能な場合はレビュー テンプレートを使用する",
+ "e001734396": "Composer で変更しない限り、ホストされたレビューを下書きとして作成します。",
+ "6ba48f07a4": "デフォルトでドラフト",
+ "15b60d54b2": "例えばオラマ 実行 llama3.1 {プロンプト}",
+ "3f1b26cc91": "コマンド入力を引数として渡します。それ以外の場合、Orca はそれを標準入力にパイプします。",
+ "4f722a5f53": "カスタムコマンドを選択するコミットメッセージ、PR、ブランチ名のレシピで使用されます。使用",
+ "47e45cbd5a": "カスタムコマンド",
+ "1ef29f8c29": "コマンド ライン Orca は、テキスト レシピがカスタム コマンドを使用するときに実行されます。",
+ "2339a89104": "選択したエージェントをその操作のコマンド テンプレートで実行する AI ボタンを追加します。",
+ "d5b45a3628": "ソース管理 AI 操作を表示する",
+ "7bcad2b200": "ソース管理のコミット、PR、ブランチ名、および修正操作の操作 レシピを追加します。",
+ "d54c64163d": "有効",
+ "4ec89c319e": "エージェント",
+ "34d0348e34": "生成する",
+ "8cd2be0948": "メッセージ",
+ "ca433708cb": "専念",
+ "0b7eafe55f": "あい",
+ "2c5436c018": "開く",
+ "6c84ba6de3": "テンプレート",
+ "ebed4d2a29": "下書き",
+ "02bab6542c": "PR",
+ "fdee745b87": "MR",
+ "b388463881": "PR",
+ "19e10a12bb": "ホストされたレビュー",
+ "b8b6fd55b4": "{プロンプト}",
+ "fc1a525fa5": "プレースホルダー",
+ "a69e1fe91a": "プロンプト",
+ "1df7d71313": "バイナリ",
+ "407d28bde6": "cli",
+ "54038660e0": "コマンド",
+ "25350d670f": "カスタム"
+ },
+ "ComputerUsePane": {
+ "1735461723": "エージェントがローカル デスクトップ アプリを検査および操作できるようにします。",
+ "93255aaf18": "パソコン利用スキル",
+ "45f8e22c2e": "オープン",
+ "d95d1cfab8": "更新",
+ "0c29da5805": "準備完了",
+ "3383ea1aab": "コンピュータ操作許可をリセットできませんでした",
+ "f189f448a3": "コンピュータ使用アクセスをリセットする",
+ "5c45349665": "コンピュータ操作許可を開けませんでした",
+ "7801ac08ec": "コンピュータ操作許可は macOS でのみ必要です",
+ "740766c291": "パソコン利用の設定はすでに完了しています",
+ "697005758f": "macOS のプライバシーとセキュリティを開く",
+ "2168fa5ab0": "コンピュータ操作許可を読み込めませんでした",
+ "0c9a33f468": "アプリのウィンドウをキャプチャして、エージェントが視覚的な状態を検査できるようにします。",
+ "07bbe4c4cb": "スクリーンショット",
+ "4d03dec2d0": "アプリのインターフェイス ツリーを読み取り、要求された操作を実行します。",
+ "6b5a2cd3a5": "アクセシビリティ",
+ "6b17602073": "アクセスをリセットする",
+ "506f2acf7a": "アクセスをリセットしています...",
+ "4b65070096": "darwin"
+ },
+ "DeveloperPermissionsPane": {
+ "4c17304beb": "更新",
+ "6326a4c5cc": "CLI、ローカル アプリ、または自動化ツールで macOS プライバシー アクセスが必要な場合は、これらのコントロールを使用します。 Orca は起動時に質問しません。",
+ "6f011b9bf6": "ターミナル ツールは、Orca の macOS プライバシー エンベロープを継承します。",
+ "bfa3402305": "許可をリクエストできませんでした",
+ "66e94d6cf3": "許可リクエストが送信されました",
+ "fa809e8ada": "macOS のプライバシーとセキュリティを開く",
+ "48d87edcd2": "許可が与えられました",
+ "a552887288": "開発者権限を読み込めませんでした",
+ "4cfaa7e98a": "Bluetooth デバイス ツールとローカル ハードウェア実験。",
+ "b2210b1b4f": "ブルートゥース",
+ "dfbc12c8c8": "ハードウェア デバッグおよび USB デバイスと通信するデバイス ツール。",
+ "bf51e4a542": "USB デバイス",
+ "f903bf20b5": "ネットワーク上の開発サーバーを検出してアクセスします。",
+ "e7bb06007c": "ローカルネットワーク",
+ "4a73f5217a": "他のローカル アプリを制御するスクリプトの Apple Events。",
+ "e119f0d66b": "オートメーション",
+ "7ca17b62c8": "ターミナルセッションから保護されたフォルダーへの永続的なアクセス。",
+ "c566bca278": "フルディスクアクセス",
+ "9f35980756": "キーストローク インジェクション、ウィンドウ コントロール、UI 自動化ツール。",
+ "5b2f22ca2d": "アクセシビリティ",
+ "0639db5496": "スクリーンショット、ビジュアル自動化、UI 検査ツール。",
+ "f24f31a884": "画面録画",
+ "550cfa3750": "Web カメラ キャプチャおよびカメラ駆動のローカル テスト アプリ。",
+ "e5b5f3d6b9": "カメラ",
+ "cc8151d9fa": "音声入力、文字起こし、オーディオ録音、sox、ffmpeg、および Whisper CLI。",
+ "16381e040a": "マイクロフォン",
+ "dac08ec03e": "処理中..."
+ },
+ "ExperimentalPane": {
+ "9762364929": "作成されたワークツリーに接続する必要がある特定のフォルダーまたはファイルの自動シンボリックリンクを許可します。",
+ "24416f42cd": "ワークツリー上のシンボリックリンク",
+ "fb82ea1d7a": "構成されたファイルまたはフォルダーを新しく作成されたワークツリーに自動的にシンボリックリンクします。",
+ "a20d5ea365": "ターミナルベルまたはエージェント完了イベントの後、そのペインを操作するまで、ペイン レベルのハイライトを表示したままにします。信号を調整しながら実験します。",
+ "ec897e8d89": "ターミナルアテンション",
+ "88b7613afb": "ターミナルベルおよびエージェント完了イベントの永続的なペインのハイライト。",
+ "0277901cf7": "完了したエージェント、ブロック中の質問、未読状態、ワークツリー作成イベントのスレッドワークツリーフィード付きエージェント項目を左サイドバーに追加します。実験的 — イベントモデルと UI は変更される場合があります。",
+ "a05bcdaf57": "エージェントビュー",
+ "f63ea281e3": "エージェントの完了とブロック状態を示すスレッド化された左側のサイドバー フィード。",
+ "ca2219fe5e": "右下隅に固定された小さなアニメーションのペットを表示します。キャラクター (Claudino、OpenCode、Gremlin) を選択するか、ステータス バーのペット メニューから独自の PNG、APNG、GIF、WebP、JPG、または SVG をアップロードします。この設定を無効にしなくても、同じメニューからいつでも非表示にできます。",
+ "dd6f0a1d45": "ペット",
+ "0e89a574ae": "右下隅に浮かぶアニメーションのペット。"
+ },
+ "FloatingWorkspacePane": {
+ "aeaf76fda9": "ステータスバー",
+ "9fb225f2d7": "フローティングボタン",
+ "3c900e26e5": "キーボード ショートカットは、トグルが表示される場所に関係なく機能します。",
+ "5e5a8da236": "トグルボタンの位置",
+ "505001823e": "フローティング ワークスペース ディレクトリを選択",
+ "81afb79785": "新規フローティングターミナルタブはここから始まります。 Markdown ノートは、Orca のアプリが所有するフローティング ワークスペースに保存されます。",
+ "12aa09f10c": "ターミナルディレクトリ",
+ "41eb95f7f0": "フローティング ワークスペース ボタンとパネルを表示します。",
+ "5136813663": "フローティング ワークスペースを有効にする",
+ "37df688d6f": "フローティング ワークスペースを有効にして、新規タブの開始位置を選択します。",
+ "1f67f39384": "フローティングワークスペース"
+ },
+ "GeneralCacheTimerSection": {
+ "05de84a104": "1時間",
+ "54395ecd7c": "5分",
+ "8b9e202e0a": "これをプロバイダーのキャッシュ TTL と一致させます。デフォルトは 5 分です。",
+ "a2a8962138": "タイマーの持続時間",
+ "b4e7302944": "キャッシュタイマー",
+ "487b176240": "Claude エージェントがアイドル状態になった後、サイドバーにカウントダウンを表示します。",
+ "9c20253679": "Claude エージェントがアイドル状態になった後にカウントダウンを表示します。",
+ "fe590653c1": "Claudeはコストを削減するために会話をキャッシュします。アイドル状態が長すぎるとキャッシュが期限切れになり、次のメッセージがより高いコストで完全なコンテキストを再送信します。カウントダウンが表示されるので、いつ再開するかがわかります。",
+ "a137f8854d": "プロンプトキャッシュタイマー",
+ "80c454e8a6": "これをプロバイダーのキャッシュ TTL と一致させます。"
+ },
+ "GeneralEditorSettingsSection": {
+ "f80603d293": "リッチ エディター モードとエージェントのハンドオフ 操作でローカルのマークダウン ノート コントロールを表示します。",
+ "4edc104f0f": "マークダウンレビューノート",
+ "5f02e6fb21": "リッチ エディター モードでローカル マークダウン レビュー ノート コントロールを表示します。",
+ "51161d1647": "ファイルの編集時にミニマップの概要を表示します。",
+ "6690b1ffb9": "ミニマップ",
+ "5a1ea6eaa2": "隠れた",
+ "73a09aad63": "示されている",
+ "1de48ad940": "デフォルトの差分ファイル ツリー",
+ "1b87897af9": "結合された差分ビューを開くときにファイル ツリーを表示または非表示にします。",
+ "12cbc0d0d6": "並んで",
+ "05b6df93b3": "インライン",
+ "7311f67ee7": "デフォルトの差分ビュー",
+ "b492397d34": "デフォルトで git diff を表示するための推奨表示形式。",
+ "a5db1d3975": "MS",
+ "fc5c5306ff": "MS。",
+ "8112cd6dcf": "最後の編集後、Orca が自動的に保存するまで待機する時間。初回起動のデフォルトは",
+ "d6cf227ca0": "自動保存の遅延",
+ "1bec6d8318": "最後の編集後、Orca が自動的に保存するまで待機する時間。",
+ "70bb30feb1": "エディターと編集可能な差分を保存すると、少し停止した後、自動的に変更されます。",
+ "0df2e4fd12": "ファイルの自動保存",
+ "d21136d9ef": "Orca がファイル編集を保持する方法を構成します。",
+ "45c6e85c4d": "エディタ"
+ },
+ "GeneralNetworkSettingsSection": {
+ "3e431564b5": "ローカルホスト、127.0.0.1、*.internal",
+ "33ee3ca3af": "オプション。ホストはカンマ、セミコロン、または改行で区切ります。",
+ "f6d76cc8f4": "プロキシ バイパス ルール",
+ "fb7130dcb9": "構成された HTTP プロキシをバイパスする必要があるホスト。",
+ "0adfce9fa7": "http、https、socks、socks4、socks5 の URL をサポートします。",
+ "476f302aca": "http://proxy.example.com:8080",
+ "1e214e265a": "システムのプロキシ設定と継承されたプロキシ環境変数を使用するには、空のままにします。",
+ "f00daf6324": "HTTPプロキシ",
+ "823e0f15b1": "Orca ネットワーク リクエストとローカルターミナルの子のプロキシ URL。",
+ "d93c7cd531": "アプリレベルのネットワークルーティングを構成します。",
+ "c46cdbbd4e": "ネットワーク"
+ },
+ "GeneralPane": {
+ "d58fccfd84": "ナビゲーション"
+ },
+ "GeneralSupportSection": {
+ "af7d9f4396": "サポートありがとうございます!",
+ "6922c1fa2b": "GitHub 上のスターOrca",
+ "511782265b": "gh CLI を介して GitHub スターでプロジェクトをサポートします。",
+ "55a87e5fd1": "Orcaをサポートする",
+ "964acc6bb4": "星",
+ "73b327e793": "再試行",
+ "c9f96d4234": "エラー",
+ "397719bee5": "主演...",
+ "1e29570462": "主演",
+ "9d181300e3": "星付き",
+ "5c49f02662": "隠れた",
+ "b3f0584f5d": "読み込み中"
+ },
+ "GeneralUpdateSettingsSection": {
+ "8a52ca1d02": "リリースノート",
+ "d89806cc89": "インストールする準備ができました。",
+ "a6b37929dc": "バージョン",
+ "8311da27ba": "利用可能です。 「アップデートのインストール」をクリックしてダウンロードしてインストールします。",
+ "f44299636f": "再起動してアップデート (",
+ "42717918f4": "アップデートのインストール (",
+ "02dc082e70": "アップデートのダウンロードを開始できませんでした。",
+ "e1a647adc5": "アップデートをチェックする",
+ "ceb579abaf": "アプリのアップデートを確認し、新規 Orca バージョンをインストールします。",
+ "d91ebfb87e": "現在のバージョン: {{value0}}",
+ "f2b1ccc12a": "アップデート",
+ "bd79d412f0": "更新チェックに失敗しました。 {{value0}}",
+ "b9ad70c30d": "アップデートエラー。 {{value0}}",
+ "6405510b92": "エラー",
+ "a0832ccdb1": "ダウンロードされた",
+ "2a48034c4c": "v{{value0}}... {{value1}}% をダウンロード中",
+ "4c1c001813": "ダウンロード",
+ "f40d88390d": "最新バージョンを使用しています。",
+ "90eb7309d7": "利用不可",
+ "82465b2444": "利用可能",
+ "31fd7150cf": "アップデートをチェックしています...",
+ "3394d1f663": "チェック中",
+ "d69a09b672": "アップデートは起動時に自動的にチェックされます。",
+ "7173352632": "idle"
+ },
+ "GeneralWorkspaceSettingsSection": {
+ "3d538a98f7": "ワークスペースの「開く」メニューから利用可能なアプリを選択します。",
+ "008f92085f": "アプリで開く",
+ "824b98a0d9": "オートメーションとその実行履歴を削除する前に確認を表示します。",
+ "ea98373cd8": "オートメーションを削除する前に確認する",
+ "d2dd2ca2e3": "オートメーションとその実行履歴を削除する前に確認ダイアログを表示します。",
+ "28bc3d085e": "コンテキスト メニューからワークスペースを削除する前に確認を表示します。削除に失敗した場合でも、強制削除のフォールバックが表示されます。",
+ "9f380934cf": "ワークスペースを削除する前に確認する",
+ "5734db82af": "ワークスペースを削除する前に確認ダイアログを表示します。",
+ "4fbf910ded": "リポジトリ名付きのサブフォルダー内にワークスペースを作成します。",
+ "ba3480642f": "ネストワークスペース",
+ "a246f5ce6f": "ワークスペースフォルダーが作成されるルートディレクトリ。",
+ "5567191a6e": "ブラウズ",
+ "0e9fc0eadc": "ワークスペースディレクトリ",
+ "e2955d9ccb": "新規ワークスペースを作成する場所を構成します。",
+ "7511097c5d": "ワークスペース"
+ },
+ "GhosttyImportModal": {
+ "9d3e56ca36": "変更を適用する",
+ "f96688b6bc": "キャンセル",
+ "b7ddae600c": "完了",
+ "e4bda7ce6f": "このシステムには Ghostty 構成が見つかりません。",
+ "b58d4c9051": "サポートされていないキー",
+ "674b5ccd6b": "インポートする新規設定はありません。現在の設定はすでに一致しています。",
+ "a4c5dec640": "更新する設定",
+ "4466f4cdaa": "インポートが完了しました",
+ "023a52c1f7": "プレビューを読み込み中…",
+ "2763b0c045": "Ghostty 構成からインポートされる設定を確認します。",
+ "d2f33670a9": "Ghostty からインポート",
+ "273e7e81fe": "構成",
+ "1f744a72f4": "構成"
+ },
+ "GitPane": {
+ "d2eede4c54": "Orca の帰属をコミット、PR、イシューに追加します。",
+ "e02ea23a32": "Orcaの帰属",
+ "e71ce09c42": "orca",
+ "b9b5771bb1": "帰属",
+ "b5f534717a": "共著",
+ "9838c921ed": "共著者",
+ "afada55042": "イシュー",
+ "b4ef5428a7": "PR",
+ "895d3f70b8": "gh",
+ "32dca11189": "github",
+ "c4f610d057": "現在の GitLab CLI REST レート制限ヘッダー (利用可能な場合)。",
+ "0de4ae556c": "GitLab API の予算",
+ "cdd793134e": "APIの予算",
+ "b9c011fbc2": "レート制限",
+ "3072428ac7": "glab",
+ "8a527d48e3": "gitlab",
+ "aa204f185f": "現在の GitHub CLI REST、Search、および GraphQL のレート制限。",
+ "612a440e57": "GitHub API の予算",
+ "2cde9044a8": "グラフキュール",
+ "36e3de3619": "古い歴史と比較することから。ブランチにコミットされていない変更またはローカルのみのコミットがある場合、Orca は更新をスキップします。",
+ "d072a12995": "git diff main...HEAD",
+ "db3a127eb1": "。これにより、次のようなコマンドが保持されます",
+ "3ae3de8898": "マスター",
+ "5bf885be48": "または",
+ "ffba483bae": "主要",
+ "976afc6b3e": "ワークスペースを作成すると、Orca はリモート ベースを更新し、一致するローカル ブランチを安全に早送りします。",
+ "1ec5c91e1d": "ブランチ名に Git ユーザー名を使用するか、カスタム プレフィックスを使用するか、プレフィックスを使用しないかを選択します。",
+ "330f584b50": "ブランチプレフィックス",
+ "1ffaadf0a0": "ワークツリーの作成時にブランチ名に追加されるプレフィックス。",
+ "813e15b346": "カスタム",
+ "2351aa5a31": "git ユーザー名",
+ "cc63fce906": "ブランチの命名",
+ "b559bf9899": "例: feature",
+ "aefa1ecb59": "git ユーザー名が設定されていません",
+ "f35007e6e8": "git ユーザー名",
+ "3d172725cc": "なし",
+ "1f32ba27a6": "カスタム",
+ "a182c5125e": "Gitのユーザー名"
+ },
+ "HiddenExperimentalGroup": {
+ "d0f914a528": "プレースホルダーの切り替え",
+ "1014ddbfaf": "今日は何もしません。隠された実験的機能オプションの最初のスロットとして予約されています。",
+ "232cf83de8": "内部テスト用の非公開トグル。ここでは何もサポートされていません。",
+ "3e9e827ca5": "隠された実験的機能"
+ },
+ "InputPane": {
+ "db15068196": "Linux および macOS ではデフォルトで有効になっています。 Linux はシステム選択クリップボードを使用します。他のプラットフォームはプライベート バッファを使用します。",
+ "ad31c3c5fb": "中クリックして「選択範囲から貼り付け」"
+ },
+ "IntegrationsPane": {
+ "2122e15517": "接続された各 Linear ワークスペースには、アクティブなランタイムによって保存された 1 つのキーがあります。フルアクセス キーは、キーの所有者がアクセスできるすべてのチームをカバーできます。制限されたキーはいつでも置き換えることができます。",
+ "e7b2dd46f9": "テスト中…",
+ "fe4d378dc4": "確認済み",
+ "f5c5246514": "Linearアクセスを追加",
+ "6432f6522e": "接続済み",
+ "077844591a": "ワークスペースへのアクセスを追加",
+ "264a9b6128": "Linear",
+ "4831ba1083": "再確認",
+ "01f6c7582e": "もっと詳しく知る",
+ "1a62c295c6": "Gitea 認証情報は設定されていますが、認証できませんでした。トークン、API ベース URL、およびリポジトリの権限を確認し、環境変数が変更されている場合は Orca を再起動。",
+ "5a1f86225a": "Orca がリモートから API URL を取得できない場合のみ。",
+ "6193444689": "ORCA_GITEA_API_BASE_URL",
+ "2c0330ec3e": "プライベートリポジトリの場合は、",
+ "e678d89e8c": "ORCA_GITEA_TOKEN",
+ "d9467ab026": "パブリック リポジトリは、git リモートから検出されます。セット",
+ "4ab9b96925": "Gitea",
+ "953b7bf6f7": "Azure DevOps 資格情報は構成されていますが、認証できませんでした。トークン、API ベース URL、およびリポジトリの権限を確認し、環境変数が変更されている場合は Orca を再起動。",
+ "6f317f5132": "Orca が git リモートから API ベース URL を取得できない場合のみ。",
+ "ae6b7f5f40": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "67a9f26a80": "。セット",
+ "8f960935c1": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "ce3c58cd63": "、または設定",
+ "5ee6ef6405": "ORCA_AZURE_DEVOPS_TOKEN",
+ "4ee74d1470": "セット",
+ "5efce6953d": "Azure DevOps",
+ "3c3cf05c63": "Bitbucket 資格情報は構成されていますが、認証できませんでした。トークンとリポジトリの権限を確認し、環境変数が変更されている場合は Orca を再起動。",
+ "6e0ff3403e": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "44cde4aa01": "ORCA_BITBUCKET_API_TOKEN",
+ "a6c2816115": "そして",
+ "b8a7efb3f6": "ORCA_BITBUCKET_EMAIL",
+ "8489c0aa49": "ビットバケット",
+ "e74de656ce": "glab認証ログイン",
+ "05e5245af7": "GitLab CLI はインストールされていますが、認証されていません。ターミナルで次のコマンドを実行します。",
+ "a83cac5726": "GitLab CLI をインストールする",
+ "35a3379372": "GitLab CLI をインストールして MR、イシュー、パイプラインを有効にします。",
+ "ea160a9978": "CLI。",
+ "a3326f6f1b": "glab",
+ "027440e1cb": "MR、イシュー、ToDo、パイプラインは",
+ "513abfe47d": "GitLab",
+ "51000487c4": "GH 認証ログイン",
+ "09285e9fe6": "GitHub CLI はインストールされていますが、認証されていません。ターミナルで次のコマンドを実行します。",
+ "399cf46867": "GitHub CLI をインストールする",
+ "c0c8575e05": "GitHub CLI をインストールして PR、イシュー、チェックを有効にします。",
+ "f36365ed45": "gh",
+ "de6a0d13ab": "PR、イシュー、チェックは",
+ "70c5f74f36": "GitHub",
+ "8e078e480c": "{{value0}} を切断します",
+ "95b9a87e7e": "テスト",
+ "62b20292de": "エラー",
+ "ae38fc62a8": "わかりました",
+ "33ae9730a8": "Linear アクセスを追加してイシューを参照し、リンクします。",
+ "98ded79cd7": "{{value0}} ワークスペース{{value1}} が接続されました",
+ "4bdc6fe4f5": "未設定",
+ "4972f3c95d": "設定済み",
+ "3614887c40": "チェック中",
+ "45bf5e6e4b": "認証に失敗しました",
+ "e1bd5364e6": "オプションのセットアップ",
+ "e7a961e1c5": "設定済み",
+ "6bd148dcb5": "Gitea REST API を介してリクエストをプルし、ステータスをコミットします。",
+ "6355fe585e": "検出されたリポジトリの PR とコミットステータス",
+ "1fac9b4910": "{{value0}} · PRとコミット ステータス",
+ "f92fbf11aa": "未設定",
+ "6791d7af95": "Azure DevOps REST API トークンを介したPRとビルド ステータス。",
+ "e3d5a24979": "検出された Azure Repos のPRとビルド ステータス",
+ "277fc23929": "{{value0}} · PRとビルド ステータス",
+ "295154e54e": "接続されています",
+ "0879860c58": "Bitbucket Cloud API トークンを介したPRとビルド ステータス。",
+ "9707523939": "PR とビルドステータス",
+ "a565377c38": "未インストール",
+ "15cf990798": "認証されていません",
+ "f7eb5f0b24": "未インストール"
+ },
+ "KagiSessionLinkForm": {
+ "92f0b4e472": "クリア",
+ "9f741627a7": "Kagi セッション リンクがクリアされました。",
+ "d5c8b94c5b": "保存",
+ "ff450194cd": "Kagiプライベートセッションリンク",
+ "e383683485": "https://kagi.com/search?token=...",
+ "81409d9362": "Kagi 認証用のオプションのプライベート セッション リンク。",
+ "3e5b7c6c25": "Kagi セッションのリンクが保存されました。",
+ "0911d5fa4c": "https://kagi.com/search?token=... から Kagi プライベート セッション リンクを入力します。"
+ },
+ "KeybindingsFileActions": {
+ "abc49853fb": "ディスクからリロードする",
+ "a8a8d6b9d3": "ファイルマネージャーで表示",
+ "9e24c0e858": "Cursorで開く",
+ "1637f64033": "VS コードで開く",
+ "98f1a23e1c": "デフォルトのアプリで開く",
+ "400397a10d": "キーバインドファイルメニューを開く",
+ "1c2be2b2c6": "Orca でファイルを編集する",
+ "c5886a31cc": "外部エディタを開けませんでした。",
+ "cdf794f46d": "キーバインド ファイルは使用できません。",
+ "dd532a01ce": "Orca でキーバインドを開けませんでした。"
+ },
+ "ManageSessionKillDialog": {
+ "6bf4627168": "キャンセル",
+ "ad9832aa26": "。そのペイン内の保存されていない作業はすべて失われます。これを元に戻すことはできません。",
+ "8401328fed": "強制終了",
+ "87dcafc85c": "このセッションを終了しますか?",
+ "0b0db4c68c": "セッションを強制終了する",
+ "d3dba51b15": "終了中…"
+ },
+ "ManageSessionsSection": {
+ "33c2a1e1b4": "セッション {{value0}} を強制終了します",
+ "2896a50f50": "ターミナル{{value0}}に移動します",
+ "e26a60d9eb": "セッションはありません。",
+ "39c53d6d74": "読み込み中…",
+ "5ed15e778c": "デーモンを再起動します",
+ "3282db098c": "すべてのセッションを強制終了します",
+ "b3b1cc5708": "更新",
+ "a795a9552a": "セッション",
+ "7c4889a724": "セッションを強制終了するか、基礎となるデーモンを再起動することにより、フリーズしたターミナルや不正な動作をしたターミナルから回復します。",
+ "d1b80fd5cd": "セッションの管理",
+ "9c940434af": "ローカル ランタイムに切り替えて、ローカル デーモン セッションを再起動または強制終了します。",
+ "ad467eaadc": "リモート ランタイム サーバーがアクティブな間は、セッション管理は利用できません。",
+ "8dbd96b463": "セッションを強制終了できませんでした。",
+ "0735b7a586": "セッションを強制終了できませんでした。すでに消滅している可能性があります。",
+ "bfba05dccd": "セッションが強制終了されました。",
+ "c535cbdd09": "セッションをロードできませんでした。",
+ "e3d1fbe008": "再起動",
+ "a06ababda0": "すべて強制終了"
+ },
+ "McpConfigFileRow": {
+ "b145eb6009": "環境:",
+ "e720c139cd": "オープン",
+ "845ae248e8": "有効"
+ },
+ "McpConfigSection": {
+ "4d16a0d9ac": "チェック済み",
+ "b900cd6282": "MCP 構成が見つかりません。このリポジトリで独自の MCP サーバーを定義する場合は、空のワークスペース構成を追加します。",
+ "3b224167ff": "サーバ",
+ "251b96564a": "検出された・",
+ "f34c152dc0": "MCP 構成を更新する",
+ "6bac9ddfc6": "SSH リポジトリは、リモート ファイル システムを通じて読み取られます。スターターの作成は、ワークスペースのルート構成に限定されます。",
+ "96f5609b04": "エージェントがこのリポジトリでの作業中に使用できる MCP サーバー定義を検査します。",
+ "55eea3ef47": "MCP 構成",
+ "9ee215caf6": ".mcp.json",
+ "1f3665e35a": "MCP 構成が作成されました",
+ "82436439eb": "MCP 構成の追加",
+ "0a5c1ead54": "空の構成を作成する"
+ },
+ "MobileEmulatorAgentControlRow": {
+ "1861982430": "CLI ステータスのロードに失敗しました。",
+ "8af7a8bc38": "コマンドは、現在のワークツリーのアクティブなエミュレータをターゲットとします。座標は 0..1 で正規化されます。",
+ "c7f3fe0a6e": "よく使うエミュレータコマンド",
+ "d94ca6a623": "エージェントがモバイル エミュレータ制御を含む Orca CLI コマンドを使用できるようにします。",
+ "67e19ee03c": "Orca CLI スキル",
+ "aaf62a3dd2": "設置場所",
+ "2fef055608": "Orca CLI コマンドを登録して、エージェントがシェルからアクティブなエミュレータを制御できるようにします。",
+ "4f2205f3b6": "Orca CLI を有効にする",
+ "ff4b7e65d6": "コーディング エージェントが Orca CLI コマンドを使用してアクティブなモバイル エミュレータを制御できるようにします。",
+ "2a674aa810": "エージェント モバイル エミュレータ制御",
+ "cdeaed9e37": "Orca CLIをPATHに登録しました。"
+ },
+ "MobileEmulatorExamples": {
+ "edf13dd03b": "コピー",
+ "c12b253997": "プロンプトの例をコピーする",
+ "d151e25078": "」",
+ "b525ff2b12": "」",
+ "4daa95f25a": "これらのいずれかを、Orca CLI スキルがインストールされているプロジェクトの Claude Code、Codex、または別のエージェントに貼り付けます。",
+ "0820b3f84f": "試してみてください — プロンプトの例",
+ "1f608e7d60": "プロンプトのコピーに失敗しました。",
+ "2b077b5544": "プロンプトをコピーしました。"
+ },
+ "MobileEmulatorSettingsPane": {
+ "19d39113b6": "コーディング エージェントが Orca CLI コマンドを使用してアクティブなモバイル エミュレータを制御できるようにします。",
+ "f2f8d97bb6": "エージェント モバイル エミュレータ制御",
+ "143961d031": "デフォルトのデバイス",
+ "8aec2f99a0": "エミュレータの利用可能性を更新する",
+ "ae1612c58c": "可用性",
+ "f9af91ea26": "新規モバイル エミュレータ 操作を表示し、エージェントがアクティブなエミュレータに接続できるようにします。",
+ "700ddbf9b1": "モバイルエミュレータを有効にする",
+ "bc39d0f115": "Orca およびコーディング エージェントのモバイル エミュレーターのサポートを構成します。",
+ "6593c9ddd3": "モバイルエミュレータ",
+ "a4f1c82d90": "無効",
+ "b5e2d93e01": "確認中...",
+ "c6f3ea4f12": "準備完了",
+ "d704fb5023": "設定が必要"
+ },
+ "MobileNetworkInterfaceSection": {
+ "63d5e4ae1e": "QR コードを再生成し、Orca モバイル アプリからスキャンします。",
+ "87985ba6f5": "このネットワーク インターフェイス メニューで、Tailscale アドレス (通常は 100.x.y.z IP) を選択します。",
+ "1f7c26d36a": "両方のデバイスで同じテールネットにサインインします。",
+ "668016be7a": "コンピューターとスマートフォンで。",
+ "1dc87a7fbc": "テールスケール",
+ "51d29927eb": "インストール",
+ "9fc5d203ff": "Orca Mobile はこのコンピュータに直接接続します。同じローカル ネットワークから離れた場所で使用するには、コンピューターとスマートフォンを同じプライベート オーバーレイ ネットワーク上に配置し、そのネットワーク アドレスを選択して QR コードを生成します。",
+ "39fad211d9": "テールネットを使用して Wi-Fi の外部に接続する",
+ "a9db5d771d": "ネットワークインターフェースを更新する",
+ "b2c384cfd6": "インターフェースが見つかりません",
+ "d536b5e20d": "QR コードでアドバタイズするネットワーク アドレスを選択します。同一ネットワーク ペアリングには LAN アドレスを使用し、クロスネットワーク アクセスにはオーバーレイ ネットワーク アドレス (Tailscale、ZeroTier) を使用します。",
+ "406a35121c": "ネットワークインターフェース",
+ "c541f67790": "QRコードの生成",
+ "1e64659126": "再生する"
+ },
+ "MobilePane": {
+ "dd3cd78d04": "Orca モバイルでスキャン",
+ "35100bca5d": "スマートフォンでターミナルを使用している間、Orca はスマートフォンの画面に合わせてターミナルを縮小します。アプリを閉じるか別のアプリに切り替えるときに、アプリをスマートフォンサイズのままにするか (インタラクティブ CLI ツールがリフローしないように)、サイズを変更してデスクトップに戻るかを制御します。ターミナル バナーの [復元] をクリックすると、いつでも手動でサイズを変更できます。",
+ "ee56f1c7e4": "モバイルアプリを終了するとき",
+ "3939fd062c": "デバイスを取り消すと、デバイスはすぐに切断されます。",
+ "254a6d09e4": "ペアリング済み",
+ "d7ce676270": "ペアリングされたデバイス",
+ "e778ecb209": "または、次のコードをモバイル アプリに貼り付けます。",
+ "310924ad2c": "Orca モバイル アプリでこのコードをスキャンします。各コードは一意のデバイス トークンを作成します。",
+ "870e1b5ca5": "デバイスの取り消しに失敗しました",
+ "2e3dd0bc29": "デバイスが取り消されました",
+ "711231348f": "ペアリングコードのコピーに失敗しました",
+ "e3c427e020": "QRコードの生成に失敗しました",
+ "cb9067c1c1": "WebSocketトランスポートが実行されていません",
+ "d714614dbf": "ネットワークインターフェースの更新に失敗しました",
+ "ff865419dc": "30分後",
+ "d4ba07d914": "5分後",
+ "c474aa09d8": "1分後",
+ "aa1263e881": "スマートフォンサイズを維持(デフォルト)",
+ "6436e56546": "モバイルペアリング用のQRコード",
+ "1b1b70279a": "まだデバイスがペアリングされていません。",
+ "1592afcc7a": "まだデバイスがペアリングされていません。 Orca モバイル アプリで QR コードをスキャンします。"
+ },
+ "MobileSettingsPane": {
+ "9a3c280e49": "GitHub リリース",
+ "b0088412a1": "または Android APK から",
+ "b5a2ed83ff": "アプリストア",
+ "c8491c17ef": "QR コードをスキャンしてスマートフォンから Orca を制御します。ベータ/早期プレビュー - バグや重大な変更が予想されます。 iOS アプリを次の場所から入手します。",
+ "e7a3ae8c4e": "モバイル",
+ "174f4a3c6d": "スマートフォンからターミナルとエージェントを操作"
+ },
+ "NotificationsPane": {
+ "906b4afebf": "テスト通知を送信する",
+ "2772d2f257": "トリガー元のワークツリーがすでに表示されている場合は、通知をスキップします。",
+ "00cd406dbb": "集中中は抑制",
+ "2a42dd8d6f": "通知音の音量",
+ "4aa5085cd7": "カスタム:",
+ "c258cb96dc": "通知音を選択する",
+ "2a2033c388": "デスクトップ通知が配信されたときに Orca が再生するアラートを選択します。",
+ "88686e6ca8": "通知音",
+ "b6fc369244": "バックグラウンドターミナルはベルの文字を発します。",
+ "591fe605b9": "ターミナルベル",
+ "55f901a59b": "コーディング エージェントが終了し、アイドル状態になります。",
+ "ca76d06fd2": "エージェントのタスクが完了しました",
+ "deff6d30da": "バックグラウンド イベントのネイティブ システム通知。",
+ "841c8c549f": "通知を有効にする",
+ "0fadad17ce": "通知音が再生できませんでした",
+ "406feb0aa6": "テスト通知が配信されませんでした",
+ "6fc3781729": "通知が無効になっています",
+ "4676a95bc3": "Orca のデスクトップ通知設定を確認してください。",
+ "0cb93240b8": "システムは通知を表示しませんでした",
+ "145227ca2b": "設定を開く",
+ "d3d54e0915": "テスト通知が送信されました",
+ "115437bc35": "macOS バナーが表示されない場合は、Orca の通知を許可するを有効にします。",
+ "7f45542625": "テスト通知が要求されました",
+ "98d70fb261": "カスタム通知音を再生できませんでした",
+ "c83b05a055": "このシステムでは通知はサポートされていません",
+ "274af61bc0": "システム",
+ "6e6df3a09a": "カスタムファイルの選択",
+ "76e02467b8": "カスタムファイルの変更",
+ "d3756cf5bc": "無効"
+ },
+ "OpenAiTranscriptionKeyDialog": {
+ "fa83512e48": "キーの保存",
+ "07b26f2742": "クリアキー",
+ "d246b2bdb3": "ローカル ランタイム キーは、利用可能な場合は Electron 暗号化ストレージを使用して ~/.orca に保存されます。",
+ "c3380e4ca5": "スク...",
+ "2f797018f0": "APIキーが設定されました",
+ "16015322f9": "APIキー",
+ "07ed3e512e": "音声は、OpenAI 音声モデルが選択されている場合にのみ OpenAI に送信されます。",
+ "439e91879e": "OpenAI 文字起こし"
+ },
+ "OpenAiTranscriptionSettingsRow": {
+ "85c589cd61": "APIキーを追加",
+ "ae2df8f511": "OpenAI APIキーの切断",
+ "a622bc3b37": "キーを交換する",
+ "3b0ab3fc0b": "接続済み",
+ "27e0cb656d": "OpenAI 文字起こし",
+ "893790e13b": "クラウド音声テキスト変換モデルを選択する前に、OpenAI API キーを追加します。",
+ "b59b9b2b51": "クラウド音声テキスト変換モデル用に構成された API キー。"
+ },
+ "OpenInMenuSetting": {
+ "03b00b1f64": "カスタムアプリ",
+ "c1d817e027": "追加した",
+ "e4064916aa": "アプリを追加",
+ "9d0413817d": "ワークスペースの「開く」メニューから利用可能なアプリを選択します。",
+ "6ed52fe71e": "アプリで開く",
+ "eb55b87570": "このアプリを開くためにターミナルに入力するコマンド。",
+ "ba1422ee07": "ターミナルコマンド",
+ "e1fc0085c6": "メニューラベル",
+ "a261931d29": "アプリを削除する",
+ "af7d1c3656": "アプリの編集",
+ "494ed535cd": "アプリの詳細を折りたたむ",
+ "810ef39b56": "cursor",
+ "3ebe650f74": "アプリ名",
+ "3743ed080c": "セットコマンド",
+ "f79084947b": "新規アプリ"
+ },
+ "OrchestrationExamplesDialog": {
+ "3d1aa105e3": "プロンプトのコピー",
+ "9b4c004998": "完了",
+ "969cec9739": "{{value0}} プロンプトの例をコピーします",
+ "4e46da1889": "プロンプトのコピーに失敗しました。",
+ "80c6f2feb8": "プロンプトの例をコピーしました。"
+ },
+ "OrchestrationPane": {
+ "52e0634e2c": "コーディネーター エージェントに、ハンドオフ、ワークツリー ハンドオーバー、および順次または並列の子エージェントにオーケストレーションを使用するように依頼します。",
+ "ae79504732": "使い方",
+ "7bc082f4de": "インストールコマンドのコピー",
+ "832f1f3ee6": "独自のターミナルをご希望ですか?",
+ "9bedd2a6e5": "エージェントがコンテキストを引き継ぎ、Orca を通じて作業を調整できるようにします。",
+ "07641b9768": "オーケストレーションスキル",
+ "2aacdb0517": "ハンドオフ、ワークツリーのハンドオーバー、および子エージェントの作業全体にわたってコーディング エージェントを調整します。",
+ "191ac34567": "エージェントオーケストレーション"
+ },
+ "OrchestrationSetupCard": {
+ "e7d2a5146c": "エージェントがコンテキストを引き継ぎ、Orca を通じて作業を調整できるようにします。",
+ "2777ff0fdc": "オーケストレーションスキル"
+ },
+ "OrchestrationSkillAgentCoverage": {
+ "6dec5ce2d2": "エージェントの範囲",
+ "ffe13e36fb": "不足",
+ "1e8f8d8fae": "準備完了"
+ },
+ "OrchestrationSkillPromptDialog": {
+ "f08d45293d": "コピーコマンド",
+ "35550f3b3b": "完了",
+ "1bdce1911e": "オーケストレーション スキルのインストール コマンドのコピー",
+ "b99f375eb2": "ターミナルでこのコマンドを実行して、エージェントのオーケストレーション スキルをインストールします。",
+ "2914abcfa2": "オーケストレーション スキルをインストールする",
+ "d3dc559225": "インストールコマンドのコピーに失敗しました。",
+ "239bf9132b": "インストールコマンドをコピーしました。"
+ },
+ "PrivacyDiagnosticBundleControls": {
+ "dc8404a930": "プレビューの作成",
+ "a5acaffdb6": "破棄",
+ "aca2c8a367": "アップロード",
+ "798b6f0be5": "プレビューを開く",
+ "2ae9a6b63e": "完了",
+ "7f14a1733c": "バンドルの削除",
+ "2801d4ce22": "チケットをコピー"
+ },
+ "PrivacyDiagnosticsSection": {
+ "acc7c66e6e": "OTLP エクスポート",
+ "4ff08ff3a7": "ローカルトレースをクリアする",
+ "9ca08a9f8f": "このマシン上のローテーションされたすべてのトレース ファイルを削除します。",
+ "fe81a52cb2": "トレースフォルダーを開く",
+ "5ff57fc986": "ファイル マネージャーに {{value0}} が表示されます。",
+ "af2fc82cde": "診断バンドル",
+ "c18cbe45df": "アップロードされた診断バンドルが削除されました",
+ "7a4944595b": "診断チケットをコピーできませんでした",
+ "13eb2c65a1": "診断チケットがコピーされました",
+ "860bca9ec9": "診断バンドルのプレビューが破棄されました",
+ "49fc6c80e8": "診断バンドルがアップロードされました",
+ "db3228e01a": "診断バンドルのプレビューが開きました",
+ "a2b3505c77": "診断バンドルのプレビューが作成されました",
+ "9666a05580": "トレースファイルをクリアできませんでした",
+ "32d767f84d": "ローカル トレース ファイルがクリアされました",
+ "b85fe972cd": "トレースフォルダーを開けませんでした",
+ "1fb00a8995": "無効",
+ "46ea3fb2d0": "有効",
+ "7c9d9820b6": "Orca が独自の OpenTelemetry コレクターを指すように ORCA_OTLP_TRACES_URL を設定します。"
+ },
+ "PrivacyPane": {
+ "36e0e2e63b": "環境変数。設定を解除し、再起動して再度有効にします。",
+ "79a0f3c16c": "テレメトリは、",
+ "e3970bbbf5": "CI 環境変数が設定されているため、テレメトリは無効になっています。設定を解除して再起動してください。",
+ "fe904ac984": "匿名の使用状況データを共有する",
+ "77410e0566": "プライバシーポリシー",
+ "8bfdd23a88": "次に何を構築するかを考えるのに協力してください。 Orca は、使用した機能と問題が発生した場所の匿名のカウントを送信します。",
+ "afec8b03be": "シ"
+ },
+ "QuickCommandsPane": {
+ "8764c6e9e4": "{{value0}} を削除",
+ "7d90fd5299": "{{value0}}を編集",
+ "8c877dec41": "グローバル",
+ "c6b155911b": "すべてのコマンド",
+ "5aacc8f7dc": "コマンドの追加",
+ "c36912efd5": "タブ バーの [クイック コマンド] ボタンから実行するか、ターミナル内で右クリックします。",
+ "f91b649324": "保存されたコマンド",
+ "3d9dc558e8": "このクイック コマンドは保存されたリストから削除されます。",
+ "3edf3deaf8": "「{{value0}}」を削除しますか?",
+ "9fcfc29519": "入れる",
+ "9b3e338d62": "入力",
+ "4ccc63da87": "エージェント",
+ "0252ddd578": "コマンドテキストなし",
+ "7784912ed6": "リポジトリ",
+ "2bb9e38e93": "無題",
+ "3eb9897ab0": "選択されたスコープにはコマンドがありません。",
+ "38d61927e6": "クイック コマンドは保存されません。",
+ "44923dd982": "破壊的な",
+ "ec1ed99e70": "削除",
+ "d1d0976320": "なし"
+ },
+ "RecentTabOrderControl": {
+ "3b17c81ede": "タブストリップの順序",
+ "6e6a3fcc61": "最新の",
+ "7a546f2309": "タブオーダー",
+ "a867a0889f": "最近のまたはタブ ストリップ。"
+ },
+ "RepositoryHooksSection": {
+ "af49e2a19e": "ファイルは存在しますが、Orca は有効な `scripts` または `issueCommand` 定義を見つけることができませんでした。",
+ "3397879bee": "ローカル コマンドが存在する場合は、どのコマンドを実行するかを選択します。",
+ "39da2ae12f": "orca.yaml",
+ "ac9038d2cc": "両方のとき",
+ "32fec28f5b": "コマンドソース",
+ "bbbd6e0bc4": "コマンドソースとorca.yaml",
+ "c9bc1bfd8f": "詳細設定",
+ "610d90fdbd": "コマンド ソースと orca.yaml の詳細。",
+ "52aef29e69": "リポジトリのデフォルトを使用するには空白のままにします",
+ "4084720f47": "{{artifact_url}} を完了",
+ "13394103bd": "カスタム GitHub イシューコマンド",
+ "70ad20f883": "リンクされた号または PR URL をご覧ください。",
+ "b997331366": "オプションの上書き。使用",
+ "2cc27dc12b": "リンクされたイシューコマンドのユーザーごとのオプションのオーバーライド。",
+ "b91a0f297d": "ワークツリーがアーカイブされる前に実行されるローカルおよび共有スクリプト。",
+ "9a100323ff": "アーカイブスクリプト",
+ "21fb607a87": "新規ワークツリーが作成されたときのデフォルトの動作。",
+ "793dcee97d": "いつ実行するか",
+ "63e1783173": "セットアップ スクリプトが使用可能な場合のデフォルトの動作を選択します。",
+ "fb6bebcf7e": "セットアップをいつ実行するか",
+ "30d555acd2": "新規ワークツリーの作成後に実行されるローカルおよび共有スクリプト。",
+ "52b31baf02": "セットアップスクリプト",
+ "8567127a40": "ワークツリーが作成またはアーカイブされるときに実行されるスクリプト。ローカル スクリプトはこのマシンに保存されます。 「orca.yaml」スクリプトはチームと共有されます。",
+ "ff082fe7c6": "ワークツリーフック",
+ "5d940bde5c": "ローカルスクリプトを追加",
+ "8c2893fae0": "単一のシェル スクリプトとして実行されます。このマシンに保存されます。",
+ "40a446ae16": "- あなただけのために、このマシンで",
+ "2d03a514db": "地元",
+ "7e4427b4a2": "変えること。",
+ "b113344b6a": "編集",
+ "f828e1de19": "- チームと共有",
+ "673a7fd10e": "確認中...",
+ "5426ecbdcb": "ローカルスクリプトは実行されません",
+ "b2b06c7ce8": "利用可能な環境変数 (カーソルを合わせると詳細が表示されます):",
+ "95a0411b3e": "テンプレート",
+ "175daba180": "例",
+ "b20c5df6ca": "「orca.yaml」ファイルを追加して、このリポジトリの共有セットアップ、アーカイブ、またはイシュー自動化のデフォルトを有効にします。テンプレートの例:",
+ "925f9e0dc4": "テキスト前景",
+ "0cc712b823": "コア構成ファイルはリポジトリ ルートに存在しますが、Orca はサポートされているフック定義をまだ解析できませんでした。",
+ "c90b858573": "テキスト-アンバー-700 ダーク:テキスト-アンバー-300",
+ "aba825233f": "このファイルには、このバージョンの Orca が認識しない構成キーが含まれています。 Orca を更新するか、ファイルにタイプミスがないか確認する必要がある場合があります。",
+ "ca424ff135": "共有フックとイシュー自動化のデフォルトはリポジトリで定義され、それを使用するすべてのユーザーが利用できます。",
+ "32f417fe17": "テキスト-エメラルド-700 ダーク:テキスト-エメラルド-300",
+ "8bfe65fc60": "ローカルコマンドを使用する",
+ "8d6c56bff8": "両方を実行します",
+ "0fa21e19ec": "ワークスペースの名前。通常はブランチ名に基づきます。",
+ "54c73d88d0": "作成されるワークツリーへのパス。セットアップ コマンドはこのディレクトリから実行されます。",
+ "30952c4aa4": "メイン リポジトリ チェックアウトへのパス。 .env などの共有ファイルをワークツリーにコピーする場合に便利です。",
+ "9b821fa19d": "# 例: echo \"$ORCA_WORKSPACE_NAME をクリーンアップしています\"",
+ "6f90ebe3fd": "ワークツリーがアーカイブまたは削除される前に実行されます。",
+ "a3fc966677": "# 例: pnpm install cp \"$ORCA_ROOT_PATH/.env\" \"$ORCA_WORKTREE_PATH/.env\"",
+ "f0710e1c83": "新規ワークツリーが作成された後に実行されます。 deps をインストールし、env ファイルをコピーし、移行を実行します。",
+ "8561b0665f": "最初に orca.yaml を作成し、次にローカル コマンドを作成します。",
+ "0e8b2a520d": "orca.yaml を無視します。ローカル コマンドのみを実行します。",
+ "83dc78202a": "ローカルのみ",
+ "29397e8bbc": "コミットされたリポジトリ コマンドのみを実行します。ローカルコマンドを無視します。",
+ "d88b6ff88f": "orca.yaml のみ",
+ "99e3264a49": "選択した場合のみセットアップを実行します。",
+ "15debc1fd9": "デフォルトでスキップ",
+ "022ba10cf2": "セットアップを自動的に実行します。",
+ "d3ef1ab247": "デフォルトで実行",
+ "90b1f50137": "セットアップを実行する前にプロンプトを表示します。",
+ "e03d9a8f38": "毎回尋ねる",
+ "8dbe6bedf5": "無効",
+ "0e0dd5b9a5": "ロード済み",
+ "9b12f15b1e": "存在するとき。",
+ "c85c2c88a2": "{{artifact_url}}",
+ "fac13f8c1e": "権威ある",
+ "0518758f38": "両方",
+ "d2b3016c20": "共有",
+ "4611b78617": "コマンドソース",
+ "c5a55a2d2e": "詳細設定",
+ "b5e3e77e89": "操作",
+ "0ce113fd7b": "ローカル スクリプトは保存されますが、スクリプト ソースは orca.yaml のみに設定されます。",
+ "7f78e5eea6": "ローカルスクリプトが保存されます。 Orca は、使用するスクリプト ソースを推奨する前に orca.yaml を引き続きチェックします。",
+ "2b6356e744": "保存されました",
+ "81057d5f71": "保存中...",
+ "da37d6f10e": "コピー",
+ "3149964b66": "コピーされました"
+ },
+ "RepositoryIconPicker": {
+ "2b7d27b93c": "{{value0}} リポジトリ カラーを使用する",
+ "fde066a63b": "PNG アップロードは 256KB 以下である必要があります。",
+ "cc1286e263": "ファビコン",
+ "03ca1a4e9b": "例.com",
+ "381b4844fd": "PNG をアップロードする",
+ "7da623abcc": "デフォルトで使用 — 所有者がカスタム イメージを設定していない場合でも、GitHub は常にイメージを提供します。",
+ "39da8a10bf": "GitHub アバターを使用する",
+ "c490787d24": "絵文字",
+ "b2d7fd2116": "アイコン",
+ "2d8bd302fa": "アバター",
+ "913c55833d": "カスタム リポジトリの色 {{value0}}",
+ "0e5f0693c1": "カスタム リポジトリの色を選択する",
+ "642dc29c6d": "色",
+ "549d126081": "リセット",
+ "4e2a14f967": "リポジトリアイコン",
+ "d71df44587": "GitHub リポジトリを解決できませんでした。",
+ "f79972271a": "このリポジトリの GitHub リモートが見つかりません。",
+ "4d039317f4": "ウェブサイトのファビコン",
+ "acf31559a0": "有効な Web サイトの URL を入力。",
+ "868c5c9b56": "リポジトリのインポートに失敗しましたアイコン"
+ },
+ "RepositoryPane": {
+ "15a99d9b9f": "相対パスは、このプロジェクトのルートから解決されます。",
+ "8ccacbeb5a": "グローバルを使用する",
+ "e9bd57a336": "ワークツリーの場所",
+ "e63bb96a9b": "新規ワークツリーのプロジェクト固有のディレクトリ。",
+ "f88db4fece": "デフォルトのワークツリーベース",
+ "8984d06520": "ワークツリー作成時のデフォルトのベースブランチまたは参照。",
+ "e641c359de": "サイドバーとタブで使用されるプロジェクトのアイコンと色。",
+ "26fef02bf3": "プロジェクトアイコン",
+ "c7ef4415de": "表示名",
+ "b0a0c14a1c": "サイドバーとタブのプロジェクト固有の表示詳細。",
+ "170624bdfb": "このプロジェクトを Orca から削除します。",
+ "0909e5d650": "プロジェクトの削除",
+ "ee5a290616": "フォルダーとして開きます。このワークスペースでは Git 機能を使用できません。",
+ "323debba71": "タイプ:",
+ "499a437335": "身元"
+ },
+ "RepositorySourceControlAiActionRows": {
+ "548a6e1281": "コマンドテンプレート",
+ "7a3a8e431d": "CLI 引数",
+ "2b2f38652b": "カスタムコマンド",
+ "0ffb081b3a": "デフォルトのエージェントを使用する",
+ "f4310cf63f": "エージェント",
+ "1cd88d470a": "カスタマイズ",
+ "403876bb48": "グローバルを使用する",
+ "f0aa2cfaea": "操作レシピ"
+ },
+ "RepositorySourceControlAiCustomCommand": {
+ "0704dd55cd": "リポジトリコマンド",
+ "e56668c291": "グローバルを使用する",
+ "fbb77e122a": "カスタム コマンドを選択するテキスト 操作のリポジトリ フォールバック。",
+ "ebffc5a28c": "カスタムコマンド",
+ "f9941f0caf": "例えばオラマ 実行 llama3.1 {プロンプト}"
+ },
+ "RepositorySourceControlAiEnablement": {
+ "84233d1bb3": "オフ",
+ "bea897eec2": "の上",
+ "62511a575d": "グローバルを使用する",
+ "30ae6dcce8": "グローバルデフォルトは",
+ "cf5959c834": "ソース管理 AI が有効になっている"
+ },
+ "RepositorySourceControlAiHostedReviewDefaults": {
+ "053ccfbf52": "オフ",
+ "777443bf89": "の上",
+ "ffc3b26b26": "グローバルを使用する",
+ "a68849a859": "グローバルデフォルトは",
+ "aa6ee4b7d6": "ホスト型レビュー作成のデフォルト",
+ "629ed8a9d3": "作成後にホストされたレビューを開く",
+ "14f1eb99d0": "「PR の作成」を開くときに詳細を生成する",
+ "d32b87e754": "利用可能な場合はレビュー テンプレートを使用する",
+ "981eae7e14": "デフォルトでドラフト"
+ },
+ "RepositorySourceControlAiSection": {
+ "67b3ff5467": "破棄",
+ "8b8bc5913a": "リポジトリ操作のレシピ。グローバル設定は、このリポジトリがカスタマイズするまで使用されます。",
+ "71b003b62b": "ソース管理 AI",
+ "152268c295": "保存",
+ "57e6e9d4b1": "保存中...",
+ "ccb07dd027": "保存されました",
+ "e57dde9d93": "未保存の変更"
+ },
+ "RuntimeAccessGrantList": {
+ "8b82879581": "アクティブな許可を持っている人は誰でも、許可を取り消すまで接続できます。共有アクセスを取り消すと、アクティブなクライアントはただちに切断されます。",
+ "68ec21309f": "アクセスを取り消す",
+ "6f6d5188ed": "{{value0}}を取り消す",
+ "87b16cd11d": "作成されました",
+ "434e4a6af6": "現在のリンク",
+ "fd83b94095": "共有サーバーへのアクセスはまだありません。",
+ "27cf8507ad": "共有アクセスを更新する",
+ "f031182867": "共有サーバーアクセス",
+ "df142657a5": "まだ使用されていません",
+ "b18d1764ef": "最後に使用したのは {{value0}}"
+ },
+ "RuntimeEnvironmentsPane": {
+ "aeb26635d2": "{{value0}} を削除",
+ "af53761f31": "キャンセル",
+ "bb90dd6487": "サーバーの削除",
+ "d2e00809e4": "スイッチ",
+ "05e0fc3ebf": "に切り替えます",
+ "b2290ed203": "Orca は、次のサーバーからプロジェクトをロードする前に、現在のサーバーからリモート ターミナルとブラウザ タブを閉じます。",
+ "d570c35a99": "スイッチサーバー",
+ "84b9b2be05": "ブラウザまたは別の Orca クライアントが接続できるように、取り消し可能なアクセス許可を作成します。",
+ "6e1280ca55": "この Orca サーバーを共有する",
+ "9a3758d983": "保存されたサーバーはありません。",
+ "9bee6bbeeb": "サーバーの追加",
+ "55fcc964cd": "サーバーに接続し、印刷されたペアリング URL を貼り付けます。",
+ "960e901ae4": "orcaserve --pairing-address <ホスト>",
+ "163671f7b5": "走る",
+ "c3d772c514": "orca://pair?code=...",
+ "9bc9b83474": "ペアリングコード",
+ "e038625857": "開発ボックス",
+ "54ebacc600": "サーバー名",
+ "1826bd0608": "保存されたサーバー",
+ "6ce4664003": "サーバーを更新する",
+ "b07070ed3c": "サーバーが接続されていません",
+ "78692becbd": "ローカルデスクトップ",
+ "64b6bea541": "アクティブサーバー",
+ "99ac81fb43": "{{value0}} に切り替えました。",
+ "b5b5114cb0": "{{value0}} を削除しました。",
+ "6cb6eae14f": "実行環境の保存に失敗しました。",
+ "7b5986c8df": "{{value0}} を保存しました。準備ができたら、アクティブ サーバーを使用して切り替えます。",
+ "a5b58465b6": "{{value0}} に接続されています。",
+ "5ef712f407": "「{{value0}}」という名前のサーバーはすでに存在します。",
+ "0c55a47480": "名前とペアリングコードは必須です。",
+ "e6410d72c3": "ランタイム環境の読み込みに失敗しました。",
+ "6ef71985da": "エンドポイントなし",
+ "ed3e3f069d": "これにより、保存されたサーバーが Orca から削除されます。アクティブなサーバーは変更されません。",
+ "b2fda48c39": "アクティブなサーバーを削除すると、このブラウザが切断され、そのサーバーのリモートターミナルとブラウザ タブが閉じます。",
+ "9f7665a01b": "アクティブ サーバーを削除すると、まず Orca がローカル デスクトップに戻り、そのサーバーのリモート ターミナルとブラウザ タブが閉じます。",
+ "3595fd1948": "新規リンク",
+ "54dee18f5c": "フォームを隠す",
+ "8cf8790697": "保存されたサーバーは、ペアになった Orca ランタイムを介してこのブラウザーをルーティングします。",
+ "f75ce1c7a5": "ローカルでは、現在のデスクトップの動作が維持されます。保存されたサーバーは、サポートされているクライアント呼び出しをリモート ランタイム経由でルーティングします。"
+ },
+ "RuntimePairingGeneratedUrlRows": {
+ "0495f68959": "{{value0}}をコピー"
+ },
+ "RuntimePairingUrlGenerator": {
+ "849825e829": "このペアリング URL を別の Orca クライアントに貼り付けます。",
+ "2e5c4e3c93": "別の Orca クライアントをペアリングする",
+ "f7cafdc9f3": "このビルドではブラウザ リンクを使用できません。ペアリング URL は Orca クライアントでも引き続き機能します。",
+ "6b9ca3e69b": "ブラウザで開く",
+ "1ca2e5194d": "選択したアドレスにアクセスできるブラウザからこの URL を使用してください。",
+ "8de0f84fff": "アクセスリンクの生成",
+ "279e0dcb57": "127.0.0.1 はこのコンピュータでのみ動作します。別のデバイスの LAN、Tailscale、またはカスタム アドレスを使用します。",
+ "45cf476df3": "ホスト、ホスト:ポート、または wss://host/path",
+ "4531ea3158": "カスタムアドレス",
+ "360c548cf3": "接続アドレスを更新する",
+ "de6d5cff95": "このコンピュータ (",
+ "de77eb1b65": "接続アドレス",
+ "ff80904fc4": "ブラウザまたはデスクトップ クライアントに対する取り消し可能なアクセス許可を作成します。",
+ "f8500e134a": "この Orca サーバーを共有する",
+ "d6c081adf4": "URLのコピーに失敗しました。",
+ "df0aa45a86": "ペアリング URL をコピーしました。",
+ "13704d635e": "Web クライアントの URL をコピーしました。",
+ "e8d83f2b0f": "共有アクセスを取り消すことができませんでした。",
+ "9f8e037c4a": "共有アクセスが取り消されました。",
+ "d797f516b1": "共有アクセスはすでに取り消されています。",
+ "2ed55c841a": "ペアリングURLの生成に失敗しました。",
+ "11d5248e62": "生成されたペアリング URL。",
+ "6dd594a507": "生成された Web クライアント URL。",
+ "2752126f3e": "ランタイムペアリングは利用できません。",
+ "95b8be4cea": "ネットワークインターフェースの更新に失敗しました。",
+ "1b4e0bbcc5": "共有アクセス許可のロードに失敗しました。",
+ "b91e36a986": "ウェブ"
+ },
+ "Settings": {
+ "3bf149e873": "プロジェクト設定 > {{value0}}",
+ "075341c763": "まだ形になりつつある新機能。試してみてください。",
+ "8b017f2506": "実験的機能",
+ "499c1cd7f9": "トラブルシューティングのための低レベルの互換性設定。",
+ "1c87f8d024": "詳細設定",
+ "c1b43dc4e2": "匿名の使用状況データとテレメトリ制御。",
+ "d7e3f62d70": "プライバシーとテレメトリ",
+ "9b83cc62c2": "ターミナルで起動される開発者ツールの macOS プライバシー アクセス。",
+ "65660d4548": "macOS のアクセス許可",
+ "c6c01ac209": "スマートフォンからターミナルとエージェントを操作",
+ "c40dadaac8": "モバイル",
+ "c2ee313198": "ファイル、ターミナル、git 用のリモート SSH ホスト。",
+ "9b02492d1f": "SSHホスト",
+ "b5ee17826b": "ローカル デスクトップ モードとペアリングされたリモート Orca ランタイムを切り替えます。",
+ "7686cb5c36": "このブラウザを保存された Orca サーバーに接続します。",
+ "bd0181eeca": "リモート Orca サーバー",
+ "8acf3f22e0": "Orca の統計と Claude、Codex、OpenCode の使用状況分析。",
+ "954a8f5aef": "統計と使用状況",
+ "a737a4bb22": "よく使う操作のキーボード ショートカット。",
+ "23bf7a1ad4": "ショートカット",
+ "7210ac09c4": "エージェントのアクティビティとターミナルイベントに関するネイティブのデスクトップ通知。",
+ "9907545fa3": "通知",
+ "d0b7021d64": "選択と編集の動作。",
+ "d7a3e635b6": "入力と編集",
+ "6d1a27e193": "テーマ、ズーム、アプリとターミナルの外観、サイドバー、ステータス バー。",
+ "2b4474780a": "外観",
+ "3d9adfe6a5": "グローバルターミナル、ブラウザ、およびマークダウンタブ。",
+ "3eb22a3ada": "フローティングワークスペース",
+ "01f9d36292": "Orca およびコーディング エージェントのモバイル エミュレーターのサポートを構成します。",
+ "f75daf1002": "モバイルエミュレータ",
+ "ad9788036f": "ホーム ページ、リンク ルーティング、およびセッション Cookie。",
+ "c46215ea03": "ブラウザ",
+ "6742c7932c": "グローバルまたはプロジェクトごとにスコープ設定された、保存されたターミナル コマンド。",
+ "13d4fe30ad": "クイックコマンド",
+ "b79b5b31e9": "シェル、レンダラ、セッション、およびターミナルの動作。",
+ "3de4bbb841": "ターミナル",
+ "dd72ed437a": "「タスク」ページとサイドバーに表示するタスクプロバイダーを選択します。",
+ "11faa2f7dd": "タスクソース",
+ "cfa34f4465": "ブランチの名前、基本参照、帰属、および Git AI 作成者。",
+ "70100f94c7": "Git とソース管理",
+ "b07041697f": "GitHub、GitLab、Linear、およびソース ホスティング サービスを接続します。",
+ "c9ca101a3b": "連携",
+ "f9b77539fd": "ワークスペースのデフォルト、アプリのセットアップ、メンテナンス。",
+ "7807c11c4d": "一般",
+ "6855b0f77d": "Orca を並行エージェント作業に活用するためのコア ワークフローを完了します。",
+ "6d119427ef": "オンボーディングチェックリスト",
+ "eb1176a14e": "オンデバイスモデルを使用したローカルの音声からテキストへのディクテーション。",
+ "5063bb47a5": "音声",
+ "7118953f14": "エージェントがコンピュータ上の任意のアプリを制御できるようにします。",
+ "c9841721cb": "コンピュータ操作",
+ "475980f53d": "Orca を通じて複数のコーディング エージェントを調整します。",
+ "00c3a7950d": "オーケストレーション",
+ "21f09426ea": "オプション。 Orca は既存のプロバイダー ログインと連携します。 Orca にアカウント間の切り替えを支援してもらいたい場合にのみ、アカウントを追加。",
+ "ad6c529693": "AI プロバイダー アカウント",
+ "ec1ba547f7": "AI エージェントを管理し、デフォルトを設定し、コマンドをカスタマイズします。",
+ "8afa676615": "エージェント",
+ "add3b97ee6": "」",
+ "3c88ec55d6": "「」の設定が見つかりませんでした。",
+ "c7ad095d96": "設定を読み込んでいます...",
+ "acc7bbdefd": "もう一度 ESC を押して設定を終了します",
+ "43b68e10f0": "Git AI Author の変更が保存されていません。離れるとそれらは破棄されます。",
+ "17bdee4ff1": "保存されていない Git AI Author の変更を破棄しますか?",
+ "084d8fac5b": "プライバシーとセキュリティ",
+ "23931df7e8": "リモートアクセス",
+ "8bd117d669": "インターフェース",
+ "e1578cd4bc": "ワークフロー",
+ "9abb9be3bc": "セットアップ",
+ "23c6874fdf": "AI 機能",
+ "2309068a6f": "破壊的な",
+ "65358016ea": "破棄"
+ },
+ "SettingsFormControls": {
+ "42a4d15a30": "一致するフォントがありません。",
+ "b55371ea18": "フォント",
+ "c766f8ac75": "フォントの候補を切り替えます",
+ "74bcecd5ec": "クリア",
+ "a4ff6143f8": "フォントの選択をクリア",
+ "b661b034ec": "・ デフォルト:",
+ "ceefb9d7f1": "テーマが見つかりませんでした。",
+ "9119fb2268": "現在",
+ "4e11f87ca6": "表示中",
+ "fbb428db98": "選択済み:",
+ "fac59213fc": "組み込みテーマを検索する",
+ "cb330ef7f8": "{{value0}}の",
+ "c822571b2e": "「{{value0}}」に一致",
+ "3119c012a5": "文字列"
+ },
+ "SettingsSidebar": {
+ "e0900f83e7": "SSH",
+ "5c9669ff9c": "プロジェクト",
+ "dbceaa8840": "設定を検索",
+ "60f8a673a7": "アプリに戻る",
+ "6503182299": "オンボーディングチェックリスト",
+ "82db1b7de4": "オンボーディングチェックリスト、{{value0}}/{{value1}} 完了。セットアップガイドを表示。",
+ "df38d612b7": "まだ追加されたプロジェクトはありません。",
+ "3e483e256b": "一致するプロジェクト設定がありません。"
+ },
+ "ShortcutBindingRow": {
+ "4a4c2c9d32": "ショートカットを追加",
+ "87381fd8f8": "キーを押してください…",
+ "9cdaaa3d8f": "ショートカットを無効にする",
+ "3b62c142fa": "{{value0}} を無効にする",
+ "f75335b155": "デフォルトにリセットする",
+ "4f2c9b2a05": "{{value0}} をデフォルトにリセット",
+ "97dccee14e": "修正済み",
+ "3b11ef3a43": "{{value0}} ショートカット",
+ "f6579be67b": "ショートカットを変更する",
+ "6a7848fdac": "ショートカットを記録中"
+ },
+ "ShortcutFilterRail": {
+ "28b63545bf": "状態",
+ "8a1e78c14b": "ショートカットステータスフィルター",
+ "df8466f3fc": "ショートカット検索のクリア",
+ "f733c4b89f": "コマンドまたはキーを検索する",
+ "02dc7d4251": "ショートカットを検索",
+ "1d5634ba31": "{{value0}} ショートカット"
+ },
+ "ShortcutRowsList": {
+ "4ce3cd24d9": "これらのフィルターに一致するショートカットはありません。"
+ },
+ "ShortcutTerminalPolicyControl": {
+ "0762983d13": "ターミナルファースト",
+ "63308571d8": "まずはOrca",
+ "c43c7ff5f9": "誰が最初にショートカットを傍受するかを決める",
+ "c3a554288e": "ターミナルのショートカット",
+ "0f55c6f15c": "ショートカットが重なった場合に、Orca とフォーカスされたターミナルのどちらが優先されるかを選択します。"
+ },
+ "ShortcutsPane": {
+ "4b7ae34062": "直接。",
+ "38e86e206a": "ショートカットを視覚的にカスタマイズまたは編集する",
+ "47f8f7aef9": "キーボードショートカット",
+ "f0b35b0b2e": "ターミナルまたは TUI にキーボード フォーカスがある間は無効になります。",
+ "5c65d5db9d": "ターミナルファースト",
+ "dfa8ff612f": "ターミナルまたは TUI にキーボード フォーカスがあるときにも実行されます。",
+ "2a0e8aeccf": "まずはOrca",
+ "3c0fac059a": "ターミナルにキーボード フォーカスがある間も実行されます。",
+ "25b0004fbf": "ターミナルがアクティブです",
+ "781cb74d22": "ターミナルペインから実行します。",
+ "cb02e00202": "ターミナル",
+ "d8c988dab4": "~/.orca/keybindings.json"
+ },
+ "SourceControlAiActionRecipeDefaults": {
+ "2576299196": "引数",
+ "b3914ecbbc": "破棄",
+ "fb09da4345": "コマンドテンプレート",
+ "2cb4bb7e5d": "CLI 引数",
+ "0740d30915": "カスタムコマンド",
+ "ee0e5c2a48": "デフォルトのエージェントを使用する",
+ "bf84dea6af": "Orca にコンテキストを挿入する場合にのみ変数を使用します。通常のエージェント設定に従い、エージェントをデフォルトのままにしておきます。",
+ "a79c567194": "操作レシピ",
+ "cf01d41bce": "各ソース管理 AI ボタンで使用されるエージェント、CLI 引数、およびコマンド テンプレート。",
+ "a9359c8aa9": "不明なエラー",
+ "b5f46664d3": "ソース管理 AI 操作のデフォルトを保存できませんでした: {{value0}}",
+ "d18d665e12": "保存",
+ "4f549a5fa8": "保存中...",
+ "9d3cc627f8": "保存されました",
+ "817128d94e": "未保存の変更",
+ "7ab1437a12": "PR",
+ "e5b24893ba": "専念",
+ "06a9dab64d": "チェック",
+ "cb67b938c5": "修理",
+ "2037c78a6f": "テンプレート",
+ "eb7e8f3b39": "モデル",
+ "d74fdc776c": "コマンド",
+ "673369fe0c": "cli",
+ "db9bd75d10": "引数",
+ "926d58e87f": "エージェント"
+ },
+ "SparsePresetSettingsSection": {
+ "6fa754d20f": "削除",
+ "fe1f2c6572": "{{value0}}を編集",
+ "88bfbf1a9c": "このリポジトリにはスパース プリセットが保存されていません。",
+ "d7565029a9": "新規プリセット",
+ "17f8c4ce10": "スパースワークツリー作成用に保存されたディレクトリセットを管理します。",
+ "388513be2d": "スパースチェックアウトプリセット",
+ "a05bc9183f": "プリセットの保存",
+ "2d7d45e991": "キャンセル",
+ "c240a16f25": "package/web や apps/api などのリポジトリ相対パスを使用します。",
+ "fde7ff2cc3": "パッケージ/Web共有/UI",
+ "caf33029cc": "ディレクトリ",
+ "3b6f1abd3e": "例えばウェブ限定",
+ "a6fcdd9e3c": "名前",
+ "b9922ec194": "プリセット編集をキャンセルする",
+ "694cc55ecb": "保存されたディレクトリは、このリポジトリのスパース ワークツリーを作成するときに使用されます。",
+ "8b64731aaf": "もっと",
+ "755c6a1a0d": "確認する",
+ "a7bcf206b1": "削除中",
+ "ba9ad2d4cd": "更新日不明",
+ "568d7e1e49": "{{value0}} を更新しました",
+ "d7b3f0bdc3": "{{value0}} ディレクトリ",
+ "9d3c087fc0": "1 ディレクトリ",
+ "8deb7024ab": "スパース プリセットをロードしています...",
+ "92c08ccae3": "スパース プリセットをロードできませんでした。",
+ "3dfa765ca7": "{{value0}} ディレクトリが保存されます。",
+ "b532b9c17d": "1つのディレクトリが保存されます。",
+ "623b4cf910": "プリセットの編集",
+ "68bbcd864a": "新規"
+ },
+ "SshDestructiveActionDialog": {
+ "895b216267": "キャンセル"
+ },
+ "SshPane": {
+ "c0f1c80166": "SSH ターゲットが構成されていません。",
+ "639ceb3698": "ターゲットの追加",
+ "51d7dba44d": "輸入",
+ "a7d28dff81": "Orca で接続するリモート ホストを追加します。",
+ "94c5284560": "ターゲット",
+ "f495689b82": "インポートに失敗しました",
+ "f8050f6307": "{{value0}} サーバー{{value1}} を同期しました",
+ "68c13b4589": "テストが失敗しました",
+ "81d08bcddf": "接続成功",
+ "2c4ee7332b": "リモートリレーのリセットに失敗しました",
+ "db2e48975e": "リモートリレーリセット",
+ "025e107643": "リモートターミナルの終了に失敗しました",
+ "90e308c98b": "リモートターミナルが終了しました",
+ "a43de1d3ee": "切断に失敗しました",
+ "e95d5ae10e": "接続に失敗しました",
+ "c2a69510e3": "ターゲットの削除に失敗しました",
+ "a0237eb1ca": "ターゲットが削除されました",
+ "2227ce47b6": "ターゲットの保存に失敗しました",
+ "f602009125": "ターゲットが追加されました",
+ "b4ba0ce33d": "ターゲットが更新されました",
+ "3879cbaa52": "リレーの猶予期間は 60 ~ {{value0}} 秒にする必要があります。または、リセットされるまでキープアライブを選択",
+ "4db9afce1c": "ポートは 1 ~ 65535 でなければなりません",
+ "0e5aa04161": "ホストまたは SSH 構成エイリアスが必要です",
+ "f1fc50dad2": "SSHターゲットのロードに失敗しました",
+ "0cda732f43": "接続テストに失敗しました"
+ },
+ "SshPassphraseDialog": {
+ "d5a234456f": "キャンセル",
+ "c3ce71aad6": "パスフレーズを入力",
+ "abaa0dc653": "パスワードを入力",
+ "ce4fdf7914": "のパスフレーズを入力",
+ "dbf9b6f2d0": "のパスワードを入力",
+ "c55f105262": "SSH認証情報リクエストのキャンセルに失敗しました",
+ "b8e88fd0de": "SSH認証情報の送信に失敗しました",
+ "405066423c": "ロックを解除する",
+ "bec2c1318f": "接続",
+ "8a349e3fac": "{{value0}} のパスフレーズ",
+ "cab3d5f5a5": "{{value0}} のパスワード",
+ "1f3dde805d": "SSH キーのパスフレーズ",
+ "106bd57f4a": "SSHパスワード"
+ },
+ "SshTargetCard": {
+ "ec6543cee9": "接続",
+ "0e53e9f8e8": "テスト",
+ "1810b51482": "接続中",
+ "4c86f30877": "切断",
+ "7f7b3d7ab4": "ターゲットの削除",
+ "3d21a22d0e": "ターゲットの削除",
+ "3d8af2949f": "ターゲットの編集",
+ "762a48c662": "リモートリレーをリセットする",
+ "97dea4e8cf": "リモートリレーのリセット",
+ "da16e108e6": "リモートターミナルを終了する",
+ "c77f1abfe3": "リモートターミナルの終了",
+ "18968ede9e": "エラー",
+ "f0871e6bfb": "接続",
+ "47e94bd6ba": "接続されています"
+ },
+ "SshTargetDestructiveActions": {
+ "7e66942808": "これにより、この SSH ターゲット上のアクティブなターミナルセッションが停止されます。再接続しても復元されません。",
+ "accf177a03": "リモートターミナルを終了しますか?",
+ "26be00392d": "これにより、この SSH ターゲットのリモート リレーが強制的に停止されます。このターゲットに対するアクティブなリモートターミナルとポート転送が終了します。",
+ "570a7a0574": "リモートリレーをリセットしますか?",
+ "3bb0cf0ee4": "これによりターゲットが削除され、アクティブなリモートターミナルがすべて終了します。",
+ "4808966c41": "SSHターゲットの削除"
+ },
+ "SshTargetForm": {
+ "fea9cb402e": "キャンセル",
+ "1b19b00e93": "(7日間)。",
+ "137e88ce8d": "切断後にリレーがターミナルを存続させる期間。デフォルト: 10800 (3 時間)。最大:",
+ "b574994adc": "リモートターミナルは、終了するかリレーをリセットするまで使用可能です。",
+ "71fc546097": "リセットされるまで生き続ける",
+ "92f80edbfd": "リレー猶予期間 (秒)",
+ "feae1d1e69": "オプション。 ProxyJump / ssh -J と同等。",
+ "11bcb4507a": "バスティオン.example.com",
+ "b2ab248ded": "ジャンプホスト",
+ "3b01ca44a0": "オプション。トンネリングに使用されます (Cloudflare Access、ProxyCommand など)。",
+ "f42d844544": "例えばCloudflared アクセス ssh --ホスト名 %h",
+ "c7d0e18ecb": "プロキシコマンド",
+ "cb91f6375c": "オプション。 SSH エージェントがデフォルトで使用されます。",
+ "d6a5f2ee5c": "~/.ssh/id_ed25519 (SSH エージェントの場合は空のままにします)",
+ "63c0c145c1": "アイデンティティファイル",
+ "c94cfa634c": "ポート",
+ "47e082bc17": "展開する",
+ "dc1dc52aaa": "ユーザー名",
+ "2ee9bcd2e8": "サーバー、deploy@server:2222、ssh://server",
+ "ce370ce674": "ホストまたはエイリアス *",
+ "b8dab0aa7b": "私のサーバー",
+ "298de87a88": "ラベル",
+ "9518545cb6": "ターゲットの追加",
+ "a62b4cb39a": "変更を保存",
+ "29af933cd5": "新規 SSH ターゲット",
+ "f2331ce599": "SSHターゲットの編集"
+ },
+ "TasksPane": {
+ "3a72b9745e": "[タスク] ページとサイドバーのショートカットに表示するタスク プロバイダーを選択します。",
+ "f71d8a9dd3": "タスクプロバイダー",
+ "71644aba56": "[タスク] ページのソース ピッカーとサイドバーのショートカットに表示するタスク プロバイダーを選択します。少なくとも 1 つのプロバイダーが表示されたままでなければなりません。",
+ "93e72ef659": "タスクソース",
+ "8e1305fcc6": "タスクのソース ピッカーとサイドバーのショートカットに Jira を表示します。",
+ "6b23a34f6d": "Jira",
+ "e4170c9615": "タスクのソース ピッカーとサイドバーのショートカットに Linear を表示します。",
+ "09ae2d7c51": "Linear",
+ "dd67a1b6e1": "タスクのソース ピッカーとサイドバーのショートカットに GitLab を表示します。",
+ "7c5d7fdc20": "GitLab",
+ "1db47236cd": "タスクのソース ピッカーとサイドバーのショートカットに GitHub を表示します。",
+ "e14063e727": "GitHub"
+ },
+ "TerminalAppearanceSection": {
+ "a14a427ae4": "ペイン分割線の太さ。",
+ "f27a99978d": "ディバイダーの厚さ",
+ "db632cb50e": "現在アクティブではないペインに不透明度が適用されます。",
+ "a6fdd6a3b1": "非アクティブなペインの不透明度",
+ "1b79379d4f": "非アクティブなペインの調光と分割ディバイダーの厚さを制御します。",
+ "e1a5c25555": "端子パネル",
+ "04cdf85dec": "ターミナルカーソルの不透明度。",
+ "b9f1804422": "Cursorの不透明度",
+ "2de6b5a699": "選択したカーソル形状の点滅バリアントを使用します。",
+ "74736cc9b1": "点滅Cursor",
+ "2e5aec3cf6": "下線",
+ "52854a5608": "ブロック",
+ "e070e8aeba": "バー",
+ "db270cc9a9": "Cursor形状",
+ "d455f2ef4f": "Orca ターミナル ペインのデフォルトのカーソルの外観。",
+ "abcb4dd019": "ターミナルCursor",
+ "70beb1bbc7": "プレビュー",
+ "31f6e61085": "リガチャーは現在、",
+ "870377082f": "オフ",
+ "84bd22f2cd": "の上",
+ "bc9ff84d61": "自動",
+ "be8da35e7f": "フォントの合字",
+ "4b1f29598e": "自動 - 「{{value0}}」では無効になります。",
+ "400e950ca5": "自動 - 「{{value0}}」に対して有効になります。",
+ "04569feb07": "出荷されているフォントであっても、常にオフになります。",
+ "7234abcd08": "常にオン。合字のないフォントはそのままレンダリングされます。",
+ "7233d594bf": "同梱されているフォントのプログラミング合字 (=>、!=、=== など) をレンダリングします。 「自動」では、既知の合字フォント (Fira Code、JetBrains Mono、Cascadia Code、Iosevka など) に対してのみ合字が有効になります。",
+ "bafc80efbc": "端子の線の高さの乗数を制御します。",
+ "c084eb7d4c": "線の高さ",
+ "36af8ad94c": "ターミナルテキストのフォントの太さを制御します。",
+ "4aae5db258": "フォントの太さ",
+ "f04b17a50e": "新規ペインとライブアップデート用のデフォルトのターミナルフォントファミリー。",
+ "a408266e67": "フォントファミリー",
+ "855a76343a": "Ghostty からインポート",
+ "711e589f18": "新規ペインとライブ アップデートのデフォルトのターミナル タイポグラフィ。",
+ "048aac8a64": "ターミナルのタイポグラフィー",
+ "4415beb958": "無効",
+ "4e7d41a9f0": "有効",
+ "e90afcc44f": "オフ",
+ "16c471ee03": "の上"
+ },
+ "TerminalFontSizeSetting": {
+ "9b5252c85a": "ピクセル",
+ "0f4c92e595": "新規ペインとライブ アップデートのデフォルトのターミナル フォント サイズ。",
+ "a4a352b1e9": "フォントサイズ"
+ },
+ "TerminalPane": {
+ "4263e940e0": "JIS 円 (¥) キーを押すと、代わりにバックスラッシュ (\\\\) が送信されます。",
+ "19f4935159": "JIS 円 (¥) からバックスラッシュ (\\\\)",
+ "1c337bef4a": "JIS 円 (¥) キーを押したときに、代わりにバックスラッシュ (\\\\) を送信するかどうかを制御します。",
+ "3fe1c5bfe0": "オフ",
+ "c73d510938": "右",
+ "e7aec1fd60": "左",
+ "badb1219fc": "両方",
+ "43c2ff7b0e": "自動",
+ "0a10420e1a": "Alt としてのオプション",
+ "ce3aadf0b2": "{{value0}} Option キーは Alt/Esc を送信します。もう 1 つは特殊文字を構成します。",
+ "b62373091a": "どちらの Option キーも Alt/Esc シーケンスを送信します。",
+ "d8998bb328": "オプションは、キーボード レイアウトに合わせて特殊文字を作成します。",
+ "d21c493808": "自動 — 検出されました: {{value0}}。",
+ "2561d3fc1b": "macOS の Option キーが Alt/Esc シーケンスを送信するか文字を合成するかを制御します。",
+ "96be03b8eb": "パワーシェル 7+",
+ "d26174e1dd": "Windows PowerShell",
+ "fe20f79dd1": "PowerShellのバージョン",
+ "822f62ddcd": "PowerShell をダウンロード 7+",
+ "a016ffbeed": "Auto は現在 Windows PowerShell を使用し、インストールされると PowerShell 7 以降に切り替わります。",
+ "5ed5c95344": "新規ターミナル ペインについては、Windows PowerShell と PowerShell 7+ のどちらかを選択します。",
+ "3d88af864d": "PowerShell シェル オプションで、新規ターミナル ペインに対して Windows PowerShell を起動するか PowerShell 7+ を起動するかを選択します。",
+ "8a956cc91e": "文字はダブルクリック選択の単語境界として扱われます。",
+ "4bebcc2b2c": "単語の区切り文字",
+ "12e06178fa": "MB",
+ "907b0b9d3e": "カスタム",
+ "5336c096af": "{{value0}}メガバイト",
+ "81d86b2dd2": "新規ターミナル ペインの最大ターミナル スクロールバック バッファ サイズ。",
+ "9df53f7c14": "スクロールバックのサイズ",
+ "c3810b2b42": "ターミナルスクロールバック バッファの最大サイズ。",
+ "267d020745": "スクロールバック、単語境界、およびプラットフォーム固有のターミナル動作。",
+ "5e5f06c82c": "詳細設定",
+ "003df129fe": "水平方向に分割",
+ "623e62df99": "水平方向に分割",
+ "332e8a2872": "垂直に分割",
+ "691ce810e0": "垂直に分割",
+ "1158f8fd55": "新規タブ",
+ "6c6a054a1c": "新規タブで実行",
+ "a9d47451d1": "[新規タブ] を選択すると、フォーカスを奪うことなく、[セットアップ] というタイトルのバックグラウンド タブでセットアップ コマンドが開きます。",
+ "d23b43c5be": "セットアップスクリプトの場所",
+ "34a0dfa06e": "新規ワークスペースの作成時にリポジトリ セットアップ スクリプトが実行される場所。",
+ "21f8da2078": "ワークスペースセットアップスクリプト",
+ "6e6480a7df": "ターミナル内のプログラム (tmux、Neovim、fzf、SSH) をシステムのクリップボードにコピーします。",
+ "3338dcf8c1": "TUI クリップボードへの書き込みを許可する (OSC 52)",
+ "69c64a479c": "tmux、Neovim、および fzf が PTY 経由 (SSH 経由を含む) でシステム クリップボードにコピーできるようにします。",
+ "4729c645fc": "ターミナルの選択内容をクリップボードに自動的にコピーします。",
+ "902f5dee1f": "選択時にコピー",
+ "9129b7e805": "ターミナル ペインにマウスを移動すると、クリックしなくてもターミナル ペインがアクティブになります。",
+ "8eefeaa3da": "フォーカスはマウスに追従します",
+ "96fe15def8": "ターミナルペインのマウスとクリップボードの動作。",
+ "45721f3e67": "ターミナルの相互作用",
+ "9c0b1c1792": "の上",
+ "c1fc9e9444": "GPU アクセラレーション",
+ "e0996d141a": "自動では、サポートされていないレンダラーまたは危険なレンダラーに対して DOM フォールバックを使用して、WebGL を試行します。",
+ "7eaccc1424": "WebGL はターミナル ペインに対して常に試行されます。",
+ "fe4acf36c6": "WebGL が無効になっています。最大限の互換性を実現する DOM レンダラー。",
+ "f07dfb4466": "ターミナルが xterm.js WebGL レンダリングを使用するかどうかを制御します。レンダラーがサポートされている場合、自動は WebGL を試行します。ソフトウェアまたは不明な GPU レンダラーには保守的な Linux フォールバックが使用されます。",
+ "72bc9334a0": "ライブ ペインと新規ペインのターミナル レンダラーの動作。",
+ "2fba319f21": "レンダリング",
+ "cc8c5ca224": "Windowsのデフォルト",
+ "d78fc4fdef": "ディストリビューションをロードしています",
+ "219aaa59f4": "WSLの配布",
+ "2503f1e86b": "アクティブなワークスペースがまだ WSL 内にない場合に、新規 WSL ターミナル ペインとローカル エージェントの検出に使用されます。",
+ "5fe79a5e56": "新規 WSL ターミナルとローカル エージェント スキャンが使用する WSL ディストリビューションを選択します。",
+ "b637dd57a7": "WSL",
+ "f61ac77f16": "Git Bash",
+ "0f1b8669e6": "コマンドプロンプト",
+ "eb7fc4d98a": "パワーシェル",
+ "27e301f22c": "デフォルトのシェル",
+ "09bf02de9a": "新規ターミナル ペインを開くときに使用されるシェル。新規ターミナルに対して有効になります。",
+ "bd68f3170d": "Windows 上の新規ターミナル ペインのデフォルト シェルを選択します。",
+ "a55eee649f": "Windows 上の新規ターミナル ペインのデフォルト シェル。",
+ "87e678a8af": "Windows シェル",
+ "05efc0bada": "真実",
+ "348246b06f": "間違い",
+ "5936387ddd": "自動",
+ "adbafefe56": "カスタム",
+ "16753eea48": "Windows では、右クリックしてクリップボードを貼り付けます。 Ctrl キーを押しながら右クリックすると、コンテキスト メニューが開きます。",
+ "9c178cf8aa": "右クリックして貼り付けます",
+ "af0c3b6e39": "Windows では、右クリックしてクリップボードをターミナルに貼り付けます。 Ctrl キーを押しながら右クリックしてコンテキスト メニューを開きます。",
+ "29154326bb": "の上",
+ "ab20575a8a": "オフ",
+ "ab3a1f9068": "wsl.exe"
+ },
+ "TerminalSettingsPreview": {
+ "a63953a48a": "{{value0}} テーマのプレビュー",
+ "2c248fcc27": "プレビューテーマ",
+ "f8931d407d": "プレビューでペイン分割線を表示",
+ "50419052fe": "ペインディバイダ",
+ "d06664e889": "ダーク"
+ },
+ "TerminalThemeSections": {
+ "db210115c5": "ライトモードのプレビュー",
+ "5e0c24b5c8": "ライト モードでペイン間の分割分割線を制御します。",
+ "ec2e33ad80": "ライトディバイダーの色",
+ "d56af60e6f": "Orca がライト モードのときに使用されるテーマを選択します。",
+ "8273bc75d7": "ライトテーマ",
+ "74b15574c8": "オプションのライトモードターミナルの外観を構成します。",
+ "b584287e84": "無効にすると、ライト モードはダーク ターミナル テーマを再利用します。",
+ "d76f60c9cc": "ライトモードで別のテーマを使用する",
+ "bc8e8a251a": "ダークモードのプレビュー",
+ "cbe56a0f79": "ダーク モードでのペイン間の分割分割線を制御します。",
+ "b739d2abfe": "ダークディバイダーカラー",
+ "7add204bd5": "ダークモードで使用するターミナルテーマを選択します。",
+ "9499ad1dc4": "ダークテーマ",
+ "f012172e21": "ダーク モードのターミナル ペインに使用されるテーマを選択します。"
+ },
+ "TerminalWindowSection": {
+ "1705318506": "ANSIマゼンタ色",
+ "03c855d15f": "すべての色のオーバーライドをリセット",
+ "63f8d9336e": "色のオーバーライド",
+ "e86e09b5c7": "個々の端子の色をオーバーライドします。",
+ "1d1920dc8a": "ターミナルに入力するときにマウス カーソルを非表示にします。",
+ "3530908ef9": "入力中にマウスを非表示にする",
+ "1846f6ee6a": "ターミナルグリッドの周りの垂直方向のパディング (ピクセル単位)。",
+ "1afcc1d973": "垂直パディング",
+ "25e2f8e8e1": "ターミナルグリッドの周囲の水平方向のパディング (ピクセル単位)。",
+ "36b8402015": "水平方向のパディング",
+ "53ce336e15": "Orca を再起動して、ウィンドウのぼかしの変更を適用します。",
+ "c65bb9ce63": "再起動が必要です",
+ "97950bb087": "ターミナルウィンドウに背景のぼかしを適用します。再起動が必要です。",
+ "2b82242f43": "窓のぼかし",
+ "809f37738d": "ターミナルの背景の透明度を制御します。 1 は完全に不透明、0 は完全に透明です。",
+ "ea7b1a158e": "背景の不透明度",
+ "03acb60aa0": "ターミナルの背景の透明度を制御します。",
+ "00eaa6b881": "ウィンドウの外観と背景の設定。",
+ "b96ba13ed1": "ウィンドウ",
+ "42e01a6055": "ANSI明るい白色",
+ "16948119cb": "ブライトホワイト",
+ "1601140f03": "ANSI 明るいシアン色",
+ "f94adc4113": "ブライトシアン",
+ "fe4d89ef85": "ANSI明るいマゼンタ色",
+ "e56e7d6ea0": "明るいマゼンタ",
+ "bef6c0f6bf": "ANSI明るい青色",
+ "66820332fa": "ブライトブルー",
+ "e2ef5f4ab7": "ANSI 明るい黄色",
+ "936a326be3": "明るい黄色",
+ "0ffb02f921": "ANSI 明るい緑色",
+ "7dafd57730": "ブライトグリーン",
+ "667de68863": "ANSI の明るい赤色",
+ "32b1b6acd7": "ブライトレッド",
+ "f30c492769": "ANSI明るい黒色",
+ "260d69ce9a": "ブライトブラック",
+ "1be593d3e8": "ANSI ブライト",
+ "28846b1ca6": "ANSI白色",
+ "0cb4459fb8": "白",
+ "bd4c759327": "ANSI シアン色",
+ "fb8bb4eb1f": "シアン",
+ "d5e92fcd94": "マゼンタ",
+ "9635a71c51": "ANSIブルーカラー",
+ "292a4c7316": "青",
+ "09c1c6b096": "ANSI黄色",
+ "bb516de873": "黄色",
+ "8a673d4206": "ANSI 緑色",
+ "8f2092b315": "緑",
+ "b41270f5ca": "ANSI赤色",
+ "3a78f30b50": "赤",
+ "cf4437a2f7": "ANSI黒色",
+ "adfdee23cb": "黒",
+ "68e9f07de0": "ANSI標準",
+ "fb8c6f1967": "太字のテキストの色。設定されていない場合は、通常の色に戻ります。",
+ "862e463f7f": "太字のテキスト",
+ "b2c0857c49": "選択したテキストの文字色",
+ "8b450b5305": "選択範囲の前景",
+ "74d8555f85": "選択したテキストの背景色",
+ "40c3cfd30a": "選択の背景",
+ "7f4063076c": "カーソル下の文字の色(ブロックカーソル)",
+ "a2d9f095a7": "Cursor文字",
+ "cd0700762b": "Cursor色",
+ "c9e1fdf42f": "Cursor",
+ "da64e8f4c1": "ターミナルの背景色",
+ "cc1b2ffeb2": "背景",
+ "026a0b8013": "本文の文字色",
+ "79f6bfb76e": "前景",
+ "cf37ff69f6": "ベース",
+ "8abdab9f7c": "今すぐ再起動",
+ "907131d741": "再起動中…"
+ },
+ "UIZoomControl": {
+ "c2c64b24d0": "リセット"
+ },
+ "VoicePane": {
+ "68de13f72c": "モデルの削除に失敗しました。",
+ "1ba81c0ff0": "推奨",
+ "cfde55c7b0": "モデルのダウンロードに失敗しました。",
+ "43fd4f454b": "音声モデル",
+ "7cf715f891": "が開催されます。",
+ "295d84b849": "一度開始し、もう一度停止します。ホールド: 言いながら言い続ける",
+ "ff9a680010": "トグル: 押す",
+ "ba4a900d1d": "ディクテーションモード",
+ "0121960365": "音声ディクテーションを有効にする",
+ "366e1b4f36": "フォーカスされたペインにテキストを書き込むことができます。",
+ "4465596675": "プレス",
+ "62d2a84d31": "OpenAI APIキーのクリアに失敗しました",
+ "37aba8bb63": "OpenAI APIキーがクリアされました",
+ "8572bbb537": "OpenAI APIキーの保存に失敗しました",
+ "506df81ba6": "OpenAI API キーが保存されました",
+ "91980ce124": "{{value0}} MB",
+ "61a16c8141": "抽出中...",
+ "b6536a1d12": "抽出する",
+ "8f4d2a51d7": "オフライン",
+ "d504ab05f0": "ストリーミング",
+ "fbe5990716": "モデルの選択",
+ "e24f7d43d2": "音声モデルを選択します。ローカル モデルはオフラインで実行されます。クラウド モデルには API キーが必要です。",
+ "174da92062": "所有",
+ "118b3c2dee": "トグル",
+ "901985625d": "トグル",
+ "ad5d036ecc": "マイクの許可を要求できませんでした。音声ディクテーションが有効になっていませんでした。",
+ "f9a9cf6928": "音声ディクテーションを有効にする前に、マイクの許可が必要です。",
+ "1eac933202": "macOS のプライバシーとセキュリティを開きました。アクセスを許可した後、ディクテーションを再度有効にします。",
+ "cd9fe37556": "マイクの許可が与えられました"
+ },
+ "WorktreeSymlinksSection": {
+ "1c1e35b219": "{{value0}} を削除",
+ "b814c618e2": "リンクされたパス",
+ "31ebab5403": "このリポジトリにはシンボリックリンク パスが設定されていません。",
+ "ea06227efa": "追加した",
+ "b2429aeb31": "追加",
+ "ab40b8a5f1": "一致はありません。入力を続けてカスタム パスを追加します。",
+ "4cd2a4c077": "パスを入力します (例: .env または node_modules)…",
+ "241325302c": "パスの追加",
+ "7ff265071d": "新規ワークツリーが作成されると、ここにリストされている各パスがプライマリ チェックアウトからシンボリックリンクされます。",
+ "4755f120b6": "ワークツリーのシンボリックリンク",
+ "b07ef5a8b6": "プライマリ チェックアウトから新しく作成されたワークツリーへのシンボリックリンクへのパス。",
+ "d72ba8dc68": "{{value0}} パス",
+ "9ea912d811": "1パス"
+ },
+ "WslCliRegistration": {
+ "c6f6f89d7c": "キャンセル",
+ "119fef6cd2": "ターゲットパス:",
+ "1dbb0377d9": "既存のランチャーターゲット:",
+ "554305956d": "コマンドパス:",
+ "9b6627522c": "更新",
+ "ab6b022a5c": "WSL CLI ステータスを更新する",
+ "d9c6880dbd": "WSLシェルコマンド",
+ "52d990420e": "WSL から `{{value0}}` を削除できませんでした。",
+ "89c7414cf5": "WSL から {{value0}} を削除しました。",
+ "6f91ad1333": "WSL への {{value0}} の登録に失敗しました。",
+ "951536dda5": "`{{value0}}`をWSLに登録しました。",
+ "26b4b3b00f": "WSL CLI ステータスのロードに失敗しました。",
+ "290bfff3ab": "登録する",
+ "f951f85196": "削除",
+ "4c4a9178a3": "登録中...",
+ "41a1480d3e": "インストール",
+ "4598b18464": "削除中...",
+ "7c3bb36706": "削除",
+ "7ee4e52b99": "Orca は {{value0}} を登録するため、コマンドは WSL ターミナルから機能します。",
+ "d8216eb22e": "これにより、WSL シェル コマンドが削除されます。 Orca 自体は Windows にインストールされたままになります。",
+ "e49688f67f": "`{{value0}}` を WSL に登録しますか?",
+ "61ac55278e": "WSL から {{value0}} を削除しますか?",
+ "e2b0ee267f": "古い",
+ "7aa456a460": "WSL内の~/.local/binに「orca-ide」を登録します。",
+ "0307677bb9": "WSL CLI 登録を確認しています..."
+ },
+ "accounts": {
+ "search": {
+ "86edc96bc9": "ステータスバー",
+ "e949b08ffb": "レート制限",
+ "7e67d7d1b6": "仕事",
+ "421c6be25e": "ID",
+ "be8b621bdc": "ワークスペース",
+ "8dcbef1856": "opencode",
+ "38d22ff8d6": "自動検索が失敗した場合は、オプションのワークスペース ID をオーバーライドします。",
+ "4ee2029e9c": "OpenCode Go ワークスペース ID",
+ "9c4e40cf6b": "セッション",
+ "61f7d1fcbe": "クッキー",
+ "d1d2ae383c": "レート制限を取得するために、opencode.ai セッション Cookie を貼り付けます。",
+ "6ed1401020": "OpenCode Go セッション Cookie",
+ "b7c2cee442": "実験的機能",
+ "7118d2f908": "資格",
+ "933deaf732": "認証",
+ "8630464352": "CLI",
+ "e8e1ff3887": "gemini",
+ "bada4a3218": "ローカルの Gemini CLI インストールから OAuth 認証情報を抽出して、Google で認証します。",
+ "d819755b02": "Gemini CLI 認証情報を使用する",
+ "35b461d817": "サインイン",
+ "f2d666a886": "オプション",
+ "8b06729e0f": "アクティブ",
+ "5b3f18ef4a": "スイッチ",
+ "06662af91e": "アカウント",
+ "70d1b8def5": "codex",
+ "87a4a8584e": "ライブ クォータ読み取りを強化するオプションの保存済み Codex アカウントを選択します。",
+ "a4bcfd6f86": "アクティブなCodex アカウント",
+ "042885c07c": "期限切れの",
+ "02c438bc7b": "期限切れ",
+ "77e32a2ad3": "再認証する",
+ "c759741d77": "クォータ",
+ "b40d5b6570": "Codex およびライブ レート制限取得のためのオプションのアカウント切り替え。",
+ "17c5d244eb": "Codexアカウント",
+ "e14049e1a8": "claude",
+ "dd75a73991": "共有チャット コンテキストを維持しながら、Claudeのオプションのアカウント切り替え。",
+ "75682e1b62": "Claude・アカウント",
+ "e02c136ad0": "認証",
+ "9f70aa706c": "プロバイダー",
+ "488a7e9206": "リナックス",
+ "0b4d948eb5": "wsl",
+ "bdbd1e668e": "窓",
+ "593720c17f": "場所",
+ "b84a5b0c8a": "プロバイダー アカウントをこのデバイスまたは WSL で検査および追加するかどうかを選択します。",
+ "d09fb5ca92": "アカウントの場所"
+ }
+ },
+ "advanced": {
+ "search": {
+ "a7002e1ac4": "アップデーター",
+ "e61ed8ab33": "アップデート",
+ "6576fce4d2": "トラブルシューティング",
+ "79e0947e95": "サポート",
+ "4383251647": "VPN",
+ "f98a60af11": "プロキシ",
+ "65bf6af262": "互換性",
+ "621233008b": "http/1.1",
+ "f8ff125ebe": "http1",
+ "a0f71bd909": "http/2",
+ "4b4ae4345a": "http2",
+ "48a1c8f534": "http",
+ "4d44352eea": "ネットワーク",
+ "2b4d26d11e": "ネットワーキング",
+ "e04e9db503": "詳細設定",
+ "585f56fae0": "プロキシの背後で HTTP/2 が失敗した場合は、Electron ネットワークに HTTP/1.1 を使用します。",
+ "11eea3da72": "HTTP/1.1 互換性"
+ }
+ },
+ "agents": {
+ "search": {
+ "2814401339": "インストール済み",
+ "719f53350c": "パス",
+ "839e82c81f": "検出",
+ "f622b8eb2a": "リナックス",
+ "d608654c03": "wsl",
+ "77c02fa3c3": "窓",
+ "d2952dfd74": "場所",
+ "96ba2373b6": "エージェント",
+ "cbdd7f3b9e": "インストールされているエージェントがこのデバイスまたは WSL で検出されるかどうかを選択します。",
+ "ef804b7337": "エージェントの場所",
+ "01926b9d8c": "AI コーディング エージェント、デフォルト エージェント、およびコマンド オーバーライドを構成します。",
+ "bb9ad95777": "エージェント",
+ "d8f3a8b8a0": "デフォルト",
+ "167daeb5e9": "コマンド",
+ "be59907510": "上書き",
+ "a6d594c17d": "インストール",
+ "f2932bf22b": "検出済み",
+ "2afd3b5858": "有効化",
+ "60393e1b17": "無効化",
+ "2e188c771c": "非表示",
+ "87fffe6c20": "表示",
+ "e2b7c0dcd7": "github",
+ "66b6b82eb4": "起きたまま",
+ "dbc8aca6b0": "スリープ",
+ "845ad9128a": "電源",
+ "48f84d10f1": "実行中",
+ "affbf130f6": "作業中",
+ "0d1c334987": "蓋",
+ "ff8de8a2ad": "ディスプレイ",
+ "0d752916f8": "フック",
+ "6984d4291a": "状態",
+ "13b20636a6": "待機",
+ "8599603496": "完了",
+ "ea71995548": "削除",
+ "c1317fe641": "復元",
+ "5963143e00": "設定",
+ "042c551bc5": "構成",
+ "f412abbba5": "claude",
+ "5ded38b843": "codex",
+ "be7ea3553b": "タブ",
+ "6956646a1e": "タイトル",
+ "32836788b0": "生成されたタイトル",
+ "966890236d": "名前",
+ "848dcae8d3": "生成",
+ "52115d0d7c": "自動",
+ "c64059f50d": "プロンプト",
+ "5784ae8c43": "名前変更",
+ "8a17fd6026": "安定",
+ "a79d266f71": "セッション",
+ "afbf35be68": "安定したセッション"
+ }
+ },
+ "appearance": {
+ "search": {
+ "468448bba4": "水彩",
+ "f586abfa35": "青",
+ "651f35b2c6": "スイッチャー",
+ "e5bc35d59e": "ウィンドウ",
+ "d18b54ca90": "ドック",
+ "1f2880a9d5": "orca",
+ "2cfb3420c0": "アプリアイコン",
+ "e80c2af428": "Dock とウィンドウのスイッチャーに表示されるアプリのアイコンを選択します。",
+ "2b313598c6": "アプリアイコン",
+ "839fb1e3ed": "ツールボックス",
+ "ac79fe4a04": "表示",
+ "648eeada79": "非表示",
+ "6cf5f54ce1": "ボタン",
+ "5bff6a2ef0": "サイドバー",
+ "5e5b8878bf": "スマートフォン",
+ "74618577c7": "モバイル",
+ "682293cadf": "左側のサイドバーの上部に Orca Mobile ボタンを表示します。",
+ "1de96ec8a6": "Orca モバイル ボタンを表示",
+ "4c920ab2d1": "スケジュール",
+ "58f4e22fa2": "オートメーション",
+ "b186f3cefb": "自動化",
+ "ae13a0d340": "左側のサイドバーの上部に [オートメーション] ボタンを表示します。",
+ "caa27e1a8e": "オートメーションボタンを表示",
+ "6b846424cc": "Linear",
+ "2ee4810f38": "github",
+ "0d5a74b606": "タスク",
+ "9a248333c7": "左側のサイドバーの上部に「タスク」ボタンを表示します。",
+ "155a1e7438": "タスクボタンを表示",
+ "a895d0f938": "ブランド",
+ "51f957ce39": "名前",
+ "36e006efc1": "アプリ",
+ "bed343b03e": "タイトルバー",
+ "18b4c4c30b": "タイトルバーに Orca を表示します。",
+ "fdd31b00d0": "タイトルバー アプリ名",
+ "c1bca1885a": "ファイルエクスプローラー",
+ "9f2df826ac": "無視されました",
+ "08c86bf58e": "ギティ無視",
+ "bce3ac317a": "git",
+ "7164edf71a": "ファイル エクスプローラーで .gitignore と一致する Dim ファイル。",
+ "f8129fb544": "Git で無視されたファイルを表示する",
+ "2f12e1aa3a": "ウイ",
+ "5095258df2": "インターフェース",
+ "fab91464dd": "いで",
+ "8b36fb3f64": "タイポグラフィ",
+ "a0e09aed9c": "書体",
+ "24094af355": "フォント",
+ "07c7c38fac": "Orca インターフェイスで使用されるフォントを選択します。",
+ "ddb991024d": "IDE フォント",
+ "0c83659f48": "ショートカット",
+ "0952091186": "倍率",
+ "3ae5de6101": "ズーム",
+ "adddb91a3d": "アプリケーションインターフェイス全体をスケーリングします。",
+ "c5e933970f": "UIズーム",
+ "3a9b69d734": "システム",
+ "44d873fd18": "ライト",
+ "262fe1d24f": "ダーク",
+ "0709c794f7": "アプリ ウィンドウで Orca がどのように見えるかを選択します。",
+ "71e06350b4": "テーマ",
+ "dc02c8759d": "ワークスペース",
+ "43cfba3b95": "サーバ",
+ "46d21eef62": "ローカルホスト",
+ "006e67b279": "ポート",
+ "896eb53fd4": "ステータスバー",
+ "0ececfa190": "ステータスバーにライブワークスペースポートを表示します。",
+ "cf409b6c4d": "ポート",
+ "cb1cc62cf8": "スペース",
+ "90bdc043ea": "ディスク",
+ "96b4fb0064": "ターミナル",
+ "4ddbde4999": "CPU",
+ "4355f18ac6": "メモリ",
+ "9c4d5f0894": "マネージャー",
+ "c690a15849": "リソース",
+ "81ef5abc2f": "CPU、メモリ、ターミナル セッション、ワークスペース ディスクの使用状況をステータス バーに表示します。",
+ "7cf005b29f": "リソースマネージャー",
+ "fe192b060e": "ホスト",
+ "f4997e0f8a": "繋がり",
+ "a278406ed5": "リモート",
+ "6ecad74eb3": "ssh",
+ "f17d66d0d2": "アクティブな SSH 接続ステータスをステータス バーに表示します。",
+ "57fb424c56": "SSHステータス",
+ "35565867cb": "ムーンショット",
+ "de586def95": "サブスクリプション",
+ "00a028f25f": "使用法",
+ "40e5c3c285": "kimi",
+ "c927a155d5": "ステータス バーに Kimi サブスクリプションの使用状況を表示します。",
+ "3a6c028ea8": "Kimi 使用量",
+ "edbf0f63a0": "料金",
+ "afbb6a3767": "トークン",
+ "d77537b580": "opencode-go",
+ "a9d56852eb": "opencode",
+ "7f72de7cbe": "OpenCode Go トークンとコストの使用状況をステータス バーに表示します。",
+ "bc046e7899": "OpenCode Go の使用法",
+ "51b0ccd6a2": "グーグル",
+ "2804a920ad": "gemini",
+ "9660c5b2f1": "Gemini トークンとコストの使用状況をステータス バーに表示します。",
+ "5bfb874d05": "Gemini 使用量",
+ "97957e374e": "openai",
+ "8dfd676c28": "codex",
+ "e9e4412545": "Codex トークンとコストの使用状況をステータス バーに表示します。",
+ "54b1acf24f": "Codex 使用量",
+ "dea0a9a665": "anthropic",
+ "c9fe3a7876": "claude",
+ "de50c6f516": "ステータスバーにClaudeトークンとコストの使用状況を表示します。",
+ "9dc15020d7": "Claude 使用量",
+ "language": {
+ "locale": "ロケール",
+ "i18n": "i18n",
+ "translation": "翻訳"
+ }
+ }
+ },
+ "auto": {
+ "rename": {
+ "branch": {
+ "search": {
+ "0971762141": "ケバブケース",
+ "a482f6a423": "ナメクジ",
+ "7adefcdd94": "テンプレート",
+ "10485c4fc5": "コマンド",
+ "50139297e6": "組み込みプロンプト",
+ "502aa57681": "説明書",
+ "40d21f2efc": "プロンプト",
+ "672387fb77": "ブランチ名の生成時に使用されるエージェント コマンド テンプレート。",
+ "722551c5b3": "ブランチ名コマンドテンプレート",
+ "f41833025e": "生成する",
+ "ed677944cc": "ワークツリー",
+ "3ef3cbe98c": "エージェント",
+ "f0acf64301": "生き物の名前",
+ "7803423877": "自動",
+ "55a1860e47": "名前変更",
+ "9319bd9827": "ブランチ",
+ "ea94b9da8a": "エージェントが起動したら、作業に基づいて自動生成されたブランチの名前を変更します。",
+ "427f2cd1eb": "ブランチ名の自動変更"
+ }
+ }
+ }
+ },
+ "browser": {
+ "search": {
+ "7539f6336c": "プロフィール",
+ "1c1e097985": "アーク",
+ "533a253deb": "角",
+ "75a0d435b7": "クロム",
+ "854ef6ce83": "ログイン",
+ "3910a41f32": "認証",
+ "2e7f951773": "輸入",
+ "66dd641a47": "セッション",
+ "29193a51d5": "クッキー",
+ "2d2d995c58": "ブラウザ",
+ "060ac1fcba": "Chrome、Edge、またはその他のブラウザから Cookie をインポートして、Orca 内の既存のログインを使用します。",
+ "96afedcb5c": "セッションとクッキー",
+ "a7a07d5415": "エディタ",
+ "8dd4805991": "ファイル",
+ "68d1db8929": "値下げ",
+ "90425d313c": "シフト",
+ "72c58f7792": "ウェブビュー",
+ "82ba1c80ea": "ローカルホスト",
+ "bea27bac4b": "リンク",
+ "44d14df30d": "プレビュー",
+ "5cb082b3e3": "リンクルーティング",
+ "95944898e0": "割合",
+ "483a0eb5e0": "新規タブ",
+ "726f2a8556": "ページズーム",
+ "5448f4097b": "デフォルト",
+ "54f4ea55f7": "倍率",
+ "4a98ed195f": "ズーム",
+ "c3d89ed4d0": "新しく開いたブラウザー タブに適用されるズーム レベル。",
+ "072b7f5c1f": "デフォルトのズーム",
+ "0bb34eacc9": "クエリ",
+ "8b8ed06e4b": "オムニボックス",
+ "3538b3aaeb": "トークン",
+ "0732ebe6fb": "プライベート",
+ "e1c2a57f07": "かぎ",
+ "ad40e75d13": "ビング",
+ "1f8153acfb": "アヒルアヒル",
+ "8a489aab8d": "グーグル",
+ "72b4b89970": "エンジン",
+ "16bd69cd82": "検索",
+ "0628d5943b": "アドレスバーに URL 以外のテキストを入力するときに使用される検索エンジン。",
+ "5e755920c9": "デフォルトの検索エンジン",
+ "4596a52cf7": "着陸",
+ "5164c47e31": "空白",
+ "4fda4fb066": "URL",
+ "0dbb1eaf4e": "ホームページ",
+ "291f480a5e": "家",
+ "a942905148": "新規ブラウザ タブを作成するときに開かれる URL。空白のタブを開くには、空白のままにします。",
+ "c3903322d2": "デフォルトのホームページ"
+ },
+ "use": {
+ "search": {
+ "3f4c559deb": "円弧プロファイル",
+ "d5afa54d21": "エッジプロファイル",
+ "22fb801af8": "クロムプロファイル",
+ "59968bb9b4": "認証されたブラウザ",
+ "62e2a790c0": "既存のセッション",
+ "63a66da648": "システムブラウザ",
+ "20c1323d1e": "コンピュータ操作",
+ "ab349a2dd0": "アーク",
+ "2e1b09897b": "角",
+ "088e7a9012": "クロム",
+ "96ce3d2de2": "認証",
+ "48557f639c": "ログイン",
+ "d5ad1f7aad": "輸入",
+ "02837ee497": "セッション",
+ "fb8178824f": "クッキー",
+ "ba4eb53b72": "ブラウザの使用",
+ "2fb24d17db": "Chrome、Edge、またはその他のブラウザから Cookie をインポートすると、エージェントがログインを再利用できるようになります。",
+ "614c756ab1": "ブラウザの Cookie をインポートする",
+ "cee44fb442": "オートメーション",
+ "a57c2172dc": "エージェントブラウザ",
+ "6ea88e5206": "npx",
+ "f5b8fdddf5": "orca-cli",
+ "e5a784bc54": "インストール",
+ "9d97446873": "エージェント",
+ "a2d489263e": "スキル",
+ "a7e82445fa": "ブラウザをインストールする スキルを使用すると、エージェントが Orca のブラウザを操作できるようになります。",
+ "a1414dcefb": "ブラウザ使用スキルをインストールする",
+ "e56c7b55c9": "設定",
+ "034c5e8d7f": "有効化",
+ "7e0dcb257a": "シェル",
+ "3ffafc9b95": "コマンド",
+ "30c74aaa1f": "パス",
+ "ff05cbc344": "orca",
+ "85fab5e12c": "CLI",
+ "890ddf943d": "エージェントがブラウザを操作できるように Orca CLI を登録します。",
+ "50f0860e18": "Orca CLI を有効にする"
+ }
+ }
+ },
+ "commit": {
+ "message": {
+ "ai": {
+ "search": {
+ "3766941527": "エージェント",
+ "181cdb0637": "開く",
+ "8e9cc598d7": "生成する",
+ "b7d50da4d8": "テンプレート",
+ "7e264b926b": "下書き",
+ "b261c88609": "PR",
+ "110be48b81": "PR",
+ "001ca3f2af": "Create PR コンポーザーが開いたときに使用されるデフォルト。",
+ "eefd33788c": "PR 作成のデフォルト",
+ "d32936bb2a": "ブランチ",
+ "127d512e75": "専念",
+ "d22a6459e4": "衝突",
+ "53e8504fb2": "シ",
+ "c46e665f7e": "チェック",
+ "37c65bbb44": "修理",
+ "402f101af8": "プロンプト",
+ "8e0bcc5d99": "モデル",
+ "f4731b22bf": "コマンド",
+ "57c851a68c": "CLI",
+ "61117e57f3": "引数",
+ "0f29331fed": "引数",
+ "18b6d38835": "各ソース管理 AI ボタンで使用されるエージェント、CLI 引数、およびコマンド テンプレート。",
+ "3c4e5e5938": "操作レシピ",
+ "ee14a9e9f7": "有効",
+ "82109d627d": "ソース管理",
+ "542e1a00a7": "codex",
+ "f121bec167": "claude",
+ "93e5210da8": "メッセージ",
+ "c33cb1b982": "あい",
+ "0b946b2abe": "ソース管理のコミット、PR、ブランチ名、および修正操作の操作 レシピを追加します。",
+ "24dbdfca78": "ソース管理 AI 操作を表示する"
+ }
+ }
+ }
+ },
+ "computer": {
+ "use": {
+ "search": {
+ "6e88da3508": "スキル",
+ "798be54d7e": "オートメーション",
+ "e27f8bafbf": "スクリーンショット",
+ "26c1290d83": "画面録画",
+ "82f01c2d2c": "アクセシビリティ",
+ "fefb452f5b": "コンピュータ操作",
+ "9210db582b": "エージェントがスクリーンショットを検査し、要求に応じてローカル アプリを操作できるようにします。",
+ "442bec10fe": "コンピュータ操作"
+ }
+ }
+ },
+ "developer": {
+ "permissions": {
+ "search": {
+ "3363889768": "ローカルネットワーク、USB、Bluetooth",
+ "6c82846f66": "デバイス",
+ "11653d3f42": "MDNS",
+ "78a10b826f": "ボンジュール",
+ "e3fbc48083": "ブルートゥース",
+ "c4a4a02ea4": "USB",
+ "fa3239cd42": "ローカルネットワーク",
+ "acad3d4743": "ターミナル セッションから使用されるデバイスおよびローカル ネットワーク ツールを許可します。",
+ "3e0131e45d": "アイクラウド",
+ "ce07159ff5": "デスクトップ",
+ "a0c19119fb": "ダウンロード",
+ "4438f81bfa": "書類",
+ "c10e36cbd1": "フルディスクアクセス",
+ "05ab708ee5": "macOS のプライバシー ペインを開いて、広範囲のターミナル ファイルにアクセスします。",
+ "bbf543a3a1": "フルディスクアクセス",
+ "7f145a3984": "ウィンドウ",
+ "5610022e1e": "オートメーション",
+ "0a467b750e": "スクリーンショット",
+ "08f8039ca9": "アクセシビリティ",
+ "3cd51d18a1": "画面録画",
+ "2e5d98ab56": "スクリーンショット、画面検査、キーストローク、ウィンドウの自動化を許可します。",
+ "39bb49e662": "画面録画とアクセシビリティ",
+ "00e954319e": "ささやき声",
+ "1e6e27b202": "ffmpeg",
+ "f061f08b7b": "ソックス",
+ "a765112513": "ビデオ",
+ "b192432ef0": "オーディオ",
+ "af122938a3": "声",
+ "259b829b84": "カメラ",
+ "ed7c12bdb4": "マイクロフォン",
+ "6eca1636b7": "音声、文字起こし、Web カメラ、メディア キャプチャ ツールを許可します。",
+ "302c0c42f9": "マイクとカメラ",
+ "4e225e7c56": "開発者ツール",
+ "6db4fca386": "マコス",
+ "0c13b249e3": "tcc",
+ "2270ccff3f": "プライバシー",
+ "a98aa11a9c": "権限",
+ "bc8ac95310": "ターミナルで起動される開発者ツールの macOS 権限。",
+ "e92cb0896d": "開発者の権限"
+ }
+ }
+ },
+ "experimental": {
+ "search": {
+ "44c7f209d5": "ノードモジュール",
+ "4ad605f222": "環境",
+ "3021571c30": "共有",
+ "f082788cfe": "リンク",
+ "3028f0bd3a": "リンク",
+ "bff1ff7768": "シンボリックリンク",
+ "c387565812": "シンボリックリンク",
+ "10b52f79c1": "ワークツリー",
+ "d23ae13990": "ワークツリー",
+ "0d24759f14": "実験的機能",
+ "603d29ed74": "構成されたファイルまたはフォルダーを新しく作成されたワークツリーに自動的にシンボリックリンクして、共有状態 (環境、キャッシュ、インストール) が接続された状態を維持します。",
+ "78c2a8dc74": "ワークツリー上のシンボリックリンク",
+ "7b79081695": "未読",
+ "f10d307468": "完了",
+ "5f067ba0f9": "エージェント",
+ "7695fd30e9": "通知",
+ "8facf10138": "ベル",
+ "edc49480a1": "ペイン",
+ "268e99d957": "ハイライト",
+ "01567f19ca": "注意",
+ "9bb3bd5098": "ターミナル",
+ "11877246fc": "ターミナルベルおよびエージェント完了イベントの永続的なペインのハイライト。",
+ "9e4ddf776d": "ターミナルアテンション",
+ "fe5688b761": "サイドバー",
+ "ca5d1f3f46": "タイムライン",
+ "d01b3882ba": "通知",
+ "244a0ecd3d": "アクティビティ",
+ "92a9357d1f": "エージェントビュー",
+ "fa72e71f05": "エージェント",
+ "4d63251595": "エージェントの完了とブロック状態を示すスレッド化された左側のサイドバー フィード。",
+ "ccc5548ac5": "エージェントビュー",
+ "9af7a518db": "キャラクター",
+ "791fefc0b0": "コーナー",
+ "65df471ab2": "アニメーション化された",
+ "9f5609bfb8": "かぶせる",
+ "2a33975d72": "マスコット",
+ "b54cea709b": "相棒",
+ "051203d37c": "ペット",
+ "6b5a56ac35": "右下隅に浮かぶアニメーションのペット。",
+ "87d99e634b": "ペット"
+ }
+ },
+ "floating": {
+ "workspace": {
+ "search": {
+ "94f4d013c8": "ステータスバー",
+ "a452146574": "トグルボタン",
+ "6765b85e48": "起動ディレクトリ",
+ "a38bfc3f77": "クイックパネル",
+ "52db6e3baf": "メモ",
+ "156ffeee08": "注記",
+ "884e5e6132": "値下げ",
+ "49db74a92d": "ブラウザ",
+ "6410fe83d8": "ターミナル",
+ "2b5efa55c9": "グローバル",
+ "ebeedb2f6a": "クイックターミナル",
+ "6f183fa1b9": "フローティング端子",
+ "a08e482f6d": "フローティングワークスペース",
+ "b96b5ee6cf": "フローティング ワークスペースを有効にし、新規タブの開始場所を選択し、トグル ボタンが表示される場所を選択します。",
+ "b2b60e7163": "フローティングワークスペース"
+ }
+ }
+ },
+ "general": {
+ "search": {
+ "bdfb6dc21b": "のように",
+ "e6b01c8e30": "フィードバック",
+ "b65665703a": "サポート",
+ "06ea5a69a6": "github",
+ "e4fb4516d0": "星",
+ "e0b8c8bc25": "gh CLI を介して GitHub スターでプロジェクトをサポートします。",
+ "36a72f0d9e": "GitHub 上のスターOrca",
+ "c61b14be7c": "grok",
+ "5d9ba08673": "copilot",
+ "f472e97440": "aider",
+ "3c30fe2d51": "gemini",
+ "5fdf1dc2d1": "omp",
+ "9b0bc30160": "pi",
+ "882c4896fd": "opencode",
+ "27d9b996ba": "codex",
+ "5baf51c4d9": "open claude",
+ "aea7d2cccb": "openclaude",
+ "95b63edde7": "claude",
+ "41c2f9a025": "デフォルト",
+ "8ea37a05bc": "エージェント",
+ "e2da948f59": "新規ワークスペース コンポーザーで AI コーディング エージェントを事前に選択します。",
+ "db11502270": "デフォルトのエージェント",
+ "3462308bd3": "トークン",
+ "660528b048": "料金",
+ "585beac3f8": "ttl",
+ "0efc9d96ad": "プロンプト",
+ "939b80f5fd": "タイマー",
+ "b2601a778c": "キャッシュ",
+ "40c9585e43": "プロンプト キャッシュが期限切れになるまでの時間を示すカウントダウン タイマー (Claude エージェント)。",
+ "1e0f28c6f1": "プロンプトキャッシュタイマー",
+ "e49e739a59": "ダウンロード",
+ "c9d8c1ce66": "リリースノート",
+ "9e86ccd05c": "バージョン",
+ "f89a94773c": "更新",
+ "79ff46776e": "アプリのアップデートを確認し、新規 Orca バージョンをインストールします。",
+ "e15af4eb64": "アップデートをチェックする",
+ "6382fe9724": "npx",
+ "baa263d6d8": "エージェント",
+ "bda108e66c": "スキル",
+ "244e3fb4c8": "Orca スキルをインストールして、エージェントが Orca CLI を使用できるようにします。",
+ "2d9f7b42df": "エージェントスキル",
+ "0a00691c06": "シェルコマンド",
+ "dbeb1f348e": "コマンド",
+ "88d3df9ce9": "ターミナル",
+ "fb4f338a3d": "パス",
+ "924a660a78": "CLI",
+ "ca529079bf": "Orca CLI コマンドを登録または削除します。",
+ "327e3fa70d": "Orca CLI",
+ "fb84767421": "スイッチ",
+ "f8f0ac213a": "一連",
+ "12ecc640a8": "ムル",
+ "54ba13831a": "最近の",
+ "750420dd9a": "コントロール",
+ "fe62b3f09f": "Ctrl",
+ "2a254b725e": "タブ",
+ "ca812803ea": "最近のタブオーダー",
+ "e53d585ed6": "最近のまたはタブ ストリップ。",
+ "256d92554d": "タブオーダー",
+ "22572e99c1": "注釈",
+ "1ff67ba40c": "メモ",
+ "4dd5684836": "レビュー",
+ "d05f629d2c": "値下げ",
+ "694613d47f": "リッチ エディター モードでローカル マークダウン レビュー ノート コントロールを表示します。",
+ "128bc09325": "マークダウンレビューノート",
+ "a0014961ae": "スクロール",
+ "3ca5ab78a5": "コード",
+ "e3919429c0": "概要",
+ "9c72990db8": "ミニマップ",
+ "716a4dfb1f": "ファイルの編集時にミニマップの概要を表示します。",
+ "6f584fcb48": "ミニマップ",
+ "19baae651b": "サイドバー",
+ "973ed6bfbf": "結合された差分",
+ "0a02059549": "ファイルツリー",
+ "2f42852568": "木",
+ "3b5733573e": "差分",
+ "dec71988f0": "結合された差分ビューを開くときにファイル ツリーを表示または非表示にします。",
+ "adec13f2ef": "デフォルトの差分ファイル ツリー",
+ "be24c7cd67": "分割",
+ "233f7e2f37": "並んで",
+ "0a5fa65926": "インライン",
+ "2b463f0bf9": "ビュー",
+ "ecb9415c80": "デフォルトで git diff を表示するための推奨表示形式。",
+ "2760c9933f": "デフォルトの差分ビュー",
+ "b2799ba622": "ミリ秒",
+ "146728ac2c": "遅れ",
+ "86f54575c7": "自動保存",
+ "8ea61ad55c": "最後の編集後、Orca が自動的に保存するまで待機する時間。",
+ "14e46c745b": "自動保存の遅延",
+ "4469b6fa4e": "保存",
+ "e9d948d3c3": "エディターと編集可能な差分を保存すると、少し停止した後、自動的に変更されます。",
+ "ae21e806ce": "ファイルの自動保存",
+ "c56cb6f1c2": "ネットワーク",
+ "3566fce83f": "ローカルホスト",
+ "91a46caafc": "no_proxy",
+ "3a73054565": "バイパス",
+ "20b711ac9e": "プロキシ",
+ "eb8946b2c9": "構成された HTTP プロキシをバイパスする必要があるホスト。",
+ "8436ff6f8e": "プロキシ バイパス ルール",
+ "e55d62dfa4": "発射台",
+ "9da6c875e5": "ドック",
+ "b9096a44cf": "https_プロキシ",
+ "8f03d44672": "http_プロキシ",
+ "e3b1d42f95": "Orca ネットワーク リクエストとローカルターミナルの子のプロキシ URL。",
+ "c29f23ab57": "HTTPプロキシ",
+ "6c2ce8457c": "ファイルエクスプローラー",
+ "c9d9636f24": "ファインダ",
+ "68d03d9980": "vscode",
+ "ebf8f056b5": "zed",
+ "0cb3d94f00": "cursor",
+ "8fb00fcd05": "ランチャー",
+ "e1ee631696": "エディタ",
+ "5a9df5566f": "メニューを開く",
+ "b8093e9a93": "開く",
+ "a916662068": "ワークスペースの「開く」メニューから利用可能なアプリを選択します。",
+ "451d4af994": "アプリで開く",
+ "7e9b556873": "スキップ",
+ "ca86dd6e27": "ダイアログ",
+ "9f8558233a": "確認",
+ "7edf4f69e2": "オートメーション",
+ "84c67d0108": "削除",
+ "a0c44061ee": "オートメーションとその実行履歴を削除する前に確認ダイアログを表示します。",
+ "d0a65b27fd": "オートメーションを削除する前に確認する",
+ "df10666259": "ワークツリー",
+ "ae98c9cf36": "ワークスペースを削除する前に確認ダイアログを表示します。",
+ "913242091d": "ワークスペースを削除する前に確認する",
+ "93f6ec5e70": "ディレクトリ",
+ "9bde064915": "サブフォルダー",
+ "ec5049e510": "入れ子になった",
+ "b9cffd374d": "リポジトリ名付きのサブフォルダー内にワークスペースを作成します。",
+ "141f71c69f": "ネストワークスペース",
+ "7887a2c262": "フォルダ",
+ "7baf524b04": "ワークスペース",
+ "d0bc793689": "ワークスペースフォルダーが作成されるルートディレクトリ。",
+ "4c95d08fa2": "ワークスペースディレクトリ"
+ }
+ },
+ "git": {
+ "search": {
+ "61eab13403": "orca",
+ "1b93c1143c": "帰属",
+ "8461c908ae": "共著",
+ "61f9f5d1fc": "共著者",
+ "af0a144bfb": "イシュー",
+ "6bdea421bb": "PR",
+ "16f53f7323": "gh",
+ "d088806071": "github",
+ "118c23484b": "Orca の帰属をコミット、PR、イシューに追加します。",
+ "bc7d9f69ce": "Orcaの帰属",
+ "40f9b815fd": "APIの予算",
+ "b7e52124c7": "レート制限",
+ "ead733645f": "glab",
+ "4808f065b3": "gitlab",
+ "2b4a72885d": "現在の GitLab CLI REST レート制限ヘッダー (利用可能な場合)。",
+ "83ecb3f470": "GitLab API の予算",
+ "65b69d9f80": "グラフキュール",
+ "1139f61512": "現在の GitHub CLI REST、Search、および GraphQL のレート制限。",
+ "ff86e354c4": "GitHub API の予算",
+ "035134fcd9": "ワークツリー",
+ "0c75583ca9": "安全に",
+ "bae91effdd": "フレッシュベース",
+ "de06e9d105": "基本参照",
+ "ab0e22c9f6": "ローカルメインをリフレッシュ",
+ "d9f70d51a0": "古いメイン",
+ "0849b571fe": "最新の",
+ "c41e345153": "メインの後ろ",
+ "6ee3cfff02": "git diff",
+ "564942ffc5": "原点/メイン",
+ "28192e3a63": "マスター",
+ "e3e9adde59": "主要",
+ "0e993bf00f": "ワークスペースを作成すると、Orca はリモート ベースを更新し、メインやマスターなどの一致するローカル ブランチを安全に早送りします。これにより、 git diff main...HEAD などのコマンドが古い履歴と比較されなくなります。ブランチにコミットされていない変更またはローカルのみのコミットがある場合、Orca は更新をスキップします。",
+ "f8bda25f29": "ローカルメインを最新の状態に保つ",
+ "769ddd7f81": "カスタム",
+ "1d2fae1fa2": "git ユーザー名",
+ "f83c8937c4": "ブランチの命名",
+ "5ecd91c5ef": "ワークツリーの作成時にブランチ名に追加されるプレフィックス。",
+ "68bd65fdb8": "ブランチプレフィックス"
+ }
+ },
+ "input": {
+ "search": {
+ "886597d6b3": "マコス",
+ "26c83b06c5": "リナックス",
+ "71905435dd": "×11",
+ "7059cfb00a": "クリップボード",
+ "c4440c3986": "ペースト",
+ "5fb84ba77f": "ミドルマウス",
+ "31ba58c8ae": "中クリック",
+ "de51e18ee9": "一次選抜",
+ "e5cd0e7a46": "選択",
+ "e25165320e": "編集",
+ "b51d47ceb7": "入力",
+ "874d88f4a6": "Linux および macOS ではデフォルトで有効になっています。 Linux はシステム選択クリップボードを使用します。他のプラットフォームはプライベート バッファを使用します。",
+ "d952ce9b46": "中クリックして「選択範囲から貼り付け」"
+ }
+ },
+ "integrations": {
+ "search": {
+ "a626990bd2": "切断する",
+ "3c3d3d8ffa": "接続",
+ "faa0b5a0d9": "APIキー",
+ "c450244ad7": "連携",
+ "7319e3015b": "Linear",
+ "16a486a49d": "Linear に接続してイシューを参照し、リンクします。",
+ "b027b4b318": "Linear 連携",
+ "20540996ef": "認証情報",
+ "2ec2bd328c": "APIトークン",
+ "7345b7c3e6": "アトラシアン",
+ "e1263dd748": "Jira",
+ "76f6af7c57": "Jira Cloud に接続するか、Jira API トークンの認証情報を更新します。",
+ "617603509b": "Jira 連携",
+ "8c568d761c": "PR",
+ "33180e8c10": "自己ホスト型",
+ "129fc59aa8": "Gitea",
+ "d0d019dc29": "API トークン環境変数を介した Gitea 認証。",
+ "aab86d64e5": "Gitea 連携",
+ "03a7b275be": "ADO",
+ "ed63380247": "Azureリポジトリ",
+ "b38b5d27f1": "Azure DevOps",
+ "7b1f3984bb": "トークン環境変数による Azure DevOps Repos 認証。",
+ "af6611fa6e": "Azure DevOps 連携",
+ "50d20817f7": "ビットバケット",
+ "c97d58a0f3": "API トークン環境変数を介した Bitbucket クラウド認証。",
+ "67a2a0e868": "Bitbucket 連携",
+ "371ee914d2": "MR",
+ "581844769a": "MR",
+ "b40cbe5de4": "glab",
+ "b939695c69": "gitlab",
+ "6e2ab619c6": "glab CLI を介した GitLab 認証。",
+ "b50b71ef9d": "GitLab 連携",
+ "41ccade05c": "gh",
+ "b79c21bd42": "GitHub",
+ "7166b9090c": "gh CLI を介した GitHub 認証。",
+ "f16e41cc72": "GitHub 連携"
+ }
+ },
+ "jira": {
+ "integration": {
+ "card": {
+ "8ff73fef62": "Jira トークンはアクティブなランタイムによって暗号化され、ローカルに保存されます。同じサイト URL と電子メールを再入力すると、そのサイトの API トークンが置き換えられます。",
+ "9046a20d4c": "{{value0}} を切断します",
+ "eaffa454e9": "アップデート",
+ "cec06a0f79": "テスト中…",
+ "ab350991b8": "確認済み",
+ "d914d7ab70": "確認中…",
+ "5936977fcd": "キャンセル",
+ "1666f8d562": "アトラシアン API トークンを作成する",
+ "1ab7f551f3": "アトラシアン API トークン",
+ "09d310e42d": "you@example.com",
+ "27dae4ab60": "https://example.atlassian.net",
+ "a28f417220": "Jira に接続する",
+ "9bb34706ca": "接続済み",
+ "efaab83c5d": "サイトを追加",
+ "09742875cd": "Jira",
+ "255bfe98ec": "テスト",
+ "5fb1562315": "エラー",
+ "3df81cb0ac": "わかりました",
+ "2e8bb790fd": "接続",
+ "33a8b261ee": "認証情報を更新する",
+ "d5c5b47bb9": "アップデート",
+ "fb854902d9": "接続する",
+ "9a9f8d4910": "Jira Cloud に接続して、イシューを参照、作成、リンクします。",
+ "74f3063026": "{{value0}} サイト{{value1}} が接続されました"
+ }
+ }
+ },
+ "mobile": {
+ "emulator": {
+ "search": {
+ "2348045036": "Orca がデフォルトで開くエミュレータ デバイスを選択します。",
+ "2bb2e09225": "モバイルスキル",
+ "bbe4267416": "エミュレータの種類",
+ "64494f03c3": "エミュレータを接続する",
+ "6f728f1456": "エミュレータタップ",
+ "f8b871d655": "エージェント CLI",
+ "2e0b45b2ba": "Orca CLI コマンドを使用して、モバイル エミュレータをリスト、アタッチ、タップ、入力します。",
+ "ea3eac39bb": "エージェント CLI 制御",
+ "8ef0f08d36": "ランタイム",
+ "27397fe8e9": "xcodeコマンドラインツール",
+ "7650063d17": "simctl",
+ "3211e7acf9": "エクスクルン",
+ "42bfab45d8": "可用性",
+ "ea1f51b980": "Xcode、simctl、serve-sim、およびエミュレータ デバイスの準備ができているかどうかを確認します。",
+ "0b95dfd5b3": "エミュレータの可用性",
+ "04c5f5d901": "デバイス",
+ "25d7bfbcd4": "ウディド",
+ "ec3c4043fd": "デフォルトのiPad",
+ "1dc8c52ffa": "デフォルトのiPhone",
+ "ab4814f3c5": "デフォルトのシミュレータ",
+ "54184cb9c5": "デフォルトのエミュレータデバイス",
+ "b8ddd13195": "エージェントエミュレータ",
+ "1ad6fb6230": "デフォルトのデバイス",
+ "ac0a985873": "エミュレータスキル",
+ "9353854ff3": "orca emulator",
+ "d4b7833894": "orca cli",
+ "84e5706975": "サーブシム",
+ "7c5a8a2bee": "xcode",
+ "bec7231663": "iPad",
+ "49727355a3": "iphone",
+ "6b6407dc1f": "エミュレータ",
+ "2d67f708ce": "シミュレータ",
+ "c5eca29310": "iOSシミュレータ",
+ "25159de808": "モバイルエミュレータ",
+ "9595354cff": "Orca およびコーディング エージェントのモバイル エミュレーターのサポートを構成します。",
+ "cdd3c31918": "モバイルエミュレータ"
+ }
+ },
+ "pane": {
+ "search": {
+ "dbccde3a60": "閉じる",
+ "9e16be01d6": "背景",
+ "3a5e31e84b": "離れる",
+ "8015fd9523": "所有",
+ "aa3f736042": "サイズ変更",
+ "356c31d6dc": "幅",
+ "fadcbfdd99": "フィット",
+ "ad08035c5f": "スマートフォン",
+ "6cd2bfdb0e": "復元",
+ "b34ad5b3a7": "ターミナル",
+ "6db86f445f": "モバイル",
+ "707fc78052": "アプリを閉じるか切り替えた後、モバイルで表示していたターミナルがどうなるかを選択します。",
+ "1e711aca11": "モバイルアプリを終了するとき",
+ "126afc5dbd": "リモート",
+ "70f505f3c3": "ラン",
+ "1802188b5d": "Wi-Fi",
+ "dd6e671aa9": "住所",
+ "1f70d63998": "ip",
+ "d0c89bc4a9": "かぶせる",
+ "87711f4b8f": "VPN",
+ "16bff559a0": "テールネット",
+ "c690e3ee38": "尾鱗",
+ "a023683767": "インターフェース",
+ "7b37c2e557": "ネットワーク",
+ "3190ef67a4": "モバイル ペアリングに使用するネットワーク アドレスを選択します。",
+ "d96c315227": "ネットワークインターフェース",
+ "7d01f93ec0": "接続されています",
+ "5e8fda4d7f": "ペアになった",
+ "905c65a308": "取り消す",
+ "82783d9b71": "デバイス",
+ "13419718b3": "ペアリングされたモバイルデバイスを管理します。",
+ "9d3a9397ba": "接続されたデバイス",
+ "2128a21096": "スキャン",
+ "e518cbd61c": "ペア",
+ "4a0c826f3d": "コード",
+ "3c1807a81a": "qr",
+ "7fb728fb2b": "QR コードをスキャンしてモバイル デバイスをペアリングします。",
+ "d49925710a": "モバイルペアリング"
+ }
+ },
+ "settings": {
+ "search": {
+ "b730ff7049": "実験的機能",
+ "8d4ba0ef09": "ベータ",
+ "6bfa001752": "apk",
+ "a7eececc1d": "android",
+ "7e801801ac": "リモート",
+ "0b7e585cb9": "スキャン",
+ "59b1d75fd1": "コード",
+ "87816d1c59": "qr",
+ "cf2c93b479": "ペア",
+ "f4ed142753": "スマートフォン",
+ "f213400800": "モバイル",
+ "671eb4173c": "スマートフォンからターミナルとエージェントを操作",
+ "ffd52a96e4": "モバイル"
+ }
+ }
+ },
+ "notifications": {
+ "search": {
+ "aa288005c3": "テスト",
+ "ca8faa40d7": "通知",
+ "4e30b1925e": "ネイティブ配信パスを使用してサンプル デスクトップ通知をトリガーします。",
+ "ef9b311346": "テスト通知を送信する",
+ "ecdeff4993": "ラウドネス",
+ "d58b64dddf": "音量",
+ "dc7d7c07cd": "音",
+ "eeb6f77322": "システム以外の通知音の再生音量。",
+ "aace1a62c6": "通知量",
+ "ef86a782cc": "ボン",
+ "3014ad1b8f": "ディン",
+ "079c29aeb5": "フラック",
+ "722face52f": "aac",
+ "6ecb8418cb": "m4a",
+ "d16ae23645": "ogg",
+ "57e34a31cd": "ウェーブ",
+ "5362074f19": "mp3",
+ "6e08f78315": "オーディオ",
+ "c718793e95": "Orca がデスクトップ通知用に再生する組み込み、システム、またはローカル オーディオ ファイルを選択します。",
+ "ea8cb8d9ce": "通知音",
+ "4ada6bfde9": "フィルタリング",
+ "fa60d8e4ab": "抑制する",
+ "a4c3b29a3c": "集中した",
+ "7247b97a31": "Orca がアクティブなワークツリーにフォーカスしているときは、通知を行わないようにしてください。",
+ "96562a72c6": "集中中は抑制",
+ "a2ab73b325": "注意",
+ "ae0487f8fd": "ベル",
+ "c638ae989d": "ターミナル",
+ "d3f1c48677": "バックグラウンドターミナルがベル文字を発したときに通知します。",
+ "a5edee1d99": "ターミナルベル",
+ "193e1f107c": "タスク",
+ "dd9d3e5f0f": "idle",
+ "5f7472d3fb": "完了",
+ "7fa07e9600": "エージェント",
+ "10d83ef8dc": "コーディング エージェントが動作状態からアイドル状態に移行したときに通知します。",
+ "bdc1edaeb4": "エージェントのタスクが完了しました",
+ "adbc3a0fcf": "ネイティブ",
+ "72539aede4": "システム",
+ "51ae2183e1": "デスクトップ",
+ "0534c76311": "Orca デスクトップ通知のマスター スイッチ。",
+ "4a210b2f72": "通知を有効にする"
+ }
+ },
+ "orchestration": {
+ "search": {
+ "f5d39af41e": "子エージェント",
+ "c766a01978": "渡す",
+ "08c65b12a2": "例",
+ "f278fd04db": "codex",
+ "32c5098e7b": "claude",
+ "21c28ccdf7": "コーディネーター",
+ "741dfc03fa": "ワーカー",
+ "ca54c69806": "DAG",
+ "7ad948b714": "タスク",
+ "eee028ae14": "急送",
+ "9a5ebdca31": "メッセージング",
+ "91fc8ab7e5": "調整",
+ "13ba5c6cbd": "エージェント",
+ "d86705ba77": "マルチエージェント",
+ "a7f76b4ca7": "オーケストレーション",
+ "e05ff36753": "メッセージング、タスク DAG、ディスパッチ、意思決定ゲートを介して複数のコーディング エージェントを調整します。",
+ "c34045764e": "エージェントオーケストレーション"
+ }
+ },
+ "privacy": {
+ "search": {
+ "3922051573": "データ",
+ "e8bc614a18": "無効化",
+ "d8191ae5ca": "環境変数",
+ "94e04427f6": "環境",
+ "664f1a8984": "継続的インテグレーション",
+ "5854a5c752": "シ",
+ "69637f4dc4": "orca_telemetry_disabled",
+ "058550f6bc": "追跡しない",
+ "83a6cd79b3": "追跡しない",
+ "f7a2d9f137": "テレメトリ送信を無効にする環境変数。",
+ "e058a3c98d": "テレメトリ環境変数",
+ "1686c07fee": "サポート",
+ "4a583f3a2f": "オープンテレメトリー",
+ "9ea93ce3d6": "オットルプ",
+ "685c68a81f": "ログ",
+ "40de3c2f19": "トレース",
+ "c0494ff48a": "診断",
+ "8b08f32366": "トレース ファイルと OTLP エクスポート コントロール。",
+ "6d258d2ed6": "診断",
+ "ead1deded2": "共有",
+ "27a27b2f63": "身を引く",
+ "4d4bb76bf4": "オプトインする",
+ "b021b9cb81": "匿名",
+ "79c319948b": "使用法",
+ "77d3180def": "テレメトリー",
+ "b707cc3981": "匿名の機能使用イベントを送信して、Orca の改善にご協力ください。",
+ "57b283461a": "匿名の使用状況データを共有する",
+ "2b5a5c312f": "posthog",
+ "4104f6f0f3": "分析",
+ "10124159f1": "プライバシー",
+ "aa3b794c17": "匿名の製品使用状況データ、診断、テレメトリ制御。",
+ "5c508bad41": "プライバシーとテレメトリ"
+ }
+ },
+ "quick": {
+ "commands": {
+ "search": {
+ "3c316e6ef8": "糸",
+ "b86c727100": "npm",
+ "b949a7c0a0": "pnpm",
+ "0b78c4a165": "起動",
+ "2d8aff42be": "走る",
+ "1c5bdcd0f2": "リポジトリ",
+ "89d2a9ad9f": "リポジトリ",
+ "f58b92a48f": "プロジェクト",
+ "8bf43c2dad": "グローバル",
+ "a26ecdb77b": "スニペット",
+ "d07d130849": "ショートカット",
+ "0073cf8ce9": "ターミナル",
+ "cfffa6cdb6": "コマンド",
+ "fecb031823": "コマンド",
+ "236d4cfac8": "素早い",
+ "d691c4e8d8": "保存されたターミナル コマンドは、グローバルまたは特定のプロジェクトにスコープ設定され、任意のターミナルから起動できます。",
+ "4c8945952b": "クイックコマンド"
+ }
+ }
+ },
+ "repository": {
+ "search": {
+ "bc7e504b8e": ".orca/イシューコマンド",
+ "603c68b68c": "orca.yaml",
+ "9dc60d7f6d": "github",
+ "ec70364df2": "ワークフロー",
+ "66b584bd6c": "コマンドを出す",
+ "2011a6a4f2": "github イシューコマンド",
+ "d42d1e49c0": "orca.yaml およびオプションのローカル オーバーライドを介して構成されたファイルベースのリンクされたイシューコマンド。",
+ "d86ea12d16": "カスタム GitHub イシューコマンド",
+ "c5e8bdbcbb": "デフォルトでスキップ",
+ "a69c5cbe90": "デフォルトで実行される",
+ "80c490b012": "聞く",
+ "f9d84b7971": "実行ポリシーのセットアップ",
+ "c00a549e03": "セットアップ スクリプトが使用可能な場合のデフォルトの動作を選択します。",
+ "cdfe398068": "セットアップをいつ実行するか",
+ "5e9445bbfd": "権威ある",
+ "f1e1bfa89f": "ソース",
+ "1d90a6cfbb": "両方",
+ "fcb8fa8144": "共有",
+ "0432d2fb7c": "地元",
+ "ed269fad69": "コマンドソース",
+ "19f58d6d89": "詳細設定",
+ "d141897c90": "コマンド ソースと orca.yaml の詳細。",
+ "cc11699c3d": "詳細設定",
+ "bf460fded8": "ヤムル",
+ "9cad92fe77": "orca.yaml フック",
+ "6b80f7d3c8": "ローカル設定スクリプト",
+ "a1a4c51d58": "アーカイブコマンド",
+ "fbfd2386e8": "アーカイブスクリプト",
+ "4c17787d7b": "アーカイブ",
+ "8655e3387b": "フック",
+ "acd1157f0c": "ワークツリーがアーカイブされる前に実行されるローカルおよび共有スクリプト。",
+ "bce0ca23c6": "アーカイブスクリプト",
+ "491b05d6e6": "セットアップコマンド",
+ "a31b43a7f8": "セットアップスクリプト",
+ "5590388dfa": "設定",
+ "baaf70bb37": "新規ワークツリーの作成後に実行されるローカルおよび共有スクリプト。",
+ "b79df26937": "セットアップスクリプト",
+ "d73fb47b45": ".claude/mcp.json",
+ "db11b337c4": ".claude.json",
+ "26f42fe773": ".cursor/mcp.json",
+ "e760e3fae7": ".mcp.json",
+ "16dc7a4637": "モデルコンテキストプロトコル",
+ "343f0a508c": "mcp",
+ "3c31801626": "プロジェクトレベルの MCP サーバー構成ファイルを検査します。",
+ "31bd0a2420": "MCP 構成",
+ "84da7fa2d7": "ノードモジュール",
+ "0a3a582794": "環境",
+ "3c180a251c": "リンク",
+ "f1c53f2820": "ワークツリー",
+ "7e228fc439": "シンボリックリンク",
+ "c06adcf136": "シンボリックリンク",
+ "ed885e589f": "プライマリ チェックアウトから新しく作成されたワークツリーへのシンボリックリンクへのパス。",
+ "01b3377ebc": "ワークツリーのシンボリックリンク",
+ "fff8834983": "プロンプト",
+ "fa3131f223": "モデル",
+ "130d76dc16": "名前変更",
+ "917dce844a": "ブランチ名",
+ "8068d8d0f1": "PR",
+ "5ff7fe1ade": "PR",
+ "eec39b3de6": "コミットメッセージ",
+ "cfad7ce5f3": "あい",
+ "a47f51127e": "ソース管理",
+ "6cc5c65e64": "プロジェクト固有の git 生成のオーバーライド。",
+ "eec3995dc6": "Git AI Author",
+ "cc876ca5f2": "リポジトリ",
+ "6469de5368": "プロジェクト",
+ "3067595d82": "削除",
+ "c86478c3d8": "このプロジェクトを Orca から削除します。",
+ "c5266c2c9d": "プロジェクトの削除",
+ "4b9a18a56d": "モノレポ",
+ "4e2529722c": "ディレクトリ",
+ "1ff4f12c0c": "ディレクトリ",
+ "9f5ae26ccd": "プリセット",
+ "095fca94fe": "プリセット",
+ "aa42616e3d": "チェックアウト",
+ "4f3c0230c2": "まばらな",
+ "90a331fd68": "スパースワークツリー作成用に保存されたディレクトリセット。",
+ "1f0f20bbb6": "スパースチェックアウトプリセット",
+ "4733ec2395": "../ワークツリー",
+ "58d8bca414": "相対的",
+ "a325a89dff": "ワークスペースパス",
+ "f3e6dee5fe": "ワークツリーパス",
+ "cd33a5525e": "新規ワークツリーのプロジェクト固有のディレクトリ。",
+ "443d127b5a": "ワークツリーの場所",
+ "9811f3d152": "ブランチ",
+ "f41cef5083": "基本参照",
+ "f571081ec4": "ワークツリー作成時のデフォルトのベースブランチまたは参照。",
+ "094adbe930": "デフォルトのワークツリーベース",
+ "27733eb6c1": "ファビコン",
+ "1e73e840ff": "絵文字",
+ "cb4b4de666": "アバター",
+ "c1075178cf": "バッジ",
+ "6d8de2f090": "16進数",
+ "8d045419b1": "色",
+ "b2546efab5": "リポジトリアイコン",
+ "6438a94c63": "プロジェクトアイコン",
+ "a1f3a2bd47": "サイドバーとタブで使用されるプロジェクトのアイコンと色。",
+ "b24f00294a": "プロジェクトアイコン",
+ "cd73b976d7": "リポジトリ名",
+ "92af66c7ce": "プロジェクト名",
+ "883aad2801": "サイドバーとタブのプロジェクト固有の表示詳細。",
+ "7e1e456a95": "表示名"
+ }
+ },
+ "runtime": {
+ "environments": {
+ "search": {
+ "772e3b4753": "vm",
+ "45501ff2c3": "雲",
+ "2bd988d041": "ペアリングコード",
+ "5cd7dca3b8": "リモート",
+ "d760866285": "クライアント",
+ "09568ccc65": "サーバ",
+ "ebd5369acf": "環境",
+ "d198440ce3": "ランタイム",
+ "baec27aa8f": "このブラウザを保存された Orca サーバーに接続します。",
+ "3517fb2ec0": "アクティブサーバー",
+ "c6e5a03aa0": "開発ボックス",
+ "f1575f1e09": "ウェブクライアント",
+ "81444c4102": "ペアリングURL",
+ "104f4d7dbd": "ペアリング",
+ "4575341c77": "ローカル デスクトップを選択するか、保存されたリモート Orca サーバーを追加するか、ペアリング URL を生成します。"
+ }
+ }
+ },
+ "shortcuts": {
+ "search": {
+ "ca6a0c2df7": "ショートカット",
+ "4811a8264a": "ターミナルファースト",
+ "afda131738": "orca first",
+ "0ecfc47434": "コンフリクト",
+ "0f8cb15582": "エージェント",
+ "f1adebbe8c": "シェル",
+ "7f1b38f59a": "トゥイ",
+ "7e3fc707aa": "ターミナル",
+ "0ecba9aa5f": "キーボード",
+ "ebd7d81e1d": "ショートカットが重なった場合に、Orca とフォーカスされたターミナルのどちらが優先されるかを選択します。",
+ "f052906167": "ターミナルのショートカット"
+ }
+ },
+ "ssh": {
+ "search": {
+ "d41f296f64": "ピング",
+ "237b391f7c": "繋がり",
+ "8cb870b109": "テスト",
+ "7efd17e816": "ssh",
+ "96ca5d9a0b": "SSH ターゲットへの接続をテストします。",
+ "a3058f3605": "テスト接続",
+ "2cd40ba0d0": "ホスト",
+ "5220501141": "構成",
+ "3b12e064a4": "輸入",
+ "7f251a45a8": "~/.ssh/config からホストをインポートします。",
+ "41a3127094": "SSH 構成からインポート",
+ "f9493b80c0": "サーバ",
+ "8fb1cc87cc": "ホスト",
+ "09395490af": "ターゲット",
+ "00d1fda01a": "新規",
+ "f7b6383aec": "追加",
+ "62826efbe9": "新規リモート SSH ターゲットを追加します。",
+ "f5a691bb6c": "SSHターゲットの追加",
+ "d4bcd497c7": "リモート",
+ "74c6d90d78": "リモート SSH ターゲットを管理します。",
+ "380a788da7": "SSH接続"
+ }
+ },
+ "tasks": {
+ "search": {
+ "58cda6f9c0": "非表示",
+ "44083ae418": "画面",
+ "604d8e4089": "アトラシアン",
+ "5430396e11": "Jira",
+ "412ec3c702": "Linear",
+ "11f001cdd4": "gitlab",
+ "c10ac2125e": "github",
+ "3d81c26d78": "ソース",
+ "cf0e3e0c2f": "プロバイダー",
+ "2ec54bee51": "タスク",
+ "765f0c544d": "[タスク] ページとサイドバーのショートカットに表示するタスク プロバイダーを選択します。",
+ "5b8e4aace5": "タスクプロバイダー"
+ }
+ },
+ "terminal": {
+ "clipboard": {
+ "search": {
+ "5fb3512e8c": "ペースト",
+ "a38508c419": "コピー",
+ "d106f44fb4": "リモート",
+ "043b32faa1": "ssh",
+ "9fda309db9": "fzf",
+ "64533e30cc": "NVIM",
+ "2061d8db1a": "ネオビム",
+ "5ffcd13c90": "tmux",
+ "10d73e22d3": "クリップボード",
+ "9dfc125cd3": "osc52",
+ "62d1208b90": "オシレーター52",
+ "459fea094a": "ターミナル内のプログラムを OSC 52 (SSH 経由を含む) 経由でシステム クリップボードにコピーします。",
+ "74db8721e4": "TUI クリップボードへの書き込みを許可する (OSC 52)",
+ "4043e294d2": "ノーム",
+ "cf83ac3dbd": "リナックス",
+ "737cef6de1": "×11",
+ "e87c6d776d": "自動",
+ "664789b73a": "自動",
+ "c38c18be15": "選択",
+ "797fdfe4ca": "選択する",
+ "603818e8d8": "端子の選択が行われるとすぐに、その選択内容をクリップボードに自動的にコピーします。",
+ "3bdc84f059": "選択時にコピー"
+ }
+ },
+ "search": {
+ "c047f398cc": "起動",
+ "b872de3926": "場所",
+ "fd6c24313d": "新規",
+ "f44643328e": "タブ",
+ "18ce996647": "垂直",
+ "54a9b3725b": "水平",
+ "de7bc1d5f5": "分割",
+ "7a48c7715b": "ワークスペース",
+ "6b659fff2a": "スクリプト",
+ "4529806908": "設定",
+ "2610ee3b56": "新規ワークスペースの作成時にリポジトリ セットアップ スクリプトが実行される場所: 垂直分割 (デフォルト)、水平分割、または「セットアップ」というタイトルの背景タブ。",
+ "5be2d67678": "セットアップスクリプトの場所",
+ "0ce176909a": "テーマ",
+ "4ba8623632": "パレット",
+ "11fd3fbcf2": "アンシ",
+ "d8bd6182b8": "上書き",
+ "674b7c8436": "色",
+ "3023e01415": "個々の端子の色をオーバーライドします。",
+ "aed2a4b4eb": "色のオーバーライド",
+ "6eaf7ee0e4": "cursor",
+ "34fe1af39d": "タイピング",
+ "ee611ae238": "非表示",
+ "ea364ce6e4": "ねずみ",
+ "77201c0bb2": "ターミナルに入力するときにマウス カーソルを非表示にします。",
+ "d1fe5f99ff": "入力中にマウスを非表示にする",
+ "f25d948664": "マージン",
+ "b2f52cb96c": "間隔",
+ "e8baf0d12c": "パディング",
+ "4655567c37": "ターミナルグリッドの周りの垂直方向のパディング (ピクセル単位)。",
+ "692c4ad032": "垂直パディング",
+ "75691e4911": "ターミナルグリッドの周囲の水平方向のパディング (ピクセル単位)。",
+ "b4f182f24d": "水平方向のパディング",
+ "6c2f9f05c8": "活気",
+ "4f7f8f28ca": "透明性",
+ "f6dd9ff606": "背景",
+ "71eb45e293": "ぼかし",
+ "0838b3717b": "ウィンドウ",
+ "bc2054657a": "ターミナルウィンドウに背景のぼかしを適用します。再起動が必要です。",
+ "72d0482137": "窓のぼかし",
+ "7db59c4738": "アルファ",
+ "46d99ef4bb": "不透明度",
+ "4c643695aa": "ターミナルの背景の透明度を制御します。",
+ "b36fd2416d": "背景の不透明度",
+ "d4daf4f612": "解凍する",
+ "88561b3499": "凍った",
+ "0a05629060": "回復する",
+ "f66a7cf715": "ターミナル",
+ "6892fb1019": "再起動",
+ "cde233f5da": "スクロールバック",
+ "3982d88725": "歴史",
+ "456da64d4d": "クリア",
+ "920573d65b": "すべて終了",
+ "a3e5297c10": "強制終了",
+ "a8d2784214": "管理",
+ "d802a578bf": "セッション",
+ "9f2dda133c": "pt",
+ "f35400f7e8": "デーモン",
+ "f72abc493c": "セッションを強制終了するか、保存されたスクロールバックをクリアするか、デーモンを再起動することで、フリーズしたターミナルを回復します。",
+ "6f5d486a68": "セッションの管理",
+ "10f9fb6fea": "設定",
+ "2ade3ea490": "構成",
+ "fd752b3cac": "輸入",
+ "82b63d07fe": "幽霊っぽい",
+ "73e9422f19": "サポートされている Ghostty ターミナル設定の 1 回限りのインポート。",
+ "a979df0083": "Ghostty からインポート",
+ "4cec42dbf7": "国際",
+ "b495dc6a9f": "JIS",
+ "d8d6f7a3c5": "マコス",
+ "1ab57a0fbd": "マック",
+ "abaa24752d": "キーボード",
+ "24f7977756": "日本語",
+ "98059d0944": "バックスラッシュ",
+ "9c35f56625": "円",
+ "063914c486": "JIS 円 (¥) キーを押したときに、代わりにバックスラッシュ (\\) を送信するかどうかを制御します。",
+ "694b8764ac": "JIS 円 (¥) からバックスラッシュ (\\)",
+ "fae142a354": "リードライン",
+ "b3b94cfcb5": "国際的",
+ "dd4f6cb541": "ドイツ人",
+ "983d45cf4c": "作曲する",
+ "7ace5beec9": "メタ",
+ "38f1b4f4cb": "鍵",
+ "c4427dc5ff": "代替",
+ "b37edfc65a": "オプション",
+ "1f8b00f5ce": "macOS の Option キーが Alt/Esc シーケンスを送信するか文字を合成するかを制御します。 Ghostty の macos-option-as-alt をミラーリングします。",
+ "9bd7229927": "Alt としてのオプション",
+ "affb14efd4": "選択",
+ "d2a366c7f9": "ダブルクリック",
+ "4ed3e239a8": "境界",
+ "d4aeafac10": "セパレーター",
+ "7286cd2566": "言葉",
+ "3ab64c47d8": "文字はダブルクリック選択の単語境界として扱われます。",
+ "957a0203fc": "単語の区切り文字",
+ "56fff3d113": "メモリ",
+ "fffdff40a7": "バッファ",
+ "f7d56b6281": "ターミナルスクロールバック バッファの最大サイズ。",
+ "7674e758e1": "スクロールバックのサイズ",
+ "411229c636": "ライト",
+ "781f49d942": "ディバイダー",
+ "77d9f9cd55": "ライト モードでペイン間の分割分割線を制御します。",
+ "595b97b446": "ライトディバイダーの色",
+ "7718d70356": "プレビュー",
+ "1dee533bd9": "Orca がライト モードのときに使用されるテーマを選択します。",
+ "1d89457764": "ライトテーマ",
+ "da864e6cec": "ライトモード",
+ "f268092ee3": "無効にすると、ライト モードはダーク ターミナル テーマを再利用します。",
+ "232e532169": "ライトモードで別のテーマを使用する",
+ "f785374072": "ダーク",
+ "9c32726f47": "ダーク モードでのペイン間の分割分割線を制御します。",
+ "8987db7ff2": "ダークディバイダーカラー",
+ "13f6310dd3": "ダークモードで使用するターミナルテーマを選択します。",
+ "ec07ce9b02": "ダークテーマ",
+ "f036794286": "アクティブ",
+ "846a7a1204": "ペイン",
+ "d1fa00a9cb": "ホバリング",
+ "b5116e7b12": "続く",
+ "f5d1e3d472": "集中",
+ "17cc3ea102": "ターミナル ペインにマウスを移動すると、クリックしなくてもターミナル ペインがアクティブになります。 Ghostty のフォーカス追従マウス設定を反映します。選択とウィンドウの切り替えは安全に行われます。",
+ "c6178a2b4d": "フォーカスはマウスに追従します",
+ "f637a7dee9": "厚さ",
+ "e58d4040d0": "ペイン分割線の太さ。",
+ "2d5ab88b7c": "ディバイダーの厚さ",
+ "6c4c85ba43": "調光",
+ "18dd5026c6": "現在アクティブではないペインに不透明度が適用されます。",
+ "72bbcbd1dd": "非アクティブなペインの不透明度",
+ "d4f7d1ce5c": "ターミナルカーソルの不透明度。",
+ "7f1e356a54": "Cursorの不透明度",
+ "25f606d9e5": "まばたきする",
+ "a27f6edf52": "選択したカーソル形状の点滅バリアントを使用します。",
+ "b03d01fd49": "点滅Cursor",
+ "eefd1d8332": "下線",
+ "015c82349f": "ブロック",
+ "a6e9dcc829": "バー",
+ "275a9d6395": "Orca ターミナル ペインのデフォルトのカーソルの外観。",
+ "97bcfff662": "Cursor形状",
+ "1abcf4d7de": "リナックス",
+ "7d924d870d": "グラフィックス",
+ "bc7ae1f7c0": "レンダリング",
+ "fffa9ab980": "レンダラー",
+ "6cddc858ba": "ウェブグル",
+ "4b4e80d850": "加速度",
+ "db82cb13b0": "GPU",
+ "8f9f953de7": "ターミナルが xterm.js WebGL レンダリングを使用するかどうかを制御します。レンダラーがサポートされている場合、自動は WebGL を試行します。ソフトウェアまたは不明な GPU レンダラーには保守的なフォールバックが使用されます。",
+ "13a2502dfc": "GPU アクセラレーション",
+ "d5e6c7fab1": "フォント特性",
+ "a16224d16a": "カルト",
+ "6ded6297fe": "ヨセフカ",
+ "e3aeea308e": "カスカディアコード",
+ "35c2311a33": "ジェットブレインモノ",
+ "7f7640c29e": "フィラコード",
+ "7ab424c4d3": "結紮",
+ "afc8d5f790": "合字",
+ "103cdb862f": "タイポグラフィ",
+ "893aa92997": "同梱されているフォントのプログラミング合字 (例: => → ≠ ≥) をレンダリングします。 「自動」では、既知の合字フォント (Fira Code、JetBrains Mono、Cascadia Code、Iosevka など) に対してのみ合字が有効になります。",
+ "58da1ae45d": "フォントの合字",
+ "7341e3d00e": "行の高さ",
+ "36a1b38bc8": "端子の線の高さの乗数を制御します。",
+ "0f2fb0cb74": "線の高さ",
+ "20ce287cc6": "重さ",
+ "98c18f2c77": "ターミナルテキストのフォントの太さを制御します。",
+ "28ea41bd2d": "フォントの太さ",
+ "b0bb76ae6b": "フォント",
+ "0acdc17891": "新規ペインとライブアップデート用のデフォルトのターミナルフォントファミリー。",
+ "e989914ad6": "フォントファミリー",
+ "33031c1465": "文字サイズ",
+ "0fe0073f0c": "新規ペインとライブ アップデートのデフォルトのターミナル フォント サイズ。",
+ "5930244899": "フォントサイズ"
+ },
+ "windows": {
+ "search": {
+ "4d09141a42": "コンテキストメニュー",
+ "fcfa53920b": "ペースト",
+ "e55186fe2b": "右クリック",
+ "28ff08ed35": "窓",
+ "e7d2793b03": "ターミナル",
+ "8ba875c132": "Windows では、右クリックしてクリップボードをターミナルに貼り付けます。 Ctrl キーを押しながら右クリックしてコンテキスト メニューを開きます。",
+ "f0b8448570": "右クリックして貼り付けます",
+ "04994f6929": "デフォルト",
+ "fc564eadaf": "デビアン",
+ "4ee2579c32": "ubuntu",
+ "5074ad8b5f": "ディストリビューション",
+ "2b4a340ce0": "分布",
+ "02c772582a": "リナックス",
+ "6e3adf4cba": "wsl",
+ "978457945b": "新規 WSL ターミナルとローカル エージェント スキャンが使用する WSL ディストリビューションを選択します。",
+ "1f402b3651": "WSLの配布",
+ "d57f870938": "詳細設定",
+ "4af2f7526e": "バージョン",
+ "d414022016": "うわー",
+ "768613e483": "パワーシェル7",
+ "f9162f0b8e": "ウィンドウズパワーシェル",
+ "2d99cd91be": "パワーシェル",
+ "41a69bc24d": "PowerShell シェル オプションで、新規ターミナル ペインに対して Windows PowerShell を起動するか PowerShell 7+ を起動するかを選択します。",
+ "860e0e6402": "PowerShellのバージョン",
+ "07ec155fb6": "bash.exe",
+ "5a2db98d23": "バッシュ",
+ "591912177b": "git bash",
+ "12519edb5d": "コマンドプロンプト",
+ "6cd20b9e64": "cmd",
+ "7c7056940a": "シェル",
+ "713c4a2f92": "Windows 上の新規ターミナル ペインのデフォルト シェルを選択します。",
+ "13715f9d23": "デフォルトのシェル"
+ }
+ }
+ },
+ "voice": {
+ "pane": {
+ "search": {
+ "f6e0dfa61c": "雲",
+ "2d206de105": "APIキー",
+ "04c25a6fb0": "openai",
+ "b9dee49cd7": "ダウンロード",
+ "10d45a9fce": "stt",
+ "3d8b853963": "スピーチ",
+ "080202facb": "モデル",
+ "7640ed9848": "声",
+ "56defcd6c3": "ディクテーションに使用するローカルまたはクラウドの音声テキスト変換モデルを選択します。",
+ "7e62cd7c41": "音声モデル",
+ "931b1a9e53": "押して話をする",
+ "064a9bd94a": "所有",
+ "6fa48bcd41": "トグル",
+ "d86f5600da": "モード",
+ "089d31a45b": "口述筆記",
+ "748b33e531": "ディクテーション動作を切り替えたり、押し続けたりします。",
+ "6a3abb4338": "ディクテーションモード",
+ "e360027a65": "マイクロフォン",
+ "698376a38d": "音声ディクテーション機能のマスター切り替え。",
+ "20574cbc72": "音声ディクテーションを有効にする",
+ "322d457a0d": "転写",
+ "dcc7846641": "クラウド音声テキスト変換モデルに使用される OpenAI API キーを構成します。",
+ "ebfd0b32e5": "OpenAI 文字起こし"
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "action": {
+ "recipe": {
+ "options": {
+ "commitMessage": "段階的な変更からコミット メッセージを生成します。",
+ "pullRequest": "ホストされたレビューのタイトルと説明を生成します。",
+ "branchName": "Orca が最初のエージェント タスクから作成したブランチの名前を変更します。",
+ "fixCommitFailure": "コミットフックまたは git コミットが失敗したときにエージェントを開始します。",
+ "fixChecks": "失敗したホスト型レビュー チェックからエージェントを開始します。",
+ "resolveConflicts": "ローカルまたはホストされたレビューのマージ競合に対してエージェントを開始します。"
+ }
+ }
+ }
+ }
+ },
+ "agent-awake-copy": {
+ "e5995ce268": "エージェント作業中はコンピューターを起きたままにする",
+ "95d3031db2": "エージェントが作業している間、このコンピューターとディスプレイを起きたままにします。蓋を閉じたときの動作は、このデバイスの電源設定に従います。",
+ "a42f6fbdd8": "エージェントが作業している間、このコンピューターとディスプレイを起きたままにします。Orca は電源ポリシーに従い、蓋が閉じているときもこのデバイスを起きたままにするよう要求します。"
+ },
+ "agent-status-hooks-copy": {
+ "7707c15abb": "エージェント状態フック",
+ "a68a642835": "Orca で作業中、待機中、完了の状態を表示します。オフにすると Orca 管理のフックを削除し、再インストールを停止します。"
+ },
+ "agent-generated-tab-title-copy": {
+ "19ad21615a": "タブタイトルを自動生成",
+ "b036c7a409": "最初に判明したエージェントのプロンプトから、短く安定したタブ名を生成します。手動での名前変更が常に優先されます。"
+ }
+ },
+ "right": {
+ "sidebar": {
+ "BulkActionBar": {
+ "79a9f5f712": "アンステージ (",
+ "ef5f5bd06e": "ステージ(",
+ "60ed678138": "選択された"
+ },
+ "ChecksPanel": {
+ "2ef90c9819": "失敗したチェックに対して AI エージェントを開始しました。",
+ "a0181a8d76": "紛争のためにAIエージェントを開始しました。",
+ "34464d00b9": "更新されました",
+ "058039787c": "キャンセル",
+ "2ab7fd4b6d": "保存",
+ "dda5924a40": "チェックには Git ブランチとホストされたレビュー コンテキストが必要です",
+ "976cefd02f": "チェックは利用できません",
+ "b5dd73a105": "チェックを表示するワークスペースを選択",
+ "a4ef4e0832": "ワークスペースが選択されていません",
+ "5594400d73": "修正が必要な失敗したチェックはありません",
+ "abf59262fb": "エージェントを開始する前に、コマンド入力全体を確認して編集します。",
+ "4ede779461": "AI を使用してレビューの競合を解決する",
+ "3b203c62f8": "これにより、PR からコメントが完全に削除されます。",
+ "ea9b649ce3": "コメントを削除しますか?",
+ "5788d1059d": "レビュー スレッドを更新できませんでした。 GitHub API の予算を確認してください。",
+ "07871c0589": "別の PR をリンクする",
+ "7202f4a40a": "PR のリンクを解除する",
+ "7f4489f370": "更新",
+ "5c88c6db07": "{{value0}}にオープン",
+ "7fad8509fe": "AI で修正する",
+ "71026ca2cb": "更新中…",
+ "889cdfba04": "{{value0}} を作成する",
+ "98f4c37b33": "プッシュして{{value0}}を作成",
+ "6633c7a1fb": "ブランチを公開",
+ "fdb27637f2": "公開中…",
+ "e56c42122e": "破壊的な",
+ "786e3c143f": "削除",
+ "653c105ecc": "その他の PR 操作"
+ },
+ "CreatePullRequestDialog": {
+ "2bc1b4345e": "キャンセル",
+ "27ef4b195c": "を作成する前に、別のベース ブランチを選択。",
+ "7ef56f3efe": "下書きとして作成",
+ "0c9f9a568c": "マークダウン形式をサポートします。 AI を使用して生成を使用して、変更内容を自動入力します。",
+ "02b2ce911f": "説明 (オプション)",
+ "1cd53359db": "説明",
+ "68314b4369": "タイトル",
+ "694550a610": "主要",
+ "0fad57a14c": "リモート ブランチを検索するか、ブランチ名を入力します。",
+ "8584ccb43c": "ベースブランチ",
+ "6f5f1962b6": "本ブランチ",
+ "b504b3ceb1": "ホストされたレビューを作成する前に詳細を確認してください。",
+ "f658ff2455": "対象のブランチを確認し、",
+ "b7f43474d7": "{{value0}} を作成する",
+ "7a21f0dae8": "{{value0}}にオープン",
+ "edc35a7027": "{{value0}} #{{value1}} はすでにオープンしています",
+ "a154fe55e6": "プッシュして{{value0}}を作成"
+ },
+ "CreatePullRequestGenerateButton": {
+ "4012459f8a": "AIで生成",
+ "a0501572c1": "AI を使用して {{value0}} の詳細を生成する",
+ "d47fd63012": "詳細。クリックして停止します。",
+ "f5513bdeb1": "生成中",
+ "a6ea6dc3aa": "生成中…",
+ "e041998cad": "生成を停止する"
+ },
+ "FileExplorer": {
+ "79b1537dd3": "ファイルを参照するワークスペースを選択"
+ },
+ "FileExplorerBackgroundMenu": {
+ "3b5e2dcb8d": "新規フォルダー",
+ "21fe46ed36": "新規ファイル"
+ },
+ "FileExplorerRow": {
+ "addc01145f": "削除",
+ "fc747429bf": "名前を変更する",
+ "0df0e5abac": "フォルダー内で検索",
+ "d6a25618aa": "フォルダを折りたたむ",
+ "d87a4c42e1": "マークダウンプレビューを開く",
+ "c2112579f6": "ダウンロード",
+ "dd112c81d2": "Orca ブラウザで開く",
+ "1bb9be455c": "プロジェクトとして追加...",
+ "0fec99bfd7": "重複",
+ "f61af83316": "新規フォルダー",
+ "37c875d827": "新規ファイル",
+ "b3e288bf41": "「{{value0}}」のダウンロードに失敗しました。",
+ "1a3df04ae1": "オープン",
+ "bce4d4e44f": "「{{value0}}」をダウンロードしました",
+ "e26010014a": ".gitignore によって無視される",
+ "a06551beee": "入力",
+ "128a99ed5e": "未割り当て",
+ "2de3b21934": "値下げ",
+ "66a29dde82": "相対パスをコピー",
+ "42e10cbf57": "相対パスのコピー",
+ "b5d436aa30": "パスのコピー",
+ "f9d7ca753d": "パスのコピー",
+ "3161c4e425": "フォルダ"
+ },
+ "FileExplorerToolbar": {
+ "d238264654": "Git で無視されたファイルを表示",
+ "78f133232c": "ドットファイルを表示",
+ "31b4c3195d": "エクスプローラーのその他の操作",
+ "d95e30fe28": "エクスプローラーを更新する",
+ "6026b16950": "すべて折りたたむ"
+ },
+ "FileExplorerTreeStatus": {
+ "ce03835e1f": "このワークスペースにはファイルがありません",
+ "c76693e456": "このワークスペースのファイルをロードできませんでした:"
+ },
+ "GitHistoryPanel": {
+ "cf7cad58d2": "まだコミットはありません",
+ "781a8bcf7b": "グラフを読み込んでいます...",
+ "d0fb0f4bf2": "コミットを更新する",
+ "9f7535d22b": "Ref は、そのコミットそのものを指すブランチ名またはタグ名です。これらは、Git にコミットの名前付き参照がある場合にのみ表示されます。",
+ "9289ba0cb9": "リファレンスとは何ですか?",
+ "d836037d02": "コミット",
+ "8232c8b2f2": "コミット {{value0}}: {{value1}} を開く",
+ "9a8b85882d": "読み込み中",
+ "62e685d5ec": "idle",
+ "111e1d0db4": "エラー",
+ "e5e81e59a6": "コミットのサイズ変更"
+ },
+ "HostedReviewActions": {
+ "4d5fb5a284": "閉じる",
+ "9845a71e17": "その他の操作",
+ "2bfaf4379c": "その他の {{value0}} 操作",
+ "377269db6f": "{{value0}} が再開されました",
+ "fa3ee9a515": "閉まっている",
+ "78f5ff294c": "これにより、{{value0}} が再度開きます。",
+ "a3d572a4de": "これにより、{{value0}} が閉じられます。",
+ "e4aca40024": "ワークスペースの削除",
+ "eefd50457e": "削除中...",
+ "3ce211ece6": "{{value0}}を再開します",
+ "6645ac7dd1": "再開...",
+ "b25f63edd7": "開く",
+ "d2ca293f3d": "処理中...",
+ "ef064cb7c3": "デフォルト",
+ "59b4dccf70": "破壊的な"
+ },
+ "PortsPanel": {
+ "3ea4a02a8f": "キャンセル",
+ "4eb801ce93": "開発サーバー",
+ "8dfed0a15c": "ラベル (オプション)",
+ "17bea6e391": "ローカルホスト",
+ "a3721a50b0": "リモートホスト",
+ "d57545ff92": "リモートと同じ",
+ "b950b1948b": "ローカルポート",
+ "9e5a4118b0": "リモートポート",
+ "c9d106547a": "フォワード",
+ "c7e920aa7c": "として宣伝される",
+ "e740075063": "削除",
+ "b3548e59f4": "編集",
+ "fe2730d050": "{{value0}}をコピー",
+ "b22b128b2a": "ブラウザで開く",
+ "75aeea592f": "ブラウザで{{value0}}を開く",
+ "de349d4560": "開く",
+ "907eb53ed2": "ポートを転送する",
+ "04efd3dad4": "ローカル マシン上のリモート サービスにアクセスするためにポートを転送します。",
+ "1f0d2a24f9": "転送ポートなし",
+ "36b1b2984a": "検出されました",
+ "ddbe58d74e": "転送されました",
+ "a103dae837": "追加",
+ "6bc058dbe1": "ポート",
+ "d4c3cd679c": "再接続中...",
+ "a2f1a47f42": "SSH接続が失われました",
+ "409afcc145": "ブラウザ用のワークスペースが選択されていません。",
+ "153145e675": "証拠",
+ "c7b4702b7b": "ワークスペース",
+ "57d930fa45": "PID",
+ "5dd86dcf2f": "プロセス",
+ "b1ff94fa27": "プロトコル",
+ "729be0b4e5": "親切",
+ "0f1d8cd324": "バインド",
+ "1c1c18cefc": "住所",
+ "f9528da632": "プロセスの停止",
+ "a223459512": "詳細を表示",
+ "bdac206faf": "詳細をコピーする",
+ "792baeb7ed": "アドレスをコピーする",
+ "d41a8241ec": "ポート",
+ "a2a9fc6899": "ローカルポートが検出されませんでした",
+ "f59c783b7a": "ポートスキャンは使用できません",
+ "7822e3edc6": "ポートのリフレッシュ",
+ "c1b115c375": "ワークスペースが選択されていません",
+ "98e9a414f8": "ブラウザを開けませんでした",
+ "a00f3a2840": "ポートの更新に失敗しました",
+ "97b562d21d": ":{{value0}} でプロセスを停止しました",
+ "9079776663": "保存",
+ "c57eda6822": "編集",
+ "9f475dc994": "転送中...",
+ "d7c83cfd24": "保存中...",
+ "31e80cff2d": "リモート ポートをローカル マシンに転送します。",
+ "10360598a4": "ポート転送構成を更新します。",
+ "80206251c8": "ポートフォワードの編集",
+ "4bc9b00912": "ワークスペース",
+ "3e13cb63ee": "未知",
+ "472054d94c": "ポート:{{value0}}",
+ "1119f90ad7": "容器",
+ "d32820d3e2": "外部の",
+ "4db4b5e435": "その他のワークスペース",
+ "38b16cfbef": "ポートが検出されませんでした",
+ "0d63d94db3": "走査...",
+ "935dda7718": "アクティブなワークスペース",
+ "740aca88ab": "ワークスペースのポートスキャンに失敗しました。"
+ },
+ "Search": {
+ "1abfb25a66": "ファイル内を検索するために入力します",
+ "d56d140747": "Enterを押して検索します",
+ "0b8104eaf2": "ファイル",
+ "4107975b3a": "で",
+ "6aeda362ed": "結果",
+ "98c8435e36": "検索するワークスペースを選択",
+ "1ec640c9c7": "マッチ",
+ "dcc294f28d": "(結果は切り捨てられています)"
+ },
+ "SearchFilters": {
+ "01e4671ccf": "除外するファイル (例: *.min.js、dist/**)",
+ "0a6412a895": "除外するファイル",
+ "8a77efcbd1": "インクルードするファイル (例: *.ts、src/**)",
+ "a69ee1bd0e": "含めるファイル"
+ },
+ "SearchHeader": {
+ "6234a5ef85": "正規表現を使用する",
+ "4567e6e0b6": "単語全体に一致",
+ "464ae3974f": "大文字と小文字を区別する",
+ "693cbeadd0": "検索"
+ },
+ "SearchResultItems": {
+ "cc06595a3b": "ラインパスのコピー",
+ "3596b9668d": "パスのコピー"
+ },
+ "SourceControl": {
+ "1406954883": "すべてのメモをクリアします...",
+ "cc05b2d088": "ファイルエクスプローラーで開く",
+ "03194cfff4": "ここで開いた競合から派生したローカル セッション状態。",
+ "413a3ba113": "コンフリクト",
+ "27a50fe970": "競合をレビューする",
+ "f6cb48b6fe": "AIで解決する",
+ "3eeccbb221": "解決されたファイルは、ライブ競合状態を抜けた後、通常の変更に戻ります。",
+ "c321542ee2": "{{value0}} 行目のメモを削除",
+ "b656381c18": "メモの削除",
+ "c085946bda": "{{value0}} 行目のメモをコピーします",
+ "1623bf4e19": "メモをコピーする",
+ "655633c08a": "送信済み",
+ "3eb9b2805e": "{{value0}} のメモを開く",
+ "0d963bf982": "{{value0}} を開く",
+ "59654650d3": "{{value0}} のメモをクリアする",
+ "ac8cbe3bf5": "差分ビューの線の上にマウスを置き、+ をクリックしてメモを追加します。",
+ "286dbda4d6": "再試行",
+ "476b77745b": "ベース参照の変更",
+ "ed34038d0d": "ブランチ比較をリフレッシュ",
+ "493f963029": "ベース参照を変更する",
+ "3278b2767b": "先に",
+ "11b5dd8e41": "と比較する",
+ "783a808870": "閉じる",
+ "a9bf7c171a": "コミット失敗",
+ "03d238218c": "詳細",
+ "011f9713fc": "コミットがブロックされました",
+ "cc199ccc5f": "コミットおよびリモート操作",
+ "4d6e1fd7f3": "その他の操作",
+ "37a81f29ad": "コミットメッセージを生成しています。クリックして停止します。",
+ "b94112eb9e": "コミットメッセージ",
+ "0d0a8359d3": "メッセージ",
+ "15b7f210d7": "エージェントを選択し、起動前に完全なコマンド入力を編集します。",
+ "054ead86b1": "AI によるコミット失敗の修正",
+ "9e5ccd00aa": "コミット失敗コンテキストが使用不可",
+ "f0a2dc9e46": "起動をカスタマイズ...",
+ "ec7bfced55": "コミット失敗を修正するエージェントを選択",
+ "dd43c47089": "このコミット失敗に対するエージェントを選択",
+ "30b8d4f181": "AI によるコミット失敗の修正",
+ "4b37ae99b0": "デフォルトの AI エージェントを開始して、このコミットの失敗を修正します",
+ "ae743199cd": "を作成する前に、別のベース ブランチを選択。",
+ "c5e4175139": "その他の {{value0}} とリモート操作",
+ "78ddfd0bb4": "下書きとして作成",
+ "e64a632456": "主要",
+ "6055949c50": "{{value0}} ベース ブランチ",
+ "1f7119f604": "ベース",
+ "9484270f45": "タイトルと説明を生成中…",
+ "a0dc20fc93": "説明 (オプション)",
+ "a8873e1d62": "{{value0}} の説明",
+ "7d6a8f0082": "タイトル",
+ "a6eda33521": "{{value0}} タイトル",
+ "02d8c04339": "AI を使用して {{value0}} の詳細を生成する",
+ "e868cec4e1": "生成中…",
+ "527e130b6f": "生成を停止する",
+ "e1970d327d": "新規",
+ "f4c766f1ca": "この実行用のエージェントとコマンド テンプレートを選択します。",
+ "1a6a6e0bc5": "ホストされたレビューの詳細を生成する",
+ "6b122529d4": "コミットメッセージの生成",
+ "e48caaf0dd": "紛争のためにAIエージェントを開始しました。",
+ "901140f47d": "エージェントを開始する前に、コマンド入力全体を確認して編集します。",
+ "19652ddd76": "AI で対立を解決する",
+ "c9ad22888e": "このリポジトリのブランチ比較ターゲットを選択します。",
+ "574d2f4413": "クリアノート",
+ "05bb8f4a48": "キャンセル",
+ "48db37cca9": "すべて見る",
+ "78ce2d37ac": "フォークにプッシュ",
+ "c05fe04839": "{{value0}} (原点ではない) のフォークにプッシュします",
+ "c35baf2f1e": "ファイルをフィルタリング…",
+ "2fe2a67580": "その他のメモ操作",
+ "eae2d051af": "すべてのメモをコピーする",
+ "cc474e0b8c": "注意事項",
+ "e131cd7128": "ソース管理は Git リポジトリでのみ使用できます",
+ "c07b236287": "変更を表示するワークスペースを選択",
+ "dc5a6465fc": "{{value0}} (例: {{value1}}{{value2}})",
+ "8eb3782a0c": "{{value0}} ファイル{{value1}} を破棄できませんでした",
+ "a5e5a11090": "失敗したすべての破棄 - 破棄する前にファイルをステージング解除できません",
+ "8a5ba6a988": "コミット差分をロードできませんでした",
+ "fe5bd1a610": "{{value0}} を作成しています...",
+ "812cb992ee": "{{value0}}にオープン",
+ "eef5446523": "{{value0}} #{{value1}} はすでにオープンしています",
+ "0453ca3a9a": "{{value0}} が作成されましたが、Orca はまだ更新できませんでした。",
+ "f99560ab29": "{{value0}} の中止に失敗しました",
+ "eae7a1da5f": "メモを消去できませんでした。",
+ "657e0c90ad": "{{value0}} 注{{value1}}",
+ "df5040e3c3": "アンステージ",
+ "8cde1a2fb0": "ステージ",
+ "d54dd48b0b": "変更を破棄する",
+ "989f3d5e34": "ファイルを復元する",
+ "2830dd64a2": "削除されました",
+ "11463f7a98": "追跡されていないファイルを削除する",
+ "d62bc0c7d8": "追跡されていない",
+ "ab31221779": "フォルダーのステージングを解除する",
+ "bfe9011a0e": "ステージフォルダー",
+ "6d7f2a47e5": "フォルダを破棄する",
+ "9b367363b6": "フォルダー内の追跡されていないものを削除",
+ "540ca8f78c": "マージを中止する",
+ "425f138269": "リベースを中止する",
+ "04832d8047": "リベース",
+ "c105a61960": "マージ",
+ "d7a5942e41": "{{value0}}: {{value1}} は未解決です",
+ "c56ba7fa06": "差分",
+ "94c42b252e": "医学博士",
+ "e59bca888a": "値下げ",
+ "b6922abb13": "ブランチ比較をロードできません。",
+ "715d229c86": "ブランチ比較は使用できません",
+ "97d8b03cdf": "ブランチ比較に失敗しました",
+ "424ee0e5bf": "エラー",
+ "834cb3f23d": "AIで修正する",
+ "60bd988f0b": "AIの修正",
+ "461575b9bc": "AIでコミットメッセージを生成",
+ "ddc1fbd690": "コミットメッセージの生成を停止する",
+ "5acbcedc1a": "{{value0}} を作成する",
+ "aaf1451654": "ドラフト {{value0}} を作成する",
+ "26511c22b4": "作成...",
+ "7a09d7f9d2": "ベース",
+ "383cf92c73": "木",
+ "d7ae61269b": "ブランチにコミット",
+ "3636d0f686": "準備完了",
+ "d2e9189866": "全て",
+ "a0cc0e6b4e": "読み込み中",
+ "9339382454": "すべてのステージを解除する",
+ "24d2598eff": "すべてのステージ",
+ "ce41708855": "すべて破棄",
+ "2f609a2e7c": "追跡されていないものをすべて削除",
+ "9bb062a886": "コミットされていない",
+ "9febd8ab5f": "作成_pr",
+ "f62ce91ade": "起源",
+ "3a231c845b": "未知",
+ "3baf6c77b4": "すべてのメモをクリップボードにコピーします",
+ "72f2bea3f4": "ノートを展開する",
+ "d13edef890": "メモを折りたたむ",
+ "0fad573938": "コミットされていない",
+ "77afaa8152": "全て"
+ },
+ "SourceControlAgentActionDialog": {
+ "8e856842d1": "選択したエージェントを開始できませんでした。",
+ "c075d00de1": "ワークスペース接続を解決できません。",
+ "808cfe0a3b": "このリポジトリのみに保存",
+ "994cddd1f7": "保存しないでください"
+ },
+ "SourceControlAgentActionDialogForm": {
+ "1bc0bdbb5e": "起動:",
+ "f84657c925": "起動レシピの保存",
+ "7ec6abbf2a": "リセット",
+ "f4f3c9ca4a": "コマンドテンプレート",
+ "fe119187bb": "--モデルソネット",
+ "bc8dc39f4b": "CLI 引数",
+ "b99c33cec5": "設定",
+ "15c5d85706": "エージェント",
+ "3e8f21954f": "エラー",
+ "74168d7ada": "idle",
+ "1d47db9bf0": "有効なエージェントがありません",
+ "c7ff8cef11": "エージェントを検出中..."
+ },
+ "SourceControlTextGenerationDialog": {
+ "c5b7fa7cb6": "グローバルデフォルトとして保存",
+ "7f1ec309a4": "すべてのリポジトリのデフォルトとして保存",
+ "5959da1e4d": "このリポジトリのみに保存",
+ "d054d5e0a0": "設定が読み込まれていません。"
+ },
+ "SourceControlTextGenerationDialogForm": {
+ "25fcd8e49a": "デフォルトを保存する",
+ "d91b0a189d": "レシピの保存",
+ "1f6fcfb6cf": "コマンドテンプレート",
+ "551ffd111b": "--モデルソネット",
+ "4eab815004": "CLI 引数",
+ "914c8f6ac2": "カスタムコマンド",
+ "cce2cbd01d": "エージェントを選択",
+ "9c14186dd2": "エージェント"
+ },
+ "activity": {
+ "bar": {
+ "buttons": {
+ "1fd284e931": "その他のサイドバータブ",
+ "f1132ea95d": "中性"
+ }
+ }
+ },
+ "checks": {
+ "panel": {
+ "content": {
+ "3916814392": "後ろ (ベースコミット:",
+ "755be805f6": "コメントはありません",
+ "751f7c6e5c": "ソースごとに最初の 100 件のコメントを表示",
+ "94557d68e2": "コメント",
+ "3fff651d32": "PRコメントを追加する",
+ "ea9fd5ed6a": "会話を開始...",
+ "0fc6f743b3": "による",
+ "8987d5a3dd": "解決済み",
+ "ba20d1a896": "{{value0}} に返信",
+ "f6a40263ff": "保存",
+ "b062f55f29": "キャンセル",
+ "c1f6fc006a": "返事",
+ "2ba0a32bdd": "ボット",
+ "6cc6eace26": "削除",
+ "03ca88f623": "編集",
+ "d3923d18fe": "コメントに移動",
+ "1abb17aac9": "もっと",
+ "74c6885b8a": "その他のコメント操作",
+ "cbcc4ab3db": "最初の 100 件のチェックを表示しています",
+ "0dca6bfab5": "オープンチェックの詳細",
+ "991f50c7e4": "チェックが設定されていません",
+ "9ad98f2a17": "保留中",
+ "5e52f4ef7f": "失敗した",
+ "02ca4f9074": "合格",
+ "e15a8b77ef": "このチェックではインライン詳細は利用できません。",
+ "679bf2093c": "ログの末尾をコピーする",
+ "d713f500b2": "ログテール (最後の 200 行)",
+ "a916648574": "詳細を開く",
+ "07eccfa397": "このチェックの詳細はありません。",
+ "49731703ea": "求人",
+ "f2fe8a4e8f": "注釈",
+ "d098e5529a": "出力",
+ "2dd5ddabc4": "ワークフロー #",
+ "aa8494ae3c": "チェック #",
+ "00e1c1658a": "完了",
+ "fd46a70f1a": "開始しました",
+ "a54ae21c6f": "状態:",
+ "e4e3af15ee": "詳細を表示",
+ "2524d1fb83": "ログテールで詳細を確認できます。",
+ "a2fb3f4408": "最初の 100 件の求人を表示しています",
+ "df137989b3": "最初の 20 個の注釈を表示",
+ "1f2b980522": "チェックの詳細を読み込んでいます…",
+ "0c96cd25e5": "解決する",
+ "3a71a6ed0b": "チェックとマージが完了する前に競合を解決してください。",
+ "60186d8498": "競合によりこれがブロックされます",
+ "c16762ac8c": "以下のチェックとコメントは、現在取得されているコンテキストを示しています。",
+ "9d0e7bcefc": "PR 操作をブロックしない",
+ "5856874b59": "Orca は、このパネルが開いている間、チェックを更新します。",
+ "5341023167": "チェック",
+ "b45db92d0e": "修理",
+ "5d4ebf9391": "詳細を検査するか、AI 修正パスを開始します。",
+ "b652f38caf": "チェックに失敗しました",
+ "87cd07c69a": "このブランチには解決する必要のある競合があります",
+ "0975eeaaef": "競合するファイル",
+ "6fa7f8723f": "専念",
+ "2b2be92919": "コメントを追加",
+ "7440d09d2c": "会話を開始する",
+ "b37ebdc51c": "コメントはできません。",
+ "90206b6353": "コメント",
+ "95ad090b01": "糸",
+ "365254cc1b": "未解決",
+ "7f793b571d": "ドラッグしてチェックのサイズを変更します",
+ "ee07b33924": "未知",
+ "cdbfda4dec": "注釈",
+ "066fedd446": "失敗したジョブ",
+ "ae8a04ef17": "競合ファイルの詳細は利用できません",
+ "73d0675356": "競合の詳細を更新しています…"
+ },
+ "empty": {
+ "state": {
+ "5b0cfae9a5": "{{value0}} を作成してチェックとレビューを開始します。",
+ "13e1c7d5ed": "{{value0}} が見つかりませんでした",
+ "d372072df1": "現在のレート制限予算により GitHub の更新が一時停止されています",
+ "7c299df37b": "PRが見つかりませんでした",
+ "3d4af82ff4": "このブランチの GitHub ステータスを更新しています",
+ "938b5606a6": "PRを確認しています",
+ "6ba2440770": "このブランチの GitHub ステータスを更新するのを待機しています",
+ "2bdd7aaf2d": "GitHub のステータスを更新できませんでした。既存のキャッシュされたデータは保存されました。",
+ "5f478ab3d3": "PRを更新できませんでした",
+ "6ce9d4e069": "{{value0}} を作成する前にブランチをプッシュします。",
+ "76e15946a9": "ブランチにプッシュされていないコミットがあります",
+ "f8543140cc": "{{value0}} を作成する前に、このブランチを公開してください。",
+ "41252bc53f": "ブランチは公開されていません",
+ "05e4aec17b": "{{value0}} チェックは操作の完了後に利用可能になります",
+ "d77c513c1e": "{{value0}} が進行中です"
+ }
+ }
+ }
+ },
+ "gitlab": {
+ "mr": {
+ "merge": {
+ "state": {
+ "04a3015a12": "マージ可能",
+ "53c6d3b7e9": "GitLab は、この MR はマージできるが、パイプラインはまだ実行中であると言っています",
+ "65c847ad1e": "保留中のチェック",
+ "b41fbc180c": "GitLab は、この MR はマージできるが、一部のパイプライン ジョブが失敗したと言っています",
+ "49ac4fec10": "チェックに失敗しました",
+ "22b7e50621": "GitLab がマージ競合を報告",
+ "96b05e374c": "紛争",
+ "d63bb6f76e": "この MR はまだ下書きです",
+ "b2715092c6": "下書き",
+ "2388413f28": "この MR はクローズされています",
+ "88d044c42f": "クローズ",
+ "ee482a2bad": "この MR はすでにマージされています",
+ "fae95ae20d": "合併しました"
+ }
+ }
+ }
+ },
+ "index": {
+ "70893f017b": "側",
+ "7b415c39e9": "トップ",
+ "864111caa2": "アクティビティバーの位置",
+ "e8e2e4ce74": "右サイドバーを切り替えます",
+ "441733b630": "ポート",
+ "83a10e3c44": "チェック",
+ "0314901467": "ソース管理",
+ "06219e4cb1": "検索",
+ "8bc2bbc3a0": "エクスプローラ",
+ "45b78f03bc": "側",
+ "34af8aadf5": "トップ",
+ "9fffaf17c1": "右サイドバーを切り替えます ({{value0}})",
+ "b37ff4a89a": "ポート",
+ "9f83375839": "チェック",
+ "6306b48afd": "ソース管理",
+ "ef182dcb12": "検索",
+ "fc3095d2ed": "エクスプローラ"
+ },
+ "right": {
+ "panel": {
+ "comment": {
+ "composer": {
+ "9bca633dee": "キャンセル",
+ "cf5a7aba6f": "リスト",
+ "d6d9c3c947": "引用",
+ "f49e0a21e0": "コード",
+ "542bf6a7e2": "イタリック",
+ "256300f8ea": "大胆な",
+ "87aff03d63": "送信中..."
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "ai": {
+ "commit": {
+ "failure": {
+ "launch": {
+ "a8b97d2318": "コミット失敗に備えて AI エージェントを開始しました。",
+ "5540ff50cc": "エージェント起動コマンドを構築できませんでした。",
+ "9bbd9077a2": "有効な AI エージェントがありません。 [設定] でエージェントを構成します。",
+ "d481ab22f9": "保存された AI エージェントは使用できません。別のエージェントを選択するには、[起動のカスタマイズ] を使用します。",
+ "f2b47026e8": "コミット失敗プロンプトは空です。ソース管理 AI 設定を更新します。",
+ "4f4e0418a0": "エージェント プロンプトを構築できませんでした。",
+ "216f762bd7": "ワークスペース接続を解決できません。"
+ }
+ }
+ }
+ },
+ "discard": {
+ "confirmation": {
+ "2ae5a785b3": "ステージングされていない変更をすべて破棄しますか?",
+ "ddf36f291c": "これにより、ステージングが解除され、ステージングされたすべての変更が元に戻ります。ステージングされた新規ファイルは削除されます。これを元に戻すことはできません。",
+ "5ddd8cac7f": "段階的な変更をすべて破棄しますか?",
+ "1426c2efff": "これにより、このファイルに対するすべての変更が元に戻ります。これを元に戻すことはできません。",
+ "d4df3a61df": "「{{value0}}」への変更を破棄しますか?",
+ "40e9357b2a": "これにより、HEAD からファイルが復元され、削除が破棄されます。これを元に戻すことはできません。",
+ "5c0bdbc4cb": "「{{value0}}」を復元しますか?",
+ "d97bf697c9": "これにより、このファイルは完全に削除されます。これを元に戻すことはできません。",
+ "96c772bee9": "「{{value0}}」を削除しますか?"
+ },
+ "dialog": {
+ "3bc61dc989": "キャンセル",
+ "15efa778e3": "破棄",
+ "6de99d162b": "エントリ",
+ "42f89dd030": "ファイル",
+ "e7611dca35": "ファイル",
+ "48c5ef95d9": "エリア",
+ "0d2d88cba5": "これを元に戻すことはできません。",
+ "1551c14668": "変更を破棄しますか?"
+ }
+ },
+ "dropdown": {
+ "items": {
+ "7aad2c0240": "ホストされたレビュー操作が進行中です…",
+ "9e779995dd": "{{value0}} を作成する",
+ "226b85a3a7": "フェッチ",
+ "323bb614aa": "コミットと同期",
+ "2b8e6595fd": "専念"
+ }
+ },
+ "primary": {
+ "action": {
+ "ed93b4f14f": "専念",
+ "946a8a05ea": "このブランチの {{value0}} を作成します",
+ "e7ffa46946": "{{value0}} を作成する",
+ "95550cff15": "押す",
+ "d64292a938": "引く",
+ "795f1509c5": "同期",
+ "390abeab93": "フォースプッシュ",
+ "1884cf34af": "このブランチをオリジンに公開します",
+ "7b4d02e6b8": "ブランチを公開",
+ "3d5dccef0b": "コミットするものはありません。PR はすでにマージされています。",
+ "41d4bcf157": "PR ステータスを確認中…",
+ "acce237921": "コミットするものは何もありません。ブランチには公開する変更はありません。",
+ "fa3bd4f40c": "少なくとも 1 つのファイルをステージングしてコミットします",
+ "5a477d80cb": "すべての変更をステージングする",
+ "18a0fca877": "ステージオール",
+ "f01f16d77f": "コミットメッセージを入力してコミット",
+ "ab41fb926b": "段階的な変更をコミットする",
+ "2d8f185fbc": "部分的にステージングされたファイルをコミットする前に、すべての変更をステージングします。",
+ "a6457b46a7": "コミットする前に競合を解決する",
+ "484f45c439": "{{value0}} が進行中です…",
+ "74fc171e99": "強制プッシュ中です…",
+ "16aee3a5c1": "コミット中です…"
+ }
+ }
+ }
+ },
+ "use": {
+ "source": {
+ "control": {
+ "ai": {
+ "cfafa92509": "送信する未解決の競合はありません。"
+ }
+ }
+ }
+ },
+ "useFileDeletion": {
+ "72691dfebc": "{{value0}} '{{value1}}' に失敗しました。",
+ "96affe1302": "「{{value0}}」は {{value1}} に移動されました",
+ "74727df633": "「{{value0}}」が削除されました",
+ "d979a4fbb5": "「{{value0}}」を完全に削除しますか?",
+ "a76c74f105": "破壊的な",
+ "92276aceb7": "削除"
+ },
+ "useFileExplorerHandlers": {
+ "32cd9fd991": "シンボリックリンクターゲットを開けません"
+ },
+ "useFileExplorerImport": {
+ "25919b2050": "{{value0}} {{value1}} をスキップしました。",
+ "132fd0e1e9": "{{value0}} {{value1}} のインポートに失敗しました。"
+ },
+ "useFileExplorerKeys": {
+ "8adb953095": "操作が失敗しました"
+ },
+ "GitHistoryGraphSvg": {
+ "47eff48230": "頭"
+ }
+ }
+ },
+ "repo": {
+ "NestedRepoChecklist": {
+ "f7e1170567": "選択された",
+ "ea54c7bf8f": "の",
+ "91b5bcadb6": "すべて選択",
+ "929734aea5": "すべての選択を解除します"
+ },
+ "NestedRepoScanLimitNotice": {
+ "642a43c139": "ネストされたリポジトリのスキャン制限",
+ "574eb5408b": "部分的なスキャン結果を表示しています。",
+ "03e9beab7b": "スキャンが早期に停止しました。"
+ },
+ "RepoCombobox": {
+ "b3e15f4525": "プロジェクトの追加",
+ "b4a235e886": "プロジェクトの追加",
+ "3639fd9da2": "SSH",
+ "e7ed739236": "検索に一致するプロジェクト/フォルダーはありません。",
+ "a0c48f5f29": "プロジェクト/フォルダーを検索...",
+ "116812151a": "プロジェクトを追加中…"
+ },
+ "repo": {
+ "icon": {
+ "0ad395d475": "箱",
+ "857977b901": "形状",
+ "b1b8d99fc4": "AI",
+ "137bdb1856": "メトリクス",
+ "d202c659a3": "デザイン",
+ "c4fd14299d": "会社",
+ "4ab9433660": "仕事",
+ "febfbe0cd5": "ツール",
+ "ecf63ec3ef": "起動",
+ "31826b712e": "API",
+ "70bef15d40": "レイヤー",
+ "b5fac337aa": "コンピューティング",
+ "d37b4e2641": "サーバ",
+ "3c5a593bc8": "ウェブ",
+ "477b28c948": "データベース",
+ "787490e9bd": "パッケージ",
+ "07012dc113": "エージェント",
+ "3eba7387ab": "ターミナル",
+ "65b437c381": "コード",
+ "bed2674f9d": "フォルダ"
+ }
+ }
+ },
+ "pet": {
+ "pet": {
+ "models": {
+ "7433516faf": "グレムリン",
+ "a84d5677ff": "OpenCode",
+ "2528586aa7": "クラウディーノ"
+ }
+ },
+ "PetOverlay": {
+ "de932b0e8f": "@keyframes ペットボブ { 0%,100% { 変換:translateY(0); } 50% { 変換:translateY(-4px); } }",
+ "4712d196c6": "@keyframes pet-{{value0}} { from { 背景位置: {{value1}}px {{value2}}px; } から { 背景位置: {{value3}}px {{value4}}px; } }"
+ }
+ },
+ "onboarding": {
+ "AgentStep": {
+ "e6a369bd04": "人気のエージェント",
+ "d7b3ef168b": "システム上で検出されました",
+ "9c163bb0e0": "インストール手順",
+ "69af7e9c1c": "はまだ PATH 上にありません。 Orca はこれをデフォルトとして設定し、いつでもインストールできます。",
+ "1eee1c7bd8": "PATH 上にエージェントが検出されませんでした。後でインストールするものを選択するか、空のターミナルを使用して続行します。",
+ "hideAgents": "エージェントを非表示にする",
+ "showMoreAgents": "{{value0}} 件のエージェントをさらに表示→"
+ },
+ "FeatureSetupChecklist": {
+ "77f74946f5": "エージェントは相互にメッセージを送信し、タスクを実行し、引き継ぎを調整できます。",
+ "399cf885c0": "エージェントオーケストレーション",
+ "c5292c409d": "エージェントは、要求に応じてアプリ ウィンドウを検査し、ローカル アプリを操作できます。",
+ "1ecfb490ac": "コンピュータ操作",
+ "01426f3a23": "エージェントはサイトを移動し、ページを検査し、ブラウザーのタスクを実行できます。",
+ "ea85d9e628": "エージェントブラウザの使用"
+ },
+ "FeatureSetupInlineTerminal": {
+ "789b59936e": "Enter キーを押してコマンドを実行し、要求されたら npx を確認します。これは、後で [設定] で設定することもできます。",
+ "47fc6cc6dc": "スキルセットアップコマンド",
+ "c767ab7061": "スキルセットアップ"
+ },
+ "IntegrationsStep": {
+ "277f30eb34": "Linear、GitLab、Bitbucket、Azure DevOps、Gitea、Jira は [設定] > [連携] にあります。",
+ "3a3e360289": "その他のタスクソース",
+ "80e3ce0bc9": "再確認",
+ "04ef416712": "Linearアクセスを追加",
+ "dd9c186a8b": "ワークスペースへのアクセスを追加",
+ "c91a5782f1": "接続済み",
+ "27743304b1": "Linear",
+ "af69f42372": "Enter を押して GitHub CLI 認証を実行します。ブラウザまたはデバイスのフローが完了したら、GitHub を再確認します。",
+ "f9d2e12d17": "GitHub サインイン コマンド",
+ "6d469169f2": "GitHubのセットアップ",
+ "bd5d976fb2": "ghをインストールする",
+ "50db38cf4b": "PR、イシュー、チェックの状態。",
+ "c1547656f0": "チェック中…",
+ "8405043962": "サインインが必要です",
+ "5c115cb713": "CLIがインストールされていない",
+ "217beb0658": "GitHub",
+ "4983ae7433": "Personal API キーを使用してLinear アクセスを追加します。フルアクセス キーは、キーの所有者がアクセスできるすべてのチームを表示できます。",
+ "b08a6ac93c": "{{value0}} ワークスペース{{value1}} がリンクされました。いつでも別のワークスペースを追加したり、制限付きキーを置き換えたりできます。",
+ "93f0c49ad1": "認証されていない",
+ "a3bcf13694": "接続されています",
+ "d6e5dba05a": "サインイン",
+ "0b4a7d23ab": "サインインする",
+ "a74c6d6b18": "未インストール"
+ },
+ "NotificationStep": {
+ "3bede04483": "テスト通知を送信する",
+ "dc897423e1": "通知音を選択する",
+ "53aaffe49a": "通知音",
+ "0fe570690c": "デスクトップ通知が配信された後に Orca が再生するアラートを選択します。",
+ "0af746e41f": "サウンドを選択",
+ "8124d085a6": "Macの設定を開く",
+ "aa36281b00": "システム設定を開き、Orca が通知の送信を許可されていることを確認します。",
+ "d2dba86837": "macOS で Orca を許可する",
+ "e52aacf380": "通知設定を読み込んでいます…",
+ "3cd5374e22": "通知設定をまだ読み込み中です",
+ "b6a994e36e": "通知音が再生できませんでした",
+ "c0692baa52": "カスタムファイルの選択",
+ "ac80d97e02": "カスタムファイルの変更"
+ },
+ "OnboardingFlow": {
+ "1b5e182e9f": "Orcaへようこそ",
+ "4db04f2f57": "の",
+ "adaa0aa627": "オンボーディング ステップ {{value0}}: {{value1}} に進みます。",
+ "a249f81538": "Orca",
+ "277ba45540": "Orca のオンボーディング",
+ "97c42cda00": "GitHub CLI をインストールして以下を実行します。",
+ "ae3b00ca82": "GitHub タスクをセットアップする",
+ "ff92d15436": "Orca は、エージェントの作業が完了したとき、またはサポートが必要になったときに通知します。",
+ "b054332836": "通知を設定する",
+ "04ae28d8ca": "何時間も眺めていたくなるテーマを選んでください。",
+ "f396db9f20": "まるで家にいるような気分にさせてくれる",
+ "322fc50a18": "Orca はすべての CLI エージェントと連携して動作します。最もアクセスしやすいものを選択。いつでも切り替え可能。",
+ "198b148b3c": "デフォルトのエージェントを選択",
+ "a5e5da02f7": "連携",
+ "35bbaf5ae0": "通知",
+ "984338477a": "テーマ",
+ "c47e1bd149": "エージェント"
+ },
+ "OnboardingFooter": {
+ "ba58547306": "戻る",
+ "111d3f8d92": "プロジェクトのセットアップにスキップ"
+ },
+ "OnboardingInlineCommandTerminal": {
+ "4123609efd": "ターミナルを起動しています..."
+ },
+ "OnboardingSkipConfirmationDialog": {
+ "9f47f345a4": "それほど時間はかかりません!",
+ "e4726b2d50": "オンボーディングをスキップしますか?"
+ },
+ "OnboardingTourStep": {
+ "3f9586c043": "ツアーに参加する",
+ "60c5576353": "出口ツアー"
+ },
+ "RepoStep": {
+ "e8fdb36338": "リポジトリをスキャンしています。クリックして停止します。",
+ "b7c4da0504": "SSH? 「設定」でホストをセットアップする",
+ "c33b190ca3": "サーバーパスのみ",
+ "7b679207e4": "ワークスペース",
+ "24c7c8696c": "サーバーパスにクローンを作成します",
+ "7932e95f68": "クローン",
+ "955134915e": "git@github.com:org/repo.git",
+ "288d8444b7": "HTTPS または SSH URL を貼り付けます。",
+ "132425a3e3": "リポジトリのクローンを作成する",
+ "6558d50c69": "一度に多くのリポジトリをインポートしたいですか?親フォルダーを選択します。",
+ "831524961f": "git リポジトリかどうかに関係なく、任意のローカル ディレクトリを選択します。",
+ "f4e9c8dcf8": "フォルダーを参照する",
+ "e8214aa632": "フォルダーとして開く",
+ "3863747c56": "Gitプロジェクトの追加",
+ "2ebbc26343": "/ホーム/ユーザー/プロジェクト",
+ "466108ab89": "ランタイムサーバー上に存在するパスを入力します。",
+ "8cab104e3c": "サーバープロジェクトを開く",
+ "2d20200346": "リポジトリのインポート",
+ "27ca610db1": "戻る",
+ "cecd6593fa": "スキャンしたフォルダー:",
+ "c7af322fc3": "スキャンを停止する",
+ "c3d9d44ca2": "スキャンの停止",
+ "cf23006ba7": "ランタイムサーバー",
+ "7ec3f48820": "/ホーム/ユーザー",
+ "2e6438dd34": "{{value0}}このフォルダー内で {{value1}} {{value2}} が見つかりました。"
+ },
+ "ThemeStep": {
+ "a4b254779d": "macOSのオプションキー",
+ "6c51398942": "ねずみ",
+ "8ca01945f2": "ディバイダー",
+ "b3a99a2d29": "ウィンドウ",
+ "86c0f1caa2": "パディング",
+ "06a24f4f2d": "色",
+ "c021e9dddd": "テーマパレット",
+ "ab2a583a97": "Cursor",
+ "cc1858e19e": "フォント",
+ "248c812283": "輸入",
+ "7ee9234e54": "Ghostty 構成が検出されました。",
+ "78b6386140": "ゴーストティから輸入しました。",
+ "2c3aa538f8": "Ghostty 設定を検索中…",
+ "94b9dc561d": "設定→ターミナル",
+ "dd5c16ad1b": "フォント、カーソル、パレットを含むその他のターミナルオプション",
+ "ad192706e6": "ライト",
+ "fa7b673ea9": "ダーク",
+ "827ea7b4a2": "システム",
+ "699ddf83c2": "Ghostty 設定のインポートに失敗しました",
+ "16a9f0446a": "インポートする Ghostty 設定が見つかりません",
+ "ad19e5c916": "インポート中…",
+ "906c4373fe": "設定"
+ },
+ "use": {
+ "onboarding": {
+ "flow": {
+ "dce4bdce5b": "SSH設定を開けませんでした",
+ "fd74e7558e": "クローン作成に失敗しました",
+ "52acfbef51": "進行状況を保存できませんでした"
+ }
+ }
+ },
+ "AgentFeatureSetupStep": {
+ "97dcdc010f": "機能を有効にする"
+ }
+ },
+ "new": {
+ "workspace": {
+ "SmartWorkspaceNameField": {
+ "2a0d535f69": "新規ブランチを作成する",
+ "a44229ce4d": "ワークスペース名として",
+ "766083a596": "」",
+ "34ca97bce3": "」",
+ "b1a7d679ba": "使用",
+ "e57c53727c": "プロジェクトを追加...",
+ "a76fcb4fa0": "に切り替えます",
+ "eadf877af5": "保つ",
+ "6859e2896c": "キャンセル",
+ "9ef1a7c4b0": "、選択したプロジェクトとは異なります。",
+ "ad188067ae": "GitHub URL は次を指しています。",
+ "4bd98f1091": "プロジェクトを切り替えますか?",
+ "0c9e668e3a": "クリア",
+ "7199ff19c7": "選択したソースをクリアする",
+ "370a1faf67": "ブラウザで開く",
+ "2c69728c2a": "ブラウザでリンクを開く",
+ "6f07a18604": "名前",
+ "2e4c7c95fe": "ブランチ",
+ "2cfc6be192": "GitLab",
+ "7a47af0565": "Linear",
+ "0a180280bd": "GitHub",
+ "b3c60c2b7c": "頭いい",
+ "26824f60dd": "全て",
+ "6fad211c66": "クローズ",
+ "2319d87718": "合併しました",
+ "622864b52a": "オープン",
+ "fda67f0b61": "現在のプロジェクト",
+ "3e8bb1176a": "設定で Linear を接続してイシューを検索します。",
+ "69ce292138": "Linear",
+ "9c004911c3": "gitlab"
+ }
+ }
+ },
+ "mobile": {
+ "MobileHero": {
+ "a8fb43cf1c": "Continue",
+ "3f90dbd274": "完了",
+ "b622eba64d": "戻る",
+ "65b3f2e8bc": "生成中…",
+ "27735e5f4e": "ペアリングQR",
+ "bb0074ce11": "ペアリング用QRコード",
+ "010dddcf27": "ペアリングコードをコピーする",
+ "4c1df4eba7": "スキャンできないのですか?",
+ "85067b9e06": "ネットワークインターフェースを更新する",
+ "ca85e595a7": "インターフェースが見つかりません",
+ "79d2f480da": "アドバタイズするネットワーク インターフェイス",
+ "dfd2aa9d5d": "ネットワーク",
+ "2f077ef4eb": "をクリックしてコードをスキャンします。",
+ "3aa7bb2d8b": "デスクトップのペアリング",
+ "d1495e5e64": "Orca モバイルを開き、 をタップします",
+ "901c98bb93": "これをペアリングします",
+ "3960f5c339": "ステップ 2/2",
+ "3241f3c26a": "QRをインストールする",
+ "7af266b80d": "QRコードをインストールする",
+ "aa97420ba4": "インストールリンクをコピーする",
+ "ac1eb64952": "Android",
+ "711e6f4b47": "iOS",
+ "e75647ace0": "スマートフォンで QR をスキャンするか、インストール リンクを開いて Orca Mobile を取得します。",
+ "0d9b33299e": "アプリを入手してください。",
+ "92ddfdfa1f": "ステップ 1/2",
+ "ff48d9d520": "別のデバイスをペアリングする",
+ "f9cbf4bb53": "デバイスを取り消します",
+ "34f878d04f": "{{value0}}を取り消す",
+ "94829abdb1": "ペアリング済み",
+ "266c18c105": "Orca Mobile を開いて中断したところから再開するか、別のデバイスをペアリングします。",
+ "5410d55d79": "Orcaモバイル",
+ "10d27b4cba": "始めましょう",
+ "da1d5e5ed0": "で利用可能",
+ "ec0607bf66": "サポートされているモバイル プラットフォーム",
+ "b4ccce5cb7": "スマートフォンから Orca をコントロールします。デスクから離れていても、エージェントの状況を確認し、変更を確認し、タスクを開始できます。",
+ "cd4e5e816f": "ワークスペースをポケットに。",
+ "a6cffbbb0b": "コードを生成する",
+ "e59a252eca": "コードを再生成する",
+ "d0b52871ce": "スマートフォンはペアリングされています。",
+ "051978a785": "スマートフォンはペアリングされています。"
+ },
+ "MobilePage": {
+ "e17393c6a3": "スマートフォンプレビュー",
+ "baea63c445": "リンクのコピーに失敗しました",
+ "fad833de8d": "インストールリンクをコピーしました",
+ "6a66e38943": "ペアリングコードのコピーに失敗しました",
+ "3c1f7168bb": "ペアリングコードをコピーしました",
+ "4c8bd11c1a": "ペアリングコードの生成に失敗しました",
+ "b353e18de1": "WebSocketトランスポートが実行されていません",
+ "4e1eb5d55c": "デバイスの取り消しに失敗しました",
+ "255372e6e8": "デバイスが取り消されました",
+ "1b4509a8a1": "ペアになった",
+ "c5909374cf": "イントロ"
+ },
+ "MobilePageToolbar": {
+ "ad2284a9e2": "閉じる・Esc",
+ "9883b58693": "Orca モバイルを閉じる",
+ "fb5f28330e": "サイドバーに表示",
+ "c669abcf8f": "サイドバーから隠す"
+ },
+ "PhoneCarousel": {
+ "96d651cb87": "ターミナルセッション",
+ "93217b41c1": "ワークツリーリスト",
+ "89c7713645": "Orca モバイルのホーム画面"
+ },
+ "mobile": {
+ "platform": {
+ "copy": {
+ "2a532d6fd7": "Android カメラでスキャンして、GitHub リリースから最新の APK をダウンロードします。",
+ "432db52b73": "iPhone のカメラでスキャンして App Store を開きます。"
+ }
+ }
+ },
+ "slides": {
+ "HomeSlide": {
+ "a7d9e2c44d": "7日",
+ "a3d5476811": "5時間",
+ "8a350a4784": "アカウントの使用状況",
+ "e27fdaee51": "新規ワークスペース",
+ "4405f3c440": "デスクトップのペアリング",
+ "0b00c98506": "クイック操作",
+ "0bad5b07c8": "GitHub とLinear",
+ "d047197480": "GitHub · Linear",
+ "a4c3f7b7aa": "タスク",
+ "d33d7a9c29": "orca · feat/mobile-page",
+ "25d6e8a491": "偉業/モバイルページ",
+ "c791677f2f": "再開する",
+ "cf3f98fa3f": "切断されました",
+ "091355da3d": "M1ミニ・ホーム",
+ "0bc1881bc4": "接続済み · 40 ワークツリー · 5 アクティブ",
+ "19c212e25e": "MacBook Pro",
+ "2f1a1d10c4": "デスクトップ",
+ "156db8a68a": "作成された PR",
+ "4a40af029b": "エージェント時間",
+ "00a6903322": "エージェントが生成されました",
+ "c0e2e9dcd9": "おかえり",
+ "af761a0c0d": "設定",
+ "5d94e8ddcc": "Orca"
+ },
+ "TerminalSlide": {
+ "0bb39f8fe6": "送信",
+ "69334b4b10": "音声ディクテーション",
+ "29f2d13839": "コマンドを入力してください…",
+ "817090af40": "Ctrl+C",
+ "53ff909568": "タブ",
+ "4930eaaae7": "ESC",
+ "fa22927f13": "ペースト",
+ "985373052e": "スマートフォンモードに切り替え",
+ "58a9ee6003": "ツール呼び出しのフォーマット。次に差分を追加しますか?",
+ "aa64b519c6": "ターミナル画面。Tokyonight パレット、Menlo、real claude",
+ "e75112c834": "ペアスキャン スライドを高忠実度のものに交換しました",
+ "3ce3e8c892": "14 件が合格、1 件がスキップ (1.8 秒)",
+ "4b3666f9a9": "src/cache/worktree-cache.test.ts",
+ "1d448b69f7": "合格",
+ "d39445686a": "src/transport/host-store.test.ts",
+ "a6e7cdc688": "pnpm テスト --フィルターモバイル",
+ "21b67dfc92": "バッシュ",
+ "d6d1041a1c": "⎿ ペアスキャンスライドをターミナルセッションに置き換えました",
+ "336c0e070e": "mobile/orca-mobile-sidebar-mock-v3.html",
+ "6d4ebd5833": "編集",
+ "fc83e0d5ef": "⎿ 2103 行を読み取ります",
+ "80cc356591": "読む",
+ "2c10d43745": "claude",
+ "e0f98be657": "orca/feat-mobile-page",
+ "2defc05141": "開発@マック",
+ "da121ba48d": "計画.md",
+ "e4befee569": "シェル",
+ "606aa93192": "ファイル",
+ "94febb0976": "ソース管理",
+ "8d6516312d": "2 ターミナル · claude active",
+ "8432787c4e": "偉業/モバイルページ",
+ "8fd998acd3": "戻る"
+ },
+ "WorktreeListSlide": {
+ "357a519567": "アクティブ",
+ "79a24ff530": "固定された",
+ "22971156df": "リポ",
+ "17f9e0d226": "最近の",
+ "0e3e809a4b": "フィルター",
+ "b4271864bd": "MacBook Pro",
+ "cefd048225": "戻る",
+ "c5ad56786d": "スピナー"
+ }
+ }
+ },
+ "gitlab": {
+ "gitlab": {
+ "rate": {
+ "limit": {
+ "display": {
+ "ebc0e8ecf1": "GitLab API 予算を読み込んでいます...",
+ "a2d3d1fdde": "GitLab API の予算は利用できません。",
+ "a2f68645ac": "GitLab API 予算を更新する",
+ "2f9c16d6c3": "Orca は GitLab CLI を通じて REST を使用します。",
+ "14e144f7a7": "GitLab API の予算",
+ "3e2c982cfa": "左、リセット",
+ "ea8ad0bae8": "の",
+ "0a891e8935": "REST API",
+ "953f7c6062": "この GitLab ホストはレート制限ヘッダーを返しませんでした。"
+ }
+ }
+ }
+ }
+ },
+ "floating": {
+ "terminal": {
+ "FloatingTerminalIconContextMenu": {
+ "8e7d775287": "フローティングワークスペースを非表示にする",
+ "763f5fa2c1": "フローティングボタンに移動",
+ "0ee79e0674": "ステータスバーに移動"
+ },
+ "FloatingTerminalOrchestrationDialog": {
+ "f726054620": "エージェントがコンテキストを引き継ぎ、Orca を通じて作業を調整できるようにします。",
+ "1cd3f8af64": "オーケストレーションスキル",
+ "6f0aed26b8": "Orca CLI とオーケストレーション スキルをインストールすると、エージェントが Orca を通じて調整できるようになります。",
+ "05d7aabc20": "未インストール",
+ "630c0ac8c8": "インストール済み",
+ "dfd021ce46": "確認中...",
+ "543f325a14": "オーケストレーションを有効にする"
+ },
+ "FloatingTerminalPanel": {
+ "fc1042e92b": "最小化",
+ "8b07759314": "新規ブラウザ",
+ "88ffb502e5": "マークダウンノートを開く",
+ "629528690b": "新規マークダウンノート",
+ "3215fc73e9": "新規ターミナル",
+ "da508bd7f5": "保存",
+ "918c2139f3": "保存しないでください",
+ "e7bf09d4d4": "キャンセル",
+ "690b6fb98a": "未保存の変更",
+ "bbc177f98f": "有効化",
+ "adc281394d": "閉じる",
+ "8cf80db43b": "エージェントが Orca を通じて調整できるように、Orca CLI とエージェント スキルをセットアップします。",
+ "2a3c5ddf5e": "オーケストレーションを有効にする",
+ "d6b563ae24": "エディターを読み込み中...",
+ "8b14ba6c17": "新規ブラウザタブ",
+ "b085fb58b5": "このファイルには保存されていない変更が含まれています。",
+ "5ddc688c52": "「{{value0}}」には未保存の変更があります。閉じる前に保存しますか?",
+ "25d7817f79": "ターミナル"
+ },
+ "FloatingTerminalToggleButton": {
+ "3b04b065b5": "フローティングワークスペースを表示",
+ "5785dd9148": "フローティングワークスペースを最小限に抑える",
+ "bfe7809a70": "{{value0}} フローティング ワークスペース ({{value1}})"
+ },
+ "FloatingTerminalWindowControls": {
+ "2f6054342c": "最小化",
+ "1bbaa0302f": "フローティングワークスペースを最小限に抑える",
+ "3f4ca29961": "フローティングワークスペースを最大化する",
+ "1c79cba25d": "フローティングワークスペースを復元する",
+ "648352c51f": "フローティング ワークスペースで {{value0}} を開く",
+ "82da3701e7": "{{value0}} の起動コマンドを構築できませんでした。",
+ "109870e023": "最大化",
+ "b5686fee1e": "復元"
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "AgentCapabilitiesSetupAction": {
+ "b8dc9dd8a2": "インストール済み",
+ "1b51644c2d": "エージェントはデスクトップを制御し、カーソルを移動したり、アプリをクリックしたり、入力したりできます。",
+ "362a07517d": "コンピュータ操作",
+ "5e8fe5a72d": "エージェントが Orca のブラウザに直接アクセスできるようにすると、ページをテストし、スクリーンショットをキャプチャし、表示された内容に基づいて行動できるようになります。",
+ "e638da007a": "エージェントブラウザの使用",
+ "c61c91e642": "エージェントが Orca を通じて調整し、大規模な複数ステップのタスクを完了まで進められるようにします。",
+ "ac07f8887f": "エージェントオーケストレーション",
+ "e9eb197e12": "開かれたコンピュータ操作許可",
+ "3a59452a67": "スキル コマンドをコピーして確認のために以下に挿入しました。",
+ "c605f51f2b": "機能セットアップの準備完了",
+ "1aa657d8f4": "一部の機能の設定には注意が必要です",
+ "c89534cbe9": "CLIとスキルのインストール"
+ },
+ "AiCommitPrSettingsCard": {
+ "8d4152701a": "例えばオラマはラマ3.1 {{value0}}を実行します",
+ "9ee54037a4": "カスタムコマンド",
+ "4b2fc4b80c": "考える努力",
+ "be8917699e": "モデル",
+ "4d9b6d84df": "サポートされていません。Claude、Codex、またはカスタムを選択します。",
+ "560d4feb00": "カスタム",
+ "29d119fe95": "エージェント",
+ "f9382b48a1": "AI 著者を有効にする",
+ "1c0cb4fabb": "AI作者",
+ "bd14e9c42a": "未設定",
+ "1f9468c5c9": "{{value0}} はサポートされていません"
+ },
+ "BrowserAnimatedVisual": {
+ "46df009982": "無料トライアルを開始する",
+ "25f15c2219": "プロ",
+ "59ae327405": "スターター",
+ "9e0f530390": "価格設定",
+ "0ce7c24b4d": "働く…",
+ "f2034c4930": ">",
+ "6e4616d039": "Claude",
+ "0f8481e1a7": "Claudeに送る",
+ "3d2352f94b": "変化を説明してください…",
+ "d8856b604a": "div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta",
+ "7da6eed7bf": "ローカルホスト:3000",
+ "0a2bd01c02": "新規ブラウザタブ",
+ "04096318ab": "ターミナル 1",
+ "eb88125c6f": "✓ 検証済み – 無料お試し版はまだ機能します。",
+ "051c97d15a": ".pp-card[data-card=\"スターター\"] .pp-cta",
+ "4fa59ca545": "✓ 更新されました",
+ "1bec24acc1": "@keyframes ブラウザフラッシュ { 0% { 不透明度: 0; } 20% { 不透明度: 0.85; 100% { 不透明度: 0; } } @keyframes browserTabIn { from { 不透明度: 0;変換:translateY(-2px); } から { 不透明度: 1;変換: なし。 } } @keyframes browserViewIn { from { 不透明度: 0;変換:translateY(4px); } から { 不透明度: 1;変換: なし。 } }",
+ "73bbb46073": "/価格設定",
+ "f39be6ca14": "/サインアップ"
+ },
+ "BrowserUseSkillSetupCard": {
+ "cbc45022d4": "エージェントが Orca のブラウザでページに移動して確認できるようにします。",
+ "d5bb1cd4ba": "ブラウザ使用スキル"
+ },
+ "ComputerUseAnimatedVisual": {
+ "d8401975b1": "承認された",
+ "f27676a92c": "状態:",
+ "6804cb356f": "クリック送信",
+ "1719b28a81": "「承認」を見つけました",
+ "79445f7512": "アプリでメモを承認する",
+ "99a8624bcb": ">",
+ "2adb561b44": "Claudeコードセッションが開始されました",
+ "94787f01f8": "Claude・コード",
+ "9cddfe96b2": "ローカルアプリ",
+ "9634d870d1": "承認する",
+ "3cc2df3671": "完了",
+ "bdd5312213": "保留中",
+ "c11dda000b": "承認された"
+ },
+ "EditorAnimatedVisual": {
+ "7a763daf2f": "イタリック",
+ "8521536429": "大胆な ・",
+ "8341391520": "ブロック用 ·",
+ "3fe42a1da0": "タイプ",
+ "8268b2376b": "コードブロック",
+ "37fa4948ce": "箇条書きリスト",
+ "f25687c588": "引用",
+ "abbdeea15d": "基本ブロック",
+ "a26a68d30c": "見出し2",
+ "722170663a": "見出し1",
+ "1fb29ad710": "見出し",
+ "4426aab46f": "新規タイルが表示されたら、ドキュメント インデックスを更新します。",
+ "95f0c3a46f": "新しいマシンでインストール フローをスモーク テストします。",
+ "22ae7b4d9d": "チームへの簡単なメモ — 出荷前に残っているものをまとめます。",
+ "5a55c00a81": "起動プラン",
+ "218503f9f3": "自動保存された",
+ "cda56c5915": "メモ / launch-plan.md",
+ "e16479c1c5": "[データスラッシュメニュー] [データスラッシュ行].slash-active { 背景: rgba(24,24,27,0.07);ボックスシャドウ: インセット 0 0 0 1px rgba(24,24,27,0.06); } [data-md-active-line][data-role=\"active\"] { color: rgb(113 113 122);フォントファミリー: ui-monospace、SFMono- Regular、Menlo、monospace;フォントサイズ: 12.5px; [data-md-active-line][data-role=\"h1\"] { color: 継承;フォントファミリー: 継承;フォントサイズ: 18px;フォントの太さ: 700;文字間隔: -0.01em;行の高さ: 1.2;マージントップ: 6px; } [data-md-caret] {表示: インラインブロック;幅: 1.5ピクセル;高さ: 1em;背景: 現在の色;垂直整列: -2px;左マージン: 1px;アニメーション: md-caret-blink 1.05 秒ステップ (1) 無限; } @keyframes md-caret-blink { 0%, 50% { 不透明度: 1 } 51%, 100% { 不透明度: 0 } } @keyframes md-block-in { from { 不透明度: 0;変換:translateY(-2px); } から { 不透明度: 1;変換: なし。 } } @keyframes md-cursor-ripple { 0% {transform:scale(0.4);不透明度: 0.9; } 100% { 変換: スケール(1.4);不透明度: 0; } } [data-clicking=\"1\"] [data-cursor-ripple] { アニメーション: md-cursor-ripple 460ms イーズアウト フォワード; }"
+ },
+ "FeatureTourPreview": {
+ "1170621527": ">",
+ "304ad0dfc1": "考え...",
+ "ef8b164dd1": "ソース/認証を確認する",
+ "952d3ddd9a": "セッションが開始されました",
+ "771d8881c2": "claude",
+ "6ed43cb0e0": "ダッシュボードの仕様",
+ "24fedd5a52": "ログイン.spec.ts",
+ "8279e9d95b": "12 個のテストを実行する",
+ "6218a9014d": "pnpm プレイライト テスト",
+ "04d54d50ec": "orca · zsh",
+ "1aa8a9a24a": "分割可能なターミナル",
+ "2a7cfc82c8": "GH #1842 にリンク",
+ "3822d8d14b": "fix/worktree-picker-truncates",
+ "d54aefe09e": "LIN-329",
+ "40bbd92ef4": "始める",
+ "c1f28c03b2": "ワークツリーピッカーが切り捨てる",
+ "fc0cc0b267": "GH #1842",
+ "0688842445": "GH #1799",
+ "bee6b4088d": "GitHub とLinearタスク",
+ "5171768676": "3 つのエージェントを調整する",
+ "cebc7769cd": "認証フローを再設計する",
+ "e44269e97d": "エージェントのオーケストレーション",
+ "ec4a73f5e6": "PR 3/3",
+ "cfdfd4d6b4": "PR 2/3",
+ "b1f17bcc74": "PR 1/3",
+ "e38112b289": "請求 Webhook をリファクタリングする",
+ "9c812e0d7c": "CIパイプラインを高速化する",
+ "3c4adfd821": "ログイン競合状態を修正",
+ "56a0271428": "隔離されたワークスペース",
+ "ef737dcee1": "GitHub とLinearタスク",
+ "ac51c061e2": "codex"
+ },
+ "FeatureWallBody": {
+ "25ec5356d6": "設定"
+ },
+ "FeatureWallModal": {
+ "33dca8bbbe": "Orca のワークフローごとの短いツアー。",
+ "3567e147c8": "Orcaを知る"
+ },
+ "FeatureWallPreview": {
+ "a666384798": "このワークフローでも"
+ },
+ "FeatureWallRail": {
+ "69ea857689": "完了",
+ "7593d15f94": "ワークフロー"
+ },
+ "FeatureWallSetupChecklist": {
+ "1a6a7d6c80": "設定",
+ "713cc529a5": "マイルストーン",
+ "b1f1981c5e": "タスクを参照",
+ "505f4c910c": "分割端子",
+ "0235b268b2": "まだ終わっていない",
+ "13294d3405": "完了"
+ },
+ "FeatureWallSetupWorkflowActions": {
+ "486c2f4d8d": "まず git プロジェクトを追加してから、そのリポジトリのセットアップ スクリプトを構成します。",
+ "00078a6134": "設定で表示",
+ "14327073cc": "保存",
+ "88469e926b": "セットアップスクリプト",
+ "5c5b65044e": "pnpmインストール",
+ "a7463915b6": "セットアップ スクリプトの保存に失敗しました",
+ "6299297dac": "セットアップスクリプトが保存されました",
+ "f0bbf7da77": "試してみてください",
+ "364430eb3d": "、またはペインを右クリックして分割を選択します。アクティブなペインを閉じる",
+ "29e64f111d": "またはダウン",
+ "971775f639": "右に分割",
+ "522cce9e33": "プロジェクトの追加"
+ },
+ "FeatureWallTourPanel": {
+ "af7d622f6f": "任意"
+ },
+ "KeepAwakeCard": {
+ "209713d3c7": "任意"
+ },
+ "ReviewNotesAnimatedVisual": {
+ "5dbd27c4c2": "Codex",
+ "09094f25e2": "Claude・コード",
+ "294aaff104": "メモの送信先",
+ "ea4e45b71b": "メモを追加",
+ "271ea0cbf3": "キャンセル",
+ "a7a89d8f94": "ライン",
+ "5cb213f967": "AIメモ",
+ "1eee3a397e": "src/server/移行.ts (差分)"
+ },
+ "ReviewPRViewAnimatedVisual": {
+ "7c2808ecff": "マージ前の切り捨て。",
+ "c2062da7ec": "標準エラー",
+ "6f4c2d7cb7": "対象ケースを追加",
+ "71828fba75": "失敗したコマンドを診断ペイロードに含めることはできますか?",
+ "fb1a856b6d": "開く",
+ "7a8b896e11": "コメント",
+ "ca36f7b27c": "通過",
+ "25f6838e43": "糸くず",
+ "2ef0b97954": "タイプチェック",
+ "8ed213397c": "ランニング",
+ "d340c052fb": "確認する",
+ "9a097cae12": "保留中 1 件",
+ "2f37142229": "スカッシュしてマージする",
+ "0aab7ab84a": "ローカル診断エラー追跡を追加する",
+ "dfe313e0c9": "開く",
+ "6e3f5223c5": "エクスプローラ",
+ "ab2901bce6": "チェック",
+ "d7f80060ca": "ソース管理",
+ "8e715588e4": "検索"
+ },
+ "ReviewShipAnimatedVisual": {
+ "4d99496b8c": "PRを作成する",
+ "62544e0852": "キャンセル",
+ "bcd5cae3c4": "PRの説明",
+ "3774b80eae": "説明",
+ "07da9245cc": "PRのタイトル",
+ "54a093c52d": "タイトル",
+ "3b9b96d6a6": "主要",
+ "ce7d5d3a18": "ベースブランチ",
+ "e4473d438f": "AIで生成",
+ "c30cd930ff": "PRの作成",
+ "ea0100dd15": "すべて見る",
+ "e725000cd7": "変更点",
+ "a079083a6c": "専念",
+ "7347fa5839": "メッセージ",
+ "d1a7f15876": "AIでコミットメッセージを生成",
+ "cd8a3a39d7": "3 コミット先"
+ },
+ "TasksAnimatedVisual": {
+ "efba6f77eb": "イシュー番号を読む",
+ "b68c92fbdc": "ワークスペースの開始",
+ "4331c4d0f8": "オープン",
+ "b13375617e": "ワークツリーピッカーが名前を切り捨てる",
+ "72f9e516a3": "押す",
+ "fe47c9c9e8": "ワークスペースの準備完了",
+ "61ffda7601": "ワークスペースの作成"
+ },
+ "WorkbenchAnimatedVisual": {
+ "633a91e358": "考え…",
+ "932c4b3a97": ">",
+ "ca2cfbf188": "スプリットターミナルダウン",
+ "e370fa8c2b": "分割端子右",
+ "b85eab49dd": "src/auth/session.ts",
+ "99f5224f1e": "編集",
+ "0d93c298a7": "src/認証をスローする",
+ "17cfdc3344": "グレップ",
+ "9923847785": "読む",
+ "c0eb94125e": "認証のエッジケースを確認する",
+ "431ca9842a": "Claudeコードセッションが開始されました",
+ "000106adfe": "claude",
+ "7d9f1d5f7d": "(0.8秒)",
+ "944199e54a": "› カート合計の更新",
+ "623881d72e": "チェックアウト仕様書",
+ "5c5cbd783f": "(1.2秒)",
+ "3261c6853b": "› サインインできます",
+ "defe550fe2": "ログイン.spec.ts",
+ "0b20782e0f": "4 人のワーカーを使用して 12 個のテストを実行する",
+ "4371cc9931": "pnpm プレイライト テスト",
+ "16877e038d": "分割する",
+ "a2b114dad0": "右に分割します ·",
+ "0bc9ad0cd1": "同じペイン:",
+ "fc84f17fe7": "Codexセッションが開始されました"
+ },
+ "agent": {
+ "capability": {
+ "setup": {
+ "status": {
+ "8eccfcb314": "インストール済み",
+ "21d4f79c93": "[CLI とスキルのインストール] をクリックして macOS アクセス設定を開きます",
+ "5c9293e51a": "アプリのアクセスを確認する",
+ "aae94eeb52": "「CLI とスキルのインストール」をクリックします",
+ "aa8e143a2f": "インストールを確認できませんでした",
+ "9b33e7fb13": "インストールを確認しています",
+ "4c8e1f92a7": "この Mac で Orca Desktop を開いてください",
+ "6d2b0a84e1": "このビルドでは利用できません"
+ }
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "usage": {
+ "tracking": {
+ "b94ec70eda": "追跡が設定されていません",
+ "cc39a87288": "接続済み · システムのデフォルト",
+ "00087eecb2": "接続されました · {{value0}}"
+ }
+ }
+ }
+ },
+ "review": {
+ "animated": {
+ "visual": {
+ "shared": {
+ "e7894927a2": "Codex",
+ "9deecb021c": "Claude"
+ },
+ "notes": {
+ "styles": {
+ "db6691aa0a": ".ravs-window { position: absolute; inset: 0; --ravs-soft-surface: color-mix(in srgb, var(--foreground) 2%, var(--card)); --ravs-soft-fill: color-mix(in srgb, var(--foreground) 6%, transparent); --ravs-panel-border: color-mix(in srgb, var(--foreground) 18%, var(--border)); --ravs-emphasis-border: color-mix(in srgb, var(--foreground) 44%, var(--border)); --ravs-floating-shadow: 0 14px 30px rgb(0 0 0 / 0.22), 0 2px 6px rgb(0 0 0 / 0.12); background: var(--card); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 1px 2px rgb(0 0 0 / 0.08); } .ravs-difftoolbar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-bottom: 1px solid var(--border); background: var(--ravs-soft-surface); font-size: 11px; color: var(--muted-foreground); } .ravs-diff-path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground); } .ravs-ai-chip { margin-left: auto; display: inline-flex; align-items: stretch; overflow: hidden; border-radius: 6px; border: 1px solid var(--border); background: var(--ravs-soft-surface); opacity: 0; transform: translateY(-2px); transition: opacity 320ms ease, transform 320ms ease; } .ravs-ai-chip.is-visible { opacity: 1; transform: none; } .ravs-ai-chip .ravs-count-btn, .ravs-ai-chip .ravs-send-btn { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; font-size: 11px; color: var(--muted-foreground); background: transparent; line-height: 1; } .ravs-ai-chip .ravs-count-btn { border-right: 1px solid var(--border); } .ravs-ai-chip .ravs-send-btn { padding: 3px 7px; position: relative; } .ravs-send-glow { position: absolute; inset: 0; background: rgba(34, 197, 94, 0.18); opacity: 0; transition: opacity 280ms ease; pointer-events: none; } .ravs-ai-chip .ravs-send-btn.is-flash .ravs-send-glow { opacity: 1; } .ravs-count-num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground); font-weight: 600; } .ravs-diffbody { flex: 1; min-height: 0; position: relative; background: var(--editor-surface, var(--card)); } .ravs-diffscroll { position: absolute; inset: 0; overflow: hidden; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; line-height: 1.55; color: var(--foreground); padding: 4px 0 8px; transition: opacity 240ms ease; } .ravs-diffscroll.is-hidden { opacity: 0; pointer-events: none; } .ravs-term { position: absolute; inset: 0; background: var(--editor-surface, var(--card)); color: var(--foreground); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 1.45; overflow: hidden; display: flex; flex-direction: column; opacity: 0; pointer-events: none; transition: opacity 240ms ease; z-index: 4; } .ravs-term.is-visible { opacity: 1; } .ravs-term-body { flex: 1; min-height: 0; padding: 10px 12px; overflow: hidden; display: flex; flex-direction: column; gap: 6px; } .ravs-term-line { white-space: pre-wrap; word-break: break-word; line-height: 1.45; } .ravs-term-muted { color: var(--muted-foreground); } .ravs-term-glyph { color: rgb(217 119 6); margin-right: 6px; } .ravs-term-check { color: rgb(16 185 129); font-weight: 700; margin-right: 6px; } .ravs-term-spinner { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 999px; border: 1.5px solid color-mix(in srgb, var(--foreground) 20%, transparent); border-top-color: var(--foreground); vertical-align: -1px; animation: ravs-term-spin 0.9s linear infinite; } @keyframes ravs-term-spin { to { transform: rotate(360deg) } } .ravs-hunk-header { display: grid; grid-template-columns: 36px 36px 16px minmax(0,1fr); align-items: center; padding: 1px 8px 1px 0; background: rgba(99, 102, 241, 0.06); color: var(--muted-foreground); font-size: 10.5px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); } .ravs-hunk-header .ravs-text { grid-column: 4 / -1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: rgb(99 102 241); font-size: 10.5px; } .ravs-diff-line { display: grid; grid-template-columns: 36px 36px 16px minmax(0,1fr); align-items: stretch; position: relative; } .ravs-ln { text-align: right; padding: 0 6px 0 0; color: var(--muted-foreground); font-size: 10.5px; user-select: none; opacity: 0.85; } .ravs-marker { text-align: center; color: var(--muted-foreground); font-weight: 700; opacity: 0.7; } .ravs-text-cell { padding-right: 8px; white-space: pre; overflow: hidden; } .ravs-tok-kw { color: #a855f7; } .ravs-tok-id { color: #2563eb; } .ravs-tok-str { color: #16a34a; } .ravs-diff-line.is-add { background: color-mix(in srgb, var(--git-decoration-added) 14%, transparent); } .ravs-diff-line.is-add .ravs-marker { color: color-mix(in srgb, var(--git-decoration-added) 72%, transparent); opacity: 1; } .ravs-diff-line.is-rem { background: color-mix(in srgb, var(--git-decoration-deleted) 14%, transparent); } .ravs-diff-line.is-rem .ravs-marker { color: color-mix(in srgb, var(--git-decoration-deleted) 72%, transparent); opacity: 1; } .ravs-add-note-btn { position: absolute; left: 4px; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 1px solid color-mix(in srgb, currentColor 22%, var(--border)); border-radius: 4px; background: var(--ravs-soft-fill); color: var(--foreground); z-index: 5; opacity: 0; box-shadow: 0 1px 2px rgb(0 0 0 / 0.14); pointer-events: none; transition: opacity 160ms ease; } .ravs-add-note-btn.is-visible { opacity: 1; } .ravs-note-row { padding: 4px 8px 4px 0; max-height: 0; overflow: hidden; opacity: 0; transition: max-height 360ms cubic-bezier(.4,0,.2,1), opacity 280ms ease 60ms, padding 360ms cubic-bezier(.4,0,.2,1); } .ravs-note-row.is-visible { max-height: 90px; opacity: 1; } .ravs-note-card { margin: 0 12px; position: relative; border: 1px solid var(--ravs-panel-border); border-left: 3px solid var(--ravs-emphasis-border); border-radius: 6px; background-color: var(--card); padding: 5px 8px 5px 10px; box-shadow: 0 1px 2px rgb(0 0 0 / 0.16); } .ravs-note-meta { font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-foreground); } .ravs-note-body { font-size: 11.5px; color: var(--foreground); line-height: 1.35; margin-top: 2px; } .ravs-popover { position: absolute; left: 12px; right: 12px; max-width: none; z-index: 20; padding: 8px 10px; border: 1px solid var(--ravs-panel-border); border-left: 3px solid var(--ravs-emphasis-border); border-radius: 6px; background-color: var(--card); color: var(--foreground); box-shadow: var(--ravs-floating-shadow); display: flex; flex-direction: column; gap: 6px; opacity: 0; transform: translateY(-4px) scale(0.985); pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; } .ravs-popover.is-visible { opacity: 1; transform: none; pointer-events: auto; } .ravs-pop-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-foreground); } .ravs-pop-input { min-height: 38px; max-height: 80px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--editor-surface, var(--card)); font-size: 12px; line-height: 1.4; color: var(--foreground); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pop-footer { display: flex; justify-content: flex-end; gap: 6px; } .ravs-pop-btn { font-size: 11px; font-weight: 500; padding: 4px 9px; border-radius: 5px; line-height: 1; border: 1px solid transparent; display: inline-flex; align-items: center; gap: 5px; } .ravs-pop-btn.is-cancel { color: var(--muted-foreground); background: transparent; } .ravs-pop-btn.is-add { color: var(--primary-foreground); background: var(--primary); } .ravs-send-menu { position: absolute; z-index: 30; right: 8px; top: 6px; min-width: 200px; background: var(--popover); color: var(--popover-foreground); border: 1px solid var(--border); border-radius: 8px; padding: 4px; box-shadow: var(--ravs-floating-shadow); opacity: 0; transform: translateY(-4px) scale(0.985); pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; } .ravs-send-menu.is-visible { opacity: 1; transform: none; pointer-events: auto; } .ravs-menu-section { padding: 4px 8px 2px; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-foreground); } .ravs-menu-row { display: grid; grid-template-columns: 16px minmax(0,1fr); align-items: center; gap: 8px; padding: 6px 8px; border-radius: 5px; font-size: 12px; color: var(--popover-foreground); } .ravs-menu-row.is-hot { background: var(--accent); box-shadow: inset 0 0 0 1px var(--border); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid color-mix(in srgb, var(--foreground) 52%, transparent); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }"
+ }
+ },
+ "pr": {
+ "view": {
+ "styles": {
+ "fc9a23c83d": ".ravpr-stage { position: absolute; inset: 0; overflow: hidden; } .ravpr-stack { position: absolute; inset: 0; display: flex; justify-content: flex-end; padding: 4px 34px 4px 2px; overflow: hidden; } .ravpr-sidebar, .ravpr-card { position: absolute; top: 4px; right: 2px; width: 464px; height: calc(100% - 8px); background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; color: var(--foreground, #18181b); overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } .ravpr-sidebar { opacity: 0; transition: opacity 220ms ease; } .ravpr-sidebar.is-visible { opacity: 1; } .ravpr-sidebar.is-hiding { opacity: 0; } .ravpr-card { display: flex; flex-direction: column; min-width: 0; opacity: 0; transition: opacity 260ms ease; } .ravpr-card.is-visible { opacity: 1; } .ravpr-tabs { position: relative; display: flex; align-items: center; gap: 14px; height: 36px; padding: 0 14px; background: rgba(24,24,27,0.015); color: var(--muted-foreground, #71717a); } .ravpr-tab { position: relative; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted-foreground, #71717a); } .ravpr-tab.is-active, .ravpr-tab.is-hovered { color: var(--foreground, #18181b); } .ravpr-tab.is-active::after { content: ''; position: absolute; left: -5px; right: -5px; bottom: -10px; height: 1px; background: var(--foreground, #18181b); } .ravpr-tooltip { position: absolute; top: 34px; left: 106px; z-index: 6; padding: 7px 11px; border-radius: 8px; background: var(--card, #fff); color: var(--foreground, #18181b); font-size: 12px; line-height: 1; box-shadow: 0 8px 22px rgba(0,0,0,0.22); opacity: 0; transform: translateY(-3px); pointer-events: none; transition: opacity 160ms ease, transform 160ms ease; } .ravpr-tooltip.is-visible { opacity: 1; transform: translateY(0); } .ravpr-explorer { padding: 10px 12px 12px; } .ravpr-heading { color: var(--muted-foreground, #71717a); font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; } .ravpr-file-list { margin-top: 8px; display: flex; flex-direction: column; gap: 2px; } .ravpr-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 22px; align-items: center; gap: 8px; min-height: 28px; padding: 4px 6px; border-radius: 6px; } .ravpr-file.is-active { background: rgba(24,24,27,0.06); box-shadow: inset 0 0 0 1px rgba(24,24,27,0.06); } .ravpr-file-icon { width: 12px; height: 12px; border-radius: 3px; background: rgba(24,24,27,0.14); } .ravpr-file-name { height: 8px; border-radius: 999px; background: rgba(24,24,27,0.14); } .ravpr-file-status { width: 14px; height: 8px; border-radius: 999px; background: rgba(24,24,27,0.12); } .ravpr-body { padding: 10px 12px 18px; display: flex; flex-direction: column; gap: 5px; min-height: 0; } .ravpr-number-row { display: flex; align-items: center; gap: 7px; } .ravpr-number { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; font-weight: 700; } .ravpr-open { display: inline-flex; align-items: center; justify-content: center; height: 18px; padding: 0 7px; border-radius: 5px; background: rgba(16,185,129,0.10); border: 1px solid rgba(16,185,129,0.28); color: rgb(4 120 87); font-size: 9px; font-weight: 700; line-height: 1; } .ravpr-title { font-size: 12px; font-weight: 600; line-height: 1.35; color: var(--foreground, #18181b); margin-bottom: 2px; } .ravpr-merge { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; min-height: 30px; flex: 0 0 30px; border-radius: 7px; background: rgb(22 163 74); color: #fff; font-size: 11.5px; font-weight: 700; margin-bottom: 2px; box-shadow: 0 1px 2px rgba(22,163,74,0.18); transition: box-shadow 220ms ease, filter 220ms ease; } .ravpr-merge.is-ready { box-shadow: 0 0 0 3px rgba(34,197,94,0.22), 0 1px 2px rgba(22,163,74,0.18); } .ravpr-section-row, .ravpr-check-row { display: grid; grid-template-columns: 18px minmax(0,1fr) auto; align-items: center; gap: 7px; padding: 5px 0; font-size: 11.5px; color: var(--foreground, #18181b); } .ravpr-check-row { padding: 5px 7px; font-size: 10.5px; } .ravpr-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ravpr-meta, .ravpr-check-state { color: var(--muted-foreground, #71717a); font-size: 10.5px; } .ravpr-check-state { font-size: 10px; } .ravpr-ring { display: inline-block; width: 14px; height: 14px; border-radius: 999px; border: 2px solid rgba(245,158,11,0.35); border-top-color: rgb(245 158 11); animation: ravpr-spin 1.1s linear infinite; } .ravpr-check { width: 15px; height: 15px; border-radius: 999px; display: none; align-items: center; justify-content: center; background: rgba(34,197,94,0.14); color: rgb(22 163 74); } .ravpr-section-row.is-done .ravpr-ring, .ravpr-check-row.is-done .ravpr-ring { display: none; } .ravpr-section-row.is-done .ravpr-check, .ravpr-check-row.is-done .ravpr-check { display: inline-flex; } .ravpr-reveal { display: flex; flex-direction: column; gap: 3px; opacity: 0; transform: translateY(4px); transition: opacity 260ms ease, transform 260ms ease; pointer-events: none; } .ravpr-reveal.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; } .ravpr-check-list, .ravpr-comment-list { display: flex; flex-direction: column; gap: 4px; min-height: 0; } .ravpr-comment-card { border: 1px solid var(--border); border-radius: 8px; background: var(--card, #fff); overflow: hidden; opacity: 0; transform: translateY(4px); transition: opacity 260ms ease, transform 260ms ease; } .ravpr-comment-card.is-visible { opacity: 1; transform: translateY(0); } .ravpr-comment-head { display: grid; grid-template-columns: 18px minmax(0,1fr) auto; align-items: center; gap: 7px; padding: 5px 7px; background: rgba(24,24,27,0.015); } .ravpr-avatar { width: 16px; height: 16px; border-radius: 999px; background: rgba(24,24,27,0.16); } .ravpr-author { width: 78px; height: 8px; border-radius: 999px; background: rgba(24,24,27,0.18); } .ravpr-comment-path { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 9.5px; color: var(--muted-foreground, #71717a); } .ravpr-comment-body { padding: 5px 7px 6px; font-size: 11px; line-height: 1.32; color: var(--foreground, #18181b); } .ravpr-comment-body code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; padding: 1px 4px; border-radius: 4px; background: rgba(24,24,27,0.06); } .ravpr-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravpr-cursor.is-visible { opacity: 1; } .ravpr-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravpr-cursor.is-clicking .ravpr-ripple { animation: ravpr-ripple 460ms ease-out forwards; } @keyframes ravpr-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } @keyframes ravpr-spin { to { transform: rotate(360deg); } }"
+ }
+ }
+ },
+ "ship": {
+ "styles": {
+ "90cdcd2ecc": ".ravs-ship-root { position: absolute; inset: 0; } .ravs-ship-stack { position: absolute; inset: 0; display: grid; grid-template-columns: 232px minmax(0,1fr); gap: 14px; padding: 4px 2px; /* Why: cards size to their content rather than stretch to the parent's full height, so the two cards don't show empty space below their content. */ align-items: start; } /* Source Control mini-sidebar — ahead-count header, commit textarea + split Commit button, then a CHANGES section with file rows. The file rows are the surface the \"reading\" pulse animates over. */ .ravs-sc-card { display: flex; flex-direction: column; background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } /* Both card headers share the same fixed height so the SC card and PR dialog align across the top edge regardless of header content. */ .ravs-sc-header, .ravs-pr-head { height: 36px; box-sizing: border-box; } .ravs-sc-header { display: flex; align-items: center; justify-content: space-between; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-sc-ahead { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } .ravs-sc-ahead svg { color: var(--muted-foreground, #71717a); } .ravs-sc-commit-area { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; } .ravs-sc-textarea { position: relative; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); padding: 6px 26px 6px 8px; min-height: 56px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-sc-textarea .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-sc-sparkle { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; transition: color 160ms ease, background 160ms ease; } .ravs-sc-sparkle.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-sc-split { display: flex; align-items: stretch; } /* Why: Commit + Create PR are surrounding chrome — the violet AI affordances are the focal points. Render them as quiet secondary buttons so they don't compete with the sparkle/scan signals. */ .ravs-sc-split .ravs-primary { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 5px 10px; background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); font-size: 11px; font-weight: 500; border-radius: 6px 0 0 6px; border: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } .ravs-sc-split .ravs-chev { display: inline-flex; align-items: center; justify-content: center; width: 22px; background: var(--secondary, #f5f5f5); color: var(--muted-foreground, #71717a); border-radius: 0 6px 6px 0; border: 1px solid var(--border); border-left: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } /* Why: when AI has filled the commit message, tint the Commit button green to signal \"ready to commit\". Uses the same success-green family as the PR flash so the two beats rhyme. Mix is intentionally strong (~28%) — at 14% it disappeared next to the violet sparkle and PR flash, so users only saw the PR change color. */ .ravs-sc-split.is-ready .ravs-primary, .ravs-sc-split.is-ready .ravs-chev { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); transition: background 220ms ease, border-color 220ms ease, color 220ms ease; } .ravs-sc-split.is-ready .ravs-chev { border-left-color: rgba(34, 197, 94, 0.55); } .ravs-sc-changes-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-sc-changes-count { color: var(--foreground, #18181b); font-weight: 600; margin-left: 2px; } .ravs-sc-view-all { font-size: 10px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted-foreground, #71717a); } .ravs-sc-files { display: flex; flex-direction: column; padding: 2px 6px 8px; flex: 1; min-height: 0; overflow: hidden; } .ravs-sc-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 12px; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 4px; font-size: 11px; line-height: 1.35; color: var(--foreground, #18181b); position: relative; transition: background 220ms ease; } .ravs-sc-ficon { color: rgb(180 83 9); display: inline-flex; } .ravs-sc-fname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ravs-sc-fmark { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; text-align: right; color: rgb(180 83 9); } .ravs-sc-file.is-reading { background: color-mix(in srgb, rgb(139 92 246) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, rgb(139 92 246) 28%, transparent); } /* PR dialog — matches the .ravs-sc-card chrome (same border, radius, elevation) so the two cards read as one design language. */ .ravs-pr-dialog { background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 1px 2px rgba(24,24,27,0.04); display: flex; flex-direction: column; min-width: 0; overflow: hidden; } .ravs-pr-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-pr-title-text { font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } /* Icon-only AI-assist chip — mirrors .ravs-sc-sparkle so the affordance reads identically across both cards. */ .ravs-pr-gen-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; border: 0; cursor: pointer; transition: color 160ms ease, background 160ms ease; } .ravs-pr-gen-btn:hover { background: rgba(24,24,27,0.06); color: var(--foreground, #18181b); } .ravs-pr-gen-btn.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-pr-body { display: flex; flex-direction: column; gap: 8px; padding: 10px; } .ravs-pr-field { display: flex; flex-direction: column; gap: 4px; } .ravs-pr-field-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-pr-base { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 6px; font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground, #18181b); background: var(--editor-surface, var(--card)); align-self: flex-start; } .ravs-pr-base svg { color: var(--muted-foreground, #71717a); } .ravs-pr-input { position: relative; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); min-height: 28px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pr-input.is-body { min-height: 50px; font-size: 11px; line-height: 1.4; } .ravs-pr-input .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-pr-footer { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 2px; } .ravs-pr-btn { font-size: 11px; font-weight: 500; padding: 5px 10px; border-radius: 6px; line-height: 1; border: 1px solid transparent; outline: none; } .ravs-pr-btn:focus, .ravs-pr-btn:focus-visible { outline: none; } /* Cancel reads as a quiet ghost button so it doesn't compete with the affirmative Create PR action. */ .ravs-pr-btn.is-outline { background: transparent; color: var(--muted-foreground, #71717a); border-color: transparent; } .ravs-pr-btn.is-outline:hover { background: rgba(24,24,27,0.05); color: var(--foreground, #18181b); } /* Quiet secondary fill — see the .ravs-sc-split note above. The flash ring still uses success-green so the \"PR created\" beat reads. The Create-PR button is slightly larger than Cancel so the affirmative action remains the bigger target. */ .ravs-pr-btn.is-solid { background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); border-color: var(--border); font-size: 12px; padding: 7px 14px; transition: background 220ms ease, border-color 220ms ease, color 220ms ease, box-shadow 220ms ease; } .ravs-pr-btn.is-solid.is-ready { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); } .ravs-pr-btn.is-solid.is-flash { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.30); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }"
+ }
+ }
+ }
+ },
+ "notes": {
+ "diff": {
+ "rows": {
+ "f621c734f8": "注・行"
+ }
+ }
+ }
+ },
+ "agents": {
+ "orchestration": {
+ "OrchestrationPage": {
+ "30b509a467": "子供2人",
+ "862605d066": "2 つの子ワークスペース"
+ },
+ "StatusesPage": {
+ "2f549fc0ba": "src/auth/session.test.ts",
+ "139e3d7458": "更新されました",
+ "7b26349cb2": "pnpm 移行最新",
+ "78f0318ac1": "走りたい",
+ "79971d1539": "認証フローを再設計する"
+ },
+ "UsageAccountsCard": {
+ "6986b36708": "表面レート制限とインラインのスワップ口座。",
+ "d90d2e1f6d": "セッションと毎週の使用状況を追跡します。",
+ "8919321417": "Codexのサインインに失敗しました。",
+ "c7b90c140b": "Codexアカウントが追加されました。",
+ "4e71d72912": "Claudeのサインインに失敗しました。",
+ "9ddeb558f9": "Claudeアカウントが追加されました。",
+ "29d0653961": "サインイン",
+ "945865332e": "サインインする"
+ },
+ "UsagePage": {
+ "64265cb295": "71% 5時間",
+ "be5a165875": "に切り替えます",
+ "277a9c65a9": "Codexアカウント",
+ "4dce5ca3aa": "4d 3h でリセット",
+ "05ce4ecdd3": "62%残っています",
+ "0470aaed99": "毎週",
+ "f421abf962": "セッション",
+ "5e45fb1238": "1分前に更新されました",
+ "6a4b1d3c38": "Codex"
+ },
+ "orchestration": {
+ "cards": {
+ "da6f1f97c9": "働く"
+ }
+ }
+ }
+ },
+ "FeatureTourWorkspaceCard": {
+ "a23ed9da7f": "codex",
+ "2f33dc932b": "claude",
+ "9220794f6a": "働く"
+ },
+ "ReviewAnimatedVisual": {
+ "8df4d52b68": "プレビュー",
+ "8ab622e4d6": "メモ"
+ }
+ },
+ "tips": {
+ "CliFeatureTipVisual": {
+ "badb4fc342": ">",
+ "22e62f3bab": "Claudeコードセッションが開始されました"
+ },
+ "CliSkillSetupTerminal": {
+ "1953e90447": "Enter を押して、エージェントに Orca CLI オーケストレーション スキルをインストールします。",
+ "43b60ec5c3": "Orca CLI およびオーケストレーション スキルのインストール ターミナル",
+ "84e9576dac": "スキルセットアップ",
+ "5c3aee22c0": "コピーコマンド",
+ "5eca672aac": "スキルインストールコマンドのコピー",
+ "6ff813fc1d": "スキルコマンドのコピーに失敗しました。",
+ "b8ad063571": "スキルインストールコマンドをコピーしました。"
+ },
+ "CmdJPaletteTipDialog": {
+ "c0bb9f869b": "設定→ショートカット",
+ "8241897205": "いつでもショートカットを再バインドします"
+ },
+ "FeatureTipActions": {
+ "eb04abece8": "たぶん後で"
+ },
+ "FeatureTipsModal": {
+ "c169298e4d": "完了",
+ "3c6c478462": "X が終了しました。レビュー タスクを送信します。」",
+ "298301b7a0": "ワークツリー",
+ "864e2db28f": "「エージェントが入ったとき、",
+ "7fc6f02099": "それぞれの PR を作成します。」",
+ "27c567a89c": "ワークツリー",
+ "55846c7f95": "「この PR を 2 つに分割します",
+ "4795ac2d4a": "尋ねてみてください:",
+ "53905bd076": "開発プレビュー: スキル設定ターミナルを開きます。",
+ "1da82af45b": "Orca CLI には注意が必要です",
+ "ce13a742d0": "orcaをPATHに登録しました。",
+ "d1a86c7eb5": "[設定] を開いて CLI セットアップを完了します。"
+ },
+ "CmdJPaletteFeatureTipVisual": {
+ "ab94e16d44": "ワークツリー「{{value0}}」を作成する",
+ "d20ccf1e61": "完了",
+ "379d776971": "タイピング",
+ "0418f9becc": "開く"
+ }
+ }
+ },
+ "error": {
+ "boundaries": {
+ "RecoverableRenderErrorBoundary": {
+ "55001880db": "再試行",
+ "34a189ae0f": "アプリの残りの部分はまだ実行されています。このサーフェスを再試行するか、切り替えて戻ってきてください。",
+ "ab855c11f4": "Orca のこの部分でエラーが発生しました。"
+ }
+ }
+ },
+ "emulator": {
+ "pane": {
+ "EmulatorPane": {
+ "59b08fa031": "エミュレータが接続されていません"
+ },
+ "emulator": {
+ "device": {
+ "frame": {
+ "9406c15775": "エミュレータ画面",
+ "8f25ffaf8a": "エミュレータ画面、キーボードがキャプチャされました。 Esc キーを押して解放します。",
+ "0022420df0": "スマートフォン"
+ }
+ },
+ "pane": {
+ "toolbar": {
+ "06e10d7356": "エミュレータをシャットダウンする",
+ "e7a0d1897e": "家",
+ "6bd8dff42a": "回転",
+ "3d836b879c": "エミュレータの選択",
+ "81b3571a07": "接続",
+ "868c0f2938": "働く…"
+ }
+ },
+ "screen": {
+ "stream": {
+ "content": {
+ "8b1a0d8694": "エミュレータのプレビュー",
+ "36841af608": "ストリームが切断されました",
+ "5f818f12ab": "エミュレータを接続中…",
+ "5ee64cd44e": "エミュレータ画面"
+ }
+ }
+ },
+ "unavailable": {
+ "pane": {
+ "f630b9ca9f": "モバイル エミュレーターには、Xcode と iOS シミュレーター ランタイムを備えた Mac が必要です。 Linux または Windows では、物理デバイスまたはリモート Mac ビルド ホストを使用します。",
+ "b2c268a0b9": "モバイルエミュレータはmacOSのみです"
+ }
+ }
+ },
+ "use": {
+ "emulator": {
+ "frame": {
+ "stream": {
+ "f1c0179002": "ストリームはフレームを生成していません。"
+ }
+ }
+ }
+ }
+ }
+ },
+ "editor": {
+ "ChangesModeView": {
+ "ef25ae2d09": "コミットされていない変更はありません。",
+ "052c184f24": "このファイルではテキストの差分を使用できません。",
+ "7dffb0f563": "バイナリファイル",
+ "54e0035b15": "差分を読み込み中..."
+ },
+ "CodeBlockCopyButton": {
+ "28921f5bf9": "コピーされました",
+ "1f9f4def45": "コードをコピーする"
+ },
+ "CombinedDiffFileTree": {
+ "f984289373": "現在のフィルターに一致するファイルはありません。",
+ "eafe1aeb53": "フィルターをリセットする",
+ "be119cb9d1": "閲覧したファイル",
+ "c00020f081": "ファイル拡張子",
+ "cd0e0ed79e": "差分ファイルのフィルタリング",
+ "4cc7b83ffe": "ファイルをフィルタリング...",
+ "21783df79f": "ファイルツリーを折りたたむ",
+ "481e63ca52": "ファイル",
+ "d5ac717d65": "コミットされていない"
+ },
+ "CombinedDiffViewer": {
+ "35cc27aeb2": "ソース管理内",
+ "e3b9a6ce02": "もっと",
+ "1da745c551": "送信済み",
+ "84898c548d": "クリア",
+ "88b70d0ef5": "コピー",
+ "bb84b4c374": "AIメモ",
+ "948a5fd6c8": "クリアノート",
+ "0f806a2ab1": "キャンセル",
+ "80a286d8f5": "このワークツリーから?",
+ "7e7ca60816": "変更されたファイル",
+ "b6c3b84476": "ファイルツリーを表示",
+ "39f8007549": "競合をレビューする",
+ "39e73e7181": "はこの差分ビューから除外されました。",
+ "689b99f8ad": "未解決の紛争",
+ "820ec01f24": "競合したファイルは個別にレビューされます",
+ "fd8892b120": "表示に変更はありません",
+ "eb5f40e49c": "通常の双方向 diff パイプラインは競合に対して安全ではないため、この diff ビューでは未解決の競合が除外されます。",
+ "45cf23b418": "メモを消去できませんでした。",
+ "0fb870a0fe": "メモ",
+ "8ab3248fd8": "注記",
+ "ec5053c7f5": "サイドバイサイド",
+ "f786fd54e1": "インライン",
+ "ea08dae15b": "すべて折りたたむ",
+ "19c45cfdc0": "すべて展開",
+ "982d14bfa5": "コミットされていない差分を開く",
+ "3d909843bb": "ブランチの差分を開く",
+ "8368d256ec": "結合分岐",
+ "8f68ad9ca9": "{{value0}} AI {{value1}} を表示",
+ "724a13568d": "{{value0}} に",
+ "6094135eec": "vs {{value0}}"
+ },
+ "ConflictComponents": {
+ "f338288514": "競合するコンテンツを読み込んでいます...",
+ "90d576adb2": "更新",
+ "a1ce36f77d": "スナップショットがキャプチャされた場所",
+ "4be41eaafc": "未解決の紛争",
+ "c8ca989aea": "ファイルツリーを表示",
+ "58ad5ad431": "閉じる",
+ "28e7db4a90": "ソース管理",
+ "31931dec46": "このレビュー スナップショットには、未解決のライブ競合はなくなりました。",
+ "992145ff5a": "すべての競合が解決されました",
+ "d5edd81755": "から改名",
+ "6e459867ad": "セッションローカルの継続状態。 Git は、このファイルがマージされていないと報告しなくなりました。",
+ "9c2901ef8a": "次の紛争",
+ "41d9af2e7a": "以前の紛争",
+ "55d61a0ccd": "対立 ・",
+ "da539359b6": "この競合に対して編集できる作業ツリー ファイルはありません。"
+ },
+ "ConflictReviewFileTree": {
+ "3449521a8c": "このスナップショットには競合はありません。",
+ "a54551c5a6": "ファイルツリーを折りたたむ",
+ "99496bab6e": "ファイル",
+ "496e28a932": "消えた",
+ "8528a5eaf5": "解決済み",
+ "69d4e210bb": "未解決"
+ },
+ "CsvViewer": {
+ "eedd0d37a7": "列",
+ "ac31d2cd60": "行",
+ "a233d55b77": "空のファイル"
+ },
+ "DiffNotesSendMenu": {
+ "f1aa04b5cf": "このファイル",
+ "8b87612461": "すべての未送信のメモ"
+ },
+ "DiffSectionBody": {
+ "35d6afb5be": "バイナリファイルが変更されました",
+ "cef4cf0ff5": "再試行",
+ "f5cf81cec2": "差分を読み込み中...",
+ "72f71f52eb": "このファイルではテキストの差分を使用できません。",
+ "7ce8436458": "ブランチ比較では、このファイルのテキスト差分は使用できません。",
+ "bdbf02d5df": "バイナリ"
+ },
+ "DiffSectionHeader": {
+ "8915726e93": "パスをコピーする"
+ },
+ "EditorContent": {
+ "56dba34e1a": "(ソースモードで編集)",
+ "e4b074749d": "フロントマター",
+ "9640d1d3db": "この差分の変更されたバージョンをプレビューします。ソースモードに切り替えて変更を検査します。",
+ "78541e254e": "バイナリファイルが変更されました",
+ "c88c73a0d3": "差分を読み込み中...",
+ "b9de81ba52": "バイナリ ファイル - 表示できません",
+ "b2735221f5": "読み込み中...",
+ "8608ce4cb1": "Markdown プレビューはバイナリ ファイルでは利用できません。",
+ "37a0e81fa6": "プレビューを読み込んでいます...",
+ "8b1a605bae": "このファイルは競合状態にありますが、編集できる作業ツリー ファイルがありません。",
+ "2a512bb46a": "再試行",
+ "39f018b052": "ファイルをロードできません",
+ "8a0898ae4c": "このファイルではテキストの差分を使用できません。",
+ "3c6e71df22": "ブランチ比較では、このファイルのテキスト差分は使用できません。",
+ "d07e4b8553": "ブランチ",
+ "d16e037f40": "リッチ"
+ },
+ "EditorPanelHeader": {
+ "fb8331694e": "プレビューを横に開く",
+ "4157f3cbf3": "マークダウンプレビューを開く",
+ "269ce4842b": "相対パスをコピー",
+ "7c08a1f990": "パスのコピー",
+ "84cdc0794b": "名前を変更する",
+ "1bb1e226ec": "ファイル {{value0}} の名前を変更します",
+ "5447c4f68f": "目次",
+ "146cb5473c": "目次はリッチ モードまたはプレビュー モードで使用できます",
+ "e836faacfa": "並列差分に切り替える",
+ "94756f08ba": "インライン差分に切り替える",
+ "c98ce191da": "この差分には開くための変更側ファイルがありません",
+ "9b80bbe1de": "ファイルタブを開く",
+ "f0fd4174b5": "ファイル タブを開いてリッチ マークダウン編集を使用する",
+ "a10d9b8337": "ファイルを開く"
+ },
+ "EditorPanelMarkdownActionsMenu": {
+ "3e0ce48c24": "PDFとしてエクスポート",
+ "561251019a": "その他の操作",
+ "8c8b7f5ff5": "前付を表示",
+ "10c39d58c1": "前付を隠す"
+ },
+ "EditorPanelShell": {
+ "e2c4dec350": "エディターを読み込み中..."
+ },
+ "EditorViewToggle": {
+ "b3410cd5e0": "ノート",
+ "e408aa9cd5": "テーブル",
+ "167f45888c": "コミットされていない変更",
+ "4837f3f578": "変更点",
+ "ac3bb87913": "編集",
+ "0d193dc03c": "プレビュー",
+ "aff15f94f5": "リッチエディター",
+ "4d6ccb7ba6": "ソース"
+ },
+ "ImageDiffViewer": {
+ "a651be62b0": "修正済み",
+ "57aac3979a": "オリジナル",
+ "fb0ae4f3c0": "プレビューなし"
+ },
+ "ImageViewer": {
+ "3c9217f5a6": "ズームイン",
+ "6c89c73d9f": "ズームをリセットする",
+ "be27304574": "ズームアウト",
+ "77bfc9b35a": "ポップアップで画像を開く",
+ "3ef9551ba2": "プレビューを読み込んでいます...",
+ "d9d2944855": "ファイルプレビューのロードに失敗しました"
+ },
+ "ImageViewerPopup": {
+ "0ef78475e7": "Escを押して閉じます",
+ "535f4e2b56": "閉じる",
+ "9e27b2ecaf": "フルサイズの画像プレビュー"
+ },
+ "IpynbViewer": {
+ "859bf9fc21": "セルを実行する",
+ "7f0d7077c6": "キャンセル",
+ "10ed04a685": "ノートブック セルは、ノートブック フォルダーからこのマシン上のローカル Python を実行します。信頼できるファイルのセルのみを実行してください。",
+ "9e06ae5d36": "ノートブックのコードを実行しますか?",
+ "d6f37a640b": "空のノート",
+ "8c3b21369a": "nbフォーマット",
+ "329764e9fc": "ベータ",
+ "15ec40a735": "ノートブックの保存",
+ "07e7d96612": "細胞",
+ "c1601b23b2": "ノートブックをレンダリングできません",
+ "66a3f7d330": "ノートブックの HTML 出力",
+ "781abd6926": "セルの削除",
+ "b42f6a9547": "マークダウンセルを下に挿入",
+ "ffc1ac2699": "上にマークダウンセルを挿入",
+ "b4208cad7e": "コードセルを下に挿入",
+ "53b839b8a0": "上にコードセルを挿入",
+ "27e064e2db": "セルを下に移動",
+ "fd8ac707bc": "セルを上に移動",
+ "3e4cbf15ea": "生",
+ "1833dbbc43": "マークダウン",
+ "7005960d73": "コード",
+ "59b6cd874b": "コード",
+ "ba149053d5": "値下げ"
+ },
+ "MarkdownPreview": {
+ "e4683f70c4": "キャンセル",
+ "d737791433": "AI に関するメモを追加",
+ "b1bfc04034": "選択したテキスト",
+ "f37b98999e": "このメモ",
+ "2b2b31382c": "フロントマター",
+ "bb629de58a": "エージェント用のメモをコピーする",
+ "322afab6ff": "レビューノート",
+ "0f9969a159": "最初のレビューノートにジャンプ",
+ "12052c639c": "検索を閉じる",
+ "b42c41bd0d": "次の試合",
+ "1febd97f5c": "前回の試合",
+ "ec77985138": "マークダウン プレビューで検索",
+ "517aea303b": "プレビューで検索",
+ "f961e94057": "エージェント用のメモをコピーする",
+ "94b520a96a": "コピーされたメモ",
+ "13f94d760c": "メモを追加",
+ "ddf087d12e": "すべての未送信のメモ",
+ "d652c87c91": "保存中…",
+ "c5dc92cfe3": "結果はありません",
+ "6c043947ae": "ファイルが見つかりません: {{value0}}",
+ "759463a221": "ディレクトリを開けません: {{value0}}"
+ },
+ "MarkdownTableOfContentsPanel": {
+ "de3928b6e4": "見出しなし",
+ "bbe8369097": "目次を閉じる",
+ "4680a4b808": "H{{value0}} に折りたたむ",
+ "a5daadd68b": "すべて展開",
+ "111e66b85d": "見出しレベル {{value0}} に折りたたむ",
+ "f3de856175": "すべての見出しレベルを展開します",
+ "0dc7b2f05a": "レベルごとに折りたたむ",
+ "06357eea60": "目次",
+ "27d0a9c49a": "目次",
+ "65b036a6c8": "{{value0}} を展開します",
+ "97ad46f11f": "{{value0}} を折りたたむ"
+ },
+ "MarkdownTemplatePicker": {
+ "22cd94426f": "無題.md",
+ "6e2e6c04ad": "空白のマークダウン",
+ "df667919ca": "一致するテンプレートがありません。",
+ "22fd4890ad": "テンプレートを検索...",
+ "7b458e0b7f": "マークダウン テンプレートを選択します。",
+ "1829437fce": "新規マークダウン"
+ },
+ "MermaidBlock": {
+ "dcc132e691": "図のエラー:"
+ },
+ "MonacoEditor": {
+ "68cb83f4a7": "選択したテキストにメモを追加する",
+ "fd68ae03b3": "ファイル内を検索"
+ },
+ "MonacoGutterContextMenu": {
+ "7b57b1b468": "リモート URL をコピー",
+ "2e0b1cdc05": "リリースをコピーします。線へのパス",
+ "4eaa991bde": "パスを線にコピー"
+ },
+ "NotesSendMenu": {
+ "44dc5e60a6": "メモを送信する",
+ "433928cd9f": "{{value0}} をエージェントに送信します"
+ },
+ "PdfFind": {
+ "cd65b1d6b0": "閉じる",
+ "eeba2547a1": "次の試合",
+ "30de726ad0": "前回の試合",
+ "2fc3ba0ea8": "ページ内で検索...",
+ "d080ab37d6": "一致しません",
+ "db56fcd6d2": "{{value0}}/{{value1}}"
+ },
+ "PdfViewer": {
+ "3e98d500d2": "PDF プレビュー",
+ "069ff59932": "PDF で検索 ({{value0}})",
+ "2b6eb1ccd6": "ズームイン",
+ "c0119616d6": "幅に合わせる",
+ "fa5d096b00": "ズームアウト"
+ },
+ "ReviewNotesSendMenuContent": {
+ "a49800405b": "新規エージェント",
+ "e84705f223": "アクティブなエージェントセッション",
+ "03378aea75": "メモの送信先",
+ "f5096c6e4e": "アクティブなエージェントにメモを送信できませんでした。",
+ "bb9c69a0c9": "メモはアクティブなエージェントに送信されます。",
+ "50f7e753ea": "アクティブなエージェントにメモを送信しています..."
+ },
+ "RichMarkdownAnnotationOverlay": {
+ "069b5677b8": "選択したテキスト",
+ "6f2f3a6001": "レビューメモを追加"
+ },
+ "RichMarkdownCodeBlock": {
+ "232d9ed853": "コピーされました",
+ "c72beafc0f": "コードをコピーする",
+ "74eab1d9b2": "YAML",
+ "5ef5605cb7": "XML",
+ "88d777bc07": "TypeScript",
+ "9e384d48dc": "迅速",
+ "3009f722b9": "SQL",
+ "d01f55be57": "シェル",
+ "5af8251002": "SCSS",
+ "e72e6b03f4": "さび",
+ "96182a2f64": "ルビー",
+ "2391f9cda9": "パイソン",
+ "89d6cc14fb": "マーメイド",
+ "983b9576b4": "マークダウン",
+ "bcb236e2d8": "コトリン",
+ "78eba32de4": "JSON",
+ "a209c57063": "JavaScript",
+ "36536ad539": "ジャワ",
+ "8c4a3fa02d": "HTML",
+ "706fd85738": "グラフQL",
+ "edfcc64182": "行く",
+ "bf6ee5caaa": "差分",
+ "026653f21f": "CSS",
+ "4daed43ae3": "C++",
+ "4227cf50fe": "バッシュ",
+ "13822cdfda": "プレーンテキスト"
+ },
+ "RichMarkdownDocLinkMenu": {
+ "e17b987473": "↑↓ 移動 ↵ 選択 esc 閉じる",
+ "90c5f0e1e4": "の",
+ "2aaf7d9678": "表示中",
+ "63ced7cb9b": "文書が見つかりませんでした",
+ "0e8489bc11": "マークダウンドキュメントのリンク",
+ "142a7d51cd": "書類"
+ },
+ "RichMarkdownErrorBoundary": {
+ "aad0998127": "再試行",
+ "4a5de9f2f0": "ソース モードに切り替えるか、[再試行] をクリックしてリッチ ビューを再読み込みします。",
+ "dfdf1cacd4": "リッチ マークダウン エディターで予期しないエラーが発生し、Orca の残りの部分の応答性を維持するためにリセットされました。"
+ },
+ "RichMarkdownLinkBubble": {
+ "1c99b726e0": "リンクを削除する",
+ "cdfe166f6f": "リンクを編集",
+ "bfc813e909": "リンクを開く",
+ "7b0b945fdc": "リンクを貼り付けるか入力してください…"
+ },
+ "RichMarkdownReviewNoteLayer": {
+ "f3ef92952b": "このメモ",
+ "9cde7ad994": "エージェント用のメモをコピーする",
+ "117432e2c6": "コピーされたメモ",
+ "3ababd949d": "レビューノート"
+ },
+ "RichMarkdownReviewRailActions": {
+ "636394af72": "エージェント用のメモをコピーする",
+ "a807596997": "コピーしたメモ",
+ "8aaf2c4c69": "レビューメモを表示",
+ "af02dc2456": "レビューメモを非表示にする"
+ },
+ "RichMarkdownSearchBar": {
+ "de68b75bde": "検索を閉じる",
+ "f7bcecbe26": "次の試合",
+ "32ae8d7d57": "前回の試合",
+ "158c645829": "リッチマークダウンエディタで検索",
+ "98b89276f3": "リッチエディターで検索",
+ "a86958d508": "結果はありません"
+ },
+ "RichMarkdownSlashMenu": {
+ "82c6816ff8": "ブロックが見つかりませんでした",
+ "dbdd2ad15f": "ブロックを検索...",
+ "550189b06c": "ブロックを検索",
+ "2e0400b958": "スラッシュコマンド",
+ "e2e12b0e98": "成分"
+ },
+ "RichMarkdownToolbar": {
+ "e935c6b61e": "画像",
+ "6d52624712": "リンク",
+ "f6a51cb9af": "引用",
+ "f97031be09": "チェックリスト",
+ "31630ed66e": "番号付きリスト",
+ "5d1539e5a9": "箇条書きリスト",
+ "0bea19a988": "ストライク",
+ "6b4ccf9493": "イタリック",
+ "4f9e789fe0": "大胆な",
+ "cf5817d827": "見出し 3",
+ "d34a2021c8": "見出し2",
+ "abb5100a3d": "見出し1",
+ "b462641ed2": "本文"
+ },
+ "UntitledFileRenameDialog": {
+ "a7dd27b0bc": "保存",
+ "949711deb4": "キャンセル",
+ "725868c75d": "フォルダを参照する",
+ "5e7f0d8a80": "フォルダーピッカーはリモートファイルには使用できません",
+ "30099dca46": "フォルダ",
+ "2d7d39dc63": ".md",
+ "c8ac7868e6": "ファイル名",
+ "b6ed807cc6": "名前",
+ "e365f3c638": "マークダウン ファイルに名前を付け、フォルダーを選択します。",
+ "674b046582": "名前を付けて保存"
+ },
+ "export": {
+ "active": {
+ "markdown": {
+ "51c4244904": "{{value0}} にエクスポートされました",
+ "d4a901e0ad": "PDF をエクスポートしています...",
+ "eda2cea3ad": "PDFのエクスポートに失敗しました"
+ }
+ }
+ },
+ "markdown": {
+ "rich": {
+ "mode": {
+ "7a8ce7c7da": "このファイルには脚注が含まれているため、コード モードでのみ編集できます。",
+ "2fd2b44073": "このファイルには参照形式のリンクが含まれているため、コード モードでのみ編集できます。",
+ "57128b73e1": "このファイルには HTML、JSX、または MDX が含まれているため、コード モードでのみ編集できます。"
+ }
+ }
+ },
+ "rich": {
+ "markdown": {
+ "editor": {
+ "click": {
+ "routing": {
+ "2d5fb9335d": "ファイルが見つかりません: {{value0}}"
+ }
+ }
+ },
+ "slash": {
+ "commands": {
+ "07e1b32396": "プレーンな Unicode 絵文字を挿入します。",
+ "8a30cbaeca": "絵文字",
+ "3324eb391a": "コンピューターから画像を挿入します。",
+ "572be8e524": "画像",
+ "ae7d0f3f37": "LaTeX 数式表示を挿入します。",
+ "6993a38ad1": "数学ブロック",
+ "565907cf7a": "インライン LaTeX 数学を挿入します。",
+ "2bf5544faf": "インライン数学",
+ "0ed9a7b38c": "マーメイドフェンスブロックを挿入します。",
+ "e516d3f6e3": "マーメイドダイアグラム",
+ "67faab829b": "3x3 のマークダウン テーブルを挿入します。",
+ "19ea597868": "テーブル",
+ "fae45ef4d3": "横罫線を挿入します。",
+ "ae8377cf6b": "ディバイダー",
+ "89e327e054": "フェンスで囲まれたコード ブロックを挿入します。",
+ "624b50cf25": "コードブロック",
+ "972ef9aeea": "折りたたみ可能なテキストセクションを作成します。",
+ "f82c78a2ee": "テキストの切り替え",
+ "9a7fe896dc": "通常の段落を開始します。",
+ "58abdb9d41": "段落",
+ "d766f44867": "チェックリストを作成します。",
+ "d0d2cdfbdb": "チェックリスト",
+ "c9b9e826b8": "順序なしリストを作成します。",
+ "56ff3237e7": "箇条書きリスト",
+ "8e00aba296": "順序付きリストを作成します。",
+ "ed4cf0ebce": "番号付きリスト",
+ "6a3def14de": "ブロック引用符を挿入します。",
+ "c4c775778b": "引用",
+ "4920740259": "小さなセクションの見出し。",
+ "30566ee962": "見出し 3",
+ "45cf7ceb3f": "中くらいのセクション見出し。",
+ "c209a116b7": "見出し2",
+ "3294a2c0cc": "大きな見出しの概要を含む折りたたみ可能なセクションを作成します。",
+ "41482b15ce": "見出し 1 を切り替えます",
+ "570611864e": "大きなセクション見出し。",
+ "e66e7f04c6": "見出し1"
+ }
+ }
+ }
+ },
+ "useContextualCopySetup": {
+ "059bfb0d94": "コンテキストがコピーされました"
+ },
+ "useLocalImagePick": {
+ "175cb8b8ce": "画像の挿入に失敗しました。",
+ "91d835dc88": "ワークツリーのパスが使用できません。"
+ },
+ "useRichMarkdownReviewData": {
+ "f9d2acd6b0": "すべての未送信のメモ"
+ }
+ },
+ "diff": {
+ "comments": {
+ "DiffCommentCard": {
+ "109a791e7b": "保存",
+ "bb0a55f856": "保存中…",
+ "0203bed775": "キャンセル",
+ "6978871a3d": "オープン",
+ "cce596969e": "メモの削除",
+ "cad3384faa": "メモを編集する",
+ "508ee678a5": "ブラウザで開く"
+ },
+ "DiffCommentPopover": {
+ "2b3ce6d394": "キャンセル",
+ "e05063cfc1": "{{value0}} 行目",
+ "c845170b3b": "行 {{value0}}-{{value1}}"
+ },
+ "useDiffCommentDecorator": {
+ "995fa28b50": "このメモ"
+ }
+ }
+ },
+ "dictation": {
+ "DictationController": {
+ "de136f1199": "音声エラー: {{value0}}",
+ "7afff43472": "ディクテーションは終了しましたが、テキストフィールドにフォーカスがありませんでした。",
+ "55127a3706": "ディクテーションが失敗しました: {{value0}}",
+ "bb7f599ee7": "設定を開く",
+ "2d5b9fabf9": "マイクへのアクセスが拒否されました。システム設定でアクセスを許可し、Orca を再起動。",
+ "5d2c3e7ae3": "音声が検出されませんでした。"
+ }
+ },
+ "dashboard": {
+ "DashboardAgentChildDisclosure": {
+ "1b57ce9fa4": "{{value0}} {{value1}} 子 {{value2}}"
+ },
+ "DashboardAgentRow": {
+ "912e136cd9": "送信",
+ "a743da52ff": "詳細を展開する",
+ "a41fb5376e": "詳細を折りたたむ",
+ "5ae84475cc": "閉じる",
+ "b06e13fcf7": "エージェントを閉じる",
+ "0272969e28": "このエージェントに送信",
+ "92a7017987": "送信中",
+ "019b74d93a": "適格"
+ },
+ "DashboardAgentRowMessage": {
+ "0a01046763": "中断された",
+ "1ec01cef03": "ユーザーによる中断"
+ }
+ },
+ "crash": {
+ "report": {
+ "CrashReportDialog": {
+ "b4951cd27c": "レポートの送信",
+ "88fea8e84e": "送信しないでください",
+ "50b00dc327": "詳細をコピーする",
+ "6d3ebe216a": "診断テキスト",
+ "835037edc9": "・Orca",
+ "56a3dfa283": "クラッシュレポートの送信に失敗しました。",
+ "8e24fe4f75": "クラッシュレポートが送信されました。",
+ "8b8473c544": "クラッシュレポートがコピーされました。",
+ "b175e90213": "クラッシュレポートはありません。",
+ "765591798d": "クラッシュレポートを確認しています..."
+ }
+ }
+ },
+ "contextual": {
+ "tours": {
+ "ContextualTourControl": {
+ "186eecc34f": "最初のエージェントメッセージからワークスペースに自動名前を付ける",
+ "02e8373219": "このテキスト ボックスを空のままにすると、新規名前が自動生成されます。",
+ "731c5573df": "最初のメッセージから自動で名前を付ける"
+ },
+ "ContextualTourOverlaySurface": {
+ "4a9568f773": "戻る",
+ "4f86e2a10b": "ツアーをスキップ",
+ "d974f32a83": "ツアーを閉じる",
+ "ffa4412b66": "次"
+ },
+ "ContextualTourProgressDots": {
+ "7734cb8ad3": "の",
+ "dcd6e6b03e": "ステップ {{value0}}/{{value1}}"
+ },
+ "contextual": {
+ "tour": {
+ "overlay": {
+ "measurement": {
+ "38b3155418": "次へ"
+ }
+ }
+ }
+ }
+ }
+ },
+ "cmd": {
+ "j": {
+ "quick": {
+ "actions": {
+ "c884a6398e": "保存されたターミナル コマンドを作成します。",
+ "a43ab56fc1": "クイックコマンドを追加",
+ "54853d52a2": "現在のワークツリーを削除します。",
+ "9537b910fe": "ワークツリーの削除",
+ "0b1f25f796": "新規ワークツリーを開始します。",
+ "52ac9da671": "ワークツリーの作成",
+ "f70812764a": "アクティブなワークスペースでターミナル タブを開きます。",
+ "34980395d4": "新規ターミナルタブ",
+ "f2a1b33f8d": "アクティブなワークスペースに無題のマークダウン ファイルを作成します。",
+ "25349b66fc": "新規マークダウンファイル",
+ "784812ca24": "アクティブなワークスペースでブラウザ タブを開きます。",
+ "892bfa9339": "新規ブラウザタブ",
+ "verbs": {
+ "newBrowser": "新規ブラウザ",
+ "newBrowserTab": "新規ブラウザタブ",
+ "openBrowser": "ブラウザを開く",
+ "browserTab": "ブラウザタブ",
+ "newMarkdown": "新規値下げ",
+ "newMarkdownFile": "新規マークダウンファイル",
+ "newMark": "新規マーク",
+ "newFile": "新規ファイル",
+ "markdownFile": "マークダウンファイル",
+ "newTerminal": "新規ターミナル",
+ "newTerminalTab": "新規ターミナルタブ",
+ "newShell": "新規シェル",
+ "terminalTab": "端子タブ",
+ "createWorktree": "ワークツリーを作成する",
+ "addWorktree": "ワークツリーを追加",
+ "newWorktree": "新規ワークツリー",
+ "deleteWorktree": "ワークツリーを削除する",
+ "deleteCurrentWorktree": "現在のワークツリーを削除する",
+ "removeWorktree": "ワークツリーを削除する",
+ "trashWorktree": "ゴミ箱ワークツリー",
+ "addQuickCommand": "クイックコマンドを追加",
+ "newQuickCommand": "新規クイックコマンド"
+ }
+ }
+ }
+ }
+ },
+ "browser": {
+ "pane": {
+ "BrowserFind": {
+ "c9d5f63fdc": "閉じる",
+ "5c0c02ae76": "次の試合",
+ "ca7aebbd7f": "前回の試合",
+ "636a69cd66": "ページ内で検索...",
+ "7baca7b1b8": "一致しません",
+ "fc63f336aa": "{{value0}}/{{value1}}"
+ },
+ "BrowserImportHintButton": {
+ "05e675fe96": "ヒントを隠す",
+ "77351d22f5": "ブラウザの設定",
+ "e0e125e074": "ファイルから…",
+ "0c6d254eca": "から",
+ "244266c122": "輸入…",
+ "e52a955e6f": "これは、[設定] > [ブラウザ] でいつでも見つけることができます。",
+ "4f5ffaa6a1": "ブラウザデータをインポートする",
+ "b24fef25be": "輸入",
+ "02e89014c5": "{{value1}}{{value2}} から {{value0}} クッキーをインポートしました。"
+ },
+ "BrowserMobileDriverOverlay": {
+ "a6914ee43f": "取り戻す",
+ "f4ecd61552": "このタブはスマートフォンから制御されています。持ち帰ってデスクトップで使用します。",
+ "d9768ec642": "ブラウザ入力が一時停止されています",
+ "20539eca03": "モバイルがこのブラウザを推進している"
+ },
+ "BrowserPane": {
+ "1ded0d3168": "スクリーンショットをコピー",
+ "f30d2d35a7": "スクリーンショット",
+ "fa6ea61de3": "キャンセル",
+ "c2ef0359b9": "コンテンツをコピーする",
+ "f2d0c22d67": "注釈 {{value0}} を削除",
+ "11c5084aa2": "注釈をクリアする",
+ "734e4343ec": "ブラウザの注釈をクリアする",
+ "95af781091": "新規エージェントにフィードバックを送信する",
+ "ac39b9366b": "送信",
+ "a3508d7e6e": "{{value0}} アノテーション{{value1}} が準備されました。別の要素を選択するか、すべてのフィードバックをコピーします。",
+ "f796c774a4": "上に URL を入力して閲覧を開始します。",
+ "366bf5d62c": "新規タブ",
+ "1c78adc73d": "外部に開く",
+ "da68d35f7b": "失敗したページをデフォルトのブラウザで開く",
+ "93be92f8d1": "アドレスをコピーする",
+ "3c085f638d": "失敗したページの URL をコピーする",
+ "c6be71329e": "更新",
+ "781d6459ad": "再試行",
+ "2fdca7df09": "閉じる",
+ "8b6fab9ffa": "保存",
+ "0f41bf80c7": "デフォルトのブラウザで開く",
+ "ec75d0c412": "ブラウザの開発ツールを開く",
+ "fc9be38f6f": "ページ要素に注釈を付ける",
+ "fdfc7fe0ef": "ページ要素を取得する",
+ "a8f37f70c3": "ページの検査",
+ "1b179ab561": "ページの URL をコピー",
+ "f7ab83f7ed": "デフォルトのブラウザでページを開く",
+ "0e080d820e": "リロード",
+ "250a9b3e42": "フォワード",
+ "40edfa75cb": "戻る",
+ "efb0e8f7f3": "リンクアドレスをコピーする",
+ "8ce4f6b12e": "デフォルトのブラウザでリンクを開く",
+ "b5b87d6cbb": "Orca ブラウザでリンクを開く",
+ "87eb75f7d2": "有効な http または localhost URL を入力します。",
+ "27d863542c": "ブラウザの注釈",
+ "e48569ac6d": "このサイトにアクセスできませんでした。",
+ "bbe8f15e83": "このペインは、アクティブなランタイム サーバーからレンダリングされます。",
+ "8b7e6d1f5a": "ブラウザの注釈は、ローカル ブラウザのタブでのみ使用できます。",
+ "deb5293610": "ブラウザの注釈はリモート ランタイムでは使用できません",
+ "90d021f2ad": "追加",
+ "0cb3bd6221": "注釈の意図",
+ "8f87e6c2e5": "意図",
+ "532bac48c5": "エージェントがここで何を変更する必要があるかを説明してください...",
+ "d2a7092e6e": "注釈コメント",
+ "b472c5fe03": "ブラウザの注釈を追加する",
+ "b5ba6085de": "質問",
+ "143204e423": "変化",
+ "e7ca5a098c": "成功",
+ "d51ef37351": "コピー",
+ "6f4ab3592b": "コピーされました",
+ "b2856516e2": "このページを読み込めません",
+ "db325a7eeb": "{{value0}} に連絡できません",
+ "499b31b84e": "すべてコピー",
+ "e72dfa268a": "注釈を付ける",
+ "168350ae6a": "要素をクリックまたはマウスを移動し、C を押してコピーするか、S を押してスクリーンショットを行います。",
+ "e852e20cea": "コピーされました — S を押してスクリーンショットを撮るか、別の要素を選択",
+ "a5dcd0fd1d": "確認する",
+ "777b5bc4ec": "要素をクリックしてエージェントへのフィードバックを追加します。",
+ "b733a91bd9": "選択した要素のフィードバックを追加します。",
+ "4328a0a062": "取得に失敗しました: {{value0}}",
+ "26615e116b": "エラー",
+ "8aec5bc044": "idle",
+ "759f32af29": "ダウンロード中",
+ "c8bc7f1f9e": "要求された",
+ "4300f38145": "{{value0}}{{value1}} からダウンロードしています",
+ "31375046b7": "{{value0}} からダウンロード",
+ "acbe79fd01": "ページ要素の取得 ({{value0}})",
+ "572046436a": "リモートブラウザ",
+ "b313a7275b": "リモートブラウザを開く"
+ },
+ "BrowserToolbarMenu": {
+ "429ef481f9": "キャンセル",
+ "64f448fb6e": "プロファイル名",
+ "67e9b9fcd6": "新規ブラウザプロファイル",
+ "58f2c81542": "スイッチ",
+ "a38f217b46": "プロファイルを切り替えると、このページがリロードされます。保存されていないフォーム データは失われます。",
+ "fe683eb3b4": "プロファイルの切り替え",
+ "a771c2b6c8": "ブラウザ設定…",
+ "ed8f54509d": "デフォルト",
+ "e5d31de1a9": "ビューポートのサイズ",
+ "56f94f4ffa": "ファイルから…",
+ "eb280bfb11": "から",
+ "2293adf620": "Cookieのインポート",
+ "cf7cdc67ef": "新規プロフィール…",
+ "7b838540c7": "ブラウザメニュー",
+ "6aa42813e4": "{{value1}}{{value2}} から {{value0}} クッキーをインポートしました。",
+ "a7a86702b3": "{{value0}} プロファイルを作成して切り替えました",
+ "4d2f9f13a7": "プロファイルの作成に失敗しました。",
+ "3ccd29d771": "{{value0}} プロファイルに切り替えました",
+ "569bce8eb1": "作成",
+ "bf648471c5": "作成…"
+ },
+ "GrabConfirmationSheet": {
+ "314a0aaa5b": "AIにアタッチする",
+ "7095e98362": "スクリーンショットをコピー",
+ "26fd87f4df": "コピー",
+ "87d97bdd6d": "キャンセル",
+ "effd75e330": "近くのコンテキスト",
+ "7d1480fbf1": "HTML",
+ "9098b118ab": "ページ",
+ "eb98a0971a": "」",
+ "d053db279d": "役割=",
+ "a759d8f866": "選択した要素",
+ "9c6ce0632a": "選択した要素のスクリーンショット",
+ "50f7114f99": "取り付ける前に確認してください。キャプチャされたページ コンテキストには、表示されているサイト コンテンツが含まれる場合があります。",
+ "f3575229df": "掴む",
+ "405bb315da": "無題"
+ },
+ "browser": {
+ "address": {
+ "bar": {
+ "suggestions": {
+ "87fcdd0da9": "{{value0}} 検索"
+ }
+ }
+ }
+ }
+ }
+ },
+ "automations": {
+ "AutomationCustomCronPanel": {
+ "3e3b2c369f": "クロン式",
+ "e81a02d61b": "保存する前に、有効な 5 フィールドの cron を入力。",
+ "968e66d686": "5 フィールドの cron を入力します。",
+ "cadb7b0bc9": "無効"
+ },
+ "AutomationDetail": {
+ "007c8ad874": "プロンプト",
+ "a1d52c2189": "使用範囲",
+ "449fc83bf7": "トークン",
+ "401f40ae79": "EST(東部基準時。過ごす",
+ "a7c312430d": "最後の実行",
+ "2df8970cd5": "エージェント",
+ "e353ab9516": "事前チェック",
+ "620b22145e": "グレース",
+ "15ea446b93": "セッション",
+ "5405a09b1f": "実行場所",
+ "2f8baf5360": "から作成",
+ "578ff46987": "次の実行",
+ "18763ded26": "スケジュール",
+ "dbef8dc110": "この SSH 自動化は、Orca が SSH ホストにアクセスできる間のみ実行されます。再接続に対話型認証情報が必要な場合、またはホストが利用できない場合、実行はスキップされたとして記録されます。",
+ "1f6026358e": "オートメーションの削除",
+ "d79452fb30": "自動化を再開する",
+ "91a4155e95": "自動化を一時停止する",
+ "4b1ea02d2e": "オートメーションの編集",
+ "2fb1605beb": "今すぐ実行",
+ "221916d93c": "自動化を作成して、エージェントの作業のスケジュール設定を開始します。",
+ "de0fedac06": "実行ごとの新規",
+ "51a470b966": "ssh",
+ "b09b2384fd": "一時停止中",
+ "eaa02014f8": "有効"
+ },
+ "AutomationEditorDialog": {
+ "fb1896a5e7": "キャンセル",
+ "57b722cbba": "エージェント",
+ "6ff66f9012": "新規実行",
+ "a2e688226d": "ワークツリー",
+ "6f9610e667": "ワークツリーは選択したワークスペースで実行されます。新規実行では、選択したブランチから毎回新規ワークスペースが作成されます。",
+ "2c3fd9bfa1": "ワークスペースモードのヘルプ",
+ "b28b140eaf": "ワークスペース",
+ "0d17f4ca8f": "プロジェクトの選択",
+ "02d351877e": "プロジェクト",
+ "a4ac8fcc62": "/ゴール",
+ "827b25a81e": "スキル、ファイル パス、および組み込みコマンドをサポートします。",
+ "6d778190b7": "依存関係の監査を毎週実行し、リスクのある変更を要約します。",
+ "058c23cb3f": "プロンプト",
+ "c4b19094c2": "スケジュール",
+ "e46c1aa9ad": "作成",
+ "a9d9dccf77": "保存",
+ "777548c2d6": "変更を保存",
+ "ff5db28639": "既存 "
+ },
+ "AutomationEditorDialogHeader": {
+ "31f9253920": "テンプレートを使用する",
+ "7e35393632": "Hermes",
+ "6f309eef8d": "Orca",
+ "58f56b73d9": "オートメーション名",
+ "1d9826933e": "平日のリポ監査",
+ "4133d33862": "オートメーションの作成",
+ "0a75e5e2fa": "エルメスオートメーションを作成する",
+ "03142e7721": "エルメスオートメーションを編集する",
+ "17086b48ee": "オートメーションの編集"
+ },
+ "AutomationMissedRunGraceField": {
+ "0f4459e91d": "48時間",
+ "adbab51feb": "24時間",
+ "ba50e2a230": "12時間",
+ "2dc9ee84d0": "3時間",
+ "521f77cd58": "1時間",
+ "e5ad263ae5": "30分",
+ "529dc6c0b7": "猶予なし",
+ "3d70c185c8": "Orca または実行ホストがスケジュールされた時刻に利用できなかった場合、Orca はこのウィンドウ内で利用可能になったときに、欠落したオカレンスを 1 つ実行します。失敗した古い実行はスキップされます。",
+ "3df53d554a": "逃走猶予ヘルプ",
+ "fc089e5fde": "グレース"
+ },
+ "AutomationPrecheckFields": {
+ "d2a2ac89ac": "10分",
+ "bf49585b3c": "5分",
+ "d84d3765fd": "2分",
+ "c820119736": "1分",
+ "51e28cdad9": "30秒",
+ "bb2dfb3629": "タイムアウト",
+ "99a577306c": "gh pr list --json 番号 -q '.[0].number'",
+ "c2a762a180": "事前チェック"
+ },
+ "AutomationRunHistory": {
+ "402651bfb6": "まだ実行はありません。",
+ "9974a2b429": "状態",
+ "13988187b3": "トークン",
+ "86a248187e": "過ごす",
+ "149c0b49c7": "ワークスペース",
+ "8faaa00726": "走る",
+ "53fc5f07ab": "実行履歴",
+ "a00e38d1a3": "該当なし",
+ "fdb3caa8fb": "知られている"
+ },
+ "AutomationRunPageFrame": {
+ "40a511bed4": "実行コンテキスト",
+ "33741dd973": "ランニングに戻る"
+ },
+ "AutomationSchedulePicker": {
+ "22359b186a": "午前または午後",
+ "9e677335b0": "分",
+ "6b802ecc99": "時間",
+ "d90981f766": "時間",
+ "6b914c5fbb": "日",
+ "233b8c94b6": "ケイデンス",
+ "b08ccb4d06": "毎時",
+ "8cc026fd73": "毎週",
+ "c3e39e17cf": "カスタム"
+ },
+ "AutomationSessionField": {
+ "f3c76dce51": "再利用",
+ "c90888ee94": "新鮮な",
+ "b675112193": "再利用は、今後の実行を前のライブ オートメーション セッションに送信します。そのセッションが終了すると、Orca は新しいセッションを開始します。",
+ "4bdce31f37": "セッション再利用のヘルプ",
+ "5ad314118e": "セッション"
+ },
+ "AutomationsPage": {
+ "2695883141": "削除",
+ "c3a28c9793": "実行を表示するオートメーションを選択します。",
+ "295698292f": "再実行",
+ "0e110a3469": "走る",
+ "bb1b2cd31e": "概要",
+ "97ff587ee3": "このソースに接続して、リモート プロファイル内の Herme オートメーションを確認します。",
+ "aaa007846f": "ソースが利用できない",
+ "25060635c6": "新規追加",
+ "d207ab4c25": "テンプレートから始める",
+ "15e0bfb13b": "削除",
+ "f4612e3f78": "編集",
+ "2faecab10b": "今すぐ実行",
+ "82eb6cb933": "ソース",
+ "13118faadf": "不明なプロジェクト",
+ "587a4b205c": "次へ",
+ "761a35834d": "オートメーション",
+ "73f630b49d": "キャンセル",
+ "1b586f0e2b": "の上",
+ "02a33e3204": "から",
+ "9adfab2596": "外部オートメーションの削除",
+ "1e2e41392f": "二度と聞かないでください",
+ "b264564427": "そしてその実行履歴。以前の実行で作成されたワークスペースは削除されません。",
+ "080dcb5fbb": "オートメーションの削除",
+ "19a6e30eae": "自動更新",
+ "8d1afa8269": "自動化を追加する",
+ "77c2778945": "自動化",
+ "0329f9bef1": "閉じる・Esc",
+ "67c7ff795b": "オートメーションを閉じる",
+ "e1bf9b1512": "ワークスペースが利用できません。",
+ "3e42a5cc1b": "SSH接続に失敗しました。",
+ "9f2855677c": "SSH接続済み。",
+ "126d726546": "外部自動化操作が失敗しました。",
+ "37288942f0": "外部自動化が再開されました。",
+ "77c518a34b": "外部オートメーションが一時停止されました。",
+ "4d7878402c": "外部オートメーションがキューに登録されました。",
+ "4c22bc9913": "外部オートメーションが削除されました。",
+ "3a4c476aa0": "オートメーションの再実行に失敗しました。",
+ "a1bdb57008": "オートメーション実行がキューに入れられました。",
+ "8a3226f172": "設定を開く",
+ "d2a01b0b6f": "これは設定で変更できます。",
+ "690b94da54": "次回からはこの確認は省略させていただきます。",
+ "b11170a008": "オートメーションを保存できませんでした。",
+ "2a20596d6b": "オートメーションが保存されました。",
+ "244727e655": "自動化が更新されました。",
+ "77b81bc4ac": "ヘルメスオートメーションが作成されました。",
+ "08efc3ae12": "エルメスオートメーションが更新されました。",
+ "e431bb85d4": "このHermesオートメーションと同じホスト上のワークスペースを選択します。",
+ "32534e7c9c": "保存する前に、使用可能なワークスペースを選択。",
+ "2360ffc956": "保存する前に、有効なエージェントを選択。",
+ "6e91dab317": "保存する前に、有効な詳細スケジュールを入力。",
+ "64bdb2304f": "保存する前に、サポートされているスケジュールを選択してください。",
+ "2430fecf53": "実行場所を選択し、保存する前にプロンプトを入力します。",
+ "7934ee0d81": "SSH接続",
+ "f93ed7a6f8": "接続中...",
+ "8705757e27": "仕事",
+ "376631ef2b": "再開する",
+ "b457436d6a": "一時停止",
+ "0ae52dd760": "エルメス",
+ "e059042585": "読み取り専用",
+ "aecdc3681f": "管理可能",
+ "8500baacb4": "外部ソース",
+ "36f71740a7": "選択したワークスペース",
+ "cd8397cc32": "実行ごとに新規ワークスペース",
+ "dd0bc7a1ba": "実行ごとの新規",
+ "7b2e285552": "このクライアントでは SSH 接続は利用できません。",
+ "d441032f7e": "一時停止",
+ "5918020edc": "走る"
+ },
+ "CreateFromPicker": {
+ "f061f49e3f": "リポジトリ ブランチを検索...",
+ "dd3841b442": "からの分岐",
+ "ef6d762538": "プロジェクトのデフォルト",
+ "e53d306056": "{{value0}} (デフォルト)",
+ "79512f22a7": "ブランチが見つかりませんでした。",
+ "9ce96621f4": "ブランチを検索中..."
+ },
+ "ExternalAutomationManagers": {
+ "e02f970595": "外部自動化マネージャーが見つかりません。",
+ "6da3bfba4b": "自動化が見つかりました。",
+ "3d58d5b67d": "いいえ",
+ "a42bf2b27e": "外部オートメーションを削除する",
+ "1c3bfd38fe": "外部自動化を再開する",
+ "0def1693bb": "外部オートメーションを一時停止する",
+ "1df491fd00": "外部オートメーションを編集する",
+ "cc77ba88ff": "外部オートメーションを実行する",
+ "5820648765": "最後",
+ "844f1acb72": "見つかった",
+ "20fd7a3a15": "次",
+ "c6695e6fbd": "外部自動化",
+ "5524365227": "OpenClaw",
+ "766abf833c": "Hermes",
+ "bf5f67b590": "エルメス",
+ "e66091daf4": "走る",
+ "8e9165af08": "走る",
+ "2b0adbce21": "一時停止中",
+ "b3feba84c7": "アクティブ",
+ "92405f1431": "利用不可",
+ "dbdcec22bd": "読み取り専用",
+ "0a2d4359a8": "管理可能",
+ "330b3c32e8": "利用可能",
+ "e2532150ed": "自動化",
+ "701515f010": "オートメーション"
+ },
+ "ExternalAutomationRunTable": {
+ "0ba9c0a95c": "次回実行ページ",
+ "52d468a0b8": "前回の実行ページ",
+ "7475c0ce96": "の",
+ "be551397ca": "状態",
+ "a813df9808": "プレビュー",
+ "d4b34feb66": "実行時間",
+ "2d4388a908": "走る",
+ "9c080765ff": "エルメスのランはまだ見つかりません。",
+ "8ea934cacf": "実行をロード中...",
+ "d5527d8fe7": "走る",
+ "872d032d05": "走る"
+ },
+ "HermesCronOutputView": {
+ "e27c716b43": "プロンプト",
+ "4557213074": "応答",
+ "05affc68e3": "エラー",
+ "88d48157fc": "デフォルト"
+ },
+ "WorkspaceCombobox": {
+ "ee5b280eba": "ワークスペースが見つかりません。",
+ "8e9c8cc6b5": "ワークスペースを検索...",
+ "66a0cd9628": "ワークスペースの選択"
+ },
+ "automation": {
+ "templates": {
+ "37571fcb16": "スタックした作業、古い生成ファイル、および失敗したローカル検証を探します。",
+ "8a0228bea3": "時間ごとのキューチェック",
+ "3b7281c75f": "最近の作業をスキャンし、正確性、UX、テスト カバレッジのリスクを指摘します。",
+ "6023075b27": "毎日の変化のレビュー",
+ "513401db93": "現在のプロジェクトの状態から毎週のリリース リスクの概要を作成します。",
+ "39ed39280a": "リリースの準備完了",
+ "a7fbd32ddb": "依存関係、失敗したテスト、および危険なオープン変更を平日ごとにチェックします。",
+ "b84757677d": "平日のリポ監査",
+ "repoHealth": {
+ "category": "リポジトリの健全性",
+ "name": "平日のリポ監査",
+ "prompt": "リポジトリの健全性を確認します。依存関係の更新、失敗したテスト、lint/typecheck ステータス、および危険なオープン変更をチェックします。調査結果を要約し、次の操作を提案します。"
+ },
+ "releasePrep": {
+ "category": "リリース準備",
+ "name": "リリース準備状況のレビュー",
+ "prompt": "リリース準備状況の概要を準備します。阻害要因、マージされていない危険な変更、検証の欠落、ドキュメントのギャップを探します。簡潔なリリース/非リリースの推奨事項で終了します。"
+ },
+ "recurringReview": {
+ "category": "定期的なレビュー",
+ "name": "毎日の変化のレビュー",
+ "prompt": "このワークスペースの最近の変更を確認します。正確性のリスク、UX の回帰、テストの欠落、フォローアップ タスクに焦点を当てます。レポートは短く、実用的なものにしてください。"
+ },
+ "maintenance": {
+ "category": "メンテナンス",
+ "name": "毎時保守点検",
+ "prompt": "スタックした作業、古い生成ファイル、検証の失敗、および人間の対応が必要なものがないか確認してください。対応が必要なイシューのみを報告してください。"
+ }
+ }
+ },
+ "external": {
+ "automation": {
+ "schedule": {
+ "display": {
+ "a8e92b815a": "スケジュールが利用できません"
+ }
+ }
+ }
+ }
+ },
+ "agent": {
+ "AgentCombobox": {
+ "19522e25ee": "エージェントの管理",
+ "986f946354": "ブランク端子",
+ "579c768bde": "検索に一致するエージェントはありません。",
+ "48c6a5a9b4": "エージェントを検索...",
+ "9c6b59fe58": "デフォルトとして設定",
+ "1b0d6965fa": "現在のデフォルト"
+ },
+ "AgentSettingsDialog": {
+ "50cdb57c03": "AI エージェントを管理し、デフォルトを設定し、コマンドをカスタマイズします。",
+ "fc0268e4ed": "エージェント"
+ }
+ },
+ "activity": {
+ "ActivityPrototypePage": {
+ "cf780197a1": "エージェントを選択してそのアクティビティを表示します",
+ "e3db9892f6": "まだ活動はありません。",
+ "1b633f5c1e": "接続端子…",
+ "8de7c5beaa": "ターミナルが使用できません",
+ "866083500b": "ドラッグしてサイズを変更します",
+ "443690186e": "アクティビティスレッドリストのサイズを変更する",
+ "7cd632006b": "これらのフィルターに一致するエージェント アクティビティはありません。",
+ "a2b4437bfb": "{{value0}} アクティビティ",
+ "023ff75afe": "すべて既読としてマークする",
+ "f70e4bec47": "コンパクトモード",
+ "a472a14700": "その他のオプション",
+ "db8a1878b5": "スレッドリストのオプション",
+ "d1a88df9a8": "未読のスレッドのみを表示",
+ "f6396e1f85": "エージェント",
+ "b29191b3e0": "ワークツリー",
+ "8c3b621ddf": "プロジェクト",
+ "4a3986b200": "状態",
+ "770d458144": "エージェントのアクティビティをグループ化する",
+ "795cbf26e2": "フィルター...",
+ "4616ea39fd": "ワークスペースにジャンプ",
+ "59b131fbd9": "スレッドを未読としてマークする",
+ "beb2c19173": "未読",
+ "5651b216c6": "不明なプロジェクト",
+ "22b22034bc": "スタンドアロンターミナルはアクティビティでは使用できません。",
+ "afdc2139a8": "エージェントターミナルが閉じられました。続行するには、このワークスペースで新規ターミナルを開いてください。"
+ },
+ "ActivityTitlebarControls": {
+ "f915168c8e": "未読",
+ "d6a8de3934": "エージェント",
+ "dc708f3eff": "エージェントを閉じる"
+ }
+ },
+ "confirmation": {
+ "dialog": {
+ "8490e5d36a": "確認する",
+ "56f5c60e0c": "キャンセル"
+ }
+ }
+ }
+ }
+}
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
new file mode 100644
index 00000000000..1ce22e37b54
--- /dev/null
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -0,0 +1,9804 @@
+{
+ "app": {
+ "recoverableError": {
+ "rootTitle": "Orca에 렌더러 오류가 발생했습니다.",
+ "rootDescription": "앱 셸에서 렌더링을 완료할 수 없습니다. 다시 마운트해 보거나 오류가 지속되면 Orca를 다시 시작하세요.",
+ "webTitle": "Orca 웹에 렌더러 오류가 발생했습니다.",
+ "webDescription": "웹 클라이언트를 다시 시도하거나 페어링된 런타임에 다시 연결하세요."
+ }
+ },
+ "settings": {
+ "appearance": {
+ "language": {
+ "title": "언어",
+ "description": "Orca 인터페이스에서 사용되는 언어를 선택합니다.",
+ "system": "시스템",
+ "english": "English",
+ "chinese": "中文(简体)",
+ "korean": "한국어",
+ "japanese": "日本語"
+ },
+ "statusBar": {
+ "claudeToggleDescription": "활성 워크스페이스에 대한 Claude 토큰 및 비용 사용량을 표시합니다.",
+ "codexToggleDescription": "활성 워크스페이스에 대한 Codex 토큰 및 비용 사용량을 표시합니다.",
+ "geminiToggleDescription": "활성 워크스페이스에 대한 Gemini 토큰 및 비용 사용량을 표시합니다.",
+ "opencodeGoToggleDescription": "활성 워크스페이스에 대한 OpenCode Go 토큰 및 비용 사용량을 표시합니다.",
+ "kimiToggleDescription": "활성 워크스페이스의 Kimi 구독 사용량을 표시합니다.",
+ "sshToggleDescription": "활성 SSH 연결을 표시합니다. SSH 대상이 구성된 후에만 표시됩니다.",
+ "resourceUsageToggleDescription": "리소스 관리자를 표시합니다. CPU, 메모리, 세션, 데몬 제어 및 워크스페이스 디스크 검색을 위해 클릭하세요.",
+ "portsToggleDescription": "라이브 워크스페이스 포트를 표시합니다. 워크스페이스 범위 포트 및 외부 수신기를 보려면 클릭하세요."
+ }
+ }
+ },
+ "menu": {
+ "checkForUpdates": "업데이트 확인...",
+ "settings": "설정",
+ "exploreOrca": "Orca 둘러보기",
+ "gettingStarted": "Orca 시작하기",
+ "reportCrash": "크래시 신고...",
+ "exportPdf": "PDF로 내보내기...",
+ "file": "파일",
+ "exit": "종료",
+ "edit": "편집",
+ "appearance": "외관",
+ "toggleLeftSidebar": "왼쪽 사이드바 표시/숨기기",
+ "toggleRightSidebar": "오른쪽 사이드바 표시/숨기기",
+ "showStatusBar": "상태 표시줄 표시",
+ "showTasksButton": "작업 버튼 표시",
+ "showAutomationsButton": "자동화 버튼 표시",
+ "showMobileButton": "Orca 모바일 버튼 표시",
+ "showTitlebarAppName": "제목 표시줄 앱 이름 표시",
+ "view": "보기",
+ "reload": "새로고침",
+ "forceReload": "강제 새로고침",
+ "resetSize": "크기 재설정",
+ "zoomIn": "확대",
+ "zoomOut": "축소",
+ "openWorktreePalette": "워크트리 팔레트 열기",
+ "window": "창",
+ "help": "도움말"
+ },
+ "worktreeJumpPalette": {
+ "matchLabel": {
+ "comment": "댓글",
+ "issue": "이슈",
+ "port": "포트",
+ "pr": "PR"
+ }
+ },
+ "auto": {
+ "App": {
+ "221a95ba38": "온보딩을 다시 시도하거나 닫고 앱에서 계속하세요.",
+ "f02d37278a": "온보딩 중 오류가 발생했습니다.",
+ "acd66311dc": "여전히 진단이 필요한 경우 다시 시도한 후 도움말 메뉴를 사용하십시오.",
+ "722d03aa62": "크래시 보고서 대화 상자에 오류가 발생했습니다.",
+ "8a023cea1f": "상태 표시줄을 다시 시도하여 컨트롤을 다시 탑재하세요.",
+ "2e8ff36f94": "상태 표시줄에 오류가 발생했습니다.",
+ "7cbfbf622f": "플로팅 워크스페이스를 다시 시도하거나 닫았다가 다시 열어보세요.",
+ "1b3024bcd6": "플로팅 워크스페이스에 오류가 발생했습니다.",
+ "8d1e160ed1": "사이드바를 다시 시도하거나 탭을 전환하여 이 표면을 다시 로드하세요.",
+ "ed6b168d00": "오른쪽 사이드바에 오류가 발생했습니다.",
+ "03a14f6b5b": "페이지를 다시 시도하거나 다른 Orca 표면으로 이동하세요.",
+ "b7a714db1e": "이 페이지에 오류가 발생했습니다.",
+ "98d4ea2823": "이 워크스페이스에서 터미널, 브라우저 또는 편집기 렌더링에 실패했습니다. 다시 마운트해 보세요.",
+ "5a9519aef0": "워크스페이스 워크벤치에 오류가 발생했습니다.",
+ "cba0fafda5": "활성 페이지는 계속 열려 있습니다. 목록을 다시 시도하거나 보기를 전환하세요.",
+ "1468601e7b": "워크스페이스 목록에 오류가 발생했습니다.",
+ "bdc71dddc9": "활성 워크스페이스는 계속 열려 있습니다. 목록을 다시 시도하거나 보기를 전환하세요.",
+ "c1cf0b0e4a": "패널 접기",
+ "8504ddf267": "앱이 아직 실행 중입니다. 셸을 다시 시도하거나 메뉴를 사용하여 크래시 세부정보를 보고하세요.",
+ "df1d56bf87": "워크스페이스 셸에 오류가 발생했습니다.",
+ "9e0b441a91": "오른쪽 사이드바 표시/숨기기",
+ "e81217c1b7": "앱 이름 숨기기",
+ "5096cbbc86": "Orca",
+ "8b0b8eb54f": "애플리케이션 메뉴",
+ "caea5b51b9": "지금 재시작",
+ "0a9e810705": "다시 시작할 때까지 변경사항이 저장되지 않습니다. 이전 탭은 디스크에 안전합니다.",
+ "12e77cf12b": "세션 복원 실패",
+ "332dbfa497": "워크스페이스가 업로드됨",
+ "e960d18540": "닫기",
+ "c9d6f98459": "최대화",
+ "66f0a552e5": "복원",
+ "bbb7f90669": "최소화",
+ "d54e66004c": "터미널",
+ "9f0152563e": "모바일",
+ "62ca9895a7": "스페이스",
+ "844eb0f4f4": "활동",
+ "3443924e91": "자동화",
+ "4f08ae8311": "작업",
+ "ca6c6eece7": "스킬",
+ "1b9d9d065f": "설정",
+ "c184e056de": "오른쪽 사이드바 표시/숨기기({{value0}})",
+ "f7aa73e785": "앞으로 이동({{value0}})",
+ "cf9099fe98": "앞으로",
+ "fe21e8f6f5": "돌아가기({{value0}})",
+ "064bd07810": "돌아가기",
+ "ce37cf5279": "사이드바 표시/숨기기({{value0}})",
+ "e4b9e7dff7": "사이드바 표시/숨기기"
+ },
+ "web": {
+ "WebConnect": {
+ "b411ec0069": "연결",
+ "2cf9e5a294": "저장된 서버 지우기",
+ "4a4c017be1": "끝점:",
+ "27393856e4": "orca://pair?code=...",
+ "7a566540de": "페어링 URL 또는 코드",
+ "cb4d287238": "서버 이름",
+ "3affe7de3a": "이 브라우저가 연결할 수 있는 Orca 서버의 페어링 URL을 붙여넣습니다.",
+ "e3bcd082ac": "Orca에 연결"
+ },
+ "web": {
+ "preload": {
+ "api": {
+ "31bfe8ae1a": "웹 클라이언트에서는 사용할 수 없습니다.",
+ "67ec964791": "웹 클라이언트에서는 쿠키 가져오기를 사용할 수 없습니다.",
+ "275a776357": "웹 클라이언트에서는 호버 추출을 사용할 수 없습니다.",
+ "8dfcb7a351": "웹 클라이언트에서는 선택 스크린샷을 사용할 수 없습니다.",
+ "31bea294d5": "웹 클라이언트에서는 그랩 모드를 사용할 수 없습니다.",
+ "b8a1618172": "웹 클라이언트에서는 PR 세부 정보 생성을 사용할 수 없습니다.",
+ "e57c82d276": "웹 클라이언트에서는 커밋 메시지 모델 검색을 사용할 수 없습니다.",
+ "9fc90740b6": "웹 클라이언트에서는 커밋 메시지 생성을 사용할 수 없습니다.",
+ "52bee9d8a0": "충돌하는 맞춤 단축키가 무시되었습니다: {{value0}}.",
+ "32f15bdb0f": "알 수 없는 플랫폼 \"{{value0}}\"이(가) 무시되었습니다.",
+ "0a69fcd8bc": "플랫폼은 darwin, linux 또는 win32 섹션이 있는 객체여야 합니다.",
+ "10898045f3": "\"{{value0}}\"에 대한 단축키가 무시되었습니다. 문자열 배열을 사용하세요.",
+ "36761d9604": "알 수 없는 키 바인딩 작업 \"{{value0}}\"이(가) 무시되었습니다.",
+ "d2e43e426a": "{{value0}}은(는) 객체여야 합니다.",
+ "fb290366b2": "웹에서는 사용할 수 없습니다."
+ }
+ },
+ "runtime": {
+ "environment": {
+ "07f788de83": "웹소켓"
+ }
+ }
+ }
+ },
+ "store": {
+ "slices": {
+ "browser": {
+ "d175274b6d": "새 브라우저 탭",
+ "08fc23631d": "브라우저"
+ },
+ "editor": {
+ "dcb521ed29": "이 파일은 충돌 상태에 있지만 편집할 수 있는 작업 트리 파일이 없습니다.",
+ "51f15c37d3": "디렉터리를 열 수 없습니다: {{value0}}",
+ "f2e00db373": "파일을 찾을 수 없습니다: {{value0}}"
+ },
+ "github": {
+ "f129c42773": "GitHub가 새 댓글을 반환하지 않았습니다.",
+ "683a21264b": "행에 소유자/저장소/번호가 없습니다.",
+ "83f9b126ad": "이슈 유형은 이슈에만 설정할 수 있습니다.",
+ "f963485d37": "행을 찾을 수 없습니다.",
+ "a967f23983": "프로젝트 보기가 로드되지 않았습니다.",
+ "87020f6605": "행에 소유자/저장소/번호가 없습니다. 기본 항목을 패치할 수 없습니다.",
+ "d49ef4b944": "이슈 소스 환경설정을 저장하지 못했습니다."
+ },
+ "sparse": {
+ "presets": {
+ "ef13e994e6": "저장하기 전에 사전 설정을 로드해야 합니다.",
+ "6ed7d6010a": "사전 설정을 제거하지 못했습니다.",
+ "ee434d7941": "사전 설정이 삭제되었습니다.",
+ "c96b770172": "사전 설정을 저장하지 못했습니다.",
+ "811be06b57": "사전 설정을 업데이트하지 못했습니다.",
+ "0696d13e56": "사전 설정이 저장되었습니다.",
+ "e10f097822": "사전 설정이 업데이트되었습니다."
+ }
+ },
+ "store": {
+ "test": {
+ "helpers": {
+ "b9a8117c33": "터미널 1"
+ }
+ }
+ },
+ "workspace": {
+ "cleanup": {
+ "9d6e531da6": "워크스페이스가 더 이상 존재하지 않습니다."
+ }
+ },
+ "worktrees": {
+ "5a58e03a26": "\"{{value0}}\"을(를) 삭제했습니다.",
+ "d1d78a7baa": "Git은 \"{{value0}}\"{{value1}} 브랜치를 안전하게 삭제할 수 없으므로 Orca는 로컬 커밋 손실을 방지하기 위해 이를 유지했습니다.",
+ "4e6496f3d2": "{{value0}} 삭제됨, 브랜치 유지됨",
+ "e50495aae6": "브랜치 강제 삭제",
+ "889487d8bb": "닫기",
+ "f4503ca505": "설정 > Git을 열고 다시 시도하세요.",
+ "34a03a6565": "{{value0}}을(를) 최신 상태로 유지하세요",
+ "fa9299a66f": "새 작업 트리는 최신이지만 로컬 {{value0}}은(는) {{value1}} {{value2}} 뒤쳐져 있습니다. AI diff는 최근 커밋을 놓칠 수 있습니다.",
+ "14bc053a47": "로컬 {{value0}}이(가) 새로 고쳐지지 않았습니다.",
+ "4a18052018": "로컬 {{value0}}이(가) {{value1}} 뒤에 있습니다.",
+ "903b51c2ed": "{{value0}}에서 워크스페이스가 생성되었지만 {{value2}} 때문에 Orca가 로컬 {{value1}}을(를) 빨리 감을 수 없습니다.",
+ "0216895fb5": "브랜치를 삭제하지 못했습니다.",
+ "19db0085fb": "로컬 브랜치가 삭제되었습니다.",
+ "2b0afc7f14": "로컬 {{value0}}을(를) 최신 상태로 유지할 수 없습니다.",
+ "670864ab52": "로컬 {{value0}}을 최신 상태로 유지"
+ },
+ "repos": {
+ "b7e14472ae": "폴더를 추가하지 못했습니다.",
+ "e649269645": "원격 런타임에서 프로젝트를 추가하려면 서버 경로를 사용하세요.",
+ "c6e022ddfc": "프로젝트를 추가하지 못했습니다.",
+ "90d129b48b": "폴더가 추가됨",
+ "8bb3ad7935": "프로젝트가 추가됨",
+ "a8e4b3af5b": "프로젝트가 이미 추가되었습니다.",
+ "6d3318e813": "저장소를 가져오지 못했습니다."
+ },
+ "settings": {
+ "e12dab333b": "서버를 전환하지 못했습니다.",
+ "faa8fb83dd": "서버를 전환하기 전에 저장되지 않은 편집기 탭을 저장하거나 닫으십시오."
+ },
+ "ui": {
+ "66e3bd7ce6": "{{value0}}(으)로 보냄",
+ "53883b7bc3": "{{value0}}(으)로 보낼 수 없습니다."
+ }
+ }
+ },
+ "lib": {
+ "agent": {
+ "catalog": {
+ "5dff448636": "OpenClaw",
+ "8a9ba743cc": "Hermes",
+ "4e63c7b956": "Rovo Dev",
+ "bee242fe3d": "Qwen Code",
+ "ca73055bd0": "Mistral Vibe",
+ "28810273af": "Kimi",
+ "739a930554": "Droid",
+ "667c104cff": "Cursor",
+ "9e2a9bb87b": "Continue",
+ "6f8056a565": "Command Code",
+ "4238b771b5": "Codebuff",
+ "cbaf0c2e0b": "Cline",
+ "1f8a19e9ad": "Autohand Code",
+ "5e8eff11b3": "Auggie",
+ "9477377a2a": "Charm",
+ "e0247254f2": "Kiro",
+ "918ba4ffed": "Kilocode",
+ "c73c573939": "Amp",
+ "8da11d876c": "Goose",
+ "b32627f09b": "Aider",
+ "691dd11789": "Antigravity",
+ "12e6baa4f7": "Gemini",
+ "09973b4d84": "OMP",
+ "302934c5d9": "Pi",
+ "e7a4ca5103": "OpenCode",
+ "706b0fe68b": "GitHub Copilot",
+ "0baad2d5d2": "Grok",
+ "760bc6883d": "Codex",
+ "a5fc0cb622": "OpenClaude",
+ "bf53f09bf8": "Claude Agent Teams",
+ "0708ed89f1": "Claude"
+ },
+ "skill": {
+ "cli": {
+ "prerequisite": {
+ "79371593b0": "Orca CLI는 아직 PATH에 표시되지 않습니다.",
+ "e99d7dc36f": "Orca CLI 등록에 주의가 필요함",
+ "2db0bd7515": "Orca CLI 등록을 사용할 수 없습니다.",
+ "8d6eedf97e": "PATH에 Orca CLI를 등록하지 못했습니다.",
+ "0f116999f1": "설정하기 전에 셸을 다시 시작하거나 Orca CLI 디렉터리를 PATH에 추가하세요.",
+ "15cbedc3e3": "에이전트 스킬 설정을 실행하기 전에 Orca CLI를 설치하십시오."
+ }
+ }
+ }
+ },
+ "ensure": {
+ "simulator": {
+ "tab": {
+ "372d21d428": "모바일 에뮬레이터"
+ }
+ }
+ },
+ "fix": {
+ "checks": {
+ "agent": {
+ "launch": {
+ "027228a06b": "이러한 검사를 위한 워크스페이스를 찾을 수 없습니다.",
+ "fb6c294e85": "에이전트 시작 명령을 빌드할 수 없습니다.",
+ "03c1d61f83": "이 검사에 연결된 워크스페이스를 열 수 없습니다.",
+ "822bf52295": "워크스페이스 시작 플랫폼을 확인할 수 없습니다.",
+ "dfb4dd7c00": "이러한 검사에 연결된 워크스페이스를 찾을 수 없습니다.",
+ "9f00d7df0c": "검사 프롬프트가 비어 있습니다. 소스 제어 AI 설정을 업데이트하세요.",
+ "2ebf794906": "이 워크스페이스 호스트에서는 활성화된 AI 에이전트가 감지되지 않았습니다.",
+ "4c7f783a7a": "이 워크스페이스 호스트에서는 저장된 확인 에이전트를 사용할 수 없습니다."
+ }
+ }
+ }
+ },
+ "floating": {
+ "workspace": {
+ "tab": {
+ "creation": {
+ "f3785eddc2": "새 브라우저 탭"
+ }
+ }
+ }
+ },
+ "launch": {
+ "agent": {
+ "in": {
+ "new": {
+ "tab": {
+ "11cce5cc77": "새 터미널에서 {{value0}}을(를) 시작할 수 없습니다.",
+ "a5a1f7033f": "{{value0}}이(가) 전송되지 않았습니다. 에이전트가 준비되면 붙여넣으세요."
+ }
+ }
+ },
+ "background": {
+ "session": {
+ "4ca0651d56": "자동화 프롬프트가 전송되지 않았습니다. 워크스페이스를 열고 붙여넣으세요."
+ }
+ }
+ },
+ "work": {
+ "item": {
+ "direct": {
+ "3de6371df3": "에이전트 시작 명령을 빌드할 수 없습니다.",
+ "67e103dd60": "워크스페이스가 생성되었지만 활성화할 수 없습니다.",
+ "19c7683acf": "생성된 워크스페이스에서는 선택한 에이전트를 사용할 수 없습니다.",
+ "8bc45efdbc": "PR 헤드를 확인하지 못했습니다.",
+ "agent": {
+ "ceeeb509b5": "에이전트를 시작하는 데 시간이 너무 오래 걸렸습니다. 워크스페이스가 준비되었습니다. 에이전트가 유휴 상태일 때 {{value0}}을 붙여넣으세요."
+ }
+ }
+ }
+ }
+ },
+ "local": {
+ "path": {
+ "open": {
+ "guard": {
+ "edc1908653": "로컬 OS에서 원격 경로를 열 수 없습니다."
+ }
+ }
+ }
+ },
+ "open": {
+ "in": {
+ "app": {
+ "catalog": {
+ "f8b8ca2711": "Zed",
+ "d62b12e98a": "Cursor",
+ "173553f73a": "VS Code"
+ }
+ }
+ }
+ },
+ "orchestration": {
+ "usage": {
+ "examples": {
+ "f91fe27f2a": "큰 변경 사항을 더 작은 PR로 분할",
+ "9e37a5b1b3": "독립적인 작업을 병렬로 실행",
+ "bddc4c09b8": "단계별 워크플로 실행",
+ "ab0e9803b7": "다른 작업 트리에 넘겨주기",
+ "5e0d489fe1": "활성 작업 전달"
+ }
+ }
+ },
+ "pr": {
+ "comment": {
+ "audience": {
+ "64deee36a9": "봇",
+ "a7150a17bc": "인간",
+ "27ce73211c": "모두",
+ "empty": {
+ "bot": "봇 댓글이 없습니다.",
+ "human": "인간의 의견이 없습니다.",
+ "all": "아직 댓글이 없습니다."
+ }
+ }
+ }
+ },
+ "resume": {
+ "sleeping": {
+ "agent": {
+ "session": {
+ "f235f604fd": "이 에이전트 세션을 재개할 수 없습니다."
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "agent": {
+ "action": {
+ "plan": {
+ "3f0ea9aa0d": "에이전트 시작 명령을 빌드할 수 없습니다.",
+ "46f1a2c9bd": "명령 입력이 비어 있습니다.",
+ "8eb541cc83": "선택한 에이전트가 이 워크스페이스 호스트에서 감지되지 않았습니다.",
+ "b96e091fc9": "선택한 에이전트는 설정에서 비활성화되어 있습니다.",
+ "a7ac8717c7": "시작하기 전에 에이전트를 선택하세요."
+ }
+ }
+ },
+ "generation": {
+ "plan": {
+ "dc480d5897": "명령 입력이 비어 있습니다."
+ }
+ }
+ }
+ },
+ "sparse": {
+ "preset": {
+ "draft": {
+ "5915a0a1f6": "루트, 절대 경로 또는 상위 세그먼트가 아닌 저장소 상대 디렉터리를 사용하십시오.",
+ "efc05d1820": "하나 이상의 디렉터리를 추가합니다."
+ }
+ }
+ },
+ "terminal": {
+ "shortcut": {
+ "capture": {
+ "notification": {
+ "b0536028c9": "바로가기 열기",
+ "141ad6c004": "터미널 단축키 처리됨",
+ "0ab0cd001a": "크기 4 텍스트 음소거 전경"
+ }
+ }
+ }
+ },
+ "workspace": {
+ "create": {
+ "error": {
+ "format": {
+ "37cf0bc991": "Orca가 이 워크스페이스에 대해 사용 가능한 기본 참조를 확인할 수 없습니다.",
+ "64555d0014": "기본 브랜치를 찾을 수 없습니다."
+ }
+ }
+ }
+ },
+ "worktree": {
+ "palette": {
+ "search": {
+ "9ccec2316b": "이슈",
+ "ca40ffcbec": "PR",
+ "0b01ff98d2": "포트",
+ "7d732521ec": "댓글"
+ }
+ }
+ }
+ },
+ "hooks": {
+ "useAutomationDispatchEvents": {
+ "59718b120b": "대상 워크스페이스를 더 이상 사용할 수 없습니다.",
+ "16a21d6413": "SSH 재연결에는 대화형 자격 증명이 필요합니다.",
+ "386db94f3e": "대상 프로젝트를 더 이상 사용할 수 없습니다."
+ },
+ "useComposerState": {
+ "7eb3f44ff7": "선택한 에이전트가 비활성화되었습니다. 생성하기 전에 활성화된 에이전트를 선택하세요.",
+ "b2ead86962": "PR 기반을 해결하지 못했습니다.",
+ "a9ff236145": "일부 첨부파일을 업로드할 수 없습니다.",
+ "3db83fc58a": "첨부 파일에 사용할 수 있는 원격 프로젝트 경로가 없습니다.",
+ "ba6cb77082": "프로젝트에 연결하지 못했습니다."
+ },
+ "useGlobalFileDrop": {
+ "38c9f034ff": "드롭한 파일을 업로드하지 못했습니다.",
+ "d720e2f855": "드롭한 일부 파일을 업로드할 수 없습니다.",
+ "245faa95b9": "드롭한 파일에 사용할 수 있는 원격 워크스페이스 경로가 없습니다."
+ },
+ "useIpcEvents": {
+ "0e3cf53060": "브라우저 탭 {{value0}}을(를) 찾을 수 없습니다",
+ "a8d2bf8e9e": "닫을 활성 브라우저 탭이 없습니다.",
+ "291c8ed902": "원격 런타임이 활성화된 동안에는 브라우저 탭을 사용할 수 없습니다.",
+ "f45fa2b03c": "원격 런타임이 활성화된 동안에는 브라우저 프로필을 사용할 수 없습니다.",
+ "f000b2ff76": "활성 작업 트리 없음",
+ "56d3ec4203": "제목 없는 마크다운 파일을 생성하지 못했습니다.",
+ "f6300deb8b": "새 브라우저 탭",
+ "7a64b31991": "원격 런타임이 활성화된 동안에는 로컬 터미널 생성을 사용할 수 없습니다.",
+ "60428567b4": "원격 런타임이 활성화된 동안에는 로컬 터미널 표시를 사용할 수 없습니다.",
+ "f8aaf2bde3": "워크스페이스가 업로드됨",
+ "2fe88c2e06": "원격 워크스페이스 동기화를 사용할 수 없습니다.",
+ "2ec42e1c52": "아직 원격 워크스페이스가 없습니다.",
+ "88214a785b": "워크스페이스 동기화가 로컬 세션 하이드레이션을 기다렸다가 시간 초과되었습니다.",
+ "4f78ba5885": "워크스페이스가 동기화되었습니다."
+ },
+ "useSettingsNavigationMetadata": {
+ "4a728cd56b": "아직 구체화되고 있는 새로운 기능입니다. 한번 시도해 보세요.",
+ "225071c560": "실험적",
+ "e338c507c1": "문제 해결을 위한 낮은 수준의 호환성 설정입니다.",
+ "580a04cd81": "고급",
+ "8400cfe1c1": "익명의 사용 데이터 및 텔레메트리 제어.",
+ "3618579df6": "개인정보 및 텔레메트리",
+ "65ec7d1968": "터미널에서 실행되는 개발자 도구에 대한 macOS 개인 정보 보호 액세스입니다.",
+ "d91ae31fbd": "macOS 권한",
+ "95a1886d94": "휴대폰에서 터미널과 에이전트를 제어하세요.",
+ "1cd25673df": "모바일",
+ "31e57d1c70": "파일, 터미널, Git을 위한 원격 SSH 호스트입니다.",
+ "94a5afe910": "SSH 호스트",
+ "40d80bad8a": "베타",
+ "de0c2907a1": "원격 Orca 서버",
+ "b351014180": "Orca 통계와 Claude, Codex 및 OpenCode 사용 분석.",
+ "d72a58b5b9": "통계 및 사용량",
+ "dcd0d9b74f": "일반 작업에 대한 키보드 단축키입니다.",
+ "94295ebfb3": "단축키",
+ "7682607591": "에이전트 및 터미널 이벤트에 대한 기본 데스크톱 알림입니다.",
+ "2eece16ad1": "알림",
+ "1f452cbd4c": "선택 및 편집 동작.",
+ "0c6ee88a5f": "입력 및 편집",
+ "b11a5a48a2": "테마, 확대/축소, 앱 및 터미널 모양, 사이드바, 상태 표시줄.",
+ "93d88d20bf": "외관",
+ "2d0659f6f0": "전역 터미널, 브라우저 및 마크다운 탭.",
+ "65b19f5bde": "플로팅 워크스페이스",
+ "3d65d3f1b9": "Orca 및 코딩 에이전트에 대한 모바일 에뮬레이터 지원을 구성합니다.",
+ "1e761cff2b": "모바일 에뮬레이터",
+ "e815fd01bd": "홈페이지, 링크 라우팅 및 세션 쿠키.",
+ "8c197f74a1": "브라우저",
+ "42ae40842f": "전역적으로 또는 프로젝트별로 범위가 지정된 저장된 터미널 명령입니다.",
+ "3fc3db144f": "빠른 명령어",
+ "c33bfd664c": "셸, 렌더러, 세션 및 터미널 동작.",
+ "a9fb10afca": "터미널",
+ "5235c215ca": "작업 페이지와 사이드바에 표시할 작업 제공자를 선택합니다.",
+ "85f4fd7710": "작업 소스",
+ "ab4b21b58e": "브랜치 이름 지정, 기본 참조, 속성 및 Git AI Author.",
+ "09607cb0fe": "Git 및 소스 제어",
+ "33a5e1d597": "GitHub, GitLab, Linear 및 소스 호스팅 서비스를 연결하세요.",
+ "2b043783ef": "연동",
+ "2cd4ea75da": "워크스페이스 기본값, 앱 설정 및 유지 관리.",
+ "13241992bd": "일반",
+ "724c440e72": "시작하기",
+ "0505d0df29": "Orca 시작하기",
+ "ea0b1bc7b8": "설정 가이드",
+ "17005c73d4": "설정 및 마일스톤 단계에 대한 온보딩 체크리스트를 엽니다.",
+ "ded9e9032f": "온보딩 체크리스트",
+ "5f32ac08f3": "핵심 Orca 워크플로에 대한 온보딩 체크리스트를 완료하세요.",
+ "8ac3de82f5": "온디바이스 모델을 사용한 로컬 음성-텍스트 받아쓰기.",
+ "6a50cdcd7c": "음성",
+ "0059bd17f3": "에이전트가 컴퓨터의 모든 앱을 제어할 수 있도록 하세요.",
+ "b35e92364b": "컴퓨터 사용",
+ "cd50cec5d7": "Orca를 통해 여러 코딩 에이전트를 조정합니다.",
+ "58a868e8e4": "오케스트레이션",
+ "7c79d3b7bf": "선택 사항",
+ "b1c2f8b0ac": "Claude, Codex, Gemini 및 OpenCode Go에 대한 선택적 계정 전환.",
+ "f70ac54d38": "AI 제공업체 계정",
+ "4121f7a0a2": "AI 에이전트를 관리하고, 기본값을 설정하고, 명령을 사용자 정의하세요.",
+ "b49abbd2f7": "에이전트"
+ }
+ },
+ "components": {
+ "CodexRestartChip": {
+ "9132779820": "닫기",
+ "c72a5fb234": "다시 시작",
+ "9263e75f49": "Codex는 이전 계정을 사용하고 있습니다"
+ },
+ "FirstLaunchBanner": {
+ "b9e1b966c7": "알림 닫기",
+ "94cc673726": "확인",
+ "fc5cc29955": "거부",
+ "d1deebb050": "개인 정보 보호 정책",
+ "958d2cc31b": "귀하가 사용하는 기능의 익명 개수는 무엇을 구축할지 우선순위를 정하는 데 도움이 됩니다. 파일 내용, 프롬프트, 터미널 출력 또는 귀하를 식별하는 어떤 것도 없습니다. 설정 -> 개인 정보 보호 및 텔레메트리에서 언제든지 변경하세요.",
+ "9784b4d7bc": "다음에 무엇을 빌드할지 결정하는 데 도움을 주세요.",
+ "fcbee32f08": "텔레메트리 알림"
+ },
+ "GitHubItemDialog": {
+ "3ab6ac0fc8": "선택한 GitHub 이슈 또는 PR을 미리보기하고 편집합니다.",
+ "3cd5ae5b7b": "변경된 파일이 없습니다.",
+ "999b5ad7d9": "파일",
+ "4bd1f5b055": "검사",
+ "e30a5470c9": "대화",
+ "474c59b4b3": "닫기 · Esc",
+ "45af57999b": "미리보기 닫기",
+ "3fdf777817": "GitHub에서 열기",
+ "c43fe79ee0": "GitHub 링크 복사",
+ "0caac1a18f": "PR에서 워크스페이스 시작",
+ "8223320f8d": "업데이트됨",
+ "10ef1afb8e": "· 업데이트됨",
+ "55962099bc": "이 이슈를 열었습니다",
+ "0ab4664a8b": "이슈에서 워크스페이스 시작",
+ "36182aa57f": "새 워크스페이스 시작",
+ "fe6ff12dc2": "추가 이슈 워크스페이스 작업",
+ "726db41722": "워크스페이스 열기",
+ "84855fedd0": "이슈에 첨부된 워크스페이스 열기",
+ "b7bf31b8de": "조회된 상태를 GitHub와 동기화하지 못했습니다.",
+ "c0253318d6": "이 PR에 대해 본 상태를 동기화할 수 없습니다.",
+ "5fea151559": "GitHub 링크를 복사하지 못했습니다.",
+ "2e77dc2053": "GitHub 링크가 복사되었습니다.",
+ "2ef631437e": "이 이슈에 첨부된 워크스페이스를 열 수 없습니다.",
+ "bf43425540": "댓글",
+ "0a73f59e85": "댓글 보내기",
+ "c5c117270e": "댓글 추가…",
+ "082515176a": "댓글을 추가하지 못했습니다.",
+ "c6f37a563d": "+ 담당자",
+ "f41ec96c13": "+ 라벨",
+ "ab050dffec": "닫힘",
+ "dc1ca081a8": "진행 중",
+ "2e4d806c92": "워크스페이스",
+ "886a64b081": "아직 없음",
+ "4ba0132f37": "라벨 수정",
+ "217e55d87c": "라벨",
+ "c67de9e2fe": "할당된 사람 없음",
+ "76adcf5fe2": "담당자 편집",
+ "83ac703dda": "담당자",
+ "00ccdf9b5a": "상태",
+ "2aa9acdf34": "GitHub에서 라벨 편집",
+ "d23bbb6416": "{{value0}} 건너뛰었습니다",
+ "18f80e1329": "{{value0}} 보류 중",
+ "b1ac991806": "{{value0}} 실패",
+ "311d0cee55": "{{value0}} 통과",
+ "e52bed9264": "아직 보고된 체크가 없습니다.",
+ "90020cc1f3": "이 PR에는 아직 보고된 체크가 없습니다.",
+ "ecffebc251": "검사를 찾을 수 없습니다.",
+ "5dddefdf58": "GitHub에서 열기",
+ "744197c84d": "이 검사에는 인라인 출력을 사용할 수 없습니다.",
+ "08d072664d": "채용 정보",
+ "96d8f36798": "주석",
+ "485609c4f2": "체크 #",
+ "0f478f5efa": "완전한",
+ "4812814bc8": "시작됨",
+ "9c3ba11a05": "상태:",
+ "934d87ab96": "검사 세부 정보 로드 중…",
+ "71c11aff84": "모든 검사를 다시 실행하세요.",
+ "e31651a224": "실패한 검사 다시 실행",
+ "1b56e28faa": "재실행",
+ "f4b1292569": "이러한 검사에서 기본 AI 에이전트를 시작합니다.",
+ "9a1004fc76": "새로고침 확인",
+ "03e542fcfe": "실패한 검사로 인해 AI 에이전트를 시작하지 못했습니다: {{value0}}",
+ "28986b3747": "실패한 검사에 대한 AI 에이전트를 시작했습니다.",
+ "1690fd7f4a": "고칠 실패한 검사가 없습니다.",
+ "9e7c221b8d": "검사를 다시 실행하지 못했습니다.",
+ "e463ec935f": "검사 재실행 요청됨",
+ "ddafe851e1": "확인 재실행이 요청되었습니다.",
+ "0bbdc673c1": "확인을 새로고침하지 못했습니다.",
+ "e7007aa1d8": "저장소 경로가 없으면 검사를 새로 고칠 수 없습니다.",
+ "675bc0d638": "취소",
+ "a18f669c7a": "{{value0}} {{value1}} 반응{{value2}}",
+ "53fe19aefc": "GitHub 병합 대화상자 열기",
+ "a2495e4784": "PR",
+ "ce360fc318": "자동 병합을 비활성화하지 못했습니다.",
+ "825a8fb8cd": "자동 병합을 활성화하지 못했습니다.",
+ "4b390bd50d": "자동 병합이 비활성화되었습니다.",
+ "a35ea5a0f6": "자동 병합이 활성화되었습니다.",
+ "aba792c8b3": "PR을 병합하지 못했습니다.",
+ "dbe5e2448e": "PR이 병합되었습니다",
+ "a27ee5ca1a": "그러면 GitHub의 PR이 업데이트됩니다.",
+ "03d7216d62": "{{value0}} PR #{{value1}}?",
+ "e9b7cb7d17": "{{value0}} PR에 실패했습니다.",
+ "bd3b4492a0": "PR가 다시 열렸습니다",
+ "9f88657c4e": "PR이 종료되었습니다.",
+ "b6f1b7adbd": "그러면 GitHub에서 PR이 다시 열립니다.",
+ "de45fedf7b": "그러면 GitHub의 PR이 종료됩니다.",
+ "5a94f3d0e9": "아직 댓글이 없습니다.",
+ "1506916c09": "댓글",
+ "9b9cb55994": "설명이 제공되지 않았습니다.",
+ "52b20b56f7": "설명",
+ "4d555d3796": "설명 수정",
+ "9df4e74bdf": "저장",
+ "0ae387d8ca": "~에 의해",
+ "228e2f59d3": "해결됨",
+ "a154ec5224": "GitHub에서 댓글 열기",
+ "bca8eb39ac": "댓글에 답장하기",
+ "68cb993d61": "해결됨",
+ "10f4ff5be8": "답글이 게시되었습니다.",
+ "745c9089ec": "저장소 경로가 없으면 응답할 수 없습니다.",
+ "58c73cb0d8": "설명을 업데이트하지 못했습니다.",
+ "5221548274": "설명이 업데이트되었습니다.",
+ "06c06e58ba": "아래에 더 많은 줄 표시",
+ "307c98e8e3": "위에 {{value0}}줄 더 표시",
+ "5664681624": "위에 줄 더 표시",
+ "b1574e8ac2": "코드 컨텍스트 재설정",
+ "d43736d09c": "코드 컨텍스트 컨트롤",
+ "bd7be7b1fd": "코멘트 L",
+ "db61d76cd5": "코드 컨텍스트 로드 중…",
+ "f2d02cdf8c": "본 파일",
+ "1257d1435d": "파일 트리 표시",
+ "a341343303": "리뷰 댓글이 추가되었습니다.",
+ "d1fa2cf888": "PR 헤드 SHA가 없으면 댓글을 달 수 없습니다.",
+ "829674460a": "PR 커밋 SHA가 누락되어 Diff를 사용할 수 없습니다.",
+ "af924014f8": "본",
+ "2d89a38d9d": "{{value0}} {{value1}} 보기",
+ "70e84e3d0b": "일치하는 리뷰어가 없습니다.",
+ "1ffce94a8b": "다른 사람들",
+ "c2b21818e1": "제안",
+ "a98433e73d": "로드 중...",
+ "b0b7344684": "최대 15명의 리뷰어 요청",
+ "934add88b6": "리뷰어",
+ "bb42774171": "사용자를 입력하거나 선택하세요.",
+ "36f9ac4a47": "요청한 리뷰어가 없습니다.",
+ "8b15a5e91c": "리뷰어 삭제 {{value0}}",
+ "6a45771d47": "리뷰어 로드 중",
+ "dc8a092c57": "리뷰어",
+ "e3243d9376": "최근에 이 파일을 편집했습니다.",
+ "8c45901789": "리뷰어 요청 {{value0}}",
+ "fedc09eeb9": "리뷰 요청 취소 {{value0}}",
+ "73487fb975": "리뷰어를 삭제하지 못했습니다.",
+ "2e69540652": "리뷰어가 삭제되었습니다.",
+ "69515bff81": "리뷰어가 삭제되었습니다.",
+ "b4af16bf43": "이 PR에 사용할 수 있는 저장소 컨텍스트가 없습니다.",
+ "c42d942b75": "리뷰어를 요청하지 못했습니다.",
+ "c016e4bac3": "리뷰어가 요청됨",
+ "ea985e657f": "리뷰어가 요청함",
+ "12e761610e": "최대 15명의 리뷰어를 요청할 수 있습니다.",
+ "94ab23a9f9": "리뷰어 입력",
+ "3853476a97": "GitHub 항목",
+ "68796dafa0": "PR",
+ "b1157c78ff": "시트",
+ "038b3d39b1": "복사됨",
+ "04539beb48": "이슈",
+ "773ff70035": "알려지지 않은",
+ "3e544d966d": "이슈",
+ "88fd82474d": "페이지",
+ "e517b4d641": "닫힘",
+ "d0a05e73f5": "콤팩트",
+ "7d42606f66": "주석",
+ "2511f44bb7": "실패한 검사를 수정하세요",
+ "9157d48ddb": "점검 수정",
+ "06482d6190": "수정 워크스페이스를 자동으로 만들 수 없습니다.",
+ "f64dd90102": "회신",
+ "5752c25aff": "전기…",
+ "ec5c4b3ab2": "PR 다시 열기",
+ "21860b58d0": "PR 닫기",
+ "5932578f51": "병합에는 등록된 로컬 저장소가 필요합니다.",
+ "ce8a85d209": "기본",
+ "924c2fe05e": "파괴적인",
+ "e2bf3e41a9": "댓글",
+ "28d0d3374f": "실",
+ "080d071d48": "@{{value0}}에 답장",
+ "86f809e2ce": "이 리뷰 스레드에 답변하기",
+ "136542c9ba": ":L{{value0}}",
+ "283699bc82": "답글을 게시하지 못했습니다.",
+ "d1c0dad471": "-L{{value0}}",
+ "31770bef03": "나란히",
+ "6e43a16435": "인라인",
+ "d00a0a7f8f": "모두 축소",
+ "3c19ec3069": "모두 확장",
+ "b0b09778c8": "리뷰 댓글을 추가하지 못했습니다.",
+ "16c1abe76c": "본 것으로 표시",
+ "ba8e329d92": "본 표시 해제",
+ "3f79ffc8b7": "현재 리뷰어를 보려면 PR 세부정보를 엽니다."
+ },
+ "GitLabItemDialog": {
+ "65e784c1f1": "다시 열기",
+ "a199eb364b": "닫기",
+ "16b3412570": "병합",
+ "131865e231": "워크스페이스 만들기",
+ "f2e64d1c20": "GitLab에서 열기",
+ "84012fa8fb": "댓글",
+ "c08e1d5a57": "{{value0}}{{value1}}에 댓글 달기…",
+ "f11e3e7675": "이 MR에 대해 파이프라인이 실행되지 않습니다.",
+ "808b1ca1ba": "변경된 파일이 없습니다.",
+ "007423f585": "차이점 콘텐츠를 사용할 수 없습니다.",
+ "a7eb4f4916": "~에서",
+ "21f8dde18a": "인라인 댓글",
+ "7a7204417f": "선",
+ "ceb08a733d": "파일",
+ "85a8170279": "아직 댓글이 없습니다.",
+ "14423484db": "설명이 없습니다.",
+ "da4174b00f": "편집",
+ "93f79a3fc1": "저장",
+ "f72fad3b16": "취소",
+ "717b706849": "라벨 로드 중",
+ "3c0b6ccca7": "버그, 백엔드",
+ "dde24ade55": "라벨",
+ "908d8d2a73": "설명",
+ "89f3f19368": "제목",
+ "7a2117129a": "추가",
+ "05939e977d": "리뷰어 추가",
+ "474b50d988": "리뷰어가 없습니다.",
+ "1b19cdc510": "리뷰어 삭제 {{value0}}",
+ "cb55b0390f": "관리",
+ "4f9313984d": "리뷰어",
+ "02cbe2de44": "관로",
+ "be3d291837": "파일",
+ "c996e2962c": "대화",
+ "b3c156dd51": "새로고침",
+ "9bfb4a24d7": "~에 의해",
+ "30c97083c2": "GitLab 작업 항목 세부정보",
+ "e089f62594": "MR !{{value0}}을(를) 병합했습니다.",
+ "865ea2703e": "MR !{{value0}}을 다시 열었습니다.",
+ "9b11cd233f": "닫힘 MR !{{value0}}",
+ "60c13320c4": "인라인 댓글이 추가되었습니다.",
+ "ffdd9a78e1": "인라인 주석에는 MR diff 참조를 사용할 수 없습니다.",
+ "00d0d25825": "파일, 라인, 코멘트가 필수입니다.",
+ "ceaf7c30c7": "이 GitLab 사용자의 리뷰어 ID를 사용할 수 없습니다.",
+ "f7cb495a12": "{{value0}}을(를) 다시 시도했습니다.",
+ "98718490e4": "MR 제목이 필요합니다.",
+ "d600c2619a": "로그 로드 중",
+ "028bde664e": "숨다",
+ "2f9b27f838": "작업 로그",
+ "032ae1312b": "GitLab에서 작업 열기",
+ "fa3e042203": "다시 시도",
+ "f23ea85341": "해결됨",
+ "4186685c78": "다시 열기",
+ "cae2712a23": "닫기",
+ "881e522e04": "병합",
+ "6de8ce0cc6": "{{value0}} 필요",
+ "22511537d2": "승인됨",
+ "00f3bab87b": "{{value0}} 중 필수",
+ "11384f99aa": "숫자",
+ "40c56b95e2": "{{value0}} 승인{{value1}} 남음",
+ "3a051b8ade": "작업 항목",
+ "32f8bef818": "로그 출력이 없습니다.",
+ "4168eb2c51": "해결"
+ },
+ "JiraIssueWorkspace": {
+ "b0b92666c9": "댓글",
+ "a585fd204e": "Jira 댓글 추가...",
+ "2441be6f9f": "워크스페이스 시작",
+ "9178090e26": "아직 댓글이 없습니다.",
+ "5cd09beaf9": "다시 시도",
+ "9a980b06b9": "댓글",
+ "c4889a47e4": "설명이 제공되지 않았습니다.",
+ "0f3c07a901": "백엔드, 버그",
+ "aee97b6913": "라벨",
+ "444865b4a8": "제목",
+ "0b6b5646ed": "할당되지 않음",
+ "51bed73f88": "우선순위 없음",
+ "7a96985ca0": "닫기",
+ "76513c7898": "Jira 이슈 미리보기 닫기",
+ "857bd2f88f": "선택한 이슈를 미리보기하고, 편집하고, 작업을 시작하세요.",
+ "0cc62bd690": "프롬프트 복사",
+ "80efa101c5": "추천 브랜치 이름 복사",
+ "38839801e8": "키 복사",
+ "779bb91ee0": "URL 복사",
+ "69da9a208c": "Jira에서 열기",
+ "fa132c8aed": "댓글을 추가하지 못했습니다.",
+ "ea21952aa3": "Jira 이슈를 업데이트하지 못했습니다.",
+ "6c41a9bcea": "{{value0}}을(를) 복사하지 못했습니다.",
+ "2ff69a3545": "{{value0}} 복사됨",
+ "666cfdd835": "알려지지 않은",
+ "9ebee71962": "라벨",
+ "def3d0e824": "제목",
+ "b8e2079d96": "담당자",
+ "54649eaeab": "+ 담당자",
+ "2a829a2f00": "우선 사항",
+ "693be070d0": "이행",
+ "ef21405c6d": "Jira 이슈"
+ },
+ "Landing": {
+ "76a95f7f47": "생성",
+ "f05d237049": "먼저 프로젝트를 추가하세요.",
+ "f9eaa9e12d": "프로젝트 추가",
+ "6ca6ff404e": "Orca",
+ "520304a067": "Orca 로고",
+ "ce44fad849": "종속성 누락",
+ "c1cf168479": "숨다",
+ "00cee697c1": "GitHub 계정을 연결하려면 터미널에서 \"gh auth login\"을 실행하세요.",
+ "9f96d018b7": "GitHub CLI가 인증되지 않았습니다.",
+ "73e1ad4282": "Orca는 GitHub CLI(gh)를 사용하여 PR, 이슈 및 검사를 표시합니다.",
+ "5beaef5f9e": "GitHub CLI가 설치되지 않았습니다.",
+ "b673e7cf1b": "Git 프로젝트, 소스 제어 및 워크스페이스 관리에는 Git이 필요합니다.",
+ "e5b7296d9d": "Git이 설치되지 않았습니다.",
+ "cd21242762": "시작하려면 프로젝트를 추가하세요.",
+ "9c00bd4adf": "시작하려면 사이드바에서 워크스페이스를 선택하세요.",
+ "16e9e3df89": "별표가 붙은",
+ "0d0ace8861": "GitHub의 스타",
+ "ec43b38ba7": "GitHub에 별표 표시됨"
+ },
+ "LinearIssueMarkdownDescriptionEditor": {
+ "d9c47069ef": "가격 인하",
+ "a7301a11f3": "저장",
+ "632096eb1c": "링크",
+ "340160f4e8": "링크 삭제",
+ "9eaf02ac01": "인용",
+ "e2a0267c8c": "체크리스트",
+ "d6b2f3d35b": "번호가 매겨진 목록",
+ "c82917e06e": "글머리 기호 목록",
+ "ad1869bd54": "인라인 코드",
+ "28fd951b83": "스트라이크",
+ "5666b4493d": "이탤릭체",
+ "caa88f50d0": "용감한",
+ "dddaa7a0a6": "제목 2",
+ "e3f741d258": "제목 1",
+ "68a41d5665": "본문 텍스트",
+ "7c52151156": "이슈 설명 형식",
+ "5c16ec8f14": "링크 URL",
+ "4f2fddc2b7": "설명이 제공되지 않았습니다."
+ },
+ "LinearIssueTextEditor": {
+ "947ba2d6f4": "저장",
+ "04d73b72dc": "이슈 제목",
+ "e8ff595db3": "{{value0}}을(를) 업데이트하지 못했습니다.",
+ "1e08a1ec80": "제목은 필수 항목입니다.",
+ "00fa439dc7": "제목",
+ "75294b07d1": "설명"
+ },
+ "LinearIssueWorkspace": {
+ "ad5dec37b7": "선택한 이슈를 미리보기하고, 편집하고, 작업을 시작하세요.",
+ "c23e79e5c0": "행위",
+ "b0eac92d85": "다시 시도",
+ "fabbd3f974": "이슈를 업데이트했습니다 ·",
+ "543970c87a": "활동",
+ "df4c86ed12": "닫기",
+ "7a4997d8bb": "Linear 이슈 미리보기 닫기",
+ "e1e0a9bca9": "워크스페이스 시작",
+ "30a7f56c0a": "이슈에서 워크스페이스 시작",
+ "30c1242f3a": "식별자 복사",
+ "9e3c49beb8": "이슈 식별자 복사",
+ "9a9a884236": "URL 복사",
+ "97c19a84f1": "Linear URL 복사",
+ "f63ef94ea8": "이슈",
+ "f6c6381593": "프롬프트 복사",
+ "5d670ec8dc": "추천 브랜치 이름 복사",
+ "937ba6ad9a": "프로젝트 로드 중",
+ "db3f269d98": "프로젝트 검색",
+ "b51276c8d6": "프로젝트",
+ "8b5b593053": "프로젝트를 업데이트하지 못했습니다.",
+ "f9d4ef9807": "프로젝트가 업데이트되었습니다.",
+ "38b80780c2": "프로젝트를 로드하지 못했습니다.",
+ "42589845bc": "생성",
+ "c182e02de5": "하위 이슈 제목",
+ "8c55d6696a": "하위 이슈 추가",
+ "b25e453c9d": "하위 이슈를 생성하지 못했습니다.",
+ "aeed19d003": "{{value0}}을(를) 생성했습니다.",
+ "9a1317cdd3": "하위 이슈를 로드하지 못했습니다.",
+ "9bcbaa2737": "{{value0}}을(를) 복사하지 못했습니다.",
+ "7835483c43": "{{value0}} 복사됨",
+ "61f424f8ca": "Linear 이슈",
+ "ca8778c124": "알려지지 않은",
+ "8a33c85e9c": "누구",
+ "f5a6b38a14": "시트",
+ "65239a714b": "Linear",
+ "af6e02c44a": "페이지",
+ "76ffd3c937": "추가할 프로젝트를 검색하세요.",
+ "c11b4e3cc2": "프로젝트를 찾을 수 없습니다.",
+ "519c3587f3": "프로젝트에 추가"
+ },
+ "LinearItemDrawer": {
+ "04008e6c46": "이슈에서 워크스페이스 시작",
+ "a4fcc57522": "아직 댓글이 없습니다.",
+ "fde849b2b6": "댓글",
+ "9dc54172db": "닫기 · Esc",
+ "0190b760c1": "Linear에서 열기",
+ "04a442f796": "선택한 Linear 이슈를 미리보기하고 편집합니다.",
+ "d369841269": "댓글 보내기",
+ "2fcff829a8": "댓글 추가…",
+ "2820f0f0f0": "댓글을 남겨주세요...",
+ "6ab35eafd5": "댓글을 추가하지 못했습니다.",
+ "367f828482": "라벨을 찾을 수 없습니다.",
+ "cddd9b04a7": "라벨 로드 중",
+ "23886c7eec": "라벨 추가",
+ "7f7b89b631": "라벨: {{value0}}",
+ "b2376d0179": "멤버 로드 중",
+ "866316f22c": "할당되지 않음",
+ "b5675b0694": "저장",
+ "ceeb8c6153": "지우기",
+ "fbb90300e2": "맞춤 견적",
+ "780ea6ed89": "주를 찾을 수 없습니다.",
+ "59b6cd3706": "로드 상태",
+ "64bfffc4dd": "라벨",
+ "dd304de85a": "속성",
+ "0be31fef8e": "추정치는 음수가 아닌 정수여야 합니다.",
+ "48e17e8cbd": "알려지지 않은",
+ "858d0630da": "미리보기 닫기",
+ "39883467f4": "Linear 이슈",
+ "fda549766e": "댓글을 달려면 {{value0}}",
+ "d71cd3003e": "+ 담당자"
+ },
+ "NewWorkspaceComposerCard": {
+ "cbb47ee0dc": "로컬 Git 프로젝트에만 사용할 수 있습니다.",
+ "d861de981b": "스파스 체크아웃",
+ "090cfedeb4": "메모 쓰기",
+ "f8728aa4f9": "메모",
+ "0ee17638fe": "워크스페이스 이름",
+ "2688050e4b": "이름",
+ "f0470c7383": "고급",
+ "ba64270bdb": "에이전트 구성",
+ "ab63f25397": "에이전트 설정 열기",
+ "01d1e8f601": "에이전트",
+ "0c5d6a479c": "[선택 사항]",
+ "b5a0796911": "연결",
+ "dccd26d4e4": "프로젝트 선택",
+ "d6b0a96f32": "프로젝트 추가",
+ "969a8bff66": "프로젝트",
+ "23bb365554": "orca.yaml",
+ "a239038146": "SSH 연결 오류",
+ "9a70e4859e": "이 워크스페이스를 만들기 전에 설정을 실행할지 여부를 선택하세요.",
+ "803b7fe72f": "설정 구성을 확인하는 중...",
+ "92e34f0311": "로컬 설정",
+ "326a578923": "orca.yaml + 로컬",
+ "2132b670da": "둘 다",
+ "0e587e31fb": "YAML",
+ "ac3748dcda": "이름 또는 '다음에서 만들기'",
+ "f660aa1454": "연결 중",
+ "7711ad5122": "로컬 설정 명령",
+ "e5db1b0419": "결합된 설정 명령",
+ "addProjectBeforeWorkspace": "워크스페이스를 만들기 전에 프로젝트를 추가하세요."
+ },
+ "NewWorkspaceComposerModal": {
+ "fa90f739a5": "워크스페이스를 생성하기 전에 프로젝트, 워크스페이스 이름, 에이전트를 선택하세요."
+ },
+ "PullRequestPage": {
+ "2560588245": "리뷰어를 요청하지 못했습니다.",
+ "3450247584": "댓글",
+ "6ad2c1ab9c": "변경된 파일이 없습니다.",
+ "4d18310d55": "파일이 변경됨",
+ "94d95cf1f7": "검사",
+ "9e8d45700e": "대화",
+ "e6996f4024": "· 업데이트됨",
+ "00b7b82329": "본점",
+ "e1f3641bfd": "~에서",
+ "c44b70352b": "기본 브랜치",
+ "b0e80f083d": "다음에 병합:",
+ "8ecda455a0": "GitHub에서 열기",
+ "1a2570e18e": "새 워크스페이스 시작",
+ "57c13a5aa4": "더 많은 PR 워크스페이스 작업",
+ "25690a3855": "PR에서 워크스페이스 시작",
+ "a459866967": "PR에 연결된 워크스페이스 재개",
+ "347034903a": "GitHub 링크 복사",
+ "5a01ca7253": "조회된 상태를 GitHub와 동기화하지 못했습니다.",
+ "996a1897d2": "이 PR에 대해 본 상태를 동기화할 수 없습니다.",
+ "e0b15c793f": "GitHub 링크를 복사하지 못했습니다.",
+ "992e799227": "GitHub 링크가 복사되었습니다.",
+ "61bfc81ada": "이 PR에 연결된 워크스페이스를 열 수 없습니다.",
+ "161d91ef02": "댓글 보내기",
+ "d2030fc8cd": "댓글 추가…",
+ "1208347ac0": "댓글을 추가하지 못했습니다.",
+ "61452f2143": "이슈에서 워크스페이스 시작",
+ "14c9fc70ed": "+ 담당자",
+ "bc215fea4d": "+ 라벨",
+ "b936cc51a4": "닫힘",
+ "7b8f6bf6d8": "열림",
+ "e6ad0a8d06": "{{value0}} 건너뛰었습니다",
+ "88267924d5": "{{value0}} 보류 중",
+ "ae2a34c7b8": "{{value0}} 실패",
+ "7c5035931a": "{{value0}} 통과",
+ "a18d01cda3": "아직 보고된 체크가 없습니다.",
+ "3912daf310": "이 PR에는 아직 보고된 체크가 없습니다.",
+ "45877f5089": "검사를 찾을 수 없습니다.",
+ "85e62c5266": "실패한 검사에 대한 AI 에이전트를 시작했습니다.",
+ "ddfd42f460": "에이전트를 선택하고 시작하기 전에 전체 명령 입력을 편집하세요.",
+ "a053bdd082": "AI로 실패한 검사 수정",
+ "1b14d0a69c": "GitHub에서 열기",
+ "1550675e5f": "이 검사에는 인라인 출력을 사용할 수 없습니다.",
+ "7720c9c3f5": "채용 정보",
+ "8432d17901": "주석",
+ "f01bf79a79": "체크 #",
+ "000f90afcf": "완전한",
+ "76551b1161": "시작됨",
+ "662bc2998d": "상태:",
+ "d8e82b7f15": "검사 세부 정보 로드 중…",
+ "54cddd1858": "모든 검사를 다시 실행하세요.",
+ "68605516dd": "실패한 검사 다시 실행",
+ "522d9353e1": "재실행",
+ "0fa8b8faec": "이러한 검사에서 기본 AI 에이전트를 시작합니다.",
+ "5d0f42766d": "새로고침 확인",
+ "98583589c6": "실패한 검사로 인해 AI 에이전트를 시작하지 못했습니다: {{value0}}",
+ "51c65c0265": "고칠 실패한 검사가 없습니다.",
+ "788a782bb0": "검사를 다시 실행하지 못했습니다.",
+ "18f2af42ac": "검사 재실행 요청됨",
+ "5963a6a852": "확인 재실행이 요청되었습니다.",
+ "246b2c6456": "확인을 새로고침하지 못했습니다.",
+ "c057f2fcb0": "저장소 경로가 없으면 검사를 새로 고칠 수 없습니다.",
+ "6591b1fa82": "취소",
+ "42c36d9166": "{{value0}} {{value1}} 반응{{value2}}",
+ "7df8d5fc60": "GitHub 병합 대화상자 열기",
+ "1939d0f663": "PR",
+ "973ef2fac9": "자동 병합을 비활성화하지 못했습니다.",
+ "d31f4b508c": "자동 병합을 활성화하지 못했습니다.",
+ "0f5821b035": "자동 병합이 비활성화되었습니다.",
+ "5edbe7eefa": "자동 병합이 활성화되었습니다.",
+ "aae645d36d": "PR을 병합하지 못했습니다.",
+ "c57873d721": "PR이 병합되었습니다",
+ "a63b3c159c": "그러면 GitHub의 PR이 업데이트됩니다.",
+ "eec3706a6a": "{{value0}} PR #{{value1}}?",
+ "b8c6cbb8c4": "{{value0}} PR에 실패했습니다.",
+ "710e47aa06": "PR가 다시 열렸습니다",
+ "7aa3b5f706": "PR이 종료되었습니다.",
+ "3d77438c92": "그러면 GitHub에서 PR이 다시 열립니다.",
+ "5a65651096": "그러면 GitHub의 PR이 종료됩니다.",
+ "d2d589556c": "아직 댓글이 없습니다.",
+ "3463d10a63": "댓글",
+ "c8ea6c7c4c": "설명이 제공되지 않았습니다.",
+ "778683ec84": "설명",
+ "da9aaa8bcf": "설명 수정",
+ "4a337ac05f": "저장",
+ "169a93b29a": "업데이트됨",
+ "3c891789f6": "~에 의해",
+ "f4fe47c2bb": "해결됨",
+ "0ac19bb52e": "GitHub에서 댓글 열기",
+ "d6c6679de7": "댓글에 답장하기",
+ "76b2a0ac5b": "해결됨",
+ "11505c7a71": "답글이 게시되었습니다.",
+ "6885c619e7": "저장소 경로가 없으면 응답할 수 없습니다.",
+ "d94810f652": "설명을 업데이트하지 못했습니다.",
+ "9b4190dc98": "설명이 업데이트되었습니다.",
+ "51ed0cf38b": "아래에 더 많은 줄 표시",
+ "e295a78c11": "위에 {{value0}}줄 더 표시",
+ "c9de94b07a": "위에 줄 더 표시",
+ "5f3e293517": "코드 컨텍스트 재설정",
+ "85d119be40": "코드 컨텍스트 컨트롤",
+ "791ddede19": "코멘트 L",
+ "4b960e5978": "코드 컨텍스트 로드 중…",
+ "89e80af1c7": "본 파일",
+ "319cf2d54b": "파일 트리 표시",
+ "eff839f438": "리뷰 댓글이 추가되었습니다.",
+ "d8c3ba91c4": "PR 헤드 SHA가 없으면 댓글을 달 수 없습니다.",
+ "74660bd80b": "PR 커밋 SHA가 누락되어 Diff를 사용할 수 없습니다.",
+ "2e528e1c2d": "본",
+ "ff84e1f54c": "{{value0}} {{value1}} 보기",
+ "5ad00c7a0e": "일치하는 리뷰어가 없습니다.",
+ "2760fa29a4": "다른 사람들",
+ "828f045847": "제안",
+ "57750f4a8c": "로드 중...",
+ "805cb72cd4": "최대 15명의 리뷰어 요청",
+ "a04c137bb7": "리뷰어",
+ "3bde131f49": "사용자를 입력하거나 선택하세요.",
+ "d10b6d5209": "요청한 리뷰어가 없습니다.",
+ "ae9a38fd4a": "리뷰어 삭제 {{value0}}",
+ "acbd110867": "리뷰어 로드 중",
+ "00d3be6bcd": "리뷰어",
+ "f4a4b3fd9f": "최근에 이 파일을 편집했습니다.",
+ "41d275d3ec": "리뷰어 요청 {{value0}}",
+ "36b514a457": "리뷰 요청 취소 {{value0}}",
+ "c798fa0ec7": "리뷰어를 삭제하지 못했습니다.",
+ "1e6d089420": "리뷰어가 삭제되었습니다.",
+ "2c1d93da43": "리뷰어가 삭제되었습니다.",
+ "1ae11c905c": "이 PR에 사용할 수 있는 저장소 컨텍스트가 없습니다.",
+ "102d3d177f": "리뷰어가 요청됨",
+ "03282ff3b9": "리뷰어가 요청함",
+ "8f369a6b6b": "최대 15명의 리뷰어를 요청할 수 있습니다.",
+ "dace0d1a9f": "리뷰어 입력",
+ "77d9388fb0": "알려지지 않은",
+ "c9e7094a7b": "워크스페이스 재개",
+ "3b6886b2ee": "복사됨",
+ "b6bda618cf": "콤팩트",
+ "35a0573f41": "주석",
+ "61a8c69a33": "페이지",
+ "a4541fd3db": "실패한 검사를 수정하세요",
+ "c808db1dd1": "점검 수정",
+ "c4c02ea23e": "수정 워크스페이스를 자동으로 만들 수 없습니다.",
+ "f119e5f5ef": "회신",
+ "894cfd884b": "전기…",
+ "9d5425918e": "PR 다시 열기",
+ "96d013ed28": "PR 닫기",
+ "d65f70786e": "닫힘",
+ "eca289e593": "병합에는 등록된 로컬 저장소가 필요합니다.",
+ "6568ae8ece": "기본",
+ "19f19560d5": "파괴적인",
+ "aae99c6c04": "PR",
+ "e01e34f5fa": "댓글",
+ "345b68254c": "실",
+ "31a7b202f2": "@{{value0}}에 답장",
+ "408e634fbb": "이 리뷰 스레드에 답변하기",
+ "34b9f7c264": ":L{{value0}}",
+ "5821aab360": "답글을 게시하지 못했습니다.",
+ "84fc40769a": "-L{{value0}}",
+ "1378d79e83": "나란히",
+ "e5f4a24f78": "인라인",
+ "dd94111c18": "모두 축소",
+ "eb722a5a8c": "모두 확장",
+ "19628e058d": "리뷰 댓글을 추가하지 못했습니다.",
+ "50b8fb290f": "본 것으로 표시",
+ "2b4fdb880c": "본 표시 해제",
+ "56ec6eafb7": "현재 리뷰어를 보려면 PR 세부정보를 엽니다."
+ },
+ "QuickOpen": {
+ "1dbd3f59ff": "이동",
+ "73b2c581f1": "닫기",
+ "95fccbae88": "Esc",
+ "61b1c871a6": "열기",
+ "250e5b2dfb": "입력",
+ "74e2e1b3e4": "일치하는 파일이 없습니다.",
+ "722a21e1a8": "파일 로드 중...",
+ "1cb6ef47b7": "파일로 이동...",
+ "9e97f08d0f": "열린 파일 검색",
+ "ec31e058f7": "파일로 이동",
+ "73b44e7bde": "설치 명령 복사",
+ "1cf8561ab4": "빠른 gitignore 인식 목록을 활성화하려면 리모콘에서 다음을 수행하세요.",
+ "5d80dc39bb": "립그렙",
+ "2ca749c15d": "설치",
+ "4725b0e931": "Quick Open 스캔이 너무 큼(",
+ "b227d88520": "{{value0}} 파일을 찾았습니다.",
+ "995be8ea22": "복사",
+ "cf144856dc": "복사됨"
+ },
+ "SelectedTextCopyMenu": {
+ "9b40d7b018": "복사"
+ },
+ "StarNagCard": {
+ "92b0f9d921": "인증된 후 다시 시도하세요.",
+ "cd8c34aac1": "gh",
+ "cf82170065": "저장소에 스타를 표시할 수 없습니다. 다음을 확인하세요",
+ "30c36231c1": "Orca를 통해 시간을 절약했다면 GitHub 스타가 큰 도움이 될 것입니다. 이는 다른 개발자가 프로젝트를 발견하는 데 도움이 되고 팀이 개선 사항을 출시하도록 동기를 부여합니다.",
+ "b5e685e4d9": "닫기",
+ "5f6df21046": "Orca를 즐기고 있나요?",
+ "2d67b6c849": "GitHub의 스타",
+ "af3c9bbb37": "스타 표시 중…"
+ },
+ "TaskPage": {
+ "513cddfa7a": "확인 중…",
+ "ff69a30681": "취소",
+ "2abe22ef76": "귀하의 토큰은 OS 키체인을 통해 암호화되어 로컬에 저장됩니다.",
+ "246c2b3dd3": "Atlassian 계정 설정",
+ "59c14d34a2": "토큰을 생성하세요",
+ "b95623e93f": "Atlassian API 토큰",
+ "68df347677": "you@example.com",
+ "163df31e0e": "https://example.atlassian.net",
+ "33fc2bcb30": "Jira Cloud 사이트 URL, Atlassian 이메일, API 토큰을 사용하여 이슈를 찾아보세요.",
+ "60f806ce99": "Jira 사이트 연결",
+ "8ff6fdc368": "만드는 중…",
+ "fc0d8a1fa4": "제출.",
+ "919a20dd5b": "{{value0}}을(를) 입력하세요",
+ "56cdb413a2": "쉼표로 구분된 값",
+ "1f0fce91e3": "{{value0}}을(를) 선택하세요",
+ "cbcdcbe244": "필수 Jira 필드 로드 중…",
+ "34d97ca682": "무슨 일이야?",
+ "f161bf9ede": "설명(선택사항)",
+ "578f730c16": "간략한 요약",
+ "16cba35bee": "제목",
+ "ae592fee62": "이슈 유형",
+ "7d63e2626e": "로드 중...",
+ "93c57f15e5": "프로젝트를 찾을 수 없습니다.",
+ "cfb56a7868": "프로젝트 검색...",
+ "00022ec0ba": "프로젝트",
+ "0c11ca0b6d": "새로운 Jira 이슈",
+ "d0ca4aa1d0": "라벨",
+ "1742eafc14": "프로젝트 없음",
+ "69591944e7": "낮은",
+ "7fd59c18d8": "중간",
+ "345b169f1f": "높은",
+ "f373ab1a4f": "긴급한",
+ "713179dfdc": "우선순위 없음",
+ "c8d5bec5f7": "우선 사항",
+ "42a9160321": "할당되지 않음",
+ "d2a876ca53": "담당자",
+ "154b0fa623": "상태",
+ "9bc8aea407": "설명 추가...",
+ "d9151fd4e9": "이슈 제목",
+ "4f3cb99f41": "팀 전환",
+ "c11105dac5": "새로운 이슈",
+ "1b59a07674": "만드는 중...",
+ "cf72580c04": "설명을 작성하거나, 프로젝트 개요를 작성하거나, 아이디어를 수집하세요.",
+ "2ea1c701b6": "목표일",
+ "7da41c9225": "목표",
+ "09623359b9": "시작일",
+ "7d08e8be0f": "시작",
+ "af9e877f30": "라벨 없음",
+ "d6cda23ef1": "회원",
+ "cfaadb6b22": "납 없음",
+ "34da8ac06c": "선두",
+ "579f98afcd": "간단한 요약 추가...",
+ "ecbcc83140": "프로젝트 이름",
+ "b6795e65fd": "닫기",
+ "a98cbe7664": "팀",
+ "02f67c0d09": "새 프로젝트",
+ "bdebffcbfe": "선택한 팀에 대한 Linear 프로젝트를 만듭니다.",
+ "1361275ec3": "새로운 Linear 프로젝트",
+ "7f3f7b4c18": "설명(선택사항, 마크다운)",
+ "9f2b4c03a6": "제출",
+ "d3d0998b7d": "새로운 GitHub 이슈",
+ "d1e243795c": "이슈",
+ "be8cf68d9f": "이슈 보기",
+ "67662ade50": "프로젝트 이슈",
+ "6244a02f46": "Linear에서 열기",
+ "606a85c774": "열기",
+ "5e8061b088": "{{value0}} {{value1}}에서 워크스페이스 시작",
+ "592a55611b": "더 많은 팀을 선택하거나 새로고침해 보세요. 팀 필터는 현재 가져온 이슈 세트에 적용됩니다.",
+ "618107fab3": "선택한 팀과 일치하는 가져온 이슈가 없습니다",
+ "903c7af49f": "Linear 이슈가 발견되지 않았습니다.",
+ "5ed38a49e5": "아래 워크스페이스 오류를 확인한 후 새로고침하세요.",
+ "cc8795e07c": "Linear 이슈를 로드할 수 없습니다.",
+ "f362667d55": "업데이트됨",
+ "b1eaa18ace": "이슈",
+ "37e7ee311e": "열쇠",
+ "b7bae28b6a": "표시됨",
+ "a26a48252e": "표시 속성",
+ "5d2d835467": "주문",
+ "5659da12fc": "그룹화",
+ "9c57663908": "보기",
+ "af377b13b1": "{{value0}} 보기",
+ "d47248df4d": "Linear 보기 모드",
+ "f397d513e3": "뒤로",
+ "b39fe6511d": "프로젝트",
+ "8675cd6188": "Linear",
+ "733b8f2421": "Linear / Views",
+ "bc06ed0fb0": "보기로 돌아가기",
+ "3cb855080f": "조회수",
+ "b4e10f096e": "소유자",
+ "a04fe7ba73": "시계",
+ "0aa8525950": "모델",
+ "dfc0c79bd8": "이슈",
+ "8a07f21e76": "건강",
+ "851017590d": "Linear 액세스 추가",
+ "228b25028f": "여기에서 직접 할당된 Linear 이슈를 찾아보고 작업을 시작하세요.",
+ "6d56559467": "리니어 계정을 연결하세요",
+ "eee68073b2": "Jira에서 열기",
+ "9497f2787c": "워크스페이스 시작",
+ "eba87f2edb": "Jira 이슈가 발견되지 않았습니다.",
+ "63b2abd3aa": "Jira 이슈",
+ "e7115334aa": "Jira 숨기기",
+ "83bce6be5c": "Jira 연결",
+ "b518ae6307": "여기에서 직접 Jira 이슈를 찾아보고, 편집하고, 생성하고, 작업을 시작하세요.",
+ "a150c59da7": "Jira 사이트 연결",
+ "bcdc1330b2": "GitLab에서 열기",
+ "00b7ffb952": "유형 / 상태",
+ "eb10c32872": "ID",
+ "e9b6955dcd": "이슈 #{{value0}}",
+ "a0544fb653": "씨!{{value0}}",
+ "8396825a14": "행동",
+ "c1d1600362": "브라우저에서 열기",
+ "b6329379ca": "새 워크스페이스 시작",
+ "054bf695cc": "초안",
+ "285bc21dc5": "쿼리를 변경하거나 지우십시오.",
+ "d0e3c8f933": "일치하는 GitHub 작업이 없습니다",
+ "5b6b2af943": "재시도 중…",
+ "0c0de0fc0e": "다음에서 이슈를 로드할 수 없습니다.",
+ "d1766fd62d": "프로젝트를 로드하지 못했습니다.",
+ "7762f4b03a": "~의",
+ "443f7dd928": "병합",
+ "a7396b05c6": "검사",
+ "f6fa3c97d0": "리뷰어",
+ "8aba10579d": "담당자",
+ "5eccb3c841": "제목 / 맥락",
+ "d4c2830063": "GitLab 작업 항목 새로 고침",
+ "c679af7ad9": "내 할 일 새로 고침",
+ "dfd72673e7": "프로젝트 선택을 저장하지 못했습니다.",
+ "b797bdd7c3": "검색 지우기",
+ "99c2755218": "Jira JQL, 예: 프로젝트 = ABC AND statusCategory != 완료",
+ "2ff9fd71fd": "Jira 이슈 새로 고침",
+ "0b65d3fb2c": "Linear 프로젝트 검색...",
+ "eec0c5c079": "Linear 이슈 검색...",
+ "8964184a8b": "Linear 새로고침",
+ "3feb524d42": "새로운 Linear 이슈",
+ "0cbf7e5cf3": "Linear 작업 모드",
+ "ff53631e6f": "GitHub 작업 새로 고침",
+ "6ffa6be99f": "GitHub 작업 새로 고침",
+ "b15ceb409d": "GitHub 이슈 검색...",
+ "eee4df4c66": "GitHub PR 검색...",
+ "e592d99051": "모든 Jira 사이트",
+ "d09b7631b7": "Jira 사이트를 전환하지 못했습니다.",
+ "8029e2bd4d": "Linear에서 열려면 하나의 Linear 팀을 선택하세요.",
+ "609532fae7": "기본 작업 소스를 저장하지 못했습니다.",
+ "4826fd1ad8": "닫기 · Esc",
+ "1a06219d5c": "작업 닫기",
+ "3f594861a5": "팀 선택을 저장하지 못했습니다.",
+ "d0d570b306": "Linear 워크스페이스를 전환하지 못했습니다.",
+ "cb98f0350c": "{{value0}}을(를) 생성했습니다.",
+ "1e1b2ad8f2": "이 이슈를 등록하기 전에 프로젝트 워크스페이스에서 팀을 선택하세요.",
+ "3ca9b424a3": "프로젝트를 생성하지 못했습니다.",
+ "3f9604efc7": "열린 이슈 #{{value0}}",
+ "585dba2989": "이 이슈에 첨부된 워크스페이스를 열 수 없습니다.",
+ "534a9c6017": "이 PR에 연결된 워크스페이스를 열 수 없습니다.",
+ "fe380f306c": "기본 작업 보기를 저장하지 못했습니다.",
+ "af2a8371de": "Jira 이슈 유형을 로드하지 못했습니다.",
+ "6775c05483": "Linear 상태를 업데이트할 수 없습니다",
+ "745ae567d4": "{{value1}}에는 \"{{value0}}\"을(를) 사용할 수 없습니다.",
+ "669e419d65": "Linear 보기에 워크스페이스 컨텍스트가 없습니다.",
+ "cba2a2b7fb": "Linear 프로젝트에 워크스페이스 컨텍스트가 없습니다.",
+ "f4374519ae": "선호하는 이슈 소스(업스트림)가 더 이상 {{value0}}에 대해 구성되지 않습니다. 원산지를 사용합니다.",
+ "e9139db03f": "{{value0}}을 숨기지 못했습니다.",
+ "b73717af92": "다음",
+ "0c8df28045": "다음 페이지",
+ "ae859c816b": "페이지 {{value0}}",
+ "cd171f3391": "...",
+ "297a805b64": "이전의",
+ "6cd6b3ae6a": "이전 페이지",
+ "e65757a338": "쪽수 매기기",
+ "37d60046e3": "GitHub 병합 대화상자 열기",
+ "1a9ea003dc": "자동 병합을 비활성화하지 못했습니다.",
+ "a3318684bc": "자동 병합을 활성화하지 못했습니다.",
+ "a5bf86defe": "자동 병합이 비활성화되었습니다.",
+ "fed317634c": "자동 병합이 활성화되었습니다.",
+ "88f478cdef": "PR을 병합하지 못했습니다.",
+ "a161925adc": "PR이 병합되었습니다",
+ "0506a78337": "그러면 GitHub의 PR이 업데이트됩니다.",
+ "844dc193c7": "{{value0}} PR #{{value1}}?",
+ "995dd6af9b": "열린 PR 검사",
+ "8a22eb3f7b": "일치하는 리뷰어가 없습니다.",
+ "67755a83a1": "다른 사람들",
+ "3ace2e6bcf": "제안",
+ "0eacf48491": "로드 중…",
+ "0b9b04f4b5": "사용자를 입력하거나 선택하세요.",
+ "62c7bd789f": "최대 15명의 리뷰어 요청",
+ "5d4fd69a6a": "이 PR에서 최근 활성화됨",
+ "ed1daeb49a": "리뷰어를 삭제하지 못했습니다.",
+ "837bb901ec": "리뷰어가 삭제되었습니다.",
+ "f9191d1714": "리뷰어가 삭제되었습니다.",
+ "dc67f69962": "리뷰어를 요청하지 못했습니다.",
+ "8f06dbb9e5": "리뷰어가 요청함",
+ "969e26577c": "최대 15명의 리뷰어를 요청할 수 있습니다.",
+ "d00571d9b1": "리뷰어 입력",
+ "edf4bc4135": "할당 가능한 사용자가 없습니다.",
+ "53e002d895": "이슈에 저장소 슬러그가 없습니다.",
+ "7f94eb6395": "이슈 할당",
+ "bb63046423": "{{value0}}에 할당됨",
+ "ca63694b4c": "담당자를 업데이트하지 못했습니다.",
+ "b36f4bf9de": "라벨이 없습니다.",
+ "5ebff3a0aa": "없음",
+ "d09bf34db7": "닫힘",
+ "1c893195ac": "상태를 업데이트하지 못했습니다.",
+ "afc68824ff": "주를 찾을 수 없습니다.",
+ "cc13109b5d": "로드 상태",
+ "d45a910c4a": "{{value0}}에서 Linear 상태 변경",
+ "d8a517ad89": "식별자",
+ "50387522d7": "그룹화 없음",
+ "d747aed72f": "판자",
+ "a6f7e93d7f": "목록",
+ "e78ec261ed": "조회수",
+ "727069bee5": "프로젝트",
+ "137e2a8a01": "PR",
+ "18451e99df": "완료",
+ "4b6e40e42c": "모두 오픈",
+ "bd9965df51": "신고됨",
+ "1301d376f1": "할당된",
+ "9cd11ba218": "Jira",
+ "11a828abf8": "GitLab",
+ "acef77f7ca": "GitHub",
+ "524f095d55": "리뷰 필요",
+ "7698af5263": "내 거",
+ "94f0339621": "나에게 할당됨",
+ "c2268a9982": "모두",
+ "37a82eaaf8": "병합됨",
+ "887efe9140": "연결",
+ "a70153f583": "연결",
+ "6459faa8b3": "오류",
+ "e15ba2d2eb": "이슈 생성",
+ "3b11c8e8fc": "정렬",
+ "e178c0a953": "이슈를 생성하기 전에 Jira 프로젝트를 선택하세요.",
+ "0f7b0d964a": "{{value0}}에 새로운 이슈를 생성합니다.",
+ "eff9800d4b": "{{value0}} 라벨{{value1}}",
+ "d7f16d0e32": "팀 선택",
+ "5301ca0f20": "프로젝트 생성",
+ "7719d8daa9": "{{value0}} 회원{{value1}}",
+ "5af6f0ae5b": "팀 선택",
+ "cfb730b73e": "이슈",
+ "3659f9792a": "판자",
+ "d079be2dc8": "할당된 이슈가 없습니다. 검색해 보세요.",
+ "2bdefbcac3": "다른 검색어를 사용해 보세요.",
+ "25ff84769a": "이 Linear 컨텍스트와 일치하는 이슈가 없습니다.",
+ "cbce2bc9cd": "없음",
+ "51411113df": "목록",
+ "60f68a2ef4": "Linear 이슈",
+ "b2007ba885": "프로젝트",
+ "6edf402e11": "개요",
+ "9ae151b26b": "Linear",
+ "94d900518d": "선택한 프리셋과 일치하는 이슈가 없습니다.",
+ "f51e254d35": "다른 JQL 쿼리를 시도해 보세요.",
+ "4645a7814f": "Jira",
+ "e224d76876": "씨",
+ "bbec4717ee": "MR",
+ "d6d08c1650": "GitLab 작업 항목을 보려면 프로젝트를 선택하세요.",
+ "f294c500ef": "이 필터와 일치하는 GitLab 작업이 없습니다.",
+ "cd7dc432a3": "이 필터와 일치하는 GitLab MR이 없습니다.",
+ "171b7739d8": "부인",
+ "a9f256ecea": "이 필터와 일치하는 GitLab 이슈가 없습니다.",
+ "2007e14d95": "gitlab",
+ "456b8512da": "MR",
+ "03da966159": "GitLab에 인증할 수 있도록 프로젝트를 선택하세요.",
+ "d591aac6ae": "대기 중인 할 일이 없습니다. 모두 따라잡았네요!",
+ "33a4bd7f5c": "해야 할 일",
+ "66ae7330f6": "추가 작업",
+ "93d5f21fc1": "PR",
+ "e104fa3d3d": "이슈에서 워크스페이스 시작",
+ "2193a99ec1": "이슈에 첨부된 워크스페이스 열기",
+ "7deb9e59a5": "더 많은 PR 작업",
+ "7753652524": "재개",
+ "e4b29c5bcf": "PR에서 워크스페이스 시작",
+ "67d881244c": "PR에 연결된 워크스페이스 재개",
+ "6430594b18": "알 수 없는 저자",
+ "7799ad9ab6": "초안",
+ "0bfbf62f75": "다시 시도",
+ "38139edb52": "GitHub",
+ "31f81cc334": "GitHub 작업을 새로고침 중…",
+ "3d93316bb0": "PR",
+ "937b29fa35": "아이템",
+ "bc46d8204e": "GitHub에서 열 프로젝트 하나를 선택하세요.",
+ "d1132848f8": "GitHub에서 열린 GitHub 프로젝트 하나를 선택하세요.",
+ "2af3ab5c58": "Linear에서 열 팀을 하나 선택하세요",
+ "aec5feeb69": "Jira 이슈를 생성하지 못했습니다.",
+ "7437e340b4": "이슈를 생성하지 못했습니다.",
+ "9e03c17847": "현재 리뷰어를 보려면 PR 세부정보를 엽니다.",
+ "3b7f34282f": "닫힘"
+ },
+ "Terminal": {
+ "73768427cf": "닫기",
+ "f82e9f02df": "취소",
+ "7958465754": "실행 중인 프로세스가 있는 로컬 터미널이 있습니다. 그래도 창을 닫으시겠어요?",
+ "2fa9c69ff3": "창을 닫으시겠습니까?",
+ "cd51e28d8b": "저장",
+ "0037b21794": "저장하지 않음",
+ "21295c6b8c": "저장되지 않은 변경사항",
+ "5c1d2a32bb": "편집기 로드 중...",
+ "f0600556b3": "제목 없는 마크다운 파일을 생성하지 못했습니다.",
+ "37da0d736f": "새 브라우저 탭",
+ "a2a279b32a": "저장 시간이 초과되었거나 실패했습니다. 닫기 전에 오류를 수정하세요.",
+ "46e08bc5c8": "이 파일에는 저장되지 않은 변경사항이 있습니다.",
+ "61ed600d29": "'{{value0}}'에 저장되지 않은 변경사항이 있습니다. 닫기 전에 저장하시겠습니까?",
+ "cdc9ac4b2d": "편집자"
+ },
+ "TerminalSearch": {
+ "db234b7519": "닫기",
+ "7cb40c04eb": "다음 경기",
+ "0f3066256e": "이전 경기",
+ "42e466b9f1": "정규식",
+ "90c61387d9": "대소문자 구분",
+ "e07012f26e": "검색..."
+ },
+ "UpdateCard": {
+ "68b235d264": "업데이트하려면 다시 시작하세요.",
+ "02d4b8a6b9": "다운로드됩니다. 준비가 되면 다시 시작하세요.",
+ "93794ea932": "Orca v{{value0}}을(를) 다운로드 중입니다.",
+ "8acbdd3961": "상태 표시줄로 최소화",
+ "17412483da": "설치 준비 완료",
+ "47126bcf57": "수동으로 다운로드",
+ "3553a8672f": "마지막 오류",
+ "90559b14e3": "다시 시작한 후 프로세스 전체의 Electron 네트워킹 스위치가 켜집니다. HTTP/2 업데이트 다운로드를 거부하는 기업 VPN 또는 프록시에 사용하세요.",
+ "6e45bfa2e0": "다운로드 중...",
+ "558842597d": "업데이트 다운로드 중",
+ "f58b5c57a6": "새로운:",
+ "ec8fe71cfc": "업데이트",
+ "44324ef542": "릴리스 노트",
+ "fdd4a364fa": "세션은 중단되지 않습니다.",
+ "c4890662e9": "준비되었습니다.",
+ "318d3b4bc7": "업데이트 닫기",
+ "9abc59f814": "업데이트 가능",
+ "aad383aecc": "전체 릴리스 노트 읽기",
+ "ccd8b0a793": "마지막 업데이트 이후 더 많은 것",
+ "b1d867f4fb": "업데이트 중에 터미널 세션이 중단되지 않습니다.",
+ "09a55c39b5": "설치 중...",
+ "ea2a41adbe": "최신 버전을 사용 중입니다.",
+ "ba5ffc949c": "업데이트 확인 중...",
+ "2c2d3e03ca": "다시 시도",
+ "4cf109845a": "업데이트 오류",
+ "6b0085010d": "재확인",
+ "48565a32bc": "다운로드 재시도",
+ "933c6fdf5b": "활성화 및 다시 시작",
+ "1339b82cee": "HTTP/2 다운로드가 차단됨",
+ "7274ef6e59": "도움말 닫기",
+ "a726967bd3": "닫기",
+ "d5253b54af": "오류",
+ "7ffc08506e": "확인",
+ "522df222b9": "스피너"
+ },
+ "WorktreeJumpPalette": {
+ "ac037cfac2": "이동",
+ "75499e01d9": "닫기",
+ "66b5a67bee": "Esc",
+ "45def60329": "열기",
+ "f65d992a11": "입력",
+ "c5081f2814": "현재 작업 트리",
+ "52404f8096": "현재 탭",
+ "739bda980c": "주요한",
+ "556e7232ca": "현재",
+ "684e8d7bc2": "최근 작업 트리와 열린 탭을 수집합니다.",
+ "ff908adfe9": "점프 타겟 로드 중",
+ "1ebe225fee": "작업 트리, 설정, 탭 및 작업 검색...",
+ "4e4ff044d5": "작업 트리, 설정, 탭 및 작업 검색",
+ "4ee378034d": "다음으로 이동...",
+ "f7fda8d562": "작업 트리를 만들거나 Orca에서 탭을 열어 시작하세요.",
+ "1628fd7dfa": "활성 작업 트리, 설정, 작업 또는 열린 탭이 없습니다.",
+ "b781ae05e3": "작업 트리, 설정, 탭 및 작업을 검색하려면 입력하세요.",
+ "f60f8730be": "전환할 다른 작업 트리가 없습니다.",
+ "c4afa68159": "작업 트리, 설정, 작업, 페이지 제목, 에뮬레이터, URL, PR 또는 포트를 사용해 보세요.",
+ "dbd9d87eec": "검색어와 일치하는 결과가 없습니다.",
+ "2c38630a01": "워크스페이스가 더 이상 존재하지 않습니다.",
+ "7726ce9970": "모바일 에뮬레이터 탭이 더 이상 존재하지 않습니다.",
+ "d7d496a451": "브라우저 페이지가 더 이상 존재하지 않습니다.",
+ "50a1d11d5b": "탭 열기",
+ "088d66d980": "작업 및 설정",
+ "dabd819ca1": "모든 {{value0}} 작업 트리를 보려면 입력하세요.",
+ "20af998bff": "{{value0}} 사용 가능한 항목{{value1}}",
+ "bb72c08e63": "{{value0}} 결과를 찾았습니다{{value1}}",
+ "34c8fbb46e": "SSH 원격",
+ "63c2be1914": "SSH 연결이 끊어졌습니다.",
+ "95be6587d3": "작업 트리 \"{{value0}}\" 만들기",
+ "worktreesHeader": "작업 트리",
+ "recentWorktreesHeader": "최근 작업 트리",
+ "settingsBadge": "설정",
+ "actionBadge": "행동"
+ },
+ "github": {
+ "pr": {
+ "merge": {
+ "state": {
+ "a80132573b": "GitHub는 여전히 이 PR 병합 상태를 계산하고 있습니다.",
+ "f958920f3a": "확인 중",
+ "9bd983ce8f": "GitHub에서는 이 PR이 병합될 수 있지만 검사는 여전히 실행 중이라고 말합니다.",
+ "4e2507176b": "검사 대기 중",
+ "1432ecff30": "GitHub에서는 이 PR이 병합될 수 있지만 일부 확인이 실패했다고 말합니다.",
+ "87fa36ac83": "확인 실패",
+ "1766eb46ba": "GitHub에서 이 PR이 차단되었다고 보고합니다.",
+ "bf5e4c6c92": "차단됨",
+ "c614e2660a": "병합하기 전에 브랜치 업데이트",
+ "039c072f94": "뒤에",
+ "b37d45bca9": "GitHub에서 병합 충돌이 보고됨",
+ "7e8bbe3cd7": "충돌",
+ "09896aad26": "이 PR에는 병합 상태를 사용할 수 없습니다.",
+ "bd4f27b50e": "병합",
+ "35ec24bc43": "이 기본 브랜치는 GitHub 병합 대기열을 사용합니다.",
+ "b289646bcd": "GitHub는 이 PR에 대해 요청된 변경 사항을 보고합니다.",
+ "c606463dc2": "변경 요청됨",
+ "a20db875ed": "이 PR을 병합하려면 GitHub에서 리뷰 승인이 필요합니다.",
+ "1f8eb81c0e": "승인 필요",
+ "f03028e055": "이 PR은 아직 초안입니다.",
+ "ec8e2cebaa": "초안",
+ "820fd21663": "이 PR이 종료되었습니다.",
+ "4f976d3450": "닫힘",
+ "62eb8d39da": "이 PR은 이미 병합되었습니다.",
+ "83ecdbb4a6": "병합됨",
+ "331ebe1170": "GitHub 병합 대기열에 이 PR을 추가하세요.",
+ "b169f943e1": "준비되면 병합",
+ "62703b1dc4": "이 PR에 대해 GitHub 자동 병합이 활성화되었습니다.",
+ "48d75ae118": "자동 병합 비활성화"
+ }
+ }
+ },
+ "project": {
+ "ColumnResizeHandle": {
+ "1304289353": "열 크기 조정"
+ },
+ "GhAuthErrorHelp": {
+ "7e800068d8": "새로고침",
+ "baa006f9af": "문서",
+ "3fefeebde4": "새로 고침 명령 복사",
+ "9c2da6353b": "로그인 명령 복사",
+ "b436c586d1": "명령 복사",
+ "8a7f6bf5dc": "복사하지 못했습니다.",
+ "224c9d0ae8": "클립보드에 복사됨",
+ "891a7d4616": "이 셸에 대해 설정되지 않음",
+ "fd17b3019f": "설정되지 않음(PowerShell, 영구)",
+ "ae43542893": "설정된 위치 찾기",
+ "df636f5886": "설정되어 있는지 확인하세요(PowerShell)."
+ },
+ "ProjectCell": {
+ "4b5b871da8": "이 저장소에는 라벨이 없습니다.",
+ "2219e945ef": "로드 중…",
+ "54cac64427": "행에는 저장소 슬러그가 없습니다.",
+ "8ae56a88a6": "라벨",
+ "f7cdb78efb": "담당자",
+ "ebde486e3c": "지우기",
+ "191905e20e": "현재 및 향후",
+ "e17bb96881": "완전한",
+ "943b3dadc9": "이 저장소에는 이슈 유형이 없습니다.",
+ "c7b059cf07": "이슈 유형",
+ "c5f949e489": "이슈",
+ "8d669084f6": "제한된",
+ "6efdc0d920": "초안",
+ "d0d0e13a5a": "PR",
+ "af5d8c912a": "제한 품목",
+ "bb7ebc11e3": "번호 추가",
+ "9cb1a0c984": "텍스트 추가",
+ "2e26a06c70": "라벨 추가",
+ "36341ffc66": "할당",
+ "e369bf4fec": "선택",
+ "ffeff79861": "PULL_REQUEST"
+ },
+ "ProjectGroupHeader": {
+ "82a22d2079": "현재",
+ "244c9e7d06": "모두"
+ },
+ "ProjectItemSlugDialog": {
+ "e55a5c4e68": "프로젝트 행 미리보기.",
+ "4450efea9c": "GitHub 항목"
+ },
+ "ProjectPicker": {
+ "96739284c3": "누락된 프로젝트에 접근하려면 아래에 프로젝트 URL을 붙여넣으세요.",
+ "9b36829267": "조회수를 찾을 수 없습니다.",
+ "72a05c04a6": "보기 로드 중…",
+ "9bf55fa1e8": "보기 선택",
+ "a51b3337ab": "← 뒤로",
+ "8ab5447c64": "핀",
+ "5009ffc2f3": "핀 제거",
+ "fce99a24a7": "추가",
+ "5113ecc298": "URL 또는 소유자/번호로 추가",
+ "7b6d39627e": "로드 중…",
+ "b787682111": "모두 찾아보기",
+ "ba0ab9a117": "모두 찾아보기(로드 중…)",
+ "b3044b7a25": "최근의",
+ "707843206c": "고정됨",
+ "f492e1b539": "프로젝트 검색",
+ "44b2c6326b": "보기를 로드하지 못했습니다: {{value0}}",
+ "ab1a2c357d": "로드맵(지원되지 않음)",
+ "d34ef9b554": "보드(지원되지 않음)",
+ "43a88ae574": "BOARD_LAYOUT",
+ "1a2b8e512e": "테이블",
+ "cafb908f34": "TABLE_LAYOUT"
+ },
+ "ProjectRow": {
+ "75b5d816e3": "작업 시작",
+ "e12be8b4d4": "GitHub에서 열기",
+ "c3b81ddea2": "DRAFT_ISSUE"
+ },
+ "ProjectViewList": {
+ "989f81dc2a": "열",
+ "f949f5b2b7": "열 구성",
+ "eddfc7a794": "{{value0}} 기준으로 정렬",
+ "4f57d2e0b1": "이 보기의 필터와 일치하는 항목이 없습니다."
+ },
+ "ProjectViewWrapper": {
+ "463f1205c0": "프로젝트 보기 로드 중",
+ "23b87ba9f7": "GitHub에서 열기",
+ "4d2a77a119": "파일 기능 요청",
+ "1bf8c01c8b": "Orca에서 이 프로젝트를 사용하려면 테이블 보기로 전환하세요.",
+ "55de4fb57a": "{{value0}}. {{value1}} {{value2}}에 기능 요청을 제출하세요.",
+ "2edf5e7e77": "{{value0}} — Orca는 아직 {{value1}} 프로젝트 보기를 지원하지 않습니다. {{value2}}에 기능 요청을 제출하세요.",
+ "7245c3d7ac": "검색 지우기",
+ "c5bc7ec007": "보기 필터: {{value0}}",
+ "840c268665": "저장소 추가",
+ "dffa899f36": "취소",
+ "7037c8f5f1": "Orca에 없는 저장소",
+ "512fc171d6": "시작하려면 프로젝트를 선택하세요.",
+ "71fb69926c": "새로고침",
+ "a8fa0d2bf5": "새로고침 중",
+ "fd15491034": "GitHub에서 보기 열기",
+ "22df63c393": "토큰에 대한 하위 이슈 데이터를 사용할 수 없습니다.",
+ "067119985c": "GitHub 검색, 예: 담당자:@나 현재:열림",
+ "1850fceac8": "{{value0}}/{{value1}}은 Orca에 추가되지 않습니다. 작업을 시작하려면 추가하거나 GitHub에서 엽니다."
+ },
+ "slug": {
+ "dialog": {
+ "AssigneesEditor": {
+ "529fec247b": "로드 중…",
+ "98914e6b36": "담당자:",
+ "94a4e6e4fa": "없음"
+ },
+ "Comments": {
+ "fd5cccd138": "댓글",
+ "1c95937c8b": "댓글을 쓰세요…",
+ "c0e576e96b": "취소",
+ "c3e829b4d9": "저장",
+ "463d030ae4": "삭제",
+ "8564f58542": "편집",
+ "5f104bf855": "아직 댓글이 없습니다."
+ },
+ "LabelsEditor": {
+ "34dd57d6c8": "로드 중…",
+ "a7b182fcda": "라벨:",
+ "1a5366b5be": "없음"
+ },
+ "SlugDialogBody": {
+ "598ad6a517": "댓글",
+ "41169e41fb": "설명 추가…",
+ "a91735d19f": "취소",
+ "e64f6c3eff": "저장",
+ "e4ef8281e9": "로드 중…",
+ "ae98897edf": "닫기",
+ "69caf40ae8": "GitHub에서 열기",
+ "7c302f8174": "제목 없음"
+ }
+ }
+ }
+ },
+ "GitHubMarkdownComposer": {
+ "015b4e607d": "취소",
+ "e3bd59143c": "끼워 넣다",
+ "f24783f470": "https://...",
+ "ec6310b731": "http:// 또는 https:// 이미지 URL을 사용하세요."
+ },
+ "IssueSourceSelector": {
+ "d6aeb2012b": "다음에서 이슈 표시",
+ "787c970baf": "이슈 소스",
+ "643d7e9496": "상류",
+ "51d1608920": "기원",
+ "cdc9bd64fa": "콤팩트",
+ "30b2c9df91": "업스트림"
+ },
+ "PRFilterDropdowns": {
+ "979be3cf6b": "담당자",
+ "b27b7e526c": "리뷰 출처",
+ "7f1ba66c3e": "리뷰어",
+ "9d0f2eda6d": "상표",
+ "01f3f3d161": "작가",
+ "13b3ac0a84": "상태",
+ "79c54552f7": "필터",
+ "8a2ffbf9b3": "{{value0}} 필터 제거",
+ "19bb6f115f": "reviewed-by"
+ },
+ "PRFilterPickers": {
+ "fdf387297c": "지우기 (",
+ "472c12ae03": "지우기",
+ "2d1f58eda6": "사용"
+ },
+ "PRFilterSections": {
+ "a00830d3f7": "사용자 없음",
+ "0103e1cb18": "리뷰어",
+ "94b42b0edf": "리뷰 요청됨",
+ "de26e2eb06": "라벨 없음",
+ "458ea3602b": "작성자 없음",
+ "b69fa4fa20": "뒤로",
+ "30ebb6ca44": "모든 필터 지우기",
+ "8177eda37e": "필터",
+ "ea3416d646": "담당자",
+ "b1d9fdea08": "상표",
+ "24754c44ad": "작가",
+ "764a0b4ce1": "상태",
+ "f0cf6dd591": "끄다",
+ "1e9b5244f2": "~에",
+ "b930de7194": "초안만",
+ "e0002f1eba": "선택된",
+ "2b2f019091": "모든 주",
+ "0fd3249e2e": "닫힘",
+ "d78b60b5c2": "열림",
+ "bd162b7d5a": "병합됨",
+ "2e639b84fa": "리뷰어",
+ "712c5abdbf": "상표",
+ "4e50c7bc03": "담당자",
+ "7bf3a6e5ac": "작가",
+ "66256a73b3": "상태",
+ "3ce4d5e96e": "PR"
+ },
+ "github": {
+ "rate": {
+ "limit": {
+ "display": {
+ "5509443543": "GitHub API 예산 로드 중…",
+ "34973d4695": "GitHub API 예산을 사용할 수 없습니다.",
+ "d12d3d6f33": "GitHub API 예산 새로 고침",
+ "d5e5de9070": "Orca는 GitHub CLI를 통해 REST, 검색 및 GraphQL을 사용합니다.",
+ "58c5f88216": "GitHub API 예산",
+ "6da1858354": "왼쪽 · 다음으로 재설정",
+ "f42790d150": "~의",
+ "01f7323e58": "GraphQL API",
+ "1daf0f22a9": "GraphQL",
+ "1f2f28a4de": "검색 API",
+ "c377a4f06a": "검색",
+ "c392c749a6": "REST API",
+ "bb227706a6": "나머지"
+ }
+ }
+ }
+ }
+ },
+ "linear": {
+ "api": {
+ "key": {
+ "dialog": {
+ "834a52c084": "확인 중...",
+ "f8f704a019": "취소",
+ "e603ee9156": "워크스페이스 API 설정",
+ "dc7ccb0f7c": "개인 API 키",
+ "e3100b36b9": "멤버 API 키가 차단된 경우 워크스페이스 관리자에게 워크스페이스 API 설정에서 이를 허용하도록 요청하세요.",
+ "d56d3629f4": "Orca가 해당 워크스페이스에서 계정으로 액세스할 수 있는 모든 팀을 표시해야 하는 경우 전체 액세스를 선호합니다. 제한된 키는 허용된 팀만 노출하며 비공개 팀에서는 키 소유자에게 액세스 권한이 필요합니다.",
+ "af52a6227f": "계정 > 보안 및 액세스에서 개인 API 키를 생성하세요.",
+ "edec49dfae": "린_아피_...",
+ "7d498f653c": "개인 API 키",
+ "57a66522c8": "연결",
+ "c9889a09f8": "키를 생성하기 전에 Linear를 사용하여 원하는 워크스페이스를 선택하세요.",
+ "e689a4d0a6": "오류"
+ }
+ }
+ },
+ "priority": {
+ "icon": {
+ "c43d3e065b": "우선 사항:"
+ }
+ },
+ "project": {
+ "view": {
+ "surfaces": {
+ "8bbecb2510": "없음",
+ "e1fa97d21d": "개요를 보려면 프로젝트를 선택하세요.",
+ "1748d3b9af": "라벨",
+ "65bda65159": "회원",
+ "c5f79616c3": "팀",
+ "25a2196732": "목표",
+ "3fb6473111": "시작",
+ "111bef9aa8": "선두",
+ "3be47aed6f": "우선 사항",
+ "f5ef24cf46": "건강",
+ "9ddb58edbd": "상태",
+ "0a6a5a7dd6": "최신 업데이트",
+ "c8db98b73b": "자원",
+ "bb1405eff8": "이정표",
+ "5d99315fb8": "계획",
+ "3ad562bdf4": "범위가 지정된 이슈",
+ "563501f191": "진전",
+ "bb5664d456": "프로젝트 설명이 없습니다.",
+ "7b147907dc": "Linear",
+ "a9785c7158": "새로고침",
+ "ee3d2caabd": "이슈",
+ "5f79bc76b0": "프로젝트로 돌아가기",
+ "aac9a4afc6": "Linear에서 열기",
+ "7616c986c6": "{{value0}} 이슈 열기",
+ "93e1f6bfca": "로드 중",
+ "98730088a6": ". 전체 세트를 보려면 Linear를 검색하거나 엽니다.",
+ "06b887d622": "먼저 표시",
+ "2c4b1c2c08": "숫자",
+ "f2cc1e0ff6": "Linear / 프로젝트",
+ "906b5e4cb8": "Linear / 프로젝트 / {{value0}}",
+ "85607ff793": "프로젝트",
+ "20b9d09b7d": "알려지지 않은",
+ "f059181bd9": "사적인",
+ "27d91cb1a6": "공유됨",
+ "9f0f51fd9e": "Linear에서 뷰를 생성하거나 저장한 후 새로 고칩니다.",
+ "f4c79cff5f": "아래 워크스페이스 오류를 확인한 후 새로고침하세요.",
+ "ef90b21366": "조회수를 찾을 수 없습니다.",
+ "c0a50f96a4": "보기를 로드할 수 없습니다.",
+ "df4bd63c1d": "할당되지 않음",
+ "30402d2c6e": "검색하거나 새로고침해 보세요.",
+ "a2f31c4cd6": "Linear 프로젝트를 찾을 수 없습니다.",
+ "c9b6e9f90d": "Linear 프로젝트를 로드할 수 없습니다."
+ }
+ }
+ },
+ "scope": {
+ "selector": {
+ "91c8871dad": "팀 액세스 추가",
+ "7783361266": "모든 팀",
+ "e1ae6bebb0": "팀",
+ "a14ce4df2b": "모든 워크스페이스",
+ "05baa5ae90": "워크스페이스",
+ "89f6580dbf": "수색팀...",
+ "b3488fad3c": "가져온 팀이 없습니다. 액세스는 키 범위, 비공개 팀 멤버십, 보관된 팀, 권한 또는 가져오기 실패에 따라 달라질 수 있습니다.",
+ "405b33c378": "가져온 팀이 검색어와 일치하지 않습니다."
+ }
+ }
+ },
+ "notification": {
+ "sound": {
+ "options": {
+ "e38b0a2e68": "삑 하는 소리",
+ "0acd3d384e": "수다",
+ "79919c832d": "땡땡",
+ "2b44847d8d": "블롭",
+ "020826ef17": "소나",
+ "588c90487d": "블립",
+ "1e4b81d892": "딸꾹질",
+ "86af8d938c": "봉",
+ "80f7cc95b3": "투톤",
+ "017abebfa6": "시스템 기본값"
+ }
+ }
+ },
+ "worktree": {
+ "creation": {
+ "WorktreeCreationPanel": {
+ "dabd226118": "닫기",
+ "34dd5ee38b": "다시 시도",
+ "ed2a664f8b": "작업 트리를 만들 수 없습니다.",
+ "a3346fc6ed": "작업 트리 생성 취소",
+ "532aea14ce": "취소",
+ "767951265d": "작업 트리를 만드는 중에 문제가 발생했습니다."
+ }
+ }
+ },
+ "workspace": {
+ "space": {
+ "WorkspaceSpacePage": {
+ "8d0048e1cb": "워크스페이스 디스크 사용량 및 회수 가능한 작업 트리 스토리지.",
+ "e8d6ba11ab": "베타",
+ "45f6302dbc": "공간",
+ "ecf72fdc3b": "뒤로"
+ }
+ },
+ "cleanup": {
+ "WorkspaceCleanupDialog": {
+ "3828408538": "{{value0}} 제거",
+ "352f15d6fc": "마지막 활동",
+ "cbf2f664e2": "삭제",
+ "b6bae1eed1": "취소",
+ "592fbab446": "가장 오래된 활동을 기준으로 정렬",
+ "dba753e94f": "삭제",
+ "38ca0b1400": "그러면 로컬 파일이 영구적으로 삭제됩니다. 이 작업은 취소할 수 없습니다.",
+ "c4f4782c02": "제안되지 않음",
+ "0a2e3c7cba": "리뷰",
+ "e97e4580c7": "더러운",
+ "9623a5107d": "푸시되지 않은 커밋",
+ "e8b3741ff7": "무시됨",
+ "a9957007eb": "{{value0}} 무시",
+ "1bffc07ba7": "{{value0}} 보기",
+ "bef0adef9b": "브랜치",
+ "0b1766738a": "레포",
+ "bbb1ab6a6f": "{{value0}}을(를) 선택하세요",
+ "d1094dd529": "리뷰 필요",
+ "4b93a235d8": "제안",
+ "f68d538c63": "이 정리 세트에는 워크스페이스가 없습니다.",
+ "4719327c9c": "모든 정리 제안은 무시됩니다.",
+ "a19040cd67": "선택한 저장소와 일치하는 비활성 워크스페이스가 없습니다.",
+ "97c772c4fe": "확인된 저장소에 비활성 워크스페이스가 없습니다.",
+ "d3eef9463d": "삭제할 비활성 워크스페이스가 없습니다.",
+ "aaee139eab": "무시된 제안 복원",
+ "06cf78521e": "{{value0}}에서 모두 선택",
+ "73690b0031": "{{value0}}에서 모두 선택 취소",
+ "b771c92598": "선택 항목 삭제",
+ "37ab28277e": "제안되지 않음",
+ "1b18868569": "리뷰 필요",
+ "b299f201b9": "안전하게 제거 가능",
+ "2b31bf68de": "비활성",
+ "ac5ba84cc1": "선택된",
+ "8b74d4ea6e": "작업 트리 및 Git 상태를 스캔한 다음 삭제를 제안하기 전에 열린 탭, 터미널, 라이브 에이전트 및 원격 가용성 신호를 결합합니다.",
+ "7eee951968": "작업장 안전 확인",
+ "191f0bc98e": "닫기",
+ "7ae2ad30f4": "새로고침",
+ "e0b5a4deaa": "로컬 파일과 Orca 상태를 삭제하기 전에 비활성 워크스페이스를 확인하세요.",
+ "b2c1331844": "비활성 워크스페이스 삭제",
+ "41d594d01e": "{{value0}} 워크스페이스{{value1}}을(를) 제거할 수 없습니다.",
+ "0f00612b6d": "{{value0}} 워크스페이스{{value1}}을(를) 삭제했습니다.",
+ "7f451a3e2c": "정리 제안을 무시할 수 없습니다.",
+ "662b8ec3f8": "워크스페이스 정리 검사 실패",
+ "bc43c37faf": "숨겨진",
+ "0c6672f5e3": "무시된 정리 제안",
+ "fc49f79434": "혼합된",
+ "2ddbd6fe8a": "확인됨"
+ }
+ }
+ },
+ "ui": {
+ "color": {
+ "picker": {
+ "ebcf6ba29e": "16진수 색상이 잘못되었습니다.",
+ "faa855a582": "마녀",
+ "1cec618bcc": "{{value0}} 선택기"
+ }
+ },
+ "dialog": {
+ "f26c4baeda": "닫기"
+ },
+ "repo": {
+ "multi": {
+ "combobox": {
+ "286ce70256": "SSH",
+ "4471d4a1c0": "검색어와 일치하는 프로젝트가 없습니다.",
+ "bfd8ce21c6": "모든 프로젝트",
+ "a58a0cd100": "프로젝트 검색...",
+ "65a3dae41d": "프로젝트 없음"
+ }
+ }
+ },
+ "sheet": {
+ "1189e9fe0a": "닫기"
+ },
+ "team": {
+ "multi": {
+ "combobox": {
+ "de83523bf9": "검색어와 일치하는 팀이 없습니다.",
+ "301f2a796e": "모든 팀",
+ "18ec58881e": "수색팀..."
+ }
+ }
+ }
+ },
+ "terminal": {
+ "quick": {
+ "commands": {
+ "TerminalQuickCommandActionToggle": {
+ "b0d58e37ed": "에이전트 프롬프트",
+ "b5ea4d64f6": "터미널 명령"
+ },
+ "TerminalQuickCommandAppendEnterSwitch": {
+ "e4e5fed3b3": "추가 추가 Enter 전환",
+ "c936c2d6d2": "텍스트만 삽입하는 대신 즉시 제출하세요.",
+ "5fa607d807": "추가 Enter"
+ },
+ "TerminalQuickCommandDialog": {
+ "925b8e0f6e": "고급",
+ "97e96cc027": "/목표",
+ "e604bd40d6": "다음과 같은 스킬, 파일 경로 및 내장 명령을 지원합니다.",
+ "79af0c0841": "npm 실행 개발자",
+ "577a342c7d": "에이전트에게 이 워크스페이스를 조사하도록 요청하세요.",
+ "026cfb232a": "프롬프트 명령을 지원하지 않습니다",
+ "346d409ab2": "에이전트 선택",
+ "0adba8fa0c": "에이전트",
+ "ec8f081919": "행동",
+ "ed04233b3e": "빠른 액세스를 위해 터미널 명령이나 에이전트 프롬프트를 저장하세요.",
+ "ca414324ee": "명령 텍스트",
+ "dc921c17ee": "즉각적인",
+ "5b3f634a55": "빠른 명령 추가",
+ "f9b184fc16": "빠른 명령 편집",
+ "6751598542": "편집"
+ },
+ "TerminalQuickCommandDialogFooter": {
+ "2e2b958dfc": "저장",
+ "8dff838dea": "저장({{value0}})",
+ "28370f16b9": "취소"
+ },
+ "TerminalQuickCommandLabelField": {
+ "66ea254301": "개발 서버 시작",
+ "db17f1e41e": "상표"
+ },
+ "TerminalQuickCommandScopeField": {
+ "2db6edede7": "저장하면 다른 프로젝트 범위를 선택하지 않는 한 기존 프로젝트 범위가 유지됩니다.",
+ "2496523a6f": "프로젝트 선택",
+ "2264edd5d3": "목록에 없는 프로젝트",
+ "3834d24243": "프로젝트",
+ "b83efc79e2": "글로벌",
+ "c25cf350ef": "범위",
+ "f0631e4999": "레포"
+ }
+ }
+ },
+ "pane": {
+ "CloseTerminalDialog": {
+ "ebd2fa844d": "닫기",
+ "1d1a7a9c1f": "취소",
+ "6b9a6975f8": "터미널에는 여전히 실행 중인 프로세스가 있습니다. 터미널을 닫으면 프로세스가 종료됩니다.",
+ "78b79d854d": "터미널을 닫으시겠습니까?"
+ },
+ "MobileDriverOverlay": {
+ "c6460cf584": "회수",
+ "c44659e09f": "모바일 원격 조작",
+ "7cffad954c": "접기",
+ "3eed73394f": "키보드가 일시중지되었습니다.",
+ "faa367dc74": "이 터미널은 모바일 앱에 맞게 크기가 조정됩니다."
+ },
+ "TerminalAgentSessionForkDialog": {
+ "17fc841e59": "컨텍스트 복사",
+ "0c8a8629b1": "포크는 중첩된 하위 항목이 아닌 자체 워크스페이스로 나타납니다. 새 에이전트는 편집 가능한 초안으로 한정된 기록을 받습니다.",
+ "620461df22": "최상위 포크",
+ "619b5a35d2": "최상위 워크스페이스 포크를 만들고 캡처된 컨텍스트로 새 에이전트 탭을 시작합니다.",
+ "64e292e8e3": "포크 에이전트 세션",
+ "9d25de2920": "포크 만들기",
+ "2b10412cfc": "만드는 중..."
+ },
+ "TerminalContextMenu": {
+ "b4cdd9314e": "화면 지우기",
+ "8c17d6786d": "창 닫기",
+ "2cf85a6a55": "창 ID 복사",
+ "39809d152f": "제목 설정…",
+ "06c2b0f043": "창 크기 균등화",
+ "98bccf4fa2": "터미널을 아래로 분할",
+ "20e565d865": "터미널 오른쪽 분할",
+ "8a7ddb8b8a": "포크 에이전트 세션…",
+ "0a82b0608c": "빠른 명령 추가...",
+ "9528a65ef8": "빠른 명령 없음",
+ "3ce594a4a0": "글로벌",
+ "ec85df5914": "빠른 명령어",
+ "0a917b591a": "반죽",
+ "f3eeb1de13": "복사",
+ "c2f0b72b8d": "끼워 넣다",
+ "925f49f210": "창 확장",
+ "df766809e0": "창 축소"
+ },
+ "TerminalErrorToast": {
+ "e4aa243f8c": "데몬 재시작",
+ "a7e2fd2699": "이슈 등록",
+ "5c8ce20be6": "이것이 지속된다면, 제발",
+ "cc6d997c65": "오래된 데몬 상태를 지우려면 여기에서 터미널 데몬을 다시 시작하세요."
+ },
+ "TerminalPane": {
+ "ac112e9036": "제목 삭제",
+ "f984ab2a30": "창 제목 제거: {{value0}}",
+ "cc5a2dc706": "창 제목 수정: {{value0}}",
+ "7dbbfcbecc": "창 제목"
+ },
+ "TerminalSessionStateSaveFailureDialog": {
+ "6bee0c8f17": "오픈 디스크 공간 분석기",
+ "ae20d0ffc2": "닫기",
+ "38c282a2c4": "분석기는 여기에서 직접 열립니다. 나중에 공간 분석기를 선택하여 왼쪽 하단 도구 상자 메뉴에서 열 수도 있습니다.",
+ "e2fcf07c0d": "로컬 저장소가 가득 찼거나 쓸 수 없기 때문에 Orca가 이 터미널 세션을 저장할 수 없습니다. 디스크 공간 분석기를 열어 정리할 수 있는 워크스페이스 저장소를 찾으세요.",
+ "678c780a2c": "디스크 공간을 사용할 수 없습니다."
+ },
+ "osc52": {
+ "clipboard": {
+ "blocked": {
+ "toast": {
+ "97c98f1afe": "설정 열기",
+ "7cf51f74fd": "SSH, tmux, Neovim 또는 fzf에서 복사하려면 터미널 설정에서 TUI 클립보드 쓰기를 활성화하세요.",
+ "89eaa3e80b": "터미널 클립보드 쓰기가 차단되었습니다."
+ }
+ }
+ }
+ },
+ "stale": {
+ "agent": {
+ "row": {
+ "ad991ece5c": "에이전트 창을 더 이상 사용할 수 없습니다.",
+ "090d607412": "오래된 에이전트 행-{{value0}}"
+ }
+ }
+ },
+ "terminal": {
+ "agent": {
+ "session": {
+ "fork": {
+ "2317900211": "포크 컨텍스트를 복사하지 못했습니다.",
+ "88e34d00eb": "새 워크스페이스에서 열린 최상위 세션 포크",
+ "fd3d12a1e1": "포크 워크스페이스를 생성하지 못했습니다.",
+ "38e41edc6e": "이 워크스페이스는 git 작업 트리로 포크할 수 없습니다.",
+ "f867385bb5": "이 포크의 소스 워크스페이스를 찾을 수 없습니다.",
+ "046e8d853c": "포크할 터미널 컨텍스트가 없습니다.",
+ "c00421d320": "포크 컨텍스트가 복사되었습니다. 에이전트를 실행하고 붙여넣어 포크를 시작합니다."
+ }
+ }
+ },
+ "drop": {
+ "handler": {
+ "1e072f611e": "{{value0}} {{value1}}을(를) 업로드하지 못했습니다.",
+ "53f015fd85": "{{value0}} 심볼릭 링크{{value1}}을 건너뛰었습니다.",
+ "29c031b49a": "{{value0}} 파일{{value1}}을 런타임에 업로드하는 중…",
+ "0c77693641": "Worktree가 준비되지 않았습니다. 잠시 후에 다시 시도하세요.",
+ "ce8248b835": "작업 트리 경로를 사용할 수 없습니다."
+ }
+ }
+ },
+ "use": {
+ "terminal": {
+ "pane": {
+ "context": {
+ "menu": {
+ "a29b9faa01": "창 ID가 복사되었습니다."
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tab": {
+ "group": {
+ "TabGroupPanel": {
+ "814fb04c43": "편집기 로드 중...",
+ "f7d6ce445e": "그룹 닫기",
+ "0db2081805": "분할",
+ "30137df7d0": "왼쪽으로 분할",
+ "4df2a06d36": "분할",
+ "ab1e2bff04": "오른쪽 분할",
+ "9acaf92093": "창 작업",
+ "1bce81dba6": "시뮬레이터",
+ "1ff1c77616": "브라우저",
+ "586d2ac445": "터미널"
+ }
+ },
+ "bar": {
+ "BrowserTab": {
+ "6e0bc8f3a8": "브라우저에서 열기",
+ "9dd880bd56": "오른쪽으로 탭 닫기",
+ "1611a1324b": "닫기",
+ "5d6e89891f": "탭 복제",
+ "966feb9ad5": "오른쪽 분할",
+ "7e8106899f": "왼쪽으로 분할",
+ "2186a8407c": "분할",
+ "96354ed249": "분할",
+ "911542656f": "핀 탭",
+ "c5aaee8c39": "탭 고정 해제"
+ },
+ "EditorFileTab": {
+ "3da7445c84": "파일 이름 바꾸기 {{value0}}"
+ },
+ "EditorFileTabContextMenu": {
+ "52ce4f4605": "상대 경로 복사",
+ "5b85754786": "경로 복사",
+ "bfd5797ef4": "마크다운 미리보기 열기",
+ "e5ff31ccaf": "오른쪽으로 탭 닫기",
+ "ba1369dd24": "모든 편집기 탭 닫기",
+ "1ba8492c5b": "닫기",
+ "68cc610e7f": "이름 바꾸기",
+ "f7c3d7d5af": "오른쪽 분할",
+ "e3ff145b98": "왼쪽으로 분할",
+ "1d04b1630b": "분할",
+ "6b3efb106e": "분할",
+ "fdd29eb669": "핀 탭",
+ "8e9d603a09": "탭 고정 해제"
+ },
+ "QuickLaunchButton": {
+ "348a04c1ad": "에이전트 설정…",
+ "ec2adf093e": "새 터미널에서 {{value0}} 실행",
+ "465e432ef1": "{{value0}}에 대한 실행 명령을 작성할 수 없습니다.",
+ "e518f544b1": "감지된 에이전트가 없습니다.",
+ "8dea9b5cdf": "활성화된 에이전트가 없습니다."
+ },
+ "RecentTabSwitcher": {
+ "329638ff6f": "스위치 탭",
+ "07ad4cd0b7": "탭 전환"
+ },
+ "SortableTab": {
+ "ab19f603eb": "탭 이름 바꾸기 {{value0}}",
+ "6df69d9388": "탭 닫기 {{value0}}",
+ "fdb2691425": "창 축소"
+ },
+ "SortableTabContextMenu": {
+ "35e8892fd0": "탭 색상",
+ "2f697b3c31": "제목 변경",
+ "c1ee099c7e": "오른쪽으로 탭 닫기",
+ "8d16f9cd30": "기타 닫기",
+ "89359a36f7": "닫기",
+ "21132389e9": "오른쪽 분할",
+ "0ce4bae39d": "왼쪽으로 분할",
+ "af80ed83c1": "분할",
+ "591f9b12c1": "분할",
+ "7703990447": "회색",
+ "845576bed1": "물오리",
+ "be905e9b0a": "녹색",
+ "69682e2ce4": "노란색",
+ "a47629b3cf": "주황색",
+ "620aec6729": "빨간색",
+ "03cf6dab1a": "분홍색",
+ "c2d8b0991f": "보라",
+ "cb3eadefd2": "파란색",
+ "20baa43c05": "없음",
+ "60f958ec75": "핀 탭",
+ "417722e9c2": "탭 고정 해제"
+ },
+ "TabBar": {
+ "b1a132357f": "새 탭",
+ "4f327c8b3d": "마크다운 열기...",
+ "3d5d6c960d": "새로운 마크다운",
+ "fd2b42aaa3": "새로운 모바일 에뮬레이터",
+ "aea43b5748": "기존 에뮬레이터 탭을 엽니다.",
+ "b426bb2615": "모바일 에뮬레이터로 이동",
+ "4833fb2cbe": "새 브라우저 탭",
+ "d364f3c8d4": "새로운 터미널",
+ "7c1313d237": "새로운 터미널:",
+ "d1afac112b": "WSL",
+ "efb33546ff": "힘내 배쉬",
+ "1a8af49530": "CMD 프롬프트",
+ "2148f65e04": "파워셸",
+ "ab589350e5": "{{value0}}에 대한 실행 명령을 작성할 수 없습니다."
+ },
+ "TabBarCreateEntry": {
+ "d62d63b807": "파일 생성",
+ "25dc1cd653": "파일 열기",
+ "7cdf8ee0c8": "URL 열기",
+ "b27864279e": "에이전트 실행",
+ "39676a184c": "모든 파일, URL, 에이전트를 엽니다..."
+ },
+ "TabBarQuickCommandsButton": {
+ "a2c7a33831": "명령 추가",
+ "20bbd75896": "명령 없음",
+ "b82e237a4b": "더 빠른 명령",
+ "85482c57bc": "빠른 명령 실행",
+ "b775303755": "빠른 명령 실행: {{value0}}",
+ "196593b6a9": "{{value0}} 제거",
+ "15529ede69": "{{value0}} 편집",
+ "1d411fb6a5": "이 저장소에 대한 빠른 명령 저장",
+ "8f1e971966": "빠른 명령 추가",
+ "3220e2da27": "이 빠른 명령은 저장된 목록에서 제거됩니다.",
+ "e8e1a52edb": "'{{value0}}'을 삭제하시겠습니까?",
+ "37e1bb90ce": "실행: {{value0}}",
+ "77ac113df0": "시작 {{value0}}: {{value1}}",
+ "7b1c9d6ae1": "달리다",
+ "c781f992e4": "파괴적인",
+ "be8f0ff166": "삭제"
+ },
+ "shell": {
+ "icons": {
+ "d4ceaa227c": "힘내",
+ "e9b2e70613": "WSL"
+ }
+ },
+ "tab": {
+ "create": {
+ "entry": {
+ "classifier": {
+ "42e6262ae9": "사용할 수 있는 작업이 없습니다.",
+ "097a982ee0": "파일 로드 중...",
+ "5a9c83c04b": "모든 파일, URL, 에이전트를 엽니다...",
+ "90eb94dc48": "http:// 또는 https:// URL을 입력하세요.",
+ "5553b283ce": "URL 또는 파일 경로를 입력하세요."
+ }
+ }
+ }
+ }
+ }
+ },
+ "status": {
+ "bar": {
+ "PetStatusSegment": {
+ "3668339495": "{{value0}} 제거",
+ "cd8c6c654c": "애완동물 설정…",
+ "ed176ad68f": ".codex-pet 번들 가져오기…",
+ "59b5955621": "직접 업로드하세요…",
+ "0608ad02a2": "애완동물 선택",
+ "b75484a01a": "애완동물 크기",
+ "c6aa805b1b": "px",
+ "2f7bbaa457": "크기",
+ "34c25dfe9c": "애완 동물",
+ "aec479308a": "애완동물 메뉴",
+ "cef0ab4636": "애완동물 번들을 가져오지 못했습니다.",
+ "2021d4f6db": "Pet 번들 가져오기에는 전체 앱을 다시 시작해야 합니다(단순히 다시 로드하는 것이 아님).",
+ "f395c9a685": "파일을 가져오지 못했습니다.",
+ "e6234bcc17": "맞춤 애완동물 업로드에는 앱 전체를 다시 시작해야 합니다(단순히 다시 로드하는 것이 아님).",
+ "6d0a8cd179": "애완동물 표시",
+ "1fbc51cc77": "애완동물 숨기기"
+ },
+ "PortsStatusSegment": {
+ "4ebf90c12e": "외부 포트가 감지되지 않았습니다.",
+ "7dac3ecc9d": "외부 포트",
+ "95495019ed": "다음에서 포트 스캔을 사용할 수 없습니다.",
+ "a8e4bdb412": "· {{value0}} 외부",
+ "9aa11005bf": "워크스페이스 ·",
+ "c22ea609fd": "포트",
+ "a11ed266ce": "워크스페이스",
+ "ca41be2802": "포트 —",
+ "b8bc3e420a": "포트, {{value0}} 워크스페이스 {{value1}}",
+ "3a87d54dfb": "워크스페이스 포트가 감지되지 않았습니다.",
+ "c174bbbfed": "워크스페이스 포트를 검색하는 중...",
+ "8caaa86e9a": "포트",
+ "45834a9ace": "포트"
+ },
+ "ResourceUsageStatusSegment": {
+ "946d9f94d0": "취소",
+ "67c4ecda49": "이 터미널을 강제 종료합니다. 창에서 저장하지 않은 작업은 모두 손실됩니다. 이 작업은 취소할 수 없습니다.",
+ "4bb076fa89": "강제 종료",
+ "996295bff2": "고아 터미널",
+ "92924a14e3": "비활성 워크스페이스 확인(",
+ "27a74f91f0": "지금은 실행 중인 항목이 없습니다.",
+ "1b24a32d3a": "메모리",
+ "298f4be7f2": "CPU",
+ "2aa2de6cb9": "이름",
+ "30ff2c3c31": "유아",
+ "6449a95c78": "Orca 추적 프로세스가 사용 중인 이 시스템의 물리적 RAM 크기입니다.",
+ "e7ccce7e87": "시스템 RAM",
+ "9e2525c89f": "Orca가 보유한 상주 메모리와 각 작업 트리 터미널 아래의 프로세스입니다.",
+ "1fedf94eae": "결합된 CPU 로드. 100%를 초과하는 값은 두 개 이상의 코어가 동시에 작동하고 있음을 의미합니다.",
+ "e7cf14ec78": "터미널 세션을 사용할 수 없습니다. 목록이 오래되었을 수 있습니다.",
+ "93b0de3c21": "다시 시작",
+ "f85af9cda6": "리소스 스냅샷과 터미널 세션을 사용할 수 없습니다.",
+ "f8e0d794b4": "데몬이 응답하지 않습니다",
+ "bd19fd7a59": "모든 세션 종료",
+ "c9382662bb": "데몬 재시작",
+ "59f178fe11": "{{value0}}, 데몬에 연결할 수 없습니다.",
+ "21cacb16d1": "· 원격",
+ "73a3fd68a9": "저장소 접기",
+ "b12e31dfcb": "저장소 확장",
+ "d659d71d2d": "워크스페이스 {{value0}} 재개",
+ "bbcd9b7b85": "워크스페이스 축소",
+ "c4a8968bdd": "워크스페이스 확장",
+ "b10695d6ce": "세션 종료",
+ "288a4dd177": "Orca",
+ "53dd5560ae": "Orca 접기",
+ "e419d27083": "Orca 확장",
+ "41ae4fa725": "종료 중…",
+ "138b99bd80": "이번 세션",
+ "888dad8c55": "로드 중…",
+ "56b6888304": "런타임 서버에 대한 로컬 리소스 사용량이 숨겨졌습니다.",
+ "14ff448686": "런타임 서버에서는 사용할 수 없습니다.",
+ "6d9793d4bc": "리소스 관리자 - 터미널",
+ "6a822b06a7": "자원 관리자",
+ "ca95d077db": "데몬에 연결할 수 없음",
+ "a82253b458": "워크스페이스를 삭제합니다.",
+ "946724a70a": "기본 워크스페이스는 삭제할 수 없습니다.",
+ "16bc3c998a": "워크스페이스 삭제 {{value0}}",
+ "0f9e50eb07": "다른",
+ "d406915b78": "렌더러",
+ "81cd37af99": "기본"
+ },
+ "SshStatusSegment": {
+ "3ad70e0365": "SSH 관리…",
+ "6e8a9a4242": "SSH 연결",
+ "d09ec41831": "SSH",
+ "fdc57e9970": "SSH 연결 상태",
+ "59b553e2aa": "연결 해제",
+ "63f36455cc": "연결",
+ "bf07aee59e": "연결 해제 실패",
+ "2c29e2de68": "연결 실패",
+ "bc5a3fd41a": "부분 연결",
+ "3d0128b105": "연결됨",
+ "fd9a3c600e": "오류",
+ "fbb3f9f05e": "충돌",
+ "95e4ff5b4b": "푸시 중",
+ "63a2b965f6": "가져오는 중"
+ },
+ "StatusBar": {
+ "9659e38343": "포트",
+ "d1e1a7a6bf": "리소스 관리자",
+ "24ac89df1a": "SSH 상태",
+ "5e59007df4": "Kimi 사용량",
+ "8c86cd77b0": "OpenCode Go 사용량",
+ "c1df0d67ec": "Gemini 사용량",
+ "c0909c686e": "Codex 사용량",
+ "3885eb74d8": "Claude 사용량",
+ "c8857b40f7": "사용량 데이터 새로 고침",
+ "75ded02687": "계정 관리…",
+ "ff0fbe9311": "활성",
+ "7657e3db9c": "Codex 계정",
+ "38b5647724": "Codex 사용 런타임",
+ "ba55303942": "Codex 세부정보 및 계정 전환 도구 열기",
+ "4dff061aab": "·",
+ "2483c60695": "···",
+ "c35af53b73": "로그인",
+ "f19a63e7cd": "사용량을 보려면 로그인하세요.",
+ "5c938d39ac": "%주간",
+ "d79c3362c4": "% 5h",
+ "8295903d17": "전환 후 이전 대화를 계속하기 전에 라이브 Claude 터미널을 다시 시작하십시오.",
+ "c98ea88392": "다른 계정 없음",
+ "9332ba8684": "다음으로 전환",
+ "d450654fa2": "Claude 계정",
+ "11e2354daf": "Claude 사용 런타임",
+ "3dd7ddfae1": "Claude 세부정보 및 계정 전환 도구 열기",
+ "59c6e7b4e0": "보이는 세션은 지금 다시 시작됩니다. 나머지는 해당 작업 트리가 활성화될 때 다시 시작됩니다.",
+ "c676918adc": "시스템 기본값",
+ "3325d996cb": "사용 한도 새로고침",
+ "fda8146810": "Kimi 사용 세부정보 열기",
+ "629251f4b6": "OpenCode Go 사용 세부정보 열기",
+ "d2375976eb": "Gemini 사용 세부정보 열기",
+ "3d79122c3f": "kimi",
+ "d7a0668acc": "opencode-go",
+ "68efc0345c": "gemini",
+ "76b06d4da5": "claude",
+ "a28a5dd9b1": "오류",
+ "cd9d7b40ff": "{{value0}} 세션 다시 시작",
+ "6cd6650b4c": "세션 다시 시작",
+ "1446d0d8a0": "{{value0}} Codex 세션은 여전히 이전 계정에 있습니다.",
+ "605901a495": "1개의 Codex 세션이 여전히 이전 계정에 있습니다."
+ },
+ "StatusBarUsageEmptyCta": {
+ "828c764a79": "계정 연결",
+ "caa0f39811": "지원:",
+ "97957ad3a3": "AI 공급자 계정을 연결하면 실시간으로 사용량을 확인하고 계정 간을 쉽게 전환할 수 있습니다.",
+ "9a542f46c7": "상태 표시줄에서 숨기기",
+ "84c3b15dca": "에이전트 사용량 한도",
+ "d663430cf9": "사용량을 확인하려면 AI 계정을 연결하세요."
+ },
+ "UpdateStatusSegment": {
+ "5cd13105a3": "업데이트에 실패했습니다. 확장하려면 클릭하세요.",
+ "2201df6987": "업데이트 실패 - 세부정보를 보려면 클릭하세요.",
+ "8533c12c3c": "업데이트 실패",
+ "962404f68e": "업데이트 설치 준비가 완료되었습니다. 확장하려면 클릭하세요.",
+ "248ee5d8ef": "Orca v{{value0}} 다운로드 중… {{value1}}%",
+ "57a29c3b0e": "업데이트 준비됨",
+ "fd1d3b3a1d": "업데이트 다운로드 중, {{value0}}퍼센트. 확장하려면 클릭하세요."
+ },
+ "WorkspaceSpaceCompactPanel": {
+ "a471aa9c24": "업데이트됨",
+ "9be86c46a0": "무료 가능",
+ "f4d2651498": "스캔됨",
+ "6a5dc3c61a": "리뷰",
+ "c361440dc0": "베타",
+ "8ff597593d": "공간",
+ "0582df6d2e": "주사",
+ "f5e1a84d79": "새로고침",
+ "2af2174d6d": "취소",
+ "5691353a21": "멎는",
+ "2837dc7c72": "취소 중",
+ "0583c806ac": "워크스페이스 디스크 사용량은 스캔되지 않습니다.",
+ "39786e3b73": "워크스페이스 크기를 스캔하는 중입니다.",
+ "bef4dc0457": "{{value0}} 회수 가능 · {{value1}} 사용 불가",
+ "3d8d47ce77": "{{value0}} · 마지막 결과가 유지됨"
+ },
+ "WorkspaceSpaceManagerPanel": {
+ "2965415393": "강제 삭제 실패",
+ "e031e93219": "일치하는 워크스페이스가 없습니다.",
+ "a02d84d2d2": "워크스페이스를 스캔 중입니다. 이 페이지를 떠날 수 있습니다.",
+ "be37293b10": "상태",
+ "33aef3e9cc": "크기",
+ "81f14d9924": "저장소",
+ "e4aebea158": "워크스페이스",
+ "1d0f8300d1": "표시되는 삭제 가능한 워크스페이스 선택",
+ "697d60c456": "보이는 선택 항목 지우기",
+ "81aaf1de65": "삭제 가능한 워크스페이스만 표시",
+ "d7ac56452e": "활동",
+ "243287ac60": "이름",
+ "6f8f6a6b04": "워크스페이스 필터링",
+ "5caccea440": "선택 항목 삭제",
+ "e4a12c455b": "지우기",
+ "0cb1501ccf": "회수 가능",
+ "65402b7192": "선택된",
+ "43171f3e60": "워크스페이스",
+ "83f1a0a932": "회수 가능",
+ "09960d86bd": "스캔됨",
+ "1cc6cd4c0f": "워크스페이스",
+ "02b27c2230": "워크스페이스",
+ "63efebe0e6": "{{value0}} {{value1}}이(가) 우주에서 제거되었습니다.",
+ "eee5240810": "워크스페이스가 삭제되었습니다.",
+ "9afc97f9a3": "워크스페이스가 삭제되었습니다.",
+ "792a214457": "워크스페이스 삭제",
+ "a998501630": "힘",
+ "9155381019": "부족한",
+ "f39d291997": "선택",
+ "16988df079": "파일을 찾을 수 없습니다.",
+ "b25c2c1086": "최상위 항목",
+ "d3f9c69ddc": "줌",
+ "ef890d31b9": "모두",
+ "c28643d3da": "워크스페이스로 이동",
+ "66870929fb": "이슈",
+ "fb2069acb7": "리뷰",
+ "b9b4a3a25d": "브랜치",
+ "c432278ec7": "편집기 버퍼",
+ "0bc756efaf": "힘내 변경",
+ "e9528a89b3": "터미널",
+ "a8d9e0de79": "에이전트",
+ "d384a4ce9f": "결정 삭제",
+ "7d7745bb8f": "삭제할 수 있음",
+ "720870a18e": "유지: 연결됨",
+ "cbc343a7a8": "유지: 사용 중",
+ "2055bc6a5a": "유지: 저장되지 않은 수정사항",
+ "ec7b076a75": "유지: git이 확인되지 않음",
+ "7ab8d7e2d7": "유지: 변경된 파일",
+ "7f7895514e": "유지: 활성",
+ "2b501ee391": "유지: 메인",
+ "39801484e0": "실패한",
+ "33653dbac2": "삭제 중",
+ "52b629eb84": "업데이트됨",
+ "e91dd2a9ae": "워크스페이스 크기를 검사하려면 스캔을 실행하세요.",
+ "61e25239da": "스캔에서 사용 가능한 워크스페이스 행이 없습니다.",
+ "8194a4fb29": "워크스페이스 크기가 수집되기 전에 스캔이 실패했습니다.",
+ "b2f82ed5ae": "삭제 가능",
+ "20a4204dce": "마지막으로 성공한 결과는 계속 표시됩니다.",
+ "8c7c57fbf8": "주사",
+ "508673bac0": "새로고침",
+ "8dc9ddac8a": "취소",
+ "1fce91d1b9": "멎는",
+ "d254f04097": "취소 중",
+ "265d956765": "{{value0}}. 이 페이지를 떠날 수 있습니다.",
+ "d595295d7d": "{{value0}}은(는) 연결된 작업 트리에서 회수될 수 있습니다.",
+ "34174bd83d": "{{value0}}. 이 페이지를 떠날 수 있습니다. 마지막 결과는 계속 표시됩니다.",
+ "433bb7f595": "좋아요",
+ "0ba046fbc5": "스캔에 실패했습니다.",
+ "5c6d25720c": "검사할 워크스페이스를 선택하세요.",
+ "c5135e7e4a": "워크스페이스 크기를 스캔하는 중입니다. 이 페이지를 떠날 수 있습니다.",
+ "0990a63160": "아직 스캔된 워크스페이스 크기가 없습니다.",
+ "977bdf9a36": "표시할 최상위 항목이 없습니다.",
+ "131662ac65": "{{value0}} 열려 있음"
+ },
+ "ports": {
+ "status": {
+ "popover": {
+ "rows": {
+ "a49ea79246": "작업 트리로 이동",
+ "f2b813345f": "워크스페이스를 사용할 수 없음",
+ "0e72c8d9fb": "프로세스 중지",
+ "536d48a5dc": "{{value0}} 복사",
+ "085f4f0334": "브라우저에서 열기",
+ "e4a709548c": "포트를 새로고침하지 못했습니다.",
+ "acdb6df590": "{{value0}}에서 프로세스가 중지되었습니다.",
+ "480d8f2347": "{{value0}} 복사됨",
+ "b854ec9ff5": "브라우저를 열지 못했습니다."
+ }
+ }
+ }
+ },
+ "tooltip": {
+ "cedb7b99e3": "% 남음",
+ "6d6df77f41": "데이터가 없습니다",
+ "7f7f208060": "월간",
+ "252c096536": "주간",
+ "94038ad2fa": "세션",
+ "2c35eca8d4": "사용량을 가져올 수 없습니다.",
+ "1292d4f2ee": "없는",
+ "7567cd1c6b": "이용불가",
+ "a9a318b7a3": "새로 고침 실패 - 캐시된 데이터 표시"
+ }
+ }
+ },
+ "stats": {
+ "ClaudeUsageDailyChart": {
+ "2a6360c7cb": "캐시 쓰기",
+ "61c58f8976": "캐시 읽기",
+ "7d2efeff5e": "출력",
+ "d7fb787e6b": "입력",
+ "a7902d3c1d": "토큰",
+ "059945f71d": "일별 입력, 출력, 캐시 읽기 및 캐시 쓰기 합계입니다.",
+ "c9f7cd30e9": "일일 사용량"
+ },
+ "ClaudeUsagePane": {
+ "21ea00bfa8": "캐시",
+ "a8b7487ff7": "출력",
+ "faf3444859": "입력",
+ "0f03975d59": "턴",
+ "1afc25eb06": "모델",
+ "c17bed0416": "프로젝트",
+ "01476891c7": "마지막 활동",
+ "abfc4a4943": "캐시 재사용률:",
+ "7e76c84153": "최근 세션",
+ "32176e1d44": "턴",
+ "02a046792e": "세션 •",
+ "f97435845c": "상위 프로젝트:",
+ "7dc9e5613b": "프로젝트별",
+ "c3fdbc5474": "상위 모델:",
+ "0f394c24e3": "모델별",
+ "51ae85fa00": "캐시 재사용률은 캐시 읽기 토큰 / (입력 토큰 + 캐시 읽기 토큰)로 계산됩니다.",
+ "b26d4ddb58": "예상 API와 동등한 비용",
+ "0f3e696ca9": "세션/턴",
+ "8cc23be4a3": "캐시 읽기 없는 턴",
+ "1634c4f404": "캐시 재사용률",
+ "b786fb4a70": "캐시 쓰기",
+ "268cf0af51": "캐시 읽기",
+ "2b8a2f14aa": "출력 토큰",
+ "ea71fae8fc": "입력 토큰",
+ "7dde9331fd": "이 범위에 대한 로컬 Claude 사용량이 아직 없습니다.",
+ "424cd50412": "Claude 사용량 분석 활성화",
+ "8d18bbb771": "새로고침",
+ "c5b9b344d0": "Claude 사용량 새로고침",
+ "505be9aac4": "기간",
+ "f61cffb9c8": "범위",
+ "dd29209b21": "필터",
+ "e9bf9fce0e": "Claude 사용 옵션",
+ "6afacbee37": "Claude 사용량 추적",
+ "0cb1a36d7d": "토큰, 모델 및 세션 통계를 표시하기 위해 로컬 Claude 사용 로그를 읽습니다.",
+ "5ce4842c2c": "모든 로컬 Claude 사용",
+ "4f8368c272": "Orca 작업 트리만 해당",
+ "cfe2282ffa": "알려지지 않은",
+ "7765a4c3e1": "해당 없음",
+ "2d41fd45c6": "• 마지막 스캔 오류: {{value0}}"
+ },
+ "CodexUsageDailyChart": {
+ "1e6f62d7e3": "추리",
+ "c646e1783c": "캐시된 입력",
+ "7b596a88b2": "출력",
+ "99a91d3143": "입력",
+ "e4bdcf0071": "토큰",
+ "c756cda6a8": "일별 입력, 캐시된 입력, 출력 및 추론 합계입니다.",
+ "609aa96e8b": "일일 사용량"
+ },
+ "CodexUsagePane": {
+ "e0b988599d": "총",
+ "bbd20344b8": "출력",
+ "3acc582214": "입력",
+ "bd0822ca47": "이벤트",
+ "c2478bcc3c": "모델",
+ "1a65900aea": "프로젝트",
+ "0c36b100be": "마지막 활동",
+ "0bd8655475": "이 범위의 가장 최근 로컬 Codex 세션입니다.",
+ "0cb0983c07": "최근 세션",
+ "79a69522a5": "이벤트",
+ "bf1bf2f674": "세션 •",
+ "829ee743f2": "상위 프로젝트:",
+ "b98718aaab": "프로젝트별",
+ "95d2d89285": "상위 모델:",
+ "5a0d1d69cd": "모델별",
+ "94ac1f1ee7": "가시성을 위해 추론 토큰이 표시되지만 비용은 캐시되지 않은 입력, 캐시된 입력 및 출력에서만 계산됩니다.",
+ "1a18fbd56b": "예상 API와 동등한 비용",
+ "907b31865f": "세션/이벤트",
+ "6e18146e9b": "추론 출력",
+ "a9ac0f423a": "캐시된 입력",
+ "5d8eba87bd": "출력 토큰",
+ "e365eaa6fd": "입력 토큰",
+ "4c865393b4": "이 범위에 대한 로컬 Codex 사용이 아직 발견되지 않았습니다.",
+ "f7c1affbd5": "Codex 사용량 분석 활성화",
+ "3022cda443": "새로고침",
+ "ec4d270e2c": "Codex 사용량 새로 고침",
+ "89162e019b": "기간",
+ "6d68e8399a": "범위",
+ "1af1a39b2f": "필터",
+ "70b5b8581f": "Codex 사용 옵션",
+ "408210470c": "Codex 사용 추적",
+ "13badcd8f2": "토큰, 모델 및 세션 통계를 표시하기 위해 로컬 Codex 사용 로그를 읽습니다.",
+ "4fe8820098": "모든 로컬 Codex 사용",
+ "201766b754": "Orca 작업 트리만 해당",
+ "bf6cf2d4dd": "알려지지 않은",
+ "ae255c3dba": "해당 없음",
+ "247c93ca92": "• 추론된 가격",
+ "8a6655f7a2": "• 마지막 스캔 오류: {{value0}}"
+ },
+ "OpenCodeUsagePane": {
+ "349f7c3f5c": "총",
+ "dfc4513657": "출력",
+ "0f2f266c9d": "입력",
+ "d416f5cf92": "이벤트",
+ "08c78441b7": "모델",
+ "a4738de041": "프로젝트",
+ "d97bdf6e27": "마지막 활동",
+ "81817a641a": "이 범위의 가장 최근 로컬 OpenCode 세션입니다.",
+ "4799177b1c": "최근 세션",
+ "1e5d410df0": "이벤트",
+ "bc0cb89901": "세션 •",
+ "048ffe4d65": "상위 프로젝트:",
+ "0f0a1684bb": "프로젝트별",
+ "a15206a63a": "상위 모델:",
+ "040c044d39": "모델별",
+ "e5bb23d85e": "비용은 어시스턴트 메시지에 기록된 경우 로컬 OpenCode 데이터베이스에서 가져옵니다.",
+ "15c34d4b08": "기록된 비용",
+ "7e9433469a": "세션/이벤트",
+ "5a65d68b77": "추론 출력",
+ "603504ee3b": "캐시된 입력",
+ "7aa4d8ce35": "출력 토큰",
+ "d637a892ed": "입력 토큰",
+ "bb6363e08c": "이 범위에 대한 로컬 OpenCode 사용이 아직 발견되지 않았습니다.",
+ "f04131b3be": "OpenCode 사용 분석 활성화",
+ "603cd138dc": "새로고침",
+ "bed558df0b": "OpenCode 사용 새로 고침",
+ "b5ed5c9fd0": "기간",
+ "40d283c837": "범위",
+ "01583b30aa": "필터",
+ "230d6de108": "OpenCode 사용 옵션",
+ "bea80ceae0": "OpenCode 사용 추적",
+ "b8b3522436": "토큰, 모델 및 세션 통계를 표시하기 위해 로컬 OpenCode 사용 로그를 읽습니다.",
+ "144a6050e9": "모든 로컬 OpenCode 사용",
+ "e04c58327c": "Orca 작업 트리만 해당",
+ "362231082f": "알려지지 않은",
+ "8095a63426": "해당 없음",
+ "6cc7782458": "• 마지막 스캔 오류: {{value0}}"
+ },
+ "ShareUsageButton": {
+ "7d6b25323d": "X에 공유",
+ "b295c1c75d": "이미지 복사",
+ "bd82c76a70": "복사됨",
+ "bce08eccb9": "사용량 공유",
+ "cecefa7c32": "공유"
+ },
+ "ShareUsageCard": {
+ "4a4c6c79a3": "세션 ·",
+ "66c83284cf": "일일 토큰",
+ "b760c0b622": "상위 모델",
+ "2d9eb39264": "총 토큰",
+ "beb6f24f37": "예상 비용",
+ "da62578d9d": "사용량",
+ "0eb31e79ee": "Orca IDE",
+ "960324e9b8": "이벤트",
+ "6adac63cfe": "턴"
+ },
+ "StatsPane": {
+ "42d3e0bdf7": "사용 분석 제공자: {{value0}}",
+ "c79f073d4c": "사용량 분석",
+ "a58aba506f": "생성된 PR",
+ "1c96f433e2": "에이전트 작업 시간",
+ "9dbec9e675": "시작된 에이전트",
+ "73ed07859c": "추적을 시작하려면 첫 번째 에이전트를 시작하세요",
+ "1e696db2f6": "OpenCode",
+ "7d26110cea": "Codex",
+ "85457c02fe": "Claude",
+ "b2cf4310ce": "개요",
+ "908c470587": "codex",
+ "eb6a066185": "claude",
+ "eee19cfade": "개요"
+ },
+ "UsageOverviewPane": {
+ "22ed1b7669": "세션",
+ "444585cb41": "데이터로",
+ "ecb0cd8a4c": "활성화됨 -",
+ "33f7b043d2": "공급자",
+ "60002bb22f": "아직 로컬 Claude, Codex 또는 OpenCode 사용을 찾을 수 없습니다. 개요는 다음 에이전트 세션에서 토큰 로그를 작성한 후에 채워집니다.",
+ "70f36452d4": "캐시 공유",
+ "327603fe8b": "활성 일수",
+ "0eaf937335": "예상 비용",
+ "3887b94ce5": "총 토큰",
+ "2d13e57f72": "OpenCode 활성화",
+ "2f1ee2878b": "Codex 활성화",
+ "0ea0cae435": "Claude 활성화",
+ "6c00c46815": "공급자가 로컬 에이전트 로그를 스캔하고 결합된 토큰 원장을 구축할 수 있도록 합니다.",
+ "49405ccc8d": "토큰 추적 시작",
+ "ca6bc5fded": "새로고침",
+ "e06d1baf5c": "새로 고침 사용량 개요",
+ "c760c481c5": "사용량 개요",
+ "55c910f4f1": "- 일부 모델 가격 확인 불가"
+ },
+ "share": {
+ "card": {
+ "utils": {
+ "19f4b4dc75": "github.com/stableai/orca",
+ "d864fc5f98": "출력",
+ "5d66fdd7c2": "입력",
+ "7080aeaebb": "추리",
+ "4ee864629a": "캐시된 입력",
+ "33d38e2177": "출력",
+ "c2d7b23d57": "입력",
+ "9d166247ee": "캐시 쓰기",
+ "cc28cb965e": "캐시 읽기"
+ }
+ }
+ },
+ "stats": {
+ "search": {
+ "cb6a9f0334": "캐시",
+ "eaf251e183": "토큰",
+ "6953af58e6": "opencode",
+ "b77826fca3": "codex",
+ "e9dc37d889": "claude",
+ "8efeae0b22": "추적",
+ "5acbe1fdf2": "시간",
+ "ef8bbf7739": "PR",
+ "ce8533f02e": "에이전트",
+ "0bba8ca244": "통계",
+ "0e2a0b6431": "사용량",
+ "372debfac0": "통계",
+ "26bb901fcd": "Orca 통계와 Claude, Codex 및 OpenCode 사용 분석, 토큰, 캐시, 모델 및 세션이 결합되어 있습니다.",
+ "cb2430ae6a": "통계 및 사용량"
+ }
+ },
+ "usage": {
+ "overview": {
+ "model": {
+ "bc474051e5": "OpenCode",
+ "eb220d193b": "Codex",
+ "544d6d4c16": "Claude"
+ },
+ "sections": {
+ "9564a3b21b": "세션 -",
+ "32330a6e66": "{{value0}}: {{value1}} 토큰",
+ "57d1448ef8": "활성화",
+ "f6df0d7d6d": "더",
+ "1dd166c920": "더 적은",
+ "52d9221dc0": "최근 토큰 활동 히트맵",
+ "c424eb3f8e": "최상의:",
+ "f28ff1f852": "최근 Claude, Codex 및 OpenCode 토큰 결합 활동.",
+ "69e2b50427": "일일 강도",
+ "3a795542fa": "결합된 토큰 믹스",
+ "e65084cb4b": "추리",
+ "3bc4a01b24": "활성화된 공급자 전체에서 입력, 출력 및 캐시 토큰을 결합했습니다.",
+ "4ff104da47": "토큰 믹스",
+ "0015facc1f": "캐시",
+ "7f270458af": "출력",
+ "9365b14a4e": "새로운 입력",
+ "3de9bf87fc": "아직 모델이 없습니다."
+ }
+ }
+ }
+ },
+ "sparse": {
+ "SparseCheckoutPresetSelect": {
+ "c4ac80151d": "새로운 사전 설정",
+ "7c3275d307": "{{value0}} 편집",
+ "c7f9b3f0c1": "끄다",
+ "8b12c0850a": "저장",
+ "de8fce5854": "취소",
+ "ddbcaef7be": "src/렌더러 패키지/UI",
+ "0e9ad9c798": "디렉토리",
+ "064c1e2d12": "렌더러 UI",
+ "b3a500c623": "이름",
+ "16223dde6a": "사전 설정 로드",
+ "a683a4bc8e": "사전 설정 로드를 다시 시도하세요.",
+ "14952d451e": "{{value0}} 디렉토리",
+ "e9283eb171": "디렉토리 1개",
+ "69c020eddc": "사전 설정 편집",
+ "bd6cec2056": "새로운"
+ }
+ },
+ "source": {
+ "control": {
+ "SourceControlActionVariableChips": {
+ "1b77798d5f": "변수",
+ "6b921a0ac2": "예",
+ "4bf6d88039": "(비어 있는)"
+ }
+ }
+ },
+ "skills": {
+ "SkillsPage": {
+ "cb142070b4": "새로고침",
+ "984405683f": "플러그인",
+ "4d177feabd": "번들로 제공",
+ "aa59462502": "저장소",
+ "571c5818c1": "집",
+ "0bc1379f4c": "모든 소스",
+ "38e0951c3a": "에이전트 스킬",
+ "fb6bf60b52": "Claude",
+ "426be2aac6": "Codex",
+ "39b6998ddb": "모든 제공업체",
+ "a68dee6a32": "스킬 검색",
+ "e46e162e2e": "~에서",
+ "b088e0785d": "베타",
+ "f43ad6edf3": "스킬",
+ "7e828fb2c6": "뒤로",
+ "ea72d6185b": "로컬 스킬을 스캔할 수 없습니다.",
+ "dc4c3328ee": "파일 공개",
+ "9963dff6d3": "설명을 찾을 수 없습니다.",
+ "995fde8337": "스킬 파일을 공개할 수 없습니다.",
+ "ab5b777350": "로컬 홈, 저장소, 번들, 플러그인 스킬 폴더를 확인했습니다.",
+ "08a321a984": "검색 또는 필터를 조정합니다.",
+ "4acd6d68ec": "로컬 스킬을 찾을 수 없습니다.",
+ "6a62a0168c": "일치하는 항목 없음",
+ "cd7893fbc1": "스킬 스캔 중",
+ "35b9a724a0": "사용 가능",
+ "0c74e7ff34": "현지의"
+ }
+ },
+ "sidebar": {
+ "AddProjectFromFolderDialog": {
+ "7d1f51678c": "프로젝트 추가",
+ "7726a16374": "취소",
+ "046751dbfb": "이 폴더를 별도의 Orca 프로젝트로 추가합니다.",
+ "e643b30398": "원격 프로젝트가 추가되었습니다."
+ },
+ "AddRepoCreateStep": {
+ "0ae45b8238": "내 프로젝트",
+ "a8149a3a5a": "이름",
+ "038729c107": "접는 사람",
+ "11fd2a7db8": "힘내 저장소",
+ "180e9b5e48": "프로젝트 종류",
+ "d877ece0d6": "Git 저장소 또는 일반 폴더를 생성하고 Orca에서 엽니다.",
+ "db9be12229": "새 프로젝트 시작",
+ "5e97f0c4b9": "프로젝트가 생성되었습니다.",
+ "2c12db1511": "프로젝트가 이미 추가되었습니다.",
+ "875dda0995": "서버 상위 경로를 입력하세요.",
+ "45b7c26034": "프로젝트 생성",
+ "85085d74d2": "만드는 중…"
+ },
+ "AddRepoNestedImportStep": {
+ "496f68cf8c": "저장소를 스캔하는 중입니다. 중지하려면 클릭하세요.",
+ "a32bef9516": "스캔 중지",
+ "2f8298f3c3": "스캔 중지",
+ "c157f31a95": "그룹으로 가져오기",
+ "40199ef7b3": "그룹 이름",
+ "b20bb7c24f": "이러한 저장소를 하나의 그룹에 함께 유지합니다. 마이크로서비스와 같은 관련 저장소에 가장 적합합니다.",
+ "787412361a": "그룹 이름은 무엇입니까?",
+ "5f857ba8e6": "~에",
+ "4df0d08cc5": "발견됨",
+ "8db50afe1a": "폴더에서 저장소 가져오기",
+ "5b2e6fe3c8": "별도로 가져오기",
+ "cf9d382ca1": "수입",
+ "220dd32d83": "스캐닝..."
+ },
+ "AddRepoRemoteStep": {
+ "5b205b5281": "스캔 중지",
+ "6680289908": "/home/user/project",
+ "ef410aa881": "원격 경로",
+ "0416bde073": "설정에 추가",
+ "df6fbcf880": "구성된 SSH 대상이 없습니다.",
+ "44637f43bd": "SSH 대상",
+ "80557be85a": "연결된 SSH 대상을 선택하고 Git 저장소 경로를 입력하세요.",
+ "91b93a90a4": "원격 프로젝트 열기",
+ "007651bdf9": "디렉터리로 이동한 후 선택을 클릭하여 선택합니다.",
+ "dd3ff65486": "원격 파일 시스템 찾아보기",
+ "36d427bb66": "원격 프로젝트 추가",
+ "35831a7312": "첨가..."
+ },
+ "AddRepoServerStartStep": {
+ "ae990c86a0": "옵션 추가로 돌아가기",
+ "e1710bf831": "폴더로 열기",
+ "8da4d1a5be": "Git 프로젝트 추가",
+ "ac66a3ed2d": "서버 파일 시스템 찾아보기",
+ "92d25420a0": "/home/user/project",
+ "867692f505": "서버 경로",
+ "423b5d3d31": "선택한 런타임 서버에 이미 존재하는 Git 저장소 또는 폴더를 추가하십시오.",
+ "3d0c035483": "오픈 서버 프로젝트",
+ "438493f214": "또는 서버 경로를 수동으로 입력하세요.",
+ "6b9958492a": "한 번에 많은 저장소를 가져오고 싶으십니까? 상위 폴더로 이동합니다.",
+ "d40d751517": "새 저장소 또는 폴더",
+ "a81ffa0a99": "서버에서 생성",
+ "a2ea37d549": "원격 Git 저장소",
+ "47759c9491": "URL에서 복제",
+ "516187414c": "기존 프로젝트 또는 폴더",
+ "0adf083af7": "서버 찾아보기",
+ "8efa930eb5": "선택한 런타임 서버에서 다른 프로젝트를 추가하십시오.",
+ "39bd249b3a": "프로젝트 추가",
+ "0f8aba944c": "디렉터리로 이동한 후 선택을 클릭하여 선택합니다."
+ },
+ "AddRepoStartSteps": {
+ "f3c96237ae": "아니면 다음에서 추가하세요…",
+ "acf895cb42": "Orca를 시작하려면 프로젝트를 추가하세요.",
+ "d13757911c": "프로젝트 추가",
+ "d301db1c9a": "저장소를 스캔하는 중입니다. 중지하려면 클릭하세요.",
+ "69ea7f8dc4": "스캔 중지",
+ "9906cae183": "스캔 중지"
+ },
+ "AddRepoStepIndicator": {
+ "3bb655c117": "뒤로"
+ },
+ "AddRepoSteps": {
+ "569326d9cc": "폴더 선택",
+ "a93ef169b5": "서버 파일 시스템 찾아보기",
+ "2ce3f6edf8": "/경로/대상/목적지",
+ "04a4c4e84a": "클론 위치",
+ "b698a4a29d": "https://github.com/user/repo.git",
+ "3d4acbe693": "힘내 URL",
+ "5b2ea674b1": "Git URL을 입력하고 복제할 위치를 선택하세요.",
+ "c05f88a31f": "URL에서 복제",
+ "fe8e629fe3": "디렉터리로 이동한 후 선택을 클릭하여 선택합니다.",
+ "df8b0e6c22": "원격 프로젝트가 추가되었습니다.",
+ "3e64e8a70d": "연결 실패",
+ "32a7256d85": "클론",
+ "69f5b5380d": "복제 중..."
+ },
+ "AutoRenameFailedDialog": {
+ "aed1623b1e": "닫기",
+ "eab8b45238": "복사 오류",
+ "a23b22d16f": "복사됨",
+ "74fc00776f": "오류 세부정보",
+ "3afcad0497": "첫 번째 에이전트 메시지에서.",
+ "ff62a18580": "Orca가 다음에 대한 브랜치 이름을 생성할 수 없습니다.",
+ "ca3b225195": "브랜치 자동 이름 지정에 실패했습니다."
+ },
+ "CreateProjectLocationField": {
+ "95548e33bf": "상위 폴더 선택...",
+ "632b456b1b": "변화",
+ "afaf54f245": "상위 폴더 변경",
+ "f520f83a97": "서버 파일 시스템 찾아보기",
+ "2a20a603a3": "/home/user/projects",
+ "134e37f711": "위치",
+ "b589b77997": "디렉터리로 이동한 후 선택을 클릭하여 선택합니다."
+ },
+ "DeleteWorktreeDialog": {
+ "ff2a74ac0e": "그리고",
+ "91492c9ad6": "제거",
+ "4f6750ca7b": "워크스페이스를 삭제하지 못했습니다.",
+ "42e610d6cf": "강제 삭제 실패",
+ "5cc1a6701c": "설정 열기",
+ "2b56b35f53": "설정에서 이를 변경할 수 있습니다.",
+ "dd3a45bbbd": "다음번에는 이 확인을 건너뛰겠습니다.",
+ "fc23c4cbdf": "워크스페이스 삭제",
+ "86f0ae1257": "워크스페이스 삭제"
+ },
+ "DeleteWorktreeDirtyChangeHint": {
+ "8e2994ce28": "이 워크스페이스를 삭제하면 이러한 변경 사항이 디스크에서 영구적으로 제거됩니다."
+ },
+ "DeleteWorktreeLineageNotice": {
+ "ad407c2d55": "더",
+ "a940f3c96e": "하위 워크스페이스가 삭제됩니다.",
+ "29b98bf9cd": "이 워크스페이스를 삭제하면 {{value0}} 하위 워크스페이스도 삭제됩니다.",
+ "66798cc6a2": "이 워크스페이스를 삭제하면 하위 워크스페이스 1개도 삭제됩니다."
+ },
+ "DeleteWorktreeSkipConfirmOption": {
+ "29aefb7e52": "다시 묻지 마세요"
+ },
+ "DeleteWorktreeWarningPanels": {
+ "026738155a": "(원본 복제 디렉토리).",
+ "c4f96a6e18": "메인 작업 트리",
+ "e3be9eba15": "이것은"
+ },
+ "ImportedWorktreesVisibilityLine": {
+ "b7a87dc32f": "작업 트리 목록에 표시",
+ "ad99f4eea9": "숨겨두세요",
+ "9f4f14e821": "나중에 프로젝트 메뉴에서 이를 변경하세요.",
+ "b2bc47c080": "더 많은 위치",
+ "b47ba1a9d2": "{{value0}} 미리보기",
+ "2251d41ebb": "숨겨진 작업 트리 그룹",
+ "f54f2bec5d": "{{value0}} {{value1}}에 대한 숨겨진 작업 트리",
+ "5a9688802a": "{{value0}} 더 보기",
+ "294de4aeb2": "간략히 표시"
+ },
+ "NonGitFolderDialog": {
+ "e52454b7f6": "폴더로 열기",
+ "05b33a17a9": "취소",
+ "8fba4b8cbb": "이 폴더는 Git 저장소가 아닙니다. 편집기, 터미널, 검색 기능은 제공되지만 Git 기반 기능은 사용할 수 없습니다.",
+ "c49fb13492": "원격 폴더를 추가하지 못했습니다."
+ },
+ "OrcaYamlTrustDialog": {
+ "f3e2b868fb": "후크 실행",
+ "43b7bec4cd": "뛰지 마세요",
+ "c494b3ccb1": "~에",
+ "79afc6772b": "orca.yaml",
+ "531689199b": "항상 신뢰하세요",
+ "bf800b7e04": ". 믿을 수 있는 경우에만 실행하세요.",
+ "831f2cd9f0": "당신의 컴퓨터에서 실행",
+ "aa3ffb33fb": "이 저장소의",
+ "c55beddbf8": "마지막으로 승인한 이후 변경되었습니다. 실행하기 전에 재리뷰하세요.",
+ "95bf974a1a": "{{value0}} 스크립트",
+ "9e52effffd": "새로운 {{value0}} 스크립트",
+ "e4a51dc4b3": "{{value1}}에서 {{value0}}을(를) 실행하시겠습니까?",
+ "02b0ede5ad": "{{value0}}의 {{value1}}이 변경되었습니다. 새 버전을 실행하시겠습니까?"
+ },
+ "PendingWorktreeRow": {
+ "af21e953d1": "작업 트리 생성 취소",
+ "188f6922a0": "취소"
+ },
+ "ProjectGroupDeleteDialog": {
+ "ca65b78f78": "취소",
+ "9be10d49ea": "해당 프로젝트의 그룹을 해제합니다.",
+ "69f5cb97d0": "삭제",
+ "591f330288": "프로젝트 그룹 삭제",
+ "2c14ce677a": "삭제 중..."
+ },
+ "ProjectGroupNameDialog": {
+ "d99a034073": "취소",
+ "83dfbc5313": "그룹 이름",
+ "4a64e78822": "저장 중..."
+ },
+ "RemoteFileBrowser": {
+ "2300612806": "필터링하려면 입력하거나 경로를 입력하세요…",
+ "9e060f5815": "폴더 선택",
+ "f8b1deb1a4": "취소",
+ "51001182e3": "빈 디렉토리",
+ "971d85cc84": "원격 프로젝트로 열립니다 · {{value0}}",
+ "00c4235c10": "'{{value0}}'과(와) 일치하는 항목이 없습니다."
+ },
+ "RemoveFolderDialog": {
+ "4dc5b5065b": "제거",
+ "d36883e046": "취소",
+ "8c097ef04e": "Orca에서. 아직 디스크에 있습니다.",
+ "e62415c3d0": "이것만 제거",
+ "b79b39d865": "프로젝트 제거"
+ },
+ "ScrollToCurrentWorkspaceToolbarButton": {
+ "23989bb663": "활성 워크스페이스 공개"
+ },
+ "SetupGuideSidebarEntry": {
+ "b0a7bfc34c": "사이드바에서 숨기기",
+ "88d402b71d": "온보딩 체크리스트"
+ },
+ "SetupScriptPromptCard": {
+ "ff1e819a11": "설정 스크립트 추가",
+ "70715947fb": "설정 스크립트는 비워둘 수 없습니다.",
+ "888b83bf78": "설정 스크립트를 저장하지 못했습니다.",
+ "a49196d538": "Orca가 새 작업 트리를 생성할 때 실행됩니다.",
+ "d9f2db2738": "프로젝트 설정",
+ "a5bb8c5135": "여기에 저장됨",
+ "dcaa645da5": "좋아요"
+ },
+ "SetupScriptPromptCardViews": {
+ "96a7f4198c": "로컬 설정 저장",
+ "3933401d28": "구성",
+ "31b8b01a45": "설정",
+ "4a98f907ae": "다시 시도",
+ "0a98169776": "Orca가 새 작업 트리를 생성할 때 실행할 설정 명령을 추가합니다.",
+ "8349e3fa4c": ". 새 작업 트리에 대해 실행되도록 저장하세요.",
+ "b56d1322f7": "다음에서 설정 명령을 찾았습니다.",
+ "aef6c0a213": "Orca가 작업 트리를 생성할 때마다 실행되도록 감지된 명령을 저장합니다.",
+ "660cdc17f8": "설정 스크립트. 로컬 명령을 추가하거나 설정에서 소스를 변경하세요.",
+ "8f6be51aa1": "orca.yaml",
+ "bb879db364": "이 저장소는 공유를 무시합니다.",
+ "0155fb9ed3": "지금은 이 저장소의 설정 스크립트를 확인할 수 없습니다.",
+ "eefa756190": "수동으로 구성",
+ "ca4efcbc25": "저장",
+ "d02e6a42b1": "다음에서 감지됨",
+ "fdbc6cb064": "감지된 설정 스크립트",
+ "7275f674cc": "감지된 설정",
+ "822ff300ad": "닫기",
+ "5bfd5c8779": "설정 스크립트 닫기"
+ },
+ "SidebarFeedbackDialog": {
+ "8bf619e4cf": "취소",
+ "8de03e23c5": "입력한 피드백만 제출하거나 'gh'를 연결하여 GitHub ID를 포함하세요.",
+ "d20439c560": "GitHub ID 확인 중…",
+ "5b120b9634": "익명으로 제출",
+ "c9e5ea0791": "GitHub:",
+ "d46ddd66fc": "무엇을 개선할 수 있나요?",
+ "3460258a54": "X를 따라가세요",
+ "26108d3699": "Discord 참여",
+ "d245c4ef6c": "GitHub 이슈",
+ "9b33530b3d": "우리에게 연락하는 다른 방법",
+ "a828fa4aee": "작동하는 부분, 손상된 부분 또는 Orca가 다음에 수행해야 할 작업을 공유하세요.",
+ "0eb643f07f": "피드백 보내기",
+ "60b721e857": "의견을 제출하지 못했습니다. 다시 시도해 주세요.",
+ "7a46c228b8": "피드백을 보내주셔서 감사합니다.",
+ "a2fd890d9e": "제출하기 전에 피드백을 입력해 주세요.",
+ "f2e42e1307": "보내기",
+ "69969ba364": "전송 중…"
+ },
+ "SidebarFilter": {
+ "e3b3898218": "프로젝트 추가",
+ "92a23e6d07": "필터 재설정",
+ "81ded53722": "SSH",
+ "b9e8802e73": "일치하는 프로젝트가 없습니다.",
+ "779b7ba05d": "지우기",
+ "139877b384": "모두 선택",
+ "5f7085a077": "프로젝트",
+ "e5cb32a898": "기본 브랜치 숨기기",
+ "638a2d221d": "슬립 중인 항목 숨기기",
+ "f506a1262a": "워크스페이스 필터링",
+ "75405270ed": "필터 편집({{value0}} 활성)",
+ "489d1c8c9f": "프로젝트 검색...",
+ "ee240a39eb": "필터 편집"
+ },
+ "SidebarHeader": {
+ "92154beb7e": "새로운 워크스페이스",
+ "49f62c5665": "워크스페이스 보드",
+ "5c9c7c16aa": "워크스페이스를 만들려면 프로젝트를 추가하세요.",
+ "ca6f729da2": "새 워크스페이스({{value0}})",
+ "a30e34eb5c": "워크스페이스 보드 닫기"
+ },
+ "SidebarNav": {
+ "80611a8b10": "검색",
+ "0c3395fd32": "작업 트리 및 브라우저 탭 검색",
+ "c86d83b5c3": "새로 만들기",
+ "1b5c41caee": "Orca 모바일",
+ "9c95e1ce91": "에이전트",
+ "f323383e9a": "자동화",
+ "e7ad3c540d": "Jira 작업 열기",
+ "c39ab10000": "Linear 작업 열기",
+ "196c1b5362": "GitLab 작업 열기",
+ "0ccba862b8": "GitHub 작업 열기",
+ "fee535205b": "작업",
+ "d599269755": "사이드바에서 숨기기"
+ },
+ "SidebarRepositoryFilterSection": {
+ "d3a9c4cea1": "지우기",
+ "7679f0c268": "프로젝트",
+ "f10ca29601": "{{value0}} 필터 제거",
+ "2656053db4": "SSH",
+ "83a820fa71": "프로젝트 필터링...",
+ "5a273fbfce": "프로젝트 추가...",
+ "4815c70605": "일치하는 프로젝트가 없습니다.",
+ "bbbc6e8e3b": "선택되지 않은 일치하는 프로젝트가 없습니다."
+ },
+ "SidebarSettingsHelpMenu": {
+ "ad3d3ed7f1": "Orca 재시작",
+ "29c56f30ee": "업데이트 확인",
+ "eb9884e55b": "Discord",
+ "5687ab246a": "GitHub",
+ "5f83d86d92": "변경 내역",
+ "cdc87f897e": "문서",
+ "e565171a7c": "키보드 단축키",
+ "4cf5b868d7": "피드백 보내기",
+ "a428c25998": "설정",
+ "2991a0106c": "돕다",
+ "4e8f5710d3": "Orca를 다시 시작할 수 없습니다.",
+ "5161eef55d": "Orca를 다시 시작하는 중…",
+ "d396773ef0": "확인 중"
+ },
+ "SidebarToolbar": {
+ "19e32d0e5f": "폴더 선택기를 열어 프로젝트를 추가하세요.",
+ "abc62b6328": "프로젝트 추가"
+ },
+ "SidebarWorkspaceFilterSection": {
+ "c3fa13dc2e": "기본 브랜치 숨기기",
+ "ed1611b65b": "슬립 중인 항목 숨기기",
+ "82594419ba": "필터"
+ },
+ "SidebarWorkspaceOptionsMenu": {
+ "95c9754653": "에이전트 활동 레이아웃",
+ "3d4b9c4997": "호버",
+ "ba87080fb7": "속성 표시",
+ "320b675c9a": "카드 레이아웃",
+ "09faabd875": "프로젝트 순서",
+ "7bada3b1ab": "정렬 기준",
+ "dc0bb670bc": "그룹화 기준",
+ "9919ae1082": "워크스페이스 옵션",
+ "bc96dbd041": "워크스페이스 옵션({{value0}})",
+ "af9249c505": "가장 최근의 워크스페이스 활동",
+ "b451c8b162": "최근의",
+ "6664282a7b": "프로젝트를 드래그하여 정렬하세요.",
+ "7b316bdd51": "수동",
+ "7153d07485": "워크스페이스를 드래그하여 각 그룹 내에서 정렬하세요.",
+ "2170d553cf": "프로젝트",
+ "b759bb87ee": "주의가 필요한 에이전트, 가장 최근 활동 순입니다.",
+ "503462f2b4": "에이전트 활동",
+ "3728165cdd": "이름",
+ "2a81e07366": "전체 목록",
+ "25105b28cb": "콤팩트",
+ "d7084e8bc8": "에이전트 활동",
+ "b64d8bcca0": "포트",
+ "26c71e536c": "메모",
+ "b8dcc6f321": "PR/MR 링크",
+ "ca4d3c522e": "Linear 이슈",
+ "91dfc653e8": "GitHub 티켓",
+ "cc17bd443b": "상세한",
+ "0f9b959b31": "PR",
+ "e029a2d775": "상태",
+ "c2c7a45cda": "없음",
+ "680043342f": "콤팩트",
+ "c7591b6014": "레포"
+ },
+ "SshDisconnectedDialog": {
+ "ca4a7892af": "연결 중...",
+ "89385db176": "닫기",
+ "656368f3a2": "재연결 실패",
+ "376bed88e5": "원격 호스트 연결에 오류가 발생했습니다.",
+ "4afcca1d24": "다시 연결",
+ "11552bf786": "SSH 연결 끊김",
+ "cb5938ae79": "다시 연결하는 중..."
+ },
+ "SshTargetRow": {
+ "4677394048": "연결 중…",
+ "75ad429b5d": "연결"
+ },
+ "WorkspaceKanbanCard": {
+ "cefae8983e": "고정됨"
+ },
+ "WorkspaceKanbanDrawerHeader": {
+ "f369f5c5a3": "닫기",
+ "e1a34450fc": "상태별로 워크스페이스를 구성하고 워크스페이스 카드를 엽니다.",
+ "81870af08f": "선택된",
+ "c6a77ab0f4": "워크스페이스 보드"
+ },
+ "WorkspaceKanbanPinDropTarget": {
+ "c30151c5ee": "상태를 변경하지 않고 고정하려면 여기에 드롭하세요.",
+ "8fae2d0862": "고정됨"
+ },
+ "WorkspaceKanbanSettingsMenu": {
+ "79eb990aa4": "상태 추가",
+ "054cb50df7": "{{value0}} 제거",
+ "b45b350eb0": "{{value0}} 왼쪽으로 이동",
+ "8ce44af9a8": "{{value0}} 이름 바꾸기",
+ "395e541d5d": "상태",
+ "34f03eb0de": "보드 설정",
+ "26cbc92150": "워크스페이스 보드 설정"
+ },
+ "WorkspaceKanbanStatusLane": {
+ "8ad104642b": "비어 있는",
+ "3611d1ae7f": "워크스페이스 보드 열 크기 조정"
+ },
+ "WorkspaceStatusAppearancePopover": {
+ "514be2f569": "{{value0}} 색상을 {{value1}}로 설정",
+ "8be427206b": "상",
+ "2ac106f6b2": "색상",
+ "74b1413279": "외관",
+ "ccbd1e2c69": "{{value0}} 모양 맞춤설정"
+ },
+ "WorktreeCard": {
+ "a88c92d0e3": "이미 존재합니다.",
+ "6f09f58541": "워크스페이스 삭제",
+ "0777de5970": "기본 작업 트리(원래 복제 디렉터리)",
+ "0f33af979b": "부분결제. 이 경로 외부의 파일은 디스크에 없습니다.",
+ "4f964d5e8c": "부족한",
+ "7d517f82e2": "주요한",
+ "c6833b5187": "첫 번째 에이전트 메시지에서 이름이 변경됩니다.",
+ "f62a3dadbc": "이름 바꾸기 보류 중",
+ "4eba2ea99e": "자동 이름을 지정하지 못했습니다. 자세한 내용을 보려면 클릭하세요.",
+ "74522ee457": "이름 바꾸기 실패",
+ "02e19349f4": "자동 이름 바꾸기 실패: 보기 오류",
+ "691ccfd622": "삭제 중…",
+ "35ccfe2475": "프로젝트 {{value0}}",
+ "1d66d84f0b": "문자열",
+ "57eaa61b55": "하위 워크스페이스 숨기기",
+ "8cb634cda6": "하위 워크스페이스 표시",
+ "01f45d3d8a": "사이드바",
+ "93aebe4529": "접는 사람",
+ "0d224eff10": "기본 작업 트리",
+ "ca74db7550": "SSH를 통한 원격 프로젝트",
+ "021538e1d1": "SSH 연결이 끊어졌습니다."
+ },
+ "WorktreeCardAgents": {
+ "1b0a156717": "에이전트"
+ },
+ "WorktreeCardMeta": {
+ "3e65e11cc6": "워크스페이스 메타데이터",
+ "c7fa72ead0": "메모 편집",
+ "93cbea12c2": "메모",
+ "eace1d2cf6": "중립적",
+ "dbe2d18972": "추가 {{value0}} 작업",
+ "ae76907ca6": "{{value0}} 연결 해제",
+ "ad25c3ff05": "{{value0}}에서 보기",
+ "2c67730e07": "Orca에서 열기",
+ "e42941631a": "Linear에서 보기",
+ "5e982e6128": "Linear {{value0}}",
+ "807b13b9ec": "이슈 편집",
+ "b22f058067": "GitHub에서 보기",
+ "e97d8f2876": "이슈 #{{value0}}",
+ "3ea2702e62": "연결됨 {{value0}} #{{value1}}",
+ "b105fd3057": "연결된 Linear {{value0}}",
+ "3f2649eeb8": "연결된 이슈 #{{value0}}",
+ "fe075cb851": "워크스페이스 메모"
+ },
+ "WorktreeCardMetadataStatusBadges": {
+ "fe188062a1": "상태: 열림",
+ "2931b42b09": "상태: 초안 {{value0}}",
+ "e888362def": "상태: 폐쇄됨",
+ "f394b3e86e": "상태: 병합됨",
+ "af2b07bda5": "상태: {{value0}}",
+ "29df45afa2": "씨"
+ },
+ "WorktreeCardPorts": {
+ "34f733dda2": "작업 트리로 이동",
+ "3240f320d7": "라이브 포트",
+ "3e5f66564e": "워크스페이스를 사용할 수 없음",
+ "2f854442ff": "프로세스 중지",
+ "c8067a829a": "{{value0}} 복사",
+ "33bc7d7495": "브라우저에서 열기",
+ "9950fe2d20": "포트를 새로고침하지 못했습니다.",
+ "5d1a5d51bb": "{{value0}}에서 프로세스가 중지되었습니다.",
+ "c89f290e25": "{{value0}} 복사됨",
+ "d1113f4660": "브라우저를 열지 못했습니다.",
+ "fed49903c9": "{{value0}} 실시간 {{value1}}"
+ },
+ "WorktreeContextMenu": {
+ "c39c37676a": "그룹을 만들고 이 프로젝트를 그룹으로 이동하세요.",
+ "6664418e98": "새로운 프로젝트 그룹",
+ "e091caab15": "프로젝트를 찾을 수 없습니다.",
+ "439fa94d53": "업데이트",
+ "579b1a8e61": "상위에서 제거",
+ "8d9cd19d09": "상위 워크스페이스 열기",
+ "d35dfeae58": "그룹에서 제거",
+ "76865d827f": "그룹으로 이동",
+ "503ec0f8e6": "프로젝트의 새 그룹",
+ "3350101edb": "경로 복사",
+ "f4475537d8": "삭제",
+ "f5ac91531d": "Orca에서 프로젝트 제거",
+ "b42391d8bf": "삭제 중…",
+ "0918b35e4f": "메모리와 CPU를 확보하려면 이 워크스페이스의 모든 활성 패널을 닫으세요.",
+ "7d190f7d2b": "선택한 워크스페이스의 모든 활성 패널을 닫아 메모리와 CPU를 확보하세요.",
+ "84cdbb7e30": "상태로 이동",
+ "56cde9e8e6": "상태를 다음으로 이동",
+ "f50603c6b2": "읽지 않은 것으로 표시",
+ "8dacff1fe0": "마크 리드",
+ "3baa7d6507": "핀",
+ "697d0f6e1b": "고정 해제"
+ },
+ "WorktreeList": {
+ "d880ea0744": "그룹을 만들고 이 프로젝트를 그룹으로 이동하세요.",
+ "bc1460beb3": "사이드바에 표시된 그룹 이름을 업데이트합니다.",
+ "13757c053c": "새로운 프로젝트 그룹",
+ "f9dc6cc5d3": "프로젝트 그룹 이름 바꾸기",
+ "370c6a55dd": "필터 지우기",
+ "b7acbf038b": "워크스페이스를 찾을 수 없습니다.",
+ "0c6ee14f23": "하위",
+ "5fc9d1891b": "삭제 중…",
+ "c83968f87f": "프로젝트 제거",
+ "64e55f7f01": "그룹에서 제거",
+ "4a08fb55f2": "그룹으로 이동",
+ "cbfd565f83": "프로젝트의 새 그룹",
+ "e82d3589a1": "프로젝트 아이콘 변경",
+ "2cdffbc728": "프로젝트 설정",
+ "2ef41bf9a7": "프로젝트 활동",
+ "609633a9e6": "{{value0}}에 대한 프로젝트 작업",
+ "902115cdbe": "그룹 삭제",
+ "4d7b73658c": "그룹 이름 바꾸기",
+ "79465e9034": "{{value0}}에 대한 그룹 작업",
+ "bfbedc547b": "작업 트리",
+ "45fbfe0335": "이름 바꾸기",
+ "ebc5c7dcef": "하위 워크스페이스 숨기기",
+ "84a2238242": "하위 워크스페이스 표시",
+ "045a8aed48": "하위",
+ "2ca6e29a3c": "레포",
+ "bb85cd86ba": "{{value0}}에 대한 워크스페이스 만들기"
+ },
+ "WorktreeMetaDialog": {
+ "3db0a2a593": "취소",
+ "b48c271d39": "저장하려면 새 줄을 입력하려면 Shift+Enter를 누르세요.",
+ "7f0be5e9a6": "**markdown** 지원 — 굵게, 목록, `코드`, 링크. Enter 키를 누르거나",
+ "030d484fc0": "이 작업 트리에 대한 참고 사항...",
+ "9c1d1e9b71": "댓글",
+ "5ae06f40fd": "PR URL을 붙여넣거나 숫자를 입력하세요. 링크를 제거하려면 비워두세요.",
+ "077a4f7b5c": "PR # 또는 GitHub URL",
+ "1b91db7e14": "GH PR",
+ "7c454be4c5": "이슈 URL을 붙여넣거나 숫자를 입력하세요. 링크를 제거하려면 비워두세요.",
+ "029ea5ec57": "GitHub 이슈 열기",
+ "741279e7b7": "이슈 # 또는 GitHub URL",
+ "645fa4a0fd": "GH 이슈",
+ "459ad7f650": "사이드바에 표시된 이름만 변경됩니다. 디스크의 폴더는 동일하게 유지됩니다. 브랜치 또는 폴더 이름을 사용하려면 비워 두세요.",
+ "7f21e0464f": "맞춤 표시 이름...",
+ "ad5e4e514f": "표시 이름",
+ "65770ad0f0": "이 워크스페이스에 대한 GitHub 링크와 메모를 편집하세요.",
+ "382fd11a3e": "작업 트리 세부정보 편집",
+ "2174f17011": "저장",
+ "61d6f612cf": "저장 중..."
+ },
+ "WorktreeOpenInMenu": {
+ "1417fd8380": "앱 맞춤설정...",
+ "8009ab69a6": "다음에서 열기",
+ "bd0e8159f8": "이 컴퓨터의 편집기 명령이나 파일 관리자 구성을 확인하세요.",
+ "9a5381eb09": "워크스페이스 폴더를 열 수 없습니다.",
+ "0bed8727db": "이동되었거나 삭제되었을 수 있습니다. 워크스페이스를 새로고침거나 Orca에서 제거하십시오.",
+ "3921d3d9a5": "워크스페이스 폴더를 찾을 수 없습니다.",
+ "f387af445b": "워크스페이스 경로가 유효한 로컬 경로가 아닙니다.",
+ "3ec372b664": "파일 관리자"
+ },
+ "WorktreeTitleInlineRename": {
+ "2f42ae024f": "읽히지 않는:",
+ "bff3bdd00c": "워크스페이스 이름 바꾸기",
+ "8df295a78d": "워크스페이스 이름을 바꾸지 못했습니다."
+ },
+ "WorktreeVisibilityDialog": {
+ "83a5ba8dd1": "비Orca 작업 트리",
+ "f1f71b9f02": "수입",
+ "759371df43": "숨다",
+ "25ddf19920": "{{value0}} 가져오기 가능",
+ "8372e4bbd9": "{{value0}} 현재 표시됨",
+ "5d02a5647f": "사이드바에서 숨겨짐",
+ "3e045d4cb8": "사이드바에 표시됨"
+ },
+ "add": {
+ "repo": {
+ "local": {
+ "start": {
+ "actions": {
+ "d72789705e": "빈 폴더에서 시작",
+ "c709860596": "새 프로젝트 만들기",
+ "5f9ffac036": "원격 Git 저장소 복제",
+ "7edb8ebe24": "URL에서 복제",
+ "a6c20dca96": "SSH 대상에서 프로젝트 열기",
+ "3d162cc76f": "원격 프로젝트",
+ "fb4fc5380e": "로컬 프로젝트, Git 저장소 또는 저장소가 많은 폴더",
+ "2281fdc8c7": "폴더 찾아보기"
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "worktree": {
+ "flow": {
+ "b81b4e40ca": "Space를 새로고침하고 워크스페이스 목록이 오래된 것처럼 보이면 다시 시도하세요.",
+ "7243145cd6": "삭제 가능한 워크스페이스가 선택되지 않았습니다.",
+ "ae57cbf6e4": "워크스페이스를 삭제하지 못했습니다.",
+ "7488ed8711": "보기",
+ "2b20ce87b3": "강제 삭제",
+ "4f3876c0f5": "강제 삭제 실패"
+ },
+ "toast": {
+ "1d0fa5c0a5": "워크스페이스 {{value0}}을(를) 삭제하지 못했습니다.",
+ "ead7b8ee15": "파일이 변경되었습니다. 어쨌든 삭제하려면 강제 삭제를 사용하세요.",
+ "905fc8efac": "Git은 이미 이 워크스페이스를 제거했습니다. 강제 삭제를 사용하여 Orca에서 삭제합니다.",
+ "0899ebdb28": "Git은 이미 이 워크스페이스를 잊어버렸지만 해당 디렉토리는 여전히 디스크에 있습니다. 강제 삭제를 사용하여 분리된 디렉터리를 제거합니다."
+ }
+ }
+ },
+ "remote": {
+ "file": {
+ "browser": {
+ "helpers": {
+ "4dbd72a7d7": "{{value0}}은(는) {{value1}}의 디렉터리가 아닙니다.",
+ "be266af66c": "{{value0}}은 {{value1}}의 여러 디렉터리와 일치합니다."
+ }
+ }
+ }
+ },
+ "repo": {
+ "header": {
+ "create": {
+ "state": {
+ "992cfbc44b": "{{value0}}에 대한 새 작업 트리 만들기",
+ "3a70acd808": "{{value0}}에 대한 워크스페이스를 만들기 전에 SSH 대상을 다시 연결하세요.",
+ "6d022563a8": "워크스페이스를 만들기 전에 SSH 대상을 다시 연결하세요.",
+ "62e71f2d5d": "{{value0}}에 대한 워크스페이스 만들기"
+ }
+ }
+ }
+ },
+ "sidebar": {
+ "project": {
+ "drop": {
+ "669e12dd97": "로컬 폴더 및 Git 리포지토리",
+ "ffc769ca29": "프로젝트를 추가하려면 폴더를 드롭하세요.",
+ "740e8d0d46": "서버 경로에 프로젝트 추가 사용",
+ "e344666fb8": "서버 런타임 활성",
+ "d0f8943f8b": "프로젝트 추가 흐름 준비",
+ "18d3cf40e9": "폴더 확인 중"
+ }
+ }
+ },
+ "sleep": {
+ "worktree": {
+ "flow": {
+ "c460fecc4a": "일부 워크스페이스를 절전 모드로 전환하지 못했습니다.",
+ "8bc3fc0671": "워크스페이스를 절전 모드로 전환하지 못했습니다."
+ }
+ }
+ },
+ "useAddRepoCloneFlow": {
+ "4d0013cc93": "저장소가 복제되었습니다.",
+ "0dc4d1b657": "복제 대상의 서버 경로를 입력합니다."
+ },
+ "useAddRepoLocalFolderFlow": {
+ "7ab10e4974": "원격 런타임에서 프로젝트를 추가하려면 서버 경로를 사용하세요."
+ },
+ "useAddRepoNestedImportFlow": {
+ "680cac2c82": "{{value0}} 실패",
+ "cbfbc7a797": "일부 저장소를 가져올 수 없습니다.",
+ "1b33c5f090": "가져온 저장소가 없습니다."
+ },
+ "useSidebarProjectDrop": {
+ "f34a286c0d": "드롭한 폴더를 추가할 수 없습니다.",
+ "451a4638db": "폴더를 끌어서 프로젝트로 추가하세요.",
+ "5ccb56c7be": "프로젝트 추가를 사용하여 서버 경로를 입력하세요.",
+ "849ef13dc0": "서버 런타임에서는 로컬 폴더 드롭을 사용할 수 없습니다.",
+ "c0315153d1": "한 번에 폴더 하나만 드롭하세요."
+ },
+ "workspace": {
+ "status": {
+ "cb387159f6": "진행중",
+ "6c1efa2cf8": "리뷰 중",
+ "6b8285b8dd": "완료",
+ "93ac840dcb": "차단됨",
+ "2c19d1db33": "놀다",
+ "111db162bf": "일시중지됨",
+ "642da473f2": "알리다",
+ "6380517b10": "깃발",
+ "251c817bdd": "타이머",
+ "409528031f": "리뷰",
+ "5f9ca31a84": "대기 중",
+ "821d156f54": "점선",
+ "226d1e7773": "진전",
+ "a702bc08d4": "점",
+ "b4a7101fe1": "원",
+ "1a9383112b": "지휘자 진행",
+ "caebe3c10f": "Conductor 리뷰",
+ "895f381714": "지휘자 완료",
+ "caabd5ca85": "아연",
+ "7adb43ecf0": "장미",
+ "ddf25b6262": "에메랄드",
+ "7cebab6d4a": "호박색",
+ "1b81da243a": "제비꽃",
+ "6437a8c253": "하늘",
+ "fc3b92756c": "파란색",
+ "52e3c6e2a4": "중립적"
+ }
+ },
+ "worktree": {
+ "card": {
+ "compact": {
+ "agents": {
+ "a128d7006b": "{{value0}} {{value1}} 하위 {{value2}}",
+ "289a1d2ca7": "{{value0}}을 확장합니다. {{value1}}",
+ "0c1debfe84": "{{value0}} 접기"
+ }
+ }
+ },
+ "list": {
+ "groups": {
+ "0ed04075b8": "모두",
+ "4aeefc5996": "고정됨",
+ "682ed5d551": "닫힘",
+ "7c2f009786": "진행중",
+ "6798dc7c94": "리뷰 중",
+ "5076efc3d2": "완료"
+ }
+ }
+ },
+ "CacheTimer": {
+ "07729cc155": "만료됨"
+ },
+ "DeleteWorktreeDialogFooter": {
+ "c0e972d726": "취소",
+ "cf95e3b5bb": "닫기"
+ },
+ "index": {
+ "b826a98b6f": "바쁘다"
+ }
+ },
+ "shared": {
+ "useDaemonActions": {
+ "01af244097": "취소",
+ "28c8e53176": "그러면 모든 워크스페이스에서 실행 중인 모든 터미널 패널이 강제 종료됩니다. 해당 세션에서 저장하지 않은 작업은 모두 손실됩니다. 데몬 자체는 계속 실행되며 새 터미널을 즉시 열 수 있습니다. 이 작업은 취소할 수 없습니다.",
+ "1bbea41a77": "모든 터미널 세션을 종료하시겠습니까?",
+ "01d6b7c64e": "실행 중인 모든 터미널 패널을 종료하고 데몬 프로세스를 다시 시작합니다. 패널에는 \"프로세스 종료됨\"이 표시되며 즉시 다시 열 수 있습니다. 이전 앱 버전의 레거시 프로토콜 세션은 보존됩니다. 이 작업은 취소할 수 없습니다.",
+ "922548bc66": "터미널 데몬을 다시 시작하시겠습니까?",
+ "2b4efdc162": "세션을 종료할 수 없습니다.",
+ "d18f3005c2": "{{value0}} 세션{{value1}} 종료를 거부했습니다.",
+ "baad8cd651": "실행 중인 세션이 없습니다.",
+ "fe2ab66d45": "{{value1}} 세션 중 {{value0}}을(를) 종료했습니다. {{value2}}이(가) 종료를 거부했습니다.",
+ "d762b41f41": "다시 시작하지 못했습니다.",
+ "b5954e12d3": "다시 시작하지 못했습니다. 로그를 확인하세요.",
+ "0e9da1b98e": "데몬이 다시 시작되었습니다."
+ }
+ },
+ "setup": {
+ "guide": {
+ "SetupGuideModal": {
+ "3598a3ca0c": "Orca를 병렬 에이전트 작업에 유용하게 만드는 핵심 워크플로를 완료합니다.",
+ "48a9e5ef2d": "시작하기",
+ "28cf59fcb4": "이렇게 하면 사이드바에서 체크리스트가 숨겨집니다.",
+ "f3b5ffb2a6": "사이드바에서 체크리스트 숨기기"
+ },
+ "SetupGuideProgressRing": {
+ "dac3a4724a": "{{value1}} 중 {{value0}} 설정 단계 완료"
+ }
+ }
+ },
+ "settings": {
+ "AccountsPane": {
+ "c2d2751587": "계정 삭제",
+ "dbb9626ed1": "취소",
+ "854ebbcc45": "Orca는 저장된 계정에 대해 관리되는 Claude 인증을 삭제합니다. 현재 활성화된 경우 Orca는 시스템 기본 Claude 로그인으로 대체됩니다.",
+ "63843e37e2": "Claude 계정을 삭제하시겠습니까?",
+ "99c8f9e498": "Orca는 저장된 계정에 대해 관리되는 Codex 홈을 삭제합니다. 현재 활성화된 경우 Orca는 시스템 기본 Codex 로그인으로 대체됩니다.",
+ "0d47394635": "Codex 계정을 제거하시겠습니까?",
+ "ae3b21eb6c": "opencode.ai/workspace/wrk_…/go",
+ "51c9104e13": "opencode.ai에 로그인한 후 URL에서 이를 찾으세요(예:",
+ "b398b834c9": "지우기",
+ "a122332371": "wrk_… (자동 조회를 위해 비워두세요)",
+ "dbdb0b0bd8": "워크스페이스 ID 재정의",
+ "d70a5287a4": "자동 조회가 실패하면 선택적 워크스페이스 ID가 재정의됩니다.",
+ "02cb127710": "OpenCode Go 워크스페이스 ID",
+ "7ce0e1907c": "). 브라우저의 DevTools → 네트워크 → 모든 opencode.ai 요청 → 쿠키 헤더에서 찾으세요. OpenCode Go 인증은 웹 기반이며 Windows 및 WSL 터미널에서 공유됩니다.",
+ "8951c5309f": "인증=Fe26.2**…",
+ "338820326a": ") 또는 전체 쿠키 헤더(예:",
+ "922b51e02d": "Fe26.2**…",
+ "0023cc336e": "원시 토큰 값(예:",
+ "a7e38affcd": "Fe26.2**… 토큰 또는 auth=Fe26.2**… 헤더",
+ "67e3c33670": "OpenCode Go 세션 쿠키",
+ "b2b1aa936d": "속도 제한을 가져오려면 opencode.ai 세션 쿠키를 붙여넣으세요.",
+ "36223200ac": "OpenCode Go 세션 쿠키",
+ "ea631977b5": "OpenCode Go 공급자 설정을 구성합니다.",
+ "4ac10b4d08": "OpenCode Go",
+ "d708749337": ". 이는 Orca가 아닌 Gemini CLI 앱에 발급된 자격 증명을 사용합니다. Google이 CLI를 업데이트하면 중단될 수 있습니다. 자신의 책임하에 사용하십시오.",
+ "c2aee76420": "Google에 인증하기 위해 로컬 Gemini CLI 설치에서 OAuth 자격 증명을 추출합니다.",
+ "96f3649526": "Gemini CLI 자격 증명 사용(실험적)",
+ "d676c41fc6": "Google 인증을 위해 로컬 Gemini CLI 설치에서 OAuth 자격 증명을 추출합니다. 이는 Orca가 아닌 Gemini CLI 앱에 발급된 자격 증명을 사용합니다. Google이 CLI를 업데이트하면 중단될 수 있습니다. 자신의 책임하에 사용하십시오.",
+ "0c7f915b01": "Gemini CLI 자격 증명 사용",
+ "973741a871": "Gemini 공급자 설정을 구성합니다.",
+ "0c64dc2a64": "Gemini",
+ "db209ee572": "제거",
+ "8a0f870153": "재인증",
+ "3d245ef7d9": "Codex에서 이 로그인이 오래되었다고 보고했습니다.",
+ "589eba1eee": "재인증 필요",
+ "e74831fb6b": "활성",
+ "d46f735a85": ". Orca는 여기에 추가할 때까지 해당 환경의 시스템 기본 Codex 로그인을 사용합니다.",
+ "b4c9450319": "다음에 대한 관리되는 Codex 계정이 없습니다.",
+ "93c47b333a": "로그인 필요",
+ "f2a265f8c7": "시스템 기본값",
+ "b0e948a4f9": "계정 추가",
+ "5568bb6d5c": "계정. 여기에 새 계정이 추가됩니다.",
+ "c0a52abfc5": "표시 중",
+ "94d351af4a": "계정",
+ "d0d53b7eb0": "Orca가 실시간 속도 제한 가져오기에 사용하는 Codex 계정을 관리합니다.",
+ "3180536c7a": "Codex 계정",
+ "340d6f7a85": "각 계정은 Orca에서 자체 로컬 로그인 컨텍스트를 유지합니다. 계정 인증은 이 기기에 유지됩니다.",
+ "cedfab35ab": "선택 사항. Orca는 일반 Codex 로그인을 사용할 수 있습니다. Orca에서 빠른 전환을 원하는 경우에만 계정을 추가하세요.",
+ "ef91cfa06b": "Codex",
+ "dea08560b4": ". Orca는 여기에 로그인을 추가할 때까지 해당 환경의 시스템 기본 Claude 로그인을 사용합니다.",
+ "3fe7862418": "다음에 대한 관리된 Claude 계정이 없습니다.",
+ "3455cf43fa": "Claude 로그인.",
+ "fcc4093fc1": "현재 {{value0}} Codex 로그인을 사용하세요.",
+ "79e484c3b2": "공유 Claude 인증 파일에 대한 선택적 계정 전환기입니다.",
+ "8bbfd74556": "Claude 계정",
+ "72b36ea174": "선택 사항. Orca는 일반적인 Claude 로그인을 사용할 수 있습니다. 채팅 세션을 이동하지 않고 빠르게 전환하려는 경우에만 계정을 추가하세요.",
+ "26ef4b55be": "Claude",
+ "2743cdc0af": "Claude 계정 업데이트에 실패했습니다.",
+ "b15ce90870": "{{value0}} -> {{value1}}. 이전 세션을 계속하기 전에 라이브 Claude 터미널을 다시 시작하십시오.",
+ "f921d32606": "Claude 계정이 업데이트되었습니다.",
+ "5bf8764953": "Codex 계정 업데이트에 실패했습니다.",
+ "2358ac71d2": "WSL 기본값",
+ "ad47a33f72": "WSL 로드 중",
+ "8619f9afa9": "WSL",
+ "46cf7e7495": "계정 위치",
+ "0b4591ff93": "검사할 로컬 환경과 새로운 관리 Claude 및 Codex 계정이 추가되는 위치를 선택하세요.",
+ "0c67a2a1aa": "이 컴퓨터에서는 WSL을 사용할 수 없습니다.",
+ "2cd197025c": "{{value0}} 또는 WSL에서 공급자 계정을 검사하고 추가할지 선택합니다.",
+ "f54b4fbd71": "계정 위치",
+ "9107406589": "Claude 계정을 로드할 수 없습니다.",
+ "b8c2905c2b": "Codex 계정을 로드할 수 없습니다.",
+ "fd62f37c24": "Codex는 이 {{value0}} 로그인이 오래되었다고 보고했습니다.",
+ "b10cb4f696": "추가 중",
+ "e4a28e8894": "Codex는 {{value0}} 로그인에 새로 로그인해야 한다고 보고했습니다. 새 Codex 세션을 시작하기 전에 다시 로그인하세요.",
+ "75ca9b718e": "Codex는 활성 계정에 새로 로그인해야 한다고 보고했습니다. 새 Codex 세션을 시작하기 전에 다시 인증하세요.",
+ "b11078a9c2": "wsl"
+ },
+ "AdvancedPane": {
+ "40b29e0bf3": "다시 시작",
+ "87a2cb2ac8": "Orca는 시작 시 이 네트워킹 모드를 적용합니다.",
+ "89958d7edf": "다시 시작해야 함",
+ "b3ad629640": "회사 VPN 또는 프록시가 HTTP/2 프로토콜 오류로 인해 업데이트 다운로드를 중단하는 경우에만 사용하십시오. 다시 시작한 후 모든 Electron 네트워킹에 영향을 미칩니다.",
+ "6627e75c92": "HTTP/1.1 호환성 설명",
+ "e9506d3377": "HTTP/1.1 호환성",
+ "8b7a8df299": "지원 문제 해결을 위한 낮은 수준의 해결 방법입니다.",
+ "8d8d8ac599": "호환성"
+ },
+ "AgentLocationSetting": {
+ "92f4238f1a": "WSL 기본값",
+ "fc806485ae": "WSL 로드 중",
+ "43663b5e69": "WSL",
+ "9bccf48906": "에이전트 위치",
+ "d00949e59b": "{{value0}}에서 설치된 에이전트를 표시합니다. 새로 고침은 해당 환경에서 PATH를 다시 확인합니다.",
+ "c7c516946f": "이 컴퓨터에서는 WSL을 사용할 수 없습니다.",
+ "f97b986b7f": "wsl"
+ },
+ "AgentSkillSetupPanel": {
+ "0b810ec59f": "Enter를 눌러 설치 명령을 실행하십시오.",
+ "ed197f59a2": "명령 복사",
+ "817d3f9f18": "설치 명령 복사",
+ "5289300939": "설치되지 않음",
+ "9fcebceb2a": "설치됨",
+ "68a468752e": "확인 중...",
+ "c689392435": "재확인",
+ "a31e2aa302": "설치 명령을 복사하지 못했습니다.",
+ "378ad26865": "설치 명령을 복사했습니다."
+ },
+ "AgentsPane": {
+ "d83834f5e6": "설치된 에이전트 감지 중…",
+ "024bd95089": "에이전트",
+ "e8da2af684": "설치 가능",
+ "ed3e110e61": "감지됨",
+ "02e0143be5": "설치됨",
+ "110b74b022": "에이전트 없음(빈 터미널)",
+ "92033495ff": "자동",
+ "9b175d0f5e": "새 워크스페이스를 열 때 미리 선택된 에이전트입니다.",
+ "385212c7a1": "기본 에이전트",
+ "f9f127d664": "이 에이전트를 시작하는 데 사용되는 바이너리 경로 또는 이름을 재정의합니다.",
+ "f95b5c79b8": "설치",
+ "fe4d630c94": "문서",
+ "8dc0192e48": "비활성",
+ "df123171d1": "설치되지 않음",
+ "c8794e622e": "감지됨",
+ "5200dac9da": "재설정",
+ "2e45ca29b6": "명령",
+ "d4d2a45d63": "활성화됨",
+ "1c9a9679ec": "{{value0}} 사용 가능 여부",
+ "0d9e293a02": "새로고침",
+ "c9b33eb5c0": "새로고침 중…",
+ "13647f9f80": "쉘 PATH를 다시 읽고 설치된 에이전트를 다시 검색하십시오.",
+ "dc4a2ffdc0": "확장 명령 재정의",
+ "cea7d97be1": "축소 명령 재정의",
+ "db9e9e5887": "명령 사용자 정의",
+ "959b67385b": "기본값 설정",
+ "24e032fa34": "기본",
+ "5f986a9b92": "기본값으로 설정",
+ "d7625cf8b2": "기본 에이전트"
+ },
+ "AppIconSelector": {
+ "d5a112dc9b": "다음 아이콘",
+ "415fa76f64": "선택한 앱 아이콘",
+ "5f5142a62a": "이전 아이콘"
+ },
+ "AppearancePane": {
+ "3057983501": "할당되지 않음",
+ "0cd9b8228f": "Dock 및 창 전환기에 표시된 앱 아이콘을 선택합니다.",
+ "ca1590d42f": "앱 아이콘",
+ "61d842eca0": "사이드바에 Orca Mobile 바로가기를 표시합니다. 도구 상자에서는 계속 사용할 수 있습니다.",
+ "9da1020447": "Orca 모바일 버튼 표시",
+ "5db6ba961f": "왼쪽 사이드바 상단에 Orca Mobile 버튼을 표시합니다.",
+ "fa882a3e6b": "왼쪽 사이드바 상단에 자동화 버튼을 표시합니다.",
+ "511f270ebb": "자동화 버튼 표시",
+ "661942ab7f": "왼쪽 사이드바 상단에 작업 버튼을 표시합니다.",
+ "cf81907069": "작업 버튼 표시",
+ "dc29f3cc0d": "사이드바",
+ "ea943d0db0": "창 하단에 표시되는 표시기를 선택합니다. 동일한 토글에 대해 상태 표시줄을 마우스 오른쪽 버튼으로 클릭할 수도 있습니다.",
+ "3e4175e5c6": "상태 표시줄",
+ "2df8f79aa5": "제목 표시줄에 Orca를 표시합니다.",
+ "9868f39007": "제목 표시줄 앱 이름",
+ "4de76f6902": "애플리케이션 제목 표시줄에 나타나는 내용을 제어합니다.",
+ "6a272ca553": "제목 표시줄",
+ "e9f2ca5582": "파일 탐색기에서 .gitignore와 일치하는 파일을 숨기려면 끄십시오.",
+ "0fafabcf35": "Git이 무시한 파일 표시",
+ "75f07ab60c": "파일 탐색기에서 .gitignore와 일치하는 파일을 표시합니다.",
+ "d496901cd0": "파일 탐색기",
+ "42554f615f": "Orca 인터페이스에서 사용되는 글꼴을 선택합니다.",
+ "102d6b5f9b": "IDE 글꼴",
+ "ef89200c1f": "터미널 패널에 없을 때.",
+ "f687711a9b": "전체 애플리케이션 인터페이스를 확장합니다. 사용",
+ "5e6d7aba8d": "UI 줌",
+ "622e1c3465": "전체 애플리케이션 인터페이스를 확장합니다.",
+ "fd89b5487c": "빛",
+ "7d26ccabe8": "다크",
+ "fb0e0b4453": "체계",
+ "932ff1fbff": "주제",
+ "0f28e7b30c": "Orca가 앱 창에 표시되는 방식을 선택합니다."
+ },
+ "AutoRenameBranchFromWorkSetting": {
+ "1626524572": "Nautilus",
+ "0de9fda203": "버리기",
+ "c71770c455": "{basePrompt}",
+ "f19a56498d": "; 브랜치 접두사 설정이 계속 적용됩니다.",
+ "800edb1e54": "수정 로그인 흐름",
+ "5d569f5199": ". Orca는 다음과 같은 마지막 세그먼트만 생성합니다.",
+ "570817d126": "그리고",
+ "56580dcf60": ". 참고하실 수도 있습니다",
+ "9c9b54e4ea": "내장된 브랜치 이름 프롬프트",
+ "69bf4830c2": "Orca도 포함",
+ "9241b59bf5": "사용",
+ "a869d0edd8": "브랜치 이름 명령 템플릿",
+ "e784ea62dc": "고급",
+ "d9b65054ef": ") 작업을 요약하는 짧은 이름으로 변경됩니다. Orca라는 이름의 브랜치만 이름이 변경되며 푸시된 후에는 이름이 변경되지 않습니다.",
+ "12ea4a408d": "에이전트가 새 워크스페이스에서 작업을 시작하면 Orca는 자동 생성된 브랜치의 이름을 바꿉니다(예:",
+ "ef787db0e3": "브랜치 자동 이름 바꾸기",
+ "6a051586d2": "에이전트가 시작되면 작업을 기반으로 자동 생성된 브랜치의 이름을 바꿉니다.",
+ "ec3e0c388e": "저장",
+ "cfd82406dd": "저장 중...",
+ "40e7be7850": "저장됨",
+ "7c7e34a66d": "저장되지 않은 변경사항",
+ "a4fa380b67": "{어시스턴트메시지}",
+ "2ee2779c05": "{첫 번째 프롬프트}"
+ },
+ "AutoRenameBranchPromptEditor": {
+ "63121132c0": "버리기",
+ "4416b25d29": "작업에서 도메인 명사를 선호하고, 티켓 ID를 피하고, 리뷰어 친화적인 이름을 유지하세요.",
+ "39278f4411": "; 브랜치 접두사 설정이 계속 적용됩니다.",
+ "ebb942a2ec": "수정 로그인 흐름",
+ "af2d9a2cc6": ". Orca는 다음과 같은 마지막 세그먼트만 생성합니다.",
+ "182d419b97": "내장된 브랜치 이름 프롬프트",
+ "2f5dc661fe": "Orca에 추가됨",
+ "7d6176f506": "즉각적인",
+ "5968112152": "저장",
+ "54ac229ad4": "저장 중...",
+ "af0831a590": "저장됨",
+ "0691753cf2": "저장되지 않은 변경사항"
+ },
+ "BaseRefPicker": {
+ "1b8e54151f": "일치하는 브랜치를 찾을 수 없습니다.",
+ "d166ff883d": "현재",
+ "a4a9372eb2": "브랜치 검색 중...",
+ "7db7fb87e5": "이름으로 브랜치 검색...",
+ "773a5687a3": "기본 사용",
+ "ade9a5bb03": ") 결과 범위를 지정합니다.",
+ "b468f46726": "업스트림/메인",
+ "80f7c82303": ") 또는 전체 참조(예:",
+ "915ad97875": "상류",
+ "a5c16712c1": "여러 개의 원격이 감지되었습니다. 원격 이름을 입력하세요(예:",
+ "9a14ec7400": "아래에서 기본 브랜치를 선택하세요.",
+ "086ce7f369": "다음 기본 브랜치({{value0}})",
+ "2f3cda96f5": "이 저장소에 고정됨",
+ "ee110e1830": "기본 기본 참조 없음"
+ },
+ "BrowserDefaultZoomSetting": {
+ "2622126877": "새로 열린 브라우저 탭에 확대/축소 수준이 적용되었습니다.",
+ "bbeec087d3": "새로 열린 브라우저 탭에 적용됩니다.",
+ "265597101f": "기본 줌"
+ },
+ "BrowserHomePageSetting": {
+ "d4ddcd0056": "저장",
+ "37a30c5bfd": "https://google.com",
+ "c6cbd1c105": "홈페이지가 저장되었습니다.",
+ "6a37540f4b": "새 브라우저 탭을 만들 때 열리는 URL입니다. 빈 탭을 열려면 비워 두세요.",
+ "70224e37b1": "기본 홈 페이지"
+ },
+ "BrowserPane": {
+ "81ff774667": "취소",
+ "7d4c0a2aa4": "프로필 이름",
+ "612f7f6861": "프로필을 생성하지 못했습니다.",
+ "8f22b7580d": "프로필 '{{value0}}'이(가) 생성되었습니다.",
+ "8481ee0331": "새 브라우저 프로필",
+ "6f2584b39e": "프로필 추가",
+ "e4aaf8051b": "도구 모음 메뉴.",
+ "cd47bc9622": "새 브라우저 탭의 기본 프로필을 선택합니다. 쿠키를 가져오고 탭별로 프로필을 전환합니다.",
+ "2d66a6efb5": "세션 및 쿠키",
+ "aa1074bfe9": "브라우저 프로필을 관리하고 Chrome, Edge, Comet 또는 기타 브라우저에서 쿠키를 가져옵니다.",
+ "113cd2dc9b": "세션 및 쿠키",
+ "d3eb69c0aa": "링크 라우팅",
+ "3e46903ad4": "주소 표시줄에 URL이 아닌 텍스트를 입력할 때 사용됩니다.",
+ "0d9c987f21": "기본 검색 엔진",
+ "7b225c78f5": "주소 표시줄에 URL이 아닌 텍스트를 입력할 때 사용되는 검색 엔진입니다.",
+ "64898ecdab": "생성",
+ "7b649a578a": "만드는 중…",
+ "4399c77caa": "기본",
+ "4af9a17947": "카기"
+ },
+ "BrowserProfileRow": {
+ "8e636cae25": "프로필 '{{value0}}'이(가) 삭제되었습니다.",
+ "2d4bea7f35": "기본 쿠키가 삭제되었습니다.",
+ "ebb78dfd6f": "파일에서…",
+ "7df818977e": "에서",
+ "cdec84552f": "쿠키 가져오기",
+ "796d846483": "가져온 쿠키가 없습니다.",
+ "c29648fe5b": "활성",
+ "d420c43729": "{{value1}}{{value2}}에서 {{value3}}로 {{value0}} 쿠키를 가져왔습니다."
+ },
+ "BrowserUseComputerUseNotice": {
+ "15b5e680ba": "열린 컴퓨터 사용",
+ "79209b37b9": "쿠키 가져오기가 적합하지 않은 경우 컴퓨터 사용은 로컬 앱을 제어할 수 있으며 해당되는 경우 기존 로그인 브라우저 세션을 사용할 수 있습니다. Computer Use 스킬을 설치하십시오. macOS에도 개인정보 보호 권한이 필요합니다.",
+ "333984cf90": "기존 브라우저 세션 사용"
+ },
+ "BrowserUseEnableSwitch": {
+ "aea3f45349": "에이전트 브라우저 사용 활성화"
+ },
+ "BrowserUseExamples": {
+ "1199258ace": "복사",
+ "1188e56af4": "예시 프롬프트 복사",
+ "b84807f228": "\"",
+ "59722f31b4": "\"",
+ "c5325e91f6": "이 중 하나를 Claude Code, Codex 또는 해당 스킬이 설치된 프로젝트의 다른 에이전트에 붙여넣으세요.",
+ "2a180694f7": "시도해 보세요 - 예시 프롬프트",
+ "5ec620ccc4": "복사하지 못했습니다.",
+ "a602d43069": "{{value0}}을(를) 복사했습니다."
+ },
+ "BrowserUsePane": {
+ "be6df68384": "파일에서…",
+ "e44c5d681e": "에서",
+ "67d9a53f47": "별도의 로그인을 위한 프로필 관리",
+ "112f70adc4": "마지막으로 가져온 위치",
+ "72d4815523": "에이전트가 인증된 페이지에 접근할 수 있도록 기존 로그인을 Orca로 가져오세요. 기본 프로필로 가져옵니다.",
+ "2eb906706c": "브라우저 쿠키 가져오기",
+ "af8c83ed61": "에이전트가 로그인을 재사용할 수 있도록 Chrome, Edge 또는 기타 브라우저에서 쿠키를 가져옵니다.",
+ "68ea76eb71": "에이전트가 Orca의 브라우저를 작동할 수 있도록 브라우저 사용 스킬을 설치하세요.",
+ "2d6ead9ab2": "브라우저 사용 스킬 설치",
+ "e9f3f3b488": "설치 위치",
+ "9fca1f7f5d": "에이전트가 셸에서 브라우저를 조정할 수 있도록 Orca CLI 명령을 등록합니다.",
+ "c6065d205d": "Orca CLI 활성화",
+ "c79eff0213": "에이전트가 브라우저를 구동할 수 있도록 Orca CLI를 등록하세요.",
+ "702488a5f7": "코딩 에이전트가 로그인을 통해 이 브라우저를 구동하게 하세요. 아래 세 단계를 완료하세요.",
+ "b8a1f2d84d": "에이전트 브라우저 사용",
+ "96b91c6349": "코딩 에이전트가 로그인을 통해 이 브라우저를 구동하게 하세요.",
+ "2ea4617e3a": "{{value1}}{{value2}}에서 {{value0}} 쿠키를 가져왔습니다.",
+ "721aee31b4": "PATH에 Orca CLI를 등록했습니다.",
+ "180a9abf3a": "CLI 상태를 로드하지 못했습니다.",
+ "2ccfc9cff8": "수입",
+ "0462565413": "다시 가져오기",
+ "de9b2f32f3": "활성화",
+ "ad8cb0ee22": "경로 수정",
+ "0289434ed6": "활성화됨",
+ "8b3054dac7": "등록 중..."
+ },
+ "BrowserUseSkillStep": {
+ "0871b6998d": "에이전트가 Orca 브라우저에서 페이지를 탐색하고 확인할 수 있습니다.",
+ "459e24eebc": "Browser Use 스킬"
+ },
+ "CliSection": {
+ "8671e406f0": "취소",
+ "a4aafe46e3": "대상 경로:",
+ "e8012c03a1": "에이전트가 Orca 워크스페이스, 터미널 및 진행 명령을 사용할 수 있도록 합니다.",
+ "6053cf736c": "CLI 스킬",
+ "36a6f919ba": "에이전트에게 Orca 인식 워크스페이스, 터미널 및 진행 워크플로를 제공합니다.",
+ "04873eea3e": "에이전트 스킬",
+ "7f2747f7dd": "현재 이 셸의 PATH에 표시되지 않습니다.",
+ "b0c310ab46": "기존 실행기 대상:",
+ "15eaad0d31": "명령 경로:",
+ "5dae812f50": "새로고침",
+ "52e640f3a0": "CLI 상태 새로 고침",
+ "38edbb5721": "쉘 명령",
+ "6930feda9e": "터미널에서 Orca를 사용하여 앱을 열고, 작업 트리를 관리하고, Orca 터미널과 상호 작용할 수 있습니다.",
+ "c5c0f2641d": "Orca CLI",
+ "d77352f2df": "PATH에서 `{{value0}}`을(를) 제거하지 못했습니다.",
+ "af5540930c": "PATH에서 `{{value0}}`을 제거했습니다.",
+ "a2b13efa94": "PATH에 `{{value0}}`을(를) 등록하지 못했습니다.",
+ "9cbcd31338": "PATH에 `{{value0}}`을 등록했습니다.",
+ "7baec27029": "CLI 상태를 로드하지 못했습니다.",
+ "d00df2e397": "등록",
+ "9a5f8a4568": "제거",
+ "b0fca411a0": "등록 중…",
+ "4c7e3e4c5f": "설치",
+ "068552b191": "제거 중…",
+ "8d96213669": "제거",
+ "aa6536977e": "Orca는 {{value0}}을 등록하므로 명령이 터미널에서 작동합니다.",
+ "a030816e3e": "그러면 쉘 명령 심볼릭 링크가 제거됩니다. Orca 자체는 설치된 상태로 유지됩니다.",
+ "fa87db3d6e": "PATH에 `{{value0}}`을 등록하시겠습니까?",
+ "14444243ba": "PATH에서 `{{value0}}`을(를) 제거하시겠습니까?",
+ "5d432fe44d": "설치됨",
+ "8a9b784c60": "탁한",
+ "d363e5929b": "CLI 등록 확인 중…"
+ },
+ "CliSkillRuntimeSetup": {
+ "04325573f8": "WSL",
+ "a58ba464ad": "스킬 위치",
+ "0ed08febc5": "WSL 셸 명령을 등록하지 못했습니다.",
+ "3728a94fb6": "WSL 셸 명령에 주의가 필요함",
+ "775a4cfbb8": "WSL 셸 명령 등록을 사용할 수 없습니다.",
+ "c47127f222": "WSL 기본값",
+ "0c9f3cf9da": "Orca가 글로벌 에이전트 스킬을 확인하고 설치하는 위치를 선택합니다.",
+ "f00d6aa9b5": "이 컴퓨터에서는 WSL을 사용할 수 없습니다.",
+ "7c776ff9d8": "wsl",
+ "fc0fcf72fd": "스킬 설정 전 WSL 쉘 명령어를 등록하세요."
+ },
+ "CommitMessageAiPane": {
+ "841ed9884a": "소스 제어 AI를 사용자 정의하지 않은 리포지토리에서 사용됩니다.",
+ "ad66ff886d": "소스 제어 AI 기본값",
+ "347094560b": "전역 호스팅 PR 기본값을 상속하는 저장소에서 사용됩니다.",
+ "2dafc7646e": "호스팅 리뷰 생성 기본값",
+ "e9d46a544d": "호스팅 PR 작성기가 열릴 때 사용되는 기본값입니다.",
+ "b125eabffa": "제출 후 브라우저에서 생성된 호스팅 리뷰를 엽니다.",
+ "7662715213": "생성 후 호스팅 PR 열기",
+ "b27b0809f3": "작성기가 열리면 호스팅 PR 세부 정보 생성을 한 번 실행합니다.",
+ "d5f0de6309": "PR 생성을 열 때 세부정보 생성",
+ "6278c0ce43": "설명이 설정되지 않은 경우 저장소 PR 템플릿을 선호합니다.",
+ "d8b6764d79": "가능한 경우 리뷰 템플릿을 사용하세요.",
+ "e001734396": "작성기에서 변경하지 않는 한 호스팅된 리뷰를 초안으로 생성합니다.",
+ "6ba48f07a4": "기본적으로 초안",
+ "15b60d54b2": "예를 들어 ollama는 llama3.1을 실행합니다. {프롬프트}",
+ "3f1b26cc91": "명령 입력을 인수로 전달합니다. 그렇지 않으면 Orca가 이를 stdin에 파이프합니다.",
+ "4f722a5f53": "사용자 지정 명령을 선택하는 커밋 메시지, PR 및 브랜치 이름 레시피에서 사용됩니다. 사용",
+ "47e45cbd5a": "사용자 정의 명령",
+ "1ef29f8c29": "명령줄 Orca는 텍스트 레시피가 사용자 정의 명령을 사용할 때 실행됩니다.",
+ "2339a89104": "해당 작업에 대한 명령 템플릿을 사용하여 선택한 에이전트를 실행하는 AI 버튼을 추가합니다.",
+ "d5b45a3628": "소스 제어 AI 작업 표시",
+ "7bcad2b200": "소스 제어 커밋, PR, 브랜치 이름 및 수정 작업에 대한 작업 레시피를 추가합니다.",
+ "d54c64163d": "활성화됨",
+ "4ec89c319e": "에이전트",
+ "34d0348e34": "생성",
+ "8cd2be0948": "메시지",
+ "ca433708cb": "저지르다",
+ "0b7eafe55f": "일체 포함",
+ "2c5436c018": "열림",
+ "6c84ba6de3": "주형",
+ "ebed4d2a29": "초안",
+ "02bab6542c": "PR",
+ "fdee745b87": "MR",
+ "b388463881": "PR",
+ "19e10a12bb": "호스팅 PR",
+ "b8b6fd55b4": "{즉각적인}",
+ "fc1a525fa5": "자리 표시자",
+ "a69e1fe91a": "즉각적인",
+ "1df7d71313": "바이너리",
+ "407d28bde6": "CLI",
+ "54038660e0": "명령",
+ "25350d670f": "custom"
+ },
+ "ComputerUsePane": {
+ "1735461723": "에이전트가 로컬 데스크톱 앱을 검사하고 작동할 수 있습니다.",
+ "93255aaf18": "Computer Use 스킬",
+ "45f8e22c2e": "열기",
+ "d95d1cfab8": "새로고침",
+ "0c29da5805": "준비됨",
+ "3383ea1aab": "컴퓨터 사용 권한을 재설정할 수 없습니다.",
+ "f189f448a3": "컴퓨터 사용 액세스 재설정",
+ "5c45349665": "컴퓨터 사용 권한을 열 수 없습니다.",
+ "7801ac08ec": "컴퓨터 사용 권한은 macOS에서만 필요합니다.",
+ "740766c291": "컴퓨터 사용 설정이 이미 완료되었습니다.",
+ "697005758f": "macOS 개인정보 보호 및 보안 오픈",
+ "2168fa5ab0": "컴퓨터 사용 권한을 로드할 수 없습니다.",
+ "0c9a33f468": "에이전트가 시각적 상태를 검사할 수 있도록 앱 창을 캡처합니다.",
+ "07bbe4c4cb": "스크린샷",
+ "4d03dec2d0": "앱 인터페이스 트리를 읽고 요청된 작업을 수행합니다.",
+ "6b5a2cd3a5": "접근성",
+ "6b17602073": "액세스 재설정",
+ "506f2acf7a": "액세스 재설정 중...",
+ "4b65070096": "darwin"
+ },
+ "DeveloperPermissionsPane": {
+ "4c17304beb": "새로고침",
+ "6326a4c5cc": "CLI, 로컬 앱 또는 자동화 도구에 macOS 개인 정보 보호 액세스가 필요한 경우 이러한 컨트롤을 사용하십시오. Orca는 시작 시 묻지 않습니다.",
+ "6f011b9bf6": "터미널 도구는 Orca의 macOS 개인 정보 보호 봉투를 상속합니다.",
+ "bfa3402305": "권한을 요청할 수 없습니다.",
+ "66e94d6cf3": "권한 요청이 전송되었습니다.",
+ "fa809e8ada": "macOS 개인정보 보호 및 보안 오픈",
+ "48d87edcd2": "허가가 부여되었습니다",
+ "a552887288": "개발자 권한을 로드할 수 없습니다.",
+ "4cfaa7e98a": "블루투스 장치 도구 및 로컬 하드웨어 실험.",
+ "b2210b1b4f": "블루투스",
+ "dfbc12c8c8": "USB 장치와 통신하는 하드웨어 디버깅 및 장치 도구입니다.",
+ "bf51e4a542": "USB 장치",
+ "f903bf20b5": "네트워크의 개발 서버를 검색하고 액세스합니다.",
+ "e7bb06007c": "로컬 네트워크",
+ "4a73f5217a": "다른 로컬 앱을 제어하는 스크립트를 위한 Apple 이벤트.",
+ "e119f0d66b": "오토메이션",
+ "7ca17b62c8": "터미널 세션에서 보호된 폴더에 대한 지속적인 액세스.",
+ "c566bca278": "전체 디스크 액세스",
+ "9f35980756": "키 입력 주입, 창 제어 및 UI 자동화 도구입니다.",
+ "5b2f22ca2d": "접근성",
+ "0639db5496": "스크린샷, 시각적 자동화, UI 검사 도구.",
+ "f24f31a884": "화면 녹화",
+ "550cfa3750": "웹캠 캡처 및 카메라 기반 로컬 테스트 앱.",
+ "e5b5f3d6b9": "카메라",
+ "cc8151d9fa": "음성 입력, 전사, 오디오 녹음, sox, ffmpeg 및 Whisper CLI.",
+ "16381e040a": "마이크로폰",
+ "dac08ec03e": "작업 중..."
+ },
+ "ExperimentalPane": {
+ "9762364929": "생성된 작업 트리에 연결해야 하는 특정 폴더 또는 파일의 자동 심볼릭 링크를 허용합니다.",
+ "24416f42cd": "작업 트리의 심볼릭 링크",
+ "fb82ea1d7a": "구성된 파일이나 폴더를 새로 생성된 작업 트리에 자동으로 심볼릭 링크합니다.",
+ "a20d5ea365": "해당 패널과 상호 작용할 때까지 터미널 벨 또는 에이전트 완료 이벤트 후에 패널 수준 강조 표시를 유지합니다. 신호를 조정하는 동안 실험적입니다.",
+ "ec897e8d89": "터미널 주의",
+ "88b7613afb": "터미널 벨 및 에이전트 완료 이벤트에 대한 지속적인 패널 강조 표시입니다.",
+ "0277901cf7": "완료된 에이전트, 차단 질문, 읽지 않은 상태 및 작업 트리 생성 이벤트에 대한 스레드 작업 트리 피드가 있는 에이전트 항목을 왼쪽 사이드바에 추가합니다. 실험적 — 이벤트 모델과 UI가 변경될 수 있습니다.",
+ "a05bcdaf57": "에이전트 보기",
+ "f63ea281e3": "에이전트 완료 및 차단 상태에 대한 스레드 왼쪽 사이드바 피드입니다.",
+ "ca2219fe5e": "오른쪽 하단에 고정된 작은 애니메이션 애완동물을 표시합니다. 캐릭터(Claudino, OpenCode, Gremlin)를 선택하거나 상태 표시줄 애완동물 메뉴에서 자신만의 PNG, APNG, GIF, WebP, JPG 또는 SVG를 업로드하세요. 이 설정을 비활성화하지 않고 동일한 메뉴에서 언제든지 숨길 수 있습니다.",
+ "dd6f0a1d45": "애완 동물",
+ "0e89a574ae": "오른쪽 하단에 떠 있는 애니메이션 애완동물."
+ },
+ "FloatingWorkspacePane": {
+ "aeaf76fda9": "상태 표시줄",
+ "9fb225f2d7": "플로팅 버튼",
+ "3c900e26e5": "키보드 단축키는 토글이 표시되는 위치에 관계없이 작동합니다.",
+ "5e5a8da236": "토글 버튼 위치",
+ "505001823e": "플로팅 워크스페이스 디렉토리 선택",
+ "81afb79785": "새로운 플로팅 터미널 탭이 여기에서 시작됩니다. 마크다운 메모는 Orca의 앱 소유 플로팅 워크스페이스에 저장됩니다.",
+ "12aa09f10c": "터미널 디렉토리",
+ "41eb95f7f0": "플로팅 워크스페이스 버튼과 패널을 표시합니다.",
+ "5136813663": "플로팅 워크스페이스 활성화",
+ "37df688d6f": "플로팅 워크스페이스를 활성화하고 새 탭이 시작되는 위치를 선택하세요.",
+ "1f67f39384": "플로팅 워크스페이스"
+ },
+ "GeneralCacheTimerSection": {
+ "05de84a104": "1시간",
+ "54395ecd7c": "5분",
+ "8b9e202e0a": "이를 공급자의 캐시 TTL과 일치시킵니다. 기본값은 5분입니다.",
+ "a2a8962138": "타이머 기간",
+ "b4e7302944": "캐시 타이머",
+ "487b176240": "Claude 에이전트가 유휴 상태가 되면 사이드바에 카운트다운을 표시합니다.",
+ "9c20253679": "Claude 에이전트가 유휴 상태가 되면 카운트다운을 표시합니다.",
+ "fe590653c1": "Claude는 비용을 줄이기 위해 대화를 캐시합니다. 너무 오랫동안 유휴 상태가 되면 캐시가 만료되고 다음 메시지는 더 높은 비용으로 전체 컨텍스트를 다시 보냅니다. 카운트다운이 표시되므로 언제 재개해야 하는지 알 수 있습니다.",
+ "a137f8854d": "프롬프트 캐시 타이머",
+ "80c454e8a6": "이를 공급자의 캐시 TTL과 일치시킵니다."
+ },
+ "GeneralEditorSettingsSection": {
+ "f80603d293": "리치 에디터 모드 및 에이전트 전달 작업에서 로컬 마크다운 메모 컨트롤을 표시합니다.",
+ "4edc104f0f": "마크다운 리뷰 노트",
+ "5f02e6fb21": "리치 에디터 모드에서 로컬 마크다운 리뷰 노트 컨트롤을 표시합니다.",
+ "51161d1647": "파일을 편집할 때 미니맵 개요를 표시합니다.",
+ "6690b1ffb9": "미니맵",
+ "5a1ea6eaa2": "숨겨진",
+ "73a09aad63": "표시됨",
+ "1de48ad940": "기본 Diff 파일 트리",
+ "1b87897af9": "결합된 차이점 보기를 열 때 파일 트리를 표시하거나 숨깁니다.",
+ "12cbc0d0d6": "나란히",
+ "05b6df93b3": "인라인",
+ "7311f67ee7": "기본 차이점 보기",
+ "b492397d34": "기본적으로 git diff를 표시하기 위해 선호되는 프레젠테이션 형식입니다.",
+ "a5db1d3975": "ms",
+ "fc5c5306ff": "ms.",
+ "8112cd6dcf": "Orca가 마지막 편집 후 자동으로 저장되기까지 기다리는 시간입니다. 첫 번째 실행의 기본값은 다음과 같습니다.",
+ "d6cf227ca0": "자동 저장 지연",
+ "1bec6d8318": "Orca가 마지막 편집 후 자동으로 저장되기까지 기다리는 시간입니다.",
+ "70bb30feb1": "잠시 후에 편집기 및 편집 가능한 diff 변경 사항을 자동으로 저장합니다.",
+ "0df2e4fd12": "자동 저장 파일",
+ "d21136d9ef": "Orca가 파일 편집을 유지하는 방법을 구성합니다.",
+ "45c6e85c4d": "편집자"
+ },
+ "GeneralNetworkSettingsSection": {
+ "3e431564b5": "로컬호스트, 127.0.0.1, *.internal",
+ "33ee3ca3af": "선택 사항. 쉼표, 세미콜론 또는 새 줄로 호스트를 구분합니다.",
+ "f6d76cc8f4": "프록시 우회 규칙",
+ "fb7130dcb9": "구성된 HTTP 프록시를 우회해야 하는 호스트입니다.",
+ "0adfce9fa7": "http, https, 양말, 양말4 및 양말5 URL을 지원합니다.",
+ "476f302aca": "http://proxy.example.com:8080",
+ "1e214e265a": "시스템 프록시 설정 및 상속된 프록시 환경 변수를 사용하려면 비워 두세요.",
+ "f00daf6324": "HTTP 프록시",
+ "823e0f15b1": "Orca 네트워크 요청 및 로컬 터미널 하위 항목에 대한 프록시 URL입니다.",
+ "d93c7cd531": "앱 수준 네트워크 라우팅을 구성합니다.",
+ "c46cdbbd4e": "회로망"
+ },
+ "GeneralPane": {
+ "d58fccfd84": "항해"
+ },
+ "GeneralSupportSection": {
+ "af7d9f4396": "지원해 주셔서 감사합니다!",
+ "6922c1fa2b": "GitHub의 스타 Orca",
+ "511782265b": "gh CLI를 통해 GitHub 스타로 프로젝트를 지원하세요.",
+ "55a87e5fd1": "Orca 지원",
+ "964acc6bb4": "별",
+ "73b327e793": "다시 시도",
+ "c9f96d4234": "오류",
+ "397719bee5": "스타 표시 중...",
+ "1e29570462": "스타 표시",
+ "9d181300e3": "별표가 붙은",
+ "5c49f02662": "숨겨진",
+ "b3f0584f5d": "로드 중"
+ },
+ "GeneralUpdateSettingsSection": {
+ "8a52ca1d02": "릴리스 노트",
+ "d89806cc89": "설치할 준비가 되었습니다.",
+ "a6b37929dc": "버전",
+ "8311da27ba": "사용할 수 있습니다. \"업데이트 설치\"를 클릭하여 다운로드하고 설치하세요.",
+ "f44299636f": "업데이트하려면 다시 시작하세요(",
+ "42717918f4": "업데이트 설치(",
+ "02dc082e70": "업데이트 다운로드를 시작할 수 없습니다.",
+ "e1a647adc5": "업데이트 확인",
+ "ceb579abaf": "앱 업데이트를 확인하고 최신 Orca 버전을 설치하세요.",
+ "d91ebfb87e": "현재 버전: {{value0}}",
+ "f2b1ccc12a": "업데이트",
+ "bd79d412f0": "업데이트 확인에 실패했습니다. {{value0}}",
+ "b9ad70c30d": "업데이트 오류입니다. {{value0}}",
+ "6405510b92": "오류",
+ "a0832ccdb1": "다운로드됨",
+ "2a48034c4c": "v{{value0}} 다운로드 중... {{value1}}%",
+ "4c1c001813": "다운로드 중",
+ "f40d88390d": "최신 버전을 사용 중입니다.",
+ "90eb7309d7": "이용할 수 없음",
+ "82465b2444": "사용 가능",
+ "31fd7150cf": "업데이트 확인 중...",
+ "3394d1f663": "확인 중",
+ "d69a09b672": "업데이트는 시작 시 자동으로 확인됩니다.",
+ "7173352632": "idle"
+ },
+ "GeneralWorkspaceSettingsSection": {
+ "3d538a98f7": "워크스페이스의 열기 메뉴에서 사용 가능한 앱을 선택하세요.",
+ "008f92085f": "앱에서 열기",
+ "824b98a0d9": "자동화 및 실행 기록을 삭제하기 전에 확인 메시지를 표시하세요.",
+ "ea98373cd8": "자동화를 삭제하기 전에 확인하세요",
+ "d2dd2ca2e3": "자동화 및 실행 기록을 삭제하기 전에 확인 대화 상자를 표시합니다.",
+ "28bc3d085e": "컨텍스트 메뉴에서 워크스페이스를 삭제하기 전에 확인 메시지를 표시합니다. 삭제에 실패해도 여전히 강제 삭제 대체가 나타납니다.",
+ "9f380934cf": "워크스페이스를 삭제하기 전에 확인",
+ "5734db82af": "워크스페이스를 삭제하기 전에 확인 대화상자를 표시합니다.",
+ "4fbf910ded": "저장소 이름이 지정된 하위 폴더 내에 워크스페이스를 만듭니다.",
+ "ba3480642f": "네스트 워크스페이스",
+ "a246f5ce6f": "워크스페이스 폴더가 생성되는 루트 디렉터리입니다.",
+ "5567191a6e": "먹다",
+ "0e9fc0eadc": "워크스페이스 디렉토리",
+ "e2955d9ccb": "새 워크스페이스가 생성되는 위치를 구성합니다.",
+ "7511097c5d": "워크스페이스"
+ },
+ "GhosttyImportModal": {
+ "9d3e56ca36": "변경 사항 적용",
+ "f96688b6bc": "취소",
+ "b7ddae600c": "완료",
+ "e4bda7ce6f": "이 시스템에는 Ghostty 구성이 없습니다.",
+ "b58d4c9051": "지원되지 않는 키",
+ "674b5ccd6b": "가져올 새 설정이 없습니다. 현재 설정이 이미 일치합니다.",
+ "a4c5dec640": "업데이트할 설정",
+ "4466f4cdaa": "가져오기 완료",
+ "023a52c1f7": "미리보기 로드 중…",
+ "2763b0c045": "Ghostty 구성에서 가져올 설정을 확인하세요.",
+ "d2f33670a9": "Ghostty에서 가져오기",
+ "273e7e81fe": "구성",
+ "1f744a72f4": "구성"
+ },
+ "GitPane": {
+ "d2eede4c54": "커밋, PR 및 이슈에 Orca 속성을 추가합니다.",
+ "e02ea23a32": "Orca 속성",
+ "e71ce09c42": "orca",
+ "b9b5771bb1": "속성",
+ "b5f534717a": "공동 집필",
+ "9838c921ed": "공저자",
+ "afada55042": "이슈",
+ "b4ef5428a7": "PR",
+ "895d3f70b8": "gh",
+ "32dca11189": "GitHub",
+ "c4f610d057": "사용 가능한 경우 현재 GitLab CLI REST 속도 제한 헤더입니다.",
+ "0de4ae556c": "GitLab API 예산",
+ "cdd793134e": "API 예산",
+ "b9c011fbc2": "비율 제한",
+ "3072428ac7": "glab",
+ "8a527d48e3": "gitlab",
+ "aa204f185f": "현재 GitHub CLI REST, 검색 및 GraphQL 속도 제한.",
+ "612a440e57": "GitHub API 예산",
+ "2cde9044a8": "그래프",
+ "36e3de3619": "오래된 역사와 비교하는 것에서. Orca는 해당 브랜치에 커밋되지 않은 변경 사항이나 로컬 전용 커밋이 있는 경우 업데이트를 건너뜁니다.",
+ "d072a12995": "git diff 메인...HEAD",
+ "db3a127eb1": ". 이것은 다음과 같은 명령을 유지합니다",
+ "3ae3de8898": "주인",
+ "5bf885be48": "또는",
+ "ffba483bae": "기본",
+ "976afc6b3e": "워크스페이스를 생성하면 Orca는 원격 기반을 새로고침하고 다음과 같은 일치하는 로컬 브랜치를 안전하게 빨리 감습니다.",
+ "1ec5c91e1d": "브랜치 이름에 Git 사용자 이름, 사용자 지정 접두사 또는 접두사 없음을 사용할지 선택합니다.",
+ "330f584b50": "브랜치 접두사",
+ "1ffaadf0a0": "작업 트리를 생성할 때 브랜치 이름에 접두사가 추가됩니다.",
+ "813e15b346": "custom",
+ "2351aa5a31": "자식 사용자 이름",
+ "cc63fce906": "브랜치 이름 지정",
+ "b559bf9899": "예: feature",
+ "aefa1ecb59": "Git 사용자 이름이 구성되지 않았습니다.",
+ "f35007e6e8": "자식 사용자 이름",
+ "3d172725cc": "없음",
+ "1f32ba27a6": "Custom",
+ "a182c5125e": "힘내 사용자 이름"
+ },
+ "HiddenExperimentalGroup": {
+ "d0f914a528": "자리 표시자 토글",
+ "1014ddbfaf": "오늘은 아무것도 하지 않습니다. 숨겨진 실험 옵션을 위한 첫 번째 슬롯으로 예약되어 있습니다.",
+ "232cf83de8": "내부 테스트를 위한 비공개 토글입니다. 여기에는 아무것도 지원되지 않습니다.",
+ "3e9e827ca5": "숨겨진 실험"
+ },
+ "InputPane": {
+ "db15068196": "Linux 및 macOS에서는 기본적으로 활성화되어 있습니다. Linux는 시스템 선택 클립보드를 사용합니다. 다른 플랫폼은 개인 버퍼를 사용합니다.",
+ "ad31c3c5fb": "선택 항목에서 붙여넣기를 마우스 가운데 버튼으로 클릭"
+ },
+ "IntegrationsPane": {
+ "2122e15517": "연결된 각 Linear 워크스페이스에는 활성 런타임에 의해 저장된 하나의 키가 있습니다. 전체 액세스 키는 키 소유자가 액세스할 수 있는 모든 팀을 포함할 수 있습니다. 제한된 키는 언제든지 교체될 수 있습니다.",
+ "e7b2dd46f9": "테스트 중…",
+ "fe4d378dc4": "확인됨",
+ "f5c5246514": "Linear 액세스 추가",
+ "6432f6522e": "연결됨",
+ "077844591a": "워크스페이스 액세스 추가",
+ "264a9b6128": "Linear",
+ "4831ba1083": "재확인",
+ "01f6c7582e": "자세히 알아보기",
+ "1a62c295c6": "Gitea 자격 증명이 구성되었지만 인증할 수 없습니다. 토큰, API 기본 URL 및 저장소 권한을 확인한 후 환경 변수가 변경된 경우 Orca를 다시 시작하십시오.",
+ "5a1f86225a": "Orca가 원격지에서 API URL을 파생할 수 없는 경우에만 가능합니다.",
+ "6193444689": "ORCA_GITEA_API_BASE_URL",
+ "2c0330ec3e": "개인 저장소의 경우",
+ "e678d89e8c": "ORCA_GITEA_TOKEN",
+ "d9467ab026": "공개 저장소는 git 원격에서 감지됩니다. 세트",
+ "4ab9b96925": "Gitea",
+ "953b7bf6f7": "Azure DevOps 자격 증명이 구성되었지만 인증할 수 없습니다. 토큰, API 기본 URL 및 저장소 권한을 확인한 후 환경 변수가 변경된 경우 Orca를 다시 시작하십시오.",
+ "6f317f5132": "Orca가 git 원격에서 API 기본 URL을 파생할 수 없는 경우에만 가능합니다.",
+ "ae6b7f5f40": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "67a9f26a80": ". 세트",
+ "8f960935c1": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "ce3c58cd63": "또는 설정",
+ "5ee6ef6405": "ORCA_AZURE_DEVOPS_TOKEN",
+ "4ee74d1470": "세트",
+ "5efce6953d": "애저 데브옵스",
+ "3c3cf05c63": "Bitbucket 자격 증명이 구성되었지만 인증할 수 없습니다. 토큰 및 저장소 권한을 확인한 후 환경 변수가 변경된 경우 Orca를 다시 시작하십시오.",
+ "6e0ff3403e": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "44cde4aa01": "ORCA_BITBUCKET_API_TOKEN",
+ "a6c2816115": "그리고",
+ "b8a7efb3f6": "ORCA_BITBUCKET_EMAIL",
+ "8489c0aa49": "비트버킷",
+ "e74de656ce": "glab 인증 로그인",
+ "05e5245af7": "GitLab CLI가 설치되었지만 인증되지 않았습니다. 터미널에서 다음 명령을 실행하세요.",
+ "a83cac5726": "GitLab CLI 설치",
+ "35a3379372": "MR, 이슈 및 파이프라인을 활성화하려면 GitLab CLI를 설치하세요.",
+ "ea160a9978": "CLI.",
+ "a3326f6f1b": "glab",
+ "027440e1cb": "다음을 통해 MR, 이슈, 할 일, 파이프라인을 병합합니다.",
+ "513abfe47d": "GitLab",
+ "51000487c4": "gh 인증 로그인",
+ "09285e9fe6": "GitHub CLI가 설치되었지만 인증되지 않았습니다. 터미널에서 다음 명령을 실행하세요.",
+ "399cf46867": "GitHub CLI 설치",
+ "c0c8575e05": "PR, 이슈 및 검사를 활성화하려면 GitHub CLI를 설치하세요.",
+ "f36365ed45": "gh",
+ "de6a0d13ab": "PR, 이슈 및 검사는 다음을 통해 이루어집니다.",
+ "70c5f74f36": "GitHub",
+ "8e078e480c": "{{value0}} 연결 끊기",
+ "95b9a87e7e": "시험",
+ "62b20292de": "오류",
+ "ae38fc62a8": "좋아요",
+ "33ae9730a8": "Linear 액세스를 추가해 이슈를 탐색하고 연결합니다.",
+ "98ded79cd7": "{{value0}} 워크스페이스{{value1}}이 연결됨",
+ "4bdc6fe4f5": "구성되지 않음",
+ "4972f3c95d": "구성된",
+ "3614887c40": "확인 중",
+ "45bf5e6e4b": "인증 실패",
+ "e1bd5364e6": "선택적 설정",
+ "e7a961e1c5": "구성됨",
+ "6bd148dcb5": "Gitea REST API를 통해 PR 및 커밋 상태를 확인할 수 있습니다.",
+ "6355fe585e": "감지된 리포지토리에 대한 PR 및 커밋 상태",
+ "1fac9b4910": "{{value0}} · PR 및 커밋 상태",
+ "f92fbf11aa": "구성되지 않음",
+ "6791d7af95": "Azure DevOps REST API 토큰을 통해 PR 및 빌드 상태를 확인하세요.",
+ "e3d5a24979": "감지된 Azure Repos에 대한 PR 및 빌드 상태",
+ "277fc23929": "{{value0}} · PR 및 빌드 상태",
+ "295154e54e": "연결됨",
+ "0879860c58": "Bitbucket Cloud API 토큰을 통해 PR 및 빌드 상태를 확인하세요.",
+ "9707523939": "PR 및 빌드 상태",
+ "a565377c38": "설치되지 않은",
+ "15cf990798": "인증되지 않음",
+ "f7eb5f0b24": "설치되지 않음"
+ },
+ "KagiSessionLinkForm": {
+ "92f0b4e472": "지우기",
+ "9f741627a7": "Kagi 세션 링크가 삭제되었습니다.",
+ "d5c8b94c5b": "저장",
+ "ff450194cd": "Kagi 비공개 세션 링크",
+ "e383683485": "https://kagi.com/search?token=...",
+ "81409d9362": "Kagi 인증을 위한 선택적 비공개 세션 링크입니다.",
+ "3e5b7c6c25": "Kagi 세션 링크가 저장되었습니다.",
+ "0911d5fa4c": "https://kagi.com/search?token=...에서 Kagi 비공개 세션 링크를 입력하세요."
+ },
+ "KeybindingsFileActions": {
+ "abc49853fb": "디스크에서 다시 로드",
+ "a8a8d6b9d3": "파일 관리자에 표시",
+ "9e24c0e858": "Cursor로 열기",
+ "1637f64033": "VS Code에서 열기",
+ "98f1a23e1c": "기본 앱으로 열기",
+ "400397a10d": "키바인딩 파일 메뉴 열기",
+ "1c2be2b2c6": "Orca에서 파일 편집",
+ "c5886a31cc": "외부 편집기를 열지 못했습니다.",
+ "cdf794f46d": "키바인딩 파일을 사용할 수 없습니다.",
+ "dd532a01ce": "Orca에서 키 바인딩을 열지 못했습니다."
+ },
+ "ManageSessionKillDialog": {
+ "6bf4627168": "취소",
+ "ad9832aa26": ". 해당 창에서 저장되지 않은 작업은 모두 손실됩니다. 이 작업은 취소할 수 없습니다.",
+ "8401328fed": "강제 종료",
+ "87dcafc85c": "이 세션을 종료하시겠습니까?",
+ "0b0db4c68c": "세션 종료",
+ "d3dba51b15": "종료 중…"
+ },
+ "ManageSessionsSection": {
+ "33c2a1e1b4": "세션 종료 {{value0}}",
+ "2896a50f50": "{{value0}} 터미널로 이동",
+ "e26a60d9eb": "세션이 없습니다.",
+ "39c53d6d74": "로드 중…",
+ "5ed15e778c": "데몬 재시작",
+ "3282db098c": "모든 세션 종료",
+ "b3b1cc5708": "새로고침",
+ "a795a9552a": "세션",
+ "7c4889a724": "세션을 종료하거나 기본 데몬을 다시 시작하여 정지되거나 오작동하는 터미널을 복구합니다.",
+ "d1b80fd5cd": "세션 관리",
+ "9c940434af": "로컬 런타임으로 다시 전환하여 로컬 데몬 세션을 다시 시작하거나 종료합니다.",
+ "ad467eaadc": "원격 런타임 서버가 활성 상태인 동안에는 세션 관리를 사용할 수 없습니다.",
+ "8dbd96b463": "세션을 종료할 수 없습니다.",
+ "0735b7a586": "세션을 종료할 수 없습니다. 이미 사라졌을 수 있습니다.",
+ "bfba05dccd": "세션이 종료되었습니다.",
+ "c535cbdd09": "세션을 로드할 수 없습니다.",
+ "e3d1fbe008": "다시 시작",
+ "a06ababda0": "모두 강제 종료"
+ },
+ "McpConfigFileRow": {
+ "b145eb6009": "환경:",
+ "e720c139cd": "열기",
+ "845ae248e8": "유효한"
+ },
+ "McpConfigSection": {
+ "4d16a0d9ac": "체크됨",
+ "b900cd6282": "MCP 구성을 찾을 수 없습니다. 이 저장소가 자체 MCP 서버를 정의하도록 하려면 빈 워크스페이스 구성을 추가하세요.",
+ "3b224167ff": "섬기는 사람",
+ "251b96564a": "감지됨 ·",
+ "f34c152dc0": "MCP 구성 새로 고침",
+ "6bac9ddfc6": "SSH 저장소는 원격 파일 시스템을 통해 읽혀집니다. 스타터 생성은 워크스페이스 루트 구성으로 제한됩니다.",
+ "96f5609b04": "이 저장소에서 작업하는 동안 에이전트가 사용할 수 있는 MCP 서버 정의를 검사하세요.",
+ "55eea3ef47": "MCP 구성",
+ "9ee215caf6": ".mcp.json",
+ "1f3665e35a": "MCP 구성이 생성되었습니다.",
+ "82436439eb": "MCP 구성 추가",
+ "0a5c1ead54": "빈 구성 만들기"
+ },
+ "MobileEmulatorAgentControlRow": {
+ "1861982430": "CLI 상태를 로드하지 못했습니다.",
+ "8af7a8bc38": "명령은 현재 작업 트리의 활성 에뮬레이터를 대상으로 합니다. 좌표는 0..1에서 정규화됩니다.",
+ "c7f3fe0a6e": "일반 에뮬레이터 명령",
+ "d94ca6a623": "에이전트가 모바일 에뮬레이터 제어를 포함하여 Orca CLI 명령을 사용할 수 있도록 합니다.",
+ "67e19ee03c": "Orca CLI 스킬",
+ "aaf62a3dd2": "설치 위치",
+ "2fef055608": "에이전트가 셸에서 활성 에뮬레이터를 제어할 수 있도록 Orca CLI 명령을 등록합니다.",
+ "4f2205f3b6": "Orca CLI 활성화",
+ "ff4b7e65d6": "코딩 에이전트가 Orca CLI 명령을 사용하여 활성 모바일 에뮬레이터를 제어하도록 합니다.",
+ "2a674aa810": "에이전트 모바일 에뮬레이터 제어",
+ "cdeaed9e37": "PATH에 Orca CLI를 등록했습니다."
+ },
+ "MobileEmulatorExamples": {
+ "edf13dd03b": "복사",
+ "c12b253997": "예시 프롬프트 복사",
+ "d151e25078": "\"",
+ "b525ff2b12": "\"",
+ "4daa95f25a": "Orca CLI 스킬이 설치된 프로젝트의 Claude Code, Codex 또는 다른 에이전트에 이들 중 하나를 붙여넣습니다.",
+ "0820b3f84f": "시도해 보세요 - 예시 프롬프트",
+ "1f608e7d60": "프롬프트를 복사하지 못했습니다.",
+ "2b077b5544": "프롬프트를 복사했습니다."
+ },
+ "MobileEmulatorSettingsPane": {
+ "19d39113b6": "코딩 에이전트가 Orca CLI 명령을 사용하여 활성 모바일 에뮬레이터를 제어하도록 합니다.",
+ "f2f8d97bb6": "에이전트 모바일 에뮬레이터 제어",
+ "143961d031": "기본 장치",
+ "8aec2f99a0": "에뮬레이터 가용성 새로 고침",
+ "ae1612c58c": "유효성",
+ "f9af91ea26": "새 모바일 에뮬레이터 작업을 표시하고 에이전트가 활성 에뮬레이터에 연결할 수 있도록 합니다.",
+ "700ddbf9b1": "모바일 에뮬레이터 활성화",
+ "bc39d0f115": "Orca 및 코딩 에이전트에 대한 모바일 에뮬레이터 지원을 구성합니다.",
+ "6593c9ddd3": "모바일 에뮬레이터",
+ "a4f1c82d90": "비활성",
+ "b5e2d93e01": "확인 중...",
+ "c6f3ea4f12": "준비됨",
+ "d704fb5023": "설정 필요"
+ },
+ "MobileNetworkInterfaceSection": {
+ "63d5e4ae1e": "QR 코드를 재생성하고 Orca 모바일 앱에서 스캔하세요.",
+ "87985ba6f5": "이 네트워크 인터페이스 메뉴에서 Tailscale 주소(일반적으로 100.x.y.z IP)를 선택합니다.",
+ "1f7c26d36a": "두 장치 모두에서 동일한 tailnet에 로그인합니다.",
+ "668016be7a": "컴퓨터와 휴대폰에서.",
+ "1dc87a7fbc": "테일스케일",
+ "51d29927eb": "설치",
+ "9fc5d203ff": "Orca Mobile은 이 컴퓨터에 직접 연결됩니다. 동일한 로컬 네트워크가 아닌 곳에서 사용하려면 컴퓨터와 휴대폰을 동일한 개인 오버레이 네트워크에 놓은 다음 해당 네트워크 주소를 선택하여 QR 코드를 생성하세요.",
+ "39fad211d9": "tailnet을 사용하여 Wi-Fi 외부에서 연결",
+ "a9db5d771d": "네트워크 인터페이스 새로 고침",
+ "b2c384cfd6": "인터페이스를 찾을 수 없습니다.",
+ "d536b5e20d": "QR 코드에 광고할 네트워크 주소를 선택하세요. 동일한 네트워크 페어링에는 LAN 주소를 사용하고, 교차 네트워크 액세스에는 오버레이 네트워크 주소(Tailscale, ZeroTier)를 사용하세요.",
+ "406a35121c": "네트워크 인터페이스",
+ "c541f67790": "QR 코드 생성",
+ "1e64659126": "재생성"
+ },
+ "MobilePane": {
+ "dd3cd78d04": "Orca 모바일로 스캔",
+ "35100bca5d": "휴대폰에서 터미널을 사용하는 동안 Orca는 휴대폰 화면에 맞게 터미널을 축소합니다. 앱을 닫거나 다른 곳으로 전환하면 앱이 휴대폰 크기로 유지되는지(대화형 CLI 도구가 리플로우되지 않음) 또는 데스크탑으로 다시 크기가 조정되는지 여부가 제어됩니다. 언제든지 터미널 배너에서 복원을 클릭하여 수동으로 크기를 조정할 수 있습니다.",
+ "ee56f1c7e4": "모바일 앱을 나갈 때",
+ "3939fd062c": "장치를 취소하면 즉시 연결이 끊어집니다.",
+ "254a6d09e4": "페어링됨",
+ "d7ce676270": "페어링된 장치",
+ "e778ecb209": "또는 모바일 앱에 다음 코드를 붙여넣으세요.",
+ "310924ad2c": "Orca 모바일 앱으로 이 코드를 스캔하세요. 각 코드는 고유한 장치 토큰을 생성합니다.",
+ "870e1b5ca5": "기기를 취소하지 못했습니다.",
+ "2e3dd0bc29": "기기가 취소되었습니다.",
+ "711231348f": "페어링 코드를 복사하지 못했습니다.",
+ "e3c427e020": "QR 코드를 생성하지 못했습니다.",
+ "cb9067c1c1": "WebSocket 전송이 실행되고 있지 않습니다.",
+ "d714614dbf": "네트워크 인터페이스를 새로고침하지 못했습니다.",
+ "ff865419dc": "30분 후",
+ "d4ba07d914": "5분 후",
+ "c474aa09d8": "1분 후",
+ "aa1263e881": "휴대폰 크기로 유지(기본값)",
+ "6436e56546": "모바일 페어링을 위한 QR 코드",
+ "1b1b70279a": "아직 페어링된 기기가 없습니다.",
+ "1592afcc7a": "아직 페어링된 기기가 없습니다. Orca 모바일 앱으로 QR 코드를 스캔하세요."
+ },
+ "MobileSettingsPane": {
+ "9a3c280e49": "GitHub 릴리스",
+ "b0088412a1": "또는 다음의 Android APK를 사용하세요.",
+ "b5a2ed83ff": "앱스토어",
+ "c8491c17ef": "QR 코드를 스캔하여 휴대폰에서 Orca를 제어하세요. 베타/초기 미리보기 - 버그 및 주요 변경 사항이 예상됩니다. 다음에서 iOS 앱을 받으세요.",
+ "e7a3ae8c4e": "모바일",
+ "174f4a3c6d": "휴대폰에서 터미널과 에이전트를 제어하세요."
+ },
+ "NotificationsPane": {
+ "906b4afebf": "테스트 알림 보내기",
+ "2772d2f257": "트리거하는 작업 트리가 이미 표시되면 알림을 건너뜁니다.",
+ "00cd406dbb": "집중하는 동안 억제",
+ "2a42dd8d6f": "알림음 볼륨",
+ "4aa5085cd7": "Custom:",
+ "c258cb96dc": "알림 소리 선택",
+ "2a2033c388": "데스크톱 알림이 전달될 때 Orca가 재생하는 경고를 선택합니다.",
+ "88686e6ca8": "알림음",
+ "b6fc369244": "배경 터미널은 벨 문자를 내보냅니다.",
+ "591fe605b9": "터미널 벨",
+ "55f901a59b": "코딩 에이전트가 완료되고 유휴 상태가 됩니다.",
+ "ca76d06fd2": "에이전트 작업 완료",
+ "deff6d30da": "백그라운드 이벤트에 대한 기본 시스템 알림입니다.",
+ "841c8c549f": "알림 활성화",
+ "0fadad17ce": "알림음을 재생할 수 없습니다.",
+ "406feb0aa6": "테스트 알림이 전달되지 않았습니다.",
+ "6fc3781729": "알림이 비활성화되었습니다.",
+ "4676a95bc3": "Orca에 대한 데스크톱 알림 설정을 확인하세요.",
+ "0cb93240b8": "시스템이 알림을 표시하지 않았습니다.",
+ "145227ca2b": "설정 열기",
+ "d3d54e0915": "테스트 알림이 전송되었습니다.",
+ "115437bc35": "macOS 배너가 나타나지 않으면 Orca에 대한 알림 허용을 활성화합니다.",
+ "7f45542625": "테스트 알림이 요청되었습니다.",
+ "98d70fb261": "맞춤 알림 소리를 재생할 수 없습니다.",
+ "c83b05a055": "이 시스템에서는 알림이 지원되지 않습니다.",
+ "274af61bc0": "체계",
+ "6e6df3a09a": "사용자 정의 파일 선택",
+ "76e02467b8": "사용자 정의 파일 변경",
+ "d3756cf5bc": "비활성"
+ },
+ "OpenAiTranscriptionKeyDialog": {
+ "fa83512e48": "키 저장",
+ "07b26f2742": "클리어 키",
+ "d246b2bdb3": "로컬 런타임 키는 가능한 경우 Electron 암호화 저장소를 사용하여 ~/.orca에 저장됩니다.",
+ "c3380e4ca5": "sk-...",
+ "2f797018f0": "API 키가 구성됨",
+ "16015322f9": "API 키",
+ "07ed3e512e": "OpenAI 음성 모델이 선택된 경우에만 오디오가 OpenAI로 전송됩니다.",
+ "439e91879e": "OpenAI 전사"
+ },
+ "OpenAiTranscriptionSettingsRow": {
+ "85c589cd61": "API 키 추가",
+ "ae2df8f511": "OpenAI API 키 연결 해제",
+ "a622bc3b37": "키 교체",
+ "3b0ab3fc0b": "연결됨",
+ "27e0cb656d": "OpenAI 전사",
+ "893790e13b": "클라우드 음성-텍스트 모델을 선택하기 전에 OpenAI API 키를 추가하세요.",
+ "b59b9b2b51": "클라우드 음성-텍스트 모델용으로 구성된 API 키입니다."
+ },
+ "OpenInMenuSetting": {
+ "03b00b1f64": "맞춤형 앱",
+ "c1d817e027": "추가됨",
+ "e4064916aa": "앱 추가",
+ "9d0413817d": "워크스페이스의 열기 메뉴에서 사용 가능한 앱을 선택하세요.",
+ "6ed52fe71e": "앱에서 열기",
+ "eb55b87570": "이 앱을 열려면 터미널에 입력하는 명령입니다.",
+ "ba1422ee07": "터미널 명령",
+ "e1fc0085c6": "메뉴 라벨",
+ "a261931d29": "앱 삭제",
+ "af7d1c3656": "앱 수정",
+ "494ed535cd": "앱 세부정보 접기",
+ "810ef39b56": "Cursor",
+ "3ebe650f74": "앱 이름",
+ "3743ed080c": "명령 설정",
+ "f79084947b": "새로운 앱"
+ },
+ "OrchestrationExamplesDialog": {
+ "3d1aa105e3": "프롬프트 복사",
+ "9b4c004998": "완료",
+ "969cec9739": "{{value0}} 예시 프롬프트 복사",
+ "4e46da1889": "프롬프트를 복사하지 못했습니다.",
+ "80c6f2feb8": "예시 프롬프트를 복사했습니다."
+ },
+ "OrchestrationPane": {
+ "52e0634e2c": "핸드오프, 작업 트리 핸드오버, 순차 또는 병렬 하위 에이전트에 대한 오케스트레이션을 사용하도록 코디네이터 에이전트에 요청하세요.",
+ "ae79504732": "사용방법",
+ "7bc082f4de": "설치 명령 복사",
+ "832f1f3ee6": "자신의 터미널을 선호하시나요?",
+ "9bedd2a6e5": "에이전트가 Orca를 통해 컨텍스트를 넘기고 작업을 조정할 수 있습니다.",
+ "07641b9768": "오케스트레이션 스킬",
+ "2aacdb0517": "핸드오프, 작업 트리 핸드오버, 하위 에이전트 작업 전반에 걸쳐 코딩 에이전트를 조정합니다.",
+ "191ac34567": "에이전트 오케스트레이션"
+ },
+ "OrchestrationSetupCard": {
+ "e7d2a5146c": "에이전트가 Orca를 통해 컨텍스트를 넘기고 작업을 조정할 수 있습니다.",
+ "2777ff0fdc": "오케스트레이션 스킬"
+ },
+ "OrchestrationSkillAgentCoverage": {
+ "6dec5ce2d2": "에이전트 적용 범위",
+ "ffe13e36fb": "누락",
+ "1e8f8d8fae": "준비됨"
+ },
+ "OrchestrationSkillPromptDialog": {
+ "f08d45293d": "명령 복사",
+ "35550f3b3b": "완료",
+ "1bdce1911e": "오케스트레이션 스킬 설치 명령 복사",
+ "b99f375eb2": "에이전트에 대한 오케스트레이션 스킬을 설치하려면 터미널에서 이 명령을 실행하세요.",
+ "2914abcfa2": "오케스트레이션 스킬 설치",
+ "d3dc559225": "설치 명령을 복사하지 못했습니다.",
+ "239bf9132b": "설치 명령을 복사했습니다."
+ },
+ "PrivacyDiagnosticBundleControls": {
+ "dc8404a930": "미리보기 만들기",
+ "a5acaffdb6": "버리기",
+ "aca2c8a367": "업로드",
+ "798b6f0be5": "미리보기 열기",
+ "2ae9a6b63e": "완료",
+ "7f14a1733c": "번들 삭제",
+ "2801d4ce22": "티켓 복사"
+ },
+ "PrivacyDiagnosticsSection": {
+ "acc7c66e6e": "OTLP 내보내기",
+ "4ff08ff3a7": "로컬 흔적 지우기",
+ "9ca08a9f8f": "이 시스템에서 회전된 모든 추적 파일을 삭제합니다.",
+ "fe81a52cb2": "추적 폴더 열기",
+ "5ff57fc986": "파일 관리자에 {{value0}}이 표시됩니다.",
+ "af2fc82cde": "진단 번들",
+ "c18cbe45df": "업로드된 진단 번들이 삭제되었습니다.",
+ "7a4944595b": "진단 티켓을 복사할 수 없습니다.",
+ "13eb2c65a1": "진단 티켓이 복사되었습니다.",
+ "860bca9ec9": "진단 번들 미리보기가 삭제되었습니다.",
+ "49fc6c80e8": "진단 번들이 업로드되었습니다.",
+ "db3228e01a": "진단 번들 미리보기 열림",
+ "a2b3505c77": "진단 번들 미리보기가 생성되었습니다.",
+ "9666a05580": "추적 파일을 지울 수 없습니다.",
+ "32d767f84d": "로컬 추적 파일이 지워졌습니다.",
+ "b85fe972cd": "추적 폴더를 열 수 없습니다.",
+ "1fb00a8995": "비활성",
+ "46ea3fb2d0": "활성화됨",
+ "7c9d9820b6": "Orca가 자체 OpenTelemetry 수집기를 가리키도록 ORCA_OTLP_TRACES_URL을 설정합니다."
+ },
+ "PrivacyPane": {
+ "36e0e2e63b": "환경 변수. 다시 활성화하려면 설정을 해제하고 다시 시작하세요.",
+ "79a0f3c16c": "텔레메트리은 다음에 의해 비활성화됩니다.",
+ "e3970bbbf5": "CI 환경 변수가 설정되었기 때문에 텔레메트리이 비활성화되었습니다. 설정을 해제하고 다시 시작하세요.",
+ "fe904ac984": "익명의 사용 데이터 공유",
+ "77410e0566": "개인 정보 보호 정책",
+ "8bfdd23a88": "다음에 무엇을 빌드할지 알아내도록 도와주세요. Orca는 귀하가 사용하는 기능과 문제가 발생한 부분에 대한 개수를 익명으로 보냅니다.",
+ "afec8b03be": "ci"
+ },
+ "QuickCommandsPane": {
+ "8764c6e9e4": "{{value0}} 제거",
+ "7d90fd5299": "{{value0}} 편집",
+ "8c877dec41": "글로벌",
+ "c6b155911b": "모든 명령",
+ "5aacc8f7dc": "명령 추가",
+ "c36912efd5": "탭 표시줄의 빠른 명령 버튼을 사용하여 실행하거나 터미널 내부를 마우스 오른쪽 버튼으로 클릭하세요.",
+ "f91b649324": "저장된 명령",
+ "3d9dc558e8": "이 빠른 명령은 저장된 목록에서 제거됩니다.",
+ "3edf3deaf8": "'{{value0}}'을 삭제하시겠습니까?",
+ "9fcfc29519": "끼워 넣다",
+ "9b3e338d62": "입력",
+ "4ccc63da87": "에이전트",
+ "0252ddd578": "명령 텍스트 없음",
+ "7784912ed6": "레포",
+ "2bb9e38e93": "제목 없음",
+ "3eb9897ab0": "선택한 범위에는 명령이 없습니다.",
+ "38d61927e6": "저장된 빠른 명령이 없습니다.",
+ "44923dd982": "파괴적인",
+ "ec1ed99e70": "삭제",
+ "d1d0976320": "없음"
+ },
+ "RecentTabOrderControl": {
+ "3b17c81ede": "탭 스트립 순서",
+ "6e6a3fcc61": "가장 최근",
+ "7a546f2309": "탭 순서",
+ "a867a0889f": "최근 또는 탭 표시줄."
+ },
+ "RepositoryHooksSection": {
+ "af49e2a19e": "파일이 있지만 Orca가 유효한 `scripts` 또는 `issueCommand` 정의를 찾을 수 없습니다.",
+ "3397879bee": "로컬 명령이 존재하는 경우 실행할 명령을 선택하십시오.",
+ "39da2ae12f": "orca.yaml",
+ "ac9038d2cc": "둘 다일 때",
+ "32fec28f5b": "명령 소스",
+ "bbbd6e0bc4": "명령 소스 및 orca.yaml",
+ "c9bc1bfd8f": "고급",
+ "610d90fdbd": "명령 소스 및 orca.yaml 세부정보",
+ "52aef29e69": "저장소 기본값을 사용하려면 비워 두세요.",
+ "4084720f47": "{{artifact_url}} 완료",
+ "13394103bd": "사용자 정의 GitHub 이슈 명령",
+ "70ad20f883": "링크된 이슈 또는 PR URL에 대한 정보입니다.",
+ "b997331366": "선택적 재정의. 사용",
+ "2cc27dc12b": "linked-issue 명령에 대한 선택적 사용자별 재정의.",
+ "b91a0f297d": "작업 트리가 보관되기 전에 실행되는 로컬 및 공유 스크립트입니다.",
+ "9a100323ff": "아카이브 스크립트",
+ "21fb607a87": "새 작업 트리가 생성될 때의 기본 동작입니다.",
+ "793dcee97d": "실행 시기",
+ "63e1783173": "설정 스크립트를 사용할 수 있는 경우 기본 동작을 선택합니다.",
+ "fb6bebcf7e": "설치 실행 시기",
+ "30d555acd2": "새 작업 트리가 생성된 후 실행되는 로컬 및 공유 스크립트입니다.",
+ "52b31baf02": "설정 스크립트",
+ "8567127a40": "작업 트리가 생성되거나 보관될 때 실행되는 스크립트입니다. 로컬 스크립트는 이 시스템에 저장됩니다. `orca.yaml` 스크립트는 팀과 공유됩니다.",
+ "ff082fe7c6": "작업트리 후크",
+ "5d940bde5c": "로컬 스크립트 추가",
+ "8c2893fae0": "단일 쉘 스크립트로 실행됩니다. 이 컴퓨터에 저장되었습니다.",
+ "40a446ae16": "- 당신만을 위한 이 기계에서",
+ "2d03a514db": "현지의",
+ "7e4427b4a2": "변경합니다.",
+ "b113344b6a": "편집",
+ "f828e1de19": "- 팀과 공유",
+ "673a7fd10e": "확인 중...",
+ "5426ecbdcb": "로컬 스크립트가 실행되지 않습니다.",
+ "b2b06c7ce8": "사용 가능한 환경 변수(자세한 내용을 보려면 마우스를 올리세요):",
+ "95a0411b3e": "주형",
+ "175daba180": "예",
+ "b20c5df6ca": "이 저장소에 대한 공유 설정, 아카이브 또는 발행 자동화 기본값을 활성화하려면 `orca.yaml` 파일을 추가하세요. 예제 템플릿:",
+ "925f9e0dc4": "텍스트 전경",
+ "0cc712b823": "핵심 구성 파일이 저장소 루트에 있지만 Orca가 아직 지원되는 후크 정의를 구문 분석할 수 없습니다.",
+ "c90b858573": "텍스트-호박-700 어두움:텍스트-호박-300",
+ "aba825233f": "파일에는 이 버전의 Orca가 인식하지 못하는 구성 키가 포함되어 있습니다. Orca를 업데이트하거나 파일에 오타가 있는지 확인해야 할 수도 있습니다.",
+ "ca424ff135": "공유 후크 및 이슈 자동화 기본값은 저장소에 정의되어 있으며 이를 사용하는 모든 사람이 사용할 수 있습니다.",
+ "32f417fe17": "텍스트-에메랄드-700 다크:텍스트-에메랄드-300",
+ "8bfe65fc60": "로컬 명령 사용",
+ "8d6c56bff8": "둘 다 실행",
+ "0fa21e19ec": "일반적으로 브랜치 이름을 기반으로 하는 워크스페이스의 이름입니다.",
+ "54c73d88d0": "생성되는 작업 트리의 경로입니다. 설치 명령은 이 디렉터리에서 실행됩니다.",
+ "30952c4aa4": "기본 저장소 체크아웃 경로입니다. .env와 같은 공유 파일을 작업 트리에 복사하는 데 유용합니다.",
+ "9b821fa19d": "# 예: echo \"$ORCA_WORKSPACE_NAME 정리 중\"",
+ "6f90ebe3fd": "작업 트리가 보관되거나 제거되기 전에 실행됩니다.",
+ "a3fc966677": "# 예: pnpm 설치 cp \"$ORCA_ROOT_PATH/.env\" \"$ORCA_WORKTREE_PATH/.env\"",
+ "f0710e1c83": "새 작업 트리가 생성된 후 실행됩니다. deps를 설치하고, env 파일을 복사하고, 마이그레이션을 실행하세요.",
+ "8561b0665f": "orca.yaml을 먼저 사용한 다음 로컬 명령을 실행합니다.",
+ "0e8b2a520d": "orca.yaml을 무시하십시오. 로컬 명령만 실행하세요.",
+ "83dc78202a": "로컬 전용",
+ "29397e8bbc": "커밋된 repo 명령만 실행하세요. 로컬 명령을 무시합니다.",
+ "d88b6ff88f": "orca.yaml 전용",
+ "99e3264a49": "선택한 경우에만 설정을 실행하세요.",
+ "15debc1fd9": "기본적으로 건너뛰기",
+ "022ba10cf2": "자동으로 설정을 실행합니다.",
+ "d3ef1ab247": "기본적으로 실행",
+ "90b1f50137": "설정을 실행하기 전에 메시지를 표시합니다.",
+ "e03d9a8f38": "매번 물어보세요",
+ "8dbe6bedf5": "유효하지 않은",
+ "0e0dd5b9a5": "짐을 실은",
+ "9b12f15b1e": "하나가 존재할 때.",
+ "c85c2c88a2": "{{artifact_url}}",
+ "fac13f8c1e": "권위 있는",
+ "0518758f38": "둘 다",
+ "d2b3016c20": "공유됨",
+ "4611b78617": "명령 소스",
+ "c5a55a2d2e": "고급의",
+ "b5e3e77e89": "행동",
+ "0ce113fd7b": "로컬 스크립트는 저장되지만 스크립트 소스는 orca.yaml로만 설정됩니다.",
+ "7f78e5eea6": "로컬 스크립트가 저장됩니다. Orca는 사용할 스크립트 소스를 추천하기 전에 orca.yaml을 계속 확인하고 있습니다.",
+ "2b6356e744": "저장됨",
+ "81057d5f71": "저장 중...",
+ "da37d6f10e": "복사",
+ "3149964b66": "복사됨"
+ },
+ "RepositoryIconPicker": {
+ "2b7d27b93c": "{{value0}} 저장소 색상 사용",
+ "fde066a63b": "PNG 업로드는 256KB 이하여야 합니다.",
+ "cc1286e263": "파비콘",
+ "03ca1a4e9b": "example.com",
+ "381b4844fd": "PNG 업로드",
+ "7da623abcc": "기본적으로 사용됨 — GitHub는 소유자가 사용자 정의 이미지를 설정하지 않은 경우에도 항상 하나를 제공합니다.",
+ "39da8a10bf": "GitHub 아바타 사용",
+ "c490787d24": "이모티콘",
+ "b2d7fd2116": "상",
+ "2d8bd302fa": "화신",
+ "913c55833d": "사용자 정의 저장소 색상 {{value0}}",
+ "0e5f0693c1": "사용자 정의 저장소 색상 선택",
+ "642dc29c6d": "색상",
+ "549d126081": "재설정",
+ "4e2a14f967": "저장소 아이콘",
+ "d71df44587": "GitHub 저장소를 확인하지 못했습니다.",
+ "f79972271a": "이 저장소에 대한 GitHub 원격을 찾을 수 없습니다.",
+ "4d039317f4": "웹사이트 파비콘",
+ "acf31559a0": "유효한 웹사이트 URL을 입력하세요.",
+ "868c5c9b56": "저장소 아이콘을 가져오지 못했습니다."
+ },
+ "RepositoryPane": {
+ "15a99d9b9f": "상대 경로는 이 프로젝트 루트에서 확인됩니다.",
+ "8ccacbeb5a": "글로벌 사용",
+ "e9bd57a336": "작업 트리 위치",
+ "e63bb96a9b": "새 작업 트리에 대한 프로젝트별 디렉터리입니다.",
+ "f88db4fece": "기본 작업 트리 기반",
+ "8984d06520": "작업 트리를 생성할 때 기본 기본 브랜치 또는 참조입니다.",
+ "e641c359de": "사이드바와 탭에 사용되는 프로젝트 아이콘과 색상입니다.",
+ "26fef02bf3": "프로젝트 아이콘",
+ "c7ef4415de": "표시 이름",
+ "b0a0c14a1c": "사이드바 및 탭에 대한 프로젝트별 표시 세부 정보입니다.",
+ "170624bdfb": "Orca에서 이 프로젝트를 제거하세요.",
+ "0909e5d650": "프로젝트 제거",
+ "ee5a290616": "폴더로 열렸습니다. 이 워크스페이스에서는 Git 기능을 사용할 수 없습니다.",
+ "323debba71": "유형:",
+ "499a437335": "신원"
+ },
+ "RepositorySourceControlAiActionRows": {
+ "548a6e1281": "명령 템플릿",
+ "7a3a8e431d": "CLI 인수",
+ "2b2f38652b": "사용자 정의 명령",
+ "0ffb081b3a": "기본 에이전트 사용",
+ "f4310cf63f": "에이전트",
+ "1cd88d470a": "사용자 정의",
+ "403876bb48": "글로벌 사용",
+ "f0aa2cfaea": "액션 레시피"
+ },
+ "RepositorySourceControlAiCustomCommand": {
+ "0704dd55cd": "저장소 명령",
+ "e56668c291": "글로벌 사용",
+ "fbb77e122a": "사용자 정의 명령을 선택하는 텍스트 작업에 대한 Repo 대체입니다.",
+ "ebffc5a28c": "사용자 정의 명령",
+ "f9941f0caf": "예를 들어 ollama는 llama3.1을 실행합니다. {프롬프트}"
+ },
+ "RepositorySourceControlAiEnablement": {
+ "84233d1bb3": "끄다",
+ "bea897eec2": "~에",
+ "62511a575d": "글로벌 사용",
+ "30ae6dcce8": "전역 기본값은",
+ "cf5959c834": "소스 제어 AI 활성화"
+ },
+ "RepositorySourceControlAiHostedReviewDefaults": {
+ "053ccfbf52": "끄다",
+ "777443bf89": "~에",
+ "ffc3b26b26": "글로벌 사용",
+ "a68849a859": "전역 기본값은",
+ "aa6ee4b7d6": "호스팅 리뷰 생성 기본값",
+ "629ed8a9d3": "생성 후 호스팅 PR 열기",
+ "14f1eb99d0": "PR 생성을 열 때 세부정보 생성",
+ "d32b87e754": "가능한 경우 리뷰 템플릿을 사용하세요.",
+ "981eae7e14": "기본적으로 초안"
+ },
+ "RepositorySourceControlAiSection": {
+ "67b3ff5467": "버리기",
+ "8b8bc5913a": "저장소 작업 레시피. 이 저장소가 사용자 정의할 때까지 전역 설정이 사용됩니다.",
+ "71b003b62b": "소스 제어 AI",
+ "152268c295": "저장",
+ "57e6e9d4b1": "저장 중...",
+ "ccb07dd027": "저장됨",
+ "e57dde9d93": "저장되지 않은 변경사항"
+ },
+ "RuntimeAccessGrantList": {
+ "8b82879581": "활성화된 권한을 가진 사람은 누구나 취소할 때까지 연결할 수 있습니다. 공유 액세스를 취소하면 활성 클라이언트의 연결이 즉시 끊어집니다.",
+ "68ec21309f": "액세스 취소",
+ "6f6d5188ed": "{{value0}} 취소",
+ "87b16cd11d": "생성됨",
+ "434e4a6af6": "현재 링크",
+ "fd83b94095": "아직 공유 서버에 액세스할 수 없습니다.",
+ "27cf8507ad": "공유 액세스 새로 고침",
+ "f031182867": "공유 서버 액세스",
+ "df142657a5": "아직 사용되지 않음",
+ "b18d1764ef": "마지막으로 사용된 날짜: {{value0}}"
+ },
+ "RuntimeEnvironmentsPane": {
+ "aeb26635d2": "{{value0}} 제거",
+ "af53761f31": "취소",
+ "bb90dd6487": "서버 제거",
+ "d2e00809e4": "스위치",
+ "05e0fc3ebf": "다음으로 전환",
+ "b2290ed203": "Orca는 다음 서버에서 프로젝트를 로드하기 전에 현재 서버에서 원격 터미널과 브라우저 탭을 닫습니다.",
+ "d570c35a99": "서버 전환",
+ "84b9b2be05": "브라우저나 다른 Orca 클라이언트가 연결할 수 있도록 취소 가능한 액세스 권한을 생성합니다.",
+ "6e1280ca55": "이 Orca 서버 공유",
+ "9a3758d983": "저장된 서버가 없습니다.",
+ "9bee6bbeeb": "서버 추가",
+ "55fcc964cd": "서버에 인쇄된 페어링 URL을 붙여넣습니다.",
+ "960e901ae4": "orca Serve --pairing-address <호스트>",
+ "163671f7b5": "달리다",
+ "c3d772c514": "orca://pair?code=...",
+ "9bc9b83474": "페어링 코드",
+ "e038625857": "개발 상자",
+ "54ebacc600": "서버 이름",
+ "1826bd0608": "저장된 서버",
+ "6ce4664003": "서버 새로 고침",
+ "b07070ed3c": "연결된 서버가 없습니다",
+ "78692becbd": "로컬 데스크탑",
+ "64b6bea541": "활성 서버",
+ "99ac81fb43": "{{value0}}(으)로 전환되었습니다.",
+ "b5b5114cb0": "{{value0}}을(를) 삭제했습니다.",
+ "6cb6eae14f": "런타임 환경을 저장하지 못했습니다.",
+ "7b5986c8df": "{{value0}}에 저장되었습니다. 준비되면 Active Server를 사용하여 전환하세요.",
+ "a5b58465b6": "{{value0}}에 연결되었습니다.",
+ "5ef712f407": "\"{{value0}}\"이라는 서버가 이미 존재합니다.",
+ "0c55a47480": "이름과 페어링 코드가 필요합니다.",
+ "e6410d72c3": "런타임 환경을 로드하지 못했습니다.",
+ "6ef71985da": "엔드포인트 없음",
+ "ed3e3f069d": "그러면 Orca에서 저장된 서버가 제거됩니다. 활성 서버는 변경되지 않습니다.",
+ "b2fda48c39": "활성 서버를 제거하면 이 브라우저의 연결이 끊어지고 해당 서버에 대한 원격 터미널과 브라우저 탭이 닫힙니다.",
+ "9f7665a01b": "먼저 활성 서버를 제거하면 Orca가 로컬 데스크톱으로 다시 전환되고 해당 서버에 대한 원격 터미널과 브라우저 탭이 닫힙니다.",
+ "3595fd1948": "새 링크",
+ "54dee18f5c": "양식 숨기기",
+ "8cf8790697": "저장된 서버는 페어링된 Orca 런타임을 통해 이 브라우저를 라우팅합니다.",
+ "f75ce1c7a5": "로컬은 오늘날의 데스크탑 동작을 유지합니다. 저장된 서버는 원격 런타임을 통해 지원되는 클라이언트 호출을 라우팅합니다."
+ },
+ "RuntimePairingGeneratedUrlRows": {
+ "0495f68959": "{{value0}} 복사"
+ },
+ "RuntimePairingUrlGenerator": {
+ "849825e829": "이 페어링 URL을 다른 Orca 클라이언트에 붙여넣습니다.",
+ "2e5c4e3c93": "다른 Orca 클라이언트와 페어링",
+ "f7cafdc9f3": "이 빌드에서는 브라우저 링크를 사용할 수 없습니다. Orca 클라이언트에서는 페어링 URL이 계속 작동합니다.",
+ "6b9ca3e69b": "브라우저에서 열기",
+ "1ca2e5194d": "선택한 주소에 접근할 수 있는 브라우저에서 이 URL을 사용하세요.",
+ "8de0f84fff": "액세스 링크 생성",
+ "279e0dcb57": "127.0.0.1은 이 컴퓨터에서만 작동합니다. 다른 장치에 LAN, Tailscale 또는 사용자 정의 주소를 사용하십시오.",
+ "45cf476df3": "호스트, 호스트:포트 또는 wss://host/path",
+ "4531ea3158": "맞춤 주소",
+ "360c548cf3": "연결 주소 새로 고침",
+ "de6d5cff95": "이 컴퓨터(",
+ "de77eb1b65": "연결 주소",
+ "ff80904fc4": "브라우저 또는 데스크톱 클라이언트에 대해 취소 가능한 액세스 권한을 만듭니다.",
+ "f8500e134a": "이 Orca 서버 공유",
+ "d6c081adf4": "URL을 복사하지 못했습니다.",
+ "df0aa45a86": "페어링 URL을 복사했습니다.",
+ "13704d635e": "웹 클라이언트 URL을 복사했습니다.",
+ "e8d83f2b0f": "공유 액세스를 취소하지 못했습니다.",
+ "9f8e037c4a": "공유 액세스가 취소되었습니다.",
+ "d797f516b1": "공유 액세스가 이미 취소되었습니다.",
+ "2ed55c841a": "페어링 URL을 생성하지 못했습니다.",
+ "11d5248e62": "생성된 페어링 URL입니다.",
+ "6dd594a507": "생성된 웹 클라이언트 URL.",
+ "2752126f3e": "런타임 페어링을 사용할 수 없습니다.",
+ "95b8be4cea": "네트워크 인터페이스를 새로고침하지 못했습니다.",
+ "1b4e0bbcc5": "공유 액세스 권한을 로드하지 못했습니다.",
+ "b91e36a986": "편물"
+ },
+ "Settings": {
+ "3bf149e873": "프로젝트 설정 > {{value0}}",
+ "075341c763": "아직 구체화되고 있는 새로운 기능입니다. 한번 시도해 보세요.",
+ "8b017f2506": "실험적",
+ "499c1cd7f9": "문제 해결을 위한 낮은 수준의 호환성 설정입니다.",
+ "1c87f8d024": "고급",
+ "c1b43dc4e2": "익명의 사용 데이터 및 텔레메트리 제어.",
+ "d7e3f62d70": "개인정보 및 텔레메트리",
+ "9b83cc62c2": "터미널에서 실행되는 개발자 도구에 대한 macOS 개인 정보 보호 액세스입니다.",
+ "65660d4548": "macOS 권한",
+ "c6c01ac209": "휴대폰에서 터미널과 에이전트를 제어하세요.",
+ "c40dadaac8": "모바일",
+ "c2ee313198": "파일, 터미널, Git을 위한 원격 SSH 호스트입니다.",
+ "9b02492d1f": "SSH 호스트",
+ "b5ee17826b": "로컬 데스크톱 모드와 페어링된 원격 Orca 런타임 간에 전환합니다.",
+ "7686cb5c36": "이 브라우저를 저장된 Orca 서버에 연결하세요.",
+ "bd0181eeca": "원격 Orca 서버",
+ "8acf3f22e0": "Orca 통계와 Claude, Codex 및 OpenCode 사용 분석.",
+ "954a8f5aef": "통계 및 사용량",
+ "a737a4bb22": "일반 작업에 대한 키보드 단축키입니다.",
+ "23bf7a1ad4": "단축키",
+ "7210ac09c4": "에이전트 활동 및 터미널 이벤트에 대한 기본 데스크톱 알림입니다.",
+ "9907545fa3": "알림",
+ "d0b7021d64": "선택 및 편집 동작.",
+ "d7a3e635b6": "입력 및 편집",
+ "6d1a27e193": "테마, 확대/축소, 앱 및 터미널 모양, 사이드바, 상태 표시줄.",
+ "2b4474780a": "외관",
+ "3d9adfe6a5": "전역 터미널, 브라우저 및 마크다운 탭.",
+ "3eb22a3ada": "플로팅 워크스페이스",
+ "01f9d36292": "Orca 및 코딩 에이전트에 대한 모바일 에뮬레이터 지원을 구성합니다.",
+ "f75daf1002": "모바일 에뮬레이터",
+ "ad9788036f": "홈페이지, 링크 라우팅 및 세션 쿠키.",
+ "c46215ea03": "브라우저",
+ "6742c7932c": "전역적으로 또는 프로젝트별로 범위가 지정된 저장된 터미널 명령입니다.",
+ "13d4fe30ad": "빠른 명령어",
+ "b79b5b31e9": "셸, 렌더러, 세션 및 터미널 동작.",
+ "3de4bbb841": "터미널",
+ "dd72ed437a": "작업 페이지와 사이드바에 표시할 작업 제공자를 선택합니다.",
+ "11faa2f7dd": "작업 소스",
+ "cfa34f4465": "브랜치 이름 지정, 기본 참조, 속성 및 Git AI Author.",
+ "70100f94c7": "Git 및 소스 제어",
+ "b07041697f": "GitHub, GitLab, Linear 및 소스 호스팅 서비스를 연결하세요.",
+ "c9ca101a3b": "연동",
+ "f9b77539fd": "워크스페이스 기본값, 앱 설정 및 유지 관리.",
+ "7807c11c4d": "일반",
+ "6855b0f77d": "Orca를 병렬 에이전트 작업에 유용하게 만드는 핵심 워크플로를 완료합니다.",
+ "6d119427ef": "온보딩 체크리스트",
+ "eb1176a14e": "온디바이스 모델을 사용한 로컬 음성-텍스트 받아쓰기.",
+ "5063bb47a5": "음성",
+ "7118953f14": "에이전트가 컴퓨터의 모든 앱을 제어할 수 있도록 하세요.",
+ "c9841721cb": "컴퓨터 사용",
+ "475980f53d": "Orca를 통해 여러 코딩 에이전트를 조정합니다.",
+ "00c3a7950d": "오케스트레이션",
+ "21f09426ea": "선택 사항. Orca는 기존 공급자 로그인과 함께 작동합니다. Orca가 계정 간 전환을 돕도록 원하는 경우에만 계정을 추가하세요.",
+ "ad6c529693": "AI 제공업체 계정",
+ "ec1ba547f7": "AI 에이전트를 관리하고, 기본값을 설정하고, 명령을 사용자 정의하세요.",
+ "8afa676615": "에이전트",
+ "add3b97ee6": "\"",
+ "3c88ec55d6": "'에 대한 설정을 찾을 수 없습니다.",
+ "c7ad095d96": "설정 로드 중...",
+ "acc7bbdefd": "설정을 종료하려면 ESC를 다시 누르세요.",
+ "43b68e10f0": "저장되지 않은 Git AI Author 변경사항이 있습니다. 떠나면 폐기됩니다.",
+ "17bdee4ff1": "저장되지 않은 Git AI Author 변경사항을 삭제하시겠습니까?",
+ "084d8fac5b": "개인 정보 보호 및 보안",
+ "23931df7e8": "원격 액세스",
+ "8bd117d669": "인터페이스",
+ "e1578cd4bc": "워크플로",
+ "9abb9be3bc": "설정 시작",
+ "23c6874fdf": "AI 기능",
+ "2309068a6f": "파괴적인",
+ "65358016ea": "버리기"
+ },
+ "SettingsFormControls": {
+ "42a4d15a30": "일치하는 글꼴이 없습니다.",
+ "b55371ea18": "글꼴",
+ "c766f8ac75": "글꼴 제안 전환",
+ "74bcecd5ec": "지우기",
+ "a4ff6143f8": "글꼴 선택 지우기",
+ "b661b034ec": "· 기본:",
+ "ceefb9d7f1": "테마를 찾을 수 없습니다.",
+ "9119fb2268": "현재",
+ "4e11f87ca6": "표시 중",
+ "fbb428db98": "선택된:",
+ "fac59213fc": "내장 테마 검색",
+ "cb330ef7f8": "{{value0}} 중",
+ "c822571b2e": "\"{{value0}}\"과 일치",
+ "3119c012a5": "문자열"
+ },
+ "SettingsSidebar": {
+ "e0900f83e7": "SSH",
+ "5c9669ff9c": "프로젝트",
+ "dbceaa8840": "설정 검색",
+ "60f8a673a7": "앱으로 돌아가기",
+ "6503182299": "온보딩 체크리스트",
+ "82db1b7de4": "온보딩 체크리스트, {{value0}}/{{value1}} 완료. 설정 가이드 보기.",
+ "df38d612b7": "아직 추가된 프로젝트가 없습니다.",
+ "3e483e256b": "일치하는 프로젝트 설정이 없습니다."
+ },
+ "ShortcutBindingRow": {
+ "4a4c2c9d32": "바로가기 추가",
+ "87381fd8f8": "키를 누르세요…",
+ "9cdaaa3d8f": "바로가기 비활성화",
+ "3b62c142fa": "{{value0}} 비활성화",
+ "f75335b155": "기본값으로 재설정",
+ "4f2c9b2a05": "{{value0}}을 기본값으로 재설정",
+ "97dccee14e": "수정됨",
+ "3b11ef3a43": "{{value0}} 바로가기",
+ "f6579be67b": "바로가기 변경",
+ "6a7848fdac": "단축키 입력 대기 중"
+ },
+ "ShortcutFilterRail": {
+ "28b63545bf": "상태",
+ "8a1e78c14b": "바로가기 상태 필터",
+ "df8466f3fc": "바로가기 검색 지우기",
+ "f733c4b89f": "검색 명령 또는 키",
+ "02dc7d4251": "바로가기 검색",
+ "1d5634ba31": "{{value0}} 바로가기"
+ },
+ "ShortcutRowsList": {
+ "4ce3cd24d9": "해당 필터와 일치하는 바로가기가 없습니다."
+ },
+ "ShortcutTerminalPolicyControl": {
+ "0762983d13": "터미널 우선",
+ "63308571d8": "Orca 먼저",
+ "c43c7ff5f9": "바로가기를 누가 먼저 가로챌지 결정",
+ "c3a554288e": "터미널의 단축키",
+ "0f55c6f15c": "바로가기가 겹칠 때 Orca 또는 집중된 터미널이 승리할지 선택합니다."
+ },
+ "ShortcutsPane": {
+ "4b7ae34062": "곧장.",
+ "38e86e206a": "바로가기를 시각적으로 사용자 정의하거나 편집하세요",
+ "47f8f7aef9": "키보드 단축키",
+ "f0b35b0b2e": "터미널 또는 TUI에 키보드 포커스가 있는 동안에는 비활성화됩니다.",
+ "5c65d5db9d": "터미널 우선",
+ "dfa8ff612f": "터미널이나 TUI에 키보드 포커스가 있는 동안에도 실행됩니다.",
+ "2a0e8aeccf": "Orca 먼저",
+ "3c0fac059a": "터미널에 키보드 포커스가 있는 동안에도 계속 실행됩니다.",
+ "25b0004fbf": "터미널 활성",
+ "781cb74d22": "터미널 패널에서 실행됩니다.",
+ "cb02e00202": "터미널",
+ "d8c988dab4": "~/.orca/keybindings.json"
+ },
+ "SourceControlAiActionRecipeDefaults": {
+ "2576299196": "인수",
+ "b3914ecbbc": "버리기",
+ "fb09da4345": "명령 템플릿",
+ "2cb4bb7e5d": "CLI 인수",
+ "0740d30915": "사용자 정의 명령",
+ "ee0e5c2a48": "기본 에이전트 사용",
+ "bf84dea6af": "Orca가 컨텍스트를 삽입하도록 하려는 경우에만 변수를 사용하십시오. 일반 에이전트 기본 설정을 따르려면 에이전트를 기본값으로 둡니다.",
+ "a79c567194": "액션 레시피",
+ "cf01d41bce": "각 소스 제어 AI 버튼에서 사용되는 에이전트, CLI 인수 및 명령 템플릿입니다.",
+ "a9359c8aa9": "알 수 없는 오류",
+ "b5f46664d3": "소스 제어 AI 작업 기본값을 저장하지 못했습니다: {{value0}}",
+ "d18d665e12": "저장",
+ "4f549a5fa8": "저장 중...",
+ "9d3cc627f8": "저장됨",
+ "817128d94e": "저장되지 않은 변경사항",
+ "7ab1437a12": "PR",
+ "e5b24893ba": "저지르다",
+ "06a9dab64d": "검사",
+ "cb67b938c5": "고치다",
+ "2037c78a6f": "주형",
+ "eb7e8f3b39": "모델",
+ "d74fdc776c": "명령",
+ "673369fe0c": "CLI",
+ "db9bd75d10": "인수",
+ "926d58e87f": "에이전트"
+ },
+ "SparsePresetSettingsSection": {
+ "6fa754d20f": "삭제",
+ "fe1f2c6572": "{{value0}} 편집",
+ "88bfbf1a9c": "이 저장소에 저장된 희소 사전 설정이 없습니다.",
+ "d7565029a9": "새로운 사전 설정",
+ "17f8c4ce10": "스파스 작업 트리 생성을 위해 저장된 디렉터리 세트를 관리합니다.",
+ "388513be2d": "스파스 체크아웃 사전 설정",
+ "a05bc9183f": "사전 설정 저장",
+ "2d7d45e991": "취소",
+ "c240a16f25": "패키지/웹 또는 앱/API와 같은 저장소 상대 경로를 사용하세요.",
+ "fde7ff2cc3": "패키지/웹 공유/UI",
+ "caf33029cc": "디렉토리",
+ "3b6f1abd3e": "예를 들어 웹 전용",
+ "a6fcdd9e3c": "이름",
+ "b9922ec194": "사전 설정 편집 취소",
+ "694cc55ecb": "저장된 디렉터리는 이 저장소에 대한 희소 작업 트리를 생성할 때 사용됩니다.",
+ "8b64731aaf": "더",
+ "755c6a1a0d": "확인",
+ "a7bcf206b1": "삭제 중",
+ "ba9ad2d4cd": "업데이트 날짜 알 수 없음",
+ "568d7e1e49": "{{value0}} 업데이트됨",
+ "d7b3f0bdc3": "{{value0}} 디렉토리",
+ "9d3c087fc0": "디렉토리 1개",
+ "8deb7024ab": "부족한 사전 설정 로드 중...",
+ "92c08ccae3": "스파스 사전 설정을 로드할 수 없습니다.",
+ "3dfa765ca7": "{{value0}} 디렉토리가 저장됩니다.",
+ "b532b9c17d": "1개의 디렉토리가 저장됩니다.",
+ "623b4cf910": "사전 설정 편집",
+ "68bbcd864a": "새로운"
+ },
+ "SshDestructiveActionDialog": {
+ "895b216267": "취소"
+ },
+ "SshPane": {
+ "c0f1c80166": "구성된 SSH 대상이 없습니다.",
+ "639ceb3698": "대상 추가",
+ "51d7dba44d": "수입",
+ "a7d28dff81": "Orca에서 연결할 원격 호스트를 추가합니다.",
+ "94c5284560": "대상",
+ "f495689b82": "가져오기 실패",
+ "f8050f6307": "동기화된 {{value0}} 서버{{value1}}",
+ "68c13b4589": "테스트 실패",
+ "81d08bcddf": "연결 성공",
+ "2c4ee7332b": "원격 릴레이를 재설정하지 못했습니다.",
+ "db2e48975e": "원격 릴레이 재설정",
+ "025e107643": "원격 터미널을 종료하지 못했습니다.",
+ "90e308c98b": "원격 터미널 종료됨",
+ "a43de1d3ee": "연결 해제 실패",
+ "e95d5ae10e": "연결 실패",
+ "c2a69510e3": "대상을 제거하지 못했습니다.",
+ "a0237eb1ca": "대상이 제거되었습니다.",
+ "2227ce47b6": "대상을 저장하지 못했습니다.",
+ "f602009125": "대상이 추가됨",
+ "b4ba0ce33d": "타겟이 업데이트되었습니다.",
+ "3879cbaa52": "릴레이 유예 기간은 60초에서 {{value0}}초 사이여야 하며, 재설정될 때까지 유지를 선택해야 합니다.",
+ "4db9afce1c": "포트는 1에서 65535 사이여야 합니다.",
+ "0e5aa04161": "호스트 또는 SSH 구성 별칭이 필요합니다.",
+ "f1fc50dad2": "SSH 대상을 로드하지 못했습니다.",
+ "0cda732f43": "연결 테스트 실패"
+ },
+ "SshPassphraseDialog": {
+ "d5a234456f": "취소",
+ "c3ce71aad6": "암호를 입력하세요",
+ "abaa0dc653": "비밀번호를 입력하세요",
+ "ce4fdf7914": "다음에 대한 암호를 입력하세요.",
+ "dbf9b6f2d0": "비밀번호를 입력하세요",
+ "c55f105262": "SSH 자격 증명 요청을 취소하지 못했습니다.",
+ "b8e88fd0de": "SSH 자격 증명을 제출하지 못했습니다.",
+ "405066423c": "터놓다",
+ "bec2c1318f": "연결",
+ "8a349e3fac": "{{value0}}의 암호",
+ "cab3d5f5a5": "{{value0}}의 비밀번호",
+ "1f3dde805d": "SSH 키 암호",
+ "106bd57f4a": "SSH 비밀번호"
+ },
+ "SshTargetCard": {
+ "ec6543cee9": "연결",
+ "0e53e9f8e8": "시험",
+ "1810b51482": "연결 중",
+ "4c86f30877": "연결 해제",
+ "7f7b3d7ab4": "대상 제거",
+ "3d21a22d0e": "대상 제거",
+ "3d8af2949f": "대상 편집",
+ "762a48c662": "원격 릴레이 재설정",
+ "97dea4e8cf": "원격 릴레이 재설정",
+ "da16e108e6": "원격 터미널 종료",
+ "c77f1abfe3": "원격 터미널 종료",
+ "18968ede9e": "오류",
+ "f0871e6bfb": "연결",
+ "47e94bd6ba": "연결됨"
+ },
+ "SshTargetDestructiveActions": {
+ "7e66942808": "그러면 이 SSH 대상에서 활성 터미널 세션이 중지됩니다. 다시 연결해도 복원되지 않습니다.",
+ "accf177a03": "원격 터미널을 종료하시겠습니까?",
+ "26be00392d": "그러면 이 SSH 대상에 대한 원격 릴레이가 강제 중지됩니다. 이 대상에 대한 활성 원격 터미널 및 포트 전달이 종료됩니다.",
+ "570a7a0574": "원격 릴레이를 재설정하시겠습니까?",
+ "3bb0cf0ee4": "그러면 대상이 제거되고 활성 원격 터미널이 종료됩니다.",
+ "4808966c41": "SSH 대상 제거"
+ },
+ "SshTargetForm": {
+ "fea9cb402e": "취소",
+ "1b19b00e93": "(7일).",
+ "137e88ce8d": "연결 해제 후 릴레이가 터미널을 활성 상태로 유지하는 기간입니다. 기본값: 10800(3시간). 최고:",
+ "b574994adc": "원격 터미널은 종료하거나 릴레이를 재설정할 때까지 계속 사용할 수 있습니다.",
+ "71fc546097": "재설정될 때까지 살아 있음",
+ "92f80edbfd": "릴레이 유예 기간(초)",
+ "feae1d1e69": "선택 사항. ProxyJump / ssh -J와 동일합니다.",
+ "11bcb4507a": "bastion.example.com",
+ "b2ab248ded": "점프 호스트",
+ "3b01ca44a0": "선택 사항. 터널링에 사용됩니다(예: Cloudflare Access, ProxyCommand).",
+ "f42d844544": "예를 들어 cloudflared 액세스 ssh --hostname %h",
+ "c7d0e18ecb": "프록시 명령",
+ "cb91f6375c": "선택 사항. SSH 에이전트는 기본적으로 사용됩니다.",
+ "d6a5f2ee5c": "~/.ssh/id_ed25519(SSH 에이전트의 경우 비워 두세요)",
+ "63c0c145c1": "신원 파일",
+ "c94cfa634c": "포트",
+ "47e082bc17": "배포",
+ "dc1dc52aaa": "사용자 이름",
+ "2ee9bcd2e8": "서버, 배포@서버:2222, ssh://서버",
+ "ce370ce674": "호스트 또는 별칭 *",
+ "b8dab0aa7b": "내 서버",
+ "298de87a88": "상표",
+ "9518545cb6": "대상 추가",
+ "a62b4cb39a": "변경 사항 저장",
+ "29af933cd5": "새로운 SSH 대상",
+ "f2331ce599": "SSH 대상 편집"
+ },
+ "TasksPane": {
+ "3a72b9745e": "작업 페이지와 사이드바 바로가기에 표시할 작업 제공자를 선택합니다.",
+ "f71d8a9dd3": "작업 제공자",
+ "71644aba56": "작업 페이지 소스 선택기 및 사이드바 바로가기에 표시할 작업 제공자를 선택합니다. 하나 이상의 제공업체가 계속 표시되어야 합니다.",
+ "93e72ef659": "작업 소스",
+ "8e1305fcc6": "작업 소스 선택기 및 사이드바 바로가기에 Jira를 표시합니다.",
+ "6b23a34f6d": "Jira",
+ "e4170c9615": "작업 소스 선택기 및 사이드바 바로가기에 Linear를 표시합니다.",
+ "09ae2d7c51": "Linear",
+ "dd67a1b6e1": "작업 소스 선택기 및 사이드바 바로가기에 GitLab을 표시합니다.",
+ "7c5d7fdc20": "GitLab",
+ "1db47236cd": "작업 소스 선택기 및 사이드바 바로가기에 GitHub를 표시합니다.",
+ "e14063e727": "GitHub"
+ },
+ "TerminalAppearanceSection": {
+ "a14a427ae4": "창 구분선의 두께입니다.",
+ "f27a99978d": "분배기 두께",
+ "db632cb50e": "현재 활성화되지 않은 창에 불투명도가 적용됩니다.",
+ "a6fdd6a3b1": "비활성 창 불투명도",
+ "1b79379d4f": "비활성 창 밝기 조절 및 분할 구분선 두께를 제어합니다.",
+ "e1a5c25555": "터미널 패널",
+ "04cdf85dec": "터미널 커서의 불투명도입니다.",
+ "b9f1804422": "Cursor 불투명도",
+ "2de6b5a699": "선택한 커서 모양의 깜박이는 변형을 사용합니다.",
+ "74736cc9b1": "깜박이는 Cursor",
+ "2e5aec3cf6": "밑줄",
+ "52854a5608": "차단",
+ "e070e8aeba": "술집",
+ "db270cc9a9": "Cursor 모양",
+ "d455f2ef4f": "Orca 터미널 패널의 기본 커서 모양입니다.",
+ "abcb4dd019": "터미널 Cursor",
+ "70beb1bbc7": "시사",
+ "31f6e61085": "합자는 현재",
+ "870377082f": "끄다",
+ "84bd22f2cd": "~에",
+ "bc9ff84d61": "자동",
+ "be8da35e7f": "글꼴 합자",
+ "4b1f29598e": "자동 - \"{{value0}}\"에 대해 비활성화되었습니다.",
+ "400e950ca5": "자동 - \"{{value0}}\"에 대해 활성화되었습니다.",
+ "04569feb07": "제공되는 글꼴의 경우에도 항상 꺼져 있습니다.",
+ "7234abcd08": "항상 켜져 있습니다. 합자가 없는 글꼴은 있는 그대로 렌더링됩니다.",
+ "7233d594bf": "제공되는 글꼴에 대한 프로그래밍 합자(예: =>, !=, ===)를 렌더링합니다. \"자동\"은 알려진 합자 글꼴(Fira Code, JetBrains Mono, Cascadia Code, Iosevka 등)에 대해서만 합자를 활성화합니다.",
+ "bafc80efbc": "터미널 라인 높이 승수를 제어합니다.",
+ "c084eb7d4c": "라인 높이",
+ "36af8ad94c": "터미널 텍스트 글꼴 두께를 제어합니다.",
+ "4aae5db258": "글꼴 두께",
+ "f04b17a50e": "새 창 및 라이브 업데이트를 위한 기본 터미널 글꼴 모음입니다.",
+ "a408266e67": "글꼴군",
+ "855a76343a": "Ghostty에서 가져오기",
+ "711e589f18": "새 창 및 실시간 업데이트에 대한 기본 터미널 입력 체계입니다.",
+ "048aac8a64": "터미널 타이포그래피",
+ "4415beb958": "비활성",
+ "4e7d41a9f0": "활성화됨",
+ "e90afcc44f": "끄다",
+ "16c471ee03": "~에"
+ },
+ "TerminalFontSizeSetting": {
+ "9b5252c85a": "px",
+ "0f4c92e595": "새 창 및 라이브 업데이트의 기본 터미널 글꼴 크기입니다.",
+ "a4a352b1e9": "글꼴 크기"
+ },
+ "TerminalPane": {
+ "4263e940e0": "대신 JIS 엔(\\) 키를 누르면 백슬래시(\\\\)가 전송됩니다.",
+ "19f4935159": "JIS 엔(¥)을 백슬래시(\\\\)로",
+ "1c337bef4a": "JIS 엔(\\) 키를 누르면 백슬래시(\\\\)가 대신 전송되는지 여부를 제어합니다.",
+ "3fe1c5bfe0": "끄다",
+ "c73d510938": "오른쪽",
+ "e7aec1fd60": "왼쪽",
+ "badb1219fc": "둘 다",
+ "43c2ff7b0e": "자동",
+ "0a10420e1a": "Alt로서의 옵션",
+ "ce3aadf0b2": "{{value0}} Option 키는 Alt/Esc를 보냅니다. 다른 하나는 특수 문자를 구성합니다.",
+ "b62373091a": "두 Option 키 모두 Alt/Esc 시퀀스를 보냅니다.",
+ "d8998bb328": "Option은 키보드 레이아웃에 대한 특수 문자를 구성합니다.",
+ "d21c493808": "자동 — 감지됨: {{value0}}.",
+ "2561d3fc1b": "macOS Option 키가 Alt/Esc 시퀀스를 보내거나 문자를 구성하는지 여부를 제어합니다.",
+ "96be03b8eb": "파워셸 7+",
+ "d26174e1dd": "윈도우 파워셸",
+ "fe20f79dd1": "파워셸 버전",
+ "822f62ddcd": "파워셸 7+ 다운로드",
+ "a016ffbeed": "Auto는 이제 Windows PowerShell을 사용하고 설치 시 PowerShell 7+로 전환합니다.",
+ "5ed5c95344": "새 터미널 패널을 위해 Windows PowerShell과 PowerShell 7+ 중에서 선택하세요.",
+ "3d88af864d": "PowerShell 셸 옵션이 새 터미널 패널에 대해 Windows PowerShell을 시작할지 아니면 PowerShell 7+를 시작할지 선택합니다.",
+ "8a956cc91e": "두 번 클릭 선택 시 단어 경계로 처리되는 문자입니다.",
+ "4bebcc2b2c": "단어 구분 기호",
+ "12e06178fa": "MB",
+ "907b0b9d3e": "Custom",
+ "5336c096af": "{{value0}}메가바이트",
+ "81d86b2dd2": "새 터미널 패널의 최대 터미널 스크롤백 버퍼 크기입니다.",
+ "9df53f7c14": "스크롤백 크기",
+ "c3810b2b42": "최대 터미널 스크롤백 버퍼 크기.",
+ "267d020745": "스크롤백, 단어 경계 및 플랫폼별 터미널 동작.",
+ "5e5f06c82c": "고급",
+ "003df129fe": "수평으로 분할",
+ "623e62df99": "가로로 분할",
+ "332e8a2872": "수직으로 분할",
+ "691ce810e0": "수직으로 분할",
+ "1158f8fd55": "새 탭",
+ "6c6a054a1c": "새 탭에서 실행",
+ "a9d47451d1": "\"새 탭\"은 포커스를 잃지 않고 \"설정\"이라는 제목의 배경 탭에서 설정 명령을 엽니다.",
+ "d23b43c5be": "설정 스크립트 위치",
+ "34a0dfa06e": "새 워크스페이스가 생성될 때 저장소 설정 스크립트가 실행되는 위치입니다.",
+ "21f8da2078": "워크스페이스 설정 스크립트",
+ "6e6480a7df": "터미널의 프로그램(tmux, Neovim, fzf, SSH)을 시스템 클립보드에 복사할 수 있습니다.",
+ "3338dcf8c1": "TUI 클립보드 쓰기 허용(OSC 52)",
+ "69c64a479c": "tmux, Neovim 및 fzf가 PTY(SSH 포함)를 통해 시스템 클립보드에 복사하도록 합니다.",
+ "4729c645fc": "터미널 선택 사항을 클립보드에 자동으로 복사합니다.",
+ "902f5dee1f": "선택 시 복사",
+ "9129b7e805": "터미널 패널에 마우스를 가리키면 클릭하지 않고도 활성화됩니다.",
+ "8eefeaa3da": "초점은 마우스를 따릅니다",
+ "96fe15def8": "터미널 패널의 마우스 및 클립보드 동작.",
+ "45721f3e67": "터미널 상호작용",
+ "9c0b1c1792": "~에",
+ "c1fc9e9444": "GPU 가속",
+ "e0996d141a": "지원되지 않거나 위험한 렌더러에 대한 DOM 대체 기능을 사용하여 WebGL을 자동으로 시도합니다.",
+ "7eaccc1424": "WebGL은 항상 터미널 패널에 대해 시도됩니다.",
+ "fe4acf36c6": "WebGL이 비활성화되었습니다. 최대 호환성을 위한 DOM 렌더러.",
+ "f07dfb4466": "터미널이 xterm.js WebGL 렌더링을 사용하는지 여부를 제어합니다. 렌더러가 지원되면 자동으로 WebGL을 시도하며, 소프트웨어 또는 알 수 없는 GPU 렌더러에 대한 보수적인 Linux 대체 기능을 사용합니다.",
+ "72bc9334a0": "라이브 창과 새 창에 대한 터미널 렌더러 동작입니다.",
+ "2fba319f21": "표현",
+ "cc8c5ca224": "윈도우 기본값",
+ "d78fc4fdef": "분포 로딩",
+ "219aaa59f4": "WSL 배포",
+ "2503f1e86b": "활성 워크스페이스가 아직 WSL 내부에 있지 않은 경우 새 WSL 터미널 패널 및 로컬 에이전트 감지에 사용됩니다.",
+ "5fe79a5e56": "새 WSL 터미널 및 로컬 에이전트 검색에서 사용할 WSL 배포를 선택합니다.",
+ "b637dd57a7": "WSL",
+ "f61ac77f16": "힘내 배쉬",
+ "0f1b8669e6": "명령 프롬프트",
+ "eb7fc4d98a": "파워셸",
+ "27e301f22c": "기본 쉘",
+ "09bf02de9a": "새 터미널 패널을 열 때 사용되는 셸입니다. 새 터미널에 적용됩니다.",
+ "bd68f3170d": "Windows의 새 터미널 패널에 대한 기본 셸을 선택합니다.",
+ "a55eee649f": "Windows의 새 터미널 패널에 대한 기본 셸입니다.",
+ "87e678a8af": "윈도우 셸",
+ "05efc0bada": "진실",
+ "348246b06f": "거짓",
+ "5936387ddd": "자동",
+ "adbafefe56": "custom",
+ "16753eea48": "Windows에서는 마우스 오른쪽 버튼을 클릭하여 클립보드를 붙여넣습니다. Ctrl+마우스 오른쪽 버튼을 클릭하면 컨텍스트 메뉴가 열립니다.",
+ "9c178cf8aa": "붙여넣으려면 마우스 오른쪽 버튼을 클릭하세요.",
+ "af0c3b6e39": "Windows에서는 마우스 오른쪽 버튼을 클릭하여 클립보드를 터미널에 붙여넣습니다. 컨텍스트 메뉴를 열려면 Ctrl+오른쪽 클릭을 사용하세요.",
+ "29154326bb": "~에",
+ "ab20575a8a": "끄다",
+ "ab3a1f9068": "wsl.exe"
+ },
+ "TerminalSettingsPreview": {
+ "a63953a48a": "{{value0}} 테마 미리보기",
+ "2c248fcc27": "테마 미리보기",
+ "f8931d407d": "미리보기에 창 구분선 표시",
+ "50419052fe": "창 구분선",
+ "d06664e889": "어두운"
+ },
+ "TerminalThemeSections": {
+ "db210115c5": "라이트 모드 미리보기",
+ "5e0c24b5c8": "조명 모드에서 창 사이의 분할 구분선을 제어합니다.",
+ "ec2e33ad80": "라이트 디바이더 색상",
+ "d56af60e6f": "Orca가 조명 모드에 있을 때 사용되는 테마를 선택합니다.",
+ "8273bc75d7": "라이트 테마",
+ "74b15574c8": "선택적 라이트 모드 터미널 모양을 구성합니다.",
+ "b584287e84": "비활성화되면 라이트 모드는 어두운 터미널 테마를 재사용합니다.",
+ "d76f60c9cc": "조명 모드에서 별도의 테마 사용",
+ "bc8e8a251a": "다크 모드 미리보기",
+ "cbe56a0f79": "어두운 모드에서 창 사이의 분할 구분선을 제어합니다.",
+ "b739d2abfe": "다크 디바이더 색상",
+ "7add204bd5": "다크 모드에서 사용되는 터미널 테마를 선택하세요.",
+ "9499ad1dc4": "어두운 테마",
+ "f012172e21": "어두운 모드에서 터미널 패널에 사용되는 테마를 선택합니다."
+ },
+ "TerminalWindowSection": {
+ "1705318506": "ANSI 마젠타색",
+ "03c855d15f": "모든 색상 재정의 재설정",
+ "63f8d9336e": "색상 재정의",
+ "e86e09b5c7": "개별 터미널 색상을 재정의합니다.",
+ "1d1920dc8a": "터미널에 입력할 때 마우스 커서를 숨깁니다.",
+ "3530908ef9": "입력하는 동안 마우스 숨기기",
+ "1846f6ee6a": "터미널 그리드 주변의 수직 패딩(픽셀)입니다.",
+ "1afcc1d973": "수직 패딩",
+ "25e2f8e8e1": "터미널 그리드 주변의 수평 패딩(픽셀)입니다.",
+ "36b8402015": "수평 패딩",
+ "53ce336e15": "창 흐림 변경 사항을 적용하려면 Orca를 다시 시작하십시오.",
+ "c65bb9ce63": "다시 시작해야 함",
+ "97950bb087": "터미널 창에 배경 흐림을 적용합니다. 다시 시작해야 합니다.",
+ "2b82242f43": "창 흐림",
+ "809f37738d": "터미널 배경의 투명도를 제어합니다. 1은 완전히 불투명하고, 0은 완전히 투명합니다.",
+ "ea7b1a158e": "배경 불투명도",
+ "03acb60aa0": "터미널 배경의 투명도를 제어합니다.",
+ "00eaa6b881": "창 모양 및 배경 설정.",
+ "b96ba13ed1": "창문",
+ "42e01a6055": "ANSI 밝은 흰색 색상",
+ "16948119cb": "밝은 흰색",
+ "1601140f03": "ANSI 밝은 청록색",
+ "f94adc4113": "밝은 청록색",
+ "fe4d89ef85": "ANSI 밝은 마젠타 색상",
+ "e56e7d6ea0": "브라이트 마젠타",
+ "bef6c0f6bf": "ANSI 밝은 파란색",
+ "66820332fa": "밝은 파란색",
+ "e2ef5f4ab7": "ANSI 밝은 노란색",
+ "936a326be3": "밝은 노란색",
+ "0ffb02f921": "ANSI 밝은 녹색 색상",
+ "7dafd57730": "밝은 녹색",
+ "667de68863": "ANSI 밝은 빨간색",
+ "32b1b6acd7": "밝은 빨간색",
+ "f30c492769": "ANSI 밝은 검정색",
+ "260d69ce9a": "브라이트 블랙",
+ "1be593d3e8": "안시 브라이트",
+ "28846b1ca6": "ANSI 화이트 색상",
+ "0cb4459fb8": "하얀색",
+ "bd4c759327": "ANSI 청록색",
+ "fb8bb4eb1f": "청록색",
+ "d5e92fcd94": "마젠타",
+ "9635a71c51": "ANSI 블루 색상",
+ "292a4c7316": "파란색",
+ "09c1c6b096": "ANSI 노란색",
+ "bb516de873": "노란색",
+ "8a673d4206": "ANSI 녹색 색상",
+ "8f2092b315": "녹색",
+ "b41270f5ca": "ANSI 레드 색상",
+ "3a78f30b50": "빨간색",
+ "cf4437a2f7": "ANSI 블랙 컬러",
+ "adfdee23cb": "검은색",
+ "68e9f07de0": "ANSI 일반",
+ "fb8c6f1967": "굵은 텍스트의 색상입니다. 설정하지 않으면 일반 색상으로 돌아갑니다.",
+ "862e463f7f": "굵은 글씨",
+ "b2c0857c49": "선택한 텍스트의 텍스트 색상",
+ "8b450b5305": "선택 전경",
+ "74d8555f85": "선택한 텍스트의 배경색",
+ "40c3cfd30a": "선택 배경",
+ "7f4063076c": "커서 아래의 텍스트 색상(블록 커서)",
+ "a2d9f095a7": "Cursor 텍스트",
+ "cd0700762b": "Cursor 색상",
+ "c9e1fdf42f": "Cursor",
+ "da64e8f4c1": "터미널 배경색",
+ "cc1b2ffeb2": "배경",
+ "026a0b8013": "본문 색상",
+ "79f6bfb76e": "전경",
+ "cf37ff69f6": "베이스",
+ "8abdab9f7c": "지금 재시작",
+ "907131d741": "다시 시작하는 중…"
+ },
+ "UIZoomControl": {
+ "c2c64b24d0": "재설정"
+ },
+ "VoicePane": {
+ "68de13f72c": "모델을 삭제하지 못했습니다.",
+ "1ba81c0ff0": "추천",
+ "cfde55c7b0": "모델을 다운로드하지 못했습니다.",
+ "43fd4f454b": "음성 모델",
+ "7cf715f891": "개최됩니다.",
+ "295d84b849": "한 번 시작하고 다시 한 번 중지합니다. 보류: 동안 지시",
+ "ff9a680010": "토글: 누르기",
+ "ba4a900d1d": "받아쓰기 모드",
+ "0121960365": "음성 받아쓰기 활성화",
+ "366e1b4f36": "초점이 맞춰진 창에 텍스트를 입력합니다.",
+ "4465596675": "누르다",
+ "62d2a84d31": "OpenAI API 키를 지우지 못했습니다.",
+ "37aba8bb63": "OpenAI API 키가 삭제되었습니다.",
+ "8572bbb537": "OpenAI API 키를 저장하지 못했습니다.",
+ "506df81ba6": "OpenAI API 키가 저장되었습니다.",
+ "91980ce124": "{{value0}}MB",
+ "61a16c8141": "적출...",
+ "b6536a1d12": "적출",
+ "8f4d2a51d7": "오프라인",
+ "d504ab05f0": "스트리밍",
+ "fbe5990716": "모델 선택",
+ "e24f7d43d2": "음성 모델을 선택하세요. 로컬 모델은 오프라인으로 실행됩니다. 클라우드 모델에는 API 키가 필요합니다.",
+ "174da92062": "잡고 있다",
+ "118b3c2dee": "비녀장",
+ "901985625d": "비녀장",
+ "ad5d036ecc": "마이크 권한을 요청할 수 없습니다. 음성 받아쓰기가 활성화되지 않았습니다.",
+ "f9a9cf6928": "음성 받아쓰기를 활성화하려면 마이크 권한이 필요합니다.",
+ "1eac933202": "macOS 개인 정보 보호 및 보안을 열었습니다. 액세스 권한을 부여한 후 받아쓰기를 다시 활성화하세요.",
+ "cd9fe37556": "마이크 권한이 부여되었습니다."
+ },
+ "WorktreeSymlinksSection": {
+ "1c1e35b219": "{{value0}} 제거",
+ "b814c618e2": "연결된 경로",
+ "31ebab5403": "이 저장소에 대해 구성된 심볼릭 링크 경로가 없습니다.",
+ "ea06227efa": "추가됨",
+ "b2429aeb31": "추가",
+ "ab40b8a5f1": "일치하는 항목이 없습니다. 사용자 정의 경로를 추가하려면 계속 입력하세요.",
+ "4cd2a4c077": "경로를 입력하세요(예: .env 또는 node_modules)…",
+ "241325302c": "경로 추가",
+ "7ff265071d": "새 작업 트리가 생성되면 여기에 나열된 각 경로가 기본 체크아웃에서 심볼릭 링크됩니다.",
+ "4755f120b6": "작업 트리 심볼릭 링크",
+ "b07ef5a8b6": "기본 체크아웃에서 새로 생성된 작업 트리로의 심볼릭 링크 경로입니다.",
+ "d72ba8dc68": "{{value0}} 경로",
+ "9ea912d811": "경로 1개"
+ },
+ "WslCliRegistration": {
+ "c6f6f89d7c": "취소",
+ "119fef6cd2": "대상 경로:",
+ "1dbb0377d9": "기존 실행기 대상:",
+ "554305956d": "명령 경로:",
+ "9b6627522c": "새로고침",
+ "ab6b022a5c": "WSL CLI 상태 새로 고침",
+ "d9c6880dbd": "WSL 셸 명령",
+ "52d990420e": "WSL에서 `{{value0}}`을(를) 제거하지 못했습니다.",
+ "89c7414cf5": "WSL에서 `{{value0}}`을 제거했습니다.",
+ "6f91ad1333": "WSL에 '{{value0}}'을(를) 등록하지 못했습니다.",
+ "951536dda5": "WSL에 `{{value0}}`을 등록했습니다.",
+ "26b4b3b00f": "WSL CLI 상태를 로드하지 못했습니다.",
+ "290bfff3ab": "등록",
+ "f951f85196": "제거",
+ "4c4a9178a3": "등록 중...",
+ "41a1480d3e": "설치",
+ "4598b18464": "제거 중...",
+ "7c3bb36706": "제거",
+ "7ee4e52b99": "Orca는 명령이 WSL 터미널에서 작동하도록 {{value0}}을 등록합니다.",
+ "d8216eb22e": "이렇게 하면 WSL 셸 명령이 제거됩니다. Orca 자체는 Windows에 설치된 상태로 유지됩니다.",
+ "e49688f67f": "WSL에 `{{value0}}`을 등록하시겠습니까?",
+ "61ac55278e": "WSL에서 `{{value0}}`을(를) 제거하시겠습니까?",
+ "e2b0ee267f": "탁한",
+ "7aa456a460": "WSL 내부의 ~/.local/bin에 `orca-ide`를 등록합니다.",
+ "0307677bb9": "WSL CLI 등록 확인 중..."
+ },
+ "accounts": {
+ "search": {
+ "86edc96bc9": "상태 표시줄",
+ "e949b08ffb": "비율 제한",
+ "7e67d7d1b6": "작업",
+ "421c6be25e": "ID",
+ "be8b621bdc": "워크스페이스",
+ "8dcbef1856": "opencode",
+ "38d22ff8d6": "자동 조회가 실패하면 선택적 워크스페이스 ID가 재정의됩니다.",
+ "4ee2029e9c": "OpenCode Go 워크스페이스 ID",
+ "9c4e40cf6b": "세션",
+ "61f7d1fcbe": "쿠키",
+ "d1d2ae383c": "속도 제한을 가져오려면 opencode.ai 세션 쿠키를 붙여넣으세요.",
+ "6ed1401020": "OpenCode Go 세션 쿠키",
+ "b7c2cee442": "실험적인",
+ "7118d2f908": "자격 증명",
+ "933deaf732": "OAuth",
+ "8630464352": "CLI",
+ "e8e1ff3887": "gemini",
+ "bada4a3218": "Google 인증을 위해 로컬 Gemini CLI 설치에서 OAuth 자격 증명을 추출합니다.",
+ "d819755b02": "Gemini CLI 자격 증명 사용",
+ "35b461d817": "로그인",
+ "f2d666a886": "선택 사항",
+ "8b06729e0f": "활동적인",
+ "5b3f18ef4a": "스위치",
+ "06662af91e": "계정",
+ "70d1b8def5": "codex",
+ "87a4a8584e": "실시간 할당량 읽기를 지원하는 선택적 저장된 Codex 계정을 선택하세요.",
+ "a4bcfd6f86": "활성 Codex 계정",
+ "042885c07c": "오래된",
+ "02c438bc7b": "만료됨",
+ "77e32a2ad3": "재인증",
+ "c759741d77": "몫",
+ "b40d5b6570": "Codex 및 실시간 속도 제한 가져오기를 위한 선택적 계정 전환.",
+ "17c5d244eb": "Codex 계정",
+ "e14049e1a8": "claude",
+ "dd75a73991": "공유 채팅 컨텍스트를 유지하면서 Claude의 선택적 계정 전환.",
+ "75682e1b62": "Claude 계정",
+ "e02c136ad0": "인증",
+ "9f70aa706c": "공급자",
+ "488a7e9206": "리눅스",
+ "0b4d948eb5": "wsl",
+ "bdbd1e668e": "창문들",
+ "593720c17f": "위치",
+ "b84a5b0c8a": "이 장치 또는 WSL에서 공급자 계정을 검사하고 추가할지 선택합니다.",
+ "d09fb5ca92": "계정 위치"
+ }
+ },
+ "advanced": {
+ "search": {
+ "a7002e1ac4": "업데이터",
+ "e61ed8ab33": "업데이트",
+ "6576fce4d2": "문제 해결",
+ "79e0947e95": "지원",
+ "4383251647": "VPN",
+ "f98a60af11": "프록시",
+ "65bf6af262": "호환성",
+ "621233008b": "http/1.1",
+ "f8ff125ebe": "http1",
+ "a0f71bd909": "http/2",
+ "4b4ae4345a": "http2",
+ "48a1c8f534": "http",
+ "4d44352eea": "회로망",
+ "2b4d26d11e": "네트워킹",
+ "e04e9db503": "고급의",
+ "585f56fae0": "프록시 뒤에서 HTTP/2가 실패하는 경우 Electron 네트워킹에 HTTP/1.1을 사용하십시오.",
+ "11eea3da72": "HTTP/1.1 호환성"
+ }
+ },
+ "agents": {
+ "search": {
+ "2814401339": "설치됨",
+ "719f53350c": "경로",
+ "839e82c81f": "감지",
+ "f622b8eb2a": "리눅스",
+ "d608654c03": "wsl",
+ "77c02fa3c3": "창문들",
+ "d2952dfd74": "위치",
+ "96ba2373b6": "에이전트",
+ "cbdd7f3b9e": "설치된 에이전트가 이 장치에서 감지되는지 아니면 WSL에서 감지되는지 선택합니다.",
+ "ef804b7337": "에이전트 위치",
+ "01926b9d8c": "AI 코딩 에이전트, 기본 에이전트 및 명령 재정의를 구성합니다.",
+ "bb9ad95777": "에이전트",
+ "d8f3a8b8a0": "기본값",
+ "167daeb5e9": "명령",
+ "be59907510": "재정의",
+ "a6d594c17d": "설치",
+ "f2932bf22b": "감지됨",
+ "2afd3b5858": "활성화",
+ "60393e1b17": "비활성화",
+ "2e188c771c": "숨기기",
+ "87fffe6c20": "표시",
+ "e2b7c0dcd7": "GitHub",
+ "66b6b82eb4": "깨어 있음",
+ "dbc8aca6b0": "절전",
+ "845ad9128a": "전원",
+ "48f84d10f1": "실행 중",
+ "affbf130f6": "작업 중",
+ "0d1c334987": "뚜껑",
+ "ff8de8a2ad": "표시",
+ "0d752916f8": "훅",
+ "6984d4291a": "상태",
+ "13b20636a6": "대기",
+ "8599603496": "완료",
+ "ea71995548": "제거",
+ "c1317fe641": "복원",
+ "5963143e00": "설정",
+ "042c551bc5": "구성",
+ "f412abbba5": "claude",
+ "5ded38b843": "codex",
+ "be7ea3553b": "탭",
+ "6956646a1e": "제목",
+ "32836788b0": "생성된 제목",
+ "966890236d": "이름",
+ "848dcae8d3": "생성됨",
+ "52115d0d7c": "자동",
+ "c64059f50d": "프롬프트",
+ "5784ae8c43": "이름 변경",
+ "8a17fd6026": "안정적",
+ "a79d266f71": "세션",
+ "afbf35be68": "안정적인 세션"
+ }
+ },
+ "appearance": {
+ "search": {
+ "468448bba4": "수채화",
+ "f586abfa35": "파란색",
+ "651f35b2c6": "스위처",
+ "e5bc35d59e": "창문",
+ "d18b54ca90": "독",
+ "1f2880a9d5": "orca",
+ "2cfb3420c0": "앱 아이콘",
+ "e80c2af428": "Dock 및 창 전환기에 표시된 앱 아이콘을 선택합니다.",
+ "2b313598c6": "앱 아이콘",
+ "839fb1e3ed": "도구 상자",
+ "ac79fe4a04": "표시",
+ "648eeada79": "숨기기",
+ "6cf5f54ce1": "단추",
+ "5bff6a2ef0": "사이드바",
+ "5e5b8878bf": "핸드폰",
+ "74618577c7": "모바일",
+ "682293cadf": "왼쪽 사이드바 상단에 Orca Mobile 버튼을 표시합니다.",
+ "1de96ec8a6": "Orca 모바일 버튼 표시",
+ "4c920ab2d1": "일정",
+ "58f4e22fa2": "오토메이션",
+ "b186f3cefb": "자동화",
+ "ae13a0d340": "왼쪽 사이드바 상단에 자동화 버튼을 표시합니다.",
+ "caa27e1a8e": "자동화 버튼 표시",
+ "6b846424cc": "Linear",
+ "2ee4810f38": "GitHub",
+ "0d5a74b606": "작업",
+ "9a248333c7": "왼쪽 사이드바 상단에 작업 버튼을 표시합니다.",
+ "155a1e7438": "작업 버튼 표시",
+ "a895d0f938": "상표",
+ "51f957ce39": "이름",
+ "36e006efc1": "앱",
+ "bed343b03e": "제목 표시줄",
+ "18b4c4c30b": "제목 표시줄에 Orca를 표시합니다.",
+ "fdd31b00d0": "제목 표시줄 앱 이름",
+ "c1bca1885a": "파일 탐색기",
+ "9f2df826ac": "무시됨",
+ "08c86bf58e": "gitignore",
+ "bce3ac317a": "자식",
+ "7164edf71a": "파일 탐색기에서 .gitignore와 일치하는 희미한 파일.",
+ "f8129fb544": "Git이 무시한 파일 표시",
+ "2f12e1aa3a": "UI",
+ "5095258df2": "인터페이스",
+ "fab91464dd": "이드",
+ "8b36fb3f64": "타이포그래피",
+ "a0e09aed9c": "서체",
+ "24094af355": "폰트",
+ "07c7c38fac": "Orca 인터페이스에서 사용되는 글꼴을 선택합니다.",
+ "ddb991024d": "IDE 글꼴",
+ "0c83659f48": "지름길",
+ "0952091186": "배율",
+ "3ae5de6101": "확대",
+ "adddb91a3d": "전체 애플리케이션 인터페이스를 확장합니다.",
+ "c5e933970f": "UI 줌",
+ "3a9b69d734": "체계",
+ "44d873fd18": "라이트",
+ "262fe1d24f": "다크",
+ "0709c794f7": "Orca가 앱 창에 표시되는 방식을 선택합니다.",
+ "71e06350b4": "주제",
+ "dc02c8759d": "워크스페이스",
+ "43cfba3b95": "섬기는 사람",
+ "46d21eef62": "로컬호스트",
+ "006e67b279": "포트",
+ "896eb53fd4": "상태 표시줄",
+ "0ececfa190": "상태 표시줄에 라이브 워크스페이스 포트를 표시합니다.",
+ "cf409b6c4d": "포트",
+ "cb1cc62cf8": "스페이스",
+ "90bdc043ea": "디스크",
+ "96b4fb0064": "터미널",
+ "4ddbde4999": "CPU",
+ "4355f18ac6": "메모리",
+ "9c4d5f0894": "관리자",
+ "c690a15849": "의지",
+ "81ef5abc2f": "상태 표시줄에 CPU, 메모리, 터미널 세션 및 워크스페이스 디스크 사용량을 표시합니다.",
+ "7cf005b29f": "자원 관리자",
+ "fe192b060e": "주인",
+ "f4997e0f8a": "연결",
+ "a278406ed5": "원격",
+ "6ecad74eb3": "SSH",
+ "f17d66d0d2": "상태 표시줄에 활성 SSH 연결 상태를 표시합니다.",
+ "57fb424c56": "SSH 상태",
+ "35565867cb": "문샷",
+ "de586def95": "신청",
+ "00a028f25f": "용법",
+ "40e5c3c285": "키미",
+ "c927a155d5": "상태 표시줄에 Kimi 구독 사용량을 표시합니다.",
+ "3a6c028ea8": "키미 사용법",
+ "edbf0f63a0": "비용",
+ "afbb6a3767": "토큰",
+ "d77537b580": "opencode-go",
+ "a9d56852eb": "opencode",
+ "7f72de7cbe": "상태 표시줄에 OpenCode Go 토큰 및 비용 사용량을 표시합니다.",
+ "bc046e7899": "OpenCode Go 사용법",
+ "51b0ccd6a2": "Google",
+ "2804a920ad": "gemini",
+ "9660c5b2f1": "상태 표시줄에 Gemini 토큰과 비용 사용량을 표시합니다.",
+ "5bfb874d05": "Gemini 사용량",
+ "97957e374e": "열기",
+ "8dfd676c28": "codex",
+ "e9e4412545": "상태 표시줄에 Codex 토큰 및 비용 사용량을 표시합니다.",
+ "54b1acf24f": "Codex 사용량",
+ "dea0a9a665": "anthropic",
+ "c9fe3a7876": "claude",
+ "de50c6f516": "상태 표시줄에 Claude 토큰 및 비용 사용량을 표시합니다.",
+ "9dc15020d7": "Claude 사용량",
+ "language": {
+ "locale": "로케일",
+ "i18n": "i18n",
+ "translation": "번역"
+ }
+ }
+ },
+ "auto": {
+ "rename": {
+ "branch": {
+ "search": {
+ "0971762141": "케밥 케이스",
+ "a482f6a423": "강타",
+ "7adefcdd94": "주형",
+ "10485c4fc5": "명령",
+ "50139297e6": "내장 프롬프트",
+ "502aa57681": "지침",
+ "40d21f2efc": "프롬프트",
+ "672387fb77": "브랜치 이름을 생성할 때 사용되는 에이전트 명령 템플릿입니다.",
+ "722551c5b3": "브랜치 이름 명령 템플릿",
+ "f41833025e": "생성",
+ "ed677944cc": "작업 트리",
+ "3ef3cbe98c": "에이전트",
+ "f0acf64301": "생물 이름",
+ "7803423877": "자동",
+ "55a1860e47": "이름 변경",
+ "9319bd9827": "브랜치",
+ "ea94b9da8a": "에이전트가 시작되면 작업을 기반으로 자동 생성된 브랜치의 이름을 바꿉니다.",
+ "427f2cd1eb": "브랜치 자동 이름 바꾸기"
+ }
+ }
+ }
+ },
+ "browser": {
+ "search": {
+ "7539f6336c": "윤곽",
+ "1c1e097985": "호",
+ "533a253deb": "가장자리",
+ "75a0d435b7": "크롬",
+ "854ef6ce83": "로그인",
+ "3910a41f32": "인증",
+ "2e7f951773": "수입",
+ "66dd641a47": "세션",
+ "29193a51d5": "쿠키",
+ "2d2d995c58": "브라우저",
+ "060ac1fcba": "Orca 내부의 기존 로그인을 사용하려면 Chrome, Edge 또는 기타 브라우저에서 쿠키를 가져오세요.",
+ "96afedcb5c": "세션 및 쿠키",
+ "a7a07d5415": "편집자",
+ "8dd4805991": "파일",
+ "68d1db8929": "가격 인하",
+ "90425d313c": "옮기다",
+ "72c58f7792": "웹뷰",
+ "82ba1c80ea": "로컬호스트",
+ "bea27bac4b": "모래밭",
+ "44d14df30d": "시사",
+ "5cb082b3e3": "링크 라우팅",
+ "95944898e0": "백분율",
+ "483a0eb5e0": "새 탭",
+ "726f2a8556": "페이지 확대",
+ "5448f4097b": "기본값",
+ "54f4ea55f7": "배율",
+ "4a98ed195f": "확대",
+ "c3d89ed4d0": "새로 열린 브라우저 탭에 확대/축소 수준이 적용되었습니다.",
+ "072b7f5c1f": "기본 줌",
+ "0bb34eacc9": "질문",
+ "8b8ed06e4b": "omnibox",
+ "3538b3aaeb": "토큰",
+ "0732ebe6fb": "사적인",
+ "e1c2a57f07": "카기",
+ "ad40e75d13": "빙",
+ "1f8153acfb": "덕덕고",
+ "8a489aab8d": "Google",
+ "72b4b89970": "엔진",
+ "16bd69cd82": "검색",
+ "0628d5943b": "주소 표시줄에 URL이 아닌 텍스트를 입력할 때 사용되는 검색 엔진입니다.",
+ "5e755920c9": "기본 검색 엔진",
+ "4596a52cf7": "착륙",
+ "5164c47e31": "공백",
+ "4fda4fb066": "URL",
+ "0dbb1eaf4e": "홈페이지",
+ "291f480a5e": "집",
+ "a942905148": "새 브라우저 탭을 만들 때 열리는 URL입니다. 빈 탭을 열려면 비워 두세요.",
+ "c3903322d2": "기본 홈 페이지"
+ },
+ "use": {
+ "search": {
+ "3f4c559deb": "호 프로파일",
+ "d5afa54d21": "가장자리 프로필",
+ "22fb801af8": "크롬 프로필",
+ "59968bb9b4": "인증된 브라우저",
+ "62e2a790c0": "기존 세션",
+ "63a66da648": "시스템 브라우저",
+ "20c1323d1e": "컴퓨터 사용",
+ "ab349a2dd0": "호",
+ "2e1b09897b": "가장자리",
+ "088e7a9012": "크롬",
+ "96ce3d2de2": "인증",
+ "48557f639c": "로그인",
+ "d5ad1f7aad": "수입",
+ "02837ee497": "세션",
+ "fb8178824f": "쿠키",
+ "ba4eb53b72": "브라우저 사용",
+ "2fb24d17db": "에이전트가 로그인을 재사용할 수 있도록 Chrome, Edge 또는 기타 브라우저에서 쿠키를 가져옵니다.",
+ "614c756ab1": "브라우저 쿠키 가져오기",
+ "cee44fb442": "오토메이션",
+ "a57c2172dc": "에이전트 브라우저",
+ "6ea88e5206": "npx",
+ "f5b8fdddf5": "orca-cli",
+ "e5a784bc54": "설치",
+ "9d97446873": "에이전트",
+ "a2d489263e": "스킬",
+ "a7e82445fa": "에이전트가 Orca의 브라우저를 작동할 수 있도록 브라우저 사용 스킬을 설치하세요.",
+ "a1414dcefb": "브라우저 사용 스킬 설치",
+ "e56c7b55c9": "설정",
+ "034c5e8d7f": "활성화",
+ "7e0dcb257a": "껍데기",
+ "3ffafc9b95": "명령",
+ "30c74aaa1f": "경로",
+ "ff05cbc344": "orca",
+ "85fab5e12c": "CLI",
+ "890ddf943d": "에이전트가 브라우저를 구동할 수 있도록 Orca CLI를 등록하세요.",
+ "50f0860e18": "Orca CLI 활성화"
+ }
+ }
+ },
+ "commit": {
+ "message": {
+ "ai": {
+ "search": {
+ "3766941527": "에이전트",
+ "181cdb0637": "열림",
+ "8e9cc598d7": "생성",
+ "b7d50da4d8": "주형",
+ "7e264b926b": "초안",
+ "b261c88609": "PR",
+ "110be48b81": "PR",
+ "001ca3f2af": "Create PR 작성기가 열릴 때 사용되는 기본값입니다.",
+ "eefd33788c": "PR 생성 기본값",
+ "d32936bb2a": "브랜치",
+ "127d512e75": "저지르다",
+ "d22a6459e4": "충돌",
+ "53e8504fb2": "ci",
+ "c46e665f7e": "검사",
+ "37c65bbb44": "고치다",
+ "402f101af8": "프롬프트",
+ "8e0bcc5d99": "모델",
+ "f4731b22bf": "명령",
+ "57c851a68c": "CLI",
+ "61117e57f3": "인수",
+ "0f29331fed": "인수",
+ "18b6d38835": "각 소스 제어 AI 버튼에서 사용되는 에이전트, CLI 인수 및 명령 템플릿입니다.",
+ "3c4e5e5938": "액션 레시피",
+ "ee14a9e9f7": "활성화됨",
+ "82109d627d": "소스 제어",
+ "542e1a00a7": "codex",
+ "f121bec167": "claude",
+ "93e5210da8": "메시지",
+ "c33cb1b982": "일체 포함",
+ "0b946b2abe": "소스 제어 커밋, PR, 브랜치 이름 및 수정 작업에 대한 작업 레시피를 추가합니다.",
+ "24dbdfca78": "소스 제어 AI 작업 표시"
+ }
+ }
+ }
+ },
+ "computer": {
+ "use": {
+ "search": {
+ "6e88da3508": "스킬",
+ "798be54d7e": "오토메이션",
+ "e27f8bafbf": "스크린샷",
+ "26c1290d83": "화면 녹화",
+ "82f01c2d2c": "접근성",
+ "fefb452f5b": "컴퓨터 사용",
+ "9210db582b": "요청 시 에이전트가 스크린샷을 검사하고 로컬 앱을 작동할 수 있도록 허용합니다.",
+ "442bec10fe": "컴퓨터 사용"
+ }
+ }
+ },
+ "developer": {
+ "permissions": {
+ "search": {
+ "3363889768": "로컬 네트워크, USB 및 블루투스",
+ "6c82846f66": "장치",
+ "11653d3f42": "mdns",
+ "78a10b826f": "봉쥬르",
+ "e3fbc48083": "블루투스",
+ "c4a4a02ea4": "USB",
+ "fa3239cd42": "로컬 네트워크",
+ "acad3d4743": "터미널 세션에서 사용되는 장치 및 로컬 네트워크 도구를 허용합니다.",
+ "3e0131e45d": "아이클라우드",
+ "ce07159ff5": "데스크탑",
+ "a0c19119fb": "다운로드",
+ "4438f81bfa": "서류",
+ "c10e36cbd1": "전체 디스크 액세스",
+ "05ab708ee5": "광범위한 터미널 파일 액세스를 위해 macOS 개인정보 보호 창을 엽니다.",
+ "bbf543a3a1": "전체 디스크 액세스",
+ "7f145a3984": "창문",
+ "5610022e1e": "오토메이션",
+ "0a467b750e": "스크린샷",
+ "08f8039ca9": "접근성",
+ "3cd51d18a1": "화면 녹화",
+ "2e5d98ab56": "스크린샷, 화면 검사, 키 입력 및 창 자동화를 허용합니다.",
+ "39bb49e662": "화면 녹화 및 접근성",
+ "00e954319e": "속삭임",
+ "1e6e27b202": "ffmpeg",
+ "f061f08b7b": "삭스",
+ "a765112513": "동영상",
+ "b192432ef0": "오디오",
+ "af122938a3": "음성",
+ "259b829b84": "카메라",
+ "ed7c12bdb4": "마이크로폰",
+ "6eca1636b7": "음성, 전사, 웹캠 및 미디어 캡처 도구를 허용합니다.",
+ "302c0c42f9": "마이크 및 카메라",
+ "4e225e7c56": "개발자 도구",
+ "6db4fca386": "마코스",
+ "0c13b249e3": "tcc",
+ "2270ccff3f": "은둔",
+ "a98aa11a9c": "권한",
+ "bc8ac95310": "터미널에서 실행되는 개발자 도구에 대한 macOS 권한입니다.",
+ "e92cb0896d": "개발자 권한"
+ }
+ }
+ },
+ "experimental": {
+ "search": {
+ "44c7f209d5": "node_modules",
+ "4ad605f222": "환경",
+ "3021571c30": "공유됨",
+ "f082788cfe": "모래밭",
+ "3028f0bd3a": "링크",
+ "bff1ff7768": "심볼릭 링크",
+ "c387565812": "심볼릭 링크",
+ "10b52f79c1": "작업 트리",
+ "d23ae13990": "작업 트리",
+ "0d24759f14": "실험적인",
+ "603d29ed74": "구성된 파일 또는 폴더를 새로 생성된 작업 트리에 자동으로 심볼릭 링크하여 공유 상태(env, 캐시, 설치)가 연결된 상태를 유지합니다.",
+ "78c2a8dc74": "작업 트리의 심볼릭 링크",
+ "7b79081695": "읽히지 않는",
+ "f10d307468": "완성",
+ "5f067ba0f9": "에이전트",
+ "7695fd30e9": "공고",
+ "8facf10138": "벨",
+ "edc49480a1": "창유리",
+ "268e99d957": "가장 밝은 부분",
+ "01567f19ca": "주목",
+ "9bb3bd5098": "터미널",
+ "11877246fc": "터미널 벨 및 에이전트 완료 이벤트에 대한 지속적인 패널 강조 표시입니다.",
+ "9e4ddf776d": "터미널 주의",
+ "fe5688b761": "사이드바",
+ "ca5d1f3f46": "타임라인",
+ "d01b3882ba": "알림",
+ "244a0ecd3d": "활동",
+ "92a9357d1f": "에이전트 보기",
+ "fa72e71f05": "에이전트",
+ "4d63251595": "에이전트 완료 및 차단 상태에 대한 스레드 왼쪽 사이드바 피드입니다.",
+ "ccc5548ac5": "에이전트 보기",
+ "9af7a518db": "성격",
+ "791fefc0b0": "모서리",
+ "65df471ab2": "생기 있는",
+ "9f5609bfb8": "씌우다",
+ "2a33975d72": "마스코트",
+ "b54cea709b": "친구",
+ "051203d37c": "애완 동물",
+ "6b5a56ac35": "오른쪽 하단에 떠 있는 애니메이션 애완동물.",
+ "87d99e634b": "애완 동물"
+ }
+ },
+ "floating": {
+ "workspace": {
+ "search": {
+ "94f4d013c8": "상태 표시줄",
+ "a452146574": "토글 버튼",
+ "6765b85e48": "실행 디렉토리",
+ "a38bfc3f77": "퀵 패널",
+ "52db6e3baf": "메모",
+ "156ffeee08": "메모",
+ "884e5e6132": "가격 인하",
+ "49db74a92d": "브라우저",
+ "6410fe83d8": "터미널",
+ "2b5efa55c9": "글로벌",
+ "ebeedb2f6a": "빠른 터미널",
+ "6f183fa1b9": "플로팅 터미널",
+ "a08e482f6d": "플로팅 워크스페이스",
+ "b96b5ee6cf": "플로팅 워크스페이스를 활성화하고, 새 탭이 시작되는 위치를 선택하고, 토글 버튼이 나타나는 위치를 선택하세요.",
+ "b2b60e7163": "플로팅 워크스페이스"
+ }
+ }
+ },
+ "general": {
+ "search": {
+ "bdfb6dc21b": "좋다",
+ "e6b01c8e30": "피드백",
+ "b65665703a": "지원",
+ "06ea5a69a6": "GitHub",
+ "e4fb4516d0": "별",
+ "e0b8c8bc25": "gh CLI를 통해 GitHub 스타로 프로젝트를 지원하세요.",
+ "36a72f0d9e": "GitHub의 스타 Orca",
+ "c61b14be7c": "그로크",
+ "5d9ba08673": "부조종사",
+ "f472e97440": "보조원",
+ "3c30fe2d51": "gemini",
+ "5fdf1dc2d1": "펌프",
+ "9b0bc30160": "파이",
+ "882c4896fd": "opencode",
+ "27d9b996ba": "codex",
+ "5baf51c4d9": "open claude",
+ "aea7d2cccb": "개방형",
+ "95b63edde7": "claude",
+ "41c2f9a025": "기본값",
+ "8ea37a05bc": "에이전트",
+ "e2da948f59": "새 워크스페이스 작성기에서 AI 코딩 에이전트를 미리 선택하세요.",
+ "db11502270": "기본 에이전트",
+ "3462308bd3": "토큰",
+ "660528b048": "비용",
+ "585beac3f8": "ttl",
+ "0efc9d96ad": "프롬프트",
+ "939b80f5fd": "타이머",
+ "b2601a778c": "캐시",
+ "40c9585e43": "프롬프트 캐시가 만료될 때까지의 시간을 표시하는 카운트다운 타이머(Claude 에이전트)",
+ "1e0f28c6f1": "프롬프트 캐시 타이머",
+ "e49e739a59": "다운로드",
+ "c9d8c1ce66": "릴리스 노트",
+ "9e86ccd05c": "버전",
+ "f89a94773c": "업데이트",
+ "79ff46776e": "앱 업데이트를 확인하고 최신 Orca 버전을 설치하세요.",
+ "e15af4eb64": "업데이트 확인",
+ "6382fe9724": "npx",
+ "baa263d6d8": "에이전트",
+ "bda108e66c": "스킬",
+ "244e3fb4c8": "에이전트가 Orca CLI를 사용하도록 Orca 스킬을 설치하세요.",
+ "2d9f7b42df": "에이전트 스킬",
+ "0a00691c06": "셸 명령",
+ "dbeb1f348e": "명령",
+ "88d3df9ce9": "터미널",
+ "fb4f338a3d": "경로",
+ "924a660a78": "CLI",
+ "ca529079bf": "Orca CLI 명령을 등록하거나 제거합니다.",
+ "327e3fa70d": "Orca CLI",
+ "fb84767421": "스위치",
+ "f8f0ac213a": "잇달아 일어나는",
+ "12ecc640a8": "므루",
+ "54ba13831a": "최근의",
+ "750420dd9a": "제어",
+ "fe62b3f09f": "Ctrl 키",
+ "2a254b725e": "탭",
+ "ca812803ea": "최근 탭 순서",
+ "e53d585ed6": "최근 또는 탭 표시줄.",
+ "256d92554d": "탭 순서",
+ "22572e99c1": "주석",
+ "1ff67ba40c": "메모",
+ "4dd5684836": "리뷰",
+ "d05f629d2c": "가격 인하",
+ "694613d47f": "리치 에디터 모드에서 로컬 마크다운 리뷰 노트 컨트롤을 표시합니다.",
+ "128bc09325": "마크다운 리뷰 노트",
+ "a0014961ae": "스크롤",
+ "3ca5ab78a5": "암호",
+ "e3919429c0": "개요",
+ "9c72990db8": "미니맵",
+ "716a4dfb1f": "파일을 편집할 때 미니맵 개요를 표시합니다.",
+ "6f584fcb48": "미니맵",
+ "19baae651b": "사이드바",
+ "973ed6bfbf": "결합된 차이",
+ "0a02059549": "파일 트리",
+ "2f42852568": "나무",
+ "3b5733573e": "차이점",
+ "dec71988f0": "결합된 차이점 보기를 열 때 파일 트리를 표시하거나 숨깁니다.",
+ "adec13f2ef": "기본 Diff 파일 트리",
+ "be24c7cd67": "분할",
+ "233f7e2f37": "나란히",
+ "0a5fa65926": "인라인",
+ "2b463f0bf9": "보기",
+ "ecb9415c80": "기본적으로 git diff를 표시하기 위해 선호되는 프레젠테이션 형식입니다.",
+ "2760c9933f": "기본 차이점 보기",
+ "b2799ba622": "밀리초",
+ "146728ac2c": "지연",
+ "86f54575c7": "자동 저장",
+ "8ea61ad55c": "Orca가 마지막 편집 후 자동으로 저장되기까지 기다리는 시간입니다.",
+ "14e46c745b": "자동 저장 지연",
+ "4469b6fa4e": "저장",
+ "e9d948d3c3": "잠시 후에 편집기 및 편집 가능한 diff 변경 사항을 자동으로 저장합니다.",
+ "ae21e806ce": "자동 저장 파일",
+ "c56cb6f1c2": "회로망",
+ "3566fce83f": "로컬호스트",
+ "91a46caafc": "no_proxy",
+ "3a73054565": "우회로",
+ "20b711ac9e": "프록시",
+ "eb8946b2c9": "구성된 HTTP 프록시를 우회해야 하는 호스트입니다.",
+ "8436ff6f8e": "프록시 우회 규칙",
+ "e55d62dfa4": "발사대",
+ "9da6c875e5": "독",
+ "b9096a44cf": "https_proxy",
+ "8f03d44672": "http_proxy",
+ "e3b1d42f95": "Orca 네트워크 요청 및 로컬 터미널 하위 항목에 대한 프록시 URL입니다.",
+ "c29f23ab57": "HTTP 프록시",
+ "6c2ce8457c": "파일 탐색기",
+ "c9d9636f24": "파인더",
+ "68d03d9980": "vscode",
+ "ebf8f056b5": "제드 자의 명칭",
+ "0cb3d94f00": "cursor",
+ "8fb00fcd05": "발사통",
+ "e1ee631696": "편집자",
+ "5a9df5566f": "메뉴 열기",
+ "b8093e9a93": "열기",
+ "a916662068": "워크스페이스의 열기 메뉴에서 사용 가능한 앱을 선택하세요.",
+ "451d4af994": "앱에서 열기",
+ "7e9b556873": "건너뛰다",
+ "ca86dd6e27": "대화",
+ "9f8558233a": "확인",
+ "7edf4f69e2": "오토메이션",
+ "84c67d0108": "삭제",
+ "a0c44061ee": "자동화 및 실행 기록을 삭제하기 전에 확인 대화 상자를 표시합니다.",
+ "d0a65b27fd": "자동화를 삭제하기 전에 확인하세요",
+ "df10666259": "작업 트리",
+ "ae98c9cf36": "워크스페이스를 삭제하기 전에 확인 대화상자를 표시합니다.",
+ "913242091d": "워크스페이스를 삭제하기 전에 확인",
+ "93f6ec5e70": "예배 규칙서",
+ "9bde064915": "하위 폴더",
+ "ec5049e510": "중첩된",
+ "b9cffd374d": "저장소 이름이 지정된 하위 폴더 내에 워크스페이스를 만듭니다.",
+ "141f71c69f": "네스트 워크스페이스",
+ "7887a2c262": "폴더",
+ "7baf524b04": "워크스페이스",
+ "d0bc793689": "워크스페이스 폴더가 생성되는 루트 디렉터리입니다.",
+ "4c95d08fa2": "워크스페이스 디렉토리"
+ }
+ },
+ "git": {
+ "search": {
+ "61eab13403": "orca",
+ "1b93c1143c": "속성",
+ "8461c908ae": "공동 집필",
+ "61f9f5d1fc": "공저자",
+ "af0a144bfb": "이슈",
+ "6bdea421bb": "PR",
+ "16f53f7323": "gh",
+ "d088806071": "GitHub",
+ "118c23484b": "커밋, PR 및 이슈에 Orca 속성을 추가합니다.",
+ "bc7d9f69ce": "Orca 속성",
+ "40f9b815fd": "API 예산",
+ "b7e52124c7": "비율 제한",
+ "ead733645f": "glab",
+ "4808f065b3": "gitlab",
+ "2b4a72885d": "사용 가능한 경우 현재 GitLab CLI REST 속도 제한 헤더입니다.",
+ "83ecb3f470": "GitLab API 예산",
+ "65b69d9f80": "그래프",
+ "1139f61512": "현재 GitHub CLI REST, 검색 및 GraphQL 속도 제한.",
+ "ff86e354c4": "GitHub API 예산",
+ "035134fcd9": "작업 트리",
+ "0c75583ca9": "안전하게",
+ "bae91effdd": "신선한 베이스",
+ "de06e9d105": "기본 참조",
+ "ab0e22c9f6": "로컬 메인 새로 고침",
+ "d9f70d51a0": "오래된 메인",
+ "0849b571fe": "최신",
+ "c41e345153": "메인 뒤에",
+ "6ee3cfff02": "자식 비교",
+ "564942ffc5": "원산지/주요",
+ "28192e3a63": "주인",
+ "e3e9adde59": "기본",
+ "0e993bf00f": "워크스페이스를 생성하면 Orca는 원격 기반을 새로고침하고 기본 또는 마스터와 같은 일치하는 로컬 브랜치를 안전하게 빨리 감습니다. 이렇게 하면 git diff main...HEAD와 같은 명령이 오래된 기록과 비교되지 않습니다. Orca는 해당 브랜치에 커밋되지 않은 변경 사항이나 로컬 전용 커밋이 있는 경우 업데이트를 건너뜁니다.",
+ "f8bda25f29": "로컬 메인을 최신 상태로 유지",
+ "769ddd7f81": "custom",
+ "1d2fae1fa2": "자식 사용자 이름",
+ "f83c8937c4": "브랜치 이름 지정",
+ "5ecd91c5ef": "작업 트리를 생성할 때 브랜치 이름에 접두사가 추가됩니다.",
+ "68bd65fdb8": "브랜치 접두사"
+ }
+ },
+ "input": {
+ "search": {
+ "886597d6b3": "마코스",
+ "26c83b06c5": "리눅스",
+ "71905435dd": "x11",
+ "7059cfb00a": "클립보드",
+ "c4440c3986": "반죽",
+ "5fb84ba77f": "가운데 마우스",
+ "31ba58c8ae": "가운데 클릭",
+ "de51e18ee9": "기본 선택",
+ "e5cd0e7a46": "선택",
+ "e25165320e": "편집",
+ "b51d47ceb7": "입력",
+ "874d88f4a6": "Linux 및 macOS에서는 기본적으로 활성화되어 있습니다. Linux는 시스템 선택 클립보드를 사용합니다. 다른 플랫폼은 개인 버퍼를 사용합니다.",
+ "d952ce9b46": "선택 항목에서 붙여넣기를 마우스 가운데 버튼으로 클릭"
+ }
+ },
+ "integrations": {
+ "search": {
+ "a626990bd2": "연결 해제",
+ "3c3d3d8ffa": "연결",
+ "faa0b5a0d9": "API 키",
+ "c450244ad7": "연동",
+ "7319e3015b": "Linear",
+ "16a486a49d": "Linear에 연결해 이슈를 탐색하고 연결합니다.",
+ "b027b4b318": "Linear 연동",
+ "20540996ef": "자격 증명",
+ "2ec2bd328c": "API 토큰",
+ "7345b7c3e6": "Atlassian",
+ "e1263dd748": "Jira",
+ "76f6af7c57": "Jira Cloud를 연결하거나 Jira API 토큰 자격 증명을 업데이트하세요.",
+ "617603509b": "Jira 연동",
+ "8c568d761c": "PR",
+ "33180e8c10": "자체 호스팅",
+ "129fc59aa8": "Gitea",
+ "d0d019dc29": "API 토큰 환경 변수를 통한 Gitea 인증.",
+ "aab86d64e5": "Gitea 연동",
+ "03a7b275be": "ADO",
+ "ed63380247": "Azure Repos",
+ "b38b5d27f1": "Azure DevOps",
+ "7b1f3984bb": "토큰 환경 변수를 통한 Azure DevOps Repos 인증.",
+ "af6611fa6e": "Azure DevOps 연동",
+ "50d20817f7": "Bitbucket",
+ "c97d58a0f3": "API 토큰 환경 변수를 통한 Bitbucket Cloud 인증.",
+ "67a2a0e868": "Bitbucket 연동",
+ "371ee914d2": "MR",
+ "581844769a": "MR",
+ "b40cbe5de4": "glab",
+ "b939695c69": "gitlab",
+ "6e2ab619c6": "glab CLI를 통한 GitLab 인증.",
+ "b50b71ef9d": "GitLab 연동",
+ "41ccade05c": "gh",
+ "b79c21bd42": "GitHub",
+ "7166b9090c": "gh CLI를 통한 GitHub 인증.",
+ "f16e41cc72": "GitHub 연동"
+ }
+ },
+ "jira": {
+ "integration": {
+ "card": {
+ "8ff73fef62": "Jira 토큰은 활성 런타임에 의해 암호화되어 로컬에 저장됩니다. 동일한 사이트 URL과 이메일을 다시 입력하면 해당 사이트의 API 토큰이 대체됩니다.",
+ "9046a20d4c": "{{value0}} 연결 끊기",
+ "eaffa454e9": "업데이트",
+ "cec06a0f79": "테스트 중…",
+ "ab350991b8": "확인됨",
+ "d914d7ab70": "확인 중…",
+ "5936977fcd": "취소",
+ "1666f8d562": "Atlassian API 토큰 만들기",
+ "1ab7f551f3": "Atlassian API 토큰",
+ "09d310e42d": "you@example.com",
+ "27dae4ab60": "https://example.atlassian.net",
+ "a28f417220": "Jira 연결",
+ "9bb34706ca": "연결됨",
+ "efaab83c5d": "사이트 추가",
+ "09742875cd": "Jira",
+ "255bfe98ec": "시험",
+ "5fb1562315": "오류",
+ "3df81cb0ac": "좋아요",
+ "2e8bb790fd": "연결",
+ "33a8b261ee": "자격 증명 업데이트",
+ "d5c5b47bb9": "업데이트",
+ "fb854902d9": "연결",
+ "9a9f8d4910": "Jira Cloud를 연결하여 이슈를 찾아보고 생성하고 연결하세요.",
+ "74f3063026": "{{value0}} 사이트{{value1}}이(가) 연결되었습니다."
+ }
+ }
+ },
+ "mobile": {
+ "emulator": {
+ "search": {
+ "2348045036": "Orca가 기본적으로 여는 에뮬레이터 장치를 선택합니다.",
+ "2bb2e09225": "모바일 스킬",
+ "bbe4267416": "에뮬레이터 유형",
+ "64494f03c3": "에뮬레이터 연결",
+ "6f728f1456": "에뮬레이터 탭",
+ "f8b871d655": "에이전트 CLI",
+ "2e0b45b2ba": "Orca CLI 명령을 사용하여 모바일 에뮬레이터를 나열하고, 연결하고, 탭하고, 입력하세요.",
+ "ea3eac39bb": "에이전트 CLI 제어",
+ "8ef0f08d36": "실행 시간",
+ "27397fe8e9": "xcode 명령줄 도구",
+ "7650063d17": "simctl",
+ "3211e7acf9": "엑스크런",
+ "42bfab45d8": "유효성",
+ "ea1f51b980": "Xcode, simctl, Serve-sim 및 에뮬레이터 장치가 준비되었는지 확인하세요.",
+ "0b95dfd5b3": "에뮬레이터 가용성",
+ "04c5f5d901": "장치",
+ "25d7bfbcd4": "유디드",
+ "ec3c4043fd": "기본 아이패드",
+ "1dc8c52ffa": "기본 아이폰",
+ "ab4814f3c5": "기본 시뮬레이터",
+ "54184cb9c5": "기본 에뮬레이터 장치",
+ "b8ddd13195": "에이전트 에뮬레이터",
+ "1ad6fb6230": "기본 장치",
+ "ac0a985873": "에뮬레이터 스킬",
+ "9353854ff3": "orca emulator",
+ "d4b7833894": "오카 클라이",
+ "84e5706975": "서브심",
+ "7c5a8a2bee": "엑스코드",
+ "bec7231663": "아이패드",
+ "49727355a3": "아이폰",
+ "6b6407dc1f": "에뮬레이터",
+ "2d67f708ce": "시뮬레이터",
+ "c5eca29310": "iOS 시뮬레이터",
+ "25159de808": "모바일 에뮬레이터",
+ "9595354cff": "Orca 및 코딩 에이전트에 대한 모바일 에뮬레이터 지원을 구성합니다.",
+ "cdd3c31918": "모바일 에뮬레이터"
+ }
+ },
+ "pane": {
+ "search": {
+ "dbccde3a60": "닫기",
+ "9e16be01d6": "배경",
+ "3a5e31e84b": "떠나다",
+ "8015fd9523": "잡고 있다",
+ "aa3f736042": "크기 조정",
+ "356c31d6dc": "너비",
+ "fadcbfdd99": "맞다",
+ "ad08035c5f": "핸드폰",
+ "6cd2bfdb0e": "복원",
+ "b34ad5b3a7": "터미널",
+ "6db86f445f": "모바일",
+ "707fc78052": "앱을 닫거나 다른 곳으로 전환한 후 모바일에서 보고 있던 터미널에 어떤 일이 발생하는지 선택하세요.",
+ "1e711aca11": "모바일 앱을 나갈 때",
+ "126afc5dbd": "원격",
+ "70f505f3c3": "란",
+ "1802188b5d": "와이파이",
+ "dd6e671aa9": "주소",
+ "1f70d63998": "아이피",
+ "d0c89bc4a9": "씌우다",
+ "87711f4b8f": "VPN",
+ "16bff559a0": "테일넷",
+ "c690e3ee38": "테일스케일",
+ "a023683767": "인터페이스",
+ "7b37c2e557": "회로망",
+ "3190ef67a4": "모바일 페어링에 사용할 네트워크 주소를 선택하세요.",
+ "d96c315227": "네트워크 인터페이스",
+ "7d01f93ec0": "연결됨",
+ "5e8fda4d7f": "짝을 이루는",
+ "905c65a308": "취소",
+ "82783d9b71": "장치",
+ "13419718b3": "페어링된 모바일 장치를 관리합니다.",
+ "9d3a9397ba": "연결된 장치",
+ "2128a21096": "주사",
+ "e518cbd61c": "쌍",
+ "4a0c826f3d": "암호",
+ "3c1807a81a": "qr",
+ "7fb728fb2b": "QR 코드를 스캔하여 모바일 장치를 페어링하세요.",
+ "d49925710a": "모바일 페어링"
+ }
+ },
+ "settings": {
+ "search": {
+ "b730ff7049": "실험적인",
+ "8d4ba0ef09": "베타",
+ "6bfa001752": "APK",
+ "a7eececc1d": "기계적 인조 인간",
+ "7e801801ac": "원격",
+ "0b7e585cb9": "주사",
+ "59b1d75fd1": "암호",
+ "87816d1c59": "qr",
+ "cf2c93b479": "쌍",
+ "f4ed142753": "핸드폰",
+ "f213400800": "모바일",
+ "671eb4173c": "휴대폰에서 터미널과 에이전트를 제어하세요.",
+ "ffd52a96e4": "모바일"
+ }
+ }
+ },
+ "notifications": {
+ "search": {
+ "aa288005c3": "시험",
+ "ca8faa40d7": "알림",
+ "4e30b1925e": "기본 전달 경로를 사용하여 샘플 데스크톱 알림을 트리거합니다.",
+ "ef9b311346": "테스트 알림 보내기",
+ "ecdeff4993": "큰 소리",
+ "d58b64dddf": "용량",
+ "dc7d7c07cd": "소리",
+ "eeb6f77322": "비시스템 알림 소리의 재생 볼륨입니다.",
+ "aace1a62c6": "알림 볼륨",
+ "ef86a782cc": "봉",
+ "3014ad1b8f": "땡땡",
+ "079c29aeb5": "flac",
+ "722face52f": "aac",
+ "6ecb8418cb": "m4a",
+ "d16ae23645": "에그",
+ "57e34a31cd": "웨이브",
+ "5362074f19": "mp3",
+ "6e08f78315": "오디오",
+ "c718793e95": "Orca가 데스크톱 알림을 위해 재생하는 내장, 시스템 또는 로컬 오디오 파일을 선택합니다.",
+ "ea8cb8d9ce": "알림음",
+ "4ada6bfde9": "필터링",
+ "fa60d8e4ab": "막다",
+ "a4c3b29a3c": "집중된",
+ "7247b97a31": "Orca가 활성 작업 트리에 집중할 때 알림을 보내지 마세요.",
+ "96562a72c6": "집중하는 동안 억제",
+ "a2ab73b325": "주목",
+ "ae0487f8fd": "벨",
+ "c638ae989d": "터미널",
+ "d3f1c48677": "백그라운드 터미널이 벨 문자를 내보낼 때 이를 알립니다.",
+ "a5edee1d99": "터미널 벨",
+ "193e1f107c": "작업",
+ "dd9d3e5f0f": "idle",
+ "5f7472d3fb": "완벽한",
+ "7fa07e9600": "에이전트",
+ "10d83ef8dc": "코딩 에이전트가 작업 중에서 유휴 상태로 전환되면 알립니다.",
+ "bdc1edaeb4": "에이전트 작업 완료",
+ "adbc3a0fcf": "토종의",
+ "72539aede4": "체계",
+ "51ae2183e1": "데스크탑",
+ "0534c76311": "Orca 데스크톱 알림용 마스터 스위치입니다.",
+ "4a210b2f72": "알림 활성화"
+ }
+ },
+ "orchestration": {
+ "search": {
+ "f5d39af41e": "하위 에이전트",
+ "c766a01978": "핸드오프",
+ "08c65b12a2": "예시",
+ "f278fd04db": "codex",
+ "32c5098e7b": "claude",
+ "21c28ccdf7": "코디네이터",
+ "741dfc03fa": "워커",
+ "ca54c69806": "DAG",
+ "7ad948b714": "작업",
+ "eee028ae14": "디스패치",
+ "9a5ebdca31": "메시징",
+ "91fc8ab7e5": "코디네이션",
+ "13ba5c6cbd": "에이전트",
+ "d86705ba77": "멀티 에이전트",
+ "a7f76b4ca7": "오케스트레이션",
+ "e05ff36753": "메시징, 작업 DAG, 디스패치 및 결정 게이트를 통해 여러 코딩 에이전트를 조정합니다.",
+ "c34045764e": "에이전트 오케스트레이션"
+ }
+ },
+ "privacy": {
+ "search": {
+ "3922051573": "데이터",
+ "e8bc614a18": "비활성화",
+ "d8191ae5ca": "환경 변수",
+ "94e04427f6": "환경",
+ "664f1a8984": "지속적인 통합",
+ "5854a5c752": "ci",
+ "69637f4dc4": "orca_telemetry_disabled",
+ "058550f6bc": "do_not_track",
+ "83a6cd79b3": "추적하지 마세요",
+ "f7a2d9f137": "텔레메트리 전송을 비활성화하는 환경 변수입니다.",
+ "e058a3c98d": "텔레메트리 환경 변수",
+ "1686c07fee": "지원",
+ "4a583f3a2f": "개방형 텔레메트리",
+ "9ea93ce3d6": "otlp",
+ "685c68a81f": "로그",
+ "40de3c2f19": "추적",
+ "c0494ff48a": "진단",
+ "8b08f32366": "추적 파일 및 OTLP 내보내기 제어.",
+ "6d258d2ed6": "진단",
+ "ead1deded2": "공유",
+ "27a27b2f63": "탈퇴",
+ "4d4bb76bf4": "선택",
+ "b021b9cb81": "익명의",
+ "79c319948b": "용법",
+ "77d3180def": "텔레메트리",
+ "b707cc3981": "익명의 기능 사용 이벤트를 보내 Orca 개선에 도움을 주세요.",
+ "57b283461a": "익명의 사용 데이터 공유",
+ "2b5a5c312f": "포스트호그",
+ "4104f6f0f3": "해석학",
+ "10124159f1": "은둔",
+ "aa3b794c17": "익명의 제품 사용 데이터, 진단 및 텔레메트리 제어.",
+ "5c508bad41": "개인정보 및 텔레메트리"
+ }
+ },
+ "quick": {
+ "commands": {
+ "search": {
+ "3c316e6ef8": "방사",
+ "b86c727100": "npm",
+ "b949a7c0a0": "pnpm",
+ "0b78c4a165": "실행",
+ "2d8aff42be": "달리다",
+ "1c5bdcd0f2": "저장소",
+ "89d2a9ad9f": "레포",
+ "f58b92a48f": "프로젝트",
+ "8bf43c2dad": "글로벌",
+ "a26ecdb77b": "단편",
+ "d07d130849": "지름길",
+ "0073cf8ce9": "터미널",
+ "cfffa6cdb6": "명령",
+ "fecb031823": "명령",
+ "236d4cfac8": "빠른",
+ "d691c4e8d8": "전역적으로 또는 특정 프로젝트로 범위가 지정된 모든 터미널에서 실행할 수 있는 저장된 터미널 명령입니다.",
+ "4c8945952b": "빠른 명령어"
+ }
+ }
+ },
+ "repository": {
+ "search": {
+ "bc7e504b8e": ".orca/issue-command",
+ "603c68b68c": "orca.yaml",
+ "9dc60d7f6d": "GitHub",
+ "ec70364df2": "작업 흐름",
+ "66b584bd6c": "명령을 내리다",
+ "2011a6a4f2": "github 발행 명령",
+ "d42d1e49c0": "orca.yaml 및 선택적 로컬 재정의를 통해 구성된 파일 기반 링크 실행 명령입니다.",
+ "d86ea12d16": "사용자 정의 GitHub 이슈 명령",
+ "c5e8bdbcbb": "기본적으로 건너뛰기",
+ "a69c5cbe90": "기본적으로 실행",
+ "80c490b012": "묻다",
+ "f9d84b7971": "실행 정책 설정",
+ "c00a549e03": "설정 스크립트를 사용할 수 있는 경우 기본 동작을 선택합니다.",
+ "cdfe398068": "설치 실행 시기",
+ "5e9445bbfd": "권위 있는",
+ "f1e1bfa89f": "원천",
+ "1d90a6cfbb": "둘 다",
+ "fcb8fa8144": "공유됨",
+ "0432d2fb7c": "현지의",
+ "ed269fad69": "명령 소스",
+ "19f58d6d89": "고급의",
+ "d141897c90": "명령 소스 및 orca.yaml 세부정보",
+ "cc11699c3d": "고급",
+ "bf460fded8": "YAML",
+ "9cad92fe77": "orca.yaml 후크",
+ "6b80f7d3c8": "로컬 설정 스크립트",
+ "a1a4c51d58": "아카이브 명령",
+ "fbfd2386e8": "아카이브 스크립트",
+ "4c17787d7b": "보관소",
+ "8655e3387b": "훅",
+ "acd1157f0c": "작업 트리가 보관되기 전에 실행되는 로컬 및 공유 스크립트입니다.",
+ "bce0ca23c6": "아카이브 스크립트",
+ "491b05d6e6": "설정 명령",
+ "a31b43a7f8": "설정 스크립트",
+ "5590388dfa": "설정",
+ "baaf70bb37": "새 작업 트리가 생성된 후 실행되는 로컬 및 공유 스크립트입니다.",
+ "b79df26937": "설정 스크립트",
+ "d73fb47b45": ".claude/mcp.json",
+ "db11b337c4": ".claude.json",
+ "26f42fe773": ".cursor/mcp.json",
+ "e760e3fae7": ".mcp.json",
+ "16dc7a4637": "모델 컨텍스트 프로토콜",
+ "343f0a508c": "mcp",
+ "3c31801626": "프로젝트 수준 MCP 서버 구성 파일을 검사합니다.",
+ "31bd0a2420": "MCP 구성",
+ "84da7fa2d7": "node_modules",
+ "0a3a582794": "환경",
+ "3c180a251c": "링크",
+ "f1c53f2820": "작업 트리",
+ "7e228fc439": "심볼릭 링크",
+ "c06adcf136": "심볼릭 링크",
+ "ed885e589f": "기본 체크아웃에서 새로 생성된 작업 트리로의 심볼릭 링크 경로입니다.",
+ "01b3377ebc": "작업 트리 심볼릭 링크",
+ "fff8834983": "프롬프트",
+ "fa3131f223": "모델",
+ "130d76dc16": "이름 변경",
+ "917dce844a": "브랜치 이름",
+ "8068d8d0f1": "PR",
+ "5ff7fe1ade": "PR",
+ "eec39b3de6": "커밋 메시지",
+ "cfad7ce5f3": "일체 포함",
+ "a47f51127e": "소스 제어",
+ "6cc5c65e64": "프로젝트별 Git 생성이 재정의됩니다.",
+ "eec3995dc6": "Git AI Author",
+ "cc876ca5f2": "저장소",
+ "6469de5368": "프로젝트",
+ "3067595d82": "삭제",
+ "c86478c3d8": "Orca에서 이 프로젝트를 제거하세요.",
+ "c5266c2c9d": "프로젝트 제거",
+ "4b9a18a56d": "모노레포",
+ "4e2529722c": "디렉토리",
+ "1ff4f12c0c": "예배 규칙서",
+ "9f5ae26ccd": "사전 설정",
+ "095fca94fe": "사전 설정",
+ "aa42616e3d": "점검",
+ "4f3c0230c2": "부족한",
+ "90a331fd68": "스파스 작업 트리 생성을 위해 저장된 디렉터리 세트입니다.",
+ "1f0f20bbb6": "스파스 체크아웃 사전 설정",
+ "4733ec2395": "../작업트리",
+ "58d8bca414": "상대적인",
+ "a325a89dff": "워크스페이스 경로",
+ "f3e6dee5fe": "작업 트리 경로",
+ "cd33a5525e": "새 작업 트리에 대한 프로젝트별 디렉터리입니다.",
+ "443d127b5a": "작업 트리 위치",
+ "9811f3d152": "브랜치",
+ "f41cef5083": "기본 참조",
+ "f571081ec4": "작업 트리를 생성할 때 기본 기본 브랜치 또는 참조입니다.",
+ "094adbe930": "기본 작업 트리 기반",
+ "27733eb6c1": "파비콘",
+ "1e73e840ff": "이모티콘",
+ "cb4b4de666": "화신",
+ "c1075178cf": "배지",
+ "6d8de2f090": "마녀",
+ "8d045419b1": "색상",
+ "b2546efab5": "저장소 아이콘",
+ "6438a94c63": "프로젝트 아이콘",
+ "a1f3a2bd47": "사이드바와 탭에 사용되는 프로젝트 아이콘과 색상입니다.",
+ "b24f00294a": "프로젝트 아이콘",
+ "cd73b976d7": "저장소 이름",
+ "92af66c7ce": "프로젝트 이름",
+ "883aad2801": "사이드바 및 탭에 대한 프로젝트별 표시 세부 정보입니다.",
+ "7e1e456a95": "표시 이름"
+ }
+ },
+ "runtime": {
+ "environments": {
+ "search": {
+ "772e3b4753": "VM",
+ "45501ff2c3": "구름",
+ "2bd988d041": "페어링 코드",
+ "5cd7dca3b8": "원격",
+ "d760866285": "고객",
+ "09568ccc65": "섬기는 사람",
+ "ebd5369acf": "환경",
+ "d198440ce3": "실행 시간",
+ "baec27aa8f": "이 브라우저를 저장된 Orca 서버에 연결하세요.",
+ "3517fb2ec0": "활성 서버",
+ "c6e5a03aa0": "개발 상자",
+ "f1575f1e09": "웹 클라이언트",
+ "81444c4102": "페어링 URL",
+ "104f4d7dbd": "편성",
+ "4575341c77": "로컬 데스크톱을 선택하고, 저장된 원격 Orca 서버를 추가하거나, 페어링 URL을 생성하세요."
+ }
+ }
+ },
+ "shortcuts": {
+ "search": {
+ "ca6a0c2df7": "지름길",
+ "4811a8264a": "터미널 우선",
+ "afda131738": "오카 먼저",
+ "0ecfc47434": "충돌",
+ "0f8cb15582": "에이전트",
+ "f1adebbe8c": "껍데기",
+ "7f1b38f59a": "투이",
+ "7e3fc707aa": "터미널",
+ "0ecba9aa5f": "건반",
+ "ebd7d81e1d": "바로가기가 겹칠 때 Orca 또는 집중된 터미널이 승리할지 선택합니다.",
+ "f052906167": "터미널의 단축키"
+ }
+ },
+ "ssh": {
+ "search": {
+ "d41f296f64": "핑",
+ "237b391f7c": "연결",
+ "8cb870b109": "시험",
+ "7efd17e816": "SSH",
+ "96ca5d9a0b": "SSH 대상에 대한 연결을 테스트합니다.",
+ "a3058f3605": "연결 테스트",
+ "2cd40ba0d0": "호스트",
+ "5220501141": "구성",
+ "3b12e064a4": "수입",
+ "7f251a45a8": "~/.ssh/config에서 호스트를 가져옵니다.",
+ "41a3127094": "SSH 구성에서 가져오기",
+ "f9493b80c0": "섬기는 사람",
+ "8fb1cc87cc": "주인",
+ "09395490af": "목표",
+ "00d1fda01a": "새로운",
+ "f7b6383aec": "추가",
+ "62826efbe9": "새로운 원격 SSH 대상을 추가합니다.",
+ "f5a691bb6c": "SSH 대상 추가",
+ "d4bcd497c7": "원격",
+ "74c6d90d78": "원격 SSH 대상을 관리합니다.",
+ "380a788da7": "SSH 연결"
+ }
+ },
+ "tasks": {
+ "search": {
+ "58cda6f9c0": "숨기기",
+ "44083ae418": "표시",
+ "604d8e4089": "Atlassian",
+ "5430396e11": "Jira",
+ "412ec3c702": "Linear",
+ "11f001cdd4": "gitlab",
+ "c10ac2125e": "GitHub",
+ "3d81c26d78": "원천",
+ "cf0e3e0c2f": "공급자",
+ "2ec54bee51": "작업",
+ "765f0c544d": "작업 페이지와 사이드바 바로가기에 표시할 작업 제공자를 선택합니다.",
+ "5b8e4aace5": "작업 제공자"
+ }
+ },
+ "terminal": {
+ "clipboard": {
+ "search": {
+ "5fb3512e8c": "반죽",
+ "a38508c419": "복사",
+ "d106f44fb4": "원격",
+ "043b32faa1": "SSH",
+ "9fda309db9": "fzf",
+ "64533e30cc": "nvim",
+ "2061d8db1a": "네오빔",
+ "5ffcd13c90": "티먹스",
+ "10d73e22d3": "클립보드",
+ "9dfc125cd3": "osc52",
+ "62d1208b90": "OSC 52",
+ "459fea094a": "SSH를 포함하여 OSC 52를 통해 터미널의 프로그램을 시스템 클립보드에 복사할 수 있습니다.",
+ "74db8721e4": "TUI 클립보드 쓰기 허용(OSC 52)",
+ "4043e294d2": "금언",
+ "cf83ac3dbd": "리눅스",
+ "737cef6de1": "x11",
+ "e87c6d776d": "오토매틱",
+ "664789b73a": "자동",
+ "c38c18be15": "선택",
+ "797fdfe4ca": "선택",
+ "603818e8d8": "터미널을 선택하자마자 자동으로 클립보드에 복사합니다.",
+ "3bdc84f059": "선택 시 복사"
+ }
+ },
+ "search": {
+ "c047f398cc": "실행",
+ "b872de3926": "위치",
+ "fd6c24313d": "새로운",
+ "f44643328e": "탭",
+ "18ce996647": "수직의",
+ "54a9b3725b": "수평의",
+ "de7bc1d5f5": "분할",
+ "7a48c7715b": "워크스페이스",
+ "6b659fff2a": "스크립트",
+ "4529806908": "설정",
+ "2610ee3b56": "새 워크스페이스가 생성될 때 저장소 설정 스크립트가 실행되는 위치: 수직 분할(기본값), 수평 분할 또는 '설정'이라는 제목의 배경 탭.",
+ "5be2d67678": "설정 스크립트 위치",
+ "0ce176909a": "테마",
+ "4ba8623632": "팔레트",
+ "11fd3fbcf2": "안시",
+ "d8bd6182b8": "재정의",
+ "674b7c8436": "색상",
+ "3023e01415": "개별 터미널 색상을 재정의합니다.",
+ "aed2a4b4eb": "색상 재정의",
+ "6eaf7ee0e4": "커서",
+ "34fe1af39d": "타자",
+ "ee611ae238": "숨기기",
+ "ea364ce6e4": "생쥐",
+ "77201c0bb2": "터미널에 입력할 때 마우스 커서를 숨깁니다.",
+ "d1fe5f99ff": "입력하는 동안 마우스 숨기기",
+ "f25d948664": "여유",
+ "b2f52cb96c": "간격",
+ "e8baf0d12c": "심",
+ "4655567c37": "터미널 그리드 주변의 수직 패딩(픽셀)입니다.",
+ "692c4ad032": "수직 패딩",
+ "75691e4911": "터미널 그리드 주변의 수평 패딩(픽셀)입니다.",
+ "b4f182f24d": "수평 패딩",
+ "6c2f9f05c8": "활기",
+ "4f7f8f28ca": "투명도",
+ "f6dd9ff606": "배경",
+ "71eb45e293": "흐림",
+ "0838b3717b": "창문",
+ "bc2054657a": "터미널 창에 배경 흐림을 적용합니다. 다시 시작해야 합니다.",
+ "72d0482137": "창 흐림",
+ "7db59c4738": "알파",
+ "46d99ef4bb": "불투명",
+ "4c643695aa": "터미널 배경의 투명도를 제어합니다.",
+ "b36fd2416d": "배경 불투명도",
+ "d4daf4f612": "녹이다",
+ "88561b3499": "언",
+ "0a05629060": "다시 덮다",
+ "f66a7cf715": "터미널",
+ "6892fb1019": "다시 시작",
+ "cde233f5da": "스크롤백",
+ "3982d88725": "역사",
+ "456da64d4d": "지우기",
+ "920573d65b": "모두 종료",
+ "a3e5297c10": "죽이다",
+ "a8d2784214": "관리",
+ "d802a578bf": "세션",
+ "9f2dda133c": "피티",
+ "f35400f7e8": "악마",
+ "f72abc493c": "세션을 종료하거나, 저장된 스크롤백을 지우거나, 데몬을 다시 시작하여 정지된 터미널을 복구하세요.",
+ "6f5d486a68": "세션 관리",
+ "10f9fb6fea": "설정",
+ "2ade3ea490": "구성",
+ "fd752b3cac": "수입",
+ "82b63d07fe": "유령같은",
+ "73e9422f19": "지원되는 Ghostty 터미널 설정을 한 번만 가져옵니다.",
+ "a979df0083": "Ghostty에서 가져오기",
+ "4cec42dbf7": "국제",
+ "b495dc6a9f": "지스",
+ "d8d6f7a3c5": "마코스",
+ "1ab57a0fbd": "스코틀랜드 사람",
+ "abaa24752d": "건반",
+ "24f7977756": "일본어",
+ "98059d0944": "백슬래시",
+ "9c35f56625": "엔",
+ "063914c486": "JIS 엔(\\) 키를 눌렀을 때 백슬래시(\\)를 대신 보낼지 여부를 제어합니다.",
+ "694b8764ac": "JIS 엔(¥)을(를) 백슬래시(\\)로 변환",
+ "fae142a354": "읽어보기",
+ "b3b94cfcb5": "국제적인",
+ "dd4f6cb541": "독일 사람",
+ "983d45cf4c": "작성",
+ "7ace5beec9": "메타",
+ "38f1b4f4cb": "열쇠",
+ "c4427dc5ff": "대체",
+ "b37edfc65a": "옵션",
+ "1f8b00f5ce": "macOS Option 키가 Alt/Esc 시퀀스를 보내거나 문자를 구성하는지 여부를 제어합니다. Ghostty의 macos-option-as-alt를 미러링합니다.",
+ "9bd7229927": "Alt로서의 옵션",
+ "affb14efd4": "선택",
+ "d2a366c7f9": "두 번 클릭",
+ "4ed3e239a8": "경계",
+ "d4aeafac10": "분리 기호",
+ "7286cd2566": "단어",
+ "3ab64c47d8": "두 번 클릭 선택 시 단어 경계로 처리되는 문자입니다.",
+ "957a0203fc": "단어 구분 기호",
+ "56fff3d113": "메모리",
+ "fffdff40a7": "완충기",
+ "f7d56b6281": "최대 터미널 스크롤백 버퍼 크기.",
+ "7674e758e1": "스크롤백 크기",
+ "411229c636": "라이트",
+ "781f49d942": "분할기",
+ "77d9f9cd55": "조명 모드에서 창 사이의 분할 구분선을 제어합니다.",
+ "595b97b446": "라이트 디바이더 색상",
+ "7718d70356": "시사",
+ "1dee533bd9": "Orca가 조명 모드에 있을 때 사용되는 테마를 선택합니다.",
+ "1d89457764": "라이트 테마",
+ "da864e6cec": "조명 모드",
+ "f268092ee3": "비활성화되면 라이트 모드는 어두운 터미널 테마를 재사용합니다.",
+ "232e532169": "조명 모드에서 별도의 테마 사용",
+ "f785374072": "다크",
+ "9c32726f47": "어두운 모드에서 창 사이의 분할 구분선을 제어합니다.",
+ "8987db7ff2": "다크 디바이더 색상",
+ "13f6310dd3": "다크 모드에서 사용되는 터미널 테마를 선택하세요.",
+ "ec07ce9b02": "어두운 테마",
+ "f036794286": "활동적인",
+ "846a7a1204": "창유리",
+ "d1fa00a9cb": "호버링",
+ "b5116e7b12": "다음",
+ "f5d1e3d472": "집중",
+ "17cc3ea102": "터미널 패널에 마우스를 가리키면 클릭하지 않고도 활성화됩니다. Ghostty의 초점이 마우스를 따라가는 설정을 반영합니다. 선택 및 창 전환이 안전하게 유지됩니다.",
+ "c6178a2b4d": "초점은 마우스를 따릅니다",
+ "f637a7dee9": "두께",
+ "e58d4040d0": "창 구분선의 두께입니다.",
+ "2d5ab88b7c": "분배기 두께",
+ "6c4c85ba43": "디밍",
+ "18dd5026c6": "현재 활성화되지 않은 창에 불투명도가 적용됩니다.",
+ "72bbcbd1dd": "비활성 창 불투명도",
+ "d4f7d1ce5c": "터미널 커서의 불투명도입니다.",
+ "7f1e356a54": "Cursor 불투명도",
+ "25f606d9e5": "깜박거리다",
+ "a27f6edf52": "선택한 커서 모양의 깜박이는 변형을 사용합니다.",
+ "b03d01fd49": "깜박이는 Cursor",
+ "eefd1d8332": "밑줄",
+ "015c82349f": "차단",
+ "a6e9dcc829": "술집",
+ "275a9d6395": "Orca 터미널 패널의 기본 커서 모양입니다.",
+ "97bcfff662": "Cursor 모양",
+ "1abcf4d7de": "리눅스",
+ "7d924d870d": "제도법",
+ "bc7ae1f7c0": "표현",
+ "fffa9ab980": "렌더러",
+ "6cddc858ba": "웹글",
+ "4b4e80d850": "가속",
+ "db82cb13b0": "GPU",
+ "8f9f953de7": "터미널이 xterm.js WebGL 렌더링을 사용하는지 여부를 제어합니다. 렌더러가 지원되면 자동으로 WebGL을 시도하며, 소프트웨어나 알 수 없는 GPU 렌더러에 대한 보수적인 폴백을 사용합니다.",
+ "13a2502dfc": "GPU 가속",
+ "d5e6c7fab1": "글꼴 기능",
+ "a16224d16a": "칼트",
+ "6ded6297fe": "이오세프카",
+ "e3aeea308e": "캐스케이드 코드",
+ "35c2311a33": "제트 브레인 모노",
+ "7f7640c29e": "피라 코드",
+ "7ab424c4d3": "합자",
+ "afc8d5f790": "합자",
+ "103cdb862f": "타이포그래피",
+ "893aa92997": "제공되는 글꼴에 대한 프로그래밍 합자(예: => → ≠ ≥)를 렌더링합니다. \"자동\"은 알려진 합자 글꼴(Fira Code, JetBrains Mono, Cascadia Code, Iosevka 등)에 대해서만 합자를 활성화합니다.",
+ "58da1ae45d": "글꼴 합자",
+ "7341e3d00e": "줄 높이",
+ "36a1b38bc8": "터미널 라인 높이 승수를 제어합니다.",
+ "0f2fb0cb74": "라인 높이",
+ "20ce287cc6": "무게",
+ "98c18f2c77": "터미널 텍스트 글꼴 두께를 제어합니다.",
+ "28ea41bd2d": "글꼴 두께",
+ "b0bb76ae6b": "폰트",
+ "0acdc17891": "새 창 및 라이브 업데이트를 위한 기본 터미널 글꼴 모음입니다.",
+ "e989914ad6": "글꼴군",
+ "33031c1465": "텍스트 크기",
+ "0fe0073f0c": "새 창 및 라이브 업데이트의 기본 터미널 글꼴 크기입니다.",
+ "5930244899": "글꼴 크기"
+ },
+ "windows": {
+ "search": {
+ "4d09141a42": "context menu",
+ "fcfa53920b": "반죽",
+ "e55186fe2b": "오른쪽 클릭",
+ "28ff08ed35": "창문들",
+ "e7d2793b03": "터미널",
+ "8ba875c132": "Windows에서는 마우스 오른쪽 버튼을 클릭하여 클립보드를 터미널에 붙여넣습니다. 컨텍스트 메뉴를 열려면 Ctrl+오른쪽 클릭을 사용하세요.",
+ "f0b8448570": "붙여넣으려면 마우스 오른쪽 버튼을 클릭하세요.",
+ "04994f6929": "기본값",
+ "fc564eadaf": "데비안",
+ "4ee2579c32": "우분투",
+ "5074ad8b5f": "배포판",
+ "2b4a340ce0": "분포",
+ "02c772582a": "리눅스",
+ "6e3adf4cba": "wsl",
+ "978457945b": "새 WSL 터미널 및 로컬 에이전트 검색에서 사용할 WSL 배포를 선택합니다.",
+ "1f402b3651": "WSL 배포",
+ "d57f870938": "고급의",
+ "4af2f7526e": "버전",
+ "d414022016": "으악",
+ "768613e483": "파워셸 7",
+ "f9162f0b8e": "윈도우 파워셸",
+ "2d99cd91be": "파워셸",
+ "41a69bc24d": "PowerShell 셸 옵션이 새 터미널 패널에 대해 Windows PowerShell을 시작할지 아니면 PowerShell 7+를 시작할지 선택합니다.",
+ "860e0e6402": "파워셸 버전",
+ "07ec155fb6": "bash.exe",
+ "5a2db98d23": "세게 때리다",
+ "591912177b": "자식 배쉬",
+ "12519edb5d": "명령 프롬프트",
+ "6cd20b9e64": "cmd",
+ "7c7056940a": "껍데기",
+ "713c4a2f92": "Windows의 새 터미널 패널에 대한 기본 셸을 선택합니다.",
+ "13715f9d23": "기본 쉘"
+ }
+ }
+ },
+ "voice": {
+ "pane": {
+ "search": {
+ "f6e0dfa61c": "구름",
+ "2d206de105": "API 키",
+ "04c25a6fb0": "열기",
+ "b9dee49cd7": "다운로드",
+ "10d45a9fce": "stt",
+ "3d8b853963": "연설",
+ "080202facb": "모델",
+ "7640ed9848": "음성",
+ "56defcd6c3": "받아쓰기에 사용할 로컬 또는 클라우드 음성-텍스트 모델을 선택하세요.",
+ "7e62cd7c41": "음성 모델",
+ "931b1a9e53": "누르고 말하기",
+ "064a9bd94a": "잡고 있다",
+ "6fa48bcd41": "비녀장",
+ "d86f5600da": "방법",
+ "089d31a45b": "받아쓰기",
+ "748b33e531": "받아쓰기 동작을 전환하거나 길게 누르세요.",
+ "6a3abb4338": "받아쓰기 모드",
+ "e360027a65": "마이크로폰",
+ "698376a38d": "음성 받아쓰기 기능을 위한 마스터 토글입니다.",
+ "20574cbc72": "음성 받아쓰기 활성화",
+ "322d457a0d": "전사",
+ "dcc7846641": "클라우드 음성-텍스트 모델에 사용되는 OpenAI API 키를 구성합니다.",
+ "ebfd0b32e5": "OpenAI 전사"
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "action": {
+ "recipe": {
+ "options": {
+ "commitMessage": "단계적 변경에서 커밋 메시지를 생성합니다.",
+ "pullRequest": "호스팅된 리뷰 제목 및 설명을 생성합니다.",
+ "branchName": "초기 에이전트 작업에서 Orca가 생성한 브랜치의 이름을 바꿉니다.",
+ "fixCommitFailure": "커밋 후크 또는 git 커밋이 실패하면 에이전트를 시작합니다.",
+ "fixChecks": "실패한 호스팅 PR 체크에서 에이전트를 시작합니다.",
+ "resolveConflicts": "로컬 또는 호스팅 PR 병합 충돌에 대한 에이전트를 시작합니다."
+ }
+ }
+ }
+ }
+ },
+ "agent-awake-copy": {
+ "e5995ce268": "에이전트 작업 중 컴퓨터를 깨어 있게 유지",
+ "95d3031db2": "에이전트가 작업하는 동안 이 컴퓨터와 디스플레이를 깨어 있게 유지합니다. 뚜껑을 닫을 때의 동작은 이 기기의 전원 설정을 따릅니다.",
+ "a42f6fbdd8": "에이전트가 작업하는 동안 이 컴퓨터와 디스플레이를 깨어 있게 유지합니다. Orca는 전원 정책에 따라 뚜껑이 닫혀 있을 때도 이 기기를 깨어 있게 유지하도록 요청합니다."
+ },
+ "agent-status-hooks-copy": {
+ "7707c15abb": "에이전트 상태 훅",
+ "a68a642835": "Orca에서 작업 중, 대기 중, 완료 상태를 표시합니다. 끄면 Orca가 관리하는 훅을 제거하고 재설치를 중단합니다."
+ },
+ "agent-generated-tab-title-copy": {
+ "19ad21615a": "탭 제목 자동 생성",
+ "b036c7a409": "첫 번째 에이전트 프롬프트에서 짧고 안정적인 탭 이름을 만듭니다. 수동으로 변경한 이름이 항상 우선합니다."
+ }
+ },
+ "right": {
+ "sidebar": {
+ "BulkActionBar": {
+ "79a9f5f712": "언스테이지(",
+ "ef5f5bd06e": "무대 (",
+ "60ed678138": "선택된"
+ },
+ "ChecksPanel": {
+ "2ef90c9819": "실패한 검사에 대한 AI 에이전트를 시작했습니다.",
+ "a0181a8d76": "충돌에 대한 AI 에이전트를 시작했습니다.",
+ "34464d00b9": "업데이트됨",
+ "058039787c": "취소",
+ "2ab7fd4b6d": "저장",
+ "dda5924a40": "검사에는 Git 브랜치 및 호스팅 PR 컨텍스트가 필요합니다.",
+ "976cefd02f": "검사를 사용할 수 없습니다.",
+ "b5dd73a105": "검사를 보려면 워크스페이스를 선택하세요.",
+ "a4ef4e0832": "선택한 워크스페이스가 없습니다.",
+ "5594400d73": "고칠 실패한 검사가 없습니다.",
+ "abf59262fb": "에이전트를 시작하기 전에 전체 명령 입력을 리뷰하고 편집하세요.",
+ "4ede779461": "AI를 통해 리뷰 충돌 해결",
+ "3b203c62f8": "이렇게 하면 PR에서 해당 댓글이 영구적으로 제거됩니다.",
+ "ea9b649ce3": "댓글을 삭제하시겠습니까?",
+ "5788d1059d": "리뷰 스레드를 업데이트할 수 없습니다. GitHub API 예산을 확인하세요.",
+ "07871c0589": "다른 PR 연결",
+ "7202f4a40a": "PR 연결 해제",
+ "7f4489f370": "새로고침",
+ "5c88c6db07": "{{value0}}에 영업 시작",
+ "7fad8509fe": "AI로 고치다",
+ "71026ca2cb": "새로고침 중…",
+ "889cdfba04": "{{value0}} 만들기",
+ "98f4c37b33": "푸시 및 생성 {{value0}}",
+ "6633c7a1fb": "게시 브랜치",
+ "fdb27637f2": "출판…",
+ "e56c42122e": "파괴적인",
+ "786e3c143f": "삭제",
+ "653c105ecc": "더 많은 PR 작업"
+ },
+ "CreatePullRequestDialog": {
+ "2bc1b4345e": "취소",
+ "27ef4b195c": "생성하기 전에 다른 기본 브랜치를 선택하세요.",
+ "7ef56f3efe": "초안으로 만들기",
+ "0c9f9a568c": "마크다운 형식을 지원합니다. AI로 생성을 사용하여 변경 사항을 자동으로 채웁니다.",
+ "02b2ce911f": "설명(선택사항)",
+ "1cd53359db": "설명",
+ "68314b4369": "제목",
+ "694550a610": "기본",
+ "0fad57a14c": "원격 브랜치를 검색하거나 브랜치 이름을 입력하세요.",
+ "8584ccb43c": "기본 브랜치",
+ "6f5f1962b6": "본점",
+ "b504b3ceb1": "호스팅된 리뷰를 생성하기 전에 자세한 내용을 확인하세요.",
+ "f658ff2455": "대상 브랜치를 확인하고",
+ "b7f43474d7": "{{value0}} 만들기",
+ "7a21f0dae8": "{{value0}}에 영업 시작",
+ "edc35a7027": "{{value0}} #{{value1}}은(는) 이미 열려 있습니다.",
+ "a154fe55e6": "푸시 및 생성 {{value0}}"
+ },
+ "CreatePullRequestGenerateButton": {
+ "4012459f8a": "AI로 생성",
+ "a0501572c1": "AI로 {{value0}} 세부정보 생성",
+ "d47fd63012": "세부. 중지하려면 클릭하세요.",
+ "f5513bdeb1": "생성 중",
+ "a6ea6dc3aa": "생성 중…",
+ "e041998cad": "생성 중지"
+ },
+ "FileExplorer": {
+ "79b1537dd3": "파일을 찾아보려면 워크스페이스를 선택하세요."
+ },
+ "FileExplorerBackgroundMenu": {
+ "3b5e2dcb8d": "새 폴더",
+ "21fe46ed36": "새 파일"
+ },
+ "FileExplorerRow": {
+ "addc01145f": "삭제",
+ "fc747429bf": "이름 바꾸기",
+ "0df0e5abac": "폴더에서 찾기",
+ "d6a25618aa": "폴더 축소",
+ "d87a4c42e1": "마크다운 미리보기 열기",
+ "c2112579f6": "다운로드",
+ "dd112c81d2": "Orca 브라우저에서 열기",
+ "1bb9be455c": "프로젝트로 추가...",
+ "0fec99bfd7": "복제",
+ "f61af83316": "새 폴더",
+ "37c875d827": "새 파일",
+ "b3e288bf41": "'{{value0}}'을(를) 다운로드하지 못했습니다.",
+ "1a3df04ae1": "열기",
+ "bce4d4e44f": "'{{value0}}'을(를) 다운로드했습니다.",
+ "e26010014a": ".gitignore에 의해 무시됨",
+ "a06551beee": "입력",
+ "128a99ed5e": "할당되지 않음",
+ "2de3b21934": "가격 인하",
+ "66a29dde82": "상대 경로 복사",
+ "42e10cbf57": "상대 경로 복사",
+ "b5d436aa30": "경로 복사",
+ "f9d7ca753d": "경로 복사",
+ "3161c4e425": "접는 사람"
+ },
+ "FileExplorerToolbar": {
+ "d238264654": "Git이 무시한 파일 표시",
+ "78f133232c": "도트 파일 표시",
+ "31b4c3195d": "추가 탐색기 작업",
+ "d95e30fe28": "탐색기 새로 고침",
+ "6026b16950": "모두 축소"
+ },
+ "FileExplorerTreeStatus": {
+ "ce03835e1f": "이 워크스페이스에는 파일이 없습니다.",
+ "c76693e456": "이 워크스페이스에 대한 파일을 로드할 수 없습니다:"
+ },
+ "GitHistoryPanel": {
+ "cf7cad58d2": "아직 커밋이 없습니다.",
+ "781a8bcf7b": "그래프 로드 중...",
+ "d0fb0f4bf2": "커밋 새로 고침",
+ "9f7535d22b": "Refs는 정확한 커밋을 가리키는 브랜치 또는 태그 이름입니다. Git에 커밋에 대한 명명된 참조가 있는 경우에만 나타납니다.",
+ "9289ba0cb9": "심판이란 무엇입니까?",
+ "d836037d02": "커밋",
+ "8232c8b2f2": "오픈 커밋 {{value0}}: {{value1}}",
+ "9a8b85882d": "로드 중",
+ "62e685d5ec": "idle",
+ "111e1d0db4": "오류",
+ "e5e81e59a6": "커밋 크기 조정"
+ },
+ "HostedReviewActions": {
+ "4d5fb5a284": "닫기",
+ "9845a71e17": "추가 작업",
+ "2bfaf4379c": "추가 {{value0}} 작업",
+ "377269db6f": "{{value0}}이 다시 열렸습니다.",
+ "fa3ee9a515": "닫힘",
+ "78f5ff294c": "그러면 {{value0}}이(가) 다시 열립니다.",
+ "a3d572a4de": "그러면 {{value0}}이(가) 닫힙니다.",
+ "e4aca40024": "워크스페이스 삭제",
+ "eefd50457e": "삭제 중...",
+ "3ce211ece6": "{{value0}} 재개설",
+ "6645ac7dd1": "재개하는 중...",
+ "b25f63edd7": "열림",
+ "d2ca293f3d": "작업 중...",
+ "ef064cb7c3": "기본",
+ "59b4dccf70": "파괴적인"
+ },
+ "PortsPanel": {
+ "3ea4a02a8f": "취소",
+ "4eb801ce93": "개발 서버",
+ "8dfed0a15c": "라벨(선택사항)",
+ "17bea6e391": "로컬호스트",
+ "a3721a50b0": "원격 호스트",
+ "d57545ff92": "원격과 동일",
+ "b950b1948b": "로컬 포트",
+ "9e5a4118b0": "원격 포트",
+ "c9d106547a": "앞으로",
+ "c7e920aa7c": "다음과 같이 광고됨",
+ "e740075063": "제거",
+ "b3548e59f4": "편집",
+ "fe2730d050": "{{value0}} 복사",
+ "b22b128b2a": "브라우저에서 열기",
+ "75aeea592f": "브라우저에서 {{value0}} 열기",
+ "de349d4560": "열립니다",
+ "907eb53ed2": "포트 전달",
+ "04efd3dad4": "로컬 시스템의 원격 서비스에 액세스하려면 포트를 전달하세요.",
+ "1f0d2a24f9": "전달된 포트 없음",
+ "36b1b2984a": "감지됨",
+ "ddbe58d74e": "전달됨",
+ "a103dae837": "추가",
+ "6bc058dbe1": "포트",
+ "d4c3cd679c": "다시 연결하는 중...",
+ "a2f1a47f42": "SSH 연결이 끊겼습니다.",
+ "409afcc145": "브라우저에 대해 선택된 워크스페이스가 없습니다.",
+ "153145e675": "증거",
+ "c7b4702b7b": "워크스페이스",
+ "57d930fa45": "PID",
+ "5dd86dcf2f": "프로세스",
+ "b1ff94fa27": "규약",
+ "729be0b4e5": "친절한",
+ "0f1d8cd324": "묶다",
+ "1c1c18cefc": "주소",
+ "f9528da632": "프로세스 중지",
+ "a223459512": "세부정보 표시",
+ "bdac206faf": "세부정보 복사",
+ "792baeb7ed": "주소 복사",
+ "d41a8241ec": "포트",
+ "a2a9fc6899": "로컬 포트가 감지되지 않았습니다.",
+ "f59c783b7a": "다음에서 포트 스캔을 사용할 수 없습니다.",
+ "7822e3edc6": "포트 새로 고침",
+ "c1b115c375": "선택한 워크스페이스가 없습니다.",
+ "98e9a414f8": "브라우저를 열지 못했습니다.",
+ "a00f3a2840": "포트를 새로고침하지 못했습니다.",
+ "97b562d21d": ":{{value0}}에서 프로세스가 중지되었습니다.",
+ "9079776663": "저장",
+ "c57eda6822": "편집",
+ "9f475dc994": "전송...",
+ "d7c83cfd24": "저장 중...",
+ "31e80cff2d": "원격 포트를 로컬 시스템으로 전달합니다.",
+ "10360598a4": "포트 전달 구성을 업데이트합니다.",
+ "80206251c8": "포트 전달 편집",
+ "4bc9b00912": "워크스페이스",
+ "3e13cb63ee": "알려지지 않은",
+ "472054d94c": "포트 :{{value0}}",
+ "1119f90ad7": "컨테이너",
+ "d32820d3e2": "외부",
+ "4db4b5e435": "기타 워크스페이스",
+ "38b16cfbef": "포트가 감지되지 않았습니다.",
+ "0d63d94db3": "스캐닝...",
+ "935dda7718": "활성 워크스페이스",
+ "740aca88ab": "워크스페이스 포트 스캔에 실패했습니다."
+ },
+ "Search": {
+ "1abfb25a66": "파일에서 검색하려면 입력하세요.",
+ "d56d140747": "검색하려면 Enter를 누르세요.",
+ "0b8104eaf2": "파일",
+ "4107975b3a": "~에",
+ "6aeda362ed": "결과",
+ "98c8435e36": "검색할 워크스페이스를 선택하세요",
+ "1ec640c9c7": "성냥",
+ "dcc294f28d": "(결과가 잘림)"
+ },
+ "SearchFilters": {
+ "01e4671ccf": "제외할 파일(예: *.min.js, dist/**)",
+ "0a6412a895": "제외할 파일",
+ "8a77efcbd1": "포함할 파일(예: *.ts, src/**)",
+ "a69ee1bd0e": "포함할 파일"
+ },
+ "SearchHeader": {
+ "6234a5ef85": "정규식 사용",
+ "4567e6e0b6": "전체 단어 일치",
+ "464ae3974f": "대소문자 일치",
+ "693cbeadd0": "검색"
+ },
+ "SearchResultItems": {
+ "cc06595a3b": "라인 경로 복사",
+ "3596b9668d": "경로 복사"
+ },
+ "SourceControl": {
+ "1406954883": "모든 메모 지우기...",
+ "cc05b2d088": "파일 탐색기에서 열기",
+ "03194cfff4": "여기에서 연 충돌에서 파생된 로컬 세션 상태입니다.",
+ "413a3ba113": "충돌",
+ "27a50fe970": "충돌 리뷰",
+ "f6cb48b6fe": "AI로 해결",
+ "3eeccbb221": "해결된 파일은 라이브 충돌 상태를 벗어나면 다시 일반 변경 사항으로 돌아갑니다.",
+ "c321542ee2": "{{value0}}행의 메모 삭제",
+ "b656381c18": "메모 삭제",
+ "c085946bda": "{{value0}}행에 메모 복사",
+ "1623bf4e19": "메모 복사",
+ "655633c08a": "전송된",
+ "3eb9b2805e": "{{value0}}에서 메모 열기",
+ "0d963bf982": "{{value0}} 열기",
+ "59654650d3": "{{value0}}에 대한 메모 지우기",
+ "ac8cbe3bf5": "diff 보기에서 라인 위에 마우스를 놓고 +를 클릭하여 메모를 추가하세요.",
+ "286dbda4d6": "다시 시도",
+ "476b77745b": "기본 참조 변경",
+ "ed34038d0d": "브랜치 비교 새로 고침",
+ "493f963029": "기본 참조 변경",
+ "3278b2767b": "앞으로",
+ "11b5dd8e41": "비교",
+ "783a808870": "닫기",
+ "a9bf7c171a": "커밋 실패",
+ "03d238218c": "세부",
+ "011f9713fc": "커밋이 차단되었습니다.",
+ "cc199ccc5f": "더 많은 커밋 및 원격 작업",
+ "4d6e1fd7f3": "추가 작업",
+ "37a81f29ad": "커밋 메시지를 생성하는 중입니다. 중지하려면 클릭하세요.",
+ "b94112eb9e": "커밋 메시지",
+ "0d0a8359d3": "메시지",
+ "15b7f210d7": "에이전트를 선택하고 시작하기 전에 전체 명령 입력을 편집하세요.",
+ "054ead86b1": "AI로 커밋 실패 수정",
+ "9e5ccd00aa": "커밋 실패 컨텍스트를 사용할 수 없습니다.",
+ "f0a2dc9e46": "실행 사용자 정의...",
+ "ec7bfced55": "커밋 실패를 해결하려면 에이전트를 선택하세요.",
+ "dd43c47089": "이 커밋 실패에 대한 에이전트를 선택하세요.",
+ "30b8d4f181": "AI로 커밋 실패 수정",
+ "4b37ae99b0": "이 커밋 실패를 수정하려면 기본 AI 에이전트를 시작하세요.",
+ "ae743199cd": "생성하기 전에 다른 기본 브랜치를 선택하세요.",
+ "c5e4175139": "더 많은 {{value0}} 및 원격 작업",
+ "78ddfd0bb4": "초안으로 만들기",
+ "e64a632456": "기본",
+ "6055949c50": "{{value0}} 기본 브랜치",
+ "1f7119f604": "베이스",
+ "9484270f45": "제목 및 설명 생성 중…",
+ "a0dc20fc93": "설명(선택사항)",
+ "a8873e1d62": "{{value0}} 설명",
+ "7d6a8f0082": "제목",
+ "a6eda33521": "{{value0}} 제목",
+ "02d8c04339": "AI로 {{value0}} 세부정보 생성",
+ "e868cec4e1": "생성 중…",
+ "527e130b6f": "생성 중지",
+ "e1970d327d": "새로 만들기",
+ "f4c766f1ca": "이 실행을 위한 에이전트 및 명령 템플릿을 선택합니다.",
+ "1a6a6e0bc5": "호스팅된 리뷰 세부 정보 생성",
+ "6b122529d4": "커밋 메시지 생성",
+ "e48caaf0dd": "충돌에 대한 AI 에이전트를 시작했습니다.",
+ "901140f47d": "에이전트를 시작하기 전에 전체 명령 입력을 리뷰하고 편집하세요.",
+ "19652ddd76": "AI로 충돌 해결",
+ "c9ad22888e": "이 저장소의 브랜치 비교 대상을 선택하세요.",
+ "574d2f4413": "메모 지우기",
+ "05bb8f4a48": "취소",
+ "48db37cca9": "모두 보기",
+ "78ce2d37ac": "포크로 푸시",
+ "c05fe04839": "{{value0}}(원점이 아님)에서 포크로 푸시됩니다.",
+ "c35baf2f1e": "파일 필터링…",
+ "2fe2a67580": "더 많은 메모 작업",
+ "eae2d051af": "모든 메모 복사",
+ "cc474e0b8c": "메모",
+ "e131cd7128": "소스 제어는 Git 리포지토리에서만 사용할 수 있습니다.",
+ "c07b236287": "변경사항을 보려면 워크스페이스를 선택하세요.",
+ "dc5a6465fc": "{{value0}}(예: {{value1}}{{value2}})",
+ "8eb3782a0c": "{{value0}} 파일{{value1}}을(를) 삭제하지 못했습니다.",
+ "a5e5a11090": "모두 삭제 실패 - 삭제하기 전에 파일을 스테이지 해제할 수 없습니다.",
+ "8a5ba6a988": "커밋 차이점을 로드하지 못했습니다.",
+ "fe5bd1a610": "{{value0}} 생성 중...",
+ "812cb992ee": "{{value0}}에 영업 시작",
+ "eef5446523": "{{value0}} #{{value1}}은(는) 이미 열려 있습니다.",
+ "0453ca3a9a": "{{value0}}이(가) 생성되었지만 Orca가 아직 새로 고칠 수 없습니다.",
+ "f99560ab29": "중단 {{value0}} 실패",
+ "eae7a1da5f": "메모를 지우지 못했습니다.",
+ "657e0c90ad": "{{value0}} 메모{{value1}}",
+ "df5040e3c3": "언스테이지",
+ "8cde1a2fb0": "단계",
+ "d54dd48b0b": "변경사항 취소",
+ "989f3d5e34": "파일 복원",
+ "2830dd64a2": "삭제됨",
+ "11463f7a98": "추적되지 않은 파일 삭제",
+ "d62bc0c7d8": "추적되지 않은",
+ "ab31221779": "언스테이지 폴더",
+ "bfe9011a0e": "스테이지 폴더",
+ "6d7f2a47e5": "폴더 삭제",
+ "9b367363b6": "추적되지 않은 폴더 삭제",
+ "540ca8f78c": "병합 중단",
+ "425f138269": "리베이스 중단",
+ "04832d8047": "리베이스",
+ "c105a61960": "병합",
+ "d7a5942e41": "{{value0}}: {{value1}} 해결되지 않음",
+ "c56ba7fa06": "차이점",
+ "94c42b252e": "MD",
+ "e59bca888a": "가격 인하",
+ "b6922abb13": "브랜치 비교를 로드할 수 없습니다.",
+ "715d229c86": "브랜치 비교 불가",
+ "97d8b03cdf": "브랜치 비교 실패",
+ "424ee0e5bf": "오류",
+ "834cb3f23d": "AI로 해결",
+ "60bd988f0b": "AI 수정",
+ "461575b9bc": "AI로 커밋 메시지 생성",
+ "ddc1fbd690": "커밋 메시지 생성 중지",
+ "5acbcedc1a": "{{value0}} 만들기",
+ "aaf1451654": "초안 만들기 {{value0}}",
+ "26511c22b4": "만드는 중...",
+ "7a09d7f9d2": "베이스",
+ "383cf92c73": "나무",
+ "d7ae61269b": "브랜치에 커밋됨",
+ "3636d0f686": "준비됨",
+ "d2e9189866": "모두",
+ "a0cc0e6b4e": "로드 중",
+ "9339382454": "모두 언스테이징",
+ "24d2598eff": "모두 스테이지",
+ "ce41708855": "모두 폐기",
+ "2f609a2e7c": "추적되지 않은 모든 항목 삭제",
+ "9bb062a886": "어느 편도 아닌",
+ "9febd8ab5f": "create_pr",
+ "f62ce91ade": "기원",
+ "3a231c845b": "알려지지 않은",
+ "3baf6c77b4": "모든 메모를 클립보드에 복사",
+ "72f2bea3f4": "메모 펼치기",
+ "d13edef890": "메모 접기",
+ "0fad573938": "어느 편도 아닌",
+ "77afaa8152": "모두"
+ },
+ "SourceControlAgentActionDialog": {
+ "8e856842d1": "선택한 에이전트를 시작할 수 없습니다.",
+ "c075d00de1": "워크스페이스 연결을 확인할 수 없습니다.",
+ "808cfe0a3b": "이 저장소에만 저장",
+ "994cddd1f7": "저장하지 않음"
+ },
+ "SourceControlAgentActionDialogForm": {
+ "1bc0bdbb5e": "실행:",
+ "f84657c925": "실행 레시피 저장",
+ "7ec6abbf2a": "재설정",
+ "f4f3c9ca4a": "명령 템플릿",
+ "fe119187bb": "--모델 소네트",
+ "bc8dc39f4b": "CLI 인수",
+ "b99c33cec5": "설정",
+ "15c5d85706": "에이전트",
+ "3e8f21954f": "오류",
+ "74168d7ada": "idle",
+ "1d47db9bf0": "활성화된 에이전트가 없습니다.",
+ "c7ff8cef11": "에이전트 감지 중..."
+ },
+ "SourceControlTextGenerationDialog": {
+ "c5b7fa7cb6": "전역 기본값으로 저장",
+ "7f1ec309a4": "모든 저장소에 대해 기본값으로 저장",
+ "5959da1e4d": "이 저장소에만 저장",
+ "d054d5e0a0": "설정이 로드되지 않았습니다."
+ },
+ "SourceControlTextGenerationDialogForm": {
+ "25fcd8e49a": "기본값 저장",
+ "d91b0a189d": "레시피 저장",
+ "1f6fcfb6cf": "명령 템플릿",
+ "551ffd111b": "--모델 소네트",
+ "4eab815004": "CLI 인수",
+ "914c8f6ac2": "사용자 정의 명령",
+ "cce2cbd01d": "에이전트 선택",
+ "9c14186dd2": "에이전트"
+ },
+ "activity": {
+ "bar": {
+ "buttons": {
+ "1fd284e931": "추가 사이드바 탭",
+ "f1132ea95d": "중립적"
+ }
+ }
+ },
+ "checks": {
+ "panel": {
+ "content": {
+ "3916814392": "뒤에(기본 커밋:",
+ "755be805f6": "댓글 없음",
+ "751f7c6e5c": "소스당 처음 100개의 댓글 표시",
+ "94557d68e2": "댓글",
+ "3fff651d32": "PR 댓글 추가",
+ "ea9fd5ed6a": "대화 시작...",
+ "0fc6f743b3": "~에 의해",
+ "8987d5a3dd": "해결됨",
+ "ba20d1a896": "{{value0}}에 답장",
+ "f6a40263ff": "저장",
+ "b062f55f29": "취소",
+ "c1f6fc006a": "회신",
+ "2ba0a32bdd": "봇",
+ "6cc6eace26": "삭제",
+ "03ca88f623": "편집",
+ "d3923d18fe": "댓글로 이동",
+ "1abb17aac9": "더",
+ "74c6885b8a": "추가 댓글 작업",
+ "cbcc4ab3db": "처음 100개 검사 표시",
+ "0dca6bfab5": "검사 세부 정보 열기",
+ "991f50c7e4": "구성된 검사가 없습니다.",
+ "9ad98f2a17": "보류 중",
+ "5e52f4ef7f": "실패",
+ "02ca4f9074": "통과",
+ "e15a8b77ef": "이 검사에는 인라인 세부정보가 없습니다.",
+ "679bf2093c": "로그 테일 복사",
+ "d713f500b2": "로그 테일(마지막 200줄)",
+ "a916648574": "세부정보 열기",
+ "07eccfa397": "이 검사에 대한 세부정보가 없습니다.",
+ "49731703ea": "채용 정보",
+ "f2fe8a4e8f": "주석",
+ "d098e5529a": "산출",
+ "2dd5ddabc4": "작업 흐름 #",
+ "aa8494ae3c": "체크 #",
+ "00e1c1658a": "완전한",
+ "fd46a70f1a": "시작됨",
+ "a54ae21c6f": "상태:",
+ "e4e3af15ee": "전체 세부정보 보기",
+ "2524d1fb83": "자세한 내용을 로그 테일에서 확인할 수 있습니다.",
+ "a2fb3f4408": "처음 100개의 채용정보 표시",
+ "df137989b3": "처음 20개의 주석 표시 중",
+ "1f2b980522": "검사 세부 정보 로드 중…",
+ "0c96cd25e5": "해결",
+ "3a71a6ed0b": "확인 및 병합이 완료되기 전에 충돌을 해결하세요.",
+ "60186d8498": "충돌로 인해 차단됨",
+ "c16762ac8c": "아래 확인 및 설명은 현재 가져온 컨텍스트를 보여줍니다.",
+ "9d0e7bcefc": "차단 PR 조치 없음",
+ "5856874b59": "Orca는 이 패널이 열려 있는 동안 검사를 새로 고칩니다.",
+ "5341023167": "확인",
+ "b45db92d0e": "고치다",
+ "5d4ebf9391": "세부 정보를 검사하거나 AI 수정 패스를 시작하세요.",
+ "b652f38caf": "점검 실패",
+ "87cd07c69a": "이 브랜치에는 해결해야 할 충돌이 있습니다.",
+ "0975eeaaef": "파일 충돌",
+ "6fa7f8723f": "저지르다",
+ "2b2be92919": "댓글 추가",
+ "7440d09d2c": "대화 시작",
+ "b37ebdc51c": "댓글을 달 수 없습니다.",
+ "90206b6353": "댓글",
+ "95ad090b01": "실",
+ "365254cc1b": "해결 취소",
+ "7f793b571d": "드래그하여 검사 영역 크기 조정",
+ "ee07b33924": "알려지지 않은",
+ "cdbfda4dec": "주석",
+ "066fedd446": "실패한 작업",
+ "ae8a04ef17": "충돌 파일 세부정보를 사용할 수 없습니다.",
+ "73d0675356": "충돌 세부정보 새로고침 중…"
+ },
+ "empty": {
+ "state": {
+ "5b0cfae9a5": "체크와 리뷰를 시작하려면 {{value0}}을(를) 만드세요.",
+ "13e1c7d5ed": "{{value0}}을(를) 찾을 수 없습니다.",
+ "d372072df1": "현재 속도 제한 예산으로 인해 GitHub 새로 고침이 일시 중지되었습니다.",
+ "7c299df37b": "PR을 찾을 수 없습니다.",
+ "3d4af82ff4": "이 브랜치의 GitHub 상태 새로고침 중",
+ "938b5606a6": "PR 확인 중",
+ "6ba2440770": "이 브랜치의 GitHub 상태 새로고침을 기다리는 중입니다.",
+ "2bdd7aaf2d": "GitHub 상태를 새로 고칠 수 없습니다. 기존 캐시 데이터는 보존되었습니다.",
+ "5f478ab3d3": "PR을 새로 고칠 수 없습니다.",
+ "6ce9d4e069": "{{value0}}을 만들기 전에 브랜치를 푸시하세요.",
+ "76e15946a9": "브랜치에 푸시되지 않은 커밋이 있습니다.",
+ "f8543140cc": "{{value0}}을 만들기 전에 이 브랜치를 게시하세요.",
+ "41252bc53f": "게시되지 않은 브랜치",
+ "05e4aec17b": "{{value0}} 검사는 작업이 완료된 후에 사용할 수 있습니다.",
+ "d77c513c1e": "{{value0}} 진행 중"
+ }
+ }
+ }
+ },
+ "gitlab": {
+ "mr": {
+ "merge": {
+ "state": {
+ "04a3015a12": "병합 가능",
+ "53c6d3b7e9": "GitLab에서는 이 MR이 병합될 수 있지만 파이프라인은 여전히 실행 중이라고 말합니다.",
+ "65c847ad1e": "검사 대기 중",
+ "b41fbc180c": "GitLab에서는 이 MR이 병합될 수 있지만 일부 파이프라인 작업이 실패했다고 말합니다.",
+ "49ac4fec10": "확인 실패",
+ "22b7e50621": "GitLab이 병합 충돌을 보고합니다.",
+ "96b05e374c": "충돌",
+ "d63bb6f76e": "이 MR은 아직 초안입니다.",
+ "b2715092c6": "초안",
+ "2388413f28": "이 MR이 종료되었습니다.",
+ "88d044c42f": "닫힘",
+ "ee482a2bad": "이 MR은 이미 병합되었습니다.",
+ "fae95ae20d": "병합됨"
+ }
+ }
+ }
+ },
+ "index": {
+ "70893f017b": "옆",
+ "7b415c39e9": "맨 위",
+ "864111caa2": "활동 표시줄 위치",
+ "e8e2e4ce74": "오른쪽 사이드바 표시/숨기기",
+ "441733b630": "포트",
+ "83a10e3c44": "검사",
+ "0314901467": "소스 제어",
+ "06219e4cb1": "검색",
+ "8bc2bbc3a0": "탐침",
+ "45b78f03bc": "옆",
+ "34af8aadf5": "맨 위",
+ "9fffaf17c1": "오른쪽 사이드바 표시/숨기기({{value0}})",
+ "b37ff4a89a": "포트",
+ "9f83375839": "검사",
+ "6306b48afd": "소스 제어",
+ "ef182dcb12": "검색",
+ "fc3095d2ed": "탐침"
+ },
+ "right": {
+ "panel": {
+ "comment": {
+ "composer": {
+ "9bca633dee": "취소",
+ "cf5a7aba6f": "목록",
+ "d6d9c3c947": "인용",
+ "f49e0a21e0": "암호",
+ "542bf6a7e2": "이탤릭체",
+ "256300f8ea": "용감한",
+ "87aff03d63": "전송 중..."
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "ai": {
+ "commit": {
+ "failure": {
+ "launch": {
+ "a8b97d2318": "커밋 실패에 대해 AI 에이전트를 시작했습니다.",
+ "5540ff50cc": "에이전트 시작 명령을 빌드할 수 없습니다.",
+ "9bbd9077a2": "활성화된 AI 에이전트가 없습니다. 설정에서 에이전트를 구성하세요.",
+ "d481ab22f9": "저장된 AI 에이전트를 사용할 수 없습니다. 다른 에이전트를 선택하려면 시작 사용자 정의를 사용하세요.",
+ "f2b47026e8": "커밋 실패 프롬프트가 비어 있습니다. 소스 제어 AI 설정을 업데이트합니다.",
+ "4f4e0418a0": "에이전트 프롬프트를 작성할 수 없습니다.",
+ "216f762bd7": "워크스페이스 연결을 확인할 수 없습니다."
+ }
+ }
+ }
+ },
+ "discard": {
+ "confirmation": {
+ "2ae5a785b3": "단계적이지 않은 변경사항을 모두 삭제하시겠습니까?",
+ "ddf36f291c": "그러면 모든 단계적 변경 사항이 단계 해제되고 되돌려집니다. 준비된 새 파일이 삭제됩니다. 이 작업은 취소할 수 없습니다.",
+ "5ddd8cac7f": "모든 단계적 변경사항을 삭제하시겠습니까?",
+ "1426c2efff": "그러면 이 파일의 모든 변경 사항이 되돌려집니다. 이 작업은 취소할 수 없습니다.",
+ "d4df3a61df": "'{{value0}}' 변경사항을 취소하시겠습니까?",
+ "40e9357b2a": "이렇게 하면 HEAD에서 파일이 복원되고 삭제 내용이 삭제됩니다. 이 작업은 취소할 수 없습니다.",
+ "5c0bdbc4cb": "'{{value0}}'을(를) 복원하시겠습니까?",
+ "d97bf697c9": "이 파일이 영구적으로 삭제됩니다. 이 작업은 취소할 수 없습니다.",
+ "96c772bee9": "'{{value0}}'을 삭제하시겠습니까?"
+ },
+ "dialog": {
+ "3bc61dc989": "취소",
+ "15efa778e3": "버리기",
+ "6de99d162b": "기입",
+ "42f89dd030": "파일",
+ "e7611dca35": "파일",
+ "48c5ef95d9": "영역",
+ "0d2d88cba5": "이 작업은 취소할 수 없습니다.",
+ "1551c14668": "변경사항을 삭제하시겠습니까?"
+ }
+ },
+ "dropdown": {
+ "items": {
+ "7aad2c0240": "호스팅 PR 작업 진행 중…",
+ "9e779995dd": "{{value0}} 만들기",
+ "226b85a3a7": "술책",
+ "323bb614aa": "커밋 및 동기화",
+ "2b8e6595fd": "저지르다"
+ }
+ },
+ "primary": {
+ "action": {
+ "ed93b4f14f": "저지르다",
+ "946a8a05ea": "이 브랜치에 대해 {{value0}}을 만듭니다.",
+ "e7ffa46946": "{{value0}} 만들기",
+ "95550cff15": "푸시",
+ "d64292a938": "당기다",
+ "795f1509c5": "동조",
+ "390abeab93": "강제 푸시",
+ "1884cf34af": "이 브랜치를 원본에 게시",
+ "7b4d02e6b8": "게시 브랜치",
+ "3d5dccef0b": "커밋할 것이 없습니다. PR은 이미 병합되었습니다.",
+ "41d4bcf157": "PR 상태 확인 중…",
+ "acce237921": "커밋할 것이 없습니다. 브랜치에 게시할 변경 사항이 없습니다.",
+ "fa3bd4f40c": "커밋할 파일을 하나 이상 준비하세요.",
+ "5a477d80cb": "모든 변경 사항을 준비합니다.",
+ "18a0fca877": "모두 스테이지",
+ "f01f16d77f": "커밋하려면 커밋 메시지를 입력하세요.",
+ "ab41fb926b": "단계적 변경 커밋",
+ "2d8f185fbc": "부분적으로 준비된 파일을 커밋하기 전에 모든 변경 사항을 준비합니다.",
+ "a6457b46a7": "커밋하기 전에 충돌을 해결하세요.",
+ "484f45c439": "{{value0}} 진행 중…",
+ "74fc171e99": "강제 푸시 진행 중…",
+ "16aee3a5c1": "커밋 진행 중…"
+ }
+ }
+ }
+ },
+ "use": {
+ "source": {
+ "control": {
+ "ai": {
+ "cfafa92509": "보낼 해결되지 않은 충돌이 없습니다."
+ }
+ }
+ }
+ },
+ "useFileDeletion": {
+ "72691dfebc": "{{value0}} '{{value1}}'에 실패했습니다.",
+ "96affe1302": "'{{value0}}'이(가) {{value1}}(으)로 이동되었습니다.",
+ "74727df633": "'{{value0}}'이(가) 삭제되었습니다.",
+ "d979a4fbb5": "'{{value0}}'을(를) 영구적으로 삭제하시겠습니까?",
+ "a76c74f105": "파괴적인",
+ "92276aceb7": "삭제"
+ },
+ "useFileExplorerHandlers": {
+ "32cd9fd991": "심볼릭 링크 대상을 열 수 없습니다"
+ },
+ "useFileExplorerImport": {
+ "25919b2050": "{{value0}} {{value1}}을(를) 건너뛰었습니다.",
+ "132fd0e1e9": "{{value0}} {{value1}}을(를) 가져오지 못했습니다."
+ },
+ "useFileExplorerKeys": {
+ "8adb953095": "작업 실패"
+ },
+ "GitHistoryGraphSvg": {
+ "47eff48230": "머리"
+ }
+ }
+ },
+ "repo": {
+ "NestedRepoChecklist": {
+ "f7e1170567": "선택된",
+ "ea54c7bf8f": "~의",
+ "91b5bcadb6": "모두 선택",
+ "929734aea5": "모두 선택 취소"
+ },
+ "NestedRepoScanLimitNotice": {
+ "642a43c139": "중첩된 저장소 검사 한도",
+ "574eb5408b": "부분 스캔 결과를 표시합니다.",
+ "03e9beab7b": "스캔이 일찍 중지되었습니다."
+ },
+ "RepoCombobox": {
+ "b3e15f4525": "프로젝트 추가",
+ "b4a235e886": "프로젝트 추가",
+ "3639fd9da2": "SSH",
+ "e7ed739236": "검색과 일치하는 프로젝트/폴더가 없습니다.",
+ "a0c48f5f29": "프로젝트/폴더 검색...",
+ "116812151a": "프로젝트 추가 중…"
+ },
+ "repo": {
+ "icon": {
+ "0ad395d475": "상자",
+ "857977b901": "모양",
+ "b1b8d99fc4": "일체 포함",
+ "137bdb1856": "측정항목",
+ "d202c659a3": "설계",
+ "c4fd14299d": "회사",
+ "4ab9433660": "작업",
+ "febfbe0cd5": "도구",
+ "ecf63ec3ef": "실행",
+ "31826b712e": "API",
+ "70bef15d40": "레이어",
+ "b5fac337aa": "컴퓨팅",
+ "d37b4e2641": "섬기는 사람",
+ "3c5a593bc8": "편물",
+ "477b28c948": "데이터 베이스",
+ "787490e9bd": "패키지",
+ "07012dc113": "에이전트",
+ "3eba7387ab": "터미널",
+ "65b437c381": "암호",
+ "bed2674f9d": "접는 사람"
+ }
+ }
+ },
+ "pet": {
+ "pet": {
+ "models": {
+ "7433516faf": "그렘린",
+ "a84d5677ff": "OpenCode",
+ "2528586aa7": "클라우디노"
+ }
+ },
+ "PetOverlay": {
+ "de932b0e8f": "@keyframes pet-bob { 0%,100% { 변환: 번역Y(0); } 50% { 변환: 번역Y(-4px); } }",
+ "4712d196c6": "@keyframes pet-{{value0}} { from { 배경 위치: {{value1}}px {{value2}}px; }에서 { 배경 위치: {{value3}}px {{value4}}px; } }"
+ }
+ },
+ "onboarding": {
+ "AgentStep": {
+ "e6a369bd04": "인기 에이전트",
+ "d7b3ef168b": "시스템에서 감지됨",
+ "9c163bb0e0": "설치 지침",
+ "69af7e9c1c": "아직 PATH에 없습니다. Orca는 이를 기본값으로 설정하며 언제든지 설치할 수 있습니다.",
+ "1eee1c7bd8": "PATH에서 에이전트가 감지되지 않습니다. 나중에 설치할 항목을 선택하거나 빈 터미널을 계속 사용하세요.",
+ "hideAgents": "에이전트 숨기기",
+ "showMoreAgents": "{{value0}}개 더 많은 에이전트 표시→"
+ },
+ "FeatureSetupChecklist": {
+ "77f74946f5": "에이전트는 서로 메시지를 보내고, 작업을 수행하고, 핸드오프를 조정할 수 있습니다.",
+ "399cf885c0": "에이전트 오케스트레이션",
+ "c5292c409d": "에이전트은 요청 시 앱 창을 검사하고 로컬 앱을 작동할 수 있습니다.",
+ "1ecfb490ac": "컴퓨터 사용",
+ "01426f3a23": "에이전트는 사이트를 탐색하고, 페이지를 검사하고, 브라우저 작업을 수행할 수 있습니다.",
+ "ea85d9e628": "에이전트 브라우저 사용"
+ },
+ "FeatureSetupInlineTerminal": {
+ "789b59936e": "Enter를 눌러 명령을 실행하고 요청 시 npx를 확인합니다. 나중에 설정에서 설정할 수도 있습니다.",
+ "47fc6cc6dc": "스킬 설정 명령어",
+ "c767ab7061": "스킬 설정"
+ },
+ "IntegrationsStep": {
+ "277f30eb34": "Linear, GitLab, Bitbucket, Azure DevOps, Gitea 및 Jira는 설정 > 연동에 있습니다.",
+ "3a3e360289": "더 많은 작업 소스",
+ "80e3ce0bc9": "재확인",
+ "04ef416712": "Linear 연결 추가",
+ "dd9c186a8b": "워크스페이스 액세스 추가",
+ "c91a5782f1": "연결됨",
+ "27743304b1": "Linear",
+ "af69f42372": "Enter를 눌러 GitHub CLI 인증을 실행하세요. 브라우저 또는 장치 흐름이 완료된 후 GitHub를 다시 확인하세요.",
+ "f9d2e12d17": "GitHub 로그인 명령",
+ "6d469169f2": "GitHub 설정",
+ "bd5d976fb2": "gh 설치",
+ "50db38cf4b": "PR, 이슈, 체크 상태를 확인하세요.",
+ "c1547656f0": "확인 중…",
+ "8405043962": "로그인이 필요합니다",
+ "5c115cb713": "CLI가 설치되지 않았습니다.",
+ "217beb0658": "GitHub",
+ "4983ae7433": "개인 API 키로 Linear를 연결하세요. 전체 액세스 키는 키 소유자가 접근할 수 있는 모든 팀을 표시할 수 있습니다.",
+ "b08a6ac93c": "{{value0}} 워크스페이스{{value1}}이 연결되었습니다. 언제든지 다른 워크스페이스를 추가하거나 제한된 키를 교체하세요.",
+ "93f0c49ad1": "인증되지 않은",
+ "a3bcf13694": "연결됨",
+ "d6e5dba05a": "로그인",
+ "0b4a7d23ab": "로그인",
+ "a74c6d6b18": "설치되지 않은"
+ },
+ "NotificationStep": {
+ "3bede04483": "테스트 알림 보내기",
+ "dc897423e1": "알림 소리 선택",
+ "53aaffe49a": "알림음",
+ "0fe570690c": "데스크톱 알림이 전달된 후 Orca가 재생하는 경고를 선택합니다.",
+ "0af746e41f": "소리를 선택하세요",
+ "8124d085a6": "맥 설정 열기",
+ "aa36281b00": "시스템 설정을 열고 Orca가 알림을 보낼 수 있는지 확인하세요.",
+ "d2dba86837": "macOS에서 Orca 허용",
+ "e52aacf380": "알림 설정 로드 중…",
+ "3cd5374e22": "알림 설정이 아직 로드 중입니다.",
+ "b6a994e36e": "알림음을 재생할 수 없습니다.",
+ "c0692baa52": "사용자 정의 파일 선택",
+ "ac80d97e02": "사용자 정의 파일 변경"
+ },
+ "OnboardingFlow": {
+ "1b5e182e9f": "Orca에 오신 것을 환영합니다",
+ "4db04f2f57": "/",
+ "adaa0aa627": "온보딩 단계 {{value0}}: {{value1}}로 이동",
+ "a249f81538": "Orca",
+ "277ba45540": "Orca 온보딩",
+ "97c42cda00": "GitHub CLI를 설치하여 다음을 수행합니다.",
+ "ae3b00ca82": "GitHub 작업 설정",
+ "ff92d15436": "에이전트 작업이 완료되거나 도움이 필요할 때 Orca가 알려 드립니다.",
+ "b054332836": "알림 설정",
+ "04ae28d8ca": "몇 시간 내내 보고 싶은 테마를 선택하세요.",
+ "f396db9f20": "집처럼 느껴지도록 하세요",
+ "322fc50a18": "Orca는 모든 CLI 에이전트와 함께 작동합니다. 가장 많이 도달할 수 있는 것을 선택하세요. 언제든지 전환하세요.",
+ "198b148b3c": "기본 에이전트를 선택하세요",
+ "a5e5da02f7": "연동",
+ "35bbaf5ae0": "알림",
+ "984338477a": "테마",
+ "c47e1bd149": "에이전트"
+ },
+ "OnboardingFooter": {
+ "ba58547306": "뒤로",
+ "111d3f8d92": "프로젝트 설정으로 건너뛰기"
+ },
+ "OnboardingInlineCommandTerminal": {
+ "4123609efd": "터미널 시작 중..."
+ },
+ "OnboardingSkipConfirmationDialog": {
+ "9f47f345a4": "오래 걸리지 않을 거예요!",
+ "e4726b2d50": "온보딩을 건너뛰시겠습니까?"
+ },
+ "OnboardingTourStep": {
+ "3f9586c043": "둘러보기",
+ "60c5576353": "투어 종료"
+ },
+ "RepoStep": {
+ "e8fdb36338": "저장소를 스캔하는 중입니다. 중지하려면 클릭하세요.",
+ "b7c4da0504": "SSH? 설정에서 호스트를 설정하세요",
+ "c33b190ca3": "서버 경로만",
+ "7b679207e4": "워크스페이스",
+ "24c7c8696c": "서버 경로로 복제",
+ "7932e95f68": "클론",
+ "955134915e": "git@github.com:org/repo.git",
+ "288d8444b7": "HTTPS 또는 SSH URL을 붙여넣습니다.",
+ "132425a3e3": "저장소 복제",
+ "6558d50c69": "한 번에 많은 저장소를 가져오고 싶으십니까? 상위 폴더를 선택합니다.",
+ "831524961f": "로컬 디렉터리(git repo 여부)를 선택하세요.",
+ "f4e9c8dcf8": "폴더 찾아보기",
+ "e8214aa632": "폴더로 열기",
+ "3863747c56": "Git 프로젝트 추가",
+ "2ebbc26343": "/home/user/project",
+ "466108ab89": "런타임 서버에 존재하는 경로를 입력하십시오.",
+ "8cab104e3c": "서버 프로젝트 열기",
+ "2d20200346": "저장소 가져오기",
+ "27ca610db1": "뒤로",
+ "cecd6593fa": "스캔한 폴더:",
+ "c7af322fc3": "스캔 중지",
+ "c3d9d44ca2": "스캔 중지",
+ "cf23006ba7": "런타임 서버",
+ "7ec3f48820": "/home/user",
+ "2e6438dd34": "{{value0}}이 폴더에서 {{value1}} {{value2}}을(를) 찾았습니다."
+ },
+ "ThemeStep": {
+ "a4b254779d": "macOS 옵션 키",
+ "6c51398942": "마우스",
+ "8ca01945f2": "구분선",
+ "b3a99a2d29": "창",
+ "86c0f1caa2": "패딩",
+ "06a24f4f2d": "색상",
+ "c021e9dddd": "테마 팔레트",
+ "ab2a583a97": "Cursor",
+ "cc1858e19e": "글꼴",
+ "248c812283": "가져오기",
+ "7ee9234e54": "고스트 구성이 감지되었습니다.",
+ "78b6386140": "Ghostty에서 가져왔습니다.",
+ "2c3aa538f8": "Ghostty 구성을 찾고 있습니다…",
+ "94b9dc561d": "설정 → 터미널",
+ "dd5c16ad1b": "글꼴, 커서 및 팔레트를 포함한 추가 터미널 옵션",
+ "ad192706e6": "라이트",
+ "fa7b673ea9": "다크",
+ "827ea7b4a2": "시스템",
+ "699ddf83c2": "Ghostty 설정을 가져오지 못했습니다.",
+ "16a9f0446a": "가져올 Ghostty 설정이 없습니다.",
+ "ad19e5c916": "가져오는 중…",
+ "906c4373fe": "설정"
+ },
+ "use": {
+ "onboarding": {
+ "flow": {
+ "dce4bdce5b": "SSH 설정을 열 수 없습니다.",
+ "fd74e7558e": "복제 실패",
+ "52acfbef51": "진행 상황을 저장할 수 없습니다."
+ }
+ }
+ },
+ "AgentFeatureSetupStep": {
+ "97dcdc010f": "기능 활성화"
+ }
+ },
+ "new": {
+ "workspace": {
+ "SmartWorkspaceNameField": {
+ "2a0d535f69": "새 브랜치 만들기",
+ "a44229ce4d": "워크스페이스 이름으로",
+ "766083a596": "\"",
+ "34ca97bce3": "\"",
+ "b1a7d679ba": "사용",
+ "e57c53727c": "프로젝트 추가...",
+ "a76fcb4fa0": "다음으로 전환",
+ "eadf877af5": "유지",
+ "6859e2896c": "취소",
+ "9ef1a7c4b0": ", 선택한 프로젝트와 다릅니다.",
+ "ad188067ae": "GitHub URL은 다음을 가리킵니다.",
+ "4bd98f1091": "프로젝트를 전환하시겠습니까?",
+ "0c9e668e3a": "지우기",
+ "7199ff19c7": "선택한 소스 지우기",
+ "370a1faf67": "브라우저에서 열기",
+ "2c69728c2a": "브라우저에서 링크 열기",
+ "6f07a18604": "이름",
+ "2e4c7c95fe": "브랜치",
+ "2cfc6be192": "GitLab",
+ "7a47af0565": "Linear",
+ "0a180280bd": "GitHub",
+ "b3c60c2b7c": "똑똑한",
+ "26824f60dd": "모두",
+ "6fad211c66": "닫힘",
+ "2319d87718": "병합됨",
+ "622864b52a": "열림",
+ "fda67f0b61": "현재 프로젝트",
+ "3e8bb1176a": "이슈를 검색하려면 설정에서 Linear를 연결하세요.",
+ "69ce292138": "Linear",
+ "9c004911c3": "gitlab"
+ }
+ }
+ },
+ "mobile": {
+ "MobileHero": {
+ "a8fb43cf1c": "Continue",
+ "3f90dbd274": "완료",
+ "b622eba64d": "뒤로",
+ "65b3f2e8bc": "생성 중…",
+ "27735e5f4e": "QR 페어링",
+ "bb0074ce11": "QR 코드 페어링",
+ "010dddcf27": "페어링 코드 복사",
+ "4c1df4eba7": "스캔할 수 없나요?",
+ "85067b9e06": "네트워크 인터페이스 새로 고침",
+ "ca85e595a7": "인터페이스를 찾을 수 없습니다.",
+ "79d2f480da": "광고할 네트워크 인터페이스",
+ "dfd2aa9d5d": "회로망",
+ "2f077ef4eb": "을 클릭하고 코드를 스캔하세요.",
+ "3aa7bb2d8b": "데스크탑 페어링",
+ "d1495e5e64": "Orca Mobile을 열고",
+ "901c98bb93": "페어링",
+ "3960f5c339": "2/2단계",
+ "3241f3c26a": "QR 설치",
+ "7af266b80d": "QR코드 설치",
+ "aa97420ba4": "설치 링크 복사",
+ "ac1eb64952": "기계적 인조 인간",
+ "711e6f4b47": "iOS",
+ "e75647ace0": "휴대폰으로 QR을 스캔하거나 설치 링크를 열어 Orca Mobile을 다운로드하세요.",
+ "0d9b33299e": "앱을 받으세요.",
+ "92ddfdfa1f": "2단계 중 1단계",
+ "ff48d9d520": "다른 장치와 페어링",
+ "f9cbf4bb53": "기기 취소",
+ "34f878d04f": "{{value0}} 취소",
+ "94829abdb1": "페어링됨",
+ "266c18c105": "Orca Mobile을 열어 중단한 부분부터 다시 시작하거나 다른 장치를 페어링하세요.",
+ "5410d55d79": "Orca 모바일",
+ "10d27b4cba": "시작하기",
+ "da1d5e5ed0": "사용 가능 날짜",
+ "ec0607bf66": "지원되는 모바일 플랫폼",
+ "b4ccce5cb7": "휴대폰에서 Orca를 제어하세요. 자리를 비운 동안 에이전트를 확인하고, 변경 사항을 리뷰하고, 작업을 시작하세요.",
+ "cd4e5e816f": "주머니 속의 워크스페이스.",
+ "a6cffbbb0b": "코드 생성",
+ "e59a252eca": "코드 재생성",
+ "d0b52871ce": "휴대전화가 페어링되었습니다.",
+ "051978a785": "휴대전화가 페어링되었습니다."
+ },
+ "MobilePage": {
+ "e17393c6a3": "전화 미리보기",
+ "baea63c445": "링크를 복사하지 못했습니다.",
+ "fad833de8d": "설치 링크 복사됨",
+ "6a66e38943": "페어링 코드를 복사하지 못했습니다.",
+ "3c1f7168bb": "페어링 코드가 복사되었습니다.",
+ "4c8bd11c1a": "페어링 코드를 생성하지 못했습니다.",
+ "b353e18de1": "WebSocket 전송이 실행되고 있지 않습니다.",
+ "4e1eb5d55c": "기기를 취소하지 못했습니다.",
+ "255372e6e8": "기기가 취소되었습니다.",
+ "1b4509a8a1": "짝을 이루는",
+ "c5909374cf": "소개"
+ },
+ "MobilePageToolbar": {
+ "ad2284a9e2": "닫기 · Esc",
+ "9883b58693": "Orca 모바일 닫기",
+ "fb5f28330e": "사이드바에 표시",
+ "c669abcf8f": "사이드바에서 숨기기"
+ },
+ "PhoneCarousel": {
+ "96d651cb87": "터미널 세션",
+ "93217b41c1": "작업 트리 목록",
+ "89c7713645": "Orca 모바일 홈 화면"
+ },
+ "mobile": {
+ "platform": {
+ "copy": {
+ "2a532d6fd7": "Android 카메라로 스캔하여 GitHub 릴리스에서 최신 APK를 다운로드하세요.",
+ "432db52b73": "iPhone 카메라로 스캔하여 App Store를 엽니다."
+ }
+ }
+ },
+ "slides": {
+ "HomeSlide": {
+ "a7d9e2c44d": "7일",
+ "a3d5476811": "5시간",
+ "8a350a4784": "계정 사용량",
+ "e27fdaee51": "새 워크스페이스",
+ "4405f3c440": "데스크탑 페어링",
+ "0b00c98506": "빠른 작업",
+ "0bad5b07c8": "GitHub 및 Linear",
+ "d047197480": "GitHub · Linear",
+ "a4c3f7b7aa": "작업",
+ "d33d7a9c29": "orca · feat/mobile-page",
+ "25d6e8a491": "feat/모바일 페이지",
+ "c791677f2f": "재개",
+ "cf3f98fa3f": "연결이 끊김",
+ "091355da3d": "M1 미니 · 집",
+ "0bc1881bc4": "연결됨 · 작업 트리 40개 · 활성 5개",
+ "19c212e25e": "맥북 프로",
+ "2f1a1d10c4": "데스크탑",
+ "156db8a68a": "생성된 PR",
+ "4a40af029b": "에이전트 시간",
+ "00a6903322": "시작된 에이전트",
+ "c0e2e9dcd9": "돌아온 것을 환영합니다",
+ "af761a0c0d": "설정",
+ "5d94e8ddcc": "Orca"
+ },
+ "TerminalSlide": {
+ "0bb39f8fe6": "보내기",
+ "69334b4b10": "음성 받아쓰기",
+ "29f2d13839": "명령을 입력하세요…",
+ "817090af40": "Ctrl+C",
+ "53ff909568": "꼬리표",
+ "4930eaaae7": "Esc",
+ "fa22927f13": "반죽",
+ "985373052e": "휴대폰 모드로 전환",
+ "58a9ee6003": "도구 호출 형식. 다음에 차이점을 추가하시겠습니까?",
+ "aa64b519c6": "터미널 화면. Tokyonight palette, Menlo, real claude",
+ "e75112c834": "페어 스캔 슬라이드를 고화질로 교체했습니다.",
+ "3ce3e8c892": "14개 통과, 1개 건너뛰기(1.8초)",
+ "4b3666f9a9": "src/cache/worktree-cache.test.ts",
+ "1d448b69f7": "통과",
+ "d39445686a": "src/transport/host-store.test.ts",
+ "a6e7cdc688": "pnpm 테스트 - 모바일 필터링",
+ "21b67dfc92": "세게 때리다",
+ "d6d1041a1c": "⎿ 페어 스캔 슬라이드를 터미널 세션으로 대체했습니다.",
+ "336c0e070e": "mobile/orca-mobile-sidebar-mock-v3.html",
+ "6d4ebd5833": "편집",
+ "fc83e0d5ef": "⎿ 2103줄 읽기",
+ "80cc356591": "읽다",
+ "2c10d43745": "claude",
+ "e0f98be657": "orca/feat-모바일 페이지",
+ "2defc05141": "개발자@mac",
+ "da121ba48d": "PLAN.md",
+ "e4befee569": "껍데기",
+ "606aa93192": "파일",
+ "94febb0976": "소스 제어",
+ "8d6516312d": "2개 터미널 · claude active",
+ "8432787c4e": "feat/모바일 페이지",
+ "8fd998acd3": "뒤로"
+ },
+ "WorktreeListSlide": {
+ "357a519567": "활성",
+ "79a24ff530": "고정됨",
+ "22971156df": "레포",
+ "17f9e0d226": "최근의",
+ "0e3e809a4b": "필터",
+ "b4271864bd": "맥북 프로",
+ "cefd048225": "뒤로",
+ "c5ad56786d": "스피너"
+ }
+ }
+ },
+ "gitlab": {
+ "gitlab": {
+ "rate": {
+ "limit": {
+ "display": {
+ "ebc0e8ecf1": "GitLab API 예산 로드 중...",
+ "a2d3d1fdde": "GitLab API 예산을 사용할 수 없습니다.",
+ "a2f68645ac": "GitLab API 예산 새로 고침",
+ "2f9c16d6c3": "Orca는 GitLab CLI를 통해 REST를 사용합니다.",
+ "14e144f7a7": "GitLab API 예산",
+ "3e2c982cfa": "왼쪽, 재설정",
+ "ea8ad0bae8": "~의",
+ "0a891e8935": "REST API",
+ "953f7c6062": "이 GitLab 호스트는 속도 제한 헤더를 반환하지 않았습니다."
+ }
+ }
+ }
+ }
+ },
+ "floating": {
+ "terminal": {
+ "FloatingTerminalIconContextMenu": {
+ "8e7d775287": "플로팅 워크스페이스 숨기기",
+ "763f5fa2c1": "플로팅 버튼으로 이동",
+ "0ee79e0674": "상태 표시줄로 이동"
+ },
+ "FloatingTerminalOrchestrationDialog": {
+ "f726054620": "에이전트가 Orca를 통해 컨텍스트를 넘기고 작업을 조정할 수 있습니다.",
+ "1cd3f8af64": "오케스트레이션 스킬",
+ "6f0aed26b8": "에이전트가 Orca를 통해 조정할 수 있도록 Orca CLI 및 오케스트레이션 스킬을 설치합니다.",
+ "05d7aabc20": "설치되지 않음",
+ "630c0ac8c8": "설치됨",
+ "dfd021ce46": "확인 중...",
+ "543f325a14": "오케스트레이션 활성화"
+ },
+ "FloatingTerminalPanel": {
+ "fc1042e92b": "최소화",
+ "8b07759314": "새 브라우저",
+ "88ffb502e5": "마크다운 노트 열기",
+ "629528690b": "새로운 마크다운 노트",
+ "3215fc73e9": "새로운 터미널",
+ "da508bd7f5": "저장",
+ "918c2139f3": "저장하지 않음",
+ "e7bf09d4d4": "취소",
+ "690b6fb98a": "저장되지 않은 변경사항",
+ "bbc177f98f": "활성화",
+ "adc281394d": "닫기",
+ "8cf80db43b": "에이전트가 Orca를 통해 조정할 수 있도록 Orca CLI 및 에이전트 스킬을 설정합니다.",
+ "2a3c5ddf5e": "오케스트레이션 활성화",
+ "d6b563ae24": "편집기 로드 중...",
+ "8b14ba6c17": "새 브라우저 탭",
+ "b085fb58b5": "이 파일에는 저장되지 않은 변경사항이 있습니다.",
+ "5ddc688c52": "'{{value0}}'에 저장되지 않은 변경사항이 있습니다. 닫기 전에 저장하시겠습니까?",
+ "25d7817f79": "터미널"
+ },
+ "FloatingTerminalToggleButton": {
+ "3b04b065b5": "플로팅 워크스페이스 표시",
+ "5785dd9148": "플로팅 워크스페이스 최소화",
+ "bfe7809a70": "{{value0}} 플로팅 워크스페이스({{value1}})"
+ },
+ "FloatingTerminalWindowControls": {
+ "2f6054342c": "최소화",
+ "1bbaa0302f": "플로팅 워크스페이스 최소화",
+ "3f4ca29961": "플로팅 워크스페이스 최대화",
+ "1c79cba25d": "플로팅 워크스페이스 복원",
+ "648352c51f": "플로팅 워크스페이스에서 {{value0}} 열기",
+ "82da3701e7": "{{value0}}에 대한 실행 명령을 작성할 수 없습니다.",
+ "109870e023": "최대화",
+ "b5686fee1e": "복원"
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "AgentCapabilitiesSetupAction": {
+ "b8dc9dd8a2": "설치됨",
+ "1b51644c2d": "에이전트가 데스크톱을 제어하고, 커서를 이동하고, 클릭하고, 모든 앱에서 입력할 수 있도록 하세요.",
+ "362a07517d": "컴퓨터 사용",
+ "5e8fe5a72d": "에이전트가 Orca의 브라우저에 직접 액세스할 수 있도록 하여 페이지를 테스트하고, 스크린샷을 캡처하고, 표시된 내용에 따라 조치를 취할 수 있도록 하세요.",
+ "e638da007a": "에이전트 브라우저 사용",
+ "c61c91e642": "에이전트가 Orca를 통해 조정하여 대규모 다단계 작업을 완료할 수 있도록 하세요.",
+ "ac07f8887f": "에이전트 오케스트레이션",
+ "e9eb197e12": "열린 컴퓨터 사용 권한",
+ "3a59452a67": "리뷰를 위해 스킬 명령을 아래에 복사하여 삽입했습니다.",
+ "c605f51f2b": "기능 설정 준비 완료",
+ "1aa657d8f4": "일부 기능 설정에 주의가 필요합니다.",
+ "c89534cbe9": "CLI 및 스킬 설치"
+ },
+ "AiCommitPrSettingsCard": {
+ "8d4152701a": "예를 들어 올라마는 llama3.1 {{value0}}을 실행합니다.",
+ "9ee54037a4": "사용자 정의 명령",
+ "4b2fc4b80c": "생각하는 노력",
+ "be8917699e": "모델",
+ "4d9b6d84df": "지원되지 않습니다. Claude, Codex 또는 Custom을 선택하세요.",
+ "560d4feb00": "Custom",
+ "29d119fe95": "에이전트",
+ "f9382b48a1": "AI author 활성화",
+ "1c0cb4fabb": "AI author",
+ "bd14e9c42a": "구성되지 않음",
+ "1f9468c5c9": "{{value0}} 지원되지 않음"
+ },
+ "BrowserAnimatedVisual": {
+ "46df009982": "무료 평가판을 시작하세요",
+ "25f15c2219": "찬성",
+ "59ae327405": "기동기",
+ "9e0f530390": "가격",
+ "0ce7c24b4d": "일하고 있는…",
+ "f2034c4930": ">",
+ "6e4616d039": "Claude",
+ "0f8481e1a7": "Claude에게 보내기",
+ "3d2352f94b": "변경사항을 설명하세요…",
+ "d8856b604a": "div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta",
+ "7da6eed7bf": "로컬호스트:3000",
+ "0a2bd01c02": "새 브라우저 탭",
+ "04096318ab": "터미널 1",
+ "eb88125c6f": "✓ 검증됨 — 무료 체험판은 여전히 작동합니다.",
+ "051c97d15a": ".pp-card[data-card=\"starter\"] .pp-cta",
+ "4fa59ca545": "✓ 업데이트됨",
+ "1bec24acc1": "@keyframes browserFlash { 0% { 불투명도: 0; } 20% { 불투명도: 0.85; } 100% { 불투명도: 0; } } @keyframes browserTabIn { from { 불투명도: 0; 변환: 번역Y(-2px); }에서 {불투명도: 1; 변환: 없음; } } @keyframes browserViewIn { from { 불투명도: 0; 변환: 번역Y(4px); }에서 {불투명도: 1; 변환: 없음; } }",
+ "73bbb46073": "/가격",
+ "f39be6ca14": "/가입"
+ },
+ "BrowserUseSkillSetupCard": {
+ "cbc45022d4": "에이전트가 Orca 브라우저에서 페이지를 탐색하고 확인할 수 있습니다.",
+ "d5bb1cd4ba": "Browser Use 스킬"
+ },
+ "ComputerUseAnimatedVisual": {
+ "d8401975b1": "승인됨",
+ "f27676a92c": "상태:",
+ "6804cb356f": "전송됨을 클릭하세요",
+ "1719b28a81": "'승인'을 찾았습니다.",
+ "79445f7512": "내 앱에서 메모 승인",
+ "99a8624bcb": ">",
+ "2adb561b44": "Claude Code 세션이 시작되었습니다.",
+ "94787f01f8": "Claude 코드",
+ "9cddfe96b2": "로컬 앱",
+ "9634d870d1": "승인",
+ "3cc2df3671": "완료",
+ "bdd5312213": "보류 중",
+ "c11dda000b": "승인됨"
+ },
+ "EditorAnimatedVisual": {
+ "7a763daf2f": "이탤릭체",
+ "8521536429": "용감한 ·",
+ "8341391520": "블록용 ·",
+ "3fe42a1da0": "유형",
+ "8268b2376b": "코드 블록",
+ "37fa4948ce": "글머리 기호 목록",
+ "f25687c588": "인용",
+ "abbdeea15d": "기본 블록",
+ "a26a68d30c": "제목 2",
+ "722170663a": "제목 1",
+ "1fb29ad710": "제목",
+ "4426aab46f": "새 타일이 도착하면 문서 색인을 업데이트하세요.",
+ "95f0c3a46f": "새 머신에서 설치 흐름을 연기 테스트합니다.",
+ "22ae7b4d9d": "팀을 위한 간단한 메모 - 배송하기 전에 남은 항목을 정리합니다.",
+ "5a55c00a81": "출시 계획",
+ "218503f9f3": "자동 저장됨",
+ "cda56c5915": "메모 / launch-plan.md",
+ "e16479c1c5": "[데이터-슬래시-메뉴] [데이터-슬래시-행].slash-active { 배경: rgba(24,24,27,0.07); 상자 그림자: 삽입 0 0 0 1px rgba(24,24,27,0.06); } [data-md-active-line][data-role=\"active\"] { 색상: rgb(113 113 122); 글꼴 계열: ui-monospace, SFMono-Regular, Menlo, monospace; 글꼴 크기: 12.5px; } [data-md-active-line][data-role=\"h1\"] { 색상: 상속; 글꼴 계열: 상속; 글꼴 크기: 18px; 글꼴 두께: 700; 문자 간격: -0.01em; 줄 높이: 1.2; 여백 상단: 6px; } [데이터-md-캐럿] { 디스플레이: 인라인 블록; 너비: 1.5px; 높이: 1em; 배경: 현재색상; 수직 정렬: -2px; 여백 왼쪽: 1px; 애니메이션: md-caret-blink 1.05s 단계(1) 무한; } @keyframes md-caret-blink { 0%, 50% { 불투명도: 1 } 51%, 100% { 불투명도: 0 } } @keyframes md-block-in { from { 불투명도: 0; 변환: 번역Y(-2px); }에서 {불투명도: 1; 변환: 없음; } } @keyframes md-cursor-ripple { 0% { 변환: scale(0.4); 불투명도: 0.9; } 100% { 변환: scale(1.4); 불투명도: 0; } } [data-clicking=\"1\"] [data-cursor-ripple] { animation: md-cursor-ripple 460ms 이지아웃 앞으로; }"
+ },
+ "FeatureTourPreview": {
+ "1170621527": ">",
+ "304ad0dfc1": "생각...",
+ "ef8b164dd1": "src/auth 리뷰",
+ "952d3ddd9a": "세션이 시작되었습니다",
+ "771d8881c2": "claude",
+ "6ed43cb0e0": "Dashboard.spec.ts",
+ "24fedd5a52": "login.spec.ts",
+ "8279e9d95b": "12개 테스트 실행",
+ "6218a9014d": "pnpm 극작가 테스트",
+ "04d54d50ec": "오카 · zsh",
+ "1aa8a9a24a": "분할 가능한 터미널",
+ "2a7cfc82c8": "GH #1842와 연결됨",
+ "3822d8d14b": "수정/작업 트리 선택기-잘림",
+ "d54aefe09e": "LIN-329",
+ "40bbd92ef4": "시작",
+ "c1f28c03b2": "작업 트리 선택 도구가 잘립니다.",
+ "fc0cc0b267": "GH #1842",
+ "0688842445": "GH #1799",
+ "bee6b4088d": "GitHub 및 Linear 작업",
+ "5171768676": "에이전트 3개 조율",
+ "cebc7769cd": "인증 흐름 재설계",
+ "e44269e97d": "에이전트 오케스트레이션",
+ "ec4a73f5e6": "PR 3/3",
+ "cfdfd4d6b4": "PR 2/3",
+ "b1f17bcc74": "PR 1/3",
+ "e38112b289": "청구 웹훅 리팩터링",
+ "9c812e0d7c": "CI 파이프라인 속도 향상",
+ "3c4adfd821": "로그인 경쟁 조건 수정",
+ "56a0271428": "격리된 워크스페이스",
+ "ef737dcee1": "GitHub 및 Linear 작업",
+ "ac51c061e2": "codex"
+ },
+ "FeatureWallBody": {
+ "25ec5356d6": "설정"
+ },
+ "FeatureWallModal": {
+ "33dca8bbbe": "Orca에 대한 짧은 워크플로별 둘러보기입니다.",
+ "3567e147c8": "Orca에 대해 알아보세요"
+ },
+ "FeatureWallPreview": {
+ "a666384798": "또한 이 워크플로우에서는"
+ },
+ "FeatureWallRail": {
+ "69ea857689": "완전한",
+ "7593d15f94": "워크플로"
+ },
+ "FeatureWallSetupChecklist": {
+ "1a6a7d6c80": "설정",
+ "713cc529a5": "이정표",
+ "b1f1981c5e": "작업 보기",
+ "505f4c910c": "분할 터미널",
+ "0235b268b2": "아직 완료되지 않음",
+ "13294d3405": "완료"
+ },
+ "FeatureWallSetupWorkflowActions": {
+ "486c2f4d8d": "먼저 git 프로젝트를 추가한 다음 해당 저장소에 대한 설정 스크립트를 구성하세요.",
+ "00078a6134": "설정에서 보기",
+ "14327073cc": "저장",
+ "88469e926b": "설정 스크립트",
+ "5c5b65044e": "pnpm 설치",
+ "a7463915b6": "설정 스크립트를 저장하지 못했습니다.",
+ "6299297dac": "설정 스크립트가 저장되었습니다.",
+ "f0bbf7da77": "사용해 보세요",
+ "364430eb3d": ", 또는 창을 마우스 오른쪽 버튼으로 클릭하고 분할을 선택합니다. 다음을 사용하여 활성 창을 닫습니다.",
+ "29e64f111d": "아니면 아래로",
+ "971775f639": "오른쪽으로 분할",
+ "522cce9e33": "프로젝트 추가"
+ },
+ "FeatureWallTourPanel": {
+ "af7d622f6f": "선택 사항"
+ },
+ "KeepAwakeCard": {
+ "209713d3c7": "선택 사항"
+ },
+ "ReviewNotesAnimatedVisual": {
+ "5dbd27c4c2": "Codex",
+ "09094f25e2": "Claude 코드",
+ "294aaff104": "메모 보내기",
+ "ea4e45b71b": "메모 추가",
+ "271ea0cbf3": "취소",
+ "a7a89d8f94": "선",
+ "5cb213f967": "AI 노트",
+ "1eee3a397e": "src/server/ migration.ts (차이점)"
+ },
+ "ReviewPRViewAnimatedVisual": {
+ "7c2808ecff": "병합 전 잘림.",
+ "c2062da7ec": "표준 오류",
+ "6f4c2d7cb7": "다음에 대한 적용 케이스를 추가하세요.",
+ "71828fba75": "진단 페이로드에 실패한 명령을 포함할 수 있나요?",
+ "fb1a856b6d": "열림",
+ "7a8b896e11": "댓글",
+ "ca36f7b27c": "통과",
+ "25f6838e43": "lint",
+ "2ef0b97954": "타이프체크",
+ "8ed213397c": "달리기",
+ "d340c052fb": "검증",
+ "9a097cae12": "1개 대기 중",
+ "2f37142229": "스쿼시 및 병합",
+ "0aab7ab84a": "로컬 진단 오류 추적 추가",
+ "dfe313e0c9": "열림",
+ "6e3f5223c5": "탐침",
+ "ab2901bce6": "검사",
+ "d7f80060ca": "소스 제어",
+ "8e715588e4": "검색"
+ },
+ "ReviewShipAnimatedVisual": {
+ "4d99496b8c": "PR 작성",
+ "62544e0852": "취소",
+ "bcd5cae3c4": "PR 설명",
+ "3774b80eae": "설명",
+ "07da9245cc": "PR 제목",
+ "54a093c52d": "제목",
+ "3b9b96d6a6": "기본",
+ "ce7d5d3a18": "기본 브랜치",
+ "e4473d438f": "AI로 생성",
+ "c30cd930ff": "PR 생성",
+ "ea0100dd15": "모두 보기",
+ "e725000cd7": "변경 사항",
+ "a079083a6c": "저지르다",
+ "7347fa5839": "메시지",
+ "d1a7f15876": "AI로 커밋 메시지 생성",
+ "cd8a3a39d7": "앞으로 3개의 커밋"
+ },
+ "TasksAnimatedVisual": {
+ "efba6f77eb": "이슈 # 읽는 중",
+ "b68c92fbdc": "워크스페이스 시작",
+ "4331c4d0f8": "열기",
+ "b13375617e": "작업 트리 선택기가 이름을 자릅니다.",
+ "72f9e516a3": "누르는 것",
+ "fe47c9c9e8": "워크스페이스 준비",
+ "61ffda7601": "워크스페이스 만들기"
+ },
+ "WorkbenchAnimatedVisual": {
+ "633a91e358": "생각…",
+ "932c4b3a97": ">",
+ "ca2cfbf188": "터미널을 아래로 분할",
+ "e370fa8c2b": "터미널 오른쪽 분할",
+ "b85eab49dd": "src/auth/session.ts",
+ "99f5224f1e": "편집",
+ "0d93c298a7": "src/auth 던지기",
+ "17cfdc3344": "그렙",
+ "9923847785": "읽다",
+ "c0eb94125e": "인증 예외 사례 리뷰",
+ "431ca9842a": "Claude Code 세션이 시작되었습니다.",
+ "000106adfe": "claude",
+ "7d9f1d5f7d": "(0.8초)",
+ "944199e54a": "› 장바구니 전체 업데이트",
+ "623881d72e": "checkout.spec.ts",
+ "5c5cbd783f": "(1.2초)",
+ "3261c6853b": "› 로그인 가능",
+ "defe550fe2": "login.spec.ts",
+ "0b20782e0f": "4명의 작업자를 사용하여 12개의 테스트 실행",
+ "4371cc9931": "pnpm 극작가 테스트",
+ "16877e038d": "쪼개진다",
+ "a2b114dad0": "오른쪽으로 쪼개짐 ·",
+ "0bc9ad0cd1": "동일한 창:",
+ "fc84f17fe7": "Codex 세션이 시작되었습니다"
+ },
+ "agent": {
+ "capability": {
+ "setup": {
+ "status": {
+ "8eccfcb314": "설치됨",
+ "21d4f79c93": "CLI 및 스킬 설치를 클릭하여 macOS 액세스 설정을 엽니다.",
+ "5c9293e51a": "앱 액세스 확인 중",
+ "aae94eeb52": "CLI 및 스킬 설치를 클릭하세요.",
+ "aa8e143a2f": "설치를 확인할 수 없습니다.",
+ "9b33e7fb13": "설치 확인 중",
+ "4c8e1f92a7": "이 Mac에서 Orca Desktop을 여세요",
+ "6d2b0a84e1": "이 빌드에서는 사용할 수 없습니다"
+ }
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "usage": {
+ "tracking": {
+ "b94ec70eda": "추적이 설정되지 않았습니다.",
+ "cc39a87288": "연결됨 · 시스템 기본값",
+ "00087eecb2": "연결됨 · {{value0}}"
+ }
+ }
+ }
+ },
+ "review": {
+ "animated": {
+ "visual": {
+ "shared": {
+ "e7894927a2": "Codex",
+ "9deecb021c": "Claude"
+ },
+ "notes": {
+ "styles": {
+ "db6691aa0a": ".ravs-window { position: absolute; inset: 0; --ravs-soft-surface: color-mix(in srgb, var(--foreground) 2%, var(--card)); --ravs-soft-fill: color-mix(in srgb, var(--foreground) 6%, transparent); --ravs-panel-border: color-mix(in srgb, var(--foreground) 18%, var(--border)); --ravs-emphasis-border: color-mix(in srgb, var(--foreground) 44%, var(--border)); --ravs-floating-shadow: 0 14px 30px rgb(0 0 0 / 0.22), 0 2px 6px rgb(0 0 0 / 0.12); background: var(--card); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 1px 2px rgb(0 0 0 / 0.08); } .ravs-difftoolbar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-bottom: 1px solid var(--border); background: var(--ravs-soft-surface); font-size: 11px; color: var(--muted-foreground); } .ravs-diff-path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground); } .ravs-ai-chip { margin-left: auto; display: inline-flex; align-items: stretch; overflow: hidden; border-radius: 6px; border: 1px solid var(--border); background: var(--ravs-soft-surface); opacity: 0; transform: translateY(-2px); transition: opacity 320ms ease, transform 320ms ease; } .ravs-ai-chip.is-visible { opacity: 1; transform: none; } .ravs-ai-chip .ravs-count-btn, .ravs-ai-chip .ravs-send-btn { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; font-size: 11px; color: var(--muted-foreground); background: transparent; line-height: 1; } .ravs-ai-chip .ravs-count-btn { border-right: 1px solid var(--border); } .ravs-ai-chip .ravs-send-btn { padding: 3px 7px; position: relative; } .ravs-send-glow { position: absolute; inset: 0; background: rgba(34, 197, 94, 0.18); opacity: 0; transition: opacity 280ms ease; pointer-events: none; } .ravs-ai-chip .ravs-send-btn.is-flash .ravs-send-glow { opacity: 1; } .ravs-count-num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground); font-weight: 600; } .ravs-diffbody { flex: 1; min-height: 0; position: relative; background: var(--editor-surface, var(--card)); } .ravs-diffscroll { position: absolute; inset: 0; overflow: hidden; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; line-height: 1.55; color: var(--foreground); padding: 4px 0 8px; transition: opacity 240ms ease; } .ravs-diffscroll.is-hidden { opacity: 0; pointer-events: none; } .ravs-term { position: absolute; inset: 0; background: var(--editor-surface, var(--card)); color: var(--foreground); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 1.45; overflow: hidden; display: flex; flex-direction: column; opacity: 0; pointer-events: none; transition: opacity 240ms ease; z-index: 4; } .ravs-term.is-visible { opacity: 1; } .ravs-term-body { flex: 1; min-height: 0; padding: 10px 12px; overflow: hidden; display: flex; flex-direction: column; gap: 6px; } .ravs-term-line { white-space: pre-wrap; word-break: break-word; line-height: 1.45; } .ravs-term-muted { color: var(--muted-foreground); } .ravs-term-glyph { color: rgb(217 119 6); margin-right: 6px; } .ravs-term-check { color: rgb(16 185 129); font-weight: 700; margin-right: 6px; } .ravs-term-spinner { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 999px; border: 1.5px solid color-mix(in srgb, var(--foreground) 20%, transparent); border-top-color: var(--foreground); vertical-align: -1px; animation: ravs-term-spin 0.9s linear infinite; } @keyframes ravs-term-spin { to { transform: rotate(360deg) } } .ravs-hunk-header { display: grid; grid-template-columns: 36px 36px 16px minmax(0,1fr); align-items: center; padding: 1px 8px 1px 0; background: rgba(99, 102, 241, 0.06); color: var(--muted-foreground); font-size: 10.5px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); } .ravs-hunk-header .ravs-text { grid-column: 4 / -1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: rgb(99 102 241); font-size: 10.5px; } .ravs-diff-line { display: grid; grid-template-columns: 36px 36px 16px minmax(0,1fr); align-items: stretch; position: relative; } .ravs-ln { text-align: right; padding: 0 6px 0 0; color: var(--muted-foreground); font-size: 10.5px; user-select: none; opacity: 0.85; } .ravs-marker { text-align: center; color: var(--muted-foreground); font-weight: 700; opacity: 0.7; } .ravs-text-cell { padding-right: 8px; white-space: pre; overflow: hidden; } .ravs-tok-kw { color: #a855f7; } .ravs-tok-id { color: #2563eb; } .ravs-tok-str { color: #16a34a; } .ravs-diff-line.is-add { background: color-mix(in srgb, var(--git-decoration-added) 14%, transparent); } .ravs-diff-line.is-add .ravs-marker { color: color-mix(in srgb, var(--git-decoration-added) 72%, transparent); opacity: 1; } .ravs-diff-line.is-rem { background: color-mix(in srgb, var(--git-decoration-deleted) 14%, transparent); } .ravs-diff-line.is-rem .ravs-marker { color: color-mix(in srgb, var(--git-decoration-deleted) 72%, transparent); opacity: 1; } .ravs-add-note-btn { position: absolute; left: 4px; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 1px solid color-mix(in srgb, currentColor 22%, var(--border)); border-radius: 4px; background: var(--ravs-soft-fill); color: var(--foreground); z-index: 5; opacity: 0; box-shadow: 0 1px 2px rgb(0 0 0 / 0.14); pointer-events: none; transition: opacity 160ms ease; } .ravs-add-note-btn.is-visible { opacity: 1; } .ravs-note-row { padding: 4px 8px 4px 0; max-height: 0; overflow: hidden; opacity: 0; transition: max-height 360ms cubic-bezier(.4,0,.2,1), opacity 280ms ease 60ms, padding 360ms cubic-bezier(.4,0,.2,1); } .ravs-note-row.is-visible { max-height: 90px; opacity: 1; } .ravs-note-card { margin: 0 12px; position: relative; border: 1px solid var(--ravs-panel-border); border-left: 3px solid var(--ravs-emphasis-border); border-radius: 6px; background-color: var(--card); padding: 5px 8px 5px 10px; box-shadow: 0 1px 2px rgb(0 0 0 / 0.16); } .ravs-note-meta { font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-foreground); } .ravs-note-body { font-size: 11.5px; color: var(--foreground); line-height: 1.35; margin-top: 2px; } .ravs-popover { position: absolute; left: 12px; right: 12px; max-width: none; z-index: 20; padding: 8px 10px; border: 1px solid var(--ravs-panel-border); border-left: 3px solid var(--ravs-emphasis-border); border-radius: 6px; background-color: var(--card); color: var(--foreground); box-shadow: var(--ravs-floating-shadow); display: flex; flex-direction: column; gap: 6px; opacity: 0; transform: translateY(-4px) scale(0.985); pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; } .ravs-popover.is-visible { opacity: 1; transform: none; pointer-events: auto; } .ravs-pop-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-foreground); } .ravs-pop-input { min-height: 38px; max-height: 80px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--editor-surface, var(--card)); font-size: 12px; line-height: 1.4; color: var(--foreground); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pop-footer { display: flex; justify-content: flex-end; gap: 6px; } .ravs-pop-btn { font-size: 11px; font-weight: 500; padding: 4px 9px; border-radius: 5px; line-height: 1; border: 1px solid transparent; display: inline-flex; align-items: center; gap: 5px; } .ravs-pop-btn.is-cancel { color: var(--muted-foreground); background: transparent; } .ravs-pop-btn.is-add { color: var(--primary-foreground); background: var(--primary); } .ravs-send-menu { position: absolute; z-index: 30; right: 8px; top: 6px; min-width: 200px; background: var(--popover); color: var(--popover-foreground); border: 1px solid var(--border); border-radius: 8px; padding: 4px; box-shadow: var(--ravs-floating-shadow); opacity: 0; transform: translateY(-4px) scale(0.985); pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; } .ravs-send-menu.is-visible { opacity: 1; transform: none; pointer-events: auto; } .ravs-menu-section { padding: 4px 8px 2px; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-foreground); } .ravs-menu-row { display: grid; grid-template-columns: 16px minmax(0,1fr); align-items: center; gap: 8px; padding: 6px 8px; border-radius: 5px; font-size: 12px; color: var(--popover-foreground); } .ravs-menu-row.is-hot { background: var(--accent); box-shadow: inset 0 0 0 1px var(--border); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid color-mix(in srgb, var(--foreground) 52%, transparent); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }"
+ }
+ },
+ "pr": {
+ "view": {
+ "styles": {
+ "fc9a23c83d": ".ravpr-stage { position: absolute; inset: 0; overflow: hidden; } .ravpr-stack { position: absolute; inset: 0; display: flex; justify-content: flex-end; padding: 4px 34px 4px 2px; overflow: hidden; } .ravpr-sidebar, .ravpr-card { position: absolute; top: 4px; right: 2px; width: 464px; height: calc(100% - 8px); background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; color: var(--foreground, #18181b); overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } .ravpr-sidebar { opacity: 0; transition: opacity 220ms ease; } .ravpr-sidebar.is-visible { opacity: 1; } .ravpr-sidebar.is-hiding { opacity: 0; } .ravpr-card { display: flex; flex-direction: column; min-width: 0; opacity: 0; transition: opacity 260ms ease; } .ravpr-card.is-visible { opacity: 1; } .ravpr-tabs { position: relative; display: flex; align-items: center; gap: 14px; height: 36px; padding: 0 14px; background: rgba(24,24,27,0.015); color: var(--muted-foreground, #71717a); } .ravpr-tab { position: relative; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted-foreground, #71717a); } .ravpr-tab.is-active, .ravpr-tab.is-hovered { color: var(--foreground, #18181b); } .ravpr-tab.is-active::after { content: ''; position: absolute; left: -5px; right: -5px; bottom: -10px; height: 1px; background: var(--foreground, #18181b); } .ravpr-tooltip { position: absolute; top: 34px; left: 106px; z-index: 6; padding: 7px 11px; border-radius: 8px; background: var(--card, #fff); color: var(--foreground, #18181b); font-size: 12px; line-height: 1; box-shadow: 0 8px 22px rgba(0,0,0,0.22); opacity: 0; transform: translateY(-3px); pointer-events: none; transition: opacity 160ms ease, transform 160ms ease; } .ravpr-tooltip.is-visible { opacity: 1; transform: translateY(0); } .ravpr-explorer { padding: 10px 12px 12px; } .ravpr-heading { color: var(--muted-foreground, #71717a); font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; } .ravpr-file-list { margin-top: 8px; display: flex; flex-direction: column; gap: 2px; } .ravpr-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 22px; align-items: center; gap: 8px; min-height: 28px; padding: 4px 6px; border-radius: 6px; } .ravpr-file.is-active { background: rgba(24,24,27,0.06); box-shadow: inset 0 0 0 1px rgba(24,24,27,0.06); } .ravpr-file-icon { width: 12px; height: 12px; border-radius: 3px; background: rgba(24,24,27,0.14); } .ravpr-file-name { height: 8px; border-radius: 999px; background: rgba(24,24,27,0.14); } .ravpr-file-status { width: 14px; height: 8px; border-radius: 999px; background: rgba(24,24,27,0.12); } .ravpr-body { padding: 10px 12px 18px; display: flex; flex-direction: column; gap: 5px; min-height: 0; } .ravpr-number-row { display: flex; align-items: center; gap: 7px; } .ravpr-number { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; font-weight: 700; } .ravpr-open { display: inline-flex; align-items: center; justify-content: center; height: 18px; padding: 0 7px; border-radius: 5px; background: rgba(16,185,129,0.10); border: 1px solid rgba(16,185,129,0.28); color: rgb(4 120 87); font-size: 9px; font-weight: 700; line-height: 1; } .ravpr-title { font-size: 12px; font-weight: 600; line-height: 1.35; color: var(--foreground, #18181b); margin-bottom: 2px; } .ravpr-merge { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; min-height: 30px; flex: 0 0 30px; border-radius: 7px; background: rgb(22 163 74); color: #fff; font-size: 11.5px; font-weight: 700; margin-bottom: 2px; box-shadow: 0 1px 2px rgba(22,163,74,0.18); transition: box-shadow 220ms ease, filter 220ms ease; } .ravpr-merge.is-ready { box-shadow: 0 0 0 3px rgba(34,197,94,0.22), 0 1px 2px rgba(22,163,74,0.18); } .ravpr-section-row, .ravpr-check-row { display: grid; grid-template-columns: 18px minmax(0,1fr) auto; align-items: center; gap: 7px; padding: 5px 0; font-size: 11.5px; color: var(--foreground, #18181b); } .ravpr-check-row { padding: 5px 7px; font-size: 10.5px; } .ravpr-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ravpr-meta, .ravpr-check-state { color: var(--muted-foreground, #71717a); font-size: 10.5px; } .ravpr-check-state { font-size: 10px; } .ravpr-ring { display: inline-block; width: 14px; height: 14px; border-radius: 999px; border: 2px solid rgba(245,158,11,0.35); border-top-color: rgb(245 158 11); animation: ravpr-spin 1.1s linear infinite; } .ravpr-check { width: 15px; height: 15px; border-radius: 999px; display: none; align-items: center; justify-content: center; background: rgba(34,197,94,0.14); color: rgb(22 163 74); } .ravpr-section-row.is-done .ravpr-ring, .ravpr-check-row.is-done .ravpr-ring { display: none; } .ravpr-section-row.is-done .ravpr-check, .ravpr-check-row.is-done .ravpr-check { display: inline-flex; } .ravpr-reveal { display: flex; flex-direction: column; gap: 3px; opacity: 0; transform: translateY(4px); transition: opacity 260ms ease, transform 260ms ease; pointer-events: none; } .ravpr-reveal.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; } .ravpr-check-list, .ravpr-comment-list { display: flex; flex-direction: column; gap: 4px; min-height: 0; } .ravpr-comment-card { border: 1px solid var(--border); border-radius: 8px; background: var(--card, #fff); overflow: hidden; opacity: 0; transform: translateY(4px); transition: opacity 260ms ease, transform 260ms ease; } .ravpr-comment-card.is-visible { opacity: 1; transform: translateY(0); } .ravpr-comment-head { display: grid; grid-template-columns: 18px minmax(0,1fr) auto; align-items: center; gap: 7px; padding: 5px 7px; background: rgba(24,24,27,0.015); } .ravpr-avatar { width: 16px; height: 16px; border-radius: 999px; background: rgba(24,24,27,0.16); } .ravpr-author { width: 78px; height: 8px; border-radius: 999px; background: rgba(24,24,27,0.18); } .ravpr-comment-path { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 9.5px; color: var(--muted-foreground, #71717a); } .ravpr-comment-body { padding: 5px 7px 6px; font-size: 11px; line-height: 1.32; color: var(--foreground, #18181b); } .ravpr-comment-body code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; padding: 1px 4px; border-radius: 4px; background: rgba(24,24,27,0.06); } .ravpr-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravpr-cursor.is-visible { opacity: 1; } .ravpr-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravpr-cursor.is-clicking .ravpr-ripple { animation: ravpr-ripple 460ms ease-out forwards; } @keyframes ravpr-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } @keyframes ravpr-spin { to { transform: rotate(360deg); } }"
+ }
+ }
+ },
+ "ship": {
+ "styles": {
+ "90cdcd2ecc": ".ravs-ship-root { position: absolute; inset: 0; } .ravs-ship-stack { position: absolute; inset: 0; display: grid; grid-template-columns: 232px minmax(0,1fr); gap: 14px; padding: 4px 2px; /* Why: cards size to their content rather than stretch to the parent's full height, so the two cards don't show empty space below their content. */ align-items: start; } /* Source Control mini-sidebar — ahead-count header, commit textarea + split Commit button, then a CHANGES section with file rows. The file rows are the surface the \"reading\" pulse animates over. */ .ravs-sc-card { display: flex; flex-direction: column; background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } /* Both card headers share the same fixed height so the SC card and PR dialog align across the top edge regardless of header content. */ .ravs-sc-header, .ravs-pr-head { height: 36px; box-sizing: border-box; } .ravs-sc-header { display: flex; align-items: center; justify-content: space-between; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-sc-ahead { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } .ravs-sc-ahead svg { color: var(--muted-foreground, #71717a); } .ravs-sc-commit-area { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; } .ravs-sc-textarea { position: relative; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); padding: 6px 26px 6px 8px; min-height: 56px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-sc-textarea .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-sc-sparkle { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; transition: color 160ms ease, background 160ms ease; } .ravs-sc-sparkle.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-sc-split { display: flex; align-items: stretch; } /* Why: Commit + Create PR are surrounding chrome — the violet AI affordances are the focal points. Render them as quiet secondary buttons so they don't compete with the sparkle/scan signals. */ .ravs-sc-split .ravs-primary { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 5px 10px; background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); font-size: 11px; font-weight: 500; border-radius: 6px 0 0 6px; border: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } .ravs-sc-split .ravs-chev { display: inline-flex; align-items: center; justify-content: center; width: 22px; background: var(--secondary, #f5f5f5); color: var(--muted-foreground, #71717a); border-radius: 0 6px 6px 0; border: 1px solid var(--border); border-left: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } /* Why: when AI has filled the commit message, tint the Commit button green to signal \"ready to commit\". Uses the same success-green family as the PR flash so the two beats rhyme. Mix is intentionally strong (~28%) — at 14% it disappeared next to the violet sparkle and PR flash, so users only saw the PR change color. */ .ravs-sc-split.is-ready .ravs-primary, .ravs-sc-split.is-ready .ravs-chev { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); transition: background 220ms ease, border-color 220ms ease, color 220ms ease; } .ravs-sc-split.is-ready .ravs-chev { border-left-color: rgba(34, 197, 94, 0.55); } .ravs-sc-changes-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-sc-changes-count { color: var(--foreground, #18181b); font-weight: 600; margin-left: 2px; } .ravs-sc-view-all { font-size: 10px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted-foreground, #71717a); } .ravs-sc-files { display: flex; flex-direction: column; padding: 2px 6px 8px; flex: 1; min-height: 0; overflow: hidden; } .ravs-sc-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 12px; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 4px; font-size: 11px; line-height: 1.35; color: var(--foreground, #18181b); position: relative; transition: background 220ms ease; } .ravs-sc-ficon { color: rgb(180 83 9); display: inline-flex; } .ravs-sc-fname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ravs-sc-fmark { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; text-align: right; color: rgb(180 83 9); } .ravs-sc-file.is-reading { background: color-mix(in srgb, rgb(139 92 246) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, rgb(139 92 246) 28%, transparent); } /* PR dialog — matches the .ravs-sc-card chrome (same border, radius, elevation) so the two cards read as one design language. */ .ravs-pr-dialog { background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 1px 2px rgba(24,24,27,0.04); display: flex; flex-direction: column; min-width: 0; overflow: hidden; } .ravs-pr-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-pr-title-text { font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } /* Icon-only AI-assist chip — mirrors .ravs-sc-sparkle so the affordance reads identically across both cards. */ .ravs-pr-gen-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; border: 0; cursor: pointer; transition: color 160ms ease, background 160ms ease; } .ravs-pr-gen-btn:hover { background: rgba(24,24,27,0.06); color: var(--foreground, #18181b); } .ravs-pr-gen-btn.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-pr-body { display: flex; flex-direction: column; gap: 8px; padding: 10px; } .ravs-pr-field { display: flex; flex-direction: column; gap: 4px; } .ravs-pr-field-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-pr-base { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 6px; font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground, #18181b); background: var(--editor-surface, var(--card)); align-self: flex-start; } .ravs-pr-base svg { color: var(--muted-foreground, #71717a); } .ravs-pr-input { position: relative; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); min-height: 28px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pr-input.is-body { min-height: 50px; font-size: 11px; line-height: 1.4; } .ravs-pr-input .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-pr-footer { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 2px; } .ravs-pr-btn { font-size: 11px; font-weight: 500; padding: 5px 10px; border-radius: 6px; line-height: 1; border: 1px solid transparent; outline: none; } .ravs-pr-btn:focus, .ravs-pr-btn:focus-visible { outline: none; } /* Cancel reads as a quiet ghost button so it doesn't compete with the affirmative Create PR action. */ .ravs-pr-btn.is-outline { background: transparent; color: var(--muted-foreground, #71717a); border-color: transparent; } .ravs-pr-btn.is-outline:hover { background: rgba(24,24,27,0.05); color: var(--foreground, #18181b); } /* Quiet secondary fill — see the .ravs-sc-split note above. The flash ring still uses success-green so the \"PR created\" beat reads. The Create-PR button is slightly larger than Cancel so the affirmative action remains the bigger target. */ .ravs-pr-btn.is-solid { background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); border-color: var(--border); font-size: 12px; padding: 7px 14px; transition: background 220ms ease, border-color 220ms ease, color 220ms ease, box-shadow 220ms ease; } .ravs-pr-btn.is-solid.is-ready { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); } .ravs-pr-btn.is-solid.is-flash { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.30); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }"
+ }
+ }
+ }
+ },
+ "notes": {
+ "diff": {
+ "rows": {
+ "f621c734f8": "참고 · 선"
+ }
+ }
+ }
+ },
+ "agents": {
+ "orchestration": {
+ "OrchestrationPage": {
+ "30b509a467": "하위 2명",
+ "862605d066": "2개의 하위 워크스페이스"
+ },
+ "StatusesPage": {
+ "2f549fc0ba": "src/auth/session.test.ts",
+ "139e3d7458": "업데이트됨",
+ "7b26349cb2": "pnpm 최신 마이그레이션",
+ "78f0318ac1": "달리고 싶다",
+ "79971d1539": "인증 흐름 재설계"
+ },
+ "UsageAccountsCard": {
+ "6986b36708": "표면 금리 제한 및 스왑 계정이 인라인으로 제공됩니다.",
+ "d90d2e1f6d": "세션 및 주간 사용량을 추적합니다.",
+ "8919321417": "Codex 로그인에 실패했습니다.",
+ "c7b90c140b": "Codex 계정이 추가되었습니다.",
+ "4e71d72912": "Claude 로그인에 실패했습니다.",
+ "9ddeb558f9": "Claude 계정이 추가되었습니다.",
+ "29d0653961": "로그인",
+ "945865332e": "로그인"
+ },
+ "UsagePage": {
+ "64265cb295": "71% 5시간",
+ "be5a165875": "다음으로 전환",
+ "277a9c65a9": "Codex 계정",
+ "4dce5ca3aa": "4일 3시간 후에 재설정됩니다.",
+ "05ce4ecdd3": "62% 남음",
+ "0470aaed99": "주간",
+ "f421abf962": "세션",
+ "5e45fb1238": "1분 전에 업데이트됨",
+ "6a4b1d3c38": "Codex"
+ },
+ "orchestration": {
+ "cards": {
+ "da6f1f97c9": "일하고 있는"
+ }
+ }
+ }
+ },
+ "FeatureTourWorkspaceCard": {
+ "a23ed9da7f": "codex",
+ "2f33dc932b": "claude",
+ "9220794f6a": "일하고 있는"
+ },
+ "ReviewAnimatedVisual": {
+ "8df4d52b68": "미리보기",
+ "8ab622e4d6": "메모"
+ }
+ },
+ "tips": {
+ "CliFeatureTipVisual": {
+ "badb4fc342": ">",
+ "22e62f3bab": "Claude Code 세션이 시작되었습니다."
+ },
+ "CliSkillSetupTerminal": {
+ "1953e90447": "Enter를 눌러 에이전트에 대한 Orca CLI 오케스트레이션 스킬을 설치하십시오.",
+ "43b60ec5c3": "Orca CLI 및 오케스트레이션 스킬 설치 터미널",
+ "84e9576dac": "스킬 설정",
+ "5c3aee22c0": "명령 복사",
+ "5eca672aac": "스킬 설치 명령어 복사",
+ "6ff813fc1d": "스킬 명령어 복사에 실패했습니다.",
+ "b8ad063571": "스킬 설치 명령어를 복사했습니다."
+ },
+ "CmdJPaletteTipDialog": {
+ "c0bb9f869b": "설정 → 바로가기",
+ "8241897205": "언제든지 바로가기를 다시 바인딩할 수 있습니다."
+ },
+ "FeatureTipActions": {
+ "eb04abece8": "어쩌면 나중에"
+ },
+ "FeatureTipsModal": {
+ "c169298e4d": "완료",
+ "3c6c478462": "X가 끝나면 리뷰 작업을 보냅니다.”",
+ "298301b7a0": "작업 트리",
+ "864e2db28f": "“에이전트가 들어오면",
+ "7fc6f02099": "각각에 대한 PR을 작성합니다.”",
+ "27c567a89c": "작업 트리",
+ "55846c7f95": "“이 PR을 두 개로 나누어",
+ "4795ac2d4a": "다음과 같이 질문해 보세요.",
+ "53905bd076": "개발 미리보기: 스킬 설정 터미널 열기.",
+ "1da82af45b": "Orca CLI에 주의가 필요합니다",
+ "ce13a742d0": "PATH에 'orca'를 등록했습니다.",
+ "d1a86c7eb5": "설정을 열어 CLI 설정을 완료하세요."
+ },
+ "CmdJPaletteFeatureTipVisual": {
+ "ab94e16d44": "작업 트리 \"{{value0}}\" 만들기",
+ "d20ccf1e61": "완료",
+ "379d776971": "타자",
+ "0418f9becc": "열림"
+ }
+ }
+ },
+ "error": {
+ "boundaries": {
+ "RecoverableRenderErrorBoundary": {
+ "55001880db": "다시 시도",
+ "34a189ae0f": "앱의 나머지 부분은 아직 실행 중입니다. 이 표면을 다시 시도하거나 다른 곳으로 전환했다가 다시 돌아오세요.",
+ "ab855c11f4": "Orca의 이 부분에 오류가 발생했습니다."
+ }
+ }
+ },
+ "emulator": {
+ "pane": {
+ "EmulatorPane": {
+ "59b08fa031": "연결된 에뮬레이터가 없습니다."
+ },
+ "emulator": {
+ "device": {
+ "frame": {
+ "9406c15775": "에뮬레이터 화면",
+ "8f25ffaf8a": "에뮬레이터 화면, 키보드 캡처. Esc를 눌러 해제하세요.",
+ "0022420df0": "핸드폰"
+ }
+ },
+ "pane": {
+ "toolbar": {
+ "06e10d7356": "에뮬레이터 종료",
+ "e7a0d1897e": "집",
+ "6bd8dff42a": "회전",
+ "3d836b879c": "에뮬레이터 선택",
+ "81b3571a07": "연결",
+ "868c0f2938": "일하고 있는…"
+ }
+ },
+ "screen": {
+ "stream": {
+ "content": {
+ "8b1a0d8694": "에뮬레이터 미리보기",
+ "36841af608": "스트림 연결이 끊어졌습니다.",
+ "5f818f12ab": "에뮬레이터 연결 중…",
+ "5ee64cd44e": "에뮬레이터 화면"
+ }
+ }
+ },
+ "unavailable": {
+ "pane": {
+ "f630b9ca9f": "모바일 에뮬레이터를 사용하려면 Xcode 및 iOS 시뮬레이터 런타임이 설치된 Mac이 필요합니다. Linux 또는 Windows에서는 물리적 장치 또는 원격 Mac 빌드 호스트를 사용합니다.",
+ "b2c268a0b9": "모바일 에뮬레이터는 macOS 전용입니다."
+ }
+ }
+ },
+ "use": {
+ "emulator": {
+ "frame": {
+ "stream": {
+ "f1c0179002": "스트림이 프레임을 생성하지 않습니다."
+ }
+ }
+ }
+ }
+ }
+ },
+ "editor": {
+ "ChangesModeView": {
+ "ef25ae2d09": "커밋되지 않은 변경 사항이 없습니다.",
+ "052c184f24": "이 파일에는 텍스트 비교를 사용할 수 없습니다.",
+ "7dffb0f563": "바이너리 파일",
+ "54e0035b15": "차이점 로드 중..."
+ },
+ "CodeBlockCopyButton": {
+ "28921f5bf9": "복사됨",
+ "1f9f4def45": "코드 복사"
+ },
+ "CombinedDiffFileTree": {
+ "f984289373": "현재 필터와 일치하는 파일이 없습니다.",
+ "eafe1aeb53": "필터 재설정",
+ "be119cb9d1": "본 파일",
+ "c00020f081": "파일 확장자",
+ "cd0e0ed79e": "차이점 파일 필터링",
+ "4cc7b83ffe": "파일 필터링...",
+ "21783df79f": "파일 트리 축소",
+ "481e63ca52": "파일",
+ "d5ac717d65": "어느 편도 아닌"
+ },
+ "CombinedDiffViewer": {
+ "35cc27aeb2": "소스 제어에서",
+ "e3b9a6ce02": "더",
+ "1da745c551": "전송된",
+ "84898c548d": "지우기",
+ "88b70d0ef5": "복사",
+ "bb84b4c374": "AI 노트",
+ "948a5fd6c8": "메모 지우기",
+ "0f806a2ab1": "취소",
+ "80a286d8f5": "이 작업 트리에서?",
+ "7e7ca60816": "변경된 파일",
+ "b6c3b84476": "파일 트리 표시",
+ "39f8007549": "충돌 리뷰",
+ "39e73e7181": "이 차이점 보기에서 제외되었습니다.",
+ "689b99f8ad": "미해결 충돌",
+ "820ec01f24": "충돌하는 파일은 별도로 리뷰됩니다.",
+ "fd8892b120": "표시할 변경사항이 없습니다.",
+ "eb5f40e49c": "일반적인 양방향 diff 파이프라인은 충돌로부터 안전하지 않기 때문에 이 diff 보기는 해결되지 않은 충돌을 제외합니다.",
+ "45cf23b418": "메모를 지우지 못했습니다.",
+ "0fb870a0fe": "메모",
+ "8ab3248fd8": "메모",
+ "ec5053c7f5": "나란히",
+ "f786fd54e1": "인라인",
+ "ea08dae15b": "모두 축소",
+ "19c45cfdc0": "모두 확장",
+ "982d14bfa5": "커밋되지 않은 Diff 열기",
+ "3d909843bb": "오픈 브랜치 차이점",
+ "8368d256ec": "결합 브랜치",
+ "8f68ad9ca9": "{{value0}} AI {{value1}} 표시",
+ "724a13568d": "{{value0}}에서",
+ "6094135eec": "대 {{value0}}"
+ },
+ "ConflictComponents": {
+ "f338288514": "충돌 콘텐츠 로드 중...",
+ "90d576adb2": "새로고침",
+ "a1ce36f77d": "스냅샷 캡처 시간:",
+ "4be41eaafc": "미해결 충돌",
+ "c8ca989aea": "파일 트리 표시",
+ "58ad5ad431": "닫기",
+ "28e7db4a90": "소스 제어",
+ "31931dec46": "이 리뷰 스냅샷에는 더 이상 실시간으로 해결되지 않은 충돌이 없습니다.",
+ "992145ff5a": "모든 충돌이 해결되었습니다.",
+ "d5edd81755": "다음에서 이름 변경됨",
+ "6e459867ad": "세션-로컬 연속성 상태. Git은 더 이상 이 파일을 병합되지 않은 것으로 보고하지 않습니다.",
+ "9c2901ef8a": "다음 충돌",
+ "41d9af2e7a": "이전 충돌",
+ "55d61a0ccd": "충돌 ·",
+ "da539359b6": "이 충돌에 대해 편집할 수 있는 작업 트리 파일이 없습니다."
+ },
+ "ConflictReviewFileTree": {
+ "3449521a8c": "이 스냅샷에는 충돌이 없습니다.",
+ "a54551c5a6": "파일 트리 축소",
+ "99496bab6e": "파일",
+ "496e28a932": "다 쓴",
+ "8528a5eaf5": "해결됨",
+ "69d4e210bb": "해결되지 않은"
+ },
+ "CsvViewer": {
+ "eedd0d37a7": "기둥",
+ "ac31d2cd60": "행",
+ "a233d55b77": "빈 파일"
+ },
+ "DiffNotesSendMenu": {
+ "f1aa04b5cf": "이 파일",
+ "8b87612461": "보내지 않은 모든 메모"
+ },
+ "DiffSectionBody": {
+ "35d6afb5be": "바이너리 파일이 변경됨",
+ "cef4cf0ff5": "다시 시도",
+ "f5cf81cec2": "차이점 로드 중...",
+ "72f71f52eb": "이 파일에는 텍스트 비교를 사용할 수 없습니다.",
+ "7ce8436458": "브랜치 비교에서는 이 파일에 대해 텍스트 비교를 사용할 수 없습니다.",
+ "bdbf02d5df": "바이너리"
+ },
+ "DiffSectionHeader": {
+ "8915726e93": "경로 복사"
+ },
+ "EditorContent": {
+ "56dba34e1a": "(소스 모드에서 편집)",
+ "e4b074749d": "머리말",
+ "9640d1d3db": "이 차이점의 수정된 버전을 미리보기 중입니다. 변경 사항을 검사하려면 소스 모드로 전환하세요.",
+ "78541e254e": "바이너리 파일이 변경됨",
+ "c88c73a0d3": "차이점 로드 중...",
+ "b9de81ba52": "바이너리 파일 - 표시할 수 없음",
+ "b2735221f5": "로드 중...",
+ "8608ce4cb1": "바이너리 파일에는 마크다운 미리보기를 사용할 수 없습니다.",
+ "37a0e81fa6": "미리보기 로드 중...",
+ "8b1a605bae": "이 파일은 충돌 상태에 있지만 편집할 수 있는 작업 트리 파일이 없습니다.",
+ "2a512bb46a": "다시 시도",
+ "39f018b052": "파일을 로드할 수 없습니다.",
+ "8a0898ae4c": "이 파일에는 텍스트 비교를 사용할 수 없습니다.",
+ "3c6e71df22": "브랜치 비교에서는 이 파일에 대해 텍스트 비교를 사용할 수 없습니다.",
+ "d07e4b8553": "브랜치",
+ "d16e037f40": "부자"
+ },
+ "EditorPanelHeader": {
+ "fb8331694e": "측면으로 미리보기 열기",
+ "4157f3cbf3": "마크다운 미리보기 열기",
+ "269ce4842b": "상대 경로 복사",
+ "7c08a1f990": "경로 복사",
+ "84cdc0794b": "이름 바꾸기",
+ "1bb1e226ec": "파일 이름 바꾸기 {{value0}}",
+ "5447c4f68f": "목차",
+ "146cb5473c": "목차는 리치 모드 또는 미리보기 모드에서 사용할 수 있습니다.",
+ "e836faacfa": "병렬 비교로 전환",
+ "94756f08ba": "인라인 비교로 전환",
+ "c98ce191da": "이 차이점에는 열 수 있는 수정된 측면 파일이 없습니다.",
+ "9b80bbe1de": "파일 탭 열기",
+ "f0fd4174b5": "풍부한 마크다운 편집을 사용하려면 파일 탭을 엽니다.",
+ "a10d9b8337": "파일 열기"
+ },
+ "EditorPanelMarkdownActionsMenu": {
+ "3e0ce48c24": "PDF로 내보내기",
+ "561251019a": "추가 작업",
+ "8c8b7f5ff5": "머리말 표시",
+ "10c39d58c1": "머리말 숨기기"
+ },
+ "EditorPanelShell": {
+ "e2c4dec350": "편집기 로드 중..."
+ },
+ "EditorViewToggle": {
+ "b3410cd5e0": "공책",
+ "e408aa9cd5": "테이블",
+ "167f45888c": "커밋되지 않은 변경 사항",
+ "4837f3f578": "변경 사항",
+ "ac3bb87913": "편집",
+ "0d193dc03c": "시사",
+ "aff15f94f5": "리치 에디터",
+ "4d6ccb7ba6": "원천"
+ },
+ "ImageDiffViewer": {
+ "a651be62b0": "수정됨",
+ "57aac3979a": "원래의",
+ "fb0ae4f3c0": "미리보기 없음"
+ },
+ "ImageViewer": {
+ "3c9217f5a6": "확대",
+ "6c89c73d9f": "확대/축소 재설정",
+ "be27304574": "축소",
+ "77bfc9b35a": "팝업으로 이미지 열기",
+ "3ef9551ba2": "미리보기 로드 중...",
+ "d9d2944855": "파일 미리보기를 로드하지 못했습니다."
+ },
+ "ImageViewerPopup": {
+ "0ef78475e7": "닫으려면 Esc를 누르세요.",
+ "535f4e2b56": "닫기",
+ "9e27b2ecaf": "전체 크기 이미지 미리보기"
+ },
+ "IpynbViewer": {
+ "859bf9fc21": "셀 실행",
+ "7f0d7077c6": "취소",
+ "10ed04a685": "노트북 셀은 노트북 폴더에서 이 컴퓨터의 로컬 Python을 실행합니다. 신뢰하는 파일의 셀만 실행하세요.",
+ "9e06ae5d36": "노트북 코드를 실행하시겠습니까?",
+ "d6f37a640b": "빈 노트",
+ "8c3b21369a": "nbformat",
+ "329764e9fc": "베타",
+ "15ec40a735": "노트북 저장",
+ "07e7d96612": "세포",
+ "c1601b23b2": "노트북을 렌더링할 수 없습니다.",
+ "66a3f7d330": "노트북 HTML 출력",
+ "781abd6926": "셀 삭제",
+ "b42f6a9547": "아래에 마크다운 셀 삽입",
+ "ffc1ac2699": "위에 마크다운 셀 삽입",
+ "b4208cad7e": "아래에 코드 셀 삽입",
+ "53b839b8a0": "위에 코드 셀 삽입",
+ "27e064e2db": "셀을 아래로 이동",
+ "fd8ac707bc": "셀을 위로 이동",
+ "3e4cbf15ea": "날것의",
+ "1833dbbc43": "가격 인하",
+ "7005960d73": "암호",
+ "59b6cd874b": "암호",
+ "ba149053d5": "가격 인하"
+ },
+ "MarkdownPreview": {
+ "e4683f70c4": "취소",
+ "d737791433": "AI에 대한 메모 추가",
+ "b1bfc04034": "선택한 텍스트",
+ "f37b98999e": "이 메모",
+ "2b2b31382c": "머리말",
+ "bb629de58a": "에이전트용 메모 복사",
+ "322afab6ff": "리뷰 노트",
+ "0f9969a159": "첫 번째 리뷰 노트로 이동",
+ "12052c639c": "검색 닫기",
+ "b42c41bd0d": "다음 경기",
+ "1febd97f5c": "이전 경기",
+ "ec77985138": "마크다운 미리보기에서 찾기",
+ "517aea303b": "미리보기에서 찾기",
+ "f961e94057": "에이전트를 위한 메모 복사",
+ "94b520a96a": "복사된 메모",
+ "13f94d760c": "메모 추가",
+ "ddf087d12e": "보내지 않은 모든 메모",
+ "d652c87c91": "저장…",
+ "c5dc92cfe3": "결과 없음",
+ "6c043947ae": "파일을 찾을 수 없습니다: {{value0}}",
+ "759463a221": "디렉터리를 열 수 없습니다: {{value0}}"
+ },
+ "MarkdownTableOfContentsPanel": {
+ "de3928b6e4": "제목 없음",
+ "bbe8369097": "목차 닫기",
+ "4680a4b808": "H{{value0}}로 축소",
+ "a5daadd68b": "모두 펼치기",
+ "111e66b85d": "제목 수준 {{value0}}로 축소",
+ "f3de856175": "모든 제목 수준 확장",
+ "0dc7b2f05a": "레벨별로 접기",
+ "06357eea60": "목차",
+ "27d0a9c49a": "목차",
+ "65b036a6c8": "{{value0}} 확장",
+ "97ad46f11f": "{{value0}} 접기"
+ },
+ "MarkdownTemplatePicker": {
+ "22cd94426f": "제목없음.md",
+ "6e2e6c04ad": "빈 마크다운",
+ "df667919ca": "일치하는 템플릿이 없습니다.",
+ "22fd4890ad": "템플릿 검색...",
+ "7b458e0b7f": "마크다운 템플릿을 선택하세요.",
+ "1829437fce": "새로운 마크다운"
+ },
+ "MermaidBlock": {
+ "dcc132e691": "다이어그램 오류:"
+ },
+ "MonacoEditor": {
+ "68cb83f4a7": "선택한 텍스트에 메모 추가",
+ "fd68ae03b3": "파일에서 검색"
+ },
+ "MonacoGutterContextMenu": {
+ "7b57b1b468": "원격 URL 복사",
+ "2e0b1cdc05": "복사 상대. 라인 경로",
+ "4eaa991bde": "라인에 경로 복사"
+ },
+ "NotesSendMenu": {
+ "44dc5e60a6": "메모 보내기",
+ "433928cd9f": "에이전트에게 {{value0}} 보내기"
+ },
+ "PdfFind": {
+ "cd65b1d6b0": "닫기",
+ "eeba2547a1": "다음 경기",
+ "30de726ad0": "이전 경기",
+ "2fc3ba0ea8": "페이지에서 찾기...",
+ "d080ab37d6": "일치하는 항목 없음",
+ "db56fcd6d2": "{{value1}} 중 {{value0}}"
+ },
+ "PdfViewer": {
+ "3e98d500d2": "PDF 미리보기",
+ "069ff59932": "PDF에서 찾기({{value0}})",
+ "2b6eb1ccd6": "확대",
+ "c0119616d6": "너비에 맞춤",
+ "fa5d096b00": "축소"
+ },
+ "ReviewNotesSendMenuContent": {
+ "a49800405b": "새로운 에이전트",
+ "e84705f223": "활성 에이전트 세션",
+ "03378aea75": "메모 보내기",
+ "f5096c6e4e": "활성 에이전트에게 메모를 보낼 수 없습니다.",
+ "bb9c69a0c9": "활성 에이전트에게 메모가 전송되었습니다.",
+ "50f7e753ea": "활성 에이전트에게 메모를 보내는 중..."
+ },
+ "RichMarkdownAnnotationOverlay": {
+ "069b5677b8": "선택한 텍스트",
+ "6f2f3a6001": "리뷰 메모 추가"
+ },
+ "RichMarkdownCodeBlock": {
+ "232d9ed853": "복사됨",
+ "c72beafc0f": "코드 복사",
+ "74eab1d9b2": "YAML",
+ "5ef5605cb7": "XML",
+ "88d777bc07": "타입스크립트",
+ "9e384d48dc": "스위프트",
+ "3009f722b9": "SQL",
+ "d01f55be57": "껍데기",
+ "5af8251002": "SCSS",
+ "e72e6b03f4": "녹",
+ "96182a2f64": "루비",
+ "2391f9cda9": "파이썬",
+ "89d6cc14fb": "인어",
+ "983b9576b4": "가격 인하",
+ "bcb236e2d8": "코틀린",
+ "78eba32de4": "JSON",
+ "a209c57063": "자바스크립트",
+ "36536ad539": "자바",
+ "8c4a3fa02d": "HTML",
+ "706fd85738": "GraphQL",
+ "edfcc64182": "가다",
+ "bf6ee5caaa": "차이점",
+ "026653f21f": "CSS",
+ "4daed43ae3": "C++",
+ "4227cf50fe": "세게 때리다",
+ "13822cdfda": "일반 텍스트"
+ },
+ "RichMarkdownDocLinkMenu": {
+ "e17b987473": "↑↓ 탐색 ↵ 선택 esc 해제",
+ "90c5f0e1e4": "~의",
+ "2aaf7d9678": "표시 중",
+ "63ced7cb9b": "문서를 찾을 수 없습니다.",
+ "0e8489bc11": "마크다운 문서 링크",
+ "142a7d51cd": "문서"
+ },
+ "RichMarkdownErrorBoundary": {
+ "aad0998127": "다시 시도",
+ "4a5de9f2f0": "소스 모드로 전환하거나 재시도를 클릭하여 리치 보기를 다시 로드하세요.",
+ "dfdf1cacd4": "리치 마크다운 편집기에 예상치 못한 오류가 발생하여 나머지 Orca의 응답성을 유지하기 위해 재설정되었습니다."
+ },
+ "RichMarkdownLinkBubble": {
+ "1c99b726e0": "링크 삭제",
+ "cdfe166f6f": "링크 수정",
+ "bfc813e909": "링크 열기",
+ "7b0b945fdc": "링크를 붙여넣거나 입력하세요…"
+ },
+ "RichMarkdownReviewNoteLayer": {
+ "f3ef92952b": "이 메모",
+ "9cde7ad994": "에이전트를 위한 메모 복사",
+ "117432e2c6": "복사된 메모",
+ "3ababd949d": "리뷰 노트"
+ },
+ "RichMarkdownReviewRailActions": {
+ "636394af72": "에이전트용 메모 복사",
+ "a807596997": "복사된 메모",
+ "8aaf2c4c69": "리뷰 메모 표시",
+ "af02dc2456": "리뷰 메모 숨기기"
+ },
+ "RichMarkdownSearchBar": {
+ "de68b75bde": "검색 닫기",
+ "f7bcecbe26": "다음 경기",
+ "32ae8d7d57": "이전 경기",
+ "158c645829": "리치 마크다운 편집기에서 찾기",
+ "98b89276f3": "리치 에디터에서 찾기",
+ "a86958d508": "결과 없음"
+ },
+ "RichMarkdownSlashMenu": {
+ "82c6816ff8": "블록을 찾을 수 없습니다.",
+ "dbdd2ad15f": "블록 검색...",
+ "550189b06c": "블록 검색",
+ "2e0400b958": "슬래시 명령",
+ "e2e12b0e98": "요소"
+ },
+ "RichMarkdownToolbar": {
+ "e935c6b61e": "영상",
+ "6d52624712": "링크",
+ "f6a51cb9af": "인용",
+ "f97031be09": "체크리스트",
+ "31630ed66e": "번호가 매겨진 목록",
+ "5d1539e5a9": "글머리 기호 목록",
+ "0bea19a988": "스트라이크",
+ "6b4ccf9493": "이탤릭체",
+ "4f9e789fe0": "용감한",
+ "cf5817d827": "제목 3",
+ "d34a2021c8": "제목 2",
+ "abb5100a3d": "제목 1",
+ "b462641ed2": "본문 텍스트"
+ },
+ "UntitledFileRenameDialog": {
+ "a7dd27b0bc": "저장",
+ "949711deb4": "취소",
+ "725868c75d": "폴더 찾아보기",
+ "5e7f0d8a80": "원격 파일에는 폴더 선택기를 사용할 수 없습니다.",
+ "30099dca46": "접는 사람",
+ "2d7d39dc63": ".md",
+ "c8ac7868e6": "파일 이름",
+ "b6ed807cc6": "이름",
+ "e365f3c638": "마크다운 파일의 이름을 지정하고 폴더를 선택하세요.",
+ "674b046582": "다른 이름으로 저장"
+ },
+ "export": {
+ "active": {
+ "markdown": {
+ "51c4244904": "{{value0}}(으)로 내보냈습니다.",
+ "d4a901e0ad": "PDF 내보내기 중...",
+ "eda2cea3ad": "PDF를 내보내지 못했습니다."
+ }
+ }
+ },
+ "markdown": {
+ "rich": {
+ "mode": {
+ "7a8ce7c7da": "이 파일에는 각주가 포함되어 있으므로 코드 모드에서만 편집할 수 있습니다.",
+ "2fd2b44073": "이 파일에는 참조 스타일 링크가 포함되어 있으므로 코드 모드에서만 편집할 수 있습니다.",
+ "57128b73e1": "이 파일에는 HTML, JSX 또는 MDX가 포함되어 있으므로 코드 모드에서만 편집할 수 있습니다."
+ }
+ }
+ },
+ "rich": {
+ "markdown": {
+ "editor": {
+ "click": {
+ "routing": {
+ "2d5fb9335d": "파일을 찾을 수 없습니다: {{value0}}"
+ }
+ }
+ },
+ "slash": {
+ "commands": {
+ "07e1b32396": "일반 유니코드 이모티콘을 삽입하세요.",
+ "8a30cbaeca": "이모티콘",
+ "3324eb391a": "컴퓨터에서 이미지를 삽입하세요.",
+ "572be8e524": "영상",
+ "ae7d0f3f37": "디스플레이 LaTeX 수학을 삽입합니다.",
+ "6993a38ad1": "수학 블록",
+ "565907cf7a": "인라인 LaTeX 수학을 삽입합니다.",
+ "2bf5544faf": "인라인 수학",
+ "0ed9a7b38c": "인어 울타리 블록을 삽입합니다.",
+ "e516d3f6e3": "인어 다이어그램",
+ "67faab829b": "3x3 마크다운 테이블을 삽입합니다.",
+ "19ea597868": "테이블",
+ "fae45ef4d3": "수평선을 삽입합니다.",
+ "ae8377cf6b": "분할기",
+ "89e327e054": "분리된 코드 블록을 삽입합니다.",
+ "624b50cf25": "코드 블록",
+ "972ef9aeea": "접을 수 있는 텍스트 섹션을 만듭니다.",
+ "f82c78a2ee": "텍스트 전환",
+ "9a7fe896dc": "일반 단락을 시작합니다.",
+ "58abdb9d41": "절",
+ "d766f44867": "체크리스트를 작성하세요.",
+ "d0d2cdfbdb": "체크리스트",
+ "c9b9e826b8": "순서가 없는 목록을 만듭니다.",
+ "56ff3237e7": "글머리 기호 목록",
+ "8e00aba296": "정렬된 목록을 만듭니다.",
+ "ed4cf0ebce": "번호 매기기 목록",
+ "6a3def14de": "인용문을 삽입하세요.",
+ "c4c775778b": "인용",
+ "4920740259": "작은 섹션 제목.",
+ "30566ee962": "제목 3",
+ "45cf7ceb3f": "중간 섹션 제목.",
+ "c209a116b7": "제목 2",
+ "3294a2c0cc": "큰 제목 요약이 포함된 접을 수 있는 섹션을 만듭니다.",
+ "41482b15ce": "제목 1 전환",
+ "570611864e": "큰 섹션 제목.",
+ "e66e7f04c6": "제목 1"
+ }
+ }
+ }
+ },
+ "useContextualCopySetup": {
+ "059bfb0d94": "컨텍스트가 복사되었습니다."
+ },
+ "useLocalImagePick": {
+ "175cb8b8ce": "이미지를 삽입하지 못했습니다.",
+ "91d835dc88": "작업 트리 경로를 사용할 수 없습니다."
+ },
+ "useRichMarkdownReviewData": {
+ "f9d2acd6b0": "보내지 않은 모든 메모"
+ }
+ },
+ "diff": {
+ "comments": {
+ "DiffCommentCard": {
+ "109a791e7b": "저장",
+ "bb0a55f856": "저장…",
+ "0203bed775": "취소",
+ "6978871a3d": "열기",
+ "cce596969e": "메모 삭제",
+ "cad3384faa": "메모 수정",
+ "508ee678a5": "브라우저에서 열기"
+ },
+ "DiffCommentPopover": {
+ "2b3ce6d394": "취소",
+ "e05063cfc1": "라인 {{value0}}",
+ "c845170b3b": "라인 {{value0}}-{{value1}}"
+ },
+ "useDiffCommentDecorator": {
+ "995fa28b50": "이 메모"
+ }
+ }
+ },
+ "dictation": {
+ "DictationController": {
+ "de136f1199": "음성 오류: {{value0}}",
+ "7afff43472": "받아쓰기가 완료되었지만 텍스트 필드에 초점이 맞춰지지 않았습니다.",
+ "55127a3706": "받아쓰기 실패: {{value0}}",
+ "bb7f599ee7": "설정 열기",
+ "2d5b9fabf9": "마이크 액세스가 거부되었습니다. 시스템 설정에서 액세스 권한을 부여한 다음 Orca를 다시 시작하세요.",
+ "5d2c3e7ae3": "음성이 감지되지 않았습니다."
+ }
+ },
+ "dashboard": {
+ "DashboardAgentChildDisclosure": {
+ "1b57ce9fa4": "{{value0}} {{value1}} 하위 {{value2}}"
+ },
+ "DashboardAgentRow": {
+ "912e136cd9": "보내기",
+ "a743da52ff": "세부정보 펼치기",
+ "a41fb5376e": "세부정보 접기",
+ "5ae84475cc": "닫기",
+ "b06e13fcf7": "에이전트 닫기",
+ "0272969e28": "이 에이전트에게 보내기",
+ "92a7017987": "전송 중",
+ "019b74d93a": "전송 가능"
+ },
+ "DashboardAgentRowMessage": {
+ "0a01046763": "중단된",
+ "1ec01cef03": "사용자에 의해 중단됨"
+ }
+ },
+ "crash": {
+ "report": {
+ "CrashReportDialog": {
+ "b4951cd27c": "보고서 보내기",
+ "88fea8e84e": "보내지 마세요",
+ "50b00dc327": "세부정보 복사",
+ "6d3ebe216a": "진단 텍스트",
+ "835037edc9": "· Orca",
+ "56a3dfa283": "크래시 보고서를 보내지 못했습니다.",
+ "8e24fe4f75": "크래시 보고서가 전송되었습니다.",
+ "8b8473c544": "크래시 보고서가 복사되었습니다.",
+ "b175e90213": "크래시 보고서가 없습니다.",
+ "765591798d": "크래시 보고서 확인 중..."
+ }
+ }
+ },
+ "contextual": {
+ "tours": {
+ "ContextualTourControl": {
+ "186eecc34f": "첫 번째 에이전트 메시지에서 워크스페이스 자동 이름 지정",
+ "02e8373219": "이 텍스트 상자를 비워두면 새 이름이 자동 생성됩니다.",
+ "731c5573df": "첫 번째 메시지부터 자동 이름 지정"
+ },
+ "ContextualTourOverlaySurface": {
+ "4a9568f773": "뒤로",
+ "4f86e2a10b": "둘러보기 건너뛰기",
+ "d974f32a83": "투어 닫기",
+ "ffa4412b66": "다음"
+ },
+ "ContextualTourProgressDots": {
+ "7734cb8ad3": "~의",
+ "dcd6e6b03e": "{{value1}}의 {{value0}} 단계"
+ },
+ "contextual": {
+ "tour": {
+ "overlay": {
+ "measurement": {
+ "38b3155418": "다음"
+ }
+ }
+ }
+ }
+ }
+ },
+ "cmd": {
+ "j": {
+ "quick": {
+ "actions": {
+ "c884a6398e": "저장된 터미널 명령을 만듭니다.",
+ "a43ab56fc1": "빠른 명령 추가",
+ "54853d52a2": "현재 작업 트리를 삭제합니다.",
+ "9537b910fe": "작업트리 삭제",
+ "0b1f25f796": "새 작업 트리를 시작합니다.",
+ "52ac9da671": "작업트리 생성",
+ "f70812764a": "활성 워크스페이스에서 터미널 탭을 엽니다.",
+ "34980395d4": "새 터미널 탭",
+ "f2a1b33f8d": "활성 워크스페이스에 제목 없는 마크다운 파일을 만듭니다.",
+ "25349b66fc": "새 마크다운 파일",
+ "784812ca24": "활성 워크스페이스에서 브라우저 탭을 엽니다.",
+ "892bfa9339": "새 브라우저 탭",
+ "verbs": {
+ "newBrowser": "새 브라우저",
+ "newBrowserTab": "새 브라우저 탭",
+ "openBrowser": "브라우저 열기",
+ "browserTab": "브라우저 탭",
+ "newMarkdown": "새로운 인하",
+ "newMarkdownFile": "새로운 마크다운 파일",
+ "newMark": "새로운 마크",
+ "newFile": "새 파일",
+ "markdownFile": "마크다운 파일",
+ "newTerminal": "새 터미널",
+ "newTerminalTab": "새 터미널 탭",
+ "newShell": "새로운 껍질",
+ "terminalTab": "터미널 탭",
+ "createWorktree": "작업 트리 만들기",
+ "addWorktree": "작업 트리 추가",
+ "newWorktree": "새 작업 트리",
+ "deleteWorktree": "작업 트리 삭제",
+ "deleteCurrentWorktree": "현재 작업 트리 삭제",
+ "removeWorktree": "작업 트리 제거",
+ "trashWorktree": "쓰레기 작업 트리",
+ "addQuickCommand": "빠른 명령 추가",
+ "newQuickCommand": "새로운 빠른 명령"
+ }
+ }
+ }
+ }
+ },
+ "browser": {
+ "pane": {
+ "BrowserFind": {
+ "c9d5f63fdc": "닫기",
+ "5c0c02ae76": "다음 경기",
+ "ca7aebbd7f": "이전 경기",
+ "636a69cd66": "페이지에서 찾기...",
+ "7baca7b1b8": "일치하는 항목 없음",
+ "fc63f336aa": "{{value1}} 중 {{value0}}"
+ },
+ "BrowserImportHintButton": {
+ "05e675fe96": "힌트 숨기기",
+ "77351d22f5": "브라우저 설정",
+ "e0e125e074": "파일에서…",
+ "0c6d254eca": "에서",
+ "244266c122": "수입…",
+ "e52a955e6f": "언제든지 설정 > 브라우저에서 찾을 수 있습니다.",
+ "4f5ffaa6a1": "브라우저 데이터 가져오기",
+ "b24fef25be": "수입",
+ "02e89014c5": "{{value1}}{{value2}}에서 {{value0}} 쿠키를 가져왔습니다."
+ },
+ "BrowserMobileDriverOverlay": {
+ "a6914ee43f": "회수",
+ "f4ecd61552": "이 탭은 휴대전화에서 제어되고 있습니다. 데스크톱에서 사용하려면 다시 가져가세요.",
+ "d9768ec642": "브라우저 입력이 일시중지되었습니다.",
+ "20539eca03": "모바일이 이 브라우저를 구동하고 있습니다."
+ },
+ "BrowserPane": {
+ "1ded0d3168": "스크린샷 복사",
+ "f30d2d35a7": "스크린샷됨",
+ "fa6ea61de3": "취소",
+ "c2ef0359b9": "내용 복사",
+ "f2d0c22d67": "주석 삭제 {{value0}}",
+ "11c5084aa2": "주석 지우기",
+ "734e4343ec": "브라우저 주석 지우기",
+ "95af781091": "새 에이전트에게 의견 보내기",
+ "ac39b9366b": "보내기",
+ "a3508d7e6e": "{{value0}} 주석{{value1}}이 준비되었습니다. 다른 요소를 선택하거나 모든 피드백을 복사하세요.",
+ "f796c774a4": "탐색을 시작하려면 위에 URL을 입력하세요.",
+ "366bf5d62c": "새 탭",
+ "1c78adc73d": "외부에서 열기",
+ "da68d35f7b": "기본 브라우저에서 실패한 페이지 열기",
+ "93be92f8d1": "주소 복사",
+ "3c085f638d": "실패한 페이지 URL 복사",
+ "c6be71329e": "새로고침",
+ "781d6459ad": "다시 시도",
+ "2fdca7df09": "닫기",
+ "8b6fab9ffa": "저장",
+ "0f41bf80c7": "기본 브라우저에서 열기",
+ "ec75d0c412": "브라우저 개발자 도구 열기",
+ "fc9be38f6f": "페이지 요소에 주석 달기",
+ "fdfc7fe0ef": "페이지 요소 가져오기",
+ "a8f37f70c3": "페이지 검사",
+ "1b179ab561": "페이지 URL 복사",
+ "f7ab83f7ed": "기본 브라우저에서 페이지 열기",
+ "0e080d820e": "새로고침",
+ "250a9b3e42": "앞으로",
+ "40edfa75cb": "뒤로",
+ "efb0e8f7f3": "링크 주소 복사",
+ "8ce4f6b12e": "기본 브라우저에서 링크 열기",
+ "b5b87d6cbb": "Orca 브라우저에서 링크 열기",
+ "87eb75f7d2": "유효한 http(s) 또는 localhost URL을 입력하세요.",
+ "27d863542c": "브라우저 주석",
+ "e48569ac6d": "이 사이트에 접속할 수 없습니다.",
+ "bbe8f15e83": "이 분할창은 활성 런타임 서버에서 렌더링됩니다.",
+ "8b7e6d1f5a": "브라우저 주석은 로컬 브라우저 탭에서만 사용할 수 있습니다.",
+ "deb5293610": "원격 런타임에서는 브라우저 주석을 사용할 수 없습니다.",
+ "90d021f2ad": "추가",
+ "0cb3bd6221": "주석 의도",
+ "8f87e6c2e5": "의지",
+ "532bac48c5": "여기에서 에이전트가 무엇을 변경해야 하는지 설명하세요...",
+ "d2a7092e6e": "주석 코멘트",
+ "b472c5fe03": "브라우저 주석 추가",
+ "b5ba6085de": "질문",
+ "143204e423": "변화",
+ "e7ca5a098c": "성공",
+ "d51ef37351": "복사",
+ "6f4ab3592b": "복사됨",
+ "b2856516e2": "이 페이지를 로드할 수 없습니다.",
+ "db325a7eeb": "{{value0}}에 연결할 수 없습니다.",
+ "499b31b84e": "모두 복사",
+ "e72dfa268a": "주석을 달다",
+ "168350ae6a": "요소를 클릭하거나 마우스로 가리킨 다음 C를 눌러 복사하거나 S를 눌러 스크린샷을 찍습니다.",
+ "e852e20cea": "복사됨 - S를 눌러 스크린샷을 찍거나 다른 요소를 선택하세요.",
+ "a5dcd0fd1d": "확인",
+ "777b5bc4ec": "에이전트에 대한 피드백을 추가하려면 요소를 클릭하세요.",
+ "b733a91bd9": "선택한 요소에 대한 피드백을 추가합니다.",
+ "4328a0a062": "가져오기 실패: {{value0}}",
+ "26615e116b": "오류",
+ "8aec5bc044": "idle",
+ "759f32af29": "다운로드 중",
+ "c8bc7f1f9e": "요청됨",
+ "4300f38145": "{{value0}}{{value1}}에서 다운로드 중",
+ "31375046b7": "{{value0}}에서 다운로드",
+ "acbe79fd01": "페이지 요소 가져오기({{value0}})",
+ "572046436a": "원격 브라우저",
+ "b313a7275b": "원격 브라우저 열기"
+ },
+ "BrowserToolbarMenu": {
+ "429ef481f9": "취소",
+ "64f448fb6e": "프로필 이름",
+ "67e9b9fcd6": "새 브라우저 프로필",
+ "58f2c81542": "스위치",
+ "a38f217b46": "프로필을 전환하면 이 페이지가 다시 로드됩니다. 저장하지 않은 양식 데이터는 모두 손실됩니다.",
+ "fe683eb3b4": "프로필 전환",
+ "a771c2b6c8": "브라우저 설정…",
+ "ed8f54509d": "기본",
+ "e5d31de1a9": "뷰포트 크기",
+ "56f94f4ffa": "파일에서…",
+ "eb280bfb11": "에서",
+ "2293adf620": "쿠키 가져오기",
+ "cf7cdc67ef": "새 프로필…",
+ "7b838540c7": "브라우저 메뉴",
+ "6aa42813e4": "{{value1}}{{value2}}에서 {{value0}} 쿠키를 가져왔습니다.",
+ "a7a86702b3": "{{value0}} 프로필을 만들고 전환했습니다.",
+ "4d2f9f13a7": "프로필을 생성하지 못했습니다.",
+ "3ccd29d771": "{{value0}} 프로필로 전환됨",
+ "569bce8eb1": "생성",
+ "bf648471c5": "만드는 중…"
+ },
+ "GrabConfirmationSheet": {
+ "314a0aaa5b": "AI에 연결",
+ "7095e98362": "스크린샷 복사",
+ "26fd87f4df": "복사",
+ "87d97bdd6d": "취소",
+ "effd75e330": "주변 컨텍스트",
+ "7d1480fbf1": "HTML",
+ "9098b118ab": "페이지",
+ "eb98a0971a": "\"",
+ "d053db279d": "역할=",
+ "a759d8f866": "선택된 요소",
+ "9c6ce0632a": "선택한 요소 스크린샷",
+ "50f7114f99": "첨부하기 전에 리뷰하세요. 캡처된 페이지 컨텍스트에는 눈에 보이는 사이트 콘텐츠가 포함될 수 있습니다.",
+ "f3575229df": "붙잡다",
+ "405bb315da": "제목 없음"
+ },
+ "browser": {
+ "address": {
+ "bar": {
+ "suggestions": {
+ "87fcdd0da9": "{{value0}} 검색"
+ }
+ }
+ }
+ }
+ }
+ },
+ "automations": {
+ "AutomationCustomCronPanel": {
+ "3e3b2c369f": "크론 표현",
+ "e81a02d61b": "저장하기 전에 유효한 5개 필드 크론을 입력하세요.",
+ "968e66d686": "5개 필드 크론을 입력하세요.",
+ "cadb7b0bc9": "유효하지 않은"
+ },
+ "AutomationDetail": {
+ "007c8ad874": "즉각적인",
+ "a1d52c2189": "사용 범위",
+ "449fc83bf7": "토큰",
+ "401f40ae79": "예상 경비",
+ "a7c312430d": "마지막 실행",
+ "2df8970cd5": "에이전트",
+ "e353ab9516": "사전 확인",
+ "620b22145e": "우아함",
+ "15ea446b93": "세션",
+ "5405a09b1f": "실행 위치",
+ "2f8baf5360": "다음에서 생성",
+ "578ff46987": "다음 실행",
+ "18763ded26": "일정",
+ "dbef8dc110": "이 SSH 자동화는 Orca가 SSH 호스트에 연결할 수 있는 동안에만 실행됩니다. 다시 연결에 대화형 자격 증명이 필요하거나 호스트를 사용할 수 없는 경우 실행이 건너뛴 것으로 기록됩니다.",
+ "1f6026358e": "자동화 삭제",
+ "d79452fb30": "자동화 재개",
+ "91a4155e95": "자동화 일시 중지",
+ "4b1ea02d2e": "자동화 편집",
+ "2fb1605beb": "지금 실행",
+ "221916d93c": "에이전트 작업 예약을 시작하려면 자동화를 만드세요.",
+ "de0fedac06": "new_per_run",
+ "51a470b966": "SSH",
+ "b09b2384fd": "일시중지됨",
+ "eaa02014f8": "활성화됨"
+ },
+ "AutomationEditorDialog": {
+ "fb1896a5e7": "취소",
+ "57b722cbba": "에이전트",
+ "6ff66f9012": "새로운 실행",
+ "a2e688226d": "작업 트리",
+ "6f9610e667": "작업 트리는 선택한 워크스페이스에서 실행됩니다. 새로 실행하면 매번 선택한 브랜치에서 새 워크스페이스가 생성됩니다.",
+ "2c3fd9bfa1": "워크스페이스 모드 도움말",
+ "b28b140eaf": "워크스페이스",
+ "0d17f4ca8f": "프로젝트 선택",
+ "02d351877e": "프로젝트",
+ "a4ac8fcc62": "/목표",
+ "827b25a81e": "다음과 같은 스킬, 파일 경로 및 내장 명령을 지원합니다.",
+ "6d778190b7": "주간 종속성 감사를 실행하고 위험한 변경 사항을 요약합니다.",
+ "058c23cb3f": "즉각적인",
+ "c4b19094c2": "일정",
+ "e46c1aa9ad": "생성",
+ "a9d9dccf77": "저장",
+ "777548c2d6": "변경 사항 저장",
+ "ff5db28639": "기존의"
+ },
+ "AutomationEditorDialogHeader": {
+ "31f9253920": "템플릿 사용",
+ "7e35393632": "Hermes",
+ "6f309eef8d": "Orca",
+ "58f56b73d9": "자동화 이름",
+ "1d9826933e": "평일 레포 감사",
+ "4133d33862": "자동화 생성",
+ "0a75e5e2fa": "Hermes 자동화 생성",
+ "03142e7721": "Hermes 자동화 편집",
+ "17086b48ee": "자동화 편집"
+ },
+ "AutomationMissedRunGraceField": {
+ "0f4459e91d": "48시간",
+ "adbab51feb": "24시간",
+ "ba50e2a230": "12시간",
+ "2dc9ee84d0": "3시간",
+ "521f77cd58": "1시간",
+ "e5ad263ae5": "30분",
+ "529dc6c0b7": "은혜가 없다",
+ "3d70c185c8": "Orca 또는 실행 호스트를 예약된 시간에 사용할 수 없는 경우 Orca는 이 창 내에서 사용할 수 있게 되면 누락된 발생을 한 번 실행합니다. 이전에 놓친 실행은 건너뜁니다.",
+ "3df53d554a": "누락된 실행 유예 도움말",
+ "fc089e5fde": "우아함"
+ },
+ "AutomationPrecheckFields": {
+ "d2a2ac89ac": "10분",
+ "bf49585b3c": "5분",
+ "d84d3765fd": "2분",
+ "c820119736": "1분",
+ "51e28cdad9": "30초",
+ "bb2dfb3629": "시간 초과",
+ "99a577306c": "gh pr list --json 번호 -q '.[0].number'",
+ "c2a762a180": "사전 확인"
+ },
+ "AutomationRunHistory": {
+ "402651bfb6": "아직 실행이 없습니다.",
+ "9974a2b429": "상태",
+ "13988187b3": "토큰",
+ "86a248187e": "경비",
+ "149c0b49c7": "워크스페이스",
+ "8faaa00726": "달리다",
+ "53fc5f07ab": "실행 기록",
+ "a00e38d1a3": "해당 없음",
+ "fdb3caa8fb": "알려진"
+ },
+ "AutomationRunPageFrame": {
+ "40a511bed4": "컨텍스트 실행",
+ "33741dd973": "실행으로 돌아가기"
+ },
+ "AutomationSchedulePicker": {
+ "22359b186a": "오전 또는 오후",
+ "9e677335b0": "분",
+ "6b802ecc99": "시간",
+ "d90981f766": "시간",
+ "6b914c5fbb": "낮",
+ "233b8c94b6": "운율",
+ "b08ccb4d06": "매시간",
+ "8cc026fd73": "주간",
+ "c3e39e17cf": "custom"
+ },
+ "AutomationSessionField": {
+ "f3c76dce51": "재사용",
+ "c90888ee94": "신선한",
+ "b675112193": "재사용은 향후 실행을 이전 라이브 자동화 세션으로 보냅니다. 해당 세션이 사라지면 Orca는 새로운 세션을 시작합니다.",
+ "4bdce31f37": "세션 재사용 도움말",
+ "5ad314118e": "세션"
+ },
+ "AutomationsPage": {
+ "2695883141": "삭제",
+ "c3a28c9793": "실행을 보려면 자동화를 선택하세요.",
+ "295698292f": "재실행",
+ "0e110a3469": "실행",
+ "bb1b2cd31e": "개요",
+ "97ff587ee3": "원격 프로필에서 Hermes 자동화를 확인하려면 이 소스를 연결하세요.",
+ "aaa007846f": "소스를 사용할 수 없음",
+ "25060635c6": "새로 추가",
+ "d207ab4c25": "템플릿에서 시작",
+ "15e0bfb13b": "삭제",
+ "f4612e3f78": "편집",
+ "2faecab10b": "지금 실행",
+ "82eb6cb933": "원천",
+ "13118faadf": "알 수 없는 프로젝트",
+ "587a4b205c": "다음",
+ "761a35834d": "오토메이션",
+ "73f630b49d": "취소",
+ "1b586f0e2b": "~에",
+ "02a33e3204": "~에서",
+ "9adfab2596": "외부 자동화 삭제",
+ "1e2e41392f": "다시 묻지 마세요",
+ "b264564427": "그리고 그 실행 기록. 이전 실행으로 생성된 워크스페이스는 삭제되지 않습니다.",
+ "080dcb5fbb": "자동화 삭제",
+ "19a6e30eae": "자동화 새로 고침",
+ "8d1afa8269": "자동화 추가",
+ "77c2778945": "자동화",
+ "0329f9bef1": "닫기 · Esc",
+ "67c7ff795b": "자동화 닫기",
+ "e1bf9b1512": "워크스페이스를 사용할 수 없습니다.",
+ "3e42a5cc1b": "SSH 연결에 실패했습니다.",
+ "9f2855677c": "SSH가 연결되었습니다.",
+ "126d726546": "외부 자동화 작업이 실패했습니다.",
+ "37288942f0": "외부 자동화가 재개되었습니다.",
+ "77c518a34b": "외부 자동화가 일시중지되었습니다.",
+ "4d7878402c": "외부 자동화가 대기 중입니다.",
+ "4c22bc9913": "외부 자동화가 삭제되었습니다.",
+ "3a4c476aa0": "자동화를 다시 실행하지 못했습니다.",
+ "a1bdb57008": "자동화 실행이 대기 중입니다.",
+ "8a3226f172": "설정 열기",
+ "d2a01b0b6f": "설정에서 이를 변경할 수 있습니다.",
+ "690b94da54": "다음번에는 이 확인을 건너뛰겠습니다.",
+ "b11170a008": "자동화를 저장하지 못했습니다.",
+ "2a20596d6b": "자동화가 저장되었습니다.",
+ "244727e655": "자동화가 업데이트되었습니다.",
+ "77b81bc4ac": "헤르메스 자동화가 생성되었습니다.",
+ "08efc3ae12": "헤르메스 자동화가 업데이트되었습니다.",
+ "e431bb85d4": "이 Hermes 자동화와 동일한 호스트에서 워크스페이스를 선택하세요.",
+ "32534e7c9c": "저장하기 전에 사용 가능한 워크스페이스를 선택하세요.",
+ "2360ffc956": "저장하기 전에 활성화된 에이전트를 선택하세요.",
+ "6e91dab317": "저장하기 전에 유효한 고급 일정을 입력하세요.",
+ "64bdb2304f": "저장하기 전에 지원되는 일정을 선택하세요.",
+ "2430fecf53": "실행 위치를 선택하고 저장하기 전에 프롬프트를 입력하세요.",
+ "7934ee0d81": "SSH 연결",
+ "f93ed7a6f8": "연결 중...",
+ "8705757e27": "직업",
+ "376631ef2b": "재개",
+ "b457436d6a": "정지시키다",
+ "0ae52dd760": "헤르메스",
+ "e059042585": "읽기 전용",
+ "aecdc3681f": "다루기 쉬운",
+ "8500baacb4": "외부 소스",
+ "36f71740a7": "선택된 워크스페이스",
+ "cd8397cc32": "실행될 때마다 새로운 워크스페이스",
+ "dd0bc7a1ba": "new_per_run",
+ "7b2e285552": "이 클라이언트에서는 SSH 연결을 사용할 수 없습니다.",
+ "d441032f7e": "정지시키다",
+ "5918020edc": "달리다"
+ },
+ "CreateFromPicker": {
+ "f061f49e3f": "저장소 브랜치 검색...",
+ "dd3841b442": "에서 브랜치",
+ "ef6d762538": "프로젝트 기본값",
+ "e53d306056": "{{value0}}(기본값)",
+ "79512f22a7": "브랜치를 찾을 수 없습니다.",
+ "9ce96621f4": "브랜치 검색 중..."
+ },
+ "ExternalAutomationManagers": {
+ "e02f970595": "외부 자동화 관리자를 찾을 수 없습니다.",
+ "6da3bfba4b": "자동화가 발견되었습니다.",
+ "3d58d5b67d": "아니요",
+ "a42bf2b27e": "외부 자동화 삭제",
+ "1c3bfd38fe": "외부 자동화 재개",
+ "0def1693bb": "외부 자동화 일시 중지",
+ "1df491fd00": "외부 자동화 편집",
+ "cc77ba88ff": "외부 자동화 실행",
+ "5820648765": "마지막",
+ "844f1acb72": "발견됨",
+ "20fd7a3a15": "다음",
+ "c6695e6fbd": "외부 자동화",
+ "5524365227": "OpenClaw",
+ "766abf833c": "Hermes",
+ "bf5f67b590": "헤르메스",
+ "e66091daf4": "달린다",
+ "8e9165af08": "달리다",
+ "2b0adbce21": "일시중지됨",
+ "b3feba84c7": "활성",
+ "92405f1431": "없는",
+ "dbdcec22bd": "읽기 전용",
+ "0a2d4359a8": "다루기 쉬운",
+ "330b3c32e8": "사용 가능",
+ "e2532150ed": "자동화",
+ "701515f010": "오토메이션"
+ },
+ "ExternalAutomationRunTable": {
+ "0ba9c0a95c": "다음 실행 페이지",
+ "52d468a0b8": "이전 실행 페이지",
+ "7475c0ce96": "~의",
+ "be551397ca": "상태",
+ "a813df9808": "시사",
+ "d4b34feb66": "런타임",
+ "2d4388a908": "실행",
+ "9c080765ff": "아직 헤르메스 실행을 찾을 수 없습니다.",
+ "8ea934cacf": "실행 로드 중...",
+ "d5527d8fe7": "달린다",
+ "872d032d05": "달리다"
+ },
+ "HermesCronOutputView": {
+ "e27c716b43": "즉각적인",
+ "4557213074": "응답",
+ "05affc68e3": "오류",
+ "88d48157fc": "기본"
+ },
+ "WorkspaceCombobox": {
+ "ee5b280eba": "워크스페이스를 찾을 수 없습니다.",
+ "8e9c8cc6b5": "워크스페이스 검색...",
+ "66a0cd9628": "워크스페이스 선택"
+ },
+ "automation": {
+ "templates": {
+ "37571fcb16": "작업 중단, 오래 생성된 파일, 로컬 유효성 검사 실패를 찾아보세요.",
+ "8a0228bea3": "시간별 대기열 확인",
+ "3b7281c75f": "최근 작업을 스캔하고 정확성, UX 및 테스트 적용 범위 위험을 알려줍니다.",
+ "6023075b27": "일일 변경 리뷰",
+ "513401db93": "현재 프로젝트 상태에서 주간 릴리스 위험 요약을 준비합니다.",
+ "39ed39280a": "출시 준비",
+ "a7fbd32ddb": "매주 종속성, 실패한 테스트, 위험한 공개 변경 사항을 확인하세요.",
+ "b84757677d": "평일 레포 감사",
+ "repoHealth": {
+ "category": "레포 건강",
+ "name": "평일 레포 감사",
+ "prompt": "저장소 상태를 리뷰합니다. 종속성 업데이트, 실패한 테스트, lint/typecheck 상태, 위험한 공개 변경 사항을 확인하세요. 조사 결과를 요약하고 다음 조치를 제안합니다."
+ },
+ "releasePrep": {
+ "category": "출시 준비",
+ "name": "출시 준비 리뷰",
+ "prompt": "릴리스 준비 요약을 준비합니다. 차단 요소, 병합되지 않은 위험한 변경 사항, 유효성 검사 누락, 문서 공백을 찾아보세요. 간결한 릴리스/비 릴리스 권장 사항으로 끝납니다."
+ },
+ "recurringReview": {
+ "category": "반복 리뷰",
+ "name": "일일 변경 리뷰",
+ "prompt": "이 워크스페이스의 최근 변경사항을 리뷰하세요. 정확성 위험, UX 회귀, 누락된 테스트 및 후속 작업에 중점을 둡니다. 보고서를 짧고 실행 가능하게 유지하세요."
+ },
+ "maintenance": {
+ "category": "유지",
+ "name": "시간별 유지보수 점검",
+ "prompt": "작업 중단, 오래 생성된 파일, 유효성 검사 실패 및 사람의 주의가 필요한 모든 사항을 확인하세요. 실행 가능한 이슈만 보고하세요."
+ }
+ }
+ },
+ "external": {
+ "automation": {
+ "schedule": {
+ "display": {
+ "a8e92b815a": "일정을 알 수 없음"
+ }
+ }
+ }
+ }
+ },
+ "agent": {
+ "AgentCombobox": {
+ "19522e25ee": "에이전트 관리",
+ "986f946354": "블랭크 터미널",
+ "579c768bde": "검색어와 일치하는 에이전트가 없습니다.",
+ "48c6a5a9b4": "검색 에이전트...",
+ "9c6b59fe58": "기본값으로 설정",
+ "1b0d6965fa": "현재 기본값"
+ },
+ "AgentSettingsDialog": {
+ "50cdb57c03": "AI 에이전트를 관리하고, 기본값을 설정하고, 명령을 사용자 정의하세요.",
+ "fc0268e4ed": "에이전트"
+ }
+ },
+ "activity": {
+ "ActivityPrototypePage": {
+ "cf780197a1": "활동을 보려면 에이전트를 선택하세요.",
+ "e3db9892f6": "아직 활동이 없습니다.",
+ "1b633f5c1e": "터미널 연결 중...",
+ "8de7c5beaa": "터미널 이용 불가",
+ "866083500b": "드래그하여 크기 조정",
+ "443690186e": "활동 스레드 목록 크기 조정",
+ "7cd632006b": "이 필터와 일치하는 에이전트 활동이 없습니다.",
+ "a2b4437bfb": "{{value0}} 활동",
+ "023ff75afe": "모두 읽은 것으로 표시",
+ "f70e4bec47": "컴팩트 모드",
+ "a472a14700": "추가 옵션",
+ "db8a1878b5": "스레드 목록 옵션",
+ "d1a88df9a8": "읽지 않은 스레드만 표시",
+ "f6396e1f85": "에이전트",
+ "b29191b3e0": "작업 트리",
+ "8c3b621ddf": "프로젝트",
+ "4a3986b200": "상태",
+ "770d458144": "그룹 에이전트 활동 기준:",
+ "795cbf26e2": "필터...",
+ "4616ea39fd": "워크스페이스로 이동",
+ "59b131fbd9": "스레드를 읽지 않은 것으로 표시",
+ "beb2c19173": "읽히지 않는",
+ "5651b216c6": "알 수 없는 프로젝트",
+ "22b22034bc": "활동에서는 독립형 터미널을 사용할 수 없습니다.",
+ "afdc2139a8": "에이전트 터미널이 폐쇄되었습니다. 계속하려면 이 워크스페이스에서 새 터미널을 엽니다."
+ },
+ "ActivityTitlebarControls": {
+ "f915168c8e": "읽히지 않는",
+ "d6a8de3934": "에이전트",
+ "dc708f3eff": "에이전트 닫기"
+ }
+ },
+ "confirmation": {
+ "dialog": {
+ "8490e5d36a": "확인",
+ "56f5c60e0c": "취소"
+ }
+ }
+ }
+ }
+}
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
new file mode 100644
index 00000000000..6b7bc70707f
--- /dev/null
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -0,0 +1,9804 @@
+{
+ "app": {
+ "recoverableError": {
+ "rootTitle": "Orca 遇到渲染器错误。",
+ "rootDescription": "应用 shell 无法完成渲染。重试以重新挂载,如果错误仍然存在,请重新启动 Orca。",
+ "webTitle": "Orca Web 遇到渲染器错误。",
+ "webDescription": "重试 Web 客户端或重新连接到配对的运行时。"
+ }
+ },
+ "settings": {
+ "appearance": {
+ "language": {
+ "title": "语言",
+ "description": "选择 Orca 界面使用的语言。",
+ "system": "系统",
+ "english": "English",
+ "chinese": "中文(简体)",
+ "korean": "한국어",
+ "japanese": "日本語"
+ },
+ "statusBar": {
+ "claudeToggleDescription": "显示活动工作区的 Claude Token 和成本使用情况。",
+ "codexToggleDescription": "显示活动工作区的 Codex Token 和成本使用情况。",
+ "geminiToggleDescription": "显示活动工作区的 Gemini Token 和成本使用情况。",
+ "opencodeGoToggleDescription": "显示活动工作区的 OpenCode Go Token 和成本使用情况。",
+ "kimiToggleDescription": "Kimi 订阅",
+ "sshToggleDescription": "显示活动的 SSH 连接。仅在配置 SSH 目标后才可见。",
+ "resourceUsageToggleDescription": "显示资源管理器。点击可查看 CPU、内存、会话、守护进程控制和工作区磁盘扫描。",
+ "portsToggleDescription": "显示实时工作区端口。单击它可获取工作区范围的端口和外部侦听器。"
+ }
+ }
+ },
+ "menu": {
+ "checkForUpdates": "检查更新...",
+ "settings": "设置",
+ "exploreOrca": "探索 Orca",
+ "gettingStarted": "Orca 入门",
+ "reportCrash": "报告崩溃...",
+ "exportPdf": "导出为 PDF...",
+ "file": "文件",
+ "exit": "退出",
+ "edit": "编辑",
+ "appearance": "外观",
+ "toggleLeftSidebar": "显示/隐藏左侧边栏",
+ "toggleRightSidebar": "显示/隐藏右侧边栏",
+ "showStatusBar": "显示状态栏",
+ "showTasksButton": "显示任务按钮",
+ "showAutomationsButton": "显示自动化按钮",
+ "showMobileButton": "显示 Orca Mobile 按钮",
+ "showTitlebarAppName": "显示标题栏应用名称",
+ "view": "查看",
+ "reload": "重新加载",
+ "forceReload": "强制重新加载",
+ "resetSize": "重置尺寸",
+ "zoomIn": "放大",
+ "zoomOut": "缩小",
+ "openWorktreePalette": "打开工作树面板",
+ "window": "窗口",
+ "help": "帮助"
+ },
+ "worktreeJumpPalette": {
+ "matchLabel": {
+ "comment": "评论",
+ "issue": "议题",
+ "port": "端口",
+ "pr": "PR"
+ }
+ },
+ "auto": {
+ "App": {
+ "221a95ba38": "重试入门引导,或关闭后继续使用应用。",
+ "f02d37278a": "入门引导遇到错误。",
+ "acd66311dc": "如果您仍需要诊断,请在重试后使用“帮助”菜单。",
+ "722d03aa62": "崩溃报告对话框出现错误。",
+ "8a023cea1f": "重试状态栏以重新挂载其控件。",
+ "2e8ff36f94": "状态栏出现错误。",
+ "7cbfbf622f": "重试浮动工作区或关闭并重新打开它。",
+ "1b3024bcd6": "浮动工作区遇到错误。",
+ "8d1e160ed1": "重试侧边栏或切换标签页以重新加载此面板。",
+ "ed6b168d00": "右侧边栏出现错误。",
+ "03a14f6b5b": "重试此页面,或导航到其他 Orca 界面。",
+ "b7a714db1e": "此页面出现错误。",
+ "98d4ea2823": "此工作区中的终端、浏览器或编辑器渲染失败。请重试以重新挂载。",
+ "5a9519aef0": "工作区工作台遇到错误。",
+ "cba0fafda5": "活动页面保持打开状态。重试列表或切换视图。",
+ "1468601e7b": "工作区列表出现错误。",
+ "bdc71dddc9": "活动工作区保持打开状态。重试列表或切换视图。",
+ "c1cf0b0e4a": "折叠窗格",
+ "8504ddf267": "应用仍在运行。请重试 shell,或通过菜单报告崩溃详情。",
+ "df1d56bf87": "工作区外壳遇到错误。",
+ "9e0b441a91": "切换右侧边栏",
+ "e81217c1b7": "隐藏应用名称",
+ "5096cbbc86": "Orca",
+ "8b0b8eb54f": "应用菜单",
+ "caea5b51b9": "立即重启",
+ "0a9e810705": "重新启动之前不会保存更改。您以前的选项卡在磁盘上是安全的。",
+ "12e77cf12b": "会话恢复失败",
+ "332dbfa497": "工作区已上传",
+ "e960d18540": "关闭",
+ "c9d6f98459": "最大化",
+ "66f0a552e5": "恢复",
+ "bbb7f90669": "最小化",
+ "d54e66004c": "终端",
+ "9f0152563e": "移动端",
+ "62ca9895a7": "空间",
+ "844eb0f4f4": "活动",
+ "3443924e91": "自动化",
+ "4f08ae8311": "任务",
+ "ca6c6eece7": "技能",
+ "1b9d9d065f": "设置",
+ "c184e056de": "切换右侧边栏 ({{value0}})",
+ "f7aa73e785": "前进 ({{value0}})",
+ "cf9099fe98": "前进",
+ "fe21e8f6f5": "返回 ({{value0}})",
+ "064bd07810": "返回",
+ "ce37cf5279": "切换侧边栏 ({{value0}})",
+ "e4b9e7dff7": "切换侧边栏"
+ },
+ "web": {
+ "WebConnect": {
+ "b411ec0069": "连接",
+ "2cf9e5a294": "清除已保存的服务器",
+ "4a4c017be1": "端点:",
+ "27393856e4": "orca://pair?code=...",
+ "7a566540de": "配对 URL 或代码",
+ "cb4d287238": "服务器名称",
+ "3affe7de3a": "粘贴来自该浏览器可以访问的 Orca 服务器的配对 URL。",
+ "e3bcd082ac": "连接到 Orca"
+ },
+ "web": {
+ "preload": {
+ "api": {
+ "31bfe8ae1a": "在网络客户端中不可用。",
+ "67ec964791": "Web 客户端不支持 Cookie 导入。",
+ "275a776357": "悬停提取在 Web 客户端中不可用。",
+ "8dfcb7a351": "选择屏幕截图在 Web 客户端中不可用。",
+ "31bea294d5": "抓取模式在 Web 客户端中不可用。",
+ "b8a1618172": "拉取请求详细信息生成在 Web 客户端中不可用。",
+ "e57c82d276": "提交消息模型发现在 Web 客户端中不可用。",
+ "9fc90740b6": "提交消息生成在 Web 客户端中不可用。",
+ "52bee9d8a0": "冲突的自定义快捷键被忽略:{{value0}}。",
+ "32f15bdb0f": "未知平台“{{value0}}”被忽略。",
+ "0a69fcd8bc": "platform 必须是具有 darwin、linux 或 win32 部分的对象。",
+ "10898045f3": "“{{value0}}”的快捷方式被忽略:使用字符串数组。",
+ "36761d9604": "未知的键绑定操作“{{value0}}”被忽略。",
+ "d2e43e426a": "{{value0}} 必须是一个对象。",
+ "fb290366b2": "无法在网络上使用。"
+ }
+ },
+ "runtime": {
+ "environment": {
+ "07f788de83": "WebSocket"
+ }
+ }
+ }
+ },
+ "store": {
+ "slices": {
+ "browser": {
+ "d175274b6d": "新浏览器选项卡",
+ "08fc23631d": "浏览器"
+ },
+ "editor": {
+ "dcb521ed29": "该文件处于冲突状态,但没有可编辑的工作树文件。",
+ "51f15c37d3": "无法打开目录:{{value0}}",
+ "f2e00db373": "未找到文件:{{value0}}"
+ },
+ "github": {
+ "f129c42773": "GitHub 没有回复新评论。",
+ "683a21264b": "行没有所有者/存储库/编号。",
+ "83f9b126ad": "议题类型只能在议题上设置。",
+ "f963485d37": "未找到行",
+ "a967f23983": "项目视图未加载",
+ "87020f6605": "行没有所有者/存储库/编号 - 无法修补底层项目",
+ "d49ef4b944": "无法保存议题源首选项"
+ },
+ "sparse": {
+ "presets": {
+ "ef13e994e6": "保存之前必须加载预设。",
+ "6ed7d6010a": "删除预设失败",
+ "ee434d7941": "预设已删除",
+ "c96b770172": "保存预设失败",
+ "811be06b57": "更新预设失败",
+ "0696d13e56": "预设已保存",
+ "e10f097822": "预设已更新"
+ }
+ },
+ "store": {
+ "test": {
+ "helpers": {
+ "b9a8117c33": "终端 1"
+ }
+ }
+ },
+ "workspace": {
+ "cleanup": {
+ "9d6e531da6": "工作区不再存在。"
+ }
+ },
+ "worktrees": {
+ "5a58e03a26": "删除了“{{value0}}”。",
+ "d1d78a7baa": "Git 无法安全删除分支“{{value0}}”{{value1}},因此 Orca 保留它以避免丢失本地提交。",
+ "4e6496f3d2": "{{value0}} 已删除,分支保留",
+ "e50495aae6": "强制删除分支",
+ "889487d8bb": "关闭",
+ "f4503ca505": "打开“设置”>“Git”并重试。",
+ "34a03a6565": "保持 {{value0}} 为最新状态",
+ "fa9299a66f": "您的新工作树是最新的,但本地 {{value0}} 落后于 {{value1}} {{value2}} 。 AI 差异可能会错过最近的提交。",
+ "14bc053a47": "本地 {{value0}} 未刷新",
+ "4a18052018": "本地 {{value0}} 落后于 {{value1}}",
+ "903b51c2ed": "从 {{value0}} 创建工作区,但 Orca 无法快进本地 {{value1}},因为 {{value2}}",
+ "0216895fb5": "删除分支失败",
+ "19db0085fb": "本地分支已删除",
+ "2b0afc7f14": "无法使本地 {{value0}} 保持最新",
+ "670864ab52": "使本地 {{value0}} 保持最新"
+ },
+ "repos": {
+ "b7e14472ae": "添加文件夹失败",
+ "e649269645": "使用服务器路径从远程运行时添加项目。",
+ "c6e022ddfc": "添加项目失败",
+ "90d129b48b": "文件夹已添加",
+ "8bb3ad7935": "项目已添加",
+ "a8e4b3af5b": "项目已添加",
+ "6d3318e813": "导入存储库失败"
+ },
+ "settings": {
+ "e12dab333b": "切换服务器失败",
+ "faa8fb83dd": "在切换服务器之前保存或关闭未保存的编辑器选项卡。"
+ },
+ "ui": {
+ "66e3bd7ce6": "发送至 {{value0}}",
+ "53883b7bc3": "无法发送至 {{value0}}"
+ }
+ }
+ },
+ "lib": {
+ "agent": {
+ "catalog": {
+ "5dff448636": "OpenClaw",
+ "8a9ba743cc": "Hermes",
+ "4e63c7b956": "Rovo Dev",
+ "bee242fe3d": "Qwen Code",
+ "ca73055bd0": "Mistral Vibe",
+ "28810273af": "Kimi",
+ "739a930554": "Droid",
+ "667c104cff": "Cursor",
+ "9e2a9bb87b": "Continue",
+ "6f8056a565": "Command Code",
+ "4238b771b5": "Codebuff",
+ "cbaf0c2e0b": "Cline",
+ "1f8a19e9ad": "Autohand Code",
+ "5e8eff11b3": "Auggie",
+ "9477377a2a": "Charm",
+ "e0247254f2": "Kiro",
+ "918ba4ffed": "Kilocode",
+ "c73c573939": "Amp",
+ "8da11d876c": "Goose",
+ "b32627f09b": "Aider",
+ "691dd11789": "Antigravity",
+ "12e6baa4f7": "Gemini",
+ "09973b4d84": "OMP",
+ "302934c5d9": "Pi",
+ "e7a4ca5103": "OpenCode",
+ "706b0fe68b": "GitHub Copilot",
+ "0baad2d5d2": "Grok",
+ "760bc6883d": "Codex",
+ "a5fc0cb622": "OpenClaude",
+ "bf53f09bf8": "Claude Agent Teams",
+ "0708ed89f1": "Claude"
+ },
+ "skill": {
+ "cli": {
+ "prerequisite": {
+ "79371593b0": "Orca CLI 在 PATH 上尚不可见",
+ "e99d7dc36f": "Orca CLI注册需要注意",
+ "2db0bd7515": "Orca CLI 注册不可用",
+ "8d6eedf97e": "无法在 PATH 中注册 Orca CLI。",
+ "0f116999f1": "在安装之前重新启动 shell 或将 Orca CLI 目录添加到 PATH。",
+ "15cbedc3e3": "在运行代理技能设置之前安装 Orca CLI。"
+ }
+ }
+ }
+ },
+ "ensure": {
+ "simulator": {
+ "tab": {
+ "372d21d428": "移动模拟器"
+ }
+ }
+ },
+ "fix": {
+ "checks": {
+ "agent": {
+ "launch": {
+ "027228a06b": "无法找到用于这些检查的工作区。",
+ "fb6c294e85": "无法构建代理启动命令。",
+ "03c1d61f83": "无法打开附加到这些检查的工作区。",
+ "822bf52295": "无法解析工作区启动平台。",
+ "dfb4dd7c00": "无法找到附加到这些检查的工作区。",
+ "9f00d7df0c": "检查提示为空。请更新源代码管理 AI 设置。",
+ "2ebf794906": "此工作区主机上未检测到已启用的 AI 代理。",
+ "4c7f783a7a": "保存的检查代理在此工作区主机上不可用。"
+ }
+ }
+ }
+ },
+ "floating": {
+ "workspace": {
+ "tab": {
+ "creation": {
+ "f3785eddc2": "新浏览器选项卡"
+ }
+ }
+ }
+ },
+ "launch": {
+ "agent": {
+ "in": {
+ "new": {
+ "tab": {
+ "11cce5cc77": "无法在新终端中启动 {{value0}}。",
+ "a5a1f7033f": "您的 {{value0}} 未发送 - 代理准备好后将其粘贴。"
+ }
+ }
+ },
+ "background": {
+ "session": {
+ "4ca0651d56": "您的自动化提示未发送 - 打开工作区并粘贴它。"
+ }
+ }
+ },
+ "work": {
+ "item": {
+ "direct": {
+ "3de6371df3": "无法构建代理启动命令。",
+ "67e103dd60": "工作区已创建但无法激活。",
+ "19c7683acf": "所选代理在创建的工作区中不可用。",
+ "8bc45efdbc": "无法解析 PR 头引用。",
+ "agent": {
+ "ceeeb509b5": "代理启动时间太长。工作区已准备就绪 - 当代理空闲时粘贴 {{value0}}。"
+ }
+ }
+ }
+ }
+ },
+ "local": {
+ "path": {
+ "open": {
+ "guard": {
+ "edc1908653": "无法在本地操作系统中打开远程路径。"
+ }
+ }
+ }
+ },
+ "open": {
+ "in": {
+ "app": {
+ "catalog": {
+ "f8b8ca2711": "Zed",
+ "d62b12e98a": "Cursor",
+ "173553f73a": "VS Code"
+ }
+ }
+ }
+ },
+ "orchestration": {
+ "usage": {
+ "examples": {
+ "f91fe27f2a": "将大的变更拆分为较小的 PR",
+ "9e37a5b1b3": "并行运行独立工作",
+ "bddc4c09b8": "运行分阶段工作流程",
+ "ab0e9803b7": "移交给另一个工作树",
+ "5e0d489fe1": "移交活动任务"
+ }
+ }
+ },
+ "pr": {
+ "comment": {
+ "audience": {
+ "64deee36a9": "机器人",
+ "a7150a17bc": "人类",
+ "27ce73211c": "全部",
+ "empty": {
+ "bot": "没有机器人评论。",
+ "human": "没有人类评论。",
+ "all": "还没有评论。"
+ }
+ }
+ }
+ },
+ "resume": {
+ "sleeping": {
+ "agent": {
+ "session": {
+ "f235f604fd": "无法恢复此代理会话。"
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "agent": {
+ "action": {
+ "plan": {
+ "3f0ea9aa0d": "无法构建代理启动命令。",
+ "46f1a2c9bd": "命令输入为空。",
+ "8eb541cc83": "此工作区主机上未检测到所选代理。",
+ "b96e091fc9": "选定的代理在“设置”中被禁用。",
+ "a7ac8717c7": "在开始之前选择一个代理。"
+ }
+ }
+ },
+ "generation": {
+ "plan": {
+ "dc480d5897": "命令输入为空。"
+ }
+ }
+ }
+ },
+ "sparse": {
+ "preset": {
+ "draft": {
+ "5915a0a1f6": "使用存储库相对目录,而不是根目录、绝对路径或父段。",
+ "efc05d1820": "添加至少一个目录。"
+ }
+ }
+ },
+ "terminal": {
+ "shortcut": {
+ "capture": {
+ "notification": {
+ "b0536028c9": "打开快捷键",
+ "141ad6c004": "处理终端快捷方式",
+ "0ab0cd001a": "大小 4 文本静音前景"
+ }
+ }
+ }
+ },
+ "workspace": {
+ "create": {
+ "error": {
+ "format": {
+ "37cf0bc991": "Orca 无法解析此工作区的可用基础引用。",
+ "64555d0014": "未找到基础分支"
+ }
+ }
+ }
+ },
+ "worktree": {
+ "palette": {
+ "search": {
+ "9ccec2316b": "议题",
+ "ca40ffcbec": "PR",
+ "0b01ff98d2": "端口",
+ "7d732521ec": "评论"
+ }
+ }
+ }
+ },
+ "hooks": {
+ "useAutomationDispatchEvents": {
+ "59718b120b": "目标工作区不再可用。",
+ "16a21d6413": "SSH 重新连接需要交互式凭据。",
+ "386db94f3e": "目标项目不再可用。"
+ },
+ "useComposerState": {
+ "7eb3f44ff7": "所选代理已禁用。创建之前选择启用的代理。",
+ "b2ead86962": "无法解析 PR 基础引用。",
+ "a9ff236145": "部分附件无法上传。",
+ "3db83fc58a": "没有可用于附件的远程项目路径。",
+ "ba6cb77082": "无法连接到项目。"
+ },
+ "useGlobalFileDrop": {
+ "38c9f034ff": "无法上传删除的文件。",
+ "d720e2f855": "部分已删除的文件无法上传。",
+ "245faa95b9": "没有可用于放置的文件的远程工作区路径。"
+ },
+ "useIpcEvents": {
+ "0e3cf53060": "未找到浏览器选项卡 {{value0}}",
+ "a8d2bf8e9e": "没有可关闭的活动浏览器选项卡",
+ "291c8ed902": "当远程运行时处于活动状态时,浏览器选项卡不可用",
+ "f45fa2b03c": "当远程运行时处于活动状态时,浏览器配置文件不可用",
+ "f000b2ff76": "没有活动的工作树",
+ "56d3ec4203": "无法创建无标题 Markdown 文件。",
+ "f6300deb8b": "新浏览器选项卡",
+ "7a64b31991": "当远程运行时处于活动状态时,本地终端创建不可用",
+ "60428567b4": "当远程运行时处于活动状态时,本地终端显示不可用",
+ "f8aaf2bde3": "工作区已上传",
+ "2fe88c2e06": "远程工作区同步不可用",
+ "2ec42e1c52": "还没有远程工作区",
+ "88214a785b": "工作区同步等待本地会话同步并超时",
+ "4f78ba5885": "工作区已同步"
+ },
+ "useSettingsNavigationMetadata": {
+ "4a728cd56b": "仍在形成的新功能。尝试一下。",
+ "225071c560": "实验性",
+ "e338c507c1": "用于故障排除的低级兼容性设置。",
+ "580a04cd81": "高级",
+ "8400cfe1c1": "匿名使用数据和遥测控制。",
+ "3618579df6": "隐私与遥测",
+ "65ec7d1968": "终端启动的开发者工具的 macOS 隐私访问。",
+ "d91ae31fbd": "macOS 权限",
+ "95a1886d94": "通过手机控制终端和代理。",
+ "1cd25673df": "移动端",
+ "31e57d1c70": "文件、终端和 git 的远程 SSH 主机。",
+ "94a5afe910": "SSH 主机",
+ "40d80bad8a": "测试版",
+ "de0c2907a1": "远程 Orca 服务器",
+ "b351014180": "Orca 统计数据以及 Claude、Codex 和 OpenCode 使用情况分析。",
+ "d72a58b5b9": "统计和使用情况",
+ "dcd0d9b74f": "常见操作的键盘快捷键。",
+ "94295ebfb3": "快捷键",
+ "7682607591": "针对代理和终端事件的原生桌面通知。",
+ "2eece16ad1": "通知",
+ "1f452cbd4c": "选择和编辑行为。",
+ "0c6ee88a5f": "输入与编辑",
+ "b11a5a48a2": "主题、缩放、应用程序和终端外观、侧边栏和状态栏。",
+ "93d88d20bf": "外观",
+ "2d0659f6f0": "全局终端、浏览器和 Markdown 选项卡。",
+ "65b19f5bde": "浮动工作区",
+ "3d65d3f1b9": "配置对 Orca 和编码代理的移动模拟器支持。",
+ "1e761cff2b": "移动模拟器",
+ "e815fd01bd": "主页、链接路由和会话 cookie。",
+ "8c197f74a1": "浏览器",
+ "42ae40842f": "保存的终端命令,范围全局或每个项目。",
+ "3fc3db144f": "快捷命令",
+ "c33bfd664c": "Shell、渲染器、会话和终端行为。",
+ "a9fb10afca": "终端",
+ "5235c215ca": "选择在“任务”页面和侧栏中显示的任务提供者。",
+ "85f4fd7710": "任务来源",
+ "ab4b21b58e": "分支命名、基础引用、归因和 Git AI Author。",
+ "09607cb0fe": "Git 和源代码控制",
+ "33a5e1d597": "连接 GitHub、GitLab、Linear 和源托管服务。",
+ "2b043783ef": "集成",
+ "2cd4ea75da": "工作区默认值、应用程序设置和维护。",
+ "13241992bd": "通用",
+ "724c440e72": "入门",
+ "0505d0df29": "开始使用 Orca",
+ "ea0b1bc7b8": "设置指南",
+ "17005c73d4": "打开入门清单以了解设置和里程碑步骤。",
+ "ded9e9032f": "入门清单",
+ "5f32ac08f3": "完成 Orca 核心工作流程的入门清单。",
+ "8ac3de82f5": "使用设备上模型进行本地语音到文本听写。",
+ "6a50cdcd7c": "语音",
+ "0059bd17f3": "使代理能够控制您计算机上的任何应用程序。",
+ "b35e92364b": "计算机控制",
+ "cd50cec5d7": "通过 Orca 协调多个编码代理。",
+ "58a868e8e4": "编排",
+ "7c79d3b7bf": "可选",
+ "b1c2f8b0ac": "Claude、Codex、Gemini 和 OpenCode Go 的可选账户切换。",
+ "f70ac54d38": "AI 提供商账户",
+ "4121f7a0a2": "管理 AI 代理、设置默认值并自定义命令。",
+ "b49abbd2f7": "代理"
+ }
+ },
+ "components": {
+ "CodexRestartChip": {
+ "9132779820": "关闭",
+ "c72a5fb234": "重新启动",
+ "9263e75f49": "Codex 正在使用以前的账户"
+ },
+ "FirstLaunchBanner": {
+ "b9e1b966c7": "关闭通知",
+ "94cc673726": "知道了",
+ "fc5cc29955": "退出",
+ "d1deebb050": "隐私政策",
+ "958d2cc31b": "您使用的功能的匿名计数有助于我们确定要构建的内容的优先级。没有文件内容、提示、终端输出或任何可以识别您身份的内容。随时在“设置”->“隐私和遥测”中进行更改。",
+ "9784b4d7bc": "帮助我们决定下一步要构建什么",
+ "fcbee32f08": "遥测通知"
+ },
+ "GitHubItemDialog": {
+ "3ab6ac0fc8": "预览并编辑选定的 GitHub 议题或拉取请求。",
+ "3cd5ae5b7b": "没有更改任何文件。",
+ "999b5ad7d9": "文件",
+ "4bd1f5b055": "检查项",
+ "e30a5470c9": "对话",
+ "474c59b4b3": "关闭 · Esc",
+ "45af57999b": "关闭预览",
+ "3fdf777817": "在 GitHub 上打开",
+ "c43fe79ee0": "复制 GitHub 链接",
+ "0caac1a18f": "从 PR 启动工作区",
+ "8223320f8d": "已更新",
+ "10ef1afb8e": "· 已更新",
+ "55962099bc": "创建了此议题",
+ "0ab4664a8b": "从议题开始工作区",
+ "36182aa57f": "启动新工作区",
+ "fe6ff12dc2": "更多议题工作区操作",
+ "726db41722": "打开工作区",
+ "84855fedd0": "打开议题所附的工作区",
+ "b7bf31b8de": "无法将查看的状态与 GitHub 同步。",
+ "c0253318d6": "无法同步此拉取请求的查看状态。",
+ "5fea151559": "复制 GitHub 链接失败",
+ "2e77dc2053": "GitHub 链接已复制",
+ "2ef631437e": "无法打开此议题所附的工作区。",
+ "bf43425540": "评论",
+ "0a73f59e85": "发送评论",
+ "c5c117270e": "添加评论...",
+ "082515176a": "添加评论失败",
+ "c6f37a563d": "+ 负责人",
+ "f41ec96c13": "+ 标签",
+ "ab050dffec": "已关闭",
+ "dc1ca081a8": "进行中",
+ "2e4d806c92": "工作区",
+ "886a64b081": "还没有",
+ "4ba0132f37": "编辑标签",
+ "217e55d87c": "标签",
+ "c67de9e2fe": "没有人分配",
+ "76adcf5fe2": "编辑负责人",
+ "83ac703dda": "负责人",
+ "00ccdf9b5a": "状态",
+ "2aa9acdf34": "在 GitHub 上编辑标签",
+ "d23bbb6416": "{{value0}} 已跳过",
+ "18f80e1329": "{{value0}} 待处理",
+ "b1ac991806": "{{value0}} 失败",
+ "311d0cee55": "{{value0}} 通过",
+ "e52bed9264": "尚未报告任何检查",
+ "90020cc1f3": "此拉取请求尚未报告检查。",
+ "ecffebc251": "未找到检查",
+ "5dddefdf58": "在 GitHub 中打开",
+ "744197c84d": "此检查没有可用的内联输出。",
+ "08d072664d": "任务",
+ "96d8f36798": "注释",
+ "485609c4f2": "检查 #",
+ "0f478f5efa": "已完成",
+ "4812814bc8": "开始",
+ "9c3ba11a05": "状态:",
+ "934d87ab96": "正在加载检查详细信息...",
+ "71c11aff84": "重新运行所有检查",
+ "e31651a224": "重新运行失败的检查",
+ "1b56e28faa": "重新运行",
+ "f4b1292569": "在这些检查中启动默认的 AI 代理",
+ "9a1004fc76": "刷新检查",
+ "03e542fcfe": "无法为失败的检查启动 AI 代理:{{value0}}",
+ "28986b3747": "已启动 AI 代理处理失败的检查。",
+ "1690fd7f4a": "没有需要修复的失败检查。",
+ "9e7c221b8d": "无法重新运行检查",
+ "e463ec935f": "检查请求重新运行",
+ "ddafe851e1": "检查请求重新运行",
+ "0bbdc673c1": "刷新检查失败",
+ "e7007aa1d8": "如果没有存储库路径,则无法刷新检查。",
+ "675bc0d638": "取消",
+ "a18f669c7a": "{{value0}} {{value1}} 反应{{value2}}",
+ "53fe19aefc": "打开 GitHub 合并框",
+ "a2495e4784": "拉取请求",
+ "ce360fc318": "无法禁用自动合并",
+ "825a8fb8cd": "无法启用自动合并",
+ "4b390bd50d": "自动合并已禁用",
+ "a35ea5a0f6": "启用自动合并",
+ "aba792c8b3": "合并拉取请求失败",
+ "dbe5e2448e": "拉取请求已合并",
+ "a27ee5ca1a": "这将更新 GitHub 上的拉取请求。",
+ "03d7216d62": "{{value0}} PR #{{value1}}?",
+ "e9b7cb7d17": "{{value0}} PR 失败",
+ "bd3b4492a0": "拉取请求已重新打开",
+ "9f88657c4e": "拉取请求已关闭",
+ "b6f1b7adbd": "这将在 GitHub 上重新打开拉取请求。",
+ "de45fedf7b": "这将关闭 GitHub 上的拉取请求。",
+ "5a94f3d0e9": "还没有评论。",
+ "1506916c09": "评论",
+ "9b9cb55994": "没有提供描述。",
+ "52b20b56f7": "描述",
+ "4d555d3796": "编辑描述",
+ "9df4e74bdf": "保存",
+ "0ae387d8ca": "由",
+ "228e2f59d3": "已解决",
+ "a154ec5224": "在 GitHub 上打开评论",
+ "bca8eb39ac": "回复评论",
+ "68cb993d61": "已解决",
+ "10f4ff5be8": "回复已发布。",
+ "745c9089ec": "如果没有存储库路径,则无法回复。",
+ "58c73cb0d8": "无法更新描述。",
+ "5221548274": "描述已更新。",
+ "06c06e58ba": "显示下面更多行",
+ "307c98e8e3": "在上面显示 {{value0}} 更多行",
+ "5664681624": "显示上面的更多行",
+ "b1574e8ac2": "重置代码上下文",
+ "d43736d09c": "代码上下文控制",
+ "bd7be7b1fd": "comment L",
+ "db61d76cd5": "正在加载代码上下文...",
+ "f2d02cdf8c": "已查看文件",
+ "1257d1435d": "显示文件树",
+ "a341343303": "已添加评审评论。",
+ "d1fa2cf888": "没有PR负责人 SHA 无法发表评论。",
+ "829674460a": "Diff 不可用,因为 PR 提交 SHA 丢失。",
+ "af924014f8": "已查看",
+ "2d89a38d9d": "{{value0}} {{value1}} 如图所示",
+ "70e84e3d0b": "没有匹配的评审人。",
+ "1ffce94a8b": "其他人",
+ "c2b21818e1": "建议",
+ "a98433e73d": "加载中...",
+ "b0b7344684": "最多请求 15 名评审人",
+ "934add88b6": "评审人",
+ "bb42774171": "输入或选择用户",
+ "36f9ac4a47": "未请求评审人",
+ "8b15a5e91c": "移除评审人 {{value0}}",
+ "6a45771d47": "正在加载评审人",
+ "dc8a092c57": "评审人",
+ "e3243d9376": "最近编辑过这些文件",
+ "8c45901789": "请求评审人 {{value0}}",
+ "fedc09eeb9": "取消请求评审人 {{value0}}",
+ "73487fb975": "移除评审人失败",
+ "2e69540652": "已移除评审人",
+ "69515bff81": "已移除评审人",
+ "b4af16bf43": "没有可用于此拉取请求的存储库上下文。",
+ "c42d942b75": "请求评审人失败",
+ "c016e4bac3": "已请求评审",
+ "ea985e657f": "已请求评审",
+ "12e761610e": "最多可请求 15 名评审人",
+ "94ab23a9f9": "输入评审人",
+ "3853476a97": "GitHub 项目",
+ "68796dafa0": "PR",
+ "b1157c78ff": "sheet",
+ "038b3d39b1": "已复制",
+ "04539beb48": "议题",
+ "773ff70035": "未知",
+ "3e544d966d": "议题",
+ "88fd82474d": "page",
+ "e517b4d641": "关闭",
+ "d0a05e73f5": "紧凑",
+ "7d42606f66": "批注",
+ "2511f44bb7": "修复失败的检查",
+ "9157d48ddb": "修复检查",
+ "06482d6190": "无法自动创建修复工作区。",
+ "f64dd90102": "回复",
+ "5752c25aff": "发布…",
+ "ec5c4b3ab2": "重新打开 PR",
+ "21860b58d0": "关闭拉取请求",
+ "5932578f51": "合并需要注册本地存储库",
+ "ce8a85d209": "默认",
+ "924c2fe05e": "destructive",
+ "e2bf3e41a9": "评论",
+ "28d0d3374f": "帖子串",
+ "080d071d48": "回复@{{value0}}",
+ "86f809e2ce": "在此评论主题中回复",
+ "136542c9ba": ":L{{value0}}",
+ "283699bc82": "无法发表回复。",
+ "d1c0dad471": "-L{{value0}}",
+ "31770bef03": "并排",
+ "6e43a16435": "内联",
+ "d00a0a7f8f": "全部折叠",
+ "3c19ec3069": "全部展开",
+ "b0b09778c8": "无法添加评论。",
+ "16c1abe76c": "标记已查看",
+ "ba8e329d92": "取消标记已查看",
+ "3f79ffc8b7": "打开 PR 详情以查看当前评审人。"
+ },
+ "GitLabItemDialog": {
+ "65e784c1f1": "重新打开",
+ "a199eb364b": "关闭",
+ "16b3412570": "合并",
+ "131865e231": "创建工作区",
+ "f2e64d1c20": "在 GitLab 中打开",
+ "84012fa8fb": "评论",
+ "c08e1d5a57": "评论 {{value0}}{{value1}}...",
+ "f11e3e7675": "此 MR 没有运行任何管道。",
+ "808b1ca1ba": "没有更改的文件。",
+ "007423f585": "差异内容不可用。",
+ "a7eb4f4916": "从",
+ "21f8dde18a": "内嵌评论",
+ "7a7204417f": "线",
+ "ceb08a733d": "文件",
+ "85a8170279": "还没有评论。",
+ "14423484db": "没有描述。",
+ "da4174b00f": "编辑",
+ "93f79a3fc1": "保存",
+ "f72fad3b16": "取消",
+ "717b706849": "装载标签",
+ "3c0b6ccca7": "错误、后端",
+ "dde24ade55": "标签",
+ "908d8d2a73": "描述",
+ "89f3f19368": "标题",
+ "7a2117129a": "添加",
+ "05939e977d": "添加评审人",
+ "474b50d988": "没有评审人",
+ "1b19cdc510": "移除评审人 {{value0}}",
+ "cb55b0390f": "管理",
+ "4f9313984d": "评审人",
+ "02cbe2de44": "管道",
+ "be3d291837": "文件",
+ "c996e2962c": "对话",
+ "b3c156dd51": "刷新",
+ "9bfb4a24d7": "由",
+ "30c97083c2": "GitLab 工作项详细信息",
+ "e089f62594": "合并 MR !{{value0}}",
+ "865ea2703e": "已重新打开 MR !{{value0}}",
+ "9b11cd233f": "已关闭先生!{{value0}}",
+ "60c13320c4": "添加了内嵌评论",
+ "ffdd9a78e1": "MR diff refs 不可用于内嵌注释。",
+ "00d0d25825": "文件、行和注释是必需的。",
+ "ceaf7c30c7": "此 GitLab 用户无法获取评审人 ID。",
+ "f7cb495a12": "重试 {{value0}}",
+ "98718490e4": "MR 职称是必需的。",
+ "d600c2619a": "加载日志",
+ "028bde664e": "隐藏",
+ "2f9b27f838": "工作日志",
+ "032ae1312b": "在 GitLab 中打开职位",
+ "fa3e042203": "重试",
+ "f23ea85341": "已解决",
+ "4186685c78": "重新打开",
+ "cae2712a23": "关闭",
+ "881e522e04": "合并",
+ "6de8ce0cc6": "需要 {{value0}}",
+ "22511537d2": "得到正式认可的",
+ "00f3bab87b": "需要 {{value0}}",
+ "11384f99aa": "数字",
+ "40c56b95e2": "{{value0}} 批准{{value1}} 剩余",
+ "3a051b8ade": "工作项目",
+ "32f8bef818": "无日志输出。",
+ "4168eb2c51": "解决"
+ },
+ "JiraIssueWorkspace": {
+ "b0b92666c9": "评论",
+ "a585fd204e": "添加 Jira 评论...",
+ "2441be6f9f": "启动工作区",
+ "9178090e26": "还没有评论。",
+ "5cd09beaf9": "重试",
+ "9a980b06b9": "评论",
+ "c4889a47e4": "没有提供描述。",
+ "0f3c07a901": "后端、错误",
+ "aee97b6913": "标签",
+ "444865b4a8": "标题",
+ "0b6b5646ed": "未分配",
+ "51bed73f88": "无优先权",
+ "7a96985ca0": "关闭",
+ "76513c7898": "关闭 Jira 议题预览",
+ "857bd2f88f": "预览、编辑并从选定的议题开始工作。",
+ "0cc62bd690": "复制提示",
+ "80efa101c5": "复制建议的分支名称",
+ "38839801e8": "复制键",
+ "779bb91ee0": "复制网址",
+ "69da9a208c": "在 Jira 中打开",
+ "fa132c8aed": "添加评论失败。",
+ "ea21952aa3": "无法更新 Jira 议题。",
+ "6c41a9bcea": "复制 {{value0}} 失败",
+ "2ff69a3545": "{{value0}} 已复制",
+ "666cfdd835": "未知",
+ "9ebee71962": "标签",
+ "def3d0e824": "标题",
+ "b8e2079d96": "负责人",
+ "54649eaeab": "+ 负责人",
+ "2a829a2f00": "优先事项",
+ "693be070d0": "过渡",
+ "ef21405c6d": "Jira 议题"
+ },
+ "Landing": {
+ "76a95f7f47": "创建",
+ "f05d237049": "先添加一个项目",
+ "f9eaa9e12d": "添加项目",
+ "6ca6ff404e": "ORCA",
+ "520304a067": "Orca 标志",
+ "ce44fad849": "缺少依赖项",
+ "c1cf168479": "隐藏",
+ "00cee697c1": "在终端中运行“gh auth login”以连接您的 GitHub 账户。",
+ "9f96d018b7": "GitHub CLI 未经过身份验证",
+ "73e1ad4282": "Orca 使用 GitHub CLI (gh) 来显示拉取请求、议题和检查。",
+ "5beaef5f9e": "GitHub CLI 未安装",
+ "b673e7cf1b": "Git 项目、源代码控制和工作区管理需要 Git。",
+ "e5b7296d9d": "未安装 Git",
+ "cd21242762": "添加一个项目即可开始。",
+ "9c00bd4adf": "从侧边栏中选择一个工作区开始。",
+ "16e9e3df89": "已加星标",
+ "0d0ace8861": "在 GitHub 上加星标",
+ "ec43b38ba7": "在 GitHub 上加星标"
+ },
+ "LinearIssueMarkdownDescriptionEditor": {
+ "d9c47069ef": "降价",
+ "a7301a11f3": "保存",
+ "632096eb1c": "关联",
+ "340160f4e8": "删除链接",
+ "9eaf02ac01": "引用",
+ "e2a0267c8c": "清单",
+ "d6b2f3d35b": "编号列表",
+ "c82917e06e": "项目符号列表",
+ "ad1869bd54": "内联代码",
+ "28fd951b83": "罢工",
+ "5666b4493d": "斜体",
+ "caa88f50d0": "大胆的",
+ "dddaa7a0a6": "标题 2",
+ "e3f741d258": "标题 1",
+ "68a41d5665": "正文",
+ "7c52151156": "议题描述格式",
+ "5c16ec8f14": "链接网址",
+ "4f2fddc2b7": "没有提供描述。"
+ },
+ "LinearIssueTextEditor": {
+ "947ba2d6f4": "保存",
+ "04d73b72dc": "议题标题",
+ "e8ff595db3": "更新 {{value0}} 失败",
+ "1e08a1ec80": "标题为必填项",
+ "00fa439dc7": "标题",
+ "75294b07d1": "描述"
+ },
+ "LinearIssueWorkspace": {
+ "ad5dec37b7": "预览、编辑并从选定的议题开始工作。",
+ "c23e79e5c0": "操作",
+ "b0eac92d85": "重试",
+ "fabbd3f974": "更新了议题·",
+ "543970c87a": "活动",
+ "df4c86ed12": "关闭",
+ "7a4997d8bb": "关闭 Linear 议题预览",
+ "e1e0a9bca9": "启动工作区",
+ "30a7f56c0a": "从议题开始工作区",
+ "30c1242f3a": "复制标识符",
+ "9e3c49beb8": "复制议题标识符",
+ "9a9a884236": "复制网址",
+ "97c19a84f1": "复制 Linear URL",
+ "f63ef94ea8": "议题",
+ "f6c6381593": "复制提示",
+ "5d670ec8dc": "复制建议的分支名称",
+ "937ba6ad9a": "加载项目",
+ "db3f269d98": "搜索项目",
+ "b51276c8d6": "项目",
+ "8b5b593053": "项目更新失败",
+ "f9d4ef9807": "项目已更新",
+ "38b80780c2": "无法加载项目",
+ "42589845bc": "创建",
+ "c182e02de5": "子议题标题",
+ "8c55d6696a": "添加子议题",
+ "b25e453c9d": "创建子议题失败",
+ "aeed19d003": "创建 {{value0}}",
+ "9a1317cdd3": "无法加载子议题",
+ "9bcbaa2737": "复制 {{value0}} 失败",
+ "7835483c43": "{{value0}} 已复制",
+ "61f424f8ca": "Linear 议题",
+ "ca8778c124": "未知",
+ "8a33c85e9c": "有人",
+ "f5a6b38a14": "sheet",
+ "65239a714b": "Linear",
+ "af6e02c44a": "page",
+ "76ffd3c937": "搜索要添加的项目。",
+ "c11b4e3cc2": "没有找到项目。",
+ "519c3587f3": "添加到项目"
+ },
+ "LinearItemDrawer": {
+ "04008e6c46": "从议题开始工作区",
+ "a4fcc57522": "还没有评论。",
+ "fde849b2b6": "评论",
+ "9dc54172db": "关闭 · Esc",
+ "0190b760c1": "在 Linear 中打开",
+ "04a442f796": "预览并编辑选定的 Linear 议题。",
+ "d369841269": "发送评论",
+ "2fcff829a8": "添加评论...",
+ "2820f0f0f0": "发表评论...",
+ "6ab35eafd5": "添加评论失败",
+ "367f828482": "没有找到标签",
+ "cddd9b04a7": "装载标签",
+ "23886c7eec": "添加标签",
+ "7f7b89b631": "标签: {{value0}}",
+ "b2376d0179": "正在加载会员",
+ "866316f22c": "未分配",
+ "b5675b0694": "保存",
+ "ceeb8c6153": "清除",
+ "fbb90300e2": "定制估价",
+ "780ea6ed89": "未找到任何州",
+ "59b6cd3706": "加载状态",
+ "64bfffc4dd": "标签",
+ "dd304de85a": "特性",
+ "0be31fef8e": "估计值必须是非负整数",
+ "48e17e8cbd": "未知",
+ "858d0630da": "关闭预览",
+ "39883467f4": "Linear 议题",
+ "fda549766e": "{{value0}} 发表评论",
+ "d71cd3003e": "+ 负责人"
+ },
+ "NewWorkspaceComposerCard": {
+ "cbb47ee0dc": "仅适用于本地 Git 项目。",
+ "d861de981b": "结账稀疏",
+ "090cfedeb4": "写一个注释",
+ "f8728aa4f9": "笔记",
+ "0ee17638fe": "工作区名称",
+ "2688050e4b": "姓名",
+ "f0470c7383": "高级",
+ "ba64270bdb": "配置代理",
+ "ab63f25397": "打开代理设置",
+ "01d1e8f601": "代理",
+ "0c5d6a479c": "[可选]",
+ "b5a0796911": "连接",
+ "dccd26d4e4": "选择项目",
+ "d6b0a96f32": "添加项目",
+ "969a8bff66": "项目",
+ "23bb365554": "Orca.yaml",
+ "a239038146": "SSH 连接错误",
+ "9a70e4859e": "选择是否在创建此工作区之前运行安装程序。",
+ "803b7fe72f": "正在检查设置配置...",
+ "92e34f0311": "本地设置",
+ "326a578923": "orca.yaml + 本地",
+ "2132b670da": "两个都",
+ "0e587e31fb": "yaml",
+ "ac3748dcda": "名称或“创建自”",
+ "f660aa1454": "连接中",
+ "7711ad5122": "本地设置命令",
+ "e5db1b0419": "组合设置命令",
+ "addProjectBeforeWorkspace": "在创建工作区之前添加项目。"
+ },
+ "NewWorkspaceComposerModal": {
+ "fa90f739a5": "创建工作区之前选择项目、工作区名称和代理。"
+ },
+ "PullRequestPage": {
+ "2560588245": "请求评审人失败",
+ "3450247584": "评论",
+ "6ad2c1ab9c": "没有更改任何文件。",
+ "4d18310d55": "文件已更改",
+ "94d95cf1f7": "检查项",
+ "9e8d45700e": "对话",
+ "e6996f4024": "· 已更新",
+ "00b7b82329": "源分支",
+ "e1f3641bfd": "从",
+ "c44b70352b": "基础分支",
+ "b0e80f083d": "想要合并到",
+ "8ecda455a0": "在 GitHub 上打开",
+ "1a2570e18e": "启动新工作区",
+ "57c13a5aa4": "更多 PR 工作区操作",
+ "25690a3855": "从 PR 启动工作区",
+ "a459866967": "恢复关联 PR 的工作区",
+ "347034903a": "复制 GitHub 链接",
+ "5a01ca7253": "无法将查看的状态与 GitHub 同步。",
+ "996a1897d2": "无法同步此拉取请求的查看状态。",
+ "e0b15c793f": "复制 GitHub 链接失败",
+ "992e799227": "GitHub 链接已复制",
+ "61bfc81ada": "无法打开附加到此拉取请求的工作区。",
+ "161d91ef02": "发送评论",
+ "d2030fc8cd": "添加评论...",
+ "1208347ac0": "添加评论失败",
+ "61452f2143": "从议题开始工作区",
+ "14c9fc70ed": "+ 负责人",
+ "bc215fea4d": "+ 标签",
+ "b936cc51a4": "已关闭",
+ "7b8f6bf6d8": "进行中",
+ "e6ad0a8d06": "{{value0}} 已跳过",
+ "88267924d5": "{{value0}} 待处理",
+ "ae2a34c7b8": "{{value0}} 失败",
+ "7c5035931a": "{{value0}} 通过",
+ "a18d01cda3": "尚未报告任何检查",
+ "3912daf310": "此拉取请求尚未报告检查。",
+ "45877f5089": "未找到检查",
+ "85e62c5266": "已启动 AI 代理处理失败的检查。",
+ "ddfd42f460": "选择代理并在启动前编辑完整的命令输入。",
+ "a053bdd082": "用 AI 修复失败的检查",
+ "1b14d0a69c": "在 GitHub 中打开",
+ "1550675e5f": "此检查没有可用的内联输出。",
+ "7720c9c3f5": "任务",
+ "8432d17901": "注释",
+ "f01bf79a79": "检查 #",
+ "000f90afcf": "已完成",
+ "76551b1161": "开始",
+ "662bc2998d": "状态:",
+ "d8e82b7f15": "正在加载检查详细信息...",
+ "54cddd1858": "重新运行所有检查",
+ "68605516dd": "重新运行失败的检查",
+ "522d9353e1": "重新运行",
+ "0fa8b8faec": "在这些检查中启动默认的 AI 代理",
+ "5d0f42766d": "刷新检查",
+ "98583589c6": "无法为失败的检查启动 AI 代理:{{value0}}",
+ "51c65c0265": "没有需要修复的失败检查。",
+ "788a782bb0": "无法重新运行检查",
+ "18f2af42ac": "检查请求重新运行",
+ "5963a6a852": "检查请求重新运行",
+ "246b2c6456": "刷新检查失败",
+ "c057f2fcb0": "如果没有存储库路径,则无法刷新检查。",
+ "6591b1fa82": "取消",
+ "42c36d9166": "{{value0}} {{value1}} 反应{{value2}}",
+ "7df8d5fc60": "打开 GitHub 合并框",
+ "1939d0f663": "拉取请求",
+ "973ef2fac9": "无法禁用自动合并",
+ "d31f4b508c": "无法启用自动合并",
+ "0f5821b035": "自动合并已禁用",
+ "5edbe7eefa": "启用自动合并",
+ "aae645d36d": "合并拉取请求失败",
+ "c57873d721": "拉取请求已合并",
+ "a63b3c159c": "这将更新 GitHub 上的拉取请求。",
+ "eec3706a6a": "{{value0}} PR #{{value1}}?",
+ "b8c6cbb8c4": "{{value0}} PR 失败",
+ "710e47aa06": "拉取请求已重新打开",
+ "7aa3b5f706": "拉取请求已关闭",
+ "3d77438c92": "这将在 GitHub 上重新打开拉取请求。",
+ "5a65651096": "这将关闭 GitHub 上的拉取请求。",
+ "d2d589556c": "还没有评论。",
+ "3463d10a63": "评论",
+ "c8ea6c7c4c": "没有提供描述。",
+ "778683ec84": "描述",
+ "da9aaa8bcf": "编辑描述",
+ "4a337ac05f": "保存",
+ "169a93b29a": "已更新",
+ "3c891789f6": "由",
+ "f4fe47c2bb": "已解决",
+ "0ac19bb52e": "在 GitHub 上打开评论",
+ "d6c6679de7": "回复评论",
+ "76b2a0ac5b": "已解决",
+ "11505c7a71": "回复已发布。",
+ "6885c619e7": "如果没有存储库路径,则无法回复。",
+ "d94810f652": "无法更新描述。",
+ "9b4190dc98": "描述已更新。",
+ "51ed0cf38b": "显示下面更多行",
+ "e295a78c11": "在上面显示 {{value0}} 更多行",
+ "c9de94b07a": "显示上面的更多行",
+ "5f3e293517": "重置代码上下文",
+ "85d119be40": "代码上下文控制",
+ "791ddede19": "comment L",
+ "4b960e5978": "正在加载代码上下文...",
+ "89e80af1c7": "已查看文件",
+ "319cf2d54b": "显示文件树",
+ "eff839f438": "已添加评审评论。",
+ "d8c3ba91c4": "没有PR负责人 SHA 无法发表评论。",
+ "74660bd80b": "Diff 不可用,因为 PR 提交 SHA 丢失。",
+ "2e528e1c2d": "已查看",
+ "ff84e1f54c": "{{value0}} {{value1}} 如图所示",
+ "5ad00c7a0e": "没有匹配的评审人。",
+ "2760fa29a4": "其他人",
+ "828f045847": "建议",
+ "57750f4a8c": "加载中...",
+ "805cb72cd4": "最多请求 15 名评审人",
+ "a04c137bb7": "评审人",
+ "3bde131f49": "输入或选择用户",
+ "d10b6d5209": "未请求评审人",
+ "ae9a38fd4a": "移除评审人 {{value0}}",
+ "acbd110867": "正在加载评审人",
+ "00d3be6bcd": "评审人",
+ "f4a4b3fd9f": "最近编辑过这些文件",
+ "41d275d3ec": "请求评审人 {{value0}}",
+ "36b514a457": "取消请求评审人 {{value0}}",
+ "c798fa0ec7": "移除评审人失败",
+ "1e6d089420": "已移除评审人",
+ "2c1d93da43": "已移除评审人",
+ "1ae11c905c": "没有可用于此拉取请求的存储库上下文。",
+ "102d3d177f": "已请求评审",
+ "03282ff3b9": "已请求评审",
+ "8f369a6b6b": "最多可请求 15 名评审人",
+ "dace0d1a9f": "输入评审人",
+ "77d9388fb0": "未知",
+ "c9e7094a7b": "恢复工作区",
+ "3b6886b2ee": "已复制",
+ "b6bda618cf": "紧凑",
+ "35a0573f41": "批注",
+ "61a8c69a33": "page",
+ "a4541fd3db": "修复失败的检查",
+ "c808db1dd1": "修复检查",
+ "c4c02ea23e": "无法自动创建修复工作区。",
+ "f119e5f5ef": "回复",
+ "894cfd884b": "发布…",
+ "9d5425918e": "重新打开 PR",
+ "96d013ed28": "关闭拉取请求",
+ "d65f70786e": "关闭",
+ "eca289e593": "合并需要注册本地存储库",
+ "6568ae8ece": "默认",
+ "19f19560d5": "destructive",
+ "aae99c6c04": "PR",
+ "e01e34f5fa": "评论",
+ "345b68254c": "帖子串",
+ "31a7b202f2": "回复@{{value0}}",
+ "408e634fbb": "在此评论主题中回复",
+ "34b9f7c264": ":L{{value0}}",
+ "5821aab360": "无法发表回复。",
+ "84fc40769a": "-L{{value0}}",
+ "1378d79e83": "并排",
+ "e5f4a24f78": "内联",
+ "dd94111c18": "全部折叠",
+ "eb722a5a8c": "全部展开",
+ "19628e058d": "无法添加评论。",
+ "50b8fb290f": "标记已查看",
+ "2b4fdb880c": "取消标记已查看",
+ "56ec6eafb7": "打开 PR 详情以查看当前评审人。"
+ },
+ "QuickOpen": {
+ "1dbd3f59ff": "移动",
+ "73b2c581f1": "关闭",
+ "95fccbae88": "Esc键",
+ "61b1c871a6": "进行中",
+ "250e5b2dfb": "进入",
+ "74e2e1b3e4": "没有匹配的文件。",
+ "722a21e1a8": "正在加载文件...",
+ "1cb6ef47b7": "转到文件...",
+ "9e97f08d0f": "搜索要打开的文件",
+ "ec31e058f7": "转到文件",
+ "73b44e7bde": "复制安装命令",
+ "1cf8561ab4": "在远程启用快速、gitignore 感知列表:",
+ "5d80dc39bb": "ripgrep",
+ "2ca749c15d": "安装",
+ "4725b0e931": "快速打开扫描太大(",
+ "b227d88520": "找到 {{value0}} 文件",
+ "995be8ea22": "复制",
+ "cf144856dc": "已复制"
+ },
+ "SelectedTextCopyMenu": {
+ "9b40d7b018": "复制"
+ },
+ "StarNagCard": {
+ "92b0f9d921": "已通过身份验证并重试。",
+ "cd8c34aac1": "gh",
+ "cf82170065": "无法为该存储库加注星标。确保",
+ "30c36231c1": "如果 Orca 节省了您的时间,那么 GitHub 之星就会大有帮助。它可以帮助其他开发人员发现该项目并保持团队进行改进的动力。",
+ "b5e685e4d9": "关闭",
+ "5f6df21046": "喜欢 Orca 吗?",
+ "2d67b6c849": "在 GitHub 上加星标",
+ "af3c9bbb37": "主演…"
+ },
+ "TaskPage": {
+ "513cddfa7a": "正在验证...",
+ "ff69a30681": "取消",
+ "2abe22ef76": "您的令牌通过操作系统钥匙串加密并存储在本地。",
+ "246c2b3dd3": "Atlassian 账户设置",
+ "59c14d34a2": "创建一个令牌",
+ "b95623e93f": "Atlassian API 令牌",
+ "68df347677": "你@example.com",
+ "163df31e0e": "https://example.atlassian.net",
+ "33fc2bcb30": "使用 Jira Cloud 站点 URL、Atlassian 电子邮件和 API 令牌来浏览议题。",
+ "60f806ce99": "连接 Jira 站点",
+ "8ff6fdc368": "创建中…",
+ "fc0d8a1fa4": "提交。",
+ "919a20dd5b": "输入 {{value0}}",
+ "56cdb413a2": "逗号分隔值",
+ "1f0fce91e3": "选择{{value0}}",
+ "cbcdcbe244": "正在加载所需的 Jira 字段...",
+ "34d97ca682": "这是怎么回事?",
+ "f161bf9ede": "说明(可选)",
+ "578f730c16": "简短摘要",
+ "16cba35bee": "标题",
+ "ae592fee62": "议题类型",
+ "7d63e2626e": "加载中...",
+ "93c57f15e5": "没有找到项目。",
+ "cfb56a7868": "搜索项目...",
+ "00022ec0ba": "项目",
+ "0c11ca0b6d": "新建 Jira 议题",
+ "d0ca4aa1d0": "标签",
+ "1742eafc14": "没有项目",
+ "69591944e7": "低的",
+ "7fd59c18d8": "中等的",
+ "345b169f1f": "高的",
+ "f373ab1a4f": "紧迫的",
+ "713179dfdc": "无优先权",
+ "c8d5bec5f7": "优先事项",
+ "42a9160321": "未分配",
+ "d2a876ca53": "负责人",
+ "154b0fa623": "状态",
+ "9bc8aea407": "添加描述...",
+ "d9151fd4e9": "议题标题",
+ "4f3cb99f41": "切换团队",
+ "c11105dac5": "新一期",
+ "1b59a07674": "创建中...",
+ "cf72580c04": "撰写描述、项目简介或收集想法...",
+ "2ea1c701b6": "目标日期",
+ "7da41c9225": "目标",
+ "09623359b9": "开始日期",
+ "7d08e8be0f": "开始",
+ "af9e877f30": "无标签",
+ "d6cda23ef1": "会员",
+ "cfaadb6b22": "无铅",
+ "34da8ac06c": "带领",
+ "579f98afcd": "添加简短摘要...",
+ "ecbcc83140": "项目名称",
+ "b6795e65fd": "关闭",
+ "a98cbe7664": "团队",
+ "02f67c0d09": "新项目",
+ "bdebffcbfe": "为所选团队创建 Linear 项目。",
+ "1361275ec3": "新建 Linear 项目",
+ "7f3f7b4c18": "描述(可选,降价)",
+ "9f2b4c03a6": "提交",
+ "d3d0998b7d": "新的 GitHub 议题",
+ "d1e243795c": "议题",
+ "be8cf68d9f": "查看议题",
+ "67662ade50": "项目议题",
+ "6244a02f46": "在 Linear 中打开",
+ "606a85c774": "进行中",
+ "5e8061b088": "从 {{value0}} {{value1}} 开始工作区",
+ "592a55611b": "尝试选择更多的团队或者刷新;团队过滤器适用于当前获取的议题集。",
+ "618107fab3": "没有获取到与所选团队匹配的议题",
+ "903c7af49f": "未找到 Linear 议题",
+ "5ed38a49e5": "查看下面的工作区错误,然后刷新。",
+ "cc8795e07c": "无法加载 Linear 议题",
+ "f362667d55": "已更新",
+ "b1eaa18ace": "议题",
+ "37e7ee311e": "钥匙",
+ "b7bae28b6a": "显示",
+ "a26a48252e": "显示属性",
+ "5d2d835467": "订购",
+ "5659da12fc": "分组",
+ "9c57663908": "查看",
+ "af377b13b1": "{{value0}} 视图",
+ "d47248df4d": "Linear 视图模式",
+ "f397d513e3": "返回",
+ "b39fe6511d": "项目",
+ "8675cd6188": "Linear",
+ "733b8f2421": "Linear/视图",
+ "bc06ed0fb0": "返回视图",
+ "3cb855080f": "意见",
+ "b4e10f096e": "所有者",
+ "a04fe7ba73": "能见度",
+ "0aa8525950": "模型",
+ "dfc0c79bd8": "议题",
+ "8a07f21e76": "健康",
+ "851017590d": "添加 Linear 访问",
+ "228b25028f": "直接从这里浏览并开始处理分配给您的 Linear 议题。",
+ "6d56559467": "连接您的 Linear 账户",
+ "eee68073b2": "在 Jira 中打开",
+ "9497f2787c": "启动工作区",
+ "eba87f2edb": "未发现 Jira 议题",
+ "63b2abd3aa": "Jira 议题",
+ "e7115334aa": "隐藏 Jira",
+ "83bce6be5c": "连接 Jira",
+ "b518ae6307": "直接从此处浏览、编辑、创建 Jira 议题并开始工作。",
+ "a150c59da7": "连接您的 Jira 站点",
+ "bcdc1330b2": "在 GitLab 中打开",
+ "00b7ffb952": "类型/状态",
+ "eb10c32872": "ID",
+ "e9b6955dcd": "议题 #{{value0}}",
+ "a0544fb653": "先生!{{value0}}",
+ "8396825a14": "操作",
+ "c1d1600362": "在浏览器中打开",
+ "b6329379ca": "启动新工作区",
+ "054bf695cc": "草稿",
+ "285bc21dc5": "更改查询或清除它。",
+ "d0e3c8f933": "没有匹配的 GitHub 工作项",
+ "5b6b2af943": "正在重试...",
+ "0c0de0fc0e": "无法加载议题,来源",
+ "d1766fd62d": "项目加载失败",
+ "7762f4b03a": "的",
+ "443f7dd928": "合并",
+ "a7396b05c6": "检查项",
+ "f6fa3c97d0": "评审人",
+ "8aba10579d": "负责人",
+ "5eccb3c841": "标题/上下文",
+ "d4c2830063": "刷新 GitLab 工作项",
+ "c679af7ad9": "刷新我的待办事项",
+ "dfd72673e7": "无法保存项目选择。",
+ "b797bdd7c3": "清除搜索",
+ "99c2755218": "Jira JQL,例如项目 = ABC AND statusCategory != 完成",
+ "2ff9fd71fd": "刷新 Jira 议题",
+ "0b65d3fb2c": "搜索 Linear 项目...",
+ "eec0c5c079": "搜索 Linear 议题...",
+ "8964184a8b": "刷新 Linear",
+ "3feb524d42": "新建 Linear 议题",
+ "0cbf7e5cf3": "Linear 任务模式",
+ "ff53631e6f": "刷新 GitHub 工作",
+ "6ffa6be99f": "刷新 GitHub 工作",
+ "b15ceb409d": "搜索 GitHub 议题...",
+ "eee4df4c66": "搜索 GitHub PR...",
+ "e592d99051": "所有 Jira 站点",
+ "d09b7631b7": "切换 Jira 站点失败。",
+ "8029e2bd4d": "选择一个 Linear 团队以在 Linear 中打开",
+ "609532fae7": "无法保存默认任务源。",
+ "4826fd1ad8": "关闭 · Esc",
+ "1a06219d5c": "关闭任务",
+ "3f594861a5": "无法保存团队选择。",
+ "d0d570b306": "无法切换 Linear 工作区。",
+ "cb98f0350c": "创建 {{value0}}",
+ "1e1b2ad8f2": "在提交此议题之前,请从项目工作区选择一个团队。",
+ "3ca9b424a3": "创建项目失败。",
+ "3f9604efc7": "已打开议题 #{{value0}}",
+ "585dba2989": "无法打开此议题所附的工作区。",
+ "534a9c6017": "无法打开附加到此拉取请求的工作区。",
+ "fe380f306c": "无法保存默认任务视图。",
+ "af2a8371de": "无法加载 Jira 议题类型。",
+ "6775c05483": "无法更新 Linear 状态",
+ "745ae567d4": "“{{value0}}”不适用于 {{value1}}",
+ "669e419d65": "Linear 视图缺少工作区上下文。",
+ "cba2a2b7fb": "Linear 项目缺少工作区上下文。",
+ "f4374519ae": "您的首选议题源(upstream)已不再为 {{value0}} 配置。将使用 origin。",
+ "e9139db03f": "无法隐藏 {{value0}}。",
+ "b73717af92": "下一步",
+ "0c8df28045": "下一页",
+ "ae859c816b": "页{{value0}}",
+ "cd171f3391": "...",
+ "297a805b64": "以前的",
+ "6cd6b3ae6a": "上一页",
+ "e65757a338": "分页",
+ "37d60046e3": "打开 GitHub 合并框",
+ "1a9ea003dc": "无法禁用自动合并",
+ "a3318684bc": "无法启用自动合并",
+ "a5bf86defe": "自动合并已禁用",
+ "fed317634c": "启用自动合并",
+ "88f478cdef": "合并拉取请求失败",
+ "a161925adc": "拉取请求已合并",
+ "0506a78337": "这将更新 GitHub 上的拉取请求。",
+ "844dc193c7": "{{value0}} PR #{{value1}}?",
+ "995dd6af9b": "开放PR检查",
+ "8a22eb3f7b": "没有匹配的评审人。",
+ "67755a83a1": "其他人",
+ "3ace2e6bcf": "建议",
+ "0eacf48491": "加载中…",
+ "0b9b04f4b5": "输入或选择用户",
+ "62c7bd789f": "最多请求 15 名评审人",
+ "5d4fd69a6a": "最近活跃于此拉取请求",
+ "ed1daeb49a": "移除评审人失败",
+ "837bb901ec": "已移除评审人",
+ "f9191d1714": "已移除评审人",
+ "dc67f69962": "请求评审人失败",
+ "8f06dbb9e5": "已请求评审",
+ "969e26577c": "最多可请求 15 名评审人",
+ "d00571d9b1": "输入评审人",
+ "edf4bc4135": "没有可分配的用户。",
+ "53e002d895": "议题没有 repo slug。",
+ "7f94eb6395": "分配议题",
+ "bb63046423": "分配给 {{value0}}",
+ "ca63694b4c": "无法更新负责人。",
+ "b36f4bf9de": "没有标签。",
+ "5ebff3a0aa": "没有任何",
+ "d09bf34db7": "已关闭",
+ "1c893195ac": "更新状态失败",
+ "afc68824ff": "未找到任何州",
+ "cc13109b5d": "加载状态",
+ "d45a910c4a": "将 Linear 状态从 {{value0}} 更改为",
+ "d8a517ad89": "标识符",
+ "50387522d7": "没有分组",
+ "d747aed72f": "木板",
+ "a6f7e93d7f": "列表",
+ "e78ec261ed": "意见",
+ "727069bee5": "项目",
+ "137e2a8a01": "PR",
+ "18451e99df": "完成",
+ "4b6e40e42c": "全部开放",
+ "bd9965df51": "已报告",
+ "1301d376f1": "已分配",
+ "9cd11ba218": "Jira",
+ "11a828abf8": "GitLab",
+ "acef77f7ca": "GitHub",
+ "524f095d55": "待评审",
+ "7698af5263": "矿",
+ "94f0339621": "分配给我",
+ "c2268a9982": "全部",
+ "37a82eaaf8": "合并",
+ "887efe9140": "连接",
+ "a70153f583": "连接",
+ "6459faa8b3": "错误",
+ "e15ba2d2eb": "创建议题",
+ "3b11c8e8fc": "大批",
+ "e178c0a953": "在创建议题之前选择一个 Jira 项目。",
+ "0f7b0d964a": "在 {{value0}} 中创建一个新议题。",
+ "eff9800d4b": "{{value0}} 标签{{value1}}",
+ "d7f16d0e32": "选择团队",
+ "5301ca0f20": "创建项目",
+ "7719d8daa9": "{{value0}} 成员{{value1}}",
+ "5af6f0ae5b": "选择团队",
+ "cfb730b73e": "议题",
+ "3659f9792a": "木板",
+ "d079be2dc8": "没有分配的议题。请尝试搜索。",
+ "2bdefbcac3": "尝试不同的搜索查询。",
+ "25ff84769a": "没有议题与此 Linear 上下文匹配。",
+ "cbce2bc9cd": "没有任何",
+ "51411113df": "列表",
+ "60f68a2ef4": "Linear 议题",
+ "b2007ba885": "项目",
+ "6edf402e11": "概述",
+ "9ae151b26b": "Linear",
+ "94d900518d": "没有与所选预设匹配的议题。",
+ "f51e254d35": "尝试不同的 JQL 查询。",
+ "4645a7814f": "Jira",
+ "e224d76876": "先生",
+ "bbec4717ee": "先生",
+ "d6d08c1650": "选择一个项目以查看 GitLab 工作项。",
+ "f294c500ef": "没有 GitLab 工作与此过滤器匹配。",
+ "cd7dc432a3": "没有 GitLab MR 与此过滤器匹配。",
+ "171b7739d8": "太太",
+ "a9f256ecea": "没有与此过滤器匹配的 GitLab 议题。",
+ "2007e14d95": "GitLab",
+ "456b8512da": "合并请求",
+ "03da966159": "选择一个项目,以便我们可以向 GitLab 进行身份验证。",
+ "d591aac6ae": "没有待办事项。你们都被抓住了!",
+ "33a4bd7f5c": "待办事项",
+ "66ae7330f6": "更多操作",
+ "93d5f21fc1": "PR",
+ "e104fa3d3d": "从议题开始工作区",
+ "2193a99ec1": "打开议题所附的工作区",
+ "7deb9e59a5": "更多 PR 操作",
+ "7753652524": "恢复",
+ "e4b29c5bcf": "从 PR 启动工作区",
+ "67d881244c": "恢复关联 PR 的工作区",
+ "6430594b18": "作者不详",
+ "7799ad9ab6": "草稿",
+ "0bfbf62f75": "重试",
+ "38139edb52": "github",
+ "31f81cc334": "正在刷新 GitHub 工作...",
+ "3d93316bb0": "PR",
+ "937b29fa35": "项目",
+ "bc46d8204e": "选择一个项目在 GitHub 中打开",
+ "d1132848f8": "选择一个 GitHub 项目在 GitHub 中打开",
+ "2af3ab5c58": "选择一个团队在 Linear 中打开",
+ "aec5feeb69": "无法创建 Jira 议题。",
+ "7437e340b4": "无法创建议题。",
+ "9e03c17847": "打开 PR 详情以查看当前评审人。",
+ "3b7f34282f": "关闭"
+ },
+ "Terminal": {
+ "73768427cf": "关闭",
+ "f82e9f02df": "取消",
+ "7958465754": "有正在运行的进程的本地终端。还是关窗吧?",
+ "2fa9c69ff3": "关闭窗口?",
+ "cd51e28d8b": "保存",
+ "0037b21794": "不保存",
+ "21295c6b8c": "未保存的更改",
+ "5c1d2a32bb": "正在加载编辑器...",
+ "f0600556b3": "无法创建无标题 Markdown 文件。",
+ "37da0d736f": "新浏览器选项卡",
+ "a2a279b32a": "保存超时或失败。关闭前修复错误。",
+ "46e08bc5c8": "该文件有未保存的更改。",
+ "61ed600d29": "“{{value0}}”有未保存的更改。您想在关闭前保存吗?",
+ "cdc9ac4b2d": "编辑"
+ },
+ "TerminalSearch": {
+ "db234b7519": "关闭",
+ "7cb40c04eb": "下一场比赛",
+ "0f3066256e": "上一场比赛",
+ "42e466b9f1": "正则表达式",
+ "90c61387d9": "区分大小写",
+ "e07012f26e": "搜索..."
+ },
+ "UpdateCard": {
+ "68b235d264": "重启即可更新",
+ "02d4b8a6b9": "已下载。准备好后重新启动。",
+ "93794ea932": "Orca v{{value0}} 正在下载。",
+ "8acbdd3961": "最小化到状态栏",
+ "17412483da": "准备安装",
+ "47126bcf57": "手动下载",
+ "3553a8672f": "最后一个错误",
+ "90559b14e3": "这将在重新启动后打开进程范围的 Electron 网络开关。将其用于拒绝 HTTP/2 更新下载的企业 VPN 或代理。",
+ "6e45bfa2e0": "正在下载...",
+ "558842597d": "下载更新",
+ "f58b5c57a6": "新的:",
+ "ec8fe71cfc": "更新",
+ "44324ef542": "发行说明",
+ "fdd4a364fa": "会话不会被中断。",
+ "c4890662e9": "准备好了。",
+ "318d3b4bc7": "关闭更新",
+ "9abc59f814": "可用更新",
+ "aad383aecc": "阅读完整的发行说明",
+ "ccd8b0a793": "自您上次更新以来还有更多内容",
+ "b1d867f4fb": "更新期间您的终端会话不会中断。",
+ "09a55c39b5": "正在安装...",
+ "ea2a41adbe": "您使用的是最新版本。",
+ "ba5ffc949c": "正在检查更新...",
+ "2c2d3e03ca": "重试",
+ "4cf109845a": "更新错误",
+ "6b0085010d": "重新检查",
+ "48565a32bc": "重试下载",
+ "933c6fdf5b": "启用并重新启动",
+ "1339b82cee": "HTTP/2 下载被阻止",
+ "7274ef6e59": "关闭提示",
+ "a726967bd3": "关闭",
+ "d5253b54af": "错误",
+ "7ffc08506e": "查看",
+ "522df222b9": "旋转器"
+ },
+ "WorktreeJumpPalette": {
+ "ac037cfac2": "移动",
+ "75499e01d9": "关闭",
+ "66b5a67bee": "Esc键",
+ "45def60329": "进行中",
+ "f65d992a11": "进入",
+ "c5081f2814": "当前工作树",
+ "52404f8096": "当前选项卡",
+ "739bda980c": "基本的",
+ "556e7232ca": "当前",
+ "684e8d7bc2": "收集您最近的工作树和打开的选项卡。",
+ "ff908adfe9": "加载跳跃目标",
+ "1ebe225fee": "搜索工作树、设置、选项卡和操作...",
+ "4e4ff044d5": "搜索工作树、设置、选项卡和操作",
+ "4ee378034d": "跳转到...",
+ "f7fda8d562": "在 Orca 中创建工作树或打开选项卡即可开始。",
+ "1628fd7dfa": "没有活动的工作树、设置、操作或打开的选项卡",
+ "b781ae05e3": "键入以搜索工作树、设置、选项卡和操作。",
+ "f60f8730be": "没有其他工作树可供切换",
+ "c4afa68159": "尝试工作树、设置、操作、页面标题、模拟器、URL、PR 或端口。",
+ "dbd9d87eec": "没有结果符合您的搜索",
+ "2c38630a01": "工作区不再存在",
+ "7726ce9970": "移动模拟器选项卡不再存在",
+ "d7d496a451": "浏览器页面不再存在",
+ "50a1d11d5b": "打开标签页",
+ "088d66d980": "操作与设置",
+ "dabd819ca1": "输入以查看所有 {{value0}} 工作树",
+ "20af998bff": "{{value0}} 可用物品{{value1}}",
+ "bb72c08e63": "找到 {{value0}} 结果{{value1}}",
+ "34c8fbb46e": "SSH远程",
+ "63c2be1914": "SSH 已断开连接",
+ "95be6587d3": "创建工作树“{{value0}}”",
+ "worktreesHeader": "工作树",
+ "recentWorktreesHeader": "最近的工作树",
+ "settingsBadge": "设置",
+ "actionBadge": "操作"
+ },
+ "github": {
+ "pr": {
+ "merge": {
+ "state": {
+ "a80132573b": "GitHub 仍在计算此拉取请求合并状态",
+ "f958920f3a": "检查中",
+ "9bd983ce8f": "GitHub 表示此 PR 可以合并,但检查仍在运行",
+ "4e2507176b": "检查待处理",
+ "1432ecff30": "GitHub 说这个 PR 可以合并,但有些检查失败",
+ "87fa36ac83": "检查失败",
+ "1766eb46ba": "GitHub 报告此拉取请求已被阻塞",
+ "bf5e4c6c92": "已阻塞",
+ "c614e2660a": "合并前更新分支",
+ "039c072f94": "在后面",
+ "b37d45bca9": "GitHub 报告合并冲突",
+ "7e8bbe3cd7": "冲突",
+ "09896aad26": "此 PR 的合并状态不可用",
+ "bd4f27b50e": "合并",
+ "35ec24bc43": "该基础分支使用 GitHub 合并队列",
+ "b289646bcd": "GitHub 报告请求对此拉取请求进行更改",
+ "c606463dc2": "要求更改",
+ "a20db875ed": "GitHub 需要评审批准才能合并此拉取请求",
+ "1f8eb81c0e": "需要批准",
+ "f03028e055": "这个拉取请求仍然是一个草稿",
+ "ec8e2cebaa": "草稿",
+ "820fd21663": "此拉取请求已关闭",
+ "4f976d3450": "已关闭",
+ "62eb8d39da": "此拉取请求已合并",
+ "83ecdbb4a6": "合并",
+ "331ebe1170": "将此拉取请求添加到 GitHub 合并队列",
+ "b169f943e1": "准备好后合并",
+ "62703b1dc4": "为此拉取请求启用了 GitHub 自动合并",
+ "48d75ae118": "禁用自动合并"
+ }
+ }
+ },
+ "project": {
+ "ColumnResizeHandle": {
+ "1304289353": "调整列大小"
+ },
+ "GhAuthErrorHelp": {
+ "7e800068d8": "重新加载",
+ "baa006f9af": "文档",
+ "3fefeebde4": "复制刷新命令",
+ "9c2da6353b": "复制登录命令",
+ "b436c586d1": "复制命令",
+ "8a7f6bf5dc": "复制失败",
+ "224c9d0ae8": "已复制到剪贴板",
+ "891a7d4616": "未为此 shell 设置",
+ "fd17b3019f": "取消设置(PowerShell,持久)",
+ "ae43542893": "找到设置的地方",
+ "df636f5886": "检查是否已设置 (PowerShell)"
+ },
+ "ProjectCell": {
+ "4b5b871da8": "此存储库中没有标签。",
+ "2219e945ef": "加载中…",
+ "54cac64427": "Row 没有 repo slug。",
+ "8ae56a88a6": "标签",
+ "f7cdb78efb": "负责人",
+ "ebde486e3c": "清除",
+ "191905e20e": "当前和即将推出的",
+ "e17bb96881": "已完成",
+ "943b3dadc9": "该存储库没有议题类型。",
+ "c7b059cf07": "议题类型",
+ "c5f949e489": "议题",
+ "8d669084f6": "受限制的",
+ "6efdc0d920": "草稿",
+ "d0d0e13a5a": "PR",
+ "af5d8c912a": "限制物品",
+ "bb7ebc11e3": "添加号码",
+ "9cb1a0c984": "添加文字",
+ "2e26a06c70": "添加标签",
+ "36341ffc66": "分配",
+ "e369bf4fec": "选择",
+ "ffeff79861": "PULL_REQUEST"
+ },
+ "ProjectGroupHeader": {
+ "82a22d2079": "当前",
+ "244c9e7d06": "全部"
+ },
+ "ProjectItemSlugDialog": {
+ "e55a5c4e68": "项目行预览。",
+ "4450efea9c": "GitHub 项目"
+ },
+ "ProjectPicker": {
+ "96739284c3": "粘贴下面的项目 URL 以查找缺失的项目。",
+ "9b36829267": "未找到任何视图。",
+ "72a05c04a6": "正在加载视图...",
+ "9bf55fa1e8": "选择一个视图",
+ "a51b3337ab": "← 返回",
+ "8ab5447c64": "别针",
+ "5009ffc2f3": "移除销钉",
+ "fce99a24a7": "添加",
+ "5113ecc298": "通过 URL 或所有者/号码添加",
+ "7b6d39627e": "加载中…",
+ "b787682111": "浏览全部",
+ "ba0ab9a117": "浏览全部(加载中...)",
+ "b3044b7a25": "最近的",
+ "707843206c": "已固定",
+ "f492e1b539": "搜索项目",
+ "44b2c6326b": "无法加载视图:{{value0}}",
+ "ab1a2c357d": "路线图(不支持)",
+ "d34ef9b554": "看板(不支持)",
+ "43a88ae574": "板布局",
+ "1a2b8e512e": "桌子",
+ "cafb908f34": "表布局"
+ },
+ "ProjectRow": {
+ "75b5d816e3": "动手",
+ "e12be8b4d4": "在 GitHub 中打开",
+ "c3b81ddea2": "DRAFT_ISSUE"
+ },
+ "ProjectViewList": {
+ "989f81dc2a": "专栏",
+ "f949f5b2b7": "配置列",
+ "eddfc7a794": "按 {{value0}} 排序",
+ "4f57d2e0b1": "没有项目与此视图的过滤器匹配。"
+ },
+ "ProjectViewWrapper": {
+ "463f1205c0": "加载项目视图",
+ "23b87ba9f7": "在 GitHub 中打开",
+ "4d2a77a119": "文件功能请求",
+ "1bf8c01c8b": "切换到表格视图以在 Orca 中处理此项目。",
+ "55de4fb57a": "{{value0}}。 {{value1}} 在 {{value2}} 提交功能请求。",
+ "2edf5e7e77": "{{value0}} — Orca 尚不支持 {{value1}} 项目视图。在 {{value2}} 提交功能请求。",
+ "7245c3d7ac": "清除搜索",
+ "c5bc7ec007": "查看过滤器:{{value0}}",
+ "840c268665": "添加存储库",
+ "dffa899f36": "取消",
+ "7037c8f5f1": "存储库不在 Orca 中",
+ "512fc171d6": "选择一个项目来开始。",
+ "71fb69926c": "刷新",
+ "a8fa0d2bf5": "刷新中",
+ "fd15491034": "在 GitHub 中打开视图",
+ "22df63c393": "您的 Token 无法获取子议题数据。",
+ "067119985c": "GitHub 搜索,例如负责人:@我是:开放",
+ "1850fceac8": "{{value0}}/{{value1}} 未添加到 Orca。添加它以开始工作,或在 GitHub 中打开。"
+ },
+ "slug": {
+ "dialog": {
+ "AssigneesEditor": {
+ "529fec247b": "加载中…",
+ "98914e6b36": "负责人:",
+ "94a4e6e4fa": "没有任何"
+ },
+ "Comments": {
+ "fd5cccd138": "评论",
+ "1c95937c8b": "写评论...",
+ "c0e576e96b": "取消",
+ "c3e829b4d9": "保存",
+ "463d030ae4": "删除",
+ "8564f58542": "编辑",
+ "5f104bf855": "还没有评论。"
+ },
+ "LabelsEditor": {
+ "34dd57d6c8": "加载中…",
+ "a7b182fcda": "标签:",
+ "1a5366b5be": "没有任何"
+ },
+ "SlugDialogBody": {
+ "598ad6a517": "评论",
+ "41169e41fb": "添加描述...",
+ "a91735d19f": "取消",
+ "e64f6c3eff": "保存",
+ "e4ef8281e9": "加载中…",
+ "ae98897edf": "关闭",
+ "69caf40ae8": "在 GitHub 中打开",
+ "7c302f8174": "无题"
+ }
+ }
+ }
+ },
+ "GitHubMarkdownComposer": {
+ "015b4e607d": "取消",
+ "e3bd59143c": "插入",
+ "f24783f470": "https://...",
+ "ec6310b731": "使用 http:// 或 https:// 图片 URL。"
+ },
+ "IssueSourceSelector": {
+ "d6aeb2012b": "显示议题来自",
+ "787c970baf": "议题来源",
+ "643d7e9496": "上游",
+ "51d1608920": "起源",
+ "cdc9bd64fa": "紧凑",
+ "30b2c9df91": "上游"
+ },
+ "PRFilterDropdowns": {
+ "979be3cf6b": "负责人",
+ "b27b7e526c": "评审来自",
+ "7f1ba66c3e": "评审人",
+ "9d0f2eda6d": "标签",
+ "01f3f3d161": "作者",
+ "13b3ac0a84": "状态",
+ "79c54552f7": "过滤器",
+ "8a2ffbf9b3": "删除 {{value0}} 过滤器",
+ "19bb6f115f": "reviewed-by"
+ },
+ "PRFilterPickers": {
+ "fdf387297c": "清除 (",
+ "472c12ae03": "清除",
+ "2d1f58eda6": "使用"
+ },
+ "PRFilterSections": {
+ "a00830d3f7": "没有用户",
+ "0103e1cb18": "评审人",
+ "94b42b0edf": "已请求评审",
+ "de26e2eb06": "无标签",
+ "458ea3602b": "没有作者",
+ "b69fa4fa20": "返回",
+ "30ebb6ca44": "清除所有过滤器",
+ "8177eda37e": "筛选",
+ "ea3416d646": "负责人",
+ "b1d9fdea08": "标签",
+ "24754c44ad": "作者",
+ "764a0b4ce1": "状态",
+ "f0cf6dd591": "离开",
+ "1e9b5244f2": "在",
+ "b930de7194": "仅草稿",
+ "e0002f1eba": "已选择",
+ "2b2f019091": "任何州",
+ "0fd3249e2e": "已关闭",
+ "d78b60b5c2": "进行中",
+ "bd162b7d5a": "合并",
+ "2e639b84fa": "评审人",
+ "712c5abdbf": "标签",
+ "4e50c7bc03": "负责人",
+ "7bf3a6e5ac": "作者",
+ "66256a73b3": "状态",
+ "3ce4d5e96e": "PR"
+ },
+ "github": {
+ "rate": {
+ "limit": {
+ "display": {
+ "5509443543": "正在加载 GitHub API 预算...",
+ "34973d4695": "GitHub API 预算不可用。",
+ "d12d3d6f33": "刷新 GitHub API 预算",
+ "d5e5de9070": "Orca 通过 GitHub CLI 使用 REST、搜索和 GraphQL。",
+ "58c5f88216": "GitHub API 预算",
+ "6da1858354": "左·重置于",
+ "f42790d150": "的",
+ "01f7323e58": "GraphQL API",
+ "1daf0f22a9": "GraphQL",
+ "1f2f28a4de": "搜索接口",
+ "c377a4f06a": "搜索",
+ "c392c749a6": "休息API",
+ "bb227706a6": "休息"
+ }
+ }
+ }
+ }
+ },
+ "linear": {
+ "api": {
+ "key": {
+ "dialog": {
+ "834a52c084": "正在验证...",
+ "f8f704a019": "取消",
+ "e603ee9156": "工作区 API 设置",
+ "dc7ccb0f7c": "个人 API 密钥",
+ "e3100b36b9": "如果成员 API 密钥被阻止,请请求工作区管理员允许他们通过工作区 API 设置。",
+ "d56d3629f4": "当 Orca 应显示该账户可以在该工作区中访问的每个团队时,首选完全访问权限。受限密钥仅公开允许的团队,而私有团队需要密钥所有者才能访问。",
+ "af52a6227f": "从账户 > 安全和访问创建个人 API 密钥。",
+ "edec49dfae": "lin_api_...",
+ "7d498f653c": "个人API密钥",
+ "57a66522c8": "连接",
+ "c9889a09f8": "在创建关键帧之前,使用 Linear 选择所需的工作区。",
+ "e689a4d0a6": "错误"
+ }
+ }
+ },
+ "priority": {
+ "icon": {
+ "c43d3e065b": "优先事项:"
+ }
+ },
+ "project": {
+ "view": {
+ "surfaces": {
+ "8bbecb2510": "没有任何",
+ "e1fa97d21d": "选择一个项目以查看其概述。",
+ "1748d3b9af": "标签",
+ "65bda65159": "会员",
+ "c5f79616c3": "团队",
+ "25a2196732": "目标",
+ "3fb6473111": "开始",
+ "111bef9aa8": "带领",
+ "3be47aed6f": "优先事项",
+ "f5ef24cf46": "健康",
+ "9ddb58edbd": "状态",
+ "0a6a5a7dd6": "最新更新",
+ "c8db98b73b": "资源",
+ "bb1405eff8": "里程碑",
+ "5d99315fb8": "规划",
+ "3ad562bdf4": "范围议题",
+ "563501f191": "进度",
+ "bb5664d456": "无项目描述。",
+ "7b147907dc": "Linear",
+ "a9785c7158": "刷新",
+ "ee3d2caabd": "议题",
+ "5f79bc76b0": "返回项目",
+ "aac9a4afc6": "在 Linear 中打开",
+ "7616c986c6": "打开 {{value0}} 议题",
+ "93e1f6bfca": "加载中",
+ "98730088a6": "。在 Linear 中搜索或打开以查看完整列表。",
+ "06b887d622": "首先显示",
+ "2c4b1c2c08": "数字",
+ "f2cc1e0ff6": "Linear/项目",
+ "906b5e4cb8": "Linear/项目/{{value0}}",
+ "85607ff793": "项目",
+ "20b9d09b7d": "未知",
+ "f059181bd9": "私人的",
+ "27d91cb1a6": "共享",
+ "9f0f51fd9e": "在 Linear 中创建或保存视图,然后刷新。",
+ "f4c79cff5f": "查看下面的工作区错误,然后刷新。",
+ "ef90b21366": "未找到任何视图",
+ "c0a50f96a4": "无法加载视图",
+ "df4bd63c1d": "未分配",
+ "30402d2c6e": "尝试搜索或刷新。",
+ "a2f31c4cd6": "未找到 Linear 项目",
+ "c9b6e9f90d": "无法加载 Linear 项目"
+ }
+ }
+ },
+ "scope": {
+ "selector": {
+ "91c8871dad": "添加团队访问权限",
+ "7783361266": "所有团队",
+ "e1ae6bebb0": "团队",
+ "a14ce4df2b": "所有工作区",
+ "05baa5ae90": "工作区",
+ "89f6580dbf": "搜索团队...",
+ "b3488fad3c": "没有提取任何团队。访问权限可能取决于密钥范围、私有团队成员资格、存档团队、权限或获取失败。",
+ "405b33c378": "没有提取的团队与您的搜索相匹配。"
+ }
+ }
+ },
+ "notification": {
+ "sound": {
+ "options": {
+ "e38b0a2e68": "嘟",
+ "0acd3d384e": "唠叨",
+ "79919c832d": "丁",
+ "2b44847d8d": "布洛普",
+ "020826ef17": "声纳",
+ "588c90487d": "光点",
+ "1e4b81d892": "扑通",
+ "86af8d938c": "奉",
+ "80f7cc95b3": "二音",
+ "017abebfa6": "系统默认值"
+ }
+ }
+ },
+ "worktree": {
+ "creation": {
+ "WorktreeCreationPanel": {
+ "dabd226118": "关闭",
+ "34dd5ee38b": "重试",
+ "ed2a664f8b": "无法创建工作树",
+ "a3346fc6ed": "取消工作树创建",
+ "532aea14ce": "取消",
+ "767951265d": "创建工作树时出现问题。"
+ }
+ }
+ },
+ "workspace": {
+ "space": {
+ "WorkspaceSpacePage": {
+ "8d0048e1cb": "工作区磁盘使用情况和可回收工作树存储。",
+ "e8d6ba11ab": "测试版",
+ "45f6302dbc": "空间",
+ "ecf72fdc3b": "返回"
+ }
+ },
+ "cleanup": {
+ "WorkspaceCleanupDialog": {
+ "3828408538": "删除 {{value0}}",
+ "352f15d6fc": "最后活跃",
+ "cbf2f664e2": "删除",
+ "b6bae1eed1": "取消",
+ "592fbab446": "按最旧的活动排序",
+ "dba753e94f": "删除",
+ "38ca0b1400": "这将永久删除他们的本地文件。您无法撤销此操作。",
+ "c4f4782c02": "不建议",
+ "0a2e3c7cba": "评审",
+ "e97e4580c7": "肮脏的",
+ "9623a5107d": "未推送的提交",
+ "e8b3741ff7": "被忽略",
+ "a9957007eb": "忽略 {{value0}}",
+ "1bffc07ba7": "查看{{value0}}",
+ "bef0adef9b": "分支",
+ "0b1766738a": "回购协议",
+ "bbb1ab6a6f": "选择{{value0}}",
+ "d1094dd529": "待评审",
+ "4b93a235d8": "建议",
+ "f68d538c63": "此清理集中没有工作区。",
+ "4719327c9c": "所有清理建议都将被忽略。",
+ "a19040cd67": "没有与所选存储库匹配的非活动工作区。",
+ "97c772c4fe": "在检查的存储库中未找到非活动工作区。",
+ "d3eef9463d": "没有要删除的非活动工作区。",
+ "aaee139eab": "恢复忽略的建议",
+ "06cf78521e": "选择 {{value0}} 中的所有内容",
+ "73690b0031": "取消选择 {{value0}} 中的所有内容",
+ "b771c92598": "删除所选内容",
+ "37ab28277e": "不建议",
+ "1b18868569": "待评审",
+ "b299f201b9": "安全移除",
+ "2b31bf68de": "不活跃的",
+ "ac5ba84cc1": "已选择",
+ "8b74d4ea6e": "扫描工作树和 git 状态,然后在建议删除之前结合打开的选项卡、终端、实时代理和远程可用性信号。",
+ "7eee951968": "检查工作区安全",
+ "191f0bc98e": "关闭",
+ "7ae2ad30f4": "刷新",
+ "e0b5a4deaa": "在删除其本地文件和 Orca 状态之前查看非活动工作区。",
+ "b2c1331844": "删除不活动的工作区",
+ "41d594d01e": "{{value0}} 工作区{{value1}} 无法删除",
+ "0f00612b6d": "删除了 {{value0}} 工作区 {{value1}}",
+ "7f451a3e2c": "无法忽略清理建议",
+ "662b8ec3f8": "工作区清理扫描失败",
+ "bc43c37faf": "隐",
+ "0c6672f5e3": "忽略清理建议",
+ "fc49f79434": "混合的",
+ "2ddbd6fe8a": "检查过"
+ }
+ }
+ },
+ "ui": {
+ "color": {
+ "picker": {
+ "ebcf6ba29e": "无效的十六进制颜色。",
+ "faa855a582": "十六进制",
+ "1cec618bcc": "{{value0}} 选择器"
+ }
+ },
+ "dialog": {
+ "f26c4baeda": "关闭"
+ },
+ "repo": {
+ "multi": {
+ "combobox": {
+ "286ce70256": "SSH",
+ "4471d4a1c0": "没有符合您搜索条件的项目。",
+ "bfd8ce21c6": "所有项目",
+ "a58a0cd100": "搜索项目...",
+ "65a3dae41d": "没有项目"
+ }
+ }
+ },
+ "sheet": {
+ "1189e9fe0a": "关闭"
+ },
+ "team": {
+ "multi": {
+ "combobox": {
+ "de83523bf9": "没有团队符合您的搜索。",
+ "301f2a796e": "所有团队",
+ "18ec58881e": "搜索团队..."
+ }
+ }
+ }
+ },
+ "terminal": {
+ "quick": {
+ "commands": {
+ "TerminalQuickCommandActionToggle": {
+ "b0d58e37ed": "代理提示",
+ "b5ea4d64f6": "终端命令"
+ },
+ "TerminalQuickCommandAppendEnterSwitch": {
+ "e4e5fed3b3": "切换追加 Enter",
+ "c936c2d6d2": "立即提交,而不仅仅是插入文本。",
+ "5fa607d807": "追加输入"
+ },
+ "TerminalQuickCommandDialog": {
+ "925b8e0f6e": "高级",
+ "97e96cc027": "/目标",
+ "e604bd40d6": "支持技能、文件路径和内置命令,例如",
+ "79af0c0841": "npm 运行开发",
+ "577a342c7d": "要求代理调查此工作区",
+ "026cfb232a": "不支持提示命令",
+ "346d409ab2": "选择代理",
+ "0adba8fa0c": "代理",
+ "ec8f081919": "操作",
+ "ed04233b3e": "保存终端命令或代理提示以便快速访问。",
+ "ca414324ee": "命令文本",
+ "dc921c17ee": "迅速的",
+ "5b3f634a55": "添加快捷命令",
+ "f9b184fc16": "编辑快速命令",
+ "6751598542": "编辑"
+ },
+ "TerminalQuickCommandDialogFooter": {
+ "2e2b958dfc": "保存",
+ "8dff838dea": "保存 ({{value0}})",
+ "28370f16b9": "取消"
+ },
+ "TerminalQuickCommandLabelField": {
+ "66ea254301": "启动开发服务器",
+ "db17f1e41e": "标签"
+ },
+ "TerminalQuickCommandScopeField": {
+ "2db6edede7": "保存将保留现有项目范围,除非您选择另一个范围。",
+ "2496523a6f": "选择项目",
+ "2264edd5d3": "项目不在列表中",
+ "3834d24243": "项目",
+ "b83efc79e2": "全球的",
+ "c25cf350ef": "范围",
+ "f0631e4999": "回购协议"
+ }
+ }
+ },
+ "pane": {
+ "CloseTerminalDialog": {
+ "ebd2fa844d": "关闭",
+ "1d1a7a9c1f": "取消",
+ "6b9a6975f8": "终端仍有正在运行的进程。如果关闭终端,该进程将被终止。",
+ "78b79d854d": "关闭终端?"
+ },
+ "MobileDriverOverlay": {
+ "c6460cf584": "收回",
+ "c44659e09f": "移动驾驶",
+ "7cffad954c": "折叠",
+ "3eed73394f": "您的键盘已暂停",
+ "faa367dc74": "该终端的尺寸适合您的移动应用程序"
+ },
+ "TerminalAgentSessionForkDialog": {
+ "17fc841e59": "复制上下文",
+ "0c8a8629b1": "Fork 会显示为独立工作区,而非嵌套子项。新代理会收到一份有界转录稿,可作为可编辑草稿。",
+ "620461df22": "顶级分叉",
+ "619b5a35d2": "创建一个顶级工作区分支并使用捕获的上下文启动一个新的代理选项卡。",
+ "64e292e8e3": "分叉代理会话",
+ "9d25de2920": "创建分叉",
+ "2b10412cfc": "创建中..."
+ },
+ "TerminalContextMenu": {
+ "b4cdd9314e": "清晰的屏幕",
+ "8c17d6786d": "关闭窗格",
+ "2cf85a6a55": "复制窗格 ID",
+ "39809d152f": "设置标题...",
+ "06c2b0f043": "均衡窗格大小",
+ "98bccf4fa2": "向下拆分终端",
+ "20e565d865": "分体式端子右",
+ "8a7ddb8b8a": "分叉代理会话...",
+ "0a82b0608c": "添加快速命令...",
+ "9528a65ef8": "没有快速命令",
+ "3ce594a4a0": "全球的",
+ "ec85df5914": "快捷命令",
+ "0a917b591a": "粘贴",
+ "f3eeb1de13": "复制",
+ "c2f0b72b8d": "插入",
+ "925f49f210": "展开窗格",
+ "df766809e0": "折叠窗格"
+ },
+ "TerminalErrorToast": {
+ "e4aa243f8c": "重新启动守护进程",
+ "a7e2fd2699": "提交议题",
+ "5c8ce20be6": "如果这种情况持续存在,请",
+ "cc6d997c65": "从此处重新启动终端守护程序以清除过时的守护程序状态。"
+ },
+ "TerminalPane": {
+ "ac112e9036": "删除标题",
+ "f984ab2a30": "删除窗格标题:{{value0}}",
+ "cc5a2dc706": "编辑窗格标题:{{value0}}",
+ "7dbbfcbecc": "窗格标题"
+ },
+ "TerminalSessionStateSaveFailureDialog": {
+ "6bee0c8f17": "打开磁盘空间分析器",
+ "ae20d0ffc2": "关闭",
+ "38c282a2c4": "分析器直接从这里打开。您也可以稍后从左下角的工具箱菜单中选择“空间分析器”将其打开。",
+ "e2fcf07c0d": "Orca 无法保存此终端会话,因为本地存储已满或不可写。打开磁盘空间分析器以查找可以清理的工作区存储。",
+ "678c780a2c": "磁盘空间不可用"
+ },
+ "osc52": {
+ "clipboard": {
+ "blocked": {
+ "toast": {
+ "97c98f1afe": "打开设置",
+ "7cf51f74fd": "在终端设置中启用 TUI 剪贴板写入,以从 SSH、tmux、Neovim 或 fzf 进行复制。",
+ "89eaa3e80b": "终端剪贴板写入被阻止"
+ }
+ }
+ }
+ },
+ "stale": {
+ "agent": {
+ "row": {
+ "ad991ece5c": "代理的窗格不再可用。",
+ "090d607412": "陈旧代理行-{{value0}}"
+ }
+ }
+ },
+ "terminal": {
+ "agent": {
+ "session": {
+ "fork": {
+ "2317900211": "无法复制 fork 上下文。",
+ "88e34d00eb": "顶级会话分支在新工作区中打开",
+ "fd3d12a1e1": "无法创建 fork 工作区。",
+ "38e41edc6e": "该工作区无法分叉为 git 工作树。",
+ "f867385bb5": "找不到此分支的源工作区。",
+ "046e8d853c": "没有要 fork 的终端上下文",
+ "c00421d320": "已复制分叉上下文。启动代理并粘贴它以启动分叉。"
+ }
+ }
+ },
+ "drop": {
+ "handler": {
+ "1e072f611e": "无法上传 {{value0}} {{value1}}。",
+ "53f015fd85": "跳过 {{value0}} 符号链接 {{value1}}。",
+ "29c031b49a": "正在上传 {{value0}} 文件{{value1}} 到运行时...",
+ "0c77693641": "工作树尚未准备好 - 请稍后再试。",
+ "ce8248b835": "工作树路径不可用。"
+ }
+ }
+ },
+ "use": {
+ "terminal": {
+ "pane": {
+ "context": {
+ "menu": {
+ "a29b9faa01": "已复制窗格 ID"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tab": {
+ "group": {
+ "TabGroupPanel": {
+ "814fb04c43": "正在加载编辑器...",
+ "f7d6ce445e": "关闭组",
+ "0db2081805": "分裂",
+ "30137df7d0": "左分割",
+ "4df2a06d36": "分裂",
+ "ab1e2bff04": "右分割",
+ "9acaf92093": "窗格操作",
+ "1bce81dba6": "模拟器",
+ "1ff1c77616": "浏览器",
+ "586d2ac445": "终端"
+ }
+ },
+ "bar": {
+ "BrowserTab": {
+ "6e0bc8f3a8": "在浏览器中打开",
+ "9dd880bd56": "关闭右侧的选项卡",
+ "1611a1324b": "关闭",
+ "5d6e89891f": "重复选项卡",
+ "966feb9ad5": "右分割",
+ "7e8106899f": "左分割",
+ "2186a8407c": "分裂",
+ "96354ed249": "分裂",
+ "911542656f": "引脚标签",
+ "c5aaee8c39": "取消固定标签"
+ },
+ "EditorFileTab": {
+ "3da7445c84": "重命名文件 {{value0}}"
+ },
+ "EditorFileTabContextMenu": {
+ "52ce4f4605": "复制相对路径",
+ "5b85754786": "复制路径",
+ "bfd5797ef4": "打开 Markdown 预览",
+ "e5ff31ccaf": "关闭右侧的选项卡",
+ "ba1369dd24": "关闭所有编辑器选项卡",
+ "1ba8492c5b": "关闭",
+ "68cc610e7f": "重命名",
+ "f7c3d7d5af": "右分割",
+ "e3ff145b98": "左分割",
+ "1d04b1630b": "分裂",
+ "6b3efb106e": "分裂",
+ "fdd29eb669": "引脚标签",
+ "8e9d603a09": "取消固定标签"
+ },
+ "QuickLaunchButton": {
+ "348a04c1ad": "代理设置...",
+ "ec2adf093e": "在新终端中启动 {{value0}}",
+ "465e432ef1": "无法为 {{value0}} 构建启动命令。",
+ "e518f544b1": "未检测到代理",
+ "8dea9b5cdf": "没有启用代理"
+ },
+ "RecentTabSwitcher": {
+ "329638ff6f": "切换选项卡",
+ "07ad4cd0b7": "切换标签"
+ },
+ "SortableTab": {
+ "ab19f603eb": "重命名选项卡 {{value0}}",
+ "6df69d9388": "关闭选项卡 {{value0}}",
+ "fdb2691425": "折叠窗格"
+ },
+ "SortableTabContextMenu": {
+ "35e8892fd0": "标签颜色",
+ "2f697b3c31": "更改标题",
+ "c1ee099c7e": "关闭右侧的选项卡",
+ "8d16f9cd30": "关闭其他",
+ "89359a36f7": "关闭",
+ "21132389e9": "右分割",
+ "0ce4bae39d": "左分割",
+ "af80ed83c1": "分裂",
+ "591f9b12c1": "分裂",
+ "7703990447": "灰色的",
+ "845576bed1": "青色",
+ "be905e9b0a": "绿色的",
+ "69682e2ce4": "黄色的",
+ "a47629b3cf": "橙子",
+ "620aec6729": "红色的",
+ "03cf6dab1a": "粉色的",
+ "c2d8b0991f": "紫色的",
+ "cb3eadefd2": "Blue",
+ "20baa43c05": "没有任何",
+ "60f958ec75": "引脚标签",
+ "417722e9c2": "取消固定标签"
+ },
+ "TabBar": {
+ "b1a132357f": "新标签页",
+ "4f327c8b3d": "打开 Markdown...",
+ "3d5d6c960d": "新降价",
+ "fd2b42aaa3": "新的移动模拟器",
+ "aea43b5748": "打开现有的模拟器选项卡。",
+ "b426bb2615": "转到移动模拟器",
+ "4833fb2cbe": "新浏览器选项卡",
+ "d364f3c8d4": "新航站楼",
+ "7c1313d237": "新航站楼:",
+ "d1afac112b": "WSL",
+ "efb33546ff": "git 重击",
+ "1a8af49530": "命令提示符",
+ "2148f65e04": "电源外壳",
+ "ab589350e5": "无法为 {{value0}} 构建启动命令。"
+ },
+ "TabBarCreateEntry": {
+ "d62d63b807": "创建文件",
+ "25dc1cd653": "打开文件",
+ "7cdf8ee0c8": "打开网址",
+ "b27864279e": "启动代理",
+ "39676a184c": "打开任何文件、URL、代理..."
+ },
+ "TabBarQuickCommandsButton": {
+ "a2c7a33831": "添加命令",
+ "20bbd75896": "无命令",
+ "b82e237a4b": "更快捷的命令",
+ "85482c57bc": "运行快速命令",
+ "b775303755": "运行快速命令:{{value0}}",
+ "196593b6a9": "删除 {{value0}}",
+ "15529ede69": "编辑 {{value0}}",
+ "1d411fb6a5": "为此存储库保存快速命令",
+ "8f1e971966": "添加快捷命令",
+ "3220e2da27": "该快速命令将从您保存的列表中删除。",
+ "e8e1a52edb": "删除“{{value0}}”?",
+ "37e1bb90ce": "运行:{{value0}}",
+ "77ac113df0": "开始 {{value0}}: {{value1}}",
+ "7b1c9d6ae1": "跑步",
+ "c781f992e4": "destructive",
+ "be8f0ff166": "删除"
+ },
+ "shell": {
+ "icons": {
+ "d4ceaa227c": "git",
+ "e9b2e70613": "WSL"
+ }
+ },
+ "tab": {
+ "create": {
+ "entry": {
+ "classifier": {
+ "42e6262ae9": "没有可用的操作。",
+ "097a982ee0": "正在加载文件...",
+ "5a9c83c04b": "打开任何文件、URL、代理...",
+ "90eb94dc48": "输入 http:// 或 https:// URL。",
+ "5553b283ce": "输入 URL 或文件路径。"
+ }
+ }
+ }
+ }
+ }
+ },
+ "status": {
+ "bar": {
+ "PetStatusSegment": {
+ "3668339495": "删除 {{value0}}",
+ "cd8c6c654c": "宠物设置...",
+ "ed176ad68f": "导入 .codex-pet 包...",
+ "59b5955621": "上传您自己的...",
+ "0608ad02a2": "选择宠物",
+ "b75484a01a": "宠物尺寸",
+ "c6aa805b1b": "像素",
+ "2f7bbaa457": "尺寸",
+ "34c25dfe9c": "宠物",
+ "aec479308a": "宠物菜单",
+ "cef0ab4636": "导入宠物包失败",
+ "2021d4f6db": "Pet 包导入需要完全重启应用(不仅是重新加载)。",
+ "f395c9a685": "导入文件失败",
+ "e6234bcc17": "自定义宠物上传需要完全重启应用(不仅是重新加载)。",
+ "6d0a8cd179": "显示宠物",
+ "1fbc51cc77": "隐藏宠物"
+ },
+ "PortsStatusSegment": {
+ "4ebf90c12e": "未检测到外部端口",
+ "7dac3ecc9d": "外部端口",
+ "95495019ed": "端口扫描不可用",
+ "a8e4bdb412": "· {{value0}} 外部",
+ "9aa11005bf": "工作区·",
+ "c22ea609fd": "端口",
+ "a11ed266ce": "工作区",
+ "ca41be2802": "端口——",
+ "b8bc3e420a": "端口,{{value0}} 工作区 {{value1}}",
+ "3a87d54dfb": "未检测到工作区端口",
+ "c174bbbfed": "正在扫描工作区端口...",
+ "8caaa86e9a": "端口",
+ "45834a9ace": "端口"
+ },
+ "ResourceUsageStatusSegment": {
+ "946d9f94d0": "取消",
+ "67c4ecda49": "强制退出该终端。窗格中所有未保存的工作都会丢失。这无法撤销。",
+ "4bb076fa89": "强制结束",
+ "996295bff2": "孤儿终端",
+ "92924a14e3": "查看非活动工作区 (",
+ "27a74f91f0": "现在没有任何运行",
+ "1b24a32d3a": "记忆",
+ "298f4be7f2": "中央处理器",
+ "2aa2de6cb9": "姓名",
+ "30ff2c3c31": "孤儿",
+ "6449a95c78": "Orca 跟踪的进程占用了该计算机的物理 RAM 的大小。",
+ "e7ccce7e87": "系统内存",
+ "9e2525c89f": "Orca 持有的常驻内存加上每个工作树终端下的进程。",
+ "1fedf94eae": "组合 CPU 负载。高于 100% 的值意味着多个核心同时工作。",
+ "e7cf14ec78": "终端会话不可用。该列表可能已过时。",
+ "93b0de3c21": "重新启动",
+ "f85af9cda6": "资源快照和终端会话不可用。",
+ "f8e0d794b4": "守护进程没有响应",
+ "bd19fd7a59": "杀死所有会话",
+ "c9382662bb": "重新启动守护进程",
+ "59f178fe11": "{{value0}},守护进程无法访问",
+ "21cacb16d1": "· 偏僻的",
+ "73a3fd68a9": "折叠存储库",
+ "b12e31dfcb": "展开存储库",
+ "d659d71d2d": "恢复工作区 {{value0}}",
+ "bbcd9b7b85": "折叠工作区",
+ "c4a8968bdd": "扩大工作区",
+ "b10695d6ce": "终止会话",
+ "288a4dd177": "Orca",
+ "53dd5560ae": "折叠 Orca",
+ "e419d27083": "展开 Orca",
+ "41ae4fa725": "正在结束…",
+ "138b99bd80": "本次会话",
+ "888dad8c55": "加载中…",
+ "56b6888304": "运行时服务器隐藏本地资源使用情况。",
+ "14ff448686": "不可用于运行时服务器",
+ "6d9793d4bc": "资源管理器 - 终端",
+ "6a822b06a7": "资源管理器",
+ "ca95d077db": "守护进程无法访问",
+ "a82253b458": "删除工作区。",
+ "946724a70a": "主工作区无法删除。",
+ "16bc3c998a": "删除工作区 {{value0}}",
+ "0f9e50eb07": "其他",
+ "d406915b78": "渲染器",
+ "81cd37af99": "主要的"
+ },
+ "SshStatusSegment": {
+ "3ad70e0365": "管理 SSH...",
+ "6e8a9a4242": "SSH 连接",
+ "d09ec41831": "SSH",
+ "fdc57e9970": "SSH 连接状态",
+ "59b553e2aa": "断开连接",
+ "63f36455cc": "连接",
+ "bf07aee59e": "断开连接失败",
+ "2c29e2de68": "连接失败",
+ "bc5a3fd41a": "部分的",
+ "3d0128b105": "已连接",
+ "fd9a3c600e": "错误",
+ "fbb3f9f05e": "冲突",
+ "95e4ff5b4b": "推动",
+ "63a2b965f6": "拉"
+ },
+ "StatusBar": {
+ "9659e38343": "端口",
+ "d1e1a7a6bf": "资源管理器",
+ "24ac89df1a": "SSH 状态",
+ "5e59007df4": "Kimi 使用量",
+ "8c86cd77b0": "OpenCode Go 使用量",
+ "c1df0d67ec": "Gemini 使用情况",
+ "c0909c686e": "Codex 使用情况",
+ "3885eb74d8": "Claude 使用情况",
+ "c8857b40f7": "刷新使用数据",
+ "75ded02687": "管理账户…",
+ "ff0fbe9311": "当前",
+ "7657e3db9c": "Codex 账户",
+ "38b5647724": "Codex 使用量运行时",
+ "ba55303942": "打开 Codex 详情和账户切换器",
+ "4dff061aab": "·",
+ "2483c60695": "···",
+ "c35af53b73": "登录",
+ "f19a63e7cd": "登录查看使用情况",
+ "5c938d39ac": "% 周",
+ "d79c3362c4": "% 5小时",
+ "8295903d17": "切换后继续旧对话之前,请重新启动实时 Claude 终端。",
+ "c98ea88392": "没有其他账户",
+ "9332ba8684": "切换到",
+ "d450654fa2": "Claude 账户",
+ "11e2354daf": "Claude 使用量运行时",
+ "3dd7ddfae1": "打开 Claude 详情和账户切换器",
+ "59c6e7b4e0": "可见会话将立即重启。其他会话会在其工作树变为活动状态时重启。",
+ "c676918adc": "系统默认",
+ "3325d996cb": "刷新速率限制",
+ "fda8146810": "打开 Kimi 使用详情",
+ "629251f4b6": "打开 OpenCode Go 使用详情",
+ "d2375976eb": "打开 Gemini 使用详情",
+ "3d79122c3f": "kimi",
+ "d7a0668acc": "opencode-go",
+ "68efc0345c": "gemini",
+ "76b06d4da5": "claude",
+ "a28a5dd9b1": "错误",
+ "cd9d7b40ff": "重新启动 {{value0}} 会话",
+ "6cd6650b4c": "重新启动会话",
+ "1446d0d8a0": "{{value0}} 个 Codex 会话仍使用旧账户。",
+ "605901a495": "1 个 Codex 会话仍使用旧账户"
+ },
+ "StatusBarUsageEmptyCta": {
+ "828c764a79": "连接账户",
+ "caa0f39811": "支持:",
+ "97957ad3a3": "连接 AI 提供商账户,即可实时查看使用量并在账户间快速切换。",
+ "9a542f46c7": "从状态栏隐藏",
+ "84c3b15dca": "代理用量限制",
+ "d663430cf9": "连接AI账户查看使用情况"
+ },
+ "UpdateStatusSegment": {
+ "5cd13105a3": "更新失败。单击以展开。",
+ "2201df6987": "更新失败——点击查看详情",
+ "8533c12c3c": "更新失败",
+ "962404f68e": "更新准备安装。单击以展开。",
+ "248ee5d8ef": "Orca v{{value0}} 正在下载... {{value1}}%",
+ "57a29c3b0e": "更新准备就绪",
+ "fd1d3b3a1d": "更新下载,{{value0}}%。单击以展开。"
+ },
+ "WorkspaceSpaceCompactPanel": {
+ "a471aa9c24": "已更新",
+ "9be86c46a0": "可自由",
+ "f4d2651498": "已扫描",
+ "6a5dc3c61a": "评审",
+ "c361440dc0": "测试版",
+ "8ff597593d": "空间",
+ "0582df6d2e": "扫描",
+ "f5e1a84d79": "刷新",
+ "2af2174d6d": "取消",
+ "5691353a21": "停止",
+ "2837dc7c72": "取消",
+ "0583c806ac": "不扫描工作区磁盘使用情况。",
+ "39786e3b73": "扫描工作区大小。",
+ "bef4dc0457": "{{value0}} 可回收 · {{value1}} 不可用",
+ "3d8d47ce77": "{{value0}} · 保留最后的结果"
+ },
+ "WorkspaceSpaceManagerPanel": {
+ "2965415393": "强制删除失败",
+ "e031e93219": "没有匹配的工作区。",
+ "a02d84d2d2": "扫描工作区。您可以离开此页面。",
+ "be37293b10": "状态",
+ "33aef3e9cc": "尺寸",
+ "81f14d9924": "存储库",
+ "e4aebea158": "工作区",
+ "1d0f8300d1": "选择可见的可删除工作区",
+ "697d60c456": "清晰可见的选择",
+ "81aaf1de65": "仅显示可删除的工作区",
+ "d7ac56452e": "活动",
+ "243287ac60": "姓名",
+ "6f8f6a6b04": "过滤工作区",
+ "5caccea440": "删除所选内容",
+ "e4a12c455b": "清除",
+ "0cb1501ccf": "可回收的",
+ "65402b7192": "已选择",
+ "43171f3e60": "工作区",
+ "83f1a0a932": "可回收",
+ "09960d86bd": "已扫描",
+ "1cc6cd4c0f": "工作区",
+ "02b27c2230": "工作区",
+ "63efebe0e6": "{{value0}} {{value1}} 从空间中移除。",
+ "eee5240810": "工作区已删除",
+ "9afc97f9a3": "工作区已删除",
+ "792a214457": "删除工作区",
+ "a998501630": "力量",
+ "9155381019": "疏",
+ "f39d291997": "选择",
+ "16988df079": "没有找到文件。",
+ "b25c2c1086": "顶级项目",
+ "d3f9c69ddc": "飞涨",
+ "ef890d31b9": "全部",
+ "c28643d3da": "转到工作区",
+ "66870929fb": "议题",
+ "fb2069acb7": "评审",
+ "b9b4a3a25d": "分支",
+ "c432278ec7": "编辑器缓冲区",
+ "0bc756efaf": "Git 更改",
+ "e9528a89b3": "终端",
+ "a8d9e0de79": "代理",
+ "d384a4ce9f": "删除决定",
+ "7d7745bb8f": "可以删除",
+ "720870a18e": "保持:链接",
+ "cbc343a7a8": "保留:使用中",
+ "2055bc6a5a": "保留:未保存的编辑",
+ "ec7b076a75": "保留:git 未检查",
+ "7ab8d7e2d7": "保留:更改的文件",
+ "7f7895514e": "保持:活跃",
+ "2b501ee391": "保留:主要",
+ "39801484e0": "失败的",
+ "33653dbac2": "正在删除",
+ "52b629eb84": "已更新",
+ "e91dd2a9ae": "运行扫描以检查工作区大小。",
+ "61e25239da": "扫描中没有可用的工作区行。",
+ "8194a4fb29": "在收集任何工作区大小之前扫描失败。",
+ "b2f82ed5ae": "可删除",
+ "20a4204dce": "最后的成功结果仍然可见。",
+ "8c7c57fbf8": "扫描",
+ "508673bac0": "刷新",
+ "8dc9ddac8a": "取消",
+ "1fce91d1b9": "停止",
+ "d254f04097": "取消",
+ "265d956765": "{{value0}}。您可以离开此页面。",
+ "d595295d7d": "{{value0}} 可以从链接的工作树中回收。",
+ "34174bd83d": "{{value0}}。您可以离开此页面;最后的结果仍然可见。",
+ "433bb7f595": "好的",
+ "0ba046fbc5": "扫描失败。",
+ "5c6d25720c": "选择要检查的工作区。",
+ "c5135e7e4a": "扫描工作区大小。您可以离开此页面。",
+ "0990a63160": "尚无扫描的工作区大小。",
+ "977bdf9a36": "没有可显示的顶级项目。",
+ "131662ac65": "{{value0}} 打开"
+ },
+ "ports": {
+ "status": {
+ "popover": {
+ "rows": {
+ "a49ea79246": "转到工作树",
+ "f2b813345f": "工作区不可用",
+ "0e72c8d9fb": "停止进程",
+ "536d48a5dc": "复制 {{value0}}",
+ "085f4f0334": "在浏览器中打开",
+ "e4a709548c": "刷新端口失败",
+ "acdb6df590": "已停止 {{value0}} 上的进程",
+ "480d8f2347": "已复制 {{value0}}",
+ "b854ec9ff5": "无法打开浏览器"
+ }
+ }
+ }
+ },
+ "tooltip": {
+ "cedb7b99e3": "剩余 %",
+ "6d6df77f41": "无可用数据",
+ "7f7f208060": "每月",
+ "252c096536": "每周",
+ "94038ad2fa": "会话",
+ "2c35eca8d4": "无法获取使用情况",
+ "1292d4f2ee": "不可用",
+ "7567cd1c6b": "无法使用",
+ "a9a318b7a3": "刷新失败——显示缓存数据"
+ }
+ }
+ },
+ "stats": {
+ "ClaudeUsageDailyChart": {
+ "2a6360c7cb": "缓存写入",
+ "61c58f8976": "缓存读取",
+ "7d2efeff5e": "输出",
+ "d7fb787e6b": "输入",
+ "a7902d3c1d": "Token",
+ "059945f71d": "按天汇总的输入、输出、缓存读取和缓存写入。",
+ "c9f7cd30e9": "每日使用量"
+ },
+ "ClaudeUsagePane": {
+ "21ea00bfa8": "缓存",
+ "a8b7487ff7": "输出",
+ "faf3444859": "输入",
+ "0f03975d59": "轮次",
+ "1afc25eb06": "模型",
+ "c17bed0416": "项目",
+ "01476891c7": "最后活跃",
+ "abfc4a4943": "缓存复用率:",
+ "7e76c84153": "最近的会话",
+ "32176e1d44": "轮次",
+ "02a046792e": "会话 •",
+ "f97435845c": "主要项目:",
+ "7dc9e5613b": "按项目",
+ "c3fdbc5474": "常用模型:",
+ "0f394c24e3": "按模型",
+ "51ae85fa00": "缓存复用率 = 缓存读取 Token /(输入 Token + 缓存读取 Token)。",
+ "b26d4ddb58": "预估 API 等效成本",
+ "0f3e696ca9": "会话/轮次",
+ "8cc23be4a3": "零缓存读取轮次",
+ "1634c4f404": "缓存复用率",
+ "b786fb4a70": "缓存写入",
+ "268cf0af51": "缓存读取",
+ "2b8a2f14aa": "输出 Token",
+ "ea71fae8fc": "输入 Token",
+ "7dde9331fd": "此范围内尚无本地 Claude 使用记录。",
+ "424cd50412": "启用 Claude 使用量分析",
+ "8d18bbb771": "刷新",
+ "c5b9b344d0": "刷新 Claude 使用量",
+ "505be9aac4": "时间范围",
+ "f61cffb9c8": "范围",
+ "dd29209b21": "筛选",
+ "e9bf9fce0e": "Claude 使用量选项",
+ "6afacbee37": "Claude 使用量跟踪",
+ "0cb1a36d7d": "读取本地 Claude 使用日志,显示 Token、模型和会话统计。",
+ "5ce4842c2c": "所有本地Claude 使用情况",
+ "4f8368c272": "仅 Orca 工作树",
+ "cfe2282ffa": "未知",
+ "7765a4c3e1": "不适用",
+ "2d41fd45c6": "• 上次扫描错误:{{value0}}"
+ },
+ "CodexUsageDailyChart": {
+ "1e6f62d7e3": "推理",
+ "c646e1783c": "缓存输入",
+ "7b596a88b2": "输出",
+ "99a91d3143": "输入",
+ "e4bdcf0071": "Token",
+ "c756cda6a8": "按天汇总的输入、缓存输入、输出和推理。",
+ "609aa96e8b": "每日使用量"
+ },
+ "CodexUsagePane": {
+ "e0b988599d": "总计",
+ "bbd20344b8": "输出",
+ "3acc582214": "输入",
+ "bd0822ca47": "事件",
+ "c2478bcc3c": "模型",
+ "1a65900aea": "项目",
+ "0c36b100be": "最后活跃",
+ "0bd8655475": "此范围内最近的本地 Codex 会话。",
+ "0cb0983c07": "最近的会话",
+ "79a69522a5": "事件",
+ "bf1bf2f674": "会话 •",
+ "829ee743f2": "主要项目:",
+ "b98718aaab": "按项目",
+ "95d2d89285": "常用模型:",
+ "5a0d1d69cd": "按模型",
+ "94ac1f1ee7": "显示推理 Token 便于查看,但成本仅按未缓存输入、缓存输入和输出计算。",
+ "1a18fbd56b": "预估 API 等效成本",
+ "907b31865f": "会话/事件",
+ "6e18146e9b": "推理输出",
+ "a9ac0f423a": "缓存输入",
+ "5d8eba87bd": "输出 Token",
+ "e365eaa6fd": "输入 Token",
+ "4c865393b4": "此范围内尚无本地 Codex 使用记录。",
+ "f7c1affbd5": "启用 Codex 使用量分析",
+ "3022cda443": "刷新",
+ "ec4d270e2c": "刷新 Codex 使用量",
+ "89162e019b": "时间范围",
+ "6d68e8399a": "范围",
+ "1af1a39b2f": "筛选",
+ "70b5b8581f": "Codex 使用量选项",
+ "408210470c": "Codex 使用量跟踪",
+ "13badcd8f2": "读取本地 Codex 使用日志,显示 Token、模型和会话统计。",
+ "4fe8820098": "所有本地 Codex 使用情况",
+ "201766b754": "仅 Orca 工作树",
+ "bf6cf2d4dd": "未知",
+ "ae255c3dba": "不适用",
+ "247c93ca92": "• 推断定价",
+ "8a6655f7a2": "• 上次扫描错误:{{value0}}"
+ },
+ "OpenCodeUsagePane": {
+ "349f7c3f5c": "全部的",
+ "dfc4513657": "输出",
+ "0f2f266c9d": "输入",
+ "d416f5cf92": "活动",
+ "08c78441b7": "模型",
+ "a4738de041": "项目",
+ "d97bdf6e27": "最后活跃",
+ "81817a641a": "此范围内的最新本地 OpenCode 会话。",
+ "4799177b1c": "最近的会话",
+ "1e5d410df0": "事件",
+ "bc0cb89901": "会话 •",
+ "048ffe4d65": "顶级项目:",
+ "0f0a1684bb": "按项目",
+ "a15206a63a": "顶级型号:",
+ "040c044d39": "按型号",
+ "e5bb23d85e": "助手消息录制时,成本来自本地OpenCode数据库。",
+ "15c34d4b08": "记录成本",
+ "7e9433469a": "会话/活动",
+ "5a65d68b77": "推理输出",
+ "603504ee3b": "缓存输入",
+ "7aa4d8ce35": "输出 Token",
+ "d637a892ed": "输入 Token",
+ "bb6363e08c": "尚未找到此范围的本地 OpenCode 用法。",
+ "f04131b3be": "启用 OpenCode 使用情况分析",
+ "603cd138dc": "刷新",
+ "bed558df0b": "刷新 OpenCode 使用情况",
+ "b5ed5c9fd0": "范围",
+ "40d283c837": "范围",
+ "01583b30aa": "过滤器",
+ "230d6de108": "OpenCode 使用选项",
+ "bea80ceae0": "OpenCode 使用情况跟踪",
+ "b8b3522436": "读取本地 OpenCode 使用日志以显示 Token、模型和会话统计信息。",
+ "144a6050e9": "所有本地 OpenCode 使用情况",
+ "e04c58327c": "仅 Orca 工作树",
+ "362231082f": "未知",
+ "8095a63426": "不适用",
+ "6cc7782458": "• 上次扫描错误:{{value0}}"
+ },
+ "ShareUsageButton": {
+ "7d6b25323d": "分享到 X",
+ "b295c1c75d": "复制图像",
+ "bd82c76a70": "已复制",
+ "bce08eccb9": "分享使用情况",
+ "cecefa7c32": "分享"
+ },
+ "ShareUsageCard": {
+ "4a4c6c79a3": "会话·",
+ "66c83284cf": "每日 Token",
+ "b760c0b622": "顶级模特",
+ "2d9eb39264": "Token 总数",
+ "beb6f24f37": "预计。成本",
+ "da62578d9d": "用法",
+ "0eb31e79ee": "Orca IDE",
+ "960324e9b8": "事件",
+ "6adac63cfe": "轮流"
+ },
+ "StatsPane": {
+ "42d3e0bdf7": "使用情况分析提供商:{{value0}}",
+ "c79f073d4c": "使用情况分析",
+ "a58aba506f": "已创建 PR",
+ "1c96f433e2": "代理工作时间",
+ "9dbec9e675": "已启动代理",
+ "73ed07859c": "启动第一个代理以开始统计",
+ "1e696db2f6": "OpenCode",
+ "7d26110cea": "Codex",
+ "85457c02fe": "Claude",
+ "b2cf4310ce": "概览",
+ "908c470587": "codex",
+ "eb6a066185": "claude",
+ "eee19cfade": "overview"
+ },
+ "UsageOverviewPane": {
+ "22ed1b7669": "会话",
+ "444585cb41": "有数据",
+ "ecb0cd8a4c": "已启用 -",
+ "33f7b043d2": "供应商",
+ "60002bb22f": "尚未找到本地 Claude、Codex 或 OpenCode 使用情况。概览将在下一个代理会话写入 Token 日志后填充。",
+ "70f36452d4": "缓存共享",
+ "327603fe8b": "活跃天数",
+ "0eaf937335": "预计。成本",
+ "3887b94ce5": "Token 总数",
+ "2d13e57f72": "启用OpenCode",
+ "2f1ee2878b": "启用 Codex",
+ "0ea0cae435": "启用Claude",
+ "6c00c46815": "启用提供商以扫描本地代理日志并构建组合的 Token 账本。",
+ "49405ccc8d": "开始跟踪 Token",
+ "ca6bc5fded": "刷新",
+ "e06d1baf5c": "刷新使用概览",
+ "c760c481c5": "使用概述",
+ "55c910f4f1": "- 部分型号价格不详"
+ },
+ "share": {
+ "card": {
+ "utils": {
+ "19f4b4dc75": "github.com/stablyai/orca",
+ "d864fc5f98": "输出",
+ "5d66fdd7c2": "输入",
+ "7080aeaebb": "推理",
+ "4ee864629a": "缓存输入",
+ "33d38e2177": "输出",
+ "c2d7b23d57": "输入",
+ "9d166247ee": "缓存写入",
+ "cc28cb965e": "缓存读取"
+ }
+ }
+ },
+ "stats": {
+ "search": {
+ "cb6a9f0334": "缓存",
+ "eaf251e183": "Token",
+ "6953af58e6": "opencode",
+ "b77826fca3": "codex",
+ "e9dc37d889": "claude",
+ "8efeae0b22": "追踪",
+ "5acbe1fdf2": "时间",
+ "ef8bbf7739": "PR",
+ "ce8533f02e": "代理",
+ "0bba8ca244": "统计数据",
+ "0e2a0b6431": "用法",
+ "372debfac0": "统计数据",
+ "26bb901fcd": "Orca 统计数据以及 Claude、Codex 和 OpenCode 的综合使用分析、Token、缓存、模型和会话。",
+ "cb2430ae6a": "统计和使用情况"
+ }
+ },
+ "usage": {
+ "overview": {
+ "model": {
+ "bc474051e5": "OpenCode",
+ "eb220d193b": "Codex",
+ "544d6d4c16": "Claude"
+ },
+ "sections": {
+ "9564a3b21b": "会话 -",
+ "32330a6e66": "{{value0}}:{{value1}} Token",
+ "57d1448ef8": "启用",
+ "f6df0d7d6d": "更多的",
+ "1dd166c920": "较少的",
+ "52d9221dc0": "近期 Token 活动热图",
+ "c424eb3f8e": "最好的:",
+ "f28ff1f852": "近期 Claude、Codex 和 OpenCode 的综合 Token 活动。",
+ "69e2b50427": "每日强度",
+ "3a795542fa": "综合 Token 分布",
+ "e65084cb4b": "推理",
+ "3bc4a01b24": "汇总已启用提供商的输入、输出和缓存 Token。",
+ "4ff104da47": "Token 分布",
+ "0015facc1f": "缓存",
+ "7f270458af": "输出",
+ "9365b14a4e": "新输入",
+ "3de9bf87fc": "还没有型号"
+ }
+ }
+ }
+ },
+ "sparse": {
+ "SparseCheckoutPresetSelect": {
+ "c4ac80151d": "新预设",
+ "7c3275d307": "编辑 {{value0}}",
+ "c7f9b3f0c1": "离开",
+ "8b12c0850a": "保存",
+ "de8fce5854": "取消",
+ "ddbcaef7be": "src/渲染器包/ui",
+ "0e9ad9c798": "目录",
+ "064c1e2d12": "渲染器用户界面",
+ "b3a500c623": "姓名",
+ "16223dde6a": "加载预设",
+ "a683a4bc8e": "重试加载预设",
+ "14952d451e": "{{value0}} 目录",
+ "e9283eb171": "1 个目录",
+ "69c020eddc": "编辑预设",
+ "bd6cec2056": "新的"
+ }
+ },
+ "source": {
+ "control": {
+ "SourceControlActionVariableChips": {
+ "1b77798d5f": "变量",
+ "6b921a0ac2": "例子",
+ "4bf6d88039": "(空的)"
+ }
+ }
+ },
+ "skills": {
+ "SkillsPage": {
+ "cb142070b4": "刷新",
+ "984405683f": "插件",
+ "4d177feabd": "捆绑式",
+ "aa59462502": "存储库",
+ "571c5818c1": "家",
+ "0bc1379f4c": "所有来源",
+ "38e0951c3a": "代理技能",
+ "fb6bf60b52": "Claude",
+ "426be2aac6": "Codex",
+ "39b6998ddb": "所有提供商",
+ "a68dee6a32": "搜索技能",
+ "e46e162e2e": "从",
+ "b088e0785d": "测试版",
+ "f43ad6edf3": "技能",
+ "7e828fb2c6": "返回",
+ "ea72d6185b": "无法扫描本地技能",
+ "dc4c3328ee": "显示文件",
+ "9963dff6d3": "没有找到描述。",
+ "995fde8337": "无法显示技能文件",
+ "ab5b777350": "检查本地主目录、存储库、捆绑和插件技能文件夹。",
+ "08a321a984": "调整搜索或过滤器。",
+ "4acd6d68ec": "未找到本地技能",
+ "6a62a0168c": "没有匹配项",
+ "cd7893fbc1": "正在扫描技能",
+ "35b9a724a0": "可用的",
+ "0c74e7ff34": "当地的"
+ }
+ },
+ "sidebar": {
+ "AddProjectFromFolderDialog": {
+ "7d1f51678c": "添加项目",
+ "7726a16374": "取消",
+ "046751dbfb": "将此文件夹添加为单独的 Orca 项目。",
+ "e643b30398": "添加了远程项目"
+ },
+ "AddRepoCreateStep": {
+ "0ae45b8238": "我的项目",
+ "a8149a3a5a": "姓名",
+ "038729c107": "文件夹",
+ "11fd2a7db8": "Git 存储库",
+ "180e9b5e48": "项目种类",
+ "d877ece0d6": "创建 Git 存储库或普通文件夹并在 Orca 中打开它。",
+ "db9be12229": "开始一个新项目",
+ "5e97f0c4b9": "项目已创建",
+ "2c12db1511": "项目已添加",
+ "875dda0995": "输入服务器父路径。",
+ "45b7c26034": "创建项目",
+ "85085d74d2": "创建中…"
+ },
+ "AddRepoNestedImportStep": {
+ "496f68cf8c": "扫描存储库。单击停止。",
+ "a32bef9516": "停止扫描",
+ "2f8298f3c3": "停止扫描",
+ "c157f31a95": "作为组导入",
+ "40199ef7b3": "团体名称",
+ "b20bb7c24f": "将这些存储库放在一组中。最适合微服务等相关存储库。",
+ "787412361a": "什么是群组名称?",
+ "5f857ba8e6": "在",
+ "4df0d08cc5": "成立",
+ "8db50afe1a": "从文件夹导入存储库",
+ "5b2e6fe3c8": "单独导入",
+ "cf9d382ca1": "导入",
+ "220dd32d83": "扫描..."
+ },
+ "AddRepoRemoteStep": {
+ "5b205b5281": "停止扫描",
+ "6680289908": "/home/用户/项目",
+ "ef410aa881": "远程路径",
+ "0416bde073": "在设置中添加",
+ "df6fbcf880": "未配置 SSH 目标。",
+ "44637f43bd": "SSH 目标",
+ "80557be85a": "选择已连接的 SSH 目标并输入 Git 存储库的路径。",
+ "91b93a90a4": "打开远程项目",
+ "007651bdf9": "导航到目录并单击“选择”以选择它。",
+ "dd3ff65486": "浏览远程文件系统",
+ "36d427bb66": "添加远程项目",
+ "35831a7312": "添加..."
+ },
+ "AddRepoServerStartStep": {
+ "ae990c86a0": "返回添加选项",
+ "e1710bf831": "作为文件夹打开",
+ "8da4d1a5be": "添加 Git 项目",
+ "ac66a3ed2d": "浏览服务器文件系统",
+ "92d25420a0": "/home/用户/项目",
+ "867692f505": "服务器路径",
+ "423b5d3d31": "添加所选运行时服务器上已存在的 Git 存储库或文件夹。",
+ "3d0c035483": "打开服务器项目",
+ "438493f214": "或者手动输入服务器路径",
+ "6b9958492a": "想要一次导入多个存储库?浏览到父文件夹。",
+ "d40d751517": "新的存储库或文件夹",
+ "a81ffa0a99": "在服务器上创建",
+ "a2ea37d549": "远程 Git 存储库",
+ "47759c9491": "从 URL 克隆",
+ "516187414c": "现有项目或文件夹",
+ "0adf083af7": "浏览服务器",
+ "8efa930eb5": "从选定的运行时服务器添加另一个项目。",
+ "39bd249b3a": "添加项目",
+ "0f8aba944c": "导航到目录并单击“选择”以选择它。"
+ },
+ "AddRepoStartSteps": {
+ "f3c96237ae": "或者添加来自...",
+ "acf895cb42": "添加一个项目以开始使用 Orca。",
+ "d13757911c": "添加项目",
+ "d301db1c9a": "扫描存储库。单击停止。",
+ "69ea7f8dc4": "停止扫描",
+ "9906cae183": "停止扫描"
+ },
+ "AddRepoStepIndicator": {
+ "3bb655c117": "返回"
+ },
+ "AddRepoSteps": {
+ "569326d9cc": "选择文件夹",
+ "a93ef169b5": "浏览服务器文件系统",
+ "2ce3f6edf8": "/路径/到/目的地",
+ "04a4c4e84a": "克隆位置",
+ "b698a4a29d": "https://github.com/user/repo.git",
+ "3d4acbe693": "git 网址",
+ "5b2ea674b1": "输入 Git URL 并选择克隆位置。",
+ "c05f88a31f": "从 URL 克隆",
+ "fe8e629fe3": "导航到目录并单击“选择”以选择它。",
+ "df8b0e6c22": "添加了远程项目",
+ "3e64e8a70d": "连接失败",
+ "32a7256d85": "克隆",
+ "69f5b5380d": "克隆..."
+ },
+ "AutoRenameFailedDialog": {
+ "aed1623b1e": "关闭",
+ "eab8b45238": "复制错误",
+ "a23b22d16f": "已复制",
+ "74fc00776f": "错误详情",
+ "3afcad0497": "从第一条代理消息开始。",
+ "ff62a18580": "Orca 无法生成分支名称",
+ "ca3b225195": "分支自动命名失败"
+ },
+ "CreateProjectLocationField": {
+ "95548e33bf": "选择父文件夹...",
+ "632b456b1b": "改变",
+ "afaf54f245": "更改父文件夹",
+ "f520f83a97": "浏览服务器文件系统",
+ "2a20a603a3": "/home/用户/项目",
+ "134e37f711": "位置",
+ "b589b77997": "导航到目录并单击“选择”以选择它。"
+ },
+ "DeleteWorktreeDialog": {
+ "ff2a74ac0e": "和",
+ "91492c9ad6": "移除",
+ "4f6750ca7b": "删除工作区失败",
+ "42e610d6cf": "强制删除失败",
+ "5cc1a6701c": "打开设置",
+ "2b56b35f53": "您可以在“设置”中更改此设置。",
+ "dd3a45bbbd": "下次我们将跳过此确认。",
+ "fc23c4cbdf": "删除工作区",
+ "86f0ae1257": "删除工作区"
+ },
+ "DeleteWorktreeDirtyChangeHint": {
+ "8e2994ce28": "删除此工作区将从磁盘中永久删除这些更改。"
+ },
+ "DeleteWorktreeLineageNotice": {
+ "ad407c2d55": "更多的",
+ "a940f3c96e": "子工作区将被删除",
+ "29b98bf9cd": "删除此工作区也会删除 {{value0}} 子工作区。",
+ "66798cc6a2": "删除此工作区也会删除 1 个子工作区。"
+ },
+ "DeleteWorktreeSkipConfirmOption": {
+ "29aefb7e52": "不要再问"
+ },
+ "DeleteWorktreeWarningPanels": {
+ "026738155a": "(原始克隆目录)。",
+ "c4f96a6e18": "主工作树",
+ "e3be9eba15": "这是"
+ },
+ "ImportedWorktreesVisibilityLine": {
+ "b7a87dc32f": "在工作树列表中显示",
+ "ad99f4eea9": "保持隐藏",
+ "9f4f14e821": "稍后从项目菜单中更改此设置。",
+ "b2bc47c080": "更多位置",
+ "b47ba1a9d2": "{{value0}} 预览",
+ "2251d41ebb": "隐藏的工作树组",
+ "f54f2bec5d": "{{value0}} 隐藏 {{value1}} 的工作树",
+ "5a9688802a": "显示 {{value0}} 更多",
+ "294de4aeb2": "显示较少"
+ },
+ "NonGitFolderDialog": {
+ "e52454b7f6": "作为文件夹打开",
+ "05b33a17a9": "取消",
+ "8fba4b8cbb": "此文件夹不是 Git 存储库。您将拥有编辑器、终端和搜索,但基于 Git 的功能将不可用。",
+ "c49fb13492": "添加远程文件夹失败"
+ },
+ "OrcaYamlTrustDialog": {
+ "f3e2b868fb": "运行钩子",
+ "43b7bec4cd": "别跑",
+ "c494b3ccb1": "在",
+ "79afc6772b": "Orca.yaml",
+ "531689199b": "永远信任",
+ "bf800b7e04": "。仅当您信任时才运行",
+ "831f2cd9f0": "在你的机器上运行",
+ "aa3ffb33fb": "这个存储库的",
+ "c55beddbf8": "自您上次批准以来已发生变化。运行前请重新评审",
+ "95bf974a1a": "{{value0}} 脚本",
+ "9e52effffd": "新的 {{value0}} 脚本",
+ "e4a51dc4b3": "从 {{value1}} 运行 {{value0}}?",
+ "02b0ede5ad": "{{value0}} 的 {{value1}} 已更改 — 运行新版本吗?"
+ },
+ "PendingWorktreeRow": {
+ "af21e953d1": "取消工作树创建",
+ "188f6922a0": "取消"
+ },
+ "ProjectGroupDeleteDialog": {
+ "ca65b78f78": "取消",
+ "9be10d49ea": "并取消其项目的分组。",
+ "69f5cb97d0": "删除",
+ "591f330288": "删除项目组",
+ "2c14ce677a": "正在删除..."
+ },
+ "ProjectGroupNameDialog": {
+ "d99a034073": "取消",
+ "83dfbc5313": "群组名称",
+ "4a64e78822": "保存中..."
+ },
+ "RemoteFileBrowser": {
+ "2300612806": "键入要过滤的内容或输入路径...",
+ "9e060f5815": "选择文件夹",
+ "f8b1deb1a4": "取消",
+ "51001182e3": "空目录",
+ "971d85cc84": "作为远程项目打开 · {{value0}}",
+ "00c4235c10": "没有匹配“{{value0}}”"
+ },
+ "RemoveFolderDialog": {
+ "4dc5b5065b": "移除",
+ "d36883e046": "取消",
+ "8c097ef04e": "来自 Orca。它仍保留在您的磁盘上。",
+ "e62415c3d0": "这仅删除",
+ "b79b39d865": "删除项目"
+ },
+ "ScrollToCurrentWorkspaceToolbarButton": {
+ "23989bb663": "显示活动工作区"
+ },
+ "SetupGuideSidebarEntry": {
+ "b0a7bfc34c": "从侧边栏隐藏",
+ "88d402b71d": "入门清单"
+ },
+ "SetupScriptPromptCard": {
+ "ff1e819a11": "添加设置脚本",
+ "70715947fb": "安装脚本不能为空",
+ "888b83bf78": "无法保存设置脚本",
+ "a49196d538": "当 Orca 创建新工作树时运行。",
+ "d9f2db2738": "项目的设置",
+ "a5bb8c5135": "保存在这个",
+ "dcaa645da5": "好的"
+ },
+ "SetupScriptPromptCardViews": {
+ "96a7f4198c": "保存本地设置",
+ "3933401d28": "配置",
+ "31b8b01a45": "设置",
+ "4a98f907ae": "重试",
+ "0a98169776": "添加在 Orca 创建新工作树时运行的设置命令。",
+ "8349e3fa4c": "。保存它以运行新的工作树。",
+ "b56d1322f7": "找到一个设置命令",
+ "aef6c0a213": "保存已检测的命令,以便在 Orca 创建工作树时运行它。",
+ "660cdc17f8": "设置脚本。添加本地命令,或在“设置”中更改源。",
+ "8f6be51aa1": "Orca.yaml",
+ "bb879db364": "此存储库忽略共享",
+ "0155fb9ed3": "目前无法验证此存储库的设置脚本。",
+ "eefa756190": "手动配置",
+ "ca4efcbc25": "保存",
+ "d02e6a42b1": "检测自",
+ "fdbc6cb064": "已检测的安装脚本",
+ "7275f674cc": "已检测的设置",
+ "822ff300ad": "关闭",
+ "5bfd5c8779": "关闭安装脚本"
+ },
+ "SidebarFeedbackDialog": {
+ "8bf619e4cf": "取消",
+ "8de03e23c5": "仅提交您输入的反馈,或连接“gh”以包含 GitHub 身份。",
+ "d20439c560": "检查 GitHub 身份...",
+ "5b120b9634": "匿名提交",
+ "c9e5ea0791": "GitHub:",
+ "d46ddd66fc": "我们可以改进什么?",
+ "3460258a54": "关注 X",
+ "26108d3699": "加入 Discord",
+ "d245c4ef6c": "GitHub 议题",
+ "9b33530b3d": "其他联系我们的方式",
+ "a828fa4aee": "分享什么是有效的、什么是有问题的,或者 Orca 接下来应该做什么。",
+ "0eb643f07f": "发送反馈",
+ "60b721e857": "提交反馈失败。请再试一次。",
+ "7a46c228b8": "感谢您的反馈。",
+ "a2fd890d9e": "请在提交前输入反馈。",
+ "f2e42e1307": "发送",
+ "69969ba364": "正在发送..."
+ },
+ "SidebarFilter": {
+ "e3b3898218": "添加项目",
+ "92a23e6d07": "重置过滤器",
+ "81ded53722": "SSH",
+ "b9e8802e73": "没有匹配的项目",
+ "779b7ba05d": "清除",
+ "139877b384": "选择全部",
+ "5f7085a077": "项目",
+ "e5cb32a898": "隐藏默认分支",
+ "638a2d221d": "隐藏休眠项",
+ "f506a1262a": "过滤工作区",
+ "75405270ed": "编辑过滤器({{value0}} 活动)",
+ "489d1c8c9f": "搜索项目...",
+ "ee240a39eb": "编辑过滤器"
+ },
+ "SidebarHeader": {
+ "92154beb7e": "新工作区",
+ "49f62c5665": "工作区板",
+ "5c9c7c16aa": "添加项目以创建工作区",
+ "ca6f729da2": "新工作区 ({{value0}})",
+ "a30e34eb5c": "关闭工作区板"
+ },
+ "SidebarNav": {
+ "80611a8b10": "搜索",
+ "0c3395fd32": "搜索工作树和浏览器选项卡",
+ "c86d83b5c3": "新建",
+ "1b5c41caee": "Orca Mobile",
+ "9c95e1ce91": "代理",
+ "f323383e9a": "自动化",
+ "e7ad3c540d": "打开 Jira 任务",
+ "c39ab10000": "打开 Linear 任务",
+ "196c1b5362": "打开 GitLab 任务",
+ "0ccba862b8": "打开 GitHub 任务",
+ "fee535205b": "任务",
+ "d599269755": "从侧边栏隐藏"
+ },
+ "SidebarRepositoryFilterSection": {
+ "d3a9c4cea1": "清除",
+ "7679f0c268": "项目",
+ "f10ca29601": "删除 {{value0}} 过滤器",
+ "2656053db4": "SSH",
+ "83a820fa71": "筛选项目...",
+ "5a273fbfce": "添加项目...",
+ "4815c70605": "没有匹配的项目",
+ "bbbc6e8e3b": "没有匹配的未选择项目"
+ },
+ "SidebarSettingsHelpMenu": {
+ "ad3d3ed7f1": "重启 Orca",
+ "29c56f30ee": "检查更新",
+ "eb9884e55b": "Discord",
+ "5687ab246a": "GitHub",
+ "5f83d86d92": "变更日志",
+ "cdc87f897e": "文档",
+ "e565171a7c": "键盘快捷键",
+ "4cf5b868d7": "发送反馈",
+ "a428c25998": "设置",
+ "2991a0106c": "帮助",
+ "4e8f5710d3": "无法重新启动 Orca。",
+ "5161eef55d": "正在重启 Orca…",
+ "d396773ef0": "检查中"
+ },
+ "SidebarToolbar": {
+ "19e32d0e5f": "打开文件夹选择器以添加项目",
+ "abc62b6328": "添加项目"
+ },
+ "SidebarWorkspaceFilterSection": {
+ "c3fa13dc2e": "隐藏默认分支",
+ "ed1611b65b": "隐藏休眠项",
+ "82594419ba": "过滤器"
+ },
+ "SidebarWorkspaceOptionsMenu": {
+ "95c9754653": "代理活动布局",
+ "3d4b9c4997": "徘徊",
+ "ba87080fb7": "显示属性",
+ "320b675c9a": "卡片布局",
+ "09faabd875": "项目订单",
+ "7bada3b1ab": "排序方式",
+ "dc0bb670bc": "分组依据",
+ "9919ae1082": "工作区选项",
+ "bc96dbd041": "工作区选项 ({{value0}})",
+ "af9249c505": "最近的工作区活动",
+ "b451c8b162": "最近的",
+ "6664282a7b": "拖动项目进行排列",
+ "7b316bdd51": "手动的",
+ "7153d07485": "拖动工作区以将它们排列在每个组中。",
+ "2170d553cf": "项目",
+ "b759bb87ee": "需要关注的代理,然后是最近的活动。",
+ "503462f2b4": "代理活动",
+ "3728165cdd": "姓名",
+ "2a81e07366": "完整列表",
+ "25105b28cb": "紧凑",
+ "d7084e8bc8": "代理活动",
+ "b64d8bcca0": "端口",
+ "26c71e536c": "笔记",
+ "b8dcc6f321": "PR/MR链接",
+ "ca4d3c522e": "Linear 议题",
+ "91dfc653e8": "GitHub 票证",
+ "cc17bd443b": "详细的",
+ "0f9b959b31": "PR",
+ "e029a2d775": "状态",
+ "c2c7a45cda": "没有任何",
+ "680043342f": "紧凑",
+ "c7591b6014": "回购协议"
+ },
+ "SshDisconnectedDialog": {
+ "ca4a7892af": "正在连接...",
+ "89385db176": "关闭",
+ "656368f3a2": "重连失败",
+ "376bed88e5": "与远程主机的连接遇到错误。",
+ "4afcca1d24": "重新连接",
+ "11552bf786": "SSH 已断开",
+ "cb5938ae79": "正在重新连接..."
+ },
+ "SshTargetRow": {
+ "4677394048": "正在连接…",
+ "75ad429b5d": "连接"
+ },
+ "WorkspaceKanbanCard": {
+ "cefae8983e": "已固定"
+ },
+ "WorkspaceKanbanDrawerHeader": {
+ "f369f5c5a3": "关闭",
+ "e1a34450fc": "按状态组织工作区并打开工作区卡。",
+ "81870af08f": "已选择",
+ "c6a77ab0f4": "工作区板"
+ },
+ "WorkspaceKanbanPinDropTarget": {
+ "c30151c5ee": "拖放到此处即可固定,无需更改状态。",
+ "8fae2d0862": "已固定"
+ },
+ "WorkspaceKanbanSettingsMenu": {
+ "79eb990aa4": "添加状态",
+ "054cb50df7": "删除 {{value0}}",
+ "b45b350eb0": "向左移动 {{value0}}",
+ "8ce44af9a8": "重命名 {{value0}}",
+ "395e541d5d": "状态",
+ "34f03eb0de": "董事会设置",
+ "26cbc92150": "工作区板设置"
+ },
+ "WorkspaceKanbanStatusLane": {
+ "8ad104642b": "空的",
+ "3611d1ae7f": "调整工作区板列的大小"
+ },
+ "WorkspaceStatusAppearancePopover": {
+ "514be2f569": "将 {{value0}} 颜色设置为 {{value1}}",
+ "8be427206b": "图标",
+ "2ac106f6b2": "颜色",
+ "74b1413279": "外观",
+ "ccbd1e2c69": "自定义 {{value0}} 外观"
+ },
+ "WorktreeCard": {
+ "a88c92d0e3": "已经存在。",
+ "6f09f58541": "删除工作区",
+ "0777de5970": "主工作树(原始克隆目录)",
+ "0f33af979b": "部分结帐。这些路径之外的文件不在磁盘上。",
+ "4f964d5e8c": "疏",
+ "7d517f82e2": "基本的",
+ "c6833b5187": "将从第一条代理消息中重命名",
+ "f62a3dadbc": "重命名待定",
+ "4eba2ea99e": "自动命名失败。点击查看详情。",
+ "74522ee457": "重命名失败",
+ "02e19349f4": "自动重命名失败:查看错误",
+ "691ccfd622": "正在删除...",
+ "35ccfe2475": "项目{{value0}}",
+ "1d66d84f0b": "字符串",
+ "57eaa61b55": "隐藏子工作区",
+ "8cb634cda6": "显示子工作区",
+ "01f45d3d8a": "侧边栏",
+ "93aebe4529": "文件夹",
+ "0d224eff10": "主要工作树",
+ "ca74db7550": "通过 SSH 远程项目",
+ "021538e1d1": "SSH 已断开连接"
+ },
+ "WorktreeCardAgents": {
+ "1b0a156717": "代理"
+ },
+ "WorktreeCardMeta": {
+ "3e65e11cc6": "工作区元数据",
+ "c7fa72ead0": "编辑笔记",
+ "93cbea12c2": "笔记",
+ "eace1d2cf6": "Neutral",
+ "dbe2d18972": "更多 {{value0}} 操作",
+ "ae76907ca6": "取消链接 {{value0}}",
+ "ad25c3ff05": "在 {{value0}} 上查看",
+ "2c67730e07": "在 Orca 中打开",
+ "e42941631a": "Linear 视图",
+ "5e982e6128": "Linear {{value0}}",
+ "807b13b9ec": "编辑议题",
+ "b22f058067": "在 GitHub 上查看",
+ "e97d8f2876": "议题 #{{value0}}",
+ "3ea2702e62": "已链接 {{value0}} #{{value1}}",
+ "b105fd3057": "链接Linear {{value0}}",
+ "3f2649eeb8": "链接议题#{{value0}}",
+ "fe075cb851": "工作区笔记"
+ },
+ "WorktreeCardMetadataStatusBadges": {
+ "fe188062a1": "状态:开放",
+ "2931b42b09": "状态:草案 {{value0}}",
+ "e888362def": "状态: 关闭",
+ "f394b3e86e": "状态:合并",
+ "af2b07bda5": "州:{{value0}}",
+ "29df45afa2": "先生"
+ },
+ "WorktreeCardPorts": {
+ "34f733dda2": "转到工作树",
+ "3240f320d7": "实时端口",
+ "3e5f66564e": "工作区不可用",
+ "2f854442ff": "停止进程",
+ "c8067a829a": "复制 {{value0}}",
+ "33bc7d7495": "在浏览器中打开",
+ "9950fe2d20": "刷新端口失败",
+ "5d1a5d51bb": "已停止 {{value0}} 上的进程",
+ "c89f290e25": "已复制 {{value0}}",
+ "d1113f4660": "无法打开浏览器",
+ "fed49903c9": "{{value0}} 直播 {{value1}}"
+ },
+ "WorktreeContextMenu": {
+ "c39c37676a": "创建一个组并将该项目移入其中。",
+ "6664418e98": "新项目组",
+ "e091caab15": "找不到该项目",
+ "439fa94d53": "更新",
+ "579b1a8e61": "从父级中删除",
+ "8d9cd19d09": "打开父工作区",
+ "d35dfeae58": "从组中删除",
+ "76865d827f": "移至群组",
+ "503ec0f8e6": "来自项目的新组",
+ "3350101edb": "复制路径",
+ "f4475537d8": "删除",
+ "f5ac91531d": "从 Orca 中删除项目",
+ "b42391d8bf": "正在删除...",
+ "0918b35e4f": "关闭此工作区中的所有活动面板以释放内存和 CPU。",
+ "7d190f7d2b": "关闭选定工作区中的所有活动面板以释放内存和 CPU。",
+ "84cdbb7e30": "移至状态",
+ "56cde9e8e6": "将状态移至",
+ "f50603c6b2": "标记为未读",
+ "8dacff1fe0": "马克·里德",
+ "3baa7d6507": "别针",
+ "697d0f6e1b": "取消固定"
+ },
+ "WorktreeList": {
+ "d880ea0744": "创建一个组并将该项目移入其中。",
+ "bc1460beb3": "更新侧栏中显示的组名称。",
+ "13757c053c": "新项目组",
+ "f9dc6cc5d3": "重命名项目组",
+ "370c6a55dd": "清除过滤器",
+ "b7acbf038b": "未找到工作区",
+ "0c6ee14f23": "孩子",
+ "5fc9d1891b": "正在删除...",
+ "c83968f87f": "删除项目",
+ "64e55f7f01": "从组中删除",
+ "4a08fb55f2": "移至群组",
+ "cbfd565f83": "来自项目的新组",
+ "e82d3589a1": "更改项目图标",
+ "2cdffbc728": "项目设置",
+ "2ef41bf9a7": "项目操作",
+ "609633a9e6": "{{value0}} 的项目操作",
+ "902115cdbe": "删除群组",
+ "4d7b73658c": "重命名组",
+ "79465e9034": "{{value0}} 的分组操作",
+ "bfbedc547b": "工作树",
+ "45fbfe0335": "重命名",
+ "ebc5c7dcef": "隐藏子工作区",
+ "84a2238242": "显示子工作区",
+ "045a8aed48": "孩子们",
+ "2ca6e29a3c": "回购协议",
+ "bb85cd86ba": "为 {{value0}} 创建工作区"
+ },
+ "WorktreeMetaDialog": {
+ "3db0a2a593": "取消",
+ "b48c271d39": "要保存,请按 Shift+Enter 换行。",
+ "7f0be5e9a6": "支持 **markdown** — 粗体、列表、“代码”、链接。按 Enter 或",
+ "030d484fc0": "关于此工作树的注释...",
+ "9c1d1e9b71": "评论",
+ "5ae06f40fd": "粘贴拉取请求 URL,或输入数字。留空以删除链接。",
+ "077a4f7b5c": "PR # 或 GitHub URL",
+ "1b91db7e14": "生长激素受体",
+ "7c454be4c5": "粘贴议题 URL,或输入数字。留空以删除链接。",
+ "029ea5ec57": "打开 GitHub 议题",
+ "741279e7b7": "议题编号或 GitHub URL",
+ "645fa4a0fd": "GH 议题",
+ "459ad7f650": "仅更改侧边栏中显示的名称 - 磁盘上的文件夹保持不变。留空以使用分支或文件夹名称。",
+ "7f21e0464f": "自定义显示名称...",
+ "ad5e4e514f": "显示名称",
+ "65770ad0f0": "编辑此工作区的 GitHub 链接和注释。",
+ "382fd11a3e": "编辑工作树详细信息",
+ "2174f17011": "保存",
+ "61d6f612cf": "保存中..."
+ },
+ "WorktreeOpenInMenu": {
+ "1417fd8380": "自定义应用程序...",
+ "8009ab69a6": "打开于",
+ "bd0e8159f8": "检查本机上的编辑器命令或文件管理器配置。",
+ "9a5381eb09": "无法打开工作区文件夹。",
+ "0bed8727db": "它可能已被移动或删除。刷新工作区或将其从 Orca 中删除。",
+ "3921d3d9a5": "找不到工作区文件夹。",
+ "f387af445b": "工作区路径不是有效的本地路径。",
+ "3ec372b664": "文件管理器"
+ },
+ "WorktreeTitleInlineRename": {
+ "2f42ae024f": "未读:",
+ "bff3bdd00c": "重命名工作区",
+ "8df295a78d": "无法重命名工作区。"
+ },
+ "WorktreeVisibilityDialog": {
+ "83a5ba8dd1": "非 Orca 工作树",
+ "f1f71b9f02": "导入",
+ "759371df43": "隐藏",
+ "25ddf19920": "{{value0}} 可导入",
+ "8372e4bbd9": "当前显示 {{value0}}",
+ "5d02a5647f": "从侧边栏隐藏",
+ "3e045d4cb8": "显示在侧边栏中"
+ },
+ "add": {
+ "repo": {
+ "local": {
+ "start": {
+ "actions": {
+ "d72789705e": "从空文件夹开始",
+ "c709860596": "创建新项目",
+ "5f9ffac036": "克隆远程 Git 存储库",
+ "7edb8ebe24": "从 URL 克隆",
+ "a6c20dca96": "从 SSH 目标打开项目",
+ "3d162cc76f": "远程项目",
+ "fb4fc5380e": "本地项目、Git 存储库或包含多个存储库的文件夹",
+ "2281fdc8c7": "浏览文件夹"
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "worktree": {
+ "flow": {
+ "b81b4e40ca": "如果工作区列表看起来过时,请刷新空间并重试。",
+ "7243145cd6": "未选择可删除的工作区",
+ "ae57cbf6e4": "删除工作区失败",
+ "7488ed8711": "查看",
+ "2b20ce87b3": "强制删除",
+ "4f3876c0f5": "强制删除失败"
+ },
+ "toast": {
+ "1d0fa5c0a5": "无法删除工作区 {{value0}}",
+ "ead7b8ee15": "它已更改文件。无论如何,请使用强制删除将其删除。",
+ "905fc8efac": "Git 已经删除了这个工作区。使用强制删除将其从 Orca 中清除。",
+ "0899ebdb28": "Git 已经忘记了这个工作区,但它的目录仍然在磁盘上。使用强制删除来删除孤立目录。"
+ }
+ }
+ },
+ "remote": {
+ "file": {
+ "browser": {
+ "helpers": {
+ "4dbd72a7d7": "{{value0}} 不是 {{value1}} 中的目录",
+ "be266af66c": "{{value0}} 匹配 {{value1}} 中的多个目录"
+ }
+ }
+ }
+ },
+ "repo": {
+ "header": {
+ "create": {
+ "state": {
+ "992cfbc44b": "为 {{value0}} 创建新工作树",
+ "3a70acd808": "在为 {{value0}} 创建工作区之前重新连接 SSH 目标",
+ "6d022563a8": "创建工作区之前重新连接 SSH 目标",
+ "62e71f2d5d": "为 {{value0}} 创建工作区"
+ }
+ }
+ }
+ },
+ "sidebar": {
+ "project": {
+ "drop": {
+ "669e12dd97": "本地文件夹和 Git 存储库",
+ "ffc769ca29": "删除文件夹以添加项目",
+ "740e8d0d46": "使用“添加项目”作为服务器路径",
+ "e344666fb8": "服务器运行时处于活动状态",
+ "d0f8943f8b": "准备项目添加流程",
+ "18d3cf40e9": "检查文件夹"
+ }
+ }
+ },
+ "sleep": {
+ "worktree": {
+ "flow": {
+ "c460fecc4a": "无法睡眠某些工作区",
+ "8bc3fc0671": "无法睡眠工作区"
+ }
+ }
+ },
+ "useAddRepoCloneFlow": {
+ "4d0013cc93": "克隆存储库",
+ "0dc4d1b657": "输入克隆目标的服务器路径。"
+ },
+ "useAddRepoLocalFolderFlow": {
+ "7ab10e4974": "使用服务器路径从远程运行时添加项目。"
+ },
+ "useAddRepoNestedImportFlow": {
+ "680cac2c82": "{{value0}} 失败",
+ "cbfbc7a797": "某些存储库无法导入",
+ "1b33c5f090": "没有导入存储库"
+ },
+ "useSidebarProjectDrop": {
+ "f34a286c0d": "无法添加删除的文件夹。",
+ "451a4638db": "拖放文件夹以将其添加为项目。",
+ "5ccb56c7be": "使用“添加项目”输入服务器路径。",
+ "849ef13dc0": "本地文件夹放置对于服务器运行时不可用。",
+ "c0315153d1": "一次放下一个文件夹。"
+ },
+ "workspace": {
+ "status": {
+ "cb387159f6": "进行中",
+ "6c1efa2cf8": "评审中",
+ "6b8285b8dd": "完成",
+ "93ac840dcb": "已阻塞",
+ "2c19d1db33": "Play",
+ "111db162bf": "已暂停",
+ "642da473f2": "警报",
+ "6380517b10": "Flag",
+ "251c817bdd": "定时器",
+ "409528031f": "评审",
+ "5f9ca31a84": "等待中",
+ "821d156f54": "虚线",
+ "226d1e7773": "进度",
+ "a702bc08d4": "圆点",
+ "b4a7101fe1": "圆形",
+ "1a9383112b": "Conductor 进度",
+ "caebe3c10f": "Conductor 评审",
+ "895f381714": "Conductor 完成",
+ "caabd5ca85": "Zinc",
+ "7adb43ecf0": "Rose",
+ "ddf25b6262": "Emerald",
+ "7cebab6d4a": "Amber",
+ "1b81da243a": "Violet",
+ "6437a8c253": "Sky",
+ "fc3b92756c": "Blue",
+ "52e3c6e2a4": "Neutral"
+ }
+ },
+ "worktree": {
+ "card": {
+ "compact": {
+ "agents": {
+ "a128d7006b": "{{value0}} {{value1}} 儿童 {{value2}}",
+ "289a1d2ca7": "展开{{value0}}。 {{value1}}",
+ "0c1debfe84": "折叠 {{value0}}"
+ }
+ }
+ },
+ "list": {
+ "groups": {
+ "0ed04075b8": "全部",
+ "4aeefc5996": "已固定",
+ "682ed5d551": "已关闭",
+ "7c2f009786": "进行中",
+ "6798dc7c94": "评审中",
+ "5076efc3d2": "完成"
+ }
+ }
+ },
+ "CacheTimer": {
+ "07729cc155": "已到期"
+ },
+ "DeleteWorktreeDialogFooter": {
+ "c0e972d726": "取消",
+ "cf95e3b5bb": "关闭"
+ },
+ "index": {
+ "b826a98b6f": "忙碌的"
+ }
+ },
+ "shared": {
+ "useDaemonActions": {
+ "01af244097": "取消",
+ "28c8e53176": "这会强制退出所有工作区中每个正在运行的终端窗格。这些会话中所有未保存的工作都会丢失。守护进程本身保持运行,并且可以立即打开新终端。这无法撤销。",
+ "1bbea41a77": "杀死所有终端会话?",
+ "01d6b7c64e": "终止每个正在运行的终端窗格并重新启动守护进程。窗格显示“进程已退出”并且可以立即重新打开。先前应用程序版本的旧协议会话将被保留。这无法撤销。",
+ "922548bc66": "重新启动终端守护程序?",
+ "2b4efdc162": "无法终止会话。",
+ "d18f3005c2": "{{value0}} 会话{{value1}} 拒绝退出。",
+ "baad8cd651": "没有正在运行的会话。",
+ "fe2ab66d45": "杀死 {{value1}} 会话中的 {{value0}}。 {{value2}} 拒绝退出。",
+ "d762b41f41": "重启失败。",
+ "b5954e12d3": "重新启动失败 - 检查日志。",
+ "0e9da1b98e": "守护进程重新启动。"
+ }
+ },
+ "setup": {
+ "guide": {
+ "SetupGuideModal": {
+ "3598a3ca0c": "完成使 Orca 对于并行代理工作有用的核心工作流程。",
+ "48a9e5ef2d": "入门",
+ "28cf59fcb4": "这将从侧边栏隐藏清单",
+ "f3b5ffb2a6": "从侧边栏隐藏清单"
+ },
+ "SetupGuideProgressRing": {
+ "dac3a4724a": "{{value1}} 设置步骤中的 {{value0}} 已完成"
+ }
+ }
+ },
+ "settings": {
+ "AccountsPane": {
+ "c2d2751587": "删除账户",
+ "dbb9626ed1": "取消",
+ "854ebbcc45": "Orca 将删除此已保存账户的托管 Claude 身份验证。如果当前处于活动状态,Orca 将回退到系统默认的 Claude 登录名。",
+ "63843e37e2": "删除 Claude 账户?",
+ "99c8f9e498": "Orca 将删除此已保存账户的托管 Codex 主目录。如果当前处于活动状态,Orca 将回退到系统默认的 Codex 登录。",
+ "0d47394635": "删除 Codex 账户?",
+ "ae3b21eb6c": "opencode.ai/workspace/wrk_…/go",
+ "51c9104e13": "登录 opencode.ai 后在 URL 中找到此内容(例如",
+ "b398b834c9": "清除",
+ "a122332371": "wrk_…(留空自动查找)",
+ "dbdb0b0bd8": "工作区 ID 覆盖",
+ "d70a5287a4": "如果自动查找失败,可选的工作区 ID 覆盖。",
+ "02cb127710": "OpenCode Go 工作区 ID",
+ "7ce0e1907c": ")。在浏览器的 DevTools → Network → 任意 opencode.ai 请求 → Cookie 请求头中找到它。OpenCode Go 认证基于 Web,可在 Windows 与 WSL 终端间共享。",
+ "8951c5309f": "auth=Fe26.2**…",
+ "338820326a": ")或完整 cookie 请求头(例如",
+ "922b51e02d": "Fe26.2**…",
+ "0023cc336e": "粘贴原始令牌值(例如",
+ "a7e38affcd": "Fe26.2**… token 或 auth=Fe26.2**… header",
+ "67e3c33670": "OpenCode Go 会话 cookie",
+ "b2b1aa936d": "粘贴您的 opencode.ai 会话 cookie 以进行速率限制获取。",
+ "36223200ac": "OpenCode Go 会话 Cookie",
+ "ea631977b5": "配置 OpenCode Go 提供商设置。",
+ "4ac10b4d08": "OpenCode Go",
+ "d708749337": "。这将使用颁发给 Gemini CLI 应用的凭据,而非 Orca。若 Google 更新 CLI,可能会失效。请自行承担风险。",
+ "c2aee76420": "从本地 Gemini CLI 安装中提取 OAuth 凭据,以通过 Google 进行身份验证",
+ "96f3649526": "使用 Gemini CLI 凭据(实验)",
+ "d676c41fc6": "从本地 Gemini CLI 安装中提取 OAuth 凭据以通过 Google 认证。这将使用颁发给 Gemini CLI 应用的凭据,而非 Orca。若 Google 更新 CLI,可能会失效。请自行承担风险。",
+ "0c7f915b01": "使用 Gemini CLI 凭据",
+ "973741a871": "配置 Gemini 提供商设置。",
+ "0c64dc2a64": "Gemini",
+ "db209ee572": "移除",
+ "8a0f870153": "重新验证",
+ "3d245ef7d9": "Codex 报告此登录已过时",
+ "589eba1eee": "需要重新授权",
+ "e74831fb6b": "当前",
+ "d46f735a85": "。 Orca 将使用该环境的系统默认 Codex 登录信息,直到您在此处添加登录信息。",
+ "b4c9450319": "没有受管理的 Codex 账户",
+ "93c47b333a": "需要登录",
+ "f2a265f8c7": "系统默认",
+ "b0e948a4f9": "添加账户",
+ "5568bb6d5c": "账户。新账户已添加到此处。",
+ "c0a52abfc5": "显示中",
+ "94d351af4a": "账户",
+ "d0d53b7eb0": "管理 Orca 使用哪个 Codex 账户进行实时速率限制提取。",
+ "3180536c7a": "Codex 账户",
+ "340d6f7a85": "每个账户在 Orca 中都保留自己的本地登录上下文。账户身份验证保留在此设备上。",
+ "cedfab35ab": "可选。Orca 可使用系统默认 Codex 登录;仅当你需要在 Orca 中快速切换账户时才添加账户。",
+ "ef91cfa06b": "Codex",
+ "dea08560b4": "。 Orca 将使用该环境的系统默认 Claude 登录名,直到您在此处添加登录名。",
+ "3fe7862418": "没有受管理的 Claude 账户",
+ "3455cf43fa": "Claude 登录。",
+ "fcc4093fc1": "使用您当前 {{value0}} Codex 登录名。",
+ "79e484c3b2": "用于共享 Claude 身份验证文件的可选账户切换器。",
+ "8bbfd74556": "Claude 账户",
+ "72b36ea174": "可选。Orca 可使用系统默认 Claude 登录;仅当你需要快速切换且不想迁移聊天会话时才添加账户。",
+ "26ef4b55be": "Claude",
+ "2743cdc0af": "Claude 账户更新失败。",
+ "b15ce90870": "{{value0}} -> {{value1}}。在继续旧会话之前重新启动实时 Claude 终端。",
+ "f921d32606": "Claude 账户已更新。",
+ "5bf8764953": "Codex 账户更新失败。",
+ "2358ac71d2": "WSL 默认值",
+ "ad47a33f72": "正在加载 WSL",
+ "8619f9afa9": "WSL",
+ "46cf7e7495": "账户位置",
+ "0b4591ff93": "选择要检查的本地环境以及添加新的托管 Claude 和 Codex 账户的位置。",
+ "0c67a2a1aa": "WSL 在此计算机上不可用。",
+ "2cd197025c": "选择是否在 {{value0}} 或 WSL 中检查并添加提供商账户。",
+ "f54b4fbd71": "账户位置",
+ "9107406589": "无法加载 Claude 账户。",
+ "b8c2905c2b": "无法加载 Codex 账户。",
+ "fd62f37c24": "Codex 报告此 {{value0}} 登录信息已过期。",
+ "b10cb4f696": "添加",
+ "e4a28e8894": "Codex 报告 {{value0}} 登录需要重新登录。在开始新的 Codex 会话之前再次登录。",
+ "75ca9b718e": "Codex 报告活动账户需要重新登录。在开始新的 Codex 会话之前重新对其进行身份验证。",
+ "b11078a9c2": "wsl"
+ },
+ "AdvancedPane": {
+ "40b29e0bf3": "重新启动",
+ "87a2cb2ac8": "Orca 在启动时应用此网络模式。",
+ "89958d7edf": "需要重新启动",
+ "b3ad629640": "仅当企业 VPN 或代理因 HTTP/2 协议错误而中断更新下载时才使用。重启后它会影响所有 Electron 网络。",
+ "6627e75c92": "解释 HTTP/1.1 兼容性",
+ "e9506d3377": "HTTP/1.1 兼容性",
+ "8b7a8df299": "支持故障排除的低级解决方法。",
+ "8d8d8ac599": "兼容性"
+ },
+ "AgentLocationSetting": {
+ "92f4238f1a": "WSL 默认值",
+ "fc806485ae": "正在加载 WSL",
+ "43663b5e69": "WSL",
+ "9bccf48906": "代理位置",
+ "d00949e59b": "显示来自 {{value0}} 的已安装代理。刷新会重新检查该环境中的 PATH。",
+ "c7c516946f": "WSL 在此计算机上不可用。",
+ "f97b986b7f": "wsl"
+ },
+ "AgentSkillSetupPanel": {
+ "0b810ec59f": "按 Enter 运行安装命令。",
+ "ed197f59a2": "复制命令",
+ "817d3f9f18": "复制安装命令",
+ "5289300939": "未安装",
+ "9fcebceb2a": "已安装",
+ "68a468752e": "检查中...",
+ "c689392435": "重新检查",
+ "a31e2aa302": "无法复制安装命令。",
+ "378ad26865": "复制安装命令。"
+ },
+ "AgentsPane": {
+ "d83834f5e6": "检测已安装的代理...",
+ "024bd95089": "代理",
+ "e8da2af684": "可安装",
+ "ed3e110e61": "已检测",
+ "02e0143be5": "已安装",
+ "110b74b022": "无代理(空白终端)",
+ "92033495ff": "自动",
+ "9b175d0f5e": "打开新工作区时预先选择的代理。",
+ "385212c7a1": "默认代理",
+ "f9f127d664": "覆盖用于启动此代理的二进制路径或名称。",
+ "f95b5c79b8": "安装",
+ "fe4d630c94": "文档",
+ "8dc0192e48": "已禁用",
+ "df123171d1": "未安装",
+ "c8794e622e": "已检测",
+ "5200dac9da": "重置",
+ "2e45ca29b6": "命令",
+ "d4d2a45d63": "启用",
+ "1c9a9679ec": "{{value0}} 可用性",
+ "0d9e293a02": "刷新",
+ "c9b33eb5c0": "刷新中…",
+ "13647f9f80": "重新读取您的 shell 路径并重新检测已安装的代理",
+ "dc4a2ffdc0": "扩展命令覆盖",
+ "cea7d97be1": "折叠命令覆盖",
+ "db9e9e5887": "自定义命令",
+ "959b67385b": "设置默认值",
+ "24e032fa34": "默认",
+ "5f986a9b92": "设置为默认值",
+ "d7625cf8b2": "默认代理"
+ },
+ "AppIconSelector": {
+ "d5a112dc9b": "下一个图标",
+ "415fa76f64": "选定的应用程序图标",
+ "5f5142a62a": "上一个图标"
+ },
+ "AppearancePane": {
+ "3057983501": "未分配",
+ "0cd9b8228f": "选择 Dock 和窗口切换器中显示的应用程序图标。",
+ "ca1590d42f": "应用程序图标",
+ "61d842eca0": "在侧边栏中显示 Orca Mobile 快捷方式。它仍然可以从 Toolbox 中获取。",
+ "9da1020447": "显示 Orca Mobile 按钮",
+ "5db6ba961f": "在左侧边栏顶部显示 Orca Mobile 按钮。",
+ "fa882a3e6b": "在左侧边栏顶部显示“自动化”按钮。",
+ "511f270ebb": "显示自动化按钮",
+ "661942ab7f": "在左侧边栏顶部显示“任务”按钮。",
+ "cf81907069": "显示任务按钮",
+ "dc29f3cc0d": "侧边栏",
+ "ea943d0db0": "选择窗口底部显示的指示器。您还可以右键单击状态栏进行相同的切换。",
+ "3e4175e5c6": "状态栏",
+ "2df8f79aa5": "在标题栏中显示 Orca。",
+ "9868f39007": "标题栏应用程序名称",
+ "4de76f6902": "控制应用程序标题栏中显示的内容。",
+ "6a272ca553": "标题栏",
+ "e9f2ca5582": "关闭以隐藏文件资源管理器中与 .gitignore 匹配的文件。",
+ "0fafabcf35": "显示 Git 忽略的文件",
+ "75f07ab60c": "在文件资源管理器中显示与 .gitignore 匹配的文件。",
+ "d496901cd0": "文件浏览器",
+ "42554f615f": "选择 Orca 界面使用的字体。",
+ "102d6b5f9b": "IDE字体",
+ "ef89200c1f": "当不在终端窗格中时。",
+ "f687711a9b": "缩放整个应用程序界面。使用",
+ "5e6d7aba8d": "用户界面缩放",
+ "622e1c3465": "缩放整个应用程序界面。",
+ "fd89b5487c": "光",
+ "7d26ccabe8": "深色",
+ "fb0e0b4453": "系统",
+ "932ff1fbff": "主题",
+ "0f28e7b30c": "选择 Orca 在应用程序窗口中的外观。"
+ },
+ "AutoRenameBranchFromWorkSetting": {
+ "1626524572": "Nautilus",
+ "0de9fda203": "放弃",
+ "c71770c455": "{基本提示}",
+ "f19a56498d": ";您的分支前缀设置仍然适用。",
+ "800edb1e54": "修复登录流程",
+ "5d569f5199": "。 Orca 仅生成最后一段,例如",
+ "570817d126": "和",
+ "56580dcf60": "。您还可以参考",
+ "9c9b54e4ea": "内置分支名称提示",
+ "69bf4830c2": "包括 Orca 的",
+ "9241b59bf5": "使用",
+ "a869d0edd8": "分支名称命令模板",
+ "e784ea62dc": "高级",
+ "d9b65054ef": ")到总结任务的简短名称。只有 Orca 命名的分支才会被重命名,并且在推送后不会被重命名。",
+ "12ea4a408d": "当代理开始在新工作区中工作时,Orca 会重命名其自动生成的分支(例如",
+ "ef787db0e3": "自动重命名分支",
+ "6a051586d2": "代理启动后,根据工作重命名自动生成的分支。",
+ "ec3e0c388e": "保存",
+ "cfd82406dd": "保存中...",
+ "40e7be7850": "已保存",
+ "7c7e34a66d": "未保存的更改",
+ "a4fa380b67": "{助理消息}",
+ "2ee2779c05": "{第一提示}"
+ },
+ "AutoRenameBranchPromptEditor": {
+ "63121132c0": "放弃",
+ "4416b25d29": "优先使用任务中的领域名词,避免工单 ID,并保持名称便于评审人理解。",
+ "39278f4411": ";您的分支前缀设置仍然适用。",
+ "ebb942a2ec": "修复登录流程",
+ "af2d9a2cc6": "。 Orca 仅生成最后一段,例如",
+ "182d419b97": "内置分支名称提示",
+ "2f5dc661fe": "附加到 Orca 的",
+ "7d6176f506": "迅速的",
+ "5968112152": "保存",
+ "54ac229ad4": "保存中...",
+ "af0831a590": "已保存",
+ "0691753cf2": "未保存的更改"
+ },
+ "BaseRefPicker": {
+ "1b8e54151f": "未找到匹配的分支。",
+ "d166ff883d": "当前",
+ "a4a9372eb2": "搜索分支...",
+ "7db7fb87e5": "按名称搜索分支...",
+ "773a5687a3": "使用主要",
+ "ade9a5bb03": ") 来确定结果范围。",
+ "b468f46726": "上游/主要",
+ "80f7c82303": ")或完整的参考(例如",
+ "915ad97875": "上游",
+ "a5c16712c1": "已检测多个遥控器。输入远程名称(例如",
+ "9a14ec7400": "选择下面的一个基础分支",
+ "086ce7f369": "跟随主分支 ({{value0}})",
+ "2f3cda96f5": "固定此存储库",
+ "ee110e1830": "没有默认的基本参考"
+ },
+ "BrowserDefaultZoomSetting": {
+ "2622126877": "缩放级别应用于新打开的浏览器选项卡。",
+ "bbeec087d3": "应用于新打开的浏览器选项卡。",
+ "265597101f": "默认缩放"
+ },
+ "BrowserHomePageSetting": {
+ "d4ddcd0056": "保存",
+ "37a30c5bfd": "https://google.com",
+ "c6cbd1c105": "主页已保存。",
+ "6a37540f4b": "创建新浏览器选项卡时打开的 URL。留空以打开空白选项卡。",
+ "70224e37b1": "默认主页"
+ },
+ "BrowserPane": {
+ "81ff774667": "取消",
+ "7d4c0a2aa4": "个人资料名称",
+ "612f7f6861": "创建个人资料失败。",
+ "8f22b7580d": "已创建配置文件“{{value0}}”。",
+ "8481ee0331": "新的浏览器配置文件",
+ "6f2584b39e": "添加个人资料",
+ "e4aaf8051b": "工具栏菜单。",
+ "cd47bc9622": "为新浏览器选项卡选择默认配置文件。通过以下方式导入 cookie 并切换每个选项卡的配置文件",
+ "2d66a6efb5": "会话和 Cookie",
+ "aa1074bfe9": "管理浏览器配置文件并从 Chrome、Edge、Comet 或其他浏览器导入 cookie。",
+ "113cd2dc9b": "会话和 Cookie",
+ "d3eb69c0aa": "链路路由",
+ "3e46903ad4": "在地址栏中输入非 URL 文本时使用。",
+ "0d9c987f21": "默认搜索引擎",
+ "7b225c78f5": "在地址栏中输入非 URL 文本时使用的搜索引擎。",
+ "64898ecdab": "创建",
+ "7b649a578a": "创建中…",
+ "4399c77caa": "默认",
+ "4af9a17947": "卡吉"
+ },
+ "BrowserProfileRow": {
+ "8e636cae25": "已删除配置文件“{{value0}}”。",
+ "2d4bea7f35": "默认 cookie 已清除。",
+ "ebb78dfd6f": "从文件...",
+ "7df818977e": "从",
+ "cdec84552f": "导入 Cookie",
+ "796d846483": "没有导入cookie",
+ "c29648fe5b": "当前",
+ "d420c43729": "将 {{value0}} cookie 从 {{value1}}{{value2}} 导入到 {{value3}} 中。"
+ },
+ "BrowserUseComputerUseNotice": {
+ "15b5e680ba": "开放计算机使用",
+ "79209b37b9": "如果 cookie 导入不合适,“计算机使用”可以控制本地应用程序,并可以在适用的情况下使用现有的登录浏览器会话。安装计算机使用技能; macOS 还需要隐私权限。",
+ "333984cf90": "使用现有的浏览器会话"
+ },
+ "BrowserUseEnableSwitch": {
+ "aea3f45349": "启用代理浏览器使用"
+ },
+ "BrowserUseExamples": {
+ "1199258ace": "复制",
+ "1188e56af4": "复制示例提示",
+ "b84807f228": "”",
+ "59722f31b4": "”",
+ "c5325e91f6": "将其中任何内容粘贴到 Claude Code、Codex 或安装该技能的项目中的其他代理中。",
+ "2a180694f7": "尝试一下 - 示例提示",
+ "5ec620ccc4": "复制失败。",
+ "a602d43069": "复制{{value0}}。"
+ },
+ "BrowserUsePane": {
+ "be6df68384": "从文件...",
+ "e44c5d681e": "从",
+ "67d9a53f47": "管理单独登录的配置文件",
+ "112f70adc4": "上次导入自",
+ "72d4815523": "将您现有的登录信息带入 Orca,以便代理可以访问经过身份验证的页面。导入到默认配置文件中。",
+ "2eb906706c": "导入浏览器 Cookie",
+ "af8c83ed61": "从 Chrome、Edge 或其他浏览器导入 cookie,以便代理可以重复使用您的登录信息。",
+ "68ea76eb71": "安装浏览器使用技能,以便代理可以操作 Orca 的浏览器。",
+ "2d6ead9ab2": "安装浏览器使用技能",
+ "e9f3f3b488": "安装于",
+ "9fca1f7f5d": "注册 Orca CLI 命令,以便代理可以从其 shell 编排浏览器。",
+ "c6065d205d": "启用 Orca CLI",
+ "c79eff0213": "注册 Orca CLI,以便代理可以驱动浏览器。",
+ "702488a5f7": "让编码代理通过您的登录来驱动此浏览器。完成以下三个步骤。",
+ "b8a1f2d84d": "代理浏览器使用",
+ "96b91c6349": "让编码代理通过您的登录来驱动此浏览器。",
+ "2ea4617e3a": "从 {{value1}}{{value2}} 导入 {{value0}} cookie。",
+ "721aee31b4": "在 PATH 中注册 Orca CLI。",
+ "180a9abf3a": "无法加载 CLI 状态。",
+ "2ccfc9cff8": "导入",
+ "0462565413": "重新导入",
+ "de9b2f32f3": "启用",
+ "ad8cb0ee22": "修复路径",
+ "0289434ed6": "启用",
+ "8b3054dac7": "注册..."
+ },
+ "BrowserUseSkillStep": {
+ "0871b6998d": "使代理能够在 Orca 浏览器中导航和验证页面。",
+ "459e24eebc": "浏览器使用技能"
+ },
+ "CliSection": {
+ "8671e406f0": "取消",
+ "a4aafe46e3": "目标路径:",
+ "e8012c03a1": "使代理能够使用 Orca 工作区、终端和进度命令。",
+ "6053cf736c": "CLI技能",
+ "36a6f919ba": "为代理提供 Orca 感知的工作区、终端和进度工作流程。",
+ "04873eea3e": "代理技能",
+ "7f2747f7dd": "当前在此 shell 的 PATH 上不可见。",
+ "b0c310ab46": "现有启动器目标:",
+ "15eaad0d31": "命令路径:",
+ "5dae812f50": "刷新",
+ "52e640f3a0": "刷新 CLI 状态",
+ "38edbb5721": "外壳命令",
+ "6930feda9e": "从终端使用 Orca 打开应用程序、管理工作树并与 Orca 终端交互。",
+ "c5c0f2641d": "Orca CLI",
+ "d77352f2df": "无法从 PATH 中删除 `{{value0}}`。",
+ "af5540930c": "从路径中删除了“{{value0}}”。",
+ "a2b13efa94": "无法在 PATH 中注册 `{{value0}}`。",
+ "9cbcd31338": "在 PATH 中注册了 `{{value0}}`。",
+ "7baec27029": "无法加载 CLI 状态。",
+ "d00df2e397": "注册",
+ "9a5f8a4568": "移除",
+ "b0fca411a0": "注册…",
+ "4c7e3e4c5f": "安装",
+ "068552b191": "正在删除...",
+ "8d96213669": "移除",
+ "aa6536977e": "Orca 将注册 {{value0}} ,以便该命令在您的终端上运行。",
+ "a030816e3e": "这将删除 shell 命令符号链接。 Orca 本身仍保持安装状态。",
+ "fa87db3d6e": "在路径中注册`{{value0}}`?",
+ "14444243ba": "从路径中删除`{{value0}}`?",
+ "5d432fe44d": "已安装",
+ "8a9b784c60": "陈旧",
+ "d363e5929b": "正在检查 CLI 注册..."
+ },
+ "CliSkillRuntimeSetup": {
+ "04325573f8": "WSL",
+ "a58ba464ad": "技能位置",
+ "0ed08febc5": "无法注册 WSL shell 命令。",
+ "3728a94fb6": "WSL shell命令需要注意的地方",
+ "775a4cfbb8": "WSL shell 命令注册不可用",
+ "c47127f222": "WSL 默认值",
+ "0c9f3cf9da": "选择 Orca 检查和安装全局代理技能的位置。",
+ "f00d6aa9b5": "WSL 在此计算机上不可用。",
+ "7c776ff9d8": "wsl",
+ "fc0fcf72fd": "在技能设置之前注册 WSL shell 命令。"
+ },
+ "CommitMessageAiPane": {
+ "841ed9884a": "由未自定义源代码控制 AI 的存储库使用。",
+ "ad66ff886d": "源代码控制 AI 默认值",
+ "347094560b": "由继承全局托管评审默认值的仓库使用。",
+ "2dafc7646e": "托管评审创建默认值",
+ "e9d46a544d": "打开托管评审编辑器时使用的默认值。",
+ "b125eabffa": "提交后在浏览器中打开创建的托管评论。",
+ "7662715213": "创建后打开托管评审",
+ "b27b0809f3": "编辑器打开时运行一次托管评审详情生成。",
+ "d5f0de6309": "打开 Create PR 时生成详细信息",
+ "6278c0ce43": "当未设置描述时,首选存储库拉取请求模板。",
+ "d8b6764d79": "可用时使用评审模板",
+ "e001734396": "除非在编辑器中更改,否则将托管评审创建为草稿。",
+ "6ba48f07a4": "默认草稿",
+ "15b60d54b2": "例如ollama 运行 llama3.1 {提示}",
+ "3f1b26cc91": "将命令输入作为参数传递;否则 Orca 将其通过标准输入进行传输。",
+ "4f722a5f53": "由选择自定义命令的提交消息、拉取请求和分支名称配方使用。使用",
+ "47e45cbd5a": "自定义命令",
+ "1ef29f8c29": "当文本配方使用自定义命令时,命令行 Orca 运行。",
+ "2339a89104": "添加 AI 按钮,用于使用该操作的命令模板运行选定的代理。",
+ "d5b45a3628": "显示源代码控制 AI 操作",
+ "7bcad2b200": "为源代码管理的提交、拉取请求、分支命名和修复操作添加操作方案。",
+ "d54c64163d": "已启用",
+ "4ec89c319e": "代理",
+ "34d0348e34": "产生",
+ "8cd2be0948": "信息",
+ "ca433708cb": "犯罪",
+ "0b7eafe55f": "AI",
+ "2c5436c018": "打开",
+ "6c84ba6de3": "模板",
+ "ebed4d2a29": "草稿",
+ "02bab6542c": "PR",
+ "fdee745b87": "合并请求",
+ "b388463881": "拉取请求",
+ "19e10a12bb": "主持评论",
+ "b8b6fd55b4": "{迅速的}",
+ "fc1a525fa5": "占位符",
+ "a69e1fe91a": "迅速的",
+ "1df7d71313": "二进制",
+ "407d28bde6": "命令行",
+ "54038660e0": "命令",
+ "25350d670f": "风俗"
+ },
+ "ComputerUsePane": {
+ "1735461723": "使代理能够检查和操作本地桌面应用程序。",
+ "93255aaf18": "计算机控制技能",
+ "45f8e22c2e": "进行中",
+ "d95d1cfab8": "刷新",
+ "0c29da5805": "就绪",
+ "3383ea1aab": "无法重置计算机使用权限",
+ "f189f448a3": "重置计算机使用访问权限",
+ "5c45349665": "无法打开计算机使用权限",
+ "7801ac08ec": "仅在 macOS 上需要计算机使用权限",
+ "740766c291": "计算机使用设置已完成",
+ "697005758f": "打开 macOS 隐私和安全",
+ "2168fa5ab0": "无法加载计算机使用权限",
+ "0c9a33f468": "捕获应用程序窗口,以便代理可以检查视觉状态。",
+ "07bbe4c4cb": "截图",
+ "4d03dec2d0": "读取应用程序界面树并执行请求的操作。",
+ "6b5a2cd3a5": "无障碍",
+ "6b17602073": "重置访问权限",
+ "506f2acf7a": "正在重置访问...",
+ "4b65070096": "darwin"
+ },
+ "DeveloperPermissionsPane": {
+ "4c17304beb": "刷新",
+ "6326a4c5cc": "当 CLI、本地应用程序或自动化工具需要 macOS 隐私访问时,请使用这些控件。 Orca 在启动时不会询问。",
+ "6f011b9bf6": "终端工具继承了 Orca 的 macOS 隐私信封。",
+ "bfa3402305": "无法请求许可",
+ "66e94d6cf3": "已发送权限请求",
+ "fa809e8ada": "打开 macOS 隐私和安全",
+ "48d87edcd2": "已获得许可",
+ "a552887288": "无法加载开发者权限",
+ "4cfaa7e98a": "蓝牙设备工具和本地硬件实验。",
+ "b2210b1b4f": "蓝牙",
+ "dfbc12c8c8": "与 USB 设备通信的硬件调试和设备工具。",
+ "bf51e4a542": "USB 设备",
+ "f903bf20b5": "发现和访问网络上的开发服务器。",
+ "e7bb06007c": "本地网络",
+ "4a73f5217a": "用于控制其他本地应用程序的脚本的 Apple 事件。",
+ "e119f0d66b": "自动化",
+ "7ca17b62c8": "从终端会话持续访问受保护的文件夹。",
+ "c566bca278": "全磁盘访问",
+ "9f35980756": "击键注入、窗口控制和 UI 自动化工具。",
+ "5b2f22ca2d": "无障碍",
+ "0639db5496": "屏幕截图、视觉自动化和 UI 检查工具。",
+ "f24f31a884": "屏幕录制",
+ "550cfa3750": "网络摄像头捕获和摄像头驱动的本地测试应用程序。",
+ "e5b5f3d6b9": "相机",
+ "cc8151d9fa": "语音输入、转录、录音、sox、ffmpeg 和 Whisper CLI。",
+ "16381e040a": "麦克风",
+ "dac08ec03e": "处理中..."
+ },
+ "ExperimentalPane": {
+ "9762364929": "允许自动符号链接必须连接到创建的工作树的某些文件夹或文件。",
+ "24416f42cd": "工作树上的符号链接",
+ "fb82ea1d7a": "自动将配置的文件或文件夹符号链接到新创建的工作树中。",
+ "a20d5ea365": "在终端响铃或代理完成事件后保持窗格级突出显示可见,直到您与该窗格交互。我们在调整信号时进行实验。",
+ "ec897e8d89": "终端关注",
+ "88b7613afb": "终端响铃和代理完成事件的持久窗格突出显示。",
+ "0277901cf7": "将代理条目添加到左侧边栏,其中包含已完成代理、阻塞待办、未读状态和工作树创建事件的线程工作树提要。实验性——事件模型和 UI 可能会改变。",
+ "a05bcdaf57": "代理查看",
+ "f63ea281e3": "用于代理完成和阻塞状态的螺纹左侧边栏提要。",
+ "ca2219fe5e": "显示固定在右下角的小动画宠物。从状态栏宠物菜单中选择一个角色(Claudino、OpenCode、Gremlin)或上传您自己的 PNG、APNG、GIF、WebP、JPG 或 SVG。随时从同一菜单隐藏它,而不禁用此设置。",
+ "dd6f0a1d45": "宠物",
+ "0e89a574ae": "右下角漂浮的动画宠物。"
+ },
+ "FloatingWorkspacePane": {
+ "aeaf76fda9": "状态栏",
+ "9fb225f2d7": "浮动按钮",
+ "3c900e26e5": "无论切换显示在何处,键盘快捷键都有效。",
+ "5e5a8da236": "切换按钮位置",
+ "505001823e": "选择浮动工作区目录",
+ "81afb79785": "新的浮动终端选项卡从这里开始。 Markdown 笔记保存在 Orca 应用程序拥有的浮动工作区中。",
+ "12aa09f10c": "终端目录",
+ "41eb95f7f0": "显示浮动工作区按钮和面板。",
+ "5136813663": "启用浮动工作区",
+ "37df688d6f": "启用浮动工作区并选择新选项卡的开始位置。",
+ "1f67f39384": "浮动工作区"
+ },
+ "GeneralCacheTimerSection": {
+ "05de84a104": "1小时",
+ "54395ecd7c": "5分钟",
+ "8b9e202e0a": "将此与您的提供商的缓存 TTL 相匹配。默认值为 5 分钟。",
+ "a2a8962138": "定时器持续时间",
+ "b4e7302944": "缓存定时器",
+ "487b176240": "Claude 代理空闲后,在侧边栏中显示倒计时。",
+ "9c20253679": "在 Claude 代理空闲后显示倒计时。",
+ "fe590653c1": "Claude 会缓存对话以降低成本。空闲过久后缓存会过期,下一条消息将以更高成本重新发送完整上下文。此倒计时可帮助您了解何时继续。",
+ "a137f8854d": "提示缓存定时器",
+ "80c454e8a6": "将此与您的提供商的缓存 TTL 相匹配。"
+ },
+ "GeneralEditorSettingsSection": {
+ "f80603d293": "在丰富的编辑器模式和代理切换操作中显示本地 Markdown 注释控件。",
+ "4edc104f0f": "Markdown 评审笔记",
+ "5f02e6fb21": "在富文本编辑器模式下显示本地 Markdown 评审笔记控件。",
+ "51161d1647": "编辑文件时显示小地图概述。",
+ "6690b1ffb9": "小地图",
+ "5a1ea6eaa2": "隐",
+ "73a09aad63": "如图所示",
+ "1de48ad940": "默认差异文件树",
+ "1b87897af9": "打开组合差异视图时显示或隐藏文件树。",
+ "12cbc0d0d6": "并排",
+ "05b6df93b3": "内联",
+ "7311f67ee7": "默认差异视图",
+ "b492397d34": "默认情况下显示 git diff 的首选演示格式。",
+ "a5db1d3975": "ms",
+ "fc5c5306ff": "ms。",
+ "8112cd6dcf": "Orca 在您上次编辑后等待多长时间才会自动保存。首次启动默认为",
+ "d6cf227ca0": "自动保存延迟",
+ "1bec6d8318": "Orca 在您上次编辑后等待多长时间才会自动保存。",
+ "70bb30feb1": "短暂暂停后自动保存编辑器和可编辑差异更改。",
+ "0df2e4fd12": "自动保存文件",
+ "d21136d9ef": "配置 Orca 如何保留文件编辑。",
+ "45c6e85c4d": "编辑"
+ },
+ "GeneralNetworkSettingsSection": {
+ "3e431564b5": "本地主机,127.0.0.1,*.internal",
+ "33ee3ca3af": "可选。用逗号、分号或换行符分隔主机。",
+ "f6d76cc8f4": "代理绕过规则",
+ "fb7130dcb9": "应绕过配置的 HTTP 代理的主机。",
+ "0adfce9fa7": "支持http、https、socks、socks4 和socks5 URL。",
+ "476f302aca": "http://proxy.example.com:8080",
+ "1e214e265a": "留空以使用系统代理设置和继承的代理环境变量。",
+ "f00daf6324": "HTTP代理",
+ "823e0f15b1": "Orca 网络请求和本地终端子项的代理 URL。",
+ "d93c7cd531": "配置应用程序级网络路由。",
+ "c46cdbbd4e": "网络"
+ },
+ "GeneralPane": {
+ "d58fccfd84": "导航"
+ },
+ "GeneralSupportSection": {
+ "af7d9f4396": "感谢您的支持!",
+ "6922c1fa2b": "GitHub 上的 Star Orca",
+ "511782265b": "通过 gh CLI 通过 GitHub star 支持该项目。",
+ "55a87e5fd1": "支持 Orca",
+ "964acc6bb4": "星星",
+ "73b327e793": "重试",
+ "c9f96d4234": "错误",
+ "397719bee5": "主演...",
+ "1e29570462": "主演",
+ "9d181300e3": "已加星标",
+ "5c49f02662": "隐",
+ "b3f0584f5d": "加载中"
+ },
+ "GeneralUpdateSettingsSection": {
+ "8a52ca1d02": "发行说明",
+ "d89806cc89": "已准备好安装。",
+ "a6b37929dc": "版本",
+ "8311da27ba": "可用。单击“安装更新”下载并安装它。",
+ "f44299636f": "重新启动以更新(",
+ "42717918f4": "安装更新(",
+ "02dc082e70": "无法开始更新下载。",
+ "e1a647adc5": "检查更新",
+ "ceb579abaf": "检查应用程序更新并安装较新的 Orca 版本。",
+ "d91ebfb87e": "当前版本:{{value0}}",
+ "f2b1ccc12a": "更新",
+ "bd79d412f0": "更新检查失败。 {{value0}}",
+ "b9ad70c30d": "更新错误。 {{value0}}",
+ "6405510b92": "错误",
+ "a0832ccdb1": "下载的",
+ "2a48034c4c": "正在下载 v{{value0}}... {{value1}}%",
+ "4c1c001813": "下载",
+ "f40d88390d": "您使用的是最新版本。",
+ "90eb7309d7": "无法使用",
+ "82465b2444": "可用的",
+ "31fd7150cf": "正在检查更新...",
+ "3394d1f663": "检查中",
+ "d69a09b672": "启动时会自动检查更新。",
+ "7173352632": "idle"
+ },
+ "GeneralWorkspaceSettingsSection": {
+ "3d538a98f7": "从工作区的“打开方式”菜单中选择可用的应用程序。",
+ "008f92085f": "在应用程序中打开",
+ "824b98a0d9": "在删除自动化及其运行历史记录之前显示确认信息。",
+ "ea98373cd8": "删除自动化之前询问",
+ "d2dd2ca2e3": "在删除自动化及其运行历史记录之前显示确认对话框。",
+ "28bc3d085e": "从上下文菜单中删除工作区之前显示确认信息。失败的删除仍然会出现强制删除后备。",
+ "9f380934cf": "删除工作区之前询问",
+ "5734db82af": "删除工作区之前显示确认对话框。",
+ "4fbf910ded": "在以 repo 命名的子文件夹内创建工作区。",
+ "ba3480642f": "嵌套工作区",
+ "a246f5ce6f": "创建工作区文件夹的根目录。",
+ "5567191a6e": "浏览",
+ "0e9fc0eadc": "工作区目录",
+ "e2955d9ccb": "配置创建新工作区的位置。",
+ "7511097c5d": "工作区"
+ },
+ "GhosttyImportModal": {
+ "9d3e56ca36": "应用更改",
+ "f96688b6bc": "取消",
+ "b7ddae600c": "完成",
+ "e4bda7ce6f": "在此系统上未找到 Ghostty 配置。",
+ "b58d4c9051": "不支持的按键",
+ "674b5ccd6b": "无需导入新设置 — 您当前设置已经匹配。",
+ "a4c5dec640": "要更新的设置",
+ "4466f4cdaa": "导入完成",
+ "023a52c1f7": "正在加载预览...",
+ "2763b0c045": "查看将从 Ghostty 配置导入的设置。",
+ "d2f33670a9": "从幽灵导入",
+ "273e7e81fe": "配置",
+ "1f744a72f4": "配置"
+ },
+ "GitPane": {
+ "d2eede4c54": "将 Orca 归因添加到提交、PR 和议题。",
+ "e02ea23a32": "Orca 归因",
+ "e71ce09c42": "orca",
+ "b9b5771bb1": "归因",
+ "b5f534717a": "合着的",
+ "9838c921ed": "共同作者",
+ "afada55042": "议题",
+ "b4ef5428a7": "PR",
+ "895d3f70b8": "gh",
+ "32dca11189": "github",
+ "c4f610d057": "当前 GitLab CLI REST 速率限制标头(如果可用)。",
+ "0de4ae556c": "亚搏体育appGitLab API预算",
+ "cdd793134e": "API预算",
+ "b9c011fbc2": "速率限制",
+ "3072428ac7": "光亮的",
+ "8a527d48e3": "GitLab",
+ "aa204f185f": "当前 GitHub CLI REST、搜索和 GraphQL 速率限制。",
+ "612a440e57": "GitHub API 预算",
+ "2cde9044a8": "图ql",
+ "36e3de3619": "通过与陈旧的历史进行比较。如果该分支有未提交的更改或仅限本地提交,Orca 会跳过更新。",
+ "d072a12995": "git diff 主要...HEAD",
+ "db3a127eb1": "。这使得命令像",
+ "3ae3de8898": "掌握",
+ "5bf885be48": "或者",
+ "ffba483bae": "主要的",
+ "976afc6b3e": "当您创建工作区时,Orca 会刷新远程库并安全地快进您匹配的本地分支,例如",
+ "1ec5c91e1d": "选择分支名称是使用您的 Git 用户名、自定义前缀还是不使用前缀。",
+ "330f584b50": "分支前缀",
+ "1ffaadf0a0": "创建工作树时添加到分支名称的前缀。",
+ "813e15b346": "风俗",
+ "2351aa5a31": "git 用户名",
+ "cc63fce906": "分支命名",
+ "b559bf9899": "例如 feature",
+ "aefa1ecb59": "没有配置 git 用户名",
+ "f35007e6e8": "git 用户名",
+ "3d172725cc": "没有任何",
+ "1f32ba27a6": "自定义",
+ "a182c5125e": "git用户名"
+ },
+ "HiddenExperimentalGroup": {
+ "d0f914a528": "占位符切换",
+ "1014ddbfaf": "今天什么也不做。保留作为隐藏实验选项的第一个插槽。",
+ "232cf83de8": "用于内部测试的未列出的切换。这里什么都不支持。",
+ "3e9e827ca5": "隐藏实验"
+ },
+ "InputPane": {
+ "db15068196": "在 Linux 和 macOS 上默认启用。 Linux使用系统选择剪贴板;其他平台使用私有缓冲区。",
+ "ad31c3c5fb": "单击鼠标中键从所选内容粘贴"
+ },
+ "IntegrationsPane": {
+ "2122e15517": "每个已连接的 Linear 工作区都有一个由活动运行时存储的密钥。全权限密钥可覆盖密钥所有者可访问的所有团队;受限密钥可随时更换。",
+ "e7b2dd46f9": "测试...",
+ "fe4d378dc4": "已验证",
+ "f5c5246514": "添加 Linear 访问",
+ "6432f6522e": "已连接",
+ "077844591a": "添加工作区访问权限",
+ "264a9b6128": "Linear",
+ "4831ba1083": "重新检查",
+ "01f6c7582e": "了解更多",
+ "1a62c295c6": "Gitea 凭据已配置,但无法进行身份验证。检查令牌、API 基本 URL 和存储库权限,如果环境变量发生更改,则重新启动 Orca。",
+ "5a1f86225a": "仅当 Orca 无法从远程获取 API URL 时。",
+ "6193444689": "ORCA_GITEA_API_BASE_URL",
+ "2c0330ec3e": "对于私有存储库,并设置",
+ "e678d89e8c": "ORCA_GITEA_TOKEN",
+ "d9467ab026": "公共仓库通过其 git 远程检测。设置",
+ "4ab9b96925": "吉泰亚",
+ "953b7bf6f7": "Azure DevOps 凭据已配置,但无法进行身份验证。检查令牌、API 基本 URL 和存储库权限,如果环境变量发生更改,则重新启动 Orca。",
+ "6f317f5132": "仅当 Orca 无法从 git 远程派生 API 基本 URL 时。",
+ "ae6b7f5f40": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "67a9f26a80": "。设置",
+ "8f960935c1": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "ce3c58cd63": ",或设置",
+ "5ee6ef6405": "ORCA_AZURE_DEVOPS_TOKEN",
+ "4ee74d1470": "放",
+ "5efce6953d": "Azure 开发运营",
+ "3c3cf05c63": "Bitbucket 凭据已配置,但无法进行身份验证。检查令牌和存储库权限,如果环境变量发生更改,则重新启动 Orca。",
+ "6e0ff3403e": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "44cde4aa01": "ORCA_BITBUCKET_API_TOKEN",
+ "a6c2816115": "和",
+ "b8a7efb3f6": "ORCA_BITBUCKET_EMAIL",
+ "8489c0aa49": "位桶",
+ "e74de656ce": "glab 身份验证登录",
+ "05e5245af7": "GitLab CLI 已安装但未经过身份验证。在终端中运行此命令:",
+ "a83cac5726": "安装 GitLab CLI",
+ "35a3379372": "安装 GitLab CLI 以启用合并请求、议题和管道。",
+ "ea160a9978": "命令行界面。",
+ "a3326f6f1b": "光亮的",
+ "027440e1cb": "通过合并请求、议题、待办事项和管道",
+ "513abfe47d": "GitLab",
+ "51000487c4": "gh 验证登录",
+ "09285e9fe6": "GitHub CLI 已安装但未经过身份验证。在终端中运行此命令:",
+ "399cf46867": "安装 GitHub CLI",
+ "c0c8575e05": "安装 GitHub CLI 以启用拉取请求、议题和检查。",
+ "f36365ed45": "gh",
+ "de6a0d13ab": "通过以下方式拉取请求、议题和检查",
+ "70c5f74f36": "GitHub",
+ "8e078e480c": "断开 {{value0}}",
+ "95b9a87e7e": "测试",
+ "62b20292de": "错误",
+ "ae38fc62a8": "好的",
+ "33ae9730a8": "添加 Linear 访问以浏览和链接议题。",
+ "98ded79cd7": "{{value0}} 工作区{{value1}} 已连接",
+ "4bdc6fe4f5": "未配置",
+ "4972f3c95d": "配置的",
+ "3614887c40": "检查中",
+ "45bf5e6e4b": "验证失败",
+ "e1bd5364e6": "可选设置",
+ "e7a961e1c5": "已配置",
+ "6bd148dcb5": "通过 Gitea REST API 拉取请求并提交状态。",
+ "6355fe585e": "已检测的存储库的拉取请求和提交状态",
+ "1fac9b4910": "{{value0}} · 拉取请求和提交状态",
+ "f92fbf11aa": "未配置",
+ "6791d7af95": "通过 Azure DevOps REST API 令牌拉取请求和构建状态。",
+ "e3d5a24979": "已检测的 Azure Repos 的拉取请求和构建状态",
+ "277fc23929": "{{value0}} · 拉取请求和构建状态",
+ "295154e54e": "已连接",
+ "0879860c58": "通过 Bitbucket Cloud API 令牌拉取请求和构建状态。",
+ "9707523939": "拉取请求和构建状态",
+ "a565377c38": "未安装",
+ "15cf990798": "未经过验证",
+ "f7eb5f0b24": "未安装"
+ },
+ "KagiSessionLinkForm": {
+ "92f0b4e472": "清除",
+ "9f741627a7": "Kagi 会话链接已清除。",
+ "d5c8b94c5b": "保存",
+ "ff450194cd": "卡吉私人会话链接",
+ "e383683485": "https://kagi.com/search?token=...",
+ "81409d9362": "Kagi 身份验证的可选私人会话链接。",
+ "3e5b7c6c25": "Kagi 会话链接已保存。",
+ "0911d5fa4c": "输入来自 https://kagi.com/search?token=... 的 Kagi 私人会话链接"
+ },
+ "KeybindingsFileActions": {
+ "abc49853fb": "从磁盘重新加载",
+ "a8a8d6b9d3": "在文件管理器中显示",
+ "9e24c0e858": "在Cursor中打开",
+ "1637f64033": "在 VS Code 中打开",
+ "98f1a23e1c": "使用默认应用程序打开",
+ "400397a10d": "打开键绑定文件菜单",
+ "1c2be2b2c6": "在 Orca 中编辑文件",
+ "c5886a31cc": "无法打开外部编辑器。",
+ "cdf794f46d": "键绑定文件不可用。",
+ "dd532a01ce": "无法在 Orca 中打开键绑定。"
+ },
+ "ManageSessionKillDialog": {
+ "6bf4627168": "取消",
+ "ad9832aa26": "。该面板中未保存的工作将丢失。此操作无法撤销。",
+ "8401328fed": "强制退出",
+ "87dcafc85c": "杀死这个会话?",
+ "0b0db4c68c": "终止会话",
+ "d3dba51b15": "正在结束…"
+ },
+ "ManageSessionsSection": {
+ "33c2a1e1b4": "终止会话 {{value0}}",
+ "2896a50f50": "前往航站楼 {{value0}}",
+ "e26a60d9eb": "没有会话。",
+ "39c53d6d74": "加载中…",
+ "5ed15e778c": "重新启动守护进程",
+ "3282db098c": "杀死所有会话",
+ "b3b1cc5708": "刷新",
+ "a795a9552a": "会话",
+ "7c4889a724": "通过终止会话或重新启动底层守护进程,从冻结或行为异常的终端中恢复。",
+ "d1b80fd5cd": "管理会话",
+ "9c940434af": "切换回本地运行时以重新启动或终止本地守护进程会话。",
+ "ad467eaadc": "当远程运行时服务器处于活动状态时,会话管理不可用。",
+ "8dbd96b463": "无法终止会话。",
+ "0735b7a586": "无法终止会话——它可能已经消失了。",
+ "bfba05dccd": "杀死会话。",
+ "c535cbdd09": "无法加载会话。",
+ "e3d1fbe008": "重新启动",
+ "a06ababda0": "全部强制结束"
+ },
+ "McpConfigFileRow": {
+ "b145eb6009": "环境:",
+ "e720c139cd": "进行中",
+ "845ae248e8": "有效的"
+ },
+ "McpConfigSection": {
+ "4d16a0d9ac": "已检查",
+ "b900cd6282": "未找到 MCP 配置。当您希望此存储库定义其自己的 MCP 服务器时,添加一个空的工作区配置。",
+ "3b224167ff": "服务器",
+ "251b96564a": "已检测·",
+ "f34c152dc0": "刷新 MCP 配置",
+ "6bac9ddfc6": "SSH 存储库是通过远程文件系统读取的。 Starter 创建仅限于工作区根配置。",
+ "96f5609b04": "检查代理在此存储库中工作时可以使用的 MCP 服务器定义。",
+ "55eea3ef47": "MCP 配置",
+ "9ee215caf6": ".mcp.json",
+ "1f3665e35a": "MCP 配置已创建",
+ "82436439eb": "添加 MCP 配置",
+ "0a5c1ead54": "创建空配置"
+ },
+ "MobileEmulatorAgentControlRow": {
+ "1861982430": "无法加载 CLI 状态。",
+ "8af7a8bc38": "命令针对当前工作树的活动模拟器。坐标从 0..1 标准化。",
+ "c7f3fe0a6e": "常用模拟器命令",
+ "d94ca6a623": "使代理能够使用 Orca CLI 命令,包括移动模拟器控制。",
+ "67e19ee03c": "Orca CLI 技能",
+ "aaf62a3dd2": "安装于",
+ "2fef055608": "注册 Orca CLI 命令,以便代理可以从其 shell 控制活动模拟器。",
+ "4f2205f3b6": "启用 Orca CLI",
+ "ff4b7e65d6": "让编码代理使用 Orca CLI 命令控制活动移动模拟器。",
+ "2a674aa810": "代理移动模拟器控制",
+ "cdeaed9e37": "在 PATH 中注册 Orca CLI。"
+ },
+ "MobileEmulatorExamples": {
+ "edf13dd03b": "复制",
+ "c12b253997": "复制示例提示",
+ "d151e25078": "”",
+ "b525ff2b12": "”",
+ "4daa95f25a": "将其中任何内容粘贴到安装了 Orca CLI 技能的项目中的 Claude Code、Codex 或其他代理中。",
+ "0820b3f84f": "尝试一下 - 示例提示",
+ "1f608e7d60": "复制提示失败。",
+ "2b077b5544": "已复制提示。"
+ },
+ "MobileEmulatorSettingsPane": {
+ "19d39113b6": "让编码代理使用 Orca CLI 命令控制活动移动模拟器。",
+ "f2f8d97bb6": "代理移动模拟器控制",
+ "143961d031": "默认设备",
+ "8aec2f99a0": "刷新模拟器可用性",
+ "ae1612c58c": "可用性",
+ "f9af91ea26": "显示“新建移动模拟器”操作并允许代理连接到活动模拟器。",
+ "700ddbf9b1": "启用移动模拟器",
+ "bc39d0f115": "配置对 Orca 和编码代理的移动模拟器支持。",
+ "6593c9ddd3": "移动模拟器",
+ "a4f1c82d90": "已禁用",
+ "b5e2d93e01": "检查中...",
+ "c6f3ea4f12": "就绪",
+ "d704fb5023": "需要设置"
+ },
+ "MobileNetworkInterfaceSection": {
+ "63d5e4ae1e": "重新生成二维码并从 Orca 移动应用程序扫描。",
+ "87985ba6f5": "在此网络接口菜单中,选择 Tailscale 地址,通常是 100.x.y.z IP。",
+ "1f7c26d36a": "在两台设备上登录相同的 tailnet。",
+ "668016be7a": "在您的计算机和手机上。",
+ "1dc87a7fbc": "尾鳞",
+ "51d29927eb": "安装",
+ "9fc5d203ff": "Orca Mobile 直接连接到此计算机。要在远离同一本地网络的地方使用它,请将您的计算机和手机置于同一私有覆盖网络上,然后使用所选的网络地址生成二维码。",
+ "39fad211d9": "使用尾网连接 Wi-Fi 外部",
+ "a9db5d771d": "刷新网络接口",
+ "b2c384cfd6": "没有找到接口",
+ "d536b5e20d": "选择要在 QR 码中公布的网络地址。使用 LAN 地址进行同网络配对,或使用覆盖网络地址(Tailscale、ZeroTier)进行跨网络访问。",
+ "406a35121c": "网络接口",
+ "c541f67790": "生成二维码",
+ "1e64659126": "再生"
+ },
+ "MobilePane": {
+ "dd3cd78d04": "使用 Orca Mobile 扫描",
+ "35100bca5d": "当您在手机上使用终端时,Orca 会将其缩小以适合您的手机屏幕。当您关闭应用程序或切换离开时,这可以控制它是保持手机大小(因此交互式 CLI 工具不会回流)还是将大小调整回桌面。您始终可以单击终端横幅上的“恢复”来手动调整其大小。",
+ "ee56f1c7e4": "当您离开移动应用程序时",
+ "3939fd062c": "撤销设备会立即断开连接。",
+ "254a6d09e4": "配对",
+ "d7ce676270": "配对设备",
+ "e778ecb209": "或者将此代码粘贴到移动应用程序中:",
+ "310924ad2c": "使用 Orca 移动应用程序扫描此代码。每个代码都会创建一个唯一的设备令牌。",
+ "870e1b5ca5": "撤销设备失败",
+ "2e3dd0bc29": "设备已撤销",
+ "711231348f": "复制配对码失败",
+ "e3c427e020": "生成二维码失败",
+ "cb9067c1c1": "WebSocket 传输未运行",
+ "d714614dbf": "刷新网络接口失败",
+ "ff865419dc": "30分钟后",
+ "d4ba07d914": "5分钟后",
+ "c474aa09d8": "1分钟后",
+ "aa1263e881": "保持手机尺寸(默认)",
+ "6436e56546": "用于移动配对的二维码",
+ "1b1b70279a": "尚未配对任何设备。",
+ "1592afcc7a": "尚未配对任何设备。使用 Orca 移动应用程序扫描二维码。"
+ },
+ "MobileSettingsPane": {
+ "9a3c280e49": "GitHub 发布",
+ "b0088412a1": "或 Android APK 来自",
+ "b5a2ed83ff": "应用商店",
+ "c8491c17ef": "通过扫描二维码从手机控制 Orca。 Beta/早期预览 - 预计会出现错误和重大更改。从以下位置获取 iOS 应用程序",
+ "e7a3ae8c4e": "移动端",
+ "174f4a3c6d": "通过手机控制终端和代理。"
+ },
+ "NotificationsPane": {
+ "906b4afebf": "发送测试通知",
+ "2772d2f257": "当触发工作树已经可见时跳过通知。",
+ "00cd406dbb": "专注时抑制",
+ "2a42dd8d6f": "通知音量",
+ "4aa5085cd7": "风俗:",
+ "c258cb96dc": "选择通知声音",
+ "2a2033c388": "选择发送桌面通知时 Orca 播放的警报。",
+ "88686e6ca8": "通知声音",
+ "b6fc369244": "后台终端发出响铃字符。",
+ "591fe605b9": "航站楼响铃",
+ "55f901a59b": "编码代理完成并变得空闲。",
+ "ca76d06fd2": "代理任务完成",
+ "deff6d30da": "后台事件的本机系统通知。",
+ "841c8c549f": "启用通知",
+ "0fadad17ce": "无法播放通知声音",
+ "406feb0aa6": "测试通知未送达",
+ "6fc3781729": "通知已禁用",
+ "4676a95bc3": "检查 Orca 的桌面通知设置。",
+ "0cb93240b8": "系统没有显示通知",
+ "145227ca2b": "打开设置",
+ "d3d54e0915": "已发送测试通知",
+ "115437bc35": "如果没有出现 macOS 横幅,请启用 Orca 的允许通知。",
+ "7f45542625": "要求测试通知",
+ "98d70fb261": "自定义通知声音无法播放",
+ "c83b05a055": "该系统不支持通知",
+ "274af61bc0": "系统",
+ "6e6df3a09a": "选择自定义文件",
+ "76e02467b8": "更改自定义文件",
+ "d3756cf5bc": "已禁用"
+ },
+ "OpenAiTranscriptionKeyDialog": {
+ "fa83512e48": "保存密钥",
+ "07b26f2742": "清除键",
+ "d246b2bdb3": "本地运行时密钥使用 Electron 加密存储(如果可用)存储在 ~/.orca 中。",
+ "c3380e4ca5": "sk-...",
+ "2f797018f0": "API 密钥已配置",
+ "16015322f9": "API密钥",
+ "07ed3e512e": "仅当选择 OpenAI 语音模型时,音频才会发送到 OpenAI。",
+ "439e91879e": "OpenAI 转录"
+ },
+ "OpenAiTranscriptionSettingsRow": {
+ "85c589cd61": "添加API密钥",
+ "ae2df8f511": "断开 OpenAI API 密钥",
+ "a622bc3b37": "更换密钥",
+ "3b0ab3fc0b": "已连接",
+ "27e0cb656d": "OpenAI 转录",
+ "893790e13b": "在选择云语音转文本模型之前添加 OpenAI API 密钥。",
+ "b59b9b2b51": "为云语音转文本模型配置的 API 密钥。"
+ },
+ "OpenInMenuSetting": {
+ "03b00b1f64": "定制应用程序",
+ "c1d817e027": "额外",
+ "e4064916aa": "添加应用程序",
+ "9d0413817d": "从工作区的“打开方式”菜单中选择可用的应用程序。",
+ "6ed52fe71e": "在应用程序中打开",
+ "eb55b87570": "您在终端中键入的命令以打开此应用程序。",
+ "ba1422ee07": "终端命令",
+ "e1fc0085c6": "菜单标签",
+ "a261931d29": "删除应用程序",
+ "af7d1c3656": "编辑应用程序",
+ "494ed535cd": "折叠应用程序详细信息",
+ "810ef39b56": "cursor",
+ "3ebe650f74": "应用名称",
+ "3743ed080c": "设置命令",
+ "f79084947b": "新应用程序"
+ },
+ "OrchestrationExamplesDialog": {
+ "3d1aa105e3": "复制提示",
+ "9b4c004998": "完成",
+ "969cec9739": "复制 {{value0}} 示例提示",
+ "4e46da1889": "复制提示失败。",
+ "80c6f2feb8": "复制示例提示。"
+ },
+ "OrchestrationPane": {
+ "52e0634e2c": "要求协调代理使用编排进行切换、工作树切换以及顺序或并行子代理。",
+ "ae79504732": "如何使用",
+ "7bc082f4de": "复制安装命令",
+ "832f1f3ee6": "更喜欢自己的终端?",
+ "9bedd2a6e5": "使代理能够通过 Orca 传递上下文并协调工作。",
+ "07641b9768": "编排技能",
+ "2aacdb0517": "跨切换、工作树切换和子代理工作协调编码代理。",
+ "191ac34567": "代理编排"
+ },
+ "OrchestrationSetupCard": {
+ "e7d2a5146c": "使代理能够通过 Orca 传递上下文并协调工作。",
+ "2777ff0fdc": "编排技能"
+ },
+ "OrchestrationSkillAgentCoverage": {
+ "6dec5ce2d2": "代理覆盖范围",
+ "ffe13e36fb": "缺失",
+ "1e8f8d8fae": "就绪"
+ },
+ "OrchestrationSkillPromptDialog": {
+ "f08d45293d": "复制命令",
+ "35550f3b3b": "完成",
+ "1bdce1911e": "复制编排技能安装命令",
+ "b99f375eb2": "在终端中运行此命令来为您的代理安装编排技能。",
+ "2914abcfa2": "安装编排技能",
+ "d3dc559225": "无法复制安装命令。",
+ "239bf9132b": "复制安装命令。"
+ },
+ "PrivacyDiagnosticBundleControls": {
+ "dc8404a930": "创建预览",
+ "a5acaffdb6": "放弃",
+ "aca2c8a367": "上传",
+ "798b6f0be5": "打开预览",
+ "2ae9a6b63e": "完成",
+ "7f14a1733c": "删除捆绑包",
+ "2801d4ce22": "复制工单"
+ },
+ "PrivacyDiagnosticsSection": {
+ "acc7c66e6e": "OTLP 导出",
+ "4ff08ff3a7": "清除局部痕迹",
+ "9ca08a9f8f": "删除该计算机上的每个轮换跟踪文件。",
+ "fe81a52cb2": "打开跟踪文件夹",
+ "5ff57fc986": "在文件管理器中显示 {{value0}}。",
+ "af2fc82cde": "诊断包",
+ "c18cbe45df": "上传的诊断包已删除",
+ "7a4944595b": "无法复制诊断票",
+ "13eb2c65a1": "已复制诊断票",
+ "860bca9ec9": "诊断包预览已放弃",
+ "49fc6c80e8": "诊断包已上传",
+ "db3228e01a": "诊断包预览已打开",
+ "a2b3505c77": "创建诊断包预览",
+ "9666a05580": "无法清除跟踪文件",
+ "32d767f84d": "本地跟踪文件已清除",
+ "b85fe972cd": "无法打开跟踪文件夹",
+ "1fb00a8995": "已禁用",
+ "46ea3fb2d0": "启用",
+ "7c9d9820b6": "设置 ORCA_OTLP_TRACES_URL 将 Orca 指向您自己的 OpenTelemetry 收集器。"
+ },
+ "PrivacyPane": {
+ "36e0e2e63b": "环境变量。取消设置并重新启动以重新启用。",
+ "79a0f3c16c": "遥测被禁用",
+ "e3970bbbf5": "由于设置了 CI 环境变量,遥测被禁用。取消设置并重新启动。",
+ "fe904ac984": "共享匿名使用数据",
+ "77410e0566": "隐私政策",
+ "8bfdd23a88": "帮助我们弄清楚下一步要构建什么。 Orca 会发送匿名计数,记录您使用的功能以及出现故障的位置。",
+ "afec8b03be": "词"
+ },
+ "QuickCommandsPane": {
+ "8764c6e9e4": "删除 {{value0}}",
+ "7d90fd5299": "编辑 {{value0}}",
+ "8c877dec41": "全球的",
+ "c6b155911b": "所有命令",
+ "5aacc8f7dc": "添加命令",
+ "c36912efd5": "从选项卡栏中的“快速命令”按钮运行它们,或者在任何终端内右键单击。",
+ "f91b649324": "保存的命令",
+ "3d9dc558e8": "该快速命令将从您保存的列表中删除。",
+ "3edf3deaf8": "删除“{{value0}}”?",
+ "9fcfc29519": "插入",
+ "9b3e338d62": "进入",
+ "4ccc63da87": "代理",
+ "0252ddd578": "无命令文本",
+ "7784912ed6": "回购协议",
+ "2bb9e38e93": "无题",
+ "3eb9897ab0": "所选范围内没有命令。",
+ "38d61927e6": "没有保存快速命令。",
+ "44923dd982": "destructive",
+ "ec1ed99e70": "删除",
+ "d1d0976320": "没有任何"
+ },
+ "RecentTabOrderControl": {
+ "3b17c81ede": "标签条顺序",
+ "6e6a3fcc61": "最近的",
+ "7a546f2309": "制表符顺序",
+ "a867a0889f": "最近或标签栏。"
+ },
+ "RepositoryHooksSection": {
+ "af49e2a19e": "该文件存在,但 Orca 找不到有效的“scripts”或“issueCommand”定义。",
+ "3397879bee": "并且本地命令存在,选择哪个运行。",
+ "39da2ae12f": "Orca.yaml",
+ "ac9038d2cc": "当两者",
+ "32fec28f5b": "命令源",
+ "bbbd6e0bc4": "命令源 & orca.yaml",
+ "c9bc1bfd8f": "高级",
+ "610d90fdbd": "命令源和 orca.yaml 详细信息。",
+ "52aef29e69": "留空以使用存储库默认值",
+ "4084720f47": "完成 {{artifact_url}}",
+ "13394103bd": "自定义 GitHub 议题命令",
+ "70ad20f883": "对于链接的议题或 PR URL。",
+ "b997331366": "可选覆盖。使用",
+ "2cc27dc12b": "关联议题命令的可选每用户覆盖。",
+ "b91a0f297d": "在归档工作树之前运行的本地和共享脚本。",
+ "9a100323ff": "存档脚本",
+ "21fb607a87": "创建新工作树时的默认行为。",
+ "793dcee97d": "何时跑步",
+ "63e1783173": "当安装脚本可用时选择默认行为。",
+ "fb6bebcf7e": "何时运行安装程序",
+ "30d555acd2": "创建新工作树后运行的本地和共享脚本。",
+ "52b31baf02": "设置脚本",
+ "8567127a40": "创建或归档工作树时运行的脚本。本地脚本存储在本机上; `orca.yaml` 脚本与您的团队共享。",
+ "ff082fe7c6": "工作树挂钩",
+ "5d940bde5c": "添加本地脚本",
+ "8c2893fae0": "作为单个 shell 脚本运行。保存在本机上。",
+ "40a446ae16": "- 只为您,在这台机器上",
+ "2d03a514db": "当地的",
+ "7e4427b4a2": "改变。",
+ "b113344b6a": "编辑",
+ "f828e1de19": "- 与您的团队分享",
+ "673a7fd10e": "检查中...",
+ "5426ecbdcb": "本地脚本将不会运行",
+ "b2b06c7ce8": "可用的环境变量(将鼠标悬停以查看详细信息):",
+ "95a0411b3e": "模板",
+ "175daba180": "例子",
+ "b20c5df6ca": "添加“orca.yaml”文件以启用此存储库的共享设置、存档或议题自动化默认值。示例模板:",
+ "925f9e0dc4": "文本前景",
+ "0cc712b823": "核心配置文件存在于存储库根目录中,但 Orca 尚无法解析支持的钩子定义。",
+ "c90b858573": "文本-Amber-700 深色:文本-Amber-300",
+ "aba825233f": "该文件包含此版本的 Orca 无法识别的配置密钥。您可能需要更新 Orca,或检查文件是否有拼写错误。",
+ "ca424ff135": "共享挂钩和议题自动化默认值在存储库中定义,可供所有使用它的人使用。",
+ "32f417fe17": "文本-emerald-700 深色:文本-emerald-300",
+ "8bfe65fc60": "使用本地命令",
+ "8d6c56bff8": "运行两者",
+ "0fa21e19ec": "工作区的名称,通常基于分支名称。",
+ "54c73d88d0": "正在创建的工作树的路径。安装命令从此目录运行。",
+ "30952c4aa4": "主仓库结帐的路径。对于将共享文件(例如 .env)复制到工作树中非常有用。",
+ "9b821fa19d": "# e.g. echo \"Cleaning up $ORCA_WORKSPACE_NAME\"",
+ "6f90ebe3fd": "在归档或删除工作树之前运行。",
+ "a3fc966677": "# e.g. pnpm install cp \"$ORCA_ROOT_PATH/.env\" \"$ORCA_WORKTREE_PATH/.env\"",
+ "f0710e1c83": "创建新工作树后运行;安装 deps,复制 env 文件,运行迁移。",
+ "8561b0665f": "首先是 orca.yaml,然后是本地命令。",
+ "0e8b2a520d": "忽略 orca.yaml;仅运行本地命令。",
+ "83dc78202a": "仅限本地",
+ "29397e8bbc": "仅运行已提交的存储库命令;忽略本地命令。",
+ "d88b6ff88f": "仅 Orca.yaml",
+ "99e3264a49": "仅在选择时运行安装程序。",
+ "15debc1fd9": "默认跳过",
+ "022ba10cf2": "自动运行安装程序。",
+ "d3ef1ab247": "默认运行",
+ "90b1f50137": "运行安装程序之前提示。",
+ "e03d9a8f38": "每次都问",
+ "8dbe6bedf5": "无效的",
+ "0e0dd5b9a5": "已加载",
+ "9b12f15b1e": "当一个存在时。",
+ "c85c2c88a2": "{{artifact_url}}",
+ "fac13f8c1e": "权威性",
+ "0518758f38": "两个都",
+ "d2b3016c20": "共享",
+ "4611b78617": "命令源",
+ "c5a55a2d2e": "高级",
+ "b5e3e77e89": "操作",
+ "0ce113fd7b": "保存本地脚本,但脚本源仅设置为 orca.yaml。",
+ "7f78e5eea6": "保存本地脚本。 Orca 仍在检查 orca.yaml,然后才能建议使用哪个脚本源。",
+ "2b6356e744": "已保存",
+ "81057d5f71": "保存中...",
+ "da37d6f10e": "复制",
+ "3149964b66": "已复制"
+ },
+ "RepositoryIconPicker": {
+ "2b7d27b93c": "使用 {{value0}} 仓库颜色",
+ "fde066a63b": "PNG 上传必须为 256KB 或更小。",
+ "cc1286e263": "网站图标",
+ "03ca1a4e9b": "example.com",
+ "381b4844fd": "上传PNG",
+ "7da623abcc": "默认使用 — GitHub 始终提供一个,即使所有者尚未设置自定义图像。",
+ "39da8a10bf": "使用 GitHub 头像",
+ "c490787d24": "表情符号",
+ "b2d7fd2116": "图标",
+ "2d8bd302fa": "阿凡达",
+ "913c55833d": "自定义仓库颜色 {{value0}}",
+ "0e5f0693c1": "选择自定义仓库颜色",
+ "642dc29c6d": "颜色",
+ "549d126081": "重置",
+ "4e2a14f967": "回购图标",
+ "d71df44587": "无法解析 GitHub 存储库。",
+ "f79972271a": "找不到此存储库的 GitHub 远程。",
+ "4d039317f4": "网站图标",
+ "acf31559a0": "输入有效的网站 URL。",
+ "868c5c9b56": "无法导入存储库图标"
+ },
+ "RepositoryPane": {
+ "15a99d9b9f": "相对路径从该项目根解析。",
+ "8ccacbeb5a": "使用全局",
+ "e9bd57a336": "工作树位置",
+ "e63bb96a9b": "新工作树的项目特定目录。",
+ "f88db4fece": "默认工作树基础",
+ "8984d06520": "创建工作树时的默认基本分支或引用。",
+ "e641c359de": "侧边栏和选项卡中使用的项目图标和颜色。",
+ "26fef02bf3": "项目图标",
+ "c7ef4415de": "显示名称",
+ "b0a0c14a1c": "侧边栏和选项卡的项目特定显示详细信息。",
+ "170624bdfb": "从 Orca 中删除该项目。",
+ "0909e5d650": "删除项目",
+ "ee5a290616": "作为文件夹打开。 Git 功能对此工作区不可用。",
+ "323debba71": "类型:",
+ "499a437335": "身份"
+ },
+ "RepositorySourceControlAiActionRows": {
+ "548a6e1281": "命令模板",
+ "7a3a8e431d": "CLI 参数",
+ "2b2f38652b": "自定义命令",
+ "0ffb081b3a": "使用默认代理",
+ "f4310cf63f": "代理",
+ "1cd88d470a": "定制",
+ "403876bb48": "使用全局",
+ "f0aa2cfaea": "操作方案"
+ },
+ "RepositorySourceControlAiCustomCommand": {
+ "0704dd55cd": "存储库命令",
+ "e56668c291": "使用全局",
+ "fbb77e122a": "选择自定义命令的文本操作的存储库回退。",
+ "ebffc5a28c": "自定义命令",
+ "f9941f0caf": "例如ollama 运行 llama3.1 {提示}"
+ },
+ "RepositorySourceControlAiEnablement": {
+ "84233d1bb3": "离开",
+ "bea897eec2": "在",
+ "62511a575d": "使用全局",
+ "30ae6dcce8": "全局默认是",
+ "cf5959c834": "启用源代码控制 AI"
+ },
+ "RepositorySourceControlAiHostedReviewDefaults": {
+ "053ccfbf52": "离开",
+ "777443bf89": "在",
+ "ffc3b26b26": "使用全局",
+ "a68849a859": "全局默认是",
+ "aa6ee4b7d6": "托管评审创建默认值",
+ "629ed8a9d3": "创建后打开托管评审",
+ "14f1eb99d0": "打开 Create PR 时生成详细信息",
+ "d32b87e754": "可用时使用评审模板",
+ "981eae7e14": "默认草稿"
+ },
+ "RepositorySourceControlAiSection": {
+ "67b3ff5467": "放弃",
+ "8b8bc5913a": "仓库操作方案。在此仓库自定义之前,将使用全局设置。",
+ "71b003b62b": "源代码控制 AI",
+ "152268c295": "保存",
+ "57e6e9d4b1": "保存中...",
+ "ccb07dd027": "已保存",
+ "e57dde9d93": "未保存的更改"
+ },
+ "RuntimeAccessGrantList": {
+ "8b82879581": "任何拥有有效授权的人都可以连接,直到您撤销授权为止。撤销共享访问会立即断开活动客户端的连接。",
+ "68ec21309f": "撤销访问权限",
+ "6f6d5188ed": "撤销 {{value0}}",
+ "87b16cd11d": "已创建",
+ "434e4a6af6": "当前链接",
+ "fd83b94095": "尚无共享服务器访问权限。",
+ "27cf8507ad": "刷新共享访问",
+ "f031182867": "共享服务器访问",
+ "df142657a5": "尚未使用",
+ "b18d1764ef": "最后使用 {{value0}}"
+ },
+ "RuntimeEnvironmentsPane": {
+ "aeb26635d2": "删除 {{value0}}",
+ "af53761f31": "取消",
+ "bb90dd6487": "删除服务器",
+ "d2e00809e4": "转变",
+ "05e0fc3ebf": "切换到",
+ "b2290ed203": "Orca 将在从下一个服务器加载项目之前关闭当前服务器的远程终端和浏览器选项卡。",
+ "d570c35a99": "切换服务器",
+ "84b9b2be05": "创建可撤销的访问授权,以便浏览器或其他 Orca 客户端可以连接。",
+ "6e1280ca55": "分享此 Orca 服务器",
+ "9a3758d983": "没有保存的服务器。",
+ "9bee6bbeeb": "添加服务器",
+ "55fcc964cd": "在服务器上并粘贴打印的配对 URL。",
+ "960e901ae4": "orca serve --pairing-address ",
+ "163671f7b5": "跑步",
+ "c3d772c514": "orca://pair?code=...",
+ "9bc9b83474": "配对码",
+ "e038625857": "开发盒",
+ "54ebacc600": "服务器名称",
+ "1826bd0608": "已保存的服务器",
+ "6ce4664003": "刷新服务器",
+ "b07070ed3c": "没有连接服务器",
+ "78692becbd": "本地桌面",
+ "64b6bea541": "活动服务器",
+ "99ac81fb43": "切换到 {{value0}}。",
+ "b5b5114cb0": "删除了 {{value0}}。",
+ "6cb6eae14f": "无法保存运行时环境。",
+ "7b5986c8df": "已保存 {{value0}}。准备好后使用 Active Server 进行切换。",
+ "a5b58465b6": "连接到 {{value0}}。",
+ "5ef712f407": "名为“{{value0}}”的服务器已存在。",
+ "0c55a47480": "需要名称和配对代码。",
+ "e6410d72c3": "无法加载运行时环境。",
+ "6ef71985da": "无终点",
+ "ed3e3f069d": "这将从 Orca 中删除保存的服务器。它不会更改活动服务器。",
+ "b2fda48c39": "删除活动服务器会断开该浏览器的连接并关闭该服务器的远程终端和浏览器选项卡。",
+ "9f7665a01b": "删除活动服务器首先将 Orca 切换回本地桌面,并关闭该服务器的远程终端和浏览器选项卡。",
+ "3595fd1948": "新链接",
+ "54dee18f5c": "隐藏表格",
+ "8cf8790697": "保存的服务器通过配对的 Orca 运行时路由该浏览器。",
+ "f75ce1c7a5": "本地保留了当今的桌面行为。保存的服务器通过远程运行时路由支持的客户端调用。"
+ },
+ "RuntimePairingGeneratedUrlRows": {
+ "0495f68959": "复制 {{value0}}"
+ },
+ "RuntimePairingUrlGenerator": {
+ "849825e829": "将此配对 URL 粘贴到另一个 Orca 客户端中。",
+ "2e5c4e3c93": "与另一个 Orca 客户端配对",
+ "f7cafdc9f3": "浏览器链接在此版本中不可用。配对 URL 仍然适用于 Orca 客户端。",
+ "6b9ca3e69b": "在浏览器中打开",
+ "1ca2e5194d": "从可以到达所选地址的浏览器使用此 URL。",
+ "8de0f84fff": "生成访问链接",
+ "279e0dcb57": "127.0.0.1 仅适用于此计算机。使用 LAN、Tailscale 或其他设备的自定义地址。",
+ "45cf476df3": "主机、主机:端口或 wss://主机/路径",
+ "4531ea3158": "自定义地址",
+ "360c548cf3": "刷新连接地址",
+ "de6d5cff95": "这台电脑(",
+ "de77eb1b65": "连接地址",
+ "ff80904fc4": "为浏览器或桌面客户端创建可撤销的访问授权。",
+ "f8500e134a": "分享此 Orca 服务器",
+ "d6c081adf4": "复制 URL 失败。",
+ "df0aa45a86": "复制的配对 URL。",
+ "13704d635e": "复制的 Web 客户端 URL。",
+ "e8d83f2b0f": "无法撤销共享访问。",
+ "9f8e037c4a": "共享访问权限已撤销。",
+ "d797f516b1": "共享访问权限已被撤销。",
+ "2ed55c841a": "无法生成配对 URL。",
+ "11d5248e62": "生成的配对 URL。",
+ "6dd594a507": "生成的 Web 客户端 URL。",
+ "2752126f3e": "运行时配对不可用。",
+ "95b8be4cea": "刷新网络接口失败。",
+ "1b4e0bbcc5": "无法加载共享访问授权。",
+ "b91e36a986": "网络"
+ },
+ "Settings": {
+ "3bf149e873": "项目设置 > {{value0}}",
+ "075341c763": "仍在形成的新功能。尝试一下。",
+ "8b017f2506": "实验性",
+ "499c1cd7f9": "用于故障排除的低级兼容性设置。",
+ "1c87f8d024": "高级",
+ "c1b43dc4e2": "匿名使用数据和遥测控制。",
+ "d7e3f62d70": "隐私与遥测",
+ "9b83cc62c2": "终端启动的开发者工具的 macOS 隐私访问。",
+ "65660d4548": "macOS 权限",
+ "c6c01ac209": "通过手机控制终端和代理。",
+ "c40dadaac8": "移动端",
+ "c2ee313198": "文件、终端和 git 的远程 SSH 主机。",
+ "9b02492d1f": "SSH 主机",
+ "b5ee17826b": "在本地桌面模式和配对的远程 Orca 运行时之间切换。",
+ "7686cb5c36": "将此浏览器连接到已保存的 Orca 服务器。",
+ "bd0181eeca": "远程 Orca 服务器",
+ "8acf3f22e0": "Orca 统计数据以及 Claude、Codex 和 OpenCode 使用情况分析。",
+ "954a8f5aef": "统计和使用情况",
+ "a737a4bb22": "常见操作的键盘快捷键。",
+ "23bf7a1ad4": "快捷键",
+ "7210ac09c4": "针对代理活动和终端事件的原生桌面通知。",
+ "9907545fa3": "通知",
+ "d0b7021d64": "选择和编辑行为。",
+ "d7a3e635b6": "输入与编辑",
+ "6d1a27e193": "主题、缩放、应用程序和终端外观、侧边栏和状态栏。",
+ "2b4474780a": "外观",
+ "3d9adfe6a5": "全局终端、浏览器和 Markdown 选项卡。",
+ "3eb22a3ada": "浮动工作区",
+ "01f9d36292": "配置对 Orca 和编码代理的移动模拟器支持。",
+ "f75daf1002": "移动模拟器",
+ "ad9788036f": "主页、链接路由和会话 cookie。",
+ "c46215ea03": "浏览器",
+ "6742c7932c": "保存的终端命令,范围全局或每个项目。",
+ "13d4fe30ad": "快捷命令",
+ "b79b5b31e9": "Shell、渲染器、会话和终端行为。",
+ "3de4bbb841": "终端",
+ "dd72ed437a": "选择在“任务”页面和侧栏中显示的任务提供者。",
+ "11faa2f7dd": "任务来源",
+ "cfa34f4465": "分支命名、基础引用、归因和 Git AI Author。",
+ "70100f94c7": "Git 和源代码控制",
+ "b07041697f": "连接 GitHub、GitLab、Linear 和源托管服务。",
+ "c9ca101a3b": "集成",
+ "f9b77539fd": "工作区默认值、应用程序设置和维护。",
+ "7807c11c4d": "通用",
+ "6855b0f77d": "完成使 Orca 对于并行代理工作有用的核心工作流程。",
+ "6d119427ef": "入门清单",
+ "eb1176a14e": "使用设备上模型进行本地语音到文本听写。",
+ "5063bb47a5": "语音",
+ "7118953f14": "使代理能够控制您计算机上的任何应用程序。",
+ "c9841721cb": "计算机控制",
+ "475980f53d": "通过 Orca 协调多个编码代理。",
+ "00c3a7950d": "编排",
+ "21f09426ea": "可选。 Orca 可与您现有的提供商登录配合使用;仅当您希望 Orca 帮助在账户之间切换时才添加账户。",
+ "ad6c529693": "AI 提供商账户",
+ "ec1ba547f7": "管理 AI 代理、设置默认值并自定义命令。",
+ "8afa676615": "代理",
+ "add3b97ee6": "”",
+ "3c88ec55d6": "找不到“的设置",
+ "c7ad095d96": "正在加载设置...",
+ "acc7bbdefd": "再按一次 ESC 退出设置",
+ "43b68e10f0": "您有未保存的 Git AI Author 更改。离开将丢弃它们。",
+ "17bdee4ff1": "放弃未保存的 Git AI Author 更改?",
+ "084d8fac5b": "隐私与安全",
+ "23931df7e8": "远程访问",
+ "8bd117d669": "界面",
+ "e1578cd4bc": "工作流程",
+ "9abb9be3bc": "初始设置",
+ "23c6874fdf": "AI 能力",
+ "2309068a6f": "destructive",
+ "65358016ea": "放弃"
+ },
+ "SettingsFormControls": {
+ "42a4d15a30": "没有匹配的字体。",
+ "b55371ea18": "字体",
+ "c766f8ac75": "切换字体建议",
+ "74bcecd5ec": "清除",
+ "a4ff6143f8": "清除字体选择",
+ "b661b034ec": "· 默认:",
+ "ceefb9d7f1": "未找到主题。",
+ "9119fb2268": "当前",
+ "4e11f87ca6": "显示中",
+ "fbb428db98": "已选择:",
+ "fac59213fc": "搜索内置主题",
+ "cb330ef7f8": "{{value0}} 的",
+ "c822571b2e": "匹配“{{value0}}”",
+ "3119c012a5": "字符串"
+ },
+ "SettingsSidebar": {
+ "e0900f83e7": "SSH",
+ "5c9669ff9c": "项目",
+ "dbceaa8840": "搜索设置",
+ "60f8a673a7": "返回应用",
+ "6503182299": "入门清单",
+ "82db1b7de4": "入门清单,已完成 {{value0}}/{{value1}}。显示设置指南。",
+ "df38d612b7": "尚未添加项目。",
+ "3e483e256b": "没有匹配的项目设置。"
+ },
+ "ShortcutBindingRow": {
+ "4a4c2c9d32": "添加快捷方式",
+ "87381fd8f8": "按键...",
+ "9cdaaa3d8f": "禁用快捷方式",
+ "3b62c142fa": "禁用 {{value0}}",
+ "f75335b155": "重置为默认值",
+ "4f2c9b2a05": "将 {{value0}} 重置为默认值",
+ "97dccee14e": "修改的",
+ "3b11ef3a43": "{{value0}} 快捷方式",
+ "f6579be67b": "更改快捷方式",
+ "6a7848fdac": "正在录制快捷键"
+ },
+ "ShortcutFilterRail": {
+ "28b63545bf": "状态",
+ "8a1e78c14b": "快捷状态过滤器",
+ "df8466f3fc": "清除快捷方式搜索",
+ "f733c4b89f": "搜索命令或按键",
+ "02dc7d4251": "搜索快捷键",
+ "1d5634ba31": "{{value0}} 快捷方式"
+ },
+ "ShortcutRowsList": {
+ "4ce3cd24d9": "没有与这些过滤器匹配的快捷键。"
+ },
+ "ShortcutTerminalPolicyControl": {
+ "0762983d13": "终端优先",
+ "63308571d8": "Orca 优先",
+ "c43c7ff5f9": "决定谁首先拦截捷径",
+ "c3a554288e": "终端中的快捷键",
+ "0f55c6f15c": "选择当快捷键重叠时 Orca 或焦点终端是否获胜。"
+ },
+ "ShortcutsPane": {
+ "4b7ae34062": "直接地。",
+ "38e86e206a": "直观地自定义快捷键或编辑",
+ "47f8f7aef9": "键盘快捷键",
+ "f0b35b0b2e": "当终端或 TUI 具有键盘焦点时禁用。",
+ "5c65d5db9d": "终端优先",
+ "dfa8ff612f": "也在终端或 TUI 具有键盘焦点时运行。",
+ "2a0e8aeccf": "Orca 优先",
+ "3c0fac059a": "当终端具有键盘焦点时仍然运行。",
+ "25b0004fbf": "终端活跃",
+ "781cb74d22": "从终端窗格运行。",
+ "cb02e00202": "终端",
+ "d8c988dab4": "~/.orca/keybindings.json"
+ },
+ "SourceControlAiActionRecipeDefaults": {
+ "2576299196": "参数",
+ "b3914ecbbc": "放弃",
+ "fb09da4345": "命令模板",
+ "2cb4bb7e5d": "CLI 参数",
+ "0740d30915": "自定义命令",
+ "ee0e5c2a48": "使用默认代理",
+ "bf84dea6af": "仅当您希望 Orca 注入上下文时才使用变量。将代理保留为默认值以遵循您的正常代理偏好。",
+ "a79c567194": "操作方案",
+ "cf01d41bce": "每个源代码管理 AI 按钮使用的代理、CLI 参数和命令模板。",
+ "a9359c8aa9": "未知错误",
+ "b5f46664d3": "无法保存源代码控制 AI 操作默认值:{{value0}}",
+ "d18d665e12": "保存",
+ "4f549a5fa8": "保存中...",
+ "9d3cc627f8": "已保存",
+ "817128d94e": "未保存的更改",
+ "7ab1437a12": "拉取请求",
+ "e5b24893ba": "犯罪",
+ "06a9dab64d": "检查",
+ "cb67b938c5": "使固定",
+ "2037c78a6f": "模板",
+ "eb7e8f3b39": "模型",
+ "d74fdc776c": "命令",
+ "673369fe0c": "命令行",
+ "db9bd75d10": "论点",
+ "926d58e87f": "代理"
+ },
+ "SparsePresetSettingsSection": {
+ "6fa754d20f": "删除",
+ "fe1f2c6572": "编辑 {{value0}}",
+ "88bfbf1a9c": "没有为此存储库保存稀疏预设。",
+ "d7565029a9": "新预设",
+ "17f8c4ce10": "管理保存的目录集以创建稀疏工作树。",
+ "388513be2d": "稀疏结账预设",
+ "a05bc9183f": "保存预设",
+ "2d7d45e991": "取消",
+ "c240a16f25": "使用存储库相对路径,例如packages/web 或apps/api。",
+ "fde7ff2cc3": "包/网络共享/ui",
+ "caf33029cc": "目录",
+ "3b6f1abd3e": "例如仅限网络",
+ "a6fcdd9e3c": "姓名",
+ "b9922ec194": "取消预设编辑",
+ "694cc55ecb": "为此存储库创建稀疏工作树时,将使用保存的目录。",
+ "8b64731aaf": "更多的",
+ "755c6a1a0d": "确认",
+ "a7bcf206b1": "正在删除",
+ "ba9ad2d4cd": "更新日期未知",
+ "568d7e1e49": "已更新 {{value0}}",
+ "d7b3f0bdc3": "{{value0}} 目录",
+ "9d3c087fc0": "1 个目录",
+ "8deb7024ab": "正在加载稀疏预设...",
+ "92c08ccae3": "无法加载稀疏预设。",
+ "3dfa765ca7": "将保存 {{value0}} 目录。",
+ "b532b9c17d": "将保存 1 个目录。",
+ "623b4cf910": "编辑预设",
+ "68bbcd864a": "新的"
+ },
+ "SshDestructiveActionDialog": {
+ "895b216267": "取消"
+ },
+ "SshPane": {
+ "c0f1c80166": "未配置 SSH 目标。",
+ "639ceb3698": "添加目标",
+ "51d7dba44d": "导入",
+ "a7d28dff81": "添加远程主机以在 Orca 中连接到它。",
+ "94c5284560": "目标",
+ "f495689b82": "导入失败",
+ "f8050f6307": "已同步 {{value0}} 服务器{{value1}}",
+ "68c13b4589": "测试失败",
+ "81d08bcddf": "连接成功",
+ "2c4ee7332b": "远程继电器复位失败",
+ "db2e48975e": "远程继电器复位",
+ "025e107643": "无法结束远程终端",
+ "90e308c98b": "远程终端结束",
+ "a43de1d3ee": "断开连接失败",
+ "e95d5ae10e": "连接失败",
+ "c2a69510e3": "删除目标失败",
+ "a0237eb1ca": "目标已移除",
+ "2227ce47b6": "保存目标失败",
+ "f602009125": "目标已添加",
+ "b4ba0ce33d": "目标已更新",
+ "3879cbaa52": "中继宽限期必须介于 60 到 {{value0}} 秒之间,或者选择保持活动状态直至重置",
+ "4db9afce1c": "端口必须介于 1 和 65535 之间",
+ "0e5aa04161": "需要主机或 SSH 配置别名",
+ "f1fc50dad2": "无法加载 SSH 目标",
+ "0cda732f43": "连接测试失败"
+ },
+ "SshPassphraseDialog": {
+ "d5a234456f": "取消",
+ "c3ce71aad6": "输入密码",
+ "abaa0dc653": "输入密码",
+ "ce4fdf7914": "输入密码",
+ "dbf9b6f2d0": "输入密码",
+ "c55f105262": "无法取消 SSH 凭据请求",
+ "b8e88fd0de": "无法提交 SSH 凭据",
+ "405066423c": "开锁",
+ "bec2c1318f": "连接",
+ "8a349e3fac": "{{value0}} 的密码",
+ "cab3d5f5a5": "{{value0}} 的密码",
+ "1f3dde805d": "SSH 密钥密码",
+ "106bd57f4a": "SSH 密码"
+ },
+ "SshTargetCard": {
+ "ec6543cee9": "连接",
+ "0e53e9f8e8": "测试",
+ "1810b51482": "连接中",
+ "4c86f30877": "断开连接",
+ "7f7b3d7ab4": "删除目标",
+ "3d21a22d0e": "移除目标",
+ "3d8af2949f": "编辑目标",
+ "762a48c662": "重置远程继电器",
+ "97dea4e8cf": "重置远程继电器",
+ "da16e108e6": "结束远程终端",
+ "c77f1abfe3": "结束远程终端",
+ "18968ede9e": "错误",
+ "f0871e6bfb": "连接",
+ "47e94bd6ba": "已连接"
+ },
+ "SshTargetDestructiveActions": {
+ "7e66942808": "这将停止此 SSH 目标上的活动终端会话。重新连接不会恢复它们。",
+ "accf177a03": "结束远程终端?",
+ "26be00392d": "这将强制停止此 SSH 目标的远程中继。该目标的活动远程终端和端口转发将结束。",
+ "570a7a0574": "重置远程继电器?",
+ "3bb0cf0ee4": "这将删除目标并结束任何活动的远程终端。",
+ "4808966c41": "删除 SSH 目标"
+ },
+ "SshTargetForm": {
+ "fea9cb402e": "取消",
+ "1b19b00e93": "(7 天)。",
+ "137e88ce8d": "断开连接后继电器使端子保持活动状态的时间。默认值:10800(3 小时)。最大限度:",
+ "b574994adc": "远程终端保持可用状态,直到您结束它们或重置继电器。",
+ "71fc546097": "保持活动状态直至重置",
+ "92f80edbfd": "中继宽限期(秒)",
+ "feae1d1e69": "可选。相当于 ProxyJump / ssh -J。",
+ "11bcb4507a": "bastion.example.com",
+ "b2ab248ded": "跳跃主机",
+ "3b01ca44a0": "可选。用于隧道(例如 Cloudflare Access、ProxyCommand)。",
+ "f42d844544": "例如cloudflared 访问 ssh --主机名 %h",
+ "c7d0e18ecb": "代理命令",
+ "cb91f6375c": "可选。默认使用 SSH 代理。",
+ "d6a5f2ee5c": "~/.ssh/id_ed25519(SSH 代理留空)",
+ "63c0c145c1": "身份文件",
+ "c94cfa634c": "端口",
+ "47e082bc17": "部署",
+ "dc1dc52aaa": "用户名",
+ "2ee9bcd2e8": "服务器,部署@服务器:2222,ssh://服务器",
+ "ce370ce674": "主机或别名 *",
+ "b8dab0aa7b": "我的服务器",
+ "298de87a88": "标签",
+ "9518545cb6": "添加目标",
+ "a62b4cb39a": "保存更改",
+ "29af933cd5": "新的 SSH 目标",
+ "f2331ce599": "编辑 SSH 目标"
+ },
+ "TasksPane": {
+ "3a72b9745e": "选择要在“任务”页面和侧边栏快捷键中显示的任务提供商。",
+ "f71d8a9dd3": "任务提供者",
+ "71644aba56": "选择要在“任务”页面源选择器和侧边栏快捷键中显示的任务提供商。至少需保留一个可见提供商。",
+ "93e72ef659": "任务来源",
+ "8e1305fcc6": "在任务源选择器和侧边栏快捷键中显示 Jira。",
+ "6b23a34f6d": "Jira",
+ "e4170c9615": "在任务源选择器和侧边栏快捷方式中显示 Linear。",
+ "09ae2d7c51": "Linear",
+ "dd67a1b6e1": "在任务源选择器和侧边栏快捷键中显示 GitLab。",
+ "7c5d7fdc20": "GitLab",
+ "1db47236cd": "在任务源选择器和侧边栏快捷键中显示 GitHub。",
+ "e14063e727": "GitHub"
+ },
+ "TerminalAppearanceSection": {
+ "a14a427ae4": "窗格分隔线的厚度。",
+ "f27a99978d": "分隔板厚度",
+ "db632cb50e": "不透明度应用于当前不活动的窗格。",
+ "a6fdd6a3b1": "非活动窗格不透明度",
+ "1b79379d4f": "控制非活动窗格调光和分割分隔板厚度。",
+ "e1a5c25555": "终端面板",
+ "04cdf85dec": "终端光标的不透明度。",
+ "b9f1804422": "Cursor不透明度",
+ "2de6b5a699": "使用所选光标形状的闪烁变体。",
+ "74736cc9b1": "闪烁Cursor",
+ "2e5aec3cf6": "强调",
+ "52854a5608": "堵塞",
+ "e070e8aeba": "酒吧",
+ "db270cc9a9": "Cursor形状",
+ "d455f2ef4f": "Orca 终端窗格的默认光标外观。",
+ "abcb4dd019": "终端Cursor",
+ "70beb1bbc7": "预览",
+ "31f6e61085": "目前连字",
+ "870377082f": "离开",
+ "84bd22f2cd": "在",
+ "bc9ff84d61": "自动",
+ "be8da35e7f": "字体连字",
+ "4b1f29598e": "自动 - 对“{{value0}}”禁用。",
+ "400e950ca5": "自动 - 为“{{value0}}”启用。",
+ "04569feb07": "始终关闭,即使对于附带它们的字体也是如此。",
+ "7234abcd08": "始终开启。没有连字的字体只是按原样渲染。",
+ "7233d594bf": "为发布它们的字体渲染编程连字(例如 =>、!=、===)。 “自动”仅对已知的连字字体(Fira Code、JetBrains Mono、Cascadia Code、Iosevka 等)启用连字。",
+ "bafc80efbc": "控制终端线高度乘数。",
+ "c084eb7d4c": "行高",
+ "36af8ad94c": "控制终端文本字体粗细。",
+ "4aae5db258": "字体粗细",
+ "f04b17a50e": "新窗格和实时更新的默认终端字体系列。",
+ "a408266e67": "字体家族",
+ "855a76343a": "从幽灵导入",
+ "711e589f18": "新窗格和实时更新的默认终端排版。",
+ "048aac8a64": "终端排版",
+ "4415beb958": "已禁用",
+ "4e7d41a9f0": "已启用",
+ "e90afcc44f": "离开",
+ "16c471ee03": "在"
+ },
+ "TerminalFontSizeSetting": {
+ "9b5252c85a": "像素",
+ "0f4c92e595": "新窗格和实时更新的默认终端字体大小。",
+ "a4a352b1e9": "字体大小"
+ },
+ "TerminalPane": {
+ "4263e940e0": "按 JIS 日元 (¥) 键会发送反斜杠 (\\\\)。",
+ "19f4935159": "JIS 日元 (¥) 至 反斜杠 (\\\\)",
+ "1c337bef4a": "控制按 JIS 日元 (¥) 键是否发送反斜杠 (\\\\)。",
+ "3fe1c5bfe0": "离开",
+ "c73d510938": "正确的",
+ "e7aec1fd60": "左边",
+ "badb1219fc": "两个都",
+ "43c2ff7b0e": "自动",
+ "0a10420e1a": "选项作为 Alt",
+ "ce3aadf0b2": "{{value0}} Option键发送Alt/Esc;另一个组成特殊字符。",
+ "b62373091a": "两个 Option 键都发送 Alt/Esc 序列。",
+ "d8998bb328": "选项为您的键盘布局组成特殊字符。",
+ "d21c493808": "自动 — 已检测:{{value0}}。",
+ "2561d3fc1b": "控制 macOS Option 键是发送 Alt/Esc 序列还是组合字符。",
+ "96be03b8eb": "PowerShell 7+",
+ "d26174e1dd": "Windows PowerShell",
+ "fe20f79dd1": "PowerShell版本",
+ "822f62ddcd": "下载 PowerShell 7+",
+ "a016ffbeed": "Auto 现在使用 Windows PowerShell,并在安装后切换到 PowerShell 7+。",
+ "5ed5c95344": "为新的终端窗格选择 Windows PowerShell 和 PowerShell 7+。",
+ "3d88af864d": "选择 PowerShell shell 选项是为新终端窗格启动 Windows PowerShell 还是 PowerShell 7+。",
+ "8a956cc91e": "双击选择时将字符视为单词边界。",
+ "4bebcc2b2c": "单词分隔符",
+ "12e06178fa": "MB",
+ "907b0b9d3e": "自定义",
+ "5336c096af": "{{value0}} 兆字节",
+ "81d86b2dd2": "新终端窗格的最大终端回滚缓冲区大小。",
+ "9df53f7c14": "回滚大小",
+ "c3810b2b42": "最大终端回滚缓冲区大小。",
+ "267d020745": "回滚、字边界和特定于平台的终端行为。",
+ "5e5f06c82c": "高级",
+ "003df129fe": "水平分割",
+ "623e62df99": "水平分割",
+ "332e8a2872": "垂直分割",
+ "691ce810e0": "垂直分割",
+ "1158f8fd55": "新标签",
+ "6c6a054a1c": "在新选项卡中运行",
+ "a9d47451d1": "“新选项卡”在标题为“设置”的后台选项卡中打开设置命令,而不会窃取焦点。",
+ "d23b43c5be": "安装脚本位置",
+ "34a0dfa06e": "创建新工作区时运行存储库设置脚本的位置。",
+ "21f8da2078": "工作区设置脚本",
+ "6e6480a7df": "让终端中的程序(tmux、Neovim、fzf、SSH)复制到系统剪贴板。",
+ "3338dcf8c1": "允许 TUI 剪贴板写入 (OSC 52)",
+ "69c64a479c": "让 tmux、Neovim 和 fzf 通过 PTY(包括通过 SSH)复制到系统剪贴板。",
+ "4729c645fc": "自动将终端选择复制到剪贴板。",
+ "902f5dee1f": "选择时复制",
+ "9129b7e805": "将鼠标悬停在终端窗格上即可将其激活,无需单击。",
+ "8eefeaa3da": "焦点跟随鼠标",
+ "96fe15def8": "终端窗格的鼠标和剪贴板行为。",
+ "45721f3e67": "终端交互",
+ "9c0b1c1792": "在",
+ "c1fc9e9444": "GPU加速",
+ "e0996d141a": "Auto 尝试使用 WebGL,并针对不受支持或有风险的渲染器使用 DOM 回退。",
+ "7eaccc1424": "始终尝试将 WebGL 用于终端窗格。",
+ "fe4acf36c6": "WebGL 已禁用; DOM 渲染器可实现最大兼容性。",
+ "f07dfb4466": "控制终端是否使用 xterm.js WebGL 渲染。当渲染器受支持时,Auto 会尝试 WebGL,并为软件或未知 GPU 渲染器提供保守的 Linux 后备方案。",
+ "72bc9334a0": "实时窗格和新窗格的终端渲染器行为。",
+ "2fba319f21": "渲染",
+ "cc8c5ca224": "Windows 默认值",
+ "d78fc4fdef": "加载分布",
+ "219aaa59f4": "WSL分布",
+ "2503f1e86b": "当活动工作区尚未位于 WSL 内时,用于新的 WSL 终端窗格和本地代理检测。",
+ "5fe79a5e56": "选择新 WSL 终端和本地代理扫描使用的 WSL 发行版。",
+ "b637dd57a7": "WSL",
+ "f61ac77f16": "git 重击",
+ "0f1b8669e6": "命令提示符",
+ "eb7fc4d98a": "电源外壳",
+ "27e301f22c": "默认外壳",
+ "09bf02de9a": "打开新终端窗格时使用的 shell。对新终端生效。",
+ "bd68f3170d": "为 Windows 上的新终端窗格选择默认 shell。",
+ "a55eee649f": "Windows 上新终端窗格的默认 shell。",
+ "87e678a8af": "Windows外壳",
+ "05efc0bada": "真的",
+ "348246b06f": "错误的",
+ "5936387ddd": "自动",
+ "adbafefe56": "风俗",
+ "16753eea48": "在 Windows 上,右键单击粘贴剪贴板。 Ctrl+右键单击打开上下文菜单。",
+ "9c178cf8aa": "右键单击粘贴",
+ "af0c3b6e39": "在 Windows 上,右键单击将剪贴板粘贴到终端中。使用 Ctrl+右键单击打开上下文菜单。",
+ "29154326bb": "在",
+ "ab20575a8a": "离开",
+ "ab3a1f9068": "执行程序"
+ },
+ "TerminalSettingsPreview": {
+ "a63953a48a": "预览 {{value0}} 主题",
+ "2c248fcc27": "预览主题",
+ "f8931d407d": "在预览中显示窗格分隔线",
+ "50419052fe": "窗格分隔线",
+ "d06664e889": "黑暗的"
+ },
+ "TerminalThemeSections": {
+ "db210115c5": "灯光模式预览",
+ "5e0c24b5c8": "控制浅色模式下窗格之间的分割分隔线。",
+ "ec2e33ad80": "分光器颜色",
+ "d56af60e6f": "选择 Orca 处于浅色模式时使用的主题。",
+ "8273bc75d7": "浅色主题",
+ "74b15574c8": "配置可选的轻型模式终端外观。",
+ "b584287e84": "禁用后,浅色模式会重用深色终端主题。",
+ "d76f60c9cc": "在浅色模式下使用单独的主题",
+ "bc8e8a251a": "深色模式预览",
+ "cbe56a0f79": "控制深色模式下窗格之间的分割分隔线。",
+ "b739d2abfe": "深色分隔线颜色",
+ "7add204bd5": "选择深色模式下使用的终端主题。",
+ "9499ad1dc4": "黑暗主题",
+ "f012172e21": "选择深色模式下用于终端窗格的主题。"
+ },
+ "TerminalWindowSection": {
+ "1705318506": "ANSI 洋红色",
+ "03c855d15f": "重置所有颜色覆盖",
+ "63f8d9336e": "颜色覆盖",
+ "e86e09b5c7": "覆盖各个终端颜色。",
+ "1d1920dc8a": "在终端中输入时隐藏鼠标光标。",
+ "3530908ef9": "打字时隐藏鼠标",
+ "1846f6ee6a": "终端网格周围的垂直填充(以像素为单位)。",
+ "1afcc1d973": "垂直内边距",
+ "25e2f8e8e1": "终端网格周围的水平填充(以像素为单位)。",
+ "36b8402015": "水平填充",
+ "53ce336e15": "重新启动 Orca 以应用窗口模糊更改。",
+ "c65bb9ce63": "需要重新启动",
+ "97950bb087": "将背景模糊应用到终端窗口。需要重新启动。",
+ "2b82242f43": "窗口模糊",
+ "809f37738d": "控制终端背景的透明度。 1 是完全不透明,0 是完全透明。",
+ "ea7b1a158e": "背景不透明度",
+ "03acb60aa0": "控制终端背景的透明度。",
+ "00eaa6b881": "窗口外观和背景设置。",
+ "b96ba13ed1": "窗户",
+ "42e01a6055": "ANSI 亮白色",
+ "16948119cb": "亮白",
+ "1601140f03": "ANSI 亮青色",
+ "f94adc4113": "亮青色",
+ "fe4d89ef85": "ANSI 明亮的洋红色",
+ "e56e7d6ea0": "亮洋红色",
+ "bef6c0f6bf": "ANSI 亮蓝色",
+ "66820332fa": "亮蓝色",
+ "e2ef5f4ab7": "ANSI 亮黄色",
+ "936a326be3": "亮黄色",
+ "0ffb02f921": "ANSI 亮绿色",
+ "7dafd57730": "亮绿色",
+ "667de68863": "ANSI 亮红色",
+ "32b1b6acd7": "亮红色",
+ "f30c492769": "ANSI 亮黑色",
+ "260d69ce9a": "亮黑色",
+ "1be593d3e8": "ANSI 明亮",
+ "28846b1ca6": "ANSI 白色",
+ "0cb4459fb8": "白色的",
+ "bd4c759327": "ANSI 青色",
+ "fb8bb4eb1f": "青色",
+ "d5e92fcd94": "品红",
+ "9635a71c51": "ANSI 蓝色",
+ "292a4c7316": "Blue",
+ "09c1c6b096": "ANSI 黄色",
+ "bb516de873": "黄色的",
+ "8a673d4206": "ANSI 绿色",
+ "8f2092b315": "绿色的",
+ "b41270f5ca": "ANSI 红色",
+ "3a78f30b50": "红色的",
+ "cf4437a2f7": "ANSI 黑色",
+ "adfdee23cb": "黑色的",
+ "68e9f07de0": "ANSI 标准",
+ "fb8c6f1967": "粗体文本的颜色。如果未设置,则返回正常颜色。",
+ "862e463f7f": "粗体文字",
+ "b2c0857c49": "所选文本的文本颜色",
+ "8b450b5305": "选择前景",
+ "74d8555f85": "所选文本的背景颜色",
+ "40c3cfd30a": "评选背景",
+ "7f4063076c": "光标下文本的颜色(块光标)",
+ "a2d9f095a7": "Cursor文本",
+ "cd0700762b": "Cursor颜色",
+ "c9e1fdf42f": "Cursor",
+ "da64e8f4c1": "终端背景颜色",
+ "cc1b2ffeb2": "背景",
+ "026a0b8013": "主要文字颜色",
+ "79f6bfb76e": "前景",
+ "cf37ff69f6": "根据",
+ "8abdab9f7c": "立即重启",
+ "907131d741": "正在重新启动..."
+ },
+ "UIZoomControl": {
+ "c2c64b24d0": "重置"
+ },
+ "VoicePane": {
+ "68de13f72c": "删除模型失败。",
+ "1ba81c0ff0": "受到推崇的",
+ "cfde55c7b0": "下载模型失败。",
+ "43fd4f454b": "语音模型",
+ "7cf715f891": "举行。",
+ "295d84b849": "一次开始,再次停止。按住:指示同时",
+ "ff9a680010": "切换:按下",
+ "ba4a900d1d": "听写模式",
+ "0121960365": "启用语音听写",
+ "366e1b4f36": "将文本听写到任何焦点窗格中。",
+ "4465596675": "按",
+ "62d2a84d31": "无法清除 OpenAI API 密钥",
+ "37aba8bb63": "OpenAI API 密钥已清除",
+ "8572bbb537": "无法保存 OpenAI API 密钥",
+ "506df81ba6": "OpenAI API 密钥已保存",
+ "91980ce124": "{{value0}} MB",
+ "61a16c8141": "正在提取...",
+ "b6536a1d12": "提取",
+ "8f4d2a51d7": "离线",
+ "d504ab05f0": "流媒体",
+ "fbe5990716": "选择型号",
+ "e24f7d43d2": "选择语音模型。本地模型离线运行;云模型需要 API 密钥。",
+ "174da92062": "抓住",
+ "118b3c2dee": "切换",
+ "901985625d": "切换",
+ "ad5d036ecc": "无法请求麦克风权限。未启用语音听写。",
+ "f9a9cf6928": "启用语音听写之前需要麦克风许可。",
+ "1eac933202": "打开 macOS 隐私和安全。授予访问权限后再次启用听写。",
+ "cd9fe37556": "已授予麦克风权限"
+ },
+ "WorktreeSymlinksSection": {
+ "1c1e35b219": "删除 {{value0}}",
+ "b814c618e2": "链接路径",
+ "31ebab5403": "没有为此存储库配置符号链接路径。",
+ "ea06227efa": "额外",
+ "b2429aeb31": "添加",
+ "ab40b8a5f1": "没有匹配项。继续输入以添加自定义路径。",
+ "4cd2a4c077": "输入路径(例如 .env 或 node_modules)...",
+ "241325302c": "添加路径",
+ "7ff265071d": "创建新工作树时,此处列出的每个路径都将从主签出进行符号链接。",
+ "4755f120b6": "工作树符号链接",
+ "b07ef5a8b6": "从主要签出到新创建的工作树的符号链接路径。",
+ "d72ba8dc68": "{{value0}} 路径",
+ "9ea912d811": "1 条路径"
+ },
+ "WslCliRegistration": {
+ "c6f6f89d7c": "取消",
+ "119fef6cd2": "目标路径:",
+ "1dbb0377d9": "现有启动器目标:",
+ "554305956d": "命令路径:",
+ "9b6627522c": "刷新",
+ "ab6b022a5c": "刷新 WSL CLI 状态",
+ "d9c6880dbd": "WSL shell 命令",
+ "52d990420e": "无法从 WSL 中删除“{{value0}}”。",
+ "89c7414cf5": "从 WSL 中删除了 `{{value0}}`。",
+ "6f91ad1333": "无法在 WSL 中注册“{{value0}}”。",
+ "951536dda5": "在 WSL 中注册了 `{{value0}}`。",
+ "26b4b3b00f": "无法加载 WSL CLI 状态。",
+ "290bfff3ab": "注册",
+ "f951f85196": "移除",
+ "4c4a9178a3": "注册...",
+ "41a1480d3e": "安装",
+ "4598b18464": "正在删除...",
+ "7c3bb36706": "移除",
+ "7ee4e52b99": "Orca 将注册 {{value0}} ,以便该命令在 WSL 终端上运行。",
+ "d8216eb22e": "这会删除 WSL shell 命令。 Orca 本身仍安装在 Windows 上。",
+ "e49688f67f": "在 WSL 中注册 `{{value0}}`?",
+ "61ac55278e": "从 WSL 中删除“{{value0}}”?",
+ "e2b0ee267f": "陈旧",
+ "7aa456a460": "在 WSL 内的 ~/.local/bin 中注册 `orca-ide`。",
+ "0307677bb9": "正在检查 WSL CLI 注册..."
+ },
+ "accounts": {
+ "search": {
+ "86edc96bc9": "状态栏",
+ "e949b08ffb": "速率限制",
+ "7e67d7d1b6": "沃克",
+ "421c6be25e": "ID",
+ "be8b621bdc": "工作区",
+ "8dcbef1856": "opencode",
+ "38d22ff8d6": "如果自动查找失败,可选的工作区 ID 覆盖。",
+ "4ee2029e9c": "OpenCode Go 工作区 ID",
+ "9c4e40cf6b": "会话",
+ "61f7d1fcbe": "曲奇饼",
+ "d1d2ae383c": "粘贴您的 opencode.ai 会话 cookie 以进行速率限制获取。",
+ "6ed1401020": "OpenCode Go 会话 Cookie",
+ "b7c2cee442": "实验性",
+ "7118d2f908": "证书",
+ "933deaf732": "OAuth",
+ "8630464352": "CLI",
+ "e8e1ff3887": "gemini",
+ "bada4a3218": "从本地 Gemini CLI 安装中提取 OAuth 凭据以通过 Google 进行身份验证。",
+ "d819755b02": "使用 Gemini CLI 凭据",
+ "35b461d817": "登入",
+ "f2d666a886": "可选",
+ "8b06729e0f": "活跃",
+ "5b3f18ef4a": "转变",
+ "06662af91e": "账户",
+ "70d1b8def5": "codex",
+ "87a4a8584e": "选择哪个可选的已保存 Codex 账户支持实时配额读取。",
+ "a4bcfd6f86": "活跃 Codex 账户",
+ "042885c07c": "过时的",
+ "02c438bc7b": "已到期",
+ "77e32a2ad3": "重新验证",
+ "c759741d77": "配额",
+ "b40d5b6570": "Codex 和实时速率限制提取的可选账户切换。",
+ "17c5d244eb": "Codex 账户",
+ "e14049e1a8": "claude",
+ "dd75a73991": "Claude 的可选账户切换,同时保留共享聊天上下文。",
+ "75682e1b62": "Claude 账户",
+ "e02c136ad0": "授权",
+ "9f70aa706c": "提供者",
+ "488a7e9206": "操作系统",
+ "0b4d948eb5": "wsl",
+ "bdbd1e668e": "视窗",
+ "593720c17f": "位置",
+ "b84a5b0c8a": "选择是否在此设备上或 WSL 中检查和添加提供商账户。",
+ "d09fb5ca92": "账户位置"
+ }
+ },
+ "advanced": {
+ "search": {
+ "a7002e1ac4": "更新程序",
+ "e61ed8ab33": "更新",
+ "6576fce4d2": "故障排除",
+ "79e0947e95": "支持",
+ "4383251647": "VPN",
+ "f98a60af11": "代理",
+ "65bf6af262": "兼容性",
+ "621233008b": "http/1.1",
+ "f8ff125ebe": "http1",
+ "a0f71bd909": "http/2",
+ "4b4ae4345a": "http2",
+ "48a1c8f534": "http",
+ "4d44352eea": "网络",
+ "2b4d26d11e": "联网",
+ "e04e9db503": "高级",
+ "585f56fae0": "当 HTTP/2 在代理后面失败时,使用 HTTP/1.1 进行 Electron 网络。",
+ "11eea3da72": "HTTP/1.1 兼容性"
+ }
+ },
+ "agents": {
+ "search": {
+ "2814401339": "已安装",
+ "719f53350c": "路径",
+ "839e82c81f": "检测",
+ "f622b8eb2a": "操作系统",
+ "d608654c03": "wsl",
+ "77c02fa3c3": "视窗",
+ "d2952dfd74": "位置",
+ "96ba2373b6": "代理",
+ "cbdd7f3b9e": "选择是否在此设备上或 WSL 中检测已安装的代理。",
+ "ef804b7337": "代理位置",
+ "01926b9d8c": "配置 AI 编码代理、默认代理和命令覆盖。",
+ "bb9ad95777": "代理",
+ "d8f3a8b8a0": "默认",
+ "167daeb5e9": "命令",
+ "be59907510": "覆盖",
+ "a6d594c17d": "安装",
+ "f2932bf22b": "已检测",
+ "2afd3b5858": "启用",
+ "60393e1b17": "禁用",
+ "2e188c771c": "隐藏",
+ "87fffe6c20": "显示",
+ "e2b7c0dcd7": "GitHub",
+ "66b6b82eb4": "唤醒",
+ "dbc8aca6b0": "睡眠",
+ "845ad9128a": "电源",
+ "48f84d10f1": "运行中",
+ "affbf130f6": "工作中",
+ "0d1c334987": "合盖",
+ "ff8de8a2ad": "显示器",
+ "0d752916f8": "钩子",
+ "6984d4291a": "状态",
+ "13b20636a6": "等待",
+ "8599603496": "完成",
+ "ea71995548": "移除",
+ "c1317fe641": "恢复",
+ "5963143e00": "设置",
+ "042c551bc5": "配置",
+ "f412abbba5": "claude",
+ "5ded38b843": "codex",
+ "be7ea3553b": "标签页",
+ "6956646a1e": "标题",
+ "32836788b0": "生成的标题",
+ "966890236d": "名称",
+ "848dcae8d3": "生成",
+ "52115d0d7c": "自动",
+ "c64059f50d": "提示词",
+ "5784ae8c43": "重命名",
+ "8a17fd6026": "稳定",
+ "a79d266f71": "会话",
+ "afbf35be68": "稳定会话"
+ }
+ },
+ "appearance": {
+ "search": {
+ "468448bba4": "水彩",
+ "f586abfa35": "Blue",
+ "651f35b2c6": "切换器",
+ "e5bc35d59e": "窗户",
+ "d18b54ca90": "码头",
+ "1f2880a9d5": "orca",
+ "2cfb3420c0": "应用程序图标",
+ "e80c2af428": "选择 Dock 和窗口切换器中显示的应用程序图标。",
+ "2b313598c6": "应用程序图标",
+ "839fb1e3ed": "工具箱",
+ "ac79fe4a04": "显示",
+ "648eeada79": "隐藏",
+ "6cf5f54ce1": "按钮",
+ "5bff6a2ef0": "侧边栏",
+ "5e5b8878bf": "手机",
+ "74618577c7": "移动端",
+ "682293cadf": "在左侧边栏顶部显示 Orca Mobile 按钮。",
+ "1de96ec8a6": "显示 Orca Mobile 按钮",
+ "4c920ab2d1": "日程",
+ "58f4e22fa2": "自动化",
+ "b186f3cefb": "自动化",
+ "ae13a0d340": "在左侧边栏顶部显示“自动化”按钮。",
+ "caa27e1a8e": "显示自动化按钮",
+ "6b846424cc": "Linear",
+ "2ee4810f38": "GitHub",
+ "0d5a74b606": "任务",
+ "9a248333c7": "在左侧边栏顶部显示“任务”按钮。",
+ "155a1e7438": "显示任务按钮",
+ "a895d0f938": "品牌",
+ "51f957ce39": "姓名",
+ "36e006efc1": "应用程序",
+ "bed343b03e": "标题栏",
+ "18b4c4c30b": "在标题栏中显示 Orca。",
+ "fdd31b00d0": "标题栏应用程序名称",
+ "c1bca1885a": "文件浏览器",
+ "9f2df826ac": "被忽略",
+ "08c86bf58e": "吉蒂诺尔",
+ "bce3ac317a": "git",
+ "7164edf71a": "文件资源管理器中与 .gitignore 匹配的暗淡文件。",
+ "f8129fb544": "显示 Git 忽略的文件",
+ "2f12e1aa3a": "用户界面",
+ "5095258df2": "界面",
+ "fab91464dd": "IDE",
+ "8b36fb3f64": "版式",
+ "a0e09aed9c": "字体",
+ "24094af355": "字体",
+ "07c7c38fac": "选择 Orca 界面使用的字体。",
+ "ddb991024d": "IDE字体",
+ "0c83659f48": "捷径",
+ "0952091186": "比例",
+ "3ae5de6101": "缩放",
+ "adddb91a3d": "缩放整个应用程序界面。",
+ "c5e933970f": "用户界面缩放",
+ "3a9b69d734": "系统",
+ "44d873fd18": "浅色",
+ "262fe1d24f": "深色",
+ "0709c794f7": "选择 Orca 在应用程序窗口中的外观。",
+ "71e06350b4": "主题",
+ "dc02c8759d": "工作区",
+ "43cfba3b95": "服务器",
+ "46d21eef62": "本地主机",
+ "006e67b279": "端口",
+ "896eb53fd4": "状态栏",
+ "0ececfa190": "在状态栏中显示实时工作区端口。",
+ "cf409b6c4d": "端口",
+ "cb1cc62cf8": "空间",
+ "90bdc043ea": "磁盘",
+ "96b4fb0064": "终端",
+ "4ddbde4999": "中央处理器",
+ "4355f18ac6": "记忆",
+ "9c4d5f0894": "经理",
+ "c690a15849": "资源",
+ "81ef5abc2f": "在状态栏中显示 CPU、内存、终端会话和工作区磁盘使用情况。",
+ "7cf005b29f": "资源管理器",
+ "fe192b060e": "主持人",
+ "f4997e0f8a": "联系",
+ "a278406ed5": "偏僻的",
+ "6ecad74eb3": "SSH",
+ "f17d66d0d2": "在状态栏中显示活动的 SSH 连接状态。",
+ "57fb424c56": "SSH 状态",
+ "35565867cb": "登月计划",
+ "de586def95": "订阅",
+ "00a028f25f": "用法",
+ "40e5c3c285": "基米",
+ "c927a155d5": "在状态栏中显示 Kimi 订阅使用情况。",
+ "3a6c028ea8": "基米用法",
+ "edbf0f63a0": "成本",
+ "afbb6a3767": "Token",
+ "d77537b580": "opencode-go",
+ "a9d56852eb": "opencode",
+ "7f72de7cbe": "在状态栏中显示 OpenCode Go Token 和成本使用情况。",
+ "bc046e7899": "OpenCode Go 用法",
+ "51b0ccd6a2": "谷歌",
+ "2804a920ad": "gemini",
+ "9660c5b2f1": "在状态栏中显示 Gemini Token 和成本使用情况。",
+ "5bfb874d05": "Gemini 使用情况",
+ "97957e374e": "开放伊",
+ "8dfd676c28": "codex",
+ "e9e4412545": "在状态栏中显示 Codex Token 和成本使用情况。",
+ "54b1acf24f": "Codex 使用情况",
+ "dea0a9a665": "anthropic",
+ "c9fe3a7876": "claude",
+ "de50c6f516": "在状态栏中显示 Claude Token 和成本使用情况。",
+ "9dc15020d7": "Claude 使用情况",
+ "language": {
+ "locale": "区域设置",
+ "i18n": "国际化",
+ "translation": "翻译"
+ }
+ }
+ },
+ "auto": {
+ "rename": {
+ "branch": {
+ "search": {
+ "0971762141": "烤肉串盒",
+ "a482f6a423": "蛞蝓",
+ "7adefcdd94": "模板",
+ "10485c4fc5": "命令",
+ "50139297e6": "内置提示",
+ "502aa57681": "指示",
+ "40d21f2efc": "提示词",
+ "672387fb77": "生成分支名称时使用的代理命令模板。",
+ "722551c5b3": "分支名称命令模板",
+ "f41833025e": "产生",
+ "ed677944cc": "工作树",
+ "3ef3cbe98c": "代理",
+ "f0acf64301": "生物名称",
+ "7803423877": "自动",
+ "55a1860e47": "重命名",
+ "9319bd9827": "分支",
+ "ea94b9da8a": "代理启动后,根据工作重命名自动生成的分支。",
+ "427f2cd1eb": "自动重命名分支"
+ }
+ }
+ }
+ },
+ "browser": {
+ "search": {
+ "7539f6336c": "轮廓",
+ "1c1e097985": "弧",
+ "533a253deb": "边缘",
+ "75a0d435b7": "铬合金",
+ "854ef6ce83": "登录",
+ "3910a41f32": "授权",
+ "2e7f951773": "导入",
+ "66dd641a47": "会话",
+ "29193a51d5": "曲奇饼",
+ "2d2d995c58": "浏览器",
+ "060ac1fcba": "从 Chrome、Edge 或其他浏览器导入 cookie,以使用 Orca 内的现有登录信息。",
+ "96afedcb5c": "会话和 Cookie",
+ "a7a07d5415": "编辑",
+ "8dd4805991": "文件",
+ "68d1db8929": "降价",
+ "90425d313c": "转移",
+ "72c58f7792": "网页视图",
+ "82ba1c80ea": "本地主机",
+ "bea27bac4b": "链接",
+ "44d14df30d": "预览",
+ "5cb082b3e3": "链路路由",
+ "95944898e0": "百分比",
+ "483a0eb5e0": "新标签",
+ "726f2a8556": "页面缩放",
+ "5448f4097b": "默认",
+ "54f4ea55f7": "比例",
+ "4a98ed195f": "缩放",
+ "c3d89ed4d0": "缩放级别应用于新打开的浏览器选项卡。",
+ "072b7f5c1f": "默认缩放",
+ "0bb34eacc9": "询问",
+ "8b8ed06e4b": "多功能框",
+ "3538b3aaeb": "Token",
+ "0732ebe6fb": "私人的",
+ "e1c2a57f07": "卡吉",
+ "ad40e75d13": "冰",
+ "1f8153acfb": "鸭鸭戈",
+ "8a489aab8d": "谷歌",
+ "72b4b89970": "引擎",
+ "16bd69cd82": "搜索",
+ "0628d5943b": "在地址栏中输入非 URL 文本时使用的搜索引擎。",
+ "5e755920c9": "默认搜索引擎",
+ "4596a52cf7": "降落",
+ "5164c47e31": "空白的",
+ "4fda4fb066": "网址",
+ "0dbb1eaf4e": "主页",
+ "291f480a5e": "家",
+ "a942905148": "创建新浏览器选项卡时打开的 URL。留空以打开空白选项卡。",
+ "c3903322d2": "默认主页"
+ },
+ "use": {
+ "search": {
+ "3f4c559deb": "圆弧轮廓",
+ "d5afa54d21": "边缘轮廓",
+ "22fb801af8": "镀铬型材",
+ "59968bb9b4": "经过身份验证的浏览器",
+ "62e2a790c0": "现有会话",
+ "63a66da648": "系统浏览器",
+ "20c1323d1e": "计算机控制",
+ "ab349a2dd0": "弧",
+ "2e1b09897b": "边缘",
+ "088e7a9012": "铬合金",
+ "96ce3d2de2": "授权",
+ "48557f639c": "登录",
+ "d5ad1f7aad": "导入",
+ "02837ee497": "会话",
+ "fb8178824f": "曲奇饼",
+ "ba4eb53b72": "浏览器使用",
+ "2fb24d17db": "从 Chrome、Edge 或其他浏览器导入 cookie,以便代理可以重复使用您的登录信息。",
+ "614c756ab1": "导入浏览器 Cookie",
+ "cee44fb442": "自动化",
+ "a57c2172dc": "代理浏览器",
+ "6ea88e5206": "恩克斯",
+ "f5b8fdddf5": "orca-cli",
+ "e5a784bc54": "安装",
+ "9d97446873": "代理",
+ "a2d489263e": "技能",
+ "a7e82445fa": "安装浏览器使用技能,以便代理可以操作 Orca 的浏览器。",
+ "a1414dcefb": "安装浏览器使用技能",
+ "e56c7b55c9": "设置",
+ "034c5e8d7f": "启用",
+ "7e0dcb257a": "壳",
+ "3ffafc9b95": "命令",
+ "30c74aaa1f": "路径",
+ "ff05cbc344": "orca",
+ "85fab5e12c": "CLI",
+ "890ddf943d": "注册 Orca CLI,以便代理可以驱动浏览器。",
+ "50f0860e18": "启用 Orca CLI"
+ }
+ }
+ },
+ "commit": {
+ "message": {
+ "ai": {
+ "search": {
+ "3766941527": "代理",
+ "181cdb0637": "打开",
+ "8e9cc598d7": "产生",
+ "b7d50da4d8": "模板",
+ "7e264b926b": "草稿",
+ "b261c88609": "PR",
+ "110be48b81": "拉取请求",
+ "001ca3f2af": "创建 PR 编辑器打开时使用的默认值。",
+ "eefd33788c": "PR 创建默认值",
+ "d32936bb2a": "分支",
+ "127d512e75": "犯罪",
+ "d22a6459e4": "冲突",
+ "53e8504fb2": "词",
+ "c46e665f7e": "检查",
+ "37c65bbb44": "使固定",
+ "402f101af8": "提示词",
+ "8e0bcc5d99": "模型",
+ "f4731b22bf": "命令",
+ "57c851a68c": "CLI",
+ "61117e57f3": "参数",
+ "0f29331fed": "论点",
+ "18b6d38835": "每个源代码管理 AI 按钮使用的代理、CLI 参数和命令模板。",
+ "3c4e5e5938": "操作方案",
+ "ee14a9e9f7": "已启用",
+ "82109d627d": "源代码控制",
+ "542e1a00a7": "codex",
+ "f121bec167": "claude",
+ "93e5210da8": "信息",
+ "c33cb1b982": "AI",
+ "0b946b2abe": "为源代码管理的提交、拉取请求、分支命名和修复操作添加操作方案。",
+ "24dbdfca78": "显示源代码控制 AI 操作"
+ }
+ }
+ }
+ },
+ "computer": {
+ "use": {
+ "search": {
+ "6e88da3508": "技能",
+ "798be54d7e": "自动化",
+ "e27f8bafbf": "截屏",
+ "26c1290d83": "屏幕录制",
+ "82f01c2d2c": "可达性",
+ "fefb452f5b": "计算机控制",
+ "9210db582b": "当您要求时,允许代理检查屏幕截图并操作本地应用程序。",
+ "442bec10fe": "计算机控制"
+ }
+ }
+ },
+ "developer": {
+ "permissions": {
+ "search": {
+ "3363889768": "本地网络、USB 和蓝牙",
+ "6c82846f66": "设备",
+ "11653d3f42": "域名服务器",
+ "78a10b826f": "你好",
+ "e3fbc48083": "蓝牙",
+ "c4a4a02ea4": "USB",
+ "fa3239cd42": "本地网络",
+ "acad3d4743": "允许从终端会话使用设备和本地网络工具。",
+ "3e0131e45d": "云",
+ "ce07159ff5": "桌面",
+ "a0c19119fb": "下载",
+ "4438f81bfa": "文件",
+ "c10e36cbd1": "全磁盘访问",
+ "05ab708ee5": "打开 macOS 隐私窗格以进行广泛的终端文件访问。",
+ "bbf543a3a1": "全磁盘访问",
+ "7f145a3984": "窗户",
+ "5610022e1e": "自动化",
+ "0a467b750e": "截屏",
+ "08f8039ca9": "可达性",
+ "3cd51d18a1": "屏幕录制",
+ "2e5d98ab56": "允许屏幕截图、屏幕检查、击键和窗口自动化。",
+ "39bb49e662": "屏幕录制和辅助功能",
+ "00e954319e": "耳语",
+ "1e6e27b202": "ffmpeg",
+ "f061f08b7b": "袜队",
+ "a765112513": "视频",
+ "b192432ef0": "声音的",
+ "af122938a3": "语音",
+ "259b829b84": "相机",
+ "ed7c12bdb4": "麦克风",
+ "6eca1636b7": "允许语音、转录、网络摄像头和媒体捕获工具。",
+ "302c0c42f9": "麦克风和摄像头",
+ "4e225e7c56": "开发者工具",
+ "6db4fca386": "麦科斯",
+ "0c13b249e3": "TCC",
+ "2270ccff3f": "隐私",
+ "a98aa11a9c": "权限",
+ "bc8ac95310": "终端启动的开发者工具的 macOS 权限。",
+ "e92cb0896d": "开发者权限"
+ }
+ }
+ },
+ "experimental": {
+ "search": {
+ "44c7f209d5": "节点模块",
+ "4ad605f222": "环境",
+ "3021571c30": "共享",
+ "f082788cfe": "链接",
+ "3028f0bd3a": "关联",
+ "bff1ff7768": "符号链接",
+ "c387565812": "符号链接",
+ "10b52f79c1": "工作树",
+ "d23ae13990": "工作树",
+ "0d24759f14": "实验性",
+ "603d29ed74": "自动将配置的文件或文件夹符号链接到新创建的工作树中,以便共享状态(环境、缓存、安装)保持连接。",
+ "78c2a8dc74": "工作树上的符号链接",
+ "7b79081695": "未读",
+ "f10d307468": "完成",
+ "5f067ba0f9": "代理",
+ "7695fd30e9": "通知",
+ "8facf10138": "钟",
+ "edc49480a1": "窗格",
+ "268e99d957": "强调",
+ "01567f19ca": "注意力",
+ "9bb3bd5098": "终端",
+ "11877246fc": "终端响铃和代理完成事件的持久窗格突出显示。",
+ "9e4ddf776d": "终端关注",
+ "fe5688b761": "侧边栏",
+ "ca5d1f3f46": "时间线",
+ "d01b3882ba": "通知",
+ "244a0ecd3d": "活动",
+ "92a9357d1f": "代理视图",
+ "fa72e71f05": "代理",
+ "4d63251595": "用于代理完成和阻塞状态的螺纹左侧边栏提要。",
+ "ccc5548ac5": "代理查看",
+ "9af7a518db": "特点",
+ "791fefc0b0": "角落",
+ "65df471ab2": "动画",
+ "9f5609bfb8": "覆盖",
+ "2a33975d72": "吉祥物",
+ "b54cea709b": "伙伴",
+ "051203d37c": "宠物",
+ "6b5a56ac35": "右下角漂浮的动画宠物。",
+ "87d99e634b": "宠物"
+ }
+ },
+ "floating": {
+ "workspace": {
+ "search": {
+ "94f4d013c8": "状态栏",
+ "a452146574": "切换按钮",
+ "6765b85e48": "启动目录",
+ "a38bfc3f77": "快速面板",
+ "52db6e3baf": "笔记",
+ "156ffeee08": "笔记",
+ "884e5e6132": "降价",
+ "49db74a92d": "浏览器",
+ "6410fe83d8": "终端",
+ "2b5efa55c9": "全球的",
+ "ebeedb2f6a": "快捷终端",
+ "6f183fa1b9": "浮动码头",
+ "a08e482f6d": "浮动工作区",
+ "b96b5ee6cf": "启用浮动工作区,选择新选项卡的开始位置,然后选择切换按钮的显示位置。",
+ "b2b60e7163": "浮动工作区"
+ }
+ }
+ },
+ "general": {
+ "search": {
+ "bdfb6dc21b": "喜欢",
+ "e6b01c8e30": "反馈",
+ "b65665703a": "支持",
+ "06ea5a69a6": "GitHub",
+ "e4fb4516d0": "星星",
+ "e0b8c8bc25": "通过 gh CLI 通过 GitHub star 支持该项目。",
+ "36a72f0d9e": "GitHub 上的 Star Orca",
+ "c61b14be7c": "grok",
+ "5d9ba08673": "copilot",
+ "f472e97440": "助手",
+ "3c30fe2d51": "gemini",
+ "5fdf1dc2d1": "奥普",
+ "9b0bc30160": "pi",
+ "882c4896fd": "opencode",
+ "27d9b996ba": "codex",
+ "5baf51c4d9": "打开 Claude",
+ "aea7d2cccb": "openclaude",
+ "95b63edde7": "claude",
+ "41c2f9a025": "默认",
+ "8ea37a05bc": "代理",
+ "e2da948f59": "在新工作区编辑器中预先选择 AI 编码代理。",
+ "db11502270": "默认代理",
+ "3462308bd3": "Token",
+ "660528b048": "成本",
+ "585beac3f8": "TTL",
+ "0efc9d96ad": "提示词",
+ "939b80f5fd": "计时器",
+ "b2601a778c": "缓存",
+ "40c9585e43": "显示提示词缓存到期倒计时的计时器(Claude 代理)。",
+ "1e0f28c6f1": "提示缓存定时器",
+ "e49e739a59": "下载",
+ "c9d8c1ce66": "发行说明",
+ "9e86ccd05c": "版本",
+ "f89a94773c": "更新",
+ "79ff46776e": "检查应用程序更新并安装较新的 Orca 版本。",
+ "e15af4eb64": "检查更新",
+ "6382fe9724": "恩克斯",
+ "baa263d6d8": "代理",
+ "bda108e66c": "技能",
+ "244e3fb4c8": "安装 Orca 技能,以便代理知道如何使用 Orca CLI。",
+ "2d9f7b42df": "代理技能",
+ "0a00691c06": "Shell 命令",
+ "dbeb1f348e": "命令",
+ "88d3df9ce9": "终端",
+ "fb4f338a3d": "路径",
+ "924a660a78": "CLI",
+ "ca529079bf": "注册或删除 Orca CLI 命令。",
+ "327e3fa70d": "Orca CLI",
+ "fb84767421": "转变",
+ "f8f0ac213a": "顺序的",
+ "12ecc640a8": "姆鲁",
+ "54ba13831a": "最近的",
+ "750420dd9a": "控制",
+ "fe62b3f09f": "控制键",
+ "2a254b725e": "标签页",
+ "ca812803ea": "最近的 Tab 键顺序",
+ "e53d585ed6": "最近或标签栏。",
+ "256d92554d": "制表符顺序",
+ "22572e99c1": "注释",
+ "1ff67ba40c": "笔记",
+ "4dd5684836": "评审",
+ "d05f629d2c": "降价",
+ "694613d47f": "在富文本编辑器模式下显示本地 Markdown 评审笔记控件。",
+ "128bc09325": "Markdown 评审笔记",
+ "a0014961ae": "滚动",
+ "3ca5ab78a5": "代码",
+ "e3919429c0": "概述",
+ "9c72990db8": "小地图",
+ "716a4dfb1f": "编辑文件时显示小地图概述。",
+ "6f584fcb48": "小地图",
+ "19baae651b": "侧边栏",
+ "973ed6bfbf": "组合差异",
+ "0a02059549": "文件树",
+ "2f42852568": "树",
+ "3b5733573e": "差异",
+ "dec71988f0": "打开组合差异视图时显示或隐藏文件树。",
+ "adec13f2ef": "默认差异文件树",
+ "be24c7cd67": "拆分",
+ "233f7e2f37": "并排",
+ "0a5fa65926": "内联",
+ "2b463f0bf9": "看法",
+ "ecb9415c80": "默认情况下显示 git diff 的首选演示格式。",
+ "2760c9933f": "默认差异视图",
+ "b2799ba622": "毫秒",
+ "146728ac2c": "延迟",
+ "86f54575c7": "自动保存",
+ "8ea61ad55c": "Orca 在您上次编辑后等待多长时间才会自动保存。",
+ "14e46c745b": "自动保存延迟",
+ "4469b6fa4e": "保存",
+ "e9d948d3c3": "短暂暂停后自动保存编辑器和可编辑差异更改。",
+ "ae21e806ce": "自动保存文件",
+ "c56cb6f1c2": "网络",
+ "3566fce83f": "本地主机",
+ "91a46caafc": "无代理",
+ "3a73054565": "旁路",
+ "20b711ac9e": "代理",
+ "eb8946b2c9": "应绕过配置的 HTTP 代理的主机。",
+ "8436ff6f8e": "代理绕过规则",
+ "e55d62dfa4": "启动板",
+ "9da6c875e5": "码头",
+ "b9096a44cf": "https_代理",
+ "8f03d44672": "http_代理",
+ "e3b1d42f95": "Orca 网络请求和本地终端子项的代理 URL。",
+ "c29f23ab57": "HTTP代理",
+ "6c2ce8457c": "文件浏览器",
+ "c9d9636f24": "发现者",
+ "68d03d9980": "VSCode",
+ "ebf8f056b5": "泽德",
+ "0cb3d94f00": "cursor",
+ "8fb00fcd05": "启动器",
+ "e1ee631696": "编辑",
+ "5a9df5566f": "打开菜单",
+ "b8093e9a93": "打开方式",
+ "a916662068": "从工作区的“打开方式”菜单中选择可用的应用程序。",
+ "451d4af994": "在应用程序中打开",
+ "7e9b556873": "跳过",
+ "ca86dd6e27": "对话",
+ "9f8558233a": "确认",
+ "7edf4f69e2": "自动化",
+ "84c67d0108": "删除",
+ "a0c44061ee": "在删除自动化及其运行历史记录之前显示确认对话框。",
+ "d0a65b27fd": "删除自动化之前询问",
+ "df10666259": "工作树",
+ "ae98c9cf36": "删除工作区之前显示确认对话框。",
+ "913242091d": "删除工作区之前询问",
+ "93f6ec5e70": "目录",
+ "9bde064915": "子文件夹",
+ "ec5049e510": "嵌套的",
+ "b9cffd374d": "在以 repo 命名的子文件夹内创建工作区。",
+ "141f71c69f": "嵌套工作区",
+ "7887a2c262": "文件夹",
+ "7baf524b04": "工作区",
+ "d0bc793689": "创建工作区文件夹的根目录。",
+ "4c95d08fa2": "工作区目录"
+ }
+ },
+ "git": {
+ "search": {
+ "61eab13403": "orca",
+ "1b93c1143c": "归因",
+ "8461c908ae": "合着的",
+ "61f9f5d1fc": "共同作者",
+ "af0a144bfb": "议题",
+ "6bdea421bb": "PR",
+ "16f53f7323": "gh",
+ "d088806071": "GitHub",
+ "118c23484b": "将 Orca 归因添加到提交、PR 和议题。",
+ "bc7d9f69ce": "Orca 归因",
+ "40f9b815fd": "API预算",
+ "b7e52124c7": "速率限制",
+ "ead733645f": "光亮的",
+ "4808f065b3": "GitLab",
+ "2b4a72885d": "当前 GitLab CLI REST 速率限制标头(如果可用)。",
+ "83ecb3f470": "亚搏体育appGitLab API预算",
+ "65b69d9f80": "图ql",
+ "1139f61512": "当前 GitHub CLI REST、搜索和 GraphQL 速率限制。",
+ "ff86e354c4": "GitHub API 预算",
+ "035134fcd9": "工作树",
+ "0c75583ca9": "安全地",
+ "bae91effdd": "新基线",
+ "de06e9d105": "基本参考",
+ "ab0e22c9f6": "刷新本地主",
+ "d9f70d51a0": "陈旧的主要",
+ "0849b571fe": "最新",
+ "c41e345153": "后面主要",
+ "6ee3cfff02": "git 差异",
+ "564942ffc5": "起源/主要",
+ "28192e3a63": "掌握",
+ "e3e9adde59": "主要的",
+ "0e993bf00f": "当您创建工作区时,Orca 会刷新远程库并安全地快进匹配的本地分支,例如 main 或 master。这使得像 git diff main...HEAD 这样的命令无法与过时的历史记录进行比较。如果该分支有未提交的更改或仅限本地提交,Orca 会跳过更新。",
+ "f8bda25f29": "保持本地主要更新",
+ "769ddd7f81": "风俗",
+ "1d2fae1fa2": "git 用户名",
+ "f83c8937c4": "分支命名",
+ "5ecd91c5ef": "创建工作树时添加到分支名称的前缀。",
+ "68bd65fdb8": "分支前缀"
+ }
+ },
+ "input": {
+ "search": {
+ "886597d6b3": "麦科斯",
+ "26c83b06c5": "操作系统",
+ "71905435dd": "x11",
+ "7059cfb00a": "剪贴板",
+ "c4440c3986": "粘贴",
+ "5fb84ba77f": "鼠标中键",
+ "31ba58c8ae": "中键单击",
+ "de51e18ee9": "初选",
+ "e5cd0e7a46": "选择",
+ "e25165320e": "编辑",
+ "b51d47ceb7": "输入",
+ "874d88f4a6": "在 Linux 和 macOS 上默认启用。 Linux使用系统选择剪贴板;其他平台使用私有缓冲区。",
+ "d952ce9b46": "单击鼠标中键从所选内容粘贴"
+ }
+ },
+ "integrations": {
+ "search": {
+ "a626990bd2": "断开",
+ "3c3d3d8ffa": "连接",
+ "faa0b5a0d9": "API密钥",
+ "c450244ad7": "集成",
+ "7319e3015b": "Linear",
+ "16a486a49d": "连接 Linear 以浏览和链接议题。",
+ "b027b4b318": "Linear 集成",
+ "20540996ef": "凭据",
+ "2ec2bd328c": "api token",
+ "7345b7c3e6": "阿特拉斯语",
+ "e1263dd748": "Jira",
+ "76f6af7c57": "连接 Jira Cloud 或更新 Jira API 令牌凭据。",
+ "617603509b": "Jira 集成",
+ "8c568d761c": "拉取请求",
+ "33180e8c10": "自托管",
+ "129fc59aa8": "Gitea",
+ "d0d019dc29": "通过 API 令牌环境变量进行 Gitea 身份验证。",
+ "aab86d64e5": "Gitea 集成",
+ "03a7b275be": "ADO",
+ "ed63380247": "天蓝色存储库",
+ "b38b5d27f1": "天蓝色 devops",
+ "7b1f3984bb": "通过令牌环境变量进行 Azure DevOps Repos 身份验证。",
+ "af6611fa6e": "Azure DevOps 集成",
+ "50d20817f7": "位桶",
+ "c97d58a0f3": "通过 API 令牌环境变量进行 Bitbucket Cloud 身份验证。",
+ "67a2a0e868": "Bitbucket 集成",
+ "371ee914d2": "合并请求",
+ "581844769a": "MR",
+ "b40cbe5de4": "glab",
+ "b939695c69": "GitLab",
+ "6e2ab619c6": "通过 glab CLI 进行 GitLab 身份验证。",
+ "b50b71ef9d": "GitLab 集成",
+ "41ccade05c": "gh",
+ "b79c21bd42": "GitHub",
+ "7166b9090c": "通过 gh CLI 进行 GitHub 身份验证。",
+ "f16e41cc72": "GitHub 集成"
+ }
+ },
+ "jira": {
+ "integration": {
+ "card": {
+ "8ff73fef62": "Jira 令牌由活动运行时加密并存储在本地。重新输入相同的站点 URL 和电子邮件将替换该站点的 API 令牌。",
+ "9046a20d4c": "断开 {{value0}}",
+ "eaffa454e9": "更新",
+ "cec06a0f79": "测试...",
+ "ab350991b8": "已验证",
+ "d914d7ab70": "正在验证...",
+ "5936977fcd": "取消",
+ "1666f8d562": "创建 Atlassian API 令牌",
+ "1ab7f551f3": "Atlassian API 令牌",
+ "09d310e42d": "你@example.com",
+ "27dae4ab60": "https://example.atlassian.net",
+ "a28f417220": "连接 Jira",
+ "9bb34706ca": "已连接",
+ "efaab83c5d": "添加站点",
+ "09742875cd": "Jira",
+ "255bfe98ec": "测试",
+ "5fb1562315": "错误",
+ "3df81cb0ac": "好的",
+ "2e8bb790fd": "连接",
+ "33a8b261ee": "更新凭证",
+ "d5c5b47bb9": "更新",
+ "fb854902d9": "连接",
+ "9a9f8d4910": "连接 Jira Cloud 以浏览、创建和链接议题。",
+ "74f3063026": "{{value0}} 站点{{value1}} 已连接"
+ }
+ }
+ },
+ "mobile": {
+ "emulator": {
+ "search": {
+ "2348045036": "选择 Orca 默认打开的模拟器设备。",
+ "2bb2e09225": "移动技能",
+ "bbe4267416": "模拟器类型",
+ "64494f03c3": "模拟器附加",
+ "6f728f1456": "模拟器抽头",
+ "f8b871d655": "代理客户端",
+ "2e0b45b2ba": "使用 Orca CLI 命令列出、附加、点击和输入移动模拟器。",
+ "ea3eac39bb": "代理 CLI 控制",
+ "8ef0f08d36": "运行时",
+ "27397fe8e9": "xcode 命令行工具",
+ "7650063d17": "模拟控制",
+ "3211e7acf9": "xcrun",
+ "42bfab45d8": "可用性",
+ "ea1f51b980": "检查Xcode、simctl、serve-sim和模拟器设备是否准备就绪。",
+ "0b95dfd5b3": "模拟器可用性",
+ "04c5f5d901": "设备",
+ "25d7bfbcd4": "乌迪德",
+ "ec3c4043fd": "默认ipad",
+ "1dc8c52ffa": "默认 iPhone",
+ "ab4814f3c5": "默认模拟器",
+ "54184cb9c5": "默认模拟器设备",
+ "b8ddd13195": "代理模拟器",
+ "1ad6fb6230": "默认设备",
+ "ac0a985873": "模拟器技能",
+ "9353854ff3": "Orca 模拟器",
+ "d4b7833894": "Orca CLI",
+ "84e5706975": "服务SIM卡",
+ "7c5a8a2bee": "Xcode",
+ "bec7231663": "平板电脑",
+ "49727355a3": "iPhone",
+ "6b6407dc1f": "模拟器",
+ "2d67f708ce": "模拟器",
+ "c5eca29310": "ios模拟器",
+ "25159de808": "移动模拟器",
+ "9595354cff": "配置对 Orca 和编码代理的移动模拟器支持。",
+ "cdd3c31918": "移动模拟器"
+ }
+ },
+ "pane": {
+ "search": {
+ "dbccde3a60": "关闭",
+ "9e16be01d6": "背景",
+ "3a5e31e84b": "离开",
+ "8015fd9523": "抓住",
+ "aa3f736042": "调整大小",
+ "356c31d6dc": "宽度",
+ "fadcbfdd99": "合身",
+ "ad08035c5f": "手机",
+ "6cd2bfdb0e": "恢复",
+ "b34ad5b3a7": "终端",
+ "6db86f445f": "移动端",
+ "707fc78052": "选择关闭应用程序或切换离开后,您在移动设备上查看的终端会发生什么情况。",
+ "1e711aca11": "当您离开移动应用程序时",
+ "126afc5dbd": "偏僻的",
+ "70f505f3c3": "局域网",
+ "1802188b5d": "无线上网",
+ "dd6e671aa9": "地址",
+ "1f70d63998": "ip",
+ "d0c89bc4a9": "覆盖",
+ "87711f4b8f": "VPN",
+ "16bff559a0": "尾网",
+ "c690e3ee38": "尾鳞",
+ "a023683767": "界面",
+ "7b37c2e557": "网络",
+ "3190ef67a4": "选择用于移动配对的网络地址。",
+ "d96c315227": "网络接口",
+ "7d01f93ec0": "已连接",
+ "5e8fda4d7f": "配对的",
+ "905c65a308": "撤销",
+ "82783d9b71": "设备",
+ "13419718b3": "管理配对的移动设备。",
+ "9d3a9397ba": "连接设备",
+ "2128a21096": "扫描",
+ "e518cbd61c": "一对",
+ "4a0c826f3d": "代码",
+ "3c1807a81a": "qr",
+ "7fb728fb2b": "通过扫描二维码来配对移动设备。",
+ "d49925710a": "手机配对"
+ }
+ },
+ "settings": {
+ "search": {
+ "b730ff7049": "实验性",
+ "8d4ba0ef09": "Beta",
+ "6bfa001752": "应用程序",
+ "a7eececc1d": "安卓",
+ "7e801801ac": "偏僻的",
+ "0b7e585cb9": "扫描",
+ "59b1d75fd1": "代码",
+ "87816d1c59": "qr",
+ "cf2c93b479": "一对",
+ "f4ed142753": "手机",
+ "f213400800": "移动端",
+ "671eb4173c": "通过手机控制终端和代理。",
+ "ffd52a96e4": "移动端"
+ }
+ }
+ },
+ "notifications": {
+ "search": {
+ "aa288005c3": "测试",
+ "ca8faa40d7": "通知",
+ "4e30b1925e": "使用本机传递路径触发示例桌面通知。",
+ "ef9b311346": "发送测试通知",
+ "ecdeff4993": "响度",
+ "d58b64dddf": "体积",
+ "dc7d7c07cd": "声音",
+ "eeb6f77322": "非系统通知声音的播放音量。",
+ "aace1a62c6": "通知音量",
+ "ef86a782cc": "邦",
+ "3014ad1b8f": "丁",
+ "079c29aeb5": "弗拉克",
+ "722face52f": "亚克",
+ "6ecb8418cb": "米4a",
+ "d16ae23645": "奥格",
+ "57e34a31cd": "声音",
+ "5362074f19": "mp3",
+ "6e08f78315": "声音的",
+ "c718793e95": "选择 Orca 为桌面通知播放的内置、系统或本地音频文件。",
+ "ea8cb8d9ce": "通知声音",
+ "4ada6bfde9": "过滤",
+ "fa60d8e4ab": "压制",
+ "a4c3b29a3c": "专注的",
+ "7247b97a31": "当 Orca 聚焦于活动工作树时,避免发出通知。",
+ "96562a72c6": "专注时抑制",
+ "a2ab73b325": "注意力",
+ "ae0487f8fd": "钟",
+ "c638ae989d": "终端",
+ "d3f1c48677": "当后台终端发出响铃字符时发出通知。",
+ "a5edee1d99": "航站楼响铃",
+ "193e1f107c": "任务",
+ "dd9d3e5f0f": "idle",
+ "5f7472d3fb": "完全的",
+ "7fa07e9600": "代理",
+ "10d83ef8dc": "当编码代理从工作状态转换为空闲状态时发出通知。",
+ "bdc1edaeb4": "代理任务完成",
+ "adbc3a0fcf": "本国的",
+ "72539aede4": "系统",
+ "51ae2183e1": "桌面",
+ "0534c76311": "Orca 桌面通知的主开关。",
+ "4a210b2f72": "启用通知"
+ }
+ },
+ "orchestration": {
+ "search": {
+ "f5d39af41e": "儿童特工",
+ "c766a01978": "不可触摸",
+ "08c65b12a2": "例子",
+ "f278fd04db": "codex",
+ "32c5098e7b": "claude",
+ "21c28ccdf7": "协调员",
+ "741dfc03fa": "工人",
+ "ca54c69806": "有向无环图",
+ "7ad948b714": "任务",
+ "eee028ae14": "派遣",
+ "9a5ebdca31": "消息传递",
+ "91fc8ab7e5": "协调",
+ "13ba5c6cbd": "代理",
+ "d86705ba77": "多代理",
+ "a7f76b4ca7": "编排",
+ "e05ff36753": "通过消息传递、任务 DAG、调度和决策门来协调多个编码代理。",
+ "c34045764e": "代理编排"
+ }
+ },
+ "privacy": {
+ "search": {
+ "3922051573": "数据",
+ "e8bc614a18": "禁用",
+ "d8191ae5ca": "环境变量",
+ "94e04427f6": "环境",
+ "664f1a8984": "持续集成",
+ "5854a5c752": "词",
+ "69637f4dc4": "orca_telemetry_disabled",
+ "058550f6bc": "不跟踪",
+ "83a6cd79b3": "不跟踪",
+ "f7a2d9f137": "禁用遥测传输的环境变量。",
+ "e058a3c98d": "遥测环境变量",
+ "1686c07fee": "支持",
+ "4a583f3a2f": "开放式遥测",
+ "9ea93ce3d6": "奥特普",
+ "685c68a81f": "日志",
+ "40de3c2f19": "痕迹",
+ "c0494ff48a": "诊断",
+ "8b08f32366": "跟踪文件和 OTLP 导出控制。",
+ "6d258d2ed6": "诊断",
+ "ead1deded2": "分享",
+ "27a27b2f63": "选择退出",
+ "4d4bb76bf4": "选择加入",
+ "b021b9cb81": "匿名的",
+ "79c319948b": "用法",
+ "77d3180def": "遥测",
+ "b707cc3981": "通过发送匿名功能使用事件来帮助改进 Orca。",
+ "57b283461a": "共享匿名使用数据",
+ "2b5a5c312f": "邮差",
+ "4104f6f0f3": "分析",
+ "10124159f1": "隐私",
+ "aa3b794c17": "匿名产品使用数据、诊断和遥测控制。",
+ "5c508bad41": "隐私与遥测"
+ }
+ },
+ "quick": {
+ "commands": {
+ "search": {
+ "3c316e6ef8": "纱",
+ "b86c727100": "新项目管理",
+ "b949a7c0a0": "PNPM",
+ "0b78c4a165": "启动",
+ "2d8aff42be": "跑步",
+ "1c5bdcd0f2": "存储库",
+ "89d2a9ad9f": "回购协议",
+ "f58b92a48f": "项目",
+ "8bf43c2dad": "全球的",
+ "a26ecdb77b": "片段",
+ "d07d130849": "捷径",
+ "0073cf8ce9": "终端",
+ "cfffa6cdb6": "命令",
+ "fecb031823": "命令",
+ "236d4cfac8": "快的",
+ "d691c4e8d8": "保存的终端命令可以从任何终端启动,范围全局或特定项目。",
+ "4c8945952b": "快捷命令"
+ }
+ }
+ },
+ "repository": {
+ "search": {
+ "bc7e504b8e": ".orca/issue-command",
+ "603c68b68c": "Orca.yaml",
+ "9dc60d7f6d": "GitHub",
+ "ec70364df2": "工作流程",
+ "66b584bd6c": "issue 命令",
+ "2011a6a4f2": "GitHub issue 命令",
+ "d42d1e49c0": "通过 orca.yaml 和可选本地覆盖配置的基于文件的关联议题命令。",
+ "d86ea12d16": "自定义 GitHub 议题命令",
+ "c5e8bdbcbb": "默认跳过",
+ "a69c5cbe90": "默认运行",
+ "80c490b012": "问",
+ "f9d84b7971": "设置运行策略",
+ "c00a549e03": "当安装脚本可用时选择默认行为。",
+ "cdfe398068": "何时运行安装程序",
+ "5e9445bbfd": "权威性",
+ "f1e1bfa89f": "来源",
+ "1d90a6cfbb": "两个都",
+ "fcb8fa8144": "共享",
+ "0432d2fb7c": "当地的",
+ "ed269fad69": "命令源",
+ "19f58d6d89": "高级",
+ "d141897c90": "命令源和 orca.yaml 详细信息。",
+ "cc11699c3d": "高级",
+ "bf460fded8": "yaml",
+ "9cad92fe77": "Orca.yaml 挂钩",
+ "6b80f7d3c8": "本地设置脚本",
+ "a1a4c51d58": "归档命令",
+ "fbfd2386e8": "存档脚本",
+ "4c17787d7b": "档案",
+ "8655e3387b": "钩子",
+ "acd1157f0c": "在归档工作树之前运行的本地和共享脚本。",
+ "bce0ca23c6": "存档脚本",
+ "491b05d6e6": "设置命令",
+ "a31b43a7f8": "设置脚本",
+ "5590388dfa": "设置",
+ "baaf70bb37": "创建新工作树后运行的本地和共享脚本。",
+ "b79df26937": "设置脚本",
+ "d73fb47b45": ".claude/mcp.json",
+ "db11b337c4": ".claude.json",
+ "26f42fe773": ".cursor/mcp.json",
+ "e760e3fae7": ".mcp.json",
+ "16dc7a4637": "模型上下文协议",
+ "343f0a508c": "MCP",
+ "3c31801626": "检查项目级 MCP 服务器配置文件。",
+ "31bd0a2420": "MCP 配置",
+ "84da7fa2d7": "节点模块",
+ "0a3a582794": "环境",
+ "3c180a251c": "关联",
+ "f1c53f2820": "工作树",
+ "7e228fc439": "符号链接",
+ "c06adcf136": "符号链接",
+ "ed885e589f": "从主要签出到新创建的工作树的符号链接路径。",
+ "01b3377ebc": "工作树符号链接",
+ "fff8834983": "提示词",
+ "fa3131f223": "模型",
+ "130d76dc16": "重命名",
+ "917dce844a": "分支名称",
+ "8068d8d0f1": "PR",
+ "5ff7fe1ade": "拉取请求",
+ "eec39b3de6": "提交消息",
+ "cfad7ce5f3": "AI",
+ "a47f51127e": "源代码控制",
+ "6cc5c65e64": "项目特定的 git 生成覆盖。",
+ "eec3995dc6": "Git AI Author",
+ "cc876ca5f2": "存储库",
+ "6469de5368": "项目",
+ "3067595d82": "删除",
+ "c86478c3d8": "从 Orca 中删除该项目。",
+ "c5266c2c9d": "删除项目",
+ "4b9a18a56d": "单一仓库",
+ "4e2529722c": "目录",
+ "1ff4f12c0c": "目录",
+ "9f5ae26ccd": "预设",
+ "095fca94fe": "预设",
+ "aa42616e3d": "查看",
+ "4f3c0230c2": "疏",
+ "90a331fd68": "保存用于稀疏工作树创建的目录集。",
+ "1f0f20bbb6": "稀疏结账预设",
+ "4733ec2395": "../worktrees",
+ "58d8bca414": "相对的",
+ "a325a89dff": "工作区路径",
+ "f3e6dee5fe": "工作树路径",
+ "cd33a5525e": "新工作树的项目特定目录。",
+ "443d127b5a": "工作树位置",
+ "9811f3d152": "分支",
+ "f41cef5083": "基本参考",
+ "f571081ec4": "创建工作树时的默认基本分支或引用。",
+ "094adbe930": "默认工作树基础",
+ "27733eb6c1": "图标",
+ "1e73e840ff": "表情符号",
+ "cb4b4de666": "头像",
+ "c1075178cf": "徽章",
+ "6d8de2f090": "十六进制",
+ "8d045419b1": "颜色",
+ "b2546efab5": "存储库图标",
+ "6438a94c63": "项目图标",
+ "a1f3a2bd47": "侧边栏和选项卡中使用的项目图标和颜色。",
+ "b24f00294a": "项目图标",
+ "cd73b976d7": "存储库名称",
+ "92af66c7ce": "项目名称",
+ "883aad2801": "侧边栏和选项卡的项目特定显示详细信息。",
+ "7e1e456a95": "显示名称"
+ }
+ },
+ "runtime": {
+ "environments": {
+ "search": {
+ "772e3b4753": "虚拟机",
+ "45501ff2c3": "云",
+ "2bd988d041": "配对码",
+ "5cd7dca3b8": "偏僻的",
+ "d760866285": "客户",
+ "09568ccc65": "服务器",
+ "ebd5369acf": "环境",
+ "d198440ce3": "运行时",
+ "baec27aa8f": "将此浏览器连接到已保存的 Orca 服务器。",
+ "3517fb2ec0": "活动服务器",
+ "c6e5a03aa0": "开发盒",
+ "f1575f1e09": "网络客户端",
+ "81444c4102": "配对网址",
+ "104f4d7dbd": "配对",
+ "4575341c77": "选择本地桌面、添加已保存的远程 Orca 服务器或生成配对 URL。"
+ }
+ }
+ },
+ "shortcuts": {
+ "search": {
+ "ca6a0c2df7": "捷径",
+ "4811a8264a": "终端优先",
+ "afda131738": "Orca 优先",
+ "0ecfc47434": "冲突",
+ "0f8cb15582": "代理",
+ "f1adebbe8c": "壳",
+ "7f1b38f59a": "推",
+ "7e3fc707aa": "终端",
+ "0ecba9aa5f": "键盘",
+ "ebd7d81e1d": "选择当快捷键重叠时 Orca 或焦点终端是否获胜。",
+ "f052906167": "终端中的快捷键"
+ }
+ },
+ "ssh": {
+ "search": {
+ "d41f296f64": "平",
+ "237b391f7c": "联系",
+ "8cb870b109": "测试",
+ "7efd17e816": "SSH",
+ "96ca5d9a0b": "测试与 SSH 目标的连接。",
+ "a3058f3605": "测试连接",
+ "2cd40ba0d0": "主机",
+ "5220501141": "配置",
+ "3b12e064a4": "导入",
+ "7f251a45a8": "从 ~/.ssh/config 导入主机。",
+ "41a3127094": "从 SSH 配置导入",
+ "f9493b80c0": "服务器",
+ "8fb1cc87cc": "主持人",
+ "09395490af": "目标",
+ "00d1fda01a": "新的",
+ "f7b6383aec": "添加",
+ "62826efbe9": "添加新的远程 SSH 目标。",
+ "f5a691bb6c": "添加 SSH 目标",
+ "d4bcd497c7": "偏僻的",
+ "74c6d90d78": "管理远程 SSH 目标。",
+ "380a788da7": "SSH 连接"
+ }
+ },
+ "tasks": {
+ "search": {
+ "58cda6f9c0": "隐藏",
+ "44083ae418": "展示",
+ "604d8e4089": "阿特拉斯语",
+ "5430396e11": "Jira",
+ "412ec3c702": "Linear",
+ "11f001cdd4": "GitLab",
+ "c10ac2125e": "GitHub",
+ "3d81c26d78": "来源",
+ "cf0e3e0c2f": "提供者",
+ "2ec54bee51": "任务",
+ "765f0c544d": "选择要在“任务”页面和侧边栏快捷键中显示的任务提供商。",
+ "5b8e4aace5": "任务提供者"
+ }
+ },
+ "terminal": {
+ "clipboard": {
+ "search": {
+ "5fb3512e8c": "粘贴",
+ "a38508c419": "复制",
+ "d106f44fb4": "偏僻的",
+ "043b32faa1": "SSH",
+ "9fda309db9": "弗兹夫",
+ "64533e30cc": "尼维姆",
+ "2061d8db1a": "新维姆",
+ "5ffcd13c90": "多路复用器",
+ "10d73e22d3": "剪贴板",
+ "9dfc125cd3": "操作系统52",
+ "62d1208b90": "振荡器52",
+ "459fea094a": "让终端中的程序通过 OSC 52(包括通过 SSH)复制到系统剪贴板。",
+ "74db8721e4": "允许 TUI 剪贴板写入 (OSC 52)",
+ "4043e294d2": "侏儒",
+ "cf83ac3dbd": "操作系统",
+ "737cef6de1": "x11",
+ "e87c6d776d": "自动的",
+ "664789b73a": "自动",
+ "c38c18be15": "选择",
+ "797fdfe4ca": "选择",
+ "603818e8d8": "一旦做出选择,就会自动将终端选择复制到剪贴板。",
+ "3bdc84f059": "选择时复制"
+ }
+ },
+ "search": {
+ "c047f398cc": "启动",
+ "b872de3926": "位置",
+ "fd6c24313d": "新的",
+ "f44643328e": "标签页",
+ "18ce996647": "垂直的",
+ "54a9b3725b": "水平的",
+ "de7bc1d5f5": "拆分",
+ "7a48c7715b": "工作区",
+ "6b659fff2a": "脚本",
+ "4529806908": "设置",
+ "2610ee3b56": "创建新工作区时运行存储库设置脚本的位置:垂直分割(默认)、水平分割或标题为“设置”的背景选项卡。",
+ "5be2d67678": "安装脚本位置",
+ "0ce176909a": "主题",
+ "4ba8623632": "配色",
+ "11fd3fbcf2": "安西",
+ "d8bd6182b8": "覆盖",
+ "674b7c8436": "颜色",
+ "3023e01415": "覆盖各个终端颜色。",
+ "aed2a4b4eb": "颜色覆盖",
+ "6eaf7ee0e4": "光标",
+ "34fe1af39d": "打字",
+ "ee611ae238": "隐藏",
+ "ea364ce6e4": "老鼠",
+ "77201c0bb2": "在终端中输入时隐藏鼠标光标。",
+ "d1fe5f99ff": "打字时隐藏鼠标",
+ "f25d948664": "利润",
+ "b2f52cb96c": "间距",
+ "e8baf0d12c": "填充",
+ "4655567c37": "终端网格周围的垂直填充(以像素为单位)。",
+ "692c4ad032": "垂直内边距",
+ "75691e4911": "终端网格周围的水平填充(以像素为单位)。",
+ "b4f182f24d": "水平填充",
+ "6c2f9f05c8": "活力",
+ "4f7f8f28ca": "透明度",
+ "f6dd9ff606": "背景",
+ "71eb45e293": "模糊",
+ "0838b3717b": "窗户",
+ "bc2054657a": "将背景模糊应用到终端窗口。需要重新启动。",
+ "72d0482137": "窗口模糊",
+ "7db59c4738": "阿尔法",
+ "46d99ef4bb": "不透明度",
+ "4c643695aa": "控制终端背景的透明度。",
+ "b36fd2416d": "背景不透明度",
+ "d4daf4f612": "解冻",
+ "88561b3499": "冷冻的",
+ "0a05629060": "恢复",
+ "f66a7cf715": "终端",
+ "6892fb1019": "重新启动",
+ "cde233f5da": "回滚",
+ "3982d88725": "历史",
+ "456da64d4d": "清除",
+ "920573d65b": "全部结束",
+ "a3e5297c10": "杀",
+ "a8d2784214": "管理",
+ "d802a578bf": "会话",
+ "9f2dda133c": "普蒂",
+ "f35400f7e8": "守护进程",
+ "f72abc493c": "通过终止会话、清除保存的回滚或重新启动守护程序,从冻结的终端中恢复。",
+ "6f5d486a68": "管理会话",
+ "10f9fb6fea": "设置",
+ "2ade3ea490": "配置",
+ "fd752b3cac": "导入",
+ "82b63d07fe": "幽灵般的",
+ "73e9422f19": "一次性导入受支持的 Ghostty 终端设置。",
+ "a979df0083": "从幽灵导入",
+ "4cec42dbf7": "国际",
+ "b495dc6a9f": "吉斯",
+ "d8d6f7a3c5": "麦科斯",
+ "1ab57a0fbd": "苹果",
+ "abaa24752d": "键盘",
+ "24f7977756": "日本人",
+ "98059d0944": "反斜杠",
+ "9c35f56625": "日元",
+ "063914c486": "控制是否按 JIS 日元 (¥) 键发送反斜杠 (\\)。",
+ "694b8764ac": "JIS 日元 (¥) 至 反斜杠 (\\)",
+ "fae142a354": "阅读线",
+ "b3b94cfcb5": "国际的",
+ "dd4f6cb541": "德语",
+ "983d45cf4c": "撰写",
+ "7ace5beec9": "元",
+ "38f1b4f4cb": "钥匙",
+ "c4427dc5ff": "替代",
+ "b37edfc65a": "选项",
+ "1f8b00f5ce": "控制 macOS Option 键是发送 Alt/Esc 序列还是组合字符。反映 Ghostty 的 macos-option-as-alt。",
+ "9bd7229927": "选项作为 Alt",
+ "affb14efd4": "选择",
+ "d2a366c7f9": "双击",
+ "4ed3e239a8": "边界",
+ "d4aeafac10": "分隔符",
+ "7286cd2566": "单词",
+ "3ab64c47d8": "双击选择时将字符视为单词边界。",
+ "957a0203fc": "单词分隔符",
+ "56fff3d113": "记忆",
+ "fffdff40a7": "缓冲",
+ "f7d56b6281": "最大终端回滚缓冲区大小。",
+ "7674e758e1": "回滚大小",
+ "411229c636": "浅色",
+ "781f49d942": "分隔线",
+ "77d9f9cd55": "控制浅色模式下窗格之间的分割分隔线。",
+ "595b97b446": "分光器颜色",
+ "7718d70356": "预览",
+ "1dee533bd9": "选择 Orca 处于浅色模式时使用的主题。",
+ "1d89457764": "浅色主题",
+ "da864e6cec": "灯光模式",
+ "f268092ee3": "禁用后,浅色模式会重用深色终端主题。",
+ "232e532169": "在浅色模式下使用单独的主题",
+ "f785374072": "深色",
+ "9c32726f47": "控制深色模式下窗格之间的分割分隔线。",
+ "8987db7ff2": "深色分隔线颜色",
+ "13f6310dd3": "选择深色模式下使用的终端主题。",
+ "ec07ce9b02": "黑暗主题",
+ "f036794286": "活跃",
+ "846a7a1204": "窗格",
+ "d1fa00a9cb": "徘徊",
+ "b5116e7b12": "如下",
+ "f5d1e3d472": "重点",
+ "17cc3ea102": "将鼠标悬停在终端窗格上即可将其激活,无需单击。反映 Ghostty 的焦点跟随鼠标设置。选择和窗口切换保持安全。",
+ "c6178a2b4d": "焦点跟随鼠标",
+ "f637a7dee9": "厚度",
+ "e58d4040d0": "窗格分隔线的厚度。",
+ "2d5ab88b7c": "分隔板厚度",
+ "6c4c85ba43": "调光",
+ "18dd5026c6": "不透明度应用于当前不活动的窗格。",
+ "72bbcbd1dd": "非活动窗格不透明度",
+ "d4f7d1ce5c": "终端光标的不透明度。",
+ "7f1e356a54": "Cursor不透明度",
+ "25f606d9e5": "眨",
+ "a27f6edf52": "使用所选光标形状的闪烁变体。",
+ "b03d01fd49": "闪烁Cursor",
+ "eefd1d8332": "强调",
+ "015c82349f": "堵塞",
+ "a6e9dcc829": "酒吧",
+ "275a9d6395": "Orca 终端窗格的默认光标外观。",
+ "97bcfff662": "Cursor形状",
+ "1abcf4d7de": "操作系统",
+ "7d924d870d": "图形",
+ "bc7ae1f7c0": "渲染",
+ "fffa9ab980": "渲染器",
+ "6cddc858ba": "网页GL",
+ "4b4e80d850": "加速度",
+ "db82cb13b0": "图形处理器",
+ "8f9f953de7": "控制终端是否使用 xterm.js WebGL 渲染。当渲染器受支持时,自动尝试 WebGL,并为软件或未知 GPU 渲染器提供保守的后备方案。",
+ "13a2502dfc": "GPU加速",
+ "d5e6c7fab1": "字体特性",
+ "a16224d16a": "卡尔特",
+ "6ded6297fe": "约塞夫卡",
+ "e3aeea308e": "卡斯卡迪亚代码",
+ "35c2311a33": "杰布林单声道",
+ "7f7640c29e": "费拉代码",
+ "7ab424c4d3": "结扎",
+ "afc8d5f790": "连字",
+ "103cdb862f": "版式",
+ "893aa92997": "为发布它们的字体渲染编程连字(例如 => → ≠ ≥)。 “自动”仅对已知的连字字体(Fira Code、JetBrains Mono、Cascadia Code、Iosevka 等)启用连字。",
+ "58da1ae45d": "字体连字",
+ "7341e3d00e": "行高",
+ "36a1b38bc8": "控制终端线高度乘数。",
+ "0f2fb0cb74": "行高",
+ "20ce287cc6": "重量",
+ "98c18f2c77": "控制终端文本字体粗细。",
+ "28ea41bd2d": "字体粗细",
+ "b0bb76ae6b": "字体",
+ "0acdc17891": "新窗格和实时更新的默认终端字体系列。",
+ "e989914ad6": "字体家族",
+ "33031c1465": "文字大小",
+ "0fe0073f0c": "新窗格和实时更新的默认终端字体大小。",
+ "5930244899": "字体大小"
+ },
+ "windows": {
+ "search": {
+ "4d09141a42": "上下文菜单",
+ "fcfa53920b": "粘贴",
+ "e55186fe2b": "右键单击",
+ "28ff08ed35": "视窗",
+ "e7d2793b03": "终端",
+ "8ba875c132": "在 Windows 上,右键单击将剪贴板粘贴到终端中。使用 Ctrl+右键单击打开上下文菜单。",
+ "f0b8448570": "右键单击粘贴",
+ "04994f6929": "默认",
+ "fc564eadaf": "德比安",
+ "4ee2579c32": "乌班图",
+ "5074ad8b5f": "发行版",
+ "2b4a340ce0": "分配",
+ "02c772582a": "操作系统",
+ "6e3adf4cba": "wsl",
+ "978457945b": "选择新 WSL 终端和本地代理扫描使用的 WSL 发行版。",
+ "1f402b3651": "WSL分布",
+ "d57f870938": "高级",
+ "4af2f7526e": "版本",
+ "d414022016": "普沃什",
+ "768613e483": "电源壳7",
+ "f9162f0b8e": "窗口 Powershell",
+ "2d99cd91be": "电源外壳",
+ "41a69bc24d": "选择 PowerShell shell 选项是为新终端窗格启动 Windows PowerShell 还是 PowerShell 7+。",
+ "860e0e6402": "PowerShell版本",
+ "07ec155fb6": "bash.exe",
+ "5a2db98d23": "巴什",
+ "591912177b": "gitbash",
+ "12519edb5d": "命令提示符",
+ "6cd20b9e64": "指令",
+ "7c7056940a": "壳",
+ "713c4a2f92": "为 Windows 上的新终端窗格选择默认 shell。",
+ "13715f9d23": "默认外壳"
+ }
+ }
+ },
+ "voice": {
+ "pane": {
+ "search": {
+ "f6e0dfa61c": "云",
+ "2d206de105": "API密钥",
+ "04c25a6fb0": "开放伊",
+ "b9dee49cd7": "下载",
+ "10d45a9fce": "时间",
+ "3d8b853963": "演讲",
+ "080202facb": "模型",
+ "7640ed9848": "语音",
+ "56defcd6c3": "选择用于听写的本地或云语音转文本模型。",
+ "7e62cd7c41": "语音模型",
+ "931b1a9e53": "即按即说",
+ "064a9bd94a": "抓住",
+ "6fa48bcd41": "切换",
+ "d86f5600da": "模式",
+ "089d31a45b": "听写",
+ "748b33e531": "切换或按住说话听写行为。",
+ "6a3abb4338": "听写模式",
+ "e360027a65": "麦克风",
+ "698376a38d": "语音听写功能的主开关。",
+ "20574cbc72": "启用语音听写",
+ "322d457a0d": "转录",
+ "dcc7846641": "配置用于云语音转文本模型的 OpenAI API 密钥。",
+ "ebfd0b32e5": "OpenAI 转录"
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "action": {
+ "recipe": {
+ "options": {
+ "commitMessage": "从分阶段更改生成提交消息。",
+ "pullRequest": "生成托管评论标题和描述。",
+ "branchName": "重命名 Orca 从初始代理任务创建的分支。",
+ "fixCommitFailure": "当提交挂钩或 git 提交失败时启动代理。",
+ "fixChecks": "从失败的托管评审检查中启动代理。",
+ "resolveConflicts": "启动用于解决本地或托管评审合并冲突的代理。"
+ }
+ }
+ }
+ }
+ },
+ "agent-awake-copy": {
+ "e5995ce268": "代理工作时保持电脑唤醒",
+ "95d3031db2": "在代理工作时保持此电脑和显示器唤醒。合盖行为遵循此设备的电源设置。",
+ "a42f6fbdd8": "在代理工作时保持此电脑和显示器唤醒。Orca 还会根据电源策略,在合盖时请求此设备保持唤醒。"
+ },
+ "agent-status-hooks-copy": {
+ "7707c15abb": "代理状态钩子",
+ "a68a642835": "在 Orca 中显示工作中、等待中和完成状态。关闭后将移除 Orca 管理的钩子并停止重新安装。"
+ },
+ "agent-generated-tab-title-copy": {
+ "19ad21615a": "自动生成标签页标题",
+ "b036c7a409": "根据第一个已知代理提示词生成简短稳定的标签页名称。手动重命名始终优先。"
+ }
+ },
+ "right": {
+ "sidebar": {
+ "BulkActionBar": {
+ "79a9f5f712": "取消暂存(",
+ "ef5f5bd06e": "阶段 (",
+ "60ed678138": "已选择"
+ },
+ "ChecksPanel": {
+ "2ef90c9819": "已启动 AI 代理处理失败的检查。",
+ "a0181a8d76": "已启动 AI 代理处理冲突。",
+ "34464d00b9": "已更新",
+ "058039787c": "取消",
+ "2ab7fd4b6d": "保存",
+ "dda5924a40": "检查需要 Git 分支和托管评审上下文",
+ "976cefd02f": "检查不可用",
+ "b5dd73a105": "选择一个工作区以查看检查",
+ "a4ef4e0832": "未选择工作区",
+ "5594400d73": "没有需要修复的失败检查。",
+ "abf59262fb": "在启动代理之前查看并编辑完整的命令输入。",
+ "4ede779461": "使用 AI 解决评审冲突",
+ "3b203c62f8": "这将从 PR 中永久删除该评论。",
+ "ea9b649ce3": "删除评论?",
+ "5788d1059d": "无法更新评论主题。检查 GitHub API 预算。",
+ "07871c0589": "链接另一个 PR",
+ "7202f4a40a": "取消PR链接",
+ "7f4489f370": "刷新",
+ "5c88c6db07": "打开于 {{value0}}",
+ "7fad8509fe": "用 AI 修复",
+ "71026ca2cb": "刷新中…",
+ "889cdfba04": "创建 {{value0}}",
+ "98f4c37b33": "推送并创建 {{value0}}",
+ "6633c7a1fb": "发布分支",
+ "fdb27637f2": "出版…",
+ "e56c42122e": "destructive",
+ "786e3c143f": "删除",
+ "653c105ecc": "更多 PR 操作"
+ },
+ "CreatePullRequestDialog": {
+ "2bc1b4345e": "取消",
+ "27ef4b195c": "在创建之前选择不同的基础分支",
+ "7ef56f3efe": "创建为草稿",
+ "0c9f9a568c": "支持 Markdown 格式。使用 AI 生成来自动填充您的更改。",
+ "02b2ce911f": "说明(可选)",
+ "1cd53359db": "描述",
+ "68314b4369": "标题",
+ "694550a610": "主要的",
+ "0fad57a14c": "搜索远程分支或输入分支名称。",
+ "8584ccb43c": "基础分支",
+ "6f5f1962b6": "源分支",
+ "b504b3ceb1": "创建托管评论之前的详细信息。",
+ "f658ff2455": "确认目标分支并",
+ "b7f43474d7": "创建 {{value0}}",
+ "7a21f0dae8": "打开于 {{value0}}",
+ "edc35a7027": "{{value0}} #{{value1}} 已开放",
+ "a154fe55e6": "推送并创建 {{value0}}"
+ },
+ "CreatePullRequestGenerateButton": {
+ "4012459f8a": "用 AI 生成",
+ "a0501572c1": "使用 AI 生成 {{value0}} 详细信息",
+ "d47fd63012": "细节。单击停止。",
+ "f5513bdeb1": "生成",
+ "a6ea6dc3aa": "生成…",
+ "e041998cad": "停止生成"
+ },
+ "FileExplorer": {
+ "79b1537dd3": "选择一个工作区来浏览文件"
+ },
+ "FileExplorerBackgroundMenu": {
+ "3b5e2dcb8d": "新建文件夹",
+ "21fe46ed36": "新文件"
+ },
+ "FileExplorerRow": {
+ "addc01145f": "删除",
+ "fc747429bf": "重命名",
+ "0df0e5abac": "在文件夹中查找",
+ "d6a25618aa": "折叠文件夹",
+ "d87a4c42e1": "打开 Markdown 预览",
+ "c2112579f6": "下载",
+ "dd112c81d2": "在 Orca 浏览器中打开",
+ "1bb9be455c": "添加为项目...",
+ "0fec99bfd7": "复制",
+ "f61af83316": "新建文件夹",
+ "37c875d827": "新文件",
+ "b3e288bf41": "无法下载“{{value0}}”。",
+ "1a3df04ae1": "进行中",
+ "bce4d4e44f": "下载“{{value0}}”",
+ "e26010014a": "被 .gitignore 忽略",
+ "a06551beee": "进入",
+ "128a99ed5e": "未分配",
+ "2de3b21934": "降价",
+ "66a29dde82": "复制相对路径",
+ "42e10cbf57": "复制相对路径",
+ "b5d436aa30": "复制路径",
+ "f9d7ca753d": "复制路径",
+ "3161c4e425": "文件夹"
+ },
+ "FileExplorerToolbar": {
+ "d238264654": "显示 Git 忽略的文件",
+ "78f133232c": "显示点文件",
+ "31b4c3195d": "更多资源管理器操作",
+ "d95e30fe28": "刷新资源管理器",
+ "6026b16950": "全部折叠"
+ },
+ "FileExplorerTreeStatus": {
+ "ce03835e1f": "此工作区中没有文件",
+ "c76693e456": "无法加载此工作区的文件:"
+ },
+ "GitHistoryPanel": {
+ "cf7cad58d2": "还没有提交",
+ "781a8bcf7b": "正在加载图表...",
+ "d0fb0f4bf2": "刷新提交",
+ "9f7535d22b": "引用是指向该确切提交的分支或标记名称。它们仅出现在 Git 具有提交的命名引用的地方。",
+ "9289ba0cb9": "什么是参考文献?",
+ "d836037d02": "提交",
+ "8232c8b2f2": "打开提交 {{value0}}: {{value1}}",
+ "9a8b85882d": "加载中",
+ "62e685d5ec": "idle",
+ "111e1d0db4": "错误",
+ "e5e81e59a6": "调整提交大小"
+ },
+ "HostedReviewActions": {
+ "4d5fb5a284": "关闭",
+ "9845a71e17": "更多操作",
+ "2bfaf4379c": "更多 {{value0}} 操作",
+ "377269db6f": "{{value0}} 重新打开",
+ "fa3ee9a515": "关闭",
+ "78f5ff294c": "这将重新打开 {{value0}}。",
+ "a3d572a4de": "这将关闭 {{value0}}。",
+ "e4aca40024": "删除工作区",
+ "eefd50457e": "正在删除...",
+ "3ce211ece6": "重新打开 {{value0}}",
+ "6645ac7dd1": "重新打开...",
+ "b25f63edd7": "打开",
+ "d2ca293f3d": "处理中...",
+ "ef064cb7c3": "默认",
+ "59b4dccf70": "destructive"
+ },
+ "PortsPanel": {
+ "3ea4a02a8f": "取消",
+ "4eb801ce93": "开发服务器",
+ "8dfed0a15c": "标签(可选)",
+ "17bea6e391": "本地主机",
+ "a3721a50b0": "远程主机",
+ "d57545ff92": "与远程相同",
+ "b950b1948b": "本地端口",
+ "9e5a4118b0": "远程端口",
+ "c9d106547a": "向前",
+ "c7e920aa7c": "显示为",
+ "e740075063": "移除",
+ "b3548e59f4": "编辑",
+ "fe2730d050": "复制 {{value0}}",
+ "b22b128b2a": "在浏览器中打开",
+ "75aeea592f": "在浏览器中打开 {{value0}}",
+ "de349d4560": "打开",
+ "907eb53ed2": "转发端口",
+ "04efd3dad4": "转发端口以访问本地计算机上的远程服务。",
+ "1f0d2a24f9": "无转发端口",
+ "36b1b2984a": "已检测",
+ "ddbe58d74e": "转发",
+ "a103dae837": "添加",
+ "6bc058dbe1": "端口",
+ "d4c3cd679c": "正在重新连接...",
+ "a2f1a47f42": "SSH 连接丢失",
+ "409afcc145": "没有为浏览器选择工作区。",
+ "153145e675": "证据",
+ "c7b4702b7b": "工作区",
+ "57d930fa45": "PID",
+ "5dd86dcf2f": "过程",
+ "b1ff94fa27": "协议",
+ "729be0b4e5": "种类",
+ "0f1d8cd324": "绑定",
+ "1c1c18cefc": "地址",
+ "f9528da632": "停止进程",
+ "a223459512": "显示详情",
+ "bdac206faf": "复制详情",
+ "792baeb7ed": "复制地址",
+ "d41a8241ec": "端口",
+ "a2a9fc6899": "未检测到本地端口",
+ "f59c783b7a": "端口扫描不可用",
+ "7822e3edc6": "刷新端口",
+ "c1b115c375": "未选择工作区",
+ "98e9a414f8": "无法打开浏览器",
+ "a00f3a2840": "刷新端口失败",
+ "97b562d21d": "已停止进程:{{value0}}",
+ "9079776663": "保存",
+ "c57eda6822": "编辑",
+ "9f475dc994": "转发...",
+ "d7c83cfd24": "保存中...",
+ "31e80cff2d": "将远程端口转发到本地计算机。",
+ "10360598a4": "更新端口转发配置。",
+ "80206251c8": "编辑端口转发",
+ "4bc9b00912": "工作区",
+ "3e13cb63ee": "未知",
+ "472054d94c": "端口:{{value0}}",
+ "1119f90ad7": "容器",
+ "d32820d3e2": "外部的",
+ "4db4b5e435": "其他工作区",
+ "38b16cfbef": "未检测到端口",
+ "0d63d94db3": "扫描...",
+ "935dda7718": "活跃的工作区",
+ "740aca88ab": "工作区端口扫描失败。"
+ },
+ "Search": {
+ "1abfb25a66": "输入要在文件中搜索的内容",
+ "d56d140747": "按 Enter 进行搜索",
+ "0b8104eaf2": "文件",
+ "4107975b3a": "在",
+ "6aeda362ed": "结果",
+ "98c8435e36": "选择要搜索的工作区",
+ "1ec640c9c7": "匹配",
+ "dcc294f28d": "(结果被截断)"
+ },
+ "SearchFilters": {
+ "01e4671ccf": "要排除的文件(例如 *.min.js、dist/**)",
+ "0a6412a895": "要排除的文件",
+ "8a77efcbd1": "要包含的文件(例如 *.ts、src/**)",
+ "a69ee1bd0e": "要包含的文件"
+ },
+ "SearchHeader": {
+ "6234a5ef85": "使用正则表达式",
+ "4567e6e0b6": "匹配整个单词",
+ "464ae3974f": "火柴盒",
+ "693cbeadd0": "搜索"
+ },
+ "SearchResultItems": {
+ "cc06595a3b": "复制线路径",
+ "3596b9668d": "复制路径"
+ },
+ "SourceControl": {
+ "1406954883": "清除所有笔记...",
+ "cc05b2d088": "在文件资源管理器中打开",
+ "03194cfff4": "本地会话状态源自您在此处打开的冲突。",
+ "413a3ba113": "冲突",
+ "27a50fe970": "评审冲突",
+ "f6cb48b6fe": "用AI解决",
+ "3eeccbb221": "已解决的文件在离开实时冲突状态后会恢复正常更改。",
+ "c321542ee2": "删除第 {{value0}} 行的注释",
+ "b656381c18": "删除注释",
+ "c085946bda": "复制行 {{value0}} 上的注释",
+ "1623bf4e19": "复制备注",
+ "655633c08a": "发送",
+ "3eb9b2805e": "打开 {{value0}} 上的注释",
+ "0d963bf982": "打开{{value0}}",
+ "59654650d3": "清除 {{value0}} 的注释",
+ "ac8cbe3bf5": "将鼠标悬停在差异视图中的一行上,然后单击 + 添加注释。",
+ "286dbda4d6": "重试",
+ "476b77745b": "更改基础参考",
+ "ed34038d0d": "刷新分支比较",
+ "493f963029": "更改基本参考",
+ "3278b2767b": "前面",
+ "11b5dd8e41": "比较",
+ "783a808870": "关闭",
+ "a9bf7c171a": "提交失败",
+ "03d238218c": "细节",
+ "011f9713fc": "提交被阻止",
+ "cc199ccc5f": "更多提交和远程操作",
+ "4d6e1fd7f3": "更多操作",
+ "37a81f29ad": "生成提交消息。单击停止。",
+ "b94112eb9e": "提交消息",
+ "0d0a8359d3": "信息",
+ "15b7f210d7": "选择代理并在启动前编辑完整的命令输入。",
+ "054ead86b1": "使用 AI 修复提交失败",
+ "9e5ccd00aa": "提交失败上下文不可用",
+ "f0a2dc9e46": "自定义启动...",
+ "ec7bfced55": "选择代理来修复提交失败",
+ "dd43c47089": "选择针对此提交失败的代理",
+ "30b8d4f181": "使用 AI 修复提交失败",
+ "4b37ae99b0": "启动默认的AI代理来修复此提交失败",
+ "ae743199cd": "在创建之前选择不同的基础分支",
+ "c5e4175139": "更多 {{value0}} 和远程操作",
+ "78ddfd0bb4": "创建为草稿",
+ "e64a632456": "主要的",
+ "6055949c50": "{{value0}} 基础分支",
+ "1f7119f604": "根据",
+ "9484270f45": "正在生成标题和描述...",
+ "a0dc20fc93": "说明(可选)",
+ "a8873e1d62": "{{value0}} 描述",
+ "7d6a8f0082": "标题",
+ "a6eda33521": "{{value0}} 标题",
+ "02d8c04339": "使用 AI 生成 {{value0}} 详细信息",
+ "e868cec4e1": "生成…",
+ "527e130b6f": "停止生成",
+ "e1970d327d": "新建",
+ "f4c766f1ca": "为此运行选择代理和命令模板。",
+ "1a6a6e0bc5": "生成托管评论详细信息",
+ "6b122529d4": "生成提交消息",
+ "e48caaf0dd": "已启动 AI 代理处理冲突。",
+ "901140f47d": "在启动代理之前查看并编辑完整的命令输入。",
+ "19652ddd76": "用 AI 解决冲突",
+ "c9ad22888e": "选择此存储库的分支比较目标。",
+ "574d2f4413": "清晰的笔记",
+ "05bb8f4a48": "取消",
+ "48db37cca9": "查看全部",
+ "78ce2d37ac": "推送到 fork",
+ "c05fe04839": "推送到 {{value0}} 的 fork(非 origin)",
+ "c35baf2f1e": "过滤文件...",
+ "2fe2a67580": "更多笔记动作",
+ "eae2d051af": "复制所有笔记",
+ "cc474e0b8c": "笔记",
+ "e131cd7128": "源代码管理仅适用于 Git 存储库",
+ "c07b236287": "选择一个工作区以查看更改",
+ "dc5a6465fc": "{{value0}}(例如 {{value1}}{{value2}})",
+ "8eb3782a0c": "无法丢弃 {{value0}} 文件{{value1}}",
+ "a5e5a11090": "放弃所有失败 - 无法在放弃之前取消暂存文件",
+ "8a5ba6a988": "无法加载提交差异",
+ "fe5bd1a610": "创建 {{value0}}...",
+ "812cb992ee": "打开于 {{value0}}",
+ "eef5446523": "{{value0}} #{{value1}} 已开放",
+ "0453ca3a9a": "{{value0}} 已创建,但 Orca 尚无法刷新它。",
+ "f99560ab29": "中止 {{value0}} 失败",
+ "eae7a1da5f": "无法清除笔记。",
+ "657e0c90ad": "{{value0}} 注{{value1}}",
+ "df5040e3c3": "取消舞台",
+ "8cde1a2fb0": "阶段",
+ "d54dd48b0b": "放弃更改",
+ "989f3d5e34": "恢复文件",
+ "2830dd64a2": "已删除",
+ "11463f7a98": "删除未跟踪的文件",
+ "d62bc0c7d8": "未追踪的",
+ "ab31221779": "取消暂存文件夹",
+ "bfe9011a0e": "舞台文件夹",
+ "6d7f2a47e5": "丢弃文件夹",
+ "9b367363b6": "删除文件夹中未跟踪的内容",
+ "540ca8f78c": "中止合并",
+ "425f138269": "中止变基",
+ "04832d8047": "变基",
+ "c105a61960": "合并",
+ "d7a5942e41": "{{value0}}:{{value1}} 未解决",
+ "c56ba7fa06": "差异",
+ "94c42b252e": "医学博士",
+ "e59bca888a": "降价",
+ "b6922abb13": "无法加载分支比较。",
+ "715d229c86": "分支比较不可用",
+ "97d8b03cdf": "分支比较失败",
+ "424ee0e5bf": "错误",
+ "834cb3f23d": "用 AI 修复",
+ "60bd988f0b": "AI 修复",
+ "461575b9bc": "使用 AI 生成提交消息",
+ "ddc1fbd690": "停止生成提交消息",
+ "5acbcedc1a": "创建 {{value0}}",
+ "aaf1451654": "创建草稿 {{value0}}",
+ "26511c22b4": "创建中...",
+ "7a09d7f9d2": "根据",
+ "383cf92c73": "树",
+ "d7ae61269b": "致力于分支",
+ "3636d0f686": "就绪",
+ "d2e9189866": "全部",
+ "a0cc0e6b4e": "加载中",
+ "9339382454": "全部取消暂存",
+ "24d2598eff": "舞台全部",
+ "ce41708855": "全部丢弃",
+ "2f609a2e7c": "删除所有未跟踪的",
+ "9bb062a886": "未提交",
+ "9febd8ab5f": "创建_pr",
+ "f62ce91ade": "起源",
+ "3a231c845b": "未知",
+ "3baf6c77b4": "将所有笔记复制到剪贴板",
+ "72f2bea3f4": "展开注释",
+ "d13edef890": "折叠笔记",
+ "0fad573938": "未提交",
+ "77afaa8152": "全部"
+ },
+ "SourceControlAgentActionDialog": {
+ "8e856842d1": "无法启动选定的代理。",
+ "c075d00de1": "无法解析工作区连接。",
+ "808cfe0a3b": "仅保存到此存储库",
+ "994cddd1f7": "不保存"
+ },
+ "SourceControlAgentActionDialogForm": {
+ "1bc0bdbb5e": "启动:",
+ "f84657c925": "保存启动配方",
+ "7ec6abbf2a": "重置",
+ "f4f3c9ca4a": "命令模板",
+ "fe119187bb": "——模范十四行诗",
+ "bc8dc39f4b": "CLI 参数",
+ "b99c33cec5": "设置",
+ "15c5d85706": "代理",
+ "3e8f21954f": "错误",
+ "74168d7ada": "idle",
+ "1d47db9bf0": "没有启用代理",
+ "c7ff8cef11": "检测剂..."
+ },
+ "SourceControlTextGenerationDialog": {
+ "c5b7fa7cb6": "保存为全局默认值",
+ "7f1ec309a4": "保存为所有存储库的默认值",
+ "5959da1e4d": "仅保存到此存储库",
+ "d054d5e0a0": "设置未加载。"
+ },
+ "SourceControlTextGenerationDialogForm": {
+ "25fcd8e49a": "保存默认值",
+ "d91b0a189d": "保存食谱",
+ "1f6fcfb6cf": "命令模板",
+ "551ffd111b": "——模范十四行诗",
+ "4eab815004": "CLI 参数",
+ "914c8f6ac2": "自定义命令",
+ "cce2cbd01d": "选择代理",
+ "9c14186dd2": "代理"
+ },
+ "activity": {
+ "bar": {
+ "buttons": {
+ "1fd284e931": "更多侧边栏选项卡",
+ "f1132ea95d": "Neutral"
+ }
+ }
+ },
+ "checks": {
+ "panel": {
+ "content": {
+ "3916814392": "落后(基本提交:",
+ "755be805f6": "暂无评论",
+ "751f7c6e5c": "显示每个来源的前 100 条评论",
+ "94557d68e2": "评论",
+ "3fff651d32": "添加PR评论",
+ "ea9fd5ed6a": "开始对话...",
+ "0fc6f743b3": "由",
+ "8987d5a3dd": "已解决",
+ "ba20d1a896": "回复{{value0}}",
+ "f6a40263ff": "保存",
+ "b062f55f29": "取消",
+ "c1f6fc006a": "回复",
+ "2ba0a32bdd": "机器人",
+ "6cc6eace26": "删除",
+ "03ca88f623": "编辑",
+ "d3923d18fe": "前往评论",
+ "1abb17aac9": "更多的",
+ "74c6885b8a": "更多评论动作",
+ "cbcc4ab3db": "显示前 100 项检查",
+ "0dca6bfab5": "打开检查详细信息",
+ "991f50c7e4": "未配置检查",
+ "9ad98f2a17": "待办的",
+ "5e52f4ef7f": "失败",
+ "02ca4f9074": "通过",
+ "e15a8b77ef": "此检查没有可用的内联详细信息。",
+ "679bf2093c": "复制日志尾部",
+ "d713f500b2": "日志尾部(最后 200 行)",
+ "a916648574": "打开详情",
+ "07eccfa397": "没有关于此检查的详细信息。",
+ "49731703ea": "任务",
+ "f2fe8a4e8f": "注释",
+ "d098e5529a": "输出",
+ "2dd5ddabc4": "工作流程#",
+ "aa8494ae3c": "检查 #",
+ "00e1c1658a": "已完成",
+ "fd46a70f1a": "开始",
+ "a54ae21c6f": "状态:",
+ "e4e3af15ee": "查看完整详细信息",
+ "2524d1fb83": "日志尾部提供完整详细信息。",
+ "a2fb3f4408": "显示前 100 个职位",
+ "df137989b3": "显示前 20 个注释",
+ "1f2b980522": "正在加载检查详细信息...",
+ "0c96cd25e5": "解决",
+ "3a71a6ed0b": "在检查和合并完成之前解决冲突。",
+ "60186d8498": "冲突阻碍了这一点",
+ "c16762ac8c": "下面的检查和注释显示当前获取的上下文。",
+ "9d0e7bcefc": "没有阻塞 PR 操作",
+ "5856874b59": "当该面板保持打开状态时,Orca 将刷新检查。",
+ "5341023167": "查看",
+ "b45db92d0e": "使固定",
+ "5d4ebf9391": "检查详细信息或启动 AI 修复过程。",
+ "b652f38caf": "检查失败",
+ "87cd07c69a": "该分支存在必须解决的冲突",
+ "0975eeaaef": "冲突的文件",
+ "6fa7f8723f": "犯罪",
+ "2b2be92919": "添加评论",
+ "7440d09d2c": "开始对话",
+ "b37ebdc51c": "无法发表评论。",
+ "90206b6353": "评论",
+ "95ad090b01": "帖子串",
+ "365254cc1b": "未解决",
+ "7f793b571d": "拖动以调整检查面板大小",
+ "ee07b33924": "未知",
+ "cdbfda4dec": "批注",
+ "066fedd446": "失败的工作",
+ "ae8a04ef17": "冲突文件详细信息不可用",
+ "73d0675356": "刷新冲突细节..."
+ },
+ "empty": {
+ "state": {
+ "5b0cfae9a5": "创建 {{value0}} 以开始检查和评审。",
+ "13e1c7d5ed": "未找到 {{value0}}",
+ "d372072df1": "GitHub 刷新因当前速率限制预算而暂停",
+ "7c299df37b": "未找到拉取请求",
+ "3d4af82ff4": "正在刷新此分支的 GitHub 状态",
+ "938b5606a6": "检查拉取请求",
+ "6ba2440770": "正在等待刷新此分支的 GitHub 状态",
+ "2bdd7aaf2d": "GitHub 状态无法刷新。现有的缓存数据被保留。",
+ "5f478ab3d3": "无法刷新拉取请求",
+ "6ce9d4e069": "在创建 {{value0}} 之前推送您的分支。",
+ "76e15946a9": "分支有未推送的提交",
+ "f8543140cc": "在创建 {{value0}} 之前发布此分支。",
+ "41252bc53f": "分支未发布",
+ "05e4aec17b": "{{value0}} 检查将在操作完成后可用",
+ "d77c513c1e": "{{value0}} 正在进行中"
+ }
+ }
+ }
+ },
+ "gitlab": {
+ "mr": {
+ "merge": {
+ "state": {
+ "04a3015a12": "可以合并",
+ "53c6d3b7e9": "GitLab 表示该 MR 可以合并,但管道仍在运行",
+ "65c847ad1e": "检查待处理",
+ "b41fbc180c": "GitLab 表示这个 MR 可以合并,但一些管道作业失败了",
+ "49ac4fec10": "检查失败",
+ "22b7e50621": "GitLab 报告合并冲突",
+ "96b05e374c": "冲突",
+ "d63bb6f76e": "此合并请求仍是草稿",
+ "b2715092c6": "草稿",
+ "2388413f28": "此合并请求已关闭",
+ "88d044c42f": "已关闭",
+ "ee482a2bad": "该合并请求已被合并",
+ "fae95ae20d": "合并"
+ }
+ }
+ }
+ },
+ "index": {
+ "70893f017b": "边",
+ "7b415c39e9": "顶部",
+ "864111caa2": "活动栏位置",
+ "e8e2e4ce74": "切换右侧边栏",
+ "441733b630": "端口",
+ "83a10e3c44": "检查项",
+ "0314901467": "源代码控制",
+ "06219e4cb1": "搜索",
+ "8bc2bbc3a0": "探险家",
+ "45b78f03bc": "边",
+ "34af8aadf5": "顶部",
+ "9fffaf17c1": "切换右侧边栏 ({{value0}})",
+ "b37ff4a89a": "端口",
+ "9f83375839": "检查",
+ "6306b48afd": "源代码控制",
+ "ef182dcb12": "搜索",
+ "fc3095d2ed": "探险家"
+ },
+ "right": {
+ "panel": {
+ "comment": {
+ "composer": {
+ "9bca633dee": "取消",
+ "cf5a7aba6f": "列表",
+ "d6d9c3c947": "引用",
+ "f49e0a21e0": "代码",
+ "542bf6a7e2": "斜体",
+ "256300f8ea": "大胆的",
+ "87aff03d63": "正在发送..."
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "ai": {
+ "commit": {
+ "failure": {
+ "launch": {
+ "a8b97d2318": "针对提交失败启动了 AI 代理。",
+ "5540ff50cc": "无法构建代理启动命令。",
+ "9bbd9077a2": "没有启用的 AI 代理。在“设置”中配置代理。",
+ "d481ab22f9": "已保存的 AI 代理不可用。使用自定义启动来选择另一个代理。",
+ "f2b47026e8": "提交失败提示为空。更新源代码管理 AI 设置。",
+ "4f4e0418a0": "无法构建代理提示符。",
+ "216f762bd7": "无法解析工作区连接。"
+ }
+ }
+ }
+ },
+ "discard": {
+ "confirmation": {
+ "2ae5a785b3": "放弃所有未暂存的更改?",
+ "ddf36f291c": "这将取消暂存并恢复所有已暂存的更改。暂存的新文件将被删除。此操作无法撤销。",
+ "5ddd8cac7f": "放弃所有分阶段的更改?",
+ "1426c2efff": "这将恢复对此文件的所有更改。此操作无法撤销。",
+ "d4df3a61df": "放弃对“{{value0}}”的更改?",
+ "40e9357b2a": "这将从 HEAD 恢复文件并放弃删除。此操作无法撤销。",
+ "5c0bdbc4cb": "恢复“{{value0}}”?",
+ "d97bf697c9": "这将永久删除该文件。此操作无法撤销。",
+ "96c772bee9": "删除“{{value0}}”?"
+ },
+ "dialog": {
+ "3bc61dc989": "取消",
+ "15efa778e3": "放弃",
+ "6de99d162b": "入口",
+ "42f89dd030": "文件",
+ "e7611dca35": "文件",
+ "48c5ef95d9": "区域",
+ "0d2d88cba5": "此操作无法撤销。",
+ "1551c14668": "放弃更改?"
+ }
+ },
+ "dropdown": {
+ "items": {
+ "7aad2c0240": "托管评审操作进行中…",
+ "9e779995dd": "创建 {{value0}}",
+ "226b85a3a7": "拿来",
+ "323bb614aa": "提交并同步",
+ "2b8e6595fd": "犯罪"
+ }
+ },
+ "primary": {
+ "action": {
+ "ed93b4f14f": "犯罪",
+ "946a8a05ea": "为此分支创建 {{value0}}",
+ "e7ffa46946": "创建 {{value0}}",
+ "95550cff15": "推",
+ "d64292a938": "拉",
+ "795f1509c5": "同步",
+ "390abeab93": "强力推",
+ "1884cf34af": "将此分支发布到 origin",
+ "7b4d02e6b8": "发布分支",
+ "3d5dccef0b": "没有可提交的内容。PR 已合并。",
+ "41d4bcf157": "检查 PR 状态...",
+ "acce237921": "没有可提交的内容。分支没有可发布的更改。",
+ "fa3bd4f40c": "暂存至少一个要提交的文件",
+ "5a477d80cb": "暂存所有更改",
+ "18a0fca877": "舞台全部",
+ "f01f16d77f": "输入提交消息以提交",
+ "ab41fb926b": "提交分阶段更改",
+ "2d8f185fbc": "在提交部分暂存的文件之前暂存所有更改",
+ "a6457b46a7": "提交前解决冲突",
+ "484f45c439": "{{value0}} 正在进行中...",
+ "74fc171e99": "强制推送正在进行中...",
+ "16aee3a5c1": "正在进行中……"
+ }
+ }
+ }
+ },
+ "use": {
+ "source": {
+ "control": {
+ "ai": {
+ "cfafa92509": "没有未解决的冲突需要发送。"
+ }
+ }
+ }
+ },
+ "useFileDeletion": {
+ "72691dfebc": "无法 {{value0}}“{{value1}}”。",
+ "96affe1302": "“{{value0}}”已移至 {{value1}}",
+ "74727df633": "“{{value0}}”已删除",
+ "d979a4fbb5": "永久删除“{{value0}}”?",
+ "a76c74f105": "destructive",
+ "92276aceb7": "删除"
+ },
+ "useFileExplorerHandlers": {
+ "32cd9fd991": "无法打开符号链接目标"
+ },
+ "useFileExplorerImport": {
+ "25919b2050": "跳过 {{value0}} {{value1}}。",
+ "132fd0e1e9": "无法导入 {{value0}} {{value1}}。"
+ },
+ "useFileExplorerKeys": {
+ "8adb953095": "操作失败"
+ },
+ "GitHistoryGraphSvg": {
+ "47eff48230": "头"
+ }
+ }
+ },
+ "repo": {
+ "NestedRepoChecklist": {
+ "f7e1170567": "已选择",
+ "ea54c7bf8f": "的",
+ "91b5bcadb6": "选择全部",
+ "929734aea5": "取消全选"
+ },
+ "NestedRepoScanLimitNotice": {
+ "642a43c139": "嵌套存储库扫描限制",
+ "574eb5408b": "显示部分扫描结果。",
+ "03e9beab7b": "扫描提前停止。"
+ },
+ "RepoCombobox": {
+ "b3e15f4525": "添加项目",
+ "b4a235e886": "添加项目",
+ "3639fd9da2": "SSH",
+ "e7ed739236": "没有项目/文件夹与您的搜索匹配。",
+ "a0c48f5f29": "搜索项目/文件夹...",
+ "116812151a": "添加项目..."
+ },
+ "repo": {
+ "icon": {
+ "0ad395d475": "盒子",
+ "857977b901": "形状",
+ "b1b8d99fc4": "AI",
+ "137bdb1856": "指标",
+ "d202c659a3": "设计",
+ "c4fd14299d": "公司",
+ "4ab9433660": "工作",
+ "febfbe0cd5": "工具",
+ "ecf63ec3ef": "启动",
+ "31826b712e": "API",
+ "70bef15d40": "层数",
+ "b5fac337aa": "计算",
+ "d37b4e2641": "服务器",
+ "3c5a593bc8": "网络",
+ "477b28c948": "数据库",
+ "787490e9bd": "包裹",
+ "07012dc113": "代理",
+ "3eba7387ab": "终端",
+ "65b437c381": "代码",
+ "bed2674f9d": "文件夹"
+ }
+ }
+ },
+ "pet": {
+ "pet": {
+ "models": {
+ "7433516faf": "格雷姆林",
+ "a84d5677ff": "OpenCode",
+ "2528586aa7": "克劳迪诺"
+ }
+ },
+ "PetOverlay": {
+ "de932b0e8f": "@keyframes pet-bob { 0%,100% { 变换:translateY(0); } 50% { 变换:translateY(-4px); } }",
+ "4712d196c6": "@keyframes pet-{{value0}} { from { 背景位置:{{value1}}px {{value2}}px; } 到 { 背景位置:{{value3}}px {{value4}}px; } }"
+ }
+ },
+ "onboarding": {
+ "AgentStep": {
+ "e6a369bd04": "热门代理",
+ "d7b3ef168b": "在系统中已检测",
+ "9c163bb0e0": "安装说明",
+ "69af7e9c1c": "尚未加入 PATH。Orca 会将其设为默认,你可随时安装。",
+ "1eee1c7bd8": "PATH 中未检测到代理。可选择一个稍后安装,或使用空白终端继续。",
+ "hideAgents": "隐藏代理",
+ "showMoreAgents": "显示另外 {{value0}} 个代理→"
+ },
+ "FeatureSetupChecklist": {
+ "77f74946f5": "代理可互相通信、领取任务并协调交接。",
+ "399cf885c0": "代理编排",
+ "c5292c409d": "按你的要求,代理可查看应用窗口并操作本地应用。",
+ "1ecfb490ac": "计算机控制",
+ "01426f3a23": "代理可浏览网站、检查页面并完成浏览器任务。",
+ "ea85d9e628": "代理浏览器操控"
+ },
+ "FeatureSetupInlineTerminal": {
+ "789b59936e": "按 Enter 运行命令并在询问时确认 npx。您也可以稍后在“设置”中进行设置。",
+ "47fc6cc6dc": "技能设置命令",
+ "c767ab7061": "技能设置"
+ },
+ "IntegrationsStep": {
+ "277f30eb34": "Linear、GitLab、Bitbucket、Azure DevOps、Gitea 和 Jira 位于“设置”>“集成”中。",
+ "3a3e360289": "更多任务来源",
+ "80e3ce0bc9": "重新检查",
+ "04ef416712": "添加 Linear 访问",
+ "dd9c186a8b": "添加工作区访问权限",
+ "c91a5782f1": "已连接",
+ "27743304b1": "Linear",
+ "af69f42372": "按 Enter 运行 GitHub CLI 身份验证。浏览器或设备流程完成后重新检查 GitHub。",
+ "f9d2e12d17": "GitHub 登录命令",
+ "6d469169f2": "GitHub 设置",
+ "bd5d976fb2": "安装gh",
+ "50db38cf4b": "拉取请求、议题和检查状态。",
+ "c1547656f0": "检查…",
+ "8405043962": "需要登录",
+ "5c115cb713": "CLI 未安装",
+ "217beb0658": "GitHub",
+ "4983ae7433": "使用个人 API 密钥添加 Linear 访问权限。完全访问密钥可显示密钥所有者可访问的全部团队。",
+ "b08a6ac93c": "{{value0}} 工作区{{value1}} 已链接。随时添加另一个工作区或更换受限密钥。",
+ "93f0c49ad1": "未认证",
+ "a3bcf13694": "已连接",
+ "d6e5dba05a": "登录",
+ "0b4a7d23ab": "登录",
+ "a74c6d6b18": "未安装"
+ },
+ "NotificationStep": {
+ "3bede04483": "发送测试通知",
+ "dc897423e1": "选择通知声音",
+ "53aaffe49a": "通知声音",
+ "0fe570690c": "选择发送桌面通知后 Orca 播放的警报。",
+ "0af746e41f": "选择声音",
+ "8124d085a6": "打开 Mac 设置",
+ "aa36281b00": "打开系统设置并确保允许 Orca 发送通知。",
+ "d2dba86837": "在 macOS 中允许 Orca",
+ "e52aacf380": "正在加载通知设置...",
+ "3cd5374e22": "通知设置仍在加载中",
+ "b6a994e36e": "无法播放通知声音",
+ "c0692baa52": "选择自定义文件",
+ "ac80d97e02": "更改自定义文件"
+ },
+ "OnboardingFlow": {
+ "1b5e182e9f": "欢迎使用 Orca",
+ "4db04f2f57": "/",
+ "adaa0aa627": "前往入门步骤 {{value0}}:{{value1}}",
+ "a249f81538": "Orca",
+ "277ba45540": "Orca 入门引导",
+ "97c42cda00": "安装 GitHub CLI 以:",
+ "ae3b00ca82": "设置 GitHub 任务",
+ "ff92d15436": "Orca 会在代理完成工作或需要帮助时通知你。",
+ "b054332836": "设置通知",
+ "04ae28d8ca": "选择你想盯着看几个小时的主题。",
+ "f396db9f20": "让这里有家的感觉",
+ "322fc50a18": "Orca 支持所有 CLI 代理。选择你最常用的一个,随时可切换。",
+ "198b148b3c": "选择默认代理",
+ "a5e5da02f7": "集成",
+ "35bbaf5ae0": "notifications",
+ "984338477a": "theme",
+ "c47e1bd149": "agent"
+ },
+ "OnboardingFooter": {
+ "ba58547306": "返回",
+ "111d3f8d92": "跳至项目设置"
+ },
+ "OnboardingInlineCommandTerminal": {
+ "4123609efd": "启动终端..."
+ },
+ "OnboardingSkipConfirmationDialog": {
+ "9f47f345a4": "不会花很长时间的!",
+ "e4726b2d50": "跳过入门引导?"
+ },
+ "OnboardingTourStep": {
+ "3f9586c043": "开始导览",
+ "60c5576353": "退出导览"
+ },
+ "RepoStep": {
+ "e8fdb36338": "扫描存储库。单击停止。",
+ "b7c4da0504": "SSH?在“设置”中设置主机",
+ "c33b190ca3": "仅服务器路径",
+ "7b679207e4": "工作区",
+ "24c7c8696c": "克隆到服务器路径",
+ "7932e95f68": "克隆",
+ "955134915e": "git@github.com:org/repo.git",
+ "288d8444b7": "粘贴 HTTPS 或 SSH URL。",
+ "132425a3e3": "克隆一个仓库",
+ "6558d50c69": "想要一次导入多个存储库?选择父文件夹。",
+ "831524961f": "选择任何本地目录,无论是否为 git repo。",
+ "f4e9c8dcf8": "浏览文件夹",
+ "e8214aa632": "作为文件夹打开",
+ "3863747c56": "添加 Git 项目",
+ "2ebbc26343": "/home/user/project",
+ "466108ab89": "输入运行时服务器上存在的路径。",
+ "8cab104e3c": "打开服务器项目",
+ "2d20200346": "导入存储库",
+ "27ca610db1": "返回",
+ "cecd6593fa": "扫描的文件夹:",
+ "c7af322fc3": "停止扫描",
+ "c3d9d44ca2": "停止扫描",
+ "cf23006ba7": "运行时服务器",
+ "7ec3f48820": "/home/user",
+ "2e6438dd34": "{{value0}}在此文件夹中找到{{value1}} {{value2}}。"
+ },
+ "ThemeStep": {
+ "a4b254779d": "macOS Option 键",
+ "6c51398942": "鼠标",
+ "8ca01945f2": "分隔线",
+ "b3a99a2d29": "窗口",
+ "86c0f1caa2": "内边距",
+ "06a24f4f2d": "颜色",
+ "c021e9dddd": "主题配色",
+ "ab2a583a97": "Cursor",
+ "cc1858e19e": "字体",
+ "248c812283": "导入",
+ "7ee9234e54": "已检测 Ghostty 配置。",
+ "78b6386140": "已从 Ghostty 导入。",
+ "2c3aa538f8": "正在查找 Ghostty 配置…",
+ "94b9dc561d": "设置 → 终端",
+ "dd5c16ad1b": "更多终端选项(字体、光标、配色等)见",
+ "ad192706e6": "浅色",
+ "fa7b673ea9": "深色",
+ "827ea7b4a2": "系统",
+ "699ddf83c2": "无法导入 Ghostty 设置",
+ "16a9f0446a": "找不到要导入的 Ghostty 设置",
+ "ad19e5c916": "导入中…",
+ "906c4373fe": "设置"
+ },
+ "use": {
+ "onboarding": {
+ "flow": {
+ "dce4bdce5b": "无法打开 SSH 设置",
+ "fd74e7558e": "克隆失败",
+ "52acfbef51": "无法保存进度"
+ }
+ }
+ },
+ "AgentFeatureSetupStep": {
+ "97dcdc010f": "启用功能"
+ }
+ },
+ "new": {
+ "workspace": {
+ "SmartWorkspaceNameField": {
+ "2a0d535f69": "创建新分支",
+ "a44229ce4d": "作为工作区名称",
+ "766083a596": "”",
+ "34ca97bce3": "”",
+ "b1a7d679ba": "使用",
+ "e57c53727c": "添加项目...",
+ "a76fcb4fa0": "切换到",
+ "eadf877af5": "保持",
+ "6859e2896c": "取消",
+ "9ef1a7c4b0": ",与所选项目不同。",
+ "ad188067ae": "GitHub URL 指向",
+ "4bd98f1091": "切换项目?",
+ "0c9e668e3a": "清除",
+ "7199ff19c7": "清除选定的来源",
+ "370a1faf67": "在浏览器中打开",
+ "2c69728c2a": "在浏览器中打开链接",
+ "6f07a18604": "姓名",
+ "2e4c7c95fe": "分支",
+ "2cfc6be192": "GitLab",
+ "7a47af0565": "Linear",
+ "0a180280bd": "GitHub",
+ "b3c60c2b7c": "聪明的",
+ "26824f60dd": "全部",
+ "6fad211c66": "已关闭",
+ "2319d87718": "合并",
+ "622864b52a": "进行中",
+ "fda67f0b61": "当前项目",
+ "3e8bb1176a": "在设置中连接 Linear 以搜索议题。",
+ "69ce292138": "Linear",
+ "9c004911c3": "GitLab"
+ }
+ }
+ },
+ "mobile": {
+ "MobileHero": {
+ "a8fb43cf1c": "Continue",
+ "3f90dbd274": "完成",
+ "b622eba64d": "返回",
+ "65b3f2e8bc": "生成…",
+ "27735e5f4e": "配对二维码",
+ "bb0074ce11": "配对二维码",
+ "010dddcf27": "复制配对码",
+ "4c1df4eba7": "无法扫描?",
+ "85067b9e06": "刷新网络接口",
+ "ca85e595a7": "没有找到接口",
+ "79d2f480da": "用于广告的网络接口",
+ "dfd2aa9d5d": "网络",
+ "2f077ef4eb": ",然后扫码。",
+ "3aa7bb2d8b": "配对桌面",
+ "d1495e5e64": "打开 Orca Mobile,点击",
+ "901c98bb93": "配对这个",
+ "3960f5c339": "第 2 步(共 2 步)",
+ "3241f3c26a": "安装二维码",
+ "7af266b80d": "安装二维码",
+ "aa97420ba4": "复制安装链接",
+ "ac1eb64952": "安卓",
+ "711e6f4b47": "iOS系统",
+ "e75647ace0": "使用手机扫描二维码或打开安装链接以获取 Orca Mobile。",
+ "0d9b33299e": "获取应用程序。",
+ "92ddfdfa1f": "第 1 步(共 2 步)",
+ "ff48d9d520": "与另一台设备配对",
+ "f9cbf4bb53": "撤销设备",
+ "34f878d04f": "撤销 {{value0}}",
+ "94829abdb1": "配对",
+ "266c18c105": "打开 Orca Mobile 从上次中断的地方继续,或配对其他设备。",
+ "5410d55d79": "Orca Mobile",
+ "10d27b4cba": "开始使用",
+ "da1d5e5ed0": "可用于",
+ "ec0607bf66": "支持的移动平台",
+ "b4ccce5cb7": "从您的手机控制 Orca。当您离开办公桌时,检查代理、查看更改并启动任务。",
+ "cd4e5e816f": "您的工作区就在您的口袋里。",
+ "a6cffbbb0b": "生成代码",
+ "e59a252eca": "重新生成代码",
+ "d0b52871ce": "您的手机已配对。",
+ "051978a785": "您的手机已配对。"
+ },
+ "MobilePage": {
+ "e17393c6a3": "手机预览",
+ "baea63c445": "复制链接失败",
+ "fad833de8d": "安装链接已复制",
+ "6a66e38943": "复制配对码失败",
+ "3c1f7168bb": "配对码已复制",
+ "4c8bd11c1a": "生成配对码失败",
+ "b353e18de1": "WebSocket 传输未运行",
+ "4e1eb5d55c": "撤销设备失败",
+ "255372e6e8": "设备已撤销",
+ "1b4509a8a1": "配对的",
+ "c5909374cf": "简介"
+ },
+ "MobilePageToolbar": {
+ "ad2284a9e2": "关闭 · Esc",
+ "9883b58693": "关闭 Orca 移动",
+ "fb5f28330e": "在侧边栏中显示",
+ "c669abcf8f": "从侧边栏隐藏"
+ },
+ "PhoneCarousel": {
+ "96d651cb87": "终端会话",
+ "93217b41c1": "工作树列表",
+ "89c7713645": "Orca 移动主屏幕"
+ },
+ "mobile": {
+ "platform": {
+ "copy": {
+ "2a532d6fd7": "使用 Android 相机扫描以从 GitHub Releases 下载最新的 APK。",
+ "432db52b73": "使用 iPhone 相机扫描以打开 App Store。"
+ }
+ }
+ },
+ "slides": {
+ "HomeSlide": {
+ "a7d9e2c44d": "7天",
+ "a3d5476811": "5小时",
+ "8a350a4784": "账户使用情况",
+ "e27fdaee51": "新工作区",
+ "4405f3c440": "配对桌面",
+ "0b00c98506": "快捷操作",
+ "0bad5b07c8": "GitHub 和 Linear",
+ "d047197480": "GitHub · Linear",
+ "a4c3f7b7aa": "任务",
+ "d33d7a9c29": "Orca 壮举/移动页面",
+ "25d6e8a491": "壮举/移动页面",
+ "c791677f2f": "恢复",
+ "cf3f98fa3f": "已断开连接",
+ "091355da3d": "M1迷你·家",
+ "0bc1881bc4": "已连接 · 40 个工作树 · 5 个活动树",
+ "19c212e25e": "MacBook Pro",
+ "2f1a1d10c4": "台式机",
+ "156db8a68a": "已创建 PR",
+ "4a40af029b": "代理时间",
+ "00a6903322": "特工产生",
+ "c0e2e9dcd9": "欢迎回来",
+ "af761a0c0d": "设置",
+ "5d94e8ddcc": "Orca"
+ },
+ "TerminalSlide": {
+ "0bb39f8fe6": "发送",
+ "69334b4b10": "语音听写",
+ "29f2d13839": "输入命令...",
+ "817090af40": "Ctrl+C",
+ "53ff909568": "选项卡",
+ "4930eaaae7": "Esc键",
+ "fa22927f13": "粘贴",
+ "985373052e": "切换到手机模式",
+ "58a9ee6003": "工具调用格式化。接下来要我添加差异吗?",
+ "aa64b519c6": "终端屏幕。Tokyonight 配色,Menlo,真实 Claude",
+ "e75112c834": "我已经用高保真幻灯片替换了配对扫描幻灯片",
+ "3ce3e8c892": "14 次通过,1 次跳过(1.8 秒)",
+ "4b3666f9a9": "src/cache/worktree-cache.test.ts",
+ "1d448b69f7": "经过",
+ "d39445686a": "src/transport/host-store.test.ts",
+ "a6e7cdc688": "pnpm 测试 -- 过滤移动设备",
+ "21b67dfc92": "重击",
+ "d6d1041a1c": "⎿ 用终端会话替换配对扫描幻灯片",
+ "336c0e070e": "移动/orca-mobile-sidebar-mock-v3.html",
+ "6d4ebd5833": "编辑",
+ "fc83e0d5ef": "⎿ 阅读2103行",
+ "80cc356591": "读",
+ "2c10d43745": "claude",
+ "e0f98be657": "Orca/壮举-移动页面",
+ "2defc05141": "开发@mac",
+ "da121ba48d": "计划.md",
+ "e4befee569": "壳",
+ "606aa93192": "文件",
+ "94febb0976": "源头控制",
+ "8d6516312d": "2 个终端 · Claude 活跃",
+ "8432787c4e": "壮举/移动页面",
+ "8fd998acd3": "返回"
+ },
+ "WorktreeListSlide": {
+ "357a519567": "当前",
+ "79a24ff530": "已固定",
+ "22971156df": "回购协议",
+ "17f9e0d226": "最近的",
+ "0e3e809a4b": "筛选",
+ "b4271864bd": "MacBook Pro",
+ "cefd048225": "返回",
+ "c5ad56786d": "旋转器"
+ }
+ }
+ },
+ "gitlab": {
+ "gitlab": {
+ "rate": {
+ "limit": {
+ "display": {
+ "ebc0e8ecf1": "正在加载 GitLab API 预算...",
+ "a2d3d1fdde": "GitLab API 预算不可用。",
+ "a2f68645ac": "刷新 GitLab API 预算",
+ "2f9c16d6c3": "Orca 通过 GitLab CLI 使用 REST。",
+ "14e144f7a7": "亚搏体育appGitLab API预算",
+ "3e2c982cfa": "向左,重置于",
+ "ea8ad0bae8": "的",
+ "0a891e8935": "休息API",
+ "953f7c6062": "此 GitLab 主机未返回速率限制标头。"
+ }
+ }
+ }
+ }
+ },
+ "floating": {
+ "terminal": {
+ "FloatingTerminalIconContextMenu": {
+ "8e7d775287": "隐藏浮动工作区",
+ "763f5fa2c1": "移动到浮动按钮",
+ "0ee79e0674": "移至状态栏"
+ },
+ "FloatingTerminalOrchestrationDialog": {
+ "f726054620": "使代理能够通过 Orca 传递上下文并协调工作。",
+ "1cd3f8af64": "编排技能",
+ "6f0aed26b8": "安装 Orca CLI 和编排技能,以便代理可以通过 Orca 进行协调。",
+ "05d7aabc20": "未安装",
+ "630c0ac8c8": "已安装",
+ "dfd021ce46": "检查中...",
+ "543f325a14": "启用编排"
+ },
+ "FloatingTerminalPanel": {
+ "fc1042e92b": "最小化",
+ "8b07759314": "新浏览器",
+ "88ffb502e5": "打开 Markdown 笔记",
+ "629528690b": "新的 Markdown 笔记",
+ "3215fc73e9": "新航站楼",
+ "da508bd7f5": "保存",
+ "918c2139f3": "不保存",
+ "e7bf09d4d4": "取消",
+ "690b6fb98a": "未保存的更改",
+ "bbc177f98f": "启用",
+ "adc281394d": "关闭",
+ "8cf80db43b": "设置 Orca CLI 和代理技能,以便代理可以通过 Orca 进行协调。",
+ "2a3c5ddf5e": "启用编排",
+ "d6b563ae24": "正在加载编辑器...",
+ "8b14ba6c17": "新浏览器选项卡",
+ "b085fb58b5": "该文件有未保存的更改。",
+ "5ddc688c52": "“{{value0}}”有未保存的更改。您想在关闭前保存吗?",
+ "25d7817f79": "终端"
+ },
+ "FloatingTerminalToggleButton": {
+ "3b04b065b5": "显示浮动工作区",
+ "5785dd9148": "最小化浮动工作区",
+ "bfe7809a70": "{{value0}} 浮动工作区 ({{value1}})"
+ },
+ "FloatingTerminalWindowControls": {
+ "2f6054342c": "最小化",
+ "1bbaa0302f": "最小化浮动工作区",
+ "3f4ca29961": "最大化浮动工作区",
+ "1c79cba25d": "恢复浮动工作区",
+ "648352c51f": "在浮动工作区中打开 {{value0}}",
+ "82da3701e7": "无法为 {{value0}} 构建启动命令。",
+ "109870e023": "最大化",
+ "b5686fee1e": "恢复"
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "AgentCapabilitiesSetupAction": {
+ "b8dc9dd8a2": "已安装",
+ "1b51644c2d": "让代理控制桌面、移动光标、单击并在任何应用程序中键入。",
+ "362a07517d": "计算机控制",
+ "5e8fe5a72d": "让代理直接访问 Orca 的浏览器,以便测试页面、捕获屏幕截图并根据所见内容执行操作。",
+ "e638da007a": "代理浏览器使用",
+ "c61c91e642": "让代理通过 Orca 进行协调,以确保大型、多步骤的任务顺利完成。",
+ "ac07f8887f": "代理编排",
+ "e9eb197e12": "打开计算机使用权限",
+ "3a59452a67": "技能命令已复制并插入到下方以供评审。",
+ "c605f51f2b": "能力设置就绪",
+ "1aa657d8f4": "一些能力设置需要注意",
+ "c89534cbe9": "安装 CLI 和技能"
+ },
+ "AiCommitPrSettingsCard": {
+ "8d4152701a": "例如llama 运行 llama3.1 {{value0}}",
+ "9ee54037a4": "自定义命令",
+ "4b2fc4b80c": "思考努力",
+ "be8917699e": "模型",
+ "4d9b6d84df": "不支持。选择 Claude、Codex 或 Custom。",
+ "560d4feb00": "自定义",
+ "29d119fe95": "代理",
+ "f9382b48a1": "启用AI作者",
+ "1c0cb4fabb": "AI 作者",
+ "bd14e9c42a": "未配置",
+ "1f9468c5c9": "{{value0}} 不支持"
+ },
+ "BrowserAnimatedVisual": {
+ "46df009982": "开始免费试用",
+ "25f15c2219": "专业版",
+ "59ae327405": "入门版",
+ "9e0f530390": "定价",
+ "0ce7c24b4d": "处理中…",
+ "f2034c4930": ">",
+ "6e4616d039": "Claude",
+ "0f8481e1a7": "发送给Claude",
+ "3d2352f94b": "描述一下变化……",
+ "d8856b604a": "div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta",
+ "7da6eed7bf": "本地主机:3000",
+ "0a2bd01c02": "新浏览器选项卡",
+ "04096318ab": "终端 1",
+ "eb88125c6f": "✓ 已验证 — 免费试用仍然有效。",
+ "051c97d15a": ".pp-card[data-card=\"starter\"] .pp-cta",
+ "4fa59ca545": "✓ 更新",
+ "1bec24acc1": "@keyframes browserFlash { 0% { 不透明度:0; } 20% { 不透明度: 0.85; } 100% { 不透明度: 0; } } @keyframes browserTabIn { 来自 { 不透明度:0;变换:translateY(-2px); } 到 { 不透明度:1;变换:无; } } @keyframes browserViewIn { 来自 { 不透明度:0;变换:翻译Y(4px); } 到 { 不透明度:1;变换:无; } }",
+ "73bbb46073": "/定价",
+ "f39be6ca14": "/报名"
+ },
+ "BrowserUseSkillSetupCard": {
+ "cbc45022d4": "使代理能够在 Orca 浏览器中导航和验证页面。",
+ "d5bb1cd4ba": "浏览器使用技能"
+ },
+ "ComputerUseAnimatedVisual": {
+ "d8401975b1": "得到正式认可的",
+ "f27676a92c": "状态:",
+ "6804cb356f": "点击发送",
+ "1719b28a81": "找到“批准”",
+ "79445f7512": "批准我的应用程序中的注释",
+ "99a8624bcb": ">",
+ "2adb561b44": "Claude Code 会话已开始",
+ "94787f01f8": "Claude·科德",
+ "9cddfe96b2": "本地应用程序",
+ "9634d870d1": "批准",
+ "3cc2df3671": "完成",
+ "bdd5312213": "待办的",
+ "c11dda000b": "得到正式认可的"
+ },
+ "EditorAnimatedVisual": {
+ "7a763daf2f": "斜体",
+ "8521536429": "大胆的 ·",
+ "8341391520": "用于块·",
+ "3fe42a1da0": "类型",
+ "8268b2376b": "代码块",
+ "37fa4948ce": "项目符号列表",
+ "f25687c588": "引用",
+ "abbdeea15d": "基本块",
+ "a26a68d30c": "标题 2",
+ "722170663a": "标题 1",
+ "1fb29ad710": "标题",
+ "4426aab46f": "新图块落地后更新文档索引。",
+ "95f0c3a46f": "在新机器上对安装流程进行冒烟测试。",
+ "22ae7b4d9d": "给团队的一句简短说明——在发布前汇总剩余工作。",
+ "5a55c00a81": "推出计划",
+ "218503f9f3": "自动保存",
+ "cda56c5915": "笔记/launch-plan.md",
+ "e16479c1c5": "[data-slash-menu] [data-slash-row].slash-active { 背景:rgba(24,24,27,0.07);框阴影:插入 0 0 0 1px rgba(24,24,27,0.06); } [data-md-active-line][data-role=\"active\"] { 颜色:rgb(113 113 122);字体系列:ui-monospace、SFMono-Regular、Menlo、等宽字体;字体大小:12.5px; } [data-md-active-line][data-role=\"h1\"] { 颜色:继承;字体系列:继承;字体大小:18px;字体粗细:700;字母间距:-0.01em;行高:1.2;顶部边距:6px; } [data-md-caret] { 显示:内联块;宽度:1.5px;高度:1em;背景:当前颜色;垂直对齐:-2px;左边距:1px;动画: md-caret-blink 1.05s steps(1) 无限; } @keyframes md-caret-blink { 0%, 50% { 不透明度: 1 } 51%, 100% { 不透明度: 0 } } @keyframes md-block-in { 来自 { 不透明度: 0; }变换:translateY(-2px); } 到 { 不透明度:1;变换:无; } } @keyframes md-cursor-ripple { 0% { 变换:缩放(0.4);不透明度:0.9; } 100% { 变换:缩放(1.4);不透明度:0; [data-clicking=\"1\"] [data-cursor-ripple] { 动画:md-cursor-ripple 460ms 向前缓出; }"
+ },
+ "FeatureTourPreview": {
+ "1170621527": ">",
+ "304ad0dfc1": "思维...",
+ "ef8b164dd1": "审查 src/auth",
+ "952d3ddd9a": "会话开始",
+ "771d8881c2": "claude",
+ "6ed43cb0e0": "仪表板规格.ts",
+ "24fedd5a52": "登录规范",
+ "8279e9d95b": "运行 12 项测试",
+ "6218a9014d": "pnpm剧作家测试",
+ "04d54d50ec": "Orca·zsh",
+ "1aa8a9a24a": "可拆分终端",
+ "2a7cfc82c8": "链接到 GH #1842",
+ "3822d8d14b": "修复/worktree-picker-截断",
+ "d54aefe09e": "林-329",
+ "40bbd92ef4": "开始",
+ "c1f28c03b2": "工作树选择器截断",
+ "fc0cc0b267": "GH #1842",
+ "0688842445": "GH#1799",
+ "bee6b4088d": "GitHub 和 Linear 任务",
+ "5171768676": "协调3个代理",
+ "cebc7769cd": "重新设计身份验证流程",
+ "e44269e97d": "代理编排",
+ "ec4a73f5e6": "PR 3/3",
+ "cfdfd4d6b4": "PR 2/3",
+ "b1f17bcc74": "PR 1/3",
+ "e38112b289": "重构计费 Webhook",
+ "9c812e0d7c": "加速 CI 管道",
+ "3c4adfd821": "修复登录竞争条件",
+ "56a0271428": "独立的工作区",
+ "ef737dcee1": "GitHub 和 Linear 任务",
+ "ac51c061e2": "codex"
+ },
+ "FeatureWallBody": {
+ "25ec5356d6": "设置"
+ },
+ "FeatureWallModal": {
+ "33dca8bbbe": "Orca 的一个简短的、逐个工作流程的浏览。",
+ "3567e147c8": "了解 Orca"
+ },
+ "FeatureWallPreview": {
+ "a666384798": "也在这个工作流程中"
+ },
+ "FeatureWallRail": {
+ "69ea857689": "已完成",
+ "7593d15f94": "工作流程"
+ },
+ "FeatureWallSetupChecklist": {
+ "1a6a7d6c80": "设置",
+ "713cc529a5": "里程碑",
+ "b1f1981c5e": "查看任务",
+ "505f4c910c": "分体终端",
+ "0235b268b2": "还没有完成",
+ "13294d3405": "完成"
+ },
+ "FeatureWallSetupWorkflowActions": {
+ "486c2f4d8d": "首先添加 git 项目,然后配置该存储库的安装脚本。",
+ "00078a6134": "在设置中查看",
+ "14327073cc": "保存",
+ "88469e926b": "设置脚本",
+ "5c5b65044e": "即插即用安装",
+ "a7463915b6": "无法保存设置脚本",
+ "6299297dac": "设置脚本已保存",
+ "f0bbf7da77": "尝试一下",
+ "364430eb3d": ",或右键单击窗格并选择拆分。关闭活动窗格",
+ "29e64f111d": "或向下",
+ "971775f639": "向右拆分",
+ "522cce9e33": "添加项目"
+ },
+ "FeatureWallTourPanel": {
+ "af7d622f6f": "可选"
+ },
+ "KeepAwakeCard": {
+ "209713d3c7": "可选"
+ },
+ "ReviewNotesAnimatedVisual": {
+ "5dbd27c4c2": "Codex",
+ "09094f25e2": "Claude·科德",
+ "294aaff104": "发送注释至",
+ "ea4e45b71b": "添加备注",
+ "271ea0cbf3": "取消",
+ "a7a89d8f94": "线",
+ "5cb213f967": "AI 笔记",
+ "1eee3a397e": "src/server/migrate.ts(差异)"
+ },
+ "ReviewPRViewAnimatedVisual": {
+ "7c2808ecff": "合并前截断。",
+ "c2062da7ec": "标准错误",
+ "6f4c2d7cb7": "添加承保案例",
+ "71828fba75": "我们可以将失败的命令包含在诊断负载中吗?",
+ "fb1a856b6d": "打开",
+ "7a8b896e11": "评论",
+ "ca36f7b27c": "通过",
+ "25f6838e43": "Lint",
+ "2ef0b97954": "类型检查",
+ "8ed213397c": "跑步",
+ "d340c052fb": "核实",
+ "9a097cae12": "1 待定",
+ "2f37142229": "压缩合并",
+ "0aab7ab84a": "添加本地诊断错误跟踪",
+ "dfe313e0c9": "打开",
+ "6e3f5223c5": "探险家",
+ "ab2901bce6": "检查项",
+ "d7f80060ca": "源代码控制",
+ "8e715588e4": "搜索"
+ },
+ "ReviewShipAnimatedVisual": {
+ "4d99496b8c": "创建PR",
+ "62544e0852": "取消",
+ "bcd5cae3c4": "拉取请求描述",
+ "3774b80eae": "描述",
+ "07da9245cc": "拉取请求标题",
+ "54a093c52d": "标题",
+ "3b9b96d6a6": "主要的",
+ "ce7d5d3a18": "基础分支",
+ "e4473d438f": "用 AI 生成",
+ "c30cd930ff": "创建拉取请求",
+ "ea0100dd15": "查看全部",
+ "e725000cd7": "变化",
+ "a079083a6c": "犯罪",
+ "7347fa5839": "信息",
+ "d1a7f15876": "使用 AI 生成提交消息",
+ "cd8a3a39d7": "提前 3 次提交"
+ },
+ "TasksAnimatedVisual": {
+ "efba6f77eb": "阅读议题 #",
+ "b68c92fbdc": "启动工作区",
+ "4331c4d0f8": "进行中",
+ "b13375617e": "工作树选择器截断名称",
+ "72f9e516a3": "紧迫",
+ "fe47c9c9e8": "工作区准备就绪",
+ "61ffda7601": "创建工作区"
+ },
+ "WorkbenchAnimatedVisual": {
+ "633a91e358": "思维…",
+ "932c4b3a97": ">",
+ "ca2cfbf188": "向下拆分终端",
+ "e370fa8c2b": "分体式端子右",
+ "b85eab49dd": "src/auth/session.ts",
+ "99f5224f1e": "编辑",
+ "0d93c298a7": "抛出 src/auth",
+ "17cfdc3344": "格雷普",
+ "9923847785": "读",
+ "c0eb94125e": "审查授权边缘情况",
+ "431ca9842a": "Claude Code 会话已开始",
+ "000106adfe": "claude",
+ "7d9f1d5f7d": "(0.8秒)",
+ "944199e54a": "› 购物车总更新",
+ "623881d72e": "结帐规格",
+ "5c5cbd783f": "(1.2秒)",
+ "3261c6853b": "› 可以登录",
+ "defe550fe2": "登录规范",
+ "0b20782e0f": "使用 4 名工作人员运行 12 项测试",
+ "4371cc9931": "pnpm剧作家测试",
+ "16877e038d": "分裂",
+ "a2b114dad0": "向右劈叉 ·",
+ "0bc9ad0cd1": "同一窗格:",
+ "fc84f17fe7": "Codex 会话已开始"
+ },
+ "agent": {
+ "capability": {
+ "setup": {
+ "status": {
+ "8eccfcb314": "已安装",
+ "21d4f79c93": "单击安装 CLI 和技能以打开 macOS 访问设置",
+ "5c9293e51a": "检查应用程序访问权限",
+ "aae94eeb52": "单击安装 CLI 和技能",
+ "aa8e143a2f": "无法检查安装",
+ "9b33e7fb13": "检查安装",
+ "4c8e1f92a7": "在此 Mac 上打开 Orca Desktop",
+ "6d2b0a84e1": "此版本不可用"
+ }
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "usage": {
+ "tracking": {
+ "b94ec70eda": "未设置跟踪",
+ "cc39a87288": "已连接·系统默认",
+ "00087eecb2": "已连接 · {{value0}}"
+ }
+ }
+ }
+ },
+ "review": {
+ "animated": {
+ "visual": {
+ "shared": {
+ "e7894927a2": "Codex",
+ "9deecb021c": "Claude"
+ },
+ "notes": {
+ "styles": {
+ "db6691aa0a": ".ravs-window { position: absolute; inset: 0; --ravs-soft-surface: color-mix(in srgb, var(--foreground) 2%, var(--card)); --ravs-soft-fill: color-mix(in srgb, var(--foreground) 6%, transparent); --ravs-panel-border: color-mix(in srgb, var(--foreground) 18%, var(--border)); --ravs-emphasis-border: color-mix(in srgb, var(--foreground) 44%, var(--border)); --ravs-floating-shadow: 0 14px 30px rgb(0 0 0 / 0.22), 0 2px 6px rgb(0 0 0 / 0.12); background: var(--card); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 1px 2px rgb(0 0 0 / 0.08); } .ravs-difftoolbar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-bottom: 1px solid var(--border); background: var(--ravs-soft-surface); font-size: 11px; color: var(--muted-foreground); } .ravs-diff-path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground); } .ravs-ai-chip { margin-left: auto; display: inline-flex; align-items: stretch; overflow: hidden; border-radius: 6px; border: 1px solid var(--border); background: var(--ravs-soft-surface); opacity: 0; transform: translateY(-2px); transition: opacity 320ms ease, transform 320ms ease; } .ravs-ai-chip.is-visible { opacity: 1; transform: none; } .ravs-ai-chip .ravs-count-btn, .ravs-ai-chip .ravs-send-btn { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; font-size: 11px; color: var(--muted-foreground); background: transparent; line-height: 1; } .ravs-ai-chip .ravs-count-btn { border-right: 1px solid var(--border); } .ravs-ai-chip .ravs-send-btn { padding: 3px 7px; position: relative; } .ravs-send-glow { position: absolute; inset: 0; background: rgba(34, 197, 94, 0.18); opacity: 0; transition: opacity 280ms ease; pointer-events: none; } .ravs-ai-chip .ravs-send-btn.is-flash .ravs-send-glow { opacity: 1; } .ravs-count-num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground); font-weight: 600; } .ravs-diffbody { flex: 1; min-height: 0; position: relative; background: var(--editor-surface, var(--card)); } .ravs-diffscroll { position: absolute; inset: 0; overflow: hidden; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; line-height: 1.55; color: var(--foreground); padding: 4px 0 8px; transition: opacity 240ms ease; } .ravs-diffscroll.is-hidden { opacity: 0; pointer-events: none; } .ravs-term { position: absolute; inset: 0; background: var(--editor-surface, var(--card)); color: var(--foreground); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 1.45; overflow: hidden; display: flex; flex-direction: column; opacity: 0; pointer-events: none; transition: opacity 240ms ease; z-index: 4; } .ravs-term.is-visible { opacity: 1; } .ravs-term-body { flex: 1; min-height: 0; padding: 10px 12px; overflow: hidden; display: flex; flex-direction: column; gap: 6px; } .ravs-term-line { white-space: pre-wrap; word-break: break-word; line-height: 1.45; } .ravs-term-muted { color: var(--muted-foreground); } .ravs-term-glyph { color: rgb(217 119 6); margin-right: 6px; } .ravs-term-check { color: rgb(16 185 129); font-weight: 700; margin-right: 6px; } .ravs-term-spinner { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 999px; border: 1.5px solid color-mix(in srgb, var(--foreground) 20%, transparent); border-top-color: var(--foreground); vertical-align: -1px; animation: ravs-term-spin 0.9s linear infinite; } @keyframes ravs-term-spin { to { transform: rotate(360deg) } } .ravs-hunk-header { display: grid; grid-template-columns: 36px 36px 16px minmax(0,1fr); align-items: center; padding: 1px 8px 1px 0; background: rgba(99, 102, 241, 0.06); color: var(--muted-foreground); font-size: 10.5px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); } .ravs-hunk-header .ravs-text { grid-column: 4 / -1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: rgb(99 102 241); font-size: 10.5px; } .ravs-diff-line { display: grid; grid-template-columns: 36px 36px 16px minmax(0,1fr); align-items: stretch; position: relative; } .ravs-ln { text-align: right; padding: 0 6px 0 0; color: var(--muted-foreground); font-size: 10.5px; user-select: none; opacity: 0.85; } .ravs-marker { text-align: center; color: var(--muted-foreground); font-weight: 700; opacity: 0.7; } .ravs-text-cell { padding-right: 8px; white-space: pre; overflow: hidden; } .ravs-tok-kw { color: #a855f7; } .ravs-tok-id { color: #2563eb; } .ravs-tok-str { color: #16a34a; } .ravs-diff-line.is-add { background: color-mix(in srgb, var(--git-decoration-added) 14%, transparent); } .ravs-diff-line.is-add .ravs-marker { color: color-mix(in srgb, var(--git-decoration-added) 72%, transparent); opacity: 1; } .ravs-diff-line.is-rem { background: color-mix(in srgb, var(--git-decoration-deleted) 14%, transparent); } .ravs-diff-line.is-rem .ravs-marker { color: color-mix(in srgb, var(--git-decoration-deleted) 72%, transparent); opacity: 1; } .ravs-add-note-btn { position: absolute; left: 4px; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 1px solid color-mix(in srgb, currentColor 22%, var(--border)); border-radius: 4px; background: var(--ravs-soft-fill); color: var(--foreground); z-index: 5; opacity: 0; box-shadow: 0 1px 2px rgb(0 0 0 / 0.14); pointer-events: none; transition: opacity 160ms ease; } .ravs-add-note-btn.is-visible { opacity: 1; } .ravs-note-row { padding: 4px 8px 4px 0; max-height: 0; overflow: hidden; opacity: 0; transition: max-height 360ms cubic-bezier(.4,0,.2,1), opacity 280ms ease 60ms, padding 360ms cubic-bezier(.4,0,.2,1); } .ravs-note-row.is-visible { max-height: 90px; opacity: 1; } .ravs-note-card { margin: 0 12px; position: relative; border: 1px solid var(--ravs-panel-border); border-left: 3px solid var(--ravs-emphasis-border); border-radius: 6px; background-color: var(--card); padding: 5px 8px 5px 10px; box-shadow: 0 1px 2px rgb(0 0 0 / 0.16); } .ravs-note-meta { font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-foreground); } .ravs-note-body { font-size: 11.5px; color: var(--foreground); line-height: 1.35; margin-top: 2px; } .ravs-popover { position: absolute; left: 12px; right: 12px; max-width: none; z-index: 20; padding: 8px 10px; border: 1px solid var(--ravs-panel-border); border-left: 3px solid var(--ravs-emphasis-border); border-radius: 6px; background-color: var(--card); color: var(--foreground); box-shadow: var(--ravs-floating-shadow); display: flex; flex-direction: column; gap: 6px; opacity: 0; transform: translateY(-4px) scale(0.985); pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; } .ravs-popover.is-visible { opacity: 1; transform: none; pointer-events: auto; } .ravs-pop-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted-foreground); } .ravs-pop-input { min-height: 38px; max-height: 80px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--editor-surface, var(--card)); font-size: 12px; line-height: 1.4; color: var(--foreground); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pop-footer { display: flex; justify-content: flex-end; gap: 6px; } .ravs-pop-btn { font-size: 11px; font-weight: 500; padding: 4px 9px; border-radius: 5px; line-height: 1; border: 1px solid transparent; display: inline-flex; align-items: center; gap: 5px; } .ravs-pop-btn.is-cancel { color: var(--muted-foreground); background: transparent; } .ravs-pop-btn.is-add { color: var(--primary-foreground); background: var(--primary); } .ravs-send-menu { position: absolute; z-index: 30; right: 8px; top: 6px; min-width: 200px; background: var(--popover); color: var(--popover-foreground); border: 1px solid var(--border); border-radius: 8px; padding: 4px; box-shadow: var(--ravs-floating-shadow); opacity: 0; transform: translateY(-4px) scale(0.985); pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; } .ravs-send-menu.is-visible { opacity: 1; transform: none; pointer-events: auto; } .ravs-menu-section { padding: 4px 8px 2px; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-foreground); } .ravs-menu-row { display: grid; grid-template-columns: 16px minmax(0,1fr); align-items: center; gap: 8px; padding: 6px 8px; border-radius: 5px; font-size: 12px; color: var(--popover-foreground); } .ravs-menu-row.is-hot { background: var(--accent); box-shadow: inset 0 0 0 1px var(--border); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid color-mix(in srgb, var(--foreground) 52%, transparent); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }"
+ }
+ },
+ "pr": {
+ "view": {
+ "styles": {
+ "fc9a23c83d": ".ravpr-stage { position: absolute; inset: 0; overflow: hidden; } .ravpr-stack { position: absolute; inset: 0; display: flex; justify-content: flex-end; padding: 4px 34px 4px 2px; overflow: hidden; } .ravpr-sidebar, .ravpr-card { position: absolute; top: 4px; right: 2px; width: 464px; height: calc(100% - 8px); background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; color: var(--foreground, #18181b); overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } .ravpr-sidebar { opacity: 0; transition: opacity 220ms ease; } .ravpr-sidebar.is-visible { opacity: 1; } .ravpr-sidebar.is-hiding { opacity: 0; } .ravpr-card { display: flex; flex-direction: column; min-width: 0; opacity: 0; transition: opacity 260ms ease; } .ravpr-card.is-visible { opacity: 1; } .ravpr-tabs { position: relative; display: flex; align-items: center; gap: 14px; height: 36px; padding: 0 14px; background: rgba(24,24,27,0.015); color: var(--muted-foreground, #71717a); } .ravpr-tab { position: relative; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted-foreground, #71717a); } .ravpr-tab.is-active, .ravpr-tab.is-hovered { color: var(--foreground, #18181b); } .ravpr-tab.is-active::after { content: ''; position: absolute; left: -5px; right: -5px; bottom: -10px; height: 1px; background: var(--foreground, #18181b); } .ravpr-tooltip { position: absolute; top: 34px; left: 106px; z-index: 6; padding: 7px 11px; border-radius: 8px; background: var(--card, #fff); color: var(--foreground, #18181b); font-size: 12px; line-height: 1; box-shadow: 0 8px 22px rgba(0,0,0,0.22); opacity: 0; transform: translateY(-3px); pointer-events: none; transition: opacity 160ms ease, transform 160ms ease; } .ravpr-tooltip.is-visible { opacity: 1; transform: translateY(0); } .ravpr-explorer { padding: 10px 12px 12px; } .ravpr-heading { color: var(--muted-foreground, #71717a); font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; } .ravpr-file-list { margin-top: 8px; display: flex; flex-direction: column; gap: 2px; } .ravpr-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 22px; align-items: center; gap: 8px; min-height: 28px; padding: 4px 6px; border-radius: 6px; } .ravpr-file.is-active { background: rgba(24,24,27,0.06); box-shadow: inset 0 0 0 1px rgba(24,24,27,0.06); } .ravpr-file-icon { width: 12px; height: 12px; border-radius: 3px; background: rgba(24,24,27,0.14); } .ravpr-file-name { height: 8px; border-radius: 999px; background: rgba(24,24,27,0.14); } .ravpr-file-status { width: 14px; height: 8px; border-radius: 999px; background: rgba(24,24,27,0.12); } .ravpr-body { padding: 10px 12px 18px; display: flex; flex-direction: column; gap: 5px; min-height: 0; } .ravpr-number-row { display: flex; align-items: center; gap: 7px; } .ravpr-number { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; font-weight: 700; } .ravpr-open { display: inline-flex; align-items: center; justify-content: center; height: 18px; padding: 0 7px; border-radius: 5px; background: rgba(16,185,129,0.10); border: 1px solid rgba(16,185,129,0.28); color: rgb(4 120 87); font-size: 9px; font-weight: 700; line-height: 1; } .ravpr-title { font-size: 12px; font-weight: 600; line-height: 1.35; color: var(--foreground, #18181b); margin-bottom: 2px; } .ravpr-merge { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; min-height: 30px; flex: 0 0 30px; border-radius: 7px; background: rgb(22 163 74); color: #fff; font-size: 11.5px; font-weight: 700; margin-bottom: 2px; box-shadow: 0 1px 2px rgba(22,163,74,0.18); transition: box-shadow 220ms ease, filter 220ms ease; } .ravpr-merge.is-ready { box-shadow: 0 0 0 3px rgba(34,197,94,0.22), 0 1px 2px rgba(22,163,74,0.18); } .ravpr-section-row, .ravpr-check-row { display: grid; grid-template-columns: 18px minmax(0,1fr) auto; align-items: center; gap: 7px; padding: 5px 0; font-size: 11.5px; color: var(--foreground, #18181b); } .ravpr-check-row { padding: 5px 7px; font-size: 10.5px; } .ravpr-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ravpr-meta, .ravpr-check-state { color: var(--muted-foreground, #71717a); font-size: 10.5px; } .ravpr-check-state { font-size: 10px; } .ravpr-ring { display: inline-block; width: 14px; height: 14px; border-radius: 999px; border: 2px solid rgba(245,158,11,0.35); border-top-color: rgb(245 158 11); animation: ravpr-spin 1.1s linear infinite; } .ravpr-check { width: 15px; height: 15px; border-radius: 999px; display: none; align-items: center; justify-content: center; background: rgba(34,197,94,0.14); color: rgb(22 163 74); } .ravpr-section-row.is-done .ravpr-ring, .ravpr-check-row.is-done .ravpr-ring { display: none; } .ravpr-section-row.is-done .ravpr-check, .ravpr-check-row.is-done .ravpr-check { display: inline-flex; } .ravpr-reveal { display: flex; flex-direction: column; gap: 3px; opacity: 0; transform: translateY(4px); transition: opacity 260ms ease, transform 260ms ease; pointer-events: none; } .ravpr-reveal.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; } .ravpr-check-list, .ravpr-comment-list { display: flex; flex-direction: column; gap: 4px; min-height: 0; } .ravpr-comment-card { border: 1px solid var(--border); border-radius: 8px; background: var(--card, #fff); overflow: hidden; opacity: 0; transform: translateY(4px); transition: opacity 260ms ease, transform 260ms ease; } .ravpr-comment-card.is-visible { opacity: 1; transform: translateY(0); } .ravpr-comment-head { display: grid; grid-template-columns: 18px minmax(0,1fr) auto; align-items: center; gap: 7px; padding: 5px 7px; background: rgba(24,24,27,0.015); } .ravpr-avatar { width: 16px; height: 16px; border-radius: 999px; background: rgba(24,24,27,0.16); } .ravpr-author { width: 78px; height: 8px; border-radius: 999px; background: rgba(24,24,27,0.18); } .ravpr-comment-path { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 9.5px; color: var(--muted-foreground, #71717a); } .ravpr-comment-body { padding: 5px 7px 6px; font-size: 11px; line-height: 1.32; color: var(--foreground, #18181b); } .ravpr-comment-body code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; padding: 1px 4px; border-radius: 4px; background: rgba(24,24,27,0.06); } .ravpr-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravpr-cursor.is-visible { opacity: 1; } .ravpr-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravpr-cursor.is-clicking .ravpr-ripple { animation: ravpr-ripple 460ms ease-out forwards; } @keyframes ravpr-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } @keyframes ravpr-spin { to { transform: rotate(360deg); } }"
+ }
+ }
+ },
+ "ship": {
+ "styles": {
+ "90cdcd2ecc": ".ravs-ship-root { position: absolute; inset: 0; } .ravs-ship-stack { position: absolute; inset: 0; display: grid; grid-template-columns: 232px minmax(0,1fr); gap: 14px; padding: 4px 2px; /* Why: cards size to their content rather than stretch to the parent's full height, so the two cards don't show empty space below their content. */ align-items: start; } /* Source Control mini-sidebar — ahead-count header, commit textarea + split Commit button, then a CHANGES section with file rows. The file rows are the surface the \"reading\" pulse animates over. */ .ravs-sc-card { display: flex; flex-direction: column; background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } /* Both card headers share the same fixed height so the SC card and PR dialog align across the top edge regardless of header content. */ .ravs-sc-header, .ravs-pr-head { height: 36px; box-sizing: border-box; } .ravs-sc-header { display: flex; align-items: center; justify-content: space-between; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-sc-ahead { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } .ravs-sc-ahead svg { color: var(--muted-foreground, #71717a); } .ravs-sc-commit-area { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; } .ravs-sc-textarea { position: relative; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); padding: 6px 26px 6px 8px; min-height: 56px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-sc-textarea .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-sc-sparkle { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; transition: color 160ms ease, background 160ms ease; } .ravs-sc-sparkle.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-sc-split { display: flex; align-items: stretch; } /* Why: Commit + Create PR are surrounding chrome — the violet AI affordances are the focal points. Render them as quiet secondary buttons so they don't compete with the sparkle/scan signals. */ .ravs-sc-split .ravs-primary { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 5px 10px; background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); font-size: 11px; font-weight: 500; border-radius: 6px 0 0 6px; border: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } .ravs-sc-split .ravs-chev { display: inline-flex; align-items: center; justify-content: center; width: 22px; background: var(--secondary, #f5f5f5); color: var(--muted-foreground, #71717a); border-radius: 0 6px 6px 0; border: 1px solid var(--border); border-left: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } /* Why: when AI has filled the commit message, tint the Commit button green to signal \"ready to commit\". Uses the same success-green family as the PR flash so the two beats rhyme. Mix is intentionally strong (~28%) — at 14% it disappeared next to the violet sparkle and PR flash, so users only saw the PR change color. */ .ravs-sc-split.is-ready .ravs-primary, .ravs-sc-split.is-ready .ravs-chev { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); transition: background 220ms ease, border-color 220ms ease, color 220ms ease; } .ravs-sc-split.is-ready .ravs-chev { border-left-color: rgba(34, 197, 94, 0.55); } .ravs-sc-changes-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-sc-changes-count { color: var(--foreground, #18181b); font-weight: 600; margin-left: 2px; } .ravs-sc-view-all { font-size: 10px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted-foreground, #71717a); } .ravs-sc-files { display: flex; flex-direction: column; padding: 2px 6px 8px; flex: 1; min-height: 0; overflow: hidden; } .ravs-sc-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 12px; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 4px; font-size: 11px; line-height: 1.35; color: var(--foreground, #18181b); position: relative; transition: background 220ms ease; } .ravs-sc-ficon { color: rgb(180 83 9); display: inline-flex; } .ravs-sc-fname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ravs-sc-fmark { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; text-align: right; color: rgb(180 83 9); } .ravs-sc-file.is-reading { background: color-mix(in srgb, rgb(139 92 246) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, rgb(139 92 246) 28%, transparent); } /* PR dialog — matches the .ravs-sc-card chrome (same border, radius, elevation) so the two cards read as one design language. */ .ravs-pr-dialog { background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 1px 2px rgba(24,24,27,0.04); display: flex; flex-direction: column; min-width: 0; overflow: hidden; } .ravs-pr-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-pr-title-text { font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } /* Icon-only AI-assist chip — mirrors .ravs-sc-sparkle so the affordance reads identically across both cards. */ .ravs-pr-gen-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; border: 0; cursor: pointer; transition: color 160ms ease, background 160ms ease; } .ravs-pr-gen-btn:hover { background: rgba(24,24,27,0.06); color: var(--foreground, #18181b); } .ravs-pr-gen-btn.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-pr-body { display: flex; flex-direction: column; gap: 8px; padding: 10px; } .ravs-pr-field { display: flex; flex-direction: column; gap: 4px; } .ravs-pr-field-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-pr-base { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 6px; font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground, #18181b); background: var(--editor-surface, var(--card)); align-self: flex-start; } .ravs-pr-base svg { color: var(--muted-foreground, #71717a); } .ravs-pr-input { position: relative; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); min-height: 28px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pr-input.is-body { min-height: 50px; font-size: 11px; line-height: 1.4; } .ravs-pr-input .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-pr-footer { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 2px; } .ravs-pr-btn { font-size: 11px; font-weight: 500; padding: 5px 10px; border-radius: 6px; line-height: 1; border: 1px solid transparent; outline: none; } .ravs-pr-btn:focus, .ravs-pr-btn:focus-visible { outline: none; } /* Cancel reads as a quiet ghost button so it doesn't compete with the affirmative Create PR action. */ .ravs-pr-btn.is-outline { background: transparent; color: var(--muted-foreground, #71717a); border-color: transparent; } .ravs-pr-btn.is-outline:hover { background: rgba(24,24,27,0.05); color: var(--foreground, #18181b); } /* Quiet secondary fill — see the .ravs-sc-split note above. The flash ring still uses success-green so the \"PR created\" beat reads. The Create-PR button is slightly larger than Cancel so the affirmative action remains the bigger target. */ .ravs-pr-btn.is-solid { background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); border-color: var(--border); font-size: 12px; padding: 7px 14px; transition: background 220ms ease, border-color 220ms ease, color 220ms ease, box-shadow 220ms ease; } .ravs-pr-btn.is-solid.is-ready { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); } .ravs-pr-btn.is-solid.is-flash { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.30); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }"
+ }
+ }
+ }
+ },
+ "notes": {
+ "diff": {
+ "rows": {
+ "f621c734f8": "注释 · 行"
+ }
+ }
+ }
+ },
+ "agents": {
+ "orchestration": {
+ "OrchestrationPage": {
+ "30b509a467": "2名儿童",
+ "862605d066": "2 个子工作区"
+ },
+ "StatusesPage": {
+ "2f549fc0ba": "src/auth/session.test.ts",
+ "139e3d7458": "已更新",
+ "7b26349cb2": "pnpm 迁移最新",
+ "78f0318ac1": "想跑",
+ "79971d1539": "重新设计身份验证流程"
+ },
+ "UsageAccountsCard": {
+ "6986b36708": "表面利率限制和内联掉期账户。",
+ "d90d2e1f6d": "跟踪会话和每周使用情况。",
+ "8919321417": "Codex 登录失败。",
+ "c7b90c140b": "添加了 Codex 账户。",
+ "4e71d72912": "Claude 登录失败。",
+ "9ddeb558f9": "已添加 Claude 账户。",
+ "29d0653961": "登入",
+ "945865332e": "登录"
+ },
+ "UsagePage": {
+ "64265cb295": "71% 5小时",
+ "be5a165875": "切换到",
+ "277a9c65a9": "Codex 账户",
+ "4dce5ca3aa": "4d 3h后重置",
+ "05ce4ecdd3": "还剩 62%",
+ "0470aaed99": "每周",
+ "f421abf962": "会话",
+ "5e45fb1238": "更新于 1 分钟前",
+ "6a4b1d3c38": "Codex"
+ },
+ "orchestration": {
+ "cards": {
+ "da6f1f97c9": "处理中"
+ }
+ }
+ }
+ },
+ "FeatureTourWorkspaceCard": {
+ "a23ed9da7f": "codex",
+ "2f33dc932b": "claude",
+ "9220794f6a": "处理中"
+ },
+ "ReviewAnimatedVisual": {
+ "8df4d52b68": "PR视图",
+ "8ab622e4d6": "笔记"
+ }
+ },
+ "tips": {
+ "CliFeatureTipVisual": {
+ "badb4fc342": ">",
+ "22e62f3bab": "Claude Code 会话已开始"
+ },
+ "CliSkillSetupTerminal": {
+ "1953e90447": "按 Enter 为您的代理安装 Orca CLI 编排技能。",
+ "43b60ec5c3": "Orca CLI 和编排技能安装终端",
+ "84e9576dac": "技能设置",
+ "5c3aee22c0": "复制命令",
+ "5eca672aac": "复制技能安装命令",
+ "6ff813fc1d": "复制技能命令失败。",
+ "b8ad063571": "复制技能安装命令。"
+ },
+ "CmdJPaletteTipDialog": {
+ "c0bb9f869b": "设置 → 快捷键",
+ "8241897205": "随时重新绑定快捷方式"
+ },
+ "FeatureTipActions": {
+ "eb04abece8": "也许稍后"
+ },
+ "FeatureTipsModal": {
+ "c169298e4d": "完成",
+ "3c6c478462": "X 完成后,把评审任务发给它。”",
+ "298301b7a0": "工作树",
+ "864e2db28f": "当",
+ "7fc6f02099": ",并分别为每个创建 PR。",
+ "27c567a89c": "工作树",
+ "55846c7f95": "将此 PR 拆成两个",
+ "4795ac2d4a": "尝试询问:",
+ "53905bd076": "开发预览:打开技能设置终端。",
+ "1da82af45b": "Orca CLI 需要注意",
+ "ce13a742d0": "在 PATH 中注册了 `orca`。",
+ "d1a86c7eb5": "打开“设置”以完成 CLI 设置。"
+ },
+ "CmdJPaletteFeatureTipVisual": {
+ "ab94e16d44": "创建工作树“{{value0}}”",
+ "d20ccf1e61": "完成",
+ "379d776971": "打字",
+ "0418f9becc": "打开"
+ }
+ }
+ },
+ "error": {
+ "boundaries": {
+ "RecoverableRenderErrorBoundary": {
+ "55001880db": "重试",
+ "34a189ae0f": "应用程序的其余部分仍在运行。重试此表面或切换出去然后再回来。",
+ "ab855c11f4": "Orca 的这一部分遇到了错误。"
+ }
+ }
+ },
+ "emulator": {
+ "pane": {
+ "EmulatorPane": {
+ "59b08fa031": "没有连接模拟器"
+ },
+ "emulator": {
+ "device": {
+ "frame": {
+ "9406c15775": "模拟器屏幕",
+ "8f25ffaf8a": "模拟器屏幕,键盘捕获。按 Esc 键释放。",
+ "0022420df0": "手机"
+ }
+ },
+ "pane": {
+ "toolbar": {
+ "06e10d7356": "关闭模拟器",
+ "e7a0d1897e": "家",
+ "6bd8dff42a": "旋转",
+ "3d836b879c": "选择模拟器",
+ "81b3571a07": "连接",
+ "868c0f2938": "处理中…"
+ }
+ },
+ "screen": {
+ "stream": {
+ "content": {
+ "8b1a0d8694": "模拟器预览",
+ "36841af608": "流已断开连接",
+ "5f818f12ab": "正在连接模拟器...",
+ "5ee64cd44e": "模拟器屏幕"
+ }
+ }
+ },
+ "unavailable": {
+ "pane": {
+ "f630b9ca9f": "移动模拟器需要配备 Xcode 和 iOS Simulator 运行时的 Mac。在 Linux 或 Windows 上,使用物理设备或远程 Mac 构建主机。",
+ "b2c268a0b9": "移动模拟器仅适用于 macOS"
+ }
+ }
+ },
+ "use": {
+ "emulator": {
+ "frame": {
+ "stream": {
+ "f1c0179002": "流不生成帧。"
+ }
+ }
+ }
+ }
+ }
+ },
+ "editor": {
+ "ChangesModeView": {
+ "ef25ae2d09": "没有未提交的更改。",
+ "052c184f24": "此文件的文本差异不可用。",
+ "7dffb0f563": "二进制文件",
+ "54e0035b15": "加载差异..."
+ },
+ "CodeBlockCopyButton": {
+ "28921f5bf9": "已复制",
+ "1f9f4def45": "复制代码"
+ },
+ "CombinedDiffFileTree": {
+ "f984289373": "没有文件与当前过滤器匹配。",
+ "eafe1aeb53": "重置过滤器",
+ "be119cb9d1": "已查看的文件",
+ "c00020f081": "文件扩展名",
+ "cd0e0ed79e": "过滤差异文件",
+ "4cc7b83ffe": "过滤文件...",
+ "21783df79f": "折叠文件树",
+ "481e63ca52": "文件",
+ "d5ac717d65": "未提交"
+ },
+ "CombinedDiffViewer": {
+ "35cc27aeb2": "在源代码控制中",
+ "e3b9a6ce02": "更多的",
+ "1da745c551": "发送",
+ "84898c548d": "清除",
+ "88b70d0ef5": "复制",
+ "bb84b4c374": "AI 笔记",
+ "948a5fd6c8": "清晰的笔记",
+ "0f806a2ab1": "取消",
+ "80a286d8f5": "从这个工作树?",
+ "7e7ca60816": "更改的文件",
+ "b6c3b84476": "显示文件树",
+ "39f8007549": "评审冲突",
+ "39e73e7181": "被排除在此差异视图之外。",
+ "689b99f8ad": "未解决的冲突",
+ "820ec01f24": "冲突文件单独评审",
+ "fd8892b120": "没有显示任何变化",
+ "eb5f40e49c": "此差异视图排除了未解决的冲突,因为普通的双向差异管道不是冲突安全的。",
+ "45cf23b418": "无法清除笔记。",
+ "0fb870a0fe": "笔记",
+ "8ab3248fd8": "笔记",
+ "ec5053c7f5": "并排",
+ "f786fd54e1": "内联",
+ "ea08dae15b": "全部折叠",
+ "19c45cfdc0": "全部展开",
+ "982d14bfa5": "打开未提交的差异",
+ "3d909843bb": "打开分支差异",
+ "8368d256ec": "组合分支",
+ "8f68ad9ca9": "显示 {{value0}} AI {{value1}}",
+ "724a13568d": "在 {{value0}}",
+ "6094135eec": "与 {{value0}}"
+ },
+ "ConflictComponents": {
+ "f338288514": "正在加载冲突内容...",
+ "90d576adb2": "刷新",
+ "a1ce36f77d": "快照拍摄于",
+ "4be41eaafc": "未解决的冲突",
+ "c8ca989aea": "显示文件树",
+ "58ad5ad431": "关闭",
+ "28e7db4a90": "源代码控制",
+ "31931dec46": "此评审快照不再有任何未解决的实时冲突。",
+ "992145ff5a": "所有冲突均已解决",
+ "d5edd81755": "重命名自",
+ "6e459867ad": "会话本地连续性状态。 Git 不再将此文件报告为未合并。",
+ "9c2901ef8a": "下一次冲突",
+ "41d9af2e7a": "以前的冲突",
+ "55d61a0ccd": "冲突 ·",
+ "da539359b6": "对于此冲突,没有可编辑的工作树文件。"
+ },
+ "ConflictReviewFileTree": {
+ "3449521a8c": "此快照中没有冲突。",
+ "a54551c5a6": "折叠文件树",
+ "99496bab6e": "文件",
+ "496e28a932": "走了",
+ "8528a5eaf5": "已解决",
+ "69d4e210bb": "未解决"
+ },
+ "CsvViewer": {
+ "eedd0d37a7": "列",
+ "ac31d2cd60": "行",
+ "a233d55b77": "空文件"
+ },
+ "DiffNotesSendMenu": {
+ "f1aa04b5cf": "这个文件",
+ "8b87612461": "所有未发送的笔记"
+ },
+ "DiffSectionBody": {
+ "35d6afb5be": "二进制文件已更改",
+ "cef4cf0ff5": "重试",
+ "f5cf81cec2": "加载差异...",
+ "72f71f52eb": "此文件的文本差异不可用。",
+ "7ce8436458": "分支比较中此文件的文本差异不可用。",
+ "bdbf02d5df": "二进制"
+ },
+ "DiffSectionHeader": {
+ "8915726e93": "复制路径"
+ },
+ "EditorContent": {
+ "56dba34e1a": "(在源模式下编辑)",
+ "e4b074749d": "前线事项",
+ "9640d1d3db": "预览此差异的修改版本。切换到源模式以检查更改。",
+ "78541e254e": "二进制文件已更改",
+ "c88c73a0d3": "加载差异...",
+ "b9de81ba52": "二进制文件——无法显示",
+ "b2735221f5": "加载中...",
+ "8608ce4cb1": "Markdown 预览不适用于二进制文件。",
+ "37a0e81fa6": "正在加载预览...",
+ "8b1a605bae": "该文件处于冲突状态,但没有可编辑的工作树文件。",
+ "2a512bb46a": "重试",
+ "39f018b052": "无法加载文件",
+ "8a0898ae4c": "此文件的文本差异不可用。",
+ "3c6e71df22": "分支比较中此文件的文本差异不可用。",
+ "d07e4b8553": "分支",
+ "d16e037f40": "富有的"
+ },
+ "EditorPanelHeader": {
+ "fb8331694e": "打开侧面预览",
+ "4157f3cbf3": "打开 Markdown 预览",
+ "269ce4842b": "复制相对路径",
+ "7c08a1f990": "复制路径",
+ "84cdc0794b": "重命名",
+ "1bb1e226ec": "重命名文件 {{value0}}",
+ "5447c4f68f": "目录",
+ "146cb5473c": "目录可在丰富模式或预览模式下使用",
+ "e836faacfa": "切换到并排差异",
+ "94756f08ba": "切换到内联差异",
+ "c98ce191da": "此差异没有可打开的修改端文件",
+ "9b80bbe1de": "打开文件选项卡",
+ "f0fd4174b5": "打开文件选项卡以使用丰富的 Markdown 编辑",
+ "a10d9b8337": "打开文件"
+ },
+ "EditorPanelMarkdownActionsMenu": {
+ "3e0ce48c24": "导出为 PDF",
+ "561251019a": "更多操作",
+ "8c8b7f5ff5": "显示前面的内容",
+ "10c39d58c1": "隐藏前面的内容"
+ },
+ "EditorPanelShell": {
+ "e2c4dec350": "正在加载编辑器..."
+ },
+ "EditorViewToggle": {
+ "b3410cd5e0": "笔记本",
+ "e408aa9cd5": "桌子",
+ "167f45888c": "未提交的更改",
+ "4837f3f578": "变化",
+ "ac3bb87913": "编辑",
+ "0d193dc03c": "预览",
+ "aff15f94f5": "丰富的编辑器",
+ "4d6ccb7ba6": "来源"
+ },
+ "ImageDiffViewer": {
+ "a651be62b0": "修改的",
+ "57aac3979a": "原来的",
+ "fb0ae4f3c0": "无预览"
+ },
+ "ImageViewer": {
+ "3c9217f5a6": "放大",
+ "6c89c73d9f": "重置变焦",
+ "be27304574": "缩小",
+ "77bfc9b35a": "在弹出窗口中打开图像",
+ "3ef9551ba2": "正在加载预览...",
+ "d9d2944855": "无法加载文件预览"
+ },
+ "ImageViewerPopup": {
+ "0ef78475e7": "按 Esc 关闭",
+ "535f4e2b56": "关闭",
+ "9e27b2ecaf": "全尺寸图像预览"
+ },
+ "IpynbViewer": {
+ "859bf9fc21": "运行单元格",
+ "7f0d7077c6": "取消",
+ "10ed04a685": "笔记本单元在本机上从笔记本文件夹执行本地 Python。仅运行您信任的文件中的单元。",
+ "9e06ae5d36": "运行笔记本代码?",
+ "d6f37a640b": "空笔记本",
+ "8c3b21369a": "nb格式",
+ "329764e9fc": "BETA",
+ "15ec40a735": "保存笔记本",
+ "07e7d96612": "细胞",
+ "c1601b23b2": "无法渲染笔记本",
+ "66a3f7d330": "笔记本 HTML 输出",
+ "781abd6926": "删除单元格",
+ "b42f6a9547": "在下面插入 Markdown 单元格",
+ "ffc1ac2699": "在上面插入 Markdown 单元格",
+ "b4208cad7e": "在下面插入代码单元格",
+ "53b839b8a0": "在上方插入代码单元格",
+ "27e064e2db": "下移单元格",
+ "fd8ac707bc": "向上移动单元格",
+ "3e4cbf15ea": "生的",
+ "1833dbbc43": "降价",
+ "7005960d73": "代码",
+ "59b6cd874b": "代码",
+ "ba149053d5": "降价"
+ },
+ "MarkdownPreview": {
+ "e4683f70c4": "取消",
+ "d737791433": "为AI添加注释",
+ "b1bfc04034": "选定的文本",
+ "f37b98999e": "此注",
+ "2b2b31382c": "前线事项",
+ "bb629de58a": "复制备注给代理",
+ "322afab6ff": "复习笔记",
+ "0f9969a159": "跳转到第一个评论笔记",
+ "12052c639c": "关闭搜索",
+ "b42c41bd0d": "下一场比赛",
+ "1febd97f5c": "上一场比赛",
+ "ec77985138": "在 Markdown 预览中查找",
+ "517aea303b": "在预览中查找",
+ "f961e94057": "复制备注给代理",
+ "94b520a96a": "复制的注释",
+ "13f94d760c": "添加备注",
+ "ddf087d12e": "所有未发送的笔记",
+ "d652c87c91": "保存…",
+ "c5dc92cfe3": "没有结果",
+ "6c043947ae": "未找到文件:{{value0}}",
+ "759463a221": "无法打开目录:{{value0}}"
+ },
+ "MarkdownTableOfContentsPanel": {
+ "de3928b6e4": "无标题",
+ "bbe8369097": "关闭目录",
+ "4680a4b808": "折叠到 H{{value0}}",
+ "a5daadd68b": "全部展开",
+ "111e66b85d": "折叠到标题级别 {{value0}}",
+ "f3de856175": "展开所有标题级别",
+ "0dc7b2f05a": "按级别折叠",
+ "06357eea60": "目录",
+ "27d0a9c49a": "目录",
+ "65b036a6c8": "展开 {{value0}}",
+ "97ad46f11f": "折叠 {{value0}}"
+ },
+ "MarkdownTemplatePicker": {
+ "22cd94426f": "无标题.md",
+ "6e2e6c04ad": "空白降价",
+ "df667919ca": "没有匹配的模板。",
+ "22fd4890ad": "搜索模板...",
+ "7b458e0b7f": "选择 Markdown 模板。",
+ "1829437fce": "新降价"
+ },
+ "MermaidBlock": {
+ "dcc132e691": "图表错误:"
+ },
+ "MonacoEditor": {
+ "68cb83f4a7": "在选定的文本上添加注释",
+ "fd68ae03b3": "在文件中搜索"
+ },
+ "MonacoGutterContextMenu": {
+ "7b57b1b468": "复制远程 URL",
+ "2e0b1cdc05": "复制相对路径到行",
+ "4eaa991bde": "复制路径到行"
+ },
+ "NotesSendMenu": {
+ "44dc5e60a6": "发送笔记",
+ "433928cd9f": "将 {{value0}} 发送给代理"
+ },
+ "PdfFind": {
+ "cd65b1d6b0": "关闭",
+ "eeba2547a1": "下一场比赛",
+ "30de726ad0": "上一场比赛",
+ "2fc3ba0ea8": "在页面中查找...",
+ "d080ab37d6": "没有匹配项",
+ "db56fcd6d2": "{{value1}} 的 {{value0}}"
+ },
+ "PdfViewer": {
+ "3e98d500d2": "PDF预览",
+ "069ff59932": "在 PDF 中查找 ({{value0}})",
+ "2b6eb1ccd6": "放大",
+ "c0119616d6": "适合宽度",
+ "fa5d096b00": "缩小"
+ },
+ "ReviewNotesSendMenuContent": {
+ "a49800405b": "新代理",
+ "e84705f223": "活动代理会话",
+ "03378aea75": "发送注释至",
+ "f5096c6e4e": "无法向活动代理发送注释。",
+ "bb9c69a0c9": "注释已发送至活动代理。",
+ "50f7e753ea": "正在向活动代理发送注释..."
+ },
+ "RichMarkdownAnnotationOverlay": {
+ "069b5677b8": "选定的文本",
+ "6f2f3a6001": "添加评论注释"
+ },
+ "RichMarkdownCodeBlock": {
+ "232d9ed853": "已复制",
+ "c72beafc0f": "复制代码",
+ "74eab1d9b2": "YAML",
+ "5ef5605cb7": "XML",
+ "88d777bc07": "打字稿",
+ "9e384d48dc": "迅速",
+ "3009f722b9": "SQL",
+ "d01f55be57": "壳",
+ "5af8251002": "社会保障体系",
+ "e72e6b03f4": "锈",
+ "96182a2f64": "红宝石",
+ "2391f9cda9": "Python",
+ "89d6cc14fb": "美人鱼",
+ "983b9576b4": "降价",
+ "bcb236e2d8": "科特林",
+ "78eba32de4": "JSON",
+ "a209c57063": "JavaScript",
+ "36536ad539": "爪哇",
+ "8c4a3fa02d": "超文本标记语言",
+ "706fd85738": "GraphQL",
+ "edfcc64182": "去",
+ "bf6ee5caaa": "差异",
+ "026653f21f": "CSS",
+ "4daed43ae3": "C++",
+ "4227cf50fe": "重击",
+ "13822cdfda": "纯文本"
+ },
+ "RichMarkdownDocLinkMenu": {
+ "e17b987473": "↑↓ 导航↵ 选择 esc 关闭",
+ "90c5f0e1e4": "的",
+ "2aaf7d9678": "显示中",
+ "63ced7cb9b": "没有找到文件",
+ "0e8489bc11": "Markdown 文档链接",
+ "142a7d51cd": "文档"
+ },
+ "RichMarkdownErrorBoundary": {
+ "aad0998127": "重试",
+ "4a5de9f2f0": "切换到源模式,或单击“重试”以重新加载丰富视图。",
+ "dfdf1cacd4": "丰富的 Markdown 编辑器遇到了意外错误,并被重置以保持 Orca 的其余部分响应。"
+ },
+ "RichMarkdownLinkBubble": {
+ "1c99b726e0": "删除链接",
+ "cdfe166f6f": "编辑链接",
+ "bfc813e909": "打开链接",
+ "7b0b945fdc": "粘贴或输入链接..."
+ },
+ "RichMarkdownReviewNoteLayer": {
+ "f3ef92952b": "此注",
+ "9cde7ad994": "复制备注给代理",
+ "117432e2c6": "复制的注释",
+ "3ababd949d": "复习笔记"
+ },
+ "RichMarkdownReviewRailActions": {
+ "636394af72": "复制备注给代理",
+ "a807596997": "复制笔记",
+ "8aaf2c4c69": "显示评论笔记",
+ "af02dc2456": "隐藏评论注释"
+ },
+ "RichMarkdownSearchBar": {
+ "de68b75bde": "关闭搜索",
+ "f7bcecbe26": "下一场比赛",
+ "32ae8d7d57": "上一场比赛",
+ "158c645829": "在丰富的 Markdown 编辑器中查找",
+ "98b89276f3": "在丰富的编辑器中查找",
+ "a86958d508": "没有结果"
+ },
+ "RichMarkdownSlashMenu": {
+ "82c6816ff8": "没有找到块",
+ "dbdd2ad15f": "搜索块...",
+ "550189b06c": "搜索块",
+ "2e0400b958": "斜杠命令",
+ "e2e12b0e98": "成分"
+ },
+ "RichMarkdownToolbar": {
+ "e935c6b61e": "图像",
+ "6d52624712": "关联",
+ "f6a51cb9af": "引用",
+ "f97031be09": "清单",
+ "31630ed66e": "编号列表",
+ "5d1539e5a9": "项目符号列表",
+ "0bea19a988": "罢工",
+ "6b4ccf9493": "斜体",
+ "4f9e789fe0": "大胆的",
+ "cf5817d827": "标题 3",
+ "d34a2021c8": "标题 2",
+ "abb5100a3d": "标题 1",
+ "b462641ed2": "正文"
+ },
+ "UntitledFileRenameDialog": {
+ "a7dd27b0bc": "保存",
+ "949711deb4": "取消",
+ "725868c75d": "浏览文件夹",
+ "5e7f0d8a80": "文件夹选择器不可用于远程文件",
+ "30099dca46": "文件夹",
+ "2d7d39dc63": ".md",
+ "c8ac7868e6": "文件名",
+ "b6ed807cc6": "姓名",
+ "e365f3c638": "为您的 Markdown 文件命名并选择一个文件夹。",
+ "674b046582": "另存为"
+ },
+ "export": {
+ "active": {
+ "markdown": {
+ "51c4244904": "导出到 {{value0}}",
+ "d4a901e0ad": "正在导出 PDF...",
+ "eda2cea3ad": "导出 PDF 失败"
+ }
+ }
+ },
+ "markdown": {
+ "rich": {
+ "mode": {
+ "7a8ce7c7da": "只能在代码模式下编辑,因为该文件包含脚注。",
+ "2fd2b44073": "只能在代码模式下编辑,因为该文件包含引用样式链接。",
+ "57128b73e1": "只能在代码模式下编辑,因为该文件包含 HTML、JSX 或 MDX。"
+ }
+ }
+ },
+ "rich": {
+ "markdown": {
+ "editor": {
+ "click": {
+ "routing": {
+ "2d5fb9335d": "未找到文件:{{value0}}"
+ }
+ }
+ },
+ "slash": {
+ "commands": {
+ "07e1b32396": "插入纯 Unicode 表情符号。",
+ "8a30cbaeca": "表情符号",
+ "3324eb391a": "插入计算机中的图像。",
+ "572be8e524": "图像",
+ "ae7d0f3f37": "插入显示 LaTeX 数学。",
+ "6993a38ad1": "数学块",
+ "565907cf7a": "插入内联 LaTeX 数学。",
+ "2bf5544faf": "内联数学",
+ "0ed9a7b38c": "插入美人鱼栅栏块。",
+ "e516d3f6e3": "美人鱼图",
+ "67faab829b": "插入 3x3 Markdown 表格。",
+ "19ea597868": "桌子",
+ "fae45ef4d3": "插入水平线。",
+ "ae8377cf6b": "分频器",
+ "89e327e054": "插入受隔离的代码块。",
+ "624b50cf25": "代码块",
+ "972ef9aeea": "创建一个可折叠的文本部分。",
+ "f82c78a2ee": "切换文本",
+ "9a7fe896dc": "开始一个正常的段落。",
+ "58abdb9d41": "段落",
+ "d766f44867": "创建一个清单。",
+ "d0d2cdfbdb": "检查清单",
+ "c9b9e826b8": "创建一个无序列表。",
+ "56ff3237e7": "项目符号列表",
+ "8e00aba296": "创建一个有序列表。",
+ "ed4cf0ebce": "编号列表",
+ "6a3def14de": "插入块引用。",
+ "c4c775778b": "引用",
+ "4920740259": "小节标题。",
+ "30566ee962": "标题 3",
+ "45cf7ceb3f": "中节标题。",
+ "c209a116b7": "标题 2",
+ "3294a2c0cc": "创建一个带有大标题摘要的可折叠部分。",
+ "41482b15ce": "切换标题 1",
+ "570611864e": "大节标题。",
+ "e66e7f04c6": "标题 1"
+ }
+ }
+ }
+ },
+ "useContextualCopySetup": {
+ "059bfb0d94": "上下文已复制"
+ },
+ "useLocalImagePick": {
+ "175cb8b8ce": "插入图片失败。",
+ "91d835dc88": "工作树路径不可用。"
+ },
+ "useRichMarkdownReviewData": {
+ "f9d2acd6b0": "所有未发送的笔记"
+ }
+ },
+ "diff": {
+ "comments": {
+ "DiffCommentCard": {
+ "109a791e7b": "保存",
+ "bb0a55f856": "保存…",
+ "0203bed775": "取消",
+ "6978871a3d": "进行中",
+ "cce596969e": "删除注释",
+ "cad3384faa": "编辑备注",
+ "508ee678a5": "在浏览器中打开"
+ },
+ "DiffCommentPopover": {
+ "2b3ce6d394": "取消",
+ "e05063cfc1": "行 {{value0}}",
+ "c845170b3b": "行 {{value0}}-{{value1}}"
+ },
+ "useDiffCommentDecorator": {
+ "995fa28b50": "此注"
+ }
+ }
+ },
+ "dictation": {
+ "DictationController": {
+ "de136f1199": "语音错误:{{value0}}",
+ "7afff43472": "听写完成,但没有聚焦文本字段。",
+ "55127a3706": "听写失败:{{value0}}",
+ "bb7f599ee7": "打开设置",
+ "2d5b9fabf9": "麦克风访问被拒绝。在系统设置中授予访问权限,然后重新启动 Orca。",
+ "5d2c3e7ae3": "未检测到语音。"
+ }
+ },
+ "dashboard": {
+ "DashboardAgentChildDisclosure": {
+ "1b57ce9fa4": "{{value0}} {{value1}} 儿童 {{value2}}"
+ },
+ "DashboardAgentRow": {
+ "912e136cd9": "发送",
+ "a743da52ff": "展开详情",
+ "a41fb5376e": "折叠详情",
+ "5ae84475cc": "关闭",
+ "b06e13fcf7": "关闭代理",
+ "0272969e28": "发送给该代理",
+ "92a7017987": "发送",
+ "019b74d93a": "有资格的"
+ },
+ "DashboardAgentRowMessage": {
+ "0a01046763": "被打断",
+ "1ec01cef03": "被用户中断"
+ }
+ },
+ "crash": {
+ "report": {
+ "CrashReportDialog": {
+ "b4951cd27c": "发送报告",
+ "88fea8e84e": "不发送",
+ "50b00dc327": "复制详情",
+ "6d3ebe216a": "诊断文本",
+ "835037edc9": "·Orca",
+ "56a3dfa283": "无法发送崩溃报告。",
+ "8e24fe4f75": "已发送崩溃报告。",
+ "8b8473c544": "已复制崩溃报告。",
+ "b175e90213": "没有可用的崩溃报告。",
+ "765591798d": "正在检查崩溃报告..."
+ }
+ }
+ },
+ "contextual": {
+ "tours": {
+ "ContextualTourControl": {
+ "186eecc34f": "根据第一条代理消息自动命名工作区",
+ "02e8373219": "当您将此文本框留空时,会自动生成新名称。",
+ "731c5573df": "根据第一条消息自动命名"
+ },
+ "ContextualTourOverlaySurface": {
+ "4a9568f773": "返回",
+ "4f86e2a10b": "跳过导览",
+ "d974f32a83": "关闭导览",
+ "ffa4412b66": "下一步"
+ },
+ "ContextualTourProgressDots": {
+ "7734cb8ad3": "的",
+ "dcd6e6b03e": "{{value1}} 的步骤 {{value0}}"
+ },
+ "contextual": {
+ "tour": {
+ "overlay": {
+ "measurement": {
+ "38b3155418": "下一步"
+ }
+ }
+ }
+ }
+ }
+ },
+ "cmd": {
+ "j": {
+ "quick": {
+ "actions": {
+ "c884a6398e": "创建保存的终端命令。",
+ "a43ab56fc1": "添加快捷命令",
+ "54853d52a2": "删除当前工作树。",
+ "9537b910fe": "删除工作树",
+ "0b1f25f796": "启动一个新的工作树。",
+ "52ac9da671": "创建工作树",
+ "f70812764a": "在活动工作区中打开终端选项卡。",
+ "34980395d4": "新终端选项卡",
+ "f2a1b33f8d": "在活动工作区中创建一个无标题的 Markdown 文件。",
+ "25349b66fc": "新的 Markdown 文件",
+ "784812ca24": "在活动工作区中打开浏览器选项卡。",
+ "892bfa9339": "新浏览器选项卡",
+ "verbs": {
+ "newBrowser": "新浏览器",
+ "newBrowserTab": "新的浏览器选项卡",
+ "openBrowser": "打开浏览器",
+ "browserTab": "浏览器选项卡",
+ "newMarkdown": "新降价",
+ "newMarkdownFile": "新的降价文件",
+ "newMark": "新标记",
+ "newFile": "新文件",
+ "markdownFile": "降价文件",
+ "newTerminal": "新航站楼",
+ "newTerminalTab": "新的终端选项卡",
+ "newShell": "新外壳",
+ "terminalTab": "终端选项卡",
+ "createWorktree": "创建工作树",
+ "addWorktree": "添加工作树",
+ "newWorktree": "新工作树",
+ "deleteWorktree": "删除工作树",
+ "deleteCurrentWorktree": "删除当前工作树",
+ "removeWorktree": "删除工作树",
+ "trashWorktree": "垃圾工作树",
+ "addQuickCommand": "添加快捷命令",
+ "newQuickCommand": "新的快速命令"
+ }
+ }
+ }
+ }
+ },
+ "browser": {
+ "pane": {
+ "BrowserFind": {
+ "c9d5f63fdc": "关闭",
+ "5c0c02ae76": "下一场比赛",
+ "ca7aebbd7f": "上一场比赛",
+ "636a69cd66": "在页面中查找...",
+ "7baca7b1b8": "没有匹配项",
+ "fc63f336aa": "{{value1}} 的 {{value0}}"
+ },
+ "BrowserImportHintButton": {
+ "05e675fe96": "隐藏提示",
+ "77351d22f5": "浏览器设置",
+ "e0e125e074": "从文件...",
+ "0c6d254eca": "从",
+ "244266c122": "导入…",
+ "e52a955e6f": "您始终可以在“设置”>“浏览器”中找到它。",
+ "4f5ffaa6a1": "导入浏览器数据",
+ "b24fef25be": "导入",
+ "02e89014c5": "从 {{value1}}{{value2}} 导入 {{value0}} cookie。"
+ },
+ "BrowserMobileDriverOverlay": {
+ "a6914ee43f": "收回",
+ "f4ecd61552": "该选项卡由您的手机控制。收回来在桌面上使用它。",
+ "d9768ec642": "浏览器输入已暂停",
+ "20539eca03": "移动设备正在推动该浏览器的发展"
+ },
+ "BrowserPane": {
+ "1ded0d3168": "复制截图",
+ "f30d2d35a7": "截图",
+ "fa6ea61de3": "取消",
+ "c2ef0359b9": "复制内容",
+ "f2d0c22d67": "删除注释 {{value0}}",
+ "11c5084aa2": "清晰的注释",
+ "734e4343ec": "清除浏览器注释",
+ "95af781091": "向新代理发送反馈",
+ "ac39b9366b": "发送",
+ "a3508d7e6e": "{{value0}} 注释{{value1}} 准备就绪。选择另一个元素或复制所有反馈。",
+ "f796c774a4": "在上面输入 URL 即可开始浏览。",
+ "366bf5d62c": "新标签",
+ "1c78adc73d": "对外开放",
+ "da68d35f7b": "在默认浏览器中打开失败页面",
+ "93be92f8d1": "复制地址",
+ "3c085f638d": "复制失败页面 URL",
+ "c6be71329e": "刷新",
+ "781d6459ad": "重试",
+ "2fdca7df09": "关闭",
+ "8b6fab9ffa": "保存",
+ "0f41bf80c7": "在默认浏览器中打开",
+ "ec75d0c412": "打开浏览器开发工具",
+ "fc9be38f6f": "注释页面元素",
+ "fdfc7fe0ef": "抓取页面元素",
+ "a8f37f70c3": "检查页面",
+ "1b179ab561": "复制页面网址",
+ "f7ab83f7ed": "在默认浏览器中打开页面",
+ "0e080d820e": "重新加载",
+ "250a9b3e42": "向前",
+ "40edfa75cb": "返回",
+ "efb0e8f7f3": "复制链接地址",
+ "8ce4f6b12e": "在默认浏览器中打开链接",
+ "b5b87d6cbb": "在 Orca 浏览器中打开链接",
+ "87eb75f7d2": "输入有效的 http(s) 或本地主机 URL。",
+ "27d863542c": "浏览器注释",
+ "e48569ac6d": "无法访问该网站。",
+ "bbe8f15e83": "该窗格是从活动运行时服务器呈现的。",
+ "8b7e6d1f5a": "浏览器注释仅在本地浏览器选项卡中可用。",
+ "deb5293610": "浏览器注释在远程运行时不可用",
+ "90d021f2ad": "添加",
+ "0cb3bd6221": "注释意图",
+ "8f87e6c2e5": "意图",
+ "532bac48c5": "描述代理应该在这里改变什么......",
+ "d2a7092e6e": "注释评论",
+ "b472c5fe03": "添加浏览器注释",
+ "b5ba6085de": "疑问",
+ "143204e423": "改变",
+ "e7ca5a098c": "成功",
+ "d51ef37351": "复制",
+ "6f4ab3592b": "已复制",
+ "b2856516e2": "无法加载此页面",
+ "db325a7eeb": "无法到达 {{value0}}",
+ "499b31b84e": "全部复制",
+ "e72dfa268a": "注释",
+ "168350ae6a": "单击或悬停一个元素,然后按 C 进行复制或按 S 进行屏幕截图。",
+ "e852e20cea": "已复制 — 按 S 进行屏幕截图,或选择另一个元素",
+ "a5dcd0fd1d": "确认",
+ "777b5bc4ec": "单击一个元素可为代理添加反馈。",
+ "b733a91bd9": "为所选元素添加反馈。",
+ "4328a0a062": "抓取失败:{{value0}}",
+ "26615e116b": "错误",
+ "8aec5bc044": "idle",
+ "759f32af29": "正在下载",
+ "c8bc7f1f9e": "要求的",
+ "4300f38145": "从 {{value0}}{{value1}} 下载",
+ "31375046b7": "从 {{value0}} 下载",
+ "acbe79fd01": "抓取页面元素 ({{value0}})",
+ "572046436a": "远程浏览器",
+ "b313a7275b": "打开远程浏览器"
+ },
+ "BrowserToolbarMenu": {
+ "429ef481f9": "取消",
+ "64f448fb6e": "个人资料名称",
+ "67e9b9fcd6": "新的浏览器配置文件",
+ "58f2c81542": "转变",
+ "a38f217b46": "切换配置文件将重新加载此页面。任何未保存的表单数据都将丢失。",
+ "fe683eb3b4": "开关配置文件",
+ "a771c2b6c8": "浏览器设置...",
+ "ed8f54509d": "默认",
+ "e5d31de1a9": "视口尺寸",
+ "56f94f4ffa": "从文件...",
+ "eb280bfb11": "从",
+ "2293adf620": "导入 Cookie",
+ "cf7cdc67ef": "新档案...",
+ "7b838540c7": "浏览器菜单",
+ "6aa42813e4": "从 {{value1}}{{value2}} 导入 {{value0}} cookie。",
+ "a7a86702b3": "创建并切换到 {{value0}} 配置文件",
+ "4d2f9f13a7": "创建个人资料失败。",
+ "3ccd29d771": "切换到 {{value0}} 配置文件",
+ "569bce8eb1": "创建",
+ "bf648471c5": "创建中…"
+ },
+ "GrabConfirmationSheet": {
+ "314a0aaa5b": "附加到 AI",
+ "7095e98362": "复制截图",
+ "26fd87f4df": "复制",
+ "87d97bdd6d": "取消",
+ "effd75e330": "附近的环境",
+ "7d1480fbf1": "超文本标记语言",
+ "9098b118ab": "页",
+ "eb98a0971a": "”",
+ "d053db279d": "角色=",
+ "a759d8f866": "选定的元素",
+ "9c6ce0632a": "所选元素屏幕截图",
+ "50f7114f99": "附加前请先检查。捕获的页面上下文可以包括可见的站点内容。",
+ "f3575229df": "抓住",
+ "405bb315da": "无题"
+ },
+ "browser": {
+ "address": {
+ "bar": {
+ "suggestions": {
+ "87fcdd0da9": "{{value0}} 搜索"
+ }
+ }
+ }
+ }
+ }
+ },
+ "automations": {
+ "AutomationCustomCronPanel": {
+ "3e3b2c369f": "克朗表达式",
+ "e81a02d61b": "保存前输入有效的五字段 cron。",
+ "968e66d686": "输入一个五字段 cron。",
+ "cadb7b0bc9": "无效的"
+ },
+ "AutomationDetail": {
+ "007c8ad874": "迅速的",
+ "a1d52c2189": "使用范围",
+ "449fc83bf7": "Token",
+ "401f40ae79": "预计。花费",
+ "a7c312430d": "最后一次运行",
+ "2df8970cd5": "代理",
+ "e353ab9516": "预检查",
+ "620b22145e": "优雅",
+ "15ea446b93": "会话",
+ "5405a09b1f": "运行位置",
+ "2f8baf5360": "创建自",
+ "578ff46987": "下次运行",
+ "18763ded26": "日程",
+ "dbef8dc110": "此 SSH 自动化仅在 Orca 可以到达 SSH 主机时运行。如果重新连接需要交互式凭据或主机不可用,则运行将记录为已跳过。",
+ "1f6026358e": "删除自动化",
+ "d79452fb30": "恢复自动化",
+ "91a4155e95": "暂停自动化",
+ "4b1ea02d2e": "编辑自动化",
+ "2fb1605beb": "立即运行",
+ "221916d93c": "创建自动化来开始安排代理工作。",
+ "de0fedac06": "每次运行新的",
+ "51a470b966": "SSH",
+ "b09b2384fd": "已暂停",
+ "eaa02014f8": "启用"
+ },
+ "AutomationEditorDialog": {
+ "fb1896a5e7": "取消",
+ "57b722cbba": "代理",
+ "6ff66f9012": "新运行",
+ "a2e688226d": "工作树",
+ "6f9610e667": "工作树在选定的工作区中运行。新运行每次都会从所选分支创建一个新的工作区。",
+ "2c3fd9bfa1": "工作区模式帮助",
+ "b28b140eaf": "工作区",
+ "0d17f4ca8f": "选择项目",
+ "02d351877e": "项目",
+ "a4ac8fcc62": "/目标",
+ "827b25a81e": "支持技能、文件路径和内置命令,例如",
+ "6d778190b7": "每周运行依赖项审计并总结有风险的更改。",
+ "058c23cb3f": "迅速的",
+ "c4b19094c2": "日程",
+ "e46c1aa9ad": "创建",
+ "a9d9dccf77": "保存",
+ "777548c2d6": "保存更改",
+ "ff5db28639": "现存的"
+ },
+ "AutomationEditorDialogHeader": {
+ "31f9253920": "使用模板",
+ "7e35393632": "Hermes",
+ "6f309eef8d": "Orca",
+ "58f56b73d9": "自动化名称",
+ "1d9826933e": "工作日回购审计",
+ "4133d33862": "创建自动化",
+ "0a75e5e2fa": "创建爱马仕自动化",
+ "03142e7721": "编辑 Hermes 自动化",
+ "17086b48ee": "编辑自动化"
+ },
+ "AutomationMissedRunGraceField": {
+ "0f4459e91d": "48小时",
+ "adbab51feb": "24小时",
+ "ba50e2a230": "12小时",
+ "2dc9ee84d0": "3小时",
+ "521f77cd58": "1小时",
+ "e5ad263ae5": "30分钟",
+ "529dc6c0b7": "没有恩典",
+ "3d70c185c8": "如果 Orca 或执行主机在计划时间不可用,Orca 会在该窗口内变得可用时运行一次错过的事件。较旧的错过运行将被跳过。",
+ "3df53d554a": "错过运行恩典帮助",
+ "fc089e5fde": "优雅"
+ },
+ "AutomationPrecheckFields": {
+ "d2a2ac89ac": "10分钟",
+ "bf49585b3c": "5分钟",
+ "d84d3765fd": "2分钟",
+ "c820119736": "1分钟",
+ "51e28cdad9": "30秒",
+ "bb2dfb3629": "暂停",
+ "99a577306c": "gh pr list --json number -q '.[0].number'",
+ "c2a762a180": "预检查"
+ },
+ "AutomationRunHistory": {
+ "402651bfb6": "还没有运行。",
+ "9974a2b429": "状态",
+ "13988187b3": "Token",
+ "86a248187e": "花费",
+ "149c0b49c7": "工作区",
+ "8faaa00726": "跑步",
+ "53fc5f07ab": "运行历史",
+ "a00e38d1a3": "不适用",
+ "fdb3caa8fb": "已知的"
+ },
+ "AutomationRunPageFrame": {
+ "40a511bed4": "运行上下文",
+ "33741dd973": "返回跑步"
+ },
+ "AutomationSchedulePicker": {
+ "22359b186a": "上午或下午",
+ "9e677335b0": "分钟",
+ "6b802ecc99": "小时",
+ "d90981f766": "时间",
+ "6b914c5fbb": "天",
+ "233b8c94b6": "节奏",
+ "b08ccb4d06": "每小时",
+ "8cc026fd73": "每周",
+ "c3e39e17cf": "风俗"
+ },
+ "AutomationSessionField": {
+ "f3c76dce51": "重复利用",
+ "c90888ee94": "新鲜的",
+ "b675112193": "重用将未来的运行发送到之前的实时自动化会话。如果该会话结束,Orca 将开始新的会话。",
+ "4bdce31f37": "会话重用帮助",
+ "5ad314118e": "会话"
+ },
+ "AutomationsPage": {
+ "2695883141": "删除",
+ "c3a28c9793": "选择一个自动化来查看运行。",
+ "295698292f": "重新运行",
+ "0e110a3469": "跑步",
+ "bb1b2cd31e": "概述",
+ "97ff587ee3": "连接此源以检查远程配置文件中的 Hermes 自动化。",
+ "aaa007846f": "来源不可用",
+ "25060635c6": "添加新的",
+ "d207ab4c25": "从模板开始",
+ "15e0bfb13b": "删除",
+ "f4612e3f78": "编辑",
+ "2faecab10b": "立即运行",
+ "82eb6cb933": "来源",
+ "13118faadf": "未知项目",
+ "587a4b205c": "下一步",
+ "761a35834d": "自动化",
+ "73f630b49d": "取消",
+ "1b586f0e2b": "在",
+ "02a33e3204": "从",
+ "9adfab2596": "删除外部自动化",
+ "1e2e41392f": "不要再问",
+ "b264564427": "及其运行历史记录。先前运行创建的工作区不会被删除。",
+ "080dcb5fbb": "删除自动化",
+ "19a6e30eae": "刷新自动化",
+ "8d1afa8269": "添加自动化",
+ "77c2778945": "自动化",
+ "0329f9bef1": "关闭 · Esc",
+ "67c7ff795b": "关闭自动化",
+ "e1bf9b1512": "工作区不可用。",
+ "3e42a5cc1b": "SSH 连接失败。",
+ "9f2855677c": "SSH 连接。",
+ "126d726546": "外部自动化操作失败。",
+ "37288942f0": "外部自动化恢复。",
+ "77c518a34b": "外部自动化暂停。",
+ "4d7878402c": "外部自动化排队。",
+ "4c22bc9913": "外部自动化已删除。",
+ "3a4c476aa0": "无法重新运行自动化。",
+ "a1bdb57008": "自动化运行排队。",
+ "8a3226f172": "打开设置",
+ "d2a01b0b6f": "您可以在“设置”中更改此设置。",
+ "690b94da54": "下次我们将跳过此确认。",
+ "b11170a008": "无法保存自动化。",
+ "2a20596d6b": "自动化已保存。",
+ "244727e655": "自动化已更新。",
+ "77b81bc4ac": "爱马仕自动化创建。",
+ "08efc3ae12": "Hermes 自动化已更新。",
+ "e431bb85d4": "选择与此 Hermes 自动化位于同一主机上的工作区。",
+ "32534e7c9c": "保存前选择一个可用的工作区。",
+ "2360ffc956": "保存前选择已启用的代理。",
+ "6e91dab317": "保存前输入有效的高级计划。",
+ "64bdb2304f": "保存前选择支持的计划。",
+ "2430fecf53": "选择运行位置并在保存前输入提示。",
+ "7934ee0d81": "连接SSH",
+ "f93ed7a6f8": "正在连接...",
+ "8705757e27": "工作",
+ "376631ef2b": "恢复",
+ "b457436d6a": "暂停",
+ "0ae52dd760": "爱马仕",
+ "e059042585": "只读",
+ "aecdc3681f": "易于管理",
+ "8500baacb4": "外部来源",
+ "36f71740a7": "选定的工作区",
+ "cd8397cc32": "每次运行新工作区",
+ "dd0bc7a1ba": "每次运行新的",
+ "7b2e285552": "SSH 连接在此客户端中不可用。",
+ "d441032f7e": "暂停",
+ "5918020edc": "跑步"
+ },
+ "CreateFromPicker": {
+ "f061f49e3f": "搜索仓库分支...",
+ "dd3841b442": "分支来自",
+ "ef6d762538": "项目默认",
+ "e53d306056": "{{value0}}(默认)",
+ "79512f22a7": "没有找到分支。",
+ "9ce96621f4": "搜索分支..."
+ },
+ "ExternalAutomationManagers": {
+ "e02f970595": "未找到外部自动化经理。",
+ "6da3bfba4b": "发现自动化。",
+ "3d58d5b67d": "不",
+ "a42bf2b27e": "删除外部自动化",
+ "1c3bfd38fe": "恢复外部自动化",
+ "0def1693bb": "暂停外部自动化",
+ "1df491fd00": "编辑外部自动化",
+ "cc77ba88ff": "运行外部自动化",
+ "5820648765": "最后的",
+ "844f1acb72": "成立",
+ "20fd7a3a15": "下一步",
+ "c6695e6fbd": "外部自动化",
+ "5524365227": "OpenClaw",
+ "766abf833c": "Hermes",
+ "bf5f67b590": "爱马仕",
+ "e66091daf4": "运行",
+ "8e9165af08": "跑步",
+ "2b0adbce21": "已暂停",
+ "b3feba84c7": "当前",
+ "92405f1431": "不可用",
+ "dbdcec22bd": "只读",
+ "0a2d4359a8": "易于管理",
+ "330b3c32e8": "可用的",
+ "e2532150ed": "自动化",
+ "701515f010": "自动化"
+ },
+ "ExternalAutomationRunTable": {
+ "0ba9c0a95c": "下一个运行页面",
+ "52d468a0b8": "上一个运行页面",
+ "7475c0ce96": "的",
+ "be551397ca": "状态",
+ "a813df9808": "预览",
+ "d4b34feb66": "运行时间",
+ "2d4388a908": "跑步",
+ "9c080765ff": "尚未找到 Hermes 运行信息。",
+ "8ea934cacf": "正在加载运行...",
+ "d5527d8fe7": "运行",
+ "872d032d05": "跑步"
+ },
+ "HermesCronOutputView": {
+ "e27c716b43": "迅速的",
+ "4557213074": "回复",
+ "05affc68e3": "错误",
+ "88d48157fc": "默认"
+ },
+ "WorkspaceCombobox": {
+ "ee5b280eba": "未找到工作区。",
+ "8e9c8cc6b5": "搜索工作区...",
+ "66a0cd9628": "选择工作区"
+ },
+ "automation": {
+ "templates": {
+ "37571fcb16": "查找卡住的工作、陈旧的生成文件以及失败的本地验证。",
+ "8a0228bea3": "每小时排队检查",
+ "3b7281c75f": "扫描最近的工作并指出正确性、用户体验和测试覆盖率风险。",
+ "6023075b27": "每日变更回顾",
+ "513401db93": "根据当前项目状态准备每周发布风险摘要。",
+ "39ed39280a": "发布准备情况",
+ "a7fbd32ddb": "每个工作日检查依赖关系、失败的测试和有风险的开放变更。",
+ "b84757677d": "工作日回购审计",
+ "repoHealth": {
+ "category": "回购健康",
+ "name": "工作日回购审计",
+ "prompt": "检查存储库的运行状况。检查依赖项更新、失败的测试、lint/类型检查状态以及有风险的开放更改。总结调查结果并建议下一步行动。"
+ },
+ "releasePrep": {
+ "category": "发布准备",
+ "name": "发布就绪评审",
+ "prompt": "准备发布准备摘要。寻找阻碍因素、未合并的风险变更、缺少验证和文档空白。以简洁的发布/不发布建议结束。"
+ },
+ "recurringReview": {
+ "category": "定期评审",
+ "name": "每日变更回顾",
+ "prompt": "查看此工作区中的最新更改。重点关注正确性风险、用户体验回归、缺失测试和后续任务。保持报告简短且具有可操作性。"
+ },
+ "maintenance": {
+ "category": "维护",
+ "name": "每小时维护检查",
+ "prompt": "检查是否有卡住的工作、过时的生成文件、失败的验证以及任何需要人工注意的内容。仅报告需处理的问题。"
+ }
+ }
+ },
+ "external": {
+ "automation": {
+ "schedule": {
+ "display": {
+ "a8e92b815a": "时间表不可用"
+ }
+ }
+ }
+ }
+ },
+ "agent": {
+ "AgentCombobox": {
+ "19522e25ee": "管理代理",
+ "986f946354": "空白端子",
+ "579c768bde": "没有代理符合您的搜索。",
+ "48c6a5a9b4": "搜索代理...",
+ "9c6b59fe58": "设置为默认值",
+ "1b0d6965fa": "当前默认值"
+ },
+ "AgentSettingsDialog": {
+ "50cdb57c03": "管理 AI 代理、设置默认值并自定义命令。",
+ "fc0268e4ed": "代理"
+ }
+ },
+ "activity": {
+ "ActivityPrototypePage": {
+ "cf780197a1": "选择一个代理以查看其活动",
+ "e3db9892f6": "还没有活动。",
+ "1b633f5c1e": "连接端子...",
+ "8de7c5beaa": "终端不可用",
+ "866083500b": "拖动以调整大小",
+ "443690186e": "调整活动线程列表的大小",
+ "7cd632006b": "没有代理活动与这些过滤器匹配。",
+ "a2b4437bfb": "{{value0}} 活动",
+ "023ff75afe": "标记全部已读",
+ "f70e4bec47": "紧凑模式",
+ "a472a14700": "更多选择",
+ "db8a1878b5": "线程列表选项",
+ "d1a88df9a8": "仅显示未读主题",
+ "f6396e1f85": "代理",
+ "b29191b3e0": "工作树",
+ "8c3b621ddf": "项目",
+ "4a3986b200": "状态",
+ "770d458144": "对代理活动进行分组",
+ "795cbf26e2": "筛选...",
+ "4616ea39fd": "跳转到工作区",
+ "59b131fbd9": "将话题标记为未读",
+ "beb2c19173": "未读",
+ "5651b216c6": "未知项目",
+ "22b22034bc": "独立终端在活动中不可用。",
+ "afdc2139a8": "代理终端关闭。在此工作区中打开一个新终端以继续。"
+ },
+ "ActivityTitlebarControls": {
+ "f915168c8e": "未读",
+ "d6a8de3934": "代理",
+ "dc708f3eff": "紧密代理"
+ }
+ },
+ "confirmation": {
+ "dialog": {
+ "8490e5d36a": "确认",
+ "56f5c60e0c": "取消"
+ }
+ }
+ }
+ }
+}
diff --git a/src/renderer/src/i18n/supported-languages.ts b/src/renderer/src/i18n/supported-languages.ts
index 0473416d3c6..02478005585 100644
--- a/src/renderer/src/i18n/supported-languages.ts
+++ b/src/renderer/src/i18n/supported-languages.ts
@@ -4,15 +4,17 @@ import {
type SupportedUiLocale
} from '../../../shared/ui-locale'
import {
+ UI_LANGUAGE_CHINESE,
UI_LANGUAGE_ENGLISH,
+ UI_LANGUAGE_JAPANESE,
+ UI_LANGUAGE_KOREAN,
UI_LANGUAGE_SYSTEM,
type UiLanguage
} from '../../../shared/ui-language'
export const DEFAULT_LOCALE = DEFAULT_UI_LOCALE
-// Why: System vs English is not meaningful until a second locale ships (e.g. ko).
-export const SHOW_UI_LANGUAGE_SETTING = false
+export const SHOW_UI_LANGUAGE_SETTING = true
export type UiLanguageChoice = {
value: UiLanguage
@@ -21,9 +23,27 @@ export type UiLanguageChoice = {
export const UI_LANGUAGE_CHOICES: UiLanguageChoice[] = [
{ value: UI_LANGUAGE_SYSTEM, labelKey: 'settings.appearance.language.system' },
- { value: UI_LANGUAGE_ENGLISH, labelKey: 'settings.appearance.language.english' }
+ { value: UI_LANGUAGE_ENGLISH, labelKey: 'settings.appearance.language.english' },
+ { value: UI_LANGUAGE_CHINESE, labelKey: 'settings.appearance.language.chinese' },
+ { value: UI_LANGUAGE_KOREAN, labelKey: 'settings.appearance.language.korean' },
+ { value: UI_LANGUAGE_JAPANESE, labelKey: 'settings.appearance.language.japanese' }
]
+const UI_LANGUAGE_CHOICE_FALLBACKS: Record = {
+ [UI_LANGUAGE_SYSTEM]: 'System',
+ [UI_LANGUAGE_ENGLISH]: 'English',
+ [UI_LANGUAGE_CHINESE]: '中文(简体)',
+ [UI_LANGUAGE_KOREAN]: '한국어',
+ [UI_LANGUAGE_JAPANESE]: '日本語'
+}
+
+export function getUiLanguageChoiceLabel(
+ choice: UiLanguageChoice,
+ translateFn: (key: string, fallback: string) => string
+): string {
+ return translateFn(choice.labelKey, UI_LANGUAGE_CHOICE_FALLBACKS[choice.value])
+}
+
export function resolveUiLocale(language: UiLanguage): SupportedUiLocale {
return resolveRendererUiLocale(language)
}
diff --git a/src/shared/ui-language.test.ts b/src/shared/ui-language.test.ts
new file mode 100644
index 00000000000..12424f17219
--- /dev/null
+++ b/src/shared/ui-language.test.ts
@@ -0,0 +1,25 @@
+import { describe, expect, it } from 'vitest'
+
+import {
+ UI_LANGUAGE_CHINESE,
+ UI_LANGUAGE_ENGLISH,
+ UI_LANGUAGE_JAPANESE,
+ UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SYSTEM,
+ normalizeUiLanguage
+} from './ui-language'
+
+describe('normalizeUiLanguage', () => {
+ it('accepts supported language settings', () => {
+ expect(normalizeUiLanguage(UI_LANGUAGE_SYSTEM)).toBe('system')
+ expect(normalizeUiLanguage(UI_LANGUAGE_ENGLISH)).toBe('en')
+ expect(normalizeUiLanguage(UI_LANGUAGE_CHINESE)).toBe('zh')
+ expect(normalizeUiLanguage(UI_LANGUAGE_KOREAN)).toBe('ko')
+ expect(normalizeUiLanguage(UI_LANGUAGE_JAPANESE)).toBe('ja')
+ })
+
+ it('falls back unknown values to system', () => {
+ expect(normalizeUiLanguage('fr')).toBe('system')
+ expect(normalizeUiLanguage(null)).toBe('system')
+ })
+})
diff --git a/src/shared/ui-language.ts b/src/shared/ui-language.ts
index 97c4f9955ed..b77eae1b984 100644
--- a/src/shared/ui-language.ts
+++ b/src/shared/ui-language.ts
@@ -1,8 +1,24 @@
export const UI_LANGUAGE_SYSTEM = 'system'
export const UI_LANGUAGE_ENGLISH = 'en'
+export const UI_LANGUAGE_CHINESE = 'zh'
+export const UI_LANGUAGE_KOREAN = 'ko'
+export const UI_LANGUAGE_JAPANESE = 'ja'
-export type UiLanguage = typeof UI_LANGUAGE_SYSTEM | typeof UI_LANGUAGE_ENGLISH
+export type UiLanguage =
+ | typeof UI_LANGUAGE_SYSTEM
+ | typeof UI_LANGUAGE_ENGLISH
+ | typeof UI_LANGUAGE_CHINESE
+ | typeof UI_LANGUAGE_KOREAN
+ | typeof UI_LANGUAGE_JAPANESE
+
+const UI_LANGUAGE_VALUES = new Set([
+ UI_LANGUAGE_SYSTEM,
+ UI_LANGUAGE_ENGLISH,
+ UI_LANGUAGE_CHINESE,
+ UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_JAPANESE
+])
export function normalizeUiLanguage(value: unknown): UiLanguage {
- return value === UI_LANGUAGE_ENGLISH ? UI_LANGUAGE_ENGLISH : UI_LANGUAGE_SYSTEM
+ return UI_LANGUAGE_VALUES.has(value as UiLanguage) ? (value as UiLanguage) : UI_LANGUAGE_SYSTEM
}
diff --git a/src/shared/ui-locale.test.ts b/src/shared/ui-locale.test.ts
index 03815aed323..fcb4fca9970 100644
--- a/src/shared/ui-locale.test.ts
+++ b/src/shared/ui-locale.test.ts
@@ -1,25 +1,70 @@
import { describe, expect, it } from 'vitest'
import { normalizeSupportedUiLocale, resolveUiLocale, resolveRendererUiLocale } from './ui-locale'
-import { UI_LANGUAGE_ENGLISH, UI_LANGUAGE_SYSTEM } from './ui-language'
+import {
+ UI_LANGUAGE_CHINESE,
+ UI_LANGUAGE_ENGLISH,
+ UI_LANGUAGE_JAPANESE,
+ UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SYSTEM
+} from './ui-language'
describe('ui-locale', () => {
it('normalizes supported locale prefixes', () => {
expect(normalizeSupportedUiLocale('en-US')).toBe('en')
- expect(normalizeSupportedUiLocale('ko-KR')).toBe('en')
+ expect(normalizeSupportedUiLocale('zh-CN')).toBe('zh')
+ expect(normalizeSupportedUiLocale('zh-Hans')).toBe('zh')
+ expect(normalizeSupportedUiLocale('zh-SG')).toBe('zh')
+ })
+
+ it('normalizes Korean locale prefixes', () => {
+ expect(normalizeSupportedUiLocale('ko-KR')).toBe('ko')
+ expect(normalizeSupportedUiLocale('ko')).toBe('ko')
+ })
+
+ it('normalizes Japanese locale prefixes', () => {
+ expect(normalizeSupportedUiLocale('ja-JP')).toBe('ja')
+ expect(normalizeSupportedUiLocale('ja')).toBe('ja')
+ })
+
+ it('falls back unsupported locales to English', () => {
+ expect(normalizeSupportedUiLocale('fr-FR')).toBe('en')
+ })
+
+ it('does not map Traditional Chinese to Simplified yet', () => {
+ expect(normalizeSupportedUiLocale('zh-TW')).toBe('en')
+ expect(normalizeSupportedUiLocale('zh-HK')).toBe('en')
+ expect(normalizeSupportedUiLocale('zh-Hant')).toBe('en')
})
it('resolves explicit English independently of system locale', () => {
- expect(resolveUiLocale(UI_LANGUAGE_ENGLISH, 'ko-KR')).toBe('en')
+ expect(resolveUiLocale(UI_LANGUAGE_ENGLISH, 'zh-CN')).toBe('en')
})
- it('maps system locale to English until more locales ship', () => {
+ it('resolves explicit Chinese independently of system locale', () => {
+ expect(resolveUiLocale(UI_LANGUAGE_CHINESE, 'en-US')).toBe('zh')
+ })
+
+ it('resolves explicit Korean independently of system locale', () => {
+ expect(resolveUiLocale(UI_LANGUAGE_KOREAN, 'en-US')).toBe('ko')
+ })
+
+ it('resolves explicit Japanese independently of system locale', () => {
+ expect(resolveUiLocale(UI_LANGUAGE_JAPANESE, 'en-US')).toBe('ja')
+ })
+
+ it('maps system locale to the closest supported locale', () => {
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'en-GB')).toBe('en')
+ expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'zh-CN')).toBe('zh')
+ expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'ko-KR')).toBe('ko')
+ expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'ja-JP')).toBe('ja')
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'fr-FR')).toBe('en')
})
it('uses renderer system locale only for the system setting', () => {
expect(resolveRendererUiLocale(UI_LANGUAGE_ENGLISH)).toBe('en')
- expect(resolveRendererUiLocale(UI_LANGUAGE_SYSTEM)).toBe('en')
+ expect(resolveRendererUiLocale(UI_LANGUAGE_CHINESE)).toBe('zh')
+ expect(resolveRendererUiLocale(UI_LANGUAGE_KOREAN)).toBe('ko')
+ expect(resolveRendererUiLocale(UI_LANGUAGE_JAPANESE)).toBe('ja')
})
})
diff --git a/src/shared/ui-locale.ts b/src/shared/ui-locale.ts
index 2b96e92c755..c0cfd429f7c 100644
--- a/src/shared/ui-locale.ts
+++ b/src/shared/ui-locale.ts
@@ -1,12 +1,30 @@
-import { UI_LANGUAGE_ENGLISH, UI_LANGUAGE_SYSTEM, type UiLanguage } from './ui-language'
+import {
+ UI_LANGUAGE_CHINESE,
+ UI_LANGUAGE_ENGLISH,
+ UI_LANGUAGE_JAPANESE,
+ UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SYSTEM,
+ type UiLanguage
+} from './ui-language'
-export const SUPPORTED_UI_LOCALES = ['en'] as const
+export const SUPPORTED_UI_LOCALES = ['en', 'zh', 'ko', 'ja'] as const
export type SupportedUiLocale = (typeof SUPPORTED_UI_LOCALES)[number]
export const DEFAULT_UI_LOCALE: SupportedUiLocale = 'en'
+function normalizeLocaleTag(locale: string | undefined): string {
+ return (locale ?? DEFAULT_UI_LOCALE).trim().toLowerCase().replace(/_/g, '-')
+}
+
export function normalizeSupportedUiLocale(locale: string | undefined): SupportedUiLocale {
- const primary = (locale ?? DEFAULT_UI_LOCALE).split('-')[0]?.toLowerCase()
+ const tag = normalizeLocaleTag(locale)
+ const primary = tag.split('-')[0]
+ if (primary === 'zh') {
+ if (tag.startsWith('zh-tw') || tag.startsWith('zh-hk') || tag.startsWith('zh-hant')) {
+ return DEFAULT_UI_LOCALE
+ }
+ return 'zh'
+ }
return SUPPORTED_UI_LOCALES.includes(primary as SupportedUiLocale)
? (primary as SupportedUiLocale)
: DEFAULT_UI_LOCALE
@@ -19,6 +37,15 @@ export function resolveUiLocale(
if (language === UI_LANGUAGE_ENGLISH) {
return DEFAULT_UI_LOCALE
}
+ if (language === UI_LANGUAGE_CHINESE) {
+ return 'zh'
+ }
+ if (language === UI_LANGUAGE_KOREAN) {
+ return 'ko'
+ }
+ if (language === UI_LANGUAGE_JAPANESE) {
+ return 'ja'
+ }
return normalizeSupportedUiLocale(systemLocale)
}
From d7f44f48e4e7e5abe95acf6c7987e6168e556b02 Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:02:35 -0700
Subject: [PATCH 006/165] Restore slim terminal scrollbar (xterm width: 7)
(#5051)
Co-authored-by: Orca
---
.../src/lib/pane-manager/pane-lifecycle.test.ts | 7 +++++--
.../src/lib/pane-manager/pane-terminal-options.ts | 11 ++++++++---
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts b/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts
index af6fa0c2b30..c1347f16ce8 100644
--- a/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts
+++ b/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts
@@ -76,8 +76,11 @@ describe('buildDefaultTerminalOptions', () => {
expect(buildDefaultTerminalOptions().cursorInactiveStyle).toBe('outline')
})
- it('does not reserve a classic scrollbar gutter when fitting terminal columns', () => {
- expect(buildDefaultTerminalOptions().scrollbar?.width).toBe(0)
+ it('shows the slim xterm scrollbar in its reserved gutter', () => {
+ // Why: 7px gutter is an accepted ~1-column cost (VS Code reserves 14);
+ // the v1.4.51 table corruption that once forced width 0 was the ZWJ
+ // width bug, fixed separately by the Orca unicode provider.
+ expect(buildDefaultTerminalOptions().scrollbar?.width).toBe(7)
})
it('only uses inactive outline for block cursors', () => {
diff --git a/src/renderer/src/lib/pane-manager/pane-terminal-options.ts b/src/renderer/src/lib/pane-manager/pane-terminal-options.ts
index 8d44391dbf9..2be964e07b1 100644
--- a/src/renderer/src/lib/pane-manager/pane-terminal-options.ts
+++ b/src/renderer/src/lib/pane-manager/pane-terminal-options.ts
@@ -32,9 +32,14 @@ export function buildDefaultTerminalOptions(): ITerminalOptions {
macOptionClickForcesSelection: true,
drawBoldTextInBrightColors: true,
scrollbar: {
- // Why: xterm's DOM scrollbar overlays the terminal in Electron; reserving
- // gutter width in FitAddon underfits wide table/TUI output by a column.
- width: 0
+ // Why: slim VS Code-style scrollbar (VS Code uses 14). FitAddon reserves
+ // this as a gutter, costing ~1 column per pane — accepted tradeoff so the
+ // scrollbar never covers content (evidence in PR #5051). The v1.4.51
+ // table corruption #4877 fixed by zeroing this was actually the ZWJ
+ // width bug; it stays fixed by pane-terminal-unicode-provider.ts. Width
+ // also enables the overview ruler, whose border is hidden in
+ // composeActiveTerminalTheme.
+ width: 7
},
// Why: advertise kitty keyboard protocol support so CLIs that probe
// (CSI ? u) know Orca accepts enhanced key reporting. Orca still writes
From de743891fe4255bb17931e008dc6461455845029 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 19:02:52 -0400
Subject: [PATCH 007/165] Allow Claude account changes with live sessions
(#5054)
Co-authored-by: Orca
---
.../claude-accounts/live-pty-gate.test.ts | 29 +++
src/main/claude-accounts/live-pty-gate.ts | 3 -
.../runtime-auth-service.test.ts | 51 ++++
.../claude-accounts/runtime-auth-service.ts | 35 ++-
src/main/claude-accounts/service.test.ts | 242 ++++++++++++++++++
src/main/claude-accounts/service.ts | 17 +-
6 files changed, 357 insertions(+), 20 deletions(-)
create mode 100644 src/main/claude-accounts/live-pty-gate.test.ts
diff --git a/src/main/claude-accounts/live-pty-gate.test.ts b/src/main/claude-accounts/live-pty-gate.test.ts
new file mode 100644
index 00000000000..1812299c4db
--- /dev/null
+++ b/src/main/claude-accounts/live-pty-gate.test.ts
@@ -0,0 +1,29 @@
+import { afterEach, describe, expect, it } from 'vitest'
+import {
+ beginClaudeAuthSwitch,
+ endClaudeAuthSwitch,
+ isClaudeAuthSwitchInProgress,
+ markClaudePtyExited,
+ markClaudePtySpawned
+} from './live-pty-gate'
+
+describe('Claude live PTY gate', () => {
+ afterEach(() => {
+ markClaudePtyExited('live-claude-pty')
+ endClaudeAuthSwitch()
+ })
+
+ it('allows switching while Claude PTYs are live', () => {
+ markClaudePtySpawned('live-claude-pty')
+
+ beginClaudeAuthSwitch()
+
+ expect(isClaudeAuthSwitchInProgress()).toBe(true)
+ })
+
+ it('still rejects overlapping account switches', () => {
+ beginClaudeAuthSwitch()
+
+ expect(() => beginClaudeAuthSwitch()).toThrow('already in progress')
+ })
+})
diff --git a/src/main/claude-accounts/live-pty-gate.ts b/src/main/claude-accounts/live-pty-gate.ts
index dbeeb03d618..028fbc29e8c 100644
--- a/src/main/claude-accounts/live-pty-gate.ts
+++ b/src/main/claude-accounts/live-pty-gate.ts
@@ -17,9 +17,6 @@ export function beginClaudeAuthSwitch(): void {
if (switchInProgress) {
throw new Error('A Claude account switch is already in progress.')
}
- if (liveClaudePtyIds.size > 0) {
- throw new Error('Close or restart live Claude terminals before switching Claude accounts.')
- }
switchInProgress = true
}
diff --git a/src/main/claude-accounts/runtime-auth-service.test.ts b/src/main/claude-accounts/runtime-auth-service.test.ts
index 607ab7da41e..e8a072fa7df 100644
--- a/src/main/claude-accounts/runtime-auth-service.test.ts
+++ b/src/main/claude-accounts/runtime-auth-service.test.ts
@@ -2872,6 +2872,57 @@ describe('ClaudeRuntimeAuthService', () => {
expect(readFileSync(runtimeCredentialsPath, 'utf-8')).toBe(account2Credentials)
})
+ it('does not clobber unverified live runtime credentials when switching accounts', async () => {
+ const runtimeCredentialsPath = join(testState.fakeHomeDir, '.claude', '.credentials.json')
+ const account1Original = createClaudeCredentialsJson('one@example.com', 'one-original', 'org-a')
+ const unverifiedLiveCredentials = createClaudeCredentialsWithoutEmail('one-live', 'org-b')
+ const account2Credentials = createClaudeCredentialsJson('two@example.com', 'two', 'org-c')
+ const managedAuthPath1 = createManagedClaudeAuth(
+ testState.userDataDir,
+ 'account-1',
+ account1Original
+ )
+ const managedAuthPath2 = createManagedClaudeAuth(
+ testState.userDataDir,
+ 'account-2',
+ account2Credentials
+ )
+ const settings = createSettings({
+ claudeManagedAccounts: [
+ createClaudeAccount('account-1', managedAuthPath1, {
+ email: 'one@example.com',
+ organizationUuid: 'org-a'
+ }),
+ createClaudeAccount('account-2', managedAuthPath2, {
+ email: 'two@example.com',
+ organizationUuid: 'org-c'
+ })
+ ],
+ activeClaudeManagedAccountId: 'account-1'
+ })
+ const store = createStore(settings)
+
+ const { ClaudeRuntimeAuthService } = await import('./runtime-auth-service')
+ const { markClaudePtyExited, markClaudePtySpawned } = await import('./live-pty-gate')
+ const service = new ClaudeRuntimeAuthService(store as never)
+ await service.syncForCurrentSelection()
+
+ markClaudePtySpawned('live-claude-pty')
+ try {
+ writeFileSync(runtimeCredentialsPath, unverifiedLiveCredentials, 'utf-8')
+ settings.activeClaudeManagedAccountId = 'account-2'
+
+ await expect(service.syncForCurrentSelection()).rejects.toThrow(
+ 'live Claude terminal has unverified refreshed auth'
+ )
+ } finally {
+ markClaudePtyExited('live-claude-pty')
+ }
+
+ expect(readManagedCredentialsForTest('account-1', managedAuthPath1)).toBe(account1Original)
+ expect(readFileSync(runtimeCredentialsPath, 'utf-8')).toBe(unverifiedLiveCredentials)
+ })
+
it('routes refreshed Claude credentials to the matching managed account', async () => {
const runtimeCredentialsPath = join(testState.fakeHomeDir, '.claude', '.credentials.json')
const account1Original = createClaudeCredentialsJson('one@example.com', 'one-original')
diff --git a/src/main/claude-accounts/runtime-auth-service.ts b/src/main/claude-accounts/runtime-auth-service.ts
index ca2d46ac23f..90656c9f1e6 100644
--- a/src/main/claude-accounts/runtime-auth-service.ts
+++ b/src/main/claude-accounts/runtime-auth-service.ts
@@ -184,9 +184,38 @@ export class ClaudeRuntimeAuthService {
: null
if (previousAccount && previousAccount.id !== activeAccount?.id) {
if (previousManagedCredentialsJson) {
- await this.readBackRefreshedTokens(previousManagedCredentialsJson, {
- updateLastWrittenCredentialsJson: true
- })
+ const outgoingReadBackResult = await this.readBackRefreshedTokens(
+ previousManagedCredentialsJson,
+ {
+ updateLastWrittenCredentialsJson: true
+ }
+ )
+ if (
+ outgoingReadBackResult.status === 'rejected' &&
+ outgoingReadBackResult.runtimeCredentialsChanged &&
+ hasLiveClaudePtys()
+ ) {
+ if (
+ outgoingReadBackResult.runtimeCredentialsJson &&
+ this.liveRuntimeCredentialsCanUpdateActiveAccount(
+ outgoingReadBackResult.runtimeCredentialsJson,
+ previousAccount,
+ previousManagedCredentialsJson,
+ previousManagedOauthAccount
+ )
+ ) {
+ // Why: switching away while Claude is live must preserve verified
+ // token refreshes before replacing the shared runtime credentials.
+ await this.writeManagedCredentials(
+ previousAccount,
+ outgoingReadBackResult.runtimeCredentialsJson
+ )
+ } else {
+ throw new Error(
+ 'Claude account switch paused because a live Claude terminal has unverified refreshed auth.'
+ )
+ }
+ }
}
}
if (!activeAccount) {
diff --git a/src/main/claude-accounts/service.test.ts b/src/main/claude-accounts/service.test.ts
index 379a98ae758..4cbfe5bf190 100644
--- a/src/main/claude-accounts/service.test.ts
+++ b/src/main/claude-accounts/service.test.ts
@@ -586,6 +586,248 @@ describe('ClaudeAccountService credential capture', () => {
expect(settings.claudeManagedAccounts[0].email).toBe('new@example.com')
})
+ it('adds an account without switching the active Claude auth while PTYs are live', async () => {
+ setPlatform('linux')
+ tempDir = '/tmp/orca-claude-service-test'
+ rmSync(tempDir, { recursive: true, force: true })
+ const hostAuthPath = join(tempDir, 'claude-accounts', 'host-account', 'auth')
+ mkdirSync(hostAuthPath, { recursive: true })
+ let settings = {
+ claudeManagedAccounts: [
+ {
+ id: 'host-account',
+ email: 'host@example.com',
+ managedAuthPath: hostAuthPath,
+ managedAuthRuntime: 'host',
+ wslDistro: null,
+ wslLinuxAuthPath: null,
+ authMethod: 'subscription-oauth',
+ organizationUuid: null,
+ organizationName: null,
+ createdAt: 1,
+ updatedAt: 1,
+ lastAuthenticatedAt: 1
+ }
+ ],
+ activeClaudeManagedAccountId: 'host-account',
+ activeClaudeManagedAccountIdsByRuntime: { host: 'host-account', wsl: { Ubuntu: null } }
+ }
+ const store = {
+ getSettings: vi.fn(() => settings),
+ updateSettings: vi.fn((updates: Partial) => {
+ settings = { ...settings, ...updates }
+ return settings
+ })
+ }
+ const runtimeAuth = {
+ clearLastWrittenCredentialsJson: vi.fn(),
+ syncForCurrentSelection: vi.fn(async () => {}),
+ forceMaterializeCurrentSelectionForRollback: vi.fn(async () => {})
+ }
+ const rateLimits = {
+ evictInactiveClaudeCache: vi.fn(),
+ refreshForClaudeAccountChange: vi.fn(async () => ({ accounts: [], activeAccountId: null }))
+ }
+ const { ClaudeAccountService } = await import('./service')
+ const { markClaudePtyExited, markClaudePtySpawned } = await import('./live-pty-gate')
+ const service = new ClaudeAccountService(
+ store as never,
+ rateLimits as never,
+ runtimeAuth as never
+ )
+ ;(
+ service as unknown as {
+ runClaudeLoginAndCapture(): Promise<{
+ credentialsJson: string
+ oauthAccount: unknown
+ identity: { email: string; organizationUuid: null; organizationName: null }
+ }>
+ }
+ ).runClaudeLoginAndCapture = vi.fn(async () => ({
+ credentialsJson: '{"new":true}\n',
+ oauthAccount: { newOauth: true },
+ identity: { email: 'new@example.com', organizationUuid: null, organizationName: null }
+ }))
+
+ markClaudePtySpawned('live-claude-pty')
+ try {
+ await service.addAccount({ runtime: 'host' })
+ } finally {
+ markClaudePtyExited('live-claude-pty')
+ }
+
+ expect(settings.claudeManagedAccounts).toHaveLength(2)
+ expect(settings.claudeManagedAccounts[1].email).toBe('new@example.com')
+ expect(settings.activeClaudeManagedAccountId).toBe('host-account')
+ expect(settings.activeClaudeManagedAccountIdsByRuntime).toEqual({
+ host: 'host-account',
+ wsl: { Ubuntu: null }
+ })
+ expect(runtimeAuth.syncForCurrentSelection).not.toHaveBeenCalled()
+ expect(rateLimits.refreshForClaudeAccountChange).not.toHaveBeenCalled()
+ expect(rateLimits.evictInactiveClaudeCache).toHaveBeenCalledWith(
+ settings.claudeManagedAccounts[1].id
+ )
+ })
+
+ it('switches the active Claude account while PTYs are live', async () => {
+ setPlatform('linux')
+ tempDir = '/tmp/orca-claude-service-test'
+ rmSync(tempDir, { recursive: true, force: true })
+ const firstAuthPath = join(tempDir, 'claude-accounts', 'account-1', 'auth')
+ const secondAuthPath = join(tempDir, 'claude-accounts', 'account-2', 'auth')
+ mkdirSync(firstAuthPath, { recursive: true })
+ mkdirSync(secondAuthPath, { recursive: true })
+ let settings = {
+ claudeManagedAccounts: [
+ {
+ id: 'account-1',
+ email: 'first@example.com',
+ managedAuthPath: firstAuthPath,
+ managedAuthRuntime: 'host',
+ wslDistro: null,
+ wslLinuxAuthPath: null,
+ authMethod: 'subscription-oauth',
+ organizationUuid: null,
+ organizationName: null,
+ createdAt: 1,
+ updatedAt: 1,
+ lastAuthenticatedAt: 1
+ },
+ {
+ id: 'account-2',
+ email: 'second@example.com',
+ managedAuthPath: secondAuthPath,
+ managedAuthRuntime: 'host',
+ wslDistro: null,
+ wslLinuxAuthPath: null,
+ authMethod: 'subscription-oauth',
+ organizationUuid: null,
+ organizationName: null,
+ createdAt: 2,
+ updatedAt: 2,
+ lastAuthenticatedAt: 2
+ }
+ ],
+ activeClaudeManagedAccountId: 'account-1',
+ activeClaudeManagedAccountIdsByRuntime: { host: 'account-1', wsl: {} }
+ }
+ const store = {
+ getSettings: vi.fn(() => settings),
+ updateSettings: vi.fn((updates: Partial) => {
+ settings = { ...settings, ...updates }
+ return settings
+ })
+ }
+ const runtimeAuth = {
+ syncForCurrentSelection: vi.fn(async () => {}),
+ forceMaterializeCurrentSelectionForRollback: vi.fn(async () => {})
+ }
+ const rateLimits = {
+ refreshForClaudeAccountChange: vi.fn(async () => ({ accounts: [], activeAccountId: null }))
+ }
+ const { ClaudeAccountService } = await import('./service')
+ const { markClaudePtyExited, markClaudePtySpawned } = await import('./live-pty-gate')
+ const service = new ClaudeAccountService(
+ store as never,
+ rateLimits as never,
+ runtimeAuth as never
+ )
+
+ markClaudePtySpawned('live-claude-pty')
+ try {
+ await service.selectAccount('account-2')
+ } finally {
+ markClaudePtyExited('live-claude-pty')
+ }
+
+ expect(settings.activeClaudeManagedAccountId).toBe('account-2')
+ expect(settings.activeClaudeManagedAccountIdsByRuntime).toEqual({
+ host: 'account-2',
+ wsl: {}
+ })
+ expect(runtimeAuth.syncForCurrentSelection).toHaveBeenCalledWith({ runtime: 'host' })
+ expect(rateLimits.refreshForClaudeAccountChange).toHaveBeenCalledWith('account-1', {
+ runtime: 'host'
+ })
+ })
+
+ it('restores the previous selection when a Claude account switch fails', async () => {
+ setPlatform('linux')
+ tempDir = '/tmp/orca-claude-service-test'
+ rmSync(tempDir, { recursive: true, force: true })
+ const firstAuthPath = join(tempDir, 'claude-accounts', 'account-1', 'auth')
+ const secondAuthPath = join(tempDir, 'claude-accounts', 'account-2', 'auth')
+ mkdirSync(firstAuthPath, { recursive: true })
+ mkdirSync(secondAuthPath, { recursive: true })
+ let settings = {
+ claudeManagedAccounts: [
+ {
+ id: 'account-1',
+ email: 'first@example.com',
+ managedAuthPath: firstAuthPath,
+ managedAuthRuntime: 'host',
+ wslDistro: null,
+ wslLinuxAuthPath: null,
+ authMethod: 'subscription-oauth',
+ organizationUuid: null,
+ organizationName: null,
+ createdAt: 1,
+ updatedAt: 1,
+ lastAuthenticatedAt: 1
+ },
+ {
+ id: 'account-2',
+ email: 'second@example.com',
+ managedAuthPath: secondAuthPath,
+ managedAuthRuntime: 'host',
+ wslDistro: null,
+ wslLinuxAuthPath: null,
+ authMethod: 'subscription-oauth',
+ organizationUuid: null,
+ organizationName: null,
+ createdAt: 2,
+ updatedAt: 2,
+ lastAuthenticatedAt: 2
+ }
+ ],
+ activeClaudeManagedAccountId: 'account-1',
+ activeClaudeManagedAccountIdsByRuntime: { host: 'account-1', wsl: {} }
+ }
+ const store = {
+ getSettings: vi.fn(() => settings),
+ updateSettings: vi.fn((updates: Partial) => {
+ settings = { ...settings, ...updates }
+ return settings
+ })
+ }
+ const runtimeAuth = {
+ syncForCurrentSelection: vi.fn(async () => {
+ throw new Error('unverified live auth')
+ }),
+ forceMaterializeCurrentSelectionForRollback: vi.fn(async () => {})
+ }
+ const rateLimits = {
+ refreshForClaudeAccountChange: vi.fn(async () => ({ accounts: [], activeAccountId: null }))
+ }
+ const { ClaudeAccountService } = await import('./service')
+ const service = new ClaudeAccountService(
+ store as never,
+ rateLimits as never,
+ runtimeAuth as never
+ )
+
+ await expect(service.selectAccount('account-2')).rejects.toThrow('unverified live auth')
+
+ expect(settings.activeClaudeManagedAccountId).toBe('account-1')
+ expect(settings.activeClaudeManagedAccountIdsByRuntime).toEqual({
+ host: 'account-1',
+ wsl: {}
+ })
+ expect(runtimeAuth.forceMaterializeCurrentSelectionForRollback).toHaveBeenCalled()
+ expect(rateLimits.refreshForClaudeAccountChange).not.toHaveBeenCalled()
+ })
+
it('selects a WSL account without changing the Windows active account', async () => {
setPlatform('linux')
tempDir = '/tmp/orca-claude-service-test'
diff --git a/src/main/claude-accounts/service.ts b/src/main/claude-accounts/service.ts
index 49c6f0f1a5c..e225f93263f 100644
--- a/src/main/claude-accounts/service.ts
+++ b/src/main/claude-accounts/service.ts
@@ -156,24 +156,13 @@ export class ClaudeAccountService {
}
const selection = normalizeClaudeRuntimeSelection(previousSettings)
- const targetSelection = getClaudeSelectionTargetForAccount(account)
- const outgoingAccountId = getSelectedClaudeAccountIdForTarget(
- previousSettings,
- targetSelection
- )
this.store.updateSettings({
claudeManagedAccounts: [...previousSettings.claudeManagedAccounts, account],
- activeClaudeManagedAccountId:
- targetSelection.runtime === 'host' ? account.id : selection.host,
- activeClaudeManagedAccountIdsByRuntime: setSelectedClaudeAccountIdForTarget(
- selection,
- account.id,
- targetSelection
- )
+ activeClaudeManagedAccountId: selection.host,
+ activeClaudeManagedAccountIdsByRuntime: selection
})
this.runtimeAuth.clearLastWrittenCredentialsJson(accountId)
- await this.syncRuntimeAuthWithLivePtyGate(targetSelection)
- await this.rateLimits.refreshForClaudeAccountChange(outgoingAccountId, targetSelection)
+ this.rateLimits.evictInactiveClaudeCache(accountId)
return this.getSnapshot()
} catch (error) {
this.restoreClaudeSettings(previousSettings)
From 442c16a3577a13fa67eba5a228cfdde34760be41 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:03:01 -0700
Subject: [PATCH 008/165] Add Project modal: roving keyboard selection (#5052)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Make Add Project highlight a roving keyboard selection
The Add Project modal previously rendered Browse folder as a permanently
filled "primary" card with a static ⏎ chip. Turn that white fill + ⏎ chip
into a roving selection indicator driven by keyboard focus: Browse starts
selected (it is autofocused on open), and Tab or ↑/↓ move the highlight —
and the ⏎ chip — to whichever action is focused, so Enter's target is always
the highlighted row.
Also flatten the unselected Browse card's surface to bg-background so it
matches the secondary rows instead of showing the outline variant's lighter
tinted/shadowed surface.
ShortcutKeyCombo gains an optional keyCapClassName so the ⏎ chip can tint
itself for the filled surface.
Co-authored-by: Orca
* Drop focus ring on selected Browse card so it stays borderless
The primary Browse card uses the Button component, whose base styles always
draw a focus-visible border + ring. Because Browse is autofocused-and-selected
on open, that ring rendered as a border on only the top card, unlike the
filled secondary rows. Suppress the ring on the selected state (the fill + ⏎
chip already indicate focus, since focus drives selection) and add a
transparent border to hold the box size steady across the outline↔default swap.
Co-authored-by: Orca
* Fix add project action selection accessibility
Co-authored-by: Orca
* Refine add project action outlines
Co-authored-by: Orca
---------
Co-authored-by: Orca
---
.../src/components/ShortcutKeyCombo.tsx | 16 +-
.../sidebar/AddRepoStartSteps.test.tsx | 144 ++++++++++++--
.../components/sidebar/AddRepoStartSteps.tsx | 180 +++++++++++++++---
src/renderer/src/i18n/locales/en.json | 2 +-
4 files changed, 299 insertions(+), 43 deletions(-)
diff --git a/src/renderer/src/components/ShortcutKeyCombo.tsx b/src/renderer/src/components/ShortcutKeyCombo.tsx
index 1f231b9b7f5..8ec8c3a34bf 100644
--- a/src/renderer/src/components/ShortcutKeyCombo.tsx
+++ b/src/renderer/src/components/ShortcutKeyCombo.tsx
@@ -1,9 +1,14 @@
import React from 'react'
import { cn } from '@/lib/utils'
-function KeyCap({ label }: { label: string }): React.JSX.Element {
+function KeyCap({ label, className }: { label: string; className?: string }): React.JSX.Element {
return (
-
+
{label}
)
@@ -13,12 +18,15 @@ type ShortcutKeyComboProps = {
keys: string[]
className?: string
separatorClassName?: string
+ // Override cap colors when chips sit on a non-default surface (e.g. a filled primary card).
+ keyCapClassName?: string
}
export function ShortcutKeyCombo({
keys,
className,
- separatorClassName
+ separatorClassName,
+ keyCapClassName
}: ShortcutKeyComboProps): React.JSX.Element {
const isMac = navigator.userAgent.includes('Mac')
@@ -26,7 +34,7 @@ export function ShortcutKeyCombo({
{keys.map((key, index) => (
-
+
{/* Why: Orca renders Mac shortcuts as adjacent glyphs, but Windows/Linux
shortcuts read more naturally with explicit "+" separators. */}
{!isMac && index < keys.length - 1 ? (
diff --git a/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx b/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx
index 10e3ff8ed9c..ace7b22bc85 100644
--- a/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx
@@ -51,7 +51,17 @@ function renderServerPathStartStep(runtimeEnvironmentId: string | null): string
)
}
-async function renderLocalStartStepDom(isSshLikely: boolean): Promise<{
+type LocalStartStepDomOptions = {
+ isAdding?: boolean
+ addProjectBusyLabel?: string | null
+ nestedScanInProgress?: boolean
+ nestedScanId?: string | null
+}
+
+async function renderLocalStartStepDom(
+ isSshLikely: boolean,
+ options: LocalStartStepDomOptions = {}
+): Promise<{
container: HTMLDivElement
root: Root
}> {
@@ -61,19 +71,21 @@ async function renderLocalStartStepDom(isSshLikely: boolean): Promise<{
await act(async () => {
root.render(
-
+
+
+
)
})
@@ -120,7 +132,7 @@ describe('AddRepoLocalStartStep', () => {
expect(markup).toContain('Clone from URL')
expect(markup).toContain('Remote project')
expect(markup).toContain('Create new project')
- expect(markup).toContain('Or add from')
+ expect(markup).toContain('Other ways to add')
expect(markup).not.toContain('More options')
})
@@ -182,6 +194,108 @@ describe('AddRepoLocalStartStep', () => {
root.unmount()
})
})
+
+ it('marks the autofocused Browse action as selected with the ⏎ chip', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+
+ expect(findButton(container, 'Browse folder').textContent).toContain('⏎')
+ expect(findButton(container, 'Clone from URL').textContent).not.toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('moves the ⏎ selection to whichever action receives focus', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+ const cloneButton = findButton(container, 'Clone from URL')
+
+ await act(async () => {
+ cloneButton.focus()
+ })
+
+ expect(findButton(container, 'Clone from URL').textContent).toContain('⏎')
+ expect(findButton(container, 'Browse folder').textContent).not.toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('clears the ⏎ selection when focus leaves the action list', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+ const outsideButton = document.createElement('button')
+ document.body.appendChild(outsideButton)
+
+ await act(async () => {
+ outsideButton.focus()
+ })
+
+ expect(document.activeElement).toBe(outsideButton)
+ expect(findButton(container, 'Browse folder').textContent).not.toContain('⏎')
+ expect(findButton(container, 'Clone from URL').textContent).not.toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('does not show an ⏎ selection while add actions are busy', async () => {
+ const { container, root } = await renderLocalStartStepDom(false, {
+ isAdding: true,
+ addProjectBusyLabel: 'Scanning repositories',
+ nestedScanInProgress: true,
+ nestedScanId: 'scan-1'
+ })
+ const stopScanButton = container.querySelector(
+ 'button[aria-label="Stop scan"]'
+ )
+
+ await act(async () => {
+ stopScanButton?.focus()
+ })
+
+ expect(document.activeElement).toBe(stopScanButton)
+ expect(findButton(container, 'Browse folder').textContent).not.toContain('⏎')
+ expect(findButton(container, 'Clone from URL').textContent).not.toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('hides the visual ⏎ chip from assistive technology', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+ const browseButton = findButton(container, 'Browse folder')
+ const enterChip = Array.from(browseButton.querySelectorAll('[aria-hidden="true"]')).find(
+ (entry) => entry.textContent?.includes('⏎')
+ )
+
+ expect(enterChip).toBeTruthy()
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('roves selection down the action list with the ArrowDown key', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+
+ await act(async () => {
+ findButton(container, 'Browse folder').dispatchEvent(
+ new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true })
+ )
+ })
+
+ // ArrowDown from Browse moves focus — and the ⏎ chip — to the first secondary action.
+ const firstSecondary = findButton(container, 'Clone from URL')
+ expect(document.activeElement).toBe(firstSecondary)
+ expect(firstSecondary.textContent).toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
})
describe('AddRepoServerPathStartStep', () => {
diff --git a/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx b/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
index bfa8f5486e3..01e26e0b0df 100644
--- a/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
@@ -1,7 +1,8 @@
-import { useEffect, useRef, type ComponentType, type Ref } from 'react'
+import { useEffect, useRef, useState, type ComponentType, type Ref } from 'react'
import { CircleStop, Loader2 } from 'lucide-react'
import { DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
+import { ShortcutKeyCombo } from '@/components/ShortcutKeyCombo'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils'
import { getAddRepoLocalStartActions } from './add-repo-local-start-actions'
@@ -32,8 +33,14 @@ function AddRepoNestedScanProgressNotice({
variant="ghost"
size="icon-xs"
className="group text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive focus-visible:ring-destructive/40"
- aria-label={translate("auto.components.sidebar.AddRepoStartSteps.9906cae183", "Stop scan")}
- title={translate("auto.components.sidebar.AddRepoStartSteps.69ea7f8dc4", "Stop scanning")}
+ aria-label={translate(
+ 'auto.components.sidebar.AddRepoStartSteps.9906cae183',
+ 'Stop scan'
+ )}
+ title={translate(
+ 'auto.components.sidebar.AddRepoStartSteps.69ea7f8dc4',
+ 'Stop scanning'
+ )}
onClick={onStopNestedScan}
>
@@ -41,7 +48,11 @@ function AddRepoNestedScanProgressNotice({
- {translate("auto.components.sidebar.AddRepoStartSteps.d301db1c9a", "Scanning repositories. Click to stop.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoStartSteps.d301db1c9a',
+ 'Scanning repositories. Click to stop.'
+ )}
+
) : null}
@@ -76,6 +87,7 @@ export function AddRepoLocalStartStep({
onStopNestedScan
}: AddRepoLocalStartStepProps): React.JSX.Element {
const browseActionRef = useRef(null)
+ const actionsRef = useRef(null)
const { primaryAction, secondaryActions } = getAddRepoLocalStartActions({
isSshLikely,
onBrowse,
@@ -84,37 +96,91 @@ export function AddRepoLocalStartStep({
onOpenCreateStep
})
+ // The white fill + ⏎ chip is a roving selection indicator, not a fixed "primary" badge:
+ // it follows keyboard focus so Enter always activates the highlighted action. Browse is
+ // autofocused on open, so it starts selected; Tab and ↑/↓ move the highlight.
+ const [selectedKind, setSelectedKind] = useState(primaryAction.kind)
+
useEffect(() => {
+ if (isAdding) {
+ setSelectedKind(null)
+ return
+ }
if (!isAdding) {
browseActionRef.current?.focus()
}
}, [isAdding])
+ // ↑/↓ rove focus across the action buttons in visual order; focus drives the selection.
+ const handleArrowNavigation = (event: React.KeyboardEvent): void => {
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
+ return
+ }
+ const buttons = Array.from(
+ actionsRef.current?.querySelectorAll('button[data-add-repo-action]') ?? []
+ )
+ if (buttons.length === 0) {
+ return
+ }
+ const currentIndex = buttons.findIndex((button) => button === document.activeElement)
+ const delta = event.key === 'ArrowDown' ? 1 : -1
+ const nextIndex = (currentIndex + delta + buttons.length) % buttons.length
+ event.preventDefault()
+ buttons[nextIndex]?.focus()
+ }
+
+ const handleActionsBlur = (event: React.FocusEvent): void => {
+ if (!(event.relatedTarget instanceof HTMLButtonElement)) {
+ setSelectedKind(null)
+ return
+ }
+ if (!event.relatedTarget.matches('button[data-add-repo-action]')) {
+ setSelectedKind(null)
+ }
+ }
+
return (
<>
- {translate("auto.components.sidebar.AddRepoStartSteps.d13757911c", "Add a project")}
+
+ {translate('auto.components.sidebar.AddRepoStartSteps.d13757911c', 'Add a project')}
+
{repoCount === 0 ? (
- {translate("auto.components.sidebar.AddRepoStartSteps.acf895cb42", "Add a project to get started with Orca.")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoStartSteps.acf895cb42',
+ 'Add a project to get started with Orca.'
+ )}
+
) : null}
-
+
setSelectedKind(primaryAction.kind)}
/>
{/* Keep secondary entry methods always visible so they stay discoverable without an extra click. */}
{/* Label clarifies the lighter-weight rows are alternate entry methods, not lesser features. */}
-
{translate("auto.components.sidebar.AddRepoStartSteps.f3c96237ae", "Or add from…")}
- {/* Match the primary card's surface (bg-background) so the group reads as the same family, not a recessed panel. */}
-
+
+ {translate('auto.components.sidebar.AddRepoStartSteps.87596c1446', 'Other ways to add')}
+
+ {/* Outline uses the `input` token (white-ish in dark mode) to match Browse's visible outline variant;
+ primary-foreground is near-black in dark mode and rendered the border invisible. */}
+
{secondaryActions.map((action, index) => (
setSelectedKind(action.kind)}
className={index === 0 ? '' : 'border-t border-border/70'}
/>
))}
@@ -147,35 +215,73 @@ type AddRepoStartActionProps = {
title: string
description: string
disabled: boolean
+ // Selected = keyboard-focused: renders the white fill + trailing ⏎ chip so Enter's target is obvious.
+ selected: boolean
onClick: () => void
+ onFocus: () => void
buttonRef?: Ref
}
+// Shared trailing chip so the ⏎ glyph travels with the selected action across primary and secondary rows.
+const AddRepoEnterChip = (): React.JSX.Element => (
+
+
+
+)
+
const AddRepoPrimaryStartAction = ({
icon: Icon,
title,
description,
disabled,
+ selected,
onClick,
+ onFocus,
buttonRef
}: AddRepoStartActionProps): React.JSX.Element => (
+ // Filled white surface marks the selected action; when unselected the card reverts to a quiet
+ // outline so the highlight reads as a moving selection, not a fixed badge. Inner tints switch to
+ // primary-foreground only while filled, because muted tokens are tuned for the dark base surface.
-
-
+
+
-
- {title}
-
+
+ {title}
+
{description}
+ {selected ? : null}
)
@@ -184,26 +290,54 @@ function AddRepoSecondaryStartAction({
title,
description,
disabled,
+ selected,
onClick,
+ onFocus,
className
}: AddRepoStartActionProps & { className?: string }): React.JSX.Element {
return (
-
+
-
- {title}
- {description}
+
+
+ {title}
+
+
+ {description}
+
+ {selected ? : null}
)
}
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index 3d82c034bd5..c81955e74e8 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -3030,7 +3030,7 @@
"0f8aba944c": "Navigate to a directory and click Select to choose it."
},
"AddRepoStartSteps": {
- "f3c96237ae": "Or add from…",
+ "87596c1446": "Other ways to add",
"acf895cb42": "Add a project to get started with Orca.",
"d13757911c": "Add a project",
"d301db1c9a": "Scanning repositories. Click to stop.",
From 3f39912a9a2408aab694c1e811b91637edd4a4e5 Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:03:20 -0700
Subject: [PATCH 009/165] Preserve floating workspace state after restart
(#5047)
* Preserve floating workspace state during restart purge
* rm doc
---
.../src/store/slices/worktrees.test.ts | 263 ++++++++++++++++++
src/renderer/src/store/slices/worktrees.ts | 9 +-
2 files changed, 270 insertions(+), 2 deletions(-)
diff --git a/src/renderer/src/store/slices/worktrees.test.ts b/src/renderer/src/store/slices/worktrees.test.ts
index 3e595b5a56c..6e997a744d7 100644
--- a/src/renderer/src/store/slices/worktrees.test.ts
+++ b/src/renderer/src/store/slices/worktrees.test.ts
@@ -88,6 +88,7 @@ import {
registerPersistentWebview,
unregisterPersistentWebview
} from '../../components/browser-pane/webview-registry'
+import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../../shared/constants'
function resetRemoteRuntimeMocks() {
clearRuntimeCompatibilityCacheForTests()
@@ -3097,6 +3098,117 @@ describe('fetchAllWorktrees hydration-time purge (design §4.4)', () => {
expect(mockApi.worktrees.list).toHaveBeenCalledTimes(4)
expect(store.getState().tabsByWorktree['repoA::/a/new-zombie']).toBeDefined()
})
+
+ it('preserves floating workspace state while purging a real stale worktree', async () => {
+ const store = createTestStore()
+ const wtA = makeWorktree({ id: 'repoA::/a/wt1', repoId: 'repoA', path: '/a/wt1' })
+ const wtB = makeWorktree({ id: 'repoB::/b/wt1', repoId: 'repoB', path: '/b/wt1' })
+ const staleId = 'repoA::/a/zombie'
+ const floatingFile = {
+ id: 'floating-file',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ filePath: '/floating/note.md',
+ relativePath: 'note.md',
+ language: 'markdown',
+ isDirty: false,
+ isPreview: false,
+ mode: 'edit' as const
+ }
+
+ mockApi.worktrees.list.mockImplementation(async ({ repoId }: { repoId: string }) =>
+ repoId === 'repoA' ? [wtA] : [wtB]
+ )
+
+ store.setState({
+ repos: [repoA, repoB],
+ activeWorktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ activeFileId: 'floating-file',
+ activeTabId: 'floating-terminal-tab',
+ activeTabType: 'editor' as const,
+ tabsByWorktree: {
+ [wtA.id]: [{ id: 'tab-A', worktreeId: wtA.id }],
+ [staleId]: [{ id: 'tab-zombie', worktreeId: staleId }],
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ { id: 'floating-terminal-tab', worktreeId: FLOATING_TERMINAL_WORKTREE_ID }
+ ]
+ },
+ browserTabsByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [{ id: 'floating-browser', url: 'https://orca.test' }]
+ },
+ activeBrowserTabIdByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: 'floating-browser'
+ },
+ openFiles: [
+ floatingFile,
+ {
+ id: 'stale-file',
+ worktreeId: staleId,
+ filePath: '/a/zombie/stale.ts',
+ relativePath: 'stale.ts',
+ language: 'typescript',
+ isDirty: false,
+ isPreview: false,
+ mode: 'edit' as const
+ }
+ ],
+ activeFileIdByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: 'floating-file',
+ [staleId]: 'stale-file'
+ },
+ unifiedTabsByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ {
+ id: 'floating-unified-tab',
+ type: 'editor',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ fileId: 'floating-file'
+ }
+ ],
+ [staleId]: [{ id: 'stale-unified-tab', worktreeId: staleId }]
+ },
+ groupsByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ {
+ id: 'floating-group',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ activeTabId: 'floating-unified-tab'
+ }
+ ],
+ [staleId]: [{ id: 'stale-group', worktreeId: staleId, activeTabId: 'stale-unified-tab' }]
+ },
+ layoutByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: { type: 'leaf', groupId: 'floating-group' },
+ [staleId]: { type: 'leaf', groupId: 'stale-group' }
+ }
+ } as unknown as Partial)
+
+ await store.getState().fetchAllWorktrees()
+
+ expect(store.getState().hasHydratedWorktreePurge).toBe(true)
+ expect(store.getState().tabsByWorktree).toEqual({
+ [wtA.id]: [{ id: 'tab-A', worktreeId: wtA.id }],
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ { id: 'floating-terminal-tab', worktreeId: FLOATING_TERMINAL_WORKTREE_ID }
+ ]
+ })
+ expect(store.getState().browserTabsByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toEqual([
+ { id: 'floating-browser', url: 'https://orca.test' }
+ ])
+ expect(store.getState().openFiles).toEqual([floatingFile])
+ expect(store.getState().activeFileIdByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toBe(
+ 'floating-file'
+ )
+ expect(store.getState().unifiedTabsByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toHaveLength(1)
+ expect(store.getState().groupsByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toHaveLength(1)
+ expect(store.getState().layoutByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toEqual({
+ type: 'leaf',
+ groupId: 'floating-group'
+ })
+ expect(store.getState().activeWorktreeId).toBe(FLOATING_TERMINAL_WORKTREE_ID)
+ expect(store.getState().activeFileId).toBe('floating-file')
+ expect(store.getState().activeTabId).toBe('floating-terminal-tab')
+ expect(store.getState().activeTabType).toBe('editor')
+ })
})
// Why: design §4.4 — purgeWorktreeTerminalState wipes every worktree-scoped
@@ -3196,6 +3308,157 @@ describe('purgeWorktreeTerminalState direct (design §4.4)', () => {
expect(store.getState().tabsByWorktree).toBe(before)
})
+
+ it('ignores the floating workspace sentinel while purging mixed real ids', () => {
+ const store = createTestStore()
+ const staleId = 'repoA::/a/wt1'
+ const floatingFile = {
+ id: 'floating-file',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ filePath: '/floating/note.md',
+ relativePath: 'note.md',
+ language: 'markdown',
+ isDirty: false,
+ isPreview: false,
+ mode: 'edit' as const
+ }
+
+ store.setState({
+ tabsByWorktree: {
+ [staleId]: [{ id: 'tab-1', worktreeId: staleId }],
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ { id: 'floating-terminal-tab', worktreeId: FLOATING_TERMINAL_WORKTREE_ID }
+ ]
+ },
+ browserTabsByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [{ id: 'floating-browser', url: 'https://orca.test' }]
+ },
+ openFiles: [
+ floatingFile,
+ {
+ id: 'stale-file',
+ worktreeId: staleId,
+ filePath: '/a/wt1/stale.ts',
+ relativePath: 'stale.ts',
+ language: 'typescript',
+ isDirty: false,
+ isPreview: false,
+ mode: 'edit' as const
+ }
+ ],
+ activeFileIdByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: 'floating-file',
+ [staleId]: 'stale-file'
+ },
+ unifiedTabsByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ {
+ id: 'floating-unified-tab',
+ type: 'editor',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ fileId: 'floating-file'
+ }
+ ],
+ [staleId]: [{ id: 'stale-unified-tab', worktreeId: staleId }]
+ },
+ groupsByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ {
+ id: 'floating-group',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ activeTabId: 'floating-unified-tab'
+ }
+ ],
+ [staleId]: [{ id: 'stale-group', worktreeId: staleId, activeTabId: 'stale-unified-tab' }]
+ },
+ layoutByWorktree: {
+ [FLOATING_TERMINAL_WORKTREE_ID]: { type: 'leaf', groupId: 'floating-group' },
+ [staleId]: { type: 'leaf', groupId: 'stale-group' }
+ }
+ } as unknown as Partial)
+
+ store.getState().purgeWorktreeTerminalState([staleId, FLOATING_TERMINAL_WORKTREE_ID])
+
+ expect(store.getState().tabsByWorktree).toEqual({
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ { id: 'floating-terminal-tab', worktreeId: FLOATING_TERMINAL_WORKTREE_ID }
+ ]
+ })
+ expect(store.getState().browserTabsByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toEqual([
+ { id: 'floating-browser', url: 'https://orca.test' }
+ ])
+ expect(store.getState().openFiles).toEqual([floatingFile])
+ expect(store.getState().activeFileIdByWorktree).toEqual({
+ [FLOATING_TERMINAL_WORKTREE_ID]: 'floating-file'
+ })
+ expect(store.getState().unifiedTabsByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toHaveLength(1)
+ expect(store.getState().groupsByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toHaveLength(1)
+ expect(store.getState().layoutByWorktree[FLOATING_TERMINAL_WORKTREE_ID]).toEqual({
+ type: 'leaf',
+ groupId: 'floating-group'
+ })
+ })
+
+ it('is a no-op when only the floating workspace sentinel is passed', () => {
+ const store = createTestStore()
+ const tabsByWorktree = {}
+ const browserTabsByWorktree = {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [{ id: 'floating-browser', url: 'https://orca.test' }]
+ }
+ const openFiles = [
+ {
+ id: 'floating-file',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ filePath: '/floating/note.md',
+ relativePath: 'note.md',
+ language: 'markdown',
+ isDirty: false,
+ isPreview: false,
+ mode: 'edit' as const
+ }
+ ]
+ const unifiedTabsByWorktree = {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ {
+ id: 'floating-unified-tab',
+ type: 'editor',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ fileId: 'floating-file'
+ }
+ ]
+ }
+ const groupsByWorktree = {
+ [FLOATING_TERMINAL_WORKTREE_ID]: [
+ {
+ id: 'floating-group',
+ worktreeId: FLOATING_TERMINAL_WORKTREE_ID,
+ activeTabId: 'floating-unified-tab'
+ }
+ ]
+ }
+ const layoutByWorktree = {
+ [FLOATING_TERMINAL_WORKTREE_ID]: { type: 'leaf', groupId: 'floating-group' }
+ }
+
+ store.setState({
+ tabsByWorktree,
+ browserTabsByWorktree,
+ openFiles,
+ activeFileIdByWorktree: { [FLOATING_TERMINAL_WORKTREE_ID]: 'floating-file' },
+ unifiedTabsByWorktree,
+ groupsByWorktree,
+ layoutByWorktree
+ } as unknown as Partial)
+
+ store.getState().purgeWorktreeTerminalState([FLOATING_TERMINAL_WORKTREE_ID])
+
+ expect(store.getState().tabsByWorktree).toBe(tabsByWorktree)
+ expect(store.getState().browserTabsByWorktree).toBe(browserTabsByWorktree)
+ expect(store.getState().openFiles).toBe(openFiles)
+ expect(store.getState().unifiedTabsByWorktree).toBe(unifiedTabsByWorktree)
+ expect(store.getState().groupsByWorktree).toBe(groupsByWorktree)
+ expect(store.getState().layoutByWorktree).toBe(layoutByWorktree)
+ })
})
describe('markWorktreeVisited', () => {
diff --git a/src/renderer/src/store/slices/worktrees.ts b/src/renderer/src/store/slices/worktrees.ts
index 276daff3016..0918c65ad38 100644
--- a/src/renderer/src/store/slices/worktrees.ts
+++ b/src/renderer/src/store/slices/worktrees.ts
@@ -39,6 +39,7 @@ import { branchName } from '@/lib/git-utils'
import { markInputQuietSchedulerInput, scheduleAfterInputQuiet } from '@/lib/input-quiet-scheduler'
import { showLocalBaseRefUpdateSuggestionToast } from '@/components/sidebar/local-base-ref-suggestion-toast'
import { translate } from '@/i18n/i18n'
+import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../../shared/constants'
export type { WorktreeSlice, WorktreeDeleteState } from './worktree-helpers'
// Why: old runtime servers only have `worktree.list`; preserve the large-list
@@ -869,6 +870,9 @@ export const createWorktreeSlice: StateCreator
return
}
const validIds = new Set()
+ // Why: floating is persisted renderer state, but not a repo worktree that
+ // authoritative runtime scans can return.
+ validIds.add(FLOATING_TERMINAL_WORKTREE_ID)
for (const result of Object.values(get().detectedWorktreesByRepo)) {
if (!result.authoritative) {
continue
@@ -2462,9 +2466,10 @@ export const createWorktreeSlice: StateCreator
getKnownWorktreeById: (worktreeId) => findKnownWorktreeById(get(), worktreeId),
purgeWorktreeTerminalState: (worktreeIds: string[]) => {
- if (worktreeIds.length === 0) {
+ const purgeableWorktreeIds = worktreeIds.filter((id) => id !== FLOATING_TERMINAL_WORKTREE_ID)
+ if (purgeableWorktreeIds.length === 0) {
return
}
- set((s) => buildWorktreePurgeState(s, worktreeIds))
+ set((s) => buildWorktreePurgeState(s, purgeableWorktreeIds))
}
})
From dd70368caa9d8c0dc3adae08fe0312acd7a8ffc3 Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:15:05 -0700
Subject: [PATCH 010/165] fix: address review findings (#5055)
---
.../src/components/PullRequestPage.tsx | 2 +-
.../components/right-sidebar/ChecksPanel.tsx | 141 ++-
.../right-sidebar/SourceControl.tsx | 816 ++++++++++++++----
.../SourceControlAgentActionDialog.tsx | 11 +-
.../SourceControlAgentActionDialogForm.tsx | 196 ++++-
...urce-control-agent-action-dialog-result.ts | 2 +
...rce-control-agent-action-dialog-support.ts | 7 +-
.../useSourceControlAgentActionDialog.ts | 12 +-
src/renderer/src/i18n/locales/en.json | 24 +-
9 files changed, 962 insertions(+), 249 deletions(-)
diff --git a/src/renderer/src/components/PullRequestPage.tsx b/src/renderer/src/components/PullRequestPage.tsx
index 1df423f6487..b8e75098b66 100644
--- a/src/renderer/src/components/PullRequestPage.tsx
+++ b/src/renderer/src/components/PullRequestPage.tsx
@@ -4476,7 +4476,7 @@ function ChecksTab({
title={translate('auto.components.PullRequestPage.a053bdd082', 'Fix Broken Checks With AI')}
description={translate(
'auto.components.PullRequestPage.ddfd42f460',
- 'Choose the agent and edit the full command input before launch.'
+ 'Review the prompt before starting an agent.'
)}
baseCommandInput={fixChecksComposerPrompt ?? ''}
connectionId={repo?.connectionId ?? null}
diff --git a/src/renderer/src/components/right-sidebar/ChecksPanel.tsx b/src/renderer/src/components/right-sidebar/ChecksPanel.tsx
index 016976c41cd..d58d3a428b9 100644
--- a/src/renderer/src/components/right-sidebar/ChecksPanel.tsx
+++ b/src/renderer/src/components/right-sidebar/ChecksPanel.tsx
@@ -165,7 +165,11 @@ export function ChecksPanelReviewHeader({
{reviewNumberLabel}
@@ -181,7 +185,7 @@ export function ChecksPanelReviewHeader({
@@ -194,8 +198,14 @@ export function ChecksPanelReviewHeader({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.right.sidebar.ChecksPanel.653c105ecc", "More PR actions")}
- title={translate("auto.components.right.sidebar.ChecksPanel.653c105ecc", "More PR actions")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.ChecksPanel.653c105ecc',
+ 'More PR actions'
+ )}
+ title={translate(
+ 'auto.components.right.sidebar.ChecksPanel.653c105ecc',
+ 'More PR actions'
+ )}
className="text-muted-foreground hover:text-foreground"
>
@@ -204,10 +214,12 @@ export function ChecksPanelReviewHeader({
- {translate("auto.components.right.sidebar.ChecksPanel.7202f4a40a", "unlink PR")}
+ {translate('auto.components.right.sidebar.ChecksPanel.7202f4a40a', 'unlink PR')}
+
- {translate("auto.components.right.sidebar.ChecksPanel.07871c0589", "Link another PR")}
+ {translate('auto.components.right.sidebar.ChecksPanel.07871c0589', 'Link another PR')}
+
)}
@@ -1721,7 +1733,12 @@ export default function ChecksPanel(): React.JSX.Element {
}
if (!ok) {
setComments(previousComments)
- toast.error(translate("auto.components.right.sidebar.ChecksPanel.5788d1059d", "Could not update review thread. Check the GitHub API budget."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.ChecksPanel.5788d1059d',
+ 'Could not update review thread. Check the GitHub API budget.'
+ )
+ )
}
return ok
},
@@ -1826,9 +1843,12 @@ export default function ChecksPanel(): React.JSX.Element {
return
}
const confirmed = await confirm({
- title: translate("auto.components.right.sidebar.ChecksPanel.ea9b649ce3", "Delete comment?"),
- description: translate("auto.components.right.sidebar.ChecksPanel.3b203c62f8", "This will permanently remove the comment from the PR."),
- confirmLabel: translate("auto.components.right.sidebar.ChecksPanel.786e3c143f", "Delete"),
+ title: translate('auto.components.right.sidebar.ChecksPanel.ea9b649ce3', 'Delete comment?'),
+ description: translate(
+ 'auto.components.right.sidebar.ChecksPanel.3b203c62f8',
+ 'This will permanently remove the comment from the PR.'
+ ),
+ confirmLabel: translate('auto.components.right.sidebar.ChecksPanel.786e3c143f', 'Delete'),
confirmVariant: 'destructive'
})
if (!confirmed) {
@@ -1907,8 +1927,14 @@ export default function ChecksPanel(): React.JSX.Element {
const conflictFiles = activeConflictReview.conflictSummary?.files ?? []
setAgentComposerState({
actionId: 'resolveConflicts',
- title: translate("auto.components.right.sidebar.ChecksPanel.4ede779461", "Resolve Review Conflicts With AI"),
- description: translate("auto.components.right.sidebar.ChecksPanel.abf59262fb", "Review and edit the full command input before starting an agent."),
+ title: translate(
+ 'auto.components.right.sidebar.ChecksPanel.4ede779461',
+ 'Resolve Review Conflicts With AI'
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.ChecksPanel.abf59262fb',
+ 'Review the prompt before starting an agent.'
+ ),
prompt: buildResolvePullRequestConflictsPrompt({
reviewKind: activeConflictReview.provider === 'gitlab' ? 'MR' : 'PR',
baseRef: activeConflictReview.conflictSummary?.baseRef,
@@ -1925,7 +1951,12 @@ export default function ChecksPanel(): React.JSX.Element {
}
const broken = getBrokenChecks(checks)
if (broken.length === 0) {
- toast.message(translate("auto.components.right.sidebar.ChecksPanel.5594400d73", "No broken checks to fix."))
+ toast.message(
+ translate(
+ 'auto.components.right.sidebar.ChecksPanel.5594400d73',
+ 'No broken checks to fix.'
+ )
+ )
return
}
const requestKey = stateRequestKey
@@ -1978,7 +2009,12 @@ export default function ChecksPanel(): React.JSX.Element {
launchSource: 'task_page'
})
if (started) {
- toast.success(translate("auto.components.right.sidebar.ChecksPanel.2ef90c9819", "Started an AI agent for the broken checks."))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.ChecksPanel.2ef90c9819',
+ 'Started an AI agent for the broken checks.'
+ )
+ )
}
} finally {
setIsFixingChecksWithAI(false)
@@ -2381,17 +2417,33 @@ export default function ChecksPanel(): React.JSX.Element {
if (!activeWorktree) {
return (
-
{translate("auto.components.right.sidebar.ChecksPanel.a4ef4e0832", "No workspace selected")}
-
{translate("auto.components.right.sidebar.ChecksPanel.b5dd73a105", "Select a workspace to view checks")}
+
+ {translate(
+ 'auto.components.right.sidebar.ChecksPanel.a4ef4e0832',
+ 'No workspace selected'
+ )}
+
+
+ {translate(
+ 'auto.components.right.sidebar.ChecksPanel.b5dd73a105',
+ 'Select a workspace to view checks'
+ )}
+
)
}
if (isFolder) {
return (
-
{translate("auto.components.right.sidebar.ChecksPanel.976cefd02f", "Checks unavailable")}
+
+ {translate('auto.components.right.sidebar.ChecksPanel.976cefd02f', 'Checks unavailable')}
+
- {translate("auto.components.right.sidebar.ChecksPanel.dda5924a40", "Checks require a Git branch and hosted review context")}
+ {translate(
+ 'auto.components.right.sidebar.ChecksPanel.dda5924a40',
+ 'Checks require a Git branch and hosted review context'
+ )}
+
)
}
@@ -2468,7 +2520,15 @@ export default function ChecksPanel(): React.JSX.Element {
disabled={isPublishingBranch || isRemoteOperationActive}
onClick={handlePublishBranch}
>
- {isPublishingBranch ? translate("auto.components.right.sidebar.ChecksPanel.fdb27637f2", "Publishing…") : translate("auto.components.right.sidebar.ChecksPanel.6633c7a1fb", "Publish Branch")}
+ {isPublishingBranch
+ ? translate(
+ 'auto.components.right.sidebar.ChecksPanel.fdb27637f2',
+ 'Publishing…'
+ )
+ : translate(
+ 'auto.components.right.sidebar.ChecksPanel.6633c7a1fb',
+ 'Publish Branch'
+ )}
)}
{(canCreate || canPushCreate) && (
@@ -2480,8 +2540,16 @@ export default function ChecksPanel(): React.JSX.Element {
}}
>
{canPushCreate
- ? translate("auto.components.right.sidebar.ChecksPanel.98f4c37b33", "Push & Create {{value0}}", { value0: emptyReviewShortLabel })
- : translate("auto.components.right.sidebar.ChecksPanel.889cdfba04", "Create {{value0}}", { value0: emptyReviewShortLabel })}
+ ? translate(
+ 'auto.components.right.sidebar.ChecksPanel.98f4c37b33',
+ 'Push & Create {{value0}}',
+ { value0: emptyReviewShortLabel }
+ )
+ : translate(
+ 'auto.components.right.sidebar.ChecksPanel.889cdfba04',
+ 'Create {{value0}}',
+ { value0: emptyReviewShortLabel }
+ )}
)}
- {emptyRefreshing ? translate("auto.components.right.sidebar.ChecksPanel.71026ca2cb", "Refreshing…") : translate("auto.components.right.sidebar.ChecksPanel.7f4489f370", "Refresh")}
+ {emptyRefreshing
+ ? translate('auto.components.right.sidebar.ChecksPanel.71026ca2cb', 'Refreshing…')
+ : translate('auto.components.right.sidebar.ChecksPanel.7f4489f370', 'Refresh')}
)}
@@ -2540,7 +2610,7 @@ export default function ChecksPanel(): React.JSX.Element {
/>
void handleSaveTitle()}
disabled={titleSaving}
>
@@ -2552,7 +2622,7 @@ export default function ChecksPanel(): React.JSX.Element {
@@ -2574,7 +2644,9 @@ export default function ChecksPanel(): React.JSX.Element {
{/* Updated at */}
{activeReview.updatedAt && (
- {reviewShortLabel} {translate("auto.components.right.sidebar.ChecksPanel.34464d00b9", "updated")}{new Date(activeReview.updatedAt).toLocaleString()}
+ {reviewShortLabel}{' '}
+ {translate('auto.components.right.sidebar.ChecksPanel.34464d00b9', 'updated')}
+ {new Date(activeReview.updatedAt).toLocaleString()}
)}
{queueBadges.length > 0 ? (
@@ -2658,7 +2730,10 @@ export default function ChecksPanel(): React.JSX.Element {
}
}}
actionId={agentComposerState?.actionId ?? 'fixChecks'}
- title={agentComposerState?.title ?? translate("auto.components.right.sidebar.ChecksPanel.7fad8509fe", "Fix With AI")}
+ title={
+ agentComposerState?.title ??
+ translate('auto.components.right.sidebar.ChecksPanel.7fad8509fe', 'Fix With AI')
+ }
description={agentComposerState?.description ?? ''}
baseCommandInput={agentComposerState?.prompt ?? ''}
worktreeId={activeWorktreeId}
@@ -2700,9 +2775,19 @@ export default function ChecksPanel(): React.JSX.Element {
onSaveAgentDefault={saveLaunchActionDefault}
onLaunched={() => {
if (agentComposerState?.actionId === 'resolveConflicts') {
- toast.success(translate("auto.components.right.sidebar.ChecksPanel.a0181a8d76", "Started an AI agent for the conflicts."))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.ChecksPanel.a0181a8d76',
+ 'Started an AI agent for the conflicts.'
+ )
+ )
} else {
- toast.success(translate("auto.components.right.sidebar.ChecksPanel.2ef90c9819", "Started an AI agent for the broken checks."))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.ChecksPanel.2ef90c9819',
+ 'Started an AI agent for the broken checks.'
+ )
+ )
}
}}
/>
diff --git a/src/renderer/src/components/right-sidebar/SourceControl.tsx b/src/renderer/src/components/right-sidebar/SourceControl.tsx
index 029ee808bf3..5694cf0b6fe 100644
--- a/src/renderer/src/components/right-sidebar/SourceControl.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControl.tsx
@@ -938,7 +938,12 @@ function SourceControlInner(): React.JSX.Element {
if (ok) {
setPendingDiffCommentsClear(null)
} else {
- toast.error(translate("auto.components.right.sidebar.SourceControl.eae7a1da5f", "Failed to clear notes."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.SourceControl.eae7a1da5f',
+ 'Failed to clear notes.'
+ )
+ )
}
} finally {
setIsClearingDiffComments(false)
@@ -1890,7 +1895,14 @@ function SourceControlInner(): React.JSX.Element {
await abortGitOperation(context)
} catch (error) {
const message = error instanceof Error ? error.message : `Failed to abort ${label}`
- toast.error(translate("auto.components.right.sidebar.SourceControl.f99560ab29", "Abort {{value0}} failed", { value0: label }), { description: message })
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.SourceControl.f99560ab29',
+ 'Abort {{value0}} failed',
+ { value0: label }
+ ),
+ { description: message }
+ )
setRemoteActionErrors((prev) => ({
...prev,
[activeWorktreeId]: { kind: isRebase ? 'abort_rebase' : 'abort_merge', message }
@@ -1992,12 +2004,23 @@ function SourceControlInner(): React.JSX.Element {
})
])
} catch {
- toast.warning(translate("auto.components.right.sidebar.SourceControl.0453ca3a9a", "{{value0}} created, but Orca could not refresh it yet.", { value0: copy.titleLabel }), {
- action: {
- label: translate("auto.components.right.sidebar.SourceControl.812cb992ee", "Open on {{value0}}", { value0: copy.providerName }),
- onClick: () => window.api.shell.openUrl(result.url)
+ toast.warning(
+ translate(
+ 'auto.components.right.sidebar.SourceControl.0453ca3a9a',
+ '{{value0}} created, but Orca could not refresh it yet.',
+ { value0: copy.titleLabel }
+ ),
+ {
+ action: {
+ label: translate(
+ 'auto.components.right.sidebar.SourceControl.812cb992ee',
+ 'Open on {{value0}}',
+ { value0: copy.providerName }
+ ),
+ onClick: () => window.api.shell.openUrl(result.url)
+ }
}
- })
+ )
}
},
[
@@ -2414,11 +2437,23 @@ function SourceControlInner(): React.JSX.Element {
const number = result.existingReview.number
toast.success(
number
- ? translate("auto.components.right.sidebar.SourceControl.eef5446523", "{{value0}} #{{value1}} is already open", { value0: hostedReviewCreateCopy.titleLabel, value1: number })
- : translate("auto.components.right.sidebar.SourceControl.eef5446523", "{{value0}} is already open", { value0: hostedReviewCreateCopy.titleLabel }),
+ ? translate(
+ 'auto.components.right.sidebar.SourceControl.eef5446523',
+ '{{value0}} #{{value1}} is already open',
+ { value0: hostedReviewCreateCopy.titleLabel, value1: number }
+ )
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.eef5446523',
+ '{{value0}} is already open',
+ { value0: hostedReviewCreateCopy.titleLabel }
+ ),
{
action: {
- label: translate("auto.components.right.sidebar.SourceControl.812cb992ee", "Open on {{value0}}", { value0: hostedReviewCreateCopy.providerName }),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControl.812cb992ee',
+ 'Open on {{value0}}',
+ { value0: hostedReviewCreateCopy.providerName }
+ ),
onClick: () => window.api.shell.openUrl(result.existingReview!.url)
}
}
@@ -2498,7 +2533,11 @@ function SourceControlInner(): React.JSX.Element {
return isCreatingPr && action.kind === 'create_pr'
? {
...action,
- title: translate("auto.components.right.sidebar.SourceControl.fe5bd1a610", "Creating {{value0}}...", { value0: hostedReviewCreateCopy.reviewLabel }),
+ title: translate(
+ 'auto.components.right.sidebar.SourceControl.fe5bd1a610',
+ 'Creating {{value0}}...',
+ { value0: hostedReviewCreateCopy.reviewLabel }
+ ),
disabled: true
}
: action
@@ -3299,7 +3338,13 @@ function SourceControlInner(): React.JSX.Element {
item.id
)
if (result.summary.status !== 'ready') {
- toast.error(result.summary.errorMessage ?? translate("auto.components.right.sidebar.SourceControl.8a5ba6a988", "Failed to load commit diff"))
+ toast.error(
+ result.summary.errorMessage ??
+ translate(
+ 'auto.components.right.sidebar.SourceControl.8a5ba6a988',
+ 'Failed to load commit diff'
+ )
+ )
return
}
openCommitAllDiffs(
@@ -3311,7 +3356,14 @@ function SourceControlInner(): React.JSX.Element {
item.message
)
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.right.sidebar.SourceControl.8a5ba6a988", "Failed to load commit diff"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.8a5ba6a988',
+ 'Failed to load commit diff'
+ )
+ )
}
},
[activeWorktreeId, openCommitAllDiffs, worktreePath]
@@ -3602,9 +3654,15 @@ function SourceControlInner(): React.JSX.Element {
}
})
if (result.aborted) {
- toast.error(translate("auto.components.right.sidebar.SourceControl.a5e5a11090", "Discard all failed — unable to unstage files before discard"), {
- description: errors[0] instanceof Error ? errors[0].message : undefined
- })
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.SourceControl.a5e5a11090',
+ 'Discard all failed — unable to unstage files before discard'
+ ),
+ {
+ description: errors[0] instanceof Error ? errors[0].message : undefined
+ }
+ )
} else if (result.failed.length > 0) {
// Why: only include the first error message to avoid a huge toast
// body on bulk failures; a short sample of failed paths gives users
@@ -3613,9 +3671,19 @@ function SourceControlInner(): React.JSX.Element {
const sample = result.failed.slice(0, 3).join(', ')
const more = result.failed.length > 3 ? `, +${result.failed.length - 3} more` : ''
toast.error(
- translate("auto.components.right.sidebar.SourceControl.8eb3782a0c", "Failed to discard {{value0}} file{{value1}}", { value0: result.failed.length, value1: result.failed.length === 1 ? '' : 's' }),
+ translate(
+ 'auto.components.right.sidebar.SourceControl.8eb3782a0c',
+ 'Failed to discard {{value0}} file{{value1}}',
+ { value0: result.failed.length, value1: result.failed.length === 1 ? '' : 's' }
+ ),
{
- description: firstMsg ? translate("auto.components.right.sidebar.SourceControl.dc5a6465fc", "{{value0}} (e.g. {{value1}}{{value2}})", { value0: firstMsg, value1: sample, value2: more }) : `${sample}${more}`
+ description: firstMsg
+ ? translate(
+ 'auto.components.right.sidebar.SourceControl.dc5a6465fc',
+ '{{value0}} (e.g. {{value1}}{{value2}})',
+ { value0: firstMsg, value1: sample, value2: more }
+ )
+ : `${sample}${more}`
}
)
}
@@ -3679,13 +3747,21 @@ function SourceControlInner(): React.JSX.Element {
if (!activeWorktree || !activeRepo || !worktreePath) {
return (
- {translate("auto.components.right.sidebar.SourceControl.c07b236287", "Select a workspace to view changes")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.c07b236287',
+ 'Select a workspace to view changes'
+ )}
+
)
}
if (isFolder) {
return (
- {translate("auto.components.right.sidebar.SourceControl.e131cd7128", "Source Control is only available for Git repositories")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.e131cd7128',
+ 'Source Control is only available for Git repositories'
+ )}
+
)
}
@@ -3714,7 +3790,12 @@ function SourceControlInner(): React.JSX.Element {
)}
onClick={() => setScope(value)}
>
- {value === "all" ? translate("auto.components.right.sidebar.SourceControl.77afaa8152", "All") : translate("auto.components.right.sidebar.SourceControl.0fad573938", "Uncommitted")}
+ {value === 'all'
+ ? translate('auto.components.right.sidebar.SourceControl.77afaa8152', 'All')
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.0fad573938',
+ 'Uncommitted'
+ )}
))}
{hostedReview && (
@@ -3734,7 +3815,7 @@ function SourceControlInner(): React.JSX.Element {
)}
- {scope === "all" && shouldShowCompareSummary(branchSummary) && (
+ {scope === 'all' && shouldShowCompareSummary(branchSummary) && (
setDiffCommentsExpanded((prev) => !prev)}
aria-expanded={diffCommentsExpanded}
- title={diffCommentsExpanded ? translate("auto.components.right.sidebar.SourceControl.d13edef890", "Collapse notes") : translate("auto.components.right.sidebar.SourceControl.72f2bea3f4", "Expand notes")}
+ title={
+ diffCommentsExpanded
+ ? translate(
+ 'auto.components.right.sidebar.SourceControl.d13edef890',
+ 'Collapse notes'
+ )
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.72f2bea3f4',
+ 'Expand notes'
+ )
+ }
>
- {translate("auto.components.right.sidebar.SourceControl.cc474e0b8c", "Notes")}
+
+ {translate('auto.components.right.sidebar.SourceControl.cc474e0b8c', 'Notes')}
+
{diffCommentCount > 0 && (
{diffCommentCount}
@@ -3791,7 +3884,10 @@ function SourceControlInner(): React.JSX.Element {
type="button"
className="inline-flex size-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
onClick={() => void handleCopyDiffComments()}
- aria-label={translate("auto.components.right.sidebar.SourceControl.3baf6c77b4", "Copy all notes to clipboard")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.3baf6c77b4',
+ 'Copy all notes to clipboard'
+ )}
>
{diffCommentsCopied ? (
@@ -3801,7 +3897,11 @@ function SourceControlInner(): React.JSX.Element {
- {translate("auto.components.right.sidebar.SourceControl.eae2d051af", "Copy all notes")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.eae2d051af',
+ 'Copy all notes'
+ )}
+
)}
@@ -3813,14 +3913,21 @@ function SourceControlInner(): React.JSX.Element {
- {translate("auto.components.right.sidebar.SourceControl.2fe2a67580", "More note actions")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.2fe2a67580',
+ 'More note actions'
+ )}
+
@@ -3835,7 +3942,11 @@ function SourceControlInner(): React.JSX.Element {
}}
>
- {translate("auto.components.right.sidebar.SourceControl.1406954883", "Clear all notes...")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.1406954883',
+ 'Clear all notes...'
+ )}
+
@@ -3865,7 +3976,10 @@ function SourceControlInner(): React.JSX.Element {
type="text"
value={filterQuery}
onChange={(e) => setFilterQuery(e.target.value)}
- placeholder={translate("auto.components.right.sidebar.SourceControl.c35baf2f1e", "Filter files…")}
+ placeholder={translate(
+ 'auto.components.right.sidebar.SourceControl.c35baf2f1e',
+ 'Filter files…'
+ )}
className="flex-1 min-w-0 bg-transparent text-xs text-foreground placeholder:text-muted-foreground/60 outline-none"
/>
{filterQuery && (
@@ -3915,7 +4029,7 @@ function SourceControlInner(): React.JSX.Element {
but there are no unresolved conflicts (e.g. between rebase steps, or
after resolving all conflicts before running --continue). The
ConflictSummaryCard handles the "has conflicts" case above. */}
- {unresolvedConflictReviewEntries.length === 0 && conflictOperation !== "unknown" && (
+ {unresolvedConflictReviewEntries.length === 0 && conflictOperation !== 'unknown' && (
)}
- {scope === "all" && showGenericEmptyState && !normalizedFilter ? (
+ {scope === 'all' && showGenericEmptyState && !normalizedFilter ? (
) : null}
- {scope === "uncommitted" && !hasUncommittedEntries && !normalizedFilter && (
+ {scope === 'uncommitted' && !hasUncommittedEntries && !normalizedFilter && (
- {translate("auto.components.right.sidebar.SourceControl.78ce2d37ac", "Pushes to fork")}{describeForkPushTarget(activeWorktree.pushTarget)}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.78ce2d37ac',
+ 'Pushes to fork'
+ )}
+ {describeForkPushTarget(activeWorktree.pushTarget)}
) : null}
{shouldRenderCommitArea(scope, unresolvedConflicts.length, conflictOperation) &&
- (primaryAction.kind === "create_pr" ? (
+ (primaryAction.kind === 'create_pr' ? (
))}
- {(scope === "all" || scope === "uncommitted") && hasFilteredUncommittedEntries && (
+ {(scope === 'all' || scope === 'uncommitted') && hasFilteredUncommittedEntries && (
<>
{SECTION_ORDER.map((area) => {
const items = filteredGrouped[area]
@@ -4104,7 +4226,15 @@ function SourceControlInner(): React.JSX.Element {
// A generic "Discard all" label hides that severity —
// label explicitly for the destructive variant.
title={
- area === "untracked" ? translate("auto.components.right.sidebar.SourceControl.2f609a2e7c", "Delete all untracked") : translate("auto.components.right.sidebar.SourceControl.ce41708855", "Discard all")
+ area === 'untracked'
+ ? translate(
+ 'auto.components.right.sidebar.SourceControl.2f609a2e7c',
+ 'Delete all untracked'
+ )
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.ce41708855',
+ 'Discard all'
+ )
}
onClick={(event) => {
event.stopPropagation()
@@ -4116,7 +4246,10 @@ function SourceControlInner(): React.JSX.Element {
{canStageAll && (
{
event.stopPropagation()
if (area === 'unstaged' || area === 'untracked') {
@@ -4129,7 +4262,10 @@ function SourceControlInner(): React.JSX.Element {
{canUnstageAll && (
{
event.stopPropagation()
void handleUnstageAll()
@@ -4151,7 +4287,11 @@ function SourceControlInner(): React.JSX.Element {
}
}}
>
- {translate("auto.components.right.sidebar.SourceControl.48db37cca9", "View all")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.48db37cca9',
+ 'View all'
+ )}
+
) : (
- {translate("auto.components.right.sidebar.SourceControl.48db37cca9", "View all")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.48db37cca9',
+ 'View all'
+ )}
+
)}
>
}
/>
{!isCollapsed &&
- (sourceControlViewMode === "tree"
+ (sourceControlViewMode === 'tree'
? visibleTreeRowsByArea[area].map((node) => {
if (node.type === 'directory') {
return (
@@ -4243,10 +4387,10 @@ function SourceControlInner(): React.JSX.Element {
>
)}
- {scope === "all" &&
+ {scope === 'all' &&
branchSummary &&
- branchSummary.status !== "ready" &&
- branchSummary.status !== "loading" ? (
+ branchSummary.status !== 'ready' &&
+ branchSummary.status !== 'loading' ? (
setBaseRefDialogOpen(true)}
@@ -4254,10 +4398,13 @@ function SourceControlInner(): React.JSX.Element {
/>
) : null}
- {scope === "all" && branchSummary?.status === "ready" && hasFilteredBranchEntries && (
+ {scope === 'all' && branchSummary?.status === 'ready' && hasFilteredBranchEntries && (
toggleSection('branch')}
@@ -4274,11 +4421,15 @@ function SourceControlInner(): React.JSX.Element {
}
}}
>
- {translate("auto.components.right.sidebar.SourceControl.48db37cca9", "View all")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.48db37cca9',
+ 'View all'
+ )}
+
}
/>
{!collapsedSections.has('branch') &&
- (sourceControlViewMode === "tree"
+ (sourceControlViewMode === 'tree'
? visibleBranchTreeRows.map((node) => {
if (node.type === 'directory') {
return (
@@ -4357,7 +4508,9 @@ function SourceControlInner(): React.JSX.Element {
>
- {translate("auto.components.right.sidebar.SourceControl.574d2f4413", "Clear Notes")}
+
+ {translate('auto.components.right.sidebar.SourceControl.574d2f4413', 'Clear Notes')}
+
{pendingDiffCommentsClearDescription}
@@ -4369,7 +4522,8 @@ function SourceControlInner(): React.JSX.Element {
onClick={() => setPendingDiffCommentsClear(null)}
disabled={isClearingDiffComments}
>
- {translate("auto.components.right.sidebar.SourceControl.05bb8f4a48", "Cancel")}
+ {translate('auto.components.right.sidebar.SourceControl.05bb8f4a48', 'Cancel')}
+
- {translate("auto.components.right.sidebar.SourceControl.574d2f4413", "Clear Notes")}
+ {translate('auto.components.right.sidebar.SourceControl.574d2f4413', 'Clear Notes')}
+
@@ -4391,9 +4546,18 @@ function SourceControlInner(): React.JSX.Element {
- {translate("auto.components.right.sidebar.SourceControl.476b77745b", "Change Base Ref")}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.476b77745b',
+ 'Change Base Ref'
+ )}
+
- {translate("auto.components.right.sidebar.SourceControl.c9ad22888e", "Pick the branch compare target for this repository.")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.c9ad22888e',
+ 'Pick the branch compare target for this repository.'
+ )}
+
toast.success(translate("auto.components.right.sidebar.SourceControl.e48caaf0dd", "Started an AI agent for the conflicts."))}
+ onLaunched={() =>
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.SourceControl.e48caaf0dd',
+ 'Started an AI agent for the conflicts.'
+ )
+ )
+ }
/>
- {translate("auto.components.right.sidebar.SourceControl.e1970d327d", "New")}{copy.reviewLabel}
+
+ {translate('auto.components.right.sidebar.SourceControl.e1970d327d', 'New')}
+ {copy.reviewLabel}
+
{aiGenerationEnabled ? (
generating ? (
@@ -4577,11 +4769,23 @@ function PullRequestComposer({
type="button"
onClick={() => onCancelGenerate()}
className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-border bg-background px-2 text-[11px] text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
- title={translate("auto.components.right.sidebar.SourceControl.527e130b6f", "Stop generating")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.527e130b6f", "Stop generating {{value0}} details", { value0: copy.reviewLabel })}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.527e130b6f',
+ 'Stop generating'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.527e130b6f',
+ 'Stop generating {{value0}} details',
+ { value0: copy.reviewLabel }
+ )}
>
- {translate("auto.components.right.sidebar.SourceControl.e868cec4e1", "Generating…")}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.e868cec4e1',
+ 'Generating…'
+ )}
+
) : (
@@ -4590,11 +4794,23 @@ function PullRequestComposer({
disabled={generateDisabled}
onClick={() => onGenerate()}
className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-border bg-background px-2 text-[11px] font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-background"
- title={generateDisabledReason ?? translate("auto.components.right.sidebar.SourceControl.02d8c04339", "Generate {{value0}} details with AI", { value0: copy.reviewLabel })}
- aria-label={translate("auto.components.right.sidebar.SourceControl.02d8c04339", "Generate {{value0}} details with AI", { value0: copy.reviewLabel })}
+ title={
+ generateDisabledReason ??
+ translate(
+ 'auto.components.right.sidebar.SourceControl.02d8c04339',
+ 'Generate {{value0}} details with AI',
+ { value0: copy.reviewLabel }
+ )
+ }
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.02d8c04339',
+ 'Generate {{value0}} details with AI',
+ { value0: copy.reviewLabel }
+ )}
>
- {translate("auto.components.right.sidebar.SourceControl.02d8c04339", "Generate")}
+ {translate('auto.components.right.sidebar.SourceControl.02d8c04339', 'Generate')}
+
)
) : null}
@@ -4611,29 +4827,47 @@ function PullRequestComposer({
'truncate font-mono',
baseSameAsBranch ? 'text-destructive' : 'text-foreground'
)}
- title={normalizedBase || translate("auto.components.right.sidebar.SourceControl.7a09d7f9d2", "base")}
+ title={
+ normalizedBase ||
+ translate('auto.components.right.sidebar.SourceControl.7a09d7f9d2', 'base')
+ }
>
- {normalizedBase || translate("auto.components.right.sidebar.SourceControl.7a09d7f9d2", "base")}
+ {normalizedBase ||
+ translate('auto.components.right.sidebar.SourceControl.7a09d7f9d2', 'base')}
) : null}
@@ -4658,17 +4897,26 @@ function PullRequestComposer({
the full width. The dropdown chevron makes the picker affordance
obvious; the inline label clarifies that this is the merge target. */}
-
{translate("auto.components.right.sidebar.SourceControl.1f7119f604", "Base")}
+
+ {translate('auto.components.right.sidebar.SourceControl.1f7119f604', 'Base')}
+
{
setBaseQuery(event.target.value)
setBase(event.target.value)
}}
- placeholder={translate("auto.components.right.sidebar.SourceControl.e64a632456", "main")}
+ placeholder={translate(
+ 'auto.components.right.sidebar.SourceControl.e64a632456',
+ 'main'
+ )}
className="h-7 w-full min-w-0 rounded-md border border-border bg-background px-2 pr-6 font-mono text-xs text-foreground outline-none placeholder:text-muted-foreground/70 focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-60"
/>
setDraft(event.target.checked)}
className="size-3.5 shrink-0 rounded border-border accent-primary"
/>
- {translate("auto.components.right.sidebar.SourceControl.78ddfd0bb4", "Create as draft")}
+
+ {translate('auto.components.right.sidebar.SourceControl.78ddfd0bb4', 'Create as draft')}
+
{baseResults.length > 0 ? (
@@ -4734,10 +4984,18 @@ function PullRequestComposer({
)}
{isCreating
- ? translate("auto.components.right.sidebar.SourceControl.26511c22b4", "Creating...")
+ ? translate('auto.components.right.sidebar.SourceControl.26511c22b4', 'Creating...')
: draft
- ? translate("auto.components.right.sidebar.SourceControl.aaf1451654", "Create draft {{value0}}", { value0: copy.shortLabel })
- : translate("auto.components.right.sidebar.SourceControl.5acbcedc1a", "Create {{value0}}", { value0: copy.shortLabel })}
+ ? translate(
+ 'auto.components.right.sidebar.SourceControl.aaf1451654',
+ 'Create draft {{value0}}',
+ { value0: copy.shortLabel }
+ )
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.5acbcedc1a',
+ 'Create {{value0}}',
+ { value0: copy.shortLabel }
+ )}
@@ -4748,8 +5006,15 @@ function PullRequestComposer({
'h-7 rounded-l-none border-l border-primary-foreground/20 px-1.5 shrink-0',
createDisabled && 'opacity-50'
)}
- aria-label={translate("auto.components.right.sidebar.SourceControl.c5e4175139", "More {{value0}} and remote actions", { value0: copy.reviewLabel })}
- title={translate("auto.components.right.sidebar.SourceControl.4d6e1fd7f3", "More actions")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.c5e4175139',
+ 'More {{value0}} and remote actions',
+ { value0: copy.reviewLabel }
+ )}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.4d6e1fd7f3',
+ 'More actions'
+ )}
>
@@ -4790,7 +5055,13 @@ function PullRequestComposer({
{baseSameAsBranch ? (
- {translate("auto.components.right.sidebar.SourceControl.ae743199cd", "Choose a different base branch before creating a")}{copy.reviewLabel}.
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.ae743199cd',
+ 'Choose a different base branch before creating a'
+ )}
+ {copy.reviewLabel}.
+
) : null}
{baseSearchError ? (
@@ -4880,8 +5151,14 @@ function CommitFailureFixSplitButton({
className={cn('rounded-r-none', primaryClassName)}
disabled={isLaunching || !canLaunch}
onClick={() => void onFixWithDefaultAgent()}
- title={translate("auto.components.right.sidebar.SourceControl.4b37ae99b0", "Start the default AI agent to fix this commit failure")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.30b8d4f181", "Fix commit failure with AI")}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.4b37ae99b0',
+ 'Start the default AI agent to fix this commit failure'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.30b8d4f181',
+ 'Fix commit failure with AI'
+ )}
>
{isLaunching ? (
@@ -4897,8 +5174,14 @@ function CommitFailureFixSplitButton({
size={size}
className={cn('rounded-l-none border-l', dividerClass, chevronClassName)}
disabled={isLaunching || !canLaunch}
- title={translate("auto.components.right.sidebar.SourceControl.dd43c47089", "Choose an agent for this commit failure")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.ec7bfced55", "Choose agent to fix commit failure")}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.dd43c47089',
+ 'Choose an agent for this commit failure'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.ec7bfced55',
+ 'Choose agent to fix commit failure'
+ )}
>
@@ -4911,9 +5194,18 @@ function CommitFailureFixSplitButton({
className="gap-2 rounded-[7px] px-2 py-1.5 text-[12px] leading-5 font-medium"
>
- {translate("auto.components.right.sidebar.SourceControl.f0a2dc9e46", "Customize launch...")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.f0a2dc9e46',
+ 'Customize launch...'
+ )}
+
) : (
- {translate("auto.components.right.sidebar.SourceControl.9e5ccd00aa", "Commit failure context unavailable")}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.9e5ccd00aa',
+ 'Commit failure context unavailable'
+ )}
+
)}
@@ -4922,8 +5214,14 @@ function CommitFailureFixSplitButton({
open={composerOpen}
onOpenChange={setComposerOpen}
actionId="fixCommitFailure"
- title={translate("auto.components.right.sidebar.SourceControl.054ead86b1", "Fix Commit Failure With AI")}
- description={translate("auto.components.right.sidebar.SourceControl.15b7f210d7", "Choose the agent and edit the full command input before launch.")}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.054ead86b1',
+ 'Fix Commit Failure With AI'
+ )}
+ description={translate(
+ 'auto.components.right.sidebar.SourceControl.15b7f210d7',
+ 'Review the prompt before starting an agent.'
+ )}
baseCommandInput={prompt}
worktreeId={worktreeId}
groupId={groupId}
@@ -5162,8 +5460,14 @@ export function CommitArea({
rows={rows}
value={commitMessage}
onChange={(e) => onCommitMessageChange(e.target.value)}
- placeholder={translate("auto.components.right.sidebar.SourceControl.0d0a8359d3", "Message")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.b94112eb9e", "Commit message")}
+ placeholder={translate(
+ 'auto.components.right.sidebar.SourceControl.0d0a8359d3',
+ 'Message'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.b94112eb9e',
+ 'Commit message'
+ )}
aria-describedby={describedBy || undefined}
// Why: reserve right padding so typed text does not slide under the
// absolute-positioned Generate icon in the top-right corner.
@@ -5183,8 +5487,14 @@ export function CommitArea({
onCancelGenerate()}
- title={translate("auto.components.right.sidebar.SourceControl.527e130b6f", "Stop generating")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.ddc1fbd690", "Stop generating commit message")}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.527e130b6f',
+ 'Stop generating'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.ddc1fbd690',
+ 'Stop generating commit message'
+ )}
className="group absolute right-1.5 top-1.5 inline-flex size-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-destructive/40"
>
@@ -5192,15 +5502,28 @@ export function CommitArea({
- {translate("auto.components.right.sidebar.SourceControl.37a81f29ad", "Generating commit message. Click to stop.")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.37a81f29ad',
+ 'Generating commit message. Click to stop.'
+ )}
+
) : (
onGenerate()}
- title={generateDisabledReason ?? translate("auto.components.right.sidebar.SourceControl.461575b9bc", "Generate commit message with AI")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.461575b9bc", "Generate commit message with AI")}
+ title={
+ generateDisabledReason ??
+ translate(
+ 'auto.components.right.sidebar.SourceControl.461575b9bc',
+ 'Generate commit message with AI'
+ )
+ }
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.461575b9bc',
+ 'Generate commit message with AI'
+ )}
className="absolute right-1.5 top-1.5 inline-flex size-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-muted-foreground"
>
@@ -5261,8 +5584,14 @@ export function CommitArea({
// that are still valid when the primary is disabled.
primaryAction.disabled && 'opacity-50'
)}
- aria-label={translate("auto.components.right.sidebar.SourceControl.cc199ccc5f", "More commit and remote actions")}
- title={translate("auto.components.right.sidebar.SourceControl.4d6e1fd7f3", "More actions")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.cc199ccc5f',
+ 'More commit and remote actions'
+ )}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.4d6e1fd7f3',
+ 'More actions'
+ )}
>
{showChevronSpinner ? (
@@ -5274,7 +5603,11 @@ export function CommitArea({
- {translate("auto.components.right.sidebar.SourceControl.cc199ccc5f", "More commit and remote actions")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.cc199ccc5f',
+ 'More commit and remote actions'
+ )}
+
{dropdownItems.map((entry, index) =>
@@ -5334,7 +5667,12 @@ export function CommitArea({
- {translate("auto.components.right.sidebar.SourceControl.011f9713fc", "Commit blocked")}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.011f9713fc',
+ 'Commit blocked'
+ )}
+
{commitFailureKindLabel ? (
{commitFailureKindLabel}
@@ -5347,7 +5685,10 @@ export function CommitArea({
setCommitFailureDialogOpen(true)}
>
- {translate("auto.components.right.sidebar.SourceControl.03d238218c", "Details")}
+ {translate('auto.components.right.sidebar.SourceControl.03d238218c', 'Details')}
+
)}
@@ -5390,7 +5732,12 @@ export function CommitArea({
>
- {translate("auto.components.right.sidebar.SourceControl.a9bf7c171a", "Commit Failed")}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.a9bf7c171a',
+ 'Commit Failed'
+ )}
+
{commitFailureSummary}
@@ -5398,7 +5745,10 @@ export function CommitArea({
- {translate("auto.components.right.sidebar.SourceControl.783a808870", "Close")}
+ {translate('auto.components.right.sidebar.SourceControl.783a808870', 'Close')}
+
@@ -5474,7 +5825,10 @@ export function CompareSummary({
return (
- {translate("auto.components.right.sidebar.SourceControl.11b5dd8e41", "Comparing against")}{summary?.baseRef ?? '…'}
+
+ {translate('auto.components.right.sidebar.SourceControl.11b5dd8e41', 'Comparing against')}
+ {summary?.baseRef ?? '…'}
+
)
}
@@ -5483,15 +5837,26 @@ export function CompareSummary({
return (
- {summary.errorMessage ?? translate("auto.components.right.sidebar.SourceControl.715d229c86", "Branch compare unavailable")}
+ {summary.errorMessage ??
+ translate(
+ 'auto.components.right.sidebar.SourceControl.715d229c86',
+ 'Branch compare unavailable'
+ )}
-
+
)
@@ -5511,17 +5876,26 @@ export function CompareSummary({
- {commitsAhead} {translate("auto.components.right.sidebar.SourceControl.3278b2767b", "ahead")}
+
+ {commitsAhead}{' '}
+ {translate('auto.components.right.sidebar.SourceControl.3278b2767b', 'ahead')}
+
@@ -5576,10 +5950,22 @@ function CompareUnavailable({
return (
- {summary.status === 'error' ? translate("auto.components.right.sidebar.SourceControl.97d8b03cdf", "Branch compare failed") : translate("auto.components.right.sidebar.SourceControl.715d229c86", "Branch compare unavailable")}
+ {summary.status === 'error'
+ ? translate(
+ 'auto.components.right.sidebar.SourceControl.97d8b03cdf',
+ 'Branch compare failed'
+ )
+ : translate(
+ 'auto.components.right.sidebar.SourceControl.715d229c86',
+ 'Branch compare unavailable'
+ )}
- {summary.errorMessage ?? translate("auto.components.right.sidebar.SourceControl.b6922abb13", "Unable to load branch compare.")}
+ {summary.errorMessage ??
+ translate(
+ 'auto.components.right.sidebar.SourceControl.b6922abb13',
+ 'Unable to load branch compare.'
+ )}
{changeBaseRefAllowed && (
@@ -5591,11 +5977,13 @@ function CompareUnavailable({
onClick={onChangeBaseRef}
>
- {translate("auto.components.right.sidebar.SourceControl.476b77745b", "Change Base Ref")}
+ {translate('auto.components.right.sidebar.SourceControl.476b77745b', 'Change Base Ref')}
+
)}
- {translate("auto.components.right.sidebar.SourceControl.286dbda4d6", "Retry")}
+ {translate('auto.components.right.sidebar.SourceControl.286dbda4d6', 'Retry')}
+
)
@@ -5635,7 +6023,9 @@ function SectionHeader({
{count}
{conflictCount > 0 && (
- · {conflictCount} {translate("auto.components.right.sidebar.SourceControl.413a3ba113", "conflict")}{conflictCount === 1 ? '' : 's'}
+ · {conflictCount}{' '}
+ {translate('auto.components.right.sidebar.SourceControl.413a3ba113', 'conflict')}
+ {conflictCount === 1 ? '' : 's'}
)}
@@ -5691,7 +6081,11 @@ function DiffCommentsInlineList({
if (comments.length === 0) {
return (
- {translate("auto.components.right.sidebar.SourceControl.ac8cbe3bf5", "Hover over a line in the diff view and click the + to add a note.")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.ac8cbe3bf5',
+ 'Hover over a line in the diff view and click the + to add a note.'
+ )}
+
)
}
@@ -5709,7 +6103,11 @@ function DiffCommentsInlineList({
onOpen(first)
}
}}
- title={translate("auto.components.right.sidebar.SourceControl.0d963bf982", "Open {{value0}}", { value0: filePath })}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.0d963bf982',
+ 'Open {{value0}}',
+ { value0: filePath }
+ )}
>
{filePath}
@@ -5717,8 +6115,16 @@ function DiffCommentsInlineList({
type="button"
className="shrink-0 rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:text-destructive focus-visible:opacity-100 group-hover/file:opacity-100"
onClick={() => onClearFile(filePath)}
- title={translate("auto.components.right.sidebar.SourceControl.59654650d3", "Clear notes for {{value0}}", { value0: filePath })}
- aria-label={translate("auto.components.right.sidebar.SourceControl.59654650d3", "Clear notes for {{value0}}", { value0: filePath })}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.59654650d3',
+ 'Clear notes for {{value0}}',
+ { value0: filePath }
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.59654650d3',
+ 'Clear notes for {{value0}}',
+ { value0: filePath }
+ )}
>
@@ -5739,18 +6145,29 @@ function DiffCommentsInlineList({
// fire the row's open handler.
className="flex min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded text-left"
onClick={() => onOpen(c)}
- title={translate("auto.components.right.sidebar.SourceControl.0d963bf982", "Open {{value0}} ({{value1}})", { value0: c.filePath, value1: getDiffCommentLineLabel(c).toLowerCase() })}
- aria-label={translate("auto.components.right.sidebar.SourceControl.3eb9b2805e", "Open note on {{value0}}", { value0: getDiffCommentLineLabel(c).toLowerCase() })}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.0d963bf982',
+ 'Open {{value0}} ({{value1}})',
+ { value0: c.filePath, value1: getDiffCommentLineLabel(c).toLowerCase() }
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.3eb9b2805e',
+ 'Open note on {{value0}}',
+ { value0: getDiffCommentLineLabel(c).toLowerCase() }
+ )}
>
{getDiffCommentLineLabel(c, true)}
- {getDiffCommentSource(c) === "markdown" ? translate("auto.components.right.sidebar.SourceControl.94c42b252e", "MD") : translate("auto.components.right.sidebar.SourceControl.c56ba7fa06", "Diff")}
+ {getDiffCommentSource(c) === 'markdown'
+ ? translate('auto.components.right.sidebar.SourceControl.94c42b252e', 'MD')
+ : translate('auto.components.right.sidebar.SourceControl.c56ba7fa06', 'Diff')}
{c.sentAt ? (
- {translate("auto.components.right.sidebar.SourceControl.655633c08a", "Sent")}
+ {translate('auto.components.right.sidebar.SourceControl.655633c08a', 'Sent')}
+
) : null}
{c.body}
@@ -5760,8 +6177,15 @@ function DiffCommentsInlineList({
type="button"
className="shrink-0 rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:text-foreground group-hover:opacity-100"
onClick={() => void handleCopyOne(c)}
- title={translate("auto.components.right.sidebar.SourceControl.1623bf4e19", "Copy note")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.c085946bda", "Copy note on line {{value0}}", { value0: c.lineNumber })}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.1623bf4e19',
+ 'Copy note'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.c085946bda',
+ 'Copy note on line {{value0}}',
+ { value0: c.lineNumber }
+ )}
>
{copiedId === c.id ? : }
@@ -5769,8 +6193,15 @@ function DiffCommentsInlineList({
type="button"
className="shrink-0 rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:text-destructive group-hover:opacity-100"
onClick={() => onDelete(c.id)}
- title={translate("auto.components.right.sidebar.SourceControl.b656381c18", "Delete note")}
- aria-label={translate("auto.components.right.sidebar.SourceControl.c321542ee2", "Delete note on line {{value0}}", { value0: c.lineNumber })}
+ title={translate(
+ 'auto.components.right.sidebar.SourceControl.b656381c18',
+ 'Delete note'
+ )}
+ aria-label={translate(
+ 'auto.components.right.sidebar.SourceControl.c321542ee2',
+ 'Delete note on line {{value0}}',
+ { value0: c.lineNumber }
+ )}
>
@@ -5822,12 +6253,19 @@ export function ConflictSummaryCard({
-
{translate("auto.components.right.sidebar.SourceControl.d7a5942e41", "{{value0}}: {{value1}} unresolved", { value0: operationLabel, value1: unresolvedCount })}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.d7a5942e41',
+ '{{value0}}: {{value1}} unresolved',
+ { value0: operationLabel, value1: unresolvedCount }
+ )}
+
- {translate("auto.components.right.sidebar.SourceControl.3eeccbb221", "Resolved files move back to normal changes after they leave the live conflict state.")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.3eeccbb221',
+ 'Resolved files move back to normal changes after they leave the live conflict state.'
+ )}
+
@@ -5844,7 +6282,8 @@ export function ConflictSummaryCard({
) : (
)}
- {translate("auto.components.right.sidebar.SourceControl.f6cb48b6fe", "Resolve with AI")}
+ {translate('auto.components.right.sidebar.SourceControl.f6cb48b6fe', 'Resolve with AI')}
+
- {translate("auto.components.right.sidebar.SourceControl.27a50fe970", "Review conflicts")}
- {(conflictOperation === "merge" || conflictOperation === "rebase") && onAbortOperation ? (
+ {translate('auto.components.right.sidebar.SourceControl.27a50fe970', 'Review conflicts')}
+
+ {(conflictOperation === 'merge' || conflictOperation === 'rebase') && onAbortOperation ? (
onAbortOperation(conflictOperation)}
>
{isAbortingOperation ? : null}
- {conflictOperation === "rebase" ? translate("auto.components.right.sidebar.SourceControl.425f138269", "Abort rebase") : translate("auto.components.right.sidebar.SourceControl.540ca8f78c", "Abort merge")}
+ {conflictOperation === 'rebase'
+ ? translate('auto.components.right.sidebar.SourceControl.425f138269', 'Abort rebase')
+ : translate('auto.components.right.sidebar.SourceControl.540ca8f78c', 'Abort merge')}
) : null}
@@ -5903,7 +6345,7 @@ export function OperationBanner({
{label}
- {(conflictOperation === "merge" || conflictOperation === "rebase") && onAbortOperation ? (
+ {(conflictOperation === 'merge' || conflictOperation === 'rebase') && onAbortOperation ? (
onAbortOperation(conflictOperation)}
>
{isAbortingOperation ? : null}
- {conflictOperation === "rebase" ? translate("auto.components.right.sidebar.SourceControl.425f138269", "Abort rebase") : translate("auto.components.right.sidebar.SourceControl.540ca8f78c", "Abort merge")}
+ {conflictOperation === 'rebase'
+ ? translate('auto.components.right.sidebar.SourceControl.425f138269', 'Abort rebase')
+ : translate('auto.components.right.sidebar.SourceControl.540ca8f78c', 'Abort merge')}
) : null}
@@ -5978,7 +6422,17 @@ function SourceControlTreeDirectoryRow({
{canDiscard && (
{
event.stopPropagation()
onRequestDiscardPaths(node.area, actionPaths.discardPaths)
@@ -5989,7 +6443,10 @@ function SourceControlTreeDirectoryRow({
{canStage && (
{
event.stopPropagation()
void onStagePaths(actionPaths.stagePaths)
@@ -6000,7 +6457,10 @@ function SourceControlTreeDirectoryRow({
{canUnstage && (
{
event.stopPropagation()
void onUnstagePaths(actionPaths.unstagePaths)
@@ -6195,7 +6655,11 @@ const UncommittedEntryRow = React.memo(function UncommittedEntryRow({
// attached, without opening the Notes tab.
{commentCount}
@@ -6219,11 +6683,20 @@ const UncommittedEntryRow = React.memo(function UncommittedEntryRow({
{
event.stopPropagation()
@@ -6234,7 +6707,7 @@ const UncommittedEntryRow = React.memo(function UncommittedEntryRow({
{canStage && (
{
event.stopPropagation()
void onStage(entry.path)
@@ -6244,7 +6717,7 @@ const UncommittedEntryRow = React.memo(function UncommittedEntryRow({
{canUnstage && (
{
event.stopPropagation()
void onUnstage(entry.path)
@@ -6264,7 +6737,14 @@ function ConflictBadge({ entry }: { entry: GitStatusEntry }): React.JSX.Element
const badge = (
{badge}
- {translate("auto.components.right.sidebar.SourceControl.03194cfff4", "Local session state derived from a conflict you opened here.")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.03194cfff4',
+ 'Local session state derived from a conflict you opened here.'
+ )}
+
)
@@ -6345,7 +6829,11 @@ function BranchEntryRow({
{commentCount > 0 && (
{commentCount}
@@ -6389,7 +6877,11 @@ function SourceControlEntryContextMenu({
- {translate("auto.components.right.sidebar.SourceControl.cc05b2d088", "Open in File Explorer")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControl.cc05b2d088',
+ 'Open in File Explorer'
+ )}
+
)
diff --git a/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialog.tsx b/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialog.tsx
index 54ff761da6c..dd5db5f5753 100644
--- a/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialog.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialog.tsx
@@ -56,7 +56,6 @@ export function SourceControlAgentActionDialog(
actionId,
title,
description,
- baseCommandInput,
savedCommandInputTemplate,
onOpenSettings,
startLabel = 'Start agent',
@@ -71,6 +70,7 @@ export function SourceControlAgentActionDialog(
statusCopy,
agentArgs,
commandTemplate,
+ saveLaunchRecipe,
saveTargetValue,
saveTargets,
settings,
@@ -81,14 +81,15 @@ export function SourceControlAgentActionDialog(
onSelectedAgentChange,
onAgentArgsChange,
onCommandTemplateChange,
+ onSaveLaunchRecipeChange,
onSaveAgentDefaultChange,
handleStart
} = useSourceControlAgentActionDialog(props)
return (
-
-
+
+
{title}
{description}
@@ -102,7 +103,7 @@ export function SourceControlAgentActionDialog(
agentArgs={agentArgs}
commandTemplate={commandTemplate}
savedCommandInputTemplate={savedCommandInputTemplate}
- baseCommandInput={baseCommandInput}
+ saveLaunchRecipe={saveLaunchRecipe}
saveTargetValue={saveTargetValue}
saveTargets={saveTargets}
settings={settings}
@@ -115,8 +116,10 @@ export function SourceControlAgentActionDialog(
onSelectedAgentChange={onSelectedAgentChange}
onAgentArgsChange={onAgentArgsChange}
onCommandTemplateChange={onCommandTemplateChange}
+ onSaveLaunchRecipeChange={onSaveLaunchRecipeChange}
onSaveAgentDefaultChange={onSaveAgentDefaultChange}
onOpenSettings={onOpenSettings}
+ onCancel={() => handleOpenChange(false)}
onStart={() => void handleStart()}
/>
diff --git a/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialogForm.tsx b/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialogForm.tsx
index 75a795bcaf0..44276430846 100644
--- a/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialogForm.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControlAgentActionDialogForm.tsx
@@ -17,7 +17,6 @@ import { cn } from '@/lib/utils'
import type { SourceControlLaunchActionId } from '../../../../shared/source-control-ai-actions'
import type { SourceControlAiWriteTarget } from '../../../../shared/source-control-ai-recipe-save'
import type { GlobalSettings, Repo, TuiAgent } from '../../../../shared/types'
-import { SourceControlActionVariableChips } from '../source-control/SourceControlActionVariableChips'
import { sourceControlActionRecipeMatchesTarget } from './source-control-action-recipe-match'
import { translate } from '@/i18n/i18n'
@@ -36,7 +35,7 @@ type SourceControlAgentActionDialogFormProps = {
agentArgs: string
commandTemplate: string
savedCommandInputTemplate?: string | null
- baseCommandInput: string
+ saveLaunchRecipe: boolean
saveTargetValue: string
saveTargets: { value: string; label: string }[]
settings: GlobalSettings | null
@@ -49,8 +48,10 @@ type SourceControlAgentActionDialogFormProps = {
onSelectedAgentChange: (agent: TuiAgent | null) => void
onAgentArgsChange: (value: string) => void
onCommandTemplateChange: (value: string) => void
+ onSaveLaunchRecipeChange: (value: boolean) => void
onSaveAgentDefaultChange: (value: string) => void
onOpenSettings?: () => void
+ onCancel: () => void
onStart: () => void
}
@@ -77,7 +78,7 @@ export function SourceControlAgentActionDialogForm({
agentArgs,
commandTemplate,
savedCommandInputTemplate,
- baseCommandInput,
+ saveLaunchRecipe,
saveTargetValue,
saveTargets,
settings,
@@ -90,10 +91,14 @@ export function SourceControlAgentActionDialogForm({
onSelectedAgentChange,
onAgentArgsChange,
onCommandTemplateChange,
+ onSaveLaunchRecipeChange,
onSaveAgentDefaultChange,
onOpenSettings,
+ onCancel,
onStart
}: SourceControlAgentActionDialogFormProps): React.JSX.Element {
+ const defaultCommandTemplate = savedCommandInputTemplate ?? '{basePrompt}'
+ const commandTemplateIncludesBasePrompt = commandTemplate.includes('{basePrompt}')
const selectedRecipe = selectedAgent
? {
agentId: selectedAgent,
@@ -118,12 +123,25 @@ export function SourceControlAgentActionDialogForm({
)
)
const showSaveLaunchRecipe = canSaveAgentDefault && selectedAgent && !allLaunchRecipesAlreadySaved
+ const saveScopeTargets = saveTargets.filter((target) => target.value !== 'none')
+ const effectiveStartLabel =
+ showSaveLaunchRecipe && saveLaunchRecipe
+ ? translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.5421a96acb',
+ 'Save & start agent'
+ )
+ : startLabel
return (
- <>
-
+
+
-
{translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.15c5d85706", "Agent")}
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.15c5d85706',
+ 'Agent'
+ )}
+
{hasEnabledAgents || selectedAgent ? (
) : (
- {detecting ? translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.c7ff8cef11", "Detecting agents...") : translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.1d47db9bf0", "No enabled agents")}
+
+ {detecting
+ ? translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.c7ff8cef11',
+ 'Detecting agents...'
+ )
+ : translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.1d47db9bf0',
+ 'No enabled agents'
+ )}
+
{onOpenSettings ? (
- {translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.b99c33cec5", "Settings")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.b99c33cec5',
+ 'Settings'
+ )}
+
) : null}
)}
@@ -152,63 +184,131 @@ export function SourceControlAgentActionDialogForm({
- {translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.bc8dc39f4b", "CLI arguments")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.bc8dc39f4b',
+ 'CLI arguments'
+ )}
+
onAgentArgsChange(event.target.value)}
className="h-8 font-mono text-xs"
/>
-
-
- {translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.f4f3c9ca4a", "Command template")}
+
+
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.f4f3c9ca4a',
+ 'Prompt template'
+ )}
+
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.1bb611240f',
+ "Use {basePrompt} for Orca's default prompt."
+ )}
+
+
onCommandTemplateChange(savedCommandInputTemplate ?? '{basePrompt}')}
+ disabled={commandTemplate === defaultCommandTemplate}
+ onClick={() => onCommandTemplateChange(defaultCommandTemplate)}
>
- {translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.7ec6abbf2a", "Reset")}
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.7ec6abbf2a',
+ 'Reset'
+ )}
+
{showSaveLaunchRecipe ? (
-
-
{translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.f84657c925", "Save launch recipe")}
-
-
-
-
-
- {saveTargets.map((target) => (
-
- {target.label}
-
- ))}
-
-
+
+
+ onSaveLaunchRecipeChange(event.target.checked)}
+ className="mt-0.5 size-3.5 accent-foreground"
+ />
+
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.c29f9cf266',
+ "Save this prompt and don't show this review next time"
+ )}
+
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.6cefcdfba1',
+ 'You can change it later in Source Control AI settings.'
+ )}
+
+
+
+ {saveLaunchRecipe ? (
+
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.013c9ac04a',
+ 'Save for'
+ )}
+
+
+
+
+
+
+ {saveScopeTargets.map((target) => (
+
+ {target.label}
+
+ ))}
+
+
+
+ ) : null}
) : null}
@@ -233,7 +333,11 @@ export function SourceControlAgentActionDialogForm({
{deliveryPlan.summary}
- {translate("auto.components.right.sidebar.SourceControlAgentActionDialogForm.1bc0bdbb5e", "Launch:")}{deliveryPlan.commandLabel}
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.1bc0bdbb5e',
+ 'Launch:'
+ )}
+ {deliveryPlan.commandLabel}
{deliveryPlan.caveat}
@@ -243,15 +347,21 @@ export function SourceControlAgentActionDialogForm({
+
+ {translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialogForm.ea4788705e',
+ 'Cancel'
+ )}
+
{isStarting ? (
) : (
)}
- {startLabel}
+ {effectiveStartLabel}
- >
+
)
}
diff --git a/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-result.ts b/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-result.ts
index 117ad745044..c061873debf 100644
--- a/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-result.ts
+++ b/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-result.ts
@@ -13,6 +13,7 @@ export type UseSourceControlAgentActionDialogResult = {
statusCopy: string | null
agentArgs: string
commandTemplate: string
+ saveLaunchRecipe: boolean
saveTargetValue: string
saveTargets: { value: string; label: string }[]
settings: ReturnType
['settings']
@@ -23,6 +24,7 @@ export type UseSourceControlAgentActionDialogResult = {
onSelectedAgentChange: (agent: TuiAgent | null) => void
onAgentArgsChange: (value: string) => void
onCommandTemplateChange: (value: string) => void
+ onSaveLaunchRecipeChange: (value: boolean) => void
onSaveAgentDefaultChange: (value: string) => void
handleStart: () => Promise
}
diff --git a/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-support.ts b/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-support.ts
index dc8aaaf6c41..ac0448b70d2 100644
--- a/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-support.ts
+++ b/src/renderer/src/components/right-sidebar/source-control-agent-action-dialog-support.ts
@@ -33,13 +33,16 @@ export function buildSourceControlAgentSaveTargets(repoId?: string | null): {
value: 'repo',
label: translate(
'auto.components.right.sidebar.SourceControlAgentActionDialog.808cfe0a3b',
- 'Save for this repository only'
+ 'This repository'
)
})
}
targets.push({
value: 'global',
- label: repoId ? 'Save as default for all repositories' : 'Save as global default'
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlAgentActionDialog.38b899cc02',
+ 'All repositories'
+ )
})
return targets
}
diff --git a/src/renderer/src/components/right-sidebar/useSourceControlAgentActionDialog.ts b/src/renderer/src/components/right-sidebar/useSourceControlAgentActionDialog.ts
index 8f388a83027..ad62bfae98f 100644
--- a/src/renderer/src/components/right-sidebar/useSourceControlAgentActionDialog.ts
+++ b/src/renderer/src/components/right-sidebar/useSourceControlAgentActionDialog.ts
@@ -55,6 +55,7 @@ export function useSourceControlAgentActionDialog({
})
const [isStarting, setIsStarting] = useState(false)
const saveTargets = useMemo(() => buildSourceControlAgentSaveTargets(repoId), [repoId])
+ const [saveLaunchRecipe, setSaveLaunchRecipe] = useState(true)
const [saveTargetValue, setSaveTargetValue] = useState(DEFAULT_SAVE_TARGET_VALUE)
const disabledAgents = settings?.disabledTuiAgents
@@ -86,6 +87,7 @@ export function useSourceControlAgentActionDialog({
setCommandTemplate(savedCommandInputTemplate ?? '{basePrompt}')
setAgentArgs(savedAgentArgs ?? '')
setSelectedAgent(savedAgentId ?? null)
+ setSaveLaunchRecipe(true)
setSaveTargetValue(DEFAULT_SAVE_TARGET_VALUE)
let stale = false
void refreshDetectedAgents().then((nextAgents) => {
@@ -121,6 +123,7 @@ export function useSourceControlAgentActionDialog({
(nextOpen: boolean) => {
if (!nextOpen) {
setDeliveryPlan({ status: 'idle' })
+ setSaveLaunchRecipe(true)
setSaveTargetValue(DEFAULT_SAVE_TARGET_VALUE)
}
onOpenChange(nextOpen)
@@ -202,7 +205,7 @@ export function useSourceControlAgentActionDialog({
trimmedCommandInput,
agentArgs,
commandTemplate,
- saveTargetValue,
+ saveTargetValue: saveLaunchRecipe ? saveTargetValue : 'none',
actionId,
repoId,
settings,
@@ -238,6 +241,7 @@ export function useSourceControlAgentActionDialog({
refreshDetectedAgents,
repo,
repoId,
+ saveLaunchRecipe,
saveTargetValue,
settings,
selectedAgent,
@@ -265,6 +269,10 @@ export function useSourceControlAgentActionDialog({
setCommandTemplate(value)
setDeliveryPlan({ status: 'idle' })
}, [])
+ const onSaveLaunchRecipeChange = useCallback((value: boolean) => {
+ setSaveLaunchRecipe(value)
+ setDeliveryPlan({ status: 'idle' })
+ }, [])
return {
handleOpenChange,
@@ -275,6 +283,7 @@ export function useSourceControlAgentActionDialog({
statusCopy,
agentArgs,
commandTemplate,
+ saveLaunchRecipe,
saveTargetValue,
saveTargets,
settings,
@@ -285,6 +294,7 @@ export function useSourceControlAgentActionDialog({
onSelectedAgentChange,
onAgentArgsChange,
onCommandTemplateChange,
+ onSaveLaunchRecipeChange,
onSaveAgentDefaultChange: setSaveTargetValue,
handleStart
}
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index c81955e74e8..41bd8ec3d49 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -1034,7 +1034,7 @@
"3912daf310": "This pull request has no reported checks yet.",
"45877f5089": "No checks found",
"85e62c5266": "Started an AI agent for the broken checks.",
- "ddfd42f460": "Choose the agent and edit the full command input before launch.",
+ "ddfd42f460": "Review the prompt before starting an agent.",
"a053bdd082": "Fix Broken Checks With AI",
"1b14d0a69c": "Open in GitHub",
"1550675e5f": "No inline output is available for this check.",
@@ -7159,7 +7159,7 @@
"b5dd73a105": "Select a workspace to view checks",
"a4ef4e0832": "No workspace selected",
"5594400d73": "No broken checks to fix.",
- "abf59262fb": "Review and edit the full command input before starting an agent.",
+ "abf59262fb": "Review the prompt before starting an agent.",
"4ede779461": "Resolve Review Conflicts With AI",
"3b203c62f8": "This will permanently remove the comment from the PR.",
"ea9b649ce3": "Delete comment?",
@@ -7401,7 +7401,7 @@
"37a81f29ad": "Generating commit message. Click to stop.",
"b94112eb9e": "Commit message",
"0d0a8359d3": "Message",
- "15b7f210d7": "Choose the agent and edit the full command input before launch.",
+ "15b7f210d7": "Review the prompt before starting an agent.",
"054ead86b1": "Fix Commit Failure With AI",
"9e5ccd00aa": "Commit failure context unavailable",
"f0a2dc9e46": "Customize launch...",
@@ -7428,7 +7428,7 @@
"1a6a6e0bc5": "Generate Hosted Review Details",
"6b122529d4": "Generate Commit Message",
"e48caaf0dd": "Started an AI agent for the conflicts.",
- "901140f47d": "Review and edit the full command input before starting an agent.",
+ "901140f47d": "Review the prompt before starting an agent.",
"19652ddd76": "Resolve Conflicts With AI",
"c9ad22888e": "Pick the branch compare target for this repository.",
"574d2f4413": "Clear Notes",
@@ -7506,14 +7506,22 @@
"SourceControlAgentActionDialog": {
"8e856842d1": "Could not start the selected agent.",
"c075d00de1": "Unable to resolve the workspace connection.",
- "808cfe0a3b": "Save for this repository only",
+ "38b899cc02": "All repositories",
+ "808cfe0a3b": "This repository",
"994cddd1f7": "Don't save"
},
"SourceControlAgentActionDialogForm": {
- "1bc0bdbb5e": "Launch:",
- "f84657c925": "Save launch recipe",
+ "013c9ac04a": "Save for",
+ "1bb611240f": "Use {basePrompt} for Orca's default prompt.",
+ "23280cbab1": "This template does not include {basePrompt}, so the agent will not receive Orca's default prompt.",
+ "5421a96acb": "Save & start agent",
+ "6cefcdfba1": "You can change it later in Source Control AI settings.",
+ "c29f9cf266": "Save this prompt and don't show this review next time",
+ "d8f40128ee": "{basePrompt} is Orca's default prompt.",
+ "ea4788705e": "Cancel",
"7ec6abbf2a": "Reset",
- "f4f3c9ca4a": "Command template",
+ "f4f3c9ca4a": "Prompt template",
+ "1bc0bdbb5e": "Launch:",
"fe119187bb": "--model sonnet",
"bc8dc39f4b": "CLI arguments",
"b99c33cec5": "Settings",
From f634f81b0eded03fff4e781f0373b71b05564901 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:44:34 -0700
Subject: [PATCH 011/165] Fix shortcut chip floating right in Cmd-J palette tip
on Windows/Linux (#4921)
Co-authored-by: Orca
---
.../feature-tips/CmdJPaletteTipDialog.tsx | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/renderer/src/components/feature-tips/CmdJPaletteTipDialog.tsx b/src/renderer/src/components/feature-tips/CmdJPaletteTipDialog.tsx
index 25cc1c00ea9..ffd8992f350 100644
--- a/src/renderer/src/components/feature-tips/CmdJPaletteTipDialog.tsx
+++ b/src/renderer/src/components/feature-tips/CmdJPaletteTipDialog.tsx
@@ -67,16 +67,21 @@ export function CmdJPaletteTipDialog({
>
{tip.eyebrow.toUpperCase()}
+ {/* Why: flow the shortcut chip as inline text (not a flex item) so the
+ short Mac label (⌘⇧J) stays on one line, while a wide label like
+ "Ctrl+Shift+J" wraps to the next line only when it doesn't fit —
+ instead of being pushed to the right edge on Win/Linux. */}
-
- {titlePrefix.trimEnd()}
- {displayShortcutLabel ? (
-
+ {titlePrefix.trimEnd()}
+ {displayShortcutLabel ? (
+ <>
+ {' '}
+
{displayShortcutLabel}
- ) : null}
- {titleSuffix ? {titleSuffix} : null}
-
+ >
+ ) : null}
+ {titleSuffix ? ` ${titleSuffix}` : null}
{tip.description}
From 25e0877b237c5b4fd6915fbc1acdce1a9876482d Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:47:25 -0700
Subject: [PATCH 012/165] Re-enable WebGL for remote-runtime terminals (#5048)
PR #4946 forced terminalGpuAcceleration to 'off' whenever a remote
runtime environment is active, as a conservative workaround alongside
the real fixes (CSS anchor-name encoding and rebuilding the WebGL
renderer after replay bytes parse). That left every remote-runtime
terminal on the slower DOM renderer even though the post-replay
rebuildPaneWebgl already covers the snapshot-after-attach race.
Remove the forced-off resolver so remote-runtime panes honor the user
GPU setting again. The snapshot path (onSnapshot -> processData with
replayingBufferedData -> onReplayData -> rebuildPaneWebgl after parse)
keeps the glyph atlas in sync, and attachWebgl re-checks all guards
(gpuRenderingEnabled, deferred attachment, context loss) on rebuild.
Co-authored-by: Orca
---
.../use-terminal-pane-lifecycle.test.ts | 19 ------------
.../use-terminal-pane-lifecycle.ts | 31 ++++---------------
2 files changed, 6 insertions(+), 44 deletions(-)
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.test.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.test.ts
index 8aee66514eb..8c7400939da 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.test.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.test.ts
@@ -1,6 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import {
- resolveTerminalGpuAccelerationForRuntime,
shouldDetachPaneTransportOnUnmount,
splitPaneWithOneShotStartup,
suppressIntentionalPaneCloseExit
@@ -126,24 +125,6 @@ describe('shouldDetachPaneTransportOnUnmount', () => {
})
})
-describe('resolveTerminalGpuAccelerationForRuntime', () => {
- it('forces DOM rendering while a remote runtime is active', () => {
- expect(resolveTerminalGpuAccelerationForRuntime('env-1', 'on')).toBe('off')
- })
-
- it('honors the user GPU setting for local terminals', () => {
- expect(resolveTerminalGpuAccelerationForRuntime(null, 'on')).toBe('on')
- })
-
- it('defaults local terminals to auto when the setting is missing', () => {
- expect(resolveTerminalGpuAccelerationForRuntime(null, undefined)).toBe('auto')
- })
-
- it('treats blank runtime ids as local', () => {
- expect(resolveTerminalGpuAccelerationForRuntime(' ', 'auto')).toBe('auto')
- })
-})
-
describe('suppressIntentionalPaneCloseExit', () => {
it('suppresses the pane PTY exit before intentional close teardown destroys the transport', () => {
const suppressPtyExit = vi.fn()
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts
index ecb8e78276e..7f721fc0d9f 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts
@@ -310,16 +310,6 @@ export function shouldDetachPaneTransportOnUnmount(args: {
)
}
-export function resolveTerminalGpuAccelerationForRuntime(
- activeRuntimeEnvironmentId: GlobalSettings['activeRuntimeEnvironmentId'] | null | undefined,
- terminalGpuAcceleration: GlobalSettings['terminalGpuAcceleration'] | null | undefined
-): GlobalSettings['terminalGpuAcceleration'] {
- if (activeRuntimeEnvironmentId?.trim()) {
- return 'off'
- }
- return terminalGpuAcceleration ?? 'auto'
-}
-
export function useTerminalPaneLifecycle({
tabId,
worktreeId,
@@ -1058,12 +1048,10 @@ export function useTerminalPaneLifecycle({
// so PTYs survive navigation. Creating WebGL for those offscreen panes
// still consumes Chromium's context budget and can blank visible panes.
initialRenderingSuspended: !isVisibleRef.current,
- // Why: remote-runtime snapshots arrive after pane open; WebGL can hold an
- // empty atlas/canvas while the server-side buffer is already populated.
- terminalGpuAcceleration: resolveTerminalGpuAccelerationForRuntime(
- settingsRef.current?.activeRuntimeEnvironmentId,
- settingsRef.current?.terminalGpuAcceleration
- ),
+ // Why: remote-runtime panes honor the user GPU setting too — snapshots
+ // that arrive after WebGL attaches are handled by the post-replay
+ // rebuildPaneWebgl in pty-connection's replay callback.
+ terminalGpuAcceleration: settingsRef.current?.terminalGpuAcceleration ?? 'auto',
debugLabel: `tab:${tabId}/wt:${worktreeId}`
})
@@ -1382,15 +1370,8 @@ export function useTerminalPaneLifecycle({
}, [settings, systemPrefersDark, effectiveMacOptionAsAlt])
useEffect(() => {
- // Why: remote-runtime panes stay on DOM rendering; local panes still honor
- // the user's GPU setting and can switch live when settings change.
- managerRef.current?.setTerminalGpuAcceleration(
- resolveTerminalGpuAccelerationForRuntime(
- settings?.activeRuntimeEnvironmentId,
- settings?.terminalGpuAcceleration
- )
- )
- }, [settings?.activeRuntimeEnvironmentId, settings?.terminalGpuAcceleration, managerRef])
+ managerRef.current?.setTerminalGpuAcceleration(settings?.terminalGpuAcceleration ?? 'auto')
+ }, [settings?.terminalGpuAcceleration, managerRef])
useEffect(() => {
const manager = managerRef.current
From 0f8ec54c288853649a245bb2fe832e2f64d2e835 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:51:11 -0700
Subject: [PATCH 013/165] Fix worktree card border-radius for multi-selected
state (#5058)
---
.../src/components/sidebar/WorktreeCard.tsx | 108 ++++++++++++++----
1 file changed, 87 insertions(+), 21 deletions(-)
diff --git a/src/renderer/src/components/sidebar/WorktreeCard.tsx b/src/renderer/src/components/sidebar/WorktreeCard.tsx
index 7371d1bac7c..d71fa68af59 100644
--- a/src/renderer/src/components/sidebar/WorktreeCard.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCard.tsx
@@ -121,7 +121,11 @@ function RepoIdentityChip({
{children}
@@ -808,7 +812,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
className={cn(
'group relative flex items-start gap-0.5 pl-0 pr-1.5 pt-1.5 pb-2 cursor-pointer transition-[background-color,border-color,opacity,box-shadow] duration-200 outline-none select-none',
flushSurface ? 'ml-1 w-[calc(100%-0.25rem)]' : 'ml-1',
- isMultiSelected ? 'rounded-sm' : 'rounded-lg',
+ 'rounded-lg',
isActiveSurface
? 'bg-black/[0.08] shadow-[0_1px_2px_rgba(0,0,0,0.04)] border border-black/[0.015] dark:bg-white/[0.10] dark:border-border/40 dark:shadow-[0_1px_2px_rgba(0,0,0,0.03)]'
: isMultiSelected
@@ -837,7 +841,8 @@ const WorktreeCard = React.memo(function WorktreeCard({
- {translate("auto.components.sidebar.WorktreeCard.691ccfd622", "Deleting…")}
+ {translate('auto.components.sidebar.WorktreeCard.691ccfd622', 'Deleting…')}
+
)}
@@ -890,7 +895,15 @@ const WorktreeCard = React.memo(function WorktreeCard({
- {isSshDisconnected ? translate("auto.components.sidebar.WorktreeCard.021538e1d1", "SSH disconnected") : translate("auto.components.sidebar.WorktreeCard.ca74db7550", "Remote project via SSH")}
+ {isSshDisconnected
+ ? translate(
+ 'auto.components.sidebar.WorktreeCard.021538e1d1',
+ 'SSH disconnected'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeCard.ca74db7550',
+ 'Remote project via SSH'
+ )}
)}
@@ -933,13 +946,21 @@ const WorktreeCard = React.memo(function WorktreeCard({
onClick={handleOpenRenameErrorDialog}
onDoubleClick={handleOpenRenameErrorDialog}
className="h-4 shrink-0 gap-0.5 rounded !px-0.5 text-[10px] font-medium leading-none text-destructive border border-destructive/40 bg-destructive/10 hover:bg-destructive/15 hover:text-destructive has-[>svg]:!px-0.5"
- aria-label={translate("auto.components.sidebar.WorktreeCard.02e19349f4", "Auto-rename failed: view error")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorktreeCard.02e19349f4',
+ 'Auto-rename failed: view error'
+ )}
>
- {translate("auto.components.sidebar.WorktreeCard.74522ee457", "rename failed")}
+ {translate('auto.components.sidebar.WorktreeCard.74522ee457', 'rename failed')}
+
- {translate("auto.components.sidebar.WorktreeCard.4eba2ea99e", "Auto-name failed. Click to see details.")}
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.4eba2ea99e',
+ 'Auto-name failed. Click to see details.'
+ )}
+
) : worktree.pendingFirstAgentMessageRename === true && !titleRenaming ? (
@@ -951,13 +972,21 @@ const WorktreeCard = React.memo(function WorktreeCard({
onClick={handlePendingFirstAgentMessageRenameInfo}
onDoubleClick={handlePendingFirstAgentMessageRenameInfo}
className="h-4 shrink-0 gap-0.5 rounded !px-0.5 text-[10px] font-medium leading-none text-muted-foreground border border-worktree-sidebar-border/60 bg-worktree-sidebar-accent/45 hover:bg-worktree-sidebar-accent hover:text-foreground has-[>svg]:!px-0.5"
- aria-label={translate("auto.components.sidebar.WorktreeCard.c6833b5187", "Will be renamed from first agent message")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorktreeCard.c6833b5187',
+ 'Will be renamed from first agent message'
+ )}
>
- {translate("auto.components.sidebar.WorktreeCard.f62a3dadbc", "rename pending")}
+ {translate('auto.components.sidebar.WorktreeCard.f62a3dadbc', 'rename pending')}
+
- {translate("auto.components.sidebar.WorktreeCard.c6833b5187", "Will be renamed from first agent message")}
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.c6833b5187',
+ 'Will be renamed from first agent message'
+ )}
+
) : null}
@@ -968,10 +997,15 @@ const WorktreeCard = React.memo(function WorktreeCard({
variant="outline"
className="h-[16px] px-1.5 text-[10px] font-medium rounded shrink-0 leading-none text-foreground/70 border-foreground/20 bg-foreground/[0.06]"
>
- {translate("auto.components.sidebar.WorktreeCard.7d517f82e2", "primary")}
+ {translate('auto.components.sidebar.WorktreeCard.7d517f82e2', 'primary')}
+
- {translate("auto.components.sidebar.WorktreeCard.0777de5970", "Primary worktree (original clone directory)")}
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.0777de5970',
+ 'Primary worktree (original clone directory)'
+ )}
+
)}
@@ -982,11 +1016,17 @@ const WorktreeCard = React.memo(function WorktreeCard({
variant="outline"
className="h-[16px] px-1.5 text-[10px] font-medium rounded shrink-0 leading-none text-amber-700 dark:text-amber-300 border-amber-500/30 bg-amber-500/5"
>
- {translate("auto.components.sidebar.WorktreeCard.4f964d5e8c", "sparse")}
+ {translate('auto.components.sidebar.WorktreeCard.4f964d5e8c', 'sparse')}
+
-
{translate("auto.components.sidebar.WorktreeCard.0f33af979b", "Partial checkout. Files outside these paths are not on disk.")}
+
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.0f33af979b',
+ 'Partial checkout. Files outside these paths are not on disk.'
+ )}
+
{worktree.sparseDirectories && worktree.sparseDirectories.length > 0 ? (
{formatSparseDirectoryPreview(worktree.sparseDirectories)}
@@ -1017,13 +1057,20 @@ const WorktreeCard = React.memo(function WorktreeCard({
- {translate("auto.components.sidebar.WorktreeCard.0777de5970", "Primary worktree (original clone directory)")}
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.0777de5970',
+ 'Primary worktree (original clone directory)'
+ )}
+
)}
@@ -1040,13 +1087,20 @@ const WorktreeCard = React.memo(function WorktreeCard({
'group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',
'text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive'
)}
- aria-label={translate("auto.components.sidebar.WorktreeCard.6f09f58541", "Delete workspace")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorktreeCard.6f09f58541',
+ 'Delete workspace'
+ )}
>
- {translate("auto.components.sidebar.WorktreeCard.6f09f58541", "Delete workspace")}
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.6f09f58541',
+ 'Delete workspace'
+ )}
+
)}
@@ -1070,7 +1124,9 @@ const WorktreeCard = React.memo(function WorktreeCard({
variant="secondary"
className="h-[16px] px-1.5 text-[10px] font-medium rounded shrink-0 text-muted-foreground bg-accent border border-border dark:bg-accent/80 dark:border-border/50 leading-none"
>
- {repo ? getRepoKindLabel(repo) : translate("auto.components.sidebar.WorktreeCard.93aebe4529", "Folder")}
+ {repo
+ ? getRepoKindLabel(repo)
+ : translate('auto.components.sidebar.WorktreeCard.93aebe4529', 'Folder')}
) : showBranch ? (
@@ -1112,7 +1168,9 @@ const WorktreeCard = React.memo(function WorktreeCard({
- {remoteBranchConflict.remote}/{remoteBranchConflict.branchName} {translate("auto.components.sidebar.WorktreeCard.a88c92d0e3", "already exists.")}
+ {remoteBranchConflict.remote}/{remoteBranchConflict.branchName}{' '}
+ {translate('auto.components.sidebar.WorktreeCard.a88c92d0e3', 'already exists.')}
+
)}
@@ -1159,7 +1217,15 @@ const WorktreeCard = React.memo(function WorktreeCard({
- {lineageCollapsed ? translate("auto.components.sidebar.WorktreeCard.8cb634cda6", "Show child workspaces") : translate("auto.components.sidebar.WorktreeCard.57eaa61b55", "Hide child workspaces")}
+ {lineageCollapsed
+ ? translate(
+ 'auto.components.sidebar.WorktreeCard.8cb634cda6',
+ 'Show child workspaces'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeCard.57eaa61b55',
+ 'Hide child workspaces'
+ )}
From cc12385ccd26042230dc328ecf74632c1ab7d9f1 Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:58:07 -0700
Subject: [PATCH 014/165] Replace pasted work-item URLs with title-derived
workspace names (#5059)
Co-authored-by: Orca
---
src/renderer/src/hooks/useComposerState.ts | 29 ++++++--
.../src/lib/work-item-lookup-text.test.ts | 34 +++++++++
src/renderer/src/lib/work-item-lookup-text.ts | 24 ++++++
tests/e2e/worktree.spec.ts | 74 +++++++++++++++++++
4 files changed, 156 insertions(+), 5 deletions(-)
create mode 100644 src/renderer/src/lib/work-item-lookup-text.test.ts
create mode 100644 src/renderer/src/lib/work-item-lookup-text.ts
diff --git a/src/renderer/src/hooks/useComposerState.ts b/src/renderer/src/hooks/useComposerState.ts
index 31e744b6dce..70a14e5589d 100644
--- a/src/renderer/src/hooks/useComposerState.ts
+++ b/src/renderer/src/hooks/useComposerState.ts
@@ -73,6 +73,7 @@ import {
getSmartGitHubSubmitResolution,
type SmartGitHubSubmitResolution
} from '@/lib/smart-github-submit'
+import { isWorkItemLookupText } from '@/lib/work-item-lookup-text'
import {
canUseRepoBackedComposerSources,
getSelectedRepoSshGate,
@@ -1162,7 +1163,13 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
})
const suggestedName =
getLinkedWorkItemWorkspaceName(item)?.seedName ?? getLinkedWorkItemSuggestedName(item)
- if (suggestedName && (!name.trim() || name === lastAutoNameRef.current)) {
+ // Why: a pasted URL/#123 in the field is the lookup query that found
+ // this item, not a deliberate name — replace it with the title-derived
+ // name or it silently becomes a slugified-URL workspace name.
+ if (
+ suggestedName &&
+ (!name.trim() || name === lastAutoNameRef.current || isWorkItemLookupText(name))
+ ) {
setName(suggestedName)
lastAutoNameRef.current = suggestedName
}
@@ -1250,7 +1257,10 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
title: item.title
})
const nextName = titleName?.seedName ?? suggestedName
- if (nextName && (!name.trim() || name === lastAutoNameRef.current)) {
+ if (
+ nextName &&
+ (!name.trim() || name === lastAutoNameRef.current || isWorkItemLookupText(name))
+ ) {
setName(nextName)
lastAutoNameRef.current = nextName
}
@@ -1808,7 +1818,14 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
setLinkedPR(null)
setLinkedWorkItem(buildLinearIssueLinkedWorkItem(issue))
const suggestedName = getLinearIssueWorkspaceName(issue)
- if (!name.trim() || name === lastAutoNameRef.current) {
+ // Why: same lookup-text rule as applyLinkedWorkItem, plus the typed
+ // Linear identifier ("STA-123") that matched this issue.
+ if (
+ !name.trim() ||
+ name === lastAutoNameRef.current ||
+ isWorkItemLookupText(name) ||
+ name.trim().toLowerCase() === issue.identifier.toLowerCase()
+ ) {
setName(suggestedName)
lastAutoNameRef.current = suggestedName
}
@@ -1929,7 +1946,8 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
const submitTitleName = submitLinkedWorkItem
? getLinkedWorkItemWorkspaceName(submitLinkedWorkItem)
: null
- const nameIsAutoManaged = !name.trim() || name === lastAutoNameRef.current
+ const nameIsAutoManaged =
+ !name.trim() || name === lastAutoNameRef.current || isWorkItemLookupText(name)
const workspaceName =
smartGitHubResolution?.workspaceName ??
(nameIsAutoManaged && submitTitleName ? submitTitleName.seedName : workspaceSeedName)
@@ -2203,7 +2221,8 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
const submitTitleName = submitLinkedWorkItem
? getLinkedWorkItemWorkspaceName(submitLinkedWorkItem)
: null
- const nameIsAutoManaged = !name.trim() || name === lastAutoNameRef.current
+ const nameIsAutoManaged =
+ !name.trim() || name === lastAutoNameRef.current || isWorkItemLookupText(name)
const workspaceName =
smartGitHubResolution?.workspaceName ??
(nameIsAutoManaged && submitTitleName ? submitTitleName.seedName : workspaceNameSeed)
diff --git a/src/renderer/src/lib/work-item-lookup-text.test.ts b/src/renderer/src/lib/work-item-lookup-text.test.ts
new file mode 100644
index 00000000000..46693afce43
--- /dev/null
+++ b/src/renderer/src/lib/work-item-lookup-text.test.ts
@@ -0,0 +1,34 @@
+import { describe, expect, it } from 'vitest'
+import { isWorkItemLookupText } from './work-item-lookup-text'
+
+describe('isWorkItemLookupText', () => {
+ it('detects GitHub PR and issue URLs', () => {
+ expect(isWorkItemLookupText('https://github.com/stablyai/orca/pull/4900')).toBe(true)
+ expect(isWorkItemLookupText('https://github.com/stablyai/orca/issues/123')).toBe(true)
+ expect(isWorkItemLookupText(' https://www.github.com/stablyai/orca/pull/1 ')).toBe(true)
+ })
+
+ it('detects hash-number shorthand', () => {
+ expect(isWorkItemLookupText('#4900')).toBe(true)
+ })
+
+ it('detects GitLab issue and MR URLs on any host', () => {
+ expect(isWorkItemLookupText('https://gitlab.com/group/project/-/merge_requests/7')).toBe(true)
+ expect(isWorkItemLookupText('https://gitlab.example.com/group/sub/project/-/issues/42')).toBe(
+ true
+ )
+ })
+
+ it('detects Linear issue URLs', () => {
+ expect(isWorkItemLookupText('https://linear.app/acme/issue/STA-123/fix-the-bug')).toBe(true)
+ })
+
+ it('rejects deliberate workspace names', () => {
+ expect(isWorkItemLookupText('')).toBe(false)
+ expect(isWorkItemLookupText(' ')).toBe(false)
+ expect(isWorkItemLookupText('my-feature')).toBe(false)
+ expect(isWorkItemLookupText('fix-2')).toBe(false)
+ expect(isWorkItemLookupText('terminal scrollbar polish')).toBe(false)
+ expect(isWorkItemLookupText('https://example.com/some/page')).toBe(false)
+ })
+})
diff --git a/src/renderer/src/lib/work-item-lookup-text.ts b/src/renderer/src/lib/work-item-lookup-text.ts
new file mode 100644
index 00000000000..e8c412d7eac
--- /dev/null
+++ b/src/renderer/src/lib/work-item-lookup-text.ts
@@ -0,0 +1,24 @@
+import { getSmartGitHubSubmitIntent } from './smart-github-submit'
+import { parseGitLabIssueOrMRLink } from './gitlab-links'
+
+const LINEAR_ISSUE_URL_RE = /^https?:\/\/(?:www\.)?linear\.app\/\S+/i
+
+/**
+ * Why: text typed into the smart name field to *find* a work item — a GitHub
+ * or GitLab URL, "#123", or a linear.app link — is a lookup query, never a
+ * deliberate workspace name. Selection handlers use this to decide that the
+ * resolved item's title-derived name may replace the field content; otherwise
+ * the pasted URL silently survives behind the selection pill and the
+ * workspace gets a slugified-URL name.
+ */
+export function isWorkItemLookupText(value: string): boolean {
+ const trimmed = value.trim()
+ if (!trimmed) {
+ return false
+ }
+ return (
+ getSmartGitHubSubmitIntent(trimmed) !== null ||
+ parseGitLabIssueOrMRLink(trimmed) !== null ||
+ LINEAR_ISSUE_URL_RE.test(trimmed)
+ )
+}
diff --git a/tests/e2e/worktree.spec.ts b/tests/e2e/worktree.spec.ts
index 6c7956f129c..8806db77b7a 100644
--- a/tests/e2e/worktree.spec.ts
+++ b/tests/e2e/worktree.spec.ts
@@ -324,4 +324,78 @@ test.describe('Create Workspace', () => {
})
}
})
+
+ test('names the workspace after the PR title when the pasted URL suggestion is selected', async ({
+ electronApp,
+ orcaPage
+ }) => {
+ const title = `E2E selected URL resolution ${Date.now()}`
+ const url = 'https://github.com/stablyai/orca/pull/2050'
+ const linkedWorkspacePattern = new RegExp(title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
+
+ try {
+ await orcaPage.getByRole('button', { name: 'New workspace', exact: true }).click()
+
+ const dialog = orcaPage.getByRole('dialog', { name: /Create (Workspace|Worktree)/i })
+ await expect(dialog).toBeVisible()
+ await expect(dialog.getByRole('combobox').first()).toBeVisible()
+
+ await electronApp.evaluate(
+ ({ ipcMain }, { title, url }) => {
+ ipcMain.removeHandler('gh:workItemByOwnerRepo')
+ ipcMain.handle(
+ 'gh:workItemByOwnerRepo',
+ (_event: unknown, args: { number: number; repoId?: string }) => ({
+ id: `e2e-pr-${args.number}`,
+ type: 'pr',
+ number: args.number,
+ title,
+ state: 'open',
+ url,
+ labels: [],
+ updatedAt: '2026-05-26T00:00:00.000Z',
+ author: 'e2e',
+ repoId: args.repoId ?? 'e2e-repo'
+ })
+ )
+ ipcMain.removeHandler('worktrees:resolvePrBase')
+ // Why: the fixture repo's default branch is master and has no
+ // remote; resolve the PR base to a ref that actually exists.
+ ipcMain.handle('worktrees:resolvePrBase', () => ({ baseBranch: 'master' }))
+ },
+ { title, url }
+ )
+
+ const nameInput = dialog.getByPlaceholder(/Type a name/i)
+ await expect(nameInput).toBeVisible()
+ await nameInput.fill(url)
+
+ // Why: this is the regression PR #4900 missed — selecting the resolved
+ // suggestion row (instead of submitting the raw URL) must not leave the
+ // pasted URL behind as the workspace name. The suggestion popover is
+ // portaled outside the dialog element, so locate it page-wide.
+ const suggestion = orcaPage.getByRole('option', { name: linkedWorkspacePattern })
+ await expect(suggestion).toBeVisible()
+ await suggestion.click()
+
+ const createButton = dialog.getByRole('button', { name: /Create (Workspace|Worktree)/i })
+ await expect(createButton).toBeEnabled()
+ await createButton.click()
+
+ await expect(dialog).toBeHidden({ timeout: 15_000 })
+ await expect(orcaPage.getByRole('option', { name: linkedWorkspacePattern })).toBeVisible({
+ timeout: 10_000
+ })
+ await expect(orcaPage.getByRole('option', { name: /https-github/i })).toHaveCount(0)
+ await expect(orcaPage.getByText('Linked PR #2050')).toBeVisible()
+ } finally {
+ await orcaPage
+ .evaluate(() => {
+ window.__store?.getState().closeModal()
+ })
+ .catch(() => {
+ /* page may already be torn down */
+ })
+ }
+ })
})
From 6d2646df1e8ab091e59caf63e646f32d0e784e4b Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Tue, 9 Jun 2026 17:12:47 -0700
Subject: [PATCH 015/165] Show full details for child worktree cards (#5056)
---
.../src/components/sidebar/WorktreeCard.tsx | 14 +-
.../WorktreeList.lineage-child-card.test.ts | 178 +++++--
...ktreeList.lineage-child-real-card.test.tsx | 392 +++++++++++++++
.../src/components/sidebar/WorktreeList.tsx | 448 ++++++------------
4 files changed, 675 insertions(+), 357 deletions(-)
create mode 100644 src/renderer/src/components/sidebar/WorktreeList.lineage-child-real-card.test.tsx
diff --git a/src/renderer/src/components/sidebar/WorktreeCard.tsx b/src/renderer/src/components/sidebar/WorktreeCard.tsx
index d71fa68af59..ac2f6f73baf 100644
--- a/src/renderer/src/components/sidebar/WorktreeCard.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCard.tsx
@@ -488,6 +488,11 @@ const WorktreeCard = React.memo(function WorktreeCard({
event.stopPropagation()
return
}
+ if (isDeleting) {
+ event.preventDefault()
+ event.stopPropagation()
+ return
+ }
// Why: route sidebar clicks through the shared activation path so the
// back/forward stack stays complete for the primary worktree navigation
// surface instead of only recording palette-driven switches.
@@ -498,7 +503,14 @@ const WorktreeCard = React.memo(function WorktreeCard({
}
onActivate?.()
},
- [worktree.id, isSshDisconnected, onActivate, onImmediateActivate, onSelectionGesture]
+ [
+ worktree.id,
+ isDeleting,
+ isSshDisconnected,
+ onActivate,
+ onImmediateActivate,
+ onSelectionGesture
+ ]
)
const handleRenameTitle = useCallback(
diff --git a/src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts b/src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
index c120f7d24d0..b7235e6e1e5 100644
--- a/src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
+++ b/src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
@@ -59,25 +59,75 @@ vi.mock('./project-header-drag', () => ({
vi.mock('./WorktreeCard', () => ({
default: ({
worktree,
+ repo,
+ isActive,
contentIndent,
flushSurface,
+ lineageChildCount,
+ lineageCollapsed,
lineageChildren
}: {
worktree: Worktree
+ repo?: Repo
+ isActive?: boolean
contentIndent?: number
flushSurface?: boolean
+ lineageChildCount?: number
+ lineageCollapsed?: boolean
lineageChildren?: React.ReactNode
- }) =>
- React.createElement(
+ }) => {
+ const deleteStateByWorktreeId =
+ (mockStore.state.deleteStateByWorktreeId as Record<
+ string,
+ { isDeleting?: boolean } | undefined
+ >) ?? {}
+ const cardProps = (mockStore.state.worktreeCardProperties as string[] | undefined) ?? []
+ const sshState =
+ repo?.connectionId && mockStore.state.sshConnectionStates instanceof Map
+ ? mockStore.state.sshConnectionStates.get(repo.connectionId)
+ : null
+ const isDeleting = deleteStateByWorktreeId[worktree.id]?.isDeleting === true
+ const showSshDialog = isActive && repo?.connectionId && sshState?.status !== 'connected'
+
+ return React.createElement(
'section',
{
'data-worktree-card-id': worktree.id,
+ 'data-worktree-card-active': isActive ? 'true' : undefined,
'data-content-indent': contentIndent,
- 'data-flush-surface': flushSurface ? 'true' : undefined
+ 'data-flush-surface': flushSurface ? 'true' : undefined,
+ 'data-lineage-child-count': lineageChildCount,
+ 'data-lineage-collapsed':
+ lineageCollapsed === undefined ? undefined : String(lineageCollapsed),
+ 'data-linked-pr': worktree.linkedPR ?? undefined,
+ 'data-linked-gitlab-mr': worktree.linkedGitLabMR ?? undefined,
+ 'aria-busy': isDeleting ? 'true' : undefined
},
React.createElement('h2', null, worktree.displayName),
+ isDeleting ? React.createElement('span', null, 'Deleting') : null,
+ cardProps.includes('unread') && worktree.isUnread
+ ? React.createElement('button', { 'aria-label': 'Mark as read' }, 'Unread')
+ : null,
+ lineageChildCount
+ ? React.createElement(
+ 'button',
+ {
+ 'data-lineage-toggle-for': worktree.id,
+ 'aria-expanded': lineageCollapsed ? 'false' : 'true'
+ },
+ `${lineageChildCount} ${lineageChildCount === 1 ? 'child' : 'children'}`
+ )
+ : null,
+ showSshDialog
+ ? React.createElement('aside', {
+ 'data-worktree-card-ssh-dialog': 'open',
+ 'data-ssh-status': sshState?.status ?? 'disconnected',
+ 'data-ssh-target-id': repo?.connectionId
+ })
+ : null,
lineageChildren
)
+ }
}))
vi.mock('./WorktreeCardAgents', () => ({
@@ -206,6 +256,7 @@ function makeLineage(worktree: Worktree, parent: Worktree): WorktreeLineage {
function setLineageFixtureState(
groupBy: 'none' | 'repo' = 'none',
options: {
+ childWorktreeOverrides?: Partial
deletingWorktreeIds?: string[]
projectGrouped?: boolean
unreadWorktreeIds?: string[]
@@ -241,6 +292,7 @@ function setLineageFixtureState(
branch: 'child-branch',
sortOrder: 20
})
+ Object.assign(child, options.childWorktreeOverrides)
const grandchild = makeWorktree({
id: 'grandchild',
instanceId: 'grandchild-instance',
@@ -453,6 +505,18 @@ async function renderWorktreeListMarkup(): Promise {
)
}
+function getCardOpeningTag(markup: string, worktreeId: string): string {
+ return (
+ markup.match(new RegExp(`]*data-worktree-card-id="${worktreeId}"[^>]*>`))?.[0] ?? ''
+ )
+}
+
+function getOptionOpeningTag(markup: string, worktreeId: string): string {
+ return (
+ markup.match(new RegExp(`]*id="worktree-list-option-${worktreeId}"[^>]*>`))?.[0] ?? ''
+ )
+}
+
describe('WorktreeList lineage child card renderer', () => {
beforeAll(async () => {
WorktreeList = (await import('./WorktreeList')).default as WorktreeListComponent
@@ -492,63 +556,76 @@ describe('WorktreeList lineage child card renderer', () => {
expect(markup).not.toContain('empty-project')
})
- it('renders nested inline agent rows before the nested child-count toggle', async () => {
+ it('renders recursive lineage descendants through WorktreeCard once', async () => {
setLineageFixtureState()
const markup = await renderWorktreeListMarkup()
- const childStart = markup.indexOf('lineage child with agent')
- const agentRowIndex = markup.indexOf('Review fixture prompt', childStart)
- const childToggleIndex = markup.indexOf('1 child', childStart)
+ expect(markup.match(/data-worktree-card-id="parent"/g)).toHaveLength(1)
+ expect(markup.match(/data-worktree-card-id="child"/g)).toHaveLength(1)
+ expect(markup.match(/data-worktree-card-id="grandchild"/g)).toHaveLength(1)
- expect(childStart).toBeGreaterThan(-1)
- expect(agentRowIndex).toBeGreaterThan(childStart)
- expect(childToggleIndex).toBeGreaterThan(childStart)
- expect(agentRowIndex).toBeLessThan(childToggleIndex)
+ const parentIndex = markup.indexOf('data-worktree-card-id="parent"')
+ const childIndex = markup.indexOf('data-worktree-card-id="child"')
+ const grandchildIndex = markup.indexOf('data-worktree-card-id="grandchild"')
+
+ expect(parentIndex).toBeGreaterThan(-1)
+ expect(childIndex).toBeGreaterThan(parentIndex)
+ expect(grandchildIndex).toBeGreaterThan(childIndex)
+ expect(getCardOpeningTag(markup, 'child')).toContain('data-lineage-child-count="1"')
})
- it('renders nested child titles through the inline rename surface', async () => {
- setLineageFixtureState()
+ it('passes child review details through the shared WorktreeCard path', async () => {
+ setLineageFixtureState('none', {
+ childWorktreeOverrides: { linkedPR: 456, linkedGitLabMR: 42 }
+ })
const markup = await renderWorktreeListMarkup()
+ const childCard = getCardOpeningTag(markup, 'child')
- expect(markup).toContain('data-worktree-title-inline-rename=""')
- expect(markup).toContain('lineage child with agent')
+ expect(childCard).toContain('data-linked-pr="456"')
+ expect(childCard).toContain('data-linked-gitlab-mr="42"')
})
- it('nests the first-level child workspace card surface under its parent', async () => {
+ it('uses shared nested-row indentation for child and grandchild cards', async () => {
setLineageFixtureState()
const markup = await renderWorktreeListMarkup()
- expect(markup).toContain('
{
setLineageFixtureState('none', { deletingWorktreeIds: ['child'] })
const markup = await renderWorktreeListMarkup()
-
- const childCard =
- markup.match(/
{
setLineageFixtureState('none', { unreadWorktreeIds: ['child'] })
mockStore.state.worktreeCardProperties = ['status', 'unread', 'inline-agents']
const markup = await renderWorktreeListMarkup()
+ const childIndex = markup.indexOf('data-worktree-card-id="child"')
+ const childMarkup = markup.slice(
+ childIndex,
+ markup.indexOf('data-worktree-card-id="grandchild"')
+ )
- const childCard =
- markup.match(/
{
+ it('lets WorktreeCard own the reconnect dialog for an active disconnected lineage child', async () => {
setLineageFixtureState()
const repo = (mockStore.state.repos as Repo[])[0]!
repo.connectionId = 'ssh-target-1'
@@ -558,17 +635,18 @@ describe('WorktreeList lineage child card renderer', () => {
const markup = await renderWorktreeListMarkup()
- expect(markup).toContain('data-lineage-ssh-dialog="open"')
+ expect(getCardOpeningTag(markup, 'child')).toContain('data-worktree-card-active="true"')
+ expect(markup).toContain('data-worktree-card-ssh-dialog="open"')
+ expect(markup).not.toContain('data-lineage-ssh-dialog="open"')
expect(markup).toContain('data-ssh-status="disconnected"')
expect(markup).toContain('data-ssh-target-id="ssh-target-1"')
- expect(markup).toContain('data-ssh-target-label="Remote target"')
})
it('does not add group indentation when grouping is disabled', async () => {
setLineageFixtureState('none')
const markup = await renderWorktreeListMarkup()
- const parentRow = markup.match(/
]*id="worktree-list-option-parent"[^>]*>/)?.[0] ?? ''
+ const parentRow = getOptionOpeningTag(markup, 'parent')
expect(parentRow).toContain('id="worktree-list-option-parent"')
expect(parentRow).not.toContain('padding-left')
@@ -578,23 +656,39 @@ describe('WorktreeList lineage child card renderer', () => {
setLineageFixtureState('repo')
const markup = await renderWorktreeListMarkup()
- const parentRow = markup.match(/
]*id="worktree-list-option-parent"[^>]*>/)?.[0] ?? ''
+ const parentRow = getOptionOpeningTag(markup, 'parent')
expect(parentRow).not.toContain('padding-left')
- expect(markup).toContain(
- '
'
- )
+ expect(getCardOpeningTag(markup, 'parent')).toContain('data-content-indent="20"')
+ expect(getCardOpeningTag(markup, 'parent')).toContain('data-flush-surface="true"')
+ })
+
+ it('keeps nested card inner padding aligned with grouped parent cards', async () => {
+ setLineageFixtureState('repo')
+ const markup = await renderWorktreeListMarkup()
+
+ expect(getOptionOpeningTag(markup, 'child')).toContain('padding-left:14px')
+ expect(getCardOpeningTag(markup, 'child')).toContain('data-content-indent="20"')
+ expect(getCardOpeningTag(markup, 'child')).toContain('data-flush-surface="true"')
+ })
+
+ it('keeps nested card inner padding aligned inside project groups', async () => {
+ setLineageFixtureState('repo', { projectGrouped: true })
+ const markup = await renderWorktreeListMarkup()
+
+ expect(getOptionOpeningTag(markup, 'child')).toContain('padding-left:14px')
+ expect(getCardOpeningTag(markup, 'child')).toContain('data-content-indent="38"')
+ expect(getCardOpeningTag(markup, 'child')).toContain('data-flush-surface="true"')
})
it('adds project group depth to workspace card content indentation', async () => {
setLineageFixtureState('repo', { projectGrouped: true })
const markup = await renderWorktreeListMarkup()
- const parentRow = markup.match(/]*id="worktree-list-option-parent"[^>]*>/)?.[0] ?? ''
+ const parentRow = getOptionOpeningTag(markup, 'parent')
expect(parentRow).not.toContain('padding-left')
- expect(markup).toContain(
- '
'
- )
+ expect(getCardOpeningTag(markup, 'parent')).toContain('data-content-indent="38"')
+ expect(getCardOpeningTag(markup, 'parent')).toContain('data-flush-surface="true"')
})
})
diff --git a/src/renderer/src/components/sidebar/WorktreeList.lineage-child-real-card.test.tsx b/src/renderer/src/components/sidebar/WorktreeList.lineage-child-real-card.test.tsx
new file mode 100644
index 00000000000..9130c45a0f6
--- /dev/null
+++ b/src/renderer/src/components/sidebar/WorktreeList.lineage-child-real-card.test.tsx
@@ -0,0 +1,392 @@
+// @vitest-environment happy-dom
+
+import { act, type ReactNode } from 'react'
+import { createRoot, type Root } from 'react-dom/client'
+import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
+import type { HostedReviewInfo } from '../../../../shared/hosted-review'
+import type {
+ Repo,
+ Worktree,
+ WorktreeCardProperty,
+ WorktreeLineage
+} from '../../../../shared/types'
+
+globalThis.IS_REACT_ACT_ENVIRONMENT = true
+
+const mockStore = vi.hoisted(() => ({
+ state: {} as Record,
+ activateWorktreeFromSidebar: vi.fn(),
+ openModal: vi.fn(),
+ updateWorktreeMeta: vi.fn(),
+ fetchHostedReviewForBranch: vi.fn(),
+ fetchIssue: vi.fn(),
+ fetchLinearIssue: vi.fn(),
+ openTaskPage: vi.fn()
+}))
+
+type WorktreeListComponent = React.ComponentType<{
+ scrollOffsetRef: React.RefObject
+ scrollAnchorRef: React.RefObject
+}>
+
+let WorktreeList: WorktreeListComponent
+
+vi.mock('@/store', () => {
+ const useAppStore = ((selector: (state: Record) => unknown) =>
+ selector(mockStore.state)) as ((
+ selector: (state: Record) => unknown
+ ) => unknown) & {
+ getState: () => Record
+ }
+ useAppStore.getState = () => mockStore.state
+ return { useAppStore }
+})
+
+vi.mock('@tanstack/react-virtual', () => ({
+ defaultRangeExtractor: ({ startIndex, endIndex }: { startIndex: number; endIndex: number }) =>
+ Array.from({ length: endIndex - startIndex + 1 }, (_, index) => startIndex + index),
+ measureElement: () => 32,
+ useVirtualizer: ({ count }: { count: number }) => ({
+ elementsCache: new Map(),
+ getTotalSize: () => count * 96,
+ getVirtualItems: () =>
+ Array.from({ length: count }, (_, index) => ({
+ index,
+ key: `row-${index}`,
+ start: index * 96
+ })),
+ measureElement: vi.fn(),
+ scrollToIndex: vi.fn()
+ })
+}))
+
+vi.mock('@/hooks/useVirtualizedScrollAnchor', () => ({
+ VIRTUALIZED_SCROLL_ANCHOR_RECORD_EVENT: 'orca:test-record-scroll-anchor',
+ useVirtualizedScrollAnchor: vi.fn()
+}))
+
+vi.mock('./project-header-drag', () => ({
+ useRepoHeaderDrag: () => ({
+ state: { draggingRepoId: null, dropIndicatorY: null },
+ onHandlePointerDown: vi.fn()
+ }),
+ isRepoHeaderActionTarget: () => false
+}))
+
+vi.mock('@/components/ui/hover-card', () => ({
+ HoverCard: ({ children }: { children: ReactNode }) => <>{children}>,
+ HoverCardContent: ({ children }: { children: ReactNode }) => (
+ {children}
+ ),
+ HoverCardTrigger: ({ children }: { children: ReactNode }) => <>{children}>
+}))
+
+vi.mock('@/components/ui/tooltip', () => ({
+ Tooltip: ({ children }: { children: ReactNode }) => <>{children}>,
+ TooltipContent: ({ children }: { children: ReactNode }) => <>{children}>,
+ TooltipTrigger: ({ children }: { children: ReactNode }) => <>{children}>
+}))
+
+vi.mock('@/components/ui/dropdown-menu', () => ({
+ DropdownMenu: ({ children }: { children: ReactNode }) => <>{children}>,
+ DropdownMenuContent: ({ children }: { children: ReactNode }) => {children}
,
+ DropdownMenuItem: ({ children, onSelect }: { children: ReactNode; onSelect?: () => void }) => (
+ {children}
+ ),
+ DropdownMenuSeparator: () => ,
+ DropdownMenuSub: ({ children }: { children: ReactNode }) => <>{children}>,
+ DropdownMenuSubContent: ({ children }: { children: ReactNode }) => {children}
,
+ DropdownMenuSubTrigger: ({ children }: { children: ReactNode }) => {children}
,
+ DropdownMenuTrigger: ({ children }: { children: ReactNode }) => <>{children}>
+}))
+
+vi.mock('@/lib/sidebar-worktree-activation', () => ({
+ activateWorktreeFromSidebar: mockStore.activateWorktreeFromSidebar
+}))
+
+vi.mock('@/lib/worktree-activation', () => ({
+ activateAndRevealWorktree: vi.fn()
+}))
+
+vi.mock('@/runtime/runtime-rpc-client', () => ({
+ getActiveRuntimeTarget: () => ({ kind: 'local' }),
+ callRuntimeRpc: vi.fn()
+}))
+
+vi.mock('./CacheTimer', () => ({
+ default: () => null,
+ usePromptCacheCountdownStartedAt: () => null
+}))
+
+vi.mock('./WorktreeCardAgents', () => ({
+ default: ({ worktreeId }: { worktreeId: string }) => (
+ Agent row
+ ),
+ SUPPRESS_WORKTREE_LIST_SCROLL_ADJUSTMENT_EVENT: 'orca:test-suppress-scroll-adjustment'
+}))
+
+vi.mock('./SshDisconnectedDialog', () => ({
+ SshDisconnectedDialog: () => null
+}))
+
+vi.mock('./WorktreeContextMenu', () => ({
+ default: ({ children }: { children: ReactNode }) => <>{children}>,
+ CLOSE_ALL_CONTEXT_MENUS_EVENT: 'orca:test-close-context-menus',
+ WORKTREE_CONTEXT_MENU_SCOPE_ATTR: 'data-orca-context-menu-scope',
+ WORKTREE_NATIVE_CONTEXT_MENU_ATTR: 'data-worktree-native-context-menu'
+}))
+
+function makeRepo(): Repo {
+ return {
+ id: 'repo-1',
+ path: '/tmp/lineage-real-card',
+ displayName: 'lineage-real-card',
+ badgeColor: '#999999',
+ addedAt: 1
+ }
+}
+
+function makeWorktree(args: {
+ id: string
+ displayName: string
+ branch: string
+ sortOrder: number
+ instanceId: string
+ overrides?: Partial
+}): Worktree {
+ return {
+ id: args.id,
+ instanceId: args.instanceId,
+ repoId: 'repo-1',
+ path: `/tmp/lineage-real-card/${args.id}`,
+ displayName: args.displayName,
+ branch: args.branch,
+ head: 'abc123',
+ isBare: false,
+ isMainWorktree: false,
+ comment: '',
+ linkedIssue: null,
+ linkedPR: null,
+ linkedLinearIssue: null,
+ isArchived: false,
+ isUnread: false,
+ isPinned: false,
+ sortOrder: args.sortOrder,
+ lastActivityAt: args.sortOrder,
+ ...args.overrides
+ }
+}
+
+function makeLineage(worktree: Worktree, parent: Worktree): WorktreeLineage {
+ return {
+ worktreeId: worktree.id,
+ worktreeInstanceId: worktree.instanceId!,
+ parentWorktreeId: parent.id,
+ parentWorktreeInstanceId: parent.instanceId!,
+ origin: 'orchestration',
+ capture: { source: 'orchestration-context', confidence: 'explicit' },
+ createdAt: 1
+ }
+}
+
+function makeHostedReview(overrides: Partial = {}): HostedReviewInfo {
+ return {
+ provider: 'gitlab',
+ number: 42,
+ title: 'Child GitLab MR',
+ state: 'open',
+ url: 'https://gitlab.com/acme/orca/-/merge_requests/42',
+ status: 'success',
+ updatedAt: '2026-06-09T00:00:00.000Z',
+ mergeable: 'MERGEABLE',
+ ...overrides
+ }
+}
+
+function setLineageState(options: { deletingChild?: boolean } = {}): void {
+ const repo = makeRepo()
+ const parent = makeWorktree({
+ id: 'parent',
+ instanceId: 'parent-instance',
+ displayName: 'lineage parent',
+ branch: 'parent-branch',
+ sortOrder: 20
+ })
+ const child = makeWorktree({
+ id: 'child',
+ instanceId: 'child-instance',
+ displayName: 'lineage child',
+ branch: 'child-branch',
+ sortOrder: 10,
+ overrides: {
+ linkedGitLabMR: 42,
+ comment: 'Child handoff note'
+ }
+ })
+ mockStore.state = {
+ activeModal: '',
+ activeView: 'terminal',
+ activeWorktreeId: null,
+ agentStatusByPaneKey: {},
+ agentStatusEpoch: 0,
+ browserTabsByWorktree: {},
+ clearPendingRevealWorktreeId: vi.fn(),
+ collapsedGroups: new Set(),
+ deleteStateByWorktreeId: options.deletingChild
+ ? { [child.id]: { isDeleting: true, error: null, canForceDelete: false } }
+ : {},
+ detectedWorktreesByRepo: {},
+ fetchHostedReviewForBranch: mockStore.fetchHostedReviewForBranch,
+ fetchIssue: mockStore.fetchIssue,
+ fetchLinearIssue: mockStore.fetchLinearIssue,
+ filterRepoIds: [],
+ gitConflictOperationByWorktree: {},
+ groupBy: 'none',
+ hideDefaultBranchWorkspace: false,
+ hostedReviewCache: {
+ 'local::repo-1::child-branch': {
+ data: makeHostedReview(),
+ fetchedAt: Date.now(),
+ linkedReviewHintKey: 'gitlab:42'
+ }
+ },
+ issueCache: {},
+ linearIssueCache: {},
+ linearStatus: null,
+ migrationUnsupportedByPtyId: {},
+ openModal: mockStore.openModal,
+ openSettingsPage: vi.fn(),
+ openSettingsTarget: null,
+ openTaskPage: mockStore.openTaskPage,
+ pendingRevealWorktree: null,
+ prCache: {},
+ projectGroups: [],
+ ptyIdsByTabId: {},
+ recordFeatureInteraction: vi.fn(),
+ remoteBranchConflictByWorktreeId: {},
+ reorderRepos: vi.fn(),
+ reportVisibleGitHubPRRefreshCandidates: vi.fn(),
+ repos: [repo],
+ retainedAgentsByPaneKey: {},
+ revealWorktreeInSidebar: vi.fn(),
+ runtimePaneTitlesByTabId: {},
+ setFilterRepoIds: vi.fn(),
+ setHideDefaultBranchWorkspace: vi.fn(),
+ setRenamingWorktreeId: vi.fn(),
+ setShowSleepingWorkspaces: vi.fn(),
+ setSortBy: vi.fn(),
+ setWorktreesPinnedAndReveal: vi.fn(),
+ settings: null,
+ showSleepingWorkspaces: true,
+ sortBy: 'manual',
+ sortEpoch: 0,
+ sshConnectedGeneration: 0,
+ sshConnectionStates: new Map(),
+ sshTargetLabels: new Map(),
+ tabsByWorktree: {},
+ terminalLayoutsByTabId: {},
+ toggleCollapsedGroup: vi.fn(),
+ updateRepo: vi.fn(),
+ updateWorktreeMeta: mockStore.updateWorktreeMeta,
+ updateWorktreesMeta: vi.fn(),
+ workspacePortScan: null,
+ workspaceStatuses: [],
+ worktreeCardProperties: [
+ 'status',
+ 'pr',
+ 'comment',
+ 'inline-agents'
+ ] satisfies WorktreeCardProperty[],
+ worktreeLineageById: {
+ [child.id]: makeLineage(child, parent)
+ },
+ worktreesByRepo: {
+ [repo.id]: [parent, child]
+ }
+ }
+}
+
+const mountedRoots: Root[] = []
+
+async function renderWorktreeList(): Promise {
+ const container = document.createElement('div')
+ document.body.appendChild(container)
+ const root = createRoot(container)
+ mountedRoots.push(root)
+ await act(async () => {
+ root.render(
+
+ )
+ })
+ return container
+}
+
+describe('WorktreeList real child WorktreeCard integration', () => {
+ beforeAll(async () => {
+ WorktreeList = (await import('./WorktreeList')).default as WorktreeListComponent
+ }, 20_000)
+
+ beforeEach(() => {
+ vi.clearAllMocks()
+ setLineageState()
+ })
+
+ afterEach(async () => {
+ await act(async () => {
+ for (const root of mountedRoots.splice(0)) {
+ root.unmount()
+ }
+ })
+ document.body.innerHTML = ''
+ })
+
+ it('renders GitLab MR metadata from a child through the real WorktreeCard path', async () => {
+ const container = await renderWorktreeList()
+ const childOption = container.querySelector('#worktree-list-option-child')
+
+ expect(childOption?.textContent).toContain('MR #42')
+ expect(childOption?.textContent).toContain('Child GitLab MR')
+ expect(childOption?.textContent).toContain('Child handoff note')
+ })
+
+ it('double-clicking a nested child opens edit metadata for the child only', async () => {
+ const container = await renderWorktreeList()
+ const childCard = container.querySelector(
+ '#worktree-list-option-child [data-worktree-card-surface="true"]'
+ )
+
+ expect(childCard).not.toBeNull()
+ await act(async () => {
+ childCard!.dispatchEvent(new MouseEvent('dblclick', { bubbles: true }))
+ })
+
+ expect(mockStore.openModal).toHaveBeenCalledTimes(1)
+ expect(mockStore.openModal).toHaveBeenCalledWith(
+ 'edit-meta',
+ expect.objectContaining({
+ worktreeId: 'child',
+ currentDisplayName: 'lineage child',
+ currentComment: 'Child handoff note'
+ })
+ )
+ expect(mockStore.openModal).not.toHaveBeenCalledWith(
+ 'edit-meta',
+ expect.objectContaining({ worktreeId: 'parent' })
+ )
+ })
+
+ it('does not activate a nested child while it is deleting', async () => {
+ setLineageState({ deletingChild: true })
+ const container = await renderWorktreeList()
+ const childCard = container.querySelector(
+ '#worktree-list-option-child [data-worktree-card-surface="true"]'
+ )
+
+ expect(childCard?.textContent).toContain('Deleting')
+ await act(async () => {
+ childCard!.dispatchEvent(new MouseEvent('click', { bubbles: true }))
+ })
+
+ expect(mockStore.activateWorktreeFromSidebar).not.toHaveBeenCalled()
+ })
+})
diff --git a/src/renderer/src/components/sidebar/WorktreeList.tsx b/src/renderer/src/components/sidebar/WorktreeList.tsx
index f3ac35f8cf7..4a76cee05c3 100644
--- a/src/renderer/src/components/sidebar/WorktreeList.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeList.tsx
@@ -12,12 +12,10 @@ import {
Eye,
FolderInput,
FolderPlus,
- Loader2,
Plus,
Shapes,
SlidersHorizontal,
- Trash2,
- Workflow
+ Trash2
} from 'lucide-react'
import { useAppStore } from '@/store'
import { useShallow } from 'zustand/react/shallow'
@@ -30,12 +28,7 @@ import {
} from '@/store/selectors'
import WorktreeCard from './WorktreeCard'
import { PendingWorktreeRow } from './PendingWorktreeRow'
-import WorktreeCardAgents, {
- SUPPRESS_WORKTREE_LIST_SCROLL_ADJUSTMENT_EVENT
-} from './WorktreeCardAgents'
-import { WorktreeTitleInlineRename } from './WorktreeTitleInlineRename'
-import { SshDisconnectedDialog } from './SshDisconnectedDialog'
-import { WorktreeCardStatusSlot } from './WorktreeCardStatusSlot'
+import { SUPPRESS_WORKTREE_LIST_SCROLL_ADJUSTMENT_EVENT } from './WorktreeCardAgents'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import {
@@ -117,14 +110,12 @@ import {
type VirtualizedScrollAnchor
} from '@/hooks/useVirtualizedScrollAnchor'
import { activateAndRevealWorktree } from '@/lib/worktree-activation'
-import { activateWorktreeFromSidebar } from '@/lib/sidebar-worktree-activation'
import { getShortcutPlatform } from '@/lib/shortcut-platform'
import {
SCROLL_TO_CURRENT_WORKSPACE_REVEAL_REQUEST_EVENT,
type ScrollToCurrentWorkspaceRevealRequestDetail
} from '@/lib/scroll-to-current-workspace-status'
import { isRepoHeaderActionTarget, useRepoHeaderDrag } from './project-header-drag'
-import WorktreeContextMenu from './WorktreeContextMenu'
import {
buildManualOrderUpdatesForGroupDrop,
buildManualOrderUpdatesForVisibleGroups,
@@ -176,7 +167,6 @@ import {
pruneWorktreeSelection,
updateWorktreeSelection
} from './worktree-multi-selection'
-import { branchDisplayName } from './WorktreeCardHelpers'
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
import { getRepoHeaderCreateState } from './repo-header-create-state'
import type { PendingSidebarWorktreeReveal } from '@/store/slices/ui'
@@ -191,7 +181,6 @@ import {
} from '../../../../shared/worktree-ownership'
import { RepoIconGlyph } from '@/components/repo/repo-icon'
import { RepoForkIndicator } from '@/components/repo/repo-fork-indicator'
-import { RepoBadgeMark } from '@/components/repo/RepoBadgeLabel'
import ImportedWorktreesVisibilityLine from './ImportedWorktreesVisibilityLine'
import {
keepImportedWorktreesHiddenCard,
@@ -362,10 +351,10 @@ function getWorktreeVisibilityMenuLabel(repo: Repo): string {
return visibility === 'show' ? 'Hide non-Orca worktrees' : 'Show hidden worktrees'
}
-// Why: child workspace cards are already nested inside the parent card body;
-// using the full tree step makes the second-level card drift too far right.
-const LINEAGE_INDENT = 14
const SIDEBAR_POINTER_DRAG_THRESHOLD_PX = 4
+// Why: nested child worktree cards sit inside the parent card body. Preserve
+// the legacy lineage surface offset instead of using the full sidebar tree step.
+const NESTED_LINEAGE_CARD_INDENT = 14
type VirtualizedWorktreeViewportProps = {
rows: Row[]
@@ -396,7 +385,6 @@ type VirtualizedWorktreeViewportProps = {
selectedWorktrees: readonly Worktree[]
onSelectionGesture: (event: React.MouseEvent, worktreeId: string) => boolean
onImmediateWorktreeActivate: (worktreeId: string) => void
- onToggleWorktreeUnread: (worktree: Worktree) => void
onContextMenuSelect: (
event: React.MouseEvent,
worktree: Worktree
@@ -439,7 +427,6 @@ type VirtualizedWorktreeViewportProps = {
draggedIds: readonly string[]
dropIndex: number
}) => void
- showInlineAgentCards: boolean
// Why: broad grouping changes still remount the viewport, while add/delete
// stays mounted for row-key anchoring and layout animation. These refs bridge
// both paths so the virtualizer never falls back to scrollTop 0.
@@ -744,7 +731,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
selectedWorktrees,
onSelectionGesture,
onImmediateWorktreeActivate,
- onToggleWorktreeUnread,
onContextMenuSelect,
repoMap,
worktreeMap,
@@ -762,7 +748,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
onDropWorktreesOnWorkspaceBoard,
shouldShowWorkspaceBoardDropIndicator,
onReorderWorktrees,
- showInlineAgentCards,
scrollOffsetRef,
scrollAnchorRef
}: VirtualizedWorktreeViewportProps) {
@@ -771,7 +756,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
const directScrollInputUntilRef = useRef(0)
const [dragOverStatus, setDragOverStatus] = useState(null)
const [pinDragOver, setPinDragOver] = useState(false)
- const [lineageReconnectWorktreeId, setLineageReconnectWorktreeId] = useState(null)
const [worktreeDragState, setWorktreeDragState] = useState(
WORKTREE_ROW_DRAG_INITIAL_STATE
)
@@ -780,9 +764,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
const [highlightedRevealWorktreeId, setHighlightedRevealWorktreeId] = useState(
null
)
- const renamingWorktreeId = useAppStore((s) => s.renamingWorktreeId)
const setRenamingWorktreeId = useAppStore((s) => s.setRenamingWorktreeId)
- const updateWorktreeMeta = useAppStore((s) => s.updateWorktreeMeta)
const worktreeDragSessionRef = useRef(null)
const worktreePointerDragRef = useRef(null)
const worktreePointerAutoscrollFrameIdRef = useRef(null)
@@ -851,7 +833,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
const sshConnectedGeneration = useAppStore((s) => s.sshConnectedGeneration)
const prVisibleRefreshGeneration = useAppStore((s) => s.prVisibleRefreshGeneration)
const settings = useAppStore((s) => s.settings)
- const deleteStateByWorktreeId = useAppStore((s) => s.deleteStateByWorktreeId)
const reorderRepos = useAppStore((s) => s.reorderRepos)
useEffect(
@@ -1015,41 +996,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
() => renderRows.findIndex((row) => renderRowContainsWorktree(row, activeWorktreeId)),
[renderRows, activeWorktreeId]
)
- const activeLineageChildRow = useMemo(() => {
- if (activeWorktreeId === null) {
- return null
- }
- for (const row of renderRows) {
- if (row.type !== 'lineage-group') {
- continue
- }
- const child = row.rows.slice(1).find((item) => item.worktree.id === activeWorktreeId)
- if (child) {
- return child
- }
- }
- return null
- }, [activeWorktreeId, renderRows])
- const activeLineageChildWorktreeId = activeLineageChildRow?.worktree.id ?? null
- const activeLineageChildConnectionId = activeLineageChildRow?.repo?.connectionId ?? null
- const activeLineageChildSshStatus = useAppStore((s) =>
- activeLineageChildConnectionId
- ? (s.sshConnectionStates.get(activeLineageChildConnectionId)?.status ?? 'disconnected')
- : null
- )
- const activeLineageChildTargetLabel = useAppStore((s) =>
- activeLineageChildConnectionId ? s.sshTargetLabels.get(activeLineageChildConnectionId) : null
- )
const sshConnectionStates = useAppStore((s) => s.sshConnectionStates)
- const activeLineageChildSshDisconnected =
- activeLineageChildSshStatus !== null && activeLineageChildSshStatus !== 'connected'
- const lineageReconnectPromptKey =
- activeLineageChildWorktreeId && activeLineageChildSshDisconnected
- ? activeLineageChildWorktreeId
- : null
- const [lastLineageReconnectPromptKey, setLastLineageReconnectPromptKey] = useState(
- null
- )
const renderRowsRef = useRef(renderRows)
renderRowsRef.current = renderRows
const getVirtualItemKey = useCallback(
@@ -1536,16 +1483,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
return () => window.removeEventListener('keydown', handleKeyDown, { capture: true })
}, [activeModal, keybindings, markDirectScrollInput, navigateWorktree])
- // Why: lightweight nested cards do not mount WorktreeCard, so the viewport
- // owns the SSH reconnect prompt for an active lineage child. The prompt key
- // keeps dismissals sticky until the active/disconnected child changes.
- if (lineageReconnectPromptKey !== lastLineageReconnectPromptKey) {
- setLastLineageReconnectPromptKey(lineageReconnectPromptKey)
- if (lineageReconnectPromptKey) {
- setLineageReconnectWorktreeId(lineageReconnectPromptKey)
- }
- }
-
const handleContainerKeyDown = useCallback(
(e: React.KeyboardEvent) => {
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
@@ -2753,7 +2690,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
data-worktree-sidebar
tabIndex={0}
role="listbox"
- aria-label={translate("auto.components.sidebar.WorktreeList.bfbedc547b", "Worktrees")}
+ aria-label={translate('auto.components.sidebar.WorktreeList.bfbedc547b', 'Worktrees')}
aria-orientation="vertical"
aria-multiselectable="true"
aria-activedescendant={activeDescendantId}
@@ -2770,24 +2707,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
className="worktree-sidebar-scrollbar h-full overflow-y-scroll overflow-x-hidden pl-1 scrollbar-sleek outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset pt-px"
style={WORKTREE_SIDEBAR_SCROLL_STYLE}
>
- {activeLineageChildConnectionId && activeLineageChildSshStatus ? (
- {
- if (!open) {
- setLineageReconnectWorktreeId(null)
- }
- }}
- targetId={activeLineageChildConnectionId}
- targetLabel={
- activeLineageChildTargetLabel ?? activeLineageChildRow?.repo?.displayName ?? ''
- }
- status={activeLineageChildSshStatus}
- />
- ) : null}
event.stopPropagation()}
onKeyDown={stopRepoHeaderKeyboardToggle}
onPointerDown={handleRepoHeaderActionPointerDown}
@@ -3035,7 +2958,11 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
}
}}
>
- {translate("auto.components.sidebar.WorktreeList.4d7b73658c", "Rename group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.4d7b73658c',
+ 'Rename group'
+ )}
+
{
@@ -3044,12 +2971,16 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
}
}}
>
- {translate("auto.components.sidebar.WorktreeList.902115cdbe", "Delete group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.902115cdbe',
+ 'Delete group'
+ )}
+
) : null}
- {row.repo && groupBy === "repo" ? (
+ {row.repo && groupBy === 'repo' ? (
@@ -3060,7 +2991,11 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
size="icon-xs"
data-repo-header-action=""
className="size-5 shrink-0 rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-accent/70 hover:text-foreground focus:opacity-100 group-hover:opacity-100 data-[state=open]:opacity-100"
- aria-label={translate("auto.components.sidebar.WorktreeList.609633a9e6", "Project actions for {{value0}}", { value0: row.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorktreeList.609633a9e6',
+ 'Project actions for {{value0}}',
+ { value0: row.label }
+ )}
onClick={(event) => event.stopPropagation()}
onKeyDown={stopRepoHeaderKeyboardToggle}
onPointerDown={handleRepoHeaderActionPointerDown}
@@ -3070,7 +3005,11 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
- {translate("auto.components.sidebar.WorktreeList.2ef41bf9a7", "Project actions")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.2ef41bf9a7',
+ 'Project actions'
+ )}
+
- {translate("auto.components.sidebar.WorktreeList.2cdffbc728", "Project Settings")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.2cdffbc728',
+ 'Project Settings'
+ )}
+
{
if (row.repo) {
@@ -3106,7 +3049,11 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
}}
>
- {translate("auto.components.sidebar.WorktreeList.e82d3589a1", "Change Project Icon")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.e82d3589a1',
+ 'Change Project Icon'
+ )}
+
{row.repo && isGitRepoKind(row.repo) ? (
{
@@ -3127,12 +3074,20 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
}}
>
- {translate("auto.components.sidebar.WorktreeList.cbfd565f83", "New group from project")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.cbfd565f83',
+ 'New group from project'
+ )}
+
{projectGroups.length > 0 ? (
- {translate("auto.components.sidebar.WorktreeList.4a08fb55f2", "Move to group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.4a08fb55f2',
+ 'Move to group'
+ )}
+
{projectGroups.map((group) => (
- {translate("auto.components.sidebar.WorktreeList.64e55f7f01", "Remove from group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.64e55f7f01',
+ 'Remove from group'
+ )}
+
) : null}
- {translate("auto.components.sidebar.WorktreeList.c83968f87f", "Remove Project")}
+ {translate(
+ 'auto.components.sidebar.WorktreeList.c83968f87f',
+ 'Remove Project'
+ )}
+
) : null}
- {row.repo && groupBy === "repo" ? (
+ {row.repo && groupBy === 'repo' ? (
{createState?.disabled ? (
@@ -3208,7 +3171,12 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
data-repo-header-action=""
className="size-5 shrink-0 rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-accent/70 hover:text-foreground focus:opacity-100 group-hover:opacity-100"
aria-label={
- createState?.ariaLabel ?? translate("auto.components.sidebar.WorktreeList.bb85cd86ba", "Create workspace for {{value0}}", { value0: row.label })
+ createState?.ariaLabel ??
+ translate(
+ 'auto.components.sidebar.WorktreeList.bb85cd86ba',
+ 'Create workspace for {{value0}}',
+ { value0: row.label }
+ )
}
onKeyDown={stopRepoHeaderKeyboardToggle}
onClick={(event) => {
@@ -3224,7 +3192,12 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
)}
- {createState?.tooltip ?? translate("auto.components.sidebar.WorktreeList.bb85cd86ba", "Create workspace for {{value0}}", { value0: row.label })}
+ {createState?.tooltip ??
+ translate(
+ 'auto.components.sidebar.WorktreeList.bb85cd86ba',
+ 'Create workspace for {{value0}}',
+ { value0: row.label }
+ )}
) : null}
@@ -3240,9 +3213,17 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
forceActiveSurface = false
) => {
const lineageToggleGroupKey = itemRow.lineageGroupKey
- // Why: child cards render inside the parent card body, so their
- // first nested level starts flush with that inset.
+ // Why: child card rows own lineage depth, while WorktreeCard
+ // still owns the project/group inset inside each card surface.
const paddingDepth = nested ? Math.max(0, itemRow.depth - 1) : itemRow.depth
+ const nestedCardPaddingLeft = nested
+ ? Math.max(0, itemRow.depth) * NESTED_LINEAGE_CARD_INDENT
+ : 0
+ const inheritedCardContentIndent = getWorktreeCardContentIndent({
+ isGrouped: groupBy !== 'none',
+ groupDepth: itemRow.groupDepth,
+ lineageDepth: 0
+ })
// Why: grouped rows inherit their project/group header depth,
// while the card surface still spans the full hit/background row.
const paddingLeft = getWorktreeCardContentIndent({
@@ -3250,6 +3231,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
groupDepth: itemRow.groupDepth,
lineageDepth: paddingDepth
})
+ const cardContentIndent = nested ? inheritedCardContentIndent : paddingLeft
const worktreeDragGroupKey = groupKeyByWorktreeId.get(itemRow.worktree.id)
const worktreeDragGroupIndex = groupIndexByWorktreeId.get(itemRow.worktree.id)
const revealHighlightTone =
@@ -3286,7 +3268,8 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
nested ? undefined : handleWorktreeRowPointerDown(event, itemRow.worktree.id)
}
style={{
- paddingLeft: nested && paddingLeft > 0 ? `${paddingLeft}px` : undefined
+ paddingLeft:
+ nested && nestedCardPaddingLeft > 0 ? `${nestedCardPaddingLeft}px` : undefined
}}
>
{
- const isActive = activeWorktreeId === child.worktree.id
- const isDeleting = deleteStateByWorktreeId[child.worktree.id]?.isDeleting ?? false
- const revealHighlightTone =
- agentSendTargetWorktreeId === child.worktree.id ? 'ai' : 'default'
- const showStatus = cardProps.includes('status')
- const showUnreadQuickAction = cardProps.includes('unread')
- const unreadTooltip = child.worktree.isUnread ? 'Mark read' : 'Mark unread'
- const stopQuickActionPointerPropagation = (
- event: React.PointerEvent
- ) => {
- event.stopPropagation()
- }
- const handleToggleUnreadQuick = (event: React.MouseEvent) => {
- event.preventDefault()
- event.stopPropagation()
- onToggleWorktreeUnread(child.worktree)
- }
- const handleClick = (event: React.MouseEvent) => {
- event.preventDefault()
- event.stopPropagation()
- if (isDeleting) {
- return
+ const renderLineageDescendants = (
+ parent: WorktreeItemRow,
+ descendants: readonly WorktreeItemRow[]
+ ): React.ReactNode | undefined => {
+ const childNodes: React.ReactNode[] = []
+ let cursor = 0
+ while (cursor < descendants.length) {
+ const child = descendants[cursor]
+ if (!child || child.depth !== parent.depth + 1) {
+ cursor++
+ continue
}
- const selectionOnly = onSelectionGesture(event, child.worktree.id)
- if (selectionOnly) {
- return
- }
- onImmediateWorktreeActivate(child.worktree.id)
- activateWorktreeFromSidebar(child.worktree.id)
- if (child.repo?.connectionId) {
- const sshStatus =
- useAppStore.getState().sshConnectionStates.get(child.repo.connectionId)
- ?.status ?? 'disconnected'
- if (sshStatus !== 'connected') {
- setLineageReconnectWorktreeId(child.worktree.id)
- }
+
+ let nextSiblingIndex = cursor + 1
+ while (
+ nextSiblingIndex < descendants.length &&
+ descendants[nextSiblingIndex]!.depth > child.depth
+ ) {
+ nextSiblingIndex++
}
+
+ const childLineageChildren = renderLineageDescendants(
+ child,
+ descendants.slice(cursor + 1, nextSiblingIndex)
+ )
+ childNodes.push(renderWorktreeRow(child, true, childLineageChildren))
+ cursor = nextSiblingIndex
}
- const lineageToggleGroupKey = child.lineageGroupKey
- const childCardIndent = Math.max(0, child.depth) * LINEAGE_INDENT
- const childContentIndent = Math.max(0, child.depth - 1) * LINEAGE_INDENT
- return (
- 0 ? { paddingLeft: `${childCardIndent}px` } : undefined}
- >
-
onContextMenuSelect(event, child.worktree)}
- >
- event.stopPropagation()}
- >
- {isDeleting && (
-
-
-
- {translate("auto.components.sidebar.WorktreeList.5fc9d1891b", "Deleting…")}
-
- )}
-
0
- ? { paddingLeft: `calc(0.5rem + ${childContentIndent}px)` }
- : undefined
- }
- >
-
-
-
-
-
- updateWorktreeMeta(child.worktree.id, { displayName })
- }
- beginEditing={renamingWorktreeId === child.worktree.id}
- onBeginEditingConsumed={() => setRenamingWorktreeId(null)}
- />
-
- {child.repo && groupBy !== "repo" ? (
-
-
-
- {child.repo.displayName}
-
-
- ) : null}
-
- {branchDisplayName(child.worktree.branch)}
-
-
- {child.worktree.linkedIssue || child.worktree.comment ? (
-
- {child.worktree.linkedIssue ? (
-
- #{child.worktree.linkedIssue}
-
- ) : null}
- {child.worktree.linkedIssue && child.worktree.comment ? ' ' : null}
- {child.worktree.comment}
-
- ) : null}
- {showInlineAgentCards ? (
- // Why: nested lineage children use this lightweight
- // renderer instead of WorktreeCard, so their inline
- // agent rows must be mounted here explicitly.
-
- ) : null}
- {child.lineageChildCount > 0 && lineageToggleGroupKey ? (
-
-
-
- {
- event.preventDefault()
- event.stopPropagation()
- toggleGroupWithScrollAnchor(lineageToggleGroupKey)
- }}
- >
-
-
- {child.lineageChildCount}{' '}
- {child.lineageChildCount === 1 ? translate("auto.components.sidebar.WorktreeList.0c6ee14f23", "child") : translate("auto.components.sidebar.WorktreeList.045a8aed48", "children")}
-
-
-
-
-
- {child.lineageCollapsed
- ? translate("auto.components.sidebar.WorktreeList.84a2238242", "Show child workspaces")
- : translate("auto.components.sidebar.WorktreeList.ebc5c7dcef", "Hide child workspaces")}
-
-
-
- ) : null}
-
-
-
-
-
- )
+
+ return childNodes.length > 0 ? childNodes : undefined
}
if (row.type === 'lineage-group') {
@@ -3554,9 +3374,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
? renderWorktreeRow(
parent,
false,
- children.length > 0
- ? children.map((child) => renderLineageChildCard(child))
- : undefined,
+ renderLineageDescendants(parent, children),
childIsActive
)
: null}
@@ -4456,13 +4274,6 @@ const WorktreeList = React.memo(function WorktreeList({
[updateWorktreeMeta, worktreeMap, workspaceStatuses]
)
- const toggleWorktreeUnread = useCallback(
- (worktree: Worktree) => {
- void updateWorktreeMeta(worktree.id, { isUnread: !worktree.isUnread })
- },
- [updateWorktreeMeta]
- )
-
const moveWorktreesToStatus = useCallback(
(worktreeIds: readonly string[], status: WorkspaceStatus) => {
const updates = new Map()
@@ -4711,14 +4522,17 @@ const WorktreeList = React.memo(function WorktreeList({
>
- {translate("auto.components.sidebar.WorktreeList.b7acbf038b", "No workspaces found")}
+
+ {translate('auto.components.sidebar.WorktreeList.b7acbf038b', 'No workspaces found')}
+
{hasFilters && (
- {translate("auto.components.sidebar.WorktreeList.370c6a55dd", "Clear Filters")}
+ {translate('auto.components.sidebar.WorktreeList.370c6a55dd', 'Clear Filters')}
+
)}
@@ -4731,12 +4545,20 @@ const WorktreeList = React.memo(function WorktreeList({
From 93e59ab0867a81d93c74b6e341aa53a7260febd4 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 20:55:20 -0400
Subject: [PATCH 016/165] fix(mobile): recover Android remote sessions without
an app restart (#5061)
Co-authored-by: Orca
---
mobile/app/h/[hostId]/files/[worktreeId].tsx | 25 +--
.../app/h/[hostId]/session/[worktreeId].tsx | 40 +++-
.../[hostId]/source-control/[worktreeId].tsx | 30 +--
...ssue-5049-unresponsive-session-findings.md | 92 ++++++++
mobile/package.json | 1 +
mobile/pnpm-lock.yaml | 30 ++-
mobile/src/session/worktree-label.ts | 12 +
mobile/src/transport/client-context.tsx | 29 ++-
.../connection-revival-triggers.test.ts | 94 ++++++++
.../transport/connection-revival-triggers.ts | 50 +++++
.../rpc-client-live-recovery.test.ts | 208 ++++++++++++++++++
mobile/src/transport/rpc-client.test.ts | 114 ++++++++++
mobile/src/transport/rpc-client.ts | 208 ++++++++----------
mobile/src/transport/socket-event-debug.ts | 34 +++
14 files changed, 798 insertions(+), 169 deletions(-)
create mode 100644 mobile/issue-5049-unresponsive-session-findings.md
create mode 100644 mobile/src/session/worktree-label.ts
create mode 100644 mobile/src/transport/connection-revival-triggers.test.ts
create mode 100644 mobile/src/transport/connection-revival-triggers.ts
create mode 100644 mobile/src/transport/rpc-client-live-recovery.test.ts
create mode 100644 mobile/src/transport/socket-event-debug.ts
diff --git a/mobile/app/h/[hostId]/files/[worktreeId].tsx b/mobile/app/h/[hostId]/files/[worktreeId].tsx
index 1f3d620d068..8180baafb81 100644
--- a/mobile/app/h/[hostId]/files/[worktreeId].tsx
+++ b/mobile/app/h/[hostId]/files/[worktreeId].tsx
@@ -11,7 +11,8 @@ import {
import { SafeAreaView } from 'react-native-safe-area-context'
import { useLocalSearchParams, useRouter } from 'expo-router'
import { ChevronDown, ChevronLeft, ChevronRight, File, FileText, Folder } from 'lucide-react-native'
-import { useHostClient } from '../../../../src/transport/client-context'
+import { useHostClient, useForceReconnect } from '../../../../src/transport/client-context'
+import { getWorktreeLabel } from '../../../../src/session/worktree-label'
import type { RpcSuccess } from '../../../../src/transport/types'
import { triggerError, triggerSelection } from '../../../../src/platform/haptics'
import { colors, radii, spacing, typography } from '../../../../src/theme/mobile-theme'
@@ -104,17 +105,6 @@ function isMarkdownPath(relativePath: string): boolean {
return /\.(md|mdx|markdown)$/i.test(relativePath)
}
-function getWorktreeLabel(name: string | undefined, worktreeId: string): string {
- if (name?.trim()) {
- return name.trim()
- }
- const pathPart = worktreeId.includes('::')
- ? worktreeId.slice(worktreeId.indexOf('::') + 2)
- : worktreeId
- const normalized = pathPart.replace(/\\/g, '/').replace(/\/+$/, '')
- return normalized.slice(normalized.lastIndexOf('/') + 1) || 'Worktree'
-}
-
export default function MobileFileExplorerScreen() {
const { hostId, worktreeId, name } = useLocalSearchParams<{
hostId: string
@@ -123,6 +113,7 @@ export default function MobileFileExplorerScreen() {
}>()
const router = useRouter()
const { client, state: connState } = useHostClient(hostId)
+ const forceReconnect = useForceReconnect()
const [files, setFiles] = useState([])
const [expanded, setExpanded] = useState>(() => new Set())
const [loading, setLoading] = useState(true)
@@ -287,7 +278,15 @@ export default function MobileFileExplorerScreen() {
) : error ? (
{error}
- void loadFiles()}>
+ {/* Why: while disconnected, re-sending the request is useless — revive
+ the parked transport instead (issue #5049); loadFiles re-runs via
+ its effect once the new client connects. */}
+
+ connState !== 'connected' && hostId ? void forceReconnect(hostId) : void loadFiles()
+ }
+ >
Retry
diff --git a/mobile/app/h/[hostId]/session/[worktreeId].tsx b/mobile/app/h/[hostId]/session/[worktreeId].tsx
index a9cc8eb7075..c5d8fb5527e 100644
--- a/mobile/app/h/[hostId]/session/[worktreeId].tsx
+++ b/mobile/app/h/[hostId]/session/[worktreeId].tsx
@@ -46,7 +46,13 @@ import {
} from 'lucide-react-native'
import type { RpcClient } from '../../../../src/transport/rpc-client'
import { loadHosts } from '../../../../src/transport/host-store'
-import { useHostClient } from '../../../../src/transport/client-context'
+import {
+ useHostClient,
+ useForceReconnect,
+ useReconnectAttempt,
+ useLastConnectedAt
+} from '../../../../src/transport/client-context'
+import { classifyConnection } from '../../../../src/transport/connection-health'
import type { ConnectionState, RpcFailure, RpcSuccess } from '../../../../src/transport/types'
import { useMobileDictation } from '../../../../src/hooks/use-mobile-dictation'
import {
@@ -924,6 +930,9 @@ export default function SessionScreen() {
// Why: shared client per host owned by RpcClientProvider. See
// docs/mobile-shared-client-per-host.md.
const { client, state: connState } = useHostClient(hostId)
+ const reconnectAttempts = useReconnectAttempt(hostId)
+ const lastConnectedAt = useLastConnectedAt(hostId)
+ const forceReconnectHost = useForceReconnect()
const initialCreateWarning = typeof createdWarning === 'string' ? createdWarning.trim() : ''
const [terminals, setTerminals] = useState([])
const terminalsRef = useRef([])
@@ -3640,6 +3649,17 @@ export default function SessionScreen() {
void handleCreateTerminal()
}, [client, creating, creatingBrowser, creatingMarkdown, showEmptyState, worktreeId])
+ // Why: the reconnect loop parks at its give-up cap; without an in-session
+ // affordance the only recovery is leaving the screen or restarting the
+ // app (issue #5049). Surface tap-to-retry once the verdict escalates.
+ const connectionVerdict = classifyConnection({
+ state: connState,
+ reconnectAttempts,
+ lastConnectedAt
+ })
+ const showConnectionRetry =
+ connectionVerdict.kind === 'warning' || connectionVerdict.kind === 'unreachable'
+
const terminalSummary =
connState === 'connected'
? showLoadingState
@@ -3647,7 +3667,9 @@ export default function SessionScreen() {
: visibleTabs.length === 1
? '1 tab'
: `${visibleTabs.length} tabs`
- : STATUS_LABELS[connState]
+ : showConnectionRetry
+ ? `${connectionVerdict.label} — tap to retry`
+ : STATUS_LABELS[connState]
// Why: keep safe-area padding in layout at all times, then visually translate
// the controls over the terminal when the keyboard appears. iOS keyboard
@@ -3790,12 +3812,22 @@ export default function SessionScreen() {
{worktreeName || 'Terminal'}
-
+ {
+ if (hostId) {
+ void forceReconnectHost(hostId)
+ }
+ }}
+ accessibilityRole={showConnectionRetry ? 'button' : undefined}
+ accessibilityLabel={showConnectionRetry ? 'Reconnect to desktop' : undefined}
+ >
{terminalSummary}
-
+
[styles.filesButton, pressed && styles.filesButtonPressed]}
diff --git a/mobile/app/h/[hostId]/source-control/[worktreeId].tsx b/mobile/app/h/[hostId]/source-control/[worktreeId].tsx
index dad4d4cfe94..59ea98736b3 100644
--- a/mobile/app/h/[hostId]/source-control/[worktreeId].tsx
+++ b/mobile/app/h/[hostId]/source-control/[worktreeId].tsx
@@ -30,7 +30,8 @@ import {
Trash2,
X
} from 'lucide-react-native'
-import { useHostClient } from '../../../../src/transport/client-context'
+import { useHostClient, useForceReconnect } from '../../../../src/transport/client-context'
+import { getWorktreeLabel } from '../../../../src/session/worktree-label'
import type { RpcClient } from '../../../../src/transport/rpc-client'
import type { RpcSuccess } from '../../../../src/transport/types'
import {
@@ -200,17 +201,6 @@ async function resolveMobileBranchCompareBaseRef(
return result.defaultBaseRef?.trim() || null
}
-function getWorktreeLabel(name: string | undefined, worktreeId: string): string {
- if (name?.trim()) {
- return name.trim()
- }
- const pathPart = worktreeId.includes('::')
- ? worktreeId.slice(worktreeId.indexOf('::') + 2)
- : worktreeId
- const normalized = pathPart.replace(/\\/g, '/').replace(/\/+$/, '')
- return normalized.slice(normalized.lastIndexOf('/') + 1) || 'Worktree'
-}
-
function formatBranchLabel(branch: string | undefined, head: string | undefined): string {
if (branch?.startsWith('refs/heads/')) {
return branch.slice('refs/heads/'.length)
@@ -249,6 +239,7 @@ export default function MobileSourceControlScreen() {
const router = useRouter()
const insets = useSafeAreaInsets()
const { client, state: connState } = useHostClient(hostId)
+ const forceReconnect = useForceReconnect()
const [screenState, setScreenState] = useState({ kind: 'loading' })
const [branchCompareState, setBranchCompareState] = useState({
kind: 'idle'
@@ -1431,7 +1422,20 @@ export default function MobileSourceControlScreen() {
{screenState.message}
{screenState.kind === 'error' ? (
- void loadStatus()}>
+ {
+ // Why: retrying the request is useless while the transport's
+ // reconnect loop is parked at its give-up cap — revive the
+ // connection instead (issue #5049). loadStatus re-runs via
+ // its connState effect once the new client connects.
+ if (connState !== 'connected' && hostId) {
+ void forceReconnect(hostId)
+ return
+ }
+ void loadStatus()
+ }}
+ >
Retry
) : null}
diff --git a/mobile/issue-5049-unresponsive-session-findings.md b/mobile/issue-5049-unresponsive-session-findings.md
new file mode 100644
index 00000000000..6440e1c990c
--- /dev/null
+++ b/mobile/issue-5049-unresponsive-session-findings.md
@@ -0,0 +1,92 @@
+# Issue #5049: Android Remote Session Unresponsiveness — Findings
+
+Date: 2026-06-09
+Issue: https://github.com/stablyai/orca/issues/5049
+
+## Reported symptoms
+
+Android + Tailscale remote session intermittently becomes unresponsive: tab/worktree
+taps do nothing, pasted text doesn't execute, the connection "appears stuck instead
+of clearly disconnected", and closing/reopening the app restores the session.
+
+## Root causes found (mobile-side)
+
+All three independently produce the exact reported symptom — a session that looks
+alive but ignores input, recoverable only by an app restart:
+
+1. **Parked reconnect loop with no recovery path (primary).** `rpc-client.ts`
+ stops retrying permanently after `GIVE_UP_AFTER_ATTEMPTS` (12 attempts ≈ 6.5 min
+ of backoff). Android backgrounding + Doze + a Tailscale tunnel drop routinely
+ burns through all 12 attempts while the user is away. Nothing ever restarted the
+ loop: there was **no AppState listener anywhere in the transport layer**, so
+ returning to the foreground did not nudge the client. The state stays
+ `'reconnecting'` forever ("appears stuck instead of clearly disconnected").
+ Reopening the app creates a fresh client with a fresh attempt budget — which is
+ exactly why "closing and reopening usually restores the session".
+
+2. **Half-open socket detection waits up to ~28s, and never starts earlier on
+ resume.** Android can kill the TCP path while backgrounded without delivering
+ `onclose`; `readyState` still reads OPEN, so every `terminal.send` (e.g. paste)
+ silently blackholes. The activity probe (20s interval + 8s timeout) eventually
+ reaps the link, but the first ~28s after resume look like "pasted text does not
+ run immediately" / "switching is very slow".
+
+3. **Stale client after `forceReconnect` (pre-existing `useHostClient` bug).**
+ `forceReconnect` swaps in a fresh `RpcClient`, but `useHostClient` only re-read
+ the client when its ref was still `null`. Any mounted screen kept driving the
+ old, **closed** client forever: the status header (fed by provider-level state
+ listeners) shows "Connected" while every RPC instantly fails with "Client
+ closed" — a session that looks alive but ignores all input.
+
+ Additionally, the session screen (where users actually live) had no recovery
+ affordance at all: just a status label, while the Retry buttons exist only on
+ the home/host/tasks screens.
+
+## Fixes
+
+- `src/transport/rpc-client.ts` — new `notifyForeground()`:
+ - state `connected` → restart the probe interval and run one probe immediately
+ (half-open link reaped in ≤8s instead of ≤28s);
+ - state `reconnecting` → clear any pending backoff timer, reset the attempt
+ budget, reconnect immediately (un-parks the give-up cap).
+ - (Also extracted the duplicated close/error event serialization into
+ `socket-event-debug.ts` to stay under the file's line cap.)
+- `src/transport/client-context.tsx`:
+ - `RpcClientProvider` now listens to AppState and calls `notifyForeground()` on
+ every live client when the app becomes active.
+ - `useHostClient` re-reads the underlying client on every state change, so
+ screens pick up the fresh client after `forceReconnect` instead of driving a
+ closed one.
+- `app/h/[hostId]/session/[worktreeId].tsx` — the status row in the session header
+ becomes tappable once `classifyConnection` escalates to warning/unreachable,
+ showing " — tap to retry" and invoking `forceReconnect`.
+
+## Repro harnesses
+
+- `src/transport/rpc-client.test.ts` → `foreground recovery` describe block:
+ deterministic fake-timer repro of the parked loop (proves it never self-recovers)
+ plus regression coverage for all `notifyForeground()` paths.
+- `src/transport/rpc-client-live-recovery.test.ts`: opt-in live harness running the
+ REAL rpc-client (real sockets, real tweetnacl E2EE, real timers) against an
+ in-process ws server with a blackhole toggle:
+ - `ORCA_MOBILE_LIVE_REPRO=1 pnpm vitest run src/transport/rpc-client-live-recovery.test.ts`
+ — half-open-link scenario (~15s).
+ - `ORCA_MOBILE_LIVE_REPRO_FULL=1 …` — full parked-loop scenario (~8.5 min): waits
+ out all 12 backoff attempts, proves the loop stays parked even after the server
+ returns, then proves `notifyForeground()` recovers it.
+
+## Not addressed (out of scope, noted for future work)
+
+- The diagnostics in `rpc-client.ts` mention a suspected RN/OkHttp process-state
+ poisoning mode (every open instantly fails with 1006 until force-quit). If that
+ mode is real, a foreground nudge reconnect attempt would also fail; the existing
+ `[net]` logs (wsCount / msSinceLast\*) are designed to confirm or rule it out from
+ device logs.
+
+## Follow-up audit (same PR)
+
+- `connection-revival-triggers.ts` (via `expo-network`) extends the foreground
+ nudge to network restoration and Wi-Fi → cellular handoffs.
+- Files and source-control screens' Retry buttons now revive the transport
+ (`forceReconnect`) when disconnected instead of pointlessly re-sending the
+ request into a parked connection.
diff --git a/mobile/package.json b/mobile/package.json
index 91d0aad7783..7472008bf83 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -27,6 +27,7 @@
"expo-haptics": "^55.0.14",
"expo-linking": "^55.0.15",
"expo-modules-core": "~55.0.25",
+ "expo-network": "~55.0.14",
"expo-notifications": "^55.0.22",
"expo-router": "^55.0.14",
"expo-secure-store": "^55.0.13",
diff --git a/mobile/pnpm-lock.yaml b/mobile/pnpm-lock.yaml
index 6bfe118caa0..b3dd184658c 100644
--- a/mobile/pnpm-lock.yaml
+++ b/mobile/pnpm-lock.yaml
@@ -47,6 +47,9 @@ importers:
expo-modules-core:
specifier: ~55.0.25
version: 55.0.25(react-native-worklets@0.8.3(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6))(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)
+ expo-network:
+ specifier: ~55.0.14
+ version: 55.0.14(expo@55.0.23)(react@19.2.6)
expo-notifications:
specifier: ^55.0.22
version: 55.0.22(expo@55.0.23)(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)(typescript@5.9.3)
@@ -1424,56 +1427,48 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-arm64-musl@0.52.0':
resolution: {integrity: sha512-wZg6bLjDvh2KibyI3QFUYo8GTXneIFsd0JvehtvJiUmQ8WRPERgxd/VM4ctWb86U5FT1FkqgS8/wZKVB+AZScg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@oxfmt/binding-linux-ppc64-gnu@0.52.0':
resolution: {integrity: sha512-IngE8uxhNvxcMrLjZNDo9xNLY7rEK33AKnaMd2B46he1e/mz2CfcW6If/U1wUjdRZddm1QzQaciqZkuMkdh1FA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-riscv64-gnu@0.52.0':
resolution: {integrity: sha512-H3+DdFMv/efN3Efmhsv18jDrpiWWqKG7wsfAlQBqAt6z/E2Bx+TwEj2Nowe51CPOWB8/mFBC2dAMSgVFLvvowA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-riscv64-musl@0.52.0':
resolution: {integrity: sha512-zji+1kb7lJKohSDjzC1IsS+K/cKRs1hdVf0ZH0VbdbiakmtLvN9twBoXo/k8VdjFax7kfo+DyPxS7vv52br1aw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@oxfmt/binding-linux-s390x-gnu@0.52.0':
resolution: {integrity: sha512-hcLBYedpCy7ToUvvBidWk7+11Yhg1oAZ4+6hKPic/mQI6NaqXJSXMps5nFlwUuX2ewhtLZZDPg63TI042qGKBg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-x64-gnu@0.52.0':
resolution: {integrity: sha512-IDO2loXK2OtTOhSPchU9MW25mWL2QCDGdJbjN8MXKZVS80qXe5gMTwQWu/gMJ3juoBHbkuUZNB2N1LHzNT7DoA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@oxfmt/binding-linux-x64-musl@0.52.0':
resolution: {integrity: sha512-mAV2Hjn0SatJ+KoAzKUC3eJhdJ8wv+3m1KyuS0dTsbF0c5weq+QrCt/DRZZM+uj/XiKzCDEUKYsBF30e2qkcyw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [musl]
'@oxfmt/binding-openharmony-arm64@0.52.0':
resolution: {integrity: sha512-vd4npaUIwChxp7XzkqmepBWTT9YMcSe/NBApVGPC30/lLyOVaV3dvma1SKo03t8O73BPRAG7EyJzGlN5cJM5hQ==}
@@ -1546,56 +1541,48 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@oxlint/binding-linux-arm64-musl@1.67.0':
resolution: {integrity: sha512-zB/Tf6sUjmmvvbva9Gj3JTJ8rJ9t4I8/U0o6vSRtd0DRIsIuyegBwJAzhSUFQHdMijIRJkW0exs/yBhpw2S20w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@oxlint/binding-linux-ppc64-gnu@1.67.0':
resolution: {integrity: sha512-kgU40Gt74CK0TCsF51KZymkIwN9U0BajKsMijB52zPqOeZU9NAHkA/NSQkZDHEaCakx42DxhXkODiAqf2b4Gug==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@oxlint/binding-linux-riscv64-gnu@1.67.0':
resolution: {integrity: sha512-tOYhkk/iaG9aD3FvGpBFd1Lrw0x0RaVoJBxjUkfNzS50rC5NS5BteNCwgr8A2zCdADrIIoze6D7u6U5Ic++/iQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@oxlint/binding-linux-riscv64-musl@1.67.0':
resolution: {integrity: sha512-sEtywrPb+0b+tHYl1SDCrw903fiC4eyKoNqzP3v+f2JT3Xcv4NEYG+P8rj+eEnX7IWhqV/xj8/JmcmVj21CXaA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
- libc: [musl]
'@oxlint/binding-linux-s390x-gnu@1.67.0':
resolution: {integrity: sha512-BvR8Moa0zCLxroOx4vZaZN9nUfwAUpSTwjZdxZyKy4bv3PrzrXrxKR/ZQ0L9wNSvlPhnMJeZfa3q5w6ZCTuN6Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@oxlint/binding-linux-x64-gnu@1.67.0':
resolution: {integrity: sha512-mm2cxM6fksOpq6l0uFws8BUGKAR4dNa/cZCn37Npq7PFbhD5HDJqWfnoIvTaeRKMy5XdS2tO0MA0qbHDrnXAAA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@oxlint/binding-linux-x64-musl@1.67.0':
resolution: {integrity: sha512-WmbMuLapKyDlobMkXAaAL0Y+Uczh4LETfIfQsUpbId4Ip8Ai82/jqeYTOoUCkuuhBFapgqP253+d83tLKOksJg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
- libc: [musl]
'@oxlint/binding-openharmony-arm64@1.67.0':
resolution: {integrity: sha512-9g/PqxYJelzzTAOR5Y+RiRqdeydhEuXv2KxNeFcAKQ7UsvnWSY1OP4MsuPMbTO2Pf70tz7mFhl1j13H3fyh+8g==}
@@ -3421,6 +3408,12 @@ packages:
react-native-worklets:
optional: true
+ expo-network@55.0.14:
+ resolution: {integrity: sha512-Sy544zTPjVh+tbOLUOU8fBX87oRSrNQqUZY6TLO0w0WF/QTNb7yxlwRh6v6wfKKRg9xpZypTIIEtdG/s6q8ZQA==}
+ peerDependencies:
+ expo: '*'
+ react: '*'
+
expo-notifications@55.0.22:
resolution: {integrity: sha512-Rwvsp/lAEXfDYBxkQZpaLF9ZB25cJ/yfHhD/ESclbPesN0nbQBZ/5rGb1xS/saANtkStbEGfDlA80uHh2zEpsA==}
peerDependencies:
@@ -10030,6 +10023,11 @@ snapshots:
optionalDependencies:
react-native-worklets: 0.8.3(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)
+ expo-network@55.0.14(expo@55.0.23)(react@19.2.6):
+ dependencies:
+ expo: 55.0.23(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.10)(expo-router@55.0.14)(react-dom@19.2.5(react@19.2.6))(react-native-webview@13.16.1(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6))(react-native-worklets@0.8.3(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6))(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)(typescript@5.9.3)
+ react: 19.2.6
+
expo-notifications@55.0.22(expo@55.0.23)(react-native@0.83.9(@babel/core@7.29.0)(@react-native/metro-config@0.85.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.6))(react@19.2.6)(typescript@5.9.3):
dependencies:
'@expo/image-utils': 0.8.14(typescript@5.9.3)
diff --git a/mobile/src/session/worktree-label.ts b/mobile/src/session/worktree-label.ts
new file mode 100644
index 00000000000..c5e67ac5aab
--- /dev/null
+++ b/mobile/src/session/worktree-label.ts
@@ -0,0 +1,12 @@
+// Why: worktree ids encode `repo::path`; screens that only receive the id
+// (deep links, route params without a name) still need a human label.
+export function getWorktreeLabel(name: string | undefined, worktreeId: string): string {
+ if (name?.trim()) {
+ return name.trim()
+ }
+ const pathPart = worktreeId.includes('::')
+ ? worktreeId.slice(worktreeId.indexOf('::') + 2)
+ : worktreeId
+ const normalized = pathPart.replace(/\\/g, '/').replace(/\/+$/, '')
+ return normalized.slice(normalized.lastIndexOf('/') + 1) || 'Worktree'
+}
diff --git a/mobile/src/transport/client-context.tsx b/mobile/src/transport/client-context.tsx
index c6ebbcc5332..f889cba51ff 100644
--- a/mobile/src/transport/client-context.tsx
+++ b/mobile/src/transport/client-context.tsx
@@ -20,6 +20,7 @@ import {
type ReactNode
} from 'react'
import { connect, type RpcClient } from './rpc-client'
+import { subscribeConnectionRevivalTriggers } from './connection-revival-triggers'
import { loadHosts } from './host-store'
import type { ConnectionState, HostProfile } from './types'
@@ -320,6 +321,17 @@ export function RpcClientProvider({ children }: { children: ReactNode }) {
}
}, [])
+ // Why: nudge every live client when the OS signals the link may be back
+ // (foreground, network restored/switched) so sessions recover without an
+ // app restart (issue #5049).
+ useEffect(() => {
+ return subscribeConnectionRevivalTriggers(() => {
+ for (const entry of storeRef.current.values()) {
+ entry.client.notifyForeground()
+ }
+ })
+ }, [])
+
const value = useMemo(
() => ({
acquire,
@@ -387,16 +399,13 @@ export function useHostClient(hostId: string | undefined): {
return
}
setState(next)
- // Why: if the client was null at first acquire (async open), the
- // first state change ('connecting'/'handshaking'/'connected') is our
- // signal to re-read.
- if (clientRef.current == null) {
- const all = ctx.getAllClients()
- const found = all.find((entry) => entry.hostId === hostId)
- if (found) {
- clientRef.current = found.client
- force((n) => n + 1)
- }
+ // Why: the client materialises after an async open, and forceReconnect
+ // swaps in a fresh client object. Re-read on every state change so a
+ // mounted screen never keeps driving a stale (closed) client.
+ const found = ctx.getAllClients().find((entry) => entry.hostId === hostId)
+ if (found && found.client !== clientRef.current) {
+ clientRef.current = found.client
+ force((n) => n + 1)
}
})
const initial = ctx.acquire(hostId)
diff --git a/mobile/src/transport/connection-revival-triggers.test.ts b/mobile/src/transport/connection-revival-triggers.test.ts
new file mode 100644
index 00000000000..30efcd4f9bd
--- /dev/null
+++ b/mobile/src/transport/connection-revival-triggers.test.ts
@@ -0,0 +1,94 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { subscribeConnectionRevivalTriggers } from './connection-revival-triggers'
+
+type AppStateListener = (next: string) => void
+type NetworkSnapshot = { isConnected?: boolean; type?: string }
+type NetworkListener = (state: NetworkSnapshot) => void
+
+let appStateListener: AppStateListener | null = null
+let networkListener: NetworkListener | null = null
+let seededNetworkState: NetworkSnapshot = { isConnected: true, type: 'WIFI' }
+const appStateRemove = vi.fn()
+const networkRemove = vi.fn()
+
+vi.mock('react-native', () => ({
+ AppState: {
+ addEventListener: (_event: string, listener: AppStateListener) => {
+ appStateListener = listener
+ return { remove: appStateRemove }
+ }
+ }
+}))
+
+vi.mock('expo-network', () => ({
+ getNetworkStateAsync: () => Promise.resolve(seededNetworkState),
+ addNetworkStateListener: (listener: NetworkListener) => {
+ networkListener = listener
+ return { remove: networkRemove }
+ }
+}))
+
+// Why: the baseline seed resolves on a microtask; flush it so listener
+// events in the test observe the same ordering as a real subscription.
+async function subscribeAndSeed(nudge: () => void): Promise<() => void> {
+ const unsubscribe = subscribeConnectionRevivalTriggers(nudge)
+ await Promise.resolve()
+ return unsubscribe
+}
+
+describe('subscribeConnectionRevivalTriggers', () => {
+ let nudge: ReturnType
+
+ beforeEach(() => {
+ vi.clearAllMocks()
+ appStateListener = null
+ networkListener = null
+ seededNetworkState = { isConnected: true, type: 'WIFI' }
+ nudge = vi.fn()
+ })
+
+ it('nudges when the app returns to the foreground, not on background', async () => {
+ await subscribeAndSeed(nudge)
+ appStateListener?.('background')
+ expect(nudge).not.toHaveBeenCalled()
+ appStateListener?.('active')
+ expect(nudge).toHaveBeenCalledTimes(1)
+ })
+
+ it('nudges when the network comes back online', async () => {
+ await subscribeAndSeed(nudge)
+ networkListener?.({ isConnected: false, type: 'NONE' })
+ expect(nudge).not.toHaveBeenCalled()
+ networkListener?.({ isConnected: true, type: 'WIFI' })
+ expect(nudge).toHaveBeenCalledTimes(1)
+ })
+
+ it('nudges when the app started offline and the first event is the recovery', async () => {
+ seededNetworkState = { isConnected: false, type: 'NONE' }
+ await subscribeAndSeed(nudge)
+ networkListener?.({ isConnected: true, type: 'WIFI' })
+ expect(nudge).toHaveBeenCalledTimes(1)
+ })
+
+ it('nudges on a Wi-Fi to cellular handoff that never reports offline', async () => {
+ await subscribeAndSeed(nudge)
+ networkListener?.({ isConnected: true, type: 'CELLULAR' })
+ expect(nudge).toHaveBeenCalledTimes(1)
+ })
+
+ it('stays quiet when the network state matches the seeded baseline', async () => {
+ await subscribeAndSeed(nudge)
+ networkListener?.({ isConnected: true, type: 'WIFI' })
+ networkListener?.({ isConnected: true, type: 'WIFI' })
+ expect(nudge).not.toHaveBeenCalled()
+ })
+
+ it('ignores a stale seed that resolves after unsubscribe', async () => {
+ seededNetworkState = { isConnected: false, type: 'NONE' }
+ const unsubscribe = subscribeConnectionRevivalTriggers(nudge)
+ unsubscribe()
+ await Promise.resolve()
+ expect(appStateRemove).toHaveBeenCalledTimes(1)
+ expect(networkRemove).toHaveBeenCalledTimes(1)
+ })
+})
diff --git a/mobile/src/transport/connection-revival-triggers.ts b/mobile/src/transport/connection-revival-triggers.ts
new file mode 100644
index 00000000000..1391607d4bf
--- /dev/null
+++ b/mobile/src/transport/connection-revival-triggers.ts
@@ -0,0 +1,50 @@
+import { AppState } from 'react-native'
+import { addNetworkStateListener, getNetworkStateAsync, type NetworkState } from 'expo-network'
+
+// Why: Android/iOS suspend JS timers and silently kill sockets while the app
+// is backgrounded, and network handoffs (Wi-Fi → cellular) kill the TCP path
+// without an onclose. Both leave clients waiting out long backoff timers or
+// parked at the reconnect give-up cap (issue #5049). Surface every "the link
+// probably just came back" OS signal as a single nudge callback.
+export function subscribeConnectionRevivalTriggers(nudge: () => void): () => void {
+ const appStateSub = AppState.addEventListener('change', (next) => {
+ if (next === 'active') {
+ nudge()
+ }
+ })
+ let lastNetwork: Pick | null = null
+ let disposed = false
+ // Why: the listener only fires on *changes*; without a seeded baseline the
+ // first change after subscribing (app launched offline, network returns)
+ // would be swallowed by the previous == null guard below.
+ void getNetworkStateAsync()
+ .then((state) => {
+ if (!disposed && lastNetwork == null) {
+ lastNetwork = { isConnected: state.isConnected, type: state.type }
+ }
+ })
+ .catch(() => {})
+ const networkSub = addNetworkStateListener((state) => {
+ const previous = lastNetwork
+ lastNetwork = { isConnected: state.isConnected, type: state.type }
+ if (state.isConnected !== true) {
+ return
+ }
+ const cameOnline = previous != null && previous.isConnected !== true
+ // Why: a type change while staying "connected" is the Wi-Fi → cellular
+ // handoff case — the old socket is dead even though we never went offline.
+ const switchedNetworks = previous?.type != null && state.type !== previous.type
+ if (cameOnline || switchedNetworks) {
+ console.log('[net] network changed — nudging clients', {
+ type: state.type,
+ cameOnline
+ })
+ nudge()
+ }
+ })
+ return () => {
+ disposed = true
+ appStateSub.remove()
+ networkSub.remove()
+ }
+}
diff --git a/mobile/src/transport/rpc-client-live-recovery.test.ts b/mobile/src/transport/rpc-client-live-recovery.test.ts
new file mode 100644
index 00000000000..da73fc0b5fd
--- /dev/null
+++ b/mobile/src/transport/rpc-client-live-recovery.test.ts
@@ -0,0 +1,208 @@
+// Live (real-socket, real-timer) repro harness for issue #5049: Android
+// remote sessions that appear connected but stop responding until the app
+// is reopened. Unlike rpc-client.test.ts (fake timers, mocked e2ee), this
+// runs the REAL rpc-client with real tweetnacl E2EE against an in-process
+// ws server, simulating the Tailscale failure modes behind the report.
+//
+// Opt-in because the quick scenario takes ~15s wall-clock and the full
+// parked-loop scenario ~8 minutes:
+// ORCA_MOBILE_LIVE_REPRO=1 pnpm vitest run src/transport/rpc-client-live-recovery.test.ts
+// ORCA_MOBILE_LIVE_REPRO_FULL=1 ... (adds the 8-minute parked-loop case)
+import { afterEach, describe, expect, it, vi } from 'vitest'
+import { randomBytes } from 'node:crypto'
+import type { AddressInfo } from 'node:net'
+import nacl from 'tweetnacl'
+import { WebSocketServer, type WebSocket as ServerSocket } from 'ws'
+import { connect, type RpcClient } from './rpc-client'
+
+// Why: expo-crypto only exists inside a React Native runtime; Node's CSPRNG
+// is equivalent for the harness. Everything else (tweetnacl, the wire
+// protocol) is the real production path.
+vi.mock('expo-crypto', () => ({
+ getRandomBytes: (n: number) => new Uint8Array(randomBytes(n))
+}))
+
+const RUN_LIVE =
+ process.env.ORCA_MOBILE_LIVE_REPRO === '1' || !!process.env.ORCA_MOBILE_LIVE_REPRO_FULL
+const RUN_FULL = process.env.ORCA_MOBILE_LIVE_REPRO_FULL === '1'
+
+const AUTH_TOKEN = 'repro-device-token'
+
+const serverKeyPair = nacl.box.keyPair()
+const serverPublicKeyB64 = Buffer.from(serverKeyPair.publicKey).toString('base64')
+
+// When true the server accepts traffic but never replies — simulates a
+// half-open link where TCP looks alive but the path is dead.
+let blackhole = false
+
+function e2eeEncrypt(plaintext: string, sharedKey: Uint8Array): string {
+ const nonce = nacl.randomBytes(nacl.box.nonceLength)
+ const msg = new TextEncoder().encode(plaintext)
+ const ciphertext = nacl.box.after(msg, nonce, sharedKey)
+ const bundle = new Uint8Array(nonce.length + ciphertext.length)
+ bundle.set(nonce)
+ bundle.set(ciphertext, nonce.length)
+ return Buffer.from(bundle).toString('base64')
+}
+
+function e2eeDecrypt(encrypted: string, sharedKey: Uint8Array): string | null {
+ const bundle = Uint8Array.from(Buffer.from(encrypted, 'base64'))
+ if (bundle.length < nacl.box.nonceLength + nacl.box.overheadLength) {
+ return null
+ }
+ const nonce = bundle.slice(0, nacl.box.nonceLength)
+ const plaintext = nacl.box.open.after(bundle.slice(nacl.box.nonceLength), nonce, sharedKey)
+ return plaintext ? new TextDecoder().decode(plaintext) : null
+}
+
+// Why: port 0 lets the OS assign a free port so the opt-in harness can't
+// fail with EADDRINUSE; the full scenario restarts on the captured port
+// because the client keeps reconnecting to its original URL.
+function startServer(port = 0): Promise {
+ const wss = new WebSocketServer({ port })
+ wss.on('connection', (ws: ServerSocket) => {
+ let sharedKey: Uint8Array | null = null
+ let authenticated = false
+ ws.on('message', (data) => {
+ if (blackhole) {
+ return
+ }
+ const msg = typeof data === 'string' ? data : data.toString('utf-8')
+ if (!sharedKey) {
+ const hello = JSON.parse(msg) as { publicKeyB64: string }
+ const clientKey = Uint8Array.from(Buffer.from(hello.publicKeyB64, 'base64'))
+ sharedKey = nacl.box.before(clientKey, serverKeyPair.secretKey)
+ ws.send(JSON.stringify({ type: 'e2ee_ready' }))
+ return
+ }
+ const plaintext = e2eeDecrypt(msg, sharedKey)
+ if (!plaintext) {
+ return
+ }
+ const request = JSON.parse(plaintext) as { id?: string; type?: string; deviceToken?: string }
+ if (!authenticated) {
+ if (request.type === 'e2ee_auth' && request.deviceToken === AUTH_TOKEN) {
+ authenticated = true
+ ws.send(e2eeEncrypt(JSON.stringify({ type: 'e2ee_authenticated' }), sharedKey))
+ }
+ return
+ }
+ ws.send(
+ e2eeEncrypt(JSON.stringify({ id: request.id, ok: true, result: { up: true } }), sharedKey)
+ )
+ })
+ })
+ return new Promise((resolve) => wss.once('listening', () => resolve(wss)))
+}
+
+function serverPort(wss: WebSocketServer): number {
+ return (wss.address() as AddressInfo).port
+}
+
+function stopServer(wss: WebSocketServer): Promise {
+ return new Promise((resolve) => {
+ for (const ws of wss.clients) {
+ ws.terminate()
+ }
+ wss.close(() => resolve())
+ })
+}
+
+function sleep(ms: number): Promise {
+ return new Promise((resolve) => setTimeout(resolve, ms))
+}
+
+async function waitFor(label: string, timeoutMs: number, check: () => boolean): Promise {
+ const start = Date.now()
+ while (Date.now() - start < timeoutMs) {
+ if (check()) {
+ return Date.now() - start
+ }
+ await sleep(200)
+ }
+ throw new Error(`timed out after ${timeoutMs / 1000}s waiting for: ${label}`)
+}
+
+describe.runIf(RUN_LIVE)('live foreground recovery (issue #5049)', () => {
+ let client: RpcClient | null = null
+ let wss: WebSocketServer | null = null
+
+ afterEach(async () => {
+ blackhole = false
+ client?.close()
+ client = null
+ if (wss) {
+ await stopServer(wss)
+ wss = null
+ }
+ })
+
+ it(
+ 'reaps a half-open link via the foreground probe and recovers',
+ { timeout: 60_000 },
+ async () => {
+ wss = await startServer()
+ client = connect(`ws://127.0.0.1:${serverPort(wss)}`, AUTH_TOKEN, serverPublicKeyB64)
+ const c = client
+ await waitFor('initial connect', 10_000, () => c.getState() === 'connected')
+ expect((await c.sendRequest('status.get')).ok).toBe(true)
+
+ // Half-open: server keeps TCP up but stops answering, then the app
+ // comes back to the foreground.
+ blackhole = true
+ c.notifyForeground()
+ // Foreground probe budget is 8s; the interval probe alone would take
+ // up to 28s. Allow scheduling slack but stay well under 28s.
+ const detectMs = await waitFor(
+ 'half-open detected',
+ 15_000,
+ () => c.getState() !== 'connected'
+ )
+ expect(detectMs).toBeLessThan(12_000)
+
+ blackhole = false
+ await waitFor('recovered after link healed', 15_000, () => c.getState() === 'connected')
+ expect((await c.sendRequest('status.get')).ok).toBe(true)
+ }
+ )
+
+ it.runIf(RUN_FULL)(
+ 'repro: parked retry loop stays stuck until the foreground nudge',
+ { timeout: 600_000 },
+ async () => {
+ wss = await startServer()
+ const port = serverPort(wss)
+ client = connect(`ws://127.0.0.1:${port}`, AUTH_TOKEN, serverPublicKeyB64)
+ const c = client
+ await waitFor('initial connect', 10_000, () => c.getState() === 'connected')
+
+ await stopServer(wss)
+ wss = null
+ await waitFor('retry cap scheduled (~5 min)', 480_000, () => c.getReconnectAttempt() >= 12)
+ // The attempt counter hits 12 when the final attempt is *scheduled*;
+ // its 60s backoff timer is still pending. Let it fire and fail while
+ // the server is still down so the loop truly parks.
+ await sleep(65_000)
+ expect(c.getState()).toBe('reconnecting')
+
+ wss = await startServer(port)
+ // Pre-fix behavior: even with the server back, a parked loop never
+ // recovers — the user had to restart the app.
+ await sleep(70_000)
+ expect(c.getState()).not.toBe('connected')
+
+ c.notifyForeground()
+ await waitFor('foreground nudge recovered the session', 15_000, () => {
+ return c.getState() === 'connected'
+ })
+ expect((await c.sendRequest('status.get')).ok).toBe(true)
+ }
+ )
+})
+
+// Why: vitest fails a file with zero tests; keep a sentinel for default runs.
+describe.runIf(!RUN_LIVE)('live foreground recovery (skipped)', () => {
+ it('is opt-in via ORCA_MOBILE_LIVE_REPRO=1', () => {
+ expect(true).toBe(true)
+ })
+})
diff --git a/mobile/src/transport/rpc-client.test.ts b/mobile/src/transport/rpc-client.test.ts
index 3e01e7e39e9..5c624dff3ba 100644
--- a/mobile/src/transport/rpc-client.test.ts
+++ b/mobile/src/transport/rpc-client.test.ts
@@ -581,6 +581,120 @@ describe('mobile rpc-client connection timeout', () => {
}
})
+ // Repro for issue #5049: Android sessions that appear connected (or stuck
+ // "Reconnecting…") after the app returns to the foreground, recoverable
+ // only by restarting the app. notifyForeground is the recovery hook the
+ // provider invokes on AppState 'active'.
+ describe('foreground recovery', () => {
+ function openAndAuthenticate(socket: MockWebSocket) {
+ socket.open()
+ socket.receive(JSON.stringify({ type: 'e2ee_ready' }))
+ socket.receive('encrypted:{"type":"e2ee_authenticated"}')
+ }
+
+ it('repro: a parked reconnect loop never retries on its own', async () => {
+ const client = connect('ws://desktop.invalid', 'token', 'server-key')
+ openAndAuthenticate(mockSockets[0]!)
+ mockSockets[0]!.close()
+
+ await vi.runAllTimersAsync()
+ expect(client.getState()).toBe('reconnecting')
+ expect(client.getReconnectAttempt()).toBe(12)
+
+ // Stuck: arbitrary additional time produces no further attempts.
+ const socketsBefore = mockSockets.length
+ await vi.advanceTimersByTimeAsync(600_000)
+ expect(mockSockets.length).toBe(socketsBefore)
+
+ client.close()
+ })
+
+ it('restarts a parked reconnect loop on foreground', async () => {
+ const client = connect('ws://desktop.invalid', 'token', 'server-key')
+ openAndAuthenticate(mockSockets[0]!)
+ mockSockets[0]!.close()
+ await vi.runAllTimersAsync()
+ expect(client.getReconnectAttempt()).toBe(12)
+
+ const socketsBefore = mockSockets.length
+ client.notifyForeground()
+
+ expect(mockSockets.length).toBe(socketsBefore + 1)
+ expect(client.getReconnectAttempt()).toBe(0)
+ openAndAuthenticate(mockSockets[mockSockets.length - 1]!)
+ expect(client.getState()).toBe('connected')
+
+ client.close()
+ })
+
+ it('fast-forwards a pending backoff timer on foreground', async () => {
+ const client = connect('ws://desktop.invalid', 'token', 'server-key')
+ openAndAuthenticate(mockSockets[0]!)
+ mockSockets[0]!.close()
+ expect(client.getState()).toBe('reconnecting')
+
+ const socketsBefore = mockSockets.length
+ client.notifyForeground()
+
+ expect(mockSockets.length).toBe(socketsBefore + 1)
+ openAndAuthenticate(mockSockets[mockSockets.length - 1]!)
+ expect(client.getState()).toBe('connected')
+
+ // The cleared backoff timer must not fire a duplicate attempt.
+ await vi.advanceTimersByTimeAsync(1_000)
+ expect(mockSockets.length).toBe(socketsBefore + 1)
+
+ client.close()
+ })
+
+ it('reaps a half-open socket within 8s of foreground', async () => {
+ const client = connect('ws://desktop.invalid', 'token', 'server-key')
+ const socket = mockSockets[0]!
+ openAndAuthenticate(socket)
+
+ // Half-open: readyState stays OPEN but the server never answers.
+ client.notifyForeground()
+ expect(sentRequests(socket, 'status.get')).toHaveLength(1)
+
+ await vi.advanceTimersByTimeAsync(8_000)
+ expect(socket.close).toHaveBeenCalled()
+ expect(client.getState()).toBe('reconnecting')
+
+ await vi.advanceTimersByTimeAsync(500)
+ openAndAuthenticate(mockSockets[mockSockets.length - 1]!)
+ expect(client.getState()).toBe('connected')
+
+ client.close()
+ })
+
+ it('keeps a healthy connection when the foreground probe is answered', async () => {
+ const client = connect('ws://desktop.invalid', 'token', 'server-key')
+ const socket = mockSockets[0]!
+ openAndAuthenticate(socket)
+
+ client.notifyForeground()
+ const probe = sentRequest(socket, 'status.get')
+ socket.receive(`encrypted:${JSON.stringify({ id: probe.id, ok: true, result: {} })}`)
+
+ await vi.advanceTimersByTimeAsync(10_000)
+ expect(socket.close).not.toHaveBeenCalled()
+ expect(client.getState()).toBe('connected')
+
+ client.close()
+ })
+
+ it('is a no-op after the client is closed', () => {
+ const client = connect('ws://desktop.invalid', 'token', 'server-key')
+ openAndAuthenticate(mockSockets[0]!)
+ client.close()
+
+ const socketsBefore = mockSockets.length
+ client.notifyForeground()
+ expect(mockSockets.length).toBe(socketsBefore)
+ expect(client.getState()).toBe('disconnected')
+ })
+ })
+
it('rejects requests waiting for reconnect after the retry cap', async () => {
const client = connect('ws://desktop.invalid', 'token', 'server-key')
const socket = mockSockets[0]!
diff --git a/mobile/src/transport/rpc-client.ts b/mobile/src/transport/rpc-client.ts
index 68c80c2284d..625a39c6f56 100644
--- a/mobile/src/transport/rpc-client.ts
+++ b/mobile/src/transport/rpc-client.ts
@@ -28,6 +28,7 @@ import {
buildTerminalUnsubscribeParams,
updateTerminalSubscriptionViewport as updateCachedTerminalSubscriptionViewport
} from './rpc-client-terminal-subscription'
+import { describeSocketEvent } from './socket-event-debug'
type PendingRequest = {
resolve: (response: RpcResponse) => void
@@ -91,6 +92,10 @@ export type RpcClient = {
// to distinguish "host moved/never reachable" from "transient blip".
getLastConnectedAt: () => number | null
onStateChange: (listener: (state: ConnectionState) => void) => () => void
+ // Why: app-resume hook. Android/iOS can kill the TCP path or park the
+ // reconnect loop while the app is backgrounded; callers invoke this on
+ // AppState 'active' so the session recovers without an app restart.
+ notifyForeground: () => void
close: () => void
}
@@ -645,38 +650,9 @@ export function connect(
const aliveMs =
currentWsOpenedAt != null && state === 'connected' ? closeAt - currentWsOpenedAt : null
const inboundIdleMs = lastInboundAt != null ? closeAt - lastInboundAt : null
- // Why: inline the diagnostic dump. Earlier hot-reload tripped
- // `Property 'enumKeys' doesn't exist` because a stale closure
- // captured a half-loaded module. Inlining keeps the handler's
- // behavior fully decided at construction time.
- let closeEventKeys: string[] = []
- let closeEventStr = ''
- try {
- closeEventKeys = event && typeof event === 'object' ? Object.keys(event as object) : []
- } catch {
- closeEventKeys = []
- }
- try {
- const seen = new WeakSet()
- closeEventStr = JSON.stringify(
- event,
- (_k, v) => {
- if (typeof v === 'object' && v !== null) {
- if (seen.has(v as object)) {
- return '[circular]'
- }
- seen.add(v as object)
- }
- if (typeof v === 'function') {
- return '[fn]'
- }
- return v
- },
- 0
- ).slice(0, 500)
- } catch {
- closeEventStr = '[unstringifiable]'
- }
+ // Why: statically imported (not closure-built) — an earlier hot-reload
+ // bug came from a stale closure capturing a half-loaded module.
+ const closeEvent = describeSocketEvent(event)
console.log('[net] ws.onclose', {
code: e?.code,
reason: e?.reason,
@@ -688,8 +664,8 @@ export function connect(
constructToCloseMs,
aliveMs,
inboundIdleMs,
- eventKeys: closeEventKeys,
- eventStr: closeEventStr
+ eventKeys: closeEvent.keys,
+ eventStr: closeEvent.json
})
lastWsClosedAt = closeAt
currentWsOpenedAt = null
@@ -704,41 +680,13 @@ export function connect(
// onclose fires right after, but logging the error message gives us
// the original cause that the close code alone can hide.
const e = event as { message?: string } | undefined
- // Why: inlined defensively — see ws.onclose comment.
- let errEventKeys: string[] = []
- let errEventStr = ''
- try {
- errEventKeys = event && typeof event === 'object' ? Object.keys(event as object) : []
- } catch {
- errEventKeys = []
- }
- try {
- const seen = new WeakSet()
- errEventStr = JSON.stringify(
- event,
- (_k, v) => {
- if (typeof v === 'object' && v !== null) {
- if (seen.has(v as object)) {
- return '[circular]'
- }
- seen.add(v as object)
- }
- if (typeof v === 'function') {
- return '[fn]'
- }
- return v
- },
- 0
- ).slice(0, 500)
- } catch {
- errEventStr = '[unstringifiable]'
- }
+ const errEvent = describeSocketEvent(event)
console.log('[net] ws.onerror', {
message: e?.message,
state,
attempt: reconnectAttempt,
- eventKeys: errEventKeys,
- eventStr: errEventStr
+ eventKeys: errEvent.keys,
+ eventStr: errEvent.json
})
}
}
@@ -818,56 +766,58 @@ export function connect(
// at the top of the file. Fires while the channel is in 'connected'
// state, sends a tiny status.get, and force-closes the WS if the probe
// fails (which the existing onclose path then turns into a reconnect).
+ function runActivityProbe() {
+ // Why: only probe while the channel is actually in 'connected'. The
+ // sendRequest path itself waits for connected, but a probe scheduled
+ // during a reconnect would just stack up timeouts and confuse logs.
+ if (state !== 'connected' || !ws) {
+ return
+ }
+ const probeWs = ws
+ // Why: short timeout (8s) — server's heartbeat is 15s, so if we
+ // don't see *anything* back within 8s the link is almost certainly
+ // half-open. Using REQUEST_TIMEOUT_MS (30s) here would make the
+ // user wait nearly a minute before reconnect kicks in.
+ const id = nextId()
+ const probeStart = Date.now()
+ let timedOut = false
+ const timeout = setTimeout(() => {
+ timedOut = true
+ pending.delete(id)
+ console.log('[net] activity-probe TIMEOUT — forcing reconnect', {
+ waitedMs: Date.now() - probeStart,
+ state
+ })
+ // Why: only force-close if this is still the same socket the
+ // probe was sent on; a normal close that already swapped `ws`
+ // shouldn't trigger a redundant terminate.
+ if (probeWs === ws && probeWs.readyState === WebSocket.OPEN) {
+ probeWs.close()
+ }
+ }, 8_000)
+ pending.set(id, {
+ resolve: () => {
+ if (timedOut) {
+ return
+ }
+ clearTimeout(timeout)
+ },
+ reject: () => {
+ if (timedOut) {
+ return
+ }
+ clearTimeout(timeout)
+ }
+ })
+ if (!sendEncrypted({ id, deviceToken, method: 'status.get' })) {
+ clearTimeout(timeout)
+ pending.delete(id)
+ }
+ }
+
function startActivityProbe() {
stopActivityProbe()
- activityProbeTimer = setInterval(() => {
- // Why: only probe while the channel is actually in 'connected'. The
- // sendRequest path itself waits for connected, but a probe scheduled
- // during a reconnect would just stack up timeouts and confuse logs.
- if (state !== 'connected' || !ws) {
- return
- }
- const probeWs = ws
- // Why: short timeout (8s) — server's heartbeat is 15s, so if we
- // don't see *anything* back within 8s the link is almost certainly
- // half-open. Using REQUEST_TIMEOUT_MS (30s) here would make the
- // user wait nearly a minute before reconnect kicks in.
- const id = nextId()
- const probeStart = Date.now()
- let timedOut = false
- const timeout = setTimeout(() => {
- timedOut = true
- pending.delete(id)
- console.log('[net] activity-probe TIMEOUT — forcing reconnect', {
- waitedMs: Date.now() - probeStart,
- state
- })
- // Why: only force-close if this is still the same socket the
- // probe was sent on; a normal close that already swapped `ws`
- // shouldn't trigger a redundant terminate.
- if (probeWs === ws && probeWs.readyState === WebSocket.OPEN) {
- probeWs.close()
- }
- }, 8_000)
- pending.set(id, {
- resolve: () => {
- if (timedOut) {
- return
- }
- clearTimeout(timeout)
- },
- reject: () => {
- if (timedOut) {
- return
- }
- clearTimeout(timeout)
- }
- })
- if (!sendEncrypted({ id, deviceToken, method: 'status.get' })) {
- clearTimeout(timeout)
- pending.delete(id)
- }
- }, ACTIVITY_PROBE_INTERVAL_MS)
+ activityProbeTimer = setInterval(runActivityProbe, ACTIVITY_PROBE_INTERVAL_MS)
}
function stopActivityProbe() {
@@ -1216,6 +1166,38 @@ export function connect(
return () => stateListeners.delete(listener)
},
+ notifyForeground(): void {
+ if (intentionallyClosed) {
+ return
+ }
+ if (state === 'connected') {
+ // Why: the OS can kill the TCP path while the app is backgrounded
+ // without delivering onclose, leaving a half-open socket that
+ // blackholes input. Probe now so death is detected in ≤8s instead
+ // of waiting out the 20s interval (issue #5049).
+ console.log('[net] foreground — probing live connection')
+ startActivityProbe()
+ runActivityProbe()
+ return
+ }
+ if (state === 'reconnecting') {
+ // Why: while backgrounded the retry loop may have parked at the
+ // give-up cap or be sitting on a 60s backoff timer. Returning to
+ // the foreground is a strong user signal — restart with a fresh
+ // attempt budget immediately instead of requiring an app restart.
+ console.log('[net] foreground — restarting reconnect loop', {
+ attempt: reconnectAttempt,
+ hadTimer: !!reconnectTimer
+ })
+ if (reconnectTimer) {
+ clearTimeout(reconnectTimer)
+ reconnectTimer = null
+ }
+ reconnectAttempt = 0
+ openConnection()
+ }
+ },
+
close() {
intentionallyClosed = true
if (reconnectTimer) {
diff --git a/mobile/src/transport/socket-event-debug.ts b/mobile/src/transport/socket-event-debug.ts
new file mode 100644
index 00000000000..89b2167c79f
--- /dev/null
+++ b/mobile/src/transport/socket-event-debug.ts
@@ -0,0 +1,34 @@
+// Why: RN's WebSocket close/error events are loosely typed and vary per
+// platform. Serialize them defensively (circular-safe, function-safe,
+// truncated) so the [net] diagnostics can never crash mid-handler.
+export function describeSocketEvent(event: unknown): { keys: string[]; json: string } {
+ let keys: string[] = []
+ try {
+ keys = event && typeof event === 'object' ? Object.keys(event as object) : []
+ } catch {
+ keys = []
+ }
+ let json = ''
+ try {
+ const seen = new WeakSet()
+ json = JSON.stringify(
+ event,
+ (_k, v) => {
+ if (typeof v === 'object' && v !== null) {
+ if (seen.has(v as object)) {
+ return '[circular]'
+ }
+ seen.add(v as object)
+ }
+ if (typeof v === 'function') {
+ return '[fn]'
+ }
+ return v
+ },
+ 0
+ ).slice(0, 500)
+ } catch {
+ json = '[unstringifiable]'
+ }
+ return { keys, json }
+}
From ad66692e7c65b23461578b10f56d6ec5c08e410e Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 21:13:45 -0400
Subject: [PATCH 017/165] fix(i18n): stop visible placeholders in Create PR and
related UI (#5063)
---
.../scripts/verify-localization-catalog.mjs | 71 +-
.../src/components/GitHubItemDialog.tsx | 2 +-
.../src/components/PullRequestPage.tsx | 2 +-
src/renderer/src/components/TaskPage.tsx | 1689 ++++++++++++-----
src/renderer/src/components/UpdateCard.tsx | 12 +-
.../browser-pane/BrowserImportHintButton.tsx | 77 +-
.../components/browser-pane/BrowserPane.tsx | 431 ++++-
.../browser-pane/BrowserToolbarMenu.tsx | 310 +--
.../browser-toolbar-menu-dropdown.tsx | 234 +++
.../browser-toolbar-profile-dialogs.tsx | 126 ++
.../feature-tips/CmdJPaletteTipDialog.tsx | 11 +-
.../feature-wall/FeatureWallBrowserAction.tsx | 72 +-
.../FloatingTerminalWindowControls.tsx | 4 +-
.../right-sidebar/CreatePullRequestDialog.tsx | 210 +-
.../CreatePullRequestDialogForm.tsx | 189 ++
.../CreatePullRequestGenerateButton.tsx | 49 +-
.../components/right-sidebar/PortsPanel.tsx | 338 +++-
.../right-sidebar/SourceControl.tsx | 150 +-
.../create-pull-request-review-copy.ts | 28 +
.../source-control-dropdown-items.ts | 52 +-
...source-control-primary-action-in-flight.ts | 65 +
.../source-control-primary-action-titles.ts | 20 +
.../source-control-primary-action-types.ts | 74 +
.../source-control-primary-action.ts | 326 ++--
.../src/components/settings/AccountsPane.tsx | 7 +-
.../components/settings/BrowserProfileRow.tsx | 66 +-
.../settings/BrowserUseCookieImportStep.tsx | 2 +-
.../settings/RuntimeEnvironmentsPane.tsx | 2 +-
.../settings/SparsePresetSettingsSection.tsx | 262 +--
.../sparse-preset-directory-preview.tsx | 33 +
.../settings/sparse-preset-draft-editor.tsx | 158 ++
.../settings/sparse-preset-settings-row.tsx | 125 ++
.../components/shared/useDaemonActions.tsx | 96 +-
.../src/components/sidebar/WorktreeCard.tsx | 43 +-
.../stats/usage-overview-sections.tsx | 91 +-
.../status-bar/PortsStatusSegment.tsx | 67 +-
.../status-bar/ResourceUsageStatusSegment.tsx | 311 ++-
.../status-bar/UpdateStatusSegment.tsx | 43 +-
.../status-bar/WorkspaceSpaceManagerPanel.tsx | 505 ++++-
.../tab-bar/tab-create-menu-options.ts | 51 +-
.../WorkspaceCleanupDialog.tsx | 381 +++-
.../src/i18n/hosted-review-localized-copy.ts | 36 +
src/renderer/src/i18n/locales/en.json | 223 ++-
src/renderer/src/i18n/locales/ja.json | 273 ++-
src/renderer/src/i18n/locales/ko.json | 273 ++-
src/renderer/src/i18n/locales/zh.json | 273 ++-
src/renderer/src/web/web-preload-api.ts | 2 +-
47 files changed, 5882 insertions(+), 1983 deletions(-)
create mode 100644 src/renderer/src/components/browser-pane/browser-toolbar-menu-dropdown.tsx
create mode 100644 src/renderer/src/components/browser-pane/browser-toolbar-profile-dialogs.tsx
create mode 100644 src/renderer/src/components/right-sidebar/CreatePullRequestDialogForm.tsx
create mode 100644 src/renderer/src/components/right-sidebar/create-pull-request-review-copy.ts
create mode 100644 src/renderer/src/components/right-sidebar/source-control-primary-action-in-flight.ts
create mode 100644 src/renderer/src/components/right-sidebar/source-control-primary-action-titles.ts
create mode 100644 src/renderer/src/components/right-sidebar/source-control-primary-action-types.ts
create mode 100644 src/renderer/src/components/settings/sparse-preset-directory-preview.tsx
create mode 100644 src/renderer/src/components/settings/sparse-preset-draft-editor.tsx
create mode 100644 src/renderer/src/components/settings/sparse-preset-settings-row.tsx
create mode 100644 src/renderer/src/i18n/hosted-review-localized-copy.ts
diff --git a/config/scripts/verify-localization-catalog.mjs b/config/scripts/verify-localization-catalog.mjs
index ed67d13176d..aee2fdea5dd 100644
--- a/config/scripts/verify-localization-catalog.mjs
+++ b/config/scripts/verify-localization-catalog.mjs
@@ -70,13 +70,14 @@ function expressionNameText(node) {
return undefined
}
-function reportAt(root, filePath, sourceFile, node, key) {
+function reportAt(root, filePath, sourceFile, node, key, fallback) {
const position = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))
return {
filePath: normalizePath(root, filePath),
line: position.line + 1,
column: position.character + 1,
- key
+ key,
+ fallback
}
}
@@ -103,7 +104,17 @@ export function collectLocalizationKeyReferences(filePath, sourceText, root = pr
firstArg &&
ts.isStringLiteralLike(firstArg)
) {
- references.push(reportAt(root, filePath, sourceFile, firstArg, firstArg.text))
+ const secondArg = node.arguments[1]
+ references.push(
+ reportAt(
+ root,
+ filePath,
+ sourceFile,
+ firstArg,
+ firstArg.text,
+ secondArg && ts.isStringLiteralLike(secondArg) ? secondArg.text : undefined
+ )
+ )
}
}
@@ -126,6 +137,52 @@ function formatMissingKeys(label, keys) {
return keys.map((key) => `${label}: ${key}`).join('\n')
}
+function normalizeInterpolationVariables(value) {
+ return collectInterpolationVariables(value)
+ .map((variable) => variable.slice(2, -2))
+ .join('|')
+}
+
+function formatInconsistentFallbackVariables(inconsistentFallbackVariables) {
+ return inconsistentFallbackVariables
+ .map(({ key, references }) => {
+ const locations = references
+ .map(
+ (reference) =>
+ ` ${reference.filePath}:${reference.line}:${reference.column} ${JSON.stringify(reference.fallback)}`
+ )
+ .join('\n')
+ return `${key}\n${locations}`
+ })
+ .join('\n\n')
+}
+
+function collectInconsistentFallbackVariables(references) {
+ const byKey = new Map()
+
+ for (const reference of references) {
+ if (typeof reference.fallback !== 'string') {
+ continue
+ }
+ const existing = byKey.get(reference.key) ?? []
+ existing.push(reference)
+ byKey.set(reference.key, existing)
+ }
+
+ return [...byKey.entries()]
+ .map(([key, keyReferences]) => {
+ const uniqueFallbackVariables = new Set(
+ keyReferences.map((reference) => normalizeInterpolationVariables(reference.fallback))
+ )
+ return {
+ key,
+ references: keyReferences,
+ uniqueFallbackVariableCount: uniqueFallbackVariables.size
+ }
+ })
+ .filter(({ uniqueFallbackVariableCount }) => uniqueFallbackVariableCount > 1)
+}
+
function collectInterpolationVariables(value) {
if (typeof value === 'string') {
const matches = value.match(PLACEHOLDER_RE) ?? []
@@ -230,6 +287,14 @@ export async function main(root = process.cwd()) {
return 1
}
+ const inconsistentFallbackVariables = collectInconsistentFallbackVariables(references)
+ if (inconsistentFallbackVariables.length > 0) {
+ console.error('Localization keys are used with inconsistent interpolation placeholders.')
+ console.error('')
+ console.error(formatInconsistentFallbackVariables(inconsistentFallbackVariables))
+ return 1
+ }
+
console.log(`Verified ${references.length} localization key references against en.json.`)
const localeFiles = (await fs.readdir(localesDir))
diff --git a/src/renderer/src/components/GitHubItemDialog.tsx b/src/renderer/src/components/GitHubItemDialog.tsx
index 9156ffeabd1..a2adbf30913 100644
--- a/src/renderer/src/components/GitHubItemDialog.tsx
+++ b/src/renderer/src/components/GitHubItemDialog.tsx
@@ -956,7 +956,7 @@ function PRReviewersPanel({
{translate(
- 'auto.components.GitHubItemDialog.8b15a5e91c',
+ 'auto.components.GitHubItemDialog.5c1c973855',
'Remove reviewer'
)}
diff --git a/src/renderer/src/components/PullRequestPage.tsx b/src/renderer/src/components/PullRequestPage.tsx
index b8e75098b66..13a851dc944 100644
--- a/src/renderer/src/components/PullRequestPage.tsx
+++ b/src/renderer/src/components/PullRequestPage.tsx
@@ -1026,7 +1026,7 @@ function PRReviewersPanel({
- {translate('auto.components.PullRequestPage.ae9a38fd4a', 'Remove reviewer')}
+ {translate('auto.components.PullRequestPage.7f964a365a', 'Remove reviewer')}
) : null}
diff --git a/src/renderer/src/components/TaskPage.tsx b/src/renderer/src/components/TaskPage.tsx
index 8ef6984fd63..ae2c66caa3a 100644
--- a/src/renderer/src/components/TaskPage.tsx
+++ b/src/renderer/src/components/TaskPage.tsx
@@ -231,15 +231,18 @@ type GitLabTaskFilter = 'opened' | 'merged' | 'closed' | 'all'
type GitLabIssueFilter = 'opened' | 'assigned-to-me'
const GITLAB_MR_FILTERS: { id: GitLabTaskFilter; label: string }[] = [
- { id: 'opened', label: translate("auto.components.TaskPage.606a85c774", "Open") },
- { id: 'merged', label: translate("auto.components.TaskPage.37a82eaaf8", "Merged") },
- { id: 'closed', label: translate("auto.components.TaskPage.d09bf34db7", "Closed") },
- { id: 'all', label: translate("auto.components.TaskPage.c2268a9982", "All") }
+ { id: 'opened', label: translate('auto.components.TaskPage.606a85c774', 'Open') },
+ { id: 'merged', label: translate('auto.components.TaskPage.37a82eaaf8', 'Merged') },
+ { id: 'closed', label: translate('auto.components.TaskPage.d09bf34db7', 'Closed') },
+ { id: 'all', label: translate('auto.components.TaskPage.c2268a9982', 'All') }
]
const GITLAB_ISSUE_FILTERS: { id: GitLabIssueFilter; label: string }[] = [
- { id: 'opened', label: translate("auto.components.TaskPage.606a85c774", "Open") },
- { id: 'assigned-to-me', label: translate("auto.components.TaskPage.94f0339621", "Assigned to me") }
+ { id: 'opened', label: translate('auto.components.TaskPage.606a85c774', 'Open') },
+ {
+ id: 'assigned-to-me',
+ label: translate('auto.components.TaskPage.94f0339621', 'Assigned to me')
+ }
]
function isGitLabMRFilter(value: GitLabTaskFilter | GitLabIssueFilter): value is GitLabTaskFilter {
@@ -259,14 +262,34 @@ type TaskQueryPreset = {
type GitHubTaskKind = 'issues' | 'prs'
const ISSUE_TASK_QUERY_PRESETS: TaskQueryPreset[] = [
- { id: 'issues', label: translate("auto.components.TaskPage.606a85c774", "Open"), query: getTaskPresetQuery('issues') },
- { id: 'my-issues', label: translate("auto.components.TaskPage.94f0339621", "Assigned to me"), query: getTaskPresetQuery('my-issues') }
+ {
+ id: 'issues',
+ label: translate('auto.components.TaskPage.606a85c774', 'Open'),
+ query: getTaskPresetQuery('issues')
+ },
+ {
+ id: 'my-issues',
+ label: translate('auto.components.TaskPage.94f0339621', 'Assigned to me'),
+ query: getTaskPresetQuery('my-issues')
+ }
]
const PR_TASK_QUERY_PRESETS: TaskQueryPreset[] = [
- { id: 'prs', label: translate("auto.components.TaskPage.606a85c774", "Open"), query: getTaskPresetQuery('prs') },
- { id: 'my-prs', label: translate("auto.components.TaskPage.7698af5263", "Mine"), query: getTaskPresetQuery('my-prs') },
- { id: 'review', label: translate("auto.components.TaskPage.524f095d55", "Needs review"), query: getTaskPresetQuery('review') }
+ {
+ id: 'prs',
+ label: translate('auto.components.TaskPage.606a85c774', 'Open'),
+ query: getTaskPresetQuery('prs')
+ },
+ {
+ id: 'my-prs',
+ label: translate('auto.components.TaskPage.7698af5263', 'Mine'),
+ query: getTaskPresetQuery('my-prs')
+ },
+ {
+ id: 'review',
+ label: translate('auto.components.TaskPage.524f095d55', 'Needs review'),
+ query: getTaskPresetQuery('review')
+ }
]
function getGitHubTaskKindPresets(kind: GitHubTaskKind): TaskQueryPreset[] {
@@ -291,22 +314,22 @@ function LinearIcon({ className }: { className?: string }): React.JSX.Element {
const SOURCE_OPTIONS: SourceOption[] = [
{
id: 'github',
- label: translate("auto.components.TaskPage.acef77f7ca", "GitHub"),
+ label: translate('auto.components.TaskPage.acef77f7ca', 'GitHub'),
Icon: ({ className }) =>
},
{
id: 'gitlab',
- label: translate("auto.components.TaskPage.11a828abf8", "GitLab"),
+ label: translate('auto.components.TaskPage.11a828abf8', 'GitLab'),
Icon: ({ className }) =>
},
{
id: 'linear',
- label: translate("auto.components.TaskPage.8675cd6188", "Linear"),
+ label: translate('auto.components.TaskPage.8675cd6188', 'Linear'),
Icon: ({ className }) =>
},
{
id: 'jira',
- label: translate("auto.components.TaskPage.9cd11ba218", "Jira"),
+ label: translate('auto.components.TaskPage.9cd11ba218', 'Jira'),
Icon: ({ className }) =>
}
]
@@ -315,10 +338,10 @@ type JiraPresetId = 'assigned' | 'reported' | 'all' | 'done'
type JiraPreset = { id: JiraPresetId; label: string }
const JIRA_PRESETS: JiraPreset[] = [
- { id: 'assigned', label: translate("auto.components.TaskPage.1301d376f1", "Assigned") },
- { id: 'reported', label: translate("auto.components.TaskPage.bd9965df51", "Reported") },
- { id: 'all', label: translate("auto.components.TaskPage.4b6e40e42c", "All Open") },
- { id: 'done', label: translate("auto.components.TaskPage.18451e99df", "Done") }
+ { id: 'assigned', label: translate('auto.components.TaskPage.1301d376f1', 'Assigned') },
+ { id: 'reported', label: translate('auto.components.TaskPage.bd9965df51', 'Reported') },
+ { id: 'all', label: translate('auto.components.TaskPage.4b6e40e42c', 'All Open') },
+ { id: 'done', label: translate('auto.components.TaskPage.18451e99df', 'Done') }
]
const TASK_SEARCH_DEBOUNCE_MS = 300
@@ -387,9 +410,9 @@ const GITHUB_TASK_STICKY_TITLE_CELL_CLASS = cn(
type GitHubModeButton = { id: GitHubTaskKind | 'project'; label: string }
const GITHUB_MODE_BUTTONS: GitHubModeButton[] = [
- { id: 'issues', label: translate("auto.components.TaskPage.dfc0c79bd8", "Issues") },
- { id: 'prs', label: translate("auto.components.TaskPage.137e2a8a01", "PRs") },
- { id: 'project', label: translate("auto.components.TaskPage.727069bee5", "Projects") }
+ { id: 'issues', label: translate('auto.components.TaskPage.dfc0c79bd8', 'Issues') },
+ { id: 'prs', label: translate('auto.components.TaskPage.137e2a8a01', 'PRs') },
+ { id: 'project', label: translate('auto.components.TaskPage.727069bee5', 'Projects') }
]
function isPRFocusedTaskView(preset: TaskViewPresetId | null, query: string): boolean {
@@ -490,9 +513,9 @@ type LinearIssueListRow =
const LINEAR_BOARD_DRAG_ISSUE_MIME = 'application/x-orca-linear-issue-id'
const LINEAR_MODE_OPTIONS: { id: LinearMode; label: string }[] = [
- { id: 'issues', label: translate("auto.components.TaskPage.dfc0c79bd8", "Issues") },
- { id: 'projects', label: translate("auto.components.TaskPage.727069bee5", "Projects") },
- { id: 'views', label: translate("auto.components.TaskPage.e78ec261ed", "Views") }
+ { id: 'issues', label: translate('auto.components.TaskPage.dfc0c79bd8', 'Issues') },
+ { id: 'projects', label: translate('auto.components.TaskPage.727069bee5', 'Projects') },
+ { id: 'views', label: translate('auto.components.TaskPage.e78ec261ed', 'Views') }
]
const LINEAR_CUSTOM_VIEW_MODELS = ['issue', 'project'] satisfies readonly LinearCustomViewModel[]
@@ -502,8 +525,12 @@ const LINEAR_VIEW_OPTIONS: {
label: string
Icon: typeof List
}[] = [
- { id: 'list', label: translate("auto.components.TaskPage.a6f7e93d7f", "List"), Icon: List },
- { id: 'board', label: translate("auto.components.TaskPage.d747aed72f", "Board"), Icon: LayoutGrid }
+ { id: 'list', label: translate('auto.components.TaskPage.a6f7e93d7f', 'List'), Icon: List },
+ {
+ id: 'board',
+ label: translate('auto.components.TaskPage.d747aed72f', 'Board'),
+ Icon: LayoutGrid
+ }
]
function mergeLinearCollectionResults(
@@ -518,26 +545,26 @@ function mergeLinearCollectionResults(
}
const LINEAR_GROUP_OPTIONS: { id: LinearGroupBy; label: string }[] = [
- { id: 'none', label: translate("auto.components.TaskPage.50387522d7", "No grouping") },
- { id: 'status', label: translate("auto.components.TaskPage.154b0fa623", "Status") },
- { id: 'assignee', label: translate("auto.components.TaskPage.d2a876ca53", "Assignee") },
- { id: 'priority', label: translate("auto.components.TaskPage.c8d5bec5f7", "Priority") },
- { id: 'team', label: translate("auto.components.TaskPage.a98cbe7664", "Team") }
+ { id: 'none', label: translate('auto.components.TaskPage.50387522d7', 'No grouping') },
+ { id: 'status', label: translate('auto.components.TaskPage.154b0fa623', 'Status') },
+ { id: 'assignee', label: translate('auto.components.TaskPage.d2a876ca53', 'Assignee') },
+ { id: 'priority', label: translate('auto.components.TaskPage.c8d5bec5f7', 'Priority') },
+ { id: 'team', label: translate('auto.components.TaskPage.a98cbe7664', 'Team') }
]
const LINEAR_ORDER_OPTIONS: { id: LinearOrderBy; label: string }[] = [
- { id: 'priority', label: translate("auto.components.TaskPage.c8d5bec5f7", "Priority") },
- { id: 'updated', label: translate("auto.components.TaskPage.f362667d55", "Updated") },
- { id: 'identifier', label: translate("auto.components.TaskPage.d8a517ad89", "Identifier") }
+ { id: 'priority', label: translate('auto.components.TaskPage.c8d5bec5f7', 'Priority') },
+ { id: 'updated', label: translate('auto.components.TaskPage.f362667d55', 'Updated') },
+ { id: 'identifier', label: translate('auto.components.TaskPage.d8a517ad89', 'Identifier') }
]
const LINEAR_DISPLAY_PROPERTIES: { id: LinearDisplayProperty; label: string }[] = [
- { id: 'state', label: translate("auto.components.TaskPage.154b0fa623", "Status") },
- { id: 'priority', label: translate("auto.components.TaskPage.c8d5bec5f7", "Priority") },
- { id: 'assignee', label: translate("auto.components.TaskPage.d2a876ca53", "Assignee") },
- { id: 'team', label: translate("auto.components.TaskPage.a98cbe7664", "Team") },
- { id: 'labels', label: translate("auto.components.TaskPage.d0ca4aa1d0", "Labels") },
- { id: 'updated', label: translate("auto.components.TaskPage.f362667d55", "Updated") }
+ { id: 'state', label: translate('auto.components.TaskPage.154b0fa623', 'Status') },
+ { id: 'priority', label: translate('auto.components.TaskPage.c8d5bec5f7', 'Priority') },
+ { id: 'assignee', label: translate('auto.components.TaskPage.d2a876ca53', 'Assignee') },
+ { id: 'team', label: translate('auto.components.TaskPage.a98cbe7664', 'Team') },
+ { id: 'labels', label: translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels') },
+ { id: 'updated', label: translate('auto.components.TaskPage.f362667d55', 'Updated') }
]
const DEFAULT_LINEAR_DISPLAY_PROPERTIES: LinearDisplayProperty[] = [
@@ -613,7 +640,10 @@ function LinearStateCell({
}
if (result.ok === false) {
patchLinearIssue(issue.id, { state: previousState })
- toast.error(result.error ?? translate("auto.components.TaskPage.6775c05483", "Failed to update Linear state"))
+ toast.error(
+ result.error ??
+ translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
+ )
}
})
.catch(() => {
@@ -621,7 +651,9 @@ function LinearStateCell({
return
}
patchLinearIssue(issue.id, { state: previousState })
- toast.error(translate("auto.components.TaskPage.6775c05483", "Failed to update Linear state"))
+ toast.error(
+ translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
+ )
})
.finally(() => {
if (reqId === reqRef.current) {
@@ -656,7 +688,11 @@ function LinearStateCell({
...getLinearStatePillStyle(issue.state.color),
cursor: pending ? 'default' : 'pointer'
}}
- aria-label={translate("auto.components.TaskPage.d45a910c4a", "Change Linear state from {{value0}}", { value0: issue.state.name })}
+ aria-label={translate(
+ 'auto.components.TaskPage.d45a910c4a',
+ 'Change Linear state from {{value0}}',
+ { value0: issue.state.name }
+ )}
aria-busy={pending || states.loading}
>
- {translate("auto.components.TaskPage.cc13109b5d", "Loading states")}
+ {translate('auto.components.TaskPage.cc13109b5d', 'Loading states')}
+
) : states.data.length > 0 ? (
states.data.map((state) => (
- {translate("auto.components.TaskPage.afc68824ff", "No states found")}
+ {translate('auto.components.TaskPage.afc68824ff', 'No states found')}
+
)}
@@ -753,7 +791,7 @@ function getLinearIssueGroup(
if (groupBy === 'team') {
return { key: `team:${issue.team.id}`, label: issue.team.name }
}
- return { key: 'all', label: translate("auto.components.TaskPage.dfc0c79bd8", "Issues") }
+ return { key: 'all', label: translate('auto.components.TaskPage.dfc0c79bd8', 'Issues') }
}
function groupLinearIssues(
@@ -763,7 +801,13 @@ function groupLinearIssues(
): LinearGroupSection[] {
const sorted = [...issues].sort((a, b) => compareLinearIssues(a, b, orderBy))
if (groupBy === 'none') {
- return [{ key: 'all', label: translate("auto.components.TaskPage.dfc0c79bd8", "Issues"), issues: sorted }]
+ return [
+ {
+ key: 'all',
+ label: translate('auto.components.TaskPage.dfc0c79bd8', 'Issues'),
+ issues: sorted
+ }
+ ]
}
const sections = new Map
()
@@ -1012,7 +1056,10 @@ function GHStatusCell({
{ state: newState === 'closed' ? 'open' : 'closed' },
item.repoId
)
- toast.error(typed.error ?? translate("auto.components.TaskPage.1c893195ac", "Failed to update state"))
+ toast.error(
+ typed.error ??
+ translate('auto.components.TaskPage.1c893195ac', 'Failed to update state')
+ )
}
})
.catch(() => {
@@ -1021,7 +1068,7 @@ function GHStatusCell({
}
updateLocalState(newState === 'closed' ? 'open' : 'closed')
patchWorkItem(item.id, { state: newState === 'closed' ? 'open' : 'closed' }, item.repoId)
- toast.error(translate("auto.components.TaskPage.1c893195ac", "Failed to update state"))
+ toast.error(translate('auto.components.TaskPage.1c893195ac', 'Failed to update state'))
})
},
[item, localState, repo, patchWorkItem, updateLocalState]
@@ -1030,7 +1077,8 @@ function GHStatusCell({
if (item.type !== 'issue' || !repo) {
return (
- {translate("auto.components.TaskPage.606a85c774", "Open")}
+ {translate('auto.components.TaskPage.606a85c774', 'Open')}
+
)
}
@@ -1047,7 +1095,9 @@ function GHStatusCell({
: 'border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300'
)}
>
- {localState === 'closed' ? translate("auto.components.TaskPage.d09bf34db7", "Closed") : translate("auto.components.TaskPage.606a85c774", "Open")}
+ {localState === 'closed'
+ ? translate('auto.components.TaskPage.d09bf34db7', 'Closed')
+ : translate('auto.components.TaskPage.606a85c774', 'Open')}
@@ -1064,7 +1114,8 @@ function GHStatusCell({
)}
>
- {translate("auto.components.TaskPage.606a85c774", "Open")}
+ {translate('auto.components.TaskPage.606a85c774', 'Open')}
+
{
@@ -1077,7 +1128,8 @@ function GHStatusCell({
)}
>
- {translate("auto.components.TaskPage.d09bf34db7", "Closed")}
+ {translate('auto.components.TaskPage.d09bf34db7', 'Closed')}
+
)
@@ -1192,7 +1244,9 @@ function GitHubIssueLabelSelector({
return (
-
{translate("auto.components.TaskPage.d0ca4aa1d0", "Labels")}
+
+ {translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels')}
+
{selectedLabels.length === 0 ? (
- {translate("auto.components.TaskPage.5ebff3a0aa", "None")}
+
+ {translate('auto.components.TaskPage.5ebff3a0aa', 'None')}
+
) : (
{selectedLabels.map((label) => (
@@ -1222,7 +1278,9 @@ function GitHubIssueLabelSelector({
{error ? (
{error}
) : labels.length === 0 ? (
- {translate("auto.components.TaskPage.b36f4bf9de", "No labels.")}
+
+ {translate('auto.components.TaskPage.b36f4bf9de', 'No labels.')}
+
) : (
labels.map((label) => (
- {translate("auto.components.TaskPage.8aba10579d", "Assignees")}
+
+ {translate('auto.components.TaskPage.8aba10579d', 'Assignees')}
+
{selectedAssignees.length === 0 ? (
- {translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+
+ {translate('auto.components.TaskPage.42a9160321', 'Unassigned')}
+
) : (
@@ -1314,7 +1376,9 @@ function GitHubIssueAssigneeSelector({
{error ? (
{error}
) : assignees.length === 0 ? (
- {translate("auto.components.TaskPage.edf4bc4135", "No assignable users.")}
+
+ {translate('auto.components.TaskPage.edf4bc4135', 'No assignable users.')}
+
) : (
assignees.map((assignee) => {
const selected = selectedLogins.has(assignee.login.toLowerCase())
@@ -1443,7 +1507,11 @@ function GHAssigneesCell({
}
} catch (err) {
patchWorkItem(item.id, { assignees: previousAssignees }, item.repoId)
- toast.error(err instanceof Error ? err.message : translate("auto.components.TaskPage.ca63694b4c", "Failed to update assignees."))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate('auto.components.TaskPage.ca63694b4c', 'Failed to update assignees.')
+ )
} finally {
setPendingLogin(null)
}
@@ -1488,8 +1556,10 @@ function GHAssigneesCell({
type="button"
aria-label={
assignees.length
- ? translate("auto.components.TaskPage.bb63046423", "Assigned to {{value0}}", { value0: assignees.map((a) => a.login).join(', ') })
- : translate("auto.components.TaskPage.7f94eb6395", "Assign issue")
+ ? translate('auto.components.TaskPage.bb63046423', 'Assigned to {{value0}}', {
+ value0: assignees.map((a) => a.login).join(', ')
+ })
+ : translate('auto.components.TaskPage.7f94eb6395', 'Assign issue')
}
aria-busy={pendingLogin !== null}
onClick={(event) => event.stopPropagation()}
@@ -1515,13 +1585,19 @@ function GHAssigneesCell({
onClick={(event) => event.stopPropagation()}
>
{!owner || !repoName ? (
- {translate("auto.components.TaskPage.53e002d895", "Issue has no repo slug.")}
+
+ {translate('auto.components.TaskPage.53e002d895', 'Issue has no repo slug.')}
+
) : metadata.loading ? (
- {translate("auto.components.TaskPage.0eacf48491", "Loading…")}
+
+ {translate('auto.components.TaskPage.0eacf48491', 'Loading…')}
+
) : metadata.error ? (
{metadata.error}
) : metadata.data.length === 0 ? (
- {translate("auto.components.TaskPage.edf4bc4135", "No assignable users.")}
+
+ {translate('auto.components.TaskPage.edf4bc4135', 'No assignable users.')}
+
) : (
metadata.data.map((user) => {
const isOn = assignees.some((a) => a.login.toLowerCase() === user.login.toLowerCase())
@@ -1834,7 +1910,11 @@ function PRReviewCell({
)
if (item.type !== 'pr') {
- return {translate("auto.components.TaskPage.b1eaa18ace", "Issue")}
+ return (
+
+ {translate('auto.components.TaskPage.b1eaa18ace', 'Issue')}
+
+ )
}
const itemWithLocalReviewRequests = { ...item, reviewRequests: localReviewRequests }
@@ -1854,11 +1934,13 @@ function PRReviewCell({
selectedReviewerLogins
)
if (logins.length === 0) {
- toast.error(translate("auto.components.TaskPage.d00571d9b1", "Enter a reviewer"))
+ toast.error(translate('auto.components.TaskPage.d00571d9b1', 'Enter a reviewer'))
return
}
if (localReviewRequests.length + logins.length > 15) {
- toast.error(translate("auto.components.TaskPage.969e26577c", "You can request up to 15 reviewers"))
+ toast.error(
+ translate('auto.components.TaskPage.969e26577c', 'You can request up to 15 reviewers')
+ )
return
}
setSubmitting(true)
@@ -1879,7 +1961,7 @@ function PRReviewCell({
reviewers: logins
})
if (result.ok) {
- toast.success(translate("auto.components.TaskPage.8f06dbb9e5", "Reviewer requested"))
+ toast.success(translate('auto.components.TaskPage.8f06dbb9e5', 'Reviewer requested'))
const nextReviewRequests = buildRequestedReviewUsers(
logins,
reviewerCandidates,
@@ -1892,7 +1974,7 @@ function PRReviewCell({
toast.error(result.error)
}
} catch {
- toast.error(translate("auto.components.TaskPage.dc67f69962", "Failed to request reviewer"))
+ toast.error(translate('auto.components.TaskPage.dc67f69962', 'Failed to request reviewer'))
} finally {
setSubmitting(false)
}
@@ -1927,7 +2009,11 @@ function PRReviewCell({
reviewers: logins
})
if (result.ok) {
- toast.success(logins.length === 1 ? translate("auto.components.TaskPage.f9191d1714", "Reviewer removed") : translate("auto.components.TaskPage.837bb901ec", "Reviewers removed"))
+ toast.success(
+ logins.length === 1
+ ? translate('auto.components.TaskPage.f9191d1714', 'Reviewer removed')
+ : translate('auto.components.TaskPage.837bb901ec', 'Reviewers removed')
+ )
const removed = new Set(logins.map((login) => login.toLowerCase()))
const nextReviewRequests = localReviewRequests.filter(
(reviewer) => !removed.has(reviewer.login.toLowerCase())
@@ -1939,7 +2025,7 @@ function PRReviewCell({
toast.error(result.error)
}
} catch {
- toast.error(translate("auto.components.TaskPage.ed1daeb49a", "Failed to remove reviewer"))
+ toast.error(translate('auto.components.TaskPage.ed1daeb49a', 'Failed to remove reviewer'))
} finally {
setSubmitting(false)
}
@@ -2009,7 +2095,11 @@ function PRReviewCell({
{options.suggested ? (
- {translate("auto.components.TaskPage.5d4fd69a6a", "Recently active in this pull request")}
+ {translate(
+ 'auto.components.TaskPage.5d4fd69a6a',
+ 'Recently active in this pull request'
+ )}
+
) : null}
@@ -2041,17 +2131,18 @@ function PRReviewCell({
>
- {translate("auto.components.TaskPage.62c7bd789f", "Request up to 15 reviewers")}
+ {translate('auto.components.TaskPage.62c7bd789f', 'Request up to 15 reviewers')}
+
setReviewerInput(event.target.value)}
- placeholder={translate("auto.components.TaskPage.0b9b04f4b5", "Type or choose a user")}
+ placeholder={translate('auto.components.TaskPage.0b9b04f4b5', 'Type or choose a user')}
disabled={!repo || submitting}
className="h-8 rounded-md bg-background px-2 text-[13px]"
- aria-label={translate("auto.components.TaskPage.0b9b04f4b5", "Type or choose a user")}
+ aria-label={translate('auto.components.TaskPage.0b9b04f4b5', 'Type or choose a user')}
aria-autocomplete="list"
onKeyDown={(event) => {
if (event.key === 'ArrowDown' && actionableReviewerRows.length > 0) {
@@ -2086,20 +2177,24 @@ function PRReviewCell({
{reviewerMetadata.loading ? (
-
{translate("auto.components.TaskPage.0eacf48491", "Loading…")}
+
+ {translate('auto.components.TaskPage.0eacf48491', 'Loading…')}
+
) : filteredReviewerCandidates.length > 0 ? (
<>
{suggestedReviewerRows.length > 0 ? (
<>
- {translate("auto.components.TaskPage.3ace2e6bcf", "Suggestions")}
+ {translate('auto.components.TaskPage.3ace2e6bcf', 'Suggestions')}
+
{suggestedReviewerRows.map((reviewer, index) =>
renderReviewerPickerRow(reviewer, { suggested: true, activeIndex: index })
)}
>
) : null}
- {translate("auto.components.TaskPage.67755a83a1", "Everyone else")}
+ {translate('auto.components.TaskPage.67755a83a1', 'Everyone else')}
+
{everyoneElseReviewerRows.length > 0 ? (
everyoneElseReviewerRows.map((reviewer, index) =>
renderReviewerPickerRow(reviewer, {
@@ -2109,15 +2204,19 @@ function PRReviewCell({
)
) : (
- {translate("auto.components.TaskPage.8a22eb3f7b", "No matching reviewers.")}
+ {translate('auto.components.TaskPage.8a22eb3f7b', 'No matching reviewers.')}
+
)}
>
) : (
{reviewerMetadata.error ??
(hasReviewerMetadata
- ? translate("auto.components.TaskPage.8a22eb3f7b", "No matching reviewers.")
- : translate("auto.components.TaskPage.9e03c17847", "Open the PR details to view current reviewers."))}
+ ? translate('auto.components.TaskPage.8a22eb3f7b', 'No matching reviewers.')
+ : translate(
+ 'auto.components.TaskPage.9e03c17847',
+ 'Open the PR details to view current reviewers.'
+ ))}
)}
@@ -2162,7 +2261,11 @@ function PRChecksCell({
}, [item.checksSummary, item.type, onLoadChecks])
if (item.type !== 'pr') {
- return
{translate("auto.components.TaskPage.b1eaa18ace", "Issue")}
+ return (
+
+ {translate('auto.components.TaskPage.b1eaa18ace', 'Issue')}
+
+ )
}
const summary = item.checksSummary
const Icon =
@@ -2196,7 +2299,8 @@ function PRChecksCell({
- {translate("auto.components.TaskPage.995dd6af9b", "Open PR checks")}
+ {translate('auto.components.TaskPage.995dd6af9b', 'Open PR checks')}
+
)
}
@@ -2213,7 +2317,11 @@ function PRMergeCell({
const [merging, setMerging] = useState(false)
const confirm = useConfirmationDialog()
if (item.type !== 'pr') {
- return
{translate("auto.components.TaskPage.b1eaa18ace", "Issue")}
+ return (
+
+ {translate('auto.components.TaskPage.b1eaa18ace', 'Issue')}
+
+ )
}
const mergePresentation = presentGitHubPRMergeState(item)
const mergeMethods = resolveGitHubPRMergeMethods(item.mergeMethodSettings)
@@ -2225,8 +2333,14 @@ function PRMergeCell({
}
const label = GITHUB_PR_MERGE_METHOD_LABELS[method]
const confirmed = await confirm({
- title: translate("auto.components.TaskPage.844dc193c7", "{{value0}} PR #{{value1}}?", { value0: label, value1: item.number }),
- description: translate("auto.components.TaskPage.0506a78337", "This will update the pull request on GitHub."),
+ title: translate('auto.components.TaskPage.844dc193c7', '{{value0}} PR #{{value1}}?', {
+ value0: label,
+ value1: item.number
+ }),
+ description: translate(
+ 'auto.components.TaskPage.0506a78337',
+ 'This will update the pull request on GitHub.'
+ ),
confirmLabel: label
})
if (!confirmed) {
@@ -2242,13 +2356,13 @@ function PRMergeCell({
prRepo: item.prRepo ?? null
})
if (result.ok) {
- toast.success(translate("auto.components.TaskPage.a161925adc", "Pull request merged"))
+ toast.success(translate('auto.components.TaskPage.a161925adc', 'Pull request merged'))
onRefresh()
} else {
toast.error(result.error)
}
} catch {
- toast.error(translate("auto.components.TaskPage.88f478cdef", "Failed to merge pull request"))
+ toast.error(translate('auto.components.TaskPage.88f478cdef', 'Failed to merge pull request'))
} finally {
setMerging(false)
}
@@ -2269,13 +2383,21 @@ function PRMergeCell({
prRepo: item.prRepo ?? null
})
if (result.ok) {
- toast.success(enabled ? translate("auto.components.TaskPage.fed317634c", "Auto-merge enabled") : translate("auto.components.TaskPage.a5bf86defe", "Auto-merge disabled"))
+ toast.success(
+ enabled
+ ? translate('auto.components.TaskPage.fed317634c', 'Auto-merge enabled')
+ : translate('auto.components.TaskPage.a5bf86defe', 'Auto-merge disabled')
+ )
onRefresh()
} else {
toast.error(result.error)
}
} catch {
- toast.error(enabled ? translate("auto.components.TaskPage.a3318684bc", "Failed to enable auto-merge") : translate("auto.components.TaskPage.1a9ea003dc", "Failed to disable auto-merge"))
+ toast.error(
+ enabled
+ ? translate('auto.components.TaskPage.a3318684bc', 'Failed to enable auto-merge')
+ : translate('auto.components.TaskPage.1a9ea003dc', 'Failed to disable auto-merge')
+ )
} finally {
setMerging(false)
}
@@ -2328,7 +2450,8 @@ function PRMergeCell({
))}
window.api.shell.openUrl(item.url)}>
- {translate("auto.components.TaskPage.37d60046e3", "Open GitHub merge box")}
+ {translate('auto.components.TaskPage.37d60046e3', 'Open GitHub merge box')}
+
)
@@ -2382,18 +2505,19 @@ function PaginationBar({
return (
onPageChange(currentPage - 1)}
- aria-label={translate("auto.components.TaskPage.6cd6b3ae6a", "Previous page")}
+ aria-label={translate('auto.components.TaskPage.6cd6b3ae6a', 'Previous page')}
className={btnClass}
>
- {translate("auto.components.TaskPage.297a805b64", "Previous")}
+ {translate('auto.components.TaskPage.297a805b64', 'Previous')}
+
{pageNumbers.map((entry, idx) =>
entry === 'ellipsis' ? (
@@ -2402,14 +2526,17 @@ function PaginationBar({
aria-hidden
className="inline-flex size-8 items-center justify-center text-sm text-muted-foreground"
>
- {translate("auto.components.TaskPage.cd171f3391", "...")}
+ {translate('auto.components.TaskPage.cd171f3391', '...')}
+
) : (
onPageChange(entry)}
- aria-label={translate("auto.components.TaskPage.ae859c816b", "Page {{value0}}", { value0: entry + 1 })}
+ aria-label={translate('auto.components.TaskPage.ae859c816b', 'Page {{value0}}', {
+ value0: entry + 1
+ })}
aria-current={entry === currentPage ? 'page' : undefined}
className={numClass(entry)}
>
@@ -2426,10 +2553,11 @@ function PaginationBar({
type="button"
disabled={currentPage >= totalPages - 1 || loadingTarget !== null}
onClick={() => onPageChange(currentPage + 1)}
- aria-label={translate("auto.components.TaskPage.0c8df28045", "Next page")}
+ aria-label={translate('auto.components.TaskPage.0c8df28045', 'Next page')}
className={btnClass}
>
- {translate("auto.components.TaskPage.b73717af92", "Next")}
+ {translate('auto.components.TaskPage.b73717af92', 'Next')}
+
)
@@ -2638,7 +2766,11 @@ export default function TaskPage(): React.JSX.Element {
visibleTaskProviders: nextVisibleTaskProviders,
defaultTaskSource: nextDefaultTaskSource
}).catch(() => {
- toast.error(translate("auto.components.TaskPage.e9139db03f", "Failed to hide {{value0}}.", { value0: label }))
+ toast.error(
+ translate('auto.components.TaskPage.e9139db03f', 'Failed to hide {{value0}}.', {
+ value0: label
+ })
+ )
})
},
[defaultTaskSource, preferredVisibleTaskProviders, updateSettings]
@@ -2955,7 +3087,11 @@ export default function TaskPage(): React.JSX.Element {
? `${entry.sources.prs.owner}/${entry.sources.prs.repo}`
: r.displayName
toast.message(
- translate("auto.components.TaskPage.f4374519ae", "Your preferred issue source (upstream) is no longer configured for {{value0}}. Using origin.", { value0: prSlug })
+ translate(
+ 'auto.components.TaskPage.f4374519ae',
+ 'Your preferred issue source (upstream) is no longer configured for {{value0}}. Using origin.',
+ { value0: prSlug }
+ )
)
fellBackToastedRef.current.add(r.id)
}
@@ -3256,7 +3392,12 @@ export default function TaskPage(): React.JSX.Element {
const openLinearProjectContext = useCallback(
(project: LinearProjectSummary, options?: { parentView?: LinearCustomViewSummary | null }) => {
if (!project.workspaceId) {
- toast.error(translate("auto.components.TaskPage.cba2a2b7fb", "Linear project is missing workspace context."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.cba2a2b7fb',
+ 'Linear project is missing workspace context.'
+ )
+ )
return
}
const parentView = options?.parentView ?? null
@@ -3290,7 +3431,12 @@ export default function TaskPage(): React.JSX.Element {
const openLinearCustomViewContext = useCallback(
(view: LinearCustomViewSummary) => {
if (!view.workspaceId) {
- toast.error(translate("auto.components.TaskPage.669e419d65", "Linear view is missing workspace context."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.669e419d65',
+ 'Linear view is missing workspace context.'
+ )
+ )
return
}
clearSelectedLinearIssue()
@@ -4156,7 +4302,13 @@ export default function TaskPage(): React.JSX.Element {
const states = await linearTeamStates(settings, issue.team.id, issue.workspaceId)
const workflowState = findLinearWorkflowStateForStatus(states, targetState)
if (!workflowState) {
- toast.error(translate("auto.components.TaskPage.745ae567d4", "\"{{value0}}\" is not available for {{value1}}", { value0: targetState.name, value1: issue.team.name }))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.745ae567d4',
+ '"{{value0}}" is not available for {{value1}}',
+ { value0: targetState.name, value1: issue.team.name }
+ )
+ )
return
}
@@ -4180,13 +4332,18 @@ export default function TaskPage(): React.JSX.Element {
patchLinearIssue(issue.id, { state: previousState })
patchScopedLinearIssue(issue.id, { state: previousState })
applyFallbackState(previousState)
- toast.error(result.error ?? translate("auto.components.TaskPage.6775c05483", "Failed to update Linear state"))
+ toast.error(
+ result.error ??
+ translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
+ )
}
} catch {
patchLinearIssue(issue.id, { state: previousState })
patchScopedLinearIssue(issue.id, { state: previousState })
applyFallbackState(previousState)
- toast.error(translate("auto.components.TaskPage.6775c05483", "Failed to update Linear state"))
+ toast.error(
+ translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
+ )
} finally {
setLinearBoardUpdatingIssueIds((prev) => {
const next = new Set(prev)
@@ -4555,7 +4712,9 @@ export default function TaskPage(): React.JSX.Element {
})
.catch(() => {
if (!cancelled) {
- toast.error(translate("auto.components.TaskPage.af2a8371de", "Failed to load Jira issue types."))
+ toast.error(
+ translate('auto.components.TaskPage.af2a8371de', 'Failed to load Jira issue types.')
+ )
}
})
.finally(() => {
@@ -5084,7 +5243,9 @@ export default function TaskPage(): React.JSX.Element {
// preset updates the persisted settings instead of only changing the
// current page state.
void updateSettings({ defaultTaskViewPreset: presetId }).catch(() => {
- toast.error(translate("auto.components.TaskPage.fe380f306c", "Failed to save default task view."))
+ toast.error(
+ translate('auto.components.TaskPage.fe380f306c', 'Failed to save default task view.')
+ )
})
},
[updateSettings]
@@ -5234,8 +5395,14 @@ export default function TaskPage(): React.JSX.Element {
if (result === false) {
toast.error(
item.type === 'pr'
- ? translate("auto.components.TaskPage.534a9c6017", "Unable to open the workspace attached to this pull request.")
- : translate("auto.components.TaskPage.585dba2989", "Unable to open the workspace attached to this issue.")
+ ? translate(
+ 'auto.components.TaskPage.534a9c6017',
+ 'Unable to open the workspace attached to this pull request.'
+ )
+ : translate(
+ 'auto.components.TaskPage.585dba2989',
+ 'Unable to open the workspace attached to this issue.'
+ )
)
}
},
@@ -5299,17 +5466,25 @@ export default function TaskPage(): React.JSX.Element {
assignees: newIssueAssignees.map((assignee) => assignee.login)
})
if (!result.ok) {
- toast.error(result.error || translate("auto.components.TaskPage.7437e340b4", "Failed to create issue."))
+ toast.error(
+ result.error ||
+ translate('auto.components.TaskPage.7437e340b4', 'Failed to create issue.')
+ )
return
}
- toast.success(translate("auto.components.TaskPage.3f9604efc7", "Opened issue #{{value0}}", { value0: result.number }), {
- action: result.url
- ? {
- label: translate("auto.components.TaskPage.9c57663908", "View"),
- onClick: () => window.open(result.url, '_blank')
- }
- : undefined
- })
+ toast.success(
+ translate('auto.components.TaskPage.3f9604efc7', 'Opened issue #{{value0}}', {
+ value0: result.number
+ }),
+ {
+ action: result.url
+ ? {
+ label: translate('auto.components.TaskPage.9c57663908', 'View'),
+ onClick: () => window.open(result.url, '_blank')
+ }
+ : undefined
+ }
+ )
setNewIssueOpen(false)
setNewIssueTitle('')
setNewIssueBody('')
@@ -5400,17 +5575,25 @@ export default function TaskPage(): React.JSX.Element {
targetDate: newLinearProjectTargetDate || undefined
})
if (!result.ok) {
- toast.error(result.error || translate("auto.components.TaskPage.3ca9b424a3", "Failed to create project."))
+ toast.error(
+ result.error ||
+ translate('auto.components.TaskPage.3ca9b424a3', 'Failed to create project.')
+ )
return
}
- toast.success(translate("auto.components.TaskPage.cb98f0350c", "Created {{value0}}", { value0: result.project.name }), {
- action: result.project.url
- ? {
- label: translate("auto.components.TaskPage.9c57663908", "View"),
- onClick: () => window.open(result.project.url, '_blank')
- }
- : undefined
- })
+ toast.success(
+ translate('auto.components.TaskPage.cb98f0350c', 'Created {{value0}}', {
+ value0: result.project.name
+ }),
+ {
+ action: result.project.url
+ ? {
+ label: translate('auto.components.TaskPage.9c57663908', 'View'),
+ onClick: () => window.open(result.project.url, '_blank')
+ }
+ : undefined
+ }
+ )
setNewLinearProjectOpen(false)
setNewLinearProjectName('')
setNewLinearProjectDescription('')
@@ -5431,7 +5614,11 @@ export default function TaskPage(): React.JSX.Element {
openLinearProjectContext(result.project)
setLinearRefreshNonce((n) => n + 1)
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.TaskPage.3ca9b424a3", "Failed to create project."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate('auto.components.TaskPage.3ca9b424a3', 'Failed to create project.')
+ )
} finally {
setNewLinearProjectSubmitting(false)
}
@@ -5464,7 +5651,12 @@ export default function TaskPage(): React.JSX.Element {
newLinearIssueProjectId === selectedLinearProject.id &&
newLinearIssueTargetTeam.workspaceId !== selectedLinearProject.workspaceId
) {
- toast.error(translate("auto.components.TaskPage.1e1b2ad8f2", "Select a team from the project workspace before filing this issue."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.1e1b2ad8f2',
+ 'Select a team from the project workspace before filing this issue.'
+ )
+ )
return
}
setNewLinearIssueSubmitting(true)
@@ -5481,17 +5673,25 @@ export default function TaskPage(): React.JSX.Element {
labelIds: newLinearIssueLabelIds.length > 0 ? newLinearIssueLabelIds : undefined
})
if (!result.ok) {
- toast.error(result.error || translate("auto.components.TaskPage.7437e340b4", "Failed to create issue."))
+ toast.error(
+ result.error ||
+ translate('auto.components.TaskPage.7437e340b4', 'Failed to create issue.')
+ )
return
}
- toast.success(translate("auto.components.TaskPage.cb98f0350c", "Created {{value0}}", { value0: result.identifier }), {
- action: result.url
- ? {
- label: translate("auto.components.TaskPage.9c57663908", "View"),
- onClick: () => window.open(result.url, '_blank')
- }
- : undefined
- })
+ toast.success(
+ translate('auto.components.TaskPage.cb98f0350c', 'Created {{value0}}', {
+ value0: result.identifier
+ }),
+ {
+ action: result.url
+ ? {
+ label: translate('auto.components.TaskPage.9c57663908', 'View'),
+ onClick: () => window.open(result.url, '_blank')
+ }
+ : undefined
+ }
+ )
setNewLinearIssueOpen(false)
setNewLinearIssueTitle('')
setNewLinearIssueBody('')
@@ -5552,17 +5752,25 @@ export default function TaskPage(): React.JSX.Element {
customFields
})
if (!result.ok) {
- toast.error(result.error || translate("auto.components.TaskPage.aec5feeb69", "Failed to create Jira issue."))
+ toast.error(
+ result.error ||
+ translate('auto.components.TaskPage.aec5feeb69', 'Failed to create Jira issue.')
+ )
return
}
- toast.success(translate("auto.components.TaskPage.cb98f0350c", "Created {{value0}}", { value0: result.key }), {
- action: result.url
- ? {
- label: translate("auto.components.TaskPage.9c57663908", "View"),
- onClick: () => window.open(result.url, '_blank')
- }
- : undefined
- })
+ toast.success(
+ translate('auto.components.TaskPage.cb98f0350c', 'Created {{value0}}', {
+ value0: result.key
+ }),
+ {
+ action: result.url
+ ? {
+ label: translate('auto.components.TaskPage.9c57663908', 'View'),
+ onClick: () => window.open(result.url, '_blank')
+ }
+ : undefined
+ }
+ )
setNewJiraIssueOpen(false)
setNewJiraIssueTitle('')
setNewJiraIssueBody('')
@@ -6286,7 +6494,9 @@ export default function TaskPage(): React.JSX.Element {
})
.catch(() => {
setLinearLoading(false)
- toast.error(translate("auto.components.TaskPage.d0d570b306", "Failed to switch Linear workspace."))
+ toast.error(
+ translate('auto.components.TaskPage.d0d570b306', 'Failed to switch Linear workspace.')
+ )
})
},
[clearSelectedLinearIssue, linearMode, selectLinearWorkspace, setTaskResumeState]
@@ -6296,7 +6506,9 @@ export default function TaskPage(): React.JSX.Element {
(next: ReadonlySet
, persisted: string[] | null): void => {
setLinearTeamSelection(new Set(next))
void updateSettings({ defaultLinearTeamSelection: persisted }).catch(() => {
- toast.error(translate("auto.components.TaskPage.3f594861a5", "Failed to save team selection."))
+ toast.error(
+ translate('auto.components.TaskPage.3f594861a5', 'Failed to save team selection.')
+ )
})
},
[updateSettings]
@@ -6412,13 +6624,17 @@ export default function TaskPage(): React.JSX.Element {
size="icon"
className="size-7 rounded-full"
onClick={closeTaskPage}
- aria-label={translate("auto.components.TaskPage.1a06219d5c", "Close tasks")}
+ aria-label={translate(
+ 'auto.components.TaskPage.1a06219d5c',
+ 'Close tasks'
+ )}
>
- {translate("auto.components.TaskPage.4826fd1ad8", "Close · Esc")}
+ {translate('auto.components.TaskPage.4826fd1ad8', 'Close · Esc')}
+
{visibleSourceOptions.map((source) => {
@@ -6433,7 +6649,12 @@ export default function TaskPage(): React.JSX.Element {
taskSourceManuallyChangedRef.current = true
openTaskPage({ taskSource: source.id })
void updateSettings({ defaultTaskSource: source.id }).catch(() => {
- toast.error(translate("auto.components.TaskPage.609532fae7", "Failed to save default task source."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.609532fae7',
+ 'Failed to save default task source.'
+ )
+ )
})
}}
aria-label={source.label}
@@ -6455,7 +6676,7 @@ export default function TaskPage(): React.JSX.Element {
)
})}
- {taskSource === "linear" && linearStatus.connected ? (
+ {taskSource === 'linear' && linearStatus.connected ? (
@@ -6493,13 +6721,20 @@ export default function TaskPage(): React.JSX.Element {
{selectedLinearTeamForExternalLink
- ? translate("auto.components.TaskPage.606a85c774", "Open {{value0}} in Linear", { value0: selectedLinearTeamForExternalLink.name })
- : translate("auto.components.TaskPage.2af3ab5c58", "Select one team to open in Linear")}
+ ? translate(
+ 'auto.components.TaskPage.246bd64aed',
+ 'Open {{value0}} in Linear',
+ { value0: selectedLinearTeamForExternalLink.name }
+ )
+ : translate(
+ 'auto.components.TaskPage.2af3ab5c58',
+ 'Select one team to open in Linear'
+ )}
) : null}
- {taskSource === "jira" && jiraStatus.connected ? (
+ {taskSource === 'jira' && jiraStatus.connected ? (
{jiraSites.length > 1 ? (
{
- toast.error(translate("auto.components.TaskPage.d09b7631b7", "Failed to switch Jira site."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.d09b7631b7',
+ 'Failed to switch Jira site.'
+ )
+ )
})
}}
>
@@ -6519,7 +6759,9 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.e592d99051", "All Jira sites")}
+
+ {translate('auto.components.TaskPage.e592d99051', 'All Jira sites')}
+
{jiraSites.map((site) => (
{site.displayName}
@@ -6532,7 +6774,7 @@ export default function TaskPage(): React.JSX.Element {
) : null}
- {taskSource === "github" ? (
+ {taskSource === 'github' ? (
{projectModeVisible ? (
@@ -6573,7 +6815,7 @@ export default function TaskPage(): React.JSX.Element {
view filter (server-side), so this control would be
inert — hide it to avoid suggesting it does
something. */}
- {githubMode !== "project" && (
+ {githubMode !== 'project' && (
<>
{
setRepoSelection(next)
void updateSettings({ defaultRepoSelection: [...next] }).catch(() => {
- toast.error(translate("auto.components.TaskPage.dfd72673e7", "Failed to save project selection."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.dfd72673e7',
+ 'Failed to save project selection.'
+ )
+ )
})
}}
onSelectAll={() => {
const allIds = new Set(eligibleRepos.map((r) => r.id))
setRepoSelection(allIds)
void updateSettings({ defaultRepoSelection: null }).catch(() => {
- toast.error(translate("auto.components.TaskPage.dfd72673e7", "Failed to save project selection."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.dfd72673e7',
+ 'Failed to save project selection.'
+ )
+ )
})
}}
triggerClassName="h-8 w-auto max-w-[220px] rounded-md border border-border/50 bg-muted/50 px-2 text-xs font-medium shadow-sm transition hover:bg-muted/50 focus:ring-2 focus:ring-ring/20 focus:outline-none"
@@ -6609,8 +6861,15 @@ export default function TaskPage(): React.JSX.Element {
}}
aria-label={
selectedGitHubRepoExternalLink
- ? translate("auto.components.TaskPage.606a85c774", "Open {{value0}} in GitHub", { value0: selectedGitHubRepoExternalLink.label })
- : translate("auto.components.TaskPage.d1132848f8", "Select one GitHub project to open in GitHub")
+ ? translate(
+ 'auto.components.TaskPage.8d1e17a3ef',
+ 'Open {{value0}} in GitHub',
+ { value0: selectedGitHubRepoExternalLink.label }
+ )
+ : translate(
+ 'auto.components.TaskPage.d1132848f8',
+ 'Select one GitHub project to open in GitHub'
+ )
}
className="h-8 w-8 rounded-md border-border/50 bg-muted/50 text-foreground shadow-sm transition hover:bg-muted/50"
>
@@ -6619,8 +6878,15 @@ export default function TaskPage(): React.JSX.Element {
{selectedGitHubRepoExternalLink
- ? translate("auto.components.TaskPage.606a85c774", "Open {{value0}} in GitHub", { value0: selectedGitHubRepoExternalLink.label })
- : translate("auto.components.TaskPage.bc46d8204e", "Select one project to open in GitHub")}
+ ? translate(
+ 'auto.components.TaskPage.8d1e17a3ef',
+ 'Open {{value0}} in GitHub',
+ { value0: selectedGitHubRepoExternalLink.label }
+ )
+ : translate(
+ 'auto.components.TaskPage.bc46d8204e',
+ 'Select one project to open in GitHub'
+ )}
>
@@ -6628,7 +6894,7 @@ export default function TaskPage(): React.JSX.Element {
) : null}
- {taskSource === "github" && githubMode === "items" ? (
+ {taskSource === 'github' && githubMode === 'items' ? (
{taskSearchInput || appliedTaskSearch ? (
@@ -6720,14 +6995,18 @@ export default function TaskPage(): React.JSX.Element {
setNewIssueOpen(true)
}}
disabled={!newIssueTargetRepo}
- aria-label={translate("auto.components.TaskPage.d3d0998b7d", "New GitHub issue")}
+ aria-label={translate(
+ 'auto.components.TaskPage.d3d0998b7d',
+ 'New GitHub issue'
+ )}
className="size-8 border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md supports-[backdrop-filter]:bg-transparent"
>
- {translate("auto.components.TaskPage.d3d0998b7d", "New GitHub issue")}
+ {translate('auto.components.TaskPage.d3d0998b7d', 'New GitHub issue')}
+
@@ -6738,7 +7017,15 @@ export default function TaskPage(): React.JSX.Element {
disabled={githubTasksBusy}
aria-busy={githubTasksBusy}
aria-label={
- githubTasksBusy ? translate("auto.components.TaskPage.6ffa6be99f", "Refreshing GitHub work") : translate("auto.components.TaskPage.ff53631e6f", "Refresh GitHub work")
+ githubTasksBusy
+ ? translate(
+ 'auto.components.TaskPage.6ffa6be99f',
+ 'Refreshing GitHub work'
+ )
+ : translate(
+ 'auto.components.TaskPage.ff53631e6f',
+ 'Refresh GitHub work'
+ )
}
className="size-8 cursor-pointer border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md disabled:pointer-events-auto disabled:cursor-wait supports-[backdrop-filter]:bg-transparent"
>
@@ -6750,7 +7037,15 @@ export default function TaskPage(): React.JSX.Element {
- {githubTasksBusy ? translate("auto.components.TaskPage.31f81cc334", "Refreshing GitHub work…") : translate("auto.components.TaskPage.ff53631e6f", "Refresh GitHub work")}
+ {githubTasksBusy
+ ? translate(
+ 'auto.components.TaskPage.31f81cc334',
+ 'Refreshing GitHub work…'
+ )
+ : translate(
+ 'auto.components.TaskPage.ff53631e6f',
+ 'Refresh GitHub work'
+ )}
@@ -6828,7 +7123,7 @@ export default function TaskPage(): React.JSX.Element {
)
})()}
- ) : taskSource === "linear" && linearStatus.connected ? (
+ ) : taskSource === 'linear' && linearStatus.connected ? (
{LINEAR_MODE_OPTIONS.map((mode) => {
const active = linearMode === mode.id
@@ -6899,9 +7197,15 @@ export default function TaskPage(): React.JSX.Element {
}}
disabled={availableTeams.length === 0}
aria-label={
- linearMode === "projects" && !selectedLinearProject
- ? translate("auto.components.TaskPage.1361275ec3", "New Linear project")
- : translate("auto.components.TaskPage.3feb524d42", "New Linear issue")
+ linearMode === 'projects' && !selectedLinearProject
+ ? translate(
+ 'auto.components.TaskPage.1361275ec3',
+ 'New Linear project'
+ )
+ : translate(
+ 'auto.components.TaskPage.3feb524d42',
+ 'New Linear issue'
+ )
}
className="size-8 border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md supports-[backdrop-filter]:bg-transparent"
>
@@ -6909,9 +7213,15 @@ export default function TaskPage(): React.JSX.Element {
- {linearMode === "projects" && !selectedLinearProject
- ? translate("auto.components.TaskPage.1361275ec3", "New Linear project")
- : translate("auto.components.TaskPage.3feb524d42", "New Linear issue")}
+ {linearMode === 'projects' && !selectedLinearProject
+ ? translate(
+ 'auto.components.TaskPage.1361275ec3',
+ 'New Linear project'
+ )
+ : translate(
+ 'auto.components.TaskPage.3feb524d42',
+ 'New Linear issue'
+ )}
@@ -6927,15 +7237,18 @@ export default function TaskPage(): React.JSX.Element {
? linearProjectsLoading || linearProjectDetailLoading
: linearCustomViewsLoading || linearCustomViewContentsLoading
}
- aria-label={translate("auto.components.TaskPage.8964184a8b", "Refresh Linear")}
+ aria-label={translate(
+ 'auto.components.TaskPage.8964184a8b',
+ 'Refresh Linear'
+ )}
className="size-8 border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md supports-[backdrop-filter]:bg-transparent"
>
- {linearMode === "issues" && linearLoading ? (
+ {linearMode === 'issues' && linearLoading ? (
- ) : linearMode === "projects" &&
+ ) : linearMode === 'projects' &&
(linearProjectsLoading || linearProjectDetailLoading) ? (
- ) : linearMode === "views" &&
+ ) : linearMode === 'views' &&
(linearCustomViewsLoading || linearCustomViewContentsLoading) ? (
) : (
@@ -6944,12 +7257,13 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.8964184a8b", "Refresh Linear")}
+ {translate('auto.components.TaskPage.8964184a8b', 'Refresh Linear')}
+
- {linearMode === "issues" ? (
+ {linearMode === 'issues' ? (
@@ -6977,13 +7291,19 @@ export default function TaskPage(): React.JSX.Element {
setLinearRefreshNonce((n) => n + 1)
}
}}
- placeholder={translate("auto.components.TaskPage.eec0c5c079", "Search Linear issues...")}
+ placeholder={translate(
+ 'auto.components.TaskPage.eec0c5c079',
+ 'Search Linear issues...'
+ )}
className="h-8 rounded-md border-border/50 bg-background pl-8 pr-8 text-xs"
/>
{linearSearchInput ? (
{
setLinearSearchInput('')
setAppliedLinearSearch('')
@@ -6997,20 +7317,26 @@ export default function TaskPage(): React.JSX.Element {
) : null}
- ) : linearMode === "projects" && !selectedLinearProject ? (
+ ) : linearMode === 'projects' && !selectedLinearProject ? (
- ) : taskSource === "jira" && jiraStatus.connected ? (
+ ) : taskSource === 'jira' && jiraStatus.connected ? (
@@ -7076,7 +7402,10 @@ export default function TaskPage(): React.JSX.Element {
disabled={
sortedAvailableJiraProjects.length === 0 || jiraProjectsLoading
}
- aria-label={translate("auto.components.TaskPage.0c11ca0b6d", "New Jira issue")}
+ aria-label={translate(
+ 'auto.components.TaskPage.0c11ca0b6d',
+ 'New Jira issue'
+ )}
className="border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md supports-[backdrop-filter]:bg-transparent"
>
{jiraProjectsLoading ? (
@@ -7087,7 +7416,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.0c11ca0b6d", "New Jira issue")}
+ {translate('auto.components.TaskPage.0c11ca0b6d', 'New Jira issue')}
+
@@ -7096,7 +7426,10 @@ export default function TaskPage(): React.JSX.Element {
size="icon"
onClick={() => setJiraRefreshNonce((n) => n + 1)}
disabled={jiraLoading}
- aria-label={translate("auto.components.TaskPage.2ff9fd71fd", "Refresh Jira issues")}
+ aria-label={translate(
+ 'auto.components.TaskPage.2ff9fd71fd',
+ 'Refresh Jira issues'
+ )}
className="border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md supports-[backdrop-filter]:bg-transparent"
>
{jiraLoading ? (
@@ -7107,7 +7440,11 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.2ff9fd71fd", "Refresh Jira issues")}
+ {translate(
+ 'auto.components.TaskPage.2ff9fd71fd',
+ 'Refresh Jira issues'
+ )}
+
@@ -7135,13 +7472,19 @@ export default function TaskPage(): React.JSX.Element {
setJiraRefreshNonce((n) => n + 1)
}
}}
- placeholder={translate("auto.components.TaskPage.99c2755218", "Jira JQL, e.g. project = ABC AND statusCategory != Done")}
+ placeholder={translate(
+ 'auto.components.TaskPage.99c2755218',
+ 'Jira JQL, e.g. project = ABC AND statusCategory != Done'
+ )}
className="h-8 rounded-md border-border/50 bg-background pl-8 pr-8 text-xs"
/>
{jiraSearchInput ? (
{
setJiraSearchInput('')
setAppliedJiraSearch('')
@@ -7156,7 +7499,7 @@ export default function TaskPage(): React.JSX.Element {
- ) : taskSource === "gitlab" ? (
+ ) : taskSource === 'gitlab' ? (
<>
@@ -7188,14 +7531,24 @@ export default function TaskPage(): React.JSX.Element {
onChange={(next) => {
setRepoSelection(next)
void updateSettings({ defaultRepoSelection: [...next] }).catch(() => {
- toast.error(translate("auto.components.TaskPage.dfd72673e7", "Failed to save project selection."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.dfd72673e7',
+ 'Failed to save project selection.'
+ )
+ )
})
}}
onSelectAll={() => {
const allIds = new Set(eligibleRepos.map((r) => r.id))
setRepoSelection(allIds)
void updateSettings({ defaultRepoSelection: null }).catch(() => {
- toast.error(translate("auto.components.TaskPage.dfd72673e7", "Failed to save project selection."))
+ toast.error(
+ translate(
+ 'auto.components.TaskPage.dfd72673e7',
+ 'Failed to save project selection.'
+ )
+ )
})
}}
triggerClassName="h-8 w-full rounded-md border border-border/50 bg-muted/50 px-2 text-xs font-medium shadow-sm transition hover:bg-muted/50 focus:ring-2 focus:ring-ring/20 focus:outline-none"
@@ -7209,7 +7562,7 @@ export default function TaskPage(): React.JSX.Element {
- {gitlabView === "issues" || gitlabView === "mrs"
+ {gitlabView === 'issues' || gitlabView === 'mrs'
? (gitlabView === 'issues'
? GITLAB_ISSUE_FILTERS
: GITLAB_MR_FILTERS
@@ -7249,9 +7602,15 @@ export default function TaskPage(): React.JSX.Element {
onClick={() => setGitlabRefreshNonce((n) => n + 1)}
disabled={gitlabLoading || gitlabTodosLoading}
aria-label={
- gitlabView === "todos"
- ? translate("auto.components.TaskPage.c679af7ad9", "Refresh My Todos")
- : translate("auto.components.TaskPage.d4c2830063", "Refresh GitLab work items")
+ gitlabView === 'todos'
+ ? translate(
+ 'auto.components.TaskPage.c679af7ad9',
+ 'Refresh My Todos'
+ )
+ : translate(
+ 'auto.components.TaskPage.d4c2830063',
+ 'Refresh GitLab work items'
+ )
}
className="border-border/50 bg-transparent hover:bg-muted/50 backdrop-blur-md supports-[backdrop-filter]:bg-transparent"
>
@@ -7263,9 +7622,15 @@ export default function TaskPage(): React.JSX.Element {
- {gitlabView === "todos"
- ? translate("auto.components.TaskPage.c679af7ad9", "Refresh My Todos")
- : translate("auto.components.TaskPage.d4c2830063", "Refresh GitLab work items")}
+ {gitlabView === 'todos'
+ ? translate(
+ 'auto.components.TaskPage.c679af7ad9',
+ 'Refresh My Todos'
+ )
+ : translate(
+ 'auto.components.TaskPage.d4c2830063',
+ 'Refresh GitLab work items'
+ )}
@@ -7277,7 +7642,7 @@ export default function TaskPage(): React.JSX.Element {
- {taskSource === "github" && dialogWorkItem ? (
+ {taskSource === 'github' && dialogWorkItem ? (
dialogWorkItem.type === 'pr' ? (
)
- ) : taskSource === "github" && githubMode === "project" ? (
+ ) : taskSource === 'github' && githubMode === 'project' ? (
- ) : taskSource === "github" ? (
+ ) : taskSource === 'github' ? (
- {translate("auto.components.TaskPage.eb10c32872", "ID")}
- {translate("auto.components.TaskPage.5eccb3c841", "Title / Context")}
- {activeGithubTaskKind === "issues" ? {translate("auto.components.TaskPage.8aba10579d", "Assignees")} : null}
+
+ {translate('auto.components.TaskPage.eb10c32872', 'ID')}
+
+
+ {translate('auto.components.TaskPage.5eccb3c841', 'Title / Context')}
+
+ {activeGithubTaskKind === 'issues' ? (
+ {translate('auto.components.TaskPage.8aba10579d', 'Assignees')}
+ ) : null}
{showPRManagementColumns ? (
<>
- {translate("auto.components.TaskPage.f6fa3c97d0", "Reviewers")}
- {translate("auto.components.TaskPage.a7396b05c6", "Checks")}
- {translate("auto.components.TaskPage.443f7dd928", "Merge")}
+ {translate('auto.components.TaskPage.f6fa3c97d0', 'Reviewers')}
+ {translate('auto.components.TaskPage.a7396b05c6', 'Checks')}
+ {translate('auto.components.TaskPage.443f7dd928', 'Merge')}
>
) : (
- {translate("auto.components.TaskPage.154b0fa623", "Status")}
+ {translate('auto.components.TaskPage.154b0fa623', 'Status')}
)}
- {translate("auto.components.TaskPage.f362667d55", "Updated")}
+ {translate('auto.components.TaskPage.f362667d55', 'Updated')}
@@ -7350,7 +7721,10 @@ export default function TaskPage(): React.JSX.Element {
// Why: per-repo partial-failure signal — distinct from a hard
// IPC reject (tasksError). The two are mutually exclusive.
- {failedCount} {translate("auto.components.TaskPage.7762f4b03a", "of")}{selectedRepos.length} {translate("auto.components.TaskPage.d1766fd62d", "projects failed to load")}
+ {failedCount} {translate('auto.components.TaskPage.7762f4b03a', 'of')}
+ {selectedRepos.length}{' '}
+ {translate('auto.components.TaskPage.d1766fd62d', 'projects failed to load')}
+
) : null}
{perRepoSourceState
@@ -7375,7 +7749,10 @@ export default function TaskPage(): React.JSX.Element {
className="flex items-center justify-between gap-3 border-b border-border/50 bg-destructive/10 px-4 py-3 text-sm text-destructive"
>
- {translate("auto.components.TaskPage.0c0de0fc0e", "Couldn't load issues from")}{' '}
+ {translate(
+ 'auto.components.TaskPage.0c0de0fc0e',
+ "Couldn't load issues from"
+ )}{' '}
{err.source.owner}/{err.source.repo}
{' '}
@@ -7390,9 +7767,10 @@ export default function TaskPage(): React.JSX.Element {
{retryingRepoPaths.has(s.repoPath) ? (
- {translate("auto.components.TaskPage.5b6b2af943", "Retrying…")}
+ {translate('auto.components.TaskPage.5b6b2af943', 'Retrying…')}
+
) : (
- translate("auto.components.TaskPage.0bfbf62f75", "Retry")
+ translate('auto.components.TaskPage.0bfbf62f75', 'Retry')
)}
@@ -7459,9 +7837,15 @@ export default function TaskPage(): React.JSX.Element {
failedCount === 0 &&
perRepoSourceState.every((s) => !s.error) ? (
-
{translate("auto.components.TaskPage.d0e3c8f933", "No matching GitHub work")}
+
+ {translate('auto.components.TaskPage.d0e3c8f933', 'No matching GitHub work')}
+
- {translate("auto.components.TaskPage.285bc21dc5", "Change the query or clear it.")}
+ {translate(
+ 'auto.components.TaskPage.285bc21dc5',
+ 'Change the query or clear it.'
+ )}
+
) : null}
@@ -7533,9 +7917,10 @@ export default function TaskPage(): React.JSX.Element {
{item.title}
- {item.type === 'pr' && item.state === "draft" ? (
+ {item.type === 'pr' && item.state === 'draft' ? (
- {translate("auto.components.TaskPage.054bf695cc", "Draft")}
+ {translate('auto.components.TaskPage.054bf695cc', 'Draft')}
+
) : null}
{selectedRepos.length > 1 && itemRepo ? (
// Why: disambiguate rows when multiple repos are in
@@ -7549,7 +7934,13 @@ export default function TaskPage(): React.JSX.Element {
) : null}
-
{item.author ?? translate("auto.components.TaskPage.6430594b18", "unknown author")}
+
+ {item.author ??
+ translate(
+ 'auto.components.TaskPage.6430594b18',
+ 'unknown author'
+ )}
+
{selectedRepos.length === 1 && itemRepo ? (
{itemRepo.displayName}
) : null}
@@ -7640,11 +8031,19 @@ export default function TaskPage(): React.JSX.Element {
)}
aria-label={
attachedWorkspace
- ? translate("auto.components.TaskPage.67d881244c", "Resume workspace attached to PR")
- : translate("auto.components.TaskPage.e4b29c5bcf", "Start workspace from PR")
+ ? translate(
+ 'auto.components.TaskPage.67d881244c',
+ 'Resume workspace attached to PR'
+ )
+ : translate(
+ 'auto.components.TaskPage.e4b29c5bcf',
+ 'Start workspace from PR'
+ )
}
>
- {attachedWorkspace ? translate("auto.components.TaskPage.7753652524", "Resume") : translate("auto.components.TaskPage.7d08e8be0f", "Start")}
+ {attachedWorkspace
+ ? translate('auto.components.TaskPage.7753652524', 'Resume')
+ : translate('auto.components.TaskPage.7d08e8be0f', 'Start')}
@@ -7656,7 +8055,10 @@ export default function TaskPage(): React.JSX.Element {
className={cn(
attachedWorkspace ? 'shadow-xs' : 'bg-background/80'
)}
- aria-label={translate("auto.components.TaskPage.7deb9e59a5", "More PR actions")}
+ aria-label={translate(
+ 'auto.components.TaskPage.7deb9e59a5',
+ 'More PR actions'
+ )}
>
@@ -7669,13 +8071,21 @@ export default function TaskPage(): React.JSX.Element {
{attachedWorkspace ? (
handleUseWorkItem(item)}>
- {translate("auto.components.TaskPage.b6329379ca", "Start new workspace")}
+ {translate(
+ 'auto.components.TaskPage.b6329379ca',
+ 'Start new workspace'
+ )}
+
) : null}
window.api.shell.openUrl(item.url)}
>
- {translate("auto.components.TaskPage.c1d1600362", "Open in browser")}
+ {translate(
+ 'auto.components.TaskPage.c1d1600362',
+ 'Open in browser'
+ )}
+
) : (
@@ -7688,12 +8098,20 @@ export default function TaskPage(): React.JSX.Element {
}}
aria-label={
attachedWorkspace
- ? translate("auto.components.TaskPage.2193a99ec1", "Open workspace attached to issue")
- : translate("auto.components.TaskPage.e104fa3d3d", "Start workspace from issue")
+ ? translate(
+ 'auto.components.TaskPage.2193a99ec1',
+ 'Open workspace attached to issue'
+ )
+ : translate(
+ 'auto.components.TaskPage.e104fa3d3d',
+ 'Start workspace from issue'
+ )
}
className="inline-flex items-center gap-1 rounded-md border border-border/50 bg-background/80 px-2 py-1 text-[11px] text-foreground transition hover:bg-muted/60"
>
- {attachedWorkspace ? translate("auto.components.TaskPage.606a85c774", "Open") : translate("auto.components.TaskPage.7d08e8be0f", "Start")}
+ {attachedWorkspace
+ ? translate('auto.components.TaskPage.606a85c774', 'Open')
+ : translate('auto.components.TaskPage.7d08e8be0f', 'Start')}
)}
@@ -7704,7 +8122,10 @@ export default function TaskPage(): React.JSX.Element {
type="button"
onClick={(e) => e.stopPropagation()}
className="rounded-lg p-1.5 text-muted-foreground transition hover:bg-muted/60 hover:text-foreground"
- aria-label={translate("auto.components.TaskPage.66ae7330f6", "More actions")}
+ aria-label={translate(
+ 'auto.components.TaskPage.66ae7330f6',
+ 'More actions'
+ )}
>
@@ -7716,13 +8137,21 @@ export default function TaskPage(): React.JSX.Element {
{attachedWorkspace ? (
handleUseWorkItem(item)}>
- {translate("auto.components.TaskPage.b6329379ca", "Start new workspace")}
+ {translate(
+ 'auto.components.TaskPage.b6329379ca',
+ 'Start new workspace'
+ )}
+
) : null}
window.api.shell.openUrl(item.url)}
>
- {translate("auto.components.TaskPage.c1d1600362", "Open in browser")}
+ {translate(
+ 'auto.components.TaskPage.c1d1600362',
+ 'Open in browser'
+ )}
+
) : null}
@@ -7753,13 +8182,13 @@ export default function TaskPage(): React.JSX.Element {
) : null}
- ) : taskSource === "gitlab" && gitlabView === "todos" ? (
+ ) : taskSource === 'gitlab' && gitlabView === 'todos' ? (
- {translate("auto.components.TaskPage.8396825a14", "Action")}
- {translate("auto.components.TaskPage.16cba35bee", "Title")}
- {translate("auto.components.TaskPage.00022ec0ba", "Project")}
- {translate("auto.components.TaskPage.f362667d55", "Updated")}
+ {translate('auto.components.TaskPage.8396825a14', 'Action')}
+ {translate('auto.components.TaskPage.16cba35bee', 'Title')}
+ {translate('auto.components.TaskPage.00022ec0ba', 'Project')}
+ {translate('auto.components.TaskPage.f362667d55', 'Updated')}
{primaryRepo
- ? translate("auto.components.TaskPage.d591aac6ae", "No pending todos. You’re all caught up!")
- : translate("auto.components.TaskPage.03da966159", "Select a project so we can authenticate to GitLab.")}
+ ? translate(
+ 'auto.components.TaskPage.d591aac6ae',
+ 'No pending todos. You’re all caught up!'
+ )
+ : translate(
+ 'auto.components.TaskPage.03da966159',
+ 'Select a project so we can authenticate to GitLab.'
+ )}
) : null}
@@ -7806,10 +8241,16 @@ export default function TaskPage(): React.JSX.Element {
}}
className="grid w-full cursor-pointer gap-3 px-3 py-2 text-left grid-cols-[110px_minmax(0,3fr)_minmax(120px,1.2fr)_110px_50px] hover:bg-muted/50"
title={
- todo.targetType === "MergeRequest"
- ? translate("auto.components.TaskPage.a0544fb653", "MR !{{value0}}", { value0: todo.targetIid ?? '' })
- : todo.targetType === "Issue"
- ? translate("auto.components.TaskPage.e9b6955dcd", "Issue #{{value0}}", { value0: todo.targetIid ?? '' })
+ todo.targetType === 'MergeRequest'
+ ? translate('auto.components.TaskPage.a0544fb653', 'MR !{{value0}}', {
+ value0: todo.targetIid ?? ''
+ })
+ : todo.targetType === 'Issue'
+ ? translate(
+ 'auto.components.TaskPage.e9b6955dcd',
+ 'Issue #{{value0}}',
+ { value0: todo.targetIid ?? '' }
+ )
: todo.targetType
}
>
@@ -7834,13 +8275,13 @@ export default function TaskPage(): React.JSX.Element {
- ) : taskSource === "gitlab" ? (
+ ) : taskSource === 'gitlab' ? (
- {translate("auto.components.TaskPage.eb10c32872", "ID")}
- {translate("auto.components.TaskPage.16cba35bee", "Title")}
- {translate("auto.components.TaskPage.00b7ffb952", "Type / State")}
- {translate("auto.components.TaskPage.f362667d55", "Updated")}
+ {translate('auto.components.TaskPage.eb10c32872', 'ID')}
+ {translate('auto.components.TaskPage.16cba35bee', 'Title')}
+ {translate('auto.components.TaskPage.00b7ffb952', 'Type / State')}
+ {translate('auto.components.TaskPage.f362667d55', 'Updated')}
{primaryRepo
- ? gitlabView === "issues"
- ? translate("auto.components.TaskPage.a9f256ecea", "No GitLab issues match this filter.")
- : gitlabView === "mrs"
- ? translate("auto.components.TaskPage.cd7dc432a3", "No GitLab MRs match this filter.")
- : translate("auto.components.TaskPage.f294c500ef", "No GitLab work matches this filter.")
- : translate("auto.components.TaskPage.d6d08c1650", "Select a project to see GitLab work items.")}
+ ? gitlabView === 'issues'
+ ? translate(
+ 'auto.components.TaskPage.a9f256ecea',
+ 'No GitLab issues match this filter.'
+ )
+ : gitlabView === 'mrs'
+ ? translate(
+ 'auto.components.TaskPage.cd7dc432a3',
+ 'No GitLab MRs match this filter.'
+ )
+ : translate(
+ 'auto.components.TaskPage.f294c500ef',
+ 'No GitLab work matches this filter.'
+ )
+ : translate(
+ 'auto.components.TaskPage.d6d08c1650',
+ 'Select a project to see GitLab work items.'
+ )}
) : null}
@@ -7909,12 +8362,15 @@ export default function TaskPage(): React.JSX.Element {
{/* Why: GitLab's user-facing convention is `!N` for MRs
and `#N` for issues — matches gitlab.com's UI so users
scanning the list can map rows back to web links. */}
- {item.type === "mr" ? '!' : '#'}
+ {item.type === 'mr' ? '!' : '#'}
{item.number}
{item.title}
- {item.type === "mr" ? translate("auto.components.TaskPage.e224d76876", "MR") : translate("auto.components.TaskPage.b1eaa18ace", "Issue")} · {item.state}
+ {item.type === 'mr'
+ ? translate('auto.components.TaskPage.e224d76876', 'MR')
+ : translate('auto.components.TaskPage.b1eaa18ace', 'Issue')}{' '}
+ · {item.state}
{item.updatedAt ? new Date(item.updatedAt).toLocaleDateString() : ''}
@@ -7930,13 +8386,18 @@ export default function TaskPage(): React.JSX.Element {
event.stopPropagation()
handleUseGitLabItem(item)
}}
- aria-label={translate("auto.components.TaskPage.5e8061b088", "Start workspace from {{value0}} {{value1}}", { value0: item.type === 'mr' ? 'MR' : 'issue', value1: item.number })}
+ aria-label={translate(
+ 'auto.components.TaskPage.5e8061b088',
+ 'Start workspace from {{value0}} {{value1}}',
+ { value0: item.type === 'mr' ? 'MR' : 'issue', value1: item.number }
+ )}
>
- {translate("auto.components.TaskPage.9497f2787c", "Start workspace")}
+ {translate('auto.components.TaskPage.9497f2787c', 'Start workspace')}
+
@@ -7955,7 +8419,7 @@ export default function TaskPage(): React.JSX.Element {
- ) : taskSource === "jira" ? (
+ ) : taskSource === 'jira' ? (
!jiraStatusChecked ? (
@@ -7963,9 +8427,15 @@ export default function TaskPage(): React.JSX.Element {
) : !jiraStatus.connected ? (
-
{translate("auto.components.TaskPage.a150c59da7", "Connect your Jira site")}
+
+ {translate('auto.components.TaskPage.a150c59da7', 'Connect your Jira site')}
+
- {translate("auto.components.TaskPage.b518ae6307", "Browse, edit, create, and start work from Jira issues directly from here.")}
+ {translate(
+ 'auto.components.TaskPage.b518ae6307',
+ 'Browse, edit, create, and start work from Jira issues directly from here.'
+ )}
+
{
@@ -7977,27 +8447,34 @@ export default function TaskPage(): React.JSX.Element {
setJiraConnectOpen(true)
}}
>
- {translate("auto.components.TaskPage.83bce6be5c", "Connect Jira")}
+ {translate('auto.components.TaskPage.83bce6be5c', 'Connect Jira')}
+
hideTaskSource('jira', 'Jira')}>
- {translate("auto.components.TaskPage.e7115334aa", "Hide Jira")}
+ {translate('auto.components.TaskPage.e7115334aa', 'Hide Jira')}
+
) : (
- {translate("auto.components.TaskPage.63b2abd3aa", "Jira issues")}
+ {translate('auto.components.TaskPage.63b2abd3aa', 'Jira issues')}
+
- {displayedJiraIssues.length} {translate("auto.components.TaskPage.b7bae28b6a", "shown")}
+ {displayedJiraIssues.length}{' '}
+ {translate('auto.components.TaskPage.b7bae28b6a', 'shown')}
+
- {translate("auto.components.TaskPage.37e7ee311e", "Key")}
- {translate("auto.components.TaskPage.b1eaa18ace", "Issue")}
- {translate("auto.components.TaskPage.154b0fa623", "Status")}
- {translate("auto.components.TaskPage.c8d5bec5f7", "Priority")}
- {translate("auto.components.TaskPage.d2a876ca53", "Assignee")}
- {translate("auto.components.TaskPage.f362667d55", "Updated")}
+ {translate('auto.components.TaskPage.37e7ee311e', 'Key')}
+ {translate('auto.components.TaskPage.b1eaa18ace', 'Issue')}
+ {translate('auto.components.TaskPage.154b0fa623', 'Status')}
+ {translate('auto.components.TaskPage.c8d5bec5f7', 'Priority')}
+
+ {translate('auto.components.TaskPage.d2a876ca53', 'Assignee')}
+
+ {translate('auto.components.TaskPage.f362667d55', 'Updated')}
@@ -8024,11 +8501,19 @@ export default function TaskPage(): React.JSX.Element {
{!jiraLoading && jiraIssues.length === 0 && !jiraError ? (
-
{translate("auto.components.TaskPage.eba87f2edb", "No Jira issues found")}
+
+ {translate('auto.components.TaskPage.eba87f2edb', 'No Jira issues found')}
+
{jiraSearchInput
- ? translate("auto.components.TaskPage.f51e254d35", "Try a different JQL query.")
- : translate("auto.components.TaskPage.94d900518d", "No issues match the selected preset.")}
+ ? translate(
+ 'auto.components.TaskPage.f51e254d35',
+ 'Try a different JQL query.'
+ )
+ : translate(
+ 'auto.components.TaskPage.94d900518d',
+ 'No issues match the selected preset.'
+ )}
) : null}
@@ -8086,10 +8571,12 @@ export default function TaskPage(): React.JSX.Element {
{issue.status.name}
- {issue.priority?.name ?? translate("auto.components.TaskPage.713179dfdc", "No priority")}
+ {issue.priority?.name ??
+ translate('auto.components.TaskPage.713179dfdc', 'No priority')}
- {issue.assignee?.displayName ?? translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+ {issue.assignee?.displayName ??
+ translate('auto.components.TaskPage.42a9160321', 'Unassigned')}
@@ -8124,7 +8611,8 @@ export default function TaskPage(): React.JSX.Element {
- {issue.priority?.name ?? translate("auto.components.TaskPage.713179dfdc", "No priority")}
+ {issue.priority?.name ??
+ translate('auto.components.TaskPage.713179dfdc', 'No priority')}
@@ -8140,7 +8628,8 @@ export default function TaskPage(): React.JSX.Element {
)}
- {issue.assignee?.displayName ?? translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+ {issue.assignee?.displayName ??
+ translate('auto.components.TaskPage.42a9160321', 'Unassigned')}
@@ -8165,13 +8654,21 @@ export default function TaskPage(): React.JSX.Element {
event.stopPropagation()
handleUseJiraItem(issue)
}}
- aria-label={translate("auto.components.TaskPage.5e8061b088", "Start workspace from {{value0}}", { value0: issue.key })}
+ aria-label={translate(
+ 'auto.components.TaskPage.ff90d0abc7',
+ 'Start workspace from {{value0}}',
+ { value0: issue.key }
+ )}
>
- {translate("auto.components.TaskPage.9497f2787c", "Start workspace")}
+ {translate(
+ 'auto.components.TaskPage.9497f2787c',
+ 'Start workspace'
+ )}
+
@@ -8182,13 +8679,18 @@ export default function TaskPage(): React.JSX.Element {
event.stopPropagation()
window.api.shell.openUrl(issue.url)
}}
- aria-label={translate("auto.components.TaskPage.606a85c774", "Open {{value0}} in Jira", { value0: issue.key })}
+ aria-label={translate(
+ 'auto.components.TaskPage.4ac8ff2275',
+ 'Open {{value0}} in Jira',
+ { value0: issue.key }
+ )}
>
- {translate("auto.components.TaskPage.eee68073b2", "Open in Jira")}
+ {translate('auto.components.TaskPage.eee68073b2', 'Open in Jira')}
+
@@ -8203,7 +8705,7 @@ export default function TaskPage(): React.JSX.Element {
/>
)
- ) : taskSource === "linear" && selectedLinearIssue ? (
+ ) : taskSource === 'linear' && selectedLinearIssue ? (
- {translate("auto.components.TaskPage.6d56559467", "Connect your Linear account")}
+
+ {translate('auto.components.TaskPage.6d56559467', 'Connect your Linear account')}
+
- {translate("auto.components.TaskPage.228b25028f", "Browse and start work on your assigned Linear issues directly from here.")}
+ {translate(
+ 'auto.components.TaskPage.228b25028f',
+ 'Browse and start work on your assigned Linear issues directly from here.'
+ )}
+
{
setLinearConnectOpen(true)
}}
>
- {translate("auto.components.TaskPage.851017590d", "Add Linear access")}
+ {translate('auto.components.TaskPage.851017590d', 'Add Linear access')}
+
- ) : selectedLinearProject && linearProjectTab === "overview" ? (
+ ) : selectedLinearProject && linearProjectTab === 'overview' ? (
setLinearProjectTab('issues')}
/>
- ) : linearMode === "projects" && !selectedLinearProject ? (
+ ) : linearMode === 'projects' && !selectedLinearProject ? (
- {translate("auto.components.TaskPage.00022ec0ba", "Project")}
- {translate("auto.components.TaskPage.154b0fa623", "Status")}
- {translate("auto.components.TaskPage.8a07f21e76", "Health")}
- {translate("auto.components.TaskPage.c8d5bec5f7", "Priority")}
- {translate("auto.components.TaskPage.34da8ac06c", "Lead")}
- {translate("auto.components.TaskPage.7da41c9225", "Target")}
- {translate("auto.components.TaskPage.dfc0c79bd8", "Issues")}
+ {translate('auto.components.TaskPage.00022ec0ba', 'Project')}
+ {translate('auto.components.TaskPage.154b0fa623', 'Status')}
+ {translate('auto.components.TaskPage.8a07f21e76', 'Health')}
+ {translate('auto.components.TaskPage.c8d5bec5f7', 'Priority')}
+ {translate('auto.components.TaskPage.34da8ac06c', 'Lead')}
+ {translate('auto.components.TaskPage.7da41c9225', 'Target')}
+ {translate('auto.components.TaskPage.dfc0c79bd8', 'Issues')}
@@ -8316,17 +8825,17 @@ export default function TaskPage(): React.JSX.Element {
errors={linearProjectsResult.errors}
hasMore={linearProjectsResult.hasMore}
count={linearProjectsResult.items.length}
- label={translate("auto.components.TaskPage.b39fe6511d", "projects")}
+ label={translate('auto.components.TaskPage.b39fe6511d', 'projects')}
/>
- ) : linearMode === "views" && !selectedLinearCustomView ? (
+ ) : linearMode === 'views' && !selectedLinearCustomView ? (
- {translate("auto.components.TaskPage.9c57663908", "View")}
- {translate("auto.components.TaskPage.0aa8525950", "Model")}
- {translate("auto.components.TaskPage.a04fe7ba73", "Visibility")}
- {translate("auto.components.TaskPage.b4e10f096e", "Owner")}
- {translate("auto.components.TaskPage.f362667d55", "Updated")}
+ {translate('auto.components.TaskPage.9c57663908', 'View')}
+ {translate('auto.components.TaskPage.0aa8525950', 'Model')}
+ {translate('auto.components.TaskPage.a04fe7ba73', 'Visibility')}
+ {translate('auto.components.TaskPage.b4e10f096e', 'Owner')}
+ {translate('auto.components.TaskPage.f362667d55', 'Updated')}
@@ -8352,10 +8861,10 @@ export default function TaskPage(): React.JSX.Element {
errors={linearCustomViewsResult.errors}
hasMore={linearCustomViewsResult.hasMore}
count={linearCustomViewsResult.items.length}
- label={translate("auto.components.TaskPage.3cb855080f", "views")}
+ label={translate('auto.components.TaskPage.3cb855080f', 'views')}
/>
- ) : selectedLinearCustomView?.model === "project" && !selectedLinearProject ? (
+ ) : selectedLinearCustomView?.model === 'project' && !selectedLinearProject ? (
@@ -8367,7 +8876,7 @@ export default function TaskPage(): React.JSX.Element {
setLinearProjectParentView(null)
setTaskResumeState({ linearContext: undefined })
}}
- aria-label={translate("auto.components.TaskPage.bc06ed0fb0", "Back to views")}
+ aria-label={translate('auto.components.TaskPage.bc06ed0fb0', 'Back to views')}
>
@@ -8375,7 +8884,9 @@ export default function TaskPage(): React.JSX.Element {
{selectedLinearCustomView.name}
-
{translate("auto.components.TaskPage.733b8f2421", "Linear / Views")}
+
+ {translate('auto.components.TaskPage.733b8f2421', 'Linear / Views')}
+
{selectedLinearCustomView.url ? (
@@ -8386,7 +8897,8 @@ export default function TaskPage(): React.JSX.Element {
className="gap-1 border-border/50 bg-background/70"
>
- {translate("auto.components.TaskPage.8675cd6188", "Linear")}
+ {translate('auto.components.TaskPage.8675cd6188', 'Linear')}
+
) : null}
@@ -8418,7 +8930,7 @@ export default function TaskPage(): React.JSX.Element {
errors={linearCustomViewProjectsResult.errors}
hasMore={linearCustomViewProjectsResult.hasMore}
count={linearCustomViewProjectsResult.items.length}
- label={translate("auto.components.TaskPage.b39fe6511d", "projects")}
+ label={translate('auto.components.TaskPage.b39fe6511d', 'projects')}
/>
) : (
@@ -8438,19 +8950,23 @@ export default function TaskPage(): React.JSX.Element {
setLinearProjectParentView(null)
setTaskResumeState({ linearContext: undefined })
}}
- aria-label={translate("auto.components.TaskPage.f397d513e3", "Back")}
+ aria-label={translate('auto.components.TaskPage.f397d513e3', 'Back')}
>
) : null}
- {activeLinearIssueContextLabel ?? translate("auto.components.TaskPage.60f68a2ef4", "Linear issues")}
+ {activeLinearIssueContextLabel ??
+ translate('auto.components.TaskPage.60f68a2ef4', 'Linear issues')}
{LINEAR_VIEW_OPTIONS.map(({ id, label, Icon }) => {
const active = linearViewMode === id
@@ -8460,7 +8976,11 @@ export default function TaskPage(): React.JSX.Element {
setLinearViewMode(id)}
- aria-label={translate("auto.components.TaskPage.af377b13b1", "{{value0}} view", { value0: label })}
+ aria-label={translate(
+ 'auto.components.TaskPage.af377b13b1',
+ '{{value0}} view',
+ { value0: label }
+ )}
aria-pressed={active}
className={cn(
'inline-flex size-6 items-center justify-center rounded text-muted-foreground transition hover:text-foreground',
@@ -8471,7 +8991,10 @@ export default function TaskPage(): React.JSX.Element {
- {label} {translate("auto.components.TaskPage.af377b13b1", "view")}
+ {translate('auto.components.TaskPage.af377b13b1', '{{value0}} view', {
+ value0: label
+ })}
+
)
})}
@@ -8484,12 +9007,14 @@ export default function TaskPage(): React.JSX.Element {
className="gap-1 border-border/50 bg-background/70 text-[11px]"
>
- {translate("auto.components.TaskPage.9c57663908", "View")}
+ {translate('auto.components.TaskPage.9c57663908', 'View')}
+
- {translate("auto.components.TaskPage.9c57663908", "View")}
+ {translate('auto.components.TaskPage.9c57663908', 'View')}
+
setLinearViewMode(value as LinearViewMode)}
@@ -8504,7 +9029,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.5659da12fc", "Grouping")}
+ {translate('auto.components.TaskPage.5659da12fc', 'Grouping')}
+
setLinearGroupBy(value as LinearGroupBy)}
@@ -8518,7 +9044,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.5d2d835467", "Ordering")}
+ {translate('auto.components.TaskPage.5d2d835467', 'Ordering')}
+
setLinearOrderBy(value as LinearOrderBy)}
@@ -8532,7 +9059,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.a26a48252e", "Display properties")}
+ {translate('auto.components.TaskPage.a26a48252e', 'Display properties')}
+
{LINEAR_DISPLAY_PROPERTIES.map((property) => (
- {pagedLinearIssues.length} {translate("auto.components.TaskPage.b7bae28b6a", "shown")}
+ {pagedLinearIssues.length}{' '}
+ {translate('auto.components.TaskPage.b7bae28b6a', 'shown')}
+
- {linearViewMode === "list" && linearGroupBy === "none" ? (
+ {linearViewMode === 'list' && linearGroupBy === 'none' ? (
- {translate("auto.components.TaskPage.37e7ee311e", "Key")}
- {translate("auto.components.TaskPage.b1eaa18ace", "Issue")}
- {effectiveLinearDisplayProperties.has('labels') ? {translate("auto.components.TaskPage.d0ca4aa1d0", "Labels")} : null}
- {effectiveLinearDisplayProperties.has('team') ? {translate("auto.components.TaskPage.a98cbe7664", "Team")} : null}
- {effectiveLinearDisplayProperties.has('state') ? {translate("auto.components.TaskPage.154b0fa623", "Status")} : null}
+ {translate('auto.components.TaskPage.37e7ee311e', 'Key')}
+ {translate('auto.components.TaskPage.b1eaa18ace', 'Issue')}
+ {effectiveLinearDisplayProperties.has('labels') ? (
+ {translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels')}
+ ) : null}
+ {effectiveLinearDisplayProperties.has('team') ? (
+ {translate('auto.components.TaskPage.a98cbe7664', 'Team')}
+ ) : null}
+ {effectiveLinearDisplayProperties.has('state') ? (
+ {translate('auto.components.TaskPage.154b0fa623', 'Status')}
+ ) : null}
{effectiveLinearDisplayProperties.has('assignee') ? (
- {translate("auto.components.TaskPage.d2a876ca53", "Assignee")}
+
+ {translate('auto.components.TaskPage.d2a876ca53', 'Assignee')}
+
+ ) : null}
+ {effectiveLinearDisplayProperties.has('updated') ? (
+ {translate('auto.components.TaskPage.f362667d55', 'Updated')}
) : null}
- {effectiveLinearDisplayProperties.has('updated') ? {translate("auto.components.TaskPage.f362667d55", "Updated")} : null}
) : null}
@@ -8595,9 +9135,17 @@ export default function TaskPage(): React.JSX.Element {
activeLinearIssueHasCollectionError ? (
- {translate("auto.components.TaskPage.cc8795e07c", "Unable to load Linear issues")}
+ {translate(
+ 'auto.components.TaskPage.cc8795e07c',
+ 'Unable to load Linear issues'
+ )}
+
- {translate("auto.components.TaskPage.5ed38a49e5", "Review the workspace error below, then refresh.")}
+ {translate(
+ 'auto.components.TaskPage.5ed38a49e5',
+ 'Review the workspace error below, then refresh.'
+ )}
+
) : null}
@@ -8606,13 +9154,24 @@ export default function TaskPage(): React.JSX.Element {
!activeLinearIssueError &&
!activeLinearIssueHasCollectionError ? (
-
{translate("auto.components.TaskPage.903c7af49f", "No Linear issues found")}
+
+ {translate('auto.components.TaskPage.903c7af49f', 'No Linear issues found')}
+
{activeLinearIssueContextLabel
- ? translate("auto.components.TaskPage.25ff84769a", "No issues match this Linear context.")
+ ? translate(
+ 'auto.components.TaskPage.25ff84769a',
+ 'No issues match this Linear context.'
+ )
: linearSearchInput
- ? translate("auto.components.TaskPage.2bdefbcac3", "Try a different search query.")
- : translate("auto.components.TaskPage.d079be2dc8", "No assigned issues. Try searching for something.")}
+ ? translate(
+ 'auto.components.TaskPage.2bdefbcac3',
+ 'Try a different search query.'
+ )
+ : translate(
+ 'auto.components.TaskPage.d079be2dc8',
+ 'No assigned issues. Try searching for something.'
+ )}
) : null}
@@ -8622,13 +9181,21 @@ export default function TaskPage(): React.JSX.Element {
filteredLinearIssues.length === 0 ? (
- {translate("auto.components.TaskPage.618107fab3", "No fetched issues match the selected teams")}
+ {translate(
+ 'auto.components.TaskPage.618107fab3',
+ 'No fetched issues match the selected teams'
+ )}
+
- {translate("auto.components.TaskPage.592a55611b", "Try selecting more teams or refreshing; team filters apply to the current fetched issue set.")}
+ {translate(
+ 'auto.components.TaskPage.592a55611b',
+ 'Try selecting more teams or refreshing; team filters apply to the current fetched issue set.'
+ )}
+
) : null}
- {linearViewMode === "board" ? (
+ {linearViewMode === 'board' ? (
{linearBoardSections.map((section) => (
@@ -8730,7 +9301,11 @@ export default function TaskPage(): React.JSX.Element {
event.stopPropagation()
window.api.shell.openUrl(issue.url)
}}
- aria-label={translate("auto.components.TaskPage.606a85c774", "Open {{value0}} in Linear", { value0: issue.identifier })}
+ aria-label={translate(
+ 'auto.components.TaskPage.246bd64aed',
+ 'Open {{value0}} in Linear',
+ { value0: issue.identifier }
+ )}
>
@@ -8741,7 +9316,13 @@ export default function TaskPage(): React.JSX.Element {
) : null}
{effectiveLinearDisplayProperties.has('assignee') ? (
- {issue.assignee?.displayName ?? translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+
+ {issue.assignee?.displayName ??
+ translate(
+ 'auto.components.TaskPage.42a9160321',
+ 'Unassigned'
+ )}
+
) : null}
{effectiveLinearDisplayProperties.has('team') ? (
{teamLabel}
@@ -8851,7 +9432,8 @@ export default function TaskPage(): React.JSX.Element {
) : null}
{effectiveLinearDisplayProperties.has('assignee') ? (
- {issue.assignee?.displayName ?? translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+ {issue.assignee?.displayName ??
+ translate('auto.components.TaskPage.42a9160321', 'Unassigned')}
) : null}
{effectiveLinearDisplayProperties.has('team') ? (
@@ -8898,7 +9480,10 @@ export default function TaskPage(): React.JSX.Element {
{issue.assignee?.avatarUrl ? (
- {issue.assignee?.displayName ?? translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+ {issue.assignee?.displayName ??
+ translate('auto.components.TaskPage.42a9160321', 'Unassigned')}
@@ -8942,13 +9528,18 @@ export default function TaskPage(): React.JSX.Element {
event.stopPropagation()
handleUseLinearItem(issue)
}}
- aria-label={translate("auto.components.TaskPage.5e8061b088", "Start workspace from {{value0}}", { value0: issue.identifier })}
+ aria-label={translate(
+ 'auto.components.TaskPage.ff90d0abc7',
+ 'Start workspace from {{value0}}',
+ { value0: issue.identifier }
+ )}
>
- {translate("auto.components.TaskPage.7d08e8be0f", "Start")}
+ {translate('auto.components.TaskPage.7d08e8be0f', 'Start')}
+
@@ -8959,13 +9550,18 @@ export default function TaskPage(): React.JSX.Element {
event.stopPropagation()
window.api.shell.openUrl(issue.url)
}}
- aria-label={translate("auto.components.TaskPage.606a85c774", "Open {{value0}} in Linear", { value0: issue.identifier })}
+ aria-label={translate(
+ 'auto.components.TaskPage.246bd64aed',
+ 'Open {{value0}} in Linear',
+ { value0: issue.identifier }
+ )}
>
- {translate("auto.components.TaskPage.6244a02f46", "Open in Linear")}
+ {translate('auto.components.TaskPage.6244a02f46', 'Open in Linear')}
+
@@ -8974,13 +9570,13 @@ export default function TaskPage(): React.JSX.Element {
)}
- {selectedLinearProject && linearProjectTab === "issues" ? (
+ {selectedLinearProject && linearProjectTab === 'issues' ? (
<>
- {translate("auto.components.TaskPage.d3d0998b7d", "New GitHub issue")}
+
+ {translate('auto.components.TaskPage.d3d0998b7d', 'New GitHub issue')}
+
{(() => {
// Why: parent design doc §1 surface 2 — the composer is the
// non-negotiable surface because User D's regression (filing a
@@ -9084,7 +9682,12 @@ export default function TaskPage(): React.JSX.Element {
? `${entry.sources.issues.owner}/${entry.sources.issues.repo}`
: null
const fallback = newIssueTargetRepo?.displayName ?? 'this repository'
- return {translate("auto.components.TaskPage.9f2b4c03a6", "Filing in")}{issuesSlug ?? fallback}
+ return (
+
+ {translate('auto.components.TaskPage.9f2b4c03a6', 'Filing in')}
+ {issuesSlug ?? fallback}
+
+ )
})()}
{(() => {
// Why: mirror the Tasks-view selector in the composer so User D
@@ -9138,7 +9741,9 @@ export default function TaskPage(): React.JSX.Element {
{selectedRepos.length > 1 ? (
- {translate("auto.components.TaskPage.00022ec0ba", "Project")}
+
+ {translate('auto.components.TaskPage.00022ec0ba', 'Project')}
+
setNewIssueRepoId(v)}
@@ -9158,7 +9763,9 @@ export default function TaskPage(): React.JSX.Element {
) : null}
- {translate("auto.components.TaskPage.16cba35bee", "Title")}
+
+ {translate('auto.components.TaskPage.16cba35bee', 'Title')}
+
- {translate("auto.components.TaskPage.7f3f7b4c18", "Description (optional, markdown)")}
+ {translate(
+ 'auto.components.TaskPage.7f3f7b4c18',
+ 'Description (optional, markdown)'
+ )}
+
void handleCreateNewIssue()}
@@ -9203,7 +9814,9 @@ export default function TaskPage(): React.JSX.Element {
onChange={setNewIssueAssignees}
/>
-
{submitShortcutLabel} {translate("auto.components.TaskPage.fc0d8a1fa4", "to submit.")}
+
+ {submitShortcutLabel} {translate('auto.components.TaskPage.fc0d8a1fa4', 'to submit.')}
+
setNewIssueOpen(false)}
disabled={newIssueSubmitting}
>
- {translate("auto.components.TaskPage.ff69a30681", "Cancel")}
+ {translate('auto.components.TaskPage.ff69a30681', 'Cancel')}
+
void handleCreateNewIssue()}
disabled={!newIssueTargetRepo || !newIssueTitle.trim() || newIssueSubmitting}
@@ -9219,9 +9833,10 @@ export default function TaskPage(): React.JSX.Element {
{newIssueSubmitting ? (
<>
- {translate("auto.components.TaskPage.8ff6fdc368", "Creating…")}>
+ {translate('auto.components.TaskPage.8ff6fdc368', 'Creating…')}
+ >
) : (
- translate("auto.components.TaskPage.e15ba2d2eb", "Create issue")
+ translate('auto.components.TaskPage.e15ba2d2eb', 'Create issue')
)}
@@ -9246,13 +9861,20 @@ export default function TaskPage(): React.JSX.Element {
}
}}
>
- {translate("auto.components.TaskPage.1361275ec3", "New Linear project")}
+
+ {translate('auto.components.TaskPage.1361275ec3', 'New Linear project')}
+
- {translate("auto.components.TaskPage.bdebffcbfe", "Create a Linear project for the selected team.")}
+ {translate(
+ 'auto.components.TaskPage.bdebffcbfe',
+ 'Create a Linear project for the selected team.'
+ )}
+
- {translate("auto.components.TaskPage.02f67c0d09", "New Project")}
+ {translate('auto.components.TaskPage.02f67c0d09', 'New Project')}
+
/
{availableTeams.length > 1 ? (
@@ -9265,14 +9887,15 @@ export default function TaskPage(): React.JSX.Element {
{newLinearProjectTargetTeam
? `${newLinearProjectTargetTeam.key} - ${newLinearProjectTargetTeam.name}`
- : translate("auto.components.TaskPage.5af6f0ae5b", "Select team")}
+ : translate('auto.components.TaskPage.5af6f0ae5b', 'Select team')}
- {translate("auto.components.TaskPage.a98cbe7664", "Team")}
+ {translate('auto.components.TaskPage.a98cbe7664', 'Team')}
+
{availableTeams.map((team) => (
setNewLinearProjectOpen(false)}
className="rounded-md p-1 text-muted-foreground transition-colors hover:text-foreground"
disabled={newLinearProjectSubmitting}
- aria-label={translate("auto.components.TaskPage.b6795e65fd", "Close")}
+ aria-label={translate('auto.components.TaskPage.b6795e65fd', 'Close')}
>
@@ -9327,7 +9950,7 @@ export default function TaskPage(): React.JSX.Element {
void handleCreateNewLinearProject()
}
}}
- placeholder={translate("auto.components.TaskPage.ecbcc83140", "Project name")}
+ placeholder={translate('auto.components.TaskPage.ecbcc83140', 'Project name')}
disabled={newLinearProjectSubmitting}
className="w-full border-none bg-transparent p-0 text-xl font-semibold text-foreground outline-none placeholder:text-muted-foreground/45 focus:outline-none focus:ring-0 focus-visible:ring-0"
/>
@@ -9335,7 +9958,10 @@ export default function TaskPage(): React.JSX.Element {
setNewLinearProjectDescription(event.target.value)}
- placeholder={translate("auto.components.TaskPage.579f98afcd", "Add a short summary...")}
+ placeholder={translate(
+ 'auto.components.TaskPage.579f98afcd',
+ 'Add a short summary...'
+ )}
disabled={newLinearProjectSubmitting}
className="w-full border-none bg-transparent p-0 text-sm text-foreground outline-none placeholder:text-muted-foreground/45 focus:outline-none focus:ring-0 focus-visible:ring-0"
/>
@@ -9355,7 +9981,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.c8d5bec5f7", "Priority")}
+ {translate('auto.components.TaskPage.c8d5bec5f7', 'Priority')}
+
{[0, 1, 2, 3, 4].map((priority) => (
{newLinearProjectMembers.data.find(
(member) => member.id === newLinearProjectLeadId
- )?.displayName ?? translate("auto.components.TaskPage.34da8ac06c", "Lead")}
+ )?.displayName ?? translate('auto.components.TaskPage.34da8ac06c', 'Lead')}
- {translate("auto.components.TaskPage.34da8ac06c", "Lead")}
+ {translate('auto.components.TaskPage.34da8ac06c', 'Lead')}
+
{newLinearProjectMembers.loading ? (
@@ -9417,7 +10045,8 @@ export default function TaskPage(): React.JSX.Element {
>
- {translate("auto.components.TaskPage.cfaadb6b22", "No lead")}
+ {translate('auto.components.TaskPage.cfaadb6b22', 'No lead')}
+
{newLinearProjectLeadId === null ?
: null}
{newLinearProjectMembers.data.map((member) => (
@@ -9464,15 +10093,23 @@ export default function TaskPage(): React.JSX.Element {
{newLinearProjectMemberIds.length === 0
- ? translate("auto.components.TaskPage.d6cda23ef1", "Members")
- : translate("auto.components.TaskPage.7719d8daa9", "{{value0}} member{{value1}}", { value0: newLinearProjectMemberIds.length, value1: newLinearProjectMemberIds.length > 1 ? 's' : '' })}
+ ? translate('auto.components.TaskPage.d6cda23ef1', 'Members')
+ : translate(
+ 'auto.components.TaskPage.7719d8daa9',
+ '{{value0}} member{{value1}}',
+ {
+ value0: newLinearProjectMemberIds.length,
+ value1: newLinearProjectMemberIds.length > 1 ? 's' : ''
+ }
+ )}
- {translate("auto.components.TaskPage.d6cda23ef1", "Members")}
+ {translate('auto.components.TaskPage.d6cda23ef1', 'Members')}
+
{newLinearProjectMembers.loading ? (
@@ -9530,15 +10167,23 @@ export default function TaskPage(): React.JSX.Element {
{newLinearProjectLabelIds.length === 0
- ? translate("auto.components.TaskPage.d0ca4aa1d0", "Labels")
- : translate("auto.components.TaskPage.eff9800d4b", "{{value0}} label{{value1}}", { value0: newLinearProjectLabelIds.length, value1: newLinearProjectLabelIds.length > 1 ? 's' : '' })}
+ ? translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels')
+ : translate(
+ 'auto.components.TaskPage.eff9800d4b',
+ '{{value0}} label{{value1}}',
+ {
+ value0: newLinearProjectLabelIds.length,
+ value1: newLinearProjectLabelIds.length > 1 ? 's' : ''
+ }
+ )}
- {translate("auto.components.TaskPage.d0ca4aa1d0", "Labels")}
+ {translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels')}
+
{newLinearProjectLabels.loading ? (
@@ -9546,7 +10191,9 @@ export default function TaskPage(): React.JSX.Element {
) : (
{newLinearProjectLabels.data.length === 0 ? (
-
{translate("auto.components.TaskPage.af9e877f30", "No labels")}
+
+ {translate('auto.components.TaskPage.af9e877f30', 'No labels')}
+
) : (
newLinearProjectLabels.data.map((label) => {
const selected = newLinearProjectLabelIds.includes(label.id)
@@ -9587,27 +10234,31 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.7d08e8be0f", "Start")}
+
+ {translate('auto.components.TaskPage.7d08e8be0f', 'Start')}
+
setNewLinearProjectStartDate(event.target.value)}
disabled={newLinearProjectSubmitting}
className="h-5 min-w-[6.75rem] cursor-pointer border-none bg-transparent p-0 text-xs text-foreground outline-none disabled:cursor-not-allowed"
- aria-label={translate("auto.components.TaskPage.09623359b9", "Start date")}
+ aria-label={translate('auto.components.TaskPage.09623359b9', 'Start date')}
/>
- {translate("auto.components.TaskPage.7da41c9225", "Target")}
+
+ {translate('auto.components.TaskPage.7da41c9225', 'Target')}
+
setNewLinearProjectTargetDate(event.target.value)}
disabled={newLinearProjectSubmitting}
className="h-5 min-w-[6.75rem] cursor-pointer border-none bg-transparent p-0 text-xs text-foreground outline-none disabled:cursor-not-allowed"
- aria-label={translate("auto.components.TaskPage.2ea1c701b6", "Target date")}
+ aria-label={translate('auto.components.TaskPage.2ea1c701b6', 'Target date')}
/>
@@ -9616,13 +10267,18 @@ export default function TaskPage(): React.JSX.Element {
- {submitShortcutLabel} {translate("auto.components.TaskPage.fc0d8a1fa4", "to submit.")}
+
+ {submitShortcutLabel} {translate('auto.components.TaskPage.fc0d8a1fa4', 'to submit.')}
+
@@ -9631,7 +10287,8 @@ export default function TaskPage(): React.JSX.Element {
onClick={() => setNewLinearProjectOpen(false)}
disabled={newLinearProjectSubmitting}
>
- {translate("auto.components.TaskPage.ff69a30681", "Cancel")}
+ {translate('auto.components.TaskPage.ff69a30681', 'Cancel')}
+
void handleCreateNewLinearProject()}
disabled={
@@ -9643,9 +10300,10 @@ export default function TaskPage(): React.JSX.Element {
{newLinearProjectSubmitting ? (
<>
- {translate("auto.components.TaskPage.1b59a07674", "Creating...")}>
+ {translate('auto.components.TaskPage.1b59a07674', 'Creating...')}
+ >
) : (
- translate("auto.components.TaskPage.5301ca0f20", "Create project")
+ translate('auto.components.TaskPage.5301ca0f20', 'Create project')
)}
@@ -9674,7 +10332,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.c11105dac5", "New Issue")}
+ {translate('auto.components.TaskPage.c11105dac5', 'New Issue')}
+
/
{availableTeams.length > 1 ? (
@@ -9684,13 +10343,15 @@ export default function TaskPage(): React.JSX.Element {
size="xs"
className="h-7 gap-1 px-2 font-medium text-xs text-foreground hover:bg-muted"
>
- {newLinearIssueTargetTeam?.key ?? translate("auto.components.TaskPage.d7f16d0e32", "Select Team")}
+ {newLinearIssueTargetTeam?.key ??
+ translate('auto.components.TaskPage.d7f16d0e32', 'Select Team')}
- {translate("auto.components.TaskPage.4f3cb99f41", "Switch Team")}
+ {translate('auto.components.TaskPage.4f3cb99f41', 'Switch Team')}
+
{availableTeams.map((t) => (
@@ -9745,7 +10406,7 @@ export default function TaskPage(): React.JSX.Element {
{newLinearStates.loading ? (
@@ -9848,7 +10513,9 @@ export default function TaskPage(): React.JSX.Element {
return (
<>
-
{translate("auto.components.TaskPage.d2a876ca53", "Assignee")}
+
+ {translate('auto.components.TaskPage.d2a876ca53', 'Assignee')}
+
>
)
})()}
@@ -9857,7 +10524,8 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.d2a876ca53", "Assignee")}
+ {translate('auto.components.TaskPage.d2a876ca53', 'Assignee')}
+
{newLinearMembers.loading ? (
@@ -9875,7 +10543,9 @@ export default function TaskPage(): React.JSX.Element {
>
- {translate("auto.components.TaskPage.42a9160321", "Unassigned")}
+
+ {translate('auto.components.TaskPage.42a9160321', 'Unassigned')}
+
{newLinearIssueAssigneeId === null && (
@@ -9925,27 +10595,31 @@ export default function TaskPage(): React.JSX.Element {
{newLinearIssuePriority === 1
- ? translate("auto.components.TaskPage.f373ab1a4f", "Urgent")
+ ? translate('auto.components.TaskPage.f373ab1a4f', 'Urgent')
: newLinearIssuePriority === 2
- ? translate("auto.components.TaskPage.345b169f1f", "High")
+ ? translate('auto.components.TaskPage.345b169f1f', 'High')
: newLinearIssuePriority === 3
- ? translate("auto.components.TaskPage.7fd59c18d8", "Medium")
+ ? translate('auto.components.TaskPage.7fd59c18d8', 'Medium')
: newLinearIssuePriority === 4
- ? translate("auto.components.TaskPage.69591944e7", "Low")
- : translate("auto.components.TaskPage.c8d5bec5f7", "Priority")}
+ ? translate('auto.components.TaskPage.69591944e7', 'Low')
+ : translate('auto.components.TaskPage.c8d5bec5f7', 'Priority')}
- {translate("auto.components.TaskPage.c8d5bec5f7", "Priority")}
+ {translate('auto.components.TaskPage.c8d5bec5f7', 'Priority')}
+
{[
- { val: 0, label: translate("auto.components.TaskPage.713179dfdc", "No priority") },
- { val: 1, label: translate("auto.components.TaskPage.f373ab1a4f", "Urgent") },
- { val: 2, label: translate("auto.components.TaskPage.345b169f1f", "High") },
- { val: 3, label: translate("auto.components.TaskPage.7fd59c18d8", "Medium") },
- { val: 4, label: translate("auto.components.TaskPage.69591944e7", "Low") }
+ {
+ val: 0,
+ label: translate('auto.components.TaskPage.713179dfdc', 'No priority')
+ },
+ { val: 1, label: translate('auto.components.TaskPage.f373ab1a4f', 'Urgent') },
+ { val: 2, label: translate('auto.components.TaskPage.345b169f1f', 'High') },
+ { val: 3, label: translate('auto.components.TaskPage.7fd59c18d8', 'Medium') },
+ { val: 4, label: translate('auto.components.TaskPage.69591944e7', 'Low') }
].map((p) => (
- {translate("auto.components.TaskPage.00022ec0ba", "Project")}
+ {translate('auto.components.TaskPage.00022ec0ba', 'Project')}
+
{newLinearIssueProjectsLoading ? (
@@ -10009,7 +10684,9 @@ export default function TaskPage(): React.JSX.Element {
>
- {translate("auto.components.TaskPage.1742eafc14", "No Project")}
+
+ {translate('auto.components.TaskPage.1742eafc14', 'No Project')}
+
{newLinearIssueProjectId === null && (
@@ -10051,15 +10728,23 @@ export default function TaskPage(): React.JSX.Element {
{newLinearIssueLabelIds.length === 0
- ? translate("auto.components.TaskPage.d0ca4aa1d0", "Labels")
- : translate("auto.components.TaskPage.eff9800d4b", "{{value0}} label{{value1}}", { value0: newLinearIssueLabelIds.length, value1: newLinearIssueLabelIds.length > 1 ? 's' : '' })}
+ ? translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels')
+ : translate(
+ 'auto.components.TaskPage.eff9800d4b',
+ '{{value0}} label{{value1}}',
+ {
+ value0: newLinearIssueLabelIds.length,
+ value1: newLinearIssueLabelIds.length > 1 ? 's' : ''
+ }
+ )}
- {translate("auto.components.TaskPage.d0ca4aa1d0", "Labels")}
+ {translate('auto.components.TaskPage.d0ca4aa1d0', 'Labels')}
+
{newLinearLabels.loading ? (
@@ -10108,7 +10793,8 @@ export default function TaskPage(): React.JSX.Element {
{/* Footer */}
- {submitShortcutLabel} {translate("auto.components.TaskPage.fc0d8a1fa4", "to submit.")}
+ {submitShortcutLabel} {translate('auto.components.TaskPage.fc0d8a1fa4', 'to submit.')}
+
- {translate("auto.components.TaskPage.ff69a30681", "Cancel")}
+ {translate('auto.components.TaskPage.ff69a30681', 'Cancel')}
+
void handleCreateNewLinearIssue()}
@@ -10131,9 +10818,10 @@ export default function TaskPage(): React.JSX.Element {
{newLinearIssueSubmitting ? (
<>
- {translate("auto.components.TaskPage.8ff6fdc368", "Creating…")}>
+ {translate('auto.components.TaskPage.8ff6fdc368', 'Creating…')}
+ >
) : (
- translate("auto.components.TaskPage.e15ba2d2eb", "Create issue")
+ translate('auto.components.TaskPage.e15ba2d2eb', 'Create issue')
)}
@@ -10159,17 +10847,28 @@ export default function TaskPage(): React.JSX.Element {
}}
>
- {translate("auto.components.TaskPage.0c11ca0b6d", "New Jira issue")}
+
+ {translate('auto.components.TaskPage.0c11ca0b6d', 'New Jira issue')}
+
{newJiraIssueTargetProject
- ? translate("auto.components.TaskPage.0f7b0d964a", "Creates a new issue in {{value0}}.", { value0: newJiraIssueTargetProject.key })
- : translate("auto.components.TaskPage.e178c0a953", "Choose a Jira project before creating the issue.")}
+ ? translate(
+ 'auto.components.TaskPage.0f7b0d964a',
+ 'Creates a new issue in {{value0}}.',
+ { value0: newJiraIssueTargetProject.key }
+ )
+ : translate(
+ 'auto.components.TaskPage.e178c0a953',
+ 'Choose a Jira project before creating the issue.'
+ )}
-
{translate("auto.components.TaskPage.00022ec0ba", "Project")}
+
+ {translate('auto.components.TaskPage.00022ec0ba', 'Project')}
+
) : (
- {translate("auto.components.TaskPage.00022ec0ba", "Project")}
+
+ {translate('auto.components.TaskPage.00022ec0ba', 'Project')}
+
)}
@@ -10209,12 +10910,17 @@ export default function TaskPage(): React.JSX.Element {
>
- {translate("auto.components.TaskPage.93c57f15e5", "No projects found.")}
+
+ {translate('auto.components.TaskPage.93c57f15e5', 'No projects found.')}
+
{filteredNewJiraIssueProjects.map((project) => {
const selectionKey = getJiraProjectSelectionKey(project)
const selected = selectionKey === newJiraIssueTargetProjectSelectionKey
@@ -10246,7 +10952,9 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.ae592fee62", "Issue type")}
+
+ {translate('auto.components.TaskPage.ae592fee62', 'Issue type')}
+
setNewJiraIssueTypeId(v)}
@@ -10258,7 +10966,11 @@ export default function TaskPage(): React.JSX.Element {
>
@@ -10272,7 +10984,9 @@ export default function TaskPage(): React.JSX.Element {
- {translate("auto.components.TaskPage.16cba35bee", "Title")}
+
+ {translate('auto.components.TaskPage.16cba35bee', 'Title')}
+
- {translate("auto.components.TaskPage.f161bf9ede", "Description (optional)")}
+ {translate('auto.components.TaskPage.f161bf9ede', 'Description (optional)')}
+
) : null}
{jiraCreateFieldsError ? (
@@ -10318,7 +11034,7 @@ export default function TaskPage(): React.JSX.Element {
{field.name}
- {field.allowedValues?.length && field.schema?.type !== "array" ? (
+ {field.allowedValues?.length && field.schema?.type !== 'array' ? (
@@ -10330,7 +11046,13 @@ export default function TaskPage(): React.JSX.Element {
disabled={newJiraIssueSubmitting}
>
-
+
{field.allowedValues.map((value) => {
@@ -10354,9 +11076,16 @@ export default function TaskPage(): React.JSX.Element {
}
type={field.schema?.type === 'number' ? 'number' : 'text'}
placeholder={
- field.schema?.type === "array"
- ? translate("auto.components.TaskPage.56cdb413a2", "Comma-separated values")
- : translate("auto.components.TaskPage.919a20dd5b", "Enter {{value0}}", { value0: field.name })
+ field.schema?.type === 'array'
+ ? translate(
+ 'auto.components.TaskPage.56cdb413a2',
+ 'Comma-separated values'
+ )
+ : translate(
+ 'auto.components.TaskPage.919a20dd5b',
+ 'Enter {{value0}}',
+ { value0: field.name }
+ )
}
disabled={newJiraIssueSubmitting}
/>
@@ -10366,7 +11095,9 @@ export default function TaskPage(): React.JSX.Element {
})}
) : null}
-
{submitShortcutLabel} {translate("auto.components.TaskPage.fc0d8a1fa4", "to submit.")}
+
+ {submitShortcutLabel} {translate('auto.components.TaskPage.fc0d8a1fa4', 'to submit.')}
+
setNewJiraIssueOpen(false)}
disabled={newJiraIssueSubmitting}
>
- {translate("auto.components.TaskPage.ff69a30681", "Cancel")}
+ {translate('auto.components.TaskPage.ff69a30681', 'Cancel')}
+
void handleCreateNewJiraIssue()}
disabled={
@@ -10389,9 +11121,10 @@ export default function TaskPage(): React.JSX.Element {
{newJiraIssueSubmitting ? (
<>
- {translate("auto.components.TaskPage.8ff6fdc368", "Creating…")}>
+ {translate('auto.components.TaskPage.8ff6fdc368', 'Creating…')}
+ >
) : (
- translate("auto.components.TaskPage.e15ba2d2eb", "Create issue")
+ translate('auto.components.TaskPage.e15ba2d2eb', 'Create issue')
)}
@@ -10466,14 +11199,23 @@ export default function TaskPage(): React.JSX.Element {
}}
>
- {translate("auto.components.TaskPage.60f806ce99", "Connect Jira site")}
+
+ {translate('auto.components.TaskPage.60f806ce99', 'Connect Jira site')}
+
- {translate("auto.components.TaskPage.33fc2bcb30", "Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.")}
+ {translate(
+ 'auto.components.TaskPage.33fc2bcb30',
+ 'Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.'
+ )}
+
{
setJiraSiteUrlDraft(e.target.value)
@@ -10486,7 +11228,7 @@ export default function TaskPage(): React.JSX.Element {
/>
{
setJiraEmailDraft(e.target.value)
@@ -10499,7 +11241,7 @@ export default function TaskPage(): React.JSX.Element {
/>
{
setJiraApiTokenDraft(e.target.value)
@@ -10514,7 +11256,7 @@ export default function TaskPage(): React.JSX.Element {
{jiraConnectError}
)}
- {translate("auto.components.TaskPage.59c14d34a2", "Create a token in")}{' '}
+ {translate('auto.components.TaskPage.59c14d34a2', 'Create a token in')}{' '}
@@ -10523,12 +11265,17 @@ export default function TaskPage(): React.JSX.Element {
)
}
>
- {translate("auto.components.TaskPage.246c2b3dd3", "Atlassian account settings")}
+ {translate('auto.components.TaskPage.246c2b3dd3', 'Atlassian account settings')}
+
.
- {translate("auto.components.TaskPage.2abe22ef76", "Your token is encrypted via the OS keychain and stored locally.")}
+ {translate(
+ 'auto.components.TaskPage.2abe22ef76',
+ 'Your token is encrypted via the OS keychain and stored locally.'
+ )}
+
setJiraConnectOpen(false)}
disabled={jiraConnectState === 'connecting'}
>
- {translate("auto.components.TaskPage.ff69a30681", "Cancel")}
+ {translate('auto.components.TaskPage.ff69a30681', 'Cancel')}
+
void handleJiraConnect()}
disabled={
@@ -10546,12 +11294,13 @@ export default function TaskPage(): React.JSX.Element {
jiraConnectState === 'connecting'
}
>
- {jiraConnectState === "connecting" ? (
+ {jiraConnectState === 'connecting' ? (
<>
- {translate("auto.components.TaskPage.513cddfa7a", "Verifying…")}>
+ {translate('auto.components.TaskPage.513cddfa7a', 'Verifying…')}
+ >
) : (
- translate("auto.components.TaskPage.887efe9140", "Connect")
+ translate('auto.components.TaskPage.887efe9140', 'Connect')
)}
diff --git a/src/renderer/src/components/UpdateCard.tsx b/src/renderer/src/components/UpdateCard.tsx
index fb354ceb312..806540832a3 100644
--- a/src/renderer/src/components/UpdateCard.tsx
+++ b/src/renderer/src/components/UpdateCard.tsx
@@ -757,8 +757,9 @@ function SimpleCardContent({
- {translate('auto.components.UpdateCard.93794ea932', 'Orca v')}
- {version} {translate('auto.components.UpdateCard.c4890662e9', 'is ready.')}
+ {translate('auto.components.UpdateCard.05ad78a6d1', 'Orca v{{value0}} is ready.', {
+ value0: version
+ })}
@@ -1013,11 +1014,10 @@ function ReadyToInstallContent({
- {translate('auto.components.UpdateCard.93794ea932', 'Orca v')}
- {version}{' '}
{translate(
- 'auto.components.UpdateCard.02d4b8a6b9',
- "is downloaded. Restart when you're ready."
+ 'auto.components.UpdateCard.6714206e5a',
+ "Orca v{{value0}} is downloaded. Restart when you're ready.",
+ { value0: version }
)}
diff --git a/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx b/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx
index 16a9e9646af..788174ceae7 100644
--- a/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx
@@ -90,7 +90,15 @@ export function BrowserImportHintButton({
if (result.ok) {
const browser = detectedBrowsers.find((entry) => entry.family === browserFamily)
toast.success(
- translate("auto.components.browser.pane.BrowserImportHintButton.02e89014c5", "Imported {{value0}} cookies from {{value1}}{{value2}}.", { value0: result.summary.importedCookies, value1: browser?.label ?? browserFamily, value2: browserProfile ? ` (${browserProfile})` : '' })
+ translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.02e89014c5',
+ 'Imported {{value0}} cookies from {{value1}}{{value2}}.',
+ {
+ value0: result.summary.importedCookies,
+ value1: browser?.label ?? browserFamily,
+ value2: browserProfile ? ` (${browserProfile})` : ''
+ }
+ )
)
return
}
@@ -104,7 +112,13 @@ export function BrowserImportHintButton({
setImportMenuOpen(false)
const result = await importCookiesToProfile(effectiveProfileId)
if (result.ok) {
- toast.success(translate("auto.components.browser.pane.BrowserImportHintButton.02e89014c5", "Imported {{value0}} cookies from file.", { value0: result.summary.importedCookies }))
+ toast.success(
+ translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.d40d584769',
+ 'Imported {{value0}} cookies from file.',
+ { value0: result.summary.importedCookies }
+ )
+ )
return
}
if (result.reason !== 'canceled') {
@@ -150,19 +164,32 @@ export function BrowserImportHintButton({
variant="secondary"
size="sm"
className="h-7 shrink-0 rounded-full px-2.5 text-xs"
- aria-label={translate("auto.components.browser.pane.BrowserImportHintButton.4f5ffaa6a1", "Import browser data")}
+ aria-label={translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.4f5ffaa6a1',
+ 'Import browser data'
+ )}
data-contextual-tour-target="browser-import-hint"
>
- {translate("auto.components.browser.pane.BrowserImportHintButton.b24fef25be", "Import")}
+ {translate('auto.components.browser.pane.BrowserImportHintButton.b24fef25be', 'Import')}
+
-
{translate("auto.components.browser.pane.BrowserImportHintButton.4f5ffaa6a1", "Import browser data")}
+
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.4f5ffaa6a1',
+ 'Import browser data'
+ )}
+
{importSummary}
- {translate("auto.components.browser.pane.BrowserImportHintButton.e52a955e6f", "You can always find this in Settings > Browser.")}
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.e52a955e6f',
+ 'You can always find this in Settings > Browser.'
+ )}
+
@@ -175,13 +202,23 @@ export function BrowserImportHintButton({
className="h-7 px-2.5 text-xs"
disabled={browserSessionImportState?.status === 'importing'}
>
- {translate("auto.components.browser.pane.BrowserImportHintButton.244266c122", "Import…")}
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.244266c122',
+ 'Import…'
+ )}
+
{detectedBrowsers.map((browser) =>
browser.profiles.length > 1 ? (
- {translate("auto.components.browser.pane.BrowserImportHintButton.0c6d254eca", "From")}{browser.label}
+
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.0c6d254eca',
+ 'From'
+ )}
+ {browser.label}
+
{browser.profiles.map((profile) => (
@@ -202,13 +239,21 @@ export function BrowserImportHintButton({
key={browser.family}
onSelect={() => void handleImportFromBrowser(browser.family)}
>
- {translate("auto.components.browser.pane.BrowserImportHintButton.0c6d254eca", "From")}{browser.label}
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.0c6d254eca',
+ 'From'
+ )}
+ {browser.label}
)
)}
{detectedBrowsers.length > 0 ? : null}
void handleImportFromFile()}>
- {translate("auto.components.browser.pane.BrowserImportHintButton.e0e125e074", "From File…")}
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.e0e125e074',
+ 'From File…'
+ )}
+
@@ -217,14 +262,22 @@ export function BrowserImportHintButton({
onClick={handleOpenBrowserSettings}
className="rounded-sm text-xs text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.browser.pane.BrowserImportHintButton.77351d22f5", "Browser Settings")}
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.77351d22f5',
+ 'Browser Settings'
+ )}
+
- {translate("auto.components.browser.pane.BrowserImportHintButton.05e675fe96", "Hide Hint")}
+ {translate(
+ 'auto.components.browser.pane.BrowserImportHintButton.05e675fe96',
+ 'Hide Hint'
+ )}
+
diff --git a/src/renderer/src/components/browser-pane/BrowserPane.tsx b/src/renderer/src/components/browser-pane/BrowserPane.tsx
index 4ed588e3433..0491106e750 100644
--- a/src/renderer/src/components/browser-pane/BrowserPane.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserPane.tsx
@@ -186,8 +186,16 @@ type BrowserOverlayAnchor = {
}
const BROWSER_ANNOTATION_INTENT_OPTIONS = [
- { value: 'change', label: translate("auto.components.browser.pane.BrowserPane.143204e423", "Change"), icon: PencilLine },
- { value: 'question', label: translate("auto.components.browser.pane.BrowserPane.b5ba6085de", "Question"), icon: MessageCircleQuestionMark }
+ {
+ value: 'change',
+ label: translate('auto.components.browser.pane.BrowserPane.143204e423', 'Change'),
+ icon: PencilLine
+ },
+ {
+ value: 'question',
+ label: translate('auto.components.browser.pane.BrowserPane.b5ba6085de', 'Question'),
+ icon: MessageCircleQuestionMark
+ }
] as const
// Why: priority remains in the persisted annotation shape for backwards
@@ -362,7 +370,10 @@ function PendingBrowserAnnotationCard({
collisionPadding={12}
portalContainer={portalContainer}
className="z-40 w-[22rem] max-w-[calc(var(--radix-popover-content-available-width)-1rem)] p-3 shadow-[0_10px_24px_rgba(0,0,0,0.18)]"
- aria-label={translate("auto.components.browser.pane.BrowserPane.b472c5fe03", "Add browser annotation")}
+ aria-label={translate(
+ 'auto.components.browser.pane.BrowserPane.b472c5fe03',
+ 'Add browser annotation'
+ )}
onEscapeKeyDown={(event) => {
event.preventDefault()
onCancel()
@@ -379,12 +390,16 @@ function PendingBrowserAnnotationCard({
- {translate("auto.components.browser.pane.BrowserPane.d2a7092e6e", "Annotation comment")}
+ {translate('auto.components.browser.pane.BrowserPane.d2a7092e6e', 'Annotation comment')}
+
setPending(null)} disabled={isBusy}>
- {translate("auto.components.shared.useDaemonActions.01af244097", "Cancel")}
+ {translate('auto.components.shared.useDaemonActions.01af244097', 'Cancel')}
+
{isBusy ? : null}
{isBusy && busyKind === pending ? copy.busyLabel : copy.confirmLabel}
diff --git a/src/renderer/src/components/sidebar/WorktreeCard.tsx b/src/renderer/src/components/sidebar/WorktreeCard.tsx
index ac2f6f73baf..3b3d9f74e1b 100644
--- a/src/renderer/src/components/sidebar/WorktreeCard.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCard.tsx
@@ -574,11 +574,34 @@ const WorktreeCard = React.memo(function WorktreeCard({
}, [])
const unreadTooltip = worktree.isUnread ? 'Mark read' : 'Mark unread'
- const childWorkspaceLabel = `${lineageChildCount} child ${
- lineageChildCount === 1 ? 'workspace' : 'workspaces'
- }`
+ const lineageChildAriaLabel =
+ lineageChildCount === 1
+ ? lineageCollapsed
+ ? translate(
+ 'auto.components.sidebar.WorktreeList.20bebf9c7f',
+ 'Show {{value0}} child workspace',
+ { value0: lineageChildCount }
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeList.e97297cb75',
+ 'Hide {{value0}} child workspace',
+ { value0: lineageChildCount }
+ )
+ : lineageCollapsed
+ ? translate(
+ 'auto.components.sidebar.WorktreeList.c1f4a31623',
+ 'Show {{value0}} child workspaces',
+ { value0: lineageChildCount }
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeList.0cd15956d4',
+ 'Hide {{value0}} child workspaces',
+ { value0: lineageChildCount }
+ )
const childWorkspaceShortLabel = `${lineageChildCount} ${
- lineageChildCount === 1 ? 'child' : 'children'
+ lineageChildCount === 1
+ ? translate('auto.components.sidebar.WorktreeList.0c6ee14f23', 'child')
+ : translate('auto.components.sidebar.WorktreeList.045a8aed48', 'children')
}`
const showLineageChildChip = lineageChildCount > 0 && onLineageToggle !== undefined
@@ -1180,8 +1203,14 @@ const WorktreeCard = React.memo(function WorktreeCard({
- {remoteBranchConflict.remote}/{remoteBranchConflict.branchName}{' '}
- {translate('auto.components.sidebar.WorktreeCard.a88c92d0e3', 'already exists.')}
+ {translate(
+ 'auto.components.sidebar.WorktreeCard.a88c92d0e3',
+ '{{value0}}/{{value1}} already exists.',
+ {
+ value0: remoteBranchConflict.remote,
+ value1: remoteBranchConflict.branchName
+ }
+ )}
)}
@@ -1214,7 +1243,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
variant="ghost"
size="xs"
className="relative z-10 h-[18px] max-w-[8rem] gap-1 rounded-md border border-worktree-sidebar-border bg-worktree-sidebar px-1.5 text-[10px] font-medium leading-none text-muted-foreground shadow-none hover:bg-worktree-sidebar-accent hover:text-foreground focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring"
- aria-label={`${lineageCollapsed ? 'Show' : 'Hide'} ${childWorkspaceLabel}`}
+ aria-label={lineageChildAriaLabel}
aria-expanded={!lineageCollapsed}
onClick={onLineageToggle}
>
diff --git a/src/renderer/src/components/stats/usage-overview-sections.tsx b/src/renderer/src/components/stats/usage-overview-sections.tsx
index 0359074bca9..0f65f4e7dc0 100644
--- a/src/renderer/src/components/stats/usage-overview-sections.tsx
+++ b/src/renderer/src/components/stats/usage-overview-sections.tsx
@@ -18,6 +18,13 @@ const INTENSITY_CLASS: Record = {
4: 'border-border/60 bg-foreground/75'
}
+function translateActivityLabel(label: UsageProviderOverview['activityLabel']): string {
+ if (label === 'turns') {
+ return translate('auto.components.stats.usage.overview.sections.c8f3a2d1e0b4', 'turns')
+ }
+ return translate('auto.components.stats.usage.overview.sections.d9a4b3e2f1c5', 'events')
+}
+
function formatDayLabel(day: string): string {
const parsed = new Date(`${day}T12:00:00`)
if (Number.isNaN(parsed.getTime())) {
@@ -30,19 +37,19 @@ export function TokenMixBar({ overview }: { overview: UsageOverviewModel }): Rea
const segments = [
{
key: 'new-input',
- label: translate("auto.components.stats.usage.overview.sections.9365b14a4e", "New input"),
+ label: translate('auto.components.stats.usage.overview.sections.9365b14a4e', 'New input'),
value: overview.newInputTokens,
className: 'bg-foreground'
},
{
key: 'output',
- label: translate("auto.components.stats.usage.overview.sections.7f270458af", "Output"),
+ label: translate('auto.components.stats.usage.overview.sections.7f270458af', 'Output'),
value: overview.outputTokens,
className: 'bg-muted-foreground'
},
{
key: 'cache',
- label: translate("auto.components.stats.usage.overview.sections.0015facc1f", "Cache"),
+ label: translate('auto.components.stats.usage.overview.sections.0015facc1f', 'Cache'),
value: overview.cacheTokens,
className: 'bg-border'
}
@@ -55,20 +62,31 @@ export function TokenMixBar({ overview }: { overview: UsageOverviewModel }): Rea
-
{translate("auto.components.stats.usage.overview.sections.4ff104da47", "Token mix")}
+
+ {translate('auto.components.stats.usage.overview.sections.4ff104da47', 'Token mix')}
+
- {translate("auto.components.stats.usage.overview.sections.3bc4a01b24", "Combined input, output, and cache tokens across enabled providers.")}
+ {translate(
+ 'auto.components.stats.usage.overview.sections.3bc4a01b24',
+ 'Combined input, output, and cache tokens across enabled providers.'
+ )}
+
{overview.reasoningTokens > 0 ? (
- {formatUsageTokens(overview.reasoningTokens)} {translate("auto.components.stats.usage.overview.sections.e65084cb4b", "reasoning")}
+ {formatUsageTokens(overview.reasoningTokens)}{' '}
+ {translate('auto.components.stats.usage.overview.sections.e65084cb4b', 'reasoning')}
+
) : null}
{mixTotal > 0 ? (
{segments.map((segment) =>
segment.value > 0 ? (
@@ -76,7 +94,11 @@ export function TokenMixBar({ overview }: { overview: UsageOverviewModel }): Rea
key={segment.key}
className={segment.className}
style={{ width: `${(segment.value / mixTotal) * 100}%` }}
- aria-label={translate("auto.components.stats.usage.overview.sections.32330a6e66", "{{value0}}: {{value1}} tokens", { value0: segment.label, value1: segment.value.toLocaleString() })}
+ aria-label={translate(
+ 'auto.components.stats.usage.overview.sections.32330a6e66',
+ '{{value0}}: {{value1}} tokens',
+ { value0: segment.label, value1: segment.value.toLocaleString() }
+ )}
/>
) : null
)}
@@ -110,33 +132,50 @@ export function DailyIntensityGrid({
-
{translate("auto.components.stats.usage.overview.sections.69e2b50427", "Daily intensity")}
+
+ {translate(
+ 'auto.components.stats.usage.overview.sections.69e2b50427',
+ 'Daily intensity'
+ )}
+
- {translate("auto.components.stats.usage.overview.sections.f28ff1f852", "Recent combined Claude, Codex, and OpenCode token activity.")}
+ {translate(
+ 'auto.components.stats.usage.overview.sections.f28ff1f852',
+ 'Recent combined Claude, Codex, and OpenCode token activity.'
+ )}
+
{bestDay && bestDay.totalTokens > 0 ? (
- {translate("auto.components.stats.usage.overview.sections.c424eb3f8e", "Best:")}{formatDayLabel(bestDay.day)}
+ {translate('auto.components.stats.usage.overview.sections.c424eb3f8e', 'Best:')}
+ {formatDayLabel(bestDay.day)}
) : null}
{formatDayLabel(days[0]?.day ?? '')}
-
{translate("auto.components.stats.usage.overview.sections.1dd166c920", "Less")}
+
{translate('auto.components.stats.usage.overview.sections.1dd166c920', 'Less')}
{[0, 1, 2, 3, 4].map((intensity) => (
))}
-
{translate("auto.components.stats.usage.overview.sections.f6df0d7d6d", "More")}
+
{translate('auto.components.stats.usage.overview.sections.f6df0d7d6d', 'More')}
{formatDayLabel(days.at(-1)?.day ?? '')}
@@ -174,21 +213,33 @@ export function ProviderUsageRow({
{status}
- {provider.topModel ?? translate("auto.components.stats.usage.overview.sections.3de9bf87fc", "No model yet")}
+ {provider.topModel ??
+ translate('auto.components.stats.usage.overview.sections.3de9bf87fc', 'No model yet')}
{provider.topProject ? ` - ${provider.topProject}` : ''}
{!provider.enabled ? (
- {translate("auto.components.stats.usage.overview.sections.57d1448ef8", "Enable")}
+ {translate('auto.components.stats.usage.overview.sections.57d1448ef8', 'Enable')}
+
) : null}
- {formatUsageTokens(provider.totalTokens)} {translate("auto.components.stats.usage.overview.sections.32330a6e66", "tokens")}
- {provider.sessions.toLocaleString()} {translate("auto.components.stats.usage.overview.sections.9564a3b21b", "sessions -")}{provider.activityCount.toLocaleString()}{' '}
- {provider.activityLabel}
+ {formatUsageTokens(provider.totalTokens)}{' '}
+ {translate('auto.components.stats.usage.overview.sections.6762f6a682', 'tokens')}
+
+
+ {translate(
+ 'auto.components.stats.usage.overview.sections.a7f937fb29',
+ '{{value0}} sessions - {{value1}} {{value2}}',
+ {
+ value0: provider.sessions.toLocaleString(),
+ value1: provider.activityCount.toLocaleString(),
+ value2: translateActivityLabel(provider.activityLabel)
+ }
+ )}
{formatUsageCost(provider.estimatedCostUsd)}
diff --git a/src/renderer/src/components/status-bar/PortsStatusSegment.tsx b/src/renderer/src/components/status-bar/PortsStatusSegment.tsx
index bb7d8d0c112..6d3ea2e6e68 100644
--- a/src/renderer/src/components/status-bar/PortsStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/PortsStatusSegment.tsx
@@ -73,7 +73,11 @@ export function PortsStatusSegment({ iconOnly }: PortsStatusSegmentProps): React
type="button"
{...STATUS_BAR_CONTEXT_MENU_EXEMPT_PROPS}
className="inline-flex cursor-pointer items-center gap-1.5 rounded px-1 py-0.5 hover:bg-accent/70"
- aria-label={translate("auto.components.status.bar.PortsStatusSegment.b8bc3e420a", "Ports, {{value0}} workspace {{value1}}", { value0: workspacePortCount, value1: workspacePortCount === 1 ? 'port' : 'ports' })}
+ aria-label={translate(
+ 'auto.components.status.bar.PortsStatusSegment.b8bc3e420a',
+ 'Ports, {{value0}} workspace {{value1}}',
+ { value0: workspacePortCount, value1: workspacePortCount === 1 ? 'port' : 'ports' }
+ )}
>
{refreshing ? (
@@ -94,8 +98,25 @@ export function PortsStatusSegment({ iconOnly }: PortsStatusSegmentProps): React
- {translate("auto.components.status.bar.PortsStatusSegment.ca41be2802", "Ports —")}{workspacePortCount} {translate("auto.components.status.bar.PortsStatusSegment.a11ed266ce", "workspace")}{workspacePortCount === 1 ? translate("auto.components.status.bar.PortsStatusSegment.45834a9ace", "port") : translate("auto.components.status.bar.PortsStatusSegment.8caaa86e9a", "ports")}
- {externalPorts.length > 0 ? translate("auto.components.status.bar.PortsStatusSegment.a8e4bdb412", " · {{value0}} external", { value0: externalPorts.length }) : ''}
+ {translate(
+ 'auto.components.status.bar.PortsStatusSegment.ca41be2802',
+ 'Ports — {{value0}} workspace {{value1}}{{value2}}',
+ {
+ value0: workspacePortCount,
+ value1:
+ workspacePortCount === 1
+ ? translate('auto.components.status.bar.PortsStatusSegment.45834a9ace', 'port')
+ : translate('auto.components.status.bar.PortsStatusSegment.8caaa86e9a', 'ports'),
+ value2:
+ externalPorts.length > 0
+ ? translate(
+ 'auto.components.status.bar.PortsStatusSegment.a8e4bdb412',
+ ' · {{value0}} external',
+ { value0: externalPorts.length }
+ )
+ : ''
+ }
+ )}
@@ -111,15 +132,26 @@ export function PortsStatusSegment({ iconOnly }: PortsStatusSegmentProps): React
-
{translate("auto.components.status.bar.PortsStatusSegment.c22ea609fd", "Ports")}
+
+ {translate('auto.components.status.bar.PortsStatusSegment.c22ea609fd', 'Ports')}
+
- {workspacePortCount} {translate("auto.components.status.bar.PortsStatusSegment.9aa11005bf", "workspace ·")}{externalPorts.length} {translate("auto.components.status.bar.PortsStatusSegment.a8e4bdb412", "external")}
+ {translate(
+ 'auto.components.status.bar.PortsStatusSegment.2b84c4d11f',
+ '{{value0}} workspace · {{value1}} external',
+ { value0: workspacePortCount, value1: externalPorts.length }
+ )}
+
{scan?.unavailableReason ? (
- {translate("auto.components.status.bar.PortsStatusSegment.95495019ed", "Port scan unavailable on")}{scan.platform}: {scan.unavailableReason}
+ {translate(
+ 'auto.components.status.bar.PortsStatusSegment.95495019ed',
+ 'Port scan unavailable on {{value0}}: {{value1}}',
+ { value0: scan.platform, value1: scan.unavailableReason }
+ )}
) : (
@@ -133,7 +165,15 @@ export function PortsStatusSegment({ iconOnly }: PortsStatusSegmentProps): React
))
) : (
- {refreshing ? translate("auto.components.status.bar.PortsStatusSegment.c174bbbfed", "Scanning for workspace ports...") : translate("auto.components.status.bar.PortsStatusSegment.3a87d54dfb", "No workspace ports detected")}
+ {refreshing
+ ? translate(
+ 'auto.components.status.bar.PortsStatusSegment.c174bbbfed',
+ 'Scanning for workspace ports...'
+ )
+ : translate(
+ 'auto.components.status.bar.PortsStatusSegment.3a87d54dfb',
+ 'No workspace ports detected'
+ )}
)}
@@ -152,7 +192,12 @@ export function PortsStatusSegment({ iconOnly }: PortsStatusSegmentProps): React
) : (
)}
-
{translate("auto.components.status.bar.PortsStatusSegment.7dac3ecc9d", "External Ports")}
+
+ {translate(
+ 'auto.components.status.bar.PortsStatusSegment.7dac3ecc9d',
+ 'External Ports'
+ )}
+
{externalPorts.length}
{externalOpen && (
@@ -168,7 +213,11 @@ export function PortsStatusSegment({ iconOnly }: PortsStatusSegmentProps): React
))
) : (
- {translate("auto.components.status.bar.PortsStatusSegment.4ebf90c12e", "No external ports detected")}
+ {translate(
+ 'auto.components.status.bar.PortsStatusSegment.4ebf90c12e',
+ 'No external ports detected'
+ )}
+
)}
)}
diff --git a/src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx b/src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx
index 542333b274e..75c68e658d2 100644
--- a/src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx
@@ -246,7 +246,17 @@ function AppSection({
type="button"
onClick={onToggle}
className="pl-2 py-2 pr-0.5 transition-colors hover:bg-muted/50"
- aria-label={isCollapsed ? translate("auto.components.status.bar.ResourceUsageStatusSegment.e419d27083", "Expand Orca") : translate("auto.components.status.bar.ResourceUsageStatusSegment.53dd5560ae", "Collapse Orca")}
+ aria-label={
+ isCollapsed
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.e419d27083',
+ 'Expand Orca'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.53dd5560ae',
+ 'Collapse Orca'
+ )
+ }
aria-expanded={!isCollapsed}
>
{isCollapsed ? (
@@ -257,7 +267,8 @@ function AppSection({
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.288a4dd177", "Orca")}
+ {translate('auto.components.status.bar.ResourceUsageStatusSegment.288a4dd177', 'Orca')}
+
@@ -267,10 +278,28 @@ function AppSection({
{!isCollapsed && (
-
-
+
+
{(app.other.cpu > 0 || app.other.memory > 0) && (
-
+
)}
)}
@@ -387,7 +416,11 @@ function SessionRow({
session.bound &&
'opacity-0 group-hover/sessrow:opacity-100 group-focus-within/sessrow:opacity-100 focus-visible:opacity-100'
)}
- aria-label={translate("auto.components.status.bar.ResourceUsageStatusSegment.b10695d6ce", "Kill session {{value0}}", { value0: session.sessionId })}
+ aria-label={translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.fa6d36758d',
+ 'Kill session {{value0}}',
+ { value0: session.sessionId }
+ )}
>
@@ -444,7 +477,17 @@ function WorktreeRow({
type="button"
onClick={onToggle}
className="pl-2 py-2 pr-0.5 shrink-0"
- aria-label={isCollapsed ? translate("auto.components.status.bar.ResourceUsageStatusSegment.c4a8968bdd", "Expand workspace") : translate("auto.components.status.bar.ResourceUsageStatusSegment.bbcd9b7b85", "Collapse workspace")}
+ aria-label={
+ isCollapsed
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.c4a8968bdd',
+ 'Expand workspace'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.bbcd9b7b85',
+ 'Collapse workspace'
+ )
+ }
>
{isCollapsed ? (
@@ -461,7 +504,11 @@ function WorktreeRow({
@@ -472,7 +519,11 @@ function WorktreeRow({
local. */}
{worktree.isRemote && (
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.21cacb16d1", "· remote")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.21cacb16d1',
+ '· remote'
+ )}
+
)}
@@ -495,7 +546,11 @@ function WorktreeRow({
type="button"
onClick={onDelete}
disabled={isMainWorktree}
- aria-label={translate("auto.components.status.bar.ResourceUsageStatusSegment.16bc3c998a", "Delete workspace {{value0}}", { value0: rowLabel })}
+ aria-label={translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.16bc3c998a',
+ 'Delete workspace {{value0}}',
+ { value0: rowLabel }
+ )}
className={cn(
'p-0.5 rounded text-muted-foreground transition-colors',
isMainWorktree
@@ -511,7 +566,15 @@ function WorktreeRow({
sideOffset={4}
className="z-[70] max-w-[200px] text-pretty"
>
- {isMainWorktree ? translate("auto.components.status.bar.ResourceUsageStatusSegment.946724a70a", "The main workspace cannot be deleted.") : translate("auto.components.status.bar.ResourceUsageStatusSegment.a82253b458", "Delete workspace.")}
+ {isMainWorktree
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.946724a70a',
+ 'The main workspace cannot be deleted.'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.a82253b458',
+ 'Delete workspace.'
+ )}
@@ -606,7 +669,17 @@ function ResourceTree({
type="button"
onClick={() => toggleRepo(group.repoId)}
className="pl-2 py-2 pr-0.5 transition-colors hover:bg-muted/50"
- aria-label={repoCollapsed ? translate("auto.components.status.bar.ResourceUsageStatusSegment.b12e31dfcb", "Expand repo") : translate("auto.components.status.bar.ResourceUsageStatusSegment.73a3fd68a9", "Collapse repo")}
+ aria-label={
+ repoCollapsed
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.b12e31dfcb',
+ 'Expand repo'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.73a3fd68a9',
+ 'Collapse repo'
+ )
+ }
>
{repoCollapsed ? (
@@ -621,7 +694,11 @@ function ResourceTree({
{group.hasRemoteChildren && (
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.21cacb16d1", "· remote")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.21cacb16d1',
+ '· remote'
+ )}
+
)}
@@ -1122,7 +1199,11 @@ export function ResourceUsageStatusSegment({
className="relative inline-flex items-center gap-1.5 cursor-pointer rounded px-1 py-0.5 hover:bg-accent/70"
aria-label={
daemonUnreachable
- ? translate("auto.components.status.bar.ResourceUsageStatusSegment.59f178fe11", "{{value0}}, daemon unreachable", { value0: resourceManagerAriaLabel })
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.59f178fe11',
+ '{{value0}}, daemon unreachable',
+ { value0: resourceManagerAriaLabel }
+ )
: resourceManagerAriaLabel
}
>
@@ -1154,7 +1235,13 @@ export function ResourceUsageStatusSegment({
)}
{daemonUnreachable && (
-
+
)}
@@ -1191,7 +1278,15 @@ export function ResourceUsageStatusSegment({
- {runtimeEnvironmentActive ? translate("auto.components.status.bar.ResourceUsageStatusSegment.6a822b06a7", "Resource Manager") : translate("auto.components.status.bar.ResourceUsageStatusSegment.6d9793d4bc", "Resource Manager - Terminals")}
+ {runtimeEnvironmentActive
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.6a822b06a7',
+ 'Resource Manager'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.6d9793d4bc',
+ 'Resource Manager - Terminals'
+ )}
@@ -1202,14 +1297,25 @@ export function ResourceUsageStatusSegment({
type="button"
onClick={() => daemonActions.setPending('restart')}
disabled={daemonActions.isBusy || runtimeEnvironmentActive}
- aria-label={translate("auto.components.status.bar.ResourceUsageStatusSegment.c9382662bb", "Restart daemon")}
+ aria-label={translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.c9382662bb',
+ 'Restart daemon'
+ )}
className="inline-flex size-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:opacity-40"
>
- {runtimeEnvironmentActive ? translate("auto.components.status.bar.ResourceUsageStatusSegment.14ff448686", "Unavailable for runtime servers") : translate("auto.components.status.bar.ResourceUsageStatusSegment.c9382662bb", "Restart daemon")}
+ {runtimeEnvironmentActive
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.14ff448686',
+ 'Unavailable for runtime servers'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.c9382662bb',
+ 'Restart daemon'
+ )}
@@ -1218,14 +1324,25 @@ export function ResourceUsageStatusSegment({
type="button"
onClick={() => daemonActions.setPending('killAll')}
disabled={daemonActions.isBusy || runtimeEnvironmentActive}
- aria-label={translate("auto.components.status.bar.ResourceUsageStatusSegment.bd19fd7a59", "Kill all sessions")}
+ aria-label={translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.bd19fd7a59',
+ 'Kill all sessions'
+ )}
className="inline-flex size-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive disabled:opacity-40"
>
- {runtimeEnvironmentActive ? translate("auto.components.status.bar.ResourceUsageStatusSegment.14ff448686", "Unavailable for runtime servers") : translate("auto.components.status.bar.ResourceUsageStatusSegment.bd19fd7a59", "Kill all sessions")}
+ {runtimeEnvironmentActive
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.14ff448686',
+ 'Unavailable for runtime servers'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.bd19fd7a59',
+ 'Kill all sessions'
+ )}
@@ -1235,9 +1352,18 @@ export function ResourceUsageStatusSegment({
-
{translate("auto.components.status.bar.ResourceUsageStatusSegment.f8e0d794b4", "Daemon is not responding")}
+
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.f8e0d794b4',
+ 'Daemon is not responding'
+ )}
+
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.f85af9cda6", "Resource snapshots and terminal sessions are unavailable.")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.f85af9cda6',
+ 'Resource snapshots and terminal sessions are unavailable.'
+ )}
+
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.93b0de3c21", "Restart")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.93b0de3c21',
+ 'Restart'
+ )}
+
)}
@@ -1257,7 +1387,12 @@ export function ResourceUsageStatusSegment({
role="status"
>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.e7cf14ec78", "Terminal sessions unavailable. The list may be stale.")}
+
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.e7cf14ec78',
+ 'Terminal sessions unavailable. The list may be stale.'
+ )}
+
)}
@@ -1274,7 +1409,11 @@ export function ResourceUsageStatusSegment({
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.1fedf94eae", "Combined CPU load. Values above 100% mean more than one core is working at once.")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.1fedf94eae',
+ 'Combined CPU load. Values above 100% mean more than one core is working at once.'
+ )}
+
·
@@ -1287,7 +1426,11 @@ export function ResourceUsageStatusSegment({
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.9e2525c89f", "Resident memory held by Orca plus the processes under each worktree's terminals.")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.9e2525c89f',
+ "Resident memory held by Orca plus the processes under each worktree's terminals."
+ )}
+
·
@@ -1296,15 +1439,34 @@ export function ResourceUsageStatusSegment({
tabIndex={0}
className="text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:rounded"
>
- {formatPercent(hostShare)} {translate("auto.components.status.bar.ResourceUsageStatusSegment.e7ccce7e87", "of system RAM")}
+ {formatPercent(hostShare)}{' '}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.e7ccce7e87',
+ 'of system RAM'
+ )}
+
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.6449a95c78", "How much of this machine's physical RAM the Orca-tracked processes are sitting on.")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.6449a95c78',
+ "How much of this machine's physical RAM the Orca-tracked processes are sitting on."
+ )}
+
{orphanCount > 0 && (
- {orphanCount} {translate("auto.components.status.bar.ResourceUsageStatusSegment.30ff2c3c31", "orphan")}{orphanCount === 1 ? '' : 's'}
+ {orphanCount === 1
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.30ff2c3c31',
+ '{{value0}} orphan',
+ { value0: orphanCount }
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.b8f4a2c1d0e3',
+ '{{value0}} orphans',
+ { value0: orphanCount }
+ )}
)}
@@ -1332,7 +1494,11 @@ export function ResourceUsageStatusSegment({
)}
aria-pressed={sortOption === 'name'}
>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.2aa2de6cb9", "Name")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.2aa2de6cb9',
+ 'Name'
+ )}
+
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.298f4be7f2", "CPU")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.298f4be7f2',
+ 'CPU'
+ )}
+
setSortOption('memory')}
@@ -1360,7 +1530,11 @@ export function ResourceUsageStatusSegment({
)}
aria-pressed={sortOption === 'memory'}
>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.1b24a32d3a", "Memory")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.1b24a32d3a',
+ 'Memory'
+ )}
+
{/* Why: empty trailing gutter so the CPU/Memory header
cells line up with the row cells; rows reserve the same
@@ -1389,7 +1563,11 @@ export function ResourceUsageStatusSegment({
{unifiedRepos.length === 0 && resourceSnapshot && (
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.27a74f91f0", "Nothing running right now")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.27a74f91f0',
+ 'Nothing running right now'
+ )}
+
)}
{resourceSnapshot && (
@@ -1403,8 +1581,14 @@ export function ResourceUsageStatusSegment({
{!resourceSnapshot && !daemonUnreachable && (
{runtimeEnvironmentActive
- ? translate("auto.components.status.bar.ResourceUsageStatusSegment.56b6888304", "Local resource usage hidden for runtime servers.")
- : translate("auto.components.status.bar.ResourceUsageStatusSegment.888dad8c55", "Loading…")}
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.56b6888304',
+ 'Local resource usage hidden for runtime servers.'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.888dad8c55',
+ 'Loading…'
+ )}
)}
@@ -1419,7 +1603,11 @@ export function ResourceUsageStatusSegment({
className="relative inline-flex w-full items-center justify-center rounded-md border border-border/70 px-2.5 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent/60"
>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.92924a14e3", "Review inactive workspaces (")}{oldWorkspaceCount})
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.92924a14e3',
+ 'Review inactive workspaces ({{value0}})',
+ { value0: oldWorkspaceCount }
+ )}
void handleKillOrphans()}
className="mt-2 inline-flex w-full items-center justify-center rounded-md border border-border/70 px-2.5 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent/60"
>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.4bb076fa89", "Kill")}{orphanCount} {translate("auto.components.status.bar.ResourceUsageStatusSegment.996295bff2", "orphan terminal")}{orphanCount === 1 ? '' : 's'}
+ {orphanCount === 1
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.c7e3b1a0d9f2',
+ 'Kill {{value0}} orphan terminal',
+ { value0: orphanCount }
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.d8f4c2b1e0a3',
+ 'Kill {{value0}} orphan terminals',
+ { value0: orphanCount }
+ )}
) : null}
@@ -1476,25 +1674,48 @@ export function ResourceUsageStatusSegment({
>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.4bb076fa89", "Kill")}{' '}
-
- {killConfirm?.label ?? translate("auto.components.status.bar.ResourceUsageStatusSegment.138b99bd80", "this session")}
-
- ?
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.e9a5d3c2b1f0',
+ 'Kill {{value0}}?',
+ {
+ value0:
+ killConfirm?.label ??
+ translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.138b99bd80',
+ 'this session'
+ )
+ }
+ )}
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.67c4ecda49", "Force-quits this terminal. Any unsaved work in the pane is lost. This can't be undone.")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.67c4ecda49',
+ "Force-quits this terminal. Any unsaved work in the pane is lost. This can't be undone."
+ )}
+
setKillConfirm(null)} disabled={killing}>
- {translate("auto.components.status.bar.ResourceUsageStatusSegment.946d9f94d0", "Cancel")}
+ {translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.946d9f94d0',
+ 'Cancel'
+ )}
+
void runKillConfirmed()}
disabled={killing}
>
{killing ? : null}
- {killing ? translate("auto.components.status.bar.ResourceUsageStatusSegment.41ae4fa725", "Killing…") : translate("auto.components.status.bar.ResourceUsageStatusSegment.b10695d6ce", "Kill session")}
+ {killing
+ ? translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.41ae4fa725',
+ 'Killing…'
+ )
+ : translate(
+ 'auto.components.status.bar.ResourceUsageStatusSegment.b10695d6ce',
+ 'Kill session'
+ )}
diff --git a/src/renderer/src/components/status-bar/UpdateStatusSegment.tsx b/src/renderer/src/components/status-bar/UpdateStatusSegment.tsx
index 92688c78679..af41d79ea48 100644
--- a/src/renderer/src/components/status-bar/UpdateStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/UpdateStatusSegment.tsx
@@ -27,23 +27,50 @@ export function UpdateStatusSegment({
return {
icon: ,
label: `${pct}%`,
- tooltip: translate("auto.components.status.bar.UpdateStatusSegment.248ee5d8ef", "Orca v{{value0}} downloading… {{value1}}%", { value0: status.version, value1: pct }),
- ariaLabel: translate("auto.components.status.bar.UpdateStatusSegment.fd1d3b3a1d", "Update downloading, {{value0}} percent. Click to expand.", { value0: pct })
+ tooltip: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.248ee5d8ef',
+ 'Orca v{{value0}} downloading… {{value1}}%',
+ { value0: status.version, value1: pct }
+ ),
+ ariaLabel: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.fd1d3b3a1d',
+ 'Update downloading, {{value0}} percent. Click to expand.',
+ { value0: pct }
+ )
}
}
if (status.state === 'downloaded') {
return {
icon: ,
- label: translate("auto.components.status.bar.UpdateStatusSegment.57a29c3b0e", "Update ready"),
- tooltip: translate("auto.components.status.bar.UpdateStatusSegment.248ee5d8ef", "Orca v{{value0}} ready to install", { value0: status.version }),
- ariaLabel: translate("auto.components.status.bar.UpdateStatusSegment.962404f68e", "Update ready to install. Click to expand.")
+ label: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.57a29c3b0e',
+ 'Update ready'
+ ),
+ tooltip: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.9d13213a56',
+ 'Orca v{{value0}} ready to install',
+ { value0: status.version }
+ ),
+ ariaLabel: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.962404f68e',
+ 'Update ready to install. Click to expand.'
+ )
}
}
return {
icon: ,
- label: translate("auto.components.status.bar.UpdateStatusSegment.8533c12c3c", "Update failed"),
- tooltip: translate("auto.components.status.bar.UpdateStatusSegment.2201df6987", "Update failed — click to see details"),
- ariaLabel: translate("auto.components.status.bar.UpdateStatusSegment.5cd13105a3", "Update failed. Click to expand.")
+ label: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.8533c12c3c',
+ 'Update failed'
+ ),
+ tooltip: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.2201df6987',
+ 'Update failed — click to see details'
+ ),
+ ariaLabel: translate(
+ 'auto.components.status.bar.UpdateStatusSegment.5cd13105a3',
+ 'Update failed. Click to expand.'
+ )
}
})()
diff --git a/src/renderer/src/components/status-bar/WorkspaceSpaceManagerPanel.tsx b/src/renderer/src/components/status-bar/WorkspaceSpaceManagerPanel.tsx
index 2fd101b95c7..dbd505533e4 100644
--- a/src/renderer/src/components/status-bar/WorkspaceSpaceManagerPanel.tsx
+++ b/src/renderer/src/components/status-bar/WorkspaceSpaceManagerPanel.tsx
@@ -306,7 +306,10 @@ function UpdatedMetric({
return (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.33653dbac2", "Deleting")}
+ {translate('auto.components.status.bar.WorkspaceSpaceManagerPanel.33653dbac2', 'Deleting')}
+
)
}
if (deleteState?.error) {
return (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.39801484e0", "Failed")}
+ {translate('auto.components.status.bar.WorkspaceSpaceManagerPanel.39801484e0', 'Failed')}
+
)
}
if (worktree.status !== 'ok') {
@@ -410,40 +415,90 @@ function StatusBadge({
)
}
if (worktree.isMainWorktree) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.2b501ee391", "Keep: main")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.2b501ee391',
+ 'Keep: main'
+ )}
+
+ )
}
if (decisionDetails?.isActive) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.7f7895514e", "Keep: active")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.7f7895514e',
+ 'Keep: active'
+ )}
+
+ )
}
if ((decisionDetails?.changedFileCount ?? 0) > 0) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.7ab8d7e2d7", "Keep: changed files")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.7ab8d7e2d7',
+ 'Keep: changed files'
+ )}
+
+ )
}
if (decisionDetails?.changedFileCount === null) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.ec7b076a75", "Keep: git not checked")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.ec7b076a75',
+ 'Keep: git not checked'
+ )}
+
+ )
}
if ((decisionDetails?.dirtyEditorBufferCount ?? 0) > 0) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.2055bc6a5a", "Keep: unsaved edits")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.2055bc6a5a',
+ 'Keep: unsaved edits'
+ )}
+
+ )
}
if (
(decisionDetails?.activeAgentCount ?? 0) > 0 ||
(decisionDetails?.liveTerminalCount ?? 0) > 0 ||
(decisionDetails?.browserTabCount ?? 0) > 0
) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.cbc343a7a8", "Keep: in use")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.cbc343a7a8',
+ 'Keep: in use'
+ )}
+
+ )
}
if (
decisionDetails?.reviewLabel ||
decisionDetails?.issueLabel ||
decisionDetails?.linearIssueLabel
) {
- return {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.720870a18e", "Keep: linked")}
+ return (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.720870a18e',
+ 'Keep: linked'
+ )}
+
+ )
}
return (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.7d7745bb8f", "Can delete")}
+ {translate('auto.components.status.bar.WorkspaceSpaceManagerPanel.7d7745bb8f', 'Can delete')}
+
)
}
@@ -588,19 +643,35 @@ function WorkspaceDecisionHoverCard({
}
- label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.d384a4ce9f", "Delete decision")}
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.d384a4ce9f',
+ 'Delete decision'
+ )}
value={deleteDecision}
tone={worktree.canDelete && worktree.status === 'ok' ? 'default' : 'warning'}
/>
- } label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.a8d9e0de79", "Agents")} value={getAgentDecisionLabel(details)} />
+ }
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.a8d9e0de79',
+ 'Agents'
+ )}
+ value={getAgentDecisionLabel(details)}
+ />
}
- label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e9528a89b3", "Terminals")}
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e9528a89b3',
+ 'Terminals'
+ )}
value={getTerminalDecisionLabel(details)}
/>
}
- label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.0bc756efaf", "Git changes")}
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.0bc756efaf',
+ 'Git changes'
+ )}
value={getGitDecisionLabel(details, gitRefreshState)}
tone={
(details.changedFileCount ?? 0) > 0 || gitRefreshState?.error ? 'warning' : 'default'
@@ -608,27 +679,47 @@ function WorkspaceDecisionHoverCard({
/>
}
- label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.c432278ec7", "Editor buffers")}
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.c432278ec7',
+ 'Editor buffers'
+ )}
value={getEditorDecisionLabel(details)}
tone={details.dirtyEditorBufferCount > 0 ? 'warning' : 'default'}
/>
}
- label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.b9b4a3a25d", "Branch")}
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.b9b4a3a25d',
+ 'Branch'
+ )}
value={details.branchStatus ?? getWorkspaceSpaceBranchLabel(worktree)}
/>
}
- label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.fb2069acb7", "Review")}
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.fb2069acb7',
+ 'Review'
+ )}
value={details.reviewLabel ?? 'No linked PR'}
/>
- } label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.66870929fb", "Issue")} value={issueLabel} />
+ }
+ label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.66870929fb',
+ 'Issue'
+ )}
+ value={issueLabel}
+ />
{details.browserTabCount > 0
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.131662ac65", "{{value0}} open", { value0: pluralize(details.browserTabCount, 'browser tab') })
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.131662ac65',
+ '{{value0}} open',
+ { value0: pluralize(details.browserTabCount, 'browser tab') }
+ )
: worktree.path}
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.c28643d3da", "Go to workspace")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.c28643d3da',
+ 'Go to workspace'
+ )}
+
)
@@ -704,15 +799,25 @@ function WorkspaceTreemap({
className="absolute right-2 top-2 gap-1.5 bg-background/90 px-2.5 backdrop-blur"
>
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.ef890d31b9", "All")}
+ {translate('auto.components.status.bar.WorkspaceSpaceManagerPanel.ef890d31b9', 'All')}
+
) : null}
{isScanning ? : null}
{isScanning
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.c5135e7e4a", "Scanning workspace sizes. You can leave this page.")
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.c5135e7e4a',
+ 'Scanning workspace sizes. You can leave this page.'
+ )
: isZoomed
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.977bdf9a36", "No top-level items to show.")
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.0990a63160", "No scanned workspace sizes yet.")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.977bdf9a36',
+ 'No top-level items to show.'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.0990a63160',
+ 'No scanned workspace sizes yet.'
+ )}
)
@@ -733,7 +838,8 @@ function WorkspaceTreemap({
className="gap-1.5 bg-background/90 px-2.5 backdrop-blur"
>
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.ef890d31b9", "All")}
+ {translate('auto.components.status.bar.WorkspaceSpaceManagerPanel.ef890d31b9', 'All')}
+
>
) : canZoomSelected ? (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.d3f9c69ddc", "Zoom")}
+ {translate('auto.components.status.bar.WorkspaceSpaceManagerPanel.d3f9c69ddc', 'Zoom')}
+
) : null}
{rects.map((rect) => {
@@ -824,8 +931,14 @@ function BreakdownList({
{isScanning ? : null}
{isScanning
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.c5135e7e4a", "Scanning workspace sizes. You can leave this page.")
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.5c6d25720c", "Select a workspace to inspect.")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.c5135e7e4a',
+ 'Scanning workspace sizes. You can leave this page.'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.5c6d25720c',
+ 'Select a workspace to inspect.'
+ )}
)
@@ -848,18 +961,34 @@ function BreakdownList({
{formatBytes(worktree.sizeBytes)}
- {formatCompactCount(topLevelItemCount)} {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.b25c2c1086", "top-level items")}
+ {formatCompactCount(topLevelItemCount)}{' '}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.b25c2c1086',
+ 'top-level items'
+ )}
+
- {worktree.status !== "ok" ? (
+ {worktree.status !== 'ok' ? (
-
{worktree.error ?? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.0ba046fbc5", "Scan failed.")}
+
+ {worktree.error ??
+ translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.0ba046fbc5',
+ 'Scan failed.'
+ )}
+
) : worktree.topLevelItems.length === 0 ? (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.16988df079", "No files found.")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.16988df079',
+ 'No files found.'
+ )}
+
) : (
@@ -951,7 +1080,11 @@ function WorkspaceRow({
@@ -961,7 +1094,14 @@ function WorkspaceRow({
{worktree.isRemote ? (
) : null}
- {worktree.isSparse ? {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.9155381019", "Sparse")} : null}
+ {worktree.isSparse ? (
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.9155381019',
+ 'Sparse'
+ )}
+
+ ) : null}
@@ -985,7 +1125,11 @@ function WorkspaceRow({
className="h-6 shrink-0 gap-1 px-2"
>
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.a998501630", "Force")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.a998501630',
+ 'Force'
+ )}
+
) : null}
) : null}
@@ -1000,7 +1144,7 @@ function WorkspaceRow({
- {worktree.status === "ok" ? formatBytes(worktree.sizeBytes) : '—'}
+ {worktree.status === 'ok' ? formatBytes(worktree.sizeBytes) : '—'}
@@ -1041,7 +1185,11 @@ function WorkspaceRow({
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.792a214457", "Delete workspace")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.792a214457',
+ 'Delete workspace'
+ )}
+
)
@@ -1384,13 +1532,27 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
}
return next
})
- toast.success(deletedIds.length === 1 ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.9afc97f9a3", "Workspace deleted") : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.eee5240810", "Workspaces deleted"), {
- description: translate(
- 'auto.components.status.bar.WorkspaceSpaceManagerPanel.63efebe0e6',
- '{{value0}} {{value1}} removed from Space.',
- { value0: deletedIds.length, value1: deletedIds.length === 1 ? 'workspace' : 'workspaces' }
- )
- })
+ toast.success(
+ deletedIds.length === 1
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.9afc97f9a3',
+ 'Workspace deleted'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.eee5240810',
+ 'Workspaces deleted'
+ ),
+ {
+ description: translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.63efebe0e6',
+ '{{value0}} {{value1}} removed from Space.',
+ {
+ value0: deletedIds.length,
+ value1: deletedIds.length === 1 ? 'workspace' : 'workspaces'
+ }
+ )
+ }
+ )
},
[removeWorkspaceSpaceWorktrees]
)
@@ -1415,17 +1577,29 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
void removeWorktree(worktree.worktreeId, true)
.then((result) => {
if (!result.ok) {
- toast.error(translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.2965415393", "Force delete failed"), {
- description: result.error
- })
+ toast.error(
+ translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.2965415393',
+ 'Force delete failed'
+ ),
+ {
+ description: result.error
+ }
+ )
return
}
handleDeletedWorktrees([worktree.worktreeId])
})
.catch((error: unknown) => {
- toast.error(translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.2965415393", "Force delete failed"), {
- description: error instanceof Error ? error.message : String(error)
- })
+ toast.error(
+ translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.2965415393',
+ 'Force delete failed'
+ ),
+ {
+ description: error instanceof Error ? error.message : String(error)
+ }
+ )
})
},
[handleDeletedWorktrees, removeWorktree]
@@ -1441,13 +1615,25 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
return (
-
+
0
@@ -1469,11 +1655,26 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
{analysis
? isScanning
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.34174bd83d", "{{value0}}. You can leave this page; the last result stays visible.", { value0: progressLabel ?? 'Scanning workspace sizes' })
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.d595295d7d", "{{value0}} can be reclaimed from linked worktrees.", { value0: formatBytes(analysis.reclaimableBytes) })
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.34174bd83d',
+ '{{value0}}. You can leave this page; the last result stays visible.',
+ { value0: progressLabel ?? 'Scanning workspace sizes' }
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.d595295d7d',
+ '{{value0}} can be reclaimed from linked worktrees.',
+ { value0: formatBytes(analysis.reclaimableBytes) }
+ )
: isScanning
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.265d956765", "{{value0}}. You can leave this page.", { value0: progressLabel ?? 'Scanning workspace sizes' })
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e91dd2a9ae", "Run a scan to inspect workspace sizes.")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.265d956765',
+ '{{value0}}. You can leave this page.',
+ { value0: progressLabel ?? 'Scanning workspace sizes' }
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e91dd2a9ae',
+ 'Run a scan to inspect workspace sizes.'
+ )}
{isScanning ? (
- progress?.state === "cancelling" ? (
+ progress?.state === 'cancelling' ? (
) : (
@@ -1493,12 +1694,24 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
)}
{isScanning
- ? progress?.state === "cancelling"
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.1fce91d1b9", "Stopping")
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.8dc9ddac8a", "Cancel")
+ ? progress?.state === 'cancelling'
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.1fce91d1b9',
+ 'Stopping'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.8dc9ddac8a',
+ 'Cancel'
+ )
: analysis
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.508673bac0", "Refresh")
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.8c7c57fbf8", "Scan")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.508673bac0',
+ 'Refresh'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.8c7c57fbf8',
+ 'Scan'
+ )}
@@ -1507,7 +1720,12 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
{scanError}
- {analysis ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.20a4204dce", "Last successful results remain visible.") : ''}
+ {analysis
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.20a4204dce',
+ 'Last successful results remain visible.'
+ )
+ : ''}
) : null}
@@ -1543,9 +1761,20 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
- {selectedDeletableIds.length} {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.65402b7192", "selected")}
+ {selectedDeletableIds.length}{' '}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.65402b7192',
+ 'selected'
+ )}
+
·
- {formatBytes(selectedReclaimableBytes)} {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.0cb1501ccf", "reclaimable")}
+
+ {formatBytes(selectedReclaimableBytes)}{' '}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.0cb1501ccf',
+ 'reclaimable'
+ )}
+
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e4a12c455b", "Clear")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e4a12c455b',
+ 'Clear'
+ )}
+
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.5caccea440", "Delete selected")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.5caccea440',
+ 'Delete selected'
+ )}
+
) : null}
@@ -1576,7 +1813,10 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
setQuery(event.target.value)}
- placeholder={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.6f8f6a6b04", "Filter workspaces")}
+ placeholder={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.6f8f6a6b04',
+ 'Filter workspaces'
+ )}
className="pl-9"
/>
@@ -1589,10 +1829,30 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.33aef3e9cc", "Size")}
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.243287ac60", "Name")}
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.81f14d9924", "Repository")}
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.d7ac56452e", "Activity")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.33aef3e9cc',
+ 'Size'
+ )}
+
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.243287ac60',
+ 'Name'
+ )}
+
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.81f14d9924',
+ 'Repository'
+ )}
+
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.d7ac56452e',
+ 'Activity'
+ )}
+
@@ -1601,9 +1861,20 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
size="sm"
onClick={() => setOnlyDeletable((current) => !current)}
className="w-32"
- aria-label={translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.81aaf1de65", "Show only deletable workspaces")}
+ aria-label={translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.81aaf1de65',
+ 'Show only deletable workspaces'
+ )}
>
- {onlyDeletable ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.b2f82ed5ae", "Deletable") : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.ef890d31b9", "All")}
+ {onlyDeletable
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.b2f82ed5ae',
+ 'Deletable'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.ef890d31b9',
+ 'All'
+ )}
- {allVisibleSelected ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e4a12c455b", "Clear") : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.f39d291997", "Select")}
+ {allVisibleSelected
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e4a12c455b',
+ 'Clear'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.f39d291997',
+ 'Select'
+ )}
) : null}
@@ -1632,8 +1919,14 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
disabled={visibleDeletableIds.length === 0}
label={
allVisibleSelected
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.697d60c456", "Clear visible selection")
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.1d0f8300d1", "Select visible deletable workspaces")
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.697d60c456',
+ 'Clear visible selection'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.1d0f8300d1',
+ 'Select visible deletable workspaces'
+ )
}
onClick={toggleVisibleSelection}
/>
@@ -1643,33 +1936,58 @@ export function WorkspaceSpaceManagerPanel(): React.JSX.Element {
onClick={() => toggleSort('name')}
className="flex items-center gap-1 text-left"
>
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e4aebea158", "Workspace")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e4aebea158',
+ 'Workspace'
+ )}
+
toggleSort('repo')}
className="flex items-center gap-1 text-left"
>
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.81f14d9924", "Repository")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.81f14d9924',
+ 'Repository'
+ )}
+
toggleSort('size')}
className="flex items-center justify-end gap-1 text-right"
>
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.33aef3e9cc", "Size")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.33aef3e9cc',
+ 'Size'
+ )}
+
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.be37293b10", "State")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.be37293b10',
+ 'State'
+ )}
+
{isInitialScan ? (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.a02d84d2d2", "Scanning workspaces. You can leave this page.")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.a02d84d2d2',
+ 'Scanning workspaces. You can leave this page.'
+ )}
+
) : rows.length === 0 ? (
- {translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e031e93219", "No matching workspaces.")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e031e93219',
+ 'No matching workspaces.'
+ )}
+
) : (
rows.map((worktree) => (
{scanError
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.8194a4fb29", "Scan failed before any workspace sizes were collected.")
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.8194a4fb29',
+ 'Scan failed before any workspace sizes were collected.'
+ )
: analysis
- ? translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.61e25239da", "No workspace rows were available from the scan.")
- : translate("auto.components.status.bar.WorkspaceSpaceManagerPanel.e91dd2a9ae", "Run a scan to inspect workspace sizes.")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.61e25239da',
+ 'No workspace rows were available from the scan.'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceManagerPanel.e91dd2a9ae',
+ 'Run a scan to inspect workspace sizes.'
+ )}
)}
diff --git a/src/renderer/src/components/tab-bar/tab-create-menu-options.ts b/src/renderer/src/components/tab-bar/tab-create-menu-options.ts
index cef3decbcbd..a6f2de6241b 100644
--- a/src/renderer/src/components/tab-bar/tab-create-menu-options.ts
+++ b/src/renderer/src/components/tab-bar/tab-create-menu-options.ts
@@ -110,7 +110,13 @@ export function buildTabCreateMenuOptions(
kind: 'new-terminal-shell',
label,
shell: entry.shell,
- keywords: ['terminal', 'shell', 'new terminal', entry.label, label]
+ keywords: [
+ translate('auto.components.tab.bar.tab.create.menu.options.5501c2fb7a', 'terminal'),
+ translate('auto.components.tab.bar.tab.create.menu.options.9630dd5494', 'shell'),
+ translate('auto.components.tab.bar.tab.create.menu.options.a094576900', 'new terminal'),
+ entry.label,
+ label
+ ]
})
}
} else {
@@ -119,7 +125,12 @@ export function buildTabCreateMenuOptions(
id: 'new-terminal',
kind: 'new-terminal',
label,
- keywords: ['terminal', 'shell', 'new terminal', 'new shell']
+ keywords: [
+ translate('auto.components.tab.bar.tab.create.menu.options.5501c2fb7a', 'terminal'),
+ translate('auto.components.tab.bar.tab.create.menu.options.9630dd5494', 'shell'),
+ translate('auto.components.tab.bar.tab.create.menu.options.a094576900', 'new terminal'),
+ translate('auto.components.tab.bar.tab.create.menu.options.4f23f4d01d', 'new shell')
+ ]
})
}
@@ -129,7 +140,12 @@ export function buildTabCreateMenuOptions(
id: 'new-browser',
kind: 'new-browser',
label,
- keywords: ['browser', 'new browser', 'browser tab', 'web']
+ keywords: [
+ translate('auto.components.tab.bar.tab.create.menu.options.4f2a91e15b', 'browser'),
+ translate('auto.components.tab.bar.tab.create.menu.options.6d0e6a4b7a', 'new browser'),
+ translate('auto.components.tab.bar.tab.create.menu.options.c87ad57785', 'browser tab'),
+ translate('auto.components.tab.bar.tab.create.menu.options.cce7ef1d2c', 'web')
+ ]
})
}
@@ -139,7 +155,13 @@ export function buildTabCreateMenuOptions(
id: 'new-markdown',
kind: 'new-markdown',
label,
- keywords: ['markdown', 'md', 'new markdown', 'new file', 'mark']
+ keywords: [
+ translate('auto.components.tab.bar.tab.create.menu.options.5f17fb9d0c', 'markdown'),
+ translate('auto.components.tab.bar.tab.create.menu.options.44caaf7b36', 'md'),
+ translate('auto.components.tab.bar.tab.create.menu.options.fb50e3d874', 'new markdown'),
+ translate('auto.components.tab.bar.tab.create.menu.options.6d8b6b4117', 'new file'),
+ translate('auto.components.tab.bar.tab.create.menu.options.b330f72434', 'mark')
+ ]
})
}
@@ -149,7 +171,12 @@ export function buildTabCreateMenuOptions(
id: 'open-markdown',
kind: 'open-markdown',
label,
- keywords: ['open markdown', 'markdown', 'md', 'open file']
+ keywords: [
+ translate('auto.components.tab.bar.tab.create.menu.options.37ff3ddca1', 'open markdown'),
+ translate('auto.components.tab.bar.tab.create.menu.options.5f17fb9d0c', 'markdown'),
+ translate('auto.components.tab.bar.tab.create.menu.options.44caaf7b36', 'md'),
+ translate('auto.components.tab.bar.tab.create.menu.options.164c394bab', 'open file')
+ ]
})
}
@@ -162,13 +189,13 @@ export function buildTabCreateMenuOptions(
kind: context.simulatorIsGoTo ? 'go-to-simulator' : 'new-simulator',
label,
keywords: [
- 'mobile emulator',
- 'emulator',
- 'simulator',
- 'ios simulator',
- 'iphone',
- 'ipad',
- 'mobile'
+ translate('auto.components.tab.bar.tab.create.menu.options.bbaf4f85a4', 'mobile emulator'),
+ translate('auto.components.tab.bar.tab.create.menu.options.3784b83bd4', 'emulator'),
+ translate('auto.components.tab.bar.tab.create.menu.options.a63847a742', 'simulator'),
+ translate('auto.components.tab.bar.tab.create.menu.options.1baeb07c17', 'ios simulator'),
+ translate('auto.components.tab.bar.tab.create.menu.options.8a580f88cf', 'iphone'),
+ translate('auto.components.tab.bar.tab.create.menu.options.7ecdc5ef08', 'ipad'),
+ translate('auto.components.tab.bar.tab.create.menu.options.14965cc123', 'mobile')
]
})
}
diff --git a/src/renderer/src/components/workspace-cleanup/WorkspaceCleanupDialog.tsx b/src/renderer/src/components/workspace-cleanup/WorkspaceCleanupDialog.tsx
index 17cee51fea2..2373d6916a6 100644
--- a/src/renderer/src/components/workspace-cleanup/WorkspaceCleanupDialog.tsx
+++ b/src/renderer/src/components/workspace-cleanup/WorkspaceCleanupDialog.tsx
@@ -204,9 +204,15 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
setActiveView('ready')
void scanWorkspaceCleanup().catch((err: unknown) => {
if (mountedRef.current) {
- toast.error(translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.662b8ec3f8", "Workspace cleanup scan failed"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.662b8ec3f8',
+ 'Workspace cleanup scan failed'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
}
})
}
@@ -346,9 +352,15 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
setRowFailures({})
void scanWorkspaceCleanup().catch((err: unknown) => {
if (mountedRef.current) {
- toast.error(translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.662b8ec3f8", "Workspace cleanup scan failed"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.662b8ec3f8',
+ 'Workspace cleanup scan failed'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
}
})
}, [mountedRef, scanWorkspaceCleanup])
@@ -386,9 +398,15 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
})
.catch((err: unknown) => {
if (mountedRef.current) {
- toast.error(translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.7f451a3e2c", "Could not ignore cleanup suggestion"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.7f451a3e2c',
+ 'Could not ignore cleanup suggestion'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
}
})
},
@@ -422,14 +440,25 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
if (result.removedIds.length > 0) {
if (mountedRef.current) {
toast.success(
- translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.0f00612b6d", "Removed {{value0}} workspace{{value1}}", { value0: result.removedIds.length, value1: result.removedIds.length === 1 ? '' : 's' })
+ translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.0f00612b6d',
+ 'Removed {{value0}} workspace{{value1}}',
+ {
+ value0: result.removedIds.length,
+ value1: result.removedIds.length === 1 ? '' : 's'
+ }
+ )
)
}
}
if (result.failures.length > 0) {
if (mountedRef.current) {
toast.error(
- translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.41d594d01e", "{{value0}} workspace{{value1}} could not be removed", { value0: result.failures.length, value1: result.failures.length === 1 ? '' : 's' })
+ translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.41d594d01e',
+ '{{value0}} workspace{{value1}} could not be removed',
+ { value0: result.failures.length, value1: result.failures.length === 1 ? '' : 's' }
+ )
)
}
} else {
@@ -457,9 +486,18 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.b2c1331844", "Delete Inactive Workspaces")}
+
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.b2c1331844',
+ 'Delete Inactive Workspaces'
+ )}
+
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.e0b5a4deaa", "Review inactive workspaces before deleting their local files and Orca state.")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.e0b5a4deaa',
+ 'Review inactive workspaces before deleting their local files and Orca state.'
+ )}
+
@@ -467,7 +505,10 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
@@ -475,12 +516,19 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.7ae2ad30f4", "Refresh")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.7ae2ad30f4',
+ 'Refresh'
+ )}
+
closeModal()}
disabled={removing}
>
@@ -495,25 +543,62 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.7eee951968", "Checking workspace safety")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.7eee951968',
+ 'Checking workspace safety'
+ )}
+
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.8b74d4ea6e", "Scanning worktrees and git state, then combining open tab, terminal, live agent, and remote availability signals before suggesting deletions.")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.8b74d4ea6e',
+ 'Scanning worktrees and git state, then combining open tab, terminal, live agent, and remote availability signals before suggesting deletions.'
+ )}
+
) : hasAnyCandidates ? (
- {selectedCount} {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.ac5ba84cc1", "selected")}
-
{inactiveCount} {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.2b31bf68de", "inactive")}
+ {selectedCount}{' '}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.ac5ba84cc1',
+ 'selected'
+ )}
+
+
+ {inactiveCount}{' '}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.2b31bf68de',
+ 'inactive'
+ )}
+
{readyCount > 0 ? (
-
{readyCount} {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.b299f201b9", "safe to remove")}
+
+ {readyCount}{' '}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.b299f201b9',
+ 'safe to remove'
+ )}
+
) : null}
{groups.review.length > 0 ? (
-
{groups.review.length} {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.1b18868569", "need review")}
+
+ {groups.review.length}{' '}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.1b18868569',
+ 'need review'
+ )}
+
) : null}
{protectedCount > 0 ? (
-
{protectedCount} {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.37ab28277e", "not suggested")}
+
+ {protectedCount}{' '}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.37ab28277e',
+ 'not suggested'
+ )}
+
) : null}
@@ -535,7 +620,11 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
disabled={selectedCount === 0}
>
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.b771c92598", "Delete selected")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.b771c92598',
+ 'Delete selected'
+ )}
+
) : null}
@@ -569,22 +658,33 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
}
aria-label={
allActiveQueueableSelected
- ? translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.73690b0031", "Unselect all in {{value0}}", { value0: TIER_LABELS[resolvedActiveView] })
- : translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.06cf78521e", "Select all in {{value0}}", { value0: TIER_LABELS[resolvedActiveView] })
+ ? translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.73690b0031',
+ 'Unselect all in {{value0}}',
+ { value0: TIER_LABELS[resolvedActiveView] }
+ )
+ : translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.06cf78521e',
+ 'Select all in {{value0}}',
+ { value0: TIER_LABELS[resolvedActiveView] }
+ )
}
onClick={toggleActiveSelection}
className="flex size-4 shrink-0 items-center justify-center rounded border border-border bg-background text-primary hover:bg-accent"
>
- {activeSelectionState === "checked" ? (
+ {activeSelectionState === 'checked' ? (
- ) : activeSelectionState === "mixed" ? (
+ ) : activeSelectionState === 'mixed' ? (
) : null}
) : null}
{resolvedActiveView === 'hidden'
- ? translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.0c6672f5e3", "Ignored cleanup suggestions")
+ ? translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.0c6672f5e3',
+ 'Ignored cleanup suggestions'
+ )
: TIER_LABELS[resolvedActiveView]}
@@ -595,27 +695,48 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
className="h-auto shrink-0 px-0 text-xs"
onClick={() => void resetDismissals()}
>
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.aaee139eab", "Restore ignored suggestions")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.aaee139eab',
+ 'Restore ignored suggestions'
+ )}
+
) : (
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.592fbab446", "Sorted by oldest activity")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.592fbab446',
+ 'Sorted by oldest activity'
+ )}
+
)}
{initialLoading ? : null}
{!loading && scan && candidates.length === 0 && !scanNoticeMessage ? (
-
+
) : null}
{!loading && scan && candidates.length === 0 && scanNoticeMessage ? (
-
+
) : null}
{!loading &&
scan &&
candidates.length > 0 &&
filteredCandidates.length === 0 ? (
setRepoSelection(new Set(eligibleRepoIds))}
/>
@@ -625,13 +746,21 @@ export default function WorkspaceCleanupDialog(): React.JSX.Element {
filteredCandidates.length > 0 &&
visibleCandidates.length === 0 ? (
setActiveView('hidden')}
/>
) : null}
{!loading && scan && activeRows.length === 0 && visibleCandidates.length > 0 ? (
-
+
) : null}
{activeRows.map((candidate, index) => (
void
}): React.JSX.Element {
const items: { view: WorkspaceCleanupView; label: string }[] = [
- { view: 'ready', label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.4b93a235d8", "Suggested") },
- { view: 'review', label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.d1094dd529", "Needs review") },
- { view: 'protected', label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.c4f4782c02", "Not suggested") },
- { view: 'hidden', label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.e8b3741ff7", "Ignored") }
+ {
+ view: 'ready',
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.4b93a235d8',
+ 'Suggested'
+ )
+ },
+ {
+ view: 'review',
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.d1094dd529',
+ 'Needs review'
+ )
+ },
+ {
+ view: 'protected',
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.c4f4782c02',
+ 'Not suggested'
+ )
+ },
+ {
+ view: 'hidden',
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.e8b3741ff7',
+ 'Ignored'
+ )
+ }
]
return (
@@ -774,7 +927,11 @@ function CandidateRow({
type="button"
role="checkbox"
aria-checked={selected}
- aria-label={translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.bbb1ab6a6f", "Select {{value0}}", { value0: candidate.displayName })}
+ aria-label={translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.bbb1ab6a6f',
+ 'Select {{value0}}',
+ { value0: candidate.displayName }
+ )}
onClick={() => onToggleSelected(candidate.worktreeId)}
className="mt-0.5 flex size-4 shrink-0 items-center justify-center rounded border border-border bg-background text-primary hover:bg-accent"
>
@@ -788,7 +945,11 @@ function CandidateRow({
{candidate.displayName}
{status.label}
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.352f15d6fc", "Last active")}{formatRelativeTime(candidate.lastActivityAt)}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.352f15d6fc',
+ 'Last active'
+ )}
+ {formatRelativeTime(candidate.lastActivityAt)}
{blockers.length > 0 ? (
@@ -800,8 +961,20 @@ function CandidateRow({
{candidate.path}
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.0b1766738a", "Repo")}{candidate.repoName}
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.bef0adef9b", "Branch")}{candidate.branch}
+
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.0b1766738a',
+ 'Repo'
+ )}
+ {candidate.repoName}
+
+
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.bef0adef9b',
+ 'Branch'
+ )}
+ {candidate.branch}
+
{formatGitStatus(candidate)}
{branchSafetyDetails.slice(0, 1).map((detail) => (
{detail}
@@ -821,14 +994,22 @@ function CandidateRow({
onView(candidate)}
>
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.1bffc07ba7", "View")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.ee81adfcef',
+ 'View'
+ )}
+
{!ignored ? (
@@ -836,14 +1017,22 @@ function CandidateRow({
onIgnore(candidate)}
>
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.a9957007eb", "Ignore")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.4d0b72481c',
+ 'Ignore'
+ )}
+
) : null}
{selectable ? (
@@ -852,7 +1041,11 @@ function CandidateRow({
onRemove(candidate)}
>
@@ -860,7 +1053,11 @@ function CandidateRow({
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.3828408538", "Remove")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.9cc26c019d',
+ 'Remove'
+ )}
+
) : null}
@@ -874,7 +1071,13 @@ function getCandidateStatus(candidate: WorkspaceCleanupCandidate): {
tone: 'neutral' | 'ready' | 'review' | 'destructive'
} {
if (candidate.blockers.includes('dismissed')) {
- return { label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.e8b3741ff7", "Ignored"), tone: 'neutral' }
+ return {
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.e8b3741ff7',
+ 'Ignored'
+ ),
+ tone: 'neutral'
+ }
}
if (candidate.tier === 'ready') {
return { label: candidate.reasons.includes('archived') ? 'Archived' : 'Clean', tone: 'ready' }
@@ -883,15 +1086,39 @@ function getCandidateStatus(candidate: WorkspaceCleanupCandidate): {
return { label: BLOCKER_LABELS[candidate.blockers[0]], tone: 'neutral' }
}
if (candidate.git.upstreamAhead && candidate.git.upstreamAhead > 0) {
- return { label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.9623a5107d", "Unpushed commits"), tone: 'review' }
+ return {
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.9623a5107d',
+ 'Unpushed commits'
+ ),
+ tone: 'review'
+ }
}
if (candidate.git.clean === false) {
- return { label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.e97e4580c7", "Dirty"), tone: 'review' }
+ return {
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.e97e4580c7',
+ 'Dirty'
+ ),
+ tone: 'review'
+ }
}
if (candidate.tier === 'review') {
- return { label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.0a2e3c7cba", "Review"), tone: 'review' }
+ return {
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.0a2e3c7cba',
+ 'Review'
+ ),
+ tone: 'review'
+ }
+ }
+ return {
+ label: translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.c4f4782c02',
+ 'Not suggested'
+ ),
+ tone: 'neutral'
}
- return { label: translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.c4f4782c02", "Not suggested"), tone: 'neutral' }
}
function formatGitStatus(candidate: WorkspaceCleanupCandidate): string {
@@ -980,18 +1207,36 @@ function ConfirmRemove({
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.cbf2f664e2", "Delete")}{count} {noun}?
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.cbf2f664e2',
+ 'Delete'
+ )}
+ {count} {noun}?
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.38ca0b1400", "This permanently deletes their local files. You can't undo this.")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.38ca0b1400',
+ "This permanently deletes their local files. You can't undo this."
+ )}
+
- {count} {noun} {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.dba753e94f", "to delete")}
-
{translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.592fbab446", "Sorted by oldest activity")}
+ {count} {noun}{' '}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.dba753e94f',
+ 'to delete'
+ )}
+
+
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.592fbab446',
+ 'Sorted by oldest activity'
+ )}
+
{candidates.map((candidate, index) => (
@@ -1005,10 +1250,18 @@ function ConfirmRemove({
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.b6bae1eed1", "Cancel")}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.b6bae1eed1',
+ 'Cancel'
+ )}
+
{removing ? : }
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.cbf2f664e2", "Delete")}{count} {noun}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.cbf2f664e2',
+ 'Delete'
+ )}
+ {count} {noun}
>
@@ -1029,7 +1282,11 @@ function ConfirmRemoveRow({
{candidate.displayName}
- {translate("auto.components.workspace.cleanup.WorkspaceCleanupDialog.352f15d6fc", "Last active")}{formatRelativeTime(candidate.lastActivityAt)}
+ {translate(
+ 'auto.components.workspace.cleanup.WorkspaceCleanupDialog.352f15d6fc',
+ 'Last active'
+ )}
+ {formatRelativeTime(candidate.lastActivityAt)}
{dirtyLabel ? {dirtyLabel} : null}
diff --git a/src/renderer/src/i18n/hosted-review-localized-copy.ts b/src/renderer/src/i18n/hosted-review-localized-copy.ts
new file mode 100644
index 00000000000..f86736fe691
--- /dev/null
+++ b/src/renderer/src/i18n/hosted-review-localized-copy.ts
@@ -0,0 +1,36 @@
+import type { HostedReviewProvider } from '../../../shared/hosted-review'
+import { translate } from '@/i18n/i18n'
+
+export type SupportedHostedReviewCopyProvider = 'github' | 'gitlab'
+
+export type LocalizedHostedReviewCopy = {
+ shortLabel: string
+ reviewLabel: string
+ titleLabel: string
+ providerName: string
+}
+
+export function resolveSupportedHostedReviewCopyProvider(
+ provider: HostedReviewProvider | null | undefined
+): SupportedHostedReviewCopyProvider {
+ return provider === 'gitlab' ? 'gitlab' : 'github'
+}
+
+export function localizedHostedReviewCopy(
+ provider: SupportedHostedReviewCopyProvider
+): LocalizedHostedReviewCopy {
+ if (provider === 'gitlab') {
+ return {
+ shortLabel: translate('auto.i18n.hostedReview.copy.c4e8f1a2b9', 'MR'),
+ reviewLabel: translate('auto.i18n.hostedReview.copy.b3d7e0f1a8', 'merge request'),
+ titleLabel: translate('auto.i18n.hostedReview.copy.a2c6d9e0f7', 'Merge Request'),
+ providerName: translate('auto.i18n.hostedReview.copy.91b5c8d7e6', 'GitLab')
+ }
+ }
+ return {
+ shortLabel: translate('auto.i18n.hostedReview.copy.f0a4b8c2d1', 'PR'),
+ reviewLabel: translate('auto.i18n.hostedReview.copy.e9f3a7b1c0', 'pull request'),
+ titleLabel: translate('auto.i18n.hostedReview.copy.d8e2f6a0b9', 'Pull Request'),
+ providerName: translate('auto.i18n.hostedReview.copy.c7d1e5f9a8', 'GitHub')
+ }
+}
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index 41bd8ec3d49..f56e16c3faf 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -144,7 +144,8 @@
"10898045f3": "Shortcut for \"{{value0}}\" was ignored: Use a string array.",
"36761d9604": "Unknown keybinding action \"{{value0}}\" was ignored.",
"d2e43e426a": "{{value0}} must be an object.",
- "fb290366b2": "Unavailable on web."
+ "fb290366b2": "Unavailable on web.",
+ "76122208ca": "Shortcut for \"{{value0}}\" was ignored: {{value1}}"
}
},
"runtime": {
@@ -742,7 +743,8 @@
"b0b09778c8": "Failed to add review comment.",
"16c1abe76c": "Mark viewed",
"ba8e329d92": "Unmark viewed",
- "3f79ffc8b7": "Open the PR details to view current reviewers."
+ "3f79ffc8b7": "Open the PR details to view current reviewers.",
+ "5c1c973855": "Remove reviewer"
},
"GitLabItemDialog": {
"65e784c1f1": "Reopen",
@@ -1158,7 +1160,8 @@
"19628e058d": "Failed to add review comment.",
"50b8fb290f": "Mark viewed",
"2b4fdb880c": "Unmark viewed",
- "56ec6eafb7": "Open the PR details to view current reviewers."
+ "56ec6eafb7": "Open the PR details to view current reviewers.",
+ "7f964a365a": "Remove reviewer"
},
"QuickOpen": {
"1dbd3f59ff": "Move",
@@ -1476,7 +1479,12 @@
"aec5feeb69": "Failed to create Jira issue.",
"7437e340b4": "Failed to create issue.",
"9e03c17847": "Open the PR details to view current reviewers.",
- "3b7f34282f": "closed"
+ "3b7f34282f": "closed",
+ "246bd64aed": "Open {{value0}} in Linear",
+ "ff90d0abc7": "Start workspace from {{value0}}",
+ "fe28c9821f": "view",
+ "8d1e17a3ef": "Open {{value0}} in GitHub",
+ "4ac8ff2275": "Open {{value0}} in Jira"
},
"Terminal": {
"73768427cf": "Close",
@@ -1504,7 +1512,7 @@
},
"UpdateCard": {
"68b235d264": "Restart to Update",
- "02d4b8a6b9": "is downloaded. Restart when you're ready.",
+ "6714206e5a": "Orca v{{value0}} is downloaded. Restart when you're ready.",
"93794ea932": "Orca v{{value0}} is downloading.",
"8acbdd3961": "Minimize to status bar",
"17412483da": "Ready to Install",
@@ -1517,7 +1525,7 @@
"ec8fe71cfc": "Update",
"44324ef542": "Release notes",
"fdd4a364fa": "Sessions won't be interrupted.",
- "c4890662e9": "is ready.",
+ "05ad78a6d1": "Orca v{{value0}} is ready.",
"318d3b4bc7": "Dismiss update",
"9abc59f814": "Update Available",
"aad383aecc": "Read the full release notes",
@@ -1997,7 +2005,10 @@
"bc43c37faf": "hidden",
"0c6672f5e3": "Ignored cleanup suggestions",
"fc49f79434": "mixed",
- "2ddbd6fe8a": "checked"
+ "2ddbd6fe8a": "checked",
+ "ee81adfcef": "View",
+ "4d0b72481c": "Ignore",
+ "9cc26c019d": "Remove"
}
}
},
@@ -2344,6 +2355,32 @@
"90eb94dc48": "Enter an http:// or https:// URL.",
"5553b283ce": "Enter a URL or file path."
}
+ },
+ "menu": {
+ "options": {
+ "5501c2fb7a": "terminal",
+ "9630dd5494": "shell",
+ "a094576900": "new terminal",
+ "4f23f4d01d": "new shell",
+ "4f2a91e15b": "browser",
+ "6d0e6a4b7a": "new browser",
+ "c87ad57785": "browser tab",
+ "cce7ef1d2c": "web",
+ "5f17fb9d0c": "markdown",
+ "44caaf7b36": "md",
+ "fb50e3d874": "new markdown",
+ "6d8b6b4117": "new file",
+ "b330f72434": "mark",
+ "37ff3ddca1": "open markdown",
+ "164c394bab": "open file",
+ "bbaf4f85a4": "mobile emulator",
+ "3784b83bd4": "emulator",
+ "a63847a742": "simulator",
+ "1baeb07c17": "ios simulator",
+ "8a580f88cf": "iphone",
+ "7ecdc5ef08": "ipad",
+ "14965cc123": "mobile"
+ }
}
}
}
@@ -2372,29 +2409,31 @@
"PortsStatusSegment": {
"4ebf90c12e": "No external ports detected",
"7dac3ecc9d": "External Ports",
- "95495019ed": "Port scan unavailable on",
+ "95495019ed": "Port scan unavailable on {{value0}}: {{value1}}",
"a8e4bdb412": " · {{value0}} external",
"9aa11005bf": "workspace ·",
"c22ea609fd": "Ports",
"a11ed266ce": "workspace",
- "ca41be2802": "Ports —",
+ "ca41be2802": "Ports — {{value0}} workspace {{value1}}{{value2}}",
"b8bc3e420a": "Ports, {{value0}} workspace {{value1}}",
"3a87d54dfb": "No workspace ports detected",
"c174bbbfed": "Scanning for workspace ports...",
"8caaa86e9a": "ports",
- "45834a9ace": "port"
+ "45834a9ace": "port",
+ "4ae65d871a": "external",
+ "2b84c4d11f": "{{value0}} workspace · {{value1}} external"
},
"ResourceUsageStatusSegment": {
"946d9f94d0": "Cancel",
"67c4ecda49": "Force-quits this terminal. Any unsaved work in the pane is lost. This can't be undone.",
"4bb076fa89": "Kill",
"996295bff2": "orphan terminal",
- "92924a14e3": "Review inactive workspaces (",
+ "92924a14e3": "Review inactive workspaces ({{value0}})",
"27a74f91f0": "Nothing running right now",
"1b24a32d3a": "Memory",
"298f4be7f2": "CPU",
"2aa2de6cb9": "Name",
- "30ff2c3c31": "orphan",
+ "30ff2c3c31": "{{value0}} orphan",
"6449a95c78": "How much of this machine's physical RAM the Orca-tracked processes are sitting on.",
"e7ccce7e87": "of system RAM",
"9e2525c89f": "Resident memory held by Orca plus the processes under each worktree's terminals.",
@@ -2429,7 +2468,12 @@
"16bc3c998a": "Delete workspace {{value0}}",
"0f9e50eb07": "Other",
"d406915b78": "Renderer",
- "81cd37af99": "Main"
+ "81cd37af99": "Main",
+ "fa6d36758d": "Kill session {{value0}}",
+ "b8f4a2c1d0e3": "{{value0}} orphans",
+ "c7e3b1a0d9f2": "Kill {{value0}} orphan terminal",
+ "d8f4c2b1e0a3": "Kill {{value0}} orphan terminals",
+ "e9a5d3c2b1f0": "Kill {{value0}}?"
},
"SshStatusSegment": {
"3ad70e0365": "Manage SSH…",
@@ -2505,7 +2549,8 @@
"962404f68e": "Update ready to install. Click to expand.",
"248ee5d8ef": "Orca v{{value0}} downloading… {{value1}}%",
"57a29c3b0e": "Update ready",
- "fd1d3b3a1d": "Update downloading, {{value0}} percent. Click to expand."
+ "fd1d3b3a1d": "Update downloading, {{value0}} percent. Click to expand.",
+ "9d13213a56": "Orca v{{value0}} ready to install"
},
"WorkspaceSpaceCompactPanel": {
"a471aa9c24": "Updated",
@@ -2597,7 +2642,8 @@
"c5135e7e4a": "Scanning workspace sizes. You can leave this page.",
"0990a63160": "No scanned workspace sizes yet.",
"977bdf9a36": "No top-level items to show.",
- "131662ac65": "{{value0}} open"
+ "131662ac65": "{{value0}} open",
+ "0d1c78d749": "Select {{value0}}"
},
"ports": {
"status": {
@@ -2878,7 +2924,11 @@
"0015facc1f": "Cache",
"7f270458af": "Output",
"9365b14a4e": "New input",
- "3de9bf87fc": "No model yet"
+ "3de9bf87fc": "No model yet",
+ "6762f6a682": "tokens",
+ "a7f937fb29": "{{value0}} sessions - {{value1}} {{value2}}",
+ "c8f3a2d1e0b4": "turns",
+ "d9a4b3e2f1c5": "events"
}
}
}
@@ -3371,7 +3421,7 @@
"ccbd1e2c69": "Customize {{value0}} appearance"
},
"WorktreeCard": {
- "a88c92d0e3": "already exists.",
+ "a88c92d0e3": "{{value0}}/{{value1}} already exists.",
"6f09f58541": "Delete workspace",
"0777de5970": "Primary worktree (original clone directory)",
"0f33af979b": "Partial checkout. Files outside these paths are not on disk.",
@@ -3485,7 +3535,12 @@
"84a2238242": "Show child workspaces",
"045a8aed48": "children",
"2ca6e29a3c": "repo",
- "bb85cd86ba": "Create workspace for {{value0}}"
+ "bb85cd86ba": "Create workspace for {{value0}}",
+ "ebadb7eadb": "{{value0}} {{value1}} child {{value2}}",
+ "20bebf9c7f": "Show {{value0}} child workspace",
+ "c1f4a31623": "Show {{value0}} child workspaces",
+ "e97297cb75": "Hide {{value0}} child workspace",
+ "0cd15956d4": "Hide {{value0}} child workspaces"
},
"WorktreeMetaDialog": {
"3db0a2a593": "Cancel",
@@ -3704,7 +3759,12 @@
"fe2ab66d45": "Killed {{value0}} of {{value1}} sessions. {{value2}} refused to exit.",
"d762b41f41": "Restart failed.",
"b5954e12d3": "Restart failed — check logs.",
- "0e9da1b98e": "Daemon restarted."
+ "0e9da1b98e": "Daemon restarted.",
+ "d6372cc797": "Killed {{value0}} session{{value1}}.",
+ "87412c2a68": "Killed {{value0}} session.",
+ "a2f040ac1c": "Killed {{value0}} sessions.",
+ "63520148e2": "{{value0}} session refused to exit.",
+ "cc0a26cb14": "{{value0}} sessions refused to exit."
}
},
"setup": {
@@ -3812,7 +3872,9 @@
"b10cb4f696": "adding",
"e4a28e8894": "Codex reported that the {{value0}} login needs a fresh sign-in. Sign in again before starting new Codex sessions.",
"75ca9b718e": "Codex reported that the active account needs a fresh sign-in. Re-authenticate it before starting new Codex sessions.",
- "b11078a9c2": "wsl"
+ "b11078a9c2": "wsl",
+ "350b2a1aa7": "Use your current",
+ "e05d0ff737": "Use your current {{value0}} Claude login."
},
"AdvancedPane": {
"40b29e0bf3": "Restart",
@@ -4010,7 +4072,10 @@
"cdec84552f": "Import Cookies",
"796d846483": "No cookies imported",
"c29648fe5b": "Active",
- "d420c43729": "Imported {{value0}} cookies from {{value1}}{{value2}} into {{value3}}."
+ "d420c43729": "Imported {{value0}} cookies from {{value1}}{{value2}} into {{value3}}.",
+ "b4c167764d": "Imported {{value0}} cookies from file into {{value1}}.",
+ "a3f8c2d1e0b4": "Imported {{value0}} cookies from {{value1}} ({{value2}}) into {{value3}}.",
+ "b4e9d3f2a1c5": "Imported {{value0}} cookies from {{value1}} into {{value2}}."
},
"BrowserUseComputerUseNotice": {
"15b5e680ba": "Open Computer Use",
@@ -4055,7 +4120,8 @@
"de9b2f32f3": "Enable",
"ad8cb0ee22": "Fix PATH",
"0289434ed6": "Enabled",
- "8b3054dac7": "Registering..."
+ "8b3054dac7": "Registering...",
+ "8f2675c2f3": "Imported {{value0}} cookies from file."
},
"BrowserUseSkillStep": {
"0871b6998d": "Enables agents to navigate and verify pages in Orca's browser.",
@@ -5012,7 +5078,8 @@
"3595fd1948": "New Link",
"54dee18f5c": "Hide Form",
"8cf8790697": "Saved servers route this browser through a paired Orca runtime.",
- "f75ce1c7a5": "Local keeps today's desktop behavior. Saved servers route supported client calls through the remote runtime."
+ "f75ce1c7a5": "Local keeps today's desktop behavior. Saved servers route supported client calls through the remote runtime.",
+ "d25f0688b1": "Remove"
},
"RuntimePairingGeneratedUrlRows": {
"0495f68959": "Copy {{value0}}"
@@ -5231,7 +5298,7 @@
"a6fcdd9e3c": "Name",
"b9922ec194": "Cancel preset edit",
"694cc55ecb": "Saved directories are used when creating sparse worktrees for this repository.",
- "8b64731aaf": "more",
+ "8b64731aaf": "+{{value0}} more",
"755c6a1a0d": "Confirm",
"a7bcf206b1": "Deleting",
"ba9ad2d4cd": "Updated date unknown",
@@ -5243,7 +5310,8 @@
"3dfa765ca7": "{{value0}} directories will be saved.",
"b532b9c17d": "1 directory will be saved.",
"623b4cf910": "Edit Preset",
- "68bbcd864a": "new"
+ "68bbcd864a": "new",
+ "2ef2b2674b": "Delete {{value0}}"
},
"SshDestructiveActionDialog": {
"895b216267": "Cancel"
@@ -7180,7 +7248,7 @@
},
"CreatePullRequestDialog": {
"2bc1b4345e": "Cancel",
- "27ef4b195c": "Choose a different base branch before creating a",
+ "27ef4b195c": "Choose a different base branch before creating a {{value0}}.",
"7ef56f3efe": "Create as draft",
"0c9f9a568c": "Supports Markdown formatting. Use Generate with AI to auto-fill from your changes.",
"02b2ce911f": "Description (optional)",
@@ -7191,18 +7259,22 @@
"8584ccb43c": "Base branch",
"6f5f1962b6": "Head branch",
"b504b3ceb1": "details before creating the hosted review.",
- "f658ff2455": "Confirm the target branch and",
+ "f658ff2455": "Confirm the target branch and {{value0}} details before creating the hosted review.",
"b7f43474d7": "Create {{value0}}",
"7a21f0dae8": "Open on {{value0}}",
"edc35a7027": "{{value0}} #{{value1}} is already open",
- "a154fe55e6": "Push & Create {{value0}}"
+ "a154fe55e6": "Push & Create {{value0}}",
+ "21c7a1daa0": "{{value0}} is already open",
+ "db9cee18f7": "Create {{value0}}"
},
"CreatePullRequestGenerateButton": {
"4012459f8a": "Generate with AI",
"a0501572c1": "Generate {{value0}} details with AI",
- "d47fd63012": "details. Click to stop.",
+ "d47fd63012": "Generating {{value0}} details. Click to stop.",
+ "bdf83ccb15": "Generating {{value0}}",
"f5513bdeb1": "Generating",
"a6ea6dc3aa": "Generating…",
+ "e61d7e7ad4": "Stop generating {{value0}} details",
"e041998cad": "Stop generating"
},
"FileExplorer": {
@@ -7288,13 +7360,13 @@
"b950b1948b": "Local Port",
"9e5a4118b0": "Remote Port",
"c9d106547a": "Forward",
- "c7e920aa7c": "advertised as",
+ "c7e920aa7c": "advertised as {{value0}}",
"e740075063": "Remove",
"b3548e59f4": "Edit",
"fe2730d050": "Copy {{value0}}",
"b22b128b2a": "Open in Browser",
"75aeea592f": "Open {{value0}} in Browser",
- "de349d4560": "opens",
+ "de349d4560": "opens {{value0}}",
"907eb53ed2": "Forward a Port",
"04efd3dad4": "Forward a port to access remote services on your local machine.",
"1f0d2a24f9": "No forwarded ports",
@@ -7319,7 +7391,7 @@
"792baeb7ed": "Copy Address",
"d41a8241ec": "Port",
"a2a9fc6899": "No local ports detected",
- "f59c783b7a": "Port scan unavailable on",
+ "f59c783b7a": "Port scan unavailable on {{value0}}: {{value1}}",
"7822e3edc6": "Refresh Ports",
"c1b115c375": "No workspace selected",
"98e9a414f8": "Failed to open browser",
@@ -7341,7 +7413,10 @@
"38b16cfbef": "No ports detected",
"0d63d94db3": "Scanning...",
"935dda7718": "Active Workspace",
- "740aca88ab": "Workspace port scan failed."
+ "740aca88ab": "Workspace port scan failed.",
+ "5be4f7f727": "Port {{value0}} menu",
+ "7550998473": "Copy",
+ "1004af16ab": "Copy {{value0}}"
},
"Search": {
"1abfb25a66": "Type to search in files",
@@ -7409,7 +7484,7 @@
"dd43c47089": "Choose an agent for this commit failure",
"30b8d4f181": "Fix commit failure with AI",
"4b37ae99b0": "Start the default AI agent to fix this commit failure",
- "ae743199cd": "Choose a different base branch before creating a",
+ "ae743199cd": "Choose a different base branch before creating a {{value0}}.",
"c5e4175139": "More {{value0}} and remote actions",
"78ddfd0bb4": "Create as draft",
"e64a632456": "main",
@@ -7421,9 +7496,11 @@
"7d6a8f0082": "Title",
"a6eda33521": "{{value0}} title",
"02d8c04339": "Generate {{value0}} details with AI",
+ "aee92f8684": "Generate",
"e868cec4e1": "Generating…",
+ "b355e740b2": "Stop generating {{value0}} details",
"527e130b6f": "Stop generating",
- "e1970d327d": "New",
+ "e1970d327d": "New {{value0}}",
"f4c766f1ca": "Choose the agent and command template for this run.",
"1a6a6e0bc5": "Generate Hosted Review Details",
"6b122529d4": "Generate Commit Message",
@@ -7501,7 +7578,24 @@
"72f2bea3f4": "Expand notes",
"d13edef890": "Collapse notes",
"0fad573938": "Uncommitted",
- "77afaa8152": "All"
+ "77afaa8152": "All",
+ "d6fb1df5fe": "{{value0}} is already open",
+ "05838cfdeb": "{{value0}} conflict",
+ "d206117f90": "{{value0}} conflict ({{value1}})",
+ "0b5b8c234c": "Open {{value0}} ({{value1}})",
+ "d97ef8f221": "lines {{value0}}-{{value1}}",
+ "6f8bfa0eb9": "line {{value0}}",
+ "c569d29a02": "both modified",
+ "ea7287d84f": "both added",
+ "bd0151ef7b": "deleted by us",
+ "44594e8c61": "deleted by them",
+ "24773ee581": "added by us",
+ "c03d7c952f": "added by them",
+ "5b176fa431": "both deleted",
+ "31f6d46278": "Unresolved",
+ "2c417432b7": "Resolved locally",
+ "f3a8b2c1d0e5": "Enter a {{value0}} title.",
+ "e2b7a1c0d9f4": "Failed to create {{value0}}"
},
"SourceControlAgentActionDialog": {
"8e856842d1": "Could not start the selected agent.",
@@ -7808,6 +7902,17 @@
},
"GitHistoryGraphSvg": {
"47eff48230": "HEAD"
+ },
+ "create": {
+ "pull": {
+ "request": {
+ "review": {
+ "copy": {
+ "a1f8c3d2e4": "Push succeeded, but {{value0}} creation failed: {{value1}}"
+ }
+ }
+ }
+ }
}
}
},
@@ -8281,7 +8386,8 @@
"648352c51f": "Open {{value0}} in floating workspace",
"82da3701e7": "Could not build launch command for {{value0}}.",
"109870e023": "Maximize",
- "b5686fee1e": "Restore"
+ "b5686fee1e": "Restore",
+ "1e502f1284": "Open"
}
}
},
@@ -8643,6 +8749,18 @@
"ReviewAnimatedVisual": {
"8df4d52b68": "pr-view",
"8ab622e4d6": "notes"
+ },
+ "FeatureWallBrowserAction": {
+ "5022c43a88": "Browser could not open",
+ "c9eb68b474": "No workspace group is available for this worktree yet.",
+ "c9728107c5": "Try it out",
+ "25dd101f15": "Browser setup needs attention",
+ "e02b11e6b0": "Browser setup ready",
+ "d6d15077df": "Skill command copied and inserted below for review.",
+ "78e65f19d9": "Browser setup failed",
+ "b7345c18db": "An unexpected error occurred.",
+ "5f97caf76b": "Installing…",
+ "c2df599513": "Install CLI & Skill"
}
},
"tips": {
@@ -9368,7 +9486,8 @@
"e52a955e6f": "You can always find this in Settings > Browser.",
"4f5ffaa6a1": "Import browser data",
"b24fef25be": "Import",
- "02e89014c5": "Imported {{value0}} cookies from {{value1}}{{value2}}."
+ "02e89014c5": "Imported {{value0}} cookies from {{value1}}{{value2}}.",
+ "d40d584769": "Imported {{value0}} cookies from file."
},
"BrowserMobileDriverOverlay": {
"a6914ee43f": "Take back",
@@ -9445,7 +9564,12 @@
"31375046b7": "Download from {{value0}}",
"acbe79fd01": "Grab page element ({{value0}})",
"572046436a": "Remote browser",
- "b313a7275b": "Opening remote browser"
+ "b313a7275b": "Opening remote browser",
+ "5f66313863": "annotation",
+ "ea6af700da": "{{value0}} annotation",
+ "c13693fe27": "{{value0}} annotations",
+ "074f0ed10b": "{{value0}} annotation ready. Select another element or copy all feedback.",
+ "a2164a6e5a": "{{value0}} annotations ready. Select another element or copy all feedback."
},
"BrowserToolbarMenu": {
"429ef481f9": "Cancel",
@@ -9458,7 +9582,7 @@
"ed8f54509d": "Default",
"e5d31de1a9": "Viewport Size",
"56f94f4ffa": "From File…",
- "eb280bfb11": "From",
+ "eb280bfb11": "From {{value0}}",
"2293adf620": "Import Cookies",
"cf7cdc67ef": "New Profile…",
"7b838540c7": "Browser menu",
@@ -9467,7 +9591,10 @@
"4d2f9f13a7": "Failed to create profile.",
"3ccd29d771": "Switched to {{value0}} profile",
"569bce8eb1": "Create",
- "bf648471c5": "Creating…"
+ "bf648471c5": "Creating…",
+ "53bbe3dab4": "Imported {{value0}} cookies from file.",
+ "c5f0e4d3b2a1": "Imported {{value0}} cookies from {{value1}} ({{value2}}).",
+ "d6a1f5e4c3b2": "Imported {{value0}} cookies from {{value1}}."
},
"GrabConfirmationSheet": {
"314a0aaa5b": "Attach to AI",
@@ -9839,6 +9966,20 @@
"56f5c60e0c": "Cancel"
}
}
+ },
+ "i18n": {
+ "hostedReview": {
+ "copy": {
+ "f0a4b8c2d1": "PR",
+ "e9f3a7b1c0": "pull request",
+ "d8e2f6a0b9": "Pull Request",
+ "c7d1e5f9a8": "GitHub",
+ "c4e8f1a2b9": "MR",
+ "b3d7e0f1a8": "merge request",
+ "a2c6d9e0f7": "Merge Request",
+ "91b5c8d7e6": "GitLab"
+ }
+ }
}
}
}
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
index dfdae89d5a7..d07fee65646 100644
--- a/src/renderer/src/i18n/locales/ja.json
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -144,7 +144,8 @@
"10898045f3": "「{{value0}}」のショートカットは無視されました: 文字列配列を使用してください。",
"36761d9604": "不明なキーバインド 操作「{{value0}}」は無視されました。",
"d2e43e426a": "{{value0}} はオブジェクトでなければなりません。",
- "fb290366b2": "ウェブでは利用できません。"
+ "fb290366b2": "ウェブでは利用できません。",
+ "76122208ca": "「{{value0}}」のショートカットは無視されました: {{value1}}"
}
},
"runtime": {
@@ -742,7 +743,8 @@
"b0b09778c8": "レビューコメントの追加に失敗しました。",
"16c1abe76c": "閲覧済みとしてマークする",
"ba8e329d92": "閲覧済みのマークを外す",
- "3f79ffc8b7": "PR の詳細を開いて、現在のレビュアーを表示します。"
+ "3f79ffc8b7": "PR の詳細を開いて、現在のレビュアーを表示します。",
+ "5c1c973855": "レビュアーを削除"
},
"GitLabItemDialog": {
"65e784c1f1": "再度開く",
@@ -1158,7 +1160,8 @@
"19628e058d": "レビューコメントの追加に失敗しました。",
"50b8fb290f": "閲覧済みとしてマークする",
"2b4fdb880c": "閲覧済みのマークを外す",
- "56ec6eafb7": "PR の詳細を開いて、現在のレビュアーを表示します。"
+ "56ec6eafb7": "PR の詳細を開いて、現在のレビュアーを表示します。",
+ "7f964a365a": "レビュアーを削除"
},
"QuickOpen": {
"1dbd3f59ff": "動く",
@@ -1476,7 +1479,12 @@
"aec5feeb69": "Jira イシューの作成に失敗しました。",
"7437e340b4": "イシューの作成に失敗しました。",
"9e03c17847": "PR の詳細を開いて、現在のレビュアーを表示します。",
- "3b7f34282f": "閉まっている"
+ "3b7f34282f": "閉まっている",
+ "246bd64aed": "{{value0}} を Linear で開く",
+ "ff90d0abc7": "{{value0}} からワークスペースを開始",
+ "fe28c9821f": "view",
+ "8d1e17a3ef": "{{value0}} を GitHub で開く",
+ "4ac8ff2275": "{{value0}} を Jira で開く"
},
"Terminal": {
"73768427cf": "閉じる",
@@ -1504,7 +1512,7 @@
},
"UpdateCard": {
"68b235d264": "再起動してアップデートする",
- "02d4b8a6b9": "ダウンロードされます。準備ができたら再起動します。",
+ "6714206e5a": "Orca v{{value0}} がダウンロードされました。準備ができたら再起動してください。",
"93794ea932": "Orca v{{value0}} をダウンロードしています。",
"8acbdd3961": "ステータスバーに最小化する",
"17412483da": "インストール可能",
@@ -1517,7 +1525,7 @@
"ec8fe71cfc": "アップデート",
"44324ef542": "リリースノート",
"fdd4a364fa": "セッションは中断されません。",
- "c4890662e9": "準備ができています。",
+ "05ad78a6d1": "Orca v{{value0}} の準備ができています。",
"318d3b4bc7": "更新を閉じる",
"9abc59f814": "利用可能なアップデート",
"aad383aecc": "リリースノート全文を読む",
@@ -1997,7 +2005,10 @@
"bc43c37faf": "隠れた",
"0c6672f5e3": "クリーンアップの提案が無視されました",
"fc49f79434": "混合された",
- "2ddbd6fe8a": "チェック済み"
+ "2ddbd6fe8a": "チェック済み",
+ "ee81adfcef": "表示",
+ "4d0b72481c": "無視",
+ "9cc26c019d": "削除"
}
}
},
@@ -2344,6 +2355,32 @@
"90eb94dc48": "http:// または https:// URL を入力します。",
"5553b283ce": "URL またはファイル パスを入力します。"
}
+ },
+ "menu": {
+ "options": {
+ "5501c2fb7a": "terminal",
+ "9630dd5494": "shell",
+ "a094576900": "new terminal",
+ "4f23f4d01d": "new shell",
+ "4f2a91e15b": "browser",
+ "6d0e6a4b7a": "new browser",
+ "c87ad57785": "browser tab",
+ "cce7ef1d2c": "web",
+ "5f17fb9d0c": "markdown",
+ "44caaf7b36": "md",
+ "fb50e3d874": "new markdown",
+ "6d8b6b4117": "new file",
+ "b330f72434": "mark",
+ "37ff3ddca1": "open markdown",
+ "164c394bab": "open file",
+ "bbaf4f85a4": "mobile emulator",
+ "3784b83bd4": "emulator",
+ "a63847a742": "simulator",
+ "1baeb07c17": "ios simulator",
+ "8a580f88cf": "iphone",
+ "7ecdc5ef08": "ipad",
+ "14965cc123": "mobile"
+ }
}
}
}
@@ -2372,29 +2409,31 @@
"PortsStatusSegment": {
"4ebf90c12e": "外部ポートが検出されませんでした",
"7dac3ecc9d": "外部ポート",
- "95495019ed": "ポートスキャンは使用できません",
+ "95495019ed": "{{value0}} ではポートスキャンを利用できません: {{value1}}",
"a8e4bdb412": "· {{value0}} 外部",
"9aa11005bf": "ワークスペース・",
"c22ea609fd": "ポート",
"a11ed266ce": "ワークスペース",
- "ca41be2802": "ポート —",
+ "ca41be2802": "ポート — {{value0}} ワークスペース {{value1}}{{value2}}",
"b8bc3e420a": "ポート、{{value0}} ワークスペース {{value1}}",
"3a87d54dfb": "ワークスペースポートが検出されませんでした",
"c174bbbfed": "ワークスペースポートをスキャンしています...",
"8caaa86e9a": "ポート",
- "45834a9ace": "ポート"
+ "45834a9ace": "ポート",
+ "4ae65d871a": "外部",
+ "2b84c4d11f": "{{value0}} ワークスペース · {{value1}} 外部"
},
"ResourceUsageStatusSegment": {
"946d9f94d0": "キャンセル",
"67c4ecda49": "このターミナルを強制終了します。ペイン内の保存されていない作業はすべて失われます。これを元に戻すことはできません。",
"4bb076fa89": "強制終了",
"996295bff2": "孤立したターミナル",
- "92924a14e3": "非アクティブなワークスペースを確認する (",
+ "92924a14e3": "非アクティブなワークスペースを確認 ({{value0}})",
"27a74f91f0": "現在何も実行されていません",
"1b24a32d3a": "メモリ",
"298f4be7f2": "CPU",
"2aa2de6cb9": "名前",
- "30ff2c3c31": "孤児",
+ "30ff2c3c31": "{{value0}} 件の孤立",
"6449a95c78": "Orca が追跡するプロセスがこのマシンの物理 RAM にどれだけの量を配置しているか。",
"e7ccce7e87": "システムRAMの",
"9e2525c89f": "Orca が保持する常駐メモリと各ワークツリーのターミナル下のプロセス。",
@@ -2429,7 +2468,12 @@
"16bc3c998a": "ワークスペース {{value0}} を削除",
"0f9e50eb07": "他の",
"d406915b78": "レンダラー",
- "81cd37af99": "主要"
+ "81cd37af99": "主要",
+ "fa6d36758d": "セッション {{value0}} を強制終了",
+ "b8f4a2c1d0e3": "{{value0}} 件の孤立",
+ "c7e3b1a0d9f2": "孤立したターミナル {{value0}} 件を終了",
+ "d8f4c2b1e0a3": "孤立したターミナル {{value0}} 件を終了",
+ "e9a5d3c2b1f0": "{{value0}} を終了しますか?"
},
"SshStatusSegment": {
"3ad70e0365": "SSHを管理…",
@@ -2505,7 +2549,8 @@
"962404f68e": "アップデートをインストールする準備ができました。クリックして展開します。",
"248ee5d8ef": "Orca v{{value0}} ダウンロード中… {{value1}}%",
"57a29c3b0e": "アップデートの準備ができました",
- "fd1d3b3a1d": "アップデートのダウンロード、{{value0}} パーセント。クリックして展開します。"
+ "fd1d3b3a1d": "アップデートのダウンロード、{{value0}} パーセント。クリックして展開します。",
+ "9d13213a56": "Orca v{{value0}} をインストールする準備ができました"
},
"WorkspaceSpaceCompactPanel": {
"a471aa9c24": "更新されました",
@@ -2597,7 +2642,8 @@
"c5135e7e4a": "ワークスペースのサイズをスキャンしています。このページから離れても構いません。",
"0990a63160": "スキャンされたワークスペースのサイズはまだありません。",
"977bdf9a36": "表示するトップレベルの項目はありません。",
- "131662ac65": "{{value0}} オープン"
+ "131662ac65": "{{value0}} オープン",
+ "0d1c78d749": "{{value0}} を選択"
},
"ports": {
"status": {
@@ -2878,7 +2924,11 @@
"0015facc1f": "キャッシュ",
"7f270458af": "出力",
"9365b14a4e": "新規入力",
- "3de9bf87fc": "まだモデルがありません"
+ "3de9bf87fc": "まだモデルがありません",
+ "6762f6a682": "トークン",
+ "a7f937fb29": "{{value0}} セッション - {{value1}} {{value2}}",
+ "c8f3a2d1e0b4": "ターン",
+ "d9a4b3e2f1c5": "イベント"
}
}
}
@@ -3013,12 +3063,12 @@
"0f8aba944c": "ディレクトリに移動し、「選択」をクリックして選択します。"
},
"AddRepoStartSteps": {
- "f3c96237ae": "または…から追加します",
"acf895cb42": "Orca の使用を開始するには、プロジェクトを追加します。",
"d13757911c": "プロジェクトを追加する",
"d301db1c9a": "リポジトリをスキャンしています。クリックして停止します。",
"69ea7f8dc4": "スキャンを停止する",
- "9906cae183": "スキャンの停止"
+ "9906cae183": "スキャンの停止",
+ "87596c1446": "その他の追加方法"
},
"AddRepoStepIndicator": {
"3bb655c117": "戻る"
@@ -3354,7 +3404,7 @@
"ccbd1e2c69": "{{value0}} の外観をカスタマイズする"
},
"WorktreeCard": {
- "a88c92d0e3": "すでに存在します。",
+ "a88c92d0e3": "{{value0}}/{{value1}} はすでに存在します。",
"6f09f58541": "ワークスペースの削除",
"0777de5970": "プライマリ ワークツリー (元のクローン ディレクトリ)",
"0f33af979b": "部分的なチェックアウト。これらのパスの外にあるファイルはディスク上にありません。",
@@ -3468,7 +3518,12 @@
"84a2238242": "子ワークスペースを表示する",
"045a8aed48": "子供たち",
"2ca6e29a3c": "リポジトリ",
- "bb85cd86ba": "{{value0}} のワークスペースを作成する"
+ "bb85cd86ba": "{{value0}} のワークスペースを作成する",
+ "ebadb7eadb": "{{value0}} {{value1}} child {{value2}}",
+ "20bebf9c7f": "{{value0}} 個の子ワークスペースを表示",
+ "c1f4a31623": "{{value0}} 個の子ワークスペースを表示",
+ "e97297cb75": "{{value0}} 個の子ワークスペースを非表示",
+ "0cd15956d4": "{{value0}} 個の子ワークスペースを非表示"
},
"WorktreeMetaDialog": {
"3db0a2a593": "キャンセル",
@@ -3672,6 +3727,23 @@
},
"index": {
"b826a98b6f": "忙しい"
+ },
+ "local": {
+ "base": {
+ "ref": {
+ "suggestion": {
+ "toast": {
+ "670864ab52": "ローカル {{value0}} を最新の状態に保つ",
+ "84c62e4d7f": "Could not turn on {{value0}}",
+ "442552c656": "Open Settings and try again.",
+ "f15fd80989": "Your new worktree is current, but local {{value0}} is {{value1}} {{value2}} behind, so AI diffs may compare to stale history. Let Orca keep it up to date automatically. Change this anytime in",
+ "3d260e1a5d": "Settings › {{value0}}",
+ "34a03a6565": "Keep {{value0}} up to date",
+ "4a18052018": "Local {{value0}} is behind {{value1}}"
+ }
+ }
+ }
+ }
}
},
"shared": {
@@ -3687,7 +3759,12 @@
"fe2ab66d45": "{{value1}} セッション中 {{value0}} を強制終了しました。 {{value2}} は退出を拒否しました。",
"d762b41f41": "再起動に失敗しました。",
"b5954e12d3": "再起動に失敗しました - ログを確認してください。",
- "0e9da1b98e": "デーモンが再起動されました。"
+ "0e9da1b98e": "デーモンが再起動されました。",
+ "d6372cc797": "{{value0}} 件のセッションを終了しました{{value1}}。",
+ "87412c2a68": "{{value0}} 個のセッションを終了しました。",
+ "a2f040ac1c": "{{value0}} 個のセッションを終了しました。",
+ "63520148e2": "{{value0}} 個のセッションが終了を拒否しました。",
+ "cc0a26cb14": "{{value0}} 個のセッションが終了を拒否しました。"
}
},
"setup": {
@@ -3780,7 +3857,9 @@
"b10cb4f696": "追加する",
"e4a28e8894": "Codex は、{{value0}} ログインには新たなサインインが必要であると報告しました。新規 Codex セッションを開始する前に、再度サインインします。",
"75ca9b718e": "Codex は、アクティブなアカウントには新たにサインインする必要があると報告しました。新規 Codex セッションを開始する前に、再認証してください。",
- "b11078a9c2": "wsl"
+ "b11078a9c2": "wsl",
+ "350b2a1aa7": "Use your current",
+ "e05d0ff737": "現在の {{value0}} Claude ログインを使用します。"
},
"AdvancedPane": {
"40b29e0bf3": "再起動",
@@ -3978,7 +4057,10 @@
"cdec84552f": "Cookieのインポート",
"796d846483": "Cookie はインポートされません",
"c29648fe5b": "アクティブ",
- "d420c43729": "{{value0}} Cookie を {{value1}}{{value2}} から {{value3}} にインポートしました。"
+ "d420c43729": "{{value0}} Cookie を {{value1}}{{value2}} から {{value3}} にインポートしました。",
+ "b4c167764d": "ファイルから {{value0}} 個の Cookie を {{value1}} にインポートしました。",
+ "a3f8c2d1e0b4": "{{value1}} ({{value2}}) から {{value0}} 件の Cookie を {{value3}} にインポートしました。",
+ "b4e9d3f2a1c5": "{{value1}} から {{value0}} 件の Cookie を {{value2}} にインポートしました。"
},
"BrowserUseComputerUseNotice": {
"15b5e680ba": "Open Computer Use",
@@ -4023,7 +4105,8 @@
"de9b2f32f3": "有効化",
"ad8cb0ee22": "パスを修正する",
"0289434ed6": "有効",
- "8b3054dac7": "登録中..."
+ "8b3054dac7": "登録中...",
+ "8f2675c2f3": "ファイルから {{value0}} 個の Cookie をインポートしました。"
},
"BrowserUseSkillStep": {
"0871b6998d": "エージェントが Orca のブラウザでページに移動して確認できるようにします。",
@@ -4980,7 +5063,8 @@
"3595fd1948": "新規リンク",
"54dee18f5c": "フォームを隠す",
"8cf8790697": "保存されたサーバーは、ペアになった Orca ランタイムを介してこのブラウザーをルーティングします。",
- "f75ce1c7a5": "ローカルでは、現在のデスクトップの動作が維持されます。保存されたサーバーは、サポートされているクライアント呼び出しをリモート ランタイム経由でルーティングします。"
+ "f75ce1c7a5": "ローカルでは、現在のデスクトップの動作が維持されます。保存されたサーバーは、サポートされているクライアント呼び出しをリモート ランタイム経由でルーティングします。",
+ "d25f0688b1": "削除"
},
"RuntimePairingGeneratedUrlRows": {
"0495f68959": "{{value0}}をコピー"
@@ -5199,7 +5283,7 @@
"a6fcdd9e3c": "名前",
"b9922ec194": "プリセット編集をキャンセルする",
"694cc55ecb": "保存されたディレクトリは、このリポジトリのスパース ワークツリーを作成するときに使用されます。",
- "8b64731aaf": "もっと",
+ "8b64731aaf": "他 +{{value0}} 件",
"755c6a1a0d": "確認する",
"a7bcf206b1": "削除中",
"ba9ad2d4cd": "更新日不明",
@@ -5211,7 +5295,8 @@
"3dfa765ca7": "{{value0}} ディレクトリが保存されます。",
"b532b9c17d": "1つのディレクトリが保存されます。",
"623b4cf910": "プリセットの編集",
- "68bbcd864a": "新規"
+ "68bbcd864a": "新規",
+ "2ef2b2674b": "{{value0}} を削除"
},
"SshDestructiveActionDialog": {
"895b216267": "キャンセル"
@@ -7107,6 +7192,21 @@
"agent-generated-tab-title-copy": {
"19ad21615a": "タブタイトルを自動生成",
"b036c7a409": "最初に判明したエージェントのプロンプトから、短く安定したタブ名を生成します。手動での名前変更が常に優先されます。"
+ },
+ "keep": {
+ "local": {
+ "main": {
+ "up": {
+ "to": {
+ "date": {
+ "setting": {
+ "f8bda25f29": "Keep Local Main Up to Date"
+ }
+ }
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -7148,7 +7248,7 @@
},
"CreatePullRequestDialog": {
"2bc1b4345e": "キャンセル",
- "27ef4b195c": "を作成する前に、別のベース ブランチを選択。",
+ "27ef4b195c": "{{value0}} を作成する前に別のベースブランチを選択してください。",
"7ef56f3efe": "下書きとして作成",
"0c9f9a568c": "マークダウン形式をサポートします。 AI を使用して生成を使用して、変更内容を自動入力します。",
"02b2ce911f": "説明 (オプション)",
@@ -7159,18 +7259,22 @@
"8584ccb43c": "ベースブランチ",
"6f5f1962b6": "本ブランチ",
"b504b3ceb1": "ホストされたレビューを作成する前に詳細を確認してください。",
- "f658ff2455": "対象のブランチを確認し、",
+ "f658ff2455": "ホストされたレビューを作成する前に、ターゲットブランチと {{value0}} の詳細を確認してください。",
"b7f43474d7": "{{value0}} を作成する",
"7a21f0dae8": "{{value0}}にオープン",
"edc35a7027": "{{value0}} #{{value1}} はすでにオープンしています",
- "a154fe55e6": "プッシュして{{value0}}を作成"
+ "a154fe55e6": "プッシュして{{value0}}を作成",
+ "21c7a1daa0": "{{value0}} はすでに開いています",
+ "db9cee18f7": "{{value0}} を作成"
},
"CreatePullRequestGenerateButton": {
"4012459f8a": "AIで生成",
"a0501572c1": "AI を使用して {{value0}} の詳細を生成する",
- "d47fd63012": "詳細。クリックして停止します。",
+ "d47fd63012": "{{value0}} の詳細を生成中です。クリックして停止します。",
+ "bdf83ccb15": "{{value0}} を生成中",
"f5513bdeb1": "生成中",
"a6ea6dc3aa": "生成中…",
+ "e61d7e7ad4": "{{value0}} の詳細生成を停止する",
"e041998cad": "生成を停止する"
},
"FileExplorer": {
@@ -7256,13 +7360,13 @@
"b950b1948b": "ローカルポート",
"9e5a4118b0": "リモートポート",
"c9d106547a": "フォワード",
- "c7e920aa7c": "として宣伝される",
+ "c7e920aa7c": "{{value0}} として公開",
"e740075063": "削除",
"b3548e59f4": "編集",
"fe2730d050": "{{value0}}をコピー",
"b22b128b2a": "ブラウザで開く",
"75aeea592f": "ブラウザで{{value0}}を開く",
- "de349d4560": "開く",
+ "de349d4560": "{{value0}} を開く",
"907eb53ed2": "ポートを転送する",
"04efd3dad4": "ローカル マシン上のリモート サービスにアクセスするためにポートを転送します。",
"1f0d2a24f9": "転送ポートなし",
@@ -7287,7 +7391,7 @@
"792baeb7ed": "アドレスをコピーする",
"d41a8241ec": "ポート",
"a2a9fc6899": "ローカルポートが検出されませんでした",
- "f59c783b7a": "ポートスキャンは使用できません",
+ "f59c783b7a": "{{value0}} ではポートスキャンを利用できません: {{value1}}",
"7822e3edc6": "ポートのリフレッシュ",
"c1b115c375": "ワークスペースが選択されていません",
"98e9a414f8": "ブラウザを開けませんでした",
@@ -7309,7 +7413,10 @@
"38b16cfbef": "ポートが検出されませんでした",
"0d63d94db3": "走査...",
"935dda7718": "アクティブなワークスペース",
- "740aca88ab": "ワークスペースのポートスキャンに失敗しました。"
+ "740aca88ab": "ワークスペースのポートスキャンに失敗しました。",
+ "5be4f7f727": "ポート {{value0}} メニュー",
+ "7550998473": "コピー",
+ "1004af16ab": "{{value0}}をコピー"
},
"Search": {
"1abfb25a66": "ファイル内を検索するために入力します",
@@ -7377,7 +7484,7 @@
"dd43c47089": "このコミット失敗に対するエージェントを選択",
"30b8d4f181": "AI によるコミット失敗の修正",
"4b37ae99b0": "デフォルトの AI エージェントを開始して、このコミットの失敗を修正します",
- "ae743199cd": "を作成する前に、別のベース ブランチを選択。",
+ "ae743199cd": "{{value0}} を作成する前に別のベースブランチを選択してください。",
"c5e4175139": "その他の {{value0}} とリモート操作",
"78ddfd0bb4": "下書きとして作成",
"e64a632456": "主要",
@@ -7389,9 +7496,11 @@
"7d6a8f0082": "タイトル",
"a6eda33521": "{{value0}} タイトル",
"02d8c04339": "AI を使用して {{value0}} の詳細を生成する",
+ "aee92f8684": "生成",
"e868cec4e1": "生成中…",
+ "b355e740b2": "{{value0}} の詳細生成を停止する",
"527e130b6f": "生成を停止する",
- "e1970d327d": "新規",
+ "e1970d327d": "新しい {{value0}}",
"f4c766f1ca": "この実行用のエージェントとコマンド テンプレートを選択します。",
"1a6a6e0bc5": "ホストされたレビューの詳細を生成する",
"6b122529d4": "コミットメッセージの生成",
@@ -7469,17 +7578,34 @@
"72f2bea3f4": "ノートを展開する",
"d13edef890": "メモを折りたたむ",
"0fad573938": "コミットされていない",
- "77afaa8152": "全て"
+ "77afaa8152": "全て",
+ "d6fb1df5fe": "{{value0}} はすでに開いています",
+ "05838cfdeb": "{{value0}} コンフリクト",
+ "0b5b8c234c": "{{value0}} ({{value1}}) を開く",
+ "d97ef8f221": "{{value0}}-{{value1}} 行",
+ "6f8bfa0eb9": "{{value0}} 行",
+ "c569d29a02": "双方で変更",
+ "ea7287d84f": "双方で追加",
+ "bd0151ef7b": "こちらで削除",
+ "44594e8c61": "相手側で削除",
+ "24773ee581": "こちらで追加",
+ "c03d7c952f": "相手側で追加",
+ "5b176fa431": "双方で削除",
+ "31f6d46278": "未解決",
+ "2c417432b7": "ローカルで解決済み",
+ "d206117f90": "{{value0}} コンフリクト ({{value1}})",
+ "f3a8b2c1d0e5": "{{value0}} のタイトルを入力してください。",
+ "e2b7a1c0d9f4": "{{value0}} の作成に失敗しました"
},
"SourceControlAgentActionDialog": {
"8e856842d1": "選択したエージェントを開始できませんでした。",
"c075d00de1": "ワークスペース接続を解決できません。",
"808cfe0a3b": "このリポジトリのみに保存",
- "994cddd1f7": "保存しないでください"
+ "994cddd1f7": "保存しないでください",
+ "38b899cc02": "すべてのリポジトリ"
},
"SourceControlAgentActionDialogForm": {
"1bc0bdbb5e": "起動:",
- "f84657c925": "起動レシピの保存",
"7ec6abbf2a": "リセット",
"f4f3c9ca4a": "コマンドテンプレート",
"fe119187bb": "--モデルソネット",
@@ -7489,7 +7615,15 @@
"3e8f21954f": "エラー",
"74168d7ada": "idle",
"1d47db9bf0": "有効なエージェントがありません",
- "c7ff8cef11": "エージェントを検出中..."
+ "c7ff8cef11": "エージェントを検出中...",
+ "013c9ac04a": "保存対象",
+ "1bb611240f": "Use {basePrompt} for Orca's default prompt.",
+ "23280cbab1": "This template does not include {basePrompt}, so the agent will not receive Orca's default prompt.",
+ "5421a96acb": "保存してエージェントを開始",
+ "6cefcdfba1": "You can change it later in Source Control AI settings.",
+ "c29f9cf266": "Save this prompt and don't show this review next time",
+ "d8f40128ee": "{basePrompt} is Orca's default prompt.",
+ "ea4788705e": "Cancel"
},
"SourceControlTextGenerationDialog": {
"c5b7fa7cb6": "グローバルデフォルトとして保存",
@@ -7768,6 +7902,17 @@
},
"GitHistoryGraphSvg": {
"47eff48230": "頭"
+ },
+ "create": {
+ "pull": {
+ "request": {
+ "review": {
+ "copy": {
+ "a1f8c3d2e4": "プッシュは成功しましたが、{{value0}} の作成に失敗しました: {{value1}}"
+ }
+ }
+ }
+ }
}
}
},
@@ -8241,7 +8386,8 @@
"648352c51f": "フローティング ワークスペースで {{value0}} を開く",
"82da3701e7": "{{value0}} の起動コマンドを構築できませんでした。",
"109870e023": "最大化",
- "b5686fee1e": "復元"
+ "b5686fee1e": "復元",
+ "1e502f1284": "開く"
}
}
},
@@ -8603,6 +8749,18 @@
"ReviewAnimatedVisual": {
"8df4d52b68": "プレビュー",
"8ab622e4d6": "メモ"
+ },
+ "FeatureWallBrowserAction": {
+ "5022c43a88": "ブラウザを開けませんでした",
+ "c9eb68b474": "このワークツリーで利用できるワークスペース グループがまだありません。",
+ "c9728107c5": "試してみる",
+ "25dd101f15": "ブラウザのセットアップに注意が必要です",
+ "e02b11e6b0": "ブラウザのセットアップが完了しました",
+ "d6d15077df": "スキル コマンドをコピーして、以下に挿入して確認しました。",
+ "78e65f19d9": "ブラウザのセットアップに失敗しました",
+ "b7345c18db": "予期しないエラーが発生しました。",
+ "5f97caf76b": "インストール中…",
+ "c2df599513": "CLI とスキルをインストール"
}
},
"tips": {
@@ -9328,7 +9486,8 @@
"e52a955e6f": "これは、[設定] > [ブラウザ] でいつでも見つけることができます。",
"4f5ffaa6a1": "ブラウザデータをインポートする",
"b24fef25be": "輸入",
- "02e89014c5": "{{value1}}{{value2}} から {{value0}} クッキーをインポートしました。"
+ "02e89014c5": "{{value1}}{{value2}} から {{value0}} クッキーをインポートしました。",
+ "d40d584769": "ファイルから {{value0}} 個の Cookie をインポートしました。"
},
"BrowserMobileDriverOverlay": {
"a6914ee43f": "取り戻す",
@@ -9405,7 +9564,12 @@
"31375046b7": "{{value0}} からダウンロード",
"acbe79fd01": "ページ要素の取得 ({{value0}})",
"572046436a": "リモートブラウザ",
- "b313a7275b": "リモートブラウザを開く"
+ "b313a7275b": "リモートブラウザを開く",
+ "5f66313863": "注釈",
+ "ea6af700da": "{{value0}} 件の注釈",
+ "c13693fe27": "{{value0}} 件の注釈",
+ "074f0ed10b": "{{value0}} 件の注釈が準備できました。別の要素を選択するか、すべてのフィードバックをコピーしてください。",
+ "a2164a6e5a": "{{value0}} 件の注釈が準備できました。別の要素を選択するか、すべてのフィードバックをコピーしてください。"
},
"BrowserToolbarMenu": {
"429ef481f9": "キャンセル",
@@ -9418,7 +9582,7 @@
"ed8f54509d": "デフォルト",
"e5d31de1a9": "ビューポートのサイズ",
"56f94f4ffa": "ファイルから…",
- "eb280bfb11": "から",
+ "eb280bfb11": "{{value0}} から",
"2293adf620": "Cookieのインポート",
"cf7cdc67ef": "新規プロフィール…",
"7b838540c7": "ブラウザメニュー",
@@ -9427,7 +9591,10 @@
"4d2f9f13a7": "プロファイルの作成に失敗しました。",
"3ccd29d771": "{{value0}} プロファイルに切り替えました",
"569bce8eb1": "作成",
- "bf648471c5": "作成…"
+ "bf648471c5": "作成…",
+ "53bbe3dab4": "ファイルから {{value0}} 個の Cookie をインポートしました。",
+ "c5f0e4d3b2a1": "{{value1}} ({{value2}}) から {{value0}} 件の Cookie をインポートしました。",
+ "d6a1f5e4c3b2": "{{value1}} から {{value0}} 件の Cookie をインポートしました。"
},
"GrabConfirmationSheet": {
"314a0aaa5b": "AIにアタッチする",
@@ -9799,6 +9966,20 @@
"56f5c60e0c": "キャンセル"
}
}
+ },
+ "i18n": {
+ "hostedReview": {
+ "copy": {
+ "f0a4b8c2d1": "PR",
+ "e9f3a7b1c0": "プルリクエスト",
+ "d8e2f6a0b9": "プルリクエスト",
+ "c7d1e5f9a8": "GitHub",
+ "c4e8f1a2b9": "MR",
+ "b3d7e0f1a8": "マージリクエスト",
+ "a2c6d9e0f7": "マージリクエスト",
+ "91b5c8d7e6": "GitLab"
+ }
+ }
}
}
}
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 1ce22e37b54..3087702d988 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -144,7 +144,8 @@
"10898045f3": "\"{{value0}}\"에 대한 단축키가 무시되었습니다. 문자열 배열을 사용하세요.",
"36761d9604": "알 수 없는 키 바인딩 작업 \"{{value0}}\"이(가) 무시되었습니다.",
"d2e43e426a": "{{value0}}은(는) 객체여야 합니다.",
- "fb290366b2": "웹에서는 사용할 수 없습니다."
+ "fb290366b2": "웹에서는 사용할 수 없습니다.",
+ "76122208ca": "\"{{value0}}\"에 대한 단축키가 무시되었습니다: {{value1}}"
}
},
"runtime": {
@@ -742,7 +743,8 @@
"b0b09778c8": "리뷰 댓글을 추가하지 못했습니다.",
"16c1abe76c": "본 것으로 표시",
"ba8e329d92": "본 표시 해제",
- "3f79ffc8b7": "현재 리뷰어를 보려면 PR 세부정보를 엽니다."
+ "3f79ffc8b7": "현재 리뷰어를 보려면 PR 세부정보를 엽니다.",
+ "5c1c973855": "리뷰어 삭제"
},
"GitLabItemDialog": {
"65e784c1f1": "다시 열기",
@@ -1158,7 +1160,8 @@
"19628e058d": "리뷰 댓글을 추가하지 못했습니다.",
"50b8fb290f": "본 것으로 표시",
"2b4fdb880c": "본 표시 해제",
- "56ec6eafb7": "현재 리뷰어를 보려면 PR 세부정보를 엽니다."
+ "56ec6eafb7": "현재 리뷰어를 보려면 PR 세부정보를 엽니다.",
+ "7f964a365a": "리뷰어 삭제"
},
"QuickOpen": {
"1dbd3f59ff": "이동",
@@ -1476,7 +1479,12 @@
"aec5feeb69": "Jira 이슈를 생성하지 못했습니다.",
"7437e340b4": "이슈를 생성하지 못했습니다.",
"9e03c17847": "현재 리뷰어를 보려면 PR 세부정보를 엽니다.",
- "3b7f34282f": "닫힘"
+ "3b7f34282f": "닫힘",
+ "246bd64aed": "Linear에서 {{value0}} 열기",
+ "ff90d0abc7": "{{value0}}에서 워크스페이스 시작",
+ "fe28c9821f": "view",
+ "8d1e17a3ef": "GitHub에서 {{value0}} 열기",
+ "4ac8ff2275": "Jira에서 {{value0}} 열기"
},
"Terminal": {
"73768427cf": "닫기",
@@ -1504,7 +1512,7 @@
},
"UpdateCard": {
"68b235d264": "업데이트하려면 다시 시작하세요.",
- "02d4b8a6b9": "다운로드됩니다. 준비가 되면 다시 시작하세요.",
+ "6714206e5a": "Orca v{{value0}}이(가) 다운로드되었습니다. 준비가 되면 다시 시작하세요.",
"93794ea932": "Orca v{{value0}}을(를) 다운로드 중입니다.",
"8acbdd3961": "상태 표시줄로 최소화",
"17412483da": "설치 준비 완료",
@@ -1517,7 +1525,7 @@
"ec8fe71cfc": "업데이트",
"44324ef542": "릴리스 노트",
"fdd4a364fa": "세션은 중단되지 않습니다.",
- "c4890662e9": "준비되었습니다.",
+ "05ad78a6d1": "Orca v{{value0}}이(가) 준비되었습니다.",
"318d3b4bc7": "업데이트 닫기",
"9abc59f814": "업데이트 가능",
"aad383aecc": "전체 릴리스 노트 읽기",
@@ -1997,7 +2005,10 @@
"bc43c37faf": "숨겨진",
"0c6672f5e3": "무시된 정리 제안",
"fc49f79434": "혼합된",
- "2ddbd6fe8a": "확인됨"
+ "2ddbd6fe8a": "확인됨",
+ "ee81adfcef": "보기",
+ "4d0b72481c": "무시",
+ "9cc26c019d": "제거"
}
}
},
@@ -2344,6 +2355,32 @@
"90eb94dc48": "http:// 또는 https:// URL을 입력하세요.",
"5553b283ce": "URL 또는 파일 경로를 입력하세요."
}
+ },
+ "menu": {
+ "options": {
+ "5501c2fb7a": "terminal",
+ "9630dd5494": "shell",
+ "a094576900": "new terminal",
+ "4f23f4d01d": "new shell",
+ "4f2a91e15b": "browser",
+ "6d0e6a4b7a": "new browser",
+ "c87ad57785": "browser tab",
+ "cce7ef1d2c": "web",
+ "5f17fb9d0c": "markdown",
+ "44caaf7b36": "md",
+ "fb50e3d874": "new markdown",
+ "6d8b6b4117": "new file",
+ "b330f72434": "mark",
+ "37ff3ddca1": "open markdown",
+ "164c394bab": "open file",
+ "bbaf4f85a4": "mobile emulator",
+ "3784b83bd4": "emulator",
+ "a63847a742": "simulator",
+ "1baeb07c17": "ios simulator",
+ "8a580f88cf": "iphone",
+ "7ecdc5ef08": "ipad",
+ "14965cc123": "mobile"
+ }
}
}
}
@@ -2372,29 +2409,31 @@
"PortsStatusSegment": {
"4ebf90c12e": "외부 포트가 감지되지 않았습니다.",
"7dac3ecc9d": "외부 포트",
- "95495019ed": "다음에서 포트 스캔을 사용할 수 없습니다.",
+ "95495019ed": "{{value0}}에서 포트 스캔을 사용할 수 없습니다: {{value1}}",
"a8e4bdb412": "· {{value0}} 외부",
"9aa11005bf": "워크스페이스 ·",
"c22ea609fd": "포트",
"a11ed266ce": "워크스페이스",
- "ca41be2802": "포트 —",
+ "ca41be2802": "포트 — {{value0}}개 워크스페이스 {{value1}}{{value2}}",
"b8bc3e420a": "포트, {{value0}} 워크스페이스 {{value1}}",
"3a87d54dfb": "워크스페이스 포트가 감지되지 않았습니다.",
"c174bbbfed": "워크스페이스 포트를 검색하는 중...",
"8caaa86e9a": "포트",
- "45834a9ace": "포트"
+ "45834a9ace": "포트",
+ "4ae65d871a": "외부",
+ "2b84c4d11f": "{{value0}} 워크스페이스 · {{value1}} 외부"
},
"ResourceUsageStatusSegment": {
"946d9f94d0": "취소",
"67c4ecda49": "이 터미널을 강제 종료합니다. 창에서 저장하지 않은 작업은 모두 손실됩니다. 이 작업은 취소할 수 없습니다.",
"4bb076fa89": "강제 종료",
"996295bff2": "고아 터미널",
- "92924a14e3": "비활성 워크스페이스 확인(",
+ "92924a14e3": "비활성 워크스페이스 검토 ({{value0}})",
"27a74f91f0": "지금은 실행 중인 항목이 없습니다.",
"1b24a32d3a": "메모리",
"298f4be7f2": "CPU",
"2aa2de6cb9": "이름",
- "30ff2c3c31": "유아",
+ "30ff2c3c31": "고아 {{value0}}개",
"6449a95c78": "Orca 추적 프로세스가 사용 중인 이 시스템의 물리적 RAM 크기입니다.",
"e7ccce7e87": "시스템 RAM",
"9e2525c89f": "Orca가 보유한 상주 메모리와 각 작업 트리 터미널 아래의 프로세스입니다.",
@@ -2429,7 +2468,12 @@
"16bc3c998a": "워크스페이스 삭제 {{value0}}",
"0f9e50eb07": "다른",
"d406915b78": "렌더러",
- "81cd37af99": "기본"
+ "81cd37af99": "기본",
+ "fa6d36758d": "세션 {{value0}} 종료",
+ "b8f4a2c1d0e3": "고아 {{value0}}개",
+ "c7e3b1a0d9f2": "고아 터미널 {{value0}}개 종료",
+ "d8f4c2b1e0a3": "고아 터미널 {{value0}}개 종료",
+ "e9a5d3c2b1f0": "{{value0}}을(를) 종료할까요?"
},
"SshStatusSegment": {
"3ad70e0365": "SSH 관리…",
@@ -2505,7 +2549,8 @@
"962404f68e": "업데이트 설치 준비가 완료되었습니다. 확장하려면 클릭하세요.",
"248ee5d8ef": "Orca v{{value0}} 다운로드 중… {{value1}}%",
"57a29c3b0e": "업데이트 준비됨",
- "fd1d3b3a1d": "업데이트 다운로드 중, {{value0}}퍼센트. 확장하려면 클릭하세요."
+ "fd1d3b3a1d": "업데이트 다운로드 중, {{value0}}퍼센트. 확장하려면 클릭하세요.",
+ "9d13213a56": "Orca v{{value0}} 설치 준비 완료"
},
"WorkspaceSpaceCompactPanel": {
"a471aa9c24": "업데이트됨",
@@ -2597,7 +2642,8 @@
"c5135e7e4a": "워크스페이스 크기를 스캔하는 중입니다. 이 페이지를 떠날 수 있습니다.",
"0990a63160": "아직 스캔된 워크스페이스 크기가 없습니다.",
"977bdf9a36": "표시할 최상위 항목이 없습니다.",
- "131662ac65": "{{value0}} 열려 있음"
+ "131662ac65": "{{value0}} 열려 있음",
+ "0d1c78d749": "{{value0}} 선택"
},
"ports": {
"status": {
@@ -2878,7 +2924,11 @@
"0015facc1f": "캐시",
"7f270458af": "출력",
"9365b14a4e": "새로운 입력",
- "3de9bf87fc": "아직 모델이 없습니다."
+ "3de9bf87fc": "아직 모델이 없습니다.",
+ "6762f6a682": "토큰",
+ "a7f937fb29": "{{value0}}개 세션 - {{value1}} {{value2}}",
+ "c8f3a2d1e0b4": "턴",
+ "d9a4b3e2f1c5": "이벤트"
}
}
}
@@ -3013,12 +3063,12 @@
"0f8aba944c": "디렉터리로 이동한 후 선택을 클릭하여 선택합니다."
},
"AddRepoStartSteps": {
- "f3c96237ae": "아니면 다음에서 추가하세요…",
"acf895cb42": "Orca를 시작하려면 프로젝트를 추가하세요.",
"d13757911c": "프로젝트 추가",
"d301db1c9a": "저장소를 스캔하는 중입니다. 중지하려면 클릭하세요.",
"69ea7f8dc4": "스캔 중지",
- "9906cae183": "스캔 중지"
+ "9906cae183": "스캔 중지",
+ "87596c1446": "다른 추가 방법"
},
"AddRepoStepIndicator": {
"3bb655c117": "뒤로"
@@ -3354,7 +3404,7 @@
"ccbd1e2c69": "{{value0}} 모양 맞춤설정"
},
"WorktreeCard": {
- "a88c92d0e3": "이미 존재합니다.",
+ "a88c92d0e3": "{{value0}}/{{value1}}이(가) 이미 있습니다.",
"6f09f58541": "워크스페이스 삭제",
"0777de5970": "기본 작업 트리(원래 복제 디렉터리)",
"0f33af979b": "부분결제. 이 경로 외부의 파일은 디스크에 없습니다.",
@@ -3468,7 +3518,12 @@
"84a2238242": "하위 워크스페이스 표시",
"045a8aed48": "하위",
"2ca6e29a3c": "레포",
- "bb85cd86ba": "{{value0}}에 대한 워크스페이스 만들기"
+ "bb85cd86ba": "{{value0}}에 대한 워크스페이스 만들기",
+ "ebadb7eadb": "{{value0}} {{value1}} child {{value2}}",
+ "20bebf9c7f": "{{value0}}개 하위 워크스페이스 표시",
+ "c1f4a31623": "{{value0}}개 하위 워크스페이스 표시",
+ "e97297cb75": "{{value0}}개 하위 워크스페이스 숨기기",
+ "0cd15956d4": "{{value0}}개 하위 워크스페이스 숨기기"
},
"WorktreeMetaDialog": {
"3db0a2a593": "취소",
@@ -3672,6 +3727,23 @@
},
"index": {
"b826a98b6f": "바쁘다"
+ },
+ "local": {
+ "base": {
+ "ref": {
+ "suggestion": {
+ "toast": {
+ "670864ab52": "로컬 {{value0}}을 최신 상태로 유지",
+ "84c62e4d7f": "Could not turn on {{value0}}",
+ "442552c656": "Open Settings and try again.",
+ "f15fd80989": "Your new worktree is current, but local {{value0}} is {{value1}} {{value2}} behind, so AI diffs may compare to stale history. Let Orca keep it up to date automatically. Change this anytime in",
+ "3d260e1a5d": "Settings › {{value0}}",
+ "34a03a6565": "Keep {{value0}} up to date",
+ "4a18052018": "Local {{value0}} is behind {{value1}}"
+ }
+ }
+ }
+ }
}
},
"shared": {
@@ -3687,7 +3759,12 @@
"fe2ab66d45": "{{value1}} 세션 중 {{value0}}을(를) 종료했습니다. {{value2}}이(가) 종료를 거부했습니다.",
"d762b41f41": "다시 시작하지 못했습니다.",
"b5954e12d3": "다시 시작하지 못했습니다. 로그를 확인하세요.",
- "0e9da1b98e": "데몬이 다시 시작되었습니다."
+ "0e9da1b98e": "데몬이 다시 시작되었습니다.",
+ "d6372cc797": "세션 {{value0}}개를 종료했습니다{{value1}}.",
+ "87412c2a68": "{{value0}}개 세션을 종료했습니다.",
+ "a2f040ac1c": "{{value0}}개 세션을 종료했습니다.",
+ "63520148e2": "{{value0}}개 세션이 종료를 거부했습니다.",
+ "cc0a26cb14": "{{value0}}개 세션이 종료를 거부했습니다."
}
},
"setup": {
@@ -3780,7 +3857,9 @@
"b10cb4f696": "추가 중",
"e4a28e8894": "Codex는 {{value0}} 로그인에 새로 로그인해야 한다고 보고했습니다. 새 Codex 세션을 시작하기 전에 다시 로그인하세요.",
"75ca9b718e": "Codex는 활성 계정에 새로 로그인해야 한다고 보고했습니다. 새 Codex 세션을 시작하기 전에 다시 인증하세요.",
- "b11078a9c2": "wsl"
+ "b11078a9c2": "wsl",
+ "350b2a1aa7": "Use your current",
+ "e05d0ff737": "현재 {{value0}} Claude 로그인을 사용하세요."
},
"AdvancedPane": {
"40b29e0bf3": "다시 시작",
@@ -3978,7 +4057,10 @@
"cdec84552f": "쿠키 가져오기",
"796d846483": "가져온 쿠키가 없습니다.",
"c29648fe5b": "활성",
- "d420c43729": "{{value1}}{{value2}}에서 {{value3}}로 {{value0}} 쿠키를 가져왔습니다."
+ "d420c43729": "{{value1}}{{value2}}에서 {{value3}}로 {{value0}} 쿠키를 가져왔습니다.",
+ "b4c167764d": "파일에서 {{value0}}개의 쿠키를 {{value1}}에 가져왔습니다.",
+ "a3f8c2d1e0b4": "{{value1}} ({{value2}})에서 {{value0}}개의 쿠키를 {{value3}}(으)로 가져왔습니다.",
+ "b4e9d3f2a1c5": "{{value1}}에서 {{value0}}개의 쿠키를 {{value2}}(으)로 가져왔습니다."
},
"BrowserUseComputerUseNotice": {
"15b5e680ba": "열린 컴퓨터 사용",
@@ -4023,7 +4105,8 @@
"de9b2f32f3": "활성화",
"ad8cb0ee22": "경로 수정",
"0289434ed6": "활성화됨",
- "8b3054dac7": "등록 중..."
+ "8b3054dac7": "등록 중...",
+ "8f2675c2f3": "파일에서 {{value0}}개의 쿠키를 가져왔습니다."
},
"BrowserUseSkillStep": {
"0871b6998d": "에이전트가 Orca 브라우저에서 페이지를 탐색하고 확인할 수 있습니다.",
@@ -4980,7 +5063,8 @@
"3595fd1948": "새 링크",
"54dee18f5c": "양식 숨기기",
"8cf8790697": "저장된 서버는 페어링된 Orca 런타임을 통해 이 브라우저를 라우팅합니다.",
- "f75ce1c7a5": "로컬은 오늘날의 데스크탑 동작을 유지합니다. 저장된 서버는 원격 런타임을 통해 지원되는 클라이언트 호출을 라우팅합니다."
+ "f75ce1c7a5": "로컬은 오늘날의 데스크탑 동작을 유지합니다. 저장된 서버는 원격 런타임을 통해 지원되는 클라이언트 호출을 라우팅합니다.",
+ "d25f0688b1": "제거"
},
"RuntimePairingGeneratedUrlRows": {
"0495f68959": "{{value0}} 복사"
@@ -5199,7 +5283,7 @@
"a6fcdd9e3c": "이름",
"b9922ec194": "사전 설정 편집 취소",
"694cc55ecb": "저장된 디렉터리는 이 저장소에 대한 희소 작업 트리를 생성할 때 사용됩니다.",
- "8b64731aaf": "더",
+ "8b64731aaf": "+{{value0}}개 더",
"755c6a1a0d": "확인",
"a7bcf206b1": "삭제 중",
"ba9ad2d4cd": "업데이트 날짜 알 수 없음",
@@ -5211,7 +5295,8 @@
"3dfa765ca7": "{{value0}} 디렉토리가 저장됩니다.",
"b532b9c17d": "1개의 디렉토리가 저장됩니다.",
"623b4cf910": "사전 설정 편집",
- "68bbcd864a": "새로운"
+ "68bbcd864a": "새로운",
+ "2ef2b2674b": "{{value0}} 삭제"
},
"SshDestructiveActionDialog": {
"895b216267": "취소"
@@ -7107,6 +7192,21 @@
"agent-generated-tab-title-copy": {
"19ad21615a": "탭 제목 자동 생성",
"b036c7a409": "첫 번째 에이전트 프롬프트에서 짧고 안정적인 탭 이름을 만듭니다. 수동으로 변경한 이름이 항상 우선합니다."
+ },
+ "keep": {
+ "local": {
+ "main": {
+ "up": {
+ "to": {
+ "date": {
+ "setting": {
+ "f8bda25f29": "Keep Local Main Up to Date"
+ }
+ }
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -7148,7 +7248,7 @@
},
"CreatePullRequestDialog": {
"2bc1b4345e": "취소",
- "27ef4b195c": "생성하기 전에 다른 기본 브랜치를 선택하세요.",
+ "27ef4b195c": "{{value0}}을(를) 만들기 전에 다른 베이스 브랜치를 선택하세요.",
"7ef56f3efe": "초안으로 만들기",
"0c9f9a568c": "마크다운 형식을 지원합니다. AI로 생성을 사용하여 변경 사항을 자동으로 채웁니다.",
"02b2ce911f": "설명(선택사항)",
@@ -7159,18 +7259,22 @@
"8584ccb43c": "기본 브랜치",
"6f5f1962b6": "본점",
"b504b3ceb1": "호스팅된 리뷰를 생성하기 전에 자세한 내용을 확인하세요.",
- "f658ff2455": "대상 브랜치를 확인하고",
+ "f658ff2455": "호스팅된 리뷰를 만들기 전에 대상 브랜치와 {{value0}} 세부 정보를 확인하세요.",
"b7f43474d7": "{{value0}} 만들기",
"7a21f0dae8": "{{value0}}에 영업 시작",
"edc35a7027": "{{value0}} #{{value1}}은(는) 이미 열려 있습니다.",
- "a154fe55e6": "푸시 및 생성 {{value0}}"
+ "a154fe55e6": "푸시 및 생성 {{value0}}",
+ "21c7a1daa0": "{{value0}}이(가) 이미 열려 있습니다",
+ "db9cee18f7": "{{value0}} 만들기"
},
"CreatePullRequestGenerateButton": {
"4012459f8a": "AI로 생성",
"a0501572c1": "AI로 {{value0}} 세부정보 생성",
- "d47fd63012": "세부. 중지하려면 클릭하세요.",
+ "d47fd63012": "{{value0}} 세부 정보를 생성하는 중입니다. 클릭하여 중지하세요.",
+ "bdf83ccb15": "{{value0}} 생성 중",
"f5513bdeb1": "생성 중",
"a6ea6dc3aa": "생성 중…",
+ "e61d7e7ad4": "{{value0}} 세부정보 생성 중지",
"e041998cad": "생성 중지"
},
"FileExplorer": {
@@ -7256,13 +7360,13 @@
"b950b1948b": "로컬 포트",
"9e5a4118b0": "원격 포트",
"c9d106547a": "앞으로",
- "c7e920aa7c": "다음과 같이 광고됨",
+ "c7e920aa7c": "{{value0}}(으)로 공개",
"e740075063": "제거",
"b3548e59f4": "편집",
"fe2730d050": "{{value0}} 복사",
"b22b128b2a": "브라우저에서 열기",
"75aeea592f": "브라우저에서 {{value0}} 열기",
- "de349d4560": "열립니다",
+ "de349d4560": "{{value0}} 열기",
"907eb53ed2": "포트 전달",
"04efd3dad4": "로컬 시스템의 원격 서비스에 액세스하려면 포트를 전달하세요.",
"1f0d2a24f9": "전달된 포트 없음",
@@ -7287,7 +7391,7 @@
"792baeb7ed": "주소 복사",
"d41a8241ec": "포트",
"a2a9fc6899": "로컬 포트가 감지되지 않았습니다.",
- "f59c783b7a": "다음에서 포트 스캔을 사용할 수 없습니다.",
+ "f59c783b7a": "{{value0}}에서 포트 스캔을 사용할 수 없습니다: {{value1}}",
"7822e3edc6": "포트 새로 고침",
"c1b115c375": "선택한 워크스페이스가 없습니다.",
"98e9a414f8": "브라우저를 열지 못했습니다.",
@@ -7309,7 +7413,10 @@
"38b16cfbef": "포트가 감지되지 않았습니다.",
"0d63d94db3": "스캐닝...",
"935dda7718": "활성 워크스페이스",
- "740aca88ab": "워크스페이스 포트 스캔에 실패했습니다."
+ "740aca88ab": "워크스페이스 포트 스캔에 실패했습니다.",
+ "5be4f7f727": "포트 {{value0}} 메뉴",
+ "7550998473": "복사",
+ "1004af16ab": "{{value0}} 복사"
},
"Search": {
"1abfb25a66": "파일에서 검색하려면 입력하세요.",
@@ -7377,7 +7484,7 @@
"dd43c47089": "이 커밋 실패에 대한 에이전트를 선택하세요.",
"30b8d4f181": "AI로 커밋 실패 수정",
"4b37ae99b0": "이 커밋 실패를 수정하려면 기본 AI 에이전트를 시작하세요.",
- "ae743199cd": "생성하기 전에 다른 기본 브랜치를 선택하세요.",
+ "ae743199cd": "{{value0}}을(를) 만들기 전에 다른 베이스 브랜치를 선택하세요.",
"c5e4175139": "더 많은 {{value0}} 및 원격 작업",
"78ddfd0bb4": "초안으로 만들기",
"e64a632456": "기본",
@@ -7389,9 +7496,11 @@
"7d6a8f0082": "제목",
"a6eda33521": "{{value0}} 제목",
"02d8c04339": "AI로 {{value0}} 세부정보 생성",
+ "aee92f8684": "생성",
"e868cec4e1": "생성 중…",
+ "b355e740b2": "{{value0}} 세부정보 생성 중지",
"527e130b6f": "생성 중지",
- "e1970d327d": "새로 만들기",
+ "e1970d327d": "새 {{value0}}",
"f4c766f1ca": "이 실행을 위한 에이전트 및 명령 템플릿을 선택합니다.",
"1a6a6e0bc5": "호스팅된 리뷰 세부 정보 생성",
"6b122529d4": "커밋 메시지 생성",
@@ -7469,17 +7578,34 @@
"72f2bea3f4": "메모 펼치기",
"d13edef890": "메모 접기",
"0fad573938": "어느 편도 아닌",
- "77afaa8152": "모두"
+ "77afaa8152": "모두",
+ "d6fb1df5fe": "{{value0}}이(가) 이미 열려 있습니다",
+ "05838cfdeb": "{{value0}} 충돌",
+ "0b5b8c234c": "{{value0}} ({{value1}}) 열기",
+ "d97ef8f221": "{{value0}}-{{value1}}줄",
+ "6f8bfa0eb9": "{{value0}}줄",
+ "c569d29a02": "양쪽에서 수정됨",
+ "ea7287d84f": "양쪽에서 추가됨",
+ "bd0151ef7b": "우리 쪽에서 삭제됨",
+ "44594e8c61": "상대 쪽에서 삭제됨",
+ "24773ee581": "우리 쪽에서 추가됨",
+ "c03d7c952f": "상대 쪽에서 추가됨",
+ "5b176fa431": "양쪽에서 삭제됨",
+ "31f6d46278": "미해결",
+ "2c417432b7": "로컬에서 해결됨",
+ "d206117f90": "{{value0}} 충돌 ({{value1}})",
+ "f3a8b2c1d0e5": "{{value0}} 제목을 입력하세요.",
+ "e2b7a1c0d9f4": "{{value0}} 생성에 실패했습니다"
},
"SourceControlAgentActionDialog": {
"8e856842d1": "선택한 에이전트를 시작할 수 없습니다.",
"c075d00de1": "워크스페이스 연결을 확인할 수 없습니다.",
"808cfe0a3b": "이 저장소에만 저장",
- "994cddd1f7": "저장하지 않음"
+ "994cddd1f7": "저장하지 않음",
+ "38b899cc02": "모든 리포지토리"
},
"SourceControlAgentActionDialogForm": {
"1bc0bdbb5e": "실행:",
- "f84657c925": "실행 레시피 저장",
"7ec6abbf2a": "재설정",
"f4f3c9ca4a": "명령 템플릿",
"fe119187bb": "--모델 소네트",
@@ -7489,7 +7615,15 @@
"3e8f21954f": "오류",
"74168d7ada": "idle",
"1d47db9bf0": "활성화된 에이전트가 없습니다.",
- "c7ff8cef11": "에이전트 감지 중..."
+ "c7ff8cef11": "에이전트 감지 중...",
+ "013c9ac04a": "저장 대상",
+ "1bb611240f": "Use {basePrompt} for Orca's default prompt.",
+ "23280cbab1": "This template does not include {basePrompt}, so the agent will not receive Orca's default prompt.",
+ "5421a96acb": "저장 후 에이전트 시작",
+ "6cefcdfba1": "You can change it later in Source Control AI settings.",
+ "c29f9cf266": "Save this prompt and don't show this review next time",
+ "d8f40128ee": "{basePrompt} is Orca's default prompt.",
+ "ea4788705e": "Cancel"
},
"SourceControlTextGenerationDialog": {
"c5b7fa7cb6": "전역 기본값으로 저장",
@@ -7768,6 +7902,17 @@
},
"GitHistoryGraphSvg": {
"47eff48230": "머리"
+ },
+ "create": {
+ "pull": {
+ "request": {
+ "review": {
+ "copy": {
+ "a1f8c3d2e4": "푸시는 성공했지만 {{value0}} 생성에 실패했습니다: {{value1}}"
+ }
+ }
+ }
+ }
}
}
},
@@ -8241,7 +8386,8 @@
"648352c51f": "플로팅 워크스페이스에서 {{value0}} 열기",
"82da3701e7": "{{value0}}에 대한 실행 명령을 작성할 수 없습니다.",
"109870e023": "최대화",
- "b5686fee1e": "복원"
+ "b5686fee1e": "복원",
+ "1e502f1284": "열기"
}
}
},
@@ -8603,6 +8749,18 @@
"ReviewAnimatedVisual": {
"8df4d52b68": "미리보기",
"8ab622e4d6": "메모"
+ },
+ "FeatureWallBrowserAction": {
+ "5022c43a88": "브라우저를 열 수 없습니다",
+ "c9eb68b474": "이 워크트리에 사용할 수 있는 워크스페이스 그룹이 아직 없습니다.",
+ "c9728107c5": "사용해 보기",
+ "25dd101f15": "브라우저 설정에 주의가 필요합니다",
+ "e02b11e6b0": "브라우저 설정이 준비되었습니다",
+ "d6d15077df": "스킬 명령을 복사해 아래에 삽입해 검토할 수 있습니다.",
+ "78e65f19d9": "브라우저 설정에 실패했습니다",
+ "b7345c18db": "예기치 않은 오류가 발생했습니다.",
+ "5f97caf76b": "설치 중…",
+ "c2df599513": "CLI 및 스킬 설치"
}
},
"tips": {
@@ -9328,7 +9486,8 @@
"e52a955e6f": "언제든지 설정 > 브라우저에서 찾을 수 있습니다.",
"4f5ffaa6a1": "브라우저 데이터 가져오기",
"b24fef25be": "수입",
- "02e89014c5": "{{value1}}{{value2}}에서 {{value0}} 쿠키를 가져왔습니다."
+ "02e89014c5": "{{value1}}{{value2}}에서 {{value0}} 쿠키를 가져왔습니다.",
+ "d40d584769": "파일에서 {{value0}}개의 쿠키를 가져왔습니다."
},
"BrowserMobileDriverOverlay": {
"a6914ee43f": "회수",
@@ -9405,7 +9564,12 @@
"31375046b7": "{{value0}}에서 다운로드",
"acbe79fd01": "페이지 요소 가져오기({{value0}})",
"572046436a": "원격 브라우저",
- "b313a7275b": "원격 브라우저 열기"
+ "b313a7275b": "원격 브라우저 열기",
+ "5f66313863": "주석",
+ "ea6af700da": "{{value0}}개 주석",
+ "c13693fe27": "{{value0}}개 주석",
+ "074f0ed10b": "{{value0}}개 주석이 준비되었습니다. 다른 요소를 선택하거나 모든 피드백을 복사하세요.",
+ "a2164a6e5a": "{{value0}}개 주석이 준비되었습니다. 다른 요소를 선택하거나 모든 피드백을 복사하세요."
},
"BrowserToolbarMenu": {
"429ef481f9": "취소",
@@ -9418,7 +9582,7 @@
"ed8f54509d": "기본",
"e5d31de1a9": "뷰포트 크기",
"56f94f4ffa": "파일에서…",
- "eb280bfb11": "에서",
+ "eb280bfb11": "{{value0}}에서",
"2293adf620": "쿠키 가져오기",
"cf7cdc67ef": "새 프로필…",
"7b838540c7": "브라우저 메뉴",
@@ -9427,7 +9591,10 @@
"4d2f9f13a7": "프로필을 생성하지 못했습니다.",
"3ccd29d771": "{{value0}} 프로필로 전환됨",
"569bce8eb1": "생성",
- "bf648471c5": "만드는 중…"
+ "bf648471c5": "만드는 중…",
+ "53bbe3dab4": "파일에서 {{value0}}개의 쿠키를 가져왔습니다.",
+ "c5f0e4d3b2a1": "{{value1}} ({{value2}})에서 {{value0}}개의 쿠키를 가져왔습니다.",
+ "d6a1f5e4c3b2": "{{value1}}에서 {{value0}}개의 쿠키를 가져왔습니다."
},
"GrabConfirmationSheet": {
"314a0aaa5b": "AI에 연결",
@@ -9799,6 +9966,20 @@
"56f5c60e0c": "취소"
}
}
+ },
+ "i18n": {
+ "hostedReview": {
+ "copy": {
+ "f0a4b8c2d1": "PR",
+ "e9f3a7b1c0": "풀 리퀘스트",
+ "d8e2f6a0b9": "풀 리퀘스트",
+ "c7d1e5f9a8": "GitHub",
+ "c4e8f1a2b9": "MR",
+ "b3d7e0f1a8": "머지 리퀘스트",
+ "a2c6d9e0f7": "머지 리퀘스트",
+ "91b5c8d7e6": "GitLab"
+ }
+ }
}
}
}
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index 6b7bc70707f..0196186018e 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -144,7 +144,8 @@
"10898045f3": "“{{value0}}”的快捷方式被忽略:使用字符串数组。",
"36761d9604": "未知的键绑定操作“{{value0}}”被忽略。",
"d2e43e426a": "{{value0}} 必须是一个对象。",
- "fb290366b2": "无法在网络上使用。"
+ "fb290366b2": "无法在网络上使用。",
+ "76122208ca": "“{{value0}}”的快捷方式被忽略:{{value1}}"
}
},
"runtime": {
@@ -742,7 +743,8 @@
"b0b09778c8": "无法添加评论。",
"16c1abe76c": "标记已查看",
"ba8e329d92": "取消标记已查看",
- "3f79ffc8b7": "打开 PR 详情以查看当前评审人。"
+ "3f79ffc8b7": "打开 PR 详情以查看当前评审人。",
+ "5c1c973855": "移除评审人"
},
"GitLabItemDialog": {
"65e784c1f1": "重新打开",
@@ -1158,7 +1160,8 @@
"19628e058d": "无法添加评论。",
"50b8fb290f": "标记已查看",
"2b4fdb880c": "取消标记已查看",
- "56ec6eafb7": "打开 PR 详情以查看当前评审人。"
+ "56ec6eafb7": "打开 PR 详情以查看当前评审人。",
+ "7f964a365a": "移除评审人"
},
"QuickOpen": {
"1dbd3f59ff": "移动",
@@ -1476,7 +1479,12 @@
"aec5feeb69": "无法创建 Jira 议题。",
"7437e340b4": "无法创建议题。",
"9e03c17847": "打开 PR 详情以查看当前评审人。",
- "3b7f34282f": "关闭"
+ "3b7f34282f": "关闭",
+ "246bd64aed": "在 Linear 中打开 {{value0}}",
+ "ff90d0abc7": "从 {{value0}} 开始工作区",
+ "fe28c9821f": "view",
+ "8d1e17a3ef": "在 GitHub 中打开 {{value0}}",
+ "4ac8ff2275": "在 Jira 中打开 {{value0}}"
},
"Terminal": {
"73768427cf": "关闭",
@@ -1504,7 +1512,7 @@
},
"UpdateCard": {
"68b235d264": "重启即可更新",
- "02d4b8a6b9": "已下载。准备好后重新启动。",
+ "6714206e5a": "Orca v{{value0}} 已下载。准备好后请重新启动。",
"93794ea932": "Orca v{{value0}} 正在下载。",
"8acbdd3961": "最小化到状态栏",
"17412483da": "准备安装",
@@ -1517,7 +1525,7 @@
"ec8fe71cfc": "更新",
"44324ef542": "发行说明",
"fdd4a364fa": "会话不会被中断。",
- "c4890662e9": "准备好了。",
+ "05ad78a6d1": "Orca v{{value0}} 已准备就绪。",
"318d3b4bc7": "关闭更新",
"9abc59f814": "可用更新",
"aad383aecc": "阅读完整的发行说明",
@@ -1997,7 +2005,10 @@
"bc43c37faf": "隐",
"0c6672f5e3": "忽略清理建议",
"fc49f79434": "混合的",
- "2ddbd6fe8a": "检查过"
+ "2ddbd6fe8a": "检查过",
+ "ee81adfcef": "查看",
+ "4d0b72481c": "忽略",
+ "9cc26c019d": "移除"
}
}
},
@@ -2344,6 +2355,32 @@
"90eb94dc48": "输入 http:// 或 https:// URL。",
"5553b283ce": "输入 URL 或文件路径。"
}
+ },
+ "menu": {
+ "options": {
+ "5501c2fb7a": "terminal",
+ "9630dd5494": "shell",
+ "a094576900": "new terminal",
+ "4f23f4d01d": "new shell",
+ "4f2a91e15b": "browser",
+ "6d0e6a4b7a": "new browser",
+ "c87ad57785": "browser tab",
+ "cce7ef1d2c": "web",
+ "5f17fb9d0c": "markdown",
+ "44caaf7b36": "md",
+ "fb50e3d874": "new markdown",
+ "6d8b6b4117": "new file",
+ "b330f72434": "mark",
+ "37ff3ddca1": "open markdown",
+ "164c394bab": "open file",
+ "bbaf4f85a4": "mobile emulator",
+ "3784b83bd4": "emulator",
+ "a63847a742": "simulator",
+ "1baeb07c17": "ios simulator",
+ "8a580f88cf": "iphone",
+ "7ecdc5ef08": "ipad",
+ "14965cc123": "mobile"
+ }
}
}
}
@@ -2372,29 +2409,31 @@
"PortsStatusSegment": {
"4ebf90c12e": "未检测到外部端口",
"7dac3ecc9d": "外部端口",
- "95495019ed": "端口扫描不可用",
+ "95495019ed": "{{value0}} 上无法进行端口扫描:{{value1}}",
"a8e4bdb412": "· {{value0}} 外部",
"9aa11005bf": "工作区·",
"c22ea609fd": "端口",
"a11ed266ce": "工作区",
- "ca41be2802": "端口——",
+ "ca41be2802": "端口 — {{value0}} 个工作区 {{value1}}{{value2}}",
"b8bc3e420a": "端口,{{value0}} 工作区 {{value1}}",
"3a87d54dfb": "未检测到工作区端口",
"c174bbbfed": "正在扫描工作区端口...",
"8caaa86e9a": "端口",
- "45834a9ace": "端口"
+ "45834a9ace": "端口",
+ "4ae65d871a": "外部",
+ "2b84c4d11f": "{{value0}} 个工作区 · {{value1}} 个外部"
},
"ResourceUsageStatusSegment": {
"946d9f94d0": "取消",
"67c4ecda49": "强制退出该终端。窗格中所有未保存的工作都会丢失。这无法撤销。",
"4bb076fa89": "强制结束",
"996295bff2": "孤儿终端",
- "92924a14e3": "查看非活动工作区 (",
+ "92924a14e3": "查看非活跃工作区 ({{value0}})",
"27a74f91f0": "现在没有任何运行",
"1b24a32d3a": "记忆",
"298f4be7f2": "中央处理器",
"2aa2de6cb9": "姓名",
- "30ff2c3c31": "孤儿",
+ "30ff2c3c31": "{{value0}} 个孤立项",
"6449a95c78": "Orca 跟踪的进程占用了该计算机的物理 RAM 的大小。",
"e7ccce7e87": "系统内存",
"9e2525c89f": "Orca 持有的常驻内存加上每个工作树终端下的进程。",
@@ -2429,7 +2468,12 @@
"16bc3c998a": "删除工作区 {{value0}}",
"0f9e50eb07": "其他",
"d406915b78": "渲染器",
- "81cd37af99": "主要的"
+ "81cd37af99": "主要的",
+ "fa6d36758d": "终止会话 {{value0}}",
+ "b8f4a2c1d0e3": "{{value0}} 个孤立项",
+ "c7e3b1a0d9f2": "终止 {{value0}} 个孤立终端",
+ "d8f4c2b1e0a3": "终止 {{value0}} 个孤立终端",
+ "e9a5d3c2b1f0": "终止 {{value0}}?"
},
"SshStatusSegment": {
"3ad70e0365": "管理 SSH...",
@@ -2505,7 +2549,8 @@
"962404f68e": "更新准备安装。单击以展开。",
"248ee5d8ef": "Orca v{{value0}} 正在下载... {{value1}}%",
"57a29c3b0e": "更新准备就绪",
- "fd1d3b3a1d": "更新下载,{{value0}}%。单击以展开。"
+ "fd1d3b3a1d": "更新下载,{{value0}}%。单击以展开。",
+ "9d13213a56": "Orca v{{value0}} 已准备好安装"
},
"WorkspaceSpaceCompactPanel": {
"a471aa9c24": "已更新",
@@ -2597,7 +2642,8 @@
"c5135e7e4a": "扫描工作区大小。您可以离开此页面。",
"0990a63160": "尚无扫描的工作区大小。",
"977bdf9a36": "没有可显示的顶级项目。",
- "131662ac65": "{{value0}} 打开"
+ "131662ac65": "{{value0}} 打开",
+ "0d1c78d749": "选择 {{value0}}"
},
"ports": {
"status": {
@@ -2878,7 +2924,11 @@
"0015facc1f": "缓存",
"7f270458af": "输出",
"9365b14a4e": "新输入",
- "3de9bf87fc": "还没有型号"
+ "3de9bf87fc": "还没有型号",
+ "6762f6a682": "Token",
+ "a7f937fb29": "{{value0}} 个会话 - {{value1}} {{value2}}",
+ "c8f3a2d1e0b4": "轮次",
+ "d9a4b3e2f1c5": "事件"
}
}
}
@@ -3013,12 +3063,12 @@
"0f8aba944c": "导航到目录并单击“选择”以选择它。"
},
"AddRepoStartSteps": {
- "f3c96237ae": "或者添加来自...",
"acf895cb42": "添加一个项目以开始使用 Orca。",
"d13757911c": "添加项目",
"d301db1c9a": "扫描存储库。单击停止。",
"69ea7f8dc4": "停止扫描",
- "9906cae183": "停止扫描"
+ "9906cae183": "停止扫描",
+ "87596c1446": "其他添加方式"
},
"AddRepoStepIndicator": {
"3bb655c117": "返回"
@@ -3354,7 +3404,7 @@
"ccbd1e2c69": "自定义 {{value0}} 外观"
},
"WorktreeCard": {
- "a88c92d0e3": "已经存在。",
+ "a88c92d0e3": "{{value0}}/{{value1}} 已存在。",
"6f09f58541": "删除工作区",
"0777de5970": "主工作树(原始克隆目录)",
"0f33af979b": "部分结帐。这些路径之外的文件不在磁盘上。",
@@ -3468,7 +3518,12 @@
"84a2238242": "显示子工作区",
"045a8aed48": "孩子们",
"2ca6e29a3c": "回购协议",
- "bb85cd86ba": "为 {{value0}} 创建工作区"
+ "bb85cd86ba": "为 {{value0}} 创建工作区",
+ "ebadb7eadb": "{{value0}} {{value1}} child {{value2}}",
+ "20bebf9c7f": "显示 {{value0}} 个子工作区",
+ "c1f4a31623": "显示 {{value0}} 个子工作区",
+ "e97297cb75": "隐藏 {{value0}} 个子工作区",
+ "0cd15956d4": "隐藏 {{value0}} 个子工作区"
},
"WorktreeMetaDialog": {
"3db0a2a593": "取消",
@@ -3672,6 +3727,23 @@
},
"index": {
"b826a98b6f": "忙碌的"
+ },
+ "local": {
+ "base": {
+ "ref": {
+ "suggestion": {
+ "toast": {
+ "670864ab52": "使本地 {{value0}} 保持最新",
+ "84c62e4d7f": "Could not turn on {{value0}}",
+ "442552c656": "Open Settings and try again.",
+ "f15fd80989": "Your new worktree is current, but local {{value0}} is {{value1}} {{value2}} behind, so AI diffs may compare to stale history. Let Orca keep it up to date automatically. Change this anytime in",
+ "3d260e1a5d": "Settings › {{value0}}",
+ "34a03a6565": "Keep {{value0}} up to date",
+ "4a18052018": "Local {{value0}} is behind {{value1}}"
+ }
+ }
+ }
+ }
}
},
"shared": {
@@ -3687,7 +3759,12 @@
"fe2ab66d45": "杀死 {{value1}} 会话中的 {{value0}}。 {{value2}} 拒绝退出。",
"d762b41f41": "重启失败。",
"b5954e12d3": "重新启动失败 - 检查日志。",
- "0e9da1b98e": "守护进程重新启动。"
+ "0e9da1b98e": "守护进程重新启动。",
+ "d6372cc797": "已终止 {{value0}} 个会话{{value1}}。",
+ "87412c2a68": "已终止 {{value0}} 个会话。",
+ "a2f040ac1c": "已终止 {{value0}} 个会话。",
+ "63520148e2": "{{value0}} 个会话拒绝退出。",
+ "cc0a26cb14": "{{value0}} 个会话拒绝退出。"
}
},
"setup": {
@@ -3780,7 +3857,9 @@
"b10cb4f696": "添加",
"e4a28e8894": "Codex 报告 {{value0}} 登录需要重新登录。在开始新的 Codex 会话之前再次登录。",
"75ca9b718e": "Codex 报告活动账户需要重新登录。在开始新的 Codex 会话之前重新对其进行身份验证。",
- "b11078a9c2": "wsl"
+ "b11078a9c2": "wsl",
+ "350b2a1aa7": "Use your current",
+ "e05d0ff737": "使用您当前 {{value0}} Claude 登录名。"
},
"AdvancedPane": {
"40b29e0bf3": "重新启动",
@@ -3978,7 +4057,10 @@
"cdec84552f": "导入 Cookie",
"796d846483": "没有导入cookie",
"c29648fe5b": "当前",
- "d420c43729": "将 {{value0}} cookie 从 {{value1}}{{value2}} 导入到 {{value3}} 中。"
+ "d420c43729": "将 {{value0}} cookie 从 {{value1}}{{value2}} 导入到 {{value3}} 中。",
+ "b4c167764d": "已从文件将 {{value0}} 个 Cookie 导入到 {{value1}}。",
+ "a3f8c2d1e0b4": "已从 {{value1}} ({{value2}}) 导入 {{value0}} 个 Cookie 到 {{value3}}。",
+ "b4e9d3f2a1c5": "已从 {{value1}} 导入 {{value0}} 个 Cookie 到 {{value2}}。"
},
"BrowserUseComputerUseNotice": {
"15b5e680ba": "开放计算机使用",
@@ -4023,7 +4105,8 @@
"de9b2f32f3": "启用",
"ad8cb0ee22": "修复路径",
"0289434ed6": "启用",
- "8b3054dac7": "注册..."
+ "8b3054dac7": "注册...",
+ "8f2675c2f3": "已从文件导入 {{value0}} 个 Cookie。"
},
"BrowserUseSkillStep": {
"0871b6998d": "使代理能够在 Orca 浏览器中导航和验证页面。",
@@ -4980,7 +5063,8 @@
"3595fd1948": "新链接",
"54dee18f5c": "隐藏表格",
"8cf8790697": "保存的服务器通过配对的 Orca 运行时路由该浏览器。",
- "f75ce1c7a5": "本地保留了当今的桌面行为。保存的服务器通过远程运行时路由支持的客户端调用。"
+ "f75ce1c7a5": "本地保留了当今的桌面行为。保存的服务器通过远程运行时路由支持的客户端调用。",
+ "d25f0688b1": "移除"
},
"RuntimePairingGeneratedUrlRows": {
"0495f68959": "复制 {{value0}}"
@@ -5199,7 +5283,7 @@
"a6fcdd9e3c": "姓名",
"b9922ec194": "取消预设编辑",
"694cc55ecb": "为此存储库创建稀疏工作树时,将使用保存的目录。",
- "8b64731aaf": "更多的",
+ "8b64731aaf": "还有 +{{value0}} 个",
"755c6a1a0d": "确认",
"a7bcf206b1": "正在删除",
"ba9ad2d4cd": "更新日期未知",
@@ -5211,7 +5295,8 @@
"3dfa765ca7": "将保存 {{value0}} 目录。",
"b532b9c17d": "将保存 1 个目录。",
"623b4cf910": "编辑预设",
- "68bbcd864a": "新的"
+ "68bbcd864a": "新的",
+ "2ef2b2674b": "删除 {{value0}}"
},
"SshDestructiveActionDialog": {
"895b216267": "取消"
@@ -7107,6 +7192,21 @@
"agent-generated-tab-title-copy": {
"19ad21615a": "自动生成标签页标题",
"b036c7a409": "根据第一个已知代理提示词生成简短稳定的标签页名称。手动重命名始终优先。"
+ },
+ "keep": {
+ "local": {
+ "main": {
+ "up": {
+ "to": {
+ "date": {
+ "setting": {
+ "f8bda25f29": "Keep Local Main Up to Date"
+ }
+ }
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -7148,7 +7248,7 @@
},
"CreatePullRequestDialog": {
"2bc1b4345e": "取消",
- "27ef4b195c": "在创建之前选择不同的基础分支",
+ "27ef4b195c": "在创建 {{value0}} 之前,请选择其他基础分支。",
"7ef56f3efe": "创建为草稿",
"0c9f9a568c": "支持 Markdown 格式。使用 AI 生成来自动填充您的更改。",
"02b2ce911f": "说明(可选)",
@@ -7159,18 +7259,22 @@
"8584ccb43c": "基础分支",
"6f5f1962b6": "源分支",
"b504b3ceb1": "创建托管评论之前的详细信息。",
- "f658ff2455": "确认目标分支并",
+ "f658ff2455": "在创建托管审查之前,请确认目标分支和 {{value0}} 详情。",
"b7f43474d7": "创建 {{value0}}",
"7a21f0dae8": "打开于 {{value0}}",
"edc35a7027": "{{value0}} #{{value1}} 已开放",
- "a154fe55e6": "推送并创建 {{value0}}"
+ "a154fe55e6": "推送并创建 {{value0}}",
+ "21c7a1daa0": "{{value0}} 已打开",
+ "db9cee18f7": "创建 {{value0}}"
},
"CreatePullRequestGenerateButton": {
"4012459f8a": "用 AI 生成",
"a0501572c1": "使用 AI 生成 {{value0}} 详细信息",
- "d47fd63012": "细节。单击停止。",
+ "d47fd63012": "正在生成 {{value0}} 详情。点击停止。",
+ "bdf83ccb15": "正在生成 {{value0}}",
"f5513bdeb1": "生成",
"a6ea6dc3aa": "生成…",
+ "e61d7e7ad4": "停止生成 {{value0}} 详细信息",
"e041998cad": "停止生成"
},
"FileExplorer": {
@@ -7256,13 +7360,13 @@
"b950b1948b": "本地端口",
"9e5a4118b0": "远程端口",
"c9d106547a": "向前",
- "c7e920aa7c": "显示为",
+ "c7e920aa7c": "公开为 {{value0}}",
"e740075063": "移除",
"b3548e59f4": "编辑",
"fe2730d050": "复制 {{value0}}",
"b22b128b2a": "在浏览器中打开",
"75aeea592f": "在浏览器中打开 {{value0}}",
- "de349d4560": "打开",
+ "de349d4560": "打开 {{value0}}",
"907eb53ed2": "转发端口",
"04efd3dad4": "转发端口以访问本地计算机上的远程服务。",
"1f0d2a24f9": "无转发端口",
@@ -7287,7 +7391,7 @@
"792baeb7ed": "复制地址",
"d41a8241ec": "端口",
"a2a9fc6899": "未检测到本地端口",
- "f59c783b7a": "端口扫描不可用",
+ "f59c783b7a": "{{value0}} 上无法进行端口扫描:{{value1}}",
"7822e3edc6": "刷新端口",
"c1b115c375": "未选择工作区",
"98e9a414f8": "无法打开浏览器",
@@ -7309,7 +7413,10 @@
"38b16cfbef": "未检测到端口",
"0d63d94db3": "扫描...",
"935dda7718": "活跃的工作区",
- "740aca88ab": "工作区端口扫描失败。"
+ "740aca88ab": "工作区端口扫描失败。",
+ "5be4f7f727": "端口 {{value0}} 菜单",
+ "7550998473": "Copy",
+ "1004af16ab": "复制 {{value0}}"
},
"Search": {
"1abfb25a66": "输入要在文件中搜索的内容",
@@ -7377,7 +7484,7 @@
"dd43c47089": "选择针对此提交失败的代理",
"30b8d4f181": "使用 AI 修复提交失败",
"4b37ae99b0": "启动默认的AI代理来修复此提交失败",
- "ae743199cd": "在创建之前选择不同的基础分支",
+ "ae743199cd": "在创建 {{value0}} 之前,请选择其他基础分支。",
"c5e4175139": "更多 {{value0}} 和远程操作",
"78ddfd0bb4": "创建为草稿",
"e64a632456": "主要的",
@@ -7389,9 +7496,11 @@
"7d6a8f0082": "标题",
"a6eda33521": "{{value0}} 标题",
"02d8c04339": "使用 AI 生成 {{value0}} 详细信息",
+ "aee92f8684": "生成",
"e868cec4e1": "生成…",
+ "b355e740b2": "停止生成 {{value0}} 详细信息",
"527e130b6f": "停止生成",
- "e1970d327d": "新建",
+ "e1970d327d": "新建 {{value0}}",
"f4c766f1ca": "为此运行选择代理和命令模板。",
"1a6a6e0bc5": "生成托管评论详细信息",
"6b122529d4": "生成提交消息",
@@ -7469,17 +7578,34 @@
"72f2bea3f4": "展开注释",
"d13edef890": "折叠笔记",
"0fad573938": "未提交",
- "77afaa8152": "全部"
+ "77afaa8152": "全部",
+ "d6fb1df5fe": "{{value0}} 已打开",
+ "05838cfdeb": "{{value0}} 冲突",
+ "0b5b8c234c": "打开 {{value0}} ({{value1}})",
+ "d97ef8f221": "第 {{value0}}-{{value1}} 行",
+ "6f8bfa0eb9": "第 {{value0}} 行",
+ "c569d29a02": "双方都修改",
+ "ea7287d84f": "双方都添加",
+ "bd0151ef7b": "我们删除",
+ "44594e8c61": "对方删除",
+ "24773ee581": "我们添加",
+ "c03d7c952f": "对方添加",
+ "5b176fa431": "双方都删除",
+ "31f6d46278": "未解决",
+ "2c417432b7": "已在本地解决",
+ "d206117f90": "{{value0}} 冲突 ({{value1}})",
+ "f3a8b2c1d0e5": "请输入 {{value0}} 标题。",
+ "e2b7a1c0d9f4": "创建 {{value0}} 失败"
},
"SourceControlAgentActionDialog": {
"8e856842d1": "无法启动选定的代理。",
"c075d00de1": "无法解析工作区连接。",
"808cfe0a3b": "仅保存到此存储库",
- "994cddd1f7": "不保存"
+ "994cddd1f7": "不保存",
+ "38b899cc02": "所有仓库"
},
"SourceControlAgentActionDialogForm": {
"1bc0bdbb5e": "启动:",
- "f84657c925": "保存启动配方",
"7ec6abbf2a": "重置",
"f4f3c9ca4a": "命令模板",
"fe119187bb": "——模范十四行诗",
@@ -7489,7 +7615,15 @@
"3e8f21954f": "错误",
"74168d7ada": "idle",
"1d47db9bf0": "没有启用代理",
- "c7ff8cef11": "检测剂..."
+ "c7ff8cef11": "检测剂...",
+ "013c9ac04a": "保存范围",
+ "1bb611240f": "Use {basePrompt} for Orca's default prompt.",
+ "23280cbab1": "This template does not include {basePrompt}, so the agent will not receive Orca's default prompt.",
+ "5421a96acb": "保存并启动代理",
+ "6cefcdfba1": "You can change it later in Source Control AI settings.",
+ "c29f9cf266": "Save this prompt and don't show this review next time",
+ "d8f40128ee": "{basePrompt} is Orca's default prompt.",
+ "ea4788705e": "Cancel"
},
"SourceControlTextGenerationDialog": {
"c5b7fa7cb6": "保存为全局默认值",
@@ -7768,6 +7902,17 @@
},
"GitHistoryGraphSvg": {
"47eff48230": "头"
+ },
+ "create": {
+ "pull": {
+ "request": {
+ "review": {
+ "copy": {
+ "a1f8c3d2e4": "推送成功,但创建 {{value0}} 失败:{{value1}}"
+ }
+ }
+ }
+ }
}
}
},
@@ -8241,7 +8386,8 @@
"648352c51f": "在浮动工作区中打开 {{value0}}",
"82da3701e7": "无法为 {{value0}} 构建启动命令。",
"109870e023": "最大化",
- "b5686fee1e": "恢复"
+ "b5686fee1e": "恢复",
+ "1e502f1284": "Open"
}
}
},
@@ -8603,6 +8749,18 @@
"ReviewAnimatedVisual": {
"8df4d52b68": "PR视图",
"8ab622e4d6": "笔记"
+ },
+ "FeatureWallBrowserAction": {
+ "5022c43a88": "无法打开浏览器",
+ "c9eb68b474": "此工作树尚无可用的工作区组。",
+ "c9728107c5": "试试看",
+ "25dd101f15": "浏览器设置需要处理",
+ "e02b11e6b0": "浏览器设置已就绪",
+ "d6d15077df": "技能命令已复制并插入到下方供查看。",
+ "78e65f19d9": "浏览器设置失败",
+ "b7345c18db": "发生了意外错误。",
+ "5f97caf76b": "正在安装…",
+ "c2df599513": "安装 CLI 和技能"
}
},
"tips": {
@@ -9328,7 +9486,8 @@
"e52a955e6f": "您始终可以在“设置”>“浏览器”中找到它。",
"4f5ffaa6a1": "导入浏览器数据",
"b24fef25be": "导入",
- "02e89014c5": "从 {{value1}}{{value2}} 导入 {{value0}} cookie。"
+ "02e89014c5": "从 {{value1}}{{value2}} 导入 {{value0}} cookie。",
+ "d40d584769": "已从文件导入 {{value0}} 个 Cookie。"
},
"BrowserMobileDriverOverlay": {
"a6914ee43f": "收回",
@@ -9405,7 +9564,12 @@
"31375046b7": "从 {{value0}} 下载",
"acbe79fd01": "抓取页面元素 ({{value0}})",
"572046436a": "远程浏览器",
- "b313a7275b": "打开远程浏览器"
+ "b313a7275b": "打开远程浏览器",
+ "5f66313863": "注释",
+ "ea6af700da": "{{value0}} 条注释",
+ "c13693fe27": "{{value0}} 条注释",
+ "074f0ed10b": "{{value0}} 条注释已准备好。请选择另一个元素或复制所有反馈。",
+ "a2164a6e5a": "{{value0}} 条注释已准备好。请选择另一个元素或复制所有反馈。"
},
"BrowserToolbarMenu": {
"429ef481f9": "取消",
@@ -9418,7 +9582,7 @@
"ed8f54509d": "默认",
"e5d31de1a9": "视口尺寸",
"56f94f4ffa": "从文件...",
- "eb280bfb11": "从",
+ "eb280bfb11": "从 {{value0}}",
"2293adf620": "导入 Cookie",
"cf7cdc67ef": "新档案...",
"7b838540c7": "浏览器菜单",
@@ -9427,7 +9591,10 @@
"4d2f9f13a7": "创建个人资料失败。",
"3ccd29d771": "切换到 {{value0}} 配置文件",
"569bce8eb1": "创建",
- "bf648471c5": "创建中…"
+ "bf648471c5": "创建中…",
+ "53bbe3dab4": "已从文件导入 {{value0}} 个 Cookie。",
+ "c5f0e4d3b2a1": "已从 {{value1}} ({{value2}}) 导入 {{value0}} 个 Cookie。",
+ "d6a1f5e4c3b2": "已从 {{value1}} 导入 {{value0}} 个 Cookie。"
},
"GrabConfirmationSheet": {
"314a0aaa5b": "附加到 AI",
@@ -9799,6 +9966,20 @@
"56f5c60e0c": "取消"
}
}
+ },
+ "i18n": {
+ "hostedReview": {
+ "copy": {
+ "f0a4b8c2d1": "PR",
+ "e9f3a7b1c0": "拉取请求",
+ "d8e2f6a0b9": "拉取请求",
+ "c7d1e5f9a8": "GitHub",
+ "c4e8f1a2b9": "MR",
+ "b3d7e0f1a8": "合并请求",
+ "a2c6d9e0f7": "合并请求",
+ "91b5c8d7e6": "GitLab"
+ }
+ }
}
}
}
diff --git a/src/renderer/src/web/web-preload-api.ts b/src/renderer/src/web/web-preload-api.ts
index 16d72501469..ad3106f3ed7 100644
--- a/src/renderer/src/web/web-preload-api.ts
+++ b/src/renderer/src/web/web-preload-api.ts
@@ -695,7 +695,7 @@ function normalizeStoredWebOverrides(
section,
actionId,
message: translate(
- 'auto.web.web.preload.api.10898045f3',
+ 'auto.web.web.preload.api.76122208ca',
'Shortcut for "{{value0}}" was ignored: {{value1}}',
{ value0: actionId, value1: error }
)
From 1cbc40b2aabb9accee5730e47f0d7a07b1464e25 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 23:19:07 -0400
Subject: [PATCH 018/165] Recover floating workspace terminal WebGL atlas on
reopen (#5069)
Co-authored-by: Orca
---
.../FloatingTerminalPanel.test.tsx | 30 ++
.../FloatingTerminalPanel.tsx | 138 +++++-
.../use-terminal-pane-global-effects.test.ts | 38 +-
.../use-terminal-pane-global-effects.ts | 19 +-
src/renderer/src/constants/terminal.ts | 8 +
...ng-workspace-reopen-webgl-recovery.spec.ts | 443 ++++++++++++++++++
6 files changed, 656 insertions(+), 20 deletions(-)
create mode 100644 tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
index da130481f2d..14888bd029e 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
@@ -2,6 +2,7 @@
* React/store environment directly so close and bootstrap behavior can be
* asserted without mounting the full Electron renderer. */
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+import { RESET_TERMINAL_WEBGL_ATLAS_EVENT } from '@/constants/terminal'
import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../../shared/constants'
import type { BrowserTab, Tab, TabGroup, TerminalTab } from '../../../../shared/types'
import type { OpenFile } from '@/store/slices/editor'
@@ -593,6 +594,9 @@ describe('FloatingTerminalPanel close behavior', () => {
}
vi.stubGlobal('window', {
addEventListener: vi.fn(),
+ // Why: the open-transition effect dispatches the WebGL atlas recovery
+ // event; the stubbed window needs a sink for it.
+ dispatchEvent: vi.fn(),
api: {
app: {
getFloatingMarkdownDirectory: mocks.getFloatingMarkdownDirectory,
@@ -952,6 +956,32 @@ describe('FloatingTerminalPanel close behavior', () => {
expect(mocks.focusTerminalTabSurface).toHaveBeenCalledWith('created-tab')
})
+ it('dispatches WebGL atlas recovery for the active terminal on reopen', async () => {
+ setFloatingTabs([makeTab({ id: 'tab-1' })])
+
+ await renderPanel(false)
+ runEffects()
+ vi.mocked(window.dispatchEvent).mockClear()
+
+ const countResetEvents = (): CustomEvent<{ tabId?: string }>[] =>
+ vi
+ .mocked(window.dispatchEvent)
+ .mock.calls.map(([event]) => event as CustomEvent<{ tabId?: string }>)
+ .filter((event) => event.type === RESET_TERMINAL_WEBGL_ATLAS_EVENT)
+
+ await renderPanel(true)
+ runEffects()
+
+ const resetEvents = countResetEvents()
+ expect(resetEvents).toHaveLength(1)
+ expect(resetEvents[0]?.detail?.tabId).toBe('tab-1')
+
+ // Why: re-renders while the panel stays open must not re-clear the atlas.
+ await renderPanel(true)
+ runEffects()
+ expect(countResetEvents()).toHaveLength(1)
+ })
+
it('routes titlebar Cmd+T to the floating workspace', async () => {
setFloatingTabs([makeTab({ id: 'tab-1' })])
const element = await renderPanel(true)
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
index 06c5566ef84..287e5f76161 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
@@ -19,6 +19,10 @@ import { ShortcutKeyCombo } from '@/components/ShortcutKeyCombo'
import TabBar from '@/components/tab-bar/TabBar'
import { resolveGroupTabFromVisibleId } from '@/components/tab-group/tab-group-visible-id'
import TerminalPane from '@/components/terminal-pane/TerminalPane'
+import {
+ RESET_TERMINAL_WEBGL_ATLAS_EVENT,
+ type ResetTerminalWebglAtlasDetail
+} from '@/constants/terminal'
import { Button } from '@/components/ui/button'
import { useMountedRef } from '@/hooks/useMountedRef'
import { useShortcutKeys } from '@/hooks/useShortcutLabel'
@@ -528,6 +532,31 @@ export function FloatingTerminalPanel({
focusTerminalTabSurface(activeTerminalId)
}, [activeTerminalId, open])
+ const wasOpenForAtlasRecoveryRef = useRef(false)
+ useEffect(() => {
+ if (!open) {
+ wasOpenForAtlasRecoveryRef.current = false
+ return
+ }
+ if (wasOpenForAtlasRecoveryRef.current) {
+ return
+ }
+ wasOpenForAtlasRecoveryRef.current = true
+ if (!activeTerminalId) {
+ return
+ }
+ // Why: closing the panel only hides it with CSS, so the active terminal
+ // keeps a live WebGL context while hidden and reopening never flips
+ // TerminalPane visibility. A glyph atlas corrupted while hidden (no
+ // context-loss event) would otherwise stay garbled until another
+ // recovery trigger such as window refocus.
+ window.dispatchEvent(
+ new CustomEvent(RESET_TERMINAL_WEBGL_ATLAS_EVENT, {
+ detail: { tabId: activeTerminalId }
+ })
+ )
+ }, [activeTerminalId, open])
+
useEffect(() => {
if (!open || hasVisibleFloatingTabs) {
return
@@ -653,7 +682,10 @@ export function FloatingTerminalPanel({
return
}
createBrowserTab(FLOATING_TERMINAL_WORKTREE_ID, url, {
- title: translate("auto.components.floating.terminal.FloatingTerminalPanel.8b14ba6c17", "New Browser Tab"),
+ title: translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.8b14ba6c17',
+ 'New Browser Tab'
+ ),
focusAddressBar: true,
targetGroupId: activeGroup?.id
})
@@ -1386,7 +1418,11 @@ export function FloatingTerminalPanel({
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.d6b563ae24", "Loading editor...")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.d6b563ae24',
+ 'Loading editor...'
+ )}
+
}
>
{/* Why: floating workspace markdown is scratch/local context,
@@ -1416,16 +1452,25 @@ export function FloatingTerminalPanel({
) : null}
- {showOrchestrationSetup && activeTabType === "terminal" ? (
+ {showOrchestrationSetup && activeTabType === 'terminal' ? (
-
{translate("auto.components.floating.terminal.FloatingTerminalPanel.2a3c5ddf5e", "Enable orchestration")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.2a3c5ddf5e',
+ 'Enable orchestration'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.8cf80db43b", "Set up the Orca CLI and agent skill so agents can coordinate through Orca.")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.8cf80db43b',
+ 'Set up the Orca CLI and agent skill so agents can coordinate through Orca.'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.adc281394d", "Dismiss")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.adc281394d',
+ 'Dismiss'
+ )}
+
setOrchestrationDialogOpen(true)}
>
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.bbc177f98f", "Enable")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.bbc177f98f',
+ 'Enable'
+ )}
+
@@ -1470,11 +1523,23 @@ export function FloatingTerminalPanel({
>
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.690b6fb98a", "Unsaved Changes")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.690b6fb98a',
+ 'Unsaved Changes'
+ )}
+
{saveDialogFile
- ? translate("auto.components.floating.terminal.FloatingTerminalPanel.5ddc688c52", "\"{{value0}}\" has unsaved changes. Do you want to save before closing?", { value0: saveDialogFile.relativePath.split('/').pop() })
- : translate("auto.components.floating.terminal.FloatingTerminalPanel.b085fb58b5", "This file has unsaved changes.")}
+ ? translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.5ddc688c52',
+ '"{{value0}}" has unsaved changes. Do you want to save before closing?',
+ { value0: saveDialogFile.relativePath.split('/').pop() }
+ )
+ : translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.b085fb58b5',
+ 'This file has unsaved changes.'
+ )}
@@ -1484,16 +1549,28 @@ export function FloatingTerminalPanel({
size="sm"
onClick={handleFloatingSaveDialogCancel}
>
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.e7bf09d4d4", "Cancel")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.e7bf09d4d4',
+ 'Cancel'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.918c2139f3", "Don't Save")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.918c2139f3',
+ "Don't Save"
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.da508bd7f5", "Save")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.da508bd7f5',
+ 'Save'
+ )}
+
@@ -1541,7 +1618,12 @@ function FloatingTerminalEmptyState({
onClick={onNewTerminal}
>
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.3215fc73e9", "New Terminal")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.3215fc73e9',
+ 'New Terminal'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.629528690b", "New Markdown Note")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.629528690b',
+ 'New Markdown Note'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.88ffb502e5", "Open Markdown Note")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.88ffb502e5',
+ 'Open Markdown Note'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.8b07759314", "New Browser")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.8b07759314',
+ 'New Browser'
+ )}
+
- {translate("auto.components.floating.terminal.FloatingTerminalPanel.fc1042e92b", "Minimize")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalPanel.fc1042e92b',
+ 'Minimize'
+ )}
+
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
index 245165b5b67..1ab57576c1e 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
@@ -1,7 +1,7 @@
/* eslint-disable max-lines -- Why: these hook tests share a mocked React lifecycle harness with global event cases. */
import type * as ReactModule from 'react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-import { SYNC_FIT_PANES_EVENT } from '@/constants/terminal'
+import { RESET_TERMINAL_WEBGL_ATLAS_EVENT, SYNC_FIT_PANES_EVENT } from '@/constants/terminal'
import { useTerminalPaneGlobalEffects } from './use-terminal-pane-global-effects'
const mocks = vi.hoisted(() => ({
@@ -359,6 +359,42 @@ describe('useTerminalPaneGlobalEffects', () => {
expect(manager.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
})
+ it('clears WebGL texture atlases for a matching reset-atlas event', () => {
+ const { manager } = useMountForFileDrop()
+
+ const resetListener = vi
+ .mocked(window.addEventListener)
+ .mock.calls.find(([eventName]) => eventName === RESET_TERMINAL_WEBGL_ATLAS_EVENT)
+
+ expect(resetListener).toBeDefined()
+ const listener = resetListener?.[1]
+ if (typeof listener !== 'function') {
+ throw new Error('expected reset-atlas listener')
+ }
+ manager.resetWebglTextureAtlases.mockClear()
+ listener(new CustomEvent(RESET_TERMINAL_WEBGL_ATLAS_EVENT, { detail: { tabId: 'tab-1' } }))
+
+ expect(manager.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
+ })
+
+ it('ignores reset-atlas events for another terminal tab', () => {
+ const { manager } = useMountForFileDrop()
+
+ const resetListener = vi
+ .mocked(window.addEventListener)
+ .mock.calls.find(([eventName]) => eventName === RESET_TERMINAL_WEBGL_ATLAS_EVENT)
+
+ expect(resetListener).toBeDefined()
+ const listener = resetListener?.[1]
+ if (typeof listener !== 'function') {
+ throw new Error('expected reset-atlas listener')
+ }
+ manager.resetWebglTextureAtlases.mockClear()
+ listener(new CustomEvent(RESET_TERMINAL_WEBGL_ATLAS_EVENT, { detail: { tabId: 'tab-2' } }))
+
+ expect(manager.resetWebglTextureAtlases).not.toHaveBeenCalled()
+ })
+
it('ignores terminal file drops for another terminal tab', () => {
const { onFileDrop } = useMountForFileDrop()
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
index 902004d5a99..9e7ff81300e 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
@@ -2,9 +2,11 @@ import { useEffect, useRef } from 'react'
import {
FOCUS_TERMINAL_PANE_EVENT,
PASTE_TERMINAL_TEXT_EVENT,
+ RESET_TERMINAL_WEBGL_ATLAS_EVENT,
TOGGLE_TERMINAL_PANE_EXPAND_EVENT,
type FocusTerminalPaneDetail,
- type PasteTerminalTextDetail
+ type PasteTerminalTextDetail,
+ type ResetTerminalWebglAtlasDetail
} from '@/constants/terminal'
import type { PaneManager } from '@/lib/pane-manager/pane-manager'
import { fitAndFocusPanes, fitPanes } from './pane-helpers'
@@ -204,6 +206,21 @@ export function useTerminalPaneGlobalEffects({
return () => window.removeEventListener(FOCUS_TERMINAL_PANE_EVENT, onFocusPane)
}, [tabId, managerRef, scheduleFollowOutputIfNeeded])
+ useEffect(() => {
+ const onResetAtlas = (event: Event): void => {
+ const detail = (event as CustomEvent).detail
+ if (!detail?.tabId || detail.tabId !== tabId) {
+ return
+ }
+ // Why: WebGL atlas corruption can occur with no context-loss event while
+ // a CSS-hidden surface (floating workspace) holds a live context; the
+ // owning surface dispatches this when it becomes visible again.
+ managerRef.current?.resetWebglTextureAtlases()
+ }
+ window.addEventListener(RESET_TERMINAL_WEBGL_ATLAS_EVENT, onResetAtlas)
+ return () => window.removeEventListener(RESET_TERMINAL_WEBGL_ATLAS_EVENT, onResetAtlas)
+ }, [tabId, managerRef])
+
useEffect(() => {
const onPasteText = (event: Event): void => {
const detail = (event as CustomEvent).detail
diff --git a/src/renderer/src/constants/terminal.ts b/src/renderer/src/constants/terminal.ts
index b59e0be006f..1a281ec9a22 100644
--- a/src/renderer/src/constants/terminal.ts
+++ b/src/renderer/src/constants/terminal.ts
@@ -7,6 +7,10 @@ export const SPLIT_TERMINAL_PANE_EVENT = 'orca-split-terminal-pane'
export const REQUEST_ACTIVE_TERMINAL_PANE_SPLIT_EVENT = 'orca-request-active-terminal-pane-split'
export const CLOSE_TERMINAL_PANE_EVENT = 'orca-close-terminal-pane'
export const BACKGROUND_MOUNT_TERMINAL_WORKTREE_EVENT = 'orca-background-mount-terminal-worktree'
+// Why: surfaces that show/hide terminals with CSS only (floating workspace)
+// never flip TerminalPane visibility, so they need an explicit trigger for
+// WebGL glyph-atlas recovery when they become visible again.
+export const RESET_TERMINAL_WEBGL_ATLAS_EVENT = 'orca-reset-terminal-webgl-atlas'
// Why: sidebar open/close is an instantaneous width change. If we wait for
// the ResizeObserver rAF (and the 150ms debounced global fit) to catch up,
@@ -42,6 +46,10 @@ export type PasteTerminalTextDetail = {
text: string
}
+export type ResetTerminalWebglAtlasDetail = {
+ tabId: string
+}
+
export type SplitTerminalPaneDetail = {
tabId: string
paneRuntimeId: number
diff --git a/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts b/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts
new file mode 100644
index 00000000000..f5670c4f263
--- /dev/null
+++ b/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts
@@ -0,0 +1,443 @@
+import type { Page } from '@stablyai/playwright-test'
+import { test, expect } from './helpers/orca-app'
+import { waitForActiveWorktree, waitForSessionReady } from './helpers/store'
+import { sendToTerminal } from './helpers/terminal'
+
+// Why: mirrors FLOATING_TERMINAL_WORKTREE_ID in src/shared/constants.ts.
+// e2e specs avoid importing renderer/shared modules into the Playwright runner.
+const FLOATING_WORKTREE_ID = 'global-floating-terminal'
+const PANEL_SELECTOR = '[data-floating-terminal-panel]'
+
+// Why: the floating panel toggles via this window event
+// (src/renderer/src/lib/floating-terminal.ts); dispatching it exercises the
+// same code path as the status bar button and the keyboard shortcut.
+const TOGGLE_EVENT = 'orca-toggle-floating-terminal'
+
+// Why: a silent foreground command blocks the shell so no prompt framework
+// (e.g. async p10k segments) repaints while screenshots are compared.
+const SILENT_FOREGROUND_COMMAND = 'node -e "setInterval(() => {}, 1000)"\r'
+
+// Why: matches the local-cast pattern used by terminal-image-paste-webgl-recovery.spec;
+// a global Window augmentation would leak into every spec in the suite.
+type RecoveryCounterWindow = typeof window & {
+ __floatingManagerResets?: number
+ __floatingRenderResumes?: number
+}
+
+async function enableFloatingWorkspaceWithWebgl(page: Page): Promise {
+ await page.evaluate((worktreeId) => {
+ const store = window.__store
+ const state = store?.getState()
+ if (!store || !state?.settings) {
+ throw new Error('Store unavailable')
+ }
+ store.setState({
+ settings: {
+ ...state.settings,
+ floatingTerminalEnabled: true,
+ terminalGpuAcceleration: 'on'
+ }
+ })
+ const tabs = store.getState().tabsByWorktree[worktreeId] ?? []
+ if (tabs.length === 0) {
+ const tab = store.getState().createTab(worktreeId, undefined, undefined, {
+ activate: false
+ })
+ store.getState().activateTab(tab.id)
+ }
+ }, FLOATING_WORKTREE_ID)
+ // Why: the toggle event listener closes over floatingTerminalEnabled; wait
+ // for the (lazy) panel to mount so React has committed the enabled state
+ // before the toggle event is dispatched, otherwise the event is dropped.
+ await page.waitForFunction(
+ (panelSelector) => Boolean(document.querySelector(panelSelector)),
+ PANEL_SELECTOR,
+ { timeout: 30_000 }
+ )
+}
+
+async function waitForFloatingPanePtyId(page: Page): Promise {
+ await expect
+ .poll(
+ () =>
+ page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ return pane?.container?.dataset?.ptyId ?? null
+ }, FLOATING_WORKTREE_ID),
+ {
+ timeout: 15_000,
+ message: 'Floating terminal pane did not receive a PTY binding'
+ }
+ )
+ .not.toBeNull()
+ const ptyId = await page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ return pane?.container?.dataset?.ptyId ?? null
+ }, FLOATING_WORKTREE_ID)
+ if (!ptyId) {
+ throw new Error('Floating terminal pane has no PTY binding')
+ }
+ return ptyId
+}
+
+async function toggleFloatingPanel(page: Page, open: boolean): Promise {
+ await page.evaluate((eventName) => {
+ window.dispatchEvent(new Event(eventName))
+ }, TOGGLE_EVENT)
+ await (open
+ ? expect(page.locator(PANEL_SELECTOR)).toBeVisible()
+ : expect(page.locator(PANEL_SELECTOR)).toBeHidden())
+}
+
+async function waitForFloatingWebglPane(page: Page): Promise {
+ // Why: a pane that mounted before the GPU setting landed needs the manager
+ // call too — mirrors forceWebgl in terminal-image-paste-webgl-recovery.spec.
+ await page
+ .waitForFunction(
+ (worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ return Boolean(manager?.getActivePane?.() ?? manager?.getPanes?.()[0])
+ },
+ FLOATING_WORKTREE_ID,
+ { timeout: 15_000 }
+ )
+ .catch(() => undefined)
+ await page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ manager?.setTerminalGpuAcceleration?.('on')
+ }, FLOATING_WORKTREE_ID)
+ // Why: getPanes()/getActivePane() return a public projection without
+ // webglAddon; getRenderingDiagnostics() is the supported way to observe
+ // whether WebGL is attached.
+ const attached = await page
+ .waitForFunction(
+ (worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ const diagnostics = manager?.getRenderingDiagnostics?.() ?? []
+ return diagnostics.some((diagnostic) => diagnostic.hasWebgl)
+ },
+ FLOATING_WORKTREE_ID,
+ { timeout: 10_000 }
+ )
+ .then(() => true)
+ .catch(() => false)
+ if (!attached) {
+ const probe = await page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tabs = state?.tabsByWorktree?.[worktreeId] ?? []
+ const tab = tabs[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ return {
+ tabCount: tabs.length,
+ hasManager: Boolean(manager),
+ diagnostics: manager?.getRenderingDiagnostics?.() ?? null,
+ gpuSetting: state?.settings?.terminalGpuAcceleration ?? null
+ }
+ }, FLOATING_WORKTREE_ID)
+ console.log(`[floating-harness] webgl attach failed: ${JSON.stringify(probe)}`)
+ }
+ return attached
+}
+
+async function writeStaticContent(page: Page, marker: string): Promise {
+ await page.evaluate(
+ async ({ worktreeId, content }) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ if (!pane) {
+ throw new Error('Floating pane unavailable')
+ }
+ await new Promise((resolve) => pane.terminal.write(content, resolve))
+ },
+ {
+ worktreeId: FLOATING_WORKTREE_ID,
+ // Why: clear screen + scrollback and hide the cursor so screenshots are
+ // time-invariant, then render dense mixed glyphs so the WebGL atlas
+ // origin region is populated.
+ content: `\x1b[2J\x1b[3J\x1b[H\x1b[?25l${Array.from(
+ { length: 14 },
+ (_, row) =>
+ `${marker} row ${row} | abcdefghijklmnopqrstuvwxyz 0123456789 []{}<>/\\#@%&*+=~ |\r\n`
+ ).join('')}`
+ }
+ )
+ // Why: let xterm's renderer paint the new content before baseline capture.
+ await page.evaluate(
+ () => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)))
+ )
+}
+
+/**
+ * Corrupts the live glyph-atlas textures of the floating terminal's WebGL
+ * context by overwriting texels in every bound TEXTURE_2D, without raising a
+ * context-loss event. This simulates the in-the-wild Chromium failure that
+ * #5042 documents ("rapid TUI redraws can corrupt xterm's WebGL glyph atlas
+ * without a context-loss event") so recovery triggers can be tested
+ * deterministically.
+ */
+async function corruptFloatingAtlas(page: Page): Promise {
+ return page.evaluate(
+ ({ worktreeId, panelSelector }) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ if (!pane) {
+ return 0
+ }
+ const panel = document.querySelector(panelSelector)
+ const canvases = panel ? Array.from(panel.querySelectorAll('canvas')) : []
+ const noise = new Uint8Array(64 * 64 * 4)
+ for (let i = 0; i < noise.length; i += 4) {
+ noise[i] = (i * 7) % 256
+ noise[i + 1] = (i * 13) % 256
+ noise[i + 2] = (i * 29) % 256
+ noise[i + 3] = 255
+ }
+ let corrupted = 0
+ for (const canvas of canvases) {
+ const gl =
+ (canvas.getContext('webgl2') as WebGL2RenderingContext | null) ??
+ (canvas.getContext('webgl') as WebGLRenderingContext | null)
+ if (!gl) {
+ continue
+ }
+ const maxUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS) as number
+ for (let unit = 0; unit < maxUnits; unit += 1) {
+ gl.activeTexture(gl.TEXTURE0 + unit)
+ const bound = gl.getParameter(gl.TEXTURE_BINDING_2D)
+ if (!bound) {
+ continue
+ }
+ // Why: glyphs rasterize from the atlas origin outward, so noise
+ // tiles across the top-left region garble the visible text.
+ for (const [x, y] of [
+ [0, 0],
+ [64, 0],
+ [128, 0],
+ [192, 0],
+ [0, 64],
+ [64, 64],
+ [128, 64],
+ [192, 64]
+ ]) {
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, noise)
+ if (gl.getError() === gl.NO_ERROR) {
+ corrupted += 1
+ }
+ }
+ }
+ gl.activeTexture(gl.TEXTURE0)
+ }
+ pane.terminal.refresh(0, pane.terminal.rows - 1)
+ return corrupted
+ },
+ { worktreeId: FLOATING_WORKTREE_ID, panelSelector: PANEL_SELECTOR }
+ )
+}
+
+async function instrumentRecoveryCounters(page: Page): Promise {
+ return page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ if (!manager?.resetWebglTextureAtlases || !manager.resumeRendering) {
+ return false
+ }
+ const counterWindow = window as RecoveryCounterWindow
+ counterWindow.__floatingManagerResets = 0
+ counterWindow.__floatingRenderResumes = 0
+ const originalReset = manager.resetWebglTextureAtlases.bind(manager)
+ manager.resetWebglTextureAtlases = () => {
+ counterWindow.__floatingManagerResets = (counterWindow.__floatingManagerResets ?? 0) + 1
+ originalReset()
+ }
+ // Why: a suspend/resume cycle also rebuilds the atlas; count it so any
+ // future fix routed through resumeRendering() is recognized as recovery.
+ const originalResume = manager.resumeRendering.bind(manager)
+ manager.resumeRendering = () => {
+ counterWindow.__floatingRenderResumes = (counterWindow.__floatingRenderResumes ?? 0) + 1
+ originalResume()
+ }
+ return true
+ }, FLOATING_WORKTREE_ID)
+}
+
+async function readRecoveryCounters(
+ page: Page
+): Promise<{ managerResets: number; renderResumes: number }> {
+ return page.evaluate(() => {
+ const counterWindow = window as RecoveryCounterWindow
+ return {
+ managerResets: counterWindow.__floatingManagerResets ?? 0,
+ renderResumes: counterWindow.__floatingRenderResumes ?? 0
+ }
+ })
+}
+
+async function screenshotFloatingTerminal(page: Page): Promise {
+ const screen = page.locator(`${PANEL_SELECTOR} .xterm-screen`).first()
+ await expect(screen).toBeVisible()
+ return screen.screenshot({ animations: 'disabled' })
+}
+
+async function settleRecoveryWindows(page: Page): Promise {
+ // Why: #5042-style recovery schedules resets up to 500ms after its trigger;
+ // waiting past that window keeps "no recovery fired" assertions honest.
+ await page.waitForTimeout(800)
+}
+
+async function captureStableBaseline(page: Page): Promise {
+ // Why: shell startup output can still be painting when content lands; two
+ // consecutive identical captures prove the surface is byte-stable before
+ // corruption comparisons begin.
+ let previous = await screenshotFloatingTerminal(page)
+ for (let attempt = 0; attempt < 10; attempt += 1) {
+ await page.waitForTimeout(250)
+ const next = await screenshotFloatingTerminal(page)
+ if (next.equals(previous)) {
+ return next
+ }
+ previous = next
+ }
+ throw new Error('Floating terminal surface did not stabilize for a baseline screenshot')
+}
+
+async function setUpCorruptedFloatingTerminal(
+ page: Page,
+ marker: string
+): Promise<{ baseline: Buffer; corrupted: Buffer } | null> {
+ await waitForSessionReady(page)
+ await waitForActiveWorktree(page)
+ await enableFloatingWorkspaceWithWebgl(page)
+ await toggleFloatingPanel(page, true)
+ if (!(await waitForFloatingWebglPane(page))) {
+ return null
+ }
+ const ptyId = await waitForFloatingPanePtyId(page)
+ await sendToTerminal(page, ptyId, SILENT_FOREGROUND_COMMAND)
+ // Why: give the shell a beat to echo the command and start blocking before
+ // the screen is cleared; later captures verify stability explicitly.
+ await page.waitForTimeout(1_000)
+ await writeStaticContent(page, marker)
+ // Why: glyphs rasterized during startup can predate web font readiness; a
+ // clean atlas rebuild here makes the baseline byte-identical to any later
+ // recovery re-rasterization, so equality is a sound "healed" oracle.
+ await page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ manager?.resetWebglTextureAtlases?.()
+ }, FLOATING_WORKTREE_ID)
+ const baseline = await captureStableBaseline(page)
+ const corruptedTiles = await corruptFloatingAtlas(page)
+ console.log(`[floating-harness] corrupted atlas tiles: ${corruptedTiles}`)
+ if (corruptedTiles === 0) {
+ return null
+ }
+ // Why: xterm paints on the next animation frame after refresh(); poll until
+ // the injected noise is actually visible so later "still corrupted" and
+ // "healed" comparisons are meaningful. Skip if the noise landed outside the
+ // atlas region glyphs are drawn from.
+ for (let attempt = 0; attempt < 8; attempt += 1) {
+ await page.waitForTimeout(250)
+ const shot = await screenshotFloatingTerminal(page)
+ if (!shot.equals(baseline)) {
+ return { baseline, corrupted: shot }
+ }
+ }
+ console.log('[floating-harness] injected atlas noise never became visible')
+ return null
+}
+
+test.describe('floating workspace reopen WebGL recovery @headful', () => {
+ test('reopening the floating workspace recovers a corrupted glyph atlas', async ({
+ orcaPage
+ }, testInfo) => {
+ // Why: the floating panel hides via CSS visibility only — its terminal
+ // keeps isVisible=true and a live WebGL context while hidden, so the
+ // visibility-resume/window-focus/paste recovery triggers never run on
+ // reopen. The panel dispatches RESET_TERMINAL_WEBGL_ATLAS_EVENT when it
+ // opens; this guards that a glyph atlas corrupted while hidden repaints.
+ const shots = await setUpCorruptedFloatingTerminal(orcaPage, 'REOPEN')
+ test.skip(!shots, 'WebGL was not active or atlas corruption could not be injected')
+ const { baseline, corrupted } = shots!
+ expect(corrupted.equals(baseline)).toBe(false)
+
+ expect(await instrumentRecoveryCounters(orcaPage)).toBe(true)
+
+ await toggleFloatingPanel(orcaPage, false)
+ // Why: the bug's precondition — the hidden floating terminal keeps its
+ // WebGL addon attached because closing the panel never suspends rendering.
+ const webglStillAttached = await orcaPage.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
+ const manager = tab ? window.__paneManagers?.get(tab.id) : null
+ const diagnostics = manager?.getRenderingDiagnostics?.() ?? []
+ return diagnostics.some((diagnostic) => diagnostic.hasWebgl)
+ }, FLOATING_WORKTREE_ID)
+ expect(webglStillAttached).toBe(true)
+
+ await toggleFloatingPanel(orcaPage, true)
+ await settleRecoveryWindows(orcaPage)
+
+ const counters = await readRecoveryCounters(orcaPage)
+ const afterReopen = await screenshotFloatingTerminal(orcaPage)
+ await testInfo.attach('baseline', {
+ body: baseline,
+ contentType: 'image/png'
+ })
+ await testInfo.attach('corrupted', {
+ body: corrupted,
+ contentType: 'image/png'
+ })
+ await testInfo.attach('after-reopen', {
+ body: afterReopen,
+ contentType: 'image/png'
+ })
+ console.log(
+ `[floating-reopen] managerResets=${counters.managerResets} renderResumes=${counters.renderResumes} healed=${afterReopen.equals(baseline)}`
+ )
+
+ expect(
+ counters.managerResets + counters.renderResumes,
+ 'reopen should reset or rebuild the corrupted atlas'
+ ).toBeGreaterThan(0)
+ expect(afterReopen.equals(baseline), 'reopened terminal should render clean glyphs').toBe(true)
+ })
+
+ test('window focus regain recovers the corrupted atlas (harness control)', async ({
+ orcaPage
+ }) => {
+ // Why: control proving the injected corruption is exactly the class the
+ // existing recovery machinery heals — isolating the reopen gap above as a
+ // missing trigger rather than a broken harness or unrecoverable state.
+ const shots = await setUpCorruptedFloatingTerminal(orcaPage, 'CONTROL')
+ test.skip(!shots, 'WebGL was not active or atlas corruption could not be injected')
+ const { baseline, corrupted } = shots!
+ expect(corrupted.equals(baseline)).toBe(false)
+
+ await orcaPage.evaluate(() => {
+ window.dispatchEvent(new Event('focus'))
+ })
+ await settleRecoveryWindows(orcaPage)
+
+ const afterFocus = await screenshotFloatingTerminal(orcaPage)
+ console.log(`[floating-control] healedByFocus=${afterFocus.equals(baseline)}`)
+ expect(afterFocus.equals(baseline), 'window focus should heal the atlas').toBe(true)
+ })
+})
From e98febcdbc49bb244c4b13650a7810d8929b42ae Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 23:22:39 -0400
Subject: [PATCH 019/165] Fix stale terminal daemon spawn health (#5064)
Co-authored-by: Orca
---
.../daemon-health-socket-cleanup.test.ts | 7 +-
src/main/daemon/daemon-health.test.ts | 21 +++++
src/main/daemon/daemon-health.ts | 39 ++++++--
src/main/daemon/daemon-init.test.ts | 94 ++++++++++++++++++-
src/main/daemon/daemon-init.ts | 86 ++++++++++-------
src/main/daemon/daemon-server.test.ts | 15 +++
src/main/daemon/daemon-server.ts | 8 ++
src/main/daemon/pty-subprocess.test.ts | 65 ++++++++++++-
src/main/daemon/pty-subprocess.ts | 70 ++++++++++++++
src/main/daemon/types.ts | 10 +-
10 files changed, 362 insertions(+), 53 deletions(-)
diff --git a/src/main/daemon/daemon-health-socket-cleanup.test.ts b/src/main/daemon/daemon-health-socket-cleanup.test.ts
index a6404ed0220..8d2f8e9ad96 100644
--- a/src/main/daemon/daemon-health-socket-cleanup.test.ts
+++ b/src/main/daemon/daemon-health-socket-cleanup.test.ts
@@ -42,7 +42,12 @@ describe('daemon health socket listener cleanup', () => {
const result = healthCheckDaemon(socketPath, tokenPath)
socket.emit('connect')
- socket.emit('data', Buffer.from('{"type":"hello","ok":true}\n{"id":"health-1","ok":true}\n'))
+ socket.emit(
+ 'data',
+ Buffer.from(
+ '{"type":"hello","ok":true}\n{"id":"health-1","ok":true}\n{"id":"health-2","ok":true}\n'
+ )
+ )
await expect(result).resolves.toBe(true)
expect(socket.listenerCount('connect')).toBe(0)
diff --git a/src/main/daemon/daemon-health.test.ts b/src/main/daemon/daemon-health.test.ts
index 92220f8d548..6bf71a37f98 100644
--- a/src/main/daemon/daemon-health.test.ts
+++ b/src/main/daemon/daemon-health.test.ts
@@ -74,15 +74,36 @@ describe('daemon health', () => {
})
it('passes when a daemon answers ping', async () => {
+ const ptySpawnHealthCheck = vi.fn(async () => {})
const server = new DaemonServer({
socketPath,
tokenPath,
+ ptySpawnHealthCheck,
spawnSubprocess: () => createMockSubprocess()
})
await server.start()
try {
await expect(healthCheckDaemon(socketPath, tokenPath)).resolves.toBe(true)
+ expect(ptySpawnHealthCheck).toHaveBeenCalledOnce()
+ } finally {
+ await server.shutdown()
+ }
+ })
+
+ it('fails when a protocol-healthy daemon cannot spawn PTYs', async () => {
+ const server = new DaemonServer({
+ socketPath,
+ tokenPath,
+ ptySpawnHealthCheck: vi.fn(async () => {
+ throw new Error('stale node-pty helper')
+ }),
+ spawnSubprocess: () => createMockSubprocess()
+ })
+ await server.start()
+
+ try {
+ await expect(healthCheckDaemon(socketPath, tokenPath)).resolves.toBe(false)
} finally {
await server.shutdown()
}
diff --git a/src/main/daemon/daemon-health.ts b/src/main/daemon/daemon-health.ts
index 049743aa97e..e74e3a848db 100644
--- a/src/main/daemon/daemon-health.ts
+++ b/src/main/daemon/daemon-health.ts
@@ -19,6 +19,8 @@ const KILL_WAIT_MS = 3_000
const KILL_POLL_MS = 100
const START_TIME_TOLERANCE_MS = 1_500
+export type DaemonHealthCheckResult = 'healthy' | 'unhealthy' | 'pty-spawn-unhealthy'
+
type ParsedDaemonPid = {
pid: number
startedAtMs: number | null
@@ -63,10 +65,13 @@ function canConnectSocket(socketPath: string): Promise {
})
}
-export function healthCheckDaemon(socketPath: string, tokenPath: string): Promise {
+export function checkDaemonHealth(
+ socketPath: string,
+ tokenPath: string
+): Promise {
return new Promise((resolve) => {
if (process.platform !== 'win32' && !existsSync(socketPath)) {
- resolve(false)
+ resolve('unhealthy')
return
}
@@ -74,13 +79,13 @@ export function healthCheckDaemon(socketPath: string, tokenPath: string): Promis
try {
token = readFileSync(tokenPath, 'utf8').trim()
} catch {
- resolve(false)
+ resolve('unhealthy')
return
}
let settled = false
let sock: Socket | null = null
- const settle = (result: boolean): void => {
+ const settle = (result: DaemonHealthCheckResult): void => {
if (settled) {
return
}
@@ -95,7 +100,7 @@ export function healthCheckDaemon(socketPath: string, tokenPath: string): Promis
sock?.off('connect', onConnect)
sock?.off('data', onData)
}
- const onError = (): void => settle(false)
+ const onError = (): void => settle('unhealthy')
const onConnect = (): void => {
const hello: HelloMessage = {
type: 'hello',
@@ -126,13 +131,13 @@ export function healthCheckDaemon(socketPath: string, tokenPath: string): Promis
try {
message = JSON.parse(line) as Record
} catch {
- settle(false)
+ settle('unhealthy')
return
}
if (message.type === 'hello') {
if (!(message as HelloResponse).ok) {
- settle(false)
+ settle('unhealthy')
return
}
sock?.write(encodeNdjson({ id: 'health-1', type: 'ping' }))
@@ -140,12 +145,24 @@ export function healthCheckDaemon(socketPath: string, tokenPath: string): Promis
}
if (message.id === 'health-1') {
- settle(Boolean(message.ok))
+ if (!message.ok) {
+ settle('unhealthy')
+ return
+ }
+ // Why: protocol ping only proves the socket loop is alive. New
+ // terminals also depend on node-pty's native helper state inside
+ // the daemon process, which can go stale after dev rebuilds.
+ sock?.write(encodeNdjson({ id: 'health-2', type: 'ptySpawnHealth' }))
+ continue
+ }
+
+ if (message.id === 'health-2') {
+ settle(message.ok ? 'healthy' : 'pty-spawn-unhealthy')
return
}
}
}
- const timer = setTimeout(() => settle(false), HEALTH_CHECK_TIMEOUT_MS)
+ const timer = setTimeout(() => settle('unhealthy'), HEALTH_CHECK_TIMEOUT_MS)
sock = connect({ path: socketPath })
sock.on('error', onError)
@@ -156,6 +173,10 @@ export function healthCheckDaemon(socketPath: string, tokenPath: string): Promis
})
}
+export async function healthCheckDaemon(socketPath: string, tokenPath: string): Promise {
+ return (await checkDaemonHealth(socketPath, tokenPath)) === 'healthy'
+}
+
function isSystemResolverHealth(value: unknown): value is SystemResolverHealth {
return value === 'healthy' || value === 'unhealthy' || value === 'unknown'
}
diff --git a/src/main/daemon/daemon-init.test.ts b/src/main/daemon/daemon-init.test.ts
index 8e3be87a60b..e320609ef09 100644
--- a/src/main/daemon/daemon-init.test.ts
+++ b/src/main/daemon/daemon-init.test.ts
@@ -20,6 +20,7 @@ const {
writeFileSyncMock,
netConnectMock,
forkMock,
+ checkDaemonHealthMock,
healthCheckDaemonMock,
getMacDaemonSystemResolverHealthMock,
getDaemonLaunchIdentityMock,
@@ -66,6 +67,7 @@ const {
}
})
+ const checkDaemonHealthMock = vi.fn(async () => 'healthy')
const healthCheckDaemonMock = vi.fn(async () => true)
const getMacDaemonSystemResolverHealthMock = vi.fn(() => 'healthy')
const getDaemonLaunchIdentityMock = vi.fn(() => 'match')
@@ -101,6 +103,7 @@ const {
writeFileSyncMock,
netConnectMock,
forkMock,
+ checkDaemonHealthMock,
healthCheckDaemonMock,
getMacDaemonSystemResolverHealthMock,
getDaemonLaunchIdentityMock,
@@ -172,6 +175,7 @@ vi.mock('child_process', () => ({ fork: forkMock }))
vi.mock('net', () => ({ connect: netConnectMock }))
vi.mock('./daemon-health', () => ({
+ checkDaemonHealth: checkDaemonHealthMock,
getDaemonLaunchIdentity: getDaemonLaunchIdentityMock,
getMacDaemonSystemResolverHealth: getMacDaemonSystemResolverHealthMock,
healthCheckDaemon: healthCheckDaemonMock,
@@ -268,6 +272,8 @@ async function importFresh() {
setLocalPtyProviderMock.mockClear()
unbindLocalProviderListenersMock.mockClear()
rebindLocalProviderListenersMock.mockClear()
+ checkDaemonHealthMock.mockClear()
+ checkDaemonHealthMock.mockResolvedValue('healthy')
healthCheckDaemonMock.mockClear()
getMacDaemonSystemResolverHealthMock.mockReset()
getMacDaemonSystemResolverHealthMock.mockReturnValue('healthy')
@@ -1025,7 +1031,7 @@ describe('daemon-init: runRestartDaemon (7-step sequence)', () => {
probeSocketExistsMock.mockImplementation(
(p?: string) => p === '/fake/app/out/main/daemon-entry.js'
)
- healthCheckDaemonMock.mockResolvedValueOnce(false)
+ checkDaemonHealthMock.mockResolvedValueOnce('unhealthy')
const mod = await importFresh()
getAppPathMock.mockReturnValue('/fake/app/out/main')
await mod.initDaemonPtyProvider()
@@ -1068,7 +1074,7 @@ describe('daemon-init: runRestartDaemon (7-step sequence)', () => {
})
it('removes detached daemon startup listeners after readiness', async () => {
- healthCheckDaemonMock.mockResolvedValueOnce(false)
+ checkDaemonHealthMock.mockResolvedValueOnce('unhealthy')
const mod = await importFresh()
await mod.initDaemonPtyProvider()
@@ -1123,7 +1129,7 @@ describe('daemon-init: runRestartDaemon (7-step sequence)', () => {
})
it('removes detached daemon startup listeners after startup error', async () => {
- healthCheckDaemonMock.mockResolvedValueOnce(false)
+ checkDaemonHealthMock.mockResolvedValueOnce('unhealthy')
const mod = await importFresh()
await mod.initDaemonPtyProvider()
@@ -1167,6 +1173,88 @@ describe('daemon-init: runRestartDaemon (7-step sequence)', () => {
expect(child.unref).not.toHaveBeenCalled()
})
+ it('preserves a spawn-unhealthy daemon when it owns live sessions', async () => {
+ const mod = await importFresh()
+ await mod.initDaemonPtyProvider()
+
+ const requestMock = vi.fn(async (method: string) => {
+ if (method === 'listSessions') {
+ return {
+ sessions: [{ sessionId: 'wt-1@@live', isAlive: true }]
+ }
+ }
+ return {}
+ })
+ const disconnectMock = vi.fn()
+ daemonClientMock.mockImplementationOnce(function MockDaemonClient() {
+ return {
+ ensureConnected: vi.fn(async () => {}),
+ request: requestMock,
+ disconnect: disconnectMock
+ }
+ })
+
+ const launcher = spawnerInstances[0].launcher as (
+ socketPath: string,
+ tokenPath: string
+ ) => Promise<{ shutdown(): Promise }>
+ checkDaemonHealthMock.mockResolvedValueOnce('pty-spawn-unhealthy')
+
+ await launcher('/fake/socket', '/fake/token')
+
+ expect(requestMock).toHaveBeenCalledWith('listSessions', undefined)
+ expect(disconnectMock).toHaveBeenCalledOnce()
+ expect(killStaleDaemonMock).not.toHaveBeenCalled()
+ expect(forkMock).not.toHaveBeenCalled()
+ })
+
+ it('replaces a spawn-unhealthy daemon when no live sessions would be lost', async () => {
+ const mod = await importFresh()
+ await mod.initDaemonPtyProvider()
+
+ const launcher = spawnerInstances[0].launcher as (
+ socketPath: string,
+ tokenPath: string
+ ) => Promise<{ shutdown(): Promise }>
+ checkDaemonHealthMock.mockResolvedValueOnce('pty-spawn-unhealthy')
+ forkMock.mockImplementationOnce(() => {
+ const handlers: Record void)[]> = {
+ message: [],
+ error: [],
+ exit: []
+ }
+ return {
+ pid: 12345,
+ on(event: string, cb: (arg?: unknown) => void) {
+ handlers[event]?.push(cb)
+ if (event === 'message') {
+ queueMicrotask(() => cb({ type: 'ready' }))
+ }
+ return this
+ },
+ off(event: string, cb: (arg?: unknown) => void) {
+ handlers[event] = handlers[event]?.filter((handler) => handler !== cb) ?? []
+ return this
+ },
+ disconnect: vi.fn(),
+ unref: vi.fn()
+ }
+ })
+
+ await launcher('/fake/socket', '/fake/token')
+
+ expect(killStaleDaemonMock).toHaveBeenCalledWith(
+ '/fake/userData/daemon',
+ '/fake/socket',
+ '/fake/token'
+ )
+ expect(forkMock).toHaveBeenCalledWith(
+ '/fake/app/out/main/daemon-entry.js',
+ ['--socket', '/fake/socket', '--token', '/fake/token'],
+ expect.objectContaining({ detached: true })
+ )
+ })
+
it('preserves a packaged healthy daemon when its app bundle is current', async () => {
const mod = await importFresh()
await mod.initDaemonPtyProvider()
diff --git a/src/main/daemon/daemon-init.ts b/src/main/daemon/daemon-init.ts
index cd9e335bc45..28807352612 100644
--- a/src/main/daemon/daemon-init.ts
+++ b/src/main/daemon/daemon-init.ts
@@ -28,10 +28,10 @@ import {
type ListSessionsResult
} from './types'
import {
+ checkDaemonHealth,
getMacDaemonSystemResolverHealth,
getDaemonLaunchIdentity,
getProcessStartedAtMs,
- healthCheckDaemon,
isDaemonStaleForCurrentBundle,
killStaleDaemon
} from './daemon-health'
@@ -164,49 +164,65 @@ async function shouldPreserveDaemonWithLiveSessions(
function createOutOfProcessLauncher(runtimeDir: string): DaemonLauncher {
return async (socketPath, tokenPath) => {
const entryPath = getDaemonEntryPath()
- const healthy = await healthCheckDaemon(socketPath, tokenPath)
- if (healthy) {
- const resolverHealth = await getMacDaemonSystemResolverHealth(socketPath, tokenPath)
- if (resolverHealth === 'unhealthy') {
- const liveSessionCount = await getAliveDaemonSessionCount(socketPath, tokenPath)
- if (liveSessionCount !== 0) {
- console.warn(
- liveSessionCount === null
- ? '[daemon] Preserving daemon with unavailable macOS system resolver because live session state could not be verified'
- : `[daemon] Preserving daemon with unavailable macOS system resolver because it owns ${liveSessionCount} live session${liveSessionCount === 1 ? '' : 's'}`
+ const health = await checkDaemonHealth(socketPath, tokenPath)
+ if (health !== 'unhealthy') {
+ if (health === 'pty-spawn-unhealthy') {
+ if (
+ await shouldPreserveDaemonWithLiveSessions(
+ socketPath,
+ tokenPath,
+ 'that cannot spawn new PTYs'
)
+ ) {
return createPreservedDaemonHandle(runtimeDir)
}
- console.warn('[daemon] Replacing daemon with unavailable macOS system resolver')
+ console.warn('[daemon] Replacing daemon that cannot spawn new PTYs')
await cleanupDaemonForProtocol(runtimeDir, PROTOCOL_VERSION)
} else {
- // Why: a protocol-healthy daemon can outlive the app bundle that
- // launched it. In dev this happens after deleting/rebuilding a
- // worktree; in packaged apps it happens when the stable
- // /Applications/Orca.app path is replaced during update.
- const identity = getDaemonLaunchIdentity(runtimeDir, socketPath, tokenPath, entryPath)
- const stalePackagedBundle =
- app.isPackaged &&
- isDaemonStaleForCurrentBundle(runtimeDir, socketPath, tokenPath, app.getVersion())
- if (identity === 'mismatch' || stalePackagedBundle) {
- // Why: replacing a healthy daemon kills its child PTYs; defer code
- // freshness until no live terminal sessions would be lost.
- const replacementLabel = stalePackagedBundle
- ? 'launched before the current app bundle was installed'
- : 'launched from a different app path'
- if (await shouldPreserveDaemonWithLiveSessions(socketPath, tokenPath, replacementLabel)) {
+ const resolverHealth = await getMacDaemonSystemResolverHealth(socketPath, tokenPath)
+ if (resolverHealth === 'unhealthy') {
+ const liveSessionCount = await getAliveDaemonSessionCount(socketPath, tokenPath)
+ if (liveSessionCount !== 0) {
+ console.warn(
+ liveSessionCount === null
+ ? '[daemon] Preserving daemon with unavailable macOS system resolver because live session state could not be verified'
+ : `[daemon] Preserving daemon with unavailable macOS system resolver because it owns ${liveSessionCount} live session${liveSessionCount === 1 ? '' : 's'}`
+ )
return createPreservedDaemonHandle(runtimeDir)
}
- console.warn(
- stalePackagedBundle
- ? '[daemon] Replacing daemon launched before the current app bundle was installed'
- : '[daemon] Replacing daemon launched from a different app path'
- )
+ console.warn('[daemon] Replacing daemon with unavailable macOS system resolver')
await cleanupDaemonForProtocol(runtimeDir, PROTOCOL_VERSION)
} else {
- // Why: daemon is already running from a previous app session and
- // responded to a protocol-level ping. Safe to reuse.
- return createPreservedDaemonHandle(runtimeDir)
+ // Why: a protocol-healthy daemon can outlive the app bundle that
+ // launched it. In dev this happens after deleting/rebuilding a
+ // worktree; in packaged apps it happens when the stable
+ // /Applications/Orca.app path is replaced during update.
+ const identity = getDaemonLaunchIdentity(runtimeDir, socketPath, tokenPath, entryPath)
+ const stalePackagedBundle =
+ app.isPackaged &&
+ isDaemonStaleForCurrentBundle(runtimeDir, socketPath, tokenPath, app.getVersion())
+ if (identity === 'mismatch' || stalePackagedBundle) {
+ // Why: replacing a healthy daemon kills its child PTYs; defer code
+ // freshness until no live terminal sessions would be lost.
+ const replacementLabel = stalePackagedBundle
+ ? 'launched before the current app bundle was installed'
+ : 'launched from a different app path'
+ if (
+ await shouldPreserveDaemonWithLiveSessions(socketPath, tokenPath, replacementLabel)
+ ) {
+ return createPreservedDaemonHandle(runtimeDir)
+ }
+ console.warn(
+ stalePackagedBundle
+ ? '[daemon] Replacing daemon launched before the current app bundle was installed'
+ : '[daemon] Replacing daemon launched from a different app path'
+ )
+ await cleanupDaemonForProtocol(runtimeDir, PROTOCOL_VERSION)
+ } else {
+ // Why: daemon is already running from a previous app session and
+ // responded to a protocol-level ping. Safe to reuse.
+ return createPreservedDaemonHandle(runtimeDir)
+ }
}
}
}
diff --git a/src/main/daemon/daemon-server.test.ts b/src/main/daemon/daemon-server.test.ts
index feb9fe9259e..7d10ce1f10a 100644
--- a/src/main/daemon/daemon-server.test.ts
+++ b/src/main/daemon/daemon-server.test.ts
@@ -198,6 +198,21 @@ describe('DaemonServer', () => {
expect(result).toEqual({ pong: true })
})
+ it('handles ptySpawnHealth through the daemon process', async () => {
+ const ptySpawnHealthCheck = vi.fn(async () => {})
+ server = new DaemonServer({
+ socketPath,
+ tokenPath,
+ ptySpawnHealthCheck,
+ spawnSubprocess: () => createMockSubprocess()
+ })
+ await server.start()
+ const c = await connectClient()
+
+ await expect(c.request('ptySpawnHealth', undefined)).resolves.toEqual({ healthy: true })
+ expect(ptySpawnHealthCheck).toHaveBeenCalledOnce()
+ })
+
it('handles systemResolverHealth', async () => {
await startServer()
const c = await connectClient()
diff --git a/src/main/daemon/daemon-server.ts b/src/main/daemon/daemon-server.ts
index 558a41b53f9..7d9940470aa 100644
--- a/src/main/daemon/daemon-server.ts
+++ b/src/main/daemon/daemon-server.ts
@@ -11,6 +11,7 @@ import { TerminalHost } from './terminal-host'
import { DaemonStreamDataBatcher } from './daemon-stream-data-batcher'
import { readCurrentProcessMacSystemResolverHealth } from '../network/macos-system-resolver-health'
import type { SubprocessHandle } from './session'
+import { checkPtySpawnHealth } from './pty-subprocess'
import {
PROTOCOL_VERSION,
NOTIFY_PREFIX,
@@ -22,6 +23,7 @@ import {
export type DaemonServerOptions = {
socketPath: string
tokenPath: string
+ ptySpawnHealthCheck?: () => Promise
spawnSubprocess: (opts: {
sessionId: string
cols: number
@@ -45,6 +47,7 @@ export class DaemonServer {
private host: TerminalHost
private socketPath: string
private tokenPath: string
+ private ptySpawnHealthCheck: () => Promise
private clients = new Map()
private streamDataBatcher = new DaemonStreamDataBatcher((clientId) => this.clients.get(clientId))
@@ -62,6 +65,7 @@ export class DaemonServer {
this.tokenPath = opts.tokenPath
this.token = randomUUID()
this.host = new TerminalHost({ spawnSubprocess: opts.spawnSubprocess })
+ this.ptySpawnHealthCheck = opts.ptySpawnHealthCheck ?? checkPtySpawnHealth
}
async start(): Promise {
@@ -375,6 +379,10 @@ export class DaemonServer {
case 'systemResolverHealth':
return { health: await readCurrentProcessMacSystemResolverHealth() }
+ case 'ptySpawnHealth':
+ await this.ptySpawnHealthCheck()
+ return { healthy: true }
+
case 'shutdown':
if (request.payload.killSessions) {
this.host.dispose()
diff --git a/src/main/daemon/pty-subprocess.test.ts b/src/main/daemon/pty-subprocess.test.ts
index a9a5fef3253..ad62e6272d1 100644
--- a/src/main/daemon/pty-subprocess.test.ts
+++ b/src/main/daemon/pty-subprocess.test.ts
@@ -1,13 +1,19 @@
/* oxlint-disable max-lines -- Why: exercises full PTY subprocess surface (spawn setup, signal routing, data events, platform-specific shell configs, and Windows PowerShell implementations) with co-located test scenarios to prevent fixture drift. */
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-import { mkdtempSync, realpathSync, rmSync } from 'fs'
+import { mkdtempSync, realpathSync, rmSync, writeFileSync } from 'fs'
import { tmpdir } from 'os'
import { join } from 'path'
import type * as LocalPtyUtils from '../providers/local-pty-utils'
-const { spawnMock, isPwshAvailableMock, validateWorkingDirectoryMock } = vi.hoisted(() => ({
+const {
+ spawnMock,
+ isPwshAvailableMock,
+ validateWorkingDirectoryMock,
+ getNodePtySpawnHelperCandidatesMock
+} = vi.hoisted(() => ({
spawnMock: vi.fn(),
isPwshAvailableMock: vi.fn(),
+ getNodePtySpawnHelperCandidatesMock: vi.fn(),
validateWorkingDirectoryMock: vi.fn((cwd: string) => {
if (cwd.includes('definitely-missing')) {
throw new Error(
@@ -29,11 +35,12 @@ vi.mock('../providers/local-pty-utils', async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
+ getNodePtySpawnHelperCandidates: getNodePtySpawnHelperCandidatesMock,
validateWorkingDirectory: validateWorkingDirectoryMock
}
})
-import { createPtySubprocess } from './pty-subprocess'
+import { checkPtySpawnHealth, createPtySubprocess } from './pty-subprocess'
const ORCA_SHELL_WRAPPER_ENV = [
'ORCA_ATTRIBUTION_SHIM_DIR',
@@ -79,6 +86,10 @@ describe('createPtySubprocess', () => {
isPwshAvailableMock.mockReturnValue(false)
previousUserDataPath = process.env.ORCA_USER_DATA_PATH
userDataPath = mkdtempSync(join(tmpdir(), 'daemon-pty-subprocess-test-'))
+ const spawnHelperPath = join(userDataPath, 'spawn-helper')
+ writeFileSync(spawnHelperPath, '')
+ getNodePtySpawnHelperCandidatesMock.mockReset()
+ getNodePtySpawnHelperCandidatesMock.mockReturnValue([spawnHelperPath])
process.env.ORCA_USER_DATA_PATH = userDataPath
for (const key of ORCA_SHELL_WRAPPER_ENV) {
savedWrapperEnv[key] = process.env[key]
@@ -169,6 +180,54 @@ describe('createPtySubprocess', () => {
)
})
+ it('checks macOS PTY spawn health with a short-lived shell', async () => {
+ const proc = mockPtyProcess()
+ spawnMock.mockReturnValue(proc)
+ const platform = Object.getOwnPropertyDescriptor(process, 'platform')
+ Object.defineProperty(process, 'platform', { value: 'darwin' })
+
+ try {
+ const result = checkPtySpawnHealth()
+ proc._simulateExit(0)
+ await expect(result).resolves.toBeUndefined()
+ expect(proc.kill).not.toHaveBeenCalled()
+ } finally {
+ if (platform) {
+ Object.defineProperty(process, 'platform', platform)
+ }
+ }
+
+ expect(spawnMock).toHaveBeenCalledWith(
+ '/bin/sh',
+ ['-c', 'exit 0'],
+ expect.objectContaining({
+ cols: 2,
+ rows: 1,
+ cwd: userDataPath,
+ name: 'xterm-256color'
+ })
+ )
+ })
+
+ it('surfaces stale node-pty helper failures during macOS PTY spawn health', async () => {
+ spawnMock.mockImplementation(() => {
+ throw new Error(
+ "node-pty: posix_spawn failed: ENOENT (errno 2, No such file or directory) - helper='/tmp/deleted/spawn-helper'"
+ )
+ })
+ const platform = Object.getOwnPropertyDescriptor(process, 'platform')
+ Object.defineProperty(process, 'platform', { value: 'darwin' })
+
+ try {
+ await expect(checkPtySpawnHealth()).rejects.toThrow('Daemon failed to spawn shell "/bin/sh"')
+ await expect(checkPtySpawnHealth()).rejects.toThrow('posix_spawn failed: ENOENT')
+ } finally {
+ if (platform) {
+ Object.defineProperty(process, 'platform', platform)
+ }
+ }
+ })
+
it('returns a SubprocessHandle with correct pid', () => {
const proc = mockPtyProcess(42)
spawnMock.mockReturnValue(proc)
diff --git a/src/main/daemon/pty-subprocess.ts b/src/main/daemon/pty-subprocess.ts
index 8f6fb96a313..53287122abc 100644
--- a/src/main/daemon/pty-subprocess.ts
+++ b/src/main/daemon/pty-subprocess.ts
@@ -29,6 +29,7 @@ import { isWindowsGitBashShellPath, resolveWindowsGitBashShellPath } from '../gi
import { WINDOWS_GIT_BASH_SHELL } from '../../shared/windows-terminal-shell'
const PANE_IDENTITY_ENV_KEYS = ['ORCA_PANE_KEY', 'ORCA_TAB_ID', 'ORCA_WORKTREE_ID'] as const
+const PTY_SPAWN_HEALTH_TIMEOUT_MS = 2_000
export type PtySubprocessOptions = {
sessionId: string
@@ -231,6 +232,75 @@ function formatPtySpawnError(err: unknown, shellPath: string, spawnCwd: string):
return formatted
}
+export async function checkPtySpawnHealth(): Promise {
+ if (process.platform !== 'darwin') {
+ return
+ }
+
+ ensureNodePtySpawnHelperExecutable()
+ preflightMacNodePtySpawnEnvironment()
+
+ const cwd = isExistingDirectory(process.env.ORCA_USER_DATA_PATH)
+ ? process.env.ORCA_USER_DATA_PATH
+ : getDefaultCwd()
+
+ let proc: pty.IPty
+ try {
+ proc = pty.spawn('/bin/sh', ['-c', 'exit 0'], {
+ name: 'xterm-256color',
+ cols: 2,
+ rows: 1,
+ cwd,
+ env: {
+ ...process.env,
+ TERM: 'xterm-256color'
+ }
+ })
+ } catch (err) {
+ throw formatPtySpawnError(err, '/bin/sh', cwd)
+ }
+
+ await new Promise((resolve, reject) => {
+ let settled = false
+ let exitDisposable: { dispose(): void } | undefined
+ const finish = (error?: Error, opts?: { kill?: boolean }): void => {
+ if (settled) {
+ return
+ }
+ settled = true
+ clearTimeout(timer)
+ exitDisposable?.dispose()
+ if (opts?.kill) {
+ try {
+ proc.kill()
+ } catch {
+ // Best-effort cleanup for a short-lived health probe.
+ }
+ }
+ if (error) {
+ reject(error)
+ return
+ }
+ resolve()
+ }
+ const timer = setTimeout(() => {
+ finish(new Error(`PTY spawn health check timed out after ${PTY_SPAWN_HEALTH_TIMEOUT_MS}ms`), {
+ kill: true
+ })
+ }, PTY_SPAWN_HEALTH_TIMEOUT_MS)
+
+ // Why: ping only proves the daemon protocol is alive. A real short-lived
+ // PTY spawn catches stale node-pty helper paths captured by this process.
+ exitDisposable = proc.onExit(({ exitCode }) => {
+ if (exitCode === 0) {
+ finish()
+ return
+ }
+ finish(new Error(`PTY spawn health check exited with code ${exitCode}`))
+ })
+ })
+}
+
function normalizeForegroundProcessName(processName: string | null | undefined): string | null {
const trimmed = processName?.trim().replace(/^["']|["']$/g, '') ?? ''
if (!trimmed || trimmed === 'xterm-256color') {
diff --git a/src/main/daemon/types.ts b/src/main/daemon/types.ts
index f0eeb9d0af8..abac7f20dee 100644
--- a/src/main/daemon/types.ts
+++ b/src/main/daemon/types.ts
@@ -3,8 +3,8 @@
// when daemon-baked behavior cannot be delivered by on-disk wrapper refresh.
// Why: bump when adding daemon wire behavior so same-version old daemons do
// not silently accept the handshake and then reject new RPCs.
-export const PROTOCOL_VERSION = 11
-export const PREVIOUS_DAEMON_PROTOCOL_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as const
+export const PROTOCOL_VERSION = 12
+export const PREVIOUS_DAEMON_PROTOCOL_VERSIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] as const
// ─── Session State Machine ──────────────────────────────────────────
export type SessionState = 'created' | 'spawning' | 'running' | 'exiting' | 'exited'
@@ -182,6 +182,11 @@ export type SystemResolverHealthRequest = {
type: 'systemResolverHealth'
}
+export type PtySpawnHealthRequest = {
+ id: string
+ type: 'ptySpawnHealth'
+}
+
export type GetSnapshotRequest = {
id: string
type: 'getSnapshot'
@@ -205,6 +210,7 @@ export type DaemonRequest =
| ShutdownRequest
| PingRequest
| SystemResolverHealthRequest
+ | PtySpawnHealthRequest
| GetSnapshotRequest
// ─── RPC Responses (Daemon → Client, on control socket) ────────────
From a26a4e48945944fc25b0f081973f6fed67f63679 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Tue, 9 Jun 2026 23:57:43 -0400
Subject: [PATCH 020/165] Suspend floating workspace terminal WebGL while the
panel is closed (#5073)
Co-authored-by: Orca
---
.../FloatingTerminalPanel.test.tsx | 35 ++++++-----------
.../FloatingTerminalPanel.tsx | 37 ++++--------------
.../use-terminal-pane-global-effects.test.ts | 38 +------------------
.../use-terminal-pane-global-effects.ts | 19 +---------
src/renderer/src/constants/terminal.ts | 8 ----
...ng-workspace-reopen-webgl-recovery.spec.ts | 18 ++++-----
6 files changed, 30 insertions(+), 125 deletions(-)
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
index 14888bd029e..1773a295335 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
@@ -2,7 +2,6 @@
* React/store environment directly so close and bootstrap behavior can be
* asserted without mounting the full Electron renderer. */
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-import { RESET_TERMINAL_WEBGL_ATLAS_EVENT } from '@/constants/terminal'
import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../../shared/constants'
import type { BrowserTab, Tab, TabGroup, TerminalTab } from '../../../../shared/types'
import type { OpenFile } from '@/store/slices/editor'
@@ -594,9 +593,6 @@ describe('FloatingTerminalPanel close behavior', () => {
}
vi.stubGlobal('window', {
addEventListener: vi.fn(),
- // Why: the open-transition effect dispatches the WebGL atlas recovery
- // event; the stubbed window needs a sink for it.
- dispatchEvent: vi.fn(),
api: {
app: {
getFloatingMarkdownDirectory: mocks.getFloatingMarkdownDirectory,
@@ -956,30 +952,23 @@ describe('FloatingTerminalPanel close behavior', () => {
expect(mocks.focusTerminalTabSurface).toHaveBeenCalledWith('created-tab')
})
- it('dispatches WebGL atlas recovery for the active terminal on reopen', async () => {
+ it('hides the active terminal pane from the renderer while the panel is closed', async () => {
setFloatingTabs([makeTab({ id: 'tab-1' })])
+ // Why: the closed panel stays mounted but CSS-hidden; gating isVisible on
+ // `open` routes the terminal through the standard hidden-terminal WebGL
+ // suspend/resume path so no live glyph atlas can corrupt while hidden.
await renderPanel(false)
runEffects()
- vi.mocked(window.dispatchEvent).mockClear()
+ await Promise.resolve()
+ const closedElement = await renderPanel(false)
+ const closedPane = findByTypeName(closedElement, 'TerminalPane')
+ expect(closedPane.props.isActive).toBe(true)
+ expect(closedPane.props.isVisible).toBe(false)
- const countResetEvents = (): CustomEvent<{ tabId?: string }>[] =>
- vi
- .mocked(window.dispatchEvent)
- .mock.calls.map(([event]) => event as CustomEvent<{ tabId?: string }>)
- .filter((event) => event.type === RESET_TERMINAL_WEBGL_ATLAS_EVENT)
-
- await renderPanel(true)
- runEffects()
-
- const resetEvents = countResetEvents()
- expect(resetEvents).toHaveLength(1)
- expect(resetEvents[0]?.detail?.tabId).toBe('tab-1')
-
- // Why: re-renders while the panel stays open must not re-clear the atlas.
- await renderPanel(true)
- runEffects()
- expect(countResetEvents()).toHaveLength(1)
+ const openElement = await renderPanel(true)
+ const openPane = findByTypeName(openElement, 'TerminalPane')
+ expect(openPane.props.isVisible).toBe(true)
})
it('routes titlebar Cmd+T to the floating workspace', async () => {
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
index 287e5f76161..151041ab648 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
@@ -19,10 +19,6 @@ import { ShortcutKeyCombo } from '@/components/ShortcutKeyCombo'
import TabBar from '@/components/tab-bar/TabBar'
import { resolveGroupTabFromVisibleId } from '@/components/tab-group/tab-group-visible-id'
import TerminalPane from '@/components/terminal-pane/TerminalPane'
-import {
- RESET_TERMINAL_WEBGL_ATLAS_EVENT,
- type ResetTerminalWebglAtlasDetail
-} from '@/constants/terminal'
import { Button } from '@/components/ui/button'
import { useMountedRef } from '@/hooks/useMountedRef'
import { useShortcutKeys } from '@/hooks/useShortcutLabel'
@@ -532,31 +528,6 @@ export function FloatingTerminalPanel({
focusTerminalTabSurface(activeTerminalId)
}, [activeTerminalId, open])
- const wasOpenForAtlasRecoveryRef = useRef(false)
- useEffect(() => {
- if (!open) {
- wasOpenForAtlasRecoveryRef.current = false
- return
- }
- if (wasOpenForAtlasRecoveryRef.current) {
- return
- }
- wasOpenForAtlasRecoveryRef.current = true
- if (!activeTerminalId) {
- return
- }
- // Why: closing the panel only hides it with CSS, so the active terminal
- // keeps a live WebGL context while hidden and reopening never flips
- // TerminalPane visibility. A glyph atlas corrupted while hidden (no
- // context-loss event) would otherwise stay garbled until another
- // recovery trigger such as window refocus.
- window.dispatchEvent(
- new CustomEvent(RESET_TERMINAL_WEBGL_ATLAS_EVENT, {
- detail: { tabId: activeTerminalId }
- })
- )
- }, [activeTerminalId, open])
-
useEffect(() => {
if (!open || hasVisibleFloatingTabs) {
return
@@ -1393,7 +1364,13 @@ export function FloatingTerminalPanel({
worktreeId={FLOATING_TERMINAL_WORKTREE_ID}
cwd={cwd}
isActive={isActive}
- isVisible={isActive}
+ // Why: the closed panel is only CSS-hidden, so gate
+ // visibility on `open` too. This routes the floating
+ // terminal through the standard hidden-terminal
+ // suspend/resume path: no live WebGL context (or glyph
+ // atlas to corrupt) while hidden, and the resume on
+ // reopen rebuilds the renderer from scratch.
+ isVisible={isActive && open}
onPtyExit={() => closeTab(tab.id)}
onCloseTab={() => closeFloatingItem(tab.id)}
/>
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
index 1ab57576c1e..245165b5b67 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
@@ -1,7 +1,7 @@
/* eslint-disable max-lines -- Why: these hook tests share a mocked React lifecycle harness with global event cases. */
import type * as ReactModule from 'react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-import { RESET_TERMINAL_WEBGL_ATLAS_EVENT, SYNC_FIT_PANES_EVENT } from '@/constants/terminal'
+import { SYNC_FIT_PANES_EVENT } from '@/constants/terminal'
import { useTerminalPaneGlobalEffects } from './use-terminal-pane-global-effects'
const mocks = vi.hoisted(() => ({
@@ -359,42 +359,6 @@ describe('useTerminalPaneGlobalEffects', () => {
expect(manager.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
})
- it('clears WebGL texture atlases for a matching reset-atlas event', () => {
- const { manager } = useMountForFileDrop()
-
- const resetListener = vi
- .mocked(window.addEventListener)
- .mock.calls.find(([eventName]) => eventName === RESET_TERMINAL_WEBGL_ATLAS_EVENT)
-
- expect(resetListener).toBeDefined()
- const listener = resetListener?.[1]
- if (typeof listener !== 'function') {
- throw new Error('expected reset-atlas listener')
- }
- manager.resetWebglTextureAtlases.mockClear()
- listener(new CustomEvent(RESET_TERMINAL_WEBGL_ATLAS_EVENT, { detail: { tabId: 'tab-1' } }))
-
- expect(manager.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
- })
-
- it('ignores reset-atlas events for another terminal tab', () => {
- const { manager } = useMountForFileDrop()
-
- const resetListener = vi
- .mocked(window.addEventListener)
- .mock.calls.find(([eventName]) => eventName === RESET_TERMINAL_WEBGL_ATLAS_EVENT)
-
- expect(resetListener).toBeDefined()
- const listener = resetListener?.[1]
- if (typeof listener !== 'function') {
- throw new Error('expected reset-atlas listener')
- }
- manager.resetWebglTextureAtlases.mockClear()
- listener(new CustomEvent(RESET_TERMINAL_WEBGL_ATLAS_EVENT, { detail: { tabId: 'tab-2' } }))
-
- expect(manager.resetWebglTextureAtlases).not.toHaveBeenCalled()
- })
-
it('ignores terminal file drops for another terminal tab', () => {
const { onFileDrop } = useMountForFileDrop()
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
index 9e7ff81300e..902004d5a99 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
@@ -2,11 +2,9 @@ import { useEffect, useRef } from 'react'
import {
FOCUS_TERMINAL_PANE_EVENT,
PASTE_TERMINAL_TEXT_EVENT,
- RESET_TERMINAL_WEBGL_ATLAS_EVENT,
TOGGLE_TERMINAL_PANE_EXPAND_EVENT,
type FocusTerminalPaneDetail,
- type PasteTerminalTextDetail,
- type ResetTerminalWebglAtlasDetail
+ type PasteTerminalTextDetail
} from '@/constants/terminal'
import type { PaneManager } from '@/lib/pane-manager/pane-manager'
import { fitAndFocusPanes, fitPanes } from './pane-helpers'
@@ -206,21 +204,6 @@ export function useTerminalPaneGlobalEffects({
return () => window.removeEventListener(FOCUS_TERMINAL_PANE_EVENT, onFocusPane)
}, [tabId, managerRef, scheduleFollowOutputIfNeeded])
- useEffect(() => {
- const onResetAtlas = (event: Event): void => {
- const detail = (event as CustomEvent).detail
- if (!detail?.tabId || detail.tabId !== tabId) {
- return
- }
- // Why: WebGL atlas corruption can occur with no context-loss event while
- // a CSS-hidden surface (floating workspace) holds a live context; the
- // owning surface dispatches this when it becomes visible again.
- managerRef.current?.resetWebglTextureAtlases()
- }
- window.addEventListener(RESET_TERMINAL_WEBGL_ATLAS_EVENT, onResetAtlas)
- return () => window.removeEventListener(RESET_TERMINAL_WEBGL_ATLAS_EVENT, onResetAtlas)
- }, [tabId, managerRef])
-
useEffect(() => {
const onPasteText = (event: Event): void => {
const detail = (event as CustomEvent).detail
diff --git a/src/renderer/src/constants/terminal.ts b/src/renderer/src/constants/terminal.ts
index 1a281ec9a22..b59e0be006f 100644
--- a/src/renderer/src/constants/terminal.ts
+++ b/src/renderer/src/constants/terminal.ts
@@ -7,10 +7,6 @@ export const SPLIT_TERMINAL_PANE_EVENT = 'orca-split-terminal-pane'
export const REQUEST_ACTIVE_TERMINAL_PANE_SPLIT_EVENT = 'orca-request-active-terminal-pane-split'
export const CLOSE_TERMINAL_PANE_EVENT = 'orca-close-terminal-pane'
export const BACKGROUND_MOUNT_TERMINAL_WORKTREE_EVENT = 'orca-background-mount-terminal-worktree'
-// Why: surfaces that show/hide terminals with CSS only (floating workspace)
-// never flip TerminalPane visibility, so they need an explicit trigger for
-// WebGL glyph-atlas recovery when they become visible again.
-export const RESET_TERMINAL_WEBGL_ATLAS_EVENT = 'orca-reset-terminal-webgl-atlas'
// Why: sidebar open/close is an instantaneous width change. If we wait for
// the ResizeObserver rAF (and the 150ms debounced global fit) to catch up,
@@ -46,10 +42,6 @@ export type PasteTerminalTextDetail = {
text: string
}
-export type ResetTerminalWebglAtlasDetail = {
- tabId: string
-}
-
export type SplitTerminalPaneDetail = {
tabId: string
paneRuntimeId: number
diff --git a/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts b/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts
index f5670c4f263..a1f48f1982d 100644
--- a/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts
+++ b/tests/e2e/floating-workspace-reopen-webgl-recovery.spec.ts
@@ -368,11 +368,10 @@ test.describe('floating workspace reopen WebGL recovery @headful', () => {
test('reopening the floating workspace recovers a corrupted glyph atlas', async ({
orcaPage
}, testInfo) => {
- // Why: the floating panel hides via CSS visibility only — its terminal
- // keeps isVisible=true and a live WebGL context while hidden, so the
- // visibility-resume/window-focus/paste recovery triggers never run on
- // reopen. The panel dispatches RESET_TERMINAL_WEBGL_ATLAS_EVENT when it
- // opens; this guards that a glyph atlas corrupted while hidden repaints.
+ // Why: the floating panel hides via CSS visibility only. Gating the
+ // terminal's isVisible on `open` suspends its WebGL renderer while
+ // hidden, so a glyph atlas corrupted with no context-loss event is
+ // discarded with the context and the resume on reopen repaints clean.
const shots = await setUpCorruptedFloatingTerminal(orcaPage, 'REOPEN')
test.skip(!shots, 'WebGL was not active or atlas corruption could not be injected')
const { baseline, corrupted } = shots!
@@ -381,16 +380,17 @@ test.describe('floating workspace reopen WebGL recovery @headful', () => {
expect(await instrumentRecoveryCounters(orcaPage)).toBe(true)
await toggleFloatingPanel(orcaPage, false)
- // Why: the bug's precondition — the hidden floating terminal keeps its
- // WebGL addon attached because closing the panel never suspends rendering.
- const webglStillAttached = await orcaPage.evaluate((worktreeId) => {
+ // Why: the prevention invariant — closing the panel suspends rendering,
+ // so no live WebGL context (or corruptible glyph atlas) exists while the
+ // floating terminal is hidden.
+ const webglAttachedWhileClosed = await orcaPage.evaluate((worktreeId) => {
const state = window.__store?.getState()
const tab = (state?.tabsByWorktree?.[worktreeId] ?? [])[0]
const manager = tab ? window.__paneManagers?.get(tab.id) : null
const diagnostics = manager?.getRenderingDiagnostics?.() ?? []
return diagnostics.some((diagnostic) => diagnostic.hasWebgl)
}, FLOATING_WORKTREE_ID)
- expect(webglStillAttached).toBe(true)
+ expect(webglAttachedWhileClosed, 'closing the panel should suspend WebGL rendering').toBe(false)
await toggleFloatingPanel(orcaPage, true)
await settleRecoveryWindows(orcaPage)
From 41adf5f15b4e54e3f08a16919d1e14da06c32172 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 00:27:01 -0400
Subject: [PATCH 021/165] Fix source control branch compare base (#5074)
Co-authored-by: Orca
---
.../SourceControl.compare-summary.test.ts | 28 ++++++++++++++
.../right-sidebar/SourceControl.tsx | 37 +++++++++++++++++--
.../src/store/slices/worktrees.test.ts | 25 +++++++++++++
src/renderer/src/store/slices/worktrees.ts | 9 ++++-
4 files changed, 94 insertions(+), 5 deletions(-)
diff --git a/src/renderer/src/components/right-sidebar/SourceControl.compare-summary.test.ts b/src/renderer/src/components/right-sidebar/SourceControl.compare-summary.test.ts
index 044291e1347..0994c5a3218 100644
--- a/src/renderer/src/components/right-sidebar/SourceControl.compare-summary.test.ts
+++ b/src/renderer/src/components/right-sidebar/SourceControl.compare-summary.test.ts
@@ -2,6 +2,7 @@ import { describe, expect, it, vi } from 'vitest'
import {
CompareSummary,
CompareSummaryToolbarButton,
+ resolveSourceControlBaseRef,
shouldShowCompareSummary
} from './SourceControl'
import type { GitBranchCompareSummary } from '../../../../shared/types'
@@ -75,6 +76,33 @@ const readySummary: GitBranchCompareSummary = {
}
describe('SourceControl compare summary', () => {
+ it('prefers the worktree creation base for branch compare', () => {
+ expect(
+ resolveSourceControlBaseRef({
+ worktreeBaseRef: 'refs/remotes/origin/main',
+ repoBaseRef: 'main',
+ defaultBaseRef: 'origin/main'
+ })
+ ).toBe('refs/remotes/origin/main')
+ })
+
+ it('falls back to repo and default base refs when worktree metadata is absent', () => {
+ expect(
+ resolveSourceControlBaseRef({
+ worktreeBaseRef: ' ',
+ repoBaseRef: ' origin/release ',
+ defaultBaseRef: 'origin/main'
+ })
+ ).toBe('origin/release')
+
+ expect(
+ resolveSourceControlBaseRef({
+ repoBaseRef: null,
+ defaultBaseRef: 'origin/main'
+ })
+ ).toBe('origin/main')
+ })
+
it('wires toolbar actions without rendering the dead view-mode toggle', () => {
const onChangeBaseRef = vi.fn()
const onRetry = vi.fn()
diff --git a/src/renderer/src/components/right-sidebar/SourceControl.tsx b/src/renderer/src/components/right-sidebar/SourceControl.tsx
index b625694a009..7fb84e20aa3 100644
--- a/src/renderer/src/components/right-sidebar/SourceControl.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControl.tsx
@@ -220,6 +220,19 @@ export type SourceControlActionError = {
message: string
}
+export function resolveSourceControlBaseRef(input: {
+ worktreeBaseRef?: string | null
+ repoBaseRef?: string | null
+ defaultBaseRef?: string | null
+}): string | null {
+ return (
+ input.worktreeBaseRef?.trim() ||
+ input.repoBaseRef?.trim() ||
+ input.defaultBaseRef?.trim() ||
+ null
+ )
+}
+
const EMPTY_GIT_STATUS_ENTRIES: GitStatusEntry[] = []
const EMPTY_BRANCH_CHANGE_ENTRIES: GitBranchChangeEntry[] = []
@@ -1153,7 +1166,15 @@ function SourceControlInner(): React.JSX.Element {
}
}, [activeRepo, isBranchVisible, isFolder])
- const effectiveBaseRef = activeRepo?.worktreeBaseRef ?? defaultBaseRef
+ const normalizedWorktreeBaseRef = activeWorktree?.baseRef?.trim() || null
+ const normalizedRepoBaseRef = activeRepo?.worktreeBaseRef?.trim() || null
+ const effectiveBaseRef = resolveSourceControlBaseRef({
+ worktreeBaseRef: normalizedWorktreeBaseRef,
+ repoBaseRef: normalizedRepoBaseRef,
+ defaultBaseRef
+ })
+ const baseRefOwnedByWorktree = normalizedWorktreeBaseRef !== null
+ const pinnedBaseRef = normalizedWorktreeBaseRef ?? normalizedRepoBaseRef
const hasUncommittedEntries = entries.length > 0
const hostedReviewCreation =
@@ -4557,14 +4578,22 @@ function SourceControlInner(): React.JSX.Element {
{
- void updateRepo(activeRepo.id, { worktreeBaseRef: ref })
+ if (baseRefOwnedByWorktree && activeWorktreeId) {
+ void updateWorktreeMeta(activeWorktreeId, { baseRef: ref })
+ } else {
+ void updateRepo(activeRepo.id, { worktreeBaseRef: ref })
+ }
setBaseRefDialogOpen(false)
window.setTimeout(() => void refreshBranchCompare(), 0)
}}
onUsePrimary={() => {
- void updateRepo(activeRepo.id, { worktreeBaseRef: undefined })
+ if (baseRefOwnedByWorktree && activeWorktreeId) {
+ void updateWorktreeMeta(activeWorktreeId, { baseRef: undefined })
+ } else {
+ void updateRepo(activeRepo.id, { worktreeBaseRef: undefined })
+ }
setBaseRefDialogOpen(false)
window.setTimeout(() => void refreshBranchCompare(), 0)
}}
diff --git a/src/renderer/src/store/slices/worktrees.test.ts b/src/renderer/src/store/slices/worktrees.test.ts
index 6e997a744d7..e2720ca209d 100644
--- a/src/renderer/src/store/slices/worktrees.test.ts
+++ b/src/renderer/src/store/slices/worktrees.test.ts
@@ -1259,6 +1259,31 @@ describe('createWorktree base status merge', () => {
})
})
+ it('merges create result metadata into a worktree inserted by the watcher race', async () => {
+ const store = createTestStore()
+ const watcherWorktree = makeWorktree({
+ id: 'repo1::/path/wt1',
+ repoId: 'repo1',
+ path: '/path/wt1'
+ })
+ const createdWorktree = makeWorktree({
+ ...watcherWorktree,
+ baseRef: 'refs/remotes/origin/main'
+ })
+ store.setState({
+ worktreesByRepo: { repo1: [watcherWorktree] }
+ } as Partial)
+ mockApi.worktrees.create.mockResolvedValue({ worktree: createdWorktree })
+
+ await store.getState().createWorktree('repo1', 'feature', 'origin/main')
+
+ expect(store.getState().worktreesByRepo.repo1).toHaveLength(1)
+ expect(store.getState().worktreesByRepo.repo1[0]).toMatchObject({
+ id: watcherWorktree.id,
+ baseRef: 'refs/remotes/origin/main'
+ })
+ })
+
it.each([
{
status: 'skipped_dirty_worktree',
diff --git a/src/renderer/src/store/slices/worktrees.ts b/src/renderer/src/store/slices/worktrees.ts
index 0918c65ad38..ce837d66021 100644
--- a/src/renderer/src/store/slices/worktrees.ts
+++ b/src/renderer/src/store/slices/worktrees.ts
@@ -1149,10 +1149,17 @@ export const createWorktreeSlice: StateCreator
set((s) => {
const current = s.worktreesByRepo[repoId] ?? []
const alreadyPresent = current.some((w) => w.id === result.worktree.id)
+ const nextWorktrees = alreadyPresent
+ ? current.map((worktree) =>
+ worktree.id === result.worktree.id
+ ? { ...worktree, ...result.worktree }
+ : worktree
+ )
+ : [...current, result.worktree]
return {
worktreesByRepo: {
...s.worktreesByRepo,
- [repoId]: alreadyPresent ? current : [...current, result.worktree]
+ [repoId]: nextWorktrees
},
...(result.initialBaseStatus
? {
From 7afe7bb7ecf6d7933fbdf925574000226b8bd17e Mon Sep 17 00:00:00 2001
From: Bryant Ung
Date: Tue, 9 Jun 2026 22:55:26 -0700
Subject: [PATCH 022/165] Fix workspace-creation tour panel clipped by the
Create Worktree dialog (#5078)
* Fix workspace-creation tour panel clipped by the composer dialog
The tour panel portals into dialog/sheet content that clips overflow, but
its position was clamped against the window viewport. With the Project
field spanning nearly the dialog's full width, the panel landed past the
dialog's right edge and overflow-hidden cut it down to a sliver. Clamp
hosted panels within the host's bounds instead, so the panel flips below
the target and stays fully visible.
Co-Authored-By: Claude Fable 5
* Add JSDoc docstrings to satisfy CodeRabbit docstring coverage check
Co-Authored-By: Claude Sonnet 4.6
* Test hosted contextual tour overlay positioning
---------
Co-authored-by: Claude Fable 5
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
---
.../contextual-tour-overlay-position.test.ts | 69 +++++++++++++++++++
.../contextual-tour-overlay-position.ts | 26 ++++---
.../contextual-tour-panel-position.test.ts | 44 +++++++-----
.../contextual-tour-panel-position.ts | 27 +++++---
4 files changed, 130 insertions(+), 36 deletions(-)
create mode 100644 src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.test.ts
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.test.ts b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.test.ts
new file mode 100644
index 00000000000..d8b9f2b149f
--- /dev/null
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.test.ts
@@ -0,0 +1,69 @@
+import { describe, expect, it } from 'vitest'
+import { getContextualTourOverlayPanelPosition } from './contextual-tour-overlay-position'
+
+function rect(
+ partial: Pick
+): DOMRect {
+ return partial as DOMRect
+}
+
+function elementWithRect(
+ bounds: Pick
+): HTMLElement {
+ return {
+ getBoundingClientRect: () => rect(bounds)
+ } as HTMLElement
+}
+
+describe('contextual tour overlay position', () => {
+ it('returns viewport coordinates for floating panels', () => {
+ const position = getContextualTourOverlayPanelPosition({
+ targetRect: rect({ left: 100, right: 200, top: 200, bottom: 240, width: 100, height: 40 }),
+ panelElement: elementWithRect({
+ left: 0,
+ right: 320,
+ top: 0,
+ bottom: 180,
+ width: 320,
+ height: 180
+ }),
+ panelHost: null,
+ viewport: { width: 1024, height: 768 }
+ })
+
+ expect(position.panelPlacement).toBe('right')
+ expect(position.panelPosition.left).toBe(212)
+ expect(position.panelPosition.top).toBe(130)
+ expect(position.panelPosition['--contextual-tour-arrow-offset']).toBe('90px')
+ })
+
+ it('returns host-local coordinates for panels portaled into clipped dialog content', () => {
+ const position = getContextualTourOverlayPanelPosition({
+ targetRect: rect({ left: 110, right: 1018, top: 240, bottom: 315, width: 908, height: 75 }),
+ panelElement: elementWithRect({
+ left: 0,
+ right: 320,
+ top: 0,
+ bottom: 180,
+ width: 320,
+ height: 180
+ }),
+ panelHost: elementWithRect({
+ left: 55,
+ right: 1075,
+ top: 42,
+ bottom: 952,
+ width: 1020,
+ height: 910
+ }),
+ viewport: { width: 1512, height: 982 }
+ })
+
+ expect(position.panelPlacement).toBe('bottom')
+ expect(position.panelPosition.left).toBe(349)
+ expect(position.panelPosition.top).toBe(285)
+ expect(position.panelPosition.left).toBeGreaterThanOrEqual(12)
+ expect(Number(position.panelPosition.left) + 320).toBeLessThanOrEqual(1020 - 12)
+ expect(position.panelPosition['--contextual-tour-arrow-offset']).toBe('160px')
+ })
+})
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.ts b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.ts
index 55a11d5e902..1ac20f3b593 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-position.ts
@@ -3,7 +3,7 @@ import type { ContextualTourStepPlacement } from '../../../../shared/contextual-
import type { ContextualTourPanelPlacement } from './contextual-tour-panel-position'
import {
clampContextualTourPanelPosition,
- getContextualTourPanelCssPosition
+ getContextualTourTargetRectInHost
} from './contextual-tour-panel-position'
const PANEL_FALLBACK_SIZE = { width: 304, height: 172 }
@@ -13,6 +13,10 @@ export type ContextualTourOverlayPanelPosition = {
panelPlacement: ContextualTourPanelPlacement
}
+/**
+ * Returns the CSS position and placement for a tour panel rendered inside an overlay host,
+ * clamping coordinates to host space so clipped containers don't obscure the panel.
+ */
export function getContextualTourOverlayPanelPosition(args: {
targetRect: DOMRect
panelElement: HTMLElement | null
@@ -24,22 +28,24 @@ export function getContextualTourOverlayPanelPosition(args: {
const panel = panelRect
? { width: panelRect.width, height: panelRect.height }
: PANEL_FALLBACK_SIZE
+ // Why: hosted panels portal into dialog/sheet content whose overflow clips
+ // them, so position and clamp in host space — viewport clamping can park the
+ // panel in the clipped region outside the host and leave only a sliver visible.
+ const hostRect = args.panelHost?.getBoundingClientRect()
const clamped = clampContextualTourPanelPosition({
- targetRect: args.targetRect,
- viewport: args.viewport,
+ targetRect: hostRect
+ ? getContextualTourTargetRectInHost(args.targetRect, hostRect)
+ : args.targetRect,
+ viewport: hostRect ? { width: hostRect.width, height: hostRect.height } : args.viewport,
panel,
preferredPlacement: args.preferredPlacement
})
- const cssPosition = getContextualTourPanelCssPosition({
- position: clamped,
- panelHostRect: args.panelHost?.getBoundingClientRect()
- })
return {
panelPlacement: clamped.placement,
panelPosition: {
- left: cssPosition.left,
- top: cssPosition.top,
- '--contextual-tour-arrow-offset': `${cssPosition.arrowOffset}px`
+ left: clamped.left,
+ top: clamped.top,
+ '--contextual-tour-arrow-offset': `${clamped.arrowOffset}px`
}
}
}
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts
index 91938d2d664..6ad3fa36cc7 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest'
import {
clampContextualTourPanelPosition,
- getContextualTourPanelCssPosition
+ getContextualTourTargetRectInHost
} from './contextual-tour-panel-position'
describe('contextual tour panel position', () => {
@@ -40,25 +40,33 @@ describe('contextual tour panel position', () => {
expect(position.arrowOffset).toBeLessThan(120)
})
- it('converts viewport panel coordinates into hosted dialog coordinates', () => {
- const position = {
- left: 838,
- top: 168,
- placement: 'right' as const,
- arrowOffset: 64
- }
-
+ it('translates a viewport target rect into hosted dialog coordinates', () => {
expect(
- getContextualTourPanelCssPosition({
- position,
- panelHostRect: { left: 500, top: 80 }
- })
- ).toEqual({ left: 338, top: 88, arrowOffset: 64 })
- expect(getContextualTourPanelCssPosition({ position })).toEqual({
- left: 838,
- top: 168,
- arrowOffset: 64
+ getContextualTourTargetRectInHost(
+ { left: 555, right: 1018, top: 240, bottom: 315, width: 463, height: 75 },
+ { left: 500, top: 80 }
+ )
+ ).toEqual({ left: 55, right: 518, top: 160, bottom: 235, width: 463, height: 75 })
+ })
+
+ it('keeps a hosted panel inside a dialog whose field spans nearly its full width', () => {
+ // Regression: the workspace-creation tour panel was clamped against the
+ // viewport, so it sat to the right of the Project field — outside the
+ // dialog content that clips overflow — and only a sliver was visible.
+ const hostRect = { left: 55, top: 42 }
+ const position = clampContextualTourPanelPosition({
+ targetRect: getContextualTourTargetRectInHost(
+ { left: 110, right: 1018, top: 240, bottom: 315, width: 908, height: 75 },
+ hostRect
+ ),
+ viewport: { width: 1020, height: 910 },
+ panel: { width: 320, height: 180 }
})
+
+ expect(position.placement).toBe('bottom')
+ expect(position.left).toBeGreaterThanOrEqual(12)
+ expect(position.left + 320).toBeLessThanOrEqual(1020 - 12)
+ expect(position.top + 180).toBeLessThanOrEqual(910 - 12)
})
it('flips below the target when neither side has horizontal room', () => {
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts
index 3e9fa45ecca..5b50e663078 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts
@@ -17,6 +17,10 @@ type PanelSize = {
height: number
}
+/**
+ * Computes the position and placement for a tour panel relative to a target element,
+ * choosing the best side and clamping the panel within the viewport.
+ */
export function clampContextualTourPanelPosition(args: {
targetRect: Pick
viewport: ViewportSize
@@ -90,6 +94,7 @@ export function clampContextualTourPanelPosition(args: {
return { left: clampedLeft, top: clampedTop, placement, arrowOffset }
}
+/** Returns the raw (unclamped) top-left position for a panel at the given placement side. */
function getUnclampedPanelPosition(args: {
placement: ContextualTourPanelPlacement
targetRect: Pick
@@ -121,16 +126,22 @@ function getUnclampedPanelPosition(args: {
}
}
-export function getContextualTourPanelCssPosition(args: {
- position: ContextualTourPanelPosition
- panelHostRect?: Pick | null
-}): Pick {
- const { position, panelHostRect } = args
- const left = panelHostRect ? position.left - panelHostRect.left : position.left
- const top = panelHostRect ? position.top - panelHostRect.top : position.top
- return { left, top, arrowOffset: position.arrowOffset }
+/** Translates a target rect from viewport coordinates into the host element's local coordinate space. */
+export function getContextualTourTargetRectInHost(
+ targetRect: Pick,
+ hostRect: Pick
+): Pick {
+ return {
+ left: targetRect.left - hostRect.left,
+ right: targetRect.right - hostRect.left,
+ top: targetRect.top - hostRect.top,
+ bottom: targetRect.bottom - hostRect.top,
+ width: targetRect.width,
+ height: targetRect.height
+ }
}
+/** Clamps a number between min and max, inclusive. */
function clampNumber(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max)
}
From c12164c8cc604de5a3a35f41f4c924d33155def5 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 10 Jun 2026 06:34:05 +0000
Subject: [PATCH 023/165] release: v1.4.56
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index cf31766093a..90630a87fb4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca",
- "version": "1.4.55-rc.0",
+ "version": "1.4.56",
"description": "Next-gen IDE for parallel agentic development",
"homepage": "https://github.com/stablyai/orca",
"author": "stablyai",
From 256e0ef81a82d4ae7ff7e366007d98ca3568c28a Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Tue, 9 Jun 2026 23:56:36 -0700
Subject: [PATCH 024/165] Handle buffer overflows gracefully and truncate diffs
fairly (#5083)
- Gracefully fall back to file-name summaries when staged diffs exceed
node/ssh execution maxBuffer limits, preventing generation failures.
- Split oversized diffs by file and allocate budget via water-filling,
ensuring single huge files do not starve smaller human changes.
- Clip truncated diff sections on line boundaries to avoid half-lines.
---
src/main/git/max-buffer-overflow.ts | 22 +++++
src/main/git/status.test.ts | 28 ++++++
src/main/git/status.ts | 31 +++++--
src/main/providers/ssh-git-provider.test.ts | 34 ++++++++
src/main/providers/ssh-git-provider.ts | 27 +++++-
src/shared/commit-message-generation.test.ts | 14 +++
src/shared/commit-message-generation.ts | 6 +-
src/shared/commit-message-prompt.test.ts | 38 +++++++--
src/shared/commit-message-prompt.ts | 89 +++++++++++++++++++-
9 files changed, 265 insertions(+), 24 deletions(-)
create mode 100644 src/main/git/max-buffer-overflow.ts
diff --git a/src/main/git/max-buffer-overflow.ts b/src/main/git/max-buffer-overflow.ts
new file mode 100644
index 00000000000..ad67d154b20
--- /dev/null
+++ b/src/main/git/max-buffer-overflow.ts
@@ -0,0 +1,22 @@
+export function isMaxBufferOverflowError(error: unknown): boolean {
+ if (!error || typeof error !== 'object') {
+ return false
+ }
+
+ const maybeError = error as { code?: unknown; message?: unknown }
+ if (maybeError.code === 'ENOBUFS') {
+ return true
+ }
+
+ return typeof maybeError.message === 'string' && /\bmaxBuffer\b/i.test(maybeError.message)
+}
+
+export function describeMaxBufferOverflowError(error: unknown): string {
+ if (error && typeof error === 'object') {
+ const message = (error as { message?: unknown }).message
+ if (typeof message === 'string' && message.length > 0) {
+ return message
+ }
+ }
+ return String(error)
+}
diff --git a/src/main/git/status.test.ts b/src/main/git/status.test.ts
index b469eecb07f..5dbf9aa5ec4 100644
--- a/src/main/git/status.test.ts
+++ b/src/main/git/status.test.ts
@@ -832,6 +832,34 @@ describe('getStagedCommitContext', () => {
}
)
})
+
+ it('falls back to the file summary when the staged patch overflows the buffer', async () => {
+ gitExecFileAsyncMock
+ .mockResolvedValueOnce({ stdout: 'feature/ai\n' })
+ .mockResolvedValueOnce({ stdout: 'A\thuge.jsonl\n' })
+ .mockRejectedValueOnce(
+ Object.assign(new Error('stdout maxBuffer length exceeded'), {
+ code: 'ENOBUFS'
+ })
+ )
+
+ const result = await getStagedCommitContext('/repo')
+
+ expect(result).toEqual({
+ branch: 'feature/ai',
+ stagedSummary: 'A\thuge.jsonl',
+ stagedPatch: ''
+ })
+ })
+
+ it('rethrows staged patch failures that are not buffer overflows', async () => {
+ gitExecFileAsyncMock
+ .mockResolvedValueOnce({ stdout: 'feature/ai\n' })
+ .mockResolvedValueOnce({ stdout: 'M\tREADME.md\n' })
+ .mockRejectedValueOnce(new Error('fatal: bad revision'))
+
+ await expect(getStagedCommitContext('/repo')).rejects.toThrow('fatal: bad revision')
+ })
})
describe('detectConflictOperation', () => {
diff --git a/src/main/git/status.ts b/src/main/git/status.ts
index 38bd205ba98..6ffc44b9cd5 100644
--- a/src/main/git/status.ts
+++ b/src/main/git/status.ts
@@ -30,6 +30,7 @@ import {
} from '../../shared/git-uncommitted-line-stats'
import { decodeGitCQuotedPath } from '../../shared/git-cquoted-path'
import { gitExecFileAsync, gitExecFileAsyncBuffer, gitOptionalLocksDisabledEnv } from './runner'
+import { describeMaxBufferOverflowError, isMaxBufferOverflowError } from './max-buffer-overflow'
import {
removeSafeUntrackedDiscardTarget,
removeSafeUntrackedDiscardTargets
@@ -1212,16 +1213,28 @@ export async function getStagedCommitContext(
return null
}
- const { stdout: stagedPatch } = await gitExecFileAsync(
- ['diff', '--cached', '--patch', '--minimal', '--no-color', '--no-ext-diff'],
- {
- cwd: worktreePath,
- // Why: the prompt builder truncates large staged patches later. Give git
- // enough buffer room to reach that truncation step instead of failing at
- // Node's default execFile limit first.
- maxBuffer: MAX_STAGED_COMMIT_CONTEXT_BYTES
+ let stagedPatch = ''
+ try {
+ const patchResult = await gitExecFileAsync(
+ ['diff', '--cached', '--patch', '--minimal', '--no-color', '--no-ext-diff'],
+ {
+ cwd: worktreePath,
+ maxBuffer: MAX_STAGED_COMMIT_CONTEXT_BYTES
+ }
+ )
+ stagedPatch = patchResult.stdout
+ } catch (error) {
+ if (!isMaxBufferOverflowError(error)) {
+ throw error
}
- )
+ // Why: a very large staged diff overflows maxBuffer (ENOBUFS). The patch is
+ // optional context that gets truncated to STAGED_DIFF_BYTE_BUDGET anyway, so
+ // degrade to the file-name summary instead of failing commit-message generation.
+ console.warn(
+ '[git] Staged patch too large to read; using file summary only:',
+ describeMaxBufferOverflowError(error)
+ )
+ }
return {
branch: branchResult.stdout.trim() || null,
diff --git a/src/main/providers/ssh-git-provider.test.ts b/src/main/providers/ssh-git-provider.test.ts
index d56a5509460..35a0bc60b2c 100644
--- a/src/main/providers/ssh-git-provider.test.ts
+++ b/src/main/providers/ssh-git-provider.test.ts
@@ -216,6 +216,40 @@ describe('SshGitProvider', () => {
expect(mux.request).toHaveBeenCalledTimes(2)
})
+ it('getStagedCommitContext falls back when the remote staged patch overflows', async () => {
+ mux.request.mockImplementation(async (_method, payload) => {
+ if (payload.args[1] === '--show-current') {
+ return { stdout: 'feature/ai-commit\n' }
+ }
+ if (payload.args[2] === '--name-status') {
+ return { stdout: 'A\thuge.jsonl\n' }
+ }
+ throw Object.assign(new Error('git stdout exceeded maxBuffer.'), { code: 'ENOBUFS' })
+ })
+
+ await expect(provider.getStagedCommitContext('/home/user/repo')).resolves.toEqual({
+ branch: 'feature/ai-commit',
+ stagedSummary: 'A\thuge.jsonl',
+ stagedPatch: ''
+ })
+ })
+
+ it('getStagedCommitContext rethrows remote patch failures that are not buffer overflows', async () => {
+ mux.request.mockImplementation(async (_method, payload) => {
+ if (payload.args[1] === '--show-current') {
+ return { stdout: 'feature/ai-commit\n' }
+ }
+ if (payload.args[2] === '--name-status') {
+ return { stdout: 'M\tREADME.md\n' }
+ }
+ throw new Error('fatal: bad revision')
+ })
+
+ await expect(provider.getStagedCommitContext('/home/user/repo')).rejects.toThrow(
+ 'fatal: bad revision'
+ )
+ })
+
it('executeCommitMessagePlan delegates the prepared plan to the relay', async () => {
const execResult = {
stdout: 'Update docs',
diff --git a/src/main/providers/ssh-git-provider.ts b/src/main/providers/ssh-git-provider.ts
index 1fc9c25c1fb..477555df9e6 100644
--- a/src/main/providers/ssh-git-provider.ts
+++ b/src/main/providers/ssh-git-provider.ts
@@ -21,6 +21,10 @@ import { JsonRpcErrorCode } from '../ssh/relay-protocol'
import type { CommitMessageDraftContext } from '../../shared/commit-message-generation'
import type { CommitMessagePlan } from '../../shared/commit-message-plan'
import type { RemoteCommitMessageExecResult } from '../text-generation/commit-message-text-generation'
+import {
+ describeMaxBufferOverflowError,
+ isMaxBufferOverflowError
+} from '../git/max-buffer-overflow'
type NonInteractiveExecQueueEntry = {
started: boolean
@@ -115,10 +119,25 @@ export class SshGitProvider implements IGitProvider {
if (!stagedSummary) {
return null
}
- const { stdout: stagedPatch } = await this.exec(
- ['diff', '--cached', '--patch', '--minimal', '--no-color', '--no-ext-diff'],
- worktreePath
- )
+ let stagedPatch = ''
+ try {
+ const patchResult = await this.exec(
+ ['diff', '--cached', '--patch', '--minimal', '--no-color', '--no-ext-diff'],
+ worktreePath
+ )
+ stagedPatch = patchResult.stdout
+ } catch (error) {
+ if (!isMaxBufferOverflowError(error)) {
+ throw error
+ }
+ // Why: a very large staged diff can overflow the remote exec buffer. The
+ // patch is optional context (truncated later anyway), so degrade to the
+ // file-name summary instead of failing commit-message generation.
+ console.warn(
+ '[ssh-git] Staged patch too large to read; using file summary only:',
+ describeMaxBufferOverflowError(error)
+ )
+ }
return {
branch: branchResult.stdout.trim() || null,
stagedSummary,
diff --git a/src/shared/commit-message-generation.test.ts b/src/shared/commit-message-generation.test.ts
index 679d2d1d4ec..eb5884991e1 100644
--- a/src/shared/commit-message-generation.test.ts
+++ b/src/shared/commit-message-generation.test.ts
@@ -33,6 +33,20 @@ describe('buildCommitMessagePrompt', () => {
expect(prompt).toContain('Branch: (detached)')
expect(prompt).toContain('Additional user prompt:\nUse Conventional Commits.')
})
+
+ it('notes when the diff was omitted so the agent relies on the file list', () => {
+ const prompt = buildCommitMessagePrompt(
+ {
+ branch: 'feature/big-diff',
+ stagedSummary: 'A\thuge.jsonl',
+ stagedPatch: ''
+ },
+ ''
+ )
+
+ expect(prompt).toContain('Staged files:\nA\thuge.jsonl')
+ expect(prompt).toContain('diff omitted — too large to read')
+ })
})
describe('splitGeneratedCommitMessage', () => {
diff --git a/src/shared/commit-message-generation.ts b/src/shared/commit-message-generation.ts
index 5626f06f53e..a1b87f67801 100644
--- a/src/shared/commit-message-generation.ts
+++ b/src/shared/commit-message-generation.ts
@@ -35,7 +35,11 @@ export function buildCommitMessagePrompt(
context: CommitMessageDraftContext,
customPrompt: string
): string {
- const patch = truncateDiffForPrompt(context.stagedPatch)
+ // Why: the staged patch is dropped when it's too large to read, so fall back to
+ // the file summary and tell the agent why the diff is missing.
+ const patch = context.stagedPatch.trim()
+ ? truncateDiffForPrompt(context.stagedPatch)
+ : '(diff omitted — too large to read; infer the change from the staged file list above)'
const base = [
'You are generating a single git commit message.',
'Return only the commit message text. Do not include a preamble, quotes, or code fences.',
diff --git a/src/shared/commit-message-prompt.test.ts b/src/shared/commit-message-prompt.test.ts
index c2d2d11d385..436075b397f 100644
--- a/src/shared/commit-message-prompt.test.ts
+++ b/src/shared/commit-message-prompt.test.ts
@@ -36,16 +36,42 @@ describe('truncateDiffForPrompt', () => {
})
it('truncates and appends a marker when over budget', () => {
- const oversized = 'A'.repeat(STAGED_DIFF_BYTE_BUDGET + 100)
+ const oversized = `${'line\n'.repeat(STAGED_DIFF_BYTE_BUDGET / 5 + 100)}`
const result = truncateDiffForPrompt(oversized)
expect(result.length).toBeLessThan(oversized.length)
- expect(result).toMatch(/diff truncated, 100 bytes omitted/)
+ expect(result).toMatch(/diff truncated, \d+ bytes omitted/)
})
- it('honors a custom budget', () => {
- const result = truncateDiffForPrompt('abcdefghij', 5)
- expect(result.startsWith('abcde')).toBe(true)
- expect(result).toMatch(/diff truncated, 5 bytes omitted/)
+ it('clips on a line boundary so the diff is never cut mid-line', () => {
+ const diff = `${'keep this line\n'.repeat(40)}`
+ const result = truncateDiffForPrompt(diff, 95)
+ const body = result.split('\n...(diff truncated')[0]
+ // Every retained line is whole.
+ for (const line of body.split('\n').filter(Boolean)) {
+ expect(line).toBe('keep this line')
+ }
+ })
+
+ it('keeps clipped output within a tight custom budget', () => {
+ const files = Array.from(
+ { length: 20 },
+ (_, i) => `diff --git a/file-${i}.txt b/file-${i}.txt\n${'+x\n'.repeat(200)}`
+ ).join('')
+ const result = truncateDiffForPrompt(files, 120)
+
+ expect(result.length).toBeLessThanOrEqual(120)
+ })
+
+ it('shares the budget fairly so a huge file does not starve a small one', () => {
+ const hugeFile = `diff --git a/data.jsonl b/data.jsonl\n${'+x\n'.repeat(5000)}`
+ const smallFile = 'diff --git a/src/app.ts b/src/app.ts\n+const meaningful = true\n'
+ const result = truncateDiffForPrompt(`${hugeFile}${smallFile}`, 1_000)
+
+ // The small, human-authored change survives instead of being cut off.
+ expect(result).toContain('a/src/app.ts')
+ expect(result).toContain('const meaningful = true')
+ // The huge file is clipped, not the small one.
+ expect(result).toMatch(/diff truncated, \d+ bytes omitted/)
})
})
diff --git a/src/shared/commit-message-prompt.ts b/src/shared/commit-message-prompt.ts
index b16aafd9fec..f8aeb495a1a 100644
--- a/src/shared/commit-message-prompt.ts
+++ b/src/shared/commit-message-prompt.ts
@@ -30,8 +30,82 @@ export function buildCommitPrompt(diff: string, customSuffix: string): string {
export const STAGED_DIFF_BYTE_BUDGET = 200_000
-/** Truncates a diff that exceeds the byte budget; appends a marker so the agent
- * knows the input was clipped. */
+/** Splits a unified diff into one section per file, keyed on the `diff --git`
+ * header. Each section keeps the leading newline that preceded its header so
+ * concatenating the sections reproduces the original byte-for-byte. */
+function splitDiffIntoFileSections(diff: string): string[] {
+ const boundary = '\ndiff --git '
+ const sections: string[] = []
+ let start = 0
+ let next = diff.indexOf(boundary)
+ while (next !== -1) {
+ // Include the boundary newline in the current section; the next section
+ // starts at the `diff --git` header itself.
+ sections.push(diff.slice(start, next + 1))
+ start = next + 1
+ next = diff.indexOf(boundary, start)
+ }
+ sections.push(diff.slice(start))
+ return sections
+}
+
+/** Clips one section to `limit` bytes on a line boundary so the agent never sees
+ * a half-written diff line, and records how many bytes were dropped. */
+function clipSectionOnLineBoundary(section: string, limit: number): string {
+ if (section.length <= limit) {
+ return section
+ }
+ if (limit <= 0) {
+ return ''
+ }
+
+ const markerFor = (omitted: number): string => `\n...(diff truncated, ${omitted} bytes omitted)\n`
+ let marker = markerFor(section.length)
+ if (marker.length >= limit) {
+ return marker.slice(0, limit)
+ }
+
+ // Reserve headroom for the marker, then back up to the previous newline unless
+ // that would discard most of the budget (one very long line).
+ const target = limit - marker.length
+ const lineBreak = section.lastIndexOf('\n', target)
+ const cut = lineBreak > target / 2 ? lineBreak : target
+ const omitted = section.length - cut
+ marker = markerFor(omitted)
+ return `${section.slice(0, Math.min(cut, Math.max(0, limit - marker.length)))}${marker}`
+}
+
+/** Distributes `budget` across `sizes` by water-filling: everyone starts with an
+ * equal share, and the slack from files that fit is handed back to the files
+ * that don't. Keeps one huge generated file from starving the human-authored
+ * changes elsewhere in the diff. */
+function allocateBudgetFairly(sizes: number[], budget: number): number[] {
+ const alloc: number[] = Array.from({ length: sizes.length }, () => 0)
+ let active = sizes.map((_, i) => i)
+ let remaining = budget
+ while (active.length > 0 && remaining > 0) {
+ const share = Math.floor(remaining / active.length)
+ if (share === 0) {
+ break
+ }
+ const stillActive: number[] = []
+ for (const i of active) {
+ const need = sizes[i] - alloc[i]
+ const grant = Math.min(need, share)
+ alloc[i] += grant
+ remaining -= grant
+ if (grant < need) {
+ stillActive.push(i)
+ }
+ }
+ active = stillActive
+ }
+ return alloc
+}
+
+/** Truncates a diff that exceeds the byte budget. Splits the budget fairly across
+ * files and clips on line boundaries, so a single oversized file can't crowd out
+ * the rest and the agent never receives a malformed diff. */
export function truncateDiffForPrompt(
diff: string,
budget: number = STAGED_DIFF_BYTE_BUDGET
@@ -39,8 +113,15 @@ export function truncateDiffForPrompt(
if (diff.length <= budget) {
return diff
}
- const omitted = diff.length - budget
- return `${diff.slice(0, budget)}\n...(diff truncated, ${omitted} bytes omitted)`
+ const sections = splitDiffIntoFileSections(diff)
+ if (sections.length <= 1) {
+ return clipSectionOnLineBoundary(diff, budget)
+ }
+ const allocations = allocateBudgetFairly(
+ sections.map((section) => section.length),
+ budget
+ )
+ return sections.map((section, i) => clipSectionOnLineBoundary(section, allocations[i])).join('')
}
/** Strips noise around the agent's output: surrounding whitespace, a single
From 0ad5add6f079f0e53bc193c8f360c30f171aeaac Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Wed, 10 Jun 2026 01:19:34 -0700
Subject: [PATCH 025/165] Wrap AI generation controls with tooltips and clean
i18n dependencies (#5087)
- Wrap the AI generation button in a tooltip so users can see the
disabled reason or the action description on hover.
- Add unit tests verifying tooltip triggers and aria-label safety.
- Simplify memo dependencies in settings metadata and worktree palette
by using 'useTranslation()' to handle language-change rerenders
directly without needing 'i18n.language'.
---
.../src/components/WorktreeJumpPalette.tsx | 11 +-
...lRequestComposer.generate-tooltip.test.tsx | 116 ++++++++++++++++++
.../right-sidebar/SourceControl.tsx | 104 ++++++++--------
.../hooks/useSettingsNavigationMetadata.ts | 6 +-
4 files changed, 180 insertions(+), 57 deletions(-)
create mode 100644 src/renderer/src/components/right-sidebar/PullRequestComposer.generate-tooltip.test.tsx
diff --git a/src/renderer/src/components/WorktreeJumpPalette.tsx b/src/renderer/src/components/WorktreeJumpPalette.tsx
index 906a345d57e..9ea18fdbb50 100644
--- a/src/renderer/src/components/WorktreeJumpPalette.tsx
+++ b/src/renderer/src/components/WorktreeJumpPalette.tsx
@@ -247,7 +247,9 @@ function getSettingsTargetFromSectionId(sectionId: string): {
}
export default function WorktreeJumpPalette(): React.JSX.Element | null {
- const { i18n } = useTranslation()
+ // Why: subscribe this palette to language changes; translated memo contents
+ // recompute on the rerender without using i18n.language as a fake dependency.
+ useTranslation()
const visible = useAppStore((s) => s.activeModal === 'worktree-palette')
const closeModal = useAppStore((s) => s.closeModal)
const openModal = useAppStore((s) => s.openModal)
@@ -581,10 +583,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
() => buildCmdJSettingsResults(settingsSections),
[settingsSections]
)
- const actionResults = useMemo(
- () => buildCmdJActionResults(getCmdJQuickActions()),
- [i18n.language]
- )
+ const actionResults = useMemo(() => buildCmdJActionResults(getCmdJQuickActions()), [])
const prefetchCreateWorkspaceBaseForComposer = useCallback((initialRepoId?: string): void => {
const state = useAppStore.getState()
@@ -782,7 +781,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
appendPaletteListEntries(entries, visibleOpenTabItems)
}
return entries
- }, [hasQuery, paletteSections, showCreateAction, worktreeItems.length, i18n.language])
+ }, [hasQuery, paletteSections, showCreateAction, worktreeItems.length])
const selectionItemIds = useMemo(
() => getWorktreePaletteSelectionItemIds(listEntries),
diff --git a/src/renderer/src/components/right-sidebar/PullRequestComposer.generate-tooltip.test.tsx b/src/renderer/src/components/right-sidebar/PullRequestComposer.generate-tooltip.test.tsx
new file mode 100644
index 00000000000..6cc3d36d859
--- /dev/null
+++ b/src/renderer/src/components/right-sidebar/PullRequestComposer.generate-tooltip.test.tsx
@@ -0,0 +1,116 @@
+import { renderToStaticMarkup } from 'react-dom/server'
+import { describe, expect, it, vi } from 'vitest'
+import { TooltipProvider } from '@/components/ui/tooltip'
+import { PullRequestComposer } from './SourceControl'
+import { resolveDropdownItems } from './source-control-dropdown-items'
+import { resolvePrimaryAction } from './source-control-primary-action'
+
+type RenderPullRequestComposerOptions = {
+ generating?: boolean
+ generateDisabled?: boolean
+ generateDisabledReason?: string
+}
+
+function renderPullRequestComposer({
+ generating = false,
+ generateDisabled = false,
+ generateDisabledReason
+}: RenderPullRequestComposerOptions = {}): string {
+ const sourceControlInputs = {
+ stagedCount: 1,
+ hasUnstagedChanges: false,
+ hasStageableChanges: false,
+ hasPartiallyStagedChanges: false,
+ hasMessage: true,
+ hasUnresolvedConflicts: false,
+ isCommitting: false,
+ isRemoteOperationActive: false,
+ upstreamStatus: { hasUpstream: true, ahead: 1, behind: 0 }
+ }
+ const primaryAction = resolvePrimaryAction(sourceControlInputs)
+
+ return renderToStaticMarkup(
+
+
+
+ )
+}
+
+function elementByLabel(markup: string, tagName: string, label: string): string {
+ const element = [...markup.matchAll(new RegExp(`<${tagName}\\b[\\s\\S]*?${tagName}>`, 'g'))]
+ .map((match) => match[0])
+ .find((entry) => entry.includes(`aria-label="${label}"`))
+
+ if (!element) {
+ throw new Error(`${tagName} not found: ${label}`)
+ }
+
+ return element
+}
+
+describe('PullRequestComposer generate tooltip', () => {
+ it('renders hosted review labels without leaking interpolation placeholders', () => {
+ const markup = renderPullRequestComposer()
+
+ expect(markup).toContain('aria-label="Generate pull request details with AI"')
+ expect(markup).not.toContain('{{value0}}')
+ expect(markup).not.toContain('title="Generate {{value0}} details with AI"')
+ })
+
+ it('keeps enabled generation controls as direct tooltip triggers', () => {
+ const markup = renderPullRequestComposer()
+ const button = elementByLabel(markup, 'button', 'Generate pull request details with AI')
+
+ expect(button).toContain('data-slot="tooltip-trigger"')
+ })
+
+ it('wraps only disabled generation controls so the disabled reason can show on hover', () => {
+ const markup = renderPullRequestComposer({
+ generateDisabled: true,
+ generateDisabledReason: 'Stage changes before generating.'
+ })
+ const wrapper = elementByLabel(markup, 'span', 'Generate pull request details with AI')
+ const button = elementByLabel(markup, 'button', 'Generate pull request details with AI')
+
+ expect(wrapper).toContain('data-slot="tooltip-trigger"')
+ expect(button).toContain('disabled=""')
+ expect(button).toContain('data-slot="button"')
+ })
+
+ it('keeps the active stop control focusable as the tooltip trigger', () => {
+ const markup = renderPullRequestComposer({ generating: true, generateDisabled: true })
+ const button = elementByLabel(markup, 'button', 'Stop generating pull request details')
+
+ expect(button).toContain('data-slot="tooltip-trigger"')
+ expect(button).not.toContain('disabled=""')
+ })
+})
diff --git a/src/renderer/src/components/right-sidebar/SourceControl.tsx b/src/renderer/src/components/right-sidebar/SourceControl.tsx
index 7fb84e20aa3..752aaeda11d 100644
--- a/src/renderer/src/components/right-sidebar/SourceControl.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControl.tsx
@@ -4718,7 +4718,7 @@ type PullRequestComposerProps = {
onDropdownAction: (kind: DropdownActionKind) => void
}
-function PullRequestComposer({
+export function PullRequestComposer({
provider,
branch,
base,
@@ -4780,6 +4780,48 @@ function PullRequestComposer({
// the user can't race the request — the hook otherwise rejects the result
// with "Fields changed while generating" and silently drops the draft.
const fieldsLocked = generating
+ const generateDetailsLabel = translate(
+ 'auto.components.right.sidebar.SourceControl.02d8c04339',
+ 'Generate {{value0}} details with AI',
+ { value0: copy.reviewLabel }
+ )
+ const stopGeneratingDetailsLabel = translate(
+ 'auto.components.right.sidebar.SourceControl.b355e740b2',
+ 'Stop generating {{value0}} details',
+ { value0: copy.reviewLabel }
+ )
+ const generateTooltipLabel = generating
+ ? stopGeneratingDetailsLabel
+ : (generateDisabledReason ?? generateDetailsLabel)
+ const generateButton = generating ? (
+ onCancelGenerate()}
+ className="text-[11px] text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
+ aria-label={stopGeneratingDetailsLabel}
+ >
+
+
+ {translate('auto.components.right.sidebar.SourceControl.e868cec4e1', 'Generating…')}
+
+
+
+ ) : (
+ onGenerate()}
+ className="text-[11px] disabled:hover:bg-background"
+ aria-label={generateDetailsLabel}
+ >
+
+ {translate('auto.components.right.sidebar.SourceControl.aee92f8684', 'Generate')}
+
+ )
return (
@@ -4796,54 +4838,18 @@ function PullRequestComposer({
{aiGenerationEnabled ? (
- generating ? (
- onCancelGenerate()}
- className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-border bg-background px-2 text-[11px] text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
- title={translate(
- 'auto.components.right.sidebar.SourceControl.527e130b6f',
- 'Stop generating'
- )}
- aria-label={translate(
- 'auto.components.right.sidebar.SourceControl.b355e740b2',
- 'Stop generating {{value0}} details',
- { value0: copy.reviewLabel }
- )}
- >
-
-
- {translate(
- 'auto.components.right.sidebar.SourceControl.e868cec4e1',
- 'Generating…'
- )}
-
-
-
- ) : (
- onGenerate()}
- className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-border bg-background px-2 text-[11px] font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-background"
- title={
- generateDisabledReason ??
- translate(
- 'auto.components.right.sidebar.SourceControl.02d8c04339',
- 'Generate {{value0}} details with AI',
- { value0: copy.reviewLabel }
- )
- }
- aria-label={translate(
- 'auto.components.right.sidebar.SourceControl.02d8c04339',
- 'Generate {{value0}} details with AI',
- { value0: copy.reviewLabel }
- )}
- >
-
- {translate('auto.components.right.sidebar.SourceControl.aee92f8684', 'Generate')}
-
- )
+
+ {!generating && generateDisabled ? (
+
+ {generateButton}
+
+ ) : (
+ {generateButton}
+ )}
+
+ {generateTooltipLabel}
+
+
) : null}
diff --git a/src/renderer/src/hooks/useSettingsNavigationMetadata.ts b/src/renderer/src/hooks/useSettingsNavigationMetadata.ts
index eed03a10b4e..33830ba845e 100644
--- a/src/renderer/src/hooks/useSettingsNavigationMetadata.ts
+++ b/src/renderer/src/hooks/useSettingsNavigationMetadata.ts
@@ -491,7 +491,9 @@ export function buildSettingsNavigationMetadata({
}
export function useSettingsNavigationMetadata(): SettingsNavSection[] {
- const { i18n } = useTranslation()
+ // Why: subscribe metadata consumers to language changes; translated memo
+ // contents refresh on rerender without depending on i18n.language directly.
+ useTranslation()
const repos = useAppStore((state) => state.repos)
const activeRuntimeEnvironmentId = useAppStore(
(state) => state.settings?.activeRuntimeEnvironmentId
@@ -518,6 +520,6 @@ export function useSettingsNavigationMetadata(): SettingsNavSection[] {
isWebClient,
repos
}),
- [i18n.language, isMac, isWindows, isWindowsTerminalHost, isWebClient, repos]
+ [isMac, isWindows, isWindowsTerminalHost, isWebClient, repos]
)
}
From 8bc15e1439c1608585f186231c14cbd1cc757e93 Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Wed, 10 Jun 2026 01:22:11 -0700
Subject: [PATCH 026/165] fix: address review findings (#5088)
---
.gitignore | 1 +
config/scripts/bootstrap-locale-catalog.mjs | 5 +
config/scripts/locale-translation-policy.mjs | 20 +-
config/scripts/locale-value-overrides.mjs | 5 +
config/scripts/repair-locale-catalog.mjs | 5 +-
package.json | 1 +
src/main/i18n/main-i18n.ts | 4 +
.../settings/AppearancePane.test.tsx | 3 +-
src/renderer/src/i18n/i18n.ts | 4 +
src/renderer/src/i18n/locales/en.json | 3 +-
src/renderer/src/i18n/locales/es.json | 9986 +++++++++++++++++
src/renderer/src/i18n/locales/ja.json | 3 +-
src/renderer/src/i18n/locales/ko.json | 3 +-
src/renderer/src/i18n/locales/zh.json | 3 +-
src/renderer/src/i18n/supported-languages.ts | 7 +-
src/shared/ui-language.test.ts | 2 +
src/shared/ui-language.ts | 5 +-
src/shared/ui-locale.test.ts | 13 +
src/shared/ui-locale.ts | 6 +-
19 files changed, 10065 insertions(+), 14 deletions(-)
create mode 100644 src/renderer/src/i18n/locales/es.json
diff --git a/.gitignore b/.gitignore
index c87bcacb82b..c7a9a9da3a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -110,3 +110,4 @@ validation-screenshots/
src/renderer/src/i18n/locales/.zh-catalog-cache.json
src/renderer/src/i18n/locales/.ko-catalog-cache.json
src/renderer/src/i18n/locales/.ja-catalog-cache.json
+src/renderer/src/i18n/locales/.es-catalog-cache.json
diff --git a/config/scripts/bootstrap-locale-catalog.mjs b/config/scripts/bootstrap-locale-catalog.mjs
index d7f15c6bc8a..05739b4da9c 100644
--- a/config/scripts/bootstrap-locale-catalog.mjs
+++ b/config/scripts/bootstrap-locale-catalog.mjs
@@ -29,6 +29,11 @@ const LOCALE_CONFIG = {
targetLanguage: 'ja',
displayName: 'Japanese',
cacheFile: '.ja-catalog-cache.json'
+ },
+ es: {
+ targetLanguage: 'es',
+ displayName: 'Spanish',
+ cacheFile: '.es-catalog-cache.json'
}
}
diff --git a/config/scripts/locale-translation-policy.mjs b/config/scripts/locale-translation-policy.mjs
index e639f116850..8871a1b9fd6 100644
--- a/config/scripts/locale-translation-policy.mjs
+++ b/config/scripts/locale-translation-policy.mjs
@@ -125,13 +125,27 @@ export const BRAND_MISTRANSLATIONS = {
'GitHub Copilot': ['GitHub コパイロット', 'コパイロット'],
Discord: ['不和'],
Linear: ['線形']
+ },
+ es: {
+ Codex: ['códice', 'Códice'],
+ Gemini: ['Géminis'],
+ Claude: ['claudia', 'Claudia'],
+ Orca: ['orca', 'Orcas', 'orcas'],
+ OpenCode: ['código abierto', 'Código abierto'],
+ OpenClaude: ['Openclaude'],
+ Antigravity: ['antigravedad', 'Antigravedad'],
+ 'GitHub Copilot': ['Copiloto de GitHub'],
+ Discord: ['discordia'],
+ Linear: ['lineal', 'Lineal'],
+ Jira: ['jira']
}
}
export const NATIVE_PICKER_LABELS = {
- zh: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語' },
- ko: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語' },
- ja: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語' }
+ zh: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語', spanish: 'Español' },
+ ko: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語', spanish: 'Español' },
+ ja: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語', spanish: 'Español' },
+ es: { chinese: '中文(简体)', korean: '한국어', japanese: '日本語', spanish: 'Español' }
}
export function isEnglishOnlyKey(key) {
diff --git a/config/scripts/locale-value-overrides.mjs b/config/scripts/locale-value-overrides.mjs
index 9ba8fe01142..9d7b436eb9b 100644
--- a/config/scripts/locale-value-overrides.mjs
+++ b/config/scripts/locale-value-overrides.mjs
@@ -3,6 +3,11 @@ import { KO_VALUE_OVERRIDES } from './locale-ko-value-overrides.mjs'
import { ZH_VALUE_OVERRIDES } from './locale-zh-value-overrides.mjs'
export const LOCALE_VALUE_OVERRIDES = {
+ es: {
+ 'Explore Orca': 'Explorar Orca',
+ 'OpenCode Go': 'OpenCode Go',
+ 'Open in Cursor': 'Abrir en Cursor'
+ },
ko: {
Save: '저장',
Close: '닫기',
diff --git a/config/scripts/repair-locale-catalog.mjs b/config/scripts/repair-locale-catalog.mjs
index 70e84f8d4ad..88b4f71618d 100644
--- a/config/scripts/repair-locale-catalog.mjs
+++ b/config/scripts/repair-locale-catalog.mjs
@@ -10,7 +10,8 @@ const LOCALES_DIR = path.join('src', 'renderer', 'src', 'i18n', 'locales')
const LOCALE_CACHE_FILES = {
ko: '.ko-catalog-cache.json',
zh: '.zh-catalog-cache.json',
- ja: '.ja-catalog-cache.json'
+ ja: '.ja-catalog-cache.json',
+ es: '.es-catalog-cache.json'
}
function parseLocaleArg(argv) {
@@ -56,7 +57,7 @@ export async function repairLocale(root, locale) {
}
export async function main(root = process.cwd(), locale = parseLocaleArg(process.argv)) {
- const locales = locale ? [locale] : ['ko', 'zh', 'ja']
+ const locales = locale ? [locale] : ['ko', 'zh', 'ja', 'es']
const unsupported = locales.filter((code) => !LOCALE_CACHE_FILES[code])
if (unsupported.length > 0) {
console.error(`Unsupported locale(s): ${unsupported.join(', ')}`)
diff --git a/package.json b/package.json
index 90630a87fb4..643026963b2 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
"bootstrap:zh-catalog": "node config/scripts/bootstrap-zh-catalog.mjs",
"bootstrap:ko-catalog": "node config/scripts/bootstrap-locale-catalog.mjs --locale ko",
"bootstrap:ja-catalog": "node config/scripts/bootstrap-locale-catalog.mjs --locale ja",
+ "bootstrap:es-catalog": "node config/scripts/bootstrap-locale-catalog.mjs --locale es",
"repair:locale-catalog": "node config/scripts/repair-locale-catalog.mjs",
"verify:localization-coverage": "node config/scripts/audit-localization-coverage.mjs --check",
"audit:localization": "node config/scripts/audit-localization-coverage.mjs",
diff --git a/src/main/i18n/main-i18n.ts b/src/main/i18n/main-i18n.ts
index bcc56fc1eb6..d485f9f83cf 100644
--- a/src/main/i18n/main-i18n.ts
+++ b/src/main/i18n/main-i18n.ts
@@ -2,6 +2,7 @@ import { app } from 'electron'
import i18next, { type i18n as I18nInstance, type TOptions } from 'i18next'
import en from '../../renderer/src/i18n/locales/en.json'
+import es from '../../renderer/src/i18n/locales/es.json'
import ja from '../../renderer/src/i18n/locales/ja.json'
import ko from '../../renderer/src/i18n/locales/ko.json'
import zh from '../../renderer/src/i18n/locales/zh.json'
@@ -38,6 +39,9 @@ export async function ensureMainI18n(): Promise {
},
ja: {
translation: ja
+ },
+ es: {
+ translation: es
}
},
interpolation: {
diff --git a/src/renderer/src/components/settings/AppearancePane.test.tsx b/src/renderer/src/components/settings/AppearancePane.test.tsx
index 7691b292ac7..553984bb0c3 100644
--- a/src/renderer/src/components/settings/AppearancePane.test.tsx
+++ b/src/renderer/src/components/settings/AppearancePane.test.tsx
@@ -143,7 +143,7 @@ describe('AppearancePane', () => {
mocks.state.settingsSearchQuery = 'automations'
})
- it('renders the language dropdown with system, english, chinese, korean, and japanese options', async () => {
+ it('renders the language dropdown with system, english, chinese, korean, japanese, and spanish options', async () => {
mocks.state.settingsSearchQuery = 'language'
const updateSettings = vi.fn()
const settings = {
@@ -166,6 +166,7 @@ describe('AppearancePane', () => {
expect(container.textContent).toContain('中文(简体)')
expect(container.textContent).toContain('한국어')
expect(container.textContent).toContain('日本語')
+ expect(container.textContent).toContain('Español')
await act(async () => {
chineseOption?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
diff --git a/src/renderer/src/i18n/i18n.ts b/src/renderer/src/i18n/i18n.ts
index 63b96dca68a..1458f14fa0a 100644
--- a/src/renderer/src/i18n/i18n.ts
+++ b/src/renderer/src/i18n/i18n.ts
@@ -2,6 +2,7 @@ import i18next, { type i18n as I18nInstance, type TOptions } from 'i18next'
import { initReactI18next } from 'react-i18next'
import en from './locales/en.json'
+import es from './locales/es.json'
import ja from './locales/ja.json'
import ko from './locales/ko.json'
import zh from './locales/zh.json'
@@ -26,6 +27,9 @@ void i18n.use(initReactI18next).init({
},
ja: {
translation: ja
+ },
+ es: {
+ translation: es
}
},
interpolation: {
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index f56e16c3faf..9a46909a64b 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -16,7 +16,8 @@
"english": "English",
"chinese": "中文(简体)",
"korean": "한국어",
- "japanese": "日本語"
+ "japanese": "日本語",
+ "spanish": "Español"
},
"statusBar": {
"claudeToggleDescription": "Show Claude token and cost usage for the active workspace.",
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
new file mode 100644
index 00000000000..4d5d4f94423
--- /dev/null
+++ b/src/renderer/src/i18n/locales/es.json
@@ -0,0 +1,9986 @@
+{
+ "app": {
+ "recoverableError": {
+ "rootTitle": "Orca tuvo un error de renderizado.",
+ "rootDescription": "El shell de la aplicación no pudo terminar de renderizarse. Vuelva a intentar volver a montarlo o reinicie Orca si el error persiste.",
+ "webTitle": "Orca web tuvo un error de renderizado.",
+ "webDescription": "Vuelva a intentar el cliente web o vuelva a conectarse al tiempo de ejecución emparejado."
+ }
+ },
+ "settings": {
+ "appearance": {
+ "language": {
+ "title": "Idioma",
+ "description": "Elija el idioma utilizado por la interfaz de Orca.",
+ "system": "Sistema",
+ "english": "Inglés",
+ "chinese": "中文(简体)",
+ "korean": "한국어",
+ "japanese": "日本語",
+ "spanish": "Español"
+ },
+ "statusBar": {
+ "claudeToggleDescription": "Muestra el token de Claude y el uso de costos para el espacio de trabajo activo.",
+ "codexToggleDescription": "Muestra el token Codex y el uso de costos para el espacio de trabajo activo.",
+ "geminiToggleDescription": "Muestra el token de Gemini y el uso de costos para el espacio de trabajo activo.",
+ "opencodeGoToggleDescription": "Muestra el token de OpenCode Go y el uso de costos para el espacio de trabajo activo.",
+ "kimiToggleDescription": "Muestra el uso de la suscripción de Kimi para el espacio de trabajo activo.",
+ "sshToggleDescription": "Muestra la conexión SSH activa. Solo es visible una vez que se configura un destino SSH.",
+ "resourceUsageToggleDescription": "Muestra el Administrador de recursos. Haga clic en él para ver la CPU, la memoria, las sesiones, los controles del demonio y los análisis del disco del espacio de trabajo.",
+ "portsToggleDescription": "Mostrar puertos del espacio de trabajo en vivo. Haga clic en él para puertos con ámbito de espacio de trabajo y oyentes externos."
+ }
+ }
+ },
+ "menu": {
+ "checkForUpdates": "Buscar actualizaciones...",
+ "settings": "Ajustes",
+ "exploreOrca": "Explorar Orca",
+ "gettingStarted": "Empezando con Orca",
+ "reportCrash": "Informar fallo...",
+ "exportPdf": "Exportar como PDF...",
+ "file": "Archivo",
+ "exit": "Salida",
+ "edit": "Editar",
+ "appearance": "Apariencia",
+ "toggleLeftSidebar": "Alternar barra lateral izquierda",
+ "toggleRightSidebar": "Alternar barra lateral derecha",
+ "showStatusBar": "Mostrar barra de estado",
+ "showTasksButton": "Botón Mostrar tareas",
+ "showAutomationsButton": "Botón Mostrar automatizaciones",
+ "showMobileButton": "Mostrar botón móvil de Orca",
+ "showTitlebarAppName": "Mostrar el nombre de la aplicación de la barra de título",
+ "view": "Vista",
+ "reload": "Recargar",
+ "forceReload": "Forzar recarga",
+ "resetSize": "Restablecer tamaño",
+ "zoomIn": "Dar un golpe de zoom",
+ "zoomOut": "Alejar",
+ "openWorktreePalette": "Abrir paleta de árbol de trabajo",
+ "window": "Ventana",
+ "help": "Ayuda"
+ },
+ "worktreeJumpPalette": {
+ "matchLabel": {
+ "comment": "Comentario",
+ "issue": "Asunto",
+ "port": "Puerto",
+ "pr": "relaciones públicas"
+ }
+ },
+ "auto": {
+ "App": {
+ "221a95ba38": "Vuelva a intentar la incorporación o ciérrela y continúe en la aplicación.",
+ "f02d37278a": "La incorporación produjo un error.",
+ "acd66311dc": "Utilice el menú Ayuda después de volver a intentarlo si aún necesita diagnóstico.",
+ "722d03aa62": "El cuadro de diálogo del informe de fallos generó un error.",
+ "8a023cea1f": "Vuelva a intentar la barra de estado para volver a montar sus controles.",
+ "2e8ff36f94": "La barra de estado encontró un error.",
+ "7cbfbf622f": "Vuelva a intentar el espacio de trabajo flotante o ciérrelo y vuelva a abrirlo.",
+ "1b3024bcd6": "Se produjo un error en el espacio de trabajo flotante.",
+ "8d1e160ed1": "Vuelva a intentar la barra lateral o cambie de pestaña para recargar esta superficie.",
+ "ed6b168d00": "La barra lateral derecha encontró un error.",
+ "03a14f6b5b": "Vuelva a intentar la página o navegue a otra superficie de Orca.",
+ "b7a714db1e": "Esta página tuvo un error.",
+ "98d4ea2823": "Error al renderizar el terminal, el navegador o el editor en este espacio de trabajo. Vuelva a intentar montarlo.",
+ "5a9519aef0": "Se produjo un error en el banco de trabajo del espacio de trabajo.",
+ "cba0fafda5": "La página activa permanece abierta. Vuelva a intentar la lista o cambie de vista.",
+ "1468601e7b": "Se produjo un error en la lista de espacios de trabajo.",
+ "bdc71dddc9": "El espacio de trabajo activo permanece abierto. Vuelva a intentar la lista o cambie de vista.",
+ "c1cf0b0e4a": "Contraer panel",
+ "8504ddf267": "La aplicación todavía se está ejecutando. Vuelva a intentar el shell o utilice el menú para informar los detalles del fallo.",
+ "df1d56bf87": "El shell del espacio de trabajo encontró un error.",
+ "9e0b441a91": "Alternar barra lateral derecha",
+ "e81217c1b7": "Ocultar nombre de la aplicación",
+ "5096cbbc86": "Orca",
+ "8b0b8eb54f": "Menú de aplicaciones",
+ "caea5b51b9": "Reiniciar ahora",
+ "0a9e810705": "Los cambios no se guardarán hasta que se reinicie. Tus pestañas anteriores están seguras en el disco.",
+ "12e77cf12b": "Error al restaurar la sesión",
+ "332dbfa497": "Espacio de trabajo subido",
+ "e960d18540": "Cerca",
+ "c9d6f98459": "Maximizar",
+ "66f0a552e5": "Restaurar",
+ "bbb7f90669": "Minimizar",
+ "d54e66004c": "Terminal",
+ "9f0152563e": "móvil",
+ "62ca9895a7": "espacio",
+ "844eb0f4f4": "actividad",
+ "3443924e91": "automatizaciones",
+ "4f08ae8311": "tareas",
+ "ca6c6eece7": "habilidades",
+ "1b9d9d065f": "ajustes",
+ "c184e056de": "Alternar barra lateral derecha ({{value0}})",
+ "f7aa73e785": "Seguir adelante ({{value0}})",
+ "cf9099fe98": "Avanzar",
+ "fe21e8f6f5": "Volver ({{value0}})",
+ "064bd07810": "Volver",
+ "ce37cf5279": "Alternar barra lateral ({{value0}})",
+ "e4b9e7dff7": "Alternar barra lateral"
+ },
+ "web": {
+ "WebConnect": {
+ "b411ec0069": "Conectar",
+ "2cf9e5a294": "Borrar servidor guardado",
+ "4a4c017be1": "Punto final:",
+ "27393856e4": "orca://pair?code=...",
+ "7a566540de": "URL o código de emparejamiento",
+ "cb4d287238": "Nombre del servidor",
+ "3affe7de3a": "Pegue una URL de emparejamiento de un servidor Orca al que este navegador pueda acceder.",
+ "e3bcd082ac": "Conéctate a Orca"
+ },
+ "web": {
+ "preload": {
+ "api": {
+ "31bfe8ae1a": "No disponible en el cliente web.",
+ "67ec964791": "La importación de cookies no está disponible en el cliente web.",
+ "275a776357": "La extracción al pasar el mouse no está disponible en el cliente web.",
+ "8dfcb7a351": "Las capturas de pantalla de selección no están disponibles en el cliente web.",
+ "31bea294d5": "El modo Grab no está disponible en el cliente web.",
+ "b8a1618172": "La generación de detalles de solicitudes de extracción no está disponible en el cliente web.",
+ "e57c82d276": "La confirmación del descubrimiento del modelo de mensaje no está disponible en el cliente web.",
+ "9fc90740b6": "La generación de mensajes de confirmación no está disponible en el cliente web.",
+ "52bee9d8a0": "Se ignoraron los atajos personalizados en conflicto: {{value0}}.",
+ "32f15bdb0f": "Se ignoró la plataforma desconocida \"{{value0}}\".",
+ "0a69fcd8bc": "plataformas debe ser un objeto con secciones darwin, linux o win32.",
+ "10898045f3": "Se ignoró el acceso directo para \"{{value0}}\": utilice una matriz de cadenas.",
+ "36761d9604": "Se ignoró la acción de combinación de teclas desconocida \"{{value0}}\".",
+ "d2e43e426a": "{{value0}} debe ser un objeto.",
+ "fb290366b2": "No disponible en la web.",
+ "76122208ca": "Se ignoró el acceso directo para \"{{value0}}\": {{value1}}"
+ }
+ },
+ "runtime": {
+ "environment": {
+ "07f788de83": "WebSocket"
+ }
+ }
+ }
+ },
+ "store": {
+ "slices": {
+ "browser": {
+ "d175274b6d": "Nueva pestaña del navegador",
+ "08fc23631d": "Navegador"
+ },
+ "editor": {
+ "dcb521ed29": "Este archivo se encuentra en estado de conflicto, pero no hay ningún archivo de árbol de trabajo disponible para editar.",
+ "51f15c37d3": "No se puede abrir el directorio: {{value0}}",
+ "f2e00db373": "Archivo no encontrado: {{value0}}"
+ },
+ "github": {
+ "f129c42773": "GitHub no devolvió el nuevo comentario.",
+ "683a21264b": "La fila no tiene propietario/repositorio/número.",
+ "83f9b126ad": "El tipo de problema solo se puede configurar en problemas.",
+ "f963485d37": "Fila no encontrada",
+ "a967f23983": "Vista del proyecto no cargada",
+ "87020f6605": "La fila no tiene propietario/repositorio/número: no se puede parchear el elemento subyacente",
+ "d49ef4b944": "No se pudo guardar la preferencia de fuente del problema"
+ },
+ "sparse": {
+ "presets": {
+ "ef13e994e6": "Los ajustes preestablecidos deben cargarse antes de guardarlos.",
+ "6ed7d6010a": "No se pudo eliminar el ajuste preestablecido",
+ "ee434d7941": "Preestablecido eliminado",
+ "c96b770172": "No se pudo guardar el ajuste preestablecido",
+ "811be06b57": "No se pudo actualizar el ajuste preestablecido",
+ "0696d13e56": "Preajuste guardado",
+ "e10f097822": "Preestablecido actualizado"
+ }
+ },
+ "store": {
+ "test": {
+ "helpers": {
+ "b9a8117c33": "Terminal 1"
+ }
+ }
+ },
+ "workspace": {
+ "cleanup": {
+ "9d6e531da6": "El espacio de trabajo ya no existe."
+ }
+ },
+ "worktrees": {
+ "5a58e03a26": "Se eliminó \"{{value0}}\".",
+ "d1d78a7baa": "Git no pudo eliminar de forma segura la rama \"{{value0}}\"{{value1}}, por lo que Orca la mantuvo para evitar perder confirmaciones locales.",
+ "4e6496f3d2": "{{value0}} eliminado, rama mantenida",
+ "e50495aae6": "Forzar eliminación de rama",
+ "889487d8bb": "Despedir",
+ "f4503ca505": "Abra Configuración > Git e inténtelo de nuevo.",
+ "34a03a6565": "Mantenga {{value0}} actualizado",
+ "fa9299a66f": "Su nuevo árbol de trabajo está actualizado, pero el {{value0}} local está {{value1}} {{value2}} atrasado. Las diferencias de IA pueden pasar por alto las confirmaciones recientes.",
+ "14bc053a47": "El local {{value0}} no se actualizó",
+ "4a18052018": "El local {{value0}} está detrás de {{value1}}",
+ "903b51c2ed": "Espacio de trabajo creado a partir de {{value0}}, pero Orca no pudo adelantar el {{value1}} local porque {{value2}}",
+ "0216895fb5": "No se pudo eliminar la rama",
+ "19db0085fb": "Sucursal local eliminada",
+ "2b0afc7f14": "No se pudo mantener actualizado el {{value0}} local",
+ "670864ab52": "Mantener actualizado el {{value0}} local"
+ },
+ "repos": {
+ "b7e14472ae": "No se pudo agregar la carpeta",
+ "e649269645": "Utilice una ruta de servidor para agregar proyectos desde un tiempo de ejecución remoto.",
+ "c6e022ddfc": "No se pudo agregar el proyecto",
+ "90d129b48b": "Carpeta agregada",
+ "8bb3ad7935": "Proyecto agregado",
+ "a8e4b3af5b": "Proyecto ya agregado",
+ "6d3318e813": "No se pudieron importar repositorios"
+ },
+ "settings": {
+ "e12dab333b": "No se pudo cambiar de servidor",
+ "faa8fb83dd": "Guarde o cierre las pestañas del editor no guardadas antes de cambiar de servidor."
+ },
+ "ui": {
+ "66e3bd7ce6": "Enviado a {{value0}}",
+ "53883b7bc3": "No se pudo enviar a {{value0}}"
+ }
+ }
+ },
+ "lib": {
+ "agent": {
+ "catalog": {
+ "5dff448636": "OpenClaw",
+ "8a9ba743cc": "Hermes",
+ "4e63c7b956": "Rovo Dev",
+ "bee242fe3d": "Qwen Code",
+ "ca73055bd0": "Mistral Vibe",
+ "28810273af": "Kimi",
+ "739a930554": "Droid",
+ "667c104cff": "Cursor",
+ "9e2a9bb87b": "Continue",
+ "6f8056a565": "Command Code",
+ "4238b771b5": "Codebuff",
+ "cbaf0c2e0b": "Cline",
+ "1f8a19e9ad": "Autohand Code",
+ "5e8eff11b3": "Auggie",
+ "9477377a2a": "Charm",
+ "e0247254f2": "Kiro",
+ "918ba4ffed": "Kilocode",
+ "c73c573939": "Amp",
+ "8da11d876c": "Goose",
+ "b32627f09b": "Aider",
+ "691dd11789": "Antigravity",
+ "12e6baa4f7": "Gemini",
+ "09973b4d84": "OMP",
+ "302934c5d9": "Pi",
+ "e7a4ca5103": "OpenCode",
+ "706b0fe68b": "GitHub Copilot",
+ "0baad2d5d2": "Grok",
+ "760bc6883d": "Codex",
+ "a5fc0cb622": "OpenClaude",
+ "bf53f09bf8": "Claude Agent Teams",
+ "0708ed89f1": "Claude"
+ },
+ "skill": {
+ "cli": {
+ "prerequisite": {
+ "79371593b0": "Orca CLI aún no es visible en PATH",
+ "e99d7dc36f": "El registro de Orca CLI necesita atención",
+ "2db0bd7515": "El registro de Orca CLI no está disponible",
+ "8d6eedf97e": "No se pudo registrar Orca CLI en PATH.",
+ "0f116999f1": "Reinicie su shell o agregue el directorio CLI de Orca a PATH antes de la instalación.",
+ "15cbedc3e3": "Instale la CLI de Orca antes de ejecutar la configuración de habilidades del agente."
+ }
+ }
+ }
+ },
+ "ensure": {
+ "simulator": {
+ "tab": {
+ "372d21d428": "Emulador móvil"
+ }
+ }
+ },
+ "fix": {
+ "checks": {
+ "agent": {
+ "launch": {
+ "027228a06b": "No se puede encontrar un espacio de trabajo para estas comprobaciones.",
+ "fb6c294e85": "No se pudo generar el comando de inicio del agente.",
+ "03c1d61f83": "No se puede abrir el espacio de trabajo adjunto a estos controles.",
+ "822bf52295": "No se puede resolver la plataforma de inicio del espacio de trabajo.",
+ "dfb4dd7c00": "No se puede encontrar el espacio de trabajo adjunto a estos controles.",
+ "9f00d7df0c": "El mensaje de corrección de comprobaciones está vacío. Actualice la configuración de AI de control de fuente.",
+ "2ebf794906": "No se detectó ningún agente de IA habilitado en este host de espacio de trabajo.",
+ "4c7f783a7a": "El agente de cheques guardados no está disponible en este host de espacio de trabajo."
+ }
+ }
+ }
+ },
+ "floating": {
+ "workspace": {
+ "tab": {
+ "creation": {
+ "f3785eddc2": "Nueva pestaña del navegador"
+ }
+ }
+ }
+ },
+ "launch": {
+ "agent": {
+ "in": {
+ "new": {
+ "tab": {
+ "11cce5cc77": "No se pudo iniciar {{value0}} en una nueva terminal.",
+ "a5a1f7033f": "Su {{value0}} no fue enviado; péguelo una vez que el agente esté listo."
+ }
+ }
+ },
+ "background": {
+ "session": {
+ "4ca0651d56": "Su mensaje de automatización no fue enviado: abra el espacio de trabajo y péguelo."
+ }
+ }
+ },
+ "work": {
+ "item": {
+ "direct": {
+ "3de6371df3": "No se pudo generar el comando de inicio del agente.",
+ "67e103dd60": "Espacio de trabajo creado pero no se pudo activar.",
+ "19c7683acf": "El agente seleccionado no está disponible en el espacio de trabajo creado.",
+ "8bc45efdbc": "No se pudo resolver el jefe de relaciones públicas.",
+ "agent": {
+ "ceeeb509b5": "El agente tardó demasiado en comenzar. El espacio de trabajo está listo: pegue {{value0}} cuando el agente esté inactivo."
+ }
+ }
+ }
+ }
+ },
+ "local": {
+ "path": {
+ "open": {
+ "guard": {
+ "edc1908653": "No está disponible abrir rutas remotas en el sistema operativo local."
+ }
+ }
+ }
+ },
+ "open": {
+ "in": {
+ "app": {
+ "catalog": {
+ "f8b8ca2711": "Zed",
+ "d62b12e98a": "Cursor",
+ "173553f73a": "VS Code"
+ }
+ }
+ }
+ },
+ "orchestration": {
+ "usage": {
+ "examples": {
+ "f91fe27f2a": "Dividir un cambio grande en RP más pequeños",
+ "9e37a5b1b3": "Ejecutar trabajo independiente en paralelo.",
+ "bddc4c09b8": "Ejecute un flujo de trabajo por fases",
+ "ab0e9803b7": "Entregar a otro árbol de trabajo",
+ "5e0d489fe1": "Entregar una tarea activa"
+ }
+ }
+ },
+ "pr": {
+ "comment": {
+ "audience": {
+ "64deee36a9": "robots",
+ "a7150a17bc": "Humanos",
+ "27ce73211c": "Todo",
+ "empty": {
+ "bot": "Sin comentarios de robots.",
+ "human": "Sin comentarios humanos.",
+ "all": "Aún no hay comentarios."
+ }
+ }
+ }
+ },
+ "resume": {
+ "sleeping": {
+ "agent": {
+ "session": {
+ "f235f604fd": "Esta sesión de agente no se puede reanudar."
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "agent": {
+ "action": {
+ "plan": {
+ "3f0ea9aa0d": "No se pudo generar el comando de inicio del agente.",
+ "46f1a2c9bd": "La entrada del comando está vacía.",
+ "8eb541cc83": "El agente seleccionado no fue detectado en este host de espacio de trabajo.",
+ "b96e091fc9": "El agente seleccionado está deshabilitado en Configuración.",
+ "a7ac8717c7": "Elija un agente antes de comenzar."
+ }
+ }
+ },
+ "generation": {
+ "plan": {
+ "dc480d5897": "La entrada del comando está vacía."
+ }
+ }
+ }
+ },
+ "sparse": {
+ "preset": {
+ "draft": {
+ "5915a0a1f6": "Utilice directorios relativos al repositorio, no raíz, rutas absolutas ni segmentos principales.",
+ "efc05d1820": "Agregue al menos un directorio."
+ }
+ }
+ },
+ "terminal": {
+ "shortcut": {
+ "capture": {
+ "notification": {
+ "b0536028c9": "Abrir atajos",
+ "141ad6c004": "Acceso directo a terminal manejado",
+ "0ab0cd001a": "tamaño-4 texto-silenciado-primer plano"
+ }
+ }
+ }
+ },
+ "workspace": {
+ "create": {
+ "error": {
+ "format": {
+ "37cf0bc991": "Orca no pudo resolver una referencia base utilizable para este espacio de trabajo.",
+ "64555d0014": "No se encontró ninguna sucursal base"
+ }
+ }
+ }
+ },
+ "worktree": {
+ "palette": {
+ "search": {
+ "9ccec2316b": "Asunto",
+ "ca40ffcbec": "relaciones públicas",
+ "0b01ff98d2": "Puerto",
+ "7d732521ec": "Comentario"
+ }
+ }
+ }
+ },
+ "hooks": {
+ "useAutomationDispatchEvents": {
+ "59718b120b": "El espacio de trabajo de destino ya no está disponible.",
+ "16a21d6413": "La reconexión SSH requiere credenciales interactivas.",
+ "386db94f3e": "El proyecto de destino ya no está disponible."
+ },
+ "useComposerState": {
+ "7eb3f44ff7": "El agente seleccionado está deshabilitado. Elija un agente habilitado antes de crear.",
+ "b2ead86962": "No se pudo resolver la base de relaciones públicas.",
+ "a9ff236145": "Algunos archivos adjuntos no se pudieron cargar.",
+ "3db83fc58a": "No hay ninguna ruta de proyecto remoto disponible para los archivos adjuntos.",
+ "ba6cb77082": "No se pudo conectar al proyecto."
+ },
+ "useGlobalFileDrop": {
+ "38c9f034ff": "No se pudieron cargar los archivos eliminados.",
+ "d720e2f855": "Algunos archivos caídos no se pudieron cargar.",
+ "245faa95b9": "No hay ninguna ruta de espacio de trabajo remoto disponible para los archivos descartados."
+ },
+ "useIpcEvents": {
+ "0e3cf53060": "Pestaña del navegador {{value0}} no encontrada",
+ "a8d2bf8e9e": "No hay ninguna pestaña activa del navegador para cerrar",
+ "291c8ed902": "Las pestañas del navegador no están disponibles mientras un tiempo de ejecución remoto está activo",
+ "f45fa2b03c": "Los perfiles del navegador no están disponibles mientras un tiempo de ejecución remoto está activo",
+ "f000b2ff76": "Ningún árbol de trabajo activo",
+ "56d3ec4203": "No se pudo crear el archivo de rebajas sin título.",
+ "f6300deb8b": "Nueva pestaña del navegador",
+ "7a64b31991": "La creación de terminal local no está disponible mientras un tiempo de ejecución remoto está activo",
+ "60428567b4": "La revelación de terminal local no está disponible mientras un tiempo de ejecución remoto está activo",
+ "f8aaf2bde3": "Espacio de trabajo subido",
+ "2fe88c2e06": "La sincronización del espacio de trabajo remoto no está disponible",
+ "2ec42e1c52": "Aún no hay espacio de trabajo remoto",
+ "88214a785b": "La sincronización del espacio de trabajo esperó a que se hidratara la sesión local y se agotó el tiempo de espera",
+ "4f78ba5885": "Espacio de trabajo sincronizado"
+ },
+ "useSettingsNavigationMetadata": {
+ "4a728cd56b": "Nuevas características que aún están tomando forma. Pruébalos.",
+ "225071c560": "Experimental",
+ "e338c507c1": "Configuraciones de compatibilidad de bajo nivel para solucionar problemas.",
+ "580a04cd81": "Avanzado",
+ "8400cfe1c1": "Datos de uso anónimos y controles de telemetría.",
+ "3618579df6": "Privacidad y telemetría",
+ "65ec7d1968": "Acceso a la privacidad de macOS para herramientas de desarrollo lanzadas en terminales.",
+ "d91ae31fbd": "Permisos de macOS",
+ "95a1886d94": "Controla terminales y agentes desde tu teléfono.",
+ "1cd25673df": "Móvil",
+ "31e57d1c70": "Hosts SSH remotos para archivos, terminales y git.",
+ "94a5afe910": "Anfitriones SSH",
+ "40d80bad8a": "Beta",
+ "de0c2907a1": "Servidores remotos de Orca",
+ "b351014180": "Estadísticas de Orca más análisis de uso de Claude, Codex y OpenCode.",
+ "d72a58b5b9": "Estadísticas y uso",
+ "dcd0d9b74f": "Atajos de teclado para acciones comunes.",
+ "94295ebfb3": "Atajos",
+ "7682607591": "Notificaciones de escritorio nativas para eventos de agentes y terminales.",
+ "2eece16ad1": "Notificaciones",
+ "1f452cbd4c": "Comportamiento de selección y edición.",
+ "0c6ee88a5f": "Entrada y edición",
+ "b11a5a48a2": "Tema, zoom, apariencia de la aplicación y del terminal, barras laterales y barra de estado.",
+ "93d88d20bf": "Apariencia",
+ "2d0659f6f0": "Terminal global, navegador y pestañas de rebajas.",
+ "65b19f5bde": "Espacio de trabajo flotante",
+ "3d65d3f1b9": "Configure la compatibilidad con el emulador móvil para Orca y agentes de codificación.",
+ "1e761cff2b": "Emulador móvil",
+ "e815fd01bd": "Página de inicio, enrutamiento de enlaces y cookies de sesión.",
+ "8c197f74a1": "Navegador",
+ "42ae40842f": "Comandos de terminal guardados, con alcance global o por proyecto.",
+ "3fc3db144f": "Comandos rápidos",
+ "c33bfd664c": "Shells, renderizador, sesiones y comportamiento del terminal.",
+ "a9fb10afca": "Terminal",
+ "5235c215ca": "Elija qué proveedores de tareas aparecen en la página Tareas y en la barra lateral.",
+ "85f4fd7710": "Fuentes de tareas",
+ "ab4b21b58e": "Nomenclatura de sucursales, referencias base, atribución y autor de Git AI.",
+ "09607cb0fe": "Git y control de código fuente",
+ "33a5e1d597": "Conecte GitHub, GitLab, Linear y servicios de alojamiento de origen.",
+ "2b043783ef": "Integraciones",
+ "2cd4ea75da": "Valores predeterminados del espacio de trabajo, configuración y mantenimiento de aplicaciones.",
+ "13241992bd": "General",
+ "724c440e72": "empezando",
+ "0505d0df29": "empezar con Orca",
+ "ea0b1bc7b8": "guía de configuración",
+ "17005c73d4": "Abra la lista de verificación de incorporación para conocer los pasos de configuración y hitos.",
+ "ded9e9032f": "Lista de verificación de incorporación",
+ "5f32ac08f3": "Complete la lista de verificación de incorporación para los flujos de trabajo principales de Orca.",
+ "8ac3de82f5": "Dictado local de voz a texto con modelos en el dispositivo.",
+ "6a50cdcd7c": "Voz",
+ "0059bd17f3": "Permita que los agentes controlen cualquier aplicación en su computadora.",
+ "b35e92364b": "Uso de la computadora",
+ "cd50cec5d7": "Coordine múltiples agentes de codificación a través de Orca.",
+ "58a868e8e4": "Orquestación",
+ "7c79d3b7bf": "Opcional",
+ "b1c2f8b0ac": "Cambio de cuenta opcional para Claude, Codex, Gemini y OpenCode Go.",
+ "f70ac54d38": "Cuentas de proveedores de IA",
+ "4121f7a0a2": "Administre agentes de IA, establezca un valor predeterminado y personalice comandos.",
+ "b49abbd2f7": "Agentes"
+ }
+ },
+ "components": {
+ "CodexRestartChip": {
+ "9132779820": "Despedir",
+ "c72a5fb234": "Reanudar",
+ "9263e75f49": "Codex está usando la cuenta anterior."
+ },
+ "FirstLaunchBanner": {
+ "b9e1b966c7": "Descartar aviso",
+ "94cc673726": "Entiendo",
+ "fc5cc29955": "Optar por no participar",
+ "d1deebb050": "Política de privacidad",
+ "958d2cc31b": "Los recuentos anónimos de las funciones que utiliza nos ayudan a priorizar qué crear. Sin contenidos de archivos, mensajes, salida de terminal ni nada que lo identifique. Cambie en cualquier momento en Configuración -> Privacidad y telemetría.",
+ "9784b4d7bc": "Ayúdanos a decidir qué construir a continuación",
+ "fcbee32f08": "Aviso de telemetría"
+ },
+ "GitHubItemDialog": {
+ "3ab6ac0fc8": "Obtenga una vista previa y edite el problema de GitHub seleccionado o la solicitud de extracción.",
+ "3cd5ae5b7b": "No se cambiaron archivos.",
+ "999b5ad7d9": "Archivos",
+ "4bd1f5b055": "cheques",
+ "e30a5470c9": "Conversación",
+ "474c59b4b3": "Cerrar · Esc",
+ "45af57999b": "Cerrar vista previa",
+ "3fdf777817": "Abrir en GitHub",
+ "c43fe79ee0": "Copiar enlace de GitHub",
+ "0caac1a18f": "Iniciar espacio de trabajo desde PR",
+ "8223320f8d": "actualizado",
+ "10ef1afb8e": "· actualizado",
+ "55962099bc": "abrió este problema",
+ "0ab4664a8b": "Iniciar espacio de trabajo desde el problema",
+ "36182aa57f": "Iniciar nuevo espacio de trabajo",
+ "fe6ff12dc2": "Más acciones en el espacio de trabajo de problemas",
+ "726db41722": "Espacio de trabajo abierto",
+ "84855fedd0": "Abrir espacio de trabajo adjunto al problema",
+ "b7bf31b8de": "No se pudo sincronizar el estado visto con GitHub.",
+ "c0253318d6": "No se puede sincronizar el estado visto para esta solicitud de extracción.",
+ "5fea151559": "No se pudo copiar el enlace de GitHub",
+ "2e77dc2053": "Enlace de GitHub copiado",
+ "2ef631437e": "No se puede abrir el espacio de trabajo adjunto a este problema.",
+ "bf43425540": "Comentario",
+ "0a73f59e85": "Enviar comentario",
+ "c5c117270e": "Añade un comentario…",
+ "082515176a": "No se pudo agregar el comentario",
+ "c6f37a563d": "+ Cesionario",
+ "f41ec96c13": "+ Etiqueta",
+ "ab050dffec": "Cerrado",
+ "dc1ca081a8": "Abierto",
+ "2e4d806c92": "Espacio de trabajo",
+ "886a64b081": "Ninguno todavía",
+ "4ba0132f37": "Editar etiquetas",
+ "217e55d87c": "Etiquetas",
+ "c67de9e2fe": "nadie asignado",
+ "76adcf5fe2": "Editar asignados",
+ "83ac703dda": "Cesionarios",
+ "00ccdf9b5a": "Estado",
+ "2aa9acdf34": "Editar etiquetas en GitHub",
+ "d23bbb6416": "{{value0}} omitido",
+ "18f80e1329": "{{value0}} pendiente",
+ "b1ac991806": "{{value0}} fallando",
+ "311d0cee55": "{{value0}} pasando",
+ "e52bed9264": "Aún no se han reportado controles",
+ "90020cc1f3": "Esta solicitud de extracción aún no tiene comprobaciones reportadas.",
+ "ecffebc251": "No se encontraron cheques",
+ "5dddefdf58": "Abrir en GitHub",
+ "744197c84d": "No hay salida en línea disponible para esta verificación.",
+ "08d072664d": "Empleos",
+ "96d8f36798": "Anotaciones",
+ "485609c4f2": "controlar #",
+ "0f478f5efa": "Terminado",
+ "4812814bc8": "Comenzó",
+ "9c3ba11a05": "Estado:",
+ "934d87ab96": "Cargando detalles del cheque...",
+ "71c11aff84": "Vuelva a ejecutar todas las comprobaciones",
+ "e31651a224": "Volver a ejecutar comprobaciones fallidas",
+ "1b56e28faa": "Repetición",
+ "f4b1292569": "Inicie el agente de IA predeterminado en estas comprobaciones",
+ "9a1004fc76": "Actualizar cheques",
+ "03e542fcfe": "No se pudo iniciar un agente de IA para los cheques rotos: {{value0}}",
+ "28986b3747": "Inició un agente de inteligencia artificial para los cheques rotos.",
+ "1690fd7f4a": "No hay cheques rotos que arreglar.",
+ "9e7c221b8d": "No se pudieron volver a ejecutar las comprobaciones",
+ "e463ec935f": "Verificar repeticiones solicitadas",
+ "ddafe851e1": "Se solicita volver a ejecutar el cheque",
+ "0bbdc673c1": "No se pudieron actualizar las comprobaciones",
+ "e7007aa1d8": "No se pueden actualizar las comprobaciones sin una ruta al repositorio.",
+ "675bc0d638": "Cancelar",
+ "a18f669c7a": "{{value0}} {{value1}} reacción{{value2}}",
+ "53fe19aefc": "Abrir el cuadro de combinación de GitHub",
+ "a2495e4784": "Solicitud de extracción",
+ "ce360fc318": "No se pudo deshabilitar la combinación automática",
+ "825a8fb8cd": "No se pudo habilitar la combinación automática",
+ "4b390bd50d": "Fusión automática deshabilitada",
+ "a35ea5a0f6": "Combinación automática habilitada",
+ "aba792c8b3": "No se pudo fusionar la solicitud de extracción",
+ "dbe5e2448e": "Solicitud de extracción fusionada",
+ "a27ee5ca1a": "Esto actualizará la solicitud de extracción en GitHub.",
+ "03d7216d62": "{{value0}} PR #{{value1}}?",
+ "e9b7cb7d17": "No se pudo {{value0}} PR",
+ "bd3b4492a0": "Solicitud de extracción reabierta",
+ "9f88657c4e": "Solicitud de extracción cerrada",
+ "b6f1b7adbd": "Esto reabrirá la solicitud de extracción en GitHub.",
+ "de45fedf7b": "Esto cerrará la solicitud de extracción en GitHub.",
+ "5a94f3d0e9": "Aún no hay comentarios.",
+ "1506916c09": "Comentarios",
+ "9b9cb55994": "No se proporciona descripción.",
+ "52b20b56f7": "Descripción",
+ "4d555d3796": "Editar descripción",
+ "9df4e74bdf": "Ahorrar",
+ "0ae387d8ca": "por",
+ "228e2f59d3": "Resuelto",
+ "a154ec5224": "Abrir comentario en GitHub",
+ "bca8eb39ac": "Responder al comentario",
+ "68cb993d61": "resuelto",
+ "10f4ff5be8": "Respuesta publicada.",
+ "745c9089ec": "No se puede responder sin una ruta al repositorio.",
+ "58c73cb0d8": "No se pudo actualizar la descripción.",
+ "5221548274": "Descripción actualizada.",
+ "06c06e58ba": "Mostrar más líneas a continuación",
+ "307c98e8e3": "Mostrar {{value0}} más líneas arriba",
+ "5664681624": "Mostrar más líneas arriba",
+ "b1574e8ac2": "Restablecer el contexto del código",
+ "d43736d09c": "Controles de contexto de código",
+ "bd7be7b1fd": "comentario l",
+ "db61d76cd5": "Cargando contexto de código...",
+ "f2d02cdf8c": "archivos vistos",
+ "1257d1435d": "Mostrar árbol de archivos",
+ "a341343303": "Se agregó el comentario de revisión.",
+ "d1fa2cf888": "No se puede comentar sin el jefe de relaciones públicas SHA.",
+ "829674460a": "La diferencia no está disponible porque faltan los SHA de confirmación de relaciones públicas.",
+ "af924014f8": "Visto",
+ "2d89a38d9d": "{{value0}} {{value1}} tal como se ve",
+ "70e84e3d0b": "No hay revisores que coincidan.",
+ "1ffce94a8b": "Todos los demás",
+ "c2b21818e1": "Sugerencias",
+ "a98433e73d": "Cargando...",
+ "b0b7344684": "Solicite hasta 15 revisores",
+ "934add88b6": "Crítico",
+ "bb42774171": "Escribe o elige un usuario",
+ "36f9ac4a47": "No se solicitaron revisores.",
+ "8b15a5e91c": "Eliminar revisor {{value0}}",
+ "6a45771d47": "Cargando revisores",
+ "dc8a092c57": "Revisores",
+ "e3243d9376": "Editados recientemente estos archivos",
+ "8c45901789": "Solicitar revisor {{value0}}",
+ "fedc09eeb9": "Revisor no solicitado {{value0}}",
+ "73487fb975": "No se pudo eliminar al revisor",
+ "2e69540652": "Revisores eliminados",
+ "69515bff81": "Revisor eliminado",
+ "b4af16bf43": "No hay contexto de repositorio disponible para esta solicitud de extracción.",
+ "c42d942b75": "No se pudo solicitar el revisor",
+ "c016e4bac3": "Revisores solicitados",
+ "ea985e657f": "Revisor solicitado",
+ "12e761610e": "Puedes solicitar hasta 15 revisores",
+ "94ab23a9f9": "Introduzca un revisor",
+ "3853476a97": "elemento de GitHub",
+ "68796dafa0": "pr",
+ "b1157c78ff": "hoja",
+ "038b3d39b1": "copiado",
+ "04539beb48": "asunto",
+ "773ff70035": "desconocido",
+ "3e544d966d": "Asunto",
+ "88fd82474d": "página",
+ "e517b4d641": "cerrado",
+ "d0a05e73f5": "compacto",
+ "7d42606f66": "Anotación",
+ "2511f44bb7": "Arreglar cheques rotos",
+ "9157d48ddb": "Arreglar cheques",
+ "06482d6190": "No se puede crear un espacio de trabajo de reparación automáticamente.",
+ "f64dd90102": "Responder",
+ "5752c25aff": "Destino…",
+ "ec5c4b3ab2": "Reabrir relaciones públicas",
+ "21860b58d0": "Cerrar solicitud de extracción",
+ "5932578f51": "La fusión requiere un repositorio local registrado",
+ "ce8a85d209": "por defecto",
+ "924c2fe05e": "destructivo",
+ "e2bf3e41a9": "comentario",
+ "28d0d3374f": "hilo",
+ "080d071d48": "Responder a @{{value0}}",
+ "86f809e2ce": "Responder en este hilo de revisión",
+ "136542c9ba": ":L{{value0}}",
+ "283699bc82": "No se pudo publicar la respuesta.",
+ "d1c0dad471": "-L{{value0}}",
+ "31770bef03": "Juntos",
+ "6e43a16435": "En línea",
+ "d00a0a7f8f": "Contraer todo",
+ "3c19ec3069": "Expandir todo",
+ "b0b09778c8": "No se pudo agregar el comentario de revisión.",
+ "16c1abe76c": "Marcar visto",
+ "ba8e329d92": "Desmarcar visto",
+ "3f79ffc8b7": "Abra los detalles de relaciones públicas para ver los revisores actuales.",
+ "5c1c973855": "Eliminar revisor"
+ },
+ "GitLabItemDialog": {
+ "65e784c1f1": "Reabrir",
+ "a199eb364b": "Cerca",
+ "16b3412570": "Unir",
+ "131865e231": "Crear espacio de trabajo",
+ "f2e64d1c20": "Abrir en GitLab",
+ "84012fa8fb": "Comentario",
+ "c08e1d5a57": "Comentar en {{value0}}{{value1}}…",
+ "f11e3e7675": "No hay tuberías para este MR.",
+ "808b1ca1ba": "No hay archivos modificados.",
+ "007423f585": "Contenido diferencial no disponible.",
+ "a7eb4f4916": "de",
+ "21f8dde18a": "comentario en línea",
+ "7a7204417f": "Línea",
+ "ceb08a733d": "Archivo",
+ "85a8170279": "Aún no hay comentarios.",
+ "14423484db": "Sin descripción.",
+ "da4174b00f": "Editar",
+ "93f79a3fc1": "Ahorrar",
+ "f72fad3b16": "Cancelar",
+ "717b706849": "Cargando etiquetas",
+ "3c0b6ccca7": "error, backend",
+ "dde24ade55": "Etiquetas",
+ "908d8d2a73": "Descripción",
+ "89f3f19368": "Título",
+ "7a2117129a": "Agregar",
+ "05939e977d": "Agregar revisor",
+ "474b50d988": "Sin revisores.",
+ "1b19cdc510": "Eliminar revisor {{value0}}",
+ "cb55b0390f": "Administrar",
+ "4f9313984d": "Revisores",
+ "02cbe2de44": "Tubería",
+ "be3d291837": "Archivos",
+ "c996e2962c": "Conversación",
+ "b3c156dd51": "Refrescar",
+ "9bfb4a24d7": "por",
+ "30c97083c2": "Detalle del elemento de trabajo de GitLab",
+ "e089f62594": "¡MR fusionado! {{value0}}",
+ "865ea2703e": "Reabierto MR!{{value0}}",
+ "9b11cd233f": "Cerrado SEÑOR !{{value0}}",
+ "60c13320c4": "Se agregó comentario en línea",
+ "ffdd9a78e1": "Las referencias de diferencias de MR no están disponibles para comentarios en línea.",
+ "00d0d25825": "Se requieren archivo, línea y comentario.",
+ "ceaf7c30c7": "La identificación del revisor no está disponible para este usuario de GitLab.",
+ "f7cb495a12": "Reintentado {{value0}}",
+ "98718490e4": "Se requiere título de MR.",
+ "d600c2619a": "Cargando registro",
+ "028bde664e": "Esconder",
+ "2f9b27f838": "Registro de trabajo",
+ "032ae1312b": "Trabajo abierto en GitLab",
+ "fa3e042203": "Rever",
+ "f23ea85341": "resuelto",
+ "4186685c78": "reabrir",
+ "cae2712a23": "cerca",
+ "881e522e04": "unir",
+ "6de8ce0cc6": "{{value0}} requerido",
+ "22511537d2": "Aprobado",
+ "00f3bab87b": "de {{value0}} requerido",
+ "11384f99aa": "número",
+ "40c56b95e2": "{{value0}} aprobación{{value1}} restante",
+ "3a051b8ade": "Elemento de trabajo",
+ "32f8bef818": "Sin salida de registro.",
+ "4168eb2c51": "Resolver"
+ },
+ "JiraIssueWorkspace": {
+ "b0b92666c9": "Comentario",
+ "a585fd204e": "Añade un comentario de Jira...",
+ "2441be6f9f": "Iniciar espacio de trabajo",
+ "9178090e26": "Aún no hay comentarios.",
+ "5cd09beaf9": "Rever",
+ "9a980b06b9": "Comentarios",
+ "c4889a47e4": "No se proporciona descripción.",
+ "0f3c07a901": "backend, error",
+ "aee97b6913": "Etiquetas",
+ "444865b4a8": "Título",
+ "0b6b5646ed": "No asignado",
+ "51bed73f88": "Sin prioridad",
+ "7a96985ca0": "Cerca",
+ "76513c7898": "Cerrar vista previa del problema de Jira",
+ "857bd2f88f": "Obtenga una vista previa, edite y comience a trabajar desde el número seleccionado.",
+ "0cc62bd690": "Copiar mensaje",
+ "80efa101c5": "Copiar el nombre de la sucursal sugerida",
+ "38839801e8": "Copiar clave",
+ "779bb91ee0": "Copiar URL",
+ "69da9a208c": "Abierto en Jira",
+ "fa132c8aed": "No se pudo agregar el comentario.",
+ "ea21952aa3": "No se pudo actualizar el problema de Jira.",
+ "6c41a9bcea": "No se pudo copiar {{value0}}",
+ "2ff69a3545": "{{value0}} copiado",
+ "666cfdd835": "Desconocido",
+ "9ebee71962": "etiquetas",
+ "def3d0e824": "título",
+ "b8e2079d96": "cesionario",
+ "54649eaeab": "+ Cesionario",
+ "2a829a2f00": "prioridad",
+ "693be070d0": "transición",
+ "ef21405c6d": "Problema con Jira"
+ },
+ "Landing": {
+ "76a95f7f47": "Crear",
+ "f05d237049": "Añade un proyecto primero",
+ "f9eaa9e12d": "Agregar proyecto",
+ "6ca6ff404e": "ORCA",
+ "520304a067": "logotipo de Orca",
+ "ce44fad849": "Dependencias faltantes",
+ "c1cf168479": "Esconder",
+ "00cee697c1": "Ejecute \"gh auth login\" en una terminal para conectar su cuenta de GitHub.",
+ "9f96d018b7": "La CLI de GitHub no está autenticada",
+ "73e1ad4282": "Orca utiliza la CLI de GitHub (gh) para mostrar solicitudes de extracción, problemas y comprobaciones.",
+ "5beaef5f9e": "La CLI de GitHub no está instalada",
+ "b673e7cf1b": "Se requiere Git para proyectos Git, control de código fuente y gestión del espacio de trabajo.",
+ "e5b7296d9d": "git no está instalado",
+ "cd21242762": "Agregue un proyecto para comenzar.",
+ "9c00bd4adf": "Seleccione un espacio de trabajo de la barra lateral para comenzar.",
+ "16e9e3df89": "sembrado de estrellas",
+ "0d0ace8861": "Estrella en GitHub",
+ "ec43b38ba7": "Destacado en GitHub"
+ },
+ "LinearIssueMarkdownDescriptionEditor": {
+ "d9c47069ef": "Reducción",
+ "a7301a11f3": "ahorrar",
+ "632096eb1c": "Enlace",
+ "340160f4e8": "Quitar enlace",
+ "9eaf02ac01": "Cita",
+ "e2a0267c8c": "Lista de verificación",
+ "d6b2f3d35b": "lista numerada",
+ "c82917e06e": "lista de viñetas",
+ "ad1869bd54": "código en línea",
+ "28fd951b83": "Huelga",
+ "5666b4493d": "Itálico",
+ "caa88f50d0": "Atrevido",
+ "dddaa7a0a6": "Título 2",
+ "e3f741d258": "Título 1",
+ "68a41d5665": "Texto del cuerpo",
+ "7c52151156": "Formato de descripción del problema",
+ "5c16ec8f14": "URL del enlace",
+ "4f2fddc2b7": "No se proporciona descripción."
+ },
+ "LinearIssueTextEditor": {
+ "947ba2d6f4": "guardar",
+ "04d73b72dc": "Título del problema",
+ "e8ff595db3": "No se pudo actualizar {{value0}}",
+ "1e08a1ec80": "Se requiere título",
+ "00fa439dc7": "título",
+ "75294b07d1": "descripción"
+ },
+ "LinearIssueWorkspace": {
+ "ad5dec37b7": "Obtenga una vista previa, edite y comience a trabajar desde el número seleccionado.",
+ "c23e79e5c0": "Comportamiento",
+ "b0eac92d85": "Rever",
+ "fabbd3f974": "actualizó el problema ·",
+ "543970c87a": "Actividad",
+ "df4c86ed12": "Cerca",
+ "7a4997d8bb": "Cerrar vista previa del problema Linear",
+ "e1e0a9bca9": "Iniciar espacio de trabajo",
+ "30a7f56c0a": "Iniciar espacio de trabajo desde el problema",
+ "30c1242f3a": "Copiar identificador",
+ "9e3c49beb8": "Copiar identificador de problema",
+ "9a9a884236": "Copiar URL",
+ "97c19a84f1": "Copiar URL Linear",
+ "f63ef94ea8": "Asuntos",
+ "f6c6381593": "Copiar mensaje",
+ "5d670ec8dc": "Copiar el nombre de la sucursal sugerida",
+ "937ba6ad9a": "Cargando proyectos",
+ "db3f269d98": "Buscar proyectos",
+ "b51276c8d6": "Proyecto",
+ "8b5b593053": "No se pudo actualizar el proyecto",
+ "f9d4ef9807": "Proyecto actualizado",
+ "38b80780c2": "No se pudieron cargar los proyectos",
+ "42589845bc": "Crear",
+ "c182e02de5": "Título del subtema",
+ "8c55d6696a": "Agregar subtemas",
+ "b25e453c9d": "No se pudo crear el subproblema",
+ "aeed19d003": "Creado {{value0}}",
+ "9a1317cdd3": "No se pudo cargar el subproblema",
+ "9bcbaa2737": "No se pudo copiar {{value0}}",
+ "7835483c43": "{{value0}} copiado",
+ "61f424f8ca": "Cuestión Linear",
+ "ca8778c124": "Desconocido",
+ "8a33c85e9c": "Alguien",
+ "f5a6b38a14": "hoja",
+ "65239a714b": "Linear",
+ "af6e02c44a": "página",
+ "76ffd3c937": "Busque un proyecto para agregar.",
+ "c11b4e3cc2": "No se encontraron proyectos.",
+ "519c3587f3": "Añadir al proyecto"
+ },
+ "LinearItemDrawer": {
+ "04008e6c46": "Iniciar espacio de trabajo desde el problema",
+ "a4fcc57522": "Aún no hay comentarios.",
+ "fde849b2b6": "Comentarios",
+ "9dc54172db": "Cerrar · Esc",
+ "0190b760c1": "Abierto en Linear",
+ "04a442f796": "Obtenga una vista previa y edite la edición Linear seleccionada.",
+ "d369841269": "Enviar comentario",
+ "2fcff829a8": "Añade un comentario…",
+ "2820f0f0f0": "Deja un comentario...",
+ "6ab35eafd5": "No se pudo agregar el comentario",
+ "367f828482": "No se encontraron etiquetas",
+ "cddd9b04a7": "Cargando etiquetas",
+ "23886c7eec": "Agregar etiqueta",
+ "7f7b89b631": "Etiquetas: {{value0}}",
+ "b2376d0179": "Cargando miembros",
+ "866316f22c": "No asignado",
+ "b5675b0694": "Ahorrar",
+ "ceeb8c6153": "Claro",
+ "fbb90300e2": "Presupuesto personalizado",
+ "780ea6ed89": "No se encontraron estados",
+ "59b6cd3706": "Estados de carga",
+ "64bfffc4dd": "Etiquetas",
+ "dd304de85a": "Propiedades",
+ "0be31fef8e": "La estimación debe ser un número entero no negativo",
+ "48e17e8cbd": "Desconocido",
+ "858d0630da": "Cerrar vista previa",
+ "39883467f4": "Cuestión Linear",
+ "fda549766e": "{{value0}} para comentar",
+ "d71cd3003e": "+ Cesionario"
+ },
+ "NewWorkspaceComposerCard": {
+ "cbb47ee0dc": "Solo disponible para proyectos Git locales.",
+ "d861de981b": "Pago escaso",
+ "090cfedeb4": "escribe una nota",
+ "f8728aa4f9": "Nota",
+ "0ee17638fe": "Nombre del espacio de trabajo",
+ "2688050e4b": "Nombre",
+ "f0470c7383": "Avanzado",
+ "ba64270bdb": "Configurar agentes",
+ "ab63f25397": "Abrir configuración del agente",
+ "01d1e8f601": "Agente",
+ "0c5d6a479c": "[Opcional]",
+ "b5a0796911": "Conectar",
+ "dccd26d4e4": "Elige proyecto",
+ "d6b0a96f32": "Agregar proyecto",
+ "969a8bff66": "Proyecto",
+ "23bb365554": "orca.yaml",
+ "a239038146": "Error de conexión SSH",
+ "9a70e4859e": "Elija si desea ejecutar la instalación antes de crear este espacio de trabajo.",
+ "803b7fe72f": "Comprobando la configuración de instalación...",
+ "92e34f0311": "configuraciones locales",
+ "326a578923": "orca.yaml + local",
+ "2132b670da": "ambos",
+ "0e587e31fb": "yaml",
+ "ac3748dcda": "Nombre o 'Crear desde'",
+ "f660aa1454": "Conectando",
+ "7711ad5122": "Comando de configuración local",
+ "e5db1b0419": "Comando de configuración combinado",
+ "addProjectBeforeWorkspace": "Agregue un proyecto antes de crear un espacio de trabajo."
+ },
+ "NewWorkspaceComposerModal": {
+ "fa90f739a5": "Elija el proyecto, el nombre del espacio de trabajo y el agente antes de crear el espacio de trabajo."
+ },
+ "PullRequestPage": {
+ "2560588245": "No se pudo solicitar el revisor",
+ "3450247584": "Comentario",
+ "6ad2c1ab9c": "No se cambiaron archivos.",
+ "4d18310d55": "Archivos cambiados",
+ "94d95cf1f7": "cheques",
+ "9e8d45700e": "Conversación",
+ "e6996f4024": "· actualizado",
+ "00b7b82329": "rama principal",
+ "e1f3641bfd": "de",
+ "c44b70352b": "rama base",
+ "b0e80f083d": "quiere fusionarse en",
+ "8ecda455a0": "Abrir en GitHub",
+ "1a2570e18e": "Iniciar nuevo espacio de trabajo",
+ "57c13a5aa4": "Más acciones en el espacio de trabajo de relaciones públicas",
+ "25690a3855": "Iniciar espacio de trabajo desde PR",
+ "a459866967": "Reanudar espacio de trabajo adjunto a PR",
+ "347034903a": "Copiar enlace de GitHub",
+ "5a01ca7253": "No se pudo sincronizar el estado visto con GitHub.",
+ "996a1897d2": "No se puede sincronizar el estado visto para esta solicitud de extracción.",
+ "e0b15c793f": "No se pudo copiar el enlace de GitHub",
+ "992e799227": "Enlace de GitHub copiado",
+ "61bfc81ada": "No se puede abrir el espacio de trabajo adjunto a esta solicitud de extracción.",
+ "161d91ef02": "Enviar comentario",
+ "d2030fc8cd": "Añade un comentario…",
+ "1208347ac0": "No se pudo agregar el comentario",
+ "61452f2143": "Iniciar espacio de trabajo desde el problema",
+ "14c9fc70ed": "+ Cesionario",
+ "bc215fea4d": "+ Etiqueta",
+ "b936cc51a4": "Cerrado",
+ "7b8f6bf6d8": "Abierto",
+ "e6ad0a8d06": "{{value0}} omitido",
+ "88267924d5": "{{value0}} pendiente",
+ "ae2a34c7b8": "{{value0}} fallando",
+ "7c5035931a": "{{value0}} pasando",
+ "a18d01cda3": "Aún no se han reportado controles",
+ "3912daf310": "Esta solicitud de extracción aún no tiene comprobaciones reportadas.",
+ "45877f5089": "No se encontraron cheques",
+ "85e62c5266": "Inició un agente de inteligencia artificial para los cheques rotos.",
+ "ddfd42f460": "Revise el mensaje antes de iniciar un agente.",
+ "a053bdd082": "Arreglar cheques rotos con IA",
+ "1b14d0a69c": "Abrir en GitHub",
+ "1550675e5f": "No hay salida en línea disponible para esta verificación.",
+ "7720c9c3f5": "Empleos",
+ "8432d17901": "Anotaciones",
+ "f01bf79a79": "controlar #",
+ "000f90afcf": "Terminado",
+ "76551b1161": "Comenzó",
+ "662bc2998d": "Estado:",
+ "d8e82b7f15": "Cargando detalles del cheque...",
+ "54cddd1858": "Vuelva a ejecutar todas las comprobaciones",
+ "68605516dd": "Volver a ejecutar comprobaciones fallidas",
+ "522d9353e1": "Repetición",
+ "0fa8b8faec": "Inicie el agente de IA predeterminado en estas comprobaciones",
+ "5d0f42766d": "Actualizar cheques",
+ "98583589c6": "No se pudo iniciar un agente de IA para los cheques rotos: {{value0}}",
+ "51c65c0265": "No hay cheques rotos que arreglar.",
+ "788a782bb0": "No se pudieron volver a ejecutar las comprobaciones",
+ "18f2af42ac": "Verificar repeticiones solicitadas",
+ "5963a6a852": "Se solicita volver a ejecutar el cheque",
+ "246b2c6456": "No se pudieron actualizar las comprobaciones",
+ "c057f2fcb0": "No se pueden actualizar las comprobaciones sin una ruta al repositorio.",
+ "6591b1fa82": "Cancelar",
+ "42c36d9166": "{{value0}} {{value1}} reacción{{value2}}",
+ "7df8d5fc60": "Abrir el cuadro de combinación de GitHub",
+ "1939d0f663": "Solicitud de extracción",
+ "973ef2fac9": "No se pudo deshabilitar la combinación automática",
+ "d31f4b508c": "No se pudo habilitar la combinación automática",
+ "0f5821b035": "Fusión automática deshabilitada",
+ "5edbe7eefa": "Combinación automática habilitada",
+ "aae645d36d": "No se pudo fusionar la solicitud de extracción",
+ "c57873d721": "Solicitud de extracción fusionada",
+ "a63b3c159c": "Esto actualizará la solicitud de extracción en GitHub.",
+ "eec3706a6a": "{{value0}} PR #{{value1}}?",
+ "b8c6cbb8c4": "No se pudo {{value0}} PR",
+ "710e47aa06": "Solicitud de extracción reabierta",
+ "7aa3b5f706": "Solicitud de extracción cerrada",
+ "3d77438c92": "Esto reabrirá la solicitud de extracción en GitHub.",
+ "5a65651096": "Esto cerrará la solicitud de extracción en GitHub.",
+ "d2d589556c": "Aún no hay comentarios.",
+ "3463d10a63": "Comentarios",
+ "c8ea6c7c4c": "No se proporciona descripción.",
+ "778683ec84": "Descripción",
+ "da9aaa8bcf": "Editar descripción",
+ "4a337ac05f": "Ahorrar",
+ "169a93b29a": "actualizado",
+ "3c891789f6": "por",
+ "f4fe47c2bb": "Resuelto",
+ "0ac19bb52e": "Abrir comentario en GitHub",
+ "d6c6679de7": "Responder al comentario",
+ "76b2a0ac5b": "resuelto",
+ "11505c7a71": "Respuesta publicada.",
+ "6885c619e7": "No se puede responder sin una ruta al repositorio.",
+ "d94810f652": "No se pudo actualizar la descripción.",
+ "9b4190dc98": "Descripción actualizada.",
+ "51ed0cf38b": "Mostrar más líneas a continuación",
+ "e295a78c11": "Mostrar {{value0}} más líneas arriba",
+ "c9de94b07a": "Mostrar más líneas arriba",
+ "5f3e293517": "Restablecer el contexto del código",
+ "85d119be40": "Controles de contexto de código",
+ "791ddede19": "comentario l",
+ "4b960e5978": "Cargando contexto de código...",
+ "89e80af1c7": "archivos vistos",
+ "319cf2d54b": "Mostrar árbol de archivos",
+ "eff839f438": "Se agregó el comentario de revisión.",
+ "d8c3ba91c4": "No se puede comentar sin el jefe de relaciones públicas SHA.",
+ "74660bd80b": "La diferencia no está disponible porque faltan los SHA de confirmación de relaciones públicas.",
+ "2e528e1c2d": "Visto",
+ "ff84e1f54c": "{{value0}} {{value1}} tal como se ve",
+ "5ad00c7a0e": "No hay revisores que coincidan.",
+ "2760fa29a4": "Todos los demás",
+ "828f045847": "Sugerencias",
+ "57750f4a8c": "Cargando...",
+ "805cb72cd4": "Solicite hasta 15 revisores",
+ "a04c137bb7": "Crítico",
+ "3bde131f49": "Escribe o elige un usuario",
+ "d10b6d5209": "No se solicitaron revisores.",
+ "ae9a38fd4a": "Eliminar revisor {{value0}}",
+ "acbd110867": "Cargando revisores",
+ "00d3be6bcd": "Revisores",
+ "f4a4b3fd9f": "Editados recientemente estos archivos",
+ "41d275d3ec": "Solicitar revisor {{value0}}",
+ "36b514a457": "Revisor no solicitado {{value0}}",
+ "c798fa0ec7": "No se pudo eliminar al revisor",
+ "1e6d089420": "Revisores eliminados",
+ "2c1d93da43": "Revisor eliminado",
+ "1ae11c905c": "No hay contexto de repositorio disponible para esta solicitud de extracción.",
+ "102d3d177f": "Revisores solicitados",
+ "03282ff3b9": "Revisor solicitado",
+ "8f369a6b6b": "Puedes solicitar hasta 15 revisores",
+ "dace0d1a9f": "Introduzca un revisor",
+ "77d9388fb0": "desconocido",
+ "c9e7094a7b": "Reanudar espacio de trabajo",
+ "3b6886b2ee": "copiado",
+ "b6bda618cf": "compacto",
+ "35a0573f41": "Anotación",
+ "61a8c69a33": "página",
+ "a4541fd3db": "Arreglar cheques rotos",
+ "c808db1dd1": "Arreglar cheques",
+ "c4c02ea23e": "No se puede crear un espacio de trabajo de reparación automáticamente.",
+ "f119e5f5ef": "Responder",
+ "894cfd884b": "Destino…",
+ "9d5425918e": "Reabrir relaciones públicas",
+ "96d013ed28": "Cerrar solicitud de extracción",
+ "d65f70786e": "cerrado",
+ "eca289e593": "La fusión requiere un repositorio local registrado",
+ "6568ae8ece": "por defecto",
+ "19f19560d5": "destructivo",
+ "aae99c6c04": "pr",
+ "e01e34f5fa": "comentario",
+ "345b68254c": "hilo",
+ "31a7b202f2": "Responder a @{{value0}}",
+ "408e634fbb": "Responder en este hilo de revisión",
+ "34b9f7c264": ":L{{value0}}",
+ "5821aab360": "No se pudo publicar la respuesta.",
+ "84fc40769a": "-L{{value0}}",
+ "1378d79e83": "Juntos",
+ "e5f4a24f78": "En línea",
+ "dd94111c18": "Contraer todo",
+ "eb722a5a8c": "Expandir todo",
+ "19628e058d": "No se pudo agregar el comentario de revisión.",
+ "50b8fb290f": "Marcar visto",
+ "2b4fdb880c": "Desmarcar visto",
+ "56ec6eafb7": "Abra los detalles de relaciones públicas para ver los revisores actuales.",
+ "7f964a365a": "Eliminar revisor"
+ },
+ "QuickOpen": {
+ "1dbd3f59ff": "Mover",
+ "73b2c581f1": "Cerca",
+ "95fccbae88": "ESC",
+ "61b1c871a6": "Abierto",
+ "250e5b2dfb": "Ingresar",
+ "74e2e1b3e4": "No hay archivos coincidentes.",
+ "722a21e1a8": "Cargando archivos...",
+ "1cb6ef47b7": "Ir al archivo...",
+ "9e97f08d0f": "Buscar un archivo para abrir",
+ "ec31e058f7": "ir al archivo",
+ "73b44e7bde": "Copiar comando de instalación",
+ "1cf8561ab4": "en el control remoto para habilitar un listado rápido y compatible con gitignore:",
+ "5d80dc39bb": "ripgrep",
+ "2ca749c15d": "Instalar",
+ "4725b0e931": "El escaneo de apertura rápida es demasiado grande (",
+ "b227d88520": "{{value0}} archivos encontrados",
+ "995be8ea22": "Copiar",
+ "cf144856dc": "copiado"
+ },
+ "SelectedTextCopyMenu": {
+ "9b40d7b018": "Copiar"
+ },
+ "StarNagCard": {
+ "92b0f9d921": "está autenticado y vuelve a intentarlo.",
+ "cd8c34aac1": "gh",
+ "cf82170065": "No se pudo destacar el repositorio. Cerciorarse",
+ "30c36231c1": "Si Orca te ha ahorrado tiempo, una estrella de GitHub es de gran ayuda. Ayuda a otros desarrolladores a descubrir el proyecto y mantiene al equipo motivado para implementar mejoras.",
+ "b5e685e4d9": "Despedir",
+ "5f6df21046": "¿Disfrutando de Orca?",
+ "2d67b6c849": "Estrella en GitHub",
+ "af3c9bbb37": "Protagonizada…"
+ },
+ "TaskPage": {
+ "513cddfa7a": "Verificando…",
+ "ff69a30681": "Cancelar",
+ "2abe22ef76": "Su token se cifra a través del llavero del sistema operativo y se almacena localmente.",
+ "246c2b3dd3": "Configuración de la cuenta de Atlassian",
+ "59c14d34a2": "Crear un token en",
+ "b95623e93f": "Token API de Atlassian",
+ "68df347677": "tu@ejemplo.com",
+ "163df31e0e": "https://example.atlassian.net",
+ "33fc2bcb30": "Utilice la URL de un sitio de Jira Cloud, un correo electrónico de Atlassian y un token de API para explorar problemas.",
+ "60f806ce99": "Conectar el sitio de Jira",
+ "8ff6fdc368": "Creando…",
+ "fc0d8a1fa4": "para presentar.",
+ "919a20dd5b": "Ingrese {{value0}}",
+ "56cdb413a2": "Valores separados por comas",
+ "1f0fce91e3": "Seleccione {{value0}}",
+ "cbcdcbe244": "Cargando campos obligatorios de Jira...",
+ "34d97ca682": "¿Qué está sucediendo?",
+ "f161bf9ede": "Descripción (opcional)",
+ "578f730c16": "Breve resumen",
+ "16cba35bee": "Título",
+ "ae592fee62": "Tipo de problema",
+ "7d63e2626e": "Cargando...",
+ "93c57f15e5": "No se encontraron proyectos.",
+ "cfb56a7868": "Buscar proyectos...",
+ "00022ec0ba": "Proyecto",
+ "0c11ca0b6d": "Nuevo problema de Jira",
+ "d0ca4aa1d0": "Etiquetas",
+ "1742eafc14": "Sin proyecto",
+ "69591944e7": "Bajo",
+ "7fd59c18d8": "Medio",
+ "345b169f1f": "Alto",
+ "f373ab1a4f": "Urgente",
+ "713179dfdc": "Sin prioridad",
+ "c8d5bec5f7": "Prioridad",
+ "42a9160321": "No asignado",
+ "d2a876ca53": "Cesionario",
+ "154b0fa623": "Estado",
+ "9bc8aea407": "Añadir descripción...",
+ "d9151fd4e9": "Título del problema",
+ "4f3cb99f41": "Cambiar de equipo",
+ "c11105dac5": "Nuevo número",
+ "1b59a07674": "Creando...",
+ "cf72580c04": "Escribe una descripción, un resumen del proyecto o recopila ideas...",
+ "2ea1c701b6": "fecha objetivo",
+ "7da41c9225": "Objetivo",
+ "09623359b9": "Fecha de inicio",
+ "7d08e8be0f": "Comenzar",
+ "af9e877f30": "Sin etiquetas",
+ "d6cda23ef1": "Miembros",
+ "cfaadb6b22": "Sin pista",
+ "34da8ac06c": "Dirigir",
+ "579f98afcd": "Añade un breve resumen...",
+ "ecbcc83140": "Nombre del proyecto",
+ "b6795e65fd": "Cerca",
+ "a98cbe7664": "Equipo",
+ "02f67c0d09": "Nuevo proyecto",
+ "bdebffcbfe": "Crea un proyecto Linear para el equipo seleccionado.",
+ "1361275ec3": "Nuevo proyecto Linear",
+ "7f3f7b4c18": "Descripción (opcional, rebaja)",
+ "9f2b4c03a6": "Presentando",
+ "d3d0998b7d": "Nuevo problema de GitHub",
+ "d1e243795c": "asuntos",
+ "be8cf68d9f": "ver problemas",
+ "67662ade50": "problemas del proyecto",
+ "6244a02f46": "Abrir en Linear",
+ "606a85c774": "Abierto",
+ "5e8061b088": "Iniciar espacio de trabajo desde {{value0}} {{value1}}",
+ "592a55611b": "Intente seleccionar más equipos o actualizar; Los filtros de equipo se aplican al conjunto de incidencias recuperadas actualmente.",
+ "618107fab3": "No hay problemas recuperados que coincidan con los equipos seleccionados.",
+ "903c7af49f": "No se encontraron problemas Lineares",
+ "5ed38a49e5": "Revise el error del espacio de trabajo a continuación y luego actualice.",
+ "cc8795e07c": "No se pueden cargar problemas Lineares",
+ "f362667d55": "Actualizado",
+ "b1eaa18ace": "Asunto",
+ "37e7ee311e": "Llave",
+ "b7bae28b6a": "mostrado",
+ "a26a48252e": "Propiedades de visualización",
+ "5d2d835467": "Realizar pedidos",
+ "5659da12fc": "Agrupamiento",
+ "9c57663908": "Vista",
+ "af377b13b1": "{{value0}} ver",
+ "d47248df4d": "Modo de vista Linear",
+ "f397d513e3": "Atrás",
+ "b39fe6511d": "proyectos",
+ "8675cd6188": "Linear",
+ "733b8f2421": "Linear / Vistas",
+ "bc06ed0fb0": "Volver a vistas",
+ "3cb855080f": "vistas",
+ "b4e10f096e": "Dueño",
+ "a04fe7ba73": "Visibilidad",
+ "0aa8525950": "Modelo",
+ "dfc0c79bd8": "Asuntos",
+ "8a07f21e76": "Salud",
+ "851017590d": "Agregar acceso Linear",
+ "228b25028f": "Explore y comience a trabajar en los problemas Lineares asignados directamente desde aquí.",
+ "6d56559467": "Conecta tu cuenta Linear",
+ "eee68073b2": "Abierto en Jira",
+ "9497f2787c": "Iniciar espacio de trabajo",
+ "eba87f2edb": "No se encontraron problemas con Jira",
+ "63b2abd3aa": "Problemas con Jira",
+ "e7115334aa": "Ocultar Jira",
+ "83bce6be5c": "Conecta Jira",
+ "b518ae6307": "Explora, edita, crea y comienza a trabajar desde incidencias de Jira directamente desde aquí.",
+ "a150c59da7": "Conecte su sitio Jira",
+ "bcdc1330b2": "Abrir en GitLab",
+ "00b7ffb952": "Tipo / Estado",
+ "eb10c32872": "IDENTIFICACIÓN",
+ "e9b6955dcd": "Número {{value0}}",
+ "a0544fb653": "¡SEÑOR! {{value0}}",
+ "8396825a14": "Acción",
+ "c1d1600362": "Abrir en el navegador",
+ "b6329379ca": "Iniciar nuevo espacio de trabajo",
+ "054bf695cc": "Borrador",
+ "285bc21dc5": "Cambie la consulta o borrela.",
+ "d0e3c8f933": "No hay trabajo de GitHub coincidente",
+ "5b6b2af943": "Reintentando…",
+ "0c0de0fc0e": "No se pudieron cargar los problemas de",
+ "d1766fd62d": "los proyectos no pudieron cargarse",
+ "7762f4b03a": "de",
+ "443f7dd928": "Unir",
+ "a7396b05c6": "cheques",
+ "f6fa3c97d0": "Revisores",
+ "8aba10579d": "Cesionarios",
+ "5eccb3c841": "Título / Contexto",
+ "d4c2830063": "Actualizar elementos de trabajo de GitLab",
+ "c679af7ad9": "Actualizar mis todos",
+ "dfd72673e7": "No se pudo guardar la selección del proyecto.",
+ "b797bdd7c3": "Borrar búsqueda",
+ "99c2755218": "Jira JQL, p.ej. proyecto = ABC AND statusCategory! = Listo",
+ "2ff9fd71fd": "Actualizar problemas de Jira",
+ "0b65d3fb2c": "Buscar proyectos Lineares...",
+ "eec0c5c079": "Buscar temas Lineares...",
+ "8964184a8b": "Actualizar Linear",
+ "3feb524d42": "Nueva edición Linear",
+ "0cbf7e5cf3": "Modo de tarea Linear",
+ "ff53631e6f": "Actualizar el trabajo de GitHub",
+ "6ffa6be99f": "Actualización del trabajo de GitHub",
+ "b15ceb409d": "Buscar problemas de GitHub...",
+ "eee4df4c66": "Buscar relaciones públicas de GitHub...",
+ "e592d99051": "Todos los sitios de Jira",
+ "d09b7631b7": "No se pudo cambiar el sitio de Jira.",
+ "8029e2bd4d": "Seleccione un equipo lineal para abrir en Linear",
+ "609532fae7": "No se pudo guardar la fuente de tarea predeterminada.",
+ "4826fd1ad8": "Cerrar · Esc",
+ "1a06219d5c": "Cerrar tareas",
+ "3f594861a5": "No se pudo guardar la selección del equipo.",
+ "d0d570b306": "No se pudo cambiar el espacio de trabajo Linear.",
+ "cb98f0350c": "Creado {{value0}}",
+ "1e1b2ad8f2": "Seleccione un equipo del espacio de trabajo del proyecto antes de presentar este problema.",
+ "3ca9b424a3": "No se pudo crear el proyecto.",
+ "3f9604efc7": "Problema abierto #{{value0}}",
+ "585dba2989": "No se puede abrir el espacio de trabajo adjunto a este problema.",
+ "534a9c6017": "No se puede abrir el espacio de trabajo adjunto a esta solicitud de extracción.",
+ "fe380f306c": "No se pudo guardar la vista de tareas predeterminada.",
+ "af2a8371de": "No se pudieron cargar los tipos de problemas de Jira.",
+ "6775c05483": "No se pudo actualizar el estado Linear",
+ "745ae567d4": "\"{{value0}}\" no está disponible para {{value1}}",
+ "669e419d65": "A la vista Linear le falta el contexto del espacio de trabajo.",
+ "cba2a2b7fb": "Al proyecto Linear le falta el contexto del espacio de trabajo.",
+ "f4374519ae": "Su fuente de problemas preferida (ascendente) ya no está configurada para {{value0}}. Usando origen.",
+ "e9139db03f": "No se pudo ocultar {{value0}}.",
+ "b73717af92": "Próximo",
+ "0c8df28045": "Página siguiente",
+ "ae859c816b": "Página {{value0}}",
+ "cd171f3391": "...",
+ "297a805b64": "Anterior",
+ "6cd6b3ae6a": "Pagina anterior",
+ "e65757a338": "Paginación",
+ "37d60046e3": "Abrir el cuadro de combinación de GitHub",
+ "1a9ea003dc": "No se pudo deshabilitar la combinación automática",
+ "a3318684bc": "No se pudo habilitar la combinación automática",
+ "a5bf86defe": "Fusión automática deshabilitada",
+ "fed317634c": "Combinación automática habilitada",
+ "88f478cdef": "No se pudo fusionar la solicitud de extracción",
+ "a161925adc": "Solicitud de extracción fusionada",
+ "0506a78337": "Esto actualizará la solicitud de extracción en GitHub.",
+ "844dc193c7": "{{value0}} PR #{{value1}}?",
+ "995dd6af9b": "Abrir cheques de relaciones públicas",
+ "8a22eb3f7b": "No hay revisores que coincidan.",
+ "67755a83a1": "Todos los demás",
+ "3ace2e6bcf": "Sugerencias",
+ "0eacf48491": "Cargando…",
+ "0b9b04f4b5": "Escribe o elige un usuario",
+ "62c7bd789f": "Solicite hasta 15 revisores",
+ "5d4fd69a6a": "Activo recientemente en esta solicitud de extracción",
+ "ed1daeb49a": "No se pudo eliminar al revisor",
+ "837bb901ec": "Revisores eliminados",
+ "f9191d1714": "Revisor eliminado",
+ "dc67f69962": "No se pudo solicitar el revisor",
+ "8f06dbb9e5": "Revisor solicitado",
+ "969e26577c": "Puedes solicitar hasta 15 revisores",
+ "d00571d9b1": "Introduzca un revisor",
+ "edf4bc4135": "No hay usuarios asignables.",
+ "53e002d895": "La emisión no tiene slug de repositorio.",
+ "7f94eb6395": "Asignar problema",
+ "bb63046423": "Asignado a {{value0}}",
+ "ca63694b4c": "No se pudieron actualizar los asignados.",
+ "b36f4bf9de": "Sin etiquetas.",
+ "5ebff3a0aa": "Ninguno",
+ "d09bf34db7": "Cerrado",
+ "1c893195ac": "No se pudo actualizar el estado",
+ "afc68824ff": "No se encontraron estados",
+ "cc13109b5d": "Estados de carga",
+ "d45a910c4a": "Cambiar estado Linear de {{value0}}",
+ "d8a517ad89": "Identificador",
+ "50387522d7": "Sin agrupación",
+ "d747aed72f": "Junta",
+ "a6f7e93d7f": "Lista",
+ "e78ec261ed": "Vistas",
+ "727069bee5": "Proyectos",
+ "137e2a8a01": "relaciones públicas",
+ "18451e99df": "Hecho",
+ "4b6e40e42c": "Todo abierto",
+ "bd9965df51": "Reportado",
+ "1301d376f1": "Asignado",
+ "9cd11ba218": "Jira",
+ "11a828abf8": "GitLab",
+ "acef77f7ca": "GitHub",
+ "524f095d55": "Necesita revisión",
+ "7698af5263": "Mío",
+ "94f0339621": "Asignado a mi",
+ "c2268a9982": "Todo",
+ "37a82eaaf8": "Fusionado",
+ "887efe9140": "Conectar",
+ "a70153f583": "conectando",
+ "6459faa8b3": "error",
+ "e15ba2d2eb": "Crear problema",
+ "3b11c8e8fc": "formación",
+ "e178c0a953": "Elija un proyecto de Jira antes de crear el problema.",
+ "0f7b0d964a": "Crea un nuevo problema en {{value0}}.",
+ "eff9800d4b": "{{value0}} etiqueta{{value1}}",
+ "d7f16d0e32": "Seleccionar equipo",
+ "5301ca0f20": "Crear proyecto",
+ "7719d8daa9": "{{value0}} miembro{{value1}}",
+ "5af6f0ae5b": "Seleccionar equipo",
+ "cfb730b73e": "asunto",
+ "3659f9792a": "junta",
+ "d079be2dc8": "No hay problemas asignados. Intenta buscar algo.",
+ "2bdefbcac3": "Pruebe con una consulta de búsqueda diferente.",
+ "25ff84769a": "Ningún problema coincide con este contexto Linear.",
+ "cbce2bc9cd": "ninguno",
+ "51411113df": "lista",
+ "60f68a2ef4": "Cuestiones Lineares",
+ "b2007ba885": "proyecto",
+ "6edf402e11": "descripción general",
+ "9ae151b26b": "lineal",
+ "94d900518d": "Ningún problema coincide con el ajuste preestablecido seleccionado.",
+ "f51e254d35": "Pruebe con una consulta JQL diferente.",
+ "4645a7814f": "jira",
+ "e224d76876": "SEÑOR",
+ "bbec4717ee": "señor",
+ "d6d08c1650": "Seleccione un proyecto para ver los elementos de trabajo de GitLab.",
+ "f294c500ef": "Ningún trabajo de GitLab coincide con este filtro.",
+ "cd7dc432a3": "Ningún GitLab MR coincide con este filtro.",
+ "171b7739d8": "señora",
+ "a9f256ecea": "Ningún problema de GitLab coincide con este filtro.",
+ "2007e14d95": "gitlab",
+ "456b8512da": "Solicitud de fusión",
+ "03da966159": "Seleccione un proyecto para que podamos autenticarnos en GitLab.",
+ "d591aac6ae": "No hay todos pendientes. ¡Estáis todos atrapados!",
+ "33a4bd7f5c": "todos",
+ "66ae7330f6": "Más acciones",
+ "93d5f21fc1": "pr",
+ "e104fa3d3d": "Iniciar espacio de trabajo desde el problema",
+ "2193a99ec1": "Abrir espacio de trabajo adjunto al problema",
+ "7deb9e59a5": "Más acciones de relaciones públicas",
+ "7753652524": "Reanudar",
+ "e4b29c5bcf": "Iniciar espacio de trabajo desde PR",
+ "67d881244c": "Reanudar espacio de trabajo adjunto a PR",
+ "6430594b18": "autor desconocido",
+ "7799ad9ab6": "borrador",
+ "0bfbf62f75": "Rever",
+ "38139edb52": "github",
+ "31f81cc334": "Actualizando el trabajo de GitHub...",
+ "3d93316bb0": "prs",
+ "937b29fa35": "elementos",
+ "bc46d8204e": "Seleccione un proyecto para abrir en GitHub",
+ "d1132848f8": "Seleccione un proyecto de GitHub para abrir en GitHub",
+ "2af3ab5c58": "Selecciona un equipo para abrir en Linear",
+ "aec5feeb69": "No se pudo crear el problema de Jira.",
+ "7437e340b4": "No se pudo crear el problema.",
+ "9e03c17847": "Abra los detalles de relaciones públicas para ver los revisores actuales.",
+ "3b7f34282f": "cerrado",
+ "246bd64aed": "Abrir {{value0}} en Linear",
+ "ff90d0abc7": "Iniciar espacio de trabajo desde {{value0}}",
+ "fe28c9821f": "vista",
+ "8d1e17a3ef": "Abra {{value0}} en GitHub",
+ "4ac8ff2275": "Abrir {{value0}} en Jira"
+ },
+ "Terminal": {
+ "73768427cf": "Cerca",
+ "f82e9f02df": "Cancelar",
+ "7958465754": "Hay terminales locales con procesos en ejecución. ¿Cerrar la ventana de todos modos?",
+ "2fa9c69ff3": "¿Cerrar ventana?",
+ "cd51e28d8b": "Ahorrar",
+ "0037b21794": "No guardar",
+ "21295c6b8c": "Cambios no guardados",
+ "5c1d2a32bb": "Cargando editor...",
+ "f0600556b3": "No se pudo crear el archivo de rebajas sin título.",
+ "37da0d736f": "Nueva pestaña del navegador",
+ "a2a279b32a": "Se agotó el tiempo de guardado o falló. Corregir errores antes de cerrar.",
+ "46e08bc5c8": "Este archivo tiene cambios no guardados.",
+ "61ed600d29": "\"{{value0}}\" tiene cambios no guardados. ¿Quieres guardar antes de cerrar?",
+ "cdc9ac4b2d": "editor"
+ },
+ "TerminalSearch": {
+ "db234b7519": "Cerca",
+ "7cb40c04eb": "Próximo partido",
+ "0f3066256e": "Partido anterior",
+ "42e466b9f1": "expresión regular",
+ "90c61387d9": "Distingue mayúsculas y minúsculas",
+ "e07012f26e": "Buscar..."
+ },
+ "UpdateCard": {
+ "68b235d264": "Reiniciar para actualizar",
+ "6714206e5a": "Se descarga Orca v{{value0}}. Reinicie cuando esté listo.",
+ "93794ea932": "Orca v{{value0}} se está descargando.",
+ "8acbdd3961": "Minimizar a la barra de estado",
+ "17412483da": "Listo para instalar",
+ "47126bcf57": "Descargar manualmente",
+ "3553a8672f": "último error",
+ "90559b14e3": "Esto activa un conmutador de red Electron de todo el proceso después del reinicio. Úselo para VPN corporativas o servidores proxy que rechacen las descargas de actualizaciones HTTP/2.",
+ "6e45bfa2e0": "Descargando...",
+ "558842597d": "Descargando actualización",
+ "f58b5c57a6": "Nuevo:",
+ "ec8fe71cfc": "Actualizar",
+ "44324ef542": "Notas de la versión",
+ "fdd4a364fa": "Las sesiones no serán interrumpidas.",
+ "05ad78a6d1": "La Orca v{{value0}} está lista.",
+ "318d3b4bc7": "Descartar actualización",
+ "9abc59f814": "Actualización disponible",
+ "aad383aecc": "Lea las notas de la versión completas",
+ "ccd8b0a793": "más desde tu última actualización",
+ "b1d867f4fb": "Las sesiones de su terminal no se interrumpirán durante la actualización.",
+ "09a55c39b5": "Instalando...",
+ "ea2a41adbe": "Estás en la última versión.",
+ "ba5ffc949c": "Buscando actualizaciones...",
+ "2c2d3e03ca": "Intentar otra vez",
+ "4cf109845a": "Error de actualización",
+ "6b0085010d": "Vuelva a comprobar",
+ "48565a32bc": "Reintentar descargar",
+ "933c6fdf5b": "Habilitar y reiniciar",
+ "1339b82cee": "Descarga HTTP/2 bloqueada",
+ "7274ef6e59": "Descartar consejo",
+ "a726967bd3": "Despedir",
+ "d5253b54af": "error",
+ "7ffc08506e": "controlar",
+ "522df222b9": "hilandero"
+ },
+ "WorktreeJumpPalette": {
+ "ac037cfac2": "Mover",
+ "75499e01d9": "Cerca",
+ "66b5a67bee": "ESC",
+ "45def60329": "Abierto",
+ "f65d992a11": "Ingresar",
+ "c5081f2814": "Árbol de trabajo actual",
+ "52404f8096": "Pestaña actual",
+ "739bda980c": "primario",
+ "556e7232ca": "Actual",
+ "684e8d7bc2": "Recopilando sus árboles de trabajo recientes y pestañas abiertas.",
+ "ff908adfe9": "Cargando objetivos de salto",
+ "1ebe225fee": "Busque árboles de trabajo, configuraciones, pestañas y acciones...",
+ "4e4ff044d5": "Buscar árboles de trabajo, configuraciones, pestañas y acciones",
+ "4ee378034d": "Saltar a...",
+ "f7fda8d562": "Cree un árbol de trabajo o abra una pestaña en Orca para comenzar.",
+ "1628fd7dfa": "No hay árboles de trabajo, configuraciones, acciones ni pestañas abiertas activas",
+ "b781ae05e3": "Escriba para buscar árboles de trabajo, configuraciones, pestañas y acciones.",
+ "f60f8730be": "No hay otros árboles de trabajo a los que cambiar",
+ "c4afa68159": "Pruebe con un árbol de trabajo, configuración, acción, título de página, emulador, URL, PR o puerto.",
+ "dbd9d87eec": "Ningún resultado coincide con tu búsqueda",
+ "2c38630a01": "El espacio de trabajo ya no existe",
+ "7726ce9970": "La pestaña del emulador móvil ya no existe",
+ "d7d496a451": "La página del navegador ya no existe",
+ "50a1d11d5b": "Pestañas abiertas",
+ "088d66d980": "Acciones y configuraciones",
+ "dabd819ca1": "Escriba para ver todos los árboles de trabajo {{value0}}",
+ "20af998bff": "{{value0}} artículos disponibles{{value1}}",
+ "bb72c08e63": "{{value0}} resultados encontrados{{value1}}",
+ "34c8fbb46e": "SSH remoto",
+ "63c2be1914": "SSH desconectado",
+ "95be6587d3": "Crear árbol de trabajo \"{{value0}}\"",
+ "worktreesHeader": "árboles de trabajo",
+ "recentWorktreesHeader": "Árboles de trabajo recientes",
+ "settingsBadge": "Ajustes",
+ "actionBadge": "Acción"
+ },
+ "github": {
+ "pr": {
+ "merge": {
+ "state": {
+ "a80132573b": "GitHub todavía está calculando el estado de fusión de esta solicitud de extracción",
+ "f958920f3a": "De cheques",
+ "9bd983ce8f": "GitHub dice que este PR puede fusionarse, pero aún se están realizando comprobaciones",
+ "4e2507176b": "Cheques pendientes",
+ "1432ecff30": "GitHub dice que este PR puede fusionarse, pero algunas comprobaciones fallaron",
+ "87fa36ac83": "Los controles fallaron",
+ "1766eb46ba": "GitHub informa que esta solicitud de extracción está bloqueada",
+ "bf5e4c6c92": "Obstruido",
+ "c614e2660a": "Actualizar la rama antes de fusionar",
+ "039c072f94": "Detrás",
+ "b37d45bca9": "GitHub informa conflictos de fusión",
+ "7e8bbe3cd7": "Conflictos",
+ "09896aad26": "El estado de fusión no está disponible para este PR",
+ "bd4f27b50e": "Unir",
+ "35ec24bc43": "Esta rama base usa la cola de combinación de GitHub",
+ "b289646bcd": "Los informes de GitHub solicitaron cambios en esta solicitud de extracción",
+ "c606463dc2": "Cambios solicitados",
+ "a20db875ed": "GitHub requiere aprobación de revisión antes de que esta solicitud de extracción pueda fusionarse",
+ "1f8eb81c0e": "Se requiere aprobación",
+ "f03028e055": "Esta solicitud de extracción aún es un borrador.",
+ "ec8e2cebaa": "Borrador",
+ "820fd21663": "Esta solicitud de extracción está cerrada.",
+ "4f976d3450": "Cerrado",
+ "62eb8d39da": "Esta solicitud de extracción ya está fusionada",
+ "83ecdbb4a6": "Fusionado",
+ "331ebe1170": "Agregue esta solicitud de extracción a la cola de combinación de GitHub",
+ "b169f943e1": "Fusionar cuando esté listo",
+ "62703b1dc4": "La fusión automática de GitHub está habilitada para esta solicitud de extracción",
+ "48d75ae118": "Deshabilitar la fusión automática"
+ }
+ }
+ },
+ "project": {
+ "ColumnResizeHandle": {
+ "1304289353": "Cambiar tamaño de columna"
+ },
+ "GhAuthErrorHelp": {
+ "7e800068d8": "Recargar",
+ "baa006f9af": "Documentos",
+ "3fefeebde4": "Copiar comando de actualización",
+ "9c2da6353b": "Copiar comando de inicio de sesión",
+ "b436c586d1": "comando copiar",
+ "8a7f6bf5dc": "No se pudo copiar",
+ "224c9d0ae8": "Copiado al portapapeles",
+ "891a7d4616": "Desarmado para este shell",
+ "fd17b3019f": "Desarmado (PowerShell, persistente)",
+ "ae43542893": "Encuentra dónde está configurado",
+ "df636f5886": "Compruebe si está configurado (PowerShell)"
+ },
+ "ProjectCell": {
+ "4b5b871da8": "No hay etiquetas en este repositorio.",
+ "2219e945ef": "Cargando…",
+ "54cac64427": "Row no tiene slug de repositorio.",
+ "8ae56a88a6": "Etiquetas",
+ "f7cdb78efb": "Cesionarios",
+ "ebde486e3c": "Claro",
+ "191905e20e": "Actual y próximo",
+ "e17bb96881": "Terminado",
+ "943b3dadc9": "Este repositorio no tiene tipos de problemas.",
+ "c7b059cf07": "Tipo de problema",
+ "c5f949e489": "Asunto",
+ "8d669084f6": "Restringido",
+ "6efdc0d920": "Borrador",
+ "d0d0e13a5a": "relaciones públicas",
+ "af5d8c912a": "Artículo restringido",
+ "bb7ebc11e3": "Añadir número",
+ "9cb1a0c984": "Agregar texto",
+ "2e26a06c70": "Agregar etiqueta",
+ "36341ffc66": "Asignar",
+ "e369bf4fec": "Seleccionar",
+ "ffeff79861": "PULL_REQUEST"
+ },
+ "ProjectGroupHeader": {
+ "82a22d2079": "Actual",
+ "244c9e7d06": "Todo"
+ },
+ "ProjectItemSlugDialog": {
+ "e55a5c4e68": "Vista previa de la fila del proyecto.",
+ "4450efea9c": "elemento de GitHub"
+ },
+ "ProjectPicker": {
+ "96739284c3": "Pegue la URL de un proyecto a continuación para llegar a los que faltan.",
+ "9b36829267": "No se encontraron vistas.",
+ "72a05c04a6": "Cargando vistas…",
+ "9bf55fa1e8": "Elige una vista",
+ "a51b3337ab": "← Volver",
+ "8ab5447c64": "Alfiler",
+ "5009ffc2f3": "Quitar pasador",
+ "fce99a24a7": "Agregar",
+ "5113ecc298": "Agregar por URL o propietario/número",
+ "7b6d39627e": "Cargando…",
+ "b787682111": "Explorar todo",
+ "ba0ab9a117": "Explorar todo (cargando…)",
+ "b3044b7a25": "Reciente",
+ "707843206c": "Fijado",
+ "f492e1b539": "Buscar proyectos",
+ "44b2c6326b": "No se pudieron cargar las vistas: {{value0}}",
+ "ab1a2c357d": "Hoja de ruta (no compatible)",
+ "d34ef9b554": "Tablero (sin soporte)",
+ "43a88ae574": "BOARD_LAYOUT",
+ "1a2b8e512e": "Mesa",
+ "cafb908f34": "TABLE_LAYOUT"
+ },
+ "ProjectRow": {
+ "75b5d816e3": "empezar a trabajar",
+ "e12be8b4d4": "Abrir en GitHub",
+ "c3b81ddea2": "BORRADOR_EDICIÓN"
+ },
+ "ProjectViewList": {
+ "989f81dc2a": "columnas",
+ "f949f5b2b7": "Configurar columnas",
+ "eddfc7a794": "Ordenar por {{value0}}",
+ "4f57d2e0b1": "Ningún elemento coincide con el filtro de esta vista."
+ },
+ "ProjectViewWrapper": {
+ "463f1205c0": "Cargando vista del proyecto",
+ "23b87ba9f7": "Abrir en GitHub",
+ "4d2a77a119": "Solicitud de función de archivo",
+ "1bf8c01c8b": "Cambie a una vista de tabla para trabajar con este proyecto en Orca.",
+ "55de4fb57a": "{{value0}}. {{value1}} Presente una solicitud de función en {{value2}}.",
+ "2edf5e7e77": "{{value0}}: Orca aún no admite vistas del proyecto {{value1}}. Presente una solicitud de función en {{value2}}.",
+ "7245c3d7ac": "Borrar búsqueda",
+ "c5bc7ec007": "Ver filtro: {{value0}}",
+ "840c268665": "Agregar repositorio",
+ "dffa899f36": "Cancelar",
+ "7037c8f5f1": "Repositorio no en Orca",
+ "512fc171d6": "Elija un proyecto para comenzar.",
+ "71fb69926c": "Refrescar",
+ "a8fa0d2bf5": "Refrescante",
+ "fd15491034": "Abrir vista en GitHub",
+ "22df63c393": "Los datos de la subemisión no están disponibles para su token.",
+ "067119985c": "Búsqueda de GitHub, p. cesionario:@yo es:abierto",
+ "1850fceac8": "{{value0}}/{{value1}} no se agrega a Orca. Agréguelo para comenzar a trabajar o ábralo en GitHub."
+ },
+ "slug": {
+ "dialog": {
+ "AssigneesEditor": {
+ "529fec247b": "Cargando…",
+ "98914e6b36": "Cesionarios:",
+ "94a4e6e4fa": "ninguno"
+ },
+ "Comments": {
+ "fd5cccd138": "Comentario",
+ "1c95937c8b": "Escribe un comentario…",
+ "c0e576e96b": "Cancelar",
+ "c3e829b4d9": "Ahorrar",
+ "463d030ae4": "Borrar",
+ "8564f58542": "Editar",
+ "5f104bf855": "Aún no hay comentarios."
+ },
+ "LabelsEditor": {
+ "34dd57d6c8": "Cargando…",
+ "a7b182fcda": "Etiquetas:",
+ "1a5366b5be": "ninguno"
+ },
+ "SlugDialogBody": {
+ "598ad6a517": "Comentarios",
+ "41169e41fb": "Añade una descripción…",
+ "a91735d19f": "Cancelar",
+ "e64f6c3eff": "Ahorrar",
+ "e4ef8281e9": "Cargando…",
+ "ae98897edf": "Cerca",
+ "69caf40ae8": "Abrir en GitHub",
+ "7c302f8174": "Intitulado"
+ }
+ }
+ }
+ },
+ "GitHubMarkdownComposer": {
+ "015b4e607d": "Cancelar",
+ "e3bd59143c": "Insertar",
+ "f24783f470": "https://...",
+ "ec6310b731": "Utilice una URL de imagen http:// o https://."
+ },
+ "IssueSourceSelector": {
+ "d6aeb2012b": "Mostrando problemas de",
+ "787c970baf": "Fuente del problema",
+ "643d7e9496": "río arriba",
+ "51d1608920": "Origen",
+ "cdc9bd64fa": "compacto",
+ "30b2c9df91": "Río arriba"
+ },
+ "PRFilterDropdowns": {
+ "979be3cf6b": "Cesionario",
+ "b27b7e526c": "Revisión de",
+ "7f1ba66c3e": "Revisado por",
+ "9d0f2eda6d": "Etiqueta",
+ "01f3f3d161": "Autor",
+ "13b3ac0a84": "Estado",
+ "79c54552f7": "Filtros",
+ "8a2ffbf9b3": "Quitar filtro {{value0}}",
+ "19bb6f115f": "revisado por"
+ },
+ "PRFilterPickers": {
+ "fdf387297c": "Claro (",
+ "472c12ae03": "Claro",
+ "2d1f58eda6": "Usar"
+ },
+ "PRFilterSections": {
+ "a00830d3f7": "Sin usuarios",
+ "0103e1cb18": "Revisado por",
+ "94b42b0edf": "Revisión solicitada",
+ "de26e2eb06": "Sin etiquetas",
+ "458ea3602b": "Sin autores",
+ "b69fa4fa20": "Atrás",
+ "30ebb6ca44": "Limpiar todos los filtros",
+ "8177eda37e": "Filtrar",
+ "ea3416d646": "Cesionario",
+ "b1d9fdea08": "Etiqueta",
+ "24754c44ad": "Autor",
+ "764a0b4ce1": "Estado",
+ "f0cf6dd591": "apagado",
+ "1e9b5244f2": "en",
+ "b930de7194": "Solo borrador",
+ "e0002f1eba": "seleccionado",
+ "2b2f019091": "cualquier estado",
+ "0fd3249e2e": "Cerrado",
+ "d78b60b5c2": "Abierto",
+ "bd162b7d5a": "Fusionado",
+ "2e639b84fa": "crítico",
+ "712c5abdbf": "etiqueta",
+ "4e50c7bc03": "cesionario",
+ "7bf3a6e5ac": "autor",
+ "66256a73b3": "estado",
+ "3ce4d5e96e": "prs"
+ },
+ "github": {
+ "rate": {
+ "limit": {
+ "display": {
+ "5509443543": "Cargando presupuesto de API de GitHub...",
+ "34973d4695": "El presupuesto de la API de GitHub no está disponible.",
+ "d12d3d6f33": "Actualizar el presupuesto de la API de GitHub",
+ "d5e5de9070": "Orca usa REST, Search y GraphQL a través de la CLI de GitHub.",
+ "58c5f88216": "Presupuesto de la API de GitHub",
+ "6da1858354": "izquierda · se reinicia en",
+ "f42790d150": "de",
+ "01f7323e58": "API GraphQL",
+ "1daf0f22a9": "GrafoQL",
+ "1f2f28a4de": "API de búsqueda",
+ "c377a4f06a": "Buscar",
+ "c392c749a6": "API DESCANSO",
+ "bb227706a6": "DESCANSAR"
+ }
+ }
+ }
+ }
+ },
+ "linear": {
+ "api": {
+ "key": {
+ "dialog": {
+ "834a52c084": "Verificando...",
+ "f8f704a019": "Cancelar",
+ "e603ee9156": "Configuración de la API del espacio de trabajo",
+ "dc7ccb0f7c": "Claves API personales",
+ "e3100b36b9": "Si las claves API de los miembros están bloqueadas, solicite a un administrador del espacio de trabajo que las permita desde la configuración de la API del espacio de trabajo.",
+ "d56d3629f4": "Prefiera el acceso completo cuando Orca debería mostrar todos los equipos a los que la cuenta puede acceder en ese espacio de trabajo. Las claves restringidas solo exponen los equipos permitidos y los equipos privados requieren que el propietario de la clave tenga acceso.",
+ "af52a6227f": "Cree una clave API personal desde Cuenta > Seguridad y acceso.",
+ "edec49dfae": "lin_api_...",
+ "7d498f653c": "Clave API personal",
+ "57a66522c8": "conectando",
+ "c9889a09f8": "Utilice Linear para elegir el espacio de trabajo deseado antes de crear la clave.",
+ "e689a4d0a6": "error"
+ }
+ }
+ },
+ "priority": {
+ "icon": {
+ "c43d3e065b": "Prioridad:"
+ }
+ },
+ "project": {
+ "view": {
+ "surfaces": {
+ "8bbecb2510": "Ninguno",
+ "e1fa97d21d": "Seleccione un proyecto para ver su descripción general.",
+ "1748d3b9af": "Etiquetas",
+ "65bda65159": "Miembros",
+ "c5f79616c3": "equipos",
+ "25a2196732": "Objetivo",
+ "3fb6473111": "Comenzar",
+ "111bef9aa8": "Dirigir",
+ "3be47aed6f": "Prioridad",
+ "f5ef24cf46": "Salud",
+ "9ddb58edbd": "Estado",
+ "0a6a5a7dd6": "Última actualización",
+ "c8db98b73b": "Recursos",
+ "bb1405eff8": "Hitos",
+ "5d99315fb8": "Planificación",
+ "3ad562bdf4": "problemas de alcance",
+ "563501f191": "Progreso",
+ "bb5664d456": "Sin descripción del proyecto.",
+ "7b147907dc": "Linear",
+ "a9785c7158": "Refrescar",
+ "ee3d2caabd": "Asuntos",
+ "5f79bc76b0": "Volver a proyectos",
+ "aac9a4afc6": "Abrir en Linear",
+ "7616c986c6": "Problemas abiertos {{value0}}",
+ "93e1f6bfca": "Cargando",
+ "98730088a6": ". Busque o abra Linear para ver el conjunto completo.",
+ "06b887d622": "Mostrando primero",
+ "2c4b1c2c08": "número",
+ "f2cc1e0ff6": "Linear / Proyectos",
+ "906b5e4cb8": "Linear / Proyectos / {{value0}}",
+ "85607ff793": "Proyecto",
+ "20b9d09b7d": "Desconocido",
+ "f059181bd9": "Privado",
+ "27d91cb1a6": "Compartido",
+ "9f0f51fd9e": "Cree o guarde vistas en Linear y luego actualice.",
+ "f4c79cff5f": "Revise el error del espacio de trabajo a continuación y luego actualice.",
+ "ef90b21366": "No se encontraron vistas",
+ "c0a50f96a4": "No se pueden cargar vistas",
+ "df4bd63c1d": "No asignado",
+ "30402d2c6e": "Intente buscar o actualizar.",
+ "a2f31c4cd6": "No se encontraron proyectos Lineares",
+ "c9b6e9f90d": "No se pueden cargar proyectos Lineares"
+ }
+ }
+ },
+ "scope": {
+ "selector": {
+ "91c8871dad": "Agregar acceso al equipo",
+ "7783361266": "Todos los equipos",
+ "e1ae6bebb0": "equipos",
+ "a14ce4df2b": "Todos los espacios de trabajo",
+ "05baa5ae90": "Espacio de trabajo",
+ "89f6580dbf": "Equipos de búsqueda...",
+ "b3488fad3c": "No se buscó ningún equipo. El acceso puede depender del alcance de la clave, la membresía de un equipo privado, los equipos archivados, los permisos o un error de recuperación.",
+ "405b33c378": "Ningún equipo encontrado coincide con su búsqueda."
+ }
+ }
+ },
+ "notification": {
+ "sound": {
+ "options": {
+ "e38b0a2e68": "Bip",
+ "0acd3d384e": "Charla",
+ "79919c832d": "Timbre",
+ "2b44847d8d": "Blop",
+ "020826ef17": "Sonar",
+ "588c90487d": "Punto luminoso en un radar",
+ "1e4b81d892": "Golpear",
+ "86af8d938c": "bong",
+ "80f7cc95b3": "dos tonos",
+ "017abebfa6": "Valor predeterminado del sistema"
+ }
+ }
+ },
+ "worktree": {
+ "creation": {
+ "WorktreeCreationPanel": {
+ "dabd226118": "Despedir",
+ "34dd5ee38b": "Rever",
+ "ed2a664f8b": "No se pudo crear el árbol de trabajo",
+ "a3346fc6ed": "Cancelar la creación del árbol de trabajo",
+ "532aea14ce": "Cancelar",
+ "767951265d": "Algo salió mal al crear el árbol de trabajo."
+ }
+ }
+ },
+ "workspace": {
+ "space": {
+ "WorkspaceSpacePage": {
+ "8d0048e1cb": "Uso del disco del espacio de trabajo y almacenamiento recuperable del árbol de trabajo.",
+ "e8d6ba11ab": "Beta",
+ "45f6302dbc": "Espacio",
+ "ecf72fdc3b": "Atrás"
+ }
+ },
+ "cleanup": {
+ "WorkspaceCleanupDialog": {
+ "3828408538": "Quitar {{value0}}",
+ "352f15d6fc": "Último activo",
+ "cbf2f664e2": "Borrar",
+ "b6bae1eed1": "Cancelar",
+ "592fbab446": "Ordenado por actividad más antigua",
+ "dba753e94f": "eliminar",
+ "38ca0b1400": "Esto elimina permanentemente sus archivos locales. No puedes deshacer esto.",
+ "c4f4782c02": "No sugerido",
+ "0a2e3c7cba": "Revisar",
+ "e97e4580c7": "Sucio",
+ "9623a5107d": "confirmaciones no enviadas",
+ "e8b3741ff7": "ignorado",
+ "a9957007eb": "Ignorar {{value0}}",
+ "1bffc07ba7": "Ver {{value0}}",
+ "bef0adef9b": "Rama",
+ "0b1766738a": "repositorio",
+ "bbb1ab6a6f": "Seleccione {{value0}}",
+ "d1094dd529": "Necesita revisión",
+ "4b93a235d8": "sugerido",
+ "f68d538c63": "No hay espacios de trabajo en este conjunto de limpieza.",
+ "4719327c9c": "Se ignoran todas las sugerencias de limpieza.",
+ "a19040cd67": "Ningún espacio de trabajo inactivo coincide con los repositorios seleccionados.",
+ "97c772c4fe": "No se encontraron espacios de trabajo inactivos en los repositorios marcados.",
+ "d3eef9463d": "No hay espacios de trabajo inactivos para eliminar.",
+ "aaee139eab": "Restaurar sugerencias ignoradas",
+ "06cf78521e": "Seleccionar todo en {{value0}}",
+ "73690b0031": "Deseleccionar todo en {{value0}}",
+ "b771c92598": "Eliminar seleccionado",
+ "37ab28277e": "no sugerido",
+ "1b18868569": "necesita revisión",
+ "b299f201b9": "seguro para eliminar",
+ "2b31bf68de": "inactivo",
+ "ac5ba84cc1": "seleccionado",
+ "8b74d4ea6e": "Escaneando árboles de trabajo y estado de git, luego combinando señales de pestaña abierta, terminal, agente en vivo y disponibilidad remota antes de sugerir eliminaciones.",
+ "7eee951968": "Comprobar la seguridad del lugar de trabajo",
+ "191f0bc98e": "Cerca",
+ "7ae2ad30f4": "Refrescar",
+ "e0b5a4deaa": "Revise los espacios de trabajo inactivos antes de eliminar sus archivos locales y el estado de Orca.",
+ "b2c1331844": "Eliminar espacios de trabajo inactivos",
+ "41d594d01e": "{{value0}} espacio de trabajo {{value1}} no se pudo eliminar",
+ "0f00612b6d": "Se eliminó {{value0}} espacio de trabajo{{value1}}",
+ "7f451a3e2c": "No se pudo ignorar la sugerencia de limpieza",
+ "662b8ec3f8": "Error en el análisis de limpieza del espacio de trabajo",
+ "bc43c37faf": "oculto",
+ "0c6672f5e3": "Sugerencias de limpieza ignoradas",
+ "fc49f79434": "mezclado",
+ "2ddbd6fe8a": "comprobado",
+ "ee81adfcef": "Vista",
+ "4d0b72481c": "Ignorar",
+ "9cc26c019d": "Eliminar"
+ }
+ }
+ },
+ "ui": {
+ "color": {
+ "picker": {
+ "ebcf6ba29e": "Color hexadecimal no válido.",
+ "faa855a582": "Maleficio",
+ "1cec618bcc": "{{value0}} selector"
+ }
+ },
+ "dialog": {
+ "f26c4baeda": "Cerca"
+ },
+ "repo": {
+ "multi": {
+ "combobox": {
+ "286ce70256": "SSH",
+ "4471d4a1c0": "Ningún proyecto coincide con su búsqueda.",
+ "bfd8ce21c6": "Todos los proyectos",
+ "a58a0cd100": "Buscar proyectos...",
+ "65a3dae41d": "Sin proyectos"
+ }
+ }
+ },
+ "sheet": {
+ "1189e9fe0a": "Cerca"
+ },
+ "team": {
+ "multi": {
+ "combobox": {
+ "de83523bf9": "Ningún equipo coincide con tu búsqueda.",
+ "301f2a796e": "Todos los equipos",
+ "18ec58881e": "Equipos de búsqueda..."
+ }
+ }
+ }
+ },
+ "terminal": {
+ "quick": {
+ "commands": {
+ "TerminalQuickCommandActionToggle": {
+ "b0d58e37ed": "Mensaje del agente",
+ "b5ea4d64f6": "Comando terminal"
+ },
+ "TerminalQuickCommandAppendEnterSwitch": {
+ "e4e5fed3b3": "Alternar agregar Ingresar",
+ "c936c2d6d2": "Envíelo inmediatamente en lugar de solo insertar texto.",
+ "5fa607d807": "Agregar Ingresar"
+ },
+ "TerminalQuickCommandDialog": {
+ "925b8e0f6e": "Avanzado",
+ "97e96cc027": "/meta",
+ "e604bd40d6": "Admite habilidades, rutas de archivos y comandos integrados como",
+ "79af0c0841": "npm ejecutar desarrollador",
+ "577a342c7d": "Pídale al agente que investigue este espacio de trabajo.",
+ "026cfb232a": "No admite comandos rápidos",
+ "346d409ab2": "Elige agente",
+ "0adba8fa0c": "Agente",
+ "ec8f081919": "Acción",
+ "ed04233b3e": "Guarde los comandos del terminal o las indicaciones del agente para un acceso rápido.",
+ "ca414324ee": "Texto de comando",
+ "dc921c17ee": "Inmediato",
+ "5b3f634a55": "Agregar comando rápido",
+ "f9b184fc16": "Editar comando rápido",
+ "6751598542": "editar"
+ },
+ "TerminalQuickCommandDialogFooter": {
+ "2e2b958dfc": "Ahorrar",
+ "8dff838dea": "Guardar ({{value0}})",
+ "28370f16b9": "Cancelar"
+ },
+ "TerminalQuickCommandLabelField": {
+ "66ea254301": "Iniciar el servidor de desarrollo",
+ "db17f1e41e": "Etiqueta"
+ },
+ "TerminalQuickCommandScopeField": {
+ "2db6edede7": "Al guardar se mantiene el alcance del proyecto existente a menos que elija otro.",
+ "2496523a6f": "Elige proyecto",
+ "2264edd5d3": "Proyecto no en la lista",
+ "3834d24243": "Proyecto",
+ "b83efc79e2": "Global",
+ "c25cf350ef": "Alcance",
+ "f0631e4999": "repositorio"
+ }
+ }
+ },
+ "pane": {
+ "CloseTerminalDialog": {
+ "ebd2fa844d": "Cerca",
+ "1d1a7a9c1f": "Cancelar",
+ "6b9a6975f8": "La terminal todavía tiene un proceso en ejecución. Si cierra la terminal, el proceso finalizará.",
+ "78b79d854d": "¿Cerrar terminal?"
+ },
+ "MobileDriverOverlay": {
+ "c6460cf584": "Devolver",
+ "c44659e09f": "conducción móvil",
+ "7cffad954c": "Colapsar",
+ "3eed73394f": "Tu teclado está en pausa",
+ "faa367dc74": "Este terminal tiene el tamaño adecuado para tu aplicación móvil"
+ },
+ "TerminalAgentSessionForkDialog": {
+ "17fc841e59": "Copiar contexto",
+ "0c8a8629b1": "La bifurcación aparece como su propio espacio de trabajo, no como un hijo anidado. El nuevo agente recibe una transcripción encuadernada como borrador editable.",
+ "620461df22": "Bifurcación de nivel superior",
+ "619b5a35d2": "Cree una bifurcación del espacio de trabajo de nivel superior e inicie una nueva pestaña de agente con contexto capturado.",
+ "64e292e8e3": "Sesión de agente de bifurcación",
+ "9d25de2920": "crear bifurcación",
+ "2b10412cfc": "Creando..."
+ },
+ "TerminalContextMenu": {
+ "b4cdd9314e": "Borrar pantalla",
+ "8c17d6786d": "Cerrar panel",
+ "2cf85a6a55": "Copiar ID del panel",
+ "39809d152f": "Establecer título…",
+ "06c2b0f043": "Igualar tamaños de paneles",
+ "98bccf4fa2": "Terminal dividido hacia abajo",
+ "20e565d865": "Terminal dividido a la derecha",
+ "8a7ddb8b8a": "Sesión de agente de bifurcación...",
+ "0a82b0608c": "Agregar comando rápido…",
+ "9528a65ef8": "Sin comandos rápidos",
+ "3ce594a4a0": "Global",
+ "ec85df5914": "Comandos rápidos",
+ "0a917b591a": "Pasta",
+ "f3eeb1de13": "Copiar",
+ "c2f0b72b8d": "Insertar",
+ "925f49f210": "Expandir panel",
+ "df766809e0": "Contraer panel"
+ },
+ "TerminalErrorToast": {
+ "e4aa243f8c": "Reiniciar demonio",
+ "a7e2fd2699": "presentar un problema",
+ "5c8ce20be6": "Si esto persiste por favor",
+ "cc6d997c65": "Reinicie el demonio del terminal desde aquí para borrar el estado obsoleto del demonio."
+ },
+ "TerminalPane": {
+ "ac112e9036": "Quitar título",
+ "f984ab2a30": "Eliminar título del panel: {{value0}}",
+ "cc5a2dc706": "Editar título del panel: {{value0}}",
+ "7dbbfcbecc": "Título del panel"
+ },
+ "TerminalSessionStateSaveFailureDialog": {
+ "6bee0c8f17": "Analizador de espacio en disco abierto",
+ "ae20d0ffc2": "Despedir",
+ "38c282a2c4": "El analizador se abre directamente desde aquí. También puede abrirlo más tarde desde el menú de la caja de herramientas inferior izquierda eligiendo Space Analyzer.",
+ "e2fcf07c0d": "Orca no pudo guardar esta sesión de terminal porque el almacenamiento local está lleno o no se puede escribir. Abra el analizador de espacio en disco para encontrar espacio de almacenamiento que pueda limpiar.",
+ "678c780a2c": "El espacio en disco no está disponible"
+ },
+ "osc52": {
+ "clipboard": {
+ "blocked": {
+ "toast": {
+ "97c98f1afe": "Abrir configuración",
+ "7cf51f74fd": "Habilite las escrituras en el portapapeles TUI en la configuración de Terminal para copiar desde SSH, tmux, Neovim o fzf.",
+ "89eaa3e80b": "Escritura en el portapapeles del terminal bloqueada"
+ }
+ }
+ }
+ },
+ "stale": {
+ "agent": {
+ "row": {
+ "ad991ece5c": "El panel del agente ya no está disponible.",
+ "090d607412": "fila-agente-obsoleto-{{value0}}"
+ }
+ }
+ },
+ "terminal": {
+ "agent": {
+ "session": {
+ "fork": {
+ "2317900211": "No se pudo copiar el contexto de la bifurcación.",
+ "88e34d00eb": "Bifurcación de sesión de nivel superior abierta en un nuevo espacio de trabajo",
+ "fd3d12a1e1": "No se pudo crear el espacio de trabajo de bifurcación.",
+ "38e41edc6e": "Este espacio de trabajo no se puede bifurcar en un árbol de trabajo de git.",
+ "f867385bb5": "No se pudo encontrar el espacio de trabajo de origen para esta bifurcación.",
+ "046e8d853c": "No hay contexto de terminal para bifurcar",
+ "c00421d320": "Se copió el contexto de la bifurcación. Inicie un agente y péguelo para iniciar la bifurcación."
+ }
+ }
+ },
+ "drop": {
+ "handler": {
+ "1e072f611e": "No se pudo cargar {{value0}} {{value1}}.",
+ "53f015fd85": "Se omitió el enlace simbólico {{value0}}{{value1}}.",
+ "29c031b49a": "Subiendo el archivo {{value0}}{{value1}} al tiempo de ejecución...",
+ "0c77693641": "Worktree no está listo; inténtalo de nuevo en un momento.",
+ "ce8248b835": "Ruta del árbol de trabajo no disponible."
+ }
+ }
+ },
+ "use": {
+ "terminal": {
+ "pane": {
+ "context": {
+ "menu": {
+ "a29b9faa01": "ID del panel copiado"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tab": {
+ "group": {
+ "TabGroupPanel": {
+ "814fb04c43": "Cargando editor...",
+ "f7d6ce445e": "Cerrar grupo",
+ "0db2081805": "Partir",
+ "30137df7d0": "Dividir a la izquierda",
+ "4df2a06d36": "Dividir hacia abajo",
+ "ab1e2bff04": "Dividir a la derecha",
+ "9acaf92093": "Acciones del panel",
+ "1bce81dba6": "simulador",
+ "1ff1c77616": "navegador",
+ "586d2ac445": "Terminal"
+ }
+ },
+ "bar": {
+ "BrowserTab": {
+ "6e0bc8f3a8": "Abrir en el navegador",
+ "9dd880bd56": "Cerrar pestañas a la derecha",
+ "1611a1324b": "Cerca",
+ "5d6e89891f": "Duplicar pestaña",
+ "966feb9ad5": "Dividir a la derecha",
+ "7e8106899f": "Dividir a la izquierda",
+ "2186a8407c": "Dividir hacia abajo",
+ "96354ed249": "Partir",
+ "911542656f": "Pestaña Fijar",
+ "c5aaee8c39": "Desanclar pestaña"
+ },
+ "EditorFileTab": {
+ "3da7445c84": "Cambiar el nombre del archivo {{value0}}"
+ },
+ "EditorFileTabContextMenu": {
+ "52ce4f4605": "Copiar ruta relativa",
+ "5b85754786": "Copiar ruta",
+ "bfd5797ef4": "Abrir vista previa de rebajas",
+ "e5ff31ccaf": "Cerrar pestañas a la derecha",
+ "ba1369dd24": "Cerrar todas las pestañas del editor",
+ "1ba8492c5b": "Cerca",
+ "68cc610e7f": "Rebautizar",
+ "f7c3d7d5af": "Dividir a la derecha",
+ "e3ff145b98": "Dividir a la izquierda",
+ "1d04b1630b": "Dividir hacia abajo",
+ "6b3efb106e": "Partir",
+ "fdd29eb669": "Pestaña Fijar",
+ "8e9d603a09": "Desanclar pestaña"
+ },
+ "QuickLaunchButton": {
+ "348a04c1ad": "Configuración del agente...",
+ "ec2adf093e": "Inicie {{value0}} en una nueva terminal",
+ "465e432ef1": "No se pudo generar el comando de inicio para {{value0}}.",
+ "e518f544b1": "No se detectaron agentes",
+ "8dea9b5cdf": "No hay agentes habilitados"
+ },
+ "RecentTabSwitcher": {
+ "329638ff6f": "Cambiar pestaña",
+ "07ad4cd0b7": "Cambiar pestañas"
+ },
+ "SortableTab": {
+ "ab19f603eb": "Cambiar nombre de pestaña {{value0}}",
+ "6df69d9388": "Cerrar pestaña {{value0}}",
+ "fdb2691425": "Contraer panel"
+ },
+ "SortableTabContextMenu": {
+ "35e8892fd0": "Color de pestaña",
+ "2f697b3c31": "Cambiar título",
+ "c1ee099c7e": "Cerrar pestañas a la derecha",
+ "8d16f9cd30": "Cerrar Otros",
+ "89359a36f7": "Cerca",
+ "21132389e9": "Dividir a la derecha",
+ "0ce4bae39d": "Dividir a la izquierda",
+ "af80ed83c1": "Dividir hacia abajo",
+ "591f9b12c1": "Partir",
+ "7703990447": "Gris",
+ "845576bed1": "verde azulado",
+ "be905e9b0a": "Verde",
+ "69682e2ce4": "Amarillo",
+ "a47629b3cf": "Naranja",
+ "620aec6729": "Rojo",
+ "03cf6dab1a": "Rosa",
+ "c2d8b0991f": "Púrpura",
+ "cb3eadefd2": "Azul",
+ "20baa43c05": "Ninguno",
+ "60f958ec75": "Pestaña Fijar",
+ "417722e9c2": "Desanclar pestaña"
+ },
+ "TabBar": {
+ "b1a132357f": "Nueva pestaña",
+ "4f327c8b3d": "Abrir rebajas...",
+ "3d5d6c960d": "Nueva rebaja",
+ "fd2b42aaa3": "Nuevo emulador móvil",
+ "aea43b5748": "Abra la pestaña del emulador existente.",
+ "b426bb2615": "Ir al emulador móvil",
+ "4833fb2cbe": "Nueva pestaña del navegador",
+ "d364f3c8d4": "Nueva Terminal",
+ "7c1313d237": "Nueva terminal:",
+ "d1afac112b": "WSL",
+ "efb33546ff": "Git bash",
+ "1a8af49530": "Mensaje CMD",
+ "2148f65e04": "PowerShell",
+ "ab589350e5": "No se pudo generar el comando de inicio para {{value0}}."
+ },
+ "TabBarCreateEntry": {
+ "d62d63b807": "crear archivo",
+ "25dc1cd653": "Abrir archivo",
+ "7cdf8ee0c8": "Abrir URL",
+ "b27864279e": "Agente de lanzamiento",
+ "39676a184c": "Abra cualquier archivo, URL, agente, ..."
+ },
+ "TabBarQuickCommandsButton": {
+ "a2c7a33831": "Agregar comando",
+ "20bbd75896": "Sin comandos",
+ "b82e237a4b": "Comandos más rápidos",
+ "85482c57bc": "Ejecutar comando rápido",
+ "b775303755": "Ejecutar comando rápido: {{value0}}",
+ "196593b6a9": "Quitar {{value0}}",
+ "15529ede69": "Editar {{value0}}",
+ "1d411fb6a5": "Guarde un comando rápido para este repositorio",
+ "8f1e971966": "Agregar comando rápido",
+ "3220e2da27": "Este comando rápido se eliminará de su lista guardada.",
+ "e8e1a52edb": "¿Eliminar \"{{value0}}\"?",
+ "37e1bb90ce": "Ejecutar: {{value0}}",
+ "77ac113df0": "Inicio {{value0}}: {{value1}}",
+ "7b1c9d6ae1": "Correr",
+ "c781f992e4": "destructivo",
+ "be8f0ff166": "Borrar"
+ },
+ "shell": {
+ "icons": {
+ "d4ceaa227c": "git",
+ "e9b2e70613": "WSL"
+ }
+ },
+ "tab": {
+ "create": {
+ "entry": {
+ "classifier": {
+ "42e6262ae9": "No hay acción disponible.",
+ "097a982ee0": "Cargando archivos...",
+ "5a9c83c04b": "Abra cualquier archivo, URL, agente, ...",
+ "90eb94dc48": "Introduzca una URL http:// o https://.",
+ "5553b283ce": "Ingrese una URL o ruta de archivo."
+ }
+ },
+ "menu": {
+ "options": {
+ "5501c2fb7a": "Terminal",
+ "9630dd5494": "caparazón",
+ "a094576900": "nueva terminal",
+ "4f23f4d01d": "nuevo caparazón",
+ "4f2a91e15b": "navegador",
+ "6d0e6a4b7a": "nuevo navegador",
+ "c87ad57785": "pestaña del navegador",
+ "cce7ef1d2c": "web",
+ "5f17fb9d0c": "reducción",
+ "44caaf7b36": "Maryland",
+ "fb50e3d874": "nueva rebaja",
+ "6d8b6b4117": "nuevo archivo",
+ "b330f72434": "marca",
+ "37ff3ddca1": "rebaja abierta",
+ "164c394bab": "abrir archivo",
+ "bbaf4f85a4": "emulador móvil",
+ "3784b83bd4": "emulador",
+ "a63847a742": "simulador",
+ "1baeb07c17": "simulador de ios",
+ "8a580f88cf": "iPhone",
+ "7ecdc5ef08": "iPad",
+ "14965cc123": "móvil"
+ }
+ }
+ }
+ }
+ }
+ },
+ "status": {
+ "bar": {
+ "PetStatusSegment": {
+ "3668339495": "Quitar {{value0}}",
+ "cd8c6c654c": "Configuración de mascotas…",
+ "ed176ad68f": "Importar paquete .codex-pet…",
+ "59b5955621": "Sube el tuyo…",
+ "0608ad02a2": "Elige mascota",
+ "b75484a01a": "Tamaño de mascota",
+ "c6aa805b1b": "píxeles",
+ "2f7bbaa457": "Tamaño",
+ "34c25dfe9c": "Mascota",
+ "aec479308a": "Menú de mascotas",
+ "cef0ab4636": "No se pudo importar el paquete de mascotas",
+ "2021d4f6db": "La importación de paquetes de mascotas necesita reiniciar completamente la aplicación (no solo recargarla).",
+ "f395c9a685": "No se pudo importar el archivo",
+ "e6234bcc17": "La carga de mascotas personalizada necesita reiniciar la aplicación por completo (no solo recargarla).",
+ "6d0a8cd179": "mostrar mascota",
+ "1fbc51cc77": "Ocultar mascota"
+ },
+ "PortsStatusSegment": {
+ "4ebf90c12e": "No se detectaron puertos externos",
+ "7dac3ecc9d": "Puertos externos",
+ "95495019ed": "Escaneo de puertos no disponible en {{value0}}: {{value1}}",
+ "a8e4bdb412": "· {{value0}} externo",
+ "9aa11005bf": "espacio de trabajo ·",
+ "c22ea609fd": "Puertos",
+ "a11ed266ce": "espacio de trabajo",
+ "ca41be2802": "Puertos: {{value0}} espacio de trabajo {{value1}}{{value2}}",
+ "b8bc3e420a": "Puertos, {{value0}} espacio de trabajo {{value1}}",
+ "3a87d54dfb": "No se detectaron puertos del espacio de trabajo",
+ "c174bbbfed": "Buscando puertos del espacio de trabajo...",
+ "8caaa86e9a": "puertos",
+ "45834a9ace": "puerto",
+ "4ae65d871a": "externo",
+ "2b84c4d11f": "{{value0}} espacio de trabajo · {{value1}} externo"
+ },
+ "ResourceUsageStatusSegment": {
+ "946d9f94d0": "Cancelar",
+ "67c4ecda49": "Forzar el cierre de esta terminal. Cualquier trabajo no guardado en el panel se perderá. Esto no se puede deshacer.",
+ "4bb076fa89": "Matar",
+ "996295bff2": "terminal huérfana",
+ "92924a14e3": "Revisar espacios de trabajo inactivos ({{value0}})",
+ "27a74f91f0": "Nada funcionando ahora mismo",
+ "1b24a32d3a": "Memoria",
+ "298f4be7f2": "UPC",
+ "2aa2de6cb9": "Nombre",
+ "30ff2c3c31": "{{value0}} huérfano",
+ "6449a95c78": "En qué cantidad de RAM física de esta máquina se encuentran los procesos rastreados por Orca.",
+ "e7ccce7e87": "de RAM del sistema",
+ "9e2525c89f": "Memoria residente en poder de Orca más los procesos bajo las terminales de cada árbol de trabajo.",
+ "1fedf94eae": "Carga de CPU combinada. Los valores superiores al 100% significan que más de un núcleo está funcionando a la vez.",
+ "e7cf14ec78": "Sesiones de terminal no disponibles. La lista puede estar obsoleta.",
+ "93b0de3c21": "Reanudar",
+ "f85af9cda6": "Las instantáneas de recursos y las sesiones de terminal no están disponibles.",
+ "f8e0d794b4": "Daemon no responde",
+ "bd19fd7a59": "Matar todas las sesiones",
+ "c9382662bb": "Reiniciar demonio",
+ "59f178fe11": "{{value0}}, demonio inalcanzable",
+ "21cacb16d1": "· remoto",
+ "73a3fd68a9": "Contraer repositorio",
+ "b12e31dfcb": "Expandir repositorio",
+ "d659d71d2d": "Reanudar el espacio de trabajo {{value0}}",
+ "bbcd9b7b85": "Contraer espacio de trabajo",
+ "c4a8968bdd": "Ampliar el espacio de trabajo",
+ "b10695d6ce": "Matar sesión",
+ "288a4dd177": "Orca",
+ "53dd5560ae": "Colapso Orca",
+ "e419d27083": "Expandir Orca",
+ "41ae4fa725": "Asesinato…",
+ "138b99bd80": "esta sesión",
+ "888dad8c55": "Cargando…",
+ "56b6888304": "Uso de recursos locales oculto para servidores de ejecución.",
+ "14ff448686": "No disponible para servidores de ejecución",
+ "6d9793d4bc": "Administrador de recursos - Terminales",
+ "6a822b06a7": "Administrador de recursos",
+ "ca95d077db": "demonio inalcanzable",
+ "a82253b458": "Eliminar espacio de trabajo.",
+ "946724a70a": "El espacio de trabajo principal no se puede eliminar.",
+ "16bc3c998a": "Eliminar espacio de trabajo {{value0}}",
+ "0f9e50eb07": "Otro",
+ "d406915b78": "renderizador",
+ "81cd37af99": "Principal",
+ "fa6d36758d": "Matar sesión {{value0}}",
+ "b8f4a2c1d0e3": "{{value0}} huérfanos",
+ "c7e3b1a0d9f2": "Mata la terminal huérfana {{value0}}",
+ "d8f4c2b1e0a3": "Mata terminales huérfanas {{value0}}",
+ "e9a5d3c2b1f0": "¿Matar a {{value0}}?"
+ },
+ "SshStatusSegment": {
+ "3ad70e0365": "Administrar SSH…",
+ "6e8a9a4242": "Conexiones SSH",
+ "d09ec41831": "SSH",
+ "fdc57e9970": "Estado de la conexión SSH",
+ "59b553e2aa": "Desconectar",
+ "63f36455cc": "Conectar",
+ "bf07aee59e": "Falló la desconexión",
+ "2c29e2de68": "La conexión falló",
+ "bc5a3fd41a": "parcial",
+ "3d0128b105": "conectado",
+ "fd9a3c600e": "error",
+ "fbb3f9f05e": "conflicto",
+ "95e4ff5b4b": "emprendedor",
+ "63a2b965f6": "tracción"
+ },
+ "StatusBar": {
+ "9659e38343": "Puertos",
+ "d1e1a7a6bf": "Administrador de recursos",
+ "24ac89df1a": "Estado SSH",
+ "5e59007df4": "Uso de Kimi",
+ "8c86cd77b0": "Uso de OpenCode Go",
+ "c1df0d67ec": "Uso de Gemini",
+ "c0909c686e": "Uso del Codex",
+ "3885eb74d8": "Uso de Claude",
+ "c8857b40f7": "Actualizar datos de uso",
+ "75ded02687": "Administrar cuentas…",
+ "ff0fbe9311": "Activo",
+ "7657e3db9c": "Cuenta del Codex",
+ "38b5647724": "Tiempo de ejecución de uso del Codex",
+ "ba55303942": "Abrir detalles del Codex y cambiar de cuenta",
+ "4dff061aab": "·",
+ "2483c60695": "···",
+ "c35af53b73": "Iniciar sesión",
+ "f19a63e7cd": "Inicia sesión para ver el uso",
+ "5c938d39ac": "% semana",
+ "d79c3362c4": "% 5h",
+ "8295903d17": "Reinicie los terminales Claude en vivo antes de continuar conversaciones antiguas después de cambiar.",
+ "c98ea88392": "Ninguna otra cuenta",
+ "9332ba8684": "Cambiar a",
+ "d450654fa2": "cuenta Claude",
+ "11e2354daf": "Tiempo de ejecución de uso de Claude",
+ "3dd7ddfae1": "Abrir detalles de Claude y cambiar de cuenta",
+ "59c6e7b4e0": "Las sesiones visibles se reinician ahora. Otros reinician cuando su árbol de trabajo se activa.",
+ "c676918adc": "Valor predeterminado del sistema",
+ "3325d996cb": "Límites de frecuencia de actualización",
+ "fda8146810": "Abrir detalles de uso de Kimi",
+ "629251f4b6": "Abrir detalles de uso de OpenCode Go",
+ "d2375976eb": "Abrir detalles de uso de Gemini",
+ "3d79122c3f": "kimi",
+ "d7a0668acc": "código abierto-ir",
+ "68efc0345c": "gemini",
+ "76b06d4da5": "claude",
+ "a28a5dd9b1": "error",
+ "cd9d7b40ff": "Reiniciar {{value0}} sesiones",
+ "6cd6650b4c": "Reiniciar sesión",
+ "1446d0d8a0": "{{value0}} Las sesiones del Codex todavía están en la cuenta anterior.",
+ "605901a495": "1 sesión del Codex todavía está en la cuenta anterior"
+ },
+ "StatusBarUsageEmptyCta": {
+ "828c764a79": "Conectar una cuenta",
+ "caa0f39811": "Soporta:",
+ "97957ad3a3": "Conecte las cuentas de su proveedor de IA para ver su uso en tiempo real y cambiar fácilmente entre cuentas.",
+ "9a542f46c7": "Ocultar de la barra de estado",
+ "84c3b15dca": "Límites de uso del agente",
+ "d663430cf9": "Conecte una cuenta de IA para ver el uso"
+ },
+ "UpdateStatusSegment": {
+ "5cd13105a3": "La actualización falló. Haga clic para ampliar.",
+ "2201df6987": "Error en la actualización: haga clic para ver los detalles",
+ "8533c12c3c": "La actualización falló",
+ "962404f68e": "Actualización lista para instalar. Haga clic para ampliar.",
+ "248ee5d8ef": "Orca v{{value0}} descargando… {{value1}}%",
+ "57a29c3b0e": "Actualización lista",
+ "fd1d3b3a1d": "Descarga de actualizaciones, {{value0}} por ciento. Haga clic para ampliar.",
+ "9d13213a56": "Orca v{{value0}} lista para instalar"
+ },
+ "WorkspaceSpaceCompactPanel": {
+ "a471aa9c24": "Actualizado",
+ "9be86c46a0": "Liberable",
+ "f4d2651498": "escaneado",
+ "6a5dc3c61a": "Revisar",
+ "c361440dc0": "Beta",
+ "8ff597593d": "Espacio",
+ "0582df6d2e": "Escanear",
+ "f5e1a84d79": "Refrescar",
+ "2af2174d6d": "Cancelar",
+ "5691353a21": "Parada",
+ "2837dc7c72": "cancelado",
+ "0583c806ac": "El uso del disco del espacio de trabajo no se analiza.",
+ "39786e3b73": "Escaneo de tamaños de espacios de trabajo.",
+ "bef4dc0457": "{{value0}} recuperable · {{value1}} no disponible",
+ "3d8d47ce77": "{{value0}} · último resultado mantenido"
+ },
+ "WorkspaceSpaceManagerPanel": {
+ "2965415393": "Error al forzar la eliminación",
+ "e031e93219": "No hay espacios de trabajo coincidentes.",
+ "a02d84d2d2": "Escaneo de espacios de trabajo. Puedes salir de esta página.",
+ "be37293b10": "Estado",
+ "33aef3e9cc": "Tamaño",
+ "81f14d9924": "Repositorio",
+ "e4aebea158": "Espacio de trabajo",
+ "1d0f8300d1": "Seleccionar espacios de trabajo visibles y eliminables",
+ "697d60c456": "Borrar selección visible",
+ "81aaf1de65": "Mostrar solo espacios de trabajo eliminables",
+ "d7ac56452e": "Actividad",
+ "243287ac60": "Nombre",
+ "6f8f6a6b04": "Filtrar espacios de trabajo",
+ "5caccea440": "Eliminar seleccionado",
+ "e4a12c455b": "Claro",
+ "0cb1501ccf": "reclamable",
+ "65402b7192": "seleccionado",
+ "43171f3e60": "Espacios de trabajo",
+ "83f1a0a932": "Reclamable",
+ "09960d86bd": "escaneado",
+ "1cc6cd4c0f": "espacios de trabajo",
+ "02b27c2230": "espacio de trabajo",
+ "63efebe0e6": "{{value0}} {{value1}} eliminado del espacio.",
+ "eee5240810": "Espacios de trabajo eliminados",
+ "9afc97f9a3": "Espacio de trabajo eliminado",
+ "792a214457": "Eliminar espacio de trabajo",
+ "a998501630": "Fuerza",
+ "9155381019": "Escaso",
+ "f39d291997": "Seleccionar",
+ "16988df079": "No se encontraron archivos.",
+ "b25c2c1086": "elementos de nivel superior",
+ "d3f9c69ddc": "Zoom",
+ "ef890d31b9": "Todo",
+ "c28643d3da": "Ir al espacio de trabajo",
+ "66870929fb": "Asunto",
+ "fb2069acb7": "Revisar",
+ "b9b4a3a25d": "Rama",
+ "c432278ec7": "Búfers del editor",
+ "0bc756efaf": "cambios de git",
+ "e9528a89b3": "Terminales",
+ "a8d9e0de79": "Agentes",
+ "d384a4ce9f": "Eliminar decisión",
+ "7d7745bb8f": "puede eliminar",
+ "720870a18e": "Mantener: vinculado",
+ "cbc343a7a8": "Mantener: en uso",
+ "2055bc6a5a": "Mantener: ediciones no guardadas",
+ "ec7b076a75": "Mantener: git no marcado",
+ "7ab8d7e2d7": "Mantener: archivos modificados",
+ "7f7895514e": "Mantener: activo",
+ "2b501ee391": "Mantener: principal",
+ "39801484e0": "Fallido",
+ "33653dbac2": "Eliminando",
+ "52b629eb84": "Actualizado",
+ "e91dd2a9ae": "Ejecute un escaneo para inspeccionar los tamaños del espacio de trabajo.",
+ "61e25239da": "No hubo filas del espacio de trabajo disponibles en el escaneo.",
+ "8194a4fb29": "El escaneo falló antes de que se recopilaran los tamaños del espacio de trabajo.",
+ "b2f82ed5ae": "Eliminable",
+ "20a4204dce": "Los últimos resultados exitosos siguen siendo visibles.",
+ "8c7c57fbf8": "Escanear",
+ "508673bac0": "Refrescar",
+ "8dc9ddac8a": "Cancelar",
+ "1fce91d1b9": "Parada",
+ "d254f04097": "cancelado",
+ "265d956765": "{{value0}}. Puedes salir de esta página.",
+ "d595295d7d": "{{value0}} se puede recuperar de árboles de trabajo vinculados.",
+ "34174bd83d": "{{value0}}. Puedes salir de esta página; el último resultado permanece visible.",
+ "433bb7f595": "OK",
+ "0ba046fbc5": "El escaneo falló.",
+ "5c6d25720c": "Seleccione un espacio de trabajo para inspeccionar.",
+ "c5135e7e4a": "Escaneo de tamaños de espacios de trabajo. Puedes salir de esta página.",
+ "0990a63160": "Aún no hay tamaños de espacio de trabajo escaneados.",
+ "977bdf9a36": "No hay elementos de nivel superior para mostrar.",
+ "131662ac65": "{{value0}} abierto",
+ "0d1c78d749": "Seleccione {{value0}}"
+ },
+ "ports": {
+ "status": {
+ "popover": {
+ "rows": {
+ "a49ea79246": "Ir al árbol de trabajo",
+ "f2b813345f": "Espacio de trabajo no disponible",
+ "0e72c8d9fb": "Detener proceso",
+ "536d48a5dc": "Copiar {{value0}}",
+ "085f4f0334": "Abrir en el navegador",
+ "e4a709548c": "No se pudieron actualizar los puertos",
+ "acdb6df590": "Proceso detenido el {{value0}}",
+ "480d8f2347": "Copiado {{value0}}",
+ "b854ec9ff5": "No se pudo abrir el navegador"
+ }
+ }
+ }
+ },
+ "tooltip": {
+ "cedb7b99e3": "% izquierda",
+ "6d6df77f41": "No hay datos disponibles",
+ "7f7f208060": "Mensual",
+ "252c096536": "Semanalmente",
+ "94038ad2fa": "Sesión",
+ "2c35eca8d4": "No se puede recuperar el uso",
+ "1292d4f2ee": "Indisponible",
+ "7567cd1c6b": "Uso no disponible",
+ "a9a318b7a3": "Error al actualizar: se muestran datos almacenados en caché"
+ }
+ }
+ },
+ "stats": {
+ "ClaudeUsageDailyChart": {
+ "2a6360c7cb": "escritura en caché",
+ "61c58f8976": "lectura de caché",
+ "7d2efeff5e": "Producción",
+ "d7fb787e6b": "Aporte",
+ "a7902d3c1d": "fichas",
+ "059945f71d": "Totales de entrada, salida, lectura de caché y escritura de caché por día.",
+ "c9f7cd30e9": "Uso diario"
+ },
+ "ClaudeUsagePane": {
+ "21ea00bfa8": "Cache",
+ "a8b7487ff7": "Producción",
+ "faf3444859": "Aporte",
+ "0f03975d59": "vueltas",
+ "1afc25eb06": "Modelo",
+ "c17bed0416": "Proyecto",
+ "01476891c7": "Último activo",
+ "abfc4a4943": "Tasa de reutilización de caché:",
+ "7e76c84153": "Sesiones recientes",
+ "32176e1d44": "vueltas",
+ "02a046792e": "sesiones •",
+ "f97435845c": "Proyecto principal:",
+ "7dc9e5613b": "Por proyecto",
+ "c3fdbc5474": "Modelo superior:",
+ "0f394c24e3": "Por modelo",
+ "51ae85fa00": "La tasa de reutilización de caché se calcula como tokens de lectura de caché / (tokens de entrada + tokens de lectura de caché).",
+ "b26d4ddb58": "Est. Costo equivalente a API",
+ "0f3e696ca9": "Sesiones / Turnos",
+ "8cc23be4a3": "Turnos de lectura de caché cero",
+ "1634c4f404": "Tasa de reutilización de caché",
+ "b786fb4a70": "escritura en caché",
+ "268cf0af51": "lectura de caché",
+ "2b8a2f14aa": "Fichas de salida",
+ "ea71fae8fc": "Fichas de entrada",
+ "7dde9331fd": "Aún no se ha encontrado ningún uso local de Claude para este ámbito.",
+ "424cd50412": "Habilitar análisis de uso de Claude",
+ "8d18bbb771": "Refrescar",
+ "c5b9b344d0": "Actualizar el uso de Claude",
+ "505be9aac4": "Rango",
+ "f61cffb9c8": "Alcance",
+ "dd29209b21": "Filtros",
+ "e9bf9fce0e": "Opciones de uso de Claude",
+ "6afacbee37": "Seguimiento de uso de Claude",
+ "0cb1a36d7d": "Lee los registros de uso locales de Claude para mostrar estadísticas de token, modelo y sesión.",
+ "5ce4842c2c": "Todo el uso local de Claude",
+ "4f8368c272": "Solo árboles de trabajo Orca",
+ "cfe2282ffa": "Desconocido",
+ "7765a4c3e1": "n / A",
+ "2d41fd45c6": "• Error del último análisis: {{value0}}"
+ },
+ "CodexUsageDailyChart": {
+ "1e6f62d7e3": "Razonamiento",
+ "c646e1783c": "Entrada en caché",
+ "7b596a88b2": "Producción",
+ "99a91d3143": "Aporte",
+ "e4bdcf0071": "fichas",
+ "c756cda6a8": "Totales de entrada, entrada en caché, salida y razonamiento por día.",
+ "609aa96e8b": "Uso diario"
+ },
+ "CodexUsagePane": {
+ "e0b988599d": "Total",
+ "bbd20344b8": "Producción",
+ "3acc582214": "Aporte",
+ "bd0822ca47": "Eventos",
+ "c2478bcc3c": "Modelo",
+ "1a65900aea": "Proyecto",
+ "0c36b100be": "Último activo",
+ "0bd8655475": "Sesiones locales más recientes del Codex en este ámbito.",
+ "0cb0983c07": "Sesiones recientes",
+ "79a69522a5": "eventos",
+ "bf1bf2f674": "sesiones •",
+ "829ee743f2": "Proyecto principal:",
+ "b98718aaab": "Por proyecto",
+ "95d2d89285": "Modelo superior:",
+ "5a0d1d69cd": "Por modelo",
+ "94ac1f1ee7": "Los tokens de razonamiento se muestran para mayor visibilidad, pero el costo se calcula a partir de entradas no almacenadas en caché, entradas almacenadas en caché y salidas únicamente.",
+ "1a18fbd56b": "Est. Costo equivalente a API",
+ "907b31865f": "Sesiones / Eventos",
+ "6e18146e9b": "Salida de razonamiento",
+ "a9ac0f423a": "Entrada en caché",
+ "5d8eba87bd": "Fichas de salida",
+ "e365eaa6fd": "Fichas de entrada",
+ "4c865393b4": "Aún no se ha encontrado ningún uso del Codex local para este ámbito.",
+ "f7c1affbd5": "Habilitar análisis de uso del Codex",
+ "3022cda443": "Refrescar",
+ "ec4d270e2c": "Actualizar el uso del Codex",
+ "89162e019b": "Rango",
+ "6d68e8399a": "Alcance",
+ "1af1a39b2f": "Filtros",
+ "70b5b8581f": "Opciones de uso del Codex",
+ "408210470c": "Seguimiento del uso del Codex",
+ "13badcd8f2": "Lee los registros de uso del Codex local para mostrar estadísticas de token, modelo y sesión.",
+ "4fe8820098": "Todo el uso del Codex local",
+ "201766b754": "Solo árboles de trabajo Orca",
+ "bf6cf2d4dd": "Desconocido",
+ "ae255c3dba": "n / A",
+ "247c93ca92": "• precios inferidos",
+ "8a6655f7a2": "• Error del último análisis: {{value0}}"
+ },
+ "OpenCodeUsagePane": {
+ "349f7c3f5c": "Total",
+ "dfc4513657": "Producción",
+ "0f2f266c9d": "Aporte",
+ "d416f5cf92": "Eventos",
+ "08c78441b7": "Modelo",
+ "a4738de041": "Proyecto",
+ "d97bdf6e27": "Último activo",
+ "81817a641a": "Sesiones locales de OpenCode más recientes en este ámbito.",
+ "4799177b1c": "Sesiones recientes",
+ "1e5d410df0": "eventos",
+ "bc0cb89901": "sesiones •",
+ "048ffe4d65": "Proyecto principal:",
+ "0f0a1684bb": "Por proyecto",
+ "a15206a63a": "Modelo superior:",
+ "040c044d39": "Por modelo",
+ "e5bb23d85e": "El costo proviene de la base de datos local OpenCode cuando el mensaje del asistente registró uno.",
+ "15c34d4b08": "Costo registrado",
+ "7e9433469a": "Sesiones / Eventos",
+ "5a65d68b77": "Salida de razonamiento",
+ "603504ee3b": "Entrada en caché",
+ "7aa4d8ce35": "Fichas de salida",
+ "d637a892ed": "Fichas de entrada",
+ "bb6363e08c": "Aún no se ha encontrado ningún uso de OpenCode local para este ámbito.",
+ "f04131b3be": "Habilitar análisis de uso de OpenCode",
+ "603cd138dc": "Refrescar",
+ "bed558df0b": "Actualizar el uso de OpenCode",
+ "b5ed5c9fd0": "Rango",
+ "40d283c837": "Alcance",
+ "01583b30aa": "Filtros",
+ "230d6de108": "Opciones de uso de OpenCode",
+ "bea80ceae0": "Seguimiento del uso de OpenCode",
+ "b8b3522436": "Lee registros de uso de OpenCode locales para mostrar estadísticas de token, modelo y sesión.",
+ "144a6050e9": "Todo el uso local de OpenCode",
+ "e04c58327c": "Solo árboles de trabajo Orca",
+ "362231082f": "Desconocido",
+ "8095a63426": "n / A",
+ "6cc7782458": "• Error del último análisis: {{value0}}"
+ },
+ "ShareUsageButton": {
+ "7d6b25323d": "Compartir en X",
+ "b295c1c75d": "Copiar imagen",
+ "bd82c76a70": "copiado",
+ "bce08eccb9": "Compartir uso",
+ "cecefa7c32": "Compartir"
+ },
+ "ShareUsageCard": {
+ "4a4c6c79a3": "sesiones ·",
+ "66c83284cf": "Fichas diarias",
+ "b760c0b622": "modelo superior",
+ "2d9eb39264": "fichas totales",
+ "beb6f24f37": "Est. costo",
+ "da62578d9d": "Uso",
+ "0eb31e79ee": "IDE de Orca",
+ "960324e9b8": "eventos",
+ "6adac63cfe": "vueltas"
+ },
+ "StatsPane": {
+ "42d3e0bdf7": "Proveedor de análisis de uso: {{value0}}",
+ "c79f073d4c": "Análisis de uso",
+ "a58aba506f": "RP creados",
+ "1c96f433e2": "Tiempo que trabajaron los agentes",
+ "9dbec9e675": "Agentes generados",
+ "73ed07859c": "Inicie su primer agente para comenzar a rastrear",
+ "1e696db2f6": "OpenCode",
+ "7d26110cea": "Codex",
+ "85457c02fe": "Claude",
+ "b2cf4310ce": "Descripción general",
+ "908c470587": "codex",
+ "eb6a066185": "claude",
+ "eee19cfade": "descripción general"
+ },
+ "UsageOverviewPane": {
+ "22ed1b7669": "sesiones",
+ "444585cb41": "con datos",
+ "ecb0cd8a4c": "activado -",
+ "33f7b043d2": "Proveedores",
+ "60002bb22f": "Aún no se ha encontrado ningún uso local de Claude, Codex u OpenCode. La descripción general se completará después de que la siguiente sesión del agente escriba registros de tokens.",
+ "70f36452d4": "compartir caché",
+ "327603fe8b": "Días activos",
+ "0eaf937335": "Est. costo",
+ "3887b94ce5": "fichas totales",
+ "2d13e57f72": "Habilitar OpenCode",
+ "2f1ee2878b": "Habilitar Codex",
+ "0ea0cae435": "Habilitar Claude",
+ "6c00c46815": "Permita que un proveedor escanee los registros de los agentes locales y cree el libro mayor de tokens combinado.",
+ "49405ccc8d": "Comenzar a rastrear tokens",
+ "ca6bc5fded": "Refrescar",
+ "e06d1baf5c": "Actualizar descripción general de uso",
+ "c760c481c5": "Descripción general de uso",
+ "55c910f4f1": "- los precios de algunos modelos no están disponibles"
+ },
+ "share": {
+ "card": {
+ "utils": {
+ "19f4b4dc75": "github.com/stablyai/orca",
+ "d864fc5f98": "producción",
+ "5d66fdd7c2": "aporte",
+ "7080aeaebb": "Razonamiento",
+ "4ee864629a": "Entrada en caché",
+ "33d38e2177": "Producción",
+ "c2d7b23d57": "Aporte",
+ "9d166247ee": "escritura en caché",
+ "cc28cb965e": "lectura de caché"
+ }
+ }
+ },
+ "stats": {
+ "search": {
+ "cb6a9f0334": "cache",
+ "eaf251e183": "fichas",
+ "6953af58e6": "código abierto",
+ "b77826fca3": "codex",
+ "e9dc37d889": "claude",
+ "8efeae0b22": "seguimiento",
+ "5acbe1fdf2": "tiempo",
+ "ef8bbf7739": "prs",
+ "ce8533f02e": "agentes",
+ "0bba8ca244": "estadística",
+ "0e2a0b6431": "uso",
+ "372debfac0": "estadísticas",
+ "26bb901fcd": "Estadísticas de Orca más análisis de uso, tokens, caché, modelos y sesiones combinados de Claude, Codex y OpenCode.",
+ "cb2430ae6a": "Estadísticas y uso"
+ }
+ },
+ "usage": {
+ "overview": {
+ "model": {
+ "bc474051e5": "OpenCode",
+ "eb220d193b": "Codex",
+ "544d6d4c16": "Claude"
+ },
+ "sections": {
+ "9564a3b21b": "sesiones -",
+ "32330a6e66": "{{value0}}: fichas {{value1}}",
+ "57d1448ef8": "Permitir",
+ "f6df0d7d6d": "Más",
+ "1dd166c920": "Menos",
+ "52d9221dc0": "Mapa de calor de actividad reciente de tokens",
+ "c424eb3f8e": "Mejor:",
+ "f28ff1f852": "Actividad reciente de tokens combinados de Claude, Codex y OpenCode.",
+ "69e2b50427": "Intensidad diaria",
+ "3a795542fa": "Mezcla de tokens combinada",
+ "e65084cb4b": "razonamiento",
+ "3bc4a01b24": "Tokens combinados de entrada, salida y caché entre proveedores habilitados.",
+ "4ff104da47": "Mezcla de tokens",
+ "0015facc1f": "Cache",
+ "7f270458af": "Producción",
+ "9365b14a4e": "Nueva entrada",
+ "3de9bf87fc": "Aún no hay modelo",
+ "6762f6a682": "fichas",
+ "a7f937fb29": "{{value0}} sesiones - {{value1}} {{value2}}",
+ "c8f3a2d1e0b4": "vueltas",
+ "d9a4b3e2f1c5": "eventos"
+ }
+ }
+ }
+ },
+ "sparse": {
+ "SparseCheckoutPresetSelect": {
+ "c4ac80151d": "Nuevo preajuste",
+ "7c3275d307": "Editar {{value0}}",
+ "c7f9b3f0c1": "Apagado",
+ "8b12c0850a": "Ahorrar",
+ "de8fce5854": "Cancelar",
+ "ddbcaef7be": "src/paquetes de renderizador/ui",
+ "0e9ad9c798": "Directorios",
+ "064c1e2d12": "Interfaz de usuario del renderizador",
+ "b3a500c623": "Nombre",
+ "16223dde6a": "Cargar ajustes preestablecidos",
+ "a683a4bc8e": "Reintentar cargar ajustes preestablecidos",
+ "14952d451e": "directorios {{value0}}",
+ "e9283eb171": "1 directorio",
+ "69c020eddc": "Editar preajuste",
+ "bd6cec2056": "nuevo"
+ }
+ },
+ "source": {
+ "control": {
+ "SourceControlActionVariableChips": {
+ "1b77798d5f": "variables",
+ "6b921a0ac2": "Ejemplo",
+ "4bf6d88039": "(vacío)"
+ }
+ }
+ },
+ "skills": {
+ "SkillsPage": {
+ "cb142070b4": "Refrescar",
+ "984405683f": "Complemento",
+ "4d177feabd": "incluido",
+ "aa59462502": "Repositorio",
+ "571c5818c1": "Hogar",
+ "0bc1379f4c": "Todas las fuentes",
+ "38e0951c3a": "Habilidades del agente",
+ "fb6bf60b52": "Claude",
+ "426be2aac6": "Codex",
+ "39b6998ddb": "Todos los proveedores",
+ "a68dee6a32": "Habilidades de búsqueda",
+ "e46e162e2e": "de",
+ "b088e0785d": "Beta",
+ "f43ad6edf3": "Habilidades",
+ "7e828fb2c6": "Atrás",
+ "ea72d6185b": "No se pudieron escanear las habilidades locales",
+ "dc4c3328ee": "Revelar archivo",
+ "9963dff6d3": "No se encontró ninguna descripción.",
+ "995fde8337": "No se pudo revelar el archivo de habilidad",
+ "ab5b777350": "Se comprobaron las carpetas de habilidades locales de inicio, repositorio, paquetes y complementos.",
+ "08a321a984": "Ajusta la búsqueda o los filtros.",
+ "4acd6d68ec": "No se encontraron habilidades locales",
+ "6a62a0168c": "No hay coincidencias",
+ "cd7893fbc1": "Habilidades de escaneo",
+ "35b9a724a0": "Disponible",
+ "0c74e7ff34": "Local"
+ }
+ },
+ "sidebar": {
+ "local": {
+ "base": {
+ "ref": {
+ "suggestion": {
+ "toast": {
+ "670864ab52": "Mantener actualizado el {{value0}} local",
+ "84c62e4d7f": "No se pudo encender {{value0}}",
+ "442552c656": "Abra Configuración e inténtelo de nuevo.",
+ "f15fd80989": "Su nuevo árbol de trabajo está actualizado, pero el {{value0}} local está {{value1}} {{value2}} atrás, por lo que las diferencias de IA pueden compararse con el historial obsoleto. Deja que Orca lo mantenga actualizado automáticamente. Cambie esto en cualquier momento en",
+ "3d260e1a5d": "Configuración › {{value0}}",
+ "34a03a6565": "Mantenga {{value0}} actualizado",
+ "4a18052018": "El local {{value0}} está detrás de {{value1}}"
+ }
+ }
+ }
+ }
+ },
+ "AddProjectFromFolderDialog": {
+ "7d1f51678c": "Agregar proyecto",
+ "7726a16374": "Cancelar",
+ "046751dbfb": "Agregue esta carpeta como un proyecto Orca separado.",
+ "e643b30398": "Proyecto remoto agregado"
+ },
+ "AddRepoCreateStep": {
+ "0ae45b8238": "mi-proyecto",
+ "a8149a3a5a": "Nombre",
+ "038729c107": "Carpeta",
+ "11fd2a7db8": "repositorio git",
+ "180e9b5e48": "Tipo de proyecto",
+ "d877ece0d6": "Cree un repositorio Git o una carpeta simple y ábralo en Orca.",
+ "db9be12229": "Iniciar un nuevo proyecto",
+ "5e97f0c4b9": "Proyecto creado",
+ "2c12db1511": "Proyecto ya agregado",
+ "875dda0995": "Introduzca una ruta principal del servidor.",
+ "45b7c26034": "Crear proyecto",
+ "85085d74d2": "Creando…"
+ },
+ "AddRepoNestedImportStep": {
+ "496f68cf8c": "Escaneo de repositorios. Haga clic para detener.",
+ "a32bef9516": "Dejar de escanear",
+ "2f8298f3c3": "Detener escaneo",
+ "c157f31a95": "Importar como grupo",
+ "40199ef7b3": "Nombre del grupo",
+ "b20bb7c24f": "Mantiene estos repositorios juntos en un grupo. Lo mejor para repositorios relacionados como microservicios.",
+ "787412361a": "¿Qué es el nombre de un grupo?",
+ "5f857ba8e6": "en",
+ "4df0d08cc5": "Encontró",
+ "8db50afe1a": "Importar repositorios desde la carpeta",
+ "5b2e6fe3c8": "Importar por separado",
+ "cf9d382ca1": "Importar",
+ "220dd32d83": "Exploración..."
+ },
+ "AddRepoRemoteStep": {
+ "5b205b5281": "Detener escaneo",
+ "6680289908": "/inicio/usuario/proyecto",
+ "ef410aa881": "Ruta remota",
+ "0416bde073": "Agregar configuración",
+ "df6fbcf880": "No hay destinos SSH configurados.",
+ "44637f43bd": "Objetivo SSH",
+ "80557be85a": "Elija un destino SSH conectado e ingrese la ruta a un repositorio Git.",
+ "91b93a90a4": "Abrir proyecto remoto",
+ "007651bdf9": "Navegue hasta un directorio y haga clic en Seleccionar para elegirlo.",
+ "dd3ff65486": "Explorar el sistema de archivos remoto",
+ "36d427bb66": "Agregar proyecto remoto",
+ "35831a7312": "Añadiendo..."
+ },
+ "AddRepoServerStartStep": {
+ "ae990c86a0": "Volver para agregar opciones",
+ "e1710bf831": "Abrir como carpeta",
+ "8da4d1a5be": "Agregar proyecto Git",
+ "ac66a3ed2d": "Explorar el sistema de archivos del servidor",
+ "92d25420a0": "/inicio/usuario/proyecto",
+ "867692f505": "Ruta del servidor",
+ "423b5d3d31": "Agregue un repositorio o carpeta de Git que ya exista en el servidor de ejecución seleccionado.",
+ "3d0c035483": "Proyecto de servidor abierto",
+ "438493f214": "O ingrese una ruta de servidor manualmente",
+ "6b9958492a": "¿Quieres importar muchos repositorios a la vez? Busque la carpeta principal.",
+ "d40d751517": "Nuevo repositorio o carpeta",
+ "a81ffa0a99": "Crear en el servidor",
+ "a2ea37d549": "Repositorio remoto de Git",
+ "47759c9491": "Clonar desde URL",
+ "516187414c": "Proyecto o carpeta existente",
+ "0adf083af7": "Examinar servidor",
+ "8efa930eb5": "Agregue otro proyecto del servidor de ejecución seleccionado.",
+ "39bd249b3a": "Agregar un proyecto",
+ "0f8aba944c": "Navegue hasta un directorio y haga clic en Seleccionar para elegirlo."
+ },
+ "AddRepoStartSteps": {
+ "87596c1446": "Otras formas de agregar",
+ "acf895cb42": "Agrega un proyecto para comenzar con Orca.",
+ "d13757911c": "Agregar un proyecto",
+ "d301db1c9a": "Escaneo de repositorios. Haga clic para detener.",
+ "69ea7f8dc4": "Dejar de escanear",
+ "9906cae183": "Detener escaneo"
+ },
+ "AddRepoStepIndicator": {
+ "3bb655c117": "Atrás"
+ },
+ "AddRepoSteps": {
+ "569326d9cc": "Elige carpeta",
+ "a93ef169b5": "Explorar el sistema de archivos del servidor",
+ "2ce3f6edf8": "/ruta/al/destino",
+ "04a4c4e84a": "Ubicación del clon",
+ "b698a4a29d": "https://github.com/user/repo.git",
+ "3d4acbe693": "URL de Git",
+ "5b2ea674b1": "Ingrese la URL de Git y elija dónde clonarla.",
+ "c05f88a31f": "Clonar desde URL",
+ "fe8e629fe3": "Navegue hasta un directorio y haga clic en Seleccionar para elegirlo.",
+ "df8b0e6c22": "Proyecto remoto agregado",
+ "3e64e8a70d": "La conexión falló",
+ "32a7256d85": "Clon",
+ "69f5b5380d": "Clonación..."
+ },
+ "AutoRenameFailedDialog": {
+ "aed1623b1e": "Cerca",
+ "eab8b45238": "Error de copia",
+ "a23b22d16f": "copiado",
+ "74fc00776f": "Detalles del error",
+ "3afcad0497": "desde el primer mensaje del agente.",
+ "ff62a18580": "Orca no pudo generar un nombre de sucursal para",
+ "ca3b225195": "Error en el nombre automático de sucursal"
+ },
+ "CreateProjectLocationField": {
+ "95548e33bf": "Elija la carpeta principal...",
+ "632b456b1b": "Cambiar",
+ "afaf54f245": "Cambiar carpeta principal",
+ "f520f83a97": "Explorar el sistema de archivos del servidor",
+ "2a20a603a3": "/inicio/usuario/proyectos",
+ "134e37f711": "Ubicación",
+ "b589b77997": "Navegue hasta un directorio y haga clic en Seleccionar para elegirlo."
+ },
+ "DeleteWorktreeDialog": {
+ "ff2a74ac0e": "y",
+ "91492c9ad6": "Eliminar",
+ "4f6750ca7b": "No se pudo eliminar el espacio de trabajo",
+ "42e610d6cf": "Error al forzar la eliminación",
+ "5cc1a6701c": "Abrir configuración",
+ "2b56b35f53": "Puedes cambiar esto en Configuración.",
+ "dd3a45bbbd": "Omitiremos esta confirmación la próxima vez.",
+ "fc23c4cbdf": "Eliminar espacio de trabajo",
+ "86f0ae1257": "Eliminar espacios de trabajo"
+ },
+ "DeleteWorktreeDirtyChangeHint": {
+ "8e2994ce28": "Al eliminar este espacio de trabajo de forma permanente, estos cambios se eliminan del disco."
+ },
+ "DeleteWorktreeLineageNotice": {
+ "ad407c2d55": "más",
+ "a940f3c96e": "Se eliminarán los espacios de trabajo secundarios",
+ "29b98bf9cd": "Al eliminar este espacio de trabajo, también se eliminan {{value0}} espacios de trabajo secundarios.",
+ "66798cc6a2": "Al eliminar este espacio de trabajo, también se elimina 1 espacio de trabajo secundario."
+ },
+ "DeleteWorktreeSkipConfirmOption": {
+ "29aefb7e52": "no vuelvas a preguntar"
+ },
+ "DeleteWorktreeWarningPanels": {
+ "026738155a": "(el directorio de clonación original).",
+ "c4f96a6e18": "árbol de trabajo principal",
+ "e3be9eba15": "Este es el"
+ },
+ "ImportedWorktreesVisibilityLine": {
+ "b7a87dc32f": "Mostrar en la lista del árbol de trabajo",
+ "ad99f4eea9": "Mantener oculto",
+ "9f4f14e821": "Cambie esto más tarde desde el menú del proyecto.",
+ "b2bc47c080": "más ubicaciones",
+ "b47ba1a9d2": "{{value0}} vista previa",
+ "2251d41ebb": "Grupos de árboles de trabajo ocultos",
+ "f54f2bec5d": "{{value0}} árboles de trabajo ocultos para {{value1}}",
+ "5a9688802a": "Mostrar {{value0}} más",
+ "294de4aeb2": "Mostrar menos"
+ },
+ "NonGitFolderDialog": {
+ "e52454b7f6": "Abrir como carpeta",
+ "05b33a17a9": "Cancelar",
+ "8fba4b8cbb": "Esta carpeta no es un repositorio de Git. Tendrás el editor, la terminal y la búsqueda, pero las funciones basadas en Git no estarán disponibles.",
+ "c49fb13492": "No se pudo agregar la carpeta remota"
+ },
+ "OrcaYamlTrustDialog": {
+ "f3e2b868fb": "Ejecutar ganchos",
+ "43b7bec4cd": "no corras",
+ "c494b3ccb1": "en",
+ "79afc6772b": "orca.yaml",
+ "531689199b": "Confía siempre",
+ "bf800b7e04": ". Solo corre si confías",
+ "831f2cd9f0": "se ejecuta en su máquina",
+ "aa3ffb33fb": "este repositorio",
+ "c55beddbf8": "cambiado desde la última vez que lo aprobó. Vuelva a revisar antes de que se ejecute",
+ "95bf974a1a": "Guión {{value0}}",
+ "9e52effffd": "Nuevo script {{value0}}",
+ "e4a51dc4b3": "¿Ejecutar {{value0}} desde {{value1}}?",
+ "02b0ede5ad": "El {{value1}} de {{value0}} cambió: ¿ejecutar la nueva versión?"
+ },
+ "PendingWorktreeRow": {
+ "af21e953d1": "Cancelar la creación del árbol de trabajo",
+ "188f6922a0": "Cancelar"
+ },
+ "ProjectGroupDeleteDialog": {
+ "ca65b78f78": "Cancelar",
+ "9be10d49ea": "y desagrupar sus proyectos.",
+ "69f5cb97d0": "Borrar",
+ "591f330288": "Eliminar grupo de proyectos",
+ "2c14ce677a": "Eliminando..."
+ },
+ "ProjectGroupNameDialog": {
+ "d99a034073": "Cancelar",
+ "83dfbc5313": "Nombre del grupo",
+ "4a64e78822": "Ahorro..."
+ },
+ "RemoteFileBrowser": {
+ "2300612806": "Escriba para filtrar o ingresar una ruta...",
+ "9e060f5815": "Seleccionar carpeta",
+ "f8b1deb1a4": "Cancelar",
+ "51001182e3": "directorio vacio",
+ "971d85cc84": "Se abre como proyecto remoto · {{value0}}",
+ "00c4235c10": "No hay coincidencias para '{{value0}}'"
+ },
+ "RemoveFolderDialog": {
+ "4dc5b5065b": "Eliminar",
+ "d36883e046": "Cancelar",
+ "8c097ef04e": "de Orca. Todavía está en tu disco.",
+ "e62415c3d0": "Esto sólo elimina",
+ "b79b39d865": "Eliminar proyecto"
+ },
+ "ScrollToCurrentWorkspaceToolbarButton": {
+ "23989bb663": "Revelar un espacio de trabajo activo"
+ },
+ "SetupGuideSidebarEntry": {
+ "b0a7bfc34c": "Ocultar de la barra lateral",
+ "88d402b71d": "Lista de verificación de incorporación"
+ },
+ "SetupScriptPromptCard": {
+ "ff1e819a11": "Agregar un script de configuración",
+ "70715947fb": "El script de configuración no puede estar vacío",
+ "888b83bf78": "No se pudo guardar el script de configuración",
+ "a49196d538": "Se ejecuta cuando Orca crea un nuevo árbol de trabajo.",
+ "d9f2db2738": "configuración del proyecto",
+ "a5bb8c5135": "Guardado en este",
+ "dcaa645da5": "OK"
+ },
+ "SetupScriptPromptCardViews": {
+ "96a7f4198c": "Guardar configuración local",
+ "3933401d28": "Configurar",
+ "31b8b01a45": "Ajustes",
+ "4a98f907ae": "Rever",
+ "0a98169776": "Agregue un comando de configuración para ejecutar cuando Orca cree nuevos árboles de trabajo.",
+ "8349e3fa4c": ". Guárdelo para ejecutarlo en busca de nuevos árboles de trabajo.",
+ "b56d1322f7": "Encontré un comando de configuración en",
+ "aef6c0a213": "Guarde el comando detectado para ejecutarlo cada vez que Orca cree un árbol de trabajo.",
+ "660cdc17f8": "guiones de configuración. Agregue un comando local o cambie la fuente en Configuración.",
+ "8f6be51aa1": "orca.yaml",
+ "bb879db364": "Este repositorio ignora lo compartido",
+ "0155fb9ed3": "No se pudo verificar el script de configuración de este repositorio en este momento.",
+ "eefa756190": "Configurar manualmente",
+ "ca4efcbc25": "Ahorrar",
+ "d02e6a42b1": "Detectado desde",
+ "fdbc6cb064": "Script de configuración detectado",
+ "7275f674cc": "Configuración detectada",
+ "822ff300ad": "Despedir",
+ "5bfd5c8779": "Descartar scripts de configuración"
+ },
+ "SidebarFeedbackDialog": {
+ "8bf619e4cf": "Cancelar",
+ "8de03e23c5": "Envíelo solo con sus comentarios escritos o conecte \"gh\" para incluir la identidad de GitHub.",
+ "d20439c560": "Comprobando la identidad de GitHub...",
+ "5b120b9634": "Enviar de forma anónima",
+ "c9e5ea0791": "GitHub:",
+ "d46ddd66fc": "¿Qué podríamos mejorar?",
+ "3460258a54": "Sigue en X",
+ "26108d3699": "Únete a la Discord",
+ "d245c4ef6c": "Problemas de GitHub",
+ "9b33530b3d": "Otras formas de llegar a nosotros",
+ "a828fa4aee": "Comparta lo que funciona, lo que no funciona o lo que Orca debería hacer a continuación.",
+ "0eb643f07f": "Enviar comentarios",
+ "60b721e857": "No se pudieron enviar comentarios. Por favor inténtalo de nuevo.",
+ "7a46c228b8": "Gracias por los comentarios.",
+ "a2fd890d9e": "Por favor ingrese sus comentarios antes de enviarlos.",
+ "f2e42e1307": "Enviar",
+ "69969ba364": "Envío…"
+ },
+ "SidebarFilter": {
+ "e3b3898218": "Agregar proyecto",
+ "92a23e6d07": "Restablecer filtros",
+ "81ded53722": "SSH",
+ "b9e8802e73": "Ningún proyecto coincide",
+ "779b7ba05d": "Claro",
+ "139877b384": "Seleccionar todo",
+ "5f7085a077": "Proyectos",
+ "e5cb32a898": "Ocultar rama predeterminada",
+ "638a2d221d": "Ocultar durmiendo",
+ "f506a1262a": "Filtrar espacios de trabajo",
+ "75405270ed": "Editar filtros ({{value0}} activo)",
+ "489d1c8c9f": "Buscar proyectos...",
+ "ee240a39eb": "Editar filtros"
+ },
+ "SidebarHeader": {
+ "92154beb7e": "Nuevo espacio de trabajo",
+ "49f62c5665": "tablero del espacio de trabajo",
+ "5c9c7c16aa": "Agregar un proyecto para crear espacios de trabajo",
+ "ca6f729da2": "Nuevo espacio de trabajo ({{value0}})",
+ "a30e34eb5c": "Cerrar tablero del espacio de trabajo"
+ },
+ "SidebarNav": {
+ "80611a8b10": "Buscar",
+ "0c3395fd32": "Buscar árboles de trabajo y pestañas del navegador",
+ "c86d83b5c3": "Nuevo",
+ "1b5c41caee": "Orca Móvil",
+ "9c95e1ce91": "Agentes",
+ "f323383e9a": "Automatizaciones",
+ "e7ad3c540d": "Abrir tareas de Jira",
+ "c39ab10000": "Abrir tareas Lineares",
+ "196c1b5362": "Abrir tareas de GitLab",
+ "0ccba862b8": "Abrir tareas de GitHub",
+ "fee535205b": "Tareas",
+ "d599269755": "Ocultar de la barra lateral"
+ },
+ "SidebarRepositoryFilterSection": {
+ "d3a9c4cea1": "Claro",
+ "7679f0c268": "Proyectos",
+ "f10ca29601": "Quitar filtro {{value0}}",
+ "2656053db4": "SSH",
+ "83a820fa71": "Filtrar proyectos...",
+ "5a273fbfce": "Añadir proyecto...",
+ "4815c70605": "Ningún proyecto coincide",
+ "bbbc6e8e3b": "Ningún proyecto no seleccionado coincide"
+ },
+ "SidebarSettingsHelpMenu": {
+ "ad3d3ed7f1": "Reiniciar Orca",
+ "29c56f30ee": "Buscar actualizaciones",
+ "eb9884e55b": "Discord",
+ "5687ab246a": "GitHub",
+ "5f83d86d92": "Registro de cambios",
+ "cdc87f897e": "Documentos",
+ "e565171a7c": "Atajos de teclado",
+ "4cf5b868d7": "Enviar comentarios",
+ "a428c25998": "Ajustes",
+ "2991a0106c": "Ayuda",
+ "4e8f5710d3": "No se pudo reiniciar Orca.",
+ "5161eef55d": "Reiniciando Orca...",
+ "d396773ef0": "de cheques"
+ },
+ "SidebarToolbar": {
+ "19e32d0e5f": "Abra el selector de carpetas para agregar un proyecto",
+ "abc62b6328": "Agregar proyecto"
+ },
+ "SidebarWorkspaceFilterSection": {
+ "c3fa13dc2e": "Ocultar rama predeterminada",
+ "ed1611b65b": "Ocultar durmiendo",
+ "82594419ba": "Filtros"
+ },
+ "SidebarWorkspaceOptionsMenu": {
+ "95c9754653": "Diseño de actividad del agente",
+ "3d4b9c4997": "Flotar",
+ "ba87080fb7": "Mostrar propiedades",
+ "320b675c9a": "Diseño de tarjeta",
+ "09faabd875": "Orden del proyecto",
+ "7bada3b1ab": "Ordenar por",
+ "dc0bb670bc": "Agrupar por",
+ "9919ae1082": "Opciones de espacio de trabajo",
+ "bc96dbd041": "Opciones de espacio de trabajo ({{value0}})",
+ "af9249c505": "Actividad más reciente en el espacio de trabajo",
+ "b451c8b162": "Reciente",
+ "6664282a7b": "Arrastra proyectos para organizarlos",
+ "7b316bdd51": "Manual",
+ "7153d07485": "Arrastre los espacios de trabajo para organizarlos dentro de cada grupo.",
+ "2170d553cf": "Proyecto",
+ "b759bb87ee": "Agentes que necesitan atención, luego actividad más reciente.",
+ "503462f2b4": "Actividad del agente",
+ "3728165cdd": "Nombre",
+ "2a81e07366": "Lista completa",
+ "25105b28cb": "Compacto",
+ "d7084e8bc8": "Actividad del agente",
+ "b64d8bcca0": "Puertos",
+ "26c71e536c": "Notas",
+ "b8dcc6f321": "Enlace PR/MR",
+ "ca4d3c522e": "Cuestión Linear",
+ "91dfc653e8": "billete de GitHub",
+ "cc17bd443b": "Detallado",
+ "0f9b959b31": "relaciones públicas",
+ "e029a2d775": "Estado",
+ "c2c7a45cda": "Ninguno",
+ "680043342f": "compacto",
+ "c7591b6014": "repositorio"
+ },
+ "SshDisconnectedDialog": {
+ "ca4a7892af": "Conectando...",
+ "89385db176": "Despedir",
+ "656368f3a2": "Error de reconexión",
+ "376bed88e5": "La conexión al host remoto encontró un error.",
+ "4afcca1d24": "Reconectar",
+ "11552bf786": "SSH desconectado",
+ "cb5938ae79": "Reconectando..."
+ },
+ "SshTargetRow": {
+ "4677394048": "Conectando…",
+ "75ad429b5d": "Conectar"
+ },
+ "WorkspaceKanbanCard": {
+ "cefae8983e": "Fijado"
+ },
+ "WorkspaceKanbanDrawerHeader": {
+ "f369f5c5a3": "Cerca",
+ "e1a34450fc": "Organice espacios de trabajo por estado y abra tarjetas de espacios de trabajo.",
+ "81870af08f": "seleccionado",
+ "c6a77ab0f4": "tablero del espacio de trabajo"
+ },
+ "WorkspaceKanbanPinDropTarget": {
+ "c30151c5ee": "Vaya aquí para fijar sin cambiar el estado.",
+ "8fae2d0862": "Fijado"
+ },
+ "WorkspaceKanbanSettingsMenu": {
+ "79eb990aa4": "Agregar estado",
+ "054cb50df7": "Quitar {{value0}}",
+ "b45b350eb0": "Mover {{value0}} a la izquierda",
+ "8ce44af9a8": "Cambiar nombre {{value0}}",
+ "395e541d5d": "Estados",
+ "34f03eb0de": "Configuración del tablero",
+ "26cbc92150": "Configuración del tablero del espacio de trabajo"
+ },
+ "WorkspaceKanbanStatusLane": {
+ "8ad104642b": "Vacío",
+ "3611d1ae7f": "Cambiar el tamaño de las columnas del tablero del espacio de trabajo"
+ },
+ "WorkspaceStatusAppearancePopover": {
+ "514be2f569": "Establezca el color {{value0}} en {{value1}}",
+ "8be427206b": "Icono",
+ "2ac106f6b2": "Color",
+ "74b1413279": "Apariencia",
+ "ccbd1e2c69": "Personaliza la apariencia de {{value0}}"
+ },
+ "WorktreeCard": {
+ "a88c92d0e3": "{{value0}}/{{value1}} ya existe.",
+ "6f09f58541": "Eliminar espacio de trabajo",
+ "0777de5970": "Árbol de trabajo principal (directorio de clonación original)",
+ "0f33af979b": "Pago parcial. Los archivos fuera de estas rutas no están en el disco.",
+ "4f964d5e8c": "escaso",
+ "7d517f82e2": "primario",
+ "c6833b5187": "Se cambiará el nombre del mensaje del primer agente.",
+ "f62a3dadbc": "cambiar nombre pendiente",
+ "4eba2ea99e": "Falló el nombre automático. Haga clic para ver detalles.",
+ "74522ee457": "cambiar el nombre falló",
+ "02e19349f4": "Error al cambiar el nombre automáticamente: ver error",
+ "691ccfd622": "Eliminando…",
+ "35ccfe2475": "Proyecto {{value0}}",
+ "1d66d84f0b": "cadena",
+ "57eaa61b55": "Ocultar espacios de trabajo secundarios",
+ "8cb634cda6": "Mostrar espacios de trabajo secundarios",
+ "01f45d3d8a": "barra lateral",
+ "93aebe4529": "Carpeta",
+ "0d224eff10": "árbol de trabajo primario",
+ "ca74db7550": "Proyecto remoto vía SSH",
+ "021538e1d1": "SSH desconectado"
+ },
+ "WorktreeCardAgents": {
+ "1b0a156717": "Agentes"
+ },
+ "WorktreeCardMeta": {
+ "3e65e11cc6": "Metadatos del espacio de trabajo",
+ "c7fa72ead0": "Editar notas",
+ "93cbea12c2": "Notas",
+ "eace1d2cf6": "neutral",
+ "dbe2d18972": "Más acciones de {{value0}}",
+ "ae76907ca6": "Desvincular {{value0}}",
+ "ad25c3ff05": "Ver en {{value0}}",
+ "2c67730e07": "Abierto en Orca",
+ "e42941631a": "Ver en Linear",
+ "5e982e6128": "Linear {{value0}}",
+ "807b13b9ec": "Editar problema",
+ "b22f058067": "Ver en GitHub",
+ "e97d8f2876": "Número {{value0}}",
+ "3ea2702e62": "Vinculado {{value0}} #{{value1}}",
+ "b105fd3057": "Linear vinculado {{value0}}",
+ "3f2649eeb8": "Problema vinculado #{{value0}}",
+ "fe075cb851": "Notas del espacio de trabajo"
+ },
+ "WorktreeCardMetadataStatusBadges": {
+ "fe188062a1": "Estado: Abierto",
+ "2931b42b09": "Estado: Borrador {{value0}}",
+ "e888362def": "Estado: Cerrado",
+ "f394b3e86e": "Estado: Fusionado",
+ "af2b07bda5": "Estado: {{value0}}",
+ "29df45afa2": "SEÑOR"
+ },
+ "WorktreeCardPorts": {
+ "34f733dda2": "Ir al árbol de trabajo",
+ "3240f320d7": "Puertos en vivo",
+ "3e5f66564e": "Espacio de trabajo no disponible",
+ "2f854442ff": "Detener proceso",
+ "c8067a829a": "Copiar {{value0}}",
+ "33bc7d7495": "Abrir en el navegador",
+ "9950fe2d20": "No se pudieron actualizar los puertos",
+ "5d1a5d51bb": "Proceso detenido el {{value0}}",
+ "c89f290e25": "Copiado {{value0}}",
+ "d1113f4660": "No se pudo abrir el navegador",
+ "fed49903c9": "{{value0}} en vivo {{value1}}"
+ },
+ "WorktreeContextMenu": {
+ "c39c37676a": "Crea un grupo y mueve este proyecto a él.",
+ "6664418e98": "Nuevo grupo de proyecto",
+ "e091caab15": "No se pudo encontrar el proyecto.",
+ "439fa94d53": "Actualizar",
+ "579b1a8e61": "Quitar del padre",
+ "8d9cd19d09": "Abrir espacio de trabajo principal",
+ "d35dfeae58": "Quitar del grupo",
+ "76865d827f": "Mover al grupo",
+ "503ec0f8e6": "Nuevo grupo del proyecto",
+ "3350101edb": "Copiar ruta",
+ "f4475537d8": "Borrar",
+ "f5ac91531d": "Eliminar proyecto de Orca",
+ "b42391d8bf": "Eliminando…",
+ "0918b35e4f": "Cierre todos los paneles activos en este espacio de trabajo para liberar memoria y CPU.",
+ "7d190f7d2b": "Cierre todos los paneles activos en los espacios de trabajo seleccionados para liberar memoria y CPU.",
+ "84cdbb7e30": "Mover al estado",
+ "56cde9e8e6": "Mover estados a",
+ "f50603c6b2": "Marcar como no leído",
+ "8dacff1fe0": "Marcar como leído",
+ "3baa7d6507": "Alfiler",
+ "697d0f6e1b": "Desprender"
+ },
+ "WorktreeList": {
+ "d880ea0744": "Crea un grupo y mueve este proyecto a él.",
+ "bc1460beb3": "Actualice el nombre del grupo que se muestra en la barra lateral.",
+ "13757c053c": "Nuevo grupo de proyecto",
+ "f9dc6cc5d3": "Cambiar nombre del grupo de proyectos",
+ "370c6a55dd": "Borrar filtros",
+ "b7acbf038b": "No se encontraron espacios de trabajo",
+ "0c6ee14f23": "niño",
+ "5fc9d1891b": "Eliminando…",
+ "c83968f87f": "Eliminar proyecto",
+ "64e55f7f01": "Quitar del grupo",
+ "4a08fb55f2": "Mover al grupo",
+ "cbfd565f83": "Nuevo grupo del proyecto",
+ "e82d3589a1": "Cambiar icono de proyecto",
+ "2cdffbc728": "Configuración del proyecto",
+ "2ef41bf9a7": "Acciones del proyecto",
+ "609633a9e6": "Acciones del proyecto para {{value0}}",
+ "902115cdbe": "Eliminar grupo",
+ "4d7b73658c": "Cambiar nombre de grupo",
+ "79465e9034": "Acciones grupales para {{value0}}",
+ "bfbedc547b": "árboles de trabajo",
+ "45fbfe0335": "rebautizar",
+ "ebc5c7dcef": "Ocultar espacios de trabajo secundarios",
+ "84a2238242": "Mostrar espacios de trabajo secundarios",
+ "045a8aed48": "niños",
+ "2ca6e29a3c": "repositorio",
+ "bb85cd86ba": "Crear espacio de trabajo para {{value0}}",
+ "ebadb7eadb": "{{value0}} {{value1}} niño {{value2}}",
+ "20bebf9c7f": "Mostrar {{value0}} espacio de trabajo secundario",
+ "c1f4a31623": "Mostrar {{value0}} espacios de trabajo secundarios",
+ "e97297cb75": "Ocultar {{value0}} espacio de trabajo secundario",
+ "0cd15956d4": "Ocultar {{value0}} espacios de trabajo secundarios"
+ },
+ "WorktreeMetaDialog": {
+ "3db0a2a593": "Cancelar",
+ "b48c271d39": "para guardar, Mayús+Entrar para una nueva línea.",
+ "7f0be5e9a6": "Admite **rebajas**: negrita, listas, \"código\", enlaces. Presione Entrar o",
+ "030d484fc0": "Notas sobre este árbol de trabajo...",
+ "9c1d1e9b71": "Comentario",
+ "5ae06f40fd": "Pegue una URL de solicitud de extracción o ingrese un número. Déjelo en blanco para eliminar el enlace.",
+ "077a4f7b5c": "PR # o URL de GitHub",
+ "1b91db7e14": "GH PR",
+ "7c454be4c5": "Pegue la URL de un problema o ingrese un número. Déjelo en blanco para eliminar el enlace.",
+ "029ea5ec57": "Abrir problema de GitHub",
+ "741279e7b7": "Número de problema o URL de GitHub",
+ "645fa4a0fd": "Problema de GH",
+ "459ad7f650": "Solo cambia el nombre que se muestra en la barra lateral; la carpeta en el disco permanece igual. Déjelo en blanco para usar el nombre de la rama o la carpeta.",
+ "7f21e0464f": "Nombre para mostrar personalizado...",
+ "ad5e4e514f": "Nombre para mostrar",
+ "65770ad0f0": "Edite enlaces y notas de GitHub para este espacio de trabajo.",
+ "382fd11a3e": "Editar detalles del árbol de trabajo",
+ "2174f17011": "Ahorrar",
+ "61d6f612cf": "Ahorro..."
+ },
+ "WorktreeOpenInMenu": {
+ "1417fd8380": "Personalizar aplicaciones...",
+ "8009ab69a6": "Abrir en",
+ "bd0e8159f8": "Verifique el comando del editor o la configuración del administrador de archivos en esta máquina.",
+ "9a5381eb09": "No se pudo abrir la carpeta del espacio de trabajo.",
+ "0bed8727db": "Es posible que se haya movido o eliminado. Actualizar los espacios de trabajo o eliminarlos de Orca.",
+ "3921d3d9a5": "No se encontró la carpeta del espacio de trabajo.",
+ "f387af445b": "La ruta del espacio de trabajo no es una ruta local válida.",
+ "3ec372b664": "administrador de archivos"
+ },
+ "WorktreeTitleInlineRename": {
+ "2f42ae024f": "No leído:",
+ "bff3bdd00c": "Cambiar nombre del espacio de trabajo",
+ "8df295a78d": "No se pudo cambiar el nombre del espacio de trabajo."
+ },
+ "WorktreeVisibilityDialog": {
+ "83a5ba8dd1": "Árboles de trabajo que no son de Orca",
+ "f1f71b9f02": "Importar",
+ "759371df43": "Esconder",
+ "25ddf19920": "{{value0}} disponible para importar",
+ "8372e4bbd9": "{{value0}} mostrado actualmente",
+ "5d02a5647f": "Oculto de la barra lateral",
+ "3e045d4cb8": "Mostrado en la barra lateral"
+ },
+ "add": {
+ "repo": {
+ "local": {
+ "start": {
+ "actions": {
+ "d72789705e": "Comenzar desde una carpeta vacía",
+ "c709860596": "Crear nuevo proyecto",
+ "5f9ffac036": "Clonar un repositorio Git remoto",
+ "7edb8ebe24": "Clonar desde URL",
+ "a6c20dca96": "Abrir un proyecto desde un destino SSH",
+ "3d162cc76f": "Proyecto remoto",
+ "fb4fc5380e": "Proyecto local, repositorio de Git o carpeta con muchos repositorios",
+ "2281fdc8c7": "Explorar carpeta"
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "worktree": {
+ "flow": {
+ "b81b4e40ca": "Actualice el espacio e inténtelo nuevamente si la lista de espacios de trabajo parece obsoleta.",
+ "7243145cd6": "No se han seleccionado espacios de trabajo eliminables",
+ "ae57cbf6e4": "No se pudo eliminar el espacio de trabajo",
+ "7488ed8711": "Vista",
+ "2b20ce87b3": "Forzar eliminación",
+ "4f3876c0f5": "Error al forzar la eliminación"
+ },
+ "toast": {
+ "1d0fa5c0a5": "No se pudo eliminar el espacio de trabajo {{value0}}",
+ "ead7b8ee15": "Ha cambiado archivos. Utilice Forzar eliminación para eliminarlo de todos modos.",
+ "905fc8efac": "Git ya eliminó este espacio de trabajo. Utilice Forzar eliminación para borrarlo de Orca.",
+ "0899ebdb28": "Git ya olvidó este espacio de trabajo, pero su directorio todavía está en el disco. Utilice Forzar eliminación para eliminar el directorio huérfano."
+ }
+ }
+ },
+ "remote": {
+ "file": {
+ "browser": {
+ "helpers": {
+ "4dbd72a7d7": "{{value0}} no es un directorio en {{value1}}",
+ "be266af66c": "{{value0}} coincide con varios directorios en {{value1}}"
+ }
+ }
+ }
+ },
+ "repo": {
+ "header": {
+ "create": {
+ "state": {
+ "992cfbc44b": "Crear un nuevo árbol de trabajo para {{value0}}",
+ "3a70acd808": "Vuelva a conectar el destino SSH antes de crear espacios de trabajo para {{value0}}",
+ "6d022563a8": "Vuelva a conectar el destino SSH antes de crear espacios de trabajo",
+ "62e71f2d5d": "Crear espacio de trabajo para {{value0}}"
+ }
+ }
+ }
+ },
+ "sidebar": {
+ "project": {
+ "drop": {
+ "669e12dd97": "Carpetas locales y repositorios Git",
+ "ffc769ca29": "Carpeta desplegable para agregar proyecto",
+ "740e8d0d46": "Utilice Agregar proyecto para rutas de servidor",
+ "e344666fb8": "Tiempo de ejecución del servidor activo",
+ "d0f8943f8b": "Preparando el flujo de adición del proyecto",
+ "18d3cf40e9": "Comprobando carpeta"
+ }
+ }
+ },
+ "sleep": {
+ "worktree": {
+ "flow": {
+ "c460fecc4a": "No se pudieron dormir algunos espacios de trabajo",
+ "8bc3fc0671": "No se pudo dormir el espacio de trabajo"
+ }
+ }
+ },
+ "useAddRepoCloneFlow": {
+ "4d0013cc93": "Repositorio clonado",
+ "0dc4d1b657": "Introduzca una ruta de servidor para el destino del clon."
+ },
+ "useAddRepoLocalFolderFlow": {
+ "7ab10e4974": "Utilice una ruta de servidor para agregar proyectos desde un tiempo de ejecución remoto."
+ },
+ "useAddRepoNestedImportFlow": {
+ "680cac2c82": "{{value0}} falló",
+ "cbfbc7a797": "Algunos repositorios no se pudieron importar",
+ "1b33c5f090": "No se importaron repositorios"
+ },
+ "useSidebarProjectDrop": {
+ "f34a286c0d": "No se pudo agregar la carpeta descartada.",
+ "451a4638db": "Suelta una carpeta para agregarla como proyecto.",
+ "5ccb56c7be": "Utilice Agregar proyecto para ingresar una ruta de servidor.",
+ "849ef13dc0": "Las ubicaciones de carpetas locales no están disponibles para los tiempos de ejecución del servidor.",
+ "c0315153d1": "Suelte una carpeta a la vez."
+ },
+ "workspace": {
+ "status": {
+ "cb387159f6": "En curso",
+ "6c1efa2cf8": "En revisión",
+ "6b8285b8dd": "Hecho",
+ "93ac840dcb": "Obstruido",
+ "2c19d1db33": "Jugar",
+ "111db162bf": "En pausa",
+ "642da473f2": "Alerta",
+ "6380517b10": "Bandera",
+ "251c817bdd": "Minutero",
+ "409528031f": "Revisar",
+ "5f9ca31a84": "Espera",
+ "821d156f54": "discontinuo",
+ "226d1e7773": "Progreso",
+ "a702bc08d4": "Punto",
+ "b4a7101fe1": "Círculo",
+ "1a9383112b": "Progreso del director",
+ "caebe3c10f": "Revisión del director",
+ "895f381714": "Director hecho",
+ "caabd5ca85": "Zinc",
+ "7adb43ecf0": "Rosa",
+ "ddf25b6262": "Esmeralda",
+ "7cebab6d4a": "Ámbar",
+ "1b81da243a": "Violeta",
+ "6437a8c253": "Cielo",
+ "fc3b92756c": "Azul",
+ "52e3c6e2a4": "Neutral"
+ }
+ },
+ "worktree": {
+ "card": {
+ "compact": {
+ "agents": {
+ "a128d7006b": "{{value0}} {{value1}} niño {{value2}}",
+ "289a1d2ca7": "Expanda {{value0}}. {{value1}}",
+ "0c1debfe84": "Contraer {{value0}}"
+ }
+ }
+ },
+ "list": {
+ "groups": {
+ "0ed04075b8": "Todo",
+ "4aeefc5996": "Fijado",
+ "682ed5d551": "Cerrado",
+ "7c2f009786": "En curso",
+ "6798dc7c94": "En revisión",
+ "5076efc3d2": "Hecho"
+ }
+ }
+ },
+ "CacheTimer": {
+ "07729cc155": "venció"
+ },
+ "DeleteWorktreeDialogFooter": {
+ "c0e972d726": "Cancelar",
+ "cf95e3b5bb": "Cerca"
+ },
+ "index": {
+ "b826a98b6f": "ocupado"
+ }
+ },
+ "shared": {
+ "useDaemonActions": {
+ "01af244097": "Cancelar",
+ "28c8e53176": "Esto fuerza el cierre de todos los paneles de terminal en ejecución en todos los espacios de trabajo. Cualquier trabajo no guardado en esas sesiones se perderá. El demonio sigue ejecutándose y se pueden abrir nuevas terminales inmediatamente. Esto no se puede deshacer.",
+ "1bbea41a77": "¿Eliminar todas las sesiones de terminal?",
+ "01d6b7c64e": "Elimina todos los paneles de terminal en ejecución y reinicia el proceso del demonio. Los paneles muestran \"Proceso cerrado\" y se pueden volver a abrir inmediatamente. Se conservan las sesiones de protocolo heredado de una versión anterior de la aplicación. Esto no se puede deshacer.",
+ "922548bc66": "¿Reiniciar el demonio del terminal?",
+ "2b4efdc162": "No se pudieron finalizar las sesiones.",
+ "d18f3005c2": "{{value0}} sesión{{value1}} se negó a salir.",
+ "baad8cd651": "No hay sesiones en ejecución.",
+ "fe2ab66d45": "Eliminó {{value0}} de {{value1}} sesiones. {{value2}} se negó a salir.",
+ "d762b41f41": "El reinicio falló.",
+ "b5954e12d3": "Error al reiniciar: verifique los registros.",
+ "0e9da1b98e": "Daemon se reinició.",
+ "d6372cc797": "Mató a {{value0}} sesión{{value1}}.",
+ "87412c2a68": "Sesión {{value0}} eliminada.",
+ "a2f040ac1c": "Mató {{value0}} sesiones.",
+ "63520148e2": "La sesión {{value0}} se negó a salir.",
+ "cc0a26cb14": "{{value0}} sesiones se negaron a salir."
+ }
+ },
+ "setup": {
+ "guide": {
+ "SetupGuideModal": {
+ "3598a3ca0c": "Termine los flujos de trabajo principales que hacen que Orca sea útil para el trabajo de agentes paralelos.",
+ "48a9e5ef2d": "Empezando",
+ "28cf59fcb4": "Esto ocultará la lista de verificación de la barra lateral.",
+ "f3b5ffb2a6": "Ocultar lista de verificación de la barra lateral"
+ },
+ "SetupGuideProgressRing": {
+ "dac3a4724a": "{{value0}} de {{value1}} pasos de configuración completos"
+ }
+ }
+ },
+ "settings": {
+ "keep": {
+ "local": {
+ "main": {
+ "up": {
+ "to": {
+ "date": {
+ "setting": {
+ "f8bda25f29": "Mantenga actualizado el principal local"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "AccountsPane": {
+ "c2d2751587": "Eliminar cuenta",
+ "dbb9626ed1": "Cancelar",
+ "854ebbcc45": "Orca eliminará la autenticación de Claude administrada para esta cuenta guardada. Si está actualmente activo, Orca recurre al inicio de sesión Claude predeterminado del sistema.",
+ "63843e37e2": "¿Eliminar la cuenta de Claude?",
+ "99c8f9e498": "Orca eliminará el hogar del Codex administrado para esta cuenta guardada. Si está actualmente activo, Orca recurre al inicio de sesión predeterminado del Codex del sistema.",
+ "0d47394635": "¿Eliminar cuenta del Codex?",
+ "ae3b21eb6c": "opencode.ai/workspace/wrk__…/go",
+ "51c9104e13": "Encuentre esto en la URL después de iniciar sesión en opencode.ai (p. ej.",
+ "b398b834c9": "Claro",
+ "a122332371": "wrk_… (dejar en blanco para búsqueda automática)",
+ "dbdb0b0bd8": "Anulación de ID del espacio de trabajo",
+ "d70a5287a4": "Anulación opcional del ID del espacio de trabajo si falla la búsqueda automática.",
+ "02cb127710": "ID del espacio de trabajo de OpenCode Go",
+ "7ce0e1907c": "). Encuéntrelo en DevTools → Red → cualquier solicitud de opencode.ai → Encabezado de cookies de su navegador. La autenticación OpenCode Go está basada en la web y se comparte entre terminales Windows y WSL.",
+ "8951c5309f": "autenticación=Fe26.2**…",
+ "338820326a": ") o el encabezado completo de la cookie (p. ej.",
+ "922b51e02d": "Fe26.2**…",
+ "0023cc336e": "Pegue el valor del token sin formato (p. ej.",
+ "a7e38affcd": "Fe26.2**… token o auth=Fe26.2**… encabezado",
+ "67e3c33670": "Cookie de sesión de OpenCode Go",
+ "b2b1aa936d": "Pegue su cookie de sesión de opencode.ai para obtener el límite de velocidad.",
+ "36223200ac": "Cookie de sesión de OpenCode Go",
+ "ea631977b5": "Configure los ajustes del proveedor OpenCode Go.",
+ "4ac10b4d08": "OpenCode Go",
+ "d708749337": ". Esto utiliza credenciales emitidas para la aplicación Gemini CLI, no para Orca. Puede fallar si Google actualiza la CLI. Úselo bajo su propio riesgo.",
+ "c2aee76420": "Extrae las credenciales de OAuth de su instalación local de CLI de Gemini para autenticarse con Google para",
+ "96f3649526": "Utilice las credenciales de Gemini CLI (experimental)",
+ "d676c41fc6": "Extrae las credenciales de OAuth de su instalación local de CLI de Gemini para autenticarse con Google. Esto utiliza credenciales emitidas para la aplicación Gemini CLI, no para Orca. Puede fallar si Google actualiza la CLI. Úselo bajo su propio riesgo.",
+ "0c7f915b01": "Utilice las credenciales de la CLI de Gemini",
+ "973741a871": "Configure los ajustes del proveedor Gemini.",
+ "0c64dc2a64": "Gemini",
+ "db209ee572": "Eliminar",
+ "8a0f870153": "Volver a autenticar",
+ "3d245ef7d9": "Codex informó que este inicio de sesión no está actualizado",
+ "589eba1eee": "Necesita volver a autenticarse",
+ "e74831fb6b": "Activo",
+ "d46f735a85": ". Orca utilizará el inicio de sesión Codex predeterminado del sistema de ese entorno hasta que agregue uno aquí.",
+ "b4c9450319": "No hay cuentas gestionadas del Codex para",
+ "93c47b333a": "Necesita iniciar sesión",
+ "f2a265f8c7": "Valor predeterminado del sistema",
+ "b0e948a4f9": "Agregar cuenta",
+ "5568bb6d5c": "cuentas. Allí se agregan nuevas cuentas.",
+ "c0a52abfc5": "Demostración",
+ "94d351af4a": "Cuentas",
+ "d0d53b7eb0": "Administre qué cuenta Codex utiliza Orca para obtener el límite de tasa en vivo.",
+ "3180536c7a": "Cuentas del Codex",
+ "340d6f7a85": "Cada cuenta mantiene su propio contexto de inicio de sesión local en Orca. La autenticación de la cuenta permanece en este dispositivo.",
+ "cedfab35ab": "Opcional. Orca puede utilizar su inicio de sesión normal del Codex; agregue cuentas solo si desea un cambio rápido en Orca.",
+ "ef91cfa06b": "Codex",
+ "dea08560b4": ". Orca utilizará el inicio de sesión Claude predeterminado del sistema de ese entorno hasta que agregue uno aquí.",
+ "3fe7862418": "No hay cuentas administradas de Claude para",
+ "3455cf43fa": "Claude iniciar sesión.",
+ "fcc4093fc1": "Utilice su inicio de sesión actual del Codex {{value0}}.",
+ "79e484c3b2": "Conmutador de cuenta opcional para los archivos de autenticación compartidos de Claude.",
+ "8bbfd74556": "Cuentas Claude",
+ "72b36ea174": "Opcional. Orca puede utilizar su inicio de sesión normal de Claude; agregue cuentas solo si desea cambiar rápidamente sin mover sesiones de chat.",
+ "26ef4b55be": "Claude",
+ "2743cdc0af": "Error al actualizar la cuenta de Claude.",
+ "b15ce90870": "{{value0}} -> {{value1}}. Reinicie los terminales Claude en vivo antes de continuar con sesiones anteriores.",
+ "f921d32606": "Cuenta Claude actualizada.",
+ "5bf8764953": "Error al actualizar la cuenta del Codex.",
+ "2358ac71d2": "WSL predeterminado",
+ "ad47a33f72": "Cargando WSL",
+ "8619f9afa9": "WSL",
+ "46cf7e7495": "Ubicación de la cuenta",
+ "0b4591ff93": "Elija qué entorno local inspeccionar y dónde se agregan las nuevas cuentas administradas de Claude y Codex.",
+ "0c67a2a1aa": "WSL no está disponible en esta máquina.",
+ "2cd197025c": "Elija si las cuentas de proveedor se inspeccionan y agregan en {{value0}} o WSL.",
+ "f54b4fbd71": "Ubicación de la cuenta",
+ "9107406589": "No se pudieron cargar las cuentas de Claude.",
+ "b8c2905c2b": "No se pudieron cargar las cuentas del Codex.",
+ "fd62f37c24": "Codex informó que este inicio de sesión {{value0}} no está actualizado.",
+ "b10cb4f696": "añadiendo",
+ "e4a28e8894": "Codex informó que el inicio de sesión {{value0}} necesita un nuevo inicio de sesión. Inicie sesión nuevamente antes de iniciar nuevas sesiones del Codex.",
+ "75ca9b718e": "Codex informó que la cuenta activa necesita un nuevo inicio de sesión. Vuelva a autenticarlo antes de iniciar nuevas sesiones del Codex.",
+ "b11078a9c2": "wsl",
+ "350b2a1aa7": "Usa tu actual",
+ "e05d0ff737": "Utilice su inicio de sesión actual de {{value0}} Claude."
+ },
+ "AdvancedPane": {
+ "40b29e0bf3": "Reanudar",
+ "87a2cb2ac8": "Orca aplica este modo de red al inicio.",
+ "89958d7edf": "Reiniciar requerido",
+ "b3ad629640": "Úselo solo cuando una VPN o proxy corporativo interrumpa las descargas de actualizaciones con errores de protocolo HTTP/2. Afecta a todas las redes de Electron después del reinicio.",
+ "6627e75c92": "Explicar la compatibilidad HTTP/1.1",
+ "e9506d3377": "Compatibilidad HTTP/1.1",
+ "8b7a8df299": "Soluciones alternativas de bajo nivel para la resolución de problemas de soporte.",
+ "8d8d8ac599": "Compatibilidad"
+ },
+ "AgentLocationSetting": {
+ "92f4238f1a": "WSL predeterminado",
+ "fc806485ae": "Cargando WSL",
+ "43663b5e69": "WSL",
+ "9bccf48906": "Ubicación del agente",
+ "d00949e59b": "Mostrar agentes instalados desde {{value0}}. Actualizar vuelve a verificar la RUTA en ese entorno.",
+ "c7c516946f": "WSL no está disponible en esta máquina.",
+ "f97b986b7f": "wsl"
+ },
+ "AgentSkillSetupPanel": {
+ "0b810ec59f": "Presione Entrar para ejecutar el comando de instalación.",
+ "ed197f59a2": "comando copiar",
+ "817d3f9f18": "Copiar comando de instalación",
+ "5289300939": "No instalado",
+ "9fcebceb2a": "Instalado",
+ "68a468752e": "De cheques...",
+ "c689392435": "Vuelva a comprobar",
+ "a31e2aa302": "No se pudo copiar el comando de instalación.",
+ "378ad26865": "Comando de instalación copiado."
+ },
+ "AgentsPane": {
+ "d83834f5e6": "Detectando agentes instalados…",
+ "024bd95089": "agentes",
+ "e8da2af684": "Disponible para instalar",
+ "ed3e110e61": "detectado",
+ "02e0143be5": "Instalado",
+ "110b74b022": "Sin agente (terminal en blanco)",
+ "92033495ff": "Auto",
+ "9b175d0f5e": "Agente preseleccionado al abrir un nuevo espacio de trabajo.",
+ "385212c7a1": "Agente predeterminado",
+ "f9f127d664": "Anule la ruta binaria o el nombre utilizado para iniciar este agente.",
+ "f95b5c79b8": "Instalar",
+ "fe4d630c94": "Documentos",
+ "8dc0192e48": "Desactivado",
+ "df123171d1": "No instalado",
+ "c8794e622e": "Detectado",
+ "5200dac9da": "Reiniciar",
+ "2e45ca29b6": "Dominio",
+ "d4d2a45d63": "Activado",
+ "1c9a9679ec": "{{value0}} disponibilidad",
+ "0d9e293a02": "Refrescar",
+ "c9b33eb5c0": "Refrescante…",
+ "13647f9f80": "Vuelva a leer la RUTA de su shell y vuelva a detectar los agentes instalados",
+ "dc4a2ffdc0": "Ampliar anulación del comando",
+ "cea7d97be1": "Anulación del comando Contraer",
+ "db9e9e5887": "Personalizar comando",
+ "959b67385b": "Establecer predeterminado",
+ "24e032fa34": "Por defecto",
+ "5f986a9b92": "Establecer como predeterminado",
+ "d7625cf8b2": "Agente predeterminado"
+ },
+ "AppIconSelector": {
+ "d5a112dc9b": "Icono siguiente",
+ "415fa76f64": "Icono de aplicación seleccionada",
+ "5f5142a62a": "Icono anterior"
+ },
+ "AppearancePane": {
+ "3057983501": "No asignado",
+ "0cd9b8228f": "Elija el ícono de la aplicación que se muestra en el Dock y en el selector de ventanas.",
+ "ca1590d42f": "Icono de aplicación",
+ "61d842eca0": "Muestra el acceso directo de Orca Mobile en la barra lateral. Sigue estando disponible en Toolbox.",
+ "9da1020447": "Mostrar botón móvil de Orca",
+ "5db6ba961f": "Muestra el botón de Orca Mobile en la parte superior de la barra lateral izquierda.",
+ "fa882a3e6b": "Muestra el botón Automatizaciones en la parte superior de la barra lateral izquierda.",
+ "511f270ebb": "Botón Mostrar automatizaciones",
+ "661942ab7f": "Muestra el botón Tareas en la parte superior de la barra lateral izquierda.",
+ "cf81907069": "Botón Mostrar tareas",
+ "dc29f3cc0d": "Barra lateral",
+ "ea943d0db0": "Elija qué indicadores aparecen en la parte inferior de la ventana. También puede hacer clic derecho en la barra de estado para los mismos cambios.",
+ "3e4175e5c6": "Barra de estado",
+ "2df8f79aa5": "Muestra Orca en la barra de título.",
+ "9868f39007": "Nombre de la aplicación de la barra de título",
+ "4de76f6902": "Controla lo que aparece en la barra de título de la aplicación.",
+ "6a272ca553": "Barra de título",
+ "e9f2ca5582": "Desactívelo para ocultar archivos que coincidan con .gitignore desde el explorador de archivos.",
+ "0fafabcf35": "Mostrar archivos ignorados por Git",
+ "75f07ab60c": "Mostrar archivos que coincidan con .gitignore en el explorador de archivos.",
+ "d496901cd0": "Explorador de archivos",
+ "42554f615f": "Elija la fuente utilizada por la interfaz de Orca.",
+ "102d6b5f9b": "Fuente IDE",
+ "ef89200c1f": "cuando no está en un panel de terminal.",
+ "f687711a9b": "Escale toda la interfaz de la aplicación. Usar",
+ "5e6d7aba8d": "Ampliación de la interfaz de usuario",
+ "622e1c3465": "Escale toda la interfaz de la aplicación.",
+ "fd89b5487c": "Luz",
+ "7d26ccabe8": "Oscuro",
+ "fb0e0b4453": "Sistema",
+ "932ff1fbff": "Tema",
+ "0f28e7b30c": "Elige cómo se ve Orca en la ventana de la aplicación."
+ },
+ "AutoRenameBranchFromWorkSetting": {
+ "1626524572": "Nautilus",
+ "0de9fda203": "Desechar",
+ "c71770c455": "{basePrompt}",
+ "f19a56498d": "; la configuración del prefijo de rama aún se aplica.",
+ "800edb1e54": "arreglar-flujo-de-inicio de sesión",
+ "5d569f5199": ". Orca genera sólo el segmento final, como",
+ "570817d126": "y",
+ "56580dcf60": ". También puedes hacer referencia",
+ "9c9b54e4ea": "mensaje de nombre de rama incorporado",
+ "69bf4830c2": "para incluir a Orca",
+ "9241b59bf5": "Usar",
+ "a869d0edd8": "Plantilla de comando de nombre de sucursal",
+ "e784ea62dc": "Avanzado",
+ "d9b65054ef": ") a un nombre corto que resume la tarea. Sólo se cambia el nombre de las ramas que Orca nombró a sí misma, y nunca después de haber sido empujadas.",
+ "12ea4a408d": "Cuando un agente comienza a trabajar en un nuevo espacio de trabajo, Orca cambia el nombre de su rama generada automáticamente (p. ej.",
+ "ef787db0e3": "Rama de cambio de nombre automático",
+ "6a051586d2": "Cambie el nombre de la rama generada automáticamente según el trabajo una vez que comience un agente.",
+ "ec3e0c388e": "Ahorrar",
+ "cfd82406dd": "Ahorro...",
+ "40e7be7850": "Guardado",
+ "7c7e34a66d": "Cambios no guardados",
+ "a4fa380b67": "{mensaje del asistente}",
+ "2ee2779c05": "{primer mensaje}"
+ },
+ "AutoRenameBranchPromptEditor": {
+ "63121132c0": "Desechar",
+ "4416b25d29": "Prefiera nombres de dominio de la tarea, evite los ID de ticket y mantenga los nombres fáciles de usar para los revisores.",
+ "39278f4411": "; la configuración del prefijo de rama aún se aplica.",
+ "ebb942a2ec": "arreglar-flujo-de-inicio de sesión",
+ "af2d9a2cc6": ". Orca genera sólo el segmento final, como",
+ "182d419b97": "mensaje de nombre de rama incorporado",
+ "2f5dc661fe": "Adjunto a Orca",
+ "7d6176f506": "Inmediato",
+ "5968112152": "Ahorrar",
+ "54ac229ad4": "Ahorro...",
+ "af0831a590": "Guardado",
+ "0691753cf2": "Cambios no guardados"
+ },
+ "BaseRefPicker": {
+ "1b8e54151f": "No se encontraron sucursales coincidentes.",
+ "d166ff883d": "Actual",
+ "a4a9372eb2": "Buscando sucursales...",
+ "7db7fb87e5": "Buscar sucursales por nombre...",
+ "773a5687a3": "Usar primario",
+ "ade9a5bb03": ") para determinar el alcance de los resultados.",
+ "b468f46726": "aguas arriba/principal",
+ "80f7c82303": ") o una referencia completa (p. ej.",
+ "915ad97875": "río arriba",
+ "a5c16712c1": "Se detectaron varios controles remotos. Escriba un nombre remoto (p. ej.",
+ "9a14ec7400": "Elija una rama base a continuación",
+ "086ce7f369": "Siguiente rama principal ({{value0}})",
+ "2f3cda96f5": "Fijado para este repositorio",
+ "ee110e1830": "Sin referencia base predeterminada"
+ },
+ "BrowserDefaultZoomSetting": {
+ "2622126877": "Nivel de zoom aplicado a las pestañas del navegador recién abiertas.",
+ "bbeec087d3": "Se aplica a las pestañas del navegador recién abiertas.",
+ "265597101f": "Zoom predeterminado"
+ },
+ "BrowserHomePageSetting": {
+ "d4ddcd0056": "Ahorrar",
+ "37a30c5bfd": "https://google.com",
+ "c6cbd1c105": "Página de inicio guardada.",
+ "6a37540f4b": "URL abierta al crear una nueva pestaña del navegador. Déjelo vacío para abrir una pestaña en blanco.",
+ "70224e37b1": "Página de inicio predeterminada"
+ },
+ "BrowserPane": {
+ "81ff774667": "Cancelar",
+ "7d4c0a2aa4": "Nombre del perfil",
+ "612f7f6861": "No se pudo crear el perfil.",
+ "8f22b7580d": "Perfil \"{{value0}}\" creado.",
+ "8481ee0331": "Nuevo perfil del navegador",
+ "6f2584b39e": "Agregar perfil",
+ "e4aaf8051b": "menú de la barra de herramientas.",
+ "cd47bc9622": "Seleccione un perfil predeterminado para las nuevas pestañas del navegador. Importe cookies y cambie perfiles por pestaña a través del",
+ "2d66a6efb5": "Sesión y cookies",
+ "aa1074bfe9": "Administre perfiles de navegador e importe cookies desde Chrome, Edge, Comet u otros navegadores.",
+ "113cd2dc9b": "Sesión y cookies",
+ "d3eb69c0aa": "Enrutamiento de enlaces",
+ "3e46903ad4": "Se utiliza al escribir texto que no es una URL en la barra de direcciones.",
+ "0d9c987f21": "Motor de búsqueda predeterminado",
+ "7b225c78f5": "Motor de búsqueda utilizado al escribir texto que no es una URL en la barra de direcciones.",
+ "64898ecdab": "Crear",
+ "7b649a578a": "Creando…",
+ "4399c77caa": "Por defecto",
+ "4af9a17947": "kagi"
+ },
+ "BrowserProfileRow": {
+ "8e636cae25": "Perfil \"{{value0}}\" eliminado.",
+ "2d4bea7f35": "Se borraron las cookies predeterminadas.",
+ "ebb78dfd6f": "Desde archivo…",
+ "7df818977e": "De",
+ "cdec84552f": "Importar cookies",
+ "796d846483": "No se importan cookies",
+ "c29648fe5b": "Activo",
+ "d420c43729": "Se importaron {{value0}} cookies de {{value1}}{{value2}} a {{value3}}.",
+ "b4c167764d": "Se importaron {{value0}} cookies del archivo a {{value1}}.",
+ "a3f8c2d1e0b4": "Se importaron {{value0}} cookies de {{value1}} ({{value2}}) a {{value3}}.",
+ "b4e9d3f2a1c5": "Se importaron {{value0}} cookies de {{value1}} a {{value2}}."
+ },
+ "BrowserUseComputerUseNotice": {
+ "15b5e680ba": "Uso abierto de la computadora",
+ "79209b37b9": "Si la importación de cookies no es la opción adecuada, Uso de la Computadora puede controlar las aplicaciones locales y puede utilizar sesiones de navegador existentes cuando corresponda. Instale la habilidad Uso de computadora; macOS también requiere permisos de privacidad.",
+ "333984cf90": "Utilice una sesión de navegador existente"
+ },
+ "BrowserUseEnableSwitch": {
+ "aea3f45349": "Habilitar el uso del navegador del agente"
+ },
+ "BrowserUseExamples": {
+ "1199258ace": "Copiar",
+ "1188e56af4": "Copiar mensaje de ejemplo",
+ "b84807f228": "\"",
+ "59722f31b4": "\"",
+ "c5325e91f6": "Pegue cualquiera de estos en Claude Code, Codex u otro agente en un proyecto donde esté instalada la habilidad.",
+ "2a180694f7": "Pruébelo: indicaciones de ejemplo",
+ "5ec620ccc4": "No se pudo copiar.",
+ "a602d43069": "Copiado {{value0}}."
+ },
+ "BrowserUsePane": {
+ "be6df68384": "Desde archivo…",
+ "e44c5d681e": "De",
+ "67d9a53f47": "Administrar perfiles para inicios de sesión separados",
+ "112f70adc4": "Última importación desde",
+ "72d4815523": "Incorpore sus inicios de sesión existentes a Orca para que los agentes puedan acceder a páginas autenticadas. Importa al perfil predeterminado.",
+ "2eb906706c": "Importar cookies del navegador",
+ "af8c83ed61": "Importe cookies de Chrome, Edge u otros navegadores para que los agentes puedan reutilizar sus inicios de sesión.",
+ "68ea76eb71": "Instale la habilidad Uso del navegador para que los agentes puedan operar el navegador de Orca.",
+ "2d6ead9ab2": "Instalar la habilidad de uso del navegador",
+ "e9f3f3b488": "Instalado en",
+ "9fca1f7f5d": "Registra el comando CLI de Orca para que los agentes puedan organizar el navegador desde su shell.",
+ "c6065d205d": "Habilitar CLI de Orca",
+ "c79eff0213": "Registre la CLI de Orca para que los agentes puedan controlar el navegador.",
+ "702488a5f7": "Deje que los agentes de codificación controlen este navegador con sus inicios de sesión. Complete los tres pasos siguientes.",
+ "b8a1f2d84d": "Uso del navegador del agente",
+ "96b91c6349": "Deje que los agentes de codificación controlen este navegador con sus inicios de sesión.",
+ "2ea4617e3a": "Se importaron {{value0}} cookies de {{value1}}{{value2}}.",
+ "721aee31b4": "Registré Orca CLI en PATH.",
+ "180a9abf3a": "No se pudo cargar el estado de CLI.",
+ "2ccfc9cff8": "Importar",
+ "0462565413": "Reimportar",
+ "de9b2f32f3": "Permitir",
+ "ad8cb0ee22": "Arreglar RUTA",
+ "0289434ed6": "Activado",
+ "8b3054dac7": "Registrando...",
+ "8f2675c2f3": "Se importaron {{value0}} cookies del archivo."
+ },
+ "BrowserUseSkillStep": {
+ "0871b6998d": "Permite a los agentes navegar y verificar páginas en el navegador de Orca.",
+ "459e24eebc": "Habilidad de uso del navegador"
+ },
+ "CliSection": {
+ "8671e406f0": "Cancelar",
+ "a4aafe46e3": "Ruta de destino:",
+ "e8012c03a1": "Permite a los agentes utilizar el espacio de trabajo, la terminal y los comandos de progreso de Orca.",
+ "6053cf736c": "Habilidad CLI",
+ "36a6f919ba": "Ofrezca a los agentes espacios de trabajo, terminales y flujos de trabajo de progreso compatibles con Orca.",
+ "04873eea3e": "Habilidades del agente",
+ "7f2747f7dd": "Actualmente no está visible en PATH para este shell.",
+ "b0c310ab46": "Objetivo del lanzador existente:",
+ "15eaad0d31": "Ruta de comando:",
+ "5dae812f50": "Refrescar",
+ "52e640f3a0": "Actualizar el estado de la CLI",
+ "38edbb5721": "Comando de shell",
+ "6930feda9e": "Utilice Orca desde su terminal para abrir la aplicación, administrar árboles de trabajo e interactuar con los terminales Orca.",
+ "c5c0f2641d": "CLI de Orca",
+ "d77352f2df": "No se pudo eliminar `{{value0}}` de PATH.",
+ "af5540930c": "Se eliminó `{{value0}}` de RUTA.",
+ "a2b13efa94": "No se pudo registrar `{{value0}}` en PATH.",
+ "9cbcd31338": "Registrado `{{value0}}` en PATH.",
+ "7baec27029": "No se pudo cargar el estado de CLI.",
+ "d00df2e397": "Registro",
+ "9a5f8a4568": "Eliminar",
+ "b0fca411a0": "Registrándose…",
+ "4c7e3e4c5f": "instalar",
+ "068552b191": "Eliminando…",
+ "8d96213669": "eliminar",
+ "aa6536977e": "Orca registrará {{value0}} para que el comando funcione desde su terminal.",
+ "a030816e3e": "Esto elimina el enlace simbólico del comando Shell. La propia Orca permanece instalada.",
+ "fa87db3d6e": "¿Registrar `{{value0}}` en PATH?",
+ "14444243ba": "¿Eliminar `{{value0}}` de RUTA?",
+ "5d432fe44d": "instalado",
+ "8a9b784c60": "duro",
+ "d363e5929b": "Comprobando el registro CLI..."
+ },
+ "CliSkillRuntimeSetup": {
+ "04325573f8": "WSL",
+ "a58ba464ad": "Ubicación de la habilidad",
+ "0ed08febc5": "No se pudo registrar el comando de shell WSL.",
+ "3728a94fb6": "El comando de shell WSL necesita atención",
+ "775a4cfbb8": "El registro del comando de shell WSL no está disponible",
+ "c47127f222": "WSL predeterminado",
+ "0c9f3cf9da": "Elija dónde Orca verifica e instala las habilidades de los agentes globales.",
+ "f00d6aa9b5": "WSL no está disponible en esta máquina.",
+ "7c776ff9d8": "wsl",
+ "fc0fcf72fd": "Registre el comando de shell WSL antes de configurar la habilidad."
+ },
+ "CommitMessageAiPane": {
+ "841ed9884a": "Utilizado por repositorios que no han personalizado Source Control AI.",
+ "ad66ff886d": "Valores predeterminados de IA de control de fuente",
+ "347094560b": "Utilizado por repositorios que heredan los valores predeterminados globales de revisión alojada.",
+ "2dafc7646e": "Valores predeterminados de creación de reseñas alojadas",
+ "e9d46a544d": "Valores predeterminados utilizados cuando se abre el redactor de reseñas alojadas.",
+ "b125eabffa": "Abra la reseña alojada creada en su navegador después de enviarla.",
+ "7662715213": "Abrir revisión alojada después de la creación",
+ "b27b0809f3": "Ejecute la generación de detalles de revisión alojada una vez cuando se abra el compositor.",
+ "d5f0de6309": "Generar detalles al abrir Crear PR",
+ "6278c0ce43": "Prefiere las plantillas de solicitud de extracción del repositorio cuando no se establece ninguna descripción.",
+ "d8b6764d79": "Utilice la plantilla de revisión cuando esté disponible",
+ "e001734396": "Cree reseñas alojadas como borradores a menos que se modifiquen en el compositor.",
+ "6ba48f07a4": "Borrador por defecto",
+ "15b60d54b2": "p.ej. ollama ejecuta llama3.1 {rápido}",
+ "3f1b26cc91": "pasar la entrada del comando como argumento; de lo contrario, Orca lo canaliza en stdin.",
+ "4f722a5f53": "Usado por recetas de mensaje de confirmación, solicitud de extracción y nombre de rama que seleccionan el comando Personalizado. Usar",
+ "47e45cbd5a": "Comando personalizado",
+ "1ef29f8c29": "Línea de comando Orca se ejecuta cuando una receta de texto usa un comando personalizado.",
+ "2339a89104": "Agrega botones AI que ejecutan el agente seleccionado con la plantilla de comando para esa acción.",
+ "d5b45a3628": "Mostrar acciones de IA de control de código fuente",
+ "7bcad2b200": "Agrega recetas de acciones para acciones de confirmación de control de código fuente, solicitud de extracción, nombre de rama y reparación.",
+ "d54c64163d": "activado",
+ "4ec89c319e": "agente",
+ "34d0348e34": "generar",
+ "8cd2be0948": "mensaje",
+ "ca433708cb": "comprometerse",
+ "0b7eafe55f": "ai",
+ "2c5436c018": "abierto",
+ "6c84ba6de3": "plantilla",
+ "ebed4d2a29": "borrador",
+ "02bab6542c": "pr",
+ "fdee745b87": "solicitud de fusión",
+ "b388463881": "solicitud de extracción",
+ "19e10a12bb": "revisión alojada",
+ "b8b6fd55b4": "{inmediato}",
+ "fc1a525fa5": "marcador de posición",
+ "a69e1fe91a": "inmediato",
+ "1df7d71313": "binario",
+ "407d28bde6": "cli",
+ "54038660e0": "dominio",
+ "25350d670f": "costumbre"
+ },
+ "ComputerUsePane": {
+ "1735461723": "Permite a los agentes inspeccionar y operar aplicaciones de escritorio locales.",
+ "93255aaf18": "Habilidad de uso de computadora",
+ "45f8e22c2e": "Abierto",
+ "d95d1cfab8": "Refrescar",
+ "0c29da5805": "Listo",
+ "3383ea1aab": "No se pudieron restablecer los permisos de uso de la computadora",
+ "f189f448a3": "Restablecer el acceso al uso de la computadora",
+ "5c45349665": "No se pudieron abrir los permisos de uso de la computadora",
+ "7801ac08ec": "Los permisos de uso de computadora solo se requieren en macOS",
+ "740766c291": "La configuración de uso de la computadora ya está completa",
+ "697005758f": "Privacidad y seguridad de macOS abiertas",
+ "2168fa5ab0": "No se pudieron cargar los permisos de uso de la computadora",
+ "0c9a33f468": "Capture ventanas de aplicaciones para que los agentes puedan inspeccionar el estado visual.",
+ "07bbe4c4cb": "Capturas de pantalla",
+ "4d03dec2d0": "Lea los árboles de la interfaz de la aplicación y realice las acciones solicitadas.",
+ "6b5a2cd3a5": "Accesibilidad",
+ "6b17602073": "Restablecer acceso",
+ "506f2acf7a": "Restableciendo acceso...",
+ "4b65070096": "darwin"
+ },
+ "DeveloperPermissionsPane": {
+ "4c17304beb": "Refrescar",
+ "6326a4c5cc": "Utilice estos controles cuando una CLI, una aplicación local o una herramienta de automatización necesiten acceso privado a macOS. Orca no pregunta al inicio.",
+ "6f011b9bf6": "Las herramientas de terminal heredan la envoltura de privacidad de macOS de Orca.",
+ "bfa3402305": "No se pudo solicitar permiso",
+ "66e94d6cf3": "Solicitud de permiso enviada",
+ "fa809e8ada": "Privacidad y seguridad de macOS abiertas",
+ "48d87edcd2": "Permiso concedido",
+ "a552887288": "No se pudieron cargar los permisos de desarrollador",
+ "4cfaa7e98a": "Herramientas de dispositivos Bluetooth y experimentos de hardware local.",
+ "b2210b1b4f": "bluetooth",
+ "dfbc12c8c8": "Herramientas de dispositivos y depuración de hardware que se comunican con dispositivos USB.",
+ "bf51e4a542": "Dispositivos USB",
+ "f903bf20b5": "Descubrimiento y acceso a servidores de desarrollo en su red.",
+ "e7bb06007c": "Red Local",
+ "4a73f5217a": "Apple Events para scripts que controlan otras aplicaciones locales.",
+ "e119f0d66b": "Automatización",
+ "7ca17b62c8": "Acceso persistente a carpetas protegidas desde sesiones de terminal.",
+ "c566bca278": "Acceso completo al disco",
+ "9f35980756": "Herramientas de inyección de pulsaciones de teclas, control de ventanas y automatización de UI.",
+ "5b2f22ca2d": "Accesibilidad",
+ "0639db5496": "Herramientas de captura de pantalla, automatización visual y inspección de la interfaz de usuario.",
+ "f24f31a884": "Grabación de pantalla",
+ "550cfa3750": "Captura de cámara web y aplicaciones de prueba locales controladas por cámara.",
+ "e5b5f3d6b9": "Cámara",
+ "cc8151d9fa": "Entrada de voz, transcripción, grabación de audio, sox, ffmpeg y CLI Whisper.",
+ "16381e040a": "Micrófono",
+ "dac08ec03e": "Laboral..."
+ },
+ "ExperimentalPane": {
+ "9762364929": "Permite enlaces simbólicos automáticos de ciertas carpetas o archivos que deben conectarse a los árboles de trabajo creados.",
+ "24416f42cd": "Enlaces simbólicos en árboles de trabajo",
+ "fb82ea1d7a": "Vincula automáticamente archivos o carpetas configurados en árboles de trabajo recién creados.",
+ "a20d5ea365": "Mantiene visible un resaltado a nivel de panel después de que suena la terminal o los eventos de finalización del agente hasta que interactúa con ese panel. Experimental mientras sintonizamos la señal.",
+ "ec897e8d89": "Atención terminal",
+ "88b7613afb": "Resaltado de panel persistente para eventos de finalización de agente y timbre de terminal.",
+ "0277901cf7": "Agrega una entrada de Agentes a la barra lateral izquierda con una fuente de árbol de trabajo encadenada para agentes completados, preguntas de bloqueo, estado no leído y eventos de creación de árbol de trabajo. Experimental: el modelo de evento y la interfaz de usuario pueden cambiar.",
+ "a05bcdaf57": "Vista de agentes",
+ "f63ea281e3": "Feed integrado en la barra lateral izquierda para completar agentes y estados de bloqueo.",
+ "ca2219fe5e": "Muestra una pequeña mascota animada fijada en la esquina inferior derecha. Elige un personaje (Claudino, OpenCode, Gremlin) o carga tu propio PNG, APNG, GIF, WebP, JPG o SVG desde el menú de mascotas de la barra de estado. Ocultarlo en cualquier momento desde el mismo menú sin desactivar esta configuración.",
+ "dd6f0a1d45": "Mascota",
+ "0e89a574ae": "Mascota animada flotante en la esquina inferior derecha."
+ },
+ "FloatingWorkspacePane": {
+ "aeaf76fda9": "Barra de estado",
+ "9fb225f2d7": "Botón flotante",
+ "3c900e26e5": "El método abreviado de teclado funciona independientemente de dónde se muestre el interruptor.",
+ "5e5a8da236": "Ubicación del botón de alternancia",
+ "505001823e": "Elija el directorio del espacio de trabajo flotante",
+ "81afb79785": "Las nuevas pestañas de terminal flotante comienzan aquí. Las notas de Markdown se guardan en el espacio de trabajo flotante propiedad de la aplicación de Orca.",
+ "12aa09f10c": "Directorio de terminales",
+ "41eb95f7f0": "Muestra el botón y el panel del espacio de trabajo flotante.",
+ "5136813663": "Habilitar espacio de trabajo flotante",
+ "37df688d6f": "Habilite el espacio de trabajo flotante y elija dónde comienzan las nuevas pestañas.",
+ "1f67f39384": "Espacio de trabajo flotante"
+ },
+ "GeneralCacheTimerSection": {
+ "05de84a104": "1 hora",
+ "54395ecd7c": "5 minutos",
+ "8b9e202e0a": "Haga coincidir esto con el TTL de caché de su proveedor. El valor predeterminado es 5 minutos.",
+ "a2a8962138": "Duración del temporizador",
+ "b4e7302944": "Temporizador de caché",
+ "487b176240": "Muestra una cuenta regresiva en la barra lateral después de que un agente de Claude quede inactivo.",
+ "9c20253679": "Muestra una cuenta regresiva después de que un agente de Claude quede inactivo.",
+ "fe590653c1": "Claude almacena en caché su conversación para reducir costos. Cuando está inactivo durante demasiado tiempo, la memoria caché caduca y el siguiente mensaje reenvía el contexto completo a un costo mayor. Esto muestra una cuenta atrás para que sepas cuándo reanudar.",
+ "a137f8854d": "Temporizador de caché rápido",
+ "80c454e8a6": "Haga coincidir esto con el TTL de caché de su proveedor."
+ },
+ "GeneralEditorSettingsSection": {
+ "f80603d293": "Muestre controles de notas de rebajas locales en modo de editor enriquecido y acciones de transferencia de agentes.",
+ "4edc104f0f": "Notas de revisión de rebajas",
+ "5f02e6fb21": "Muestre los controles de notas de revisión de rebajas locales en el modo de editor enriquecido.",
+ "51161d1647": "Muestra la descripción general del minimapa al editar un archivo.",
+ "6690b1ffb9": "Minimapa",
+ "5a1ea6eaa2": "Oculto",
+ "73a09aad63": "Mostrado",
+ "1de48ad940": "Árbol de archivos de diferencias predeterminado",
+ "1b87897af9": "Muestre u oculte el árbol de archivos al abrir vistas de diferencias combinadas.",
+ "12cbc0d0d6": "Lado a lado",
+ "05b6df93b3": "En línea",
+ "7311f67ee7": "Vista de diferencias predeterminada",
+ "b492397d34": "Formato de presentación preferido para mostrar diferencias de git de forma predeterminada.",
+ "a5db1d3975": "EM",
+ "fc5c5306ff": "EM.",
+ "8112cd6dcf": "Cuánto tiempo espera Orca después de su última edición antes de guardar automáticamente. El primer lanzamiento predeterminado es",
+ "d6cf227ca0": "Retraso de guardado automático",
+ "1bec6d8318": "Cuánto tiempo espera Orca después de su última edición antes de guardar automáticamente.",
+ "70bb30feb1": "Guarde el editor y los cambios de diferencias editables automáticamente después de una breve pausa.",
+ "0df2e4fd12": "Guardar archivos automáticamente",
+ "d21136d9ef": "Configure cómo Orca persiste en las ediciones de archivos.",
+ "45c6e85c4d": "Editor"
+ },
+ "GeneralNetworkSettingsSection": {
+ "3e431564b5": "host local, 127.0.0.1, *.interno",
+ "33ee3ca3af": "Opcional. Separe los hosts con comas, punto y coma o líneas nuevas.",
+ "f6d76cc8f4": "Reglas de omisión de proxy",
+ "fb7130dcb9": "Hosts que deberían omitir el proxy HTTP configurado.",
+ "0adfce9fa7": "Admite URL http, https, calcetines, calcetines4 y calcetines5.",
+ "476f302aca": "http://proxy.example.com:8080",
+ "1e214e265a": "Déjelo vacío para usar la configuración del proxy del sistema y las variables de entorno del proxy heredadas.",
+ "f00daf6324": "Proxy HTTP",
+ "823e0f15b1": "URL proxy para solicitudes de red Orca y terminales secundarios locales.",
+ "d93c7cd531": "Configure el enrutamiento de red a nivel de aplicación.",
+ "c46cdbbd4e": "Red"
+ },
+ "GeneralPane": {
+ "d58fccfd84": "Navegación"
+ },
+ "GeneralSupportSection": {
+ "af7d9f4396": "¡Gracias por el apoyo!",
+ "6922c1fa2b": "Orca estrella en GitHub",
+ "511782265b": "Apoye el proyecto con una estrella de GitHub a través de la CLI de gh.",
+ "55a87e5fd1": "Apoya a la Orca",
+ "964acc6bb4": "Estrella",
+ "73b327e793": "Intentar otra vez",
+ "c9f96d4234": "error",
+ "397719bee5": "Protagonizada...",
+ "1e29570462": "protagonizada",
+ "9d181300e3": "sembrado de estrellas",
+ "5c49f02662": "oculto",
+ "b3f0584f5d": "cargando"
+ },
+ "GeneralUpdateSettingsSection": {
+ "8a52ca1d02": "Notas de la versión",
+ "d89806cc89": "está listo para instalar.",
+ "a6b37929dc": "Versión",
+ "8311da27ba": "está disponible. Haga clic en \"Instalar actualización\" para descargarla e instalarla.",
+ "f44299636f": "Reiniciar para actualizar (",
+ "42717918f4": "Instalar actualización (",
+ "02dc082e70": "No se pudo iniciar la descarga de la actualización.",
+ "e1a647adc5": "Buscar actualizaciones",
+ "ceb579abaf": "Busque actualizaciones de la aplicación e instale una versión más reciente de Orca.",
+ "d91ebfb87e": "Versión actual: {{value0}}",
+ "f2b1ccc12a": "Actualizaciones",
+ "bd79d412f0": "La verificación de actualización falló. {{value0}}",
+ "b9ad70c30d": "Error de actualización. {{value0}}",
+ "6405510b92": "error",
+ "a0832ccdb1": "descargado",
+ "2a48034c4c": "Descargando v{{value0}}... {{value1}}%",
+ "4c1c001813": "descargando",
+ "f40d88390d": "Estás en la última versión.",
+ "90eb7309d7": "No disponible",
+ "82465b2444": "disponible",
+ "31fd7150cf": "Buscando actualizaciones...",
+ "3394d1f663": "de cheques",
+ "d69a09b672": "Las actualizaciones se verifican automáticamente al iniciarse.",
+ "7173352632": "idle"
+ },
+ "GeneralWorkspaceSettingsSection": {
+ "3d538a98f7": "Elija las aplicaciones disponibles en el menú Abrir en de un espacio de trabajo.",
+ "008f92085f": "Abrir en aplicaciones",
+ "824b98a0d9": "Muestra una confirmación antes de eliminar automatizaciones y su historial de ejecución.",
+ "ea98373cd8": "Pregunte antes de eliminar automatizaciones",
+ "d2dd2ca2e3": "Muestra un cuadro de diálogo de confirmación antes de eliminar una automatización y su historial de ejecución.",
+ "28bc3d085e": "Muestra una confirmación antes de eliminar un espacio de trabajo del menú contextual. Las eliminaciones fallidas aún muestran un recurso de Forzar eliminación.",
+ "9f380934cf": "Preguntar antes de eliminar espacios de trabajo",
+ "5734db82af": "Muestra un cuadro de diálogo de confirmación antes de eliminar un espacio de trabajo.",
+ "4fbf910ded": "Cree espacios de trabajo dentro de una subcarpeta con nombre de repositorio.",
+ "ba3480642f": "Espacios de trabajo anidados",
+ "a246f5ce6f": "Directorio raíz donde se crean las carpetas del espacio de trabajo.",
+ "5567191a6e": "Navegar",
+ "0e9fc0eadc": "Directorio de espacio de trabajo",
+ "e2955d9ccb": "Configure dónde se crean nuevos espacios de trabajo.",
+ "7511097c5d": "Espacio de trabajo"
+ },
+ "GhosttyImportModal": {
+ "9d3e56ca36": "Aplicar cambios",
+ "f96688b6bc": "Cancelar",
+ "b7ddae600c": "Hecho",
+ "e4bda7ce6f": "No se encontró ninguna configuración de Ghostty en este sistema.",
+ "b58d4c9051": "Claves no compatibles",
+ "674b5ccd6b": "No hay nuevas configuraciones para importar: su configuración actual ya coincide.",
+ "a4c5dec640": "Configuraciones para actualizar",
+ "4466f4cdaa": "Importación completa",
+ "023a52c1f7": "Cargando vista previa…",
+ "2763b0c045": "Revise la configuración que se importará desde su configuración de Ghostty.",
+ "d2f33670a9": "Importar desde Ghostty",
+ "273e7e81fe": "Configuraciones",
+ "1f744a72f4": "configuración"
+ },
+ "GitPane": {
+ "d2eede4c54": "Agregue la atribución de Orca a confirmaciones, relaciones públicas y problemas.",
+ "e02ea23a32": "Atribución de Orca",
+ "e71ce09c42": "orca",
+ "b9b5771bb1": "atribución",
+ "b5f534717a": "coautor",
+ "9838c921ed": "coautor",
+ "afada55042": "asunto",
+ "b4ef5428a7": "pr",
+ "895d3f70b8": "gh",
+ "32dca11189": "github",
+ "c4f610d057": "Encabezados de límite de velocidad REST de GitLab CLI actuales cuando estén disponibles.",
+ "0de4ae556c": "Presupuesto de la API de GitLab",
+ "cdd793134e": "presupuesto API",
+ "b9c011fbc2": "límite de tasa",
+ "3072428ac7": "glabro",
+ "8a527d48e3": "gitlab",
+ "aa204f185f": "Límites de velocidad actuales de GitHub CLI REST, Search y GraphQL.",
+ "612a440e57": "Presupuesto de la API de GitHub",
+ "2cde9044a8": "graficoql",
+ "36e3de3619": "de comparar con la historia obsoleta. Orca omite la actualización si esa rama tiene cambios no confirmados o confirmaciones solo locales.",
+ "d072a12995": "git diff principal...CABEZA",
+ "db3a127eb1": ". Esto mantiene comandos como",
+ "3ae3de8898": "maestro",
+ "5bf885be48": "o",
+ "ffba483bae": "principal",
+ "976afc6b3e": "Cuando crea un espacio de trabajo, Orca actualiza la base remota y adelanta de forma segura su sucursal local coincidente, como",
+ "1ec5c91e1d": "Elija si los nombres de las ramas usan su nombre de usuario de Git, un prefijo personalizado o ningún prefijo.",
+ "330f584b50": "Prefijo de rama",
+ "1ffaadf0a0": "Prefijo agregado a los nombres de las ramas al crear árboles de trabajo.",
+ "813e15b346": "costumbre",
+ "2351aa5a31": "nombre de usuario git",
+ "cc63fce906": "denominación de sucursales",
+ "b559bf9899": "p.ej. característica",
+ "aefa1ecb59": "No hay ningún nombre de usuario de git configurado",
+ "f35007e6e8": "nombre de usuario git",
+ "3d172725cc": "Ninguno",
+ "1f32ba27a6": "Costumbre",
+ "a182c5125e": "Nombre de usuario"
+ },
+ "HiddenExperimentalGroup": {
+ "d0f914a528": "Alternar marcador de posición",
+ "1014ddbfaf": "No hace nada hoy. Reservado como primer espacio para opciones experimentales ocultas.",
+ "232cf83de8": "Alternadores no listados para pruebas internas. Aquí no se admite nada.",
+ "3e9e827ca5": "experimental oculto"
+ },
+ "InputPane": {
+ "db15068196": "Habilitado de forma predeterminada en Linux y macOS. Linux usa el portapapeles de selección del sistema; otras plataformas utilizan un búfer privado.",
+ "ad31c3c5fb": "Haga clic con el botón central en Pegar desde la selección"
+ },
+ "IntegrationsPane": {
+ "2122e15517": "Cada espacio de trabajo Linear conectado tiene una clave almacenada por el tiempo de ejecución activo. Las claves de acceso total pueden cubrir todos los equipos a los que puede acceder el propietario de la clave; Las claves restringidas se pueden reemplazar en cualquier momento.",
+ "e7b2dd46f9": "Pruebas…",
+ "fe4d378dc4": "Verificado",
+ "f5c5246514": "Agregar acceso Linear",
+ "6432f6522e": "Conectado",
+ "077844591a": "Agregar acceso al espacio de trabajo",
+ "264a9b6128": "Linear",
+ "4831ba1083": "Vuelva a comprobar",
+ "01f6c7582e": "Más información",
+ "1a62c295c6": "Las credenciales de Gitea están configuradas pero no se pudieron autenticar. Verifique el token, la URL base de la API y los permisos del repositorio, luego reinicie Orca si las variables de entorno cambiaron.",
+ "5a1f86225a": "sólo cuando Orca no puede derivar la URL de la API desde el control remoto.",
+ "6193444689": "ORCA_GITEA_API_BASE_URL",
+ "2c0330ec3e": "para repositorios privados y establecer",
+ "e678d89e8c": "ORCA_GITEA_TOKEN",
+ "d9467ab026": "Los repositorios públicos se detectan desde su control remoto git. Colocar",
+ "4ab9b96925": "casa rural",
+ "953b7bf6f7": "Las credenciales de Azure DevOps están configuradas pero no se pudieron autenticar. Verifique el token, la URL base de la API y los permisos del repositorio, luego reinicie Orca si las variables de entorno cambiaron.",
+ "6f317f5132": "solo cuando Orca no puede derivar la URL base de la API desde el control remoto de git.",
+ "ae6b7f5f40": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "67a9f26a80": ". Colocar",
+ "8f960935c1": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "ce3c58cd63": ", o establecer",
+ "5ee6ef6405": "ORCA_AZURE_DEVOPS_TOKEN",
+ "4ee74d1470": "Colocar",
+ "5efce6953d": "Azure DevOps",
+ "3c3cf05c63": "Las credenciales de Bitbucket están configuradas pero no se pudieron autenticar. Verifique los permisos del token y del repositorio, luego reinicie Orca si las variables de entorno cambiaron.",
+ "6e0ff3403e": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "44cde4aa01": "ORCA_BITBUCKET_API_TOKEN",
+ "a6c2816115": "y",
+ "b8a7efb3f6": "ORCA_BITBUCKET_EMAIL",
+ "8489c0aa49": "Bitbucket",
+ "e74de656ce": "inicio de sesión de autenticación glab",
+ "05e5245af7": "La CLI de GitLab está instalada pero no autenticada. Ejecute este comando en una terminal:",
+ "a83cac5726": "Instalar la CLI de GitLab",
+ "35a3379372": "Instale la CLI de GitLab para habilitar solicitudes de fusión, problemas y canalizaciones.",
+ "ea160a9978": "CLI.",
+ "a3326f6f1b": "glabro",
+ "027440e1cb": "Fusionar solicitudes, problemas, todos y canalizaciones a través de",
+ "513abfe47d": "GitLab",
+ "51000487c4": "inicio de sesión de autenticación gh",
+ "09285e9fe6": "La CLI de GitHub está instalada pero no autenticada. Ejecute este comando en una terminal:",
+ "399cf46867": "Instalar la CLI de GitHub",
+ "c0c8575e05": "Instale la CLI de GitHub para habilitar solicitudes de extracción, problemas y comprobaciones.",
+ "f36365ed45": "gh",
+ "de6a0d13ab": "Solicitudes de extracción, problemas y comprobaciones a través de",
+ "70c5f74f36": "GitHub",
+ "8e078e480c": "Desconectar {{value0}}",
+ "95b9a87e7e": "Prueba",
+ "62b20292de": "error",
+ "ae38fc62a8": "OK",
+ "33ae9730a8": "Agregue acceso Linear para explorar y vincular problemas.",
+ "98ded79cd7": "{{value0}} espacio de trabajo{{value1}} conectado",
+ "4bdc6fe4f5": "no configurado",
+ "4972f3c95d": "configurado",
+ "3614887c40": "de cheques",
+ "45bf5e6e4b": "Error de autenticación",
+ "e1bd5364e6": "Configuración opcional",
+ "e7a961e1c5": "Configurado",
+ "6bd148dcb5": "Solicitudes de extracción y estados de confirmación a través de la API REST de Gitea.",
+ "6355fe585e": "Solicitudes de extracción y estados de confirmación para repositorios detectados",
+ "1fac9b4910": "{{value0}} · Solicitudes de extracción y estados de confirmación",
+ "f92fbf11aa": "No configurado",
+ "6791d7af95": "Solicitudes de extracción y estados de compilación a través de tokens de API REST de Azure DevOps.",
+ "e3d5a24979": "Solicitudes de extracción y estados de compilación para Azure Repos detectados",
+ "277fc23929": "{{value0}} · Solicitudes de extracción y estados de compilación",
+ "295154e54e": "conectado",
+ "0879860c58": "Solicitudes de extracción y estados de compilación a través de tokens API de Bitbucket Cloud.",
+ "9707523939": "Solicitudes de extracción y estados de compilación",
+ "a565377c38": "no instalado",
+ "15cf990798": "No autenticado",
+ "f7eb5f0b24": "No instalado"
+ },
+ "KagiSessionLinkForm": {
+ "92f0b4e472": "Claro",
+ "9f741627a7": "Se borró el enlace de la sesión de Kagi.",
+ "d5c8b94c5b": "Ahorrar",
+ "ff450194cd": "Enlace de sesión privada de Kagi",
+ "e383683485": "https://kagi.com/search?token=...",
+ "81409d9362": "Enlace de sesión privada opcional para la autenticación Kagi.",
+ "3e5b7c6c25": "Enlace de sesión de Kagi guardado.",
+ "0911d5fa4c": "Ingrese un enlace de sesión privada de Kagi desde https://kagi.com/search?token=..."
+ },
+ "KeybindingsFileActions": {
+ "abc49853fb": "Recargar desde el disco",
+ "a8a8d6b9d3": "Revelar en el Administrador de archivos",
+ "9e24c0e858": "Abrir en Cursor",
+ "1637f64033": "Abrir en código VS",
+ "98f1a23e1c": "Abrir con la aplicación predeterminada",
+ "400397a10d": "Abrir menú de archivo de combinaciones de teclas",
+ "1c2be2b2c6": "Editar archivo en Orca",
+ "c5886a31cc": "No se pudo abrir el editor externo.",
+ "cdf794f46d": "El archivo de combinaciones de teclas no está disponible.",
+ "dd532a01ce": "No se pudieron abrir las combinaciones de teclas en Orca."
+ },
+ "ManageSessionKillDialog": {
+ "6bf4627168": "Cancelar",
+ "ad9832aa26": ". Cualquier trabajo no guardado en ese panel se perderá. Esto no se puede deshacer.",
+ "8401328fed": "Renuncias forzadas",
+ "87dcafc85c": "¿Matar esta sesión?",
+ "0b0db4c68c": "Matar sesión",
+ "d3dba51b15": "Asesinato…"
+ },
+ "ManageSessionsSection": {
+ "33c2a1e1b4": "Matar sesión {{value0}}",
+ "2896a50f50": "Ir a la terminal {{value0}}",
+ "e26a60d9eb": "Sin sesiones.",
+ "39c53d6d74": "Cargando…",
+ "5ed15e778c": "Reiniciar demonio",
+ "3282db098c": "Matar todas las sesiones",
+ "b3b1cc5708": "Refrescar",
+ "a795a9552a": "Sesiones",
+ "7c4889a724": "Recupérese de una terminal congelada o que se comporta mal cancelando sesiones o reiniciando el demonio subyacente.",
+ "d1b80fd5cd": "Administrar sesiones",
+ "9c940434af": "Vuelva al tiempo de ejecución local para reiniciar o finalizar las sesiones del demonio local.",
+ "ad467eaadc": "La administración de sesiones no está disponible mientras un servidor de ejecución remoto está activo.",
+ "8dbd96b463": "No se pudo finalizar la sesión.",
+ "0735b7a586": "No se pudo cerrar la sesión; es posible que ya haya desaparecido.",
+ "bfba05dccd": "Sesión asesinada.",
+ "c535cbdd09": "No se pudieron cargar las sesiones.",
+ "e3d1fbe008": "Reanudar",
+ "a06ababda0": "matar a todos"
+ },
+ "McpConfigFileRow": {
+ "b145eb6009": "entorno:",
+ "e720c139cd": "Abierto",
+ "845ae248e8": "válido"
+ },
+ "McpConfigSection": {
+ "4d16a0d9ac": "Comprobado",
+ "b900cd6282": "No se encontró ninguna configuración de MCP. Agregue una configuración de espacio de trabajo vacío cuando desee que este repositorio defina sus propios servidores MCP.",
+ "3b224167ff": "servidor",
+ "251b96564a": "detectado ·",
+ "f34c152dc0": "Actualizar configuraciones de MCP",
+ "6bac9ddfc6": "Los repositorios SSH se leen a través del sistema de archivos remoto. La creación inicial se limita a la configuración raíz del espacio de trabajo.",
+ "96f5609b04": "Inspeccione las definiciones del servidor MCP que los agentes pueden usar mientras trabajan en este repositorio.",
+ "55eea3ef47": "Configuraciones de MCP",
+ "9ee215caf6": ".mcp.json",
+ "1f3665e35a": "Configuración de MCP creada",
+ "82436439eb": "Agregar configuración de MCP",
+ "0a5c1ead54": "Crear configuración vacía"
+ },
+ "MobileEmulatorAgentControlRow": {
+ "1861982430": "No se pudo cargar el estado de CLI.",
+ "8af7a8bc38": "Los comandos apuntan al emulador activo del árbol de trabajo actual. Las coordenadas están normalizadas de 0 a 1.",
+ "c7f3fe0a6e": "Comandos comunes del emulador",
+ "d94ca6a623": "Permite a los agentes utilizar comandos CLI de Orca, incluido el control del emulador móvil.",
+ "67e19ee03c": "Habilidad CLI de Orca",
+ "aaf62a3dd2": "Instalado en",
+ "2fef055608": "Registra el comando CLI de Orca para que los agentes puedan controlar el emulador activo desde su shell.",
+ "4f2205f3b6": "Habilitar CLI de Orca",
+ "ff4b7e65d6": "Deje que los agentes de codificación controlen el emulador móvil activo con los comandos CLI de Orca.",
+ "2a674aa810": "Control del emulador móvil del agente",
+ "cdeaed9e37": "Registré Orca CLI en PATH."
+ },
+ "MobileEmulatorExamples": {
+ "edf13dd03b": "Copiar",
+ "c12b253997": "Copiar mensaje de ejemplo",
+ "d151e25078": "\"",
+ "b525ff2b12": "\"",
+ "4daa95f25a": "Pegue cualquiera de estos en Claude Code, Codex u otro agente en un proyecto donde esté instalada la habilidad Orca CLI.",
+ "0820b3f84f": "Pruébelo: indicaciones de ejemplo",
+ "1f608e7d60": "No se pudo copiar el mensaje.",
+ "2b077b5544": "Mensaje copiado."
+ },
+ "MobileEmulatorSettingsPane": {
+ "19d39113b6": "Deje que los agentes de codificación controlen el emulador móvil activo con los comandos CLI de Orca.",
+ "f2f8d97bb6": "Control del emulador móvil del agente",
+ "143961d031": "Dispositivo predeterminado",
+ "8aec2f99a0": "Actualizar la disponibilidad del emulador",
+ "ae1612c58c": "Disponibilidad",
+ "f9af91ea26": "Muestra la acción Nuevo emulador móvil y permite que los agentes se conecten al emulador activo.",
+ "700ddbf9b1": "Habilitar emulador móvil",
+ "bc39d0f115": "Configure la compatibilidad con el emulador móvil para Orca y agentes de codificación.",
+ "6593c9ddd3": "Emulador móvil",
+ "a4f1c82d90": "Desactivado",
+ "b5e2d93e01": "De cheques...",
+ "c6f3ea4f12": "Listo",
+ "d704fb5023": "Necesita configuración"
+ },
+ "MobileNetworkInterfaceSection": {
+ "63d5e4ae1e": "Regenera el código QR y escanéalo desde la aplicación móvil de Orca.",
+ "87985ba6f5": "En este menú de Interfaz de red, elija la dirección Tailscale, generalmente una IP 100.x.y.z.",
+ "1f7c26d36a": "Inicie sesión en la misma tailnet en ambos dispositivos.",
+ "668016be7a": "en su computadora y teléfono.",
+ "1dc87a7fbc": "Escala de cola",
+ "51d29927eb": "Instalar",
+ "9fc5d203ff": "Orca Mobile se conecta directamente a esta computadora. Para usarlo fuera de la misma red local, coloque su computadora y teléfono en la misma red superpuesta privada, luego genere el código QR con esa dirección de red seleccionada.",
+ "39fad211d9": "Conéctate fuera de tu Wi-Fi con una tailnet",
+ "a9db5d771d": "Actualizar interfaces de red",
+ "b2c384cfd6": "No se encontraron interfaces",
+ "d536b5e20d": "Elija qué dirección de red anunciar en el código QR. Utilice su dirección LAN para el emparejamiento de la misma red o una dirección de red superpuesta (Tailscale, ZeroTier) para el acceso entre redes.",
+ "406a35121c": "Interfaz de red",
+ "c541f67790": "Generar código QR",
+ "1e64659126": "Regenerado"
+ },
+ "MobilePane": {
+ "dd3cd78d04": "Escanear con Orca Móvil",
+ "35100bca5d": "Mientras usas un terminal en tu teléfono, Orca lo reduce para que se ajuste a la pantalla de tu teléfono. Cuando cierra la aplicación o la abandona, esto controla si permanece en el tamaño del teléfono (para que las herramientas CLI interactivas no vuelvan a fluir) o cambia de tamaño a su escritorio. Siempre puedes hacer clic en Restaurar en el banner del terminal para cambiar su tamaño manualmente.",
+ "ee56f1c7e4": "Cuando sales de la aplicación móvil",
+ "3939fd062c": "Revocar un dispositivo lo desconecta inmediatamente.",
+ "254a6d09e4": "emparejado",
+ "d7ce676270": "Dispositivos emparejados",
+ "e778ecb209": "O pegue este código en la aplicación móvil:",
+ "310924ad2c": "Escanea este código con la aplicación móvil de Orca. Cada código crea un token de dispositivo único.",
+ "870e1b5ca5": "No se pudo revocar el dispositivo",
+ "2e3dd0bc29": "Dispositivo revocado",
+ "711231348f": "No se pudo copiar el código de emparejamiento",
+ "e3c427e020": "No se pudo generar el código QR",
+ "cb9067c1c1": "El transporte de WebSocket no se está ejecutando",
+ "d714614dbf": "No se pudieron actualizar las interfaces de red",
+ "ff865419dc": "Después de 30 minutos",
+ "d4ba07d914": "Después de 5 minutos",
+ "c474aa09d8": "Después de 1 minuto",
+ "aa1263e881": "Mantener en el tamaño del teléfono (predeterminado)",
+ "6436e56546": "Código QR para emparejamiento de móviles",
+ "1b1b70279a": "Aún no hay dispositivos emparejados.",
+ "1592afcc7a": "Aún no hay dispositivos emparejados. Escanea el código QR con la aplicación móvil de Orca."
+ },
+ "MobileSettingsPane": {
+ "9a3c280e49": "Lanzamientos de GitHub",
+ "b0088412a1": "o el APK de Android desde",
+ "b5a2ed83ff": "Tienda de aplicaciones",
+ "c8491c17ef": "Controla Orca desde tu teléfono escaneando un código QR. Beta/vista previa anticipada: espere errores y cambios importantes. Obtenga la aplicación para iOS desde",
+ "e7a3ae8c4e": "Móvil",
+ "174f4a3c6d": "Controla terminales y agentes desde tu teléfono."
+ },
+ "NotificationsPane": {
+ "906b4afebf": "Enviar notificación de prueba",
+ "2772d2f257": "Omita las notificaciones cuando el árbol de trabajo desencadenante ya esté visible.",
+ "00cd406dbb": "Suprimir mientras estás concentrado",
+ "2a42dd8d6f": "Volumen del sonido de notificación",
+ "4aa5085cd7": "Costumbre:",
+ "c258cb96dc": "Elige sonido de notificación",
+ "2a2033c388": "Elija la alerta que Orca reproduce cuando se entrega una notificación de escritorio.",
+ "88686e6ca8": "Sonido de notificación",
+ "b6fc369244": "Un terminal en segundo plano emite un carácter de campana.",
+ "591fe605b9": "Campana terminal",
+ "55f901a59b": "Un agente de codificación finaliza y queda inactivo.",
+ "ca76d06fd2": "Tarea del agente completada",
+ "deff6d30da": "Notificaciones nativas del sistema para eventos en segundo plano.",
+ "841c8c549f": "Habilitar notificaciones",
+ "0fadad17ce": "No se pudo reproducir el sonido de notificación",
+ "406feb0aa6": "La notificación de prueba no fue entregada",
+ "6fc3781729": "Las notificaciones están deshabilitadas",
+ "4676a95bc3": "Verifique la configuración de notificaciones de su escritorio para Orca.",
+ "0cb93240b8": "El sistema no mostró la notificación.",
+ "145227ca2b": "Abrir configuración",
+ "d3d54e0915": "Notificación de prueba enviada",
+ "115437bc35": "Si no apareció ningún banner de macOS, habilite Permitir notificaciones para Orca.",
+ "7f45542625": "Notificación de prueba solicitada",
+ "98d70fb261": "No se pudo reproducir el sonido de notificación personalizado",
+ "c83b05a055": "Las notificaciones no son compatibles con este sistema.",
+ "274af61bc0": "sistema",
+ "6e6df3a09a": "Elija un archivo personalizado",
+ "76e02467b8": "Cambiar archivo personalizado",
+ "d3756cf5bc": "desactivado"
+ },
+ "OpenAiTranscriptionKeyDialog": {
+ "fa83512e48": "Guardar clave",
+ "07b26f2742": "Borrar clave",
+ "d246b2bdb3": "Las claves de tiempo de ejecución local se almacenan en ~/.orca utilizando el almacenamiento cifrado Electron cuando esté disponible.",
+ "c3380e4ca5": "sk-...",
+ "2f797018f0": "Clave API configurada",
+ "16015322f9": "Clave API",
+ "07ed3e512e": "El audio se envía a OpenAI solo cuando se selecciona un modelo de voz OpenAI.",
+ "439e91879e": "Transcripción OpenAI"
+ },
+ "OpenAiTranscriptionSettingsRow": {
+ "85c589cd61": "Agregar clave API",
+ "ae2df8f511": "Desconectar la clave API de OpenAI",
+ "a622bc3b37": "Reemplazar clave",
+ "3b0ab3fc0b": "Conectado",
+ "27e0cb656d": "Transcripción OpenAI",
+ "893790e13b": "Agregue una clave API de OpenAI antes de seleccionar modelos de voz a texto en la nube.",
+ "b59b9b2b51": "Clave API configurada para modelos de voz a texto en la nube."
+ },
+ "OpenInMenuSetting": {
+ "03b00b1f64": "Aplicación personalizada",
+ "c1d817e027": "Agregado",
+ "e4064916aa": "Agregar aplicación",
+ "9d0413817d": "Elija las aplicaciones disponibles en el menú Abrir en de un espacio de trabajo.",
+ "6ed52fe71e": "Abrir en aplicaciones",
+ "eb55b87570": "El comando que escribirías en Terminal para abrir esta aplicación.",
+ "ba1422ee07": "comando terminal",
+ "e1fc0085c6": "Etiqueta de menú",
+ "a261931d29": "Quitar aplicación",
+ "af7d1c3656": "Editar aplicación",
+ "494ed535cd": "Contraer detalles de la aplicación",
+ "810ef39b56": "cursor",
+ "3ebe650f74": "Nombre de la aplicación",
+ "3743ed080c": "Establecer comando",
+ "f79084947b": "Nueva aplicación"
+ },
+ "OrchestrationExamplesDialog": {
+ "3d1aa105e3": "Copiar mensaje",
+ "9b4c004998": "Hecho",
+ "969cec9739": "Copiar mensaje de ejemplo {{value0}}",
+ "4e46da1889": "No se pudo copiar el mensaje.",
+ "80c6f2feb8": "Mensaje de ejemplo copiado."
+ },
+ "OrchestrationPane": {
+ "52e0634e2c": "Solicite a un agente coordinador que utilice la orquestación para traspasos, traspasos de árboles de trabajo y agentes secundarios secuenciales o paralelos.",
+ "ae79504732": "como usarlo",
+ "7bc082f4de": "Copiar comando de instalación",
+ "832f1f3ee6": "¿Prefieres tu propia terminal?",
+ "9bedd2a6e5": "Permite a los agentes traspasar contexto y coordinar el trabajo a través de Orca.",
+ "07641b9768": "Habilidad de orquestación",
+ "2aacdb0517": "Coordine a los agentes de codificación en traspasos, traspasos de árboles de trabajo y trabajo de agentes secundarios.",
+ "191ac34567": "Orquestación de agentes"
+ },
+ "OrchestrationSetupCard": {
+ "e7d2a5146c": "Permite a los agentes traspasar contexto y coordinar el trabajo a través de Orca.",
+ "2777ff0fdc": "Habilidad de orquestación"
+ },
+ "OrchestrationSkillAgentCoverage": {
+ "6dec5ce2d2": "Cobertura del agente",
+ "ffe13e36fb": "Desaparecido",
+ "1e8f8d8fae": "Listo"
+ },
+ "OrchestrationSkillPromptDialog": {
+ "f08d45293d": "comando copiar",
+ "35550f3b3b": "Hecho",
+ "1bdce1911e": "Copiar comando de instalación de habilidad de orquestación",
+ "b99f375eb2": "Ejecute este comando en una terminal para instalar la habilidad de orquestación para sus agentes.",
+ "2914abcfa2": "Instalar habilidad de orquestación",
+ "d3dc559225": "No se pudo copiar el comando de instalación.",
+ "239bf9132b": "Comando de instalación copiado."
+ },
+ "PrivacyDiagnosticBundleControls": {
+ "dc8404a930": "Crear vista previa",
+ "a5acaffdb6": "Desechar",
+ "aca2c8a367": "Subir",
+ "798b6f0be5": "Abrir vista previa",
+ "2ae9a6b63e": "Hecho",
+ "7f14a1733c": "Eliminar paquete",
+ "2801d4ce22": "Copiar billete"
+ },
+ "PrivacyDiagnosticsSection": {
+ "acc7c66e6e": "exportación OTLP",
+ "4ff08ff3a7": "Borrar rastros locales",
+ "9ca08a9f8f": "Elimina todos los archivos de seguimiento rotados en esta máquina.",
+ "fe81a52cb2": "Abrir carpeta de seguimiento",
+ "5ff57fc986": "Revela {{value0}} en su administrador de archivos.",
+ "af2fc82cde": "Paquete de diagnóstico",
+ "c18cbe45df": "Paquete de diagnóstico cargado eliminado",
+ "7a4944595b": "No se pudo copiar el ticket de diagnóstico",
+ "13eb2c65a1": "Ticket de diagnóstico copiado",
+ "860bca9ec9": "Vista previa del paquete de diagnóstico descartada",
+ "49fc6c80e8": "Paquete de diagnóstico subido",
+ "db3228e01a": "Vista previa del paquete de diagnóstico abierta",
+ "a2b3505c77": "Vista previa del paquete de diagnóstico creada",
+ "9666a05580": "No se pudieron borrar los archivos de seguimiento",
+ "32d767f84d": "Archivos de seguimiento locales borrados",
+ "b85fe972cd": "No se pudo abrir la carpeta de seguimiento",
+ "1fb00a8995": "Desactivado",
+ "46ea3fb2d0": "Activado",
+ "7c9d9820b6": "Configure ORCA_OTLP_TRACES_URL para que Orca apunte a su propio recopilador OpenTelemetry."
+ },
+ "PrivacyPane": {
+ "36e0e2e63b": "variable de entorno. Desconfigúrelo y reinicie para volver a habilitarlo.",
+ "79a0f3c16c": "La telemetría está desactivada por el",
+ "e3970bbbf5": "La telemetría está deshabilitada porque se establece una variable de entorno de CI. Desactívalo y reinicia.",
+ "fe904ac984": "Compartir datos de uso anónimos",
+ "77410e0566": "Política de privacidad",
+ "8bfdd23a88": "Ayúdanos a descubrir qué construir a continuación. Orca envía recuentos anónimos de qué funciones utiliza y dónde fallan las cosas.",
+ "afec8b03be": "ci"
+ },
+ "QuickCommandsPane": {
+ "8764c6e9e4": "Quitar {{value0}}",
+ "7d90fd5299": "Editar {{value0}}",
+ "8c877dec41": "Global",
+ "c6b155911b": "Todos los comandos",
+ "5aacc8f7dc": "Agregar comando",
+ "c36912efd5": "Ejecútelos desde el botón Comandos rápidos en la barra de pestañas, o haga clic derecho dentro de cualquier terminal.",
+ "f91b649324": "Comandos guardados",
+ "3d9dc558e8": "Este comando rápido se eliminará de su lista guardada.",
+ "3edf3deaf8": "¿Eliminar \"{{value0}}\"?",
+ "9fcfc29519": "Insertar",
+ "9b3e338d62": "Ingresar",
+ "4ccc63da87": "Agente",
+ "0252ddd578": "Sin texto de comando",
+ "7784912ed6": "repositorio",
+ "2bb9e38e93": "Intitulado",
+ "3eb9897ab0": "No hay comandos en los ámbitos seleccionados.",
+ "38d61927e6": "No se guardaron comandos rápidos.",
+ "44923dd982": "destructivo",
+ "ec1ed99e70": "Borrar",
+ "d1d0976320": "Ninguno"
+ },
+ "RecentTabOrderControl": {
+ "3b17c81ede": "Orden de tiras de pestañas",
+ "6e6a3fcc61": "Más reciente",
+ "7a546f2309": "Orden de tabulación",
+ "a867a0889f": "Tira reciente o de pestañas."
+ },
+ "RepositoryHooksSection": {
+ "af49e2a19e": "El archivo está presente, pero Orca no pudo encontrar definiciones válidas de `scripts` o `issueCommand`.",
+ "3397879bee": "y existen comandos locales, elija cuál ejecutar.",
+ "39da2ae12f": "orca.yaml",
+ "ac9038d2cc": "cuando ambos",
+ "32fec28f5b": "Fuente de comando",
+ "bbbd6e0bc4": "Fuente de comando y orca.yaml",
+ "c9bc1bfd8f": "Avanzado",
+ "610d90fdbd": "Fuente del comando y detalles de orca.yaml.",
+ "52aef29e69": "Déjelo en blanco para usar el repositorio predeterminado desde",
+ "4084720f47": "Completo {{artifact_url}}",
+ "13394103bd": "Comando de problema personalizado de GitHub",
+ "70ad20f883": "para el problema vinculado o la URL de PR.",
+ "b997331366": "Anulación opcional. Usar",
+ "2cc27dc12b": "Anulación opcional por usuario para el comando de problema vinculado.",
+ "b91a0f297d": "Scripts locales y compartidos que se ejecutan antes de archivar un árbol de trabajo.",
+ "9a100323ff": "Guión de archivo",
+ "21fb607a87": "Comportamiento predeterminado cuando se crea un nuevo árbol de trabajo.",
+ "793dcee97d": "cuando correr",
+ "63e1783173": "Elija el comportamiento predeterminado cuando haya un script de configuración disponible.",
+ "fb6bebcf7e": "Cuándo ejecutar la configuración",
+ "30d555acd2": "Scripts locales y compartidos que se ejecutan después de crear un nuevo árbol de trabajo.",
+ "52b31baf02": "Guión de configuración",
+ "8567127a40": "Scripts que se ejecutan cuando se crean o archivan árboles de trabajo. Los scripts locales se almacenan en esta máquina; Los scripts `orca.yaml` se comparten con tu equipo.",
+ "ff082fe7c6": "Ganchos para árbol de trabajo",
+ "5d940bde5c": "Agregar secuencia de comandos local",
+ "8c2893fae0": "Se ejecuta como un script de shell único. Guardado en esta máquina.",
+ "40a446ae16": "- sólo para ti, en esta máquina",
+ "2d03a514db": "local",
+ "7e4427b4a2": "para cambiar.",
+ "b113344b6a": "Editar",
+ "f828e1de19": "- compartido con tu equipo",
+ "673a7fd10e": "De cheques...",
+ "5426ecbdcb": "Los scripts locales no se ejecutarán",
+ "b2b06c7ce8": "Variables de entorno disponibles (pase el cursor para obtener más detalles):",
+ "95a0411b3e": "plantilla",
+ "175daba180": "Ejemplo",
+ "b20c5df6ca": "Agregue un archivo `orca.yaml` para habilitar los valores predeterminados de configuración, archivo o automatización de problemas compartidos para este repositorio. Plantilla de ejemplo:",
+ "925f9e0dc4": "texto-primer plano",
+ "0cc712b823": "El archivo de configuración principal existe en la raíz del repositorio, pero Orca aún no pudo analizar las definiciones de gancho admitidas.",
+ "c90b858573": "texto-ámbar-700 oscuro:texto-ámbar-300",
+ "aba825233f": "El archivo contiene claves de configuración que esta versión de Orca no reconoce. Es posible que necesites actualizar Orca o revisar el archivo en busca de errores tipográficos.",
+ "ca424ff135": "Los valores predeterminados de automatización de problemas y gancho compartido se definen en el repositorio y están disponibles para todos los que lo usan.",
+ "32f417fe17": "texto-esmeralda-700 oscuro:texto-esmeralda-300",
+ "8bfe65fc60": "Usar comandos locales",
+ "8d6c56bff8": "Ejecute ambos",
+ "0fa21e19ec": "Nombre del espacio de trabajo, normalmente basado en el nombre de la sucursal.",
+ "54c73d88d0": "Ruta al árbol de trabajo que se está creando. Los comandos de configuración se ejecutan desde este directorio.",
+ "30952c4aa4": "Ruta al pago del repositorio principal. Útil para copiar archivos compartidos, como .env, en un árbol de trabajo.",
+ "9b821fa19d": "# p.ej. echo \"Limpiando $ORCA_WORKSPACE_NAME\"",
+ "6f90ebe3fd": "Se ejecuta antes de archivar o eliminar un árbol de trabajo.",
+ "a3fc966677": "# p.ej. pnpm instalar cp \"$ORCA_ROOT_PATH/.env\" \"$ORCA_WORKTREE_PATH/.env\"",
+ "f0710e1c83": "Se ejecuta después de que se crea un nuevo árbol de trabajo; instalar departamentos, copiar archivos env, ejecutar migraciones.",
+ "8561b0665f": "orca.yaml primero, luego tus comandos locales.",
+ "0e8b2a520d": "Ignorar orca.yaml; ejecute solo sus comandos locales.",
+ "83dc78202a": "Sólo locales",
+ "29397e8bbc": "Ejecute solo comandos de repositorio comprometidos; ignorar los comandos locales.",
+ "d88b6ff88f": "orca.yaml solamente",
+ "99e3264a49": "Ejecute la configuración solo cuando lo elija.",
+ "15debc1fd9": "Saltar por defecto",
+ "022ba10cf2": "Ejecute la configuración automáticamente.",
+ "d3ef1ab247": "Ejecutar por defecto",
+ "90b1f50137": "Preguntar antes de ejecutar la instalación.",
+ "e03d9a8f38": "pregunta cada vez",
+ "8dbe6bedf5": "inválido",
+ "0e0dd5b9a5": "cargado",
+ "9b12f15b1e": "cuando uno existe.",
+ "c85c2c88a2": "{{artifact_url}}",
+ "fac13f8c1e": "autorizado",
+ "0518758f38": "ambos",
+ "d2b3016c20": "compartido",
+ "4611b78617": "fuente de comando",
+ "c5a55a2d2e": "avanzado",
+ "b5e3e77e89": "acción",
+ "0ce113fd7b": "Los scripts locales se guardan, pero el origen del script está configurado únicamente en orca.yaml.",
+ "7f78e5eea6": "Se guardan los scripts locales. Orca todavía está revisando orca.yaml antes de poder recomendar qué fuente de script usar.",
+ "2b6356e744": "Guardado",
+ "81057d5f71": "Ahorro...",
+ "da37d6f10e": "Copiar",
+ "3149964b66": "copiado"
+ },
+ "RepositoryIconPicker": {
+ "2b7d27b93c": "Utilice el color del repositorio {{value0}}",
+ "fde066a63b": "Las cargas PNG deben tener un tamaño de 256 KB o menos.",
+ "cc1286e263": "favicon",
+ "03ca1a4e9b": "ejemplo.com",
+ "381b4844fd": "Subir PNG",
+ "7da623abcc": "Se utiliza de forma predeterminada: GitHub siempre proporciona una, incluso cuando el propietario no ha configurado una imagen personalizada.",
+ "39da8a10bf": "Usar avatar de GitHub",
+ "c490787d24": "emojis",
+ "b2d7fd2116": "Icono",
+ "2d8bd302fa": "Avatar",
+ "913c55833d": "Color de repositorio personalizado {{value0}}",
+ "0e5f0693c1": "Elija un color de repositorio personalizado",
+ "642dc29c6d": "Color",
+ "549d126081": "Reiniciar",
+ "4e2a14f967": "Icono de repositorio",
+ "d71df44587": "No se pudo resolver el repositorio de GitHub.",
+ "f79972271a": "No se encontró ningún control remoto de GitHub para este repositorio.",
+ "4d039317f4": "favicon del sitio web",
+ "acf31559a0": "Ingrese una URL de sitio web válida.",
+ "868c5c9b56": "No se pudo importar el icono del repositorio"
+ },
+ "RepositoryPane": {
+ "15a99d9b9f": "Las rutas relativas se resuelven desde la raíz de este proyecto.",
+ "8ccacbeb5a": "Usar global",
+ "e9bd57a336": "Ubicación del árbol de trabajo",
+ "e63bb96a9b": "Directorio específico del proyecto para nuevos árboles de trabajo.",
+ "f88db4fece": "Base de árbol de trabajo predeterminada",
+ "8984d06520": "Rama base o referencia predeterminada al crear árboles de trabajo.",
+ "e641c359de": "Ícono y color del proyecto utilizados en la barra lateral y las pestañas.",
+ "26fef02bf3": "Icono de proyecto",
+ "c7ef4415de": "Nombre para mostrar",
+ "b0a0c14a1c": "Detalles de visualización específicos del proyecto para la barra lateral y las pestañas.",
+ "170624bdfb": "Eliminar este proyecto de Orca.",
+ "0909e5d650": "Eliminar proyecto",
+ "ee5a290616": "Abierto como carpeta. Las funciones de Git no están disponibles para este espacio de trabajo.",
+ "323debba71": "Tipo:",
+ "499a437335": "Identidad"
+ },
+ "RepositorySourceControlAiActionRows": {
+ "548a6e1281": "Plantilla de comando",
+ "7a3a8e431d": "Argumentos CLI",
+ "2b2f38652b": "Comando personalizado",
+ "0ffb081b3a": "Usar agente predeterminado",
+ "f4310cf63f": "Agente",
+ "1cd88d470a": "Personalizar",
+ "403876bb48": "Usar global",
+ "f0aa2cfaea": "Recetas de acción"
+ },
+ "RepositorySourceControlAiCustomCommand": {
+ "0704dd55cd": "Comando de repositorio",
+ "e56668c291": "Usar global",
+ "fbb77e122a": "Reserva de repositorio para acciones de texto que seleccionan el comando personalizado.",
+ "ebffc5a28c": "Comando personalizado",
+ "f9941f0caf": "p.ej. ollama ejecuta llama3.1 {rápido}"
+ },
+ "RepositorySourceControlAiEnablement": {
+ "84233d1bb3": "Apagado",
+ "bea897eec2": "En",
+ "62511a575d": "Usar global",
+ "30ae6dcce8": "El valor predeterminado global es",
+ "cf5959c834": "Control de fuente AI habilitado"
+ },
+ "RepositorySourceControlAiHostedReviewDefaults": {
+ "053ccfbf52": "Apagado",
+ "777443bf89": "En",
+ "ffc3b26b26": "Usar global",
+ "a68849a859": "El valor predeterminado global es",
+ "aa6ee4b7d6": "Valores predeterminados de creación de reseñas alojadas",
+ "629ed8a9d3": "Abrir revisión alojada después de la creación",
+ "14f1eb99d0": "Generar detalles al abrir Crear PR",
+ "d32b87e754": "Utilice la plantilla de revisión cuando esté disponible",
+ "981eae7e14": "Borrador por defecto"
+ },
+ "RepositorySourceControlAiSection": {
+ "67b3ff5467": "Desechar",
+ "8b8bc5913a": "Recetas de acción del repositorio. La configuración global se utiliza hasta que este repositorio la personalice.",
+ "71b003b62b": "IA de control de fuente",
+ "152268c295": "Ahorrar",
+ "57e6e9d4b1": "Ahorro...",
+ "ccb07dd027": "Guardado",
+ "e57dde9d93": "Cambios no guardados"
+ },
+ "RuntimeAccessGrantList": {
+ "8b82879581": "Cualquier persona con una concesión activa puede conectarse hasta que la revoques. Revocar el acceso compartido desconecta a los clientes activos inmediatamente.",
+ "68ec21309f": "Revocar acceso",
+ "6f6d5188ed": "Revocar {{value0}}",
+ "87b16cd11d": "Creado",
+ "434e4a6af6": "Enlace actual",
+ "fd83b94095": "Aún no hay acceso al servidor compartido.",
+ "27cf8507ad": "Actualizar acceso compartido",
+ "f031182867": "Acceso al servidor compartido",
+ "df142657a5": "Aún no usado",
+ "b18d1764ef": "Usado por última vez {{value0}}"
+ },
+ "RuntimeEnvironmentsPane": {
+ "aeb26635d2": "Quitar {{value0}}",
+ "af53761f31": "Cancelar",
+ "bb90dd6487": "Quitar servidor",
+ "d2e00809e4": "Cambiar",
+ "05e0fc3ebf": "Cambiar a",
+ "b2290ed203": "Orca cerrará las terminales remotas y las pestañas del navegador del servidor actual antes de cargar proyectos desde el siguiente servidor.",
+ "d570c35a99": "Cambiar servidor",
+ "84b9b2be05": "Cree una concesión de acceso revocable para que un navegador u otro cliente de Orca pueda conectarse.",
+ "6e1280ca55": "Comparte este servidor Orca",
+ "9a3758d983": "No hay servidores guardados.",
+ "9bee6bbeeb": "Agregar servidor",
+ "55fcc964cd": "en el servidor y pegue la URL de emparejamiento impresa.",
+ "960e901ae4": "servicio de orca --dirección-emparejamiento ",
+ "163671f7b5": "Correr",
+ "c3d772c514": "orca://pair?code=...",
+ "9bc9b83474": "código de emparejamiento",
+ "e038625857": "cuadro de desarrollo",
+ "54ebacc600": "Nombre del servidor",
+ "1826bd0608": "Servidores guardados",
+ "6ce4664003": "Actualizar servidores",
+ "b07070ed3c": "Ningún servidor conectado",
+ "78692becbd": "Escritorio local",
+ "64b6bea541": "Servidor activo",
+ "99ac81fb43": "Cambiado a {{value0}}.",
+ "b5b5114cb0": "Se eliminó {{value0}}.",
+ "6cb6eae14f": "No se pudo guardar el entorno de ejecución.",
+ "7b5986c8df": "Guardado {{value0}}. Utilice Active Server para cambiar cuando esté listo.",
+ "a5b58465b6": "Conectado a {{value0}}.",
+ "5ef712f407": "Ya existe un servidor llamado \"{{value0}}\".",
+ "0c55a47480": "Se requieren nombre y código de emparejamiento.",
+ "e6410d72c3": "No se pudieron cargar los entornos de ejecución.",
+ "6ef71985da": "Sin punto final",
+ "ed3e3f069d": "Esto elimina el servidor guardado de Orca. No cambia el servidor activo.",
+ "b2fda48c39": "Al eliminar el servidor activo, se desconecta este navegador y se cierran los terminales remotos y las pestañas del navegador para ese servidor.",
+ "9f7665a01b": "Al eliminar el servidor activo, Orca vuelve al escritorio local y cierra los terminales remotos y las pestañas del navegador para ese servidor.",
+ "3595fd1948": "Nuevo enlace",
+ "54dee18f5c": "Ocultar formulario",
+ "8cf8790697": "Los servidores guardados enrutan este navegador a través de un tiempo de ejecución de Orca emparejado.",
+ "f75ce1c7a5": "Local mantiene el comportamiento actual del escritorio. Los servidores guardados enrutan las llamadas de los clientes admitidos a través del tiempo de ejecución remoto.",
+ "d25f0688b1": "Eliminar"
+ },
+ "RuntimePairingGeneratedUrlRows": {
+ "0495f68959": "Copiar {{value0}}"
+ },
+ "RuntimePairingUrlGenerator": {
+ "849825e829": "Pegue esta URL de emparejamiento en otro cliente Orca.",
+ "2e5c4e3c93": "Emparejar otro cliente Orca",
+ "f7cafdc9f3": "El enlace del navegador no está disponible en esta compilación. La URL de emparejamiento todavía funciona para los clientes de Orca.",
+ "6b9ca3e69b": "Abrir en el navegador",
+ "1ca2e5194d": "Utilice esta URL desde un navegador que pueda llegar a la dirección seleccionada.",
+ "8de0f84fff": "Generar enlace de acceso",
+ "279e0dcb57": "127.0.0.1 solo funciona en esta computadora. Utilice una LAN, Tailscale o una dirección personalizada para otro dispositivo.",
+ "45cf476df3": "host, host:puerto o wss://host/ruta",
+ "4531ea3158": "Dirección personalizada",
+ "360c548cf3": "Actualizar direcciones de conexión",
+ "de6d5cff95": "Esta computadora (",
+ "de77eb1b65": "Dirección de conexión",
+ "ff80904fc4": "Cree una concesión de acceso revocable para clientes de navegador o de escritorio.",
+ "f8500e134a": "Comparte este servidor Orca",
+ "d6c081adf4": "No se pudo copiar la URL.",
+ "df0aa45a86": "URL de emparejamiento copiada.",
+ "13704d635e": "URL del cliente web copiada.",
+ "e8d83f2b0f": "No se pudo revocar el acceso compartido.",
+ "9f8e037c4a": "Acceso compartido revocado.",
+ "d797f516b1": "El acceso compartido ya fue revocado.",
+ "2ed55c841a": "No se pudo generar la URL de emparejamiento.",
+ "11d5248e62": "URL de emparejamiento generada.",
+ "6dd594a507": "URL del cliente web generada.",
+ "2752126f3e": "El emparejamiento en tiempo de ejecución no está disponible.",
+ "95b8be4cea": "No se pudieron actualizar las interfaces de red.",
+ "1b4e0bbcc5": "No se pudieron cargar las concesiones de acceso compartido.",
+ "b91e36a986": "web"
+ },
+ "Settings": {
+ "3bf149e873": "Configuración del proyecto > {{value0}}",
+ "075341c763": "Nuevas características que aún están tomando forma. Pruébalos.",
+ "8b017f2506": "Experimental",
+ "499c1cd7f9": "Configuraciones de compatibilidad de bajo nivel para solucionar problemas.",
+ "1c87f8d024": "Avanzado",
+ "c1b43dc4e2": "Datos de uso anónimos y controles de telemetría.",
+ "d7e3f62d70": "Privacidad y telemetría",
+ "9b83cc62c2": "Acceso a la privacidad de macOS para herramientas de desarrollo lanzadas en terminales.",
+ "65660d4548": "Permisos de macOS",
+ "c6c01ac209": "Controla terminales y agentes desde tu teléfono.",
+ "c40dadaac8": "Móvil",
+ "c2ee313198": "Hosts SSH remotos para archivos, terminales y git.",
+ "9b02492d1f": "Anfitriones SSH",
+ "b5ee17826b": "Cambie entre el modo de escritorio local y los tiempos de ejecución remotos de Orca emparejados.",
+ "7686cb5c36": "Conecte este navegador a un servidor Orca guardado.",
+ "bd0181eeca": "Servidores remotos de Orca",
+ "8acf3f22e0": "Estadísticas de Orca más análisis de uso de Claude, Codex y OpenCode.",
+ "954a8f5aef": "Estadísticas y uso",
+ "a737a4bb22": "Atajos de teclado para acciones comunes.",
+ "23bf7a1ad4": "Atajos",
+ "7210ac09c4": "Notificaciones de escritorio nativas para la actividad de los agentes y eventos de terminal.",
+ "9907545fa3": "Notificaciones",
+ "d0b7021d64": "Comportamiento de selección y edición.",
+ "d7a3e635b6": "Entrada y edición",
+ "6d1a27e193": "Tema, zoom, apariencia de la aplicación y del terminal, barras laterales y barra de estado.",
+ "2b4474780a": "Apariencia",
+ "3d9adfe6a5": "Terminal global, navegador y pestañas de rebajas.",
+ "3eb22a3ada": "Espacio de trabajo flotante",
+ "01f9d36292": "Configure la compatibilidad con el emulador móvil para Orca y agentes de codificación.",
+ "f75daf1002": "Emulador móvil",
+ "ad9788036f": "Página de inicio, enrutamiento de enlaces y cookies de sesión.",
+ "c46215ea03": "Navegador",
+ "6742c7932c": "Comandos de terminal guardados, con alcance global o por proyecto.",
+ "13d4fe30ad": "Comandos rápidos",
+ "b79b5b31e9": "Shells, renderizador, sesiones y comportamiento del terminal.",
+ "3de4bbb841": "Terminal",
+ "dd72ed437a": "Elija qué proveedores de tareas aparecen en la página Tareas y en la barra lateral.",
+ "11faa2f7dd": "Fuentes de tareas",
+ "cfa34f4465": "Nomenclatura de sucursales, referencias base, atribución y autor de Git AI.",
+ "70100f94c7": "Git y control de código fuente",
+ "b07041697f": "Conecte GitHub, GitLab, Linear y servicios de alojamiento de origen.",
+ "c9ca101a3b": "Integraciones",
+ "f9b77539fd": "Valores predeterminados del espacio de trabajo, configuración y mantenimiento de aplicaciones.",
+ "7807c11c4d": "General",
+ "6855b0f77d": "Termine los flujos de trabajo principales que hacen que Orca sea útil para el trabajo de agentes paralelos.",
+ "6d119427ef": "Lista de verificación de incorporación",
+ "eb1176a14e": "Dictado local de voz a texto con modelos en el dispositivo.",
+ "5063bb47a5": "Voz",
+ "7118953f14": "Permita que los agentes controlen cualquier aplicación en su computadora.",
+ "c9841721cb": "Uso de la computadora",
+ "475980f53d": "Coordine múltiples agentes de codificación a través de Orca.",
+ "00c3a7950d": "Orquestación",
+ "21f09426ea": "Opcional. Orca trabaja con los inicios de sesión de su proveedor existente; agregue cuentas solo si desea que Orca le ayude a cambiar entre ellas.",
+ "ad6c529693": "Cuentas de proveedores de IA",
+ "ec1ba547f7": "Administre agentes de IA, establezca un valor predeterminado y personalice comandos.",
+ "8afa676615": "Agentes",
+ "add3b97ee6": "\"",
+ "3c88ec55d6": "No se encontraron configuraciones para \"",
+ "c7ad095d96": "Cargando configuración...",
+ "acc7bbdefd": "Presione ESC nuevamente para salir de la configuración",
+ "43b68e10f0": "No has guardado los cambios de autor de Git AI. Irse los descartará.",
+ "17bdee4ff1": "¿Descartar los cambios de autor de Git AI no guardados?",
+ "084d8fac5b": "Privacidad y seguridad",
+ "23931df7e8": "Acceso remoto",
+ "8bd117d669": "Interfaz",
+ "e1578cd4bc": "Flujos de trabajo",
+ "9abb9be3bc": "Configuración",
+ "23c6874fdf": "Capacidades de IA",
+ "2309068a6f": "destructivo",
+ "65358016ea": "Desechar"
+ },
+ "SettingsFormControls": {
+ "42a4d15a30": "No hay fuentes coincidentes.",
+ "b55371ea18": "Fuentes",
+ "c766f8ac75": "Alternar sugerencias de fuentes",
+ "74bcecd5ec": "Claro",
+ "a4ff6143f8": "Borrar selección de fuente",
+ "b661b034ec": "· Por defecto:",
+ "ceefb9d7f1": "No se encontraron temas.",
+ "9119fb2268": "Actual",
+ "4e11f87ca6": "Demostración",
+ "fbb428db98": "Seleccionado:",
+ "fac59213fc": "Buscar temas integrados",
+ "cb330ef7f8": "de {{value0}}",
+ "c822571b2e": "coincidente con \"{{value0}}\"",
+ "3119c012a5": "cadena"
+ },
+ "SettingsSidebar": {
+ "e0900f83e7": "SSH",
+ "5c9669ff9c": "Proyectos",
+ "dbceaa8840": "Configuración de búsqueda",
+ "60f8a673a7": "Volver a la aplicación",
+ "6503182299": "Lista de verificación de incorporación",
+ "82db1b7de4": "Lista de verificación de incorporación, {{value0}} de {{value1}} realizada. Mostrar guía de configuración.",
+ "df38d612b7": "Aún no se han agregado proyectos.",
+ "3e483e256b": "No hay configuraciones de proyecto coincidentes."
+ },
+ "ShortcutBindingRow": {
+ "4a4c2c9d32": "Agregar acceso directo",
+ "87381fd8f8": "Presione las teclas…",
+ "9cdaaa3d8f": "Deshabilitar acceso directo",
+ "3b62c142fa": "Deshabilitar {{value0}}",
+ "f75335b155": "Restablecer los valores predeterminados",
+ "4f2c9b2a05": "Restablecer {{value0}} a los valores predeterminados",
+ "97dccee14e": "Modificado",
+ "3b11ef3a43": "{{value0}} atajo",
+ "f6579be67b": "Cambiar acceso directo",
+ "6a7848fdac": "Escuchando atajos"
+ },
+ "ShortcutFilterRail": {
+ "28b63545bf": "Estado",
+ "8a1e78c14b": "Filtros de estado de acceso directo",
+ "df8466f3fc": "Borrar búsqueda de accesos directos",
+ "f733c4b89f": "Comando o teclas de búsqueda",
+ "02dc7d4251": "encontrar atajos",
+ "1d5634ba31": "{{value0}} atajo"
+ },
+ "ShortcutRowsList": {
+ "4ce3cd24d9": "Ningún atajo coincide con esos filtros."
+ },
+ "ShortcutTerminalPolicyControl": {
+ "0762983d13": "Terminal primero",
+ "63308571d8": "Orca primero",
+ "c43c7ff5f9": "Decide quién intercepta primero los atajos",
+ "c3a554288e": "Atajos en la Terminal",
+ "0f55c6f15c": "Elija si Orca o el terminal enfocado gana cuando los atajos se superponen."
+ },
+ "ShortcutsPane": {
+ "4b7ae34062": "directamente.",
+ "38e86e206a": "Personaliza los atajos visualmente o edítalos",
+ "47f8f7aef9": "Atajos de teclado",
+ "f0b35b0b2e": "Deshabilitado mientras un terminal o TUI tiene el foco del teclado.",
+ "5c65d5db9d": "Terminal primero",
+ "dfa8ff612f": "También se ejecuta mientras una terminal o TUI tiene el foco del teclado.",
+ "2a0e8aeccf": "Orca primero",
+ "3c0fac059a": "Todavía se ejecuta mientras una terminal tiene el foco del teclado.",
+ "25b0004fbf": "Terminal activo",
+ "781cb74d22": "Se ejecuta desde paneles de terminales.",
+ "cb02e00202": "Terminal",
+ "d8c988dab4": "~/.orca/keybindings.json"
+ },
+ "SourceControlAiActionRecipeDefaults": {
+ "2576299196": "argumentos",
+ "b3914ecbbc": "Desechar",
+ "fb09da4345": "Plantilla de comando",
+ "2cb4bb7e5d": "Argumentos CLI",
+ "0740d30915": "Comando personalizado",
+ "ee0e5c2a48": "Usar agente predeterminado",
+ "bf84dea6af": "Utilice variables sólo cuando desee que Orca inyecte contexto. Deje al agente como predeterminado para seguir su preferencia normal de agente.",
+ "a79c567194": "Recetas de acción",
+ "cf01d41bce": "Agente, argumentos CLI y plantilla de comando utilizados por cada botón AI de control de código fuente.",
+ "a9359c8aa9": "Error desconocido",
+ "b5f46664d3": "No se pudo guardar la acción predeterminada de AI de control de código fuente: {{value0}}",
+ "d18d665e12": "Ahorrar",
+ "4f549a5fa8": "Ahorro...",
+ "9d3cc627f8": "Guardado",
+ "817128d94e": "Cambios no guardados",
+ "7ab1437a12": "solicitud de extracción",
+ "e5b24893ba": "comprometerse",
+ "06a9dab64d": "cheques",
+ "cb67b938c5": "arreglar",
+ "2037c78a6f": "plantilla",
+ "eb7e8f3b39": "modelo",
+ "d74fdc776c": "dominio",
+ "673369fe0c": "cli",
+ "db9bd75d10": "argumentos",
+ "926d58e87f": "agente"
+ },
+ "SparsePresetSettingsSection": {
+ "6fa754d20f": "Borrar",
+ "fe1f2c6572": "Editar {{value0}}",
+ "88bfbf1a9c": "No hay pocos ajustes preestablecidos guardados para este repositorio.",
+ "d7565029a9": "Nuevo preestablecido",
+ "17f8c4ce10": "Administre conjuntos de directorios guardados para la creación de árboles de trabajo dispersos.",
+ "388513be2d": "Ajustes preestablecidos de pago dispersos",
+ "a05bc9183f": "Guardar preestablecido",
+ "2d7d45e991": "Cancelar",
+ "c240a16f25": "Utilice rutas relativas al repositorio como paquetes/web o aplicaciones/api.",
+ "fde7ff2cc3": "paquetes/web compartida/ui",
+ "caf33029cc": "Directorios",
+ "3b6f1abd3e": "p.ej. solo web",
+ "a6fcdd9e3c": "Nombre",
+ "b9922ec194": "Cancelar edición preestablecida",
+ "694cc55ecb": "Los directorios guardados se utilizan al crear árboles de trabajo dispersos para este repositorio.",
+ "8b64731aaf": "+{{value0}} más",
+ "755c6a1a0d": "Confirmar",
+ "a7bcf206b1": "Eliminando",
+ "ba9ad2d4cd": "Fecha de actualización desconocida",
+ "568d7e1e49": "Actualizado {{value0}}",
+ "d7b3f0bdc3": "directorios {{value0}}",
+ "9d3c087fc0": "1 directorio",
+ "8deb7024ab": "Cargando ajustes preestablecidos escasos...",
+ "92c08ccae3": "No se pudieron cargar los ajustes preestablecidos escasos.",
+ "3dfa765ca7": "Se guardarán {{value0}} directorios.",
+ "b532b9c17d": "Se guardará 1 directorio.",
+ "623b4cf910": "Editar preajuste",
+ "68bbcd864a": "nuevo",
+ "2ef2b2674b": "Eliminar {{value0}}"
+ },
+ "SshDestructiveActionDialog": {
+ "895b216267": "Cancelar"
+ },
+ "SshPane": {
+ "c0f1c80166": "No hay destinos SSH configurados.",
+ "639ceb3698": "Agregar destino",
+ "51d7dba44d": "Importar",
+ "a7d28dff81": "Agregue un host remoto para conectarse a él en Orca.",
+ "94c5284560": "Objetivos",
+ "f495689b82": "Importación fallida",
+ "f8050f6307": "Servidor {{value0}} sincronizado {{value1}}",
+ "68c13b4589": "Prueba fallida",
+ "81d08bcddf": "Conexión exitosa",
+ "2c4ee7332b": "No se pudo restablecer el relé remoto",
+ "db2e48975e": "Restablecimiento remoto del relé",
+ "025e107643": "No se pudieron finalizar los terminales remotos",
+ "90e308c98b": "Terminales remotas terminadas",
+ "a43de1d3ee": "Falló la desconexión",
+ "e95d5ae10e": "La conexión falló",
+ "c2a69510e3": "No se pudo eliminar el objetivo",
+ "a0237eb1ca": "Objetivo eliminado",
+ "2227ce47b6": "No se pudo guardar el objetivo",
+ "f602009125": "Objetivo agregado",
+ "b4ba0ce33d": "Objetivo actualizado",
+ "3879cbaa52": "El período de gracia de retransmisión debe estar entre 60 y {{value0}} segundos, o elegir mantener activo hasta que se reinicie",
+ "4db9afce1c": "El puerto debe estar entre 1 y 65535",
+ "0e5aa04161": "Se requiere un alias de configuración de host o SSH",
+ "f1fc50dad2": "No se pudieron cargar destinos SSH",
+ "0cda732f43": "La prueba de conexión falló"
+ },
+ "SshPassphraseDialog": {
+ "d5a234456f": "Cancelar",
+ "c3ce71aad6": "Introduzca la frase de contraseña",
+ "abaa0dc653": "Introduce la contraseña",
+ "ce4fdf7914": "Ingrese la contraseña para",
+ "dbf9b6f2d0": "Introduzca la contraseña para",
+ "c55f105262": "No se pudo cancelar la solicitud de credencial SSH",
+ "b8e88fd0de": "No se pudo enviar la credencial SSH",
+ "405066423c": "Descubrir",
+ "bec2c1318f": "Conectar",
+ "8a349e3fac": "Frase de contraseña para {{value0}}",
+ "cab3d5f5a5": "Contraseña para {{value0}}",
+ "1f3dde805d": "Frase de contraseña de clave SSH",
+ "106bd57f4a": "Contraseña SSH"
+ },
+ "SshTargetCard": {
+ "ec6543cee9": "Conectar",
+ "0e53e9f8e8": "Prueba",
+ "1810b51482": "Conectando",
+ "4c86f30877": "Desconectar",
+ "7f7b3d7ab4": "Eliminar objetivo",
+ "3d21a22d0e": "Eliminando objetivo",
+ "3d8af2949f": "Editar objetivo",
+ "762a48c662": "Restablecer el relé remoto",
+ "97dea4e8cf": "Restablecer el relé remoto",
+ "da16e108e6": "Terminales remotos finales",
+ "c77f1abfe3": "Terminar con terminales remotos",
+ "18968ede9e": "Error",
+ "f0871e6bfb": "conectar",
+ "47e94bd6ba": "conectado"
+ },
+ "SshTargetDestructiveActions": {
+ "7e66942808": "Esto detendrá las sesiones de terminal activas en este destino SSH. Volver a conectarlos no los restaurará.",
+ "accf177a03": "¿Acabar con los terminales remotos?",
+ "26be00392d": "Esto fuerza la detención de la retransmisión remota para este destino SSH. Los terminales remotos activos y los reenvíos de puertos para este destino finalizarán.",
+ "570a7a0574": "¿Reiniciar el relé remoto?",
+ "3bb0cf0ee4": "Esto eliminará el objetivo y finalizará cualquier terminal remoto activo.",
+ "4808966c41": "Eliminar destino SSH"
+ },
+ "SshTargetForm": {
+ "fea9cb402e": "Cancelar",
+ "1b19b00e93": "(7 días).",
+ "137e88ce8d": "Cuánto tiempo el relé mantiene vivos los terminales después de la desconexión. Predeterminado: 10800 (3 horas). Máximo:",
+ "b574994adc": "Los terminales remotos permanecen disponibles hasta que los finalice o reinicie el relé.",
+ "71fc546097": "Mantener vivo hasta reiniciar",
+ "92f80edbfd": "Período de gracia del relevo (segundos)",
+ "feae1d1e69": "Opcional. Equivalente a ProxyJump/ssh -J.",
+ "11bcb4507a": "bastion.ejemplo.com",
+ "b2ab248ded": "Anfitrión de salto",
+ "3b01ca44a0": "Opcional. Se utiliza para hacer túneles (por ejemplo, Cloudflare Access, ProxyCommand).",
+ "f42d844544": "p.ej. acceso a la nube ssh --hostname %h",
+ "c7d0e18ecb": "Comando proxy",
+ "cb91f6375c": "Opcional. El agente SSH se utiliza de forma predeterminada.",
+ "d6a5f2ee5c": "~/.ssh/id_ed25519 (dejar vacío para el agente SSH)",
+ "63c0c145c1": "Archivo de identidad",
+ "c94cfa634c": "Puerto",
+ "47e082bc17": "desplegar",
+ "dc1dc52aaa": "Nombre de usuario",
+ "2ee9bcd2e8": "servidor, implementar@servidor:2222, ssh://servidor",
+ "ce370ce674": "Anfitrión o alias *",
+ "b8dab0aa7b": "mi servidor",
+ "298de87a88": "Etiqueta",
+ "9518545cb6": "Agregar destino",
+ "a62b4cb39a": "Guardar cambios",
+ "29af933cd5": "Nuevo destino SSH",
+ "f2331ce599": "Editar destino SSH"
+ },
+ "TasksPane": {
+ "3a72b9745e": "Elija qué proveedores de tareas aparecen en la página Tareas y en los accesos directos de la barra lateral.",
+ "f71d8a9dd3": "Proveedores de tareas",
+ "71644aba56": "Elija qué proveedores de tareas aparecen en el selector de fuente de la página Tareas y en los accesos directos de la barra lateral. Al menos un proveedor debe permanecer visible.",
+ "93e72ef659": "Fuentes de tareas",
+ "8e1305fcc6": "Muestre Jira en el selector de fuente de Tareas y en los accesos directos de la barra lateral.",
+ "6b23a34f6d": "Jira",
+ "e4170c9615": "Muestre Linear en el selector de fuente de Tareas y en los accesos directos de la barra lateral.",
+ "09ae2d7c51": "Linear",
+ "dd67a1b6e1": "Muestre GitLab en el selector de fuente de Tareas y en los accesos directos de la barra lateral.",
+ "7c5d7fdc20": "GitLab",
+ "1db47236cd": "Muestre GitHub en el selector de fuente de Tareas y en los accesos directos de la barra lateral.",
+ "e14063e727": "GitHub"
+ },
+ "TerminalAppearanceSection": {
+ "a14a427ae4": "Grosor de la línea divisoria del panel.",
+ "f27a99978d": "Grosor del divisor",
+ "db632cb50e": "Opacidad aplicada a paneles que no están actualmente activos.",
+ "a6fdd6a3b1": "Opacidad del panel inactivo",
+ "1b79379d4f": "Controle la atenuación del panel inactivo y divida el espesor del divisor.",
+ "e1a5c25555": "Paneles terminales",
+ "04cdf85dec": "Opacidad del cursor terminal.",
+ "b9f1804422": "Opacidad del cursor",
+ "2de6b5a699": "Utiliza la variante parpadeante de la forma del cursor seleccionada.",
+ "74736cc9b1": "Cursor parpadeante",
+ "2e5aec3cf6": "Subrayar",
+ "52854a5608": "Bloquear",
+ "e070e8aeba": "Bar",
+ "db270cc9a9": "Forma del cursor",
+ "d455f2ef4f": "Apariencia predeterminada del cursor para los paneles del terminal Orca.",
+ "abcb4dd019": "Cursor de terminales",
+ "70beb1bbc7": "Avance",
+ "31f6e61085": "Actualmente las ligaduras",
+ "870377082f": "Apagado",
+ "84bd22f2cd": "En",
+ "bc9ff84d61": "Auto",
+ "be8da35e7f": "Ligaduras de fuentes",
+ "4b1f29598e": "Automático: deshabilitado para \"{{value0}}\".",
+ "400e950ca5": "Automático: habilitado para \"{{value0}}\".",
+ "04569feb07": "Siempre desactivado, incluso para las fuentes que los incluyen.",
+ "7234abcd08": "Siempre encendido. Las fuentes sin ligaduras simplemente se muestran tal cual.",
+ "7233d594bf": "Renderice ligaduras de programación (por ejemplo, =>, !=, ===) para las fuentes que las incluyen. \"Auto\" habilita ligaduras solo para fuentes de ligadura conocidas (Fira Code, JetBrains Mono, Cascadia Code, Iosevka, etc.).",
+ "bafc80efbc": "Controla el multiplicador de altura de la línea terminal.",
+ "c084eb7d4c": "Altura de línea",
+ "36af8ad94c": "Controla el peso de la fuente del texto del terminal.",
+ "4aae5db258": "Peso de fuente",
+ "f04b17a50e": "Familia de fuentes de terminal predeterminada para nuevos paneles y actualizaciones en vivo.",
+ "a408266e67": "Familia de fuentes",
+ "855a76343a": "Importar desde Ghostty",
+ "711e589f18": "Tipografía de terminal predeterminada para nuevos paneles y actualizaciones en vivo.",
+ "048aac8a64": "Tipografía de terminales",
+ "4415beb958": "desactivado",
+ "4e7d41a9f0": "activado",
+ "e90afcc44f": "apagado",
+ "16c471ee03": "en"
+ },
+ "TerminalFontSizeSetting": {
+ "9b5252c85a": "píxeles",
+ "0f4c92e595": "Tamaño de fuente de terminal predeterminado para nuevos paneles y actualizaciones en vivo.",
+ "a4a352b1e9": "Tamaño de fuente"
+ },
+ "TerminalPane": {
+ "4263e940e0": "Al presionar la tecla JIS Yen (¥), se envía una barra invertida (\\\\).",
+ "19f4935159": "Yen JIS (¥) a Barra invertida (\\\\)",
+ "1c337bef4a": "Controla si al presionar la tecla JIS Yen (¥) se envía una barra invertida (\\\\).",
+ "3fe1c5bfe0": "Apagado",
+ "c73d510938": "Bien",
+ "e7aec1fd60": "Izquierda",
+ "badb1219fc": "Ambos",
+ "43c2ff7b0e": "Auto",
+ "0a10420e1a": "Opción como Alt",
+ "ce3aadf0b2": "La tecla Opción {{value0}} envía Alt/Esc; el otro compone caracteres especiales.",
+ "b62373091a": "Ambas teclas de opción envían secuencias Alt/Esc.",
+ "d8998bb328": "La opción compone caracteres especiales para la distribución de su teclado.",
+ "d21c493808": "Automático: detectado: {{value0}}.",
+ "2561d3fc1b": "Controla si la tecla Opción de macOS envía secuencias Alt/Esc o compone caracteres.",
+ "96be03b8eb": "PowerShell 7+",
+ "d26174e1dd": "WindowsPowerShell",
+ "fe20f79dd1": "Versión de PowerShell",
+ "822f62ddcd": "Descargar PowerShell 7+",
+ "a016ffbeed": "Auto usa Windows PowerShell ahora y cambia a PowerShell 7+ cuando está instalado.",
+ "5ed5c95344": "Elija entre Windows PowerShell y PowerShell 7+ para obtener nuevos paneles de terminal.",
+ "3d88af864d": "Elija si la opción de shell de PowerShell inicia Windows PowerShell o PowerShell 7+ para nuevos paneles de terminal.",
+ "8a956cc91e": "Caracteres tratados como límites de palabras para la selección con doble clic.",
+ "4bebcc2b2c": "Separadores de palabras",
+ "12e06178fa": "MEGABYTE",
+ "907b0b9d3e": "Costumbre",
+ "5336c096af": "{{value0}} megabytes",
+ "81d86b2dd2": "Tamaño máximo del búfer de desplazamiento hacia atrás del terminal para nuevos paneles de terminal.",
+ "9df53f7c14": "Tamaño de desplazamiento hacia atrás",
+ "c3810b2b42": "Tamaño máximo del búfer de desplazamiento hacia atrás del terminal.",
+ "267d020745": "Desplazamiento hacia atrás, límites de palabras y comportamientos de terminal específicos de la plataforma.",
+ "5e5f06c82c": "Avanzado",
+ "003df129fe": "Dividir horizontalmente",
+ "623e62df99": "Dividir horizontalmente",
+ "332e8a2872": "Dividir verticalmente",
+ "691ce810e0": "Dividir verticalmente",
+ "1158f8fd55": "Nueva pestaña",
+ "6c6a054a1c": "Ejecutar en una nueva pestaña",
+ "a9d47451d1": "\"Nueva pestaña\" abre el comando de configuración en una pestaña de fondo titulada \"Configuración\" sin robar el foco.",
+ "d23b43c5be": "Ubicación del script de configuración",
+ "34a0dfa06e": "Dónde se ejecuta el script de configuración del repositorio cuando se crea un nuevo espacio de trabajo.",
+ "21f8da2078": "Script de configuración del espacio de trabajo",
+ "6e6480a7df": "Deje que los programas en la terminal (tmux, Neovim, fzf, SSH) se copie al portapapeles de su sistema.",
+ "3338dcf8c1": "Permitir escrituras en el portapapeles TUI (OSC 52)",
+ "69c64a479c": "Deje que tmux, Neovim y fzf copie al portapapeles del sistema a través de PTY (incluso a través de SSH).",
+ "4729c645fc": "Copie automáticamente las selecciones de terminal al portapapeles.",
+ "902f5dee1f": "Copiar al seleccionar",
+ "9129b7e805": "Al pasar el cursor sobre un panel de terminal, se activa sin necesidad de hacer clic.",
+ "8eefeaa3da": "El foco sigue al ratón",
+ "96fe15def8": "Comportamiento del mouse y del portapapeles para paneles de terminales.",
+ "45721f3e67": "Interacción terminal",
+ "9c0b1c1792": "En",
+ "c1fc9e9444": "Aceleración de GPU",
+ "e0996d141a": "Auto prueba WebGL, con respaldo DOM para renderizadores riesgosos o no compatibles.",
+ "7eaccc1424": "Siempre se intenta WebGL para paneles de terminales.",
+ "fe4acf36c6": "WebGL deshabilitado; Renderizador DOM para máxima compatibilidad.",
+ "f07dfb4466": "Controla si el terminal utiliza la representación WebGL de xterm.js. Auto prueba WebGL cuando el renderizador es compatible, con una alternativa conservadora de Linux para software o renderizadores de GPU desconocidos.",
+ "72bc9334a0": "Comportamiento del renderizador de terminal para paneles activos y paneles nuevos.",
+ "2fba319f21": "Representación",
+ "cc8c5ca224": "predeterminado de Windows",
+ "d78fc4fdef": "Cargando distribuciones",
+ "219aaa59f4": "Distribución WSL",
+ "2503f1e86b": "Se utiliza para nuevos paneles de terminal WSL y detección de agentes locales cuando el espacio de trabajo activo aún no está dentro de WSL.",
+ "5fe79a5e56": "Elija qué distribución WSL utilizarán los nuevos terminales WSL y los análisis de agentes locales.",
+ "b637dd57a7": "WSL",
+ "f61ac77f16": "Git bash",
+ "0f1b8669e6": "Símbolo del sistema",
+ "eb7fc4d98a": "PowerShell",
+ "27e301f22c": "Shell predeterminado",
+ "09bf02de9a": "Shell utilizado al abrir un nuevo panel de terminal. Entra en vigor para nuevos terminales.",
+ "bd68f3170d": "Elija el shell predeterminado para los nuevos paneles de terminal en Windows.",
+ "a55eee649f": "Shell predeterminado para nuevos paneles de terminal en Windows.",
+ "87e678a8af": "Cáscara de Windows",
+ "05efc0bada": "verdadero",
+ "348246b06f": "FALSO",
+ "5936387ddd": "auto",
+ "adbafefe56": "costumbre",
+ "16753eea48": "En Windows, haga clic derecho y pegue el portapapeles. Ctrl+clic derecho abre el menú contextual.",
+ "9c178cf8aa": "Haga clic derecho para pegar",
+ "af0c3b6e39": "En Windows, haga clic derecho y pegue el portapapeles en la terminal. Utilice Ctrl+clic derecho para abrir el menú contextual.",
+ "29154326bb": "en",
+ "ab20575a8a": "apagado",
+ "ab3a1f9068": "wsl.exe"
+ },
+ "TerminalSettingsPreview": {
+ "a63953a48a": "Vista previa del tema {{value0}}",
+ "2c248fcc27": "Tema de vista previa",
+ "f8931d407d": "Mostrar divisor de panel en vista previa",
+ "50419052fe": "Divisor de panel",
+ "d06664e889": "oscuro"
+ },
+ "TerminalThemeSections": {
+ "db210115c5": "Vista previa del modo de luz",
+ "5e0c24b5c8": "Controla la línea divisoria dividida entre paneles en modo claro.",
+ "ec2e33ad80": "Color del divisor de luz",
+ "d56af60e6f": "Elige el tema utilizado cuando Orca está en modo claro.",
+ "8273bc75d7": "Tema ligero",
+ "74b15574c8": "Configure la apariencia del terminal en modo de luz opcional.",
+ "b584287e84": "Cuando está deshabilitado, el modo claro reutiliza el tema oscuro del terminal.",
+ "d76f60c9cc": "Utilice un tema independiente en el modo claro",
+ "bc8e8a251a": "Vista previa del modo oscuro",
+ "cbe56a0f79": "Controla la línea divisoria entre paneles en modo oscuro.",
+ "b739d2abfe": "Color divisor oscuro",
+ "7add204bd5": "Elija el tema del terminal utilizado en modo oscuro.",
+ "9499ad1dc4": "Tema oscuro",
+ "f012172e21": "Elija el tema utilizado para los paneles de terminal en modo oscuro."
+ },
+ "TerminalWindowSection": {
+ "1705318506": "color magenta ANSI",
+ "03c855d15f": "Restablecer todas las anulaciones de color",
+ "63f8d9336e": "Anulaciones de color",
+ "e86e09b5c7": "Anula los colores de terminales individuales.",
+ "1d1920dc8a": "Oculte el cursor del mouse al escribir en la terminal.",
+ "3530908ef9": "Ocultar el mouse mientras escribe",
+ "1846f6ee6a": "Relleno vertical alrededor de la cuadrícula del terminal en píxeles.",
+ "1afcc1d973": "Acolchado vertical",
+ "25e2f8e8e1": "Relleno horizontal alrededor de la cuadrícula del terminal en píxeles.",
+ "36b8402015": "Acolchado horizontal",
+ "53ce336e15": "Reinicie Orca para aplicar el cambio de desenfoque de ventana.",
+ "c65bb9ce63": "Reiniciar requerido",
+ "97950bb087": "Aplique desenfoque de fondo a la ventana del terminal. Requiere reinicio.",
+ "2b82242f43": "Desenfoque de ventana",
+ "809f37738d": "Controla la transparencia del fondo del terminal. 1 es completamente opaco, 0 es completamente transparente.",
+ "ea7b1a158e": "Opacidad del fondo",
+ "03acb60aa0": "Controla la transparencia del fondo del terminal.",
+ "00eaa6b881": "Configuración de apariencia y fondo de la ventana.",
+ "b96ba13ed1": "Ventana",
+ "42e01a6055": "Color blanco brillante ANSI",
+ "16948119cb": "Blanco brillante",
+ "1601140f03": "Color cian brillante ANSI",
+ "f94adc4113": "Cian brillante",
+ "fe4d89ef85": "Color magenta brillante ANSI",
+ "e56e7d6ea0": "magenta brillante",
+ "bef6c0f6bf": "ANSI color azul brillante",
+ "66820332fa": "azul brillante",
+ "e2ef5f4ab7": "Color amarillo brillante ANSI",
+ "936a326be3": "Amarillo brillante",
+ "0ffb02f921": "Color verde brillante ANSI",
+ "7dafd57730": "verde brillante",
+ "667de68863": "Color rojo brillante ANSI",
+ "32b1b6acd7": "Lacre",
+ "f30c492769": "ANSI color negro brillante",
+ "260d69ce9a": "Negro brillante",
+ "1be593d3e8": "ANSI brillante",
+ "28846b1ca6": "color blanco ANSI",
+ "0cb4459fb8": "Blanco",
+ "bd4c759327": "Color cian ANSI",
+ "fb8bb4eb1f": "cian",
+ "d5e92fcd94": "Magenta",
+ "9635a71c51": "Color azul ANSI",
+ "292a4c7316": "Azul",
+ "09c1c6b096": "Color amarillo ANSI",
+ "bb516de873": "Amarillo",
+ "8a673d4206": "color verde ANSI",
+ "8f2092b315": "Verde",
+ "b41270f5ca": "Color rojo ANSI",
+ "3a78f30b50": "Rojo",
+ "cf4437a2f7": "Color negro ANSI.",
+ "adfdee23cb": "Negro",
+ "68e9f07de0": "Norma ANSI",
+ "fb8c6f1967": "Color para texto en negrita. Vuelve al color normal si no se establece.",
+ "862e463f7f": "Texto en negrita",
+ "b2c0857c49": "Color del texto del texto seleccionado",
+ "8b450b5305": "Selección en primer plano",
+ "74d8555f85": "Color de fondo del texto seleccionado",
+ "40c3cfd30a": "Antecedentes de selección",
+ "7f4063076c": "Color del texto debajo del cursor (cursor de bloque)",
+ "a2d9f095a7": "Texto del cursor",
+ "cd0700762b": "Color del cursor",
+ "c9e1fdf42f": "Cursor",
+ "da64e8f4c1": "Color de fondo del terminal",
+ "cc1b2ffeb2": "Fondo",
+ "026a0b8013": "Color del texto principal",
+ "79f6bfb76e": "Primer plano",
+ "cf37ff69f6": "Base",
+ "8abdab9f7c": "Reiniciar ahora",
+ "907131d741": "Reiniciando…"
+ },
+ "UIZoomControl": {
+ "c2c64b24d0": "Reiniciar"
+ },
+ "VoicePane": {
+ "68de13f72c": "No se pudo eliminar el modelo.",
+ "1ba81c0ff0": "recomendado",
+ "cfde55c7b0": "No se pudo descargar el modelo.",
+ "43fd4f454b": "Modelo de habla",
+ "7cf715f891": "se lleva a cabo.",
+ "295d84b849": "una vez para empezar, otra vez para parar. Mantener: dictar mientras",
+ "ff9a680010": "Alternar: presionar",
+ "ba4a900d1d": "Modo de dictado",
+ "0121960365": "Habilitar dictado de voz",
+ "366e1b4f36": "para dictar texto en cualquier panel enfocado.",
+ "4465596675": "Prensa",
+ "62d2a84d31": "No se pudo borrar la clave API de OpenAI",
+ "37aba8bb63": "Clave API de OpenAI borrada",
+ "8572bbb537": "No se pudo guardar la clave API de OpenAI",
+ "506df81ba6": "Clave API de OpenAI guardada",
+ "91980ce124": "{{value0}}MB",
+ "61a16c8141": "Extrayendo...",
+ "b6536a1d12": "extrayendo",
+ "8f4d2a51d7": "desconectado",
+ "d504ab05f0": "transmisión",
+ "fbe5990716": "Seleccionar modelo",
+ "e24f7d43d2": "Seleccione un modelo de discurso. Los modelos locales funcionan sin conexión; Los modelos en la nube requieren una clave API.",
+ "174da92062": "Sostener",
+ "118b3c2dee": "Palanca",
+ "901985625d": "palanca",
+ "ad5d036ecc": "No se pudo solicitar permiso del micrófono. El dictado de voz no estaba habilitado.",
+ "f9a9cf6928": "Se requiere permiso del micrófono antes de habilitar el dictado de voz.",
+ "1eac933202": "Se abrió Privacidad y seguridad de macOS. Habilite el dictado nuevamente después de otorgar acceso.",
+ "cd9fe37556": "Permiso de micrófono concedido"
+ },
+ "WorktreeSymlinksSection": {
+ "1c1e35b219": "Quitar {{value0}}",
+ "b814c618e2": "Caminos vinculados",
+ "31ebab5403": "No hay rutas de enlaces simbólicos configuradas para este repositorio.",
+ "ea06227efa": "agregado",
+ "b2429aeb31": "Agregar",
+ "ab40b8a5f1": "Sin coincidencias. Sigue escribiendo para agregar una ruta personalizada.",
+ "4cd2a4c077": "Escriba una ruta (por ejemplo, .env o node_modules)…",
+ "241325302c": "Agregar ruta",
+ "7ff265071d": "Cuando se crea un nuevo árbol de trabajo, cada ruta enumerada aquí tendrá un enlace simbólico desde el pago principal.",
+ "4755f120b6": "Enlaces simbólicos del árbol de trabajo",
+ "b07ef5a8b6": "Rutas para vincular simbólicamente desde el pago principal a árboles de trabajo recién creados.",
+ "d72ba8dc68": "{{value0}} caminos",
+ "9ea912d811": "1 camino"
+ },
+ "WslCliRegistration": {
+ "c6f6f89d7c": "Cancelar",
+ "119fef6cd2": "Ruta de destino:",
+ "1dbb0377d9": "Objetivo del lanzador existente:",
+ "554305956d": "Ruta de comando:",
+ "9b6627522c": "Refrescar",
+ "ab6b022a5c": "Actualizar el estado de la CLI de WSL",
+ "d9c6880dbd": "comando de shell WSL",
+ "52d990420e": "No se pudo eliminar `{{value0}}` de WSL.",
+ "89c7414cf5": "Se eliminó `{{value0}}` de WSL.",
+ "6f91ad1333": "No se pudo registrar `{{value0}}` en WSL.",
+ "951536dda5": "Registrado `{{value0}}` en WSL.",
+ "26b4b3b00f": "No se pudo cargar el estado de la CLI de WSL.",
+ "290bfff3ab": "Registro",
+ "f951f85196": "Eliminar",
+ "4c4a9178a3": "Registrando...",
+ "41a1480d3e": "instalar",
+ "4598b18464": "Eliminando...",
+ "7c3bb36706": "eliminar",
+ "7ee4e52b99": "Orca registrará {{value0}} para que el comando funcione desde terminales WSL.",
+ "d8216eb22e": "Esto elimina el comando de shell WSL. La propia Orca permanece instalada en Windows.",
+ "e49688f67f": "¿Registrar `{{value0}}` en WSL?",
+ "61ac55278e": "¿Eliminar `{{value0}}` de WSL?",
+ "e2b0ee267f": "duro",
+ "7aa456a460": "Registre `orca-ide` en ~/.local/bin dentro de WSL.",
+ "0307677bb9": "Comprobando el registro de WSL CLI..."
+ },
+ "accounts": {
+ "search": {
+ "86edc96bc9": "barra de estado",
+ "e949b08ffb": "límite de tasa",
+ "7e67d7d1b6": "trabajo",
+ "421c6be25e": "identificación",
+ "be8b621bdc": "espacio de trabajo",
+ "8dcbef1856": "código abierto",
+ "38d22ff8d6": "Anulación opcional del ID del espacio de trabajo si falla la búsqueda automática.",
+ "4ee2029e9c": "ID del espacio de trabajo de OpenCode Go",
+ "9c4e40cf6b": "sesión",
+ "61f7d1fcbe": "galleta",
+ "d1d2ae383c": "Pegue su cookie de sesión de opencode.ai para obtener el límite de velocidad.",
+ "6ed1401020": "Cookie de sesión de OpenCode Go",
+ "b7c2cee442": "experimental",
+ "7118d2f908": "cartas credenciales",
+ "933deaf732": "juramento",
+ "8630464352": "cli",
+ "e8e1ff3887": "gemini",
+ "bada4a3218": "Extrae las credenciales de OAuth de su instalación local de CLI de Gemini para autenticarse con Google.",
+ "d819755b02": "Utilice las credenciales de la CLI de Gemini",
+ "35b461d817": "iniciar sesión",
+ "f2d666a886": "opcional",
+ "8b06729e0f": "activo",
+ "5b3f18ef4a": "cambiar",
+ "06662af91e": "cuenta",
+ "70d1b8def5": "codex",
+ "87a4a8584e": "Elija qué cuenta Codex guardada opcional impulsa las lecturas de cuotas en vivo.",
+ "a4bcfd6f86": "Cuenta activa del Codex",
+ "042885c07c": "fuera de fecha",
+ "02c438bc7b": "venció",
+ "77e32a2ad3": "volver a autenticar",
+ "c759741d77": "cuota",
+ "b40d5b6570": "Cambio de cuenta opcional para Codex y recuperación de límite de tasa en vivo.",
+ "17c5d244eb": "Cuentas del Codex",
+ "e14049e1a8": "claude",
+ "dd75a73991": "Cambio de cuenta opcional para Claude preservando el contexto de chat compartido.",
+ "75682e1b62": "Cuentas Claude",
+ "e02c136ad0": "autenticación",
+ "9f70aa706c": "proveedor",
+ "488a7e9206": "Linux",
+ "0b4d948eb5": "wsl",
+ "bdbd1e668e": "ventanas",
+ "593720c17f": "ubicación",
+ "b84a5b0c8a": "Elija si las cuentas de proveedor se inspeccionan y agregan en este dispositivo o en WSL.",
+ "d09fb5ca92": "Ubicación de la cuenta"
+ }
+ },
+ "advanced": {
+ "search": {
+ "a7002e1ac4": "actualizador",
+ "e61ed8ab33": "actualizaciones",
+ "6576fce4d2": "solución de problemas",
+ "79e0947e95": "apoyo",
+ "4383251647": "VPN",
+ "f98a60af11": "apoderado",
+ "65bf6af262": "compatibilidad",
+ "621233008b": "http/1.1",
+ "f8ff125ebe": "http1",
+ "a0f71bd909": "http/2",
+ "4b4ae4345a": "http2",
+ "48a1c8f534": "http",
+ "4d44352eea": "red",
+ "2b4d26d11e": "redes",
+ "e04e9db503": "avanzado",
+ "585f56fae0": "Utilice HTTP/1.1 para redes Electron cuando HTTP/2 falle detrás de un proxy.",
+ "11eea3da72": "Compatibilidad HTTP/1.1"
+ }
+ },
+ "agents": {
+ "search": {
+ "2814401339": "instalado",
+ "719f53350c": "camino",
+ "839e82c81f": "detectar",
+ "f622b8eb2a": "Linux",
+ "d608654c03": "wsl",
+ "77c02fa3c3": "ventanas",
+ "d2952dfd74": "ubicación",
+ "96ba2373b6": "agente",
+ "cbdd7f3b9e": "Elija si los agentes instalados se detectan en este dispositivo o en WSL.",
+ "ef804b7337": "Ubicación del agente",
+ "01926b9d8c": "Configure agentes de codificación de IA, agente predeterminado y anulaciones de comandos.",
+ "bb9ad95777": "Agentes",
+ "d8f3a8b8a0": "por defecto",
+ "167daeb5e9": "dominio",
+ "be59907510": "anular",
+ "a6d594c17d": "instalar",
+ "f2932bf22b": "detectado",
+ "2afd3b5858": "permitir",
+ "60393e1b17": "desactivar",
+ "2e188c771c": "esconder",
+ "87fffe6c20": "espectáculo",
+ "e2b7c0dcd7": "github",
+ "66b6b82eb4": "despierto",
+ "dbc8aca6b0": "dormir",
+ "845ad9128a": "fuerza",
+ "48f84d10f1": "correr",
+ "affbf130f6": "laboral",
+ "0d1c334987": "tapa",
+ "ff8de8a2ad": "mostrar",
+ "0d752916f8": "manos",
+ "6984d4291a": "estado",
+ "13b20636a6": "espera",
+ "8599603496": "hecho",
+ "ea71995548": "eliminar",
+ "c1317fe641": "restaurar",
+ "5963143e00": "ajustes",
+ "042c551bc5": "configuración",
+ "f412abbba5": "claude",
+ "5ded38b843": "codex",
+ "be7ea3553b": "pestaña",
+ "6956646a1e": "título",
+ "32836788b0": "título generado",
+ "966890236d": "nombre",
+ "848dcae8d3": "generado",
+ "52115d0d7c": "auto",
+ "c64059f50d": "inmediato",
+ "5784ae8c43": "rebautizar",
+ "8a17fd6026": "estable",
+ "a79d266f71": "sesión",
+ "afbf35be68": "sesión estable"
+ }
+ },
+ "appearance": {
+ "search": {
+ "468448bba4": "acuarela",
+ "f586abfa35": "azul",
+ "651f35b2c6": "conmutador",
+ "e5bc35d59e": "ventana",
+ "d18b54ca90": "muelle",
+ "1f2880a9d5": "orca",
+ "2cfb3420c0": "icono de la aplicación",
+ "e80c2af428": "Elija el ícono de la aplicación que se muestra en el Dock y en el selector de ventanas.",
+ "2b313598c6": "Icono de aplicación",
+ "839fb1e3ed": "caja de instrumento",
+ "ac79fe4a04": "espectáculo",
+ "648eeada79": "esconder",
+ "6cf5f54ce1": "botón",
+ "5bff6a2ef0": "barra lateral",
+ "5e5b8878bf": "teléfono",
+ "74618577c7": "móvil",
+ "682293cadf": "Muestra el botón de Orca Mobile en la parte superior de la barra lateral izquierda.",
+ "1de96ec8a6": "Mostrar botón móvil de Orca",
+ "4c920ab2d1": "cronograma",
+ "58f4e22fa2": "automatización",
+ "b186f3cefb": "automatizaciones",
+ "ae13a0d340": "Muestra el botón Automatizaciones en la parte superior de la barra lateral izquierda.",
+ "caa27e1a8e": "Botón Mostrar automatizaciones",
+ "6b846424cc": "lineal",
+ "2ee4810f38": "github",
+ "0d5a74b606": "tareas",
+ "9a248333c7": "Muestra el botón Tareas en la parte superior de la barra lateral izquierda.",
+ "155a1e7438": "Botón Mostrar tareas",
+ "a895d0f938": "marca",
+ "51f957ce39": "nombre",
+ "36e006efc1": "aplicación",
+ "bed343b03e": "barra de título",
+ "18b4c4c30b": "Muestra Orca en la barra de título.",
+ "fdd31b00d0": "Nombre de la aplicación de la barra de título",
+ "c1bca1885a": "explorador de archivos",
+ "9f2df826ac": "ignorado",
+ "08c86bf58e": "gitignorar",
+ "bce3ac317a": "git",
+ "7164edf71a": "Atenúe los archivos que coincidan con .gitignore en el explorador de archivos.",
+ "f8129fb544": "Mostrar archivos ignorados por Git",
+ "2f12e1aa3a": "interfaz de usuario",
+ "5095258df2": "interfaz",
+ "fab91464dd": "idea",
+ "8b36fb3f64": "tipografía",
+ "a0e09aed9c": "tipo de letra",
+ "24094af355": "fuente",
+ "07c7c38fac": "Elija la fuente utilizada por la interfaz de Orca.",
+ "ddb991024d": "Fuente IDE",
+ "0c83659f48": "atajo",
+ "0952091186": "escala",
+ "3ae5de6101": "zoom",
+ "adddb91a3d": "Escale toda la interfaz de la aplicación.",
+ "c5e933970f": "Ampliación de la interfaz de usuario",
+ "3a9b69d734": "sistema",
+ "44d873fd18": "luz",
+ "262fe1d24f": "oscuro",
+ "0709c794f7": "Elige cómo se ve Orca en la ventana de la aplicación.",
+ "71e06350b4": "Tema",
+ "dc02c8759d": "espacio de trabajo",
+ "43cfba3b95": "servidor",
+ "46d21eef62": "servidor local",
+ "006e67b279": "puertos",
+ "896eb53fd4": "barra de estado",
+ "0ececfa190": "Muestre los puertos del espacio de trabajo en vivo en la barra de estado.",
+ "cf409b6c4d": "Puertos",
+ "cb1cc62cf8": "espacio",
+ "90bdc043ea": "disco",
+ "96b4fb0064": "Terminal",
+ "4ddbde4999": "UPC",
+ "4355f18ac6": "memoria",
+ "9c4d5f0894": "gerente",
+ "c690a15849": "recurso",
+ "81ef5abc2f": "Muestra el uso de CPU, memoria, sesiones de terminal y disco del espacio de trabajo en la barra de estado.",
+ "7cf005b29f": "Administrador de recursos",
+ "fe192b060e": "anfitrión",
+ "f4997e0f8a": "conexión",
+ "a278406ed5": "remoto",
+ "6ecad74eb3": "ssh",
+ "f17d66d0d2": "Muestra el estado de la conexión SSH activa en la barra de estado.",
+ "57fb424c56": "Estado SSH",
+ "35565867cb": "disparo a la luna",
+ "de586def95": "suscripción",
+ "00a028f25f": "uso",
+ "40e5c3c285": "kimi",
+ "c927a155d5": "Muestra el uso de la suscripción de Kimi en la barra de estado.",
+ "3a6c028ea8": "Uso de Kimi",
+ "edbf0f63a0": "costo",
+ "afbb6a3767": "fichas",
+ "d77537b580": "código abierto-ir",
+ "a9d56852eb": "código abierto",
+ "7f72de7cbe": "Muestra el token OpenCode Go y el uso de costos en la barra de estado.",
+ "bc046e7899": "Uso de OpenCode Go",
+ "51b0ccd6a2": "Google",
+ "2804a920ad": "gemini",
+ "9660c5b2f1": "Muestra el token Gemini y el uso de costos en la barra de estado.",
+ "5bfb874d05": "Uso de Gemini",
+ "97957e374e": "abierto",
+ "8dfd676c28": "codex",
+ "e9e4412545": "Muestra el token Codex y el uso de costos en la barra de estado.",
+ "54b1acf24f": "Uso del Codex",
+ "dea0a9a665": "anthropic",
+ "c9fe3a7876": "claude",
+ "de50c6f516": "Muestra el token de Claude y el uso de costos en la barra de estado.",
+ "9dc15020d7": "Uso de Claude",
+ "language": {
+ "locale": "lugar",
+ "i18n": "i18n",
+ "translation": "traducción"
+ }
+ }
+ },
+ "auto": {
+ "rename": {
+ "branch": {
+ "search": {
+ "0971762141": "estuche-kebab",
+ "a482f6a423": "babosa",
+ "7adefcdd94": "plantilla",
+ "10485c4fc5": "dominio",
+ "50139297e6": "aviso incorporado",
+ "502aa57681": "instrucciones",
+ "40d21f2efc": "inmediato",
+ "672387fb77": "Plantilla de comando del agente utilizada al generar nombres de sucursales.",
+ "722551c5b3": "Plantilla de comando de nombre de sucursal",
+ "f41833025e": "generar",
+ "ed677944cc": "árbol de trabajo",
+ "3ef3cbe98c": "agente",
+ "f0acf64301": "nombre de la criatura",
+ "7803423877": "auto",
+ "55a1860e47": "rebautizar",
+ "9319bd9827": "rama",
+ "ea94b9da8a": "Cambie el nombre de la rama generada automáticamente según el trabajo una vez que comience un agente.",
+ "427f2cd1eb": "Rama de cambio de nombre automático"
+ }
+ }
+ }
+ },
+ "browser": {
+ "search": {
+ "7539f6336c": "perfil",
+ "1c1e097985": "arco",
+ "533a253deb": "borde",
+ "75a0d435b7": "cromo",
+ "854ef6ce83": "acceso",
+ "3910a41f32": "autenticación",
+ "2e7f951773": "importar",
+ "66dd641a47": "sesión",
+ "29193a51d5": "galletas",
+ "2d2d995c58": "navegador",
+ "060ac1fcba": "Importe cookies de Chrome, Edge u otros navegadores para utilizar los inicios de sesión existentes dentro de Orca.",
+ "96afedcb5c": "Sesión y cookies",
+ "a7a07d5415": "editor",
+ "8dd4805991": "archivo",
+ "68d1db8929": "reducción",
+ "90425d313c": "cambio",
+ "72c58f7792": "vista web",
+ "82ba1c80ea": "servidor local",
+ "bea27bac4b": "campo de golf",
+ "44d14df30d": "avance",
+ "5cb082b3e3": "Enrutamiento de enlaces",
+ "95944898e0": "porcentaje",
+ "483a0eb5e0": "nueva pestaña",
+ "726f2a8556": "ampliación de página",
+ "5448f4097b": "por defecto",
+ "54f4ea55f7": "escala",
+ "4a98ed195f": "zoom",
+ "c3d89ed4d0": "Nivel de zoom aplicado a las pestañas del navegador recién abiertas.",
+ "072b7f5c1f": "Zoom predeterminado",
+ "0bb34eacc9": "consulta",
+ "8b8ed06e4b": "omnibox",
+ "3538b3aaeb": "simbólico",
+ "0732ebe6fb": "privado",
+ "e1c2a57f07": "kagi",
+ "ad40e75d13": "bing",
+ "1f8153acfb": "patopatogo",
+ "8a489aab8d": "Google",
+ "72b4b89970": "motor",
+ "16bd69cd82": "buscar",
+ "0628d5943b": "Motor de búsqueda utilizado al escribir texto que no es una URL en la barra de direcciones.",
+ "5e755920c9": "Motor de búsqueda predeterminado",
+ "4596a52cf7": "aterrizaje",
+ "5164c47e31": "blanco",
+ "4fda4fb066": "URL",
+ "0dbb1eaf4e": "página principal",
+ "291f480a5e": "hogar",
+ "a942905148": "URL abierta al crear una nueva pestaña del navegador. Déjelo vacío para abrir una pestaña en blanco.",
+ "c3903322d2": "Página de inicio predeterminada"
+ },
+ "use": {
+ "search": {
+ "3f4c559deb": "perfil de arco",
+ "d5afa54d21": "perfil de borde",
+ "22fb801af8": "perfil cromado",
+ "59968bb9b4": "navegador autenticado",
+ "62e2a790c0": "sesión existente",
+ "63a66da648": "navegador del sistema",
+ "20c1323d1e": "uso de la computadora",
+ "ab349a2dd0": "arco",
+ "2e1b09897b": "borde",
+ "088e7a9012": "cromo",
+ "96ce3d2de2": "autenticación",
+ "48557f639c": "acceso",
+ "d5ad1f7aad": "importar",
+ "02837ee497": "sesión",
+ "fb8178824f": "galletas",
+ "ba4eb53b72": "uso del navegador",
+ "2fb24d17db": "Importe cookies de Chrome, Edge u otros navegadores para que los agentes puedan reutilizar sus inicios de sesión.",
+ "614c756ab1": "Importar cookies del navegador",
+ "cee44fb442": "automatización",
+ "a57c2172dc": "navegador-agente",
+ "6ea88e5206": "npx",
+ "f5b8fdddf5": "orca-cli",
+ "e5a784bc54": "instalar",
+ "9d97446873": "agente",
+ "a2d489263e": "habilidad",
+ "a7e82445fa": "Instale la habilidad Uso del navegador para que los agentes puedan operar el navegador de Orca.",
+ "a1414dcefb": "Instalar la habilidad de uso del navegador",
+ "e56c7b55c9": "configuración",
+ "034c5e8d7f": "permitir",
+ "7e0dcb257a": "caparazón",
+ "3ffafc9b95": "dominio",
+ "30c74aaa1f": "camino",
+ "ff05cbc344": "orca",
+ "85fab5e12c": "cli",
+ "890ddf943d": "Registre la CLI de Orca para que los agentes puedan controlar el navegador.",
+ "50f0860e18": "Habilitar CLI de Orca"
+ }
+ }
+ },
+ "commit": {
+ "message": {
+ "ai": {
+ "search": {
+ "3766941527": "agente",
+ "181cdb0637": "abierto",
+ "8e9cc598d7": "generar",
+ "b7d50da4d8": "plantilla",
+ "7e264b926b": "borrador",
+ "b261c88609": "pr",
+ "110be48b81": "solicitud de extracción",
+ "001ca3f2af": "Valores predeterminados utilizados cuando se abre el compositor Crear PR.",
+ "eefd33788c": "Valores predeterminados de creación de relaciones públicas",
+ "d32936bb2a": "rama",
+ "127d512e75": "comprometerse",
+ "d22a6459e4": "conflictos",
+ "53e8504fb2": "ci",
+ "c46e665f7e": "cheques",
+ "37c65bbb44": "arreglar",
+ "402f101af8": "inmediato",
+ "8e0bcc5d99": "modelo",
+ "f4731b22bf": "dominio",
+ "57c851a68c": "cli",
+ "61117e57f3": "argumentos",
+ "0f29331fed": "argumentos",
+ "18b6d38835": "Agente, argumentos CLI y plantilla de comando utilizados por cada botón AI de control de código fuente.",
+ "3c4e5e5938": "Recetas de acción",
+ "ee14a9e9f7": "activado",
+ "82109d627d": "control de fuente",
+ "542e1a00a7": "codex",
+ "f121bec167": "claude",
+ "93e5210da8": "mensaje",
+ "c33cb1b982": "ai",
+ "0b946b2abe": "Agrega recetas de acciones para acciones de confirmación de control de código fuente, solicitud de extracción, nombre de rama y reparación.",
+ "24dbdfca78": "Mostrar acciones de IA de control de código fuente"
+ }
+ }
+ }
+ },
+ "computer": {
+ "use": {
+ "search": {
+ "6e88da3508": "habilidad",
+ "798be54d7e": "automatización",
+ "e27f8bafbf": "captura de pantalla",
+ "26c1290d83": "grabación de pantalla",
+ "82f01c2d2c": "accesibilidad",
+ "fefb452f5b": "uso de la computadora",
+ "9210db582b": "Permita que los agentes inspeccionen capturas de pantalla y operen aplicaciones locales cuando usted lo solicite.",
+ "442bec10fe": "Uso de la computadora"
+ }
+ }
+ },
+ "developer": {
+ "permissions": {
+ "search": {
+ "3363889768": "Red local, USB y Bluetooth",
+ "6c82846f66": "dispositivo",
+ "11653d3f42": "mdns",
+ "78a10b826f": "buen día",
+ "e3fbc48083": "bluetooth",
+ "c4a4a02ea4": "USB",
+ "fa3239cd42": "red local",
+ "acad3d4743": "Permitir que las herramientas del dispositivo y de la red local se utilicen desde sesiones de terminal.",
+ "3e0131e45d": "nube",
+ "ce07159ff5": "de oficina",
+ "a0c19119fb": "descargas",
+ "4438f81bfa": "documentos",
+ "c10e36cbd1": "acceso completo al disco",
+ "05ab708ee5": "Abra el panel de privacidad de macOS para obtener un amplio acceso a los archivos del terminal.",
+ "bbf543a3a1": "Acceso completo al disco",
+ "7f145a3984": "ventana",
+ "5610022e1e": "automatización",
+ "0a467b750e": "captura de pantalla",
+ "08f8039ca9": "accesibilidad",
+ "3cd51d18a1": "grabación de pantalla",
+ "2e5d98ab56": "Permita capturas de pantalla, inspección de pantalla, pulsaciones de teclas y automatización de ventanas.",
+ "39bb49e662": "Grabación de pantalla y accesibilidad",
+ "00e954319e": "susurro",
+ "1e6e27b202": "ffmpeg",
+ "f061f08b7b": "medias",
+ "a765112513": "video",
+ "b192432ef0": "audio",
+ "af122938a3": "voz",
+ "259b829b84": "cámara",
+ "ed7c12bdb4": "micrófono",
+ "6eca1636b7": "Permitir herramientas de captura de voz, transcripción, cámara web y medios.",
+ "302c0c42f9": "Micrófono y cámara",
+ "4e225e7c56": "herramientas de desarrollo",
+ "6db4fca386": "macos",
+ "0c13b249e3": "tcc",
+ "2270ccff3f": "privacidad",
+ "a98aa11a9c": "permisos",
+ "bc8ac95310": "Permisos de macOS para herramientas de desarrollador lanzadas en terminal.",
+ "e92cb0896d": "Permisos de desarrollador"
+ }
+ }
+ },
+ "experimental": {
+ "search": {
+ "44c7f209d5": "módulos_nodo",
+ "4ad605f222": "ambiente",
+ "3021571c30": "compartido",
+ "f082788cfe": "campo de golf",
+ "3028f0bd3a": "enlace",
+ "bff1ff7768": "enlaces simbólicos",
+ "c387565812": "enlace simbólico",
+ "10b52f79c1": "árboles de trabajo",
+ "d23ae13990": "árbol de trabajo",
+ "0d24759f14": "experimental",
+ "603d29ed74": "Vincula automáticamente archivos o carpetas configurados en árboles de trabajo recién creados para que el estado compartido (envs, cachés, instalaciones) permanezca conectado.",
+ "78c2a8dc74": "Enlaces simbólicos en árboles de trabajo",
+ "7b79081695": "no leído",
+ "f10d307468": "terminación",
+ "5f067ba0f9": "agente",
+ "7695fd30e9": "notificación",
+ "8facf10138": "campana",
+ "edc49480a1": "cristal",
+ "268e99d957": "destacar",
+ "01567f19ca": "atención",
+ "9bb3bd5098": "Terminal",
+ "11877246fc": "Resaltado de panel persistente para eventos de finalización de agente y timbre de terminal.",
+ "9e4ddf776d": "Atención terminal",
+ "fe5688b761": "barra lateral",
+ "ca5d1f3f46": "línea de tiempo",
+ "d01b3882ba": "notificaciones",
+ "244a0ecd3d": "actividad",
+ "92a9357d1f": "vista de agentes",
+ "fa72e71f05": "agentes",
+ "4d63251595": "Feed integrado en la barra lateral izquierda para completar agentes y estados de bloqueo.",
+ "ccc5548ac5": "Vista de agentes",
+ "9af7a518db": "personaje",
+ "791fefc0b0": "esquina",
+ "65df471ab2": "animado",
+ "9f5609bfb8": "cubrir",
+ "2a33975d72": "mascota",
+ "b54cea709b": "compañero",
+ "051203d37c": "mascota",
+ "6b5a56ac35": "Mascota animada flotante en la esquina inferior derecha.",
+ "87d99e634b": "Mascota"
+ }
+ },
+ "floating": {
+ "workspace": {
+ "search": {
+ "94f4d013c8": "barra de estado",
+ "a452146574": "botón de alternancia",
+ "6765b85e48": "directorio de inicio",
+ "a38bfc3f77": "panel rápido",
+ "52db6e3baf": "notas",
+ "156ffeee08": "nota",
+ "884e5e6132": "reducción",
+ "49db74a92d": "navegador",
+ "6410fe83d8": "Terminal",
+ "2b5efa55c9": "global",
+ "ebeedb2f6a": "terminal rápido",
+ "6f183fa1b9": "terminal flotante",
+ "a08e482f6d": "espacio de trabajo flotante",
+ "b96b5ee6cf": "Habilite el espacio de trabajo flotante, elija dónde comienzan las nuevas pestañas y elija dónde aparece el botón de alternancia.",
+ "b2b60e7163": "Espacio de trabajo flotante"
+ }
+ }
+ },
+ "general": {
+ "search": {
+ "bdfb6dc21b": "como",
+ "e6b01c8e30": "comentario",
+ "b65665703a": "apoyo",
+ "06ea5a69a6": "github",
+ "e4fb4516d0": "estrella",
+ "e0b8c8bc25": "Apoye el proyecto con una estrella de GitHub a través de la CLI de gh.",
+ "36a72f0d9e": "Orca estrella en GitHub",
+ "c61b14be7c": "asimilar",
+ "5d9ba08673": "copiloto",
+ "f472e97440": "ayudante",
+ "3c30fe2d51": "gemini",
+ "5fdf1dc2d1": "omp",
+ "9b0bc30160": "pi",
+ "882c4896fd": "código abierto",
+ "27d9b996ba": "codex",
+ "5baf51c4d9": "claudio abierto",
+ "aea7d2cccb": "claudia abierta",
+ "95b63edde7": "claude",
+ "41c2f9a025": "por defecto",
+ "8ea37a05bc": "agente",
+ "e2da948f59": "Preseleccione un agente de codificación de IA en el compositor del nuevo espacio de trabajo.",
+ "db11502270": "Agente predeterminado",
+ "3462308bd3": "fichas",
+ "660528b048": "costo",
+ "585beac3f8": "ttl",
+ "0efc9d96ad": "inmediato",
+ "939b80f5fd": "minutero",
+ "b2601a778c": "cache",
+ "40c9585e43": "Temporizador de cuenta regresiva que muestra el tiempo hasta que caduque el caché de mensajes (agentes Claude).",
+ "1e0f28c6f1": "Temporizador de caché rápido",
+ "e49e739a59": "descargar",
+ "c9d8c1ce66": "notas de lanzamiento",
+ "9e86ccd05c": "versión",
+ "f89a94773c": "actualizar",
+ "79ff46776e": "Busque actualizaciones de la aplicación e instale una versión más reciente de Orca.",
+ "e15af4eb64": "Buscar actualizaciones",
+ "6382fe9724": "npx",
+ "baa263d6d8": "agentes",
+ "bda108e66c": "habilidad",
+ "244e3fb4c8": "Instale la habilidad Orca para que los agentes sepan cómo usar la CLI de Orca.",
+ "2d9f7b42df": "Habilidad del agente",
+ "0a00691c06": "comando de shell",
+ "dbeb1f348e": "dominio",
+ "88d3df9ce9": "Terminal",
+ "fb4f338a3d": "camino",
+ "924a660a78": "cli",
+ "ca529079bf": "Registre o elimine el comando CLI de Orca.",
+ "327e3fa70d": "CLI de Orca",
+ "fb84767421": "cambiar",
+ "f8f0ac213a": "secuencial",
+ "12ecc640a8": "mru",
+ "54ba13831a": "reciente",
+ "750420dd9a": "control",
+ "fe62b3f09f": "control",
+ "2a254b725e": "pestaña",
+ "ca812803ea": "orden de tabulación reciente",
+ "e53d585ed6": "Tira reciente o de pestañas.",
+ "256d92554d": "Orden de tabulación",
+ "22572e99c1": "anotaciones",
+ "1ff67ba40c": "notas",
+ "4dd5684836": "revisar",
+ "d05f629d2c": "reducción",
+ "694613d47f": "Muestre los controles de notas de revisión de rebajas locales en el modo de editor enriquecido.",
+ "128bc09325": "Notas de revisión de rebajas",
+ "a0014961ae": "voluta",
+ "3ca5ab78a5": "código",
+ "e3919429c0": "descripción general",
+ "9c72990db8": "minimapa",
+ "716a4dfb1f": "Muestra la descripción general del minimapa al editar un archivo.",
+ "6f584fcb48": "Minimapa",
+ "19baae651b": "barra lateral",
+ "973ed6bfbf": "diferencia combinada",
+ "0a02059549": "árbol de archivos",
+ "2f42852568": "árbol",
+ "3b5733573e": "diferencia",
+ "dec71988f0": "Muestre u oculte el árbol de archivos al abrir vistas de diferencias combinadas.",
+ "adec13f2ef": "Árbol de archivos de diferencias predeterminado",
+ "be24c7cd67": "dividir",
+ "233f7e2f37": "lado a lado",
+ "0a5fa65926": "en línea",
+ "2b463f0bf9": "vista",
+ "ecb9415c80": "Formato de presentación preferido para mostrar diferencias de git de forma predeterminada.",
+ "2760c9933f": "Vista de diferencias predeterminada",
+ "b2799ba622": "milisegundos",
+ "146728ac2c": "demora",
+ "86f54575c7": "guardado automático",
+ "8ea61ad55c": "Cuánto tiempo espera Orca después de su última edición antes de guardar automáticamente.",
+ "14e46c745b": "Retraso de guardado automático",
+ "4469b6fa4e": "ahorrar",
+ "e9d948d3c3": "Guarde el editor y los cambios de diferencias editables automáticamente después de una breve pausa.",
+ "ae21e806ce": "Guardar archivos automáticamente",
+ "c56cb6f1c2": "red",
+ "3566fce83f": "servidor local",
+ "91a46caafc": "no_proxy",
+ "3a73054565": "derivación",
+ "20b711ac9e": "apoderado",
+ "eb8946b2c9": "Hosts que deberían omitir el proxy HTTP configurado.",
+ "8436ff6f8e": "Reglas de omisión de proxy",
+ "e55d62dfa4": "plataforma de lanzamiento",
+ "9da6c875e5": "muelle",
+ "b9096a44cf": "https_proxy",
+ "8f03d44672": "http_proxy",
+ "e3b1d42f95": "URL proxy para solicitudes de red Orca y terminales secundarios locales.",
+ "c29f23ab57": "Proxy HTTP",
+ "6c2ce8457c": "explorador de archivos",
+ "c9d9636f24": "descubridor",
+ "68d03d9980": "código vs",
+ "ebf8f056b5": "zed",
+ "0cb3d94f00": "cursor",
+ "8fb00fcd05": "lanzacohetes",
+ "e1ee631696": "editor",
+ "5a9df5566f": "abrir menú",
+ "b8093e9a93": "abrir en",
+ "a916662068": "Elija las aplicaciones disponibles en el menú Abrir en de un espacio de trabajo.",
+ "451d4af994": "Abrir en aplicaciones",
+ "7e9b556873": "saltar",
+ "ca86dd6e27": "diálogo",
+ "9f8558233a": "confirmar",
+ "7edf4f69e2": "automatización",
+ "84c67d0108": "borrar",
+ "a0c44061ee": "Muestra un cuadro de diálogo de confirmación antes de eliminar una automatización y su historial de ejecución.",
+ "d0a65b27fd": "Pregunte antes de eliminar automatizaciones",
+ "df10666259": "árbol de trabajo",
+ "ae98c9cf36": "Muestra un cuadro de diálogo de confirmación antes de eliminar un espacio de trabajo.",
+ "913242091d": "Preguntar antes de eliminar espacios de trabajo",
+ "93f6ec5e70": "directorio",
+ "9bde064915": "subcarpeta",
+ "ec5049e510": "anidado",
+ "b9cffd374d": "Cree espacios de trabajo dentro de una subcarpeta con nombre de repositorio.",
+ "141f71c69f": "Espacios de trabajo anidados",
+ "7887a2c262": "carpeta",
+ "7baf524b04": "espacio de trabajo",
+ "d0bc793689": "Directorio raíz donde se crean las carpetas del espacio de trabajo.",
+ "4c95d08fa2": "Directorio de espacio de trabajo"
+ }
+ },
+ "git": {
+ "search": {
+ "61eab13403": "orca",
+ "1b93c1143c": "atribución",
+ "8461c908ae": "coautor",
+ "61f9f5d1fc": "coautor",
+ "af0a144bfb": "asunto",
+ "6bdea421bb": "pr",
+ "16f53f7323": "gh",
+ "d088806071": "github",
+ "118c23484b": "Agregue la atribución de Orca a confirmaciones, relaciones públicas y problemas.",
+ "bc7d9f69ce": "Atribución de Orca",
+ "40f9b815fd": "presupuesto API",
+ "b7e52124c7": "límite de tasa",
+ "ead733645f": "glabro",
+ "4808f065b3": "gitlab",
+ "2b4a72885d": "Encabezados de límite de velocidad REST de GitLab CLI actuales cuando estén disponibles.",
+ "83ecb3f470": "Presupuesto de la API de GitLab",
+ "65b69d9f80": "graficoql",
+ "1139f61512": "Límites de velocidad actuales de GitHub CLI REST, Search y GraphQL.",
+ "ff86e354c4": "Presupuesto de la API de GitHub",
+ "035134fcd9": "árbol de trabajo",
+ "0c75583ca9": "sin peligro",
+ "bae91effdd": "base fresca",
+ "de06e9d105": "referencia base",
+ "ab0e22c9f6": "actualizar local principal",
+ "d9f70d51a0": "principal obsoleto",
+ "0849b571fe": "A hoy",
+ "c41e345153": "detrás principal",
+ "6ee3cfff02": "diferencia git",
+ "564942ffc5": "origen/principal",
+ "28192e3a63": "maestro",
+ "e3e9adde59": "principal",
+ "0e993bf00f": "Cuando crea un espacio de trabajo, Orca actualiza la base remota y adelanta de forma segura su rama local coincidente, como principal o maestra. Esto evita que comandos como git diff main...HEAD se comparen con el historial obsoleto. Orca omite la actualización si esa rama tiene cambios no confirmados o confirmaciones solo locales.",
+ "f8bda25f29": "Mantenga actualizado el principal local",
+ "769ddd7f81": "costumbre",
+ "1d2fae1fa2": "nombre de usuario git",
+ "f83c8937c4": "denominación de sucursales",
+ "5ecd91c5ef": "Prefijo agregado a los nombres de las ramas al crear árboles de trabajo.",
+ "68bd65fdb8": "Prefijo de rama"
+ }
+ },
+ "input": {
+ "search": {
+ "886597d6b3": "macos",
+ "26c83b06c5": "Linux",
+ "71905435dd": "x11",
+ "7059cfb00a": "portapapeles",
+ "c4440c3986": "pasta",
+ "5fb84ba77f": "ratón del medio",
+ "31ba58c8ae": "clic central",
+ "de51e18ee9": "selección primaria",
+ "e5cd0e7a46": "selección",
+ "e25165320e": "edición",
+ "b51d47ceb7": "aporte",
+ "874d88f4a6": "Habilitado de forma predeterminada en Linux y macOS. Linux usa el portapapeles de selección del sistema; otras plataformas utilizan un búfer privado.",
+ "d952ce9b46": "Haga clic con el botón central en Pegar desde la selección"
+ }
+ },
+ "integrations": {
+ "search": {
+ "a626990bd2": "desconectar",
+ "3c3d3d8ffa": "conectar",
+ "faa0b5a0d9": "clave API",
+ "c450244ad7": "integración",
+ "7319e3015b": "lineal",
+ "16a486a49d": "Conecte Linear para explorar y vincular problemas.",
+ "b027b4b318": "Integración Linear",
+ "20540996ef": "cartas credenciales",
+ "2ec2bd328c": "token de API",
+ "7345b7c3e6": "atlasiano",
+ "e1263dd748": "jira",
+ "76f6af7c57": "Conecte Jira Cloud o actualice las credenciales del token API de Jira.",
+ "617603509b": "Integración de Jira",
+ "8c568d761c": "solicitud de extracción",
+ "33180e8c10": "autohospedado",
+ "129fc59aa8": "gitea",
+ "d0d019dc29": "Autenticación de Gitea a través de variables de entorno de token API.",
+ "aab86d64e5": "Integración de Gitea",
+ "03a7b275be": "alharaca",
+ "ed63380247": "repositorios azules",
+ "b38b5d27f1": "devops azules",
+ "7b1f3984bb": "Autenticación de Azure DevOps Repos mediante variables de entorno de token.",
+ "af6611fa6e": "Integración de Azure DevOps",
+ "50d20817f7": "bitbucket",
+ "c97d58a0f3": "Autenticación de Bitbucket Cloud a través de variables de entorno de token API.",
+ "67a2a0e868": "Integración de Bitbucket",
+ "371ee914d2": "solicitud de fusión",
+ "581844769a": "señor",
+ "b40cbe5de4": "glabro",
+ "b939695c69": "gitlab",
+ "6e2ab619c6": "Autenticación de GitLab a través de la CLI glab.",
+ "b50b71ef9d": "Integración de GitLab",
+ "41ccade05c": "gh",
+ "b79c21bd42": "github",
+ "7166b9090c": "Autenticación de GitHub a través de la CLI de gh.",
+ "f16e41cc72": "Integración de GitHub"
+ }
+ },
+ "jira": {
+ "integration": {
+ "card": {
+ "8ff73fef62": "Los tokens de Jira están cifrados por el tiempo de ejecución activo y almacenados localmente. Volver a ingresar la misma URL del sitio y el mismo correo electrónico reemplaza el token API de ese sitio.",
+ "9046a20d4c": "Desconectar {{value0}}",
+ "eaffa454e9": "Actualizar",
+ "cec06a0f79": "Pruebas…",
+ "ab350991b8": "Verificado",
+ "d914d7ab70": "Verificando…",
+ "5936977fcd": "Cancelar",
+ "1666f8d562": "Crear un token API de Atlassian",
+ "1ab7f551f3": "Token API de Atlassian",
+ "09d310e42d": "tu@ejemplo.com",
+ "27dae4ab60": "https://example.atlassian.net",
+ "a28f417220": "Conecta Jira",
+ "9bb34706ca": "Conectado",
+ "efaab83c5d": "Agregar sitio",
+ "09742875cd": "Jira",
+ "255bfe98ec": "Prueba",
+ "5fb1562315": "error",
+ "3df81cb0ac": "OK",
+ "2e8bb790fd": "Conectar",
+ "33a8b261ee": "Actualizar credenciales",
+ "d5c5b47bb9": "actualizar",
+ "fb854902d9": "conectando",
+ "9a9f8d4910": "Conecte Jira Cloud para explorar, crear y vincular incidencias.",
+ "74f3063026": "{{value0}} sitio{{value1}} conectado"
+ }
+ }
+ },
+ "mobile": {
+ "emulator": {
+ "search": {
+ "2348045036": "Elija qué dispositivo emulador abre Orca de forma predeterminada.",
+ "2bb2e09225": "habilidad móvil",
+ "bbe4267416": "tipo de emulador",
+ "64494f03c3": "adjuntar emulador",
+ "6f728f1456": "grifo del emulador",
+ "f8b871d655": "agente cli",
+ "2e0b45b2ba": "Utilice los comandos de Orca CLI para enumerar, adjuntar, tocar y escribir en un emulador móvil.",
+ "ea3eac39bb": "Control CLI del agente",
+ "8ef0f08d36": "tiempo de ejecución",
+ "27397fe8e9": "herramientas de línea de comando xcode",
+ "7650063d17": "simctl",
+ "3211e7acf9": "xcrun",
+ "42bfab45d8": "disponibilidad",
+ "ea1f51b980": "Compruebe si los dispositivos Xcode, simctl, server-sim y emulador están listos.",
+ "0b95dfd5b3": "Disponibilidad del emulador",
+ "04c5f5d901": "dispositivo",
+ "25d7bfbcd4": "udid",
+ "ec3c4043fd": "ipad predeterminado",
+ "1dc8c52ffa": "iPhone predeterminado",
+ "ab4814f3c5": "simulador predeterminado",
+ "54184cb9c5": "Dispositivo emulador predeterminado",
+ "b8ddd13195": "emulador de agente",
+ "1ad6fb6230": "dispositivo predeterminado",
+ "ac0a985873": "habilidad del emulador",
+ "9353854ff3": "emulador de orcas",
+ "d4b7833894": "orca cli",
+ "84e5706975": "Simulación de servicio",
+ "7c5a8a2bee": "código x",
+ "bec7231663": "iPad",
+ "49727355a3": "iPhone",
+ "6b6407dc1f": "emulador",
+ "2d67f708ce": "simulador",
+ "c5eca29310": "simulador de ios",
+ "25159de808": "emulador móvil",
+ "9595354cff": "Configure la compatibilidad con el emulador móvil para Orca y agentes de codificación.",
+ "cdd3c31918": "Emulador móvil"
+ }
+ },
+ "pane": {
+ "search": {
+ "dbccde3a60": "cerca",
+ "9e16be01d6": "fondo",
+ "3a5e31e84b": "dejar",
+ "8015fd9523": "sostener",
+ "aa3f736042": "cambiar el tamaño",
+ "356c31d6dc": "ancho",
+ "fadcbfdd99": "adaptar",
+ "ad08035c5f": "teléfono",
+ "6cd2bfdb0e": "restaurar",
+ "b34ad5b3a7": "Terminal",
+ "6db86f445f": "móvil",
+ "707fc78052": "Elija qué sucede con los terminales que estaba viendo en el móvil después de cerrar la aplicación o salir.",
+ "1e711aca11": "Cuando sales de la aplicación móvil",
+ "126afc5dbd": "remoto",
+ "70f505f3c3": "LAN",
+ "1802188b5d": "wifi",
+ "dd6e671aa9": "DIRECCIÓN",
+ "1f70d63998": "IP",
+ "d0c89bc4a9": "cubrir",
+ "87711f4b8f": "VPN",
+ "16bff559a0": "red de cola",
+ "c690e3ee38": "escala de cola",
+ "a023683767": "interfaz",
+ "7b37c2e557": "red",
+ "3190ef67a4": "Elija qué dirección de red usar para el emparejamiento móvil.",
+ "d96c315227": "Interfaz de red",
+ "7d01f93ec0": "conectado",
+ "5e8fda4d7f": "emparejado",
+ "905c65a308": "revocar",
+ "82783d9b71": "dispositivos",
+ "13419718b3": "Administrar dispositivos móviles emparejados.",
+ "9d3a9397ba": "Dispositivos conectados",
+ "2128a21096": "escanear",
+ "e518cbd61c": "par",
+ "4a0c826f3d": "código",
+ "3c1807a81a": "qr",
+ "7fb728fb2b": "Empareje un dispositivo móvil escaneando un código QR.",
+ "d49925710a": "Emparejamiento móvil"
+ }
+ },
+ "settings": {
+ "search": {
+ "b730ff7049": "experimental",
+ "8d4ba0ef09": "beta",
+ "6bfa001752": "apk",
+ "a7eececc1d": "androide",
+ "7e801801ac": "remoto",
+ "0b7e585cb9": "escanear",
+ "59b1d75fd1": "código",
+ "87816d1c59": "qr",
+ "cf2c93b479": "par",
+ "f4ed142753": "teléfono",
+ "f213400800": "móvil",
+ "671eb4173c": "Controla terminales y agentes desde tu teléfono.",
+ "ffd52a96e4": "Móvil"
+ }
+ }
+ },
+ "notifications": {
+ "search": {
+ "aa288005c3": "prueba",
+ "ca8faa40d7": "notificaciones",
+ "4e30b1925e": "Active una notificación de escritorio de muestra utilizando la ruta de entrega nativa.",
+ "ef9b311346": "Enviar notificación de prueba",
+ "ecdeff4993": "volumen",
+ "d58b64dddf": "volumen",
+ "dc7d7c07cd": "sonido",
+ "eeb6f77322": "Volumen de reproducción para sonidos de notificación que no pertenecen al sistema.",
+ "aace1a62c6": "Volumen de notificaciones",
+ "ef86a782cc": "bong",
+ "3014ad1b8f": "timbre",
+ "079c29aeb5": "flaco",
+ "722face52f": "acac",
+ "6ecb8418cb": "m4a",
+ "d16ae23645": "ogg",
+ "57e34a31cd": "wav",
+ "5362074f19": "mp3",
+ "6e08f78315": "audio",
+ "c718793e95": "Elija el archivo de audio integrado, del sistema o local que Orca reproduce para las notificaciones de escritorio.",
+ "ea8cb8d9ce": "Sonido de notificación",
+ "4ada6bfde9": "filtración",
+ "fa60d8e4ab": "reprimir",
+ "a4c3b29a3c": "enfocado",
+ "7247b97a31": "Evite notificar cuando Orca esté enfocado en el árbol de trabajo activo.",
+ "96562a72c6": "Suprimir mientras estás concentrado",
+ "a2ab73b325": "atención",
+ "ae0487f8fd": "campana",
+ "c638ae989d": "Terminal",
+ "d3f1c48677": "Notificar cuando un terminal en segundo plano emite un carácter de campana.",
+ "a5edee1d99": "Campana terminal",
+ "193e1f107c": "tarea",
+ "dd9d3e5f0f": "idle",
+ "5f7472d3fb": "completo",
+ "7fa07e9600": "agente",
+ "10d83ef8dc": "Notificar cuando un agente de codificación pasa de estar en funcionamiento a estar inactivo.",
+ "bdc1edaeb4": "Tarea del agente completada",
+ "adbc3a0fcf": "nativo",
+ "72539aede4": "sistema",
+ "51ae2183e1": "de oficina",
+ "0534c76311": "Interruptor maestro para notificaciones de escritorio de Orca.",
+ "4a210b2f72": "Habilitar notificaciones"
+ }
+ },
+ "orchestration": {
+ "search": {
+ "f5d39af41e": "agentes infantiles",
+ "c766a01978": "manos libres",
+ "08c65b12a2": "ejemplos",
+ "f278fd04db": "codex",
+ "32c5098e7b": "claude",
+ "21c28ccdf7": "coordinador",
+ "741dfc03fa": "obrero",
+ "ca54c69806": "TROZO DE CUERO",
+ "7ad948b714": "tarea",
+ "eee028ae14": "despacho",
+ "9a5ebdca31": "mensajería",
+ "91fc8ab7e5": "coordinación",
+ "13ba5c6cbd": "agentes",
+ "d86705ba77": "multiagente",
+ "a7f76b4ca7": "orquestación",
+ "e05ff36753": "Coordine múltiples agentes de codificación a través de mensajes, DAG de tareas, despacho y puertas de decisión.",
+ "c34045764e": "Orquestación de agentes"
+ }
+ },
+ "privacy": {
+ "search": {
+ "3922051573": "datos",
+ "e8bc614a18": "desactivar",
+ "d8191ae5ca": "variable de entorno",
+ "94e04427f6": "ambiente",
+ "664f1a8984": "integración continua",
+ "5854a5c752": "ci",
+ "69637f4dc4": "orca_telemetría_disabled",
+ "058550f6bc": "no_seguimiento",
+ "83a6cd79b3": "no rastrear",
+ "f7a2d9f137": "Variables de entorno que deshabilitan la transmisión de telemetría.",
+ "e058a3c98d": "Variables de entorno de telemetría",
+ "1686c07fee": "apoyo",
+ "4a583f3a2f": "telemetría abierta",
+ "9ea93ce3d6": "otlp",
+ "685c68a81f": "registros",
+ "40de3c2f19": "rastro",
+ "c0494ff48a": "diagnóstico",
+ "8b08f32366": "Archivos de seguimiento y controles de exportación OTLP.",
+ "6d258d2ed6": "Diagnóstico",
+ "ead1deded2": "compartir",
+ "27a27b2f63": "optar por no participar",
+ "4d4bb76bf4": "optar por",
+ "b021b9cb81": "anónimo",
+ "79c319948b": "uso",
+ "77d3180def": "telemetria",
+ "b707cc3981": "Ayude a mejorar Orca enviando eventos anónimos de uso de funciones.",
+ "57b283461a": "Compartir datos de uso anónimos",
+ "2b5a5c312f": "posthog",
+ "4104f6f0f3": "analítica",
+ "10124159f1": "privacidad",
+ "aa3b794c17": "Datos anónimos de uso del producto, diagnósticos y controles de telemetría.",
+ "5c508bad41": "Privacidad y telemetría"
+ }
+ },
+ "quick": {
+ "commands": {
+ "search": {
+ "3c316e6ef8": "hilo",
+ "b86c727100": "mpn",
+ "b949a7c0a0": "pnpm",
+ "0b78c4a165": "lanzamiento",
+ "2d8aff42be": "correr",
+ "1c5bdcd0f2": "repositorio",
+ "89d2a9ad9f": "repositorio",
+ "f58b92a48f": "proyecto",
+ "8bf43c2dad": "global",
+ "a26ecdb77b": "retazo",
+ "d07d130849": "atajo",
+ "0073cf8ce9": "Terminal",
+ "cfffa6cdb6": "comandos",
+ "fecb031823": "dominio",
+ "236d4cfac8": "rápido",
+ "d691c4e8d8": "Comandos de terminal guardados que se pueden ejecutar desde cualquier terminal, con alcance global o para un proyecto específico.",
+ "4c8945952b": "Comandos rápidos"
+ }
+ }
+ },
+ "repository": {
+ "search": {
+ "bc7e504b8e": ".orca/comando-edición",
+ "603c68b68c": "orca.yaml",
+ "9dc60d7f6d": "github",
+ "ec70364df2": "flujo de trabajo",
+ "66b584bd6c": "emitir comando",
+ "2011a6a4f2": "comando de problema de github",
+ "d42d1e49c0": "Comando de problema vinculado basado en archivos configurado a través de orca.yaml y anulación local opcional.",
+ "d86ea12d16": "Comando de problema personalizado de GitHub",
+ "c5e8bdbcbb": "omitir por defecto",
+ "a69c5cbe90": "ejecutar por defecto",
+ "80c490b012": "preguntar",
+ "f9d84b7971": "política de ejecución de configuración",
+ "c00a549e03": "Elija el comportamiento predeterminado cuando haya un script de configuración disponible.",
+ "cdfe398068": "Cuándo ejecutar la configuración",
+ "5e9445bbfd": "autorizado",
+ "f1e1bfa89f": "fuente",
+ "1d90a6cfbb": "ambos",
+ "fcb8fa8144": "compartido",
+ "0432d2fb7c": "local",
+ "ed269fad69": "fuente de comando",
+ "19f58d6d89": "avanzado",
+ "d141897c90": "Fuente del comando y detalles de orca.yaml.",
+ "cc11699c3d": "Avanzado",
+ "bf460fded8": "yaml",
+ "9cad92fe77": "ganchos orca.yaml",
+ "6b80f7d3c8": "scripts de configuración local",
+ "a1a4c51d58": "comando de archivo",
+ "fbfd2386e8": "script de archivo",
+ "4c17787d7b": "archivo",
+ "8655e3387b": "manos",
+ "acd1157f0c": "Scripts locales y compartidos que se ejecutan antes de archivar un árbol de trabajo.",
+ "bce0ca23c6": "Guión de archivo",
+ "491b05d6e6": "comando de configuración",
+ "a31b43a7f8": "guión de configuración",
+ "5590388dfa": "configuración",
+ "baaf70bb37": "Scripts locales y compartidos que se ejecutan después de crear un nuevo árbol de trabajo.",
+ "b79df26937": "Guión de configuración",
+ "d73fb47b45": ".claude/mcp.json",
+ "db11b337c4": ".claude.json",
+ "26f42fe773": ".cursor/mcp.json",
+ "e760e3fae7": ".mcp.json",
+ "16dc7a4637": "protocolo de contexto modelo",
+ "343f0a508c": "mcp",
+ "3c31801626": "Inspeccione los archivos de configuración del servidor MCP a nivel de proyecto.",
+ "31bd0a2420": "Configuraciones de MCP",
+ "84da7fa2d7": "módulos_nodo",
+ "0a3a582794": "ambiente",
+ "3c180a251c": "enlace",
+ "f1c53f2820": "árbol de trabajo",
+ "7e228fc439": "enlaces simbólicos",
+ "c06adcf136": "enlace simbólico",
+ "ed885e589f": "Rutas para vincular simbólicamente desde el pago principal a árboles de trabajo recién creados.",
+ "01b3377ebc": "Enlaces simbólicos del árbol de trabajo",
+ "fff8834983": "inmediato",
+ "fa3131f223": "modelo",
+ "130d76dc16": "rebautizar",
+ "917dce844a": "nombre de la sucursal",
+ "8068d8d0f1": "pr",
+ "5ff7fe1ade": "solicitud de extracción",
+ "eec39b3de6": "mensaje de confirmación",
+ "cfad7ce5f3": "ai",
+ "a47f51127e": "control de fuente",
+ "6cc5c65e64": "Anulaciones de generación de git específicas del proyecto.",
+ "eec3995dc6": "Autor de Git AI",
+ "cc876ca5f2": "repositorio",
+ "6469de5368": "proyecto",
+ "3067595d82": "borrar",
+ "c86478c3d8": "Eliminar este proyecto de Orca.",
+ "c5266c2c9d": "Eliminar proyecto",
+ "4b9a18a56d": "monorepo",
+ "4e2529722c": "directorios",
+ "1ff4f12c0c": "directorio",
+ "9f5ae26ccd": "preajustes",
+ "095fca94fe": "programar",
+ "aa42616e3d": "verificar",
+ "4f3c0230c2": "escaso",
+ "90a331fd68": "Conjuntos de directorios guardados para la creación de árboles de trabajo dispersos.",
+ "1f0f20bbb6": "Ajustes preestablecidos de pago dispersos",
+ "4733ec2395": "../árboles de trabajo",
+ "58d8bca414": "relativo",
+ "a325a89dff": "ruta del espacio de trabajo",
+ "f3e6dee5fe": "ruta del árbol de trabajo",
+ "cd33a5525e": "Directorio específico del proyecto para nuevos árboles de trabajo.",
+ "443d127b5a": "Ubicación del árbol de trabajo",
+ "9811f3d152": "rama",
+ "f41cef5083": "referencia base",
+ "f571081ec4": "Rama base o referencia predeterminada al crear árboles de trabajo.",
+ "094adbe930": "Base de árbol de trabajo predeterminada",
+ "27733eb6c1": "favicon",
+ "1e73e840ff": "emojis",
+ "cb4b4de666": "avatar",
+ "c1075178cf": "insignia",
+ "6d8de2f090": "maleficio",
+ "8d045419b1": "color",
+ "b2546efab5": "icono del repositorio",
+ "6438a94c63": "icono de proyecto",
+ "a1f3a2bd47": "Ícono y color del proyecto utilizados en la barra lateral y las pestañas.",
+ "b24f00294a": "Icono de proyecto",
+ "cd73b976d7": "nombre del repositorio",
+ "92af66c7ce": "nombre del proyecto",
+ "883aad2801": "Detalles de visualización específicos del proyecto para la barra lateral y las pestañas.",
+ "7e1e456a95": "Nombre para mostrar"
+ }
+ },
+ "runtime": {
+ "environments": {
+ "search": {
+ "772e3b4753": "vm",
+ "45501ff2c3": "nube",
+ "2bd988d041": "código de emparejamiento",
+ "5cd7dca3b8": "remoto",
+ "d760866285": "cliente",
+ "09568ccc65": "servidor",
+ "ebd5369acf": "ambiente",
+ "d198440ce3": "tiempo de ejecución",
+ "baec27aa8f": "Conecte este navegador a un servidor Orca guardado.",
+ "3517fb2ec0": "Servidor activo",
+ "c6e5a03aa0": "caja de desarrollo",
+ "f1575f1e09": "cliente web",
+ "81444c4102": "URL de emparejamiento",
+ "104f4d7dbd": "emparejamiento",
+ "4575341c77": "Elija el escritorio local, agregue un servidor Orca remoto guardado o genere una URL de emparejamiento."
+ }
+ }
+ },
+ "shortcuts": {
+ "search": {
+ "ca6a0c2df7": "atajo",
+ "4811a8264a": "terminal primero",
+ "afda131738": "orca primero",
+ "0ecfc47434": "conflicto",
+ "0f8cb15582": "agente",
+ "f1adebbe8c": "caparazón",
+ "7f1b38f59a": "tui",
+ "7e3fc707aa": "Terminal",
+ "0ecba9aa5f": "teclado",
+ "ebd7d81e1d": "Elija si Orca o el terminal enfocado gana cuando los atajos se superponen.",
+ "f052906167": "Atajos en la Terminal"
+ }
+ },
+ "ssh": {
+ "search": {
+ "d41f296f64": "silbido",
+ "237b391f7c": "conexión",
+ "8cb870b109": "prueba",
+ "7efd17e816": "ssh",
+ "96ca5d9a0b": "Pruebe la conectividad con un destino SSH.",
+ "a3058f3605": "Conexión de prueba",
+ "2cd40ba0d0": "anfitriones",
+ "5220501141": "configuración",
+ "3b12e064a4": "importar",
+ "7f251a45a8": "Importe hosts desde ~/.ssh/config.",
+ "41a3127094": "Importar desde configuración SSH",
+ "f9493b80c0": "servidor",
+ "8fb1cc87cc": "anfitrión",
+ "09395490af": "objetivo",
+ "00d1fda01a": "nuevo",
+ "f7b6383aec": "agregar",
+ "62826efbe9": "Agregue un nuevo destino SSH remoto.",
+ "f5a691bb6c": "Agregar destino SSH",
+ "d4bcd497c7": "remoto",
+ "74c6d90d78": "Administre objetivos SSH remotos.",
+ "380a788da7": "Conexiones SSH"
+ }
+ },
+ "tasks": {
+ "search": {
+ "58cda6f9c0": "esconder",
+ "44083ae418": "mostrar",
+ "604d8e4089": "atlasiano",
+ "5430396e11": "jira",
+ "412ec3c702": "lineal",
+ "11f001cdd4": "gitlab",
+ "c10ac2125e": "github",
+ "3d81c26d78": "fuente",
+ "cf0e3e0c2f": "proveedor",
+ "2ec54bee51": "tareas",
+ "765f0c544d": "Elija qué proveedores de tareas aparecen en la página Tareas y en los accesos directos de la barra lateral.",
+ "5b8e4aace5": "Proveedores de tareas"
+ }
+ },
+ "terminal": {
+ "clipboard": {
+ "search": {
+ "5fb3512e8c": "pasta",
+ "a38508c419": "Copiar",
+ "d106f44fb4": "remoto",
+ "043b32faa1": "ssh",
+ "9fda309db9": "fzf",
+ "64533e30cc": "nvim",
+ "2061d8db1a": "neovim",
+ "5ffcd13c90": "tmux",
+ "10d73e22d3": "portapapeles",
+ "9dfc125cd3": "osc52",
+ "62d1208b90": "osc 52",
+ "459fea094a": "Permita que los programas en la terminal se copie al portapapeles del sistema a través de OSC 52, incluso a través de SSH.",
+ "74db8721e4": "Permitir escrituras en el portapapeles TUI (OSC 52)",
+ "4043e294d2": "gnomo",
+ "cf83ac3dbd": "Linux",
+ "737cef6de1": "x11",
+ "e87c6d776d": "automático",
+ "664789b73a": "auto",
+ "c38c18be15": "selección",
+ "797fdfe4ca": "seleccionar",
+ "603818e8d8": "Copie automáticamente las selecciones de terminal al portapapeles tan pronto como se realice una selección.",
+ "3bdc84f059": "Copiar al seleccionar"
+ }
+ },
+ "search": {
+ "c047f398cc": "lanzamiento",
+ "b872de3926": "ubicación",
+ "fd6c24313d": "nuevo",
+ "f44643328e": "pestaña",
+ "18ce996647": "vertical",
+ "54a9b3725b": "horizontal",
+ "de7bc1d5f5": "dividir",
+ "7a48c7715b": "espacio de trabajo",
+ "6b659fff2a": "guion",
+ "4529806908": "configuración",
+ "2610ee3b56": "Dónde se ejecuta el script de configuración del repositorio cuando se crea un nuevo espacio de trabajo: una división vertical (predeterminada), una división horizontal o una pestaña de fondo titulada 'Configuración'.",
+ "5be2d67678": "Ubicación del script de configuración",
+ "0ce176909a": "tema",
+ "4ba8623632": "paleta",
+ "11fd3fbcf2": "ansi",
+ "d8bd6182b8": "anular",
+ "674b7c8436": "color",
+ "3023e01415": "Anula los colores de terminales individuales.",
+ "aed2a4b4eb": "Anulaciones de color",
+ "6eaf7ee0e4": "cursor",
+ "34fe1af39d": "mecanografía",
+ "ee611ae238": "esconder",
+ "ea364ce6e4": "ratón",
+ "77201c0bb2": "Oculte el cursor del mouse al escribir en la terminal.",
+ "d1fe5f99ff": "Ocultar el mouse mientras escribe",
+ "f25d948664": "margen",
+ "b2f52cb96c": "espaciado",
+ "e8baf0d12c": "relleno",
+ "4655567c37": "Relleno vertical alrededor de la cuadrícula del terminal en píxeles.",
+ "692c4ad032": "Acolchado vertical",
+ "75691e4911": "Relleno horizontal alrededor de la cuadrícula del terminal en píxeles.",
+ "b4f182f24d": "Acolchado horizontal",
+ "6c2f9f05c8": "vitalidad",
+ "4f7f8f28ca": "transparencia",
+ "f6dd9ff606": "fondo",
+ "71eb45e293": "difuminar",
+ "0838b3717b": "ventana",
+ "bc2054657a": "Aplique desenfoque de fondo a la ventana del terminal. Requiere reinicio.",
+ "72d0482137": "Desenfoque de ventana",
+ "7db59c4738": "alfa",
+ "46d99ef4bb": "opacidad",
+ "4c643695aa": "Controla la transparencia del fondo del terminal.",
+ "b36fd2416d": "Opacidad del fondo",
+ "d4daf4f612": "descongelar",
+ "88561b3499": "congelado",
+ "0a05629060": "recuperar",
+ "f66a7cf715": "Terminal",
+ "6892fb1019": "Reanudar",
+ "cde233f5da": "desplazarse hacia atrás",
+ "3982d88725": "historia",
+ "456da64d4d": "claro",
+ "920573d65b": "matar a todos",
+ "a3e5297c10": "matar",
+ "a8d2784214": "administrar",
+ "d802a578bf": "sesiones",
+ "9f2dda133c": "pty",
+ "f35400f7e8": "demonio",
+ "f72abc493c": "Recupérese de terminales congeladas finalizando sesiones, borrando el desplazamiento hacia atrás guardado o reiniciando el demonio.",
+ "6f5d486a68": "Administrar sesiones",
+ "10f9fb6fea": "ajustes",
+ "2ade3ea490": "configuración",
+ "fd752b3cac": "importar",
+ "82b63d07fe": "fantasmal",
+ "73e9422f19": "Importación única de configuraciones de terminal Ghostty compatibles.",
+ "a979df0083": "Importar desde Ghostty",
+ "4cec42dbf7": "internacional",
+ "b495dc6a9f": "jis",
+ "d8d6f7a3c5": "macos",
+ "1ab57a0fbd": "impermeable",
+ "abaa24752d": "teclado",
+ "24f7977756": "japonés",
+ "98059d0944": "barra invertida",
+ "9c35f56625": "yen",
+ "063914c486": "Controla si al presionar la tecla JIS Yen (¥) se envía una barra invertida (\\).",
+ "694b8764ac": "Yen JIS (¥) a Barra invertida (\\)",
+ "fae142a354": "línea de lectura",
+ "b3b94cfcb5": "internacional",
+ "dd4f6cb541": "alemán",
+ "983d45cf4c": "componer",
+ "7ace5beec9": "meta",
+ "38f1b4f4cb": "llave",
+ "c4427dc5ff": "alternativo",
+ "b37edfc65a": "opción",
+ "1f8b00f5ce": "Controla si la tecla Opción de macOS envía secuencias Alt/Esc o compone caracteres. Refleja la opción-macos-como-alt de Ghostty.",
+ "9bd7229927": "Opción como Alt",
+ "affb14efd4": "selección",
+ "d2a366c7f9": "haga doble clic",
+ "4ed3e239a8": "límite",
+ "d4aeafac10": "separador",
+ "7286cd2566": "palabra",
+ "3ab64c47d8": "Caracteres tratados como límites de palabras para la selección con doble clic.",
+ "957a0203fc": "Separadores de palabras",
+ "56fff3d113": "memoria",
+ "fffdff40a7": "buffer",
+ "f7d56b6281": "Tamaño máximo del búfer de desplazamiento hacia atrás del terminal.",
+ "7674e758e1": "Tamaño de desplazamiento hacia atrás",
+ "411229c636": "luz",
+ "781f49d942": "divisor",
+ "77d9f9cd55": "Controla la línea divisoria dividida entre paneles en modo claro.",
+ "595b97b446": "Color del divisor de luz",
+ "7718d70356": "avance",
+ "1dee533bd9": "Elige el tema utilizado cuando Orca está en modo claro.",
+ "1d89457764": "Tema ligero",
+ "da864e6cec": "modo de luz",
+ "f268092ee3": "Cuando está deshabilitado, el modo claro reutiliza el tema oscuro del terminal.",
+ "232e532169": "Utilice un tema independiente en el modo claro",
+ "f785374072": "oscuro",
+ "9c32726f47": "Controla la línea divisoria entre paneles en modo oscuro.",
+ "8987db7ff2": "Color divisor oscuro",
+ "13f6310dd3": "Elija el tema del terminal utilizado en modo oscuro.",
+ "ec07ce9b02": "Tema oscuro",
+ "f036794286": "activo",
+ "846a7a1204": "cristal",
+ "d1fa00a9cb": "flotar",
+ "b5116e7b12": "sigue",
+ "f5d1e3d472": "enfocar",
+ "17cc3ea102": "Al pasar el cursor sobre un panel de terminal, se activa sin necesidad de hacer clic. Refleja la configuración de enfoque que sigue al mouse de Ghostty. Las selecciones y el cambio de ventana se mantienen seguros.",
+ "c6178a2b4d": "El foco sigue al ratón",
+ "f637a7dee9": "espesor",
+ "e58d4040d0": "Grosor de la línea divisoria del panel.",
+ "2d5ab88b7c": "Grosor del divisor",
+ "6c4c85ba43": "oscurecimiento",
+ "18dd5026c6": "Opacidad aplicada a paneles que no están actualmente activos.",
+ "72bbcbd1dd": "Opacidad del panel inactivo",
+ "d4f7d1ce5c": "Opacidad del cursor terminal.",
+ "7f1e356a54": "Opacidad del cursor",
+ "25f606d9e5": "parpadear",
+ "a27f6edf52": "Utiliza la variante parpadeante de la forma del cursor seleccionada.",
+ "b03d01fd49": "Cursor parpadeante",
+ "eefd1d8332": "subrayar",
+ "015c82349f": "bloquear",
+ "a6e9dcc829": "bar",
+ "275a9d6395": "Apariencia predeterminada del cursor para los paneles del terminal Orca.",
+ "97bcfff662": "Forma del cursor",
+ "1abcf4d7de": "Linux",
+ "7d924d870d": "gráficos",
+ "bc7ae1f7c0": "representación",
+ "fffa9ab980": "renderizador",
+ "6cddc858ba": "webgl",
+ "4b4e80d850": "aceleración",
+ "db82cb13b0": "GPU",
+ "8f9f953de7": "Controla si el terminal utiliza la representación WebGL de xterm.js. Auto prueba WebGL cuando el renderizador es compatible, con respaldo conservador para software o renderizadores de GPU desconocidos.",
+ "13a2502dfc": "Aceleración de GPU",
+ "d5e6c7fab1": "características de la fuente",
+ "a16224d16a": "calto",
+ "6ded6297fe": "iosevka",
+ "e3aeea308e": "código cascada",
+ "35c2311a33": "cerebros jet mono",
+ "7f7640c29e": "codigo fira",
+ "7ab424c4d3": "ligadura",
+ "afc8d5f790": "ligaduras",
+ "103cdb862f": "tipografía",
+ "893aa92997": "Renderice ligaduras de programación (por ejemplo, => → ≠ ≥) para las fuentes que las incluyen. \"Auto\" habilita ligaduras solo para fuentes de ligadura conocidas (Fira Code, JetBrains Mono, Cascadia Code, Iosevka, etc.).",
+ "58da1ae45d": "Ligaduras de fuentes",
+ "7341e3d00e": "altura de la línea",
+ "36a1b38bc8": "Controla el multiplicador de altura de la línea terminal.",
+ "0f2fb0cb74": "Altura de línea",
+ "20ce287cc6": "peso",
+ "98c18f2c77": "Controla el peso de la fuente del texto del terminal.",
+ "28ea41bd2d": "Peso de fuente",
+ "b0bb76ae6b": "fuente",
+ "0acdc17891": "Familia de fuentes de terminal predeterminada para nuevos paneles y actualizaciones en vivo.",
+ "e989914ad6": "Familia de fuentes",
+ "33031c1465": "tamaño del texto",
+ "0fe0073f0c": "Tamaño de fuente de terminal predeterminado para nuevos paneles y actualizaciones en vivo.",
+ "5930244899": "Tamaño de fuente"
+ },
+ "windows": {
+ "search": {
+ "4d09141a42": "menú contextual",
+ "fcfa53920b": "pasta",
+ "e55186fe2b": "clic derecho",
+ "28ff08ed35": "ventanas",
+ "e7d2793b03": "Terminal",
+ "8ba875c132": "En Windows, haga clic derecho y pegue el portapapeles en la terminal. Utilice Ctrl+clic derecho para abrir el menú contextual.",
+ "f0b8448570": "Haga clic derecho para pegar",
+ "04994f6929": "por defecto",
+ "fc564eadaf": "debian",
+ "4ee2579c32": "ubuntu",
+ "5074ad8b5f": "distribución",
+ "2b4a340ce0": "distribución",
+ "02c772582a": "Linux",
+ "6e3adf4cba": "wsl",
+ "978457945b": "Elija qué distribución WSL utilizarán los nuevos terminales WSL y los análisis de agentes locales.",
+ "1f402b3651": "Distribución WSL",
+ "d57f870938": "avanzado",
+ "4af2f7526e": "versión",
+ "d414022016": "pwsh",
+ "768613e483": "powershell 7",
+ "f9162f0b8e": "powershell de windows",
+ "2d99cd91be": "powershell",
+ "41a69bc24d": "Elija si la opción de shell de PowerShell inicia Windows PowerShell o PowerShell 7+ para nuevos paneles de terminal.",
+ "860e0e6402": "Versión de PowerShell",
+ "07ec155fb6": "bash.exe",
+ "5a2db98d23": "intento",
+ "591912177b": "git bash",
+ "12519edb5d": "símbolo del sistema",
+ "6cd20b9e64": "cmd",
+ "7c7056940a": "caparazón",
+ "713c4a2f92": "Elija el shell predeterminado para los nuevos paneles de terminal en Windows.",
+ "13715f9d23": "Shell predeterminado"
+ }
+ }
+ },
+ "voice": {
+ "pane": {
+ "search": {
+ "f6e0dfa61c": "nube",
+ "2d206de105": "clave API",
+ "04c25a6fb0": "abierto",
+ "b9dee49cd7": "descargar",
+ "10d45a9fce": "stt",
+ "3d8b853963": "discurso",
+ "080202facb": "modelo",
+ "7640ed9848": "voz",
+ "56defcd6c3": "Seleccione un modelo de voz a texto local o en la nube para usarlo en el dictado.",
+ "7e62cd7c41": "Modelo de habla",
+ "931b1a9e53": "empujar para hablar",
+ "064a9bd94a": "sostener",
+ "6fa48bcd41": "palanca",
+ "d86f5600da": "modo",
+ "089d31a45b": "dictado",
+ "748b33e531": "Alternar o mantener presionado el comportamiento de dictado.",
+ "6a3abb4338": "Modo de dictado",
+ "e360027a65": "micrófono",
+ "698376a38d": "Alternancia maestra para funciones de dictado de voz.",
+ "20574cbc72": "Habilitar dictado de voz",
+ "322d457a0d": "transcripción",
+ "dcc7846641": "Configure la clave API de OpenAI utilizada para los modelos de voz a texto en la nube.",
+ "ebfd0b32e5": "Transcripción OpenAI"
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "action": {
+ "recipe": {
+ "options": {
+ "commitMessage": "Genere el mensaje de confirmación a partir de cambios preparados.",
+ "pullRequest": "Genere el título y la descripción de la reseña alojada.",
+ "branchName": "Cambie el nombre de las ramas creadas por Orca desde la tarea inicial del agente.",
+ "fixCommitFailure": "Inicie un agente cuando falle un enlace de confirmación o una confirmación de git.",
+ "fixChecks": "Inicie un agente a partir de comprobaciones fallidas de revisión alojada.",
+ "resolveConflicts": "Inicie un agente para conflictos de fusión de revisión local o alojada."
+ }
+ }
+ }
+ }
+ },
+ "agent-awake-copy": {
+ "e5995ce268": "Mantener la computadora activa mientras los agentes están trabajando",
+ "95d3031db2": "Mantiene esta computadora y pantalla activas mientras los agentes están trabajando. El comportamiento de cierre de la tapa sigue la configuración de energía de este dispositivo.",
+ "a42f6fbdd8": "Mantiene esta computadora y pantalla activas mientras los agentes están trabajando. Orca también le pide a este dispositivo que permanezca despierto cuando la tapa está cerrada, sujeto a su política de energía."
+ },
+ "agent-status-hooks-copy": {
+ "7707c15abb": "Ganchos de estado del agente",
+ "a68a642835": "Muestra los estados de trabajo, espera y finalización en Orca. Apague para quitar los ganchos administrados por Orca y deje de reinstalarlos."
+ },
+ "agent-generated-tab-title-copy": {
+ "19ad21615a": "Generar títulos de pestañas automáticamente",
+ "b036c7a409": "Derive nombres breves de pestañas estables a partir del primer mensaje de agente conocido. Los cambios de nombre manuales siempre ganan."
+ }
+ },
+ "right": {
+ "sidebar": {
+ "BulkActionBar": {
+ "79a9f5f712": "fuera del escenario (",
+ "ef5f5bd06e": "Escenario (",
+ "60ed678138": "seleccionado"
+ },
+ "ChecksPanel": {
+ "2ef90c9819": "Inició un agente de inteligencia artificial para los cheques rotos.",
+ "a0181a8d76": "Inició un agente de IA para los conflictos.",
+ "34464d00b9": "actualizado",
+ "058039787c": "Cancelar",
+ "2ab7fd4b6d": "Ahorrar",
+ "dda5924a40": "Las comprobaciones requieren una rama de Git y un contexto de revisión alojado",
+ "976cefd02f": "Cheques no disponibles",
+ "b5dd73a105": "Seleccione un espacio de trabajo para ver cheques",
+ "a4ef4e0832": "Ningún espacio de trabajo seleccionado",
+ "5594400d73": "No hay cheques rotos que arreglar.",
+ "abf59262fb": "Revise el mensaje antes de iniciar un agente.",
+ "4ede779461": "Resolver conflictos de revisión con IA",
+ "3b203c62f8": "Esto eliminará permanentemente el comentario del PR.",
+ "ea9b649ce3": "¿Eliminar comentario?",
+ "5788d1059d": "No se pudo actualizar el hilo de revisión. Consulta el presupuesto de la API de GitHub.",
+ "07871c0589": "Vincular otro PR",
+ "7202f4a40a": "desvincular relaciones públicas",
+ "7f4489f370": "Refrescar",
+ "5c88c6db07": "Abierto el {{value0}}",
+ "7fad8509fe": "Arreglar con IA",
+ "71026ca2cb": "Refrescante…",
+ "889cdfba04": "Crear {{value0}}",
+ "98f4c37b33": "Empujar y crear {{value0}}",
+ "6633c7a1fb": "Rama de publicación",
+ "fdb27637f2": "Publicación…",
+ "e56c42122e": "destructivo",
+ "786e3c143f": "Borrar",
+ "653c105ecc": "Más acciones de relaciones públicas"
+ },
+ "CreatePullRequestDialog": {
+ "2bc1b4345e": "Cancelar",
+ "27ef4b195c": "Elija una rama base diferente antes de crear un {{value0}}.",
+ "7ef56f3efe": "Crear como borrador",
+ "0c9f9a568c": "Admite el formato Markdown. Utilice Generar con IA para completar automáticamente sus cambios.",
+ "02b2ce911f": "Descripción (opcional)",
+ "1cd53359db": "Descripción",
+ "68314b4369": "Título",
+ "694550a610": "principal",
+ "0fad57a14c": "Busque sucursales remotas o ingrese el nombre de una sucursal.",
+ "8584ccb43c": "sucursal base",
+ "6f5f1962b6": "rama principal",
+ "b504b3ceb1": "detalles antes de crear la reseña alojada.",
+ "f658ff2455": "Confirme la sucursal de destino y los detalles de {{value0}} antes de crear la revisión alojada.",
+ "b7f43474d7": "Crear {{value0}}",
+ "7a21f0dae8": "Abierto el {{value0}}",
+ "edc35a7027": "{{value0}} #{{value1}} ya está abierto",
+ "a154fe55e6": "Empujar y crear {{value0}}",
+ "21c7a1daa0": "{{value0}} ya está abierto",
+ "db9cee18f7": "Crear {{value0}}"
+ },
+ "CreatePullRequestGenerateButton": {
+ "4012459f8a": "Generar con IA",
+ "a0501572c1": "Genera detalles {{value0}} con IA",
+ "d47fd63012": "Generando detalles {{value0}}. Haga clic para detener.",
+ "bdf83ccb15": "Generando {{value0}}",
+ "f5513bdeb1": "generando",
+ "a6ea6dc3aa": "Generando…",
+ "e61d7e7ad4": "Dejar de generar detalles {{value0}}",
+ "e041998cad": "dejar de generar"
+ },
+ "FileExplorer": {
+ "79b1537dd3": "Seleccione un espacio de trabajo para buscar archivos"
+ },
+ "FileExplorerBackgroundMenu": {
+ "3b5e2dcb8d": "Nueva carpeta",
+ "21fe46ed36": "Nuevo archivo"
+ },
+ "FileExplorerRow": {
+ "addc01145f": "Borrar",
+ "fc747429bf": "Rebautizar",
+ "0df0e5abac": "Buscar en la carpeta",
+ "d6a25618aa": "Contraer carpeta",
+ "d87a4c42e1": "Abrir vista previa de rebajas",
+ "c2112579f6": "Descargar",
+ "dd112c81d2": "Abrir en el navegador Orca",
+ "1bb9be455c": "Agregar como proyecto...",
+ "0fec99bfd7": "Duplicado",
+ "f61af83316": "Nueva carpeta",
+ "37c875d827": "Nuevo archivo",
+ "b3e288bf41": "No se pudo descargar '{{value0}}'.",
+ "1a3df04ae1": "Abierto",
+ "bce4d4e44f": "Descargado '{{value0}}'",
+ "e26010014a": "Ignorado por .gitignore",
+ "a06551beee": "Ingresar",
+ "128a99ed5e": "No asignado",
+ "2de3b21934": "reducción",
+ "66a29dde82": "Copiar ruta relativa",
+ "42e10cbf57": "Copiar rutas relativas",
+ "b5d436aa30": "Copiar ruta",
+ "f9d7ca753d": "Copiar rutas",
+ "3161c4e425": "carpeta"
+ },
+ "FileExplorerToolbar": {
+ "d238264654": "Mostrar archivos ignorados de Git",
+ "78f133232c": "Mostrar archivos de puntos",
+ "31b4c3195d": "Más acciones del explorador",
+ "d95e30fe28": "Actualizar explorador",
+ "6026b16950": "Contraer todo"
+ },
+ "FileExplorerTreeStatus": {
+ "ce03835e1f": "No hay archivos en este espacio de trabajo",
+ "c76693e456": "No se pudieron cargar archivos para este espacio de trabajo:"
+ },
+ "GitHistoryPanel": {
+ "cf7cad58d2": "Aún no hay compromisos",
+ "781a8bcf7b": "Cargando gráfico...",
+ "d0fb0f4bf2": "Actualizar confirmaciones",
+ "9f7535d22b": "Las referencias son nombres de ramas o etiquetas que apuntan a esa confirmación exacta. Solo aparecen cuando Git tiene una referencia con nombre para la confirmación.",
+ "9289ba0cb9": "¿Qué son los árbitros?",
+ "d836037d02": "Se compromete",
+ "8232c8b2f2": "Confirmación abierta {{value0}}: {{value1}}",
+ "9a8b85882d": "cargando",
+ "62e685d5ec": "idle",
+ "111e1d0db4": "error",
+ "e5e81e59a6": "Cambiar el tamaño de las confirmaciones"
+ },
+ "HostedReviewActions": {
+ "4d5fb5a284": "Cerca",
+ "9845a71e17": "Más acciones",
+ "2bfaf4379c": "Más acciones de {{value0}}",
+ "377269db6f": "{{value0}} reabierto",
+ "fa3ee9a515": "cerrado",
+ "78f5ff294c": "Esto reabrirá el {{value0}}.",
+ "a3d572a4de": "Esto cerrará el {{value0}}.",
+ "e4aca40024": "Eliminar espacio de trabajo",
+ "eefd50457e": "Eliminando...",
+ "3ce211ece6": "Reabrir {{value0}}",
+ "6645ac7dd1": "Reapertura...",
+ "b25f63edd7": "abierto",
+ "d2ca293f3d": "Laboral...",
+ "ef064cb7c3": "por defecto",
+ "59b4dccf70": "destructivo"
+ },
+ "PortsPanel": {
+ "3ea4a02a8f": "Cancelar",
+ "4eb801ce93": "servidor de desarrollo",
+ "8dfed0a15c": "Etiqueta (opcional)",
+ "17bea6e391": "servidor local",
+ "a3721a50b0": "Anfitrión remoto",
+ "d57545ff92": "Igual que remoto",
+ "b950b1948b": "Puerto Local",
+ "9e5a4118b0": "Puerto remoto",
+ "c9d106547a": "Adelante",
+ "c7e920aa7c": "anunciado como {{value0}}",
+ "e740075063": "Eliminar",
+ "b3548e59f4": "Editar",
+ "fe2730d050": "Copiar {{value0}}",
+ "b22b128b2a": "Abrir en el navegador",
+ "75aeea592f": "Abra {{value0}} en el navegador",
+ "de349d4560": "abre {{value0}}",
+ "907eb53ed2": "Reenviar un puerto",
+ "04efd3dad4": "Reenvíe un puerto para acceder a servicios remotos en su máquina local.",
+ "1f0d2a24f9": "Sin puertos reenviados",
+ "36b1b2984a": "Detectado",
+ "ddbe58d74e": "reenviado",
+ "a103dae837": "Agregar",
+ "6bc058dbe1": "Puertos",
+ "d4c3cd679c": "Reconectando...",
+ "a2f1a47f42": "Se perdió la conexión SSH",
+ "409afcc145": "No se ha seleccionado ningún espacio de trabajo para el navegador.",
+ "153145e675": "Evidencia",
+ "c7b4702b7b": "Espacio de trabajo",
+ "57d930fa45": "PID",
+ "5dd86dcf2f": "Proceso",
+ "b1ff94fa27": "Protocolo",
+ "729be0b4e5": "Amable",
+ "0f1d8cd324": "Unir",
+ "1c1c18cefc": "DIRECCIÓN",
+ "f9528da632": "Detener proceso",
+ "a223459512": "Mostrar detalles",
+ "bdac206faf": "Copiar detalles",
+ "792baeb7ed": "Copiar dirección",
+ "d41a8241ec": "Puerto",
+ "a2a9fc6899": "No se detectaron puertos locales",
+ "f59c783b7a": "Escaneo de puertos no disponible en {{value0}}: {{value1}}",
+ "7822e3edc6": "Actualizar puertos",
+ "c1b115c375": "Ningún espacio de trabajo seleccionado",
+ "98e9a414f8": "No se pudo abrir el navegador",
+ "a00f3a2840": "No se pudieron actualizar los puertos",
+ "97b562d21d": "Proceso detenido el :{{value0}}",
+ "9079776663": "Ahorrar",
+ "c57eda6822": "editar",
+ "9f475dc994": "Reenviando...",
+ "d7c83cfd24": "Ahorro...",
+ "31e80cff2d": "Reenvíe un puerto remoto a su máquina local.",
+ "10360598a4": "Actualice la configuración de reenvío de puertos.",
+ "80206251c8": "Editar reenvío de puerto",
+ "4bc9b00912": "espacio de trabajo",
+ "3e13cb63ee": "Desconocido",
+ "472054d94c": "Puerto :{{value0}}",
+ "1119f90ad7": "recipiente",
+ "d32820d3e2": "Externo",
+ "4db4b5e435": "Otros espacios de trabajo",
+ "38b16cfbef": "No se detectaron puertos",
+ "0d63d94db3": "Exploración...",
+ "935dda7718": "Espacio de trabajo activo",
+ "740aca88ab": "Error al escanear el puerto del espacio de trabajo.",
+ "5be4f7f727": "Menú Puerto {{value0}}",
+ "7550998473": "Copiar",
+ "1004af16ab": "Copiar {{value0}}"
+ },
+ "Search": {
+ "1abfb25a66": "Escriba para buscar en archivos",
+ "d56d140747": "Presione Enter para buscar",
+ "0b8104eaf2": "archivo",
+ "4107975b3a": "en",
+ "6aeda362ed": "resultado",
+ "98c8435e36": "Seleccione un espacio de trabajo para buscar",
+ "1ec640c9c7": "fósforo",
+ "dcc294f28d": "(resultados truncados)"
+ },
+ "SearchFilters": {
+ "01e4671ccf": "archivos a excluir (por ejemplo, *.min.js, dist/**)",
+ "0a6412a895": "Archivos para excluir",
+ "8a77efcbd1": "archivos a incluir (por ejemplo, *.ts, src/**)",
+ "a69ee1bd0e": "Archivos para incluir"
+ },
+ "SearchHeader": {
+ "6234a5ef85": "Usar expresión regular",
+ "4567e6e0b6": "Coincidir con toda la palabra",
+ "464ae3974f": "Caso de partido",
+ "693cbeadd0": "Buscar"
+ },
+ "SearchResultItems": {
+ "cc06595a3b": "Copiar ruta de línea",
+ "3596b9668d": "Copiar ruta"
+ },
+ "SourceControl": {
+ "1406954883": "Borrar todas las notas...",
+ "cc05b2d088": "Abrir en el Explorador de archivos",
+ "03194cfff4": "Estado de la sesión local derivado de un conflicto que abrió aquí.",
+ "413a3ba113": "conflicto",
+ "27a50fe970": "Revisar conflictos",
+ "f6cb48b6fe": "Resolver con IA",
+ "3eeccbb221": "Los archivos resueltos vuelven a los cambios normales después de salir del estado de conflicto activo.",
+ "c321542ee2": "Eliminar nota en la línea {{value0}}",
+ "b656381c18": "Eliminar nota",
+ "c085946bda": "Copiar nota en la línea {{value0}}",
+ "1623bf4e19": "Copiar nota",
+ "655633c08a": "Enviado",
+ "3eb9b2805e": "Abrir nota sobre {{value0}}",
+ "0d963bf982": "Abierto {{value0}}",
+ "59654650d3": "Borrar notas para {{value0}}",
+ "ac8cbe3bf5": "Pase el cursor sobre una línea en la vista de diferencias y haga clic en + para agregar una nota.",
+ "286dbda4d6": "Rever",
+ "476b77745b": "Cambiar referencia base",
+ "ed34038d0d": "Actualizar comparación de sucursales",
+ "493f963029": "Cambiar referencia base",
+ "3278b2767b": "adelante",
+ "11b5dd8e41": "Comparando contra",
+ "783a808870": "Cerca",
+ "a9bf7c171a": "Confirmación fallida",
+ "03d238218c": "Detalles",
+ "011f9713fc": "Confirmación bloqueada",
+ "cc199ccc5f": "Más compromisos y acciones remotas",
+ "4d6e1fd7f3": "Más acciones",
+ "37a81f29ad": "Generando mensaje de confirmación. Haga clic para detener.",
+ "b94112eb9e": "mensaje de confirmación",
+ "0d0a8359d3": "Mensaje",
+ "15b7f210d7": "Revise el mensaje antes de iniciar un agente.",
+ "054ead86b1": "Solucionar errores de confirmación con IA",
+ "9e5ccd00aa": "Contexto de error de confirmación no disponible",
+ "f0a2dc9e46": "Personalizar el lanzamiento...",
+ "ec7bfced55": "Elija un agente para solucionar el error de confirmación",
+ "dd43c47089": "Elija un agente para este error de confirmación",
+ "30b8d4f181": "Soluciona el error de confirmación con IA",
+ "4b37ae99b0": "Inicie el agente de IA predeterminado para solucionar este error de confirmación",
+ "ae743199cd": "Elija una rama base diferente antes de crear un {{value0}}.",
+ "c5e4175139": "Más {{value0}} y acciones remotas",
+ "78ddfd0bb4": "Crear como borrador",
+ "e64a632456": "principal",
+ "6055949c50": "{{value0}} rama base",
+ "1f7119f604": "Base",
+ "9484270f45": "Generando título y descripción…",
+ "a0dc20fc93": "Descripción (opcional)",
+ "a8873e1d62": "{{value0}} descripción",
+ "7d6a8f0082": "Título",
+ "a6eda33521": "{{value0}} título",
+ "02d8c04339": "Genera detalles {{value0}} con IA",
+ "aee92f8684": "Generar",
+ "e868cec4e1": "Generando…",
+ "b355e740b2": "Dejar de generar detalles {{value0}}",
+ "527e130b6f": "dejar de generar",
+ "e1970d327d": "Nuevo {{value0}}",
+ "f4c766f1ca": "Elija el agente y la plantilla de comando para esta ejecución.",
+ "1a6a6e0bc5": "Generar detalles de reseña alojada",
+ "6b122529d4": "Generar mensaje de confirmación",
+ "e48caaf0dd": "Inició un agente de IA para los conflictos.",
+ "901140f47d": "Revise el mensaje antes de iniciar un agente.",
+ "19652ddd76": "Resolver conflictos con IA",
+ "c9ad22888e": "Elija el objetivo de comparación de sucursales para este repositorio.",
+ "574d2f4413": "Borrar notas",
+ "05bb8f4a48": "Cancelar",
+ "48db37cca9": "Ver todo",
+ "78ce2d37ac": "Empuja al tenedor",
+ "c05fe04839": "Empuja hacia la bifurcación en {{value0}} (no origen)",
+ "c35baf2f1e": "Filtrar archivos…",
+ "2fe2a67580": "Más acciones de notas",
+ "eae2d051af": "Copiar todas las notas",
+ "cc474e0b8c": "Notas",
+ "e131cd7128": "Source Control sólo está disponible para repositorios Git",
+ "c07b236287": "Seleccione un espacio de trabajo para ver los cambios",
+ "dc5a6465fc": "{{value0}} (por ejemplo, {{value1}}{{value2}})",
+ "8eb3782a0c": "No se pudo descartar el archivo {{value0}}{{value1}}",
+ "a5e5a11090": "Descartar todo falló: no se pueden eliminar los archivos antes de descartarlos",
+ "8a5ba6a988": "No se pudo cargar la diferencia de confirmación",
+ "fe5bd1a610": "Creando {{value0}}...",
+ "812cb992ee": "Abierto el {{value0}}",
+ "eef5446523": "{{value0}} #{{value1}} ya está abierto",
+ "0453ca3a9a": "{{value0}} creado, pero Orca no pudo actualizarlo todavía.",
+ "f99560ab29": "Cancelar {{value0}} falló",
+ "eae7a1da5f": "No se pudieron borrar las notas.",
+ "657e0c90ad": "{{value0}} nota{{value1}}",
+ "df5040e3c3": "fuera del escenario",
+ "8cde1a2fb0": "Escenario",
+ "d54dd48b0b": "Descartar cambios",
+ "989f3d5e34": "Restaurar archivo",
+ "2830dd64a2": "eliminado",
+ "11463f7a98": "Eliminar archivo sin seguimiento",
+ "d62bc0c7d8": "sin seguimiento",
+ "ab31221779": "Carpeta sin escenario",
+ "bfe9011a0e": "Carpeta de escenario",
+ "6d7f2a47e5": "Descartar carpeta",
+ "9b367363b6": "Eliminar sin seguimiento en la carpeta",
+ "540ca8f78c": "Cancelar fusión",
+ "425f138269": "Abortar rebase",
+ "04832d8047": "rebase",
+ "c105a61960": "unir",
+ "d7a5942e41": "{{value0}}: {{value1}} sin resolver",
+ "c56ba7fa06": "diferencia",
+ "94c42b252e": "Maryland",
+ "e59bca888a": "reducción",
+ "b6922abb13": "No se puede cargar la comparación de ramas.",
+ "715d229c86": "Comparación de sucursales no disponible",
+ "97d8b03cdf": "Error en la comparación de sucursales",
+ "424ee0e5bf": "error",
+ "834cb3f23d": "Arreglar con IA",
+ "60bd988f0b": "Corrección de IA",
+ "461575b9bc": "Generar mensaje de confirmación con IA",
+ "ddc1fbd690": "Dejar de generar mensaje de confirmación",
+ "5acbcedc1a": "Crear {{value0}}",
+ "aaf1451654": "Crear borrador {{value0}}",
+ "26511c22b4": "Creando...",
+ "7a09d7f9d2": "base",
+ "383cf92c73": "árbol",
+ "d7ae61269b": "Comprometidos en Sucursal",
+ "3636d0f686": "listo",
+ "d2e9189866": "todo",
+ "a0cc0e6b4e": "cargando",
+ "9339382454": "Dejar de escena todo",
+ "24d2598eff": "poner en escena todo",
+ "ce41708855": "Descartar todo",
+ "2f609a2e7c": "Eliminar todo sin seguimiento",
+ "9bb062a886": "no comprometido",
+ "9febd8ab5f": "crear_pr",
+ "f62ce91ade": "origen",
+ "3a231c845b": "desconocido",
+ "3baf6c77b4": "Copiar todas las notas al portapapeles",
+ "72f2bea3f4": "Expandir notas",
+ "d13edef890": "Contraer notas",
+ "0fad573938": "No comprometido",
+ "77afaa8152": "Todo",
+ "d6fb1df5fe": "{{value0}} ya está abierto",
+ "05838cfdeb": "{{value0}} conflicto",
+ "d206117f90": "{{value0}} conflicto ({{value1}})",
+ "0b5b8c234c": "Abierto {{value0}} ({{value1}})",
+ "d97ef8f221": "líneas {{value0}}-{{value1}}",
+ "6f8bfa0eb9": "línea {{value0}}",
+ "c569d29a02": "ambos modificados",
+ "ea7287d84f": "ambos agregados",
+ "bd0151ef7b": "eliminado por nosotros",
+ "44594e8c61": "eliminado por ellos",
+ "24773ee581": "añadido por nosotros",
+ "c03d7c952f": "añadido por ellos",
+ "5b176fa431": "ambos eliminados",
+ "31f6d46278": "Irresoluto",
+ "2c417432b7": "Resuelto localmente",
+ "f3a8b2c1d0e5": "Ingrese un título {{value0}}.",
+ "e2b7a1c0d9f4": "No se pudo crear {{value0}}"
+ },
+ "SourceControlAgentActionDialog": {
+ "8e856842d1": "No se pudo iniciar el agente seleccionado.",
+ "c075d00de1": "No se puede resolver la conexión del espacio de trabajo.",
+ "38b899cc02": "Todos los repositorios",
+ "808cfe0a3b": "este repositorio",
+ "994cddd1f7": "no guardar"
+ },
+ "SourceControlAgentActionDialogForm": {
+ "013c9ac04a": "Fuera de",
+ "1bb611240f": "Utilice {basePrompt} para el mensaje predeterminado de Orca.",
+ "23280cbab1": "Esta plantilla no incluye {basePrompt}, por lo que el agente no recibirá el mensaje predeterminado de Orca.",
+ "5421a96acb": "Guardar e iniciar agente",
+ "6cefcdfba1": "Puede cambiarlo más tarde en la configuración de AI de control de fuente.",
+ "c29f9cf266": "Guarde este mensaje y no muestre esta reseña la próxima vez",
+ "d8f40128ee": "{basePrompt} es el mensaje predeterminado de Orca.",
+ "ea4788705e": "Cancelar",
+ "7ec6abbf2a": "Reiniciar",
+ "f4f3c9ca4a": "plantilla de aviso",
+ "1bc0bdbb5e": "Lanzamiento:",
+ "fe119187bb": "--soneto modelo",
+ "bc8dc39f4b": "Argumentos CLI",
+ "b99c33cec5": "Ajustes",
+ "15c5d85706": "Agente",
+ "3e8f21954f": "error",
+ "74168d7ada": "idle",
+ "1d47db9bf0": "No hay agentes habilitados",
+ "c7ff8cef11": "Detectando agentes..."
+ },
+ "SourceControlTextGenerationDialog": {
+ "c5b7fa7cb6": "Guardar como valor predeterminado global",
+ "7f1ec309a4": "Guardar como predeterminado para todos los repositorios",
+ "5959da1e4d": "Guardar solo para este repositorio",
+ "d054d5e0a0": "La configuración no está cargada."
+ },
+ "SourceControlTextGenerationDialogForm": {
+ "25fcd8e49a": "Guardar valores predeterminados",
+ "d91b0a189d": "guardar receta",
+ "1f6fcfb6cf": "Plantilla de comando",
+ "551ffd111b": "--soneto modelo",
+ "4eab815004": "Argumentos CLI",
+ "914c8f6ac2": "Comando personalizado",
+ "cce2cbd01d": "Elige agente",
+ "9c14186dd2": "Agente"
+ },
+ "activity": {
+ "bar": {
+ "buttons": {
+ "1fd284e931": "Más pestañas de la barra lateral",
+ "f1132ea95d": "neutral"
+ }
+ }
+ },
+ "checks": {
+ "panel": {
+ "content": {
+ "3916814392": "detrás (compromiso base:",
+ "755be805f6": "Sin comentarios",
+ "751f7c6e5c": "Mostrando los primeros 100 comentarios por fuente",
+ "94557d68e2": "Comentarios",
+ "3fff651d32": "Añadir un comentario de relaciones públicas",
+ "ea9fd5ed6a": "Iniciar conversación...",
+ "0fc6f743b3": "por",
+ "8987d5a3dd": "Resuelto",
+ "ba20d1a896": "Responder a {{value0}}",
+ "f6a40263ff": "Ahorrar",
+ "b062f55f29": "Cancelar",
+ "c1f6fc006a": "Responder",
+ "2ba0a32bdd": "bot",
+ "6cc6eace26": "Borrar",
+ "03ca88f623": "Editar",
+ "d3923d18fe": "ir a comentar",
+ "1abb17aac9": "Más",
+ "74c6885b8a": "Más acciones de comentarios",
+ "cbcc4ab3db": "Mostrando los primeros 100 cheques",
+ "0dca6bfab5": "Abrir detalles del cheque",
+ "991f50c7e4": "No hay controles configurados",
+ "9ad98f2a17": "pendiente",
+ "5e52f4ef7f": "defecto",
+ "02ca4f9074": "paso",
+ "e15a8b77ef": "No hay detalles en línea disponibles para esta verificación.",
+ "679bf2093c": "Copiar la cola del registro",
+ "d713f500b2": "Cola de registro (últimas 200 líneas)",
+ "a916648574": "Abrir detalles",
+ "07eccfa397": "No hay detalles disponibles para este cheque.",
+ "49731703ea": "Empleos",
+ "f2fe8a4e8f": "Anotaciones",
+ "d098e5529a": "Producción",
+ "2dd5ddabc4": "flujo de trabajo #",
+ "aa8494ae3c": "controlar #",
+ "00e1c1658a": "Terminado",
+ "fd46a70f1a": "Comenzó",
+ "a54ae21c6f": "Estado:",
+ "e4e3af15ee": "Ver todos los detalles",
+ "2524d1fb83": "Cola de registro disponible con todos los detalles.",
+ "a2fb3f4408": "Mostrando los primeros 100 empleos",
+ "df137989b3": "Mostrando las primeras 20 anotaciones",
+ "1f2b980522": "Cargando detalles del cheque...",
+ "0c96cd25e5": "Resolver",
+ "3a71a6ed0b": "Resuelva los conflictos antes de que se puedan completar las comprobaciones y la fusión.",
+ "60186d8498": "Los conflictos bloquean esto",
+ "c16762ac8c": "Las comprobaciones y comentarios a continuación muestran el contexto obtenido actualmente.",
+ "9d0e7bcefc": "Sin acciones de relaciones públicas de bloqueo",
+ "5856874b59": "Orca actualizará los controles mientras este panel permanezca abierto.",
+ "5341023167": "controlar",
+ "b45db92d0e": "Arreglar",
+ "5d4ebf9391": "Inspeccione los detalles o inicie un pase de reparación de IA.",
+ "b652f38caf": "cheque fallido",
+ "87cd07c69a": "Esta rama tiene conflictos que deben ser resueltos.",
+ "0975eeaaef": "Archivos conflictivos",
+ "6fa7f8723f": "comprometerse",
+ "2b2be92919": "Añadir comentario",
+ "7440d09d2c": "Iniciar conversación",
+ "b37ebdc51c": "Comentarios no disponibles.",
+ "90206b6353": "comentario",
+ "95ad090b01": "hilo",
+ "365254cc1b": "no resolver",
+ "7f793b571d": "Arrastre para cambiar el tamaño de los cheques",
+ "ee07b33924": "desconocido",
+ "cdbfda4dec": "Anotación",
+ "066fedd446": "Trabajos fallidos",
+ "ae8a04ef17": "Los detalles del archivo de conflicto no están disponibles",
+ "73d0675356": "Detalles refrescantes del conflicto..."
+ },
+ "empty": {
+ "state": {
+ "5b0cfae9a5": "Cree un {{value0}} para iniciar comprobaciones y revisiones.",
+ "13e1c7d5ed": "No se encontró {{value0}}",
+ "d372072df1": "La actualización de GitHub está pausada por el presupuesto de límite de velocidad actual",
+ "7c299df37b": "No se encontró ninguna solicitud de extracción",
+ "3d4af82ff4": "Actualizando el estado de GitHub para esta rama",
+ "938b5606a6": "Comprobando la solicitud de extracción",
+ "6ba2440770": "Esperando actualizar el estado de GitHub para esta rama",
+ "2bdd7aaf2d": "No se pudo actualizar el estado de GitHub. Se conservaron los datos almacenados en caché existentes.",
+ "5f478ab3d3": "No se pudo actualizar la solicitud de extracción",
+ "6ce9d4e069": "Empuje su rama antes de crear un {{value0}}.",
+ "76e15946a9": "La rama tiene confirmaciones no enviadas",
+ "f8543140cc": "Publique esta rama antes de crear un {{value0}}.",
+ "41252bc53f": "Sucursal no publicada",
+ "05e4aec17b": "{{value0}} cheques estarán disponibles una vez completada la operación.",
+ "d77c513c1e": "{{value0}} en progreso"
+ }
+ }
+ }
+ },
+ "gitlab": {
+ "mr": {
+ "merge": {
+ "state": {
+ "04a3015a12": "Capaz de fusionarse",
+ "53c6d3b7e9": "GitLab dice que este MR se puede fusionar, pero el proceso aún está en ejecución",
+ "65c847ad1e": "Cheques pendientes",
+ "b41fbc180c": "GitLab dice que este MR se puede fusionar, pero algunos trabajos de canalización fallaron",
+ "49ac4fec10": "Los controles fallaron",
+ "22b7e50621": "Los informes de GitLab fusionan conflictos",
+ "96b05e374c": "Conflictos",
+ "d63bb6f76e": "Esta solicitud de fusión aún es un borrador.",
+ "b2715092c6": "Borrador",
+ "2388413f28": "Esta solicitud de fusión está cerrada",
+ "88d044c42f": "Cerrado",
+ "ee482a2bad": "Esta solicitud de fusión ya está fusionada",
+ "fae95ae20d": "Fusionado"
+ }
+ }
+ }
+ },
+ "index": {
+ "70893f017b": "Lado",
+ "7b415c39e9": "Arriba",
+ "864111caa2": "Posición de la barra de actividades",
+ "e8e2e4ce74": "Alternar barra lateral derecha",
+ "441733b630": "Puertos",
+ "83a10e3c44": "cheques",
+ "0314901467": "Control de fuente",
+ "06219e4cb1": "Buscar",
+ "8bc2bbc3a0": "Explorador",
+ "45b78f03bc": "lado",
+ "34af8aadf5": "arriba",
+ "9fffaf17c1": "Alternar barra lateral derecha ({{value0}})",
+ "b37ff4a89a": "puertos",
+ "9f83375839": "cheques",
+ "6306b48afd": "control de fuente",
+ "ef182dcb12": "buscar",
+ "fc3095d2ed": "explorador"
+ },
+ "right": {
+ "panel": {
+ "comment": {
+ "composer": {
+ "9bca633dee": "Cancelar",
+ "cf5a7aba6f": "Lista",
+ "d6d9c3c947": "Cita",
+ "f49e0a21e0": "Código",
+ "542bf6a7e2": "Itálico",
+ "256300f8ea": "Atrevido",
+ "87aff03d63": "Envío..."
+ }
+ }
+ }
+ },
+ "source": {
+ "control": {
+ "ai": {
+ "commit": {
+ "failure": {
+ "launch": {
+ "a8b97d2318": "Se inició un agente de IA para el error de confirmación.",
+ "5540ff50cc": "No se pudo generar el comando de inicio del agente.",
+ "9bbd9077a2": "No hay agentes de IA habilitados. Configure los agentes en Configuración.",
+ "d481ab22f9": "El agente de IA guardado no está disponible. Utilice Personalizar inicio para elegir otro agente.",
+ "f2b47026e8": "El mensaje de error de confirmación está vacío. Actualice la configuración de AI de control de fuente.",
+ "4f4e0418a0": "No se pudo generar el mensaje del agente.",
+ "216f762bd7": "No se puede resolver la conexión del espacio de trabajo."
+ }
+ }
+ }
+ },
+ "discard": {
+ "confirmation": {
+ "2ae5a785b3": "¿Descartar todos los cambios no preparados?",
+ "ddf36f291c": "Esto eliminará y revertirá todos los cambios preparados. Se eliminarán los archivos nuevos preparados. Esto no se puede deshacer.",
+ "5ddd8cac7f": "¿Descartar todos los cambios por etapas?",
+ "1426c2efff": "Esto revertirá todos los cambios realizados en este archivo. Esto no se puede deshacer.",
+ "d4df3a61df": "¿Descartar cambios a \"{{value0}}\"?",
+ "40e9357b2a": "Esto restaurará el archivo desde HEAD y descartará la eliminación. Esto no se puede deshacer.",
+ "5c0bdbc4cb": "¿Restaurar \"{{value0}}\"?",
+ "d97bf697c9": "Esto eliminará permanentemente este archivo. Esto no se puede deshacer.",
+ "96c772bee9": "¿Eliminar \"{{value0}}\"?"
+ },
+ "dialog": {
+ "3bc61dc989": "Cancelar",
+ "15efa778e3": "Desechar",
+ "6de99d162b": "entrada",
+ "42f89dd030": "archivos",
+ "e7611dca35": "archivo",
+ "48c5ef95d9": "área",
+ "0d2d88cba5": "Esto no se puede deshacer.",
+ "1551c14668": "¿Descartar cambios?"
+ }
+ },
+ "dropdown": {
+ "items": {
+ "7aad2c0240": "Operación de revisión alojada en curso...",
+ "9e779995dd": "Crear {{value0}}",
+ "226b85a3a7": "Buscar",
+ "323bb614aa": "Confirmar y sincronizar",
+ "2b8e6595fd": "Comprometerse"
+ }
+ },
+ "primary": {
+ "action": {
+ "ed93b4f14f": "Comprometerse",
+ "946a8a05ea": "Crea un {{value0}} para esta rama",
+ "e7ffa46946": "Crear {{value0}}",
+ "95550cff15": "Empujar",
+ "d64292a938": "Jalar",
+ "795f1509c5": "Sincronizar",
+ "390abeab93": "Empuje forzado",
+ "1884cf34af": "Publicar esta rama en origen",
+ "7b4d02e6b8": "Rama de publicación",
+ "3d5dccef0b": "Nada que comprometer. PR ya está fusionado.",
+ "41d4bcf157": "Comprobando el estado de las relaciones públicas...",
+ "acce237921": "Nada que comprometer. La sucursal no tiene cambios para publicar.",
+ "fa3bd4f40c": "Prepare al menos un archivo para confirmar",
+ "5a477d80cb": "Organiza todos los cambios",
+ "18a0fca877": "Escenario todo",
+ "f01f16d77f": "Ingrese un mensaje de confirmación para confirmar",
+ "ab41fb926b": "Realizar cambios por etapas",
+ "2d8f185fbc": "Prepare todos los cambios antes de enviar archivos parcialmente preparados",
+ "a6457b46a7": "Resolver conflictos antes de comprometerse",
+ "484f45c439": "{{value0}} en progreso…",
+ "74fc171e99": "Empuje forzado en progreso...",
+ "16aee3a5c1": "Compromiso en progreso..."
+ }
+ }
+ }
+ },
+ "use": {
+ "source": {
+ "control": {
+ "ai": {
+ "cfafa92509": "No hay conflictos sin resolver para enviar."
+ }
+ }
+ }
+ },
+ "useFileDeletion": {
+ "72691dfebc": "No se pudo realizar {{value0}} '{{value1}}'.",
+ "96affe1302": "'{{value0}}' se movió a {{value1}}",
+ "74727df633": "'{{value0}}' eliminado",
+ "d979a4fbb5": "¿Eliminar permanentemente '{{value0}}'?",
+ "a76c74f105": "destructivo",
+ "92276aceb7": "Borrar"
+ },
+ "useFileExplorerHandlers": {
+ "32cd9fd991": "No se puede abrir el destino del enlace simbólico"
+ },
+ "useFileExplorerImport": {
+ "25919b2050": "Se omitió {{value0}} {{value1}}.",
+ "132fd0e1e9": "No se pudo importar {{value0}} {{value1}}."
+ },
+ "useFileExplorerKeys": {
+ "8adb953095": "Operación fallida"
+ },
+ "GitHistoryGraphSvg": {
+ "47eff48230": "CABEZA"
+ },
+ "create": {
+ "pull": {
+ "request": {
+ "review": {
+ "copy": {
+ "a1f8c3d2e4": "La inserción se realizó correctamente, pero la creación de {{value0}} falló: {{value1}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "repo": {
+ "NestedRepoChecklist": {
+ "f7e1170567": "seleccionado",
+ "ea54c7bf8f": "de",
+ "91b5bcadb6": "Seleccionar todo",
+ "929734aea5": "Deseleccionar todo"
+ },
+ "NestedRepoScanLimitNotice": {
+ "642a43c139": "Límites de análisis del repositorio anidado",
+ "574eb5408b": "Mostrando resultados de escaneo parciales.",
+ "03e9beab7b": "El escaneo se detuvo antes de tiempo."
+ },
+ "RepoCombobox": {
+ "b3e15f4525": "Agregar proyecto",
+ "b4a235e886": "Agregar proyecto",
+ "3639fd9da2": "SSH",
+ "e7ed739236": "Ningún proyecto/carpeta coincide con su búsqueda.",
+ "a0c48f5f29": "Buscar proyectos/carpetas...",
+ "116812151a": "Agregando proyecto…"
+ },
+ "repo": {
+ "icon": {
+ "0ad395d475": "Caja",
+ "857977b901": "formas",
+ "b1b8d99fc4": "AI",
+ "137bdb1856": "Métrica",
+ "d202c659a3": "Diseño",
+ "c4fd14299d": "Compañía",
+ "4ab9433660": "Trabajar",
+ "febfbe0cd5": "Herramientas",
+ "ecf63ec3ef": "Lanzamiento",
+ "31826b712e": "API",
+ "70bef15d40": "capas",
+ "b5fac337aa": "Calcular",
+ "d37b4e2641": "Servidor",
+ "3c5a593bc8": "Web",
+ "477b28c948": "Base de datos",
+ "787490e9bd": "Paquete",
+ "07012dc113": "Agente",
+ "3eba7387ab": "Terminal",
+ "65b437c381": "Código",
+ "bed2674f9d": "Carpeta"
+ }
+ }
+ },
+ "pet": {
+ "pet": {
+ "models": {
+ "7433516faf": "Duendecillo",
+ "a84d5677ff": "OpenCode",
+ "2528586aa7": "Claudio"
+ }
+ },
+ "PetOverlay": {
+ "de932b0e8f": "@keyframes pet-bob { 0%,100% { transformar: traducirY(0); } 50% { transformar: traducirY(-4px); } }",
+ "4712d196c6": "@keyframes pet-{{value0}} { desde { posición-fondo: {{value1}}px {{value2}}px; } a { posición de fondo: {{value3}}px {{value4}}px; } }"
+ }
+ },
+ "onboarding": {
+ "AgentStep": {
+ "e6a369bd04": "Agentes populares",
+ "d7b3ef168b": "Detectado en su sistema",
+ "9c163bb0e0": "Instrucciones de instalación",
+ "69af7e9c1c": "aún no está en tu RUTA. Orca lo configurará como predeterminado y podrás instalarlo en cualquier momento.",
+ "1eee1c7bd8": "No se detectaron agentes en su RUTA. Elija uno para instalarlo más tarde o continúe con un terminal en blanco.",
+ "hideAgents": "Ocultar agentes",
+ "showMoreAgents": "Mostrar {{value0}} más agentes→"
+ },
+ "FeatureSetupChecklist": {
+ "77f74946f5": "Los agentes pueden enviarse mensajes entre sí, realizar tareas y coordinar traspasos.",
+ "399cf885c0": "Orquestación de agentes",
+ "c5292c409d": "Los agentes pueden inspeccionar las ventanas de las aplicaciones y operar aplicaciones locales cuando usted lo solicite.",
+ "1ecfb490ac": "Uso de la computadora",
+ "01426f3a23": "Los agentes pueden navegar por sitios, inspeccionar páginas y realizar tareas del navegador.",
+ "ea85d9e628": "Uso del navegador del agente"
+ },
+ "FeatureSetupInlineTerminal": {
+ "789b59936e": "Presione Enter para ejecutar el comando y confirme npx si se le solicita. También puedes configurar esto más tarde en Configuración.",
+ "47fc6cc6dc": "Comando de configuración de habilidades",
+ "c767ab7061": "Configuración de habilidades"
+ },
+ "IntegrationsStep": {
+ "277f30eb34": "Linear, GitLab, Bitbucket, Azure DevOps, Gitea y Jira se encuentran en Configuración > Integraciones.",
+ "3a3e360289": "Más fuentes de tareas",
+ "80e3ce0bc9": "Vuelva a comprobar",
+ "04ef416712": "Agregar acceso Linear",
+ "dd9c186a8b": "Agregar acceso al espacio de trabajo",
+ "c91a5782f1": "Conectado",
+ "27743304b1": "Linear",
+ "af69f42372": "Presione Entrar para ejecutar la autenticación CLI de GitHub. Vuelva a verificar GitHub después de que finalice el flujo del navegador o dispositivo.",
+ "f9d2e12d17": "Comando de inicio de sesión de GitHub",
+ "6d469169f2": "Configuración de GitHub",
+ "bd5d976fb2": "Instalar gh",
+ "50db38cf4b": "Solicitudes de extracción, problemas y estado de verificación.",
+ "c1547656f0": "De cheques…",
+ "8405043962": "Iniciar sesión es necesario",
+ "5c115cb713": "CLI no instalado",
+ "217beb0658": "GitHub",
+ "4983ae7433": "Agregue acceso Linear con una clave API personal. Las claves de acceso total pueden mostrar todos los equipos a los que puede acceder el propietario de la clave.",
+ "b08a6ac93c": "{{value0}} espacio de trabajo{{value1}} vinculado. Agregue otro espacio de trabajo o reemplace una clave restringida en cualquier momento.",
+ "93f0c49ad1": "no autenticado",
+ "a3bcf13694": "conectado",
+ "d6e5dba05a": "Iniciar sesión",
+ "0b4a7d23ab": "Iniciar sesión",
+ "a74c6d6b18": "no instalado"
+ },
+ "NotificationStep": {
+ "3bede04483": "Enviar notificación de prueba",
+ "dc897423e1": "Elige sonido de notificación",
+ "53aaffe49a": "Sonido de notificación",
+ "0fe570690c": "Elija la alerta que Orca reproduce después de que se envía una notificación de escritorio.",
+ "0af746e41f": "Elige un sonido",
+ "8124d085a6": "Abra la configuración de Mac",
+ "aa36281b00": "Abra Configuración del sistema y asegúrese de que Orca pueda enviar notificaciones.",
+ "d2dba86837": "Permitir Orca en macOS",
+ "e52aacf380": "Cargando configuración de notificaciones…",
+ "3cd5374e22": "La configuración de notificaciones aún se está cargando",
+ "b6a994e36e": "No se pudo reproducir el sonido de notificación",
+ "c0692baa52": "Elija un archivo personalizado",
+ "ac80d97e02": "Cambiar archivo personalizado"
+ },
+ "OnboardingFlow": {
+ "1b5e182e9f": "Bienvenido a Orca",
+ "4db04f2f57": "de",
+ "adaa0aa627": "Vaya al paso de incorporación {{value0}}: {{value1}}",
+ "a249f81538": "Orca",
+ "277ba45540": "Incorporación de Orca",
+ "97c42cda00": "Instale la CLI de GitHub para:",
+ "ae3b00ca82": "Configurar tareas de GitHub",
+ "ff92d15436": "Orca le notificará cuando los agentes hayan terminado o necesiten ayuda.",
+ "b054332836": "Configurar notificaciones",
+ "04ae28d8ca": "Elige el look que quieras mirar durante horas.",
+ "f396db9f20": "Haz que te sientas como en casa",
+ "322fc50a18": "Orca trabaja con todos los agentes CLI. Elija el que alcanzará más. Cambie en cualquier momento.",
+ "198b148b3c": "Elija su agente predeterminado",
+ "a5e5da02f7": "integraciones",
+ "35bbaf5ae0": "notificaciones",
+ "984338477a": "tema",
+ "c47e1bd149": "agente"
+ },
+ "OnboardingFooter": {
+ "ba58547306": "Atrás",
+ "111d3f8d92": "Saltar a la configuración del proyecto"
+ },
+ "OnboardingInlineCommandTerminal": {
+ "4123609efd": "Terminal de arranque..."
+ },
+ "OnboardingSkipConfirmationDialog": {
+ "9f47f345a4": "¡No tardará mucho!",
+ "e4726b2d50": "¿Saltar la incorporación?"
+ },
+ "OnboardingTourStep": {
+ "3f9586c043": "Haz el recorrido",
+ "60c5576353": "Salir del recorrido"
+ },
+ "RepoStep": {
+ "e8fdb36338": "Escaneo de repositorios. Haga clic para detener.",
+ "b7c4da0504": "SSH? Configurar hosts en Configuración",
+ "c33b190ca3": "Sólo rutas de servidor",
+ "7b679207e4": "Espacio de trabajo",
+ "24c7c8696c": "Clonar en la ruta del servidor",
+ "7932e95f68": "Clon",
+ "955134915e": "git@github.com:org/repo.git",
+ "288d8444b7": "Pegue una URL HTTPS o SSH.",
+ "132425a3e3": "Clonar un repositorio",
+ "6558d50c69": "¿Quieres importar muchos repositorios a la vez? Seleccione la carpeta principal.",
+ "831524961f": "Elija cualquier directorio local, repositorio git o no.",
+ "f4e9c8dcf8": "Buscar una carpeta",
+ "e8214aa632": "Abrir como carpeta",
+ "3863747c56": "Agregar proyecto Git",
+ "2ebbc26343": "/inicio/usuario/proyecto",
+ "466108ab89": "Introduzca una ruta que exista en el servidor de ejecución.",
+ "8cab104e3c": "Abrir un proyecto de servidor",
+ "2d20200346": "Importar repositorios",
+ "27ca610db1": "Atrás",
+ "cecd6593fa": "Carpeta escaneada:",
+ "c7af322fc3": "Dejar de escanear",
+ "c3d9d44ca2": "Detener escaneo",
+ "cf23006ba7": "Servidor de ejecución",
+ "7ec3f48820": "/casa/usuario",
+ "2e6438dd34": "{{value0}}Encontrado {{value1}} {{value2}} en esta carpeta."
+ },
+ "ThemeStep": {
+ "a4b254779d": "Tecla de opción de macOS",
+ "6c51398942": "Ratón",
+ "8ca01945f2": "Divisores",
+ "b3a99a2d29": "Ventana",
+ "86c0f1caa2": "Relleno",
+ "06a24f4f2d": "Bandera",
+ "c021e9dddd": "paleta temática",
+ "ab2a583a97": "Cursor",
+ "cc1858e19e": "Fuente",
+ "248c812283": "Importar",
+ "7ee9234e54": "Se detectó una configuración fantasmal.",
+ "78b6386140": "Importado de Ghostty.",
+ "2c3aa538f8": "Buscando una configuración de Ghostty...",
+ "94b9dc561d": "Configuración → Terminal",
+ "dd5c16ad1b": "Más opciones de terminal, incluyendo fuente, cursor y paleta, en",
+ "ad192706e6": "Luz",
+ "fa7b673ea9": "Oscuro",
+ "827ea7b4a2": "Sistema",
+ "699ddf83c2": "No se pudo importar la configuración de Ghostty",
+ "16a9f0446a": "No se encontraron configuraciones de Ghostty para importar",
+ "ad19e5c916": "Importador…",
+ "906c4373fe": "ajustes"
+ },
+ "use": {
+ "onboarding": {
+ "flow": {
+ "dce4bdce5b": "No se pudo abrir la configuración de SSH",
+ "fd74e7558e": "Clon falló",
+ "52acfbef51": "No se pudo guardar el progreso"
+ }
+ }
+ },
+ "AgentFeatureSetupStep": {
+ "97dcdc010f": "Habilitar capacidades"
+ }
+ },
+ "new": {
+ "workspace": {
+ "SmartWorkspaceNameField": {
+ "2a0d535f69": "Crear nueva sucursal",
+ "a44229ce4d": "como nombre del espacio de trabajo",
+ "766083a596": "\"",
+ "34ca97bce3": "\"",
+ "b1a7d679ba": "Usar",
+ "e57c53727c": "Añadir proyecto...",
+ "a76fcb4fa0": "Cambiar a",
+ "eadf877af5": "Mantener",
+ "6859e2896c": "Cancelar",
+ "9ef1a7c4b0": ", que es diferente del proyecto seleccionado.",
+ "ad188067ae": "La URL de GitHub apunta a",
+ "4bd98f1091": "¿Cambiar de proyecto?",
+ "0c9e668e3a": "Claro",
+ "7199ff19c7": "Borrar fuente seleccionada",
+ "370a1faf67": "Abrir en el navegador",
+ "2c69728c2a": "Abrir enlace en el navegador",
+ "6f07a18604": "Nombre",
+ "2e4c7c95fe": "Rama",
+ "2cfc6be192": "GitLab",
+ "7a47af0565": "Linear",
+ "0a180280bd": "GitHub",
+ "b3c60c2b7c": "Elegante",
+ "26824f60dd": "Todo",
+ "6fad211c66": "Cerrado",
+ "2319d87718": "Fusionado",
+ "622864b52a": "Abierto",
+ "fda67f0b61": "proyecto actual",
+ "3e8bb1176a": "Conecte Linear en Configuración para buscar problemas.",
+ "69ce292138": "lineal",
+ "9c004911c3": "gitlab"
+ }
+ }
+ },
+ "mobile": {
+ "MobileHero": {
+ "a8fb43cf1c": "Continue",
+ "3f90dbd274": "Hecho",
+ "b622eba64d": "Atrás",
+ "65b3f2e8bc": "Generando…",
+ "27735e5f4e": "Emparejamiento QR",
+ "bb0074ce11": "Emparejamiento de código QR",
+ "010dddcf27": "Copiar código de emparejamiento",
+ "4c1df4eba7": "¿No puedes escanear?",
+ "85067b9e06": "Actualizar interfaces de red",
+ "ca85e595a7": "No se encontraron interfaces",
+ "79d2f480da": "Interfaz de red para anunciar",
+ "dfd2aa9d5d": "Red",
+ "2f077ef4eb": "y escanea el código.",
+ "3aa7bb2d8b": "Emparejar escritorio",
+ "d1495e5e64": "Abra Orca Mobile, toque",
+ "901c98bb93": "Empareja esto",
+ "3960f5c339": "Paso 2 de 2",
+ "3241f3c26a": "Instalar QR",
+ "7af266b80d": "Instalar código QR",
+ "aa97420ba4": "Copiar enlace de instalación",
+ "ac1eb64952": "Androide",
+ "711e6f4b47": "iOS",
+ "e75647ace0": "Escanee el QR con su teléfono o abra el enlace de instalación para obtener Orca Mobile.",
+ "0d9b33299e": "Obtén la aplicación.",
+ "92ddfdfa1f": "Paso 1 de 2",
+ "ff48d9d520": "Emparejar otro dispositivo",
+ "f9cbf4bb53": "Revocar dispositivo",
+ "34f878d04f": "Revocar {{value0}}",
+ "94829abdb1": "emparejado",
+ "266c18c105": "Abre Orca Mobile para continuar donde lo dejaste o vincular otro dispositivo.",
+ "5410d55d79": "Orca Móvil",
+ "10d27b4cba": "empezar",
+ "da1d5e5ed0": "Disponible en",
+ "ec0607bf66": "Plataformas móviles compatibles",
+ "b4ccce5cb7": "Controla Orca desde tu teléfono. Consulte a los agentes, revise los cambios e inicie tareas mientras no está en su escritorio.",
+ "cd4e5e816f": "Tus espacios de trabajo, en tu bolsillo.",
+ "a6cffbbb0b": "Generar código",
+ "e59a252eca": "regenerar código",
+ "d0b52871ce": "Tus teléfonos están emparejados.",
+ "051978a785": "Tu teléfono está emparejado."
+ },
+ "MobilePage": {
+ "e17393c6a3": "Vista previa del teléfono",
+ "baea63c445": "No se pudo copiar el enlace",
+ "fad833de8d": "Enlace de instalación copiado",
+ "6a66e38943": "No se pudo copiar el código de emparejamiento",
+ "3c1f7168bb": "Código de emparejamiento copiado",
+ "4c8bd11c1a": "No se pudo generar el código de emparejamiento",
+ "b353e18de1": "El transporte de WebSocket no se está ejecutando",
+ "4e1eb5d55c": "No se pudo revocar el dispositivo",
+ "255372e6e8": "Dispositivo revocado",
+ "1b4509a8a1": "emparejado",
+ "c5909374cf": "introducción"
+ },
+ "MobilePageToolbar": {
+ "ad2284a9e2": "Cerrar · Esc",
+ "9883b58693": "Cerrar Orca Móvil",
+ "fb5f28330e": "Mostrar en la barra lateral",
+ "c669abcf8f": "Ocultar de la barra lateral"
+ },
+ "PhoneCarousel": {
+ "96d651cb87": "Sesión terminal",
+ "93217b41c1": "Lista de árbol de trabajo",
+ "89c7713645": "Pantalla de inicio de Orca Móvil"
+ },
+ "mobile": {
+ "platform": {
+ "copy": {
+ "2a532d6fd7": "Escanee con su cámara Android para descargar el último APK de GitHub Releases.",
+ "432db52b73": "Escanee con la cámara de su iPhone para abrir la App Store."
+ }
+ }
+ },
+ "slides": {
+ "HomeSlide": {
+ "a7d9e2c44d": "7d",
+ "a3d5476811": "5h",
+ "8a350a4784": "Uso de la cuenta",
+ "e27fdaee51": "Nuevo espacio de trabajo",
+ "4405f3c440": "Emparejar escritorio",
+ "0b00c98506": "Acciones rápidas",
+ "0bad5b07c8": "GitHub y Linear",
+ "d047197480": "GitHub · Linear",
+ "a4c3f7b7aa": "Tareas",
+ "d33d7a9c29": "orca · feat/página móvil",
+ "25d6e8a491": "hazaña/página móvil",
+ "c791677f2f": "Reanudar",
+ "cf3f98fa3f": "Desconectado",
+ "091355da3d": "M1 Mini · inicio",
+ "0bc1881bc4": "Conectados · 40 árboles de trabajo · 5 activos",
+ "19c212e25e": "macbook pro",
+ "2f1a1d10c4": "Escritorios",
+ "156db8a68a": "RP creados",
+ "4a40af029b": "tiempo del agente",
+ "00a6903322": "Agentes generados",
+ "c0e2e9dcd9": "Bienvenido de nuevo",
+ "af761a0c0d": "Ajustes",
+ "5d94e8ddcc": "Orca"
+ },
+ "TerminalSlide": {
+ "0bb39f8fe6": "Enviar",
+ "69334b4b10": "Dictado de voz",
+ "29f2d13839": "Escribe un comando...",
+ "817090af40": "Ctrl+C",
+ "53ff909568": "Pestaña",
+ "4930eaaae7": "ESC",
+ "fa22927f13": "Pasta",
+ "985373052e": "Cambiar al modo teléfono",
+ "58a9ee6003": "formato de llamada de herramienta. ¿Quieres que agregue la diferencia a continuación?",
+ "aa64b519c6": "pantalla del terminal. Paleta Tokyonight, Menlo, real claude",
+ "e75112c834": "Reemplacé la diapositiva de escaneo en pares con una de alta fidelidad.",
+ "3ce3e8c892": "14 aprobados, 1 saltado (1,8s)",
+ "4b3666f9a9": "src/cache/worktree-cache.test.ts",
+ "1d448b69f7": "APROBAR",
+ "d39445686a": "src/transport/host-store.test.ts",
+ "a6e7cdc688": "prueba pnpm --filtro móvil",
+ "21b67dfc92": "Intento",
+ "d6d1041a1c": "⎿ Se reemplazó la diapositiva de escaneo de pares con sesión de terminal",
+ "336c0e070e": "móvil/orca-mobile-sidebar-mock-v3.html",
+ "6d4ebd5833": "Editar",
+ "fc83e0d5ef": "⎿ Leer 2103 líneas",
+ "80cc356591": "Leer",
+ "2c10d43745": "claude",
+ "e0f98be657": "orca/feat-mobile-page",
+ "2defc05141": "desarrollador@mac",
+ "da121ba48d": "PLAN.md",
+ "e4befee569": "caparazón",
+ "606aa93192": "Archivos",
+ "94febb0976": "control de fuente",
+ "8d6516312d": "2 terminales · claude activo",
+ "8432787c4e": "hazaña/página móvil",
+ "8fd998acd3": "Atrás"
+ },
+ "WorktreeListSlide": {
+ "357a519567": "Activo",
+ "79a24ff530": "Fijado",
+ "22971156df": "repositorio",
+ "17f9e0d226": "Reciente",
+ "0e3e809a4b": "Filtrar",
+ "b4271864bd": "macbook pro",
+ "cefd048225": "Atrás",
+ "c5ad56786d": "hilandero"
+ }
+ }
+ },
+ "gitlab": {
+ "gitlab": {
+ "rate": {
+ "limit": {
+ "display": {
+ "ebc0e8ecf1": "Cargando presupuesto de API de GitLab...",
+ "a2d3d1fdde": "El presupuesto de la API de GitLab no está disponible.",
+ "a2f68645ac": "Actualizar el presupuesto de la API de GitLab",
+ "2f9c16d6c3": "Orca usa REST a través de la CLI de GitLab.",
+ "14e144f7a7": "Presupuesto de la API de GitLab",
+ "3e2c982cfa": "izquierda, se reinicia en",
+ "ea8ad0bae8": "de",
+ "0a891e8935": "API DESCANSO",
+ "953f7c6062": "Este host de GitLab no devolvió encabezados de límite de velocidad."
+ }
+ }
+ }
+ }
+ },
+ "floating": {
+ "terminal": {
+ "FloatingTerminalIconContextMenu": {
+ "8e7d775287": "Ocultar espacio de trabajo flotante",
+ "763f5fa2c1": "Mover al botón flotante",
+ "0ee79e0674": "Mover a la barra de estado"
+ },
+ "FloatingTerminalOrchestrationDialog": {
+ "f726054620": "Permite a los agentes traspasar contexto y coordinar el trabajo a través de Orca.",
+ "1cd3f8af64": "Habilidad de orquestación",
+ "6f0aed26b8": "Instale la CLI de Orca y la habilidad de orquestación para que los agentes puedan coordinarse a través de Orca.",
+ "05d7aabc20": "No instalado",
+ "630c0ac8c8": "Instalado",
+ "dfd021ce46": "De cheques...",
+ "543f325a14": "Habilitar orquestación"
+ },
+ "FloatingTerminalPanel": {
+ "fc1042e92b": "Minimizar",
+ "8b07759314": "Nuevo navegador",
+ "88ffb502e5": "Abrir nota de rebajas",
+ "629528690b": "Nueva nota de rebajas",
+ "3215fc73e9": "Nueva Terminal",
+ "da508bd7f5": "Ahorrar",
+ "918c2139f3": "No guardar",
+ "e7bf09d4d4": "Cancelar",
+ "690b6fb98a": "Cambios no guardados",
+ "bbc177f98f": "Permitir",
+ "adc281394d": "Despedir",
+ "8cf80db43b": "Configure la CLI de Orca y la habilidad del agente para que los agentes puedan coordinarse a través de Orca.",
+ "2a3c5ddf5e": "Habilitar orquestación",
+ "d6b563ae24": "Cargando editor...",
+ "8b14ba6c17": "Nueva pestaña del navegador",
+ "b085fb58b5": "Este archivo tiene cambios no guardados.",
+ "5ddc688c52": "\"{{value0}}\" tiene cambios no guardados. ¿Quieres guardar antes de cerrar?",
+ "25d7817f79": "Terminal"
+ },
+ "FloatingTerminalToggleButton": {
+ "3b04b065b5": "Mostrar espacio de trabajo flotante",
+ "5785dd9148": "Minimizar el espacio de trabajo flotante",
+ "bfe7809a70": "{{value0}} espacio de trabajo flotante ({{value1}})"
+ },
+ "FloatingTerminalWindowControls": {
+ "2f6054342c": "Minimizar",
+ "1bbaa0302f": "Minimizar el espacio de trabajo flotante",
+ "3f4ca29961": "Maximizar el espacio de trabajo flotante",
+ "1c79cba25d": "Restaurar el espacio de trabajo flotante",
+ "648352c51f": "Abra {{value0}} en el espacio de trabajo flotante",
+ "82da3701e7": "No se pudo generar el comando de inicio para {{value0}}.",
+ "109870e023": "Maximizar",
+ "b5686fee1e": "Restaurar",
+ "1e502f1284": "Abierto"
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "AgentCapabilitiesSetupAction": {
+ "b8dc9dd8a2": "Instalado",
+ "1b51644c2d": "Deje que los agentes controlen el escritorio, muevan el cursor, hagan clic y escriban en cualquier aplicación.",
+ "362a07517d": "Uso de la computadora",
+ "5e8fe5a72d": "Ofrezca a los agentes acceso directo al navegador de Orca para que puedan probar páginas, realizar capturas de pantalla y actuar en función de lo que ven.",
+ "e638da007a": "Uso del navegador del agente",
+ "c61c91e642": "Permita que los agentes se coordinen a través de Orca para que las tareas grandes de varios pasos avancen hasta su finalización.",
+ "ac07f8887f": "Orquestación de agentes",
+ "e9eb197e12": "Permisos de uso de computadora abiertos",
+ "3a59452a67": "Comando de habilidad copiado e insertado a continuación para su revisión.",
+ "c605f51f2b": "Configuración de capacidad lista",
+ "1aa657d8f4": "Alguna configuración de capacidad necesita atención",
+ "c89534cbe9": "Instalar CLI y habilidades"
+ },
+ "AiCommitPrSettingsCard": {
+ "8d4152701a": "p.ej. ollama corre llama3.1 {{value0}}",
+ "9ee54037a4": "Comando personalizado",
+ "4b2fc4b80c": "esfuerzo de pensamiento",
+ "be8917699e": "Modelo",
+ "4d9b6d84df": "sin soporte. Elija Claude, Codex o Personalizado.",
+ "560d4feb00": "Costumbre",
+ "29d119fe95": "Agente",
+ "f9382b48a1": "Habilitar autor de IA",
+ "1c0cb4fabb": "autor de IA",
+ "bd14e9c42a": "No configurado",
+ "1f9468c5c9": "{{value0}} no compatible"
+ },
+ "BrowserAnimatedVisual": {
+ "46df009982": "Comienza tu prueba gratuita",
+ "25f15c2219": "Pro",
+ "59ae327405": "Motor de arranque",
+ "9e0f530390": "Precios",
+ "0ce7c24b4d": "Laboral…",
+ "f2034c4930": ">",
+ "6e4616d039": "Claude",
+ "0f8481e1a7": "Enviar a Claude",
+ "3d2352f94b": "Describe el cambio...",
+ "d8856b604a": "div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta",
+ "7da6eed7bf": "servidor local: 3000",
+ "0a2bd01c02": "Nueva pestaña del navegador",
+ "04096318ab": "Terminal 1",
+ "eb88125c6f": "✓ Verificado: la prueba gratuita aún funciona.",
+ "051c97d15a": ".pp-card[data-card=\"inicio\"] .pp-cta",
+ "4fa59ca545": "✓ Actualizado",
+ "1bec24acc1": "@keyframes browserFlash { 0% { opacidad: 0; } 20% { opacidad: 0,85; } 100% { opacidad: 0; } } @keyframes browserTabIn { de { opacidad: 0; transformar: traducirY(-2px); } a {opacidad: 1; transformar: ninguno; } } @keyframes browserViewIn { de { opacidad: 0; transformar: traducirY(4px); } a {opacidad: 1; transformar: ninguno; } }",
+ "73bbb46073": "/precios",
+ "f39be6ca14": "/inscribirse"
+ },
+ "BrowserUseSkillSetupCard": {
+ "cbc45022d4": "Permite a los agentes navegar y verificar páginas en el navegador de Orca.",
+ "d5bb1cd4ba": "Habilidad de uso del navegador"
+ },
+ "ComputerUseAnimatedVisual": {
+ "d8401975b1": "aprobado",
+ "f27676a92c": "estado:",
+ "6804cb356f": "haga clic en enviado",
+ "1719b28a81": "encontrado \"Aprobar\"",
+ "79445f7512": "aprobar la nota en mi aplicación",
+ "99a8624bcb": ">",
+ "2adb561b44": "Sesión de Claude Code iniciada",
+ "94787f01f8": "Código Claude",
+ "9cddfe96b2": "aplicación local",
+ "9634d870d1": "Aprobar",
+ "3cc2df3671": "Hecho",
+ "bdd5312213": "Pendiente",
+ "c11dda000b": "Aprobado"
+ },
+ "EditorAnimatedVisual": {
+ "7a763daf2f": "itálico",
+ "8521536429": "atrevido ·",
+ "8341391520": "para bloques ·",
+ "3fe42a1da0": "Tipo",
+ "8268b2376b": "Bloque de código",
+ "37fa4948ce": "Lista de viñetas",
+ "f25687c588": "Cita",
+ "abbdeea15d": "Bloques básicos",
+ "a26a68d30c": "Título 2",
+ "722170663a": "Título 1",
+ "1fb29ad710": "Encabezamientos",
+ "4426aab46f": "Actualice el índice de documentos una vez que aparezca el nuevo mosaico.",
+ "95f0c3a46f": "Pruebe con humo el flujo de instalación en una máquina nueva.",
+ "22ae7b4d9d": "Una breve nota para el equipo: reunir lo que queda antes del envío.",
+ "5a55c00a81": "plan de lanzamiento",
+ "218503f9f3": "guardado automáticamente",
+ "cda56c5915": "notas / plan de lanzamiento.md",
+ "e16479c1c5": "[menú-barra-datos] [fila-barra-datos].barra-activa { fondo: rgba(24,24,27,0.07); sombra de cuadro: inserción 0 0 0 1px rgba(24,24,27,0.06); } [data-md-active-line][data-role=\"activo\"] { color: rgb(113 113 122); familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 12,5 px; } [data-md-active-line][data-role=\"h1\"] { color: heredar; familia de fuentes: heredar; tamaño de fuente: 18px; peso de fuente: 700; espacio entre letras: -0,01 em; altura de línea: 1,2; margen superior: 6px; } [datos-md-caret] { mostrar: bloque en línea; ancho: 1,5 px; altura: 1em; fondo: color actual; alineación vertical: -2px; margen izquierdo: 1px; animación: md-caret-blink 1.05s pasos(1) infinito; } @keyframes md-caret-blink { 0%, 50% { opacidad: 1 } 51%, 100% { opacidad: 0 } } @keyframes md-block-in { de { opacidad: 0; transformar: traducirY(-2px); } a {opacidad: 1; transformar: ninguno; } } @keyframes md-cursor-ripple { 0% { transformar: escala (0.4); opacidad: 0,9; } 100% { transformar: escala(1.4); opacidad: 0; } } [data-clicking=\"1\"] [data-cursor-ripple] { animación: md-cursor-ripple 460ms de avance gradual; }"
+ },
+ "FeatureTourPreview": {
+ "1170621527": ">",
+ "304ad0dfc1": "Pensamiento...",
+ "ef8b164dd1": "revisar src/autenticación",
+ "952d3ddd9a": "sesión iniciada",
+ "771d8881c2": "claude",
+ "6ed43cb0e0": "tablero.spec.ts",
+ "24fedd5a52": "iniciar sesión.spec.ts",
+ "8279e9d95b": "Ejecutando 12 pruebas",
+ "6218a9014d": "prueba de dramaturgo pnpm",
+ "04d54d50ec": "orca · zsh",
+ "1aa8a9a24a": "Terminal divisible",
+ "2a7cfc82c8": "Vinculado a GH #1842",
+ "3822d8d14b": "fix/worktree-picker-trunca",
+ "d54aefe09e": "LIN-329",
+ "40bbd92ef4": "Comenzar",
+ "c1f28c03b2": "El selector de árbol de trabajo se trunca",
+ "fc0cc0b267": "#1842",
+ "0688842445": "GH #1799",
+ "bee6b4088d": "GitHub y tareas Lineares",
+ "5171768676": "orquestando 3 agentes",
+ "cebc7769cd": "rediseñar el flujo de autenticación",
+ "e44269e97d": "Orquestación de agentes",
+ "ec4a73f5e6": "PR 3/3",
+ "cfdfd4d6b4": "PR 2/3",
+ "b1f17bcc74": "PR 1/3",
+ "e38112b289": "refactorizar el webhook de facturación",
+ "9c812e0d7c": "acelerar el proceso de CI",
+ "3c4adfd821": "arreglar la condición de carrera de inicio de sesión",
+ "56a0271428": "Espacios de trabajo aislados",
+ "ef737dcee1": "GitHub y tareas Lineares",
+ "ac51c061e2": "codex"
+ },
+ "FeatureWallBody": {
+ "25ec5356d6": "Configuración"
+ },
+ "FeatureWallModal": {
+ "33dca8bbbe": "Un breve recorrido por Orca, flujo de trabajo por flujo de trabajo.",
+ "3567e147c8": "Conozca Orca"
+ },
+ "FeatureWallPreview": {
+ "a666384798": "También en este flujo de trabajo"
+ },
+ "FeatureWallRail": {
+ "69ea857689": "Terminado",
+ "7593d15f94": "Flujos de trabajo"
+ },
+ "FeatureWallSetupChecklist": {
+ "1a6a7d6c80": "Configuración",
+ "713cc529a5": "Hitos",
+ "b1f1981c5e": "Ver tareas",
+ "505f4c910c": "terminal dividido",
+ "0235b268b2": "Aún no hecho",
+ "13294d3405": "Hecho"
+ },
+ "FeatureWallSetupWorkflowActions": {
+ "486c2f4d8d": "Primero agregue un proyecto git, luego configure el script de configuración para ese repositorio.",
+ "00078a6134": "Ver en configuración",
+ "14327073cc": "Ahorrar",
+ "88469e926b": "Guión de configuración",
+ "5c5b65044e": "instalación pnpm",
+ "a7463915b6": "No se pudo guardar el script de configuración",
+ "6299297dac": "Script de configuración guardado",
+ "f0bbf7da77": "Pruébalo",
+ "364430eb3d": "o haga clic con el botón derecho en un panel y elija una división. Cierre el panel activo con",
+ "29e64f111d": "o abajo con",
+ "971775f639": "Dividir a la derecha con",
+ "522cce9e33": "Agregar proyecto"
+ },
+ "FeatureWallTourPanel": {
+ "af7d622f6f": "Opcional"
+ },
+ "KeepAwakeCard": {
+ "209713d3c7": "Opcional"
+ },
+ "ReviewNotesAnimatedVisual": {
+ "5dbd27c4c2": "Codex",
+ "09094f25e2": "Código Claude",
+ "294aaff104": "enviar notas a",
+ "ea4e45b71b": "Agregar nota",
+ "271ea0cbf3": "Cancelar",
+ "a7a89d8f94": "Línea",
+ "5cb213f967": "notas de IA",
+ "1eee3a397e": "src/server/migrate.ts (diferencia)"
+ },
+ "ReviewPRViewAnimatedVisual": {
+ "7c2808ecff": "truncamiento antes de la fusión.",
+ "c2062da7ec": "stderr",
+ "6f4c2d7cb7": "Agregar un caso de cobertura para",
+ "71828fba75": "¿Podemos incluir el comando defectuoso en la carga útil de diagnóstico?",
+ "fb1a856b6d": "abierto",
+ "7a8b896e11": "Comentarios",
+ "ca36f7b27c": "Aprobado",
+ "25f6838e43": "hilas",
+ "2ef0b97954": "verificación de tipo",
+ "8ed213397c": "Correr",
+ "d340c052fb": "verificar",
+ "9a097cae12": "1 pendiente",
+ "2f37142229": "Aplastar y fusionar",
+ "0aab7ab84a": "Agregar seguimiento de errores de diagnóstico local",
+ "dfe313e0c9": "ABIERTO",
+ "6e3f5223c5": "Explorador",
+ "ab2901bce6": "cheques",
+ "d7f80060ca": "Control de fuente",
+ "8e715588e4": "Buscar"
+ },
+ "ReviewShipAnimatedVisual": {
+ "4d99496b8c": "Crear relaciones públicas",
+ "62544e0852": "Cancelar",
+ "bcd5cae3c4": "Descripción de la solicitud de extracción",
+ "3774b80eae": "Descripción",
+ "07da9245cc": "Título de la solicitud de extracción",
+ "54a093c52d": "Título",
+ "3b9b96d6a6": "principal",
+ "ce7d5d3a18": "sucursal base",
+ "e4473d438f": "Generar con IA",
+ "c30cd930ff": "Crear solicitud de extracción",
+ "ea0100dd15": "Ver todo",
+ "e725000cd7": "Cambios",
+ "a079083a6c": "Comprometerse",
+ "7347fa5839": "Mensaje",
+ "d1a7f15876": "Generar mensaje de confirmación con IA",
+ "cd8a3a39d7": "3 compromisos por delante"
+ },
+ "TasksAnimatedVisual": {
+ "efba6f77eb": "Número de lectura #",
+ "b68c92fbdc": "Iniciar espacio de trabajo",
+ "4331c4d0f8": "Abierto",
+ "b13375617e": "El selector de árbol de trabajo trunca los nombres",
+ "72f9e516a3": "prensado",
+ "fe47c9c9e8": "Espacio de trabajo listo",
+ "61ffda7601": "Creando espacio de trabajo"
+ },
+ "WorkbenchAnimatedVisual": {
+ "633a91e358": "Pensamiento…",
+ "932c4b3a97": ">",
+ "ca2cfbf188": "Terminal dividido hacia abajo",
+ "e370fa8c2b": "Terminal dividido a la derecha",
+ "b85eab49dd": "src/auth/session.ts",
+ "99f5224f1e": "Editar",
+ "0d93c298a7": "lanzar src/auth",
+ "17cfdc3344": "grep",
+ "9923847785": "Leer",
+ "c0eb94125e": "revisar casos extremos de autenticación",
+ "431ca9842a": "Sesión de Claude Code iniciada",
+ "000106adfe": "claude",
+ "7d9f1d5f7d": "(0,8s)",
+ "944199e54a": "› actualizaciones totales del carrito",
+ "623881d72e": "pago.spec.ts",
+ "5c5cbd783f": "(1,2s)",
+ "3261c6853b": "› puede iniciar sesión",
+ "defe550fe2": "iniciar sesión.spec.ts",
+ "0b20782e0f": "Ejecutando 12 pruebas con 4 trabajadores",
+ "4371cc9931": "prueba de dramaturgo pnpm",
+ "16877e038d": "se divide",
+ "a2b114dad0": "se divide a la derecha ·",
+ "0bc9ad0cd1": "Mismo panel:",
+ "fc84f17fe7": "Sesión del Codex iniciada"
+ },
+ "agent": {
+ "capability": {
+ "setup": {
+ "status": {
+ "8eccfcb314": "Instalado",
+ "21d4f79c93": "haga clic en Instalar CLI y habilidades para abrir la configuración de acceso de macOS",
+ "5c9293e51a": "comprobando el acceso a la aplicación",
+ "aae94eeb52": "Haga clic en Instalar CLI y habilidades",
+ "aa8e143a2f": "No se pudo verificar la instalación",
+ "9b33e7fb13": "Comprobando instalación",
+ "4c8e1f92a7": "abre Orca Desktop en esta Mac",
+ "6d2b0a84e1": "No disponible en esta compilación"
+ }
+ }
+ }
+ },
+ "feature": {
+ "wall": {
+ "usage": {
+ "tracking": {
+ "b94ec70eda": "Seguimiento no configurado",
+ "cc39a87288": "Conectado · Sistema predeterminado",
+ "00087eecb2": "Conectado · {{value0}}"
+ }
+ }
+ }
+ },
+ "review": {
+ "animated": {
+ "visual": {
+ "shared": {
+ "e7894927a2": "Codex",
+ "9deecb021c": "Claude"
+ },
+ "notes": {
+ "styles": {
+ "db6691aa0a": ".ravs-window { posición: absoluta; recuadro: 0; --ravs-soft-surface: color-mix(en srgb, var(--primer plano) 2%, var(--card)); --ravs-soft-fill: mezcla de colores (en srgb, var(--primer plano) 6%, transparente); --ravs-panel-border: mezcla de colores (en srgb, var(--primer plano) 18%, var(--border)); --ravs-emphasis-border: color-mix(en srgb, var(--primer plano) 44%, var(--border)); --ravs-sombra-flotante: 0 14px 30px rgb(0 0 0 / 0.22), 0 2px 6px rgb(0 0 0 / 0.12); fondo: var(--tarjeta); borde: 1px var sólido (--borde); radio del borde: 10px; desbordamiento: oculto; pantalla: flexible; dirección flexible: columna; sombra de cuadro: 0 1px 2px rgb(0 0 0 / 0.08); } .ravs-difftoolbar { mostrar: flex; alinear elementos: centro; espacio: 8px; relleno: 6px 10px; borde inferior: var sólido de 1 px (--borde); fondo: var(--ravs-soft-surface); tamaño de fuente: 11px; color: var(--primer plano silenciado); } .ravs-diff-path { ancho mínimo: 0; desbordamiento: oculto; desbordamiento de texto: puntos suspensivos; espacio en blanco: nowrap; familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--primer plano); } .ravs-ai-chip { margen izquierdo: automático; pantalla: flexible en línea; alinear elementos: estirar; desbordamiento: oculto; radio del borde: 6px; borde: 1px var sólido (--borde); fondo: var(--ravs-soft-surface); opacidad: 0; transformar: traducirY(-2px); transición: opacidad 320 ms facilidad, transformación 320 ms facilidad; } .ravs-ai-chip.is-visible { opacidad: 1; transformar: ninguno; } .ravs-ai-chip .ravs-count-btn, .ravs-ai-chip .ravs-send-btn { pantalla: inline-flex; alinear elementos: centro; espacio: 5px; relleno: 3px 8px; tamaño de fuente: 11px; color: var(--primer plano silenciado); fondo: transparente; altura de línea: 1; } .ravs-ai-chip .ravs-count-btn { borde-derecha: 1px solid var(--border); } .ravs-ai-chip .ravs-send-btn { relleno: 3px 7px; posición: relativa; } .ravs-send-glow { posición: absoluta; recuadro: 0; fondo: rgba(34, 197, 94, 0,18); opacidad: 0; transición: opacidad 280 ms facilidad; eventos de puntero: ninguno; } .ravs-ai-chip .ravs-send-btn.is-flash .ravs-send-glow { opacidad: 1; } .ravs-count-num { familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--primer plano); peso de fuente: 600; } .ravs-diffbody { flexionar: 1; altura mínima: 0; posición: relativa; fondo: var(--editor-surface, var(--card)); } .ravs-diffscroll { posición: absoluta; recuadro: 0; desbordamiento: oculto; familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 11,5 px; altura de línea: 1,55; color: var(--primer plano); relleno: 4px 0 8px; transición: opacidad 240 ms facilidad; } .ravs-diffscroll.is-hidden { opacidad: 0; eventos de puntero: ninguno; } .ravs-term { posición: absoluta; recuadro: 0; fondo: var(--editor-surface, var(--card)); color: var(--primer plano); familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 11px; altura de línea: 1,45; desbordamiento: oculto; pantalla: flexible; dirección flexible: columna; opacidad: 0; eventos de puntero: ninguno; transición: opacidad 240 ms facilidad; índice z: 4; } .ravs-term.is-visible { opacidad: 1; } .ravs-term-body { flex: 1; altura mínima: 0; relleno: 10px 12px; desbordamiento: oculto; pantalla: flexible; dirección flexible: columna; espacio: 6px; } .ravs-term-line { espacio en blanco: pre-envoltura; salto de palabra: salto de palabra; altura de línea: 1,45; } .ravs-term-muted { color: var(--silenciado-primer plano); } .ravs-term-glifo { color: rgb(217 119 6); margen derecho: 6px; } .ravs-term-check { color: rgb(16 185 129); peso de fuente: 700; margen derecho: 6px; } .ravs-term-spinner { mostrar: bloque en línea; ancho: 8px; altura: 8px; margen derecho: 6px; radio del borde: 999px; borde: mezcla de colores sólidos de 1,5 px (en srgb, var (--primer plano) 20%, transparente); color-superior-borde: var(--primer plano); alineación vertical: -1px; animación: ravs-term-spin 0,9 s lineal infinito; } @keyframes ravs-term-spin { a { transformar: rotar (360 grados) } } .ravs-hunk-header { display: grid; columnas-plantilla-cuadrícula: 36px 36px 16px minmax(0,1fr); alinear elementos: centro; relleno: 1px 8px 1px 0; fondo: rgba(99, 102, 241, 0,06); color: var(--primer plano silenciado); tamaño de fuente: 10,5 px; borde superior: var sólido de 1 px (--borde); borde inferior: var sólido de 1 px (--borde); } .ravs-hunk-header .ravs-text { columna-cuadrícula: 4 / -1; espacio en blanco: nowrap; desbordamiento: oculto; desbordamiento de texto: puntos suspensivos; color: rgb(99102241); tamaño de fuente: 10,5 px; } .ravs-diff-line { mostrar: cuadrícula; columnas-plantilla-cuadrícula: 36px 36px 16px minmax(0,1fr); alinear elementos: estirar; posición: relativa; } .ravs-ln { text-align: derecha; relleno: 0 6px 0 0; color: var(--primer plano silenciado); tamaño de fuente: 10,5 px; selección de usuario: ninguna; opacidad: 0,85; } .ravs-marker { text-align: centro; color: var(--primer plano silenciado); peso de fuente: 700; opacidad: 0,7; } .ravs-text-cell { padding-right: 8px; espacio en blanco: pre; desbordamiento: oculto; } .ravs-tok-kw { color: #a855f7; } .ravs-tok-id { color: #2563eb; } .ravs-tok-str { color: #16a34a; } .ravs-diff-line.is-add { fondo: color-mix(en srgb, var(--git-decoration-added) 14%, transparente); } .ravs-diff-line.is-add .ravs-marker { color: color-mix(en srgb, var(--git-decoration-added) 72%, transparente); opacidad: 1; } .ravs-diff-line.is-rem { fondo: color-mix(en srgb, var(--git-decoration-deleted) 14%, transparente); } .ravs-diff-line.is-rem .ravs-marker { color: color-mix(en srgb, var(--git-decoration-deleted) 72%, transparente); opacidad: 1; } .ravs-add-note-btn { posición: absoluta; izquierda: 4px; ancho: 18px; altura: 18px; pantalla: flexible en línea; alinear elementos: centro; justificar-contenido: centro; relleno: 0; borde: mezcla de colores sólidos de 1 px (en srgb, color actual 22%, var (--borde)); radio del borde: 4px; fondo: var(--ravs-soft-fill); color: var(--primer plano); índice z: 5; opacidad: 0; sombra de cuadro: 0 1px 2px rgb(0 0 0 / 0.14); eventos de puntero: ninguno; transición: opacidad 160 ms facilidad; } .ravs-add-note-btn.is-visible { opacidad: 1; } .ravs-note-row { relleno: 4px 8px 4px 0; altura máxima: 0; desbordamiento: oculto; opacidad: 0; transición: altura máxima 360 ms cúbico-bezier (.4,0,.2,1), opacidad 280 ms facilidad 60 ms, relleno 360 ms cúbico-bezier (.4,0,.2,1); } .ravs-note-row.is-visible { altura máxima: 90px; opacidad: 1; } .ravs-note-card { margen: 0 12px; posición: relativa; borde: 1px solid var(--ravs-panel-border); borde izquierdo: 3px solid var(--ravs-emphasis-border); radio del borde: 6px; color de fondo: var(--card); relleno: 5px 8px 5px 10px; sombra de cuadro: 0 1px 2px rgb(0 0 0 / 0.16); } .ravs-note-meta { tamaño de fuente: 9.5px; peso de fuente: 600; transformación de texto: mayúsculas; espacio entre letras: 0,04 em; color: var(--primer plano silenciado); } .ravs-note-body { tamaño de fuente: 11,5 px; color: var(--primer plano); altura de línea: 1,35; margen superior: 2px; } .ravs-popover { posición: absoluta; izquierda: 12px; derecha: 12px; ancho máximo: ninguno; índice z: 20; relleno: 8px 10px; borde: 1px solid var(--ravs-panel-border); borde izquierdo: 3px solid var(--ravs-emphasis-border); radio del borde: 6px; color de fondo: var(--card); color: var(--primer plano); sombra-cuadro: var(--ravs-sombra-flotante); pantalla: flexible; dirección flexible: columna; espacio: 6px; opacidad: 0; transformar: traducirY(-4px) escala(0.985); eventos de puntero: ninguno; transición: opacidad 180 ms facilidad, transformación 180 ms facilidad; } .ravs-popover.is-visible { opacidad: 1; transformar: ninguno; eventos de puntero: automático; } .ravs-pop-label { tamaño de fuente: 10px; peso de fuente: 600; transformación de texto: mayúsculas; espacio entre letras: 0,04 em; color: var(--primer plano silenciado); } .ravs-pop-input { altura mínima: 38px; altura máxima: 80 px; relleno: 6px 8px; borde: 1px var sólido (--borde); radio del borde: 4px; fondo: var(--editor-surface, var(--card)); tamaño de fuente: 12px; altura de línea: 1,4; color: var(--primer plano); espacio en blanco: preenvoltura; salto de palabra: salto de palabra; desbordamiento: oculto; } .ravs-pop-footer { pantalla: flex; justificar contenido: extremo flexible; espacio: 6px; } .ravs-pop-btn { tamaño de fuente: 11px; peso de fuente: 500; relleno: 4px 9px; radio del borde: 5px; altura de línea: 1; borde: 1px sólido transparente; pantalla: flexible en línea; alinear elementos: centro; espacio: 5px; } .ravs-pop-btn.is-cancel { color: var(--silenciado-primer plano); fondo: transparente; } .ravs-pop-btn.is-add { color: var(--primer-primer plano); fondo: var(--primario); } .ravs-send-menu { posición: absoluta; índice z: 30; derecha: 8px; arriba: 6px; ancho mínimo: 200px; fondo: var(--popover); color: var(--popover-primer plano); borde: 1px var sólido (--borde); radio del borde: 8px; relleno: 4px; sombra-cuadro: var(--ravs-sombra-flotante); opacidad: 0; transformar: traducirY(-4px) escala(0.985); eventos de puntero: ninguno; transición: opacidad 180 ms facilidad, transformación 180 ms facilidad; } .ravs-send-menu.is-visible { opacidad: 1; transformar: ninguno; eventos de puntero: automático; } .ravs-menu-section { relleno: 4px 8px 2px; tamaño de fuente: 9,5 px; peso de fuente: 700; transformación de texto: mayúsculas; espacio entre letras: 0,06 em; color: var(--primer plano silenciado); } .ravs-menu-row { mostrar: cuadrícula; columnas-plantilla-cuadrícula: 16px minmax(0,1fr); alinear elementos: centro; espacio: 8px; relleno: 6px 8px; radio del borde: 5px; tamaño de fuente: 12px; color: var(--popover-primer plano); } .ravs-menu-row.is-hot { fondo: var(--accent); sombra de cuadro: inserción 0 0 0 1px var (--borde); } .ravs-cursor { posición: absoluta; índice z: 40; eventos de puntero: ninguno; transición: transformar 600 ms cúbico-bezier (.45, .05, .2,1), opacidad 200 ms facilidad; transformar: traducir (-30px, 220px); opacidad: 0; } .ravs-cursor.is-visible { opacidad: 1; } .ravs-cursor .ravs-ripple { posición: absoluta; izquierda: -6px; arriba: -6px; ancho: 28px; altura: 28 píxeles; radio del borde: 999px; borde: mezcla de colores sólidos de 2px (en srgb, var(--primer plano) 52%, transparente); opacidad: 0; } .ravs-cursor.is-clicking .ravs-ripple { animación: ravs-ripple 460 ms hacia adelante; } @keyframes ravs-ripple { 0% { transformar: escala(0.4); opacidad: 0,9; } 100% { transformar: escala(1.4); opacidad: 0; } } .ravs-caret { mostrar: bloque en línea; ancho: 1,5 px; altura: 1em; fondo: color actual; alineación vertical: -2px; margen izquierdo: 1px; animación: ravs-caret-blink 1,05s pasos(1) infinito; } @keyframes ravs-caret-blink { 0%, 50% { opacidad: 1 } 51%, 100% { opacidad: 0 } }"
+ }
+ },
+ "pr": {
+ "view": {
+ "styles": {
+ "fc9a23c83d": ".ravpr-stage { posición: absoluta; recuadro: 0; desbordamiento: oculto; } .ravpr-stack { posición: absoluta; recuadro: 0; pantalla: flexible; justificar contenido: extremo flexible; relleno: 4px 34px 4px 2px; desbordamiento: oculto; } .ravpr-sidebar, .ravpr-card { posición: absoluta; arriba: 4px; derecha: 2px; ancho: 464px; altura: calc(100% - 8px); fondo: var(--card, #fff); borde: 1px var sólido (--borde); radio del borde: 10px; color: var(--primer plano, #18181b); desbordamiento: oculto; sombra de cuadro: 0 1px 2px rgba(24,24,27,0.04); } .ravpr-sidebar { opacidad: 0; transición: opacidad 220 ms facilidad; } .ravpr-sidebar.is-visible { opacidad: 1; } .ravpr-sidebar.is-hiding { opacidad: 0; } .ravpr-card { pantalla: flex; dirección flexible: columna; ancho mínimo: 0; opacidad: 0; transición: opacidad 260 ms facilidad; } .ravpr-card.is-visible { opacidad: 1; } .ravpr-tabs { posición: relativa; pantalla: flexible; alinear elementos: centro; espacio: 14px; altura: 36px; relleno: 0 14px; fondo: rgba(24,24,27,0.015); color: var(--primer plano silenciado, #71717a); } .ravpr-tab { posición: relativa; ancho: 18px; altura: 18px; pantalla: flexible en línea; alinear elementos: centro; justificar-contenido: centro; color: var(--primer plano silenciado, #71717a); } .ravpr-tab.is-active, .ravpr-tab.is-hovered { color: var(--primer plano, #18181b); } .ravpr-tab.is-active::después { contenido: ''; posición: absoluta; izquierda: -5px; derecha: -5px; abajo: -10px; altura: 1px; fondo: var(--primer plano, #18181b); } .ravpr-tooltip { posición: absoluta; arriba: 34px; izquierda: 106px; índice z: 6; relleno: 7px 11px; radio del borde: 8px; fondo: var(--card, #fff); color: var(--primer plano, #18181b); tamaño de fuente: 12px; altura de línea: 1; sombra de cuadro: 0 8px 22px rgba(0,0,0,0.22); opacidad: 0; transformar: traducirY(-3px); eventos de puntero: ninguno; transición: opacidad 160 ms facilidad, transformación 160 ms facilidad; } .ravpr-tooltip.is-visible { opacidad: 1; transformar: traducirY(0); } .ravpr-explorer { relleno: 10px 12px 12px; } .ravpr-heading { color: var(--primer plano silenciado, #71717a); tamaño de fuente: 10px; peso de fuente: 600; espacio entre letras: 0,05 em; transformación de texto: mayúsculas; } .ravpr-file-list { margen superior: 8px; pantalla: flexible; dirección flexible: columna; espacio: 2px; } .ravpr-file { pantalla: cuadrícula; columnas-plantilla-cuadrícula: 14px minmax(0,1fr) 22px; alinear elementos: centro; espacio: 8px; altura mínima: 28px; relleno: 4px 6px; radio del borde: 6px; } .ravpr-file.is-active { fondo: rgba(24,24,27,0.06); sombra de cuadro: inserción 0 0 0 1px rgba(24,24,27,0.06); } .ravpr-file-icon { ancho: 12px; altura: 12px; radio del borde: 3px; fondo: rgba(24,24,27,0.14); } .ravpr-nombre-archivo { altura: 8px; radio del borde: 999px; fondo: rgba(24,24,27,0.14); } .ravpr-file-status { ancho: 14px; altura: 8px; radio del borde: 999px; fondo: rgba(24,24,27,0.12); } .ravpr-body { relleno: 10px 12px 18px; pantalla: flexible; dirección flexible: columna; espacio: 5px; altura mínima: 0; } .ravpr-número-fila { mostrar: flex; alinear elementos: centro; espacio: 7px; } .ravpr-number { familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 12px; peso de fuente: 700; } .ravpr-open { pantalla: inline-flex; alinear elementos: centro; justificar-contenido: centro; altura: 18px; relleno: 0 7px; radio del borde: 5px; fondo: rgba(16.185.129,0,10); borde: 1px rgba sólido (16,185,129,0.28); color: rgb(4 120 87); tamaño de fuente: 9px; peso de fuente: 700; altura de línea: 1; } .ravpr-title { tamaño de fuente: 12px; peso de fuente: 600; altura de línea: 1,35; color: var(--primer plano, #18181b); margen inferior: 2px; } .ravpr-merge { mostrar: inline-flex; alinear elementos: centro; justificar-contenido: centro; espacio: 6px; altura: 30 píxeles; altura mínima: 30px; flexionar: 0 0 30px; radio del borde: 7px; fondo: rgb(22 163 74); color: #fff; tamaño de fuente: 11,5 px; peso de fuente: 700; margen inferior: 2px; sombra de cuadro: 0 1px 2px rgba(22,163,74,0.18); transición: caja-sombra 220 ms de facilidad, filtro 220 ms de facilidad; } .ravpr-merge.is-ready { box-shadow: 0 0 0 3px rgba(34,197,94,0.22), 0 1px 2px rgba(22,163,74,0.18); } .ravpr-section-row, .ravpr-check-row { mostrar: cuadrícula; columnas-plantilla-cuadrícula: 18px minmax(0,1fr) auto; alinear elementos: centro; espacio: 7px; relleno: 5px 0; tamaño de fuente: 11,5 px; color: var(--primer plano, #18181b); } .ravpr-check-row { relleno: 5px 7px; tamaño de fuente: 10,5 px; } .ravpr-label { espacio en blanco: nowrap; desbordamiento: oculto; desbordamiento de texto: puntos suspensivos; } .ravpr-meta, .ravpr-check-state { color: var(--primer plano silenciado, #71717a); tamaño de fuente: 10,5 px; } .ravpr-check-state { tamaño de fuente: 10px; } .ravpr-ring { mostrar: bloque en línea; ancho: 14px; altura: 14px; radio del borde: 999px; borde: 2px rgba sólido (245,158,11,0.35); color del borde superior: rgb(245 158 11); animación: ravpr-spin 1.1s lineal infinito; } .ravpr-check { ancho: 15px; altura: 15 píxeles; radio del borde: 999px; pantalla: ninguna; alinear elementos: centro; justificar-contenido: centro; fondo: rgba(34,197,94,0.14); color: rgb(22 163 74); } .ravpr-section-row.is-done .ravpr-ring, .ravpr-check-row.is-done .ravpr-ring { pantalla: ninguna; } .ravpr-section-row.is-done .ravpr-check, .ravpr-check-row.is-done .ravpr-check { display: inline-flex; } .ravpr-reveal { mostrar: flex; dirección flexible: columna; espacio: 3px; opacidad: 0; transformar: traducirY(4px); transición: opacidad 260 ms facilidad, transformación 260 ms facilidad; eventos de puntero: ninguno; } .ravpr-reveal.is-visible { opacidad: 1; transformar: traducirY(0); eventos de puntero: automático; } .ravpr-check-list, .ravpr-comment-list { mostrar: flex; dirección flexible: columna; espacio: 4px; altura mínima: 0; } .ravpr-comment-card { borde: var sólida de 1px (--borde); radio del borde: 8px; fondo: var(--card, #fff); desbordamiento: oculto; opacidad: 0; transformar: traducirY(4px); transición: opacidad 260 ms facilidad, transformación 260 ms facilidad; } .ravpr-comment-card.is-visible { opacidad: 1; transformar: traducirY(0); } .ravpr-comment-head { mostrar: cuadrícula; columnas-plantilla-cuadrícula: 18px minmax(0,1fr) auto; alinear elementos: centro; espacio: 7px; relleno: 5px 7px; fondo: rgba(24,24,27,0.015); } .ravpr-avatar { ancho: 16px; altura: 16px; radio del borde: 999px; fondo: rgba(24,24,27,0.16); } .ravpr-autor { ancho: 78px; altura: 8px; radio del borde: 999px; fondo: rgba(24,24,27,0.18); } .ravpr-comment-path { familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 9,5 px; color: var(--primer plano silenciado, #71717a); } .ravpr-comment-body { relleno: 5px 7px 6px; tamaño de fuente: 11px; altura de línea: 1,32; color: var(--primer plano, #18181b); } .ravpr-comment-body code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 10,5 px; relleno: 1px 4px; radio del borde: 4px; fondo: rgba(24,24,27,0.06); } .ravpr-cursor { posición: absoluta; índice z: 40; eventos de puntero: ninguno; transición: transformar 600 ms cúbico-bezier (.45, .05, .2,1), opacidad 200 ms facilidad; transformar: traducir (-30px, 220px); opacidad: 0; } .ravpr-cursor.is-visible { opacidad: 1; } .ravpr-ripple { posición: absoluta; izquierda: -6px; arriba: -6px; ancho: 28px; altura: 28 píxeles; radio del borde: 999px; borde: 2px rgba sólido (24,24,27,0.5); opacidad: 0; } .ravpr-cursor.is-clicking .ravpr-ripple { animación: ravpr-ripple 460 ms hacia adelante; } @keyframes ravpr-ripple { 0% { transformar: escala (0.4); opacidad: 0,9; } 100% { transformar: escala(1.4); opacidad: 0; } } @keyframes ravpr-spin { a { transformar: rotar (360 grados); } }"
+ }
+ }
+ },
+ "ship": {
+ "styles": {
+ "90cdcd2ecc": ".ravs-ship-root { posición: absoluta; recuadro: 0; } .ravs-ship-stack { posición: absoluta; recuadro: 0; pantalla: cuadrícula; columnas-plantilla-cuadrícula: 232px minmax(0,1fr); espacio: 14px; relleno: 4px 2px; /* Por qué: las tarjetas se ajustan al tamaño de su contenido en lugar de extenderse hasta la altura total del padre, para que las dos tarjetas no muestren espacios vacíos debajo de su contenido. */ alinear-elementos: inicio; } /* Minibarra lateral de control de código fuente: encabezado de recuento anticipado, área de texto de confirmación + botón de confirmación dividido, luego una sección de CAMBIOS con filas de archivos. Las filas del archivo son la superficie sobre la que se anima el pulso de \"lectura\". */ .ravs-sc-card { pantalla: flex; dirección flexible: columna; fondo: var(--card, #fff); borde: 1px var sólido (--borde); radio del borde: 10px; desbordamiento: oculto; sombra de cuadro: 0 1px 2px rgba(24,24,27,0.04); } /* Ambos encabezados de tarjetas comparten la misma altura fija, por lo que la tarjeta SC y el cuadro de diálogo PR se alinean en el borde superior independientemente del contenido del encabezado. */ .ravs-sc-header, .ravs-pr-head { altura: 36px; tamaño de caja: cuadro de borde; } .ravs-sc-header { pantalla: flex; alinear elementos: centro; justificar contenido: espacio entre; relleno: 0 10px; borde inferior: var sólido de 1 px (--borde); } .ravs-sc-ahead { mostrar: inline-flex; alinear elementos: centro; espacio: 5px; tamaño de fuente: 11px; peso de fuente: 500; color: var(--primer plano, #18181b); } .ravs-sc-ahead svg { color: var(--silenciado-primer plano, #71717a); } .ravs-sc-commit-area { pantalla: flex; dirección flexible: columna; espacio: 6px; relleno: 8px 10px; } .ravs-sc-textarea { posición: relativa; borde: 1px var sólido (--borde); radio del borde: 6px; fondo: var(--editor-surface, var(--card)); relleno: 6px 26px 6px 8px; altura mínima: 56px; tamaño de fuente: 12px; altura de línea: 1,45; color: var(--primer plano, #18181b); espacio en blanco: preenvoltura; salto de palabra: salto de palabra; desbordamiento: oculto; } .ravs-sc-textarea .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-sc-sparkle { posición: absoluta; derecha: 6px; arriba: 6px; ancho: 20px; altura: 20 píxeles; pantalla: flexible en línea; alinear elementos: centro; justificar-contenido: centro; radio del borde: 4px; color: var(--primer plano silenciado, #71717a); fondo: transparente; transición: color con 160 ms de facilidad, fondo con 160 ms de facilidad; } .ravs-sc-sparkle.is-scanning { color: rgb(109 40 217); fondo: mezcla de colores (en srgb, rgb(139 92 246) 18%, transparente); } .ravs-sc-split { pantalla: flex; alinear elementos: estirar; } /* Por qué: Comprometerse y crear relaciones públicas rodean a Chrome; las posibilidades violetas de la IA son los puntos focales. Representelos como botones secundarios silenciosos para que no compitan con las señales de brillo/escaneo. */ .ravs-sc-split .ravs-primary { flex: 1; pantalla: flexible en línea; alinear elementos: centro; justificar-contenido: centro; espacio: 5px; relleno: 5px 10px; fondo: var(--secundario, #f5f5f5); color: var(--primer plano secundario, #171717); tamaño de fuente: 11px; peso de fuente: 500; radio de borde: 6px 0 0 6px; borde: 1px var sólido (--borde); transición: fondo con 240 ms de facilidad, color de borde con 240 ms de facilidad, color con 240 ms de facilidad; } .ravs-sc-split .ravs-chev { pantalla: inline-flex; alinear elementos: centro; justificar-contenido: centro; ancho: 22px; fondo: var(--secundario, #f5f5f5); color: var(--primer plano silenciado, #71717a); radio de borde: 0 6px 6px 0; borde: 1px var sólido (--borde); borde izquierdo: var sólido de 1 px (--borde); transición: fondo con 240 ms de facilidad, color de borde con 240 ms de facilidad, color con 240 ms de facilidad; } /* Por qué: cuando la IA haya completado el mensaje de confirmación, tiñe el botón Confirmar de verde para indicar \"listo para confirmar\". Utiliza la misma familia de éxito verde que el flash PR para que los dos tiempos rimen. La mezcla es intencionalmente fuerte (~28%): al 14% desapareció junto al brillo violeta y el flash PR, por lo que los usuarios solo vieron el PR cambiar de color. */ .ravs-sc-split.is-ready .ravs-primary, .ravs-sc-split.is-ready .ravs-chev { fondo: mezcla de colores (en srgb, rgb(34 197 94) 28%, var(--secundario, #f5f5f5)); color del borde: rgb(34 197 94); color: rgb(21 128 61); transición: fondo con 220 ms de facilidad, color de borde con 220 ms de facilidad, color con 220 ms de facilidad; } .ravs-sc-split.is-ready .ravs-chev { borde-izquierdo-color: rgba(34, 197, 94, 0,55); } .ravs-sc-changes-header { pantalla: flex; alinear elementos: centro; justificar contenido: espacio entre; relleno: 8px 10px 4px; tamaño de fuente: 10px; peso de fuente: 600; transformación de texto: mayúsculas; espacio entre letras: 0,05 em; color: var(--primer plano silenciado, #71717a); } .ravs-sc-changes-count { color: var(--primer plano, #18181b); peso de fuente: 600; margen izquierdo: 2px; } .ravs-sc-view-all { tamaño de fuente: 10px; peso de fuente: 500; transformación de texto: ninguna; espacio entre letras: 0; color: var(--primer plano silenciado, #71717a); } .ravs-sc-files { mostrar: flex; dirección flexible: columna; relleno: 2px 6px 8px; flexión: 1; altura mínima: 0; desbordamiento: oculto; } .ravs-sc-file { mostrar: cuadrícula; columnas-plantilla-cuadrícula: 14px minmax(0,1fr) 12px; alinear elementos: centro; espacio: 6px; relleno: 3px 6px; radio del borde: 4px; tamaño de fuente: 11px; altura de línea: 1,35; color: var(--primer plano, #18181b); posición: relativa; transición: facilidad de fondo 220 ms; } .ravs-sc-ficon { color: rgb(180 83 9); pantalla: flexible en línea; } .ravs-sc-fname { ancho mínimo: 0; desbordamiento: oculto; desbordamiento de texto: puntos suspensivos; espacio en blanco: nowrap; } .ravs-sc-fmark { familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; tamaño de fuente: 10px; alineación de texto: derecha; color: rgb(180 83 9); } .ravs-sc-file.is-reading { fondo: color-mix(en srgb, rgb(139 92 246) 14%, transparente); sombra de cuadro: inserción 0 0 0 1px mezcla de colores (en srgb, rgb (139 92 246) 28%, transparente); } /* Cuadro de diálogo PR: coincide con el cromo de la tarjeta .ravs-sc (mismo borde, radio, elevación) para que las dos tarjetas se lean como un solo lenguaje de diseño. */ .ravs-pr-dialog { fondo: var(--card, #fff); borde: 1px var sólido (--borde); radio del borde: 10px; sombra de cuadro: 0 1px 2px rgba(24,24,27,0.04); pantalla: flexible; dirección flexible: columna; ancho mínimo: 0; desbordamiento: oculto; } .ravs-pr-head { pantalla: flex; alinear elementos: centro; justificar contenido: espacio entre; espacio: 6px; relleno: 0 10px; borde inferior: var sólido de 1 px (--borde); } .ravs-pr-title-text { tamaño de fuente: 11px; peso de fuente: 500; color: var(--primer plano, #18181b); } /* Chip de asistencia de IA de solo íconos: refleja .ravs-sc-sparkle para que la capacidad se lea de manera idéntica en ambas tarjetas. */ .ravs-pr-gen-btn { pantalla: inline-flex; alinear elementos: centro; justificar-contenido: centro; ancho: 22px; altura: 22 píxeles; relleno: 0; radio del borde: 4px; color: var(--primer plano silenciado, #71717a); fondo: transparente; borde: 0; cursor: puntero; transición: color con 160 ms de facilidad, fondo con 160 ms de facilidad; } .ravs-pr-gen-btn:hover { fondo: rgba(24,24,27,0.06); color: var(--primer plano, #18181b); } .ravs-pr-gen-btn.is-scanning { color: rgb(109 40 217); fondo: mezcla de colores (en srgb, rgb(139 92 246) 18%, transparente); } .ravs-pr-body { pantalla: flex; dirección flexible: columna; espacio: 8px; relleno: 10px; } .ravs-pr-field { pantalla: flex; dirección flexible: columna; espacio: 4px; } .ravs-pr-field-label { tamaño de fuente: 10px; peso de fuente: 600; transformación de texto: mayúsculas; espacio entre letras: 0,05 em; color: var(--primer plano silenciado, #71717a); } .ravs-pr-base { mostrar: inline-flex; alinear elementos: centro; espacio: 5px; relleno: 4px 9px; borde: 1px var sólido (--borde); radio del borde: 6px; tamaño de fuente: 11px; familia de fuentes: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--primer plano, #18181b); fondo: var(--editor-surface, var(--card)); alineación propia: inicio flexible; } .ravs-pr-base svg { color: var(--primer plano silenciado, #71717a); } .ravs-pr-input { posición: relativa; relleno: 6px 8px; borde: 1px var sólido (--borde); radio del borde: 6px; fondo: var(--editor-surface, var(--card)); altura mínima: 28px; tamaño de fuente: 12px; altura de línea: 1,45; color: var(--primer plano, #18181b); espacio en blanco: preenvoltura; salto de palabra: salto de palabra; desbordamiento: oculto; } .ravs-pr-input.is-body { altura mínima: 50px; tamaño de fuente: 11px; altura de línea: 1,4; } .ravs-pr-input .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-pr-footer { pantalla: flex; alinear elementos: centro; espacio: 6px; justificar contenido: extremo flexible; margen superior: 2px; } .ravs-pr-btn { tamaño de fuente: 11px; peso de fuente: 500; relleno: 5px 10px; radio del borde: 6px; altura de línea: 1; borde: 1px sólido transparente; esquema: ninguno; } .ravs-pr-btn:focus, .ravs-pr-btn:focus-visible { esquema: ninguno; } /* Cancelar se lee como un botón fantasma silencioso para que no compita con la acción afirmativa Crear PR. */ .ravs-pr-btn.is-outline { fondo: transparente; color: var(--primer plano silenciado, #71717a); color del borde: transparente; } .ravs-pr-btn.is-outline:hover { fondo: rgba(24,24,27,0.05); color: var(--primer plano, #18181b); } /* Relleno secundario silencioso: consulte la nota .ravs-sc-split anterior. El anillo de destello todavía usa el color verde exitoso para que se lea el ritmo \"PR creado\". El botón Crear-PR es ligeramente más grande que Cancelar, por lo que la acción afirmativa sigue siendo el objetivo más importante. */ .ravs-pr-btn.is-solid { fondo: var(--secundario, #f5f5f5); color: var(--primer plano secundario, #171717); color del borde: var(--borde); tamaño de fuente: 12px; relleno: 7px 14px; transición: fondo con 220 ms de facilidad, color de borde con 220 ms de facilidad, color con 220 ms de facilidad, cuadro de sombra con 220 ms de facilidad; } .ravs-pr-btn.is-solid.is-ready { fondo: color-mix(en srgb, rgb(34 197 94) 28%, var(--secundario, #f5f5f5)); color del borde: rgb(34 197 94); color: rgb(21 128 61); } .ravs-pr-btn.is-solid.is-flash { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.30); } .ravs-cursor { posición: absoluta; índice z: 40; eventos de puntero: ninguno; transición: transformar 600 ms cúbico-bezier (.45, .05, .2,1), opacidad 200 ms facilidad; transformar: traducir (-30px, 220px); opacidad: 0; } .ravs-cursor.is-visible { opacidad: 1; } .ravs-cursor .ravs-ripple { posición: absoluta; izquierda: -6px; arriba: -6px; ancho: 28px; altura: 28 píxeles; radio del borde: 999px; borde: 2px rgba sólido (24,24,27,0.5); opacidad: 0; } .ravs-cursor.is-clicking .ravs-ripple { animación: ravs-ripple 460 ms hacia adelante; } @keyframes ravs-ripple { 0% { transformar: escala(0.4); opacidad: 0,9; } 100% { transformar: escala(1.4); opacidad: 0; } } .ravs-caret { mostrar: bloque en línea; ancho: 1,5 px; altura: 1em; fondo: color actual; alineación vertical: -2px; margen izquierdo: 1px; animación: ravs-caret-blink 1,05s pasos(1) infinito; } @keyframes ravs-caret-blink { 0%, 50% { opacidad: 1 } 51%, 100% { opacidad: 0 } }"
+ }
+ }
+ }
+ },
+ "notes": {
+ "diff": {
+ "rows": {
+ "f621c734f8": "Nota · línea"
+ }
+ }
+ }
+ },
+ "agents": {
+ "orchestration": {
+ "OrchestrationPage": {
+ "30b509a467": "2 niños",
+ "862605d066": "2 espacios de trabajo infantiles"
+ },
+ "StatusesPage": {
+ "2f549fc0ba": "src/auth/session.test.ts",
+ "139e3d7458": "Actualizado",
+ "7b26349cb2": "pnpm migrar más reciente",
+ "78f0318ac1": "quiere correr",
+ "79971d1539": "rediseñar el flujo de autenticación"
+ },
+ "UsageAccountsCard": {
+ "6986b36708": "Límites de tasas superficiales y cuentas swap en línea.",
+ "d90d2e1f6d": "Seguimiento de la sesión y el uso semanal.",
+ "8919321417": "Error al iniciar sesión en el Codex.",
+ "c7b90c140b": "Se agregó la cuenta del Codex.",
+ "4e71d72912": "Error al iniciar sesión en Claude.",
+ "9ddeb558f9": "Se agregó la cuenta de Claude.",
+ "29d0653961": "Iniciar sesión",
+ "945865332e": "Iniciar sesión"
+ },
+ "UsagePage": {
+ "64265cb295": "71% 5h",
+ "be5a165875": "Cambiar a",
+ "277a9c65a9": "Cuenta del Codex",
+ "4dce5ca3aa": "Se reinicia en 4d 3h",
+ "05ce4ecdd3": "62% restante",
+ "0470aaed99": "Semanalmente",
+ "f421abf962": "Sesión",
+ "5e45fb1238": "Actualizado hace 1m",
+ "6a4b1d3c38": "Codex"
+ },
+ "orchestration": {
+ "cards": {
+ "da6f1f97c9": "laboral"
+ }
+ }
+ }
+ },
+ "FeatureTourWorkspaceCard": {
+ "a23ed9da7f": "codex",
+ "2f33dc932b": "claude",
+ "9220794f6a": "laboral"
+ },
+ "ReviewAnimatedVisual": {
+ "8df4d52b68": "pr-vista",
+ "8ab622e4d6": "notas"
+ },
+ "FeatureWallBrowserAction": {
+ "5022c43a88": "El navegador no pudo abrir",
+ "c9eb68b474": "Aún no hay ningún grupo de espacio de trabajo disponible para este árbol de trabajo.",
+ "c9728107c5": "Pruébalo",
+ "25dd101f15": "La configuración del navegador necesita atención",
+ "e02b11e6b0": "Configuración del navegador lista",
+ "d6d15077df": "Comando de habilidad copiado e insertado a continuación para su revisión.",
+ "78e65f19d9": "La configuración del navegador falló",
+ "b7345c18db": "Se produjo un error inesperado.",
+ "5f97caf76b": "Instalando…",
+ "c2df599513": "Instalar CLI y habilidad"
+ }
+ },
+ "tips": {
+ "CliFeatureTipVisual": {
+ "badb4fc342": ">",
+ "22e62f3bab": "Sesión de Claude Code iniciada"
+ },
+ "CliSkillSetupTerminal": {
+ "1953e90447": "Presione Entrar para instalar la habilidad de orquestación CLI de Orca para sus agentes.",
+ "43b60ec5c3": "Terminal de instalación de habilidades de orquestación y CLI de Orca",
+ "84e9576dac": "Configuración de habilidades",
+ "5c3aee22c0": "comando copiar",
+ "5eca672aac": "Copiar comando de instalación de habilidad",
+ "6ff813fc1d": "No se pudo copiar el comando de habilidad.",
+ "b8ad063571": "Copié el comando de instalación de habilidades."
+ },
+ "CmdJPaletteTipDialog": {
+ "c0bb9f869b": "Configuración → Atajos",
+ "8241897205": "Vuelva a vincular el acceso directo en cualquier momento en"
+ },
+ "FeatureTipActions": {
+ "eb04abece8": "Quizás más tarde"
+ },
+ "FeatureTipsModal": {
+ "c169298e4d": "Hecho",
+ "3c6c478462": "X termina, envíale la tarea de revisión”.",
+ "298301b7a0": "árbol de trabajo",
+ "864e2db28f": "“Cuando el agente en",
+ "7fc6f02099": "y crear relaciones públicas para cada uno”.",
+ "27c567a89c": "árboles de trabajo",
+ "55846c7f95": "“Divide este PR en dos",
+ "4795ac2d4a": "Intenta preguntar:",
+ "53905bd076": "Vista previa del desarrollo: apertura del terminal de configuración de habilidades.",
+ "1da82af45b": "Orca CLI necesita atención",
+ "ce13a742d0": "Orca registrada en PATH.",
+ "d1a86c7eb5": "Abra Configuración para finalizar la configuración de CLI."
+ },
+ "CmdJPaletteFeatureTipVisual": {
+ "ab94e16d44": "Crear árbol de trabajo \"{{value0}}\"",
+ "d20ccf1e61": "hecho",
+ "379d776971": "mecanografía",
+ "0418f9becc": "abierto"
+ }
+ }
+ },
+ "error": {
+ "boundaries": {
+ "RecoverableRenderErrorBoundary": {
+ "55001880db": "Rever",
+ "34a189ae0f": "El resto de la aplicación sigue ejecutándose. Vuelva a intentar esta superficie o cambie y regrese.",
+ "ab855c11f4": "Esta parte de Orca tuvo un error."
+ }
+ }
+ },
+ "emulator": {
+ "pane": {
+ "EmulatorPane": {
+ "59b08fa031": "Ningún emulador conectado"
+ },
+ "emulator": {
+ "device": {
+ "frame": {
+ "9406c15775": "Pantalla del emulador",
+ "8f25ffaf8a": "Pantalla del emulador, teclado capturado. Presione Escape para liberar.",
+ "0022420df0": "teléfono"
+ }
+ },
+ "pane": {
+ "toolbar": {
+ "06e10d7356": "Apagar el emulador",
+ "e7a0d1897e": "Hogar",
+ "6bd8dff42a": "Girar",
+ "3d836b879c": "Elige emulador",
+ "81b3571a07": "Conectar",
+ "868c0f2938": "Laboral…"
+ }
+ },
+ "screen": {
+ "stream": {
+ "content": {
+ "8b1a0d8694": "Vista previa del emulador",
+ "36841af608": "Transmisión desconectada",
+ "5f818f12ab": "Conectando el emulador…",
+ "5ee64cd44e": "Pantalla del emulador"
+ }
+ }
+ },
+ "unavailable": {
+ "pane": {
+ "f630b9ca9f": "Mobile Emulator requiere una Mac con Xcode y el tiempo de ejecución del simulador de iOS. En Linux o Windows, utilice un dispositivo físico o un host de compilación Mac remoto.",
+ "b2c268a0b9": "Mobile Emulator es solo macOS"
+ }
+ }
+ },
+ "use": {
+ "emulator": {
+ "frame": {
+ "stream": {
+ "f1c0179002": "La transmisión no produce fotogramas."
+ }
+ }
+ }
+ }
+ }
+ },
+ "editor": {
+ "ChangesModeView": {
+ "ef25ae2d09": "No hay cambios no confirmados.",
+ "052c184f24": "La diferenciación de texto no está disponible para este archivo.",
+ "7dffb0f563": "archivo binario",
+ "54e0035b15": "Cargando diferencias..."
+ },
+ "CodeBlockCopyButton": {
+ "28921f5bf9": "copiado",
+ "1f9f4def45": "Copiar código"
+ },
+ "CombinedDiffFileTree": {
+ "f984289373": "Ningún archivo coincide con los filtros actuales.",
+ "eafe1aeb53": "Restablecer filtros",
+ "be119cb9d1": "Archivos vistos",
+ "c00020f081": "Extensiones de archivo",
+ "cd0e0ed79e": "Filtrar archivos de diferencias",
+ "4cc7b83ffe": "Filtrar archivos...",
+ "21783df79f": "Contraer árbol de archivos",
+ "481e63ca52": "Archivos",
+ "d5ac717d65": "no comprometido"
+ },
+ "CombinedDiffViewer": {
+ "35cc27aeb2": "en control de fuente",
+ "e3b9a6ce02": "más",
+ "1da745c551": "Enviado",
+ "84898c548d": "Claro",
+ "88b70d0ef5": "Copiar",
+ "bb84b4c374": "notas de IA",
+ "948a5fd6c8": "Borrar notas",
+ "0f806a2ab1": "Cancelar",
+ "80a286d8f5": "de este árbol de trabajo?",
+ "7e7ca60816": "archivos cambiados",
+ "b6c3b84476": "Mostrar árbol de archivos",
+ "39f8007549": "Revisar conflictos",
+ "39e73e7181": "fueron excluidos de esta vista diferente.",
+ "689b99f8ad": "conflicto no resuelto",
+ "820ec01f24": "Los archivos en conflicto se revisan por separado",
+ "fd8892b120": "No hay cambios para mostrar",
+ "eb5f40e49c": "Esta vista de diferencias excluye los conflictos no resueltos porque la canalización de diferencias bidireccional normal no es segura para conflictos.",
+ "45cf23b418": "No se pudieron borrar las notas.",
+ "0fb870a0fe": "notas",
+ "8ab3248fd8": "nota",
+ "ec5053c7f5": "Juntos",
+ "f786fd54e1": "En línea",
+ "ea08dae15b": "Contraer todo",
+ "19c45cfdc0": "Expandir todo",
+ "982d14bfa5": "Abrir diferencia no confirmada",
+ "3d909843bb": "Diferencia de rama abierta",
+ "8368d256ec": "rama combinada",
+ "8f68ad9ca9": "Mostrar {{value0}} AI {{value1}}",
+ "724a13568d": "en {{value0}}",
+ "6094135eec": "frente a {{value0}}"
+ },
+ "ConflictComponents": {
+ "f338288514": "Cargando contenidos conflictivos...",
+ "90d576adb2": "Refrescar",
+ "a1ce36f77d": "Instantánea capturada en",
+ "4be41eaafc": "conflicto no resuelto",
+ "c8ca989aea": "Mostrar árbol de archivos",
+ "58ad5ad431": "Despedir",
+ "28e7db4a90": "Control de fuente",
+ "31931dec46": "Esta instantánea de revisión ya no tiene conflictos activos sin resolver.",
+ "992145ff5a": "Todos los conflictos resueltos",
+ "d5edd81755": "Renombrado de",
+ "6e459867ad": "Estado de continuidad local de sesión. Git ya no informa que este archivo no está fusionado.",
+ "9c2901ef8a": "Próximo conflicto",
+ "41d9af2e7a": "Conflicto anterior",
+ "55d61a0ccd": "conflicto ·",
+ "da539359b6": "No hay ningún archivo de árbol de trabajo disponible para editar para este conflicto."
+ },
+ "ConflictReviewFileTree": {
+ "3449521a8c": "No hay conflictos en esta instantánea.",
+ "a54551c5a6": "Contraer árbol de archivos",
+ "99496bab6e": "Archivos",
+ "496e28a932": "Desaparecido",
+ "8528a5eaf5": "Resuelto",
+ "69d4e210bb": "Irresoluto"
+ },
+ "CsvViewer": {
+ "eedd0d37a7": "columnas",
+ "ac31d2cd60": "filas",
+ "a233d55b77": "archivo vacio"
+ },
+ "DiffNotesSendMenu": {
+ "f1aa04b5cf": "este archivo",
+ "8b87612461": "Todas las notas no enviadas"
+ },
+ "DiffSectionBody": {
+ "35d6afb5be": "Archivo binario cambiado",
+ "cef4cf0ff5": "Rever",
+ "f5cf81cec2": "Cargando diferencias...",
+ "72f71f52eb": "La diferenciación de texto no está disponible para este archivo.",
+ "7ce8436458": "La diferencia de texto no está disponible para este archivo en la comparación de ramas.",
+ "bdbf02d5df": "binario"
+ },
+ "DiffSectionHeader": {
+ "8915726e93": "Copiar ruta"
+ },
+ "EditorContent": {
+ "56dba34e1a": "(editar en modo fuente)",
+ "e4b074749d": "Asunto frontal",
+ "9640d1d3db": "Vista previa de la versión modificada de esta diferencia. Cambie al modo fuente para inspeccionar los cambios.",
+ "78541e254e": "Archivo binario cambiado",
+ "c88c73a0d3": "Cargando diferencias...",
+ "b9de81ba52": "Archivo binario: no se puede mostrar",
+ "b2735221f5": "Cargando...",
+ "8608ce4cb1": "La vista previa de Markdown no está disponible para archivos binarios.",
+ "37a0e81fa6": "Cargando vista previa...",
+ "8b1a605bae": "Este archivo se encuentra en estado de conflicto, pero no hay ningún archivo de árbol de trabajo disponible para editar.",
+ "2a512bb46a": "Rever",
+ "39f018b052": "No se puede cargar el archivo",
+ "8a0898ae4c": "La diferenciación de texto no está disponible para este archivo.",
+ "3c6e71df22": "La diferencia de texto no está disponible para este archivo en la comparación de ramas.",
+ "d07e4b8553": "rama",
+ "d16e037f40": "rico"
+ },
+ "EditorPanelHeader": {
+ "fb8331694e": "Abrir vista previa al lado",
+ "4157f3cbf3": "Abrir vista previa de rebajas",
+ "269ce4842b": "Copiar ruta relativa",
+ "7c08a1f990": "Copiar ruta",
+ "84cdc0794b": "Rebautizar",
+ "1bb1e226ec": "Cambiar el nombre del archivo {{value0}}",
+ "5447c4f68f": "Tabla de contenido",
+ "146cb5473c": "La tabla de contenidos está disponible en modo enriquecido o de vista previa.",
+ "e836faacfa": "Cambiar a diferenciación lado a lado",
+ "94756f08ba": "Cambiar a diferencia en línea",
+ "c98ce191da": "Esta diferenciación no tiene ningún archivo del lado modificado para abrir",
+ "9b80bbe1de": "Abrir pestaña de archivo",
+ "f0fd4174b5": "Abra la pestaña de archivo para utilizar la edición de rebajas enriquecida",
+ "a10d9b8337": "Abrir archivo"
+ },
+ "EditorPanelMarkdownActionsMenu": {
+ "3e0ce48c24": "Exportar como PDF",
+ "561251019a": "Más acciones",
+ "8c8b7f5ff5": "Mostrar portada",
+ "10c39d58c1": "Ocultar materia preliminar"
+ },
+ "EditorPanelShell": {
+ "e2c4dec350": "Cargando editor..."
+ },
+ "EditorViewToggle": {
+ "b3410cd5e0": "Computadora portátil",
+ "e408aa9cd5": "Mesa",
+ "167f45888c": "Cambios no confirmados",
+ "4837f3f578": "Cambios",
+ "ac3bb87913": "Editar",
+ "0d193dc03c": "Avance",
+ "aff15f94f5": "Editor rico",
+ "4d6ccb7ba6": "Fuente"
+ },
+ "ImageDiffViewer": {
+ "a651be62b0": "Modificado",
+ "57aac3979a": "Original",
+ "fb0ae4f3c0": "Sin vista previa"
+ },
+ "ImageViewer": {
+ "3c9217f5a6": "Dar un golpe de zoom",
+ "6c89c73d9f": "Restablecer zoom",
+ "be27304574": "alejar",
+ "77bfc9b35a": "Abrir imagen en ventana emergente",
+ "3ef9551ba2": "Cargando vista previa...",
+ "d9d2944855": "No se pudo cargar la vista previa del archivo"
+ },
+ "ImageViewerPopup": {
+ "0ef78475e7": "Presione Esc para cerrar",
+ "535f4e2b56": "Cerca",
+ "9e27b2ecaf": "Vista previa de imagen a tamaño completo"
+ },
+ "IpynbViewer": {
+ "859bf9fc21": "Ejecutar celda",
+ "7f0d7077c6": "Cancelar",
+ "10ed04a685": "Las celdas del cuaderno ejecutan Python local en esta máquina desde la carpeta del cuaderno. Ejecute únicamente celdas de archivos en los que confíe.",
+ "9e06ae5d36": "¿Ejecutar el código del cuaderno?",
+ "d6f37a640b": "cuaderno vacio",
+ "8c3b21369a": "formato nb",
+ "329764e9fc": "BETA",
+ "15ec40a735": "guardar cuaderno",
+ "07e7d96612": "células",
+ "c1601b23b2": "No se puede renderizar el cuaderno",
+ "66a3f7d330": "Salida HTML del cuaderno",
+ "781abd6926": "Eliminar celda",
+ "b42f6a9547": "Insertar celda de rebajas a continuación",
+ "ffc1ac2699": "Insertar celda de rebajas arriba",
+ "b4208cad7e": "Inserte la celda de código a continuación",
+ "53b839b8a0": "Insertar celda de código arriba",
+ "27e064e2db": "Mover celda hacia abajo",
+ "fd8ac707bc": "Mover celda hacia arriba",
+ "3e4cbf15ea": "Crudo",
+ "1833dbbc43": "Reducción",
+ "7005960d73": "Código",
+ "59b6cd874b": "código",
+ "ba149053d5": "reducción"
+ },
+ "MarkdownPreview": {
+ "e4683f70c4": "Cancelar",
+ "d737791433": "Agregar nota para la IA",
+ "b1bfc04034": "Texto seleccionado",
+ "f37b98999e": "esta nota",
+ "2b2b31382c": "Asunto frontal",
+ "bb629de58a": "Copiar notas para el agente",
+ "322afab6ff": "Notas de revisión",
+ "0f9969a159": "Saltar a la primera nota de revisión",
+ "12052c639c": "Cerrar búsqueda",
+ "b42c41bd0d": "Próximo partido",
+ "1febd97f5c": "Partido anterior",
+ "ec77985138": "Buscar en vista previa de rebajas",
+ "517aea303b": "Buscar en vista previa",
+ "f961e94057": "Copiar nota para el agente",
+ "94b520a96a": "nota copiada",
+ "13f94d760c": "Agregar nota",
+ "ddf087d12e": "Todas las notas no enviadas",
+ "d652c87c91": "Ahorro…",
+ "c5dc92cfe3": "Sin resultados",
+ "6c043947ae": "Archivo no encontrado: {{value0}}",
+ "759463a221": "No se puede abrir el directorio: {{value0}}"
+ },
+ "MarkdownTableOfContentsPanel": {
+ "de3928b6e4": "Sin encabezados",
+ "bbe8369097": "Cerrar tabla de contenidos",
+ "4680a4b808": "Contraer a H{{value0}}",
+ "a5daadd68b": "Expandir todo",
+ "111e66b85d": "Contraer al nivel de título {{value0}}",
+ "f3de856175": "Expandir todos los niveles de encabezado",
+ "0dc7b2f05a": "Contraer por nivel",
+ "06357eea60": "Tabla de contenido",
+ "27d0a9c49a": "Tabla de contenido",
+ "65b036a6c8": "Expandir {{value0}}",
+ "97ad46f11f": "Contraer {{value0}}"
+ },
+ "MarkdownTemplatePicker": {
+ "22cd94426f": "sin título.md",
+ "6e2e6c04ad": "Rebaja en blanco",
+ "df667919ca": "No hay plantillas coincidentes.",
+ "22fd4890ad": "Buscar plantillas...",
+ "7b458e0b7f": "Elija una plantilla de Markdown.",
+ "1829437fce": "Nueva rebaja"
+ },
+ "MermaidBlock": {
+ "dcc132e691": "Error de diagrama:"
+ },
+ "MonacoEditor": {
+ "68cb83f4a7": "Agregar nota sobre el texto seleccionado",
+ "fd68ae03b3": "Buscar en archivos"
+ },
+ "MonacoGutterContextMenu": {
+ "7b57b1b468": "Copiar URL remota",
+ "2e0b1cdc05": "Copiar Rel. Camino a la línea",
+ "4eaa991bde": "Copiar ruta a línea"
+ },
+ "NotesSendMenu": {
+ "44dc5e60a6": "enviar notas",
+ "433928cd9f": "Enviar {{value0}} a un agente"
+ },
+ "PdfFind": {
+ "cd65b1d6b0": "Cerca",
+ "eeba2547a1": "Próximo partido",
+ "30de726ad0": "Partido anterior",
+ "2fc3ba0ea8": "Buscar en la página...",
+ "d080ab37d6": "No hay coincidencias",
+ "db56fcd6d2": "{{value0}} de {{value1}}"
+ },
+ "PdfViewer": {
+ "3e98d500d2": "Vista previa de PDF",
+ "069ff59932": "Buscar en PDF ({{value0}})",
+ "2b6eb1ccd6": "Dar un golpe de zoom",
+ "c0119616d6": "Ajustar al ancho",
+ "fa5d096b00": "alejar"
+ },
+ "ReviewNotesSendMenuContent": {
+ "a49800405b": "Nuevo agente",
+ "e84705f223": "Sesión de agente activo",
+ "03378aea75": "enviar notas a",
+ "f5096c6e4e": "No se pudieron enviar notas al agente activo.",
+ "bb9c69a0c9": "Notas enviadas al agente activo.",
+ "50f7e753ea": "Enviando notas al agente activo..."
+ },
+ "RichMarkdownAnnotationOverlay": {
+ "069b5677b8": "Texto seleccionado",
+ "6f2f3a6001": "Agregar nota de revisión"
+ },
+ "RichMarkdownCodeBlock": {
+ "232d9ed853": "copiado",
+ "c72beafc0f": "Copiar código",
+ "74eab1d9b2": "YAML",
+ "5ef5605cb7": "XML",
+ "88d777bc07": "Mecanografiado",
+ "9e384d48dc": "Rápido",
+ "3009f722b9": "SQL",
+ "d01f55be57": "Caparazón",
+ "5af8251002": "SCSS",
+ "e72e6b03f4": "Óxido",
+ "96182a2f64": "Rubí",
+ "2391f9cda9": "Pitón",
+ "89d6cc14fb": "Sirena",
+ "983b9576b4": "Reducción",
+ "bcb236e2d8": "Kotlin",
+ "78eba32de4": "JSON",
+ "a209c57063": "javascript",
+ "36536ad539": "Java",
+ "8c4a3fa02d": "HTML",
+ "706fd85738": "GrafoQL",
+ "edfcc64182": "Ir",
+ "bf6ee5caaa": "diferencia",
+ "026653f21f": "CSS",
+ "4daed43ae3": "C++",
+ "4227cf50fe": "Intento",
+ "13822cdfda": "Texto sin formato"
+ },
+ "RichMarkdownDocLinkMenu": {
+ "e17b987473": "↑↓ navegar ↵ seleccionar esc descartar",
+ "90c5f0e1e4": "de",
+ "2aaf7d9678": "Demostración",
+ "63ced7cb9b": "No se encontraron documentos",
+ "0e8489bc11": "Enlaces de documentos de rebajas",
+ "142a7d51cd": "documento"
+ },
+ "RichMarkdownErrorBoundary": {
+ "aad0998127": "Rever",
+ "4a5de9f2f0": "Cambie al modo fuente o haga clic en Reintentar para recargar la vista enriquecida.",
+ "dfdf1cacd4": "El editor de rebajas enriquecido sufrió un error inesperado y se restableció para que el resto de Orca siguiera respondiendo."
+ },
+ "RichMarkdownLinkBubble": {
+ "1c99b726e0": "Quitar enlace",
+ "cdfe166f6f": "Editar enlace",
+ "bfc813e909": "Abrir enlace",
+ "7b0b945fdc": "Pegue o escriba un enlace..."
+ },
+ "RichMarkdownReviewNoteLayer": {
+ "f3ef92952b": "esta nota",
+ "9cde7ad994": "Copiar nota para el agente",
+ "117432e2c6": "nota copiada",
+ "3ababd949d": "Notas de revisión"
+ },
+ "RichMarkdownReviewRailActions": {
+ "636394af72": "Copiar notas para el agente",
+ "a807596997": "notas copiadas",
+ "8aaf2c4c69": "Mostrar notas de revisión",
+ "af02dc2456": "Ocultar notas de revisión"
+ },
+ "RichMarkdownSearchBar": {
+ "de68b75bde": "Cerrar búsqueda",
+ "f7bcecbe26": "Próximo partido",
+ "32ae8d7d57": "Partido anterior",
+ "158c645829": "Buscar en el editor de rebajas enriquecido",
+ "98b89276f3": "Buscar en editor enriquecido",
+ "a86958d508": "Sin resultados"
+ },
+ "RichMarkdownSlashMenu": {
+ "82c6816ff8": "No se encontraron bloques",
+ "dbdd2ad15f": "Bloques de búsqueda...",
+ "550189b06c": "Bloques de búsqueda",
+ "2e0400b958": "Comandos de barra diagonal",
+ "e2e12b0e98": "componente"
+ },
+ "RichMarkdownToolbar": {
+ "e935c6b61e": "Imagen",
+ "6d52624712": "Enlace",
+ "f6a51cb9af": "Cita",
+ "f97031be09": "Lista de verificación",
+ "31630ed66e": "lista numerada",
+ "5d1539e5a9": "lista de viñetas",
+ "0bea19a988": "Huelga",
+ "6b4ccf9493": "Itálico",
+ "4f9e789fe0": "Atrevido",
+ "cf5817d827": "Título 3",
+ "d34a2021c8": "Título 2",
+ "abb5100a3d": "Título 1",
+ "b462641ed2": "Texto del cuerpo"
+ },
+ "UntitledFileRenameDialog": {
+ "a7dd27b0bc": "Ahorrar",
+ "949711deb4": "Cancelar",
+ "725868c75d": "Explorar carpetas",
+ "5e7f0d8a80": "Selector de carpetas no disponible para archivos remotos",
+ "30099dca46": "Carpeta",
+ "2d7d39dc63": ".Maryland",
+ "c8ac7868e6": "Nombre del archivo",
+ "b6ed807cc6": "Nombre",
+ "e365f3c638": "Asigne un nombre a su archivo de rebajas y elija una carpeta.",
+ "674b046582": "Guardar como"
+ },
+ "export": {
+ "active": {
+ "markdown": {
+ "51c4244904": "Exportado a {{value0}}",
+ "d4a901e0ad": "Exportando PDF...",
+ "eda2cea3ad": "No se pudo exportar el PDF"
+ }
+ }
+ },
+ "markdown": {
+ "rich": {
+ "mode": {
+ "7a8ce7c7da": "Editable solo en modo código porque este archivo contiene notas a pie de página.",
+ "2fd2b44073": "Editable solo en modo código porque este archivo contiene enlaces de estilo de referencia.",
+ "57128b73e1": "Editable solo en modo código porque este archivo contiene HTML, JSX o MDX."
+ }
+ }
+ },
+ "rich": {
+ "markdown": {
+ "editor": {
+ "click": {
+ "routing": {
+ "2d5fb9335d": "Archivo no encontrado: {{value0}}"
+ }
+ }
+ },
+ "slash": {
+ "commands": {
+ "07e1b32396": "Inserta un emoji Unicode simple.",
+ "8a30cbaeca": "emojis",
+ "3324eb391a": "Inserta una imagen desde tu computadora.",
+ "572be8e524": "Imagen",
+ "ae7d0f3f37": "Insertar pantalla matemática LaTeX.",
+ "6993a38ad1": "Bloque matemático",
+ "565907cf7a": "Inserte matemáticas LaTeX en línea.",
+ "2bf5544faf": "Matemáticas en línea",
+ "0ed9a7b38c": "Inserta un bloque vallado de sirena.",
+ "e516d3f6e3": "Diagrama de sirena",
+ "67faab829b": "Inserte una tabla de rebajas de 3x3.",
+ "19ea597868": "Mesa",
+ "fae45ef4d3": "Inserta una regla horizontal.",
+ "ae8377cf6b": "Divisor",
+ "89e327e054": "Inserte un bloque de código vallado.",
+ "624b50cf25": "Bloque de código",
+ "972ef9aeea": "Crea una sección de texto plegable.",
+ "f82c78a2ee": "Alternar texto",
+ "9a7fe896dc": "Comience un párrafo normal.",
+ "58abdb9d41": "Párrafo",
+ "d766f44867": "Crea una lista de verificación.",
+ "d0d2cdfbdb": "Lista de verificación",
+ "c9b9e826b8": "Crea una lista desordenada.",
+ "56ff3237e7": "Lista de viñetas",
+ "8e00aba296": "Crea una lista ordenada.",
+ "ed4cf0ebce": "Lista numerada",
+ "6a3def14de": "Inserte una cita en bloque.",
+ "c4c775778b": "Cita",
+ "4920740259": "Título de sección pequeña.",
+ "30566ee962": "Título 3",
+ "45cf7ceb3f": "Encabezado de sección media.",
+ "c209a116b7": "Título 2",
+ "3294a2c0cc": "Cree una sección plegable con un resumen de encabezado grande.",
+ "41482b15ce": "Alternar título 1",
+ "570611864e": "Encabezado de sección grande.",
+ "e66e7f04c6": "Título 1"
+ }
+ }
+ }
+ },
+ "useContextualCopySetup": {
+ "059bfb0d94": "Contexto copiado"
+ },
+ "useLocalImagePick": {
+ "175cb8b8ce": "No se pudo insertar la imagen.",
+ "91d835dc88": "Ruta del árbol de trabajo no disponible."
+ },
+ "useRichMarkdownReviewData": {
+ "f9d2acd6b0": "Todas las notas no enviadas"
+ }
+ },
+ "diff": {
+ "comments": {
+ "DiffCommentCard": {
+ "109a791e7b": "Ahorrar",
+ "bb0a55f856": "Ahorro…",
+ "0203bed775": "Cancelar",
+ "6978871a3d": "Abierto",
+ "cce596969e": "Eliminar nota",
+ "cad3384faa": "Editar nota",
+ "508ee678a5": "Abrir en el navegador"
+ },
+ "DiffCommentPopover": {
+ "2b3ce6d394": "Cancelar",
+ "e05063cfc1": "Línea {{value0}}",
+ "c845170b3b": "Líneas {{value0}}-{{value1}}"
+ },
+ "useDiffCommentDecorator": {
+ "995fa28b50": "esta nota"
+ }
+ }
+ },
+ "dictation": {
+ "DictationController": {
+ "de136f1199": "Error de voz: {{value0}}",
+ "7afff43472": "El dictado finalizó, pero no se centró ningún campo de texto.",
+ "55127a3706": "Dictado fallido: {{value0}}",
+ "bb7f599ee7": "Abrir configuración",
+ "2d5b9fabf9": "Acceso al micrófono denegado. Conceda acceso en la configuración del sistema, luego reinicie Orca.",
+ "5d2c3e7ae3": "No se detectó ninguna voz."
+ }
+ },
+ "dashboard": {
+ "DashboardAgentChildDisclosure": {
+ "1b57ce9fa4": "{{value0}} {{value1}} niño {{value2}}"
+ },
+ "DashboardAgentRow": {
+ "912e136cd9": "Enviar",
+ "a743da52ff": "Ampliar detalles",
+ "a41fb5376e": "Contraer detalles",
+ "5ae84475cc": "Despedir",
+ "b06e13fcf7": "Despedir agente",
+ "0272969e28": "Enviar a este agente",
+ "92a7017987": "envío",
+ "019b74d93a": "elegible"
+ },
+ "DashboardAgentRowMessage": {
+ "0a01046763": "interrumpido",
+ "1ec01cef03": "Interrumpido por el usuario"
+ }
+ },
+ "crash": {
+ "report": {
+ "CrashReportDialog": {
+ "b4951cd27c": "Enviar informe",
+ "88fea8e84e": "No enviar",
+ "50b00dc327": "Copiar detalles",
+ "6d3ebe216a": "Texto de diagnóstico",
+ "835037edc9": "· Orcas",
+ "56a3dfa283": "No se pudo enviar el informe de fallas.",
+ "8e24fe4f75": "Informe de fallo enviado.",
+ "8b8473c544": "Se copió el informe de fallos.",
+ "b175e90213": "No hay ningún informe de fallo disponible.",
+ "765591798d": "Comprobando informes de fallos..."
+ }
+ }
+ },
+ "contextual": {
+ "tours": {
+ "ContextualTourControl": {
+ "186eecc34f": "Nombre automático del espacio de trabajo desde el primer mensaje del agente",
+ "02e8373219": "Genera automáticamente un nuevo nombre cuando deja este cuadro de texto vacío.",
+ "731c5573df": "Nombre automático desde el primer mensaje"
+ },
+ "ContextualTourOverlaySurface": {
+ "4a9568f773": "Atrás",
+ "4f86e2a10b": "Saltar recorrido",
+ "d974f32a83": "Descartar recorrido",
+ "ffa4412b66": "próximo"
+ },
+ "ContextualTourProgressDots": {
+ "7734cb8ad3": "de",
+ "dcd6e6b03e": "Paso {{value0}} de {{value1}}"
+ },
+ "contextual": {
+ "tour": {
+ "overlay": {
+ "measurement": {
+ "38b3155418": "Próximo"
+ }
+ }
+ }
+ }
+ }
+ },
+ "cmd": {
+ "j": {
+ "quick": {
+ "actions": {
+ "c884a6398e": "Cree un comando de terminal guardado.",
+ "a43ab56fc1": "Agregar comando rápido",
+ "54853d52a2": "Eliminar el árbol de trabajo actual.",
+ "9537b910fe": "Eliminar árbol de trabajo",
+ "0b1f25f796": "Inicie un nuevo árbol de trabajo.",
+ "52ac9da671": "Crear árbol de trabajo",
+ "f70812764a": "Abra una pestaña de terminal en el espacio de trabajo activo.",
+ "34980395d4": "Nueva pestaña de terminal",
+ "f2a1b33f8d": "Cree un archivo de rebajas sin título en el espacio de trabajo activo.",
+ "25349b66fc": "Nuevo archivo de rebajas",
+ "784812ca24": "Abra una pestaña del navegador en el espacio de trabajo activo.",
+ "892bfa9339": "Nueva pestaña del navegador",
+ "verbs": {
+ "newBrowser": "nuevo navegador",
+ "newBrowserTab": "nueva pestaña del navegador",
+ "openBrowser": "abrir el navegador",
+ "browserTab": "pestaña del navegador",
+ "newMarkdown": "nueva rebaja",
+ "newMarkdownFile": "nuevo archivo de rebajas",
+ "newMark": "nueva marca",
+ "newFile": "nuevo archivo",
+ "markdownFile": "archivo de rebajas",
+ "newTerminal": "nueva terminal",
+ "newTerminalTab": "nueva pestaña de terminal",
+ "newShell": "nuevo caparazón",
+ "terminalTab": "pestaña terminal",
+ "createWorktree": "crear árbol de trabajo",
+ "addWorktree": "agregar árbol de trabajo",
+ "newWorktree": "nuevo árbol de trabajo",
+ "deleteWorktree": "eliminar árbol de trabajo",
+ "deleteCurrentWorktree": "eliminar el árbol de trabajo actual",
+ "removeWorktree": "eliminar árbol de trabajo",
+ "trashWorktree": "árbol de trabajo de basura",
+ "addQuickCommand": "agregar comando rápido",
+ "newQuickCommand": "nuevo comando rápido"
+ }
+ }
+ }
+ }
+ },
+ "browser": {
+ "pane": {
+ "BrowserFind": {
+ "c9d5f63fdc": "Cerca",
+ "5c0c02ae76": "Próximo partido",
+ "ca7aebbd7f": "Partido anterior",
+ "636a69cd66": "Buscar en la página...",
+ "7baca7b1b8": "No hay coincidencias",
+ "fc63f336aa": "{{value0}} de {{value1}}"
+ },
+ "BrowserImportHintButton": {
+ "05e675fe96": "Ocultar pista",
+ "77351d22f5": "Configuración del navegador",
+ "e0e125e074": "Desde archivo…",
+ "0c6d254eca": "De",
+ "244266c122": "Importar…",
+ "e52a955e6f": "Siempre puedes encontrar esto en Configuración > Navegador.",
+ "4f5ffaa6a1": "Importar datos del navegador",
+ "b24fef25be": "Importar",
+ "02e89014c5": "Se importaron {{value0}} cookies de {{value1}}{{value2}}.",
+ "d40d584769": "Se importaron {{value0}} cookies del archivo."
+ },
+ "BrowserMobileDriverOverlay": {
+ "a6914ee43f": "Devolver",
+ "f4ecd61552": "Esta pestaña se controla desde su teléfono. Vuelva a usarlo en el escritorio.",
+ "d9768ec642": "La entrada del navegador está en pausa",
+ "20539eca03": "El móvil impulsa este navegador"
+ },
+ "BrowserPane": {
+ "1ded0d3168": "Copiar captura de pantalla",
+ "f30d2d35a7": "Captura de pantalla",
+ "fa6ea61de3": "Cancelar",
+ "c2ef0359b9": "Copiar contenido",
+ "f2d0c22d67": "Eliminar anotación {{value0}}",
+ "11c5084aa2": "Borrar anotaciones",
+ "734e4343ec": "Borrar anotaciones del navegador",
+ "95af781091": "Enviar comentarios a un nuevo agente",
+ "ac39b9366b": "Enviar",
+ "a3508d7e6e": "{{value0}} anotación{{value1}} listo. Seleccione otro elemento o copie todos los comentarios.",
+ "f796c774a4": "Escriba una URL arriba para comenzar a navegar.",
+ "366bf5d62c": "Nueva pestaña",
+ "1c78adc73d": "Abrir externamente",
+ "da68d35f7b": "Abrir página fallida en el navegador predeterminado",
+ "93be92f8d1": "Copiar dirección",
+ "3c085f638d": "Copiar la URL de la página fallida",
+ "c6be71329e": "Refrescar",
+ "781d6459ad": "Rever",
+ "2fdca7df09": "Despedir",
+ "8b6fab9ffa": "Ahorrar",
+ "0f41bf80c7": "Abrir en el navegador predeterminado",
+ "ec75d0c412": "Abrir herramientas de desarrollo del navegador",
+ "fc9be38f6f": "Anotar elemento de página",
+ "fdfc7fe0ef": "Tomar elemento de página",
+ "a8f37f70c3": "Inspeccionar página",
+ "1b179ab561": "Copiar URL de página",
+ "f7ab83f7ed": "Abrir página en el navegador predeterminado",
+ "0e080d820e": "Recargar",
+ "250a9b3e42": "Adelante",
+ "40edfa75cb": "Atrás",
+ "efb0e8f7f3": "Copiar dirección de enlace",
+ "8ce4f6b12e": "Abrir enlace en el navegador predeterminado",
+ "b5b87d6cbb": "Abrir enlace en el navegador Orca",
+ "87eb75f7d2": "Introduzca una URL http(s) o localhost válida.",
+ "27d863542c": "Anotaciones del navegador",
+ "e48569ac6d": "No se pudo acceder a este sitio.",
+ "bbe8f15e83": "Este panel se representa desde el servidor de ejecución activo.",
+ "8b7e6d1f5a": "Las anotaciones del navegador solo están disponibles en las pestañas del navegador local.",
+ "deb5293610": "Las anotaciones del navegador no están disponibles en el tiempo de ejecución remoto",
+ "90d021f2ad": "Agregar",
+ "0cb3bd6221": "Intención de anotación",
+ "8f87e6c2e5": "Intención",
+ "532bac48c5": "Describe aquí lo que el agente debería cambiar...",
+ "d2a7092e6e": "comentario de anotación",
+ "b472c5fe03": "Agregar anotación del navegador",
+ "b5ba6085de": "Pregunta",
+ "143204e423": "Cambiar",
+ "e7ca5a098c": "éxito",
+ "d51ef37351": "Copiar",
+ "6f4ab3592b": "copiado",
+ "b2856516e2": "No se puede cargar esta página",
+ "db325a7eeb": "No puedo comunicarme con {{value0}}",
+ "499b31b84e": "Copiar todo",
+ "e72dfa268a": "anotar",
+ "168350ae6a": "Haga clic o coloque el cursor sobre un elemento, luego presione C para copiar o S para hacer una captura de pantalla.",
+ "e852e20cea": "Copiado: presione S para hacer una captura de pantalla o seleccione otro elemento",
+ "a5dcd0fd1d": "confirmando",
+ "777b5bc4ec": "Haga clic en un elemento para agregar comentarios para el agente.",
+ "b733a91bd9": "Agregue comentarios para el elemento seleccionado.",
+ "4328a0a062": "Grabación fallida: {{value0}}",
+ "26615e116b": "error",
+ "8aec5bc044": "idle",
+ "759f32af29": "Descargando",
+ "c8bc7f1f9e": "solicitado",
+ "4300f38145": "Descargando desde {{value0}}{{value1}}",
+ "31375046b7": "Descargar desde {{value0}}",
+ "acbe79fd01": "Tomar elemento de página ({{value0}})",
+ "572046436a": "Navegador remoto",
+ "b313a7275b": "Abrir navegador remoto",
+ "5f66313863": "anotación",
+ "ea6af700da": "{{value0}} anotación",
+ "c13693fe27": "{{value0}} anotaciones",
+ "074f0ed10b": "{{value0}} anotación lista. Seleccione otro elemento o copie todos los comentarios.",
+ "a2164a6e5a": "{{value0}} anotaciones listas. Seleccione otro elemento o copie todos los comentarios."
+ },
+ "BrowserToolbarMenu": {
+ "429ef481f9": "Cancelar",
+ "64f448fb6e": "Nombre del perfil",
+ "67e9b9fcd6": "Nuevo perfil del navegador",
+ "58f2c81542": "Cambiar",
+ "a38f217b46": "Cambiar de perfil recargará esta página. Todos los datos del formulario no guardados se perderán.",
+ "fe683eb3b4": "Cambiar perfil",
+ "a771c2b6c8": "Configuración del navegador…",
+ "ed8f54509d": "Por defecto",
+ "e5d31de1a9": "Tamaño de la ventana gráfica",
+ "56f94f4ffa": "Desde archivo…",
+ "eb280bfb11": "Desde {{value0}}",
+ "2293adf620": "Importar cookies",
+ "cf7cdc67ef": "Nuevo perfil…",
+ "7b838540c7": "Menú del navegador",
+ "6aa42813e4": "Se importaron {{value0}} cookies de {{value1}}{{value2}}.",
+ "a7a86702b3": "Creado y cambiado al perfil {{value0}}",
+ "4d2f9f13a7": "No se pudo crear el perfil.",
+ "3ccd29d771": "Cambiado al perfil {{value0}}",
+ "569bce8eb1": "Crear",
+ "bf648471c5": "Creando…",
+ "53bbe3dab4": "Se importaron {{value0}} cookies del archivo.",
+ "c5f0e4d3b2a1": "Se importaron {{value0}} cookies de {{value1}} ({{value2}}).",
+ "d6a1f5e4c3b2": "Se importaron {{value0}} cookies de {{value1}}."
+ },
+ "GrabConfirmationSheet": {
+ "314a0aaa5b": "Adjuntar a IA",
+ "7095e98362": "Copiar captura de pantalla",
+ "26fd87f4df": "Copiar",
+ "87d97bdd6d": "Cancelar",
+ "effd75e330": "Contexto cercano",
+ "7d1480fbf1": "HTML",
+ "9098b118ab": "Página",
+ "eb98a0971a": "\"",
+ "d053db279d": "rol=",
+ "a759d8f866": "Elemento seleccionado",
+ "9c6ce0632a": "Captura de pantalla del elemento seleccionado",
+ "50f7114f99": "Revisar antes de adjuntar. El contexto de la página capturada puede incluir contenido visible del sitio.",
+ "f3575229df": "Agarrar",
+ "405bb315da": "Intitulado"
+ },
+ "browser": {
+ "address": {
+ "bar": {
+ "suggestions": {
+ "87fcdd0da9": "{{value0}} Buscar"
+ }
+ }
+ }
+ }
+ }
+ },
+ "automations": {
+ "AutomationCustomCronPanel": {
+ "3e3b2c369f": "expresión cron",
+ "e81a02d61b": "Ingrese un cron válido de cinco campos antes de guardar.",
+ "968e66d686": "Ingrese un cron de cinco campos.",
+ "cadb7b0bc9": "inválido"
+ },
+ "AutomationDetail": {
+ "007c8ad874": "Inmediato",
+ "a1d52c2189": "Cobertura de uso",
+ "449fc83bf7": "Fichas",
+ "401f40ae79": "Est. gastar",
+ "a7c312430d": "última ejecución",
+ "2df8970cd5": "Agente",
+ "e353ab9516": "verificación previa",
+ "620b22145e": "Gracia",
+ "15ea446b93": "Sesión",
+ "5405a09b1f": "Ejecutar ubicación",
+ "2f8baf5360": "Crear desde",
+ "578ff46987": "Próxima ejecución",
+ "18763ded26": "Cronograma",
+ "dbef8dc110": "Esta automatización SSH se ejecuta sólo mientras Orca puede comunicarse con el host SSH. Si la reconexión necesita credenciales interactivas o el host no está disponible, la ejecución se registra como omitida.",
+ "1f6026358e": "Eliminar automatización",
+ "d79452fb30": "Reanudar la automatización",
+ "91a4155e95": "Pausar la automatización",
+ "4b1ea02d2e": "Editar automatización",
+ "2fb1605beb": "Ejecutar ahora",
+ "221916d93c": "Cree una automatización para comenzar a programar el trabajo de los agentes.",
+ "de0fedac06": "nuevo_por_ejecución",
+ "51a470b966": "ssh",
+ "b09b2384fd": "En pausa",
+ "eaa02014f8": "Activado"
+ },
+ "AutomationEditorDialog": {
+ "fb1896a5e7": "Cancelar",
+ "57b722cbba": "Agente",
+ "6ff66f9012": "Nueva carrera",
+ "a2e688226d": "árbol de trabajo",
+ "6f9610e667": "Worktree se ejecuta en el espacio de trabajo seleccionado. La nueva ejecución crea un espacio de trabajo nuevo a partir de la rama seleccionada cada vez.",
+ "2c3fd9bfa1": "Ayuda del modo espacio de trabajo",
+ "b28b140eaf": "Espacio de trabajo",
+ "0d17f4ca8f": "Seleccionar proyecto",
+ "02d351877e": "Proyecto",
+ "a4ac8fcc62": "/meta",
+ "827b25a81e": "Admite habilidades, rutas de archivos y comandos integrados como",
+ "6d778190b7": "Ejecute la auditoría de dependencia semanal y resuma los cambios riesgosos.",
+ "058c23cb3f": "Inmediato",
+ "c4b19094c2": "Cronograma",
+ "e46c1aa9ad": "Crear",
+ "a9d9dccf77": "Ahorrar",
+ "777548c2d6": "Guardar cambios",
+ "ff5db28639": "existente"
+ },
+ "AutomationEditorDialogHeader": {
+ "31f9253920": "Usar plantilla",
+ "7e35393632": "Hermes",
+ "6f309eef8d": "Orca",
+ "58f56b73d9": "Nombre de la automatización",
+ "1d9826933e": "Auditoría de repositorios entre semana",
+ "4133d33862": "Crear automatización",
+ "0a75e5e2fa": "Crear automatización Hermes",
+ "03142e7721": "Editar la automatización de Hermes",
+ "17086b48ee": "Editar automatización"
+ },
+ "AutomationMissedRunGraceField": {
+ "0f4459e91d": "48 horas",
+ "adbab51feb": "24 horas",
+ "ba50e2a230": "12 horas",
+ "2dc9ee84d0": "3 horas",
+ "521f77cd58": "1 hora",
+ "e5ad263ae5": "30 minutos",
+ "529dc6c0b7": "sin gracia",
+ "3d70c185c8": "Si Orca o el host de ejecución no estaban disponibles a la hora programada, Orca ejecuta una ocurrencia perdida cuando esté disponible dentro de esta ventana. Se omiten las carreras perdidas más antiguas.",
+ "3df53d554a": "Ayuda de gracia para carreras perdidas",
+ "fc089e5fde": "Gracia"
+ },
+ "AutomationPrecheckFields": {
+ "d2a2ac89ac": "10 minutos",
+ "bf49585b3c": "5 minutos",
+ "d84d3765fd": "2 minutos",
+ "c820119736": "1 minuto",
+ "51e28cdad9": "30 seg",
+ "bb2dfb3629": "Se acabó el tiempo",
+ "99a577306c": "gh pr list --json número -q '.[0].número'",
+ "c2a762a180": "verificación previa"
+ },
+ "AutomationRunHistory": {
+ "402651bfb6": "Aún no hay carreras.",
+ "9974a2b429": "Estado",
+ "13988187b3": "Fichas",
+ "86a248187e": "Gastar",
+ "149c0b49c7": "Espacio de trabajo",
+ "8faaa00726": "Correr",
+ "53fc5f07ab": "Historial de ejecución",
+ "a00e38d1a3": "n / A",
+ "fdb3caa8fb": "conocido"
+ },
+ "AutomationRunPageFrame": {
+ "40a511bed4": "Ejecutar contexto",
+ "33741dd973": "Volver a carreras"
+ },
+ "AutomationSchedulePicker": {
+ "22359b186a": "mañana o tarde",
+ "9e677335b0": "Minuto",
+ "6b802ecc99": "Hora",
+ "d90981f766": "Tiempo",
+ "6b914c5fbb": "Día",
+ "233b8c94b6": "Cadencia",
+ "b08ccb4d06": "cada hora",
+ "8cc026fd73": "semanalmente",
+ "c3e39e17cf": "costumbre"
+ },
+ "AutomationSessionField": {
+ "f3c76dce51": "Reutilizar",
+ "c90888ee94": "Fresco",
+ "b675112193": "La reutilización envía ejecuciones futuras a la sesión de automatización en vivo anterior. Si esa sesión termina, Orca comienza una nueva.",
+ "4bdce31f37": "Ayuda para la reutilización de sesiones",
+ "5ad314118e": "Sesión"
+ },
+ "AutomationsPage": {
+ "2695883141": "borrar",
+ "c3a28c9793": "Seleccione una automatización para ver las ejecuciones.",
+ "295698292f": "Repetición",
+ "0e110a3469": "Corre",
+ "bb1b2cd31e": "Descripción general",
+ "97ff587ee3": "Conecte esta fuente para comprobar si hay automatizaciones Hermes en el perfil remoto.",
+ "aaa007846f": "fuente no disponible",
+ "25060635c6": "Agregar nuevo",
+ "d207ab4c25": "Empezar desde una plantilla",
+ "15e0bfb13b": "Borrar",
+ "f4612e3f78": "Editar",
+ "2faecab10b": "Ejecutar ahora",
+ "82eb6cb933": "fuente",
+ "13118faadf": "Proyecto desconocido",
+ "587a4b205c": "Próximo",
+ "761a35834d": "Automatización",
+ "73f630b49d": "Cancelar",
+ "1b586f0e2b": "en",
+ "02a33e3204": "de",
+ "9adfab2596": "Eliminar automatización externa",
+ "1e2e41392f": "no vuelvas a preguntar",
+ "b264564427": "y su historial de ejecución. Los espacios de trabajo creados por ejecuciones anteriores no se eliminan.",
+ "080dcb5fbb": "Eliminar automatización",
+ "19a6e30eae": "Actualizar automatizaciones",
+ "8d1afa8269": "Agregar automatización",
+ "77c2778945": "Automatizaciones",
+ "0329f9bef1": "Cerrar · Esc",
+ "67c7ff795b": "Cerrar automatizaciones",
+ "e1bf9b1512": "El espacio de trabajo no está disponible.",
+ "3e42a5cc1b": "La conexión SSH falló.",
+ "9f2855677c": "SSH conectado.",
+ "126d726546": "La acción de automatización externa falló.",
+ "37288942f0": "Se reanudó la automatización externa.",
+ "77c518a34b": "La automatización externa se detuvo.",
+ "4d7878402c": "Automatización externa en cola.",
+ "4c22bc9913": "Automatización externa eliminada.",
+ "3a4c476aa0": "No se pudo volver a ejecutar la automatización.",
+ "a1bdb57008": "Ejecución de automatización en cola.",
+ "8a3226f172": "Abrir configuración",
+ "d2a01b0b6f": "Puedes cambiar esto en Configuración.",
+ "690b94da54": "Omitiremos esta confirmación la próxima vez.",
+ "b11170a008": "No se pudo guardar la automatización.",
+ "2a20596d6b": "Automatización guardada.",
+ "244727e655": "Automatización actualizada.",
+ "77b81bc4ac": "Se crea la automatización de Hermes.",
+ "08efc3ae12": "Automatización Hermes actualizada.",
+ "e431bb85d4": "Elija un espacio de trabajo en el mismo host que esta automatización de Hermes.",
+ "32534e7c9c": "Elija un espacio de trabajo disponible antes de guardar.",
+ "2360ffc956": "Elija un agente habilitado antes de guardar.",
+ "6e91dab317": "Ingrese un horario avanzado válido antes de guardar.",
+ "64bdb2304f": "Elija un horario admitido antes de guardar.",
+ "2430fecf53": "Elija una ubicación de ejecución e ingrese un mensaje antes de guardar.",
+ "7934ee0d81": "Conectar SSH",
+ "f93ed7a6f8": "Conectando...",
+ "8705757e27": "trabajo",
+ "376631ef2b": "Reanudar",
+ "b457436d6a": "Pausa",
+ "0ae52dd760": "Hermes",
+ "e059042585": "Sólo lectura",
+ "aecdc3681f": "Manejable",
+ "8500baacb4": "fuente externa",
+ "36f71740a7": "Espacio de trabajo seleccionado",
+ "cd8397cc32": "Nuevo espacio de trabajo en cada ejecución",
+ "dd0bc7a1ba": "nuevo_por_ejecución",
+ "7b2e285552": "Las conexiones SSH no están disponibles en este cliente.",
+ "d441032f7e": "pausa",
+ "5918020edc": "correr"
+ },
+ "CreateFromPicker": {
+ "f061f49e3f": "Buscar sucursales de repositorio...",
+ "dd3841b442": "Derivarse de",
+ "ef6d762538": "Valor predeterminado del proyecto",
+ "e53d306056": "{{value0}} (predeterminado)",
+ "79512f22a7": "No se encontraron sucursales.",
+ "9ce96621f4": "Buscando sucursales..."
+ },
+ "ExternalAutomationManagers": {
+ "e02f970595": "No se encontraron administradores de automatización externos.",
+ "6da3bfba4b": "Automatizaciones encontradas.",
+ "3d58d5b67d": "No",
+ "a42bf2b27e": "Eliminar automatización externa",
+ "1c3bfd38fe": "Reanudar la automatización externa",
+ "0def1693bb": "Pausar la automatización externa",
+ "1df491fd00": "Editar automatización externa",
+ "cc77ba88ff": "Ejecutar automatización externa",
+ "5820648765": "Último",
+ "844f1acb72": "encontró",
+ "20fd7a3a15": "próximo",
+ "c6695e6fbd": "Automatizaciones externas",
+ "5524365227": "OpenClaw",
+ "766abf833c": "Hermes",
+ "bf5f67b590": "Hermes",
+ "e66091daf4": "corre",
+ "8e9165af08": "correr",
+ "2b0adbce21": "En pausa",
+ "b3feba84c7": "Activo",
+ "92405f1431": "Indisponible",
+ "dbdcec22bd": "Sólo lectura",
+ "0a2d4359a8": "Manejable",
+ "330b3c32e8": "disponible",
+ "e2532150ed": "automatizaciones",
+ "701515f010": "automatización"
+ },
+ "ExternalAutomationRunTable": {
+ "0ba9c0a95c": "Página de próxima ejecución",
+ "52d468a0b8": "Página de ejecución anterior",
+ "7475c0ce96": "de",
+ "be551397ca": "Estado",
+ "a813df9808": "Avance",
+ "d4b34feb66": "tiempo de ejecución",
+ "2d4388a908": "Corre",
+ "9c080765ff": "Aún no se han encontrado ejecuciones de Hermes.",
+ "8ea934cacf": "Cargando ejecuciones...",
+ "d5527d8fe7": "corre",
+ "872d032d05": "correr"
+ },
+ "HermesCronOutputView": {
+ "e27c716b43": "Inmediato",
+ "4557213074": "Respuesta",
+ "05affc68e3": "Error",
+ "88d48157fc": "por defecto"
+ },
+ "WorkspaceCombobox": {
+ "ee5b280eba": "No se encontraron espacios de trabajo.",
+ "8e9c8cc6b5": "Buscar espacios de trabajo...",
+ "66a0cd9628": "Seleccionar espacio de trabajo"
+ },
+ "automation": {
+ "templates": {
+ "37571fcb16": "Busque trabajos atascados, archivos generados obsoletos y validación local fallida.",
+ "8a0228bea3": "Verificación de cola por hora",
+ "3b7281c75f": "Escanee trabajos recientes y mencione los riesgos de corrección, UX y cobertura de pruebas.",
+ "6023075b27": "Revisión diaria de cambios",
+ "513401db93": "Prepare un resumen semanal del riesgo de liberación del estado actual del proyecto.",
+ "39ed39280a": "Preparación para el lanzamiento",
+ "a7fbd32ddb": "Verifique las dependencias, las pruebas fallidas y los cambios abiertos riesgosos todos los días de la semana.",
+ "b84757677d": "Auditoría de repositorios entre semana",
+ "repoHealth": {
+ "category": "Salud del repositorio",
+ "name": "Auditoría de repositorios entre semana",
+ "prompt": "Revisar el estado del repositorio. Verifique las actualizaciones de dependencia, las pruebas fallidas, el estado de pelusa/verificación de tipos y los cambios abiertos riesgosos. Resuma los hallazgos y sugiera la siguiente acción."
+ },
+ "releasePrep": {
+ "category": "Preparación de lanzamiento",
+ "name": "Revisión de preparación para el lanzamiento",
+ "prompt": "Prepare un resumen de preparación para el lanzamiento. Busque bloqueadores, cambios riesgosos no fusionados, validación faltante y lagunas en la documentación. Termine con una recomendación concisa de liberación/no liberación."
+ },
+ "recurringReview": {
+ "category": "Revisión recurrente",
+ "name": "Revisión diaria de cambios",
+ "prompt": "Revise los cambios recientes en este espacio de trabajo. Concéntrese en los riesgos de corrección, las regresiones de UX, las pruebas faltantes y las tareas de seguimiento. Mantenga el informe breve y práctico."
+ },
+ "maintenance": {
+ "category": "Mantenimiento",
+ "name": "Control de mantenimiento cada hora",
+ "prompt": "Compruebe si hay trabajos atascados, archivos generados obsoletos, validación fallida y cualquier cosa que necesite atención humana. Informe solo problemas procesables."
+ }
+ }
+ },
+ "external": {
+ "automation": {
+ "schedule": {
+ "display": {
+ "a8e92b815a": "Horario no disponible"
+ }
+ }
+ }
+ }
+ },
+ "agent": {
+ "AgentCombobox": {
+ "19522e25ee": "Administrar agentes",
+ "986f946354": "Terminal en blanco",
+ "579c768bde": "Ningún agente coincide con su búsqueda.",
+ "48c6a5a9b4": "Agentes de búsqueda...",
+ "9c6b59fe58": "Establecer como predeterminado",
+ "1b0d6965fa": "Valor predeterminado actual"
+ },
+ "AgentSettingsDialog": {
+ "50cdb57c03": "Administre agentes de IA, establezca un valor predeterminado y personalice comandos.",
+ "fc0268e4ed": "Agentes"
+ }
+ },
+ "activity": {
+ "ActivityPrototypePage": {
+ "cf780197a1": "Seleccione un agente para ver su actividad",
+ "e3db9892f6": "Aún no hay actividad.",
+ "1b633f5c1e": "Terminal de conexión...",
+ "8de7c5beaa": "Terminal no disponible",
+ "866083500b": "Arrastra para cambiar el tamaño",
+ "443690186e": "Cambiar el tamaño de la lista de hilos de actividad",
+ "7cd632006b": "Ninguna actividad de agente coincide con estos filtros.",
+ "a2b4437bfb": "{{value0}} actividad",
+ "023ff75afe": "Marcar todo como leído",
+ "f70e4bec47": "Modo compacto",
+ "a472a14700": "Más opciones",
+ "db8a1878b5": "Opciones de lista de hilos",
+ "d1a88df9a8": "Mostrar solo hilos no leídos",
+ "f6396e1f85": "Agente",
+ "b29191b3e0": "árbol de trabajo",
+ "8c3b621ddf": "Proyecto",
+ "4a3986b200": "Estado",
+ "770d458144": "Actividad del agente de grupo por",
+ "795cbf26e2": "Filtrar...",
+ "4616ea39fd": "Saltar al espacio de trabajo",
+ "59b131fbd9": "Marcar hilo como no leído",
+ "beb2c19173": "No leído",
+ "5651b216c6": "Proyecto desconocido",
+ "22b22034bc": "Terminal independiente no disponible en Actividad.",
+ "afdc2139a8": "Terminal de agente cerrada. Abra una nueva terminal en este espacio de trabajo para continuar."
+ },
+ "ActivityTitlebarControls": {
+ "f915168c8e": "no leído",
+ "d6a8de3934": "agentes",
+ "dc708f3eff": "Agentes cercanos"
+ }
+ },
+ "confirmation": {
+ "dialog": {
+ "8490e5d36a": "Confirmar",
+ "56f5c60e0c": "Cancelar"
+ }
+ }
+ },
+ "i18n": {
+ "hostedReview": {
+ "copy": {
+ "f0a4b8c2d1": "relaciones públicas",
+ "e9f3a7b1c0": "solicitud de extracción",
+ "d8e2f6a0b9": "Solicitud de extracción",
+ "c7d1e5f9a8": "GitHub",
+ "c4e8f1a2b9": "SEÑOR",
+ "b3d7e0f1a8": "solicitud de fusión",
+ "a2c6d9e0f7": "Solicitud de fusión",
+ "91b5c8d7e6": "GitLab"
+ }
+ }
+ }
+ }
+}
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
index d07fee65646..5ec82f9370e 100644
--- a/src/renderer/src/i18n/locales/ja.json
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -16,7 +16,8 @@
"english": "English",
"chinese": "中文(简体)",
"korean": "한국어",
- "japanese": "日本語"
+ "japanese": "日本語",
+ "spanish": "Español"
},
"statusBar": {
"claudeToggleDescription": "アクティブなワークスペースのClaude トークンとコストの使用状況を表示します。",
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 3087702d988..43d62cd9d26 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -16,7 +16,8 @@
"english": "English",
"chinese": "中文(简体)",
"korean": "한국어",
- "japanese": "日本語"
+ "japanese": "日本語",
+ "spanish": "Español"
},
"statusBar": {
"claudeToggleDescription": "활성 워크스페이스에 대한 Claude 토큰 및 비용 사용량을 표시합니다.",
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index 0196186018e..ca63204c284 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -16,7 +16,8 @@
"english": "English",
"chinese": "中文(简体)",
"korean": "한국어",
- "japanese": "日本語"
+ "japanese": "日本語",
+ "spanish": "Español"
},
"statusBar": {
"claudeToggleDescription": "显示活动工作区的 Claude Token 和成本使用情况。",
diff --git a/src/renderer/src/i18n/supported-languages.ts b/src/renderer/src/i18n/supported-languages.ts
index 02478005585..56d74726109 100644
--- a/src/renderer/src/i18n/supported-languages.ts
+++ b/src/renderer/src/i18n/supported-languages.ts
@@ -8,6 +8,7 @@ import {
UI_LANGUAGE_ENGLISH,
UI_LANGUAGE_JAPANESE,
UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SPANISH,
UI_LANGUAGE_SYSTEM,
type UiLanguage
} from '../../../shared/ui-language'
@@ -26,7 +27,8 @@ export const UI_LANGUAGE_CHOICES: UiLanguageChoice[] = [
{ value: UI_LANGUAGE_ENGLISH, labelKey: 'settings.appearance.language.english' },
{ value: UI_LANGUAGE_CHINESE, labelKey: 'settings.appearance.language.chinese' },
{ value: UI_LANGUAGE_KOREAN, labelKey: 'settings.appearance.language.korean' },
- { value: UI_LANGUAGE_JAPANESE, labelKey: 'settings.appearance.language.japanese' }
+ { value: UI_LANGUAGE_JAPANESE, labelKey: 'settings.appearance.language.japanese' },
+ { value: UI_LANGUAGE_SPANISH, labelKey: 'settings.appearance.language.spanish' }
]
const UI_LANGUAGE_CHOICE_FALLBACKS: Record = {
@@ -34,7 +36,8 @@ const UI_LANGUAGE_CHOICE_FALLBACKS: Record = {
[UI_LANGUAGE_ENGLISH]: 'English',
[UI_LANGUAGE_CHINESE]: '中文(简体)',
[UI_LANGUAGE_KOREAN]: '한국어',
- [UI_LANGUAGE_JAPANESE]: '日本語'
+ [UI_LANGUAGE_JAPANESE]: '日本語',
+ [UI_LANGUAGE_SPANISH]: 'Español'
}
export function getUiLanguageChoiceLabel(
diff --git a/src/shared/ui-language.test.ts b/src/shared/ui-language.test.ts
index 12424f17219..b27ab0c8312 100644
--- a/src/shared/ui-language.test.ts
+++ b/src/shared/ui-language.test.ts
@@ -5,6 +5,7 @@ import {
UI_LANGUAGE_ENGLISH,
UI_LANGUAGE_JAPANESE,
UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SPANISH,
UI_LANGUAGE_SYSTEM,
normalizeUiLanguage
} from './ui-language'
@@ -16,6 +17,7 @@ describe('normalizeUiLanguage', () => {
expect(normalizeUiLanguage(UI_LANGUAGE_CHINESE)).toBe('zh')
expect(normalizeUiLanguage(UI_LANGUAGE_KOREAN)).toBe('ko')
expect(normalizeUiLanguage(UI_LANGUAGE_JAPANESE)).toBe('ja')
+ expect(normalizeUiLanguage(UI_LANGUAGE_SPANISH)).toBe('es')
})
it('falls back unknown values to system', () => {
diff --git a/src/shared/ui-language.ts b/src/shared/ui-language.ts
index b77eae1b984..9a2f7a4a028 100644
--- a/src/shared/ui-language.ts
+++ b/src/shared/ui-language.ts
@@ -3,6 +3,7 @@ export const UI_LANGUAGE_ENGLISH = 'en'
export const UI_LANGUAGE_CHINESE = 'zh'
export const UI_LANGUAGE_KOREAN = 'ko'
export const UI_LANGUAGE_JAPANESE = 'ja'
+export const UI_LANGUAGE_SPANISH = 'es'
export type UiLanguage =
| typeof UI_LANGUAGE_SYSTEM
@@ -10,13 +11,15 @@ export type UiLanguage =
| typeof UI_LANGUAGE_CHINESE
| typeof UI_LANGUAGE_KOREAN
| typeof UI_LANGUAGE_JAPANESE
+ | typeof UI_LANGUAGE_SPANISH
const UI_LANGUAGE_VALUES = new Set([
UI_LANGUAGE_SYSTEM,
UI_LANGUAGE_ENGLISH,
UI_LANGUAGE_CHINESE,
UI_LANGUAGE_KOREAN,
- UI_LANGUAGE_JAPANESE
+ UI_LANGUAGE_JAPANESE,
+ UI_LANGUAGE_SPANISH
])
export function normalizeUiLanguage(value: unknown): UiLanguage {
diff --git a/src/shared/ui-locale.test.ts b/src/shared/ui-locale.test.ts
index fcb4fca9970..90ac28ab7d5 100644
--- a/src/shared/ui-locale.test.ts
+++ b/src/shared/ui-locale.test.ts
@@ -6,6 +6,7 @@ import {
UI_LANGUAGE_ENGLISH,
UI_LANGUAGE_JAPANESE,
UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SPANISH,
UI_LANGUAGE_SYSTEM
} from './ui-language'
@@ -27,6 +28,12 @@ describe('ui-locale', () => {
expect(normalizeSupportedUiLocale('ja')).toBe('ja')
})
+ it('normalizes Spanish locale prefixes', () => {
+ expect(normalizeSupportedUiLocale('es-ES')).toBe('es')
+ expect(normalizeSupportedUiLocale('es-MX')).toBe('es')
+ expect(normalizeSupportedUiLocale('es')).toBe('es')
+ })
+
it('falls back unsupported locales to English', () => {
expect(normalizeSupportedUiLocale('fr-FR')).toBe('en')
})
@@ -53,11 +60,16 @@ describe('ui-locale', () => {
expect(resolveUiLocale(UI_LANGUAGE_JAPANESE, 'en-US')).toBe('ja')
})
+ it('resolves explicit Spanish independently of system locale', () => {
+ expect(resolveUiLocale(UI_LANGUAGE_SPANISH, 'en-US')).toBe('es')
+ })
+
it('maps system locale to the closest supported locale', () => {
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'en-GB')).toBe('en')
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'zh-CN')).toBe('zh')
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'ko-KR')).toBe('ko')
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'ja-JP')).toBe('ja')
+ expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'es-MX')).toBe('es')
expect(resolveUiLocale(UI_LANGUAGE_SYSTEM, 'fr-FR')).toBe('en')
})
@@ -66,5 +78,6 @@ describe('ui-locale', () => {
expect(resolveRendererUiLocale(UI_LANGUAGE_CHINESE)).toBe('zh')
expect(resolveRendererUiLocale(UI_LANGUAGE_KOREAN)).toBe('ko')
expect(resolveRendererUiLocale(UI_LANGUAGE_JAPANESE)).toBe('ja')
+ expect(resolveRendererUiLocale(UI_LANGUAGE_SPANISH)).toBe('es')
})
})
diff --git a/src/shared/ui-locale.ts b/src/shared/ui-locale.ts
index c0cfd429f7c..4435ef14e5f 100644
--- a/src/shared/ui-locale.ts
+++ b/src/shared/ui-locale.ts
@@ -3,11 +3,12 @@ import {
UI_LANGUAGE_ENGLISH,
UI_LANGUAGE_JAPANESE,
UI_LANGUAGE_KOREAN,
+ UI_LANGUAGE_SPANISH,
UI_LANGUAGE_SYSTEM,
type UiLanguage
} from './ui-language'
-export const SUPPORTED_UI_LOCALES = ['en', 'zh', 'ko', 'ja'] as const
+export const SUPPORTED_UI_LOCALES = ['en', 'zh', 'ko', 'ja', 'es'] as const
export type SupportedUiLocale = (typeof SUPPORTED_UI_LOCALES)[number]
export const DEFAULT_UI_LOCALE: SupportedUiLocale = 'en'
@@ -46,6 +47,9 @@ export function resolveUiLocale(
if (language === UI_LANGUAGE_JAPANESE) {
return 'ja'
}
+ if (language === UI_LANGUAGE_SPANISH) {
+ return 'es'
+ }
return normalizeSupportedUiLocale(systemLocale)
}
From baa817aa5c516946309358a228f42268f912ed0d Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Wed, 10 Jun 2026 01:37:50 -0700
Subject: [PATCH 027/165] Fix localization in repository hooks and base ref
suggestion toast (#5089)
* Fix localization in base ref toast and custom hook description
- Localize the "commit"/"commits" plural nouns in the base ref toast.
- Translate missing suggestion toast strings for JA, KO, and ZH locales.
- Pass `{{artifact_url}}` as a literal template variable to translate
calls to prevent i18next from treating it as a dynamic placeholder.
* Fix localization reactivity in RepositoryHooksSection
Move static variables containing translation calls into helper functions
and subscribe to translation updates using useTranslation. This ensures
that localized options, descriptions, and error messages refresh
dynamically when the user changes the UI language.
---
.../settings/RepositoryHooksSection.tsx | 634 +++++++++++++-----
.../local-base-ref-suggestion-toast.tsx | 5 +-
src/renderer/src/i18n/locales/en.json | 10 +-
src/renderer/src/i18n/locales/ja.json | 22 +-
src/renderer/src/i18n/locales/ko.json | 22 +-
src/renderer/src/i18n/locales/zh.json | 24 +-
6 files changed, 536 insertions(+), 181 deletions(-)
diff --git a/src/renderer/src/components/settings/RepositoryHooksSection.tsx b/src/renderer/src/components/settings/RepositoryHooksSection.tsx
index fc6854e3441..a8ce20b354b 100644
--- a/src/renderer/src/components/settings/RepositoryHooksSection.tsx
+++ b/src/renderer/src/components/settings/RepositoryHooksSection.tsx
@@ -10,6 +10,7 @@ import type {
} from '../../../../shared/types'
import { AlertTriangle, ChevronRight, Plus } from 'lucide-react'
import { toast } from 'sonner'
+import { useTranslation } from 'react-i18next'
import { Button } from '../ui/button'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip'
import { SearchableSetting } from './SearchableSetting'
@@ -40,39 +41,8 @@ type HookSettingsPolicyDraft = Partial<
Pick
>
-const SETUP_RUN_POLICY_OPTIONS: PolicyOption[] = [
- { policy: 'ask', label: translate("auto.components.settings.RepositoryHooksSection.e03d9a8f38", "Ask every time"), description: translate("auto.components.settings.RepositoryHooksSection.90b1f50137", "Prompt before running setup.") },
- { policy: 'run-by-default', label: translate("auto.components.settings.RepositoryHooksSection.d3ef1ab247", "Run by default"), description: translate("auto.components.settings.RepositoryHooksSection.022ba10cf2", "Run setup automatically.") },
- {
- policy: 'skip-by-default',
- label: translate("auto.components.settings.RepositoryHooksSection.15debc1fd9", "Skip by default"),
- description: translate("auto.components.settings.RepositoryHooksSection.99e3264a49", "Only run setup when chosen.")
- }
-]
-
-const COMMAND_SOURCE_POLICY_OPTIONS: PolicyOption[] = [
- {
- policy: 'shared-only',
- label: translate("auto.components.settings.RepositoryHooksSection.d88b6ff88f", "orca.yaml only"),
- description: translate("auto.components.settings.RepositoryHooksSection.29397e8bbc", "Run only committed repo commands; ignore local commands.")
- },
- {
- policy: 'local-only',
- label: translate("auto.components.settings.RepositoryHooksSection.83dc78202a", "Local only"),
- description: translate("auto.components.settings.RepositoryHooksSection.0e8b2a520d", "Ignore orca.yaml; run only your local commands.")
- },
- {
- policy: 'run-both',
- label: translate("auto.components.settings.RepositoryHooksSection.8d6c56bff8", "Run both"),
- description: translate("auto.components.settings.RepositoryHooksSection.8561b0665f", "orca.yaml first, then your local commands.")
- }
-]
-
-const COMMAND_SOURCE_LABEL: Record = {
- 'shared-only': 'orca.yaml only',
- 'local-only': 'Local only',
- 'run-both': 'Run both'
-}
+// Why: this is a literal issue-command template token, not app data for i18next to fill.
+const ARTIFACT_URL_TEMPLATE_TOKEN = '{{artifact_url}}'
type LocalHookField = {
name: LocalHookName
@@ -81,38 +51,6 @@ type LocalHookField = {
placeholder: string
}
-const LOCAL_HOOK_FIELDS: LocalHookField[] = [
- {
- name: 'setup',
- label: translate("auto.components.settings.RepositoryHooksSection.52b31baf02", "Setup Script"),
- description:
- translate("auto.components.settings.RepositoryHooksSection.f0710e1c83", "Runs after a new worktree is created; install deps, copy env files, run migrations."),
- placeholder: translate("auto.components.settings.RepositoryHooksSection.a3fc966677", "# e.g. pnpm install cp \"$ORCA_ROOT_PATH/.env\" \"$ORCA_WORKTREE_PATH/.env\"")
- },
- {
- name: 'archive',
- label: translate("auto.components.settings.RepositoryHooksSection.9a100323ff", "Archive Script"),
- description: translate("auto.components.settings.RepositoryHooksSection.6f90ebe3fd", "Runs before a worktree is archived or removed."),
- placeholder: translate("auto.components.settings.RepositoryHooksSection.9b821fa19d", "# e.g. echo \"Cleaning up $ORCA_WORKSPACE_NAME\"")
- }
-]
-
-const ENV_VARS: readonly { name: string; description: string }[] = [
- {
- name: '$ORCA_ROOT_PATH',
- description:
- translate("auto.components.settings.RepositoryHooksSection.30952c4aa4", "Path to the main repo checkout. Useful for copying shared files, like .env, into a worktree.")
- },
- {
- name: '$ORCA_WORKTREE_PATH',
- description: translate("auto.components.settings.RepositoryHooksSection.54c73d88d0", "Path to the worktree being created. Setup commands run from this directory.")
- },
- {
- name: '$ORCA_WORKSPACE_NAME',
- description: translate("auto.components.settings.RepositoryHooksSection.0fa21e19ec", "Name of the workspace, usually based on the branch name.")
- }
-]
-
const EXAMPLE_TEMPLATE = `scripts:
setup: |
pnpm worktree:setup
@@ -169,44 +107,251 @@ export function getLocalCommandSourcePolicyNotice({
return { kind: 'checking' }
}
return hasSharedScript
- ? { kind: 'action', policy: 'run-both', label: translate("auto.components.settings.RepositoryHooksSection.8d6c56bff8", "Run both") }
- : { kind: 'action', policy: 'local-only', label: translate("auto.components.settings.RepositoryHooksSection.8bfe65fc60", "Use local commands") }
+ ? {
+ kind: 'action',
+ policy: 'run-both',
+ label: translate('auto.components.settings.RepositoryHooksSection.8d6c56bff8', 'Run both')
+ }
+ : {
+ kind: 'action',
+ policy: 'local-only',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.8bfe65fc60',
+ 'Use local commands'
+ )
+ }
}
-const YAML_STATE_STYLES: Record<
- string,
- { card: string; title: string; heading: string; description: string }
-> = {
+const YAML_STATE_STYLES: Record = {
loaded: {
card: 'border-emerald-500/20 bg-emerald-500/5',
- title: translate("auto.components.settings.RepositoryHooksSection.32f417fe17", "text-emerald-700 dark:text-emerald-300"),
- heading: 'Using `orca.yaml`',
- description:
- translate("auto.components.settings.RepositoryHooksSection.ca424ff135", "Shared hook and issue-automation defaults are defined in the repo and available to everyone who uses it.")
+ titleClassName: 'text-emerald-700 dark:text-emerald-300'
},
'update-available': {
card: 'border-amber-500/20 bg-amber-500/5',
- title: translate("auto.components.settings.RepositoryHooksSection.c90b858573", "text-amber-700 dark:text-amber-300"),
- heading: '`orca.yaml` could not be parsed',
- description:
- translate("auto.components.settings.RepositoryHooksSection.aba825233f", "The file contains configuration keys that this version of Orca does not recognize. You may need to update Orca, or check the file for typos.")
+ titleClassName: 'text-amber-700 dark:text-amber-300'
},
invalid: {
card: 'border-amber-500/20 bg-amber-500/5',
- title: translate("auto.components.settings.RepositoryHooksSection.c90b858573", "text-amber-700 dark:text-amber-300"),
- heading: '`orca.yaml` could not be parsed',
- description:
- translate("auto.components.settings.RepositoryHooksSection.0cc712b823", "The core configuration file exists in the repo root, but Orca could not parse the supported hook definitions yet.")
+ titleClassName: 'text-amber-700 dark:text-amber-300'
},
missing: {
card: 'border-border/50 bg-muted/20',
- title: translate("auto.components.settings.RepositoryHooksSection.925f9e0dc4", "text-foreground"),
- heading: 'No `orca.yaml` detected',
- description:
- translate("auto.components.settings.RepositoryHooksSection.b20c5df6ca", "Add an `orca.yaml` file to enable shared setup, archive, or issue-automation defaults for this repo. Example template:")
+ titleClassName: 'text-foreground'
}
}
+function getSetupRunPolicyOptions(): PolicyOption[] {
+ return [
+ {
+ policy: 'ask',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.e03d9a8f38',
+ 'Ask every time'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.90b1f50137',
+ 'Prompt before running setup.'
+ )
+ },
+ {
+ policy: 'run-by-default',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.d3ef1ab247',
+ 'Run by default'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.022ba10cf2',
+ 'Run setup automatically.'
+ )
+ },
+ {
+ policy: 'skip-by-default',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.15debc1fd9',
+ 'Skip by default'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.99e3264a49',
+ 'Only run setup when chosen.'
+ )
+ }
+ ]
+}
+
+function getCommandSourcePolicyOptions(): PolicyOption[] {
+ return [
+ {
+ policy: 'shared-only',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.d88b6ff88f',
+ 'orca.yaml only'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.29397e8bbc',
+ 'Run only committed repo commands; ignore local commands.'
+ )
+ },
+ {
+ policy: 'local-only',
+ label: translate('auto.components.settings.RepositoryHooksSection.83dc78202a', 'Local only'),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.0e8b2a520d',
+ 'Ignore orca.yaml; run only your local commands.'
+ )
+ },
+ {
+ policy: 'run-both',
+ label: translate('auto.components.settings.RepositoryHooksSection.8d6c56bff8', 'Run both'),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.8561b0665f',
+ 'orca.yaml first, then your local commands.'
+ )
+ }
+ ]
+}
+
+function getCommandSourceLabel(policy: HookCommandSourcePolicy): string {
+ switch (policy) {
+ case 'shared-only':
+ return translate(
+ 'auto.components.settings.RepositoryHooksSection.d88b6ff88f',
+ 'orca.yaml only'
+ )
+ case 'local-only':
+ return translate('auto.components.settings.RepositoryHooksSection.83dc78202a', 'Local only')
+ case 'run-both':
+ return translate('auto.components.settings.RepositoryHooksSection.8d6c56bff8', 'Run both')
+ }
+}
+
+function getLocalHookFields(): readonly [LocalHookField, LocalHookField] {
+ return [
+ {
+ name: 'setup',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.52b31baf02',
+ 'Setup Script'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.f0710e1c83',
+ 'Runs after a new worktree is created; install deps, copy env files, run migrations.'
+ ),
+ placeholder: translate(
+ 'auto.components.settings.RepositoryHooksSection.a3fc966677',
+ '# e.g. pnpm install cp "$ORCA_ROOT_PATH/.env" "$ORCA_WORKTREE_PATH/.env"'
+ )
+ },
+ {
+ name: 'archive',
+ label: translate(
+ 'auto.components.settings.RepositoryHooksSection.9a100323ff',
+ 'Archive Script'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.6f90ebe3fd',
+ 'Runs before a worktree is archived or removed.'
+ ),
+ placeholder: translate(
+ 'auto.components.settings.RepositoryHooksSection.9b821fa19d',
+ '# e.g. echo "Cleaning up $ORCA_WORKSPACE_NAME"'
+ )
+ }
+ ]
+}
+
+function getEnvVars(): readonly { name: string; description: string }[] {
+ return [
+ {
+ name: '$ORCA_ROOT_PATH',
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.30952c4aa4',
+ 'Path to the main repo checkout. Useful for copying shared files, like .env, into a worktree.'
+ )
+ },
+ {
+ name: '$ORCA_WORKTREE_PATH',
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.54c73d88d0',
+ 'Path to the worktree being created. Setup commands run from this directory.'
+ )
+ },
+ {
+ name: '$ORCA_WORKSPACE_NAME',
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.0fa21e19ec',
+ 'Name of the workspace, usually based on the branch name.'
+ )
+ }
+ ]
+}
+
+function getYamlStateCopy(yamlState: string): { heading: string; description: string } {
+ switch (yamlState) {
+ case 'loaded':
+ return {
+ heading: translate(
+ 'auto.components.settings.RepositoryHooksSection.56f9a4a1d0',
+ 'Using `orca.yaml`'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.ca424ff135',
+ 'Shared hook and issue-automation defaults are defined in the repo and available to everyone who uses it.'
+ )
+ }
+ case 'update-available':
+ return {
+ heading: translate(
+ 'auto.components.settings.RepositoryHooksSection.623e0c9f31',
+ '`orca.yaml` could not be parsed'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.aba825233f',
+ 'The file contains configuration keys that this version of Orca does not recognize. You may need to update Orca, or check the file for typos.'
+ )
+ }
+ case 'invalid':
+ return {
+ heading: translate(
+ 'auto.components.settings.RepositoryHooksSection.623e0c9f31',
+ '`orca.yaml` could not be parsed'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.0cc712b823',
+ 'The core configuration file exists in the repo root, but Orca could not parse the supported hook definitions yet.'
+ )
+ }
+ default:
+ return {
+ heading: translate(
+ 'auto.components.settings.RepositoryHooksSection.5a67e4793d',
+ 'No `orca.yaml` detected'
+ ),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.b20c5df6ca',
+ 'Add an `orca.yaml` file to enable shared setup, archive, or issue-automation defaults for this repo. Example template:'
+ )
+ }
+ }
+}
+
+function getParseErrorFixes(): readonly string[] {
+ return [
+ translate(
+ 'auto.components.settings.RepositoryHooksSection.07ba35bc68',
+ 'Check the indentation under `scripts:`. Hook keys should use two spaces, and command lines should use four.'
+ ),
+ translate(
+ 'auto.components.settings.RepositoryHooksSection.787ca433ef',
+ 'Define only the supported keys: `scripts`, `setup`, `archive`, and `issueCommand`.'
+ ),
+ translate(
+ 'auto.components.settings.RepositoryHooksSection.ecc73d9125',
+ 'Compare your file against the working template below and copy that shape if needed.'
+ )
+ ]
+}
+
function PolicyOptionGrid({
options,
selected,
@@ -291,7 +436,12 @@ function ExampleTemplateCard({
return (
- {translate("auto.components.settings.RepositoryHooksSection.175daba180", "Example")}{translate("auto.components.settings.RepositoryHooksSection.39da2ae12f", "orca.yaml")} {translate("auto.components.settings.RepositoryHooksSection.95a0411b3e", "template")}
+ {translate('auto.components.settings.RepositoryHooksSection.175daba180', 'Example')}
+
+ {translate('auto.components.settings.RepositoryHooksSection.39da2ae12f', 'orca.yaml')}
+ {' '}
+ {translate('auto.components.settings.RepositoryHooksSection.95a0411b3e', 'template')}
+
- {copiedTemplate ? translate("auto.components.settings.RepositoryHooksSection.3149964b66", "Copied") : translate("auto.components.settings.RepositoryHooksSection.da37d6f10e", "Copy")}
+ {copiedTemplate
+ ? translate('auto.components.settings.RepositoryHooksSection.3149964b66', 'Copied')
+ : translate('auto.components.settings.RepositoryHooksSection.da37d6f10e', 'Copy')}
{EXAMPLE_TEMPLATE}
@@ -321,13 +473,19 @@ function YamlScriptBlock({ content }: { content: string }): React.JSX.Element {
}
function EnvVarChips(): React.JSX.Element {
+ const envVars = getEnvVars()
+
return (
- {translate("auto.components.settings.RepositoryHooksSection.b2b06c7ce8", "Available environment variables (hover for details):")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.b2b06c7ce8',
+ 'Available environment variables (hover for details):'
+ )}
+
- {ENV_VARS.map(({ name, description }) => (
+ {envVars.map(({ name, description }) => (
- {isSaving ? translate("auto.components.settings.RepositoryHooksSection.81057d5f71", "Saving...") : translate("auto.components.settings.RepositoryHooksSection.2b6356e744", "Saved")}
+ {isSaving
+ ? translate('auto.components.settings.RepositoryHooksSection.81057d5f71', 'Saving...')
+ : translate('auto.components.settings.RepositoryHooksSection.2b6356e744', 'Saved')}
)
}
@@ -384,11 +544,21 @@ function LocalCommandSourceNotice({
- {translate("auto.components.settings.RepositoryHooksSection.5426ecbdcb", "Local scripts will not run")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.5426ecbdcb',
+ 'Local scripts will not run'
+ )}
+
{isChecking
- ? translate("auto.components.settings.RepositoryHooksSection.7f78e5eea6", "Local scripts are saved. Orca is still checking orca.yaml before it can recommend which script source to use.")
- : translate("auto.components.settings.RepositoryHooksSection.0ce113fd7b", "Local scripts are saved, but Script Source is set to orca.yaml only.")}
+ ? translate(
+ 'auto.components.settings.RepositoryHooksSection.7f78e5eea6',
+ 'Local scripts are saved. Orca is still checking orca.yaml before it can recommend which script source to use.'
+ )
+ : translate(
+ 'auto.components.settings.RepositoryHooksSection.0ce113fd7b',
+ 'Local scripts are saved, but Script Source is set to orca.yaml only.'
+ )}
@@ -404,7 +574,8 @@ function LocalCommandSourceNotice({
) : (
- {translate("auto.components.settings.RepositoryHooksSection.673a7fd10e", "Checking...")}
+ {translate('auto.components.settings.RepositoryHooksSection.673a7fd10e', 'Checking...')}
+
)}
)
@@ -480,11 +651,27 @@ function ScriptEditor({
- {translate("auto.components.settings.RepositoryHooksSection.39da2ae12f", "orca.yaml")}
- {translate("auto.components.settings.RepositoryHooksSection.f828e1de19", "- shared with your team")}
+ {translate('auto.components.settings.RepositoryHooksSection.39da2ae12f', 'orca.yaml')}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.f828e1de19',
+ '- shared with your team'
+ )}
+
- {translate("auto.components.settings.RepositoryHooksSection.b113344b6a", "Edit")}{translate("auto.components.settings.RepositoryHooksSection.39da2ae12f", "orca.yaml")} {translate("auto.components.settings.RepositoryHooksSection.7e4427b4a2", "to change.")}
+ {translate('auto.components.settings.RepositoryHooksSection.b113344b6a', 'Edit')}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.39da2ae12f',
+ 'orca.yaml'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.7e4427b4a2',
+ 'to change.'
+ )}
+
@@ -495,7 +682,13 @@ function ScriptEditor({
{hasShared ? (
- {translate("auto.components.settings.RepositoryHooksSection.2d03a514db", "local")}{translate("auto.components.settings.RepositoryHooksSection.40a446ae16", "- just for you, on this machine")}
+ {translate('auto.components.settings.RepositoryHooksSection.2d03a514db', 'local')}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.40a446ae16',
+ '- just for you, on this machine'
+ )}
+
) : (
@@ -513,7 +706,11 @@ function ScriptEditor({
className="w-full min-w-0 resize-y rounded-lg border border-input bg-muted/20 px-3 py-2 font-mono text-[12px] leading-[1.55] shadow-xs transition-[color,box-shadow] outline-none placeholder:italic placeholder:text-muted-foreground/60 focus-visible:border-ring focus-visible:bg-background focus-visible:ring-[3px] focus-visible:ring-ring/40"
/>
- {translate("auto.components.settings.RepositoryHooksSection.8c2893fae0", "Runs as a single shell script. Saved on this machine.")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.8c2893fae0',
+ 'Runs as a single shell script. Saved on this machine.'
+ )}
+
) : (
- {translate("auto.components.settings.RepositoryHooksSection.5d940bde5c", "Add local script")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.5d940bde5c',
+ 'Add local script'
+ )}
+
)}
)
@@ -541,6 +742,9 @@ export function RepositoryHooksSection({
onCopyTemplate,
onUpdateHookSettings
}: RepositoryHooksSectionProps): React.JSX.Element {
+ // Why: this component uses the lightweight translate() helper; subscribe here
+ // so render-time option/copy builders refresh when the UI language changes.
+ useTranslation()
const settings = useAppStore((s) => s.settings)
const settingsSearchQuery = useAppStore((s) => s.settingsSearchQuery)
const yamlState = yamlHooks
@@ -565,6 +769,11 @@ export function RepositoryHooksSection({
const selectedSetupRunPolicy: SetupRunPolicy =
hookSettingsDraft.setupRunPolicy ?? 'run-by-default'
+ const setupRunPolicyOptions = getSetupRunPolicyOptions()
+ const commandSourcePolicyOptions = getCommandSourcePolicyOptions()
+ const localHookFields = getLocalHookFields()
+ const yamlStateCopy = getYamlStateCopy(yamlState)
+ const parseErrorFixes = getParseErrorFixes()
const [issueCommandDraft, setIssueCommandDraft] = useState('')
const [hasSharedIssueCommand, setHasSharedIssueCommand] = useState(false)
@@ -754,16 +963,19 @@ export function RepositoryHooksSection({
const advancedMatchesSearch =
settingsSearchQuery.trim() !== '' &&
matchesSettingsSearch(settingsSearchQuery, {
- title: translate("auto.components.settings.RepositoryHooksSection.c9bc1bfd8f", "Advanced"),
- description: translate("auto.components.settings.RepositoryHooksSection.610d90fdbd", "Command source and orca.yaml details."),
+ title: translate('auto.components.settings.RepositoryHooksSection.c9bc1bfd8f', 'Advanced'),
+ description: translate(
+ 'auto.components.settings.RepositoryHooksSection.610d90fdbd',
+ 'Command source and orca.yaml details.'
+ ),
keywords: [
- translate("auto.components.settings.RepositoryHooksSection.c5a55a2d2e", "advanced"),
- translate("auto.components.settings.RepositoryHooksSection.4611b78617", "command source"),
- translate("auto.components.settings.RepositoryHooksSection.39da2ae12f", "orca.yaml"),
- translate("auto.components.settings.RepositoryHooksSection.d2b3016c20", "shared"),
- translate("auto.components.settings.RepositoryHooksSection.2d03a514db", "local"),
- translate("auto.components.settings.RepositoryHooksSection.0518758f38", "both"),
- translate("auto.components.settings.RepositoryHooksSection.fac13f8c1e", "authoritative")
+ translate('auto.components.settings.RepositoryHooksSection.c5a55a2d2e', 'advanced'),
+ translate('auto.components.settings.RepositoryHooksSection.4611b78617', 'command source'),
+ translate('auto.components.settings.RepositoryHooksSection.39da2ae12f', 'orca.yaml'),
+ translate('auto.components.settings.RepositoryHooksSection.d2b3016c20', 'shared'),
+ translate('auto.components.settings.RepositoryHooksSection.2d03a514db', 'local'),
+ translate('auto.components.settings.RepositoryHooksSection.0518758f38', 'both'),
+ translate('auto.components.settings.RepositoryHooksSection.fac13f8c1e', 'authoritative')
]
})
const [isAdvancedOpen, setIsAdvancedOpen] = useState(false)
@@ -771,14 +983,29 @@ export function RepositoryHooksSection({
return (
-
{translate("auto.components.settings.RepositoryHooksSection.ff082fe7c6", "Worktree Hooks")}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.ff082fe7c6',
+ 'Worktree Hooks'
+ )}
+
- {translate("auto.components.settings.RepositoryHooksSection.8567127a40", "Scripts that run when worktrees are created or archived. Local scripts are stored on this machine; `orca.yaml` scripts are shared with your team.")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.8567127a40',
+ 'Scripts that run when worktrees are created or archived. Local scripts are stored on this machine; `orca.yaml` scripts are shared with your team.'
+ )}
+
-
{translate("auto.components.settings.RepositoryHooksSection.793dcee97d", "When to run")}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.793dcee97d',
+ 'When to run'
+ )}
+
- {translate("auto.components.settings.RepositoryHooksSection.21fb607a87", "Default behavior when a new worktree is created.")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.21fb607a87',
+ 'Default behavior when a new worktree is created.'
+ )}
+
updateHookSettingsPolicyDraft({ setupRunPolicy: policy })}
/>
@@ -824,8 +1066,14 @@ export function RepositoryHooksSection({
-
{translate("auto.components.settings.RepositoryHooksSection.13394103bd", "Custom GitHub Issue Command")}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.13394103bd',
+ 'Custom GitHub Issue Command'
+ )}
+
- {translate("auto.components.settings.RepositoryHooksSection.b997331366", "Optional override. Use")}{' '}
- {translate("auto.components.settings.RepositoryHooksSection.c85c2c88a2", "{{artifact_url}}")} {translate("auto.components.settings.RepositoryHooksSection.70ad20f883", "for the linked issue or PR URL.")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.b997331366',
+ 'Optional override. Use'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.c85c2c88a2',
+ '{{artifact_url}}',
+ { artifact_url: ARTIFACT_URL_TEMPLATE_TOKEN }
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.70ad20f883',
+ 'for the linked issue or PR URL.'
+ )}
+
@@ -1343,14 +1484,23 @@ export default function GitLabItemDialog({
) : (
- {translate("auto.components.GitLabItemDialog.007423f585", "Diff content unavailable.")}
+ {translate(
+ 'auto.components.GitLabItemDialog.007423f585',
+ 'Diff content unavailable.'
+ )}
+
)}
))}
>
) : (
- {translate("auto.components.GitLabItemDialog.808b1ca1ba", "No changed files.")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.808b1ca1ba',
+ 'No changed files.'
+ )}
+
)}
) : null}
@@ -1376,7 +1526,12 @@ export default function GitLabItemDialog({
))}
) : (
- {translate("auto.components.GitLabItemDialog.f11e3e7675", "No pipeline runs for this MR.")}
+
+ {translate(
+ 'auto.components.GitLabItemDialog.f11e3e7675',
+ 'No pipeline runs for this MR.'
+ )}
+
)}
) : null}
@@ -1390,7 +1545,11 @@ export default function GitLabItemDialog({
updateCommentDraft(e.target.value)}
- placeholder={translate("auto.components.GitLabItemDialog.c08e1d5a57", "Comment on {{value0}}{{value1}}…", { value0: prefix, value1: item.number })}
+ placeholder={translate(
+ 'auto.components.GitLabItemDialog.c08e1d5a57',
+ 'Comment on {{value0}}{{value1}}…',
+ { value0: prefix, value1: item.number }
+ )}
rows={2}
disabled={commentSubmitting}
className="min-h-9 w-full resize-none rounded-md border border-input bg-transparent px-2.5 py-1.5 text-sm shadow-xs focus:border-ring focus:outline-none focus:ring-[3px] focus:ring-ring/50"
@@ -1414,7 +1573,8 @@ export default function GitLabItemDialog({
) : (
)}
- {translate("auto.components.GitLabItemDialog.84012fa8fb", "Comment")}
+ {translate('auto.components.GitLabItemDialog.84012fa8fb', 'Comment')}
+
@@ -1425,11 +1585,13 @@ export default function GitLabItemDialog({
className="gap-1.5"
>
- {translate("auto.components.GitLabItemDialog.f2e64d1c20", "Open in GitLab")}
+ {translate('auto.components.GitLabItemDialog.f2e64d1c20', 'Open in GitLab')}
+
{onCreateWorkspace ? (
onCreateWorkspace(item)}>
- {translate("auto.components.GitLabItemDialog.131865e231", "Create workspace")}
+ {translate('auto.components.GitLabItemDialog.131865e231', 'Create workspace')}
+
) : null}
{canMerge ? (
void handleMerge()}
>
- {actionInFlight === "merge" ? (
+ {actionInFlight === 'merge' ? (
) : null}
- {translate("auto.components.GitLabItemDialog.16b3412570", "Merge")}
+ {translate('auto.components.GitLabItemDialog.16b3412570', 'Merge')}
+
) : null}
{canClose ? (
void handleClose()}
>
- {actionInFlight === "close" ? (
+ {actionInFlight === 'close' ? (
) : null}
- {translate("auto.components.GitLabItemDialog.a199eb364b", "Close")}
+ {translate('auto.components.GitLabItemDialog.a199eb364b', 'Close')}
+
) : null}
{canReopen ? (
void handleReopen()}
>
- {actionInFlight === "reopen" ? (
+ {actionInFlight === 'reopen' ? (
) : null}
- {translate("auto.components.GitLabItemDialog.65e784c1f1", "Reopen")}
+ {translate('auto.components.GitLabItemDialog.65e784c1f1', 'Reopen')}
+
) : null}
diff --git a/src/renderer/src/components/JiraIssueWorkspace.tsx b/src/renderer/src/components/JiraIssueWorkspace.tsx
index 71859eba700..4be68a77b56 100644
--- a/src/renderer/src/components/JiraIssueWorkspace.tsx
+++ b/src/renderer/src/components/JiraIssueWorkspace.tsx
@@ -94,9 +94,17 @@ function jiraStatusClass(categoryKey: string): string {
async function copyTextToClipboard(text: string, label: string): Promise {
try {
await window.api.ui.writeClipboardText(text)
- toast.success(translate("auto.components.JiraIssueWorkspace.2ff69a3545", "{{value0}} copied", { value0: label }))
+ toast.success(
+ translate('auto.components.JiraIssueWorkspace.2ff69a3545', '{{value0}} copied', {
+ value0: label
+ })
+ )
} catch {
- toast.error(translate("auto.components.JiraIssueWorkspace.6c41a9bcea", "Failed to copy {{value0}}", { value0: label.toLowerCase() }))
+ toast.error(
+ translate('auto.components.JiraIssueWorkspace.6c41a9bcea', 'Failed to copy {{value0}}', {
+ value0: label.toLowerCase()
+ })
+ )
}
}
@@ -253,7 +261,14 @@ export default function JiraIssueWorkspace({
} catch (error) {
setFullIssue(previous)
patchJiraIssue(previous.key, previous)
- toast.error(error instanceof Error ? error.message : translate("auto.components.JiraIssueWorkspace.ea21952aa3", "Failed to update Jira issue."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.JiraIssueWorkspace.ea21952aa3',
+ 'Failed to update Jira issue.'
+ )
+ )
} finally {
setPendingField(null)
}
@@ -308,7 +323,11 @@ export default function JiraIssueWorkspace({
setComments((prev) => [...prev, comment])
setCommentDraft('')
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.JiraIssueWorkspace.fa132c8aed", "Failed to add comment."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate('auto.components.JiraIssueWorkspace.fa132c8aed', 'Failed to add comment.')
+ )
} finally {
setCommentSubmitting(false)
}
@@ -320,27 +339,30 @@ export default function JiraIssueWorkspace({
}
return [
{
- label: translate("auto.components.JiraIssueWorkspace.69da9a208c", "Open in Jira"),
+ label: translate('auto.components.JiraIssueWorkspace.69da9a208c', 'Open in Jira'),
icon: ExternalLink,
action: () => window.api.shell.openUrl(displayed.url)
},
{
- label: translate("auto.components.JiraIssueWorkspace.779bb91ee0", "Copy URL"),
+ label: translate('auto.components.JiraIssueWorkspace.779bb91ee0', 'Copy URL'),
icon: Clipboard,
action: () => void copyTextToClipboard(displayed.url, 'URL')
},
{
- label: translate("auto.components.JiraIssueWorkspace.38839801e8", "Copy key"),
+ label: translate('auto.components.JiraIssueWorkspace.38839801e8', 'Copy key'),
icon: Clipboard,
action: () => void copyTextToClipboard(displayed.key, 'Key')
},
{
- label: translate("auto.components.JiraIssueWorkspace.80efa101c5", "Copy suggested branch name"),
+ label: translate(
+ 'auto.components.JiraIssueWorkspace.80efa101c5',
+ 'Copy suggested branch name'
+ ),
icon: GitBranch,
action: () => void copyTextToClipboard(buildJiraBranchName(displayed), 'Branch name')
},
{
- label: translate("auto.components.JiraIssueWorkspace.0cc62bd690", "Copy prompt"),
+ label: translate('auto.components.JiraIssueWorkspace.0cc62bd690', 'Copy prompt'),
icon: Clipboard,
action: () => void copyTextToClipboard(buildJiraPrompt(displayed), 'Prompt')
}
@@ -356,11 +378,18 @@ export default function JiraIssueWorkspace({
onOpenAutoFocus={(event) => event.preventDefault()}
>
- {displayed?.title ?? translate("auto.components.JiraIssueWorkspace.ef21405c6d", "Jira issue")}
+
+ {displayed?.title ??
+ translate('auto.components.JiraIssueWorkspace.ef21405c6d', 'Jira issue')}
+
- {translate("auto.components.JiraIssueWorkspace.857bd2f88f", "Preview, edit, and start work from the selected issue.")}
+ {translate(
+ 'auto.components.JiraIssueWorkspace.857bd2f88f',
+ 'Preview, edit, and start work from the selected issue.'
+ )}
+
{displayed ? (
@@ -384,7 +413,8 @@ export default function JiraIssueWorkspace({
className="hidden shrink-0 gap-2 sm:inline-flex"
size="sm"
>
- {translate("auto.components.JiraIssueWorkspace.2441be6f9f", "Start workspace")}
+ {translate('auto.components.JiraIssueWorkspace.2441be6f9f', 'Start workspace')}
+
@@ -393,13 +423,17 @@ export default function JiraIssueWorkspace({
size="icon-sm"
className="shrink-0"
onClick={onClose}
- aria-label={translate("auto.components.JiraIssueWorkspace.76513c7898", "Close Jira issue preview")}
+ aria-label={translate(
+ 'auto.components.JiraIssueWorkspace.76513c7898',
+ 'Close Jira issue preview'
+ )}
>
- {translate("auto.components.JiraIssueWorkspace.7a96985ca0", "Close")}
+ {translate('auto.components.JiraIssueWorkspace.7a96985ca0', 'Close')}
+
@@ -416,7 +450,7 @@ export default function JiraIssueWorkspace({
)}
>
{displayed.status.name}
- {pendingField === "transition" ? (
+ {pendingField === 'transition' ? (
) : null}
@@ -451,8 +485,9 @@ export default function JiraIssueWorkspace({
disabled={pendingField === 'priority'}
className="rounded-md px-1.5 py-0.5 text-[11px] text-muted-foreground transition hover:bg-muted/40 disabled:opacity-50"
>
- {displayed.priority?.name ?? translate("auto.components.JiraIssueWorkspace.51bed73f88", "No priority")}
- {pendingField === "priority" ? (
+ {displayed.priority?.name ??
+ translate('auto.components.JiraIssueWorkspace.51bed73f88', 'No priority')}
+ {pendingField === 'priority' ? (
) : null}
@@ -468,7 +503,8 @@ export default function JiraIssueWorkspace({
}
className="flex w-full items-center rounded-sm px-2 py-1.5 text-left text-[12px] hover:bg-accent"
>
- {translate("auto.components.JiraIssueWorkspace.51bed73f88", "No priority")}
+ {translate('auto.components.JiraIssueWorkspace.51bed73f88', 'No priority')}
+
{priorities.map((priority) => (
- {displayed.assignee?.displayName ?? translate("auto.components.JiraIssueWorkspace.54649eaeab", "+ Assignee")}
- {pendingField === "assignee" ? (
+ {displayed.assignee?.displayName ??
+ translate('auto.components.JiraIssueWorkspace.54649eaeab', '+ Assignee')}
+ {pendingField === 'assignee' ? (
) : null}
@@ -512,7 +549,8 @@ export default function JiraIssueWorkspace({
}
className="flex w-full items-center rounded-sm px-2 py-1.5 text-left text-[12px] hover:bg-accent"
>
- {translate("auto.components.JiraIssueWorkspace.0b6b5646ed", "Unassigned")}
+ {translate('auto.components.JiraIssueWorkspace.0b6b5646ed', 'Unassigned')}
+
{users.map((user) => (
-
{translate("auto.components.JiraIssueWorkspace.444865b4a8", "Title")}
+
+ {translate('auto.components.JiraIssueWorkspace.444865b4a8', 'Title')}
+
- {pendingField === "title" ? (
+ {pendingField === 'title' ? (
) : (
@@ -567,12 +607,16 @@ export default function JiraIssueWorkspace({
- {translate("auto.components.JiraIssueWorkspace.aee97b6913", "Labels")}
+ {translate('auto.components.JiraIssueWorkspace.aee97b6913', 'Labels')}
+
setLabelsDraft(event.target.value)}
- placeholder={translate("auto.components.JiraIssueWorkspace.0f3c07a901", "backend, bug")}
+ placeholder={translate(
+ 'auto.components.JiraIssueWorkspace.0f3c07a901',
+ 'backend, bug'
+ )}
className="h-8 text-xs"
/>
- {pendingField === "labels" ? (
+ {pendingField === 'labels' ? (
) : (
@@ -598,7 +642,9 @@ export default function JiraIssueWorkspace({
{displayed.issueType.name}
- {displayed.project.key} · {displayed.assignee?.displayName ?? translate("auto.components.JiraIssueWorkspace.0b6b5646ed", "Unassigned")}
+ {displayed.project.key} ·{' '}
+ {displayed.assignee?.displayName ??
+ translate('auto.components.JiraIssueWorkspace.0b6b5646ed', 'Unassigned')}
{displayed.description?.trim() ? (
@@ -607,14 +653,21 @@ export default function JiraIssueWorkspace({
className="text-[14px] leading-relaxed"
/>
) : (
-
{translate("auto.components.JiraIssueWorkspace.c4889a47e4", "No description provided.")}
+
+ {translate(
+ 'auto.components.JiraIssueWorkspace.c4889a47e4',
+ 'No description provided.'
+ )}
+
)}
- {translate("auto.components.JiraIssueWorkspace.9a980b06b9", "Comments")}
+
+ {translate('auto.components.JiraIssueWorkspace.9a980b06b9', 'Comments')}
+
{comments.length > 0 ? (
{comments.length}
) : null}
@@ -632,7 +685,8 @@ export default function JiraIssueWorkspace({
) : (
)}
- {translate("auto.components.JiraIssueWorkspace.5cd09beaf9", "Retry")}
+ {translate('auto.components.JiraIssueWorkspace.5cd09beaf9', 'Retry')}
+
) : null}
{commentsError ? (
@@ -644,7 +698,12 @@ export default function JiraIssueWorkspace({
) : comments.length === 0 ? (
- {translate("auto.components.JiraIssueWorkspace.9178090e26", "No comments yet.")}
+
+ {translate(
+ 'auto.components.JiraIssueWorkspace.9178090e26',
+ 'No comments yet.'
+ )}
+
) : (
{comments.map((comment) => (
@@ -661,7 +720,11 @@ export default function JiraIssueWorkspace({
/>
) : null}
- {comment.user?.displayName ?? translate("auto.components.JiraIssueWorkspace.666cfdd835", "Unknown")}
+ {comment.user?.displayName ??
+ translate(
+ 'auto.components.JiraIssueWorkspace.666cfdd835',
+ 'Unknown'
+ )}
{formatRelativeTime(comment.createdAt)}
@@ -685,7 +748,8 @@ export default function JiraIssueWorkspace({
onClick={() => onUse(displayed)}
className="mb-3 w-full justify-center gap-2 sm:hidden"
>
- {translate("auto.components.JiraIssueWorkspace.2441be6f9f", "Start workspace")}
+ {translate('auto.components.JiraIssueWorkspace.2441be6f9f', 'Start workspace')}
+
{actionItems.map((item) => {
@@ -717,7 +781,10 @@ export default function JiraIssueWorkspace({
setCommentDraft(event.target.value)}
- placeholder={translate("auto.components.JiraIssueWorkspace.a585fd204e", "Add a Jira comment...")}
+ placeholder={translate(
+ 'auto.components.JiraIssueWorkspace.a585fd204e',
+ 'Add a Jira comment...'
+ )}
rows={2}
disabled={commentSubmitting}
className="min-h-10 flex-1 resize-none rounded-md border border-input bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
@@ -732,7 +799,8 @@ export default function JiraIssueWorkspace({
) : (
)}
- {translate("auto.components.JiraIssueWorkspace.b0b92666c9", "Comment")}
+ {translate('auto.components.JiraIssueWorkspace.b0b92666c9', 'Comment')}
+
diff --git a/src/renderer/src/components/LinearIssueMarkdownDescriptionEditor.tsx b/src/renderer/src/components/LinearIssueMarkdownDescriptionEditor.tsx
index eb754d0576a..dc03f202875 100644
--- a/src/renderer/src/components/LinearIssueMarkdownDescriptionEditor.tsx
+++ b/src/renderer/src/components/LinearIssueMarkdownDescriptionEditor.tsx
@@ -45,7 +45,10 @@ type LinearIssueMarkdownToolbarButtonProps = {
const linearIssueMarkdownExtensions = [
...createRichMarkdownExtensions(),
Placeholder.configure({
- placeholder: translate("auto.components.LinearIssueMarkdownDescriptionEditor.4f2fddc2b7", "No description provided.")
+ placeholder: translate(
+ 'auto.components.LinearIssueMarkdownDescriptionEditor.4f2fddc2b7',
+ 'No description provided.'
+ )
})
]
@@ -91,7 +94,10 @@ function applyLinearIssueLink(editor: Editor | null): void {
}
const previousHref = editor.getAttributes('link').href as string | undefined
- const href = window.prompt(translate("auto.components.LinearIssueMarkdownDescriptionEditor.5c16ec8f14", "Link URL"), previousHref ?? '')
+ const href = window.prompt(
+ translate('auto.components.LinearIssueMarkdownDescriptionEditor.5c16ec8f14', 'Link URL'),
+ previousHref ?? ''
+ )
if (href === null) {
editor.chain().focus().run()
return
@@ -124,16 +130,28 @@ function LinearIssueMarkdownToolbar({
)
return (
-
+
runCommand((nextEditor) => nextEditor.chain().focus().setParagraph().run())}
>
@@ -143,7 +161,10 @@ function LinearIssueMarkdownToolbar({
@@ -154,7 +175,7 @@ function LinearIssueMarkdownToolbar({
runCommand((nextEditor) => nextEditor.chain().focus().toggleBold().run())}
@@ -162,7 +183,10 @@ function LinearIssueMarkdownToolbar({
runCommand((nextEditor) => nextEditor.chain().focus().toggleItalic().run())}
@@ -170,7 +194,10 @@ function LinearIssueMarkdownToolbar({
runCommand((nextEditor) => nextEditor.chain().focus().toggleStrike().run())}
@@ -178,7 +205,10 @@ function LinearIssueMarkdownToolbar({
runCommand((nextEditor) => nextEditor.chain().focus().toggleCode().run())}
@@ -187,7 +217,10 @@ function LinearIssueMarkdownToolbar({
@@ -197,7 +230,10 @@ function LinearIssueMarkdownToolbar({
@@ -207,7 +243,10 @@ function LinearIssueMarkdownToolbar({
@@ -218,7 +257,10 @@ function LinearIssueMarkdownToolbar({
@@ -228,7 +270,14 @@ function LinearIssueMarkdownToolbar({
runCommand(applyLinearIssueLink)}
@@ -333,10 +382,14 @@ export function LinearIssueMarkdownDescriptionEditor({
{submitShortcutLabel}
- {translate("auto.components.LinearIssueMarkdownDescriptionEditor.a7301a11f3", "save")}
+
+ {translate('auto.components.LinearIssueMarkdownDescriptionEditor.a7301a11f3', 'save')}
+
·
- {translate("auto.components.LinearIssueMarkdownDescriptionEditor.d9c47069ef", "Markdown")}
+
+ {translate('auto.components.LinearIssueMarkdownDescriptionEditor.d9c47069ef', 'Markdown')}
+
{disabled ? (
diff --git a/src/renderer/src/components/LinearIssueTextEditor.tsx b/src/renderer/src/components/LinearIssueTextEditor.tsx
index a2ce53a3020..3e97489e8df 100644
--- a/src/renderer/src/components/LinearIssueTextEditor.tsx
+++ b/src/renderer/src/components/LinearIssueTextEditor.tsx
@@ -97,7 +97,9 @@ export function LinearIssueTextEditor({
})
if (savePlan.kind === 'empty-title') {
updateTitleDraft(issue.title)
- toast.error(translate("auto.components.LinearIssueTextEditor.1e08a1ec80", "Title is required"))
+ toast.error(
+ translate('auto.components.LinearIssueTextEditor.1e08a1ec80', 'Title is required')
+ )
return
}
if (savePlan.kind === 'unchanged') {
@@ -130,7 +132,15 @@ export function LinearIssueTextEditor({
updateDescriptionDraft(issue.description ?? '')
}
}
- toast.error(error instanceof Error ? error.message : translate("auto.components.LinearIssueTextEditor.e8ff595db3", "Failed to update {{value0}}", { value0: field }))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.LinearIssueTextEditor.e8ff595db3',
+ 'Failed to update {{value0}}',
+ { value0: field }
+ )
+ )
} finally {
if (mountedRef.current && lastIssueIdRef.current === issue.id) {
setSavingField(null)
@@ -190,7 +200,7 @@ export function LinearIssueTextEditor({
: 'text-[15px] font-semibold leading-tight'
return (
- {fields !== "description" ? (
+ {fields !== 'description' ? (
↵
- {translate("auto.components.LinearIssueTextEditor.947ba2d6f4", "to save")}
+ {translate('auto.components.LinearIssueTextEditor.947ba2d6f4', 'to save')}
- {savingField === "title" ? (
+ {savingField === 'title' ? (
) : null}
) : null}
- {fields !== "title" ? (
+ {fields !== 'title' ? (
{
try {
await window.api.ui.writeClipboardText(text)
- toast.success(translate("auto.components.LinearIssueWorkspace.7835483c43", "{{value0}} copied", { value0: label }))
+ toast.success(
+ translate('auto.components.LinearIssueWorkspace.7835483c43', '{{value0}} copied', {
+ value0: label
+ })
+ )
} catch {
- toast.error(translate("auto.components.LinearIssueWorkspace.9bcbaa2737", "Failed to copy {{value0}}", { value0: label.toLowerCase() }))
+ toast.error(
+ translate('auto.components.LinearIssueWorkspace.9bcbaa2737', 'Failed to copy {{value0}}', {
+ value0: label.toLowerCase()
+ })
+ )
}
}
@@ -144,11 +152,20 @@ function LinearIssueSubIssueButton({
if (fullIssue) {
onOpenIssue(fullIssue)
} else {
- toast.error(translate("auto.components.LinearIssueWorkspace.9a1317cdd3", "Failed to load sub-issue"))
+ toast.error(
+ translate('auto.components.LinearIssueWorkspace.9a1317cdd3', 'Failed to load sub-issue')
+ )
}
} catch (error) {
if (mountedRef.current) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.LinearIssueWorkspace.9a1317cdd3", "Failed to load sub-issue"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.LinearIssueWorkspace.9a1317cdd3',
+ 'Failed to load sub-issue'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -190,14 +207,25 @@ function LinearIssueSubIssueButton({
}
return { issueId: issue.id, subIssues: [...currentSubIssues, child] }
})
- toast.success(translate("auto.components.LinearIssueWorkspace.aeed19d003", "Created {{value0}}", { value0: result.identifier }))
+ toast.success(
+ translate('auto.components.LinearIssueWorkspace.aeed19d003', 'Created {{value0}}', {
+ value0: result.identifier
+ })
+ )
setTitle('')
setOpen(false)
} else {
toast.error(result.error)
}
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.LinearIssueWorkspace.b25e453c9d", "Failed to create sub-issue"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.LinearIssueWorkspace.b25e453c9d',
+ 'Failed to create sub-issue'
+ )
+ )
} finally {
setSubmitting(false)
}
@@ -242,7 +270,9 @@ function LinearIssueSubIssueButton({
className="flex h-9 items-center gap-2 rounded-md px-1 text-sm font-medium text-muted-foreground transition hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.LinearIssueWorkspace.8c55d6696a", "Add sub-issues")}
+
+ {translate('auto.components.LinearIssueWorkspace.8c55d6696a', 'Add sub-issues')}
+
@@ -256,7 +286,10 @@ function LinearIssueSubIssueButton({
void handleCreate()
}
}}
- placeholder={translate("auto.components.LinearIssueWorkspace.c182e02de5", "Sub-issue title")}
+ placeholder={translate(
+ 'auto.components.LinearIssueWorkspace.c182e02de5',
+ 'Sub-issue title'
+ )}
className="h-9 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus-visible:ring-1 focus-visible:ring-ring"
/>
@@ -266,7 +299,8 @@ function LinearIssueSubIssueButton({
disabled={!title.trim() || submitting}
>
{submitting ? : null}
- {translate("auto.components.LinearIssueWorkspace.42589845bc", "Create")}
+ {translate('auto.components.LinearIssueWorkspace.42589845bc', 'Create')}
+
@@ -305,7 +339,14 @@ function LinearIssueSidebarProjectCard({
})
.catch((error) => {
if (!cancelled) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.LinearIssueWorkspace.38b80780c2", "Failed to load projects"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.LinearIssueWorkspace.38b80780c2',
+ 'Failed to load projects'
+ )
+ )
}
})
.finally(() => {
@@ -333,13 +374,22 @@ function LinearIssueSidebarProjectCard({
if (result.ok) {
onProjectChanged(project)
patchLinearIssue(issue.id, { project })
- toast.success(translate("auto.components.LinearIssueWorkspace.f9d4ef9807", "Project updated"))
+ toast.success(
+ translate('auto.components.LinearIssueWorkspace.f9d4ef9807', 'Project updated')
+ )
setOpen(false)
} else {
toast.error(result.error)
}
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.LinearIssueWorkspace.8b5b593053", "Failed to update project"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.LinearIssueWorkspace.8b5b593053',
+ 'Failed to update project'
+ )
+ )
} finally {
setSavingProjectId(null)
}
@@ -350,7 +400,7 @@ function LinearIssueSidebarProjectCard({
return (
- {translate("auto.components.LinearIssueWorkspace.b51276c8d6", "Project")}
+ {translate('auto.components.LinearIssueWorkspace.b51276c8d6', 'Project')}
@@ -361,7 +411,8 @@ function LinearIssueSidebarProjectCard({
>
- {issue.project?.name ?? translate("auto.components.LinearIssueWorkspace.519c3587f3", "Add to project")}
+ {issue.project?.name ??
+ translate('auto.components.LinearIssueWorkspace.519c3587f3', 'Add to project')}
@@ -371,14 +422,18 @@ function LinearIssueSidebarProjectCard({
setQuery(event.target.value)}
- placeholder={translate("auto.components.LinearIssueWorkspace.db3f269d98", "Search projects")}
+ placeholder={translate(
+ 'auto.components.LinearIssueWorkspace.db3f269d98',
+ 'Search projects'
+ )}
className="h-8 w-full rounded-md border border-input bg-background px-2 text-sm outline-none focus-visible:ring-1 focus-visible:ring-ring"
/>
{loading ? (
- {translate("auto.components.LinearIssueWorkspace.937ba6ad9a", "Loading projects")}
+ {translate('auto.components.LinearIssueWorkspace.937ba6ad9a', 'Loading projects')}
+
) : projects.length > 0 ? (
projects.map((project) => (
- {query.trim() ? translate("auto.components.LinearIssueWorkspace.c11b4e3cc2", "No projects found.") : translate("auto.components.LinearIssueWorkspace.76ffd3c937", "Search for a project to add.")}
+ {query.trim()
+ ? translate(
+ 'auto.components.LinearIssueWorkspace.c11b4e3cc2',
+ 'No projects found.'
+ )
+ : translate(
+ 'auto.components.LinearIssueWorkspace.76ffd3c937',
+ 'Search for a project to add.'
+ )}
)}
@@ -585,23 +648,26 @@ export default function LinearIssueWorkspace({
}
return [
{
- label: translate("auto.components.LinearIssueWorkspace.9a9a884236", "Copy URL"),
+ label: translate('auto.components.LinearIssueWorkspace.9a9a884236', 'Copy URL'),
icon: Clipboard,
action: () => void copyTextToClipboard(displayed.url, 'URL')
},
{
- label: translate("auto.components.LinearIssueWorkspace.30c1242f3a", "Copy identifier"),
+ label: translate('auto.components.LinearIssueWorkspace.30c1242f3a', 'Copy identifier'),
icon: Clipboard,
action: () => void copyTextToClipboard(displayed.identifier, 'Identifier')
},
{
- label: translate("auto.components.LinearIssueWorkspace.5d670ec8dc", "Copy suggested branch name"),
+ label: translate(
+ 'auto.components.LinearIssueWorkspace.5d670ec8dc',
+ 'Copy suggested branch name'
+ ),
icon: GitBranch,
action: () =>
void copyTextToClipboard(buildLinearIssueBranchName(displayed), 'Suggested branch name')
},
{
- label: translate("auto.components.LinearIssueWorkspace.f6c6381593", "Copy prompt"),
+ label: translate('auto.components.LinearIssueWorkspace.f6c6381593', 'Copy prompt'),
icon: Clipboard,
action: () => {
const renderedText = buildLinearIssueContextSnapshot(displayed, comments)
@@ -621,7 +687,7 @@ export default function LinearIssueWorkspace({
- {variant === "page" ? (
+ {variant === 'page' ? (
- {displayed.workspaceName ?? translate("auto.components.LinearIssueWorkspace.65239a714b", "Linear")}
+ {displayed.workspaceName ??
+ translate('auto.components.LinearIssueWorkspace.65239a714b', 'Linear')}
-
{translate("auto.components.LinearIssueWorkspace.f63ef94ea8", "Issues")}
+
+ {translate('auto.components.LinearIssueWorkspace.f63ef94ea8', 'Issues')}
+
{displayed.identifier}
{displayed.title}
@@ -653,13 +722,17 @@ export default function LinearIssueWorkspace({
variant="ghost"
size="icon-sm"
onClick={() => void copyTextToClipboard(displayed.url, 'URL')}
- aria-label={translate("auto.components.LinearIssueWorkspace.97c19a84f1", "Copy Linear URL")}
+ aria-label={translate(
+ 'auto.components.LinearIssueWorkspace.97c19a84f1',
+ 'Copy Linear URL'
+ )}
>
- {translate("auto.components.LinearIssueWorkspace.9a9a884236", "Copy URL")}
+ {translate('auto.components.LinearIssueWorkspace.9a9a884236', 'Copy URL')}
+
@@ -667,13 +740,17 @@ export default function LinearIssueWorkspace({
variant="ghost"
size="icon-sm"
onClick={() => void copyTextToClipboard(displayed.identifier, 'Identifier')}
- aria-label={translate("auto.components.LinearIssueWorkspace.9e3c49beb8", "Copy issue identifier")}
+ aria-label={translate(
+ 'auto.components.LinearIssueWorkspace.9e3c49beb8',
+ 'Copy issue identifier'
+ )}
>
- {translate("auto.components.LinearIssueWorkspace.30c1242f3a", "Copy identifier")}
+ {translate('auto.components.LinearIssueWorkspace.30c1242f3a', 'Copy identifier')}
+
@@ -681,28 +758,36 @@ export default function LinearIssueWorkspace({
variant="ghost"
size="icon-sm"
onClick={handleUseIssue}
- aria-label={translate("auto.components.LinearIssueWorkspace.30a7f56c0a", "Start workspace from issue")}
+ aria-label={translate(
+ 'auto.components.LinearIssueWorkspace.30a7f56c0a',
+ 'Start workspace from issue'
+ )}
>
- {translate("auto.components.LinearIssueWorkspace.e1e0a9bca9", "Start workspace")}
+ {translate('auto.components.LinearIssueWorkspace.e1e0a9bca9', 'Start workspace')}
+
- {variant === "sheet" ? (
+ {variant === 'sheet' ? (
- {translate("auto.components.LinearIssueWorkspace.df4c86ed12", "Close")}
+ {translate('auto.components.LinearIssueWorkspace.df4c86ed12', 'Close')}
+
) : null}
@@ -717,7 +802,9 @@ export default function LinearIssueWorkspace({
-
{translate("auto.components.LinearIssueWorkspace.543970c87a", "Activity")}
+
+ {translate('auto.components.LinearIssueWorkspace.543970c87a', 'Activity')}
+
- {displayed.assignee?.displayName ?? translate("auto.components.LinearIssueWorkspace.8a33c85e9c", "Someone")} {translate("auto.components.LinearIssueWorkspace.fabbd3f974", "updated the issue ·")}{' '}
+ {displayed.assignee?.displayName ??
+ translate('auto.components.LinearIssueWorkspace.8a33c85e9c', 'Someone')}{' '}
+ {translate(
+ 'auto.components.LinearIssueWorkspace.fabbd3f974',
+ 'updated the issue ·'
+ )}{' '}
{formatLinearIssueRelativeTime(displayed.updatedAt)}
@@ -754,7 +846,8 @@ export default function LinearIssueWorkspace({
) : (
)}
- {translate("auto.components.LinearIssueWorkspace.b0eac92d85", "Retry")}
+ {translate('auto.components.LinearIssueWorkspace.b0eac92d85', 'Retry')}
+
) : null}
@@ -774,7 +867,11 @@ export default function LinearIssueWorkspace({
- {comment.user?.displayName ?? translate("auto.components.LinearIssueWorkspace.ca8778c124", "Unknown")}
+ {comment.user?.displayName ??
+ translate(
+ 'auto.components.LinearIssueWorkspace.ca8778c124',
+ 'Unknown'
+ )}
{formatLinearIssueRelativeTime(comment.createdAt)}
@@ -816,7 +913,9 @@ export default function LinearIssueWorkspace({
/>
- {translate("auto.components.LinearIssueWorkspace.c23e79e5c0", "Actions")}
+
+ {translate('auto.components.LinearIssueWorkspace.c23e79e5c0', 'Actions')}
+
@@ -867,11 +966,18 @@ export default function LinearIssueWorkspace({
}}
>
- {displayed?.title ?? translate("auto.components.LinearIssueWorkspace.61f424f8ca", "Linear issue")}
+
+ {displayed?.title ??
+ translate('auto.components.LinearIssueWorkspace.61f424f8ca', 'Linear issue')}
+
- {translate("auto.components.LinearIssueWorkspace.ad5dec37b7", "Preview, edit, and start work from the selected issue.")}
+ {translate(
+ 'auto.components.LinearIssueWorkspace.ad5dec37b7',
+ 'Preview, edit, and start work from the selected issue.'
+ )}
+
{content}
diff --git a/src/renderer/src/components/LinearItemDrawer.tsx b/src/renderer/src/components/LinearItemDrawer.tsx
index 49231bf12b7..501cd5c2b8e 100644
--- a/src/renderer/src/components/LinearItemDrawer.tsx
+++ b/src/renderer/src/components/LinearItemDrawer.tsx
@@ -193,6 +193,9 @@ export function LinearIssueEditSection({
onEditStateChange({ state: prevState })
patchLinearIssue(issue.id, { state: prevState })
},
+ onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
+ },
onError: (err) => toast.error(err)
})
},
@@ -222,6 +225,9 @@ export function LinearIssueEditSection({
onEditStateChange({ priority: prevPriority })
patchLinearIssue(issue.id, { priority: prevPriority })
},
+ onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
+ },
onError: (err) => toast.error(err)
})
},
@@ -242,6 +248,9 @@ export function LinearIssueEditSection({
onEditStateChange({ estimate: prevEstimate })
patchLinearIssue(issue.id, { estimate: prevEstimate })
},
+ onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
+ },
onError: (err) => toast.error(err)
})
},
@@ -257,7 +266,12 @@ export function LinearIssueEditSection({
const estimate = Number(trimmed)
if (!Number.isInteger(estimate) || estimate < 0) {
- toast.error(translate("auto.components.LinearItemDrawer.0be31fef8e", "Estimate must be a non-negative integer"))
+ toast.error(
+ translate(
+ 'auto.components.LinearItemDrawer.0be31fef8e',
+ 'Estimate must be a non-negative integer'
+ )
+ )
return
}
@@ -282,6 +296,9 @@ export function LinearIssueEditSection({
onEditStateChange({ assignee: prevAssignee })
patchLinearIssue(issue.id, { assignee: prevAssignee })
},
+ onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
+ },
onError: (err) => toast.error(err)
})
},
@@ -320,6 +337,9 @@ export function LinearIssueEditSection({
onEditStateChange({ labelIds: prevLabelIds, labels: prevLabels })
patchLinearIssue(issue.id, { labelIds: prevLabelIds, labels: prevLabels })
},
+ onSuccess: () => {
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
+ },
onError: (err) => toast.error(err)
})
},
@@ -372,7 +392,7 @@ export function LinearIssueEditSection({
- {translate("auto.components.LinearItemDrawer.dd304de85a", "Properties")}
+ {translate('auto.components.LinearItemDrawer.dd304de85a', 'Properties')}
@@ -403,7 +423,8 @@ export function LinearIssueEditSection({
) : states.loading ? (
- {translate("auto.components.LinearItemDrawer.59b6cd3706", "Loading states")}
+ {translate('auto.components.LinearItemDrawer.59b6cd3706', 'Loading states')}
+
) : states.data.length > 0 ? (
{states.data.map((s) => (
@@ -426,7 +447,8 @@ export function LinearIssueEditSection({
) : (
- {translate("auto.components.LinearItemDrawer.780ea6ed89", "No states found")}
+ {translate('auto.components.LinearItemDrawer.780ea6ed89', 'No states found')}
+
)}
@@ -482,7 +504,9 @@ export function LinearIssueEditSection({
)}
- {localAssignee ? localAssignee.displayName : translate("auto.components.LinearItemDrawer.866316f22c", "Unassigned")}
+ {localAssignee
+ ? localAssignee.displayName
+ : translate('auto.components.LinearItemDrawer.866316f22c', 'Unassigned')}
@@ -497,7 +521,8 @@ export function LinearIssueEditSection({
onClick={() => handleAssigneeChange('__unassign__')}
className={cn(LINEAR_EDIT_MENU_ITEM_CLASS, !localAssignee && 'bg-accent/50')}
>
- {translate("auto.components.LinearItemDrawer.866316f22c", "Unassigned")}
+ {translate('auto.components.LinearItemDrawer.866316f22c', 'Unassigned')}
+
{members.error ? (
{members.error}
@@ -505,7 +530,8 @@ export function LinearIssueEditSection({
) : members.loading ? (
- {translate("auto.components.LinearItemDrawer.b2376d0179", "Loading members")}
+ {translate('auto.components.LinearItemDrawer.b2376d0179', 'Loading members')}
+
) : (
members.data.map((m) => (
@@ -577,7 +606,8 @@ export function LinearIssueEditSection({
size="sm"
onClick={() => handleEstimateChange(null)}
>
- {translate("auto.components.LinearItemDrawer.ceeb8c6153", "Clear")}
+ {translate('auto.components.LinearItemDrawer.ceeb8c6153', 'Clear')}
+
{estimatePending ? : null}
- {translate("auto.components.LinearItemDrawer.b5675b0694", "Save")}
+ {translate('auto.components.LinearItemDrawer.b5675b0694', 'Save')}
+
@@ -595,7 +626,7 @@ export function LinearIssueEditSection({
- {translate("auto.components.LinearItemDrawer.64bfffc4dd", "Labels")}
+ {translate('auto.components.LinearItemDrawer.64bfffc4dd', 'Labels')}
@@ -606,13 +637,21 @@ export function LinearIssueEditSection({
disabled={labelsPending}
className={propertyRowClass}
aria-label={
- localLabels.length ? translate("auto.components.LinearItemDrawer.7f7b89b631", "Labels: {{value0}}", { value0: localLabels.join(', ') }) : translate("auto.components.LinearItemDrawer.23886c7eec", "Add label")
+ localLabels.length
+ ? translate(
+ 'auto.components.LinearItemDrawer.7f7b89b631',
+ 'Labels: {{value0}}',
+ { value0: localLabels.join(', ') }
+ )
+ : translate('auto.components.LinearItemDrawer.23886c7eec', 'Add label')
}
aria-busy={labelsPending || labels.loading}
>
- {localLabels.length ? labelSummary : translate("auto.components.LinearItemDrawer.23886c7eec", "Add label")}
+ {localLabels.length
+ ? labelSummary
+ : translate('auto.components.LinearItemDrawer.23886c7eec', 'Add label')}
@@ -628,7 +667,8 @@ export function LinearIssueEditSection({
) : labels.loading ? (
- {translate("auto.components.LinearItemDrawer.cddd9b04a7", "Loading labels")}
+ {translate('auto.components.LinearItemDrawer.cddd9b04a7', 'Loading labels')}
+
) : labels.data.length > 0 ? (
{labels.data.map((label) => (
@@ -658,7 +698,8 @@ export function LinearIssueEditSection({
) : (
- {translate("auto.components.LinearItemDrawer.367f828482", "No labels found")}
+ {translate('auto.components.LinearItemDrawer.367f828482', 'No labels found')}
+
)}
@@ -694,7 +735,8 @@ export function LinearIssueEditSection({
) : states.loading ? (
- {translate("auto.components.LinearItemDrawer.59b6cd3706", "Loading states")}
+ {translate('auto.components.LinearItemDrawer.59b6cd3706', 'Loading states')}
+
) : states.data.length > 0 ? (
{states.data.map((s) => (
@@ -717,7 +759,8 @@ export function LinearIssueEditSection({
) : (
- {translate("auto.components.LinearItemDrawer.780ea6ed89", "No states found")}
+ {translate('auto.components.LinearItemDrawer.780ea6ed89', 'No states found')}
+
)}
@@ -796,7 +839,10 @@ export function LinearIssueEditSection({
}
}}
inputMode="numeric"
- placeholder={translate("auto.components.LinearItemDrawer.fbb90300e2", "Custom estimate")}
+ placeholder={translate(
+ 'auto.components.LinearItemDrawer.fbb90300e2',
+ 'Custom estimate'
+ )}
className="h-8 text-sm"
/>
@@ -806,7 +852,8 @@ export function LinearIssueEditSection({
size="sm"
onClick={() => handleEstimateChange(null)}
>
- {translate("auto.components.LinearItemDrawer.ceeb8c6153", "Clear")}
+ {translate('auto.components.LinearItemDrawer.ceeb8c6153', 'Clear')}
+
{estimatePending ? : null}
- {translate("auto.components.LinearItemDrawer.b5675b0694", "Save")}
+ {translate('auto.components.LinearItemDrawer.b5675b0694', 'Save')}
+
@@ -830,7 +878,9 @@ export function LinearIssueEditSection({
aria-busy={assigneePending || members.loading}
>
- {localAssignee ? localAssignee.displayName : translate("auto.components.LinearItemDrawer.d71cd3003e", "+ Assignee")}
+ {localAssignee
+ ? localAssignee.displayName
+ : translate('auto.components.LinearItemDrawer.d71cd3003e', '+ Assignee')}
@@ -842,7 +892,8 @@ export function LinearIssueEditSection({
onClick={() => handleAssigneeChange('__unassign__')}
className={cn(LINEAR_EDIT_MENU_ITEM_CLASS, !localAssignee && 'bg-accent/50')}
>
- {translate("auto.components.LinearItemDrawer.866316f22c", "Unassigned")}
+ {translate('auto.components.LinearItemDrawer.866316f22c', 'Unassigned')}
+
{members.error ? (
{members.error}
@@ -850,7 +901,8 @@ export function LinearIssueEditSection({
) : members.loading ? (
- {translate("auto.components.LinearItemDrawer.b2376d0179", "Loading members")}
+ {translate('auto.components.LinearItemDrawer.b2376d0179', 'Loading members')}
+
) : (
members.data.map((m) => (
{labelSummary}
@@ -890,7 +948,8 @@ export function LinearIssueEditSection({
) : labels.loading ? (
- {translate("auto.components.LinearItemDrawer.cddd9b04a7", "Loading labels")}
+ {translate('auto.components.LinearItemDrawer.cddd9b04a7', 'Loading labels')}
+
) : labels.data.length > 0 ? (
{labels.data.map((label) => (
@@ -920,7 +979,8 @@ export function LinearIssueEditSection({
) : (
- {translate("auto.components.LinearItemDrawer.367f828482", "No labels found")}
+ {translate('auto.components.LinearItemDrawer.367f828482', 'No labels found')}
+
)}
@@ -977,17 +1037,25 @@ export function LinearIssueCommentFooter({
}
if (typed.ok) {
setBody('')
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
onCommentAdded({
id: typed.id ?? createBrowserUuid(),
body: trimmed,
createdAt: new Date().toISOString()
})
} else {
- toast.error(typed.error ?? translate("auto.components.LinearItemDrawer.6ab35eafd5", "Failed to add comment"))
+ toast.error(
+ typed.error ??
+ translate('auto.components.LinearItemDrawer.6ab35eafd5', 'Failed to add comment')
+ )
}
} catch (err) {
if (mountedRef.current) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.LinearItemDrawer.6ab35eafd5", "Failed to add comment"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate('auto.components.LinearItemDrawer.6ab35eafd5', 'Failed to add comment')
+ )
}
} finally {
if (mountedRef.current) {
@@ -1020,19 +1088,26 @@ export function LinearIssueCommentFooter({
autoGrow()
}}
onKeyDown={handleKeyDown}
- placeholder={translate("auto.components.LinearItemDrawer.2820f0f0f0", "Leave a comment...")}
+ placeholder={translate(
+ 'auto.components.LinearItemDrawer.2820f0f0f0',
+ 'Leave a comment...'
+ )}
rows={3}
className="scrollbar-sleek min-h-24 max-h-40 w-full resize-none overflow-y-auto rounded-t-xl bg-transparent px-5 py-4 text-sm placeholder:text-muted-foreground focus-visible:outline-none"
/>
- {submitShortcutLabel !== "Unassigned" ? translate("auto.components.LinearItemDrawer.fda549766e", "{{value0}} to comment", { value0: submitShortcutLabel }) : ''}
+ {submitShortcutLabel !== 'Unassigned'
+ ? translate('auto.components.LinearItemDrawer.fda549766e', '{{value0}} to comment', {
+ value0: submitShortcutLabel
+ })
+ : ''}
{submitting ? (
@@ -1058,7 +1133,7 @@ export function LinearIssueCommentFooter({
autoGrow()
}}
onKeyDown={handleKeyDown}
- placeholder={translate("auto.components.LinearItemDrawer.2fcff829a8", "Add a comment…")}
+ placeholder={translate('auto.components.LinearItemDrawer.2fcff829a8', 'Add a comment…')}
rows={1}
className="scrollbar-sleek min-h-[32px] max-h-[96px] flex-1 resize-none overflow-y-auto rounded-md border border-input bg-transparent px-3 py-2 text-[13px] placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
/>
@@ -1067,7 +1142,7 @@ export function LinearIssueCommentFooter({
onClick={handleSubmit}
disabled={!body.trim() || submitting}
className="size-8 shrink-0"
- aria-label={translate("auto.components.LinearItemDrawer.d369841269", "Send comment")}
+ aria-label={translate('auto.components.LinearItemDrawer.d369841269', 'Send comment')}
>
{submitting ? (
@@ -1238,10 +1313,18 @@ export default function LinearItemDrawer({
}}
>
- {displayed?.title ?? translate("auto.components.LinearItemDrawer.39883467f4", "Linear issue")}
+
+ {displayed?.title ??
+ translate('auto.components.LinearItemDrawer.39883467f4', 'Linear issue')}
+
- {translate("auto.components.LinearItemDrawer.04a442f796", "Preview and edit the selected Linear issue.")}
+
+ {translate(
+ 'auto.components.LinearItemDrawer.04a442f796',
+ 'Preview and edit the selected Linear issue.'
+ )}
+
{displayed && (
@@ -1276,13 +1359,17 @@ export default function LinearItemDrawer({
size="icon"
className="size-7"
onClick={() => window.api.shell.openUrl(displayed.url)}
- aria-label={translate("auto.components.LinearItemDrawer.0190b760c1", "Open on Linear")}
+ aria-label={translate(
+ 'auto.components.LinearItemDrawer.0190b760c1',
+ 'Open on Linear'
+ )}
>
- {translate("auto.components.LinearItemDrawer.0190b760c1", "Open on Linear")}
+ {translate('auto.components.LinearItemDrawer.0190b760c1', 'Open on Linear')}
+
@@ -1291,13 +1378,17 @@ export default function LinearItemDrawer({
size="icon"
className="size-7"
onClick={onClose}
- aria-label={translate("auto.components.LinearItemDrawer.858d0630da", "Close preview")}
+ aria-label={translate(
+ 'auto.components.LinearItemDrawer.858d0630da',
+ 'Close preview'
+ )}
>
- {translate("auto.components.LinearItemDrawer.9dc54172db", "Close · Esc")}
+ {translate('auto.components.LinearItemDrawer.9dc54172db', 'Close · Esc')}
+
@@ -1325,7 +1416,9 @@ export default function LinearItemDrawer({
- {translate("auto.components.LinearItemDrawer.fde849b2b6", "Comments")}
+
+ {translate('auto.components.LinearItemDrawer.fde849b2b6', 'Comments')}
+
{comments.length > 0 && (
{comments.length}
)}
@@ -1335,7 +1428,9 @@ export default function LinearItemDrawer({
) : comments.length === 0 ? (
-
{translate("auto.components.LinearItemDrawer.a4fcc57522", "No comments yet.")}
+
+ {translate('auto.components.LinearItemDrawer.a4fcc57522', 'No comments yet.')}
+
) : (
{comments.map((comment) => (
@@ -1352,7 +1447,8 @@ export default function LinearItemDrawer({
/>
)}
- {comment.user?.displayName ?? translate("auto.components.LinearItemDrawer.48e17e8cbd", "Unknown")}
+ {comment.user?.displayName ??
+ translate('auto.components.LinearItemDrawer.48e17e8cbd', 'Unknown')}
· {formatRelativeTime(comment.createdAt)}
@@ -1381,9 +1477,16 @@ export default function LinearItemDrawer({
onUse(displayed)}
className="w-full justify-center gap-2"
- aria-label={translate("auto.components.LinearItemDrawer.04008e6c46", "Start workspace from issue")}
+ aria-label={translate(
+ 'auto.components.LinearItemDrawer.04008e6c46',
+ 'Start workspace from issue'
+ )}
>
- {translate("auto.components.LinearItemDrawer.04008e6c46", "Start workspace from issue")}
+ {translate(
+ 'auto.components.LinearItemDrawer.04008e6c46',
+ 'Start workspace from issue'
+ )}
+
diff --git a/src/renderer/src/components/NewWorkspaceComposerModal.tsx b/src/renderer/src/components/NewWorkspaceComposerModal.tsx
index 66ca96f5e5f..a5b68b7395e 100644
--- a/src/renderer/src/components/NewWorkspaceComposerModal.tsx
+++ b/src/renderer/src/components/NewWorkspaceComposerModal.tsx
@@ -229,7 +229,11 @@ function QuickTabBody({
{primaryActionLabel}
- {translate("auto.components.NewWorkspaceComposerModal.fa90f739a5", "Choose the project, workspace name, and agent before creating the workspace.")}
+ {translate(
+ 'auto.components.NewWorkspaceComposerModal.fa90f739a5',
+ 'Choose the project, workspace name, and agent before creating the workspace.'
+ )}
+
- {translate("auto.components.QuickOpen.4725b0e931", "Quick Open scan too large (")}{reason}).
+
+ {translate('auto.components.QuickOpen.4725b0e931', 'Quick Open scan too large (')}
+ {reason}).
+
- {translate("auto.components.QuickOpen.2ca749c15d", "Install")}{' '}
- {translate("auto.components.QuickOpen.5d80dc39bb", "ripgrep")} {translate("auto.components.QuickOpen.1cf8561ab4", "on the remote to enable fast, gitignore-aware listing:")}
+ {translate('auto.components.QuickOpen.2ca749c15d', 'Install')}{' '}
+
+ {translate('auto.components.QuickOpen.5d80dc39bb', 'ripgrep')}
+ {' '}
+ {translate(
+ 'auto.components.QuickOpen.1cf8561ab4',
+ 'on the remote to enable fast, gitignore-aware listing:'
+ )}
+
{command ? (
{command}
@@ -135,10 +145,12 @@ function InstallRgGuidance({
type="button"
onClick={handleCopy}
className="flex items-center gap-1 rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
- aria-label={translate("auto.components.QuickOpen.73b44e7bde", "Copy install command")}
+ aria-label={translate('auto.components.QuickOpen.73b44e7bde', 'Copy install command')}
>
{copied ? : }
- {copied ? translate("auto.components.QuickOpen.cf144856dc", "Copied") : translate("auto.components.QuickOpen.995be8ea22", "Copy")}
+ {copied
+ ? translate('auto.components.QuickOpen.cf144856dc', 'Copied')
+ : translate('auto.components.QuickOpen.995be8ea22', 'Copy')}
) : guidance ? (
@@ -218,13 +230,19 @@ export default function QuickOpen(): React.JSX.Element | null {
onOpenChange={handleOpenChange}
shouldFilter={false}
onCloseAutoFocus={handleCloseAutoFocus}
- title={translate("auto.components.QuickOpen.ec31e058f7", "Go to file")}
- description={translate("auto.components.QuickOpen.9e97f08d0f", "Search for a file to open")}
+ title={translate('auto.components.QuickOpen.ec31e058f7', 'Go to file')}
+ description={translate('auto.components.QuickOpen.9e97f08d0f', 'Search for a file to open')}
>
-
+
{loading ? (
- {translate("auto.components.QuickOpen.722a21e1a8", "Loading files...")}
+
+ {translate('auto.components.QuickOpen.722a21e1a8', 'Loading files...')}
+
) : loadError ? (
(() => {
const guidance = parseInstallRgGuidance(loadError)
@@ -241,7 +259,9 @@ export default function QuickOpen(): React.JSX.Element | null {
)
})()
) : filtered.length === 0 ? (
- {translate("auto.components.QuickOpen.74e2e1b3e4", "No matching files.")}
+
+ {translate('auto.components.QuickOpen.74e2e1b3e4', 'No matching files.')}
+
) : (
filtered.map((item) => {
const lastSlash = item.path.lastIndexOf('/')
@@ -266,17 +286,21 @@ export default function QuickOpen(): React.JSX.Element | null {
- {translate("auto.components.QuickOpen.250e5b2dfb", "Enter")}
- {translate("auto.components.QuickOpen.61b1c871a6", "Open")}
- {translate("auto.components.QuickOpen.95fccbae88", "Esc")}
- {translate("auto.components.QuickOpen.73b2c581f1", "Close")}
+ {translate('auto.components.QuickOpen.250e5b2dfb', 'Enter')}
+ {translate('auto.components.QuickOpen.61b1c871a6', 'Open')}
+ {translate('auto.components.QuickOpen.95fccbae88', 'Esc')}
+ {translate('auto.components.QuickOpen.73b2c581f1', 'Close')}
↑↓
- {translate("auto.components.QuickOpen.1dbd3f59ff", "Move")}
+ {translate('auto.components.QuickOpen.1dbd3f59ff', 'Move')}
{/* Accessibility: announce result count changes */}
- {deferredQuery.trim() ? translate("auto.components.QuickOpen.b227d88520", "{{value0}} files found", { value0: filtered.length }) : ''}
+ {deferredQuery.trim()
+ ? translate('auto.components.QuickOpen.b227d88520', '{{value0}} files found', {
+ value0: filtered.length
+ })
+ : ''}
)
diff --git a/src/renderer/src/components/SelectedTextCopyMenu.tsx b/src/renderer/src/components/SelectedTextCopyMenu.tsx
index 17ed6702588..d08acaf9d44 100644
--- a/src/renderer/src/components/SelectedTextCopyMenu.tsx
+++ b/src/renderer/src/components/SelectedTextCopyMenu.tsx
@@ -115,7 +115,8 @@ export function SelectedTextCopyMenu({
onClick={handleCopy}
>
- {translate("auto.components.SelectedTextCopyMenu.9b40d7b018", "Copy")}
+ {translate('auto.components.SelectedTextCopyMenu.9b40d7b018', 'Copy')}
+
,
document.body
)}
diff --git a/src/renderer/src/components/StarNagCard.tsx b/src/renderer/src/components/StarNagCard.tsx
index 7223a2f1009..f963269824e 100644
--- a/src/renderer/src/components/StarNagCard.tsx
+++ b/src/renderer/src/components/StarNagCard.tsx
@@ -101,25 +101,39 @@ export function StarNagCard(): React.JSX.Element | null {
- {translate("auto.components.StarNagCard.5f6df21046", "Enjoying Orca?")}
+ {translate('auto.components.StarNagCard.5f6df21046', 'Enjoying Orca?')}
+
- {translate("auto.components.StarNagCard.30c36231c1", "If Orca has saved you time, a GitHub star goes a long way. It helps other developers discover the project and keeps the team motivated to ship improvements.")}
+ {translate(
+ 'auto.components.StarNagCard.30c36231c1',
+ 'If Orca has saved you time, a GitHub star goes a long way. It helps other developers discover the project and keeps the team motivated to ship improvements.'
+ )}
+
{error ? (
- {translate("auto.components.StarNagCard.cf82170065", "Could not star the repo. Make sure")}{translate("auto.components.StarNagCard.cd8c34aac1", "gh")} {translate("auto.components.StarNagCard.92b0f9d921", "is authenticated and try again.")}
+ {translate(
+ 'auto.components.StarNagCard.cf82170065',
+ 'Could not star the repo. Make sure'
+ )}
+ {translate('auto.components.StarNagCard.cd8c34aac1', 'gh')}{' '}
+ {translate(
+ 'auto.components.StarNagCard.92b0f9d921',
+ 'is authenticated and try again.'
+ )}
+
) : null}
- {busy ? translate("auto.components.StarNagCard.af3c9bbb37", "Starring…") : translate("auto.components.StarNagCard.2d67b6c849", "Star on GitHub")}
+ {busy
+ ? translate('auto.components.StarNagCard.af3c9bbb37', 'Starring…')
+ : translate('auto.components.StarNagCard.2d67b6c849', 'Star on GitHub')}
diff --git a/src/renderer/src/components/TaskPage.tsx b/src/renderer/src/components/TaskPage.tsx
index f7f68eaf7ab..48a6ad87eb2 100644
--- a/src/renderer/src/components/TaskPage.tsx
+++ b/src/renderer/src/components/TaskPage.tsx
@@ -488,7 +488,9 @@ function LinearStateCell({
result.error ??
translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
})
.catch(() => {
if (reqId !== reqRef.current) {
@@ -904,7 +906,9 @@ function GHStatusCell({
typed.error ??
translate('auto.components.TaskPage.1c893195ac', 'Failed to update state')
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
})
.catch(() => {
if (reqId !== reqRef.current) {
@@ -1349,6 +1353,7 @@ function GHAssigneesCell({
} else {
throw new Error('No GitHub repository context available for this issue.')
}
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
} catch (err) {
patchWorkItem(item.id, { assignees: previousAssignees }, item.repoId)
toast.error(
@@ -1814,6 +1819,7 @@ function PRReviewCell({
setLocalReviewRequests(nextReviewRequests)
patchWorkItem(item.id, { reviewRequests: nextReviewRequests }, item.repoId)
setReviewerInput('')
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
} else {
toast.error(result.error)
}
@@ -2200,6 +2206,7 @@ function PRMergeCell({
prRepo: item.prRepo ?? null
})
if (result.ok) {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
toast.success(translate('auto.components.TaskPage.a161925adc', 'Pull request merged'))
onRefresh()
} else {
@@ -2227,6 +2234,7 @@ function PRMergeCell({
prRepo: item.prRepo ?? null
})
if (result.ok) {
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
toast.success(
enabled
? translate('auto.components.TaskPage.fed317634c', 'Auto-merge enabled')
@@ -2850,12 +2858,15 @@ export default function TaskPage(): React.JSX.Element {
const openGitHubDetailPage = useCallback(
(item: GitHubWorkItem, initialTab: ItemDialogTab = 'conversation') => {
- openTaskPage({
- taskSource: 'github',
- preselectedRepoId: item.repoId,
- openGitHubWorkItem: item,
- openGitHubInitialTab: initialTab
- })
+ openTaskPage(
+ {
+ taskSource: 'github',
+ preselectedRepoId: item.repoId,
+ openGitHubWorkItem: item,
+ openGitHubInitialTab: initialTab
+ },
+ { recordTasksInteraction: false }
+ )
},
[openTaskPage]
)
@@ -3078,7 +3089,10 @@ export default function TaskPage(): React.JSX.Element {
const openLinearDetailPage = useCallback(
(issue: LinearIssue) => {
- openTaskPage({ taskSource: 'linear', openLinearIssue: issue })
+ openTaskPage(
+ { taskSource: 'linear', openLinearIssue: issue },
+ { recordTasksInteraction: false }
+ )
},
[openTaskPage]
)
@@ -4192,7 +4206,9 @@ export default function TaskPage(): React.JSX.Element {
result.error ??
translate('auto.components.TaskPage.6775c05483', 'Failed to update Linear state')
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
} catch {
patchLinearIssue(issue.id, { state: previousState })
patchScopedLinearIssue(issue.id, { state: previousState })
@@ -5229,6 +5245,7 @@ export default function TaskPage(): React.JSX.Element {
// the worktree appeared in the sidebar before the user had a chance
// to review it. The composer already owns the prefill flow. Telemetry
// attribution flows via `openComposerForItem` (sets telemetrySource).
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
openComposerForItem(item)
},
[openComposerForItem]
@@ -5260,7 +5277,9 @@ export default function TaskPage(): React.JSX.Element {
'Unable to open the workspace attached to this issue.'
)
)
+ return
}
+ useAppStore.getState().recordFeatureInteraction('github-tasks')
},
[handleUseWorkItem]
)
@@ -5285,6 +5304,7 @@ export default function TaskPage(): React.JSX.Element {
const handleUseGitLabItem = useCallback(
(item: GitLabWorkItem): void => {
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
openComposerForGitLabItem(item)
},
[openComposerForGitLabItem]
@@ -5557,13 +5577,14 @@ export default function TaskPage(): React.JSX.Element {
setNewLinearIssueProjectId(null)
setNewLinearIssueLabelIds([])
setLinearRefreshNonce((n) => n + 1)
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
// Why: auto-select the new issue in the inline workspace so the user
// sees exactly what was filed, mirroring the GitHub create-issue flow.
void linearGetIssue(settings, result.id, newLinearIssueTargetTeam.workspaceId)
.then((full) => {
if (full) {
- openLinearDetailPage(full)
+ setSelectedLinearIssue(full, { allowOutsideList: true })
}
})
.catch(() => {})
@@ -5580,8 +5601,8 @@ export default function TaskPage(): React.JSX.Element {
newLinearIssueAssigneeId,
newLinearIssueProjectId,
newLinearIssueLabelIds,
- openLinearDetailPage,
selectedLinearProject,
+ setSelectedLinearIssue,
settings
])
@@ -6314,6 +6335,7 @@ export default function TaskPage(): React.JSX.Element {
// dialog pre-filled rather than yolo-creating the worktree, so the
// user can confirm name / agent / setup before the worktree lands in
// the sidebar. Telemetry attribution flows via openComposerForLinearItem.
+ useAppStore.getState().recordFeatureInteraction('linear-tasks')
openComposerForLinearItem(issue, renderedText)
},
[openComposerForLinearItem]
@@ -6503,7 +6525,10 @@ export default function TaskPage(): React.JSX.Element {
disabled={source.disabled}
onClick={() => {
taskSourceManuallyChangedRef.current = true
- openTaskPage({ taskSource: source.id })
+ openTaskPage(
+ { taskSource: source.id },
+ { recordTasksInteraction: false }
+ )
void updateSettings({ defaultTaskSource: source.id }).catch(() => {
toast.error(
translate(
@@ -8205,10 +8230,14 @@ export default function TaskPage(): React.JSX.Element {
role="button"
tabIndex={0}
key={item.id}
- onClick={() => setGitlabDialogItem(item)}
+ onClick={() => {
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
+ setGitlabDialogItem(item)
+ }}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
+ useAppStore.getState().recordFeatureInteraction('gitlab-tasks')
setGitlabDialogItem(item)
}
}}
diff --git a/src/renderer/src/components/Terminal.tsx b/src/renderer/src/components/Terminal.tsx
index 2cb006b52b0..889e03a7ae5 100644
--- a/src/renderer/src/components/Terminal.tsx
+++ b/src/renderer/src/components/Terminal.tsx
@@ -546,7 +546,12 @@ function Terminal(): React.JSX.Element | null {
releaseCloseDialogGuardAfterDebounce()
return
}
- toast.error(translate("auto.components.Terminal.a2a279b32a", "Save timed out or failed. Fix errors before closing."))
+ toast.error(
+ translate(
+ 'auto.components.Terminal.a2a279b32a',
+ 'Save timed out or failed. Fix errors before closing.'
+ )
+ )
setSaveDialogFileId(fileId)
// Why: a genuine timeout leaves the user back on the same dialog, so
// release the guard immediately — a new click here is a deliberate
@@ -861,7 +866,7 @@ function Terminal(): React.JSX.Element | null {
return
}
createBrowserTab(activeWorktreeId, defaultUrl, {
- title: translate("auto.components.Terminal.37da0d736f", "New Browser Tab"),
+ title: translate('auto.components.Terminal.37da0d736f', 'New Browser Tab'),
focusAddressBar: true
})
}, [
@@ -1292,7 +1297,12 @@ function Terminal(): React.JSX.Element | null {
if (floatingWorkspaceFocused) {
void createFloatingWorkspaceMarkdownTab(useAppStore.getState()).catch((err) => {
toast.error(
- err instanceof Error ? err.message : translate("auto.components.Terminal.f0600556b3", "Failed to create untitled markdown file.")
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.Terminal.f0600556b3',
+ 'Failed to create untitled markdown file.'
+ )
)
})
return
@@ -1806,11 +1816,12 @@ function Terminal(): React.JSX.Element | null {
})}
- {renderedActiveWorktreeId && activeTabType === "editor" && worktreeFiles.length > 0 && (
+ {renderedActiveWorktreeId && activeTabType === 'editor' && worktreeFiles.length > 0 && (
- {translate("auto.components.Terminal.5c1d2a32bb", "Loading editor...")}
+ {translate('auto.components.Terminal.5c1d2a32bb', 'Loading editor...')}
+
}
>
@@ -1830,20 +1841,32 @@ function Terminal(): React.JSX.Element | null {
>
- {translate("auto.components.Terminal.21295c6b8c", "Unsaved Changes")}
+
+ {translate('auto.components.Terminal.21295c6b8c', 'Unsaved Changes')}
+
{saveDialogFile
- ? translate("auto.components.Terminal.61ed600d29", "\"{{value0}}\" has unsaved changes. Do you want to save before closing?", { value0: basename(saveDialogFile.relativePath) })
- : translate("auto.components.Terminal.46e08bc5c8", "This file has unsaved changes.")}
+ ? translate(
+ 'auto.components.Terminal.61ed600d29',
+ '"{{value0}}" has unsaved changes. Do you want to save before closing?',
+ { value0: basename(saveDialogFile.relativePath) }
+ )
+ : translate(
+ 'auto.components.Terminal.46e08bc5c8',
+ 'This file has unsaved changes.'
+ )}
- {translate("auto.components.Terminal.f82e9f02df", "Cancel")}
+ {translate('auto.components.Terminal.f82e9f02df', 'Cancel')}
+
- {translate("auto.components.Terminal.0037b21794", "Don't Save")}
+ {translate('auto.components.Terminal.0037b21794', "Don't Save")}
+
- {translate("auto.components.Terminal.cd51e28d8b", "Save")}
+ {translate('auto.components.Terminal.cd51e28d8b', 'Save')}
+
@@ -1859,9 +1882,15 @@ function Terminal(): React.JSX.Element | null {
>
- {translate("auto.components.Terminal.2fa9c69ff3", "Close Window?")}
+
+ {translate('auto.components.Terminal.2fa9c69ff3', 'Close Window?')}
+
- {translate("auto.components.Terminal.7958465754", "There are local terminals with running processes. Close the window anyway?")}
+ {translate(
+ 'auto.components.Terminal.7958465754',
+ 'There are local terminals with running processes. Close the window anyway?'
+ )}
+
setWindowCloseDialogOpen(false)}
>
- {translate("auto.components.Terminal.f82e9f02df", "Cancel")}
+ {translate('auto.components.Terminal.f82e9f02df', 'Cancel')}
+
- {translate("auto.components.Terminal.73768427cf", "Close")}
+ {translate('auto.components.Terminal.73768427cf', 'Close')}
+
diff --git a/src/renderer/src/components/TerminalSearch.tsx b/src/renderer/src/components/TerminalSearch.tsx
index ff8f860ecdb..3832c431237 100644
--- a/src/renderer/src/components/TerminalSearch.tsx
+++ b/src/renderer/src/components/TerminalSearch.tsx
@@ -110,7 +110,7 @@ export default function TerminalSearch({
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
- placeholder={translate("auto.components.TerminalSearch.e07012f26e", "Search...")}
+ placeholder={translate('auto.components.TerminalSearch.e07012f26e', 'Search...')}
className="min-w-0 flex-1 border-none bg-transparent text-sm text-white outline-none placeholder:text-zinc-500"
/>
@@ -122,7 +122,7 @@ export default function TerminalSearch({
className={`flex size-6 shrink-0 items-center justify-center rounded ${
caseSensitive ? 'bg-zinc-700/50 text-blue-400' : 'text-zinc-400 hover:text-zinc-200'
}`}
- title={translate("auto.components.TerminalSearch.90c61387d9", "Case sensitive")}
+ title={translate('auto.components.TerminalSearch.90c61387d9', 'Case sensitive')}
>
@@ -135,7 +135,7 @@ export default function TerminalSearch({
className={`flex size-6 shrink-0 items-center justify-center rounded ${
regex ? 'bg-zinc-700/50 text-blue-400' : 'text-zinc-400 hover:text-zinc-200'
}`}
- title={translate("auto.components.TerminalSearch.42e466b9f1", "Regex")}
+ title={translate('auto.components.TerminalSearch.42e466b9f1', 'Regex')}
>
@@ -148,7 +148,7 @@ export default function TerminalSearch({
size="icon-xs"
onClick={findPrevious}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.TerminalSearch.0f3066256e", "Previous match")}
+ title={translate('auto.components.TerminalSearch.0f3066256e', 'Previous match')}
>
@@ -159,7 +159,7 @@ export default function TerminalSearch({
size="icon-xs"
onClick={findNext}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.TerminalSearch.7cb40c04eb", "Next match")}
+ title={translate('auto.components.TerminalSearch.7cb40c04eb', 'Next match')}
>
@@ -172,7 +172,7 @@ export default function TerminalSearch({
size="icon-xs"
onClick={onClose}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.TerminalSearch.db234b7519", "Close")}
+ title={translate('auto.components.TerminalSearch.db234b7519', 'Close')}
>
diff --git a/src/renderer/src/components/WorktreeJumpPalette.tsx b/src/renderer/src/components/WorktreeJumpPalette.tsx
index 9ea18fdbb50..80861bff424 100644
--- a/src/renderer/src/components/WorktreeJumpPalette.tsx
+++ b/src/renderer/src/components/WorktreeJumpPalette.tsx
@@ -255,6 +255,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
const openModal = useAppStore((s) => s.openModal)
const openSettingsPage = useAppStore((s) => s.openSettingsPage)
const openSettingsTarget = useAppStore((s) => s.openSettingsTarget)
+ const recordFeatureInteraction = useAppStore((s) => s.recordFeatureInteraction)
const worktreesByRepo = useAppStore((s) => s.worktreesByRepo)
const allWorktrees = useAllWorktrees()
const repos = useAppStore((s) => s.repos)
@@ -799,6 +800,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
useEffect(() => {
if (visible && !wasVisibleRef.current) {
+ recordFeatureInteraction('cmd-j')
createLookupGuard.invalidate()
activeGroupSnapshotRef.current = captureCmdJActiveGroupSnapshot(
useAppStore.getState(),
@@ -845,6 +847,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
activeWorktreeId,
browserTabsByWorktree,
createLookupGuard,
+ recordFeatureInteraction,
visible
])
@@ -953,12 +956,13 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
return
}
activateAndRevealWorktree(worktreeId)
+ recordFeatureInteraction('cmd-j-workspace-open')
skipRestoreFocusRef.current = true
closeModal()
setSelectedItemId('')
focusFallbackSurface()
},
- [closeModal, focusFallbackSurface]
+ [closeModal, focusFallbackSurface, recordFeatureInteraction]
)
const handleSelectBrowserPage = useCallback(
@@ -989,6 +993,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
const state = useAppStore.getState()
state.setActiveBrowserTab(workspace.id)
state.setActiveBrowserPage(workspace.id, pageId)
+ recordFeatureInteraction('cmd-j-browser-page-open')
skipRestoreFocusRef.current = true
closeModal()
setSelectedItemId('')
@@ -997,7 +1002,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
target: isBlankBrowserUrl(page.url) ? 'address-bar' : 'webview'
})
},
- [closeModal, requestBrowserFocus]
+ [closeModal, recordFeatureInteraction, requestBrowserFocus]
)
const handleSelectSimulatorTab = useCallback(
@@ -1046,8 +1051,9 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
setSelectedItemId('')
openSettingsTarget(target)
openSettingsPage()
+ recordFeatureInteraction('cmd-j-settings-open')
},
- [closeModal, openSettingsPage, openSettingsTarget]
+ [closeModal, openSettingsPage, openSettingsTarget, recordFeatureInteraction]
)
const handleSelectQuickAction = useCallback(
@@ -1059,10 +1065,16 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
void action.run(ctx).then((result) => {
if (result.status === 'unavailable') {
toast.error(getUnavailableQuickActionMessage(action.title, result.reason))
+ return
}
+ if (action.id === 'create-workspace') {
+ recordFeatureInteraction('cmd-j-create-workspace')
+ return
+ }
+ recordFeatureInteraction('cmd-j-quick-action')
})
},
- [buildQuickActionContext, closeModal]
+ [buildQuickActionContext, closeModal, recordFeatureInteraction]
)
const handleSelectItem = useCallback(
@@ -1099,6 +1111,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
typeof data.initialRepoId === 'string' ? data.initialRepoId : undefined
)
closeModal()
+ recordFeatureInteraction('cmd-j-create-workspace')
// Why: defer opening so Radix fully unmounts the palette's dialog before
// the composer modal mounts, avoiding focus churn between the two.
queueMicrotask(() =>
@@ -1122,6 +1135,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
if (activeMatch) {
closeModal()
activateAndRevealWorktree(activeMatch.id)
+ recordFeatureInteraction('cmd-j-workspace-open')
return
}
@@ -1141,6 +1155,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
// composer once the lookup returns.
const lookupToken = createLookupGuard.start()
preserveCreateLookupOnCloseRef.current = true
+ recordFeatureInteraction('cmd-j-create-workspace')
closeModal()
void window.api.gh
.workItemByOwnerRepo({
@@ -1199,6 +1214,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
if (activeMatch) {
closeModal()
activateAndRevealWorktree(activeMatch.id)
+ recordFeatureInteraction('cmd-j-workspace-open')
return
}
@@ -1213,6 +1229,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
prefetchCreateWorkspaceBaseForComposer(repoForLookup.id)
const lookupToken = createLookupGuard.start()
preserveCreateLookupOnCloseRef.current = true
+ recordFeatureInteraction('cmd-j-create-workspace')
closeModal()
void window.api.gh
.workItem({ repoPath: repoForLookup.path, repoId: repoForLookup.id, number: ghNumber })
@@ -1263,6 +1280,7 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
createWorktreeName,
openModal,
prefetchCreateWorkspaceBaseForComposer,
+ recordFeatureInteraction,
repoMap
])
diff --git a/src/renderer/src/components/activity/ActivityPrototypePage.tsx b/src/renderer/src/components/activity/ActivityPrototypePage.tsx
index 1720123c5ba..5d9f2e6ea4b 100644
--- a/src/renderer/src/components/activity/ActivityPrototypePage.tsx
+++ b/src/renderer/src/components/activity/ActivityPrototypePage.tsx
@@ -911,7 +911,13 @@ export function getActivityThreadGroup(
if (groupBy === 'project') {
return thread.repo
? { key: `project:${thread.repo.id}`, label: thread.repo.displayName }
- : { key: 'project:unknown', label: translate("auto.components.activity.ActivityPrototypePage.5651b216c6", "Unknown project") }
+ : {
+ key: 'project:unknown',
+ label: translate(
+ 'auto.components.activity.ActivityPrototypePage.5651b216c6',
+ 'Unknown project'
+ )
+ }
}
if (groupBy === 'worktree') {
return { key: `worktree:${thread.worktree.id}`, label: thread.worktree.displayName }
@@ -1162,7 +1168,10 @@ function ThreadRow({
{thread.unread ? (
) : (
@@ -1179,12 +1188,20 @@ function ThreadRow({
'hover:bg-accent/80 active:scale-95',
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'
)}
- aria-label={translate("auto.components.activity.ActivityPrototypePage.59b131fbd9", "Mark thread unread")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.59b131fbd9',
+ 'Mark thread unread'
+ )}
>
- {translate("auto.components.activity.ActivityPrototypePage.59b131fbd9", "Mark thread unread")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.59b131fbd9',
+ 'Mark thread unread'
+ )}
+
)}
@@ -1216,7 +1233,10 @@ function ThreadRow({
type="button"
variant="outline"
size="icon-xs"
- aria-label={translate("auto.components.activity.ActivityPrototypePage.4616ea39fd", "Jump to workspace")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.4616ea39fd',
+ 'Jump to workspace'
+ )}
onClick={(event) => {
event.stopPropagation()
onJump()
@@ -1226,7 +1246,12 @@ function ThreadRow({
- {translate("auto.components.activity.ActivityPrototypePage.4616ea39fd", "Jump to workspace")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.4616ea39fd',
+ 'Jump to workspace'
+ )}
+
) : null}
@@ -1615,7 +1640,10 @@ export default function ActivityPrototypePage(): React.JSX.Element {
setQuery(event.target.value)}
- placeholder={translate("auto.components.activity.ActivityPrototypePage.795cbf26e2", "Filter...")}
+ placeholder={translate(
+ 'auto.components.activity.ActivityPrototypePage.795cbf26e2',
+ 'Filter...'
+ )}
className="h-8 w-full pl-7 text-xs"
/>
@@ -1626,15 +1654,38 @@ export default function ActivityPrototypePage(): React.JSX.Element {
- {translate("auto.components.activity.ActivityPrototypePage.4a3986b200", "Status")}
- {translate("auto.components.activity.ActivityPrototypePage.8c3b621ddf", "Project")}
- {translate("auto.components.activity.ActivityPrototypePage.b29191b3e0", "Worktree")}
- {translate("auto.components.activity.ActivityPrototypePage.f6396e1f85", "Agent")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.4a3986b200',
+ 'Status'
+ )}
+
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.8c3b621ddf',
+ 'Project'
+ )}
+
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.b29191b3e0',
+ 'Worktree'
+ )}
+
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.f6396e1f85',
+ 'Agent'
+ )}
+
@@ -1650,12 +1701,20 @@ export default function ActivityPrototypePage(): React.JSX.Element {
? '!border-primary !bg-primary !text-primary-foreground shadow-xs ring-2 ring-primary/35 hover:!bg-primary/90 hover:!text-primary-foreground'
: 'text-muted-foreground hover:text-foreground'
)}
- aria-label={translate("auto.components.activity.ActivityPrototypePage.d1a88df9a8", "Show unread threads only")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.d1a88df9a8',
+ 'Show unread threads only'
+ )}
>
- {translate("auto.components.activity.ActivityPrototypePage.d1a88df9a8", "Show unread threads only")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.d1a88df9a8',
+ 'Show unread threads only'
+ )}
+
{/* Why (overflow menu): "Mark all read" is a low-frequency,
destructive-feeling action — parking it behind a `…` keeps
@@ -1671,13 +1730,21 @@ export default function ActivityPrototypePage(): React.JSX.Element {
variant="outline"
size="sm"
className="size-8 shrink-0 border-input bg-transparent p-0 text-muted-foreground shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-transparent dark:hover:bg-accent dark:hover:text-accent-foreground"
- aria-label={translate("auto.components.activity.ActivityPrototypePage.db8a1878b5", "Thread list options")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityPrototypePage.db8a1878b5',
+ 'Thread list options'
+ )}
>
- {translate("auto.components.activity.ActivityPrototypePage.a472a14700", "More options")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.a472a14700',
+ 'More options'
+ )}
+
setCompactMode(checked === true)}
onSelect={(event) => event.preventDefault()}
>
- {translate("auto.components.activity.ActivityPrototypePage.f70e4bec47", "Compact mode")}
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.f70e4bec47',
+ 'Compact mode'
+ )}
+
markAllThreadsRead()}
disabled={!hasUnreadThreads}
>
- {translate("auto.components.activity.ActivityPrototypePage.023ff75afe", "Mark all read")}
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.023ff75afe',
+ 'Mark all read'
+ )}
+
{visibleThreadGroups.map((group) => (
-
+
{group.threads.map((thread) => (
- {translate("auto.components.activity.ActivityPrototypePage.7cd632006b", "No agent activity matches these filters.")}
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.7cd632006b',
+ 'No agent activity matches these filters.'
+ )}
+
) : null}
{storeData.worktreeMap.has(selectedThread.worktree.id)
- ? translate("auto.components.activity.ActivityPrototypePage.afdc2139a8", "Agent terminal closed. Open a new terminal in this workspace to continue.")
- : translate("auto.components.activity.ActivityPrototypePage.22b22034bc", "Standalone terminal unavailable in Activity.")}
+ ? translate(
+ 'auto.components.activity.ActivityPrototypePage.afdc2139a8',
+ 'Agent terminal closed. Open a new terminal in this workspace to continue.'
+ )
+ : translate(
+ 'auto.components.activity.ActivityPrototypePage.22b22034bc',
+ 'Standalone terminal unavailable in Activity.'
+ )}
)
}
@@ -1815,12 +1913,22 @@ export default function ActivityPrototypePage(): React.JSX.Element {
{visiblePortalUnavailable ? (
- {translate("auto.components.activity.ActivityPrototypePage.8de7c5beaa", "Terminal unavailable")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.8de7c5beaa',
+ 'Terminal unavailable'
+ )}
+
) : showTerminalLoadingLabel ? (
- {translate("auto.components.activity.ActivityPrototypePage.1b633f5c1e", "Connecting terminal...")}
+
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.1b633f5c1e',
+ 'Connecting terminal...'
+ )}
+
) : null}
@@ -1834,11 +1942,19 @@ export default function ActivityPrototypePage(): React.JSX.Element {
{visibleThreads.length === 0 ? (
<>
- {translate("auto.components.activity.ActivityPrototypePage.e3db9892f6", "No activity yet.")}>
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.e3db9892f6',
+ 'No activity yet.'
+ )}
+ >
) : (
<>
- {translate("auto.components.activity.ActivityPrototypePage.cf780197a1", "Select an agent to view its activity")}>
+ {translate(
+ 'auto.components.activity.ActivityPrototypePage.cf780197a1',
+ 'Select an agent to view its activity'
+ )}
+ >
)}
)}
diff --git a/src/renderer/src/components/activity/ActivityTitlebarControls.tsx b/src/renderer/src/components/activity/ActivityTitlebarControls.tsx
index 9516662e704..93ca4c65c1c 100644
--- a/src/renderer/src/components/activity/ActivityTitlebarControls.tsx
+++ b/src/renderer/src/components/activity/ActivityTitlebarControls.tsx
@@ -27,18 +27,29 @@ export function ActivityTitlebarControls(): React.JSX.Element {
variant="ghost"
size="icon-xs"
onClick={closeActivityPage}
- aria-label={translate("auto.components.activity.ActivityTitlebarControls.dc708f3eff", "Close agents")}
+ aria-label={translate(
+ 'auto.components.activity.ActivityTitlebarControls.dc708f3eff',
+ 'Close agents'
+ )}
>
- {translate("auto.components.activity.ActivityTitlebarControls.dc708f3eff", "Close agents")}
+ {translate(
+ 'auto.components.activity.ActivityTitlebarControls.dc708f3eff',
+ 'Close agents'
+ )}
+
- {translate("auto.components.activity.ActivityTitlebarControls.d6a8de3934", "agents")}
+
+ {translate('auto.components.activity.ActivityTitlebarControls.d6a8de3934', 'agents')}
+
- {unreadCount} {translate("auto.components.activity.ActivityTitlebarControls.f915168c8e", "unread")}
+ {unreadCount}{' '}
+ {translate('auto.components.activity.ActivityTitlebarControls.f915168c8e', 'unread')}
+
)
diff --git a/src/renderer/src/components/agent/AgentCombobox.tsx b/src/renderer/src/components/agent/AgentCombobox.tsx
index ef8f492db4c..fb15e5722a5 100644
--- a/src/renderer/src/components/agent/AgentCombobox.tsx
+++ b/src/renderer/src/components/agent/AgentCombobox.tsx
@@ -102,7 +102,9 @@ function renderItem({
- {isDefault ? translate("auto.components.agent.AgentCombobox.1b0d6965fa", "Current default") : translate("auto.components.agent.AgentCombobox.9c6b59fe58", "Set as default")}
+ {isDefault
+ ? translate('auto.components.agent.AgentCombobox.1b0d6965fa', 'Current default')
+ : translate('auto.components.agent.AgentCombobox.9c6b59fe58', 'Set as default')}
@@ -286,7 +288,9 @@ export default function AgentCombobox({
) : (
- {translate("auto.components.agent.AgentCombobox.986f946354", "Blank Terminal")}
+
+ {translate('auto.components.agent.AgentCombobox.986f946354', 'Blank Terminal')}
+
)}
@@ -307,12 +311,20 @@ export default function AgentCombobox({
- {translate("auto.components.agent.AgentCombobox.579c768bde", "No agents match your search.")}
+
+ {translate(
+ 'auto.components.agent.AgentCombobox.579c768bde',
+ 'No agents match your search.'
+ )}
+
{blankMatchesQuery
? renderItem({
key: BLANK_VALUE,
@@ -322,7 +334,10 @@ export default function AgentCombobox({
onSelect: () => handleSelect(null),
onSetDefault: onSetDefault ? () => onSetDefault('blank') : undefined,
icon: ,
- label: translate("auto.components.agent.AgentCombobox.986f946354", "Blank Terminal")
+ label: translate(
+ 'auto.components.agent.AgentCombobox.986f946354',
+ 'Blank Terminal'
+ )
})
: null}
{filteredAgents.map((agent) =>
@@ -348,7 +363,8 @@ export default function AgentCombobox({
onMouseEnter={() => setCommandValue('')}
className="h-9 w-full justify-start rounded-none px-3 text-xs font-normal text-muted-foreground"
>
- {translate("auto.components.agent.AgentCombobox.19522e25ee", "Manage agents")}
+ {translate('auto.components.agent.AgentCombobox.19522e25ee', 'Manage agents')}
+
) : null}
diff --git a/src/renderer/src/components/agent/AgentSettingsDialog.tsx b/src/renderer/src/components/agent/AgentSettingsDialog.tsx
index 86e05aea296..dd33b771a92 100644
--- a/src/renderer/src/components/agent/AgentSettingsDialog.tsx
+++ b/src/renderer/src/components/agent/AgentSettingsDialog.tsx
@@ -34,9 +34,15 @@ export default function AgentSettingsDialog({
agents are detected. */}
- {translate("auto.components.agent.AgentSettingsDialog.fc0268e4ed", "Agents")}
+
+ {translate('auto.components.agent.AgentSettingsDialog.fc0268e4ed', 'Agents')}
+
- {translate("auto.components.agent.AgentSettingsDialog.50cdb57c03", "Manage AI agents, set a default, and customize commands.")}
+ {translate(
+ 'auto.components.agent.AgentSettingsDialog.50cdb57c03',
+ 'Manage AI agents, set a default, and customize commands.'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx b/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx
index 39c79c4a843..311d6bf4d98 100644
--- a/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx
+++ b/src/renderer/src/components/automations/AutomationCustomCronPanel.tsx
@@ -17,10 +17,22 @@ export function getCronScheduleStatusLabel(
): { kind: 'empty' | 'invalid' | 'valid'; label: string } {
const trimmed = schedule.trim()
if (!trimmed) {
- return { kind: 'empty', label: translate("auto.components.automations.AutomationCustomCronPanel.968e66d686", "Enter a five-field cron.") }
+ return {
+ kind: 'empty',
+ label: translate(
+ 'auto.components.automations.AutomationCustomCronPanel.968e66d686',
+ 'Enter a five-field cron.'
+ )
+ }
}
if (!validateSchedule(trimmed)) {
- return { kind: 'invalid', label: translate("auto.components.automations.AutomationCustomCronPanel.e81a02d61b", "Enter a valid five-field cron before saving.") }
+ return {
+ kind: 'invalid',
+ label: translate(
+ 'auto.components.automations.AutomationCustomCronPanel.e81a02d61b',
+ 'Enter a valid five-field cron before saving.'
+ )
+ }
}
const formatted = formatAutomationSchedule(trimmed)
return { kind: 'valid', label: formatted === 'Custom schedule' ? 'Valid custom cron' : formatted }
@@ -50,7 +62,12 @@ export function AutomationCustomCronPanel({
return (
-
+
- {customScheduleStatus.kind === "invalid" ? (
+ {customScheduleStatus.kind === 'invalid' ? (
) : (
diff --git a/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx b/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx
index 6069d78abeb..b1712f5250c 100644
--- a/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx
+++ b/src/renderer/src/components/automations/AutomationEditorDialogHeader.tsx
@@ -69,17 +69,35 @@ export function AutomationEditorDialogHeader({
{isEditing
- ? translate("auto.components.automations.AutomationEditorDialogHeader.17086b48ee", "Edit automation")
+ ? translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.17086b48ee',
+ 'Edit automation'
+ )
: isEditingExternal
- ? translate("auto.components.automations.AutomationEditorDialogHeader.03142e7721", "Edit Hermes automation")
+ ? translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.03142e7721',
+ 'Edit Hermes automation'
+ )
: isHermesCreate
- ? translate("auto.components.automations.AutomationEditorDialogHeader.0a75e5e2fa", "Create Hermes automation")
- : translate("auto.components.automations.AutomationEditorDialogHeader.4133d33862", "Create automation")}
+ ? translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.0a75e5e2fa',
+ 'Create Hermes automation'
+ )
+ : translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.4133d33862',
+ 'Create automation'
+ )}
onDraftNameChange(event.target.value)}
/>
@@ -97,9 +115,17 @@ export function AutomationEditorDialogHeader({
className="grid grid-cols-2"
>
- {translate("auto.components.automations.AutomationEditorDialogHeader.6f309eef8d", "Orca")}
+ {translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.6f309eef8d',
+ 'Orca'
+ )}
+
- {translate("auto.components.automations.AutomationEditorDialogHeader.7e35393632", "Hermes")}
+ {translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.7e35393632',
+ 'Hermes'
+ )}
+
@@ -110,7 +136,11 @@ export function AutomationEditorDialogHeader({
className={pickerTriggerClassName}
>
- {translate("auto.components.automations.AutomationEditorDialogHeader.31f9253920", "Use template")}
+ {translate(
+ 'auto.components.automations.AutomationEditorDialogHeader.31f9253920',
+ 'Use template'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx b/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx
index 86d15307993..01e68d038df 100644
--- a/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx
+++ b/src/renderer/src/components/automations/AutomationMissedRunGraceField.tsx
@@ -28,18 +28,29 @@ export function AutomationMissedRunGraceField({
- {translate("auto.components.automations.AutomationMissedRunGraceField.fc089e5fde", "Grace")}
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.fc089e5fde',
+ 'Grace'
+ )}
+
- {translate("auto.components.automations.AutomationMissedRunGraceField.3d70c185c8", "If Orca or the execution host was unavailable at the scheduled time, Orca runs one missed occurrence when it becomes available within this window. Older missed runs are skipped.")}
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.3d70c185c8',
+ 'If Orca or the execution host was unavailable at the scheduled time, Orca runs one missed occurrence when it becomes available within this window. Older missed runs are skipped.'
+ )}
+
}
@@ -55,13 +66,48 @@ export function AutomationMissedRunGraceField({
- {translate("auto.components.automations.AutomationMissedRunGraceField.529dc6c0b7", "No grace")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.e5ad263ae5", "30 minutes")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.521f77cd58", "1 hour")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.2dc9ee84d0", "3 hours")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.ba50e2a230", "12 hours")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.adbab51feb", "24 hours")}
- {translate("auto.components.automations.AutomationMissedRunGraceField.0f4459e91d", "48 hours")}
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.529dc6c0b7',
+ 'No grace'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.e5ad263ae5',
+ '30 minutes'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.521f77cd58',
+ '1 hour'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.2dc9ee84d0',
+ '3 hours'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.ba50e2a230',
+ '12 hours'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.adbab51feb',
+ '24 hours'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationMissedRunGraceField.0f4459e91d',
+ '48 hours'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationPrecheckFields.tsx b/src/renderer/src/components/automations/AutomationPrecheckFields.tsx
index 8621ae0d435..07f3643b450 100644
--- a/src/renderer/src/components/automations/AutomationPrecheckFields.tsx
+++ b/src/renderer/src/components/automations/AutomationPrecheckFields.tsx
@@ -24,11 +24,19 @@ export function AutomationPrecheckFields({
}: AutomationPrecheckFieldsProps): React.JSX.Element {
return (
<>
-
+
onDraftChange((current) => ({
...current,
@@ -38,7 +46,12 @@ export function AutomationPrecheckFields({
className="min-h-[68px] w-full resize-none rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-xs outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30"
/>
-
+
- {translate("auto.components.automations.AutomationPrecheckFields.51e28cdad9", "30 sec")}
- {translate("auto.components.automations.AutomationPrecheckFields.c820119736", "1 min")}
- {translate("auto.components.automations.AutomationPrecheckFields.d84d3765fd", "2 min")}
- {translate("auto.components.automations.AutomationPrecheckFields.bf49585b3c", "5 min")}
- {translate("auto.components.automations.AutomationPrecheckFields.d2a2ac89ac", "10 min")}
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.51e28cdad9',
+ '30 sec'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.c820119736',
+ '1 min'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.d84d3765fd',
+ '2 min'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.bf49585b3c',
+ '5 min'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.AutomationPrecheckFields.d2a2ac89ac',
+ '10 min'
+ )}
+
diff --git a/src/renderer/src/components/automations/AutomationRunHistory.tsx b/src/renderer/src/components/automations/AutomationRunHistory.tsx
index 90c3113f19c..be8a76dcd5e 100644
--- a/src/renderer/src/components/automations/AutomationRunHistory.tsx
+++ b/src/renderer/src/components/automations/AutomationRunHistory.tsx
@@ -48,16 +48,28 @@ export function AutomationRunHistory({
return (
-
{translate("auto.components.automations.AutomationRunHistory.53fc5f07ab", "Run history")}
+
+ {translate('auto.components.automations.AutomationRunHistory.53fc5f07ab', 'Run history')}
+
{runCountLabel}
-
{translate("auto.components.automations.AutomationRunHistory.8faaa00726", "Run")}
-
{translate("auto.components.automations.AutomationRunHistory.149c0b49c7", "Workspace")}
-
{translate("auto.components.automations.AutomationRunHistory.86a248187e", "Spend")}
-
{translate("auto.components.automations.AutomationRunHistory.13988187b3", "Tokens")}
-
{translate("auto.components.automations.AutomationRunHistory.9974a2b429", "Status")}
+
+ {translate('auto.components.automations.AutomationRunHistory.8faaa00726', 'Run')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.149c0b49c7', 'Workspace')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.86a248187e', 'Spend')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.13988187b3', 'Tokens')}
+
+
+ {translate('auto.components.automations.AutomationRunHistory.9974a2b429', 'Status')}
+
{runs.map((run) => {
@@ -115,9 +127,12 @@ export function AutomationRunHistory({
}
title={usageLabel}
>
- {run.usage?.status === "known"
+ {run.usage?.status === 'known'
? formatAutomationTokens(run.usage.totalTokens)
- : translate("auto.components.automations.AutomationRunHistory.a00e38d1a3", "n/a")}
+ : translate(
+ 'auto.components.automations.AutomationRunHistory.a00e38d1a3',
+ 'n/a'
+ )}
@@ -128,7 +143,12 @@ export function AutomationRunHistory({
)
})}
{runs.length === 0 ? (
- {translate("auto.components.automations.AutomationRunHistory.402651bfb6", "No runs yet.")}
+
+ {translate(
+ 'auto.components.automations.AutomationRunHistory.402651bfb6',
+ 'No runs yet.'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/automations/AutomationRunPageFrame.tsx b/src/renderer/src/components/automations/AutomationRunPageFrame.tsx
index dd7995f94bc..30c323d6dc8 100644
--- a/src/renderer/src/components/automations/AutomationRunPageFrame.tsx
+++ b/src/renderer/src/components/automations/AutomationRunPageFrame.tsx
@@ -34,7 +34,10 @@ export function AutomationRunPageFrame({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.automations.AutomationRunPageFrame.33741dd973", "Back to runs")}
+ aria-label={translate(
+ 'auto.components.automations.AutomationRunPageFrame.33741dd973',
+ 'Back to runs'
+ )}
onClick={onBack}
>
@@ -46,7 +49,10 @@ export function AutomationRunPageFrame({
{breadcrumbs.length > 0 ? (
{breadcrumbs.map((breadcrumb, index) => (
diff --git a/src/renderer/src/components/automations/AutomationSchedulePicker.tsx b/src/renderer/src/components/automations/AutomationSchedulePicker.tsx
index 1786770bfa5..eb203f9c36c 100644
--- a/src/renderer/src/components/automations/AutomationSchedulePicker.tsx
+++ b/src/renderer/src/components/automations/AutomationSchedulePicker.tsx
@@ -172,7 +172,12 @@ export function AutomationSchedulePicker({
className="popover-scroll-content scrollbar-sleek max-h-[var(--radix-popover-content-available-height)] w-[min(var(--radix-popover-trigger-width),calc(100vw-2rem))] min-w-[min(22rem,calc(100vw-2rem))] max-w-[calc(100vw-2rem)] overflow-y-auto p-3"
>
-
+
@@ -194,7 +199,7 @@ export function AutomationSchedulePicker({
- {draft.preset === "custom" ? (
+ {draft.preset === 'custom' ? (
) : (
<>
- {draft.preset === "weekly" ? (
-
+ {draft.preset === 'weekly' ? (
+
@@ -224,8 +234,13 @@ export function AutomationSchedulePicker({
) : null}
- {draft.preset === "hourly" ? (
-
+ {draft.preset === 'hourly' ? (
+
@@ -249,7 +264,12 @@ export function AutomationSchedulePicker({
) : (
-
+
@@ -286,7 +309,10 @@ export function AutomationSchedulePicker({
}
>
@@ -310,7 +336,10 @@ export function AutomationSchedulePicker({
}
>
diff --git a/src/renderer/src/components/automations/AutomationSessionField.tsx b/src/renderer/src/components/automations/AutomationSessionField.tsx
index 08f384ca8ce..b6aef00ebd8 100644
--- a/src/renderer/src/components/automations/AutomationSessionField.tsx
+++ b/src/renderer/src/components/automations/AutomationSessionField.tsx
@@ -21,18 +21,26 @@ export function AutomationSessionField({
- {translate("auto.components.automations.AutomationSessionField.5ad314118e", "Session")}
+ {translate('auto.components.automations.AutomationSessionField.5ad314118e', 'Session')}
+
- {translate("auto.components.automations.AutomationSessionField.b675112193", "Reuse sends future runs to the previous live automation session. If that session is gone, Orca starts a fresh one.")}
+ {translate(
+ 'auto.components.automations.AutomationSessionField.b675112193',
+ 'Reuse sends future runs to the previous live automation session. If that session is gone, Orca starts a fresh one.'
+ )}
+
}
@@ -55,9 +63,11 @@ export function AutomationSessionField({
className="grid w-full grid-cols-2"
>
- {translate("auto.components.automations.AutomationSessionField.c90888ee94", "Fresh")}
+ {translate('auto.components.automations.AutomationSessionField.c90888ee94', 'Fresh')}
+
- {translate("auto.components.automations.AutomationSessionField.f3c76dce51", "Reuse")}
+ {translate('auto.components.automations.AutomationSessionField.f3c76dce51', 'Reuse')}
+
)
diff --git a/src/renderer/src/components/automations/CreateFromPicker.tsx b/src/renderer/src/components/automations/CreateFromPicker.tsx
index 8bb63717e2f..8b89da1852b 100644
--- a/src/renderer/src/components/automations/CreateFromPicker.tsx
+++ b/src/renderer/src/components/automations/CreateFromPicker.tsx
@@ -176,7 +176,12 @@ export function CreateFromPicker({
className={cn('h-9 w-full justify-between px-3 text-sm font-normal', triggerClassName)}
>
- {translate("auto.components.automations.CreateFromPicker.dd3841b442", "Branch from")}
+
+ {translate(
+ 'auto.components.automations.CreateFromPicker.dd3841b442',
+ 'Branch from'
+ )}
+
{selectedLabel}
@@ -195,11 +200,22 @@ export function CreateFromPicker({
ref={setInputNode}
value={query}
onValueChange={setQuery}
- placeholder={translate("auto.components.automations.CreateFromPicker.f061f49e3f", "Search repo branches...")}
+ placeholder={translate(
+ 'auto.components.automations.CreateFromPicker.f061f49e3f',
+ 'Search repo branches...'
+ )}
/>
- {isSearching ? translate("auto.components.automations.CreateFromPicker.9ce96621f4", "Searching branches...") : translate("auto.components.automations.CreateFromPicker.79512f22a7", "No branches found.")}
+ {isSearching
+ ? translate(
+ 'auto.components.automations.CreateFromPicker.9ce96621f4',
+ 'Searching branches...'
+ )
+ : translate(
+ 'auto.components.automations.CreateFromPicker.79512f22a7',
+ 'No branches found.'
+ )}
- {effectiveDefault ? translate("auto.components.automations.CreateFromPicker.e53d306056", "{{value0}} (default)", { value0: effectiveDefault }) : translate("auto.components.automations.CreateFromPicker.ef6d762538", "Project default")}
+ {effectiveDefault
+ ? translate(
+ 'auto.components.automations.CreateFromPicker.e53d306056',
+ '{{value0}} (default)',
+ { value0: effectiveDefault }
+ )
+ : translate(
+ 'auto.components.automations.CreateFromPicker.ef6d762538',
+ 'Project default'
+ )}
{branchOptions
diff --git a/src/renderer/src/components/automations/ExternalAutomationManagers.tsx b/src/renderer/src/components/automations/ExternalAutomationManagers.tsx
index 378d9c9cfeb..e116564cbdd 100644
--- a/src/renderer/src/components/automations/ExternalAutomationManagers.tsx
+++ b/src/renderer/src/components/automations/ExternalAutomationManagers.tsx
@@ -111,10 +111,24 @@ export function ExternalAutomationManagers({
-
{translate("auto.components.automations.ExternalAutomationManagers.c6695e6fbd", "External automations")}
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.c6695e6fbd',
+ 'External automations'
+ )}
+
- {automationCount} {automationCount === 1 ? translate("auto.components.automations.ExternalAutomationManagers.701515f010", "automation") : translate("auto.components.automations.ExternalAutomationManagers.e2532150ed", "automations")}
+ {automationCount}{' '}
+ {automationCount === 1
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.701515f010',
+ 'automation'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.e2532150ed',
+ 'automations'
+ )}
@@ -127,9 +141,18 @@ export function ExternalAutomationManagers({
{getProviderLabel(manager)} / {getTargetKindLabel(manager)} ·{' '}
{manager.status === 'available'
? manager.canManage
- ? translate("auto.components.automations.ExternalAutomationManagers.0a2d4359a8", "Manageable")
- : translate("auto.components.automations.ExternalAutomationManagers.dbdcec22bd", "Read-only")
- : translate("auto.components.automations.ExternalAutomationManagers.92405f1431", "Unavailable")}
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.0a2d4359a8',
+ 'Manageable'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.dbdcec22bd',
+ 'Read-only'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.92405f1431',
+ 'Unavailable'
+ )}
{manager.error ? ` - ${manager.error}` : null}
@@ -149,19 +172,45 @@ export function ExternalAutomationManagers({
{job.name}
- {job.enabled ? translate("auto.components.automations.ExternalAutomationManagers.b3feba84c7", "Active") : translate("auto.components.automations.ExternalAutomationManagers.2b0adbce21", "Paused")}
+ {job.enabled
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.b3feba84c7',
+ 'Active'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.2b0adbce21',
+ 'Paused'
+ )}
{scheduleDisplay.label}
- {translate("auto.components.automations.ExternalAutomationManagers.20fd7a3a15", "next")} {formatExternalDate(job.nextRunAt, now)} · {getProviderLabel(manager)}{' '}
- / {manager.targetLabel}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.20fd7a3a15',
+ 'next'
+ )}{' '}
+ {formatExternalDate(job.nextRunAt, now)} · {getProviderLabel(manager)} /{' '}
+ {manager.targetLabel}
- {manager.provider === "hermes" ? (
+ {manager.provider === 'hermes' ? (
- {job.runCount} {job.runCount === 1 ? translate("auto.components.automations.ExternalAutomationManagers.8e9165af08", "run") : translate("auto.components.automations.ExternalAutomationManagers.e66091daf4", "runs")} {translate("auto.components.automations.ExternalAutomationManagers.844f1acb72", "found")}
+ {job.runCount}{' '}
+ {job.runCount === 1
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.8e9165af08',
+ 'run'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.e66091daf4',
+ 'runs'
+ )}{' '}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.844f1acb72',
+ 'found'
+ )}
+
) : null}
{job.promptPreview || job.lastError ? (
@@ -170,12 +219,19 @@ export function ExternalAutomationManagers({
) : null}
- {translate("auto.components.automations.ExternalAutomationManagers.5820648765", "Last")}{formatExternalDate(job.lastRunAt, now)}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.5820648765',
+ 'Last'
+ )}
+ {formatExternalDate(job.lastRunAt, now)}
{job.lastStatus ? ` · ${job.lastStatus}` : null}
onAction(manager, job, 'run')}
>
@@ -185,9 +241,12 @@ export function ExternalAutomationManagers({
)}
- {manager.provider === "hermes" ? (
+ {manager.provider === 'hermes' ? (
onEdit?.(manager, job)}
>
@@ -196,7 +255,15 @@ export function ExternalAutomationManagers({
) : null}
onAction(manager, job, job.enabled ? 'pause' : 'resume')}
@@ -211,7 +278,10 @@ export function ExternalAutomationManagers({
)}
onAction(manager, job, 'delete')}
@@ -223,7 +293,7 @@ export function ExternalAutomationManagers({
)}
- {manager.provider === "hermes" ? (
+ {manager.provider === 'hermes' ? (
- {translate("auto.components.automations.ExternalAutomationManagers.3d58d5b67d", "No")}{' '}
- {manager.provider === 'hermes' ? translate("auto.components.automations.ExternalAutomationManagers.766abf833c", "Hermes") : translate("auto.components.automations.ExternalAutomationManagers.5524365227", "OpenClaw")} {translate("auto.components.automations.ExternalAutomationManagers.6da3bfba4b", "automations found.")}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.3d58d5b67d',
+ 'No'
+ )}{' '}
+ {manager.provider === 'hermes'
+ ? translate(
+ 'auto.components.automations.ExternalAutomationManagers.766abf833c',
+ 'Hermes'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationManagers.5524365227',
+ 'OpenClaw'
+ )}{' '}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.6da3bfba4b',
+ 'automations found.'
+ )}
+
) : null}
))}
{managers.length === 0 ? (
- {translate("auto.components.automations.ExternalAutomationManagers.e02f970595", "No external automation managers found.")}
+ {translate(
+ 'auto.components.automations.ExternalAutomationManagers.e02f970595',
+ 'No external automation managers found.'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx b/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx
index ea9e9df6976..aa8ff9666c7 100644
--- a/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx
+++ b/src/renderer/src/components/automations/ExternalAutomationRunTable.tsx
@@ -183,7 +183,9 @@ export function ExternalAutomationRunTable({
-
{translate("auto.components.automations.ExternalAutomationRunTable.2d4388a908", "Runs")}
+
+ {translate('auto.components.automations.ExternalAutomationRunTable.2d4388a908', 'Runs')}
+
{isLoading ?
: null}
{fetchError ? (
@@ -197,7 +199,13 @@ export function ExternalAutomationRunTable({
) : null}
- {totalCount} {totalCount === 1 ? translate("auto.components.automations.ExternalAutomationRunTable.872d032d05", "run") : translate("auto.components.automations.ExternalAutomationRunTable.d5527d8fe7", "runs")}
+ {totalCount}{' '}
+ {totalCount === 1
+ ? translate('auto.components.automations.ExternalAutomationRunTable.872d032d05', 'run')
+ : translate(
+ 'auto.components.automations.ExternalAutomationRunTable.d5527d8fe7',
+ 'runs'
+ )}
@@ -205,9 +213,24 @@ export function ExternalAutomationRunTable({
- {translate("auto.components.automations.ExternalAutomationRunTable.d4b34feb66", "Run time")}
- {translate("auto.components.automations.ExternalAutomationRunTable.a813df9808", "Preview")}
- {translate("auto.components.automations.ExternalAutomationRunTable.be551397ca", "Status")}
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationRunTable.d4b34feb66',
+ 'Run time'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationRunTable.a813df9808',
+ 'Preview'
+ )}
+
+
+ {translate(
+ 'auto.components.automations.ExternalAutomationRunTable.be551397ca',
+ 'Status'
+ )}
+
{visibleRuns.map((run) => (
@@ -248,7 +271,15 @@ export function ExternalAutomationRunTable({
) : (
- {isLoading ? translate("auto.components.automations.ExternalAutomationRunTable.8ea934cacf", "Loading runs...") : translate("auto.components.automations.ExternalAutomationRunTable.9c080765ff", "No Hermes runs found yet.")}
+ {isLoading
+ ? translate(
+ 'auto.components.automations.ExternalAutomationRunTable.8ea934cacf',
+ 'Loading runs...'
+ )
+ : translate(
+ 'auto.components.automations.ExternalAutomationRunTable.9c080765ff',
+ 'No Hermes runs found yet.'
+ )}
)}
@@ -256,7 +287,9 @@ export function ExternalAutomationRunTable({
- {pageStart}-{pageEnd} {translate("auto.components.automations.ExternalAutomationRunTable.7475c0ce96", "of")}{totalCount}
+ {pageStart}-{pageEnd}{' '}
+ {translate('auto.components.automations.ExternalAutomationRunTable.7475c0ce96', 'of')}
+ {totalCount}
@@ -264,7 +297,10 @@ export function ExternalAutomationRunTable({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.automations.ExternalAutomationRunTable.52d468a0b8", "Previous run page")}
+ aria-label={translate(
+ 'auto.components.automations.ExternalAutomationRunTable.52d468a0b8',
+ 'Previous run page'
+ )}
disabled={page === 0 || isLoading}
onClick={() => handlePageChange(Math.max(0, page - 1))}
>
@@ -277,7 +313,10 @@ export function ExternalAutomationRunTable({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.automations.ExternalAutomationRunTable.0ba9c0a95c", "Next run page")}
+ aria-label={translate(
+ 'auto.components.automations.ExternalAutomationRunTable.0ba9c0a95c',
+ 'Next run page'
+ )}
disabled={page >= totalPages - 1 || isLoading}
onClick={() => handlePageChange(Math.min(totalPages - 1, page + 1))}
>
diff --git a/src/renderer/src/components/automations/HermesCronOutputView.tsx b/src/renderer/src/components/automations/HermesCronOutputView.tsx
index 0a31387e89d..4d8dabaea30 100644
--- a/src/renderer/src/components/automations/HermesCronOutputView.tsx
+++ b/src/renderer/src/components/automations/HermesCronOutputView.tsx
@@ -303,7 +303,10 @@ export function HermesCronOutputView({ content }: { content: string }): React.JS
) : null}
{errorSection ? (
-
+
+
- {selected?.displayName ?? translate("auto.components.automations.WorkspaceCombobox.66a0cd9628", "Select workspace")}
+ {selected?.displayName ??
+ translate(
+ 'auto.components.automations.WorkspaceCombobox.66a0cd9628',
+ 'Select workspace'
+ )}
@@ -89,9 +93,20 @@ export function WorkspaceCombobox({
}}
>
-
+
- {translate("auto.components.automations.WorkspaceCombobox.ee5b280eba", "No workspaces found.")}
+
+ {translate(
+ 'auto.components.automations.WorkspaceCombobox.ee5b280eba',
+ 'No workspaces found.'
+ )}
+
{worktrees.map((worktree) => (
setQuery(e.target.value)}
- placeholder={translate("auto.components.browser.pane.BrowserFind.636a69cd66", "Find in page...")}
+ placeholder={translate(
+ 'auto.components.browser.pane.BrowserFind.636a69cd66',
+ 'Find in page...'
+ )}
className="min-w-0 flex-1 border-none bg-transparent text-sm text-white outline-none placeholder:text-zinc-500"
/>
{query ? (
- {totalMatches > 0 ? translate("auto.components.browser.pane.BrowserFind.fc63f336aa", "{{value0}} of {{value1}}", { value0: activeMatch, value1: totalMatches }) : translate("auto.components.browser.pane.BrowserFind.7baca7b1b8", "No matches")}
+ {totalMatches > 0
+ ? translate(
+ 'auto.components.browser.pane.BrowserFind.fc63f336aa',
+ '{{value0}} of {{value1}}',
+ { value0: activeMatch, value1: totalMatches }
+ )
+ : translate('auto.components.browser.pane.BrowserFind.7baca7b1b8', 'No matches')}
) : null}
@@ -170,7 +179,7 @@ export default function BrowserFind({
size="icon-xs"
onClick={findPrevious}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.browser.pane.BrowserFind.ca7aebbd7f", "Previous match")}
+ title={translate('auto.components.browser.pane.BrowserFind.ca7aebbd7f', 'Previous match')}
>
@@ -181,7 +190,7 @@ export default function BrowserFind({
size="icon-xs"
onClick={findNext}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.browser.pane.BrowserFind.5c0c02ae76", "Next match")}
+ title={translate('auto.components.browser.pane.BrowserFind.5c0c02ae76', 'Next match')}
>
@@ -194,7 +203,7 @@ export default function BrowserFind({
size="icon-xs"
onClick={onClose}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.browser.pane.BrowserFind.c9d5f63fdc", "Close")}
+ title={translate('auto.components.browser.pane.BrowserFind.c9d5f63fdc', 'Close')}
>
diff --git a/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx b/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx
index 52e063f710e..4bb0bd4d4eb 100644
--- a/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserMobileDriverOverlay.tsx
@@ -53,15 +53,33 @@ export function BrowserMobileDriverOverlay({ driver, onTakeBack }: Props): React
●
- {translate("auto.components.browser.pane.BrowserMobileDriverOverlay.20539eca03", "Mobile is driving this browser")}
+
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.20539eca03',
+ 'Mobile is driving this browser'
+ )}
+
+
+
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.d9768ec642',
+ 'Browser input is paused'
+ )}
-
{translate("auto.components.browser.pane.BrowserMobileDriverOverlay.d9768ec642", "Browser input is paused")}
- {translate("auto.components.browser.pane.BrowserMobileDriverOverlay.f4ecd61552", "This tab is being controlled from your phone. Take back to use it on desktop.")}
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.f4ecd61552',
+ 'This tab is being controlled from your phone. Take back to use it on desktop.'
+ )}
+
{/* autoFocus puts keyboard users on the recovery action when the lock appears. */}
- {translate("auto.components.browser.pane.BrowserMobileDriverOverlay.a6914ee43f", "Take back")}
+ {translate(
+ 'auto.components.browser.pane.BrowserMobileDriverOverlay.a6914ee43f',
+ 'Take back'
+ )}
+
diff --git a/src/renderer/src/components/browser-pane/BrowserPane.tsx b/src/renderer/src/components/browser-pane/BrowserPane.tsx
index 0491106e750..74ae96ee901 100644
--- a/src/renderer/src/components/browser-pane/BrowserPane.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserPane.tsx
@@ -4173,6 +4173,10 @@ function BrowserPagePane({
[annotationBannerSendModeId, annotationTraySendModeId, closeAgentSendPopoverTargetMode]
)
+ const handleBrowserAnnotationsSentToAgent = useCallback((): void => {
+ recordFeatureInteraction('browser-annotations-sent-to-agent')
+ }, [recordFeatureInteraction])
+
const handleClearBrowserAnnotations = useCallback((): void => {
if (browserAnnotationsRef.current.length === 0) {
return
@@ -4877,6 +4881,7 @@ function BrowserPagePane({
prompt={browserAnnotationsPrompt}
promptDelivery="submit-after-ready"
launchSource="notes_send"
+ onPromptDelivered={handleBrowserAnnotationsSentToAgent}
/>
@@ -5136,6 +5141,7 @@ function BrowserPagePane({
prompt={browserAnnotationsPrompt}
promptDelivery="submit-after-ready"
launchSource="notes_send"
+ onPromptDelivered={handleBrowserAnnotationsSentToAgent}
/>
diff --git a/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx b/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx
index 894153de538..855bed0b36b 100644
--- a/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx
+++ b/src/renderer/src/components/browser-pane/GrabConfirmationSheet.tsx
@@ -128,9 +128,14 @@ export default function GrabConfirmationSheet({
- {translate("auto.components.browser.pane.GrabConfirmationSheet.f3575229df", "Grab")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.f3575229df', 'Grab')}
+
- {translate("auto.components.browser.pane.GrabConfirmationSheet.50f7114f99", "Review before attaching. Captured page context may include visible site content.")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.50f7114f99',
+ 'Review before attaching. Captured page context may include visible site content.'
+ )}
+
@@ -147,7 +152,10 @@ export default function GrabConfirmationSheet({
@@ -156,7 +164,11 @@ export default function GrabConfirmationSheet({
{/* Element summary */}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.a759d8f866", "Selected Element")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.a759d8f866',
+ 'Selected Element'
+ )}
+
@@ -164,14 +176,20 @@ export default function GrabConfirmationSheet({
{target.accessibility.role ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.d053db279d", "role=")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.d053db279d',
+ 'role='
+ )}
+
) : null}
{target.accessibility.accessibleName ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a", "\"")}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a", "\"")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a', '"')}
+
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.eb98a0971a', '"')}
+
) : null}
@@ -185,10 +203,19 @@ export default function GrabConfirmationSheet({
{/* Page info */}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.9098b118ab", "Page")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.9098b118ab', 'Page')}
+
-
+
@@ -200,7 +227,8 @@ export default function GrabConfirmationSheet({
{target.htmlSnippet ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.7d1480fbf1", "HTML")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.7d1480fbf1', 'HTML')}
+
@@ -211,7 +239,11 @@ export default function GrabConfirmationSheet({
{nearbyText.length > 0 ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.effd75e330", "Nearby Context")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.effd75e330',
+ 'Nearby Context'
+ )}
+
{nearbyText.map((text, i) => (
@@ -229,18 +261,28 @@ export default function GrabConfirmationSheet({
{/* Actions */}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.87d97bdd6d", "Cancel")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.87d97bdd6d', 'Cancel')}
+
- {translate("auto.components.browser.pane.GrabConfirmationSheet.26fd87f4df", "Copy")}
+ {translate('auto.components.browser.pane.GrabConfirmationSheet.26fd87f4df', 'Copy')}
+
{onCopyScreenshot ? (
- {translate("auto.components.browser.pane.GrabConfirmationSheet.7095e98362", "Copy Screenshot")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.7095e98362',
+ 'Copy Screenshot'
+ )}
+
) : null}
- {translate("auto.components.browser.pane.GrabConfirmationSheet.314a0aaa5b", "Attach to AI")}
+ {translate(
+ 'auto.components.browser.pane.GrabConfirmationSheet.314a0aaa5b',
+ 'Attach to AI'
+ )}
+
)
diff --git a/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts b/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts
index 137547cc9a4..6454b6b7c15 100644
--- a/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts
+++ b/src/renderer/src/components/browser-pane/browser-address-bar-suggestions.ts
@@ -83,7 +83,11 @@ export function buildBrowserAddressBarSuggestions({
topAction = {
url: buildSearchUrl(trimmed, searchEngine, { kagiSessionLink }),
title: trimmed,
- subtitle: translate("auto.components.browser.pane.browser.address.bar.suggestions.87fcdd0da9", "{{value0}} Search", { value0: SEARCH_ENGINE_LABELS[searchEngine] }),
+ subtitle: translate(
+ 'auto.components.browser.pane.browser.address.bar.suggestions.87fcdd0da9',
+ '{{value0}} Search',
+ { value0: SEARCH_ENGINE_LABELS[searchEngine] }
+ ),
lastVisitedAt: 0,
visitCount: 0,
isSearch: true
diff --git a/src/renderer/src/components/confirmation-dialog.tsx b/src/renderer/src/components/confirmation-dialog.tsx
index 7d4c252a61b..f13285c4907 100644
--- a/src/renderer/src/components/confirmation-dialog.tsx
+++ b/src/renderer/src/components/confirmation-dialog.tsx
@@ -99,14 +99,16 @@ export function ConfirmationDialogProvider({
settleActiveRequest(false)}>
- {displayedRequest?.options.cancelLabel ?? translate("auto.components.confirmation.dialog.56f5c60e0c", "Cancel")}
+ {displayedRequest?.options.cancelLabel ??
+ translate('auto.components.confirmation.dialog.56f5c60e0c', 'Cancel')}
settleActiveRequest(true)}
>
- {displayedRequest?.options.confirmLabel ?? translate("auto.components.confirmation.dialog.8490e5d36a", "Confirm")}
+ {displayedRequest?.options.confirmLabel ??
+ translate('auto.components.confirmation.dialog.8490e5d36a', 'Confirm')}
diff --git a/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx b/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx
index f70ed09b557..d85d2c72ed6 100644
--- a/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx
+++ b/src/renderer/src/components/contextual-tours/ContextualTourControl.tsx
@@ -36,15 +36,27 @@ function AutoRenameBranchFromWorkControl(): JSX.Element {
-
{translate("auto.components.contextual.tours.ContextualTourControl.731c5573df", "Auto-name from first message")}
+
+ {translate(
+ 'auto.components.contextual.tours.ContextualTourControl.731c5573df',
+ 'Auto-name from first message'
+ )}
+
- {translate("auto.components.contextual.tours.ContextualTourControl.02e8373219", "Auto-generates a new name when you leave this text box empty.")}
+ {translate(
+ 'auto.components.contextual.tours.ContextualTourControl.02e8373219',
+ 'Auto-generates a new name when you leave this text box empty.'
+ )}
+
{
toggleAutoRenameBranchFromWork({
enabled,
diff --git a/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx b/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx
index d3506cffb20..0fac9afccda 100644
--- a/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx
+++ b/src/renderer/src/components/contextual-tours/ContextualTourOverlaySurface.tsx
@@ -132,7 +132,17 @@ export function ContextualTourOverlaySurface({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={renderState.isLastStep ? translate("auto.components.contextual.tours.ContextualTourOverlaySurface.d974f32a83", "Dismiss tour") : translate("auto.components.contextual.tours.ContextualTourOverlaySurface.4f86e2a10b", "Skip tour")}
+ aria-label={
+ renderState.isLastStep
+ ? translate(
+ 'auto.components.contextual.tours.ContextualTourOverlaySurface.d974f32a83',
+ 'Dismiss tour'
+ )
+ : translate(
+ 'auto.components.contextual.tours.ContextualTourOverlaySurface.4f86e2a10b',
+ 'Skip tour'
+ )
+ }
onClick={() => onSkip(activeTourId)}
className="absolute right-2 top-2 text-muted-foreground hover:text-foreground"
>
@@ -150,9 +160,22 @@ export function ContextualTourOverlaySurface({
/>
{!renderState.isFirstStep ? (
-
+
- {translate("auto.components.contextual.tours.ContextualTourOverlaySurface.4a9568f773", "Back")}
+ {translate(
+ 'auto.components.contextual.tours.ContextualTourOverlaySurface.4a9568f773',
+ 'Back'
+ )}
+
) : null}
{renderState.secondaryAction ? (
{primaryAction.label}
- {primaryAction.kind === "next" && !renderState.isLastStep ? : null}
+ {primaryAction.kind === 'next' && !renderState.isLastStep ? : null}
) : null}
diff --git a/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx b/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx
index 88361ea22f9..b52cbb6fdf4 100644
--- a/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx
+++ b/src/renderer/src/components/contextual-tours/ContextualTourProgressDots.tsx
@@ -19,7 +19,11 @@ export function ContextualTourProgressDots({
aria-valuemin={1}
aria-valuemax={total}
aria-valuenow={current}
- aria-label={translate("auto.components.contextual.tours.ContextualTourProgressDots.dcd6e6b03e", "Step {{value0}} of {{value1}}", { value0: current, value1: total })}
+ aria-label={translate(
+ 'auto.components.contextual.tours.ContextualTourProgressDots.dcd6e6b03e',
+ 'Step {{value0}} of {{value1}}',
+ { value0: current, value1: total }
+ )}
>
{Array.from({ length: total }).map((_, index) => {
@@ -41,7 +45,9 @@ export function ContextualTourProgressDots({
})}
- {current} {translate("auto.components.contextual.tours.ContextualTourProgressDots.7734cb8ad3", "of")}{total}
+ {current}{' '}
+ {translate('auto.components.contextual.tours.ContextualTourProgressDots.7734cb8ad3', 'of')}
+ {total}
)
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts
index 79d786799b3..a807ade9fe4 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-overlay-measurement.ts
@@ -118,7 +118,13 @@ export function measureContextualTourOverlayRenderState(args: {
const sidebarAlreadyVisible =
activeStep.primaryAction?.kind === 'show-worktrees' && args.sidebarOpen
const primaryAction = sidebarAlreadyVisible
- ? ({ kind: 'next', label: translate("auto.components.contextual.tours.contextual.tour.overlay.measurement.38b3155418", "Next") } as const)
+ ? ({
+ kind: 'next',
+ label: translate(
+ 'auto.components.contextual.tours.contextual.tour.overlay.measurement.38b3155418',
+ 'Next'
+ )
+ } as const)
: activeStep.primaryAction
const secondaryAction = sidebarAlreadyVisible ? undefined : activeStep.secondaryAction
diff --git a/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx b/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx
index 8babffcdd50..82cd87fe47c 100644
--- a/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx
+++ b/src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.tsx
@@ -52,7 +52,15 @@ export function DashboardAgentChildDisclosure({
onMouseDown={stopMouseDown}
onKeyDown={stopKeyDown}
className="-ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-sm border border-sidebar-border/80 bg-sidebar text-foreground/80 shadow-xs hover:bg-sidebar-accent hover:text-foreground"
- aria-label={translate("auto.components.dashboard.DashboardAgentChildDisclosure.1b57ce9fa4", "{{value0}} {{value1}} child {{value2}}", { value0: childAgentsExpanded ? 'Hide' : 'Show', value1: childAgentCount, value2: childAgentCount === 1 ? 'agent' : 'agents' })}
+ aria-label={translate(
+ 'auto.components.dashboard.DashboardAgentChildDisclosure.1b57ce9fa4',
+ '{{value0}} {{value1}} child {{value2}}',
+ {
+ value0: childAgentsExpanded ? 'Hide' : 'Show',
+ value1: childAgentCount,
+ value2: childAgentCount === 1 ? 'agent' : 'agents'
+ }
+ )}
aria-expanded={childAgentsExpanded}
>
- {translate("auto.components.dashboard.DashboardAgentRowMessage.0a01046763", "interrupted")}
+ {translate(
+ 'auto.components.dashboard.DashboardAgentRowMessage.0a01046763',
+ 'interrupted'
+ )}
+
) : null}
{lastAssistantMessage ? (
{
ev.preventDefault()
ev.stopPropagation()
void window.api.shell.openUrl(url)
}}
>
- {translate("auto.components.diff.comments.DiffCommentCard.6978871a3d", "Open")}
+ {translate('auto.components.diff.comments.DiffCommentCard.6978871a3d', 'Open')}
+
{(onSubmitEdit || onDelete) && (
)}
@@ -178,8 +185,14 @@ export function DiffCommentCard({
{
ev.preventDefault()
ev.stopPropagation()
@@ -195,8 +208,14 @@ export function DiffCommentCard({
{
ev.preventDefault()
ev.stopPropagation()
@@ -249,14 +268,23 @@ export function DiffCommentCard({
/>
- {translate("auto.components.diff.comments.DiffCommentCard.0203bed775", "Cancel")}
+ {translate('auto.components.diff.comments.DiffCommentCard.0203bed775', 'Cancel')}
+
void handleSubmit()}
disabled={!canSubmit}
- title={submitting ? translate("auto.components.diff.comments.DiffCommentCard.bb0a55f856", "Saving…") : undefined}
+ title={
+ submitting
+ ? translate(
+ 'auto.components.diff.comments.DiffCommentCard.bb0a55f856',
+ 'Saving…'
+ )
+ : undefined
+ }
>
- {translate("auto.components.diff.comments.DiffCommentCard.109a791e7b", "Save")}
+ {translate('auto.components.diff.comments.DiffCommentCard.109a791e7b', 'Save')}
+
diff --git a/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx b/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
index dd9d631a73a..ebfd2cb7c52 100644
--- a/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
+++ b/src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
@@ -130,8 +130,16 @@ export function DiffCommentPopover({
{title ??
(startLine && startLine !== lineNumber
- ? translate("auto.components.diff.comments.DiffCommentPopover.c845170b3b", "Lines {{value0}}-{{value1}}", { value0: startLine, value1: lineNumber })
- : translate("auto.components.diff.comments.DiffCommentPopover.e05063cfc1", "Line {{value0}}", { value0: lineNumber }))}
+ ? translate(
+ 'auto.components.diff.comments.DiffCommentPopover.c845170b3b',
+ 'Lines {{value0}}-{{value1}}',
+ { value0: startLine, value1: lineNumber }
+ )
+ : translate(
+ 'auto.components.diff.comments.DiffCommentPopover.e05063cfc1',
+ 'Line {{value0}}',
+ { value0: lineNumber }
+ ))}
- {translate("auto.components.diff.comments.DiffCommentPopover.2b3ce6d394", "Cancel")}
+ {translate('auto.components.diff.comments.DiffCommentPopover.2b3ce6d394', 'Cancel')}
+
- {translate("auto.components.editor.ChangesModeView.54e0035b15", "Loading diff...")}
+ {translate('auto.components.editor.ChangesModeView.54e0035b15', 'Loading diff...')}
+
)
}
if (dc.kind === 'binary') {
return (
-
{translate("auto.components.editor.ChangesModeView.7dffb0f563", "Binary file")}
+
+ {translate('auto.components.editor.ChangesModeView.7dffb0f563', 'Binary file')}
+
- {translate("auto.components.editor.ChangesModeView.052c184f24", "Text diff is unavailable for this file.")}
+ {translate(
+ 'auto.components.editor.ChangesModeView.052c184f24',
+ 'Text diff is unavailable for this file.'
+ )}
+
)
@@ -68,7 +75,11 @@ export function ChangesModeView({
{activeFile.conflict &&
}
{isIdentical && (
- {translate("auto.components.editor.ChangesModeView.ef25ae2d09", "No uncommitted changes.")}
+ {translate(
+ 'auto.components.editor.ChangesModeView.ef25ae2d09',
+ 'No uncommitted changes.'
+ )}
+
)}
{copied ? (
<>
- {translate("auto.components.editor.CodeBlockCopyButton.28921f5bf9", "Copied")}
+
+ {translate('auto.components.editor.CodeBlockCopyButton.28921f5bf9', 'Copied')}
+
>
) : (
diff --git a/src/renderer/src/components/editor/CombinedDiffFileTree.tsx b/src/renderer/src/components/editor/CombinedDiffFileTree.tsx
index f09c5378ed7..5a92bdae79e 100644
--- a/src/renderer/src/components/editor/CombinedDiffFileTree.tsx
+++ b/src/renderer/src/components/editor/CombinedDiffFileTree.tsx
@@ -171,12 +171,16 @@ export function CombinedDiffFileTree({
@@ -198,7 +205,10 @@ export function CombinedDiffFileTree({
type="button"
variant="outline"
size="icon-sm"
- aria-label={translate("auto.components.editor.CombinedDiffFileTree.cd0e0ed79e", "Filter diff files")}
+ aria-label={translate(
+ 'auto.components.editor.CombinedDiffFileTree.cd0e0ed79e',
+ 'Filter diff files'
+ )}
className={cn(activeFilterCount > 0 && 'border-foreground/30 text-foreground')}
>
@@ -206,7 +216,11 @@ export function CombinedDiffFileTree({
- {translate("auto.components.editor.CombinedDiffFileTree.c00020f081", "File extensions")}
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.c00020f081',
+ 'File extensions'
+ )}
+
{availableExtensions.map((extension) => {
const checked = !excludedExtensions.has(extension)
@@ -234,7 +248,12 @@ export function CombinedDiffFileTree({
- {translate("auto.components.editor.CombinedDiffFileTree.be119cb9d1", "Viewed files")}
+
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.be119cb9d1',
+ 'Viewed files'
+ )}
+
{activeFilterCount > 0 && (
- {translate("auto.components.editor.CombinedDiffFileTree.eafe1aeb53", "Reset filters")}
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.eafe1aeb53',
+ 'Reset filters'
+ )}
+
)}
@@ -252,8 +275,12 @@ export function CombinedDiffFileTree({
{filteredEntries.length === 0 ? (
- {translate("auto.components.editor.CombinedDiffFileTree.f984289373", "No files match the current filters.")}
- ) : mode === "uncommitted" ? (
+ {translate(
+ 'auto.components.editor.CombinedDiffFileTree.f984289373',
+ 'No files match the current filters.'
+ )}
+
+ ) : mode === 'uncommitted' ? (
uncommittedGroups.map((group) => (
diff --git a/src/renderer/src/components/editor/CombinedDiffViewer.tsx b/src/renderer/src/components/editor/CombinedDiffViewer.tsx
index 734663e2c3f..a1050c648da 100644
--- a/src/renderer/src/components/editor/CombinedDiffViewer.tsx
+++ b/src/renderer/src/components/editor/CombinedDiffViewer.tsx
@@ -1219,7 +1219,12 @@ export default function CombinedDiffViewer({
if (ok) {
setClearNotesDialogOpen(false)
} else {
- toast.error(translate("auto.components.editor.CombinedDiffViewer.45cf23b418", "Failed to clear notes."))
+ toast.error(
+ translate(
+ 'auto.components.editor.CombinedDiffViewer.45cf23b418',
+ 'Failed to clear notes.'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -1269,9 +1274,17 @@ export default function CombinedDiffViewer({
- {translate("auto.components.editor.CombinedDiffViewer.820ec01f24", "Conflicted files are reviewed separately")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.820ec01f24',
+ 'Conflicted files are reviewed separately'
+ )}
+
- {translate("auto.components.editor.CombinedDiffViewer.eb5f40e49c", "This diff view excludes unresolved conflicts because the normal two-way diff pipeline is not conflict-safe.")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.eb5f40e49c',
+ 'This diff view excludes unresolved conflicts because the normal two-way diff pipeline is not conflict-safe.'
+ )}
+
{file.skippedConflicts!.map((entry) => entry.path).join(', ')}
@@ -1292,7 +1305,11 @@ export default function CombinedDiffViewer({
)
}
>
- {translate("auto.components.editor.CombinedDiffViewer.39f8007549", "Review conflicts")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.39f8007549',
+ 'Review conflicts'
+ )}
+
@@ -1305,7 +1322,11 @@ export default function CombinedDiffViewer({
{commitHeader}
- {translate("auto.components.editor.CombinedDiffViewer.fd8892b120", "No changes to display")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.fd8892b120',
+ 'No changes to display'
+ )}
+
)
}
@@ -1313,9 +1334,21 @@ export default function CombinedDiffViewer({
const skippedConflictNotice =
(file.skippedConflicts?.length ?? 0) > 0 ? (
-
{translate("auto.components.editor.CombinedDiffViewer.820ec01f24", "Conflicted files are reviewed separately")}
+
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.820ec01f24',
+ 'Conflicted files are reviewed separately'
+ )}
+
- {file.skippedConflicts!.length} {translate("auto.components.editor.CombinedDiffViewer.689b99f8ad", "unresolved conflict")}{file.skippedConflicts!.length === 1 ? '' : 's'} {translate("auto.components.editor.CombinedDiffViewer.39e73e7181", "were excluded from this diff view.")}
+ {file.skippedConflicts!.length}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.689b99f8ad', 'unresolved conflict')}
+ {file.skippedConflicts!.length === 1 ? '' : 's'}{' '}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.39e73e7181',
+ 'were excluded from this diff view.'
+ )}
+
- {translate("auto.components.editor.CombinedDiffViewer.39f8007549", "Review conflicts")}
+ {translate('auto.components.editor.CombinedDiffViewer.39f8007549', 'Review conflicts')}
+
) : null
@@ -1352,19 +1386,40 @@ export default function CombinedDiffViewer({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.CombinedDiffViewer.b6c3b84476", "Show file tree")}
+ aria-label={translate(
+ 'auto.components.editor.CombinedDiffViewer.b6c3b84476',
+ 'Show file tree'
+ )}
onClick={() => setFileTreeCollapsed(false)}
>
- {translate("auto.components.editor.CombinedDiffViewer.b6c3b84476", "Show file tree")}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.b6c3b84476',
+ 'Show file tree'
+ )}
+
)}
- {sections.length} {translate("auto.components.editor.CombinedDiffViewer.7e7ca60816", "changed files")}{isBranchMode && branchCompare ? translate("auto.components.editor.CombinedDiffViewer.6094135eec", " vs {{value0}}", { value0: branchCompare.baseRef }) : ''}
- {isCommitMode && commitCompare ? translate("auto.components.editor.CombinedDiffViewer.724a13568d", " in {{value0}}", { value0: commitCompare.compareRef }) : ''}
+ {sections.length}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.7e7ca60816', 'changed files')}
+ {isBranchMode && branchCompare
+ ? translate(
+ 'auto.components.editor.CombinedDiffViewer.6094135eec',
+ ' vs {{value0}}',
+ { value0: branchCompare.baseRef }
+ )
+ : ''}
+ {isCommitMode && commitCompare
+ ? translate(
+ 'auto.components.editor.CombinedDiffViewer.724a13568d',
+ ' in {{value0}}',
+ { value0: commitCompare.compareRef }
+ )
+ : ''}
{diffCommentCount > 0 && (
@@ -1373,10 +1428,22 @@ export default function CombinedDiffViewer({
- {translate("auto.components.editor.CombinedDiffViewer.bb84b4c374", "AI notes")}
+
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.bb84b4c374',
+ 'AI notes'
+ )}
+
{diffCommentCount}
@@ -1409,22 +1476,32 @@ export default function CombinedDiffViewer({
className="text-xs text-muted-foreground hover:text-foreground transition-colors"
onClick={openAlternateDiff}
>
- {file.combinedAlternate.source === "combined-branch"
- ? translate("auto.components.editor.CombinedDiffViewer.3d909843bb", "Open Branch Diff")
- : translate("auto.components.editor.CombinedDiffViewer.982d14bfa5", "Open Uncommitted Diff")}
+ {file.combinedAlternate.source === 'combined-branch'
+ ? translate(
+ 'auto.components.editor.CombinedDiffViewer.3d909843bb',
+ 'Open Branch Diff'
+ )
+ : translate(
+ 'auto.components.editor.CombinedDiffViewer.982d14bfa5',
+ 'Open Uncommitted Diff'
+ )}
)}
setAllSectionsCollapsed(!allSectionsCollapsed)}
>
- {allSectionsCollapsed ? translate("auto.components.editor.CombinedDiffViewer.19c45cfdc0", "Expand All") : translate("auto.components.editor.CombinedDiffViewer.ea08dae15b", "Collapse All")}
+ {allSectionsCollapsed
+ ? translate('auto.components.editor.CombinedDiffViewer.19c45cfdc0', 'Expand All')
+ : translate('auto.components.editor.CombinedDiffViewer.ea08dae15b', 'Collapse All')}
- {sideBySide ? translate("auto.components.editor.CombinedDiffViewer.f786fd54e1", "Inline") : translate("auto.components.editor.CombinedDiffViewer.ec5053c7f5", "Side by Side")}
+ {sideBySide
+ ? translate('auto.components.editor.CombinedDiffViewer.f786fd54e1', 'Inline')
+ : translate('auto.components.editor.CombinedDiffViewer.ec5053c7f5', 'Side by Side')}
@@ -1538,9 +1615,20 @@ export default function CombinedDiffViewer({
>
- {translate("auto.components.editor.CombinedDiffViewer.948a5fd6c8", "Clear Notes")}
+
+ {translate('auto.components.editor.CombinedDiffViewer.948a5fd6c8', 'Clear Notes')}
+
- {translate("auto.components.editor.CombinedDiffViewer.84898c548d", "Clear")}{diffCommentCount} {diffCommentCount === 1 ? translate("auto.components.editor.CombinedDiffViewer.8ab3248fd8", "note") : translate("auto.components.editor.CombinedDiffViewer.0fb870a0fe", "notes")} {translate("auto.components.editor.CombinedDiffViewer.80a286d8f5", "from this worktree?")}
+ {translate('auto.components.editor.CombinedDiffViewer.84898c548d', 'Clear')}
+ {diffCommentCount}{' '}
+ {diffCommentCount === 1
+ ? translate('auto.components.editor.CombinedDiffViewer.8ab3248fd8', 'note')
+ : translate('auto.components.editor.CombinedDiffViewer.0fb870a0fe', 'notes')}{' '}
+ {translate(
+ 'auto.components.editor.CombinedDiffViewer.80a286d8f5',
+ 'from this worktree?'
+ )}
+
setClearNotesDialogOpen(false)}
disabled={isClearingNotes}
>
- {translate("auto.components.editor.CombinedDiffViewer.0f806a2ab1", "Cancel")}
+ {translate('auto.components.editor.CombinedDiffViewer.0f806a2ab1', 'Cancel')}
+
- {translate("auto.components.editor.CombinedDiffViewer.948a5fd6c8", "Clear Notes")}
+ {translate('auto.components.editor.CombinedDiffViewer.948a5fd6c8', 'Clear Notes')}
+
@@ -1585,7 +1675,9 @@ function DiffNotesPreviewPopover({
- {translate("auto.components.editor.CombinedDiffViewer.bb84b4c374", "AI notes")}
+
+ {translate('auto.components.editor.CombinedDiffViewer.bb84b4c374', 'AI notes')}
+
{totalCount}
@@ -1600,7 +1692,8 @@ function DiffNotesPreviewPopover({
disabled={totalCount === 0}
>
{copied ? : }
- {translate("auto.components.editor.CombinedDiffViewer.88b70d0ef5", "Copy")}
+ {translate('auto.components.editor.CombinedDiffViewer.88b70d0ef5', 'Copy')}
+
- {translate("auto.components.editor.CombinedDiffViewer.84898c548d", "Clear")}
+ {translate('auto.components.editor.CombinedDiffViewer.84898c548d', 'Clear')}
+
@@ -1620,7 +1714,8 @@ function DiffNotesPreviewPopover({
{comment.filePath}
{comment.sentAt ? (
- {translate("auto.components.editor.CombinedDiffViewer.1da745c551", "Sent")}
+ {translate('auto.components.editor.CombinedDiffViewer.1da745c551', 'Sent')}
+
) : null}
{getDiffCommentLineLabel(comment, true)}
@@ -1633,7 +1728,13 @@ function DiffNotesPreviewPopover({
))}
{remainingCount > 0 && (
- {remainingCount} {translate("auto.components.editor.CombinedDiffViewer.e3b9a6ce02", "more")}{remainingCount === 1 ? translate("auto.components.editor.CombinedDiffViewer.8ab3248fd8", "note") : translate("auto.components.editor.CombinedDiffViewer.0fb870a0fe", "notes")} {translate("auto.components.editor.CombinedDiffViewer.35cc27aeb2", "in Source Control")}
+ {remainingCount}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.e3b9a6ce02', 'more')}
+ {remainingCount === 1
+ ? translate('auto.components.editor.CombinedDiffViewer.8ab3248fd8', 'note')
+ : translate('auto.components.editor.CombinedDiffViewer.0fb870a0fe', 'notes')}{' '}
+ {translate('auto.components.editor.CombinedDiffViewer.35cc27aeb2', 'in Source Control')}
+
)}
diff --git a/src/renderer/src/components/editor/ConflictComponents.tsx b/src/renderer/src/components/editor/ConflictComponents.tsx
index 23740ba2c9d..47c74ae88db 100644
--- a/src/renderer/src/components/editor/ConflictComponents.tsx
+++ b/src/renderer/src/components/editor/ConflictComponents.tsx
@@ -100,7 +100,9 @@ export function ConflictBanner({
)}
- {label} {translate("auto.components.editor.ConflictComponents.55d61a0ccd", "conflict ·")}{CONFLICT_KIND_LABELS[conflict.conflictKind]}
+ {label}{' '}
+ {translate('auto.components.editor.ConflictComponents.55d61a0ccd', 'conflict ·')}
+ {CONFLICT_KIND_LABELS[conflict.conflictKind]}
{conflictNavigation && conflictNavigation.total > 0 && (
@@ -116,14 +118,21 @@ export function ConflictBanner({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.ConflictComponents.41d9af2e7a", "Previous conflict")}
+ aria-label={translate(
+ 'auto.components.editor.ConflictComponents.41d9af2e7a',
+ 'Previous conflict'
+ )}
onClick={() => conflictNavigation.onJump('previous')}
>
- {translate("auto.components.editor.ConflictComponents.41d9af2e7a", "Previous conflict")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.41d9af2e7a',
+ 'Previous conflict'
+ )}
+
@@ -131,14 +140,18 @@ export function ConflictBanner({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.ConflictComponents.9c2901ef8a", "Next conflict")}
+ aria-label={translate(
+ 'auto.components.editor.ConflictComponents.9c2901ef8a',
+ 'Next conflict'
+ )}
onClick={() => conflictNavigation.onJump('next')}
>
- {translate("auto.components.editor.ConflictComponents.9c2901ef8a", "Next conflict")}
+ {translate('auto.components.editor.ConflictComponents.9c2901ef8a', 'Next conflict')}
+
)}
@@ -150,10 +163,17 @@ export function ConflictBanner({
list where it provides actionable guidance. */}
{!isUnresolved && (
- {translate("auto.components.editor.ConflictComponents.6e459867ad", "Session-local continuity state. Git is no longer reporting this file as unmerged.")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.6e459867ad',
+ 'Session-local continuity state. Git is no longer reporting this file as unmerged.'
+ )}
+
)}
{entry?.oldPath && (
- {translate("auto.components.editor.ConflictComponents.d5edd81755", "Renamed from")}{entry.oldPath}
+
+ {translate('auto.components.editor.ConflictComponents.d5edd81755', 'Renamed from')}
+ {entry.oldPath}
+
)}
)
@@ -172,7 +192,11 @@ export function ConflictPlaceholderView({ file }: { file: OpenFile }): React.JSX
{CONFLICT_KIND_LABELS[conflict.conflictKind]}
- {conflict.message ?? translate("auto.components.editor.ConflictComponents.da539359b6", "No working-tree file is available to edit for this conflict.")}
+ {conflict.message ??
+ translate(
+ 'auto.components.editor.ConflictComponents.da539359b6',
+ 'No working-tree file is available to edit for this conflict.'
+ )}
{conflict.guidance ?? CONFLICT_HINT_MAP[conflict.conflictKind]}
@@ -233,16 +257,27 @@ export function ConflictReviewPanel({
return (
-
{translate("auto.components.editor.ConflictComponents.992145ff5a", "All conflicts resolved")}
+
+ {translate(
+ 'auto.components.editor.ConflictComponents.992145ff5a',
+ 'All conflicts resolved'
+ )}
+
- {translate("auto.components.editor.ConflictComponents.31931dec46", "This review snapshot no longer has any live unresolved conflicts.")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.31931dec46',
+ 'This review snapshot no longer has any live unresolved conflicts.'
+ )}
+
- {translate("auto.components.editor.ConflictComponents.28e7db4a90", "Source Control")}
+ {translate('auto.components.editor.ConflictComponents.28e7db4a90', 'Source Control')}
+
- {translate("auto.components.editor.ConflictComponents.58ad5ad431", "Dismiss")}
+ {translate('auto.components.editor.ConflictComponents.58ad5ad431', 'Dismiss')}
+
@@ -268,34 +303,55 @@ export function ConflictReviewPanel({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.ConflictComponents.c8ca989aea", "Show file tree")}
+ aria-label={translate(
+ 'auto.components.editor.ConflictComponents.c8ca989aea',
+ 'Show file tree'
+ )}
onClick={() => setFileTreeCollapsed(false)}
>
- {translate("auto.components.editor.ConflictComponents.c8ca989aea", "Show file tree")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.c8ca989aea',
+ 'Show file tree'
+ )}
+
)}
- {unresolvedCount} {translate("auto.components.editor.ConflictComponents.4be41eaafc", "unresolved conflict")}{unresolvedCount === 1 ? '' : 's'}
+ {unresolvedCount}{' '}
+ {translate(
+ 'auto.components.editor.ConflictComponents.4be41eaafc',
+ 'unresolved conflict'
+ )}
+ {unresolvedCount === 1 ? '' : 's'}
·
- {translate("auto.components.editor.ConflictComponents.a1ce36f77d", "Snapshot captured at")}{snapshotTime}.
+ {translate(
+ 'auto.components.editor.ConflictComponents.a1ce36f77d',
+ 'Snapshot captured at'
+ )}
+ {snapshotTime}.
- {translate("auto.components.editor.ConflictComponents.90d576adb2", "Refresh")}
+ {translate('auto.components.editor.ConflictComponents.90d576adb2', 'Refresh')}
+
{selectedContent ?? (
- {translate("auto.components.editor.ConflictComponents.f338288514", "Loading conflict contents...")}
+ {translate(
+ 'auto.components.editor.ConflictComponents.f338288514',
+ 'Loading conflict contents...'
+ )}
+
)}
diff --git a/src/renderer/src/components/editor/ConflictReviewFileTree.tsx b/src/renderer/src/components/editor/ConflictReviewFileTree.tsx
index 2a702ef0eee..f3e5e02c425 100644
--- a/src/renderer/src/components/editor/ConflictReviewFileTree.tsx
+++ b/src/renderer/src/components/editor/ConflictReviewFileTree.tsx
@@ -73,14 +73,18 @@ export function ConflictReviewFileTree({
- {translate("auto.components.editor.ConflictReviewFileTree.99496bab6e", "Files")}
+ {translate('auto.components.editor.ConflictReviewFileTree.99496bab6e', 'Files')}
+
{entries.length}
onCollapsedChange(true)}
>
@@ -90,7 +94,11 @@ export function ConflictReviewFileTree({
{rows.length === 0 ? (
- {translate("auto.components.editor.ConflictReviewFileTree.3449521a8c", "No conflicts in this snapshot.")}
+ {translate(
+ 'auto.components.editor.ConflictReviewFileTree.3449521a8c',
+ 'No conflicts in this snapshot.'
+ )}
+
) : (
rows.map((node) => (
- {isStillUnresolved ? translate("auto.components.editor.ConflictReviewFileTree.69d4e210bb", "Unresolved") : liveEntry ? translate("auto.components.editor.ConflictReviewFileTree.8528a5eaf5", "Resolved") : translate("auto.components.editor.ConflictReviewFileTree.496e28a932", "Gone")}
+ {isStillUnresolved
+ ? translate('auto.components.editor.ConflictReviewFileTree.69d4e210bb', 'Unresolved')
+ : liveEntry
+ ? translate('auto.components.editor.ConflictReviewFileTree.8528a5eaf5', 'Resolved')
+ : translate('auto.components.editor.ConflictReviewFileTree.496e28a932', 'Gone')}
)
diff --git a/src/renderer/src/components/editor/CsvViewer.tsx b/src/renderer/src/components/editor/CsvViewer.tsx
index b0db869d504..e424a98c938 100644
--- a/src/renderer/src/components/editor/CsvViewer.tsx
+++ b/src/renderer/src/components/editor/CsvViewer.tsx
@@ -92,7 +92,8 @@ export default function CsvViewer({ content, filePath }: CsvViewerProps): React.
if (parsed.rows.length === 0) {
return (
- {translate("auto.components.editor.CsvViewer.a233d55b77", "Empty file")}
+ {translate('auto.components.editor.CsvViewer.a233d55b77', 'Empty file')}
+
)
}
@@ -178,8 +179,13 @@ export default function CsvViewer({ content, filePath }: CsvViewerProps): React.
- {bodyRows.length.toLocaleString()} {translate("auto.components.editor.CsvViewer.ac31d2cd60", "rows")}
- {columnCount} {translate("auto.components.editor.CsvViewer.eedd0d37a7", "columns")}
+
+ {bodyRows.length.toLocaleString()}{' '}
+ {translate('auto.components.editor.CsvViewer.ac31d2cd60', 'rows')}
+
+
+ {columnCount} {translate('auto.components.editor.CsvViewer.eedd0d37a7', 'columns')}
+
)
diff --git a/src/renderer/src/components/editor/DiffNotesSendMenu.tsx b/src/renderer/src/components/editor/DiffNotesSendMenu.tsx
index 15985bec04f..32638d4faab 100644
--- a/src/renderer/src/components/editor/DiffNotesSendMenu.tsx
+++ b/src/renderer/src/components/editor/DiffNotesSendMenu.tsx
@@ -43,7 +43,7 @@ export function DiffNotesSendMenu({
const scopes = useMemo[]>(() => {
const allNotesScope = {
id: 'all',
- label: translate("auto.components.editor.DiffNotesSendMenu.8b87612461", "All unsent notes"),
+ label: translate('auto.components.editor.DiffNotesSendMenu.8b87612461', 'All unsent notes'),
notes: unsentNotes,
prompt: unsentPrompt
}
@@ -53,7 +53,7 @@ export function DiffNotesSendMenu({
return [
{
id: 'file',
- label: translate("auto.components.editor.DiffNotesSendMenu.f1aa04b5cf", "This file"),
+ label: translate('auto.components.editor.DiffNotesSendMenu.f1aa04b5cf', 'This file'),
notes: unsentFileNotes,
prompt: unsentFilePrompt
},
diff --git a/src/renderer/src/components/editor/DiffSectionBody.tsx b/src/renderer/src/components/editor/DiffSectionBody.tsx
index 2a472cac5fe..0010edc760e 100644
--- a/src/renderer/src/components/editor/DiffSectionBody.tsx
+++ b/src/renderer/src/components/editor/DiffSectionBody.tsx
@@ -85,7 +85,9 @@ export function DiffSectionBody({
{section.loading ? (
- {translate("auto.components.editor.DiffSectionBody.f5cf81cec2", "Loading diff...")}
+
+ {translate('auto.components.editor.DiffSectionBody.f5cf81cec2', 'Loading diff...')}
+
) : section.error ? (
@@ -104,7 +106,8 @@ export function DiffSectionBody({
}}
>
- {translate("auto.components.editor.DiffSectionBody.cef4cf0ff5", "Retry")}
+ {translate('auto.components.editor.DiffSectionBody.cef4cf0ff5', 'Retry')}
+
) : section.diffResult?.kind === 'binary' ? (
section.diffResult.isImage ? (
@@ -119,11 +122,22 @@ export function DiffSectionBody({
) : (
-
{translate("auto.components.editor.DiffSectionBody.35d6afb5be", "Binary file changed")}
+
+ {translate(
+ 'auto.components.editor.DiffSectionBody.35d6afb5be',
+ 'Binary file changed'
+ )}
+
{isBranchMode
- ? translate("auto.components.editor.DiffSectionBody.7ce8436458", "Text diff is unavailable for this file in branch compare.")
- : translate("auto.components.editor.DiffSectionBody.72f71f52eb", "Text diff is unavailable for this file.")}
+ ? translate(
+ 'auto.components.editor.DiffSectionBody.7ce8436458',
+ 'Text diff is unavailable for this file in branch compare.'
+ )
+ : translate(
+ 'auto.components.editor.DiffSectionBody.72f71f52eb',
+ 'Text diff is unavailable for this file.'
+ )}
diff --git a/src/renderer/src/components/editor/DiffSectionHeader.tsx b/src/renderer/src/components/editor/DiffSectionHeader.tsx
index b2529feba78..c69600a8b24 100644
--- a/src/renderer/src/components/editor/DiffSectionHeader.tsx
+++ b/src/renderer/src/components/editor/DiffSectionHeader.tsx
@@ -56,7 +56,7 @@ export function DiffSectionHeader({
console.error('Failed to copy diff path:', error)
})
}}
- title={translate("auto.components.editor.DiffSectionHeader.8915726e93", "Copy path")}
+ title={translate('auto.components.editor.DiffSectionHeader.8915726e93', 'Copy path')}
>
{path}
diff --git a/src/renderer/src/components/editor/EditorContent.tsx b/src/renderer/src/components/editor/EditorContent.tsx
index 8b1aed68ff4..1e572714926 100644
--- a/src/renderer/src/components/editor/EditorContent.tsx
+++ b/src/renderer/src/components/editor/EditorContent.tsx
@@ -81,11 +81,14 @@ function FileLoadErrorView({
-
{translate("auto.components.editor.EditorContent.39f018b052", "Unable to load file")}
+
+ {translate('auto.components.editor.EditorContent.39f018b052', 'Unable to load file')}
+
{message}
- {translate("auto.components.editor.EditorContent.2a512bb46a", "Retry")}
+ {translate('auto.components.editor.EditorContent.2a512bb46a', 'Retry')}
+
@@ -253,8 +256,10 @@ export function EditorContent({
conflictKind: entry.conflictKind,
conflictStatus: entry.conflictStatus,
conflictStatusSource: entry.conflictStatusSource,
- message:
- translate("auto.components.editor.EditorContent.8b1a605bae", "This file is in a conflict state, but no working-tree file is available to edit."),
+ message: translate(
+ 'auto.components.editor.EditorContent.8b1a605bae',
+ 'This file is in a conflict state, but no working-tree file is available to edit.'
+ ),
guidance: 'Resolve the conflict in Git or restore one side before reopening it.'
}
: {
@@ -477,7 +482,8 @@ export function EditorContent({
return (
- {translate("auto.components.editor.EditorContent.b2735221f5", "Loading...")}
+ {translate('auto.components.editor.EditorContent.b2735221f5', 'Loading...')}
+
)
}
@@ -506,7 +512,11 @@ export function EditorContent({
return (
- {translate("auto.components.editor.EditorContent.b9de81ba52", "Binary file — cannot display")}
+ {translate(
+ 'auto.components.editor.EditorContent.b9de81ba52',
+ 'Binary file — cannot display'
+ )}
+
)
}
@@ -650,7 +660,8 @@ export function EditorContent({
if (!fc) {
return (
- {translate("auto.components.editor.EditorContent.37a0e81fa6", "Loading preview...")}
+ {translate('auto.components.editor.EditorContent.37a0e81fa6', 'Loading preview...')}
+
)
}
if (fc.loadError) {
@@ -661,7 +672,11 @@ export function EditorContent({
if (fc.isBinary) {
return (
- {translate("auto.components.editor.EditorContent.8608ce4cb1", "Markdown preview is unavailable for binary files.")}
+ {translate(
+ 'auto.components.editor.EditorContent.8608ce4cb1',
+ 'Markdown preview is unavailable for binary files.'
+ )}
+
)
}
const previewSourceFileId = activeFile.markdownPreviewSourceFileId ?? activeFile.filePath
@@ -694,7 +709,8 @@ export function EditorContent({
if (!fc) {
return (
- {translate("auto.components.editor.EditorContent.b2735221f5", "Loading...")}
+ {translate('auto.components.editor.EditorContent.b2735221f5', 'Loading...')}
+
)
}
if (fc.loadError) {
@@ -710,7 +726,11 @@ export function EditorContent({
}
return (
- {translate("auto.components.editor.EditorContent.b9de81ba52", "Binary file — cannot display")}
+ {translate(
+ 'auto.components.editor.EditorContent.b9de81ba52',
+ 'Binary file — cannot display'
+ )}
+
)
}
if (isChangesMode) {
@@ -744,19 +764,19 @@ export function EditorContent({
{isMarkdown ? (
renderMarkdownContent(fc)
- ) : isMermaid && mdViewMode === "rich" ? (
+ ) : isMermaid && mdViewMode === 'rich' ? (
- ) : isCsv && mdViewMode === "rich" ? (
+ ) : isCsv && mdViewMode === 'rich' ? (
- ) : isNotebook && mdViewMode === "rich" ? (
+ ) : isNotebook && mdViewMode === 'rich' ? (
- {translate("auto.components.editor.EditorContent.c88c73a0d3", "Loading diff...")}
+ {translate('auto.components.editor.EditorContent.c88c73a0d3', 'Loading diff...')}
+
)
}
const isEditable = activeFile.diffSource === 'unstaged'
@@ -800,11 +821,19 @@ export function EditorContent({
return (
-
{translate("auto.components.editor.EditorContent.78541e254e", "Binary file changed")}
+
+ {translate('auto.components.editor.EditorContent.78541e254e', 'Binary file changed')}
+
- {activeFile.diffSource === "branch"
- ? translate("auto.components.editor.EditorContent.3c6e71df22", "Text diff is unavailable for this file in branch compare.")
- : translate("auto.components.editor.EditorContent.8a0898ae4c", "Text diff is unavailable for this file.")}
+ {activeFile.diffSource === 'branch'
+ ? translate(
+ 'auto.components.editor.EditorContent.3c6e71df22',
+ 'Text diff is unavailable for this file in branch compare.'
+ )
+ : translate(
+ 'auto.components.editor.EditorContent.8a0898ae4c',
+ 'Text diff is unavailable for this file.'
+ )}
@@ -819,7 +848,11 @@ export function EditorContent({
deletions simultaneously, so preview mode intentionally shows the
modified side of the diff. Source mode remains available for the
actual line-by-line comparison. */}
- {translate("auto.components.editor.EditorContent.9640d1d3db", "Previewing the modified version of this diff. Switch to source mode to inspect changes.")}
+ {translate(
+ 'auto.components.editor.EditorContent.9640d1d3db',
+ 'Previewing the modified version of this diff. Switch to source mode to inspect changes.'
+ )}
+
- {translate("auto.components.editor.EditorContent.e4b074749d", "Front Matter")}
- {translate("auto.components.editor.EditorContent.56dba34e1a", "(edit in source mode)")}
+ {translate('auto.components.editor.EditorContent.e4b074749d', 'Front Matter')}
+
+ {translate('auto.components.editor.EditorContent.56dba34e1a', '(edit in source mode)')}
+
{inner}
diff --git a/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx b/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx
index 2a84a561ec4..61f8128c894 100644
--- a/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx
+++ b/src/renderer/src/components/editor/EditorPanelMarkdownActionsMenu.tsx
@@ -39,8 +39,14 @@ export function EditorPanelMarkdownActionsMenu({
@@ -54,7 +60,15 @@ export function EditorPanelMarkdownActionsMenu({
onToggleMarkdownFrontmatter()
}}
>
- {markdownFrontmatterVisible ? translate("auto.components.editor.EditorPanelMarkdownActionsMenu.10c39d58c1", "Hide front matter") : translate("auto.components.editor.EditorPanelMarkdownActionsMenu.8c8b7f5ff5", "Show front matter")}
+ {markdownFrontmatterVisible
+ ? translate(
+ 'auto.components.editor.EditorPanelMarkdownActionsMenu.10c39d58c1',
+ 'Hide front matter'
+ )
+ : translate(
+ 'auto.components.editor.EditorPanelMarkdownActionsMenu.8c8b7f5ff5',
+ 'Show front matter'
+ )}
{hasViewModeToggle ? : null}
>
@@ -67,7 +81,11 @@ export function EditorPanelMarkdownActionsMenu({
disabled={mdViewMode === 'source'}
onSelect={onExportMarkdownToPdf}
>
- {translate("auto.components.editor.EditorPanelMarkdownActionsMenu.3e0ce48c24", "Export as PDF")}
+ {translate(
+ 'auto.components.editor.EditorPanelMarkdownActionsMenu.3e0ce48c24',
+ 'Export as PDF'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/editor/EditorPanelShell.tsx b/src/renderer/src/components/editor/EditorPanelShell.tsx
index cc2c84238ad..3eac493d120 100644
--- a/src/renderer/src/components/editor/EditorPanelShell.tsx
+++ b/src/renderer/src/components/editor/EditorPanelShell.tsx
@@ -185,6 +185,7 @@ export function EditorPanelShell({
function EditorLoadingFallback(): JSX.Element {
return (
- {translate("auto.components.editor.EditorPanelShell.e2c4dec350", "Loading editor...")}
+ {translate('auto.components.editor.EditorPanelShell.e2c4dec350', 'Loading editor...')}
+
)
}
diff --git a/src/renderer/src/components/editor/EditorViewToggle.tsx b/src/renderer/src/components/editor/EditorViewToggle.tsx
index 30228a07a23..82b07c3a224 100644
--- a/src/renderer/src/components/editor/EditorViewToggle.tsx
+++ b/src/renderer/src/components/editor/EditorViewToggle.tsx
@@ -27,29 +27,29 @@ type ViewModeMetadata = { label: string; icon: LucideIcon; title?: string }
const DEFAULT_VIEW_MODE_METADATA: Record = {
source: {
- label: translate("auto.components.editor.EditorViewToggle.4d6ccb7ba6", "Source"),
+ label: translate('auto.components.editor.EditorViewToggle.4d6ccb7ba6', 'Source'),
icon: Code
},
rich: {
- label: translate("auto.components.editor.EditorViewToggle.aff15f94f5", "Rich Editor"),
+ label: translate('auto.components.editor.EditorViewToggle.aff15f94f5', 'Rich Editor'),
icon: Pencil
},
preview: {
- label: translate("auto.components.editor.EditorViewToggle.0d193dc03c", "Preview"),
+ label: translate('auto.components.editor.EditorViewToggle.0d193dc03c', 'Preview'),
icon: Eye
},
edit: {
- label: translate("auto.components.editor.EditorViewToggle.ac3bb87913", "Edit"),
+ label: translate('auto.components.editor.EditorViewToggle.ac3bb87913', 'Edit'),
icon: FileText
},
changes: {
- label: translate("auto.components.editor.EditorViewToggle.4837f3f578", "Changes"),
+ label: translate('auto.components.editor.EditorViewToggle.4837f3f578', 'Changes'),
icon: GitCompareArrows,
// Why: "Changes" collides with the Source Control sidebar's "Branch
// Changes" section, which diffs against the base ref. This toggle shows
// uncommitted changes (working tree vs HEAD), so disambiguate in the
// hover title without repeating the button label.
- title: translate("auto.components.editor.EditorViewToggle.167f45888c", "Uncommitted changes")
+ title: translate('auto.components.editor.EditorViewToggle.167f45888c', 'Uncommitted changes')
}
}
@@ -58,14 +58,14 @@ const DEFAULT_VIEW_MODE_METADATA: Record =
// which we don't offer, so callers can override the per-mode presentation.
export const CSV_VIEW_MODE_METADATA: Partial> = {
rich: {
- label: translate("auto.components.editor.EditorViewToggle.e408aa9cd5", "Table"),
+ label: translate('auto.components.editor.EditorViewToggle.e408aa9cd5', 'Table'),
icon: TableIcon
}
}
export const NOTEBOOK_VIEW_MODE_METADATA: Partial> = {
rich: {
- label: translate("auto.components.editor.EditorViewToggle.b3410cd5e0", "Notebook"),
+ label: translate('auto.components.editor.EditorViewToggle.b3410cd5e0', 'Notebook'),
icon: NotebookText
}
}
diff --git a/src/renderer/src/components/editor/ImageDiffViewer.tsx b/src/renderer/src/components/editor/ImageDiffViewer.tsx
index 9a6634c9a79..2e021433967 100644
--- a/src/renderer/src/components/editor/ImageDiffViewer.tsx
+++ b/src/renderer/src/components/editor/ImageDiffViewer.tsx
@@ -42,7 +42,8 @@ function ImageDiffPane({
isIntrinsicLayout ? 'min-h-32' : 'flex-1'
)}
>
- {translate("auto.components.editor.ImageDiffViewer.fb0ae4f3c0", "No preview")}
+ {translate('auto.components.editor.ImageDiffViewer.fb0ae4f3c0', 'No preview')}
+
)
}
@@ -94,14 +95,14 @@ export default function ImageDiffViewer({
style={gridRowStyle}
>
- {translate("auto.components.editor.ImageViewer.d9d2944855", "Failed to load file preview")}
+
+ {translate(
+ 'auto.components.editor.ImageViewer.d9d2944855',
+ 'Failed to load file preview'
+ )}
+
{filename}
)
@@ -233,7 +238,8 @@ export default function ImageViewer({
isIntrinsicLayout ? 'min-h-64' : 'h-full'
)}
>
- {translate("auto.components.editor.ImageViewer.3ef9551ba2", "Loading preview...")}
+ {translate('auto.components.editor.ImageViewer.3ef9551ba2', 'Loading preview...')}
+
)
}
@@ -249,7 +255,7 @@ export default function ImageViewer({
: 'flex-1 overflow-auto scrollbar-editor'
)}
onClick={openPopup}
- title={translate("auto.components.editor.ImageViewer.77bfc9b35a", "Open image in popup")}
+ title={translate('auto.components.editor.ImageViewer.77bfc9b35a', 'Open image in popup')}
>
currentZoom / IMAGE_VIEWER_ZOOM_STEP)
}
disabled={inlineZoom <= MIN_IMAGE_VIEWER_ZOOM}
- title={translate("auto.components.editor.ImageViewer.be27304574", "Zoom out")}
+ title={translate('auto.components.editor.ImageViewer.be27304574', 'Zoom out')}
>
@@ -308,7 +314,7 @@ export default function ImageViewer({
className="rounded p-1 hover:bg-accent hover:text-foreground disabled:opacity-50"
onClick={() => applyInlineZoomChange(() => 1)}
disabled={inlineZoom === 1}
- title={translate("auto.components.editor.ImageViewer.6c89c73d9f", "Reset zoom")}
+ title={translate('auto.components.editor.ImageViewer.6c89c73d9f', 'Reset zoom')}
>
@@ -319,7 +325,7 @@ export default function ImageViewer({
applyInlineZoomChange((currentZoom) => currentZoom * IMAGE_VIEWER_ZOOM_STEP)
}
disabled={inlineZoom >= MAX_IMAGE_VIEWER_ZOOM}
- title={translate("auto.components.editor.ImageViewer.3c9217f5a6", "Zoom in")}
+ title={translate('auto.components.editor.ImageViewer.3c9217f5a6', 'Zoom in')}
>
diff --git a/src/renderer/src/components/editor/ImageViewerPopup.tsx b/src/renderer/src/components/editor/ImageViewerPopup.tsx
index 93107f1ac47..c5d4918cd4b 100644
--- a/src/renderer/src/components/editor/ImageViewerPopup.tsx
+++ b/src/renderer/src/components/editor/ImageViewerPopup.tsx
@@ -33,7 +33,12 @@ export default function ImageViewerPopup({
className="top-1/2 left-1/2 flex h-[80vh] w-[70vw] max-w-[70vw] -translate-x-1/2 -translate-y-1/2 flex-col gap-0 overflow-hidden border border-border/60 bg-background p-0 shadow-2xl sm:max-w-[70vw]"
>
{filename}
-
{translate("auto.components.editor.ImageViewerPopup.9e27b2ecaf", "Full-size image preview")}
+
+ {translate(
+ 'auto.components.editor.ImageViewerPopup.9e27b2ecaf',
+ 'Full-size image preview'
+ )}
+
{filename}
onOpenChange(false)}
>
- {translate("auto.components.editor.ImageViewerPopup.535f4e2b56", "Close")}
+ {translate('auto.components.editor.ImageViewerPopup.535f4e2b56', 'Close')}
-
{translate("auto.components.editor.ImageViewerPopup.0ef78475e7", "Press Esc to close")}
+
+ {translate('auto.components.editor.ImageViewerPopup.0ef78475e7', 'Press Esc to close')}
+
{zoomPercent}%
diff --git a/src/renderer/src/components/editor/IpynbViewer.tsx b/src/renderer/src/components/editor/IpynbViewer.tsx
index cbb4b8019d2..31abbc557e7 100644
--- a/src/renderer/src/components/editor/IpynbViewer.tsx
+++ b/src/renderer/src/components/editor/IpynbViewer.tsx
@@ -181,29 +181,56 @@ function NotebookCellHeader({
onChange={(event) => onKindChange(event.target.value as IpynbCellKind)}
className="h-7 rounded-md border border-input bg-background px-2 text-xs text-foreground"
>
-
{translate("auto.components.editor.IpynbViewer.7005960d73", "Code")}
-
{translate("auto.components.editor.IpynbViewer.1833dbbc43", "Markdown")}
-
{translate("auto.components.editor.IpynbViewer.3e4cbf15ea", "Raw")}
+
+ {translate('auto.components.editor.IpynbViewer.7005960d73', 'Code')}
+
+
+ {translate('auto.components.editor.IpynbViewer.1833dbbc43', 'Markdown')}
+
+
+ {translate('auto.components.editor.IpynbViewer.3e4cbf15ea', 'Raw')}
+
- {cell.kind === "code" ? (
-
+ {cell.kind === 'code' ? (
+
{running ? : }
) : null}
-
+
-
+
- onInsertAbove('code')}>
+ onInsertAbove('code')}
+ >
- onInsertBelow('code')}>
+ onInsertBelow('code')}
+ >
onInsertAbove('markdown')}
>
@@ -212,7 +239,10 @@ function NotebookCellHeader({
onInsertBelow('markdown')}
>
@@ -220,7 +250,10 @@ function NotebookCellHeader({
-
+
#{index + 1}
@@ -438,7 +471,7 @@ function OutputItem({ item }: { item: IpynbOutputItem }): React.JSX.Element | nu
})
return (
@@ -837,27 +875,35 @@ export default function IpynbViewer({
>
{filePath.split(/[/\\]/).pop()}
-
{notebook.cells.length} {translate("auto.components.editor.IpynbViewer.07e7d96612", "cells")}
+
+ {notebook.cells.length}{' '}
+ {translate('auto.components.editor.IpynbViewer.07e7d96612', 'cells')}
+
{notebook.language}
{notebook.kernelName ?
{notebook.kernelName} : null}
{runError ?
{runError} : null}
void saveNotebook()}
>
- {translate("auto.components.editor.IpynbViewer.329764e9fc", "BETA")}
- {translate("auto.components.editor.IpynbViewer.8c3b21369a", "nbformat")}{notebook.nbformat}
+ {translate('auto.components.editor.IpynbViewer.329764e9fc', 'BETA')}
+
+
+ {translate('auto.components.editor.IpynbViewer.8c3b21369a', 'nbformat')}
+ {notebook.nbformat}
+
{notebook.cells.length === 0 ? (
- {translate("auto.components.editor.IpynbViewer.d6f37a640b", "Empty notebook")}
+ {translate('auto.components.editor.IpynbViewer.d6f37a640b', 'Empty notebook')}
+
) : (
notebook.cells.map((cell, index) => {
const cellKey = getCellKey(cell, index)
@@ -883,7 +929,7 @@ export default function IpynbViewer({
onMoveDown={() => moveCell(index, 1)}
onDelete={() => deleteCell(index)}
/>
- {cell.kind === "markdown" ? (
+ {cell.kind === 'markdown' ? (
- ) : cell.kind === "code" ? (
+ ) : cell.kind === 'code' ? (
- {translate("auto.components.editor.IpynbViewer.9e06ae5d36", "Run Notebook Code?")}
+
+ {translate('auto.components.editor.IpynbViewer.9e06ae5d36', 'Run Notebook Code?')}
+
- {translate("auto.components.editor.IpynbViewer.10ed04a685", "Notebook cells execute local Python on this machine from the notebook folder. Only run cells from files you trust.")}
+ {translate(
+ 'auto.components.editor.IpynbViewer.10ed04a685',
+ 'Notebook cells execute local Python on this machine from the notebook folder. Only run cells from files you trust.'
+ )}
+
- {translate("auto.components.editor.IpynbViewer.7f0d7077c6", "Cancel")}
+ {translate('auto.components.editor.IpynbViewer.7f0d7077c6', 'Cancel')}
+
- {translate("auto.components.editor.IpynbViewer.859bf9fc21", "Run cell")}
+ {translate('auto.components.editor.IpynbViewer.859bf9fc21', 'Run cell')}
+
diff --git a/src/renderer/src/components/editor/MarkdownPreview.tsx b/src/renderer/src/components/editor/MarkdownPreview.tsx
index 92881542d4d..ea9d90350a6 100644
--- a/src/renderer/src/components/editor/MarkdownPreview.tsx
+++ b/src/renderer/src/components/editor/MarkdownPreview.tsx
@@ -595,7 +595,7 @@ export default function MarkdownPreview({
() => [
{
id: 'all',
- label: translate("auto.components.editor.MarkdownPreview.ddf087d12e", "All unsent notes"),
+ label: translate('auto.components.editor.MarkdownPreview.ddf087d12e', 'All unsent notes'),
notes: unsentMarkdownReviewNotes,
prompt: unsentMarkdownReviewPrompt
}
@@ -1035,8 +1035,8 @@ export default function MarkdownPreview({
{
event.preventDefault()
event.stopPropagation()
@@ -1081,10 +1081,26 @@ export default function MarkdownPreview({
type="button"
className="orca-diff-comment-pill-btn"
title={
- copiedReviewNoteId === comment.id ? translate("auto.components.editor.MarkdownPreview.94b520a96a", "Copied note") : translate("auto.components.editor.MarkdownPreview.f961e94057", "Copy note for agent")
+ copiedReviewNoteId === comment.id
+ ? translate(
+ 'auto.components.editor.MarkdownPreview.94b520a96a',
+ 'Copied note'
+ )
+ : translate(
+ 'auto.components.editor.MarkdownPreview.f961e94057',
+ 'Copy note for agent'
+ )
}
aria-label={
- copiedReviewNoteId === comment.id ? translate("auto.components.editor.MarkdownPreview.94b520a96a", "Copied note") : translate("auto.components.editor.MarkdownPreview.f961e94057", "Copy note for agent")
+ copiedReviewNoteId === comment.id
+ ? translate(
+ 'auto.components.editor.MarkdownPreview.94b520a96a',
+ 'Copied note'
+ )
+ : translate(
+ 'auto.components.editor.MarkdownPreview.f961e94057',
+ 'Copy note for agent'
+ )
}
onClick={(event) => {
event.preventDefault()
@@ -1264,7 +1280,11 @@ export default function MarkdownPreview({
void window.api.shell.pathExists(classified.absolutePath).then((exists) => {
if (!exists) {
toast.error(
- translate("auto.components.editor.MarkdownPreview.6c043947ae", "File not found: {{value0}}", { value0: classified.relativePath ?? classified.absolutePath })
+ translate(
+ 'auto.components.editor.MarkdownPreview.6c043947ae',
+ 'File not found: {{value0}}',
+ { value0: classified.relativePath ?? classified.absolutePath }
+ )
)
return
}
@@ -1356,11 +1376,23 @@ export default function MarkdownPreview({
absolutePath
)
if (stats.isDirectory) {
- toast.error(translate("auto.components.editor.MarkdownPreview.759463a221", "Cannot open directory: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate(
+ 'auto.components.editor.MarkdownPreview.759463a221',
+ 'Cannot open directory: {{value0}}',
+ { value0: relativePath }
+ )
+ )
return
}
} catch {
- toast.error(translate("auto.components.editor.MarkdownPreview.6c043947ae", "File not found: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate(
+ 'auto.components.editor.MarkdownPreview.6c043947ae',
+ 'File not found: {{value0}}',
+ { value0: relativePath }
+ )
+ )
return
}
@@ -1663,14 +1695,20 @@ export default function MarkdownPreview({
rootRef.current?.focus()
}
}}
- placeholder={translate("auto.components.editor.MarkdownPreview.517aea303b", "Find in preview")}
+ placeholder={translate(
+ 'auto.components.editor.MarkdownPreview.517aea303b',
+ 'Find in preview'
+ )}
className="markdown-preview-search-input h-7 !border-0 bg-transparent px-2 shadow-none focus-visible:!border-0 focus-visible:ring-0"
- aria-label={translate("auto.components.editor.MarkdownPreview.ec77985138", "Find in markdown preview")}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.ec77985138',
+ 'Find in markdown preview'
+ )}
/>
{query && matchCount === 0
- ? translate("auto.components.editor.MarkdownPreview.c5dc92cfe3", "No results")
+ ? translate('auto.components.editor.MarkdownPreview.c5dc92cfe3', 'No results')
: `${matchCount === 0 ? 0 : activeMatchIndex + 1}/${matchCount}`}
moveToMatch(-1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.MarkdownPreview.1febd97f5c", "Previous match")}
- aria-label={translate("auto.components.editor.MarkdownPreview.1febd97f5c", "Previous match")}
+ title={translate(
+ 'auto.components.editor.MarkdownPreview.1febd97f5c',
+ 'Previous match'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.1febd97f5c',
+ 'Previous match'
+ )}
className="markdown-preview-search-button"
>
@@ -1691,8 +1735,11 @@ export default function MarkdownPreview({
size="icon-xs"
onClick={() => moveToMatch(1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.MarkdownPreview.b42c41bd0d", "Next match")}
- aria-label={translate("auto.components.editor.MarkdownPreview.b42c41bd0d", "Next match")}
+ title={translate('auto.components.editor.MarkdownPreview.b42c41bd0d', 'Next match')}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.b42c41bd0d',
+ 'Next match'
+ )}
className="markdown-preview-search-button"
>
@@ -1703,8 +1750,11 @@ export default function MarkdownPreview({
variant="ghost"
size="icon-xs"
onClick={closeSearch}
- title={translate("auto.components.editor.MarkdownPreview.12052c639c", "Close search")}
- aria-label={translate("auto.components.editor.MarkdownPreview.12052c639c", "Close search")}
+ title={translate('auto.components.editor.MarkdownPreview.12052c639c', 'Close search')}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.12052c639c',
+ 'Close search'
+ )}
className="markdown-preview-search-button"
>
@@ -1723,11 +1773,19 @@ export default function MarkdownPreview({
}
}}
disabled={markdownReviewNotes.length === 0}
- title={translate("auto.components.editor.MarkdownPreview.0f9969a159", "Jump to first review note")}
- aria-label={translate("auto.components.editor.MarkdownPreview.0f9969a159", "Jump to first review note")}
+ title={translate(
+ 'auto.components.editor.MarkdownPreview.0f9969a159',
+ 'Jump to first review note'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.0f9969a159',
+ 'Jump to first review note'
+ )}
>
- {translate("auto.components.editor.MarkdownPreview.322afab6ff", "Review notes")}
+
+ {translate('auto.components.editor.MarkdownPreview.322afab6ff', 'Review notes')}
+
{markdownReviewNotes.length}
void handleCopyMarkdownReviewNotes()}
disabled={markdownReviewNotes.length === 0}
- title={translate("auto.components.editor.MarkdownPreview.bb629de58a", "Copy notes for agent")}
- aria-label={translate("auto.components.editor.MarkdownPreview.bb629de58a", "Copy notes for agent")}
+ title={translate(
+ 'auto.components.editor.MarkdownPreview.bb629de58a',
+ 'Copy notes for agent'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownPreview.bb629de58a',
+ 'Copy notes for agent'
+ )}
>
{reviewNotesCopied ? : }
@@ -1759,7 +1823,8 @@ export default function MarkdownPreview({
{frontMatter && frontmatterVisible ? (
- {translate("auto.components.editor.MarkdownPreview.2b2b31382c", "Front Matter")}
+ {translate('auto.components.editor.MarkdownPreview.2b2b31382c', 'Front Matter')}
+
{frontMatterInner}
@@ -1820,7 +1885,7 @@ function MarkdownSingleNoteSendMenu({
scopes={[
{
id: 'note',
- label: translate("auto.components.editor.MarkdownPreview.f37b98999e", "This note"),
+ label: translate('auto.components.editor.MarkdownPreview.f37b98999e', 'This note'),
notes: note.sentAt ? [] : [note],
prompt: formatMarkdownReviewNotes([note], content)
}
@@ -1876,11 +1941,16 @@ function MarkdownAnnotationComposer({
return (
event.stopPropagation()}>
-
{translate("auto.components.editor.MarkdownPreview.b1bfc04034", "Selected text")}
+
+ {translate('auto.components.editor.MarkdownPreview.b1bfc04034', 'Selected text')}
+
{
setBody(event.target.value)
@@ -1903,9 +1973,12 @@ function MarkdownAnnotationComposer({
/>
- {translate("auto.components.editor.MarkdownPreview.e4683f70c4", "Cancel")}
+ {translate('auto.components.editor.MarkdownPreview.e4683f70c4', 'Cancel')}
+
void submit()} disabled={submitting || !trimmed}>
- {submitting ? translate("auto.components.editor.MarkdownPreview.d652c87c91", "Saving…") : translate("auto.components.editor.MarkdownPreview.13f94d760c", "Add note")}
+ {submitting
+ ? translate('auto.components.editor.MarkdownPreview.d652c87c91', 'Saving…')
+ : translate('auto.components.editor.MarkdownPreview.13f94d760c', 'Add note')}
{!submitting && }
diff --git a/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx b/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx
index 445d5732536..678877de8bb 100644
--- a/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx
+++ b/src/renderer/src/components/editor/MarkdownTableOfContentsPanel.tsx
@@ -52,7 +52,19 @@ function MarkdownTocRow({
onToggleCollapsed(item.id)}
>
@@ -108,12 +120,30 @@ export function MarkdownTableOfContentsPanel({
}
return (
-
+
-
{translate("auto.components.editor.MarkdownTableOfContentsPanel.06357eea60", "Table of Contents")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.06357eea60',
+ 'Table of Contents'
+ )}
+
-
+
{TOC_LEVELS.map((level) => (
collapseToLevel(level)}
>
H{level}
@@ -135,8 +185,14 @@ export function MarkdownTableOfContentsPanel({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097", "Close table of contents")}
- title={translate("auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097", "Close table of contents")}
+ aria-label={translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097',
+ 'Close table of contents'
+ )}
+ title={translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.bbe8369097',
+ 'Close table of contents'
+ )}
onClick={onClose}
>
@@ -156,7 +212,12 @@ export function MarkdownTableOfContentsPanel({
/>
))
) : (
- {translate("auto.components.editor.MarkdownTableOfContentsPanel.de3928b6e4", "No headings")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTableOfContentsPanel.de3928b6e4',
+ 'No headings'
+ )}
+
)}
diff --git a/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx b/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx
index 9387ffecd77..794f42d1861 100644
--- a/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx
+++ b/src/renderer/src/components/editor/MarkdownTemplatePicker.tsx
@@ -53,13 +53,26 @@ export function MarkdownTemplatePicker(): JSX.Element {
resolveRequest({ type: 'cancel' })
}
}}
- title={translate("auto.components.editor.MarkdownTemplatePicker.1829437fce", "New Markdown")}
- description={translate("auto.components.editor.MarkdownTemplatePicker.7b458e0b7f", "Choose a Markdown template.")}
+ title={translate('auto.components.editor.MarkdownTemplatePicker.1829437fce', 'New Markdown')}
+ description={translate(
+ 'auto.components.editor.MarkdownTemplatePicker.7b458e0b7f',
+ 'Choose a Markdown template.'
+ )}
contentClassName="w-[520px]"
>
-
+
- {translate("auto.components.editor.MarkdownTemplatePicker.df667919ca", "No matching templates.")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTemplatePicker.df667919ca',
+ 'No matching templates.'
+ )}
+
- {translate("auto.components.editor.MarkdownTemplatePicker.6e2e6c04ad", "Blank Markdown")}
- {translate("auto.components.editor.MarkdownTemplatePicker.22cd94426f", "untitled.md")}
+
+ {translate(
+ 'auto.components.editor.MarkdownTemplatePicker.6e2e6c04ad',
+ 'Blank Markdown'
+ )}
+
+
+ {translate(
+ 'auto.components.editor.MarkdownTemplatePicker.22cd94426f',
+ 'untitled.md'
+ )}
+
diff --git a/src/renderer/src/components/editor/MermaidBlock.tsx b/src/renderer/src/components/editor/MermaidBlock.tsx
index b798751b204..c85636e5399 100644
--- a/src/renderer/src/components/editor/MermaidBlock.tsx
+++ b/src/renderer/src/components/editor/MermaidBlock.tsx
@@ -84,7 +84,10 @@ export default function MermaidBlock({
if (error) {
return (
-
{translate("auto.components.editor.MermaidBlock.dcc132e691", "Diagram error:")}{error}
+
+ {translate('auto.components.editor.MermaidBlock.dcc132e691', 'Diagram error:')}
+ {error}
+
{content}
diff --git a/src/renderer/src/components/editor/MonacoEditor.tsx b/src/renderer/src/components/editor/MonacoEditor.tsx
index c3426cb4ca2..f3eed459f2c 100644
--- a/src/renderer/src/components/editor/MonacoEditor.tsx
+++ b/src/renderer/src/components/editor/MonacoEditor.tsx
@@ -382,7 +382,7 @@ export default function MonacoEditor({
)
const searchInFilesAction = editorInstance.addAction({
id: 'orca.searchInFiles',
- label: translate("auto.components.editor.MonacoEditor.fd68ae03b3", "Search in Files"),
+ label: translate('auto.components.editor.MonacoEditor.fd68ae03b3', 'Search in Files'),
contextMenuGroupId: 'navigation',
contextMenuOrder: 2,
run: () => {
@@ -751,8 +751,14 @@ export default function MonacoEditor({
top: Math.max(4, selectionAnnotationTarget.top - 22),
left: selectionAnnotationTarget.left ?? 4
}}
- title={translate("auto.components.editor.MonacoEditor.68cb83f4a7", "Add note on selected text")}
- aria-label={translate("auto.components.editor.MonacoEditor.68cb83f4a7", "Add note on selected text")}
+ title={translate(
+ 'auto.components.editor.MonacoEditor.68cb83f4a7',
+ 'Add note on selected text'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.MonacoEditor.68cb83f4a7',
+ 'Add note on selected text'
+ )}
onMouseDown={(event) => {
event.preventDefault()
event.stopPropagation()
diff --git a/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx b/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx
index 4c184e41e89..81fc40367de 100644
--- a/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx
+++ b/src/renderer/src/components/editor/MonacoGutterContextMenu.tsx
@@ -45,14 +45,22 @@ export function MonacoGutterContextMenu({
onSelect={() => window.api.ui.writeClipboardText(formatPathLineReference(filePath, line))}
>
- {translate("auto.components.editor.MonacoGutterContextMenu.4eaa991bde", "Copy Path to Line")}
+ {translate(
+ 'auto.components.editor.MonacoGutterContextMenu.4eaa991bde',
+ 'Copy Path to Line'
+ )}
+
window.api.ui.writeClipboardText(formatPathLineReference(relativePath, line))
}
>
- {translate("auto.components.editor.MonacoGutterContextMenu.2e0b1cdc05", "Copy Rel. Path to Line")}
+ {translate(
+ 'auto.components.editor.MonacoGutterContextMenu.2e0b1cdc05',
+ 'Copy Rel. Path to Line'
+ )}
+
{
const state = useAppStore.getState()
@@ -80,7 +88,11 @@ export function MonacoGutterContextMenu({
}}
>
- {translate("auto.components.editor.MonacoGutterContextMenu.7b57b1b468", "Copy Remote URL")}
+ {translate(
+ 'auto.components.editor.MonacoGutterContextMenu.7b57b1b468',
+ 'Copy Remote URL'
+ )}
+
)
diff --git a/src/renderer/src/components/editor/NotesSendMenu.tsx b/src/renderer/src/components/editor/NotesSendMenu.tsx
index 6c10280632c..823a001dd66 100644
--- a/src/renderer/src/components/editor/NotesSendMenu.tsx
+++ b/src/renderer/src/components/editor/NotesSendMenu.tsx
@@ -151,7 +151,15 @@ export function NotesSendMenu
({
)}
disabled={!hasDeliverableNotes}
title={hasDeliverableNotes ? ENABLED_SEND_TOOLTIP : disabledTooltip}
- aria-label={triggerLabel ? translate("auto.components.editor.NotesSendMenu.433928cd9f", "Send {{value0}} to an agent", { value0: triggerLabel }) : ENABLED_SEND_TOOLTIP}
+ aria-label={
+ triggerLabel
+ ? translate(
+ 'auto.components.editor.NotesSendMenu.433928cd9f',
+ 'Send {{value0}} to an agent',
+ { value0: triggerLabel }
+ )
+ : ENABLED_SEND_TOOLTIP
+ }
onMouseDown={(event) => event.stopPropagation()}
onClick={(event) => event.stopPropagation()}
>
@@ -184,7 +192,9 @@ export function NotesSendMenu({
>
{scopes.length > 1 ? (
<>
- {translate("auto.components.editor.NotesSendMenu.44dc5e60a6", "Send notes")}
+
+ {translate('auto.components.editor.NotesSendMenu.44dc5e60a6', 'Send notes')}
+
{scopes.map((scope) => (
setQuery(e.target.value)}
- placeholder={translate("auto.components.editor.PdfFind.2fc3ba0ea8", "Find in page...")}
+ placeholder={translate('auto.components.editor.PdfFind.2fc3ba0ea8', 'Find in page...')}
className="min-w-0 flex-1 border-none bg-transparent text-sm text-white outline-none placeholder:text-zinc-500"
/>
{query ? (
- {totalMatches > 0 ? translate("auto.components.editor.PdfFind.db56fcd6d2", "{{value0}} of {{value1}}", { value0: activeMatch, value1: totalMatches }) : translate("auto.components.editor.PdfFind.d080ab37d6", "No matches")}
+ {totalMatches > 0
+ ? translate('auto.components.editor.PdfFind.db56fcd6d2', '{{value0}} of {{value1}}', {
+ value0: activeMatch,
+ value1: totalMatches
+ })
+ : translate('auto.components.editor.PdfFind.d080ab37d6', 'No matches')}
) : null}
@@ -140,7 +145,7 @@ export default function PdfFind({
size="icon-xs"
onClick={findPrevious}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.editor.PdfFind.30de726ad0", "Previous match")}
+ title={translate('auto.components.editor.PdfFind.30de726ad0', 'Previous match')}
>
@@ -150,7 +155,7 @@ export default function PdfFind({
size="icon-xs"
onClick={findNext}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.editor.PdfFind.eeba2547a1", "Next match")}
+ title={translate('auto.components.editor.PdfFind.eeba2547a1', 'Next match')}
>
@@ -161,7 +166,7 @@ export default function PdfFind({
size="icon-xs"
onClick={onClose}
className="flex size-6 shrink-0 items-center justify-center rounded text-zinc-400 hover:text-zinc-200"
- title={translate("auto.components.editor.PdfFind.cd65b1d6b0", "Close")}
+ title={translate('auto.components.editor.PdfFind.cd65b1d6b0', 'Close')}
>
diff --git a/src/renderer/src/components/editor/PdfViewer.tsx b/src/renderer/src/components/editor/PdfViewer.tsx
index c5127775338..60495f7f837 100644
--- a/src/renderer/src/components/editor/PdfViewer.tsx
+++ b/src/renderer/src/components/editor/PdfViewer.tsx
@@ -216,7 +216,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
{filename}
- {translate("auto.components.editor.PdfViewer.3e98d500d2", "PDF preview")}
+ {translate('auto.components.editor.PdfViewer.3e98d500d2', 'PDF preview')}
)
@@ -252,7 +252,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
className="rounded p-1 hover:bg-accent hover:text-foreground disabled:opacity-50"
onClick={zoomOut}
disabled={scale <= MIN_SCALE}
- title={translate("auto.components.editor.PdfViewer.fa5d096b00", "Zoom out")}
+ title={translate('auto.components.editor.PdfViewer.fa5d096b00', 'Zoom out')}
>
@@ -260,7 +260,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
type="button"
className="rounded p-1 hover:bg-accent hover:text-foreground"
onClick={zoomReset}
- title={translate("auto.components.editor.PdfViewer.c0119616d6", "Fit to width")}
+ title={translate('auto.components.editor.PdfViewer.c0119616d6', 'Fit to width')}
>
@@ -269,7 +269,7 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
className="rounded p-1 hover:bg-accent hover:text-foreground disabled:opacity-50"
onClick={zoomIn}
disabled={scale >= MAX_SCALE}
- title={translate("auto.components.editor.PdfViewer.2b6eb1ccd6", "Zoom in")}
+ title={translate('auto.components.editor.PdfViewer.2b6eb1ccd6', 'Zoom in')}
>
@@ -279,14 +279,18 @@ export default function PdfViewer({ content, filePath }: PdfViewerProps): JSX.El
type="button"
className="rounded p-1 hover:bg-accent hover:text-foreground"
onClick={() => setFindOpen(true)}
- title={translate("auto.components.editor.PdfViewer.069ff59932", "Find in PDF ({{value0}})", { value0: findShortcutLabel })}
+ title={translate(
+ 'auto.components.editor.PdfViewer.069ff59932',
+ 'Find in PDF ({{value0}})',
+ { value0: findShortcutLabel }
+ )}
>
{filename}
-
{translate("auto.components.editor.PdfViewer.3e98d500d2", "PDF preview")}
+
{translate('auto.components.editor.PdfViewer.3e98d500d2', 'PDF preview')}
)
diff --git a/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx b/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx
index 3457908b326..572746cda2f 100644
--- a/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx
+++ b/src/renderer/src/components/editor/ReviewNotesSendMenuContent.tsx
@@ -38,19 +38,34 @@ export function ReviewNotesSendMenuContent({
if (!hasPrompt || !canSendToActiveAgent) {
return
}
- const pending = toast.loading(translate("auto.components.editor.ReviewNotesSendMenuContent.50f7e753ea", "Sending notes to active agent..."))
+ const pending = toast.loading(
+ translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.50f7e753ea',
+ 'Sending notes to active agent...'
+ )
+ )
void sendNotesToActiveAgentSession({ worktreeId, prompt })
.then((result) => {
if (result.status === 'sent') {
onPromptDelivered?.()
- toast.success(translate("auto.components.editor.ReviewNotesSendMenuContent.bb9c69a0c9", "Notes sent to active agent."))
+ toast.success(
+ translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.bb9c69a0c9',
+ 'Notes sent to active agent.'
+ )
+ )
return
}
toast.message(activeAgentNotesSendFailureMessage(result.status))
})
.catch((error) => {
console.error('Failed to send notes to active agent:', error)
- toast.error(translate("auto.components.editor.ReviewNotesSendMenuContent.f5096c6e4e", "Could not send notes to the active agent."))
+ toast.error(
+ translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.f5096c6e4e',
+ 'Could not send notes to the active agent.'
+ )
+ )
})
.finally(() => {
toast.dismiss(pending)
@@ -59,16 +74,24 @@ export function ReviewNotesSendMenuContent({
return (
<>
- {translate("auto.components.editor.ReviewNotesSendMenuContent.03378aea75", "Send notes to")}
+
+ {translate('auto.components.editor.ReviewNotesSendMenuContent.03378aea75', 'Send notes to')}
+
- {translate("auto.components.editor.ReviewNotesSendMenuContent.e84705f223", "Active agent session")}
+ {translate(
+ 'auto.components.editor.ReviewNotesSendMenuContent.e84705f223',
+ 'Active agent session'
+ )}
+
- {translate("auto.components.editor.ReviewNotesSendMenuContent.a49800405b", "New agent")}
+
+ {translate('auto.components.editor.ReviewNotesSendMenuContent.a49800405b', 'New agent')}
+
{
event.preventDefault()
event.stopPropagation()
@@ -56,7 +62,10 @@ export function RichMarkdownAnnotationOverlay({
}
top={popover.top}
left={popover.left}
- title={translate("auto.components.editor.RichMarkdownAnnotationOverlay.069b5677b8", "Selected text")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownAnnotationOverlay.069b5677b8',
+ 'Selected text'
+ )}
onCancel={onCancelPopover}
onSubmit={onSubmit}
/>
diff --git a/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx b/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx
index 77652225b4f..8a6aad7db50 100644
--- a/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownCodeBlock.tsx
@@ -12,31 +12,103 @@ import { translate } from '@/i18n/i18n'
* this list is just for quick picking in the UI.
*/
const LANGUAGES = [
- { value: '', label: translate("auto.components.editor.RichMarkdownCodeBlock.13822cdfda", "Plain text") },
- { value: 'bash', label: translate("auto.components.editor.RichMarkdownCodeBlock.4227cf50fe", "Bash") },
+ {
+ value: '',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.13822cdfda', 'Plain text')
+ },
+ {
+ value: 'bash',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.4227cf50fe', 'Bash')
+ },
{ value: 'c', label: 'C' },
- { value: 'cpp', label: translate("auto.components.editor.RichMarkdownCodeBlock.4daed43ae3", "C++") },
- { value: 'css', label: translate("auto.components.editor.RichMarkdownCodeBlock.026653f21f", "CSS") },
- { value: 'diff', label: translate("auto.components.editor.RichMarkdownCodeBlock.bf6ee5caaa", "Diff") },
- { value: 'go', label: translate("auto.components.editor.RichMarkdownCodeBlock.edfcc64182", "Go") },
- { value: 'graphql', label: translate("auto.components.editor.RichMarkdownCodeBlock.706fd85738", "GraphQL") },
- { value: 'html', label: translate("auto.components.editor.RichMarkdownCodeBlock.8c4a3fa02d", "HTML") },
- { value: 'java', label: translate("auto.components.editor.RichMarkdownCodeBlock.36536ad539", "Java") },
- { value: 'javascript', label: translate("auto.components.editor.RichMarkdownCodeBlock.a209c57063", "JavaScript") },
- { value: 'json', label: translate("auto.components.editor.RichMarkdownCodeBlock.78eba32de4", "JSON") },
- { value: 'kotlin', label: translate("auto.components.editor.RichMarkdownCodeBlock.bcb236e2d8", "Kotlin") },
- { value: 'markdown', label: translate("auto.components.editor.RichMarkdownCodeBlock.983b9576b4", "Markdown") },
- { value: 'mermaid', label: translate("auto.components.editor.RichMarkdownCodeBlock.89d6cc14fb", "Mermaid") },
- { value: 'python', label: translate("auto.components.editor.RichMarkdownCodeBlock.2391f9cda9", "Python") },
- { value: 'ruby', label: translate("auto.components.editor.RichMarkdownCodeBlock.96182a2f64", "Ruby") },
- { value: 'rust', label: translate("auto.components.editor.RichMarkdownCodeBlock.e72e6b03f4", "Rust") },
- { value: 'scss', label: translate("auto.components.editor.RichMarkdownCodeBlock.5af8251002", "SCSS") },
- { value: 'shell', label: translate("auto.components.editor.RichMarkdownCodeBlock.d01f55be57", "Shell") },
- { value: 'sql', label: translate("auto.components.editor.RichMarkdownCodeBlock.3009f722b9", "SQL") },
- { value: 'swift', label: translate("auto.components.editor.RichMarkdownCodeBlock.9e384d48dc", "Swift") },
- { value: 'typescript', label: translate("auto.components.editor.RichMarkdownCodeBlock.88d777bc07", "TypeScript") },
- { value: 'xml', label: translate("auto.components.editor.RichMarkdownCodeBlock.5ef5605cb7", "XML") },
- { value: 'yaml', label: translate("auto.components.editor.RichMarkdownCodeBlock.74eab1d9b2", "YAML") }
+ {
+ value: 'cpp',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.4daed43ae3', 'C++')
+ },
+ {
+ value: 'css',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.026653f21f', 'CSS')
+ },
+ {
+ value: 'diff',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.bf6ee5caaa', 'Diff')
+ },
+ {
+ value: 'go',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.edfcc64182', 'Go')
+ },
+ {
+ value: 'graphql',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.706fd85738', 'GraphQL')
+ },
+ {
+ value: 'html',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.8c4a3fa02d', 'HTML')
+ },
+ {
+ value: 'java',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.36536ad539', 'Java')
+ },
+ {
+ value: 'javascript',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.a209c57063', 'JavaScript')
+ },
+ {
+ value: 'json',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.78eba32de4', 'JSON')
+ },
+ {
+ value: 'kotlin',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.bcb236e2d8', 'Kotlin')
+ },
+ {
+ value: 'markdown',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.983b9576b4', 'Markdown')
+ },
+ {
+ value: 'mermaid',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.89d6cc14fb', 'Mermaid')
+ },
+ {
+ value: 'python',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.2391f9cda9', 'Python')
+ },
+ {
+ value: 'ruby',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.96182a2f64', 'Ruby')
+ },
+ {
+ value: 'rust',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.e72e6b03f4', 'Rust')
+ },
+ {
+ value: 'scss',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.5af8251002', 'SCSS')
+ },
+ {
+ value: 'shell',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.d01f55be57', 'Shell')
+ },
+ {
+ value: 'sql',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.3009f722b9', 'SQL')
+ },
+ {
+ value: 'swift',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.9e384d48dc', 'Swift')
+ },
+ {
+ value: 'typescript',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.88d777bc07', 'TypeScript')
+ },
+ {
+ value: 'xml',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.5ef5605cb7', 'XML')
+ },
+ {
+ value: 'yaml',
+ label: translate('auto.components.editor.RichMarkdownCodeBlock.74eab1d9b2', 'YAML')
+ }
]
export function RichMarkdownCodeBlock({
@@ -128,13 +200,18 @@ export function RichMarkdownCodeBlock({
className="code-block-copy-btn"
contentEditable={false}
onClick={handleCopy}
- aria-label={translate("auto.components.editor.RichMarkdownCodeBlock.c72beafc0f", "Copy code")}
- title={translate("auto.components.editor.RichMarkdownCodeBlock.c72beafc0f", "Copy code")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownCodeBlock.c72beafc0f',
+ 'Copy code'
+ )}
+ title={translate('auto.components.editor.RichMarkdownCodeBlock.c72beafc0f', 'Copy code')}
>
{copied ? (
<>
- {translate("auto.components.editor.RichMarkdownCodeBlock.232d9ed853", "Copied")}
+
+ {translate('auto.components.editor.RichMarkdownCodeBlock.232d9ed853', 'Copied')}
+
>
) : (
diff --git a/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx b/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx
index ea548a5e4e6..d339f1e3da6 100644
--- a/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownDocLinkMenu.tsx
@@ -26,10 +26,18 @@ export function RichMarkdownDocLinkMenu({
className="rich-markdown-doc-link-menu"
style={{ left: menu.left, top: menu.top }}
role="listbox"
- aria-label={translate("auto.components.editor.RichMarkdownDocLinkMenu.0e8489bc11", "Markdown document links")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownDocLinkMenu.0e8489bc11',
+ 'Markdown document links'
+ )}
>
{rows.length === 0 ? (
- {translate("auto.components.editor.RichMarkdownDocLinkMenu.63ced7cb9b", "No documents found")}
+
+ {translate(
+ 'auto.components.editor.RichMarkdownDocLinkMenu.63ced7cb9b',
+ 'No documents found'
+ )}
+
) : (
rows.map((row, index) => {
const rowKey = row.kind === 'document' ? row.document.filePath : row.id
@@ -60,11 +68,18 @@ export function RichMarkdownDocLinkMenu({
)}
{overflow ? (
- {translate("auto.components.editor.RichMarkdownDocLinkMenu.2aaf7d9678", "Showing")}{rows.length} {translate("auto.components.editor.RichMarkdownDocLinkMenu.90c5f0e1e4", "of")}{totalMatches}
+ {translate('auto.components.editor.RichMarkdownDocLinkMenu.2aaf7d9678', 'Showing')}
+ {rows.length}{' '}
+ {translate('auto.components.editor.RichMarkdownDocLinkMenu.90c5f0e1e4', 'of')}
+ {totalMatches}
) : null}
- {translate("auto.components.editor.RichMarkdownDocLinkMenu.e17b987473", "↑↓ navigate ↵ select esc dismiss")}
+ {translate(
+ 'auto.components.editor.RichMarkdownDocLinkMenu.e17b987473',
+ '↑↓ navigate ↵ select esc dismiss'
+ )}
+
)
}
diff --git a/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx b/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx
index a26391f3f15..c99cc1a675b 100644
--- a/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownErrorBoundary.tsx
@@ -55,14 +55,23 @@ export class RichMarkdownErrorBoundary extends React.Component {
return (
- {translate("auto.components.editor.RichMarkdownErrorBoundary.dfdf1cacd4", "The rich markdown editor hit an unexpected error and was reset to keep the rest of Orca responsive.")}
+ {translate(
+ 'auto.components.editor.RichMarkdownErrorBoundary.dfdf1cacd4',
+ 'The rich markdown editor hit an unexpected error and was reset to keep the rest of Orca responsive.'
+ )}
+
- {translate("auto.components.editor.RichMarkdownErrorBoundary.4a5de9f2f0", "Switch to source mode, or click retry to reload the rich view.")}
+ {translate(
+ 'auto.components.editor.RichMarkdownErrorBoundary.4a5de9f2f0',
+ 'Switch to source mode, or click retry to reload the rich view.'
+ )}
+
- {translate("auto.components.editor.RichMarkdownErrorBoundary.aad0998127", "Retry")}
+ {translate('auto.components.editor.RichMarkdownErrorBoundary.aad0998127', 'Retry')}
+
)
}
diff --git a/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx b/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx
index 801fefb3840..7a144d446d6 100644
--- a/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownLinkBubble.tsx
@@ -81,7 +81,10 @@ function LinkEditInput({
onCancel()
}
}}
- placeholder={translate("auto.components.editor.RichMarkdownLinkBubble.7b0b945fdc", "Paste or type a link…")}
+ placeholder={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.7b0b945fdc',
+ 'Paste or type a link…'
+ )}
className="rich-markdown-link-input"
/>
)
@@ -130,7 +133,10 @@ export function RichMarkdownLinkBubble({
type="button"
className="rich-markdown-link-button"
onClick={onOpen}
- title={translate("auto.components.editor.RichMarkdownLinkBubble.bfc813e909", "Open link")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.bfc813e909',
+ 'Open link'
+ )}
>
@@ -138,7 +144,10 @@ export function RichMarkdownLinkBubble({
type="button"
className="rich-markdown-link-button"
onClick={onEditStart}
- title={translate("auto.components.editor.RichMarkdownLinkBubble.cdfe166f6f", "Edit link")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.cdfe166f6f',
+ 'Edit link'
+ )}
>
@@ -146,7 +155,10 @@ export function RichMarkdownLinkBubble({
type="button"
className="rich-markdown-link-button"
onClick={onRemove}
- title={translate("auto.components.editor.RichMarkdownLinkBubble.1c99b726e0", "Remove link")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownLinkBubble.1c99b726e0',
+ 'Remove link'
+ )}
>
diff --git a/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx b/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx
index 39d447e0f90..881cef3ff1d 100644
--- a/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownReviewNoteLayer.tsx
@@ -49,7 +49,13 @@ export function RichMarkdownReviewNoteLayer({
onDelivered
}: RichMarkdownReviewNoteLayerProps): React.JSX.Element {
return (
-
+
{positions.map(({ comment, top }) => (
event.stopPropagation()}
onClick={(event) => {
@@ -105,7 +129,10 @@ export function RichMarkdownReviewNoteLayer({
scopes={[
{
id: 'note',
- label: translate("auto.components.editor.RichMarkdownReviewNoteLayer.f3ef92952b", "This note"),
+ label: translate(
+ 'auto.components.editor.RichMarkdownReviewNoteLayer.f3ef92952b',
+ 'This note'
+ ),
notes: comment.sentAt ? [] : [comment as MarkdownReviewNote],
prompt: formatMarkdownReviewNotes(
[comment as MarkdownReviewNote],
diff --git a/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx b/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx
index 922e889138c..4c0c058e88a 100644
--- a/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownReviewRailActions.tsx
@@ -31,9 +31,29 @@ export function RichMarkdownReviewRailActions({
@@ -42,8 +62,28 @@ export function RichMarkdownReviewRailActions({
{notesCopied ? : }
diff --git a/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx b/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx
index 9aa31e1d133..aa985fdb8de 100644
--- a/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownSearchBar.tsx
@@ -59,14 +59,20 @@ export function RichMarkdownSearchBar({
onClose()
}
}}
- placeholder={translate("auto.components.editor.RichMarkdownSearchBar.98b89276f3", "Find in rich editor")}
+ placeholder={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.98b89276f3',
+ 'Find in rich editor'
+ )}
className="rich-markdown-search-input h-7 !border-0 bg-transparent px-2 shadow-none focus-visible:!border-0 focus-visible:ring-0"
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.158c645829", "Find in rich markdown editor")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.158c645829',
+ 'Find in rich markdown editor'
+ )}
/>
{query && matchCount === 0
- ? translate("auto.components.editor.RichMarkdownSearchBar.a86958d508", "No results")
+ ? translate('auto.components.editor.RichMarkdownSearchBar.a86958d508', 'No results')
: `${matchCount === 0 ? 0 : activeMatchIndex + 1}/${matchCount}`}
onMoveToMatch(-1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.RichMarkdownSearchBar.32ae8d7d57", "Previous match")}
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.32ae8d7d57", "Previous match")}
+ title={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.32ae8d7d57',
+ 'Previous match'
+ )}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.32ae8d7d57',
+ 'Previous match'
+ )}
className="rich-markdown-search-button"
>
@@ -89,8 +101,11 @@ export function RichMarkdownSearchBar({
onMouseDown={keepSearchFocus}
onClick={() => onMoveToMatch(1)}
disabled={matchCount === 0}
- title={translate("auto.components.editor.RichMarkdownSearchBar.f7bcecbe26", "Next match")}
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.f7bcecbe26", "Next match")}
+ title={translate('auto.components.editor.RichMarkdownSearchBar.f7bcecbe26', 'Next match')}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.f7bcecbe26',
+ 'Next match'
+ )}
className="rich-markdown-search-button"
>
@@ -102,8 +117,11 @@ export function RichMarkdownSearchBar({
size="icon-xs"
onMouseDown={keepSearchFocus}
onClick={onClose}
- title={translate("auto.components.editor.RichMarkdownSearchBar.de68b75bde", "Close search")}
- aria-label={translate("auto.components.editor.RichMarkdownSearchBar.de68b75bde", "Close search")}
+ title={translate('auto.components.editor.RichMarkdownSearchBar.de68b75bde', 'Close search')}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSearchBar.de68b75bde',
+ 'Close search'
+ )}
className="rich-markdown-search-button"
>
diff --git a/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx b/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx
index c1d90169a0d..a3a1e5f7614 100644
--- a/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownSlashMenu.tsx
@@ -30,21 +30,35 @@ export function RichMarkdownSlashMenu({
className="rich-markdown-slash-menu"
style={{ left: slashMenu.left, top: slashMenu.top }}
role="dialog"
- aria-label={translate("auto.components.editor.RichMarkdownSlashMenu.2e0400b958", "Slash commands")}
+ aria-label={translate(
+ 'auto.components.editor.RichMarkdownSlashMenu.2e0400b958',
+ 'Slash commands'
+ )}
>
event.preventDefault()}>
{filteredCommands.length === 0 ? (
-
{translate("auto.components.editor.RichMarkdownSlashMenu.82c6816ff8", "No blocks found")}
+
+ {translate(
+ 'auto.components.editor.RichMarkdownSlashMenu.82c6816ff8',
+ 'No blocks found'
+ )}
+
) : (
filteredCommands.map((command, index) => {
const showGroup = command.group !== currentGroup
diff --git a/src/renderer/src/components/editor/RichMarkdownToolbar.tsx b/src/renderer/src/components/editor/RichMarkdownToolbar.tsx
index 7dff6dc7168..7120a71db12 100644
--- a/src/renderer/src/components/editor/RichMarkdownToolbar.tsx
+++ b/src/renderer/src/components/editor/RichMarkdownToolbar.tsx
@@ -34,28 +34,28 @@ export function RichMarkdownToolbar({
editor?.chain().focus().setParagraph().run()}
>
editor?.chain().focus().toggleHeading({ level: 1 }).run()}
>
editor?.chain().focus().toggleHeading({ level: 2 }).run()}
>
editor?.chain().focus().toggleHeading({ level: 3 }).run()}
>
@@ -63,21 +63,21 @@ export function RichMarkdownToolbar({
editor?.chain().focus().toggleBold().run()}
>
B
editor?.chain().focus().toggleItalic().run()}
>
I
editor?.chain().focus().toggleStrike().run()}
>
S
@@ -85,21 +85,21 @@ export function RichMarkdownToolbar({
editor?.chain().focus().toggleBulletList().run()}
>
editor?.chain().focus().toggleOrderedList().run()}
>
editor?.chain().focus().toggleTaskList().run()}
>
@@ -107,15 +107,23 @@ export function RichMarkdownToolbar({
editor?.chain().focus().toggleBlockquote().run()}
>
-
+
-
+
diff --git a/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx b/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx
index c1094969025..e9e6d9c018c 100644
--- a/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx
+++ b/src/renderer/src/components/editor/UntitledFileRenameDialog.tsx
@@ -133,13 +133,21 @@ export function UntitledFileRenameDialog({
}}
>
- {translate("auto.components.editor.UntitledFileRenameDialog.674b046582", "Save as")}
+
+ {translate('auto.components.editor.UntitledFileRenameDialog.674b046582', 'Save as')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.e365f3c638", "Name your markdown file and pick a folder.")}
+ {translate(
+ 'auto.components.editor.UntitledFileRenameDialog.e365f3c638',
+ 'Name your markdown file and pick a folder.'
+ )}
+
-
{translate("auto.components.editor.UntitledFileRenameDialog.b6ed807cc6", "Name")}
+
+ {translate('auto.components.editor.UntitledFileRenameDialog.b6ed807cc6', 'Name')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.2d7d39dc63", ".md")}
+
+ {translate('auto.components.editor.UntitledFileRenameDialog.2d7d39dc63', '.md')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.30099dca46", "Folder")}
+ {translate('auto.components.editor.UntitledFileRenameDialog.30099dca46', 'Folder')}
+
void handleBrowse()}
title={
- disableBrowse ? translate("auto.components.editor.UntitledFileRenameDialog.5e7f0d8a80", "Folder picker unavailable for remote files") : translate("auto.components.editor.UntitledFileRenameDialog.725868c75d", "Browse folders")
+ disableBrowse
+ ? translate(
+ 'auto.components.editor.UntitledFileRenameDialog.5e7f0d8a80',
+ 'Folder picker unavailable for remote files'
+ )
+ : translate(
+ 'auto.components.editor.UntitledFileRenameDialog.725868c75d',
+ 'Browse folders'
+ )
}
>
@@ -198,9 +220,11 @@ export function UntitledFileRenameDialog({
{displayError &&
{displayError}
}
- {translate("auto.components.editor.UntitledFileRenameDialog.949711deb4", "Cancel")}
+ {translate('auto.components.editor.UntitledFileRenameDialog.949711deb4', 'Cancel')}
+
- {translate("auto.components.editor.UntitledFileRenameDialog.a7dd27b0bc", "Save")}
+ {translate('auto.components.editor.UntitledFileRenameDialog.a7dd27b0bc', 'Save')}
+
diff --git a/src/renderer/src/components/editor/export-active-markdown.ts b/src/renderer/src/components/editor/export-active-markdown.ts
index 6125e836ea2..eccc260b536 100644
--- a/src/renderer/src/components/editor/export-active-markdown.ts
+++ b/src/renderer/src/components/editor/export-active-markdown.ts
@@ -16,14 +16,23 @@ export async function exportActiveMarkdownToPdf(): Promise
{
return
}
- const toastId = toast.loading(translate("auto.components.editor.export.active.markdown.d4a901e0ad", "Exporting PDF..."))
+ const toastId = toast.loading(
+ translate('auto.components.editor.export.active.markdown.d4a901e0ad', 'Exporting PDF...')
+ )
try {
const result = await window.api.export.htmlToPdf({
html: payload.html,
title: payload.title
})
if (result.success) {
- toast.success(translate("auto.components.editor.export.active.markdown.51c4244904", "Exported to {{value0}}", { value0: result.filePath }), { id: toastId })
+ toast.success(
+ translate(
+ 'auto.components.editor.export.active.markdown.51c4244904',
+ 'Exported to {{value0}}',
+ { value0: result.filePath }
+ ),
+ { id: toastId }
+ )
return
}
if (result.cancelled) {
@@ -32,7 +41,14 @@ export async function exportActiveMarkdownToPdf(): Promise {
toast.dismiss(toastId)
return
}
- toast.error(result.error ?? translate("auto.components.editor.export.active.markdown.eda2cea3ad", "Failed to export PDF"), { id: toastId })
+ toast.error(
+ result.error ??
+ translate(
+ 'auto.components.editor.export.active.markdown.eda2cea3ad',
+ 'Failed to export PDF'
+ ),
+ { id: toastId }
+ )
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to export PDF'
toast.error(message, { id: toastId })
diff --git a/src/renderer/src/components/editor/markdown-rich-mode.ts b/src/renderer/src/components/editor/markdown-rich-mode.ts
index b22e2358d39..2cd1aebf7d0 100644
--- a/src/renderer/src/components/editor/markdown-rich-mode.ts
+++ b/src/renderer/src/components/editor/markdown-rich-mode.ts
@@ -17,7 +17,10 @@ type UnsupportedMatch = {
const UNSUPPORTED_PATTERNS: UnsupportedMatch[] = [
{
reason: 'html-or-jsx',
- message: translate("auto.components.editor.markdown.rich.mode.57128b73e1", "Editable only in code mode because this file contains HTML, JSX, or MDX."),
+ message: translate(
+ 'auto.components.editor.markdown.rich.mode.57128b73e1',
+ 'Editable only in code mode because this file contains HTML, JSX, or MDX.'
+ ),
// Why: the rich editor preserves common embedded markup via placeholder
// tokens before parsing, but any HTML shape that still fails round-trip
// must fall back instead of risking silent source corruption.
@@ -25,12 +28,18 @@ const UNSUPPORTED_PATTERNS: UnsupportedMatch[] = [
},
{
reason: 'reference-links',
- message: translate("auto.components.editor.markdown.rich.mode.2fd2b44073", "Editable only in code mode because this file contains reference-style links."),
+ message: translate(
+ 'auto.components.editor.markdown.rich.mode.2fd2b44073',
+ 'Editable only in code mode because this file contains reference-style links.'
+ ),
pattern: /^\[[^\]]+\]:\s+\S+/m
},
{
reason: 'footnotes',
- message: translate("auto.components.editor.markdown.rich.mode.7a8ce7c7da", "Editable only in code mode because this file contains footnotes."),
+ message: translate(
+ 'auto.components.editor.markdown.rich.mode.7a8ce7c7da',
+ 'Editable only in code mode because this file contains footnotes.'
+ ),
pattern: /^\[\^[^\]]+\]:\s+/m
}
]
diff --git a/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts b/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts
index 7258f7d1688..4df725b8b63 100644
--- a/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts
+++ b/src/renderer/src/components/editor/rich-markdown-editor-click-routing.ts
@@ -198,7 +198,13 @@ function openMarkdownLinkInClientOs({
if (classified.kind === 'markdown') {
void window.api.shell.pathExists(classified.absolutePath).then((exists) => {
if (!exists) {
- toast.error(translate("auto.components.editor.rich.markdown.editor.click.routing.2d5fb9335d", "File not found: {{value0}}", { value0: classified.relativePath }))
+ toast.error(
+ translate(
+ 'auto.components.editor.rich.markdown.editor.click.routing.2d5fb9335d',
+ 'File not found: {{value0}}',
+ { value0: classified.relativePath }
+ )
+ )
return
}
void window.api.shell.openFileUri(toFileUrlForOsEscape(classified.absolutePath))
diff --git a/src/renderer/src/components/editor/useContextualCopySetup.tsx b/src/renderer/src/components/editor/useContextualCopySetup.tsx
index 5b268650ba7..e115422f88b 100644
--- a/src/renderer/src/components/editor/useContextualCopySetup.tsx
+++ b/src/renderer/src/components/editor/useContextualCopySetup.tsx
@@ -35,7 +35,8 @@ export function useContextualCopySetup() {
className="pointer-events-none fixed z-50 rounded-md bg-foreground px-2 py-1 text-xs text-background shadow-sm"
style={{ left: copyToast.left, top: copyToast.top }}
>
- {translate("auto.components.editor.useContextualCopySetup.059bfb0d94", "Context copied")}
+ {translate('auto.components.editor.useContextualCopySetup.059bfb0d94', 'Context copied')}
+
) : null
return { setupCopy, toastNode }
diff --git a/src/renderer/src/components/editor/useLocalImagePick.ts b/src/renderer/src/components/editor/useLocalImagePick.ts
index fb8ed8db8c7..f04445e5301 100644
--- a/src/renderer/src/components/editor/useLocalImagePick.ts
+++ b/src/renderer/src/components/editor/useLocalImagePick.ts
@@ -37,7 +37,12 @@ export function useLocalImagePick(
if (settings?.activeRuntimeEnvironmentId?.trim() || connectionId) {
const worktreePath = getWorktreePath(worktreeId)
if (settings?.activeRuntimeEnvironmentId?.trim() && !worktreePath) {
- toast.error(translate("auto.components.editor.useLocalImagePick.91d835dc88", "Worktree path not available."))
+ toast.error(
+ translate(
+ 'auto.components.editor.useLocalImagePick.91d835dc88',
+ 'Worktree path not available.'
+ )
+ )
return
}
// Why: picked images are client-local files while remote markdown lives
@@ -55,7 +60,12 @@ export function useLocalImagePick(
)
const imported = results.find((result) => result.status === 'imported')
if (!imported) {
- toast.error(translate("auto.components.editor.useLocalImagePick.175cb8b8ce", "Failed to insert image."))
+ toast.error(
+ translate(
+ 'auto.components.editor.useLocalImagePick.175cb8b8ce',
+ 'Failed to insert image.'
+ )
+ )
return
}
editor
diff --git a/src/renderer/src/components/editor/useRichMarkdownReviewData.ts b/src/renderer/src/components/editor/useRichMarkdownReviewData.ts
index 66baa59cdb8..e0dc9286034 100644
--- a/src/renderer/src/components/editor/useRichMarkdownReviewData.ts
+++ b/src/renderer/src/components/editor/useRichMarkdownReviewData.ts
@@ -57,7 +57,10 @@ export function useRichMarkdownReviewData({
return [
{
id: 'all',
- label: translate("auto.components.editor.useRichMarkdownReviewData.f9d2acd6b0", "All unsent notes"),
+ label: translate(
+ 'auto.components.editor.useRichMarkdownReviewData.f9d2acd6b0',
+ 'All unsent notes'
+ ),
notes: unsentNotes,
prompt: formatMarkdownReviewNotes(unsentNotes, markdownReviewContent)
}
diff --git a/src/renderer/src/components/emulator-pane/EmulatorPane.tsx b/src/renderer/src/components/emulator-pane/EmulatorPane.tsx
index 8913b91a027..1b3499e827c 100644
--- a/src/renderer/src/components/emulator-pane/EmulatorPane.tsx
+++ b/src/renderer/src/components/emulator-pane/EmulatorPane.tsx
@@ -71,7 +71,12 @@ function EmulatorPaneContent({ tab, worktreeId, isActive = true }: EmulatorPaneP
{!isLive && !loading ? (
-
{translate("auto.components.emulator.pane.EmulatorPane.59b08fa031", "No emulator connected")}
+
+ {translate(
+ 'auto.components.emulator.pane.EmulatorPane.59b08fa031',
+ 'No emulator connected'
+ )}
+
) : null}
- {frameLayout?.kind === "phone" ? : null}
+ {frameLayout?.kind === 'phone' ? : null}
diff --git a/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx b/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx
index 3ede31d788f..764a9e579d7 100644
--- a/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx
+++ b/src/renderer/src/components/emulator-pane/emulator-pane-toolbar.tsx
@@ -65,7 +65,12 @@ export function EmulatorPaneToolbar({
disabled={loading || devices.length === 0}
>
-
+
{devices.map((d) => (
@@ -84,14 +89,23 @@ export function EmulatorPaneToolbar({
className="h-7 gap-1 px-2 text-xs"
onClick={onRotate}
disabled={!isLive || loading}
- aria-label={translate("auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a", "Rotate")}
+ aria-label={translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a',
+ 'Rotate'
+ )}
>
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a", "Rotate")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a',
+ 'Rotate'
+ )}
+
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a", "Rotate")}
+ {translate('auto.components.emulator.pane.emulator.pane.toolbar.6bd8dff42a', 'Rotate')}
+
@@ -102,13 +116,17 @@ export function EmulatorPaneToolbar({
className="size-7"
onClick={onHome}
disabled={!isLive || loading}
- aria-label={translate("auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e", "Home")}
+ aria-label={translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e',
+ 'Home'
+ )}
>
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e", "Home")}
+ {translate('auto.components.emulator.pane.emulator.pane.toolbar.e7a0d1897e', 'Home')}
+
{isLive ? (
@@ -120,13 +138,20 @@ export function EmulatorPaneToolbar({
className="size-7 text-muted-foreground hover:text-destructive"
onClick={onShutdown}
disabled={loading}
- aria-label={translate("auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356", "Shut down emulator")}
+ aria-label={translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356',
+ 'Shut down emulator'
+ )}
>
- {translate("auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356", "Shut down emulator")}
+ {translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.06e10d7356',
+ 'Shut down emulator'
+ )}
+
) : (
- {loading ? translate("auto.components.emulator.pane.emulator.pane.toolbar.868c0f2938", "Working…") : translate("auto.components.emulator.pane.emulator.pane.toolbar.81b3571a07", "Connect")}
+ {loading
+ ? translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.868c0f2938',
+ 'Working…'
+ )
+ : translate(
+ 'auto.components.emulator.pane.emulator.pane.toolbar.81b3571a07',
+ 'Connect'
+ )}
)}
diff --git a/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx b/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx
index 5dad5751c72..426212484a1 100644
--- a/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx
+++ b/src/renderer/src/components/emulator-pane/emulator-screen-stream-content.tsx
@@ -44,7 +44,10 @@ export function EmulatorScreenStreamContent({
- {translate("auto.components.emulator.pane.emulator.screen.stream.content.5f818f12ab", "Connecting emulator…")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.screen.stream.content.5f818f12ab',
+ 'Connecting emulator…'
+ )}
+
>
) : displayError ? (
- {translate("auto.components.emulator.pane.emulator.screen.stream.content.36841af608", "Stream disconnected")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.screen.stream.content.36841af608',
+ 'Stream disconnected'
+ )}
+
) : (
- {translate("auto.components.emulator.pane.emulator.screen.stream.content.8b1a0d8694", "Emulator preview")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.screen.stream.content.8b1a0d8694',
+ 'Emulator preview'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx b/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx
index 96f06e6bdc8..5be35a7549c 100644
--- a/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx
+++ b/src/renderer/src/components/emulator-pane/emulator-unavailable-pane.tsx
@@ -5,9 +5,18 @@ export function EmulatorUnavailablePane() {
return (
-
{translate("auto.components.emulator.pane.emulator.unavailable.pane.b2c268a0b9", "Mobile Emulator is macOS only")}
+
+ {translate(
+ 'auto.components.emulator.pane.emulator.unavailable.pane.b2c268a0b9',
+ 'Mobile Emulator is macOS only'
+ )}
+
- {translate("auto.components.emulator.pane.emulator.unavailable.pane.f630b9ca9f", "Mobile Emulator requires a Mac with Xcode and the iOS Simulator runtime. On Linux or Windows, use a physical device or a remote Mac build host.")}
+ {translate(
+ 'auto.components.emulator.pane.emulator.unavailable.pane.f630b9ca9f',
+ 'Mobile Emulator requires a Mac with Xcode and the iOS Simulator runtime. On Linux or Windows, use a physical device or a remote Mac build host.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts b/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts
index d29847e011f..367b37e6b37 100644
--- a/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts
+++ b/src/renderer/src/components/emulator-pane/use-emulator-frame-stream.ts
@@ -47,7 +47,13 @@ export function useEmulatorFrameStream(
setState((current) =>
current.streamIdentity !== streamIdentity || current.frameUrl
? current
- : { ...current, error: translate("auto.components.emulator.pane.use.emulator.frame.stream.f1c0179002", "Stream is not producing frames.") }
+ : {
+ ...current,
+ error: translate(
+ 'auto.components.emulator.pane.use.emulator.frame.stream.f1c0179002',
+ 'Stream is not producing frames.'
+ )
+ }
)
}, FIRST_FRAME_TIMEOUT_MS)
diff --git a/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx b/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx
index b707d8c087a..afa7fbf3dc9 100644
--- a/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx
+++ b/src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.tsx
@@ -83,16 +83,27 @@ export class RecoverableRenderErrorBoundary extends React.Component
- {this.props.title ?? translate("auto.components.error.boundaries.RecoverableRenderErrorBoundary.ab855c11f4", "This part of Orca hit an error.")}
+ {this.props.title ??
+ translate(
+ 'auto.components.error.boundaries.RecoverableRenderErrorBoundary.ab855c11f4',
+ 'This part of Orca hit an error.'
+ )}
{this.props.description ??
- translate("auto.components.error.boundaries.RecoverableRenderErrorBoundary.34a189ae0f", "The rest of the app is still running. Retry this surface or switch away and come back.")}
+ translate(
+ 'auto.components.error.boundaries.RecoverableRenderErrorBoundary.34a189ae0f',
+ 'The rest of the app is still running. Retry this surface or switch away and come back.'
+ )}
- {translate("auto.components.error.boundaries.RecoverableRenderErrorBoundary.55001880db", "Retry")}
+ {translate(
+ 'auto.components.error.boundaries.RecoverableRenderErrorBoundary.55001880db',
+ 'Retry'
+ )}
+
)
}
diff --git a/src/renderer/src/components/feature-interaction-writer-boundaries.test.ts b/src/renderer/src/components/feature-interaction-writer-boundaries.test.ts
new file mode 100644
index 00000000000..4c0603355d3
--- /dev/null
+++ b/src/renderer/src/components/feature-interaction-writer-boundaries.test.ts
@@ -0,0 +1,227 @@
+import { readFileSync } from 'node:fs'
+import { join } from 'node:path'
+import { describe, expect, it } from 'vitest'
+
+const COMPONENT_ROOT = __dirname
+
+function componentSource(relativePath: string): string {
+ return readFileSync(join(COMPONENT_ROOT, relativePath), 'utf8')
+}
+
+function sourceBetween(source: string, startPattern: string, endPattern: string): string {
+ const start = source.indexOf(startPattern)
+ expect(start).toBeGreaterThanOrEqual(0)
+ const end = source.indexOf(endPattern, start + startPattern.length)
+ expect(end).toBeGreaterThan(start)
+ return source.slice(start, end)
+}
+
+function componentBodyBeforeRender(source: string, componentName: string): string {
+ return sourceBetween(source, `function ${componentName}`, '\n return (\n <')
+}
+
+describe('feature interaction writer boundaries', () => {
+ it('keeps Cmd+J feature writers in open/selection handlers, not query or navigation rendering', () => {
+ const source = componentSource('WorktreeJumpPalette.tsx')
+ const renderStart = source.lastIndexOf(' return (')
+ expect(renderStart).toBeGreaterThan(0)
+
+ const handlerSection = source.slice(0, renderStart)
+ const renderSection = source.slice(renderStart)
+
+ const cmdJWriterPattern = /recordFeatureInteraction\('cmd-j/g
+ const allCmdJWriterCount = source.match(cmdJWriterPattern)?.length ?? 0
+ expect(allCmdJWriterCount).toBeGreaterThanOrEqual(6)
+ expect(handlerSection.match(cmdJWriterPattern)?.length ?? 0).toBe(allCmdJWriterCount)
+ expect(renderSection).not.toContain("recordFeatureInteraction('cmd-j")
+ expect(
+ sourceBetween(source, 'const handleQueryChange', 'const cancelFallbackFocusFrames')
+ ).not.toContain("recordFeatureInteraction('cmd-j")
+ })
+
+ it('keeps task-provider writers off filters, tab switches, query edits, refresh, and pagination', () => {
+ const source = componentSource('TaskPage.tsx')
+ const providerWriter = /recordFeatureInteraction\('(github|gitlab|linear)-tasks'\)/
+
+ const passiveSections = [
+ sourceBetween(source, 'const handleRefreshGithubTasks', 'const [newIssueOpen'),
+ sourceBetween(
+ source,
+ 'const handleLoadNextPage',
+ 'useEffect(() => {\n if (!taskResumeApplied)'
+ ),
+ sourceBetween(source, 'const handleApplyTaskSearch', 'const handleSetDefaultTaskPreset'),
+ sourceBetween(source, 'const handleSelectGithubTaskKind', 'const handleResetGithubTaskSearch')
+ ]
+ for (const section of passiveSections) {
+ expect(section).not.toMatch(providerWriter)
+ }
+ })
+
+ it('records GitHub provider-depth for inline item mutation success paths', () => {
+ const source = componentSource('TaskPage.tsx')
+ const githubWriter = "recordFeatureInteraction('github-tasks')"
+ const mutationSections = [
+ sourceBetween(source, 'function GHAssigneesCell', 'const triggerContent ='),
+ sourceBetween(source, 'function PRReviewCell', 'const requestReviewer ='),
+ componentBodyBeforeRender(source, 'PRMergeCell'),
+ sourceBetween(
+ source,
+ 'const handleOpenOrUseGitHubWorkItem',
+ 'const openComposerForGitLabItem'
+ )
+ ]
+
+ for (const section of mutationSections) {
+ expect(section).toContain(githubWriter)
+ }
+ })
+
+ it('suppresses Tasks surface telemetry for in-page provider switches and detail opens', () => {
+ const source = componentSource('TaskPage.tsx')
+ const suppression = 'recordTasksInteraction: false'
+
+ const inPageNavigationSections = [
+ sourceBetween(source, 'const openGitHubDetailPage', 'const patchTaskPageWorkItemRows'),
+ sourceBetween(source, 'const openLinearDetailPage', 'const openRelatedLinearIssue'),
+ sourceBetween(source, 'taskSourceManuallyChangedRef.current = true', 'void updateSettings')
+ ]
+
+ for (const section of inPageNavigationSections) {
+ expect(section).toContain(suppression)
+ }
+ })
+
+ it('records Cmd+J create-workspace as its own destination, not a generic quick action', () => {
+ const source = componentSource('WorktreeJumpPalette.tsx')
+ const section = sourceBetween(source, 'const handleSelectQuickAction', 'const handleSelectItem')
+
+ expect(section).toContain("recordFeatureInteraction('cmd-j-create-workspace')")
+ expect(section).toContain("recordFeatureInteraction('cmd-j-quick-action')")
+ expect(section.indexOf("recordFeatureInteraction('cmd-j-create-workspace')")).toBeLessThan(
+ section.indexOf("recordFeatureInteraction('cmd-j-quick-action')")
+ )
+ expect(
+ sourceBetween(
+ section,
+ "if (action.id === 'create-workspace')",
+ "recordFeatureInteraction('cmd-j-quick-action')"
+ )
+ ).toContain('return')
+ })
+
+ it('records GitLab provider-depth for detail opens, workspace use, and dialog mutations', () => {
+ const taskPageSource = componentSource('TaskPage.tsx')
+ const dialogSource = componentSource('GitLabItemDialog.tsx')
+ const gitlabWriter = "recordFeatureInteraction('gitlab-tasks')"
+
+ expect(
+ sourceBetween(
+ taskPageSource,
+ '{displayedGitLabItems.map((item) => (',
+ '
{
+ const taskPageSource = componentSource('TaskPage.tsx')
+ const drawerSource = componentSource('LinearItemDrawer.tsx')
+ const linearWriter = "recordFeatureInteraction('linear-tasks')"
+
+ const taskPageSections = [
+ sourceBetween(taskPageSource, 'function LinearStateCell', 'return ('),
+ sourceBetween(
+ taskPageSource,
+ 'const handleLinearBoardDrop',
+ 'const toggleLinearDisplayProperty'
+ ),
+ sourceBetween(
+ taskPageSource,
+ 'const handleCreateNewLinearIssue',
+ 'const openComposerForLinearItem'
+ ),
+ sourceBetween(
+ taskPageSource,
+ 'const handleUseLinearItem',
+ 'const handleLinearWorkspaceChange'
+ )
+ ]
+ for (const section of taskPageSections) {
+ expect(section).toContain(linearWriter)
+ }
+
+ const drawerMutationSections = [
+ sourceBetween(drawerSource, 'const handleStateChange', 'const handlePriorityChange'),
+ sourceBetween(drawerSource, 'const handlePriorityChange', 'const handleEstimateChange'),
+ sourceBetween(drawerSource, 'const handleEstimateChange', 'const handleEstimateSubmit'),
+ sourceBetween(drawerSource, 'const handleAssigneeChange', 'const handleLabelToggle'),
+ sourceBetween(drawerSource, 'const handleLabelToggle', 'return ('),
+ sourceBetween(drawerSource, 'const handleSubmit = useCallback(async () => {', 'return (')
+ ]
+ for (const section of drawerMutationSections) {
+ expect(section).toContain(linearWriter)
+ }
+ })
+
+ it('records browser annotation agent handoff only from the prompt-delivered callback', () => {
+ const source = componentSource('browser-pane/BrowserPane.tsx')
+ expect(
+ source.match(/recordFeatureInteraction\('browser-annotations-sent-to-agent'\)/g)
+ ).toHaveLength(1)
+ expect(
+ sourceBetween(
+ source,
+ 'const handleBrowserAnnotationsSentToAgent',
+ 'const handleClearBrowserAnnotations'
+ )
+ ).toContain("recordFeatureInteraction('browser-annotations-sent-to-agent')")
+ expect(
+ sourceBetween(
+ source,
+ 'const handleCopyBrowserAnnotations',
+ 'const handleBrowserAnnotationsSentToAgent'
+ )
+ ).not.toContain("recordFeatureInteraction('browser-annotations-sent-to-agent')")
+ expect(
+ sourceBetween(
+ source,
+ 'const handleClearBrowserAnnotations',
+ 'const handleDeleteBrowserAnnotation'
+ )
+ ).not.toContain("recordFeatureInteraction('browser-annotations-sent-to-agent')")
+ })
+
+ it('records floating workspace hide only from explicit disable or hide actions', () => {
+ const allowedSources = [
+ componentSource('settings/FloatingWorkspacePane.tsx'),
+ componentSource('floating-terminal/FloatingTerminalIconContextMenu.tsx')
+ ].join('\n')
+ const passiveSources = [
+ componentSource('../App.tsx'),
+ componentSource('floating-terminal/FloatingTerminalPanel.tsx')
+ ].join('\n')
+
+ expect(
+ allowedSources.match(/recordFeatureInteraction\('floating-workspace-hidden'\)/g) ?? []
+ ).toHaveLength(2)
+ expect(passiveSources).not.toContain("recordFeatureInteraction('floating-workspace-hidden')")
+ })
+})
diff --git a/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx b/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx
index d97c5a7dafb..5197db2a559 100644
--- a/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx
+++ b/src/renderer/src/components/feature-tips/CliFeatureTipVisual.tsx
@@ -64,7 +64,12 @@ export function CliFeatureTipVisual(): JSX.Element {
- ● {translate("auto.components.feature.tips.CliFeatureTipVisual.22e62f3bab", "Claude Code session started")}
+
●
+ {translate(
+ 'auto.components.feature.tips.CliFeatureTipVisual.22e62f3bab',
+ 'Claude Code session started'
+ )}
+
{CLI_AGENT_COMMANDS.map((command, index) => {
const isVisible = index < visibleCommandCount
const isCurrentLine = isVisible && index === visibleCommandCount - 1
@@ -73,7 +78,9 @@ export function CliFeatureTipVisual(): JSX.Element {
key={command}
className={`truncate ${isVisible ? 'animate-cli-tip-command-line' : 'invisible'}`}
>
- {translate("auto.components.feature.tips.CliFeatureTipVisual.badb4fc342", ">")}
+
+ {translate('auto.components.feature.tips.CliFeatureTipVisual.badb4fc342', '>')}
+
{command}
{isCurrentLine ? (
diff --git a/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx b/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx
index 287d4466608..b9e9f1fac88 100644
--- a/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx
+++ b/src/renderer/src/components/feature-tips/CliSkillSetupTerminal.tsx
@@ -10,9 +10,21 @@ export function CliSkillSetupTerminal(): React.JSX.Element {
const handleCopySkillCommand = async (): Promise => {
try {
await window.api.ui.writeClipboardText(ORCA_CLI_ORCHESTRATION_SKILL_INSTALL_COMMAND)
- toast.success(translate("auto.components.feature.tips.CliSkillSetupTerminal.b8ad063571", "Copied the skill install command."))
+ toast.success(
+ translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.b8ad063571',
+ 'Copied the skill install command.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.feature.tips.CliSkillSetupTerminal.6ff813fc1d", "Failed to copy skill command."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.6ff813fc1d',
+ 'Failed to copy skill command.'
+ )
+ )
}
}
@@ -29,20 +41,36 @@ export function CliSkillSetupTerminal(): React.JSX.Element {
size="icon-sm"
className="shrink-0"
onClick={() => void handleCopySkillCommand()}
- aria-label={translate("auto.components.feature.tips.CliSkillSetupTerminal.5eca672aac", "Copy skill install command")}
+ aria-label={translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.5eca672aac',
+ 'Copy skill install command'
+ )}
>
- {translate("auto.components.feature.tips.CliSkillSetupTerminal.5c3aee22c0", "Copy command")}
+ {translate(
+ 'auto.components.feature.tips.CliSkillSetupTerminal.5c3aee22c0',
+ 'Copy command'
+ )}
+
{renderQuery}
- {!reducedMotion && (phase === 'open' || phase === "typing") ? (
+ {!reducedMotion && (phase === 'open' || phase === 'typing') ? (
) : null}
@@ -224,7 +224,7 @@ export function CmdJPaletteFeatureTipVisual(): JSX.Element {
className={`flex shrink-0 items-center gap-2.5 rounded-lg border border-transparent px-2.5 py-1.5 ${resultEnterClass}`}
>
- {result.status === "done" ? (
+ {result.status === 'done' ? (
) : (
// Why: yellow border spinner mirrors StatusIndicator's
@@ -255,7 +255,11 @@ export function CmdJPaletteFeatureTipVisual(): JSX.Element {
- {translate("auto.components.feature.tips.CmdJPaletteFeatureTipVisual.ab94e16d44", "Create worktree \"{{value0}}\"", { value0: renderQuery.trim() })}
+ {translate(
+ 'auto.components.feature.tips.CmdJPaletteFeatureTipVisual.ab94e16d44',
+ 'Create worktree "{{value0}}"',
+ { value0: renderQuery.trim() }
+ )}
) : null}
diff --git a/src/renderer/src/components/feature-tips/FeatureTipActions.tsx b/src/renderer/src/components/feature-tips/FeatureTipActions.tsx
index 56125568177..985732d2e50 100644
--- a/src/renderer/src/components/feature-tips/FeatureTipActions.tsx
+++ b/src/renderer/src/components/feature-tips/FeatureTipActions.tsx
@@ -30,7 +30,8 @@ export function FeatureTipActions({
<>
{showSkip ? (
- {translate("auto.components.feature.tips.FeatureTipActions.eb04abece8", "Maybe Later")}
+ {translate('auto.components.feature.tips.FeatureTipActions.eb04abece8', 'Maybe Later')}
+
) : null}
- {translate("auto.components.feature.tips.FeatureTipsModal.4795ac2d4a", "Try asking:")}
+
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.4795ac2d4a',
+ 'Try asking:'
+ )}
+
- {translate("auto.components.feature.tips.FeatureTipsModal.55846c7f95", "“Split this PR into two")}{translate("auto.components.feature.tips.FeatureTipsModal.27c567a89c", "worktrees")} {translate("auto.components.feature.tips.FeatureTipsModal.7fc6f02099", "and create PRs for each.”")}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.55846c7f95',
+ '“Split this PR into two'
+ )}
+
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.27c567a89c',
+ 'worktrees'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.7fc6f02099',
+ 'and create PRs for each.”'
+ )}
+
- {translate("auto.components.feature.tips.FeatureTipsModal.864e2db28f", "“When the agent in")}{translate("auto.components.feature.tips.FeatureTipsModal.298301b7a0", "worktree")} {translate("auto.components.feature.tips.FeatureTipsModal.3c6c478462", "X finishes, send it the review task.”")}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.864e2db28f',
+ '“When the agent in'
+ )}
+
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.298301b7a0',
+ 'worktree'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.feature.tips.FeatureTipsModal.3c6c478462',
+ 'X finishes, send it the review task.”'
+ )}
+
{skillTerminalOpen ? : null}
@@ -291,7 +345,8 @@ export default function FeatureTipsModal(): JSX.Element | null {
{skillTerminalOpen ? (
- {translate("auto.components.feature.tips.FeatureTipsModal.c169298e4d", "Done")}
+ {translate('auto.components.feature.tips.FeatureTipsModal.c169298e4d', 'Done')}
+
) : (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.4fa59ca545", "✓ Updated")}{' '}
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.4fa59ca545', '✓ Updated')}{' '}
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.051c97d15a", ".pp-card[data-card=\"starter\"] .pp-cta")}
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.051c97d15a',
+ '.pp-card[data-card="starter"] .pp-cta'
+ )}
+
>
)
},
@@ -152,7 +156,14 @@ const TERM_ENTRIES: readonly { entry: TermEntry; minPhase: Phase }[] = [
{
entry: {
kind: 'ok',
- html: <>{translate("auto.components.feature.wall.BrowserAnimatedVisual.eb88125c6f", "✓ Verified — Try free still works.")}>
+ html: (
+ <>
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.eb88125c6f',
+ '✓ Verified — Try free still works.'
+ )}
+ >
+ )
},
minPhase: 'verified'
}
@@ -496,10 +507,20 @@ export function BrowserAnimatedVisual(props: {
}
- title={translate("auto.components.feature.wall.BrowserAnimatedVisual.04096318ab", "Terminal 1")}
+ title={translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.04096318ab',
+ 'Terminal 1'
+ )}
/>
{browserTabVisible ? (
- } title={translate("auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf", "localhost:3000")} />
+ }
+ title={translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf',
+ 'localhost:3000'
+ )}
+ />
) : null}
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.0a2bd01c02", "New Browser Tab")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.0a2bd01c02',
+ 'New Browser Tab'
+ )}
+
{newBrowserShortcutLabel}
@@ -566,9 +592,22 @@ export function BrowserAnimatedVisual(props: {
) : (
<>
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf", "localhost:3000")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.7da6eed7bf',
+ 'localhost:3000'
+ )}
+
- {showSignup ? translate("auto.components.feature.wall.BrowserAnimatedVisual.f39be6ca14", "/signup") : translate("auto.components.feature.wall.BrowserAnimatedVisual.73bbb46073", "/pricing")}
+ {showSignup
+ ? translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.f39be6ca14',
+ '/signup'
+ )
+ : translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.73bbb46073',
+ '/pricing'
+ )}
>
)}
@@ -612,7 +651,11 @@ export function BrowserAnimatedVisual(props: {
style={{ left: annotateAnchor.left, top: annotateAnchor.top, width: 188 }}
>
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.d8856b604a", "div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta")}
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.d8856b604a',
+ 'div.pricing-grid > div.card.starter:nth-of-type(1) > a.cta'
+ )}
+
{typedChars > 0 ? (
@@ -621,13 +664,21 @@ export function BrowserAnimatedVisual(props: {
>
) : (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.3d2352f94b", "Describe the change…")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.3d2352f94b',
+ 'Describe the change…'
+ )}
+
)}
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.6e4616d039", "Claude")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.6e4616d039',
+ 'Claude'
+ )}
+
{TERM_ENTRIES.map(({ entry, minPhase }, i) => (
@@ -683,7 +739,12 @@ export function BrowserAnimatedVisual(props: {
-
+
)
}
@@ -734,7 +795,10 @@ function TermEntryView(props: { entry: TermEntry }): JSX.Element {
if (entry.kind === 'prompt') {
return (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.f2034c4930", ">")} {entry.text}
+
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.f2034c4930', '>')}
+ {' '}
+ {entry.text}
)
}
@@ -742,7 +806,8 @@ function TermEntryView(props: { entry: TermEntry }): JSX.Element {
return (
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.0ce7c24b4d", "Working…")}
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.0ce7c24b4d', 'Working…')}
+
)
}
if (entry.kind === 'ok') {
@@ -783,20 +848,29 @@ function PricingView(props: {
}): JSX.Element {
return (
<>
- {translate("auto.components.feature.wall.BrowserAnimatedVisual.9e0f530390", "Pricing")}
+
+ {translate('auto.components.feature.wall.BrowserAnimatedVisual.9e0f530390', 'Pricing')}
+
>
)
@@ -805,7 +879,12 @@ function PricingView(props: {
function SignupView(): JSX.Element {
return (
-
{translate("auto.components.feature.wall.BrowserAnimatedVisual.46df009982", "Start your free trial")}
+
+ {translate(
+ 'auto.components.feature.wall.BrowserAnimatedVisual.46df009982',
+ 'Start your free trial'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx b/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx
index b76be56f083..12fd9c5d359 100644
--- a/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx
+++ b/src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx
@@ -26,8 +26,14 @@ export function BrowserUseSkillSetupCard(props: {
const setupPanel = (
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.9cddfe96b2", "Local app")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.9cddfe96b2',
+ 'Local app'
+ )}
+
@@ -100,7 +104,15 @@ export function ComputerUseAnimatedVisual(props: {
: 'border-border bg-muted/40 text-muted-foreground'
)}
>
- {verified ? translate("auto.components.feature.wall.ComputerUseAnimatedVisual.c11dda000b", "Approved") : translate("auto.components.feature.wall.ComputerUseAnimatedVisual.bdd5312213", "Pending")}
+ {verified
+ ? translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.c11dda000b',
+ 'Approved'
+ )
+ : translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.bdd5312213',
+ 'Pending'
+ )}
@@ -131,7 +143,15 @@ export function ComputerUseAnimatedVisual(props: {
phase === 'click' ? 'scale-[0.97]' : null
)}
>
- {clicked ? translate("auto.components.feature.wall.ComputerUseAnimatedVisual.3cc2df3671", "Done") : translate("auto.components.feature.wall.ComputerUseAnimatedVisual.9634d870d1", "Approve")}
+ {clicked
+ ? translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.3cc2df3671',
+ 'Done'
+ )
+ : translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.9634d870d1',
+ 'Approve'
+ )}
@@ -159,7 +179,12 @@ function AgentWorktreeTerminal(props: {
-
{translate("auto.components.feature.wall.ComputerUseAnimatedVisual.94787f01f8", "Claude Code")}
+
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.94787f01f8',
+ 'Claude Code'
+ )}
+
{WORKTREE_LABEL}
@@ -168,10 +193,20 @@ function AgentWorktreeTerminal(props: {
●
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.2adb561b44", "Claude Code session started")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.2adb561b44',
+ 'Claude Code session started'
+ )}
+
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.99a8624bcb", ">")}
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.79445f7512", "approve the note in my app")}
+
+ {translate('auto.components.feature.wall.ComputerUseAnimatedVisual.99a8624bcb', '>')}
+
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.79445f7512',
+ 'approve the note in my app'
+ )}
+
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.1719b28a81", "found \"Approve\"")}[#7]
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.1719b28a81',
+ 'found "Approve"'
+ )}
+ [#7]
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.6804cb356f", "click sent")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.6804cb356f',
+ 'click sent'
+ )}
+
- {translate("auto.components.feature.wall.ComputerUseAnimatedVisual.f27676a92c", "status:")}{translate("auto.components.feature.wall.ComputerUseAnimatedVisual.d8401975b1", "approved")}
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.f27676a92c',
+ 'status:'
+ )}
+
+ {translate(
+ 'auto.components.feature.wall.ComputerUseAnimatedVisual.d8401975b1',
+ 'approved'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx
index 1a240f3dda9..ff02e98bf82 100644
--- a/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/EditorAnimatedVisual.tsx
@@ -604,7 +604,11 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
- {translate("auto.components.feature.wall.EditorAnimatedVisual.cda56c5915", "notes / launch-plan.md")}
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.cda56c5915',
+ 'notes / launch-plan.md'
+ )}
+
{/* Toolbar — visual-only, mirrors RichMarkdownToolbar.tsx button order. */}
@@ -624,7 +628,9 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
- {translate("auto.components.feature.wall.EditorAnimatedVisual.218503f9f3", "autosaved")}
+
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.218503f9f3', 'autosaved')}
+
@@ -635,13 +641,29 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
className="relative overflow-hidden bg-background px-6 pb-5 pt-4"
style={{ minHeight: 280 }}
>
- {translate("auto.components.feature.wall.EditorAnimatedVisual.5a55c00a81", "Launch plan")}
+
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.5a55c00a81', 'Launch plan')}
+
- {translate("auto.components.feature.wall.EditorAnimatedVisual.22ae7b4d9d", "A quick note for the team — pulling together what's left before we ship.")}
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.22ae7b4d9d',
+ "A quick note for the team — pulling together what's left before we ship."
+ )}
+
- {translate("auto.components.feature.wall.EditorAnimatedVisual.95f0c3a46f", "Smoke-test the install flow on a fresh machine.")}
- {translate("auto.components.feature.wall.EditorAnimatedVisual.4426aab46f", "Update the docs index once the new tile lands.")}
+
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.95f0c3a46f',
+ 'Smoke-test the install flow on a fresh machine.'
+ )}
+
+
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.4426aab46f',
+ 'Update the docs index once the new tile lands.'
+ )}
+
{/* Active line where the slash menu fires. The animation imperatively
mutates this node — typing a glyph, swapping role to h1, etc. */}
@@ -663,30 +685,62 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
data-slash-show="all"
className="px-2 pb-1 pt-1.5 text-[9.5px] font-bold uppercase tracking-[0.06em] text-muted-foreground"
>
- {translate("auto.components.feature.wall.EditorAnimatedVisual.1fb29ad710", "Headings")}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.1fb29ad710', 'Headings')}
+
{
rowH1Ref.current = el
}}
iconKey="h1"
- label={translate("auto.components.feature.wall.EditorAnimatedVisual.722170663a", "Heading 1")}
+ label={translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.722170663a',
+ 'Heading 1'
+ )}
shortcut="#"
/>
-
+
- {translate("auto.components.feature.wall.EditorAnimatedVisual.abbdeea15d", "Basic blocks")}
-
-
+ {translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.abbdeea15d',
+ 'Basic blocks'
+ )}
+
+
+
{
rowCodeRef.current = el
}}
iconKey="code"
- label={translate("auto.components.feature.wall.EditorAnimatedVisual.8268b2376b", "Code Block")}
+ label={translate(
+ 'auto.components.feature.wall.EditorAnimatedVisual.8268b2376b',
+ 'Code Block'
+ )}
shortcut="```"
/>
@@ -714,15 +768,25 @@ export function EditorAnimatedVisual(props: { reducedMotion: boolean }): JSX.Ele
WorkbenchAnimatedVisual so the workbench sub-steps share a footer
shape. */}
- {translate("auto.components.feature.wall.EditorAnimatedVisual.3fe42a1da0", "Type")}/ {translate("auto.components.feature.wall.EditorAnimatedVisual.8341391520", "for blocks ·")}{' '}
- {boldShortcutLabel} {translate("auto.components.feature.wall.EditorAnimatedVisual.8521536429", "bold ·")}{' '}
- {italicShortcutLabel} {translate("auto.components.feature.wall.EditorAnimatedVisual.7a763daf2f", "italic")}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.3fe42a1da0', 'Type')}
+ / {' '}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.8341391520', 'for blocks ·')}{' '}
+ {boldShortcutLabel} {' '}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.8521536429', 'bold ·')}{' '}
+ {italicShortcutLabel} {' '}
+ {translate('auto.components.feature.wall.EditorAnimatedVisual.7a763daf2f', 'italic')}
+
{/* Why: the imperative loop adds .slash-active and toggles
[data-cursor-ripple] state via [data-clicking]. We pin those
presentation rules here instead of TS so the React tree stays
declarative. */}
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx b/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx
index 4e64c143921..0004b27ef2c 100644
--- a/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureTourWorkspaceCard.tsx
@@ -26,7 +26,7 @@ export function FeatureTourWorkspaceCard({
)}
>
- {status === "working" ? (
+ {status === 'working' ? (
) : (
@@ -43,14 +43,14 @@ export function FeatureTourWorkspaceCard({
{agents.map((agent, idx) => (
- {agent.state === "working" ? (
+ {agent.state === 'working' ? (
) : (
)}
- {agent.kind === "claude" ? (
+ {agent.kind === 'claude' ? (
- ) : agent.kind === "codex" ? (
+ ) : agent.kind === 'codex' ? (
) : (
diff --git a/src/renderer/src/components/feature-wall/FeatureWallBody.tsx b/src/renderer/src/components/feature-wall/FeatureWallBody.tsx
index 1e4511ec7ba..0eb0314d89e 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallBody.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallBody.tsx
@@ -268,7 +268,8 @@ export function FeatureWallBody(props: {
>
<>
- {translate("auto.components.feature.wall.FeatureWallBody.25ec5356d6", "Setup")}
+ {translate('auto.components.feature.wall.FeatureWallBody.25ec5356d6', 'Setup')}
+
{settingContent}
>
diff --git a/src/renderer/src/components/feature-wall/FeatureWallModal.tsx b/src/renderer/src/components/feature-wall/FeatureWallModal.tsx
index d7b599c0222..215ce457643 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallModal.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallModal.tsx
@@ -35,11 +35,20 @@ export default function FeatureWallModal(): JSX.Element | null {
tabIndex={-1}
>
- {translate("auto.components.feature.wall.FeatureWallModal.3567e147c8", "Get to know Orca")}
+
+ {translate(
+ 'auto.components.feature.wall.FeatureWallModal.3567e147c8',
+ 'Get to know Orca'
+ )}
+
{/* Why: Radix requires a description for the dialog to be a11y-compliant,
but we don't want it visible - the rail and step copy already orient users. */}
- {translate("auto.components.feature.wall.FeatureWallModal.33dca8bbbe", "A short, workflow-by-workflow tour of Orca.")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallModal.33dca8bbbe',
+ 'A short, workflow-by-workflow tour of Orca.'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx b/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx
index cd75b437274..db9580d8dc5 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallPreview.tsx
@@ -67,7 +67,11 @@ export function RelatedFeatures(props: {
return (
- {translate("auto.components.feature.wall.FeatureWallPreview.a666384798", "Also in this workflow")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallPreview.a666384798',
+ 'Also in this workflow'
+ )}
+
{items.map((tile) => (
diff --git a/src/renderer/src/components/feature-wall/FeatureWallRail.tsx b/src/renderer/src/components/feature-wall/FeatureWallRail.tsx
index 339aa3f7f76..e3224d8ed5d 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallRail.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallRail.tsx
@@ -56,7 +56,7 @@ export function FeatureWallRail(props: {
return (
{FEATURE_WALL_WORKFLOWS.map((workflow, index) => {
@@ -114,7 +114,14 @@ export function FeatureWallRail(props: {
? 'border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300'
: 'border-border bg-card text-muted-foreground'
)}
- aria-label={isDone ? translate("auto.components.feature.wall.FeatureWallRail.69ea857689", "Completed") : undefined}
+ aria-label={
+ isDone
+ ? translate(
+ 'auto.components.feature.wall.FeatureWallRail.69ea857689',
+ 'Completed'
+ )
+ : undefined
+ }
>
{isDone ?
: index + 1}
@@ -155,7 +162,14 @@ export function FeatureWallRail(props: {
? 'border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-300'
: 'border-border bg-card text-muted-foreground'
)}
- aria-label={isStepDone ? translate("auto.components.feature.wall.FeatureWallRail.69ea857689", "Completed") : undefined}
+ aria-label={
+ isStepDone
+ ? translate(
+ 'auto.components.feature.wall.FeatureWallRail.69ea857689',
+ 'Completed'
+ )
+ : undefined
+ }
>
{isStepDone ?
: `${label}.`}
diff --git a/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx b/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
index ba36b57d3fc..260f6f4d060 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
@@ -253,7 +253,11 @@ function TaskSourcesAction(): React.JSX.Element {
}}
>
- {translate("auto.components.feature.wall.FeatureWallSetupChecklist.b1f1981c5e", "See tasks")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupChecklist.b1f1981c5e',
+ 'See tasks'
+ )}
+
)
@@ -296,7 +300,10 @@ export function FeatureWallSetupChecklist(
)}
>
- {activeDone ? translate("auto.components.feature.wall.FeatureWallSetupChecklist.13294d3405", "Done") : translate("auto.components.feature.wall.FeatureWallSetupChecklist.0235b268b2", "Not done yet")}
+ {activeDone
+ ? translate(
+ 'auto.components.feature.wall.FeatureWallSetupChecklist.13294d3405',
+ 'Done'
+ )
+ : translate(
+ 'auto.components.feature.wall.FeatureWallSetupChecklist.0235b268b2',
+ 'Not done yet'
+ )}
{activeStep.description}
- {activeStep.id === "split-terminal" ? (
+ {activeStep.id === 'split-terminal' ? (
diff --git a/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx b/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx
index 55c25aed83f..eeb7568ae8b 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.tsx
@@ -46,7 +46,11 @@ export function AddReposAction(): React.JSX.Element {
return (
openModal('add-repo')}>
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.522cce9e33", "Add project")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.522cce9e33',
+ 'Add project'
+ )}
+
)
}
@@ -80,7 +84,11 @@ export function TwoAgentsAction(props: { done: boolean }): React.JSX.Element | n
return (
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77", "Try it out")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77',
+ 'Try it out'
+ )}
+
)
}
@@ -96,8 +104,21 @@ export function SplitTerminalShortcutHint(): React.JSX.Element {
return (
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.971775f639", "Split right with")}{splitRight} {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.29e64f111d", "or down with")}{' '}
- {splitDown} {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.364430eb3d", ", or right-click a pane and choose a split. Close the active pane with")}{closePane} .
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.971775f639',
+ 'Split right with'
+ )}
+ {splitRight} {' '}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.29e64f111d',
+ 'or down with'
+ )}{' '}
+ {splitDown}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.364430eb3d',
+ ', or right-click a pane and choose a split. Close the active pane with'
+ )}
+ {closePane} .
)
@@ -139,7 +160,11 @@ export function WorkspacesAction(props: { done: boolean }): React.JSX.Element |
}}
>
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77", "Try it out")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.f0bbf7da77',
+ 'Try it out'
+ )}
+
)
}
@@ -197,9 +222,19 @@ export function SetupScriptAction(): React.JSX.Element {
}
const updated = await updateRepo(repo.id, { hookSettings: nextHookSettings })
if (updated) {
- toast.success(translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.6299297dac", "Setup script saved"))
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.6299297dac',
+ 'Setup script saved'
+ )
+ )
} else {
- toast.error(translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.a7463915b6", "Failed to save setup script"))
+ toast.error(
+ translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.a7463915b6',
+ 'Failed to save setup script'
+ )
+ )
}
}, [repo, setupScript, updateRepo])
@@ -210,8 +245,14 @@ export function SetupScriptAction(): React.JSX.Element {
value={setupScript}
disabled={!canConfigure}
onChange={(event) => setSetupScript(event.target.value)}
- placeholder={translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.5c5b65044e", "pnpm install")}
- aria-label={translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.88469e926b", "Setup script")}
+ placeholder={translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.5c5b65044e',
+ 'pnpm install'
+ )}
+ aria-label={translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.88469e926b',
+ 'Setup script'
+ )}
className="font-mono text-sm"
/>
void handleSaveSetupScript()}
>
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.14327073cc", "Save")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.14327073cc',
+ 'Save'
+ )}
+
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.00078a6134", "View in settings")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.00078a6134',
+ 'View in settings'
+ )}
+
{!canConfigure ? (
- {translate("auto.components.feature.wall.FeatureWallSetupWorkflowActions.486c2f4d8d", "Add a git project first, then configure the setup script for that repository.")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallSetupWorkflowActions.486c2f4d8d',
+ 'Add a git project first, then configure the setup script for that repository.'
+ )}
+
) : null}
)
diff --git a/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx b/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx
index b0a1b14233e..93646baa2f8 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx
@@ -116,7 +116,11 @@ export function FeatureWallTourPanel(props: {
{props.activeStepCopy?.optional ? (
- {translate("auto.components.feature.wall.FeatureWallTourPanel.af7d622f6f", "Optional")}
+ {translate(
+ 'auto.components.feature.wall.FeatureWallTourPanel.af7d622f6f',
+ 'Optional'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx
index b9f1c60b1f6..c1e0f7ef36f 100644
--- a/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/ReviewAnimatedVisual.tsx
@@ -29,9 +29,9 @@ export function ReviewAnimatedVisual(props: {
transform: `translateX(-50%) scale(${scale})`
}}
>
- {activeStepId === "notes" ? (
+ {activeStepId === 'notes' ? (
- ) : activeStepId === "pr-view" ? (
+ ) : activeStepId === 'pr-view' ? (
) : (
diff --git a/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx
index 4835a78a5a5..24c8399761e 100644
--- a/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/ReviewNotesAnimatedVisual.tsx
@@ -340,10 +340,19 @@ export function ReviewNotesAnimatedVisual(props: { reducedMotion: boolean }): JS
return (
-
{translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.1eee3a397e", "src/server/migrate.ts (diff)")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.1eee3a397e',
+ 'src/server/migrate.ts (diff)'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.5cb213f967", "AI notes")}{' '}
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.5cb213f967',
+ 'AI notes'
+ )}{' '}
0
@@ -372,26 +381,50 @@ export function ReviewNotesAnimatedVisual(props: { reducedMotion: boolean }): JS
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.a7a89d8f94", "Line")}?
+ {translate('auto.components.feature.wall.ReviewNotesAnimatedVisual.a7a89d8f94', 'Line')}
+ ?
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.271ea0cbf3", "Cancel")}
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.271ea0cbf3',
+ 'Cancel'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.ea4e45b71b", "Add note")}
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.ea4e45b71b',
+ 'Add note'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.294aaff104", "Send notes to")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.294aaff104',
+ 'Send notes to'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.09094f25e2", "Claude Code")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.09094f25e2',
+ 'Claude Code'
+ )}
+
- {translate("auto.components.feature.wall.ReviewNotesAnimatedVisual.5dbd27c4c2", "Codex")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewNotesAnimatedVisual.5dbd27c4c2',
+ 'Codex'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx
index 1faa973a240..0b2ef880ffa 100644
--- a/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/ReviewShipAnimatedVisual.tsx
@@ -256,7 +256,12 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.cd8a3a39d7", "3 commits ahead")}
+
{' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.cd8a3a39d7',
+ '3 commits ahead'
+ )}
+
@@ -264,18 +269,30 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
type="button"
className="ravs-sc-sparkle"
data-commit-sparkle
- aria-label={translate("auto.components.feature.wall.ReviewShipAnimatedVisual.d1a7f15876", "Generate commit message with AI")}
+ aria-label={translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.d1a7f15876',
+ 'Generate commit message with AI'
+ )}
>
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.7347fa5839", "Message")}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.7347fa5839',
+ 'Message'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.a079083a6c", "Commit")}
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.a079083a6c',
+ 'Commit'
+ )}
+
@@ -283,9 +300,18 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.e725000cd7", "Changes")}{SHIP_FILES.length}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.e725000cd7',
+ 'Changes'
+ )}
+ {SHIP_FILES.length}
+
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.ea0100dd15',
+ 'View all'
+ )}
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.ea0100dd15", "View all")}
{SHIP_FILES.map((name) => (
@@ -302,42 +328,91 @@ export function ReviewShipAnimatedVisual(props: { reducedMotion: boolean }): JSX
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.c30cd930ff", "Create Pull Request")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.c30cd930ff',
+ 'Create Pull Request'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.ce7d5d3a18", "Base branch")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.ce7d5d3a18',
+ 'Base branch'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.3b9b96d6a6", "main")}
+
{' '}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.3b9b96d6a6',
+ 'main'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.54a093c52d", "Title")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.54a093c52d',
+ 'Title'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.07da9245cc", "Pull request title")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.07da9245cc',
+ 'Pull request title'
+ )}
+
-
{translate("auto.components.feature.wall.ReviewShipAnimatedVisual.3774b80eae", "Description")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.3774b80eae',
+ 'Description'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.bcd5cae3c4", "Pull request description")}
+
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.bcd5cae3c4',
+ 'Pull request description'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.62544e0852", "Cancel")}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.62544e0852',
+ 'Cancel'
+ )}
+
- {translate("auto.components.feature.wall.ReviewShipAnimatedVisual.4d99496b8c", "Create PR")}
+ {translate(
+ 'auto.components.feature.wall.ReviewShipAnimatedVisual.4d99496b8c',
+ 'Create PR'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
index acc8db82670..73d711449be 100644
--- a/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/TasksAnimatedVisual.tsx
@@ -12,7 +12,15 @@ type Issue = {
title: string
}
-const ISSUES: readonly Issue[] = [{ number: 1842, title: translate("auto.components.feature.wall.TasksAnimatedVisual.b13375617e", "Worktree picker truncates names") }]
+const ISSUES: readonly Issue[] = [
+ {
+ number: 1842,
+ title: translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.b13375617e',
+ 'Worktree picker truncates names'
+ )
+ }
+]
type Phase =
| { kind: 'idle' }
@@ -245,7 +253,11 @@ export function TasksAnimatedVisual(props: { reducedMotion: boolean }): JSX.Elem
{!isActive ? (
- {translate("auto.components.feature.wall.TasksAnimatedVisual.4331c4d0f8", "Open")}
+ {translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.4331c4d0f8',
+ 'Open'
+ )}
+
) : (
- {translate("auto.components.feature.wall.TasksAnimatedVisual.b68c92fbdc", "Start workspace")}
+ {translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.b68c92fbdc',
+ 'Start workspace'
+ )}
+
)}
@@ -280,7 +296,17 @@ export function TasksAnimatedVisual(props: { reducedMotion: boolean }): JSX.Elem
) : (
)}
-
{workspaceCreating ? translate("auto.components.feature.wall.TasksAnimatedVisual.61ffda7601", "Creating workspace") : translate("auto.components.feature.wall.TasksAnimatedVisual.fe47c9c9e8", "Workspace ready")}
+
+ {workspaceCreating
+ ? translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.61ffda7601',
+ 'Creating workspace'
+ )
+ : translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.fe47c9c9e8',
+ 'Workspace ready'
+ )}
+
{workspaceIssue ? (
- {translate("auto.components.feature.wall.TasksAnimatedVisual.efba6f77eb", "Reading issue #")}{workspaceIssue.number}…
+ {translate(
+ 'auto.components.feature.wall.TasksAnimatedVisual.efba6f77eb',
+ 'Reading issue #'
+ )}
+ {workspaceIssue.number}…
@@ -319,7 +349,7 @@ export function TasksAnimatedVisual(props: { reducedMotion: boolean }): JSX.Elem
>
- {phase.kind === "pressing" ? : null}
+ {phase.kind === 'pressing' ? : null}
diff --git a/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx b/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx
index 26ec6e25b5f..a5c02d28afc 100644
--- a/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx
+++ b/src/renderer/src/components/feature-wall/WorkbenchAnimatedVisual.tsx
@@ -511,8 +511,21 @@ export function WorkbenchAnimatedVisual(props: {
/* Standalone keyboard hint stays inside the visual so the tour copy can
remain a single subheader line. */
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.0bc9ad0cd1", "Same pane:")}{splitRightShortcutLabel} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.a2b114dad0", "splits right ·")}{' '}
- {splitDownShortcutLabel} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.16877e038d", "splits down")}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.0bc9ad0cd1',
+ 'Same pane:'
+ )}
+ {splitRightShortcutLabel} {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.a2b114dad0',
+ 'splits right ·'
+ )}{' '}
+ {splitDownShortcutLabel} {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.16877e038d',
+ 'splits down'
+ )}
+
)}
)
@@ -526,18 +539,54 @@ function PlaywrightPane(props: {
<>
$
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.4371cc9931", "pnpm playwright test")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.4371cc9931',
+ 'pnpm playwright test'
+ )}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.0b20782e0f", "Running 12 tests using 4 workers")}
-
-
- 1 {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.defe550fe2", "login.spec.ts")} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.3261c6853b", "› can sign in")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.5c5cbd783f", "(1.2s)")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.0b20782e0f',
+ 'Running 12 tests using 4 workers'
+ )}
- 2 {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.623881d72e", "checkout.spec.ts")} {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.944199e54a", "› cart total updates")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.7d9f1d5f7d", "(0.8s)")}
+ 1
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.defe550fe2',
+ 'login.spec.ts'
+ )}
+
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.3261c6853b',
+ '› can sign in'
+ )}
+
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.5c5cbd783f', '(1.2s)')}
+
+
+
+
+ 2
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.623881d72e',
+ 'checkout.spec.ts'
+ )}
+
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.944199e54a',
+ '› cart total updates'
+ )}
+
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.7d9f1d5f7d', '(0.8s)')}
+
@@ -554,30 +603,63 @@ function ClaudeChecklistPane(props: { reducedMotion: boolean }): JSX.Element {
<>
$
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.000106adfe", "claude")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.000106adfe', 'claude')}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a", "Claude Code session started")}
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a',
+ 'Claude Code session started'
+ )}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97", ">")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.c0eb94125e", "review auth edge cases")}
-
- ✓
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.9923847785", "Read")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd", "src/auth/session.ts")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97', '>')}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.c0eb94125e',
+ 'review auth edge cases'
+ )}
✓
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.17cfdc3344", "Grep")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.0d93c298a7", "throw src/auth")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.9923847785', 'Read')}
+
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd',
+ 'src/auth/session.ts'
+ )}
+
+
+
+ ✓
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.17cfdc3344', 'Grep')}
+
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.0d93c298a7',
+ 'throw src/auth'
+ )}
+
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.99f5224f1e", "Edit")}
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd", "src/auth/session.ts")}
+
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.99f5224f1e', 'Edit')}
+
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.b85eab49dd',
+ 'src/auth/session.ts'
+ )}
+
>
)
@@ -666,7 +748,12 @@ function ContextMenu(props: {
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.e370fa8c2b", "Split Terminal Right")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.e370fa8c2b',
+ 'Split Terminal Right'
+ )}
+
{props.splitRightShortcutLabel}
@@ -675,7 +762,12 @@ function ContextMenu(props: {
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.ca2cfbf188", "Split Terminal Down")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.ca2cfbf188',
+ 'Split Terminal Down'
+ )}
+
{props.splitDownShortcutLabel}
@@ -729,7 +821,15 @@ function RightPaneScrollback(props: {
) : (
●
)}
- {props.isCodex ? translate("auto.components.feature.wall.WorkbenchAnimatedVisual.fc84f17fe7", "Codex session started") : translate("auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a", "Claude Code session started")}
+ {props.isCodex
+ ? translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.fc84f17fe7',
+ 'Codex session started'
+ )
+ : translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.431ca9842a',
+ 'Claude Code session started'
+ )}
)
}
@@ -737,7 +837,8 @@ function RightPaneScrollback(props: {
return (
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97", ">")}
+ {translate('auto.components.feature.wall.WorkbenchAnimatedVisual.932c4b3a97', '>')}
+
{line.text}
)
@@ -746,7 +847,12 @@ function RightPaneScrollback(props: {
return (
- {translate("auto.components.feature.wall.WorkbenchAnimatedVisual.633a91e358", "Thinking…")}
+
+ {translate(
+ 'auto.components.feature.wall.WorkbenchAnimatedVisual.633a91e358',
+ 'Thinking…'
+ )}
+
)
}
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
index de119416ab6..0ef1cd631ef 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
@@ -320,10 +320,18 @@ export function OrchestrationPage(props: {
- {translate("auto.components.feature.wall.agents.orchestration.OrchestrationPage.30b509a467", "2 children")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.OrchestrationPage.30b509a467',
+ '2 children'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
index 87d1e84260d..a32fd8c38f9 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
@@ -71,7 +71,15 @@ function ProviderRow(props: {
) : (
)}
- {isAdding ? translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.945865332e", "Signing in") : translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.29d0653961", "Sign in")}
+ {isAdding
+ ? translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.945865332e',
+ 'Signing in'
+ )
+ : translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.29d0653961',
+ 'Sign in'
+ )}
)}
@@ -154,14 +162,25 @@ export function UsageAccountsCard(props: {
if (mountedRef.current) {
await onAccountStateChange?.()
if (mountedRef.current) {
- toast.success(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.9ddeb558f9", "Claude account added."))
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.9ddeb558f9',
+ 'Claude account added.'
+ )
+ )
}
}
} catch (error) {
if (mountedRef.current) {
- toast.error(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.4e71d72912", "Claude sign-in failed."), {
- description: String((error as Error)?.message ?? error)
- })
+ toast.error(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.4e71d72912',
+ 'Claude sign-in failed.'
+ ),
+ {
+ description: String((error as Error)?.message ?? error)
+ }
+ )
}
} finally {
if (mountedRef.current) {
@@ -184,14 +203,25 @@ export function UsageAccountsCard(props: {
if (mountedRef.current) {
await onAccountStateChange?.()
if (mountedRef.current) {
- toast.success(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.c7b90c140b", "Codex account added."))
+ toast.success(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.c7b90c140b',
+ 'Codex account added.'
+ )
+ )
}
}
} catch (error) {
if (mountedRef.current) {
- toast.error(translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.8919321417", "Codex sign-in failed."), {
- description: String((error as Error)?.message ?? error)
- })
+ toast.error(
+ translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.8919321417',
+ 'Codex sign-in failed.'
+ ),
+ {
+ description: String((error as Error)?.message ?? error)
+ }
+ )
}
} finally {
if (mountedRef.current) {
@@ -205,7 +235,10 @@ export function UsageAccountsCard(props: {
}
name="Claude"
- description={translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.d90d2e1f6d", "Track session and weekly usage.")}
+ description={translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.d90d2e1f6d',
+ 'Track session and weekly usage.'
+ )}
connected={claudeConnection.connected}
connectionLabel={claudeConnection.label}
isAdding={claudeAction === 'adding'}
@@ -214,7 +247,10 @@ export function UsageAccountsCard(props: {
}
name="Codex"
- description={translate("auto.components.feature.wall.agents.orchestration.UsageAccountsCard.6986b36708", "Surface rate limits and swap accounts inline.")}
+ description={translate(
+ 'auto.components.feature.wall.agents.orchestration.UsageAccountsCard.6986b36708',
+ 'Surface rate limits and swap accounts inline.'
+ )}
connected={codexConnection.connected}
connectionLabel={codexConnection.label}
isAdding={codexAction === 'adding'}
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx
index 4842403242a..faac3d45669 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/UsagePage.tsx
@@ -98,13 +98,26 @@ function Popover(props: {
-
{translate("auto.components.feature.wall.agents.orchestration.UsagePage.6a4b1d3c38", "Codex")}
-
{translate("auto.components.feature.wall.agents.orchestration.UsagePage.5e45fb1238", "Updated 1m ago")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.6a4b1d3c38',
+ 'Codex'
+ )}
+
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.5e45fb1238',
+ 'Updated 1m ago'
+ )}
+
{sessionResetText}}
/>
{translate("auto.components.feature.wall.agents.orchestration.UsagePage.05ce4ecdd3", "62% left")}}
- metaRight={{translate("auto.components.feature.wall.agents.orchestration.UsagePage.4dce5ca3aa", "Resets in 4d 3h")} }
+ metaLeft={
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.05ce4ecdd3',
+ '62% left'
+ )}
+
+ }
+ metaRight={
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.4dce5ca3aa',
+ 'Resets in 4d 3h'
+ )}
+
+ }
/>
- {translate("auto.components.feature.wall.agents.orchestration.UsagePage.277a9c65a9", "Codex Account")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.277a9c65a9',
+ 'Codex Account'
+ )}
+
- {translate("auto.components.feature.wall.agents.orchestration.UsagePage.be5a165875", "Switch to")}
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.be5a165875',
+ 'Switch to'
+ )}
+
- {translate("auto.components.feature.wall.agents.orchestration.UsagePage.64265cb295", "71% 5h")}
+
+ {translate(
+ 'auto.components.feature.wall.agents.orchestration.UsagePage.64265cb295',
+ '71% 5h'
+ )}
+
diff --git a/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx b/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx
index 4e435a7ef9f..69fb4cd816f 100644
--- a/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx
+++ b/src/renderer/src/components/feature-wall/agents-orchestration/orchestration-cards.tsx
@@ -83,7 +83,7 @@ export function AgentRow(props: {
width: 'var(--feature-wall-agent-status-box, 16px)'
}}
>
- {state === "working" ? (
+ {state === 'working' ? (
) : (
0) {
- return { connected: true, label: translate("auto.components.feature.wall.feature.wall.usage.tracking.00087eecb2", "Connected · {{value0}}", { value0: args.managedAccountCount }) }
+ return {
+ connected: true,
+ label: translate(
+ 'auto.components.feature.wall.feature.wall.usage.tracking.00087eecb2',
+ 'Connected · {{value0}}',
+ { value0: args.managedAccountCount }
+ )
+ }
}
if (hasFeatureWallProviderUsageTracking(args.provider)) {
- return { connected: true, label: translate("auto.components.feature.wall.feature.wall.usage.tracking.cc39a87288", "Connected · System default") }
+ return {
+ connected: true,
+ label: translate(
+ 'auto.components.feature.wall.feature.wall.usage.tracking.cc39a87288',
+ 'Connected · System default'
+ )
+ }
+ }
+ return {
+ connected: false,
+ label: translate(
+ 'auto.components.feature.wall.feature.wall.usage.tracking.b94ec70eda',
+ 'Tracking not set up'
+ )
}
- return { connected: false, label: translate("auto.components.feature.wall.feature.wall.usage.tracking.b94ec70eda", "Tracking not set up") }
}
export function hasFeatureWallUsageTracking(args: {
diff --git a/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx b/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx
index 30833664c4b..babac2445d6 100644
--- a/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx
+++ b/src/renderer/src/components/feature-wall/review-animated-visual-notes-styles.tsx
@@ -7,6 +7,11 @@ import { translate } from '@/i18n/i18n'
// to keep each file under the per-file line-length lint cap.
export function ReviewNotesVisualStyles(): JSX.Element {
return (
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx b/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx
index fc9cef58f90..eab0088113a 100644
--- a/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx
+++ b/src/renderer/src/components/feature-wall/review-animated-visual-pr-view-styles.tsx
@@ -5,6 +5,11 @@ import { translate } from '@/i18n/i18n'
// animation logic stays under the project max-lines lint cap.
export function ReviewPRViewVisualStyles(): JSX.Element {
return (
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx b/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx
index 25e583aee58..4690370c4d8 100644
--- a/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx
+++ b/src/renderer/src/components/feature-wall/review-animated-visual-shared.tsx
@@ -168,7 +168,15 @@ export function ChevDownIcon(): JSX.Element {
export function ClaudeLogo(): JSX.Element {
return (
-
+
+
{translate("auto.components.feature.wall.review.animated.visual.ship.styles.90cdcd2ecc", ".ravs-ship-root { position: absolute; inset: 0; } .ravs-ship-stack { position: absolute; inset: 0; display: grid; grid-template-columns: 232px minmax(0,1fr); gap: 14px; padding: 4px 2px; /* Why: cards size to their content rather than stretch to the parent's full height, so the two cards don't show empty space below their content. */ align-items: start; } /* Source Control mini-sidebar — ahead-count header, commit textarea + split Commit button, then a CHANGES section with file rows. The file rows are the surface the \"reading\" pulse animates over. */ .ravs-sc-card { display: flex; flex-direction: column; background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(24,24,27,0.04); } /* Both card headers share the same fixed height so the SC card and PR dialog align across the top edge regardless of header content. */ .ravs-sc-header, .ravs-pr-head { height: 36px; box-sizing: border-box; } .ravs-sc-header { display: flex; align-items: center; justify-content: space-between; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-sc-ahead { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } .ravs-sc-ahead svg { color: var(--muted-foreground, #71717a); } .ravs-sc-commit-area { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; } .ravs-sc-textarea { position: relative; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); padding: 6px 26px 6px 8px; min-height: 56px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-sc-textarea .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-sc-sparkle { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; transition: color 160ms ease, background 160ms ease; } .ravs-sc-sparkle.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-sc-split { display: flex; align-items: stretch; } /* Why: Commit + Create PR are surrounding chrome — the violet AI affordances are the focal points. Render them as quiet secondary buttons so they don't compete with the sparkle/scan signals. */ .ravs-sc-split .ravs-primary { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 5px 10px; background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); font-size: 11px; font-weight: 500; border-radius: 6px 0 0 6px; border: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } .ravs-sc-split .ravs-chev { display: inline-flex; align-items: center; justify-content: center; width: 22px; background: var(--secondary, #f5f5f5); color: var(--muted-foreground, #71717a); border-radius: 0 6px 6px 0; border: 1px solid var(--border); border-left: 1px solid var(--border); transition: background 240ms ease, border-color 240ms ease, color 240ms ease; } /* Why: when AI has filled the commit message, tint the Commit button green to signal \"ready to commit\". Uses the same success-green family as the PR flash so the two beats rhyme. Mix is intentionally strong (~28%) — at 14% it disappeared next to the violet sparkle and PR flash, so users only saw the PR change color. */ .ravs-sc-split.is-ready .ravs-primary, .ravs-sc-split.is-ready .ravs-chev { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); transition: background 220ms ease, border-color 220ms ease, color 220ms ease; } .ravs-sc-split.is-ready .ravs-chev { border-left-color: rgba(34, 197, 94, 0.55); } .ravs-sc-changes-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-sc-changes-count { color: var(--foreground, #18181b); font-weight: 600; margin-left: 2px; } .ravs-sc-view-all { font-size: 10px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted-foreground, #71717a); } .ravs-sc-files { display: flex; flex-direction: column; padding: 2px 6px 8px; flex: 1; min-height: 0; overflow: hidden; } .ravs-sc-file { display: grid; grid-template-columns: 14px minmax(0,1fr) 12px; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 4px; font-size: 11px; line-height: 1.35; color: var(--foreground, #18181b); position: relative; transition: background 220ms ease; } .ravs-sc-ficon { color: rgb(180 83 9); display: inline-flex; } .ravs-sc-fname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ravs-sc-fmark { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; text-align: right; color: rgb(180 83 9); } .ravs-sc-file.is-reading { background: color-mix(in srgb, rgb(139 92 246) 14%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, rgb(139 92 246) 28%, transparent); } /* PR dialog — matches the .ravs-sc-card chrome (same border, radius, elevation) so the two cards read as one design language. */ .ravs-pr-dialog { background: var(--card, #fff); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 1px 2px rgba(24,24,27,0.04); display: flex; flex-direction: column; min-width: 0; overflow: hidden; } .ravs-pr-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 0 10px; border-bottom: 1px solid var(--border); } .ravs-pr-title-text { font-size: 11px; font-weight: 500; color: var(--foreground, #18181b); } /* Icon-only AI-assist chip — mirrors .ravs-sc-sparkle so the affordance reads identically across both cards. */ .ravs-pr-gen-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border-radius: 4px; color: var(--muted-foreground, #71717a); background: transparent; border: 0; cursor: pointer; transition: color 160ms ease, background 160ms ease; } .ravs-pr-gen-btn:hover { background: rgba(24,24,27,0.06); color: var(--foreground, #18181b); } .ravs-pr-gen-btn.is-scanning { color: rgb(109 40 217); background: color-mix(in srgb, rgb(139 92 246) 18%, transparent); } .ravs-pr-body { display: flex; flex-direction: column; gap: 8px; padding: 10px; } .ravs-pr-field { display: flex; flex-direction: column; gap: 4px; } .ravs-pr-field-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-foreground, #71717a); } .ravs-pr-base { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 6px; font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--foreground, #18181b); background: var(--editor-surface, var(--card)); align-self: flex-start; } .ravs-pr-base svg { color: var(--muted-foreground, #71717a); } .ravs-pr-input { position: relative; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--editor-surface, var(--card)); min-height: 28px; font-size: 12px; line-height: 1.45; color: var(--foreground, #18181b); white-space: pre-wrap; word-break: break-word; overflow: hidden; } .ravs-pr-input.is-body { min-height: 50px; font-size: 11px; line-height: 1.4; } .ravs-pr-input .ravs-placeholder { color: rgba(113,113,122,0.7); } .ravs-pr-footer { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 2px; } .ravs-pr-btn { font-size: 11px; font-weight: 500; padding: 5px 10px; border-radius: 6px; line-height: 1; border: 1px solid transparent; outline: none; } .ravs-pr-btn:focus, .ravs-pr-btn:focus-visible { outline: none; } /* Cancel reads as a quiet ghost button so it doesn't compete with the affirmative Create PR action. */ .ravs-pr-btn.is-outline { background: transparent; color: var(--muted-foreground, #71717a); border-color: transparent; } .ravs-pr-btn.is-outline:hover { background: rgba(24,24,27,0.05); color: var(--foreground, #18181b); } /* Quiet secondary fill — see the .ravs-sc-split note above. The flash ring still uses success-green so the \"PR created\" beat reads. The Create-PR button is slightly larger than Cancel so the affirmative action remains the bigger target. */ .ravs-pr-btn.is-solid { background: var(--secondary, #f5f5f5); color: var(--secondary-foreground, #171717); border-color: var(--border); font-size: 12px; padding: 7px 14px; transition: background 220ms ease, border-color 220ms ease, color 220ms ease, box-shadow 220ms ease; } .ravs-pr-btn.is-solid.is-ready { background: color-mix(in srgb, rgb(34 197 94) 28%, var(--secondary, #f5f5f5)); border-color: rgb(34 197 94); color: rgb(21 128 61); } .ravs-pr-btn.is-solid.is-flash { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.30); } .ravs-cursor { position: absolute; z-index: 40; pointer-events: none; transition: transform 600ms cubic-bezier(.45,.05,.2,1), opacity 200ms ease; transform: translate(-30px, 220px); opacity: 0; } .ravs-cursor.is-visible { opacity: 1; } .ravs-cursor .ravs-ripple { position: absolute; left: -6px; top: -6px; width: 28px; height: 28px; border-radius: 999px; border: 2px solid rgba(24,24,27,0.5); opacity: 0; } .ravs-cursor.is-clicking .ravs-ripple { animation: ravs-ripple 460ms ease-out forwards; } @keyframes ravs-ripple { 0% { transform: scale(0.4); opacity: 0.9; } 100% { transform: scale(1.4); opacity: 0; } } .ravs-caret { display: inline-block; width: 1.5px; height: 1em; background: currentColor; vertical-align: -2px; margin-left: 1px; animation: ravs-caret-blink 1.05s steps(1) infinite; } @keyframes ravs-caret-blink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }")}
+
)
}
diff --git a/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx b/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx
index 20f100cc444..c5c476a39d2 100644
--- a/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx
+++ b/src/renderer/src/components/feature-wall/review-notes-diff-rows.tsx
@@ -82,7 +82,11 @@ export function ReviewDiffRows(): JSX.Element {
- {translate("auto.components.feature.wall.review.notes.diff.rows.f621c734f8", "Note · line")}?
+ {translate(
+ 'auto.components.feature.wall.review.notes.diff.rows.f621c734f8',
+ 'Note · line'
+ )}
+ ?
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
index 302d7037ed1..8947efc01f3 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
@@ -42,13 +42,19 @@ export function FloatingTerminalIconContextMenu({
if (currentLocation === 'floating-button') {
return {
icon:
,
- label: translate("auto.components.floating.terminal.FloatingTerminalIconContextMenu.0ee79e0674", "Move to Status Bar"),
+ label: translate(
+ 'auto.components.floating.terminal.FloatingTerminalIconContextMenu.0ee79e0674',
+ 'Move to Status Bar'
+ ),
location: 'status-bar' as const
}
}
return {
icon:
,
- label: translate("auto.components.floating.terminal.FloatingTerminalIconContextMenu.763f5fa2c1", "Move to Floating Button"),
+ label: translate(
+ 'auto.components.floating.terminal.FloatingTerminalIconContextMenu.763f5fa2c1',
+ 'Move to Floating Button'
+ ),
location: 'floating-button' as const
}
}, [currentLocation])
@@ -105,11 +111,16 @@ export function FloatingTerminalIconContextMenu({
{
+ useAppStore.getState().recordFeatureInteraction('floating-workspace-hidden')
void updateSettings({ floatingTerminalEnabled: false })
}}
>
- {translate("auto.components.floating.terminal.FloatingTerminalIconContextMenu.8e7d775287", "Hide Floating Workspace")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalIconContextMenu.8e7d775287',
+ 'Hide Floating Workspace'
+ )}
+
>
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx
index af9efbac037..e16de1e41ef 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalOrchestrationDialog.tsx
@@ -57,22 +57,52 @@ export function FloatingTerminalOrchestrationDialog({
{/* Why: the panel renders with hideHeader, so the modal owns the title
and status pill — avoiding a duplicate heading inside the modal. */}
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.543f325a14", "Enable orchestration")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.543f325a14',
+ 'Enable orchestration'
+ )}
+
{orchestrationSkillLoading && !orchestrationSkillDetected ? (
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.dfd021ce46", "Checking...")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.dfd021ce46',
+ 'Checking...'
+ )}
+
) : orchestrationSkillDetected ? (
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.630c0ac8c8", "Installed")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.630c0ac8c8',
+ 'Installed'
+ )}
+
) : (
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.05d7aabc20", "Not installed")}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.05d7aabc20',
+ 'Not installed'
+ )}
+
)}
- {translate("auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.6f0aed26b8", "Install the Orca CLI and orchestration skill so agents can coordinate through Orca.")}
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalOrchestrationDialog.6f0aed26b8',
+ 'Install the Orca CLI and orchestration skill so agents can coordinate through Orca.'
+ )}
+
-
{translate("auto.components.floating.terminal.FloatingTerminalToggleButton.bfe7809a70", "{{value0}} floating workspace ({{value1}})", { value0: open ? 'Minimize' : 'Show', value1: shortcutLabel })}
+
+ {translate(
+ 'auto.components.floating.terminal.FloatingTerminalToggleButton.bfe7809a70',
+ '{{value0}} floating workspace ({{value1}})',
+ { value0: open ? 'Minimize' : 'Show', value1: shortcutLabel }
+ )}
+
)
diff --git a/src/renderer/src/components/github-pr-merge-state.ts b/src/renderer/src/components/github-pr-merge-state.ts
index 7c8f90318ba..071e0270550 100644
--- a/src/renderer/src/components/github-pr-merge-state.ts
+++ b/src/renderer/src/components/github-pr-merge-state.ts
@@ -58,58 +58,85 @@ export function presentGitHubPRMergeState(
: item.autoMergeEnabled === true
? {
kind: 'disable' as const,
- label: translate("auto.components.github.pr.merge.state.48d75ae118", "Disable auto-merge"),
- tooltip: translate("auto.components.github.pr.merge.state.62703b1dc4", "GitHub auto-merge is enabled for this pull request")
+ label: translate(
+ 'auto.components.github.pr.merge.state.48d75ae118',
+ 'Disable auto-merge'
+ ),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.62703b1dc4',
+ 'GitHub auto-merge is enabled for this pull request'
+ )
}
: item.mergeQueueRequired === true
? {
kind: 'enable' as const,
- label: translate("auto.components.github.pr.merge.state.b169f943e1", "Merge when ready"),
- tooltip: translate("auto.components.github.pr.merge.state.331ebe1170", "Add this pull request to the GitHub merge queue")
+ label: translate(
+ 'auto.components.github.pr.merge.state.b169f943e1',
+ 'Merge when ready'
+ ),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.331ebe1170',
+ 'Add this pull request to the GitHub merge queue'
+ )
}
: null
if (item.state === 'merged') {
return {
- label: translate("auto.components.github.pr.merge.state.83ecdbb4a6", "Merged"),
+ label: translate('auto.components.github.pr.merge.state.83ecdbb4a6', 'Merged'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.62eb8d39da", "This pull request is already merged"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.62eb8d39da',
+ 'This pull request is already merged'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.state === 'closed') {
return {
- label: translate("auto.components.github.pr.merge.state.4f976d3450", "Closed"),
+ label: translate('auto.components.github.pr.merge.state.4f976d3450', 'Closed'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.820fd21663", "This pull request is closed"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.820fd21663',
+ 'This pull request is closed'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.state === 'draft') {
return {
- label: translate("auto.components.github.pr.merge.state.ec8e2cebaa", "Draft"),
+ label: translate('auto.components.github.pr.merge.state.ec8e2cebaa', 'Draft'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.f03028e055", "This pull request is still a draft"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.f03028e055',
+ 'This pull request is still a draft'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.reviewDecision === 'REVIEW_REQUIRED') {
return {
- label: translate("auto.components.github.pr.merge.state.1f8eb81c0e", "Approval required"),
+ label: translate('auto.components.github.pr.merge.state.1f8eb81c0e', 'Approval required'),
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.a20db875ed", "GitHub requires review approval before this pull request can merge"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.a20db875ed',
+ 'GitHub requires review approval before this pull request can merge'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.reviewDecision === 'CHANGES_REQUESTED') {
return {
- label: translate("auto.components.github.pr.merge.state.c606463dc2", "Changes requested"),
+ label: translate('auto.components.github.pr.merge.state.c606463dc2', 'Changes requested'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.b289646bcd", "GitHub reports requested changes on this pull request"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.b289646bcd',
+ 'GitHub reports requested changes on this pull request'
+ ),
directMergeAvailable: false,
autoMergeAction
}
@@ -118,43 +145,58 @@ export function presentGitHubPRMergeState(
return {
label: item.autoMergeEnabled ? 'Auto-merge on' : 'Merge when ready',
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.35ec24bc43", "This base branch uses GitHub merge queue"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.35ec24bc43',
+ 'This base branch uses GitHub merge queue'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (!hasFullMergeMetadata(item)) {
return {
- label: translate("auto.components.github.pr.merge.state.bd4f27b50e", "Merge"),
+ label: translate('auto.components.github.pr.merge.state.bd4f27b50e', 'Merge'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.09896aad26", "Merge status is unavailable for this PR"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.09896aad26',
+ 'Merge status is unavailable for this PR'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.mergeable === 'CONFLICTING' || item.mergeStateStatus === 'DIRTY') {
return {
- label: translate("auto.components.github.pr.merge.state.7e8bbe3cd7", "Conflicts"),
+ label: translate('auto.components.github.pr.merge.state.7e8bbe3cd7', 'Conflicts'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.b37d45bca9", "GitHub reports merge conflicts"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.b37d45bca9',
+ 'GitHub reports merge conflicts'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.mergeStateStatus === 'BEHIND') {
return {
- label: translate("auto.components.github.pr.merge.state.039c072f94", "Behind"),
+ label: translate('auto.components.github.pr.merge.state.039c072f94', 'Behind'),
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.c614e2660a", "Update the branch before merging"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.c614e2660a',
+ 'Update the branch before merging'
+ ),
directMergeAvailable: false,
autoMergeAction
}
}
if (item.mergeStateStatus === 'BLOCKED') {
return {
- label: translate("auto.components.github.pr.merge.state.bf5e4c6c92", "Blocked"),
+ label: translate('auto.components.github.pr.merge.state.bf5e4c6c92', 'Blocked'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.1766eb46ba", "GitHub reports this pull request is blocked"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.1766eb46ba',
+ 'GitHub reports this pull request is blocked'
+ ),
directMergeAvailable: false,
autoMergeAction
}
@@ -164,15 +206,24 @@ export function presentGitHubPRMergeState(
const checkStatus =
checkState === 'failure'
? {
- label: translate("auto.components.github.pr.merge.state.87fa36ac83", "Checks failed"),
+ label: translate('auto.components.github.pr.merge.state.87fa36ac83', 'Checks failed'),
tone: DANGER_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.1432ecff30", "GitHub says this PR can merge, but some checks failed")
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.1432ecff30',
+ 'GitHub says this PR can merge, but some checks failed'
+ )
}
: checkState === 'pending'
? {
- label: translate("auto.components.github.pr.merge.state.4e2507176b", "Checks pending"),
+ label: translate(
+ 'auto.components.github.pr.merge.state.4e2507176b',
+ 'Checks pending'
+ ),
tone: WARNING_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.9bd983ce8f", "GitHub says this PR can merge, but checks are still running")
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.9bd983ce8f',
+ 'GitHub says this PR can merge, but checks are still running'
+ )
}
: null
return {
@@ -188,9 +239,12 @@ export function presentGitHubPRMergeState(
}
}
return {
- label: translate("auto.components.github.pr.merge.state.f958920f3a", "Checking"),
+ label: translate('auto.components.github.pr.merge.state.f958920f3a', 'Checking'),
tone: MUTED_TONE,
- tooltip: translate("auto.components.github.pr.merge.state.a80132573b", "GitHub is still computing this pull request merge status"),
+ tooltip: translate(
+ 'auto.components.github.pr.merge.state.a80132573b',
+ 'GitHub is still computing this pull request merge status'
+ ),
directMergeAvailable: false,
autoMergeAction
}
diff --git a/src/renderer/src/components/github-project/ColumnResizeHandle.tsx b/src/renderer/src/components/github-project/ColumnResizeHandle.tsx
index bd1f70d27b3..cd7f6c95920 100644
--- a/src/renderer/src/components/github-project/ColumnResizeHandle.tsx
+++ b/src/renderer/src/components/github-project/ColumnResizeHandle.tsx
@@ -75,7 +75,10 @@ export default function ColumnResizeHandle({
ref={handleRef}
role="separator"
aria-orientation="vertical"
- aria-label={translate("auto.components.github.project.ColumnResizeHandle.1304289353", "Resize column")}
+ aria-label={translate(
+ 'auto.components.github.project.ColumnResizeHandle.1304289353',
+ 'Resize column'
+ )}
onMouseDown={(e) => {
if (e.button !== 0) {
return
diff --git a/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx b/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx
index bfc5e3bd4f2..9131094bdc7 100644
--- a/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx
+++ b/src/renderer/src/components/github-project/GhAuthErrorHelp.tsx
@@ -40,12 +40,18 @@ function reloadOrcaRenderer(): void {
function findEnvVarCommand(varName: string): { label: string; command: string } {
if (IS_WINDOWS) {
return {
- label: translate("auto.components.github.project.GhAuthErrorHelp.df636f5886", "Check if it’s set (PowerShell)"),
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.df636f5886',
+ 'Check if it’s set (PowerShell)'
+ ),
command: `Get-ChildItem Env:${varName}`
}
}
return {
- label: translate("auto.components.github.project.GhAuthErrorHelp.ae43542893", "Find where it’s set"),
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.ae43542893',
+ 'Find where it’s set'
+ ),
command: `grep -RIn '${varName}' ~/.zshrc ~/.zshenv ~/.bashrc ~/.bash_profile ~/.profile ~/.config 2>/dev/null`
}
}
@@ -55,11 +61,20 @@ function unsetEnvVarCommand(varName: string): { label: string; command: string }
// Persistent removal at the user scope; the user still needs a fresh
// shell/Orca relaunch for the change to take effect.
return {
- label: translate("auto.components.github.project.GhAuthErrorHelp.fd17b3019f", "Unset (PowerShell, persistent)"),
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.fd17b3019f',
+ 'Unset (PowerShell, persistent)'
+ ),
command: `Remove-Item Env:${varName}; [Environment]::SetEnvironmentVariable('${varName}', $null, 'User')`
}
}
- return { label: translate("auto.components.github.project.GhAuthErrorHelp.891a7d4616", "Unset for this shell"), command: `unset ${varName}` }
+ return {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.891a7d4616',
+ 'Unset for this shell'
+ ),
+ command: `unset ${varName}`
+ }
}
function openExternal(url: string): void {
@@ -72,9 +87,13 @@ function openExternal(url: string): void {
async function copyToClipboard(text: string): Promise
{
try {
await window.api.ui.writeClipboardText(text)
- toast.success(translate("auto.components.github.project.GhAuthErrorHelp.224c9d0ae8", "Copied to clipboard"))
+ toast.success(
+ translate('auto.components.github.project.GhAuthErrorHelp.224c9d0ae8', 'Copied to clipboard')
+ )
} catch {
- toast.error(translate("auto.components.github.project.GhAuthErrorHelp.8a7f6bf5dc", "Failed to copy"))
+ toast.error(
+ translate('auto.components.github.project.GhAuthErrorHelp.8a7f6bf5dc', 'Failed to copy')
+ )
}
}
@@ -100,7 +119,13 @@ function buildRemediation(
return {
summary: errorMessage,
commands: [
- { label: translate("auto.components.github.project.GhAuthErrorHelp.b436c586d1", "Copy command"), command: kind === 'auth_required' ? LOGIN_CMD : REFRESH_CMD }
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.b436c586d1',
+ 'Copy command'
+ ),
+ command: kind === 'auth_required' ? LOGIN_CMD : REFRESH_CMD
+ }
]
}
}
@@ -110,7 +135,15 @@ function buildRemediation(
summary: 'GitHub CLI (`gh`) is not installed or not on PATH.',
detail:
'Orca uses `gh` to talk to GitHub Projects. Install it from cli.github.com, then sign in.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.9c2da6353b", "Copy login command"), command: LOGIN_CMD }],
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.9c2da6353b',
+ 'Copy login command'
+ ),
+ command: LOGIN_CMD
+ }
+ ],
docsUrl: 'https://cli.github.com/'
}
}
@@ -152,7 +185,15 @@ function buildRemediation(
if (kind === 'auth_required' || !active) {
return {
summary: 'You’re not signed in to GitHub via `gh`.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.9c2da6353b", "Copy login command"), command: LOGIN_CMD }]
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.9c2da6353b',
+ 'Copy login command'
+ ),
+ command: LOGIN_CMD
+ }
+ ]
}
}
@@ -166,7 +207,15 @@ function buildRemediation(
)} scope${diag.missingScopes.length === 1 ? '' : 's'} needed for GitHub Projects.`,
detail:
'Run the refresh command in a terminal. It will open a browser to authorize the new scopes, then come back here and reload.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.3fefeebde4", "Copy refresh command"), command: REFRESH_CMD }]
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.3fefeebde4',
+ 'Copy refresh command'
+ ),
+ command: REFRESH_CMD
+ }
+ ]
}
}
@@ -177,7 +226,15 @@ function buildRemediation(
summary: errorMessage,
detail:
'Your token has the required scopes but GitHub still denied access. If the project is in an org with SAML SSO, you must authorize this token for the org under Settings → Developer settings → Personal access tokens → Configure SSO.',
- commands: [{ label: translate("auto.components.github.project.GhAuthErrorHelp.3fefeebde4", "Copy refresh command"), command: REFRESH_CMD }],
+ commands: [
+ {
+ label: translate(
+ 'auto.components.github.project.GhAuthErrorHelp.3fefeebde4',
+ 'Copy refresh command'
+ ),
+ command: REFRESH_CMD
+ }
+ ],
docsUrl:
'https://docs.github.com/en/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on'
}
@@ -233,7 +290,9 @@ export function GhAuthErrorHelp({
onClick={() => openExternal(docsUrl)}
className="inline-flex items-center gap-1 rounded border border-amber-500/30 px-1.5 py-0.5 text-[11px] hover:bg-amber-500/20"
>
- {translate("auto.components.github.project.GhAuthErrorHelp.baa006f9af", "Docs")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.baa006f9af', 'Docs')}
+
) : null}
{/* Why: after running the refresh command in a terminal, users need to
reload the renderer to pick up the new gh token state. */}
@@ -242,7 +301,9 @@ export function GhAuthErrorHelp({
onClick={reloadOrcaRenderer}
className="inline-flex items-center gap-1 rounded border border-amber-500/30 px-1.5 py-0.5 text-[11px] hover:bg-amber-500/20"
>
- {translate("auto.components.github.project.GhAuthErrorHelp.7e800068d8", "Reload")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.7e800068d8', 'Reload')}
+
)
@@ -266,12 +327,16 @@ export function GhAuthErrorHelp({
))}
{docsUrl ? (
openExternal(docsUrl)}>
- {translate("auto.components.github.project.GhAuthErrorHelp.baa006f9af", "Docs")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.baa006f9af', 'Docs')}
+
) : null}
{/* Why: after running the refresh command in a terminal, users need to
reload the renderer to pick up the new gh token state. */}
- {translate("auto.components.github.project.GhAuthErrorHelp.7e800068d8", "Reload")}
+ {' '}
+ {translate('auto.components.github.project.GhAuthErrorHelp.7e800068d8', 'Reload')}
+
)
diff --git a/src/renderer/src/components/github-project/ProjectCell.tsx b/src/renderer/src/components/github-project/ProjectCell.tsx
index afc1ee4d153..0f916be3ae7 100644
--- a/src/renderer/src/components/github-project/ProjectCell.tsx
+++ b/src/renderer/src/components/github-project/ProjectCell.tsx
@@ -112,7 +112,7 @@ export default function ProjectCell({
{
if (next === '') {
onEditField?.(field.id, null)
@@ -130,7 +130,10 @@ export default function ProjectCell({
value={num}
editable={editable && !isRedacted}
numeric
- placeholder={translate("auto.components.github.project.ProjectCell.bb7ebc11e3", "Add number")}
+ placeholder={translate(
+ 'auto.components.github.project.ProjectCell.bb7ebc11e3',
+ 'Add number'
+ )}
onCommit={(next) => {
if (next === '') {
onEditField?.(field.id, null)
@@ -194,7 +197,9 @@ function TitleCell({
return (
- {translate("auto.components.github.project.ProjectCell.af5d8c912a", "Restricted item")}
+
+ {translate('auto.components.github.project.ProjectCell.af5d8c912a', 'Restricted item')}
+
)
}
@@ -203,7 +208,7 @@ function TitleCell({
// already read as issues), so it's omitted.
const content = (
- {row.itemType === "PULL_REQUEST" ? (
+ {row.itemType === 'PULL_REQUEST' ? (
) : null}
{row.content.number != null ? (
@@ -245,10 +250,19 @@ function TypeCell({
}
const meta =
row.itemType === 'PULL_REQUEST'
- ? { Icon: GitPullRequest, label: translate("auto.components.github.project.ProjectCell.d0d0e13a5a", "PR") }
+ ? {
+ Icon: GitPullRequest,
+ label: translate('auto.components.github.project.ProjectCell.d0d0e13a5a', 'PR')
+ }
: row.itemType === 'DRAFT_ISSUE'
- ? { Icon: FileText, label: translate("auto.components.github.project.ProjectCell.6efdc0d920", "Draft") }
- : { Icon: Lock, label: translate("auto.components.github.project.ProjectCell.8d669084f6", "Restricted") }
+ ? {
+ Icon: FileText,
+ label: translate('auto.components.github.project.ProjectCell.6efdc0d920', 'Draft')
+ }
+ : {
+ Icon: Lock,
+ label: translate('auto.components.github.project.ProjectCell.8d669084f6', 'Restricted')
+ }
const { Icon, label } = meta
return (
@@ -325,7 +339,9 @@ function IssueTypeCell({
)
})()
) : (
- {translate("auto.components.github.project.ProjectCell.c5f949e489", "Issue")}
+
+ {translate('auto.components.github.project.ProjectCell.c5f949e489', 'Issue')}
+
)}
)
@@ -339,7 +355,10 @@ function IssueTypeCell({
{trigger}
@@ -347,12 +366,23 @@ function IssueTypeCell({
{!owner || !repo ? (
- {translate("auto.components.github.project.ProjectCell.54cac64427", "Row has no repo slug.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.54cac64427',
+ 'Row has no repo slug.'
+ )}
+
) : loading ? (
- {translate("auto.components.github.project.ProjectCell.2219e945ef", "Loading…")}
+
+ {translate('auto.components.github.project.ProjectCell.2219e945ef', 'Loading…')}
+
) : options.length === 0 ? (
- {translate("auto.components.github.project.ProjectCell.943b3dadc9", "This repo has no Issue Types.")}
+ {translate(
+ 'auto.components.github.project.ProjectCell.943b3dadc9',
+ 'This repo has no Issue Types.'
+ )}
+
) : (
options.map((t) => (
- {translate("auto.components.github.project.ProjectCell.ebde486e3c", "Clear")}
+ {translate('auto.components.github.project.ProjectCell.ebde486e3c', 'Clear')}
+
) : null}
@@ -441,7 +472,11 @@ function SingleSelectCell({
aria-label={field.name}
className="flex h-full w-full cursor-pointer items-center px-1 text-left"
>
- {label ?? }
+ {label ?? (
+
+ )}
@@ -470,7 +505,8 @@ function SingleSelectCell({
setOpen(false)
}}
>
- {translate("auto.components.github.project.ProjectCell.ebde486e3c", "Clear")}
+ {translate('auto.components.github.project.ProjectCell.ebde486e3c', 'Clear')}
+
)
@@ -509,13 +545,18 @@ function IterationCell({
aria-label={field.name}
className="flex h-full w-full cursor-pointer items-center px-1 text-left"
>
- {label ?? }
+ {label ?? (
+
+ )}
{completed.length > 0 ? (
- {translate("auto.components.github.project.ProjectCell.e17bb96881", "Completed")}
+ {translate('auto.components.github.project.ProjectCell.e17bb96881', 'Completed')}
+
) : null}
{completed.map((it) => (
0 ? (
- {translate("auto.components.github.project.ProjectCell.191905e20e", "Current & upcoming")}
+ {translate(
+ 'auto.components.github.project.ProjectCell.191905e20e',
+ 'Current & upcoming'
+ )}
+
) : null}
{active.map((it) => (
- {translate("auto.components.github.project.ProjectCell.ebde486e3c", "Clear")}
+ {translate('auto.components.github.project.ProjectCell.ebde486e3c', 'Clear')}
+
)
@@ -776,19 +822,33 @@ function AssigneesCell({
- {labelContent ?? }
+ {labelContent ?? (
+
+ )}
{!owner || !repo ? (
- {translate("auto.components.github.project.ProjectCell.54cac64427", "Row has no repo slug.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.54cac64427',
+ 'Row has no repo slug.'
+ )}
+
) : metadata.loading ? (
- {translate("auto.components.github.project.ProjectCell.2219e945ef", "Loading…")}
+
+ {translate('auto.components.github.project.ProjectCell.2219e945ef', 'Loading…')}
+
) : (
metadata.data.map((u) => {
const isOn = assignees.some((a) => a.login === u.login)
@@ -852,19 +912,38 @@ function LabelsCell({
- {labelContent ?? }
+ {labelContent ?? (
+
+ )}
{!owner || !repo ? (
- {translate("auto.components.github.project.ProjectCell.54cac64427", "Row has no repo slug.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.54cac64427',
+ 'Row has no repo slug.'
+ )}
+
) : metadata.loading ? (
- {translate("auto.components.github.project.ProjectCell.2219e945ef", "Loading…")}
+
+ {translate('auto.components.github.project.ProjectCell.2219e945ef', 'Loading…')}
+
) : metadata.data.length === 0 ? (
- {translate("auto.components.github.project.ProjectCell.4b5b871da8", "No labels in this repo.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectCell.4b5b871da8',
+ 'No labels in this repo.'
+ )}
+
) : (
metadata.data.map((name) => {
const isOn = labels.some((l) => l.name === name)
diff --git a/src/renderer/src/components/github-project/ProjectGroupHeader.tsx b/src/renderer/src/components/github-project/ProjectGroupHeader.tsx
index 6c0eb1fdda9..c0856cb59a3 100644
--- a/src/renderer/src/components/github-project/ProjectGroupHeader.tsx
+++ b/src/renderer/src/components/github-project/ProjectGroupHeader.tsx
@@ -29,14 +29,18 @@ export default function ProjectGroupHeader({
)}
>
{expanded ? : }
- {group.label || translate("auto.components.github.project.ProjectGroupHeader.244c9e7d06", "All")}
+
+ {group.label ||
+ translate('auto.components.github.project.ProjectGroupHeader.244c9e7d06', 'All')}
+
{group.rows.length}
{dateRange ? {dateRange} : null}
{isCurrent ? (
- {translate("auto.components.github.project.ProjectGroupHeader.82a22d2079", "Current")}
+ {translate('auto.components.github.project.ProjectGroupHeader.82a22d2079', 'Current')}
+
) : null}
)
diff --git a/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx b/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx
index 7a858a8db98..51db853fc1b 100644
--- a/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx
+++ b/src/renderer/src/components/github-project/ProjectItemSlugDialog.tsx
@@ -34,10 +34,20 @@ export default function ProjectItemSlugDialog({
onOpenAutoFocus={(e) => e.preventDefault()}
>
- {translate("auto.components.github.project.ProjectItemSlugDialog.4450efea9c", "GitHub item")}
+
+ {translate(
+ 'auto.components.github.project.ProjectItemSlugDialog.4450efea9c',
+ 'GitHub item'
+ )}
+
- {translate("auto.components.github.project.ProjectItemSlugDialog.e55a5c4e68", "Project row preview.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectItemSlugDialog.e55a5c4e68',
+ 'Project row preview.'
+ )}
+
{projectOrigin ? : null}
diff --git a/src/renderer/src/components/github-project/ProjectPicker.tsx b/src/renderer/src/components/github-project/ProjectPicker.tsx
index ac38e60704e..c77ce48948e 100644
--- a/src/renderer/src/components/github-project/ProjectPicker.tsx
+++ b/src/renderer/src/components/github-project/ProjectPicker.tsx
@@ -304,7 +304,13 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
// a transport-level message so the user can retry or paste again.
if (mountedRef.current) {
setViewList([])
- toast.error(translate("auto.components.github.project.ProjectPicker.44b2c6326b", "Failed to load views: {{value0}}", { value0: err instanceof Error ? err.message : String(err) }))
+ toast.error(
+ translate(
+ 'auto.components.github.project.ProjectPicker.44b2c6326b',
+ 'Failed to load views: {{value0}}',
+ { value0: err instanceof Error ? err.message : String(err) }
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -407,7 +413,10 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
setQuery(e.target.value)}
- placeholder={translate("auto.components.github.project.ProjectPicker.f492e1b539", "Search projects")}
+ placeholder={translate(
+ 'auto.components.github.project.ProjectPicker.f492e1b539',
+ 'Search projects'
+ )}
className="h-8 pl-7 text-xs"
/>
@@ -418,7 +427,12 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
) : null}
{projectSettings.pinned.length > 0 ? (
-
+
{projectSettings.pinned.map((p) => {
const key = `${p.ownerType}:${p.owner}:${p.number}`
const knownGood = projectSettings.lastViewByProject[key]?.viewId != null
@@ -453,7 +467,12 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
) : null}
{projectSettings.recent.length > 0 ? (
-
+
{projectSettings.recent
.filter(
(r) =>
@@ -498,10 +517,27 @@ export default function ProjectPicker({ activeProject, onSelect }: Props): React
})}
) : null}
-
+
{browseLoading ? (
- {translate("auto.components.github.project.ProjectPicker.7b6d39627e", "Loading…")}
+ {' '}
+ {translate(
+ 'auto.components.github.project.ProjectPicker.7b6d39627e',
+ 'Loading…'
+ )}
+
) : null}
{filteredBrowse.map((p) => (
- {translate("auto.components.github.project.ProjectPicker.fce99a24a7", "Add")}
+ {translate('auto.components.github.project.ProjectPicker.fce99a24a7', 'Add')}
+
{pasteError ? (
{pasteError}
@@ -603,13 +643,14 @@ function PickerRow({
className="text-[10px] text-muted-foreground hover:text-foreground"
onClick={onRemovePin}
>
- {translate("auto.components.github.project.ProjectPicker.5009ffc2f3", "Remove pin")}
+ {translate('auto.components.github.project.ProjectPicker.5009ffc2f3', 'Remove pin')}
+
) : null}
{canPin ? (
@@ -639,16 +680,26 @@ function ViewPickStep({
onClick={onBack}
className="text-xs text-muted-foreground hover:text-foreground"
>
- {translate("auto.components.github.project.ProjectPicker.a51b3337ab", "← Back")}
- {translate("auto.components.github.project.ProjectPicker.9bf55fa1e8", "Choose a view")}
+ {translate('auto.components.github.project.ProjectPicker.a51b3337ab', '← Back')}
+
+
+ {translate('auto.components.github.project.ProjectPicker.9bf55fa1e8', 'Choose a view')}
+
{loading ? (
- {translate("auto.components.github.project.ProjectPicker.72a05c04a6", "Loading views…")}
+
{' '}
+ {translate('auto.components.github.project.ProjectPicker.72a05c04a6', 'Loading views…')}
+
) : views.length === 0 ? (
- {translate("auto.components.github.project.ProjectPicker.9b36829267", "No views found.")}
+
+ {translate(
+ 'auto.components.github.project.ProjectPicker.9b36829267',
+ 'No views found.'
+ )}
+
) : (
views.map((v) => {
const supported = v.layout === 'TABLE_LAYOUT'
@@ -665,11 +716,17 @@ function ViewPickStep({
>
{v.name}
- {v.layout === "TABLE_LAYOUT"
- ? translate("auto.components.github.project.ProjectPicker.1a2b8e512e", "Table")
- : v.layout === "BOARD_LAYOUT"
- ? translate("auto.components.github.project.ProjectPicker.d34ef9b554", "Board (unsupported)")
- : translate("auto.components.github.project.ProjectPicker.ab1a2c357d", "Roadmap (unsupported)")}
+ {v.layout === 'TABLE_LAYOUT'
+ ? translate('auto.components.github.project.ProjectPicker.1a2b8e512e', 'Table')
+ : v.layout === 'BOARD_LAYOUT'
+ ? translate(
+ 'auto.components.github.project.ProjectPicker.d34ef9b554',
+ 'Board (unsupported)'
+ )
+ : translate(
+ 'auto.components.github.project.ProjectPicker.ab1a2c357d',
+ 'Roadmap (unsupported)'
+ )}
)
@@ -706,7 +763,11 @@ function PartialFailuresBanner({
{summary}
- {translate("auto.components.github.project.ProjectPicker.96739284c3", "Paste a project URL below to reach missing ones.")}
+ {translate(
+ 'auto.components.github.project.ProjectPicker.96739284c3',
+ 'Paste a project URL below to reach missing ones.'
+ )}
+
diff --git a/src/renderer/src/components/github-project/ProjectRow.tsx b/src/renderer/src/components/github-project/ProjectRow.tsx
index 091e2ff1636..1513f275da9 100644
--- a/src/renderer/src/components/github-project/ProjectRow.tsx
+++ b/src/renderer/src/components/github-project/ProjectRow.tsx
@@ -118,28 +118,38 @@ export default function ProjectRow({
- {translate("auto.components.github.project.ProjectRow.e12be8b4d4", "Open in GitHub")}
+
+ {translate('auto.components.github.project.ProjectRow.e12be8b4d4', 'Open in GitHub')}
+
) : null}
- {!disabled && row.itemType !== "DRAFT_ISSUE" && row.content.number != null ? (
+ {!disabled && row.itemType !== 'DRAFT_ISSUE' && row.content.number != null ? (
- {translate("auto.components.github.project.ProjectRow.75b5d816e3", "Start work")}
+
+ {translate('auto.components.github.project.ProjectRow.75b5d816e3', 'Start work')}
+
) : null}
diff --git a/src/renderer/src/components/github-project/ProjectViewList.tsx b/src/renderer/src/components/github-project/ProjectViewList.tsx
index b24f47404c7..ebaaba0b7c4 100644
--- a/src/renderer/src/components/github-project/ProjectViewList.tsx
+++ b/src/renderer/src/components/github-project/ProjectViewList.tsx
@@ -180,7 +180,11 @@ export default function ProjectViewList({
if (table.rows.length === 0) {
return (
- {translate("auto.components.github.project.ProjectViewList.4f57d2e0b1", "No items match this view's filter.")}
+ {translate(
+ 'auto.components.github.project.ProjectViewList.4f57d2e0b1',
+ "No items match this view's filter."
+ )}
+
)
}
@@ -324,7 +328,11 @@ function ProjectHeaderRow({
'group flex min-w-0 flex-1 items-center gap-1 truncate text-left uppercase tracking-wide hover:text-foreground',
isActive && 'text-foreground'
)}
- aria-label={translate("auto.components.github.project.ProjectViewList.eddfc7a794", "Sort by {{value0}}", { value0: f.name })}
+ aria-label={translate(
+ 'auto.components.github.project.ProjectViewList.eddfc7a794',
+ 'Sort by {{value0}}',
+ { value0: f.name }
+ )}
>
{f.name}
@@ -359,7 +370,8 @@ function ProjectHeaderRow({
- {translate("auto.components.github.project.ProjectViewList.989f81dc2a", "Columns")}
+ {translate('auto.components.github.project.ProjectViewList.989f81dc2a', 'Columns')}
+
{availableFields.map((f) => {
// Why: TITLE is the only column that anchors the row's identity
// and click target — disallow hiding it so users can't end up
diff --git a/src/renderer/src/components/github-project/ProjectViewWrapper.tsx b/src/renderer/src/components/github-project/ProjectViewWrapper.tsx
index bde0fad35f3..d1c6dcd9a2e 100644
--- a/src/renderer/src/components/github-project/ProjectViewWrapper.tsx
+++ b/src/renderer/src/components/github-project/ProjectViewWrapper.tsx
@@ -344,7 +344,12 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
if (parentDroppedToasted.has(currentCacheKey)) {
return
}
- toast.message(translate("auto.components.github.project.ProjectViewWrapper.22df63c393", "Sub-issue data is unavailable for your token."))
+ toast.message(
+ translate(
+ 'auto.components.github.project.ProjectViewWrapper.22df63c393',
+ 'Sub-issue data is unavailable for your token.'
+ )
+ )
setParentDroppedToasted((prev) => {
const next = new Set(prev)
next.add(currentCacheKey)
@@ -675,7 +680,10 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
size="icon"
className="h-7 w-7"
onClick={() => void window.api.shell.openUrl(selectedViewUrl)}
- aria-label={translate("auto.components.github.project.ProjectViewWrapper.fd15491034", "Open view in GitHub")}
+ aria-label={translate(
+ 'auto.components.github.project.ProjectViewWrapper.fd15491034',
+ 'Open view in GitHub'
+ )}
>
@@ -706,8 +714,28 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
}}
disabled={loading}
aria-busy={loading}
- aria-label={loading ? translate("auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5", "Refreshing") : translate("auto.components.github.project.ProjectViewWrapper.71fb69926c", "Refresh")}
- title={loading ? translate("auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5", "Refreshing") : translate("auto.components.github.project.ProjectViewWrapper.71fb69926c", "Refresh")}
+ aria-label={
+ loading
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5',
+ 'Refreshing'
+ )
+ : translate(
+ 'auto.components.github.project.ProjectViewWrapper.71fb69926c',
+ 'Refresh'
+ )
+ }
+ title={
+ loading
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.a8fa0d2bf5',
+ 'Refreshing'
+ )
+ : translate(
+ 'auto.components.github.project.ProjectViewWrapper.71fb69926c',
+ 'Refresh'
+ )
+ }
>
@@ -732,7 +760,11 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
{!activeProject ? (
- {translate("auto.components.github.project.ProjectViewWrapper.512fc171d6", "Choose a project to get started.")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.512fc171d6',
+ 'Choose a project to get started.'
+ )}
+
) : loading && !table ? (
) : error ? (
@@ -809,16 +841,29 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
>
- {translate("auto.components.github.project.ProjectViewWrapper.7037c8f5f1", "Repository not in Orca")}
+
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.7037c8f5f1',
+ 'Repository not in Orca'
+ )}
+
{resolvedMissingRepoDialogs.repoNotInOrca
- ? translate("auto.components.github.project.ProjectViewWrapper.1850fceac8", "{{value0}}/{{value1}} isn't added to Orca. Add it to start work, or open in GitHub.", { value0: resolvedMissingRepoDialogs.repoNotInOrca.owner, value1: resolvedMissingRepoDialogs.repoNotInOrca.repo })
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.1850fceac8',
+ "{{value0}}/{{value1}} isn't added to Orca. Add it to start work, or open in GitHub.",
+ {
+ value0: resolvedMissingRepoDialogs.repoNotInOrca.owner,
+ value1: resolvedMissingRepoDialogs.repoNotInOrca.repo
+ }
+ )
: null}
setRepoNotInOrca(null)}>
- {translate("auto.components.github.project.ProjectViewWrapper.dffa899f36", "Cancel")}
+ {translate('auto.components.github.project.ProjectViewWrapper.dffa899f36', 'Cancel')}
+
{resolvedMissingRepoDialogs.repoNotInOrca?.url ? (
- {translate("auto.components.github.project.ProjectViewWrapper.23b87ba9f7", "Open in GitHub")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.23b87ba9f7',
+ 'Open in GitHub'
+ )}
+
) : null}
{
@@ -842,7 +891,11 @@ export default function ProjectViewWrapper(_props: Props = {} as Props): React.J
await addRepoFromStore()
}}
>
- {translate("auto.components.github.project.ProjectViewWrapper.840c268665", "Add repo")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.840c268665',
+ 'Add repo'
+ )}
+
@@ -937,8 +990,22 @@ function ProjectSearchInput({
apply(value)
}
}}
- placeholder={viewFilter || translate("auto.components.github.project.ProjectViewWrapper.067119985c", "GitHub search, e.g. assignee:@me is:open")}
- title={viewFilter ? translate("auto.components.github.project.ProjectViewWrapper.c5bc7ec007", "View filter: {{value0}}", { value0: viewFilter }) : undefined}
+ placeholder={
+ viewFilter ||
+ translate(
+ 'auto.components.github.project.ProjectViewWrapper.067119985c',
+ 'GitHub search, e.g. assignee:@me is:open'
+ )
+ }
+ title={
+ viewFilter
+ ? translate(
+ 'auto.components.github.project.ProjectViewWrapper.c5bc7ec007',
+ 'View filter: {{value0}}',
+ { value0: viewFilter }
+ )
+ : undefined
+ }
className={cn(
'h-7 rounded-md border-border/50 bg-background pl-8 pr-7 text-[11px]',
dirty && 'border-amber-500/50'
@@ -947,7 +1014,10 @@ function ProjectSearchInput({
{value ? (
e.preventDefault()}
onClick={() => {
setValue('')
@@ -1001,7 +1071,11 @@ function ViewTabStrip({
title={
supported
? v.name
- : translate("auto.components.github.project.ProjectViewWrapper.2edf5e7e77", "{{value0}} — Orca doesn't support {{value1}} project views yet. File a feature request at {{value2}}.", { value0: v.name, value1: layoutLabel, value2: ORCA_FEATURE_REQUEST_URL })
+ : translate(
+ 'auto.components.github.project.ProjectViewWrapper.2edf5e7e77',
+ "{{value0}} — Orca doesn't support {{value1}} project views yet. File a feature request at {{value2}}.",
+ { value0: v.name, value1: layoutLabel, value2: ORCA_FEATURE_REQUEST_URL }
+ )
}
className={cn(
'inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-t-md border-x border-t px-3 py-1.5 text-xs',
@@ -1025,7 +1099,11 @@ function ViewTabStrip({
{tab}
@@ -1034,14 +1112,23 @@ function ViewTabStrip({
- {unsupportedMessage} {translate("auto.components.github.project.ProjectViewWrapper.1bf8c01c8b", "Switch to a Table view to work with this project in Orca.")}
+ {unsupportedMessage}{' '}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.1bf8c01c8b',
+ 'Switch to a Table view to work with this project in Orca.'
+ )}
+
void window.api.shell.openUrl(ORCA_FEATURE_REQUEST_URL)}
>
- {translate("auto.components.github.project.ProjectViewWrapper.4d2a77a119", "File feature request")}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.4d2a77a119',
+ 'File feature request'
+ )}
+
@@ -1071,7 +1158,12 @@ function ErrorState({
error={error as GitHubProjectViewError & { type: 'auth_required' | 'scope_missing' }}
/>
- {translate("auto.components.github.project.ProjectViewWrapper.23b87ba9f7", "Open in GitHub")}
+ {' '}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.23b87ba9f7',
+ 'Open in GitHub'
+ )}
+
)
}
@@ -1090,7 +1182,12 @@ function ErrorState({
{copy}
- {translate("auto.components.github.project.ProjectViewWrapper.23b87ba9f7", "Open in GitHub")}
+ {' '}
+ {translate(
+ 'auto.components.github.project.ProjectViewWrapper.23b87ba9f7',
+ 'Open in GitHub'
+ )}
+
)
@@ -1105,7 +1202,10 @@ function ProjectTableSkeleton(): React.JSX.Element {
return (
diff --git a/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx b/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx
index cd8e870085e..1b9e3a2b028 100644
--- a/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/AssigneesEditor.tsx
@@ -38,12 +38,26 @@ export function AssigneesEditor({
disabled={disabled}
className="rounded-md border border-border/50 bg-muted/30 px-2 py-0.5 text-[11px] hover:bg-muted disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-muted/30"
>
- {translate("auto.components.github.project.slug.dialog.AssigneesEditor.98914e6b36", "Assignees:")}{selected.length === 0 ? translate("auto.components.github.project.slug.dialog.AssigneesEditor.94a4e6e4fa", "none") : selected.join(', ')}
+ {translate(
+ 'auto.components.github.project.slug.dialog.AssigneesEditor.98914e6b36',
+ 'Assignees:'
+ )}
+ {selected.length === 0
+ ? translate(
+ 'auto.components.github.project.slug.dialog.AssigneesEditor.94a4e6e4fa',
+ 'none'
+ )
+ : selected.join(', ')}
{metadata.loading ? (
- {translate("auto.components.github.project.slug.dialog.AssigneesEditor.529fec247b", "Loading…")}
+
+ {translate(
+ 'auto.components.github.project.slug.dialog.AssigneesEditor.529fec247b',
+ 'Loading…'
+ )}
+
) : (
metadata.data.map((u) => {
const isOn = selected.includes(u.login)
diff --git a/src/renderer/src/components/github-project/slug-dialog/Comments.tsx b/src/renderer/src/components/github-project/slug-dialog/Comments.tsx
index fa0cf56e55f..4a9186657e3 100644
--- a/src/renderer/src/components/github-project/slug-dialog/Comments.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/Comments.tsx
@@ -31,7 +31,12 @@ export function CommentsList({
return (
{comments.length === 0 ? (
-
{translate("auto.components.github.project.slug.dialog.Comments.5f104bf855", "No comments yet.")}
+
+ {translate(
+ 'auto.components.github.project.slug.dialog.Comments.5f104bf855',
+ 'No comments yet.'
+ )}
+
) : (
comments.map((c) => (
- {translate("auto.components.github.project.slug.dialog.Comments.8564f58542", "Edit")}
+ {translate('auto.components.github.project.slug.dialog.Comments.8564f58542', 'Edit')}
+
void onDelete()}>
- {translate("auto.components.github.project.slug.dialog.Comments.463d030ae4", "Delete")}
+ {translate('auto.components.github.project.slug.dialog.Comments.463d030ae4', 'Delete')}
+
{editing ? (
@@ -136,9 +143,14 @@ function CommentRow({
void onEdit(draft)
}}
>
- {translate("auto.components.github.project.slug.dialog.Comments.c3e829b4d9", "Save")}
+ {translate('auto.components.github.project.slug.dialog.Comments.c3e829b4d9', 'Save')}
+
setEditing(false)}>
- {translate("auto.components.github.project.slug.dialog.Comments.c0e576e96b", "Cancel")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.Comments.c0e576e96b',
+ 'Cancel'
+ )}
+
) : (
@@ -166,7 +178,10 @@ export function NewCommentForm({
setDraft(e.target.value)}
- placeholder={translate("auto.components.github.project.slug.dialog.Comments.1c95937c8b", "Write a comment…")}
+ placeholder={translate(
+ 'auto.components.github.project.slug.dialog.Comments.1c95937c8b',
+ 'Write a comment…'
+ )}
className="min-h-[80px] w-full rounded border border-border/50 bg-background p-2 text-sm"
/>
@@ -201,7 +216,9 @@ export function NewCommentForm({
}
}}
>
- {translate("auto.components.github.project.slug.dialog.Comments.fd5cccd138", "Comment")}
+ {' '}
+ {translate('auto.components.github.project.slug.dialog.Comments.fd5cccd138', 'Comment')}
+
)
diff --git a/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx b/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx
index 93ba5b11b6d..a2e64a8e968 100644
--- a/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/LabelsEditor.tsx
@@ -29,12 +29,26 @@ export function LabelsEditor({
disabled={disabled}
className="rounded-md border border-border/50 bg-muted/30 px-2 py-0.5 text-[11px] hover:bg-muted disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:bg-muted/30"
>
- {translate("auto.components.github.project.slug.dialog.LabelsEditor.a7b182fcda", "Labels:")}{selected.length === 0 ? translate("auto.components.github.project.slug.dialog.LabelsEditor.1a5366b5be", "none") : selected.join(', ')}
+ {translate(
+ 'auto.components.github.project.slug.dialog.LabelsEditor.a7b182fcda',
+ 'Labels:'
+ )}
+ {selected.length === 0
+ ? translate(
+ 'auto.components.github.project.slug.dialog.LabelsEditor.1a5366b5be',
+ 'none'
+ )
+ : selected.join(', ')}
{metadata.loading ? (
- {translate("auto.components.github.project.slug.dialog.LabelsEditor.34dd57d6c8", "Loading…")}
+
+ {translate(
+ 'auto.components.github.project.slug.dialog.LabelsEditor.34dd57d6c8',
+ 'Loading…'
+ )}
+
) : (
metadata.data.map((name) => {
const isOn = selected.includes(name)
diff --git a/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx b/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx
index 03cb01e86b3..29534bfdccb 100644
--- a/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx
+++ b/src/renderer/src/components/github-project/slug-dialog/SlugDialogBody.tsx
@@ -165,7 +165,11 @@ export function SlugDialogBody({
setEditingTitle(true)
}}
>
- {title || translate("auto.components.github.project.slug.dialog.SlugDialogBody.7c302f8174", "Untitled")}
+ {title ||
+ translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.7c302f8174',
+ 'Untitled'
+ )}
)}
@@ -176,7 +180,10 @@ export function SlugDialogBody({
size="icon"
className="h-7 w-7"
onClick={() => void window.api.shell.openUrl(url)}
- aria-label={translate("auto.components.github.project.slug.dialog.SlugDialogBody.69caf40ae8", "Open in GitHub")}
+ aria-label={translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.69caf40ae8',
+ 'Open in GitHub'
+ )}
>
@@ -186,7 +193,10 @@ export function SlugDialogBody({
size="icon"
className="h-7 w-7"
onClick={onClose}
- aria-label={translate("auto.components.github.project.slug.dialog.SlugDialogBody.ae98897edf", "Close")}
+ aria-label={translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.ae98897edf',
+ 'Close'
+ )}
>
@@ -237,7 +247,12 @@ export function SlugDialogBody({
{loading && !details ? (
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.e4ef8281e9", "Loading…")}
+
{' '}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.e4ef8281e9',
+ 'Loading…'
+ )}
+
) : error ? (
{error}
) : details ? (
@@ -253,9 +268,17 @@ export function SlugDialogBody({
/>
void commitBody()}>
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.e64f6c3eff", "Save")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.e64f6c3eff',
+ 'Save'
+ )}
+
setEditingBody(false)}>
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.a91735d19f", "Cancel")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.a91735d19f',
+ 'Cancel'
+ )}
+
) : body ? (
@@ -280,12 +303,20 @@ export function SlugDialogBody({
setEditingBody(true)
}}
>
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.41169e41fb", "Add a description…")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.41169e41fb',
+ 'Add a description…'
+ )}
+
)}
- {translate("auto.components.github.project.slug.dialog.SlugDialogBody.598ad6a517", "Comments")}
+ {translate(
+ 'auto.components.github.project.slug.dialog.SlugDialogBody.598ad6a517',
+ 'Comments'
+ )}
+
- {translate("auto.components.github.GitHubMarkdownComposer.e3bd59143c", "Insert")}
+ {translate('auto.components.github.GitHubMarkdownComposer.e3bd59143c', 'Insert')}
+
setImageInputOpen(false)}>
- {translate("auto.components.github.GitHubMarkdownComposer.015b4e607d", "Cancel")}
+ {translate('auto.components.github.GitHubMarkdownComposer.015b4e607d', 'Cancel')}
+
) : null}
diff --git a/src/renderer/src/components/github/IssueSourceSelector.tsx b/src/renderer/src/components/github/IssueSourceSelector.tsx
index 54b58b506bb..e428d53f525 100644
--- a/src/renderer/src/components/github/IssueSourceSelector.tsx
+++ b/src/renderer/src/components/github/IssueSourceSelector.tsx
@@ -114,7 +114,10 @@ export default function IssueSourceSelector({
const group = (
- {density === "compact" ? 'U' : translate("auto.components.github.IssueSourceSelector.30b2c9df91", "Upstream")}
+ {density === 'compact'
+ ? 'U'
+ : translate('auto.components.github.IssueSourceSelector.30b2c9df91', 'Upstream')}
- {density === "compact" ? 'O' : translate("auto.components.github.IssueSourceSelector.51d1608920", "Origin")}
+ {density === 'compact'
+ ? 'O'
+ : translate('auto.components.github.IssueSourceSelector.51d1608920', 'Origin')}
)
@@ -171,8 +178,8 @@ export default function IssueSourceSelector({
{group}
- {translate("auto.components.github.IssueSourceSelector.d6aeb2012b", "Showing issues from")}{' '}
- {effective === "upstream" ? upstreamSlug : originSlug}
+ {translate('auto.components.github.IssueSourceSelector.d6aeb2012b', 'Showing issues from')}{' '}
+ {effective === 'upstream' ? upstreamSlug : originSlug}
)
diff --git a/src/renderer/src/components/github/PRFilterDropdowns.tsx b/src/renderer/src/components/github/PRFilterDropdowns.tsx
index 27030b626d5..c5cebb4ffd7 100644
--- a/src/renderer/src/components/github/PRFilterDropdowns.tsx
+++ b/src/renderer/src/components/github/PRFilterDropdowns.tsx
@@ -56,7 +56,11 @@ function ActivePill({
{value}
@@ -177,7 +181,8 @@ export default function PRFilterDropdowns({
)}
>
- {translate("auto.components.github.PRFilterDropdowns.79c54552f7", "Filters")}{activeCount > 0 ? (
+ {translate('auto.components.github.PRFilterDropdowns.79c54552f7', 'Filters')}
+ {activeCount > 0 ? (
{activeCount}
@@ -238,35 +243,39 @@ export default function PRFilterDropdowns({
{statusPillValue ? (
onChange({ state: 'open', draft: false })}
/>
) : null}
{parsed.author ? (
onChange({ author: null })}
/>
) : null}
{parsed.labels.length > 0 ? (
onChange({ labels: [] })}
/>
) : null}
{reviewerActive ? (
onChange({ reviewer: null })}
/>
) : null}
{parsed.assignee ? (
onChange({ assignee: null })}
/>
diff --git a/src/renderer/src/components/github/PRFilterPickers.tsx b/src/renderer/src/components/github/PRFilterPickers.tsx
index 2ddd7706f48..0d5c11af6d8 100644
--- a/src/renderer/src/components/github/PRFilterPickers.tsx
+++ b/src/renderer/src/components/github/PRFilterPickers.tsx
@@ -78,7 +78,9 @@ export function SingleSelectList({
onSelect={() => onSelect(trimmed)}
className="items-center gap-2 px-3 py-1.5 text-xs"
>
- {translate("auto.components.github.PRFilterPickers.2d1f58eda6", "Use")}
+
+ {translate('auto.components.github.PRFilterPickers.2d1f58eda6', 'Use')}
+
{trimmed}
) : null}
@@ -88,7 +90,8 @@ export function SingleSelectList({
onSelect={() => onSelect(null)}
className="gap-2 px-3 py-1.5 text-xs text-muted-foreground"
>
- {translate("auto.components.github.PRFilterPickers.472c12ae03", "Clear")}
+ {translate('auto.components.github.PRFilterPickers.472c12ae03', 'Clear')}
+
) : null}
{filtered.map((opt) => {
const isActive = opt.key === activeValue
@@ -162,7 +165,8 @@ export function MultiSelectList({
onSelect={() => onChange([])}
className="gap-2 px-3 py-1.5 text-xs text-muted-foreground"
>
- {translate("auto.components.github.PRFilterPickers.fdf387297c", "Clear (")}{selected.length})
+ {translate('auto.components.github.PRFilterPickers.fdf387297c', 'Clear (')}
+ {selected.length})
) : null}
{filtered.map((opt) => {
diff --git a/src/renderer/src/components/github/PRFilterSections.tsx b/src/renderer/src/components/github/PRFilterSections.tsx
index 176a631f424..59fc7634120 100644
--- a/src/renderer/src/components/github/PRFilterSections.tsx
+++ b/src/renderer/src/components/github/PRFilterSections.tsx
@@ -49,15 +49,36 @@ function StatusSection({
const states: { key: 'open' | 'closed' | 'merged' | 'all'; label: string }[] =
kind === 'prs'
? [
- { key: 'open', label: translate("auto.components.github.PRFilterSections.d78b60b5c2", "Open") },
- { key: 'closed', label: translate("auto.components.github.PRFilterSections.0fd3249e2e", "Closed") },
- { key: 'merged', label: translate("auto.components.github.PRFilterSections.bd162b7d5a", "Merged") },
- { key: 'all', label: translate("auto.components.github.PRFilterSections.2b2f019091", "Any state") }
+ {
+ key: 'open',
+ label: translate('auto.components.github.PRFilterSections.d78b60b5c2', 'Open')
+ },
+ {
+ key: 'closed',
+ label: translate('auto.components.github.PRFilterSections.0fd3249e2e', 'Closed')
+ },
+ {
+ key: 'merged',
+ label: translate('auto.components.github.PRFilterSections.bd162b7d5a', 'Merged')
+ },
+ {
+ key: 'all',
+ label: translate('auto.components.github.PRFilterSections.2b2f019091', 'Any state')
+ }
]
: [
- { key: 'open', label: translate("auto.components.github.PRFilterSections.d78b60b5c2", "Open") },
- { key: 'closed', label: translate("auto.components.github.PRFilterSections.0fd3249e2e", "Closed") },
- { key: 'all', label: translate("auto.components.github.PRFilterSections.2b2f019091", "Any state") }
+ {
+ key: 'open',
+ label: translate('auto.components.github.PRFilterSections.d78b60b5c2', 'Open')
+ },
+ {
+ key: 'closed',
+ label: translate('auto.components.github.PRFilterSections.0fd3249e2e', 'Closed')
+ },
+ {
+ key: 'all',
+ label: translate('auto.components.github.PRFilterSections.2b2f019091', 'Any state')
+ }
]
return (
@@ -74,11 +95,15 @@ function StatusSection({
)}
>
{s.label}
- {active ? {translate("auto.components.github.PRFilterSections.e0002f1eba", "selected")} : null}
+ {active ? (
+
+ {translate('auto.components.github.PRFilterSections.e0002f1eba', 'selected')}
+
+ ) : null}
)
})}
- {kind !== "prs" ? null : }
+ {kind !== 'prs' ? null : }
)
}
@@ -101,11 +126,15 @@ function DraftToggle({
parsed.draft && 'bg-muted/40 font-medium'
)}
>
- {translate("auto.components.github.PRFilterSections.b930de7194", "Draft only")}
+ {translate('auto.components.github.PRFilterSections.b930de7194', 'Draft only')}
{parsed.draft ? (
- {translate("auto.components.github.PRFilterSections.1e9b5244f2", "on")}
+
+ {translate('auto.components.github.PRFilterSections.1e9b5244f2', 'on')}
+
) : (
- {translate("auto.components.github.PRFilterSections.f0cf6dd591", "off")}
+
+ {translate('auto.components.github.PRFilterSections.f0cf6dd591', 'off')}
+
)}
>
@@ -140,11 +169,19 @@ export function SectionMenu({
}): React.JSX.Element {
const status = statusLabel(parsed)
const rows: { key: SectionKey; label: string; value: string | null }[] = [
- { key: 'status', label: translate("auto.components.github.PRFilterSections.764a0b4ce1", "Status"), value: status || null },
- { key: 'author', label: translate("auto.components.github.PRFilterSections.24754c44ad", "Author"), value: parsed.author },
+ {
+ key: 'status',
+ label: translate('auto.components.github.PRFilterSections.764a0b4ce1', 'Status'),
+ value: status || null
+ },
+ {
+ key: 'author',
+ label: translate('auto.components.github.PRFilterSections.24754c44ad', 'Author'),
+ value: parsed.author
+ },
{
key: 'label',
- label: translate("auto.components.github.PRFilterSections.b1d9fdea08", "Label"),
+ label: translate('auto.components.github.PRFilterSections.b1d9fdea08', 'Label'),
value:
parsed.labels.length === 0
? null
@@ -161,13 +198,18 @@ export function SectionMenu({
}
]
: []),
- { key: 'assignee', label: translate("auto.components.github.PRFilterSections.ea3416d646", "Assignee"), value: parsed.assignee }
+ {
+ key: 'assignee',
+ label: translate('auto.components.github.PRFilterSections.ea3416d646', 'Assignee'),
+ value: parsed.assignee
+ }
]
const subject = kind === 'prs' ? 'pull requests' : 'issues'
return (
- {translate("auto.components.github.PRFilterSections.8177eda37e", "Filter")}{subject}
+ {translate('auto.components.github.PRFilterSections.8177eda37e', 'Filter')}
+ {subject}
{rows.map((row) => (
- {translate("auto.components.github.PRFilterSections.30ebb6ca44", "Clear all filters")}
+ {translate('auto.components.github.PRFilterSections.30ebb6ca44', 'Clear all filters')}
+
>
) : null}
@@ -237,48 +280,49 @@ export function SectionDetail({
className="flex w-full items-center gap-1 border-b border-border px-3 py-1.5 text-[11px] text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
>
- {translate("auto.components.github.PRFilterSections.b69fa4fa20", "Back")}
- {section === "status" ? (
+ {translate('auto.components.github.PRFilterSections.b69fa4fa20', 'Back')}
+
+ {section === 'status' ? (
) : null}
- {section === "author" ? (
+ {section === 'author' ? (
}
onSelect={(value) => onSelect({ author: value })}
/>
) : null}
- {section === "assignee" ? (
+ {section === 'assignee' ? (
}
onSelect={(value) => onSelect({ assignee: value })}
/>
) : null}
- {section === "label" ? (
+ {section === 'label' ? (
onSelect({ labels: next })}
/>
) : null}
- {section === "reviewer" ? (
+ {section === 'reviewer' ? (
<>
- {translate("auto.components.github.PRFilterSections.94b42b0edf", "Review requested")}
+ {translate('auto.components.github.PRFilterSections.94b42b0edf', 'Review requested')}
+
setReviewerMode('reviewed-by')}
@@ -302,7 +347,8 @@ export function SectionDetail({
: 'text-muted-foreground hover:bg-muted/50'
)}
>
- {translate("auto.components.github.PRFilterSections.0103e1cb18", "Reviewed by")}
+ {translate('auto.components.github.PRFilterSections.0103e1cb18', 'Reviewed by')}
+
}
onSelect={(login) =>
diff --git a/src/renderer/src/components/github/github-rate-limit-display.tsx b/src/renderer/src/components/github/github-rate-limit-display.tsx
index c9f1cf6f5f3..4321aeeec04 100644
--- a/src/renderer/src/components/github/github-rate-limit-display.tsx
+++ b/src/renderer/src/components/github/github-rate-limit-display.tsx
@@ -18,9 +18,30 @@ type BucketMeta = {
}
const BUCKETS: BucketMeta[] = [
- { key: 'core', label: translate("auto.components.github.github.rate.limit.display.bb227706a6", "REST"), description: translate("auto.components.github.github.rate.limit.display.c392c749a6", "REST API") },
- { key: 'search', label: translate("auto.components.github.github.rate.limit.display.c377a4f06a", "Search"), description: translate("auto.components.github.github.rate.limit.display.1f2f28a4de", "Search API") },
- { key: 'graphql', label: translate("auto.components.github.github.rate.limit.display.1daf0f22a9", "GraphQL"), description: translate("auto.components.github.github.rate.limit.display.01f7323e58", "GraphQL API") }
+ {
+ key: 'core',
+ label: translate('auto.components.github.github.rate.limit.display.bb227706a6', 'REST'),
+ description: translate(
+ 'auto.components.github.github.rate.limit.display.c392c749a6',
+ 'REST API'
+ )
+ },
+ {
+ key: 'search',
+ label: translate('auto.components.github.github.rate.limit.display.c377a4f06a', 'Search'),
+ description: translate(
+ 'auto.components.github.github.rate.limit.display.1f2f28a4de',
+ 'Search API'
+ )
+ },
+ {
+ key: 'graphql',
+ label: translate('auto.components.github.github.rate.limit.display.1daf0f22a9', 'GraphQL'),
+ description: translate(
+ 'auto.components.github.github.rate.limit.display.01f7323e58',
+ 'GraphQL API'
+ )
+ }
]
export function formatGitHubRateLimitReset(resetAt: number): string {
@@ -127,7 +148,14 @@ function GitHubRateLimitRows({
tone === 'warn' && 'text-amber-700 dark:text-amber-300'
)}
>
- {v.remaining} {translate("auto.components.github.github.rate.limit.display.f42790d150", "of")}{v.limit} {translate("auto.components.github.github.rate.limit.display.6da1858354", "left · resets in")}{formatGitHubRateLimitReset(v.resetAt)}
+ {v.remaining}{' '}
+ {translate('auto.components.github.github.rate.limit.display.f42790d150', 'of')}
+ {v.limit}{' '}
+ {translate(
+ 'auto.components.github.github.rate.limit.display.6da1858354',
+ 'left · resets in'
+ )}
+ {formatGitHubRateLimitReset(v.resetAt)}
)
@@ -145,26 +173,47 @@ export function GitHubRateLimitPanel({ className }: { className?: string }): Rea
- {translate("auto.components.github.github.rate.limit.display.58c5f88216", "GitHub API Budget")}
+ {translate(
+ 'auto.components.github.github.rate.limit.display.58c5f88216',
+ 'GitHub API Budget'
+ )}
+
- {translate("auto.components.github.github.rate.limit.display.d5e5de9070", "Orca uses REST, Search, and GraphQL through the GitHub CLI.")}
+ {translate(
+ 'auto.components.github.github.rate.limit.display.d5e5de9070',
+ 'Orca uses REST, Search, and GraphQL through the GitHub CLI.'
+ )}
+
void refresh(true)}
disabled={isFetching}
className="inline-flex size-7 items-center justify-center rounded-md border border-border bg-secondary text-secondary-foreground transition hover:bg-accent disabled:opacity-50"
- aria-label={translate("auto.components.github.github.rate.limit.display.d12d3d6f33", "Refresh GitHub API budget")}
+ aria-label={translate(
+ 'auto.components.github.github.rate.limit.display.d12d3d6f33',
+ 'Refresh GitHub API budget'
+ )}
>
{hasError ? (
- {translate("auto.components.github.github.rate.limit.display.34973d4695", "GitHub API budget is unavailable.")}
+
+ {translate(
+ 'auto.components.github.github.rate.limit.display.34973d4695',
+ 'GitHub API budget is unavailable.'
+ )}
+
) : snapshot ? (
) : (
- {translate("auto.components.github.github.rate.limit.display.5509443543", "Loading GitHub API budget…")}
+
+ {translate(
+ 'auto.components.github.github.rate.limit.display.5509443543',
+ 'Loading GitHub API budget…'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx b/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx
index be12248d469..e477146fd1c 100644
--- a/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx
+++ b/src/renderer/src/components/gitlab/gitlab-rate-limit-display.tsx
@@ -109,14 +109,20 @@ function GitLabRateLimitRows({
if (!rest) {
return (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.953f7c6062", "This GitLab host did not return rate-limit headers.")}
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.953f7c6062',
+ 'This GitLab host did not return rate-limit headers.'
+ )}
+
)
}
const tone = toneForGitLabBucket(rest.remaining, rest.limit)
return (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.0a891e8935", "REST API")}
+
+ {translate('auto.components.gitlab.gitlab.rate.limit.display.0a891e8935', 'REST API')}
+
- {rest.remaining} {translate("auto.components.gitlab.gitlab.rate.limit.display.ea8ad0bae8", "of")}{rest.limit} {translate("auto.components.gitlab.gitlab.rate.limit.display.3e2c982cfa", "left, resets in")}{' '}
+ {rest.remaining}{' '}
+ {translate('auto.components.gitlab.gitlab.rate.limit.display.ea8ad0bae8', 'of')}
+ {rest.limit}{' '}
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.3e2c982cfa',
+ 'left, resets in'
+ )}{' '}
{formatGitLabRateLimitReset(rest.resetAt)}
@@ -141,8 +153,17 @@ export function GitLabRateLimitPanel({ className }: { className?: string }): Rea
- {translate("auto.components.gitlab.gitlab.rate.limit.display.14e144f7a7", "GitLab API Budget")}
-
{translate("auto.components.gitlab.gitlab.rate.limit.display.2f9c16d6c3", "Orca uses REST through the GitLab CLI.")}
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.14e144f7a7',
+ 'GitLab API Budget'
+ )}
+
+
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.2f9c16d6c3',
+ 'Orca uses REST through the GitLab CLI.'
+ )}
+
void refresh(true)}
disabled={isFetching}
- aria-label={translate("auto.components.gitlab.gitlab.rate.limit.display.a2f68645ac", "Refresh GitLab API budget")}
+ aria-label={translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.a2f68645ac',
+ 'Refresh GitLab API budget'
+ )}
>
{hasError ? (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.a2d3d1fdde", "GitLab API budget is unavailable.")}
+
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.a2d3d1fdde',
+ 'GitLab API budget is unavailable.'
+ )}
+
) : snapshot ? (
) : (
- {translate("auto.components.gitlab.gitlab.rate.limit.display.ebc0e8ecf1", "Loading GitLab API budget...")}
+
+ {translate(
+ 'auto.components.gitlab.gitlab.rate.limit.display.ebc0e8ecf1',
+ 'Loading GitLab API budget...'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/linear-api-key-dialog.tsx b/src/renderer/src/components/linear-api-key-dialog.tsx
index f884810c1fe..b9e94ba3bd0 100644
--- a/src/renderer/src/components/linear-api-key-dialog.tsx
+++ b/src/renderer/src/components/linear-api-key-dialog.tsx
@@ -139,12 +139,16 @@ export function LinearApiKeyDialog({
- {translate("auto.components.linear.api.key.dialog.7d498f653c", "Personal API key")}
+ {translate('auto.components.linear.api.key.dialog.7d498f653c', 'Personal API key')}
+
{
const nextDraft = event.target.value
@@ -166,15 +170,29 @@ export function LinearApiKeyDialog({
) : null}
- {translate("auto.components.linear.api.key.dialog.af52a6227f", "Create a Personal API key from Account > Security & Access.")}{' '}
+ {translate(
+ 'auto.components.linear.api.key.dialog.af52a6227f',
+ 'Create a Personal API key from Account > Security & Access.'
+ )}{' '}
{!workspace
- ? translate("auto.components.linear.api.key.dialog.c9889a09f8", "Use Linear to choose the intended workspace before creating the key.")
+ ? translate(
+ 'auto.components.linear.api.key.dialog.c9889a09f8',
+ 'Use Linear to choose the intended workspace before creating the key.'
+ )
: null}
- {translate("auto.components.linear.api.key.dialog.d56d3629f4", "Prefer full access when Orca should show every team the account can access in that workspace. Restricted keys only expose permitted teams, and private teams require the key owner to have access.")}
+ {translate(
+ 'auto.components.linear.api.key.dialog.d56d3629f4',
+ 'Prefer full access when Orca should show every team the account can access in that workspace. Restricted keys only expose permitted teams, and private teams require the key owner to have access.'
+ )}
+
- {translate("auto.components.linear.api.key.dialog.e3100b36b9", "If member API keys are blocked, ask a workspace admin to allow them from workspace API settings.")}
+ {translate(
+ 'auto.components.linear.api.key.dialog.e3100b36b9',
+ 'If member API keys are blocked, ask a workspace admin to allow them from workspace API settings.'
+ )}
+
window.api.shell.openUrl(personalKeyUrl)}
>
- {translate("auto.components.linear.api.key.dialog.dc7ccb0f7c", "Personal API keys")}
+ {translate('auto.components.linear.api.key.dialog.dc7ccb0f7c', 'Personal API keys')}
+
|
window.api.shell.openUrl(workspaceApiUrl)}
>
- {translate("auto.components.linear.api.key.dialog.e603ee9156", "Workspace API settings")}
+ {translate(
+ 'auto.components.linear.api.key.dialog.e603ee9156',
+ 'Workspace API settings'
+ )}
+
@@ -204,15 +227,17 @@ export function LinearApiKeyDialog({
onClick={() => onOpenChange(false)}
disabled={connectState === 'connecting'}
>
- {translate("auto.components.linear.api.key.dialog.f8f704a019", "Cancel")}
+ {translate('auto.components.linear.api.key.dialog.f8f704a019', 'Cancel')}
+
void handleConnect()}
disabled={!apiKeyDraft.trim() || connectState === 'connecting'}
>
- {connectState === "connecting" ? (
+ {connectState === 'connecting' ? (
<>
- {translate("auto.components.linear.api.key.dialog.834a52c084", "Verifying...")}>
+ {translate('auto.components.linear.api.key.dialog.834a52c084', 'Verifying...')}
+ >
) : (
submitLabel
)}
diff --git a/src/renderer/src/components/linear-priority-icon.tsx b/src/renderer/src/components/linear-priority-icon.tsx
index 70cb9f2aabe..ae9ebbb16a8 100644
--- a/src/renderer/src/components/linear-priority-icon.tsx
+++ b/src/renderer/src/components/linear-priority-icon.tsx
@@ -53,7 +53,10 @@ export function LinearPriorityIcon({
title={label}
>
!
- {translate("auto.components.linear.priority.icon.c43d3e065b", "Priority:")}{label}
+
+ {translate('auto.components.linear.priority.icon.c43d3e065b', 'Priority:')}
+ {label}
+
)
}
@@ -68,7 +71,10 @@ export function LinearPriorityIcon({
aria-hidden="true"
className="size-3 rounded-full border border-muted-foreground/55"
/>
- {translate("auto.components.linear.priority.icon.c43d3e065b", "Priority:")}{label}
+
+ {translate('auto.components.linear.priority.icon.c43d3e065b', 'Priority:')}
+ {label}
+
)
}
@@ -103,7 +109,10 @@ export function LinearPriorityIcon({
)
})}
- {translate("auto.components.linear.priority.icon.c43d3e065b", "Priority:")}{label}
+
+ {translate('auto.components.linear.priority.icon.c43d3e065b', 'Priority:')}
+ {label}
+
)
}
diff --git a/src/renderer/src/components/linear-project-view-surfaces.tsx b/src/renderer/src/components/linear-project-view-surfaces.tsx
index d070026f1d9..58970a8215a 100644
--- a/src/renderer/src/components/linear-project-view-surfaces.tsx
+++ b/src/renderer/src/components/linear-project-view-surfaces.tsx
@@ -192,8 +192,16 @@ export function LinearCollectionNotice({
{onLoadMore ? null : (
- {translate("auto.components.linear.project.view.surfaces.06b887d622", "Showing first")} {count} {label}
- {translate("auto.components.linear.project.view.surfaces.98730088a6", ". Search or open Linear for the full set.")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.06b887d622',
+ 'Showing first'
+ )}{' '}
+ {count} {label}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.98730088a6',
+ '. Search or open Linear for the full set.'
+ )}
+
)}
{onLoadMore ? (
- {translate("auto.components.linear.project.view.surfaces.93e1f6bfca", "Loading")}>
+ {translate('auto.components.linear.project.view.surfaces.93e1f6bfca', 'Loading')}
+ >
) : (
<>
{loadMoreLabel}
@@ -258,10 +267,26 @@ export function LinearProjectTable({
return (
- {hasError ? translate("auto.components.linear.project.view.surfaces.c9b6e9f90d", "Unable to load Linear projects") : translate("auto.components.linear.project.view.surfaces.a2f31c4cd6", "No Linear projects found")}
+ {hasError
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.c9b6e9f90d',
+ 'Unable to load Linear projects'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.a2f31c4cd6',
+ 'No Linear projects found'
+ )}
- {hasError ? translate("auto.components.linear.project.view.surfaces.f4c79cff5f", "Review the workspace error below, then refresh.") : translate("auto.components.linear.project.view.surfaces.30402d2c6e", "Try search or refresh.")}
+ {hasError
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.f4c79cff5f',
+ 'Review the workspace error below, then refresh.'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.30402d2c6e',
+ 'Try search or refresh.'
+ )}
)
@@ -317,21 +342,23 @@ export function LinearProjectTable({
- {textFromUnknown(projectLike.health) ?? translate("auto.components.linear.project.view.surfaces.8bbecb2510", "None")}
+ {textFromUnknown(projectLike.health) ??
+ translate('auto.components.linear.project.view.surfaces.8bbecb2510', 'None')}
{priorityLabel(projectLike.priority, projectLike.priorityLabel)}
- {textFromUnknown(projectLike.lead) ?? translate("auto.components.linear.project.view.surfaces.df4bd63c1d", "Unassigned")}
+ {textFromUnknown(projectLike.lead) ??
+ translate('auto.components.linear.project.view.surfaces.df4bd63c1d', 'Unassigned')}
{dateLabel(project.targetDate)}
- {typeof project.issueCount === "number"
+ {typeof project.issueCount === 'number'
? project.issueCount
- : typeof project.scope === "number"
+ : typeof project.scope === 'number'
? project.scope
: progress !== null
? `${progress}%`
@@ -348,13 +375,18 @@ export function LinearProjectTable({
event.stopPropagation()
onUseProjectIssues(project)
}}
- aria-label={translate("auto.components.linear.project.view.surfaces.7616c986c6", "Open {{value0}} issues", { value0: project.name })}
+ aria-label={translate(
+ 'auto.components.linear.project.view.surfaces.7616c986c6',
+ 'Open {{value0}} issues',
+ { value0: project.name }
+ )}
>
- {translate("auto.components.linear.project.view.surfaces.ee3d2caabd", "Issues")}
+ {translate('auto.components.linear.project.view.surfaces.ee3d2caabd', 'Issues')}
+
) : null}
@@ -366,13 +398,21 @@ export function LinearProjectTable({
event.stopPropagation()
onOpenProject(project)
}}
- aria-label={translate("auto.components.linear.project.view.surfaces.7616c986c6", "Open {{value0}} in Linear", { value0: project.name })}
+ aria-label={translate(
+ 'auto.components.linear.project.view.surfaces.7616c986c6',
+ 'Open {{value0}} in Linear',
+ { value0: project.name }
+ )}
>
- {translate("auto.components.linear.project.view.surfaces.aac9a4afc6", "Open in Linear")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.aac9a4afc6',
+ 'Open in Linear'
+ )}
+
@@ -415,12 +455,26 @@ export function LinearCustomViewTable({
return (
- {hasError ? translate("auto.components.linear.project.view.surfaces.c0a50f96a4", "Unable to load views") : translate("auto.components.linear.project.view.surfaces.ef90b21366", "No views found")}
+ {hasError
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.c0a50f96a4',
+ 'Unable to load views'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.ef90b21366',
+ 'No views found'
+ )}
{hasError
- ? translate("auto.components.linear.project.view.surfaces.f4c79cff5f", "Review the workspace error below, then refresh.")
- : translate("auto.components.linear.project.view.surfaces.9f0f51fd9e", "Create or save views in Linear, then refresh.")}
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.f4c79cff5f',
+ 'Review the workspace error below, then refresh.'
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.9f0f51fd9e',
+ 'Create or save views in Linear, then refresh.'
+ )}
)
@@ -471,13 +525,18 @@ export function LinearCustomViewTable({
{view.model}
- {view.shared ? translate("auto.components.linear.project.view.surfaces.27d91cb1a6", "Shared") : translate("auto.components.linear.project.view.surfaces.f059181bd9", "Private")}
+ {view.shared
+ ? translate('auto.components.linear.project.view.surfaces.27d91cb1a6', 'Shared')
+ : translate('auto.components.linear.project.view.surfaces.f059181bd9', 'Private')}
- {textFromUnknown(view.owner ?? view.creator) ?? translate("auto.components.linear.project.view.surfaces.20b9d09b7d", "Unknown")}
+ {textFromUnknown(view.owner ?? view.creator) ??
+ translate('auto.components.linear.project.view.surfaces.20b9d09b7d', 'Unknown')}
- {view.updatedAt ? dateLabel(view.updatedAt) : translate("auto.components.linear.project.view.surfaces.20b9d09b7d", "Unknown")}
+ {view.updatedAt
+ ? dateLabel(view.updatedAt)
+ : translate('auto.components.linear.project.view.surfaces.20b9d09b7d', 'Unknown')}
@@ -489,13 +548,21 @@ export function LinearCustomViewTable({
event.stopPropagation()
onOpenView(view)
}}
- aria-label={translate("auto.components.linear.project.view.surfaces.7616c986c6", "Open {{value0}} in Linear", { value0: view.name })}
+ aria-label={translate(
+ 'auto.components.linear.project.view.surfaces.7616c986c6',
+ 'Open {{value0}} in Linear',
+ { value0: view.name }
+ )}
>
- {translate("auto.components.linear.project.view.surfaces.aac9a4afc6", "Open in Linear")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.aac9a4afc6',
+ 'Open in Linear'
+ )}
+
@@ -528,17 +595,33 @@ export function LinearProjectOverview({
-
+
- {project?.name ?? translate("auto.components.linear.project.view.surfaces.85607ff793", "Project")}
+ {project?.name ??
+ translate('auto.components.linear.project.view.surfaces.85607ff793', 'Project')}
{project?.workspaceName
- ? translate("auto.components.linear.project.view.surfaces.906b5e4cb8", "Linear / Projects / {{value0}}", { value0: project.workspaceName })
- : translate("auto.components.linear.project.view.surfaces.f2cc1e0ff6", "Linear / Projects")}
+ ? translate(
+ 'auto.components.linear.project.view.surfaces.906b5e4cb8',
+ 'Linear / Projects / {{value0}}',
+ { value0: project.workspaceName }
+ )
+ : translate(
+ 'auto.components.linear.project.view.surfaces.f2cc1e0ff6',
+ 'Linear / Projects'
+ )}
@@ -551,7 +634,8 @@ export function LinearProjectOverview({
className="gap-1 border-border/50 bg-background/70"
>
- {translate("auto.components.linear.project.view.surfaces.ee3d2caabd", "Issues")}
+ {translate('auto.components.linear.project.view.surfaces.ee3d2caabd', 'Issues')}
+
) : null}
- {translate("auto.components.linear.project.view.surfaces.a9785c7158", "Refresh")}
+ {translate('auto.components.linear.project.view.surfaces.a9785c7158', 'Refresh')}
+
{project ? (
- {translate("auto.components.linear.project.view.surfaces.7b147907dc", "Linear")}
+ {translate('auto.components.linear.project.view.surfaces.7b147907dc', 'Linear')}
+
) : null}
@@ -602,41 +688,70 @@ export function LinearProjectOverview({
{body}
) : (
- {translate("auto.components.linear.project.view.surfaces.bb5664d456", "No project description.")}
+
+ {translate(
+ 'auto.components.linear.project.view.surfaces.bb5664d456',
+ 'No project description.'
+ )}
+
)}
{progress !== null ? (
- {translate("auto.components.linear.project.view.surfaces.563501f191", "Progress")}
+
+ {translate(
+ 'auto.components.linear.project.view.surfaces.563501f191',
+ 'Progress'
+ )}
+
{progress}%
- {typeof projectLike.scope === "number" ? (
+ {typeof projectLike.scope === 'number' ? (
- {projectLike.scope} {translate("auto.components.linear.project.view.surfaces.3ad562bdf4", "scoped issues")}
+ {projectLike.scope}{' '}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.3ad562bdf4',
+ 'scoped issues'
+ )}
+
) : null}
) : null}
{milestones.length > 0 || resources.length > 0 || latestUpdate ? (
- {translate("auto.components.linear.project.view.surfaces.5d99315fb8", "Planning")}
+
+ {translate(
+ 'auto.components.linear.project.view.surfaces.5d99315fb8',
+ 'Planning'
+ )}
+
}
- label={translate("auto.components.linear.project.view.surfaces.bb1405eff8", "Milestones")}
+ label={translate(
+ 'auto.components.linear.project.view.surfaces.bb1405eff8',
+ 'Milestones'
+ )}
items={milestones}
/>
}
- label={translate("auto.components.linear.project.view.surfaces.c8db98b73b", "Resources")}
+ label={translate(
+ 'auto.components.linear.project.view.surfaces.c8db98b73b',
+ 'Resources'
+ )}
items={resources}
/>
}
- label={translate("auto.components.linear.project.view.surfaces.0a6a5a7dd6", "Latest update")}
+ label={translate(
+ 'auto.components.linear.project.view.surfaces.0a6a5a7dd6',
+ 'Latest update'
+ )}
items={latestUpdate ? [latestUpdate] : []}
/>
@@ -646,37 +761,77 @@ export function LinearProjectOverview({
-
+
}
/>
}
/>
}
/>
-
-
-
+
+
+
) : (
- {translate("auto.components.linear.project.view.surfaces.e1fa97d21d", "Select a project to view its overview.")}
+ {translate(
+ 'auto.components.linear.project.view.surfaces.e1fa97d21d',
+ 'Select a project to view its overview.'
+ )}
+
)}
@@ -727,7 +882,9 @@ function MetadataList({
))}
) : (
- {translate("auto.components.linear.project.view.surfaces.8bbecb2510", "None")}
+
+ {translate('auto.components.linear.project.view.surfaces.8bbecb2510', 'None')}
+
)}
)
diff --git a/src/renderer/src/components/linear-scope-selector.tsx b/src/renderer/src/components/linear-scope-selector.tsx
index 24f155fb8fd..3cf4c4b1b2e 100644
--- a/src/renderer/src/components/linear-scope-selector.tsx
+++ b/src/renderer/src/components/linear-scope-selector.tsx
@@ -230,7 +230,10 @@ export function LinearScopeSelector({
1 ? (
- {translate("auto.components.linear.scope.selector.05baa5ae90", "Workspace")}
+ {translate('auto.components.linear.scope.selector.05baa5ae90', 'Workspace')}
+
{
@@ -254,7 +258,12 @@ export function LinearScopeSelector({
selectedWorkspaceId === 'all' ? 'opacity-70' : 'opacity-0'
)}
/>
- {translate("auto.components.linear.scope.selector.a14ce4df2b", "All workspaces")}
+
+ {translate(
+ 'auto.components.linear.scope.selector.a14ce4df2b',
+ 'All workspaces'
+ )}
+
{workspaces.map((workspace) => (
- {translate("auto.components.linear.scope.selector.e1ae6bebb0", "Teams")}
+ {translate('auto.components.linear.scope.selector.e1ae6bebb0', 'Teams')}
+
handleAllTeams()}
@@ -291,7 +301,9 @@ export function LinearScopeSelector({
allTeamsSelected || teamSelectionIsStickyAll ? 'opacity-70' : 'opacity-0'
)}
/>
- {translate("auto.components.linear.scope.selector.7783361266", "All teams")}
+
+ {translate('auto.components.linear.scope.selector.7783361266', 'All teams')}
+
{filteredTeams.length > 0 ? (
@@ -332,8 +344,14 @@ export function LinearScopeSelector({
) : (
{query.trim()
- ? translate("auto.components.linear.scope.selector.405b33c378", "No fetched teams match your search.")
- : translate("auto.components.linear.scope.selector.b3488fad3c", "No teams were fetched. Access can depend on key scope, private-team membership, archived teams, permissions, or a fetch failure.")}
+ ? translate(
+ 'auto.components.linear.scope.selector.405b33c378',
+ 'No fetched teams match your search.'
+ )
+ : translate(
+ 'auto.components.linear.scope.selector.b3488fad3c',
+ 'No teams were fetched. Access can depend on key scope, private-team membership, archived teams, permissions, or a fetch failure.'
+ )}
)}
@@ -348,7 +366,9 @@ export function LinearScopeSelector({
className="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-xs text-foreground transition hover:bg-accent hover:text-accent-foreground"
>
- {translate("auto.components.linear.scope.selector.91c8871dad", "Add team access")}
+
+ {translate('auto.components.linear.scope.selector.91c8871dad', 'Add team access')}
+
diff --git a/src/renderer/src/components/mobile/MobilePageToolbar.tsx b/src/renderer/src/components/mobile/MobilePageToolbar.tsx
index ee734c198e4..097b02919f7 100644
--- a/src/renderer/src/components/mobile/MobilePageToolbar.tsx
+++ b/src/renderer/src/components/mobile/MobilePageToolbar.tsx
@@ -23,13 +23,17 @@ export function MobilePageToolbar({
size="icon"
className="size-7 rounded-full"
onClick={onClose}
- aria-label={translate("auto.components.mobile.MobilePageToolbar.9883b58693", "Close Orca Mobile")}
+ aria-label={translate(
+ 'auto.components.mobile.MobilePageToolbar.9883b58693',
+ 'Close Orca Mobile'
+ )}
>
- {translate("auto.components.mobile.MobilePageToolbar.ad2284a9e2", "Close · Esc")}
+ {translate('auto.components.mobile.MobilePageToolbar.ad2284a9e2', 'Close · Esc')}
+
{showMobileButton ? : }
- {showMobileButton ? translate("auto.components.mobile.MobilePageToolbar.c669abcf8f", "Hide from sidebar") : translate("auto.components.mobile.MobilePageToolbar.fb5f28330e", "Show in sidebar")}
+ {showMobileButton
+ ? translate('auto.components.mobile.MobilePageToolbar.c669abcf8f', 'Hide from sidebar')
+ : translate('auto.components.mobile.MobilePageToolbar.fb5f28330e', 'Show in sidebar')}
)
diff --git a/src/renderer/src/components/mobile/PhoneCarousel.tsx b/src/renderer/src/components/mobile/PhoneCarousel.tsx
index 250a420a951..9d801d2e16d 100644
--- a/src/renderer/src/components/mobile/PhoneCarousel.tsx
+++ b/src/renderer/src/components/mobile/PhoneCarousel.tsx
@@ -114,13 +114,31 @@ export function PhoneCarousel(): React.JSX.Element {
return (
-
+
-
+
-
diff --git a/src/renderer/src/components/mobile/mobile-platform-copy.ts b/src/renderer/src/components/mobile/mobile-platform-copy.ts
index f63c4ce794d..e09bbbc1eee 100644
--- a/src/renderer/src/components/mobile/mobile-platform-copy.ts
+++ b/src/renderer/src/components/mobile/mobile-platform-copy.ts
@@ -6,12 +6,18 @@ export const PLATFORM_COPY: Record<
{ description: string; ctaLabel: string; url: string }
> = {
ios: {
- description: translate("auto.components.mobile.mobile.platform.copy.432db52b73", "Scan with your iPhone camera to open the App Store."),
+ description: translate(
+ 'auto.components.mobile.mobile.platform.copy.432db52b73',
+ 'Scan with your iPhone camera to open the App Store.'
+ ),
ctaLabel: 'Open App Store',
url: 'https://apps.apple.com/app/orca-ide/id6766130217'
},
android: {
- description: translate("auto.components.mobile.mobile.platform.copy.2a532d6fd7", "Scan with your Android camera to download the latest APK from GitHub Releases."),
+ description: translate(
+ 'auto.components.mobile.mobile.platform.copy.2a532d6fd7',
+ 'Scan with your Android camera to download the latest APK from GitHub Releases.'
+ ),
ctaLabel: 'Download APK',
url: 'https://github.com/stablyai/orca/releases/download/mobile-v0.0.12/app-release.apk'
}
diff --git a/src/renderer/src/components/mobile/slides/HomeSlide.tsx b/src/renderer/src/components/mobile/slides/HomeSlide.tsx
index e5a474e6d4d..0e02b6511f6 100644
--- a/src/renderer/src/components/mobile/slides/HomeSlide.tsx
+++ b/src/renderer/src/components/mobile/slides/HomeSlide.tsx
@@ -8,34 +8,63 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.5d94e8ddcc", "Orca")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.5d94e8ddcc', 'Orca')}
+
-
+
-
{translate("auto.components.mobile.slides.HomeSlide.c0e2e9dcd9", "Welcome back")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.c0e2e9dcd9', 'Welcome back')}
+
-
-
-
+
+
+
-
{translate("auto.components.mobile.slides.HomeSlide.2f1a1d10c4", "Desktops")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.2f1a1d10c4', 'Desktops')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.19c212e25e", "MacBook Pro")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.19c212e25e', 'MacBook Pro')}
+
- {translate("auto.components.mobile.slides.HomeSlide.0bc1881bc4", "Connected · 40 worktrees · 5 active")}
+
+ {translate(
+ 'auto.components.mobile.slides.HomeSlide.0bc1881bc4',
+ 'Connected · 40 worktrees · 5 active'
+ )}
+
@@ -47,10 +76,14 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
-
{translate("auto.components.mobile.slides.HomeSlide.091355da3d", "M1 Mini · home")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.091355da3d', 'M1 Mini · home')}
+
- {translate("auto.components.mobile.slides.HomeSlide.cf3f98fa3f", "Disconnected")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.cf3f98fa3f', 'Disconnected')}
+
@@ -59,16 +92,24 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.c791677f2f", "Resume")}
+ {translate('auto.components.mobile.slides.HomeSlide.c791677f2f', 'Resume')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.25d6e8a491", "feat/mobile-page")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.25d6e8a491', 'feat/mobile-page')}
+
- {translate("auto.components.mobile.slides.HomeSlide.d33d7a9c29", "orca · feat/mobile-page")}
+
+ {translate(
+ 'auto.components.mobile.slides.HomeSlide.d33d7a9c29',
+ 'orca · feat/mobile-page'
+ )}
+
@@ -77,16 +118,27 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.a4c3f7b7aa", "Tasks")}
+ {translate('auto.components.mobile.slides.HomeSlide.a4c3f7b7aa', 'Tasks')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.a4c3f7b7aa", "Tasks")}
-
{translate("auto.components.mobile.slides.HomeSlide.d047197480", "GitHub · Linear")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.a4c3f7b7aa', 'Tasks')}
+
+
+ {translate('auto.components.mobile.slides.HomeSlide.d047197480', 'GitHub · Linear')}
+
-
+
@@ -100,24 +152,30 @@ export function HomeSlide({ tapping }: { tapping: boolean }): React.JSX.Element
- {translate("auto.components.mobile.slides.HomeSlide.0b00c98506", "Quick Actions")}
+ {translate('auto.components.mobile.slides.HomeSlide.0b00c98506', 'Quick Actions')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.4405f3c440", "Pair Desktop")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.4405f3c440', 'Pair Desktop')}
+
-
{translate("auto.components.mobile.slides.HomeSlide.e27fdaee51", "New Workspace")}
+
+ {translate('auto.components.mobile.slides.HomeSlide.e27fdaee51', 'New Workspace')}
+
- {translate("auto.components.mobile.slides.HomeSlide.8a350a4784", "Account usage")}
+ {translate('auto.components.mobile.slides.HomeSlide.8a350a4784', 'Account usage')}
+
}
@@ -163,8 +221,14 @@ function AccountRow({
diff --git a/src/renderer/src/components/mobile/slides/TerminalSlide.tsx b/src/renderer/src/components/mobile/slides/TerminalSlide.tsx
index 5de7cffed69..27714e4c7a9 100644
--- a/src/renderer/src/components/mobile/slides/TerminalSlide.tsx
+++ b/src/renderer/src/components/mobile/slides/TerminalSlide.tsx
@@ -4,32 +4,66 @@ export function TerminalSlide(): React.JSX.Element {
-
+
-
{translate("auto.components.mobile.slides.TerminalSlide.8432787c4e", "feat/mobile-page")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.8432787c4e',
+ 'feat/mobile-page'
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.8d6516312d", "2 terminals · claude active")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.8d6516312d',
+ '2 terminals · claude active'
+ )}
+
-
+
-
+
-
{translate("auto.components.mobile.slides.TerminalSlide.2c10d43745", "claude")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.2c10d43745', 'claude')}
+
- {translate("auto.components.mobile.slides.TerminalSlide.e4befee569", "shell")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.e4befee569', 'shell')}
+
- {translate("auto.components.mobile.slides.TerminalSlide.da121ba48d", "PLAN.md")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.da121ba48d', 'PLAN.md')}
+
@@ -39,60 +73,139 @@ export function TerminalSlide(): React.JSX.Element {
- {translate("auto.components.mobile.slides.TerminalSlide.2defc05141", "dev@mac")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.e0f98be657", "orca/feat-mobile-page")} {' '}
- $ {translate("auto.components.mobile.slides.TerminalSlide.2c10d43745", "claude")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.2defc05141', 'dev@mac')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.e0f98be657',
+ 'orca/feat-mobile-page'
+ )}
+ {' '}
+ $ {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.2c10d43745', 'claude')}
+
- ● {translate("auto.components.mobile.slides.TerminalSlide.80cc356591", "Read")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.336c0e070e", "mobile/orca-mobile-sidebar-mock-v3.html")}
+ ● {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.80cc356591', 'Read')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.336c0e070e',
+ 'mobile/orca-mobile-sidebar-mock-v3.html'
+ )}
+
{' '}
- {translate("auto.components.mobile.slides.TerminalSlide.fc83e0d5ef", "⎿ Read 2103 lines")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.fc83e0d5ef',
+ '⎿ Read 2103 lines'
+ )}
+
- ● {translate("auto.components.mobile.slides.TerminalSlide.6d4ebd5833", "Edit")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.336c0e070e", "mobile/orca-mobile-sidebar-mock-v3.html")}
+ ● {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.6d4ebd5833', 'Edit')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.336c0e070e',
+ 'mobile/orca-mobile-sidebar-mock-v3.html'
+ )}
+
{' '}
- {translate("auto.components.mobile.slides.TerminalSlide.d6d1041a1c", "⎿ Replaced pair-scan slide with terminal session")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.d6d1041a1c',
+ '⎿ Replaced pair-scan slide with terminal session'
+ )}
+
- ● {translate("auto.components.mobile.slides.TerminalSlide.21b67dfc92", "Bash")} {' '}
- {translate("auto.components.mobile.slides.TerminalSlide.a6e7cdc688", "pnpm test --filter mobile")}
+ ● {' '}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.21b67dfc92', 'Bash')}
+ {' '}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.a6e7cdc688',
+ 'pnpm test --filter mobile'
+ )}
+
{' '}
⎿
- {translate("auto.components.mobile.slides.TerminalSlide.1d448b69f7", "PASS")}
- {translate("auto.components.mobile.slides.TerminalSlide.d39445686a", "src/transport/host-store.test.ts")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.1d448b69f7', 'PASS')}
+
+
+ {' '}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.d39445686a',
+ 'src/transport/host-store.test.ts'
+ )}
+
{' '}
- {translate("auto.components.mobile.slides.TerminalSlide.1d448b69f7", "PASS")}
- {translate("auto.components.mobile.slides.TerminalSlide.4b3666f9a9", "src/cache/worktree-cache.test.ts")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.1d448b69f7', 'PASS')}
+
+
+ {' '}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.4b3666f9a9',
+ 'src/cache/worktree-cache.test.ts'
+ )}
+
{' '}
●
- {translate("auto.components.mobile.slides.TerminalSlide.3ce3e8c892", "14 passed, 1 skipped (1.8s)")}
+
+ {' '}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.3ce3e8c892',
+ '14 passed, 1 skipped (1.8s)'
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.e75112c834", "I've replaced the pair-scan slide with a high-fidelity")}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.e75112c834',
+ "I've replaced the pair-scan slide with a high-fidelity"
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.aa64b519c6", "terminal screen. Tokyonight palette, Menlo, real claude")}
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.aa64b519c6',
+ 'terminal screen. Tokyonight palette, Menlo, real claude'
+ )}
+
- {translate("auto.components.mobile.slides.TerminalSlide.58a9ee6003", "tool-call formatting. Want me to add the diff next?")}
+
+ {translate(
+ 'auto.components.mobile.slides.TerminalSlide.58a9ee6003',
+ 'tool-call formatting. Want me to add the diff next?'
+ )}
+
@@ -102,27 +215,52 @@ export function TerminalSlide(): React.JSX.Element {
-
+
-
{translate("auto.components.mobile.slides.TerminalSlide.fa22927f13", "Paste")}
-
{translate("auto.components.mobile.slides.TerminalSlide.4930eaaae7", "Esc")}
-
{translate("auto.components.mobile.slides.TerminalSlide.53ff909568", "Tab")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.fa22927f13', 'Paste')}
+
+
+ {translate('auto.components.mobile.slides.TerminalSlide.4930eaaae7', 'Esc')}
+
+
+ {translate('auto.components.mobile.slides.TerminalSlide.53ff909568', 'Tab')}
+
⌫
↑
↓
←
→
-
{translate("auto.components.mobile.slides.TerminalSlide.817090af40", "Ctrl+C")}
+
+ {translate('auto.components.mobile.slides.TerminalSlide.817090af40', 'Ctrl+C')}
+
-
{translate("auto.components.mobile.slides.TerminalSlide.29f2d13839", "Type a command…")}
-
+
+ {translate('auto.components.mobile.slides.TerminalSlide.29f2d13839', 'Type a command…')}
+
+
-
diff --git a/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx b/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx
index ab209993ad0..671be8c60b1 100644
--- a/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx
+++ b/src/renderer/src/components/mobile/slides/WorktreeListSlide.tsx
@@ -20,24 +20,39 @@ export function WorktreeListSlide({ tapping }: { tapping: boolean }): React.JSX.
-
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.b4271864bd", "MacBook Pro")}
+
+ {translate(
+ 'auto.components.mobile.slides.WorktreeListSlide.b4271864bd',
+ 'MacBook Pro'
+ )}
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.0e3e809a4b", "Filter")}
+ {translate('auto.components.mobile.slides.WorktreeListSlide.0e3e809a4b', 'Filter')}
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.17f9e0d226", "Recent")}
+ {translate('auto.components.mobile.slides.WorktreeListSlide.17f9e0d226', 'Recent')}
+
- {translate("auto.components.mobile.slides.WorktreeListSlide.22971156df", "Repo")}
+ {translate('auto.components.mobile.slides.WorktreeListSlide.22971156df', 'Repo')}
+
@@ -54,7 +69,9 @@ export function WorktreeListSlide({ tapping }: { tapping: boolean }): React.JSX.
-
{translate("auto.components.mobile.slides.WorktreeListSlide.79a24ff530", "Pinned")}
+
+ {translate('auto.components.mobile.slides.WorktreeListSlide.79a24ff530', 'Pinned')}
+
3
@@ -95,7 +112,9 @@ export function WorktreeListSlide({ tapping }: { tapping: boolean }): React.JSX.
- {translate("auto.components.mobile.slides.WorktreeListSlide.357a519567", "Active")}
+
+ {translate('auto.components.mobile.slides.WorktreeListSlide.357a519567', 'Active')}
+
37
@@ -172,7 +191,7 @@ function WorktreeRow({
return (
- {indicator === "spinner" ? (
+ {indicator === 'spinner' ? (
) : (
diff --git a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
index 644935e5af0..b31edc93171 100644
--- a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
+++ b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
@@ -68,10 +68,22 @@ import { translate } from '@/i18n/i18n'
type MrStateFilter = 'opened' | 'merged' | 'closed' | 'all'
const MR_STATE_FILTERS: { id: MrStateFilter; label: string }[] = [
- { id: 'opened', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.622864b52a", "Open") },
- { id: 'merged', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.2319d87718", "Merged") },
- { id: 'closed', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.6fad211c66", "Closed") },
- { id: 'all', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.26824f60dd", "All") }
+ {
+ id: 'opened',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.622864b52a', 'Open')
+ },
+ {
+ id: 'merged',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.2319d87718', 'Merged')
+ },
+ {
+ id: 'closed',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.6fad211c66', 'Closed')
+ },
+ {
+ id: 'all',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.26824f60dd', 'All')
+ }
]
type RepoOption = ReturnType
['repos'][number]
@@ -111,20 +123,40 @@ const MODES: {
label: string
Icon: React.ComponentType<{ className?: string }>
}[] = [
- { id: 'smart', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.b3c60c2b7c", "Smart"), Icon: Sparkles },
- { id: 'github', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.0a180280bd", "GitHub"), Icon: Github },
+ {
+ id: 'smart',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.b3c60c2b7c', 'Smart'),
+ Icon: Sparkles
+ },
+ {
+ id: 'github',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.0a180280bd', 'GitHub'),
+ Icon: Github
+ },
{
id: 'linear',
- label: translate("auto.components.new.workspace.SmartWorkspaceNameField.7a47af0565", "Linear"),
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.7a47af0565', 'Linear'),
Icon: ({ className }: { className?: string }) => (
)
},
- { id: 'gitlab', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.2cfc6be192", "GitLab"), Icon: Gitlab },
- { id: 'branches', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.2e4c7c95fe", "Branch"), Icon: GitBranch },
- { id: 'text', label: translate("auto.components.new.workspace.SmartWorkspaceNameField.6f07a18604", "Name"), Icon: CaseSensitive }
+ {
+ id: 'gitlab',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.2cfc6be192', 'GitLab'),
+ Icon: Gitlab
+ },
+ {
+ id: 'branches',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.2e4c7c95fe', 'Branch'),
+ Icon: GitBranch
+ },
+ {
+ id: 'text',
+ label: translate('auto.components.new.workspace.SmartWorkspaceNameField.6f07a18604', 'Name'),
+ Icon: CaseSensitive
+ }
]
type RowEntry = SmartWorkspaceSourceRow
@@ -989,13 +1021,20 @@ export default function SmartWorkspaceNameField({
size="icon-xs"
onClick={() => void window.api.shell.openUrl(selectedSource.url!)}
className="size-6 shrink-0 rounded-sm text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.new.workspace.SmartWorkspaceNameField.2c69728c2a", "Open link in browser")}
+ aria-label={translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.2c69728c2a',
+ 'Open link in browser'
+ )}
>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.370a1faf67", "Open in browser")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.370a1faf67',
+ 'Open in browser'
+ )}
+
) : null}
@@ -1006,13 +1045,20 @@ export default function SmartWorkspaceNameField({
size="icon-xs"
onClick={onClearSelectedSource}
className="size-6 shrink-0 rounded-sm text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.new.workspace.SmartWorkspaceNameField.7199ff19c7", "Clear selected source")}
+ aria-label={translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.7199ff19c7',
+ 'Clear selected source'
+ )}
>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.0c9e668e3a", "Clear")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.0c9e668e3a',
+ 'Clear'
+ )}
+
) : (
@@ -1110,7 +1156,7 @@ export default function SmartWorkspaceNameField({
}
}}
>
- {mode === "gitlab" ? (
+ {mode === 'gitlab' ? (
// Why: GitLab MR-state filter — Open / Merged / Closed / All —
// mirrors the gitlab.com merge-requests page tab strip so users
// arriving from the web UI find a familiar control.
@@ -1141,8 +1187,11 @@ export default function SmartWorkspaceNameField({
) : rows.length === 0 ? (
- {mode === "linear" && linearStatusChecked && !linearStatus.connected
- ? translate("auto.components.new.workspace.SmartWorkspaceNameField.3e8bb1176a", "Connect Linear in Settings to search issues.")
+ {mode === 'linear' && linearStatusChecked && !linearStatus.connected
+ ? translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.3e8bb1176a',
+ 'Connect Linear in Settings to search issues.'
+ )
: getSmartWorkspaceEmptyHint(mode)}
) : (
@@ -1170,23 +1219,57 @@ export default function SmartWorkspaceNameField({
>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.4bd98f1091", "Switch project?")}
+
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.4bd98f1091',
+ 'Switch project?'
+ )}
+
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.ad188067ae", "The GitHub URL points to")}{crossRepoPrompt?.link.slug.owner}/
- {crossRepoPrompt?.link.slug.repo}{translate("auto.components.new.workspace.SmartWorkspaceNameField.9ef1a7c4b0", ", which is different from the selected project.")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.ad188067ae',
+ 'The GitHub URL points to'
+ )}
+ {crossRepoPrompt?.link.slug.owner}/{crossRepoPrompt?.link.slug.repo}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.9ef1a7c4b0',
+ ', which is different from the selected project.'
+ )}
+
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.6859e2896c", "Cancel")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.6859e2896c',
+ 'Cancel'
+ )}
+
void handleUseCurrentRepo()}>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.eadf877af5", "Keep")}{selectedRepo?.displayName ?? translate("auto.components.new.workspace.SmartWorkspaceNameField.fda67f0b61", "current project")}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.eadf877af5',
+ 'Keep'
+ )}
+ {selectedRepo?.displayName ??
+ translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.fda67f0b61',
+ 'current project'
+ )}
{crossRepoPrompt?.matchingRepo ? (
void acceptGitHubLink(crossRepoPrompt.matchingRepo!)}>
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.a76fcb4fa0", "Switch to")}{crossRepoPrompt.matchingRepo.displayName}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.a76fcb4fa0',
+ 'Switch to'
+ )}
+ {crossRepoPrompt.matchingRepo.displayName}
) : (
- void handleAddMatchingRepo()}>{translate("auto.components.new.workspace.SmartWorkspaceNameField.e57c53727c", "Add project...")}
+ void handleAddMatchingRepo()}>
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.e57c53727c',
+ 'Add project...'
+ )}
+
)}
@@ -1253,13 +1336,26 @@ function RowLabel({ row }: { row: RowEntry }): React.JSX.Element {
if (row.kind === 'use-name') {
return (
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.b1a7d679ba", "Use")}{translate("auto.components.new.workspace.SmartWorkspaceNameField.34ca97bce3", "\"")}{row.name}{translate("auto.components.new.workspace.SmartWorkspaceNameField.766083a596", "\"")} {translate("auto.components.new.workspace.SmartWorkspaceNameField.a44229ce4d", "as workspace name")}
+ {translate('auto.components.new.workspace.SmartWorkspaceNameField.b1a7d679ba', 'Use')}
+
+ {translate('auto.components.new.workspace.SmartWorkspaceNameField.34ca97bce3', '"')}
+ {row.name}
+ {translate('auto.components.new.workspace.SmartWorkspaceNameField.766083a596', '"')}
+ {' '}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.a44229ce4d',
+ 'as workspace name'
+ )}
+
)
}
if (row.kind === 'create-branch') {
return (
- {translate("auto.components.new.workspace.SmartWorkspaceNameField.2a0d535f69", "Create new branch")}{' '}
+ {translate(
+ 'auto.components.new.workspace.SmartWorkspaceNameField.2a0d535f69',
+ 'Create new branch'
+ )}{' '}
{row.name}
)
diff --git a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx
index 52d725173cb..3533b117f07 100644
--- a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx
+++ b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx
@@ -41,7 +41,11 @@ export function AgentFeatureSetupStep({
onClick={onStartFeatureSetup}
>
{setupBusyLabel ?
: null}
- {setupBusyLabel ?? translate("auto.components.onboarding.AgentFeatureSetupStep.97dcdc010f", "Enable capabilities")}
+ {setupBusyLabel ??
+ translate(
+ 'auto.components.onboarding.AgentFeatureSetupStep.97dcdc010f',
+ 'Enable capabilities'
+ )}
) : null}
diff --git a/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx b/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
index 98bbfaeada4..56e79fb2890 100644
--- a/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
+++ b/src/renderer/src/components/onboarding/FeatureSetupChecklist.tsx
@@ -23,22 +23,37 @@ type FeatureSetupRow = {
const FEATURE_SETUP_ROWS: readonly FeatureSetupRow[] = [
{
id: 'browserUse',
- title: translate("auto.components.onboarding.FeatureSetupChecklist.ea85d9e628", "Agent Browser Use"),
- description: translate("auto.components.onboarding.FeatureSetupChecklist.01426f3a23", "Agents can navigate sites, inspect pages, and work through browser tasks."),
+ title: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.ea85d9e628',
+ 'Agent Browser Use'
+ ),
+ description: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.01426f3a23',
+ 'Agents can navigate sites, inspect pages, and work through browser tasks.'
+ ),
setupSummary: 'Enables browser use, prepares orca-cli, and leaves cookies for Settings.',
icon:
},
{
id: 'computerUse',
- title: translate("auto.components.onboarding.FeatureSetupChecklist.1ecfb490ac", "Computer Use"),
- description: translate("auto.components.onboarding.FeatureSetupChecklist.c5292c409d", "Agents can inspect app windows and operate local apps when you ask."),
+ title: translate('auto.components.onboarding.FeatureSetupChecklist.1ecfb490ac', 'Computer Use'),
+ description: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.c5292c409d',
+ 'Agents can inspect app windows and operate local apps when you ask.'
+ ),
setupSummary: 'Registers the Orca CLI, opens permissions, and prepares the skill.',
icon:
},
{
id: 'orchestration',
- title: translate("auto.components.onboarding.FeatureSetupChecklist.399cf885c0", "Agent Orchestration"),
- description: translate("auto.components.onboarding.FeatureSetupChecklist.77f74946f5", "Agents can message each other, take tasks, and coordinate handoffs."),
+ title: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.399cf885c0',
+ 'Agent Orchestration'
+ ),
+ description: translate(
+ 'auto.components.onboarding.FeatureSetupChecklist.77f74946f5',
+ 'Agents can message each other, take tasks, and coordinate handoffs.'
+ ),
setupSummary: 'Registers the Orca CLI, enables orchestration, and prepares the skill.',
icon:
}
diff --git a/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx b/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx
index fe208e5ffaa..e15c796d4bf 100644
--- a/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx
+++ b/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx
@@ -57,9 +57,18 @@ export function FeatureSetupInlineTerminal({
return (
-
{translate("auto.components.onboarding.IntegrationsStep.217beb0658", "GitHub")}
- {state === "connected" ? (
- {translate("auto.components.onboarding.IntegrationsStep.c91a5782f1", "Connected")}
- ) : state === "not-installed" ? (
- {translate("auto.components.onboarding.IntegrationsStep.5c115cb713", "CLI not installed")}
- ) : state === "not-authenticated" ? (
- {translate("auto.components.onboarding.IntegrationsStep.8405043962", "Sign in needed")}
+
+ {translate('auto.components.onboarding.IntegrationsStep.217beb0658', 'GitHub')}
+
+ {state === 'connected' ? (
+
+ {translate('auto.components.onboarding.IntegrationsStep.c91a5782f1', 'Connected')}
+
+ ) : state === 'not-installed' ? (
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.5c115cb713',
+ 'CLI not installed'
+ )}
+
+ ) : state === 'not-authenticated' ? (
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.8405043962',
+ 'Sign in needed'
+ )}
+
) : (
- {translate("auto.components.onboarding.IntegrationsStep.c1547656f0", "Checking…")}
+
+ {translate('auto.components.onboarding.IntegrationsStep.c1547656f0', 'Checking…')}
+
)}
- {translate("auto.components.onboarding.IntegrationsStep.50db38cf4b", "Pull requests, issues, and check status.")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.50db38cf4b',
+ 'Pull requests, issues, and check status.'
+ )}
+
- {state === "not-installed" ? (
+ {state === 'not-installed' ? (
window.api.shell.openUrl('https://cli.github.com')}
>
- {translate("auto.components.onboarding.IntegrationsStep.bd5d976fb2", "Install gh")}
+ {translate('auto.components.onboarding.IntegrationsStep.bd5d976fb2', 'Install gh')}
+
) : null}
- {state === "not-authenticated" ? (
+ {state === 'not-authenticated' ? (
setGithubTerminalOpen(true)}
>
- {githubTerminalOpen ? translate("auto.components.onboarding.IntegrationsStep.0b4a7d23ab", "Signing in") : translate("auto.components.onboarding.IntegrationsStep.d6e5dba05a", "Sign in")}
+ {githubTerminalOpen
+ ? translate('auto.components.onboarding.IntegrationsStep.0b4a7d23ab', 'Signing in')
+ : translate('auto.components.onboarding.IntegrationsStep.d6e5dba05a', 'Sign in')}
) : null}
- {state !== "connected" ? (
+ {state !== 'connected' ? (
void refreshPreflightStatus({ force: true })}
>
- {translate("auto.components.onboarding.IntegrationsStep.80e3ce0bc9", "Re-check")}
+ {translate('auto.components.onboarding.IntegrationsStep.80e3ce0bc9', 'Re-check')}
+
) : null}
- {state === "not-authenticated" && githubTerminalOpen ? (
+ {state === 'not-authenticated' && githubTerminalOpen ? (
) : null}
@@ -122,29 +155,52 @@ export function LinearRow(props: { compact?: boolean } = {}): React.JSX.Element
-
{translate("auto.components.onboarding.IntegrationsStep.27743304b1", "Linear")}
+
+ {translate('auto.components.onboarding.IntegrationsStep.27743304b1', 'Linear')}
+
{linearStatus.connected ? (
- {translate("auto.components.onboarding.IntegrationsStep.c91a5782f1", "Connected")}
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.c91a5782f1',
+ 'Connected'
+ )}
+
) : null}
{linearStatus.connected
- ? translate("auto.components.onboarding.IntegrationsStep.b08a6ac93c", "{{value0}} workspace{{value1}} linked. Add another workspace or replace a restricted key any time.", { value0: workspaceCount, value1: workspaceCount === 1 ? '' : 's' })
- : translate("auto.components.onboarding.IntegrationsStep.4983ae7433", "Add Linear access with a Personal API key. Full-access keys can show every team the key owner can access.")}
+ ? translate(
+ 'auto.components.onboarding.IntegrationsStep.b08a6ac93c',
+ '{{value0}} workspace{{value1}} linked. Add another workspace or replace a restricted key any time.',
+ { value0: workspaceCount, value1: workspaceCount === 1 ? '' : 's' }
+ )
+ : translate(
+ 'auto.components.onboarding.IntegrationsStep.4983ae7433',
+ 'Add Linear access with a Personal API key. Full-access keys can show every team the key owner can access.'
+ )}
{linearStatus.connected ? (
setDialogOpen(true)}>
- {translate("auto.components.onboarding.IntegrationsStep.dd9c186a8b", "Add workspace access")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.dd9c186a8b',
+ 'Add workspace access'
+ )}
+
) : (
setDialogOpen(true)}>
- {translate("auto.components.onboarding.IntegrationsStep.04ef416712", "Add Linear access")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.04ef416712',
+ 'Add Linear access'
+ )}
+
)}
{!linearStatus.connected ? (
void checkLinearConnection(true)}>
- {translate("auto.components.onboarding.IntegrationsStep.80e3ce0bc9", "Re-check")}
+ {translate('auto.components.onboarding.IntegrationsStep.80e3ce0bc9', 'Re-check')}
+
) : null}
@@ -190,9 +246,18 @@ export function IntegrationsStep(): React.JSX.Element {
- {translate("auto.components.onboarding.IntegrationsStep.3a3e360289", "More task sources")}
+
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.3a3e360289',
+ 'More task sources'
+ )}
+
- {translate("auto.components.onboarding.IntegrationsStep.277f30eb34", "Linear, GitLab, Bitbucket, Azure DevOps, Gitea, and Jira live in Settings > Integrations.")}
+ {translate(
+ 'auto.components.onboarding.IntegrationsStep.277f30eb34',
+ 'Linear, GitLab, Bitbucket, Azure DevOps, Gitea, and Jira live in Settings > Integrations.'
+ )}
+
diff --git a/src/renderer/src/components/onboarding/NotificationStep.tsx b/src/renderer/src/components/onboarding/NotificationStep.tsx
index 41b3d3412e4..afdfcd3c37e 100644
--- a/src/renderer/src/components/onboarding/NotificationStep.tsx
+++ b/src/renderer/src/components/onboarding/NotificationStep.tsx
@@ -118,7 +118,12 @@ export function NotificationStep({
})
if (!result.played) {
if (mountedRef.current) {
- toast.error(translate("auto.components.onboarding.NotificationStep.b6a994e36e", "Notification sound could not be played"))
+ toast.error(
+ translate(
+ 'auto.components.onboarding.NotificationStep.b6a994e36e',
+ 'Notification sound could not be played'
+ )
+ )
}
}
}
@@ -149,7 +154,12 @@ export function NotificationStep({
const handleSendTestNotification = async (): Promise => {
if (!notificationSettings) {
- toast.error(translate("auto.components.onboarding.NotificationStep.3cd5374e22", "Notification settings are still loading"))
+ toast.error(
+ translate(
+ 'auto.components.onboarding.NotificationStep.3cd5374e22',
+ 'Notification settings are still loading'
+ )
+ )
return
}
await sendNotificationSettingsTestNotification(notificationSettings, getCustomSoundVolume())
@@ -158,7 +168,11 @@ export function NotificationStep({
if (!notificationSettings) {
return (
- {translate("auto.components.onboarding.NotificationStep.e52aacf380", "Loading notification settings…")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.e52aacf380',
+ 'Loading notification settings…'
+ )}
+
)
}
@@ -175,9 +189,17 @@ export function NotificationStep({
- {translate("auto.components.onboarding.NotificationStep.d2dba86837", "Allow Orca in macOS")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.d2dba86837',
+ 'Allow Orca in macOS'
+ )}
+
- {translate("auto.components.onboarding.NotificationStep.aa36281b00", "Open System Settings and make sure Orca is allowed to send notifications.")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.aa36281b00',
+ 'Open System Settings and make sure Orca is allowed to send notifications.'
+ )}
+
void handleMacPermission()}
>
- {translate("auto.components.onboarding.NotificationStep.8124d085a6", "Open Mac Settings")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.8124d085a6',
+ 'Open Mac Settings'
+ )}
+
) : null}
-
{translate("auto.components.onboarding.NotificationStep.0af746e41f", "Choose a sound")}
+
+ {translate('auto.components.onboarding.NotificationStep.0af746e41f', 'Choose a sound')}
+
- {translate("auto.components.onboarding.NotificationStep.0fe570690c", "Pick the alert Orca plays after a desktop notification is delivered.")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.0fe570690c',
+ 'Pick the alert Orca plays after a desktop notification is delivered.'
+ )}
+
- {translate("auto.components.onboarding.NotificationStep.53aaffe49a", "Notification Sound")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.53aaffe49a',
+ 'Notification Sound'
+ )}
+
-
+
- {customPath ? translate("auto.components.onboarding.NotificationStep.ac80d97e02", "Change Custom File") : translate("auto.components.onboarding.NotificationStep.c0692baa52", "Choose Custom File")}
+
+ {customPath
+ ? translate(
+ 'auto.components.onboarding.NotificationStep.ac80d97e02',
+ 'Change Custom File'
+ )
+ : translate(
+ 'auto.components.onboarding.NotificationStep.c0692baa52',
+ 'Choose Custom File'
+ )}
+
@@ -242,7 +293,11 @@ export function NotificationStep({
onClick={() => void handleSendTestNotification()}
>
- {translate("auto.components.onboarding.NotificationStep.3bede04483", "Send Test Notification")}
+ {translate(
+ 'auto.components.onboarding.NotificationStep.3bede04483',
+ 'Send Test Notification'
+ )}
+
diff --git a/src/renderer/src/components/onboarding/OnboardingFlow.tsx b/src/renderer/src/components/onboarding/OnboardingFlow.tsx
index 28538494863..791cf11d624 100644
--- a/src/renderer/src/components/onboarding/OnboardingFlow.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingFlow.tsx
@@ -17,21 +17,41 @@ import { translate } from '@/i18n/i18n'
const stepCopy = {
agent: {
- title: translate("auto.components.onboarding.OnboardingFlow.198b148b3c", "Pick your default agent"),
- subtitle:
- translate("auto.components.onboarding.OnboardingFlow.322fc50a18", "Orca works with every CLI agent. Choose the one you'll reach for most. Switch any time.")
+ title: translate(
+ 'auto.components.onboarding.OnboardingFlow.198b148b3c',
+ 'Pick your default agent'
+ ),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.322fc50a18',
+ "Orca works with every CLI agent. Choose the one you'll reach for most. Switch any time."
+ )
},
theme: {
- title: translate("auto.components.onboarding.OnboardingFlow.f396db9f20", "Make it feel like home"),
- subtitle: translate("auto.components.onboarding.OnboardingFlow.04ae28d8ca", "Pick the look you want to stare at for hours.")
+ title: translate(
+ 'auto.components.onboarding.OnboardingFlow.f396db9f20',
+ 'Make it feel like home'
+ ),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.04ae28d8ca',
+ 'Pick the look you want to stare at for hours.'
+ )
},
notifications: {
- title: translate("auto.components.onboarding.OnboardingFlow.b054332836", "Set up notifications"),
- subtitle: translate("auto.components.onboarding.OnboardingFlow.ff92d15436", "Orca will notify you know when agents are done or need help.")
+ title: translate(
+ 'auto.components.onboarding.OnboardingFlow.b054332836',
+ 'Set up notifications'
+ ),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.ff92d15436',
+ 'Orca will notify you know when agents are done or need help.'
+ )
},
integrations: {
- title: translate("auto.components.onboarding.OnboardingFlow.ae3b00ca82", "Set up GitHub tasks"),
- subtitle: translate("auto.components.onboarding.OnboardingFlow.97c42cda00", "Install the GitHub CLI to:")
+ title: translate('auto.components.onboarding.OnboardingFlow.ae3b00ca82', 'Set up GitHub tasks'),
+ subtitle: translate(
+ 'auto.components.onboarding.OnboardingFlow.97c42cda00',
+ 'Install the GitHub CLI to:'
+ )
}
} as const
@@ -137,7 +157,10 @@ export default function OnboardingFlow({
-
{translate("auto.components.onboarding.OnboardingFlow.a249f81538", "Orca")}
+
{translate('auto.components.onboarding.OnboardingFlow.a249f81538', 'Orca')}
@@ -176,7 +199,11 @@ export default function OnboardingFlow({
? 'w-6 bg-muted-foreground/70 hover:bg-foreground/80'
: 'w-6 bg-muted-foreground/25 hover:bg-muted-foreground/45'
)}
- aria-label={translate("auto.components.onboarding.OnboardingFlow.adaa0aa627", "Go to onboarding step {{value0}}: {{value1}}", { value0: visibleIdx + 1, value1: stepCopy[step.id].title })}
+ aria-label={translate(
+ 'auto.components.onboarding.OnboardingFlow.adaa0aa627',
+ 'Go to onboarding step {{value0}}: {{value1}}',
+ { value0: visibleIdx + 1, value1: stepCopy[step.id].title }
+ )}
aria-current={isActive ? 'step' : undefined}
onClick={() => flow.jumpToStep(realStepIndex)}
/>
@@ -189,7 +216,8 @@ export default function OnboardingFlow({
})}
- {flow.visibleStepIndex + 1} {translate("auto.components.onboarding.OnboardingFlow.4db04f2f57", "of")}{' '}
+ {flow.visibleStepIndex + 1}{' '}
+ {translate('auto.components.onboarding.OnboardingFlow.4db04f2f57', 'of')}{' '}
{flow.visibleSteps.length}
@@ -197,7 +225,11 @@ export default function OnboardingFlow({
{stepIndex === 0 && (
- {translate("auto.components.onboarding.OnboardingFlow.1b5e182e9f", "Welcome to Orca")}
+ {translate(
+ 'auto.components.onboarding.OnboardingFlow.1b5e182e9f',
+ 'Welcome to Orca'
+ )}
+
)}
{copy.title}
@@ -217,7 +249,7 @@ export default function OnboardingFlow({
cn('scrollbar-sleek overflow-y-auto pr-1', 'mt-10')
)}
>
- {currentStep.id === "agent" && (
+ {currentStep.id === 'agent' && (
)}
- {currentStep.id === "theme" && (
+ {currentStep.id === 'theme' && (
)}
- {currentStep.id === "notifications" && (
+ {currentStep.id === 'notifications' && (
)}
- {currentStep.id === "integrations" && }
+ {currentStep.id === 'integrations' && }
- {translate("auto.components.onboarding.OnboardingFooter.111d3f8d92", "Skip to project setup")}
+ {translate(
+ 'auto.components.onboarding.OnboardingFooter.111d3f8d92',
+ 'Skip to project setup'
+ )}
+
) : (
)}
@@ -46,7 +50,8 @@ export function OnboardingFooter({
onClick={onBack}
>
- {translate("auto.components.onboarding.OnboardingFooter.ba58547306", "Back")}
+ {translate('auto.components.onboarding.OnboardingFooter.ba58547306', 'Back')}
+
)}
{showPrimary && (
- {translate("auto.components.onboarding.OnboardingInlineCommandTerminal.4123609efd", "Starting terminal...")}
+ {translate(
+ 'auto.components.onboarding.OnboardingInlineCommandTerminal.4123609efd',
+ 'Starting terminal...'
+ )}
+
)}
diff --git a/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx b/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
index ba3a3270c34..4b7d2602ded 100644
--- a/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingSkipConfirmationDialog.tsx
@@ -10,8 +10,14 @@ import {
import { translate } from '@/i18n/i18n'
export const ONBOARDING_SKIP_CONFIRMATION_COPY = {
- title: translate("auto.components.onboarding.OnboardingSkipConfirmationDialog.e4726b2d50", "Skip onboarding?"),
- description: translate("auto.components.onboarding.OnboardingSkipConfirmationDialog.9f47f345a4", "It won't take long!"),
+ title: translate(
+ 'auto.components.onboarding.OnboardingSkipConfirmationDialog.e4726b2d50',
+ 'Skip onboarding?'
+ ),
+ description: translate(
+ 'auto.components.onboarding.OnboardingSkipConfirmationDialog.9f47f345a4',
+ "It won't take long!"
+ ),
skipLabel: 'Skip',
keepGoingLabel: 'No, keep going'
} as const
diff --git a/src/renderer/src/components/onboarding/OnboardingTourStep.tsx b/src/renderer/src/components/onboarding/OnboardingTourStep.tsx
index ca94b92431a..a9f2b43065b 100644
--- a/src/renderer/src/components/onboarding/OnboardingTourStep.tsx
+++ b/src/renderer/src/components/onboarding/OnboardingTourStep.tsx
@@ -85,7 +85,8 @@ export function OnboardingTourStep({
disabled={Boolean(busyLabel)}
onClick={onExitTour}
>
- {translate("auto.components.onboarding.OnboardingTourStep.60c5576353", "Exit tour")}
+ {translate('auto.components.onboarding.OnboardingTourStep.60c5576353', 'Exit tour')}
+
}
/>
)
@@ -95,7 +96,8 @@ export function OnboardingTourStep({
- {translate("auto.components.onboarding.OnboardingTourStep.3f9586c043", "Take the tour")}
+ {translate('auto.components.onboarding.OnboardingTourStep.3f9586c043', 'Take the tour')}
+
)
diff --git a/src/renderer/src/components/pet/PetOverlay.tsx b/src/renderer/src/components/pet/PetOverlay.tsx
index 9d26bc6cd02..7dfc27c3781 100644
--- a/src/renderer/src/components/pet/PetOverlay.tsx
+++ b/src/renderer/src/components/pet/PetOverlay.tsx
@@ -68,7 +68,13 @@ function SpriteFrame({
const duration = Math.max(0.1, frames / Math.max(0.1, sprite.fps))
return (
<>
-
+
{sprite ? (
- {allSelected ? translate("auto.components.repo.NestedRepoChecklist.929734aea5", "Deselect all") : translate("auto.components.repo.NestedRepoChecklist.91b5bcadb6", "Select all")}
+ {allSelected
+ ? translate('auto.components.repo.NestedRepoChecklist.929734aea5', 'Deselect all')
+ : translate('auto.components.repo.NestedRepoChecklist.91b5bcadb6', 'Select all')}
- {selectedCount} {translate("auto.components.repo.NestedRepoChecklist.ea54c7bf8f", "of")} {total} {translate("auto.components.repo.NestedRepoChecklist.f7e1170567", "selected")}
+ {selectedCount} {translate('auto.components.repo.NestedRepoChecklist.ea54c7bf8f', 'of')}{' '}
+ {total} {translate('auto.components.repo.NestedRepoChecklist.f7e1170567', 'selected')}
+
)
}
diff --git a/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx b/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx
index 3f3856a0ed9..59066a6675b 100644
--- a/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx
+++ b/src/renderer/src/components/repo/NestedRepoScanLimitNotice.tsx
@@ -31,12 +31,25 @@ export function NestedRepoScanLimitNotice({ scan }: { scan: NestedRepoScanResult
onFocusCapture={() => setDetailsOpen(true)}
onBlurCapture={() => setDetailsOpen(false)}
>
-
{scan.stopped ? translate("auto.components.repo.NestedRepoScanLimitNotice.03e9beab7b", "Scan stopped early.") : translate("auto.components.repo.NestedRepoScanLimitNotice.574eb5408b", "Showing partial scan results.")}
+
+ {scan.stopped
+ ? translate(
+ 'auto.components.repo.NestedRepoScanLimitNotice.03e9beab7b',
+ 'Scan stopped early.'
+ )
+ : translate(
+ 'auto.components.repo.NestedRepoScanLimitNotice.574eb5408b',
+ 'Showing partial scan results.'
+ )}
+
) : (
- {selectedCount} {translate("auto.components.right.sidebar.BulkActionBar.60ed678138", "selected")}
+
+ {selectedCount}{' '}
+ {translate('auto.components.right.sidebar.BulkActionBar.60ed678138', 'selected')}
+
)}
@@ -40,7 +43,8 @@ export function BulkActionBar({
disabled={isExecuting}
>
- {translate("auto.components.right.sidebar.BulkActionBar.ef5f5bd06e", "Stage (")}{stageableCount})
+ {translate('auto.components.right.sidebar.BulkActionBar.ef5f5bd06e', 'Stage (')}
+ {stageableCount})
)}
{unstageableCount > 0 && (
@@ -53,7 +57,8 @@ export function BulkActionBar({
disabled={isExecuting}
>
- {translate("auto.components.right.sidebar.BulkActionBar.79a9f5f712", "Unstage (")}{unstageableCount})
+ {translate('auto.components.right.sidebar.BulkActionBar.79a9f5f712', 'Unstage (')}
+ {unstageableCount})
)}
- {translate("auto.components.right.sidebar.FileExplorer.79b1537dd3", "Select a workspace to browse files")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorer.79b1537dd3',
+ 'Select a workspace to browse files'
+ )}
+
)
}
diff --git a/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx b/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx
index c4494c427af..c661dac8a50 100644
--- a/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx
+++ b/src/renderer/src/components/right-sidebar/FileExplorerBackgroundMenu.tsx
@@ -50,10 +50,18 @@ export function FileExplorerBackgroundMenu({
>
onStartNew('file', worktreePath, 0)}>
- {translate("auto.components.right.sidebar.FileExplorerBackgroundMenu.21fe46ed36", "New File")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerBackgroundMenu.21fe46ed36',
+ 'New File'
+ )}
+
onStartNew('folder', worktreePath, 0)}>
- {translate("auto.components.right.sidebar.FileExplorerBackgroundMenu.3b5e2dcb8d", "New Folder")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerBackgroundMenu.3b5e2dcb8d',
+ 'New Folder'
+ )}
+
)
diff --git a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx
index a502cbadbf0..1b706415b4e 100644
--- a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx
+++ b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx
@@ -203,7 +203,7 @@ export function InlineInputRow({
style={{ paddingLeft: `${depth * 16 + 8}px` }}
>
- {inlineInput.type === "folder" ? (
+ {inlineInput.type === 'folder' ? (
) : (
@@ -319,16 +319,32 @@ export async function downloadRemoteFile(node: TreeNode, connectionId: string):
if (result.canceled) {
return
}
- toast.success(translate("auto.components.right.sidebar.FileExplorerRow.bce4d4e44f", "Downloaded '{{value0}}'", { value0: node.name }), {
- action: {
- label: translate("auto.components.right.sidebar.FileExplorerRow.1a3df04ae1", "Open"),
- onClick: () => {
- void window.api.shell.openPath(result.destinationPath)
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.FileExplorerRow.bce4d4e44f',
+ "Downloaded '{{value0}}'",
+ { value0: node.name }
+ ),
+ {
+ action: {
+ label: translate('auto.components.right.sidebar.FileExplorerRow.1a3df04ae1', 'Open'),
+ onClick: () => {
+ void window.api.shell.openPath(result.destinationPath)
+ }
}
}
- })
+ )
} catch (error) {
- toast.error(extractIpcErrorMessage(error, translate("auto.components.right.sidebar.FileExplorerRow.b3e288bf41", "Failed to download '{{value0}}'.", { value0: node.name })))
+ toast.error(
+ extractIpcErrorMessage(
+ error,
+ translate(
+ 'auto.components.right.sidebar.FileExplorerRow.b3e288bf41',
+ "Failed to download '{{value0}}'.",
+ { value0: node.name }
+ )
+ )
+ )
}
}
@@ -539,7 +555,10 @@ export function FileExplorerRow({
) : isIgnored ? (
@@ -553,41 +572,62 @@ export function FileExplorerRow({
>
onStartNew('file', targetDir, targetDepth)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.37c875d827", "New File")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.37c875d827', 'New File')}
+
onStartNew('folder', targetDir, targetDepth)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.f61af83316", "New Folder")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.f61af83316', 'New Folder')}
+
onCopyPaths('absolute')}>
- {selectionSize > 1 ? translate("auto.components.right.sidebar.FileExplorerRow.f9d7ca753d", "Copy Paths") : translate("auto.components.right.sidebar.FileExplorerRow.b5d436aa30", "Copy Path")}
- {copyPathShortcutLabel !== "Unassigned" ? (
+ {selectionSize > 1
+ ? translate('auto.components.right.sidebar.FileExplorerRow.f9d7ca753d', 'Copy Paths')
+ : translate('auto.components.right.sidebar.FileExplorerRow.b5d436aa30', 'Copy Path')}
+ {copyPathShortcutLabel !== 'Unassigned' ? (
{copyPathShortcutLabel}
) : null}
onCopyPaths('relative')}>
- {selectionSize > 1 ? translate("auto.components.right.sidebar.FileExplorerRow.42e10cbf57", "Copy Relative Paths") : translate("auto.components.right.sidebar.FileExplorerRow.66a29dde82", "Copy Relative Path")}
- {copyRelativePathShortcutLabel !== "Unassigned" ? (
+ {selectionSize > 1
+ ? translate(
+ 'auto.components.right.sidebar.FileExplorerRow.42e10cbf57',
+ 'Copy Relative Paths'
+ )
+ : translate(
+ 'auto.components.right.sidebar.FileExplorerRow.66a29dde82',
+ 'Copy Relative Path'
+ )}
+ {copyRelativePathShortcutLabel !== 'Unassigned' ? (
{copyRelativePathShortcutLabel}
) : null}
{!node.isDirectory && (
onDuplicate(node)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.0fec99bfd7", "Duplicate")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.0fec99bfd7', 'Duplicate')}
+
)}
{canAddAsProject && (
- {translate("auto.components.right.sidebar.FileExplorerRow.1bb9be455c", "Add as Project...")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.1bb9be455c',
+ 'Add as Project...'
+ )}
+
)}
{!node.isDirectory && activeWorktreeId && (
- {translate("auto.components.right.sidebar.FileExplorerRow.dd112c81d2", "Open in Orca Browser")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.dd112c81d2',
+ 'Open in Orca Browser'
+ )}
+
)}
- {!node.isDirectory && activeWorktreeId && detectLanguage(node.path) === "markdown" && (
+ {!node.isDirectory && activeWorktreeId && detectLanguage(node.path) === 'markdown' && (
openMarkdownPreview({
@@ -599,23 +639,35 @@ export function FileExplorerRow({
}
>
- {translate("auto.components.right.sidebar.FileExplorerRow.d87a4c42e1", "Open Markdown Preview")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.d87a4c42e1',
+ 'Open Markdown Preview'
+ )}
+
)}
{showRemoteDownloadAction && (
- {translate("auto.components.right.sidebar.FileExplorerRow.c2112579f6", "Download")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.c2112579f6', 'Download')}
)}
{shouldShowCollapseFolderAction(node, isExpanded) && (
- {translate("auto.components.right.sidebar.FileExplorerRow.d6a25618aa", "Collapse Folder")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.d6a25618aa',
+ 'Collapse Folder'
+ )}
+
)}
{shouldShowFindInFolderAction(node) && (
- {translate("auto.components.right.sidebar.FileExplorerRow.0df0e5abac", "Find in Folder")}{findInFolderShortcutLabel !== "Unassigned" ? (
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerRow.0df0e5abac',
+ 'Find in Folder'
+ )}
+ {findInFolderShortcutLabel !== 'Unassigned' ? (
{findInFolderShortcutLabel}
) : null}
@@ -646,11 +698,17 @@ export function FileExplorerRow({
onStartRename(node)}>
- {translate("auto.components.right.sidebar.FileExplorerRow.fc747429bf", "Rename")}{isMac ? '↩' : translate("auto.components.right.sidebar.FileExplorerRow.a06551beee", "Enter")}
+ {translate('auto.components.right.sidebar.FileExplorerRow.fc747429bf', 'Rename')}
+
+ {isMac
+ ? '↩'
+ : translate('auto.components.right.sidebar.FileExplorerRow.a06551beee', 'Enter')}
+
- {translate("auto.components.right.sidebar.FileExplorerRow.addc01145f", "Delete")}{deleteShortcutLabel}
+ {translate('auto.components.right.sidebar.FileExplorerRow.addc01145f', 'Delete')}
+ {deleteShortcutLabel}
diff --git a/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx b/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx
index d9d1e77ea67..341b2e0a472 100644
--- a/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx
+++ b/src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx
@@ -58,7 +58,10 @@ export function FileExplorerToolbar({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.right.sidebar.FileExplorerToolbar.6026b16950", "Collapse All")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.6026b16950',
+ 'Collapse All'
+ )}
disabled={!canCollapseAll}
onClick={onCollapseAll}
>
@@ -66,7 +69,11 @@ export function FileExplorerToolbar({
- {translate("auto.components.right.sidebar.FileExplorerToolbar.6026b16950", "Collapse All")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.6026b16950',
+ 'Collapse All'
+ )}
+
@@ -75,7 +82,10 @@ export function FileExplorerToolbar({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28", "Refresh Explorer")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28',
+ 'Refresh Explorer'
+ )}
disabled={refresh.isRefreshing}
onClick={refresh.handleRefresh}
>
@@ -87,7 +97,11 @@ export function FileExplorerToolbar({
- {translate("auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28", "Refresh Explorer")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.d95e30fe28',
+ 'Refresh Explorer'
+ )}
+
@@ -98,24 +112,39 @@ export function FileExplorerToolbar({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d", "More Explorer Actions")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d',
+ 'More Explorer Actions'
+ )}
>
- {translate("auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d", "More Explorer Actions")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.31b4c3195d',
+ 'More Explorer Actions'
+ )}
+
- {translate("auto.components.right.sidebar.FileExplorerToolbar.78f133232c", "Show Dotfiles")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.78f133232c',
+ 'Show Dotfiles'
+ )}
+
{showGitIgnoredFilesToggle ? (
- {translate("auto.components.right.sidebar.FileExplorerToolbar.d238264654", "Show Git Ignored Files")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerToolbar.d238264654',
+ 'Show Git Ignored Files'
+ )}
+
) : null}
- {translate("auto.components.right.sidebar.FileExplorerTreeStatus.c76693e456", "Could not load files for this workspace:")}{error}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerTreeStatus.c76693e456',
+ 'Could not load files for this workspace:'
+ )}
+ {error}
)
}
@@ -32,7 +36,11 @@ export function FileExplorerTreeStatus({
if (isEmpty) {
return (
- {translate("auto.components.right.sidebar.FileExplorerTreeStatus.ce03835e1f", "No files in this workspace")}
+ {translate(
+ 'auto.components.right.sidebar.FileExplorerTreeStatus.ce03835e1f',
+ 'No files in this workspace'
+ )}
+
)
}
diff --git a/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx b/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx
index 072806cddd0..6eea947b4c6 100644
--- a/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx
+++ b/src/renderer/src/components/right-sidebar/GitHistoryGraphSvg.tsx
@@ -169,7 +169,7 @@ export function GitHistoryGraphSvg({
viewBox={`0 0 ${width} ${SWIMLANE_HEIGHT}`}
>
{paths}
- {viewModel.kind === "HEAD" && (
+ {viewModel.kind === 'HEAD' && (
<>
>
)}
- {!isBoundaryNode && viewModel.kind !== "HEAD" && isMergeNode && (
+ {!isBoundaryNode && viewModel.kind !== 'HEAD' && isMergeNode && (
<>
>
)}
- {!isBoundaryNode && viewModel.kind !== "HEAD" && !isMergeNode && (
+ {!isBoundaryNode && viewModel.kind !== 'HEAD' && !isMergeNode && (
)}
diff --git a/src/renderer/src/components/right-sidebar/SearchFilters.tsx b/src/renderer/src/components/right-sidebar/SearchFilters.tsx
index e7c9ef0a151..c12b248f6ec 100644
--- a/src/renderer/src/components/right-sidebar/SearchFilters.tsx
+++ b/src/renderer/src/components/right-sidebar/SearchFilters.tsx
@@ -22,12 +22,16 @@ export function SearchFilters({
- {translate("auto.components.right.sidebar.SearchFilters.a69ee1bd0e", "Files To Include")}
+ {translate('auto.components.right.sidebar.SearchFilters.a69ee1bd0e', 'Files To Include')}
+
onIncludeChange(e.target.value)}
spellCheck={false}
@@ -35,12 +39,16 @@ export function SearchFilters({
- {translate("auto.components.right.sidebar.SearchFilters.0a6412a895", "Files To Exclude")}
+ {translate('auto.components.right.sidebar.SearchFilters.0a6412a895', 'Files To Exclude')}
+
onExcludeChange(e.target.value)}
spellCheck={false}
diff --git a/src/renderer/src/components/right-sidebar/SearchHeader.tsx b/src/renderer/src/components/right-sidebar/SearchHeader.tsx
index a30d64eac4b..1d84adfc574 100644
--- a/src/renderer/src/components/right-sidebar/SearchHeader.tsx
+++ b/src/renderer/src/components/right-sidebar/SearchHeader.tsx
@@ -54,7 +54,7 @@ export function SearchHeader({
ref={inputRef}
type="text"
className="flex-1 bg-transparent text-xs py-1.5 outline-none text-foreground placeholder:text-muted-foreground/50 min-w-0"
- placeholder={translate("auto.components.right.sidebar.SearchHeader.693cbeadd0", "Search")}
+ placeholder={translate('auto.components.right.sidebar.SearchHeader.693cbeadd0', 'Search')}
value={query}
onChange={onQueryChange}
onKeyDown={onKeyDown}
@@ -74,13 +74,31 @@ export function SearchHeader({
)}
-
+
-
+
-
+
diff --git a/src/renderer/src/components/right-sidebar/SearchResultItems.tsx b/src/renderer/src/components/right-sidebar/SearchResultItems.tsx
index ce60f34336d..588c12a9611 100644
--- a/src/renderer/src/components/right-sidebar/SearchResultItems.tsx
+++ b/src/renderer/src/components/right-sidebar/SearchResultItems.tsx
@@ -105,7 +105,11 @@ export function FileResultRow({
onClick={() => window.api.ui.writeClipboardText(fileResult.relativePath)}
>
- {translate("auto.components.right.sidebar.SearchResultItems.3596b9668d", "Copy Path")}
+ {translate(
+ 'auto.components.right.sidebar.SearchResultItems.3596b9668d',
+ 'Copy Path'
+ )}
+
{/* Why: the row label intentionally truncates long parent paths to
@@ -200,7 +204,11 @@ export function MatchResultRow({
onClick={() => window.api.ui.writeClipboardText(`${relativePath}#L${match.line}`)}
>
- {translate("auto.components.right.sidebar.SearchResultItems.cc06595a3b", "Copy Line Path")}
+ {translate(
+ 'auto.components.right.sidebar.SearchResultItems.cc06595a3b',
+ 'Copy Line Path'
+ )}
+
)
diff --git a/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx b/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx
index 7ef7ab9c82f..f3bb32767ab 100644
--- a/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx
+++ b/src/renderer/src/components/right-sidebar/SourceControlTextGenerationDialog.tsx
@@ -101,7 +101,13 @@ export function SourceControlTextGenerationDialog({
operation: actionId,
discoveryHostKey
})
- : { ok: false as const, error: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.d054d5e0a0", "Settings are not loaded.") },
+ : {
+ ok: false as const,
+ error: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.d054d5e0a0',
+ 'Settings are not loaded.'
+ )
+ },
[actionId, discoveryHostKey, repo, settings]
)
const baseParams = resolved.ok ? resolved.value.params : null
@@ -115,19 +121,28 @@ export function SourceControlTextGenerationDialog({
? [
{
target: { type: 'repo', repoId: repo.id },
- label: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.5959da1e4d", "Save for this repository only"),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.5959da1e4d',
+ 'Save for this repository only'
+ ),
successMessage: `Saved ${recipeLabel} for this repository.`
},
{
target: { type: 'global' },
- label: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.7f1ec309a4", "Save as default for all repositories"),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.7f1ec309a4',
+ 'Save as default for all repositories'
+ ),
successMessage: `Saved ${recipeLabel} as a global default.`
}
]
: [
{
target: { type: 'global' },
- label: translate("auto.components.right.sidebar.SourceControlTextGenerationDialog.c5b7fa7cb6", "Save as global default"),
+ label: translate(
+ 'auto.components.right.sidebar.SourceControlTextGenerationDialog.c5b7fa7cb6',
+ 'Save as global default'
+ ),
successMessage: `Saved ${recipeLabel} as a global default.`
}
]
diff --git a/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx b/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx
index 2769eb5c60a..d6fe74e71e6 100644
--- a/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx
+++ b/src/renderer/src/components/right-sidebar/activity-bar-buttons.tsx
@@ -57,7 +57,10 @@ export function TopActivityOverflowMenu({
'relative flex h-[36px] w-8 shrink-0 items-center justify-center text-muted-foreground/60 transition-colors hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
RIGHT_SIDEBAR_HEADER_NO_DRAG_CLASS_NAME
)}
- aria-label={translate("auto.components.right.sidebar.activity.bar.buttons.1fd284e931", "More sidebar tabs")}
+ aria-label={translate(
+ 'auto.components.right.sidebar.activity.bar.buttons.1fd284e931',
+ 'More sidebar tabs'
+ )}
>
{hiddenChecksStatus && (
@@ -124,7 +127,7 @@ export function ActivityBarButton({
>
- {statusIndicator && statusIndicator !== "neutral" && (
+ {statusIndicator && statusIndicator !== 'neutral' && (
{onCancel && (
- {translate("auto.components.right.sidebar.right.panel.comment.composer.9bca633dee", "Cancel")}
+ {translate(
+ 'auto.components.right.sidebar.right.panel.comment.composer.9bca633dee',
+ 'Cancel'
+ )}
+
)}
@@ -236,7 +275,12 @@ export function RightPanelCommentComposer({
disabled={disabled || submitting || body.trim().length === 0}
onClick={() => void submit()}
>
- {submitting ? translate("auto.components.right.sidebar.right.panel.comment.composer.87aff03d63", "Sending...") : submitLabel}
+ {submitting
+ ? translate(
+ 'auto.components.right.sidebar.right.panel.comment.composer.87aff03d63',
+ 'Sending...'
+ )
+ : submitLabel}
diff --git a/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts b/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts
index effd60f344d..191c7544482 100644
--- a/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts
+++ b/src/renderer/src/components/right-sidebar/source-control-ai-commit-failure-launch.ts
@@ -42,7 +42,12 @@ export async function launchCommitFailureAgentWithDefault({
}): Promise {
const connectionId = getConnectionId(activeWorktreeId) ?? sourceRepoConnectionId ?? null
if (connectionId === undefined) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.216f762bd7", "Unable to resolve the workspace connection."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.216f762bd7',
+ 'Unable to resolve the workspace connection.'
+ )
+ )
return false
}
@@ -59,7 +64,12 @@ export async function launchCommitFailureAgentWithDefault({
return false
}
if (!commitFailureRecoveryPrompt) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.4f4e0418a0", "Could not build the agent prompt."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.4f4e0418a0',
+ 'Could not build the agent prompt.'
+ )
+ )
return false
}
const prompt = buildCommitFailureAgentCommandInput({
@@ -68,7 +78,12 @@ export async function launchCommitFailureAgentWithDefault({
basePrompt: commitFailureRecoveryPrompt
})
if (!prompt) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.f2b47026e8", "Commit failure prompt is empty. Update Source Control AI settings."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.f2b47026e8',
+ 'Commit failure prompt is empty. Update Source Control AI settings.'
+ )
+ )
return false
}
@@ -82,7 +97,12 @@ export async function launchCommitFailureAgentWithDefault({
(!detectedAgents.includes(savedAgent) ||
!isTuiAgentEnabled(savedAgent, store.settings?.disabledTuiAgents))
) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.d481ab22f9", "Saved AI agent is unavailable. Use Customize launch to choose another agent."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.d481ab22f9',
+ 'Saved AI agent is unavailable. Use Customize launch to choose another agent.'
+ )
+ )
return false
}
const agent = pickSourceControlLaunchAgent({
@@ -92,7 +112,12 @@ export async function launchCommitFailureAgentWithDefault({
disabledAgents: store.settings?.disabledTuiAgents
})
if (!agent) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.9bbd9077a2", "No enabled AI agents. Configure agents in Settings."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.9bbd9077a2',
+ 'No enabled AI agents. Configure agents in Settings.'
+ )
+ )
return false
}
const result = launchAgentInNewTab({
@@ -106,13 +131,23 @@ export async function launchCommitFailureAgentWithDefault({
launchSource: 'source_control_recovery'
})
if (!result) {
- toast.error(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.5540ff50cc", "Could not build the agent launch command."))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.5540ff50cc',
+ 'Could not build the agent launch command.'
+ )
+ )
return false
}
if (result.tabId) {
focusTerminalTabSurface(result.tabId)
}
- toast.success(translate("auto.components.right.sidebar.source.control.ai.commit.failure.launch.a8b97d2318", "Started an AI agent for the commit failure."))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.source.control.ai.commit.failure.launch.a8b97d2318',
+ 'Started an AI agent for the commit failure.'
+ )
+ )
return true
}
diff --git a/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts b/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts
index 4ad03735794..ff020c434ec 100644
--- a/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts
+++ b/src/renderer/src/components/right-sidebar/source-control-discard-confirmation.ts
@@ -18,24 +18,44 @@ export function getDiscardEntryConfirmationCopy(
// Orca's discard path removes the working-tree file in those cases.
if (entry.area === 'untracked' || entry.status === 'untracked' || entry.status === 'added') {
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.96c772bee9", "Delete \"{{value0}}\"?", { value0: name }),
- description: translate("auto.components.right.sidebar.source.control.discard.confirmation.d97bf697c9", "This will permanently delete this file. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.96c772bee9',
+ 'Delete "{{value0}}"?',
+ { value0: name }
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.d97bf697c9',
+ 'This will permanently delete this file. This cannot be undone.'
+ ),
confirmLabel: 'Delete'
}
}
if (entry.status === 'deleted') {
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.5c0bdbc4cb", "Restore \"{{value0}}\"?", { value0: name }),
- description:
- translate("auto.components.right.sidebar.source.control.discard.confirmation.40e9357b2a", "This will restore the file from HEAD and discard the deletion. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.5c0bdbc4cb',
+ 'Restore "{{value0}}"?',
+ { value0: name }
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.40e9357b2a',
+ 'This will restore the file from HEAD and discard the deletion. This cannot be undone.'
+ ),
confirmLabel: 'Restore'
}
}
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.d4df3a61df", "Discard changes to \"{{value0}}\"?", { value0: name }),
- description: translate("auto.components.right.sidebar.source.control.discard.confirmation.1426c2efff", "This will revert all changes to this file. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.d4df3a61df',
+ 'Discard changes to "{{value0}}"?',
+ { value0: name }
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.1426c2efff',
+ 'This will revert all changes to this file. This cannot be undone.'
+ ),
confirmLabel: 'Discard'
}
}
@@ -56,14 +76,22 @@ export function getDiscardAreaConfirmationCopy(
}
case 'staged':
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.5ddd8cac7f", "Discard all staged changes?"),
- description:
- translate("auto.components.right.sidebar.source.control.discard.confirmation.ddf36f291c", "This will unstage and revert all staged changes. Staged new files will be deleted. This cannot be undone."),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.5ddd8cac7f',
+ 'Discard all staged changes?'
+ ),
+ description: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.ddf36f291c',
+ 'This will unstage and revert all staged changes. Staged new files will be deleted. This cannot be undone.'
+ ),
confirmLabel: 'Discard all'
}
case 'unstaged':
return {
- title: translate("auto.components.right.sidebar.source.control.discard.confirmation.2ae5a785b3", "Discard all unstaged changes?"),
+ title: translate(
+ 'auto.components.right.sidebar.source.control.discard.confirmation.2ae5a785b3',
+ 'Discard all unstaged changes?'
+ ),
description:
count === 1
? 'This will revert the unstaged changes in 1 file. This cannot be undone.'
diff --git a/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx b/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx
index 0df1cfa58b8..6741a72ac55 100644
--- a/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx
+++ b/src/renderer/src/components/right-sidebar/source-control-discard-dialog.tsx
@@ -72,15 +72,32 @@ export function SourceControlDiscardDialog({
>
- {pendingDiscardCopy?.title ?? translate("auto.components.right.sidebar.source.control.discard.dialog.1551c14668", "Discard changes?")}
+ {pendingDiscardCopy?.title ??
+ translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.1551c14668',
+ 'Discard changes?'
+ )}
- {pendingDiscardCopy?.description ?? translate("auto.components.right.sidebar.source.control.discard.dialog.0d2d88cba5", "This cannot be undone.")}
+ {pendingDiscardCopy?.description ??
+ translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.0d2d88cba5',
+ 'This cannot be undone.'
+ )}
{pendingDiscard?.kind === 'area' ? (
- {pendingDiscard.paths.length} {pendingDiscard.paths.length === 1 ? translate("auto.components.right.sidebar.source.control.discard.dialog.e7611dca35", "file") : translate("auto.components.right.sidebar.source.control.discard.dialog.42f89dd030", "files")}
+ {pendingDiscard.paths.length}{' '}
+ {pendingDiscard.paths.length === 1
+ ? translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.e7611dca35',
+ 'file'
+ )
+ : translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.42f89dd030',
+ 'files'
+ )}
) : pendingDiscard?.kind === 'entry' ? (
@@ -89,7 +106,11 @@ export function SourceControlDiscardDialog({
) : null}
- {translate("auto.components.right.sidebar.source.control.discard.dialog.3bc61dc989", "Cancel")}
+ {translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.3bc61dc989',
+ 'Cancel'
+ )}
+
- {pendingDiscardCopy?.confirmLabel ?? translate("auto.components.right.sidebar.source.control.discard.dialog.15efa778e3", "Discard")}
+ {pendingDiscardCopy?.confirmLabel ??
+ translate(
+ 'auto.components.right.sidebar.source.control.discard.dialog.15efa778e3',
+ 'Discard'
+ )}
diff --git a/src/renderer/src/components/right-sidebar/use-source-control-ai.ts b/src/renderer/src/components/right-sidebar/use-source-control-ai.ts
index 45d54f2a3b2..2f596283388 100644
--- a/src/renderer/src/components/right-sidebar/use-source-control-ai.ts
+++ b/src/renderer/src/components/right-sidebar/use-source-control-ai.ts
@@ -160,7 +160,12 @@ export function useSourceControlAi({
return
}
if (unresolvedConflicts.length === 0) {
- toast.message(translate("auto.components.right.sidebar.use.source.control.ai.cfafa92509", "No unresolved conflicts to send."))
+ toast.message(
+ translate(
+ 'auto.components.right.sidebar.use.source.control.ai.cfafa92509',
+ 'No unresolved conflicts to send.'
+ )
+ )
return
}
setResolveConflictsComposerOpen(true)
diff --git a/src/renderer/src/components/right-sidebar/useFileDeletion.ts b/src/renderer/src/components/right-sidebar/useFileDeletion.ts
index a01de54ad0a..f46a2f09e1a 100644
--- a/src/renderer/src/components/right-sidebar/useFileDeletion.ts
+++ b/src/renderer/src/components/right-sidebar/useFileDeletion.ts
@@ -84,9 +84,16 @@ export function useFileDeletion({
? `Permanently delete '${node.name}' and all its contents? This cannot be undone.`
: `Permanently delete '${node.name}'? This cannot be undone.`
const confirmed = await confirm({
- title: translate("auto.components.right.sidebar.useFileDeletion.d979a4fbb5", "Permanently delete '{{value0}}'?", { value0: node.name }),
+ title: translate(
+ 'auto.components.right.sidebar.useFileDeletion.d979a4fbb5',
+ "Permanently delete '{{value0}}'?",
+ { value0: node.name }
+ ),
description: message,
- confirmLabel: translate("auto.components.right.sidebar.useFileDeletion.92276aceb7", "Delete"),
+ confirmLabel: translate(
+ 'auto.components.right.sidebar.useFileDeletion.92276aceb7',
+ 'Delete'
+ ),
confirmVariant: 'destructive'
})
if (!confirmed) {
@@ -185,15 +192,35 @@ export function useFileDeletion({
// to reflect that so users aren't misled into thinking they can
// recover a remote file from a Trash/Recycle Bin that doesn't exist.
if (isRemote) {
- toast.success(translate("auto.components.right.sidebar.useFileDeletion.74727df633", "'{{value0}}' deleted", { value0: node.name }))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.useFileDeletion.74727df633',
+ "'{{value0}}' deleted",
+ { value0: node.name }
+ )
+ )
} else {
const destination = isWindows ? 'Recycle Bin' : 'Trash'
- toast.success(translate("auto.components.right.sidebar.useFileDeletion.96affe1302", "'{{value0}}' moved to {{value1}}", { value0: node.name, value1: destination }))
+ toast.success(
+ translate(
+ 'auto.components.right.sidebar.useFileDeletion.96affe1302',
+ "'{{value0}}' moved to {{value1}}",
+ { value0: node.name, value1: destination }
+ )
+ )
}
return true
} catch (error) {
const action = isRemote ? 'delete' : isWindows ? 'move to Recycle Bin' : 'move to Trash'
- toast.error(error instanceof Error ? error.message : translate("auto.components.right.sidebar.useFileDeletion.72691dfebc", "Failed to {{value0}} '{{value1}}'.", { value0: action, value1: node.name }))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.right.sidebar.useFileDeletion.72691dfebc',
+ "Failed to {{value0}} '{{value1}}'.",
+ { value0: action, value1: node.name }
+ )
+ )
return false
} finally {
inFlightRef.current.delete(node.path)
diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts b/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts
index 29f400472e3..175b40b5766 100644
--- a/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts
+++ b/src/renderer/src/components/right-sidebar/useFileExplorerHandlers.ts
@@ -75,7 +75,12 @@ export async function activateFileExplorerNode(args: {
try {
targetIsDirectory = (await statPath(node.path)).isDirectory
} catch {
- toast.error(translate("auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991", "Cannot open symlink target"))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991',
+ 'Cannot open symlink target'
+ )
+ )
return
}
if (targetIsDirectory) {
@@ -87,7 +92,12 @@ export async function activateFileExplorerNode(args: {
markPathAsDirectory(node.path)
toggleDir(activeWorktreeId, node.path)
} else {
- toast.error(translate("auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991", "Cannot open symlink target"))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerHandlers.32cd9fd991',
+ 'Cannot open symlink target'
+ )
+ )
}
return
}
diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts b/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts
index 7ca9f218923..2b314c536cf 100644
--- a/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts
+++ b/src/renderer/src/components/right-sidebar/useFileExplorerImport.ts
@@ -91,10 +91,22 @@ export function useFileExplorerImport({
if (failed.length > 0) {
const noun = failed.length === 1 ? 'file' : 'files'
- toast.error(translate("auto.components.right.sidebar.useFileExplorerImport.132fd0e1e9", "Failed to import {{value0}} {{value1}}.", { value0: failed.length, value1: noun }))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerImport.132fd0e1e9',
+ 'Failed to import {{value0}} {{value1}}.',
+ { value0: failed.length, value1: noun }
+ )
+ )
} else if (skipped.length > 0 && imported.length === 0) {
const noun = skipped.length === 1 ? 'file' : 'files'
- toast.error(translate("auto.components.right.sidebar.useFileExplorerImport.25919b2050", "Skipped {{value0}} {{value1}}.", { value0: skipped.length, value1: noun }))
+ toast.error(
+ translate(
+ 'auto.components.right.sidebar.useFileExplorerImport.25919b2050',
+ 'Skipped {{value0}} {{value1}}.',
+ { value0: skipped.length, value1: noun }
+ )
+ )
}
} catch (err) {
toast.error(extractIpcErrorMessage(err, 'Failed to import files.'))
diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts b/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts
index 34a00120e58..c2105f78850 100644
--- a/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts
+++ b/src/renderer/src/components/right-sidebar/useFileExplorerKeys.ts
@@ -149,7 +149,14 @@ export function useFileExplorerKeys(opts: {
e.preventDefault()
const run = wantRedo ? redoFileExplorer() : undoFileExplorer()
void run.catch((err: unknown) => {
- toast.error(err instanceof Error ? err.message : translate("auto.components.right.sidebar.useFileExplorerKeys.8adb953095", "Operation failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.right.sidebar.useFileExplorerKeys.8adb953095',
+ 'Operation failed'
+ )
+ )
})
return
}
diff --git a/src/renderer/src/components/settings/AgentLocationSetting.tsx b/src/renderer/src/components/settings/AgentLocationSetting.tsx
index 124f39eda50..fa7d1c072f9 100644
--- a/src/renderer/src/components/settings/AgentLocationSetting.tsx
+++ b/src/renderer/src/components/settings/AgentLocationSetting.tsx
@@ -36,7 +36,10 @@ function getSelectedAgentRuntime(
settings.localAgentRuntime ?? (settings.terminalWindowsShell === 'wsl.exe' ? 'wsl' : 'host')
if (wslSupportedPlatform && configuredRuntime === 'wsl') {
if (!wslAvailable && !wslCapabilitiesLoading) {
- return { runtime: 'wsl', label: translate("auto.components.settings.AgentLocationSetting.43663b5e69", "WSL") }
+ return {
+ runtime: 'wsl',
+ label: translate('auto.components.settings.AgentLocationSetting.43663b5e69', 'WSL')
+ }
}
const configuredDistro =
settings.localAgentWslDistro?.trim() || settings.terminalWindowsWslDistro?.trim() || null
@@ -80,17 +83,30 @@ export function AgentLocationSetting({
return (
updateAgentLocation({ localAgentRuntime: value })}
equalWidth
@@ -100,14 +116,17 @@ export function AgentLocationSetting({
? [
{
value: 'wsl',
- label: translate("auto.components.settings.AgentLocationSetting.43663b5e69", "WSL"),
+ label: translate(
+ 'auto.components.settings.AgentLocationSetting.43663b5e69',
+ 'WSL'
+ ),
disabled: wslCapabilitiesLoading || !wslAvailable
} as const
]
: [])
]}
/>
- {wslSupportedPlatform && agentRuntime.runtime === "wsl" ? (
+ {wslSupportedPlatform && agentRuntime.runtime === 'wsl' ? (
@@ -120,11 +139,26 @@ export function AgentLocationSetting({
>
- {translate("auto.components.settings.AgentLocationSetting.92f4238f1a", "WSL default")}
+
+ {translate(
+ 'auto.components.settings.AgentLocationSetting.92f4238f1a',
+ 'WSL default'
+ )}
+
{wslDistros.map((distro) => (
{distro}
diff --git a/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx b/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx
index 35172b770a0..fca5d39fec5 100644
--- a/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx
+++ b/src/renderer/src/components/settings/AgentSkillSetupPanel.tsx
@@ -132,9 +132,21 @@ export function AgentSkillSetupPanel({
const copyInstallCommand = async (): Promise => {
try {
await window.api.ui.writeClipboardText(command)
- toast.success(translate("auto.components.settings.AgentSkillSetupPanel.378ad26865", "Copied install command."))
+ toast.success(
+ translate(
+ 'auto.components.settings.AgentSkillSetupPanel.378ad26865',
+ 'Copied install command.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.AgentSkillSetupPanel.a31e2aa302", "Failed to copy install command."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.AgentSkillSetupPanel.a31e2aa302',
+ 'Failed to copy install command.'
+ )
+ )
}
}
@@ -173,7 +185,8 @@ export function AgentSkillSetupPanel({
disabled={loading}
>
- {translate("auto.components.settings.AgentSkillSetupPanel.c689392435", "Re-check")}
+ {translate('auto.components.settings.AgentSkillSetupPanel.c689392435', 'Re-check')}
+
) : null}
)
@@ -205,11 +218,26 @@ export function AgentSkillSetupPanel({
{title}
{loading && !installed ? (
- {translate("auto.components.settings.AgentSkillSetupPanel.68a468752e", "Checking...")}
+
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.68a468752e',
+ 'Checking...'
+ )}
+
) : installed ? (
- {translate("auto.components.settings.AgentSkillSetupPanel.9fcebceb2a", "Installed")}
+
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.9fcebceb2a',
+ 'Installed'
+ )}
+
) : (
- {translate("auto.components.settings.AgentSkillSetupPanel.5289300939", "Not installed")}
+
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.5289300939',
+ 'Not installed'
+ )}
+
)}
{error ? {error}
: null}
@@ -252,21 +280,31 @@ export function AgentSkillSetupPanel({
variant="ghost"
size="icon-sm"
className="shrink-0"
- aria-label={translate("auto.components.settings.AgentSkillSetupPanel.817d3f9f18", "Copy install command")}
+ aria-label={translate(
+ 'auto.components.settings.AgentSkillSetupPanel.817d3f9f18',
+ 'Copy install command'
+ )}
onClick={() => void copyInstallCommand()}
>
- {translate("auto.components.settings.AgentSkillSetupPanel.ed197f59a2", "Copy command")}
+ {translate(
+ 'auto.components.settings.AgentSkillSetupPanel.ed197f59a2',
+ 'Copy command'
+ )}
+
- onChange(getOffsetIcon(selected, -1))}>
+ onChange(getOffsetIcon(selected, -1))}
+ >
- onChange(getOffsetIcon(selected, 1))}>
+ onChange(getOffsetIcon(selected, 1))}
+ >
diff --git a/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx b/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx
index 84e3d34d9d5..2cf73e5436c 100644
--- a/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx
+++ b/src/renderer/src/components/settings/AutoRenameBranchPromptEditor.tsx
@@ -31,16 +31,25 @@ export function AutoRenameBranchPromptEditor({
// divide-y divider the way the model/prompt rows are spaced.
-
{translate("auto.components.settings.AutoRenameBranchPromptEditor.7d6176f506", "Prompt")}
+
+ {translate('auto.components.settings.AutoRenameBranchPromptEditor.7d6176f506', 'Prompt')}
+
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.2f5dc661fe", "Appended to Orca's")}{' '}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.2f5dc661fe',
+ "Appended to Orca's"
+ )}{' '}
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.182d419b97", "built-in branch-name prompt")}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.182d419b97',
+ 'built-in branch-name prompt'
+ )}
+
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.af2d9a2cc6", ". Orca generates only the final segment, like")}{' '}
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.ebb942a2ec", "fix-login-flow")}{translate("auto.components.settings.AutoRenameBranchPromptEditor.39278f4411", "; your branch prefix setting still applies.")}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.af2d9a2cc6',
+ '. Orca generates only the final segment, like'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.ebb942a2ec',
+ 'fix-login-flow'
+ )}
+
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.39278f4411',
+ '; your branch prefix setting still applies.'
+ )}
+
onDraftChange(event.target.value)}
- placeholder={translate("auto.components.settings.AutoRenameBranchPromptEditor.4416b25d29", "Prefer domain nouns from the task, avoid ticket IDs, and keep names reviewer-friendly.")}
+ placeholder={translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.4416b25d29',
+ 'Prefer domain nouns from the task, avoid ticket IDs, and keep names reviewer-friendly.'
+ )}
className="w-full resize-y rounded-md border border-border bg-background px-2 py-1.5 text-xs text-foreground outline-none placeholder:text-muted-foreground/70 focus-visible:ring-1 focus-visible:ring-ring"
/>
-
{dirty ? translate("auto.components.settings.AutoRenameBranchPromptEditor.0691753cf2", "Unsaved changes") : translate("auto.components.settings.AutoRenameBranchPromptEditor.af0831a590", "Saved")}
+
+ {dirty
+ ? translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.0691753cf2',
+ 'Unsaved changes'
+ )
+ : translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.af0831a590',
+ 'Saved'
+ )}
+
{dirty ? (
- {translate("auto.components.settings.AutoRenameBranchPromptEditor.63121132c0", "Discard")}
+ {translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.63121132c0',
+ 'Discard'
+ )}
+
) : null}
void onSave()}
disabled={!dirty || saving}
>
- {saving ? translate("auto.components.settings.AutoRenameBranchPromptEditor.54ac229ad4", "Saving...") : translate("auto.components.settings.AutoRenameBranchPromptEditor.5968112152", "Save")}
+ {saving
+ ? translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.54ac229ad4',
+ 'Saving...'
+ )
+ : translate(
+ 'auto.components.settings.AutoRenameBranchPromptEditor.5968112152',
+ 'Save'
+ )}
diff --git a/src/renderer/src/components/settings/BaseRefPicker.tsx b/src/renderer/src/components/settings/BaseRefPicker.tsx
index b94bb4cad5f..6c0513e5dbe 100644
--- a/src/renderer/src/components/settings/BaseRefPicker.tsx
+++ b/src/renderer/src/components/settings/BaseRefPicker.tsx
@@ -116,14 +116,25 @@ export function BaseRefPicker({
- {effectiveBaseRef ?? translate("auto.components.settings.BaseRefPicker.ee110e1830", "No default base ref")}
+ {effectiveBaseRef ??
+ translate('auto.components.settings.BaseRefPicker.ee110e1830', 'No default base ref')}
{currentBaseRef
- ? translate("auto.components.settings.BaseRefPicker.2f3cda96f5", "Pinned for this repo")
+ ? translate(
+ 'auto.components.settings.BaseRefPicker.2f3cda96f5',
+ 'Pinned for this repo'
+ )
: defaultBaseRef
- ? translate("auto.components.settings.BaseRefPicker.086ce7f369", "Following primary branch ({{value0}})", { value0: defaultBaseRef })
- : translate("auto.components.settings.BaseRefPicker.9a14ec7400", "Pick a base branch below")}
+ ? translate(
+ 'auto.components.settings.BaseRefPicker.086ce7f369',
+ 'Following primary branch ({{value0}})',
+ { value0: defaultBaseRef }
+ )
+ : translate(
+ 'auto.components.settings.BaseRefPicker.9a14ec7400',
+ 'Pick a base branch below'
+ )}
{/* Why: passive hint that fork workflows have other remotes worth
searching (e.g. `upstream`). Host-agnostic and remote-name-agnostic
@@ -137,24 +148,48 @@ export function BaseRefPicker({
// whenever remoteCount>1, not a dynamic status update. aria-live would
// cause screen readers to re-announce it on every mount/repo switch.
- {translate("auto.components.settings.BaseRefPicker.a5c16712c1", "Multiple remotes detected. Type a remote name (e.g.")}{translate("auto.components.settings.BaseRefPicker.915ad97875", "upstream")}{translate("auto.components.settings.BaseRefPicker.80f7c82303", ") or a full ref (e.g.")}{translate("auto.components.settings.BaseRefPicker.b468f46726", "upstream/main")}{translate("auto.components.settings.BaseRefPicker.ade9a5bb03", ") to scope results.")}
+ {translate(
+ 'auto.components.settings.BaseRefPicker.a5c16712c1',
+ 'Multiple remotes detected. Type a remote name (e.g.'
+ )}
+
+ {translate('auto.components.settings.BaseRefPicker.915ad97875', 'upstream')}
+
+ {translate(
+ 'auto.components.settings.BaseRefPicker.80f7c82303',
+ ') or a full ref (e.g.'
+ )}
+
+ {translate('auto.components.settings.BaseRefPicker.b468f46726', 'upstream/main')}
+
+ {translate(
+ 'auto.components.settings.BaseRefPicker.ade9a5bb03',
+ ') to scope results.'
+ )}
+
) : null}
{onUsePrimary && (
- {translate("auto.components.settings.BaseRefPicker.773a5687a3", "Use Primary")}
+ {translate('auto.components.settings.BaseRefPicker.773a5687a3', 'Use Primary')}
+
)}
setBaseRefQuery(e.target.value)}
- placeholder={translate("auto.components.settings.BaseRefPicker.7db7fb87e5", "Search branches by name...")}
+ placeholder={translate(
+ 'auto.components.settings.BaseRefPicker.7db7fb87e5',
+ 'Search branches by name...'
+ )}
className="max-w-md"
/>
{isSearchingBaseRefs ? (
- {translate("auto.components.settings.BaseRefPicker.a4a9372eb2", "Searching branches...")}
+
+ {translate('auto.components.settings.BaseRefPicker.a4a9372eb2', 'Searching branches...')}
+
) : null}
{!isSearchingBaseRefs && baseRefQuery.trim().length >= 2 ? (
@@ -182,14 +217,21 @@ export function BaseRefPicker({
>
{ref}
{effectiveBaseRef === ref ? (
- {translate("auto.components.settings.BaseRefPicker.d166ff883d", "Current")}
+
+ {translate('auto.components.settings.BaseRefPicker.d166ff883d', 'Current')}
+
) : null}
))}
) : (
- {translate("auto.components.settings.BaseRefPicker.1b8e54151f", "No matching branches found.")}
+
+ {translate(
+ 'auto.components.settings.BaseRefPicker.1b8e54151f',
+ 'No matching branches found.'
+ )}
+
)
) : null}
diff --git a/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx b/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx
index b078f6d4188..6c7ef5c5b2a 100644
--- a/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx
+++ b/src/renderer/src/components/settings/BrowserDefaultZoomSetting.tsx
@@ -21,14 +21,30 @@ export function BrowserDefaultZoomSetting({
return (
-
{translate("auto.components.settings.BrowserDefaultZoomSetting.265597101f", "Default Zoom")}
-
{translate("auto.components.settings.BrowserDefaultZoomSetting.bbeec087d3", "Applied to newly opened browser tabs.")}
+
+ {translate(
+ 'auto.components.settings.BrowserDefaultZoomSetting.265597101f',
+ 'Default Zoom'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.BrowserDefaultZoomSetting.bbeec087d3',
+ 'Applied to newly opened browser tabs.'
+ )}
+
onChange(Number(next))}>
diff --git a/src/renderer/src/components/settings/BrowserHomePageSetting.tsx b/src/renderer/src/components/settings/BrowserHomePageSetting.tsx
index c589ce204af..f0b25262ea6 100644
--- a/src/renderer/src/components/settings/BrowserHomePageSetting.tsx
+++ b/src/renderer/src/components/settings/BrowserHomePageSetting.tsx
@@ -20,15 +20,30 @@ export function BrowserHomePageSetting({
}: BrowserHomePageSettingProps): React.JSX.Element {
return (
-
{translate("auto.components.settings.BrowserHomePageSetting.70224e37b1", "Default Home Page")}
+
+ {translate(
+ 'auto.components.settings.BrowserHomePageSetting.70224e37b1',
+ 'Default Home Page'
+ )}
+
- {translate("auto.components.settings.BrowserHomePageSetting.6a37540f4b", "URL opened when creating a new browser tab. Leave empty to open a blank tab.")}
+ {translate(
+ 'auto.components.settings.BrowserHomePageSetting.6a37540f4b',
+ 'URL opened when creating a new browser tab. Leave empty to open a blank tab.'
+ )}
+
onChange(event.target.value)}
- placeholder={translate("auto.components.settings.BrowserHomePageSetting.37a30c5bfd", "https://google.com")}
+ placeholder={translate(
+ 'auto.components.settings.BrowserHomePageSetting.37a30c5bfd',
+ 'https://google.com'
+ )}
spellCheck={false}
autoCapitalize="none"
autoCorrect="off"
className="h-7 w-52 text-xs"
/>
- {translate("auto.components.settings.BrowserHomePageSetting.d4ddcd0056", "Save")}
+ {translate('auto.components.settings.BrowserHomePageSetting.d4ddcd0056', 'Save')}
+
)
diff --git a/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx b/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx
index 1d7d5bd3e24..c498caf9fef 100644
--- a/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx
+++ b/src/renderer/src/components/settings/BrowserUseComputerUseNotice.tsx
@@ -11,9 +11,18 @@ export function BrowserUseComputerUseNotice({
-
{translate("auto.components.settings.BrowserUseComputerUseNotice.333984cf90", "Use an existing browser session")}
+
+ {translate(
+ 'auto.components.settings.BrowserUseComputerUseNotice.333984cf90',
+ 'Use an existing browser session'
+ )}
+
- {translate("auto.components.settings.BrowserUseComputerUseNotice.79209b37b9", "If cookie import is not the right fit, Computer Use can control local apps and may use existing logged-in browser sessions where applicable. Install the Computer Use skill; macOS also requires privacy permissions.")}
+ {translate(
+ 'auto.components.settings.BrowserUseComputerUseNotice.79209b37b9',
+ 'If cookie import is not the right fit, Computer Use can control local apps and may use existing logged-in browser sessions where applicable. Install the Computer Use skill; macOS also requires privacy permissions.'
+ )}
+
- {translate("auto.components.settings.BrowserUseComputerUseNotice.15b5e680ba", "Open Computer Use")}
+ {translate(
+ 'auto.components.settings.BrowserUseComputerUseNotice.15b5e680ba',
+ 'Open Computer Use'
+ )}
+
)
diff --git a/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx b/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx
index 36a965900ae..cbb4c3361b4 100644
--- a/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx
+++ b/src/renderer/src/components/settings/BrowserUseEnableSwitch.tsx
@@ -10,7 +10,10 @@ export function BrowserUseEnableSwitch({
{
try {
await window.api.ui.writeClipboardText(text)
- toast.success(translate("auto.components.settings.BrowserUseExamples.a602d43069", "Copied {{value0}}.", { value0: label }))
+ toast.success(
+ translate('auto.components.settings.BrowserUseExamples.a602d43069', 'Copied {{value0}}.', {
+ value0: label
+ })
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.BrowserUseExamples.5ec620ccc4", "Failed to copy."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate('auto.components.settings.BrowserUseExamples.5ec620ccc4', 'Failed to copy.')
+ )
}
}
@@ -24,10 +32,19 @@ export function BrowserUseExamples(): React.JSX.Element {
-
{translate("auto.components.settings.BrowserUseExamples.2a180694f7", "Try it — example prompts")}
+
+ {translate(
+ 'auto.components.settings.BrowserUseExamples.2a180694f7',
+ 'Try it — example prompts'
+ )}
+
- {translate("auto.components.settings.BrowserUseExamples.c5325e91f6", "Paste any of these into Claude Code, Codex, or another agent in a project where the skill is installed.")}
+ {translate(
+ 'auto.components.settings.BrowserUseExamples.c5325e91f6',
+ 'Paste any of these into Claude Code, Codex, or another agent in a project where the skill is installed.'
+ )}
+
- {updateStatus.state === 'idle' && translate("auto.components.settings.GeneralUpdateSettingsSection.d69a09b672", "Updates are checked automatically on launch.")}
- {updateStatus.state === 'checking' && translate("auto.components.settings.GeneralUpdateSettingsSection.31fd7150cf", "Checking for updates...")}
+ {updateStatus.state === 'idle' &&
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.d69a09b672',
+ 'Updates are checked automatically on launch.'
+ )}
+ {updateStatus.state === 'checking' &&
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.31fd7150cf',
+ 'Checking for updates...'
+ )}
{updateStatus.state === 'available' && (
<>
- {translate("auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc", "Version")}{updateStatus.version} {translate("auto.components.settings.GeneralUpdateSettingsSection.8311da27ba", "is available. Click \"Install Update\" to download and install it.")}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc',
+ 'Version'
+ )}
+ {updateStatus.version}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.8311da27ba',
+ 'is available. Click "Install Update" to download and install it.'
+ )}{' '}
- {translate("auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02", "Release notes")}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02',
+ 'Release notes'
+ )}
+
>
)}
- {updateStatus.state === 'not-available' && translate("auto.components.settings.GeneralUpdateSettingsSection.f40d88390d", "You’re on the latest version.")}
+ {updateStatus.state === 'not-available' &&
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.f40d88390d',
+ 'You’re on the latest version.'
+ )}
{updateStatus.state === 'downloading' &&
- translate("auto.components.settings.GeneralUpdateSettingsSection.2a48034c4c", "Downloading v{{value0}}... {{value1}}%", { value0: updateStatus.version, value1: updateStatus.percent })}
+ translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.2a48034c4c',
+ 'Downloading v{{value0}}... {{value1}}%',
+ { value0: updateStatus.version, value1: updateStatus.percent }
+ )}
{updateStatus.state === 'downloaded' && (
<>
- {translate("auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc", "Version")}{updateStatus.version} {translate("auto.components.settings.GeneralUpdateSettingsSection.d89806cc89", "is ready to install.")}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.a6b37929dc',
+ 'Version'
+ )}
+ {updateStatus.version}{' '}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.d89806cc89',
+ 'is ready to install.'
+ )}{' '}
- {translate("auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02", "Release notes")}
+ {translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.8a52ca1d02',
+ 'Release notes'
+ )}
+
>
)}
{updateStatus.state === 'error' &&
@@ -159,8 +230,16 @@ export function GeneralUpdateSettingsSection(): React.JSX.Element {
// 'downloaded' state). Label accordingly so a download failure
// isn't mislabeled as a "check" failure. Mirrors UpdateCard.tsx.
(updateVersionRef.current
- ? translate("auto.components.settings.GeneralUpdateSettingsSection.b9ad70c30d", "Update error. {{value0}}", { value0: updateStatus.message })
- : translate("auto.components.settings.GeneralUpdateSettingsSection.bd79d412f0", "Update check failed. {{value0}}", { value0: updateStatus.message }))}
+ ? translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.b9ad70c30d',
+ 'Update error. {{value0}}',
+ { value0: updateStatus.message }
+ )
+ : translate(
+ 'auto.components.settings.GeneralUpdateSettingsSection.bd79d412f0',
+ 'Update check failed. {{value0}}',
+ { value0: updateStatus.message }
+ ))}
diff --git a/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx b/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx
index 0da472b900a..9686ac70781 100644
--- a/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx
+++ b/src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.tsx
@@ -28,17 +28,34 @@ export function GeneralWorkspaceSettingsSection({
return (
- {translate("auto.components.settings.GeneralWorkspaceSettingsSection.0e9fc0eadc", "Workspace Directory")}
+
+ {translate(
+ 'auto.components.settings.GeneralWorkspaceSettingsSection.0e9fc0eadc',
+ 'Workspace Directory'
+ )}
+
- {translate("auto.components.settings.GeneralWorkspaceSettingsSection.5567191a6e", "Browse")}
+ {translate(
+ 'auto.components.settings.GeneralWorkspaceSettingsSection.5567191a6e',
+ 'Browse'
+ )}
+
- {translate("auto.components.settings.GeneralWorkspaceSettingsSection.a246f5ce6f", "Root directory where workspace folders are created.")}
+ {translate(
+ 'auto.components.settings.GeneralWorkspaceSettingsSection.a246f5ce6f',
+ 'Root directory where workspace folders are created.'
+ )}
+
updateSettings({ nestWorkspaces: !settings.nestWorkspaces })}
/>
@@ -76,13 +113,25 @@ export function GeneralWorkspaceSettingsSection({
breaks that toast action even though this pane still renders fine. */}
updateSettings({
@@ -95,13 +144,25 @@ export function GeneralWorkspaceSettingsSection({
updateSettings({
@@ -118,8 +179,14 @@ export function GeneralWorkspaceSettingsSection({
className="scroll-mt-6"
>
- {translate("auto.components.settings.GhosttyImportModal.d2f33670a9", "Import from Ghostty")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.d2f33670a9',
+ 'Import from Ghostty'
+ )}
+
- {translate("auto.components.settings.GhosttyImportModal.2763b0c045", "Review the settings that will be imported from your Ghostty config.")}
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.2763b0c045',
+ 'Review the settings that will be imported from your Ghostty config.'
+ )}
+
{loading ? (
- {translate("auto.components.settings.GhosttyImportModal.023a52c1f7", "Loading preview…")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.023a52c1f7',
+ 'Loading preview…'
+ )}
+
) : preview == null ? null : preview.found ? (
{configPaths.length > 0 && !applied && (
- {configPaths.length === 1 ? translate("auto.components.settings.GhosttyImportModal.1f744a72f4", "Config") : translate("auto.components.settings.GhosttyImportModal.273e7e81fe", "Configs")}: {configPaths.join(', ')}
+ {configPaths.length === 1
+ ? translate('auto.components.settings.GhosttyImportModal.1f744a72f4', 'Config')
+ : translate('auto.components.settings.GhosttyImportModal.273e7e81fe', 'Configs')}
+ : {configPaths.join(', ')}
)}
{applied ? (
-
{translate("auto.components.settings.GhosttyImportModal.4466f4cdaa", "Import complete")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.4466f4cdaa',
+ 'Import complete'
+ )}
+
{Object.entries(preview.diff).map(([key, value]) => (
@@ -75,7 +97,12 @@ export function GhosttyImportModal({
) : hasChanges ? (
-
{translate("auto.components.settings.GhosttyImportModal.a4c5dec640", "Settings to update")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.a4c5dec640',
+ 'Settings to update'
+ )}
+
{Object.entries(preview.diff).map(([key, value]) => (
@@ -87,14 +114,23 @@ export function GhosttyImportModal({
) : (
- {translate("auto.components.settings.GhosttyImportModal.674b5ccd6b", "No new settings to import — your current settings already match.")}
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.674b5ccd6b',
+ 'No new settings to import — your current settings already match.'
+ )}
+
)}
{!applied && applyError &&
{applyError}
}
{!applied && preview.unsupportedKeys.length > 0 && (
-
{translate("auto.components.settings.GhosttyImportModal.b58d4c9051", "Unsupported keys")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.b58d4c9051',
+ 'Unsupported keys'
+ )}
+
{preview.unsupportedKeys.map((key) => (
@@ -108,17 +144,32 @@ export function GhosttyImportModal({
) : preview.error ? (
{preview.error}
) : (
- {translate("auto.components.settings.GhosttyImportModal.e4bda7ce6f", "No Ghostty config found on this system.")}
+
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.e4bda7ce6f',
+ 'No Ghostty config found on this system.'
+ )}
+
)}
{applied ? (
- onOpenChange(false)}>{translate("auto.components.settings.GhosttyImportModal.b7ddae600c", "Done")}
+ onOpenChange(false)}>
+ {translate('auto.components.settings.GhosttyImportModal.b7ddae600c', 'Done')}
+
) : (
<>
onOpenChange(false)}>
- {translate("auto.components.settings.GhosttyImportModal.f96688b6bc", "Cancel")}
- {hasChanges && void onApply()}>{translate("auto.components.settings.GhosttyImportModal.9d3e56ca36", "Apply Changes")} }
+ {translate('auto.components.settings.GhosttyImportModal.f96688b6bc', 'Cancel')}
+
+ {hasChanges && (
+ void onApply()}>
+ {translate(
+ 'auto.components.settings.GhosttyImportModal.9d3e56ca36',
+ 'Apply Changes'
+ )}
+
+ )}
>
)}
diff --git a/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx b/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx
index ab778e0135e..bcf702c166a 100644
--- a/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx
+++ b/src/renderer/src/components/settings/HiddenExperimentalGroup.tsx
@@ -10,20 +10,40 @@ export function HiddenExperimentalGroup(): React.JSX.Element {
- {translate("auto.components.settings.HiddenExperimentalGroup.3e9e827ca5", "Hidden experimental")}
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.3e9e827ca5',
+ 'Hidden experimental'
+ )}
+
- {translate("auto.components.settings.HiddenExperimentalGroup.232cf83de8", "Unlisted toggles for internal testing. Nothing here is supported.")}
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.232cf83de8',
+ 'Unlisted toggles for internal testing. Nothing here is supported.'
+ )}
+
-
{translate("auto.components.settings.HiddenExperimentalGroup.d0f914a528", "Placeholder toggle")}
+
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.d0f914a528',
+ 'Placeholder toggle'
+ )}
+
- {translate("auto.components.settings.HiddenExperimentalGroup.1014ddbfaf", "Does nothing today. Reserved as the first slot for hidden experimental options.")}
+ {translate(
+ 'auto.components.settings.HiddenExperimentalGroup.1014ddbfaf',
+ 'Does nothing today. Reserved as the first slot for hidden experimental options.'
+ )}
+
diff --git a/src/renderer/src/components/settings/KagiSessionLinkForm.tsx b/src/renderer/src/components/settings/KagiSessionLinkForm.tsx
index 2e5255fd7c0..d9ea1e1b4a2 100644
--- a/src/renderer/src/components/settings/KagiSessionLinkForm.tsx
+++ b/src/renderer/src/components/settings/KagiSessionLinkForm.tsx
@@ -50,17 +50,32 @@ export function KagiSessionLinkForm(): React.JSX.Element {
if (!trimmed) {
setBrowserKagiSessionLink(null)
setDraftState(createKagiSessionLinkDraftState(''))
- toast.success(translate("auto.components.settings.KagiSessionLinkForm.9f741627a7", "Kagi session link cleared."))
+ toast.success(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.9f741627a7',
+ 'Kagi session link cleared.'
+ )
+ )
return
}
const normalized = normalizeKagiSessionLink(trimmed)
if (!normalized) {
- toast.error(translate("auto.components.settings.KagiSessionLinkForm.0911d5fa4c", "Enter a Kagi private session link from https://kagi.com/search?token=..."))
+ toast.error(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.0911d5fa4c',
+ 'Enter a Kagi private session link from https://kagi.com/search?token=...'
+ )
+ )
return
}
setBrowserKagiSessionLink(normalized)
setDraftState(createKagiSessionLinkDraftState(normalized))
- toast.success(translate("auto.components.settings.KagiSessionLinkForm.3e5b7c6c25", "Kagi session link saved."))
+ toast.success(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.3e5b7c6c25',
+ 'Kagi session link saved.'
+ )
+ )
}
return (
@@ -72,22 +87,33 @@ export function KagiSessionLinkForm(): React.JSX.Element {
}}
>
- {translate("auto.components.settings.KagiSessionLinkForm.81409d9362", "Optional private session link for Kagi auth.")}
+ {translate(
+ 'auto.components.settings.KagiSessionLinkForm.81409d9362',
+ 'Optional private session link for Kagi auth.'
+ )}
+
setDraft(e.target.value)}
- placeholder={translate("auto.components.settings.KagiSessionLinkForm.e383683485", "https://kagi.com/search?token=...")}
+ placeholder={translate(
+ 'auto.components.settings.KagiSessionLinkForm.e383683485',
+ 'https://kagi.com/search?token=...'
+ )}
spellCheck={false}
autoCapitalize="none"
autoCorrect="off"
autoComplete="off"
- aria-label={translate("auto.components.settings.KagiSessionLinkForm.ff450194cd", "Kagi private session link")}
+ aria-label={translate(
+ 'auto.components.settings.KagiSessionLinkForm.ff450194cd',
+ 'Kagi private session link'
+ )}
className="h-7 w-72 text-xs"
/>
- {translate("auto.components.settings.KagiSessionLinkForm.d5c8b94c5b", "Save")}
+ {translate('auto.components.settings.KagiSessionLinkForm.d5c8b94c5b', 'Save')}
+
{browserKagiSessionLink ? (
{
setBrowserKagiSessionLink(null)
setDraftState(createKagiSessionLinkDraftState(''))
- toast.success(translate("auto.components.settings.KagiSessionLinkForm.9f741627a7", "Kagi session link cleared."))
+ toast.success(
+ translate(
+ 'auto.components.settings.KagiSessionLinkForm.9f741627a7',
+ 'Kagi session link cleared.'
+ )
+ )
}}
>
- {translate("auto.components.settings.KagiSessionLinkForm.92f0b4e472", "Clear")}
+ {translate('auto.components.settings.KagiSessionLinkForm.92f0b4e472', 'Clear')}
+
) : null}
diff --git a/src/renderer/src/components/settings/KeybindingsFileActions.tsx b/src/renderer/src/components/settings/KeybindingsFileActions.tsx
index 41b9928634f..24a6a5116da 100644
--- a/src/renderer/src/components/settings/KeybindingsFileActions.tsx
+++ b/src/renderer/src/components/settings/KeybindingsFileActions.tsx
@@ -71,7 +71,12 @@ export function KeybindingsFileActions(): React.JSX.Element {
try {
const filePath = await prepareKeybindingsPath()
if (!filePath) {
- toast.error(translate("auto.components.settings.KeybindingsFileActions.cdf794f46d", "Keybindings file is not available."))
+ toast.error(
+ translate(
+ 'auto.components.settings.KeybindingsFileActions.cdf794f46d',
+ 'Keybindings file is not available.'
+ )
+ )
return
}
const existingFile = openFiles.find(
@@ -104,7 +109,14 @@ export function KeybindingsFileActions(): React.JSX.Element {
}
})
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.KeybindingsFileActions.dd532a01ce", "Failed to open keybindings in Orca."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.KeybindingsFileActions.dd532a01ce',
+ 'Failed to open keybindings in Orca.'
+ )
+ )
}
}
@@ -112,7 +124,12 @@ export function KeybindingsFileActions(): React.JSX.Element {
try {
const filePath = await prepareKeybindingsPath()
if (!filePath) {
- toast.error(translate("auto.components.settings.KeybindingsFileActions.cdf794f46d", "Keybindings file is not available."))
+ toast.error(
+ translate(
+ 'auto.components.settings.KeybindingsFileActions.cdf794f46d',
+ 'Keybindings file is not available.'
+ )
+ )
return
}
const result = await window.api.shell.openInExternalEditor(filePath, command)
@@ -120,7 +137,14 @@ export function KeybindingsFileActions(): React.JSX.Element {
toast.error(openFailureMessage(result.reason))
}
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.KeybindingsFileActions.c5886a31cc", "Failed to open external editor."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.KeybindingsFileActions.c5886a31cc',
+ 'Failed to open external editor.'
+ )
+ )
}
}
@@ -137,7 +161,11 @@ export function KeybindingsFileActions(): React.JSX.Element {
onClick={() => void editKeybindingsInOrca()}
>
- {translate("auto.components.settings.KeybindingsFileActions.1c2be2b2c6", "Edit File in Orca")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.1c2be2b2c6',
+ 'Edit File in Orca'
+ )}
+
@@ -153,20 +184,40 @@ export function KeybindingsFileActions(): React.JSX.Element {
void openKeybindingsFile()}>
- {translate("auto.components.settings.KeybindingsFileActions.98f1a23e1c", "Open with Default App")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.98f1a23e1c',
+ 'Open with Default App'
+ )}
+
void openKeybindingsInExternalEditor('code')}>
- {translate("auto.components.settings.KeybindingsFileActions.1637f64033", "Open in VS Code")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.1637f64033',
+ 'Open in VS Code'
+ )}
+
void openKeybindingsInExternalEditor('cursor')}>
- {translate("auto.components.settings.KeybindingsFileActions.9e24c0e858", "Open in Cursor")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.9e24c0e858',
+ 'Open in Cursor'
+ )}
+
void revealKeybindingsFile()}>
- {translate("auto.components.settings.KeybindingsFileActions.a8a8d6b9d3", "Reveal in File Manager")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.a8a8d6b9d3',
+ 'Reveal in File Manager'
+ )}
+
void reloadKeybindings()}>
- {translate("auto.components.settings.KeybindingsFileActions.abc49853fb", "Reload from Disk")}
+ {translate(
+ 'auto.components.settings.KeybindingsFileActions.abc49853fb',
+ 'Reload from Disk'
+ )}
+
diff --git a/src/renderer/src/components/settings/ManageSessionKillDialog.tsx b/src/renderer/src/components/settings/ManageSessionKillDialog.tsx
index e2375c4434e..56ddb9845ee 100644
--- a/src/renderer/src/components/settings/ManageSessionKillDialog.tsx
+++ b/src/renderer/src/components/settings/ManageSessionKillDialog.tsx
@@ -56,17 +56,39 @@ export function ManageSessionKillDialog({
{session ? (
<>
- {translate("auto.components.settings.ManageSessionKillDialog.87dcafc85c", "Kill this session?")}
+
+ {translate(
+ 'auto.components.settings.ManageSessionKillDialog.87dcafc85c',
+ 'Kill this session?'
+ )}
+
- {translate("auto.components.settings.ManageSessionKillDialog.8401328fed", "Force-quits")}{session.sessionId}
- {translate("auto.components.settings.ManageSessionKillDialog.ad9832aa26", ". Any unsaved work in that pane is lost. This can't be undone.")}
+ {translate(
+ 'auto.components.settings.ManageSessionKillDialog.8401328fed',
+ 'Force-quits'
+ )}
+ {session.sessionId}
+ {translate(
+ 'auto.components.settings.ManageSessionKillDialog.ad9832aa26',
+ ". Any unsaved work in that pane is lost. This can't be undone."
+ )}
+
- {translate("auto.components.settings.ManageSessionKillDialog.6bf4627168", "Cancel")}
+ {translate('auto.components.settings.ManageSessionKillDialog.6bf4627168', 'Cancel')}
+
{isBusy ? : null}
- {isBusy ? translate("auto.components.settings.ManageSessionKillDialog.d3dba51b15", "Killing…") : translate("auto.components.settings.ManageSessionKillDialog.0b0db4c68c", "Kill session")}
+ {isBusy
+ ? translate(
+ 'auto.components.settings.ManageSessionKillDialog.d3dba51b15',
+ 'Killing…'
+ )
+ : translate(
+ 'auto.components.settings.ManageSessionKillDialog.0b0db4c68c',
+ 'Kill session'
+ )}
>
diff --git a/src/renderer/src/components/settings/McpConfigFileRow.tsx b/src/renderer/src/components/settings/McpConfigFileRow.tsx
index 025a9b87af4..632d56fc366 100644
--- a/src/renderer/src/components/settings/McpConfigFileRow.tsx
+++ b/src/renderer/src/components/settings/McpConfigFileRow.tsx
@@ -53,7 +53,7 @@ export function McpConfigFileRow({ config, onOpen }: McpConfigFileRowProps): Rea
return (
- {config.status === "valid" && !config.readError ? (
+ {config.status === 'valid' && !config.readError ? (
) : (
@@ -73,7 +73,8 @@ export function McpConfigFileRow({ config, onOpen }: McpConfigFileRowProps): Rea
{config.exists ? (
onOpen(config)}>
- {translate("auto.components.settings.McpConfigFileRow.e720c139cd", "Open")}
+ {translate('auto.components.settings.McpConfigFileRow.e720c139cd', 'Open')}
+
) : null}
@@ -100,7 +101,7 @@ export function McpConfigFileRow({ config, onOpen }: McpConfigFileRowProps): Rea
{server.env && Object.keys(server.env).length > 0 ? (
- {translate("auto.components.settings.McpConfigFileRow.b145eb6009", "env:")}{' '}
+ {translate('auto.components.settings.McpConfigFileRow.b145eb6009', 'env:')}{' '}
{Object.entries(server.env)
.map(([key, value]) => `${key}=${value}`)
.join(', ')}
diff --git a/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx b/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx
index 9e825952318..9ab5f1532d2 100644
--- a/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx
+++ b/src/renderer/src/components/settings/MobileEmulatorAgentControlRow.tsx
@@ -64,7 +64,14 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
setCliInstallStatus(await window.api.cli.getInstallStatus())
} catch (error) {
if (mountedRef.current) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.MobileEmulatorAgentControlRow.1861982430", "Failed to load CLI status."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.1861982430',
+ 'Failed to load CLI status.'
+ )
+ )
}
setCliInstallStatus(null)
} finally {
@@ -90,7 +97,12 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
onStatusChange: setCliInstallStatus
})
if (mountedRef.current && isOrcaCliAvailableOnPath(next)) {
- toast.success(translate("auto.components.settings.MobileEmulatorAgentControlRow.cdeaed9e37", "Registered the Orca CLI in PATH."))
+ toast.success(
+ translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.cdeaed9e37',
+ 'Registered the Orca CLI in PATH.'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -103,9 +115,18 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
-
{translate("auto.components.settings.MobileEmulatorAgentControlRow.2a674aa810", "Agent Mobile Emulator Control")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.2a674aa810',
+ 'Agent Mobile Emulator Control'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.ff4b7e65d6", "Let coding agents control the active mobile emulator with Orca CLI commands.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.ff4b7e65d6',
+ 'Let coding agents control the active mobile emulator with Orca CLI commands.'
+ )}
+
-
{translate("auto.components.settings.MobileEmulatorAgentControlRow.4f2205f3b6", "Enable Orca CLI")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.4f2205f3b6',
+ 'Enable Orca CLI'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.2fef055608", "Registers the Orca CLI command so agents can control the active emulator from their shell.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.2fef055608',
+ 'Registers the Orca CLI command so agents can control the active emulator from their shell.'
+ )}
+
{cliInstallStatus?.commandPath && cliEnabled ? (
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.aaf62a3dd2", "Installed at")}{' '}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.aaf62a3dd2',
+ 'Installed at'
+ )}{' '}
{cliInstallStatus.commandPath}
) : null}
@@ -163,8 +196,14 @@ export function MobileEmulatorAgentControlRow(): React.JSX.Element {
-
{translate("auto.components.settings.MobileEmulatorAgentControlRow.c7f3fe0a6e", "Common emulator commands")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.c7f3fe0a6e',
+ 'Common emulator commands'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorAgentControlRow.8af7a8bc38", "Commands target the active emulator for the current worktree. Coordinates are normalized from 0..1.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorAgentControlRow.8af7a8bc38',
+ 'Commands target the active emulator for the current worktree. Coordinates are normalized from 0..1.'
+ )}
+
{EMULATOR_CLI_COMMANDS.map((command) => (
{
try {
await window.api.ui.writeClipboardText(prompt)
- toast.success(translate("auto.components.settings.MobileEmulatorExamples.2b077b5544", "Copied prompt."))
+ toast.success(
+ translate('auto.components.settings.MobileEmulatorExamples.2b077b5544', 'Copied prompt.')
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.MobileEmulatorExamples.1f608e7d60", "Failed to copy prompt."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.MobileEmulatorExamples.1f608e7d60',
+ 'Failed to copy prompt.'
+ )
+ )
}
}
@@ -35,10 +44,19 @@ export function MobileEmulatorExamples({
>
-
{translate("auto.components.settings.MobileEmulatorExamples.0820b3f84f", "Try it — example prompts")}
+
+ {translate(
+ 'auto.components.settings.MobileEmulatorExamples.0820b3f84f',
+ 'Try it — example prompts'
+ )}
+
- {translate("auto.components.settings.MobileEmulatorExamples.4daa95f25a", "Paste any of these into Claude Code, Codex, or another agent in a project where the Orca CLI skill is installed.")}
+ {translate(
+ 'auto.components.settings.MobileEmulatorExamples.4daa95f25a',
+ 'Paste any of these into Claude Code, Codex, or another agent in a project where the Orca CLI skill is installed.'
+ )}
+
{EMULATOR_EXAMPLE_PROMPTS.map((prompt) => (
- {translate("auto.components.settings.MobileEmulatorExamples.b525ff2b12", "\"")}{prompt}{translate("auto.components.settings.MobileEmulatorExamples.d151e25078", "\"")}
+ {translate('auto.components.settings.MobileEmulatorExamples.b525ff2b12', '"')}
+ {prompt}
+ {translate('auto.components.settings.MobileEmulatorExamples.d151e25078', '"')}
+
@@ -54,14 +75,18 @@ export function MobileEmulatorExamples({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.settings.MobileEmulatorExamples.c12b253997", "Copy example prompt")}
+ aria-label={translate(
+ 'auto.components.settings.MobileEmulatorExamples.c12b253997',
+ 'Copy example prompt'
+ )}
onClick={() => void copyPrompt(prompt)}
>
- {translate("auto.components.settings.MobileEmulatorExamples.edf13dd03b", "Copy")}
+ {translate('auto.components.settings.MobileEmulatorExamples.edf13dd03b', 'Copy')}
+
diff --git a/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx b/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx
index d72a167eb37..dff685415ef 100644
--- a/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx
+++ b/src/renderer/src/components/settings/MobileNetworkInterfaceSection.tsx
@@ -37,15 +37,29 @@ export function MobileNetworkInterfaceSection({
- {translate("auto.components.settings.MobileNetworkInterfaceSection.406a35121c", "Network Interface")}
+
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.406a35121c',
+ 'Network Interface'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.d536b5e20d", "Choose which network address to advertise in the QR code. Use your LAN address for same-network pairing, or an overlay network address (Tailscale, ZeroTier) for cross-network access.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.d536b5e20d',
+ 'Choose which network address to advertise in the QR code. Use your LAN address for same-network pairing, or an overlay network address (Tailscale, ZeroTier) for cross-network access.'
+ )}
+
-
+
{networkInterfaces.map((iface) => (
@@ -65,14 +79,21 @@ export function MobileNetworkInterfaceSection({
size="icon-sm"
onClick={onRefreshNetworkInterfaces}
disabled={refreshingNetworkInterfaces}
- aria-label={translate("auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d", "Refresh network interfaces")}
+ aria-label={translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d',
+ 'Refresh network interfaces'
+ )}
className="text-muted-foreground"
>
- {translate("auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d", "Refresh network interfaces")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.a9db5d771d',
+ 'Refresh network interfaces'
+ )}
+
)}
- {hasQrCode ? translate("auto.components.settings.MobileNetworkInterfaceSection.1e64659126", "Regenerate") : translate("auto.components.settings.MobileNetworkInterfaceSection.c541f67790", "Generate QR Code")}
+ {hasQrCode
+ ? translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.1e64659126',
+ 'Regenerate'
+ )
+ : translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.c541f67790',
+ 'Generate QR Code'
+ )}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.39fad211d9", "Connect outside your Wi-Fi with a tailnet")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.39fad211d9',
+ 'Connect outside your Wi-Fi with a tailnet'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.9fc5d203ff", "Orca Mobile connects directly to this computer. To use it away from the same local network, put your computer and phone on the same private overlay network, then generate the QR code with that network address selected.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.9fc5d203ff',
+ 'Orca Mobile connects directly to this computer. To use it away from the same local network, put your computer and phone on the same private overlay network, then generate the QR code with that network address selected.'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.51d29927eb", "Install")}{' '}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.51d29927eb',
+ 'Install'
+ )}{' '}
void window.api.shell.openUrl(TAILSCALE_DOWNLOAD_URL)}
className="inline-flex items-center gap-1 font-medium text-foreground underline-offset-2 hover:underline"
>
- {translate("auto.components.settings.MobileNetworkInterfaceSection.1dc87a7fbc", "Tailscale")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.1dc87a7fbc',
+ 'Tailscale'
+ )}
+
{' '}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.668016be7a", "on your computer and phone.")}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.1f7c26d36a", "Sign in to the same tailnet on both devices.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.668016be7a',
+ 'on your computer and phone.'
+ )}
+
- {translate("auto.components.settings.MobileNetworkInterfaceSection.87985ba6f5", "In this Network Interface menu, choose the Tailscale address, usually a 100.x.y.z IP.")}
- {translate("auto.components.settings.MobileNetworkInterfaceSection.63d5e4ae1e", "Regenerate the QR code and scan it from the Orca mobile app.")}
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.1f7c26d36a',
+ 'Sign in to the same tailnet on both devices.'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.87985ba6f5',
+ 'In this Network Interface menu, choose the Tailscale address, usually a 100.x.y.z IP.'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.MobileNetworkInterfaceSection.63d5e4ae1e',
+ 'Regenerate the QR code and scan it from the Orca mobile app.'
+ )}
+
diff --git a/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx b/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx
index ace5250899d..660a42434bd 100644
--- a/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx
+++ b/src/renderer/src/components/settings/OpenAiTranscriptionKeyDialog.tsx
@@ -37,17 +37,41 @@ export function OpenAiTranscriptionKeyDialog({
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.439e91879e", "OpenAI Transcription")}
+
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.439e91879e',
+ 'OpenAI Transcription'
+ )}
+
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.07ed3e512e", "Audio is sent to OpenAI only when an OpenAI speech model is selected.")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.07ed3e512e',
+ 'Audio is sent to OpenAI only when an OpenAI speech model is selected.'
+ )}
+
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.16015322f9", "API Key")}
+
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.16015322f9',
+ 'API Key'
+ )}
+
onApiKeyDraftChange(event.target.value)}
onKeyDown={(event) => {
@@ -59,15 +83,27 @@ export function OpenAiTranscriptionKeyDialog({
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.d246b2bdb3", "Local runtime keys are stored in ~/.orca using Electron encrypted storage when available.")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.d246b2bdb3',
+ 'Local runtime keys are stored in ~/.orca using Electron encrypted storage when available.'
+ )}
+
{configured && (
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.07b26f2742", "Clear Key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.07b26f2742',
+ 'Clear Key'
+ )}
+
)}
{pending ? : null}
- {translate("auto.components.settings.OpenAiTranscriptionKeyDialog.fa83512e48", "Save Key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionKeyDialog.fa83512e48',
+ 'Save Key'
+ )}
+
diff --git a/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx b/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx
index ace152f53b2..7ea09a10f1f 100644
--- a/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx
+++ b/src/renderer/src/components/settings/OpenAiTranscriptionSettingsRow.tsx
@@ -21,26 +21,48 @@ export function OpenAiTranscriptionSettingsRow({
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.27e0cb656d", "OpenAI Transcription")}
+
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.27e0cb656d',
+ 'OpenAI Transcription'
+ )}
+
{configured && (
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.3b0ab3fc0b", "Connected")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.3b0ab3fc0b',
+ 'Connected'
+ )}
+
)}
{configured
- ? translate("auto.components.settings.OpenAiTranscriptionSettingsRow.b59b9b2b51", "API key configured for cloud speech-to-text models.")
- : translate("auto.components.settings.OpenAiTranscriptionSettingsRow.893790e13b", "Add an OpenAI API key before selecting cloud speech-to-text models.")}
+ ? translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.b59b9b2b51',
+ 'API key configured for cloud speech-to-text models.'
+ )
+ : translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.893790e13b',
+ 'Add an OpenAI API key before selecting cloud speech-to-text models.'
+ )}
{configured ? (
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.a622bc3b37", "Replace key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.a622bc3b37',
+ 'Replace key'
+ )}
+
@@ -49,7 +71,11 @@ export function OpenAiTranscriptionSettingsRow({
) : (
- {translate("auto.components.settings.OpenAiTranscriptionSettingsRow.85c589cd61", "Add API key")}
+ {translate(
+ 'auto.components.settings.OpenAiTranscriptionSettingsRow.85c589cd61',
+ 'Add API key'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx b/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx
index 5e2b72d4514..af2484aae0d 100644
--- a/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx
+++ b/src/renderer/src/components/settings/OrchestrationExamplesDialog.tsx
@@ -51,9 +51,21 @@ export function OrchestrationExampleDialog(props: {
const copyPrompt = async (prompt: string): Promise => {
try {
await window.api.ui.writeClipboardText(prompt)
- toast.success(translate("auto.components.settings.OrchestrationExamplesDialog.80c6f2feb8", "Copied example prompt."))
+ toast.success(
+ translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.80c6f2feb8',
+ 'Copied example prompt.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.OrchestrationExamplesDialog.4e46da1889", "Failed to copy prompt."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.4e46da1889',
+ 'Failed to copy prompt.'
+ )
+ )
}
}
@@ -88,7 +100,11 @@ export function OrchestrationExampleDialog(props: {
variant="ghost"
size="icon-xs"
className="absolute top-2 right-2 shrink-0 opacity-70 transition-opacity group-hover:opacity-100"
- aria-label={translate("auto.components.settings.OrchestrationExamplesDialog.969cec9739", "Copy {{value0}} example prompt", { value0: example.title })}
+ aria-label={translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.969cec9739',
+ 'Copy {{value0}} example prompt',
+ { value0: example.title }
+ )}
onClick={() => void copyPrompt(example.prompt)}
>
@@ -98,10 +114,15 @@ export function OrchestrationExampleDialog(props: {
onOpenChange(false)}>
- {translate("auto.components.settings.OrchestrationExamplesDialog.9b4c004998", "Done")}
+ {translate('auto.components.settings.OrchestrationExamplesDialog.9b4c004998', 'Done')}
+
void copyPrompt(example.prompt)}>
- {translate("auto.components.settings.OrchestrationExamplesDialog.3d1aa105e3", "Copy prompt")}
+ {translate(
+ 'auto.components.settings.OrchestrationExamplesDialog.3d1aa105e3',
+ 'Copy prompt'
+ )}
+
diff --git a/src/renderer/src/components/settings/OrchestrationSetupCard.tsx b/src/renderer/src/components/settings/OrchestrationSetupCard.tsx
index 52fc967ec84..2b9c8c4c054 100644
--- a/src/renderer/src/components/settings/OrchestrationSetupCard.tsx
+++ b/src/renderer/src/components/settings/OrchestrationSetupCard.tsx
@@ -19,8 +19,14 @@ export function OrchestrationSetupCard(props: {
const setupPanel = (
- {status.installed ? translate("auto.components.settings.OrchestrationSkillAgentCoverage.1e8f8d8fae", "Ready") : translate("auto.components.settings.OrchestrationSkillAgentCoverage.ffe13e36fb", "Missing")}
+ {status.installed
+ ? translate(
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.1e8f8d8fae',
+ 'Ready'
+ )
+ : translate(
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.ffe13e36fb',
+ 'Missing'
+ )}
)
@@ -89,7 +97,12 @@ export function OrchestrationSkillAgentCoverage(props: {
)}
>
-
{translate("auto.components.settings.OrchestrationSkillAgentCoverage.6dec5ce2d2", "Agent coverage")}
+
+ {translate(
+ 'auto.components.settings.OrchestrationSkillAgentCoverage.6dec5ce2d2',
+ 'Agent coverage'
+ )}
+
{summary}
diff --git a/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx b/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx
index 1195b6b8ea3..c1c6f2feea4 100644
--- a/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx
+++ b/src/renderer/src/components/settings/OrchestrationSkillPromptDialog.tsx
@@ -21,9 +21,21 @@ export function OrchestrationSkillPromptDialog(props: {
const copyCommand = async (): Promise => {
try {
await window.api.ui.writeClipboardText(command)
- toast.success(translate("auto.components.settings.OrchestrationSkillPromptDialog.239bf9132b", "Copied install command."))
+ toast.success(
+ translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.239bf9132b',
+ 'Copied install command.'
+ )
+ )
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.OrchestrationSkillPromptDialog.d3dc559225", "Failed to copy install command."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.d3dc559225',
+ 'Failed to copy install command.'
+ )
+ )
}
}
@@ -33,9 +45,17 @@ export function OrchestrationSkillPromptDialog(props: {
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.2914abcfa2", "Install orchestration skill")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.2914abcfa2',
+ 'Install orchestration skill'
+ )}
+
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.b99f375eb2", "Run this command in a terminal to install the orchestration skill for your agents.")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.b99f375eb2',
+ 'Run this command in a terminal to install the orchestration skill for your agents.'
+ )}
+
@@ -49,7 +69,10 @@ export function OrchestrationSkillPromptDialog(props: {
variant="ghost"
size="icon-xs"
className="absolute top-2 right-2 shrink-0 opacity-70 transition-opacity group-hover:opacity-100"
- aria-label={translate("auto.components.settings.OrchestrationSkillPromptDialog.1bdce1911e", "Copy orchestration skill install command")}
+ aria-label={translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.1bdce1911e',
+ 'Copy orchestration skill install command'
+ )}
onClick={() => void copyCommand()}
>
@@ -59,10 +82,18 @@ export function OrchestrationSkillPromptDialog(props: {
onOpenChange(false)}>
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.35550f3b3b", "Done")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.35550f3b3b',
+ 'Done'
+ )}
+
void copyCommand()}>
- {translate("auto.components.settings.OrchestrationSkillPromptDialog.f08d45293d", "Copy command")}
+ {translate(
+ 'auto.components.settings.OrchestrationSkillPromptDialog.f08d45293d',
+ 'Copy command'
+ )}
+
diff --git a/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx b/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx
index 8cd6a480ef9..54af2be9a29 100644
--- a/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx
+++ b/src/renderer/src/components/settings/PrivacyDiagnosticBundleControls.tsx
@@ -53,7 +53,11 @@ export function PrivacyDiagnosticBundleControls({
onClick={() => void onCopyTicket()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.2801d4ce22", "Copy ticket")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.2801d4ce22',
+ 'Copy ticket'
+ )}
+
void onDeleteUploadedBundle()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.7f14a1733c", "Delete bundle")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.7f14a1733c',
+ 'Delete bundle'
+ )}
+
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.2ae9a6b63e", "Done")}
+ {translate('auto.components.settings.PrivacyDiagnosticBundleControls.2ae9a6b63e', 'Done')}
+
>
)
}
@@ -79,13 +88,25 @@ export function PrivacyDiagnosticBundleControls({
onClick={() => void onOpenPreview()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.798b6f0be5", "Open preview")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.798b6f0be5',
+ 'Open preview'
+ )}
+
void onUpload()}>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.aca2c8a367", "Upload")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.aca2c8a367',
+ 'Upload'
+ )}
+
void onDiscard()}>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.a5acaffdb6", "Discard")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.a5acaffdb6',
+ 'Discard'
+ )}
+
>
)
}
@@ -98,7 +119,11 @@ export function PrivacyDiagnosticBundleControls({
onClick={() => void onCollect()}
>
} />
- {translate("auto.components.settings.PrivacyDiagnosticBundleControls.dc8404a930", "Create preview")}
+ {translate(
+ 'auto.components.settings.PrivacyDiagnosticBundleControls.dc8404a930',
+ 'Create preview'
+ )}
+
)
}
diff --git a/src/renderer/src/components/settings/PrivacyPane.tsx b/src/renderer/src/components/settings/PrivacyPane.tsx
index a6a85a1ca60..f2334e8676e 100644
--- a/src/renderer/src/components/settings/PrivacyPane.tsx
+++ b/src/renderer/src/components/settings/PrivacyPane.tsx
@@ -89,23 +89,35 @@ export function PrivacyPane({ settings }: PrivacyPaneProps): React.JSX.Element {
- {translate("auto.components.settings.PrivacyPane.fe904ac984", "Share anonymous usage data")}
+
+ {translate(
+ 'auto.components.settings.PrivacyPane.fe904ac984',
+ 'Share anonymous usage data'
+ )}
+
- {translate("auto.components.settings.PrivacyPane.8bfdd23a88", "Help us figure out what to build next. Orca sends anonymous counts of which features you use and where things break.")}{' '}
+ {translate(
+ 'auto.components.settings.PrivacyPane.8bfdd23a88',
+ 'Help us figure out what to build next. Orca sends anonymous counts of which features you use and where things break.'
+ )}{' '}
void window.api.shell.openUrl(PRIVACY_URL)}
>
- {translate("auto.components.settings.PrivacyPane.77410e0566", "Privacy policy")}
+ {translate('auto.components.settings.PrivacyPane.77410e0566', 'Privacy policy')}
+
.
- {blocked.reason === "ci" ? (
- {translate("auto.components.settings.PrivacyPane.e3970bbbf5", "Telemetry is disabled because a CI environment variable is set. Unset it and restart.")}
+ {blocked.reason === 'ci' ? (
+
+ {translate(
+ 'auto.components.settings.PrivacyPane.e3970bbbf5',
+ 'Telemetry is disabled because a CI environment variable is set. Unset it and restart.'
+ )}
+
) : (
- {translate("auto.components.settings.PrivacyPane.79a0f3c16c", "Telemetry is disabled by the")}{' '}
+ {translate(
+ 'auto.components.settings.PrivacyPane.79a0f3c16c',
+ 'Telemetry is disabled by the'
+ )}{' '}
{envVarNameForReason(blocked.reason)}
{' '}
- {translate("auto.components.settings.PrivacyPane.36e0e2e63b", "environment variable. Unset it and restart to re-enable.")}
+ {translate(
+ 'auto.components.settings.PrivacyPane.36e0e2e63b',
+ 'environment variable. Unset it and restart to re-enable.'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/settings/RecentTabOrderControl.tsx b/src/renderer/src/components/settings/RecentTabOrderControl.tsx
index f4c45b1466d..84e54c617b5 100644
--- a/src/renderer/src/components/settings/RecentTabOrderControl.tsx
+++ b/src/renderer/src/components/settings/RecentTabOrderControl.tsx
@@ -16,13 +16,16 @@ export function RecentTabOrderControl({
}): React.JSX.Element {
return (
- {translate("auto.components.settings.RecentTabOrderControl.6e6a3fcc61", "Most recent")}
- {translate("auto.components.settings.RecentTabOrderControl.3b17c81ede", "Tab strip order")}
+
+ {translate(
+ 'auto.components.settings.RecentTabOrderControl.6e6a3fcc61',
+ 'Most recent'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RecentTabOrderControl.3b17c81ede',
+ 'Tab strip order'
+ )}
+
}
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx
index 2253db0d5cd..6a22472b2ee 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiCustomCommand.tsx
@@ -29,9 +29,18 @@ export function RepositorySourceControlAiCustomCommand({
-
{translate("auto.components.settings.RepositorySourceControlAiCustomCommand.ebffc5a28c", "Custom command")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.ebffc5a28c',
+ 'Custom command'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiCustomCommand.fbb77e122a", "Repo fallback for text actions that select Custom command.")}
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.fbb77e122a',
+ 'Repo fallback for text actions that select Custom command.'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiCustomCommand.e56668c291", "Use global")}
- {translate("auto.components.settings.RepositorySourceControlAiCustomCommand.0704dd55cd", "Repository command")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.e56668c291',
+ 'Use global'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.0704dd55cd',
+ 'Repository command'
+ )}
+
@@ -60,7 +79,13 @@ export function RepositorySourceControlAiCustomCommand({
const nextValue = event.target.value
onChange(nextValue === '' ? undefined : nextValue)
}}
- placeholder={source.customAgentCommand || translate("auto.components.settings.RepositorySourceControlAiCustomCommand.f9941f0caf", "e.g. ollama run llama3.1 {prompt}")}
+ placeholder={
+ source.customAgentCommand ||
+ translate(
+ 'auto.components.settings.RepositorySourceControlAiCustomCommand.f9941f0caf',
+ 'e.g. ollama run llama3.1 {prompt}'
+ )
+ }
spellCheck={false}
className="h-8 font-mono text-xs"
/>
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx
index 66accb5d351..40befa958f2 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiEnablement.tsx
@@ -28,9 +28,27 @@ export function RepositorySourceControlAiEnablement({
return (
-
{translate("auto.components.settings.RepositorySourceControlAiEnablement.cf5959c834", "Source Control AI enabled")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.cf5959c834',
+ 'Source Control AI enabled'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.30ae6dcce8", "Global default is")}{source.enabled ? translate("auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2", "On") : translate("auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3", "Off")}.
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.30ae6dcce8',
+ 'Global default is'
+ )}
+ {source.enabled
+ ? translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2',
+ 'On'
+ )
+ : translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3',
+ 'Off'
+ )}
+ .
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.62511a575d", "Use global")}
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2", "On")}
- {translate("auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3", "Off")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.62511a575d',
+ 'Use global'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.bea897eec2',
+ 'On'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiEnablement.84233d1bb3',
+ 'Off'
+ )}
+
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
index 376c3f121f4..4a2e6aba53e 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiHostedReviewDefaults.tsx
@@ -17,10 +17,34 @@ type RepositorySourceControlAiHostedReviewDefaultsProps = {
}
const HOSTED_REVIEW_DEFAULT_ROWS: { key: HostedReviewDefaultKey; label: string }[] = [
- { key: 'draft', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.981eae7e14", "Draft by default") },
- { key: 'useTemplate', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.d32b87e754", "Use review template when available") },
- { key: 'generateDetailsOnOpen', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.14f1eb99d0", "Generate details when opening Create PR") },
- { key: 'openAfterCreate', label: translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.629ed8a9d3", "Open hosted review after creation") }
+ {
+ key: 'draft',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.981eae7e14',
+ 'Draft by default'
+ )
+ },
+ {
+ key: 'useTemplate',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.d32b87e754',
+ 'Use review template when available'
+ )
+ },
+ {
+ key: 'generateDetailsOnOpen',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.14f1eb99d0',
+ 'Generate details when opening Create PR'
+ )
+ },
+ {
+ key: 'openAfterCreate',
+ label: translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.629ed8a9d3',
+ 'Open hosted review after creation'
+ )
+ }
]
export function RepositorySourceControlAiHostedReviewDefaults({
@@ -30,7 +54,12 @@ export function RepositorySourceControlAiHostedReviewDefaults({
}: RepositorySourceControlAiHostedReviewDefaultsProps): React.JSX.Element {
return (
-
{translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.aa6ee4b7d6", "Hosted-review creation defaults")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.aa6ee4b7d6',
+ 'Hosted-review creation defaults'
+ )}
+
{HOSTED_REVIEW_DEFAULT_ROWS.map((row) => {
const inherited = source.prCreationDefaults?.[row.key] === true ? 'On' : 'Off'
@@ -42,7 +71,11 @@ export function RepositorySourceControlAiHostedReviewDefaults({
{row.label}
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.a68849a859", "Global default is")}{inherited}.
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.a68849a859',
+ 'Global default is'
+ )}
+ {inherited}.
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.ffc3b26b26", "Use global")}
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.777443bf89", "On")}
- {translate("auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.053ccfbf52", "Off")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.ffc3b26b26',
+ 'Use global'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.777443bf89',
+ 'On'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiHostedReviewDefaults.053ccfbf52',
+ 'Off'
+ )}
+
diff --git a/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx b/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx
index 852ce8f1b1c..3dccec319e6 100644
--- a/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx
+++ b/src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx
@@ -296,14 +296,31 @@ export function RepositorySourceControlAiSection({
>
-
{translate("auto.components.settings.RepositorySourceControlAiSection.71b003b62b", "Source Control AI")}
+
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.71b003b62b',
+ 'Source Control AI'
+ )}
+
- {translate("auto.components.settings.RepositorySourceControlAiSection.8b8bc5913a", "Repository action recipes. Global settings are used until this repository customizes them.")}
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.8b8bc5913a',
+ 'Repository action recipes. Global settings are used until this repository customizes them.'
+ )}
+
{saveError ?
{saveError}
: null}
- {isDirty ? translate("auto.components.settings.RepositorySourceControlAiSection.e57dde9d93", "Unsaved changes") : translate("auto.components.settings.RepositorySourceControlAiSection.ccb07dd027", "Saved")}
+ {isDirty
+ ? translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.e57dde9d93',
+ 'Unsaved changes'
+ )
+ : translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.ccb07dd027',
+ 'Saved'
+ )}
{isDirty ? (
- {translate("auto.components.settings.RepositorySourceControlAiSection.67b3ff5467", "Discard")}
+ {translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.67b3ff5467',
+ 'Discard'
+ )}
+
) : null}
void saveDraft()}
disabled={!isDirty || isSaving}
>
- {isSaving ? translate("auto.components.settings.RepositorySourceControlAiSection.57e6e9d4b1", "Saving...") : translate("auto.components.settings.RepositorySourceControlAiSection.152268c295", "Save")}
+ {isSaving
+ ? translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.57e6e9d4b1',
+ 'Saving...'
+ )
+ : translate(
+ 'auto.components.settings.RepositorySourceControlAiSection.152268c295',
+ 'Save'
+ )}
diff --git a/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx b/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx
index 16cd56e4742..82e4e4d8897 100644
--- a/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx
+++ b/src/renderer/src/components/settings/RuntimeAccessGrantList.tsx
@@ -35,7 +35,12 @@ export function RuntimeAccessGrantList({
return (
-
{translate("auto.components.settings.RuntimeAccessGrantList.f031182867", "Shared Server Access")}
+
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.f031182867',
+ 'Shared Server Access'
+ )}
+
- {translate("auto.components.settings.RuntimeAccessGrantList.27cf8507ad", "Refresh shared access")}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.27cf8507ad',
+ 'Refresh shared access'
+ )}
+
{grants.length === 0 ? (
-
{translate("auto.components.settings.RuntimeAccessGrantList.fd83b94095", "No shared server access yet.")}
+
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.fd83b94095',
+ 'No shared server access yet.'
+ )}
+
) : (
{grants.map((grant) => {
@@ -70,14 +87,30 @@ export function RuntimeAccessGrantList({
{grant.name}
{isCurrent ? (
- {translate("auto.components.settings.RuntimeAccessGrantList.434e4a6af6", "Current link")}
+
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.434e4a6af6',
+ 'Current link'
+ )}
+
) : null}
- {translate("auto.components.settings.RuntimeAccessGrantList.87b16cd11d", "Created")}{formatAccessTimestamp(grant.createdAt)} ·{' '}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.87b16cd11d',
+ 'Created'
+ )}
+ {formatAccessTimestamp(grant.createdAt)} ·{' '}
{grant.lastSeenAt
- ? translate("auto.components.settings.RuntimeAccessGrantList.b18d1764ef", "Last used {{value0}}", { value0: formatAccessTimestamp(grant.lastSeenAt) })
- : translate("auto.components.settings.RuntimeAccessGrantList.df142657a5", "Not used yet")}
+ ? translate(
+ 'auto.components.settings.RuntimeAccessGrantList.b18d1764ef',
+ 'Last used {{value0}}',
+ { value0: formatAccessTimestamp(grant.lastSeenAt) }
+ )
+ : translate(
+ 'auto.components.settings.RuntimeAccessGrantList.df142657a5',
+ 'Not used yet'
+ )}
@@ -89,7 +122,11 @@ export function RuntimeAccessGrantList({
className="text-destructive hover:text-destructive shrink-0"
onClick={() => onRevoke(grant)}
disabled={isRevoking}
- aria-label={translate("auto.components.settings.RuntimeAccessGrantList.6f6d5188ed", "Revoke {{value0}}", { value0: grant.name })}
+ aria-label={translate(
+ 'auto.components.settings.RuntimeAccessGrantList.6f6d5188ed',
+ 'Revoke {{value0}}',
+ { value0: grant.name }
+ )}
>
{isRevoking ? (
@@ -99,7 +136,11 @@ export function RuntimeAccessGrantList({
- {translate("auto.components.settings.RuntimeAccessGrantList.68ec21309f", "Revoke access")}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.68ec21309f',
+ 'Revoke access'
+ )}
+
)
@@ -108,7 +149,11 @@ export function RuntimeAccessGrantList({
)}
{grants.length > 0 ? (
- {translate("auto.components.settings.RuntimeAccessGrantList.8b82879581", "Anyone with an active grant can connect until you revoke it. Revoking shared access disconnects active clients immediately.")}
+ {translate(
+ 'auto.components.settings.RuntimeAccessGrantList.8b82879581',
+ 'Anyone with an active grant can connect until you revoke it. Revoking shared access disconnects active clients immediately.'
+ )}
+
) : null}
)
diff --git a/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx b/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx
index 281d53a3779..0e9186fd680 100644
--- a/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx
+++ b/src/renderer/src/components/settings/RuntimePairingGeneratedUrlRows.tsx
@@ -29,7 +29,11 @@ export function GeneratedUrlRow({
variant="ghost"
size="icon-xs"
onClick={onCopy}
- aria-label={translate("auto.components.settings.RuntimePairingGeneratedUrlRows.0495f68959", "Copy {{value0}}", { value0: label })}
+ aria-label={translate(
+ 'auto.components.settings.RuntimePairingGeneratedUrlRows.0495f68959',
+ 'Copy {{value0}}',
+ { value0: label }
+ )}
>
{copied ?
:
}
diff --git a/src/renderer/src/components/settings/ShortcutBindingRow.tsx b/src/renderer/src/components/settings/ShortcutBindingRow.tsx
index cbc14781458..fb1bc35b9bd 100644
--- a/src/renderer/src/components/settings/ShortcutBindingRow.tsx
+++ b/src/renderer/src/components/settings/ShortcutBindingRow.tsx
@@ -110,7 +110,11 @@ export function ShortcutBindingRow({
return (
@@ -119,7 +123,8 @@ export function ShortcutBindingRow({
{item.title}
{modified ? (
- {translate("auto.components.settings.ShortcutBindingRow.97dccee14e", "Modified")}
+ {translate('auto.components.settings.ShortcutBindingRow.97dccee14e', 'Modified')}
+
) : null}
{terminalStatus ? (
@@ -164,14 +169,22 @@ export function ShortcutBindingRow({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-foreground"
- aria-label={translate("auto.components.settings.ShortcutBindingRow.4f2c9b2a05", "Reset {{value0}} to default", { value0: item.title })}
+ aria-label={translate(
+ 'auto.components.settings.ShortcutBindingRow.4f2c9b2a05',
+ 'Reset {{value0}} to default',
+ { value0: item.title }
+ )}
onClick={() => onReset(item.id)}
>
- {translate("auto.components.settings.ShortcutBindingRow.f75335b155", "Reset to default")}
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.f75335b155',
+ 'Reset to default'
+ )}
+
) : null}
@@ -181,14 +194,22 @@ export function ShortcutBindingRow({
variant="ghost"
size="icon-xs"
className="text-muted-foreground hover:text-destructive"
- aria-label={translate("auto.components.settings.ShortcutBindingRow.3b62c142fa", "Disable {{value0}}", { value0: item.title })}
+ aria-label={translate(
+ 'auto.components.settings.ShortcutBindingRow.3b62c142fa',
+ 'Disable {{value0}}',
+ { value0: item.title }
+ )}
onClick={() => onDisable(item.id)}
>
- {translate("auto.components.settings.ShortcutBindingRow.9cdaaa3d8f", "Disable shortcut")}
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.9cdaaa3d8f',
+ 'Disable shortcut'
+ )}
+
) : null}
@@ -219,7 +240,12 @@ export function ShortcutBindingRow({
)}
>
{recording ? (
- {translate("auto.components.settings.ShortcutBindingRow.87381fd8f8", "Press keys…")}
+
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.87381fd8f8',
+ 'Press keys…'
+ )}
+
) : hasBinding ? (
{effective.map((binding) => (
@@ -229,12 +255,29 @@ export function ShortcutBindingRow({
) : (
- {translate("auto.components.settings.ShortcutBindingRow.4a4c2c9d32", "Add shortcut")}
+ {translate(
+ 'auto.components.settings.ShortcutBindingRow.4a4c2c9d32',
+ 'Add shortcut'
+ )}
+
)}
- {recording ? translate("auto.components.settings.ShortcutBindingRow.6a7848fdac", "Listening for shortcut") : hasBinding ? translate("auto.components.settings.ShortcutBindingRow.f6579be67b", "Change shortcut") : translate("auto.components.settings.ShortcutBindingRow.4a4c2c9d32", "Add shortcut")}
+ {recording
+ ? translate(
+ 'auto.components.settings.ShortcutBindingRow.6a7848fdac',
+ 'Listening for shortcut'
+ )
+ : hasBinding
+ ? translate(
+ 'auto.components.settings.ShortcutBindingRow.f6579be67b',
+ 'Change shortcut'
+ )
+ : translate(
+ 'auto.components.settings.ShortcutBindingRow.4a4c2c9d32',
+ 'Add shortcut'
+ )}
diff --git a/src/renderer/src/components/settings/ShortcutFilterRail.tsx b/src/renderer/src/components/settings/ShortcutFilterRail.tsx
index 9a8191d30d3..97a86badc96 100644
--- a/src/renderer/src/components/settings/ShortcutFilterRail.tsx
+++ b/src/renderer/src/components/settings/ShortcutFilterRail.tsx
@@ -34,7 +34,11 @@ const SHORTCUT_FILTER_LABELS: Record
= {
export function getShortcutSearchEntry(row: ShortcutRowModel): SettingsSearchEntry {
return {
title: row.item.title,
- description: translate("auto.components.settings.ShortcutFilterRail.1d5634ba31", "{{value0}} shortcut", { value0: row.groupTitle }),
+ description: translate(
+ 'auto.components.settings.ShortcutFilterRail.1d5634ba31',
+ '{{value0}} shortcut',
+ { value0: row.groupTitle }
+ ),
keywords: [...row.item.searchKeywords]
}
}
@@ -98,7 +102,8 @@ export function ShortcutFilterRail({
- {translate("auto.components.settings.ShortcutFilterRail.02dc7d4251", "Find shortcuts")}
+ {translate('auto.components.settings.ShortcutFilterRail.02dc7d4251', 'Find shortcuts')}
+
{visibleCount}/{totalCount}
@@ -109,7 +114,10 @@ export function ShortcutFilterRail({
id="shortcut-filter-search"
value={query}
onChange={(event) => onQueryChange(event.target.value)}
- placeholder={translate("auto.components.settings.ShortcutFilterRail.f733c4b89f", "Search command or keys")}
+ placeholder={translate(
+ 'auto.components.settings.ShortcutFilterRail.f733c4b89f',
+ 'Search command or keys'
+ )}
className="h-8 pl-8 pr-8 text-sm"
/>
{query ? (
@@ -117,7 +125,10 @@ export function ShortcutFilterRail({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.settings.ShortcutFilterRail.df8466f3fc", "Clear shortcut search")}
+ aria-label={translate(
+ 'auto.components.settings.ShortcutFilterRail.df8466f3fc',
+ 'Clear shortcut search'
+ )}
onClick={() => onQueryChange('')}
className="absolute top-1/2 right-1 -translate-y-1/2 text-muted-foreground"
>
@@ -127,9 +138,16 @@ export function ShortcutFilterRail({
-
+
- {translate("auto.components.settings.ShortcutFilterRail.28b63545bf", "Status")}
+ {translate('auto.components.settings.ShortcutFilterRail.28b63545bf', 'Status')}
+
{filters.map((option) => (
- {translate("auto.components.settings.ShortcutRowsList.4ce3cd24d9", "No shortcuts match those filters.")}
+ {translate(
+ 'auto.components.settings.ShortcutRowsList.4ce3cd24d9',
+ 'No shortcuts match those filters.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx b/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx
index 1772926ed2c..61bf22cabb8 100644
--- a/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx
+++ b/src/renderer/src/components/settings/ShortcutTerminalPolicyControl.tsx
@@ -19,14 +19,26 @@ export function ShortcutTerminalPolicyControl({
return (
- {translate("auto.components.settings.ShortcutTerminalPolicyControl.63308571d8", "Orca first")}
- {translate("auto.components.settings.ShortcutTerminalPolicyControl.0762983d13", "Terminal first")}
+
+ {translate(
+ 'auto.components.settings.ShortcutTerminalPolicyControl.63308571d8',
+ 'Orca first'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.ShortcutTerminalPolicyControl.0762983d13',
+ 'Terminal first'
+ )}
+
}
diff --git a/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx b/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx
index 973162924d7..a903c7f1d8c 100644
--- a/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx
+++ b/src/renderer/src/components/settings/SshDestructiveActionDialog.tsx
@@ -57,7 +57,8 @@ export function SshDestructiveActionDialog({
onOpenChange(false)} disabled={isBusy}>
- {translate("auto.components.settings.SshDestructiveActionDialog.895b216267", "Cancel")}
+ {translate('auto.components.settings.SshDestructiveActionDialog.895b216267', 'Cancel')}
+
{isBusy ? : null}
{isBusy ? (busyLabel ?? actionLabel) : actionLabel}
diff --git a/src/renderer/src/components/settings/SshPassphraseDialog.tsx b/src/renderer/src/components/settings/SshPassphraseDialog.tsx
index 4943eaf5445..3f25f5d91e2 100644
--- a/src/renderer/src/components/settings/SshPassphraseDialog.tsx
+++ b/src/renderer/src/components/settings/SshPassphraseDialog.tsx
@@ -69,7 +69,14 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
await window.api.ssh.submitCredential({ requestId: request.requestId, value })
removeRequest(request.requestId)
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.settings.SshPassphraseDialog.b8e88fd0de", "Failed to submit SSH credential"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.b8e88fd0de',
+ 'Failed to submit SSH credential'
+ )
+ )
setSubmitting(false)
}
}, [request, value, removeRequest])
@@ -81,7 +88,14 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
await window.api.ssh.submitCredential({ requestId: request.requestId, value: null })
removeRequest(request.requestId)
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.settings.SshPassphraseDialog.c55f105262", "Failed to cancel SSH credential request"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.c55f105262',
+ 'Failed to cancel SSH credential request'
+ )
+ )
setSubmitting(false)
}
}
@@ -99,16 +113,29 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
- {isPassword ? translate("auto.components.settings.SshPassphraseDialog.106bd57f4a", "SSH Password") : translate("auto.components.settings.SshPassphraseDialog.1f3dde805d", "SSH Key Passphrase")}
+ {isPassword
+ ? translate('auto.components.settings.SshPassphraseDialog.106bd57f4a', 'SSH Password')
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.1f3dde805d',
+ 'SSH Key Passphrase'
+ )}
{isPassword ? (
<>
- {translate("auto.components.settings.SshPassphraseDialog.dbf9b6f2d0", "Enter the password for")}{label}
+ {translate(
+ 'auto.components.settings.SshPassphraseDialog.dbf9b6f2d0',
+ 'Enter the password for'
+ )}
+ {label}
>
) : (
<>
- {translate("auto.components.settings.SshPassphraseDialog.ce4fdf7914", "Enter the passphrase for")}{label}
+ {translate(
+ 'auto.components.settings.SshPassphraseDialog.ce4fdf7914',
+ 'Enter the passphrase for'
+ )}
+ {label}
>
)}
@@ -118,7 +145,17 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
htmlFor="ssh-credential-input"
className="text-[11px] font-medium text-muted-foreground mb-1 block"
>
- {isPassword ? translate("auto.components.settings.SshPassphraseDialog.cab3d5f5a5", "Password for {{value0}}", { value0: request.detail }) : translate("auto.components.settings.SshPassphraseDialog.8a349e3fac", "Passphrase for {{value0}}", { value0: request.detail })}
+ {isPassword
+ ? translate(
+ 'auto.components.settings.SshPassphraseDialog.cab3d5f5a5',
+ 'Password for {{value0}}',
+ { value0: request.detail }
+ )
+ : translate(
+ 'auto.components.settings.SshPassphraseDialog.8a349e3fac',
+ 'Passphrase for {{value0}}',
+ { value0: request.detail }
+ )}
@@ -144,9 +191,12 @@ export function SshPassphraseDialog(): React.JSX.Element | null {
onClick={() => void handleCancel()}
disabled={submitting}
>
- {translate("auto.components.settings.SshPassphraseDialog.d5a234456f", "Cancel")}
+ {translate('auto.components.settings.SshPassphraseDialog.d5a234456f', 'Cancel')}
+
void handleSubmit()} disabled={!value || submitting}>
- {isPassword ? translate("auto.components.settings.SshPassphraseDialog.bec2c1318f", "Connect") : translate("auto.components.settings.SshPassphraseDialog.405066423c", "Unlock")}
+ {isPassword
+ ? translate('auto.components.settings.SshPassphraseDialog.bec2c1318f', 'Connect')
+ : translate('auto.components.settings.SshPassphraseDialog.405066423c', 'Unlock')}
diff --git a/src/renderer/src/components/settings/SshTargetCard.tsx b/src/renderer/src/components/settings/SshTargetCard.tsx
index 1c308793a7d..a41c560b571 100644
--- a/src/renderer/src/components/settings/SshTargetCard.tsx
+++ b/src/renderer/src/components/settings/SshTargetCard.tsx
@@ -29,7 +29,7 @@ export const STATUS_LABELS: Record = {
connected: 'Connected',
reconnecting: 'Reconnecting\u2026',
'reconnection-failed': 'Reconnection failed',
- error: translate("auto.components.settings.SshTargetCard.18968ede9e", "Error")
+ error: translate('auto.components.settings.SshTargetCard.18968ede9e', 'Error')
}
export function statusColor(status: SshConnectionStatus): string {
@@ -144,7 +144,17 @@ export function SshTargetCard({
onClick={handleTerminateSessions}
className="size-7 text-muted-foreground hover:text-red-400"
disabled={hasActionInFlight}
- aria-label={terminateInFlight ? translate("auto.components.settings.SshTargetCard.c77f1abfe3", "Ending remote terminals") : translate("auto.components.settings.SshTargetCard.da16e108e6", "End remote terminals")}
+ aria-label={
+ terminateInFlight
+ ? translate(
+ 'auto.components.settings.SshTargetCard.c77f1abfe3',
+ 'Ending remote terminals'
+ )
+ : translate(
+ 'auto.components.settings.SshTargetCard.da16e108e6',
+ 'End remote terminals'
+ )
+ }
>
{terminateInFlight ? (
@@ -154,7 +164,8 @@ export function SshTargetCard({
- {translate("auto.components.settings.SshTargetCard.da16e108e6", "End remote terminals")}
+ {translate('auto.components.settings.SshTargetCard.da16e108e6', 'End remote terminals')}
+
)
@@ -167,7 +178,14 @@ export function SshTargetCard({
onClick={handleResetRelay}
className="size-7 text-muted-foreground hover:text-red-400"
disabled={hasActionInFlight}
- aria-label={resetInFlight ? translate("auto.components.settings.SshTargetCard.97dea4e8cf", "Resetting remote relay") : translate("auto.components.settings.SshTargetCard.762a48c662", "Reset remote relay")}
+ aria-label={
+ resetInFlight
+ ? translate(
+ 'auto.components.settings.SshTargetCard.97dea4e8cf',
+ 'Resetting remote relay'
+ )
+ : translate('auto.components.settings.SshTargetCard.762a48c662', 'Reset remote relay')
+ }
>
{resetInFlight ? (
@@ -177,7 +195,8 @@ export function SshTargetCard({
- {translate("auto.components.settings.SshTargetCard.762a48c662", "Reset remote relay")}
+ {translate('auto.components.settings.SshTargetCard.762a48c662', 'Reset remote relay')}
+
)
@@ -193,13 +212,17 @@ export function SshTargetCard({
onClick={() => onEdit(target)}
className="size-7"
disabled={hasActionInFlight}
- aria-label={translate("auto.components.settings.SshTargetCard.3d8af2949f", "Edit target")}
+ aria-label={translate(
+ 'auto.components.settings.SshTargetCard.3d8af2949f',
+ 'Edit target'
+ )}
>
- {translate("auto.components.settings.SshTargetCard.3d8af2949f", "Edit target")}
+ {translate('auto.components.settings.SshTargetCard.3d8af2949f', 'Edit target')}
+
@@ -209,7 +232,11 @@ export function SshTargetCard({
onClick={() => onRemove(target.id)}
className="size-7 text-muted-foreground hover:text-red-400"
disabled={hasActionInFlight}
- aria-label={removeInFlight ? translate("auto.components.settings.SshTargetCard.3d21a22d0e", "Removing target") : translate("auto.components.settings.SshTargetCard.7f7b3d7ab4", "Remove target")}
+ aria-label={
+ removeInFlight
+ ? translate('auto.components.settings.SshTargetCard.3d21a22d0e', 'Removing target')
+ : translate('auto.components.settings.SshTargetCard.7f7b3d7ab4', 'Remove target')
+ }
>
{removeInFlight ? (
@@ -219,7 +246,8 @@ export function SshTargetCard({
- {translate("auto.components.settings.SshTargetCard.7f7b3d7ab4", "Remove target")}
+ {translate('auto.components.settings.SshTargetCard.7f7b3d7ab4', 'Remove target')}
+
)
@@ -247,7 +275,7 @@ export function SshTargetCard({
- {status === "connected" ? (
+ {status === 'connected' ? (
<>
{renderSecondaryIconActions(true)}
- {translate("auto.components.settings.SshTargetCard.4c86f30877", "Disconnect")}
+ {translate('auto.components.settings.SshTargetCard.4c86f30877', 'Disconnect')}
+
>
) : isSshTargetConnecting(status) ? (
<>
{renderSecondaryIconActions(false)}
- {translate("auto.components.settings.SshTargetCard.1810b51482", "Connecting")}
+ {translate('auto.components.settings.SshTargetCard.1810b51482', 'Connecting')}
+
>
) : (
<>
@@ -282,7 +312,8 @@ export function SshTargetCard({
) : (
)}
- {translate("auto.components.settings.SshTargetCard.0e53e9f8e8", "Test")}
+ {translate('auto.components.settings.SshTargetCard.0e53e9f8e8', 'Test')}
+
- {actionInFlight === "connect" ? (
+ {actionInFlight === 'connect' ? (
) : (
)}
- {translate("auto.components.settings.SshTargetCard.ec6543cee9", "Connect")}
+ {translate('auto.components.settings.SshTargetCard.ec6543cee9', 'Connect')}
+
>
)}
diff --git a/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx b/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx
index db9adf1279e..44aaaddb814 100644
--- a/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx
+++ b/src/renderer/src/components/settings/SshTargetDestructiveActions.tsx
@@ -159,8 +159,14 @@ export function SshTargetDestructiveActions({
- {editingId ? translate("auto.components.settings.SshTargetForm.f2331ce599", "Edit SSH Target") : translate("auto.components.settings.SshTargetForm.29af933cd5", "New SSH Target")}
+
+ {editingId
+ ? translate('auto.components.settings.SshTargetForm.f2331ce599', 'Edit SSH Target')
+ : translate('auto.components.settings.SshTargetForm.29af933cd5', 'New SSH Target')}
+
- {translate("auto.components.settings.SshTargetForm.298de87a88", "Label")}
+ {translate('auto.components.settings.SshTargetForm.298de87a88', 'Label')}
onFormChange((f) => ({ ...f, label: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.b8dab0aa7b", "My Server")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.b8dab0aa7b',
+ 'My Server'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.ce370ce674", "Host or alias *")}
+
+ {translate('auto.components.settings.SshTargetForm.ce370ce674', 'Host or alias *')}
+
onFormChange((f) => ({ ...f, host: e.target.value }))}
onBlur={() => onFormChange(applyParsedSshHostInput)}
- placeholder={translate("auto.components.settings.SshTargetForm.2ee9bcd2e8", "server, deploy@server:2222, ssh://server")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.2ee9bcd2e8',
+ 'server, deploy@server:2222, ssh://server'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.dc1dc52aaa", "Username")}
+
+ {translate('auto.components.settings.SshTargetForm.dc1dc52aaa', 'Username')}
+
onFormChange((f) => ({ ...f, username: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.47e082bc17", "deploy")}
+ placeholder={translate('auto.components.settings.SshTargetForm.47e082bc17', 'deploy')}
/>
-
{translate("auto.components.settings.SshTargetForm.c94cfa634c", "Port")}
+
{translate('auto.components.settings.SshTargetForm.c94cfa634c', 'Port')}
- {translate("auto.components.settings.SshTargetForm.63c0c145c1", "Identity File")}
+ {translate('auto.components.settings.SshTargetForm.63c0c145c1', 'Identity File')}
+
onFormChange((f) => ({ ...f, identityFile: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.d6a5f2ee5c", "~/.ssh/id_ed25519 (leave empty for SSH agent)")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.d6a5f2ee5c',
+ '~/.ssh/id_ed25519 (leave empty for SSH agent)'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.cb91f6375c", "Optional. SSH agent is used by default.")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.cb91f6375c',
+ 'Optional. SSH agent is used by default.'
+ )}
+
-
{translate("auto.components.settings.SshTargetForm.c7d0e18ecb", "Proxy Command")}
+
+ {translate('auto.components.settings.SshTargetForm.c7d0e18ecb', 'Proxy Command')}
+
onFormChange((f) => ({ ...f, proxyCommand: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.f42d844544", "e.g. cloudflared access ssh --hostname %h")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.f42d844544',
+ 'e.g. cloudflared access ssh --hostname %h'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.3b01ca44a0", "Optional. Used for tunneling (e.g. Cloudflare Access, ProxyCommand).")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.3b01ca44a0',
+ 'Optional. Used for tunneling (e.g. Cloudflare Access, ProxyCommand).'
+ )}
+
-
{translate("auto.components.settings.SshTargetForm.b2ab248ded", "Jump Host")}
+
+ {translate('auto.components.settings.SshTargetForm.b2ab248ded', 'Jump Host')}
+
onFormChange((f) => ({ ...f, jumpHost: e.target.value }))}
- placeholder={translate("auto.components.settings.SshTargetForm.11bcb4507a", "bastion.example.com")}
+ placeholder={translate(
+ 'auto.components.settings.SshTargetForm.11bcb4507a',
+ 'bastion.example.com'
+ )}
/>
- {translate("auto.components.settings.SshTargetForm.feae1d1e69", "Optional. Equivalent to ProxyJump / ssh -J.")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.feae1d1e69',
+ 'Optional. Equivalent to ProxyJump / ssh -J.'
+ )}
+
-
{translate("auto.components.settings.SshTargetForm.92f80edbfd", "Relay Grace Period (seconds)")}
+
+ {translate(
+ 'auto.components.settings.SshTargetForm.92f80edbfd',
+ 'Relay Grace Period (seconds)'
+ )}
+
- {translate("auto.components.settings.SshTargetForm.71fc546097", "Keep alive until reset")}
+
+ {translate(
+ 'auto.components.settings.SshTargetForm.71fc546097',
+ 'Keep alive until reset'
+ )}
+
- {translate("auto.components.settings.SshTargetForm.b574994adc", "Remote terminals stay available until you end them or reset the relay.")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.b574994adc',
+ 'Remote terminals stay available until you end them or reset the relay.'
+ )}
+
- {translate("auto.components.settings.SshTargetForm.137e88ce8d", "How long the relay keeps terminals alive after disconnect. Default: 10800 (3 hours). Maximum:")}{MAX_SSH_RELAY_GRACE_PERIOD_SECONDS} {translate("auto.components.settings.SshTargetForm.1b19b00e93", "(7 days).")}
+ {translate(
+ 'auto.components.settings.SshTargetForm.137e88ce8d',
+ 'How long the relay keeps terminals alive after disconnect. Default: 10800 (3 hours). Maximum:'
+ )}
+ {MAX_SSH_RELAY_GRACE_PERIOD_SECONDS}{' '}
+ {translate('auto.components.settings.SshTargetForm.1b19b00e93', '(7 days).')}
+
- {editingId ? translate("auto.components.settings.SshTargetForm.a62b4cb39a", "Save Changes") : translate("auto.components.settings.SshTargetForm.9518545cb6", "Add Target")}
+ {editingId
+ ? translate('auto.components.settings.SshTargetForm.a62b4cb39a', 'Save Changes')
+ : translate('auto.components.settings.SshTargetForm.9518545cb6', 'Add Target')}
- {translate("auto.components.settings.SshTargetForm.fea9cb402e", "Cancel")}
+ {translate('auto.components.settings.SshTargetForm.fea9cb402e', 'Cancel')}
+
)
diff --git a/src/renderer/src/components/settings/TasksPane.tsx b/src/renderer/src/components/settings/TasksPane.tsx
index a3e1a9a69dd..2195201b112 100644
--- a/src/renderer/src/components/settings/TasksPane.tsx
+++ b/src/renderer/src/components/settings/TasksPane.tsx
@@ -26,26 +26,38 @@ const TASK_PROVIDER_OPTIONS: readonly {
}[] = [
{
id: 'github',
- label: translate("auto.components.settings.TasksPane.e14063e727", "GitHub"),
- description: translate("auto.components.settings.TasksPane.1db47236cd", "Show GitHub in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.e14063e727', 'GitHub'),
+ description: translate(
+ 'auto.components.settings.TasksPane.1db47236cd',
+ 'Show GitHub in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
},
{
id: 'gitlab',
- label: translate("auto.components.settings.TasksPane.7c5d7fdc20", "GitLab"),
- description: translate("auto.components.settings.TasksPane.dd67a1b6e1", "Show GitLab in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.7c5d7fdc20', 'GitLab'),
+ description: translate(
+ 'auto.components.settings.TasksPane.dd67a1b6e1',
+ 'Show GitLab in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
},
{
id: 'linear',
- label: translate("auto.components.settings.TasksPane.09ae2d7c51", "Linear"),
- description: translate("auto.components.settings.TasksPane.e4170c9615", "Show Linear in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.09ae2d7c51', 'Linear'),
+ description: translate(
+ 'auto.components.settings.TasksPane.e4170c9615',
+ 'Show Linear in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
},
{
id: 'jira',
- label: translate("auto.components.settings.TasksPane.6b23a34f6d", "Jira"),
- description: translate("auto.components.settings.TasksPane.8e1305fcc6", "Show Jira in the Tasks source picker and sidebar shortcuts."),
+ label: translate('auto.components.settings.TasksPane.6b23a34f6d', 'Jira'),
+ description: translate(
+ 'auto.components.settings.TasksPane.8e1305fcc6',
+ 'Show Jira in the Tasks source picker and sidebar shortcuts.'
+ ),
Icon: ({ className }) =>
}
]
@@ -73,13 +85,19 @@ export function TasksPane({ settings, updateSettings }: TasksPaneProps): React.J
- {translate("auto.components.settings.TerminalFontSizeSetting.9b5252c85a", "px")}
+
+ {translate('auto.components.settings.TerminalFontSizeSetting.9b5252c85a', 'px')}
+
}
/>
diff --git a/src/renderer/src/components/settings/UIZoomControl.tsx b/src/renderer/src/components/settings/UIZoomControl.tsx
index 35c8b1b8bf2..eafee9b796b 100644
--- a/src/renderer/src/components/settings/UIZoomControl.tsx
+++ b/src/renderer/src/components/settings/UIZoomControl.tsx
@@ -50,7 +50,8 @@ export function UIZoomControl(): React.JSX.Element {
className="ml-1 gap-1.5"
>
- {translate("auto.components.settings.UIZoomControl.c2c64b24d0", "Reset")}
+ {translate('auto.components.settings.UIZoomControl.c2c64b24d0', 'Reset')}
+
)
}
diff --git a/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx b/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx
index 315d2448c78..821c35dd165 100644
--- a/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx
+++ b/src/renderer/src/components/settings/WorktreeSymlinksSection.tsx
@@ -96,8 +96,14 @@ export function WorktreeSymlinksSection({
return (
-
{translate("auto.components.settings.WorktreeSymlinksSection.4755f120b6", "Worktree Symlinks")}
+
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.4755f120b6',
+ 'Worktree Symlinks'
+ )}
+
- {translate("auto.components.settings.WorktreeSymlinksSection.7ff265071d", "When a new worktree is created, each path listed here will be symlinked from the primary checkout.")}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.7ff265071d',
+ 'When a new worktree is created, each path listed here will be symlinked from the primary checkout.'
+ )}
+
- {translate("auto.components.settings.WorktreeSymlinksSection.241325302c", "Add Path")}
+ {translate('auto.components.settings.WorktreeSymlinksSection.241325302c', 'Add Path')}
+
- {translate("auto.components.settings.WorktreeSymlinksSection.ab40b8a5f1", "No matches. Keep typing to add a custom path.")}
+
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.ab40b8a5f1',
+ 'No matches. Keep typing to add a custom path.'
+ )}
+
{showLiteralItem ? (
- {translate("auto.components.settings.WorktreeSymlinksSection.b2429aeb31", "Add")}{' '}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.b2429aeb31',
+ 'Add'
+ )}{' '}
{queryTrimmed}
@@ -165,7 +192,11 @@ export function WorktreeSymlinksSection({
{entry.name}
{alreadyAdded ? (
- {translate("auto.components.settings.WorktreeSymlinksSection.ea06227efa", "added")}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.ea06227efa',
+ 'added'
+ )}
+
) : null}
)
@@ -178,7 +209,11 @@ export function WorktreeSymlinksSection({
{paths.length === 0 ? (
- {translate("auto.components.settings.WorktreeSymlinksSection.31ebab5403", "No symlink paths configured for this repository.")}
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.31ebab5403',
+ 'No symlink paths configured for this repository.'
+ )}
+
) : (
@@ -187,9 +222,23 @@ export function WorktreeSymlinksSection({
-
{translate("auto.components.settings.WorktreeSymlinksSection.b814c618e2", "Linked paths")}
+
+ {translate(
+ 'auto.components.settings.WorktreeSymlinksSection.b814c618e2',
+ 'Linked paths'
+ )}
+
- {paths.length === 1 ? translate("auto.components.settings.WorktreeSymlinksSection.9ea912d811", "1 path") : translate("auto.components.settings.WorktreeSymlinksSection.d72ba8dc68", "{{value0}} paths", { value0: paths.length })}
+ {paths.length === 1
+ ? translate(
+ 'auto.components.settings.WorktreeSymlinksSection.9ea912d811',
+ '1 path'
+ )
+ : translate(
+ 'auto.components.settings.WorktreeSymlinksSection.d72ba8dc68',
+ '{{value0}} paths',
+ { value0: paths.length }
+ )}
@@ -204,7 +253,11 @@ export function WorktreeSymlinksSection({
size="icon-xs"
variant="ghost"
onClick={() => handleRemove(path)}
- aria-label={translate("auto.components.settings.WorktreeSymlinksSection.1c1e35b219", "Remove {{value0}}", { value0: path })}
+ aria-label={translate(
+ 'auto.components.settings.WorktreeSymlinksSection.1c1e35b219',
+ 'Remove {{value0}}',
+ { value0: path }
+ )}
className="size-4 shrink-0 rounded-sm"
>
diff --git a/src/renderer/src/components/settings/WslCliRegistration.tsx b/src/renderer/src/components/settings/WslCliRegistration.tsx
index ea0eacf0e47..9d23dbeca93 100644
--- a/src/renderer/src/components/settings/WslCliRegistration.tsx
+++ b/src/renderer/src/components/settings/WslCliRegistration.tsx
@@ -41,7 +41,14 @@ export function WslCliRegistration({
}
} catch (error) {
if (mountedRef.current) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.settings.WslCliRegistration.26b4b3b00f", "Failed to load WSL CLI status."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.WslCliRegistration.26b4b3b00f',
+ 'Failed to load WSL CLI status.'
+ )
+ )
}
} finally {
if (mountedRef.current) {
@@ -73,11 +80,23 @@ export function WslCliRegistration({
}
setStatus(next)
setDialogOpen(false)
- toast.success(translate("auto.components.settings.WslCliRegistration.951536dda5", "Registered `{{value0}}` in WSL.", { value0: next.commandName }))
+ toast.success(
+ translate(
+ 'auto.components.settings.WslCliRegistration.951536dda5',
+ 'Registered `{{value0}}` in WSL.',
+ { value0: next.commandName }
+ )
+ )
} catch (error) {
if (mountedRef.current) {
toast.error(
- error instanceof Error ? error.message : translate("auto.components.settings.WslCliRegistration.6f91ad1333", "Failed to register `{{value0}}` in WSL.", { value0: commandName })
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.WslCliRegistration.6f91ad1333',
+ 'Failed to register `{{value0}}` in WSL.',
+ { value0: commandName }
+ )
)
}
} finally {
@@ -96,11 +115,23 @@ export function WslCliRegistration({
}
setStatus(next)
setDialogOpen(false)
- toast.success(translate("auto.components.settings.WslCliRegistration.89c7414cf5", "Removed `{{value0}}` from WSL.", { value0: next.commandName }))
+ toast.success(
+ translate(
+ 'auto.components.settings.WslCliRegistration.89c7414cf5',
+ 'Removed `{{value0}}` from WSL.',
+ { value0: next.commandName }
+ )
+ )
} catch (error) {
if (mountedRef.current) {
toast.error(
- error instanceof Error ? error.message : translate("auto.components.settings.WslCliRegistration.52d990420e", "Failed to remove `{{value0}}` from WSL.", { value0: commandName })
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.settings.WslCliRegistration.52d990420e',
+ 'Failed to remove `{{value0}}` from WSL.',
+ { value0: commandName }
+ )
)
}
} finally {
@@ -115,11 +146,23 @@ export function WslCliRegistration({
-
{translate("auto.components.settings.WslCliRegistration.d9c6880dbd", "WSL shell command")}
+
+ {translate(
+ 'auto.components.settings.WslCliRegistration.d9c6880dbd',
+ 'WSL shell command'
+ )}
+
{loading
- ? translate("auto.components.settings.WslCliRegistration.0307677bb9", "Checking WSL CLI registration...")
- : (status?.detail ?? translate("auto.components.settings.WslCliRegistration.7aa456a460", "Register `orca-ide` in ~/.local/bin inside WSL."))}
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.0307677bb9',
+ 'Checking WSL CLI registration...'
+ )
+ : (status?.detail ??
+ translate(
+ 'auto.components.settings.WslCliRegistration.7aa456a460',
+ 'Register `orca-ide` in ~/.local/bin inside WSL.'
+ ))}
@@ -131,13 +174,17 @@ export function WslCliRegistration({
size="icon-xs"
onClick={() => void refreshStatus()}
disabled={loading || busyAction !== null}
- aria-label={translate("auto.components.settings.WslCliRegistration.ab6b022a5c", "Refresh WSL CLI status")}
+ aria-label={translate(
+ 'auto.components.settings.WslCliRegistration.ab6b022a5c',
+ 'Refresh WSL CLI status'
+ )}
>
- {translate("auto.components.settings.WslCliRegistration.9b6627522c", "Refresh")}
+ {translate('auto.components.settings.WslCliRegistration.9b6627522c', 'Refresh')}
+
- {translate("auto.components.settings.WslCliRegistration.554305956d", "Command path:")}{' '}
+ {translate('auto.components.settings.WslCliRegistration.554305956d', 'Command path:')}{' '}
{status.commandPath}
) : null}
- {status?.state === "stale" && status.currentTarget ? (
+ {status?.state === 'stale' && status.currentTarget ? (
- {translate("auto.components.settings.WslCliRegistration.1dbb0377d9", "Existing launcher target:")}{status.currentTarget}
+ {translate(
+ 'auto.components.settings.WslCliRegistration.1dbb0377d9',
+ 'Existing launcher target:'
+ )}
+ {status.currentTarget}
) : null}
@@ -177,18 +228,33 @@ export function WslCliRegistration({
{isEnabled
- ? translate("auto.components.settings.WslCliRegistration.61ac55278e", "Remove `{{value0}}` from WSL?", { value0: commandName })
- : translate("auto.components.settings.WslCliRegistration.e49688f67f", "Register `{{value0}}` in WSL?", { value0: commandName })}
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.61ac55278e',
+ 'Remove `{{value0}}` from WSL?',
+ { value0: commandName }
+ )
+ : translate(
+ 'auto.components.settings.WslCliRegistration.e49688f67f',
+ 'Register `{{value0}}` in WSL?',
+ { value0: commandName }
+ )}
{isEnabled
- ? translate("auto.components.settings.WslCliRegistration.d8216eb22e", "This removes the WSL shell command. Orca itself remains installed on Windows.")
- : translate("auto.components.settings.WslCliRegistration.7ee4e52b99", "Orca will register {{value0}} so the command works from WSL terminals.", { value0: status?.commandPath ?? commandName })}
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.d8216eb22e',
+ 'This removes the WSL shell command. Orca itself remains installed on Windows.'
+ )
+ : translate(
+ 'auto.components.settings.WslCliRegistration.7ee4e52b99',
+ 'Orca will register {{value0}} so the command works from WSL terminals.',
+ { value0: status?.commandPath ?? commandName }
+ )}
{status?.commandPath ? (
- {translate("auto.components.settings.WslCliRegistration.119fef6cd2", "Target path:")}{' '}
+ {translate('auto.components.settings.WslCliRegistration.119fef6cd2', 'Target path:')}{' '}
{status.commandPath}
) : null}
@@ -198,18 +264,25 @@ export function WslCliRegistration({
onClick={() => setDialogOpen(false)}
disabled={busyAction !== null}
>
- {translate("auto.components.settings.WslCliRegistration.c6f6f89d7c", "Cancel")}
+ {translate('auto.components.settings.WslCliRegistration.c6f6f89d7c', 'Cancel')}
+
void (isEnabled ? handleRemove() : handleInstall())}
disabled={busyAction !== null || !isSupported}
>
- {busyAction === "remove"
- ? translate("auto.components.settings.WslCliRegistration.4598b18464", "Removing...")
- : busyAction === "install"
- ? translate("auto.components.settings.WslCliRegistration.4c4a9178a3", "Registering...")
+ {busyAction === 'remove'
+ ? translate('auto.components.settings.WslCliRegistration.4598b18464', 'Removing...')
+ : busyAction === 'install'
+ ? translate(
+ 'auto.components.settings.WslCliRegistration.4c4a9178a3',
+ 'Registering...'
+ )
: isEnabled
- ? translate("auto.components.settings.WslCliRegistration.f951f85196", "Remove")
- : translate("auto.components.settings.WslCliRegistration.290bfff3ab", "Register")}
+ ? translate('auto.components.settings.WslCliRegistration.f951f85196', 'Remove')
+ : translate(
+ 'auto.components.settings.WslCliRegistration.290bfff3ab',
+ 'Register'
+ )}
diff --git a/src/renderer/src/components/settings/jira-integration-card.tsx b/src/renderer/src/components/settings/jira-integration-card.tsx
index c4b63bc1911..9abdb29c210 100644
--- a/src/renderer/src/components/settings/jira-integration-card.tsx
+++ b/src/renderer/src/components/settings/jira-integration-card.tsx
@@ -132,26 +132,38 @@ export function JiraIntegrationCard(): React.JSX.Element {
-
{translate("auto.components.settings.jira.integration.card.09742875cd", "Jira")}
+
+ {translate('auto.components.settings.jira.integration.card.09742875cd', 'Jira')}
+
{jiraStatus.connected
- ? translate("auto.components.settings.jira.integration.card.74f3063026", "{{value0}} site{{value1}} connected", { value0: jiraSites.length, value1: jiraSites.length === 1 ? '' : 's' })
- : translate("auto.components.settings.jira.integration.card.9a9f8d4910", "Connect Jira Cloud to browse, create, and link issues.")}
+ ? translate(
+ 'auto.components.settings.jira.integration.card.74f3063026',
+ '{{value0}} site{{value1}} connected',
+ { value0: jiraSites.length, value1: jiraSites.length === 1 ? '' : 's' }
+ )
+ : translate(
+ 'auto.components.settings.jira.integration.card.9a9f8d4910',
+ 'Connect Jira Cloud to browse, create, and link issues.'
+ )}
{jiraStatus.connected ? (
- {translate("auto.components.settings.jira.integration.card.efaab83c5d", "Add site")}
+ {translate('auto.components.settings.jira.integration.card.efaab83c5d', 'Add site')}
+
- {translate("auto.components.settings.jira.integration.card.9bb34706ca", "Connected")}
+ {translate('auto.components.settings.jira.integration.card.9bb34706ca', 'Connected')}
+
) : (
- {translate("auto.components.settings.jira.integration.card.a28f417220", "Connect Jira")}
+ {translate('auto.components.settings.jira.integration.card.a28f417220', 'Connect Jira')}
+
)}
@@ -159,7 +171,10 @@ export function JiraIntegrationCard(): React.JSX.Element {
{
setSiteUrlDraft(e.target.value)
@@ -170,7 +185,10 @@ export function JiraIntegrationCard(): React.JSX.Element {
/>
{
setEmailDraft(e.target.value)
@@ -182,7 +200,10 @@ export function JiraIntegrationCard(): React.JSX.Element {
{
setApiTokenDraft(e.target.value)
@@ -205,7 +226,11 @@ export function JiraIntegrationCard(): React.JSX.Element {
}
>
- {translate("auto.components.settings.jira.integration.card.1666f8d562", "Create an Atlassian API token")}
+ {translate(
+ 'auto.components.settings.jira.integration.card.1666f8d562',
+ 'Create an Atlassian API token'
+ )}
+
- {translate("auto.components.settings.jira.integration.card.5936977fcd", "Cancel")}
+ {translate('auto.components.settings.jira.integration.card.5936977fcd', 'Cancel')}
+
- {connectState === "connecting" ? (
+ {connectState === 'connecting' ? (
<>
- {translate("auto.components.settings.jira.integration.card.d914d7ab70", "Verifying…")}>
- ) : formMode.kind === "update" ? (
- translate("auto.components.settings.jira.integration.card.33a8b261ee", "Update credentials")
+ {translate(
+ 'auto.components.settings.jira.integration.card.d914d7ab70',
+ 'Verifying…'
+ )}
+ >
+ ) : formMode.kind === 'update' ? (
+ translate(
+ 'auto.components.settings.jira.integration.card.33a8b261ee',
+ 'Update credentials'
+ )
) : (
- translate("auto.components.settings.jira.integration.card.2e8bb790fd", "Connect")
+ translate('auto.components.settings.jira.integration.card.2e8bb790fd', 'Connect')
)}
@@ -256,10 +289,14 @@ export function JiraIntegrationCard(): React.JSX.Element {
{site.siteUrl}
- {testResult?.state === "ok" ? (
+ {testResult?.state === 'ok' ? (
- {translate("auto.components.settings.jira.integration.card.ab350991b8", "Verified")}
+ {translate(
+ 'auto.components.settings.jira.integration.card.ab350991b8',
+ 'Verified'
+ )}
+
) : null}
{testResult?.state === 'error' ? (
@@ -276,16 +313,25 @@ export function JiraIntegrationCard(): React.JSX.Element {
{testing ? (
<>
- {translate("auto.components.settings.jira.integration.card.cec06a0f79", "Testing…")}>
+ {translate(
+ 'auto.components.settings.jira.integration.card.cec06a0f79',
+ 'Testing…'
+ )}
+ >
) : (
- translate("auto.components.settings.jira.integration.card.255bfe98ec", "Test")
+ translate('auto.components.settings.jira.integration.card.255bfe98ec', 'Test')
)}
openUpdateForm(site)}>
- {translate("auto.components.settings.jira.integration.card.eaffa454e9", "Update")}
+ {translate('auto.components.settings.jira.integration.card.eaffa454e9', 'Update')}
+
void handleDisconnect(site.id)}
- aria-label={translate("auto.components.settings.jira.integration.card.9046a20d4c", "Disconnect {{value0}}", { value0: getJiraSiteLabel(site) })}
+ aria-label={translate(
+ 'auto.components.settings.jira.integration.card.9046a20d4c',
+ 'Disconnect {{value0}}',
+ { value0: getJiraSiteLabel(site) }
+ )}
className="rounded-md p-1 text-muted-foreground/50 transition-colors hover:text-destructive"
>
@@ -294,7 +340,11 @@ export function JiraIntegrationCard(): React.JSX.Element {
)
})}
- {translate("auto.components.settings.jira.integration.card.8ff73fef62", "Jira tokens are encrypted by the active runtime and stored locally. Re-entering the same site URL and email replaces that site's API token.")}
+ {translate(
+ 'auto.components.settings.jira.integration.card.8ff73fef62',
+ "Jira tokens are encrypted by the active runtime and stored locally. Re-entering the same site URL and email replaces that site's API token."
+ )}
+
) : null}
diff --git a/src/renderer/src/components/setup-guide/SetupGuideModal.tsx b/src/renderer/src/components/setup-guide/SetupGuideModal.tsx
index 54bd89fe2cb..cda8292a8a1 100644
--- a/src/renderer/src/components/setup-guide/SetupGuideModal.tsx
+++ b/src/renderer/src/components/setup-guide/SetupGuideModal.tsx
@@ -124,7 +124,10 @@ export default function SetupGuideModal(): JSX.Element | null {
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.setup.guide.SetupGuideModal.f3b5ffb2a6", "Hide checklist from sidebar")}
+ aria-label={translate(
+ 'auto.components.setup.guide.SetupGuideModal.f3b5ffb2a6',
+ 'Hide checklist from sidebar'
+ )}
onClick={handleHideFromSidebar}
className="absolute right-10 top-3.5 text-muted-foreground"
>
@@ -132,11 +135,20 @@ export default function SetupGuideModal(): JSX.Element | null {
- {translate("auto.components.setup.guide.SetupGuideModal.28cf59fcb4", "This will hide the checklist from the sidebar")}
+ {translate(
+ 'auto.components.setup.guide.SetupGuideModal.28cf59fcb4',
+ 'This will hide the checklist from the sidebar'
+ )}
+
- {translate("auto.components.setup.guide.SetupGuideModal.48a9e5ef2d", "Getting started")}
+
+ {translate(
+ 'auto.components.setup.guide.SetupGuideModal.48a9e5ef2d',
+ 'Getting started'
+ )}
+
- {translate("auto.components.setup.guide.SetupGuideModal.3598a3ca0c", "Finish the core workflows that make Orca useful for parallel agent work.")}
+ {translate(
+ 'auto.components.setup.guide.SetupGuideModal.3598a3ca0c',
+ 'Finish the core workflows that make Orca useful for parallel agent work.'
+ )}
+
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c", "Add Project")}
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.046751dbfb", "Add this folder as a separate Orca project.")}
+
+ {translate(
+ 'auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c',
+ 'Add Project'
+ )}
+
+
+ {translate(
+ 'auto.components.sidebar.AddProjectFromFolderDialog.046751dbfb',
+ 'Add this folder as a separate Orca project.'
+ )}
+
{folderPath && (
@@ -171,14 +187,19 @@ const AddProjectFromFolderDialog = React.memo(function AddProjectFromFolderDialo
handleOpenChange(false)} disabled={isAdding}>
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.7726a16374", "Cancel")}
+ {translate('auto.components.sidebar.AddProjectFromFolderDialog.7726a16374', 'Cancel')}
+
{isAdding ? (
) : (
)}
- {translate("auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c", "Add Project")}
+ {translate(
+ 'auto.components.sidebar.AddProjectFromFolderDialog.7d1f51678c',
+ 'Add Project'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx b/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
index 1d612020148..204ef5bc410 100644
--- a/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
@@ -53,7 +53,12 @@ export function useCreateRepo(
if (useAppStore.getState().settings?.activeRuntimeEnvironmentId?.trim()) {
// Why: the native folder picker returns a client-local path. Runtime
// project creation needs an explicit server parent path.
- toast.error(translate("auto.components.sidebar.AddRepoCreateStep.875dda0995", "Enter a server parent path."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.AddRepoCreateStep.875dda0995',
+ 'Enter a server parent path.'
+ )
+ )
return
}
const gen = createGenRef.current
@@ -119,13 +124,22 @@ export function useCreateRepo(
useAppStore.setState({ repos: updated })
}
if (wasDeduped) {
- toast.info(translate("auto.components.sidebar.AddRepoCreateStep.2c12db1511", "Project already added"), {
- description: repo.displayName
- })
+ toast.info(
+ translate(
+ 'auto.components.sidebar.AddRepoCreateStep.2c12db1511',
+ 'Project already added'
+ ),
+ {
+ description: repo.displayName
+ }
+ )
} else {
- toast.success(translate("auto.components.sidebar.AddRepoCreateStep.5e97f0c4b9", "Project created"), {
- description: repo.displayName
- })
+ toast.success(
+ translate('auto.components.sidebar.AddRepoCreateStep.5e97f0c4b9', 'Project created'),
+ {
+ description: repo.displayName
+ }
+ )
}
if (isGitRepoKind(repo)) {
// Why: Git repos use the shared default-checkout completion path.
@@ -336,9 +350,15 @@ export function CreateStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoCreateStep.db9be12229", "Start a new project")}
+
+ {translate('auto.components.sidebar.AddRepoCreateStep.db9be12229', 'Start a new project')}
+
- {translate("auto.components.sidebar.AddRepoCreateStep.d877ece0d6", "Create a Git repository or a plain folder and open it in Orca.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.d877ece0d6',
+ 'Create a Git repository or a plain folder and open it in Orca.'
+ )}
+
{/* Why: DialogContent is a CSS grid; grid items default to min-width:auto
@@ -350,7 +370,10 @@ export function CreateStep({
onKindChange('git')}
onArrowNav={cycleKind}
icon={ }
- title={translate("auto.components.sidebar.AddRepoCreateStep.11fd2a7db8", "Git repository")}
+ title={translate(
+ 'auto.components.sidebar.AddRepoCreateStep.11fd2a7db8',
+ 'Git repository'
+ )}
caption="Initializes an empty Git repo"
/>
onKindChange('folder')}
onArrowNav={cycleKind}
icon={ }
- title={translate("auto.components.sidebar.AddRepoCreateStep.038729c107", "Folder")}
+ title={translate('auto.components.sidebar.AddRepoCreateStep.038729c107', 'Folder')}
caption="Create a new folder"
/>
@@ -381,12 +407,16 @@ export function CreateStep({
htmlFor="create-project-name"
className="text-[11px] font-medium text-muted-foreground block"
>
- {translate("auto.components.sidebar.AddRepoCreateStep.a8149a3a5a", "Name")}
+ {translate('auto.components.sidebar.AddRepoCreateStep.a8149a3a5a', 'Name')}
+
onNameChange(e.target.value)}
- placeholder={translate("auto.components.sidebar.AddRepoCreateStep.0ae45b8238", "my-project")}
+ placeholder={translate(
+ 'auto.components.sidebar.AddRepoCreateStep.0ae45b8238',
+ 'my-project'
+ )}
className="h-11 text-sm font-mono"
disabled={isCreating}
autoFocus
@@ -413,7 +443,9 @@ export function CreateStep({
)}
- {isCreating ? translate("auto.components.sidebar.AddRepoCreateStep.85085d74d2", "Creating…") : translate("auto.components.sidebar.AddRepoCreateStep.45b7c26034", "Create project")}
+ {isCreating
+ ? translate('auto.components.sidebar.AddRepoCreateStep.85085d74d2', 'Creating…')
+ : translate('auto.components.sidebar.AddRepoCreateStep.45b7c26034', 'Create project')}
>
diff --git a/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx b/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
index be5d363629c..e58c0aa51d8 100644
--- a/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
@@ -45,12 +45,24 @@ export function AddRepoNestedImportStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoNestedImportStep.8db50afe1a", "Import repositories from folder")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.8db50afe1a',
+ 'Import repositories from folder'
+ )}
+
{scanInProgress ?
: null}
- {scanInProgress ? translate("auto.components.sidebar.AddRepoNestedImportStep.220dd32d83", "Scanning...") : null}
- {translate("auto.components.sidebar.AddRepoNestedImportStep.4df0d08cc5", "Found")} {repoCountLabel} {translate("auto.components.sidebar.AddRepoNestedImportStep.5f857ba8e6", "in")}{' '}
+ {scanInProgress
+ ? translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.220dd32d83',
+ 'Scanning...'
+ )
+ : null}
+ {translate('auto.components.sidebar.AddRepoNestedImportStep.4df0d08cc5', 'Found')}{' '}
+ {repoCountLabel}{' '}
+ {translate('auto.components.sidebar.AddRepoNestedImportStep.5f857ba8e6', 'in')}{' '}
{scan.selectedPath}
@@ -75,26 +87,40 @@ export function AddRepoNestedImportStep({
- {translate("auto.components.sidebar.AddRepoNestedImportStep.40199ef7b3", "Group name")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.40199ef7b3',
+ 'Group name'
+ )}
+
- {translate("auto.components.sidebar.AddRepoNestedImportStep.b20bb7c24f", "Keeps these repos together in one group. Best for related repos like microservices.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.b20bb7c24f',
+ 'Keeps these repos together in one group. Best for related repos like microservices.'
+ )}
+
onGroupNameChange(event.target.value)}
disabled={isAdding || scanInProgress}
@@ -109,14 +135,23 @@ export function AddRepoNestedImportStep({
disabled={isAdding || scanInProgress || selectedPaths.size === 0}
variant={isFirstRepoImport ? 'default' : 'outline'}
>
- {isFirstRepoImport ? translate("auto.components.sidebar.AddRepoNestedImportStep.cf9d382ca1", "Import") : translate("auto.components.sidebar.AddRepoNestedImportStep.5b2e6fe3c8", "Import separately")}
+ {isFirstRepoImport
+ ? translate('auto.components.sidebar.AddRepoNestedImportStep.cf9d382ca1', 'Import')
+ : translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.5b2e6fe3c8',
+ 'Import separately'
+ )}
{!isFirstRepoImport ? (
onImport('group')}
disabled={isAdding || scanInProgress || selectedPaths.size === 0}
>
- {translate("auto.components.sidebar.AddRepoNestedImportStep.c157f31a95", "Import as group")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.c157f31a95',
+ 'Import as group'
+ )}
+
) : null}
@@ -137,8 +172,14 @@ function AddRepoNestedImportStopButton({
variant="ghost"
size="icon-xs"
className="group text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:bg-destructive/10 focus-visible:text-destructive focus-visible:ring-destructive/40"
- aria-label={translate("auto.components.sidebar.AddRepoNestedImportStep.2f8298f3c3", "Stop scan")}
- title={translate("auto.components.sidebar.AddRepoNestedImportStep.a32bef9516", "Stop scanning")}
+ aria-label={translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.2f8298f3c3',
+ 'Stop scan'
+ )}
+ title={translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.a32bef9516',
+ 'Stop scanning'
+ )}
onClick={onStopScan}
>
@@ -146,7 +187,11 @@ function AddRepoNestedImportStopButton({
- {translate("auto.components.sidebar.AddRepoNestedImportStep.496f68cf8c", "Scanning repositories. Click to stop.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoNestedImportStep.496f68cf8c',
+ 'Scanning repositories. Click to stop.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx b/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx
index 0c3fc6795ae..8332415fa2a 100644
--- a/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoRemoteStep.tsx
@@ -43,9 +43,18 @@ export function RemoteStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoRemoteStep.dd3ff65486", "Browse remote filesystem")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.dd3ff65486',
+ 'Browse remote filesystem'
+ )}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.007651bdf9", "Navigate to a directory and click Select to choose it.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.007651bdf9',
+ 'Navigate to a directory and click Select to choose it.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.91b93a90a4", "Open remote project")}
+
+ {translate('auto.components.sidebar.AddRepoRemoteStep.91b93a90a4', 'Open remote project')}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.80557be85a", "Choose a connected SSH target and enter the path to a Git repository.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.80557be85a',
+ 'Choose a connected SSH target and enter the path to a Git repository.'
+ )}
+
-
{translate("auto.components.sidebar.AddRepoRemoteStep.44637f43bd", "SSH target")}
+
+ {translate('auto.components.sidebar.AddRepoRemoteStep.44637f43bd', 'SSH target')}
+
{sshTargets.length === 0 ? (
-
{translate("auto.components.sidebar.AddRepoRemoteStep.df6fbcf880", "No SSH targets configured.")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.df6fbcf880',
+ 'No SSH targets configured.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoRemoteStep.0416bde073", "Add in Settings")}
+ {translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.0416bde073',
+ 'Add in Settings'
+ )}
+
) : (
@@ -99,7 +125,9 @@ export function RemoteStep({
-
{translate("auto.components.sidebar.AddRepoRemoteStep.ef410aa881", "Remote path")}
+
+ {translate('auto.components.sidebar.AddRepoRemoteStep.ef410aa881', 'Remote path')}
+
@@ -135,12 +166,18 @@ export function RemoteStep({
disabled={!selectedTargetId || !remotePath.trim() || isAddingRemote}
className="w-full"
>
- {isAddingRemote ? translate("auto.components.sidebar.AddRepoRemoteStep.35831a7312", "Adding...") : translate("auto.components.sidebar.AddRepoRemoteStep.36d427bb66", "Add remote project")}
+ {isAddingRemote
+ ? translate('auto.components.sidebar.AddRepoRemoteStep.35831a7312', 'Adding...')
+ : translate(
+ 'auto.components.sidebar.AddRepoRemoteStep.36d427bb66',
+ 'Add remote project'
+ )}
{isScanningNested ? (
- {translate("auto.components.sidebar.AddRepoRemoteStep.5b205b5281", "Stop scan")}
+ {translate('auto.components.sidebar.AddRepoRemoteStep.5b205b5281', 'Stop scan')}
+
) : null}
>
diff --git a/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx b/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx
index 2667032d3c3..98b2f01fee9 100644
--- a/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoServerStartStep.tsx
@@ -35,9 +35,18 @@ export function AddRepoServerPathStartStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d", "Browse server filesystem")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d',
+ 'Browse server filesystem'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.0f8aba944c", "Navigate to a directory and click Select to choose it.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.0f8aba944c',
+ 'Navigate to a directory and click Select to choose it.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.39bd249b3a", "Add a project")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.39bd249b3a',
+ 'Add a project'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.8efa930eb5", "Add another project from the selected runtime server.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.8efa930eb5',
+ 'Add another project from the selected runtime server.'
+ )}
+
setBrowsing(true)}
/>
@@ -94,7 +130,11 @@ export function AddRepoServerPathStartStep({
- {translate("auto.components.sidebar.AddRepoServerStartStep.6b9958492a", "Want to import many repos at once? Browse to the parent folder.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.6b9958492a',
+ 'Want to import many repos at once? Browse to the parent folder.'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.438493f214", "Or enter a server path manually")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.438493f214',
+ 'Or enter a server path manually'
+ )}
+
>
)
@@ -112,9 +156,18 @@ export function AddRepoServerPathStartStep({
return (
<>
- {translate("auto.components.sidebar.AddRepoServerStartStep.3d0c035483", "Open server project")}
+
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.3d0c035483',
+ 'Open server project'
+ )}
+
- {translate("auto.components.sidebar.AddRepoServerStartStep.423b5d3d31", "Add a Git repository or folder that already exists on the selected runtime server.")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.423b5d3d31',
+ 'Add a Git repository or folder that already exists on the selected runtime server.'
+ )}
+
@@ -123,13 +176,17 @@ export function AddRepoServerPathStartStep({
htmlFor="server-project-path"
className="block text-[11px] font-medium text-muted-foreground"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.867692f505", "Server path")}
+ {translate('auto.components.sidebar.AddRepoServerStartStep.867692f505', 'Server path')}
+
onServerPathChange(event.target.value)}
- placeholder={translate("auto.components.sidebar.AddRepoServerStartStep.92d25420a0", "/home/user/project")}
+ placeholder={translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.92d25420a0',
+ '/home/user/project'
+ )}
className="h-11 min-w-0 flex-1 font-mono text-sm"
disabled={isAddingServerPath}
autoFocus
@@ -144,13 +201,20 @@ export function AddRepoServerPathStartStep({
className="h-11 w-11 shrink-0"
onClick={() => setBrowsing(true)}
disabled={isAddingServerPath || !runtimeEnvironmentId}
- aria-label={translate("auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d", "Browse server filesystem")}
+ aria-label={translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d',
+ 'Browse server filesystem'
+ )}
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d", "Browse server filesystem")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ac66a3ed2d',
+ 'Browse server filesystem'
+ )}
+
@@ -160,14 +224,22 @@ export function AddRepoServerPathStartStep({
disabled={!serverPath.trim() || isAddingServerPath}
className="h-10"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.8da4d1a5be", "Add Git Project")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.8da4d1a5be',
+ 'Add Git Project'
+ )}
+
onAddServerPath('folder')}
disabled={!serverPath.trim() || isAddingServerPath}
variant="outline"
className="h-10"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.e1710bf831", "Open as Folder")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.e1710bf831',
+ 'Open as Folder'
+ )}
+
{isAddingServerPath && addProjectBusyLabel ? (
@@ -181,7 +253,11 @@ export function AddRepoServerPathStartStep({
disabled={isAddingServerPath}
className="mx-auto block rounded px-2 py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-default disabled:opacity-40"
>
- {translate("auto.components.sidebar.AddRepoServerStartStep.ae990c86a0", "Back to add options")}
+ {translate(
+ 'auto.components.sidebar.AddRepoServerStartStep.ae990c86a0',
+ 'Back to add options'
+ )}
+
>
)
diff --git a/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx b/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx
index 80337443f4a..514d4f6af1a 100644
--- a/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoStepIndicator.tsx
@@ -27,7 +27,8 @@ export function AddRepoStepIndicator({
onClick={onBack}
>
- {translate("auto.components.sidebar.AddRepoStepIndicator.3bb655c117", "Back")}
+ {translate('auto.components.sidebar.AddRepoStepIndicator.3bb655c117', 'Back')}
+
)
}
diff --git a/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx b/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx
index 3b386bf5227..12fddd8ee40 100644
--- a/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx
+++ b/src/renderer/src/components/sidebar/AutoRenameFailedDialog.tsx
@@ -66,22 +66,46 @@ export function AutoRenameFailedDialog({
- {translate("auto.components.sidebar.AutoRenameFailedDialog.ca3b225195", "Branch auto-name failed")}
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.ca3b225195',
+ 'Branch auto-name failed'
+ )}
+
- {translate("auto.components.sidebar.AutoRenameFailedDialog.ff62a18580", "Orca couldn't generate a branch name for")}{' '}
- {worktreeName} {translate("auto.components.sidebar.AutoRenameFailedDialog.3afcad0497", "from the first agent message.")}
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.ff62a18580',
+ "Orca couldn't generate a branch name for"
+ )}{' '}
+
{worktreeName} {' '}
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.3afcad0497',
+ 'from the first agent message.'
+ )}
+
{/* Why: agent-CLI output is literal and often multi-line, so render it
verbatim (mono, wrapped) inside a height-capped scroll region. */}
-
{translate("auto.components.sidebar.AutoRenameFailedDialog.74fc00776f", "Error details")}
+
+ {translate(
+ 'auto.components.sidebar.AutoRenameFailedDialog.74fc00776f',
+ 'Error details'
+ )}
+
onOpenChange(false)}>
- {translate("auto.components.sidebar.AutoRenameFailedDialog.aed1623b1e", "Close")}
+ {translate('auto.components.sidebar.AutoRenameFailedDialog.aed1623b1e', 'Close')}
+
diff --git a/src/renderer/src/components/sidebar/CacheTimer.tsx b/src/renderer/src/components/sidebar/CacheTimer.tsx
index 4155f83b751..4baf4ecf805 100644
--- a/src/renderer/src/components/sidebar/CacheTimer.tsx
+++ b/src/renderer/src/components/sidebar/CacheTimer.tsx
@@ -65,7 +65,11 @@ export default function CacheTimer({
)}
>
- {expired ? translate("auto.components.sidebar.CacheTimer.07729cc155", "expired") : label}
+
+ {expired
+ ? translate('auto.components.sidebar.CacheTimer.07729cc155', 'expired')
+ : label}
+
diff --git a/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx b/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
index 463f07a1e0b..025045b7938 100644
--- a/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
+++ b/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
@@ -22,9 +22,18 @@ export function CreateProjectParentBrowser({
return (
<>
- {translate("auto.components.sidebar.CreateProjectLocationField.f520f83a97", "Browse server filesystem")}
+
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.f520f83a97',
+ 'Browse server filesystem'
+ )}
+
- {translate("auto.components.sidebar.CreateProjectLocationField.b589b77997", "Navigate to a directory and click Select to choose it.")}
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.b589b77997',
+ 'Navigate to a directory and click Select to choose it.'
+ )}
+
- {translate("auto.components.sidebar.CreateProjectLocationField.134e37f711", "Location")}
+
+ {translate('auto.components.sidebar.CreateProjectLocationField.134e37f711', 'Location')}
+
{manualParentEntry ? (
onParentChange(e.target.value)}
- placeholder={translate("auto.components.sidebar.CreateProjectLocationField.2a20a603a3", "/home/user/projects")}
+ placeholder={translate(
+ 'auto.components.sidebar.CreateProjectLocationField.2a20a603a3',
+ '/home/user/projects'
+ )}
className="h-11 min-w-0 flex-1 text-sm font-mono"
disabled={isCreating}
spellCheck={false}
@@ -81,13 +95,20 @@ export function CreateProjectLocationField({
className="h-11 w-11 shrink-0"
onClick={onBrowseServer}
disabled={isCreating || !runtimeEnvironmentId}
- aria-label={translate("auto.components.sidebar.CreateProjectLocationField.f520f83a97", "Browse server filesystem")}
+ aria-label={translate(
+ 'auto.components.sidebar.CreateProjectLocationField.f520f83a97',
+ 'Browse server filesystem'
+ )}
>
- {translate("auto.components.sidebar.CreateProjectLocationField.f520f83a97", "Browse server filesystem")}
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.f520f83a97',
+ 'Browse server filesystem'
+ )}
+
) : createParent ? (
@@ -103,10 +124,14 @@ export function CreateProjectLocationField({
onClick={onPickParent}
disabled={isCreating}
className="shrink-0 inline-flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:cursor-not-allowed"
- aria-label={translate("auto.components.sidebar.CreateProjectLocationField.afaf54f245", "Change parent folder")}
+ aria-label={translate(
+ 'auto.components.sidebar.CreateProjectLocationField.afaf54f245',
+ 'Change parent folder'
+ )}
>
- {translate("auto.components.sidebar.CreateProjectLocationField.632b456b1b", "Change")}
+ {translate('auto.components.sidebar.CreateProjectLocationField.632b456b1b', 'Change')}
+
) : (
- {translate("auto.components.sidebar.CreateProjectLocationField.95548e33bf", "Choose parent folder...")}
+ {translate(
+ 'auto.components.sidebar.CreateProjectLocationField.95548e33bf',
+ 'Choose parent folder...'
+ )}
+
)}
)
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx
index 33fa7ab12bc..e77787f23ee 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeDialogFooter.tsx
@@ -43,7 +43,9 @@ export function DeleteWorktreeDialogFooter({
return (
<>
- {isMainWorktree ? translate("auto.components.sidebar.DeleteWorktreeDialogFooter.cf95e3b5bb", "Close") : translate("auto.components.sidebar.DeleteWorktreeDialogFooter.c0e972d726", "Cancel")}
+ {isMainWorktree
+ ? translate('auto.components.sidebar.DeleteWorktreeDialogFooter.cf95e3b5bb', 'Close')
+ : translate('auto.components.sidebar.DeleteWorktreeDialogFooter.c0e972d726', 'Cancel')}
{!isMainWorktree && (
- {translate("auto.components.sidebar.DeleteWorktreeDirtyChangeHint.8e2994ce28", "Deleting this workspace permanently removes these changes from disk.")}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeDirtyChangeHint.8e2994ce28',
+ 'Deleting this workspace permanently removes these changes from disk.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx
index cc44246147e..427b96308cc 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeLineageNotice.tsx
@@ -23,11 +23,23 @@ export function DeleteWorktreeLineageNotice({
-
{translate("auto.components.sidebar.DeleteWorktreeLineageNotice.a940f3c96e", "Child workspaces will be deleted")}
+
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.a940f3c96e',
+ 'Child workspaces will be deleted'
+ )}
+
{childWorkspaceCount === 1
- ? translate("auto.components.sidebar.DeleteWorktreeLineageNotice.66798cc6a2", "Deleting this workspace also deletes 1 child workspace.")
- : translate("auto.components.sidebar.DeleteWorktreeLineageNotice.29b98bf9cd", "Deleting this workspace also deletes {{value0}} child workspaces.", { value0: childWorkspaceCount })}
+ ? translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.66798cc6a2',
+ 'Deleting this workspace also deletes 1 child workspace.'
+ )
+ : translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.29b98bf9cd',
+ 'Deleting this workspace also deletes {{value0}} child workspaces.',
+ { value0: childWorkspaceCount }
+ )}
{/* Why: long nowrap paths can otherwise give this grid child an
intrinsic width wider than the modal. */}
@@ -42,7 +54,13 @@ export function DeleteWorktreeLineageNotice({
))}
{descendants.length > 4 ? (
-
+{descendants.length - 4} {translate("auto.components.sidebar.DeleteWorktreeLineageNotice.ad407c2d55", "more")}
+
+ +{descendants.length - 4}{' '}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeLineageNotice.ad407c2d55',
+ 'more'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx
index 15f26de743f..67ca3a0ee21 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeSkipConfirmOption.tsx
@@ -32,6 +32,10 @@ export function DeleteWorktreeSkipConfirmOption({
>
{dontAskAgain ?
: null}
- {translate("auto.components.sidebar.DeleteWorktreeSkipConfirmOption.29aefb7e52", "Don't ask again")}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeSkipConfirmOption.29aefb7e52',
+ "Don't ask again"
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx b/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx
index 9bb0b37e2f9..89b22f6c841 100644
--- a/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx
+++ b/src/renderer/src/components/sidebar/DeleteWorktreeWarningPanels.tsx
@@ -18,7 +18,21 @@ export function DeleteWorktreeWarningPanels({
- {translate("auto.components.sidebar.DeleteWorktreeWarningPanels.e3be9eba15", "This is the")}{translate("auto.components.sidebar.DeleteWorktreeWarningPanels.c4f96a6e18", "main worktree")} {translate("auto.components.sidebar.DeleteWorktreeWarningPanels.026738155a", "(the original clone directory).")}{mainWorktreeBlocker}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeWarningPanels.e3be9eba15',
+ 'This is the'
+ )}
+
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeWarningPanels.c4f96a6e18',
+ 'main worktree'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.DeleteWorktreeWarningPanels.026738155a',
+ '(the original clone directory).'
+ )}
+ {mainWorktreeBlocker}
diff --git a/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx b/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx
index 84c4c05a632..4699f98a395 100644
--- a/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx
+++ b/src/renderer/src/components/sidebar/ImportedWorktreesVisibilityLine.tsx
@@ -130,7 +130,11 @@ export default function ImportedWorktreesVisibilityLine({
size="icon-xs"
disabled={pending}
aria-expanded={isExpanded}
- aria-label={translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.f54f2bec5d", "{{value0}} hidden worktrees for {{value1}}", { value0: isExpanded ? 'Collapse' : 'Expand', value1: repoDisplayName })}
+ aria-label={translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.f54f2bec5d',
+ '{{value0}} hidden worktrees for {{value1}}',
+ { value0: isExpanded ? 'Collapse' : 'Expand', value1: repoDisplayName }
+ )}
onClick={() => setIsExpanded((value) => !value)}
className="shrink-0 rounded-[4px] text-muted-foreground hover:bg-worktree-sidebar-accent hover:text-worktree-sidebar-accent-foreground"
>
@@ -166,7 +170,10 @@ export default function ImportedWorktreesVisibilityLine({
{isExpanded ? (
{visibleWorktreeGroups.map((group) => (
@@ -190,7 +197,11 @@ export default function ImportedWorktreesVisibilityLine({
{group.worktrees
.slice(
@@ -220,8 +231,15 @@ export default function ImportedWorktreesVisibilityLine({
className="h-6 justify-start px-0 text-[11px] font-normal text-muted-foreground hover:text-worktree-sidebar-accent-foreground"
>
{expandedGroupPathKeys.has(normalizeRuntimePathForComparison(group.path))
- ? translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.294de4aeb2", "Show fewer")
- : translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.5a9688802a", "Show {{value0}} more", { value0: group.worktrees.length - PREVIEW_LIMIT })}
+ ? translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.294de4aeb2',
+ 'Show fewer'
+ )
+ : translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.5a9688802a',
+ 'Show {{value0}} more',
+ { value0: group.worktrees.length - PREVIEW_LIMIT }
+ )}
) : null}
@@ -230,11 +248,20 @@ export default function ImportedWorktreesVisibilityLine({
))}
{remainingGroupCount > 0 ? (
- + {remainingGroupCount} {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.b2bc47c080", "more locations")}
+ + {remainingGroupCount}{' '}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.b2bc47c080',
+ 'more locations'
+ )}
+
) : null}
- {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.9f4f14e821", "Change this later from the project menu.")}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.9f4f14e821',
+ 'Change this later from the project menu.'
+ )}
+
{onKeepHidden ? (
- {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.ad99f4eea9", "Keep hidden")}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.ad99f4eea9',
+ 'Keep hidden'
+ )}
+
) : null}
{onShow ? (
- {translate("auto.components.sidebar.ImportedWorktreesVisibilityLine.b7a87dc32f", "Show in worktree list")}
+ {translate(
+ 'auto.components.sidebar.ImportedWorktreesVisibilityLine.b7a87dc32f',
+ 'Show in worktree list'
+ )}
+
) : null}
diff --git a/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx b/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx
index dbb21e0a436..1e9ef329da3 100644
--- a/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx
+++ b/src/renderer/src/components/sidebar/NonGitFolderDialog.tsx
@@ -68,7 +68,14 @@ const NonGitFolderDialog = React.memo(function NonGitFolderDialog() {
} catch (err) {
// This code path calls addRemote directly (not through the store),
// so the store's toast handling does not apply.
- toast.error(err instanceof Error ? err.message : translate("auto.components.sidebar.NonGitFolderDialog.c49fb13492", "Failed to add remote folder"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.sidebar.NonGitFolderDialog.c49fb13492',
+ 'Failed to add remote folder'
+ )
+ )
}
})()
} else if (folderPath) {
@@ -90,9 +97,15 @@ const NonGitFolderDialog = React.memo(function NonGitFolderDialog() {
- {translate("auto.components.sidebar.NonGitFolderDialog.e52454b7f6", "Open as Folder")}
+
+ {translate('auto.components.sidebar.NonGitFolderDialog.e52454b7f6', 'Open as Folder')}
+
- {translate("auto.components.sidebar.NonGitFolderDialog.8fba4b8cbb", "This folder isn't a Git repository. You'll have the editor, terminal, and search, but Git-based features won't be available.")}
+ {translate(
+ 'auto.components.sidebar.NonGitFolderDialog.8fba4b8cbb',
+ "This folder isn't a Git repository. You'll have the editor, terminal, and search, but Git-based features won't be available."
+ )}
+
{folderPath && (
@@ -103,8 +116,11 @@ const NonGitFolderDialog = React.memo(function NonGitFolderDialog() {
handleOpenChange(false)}>
- {translate("auto.components.sidebar.NonGitFolderDialog.05b33a17a9", "Cancel")}
- {translate("auto.components.sidebar.NonGitFolderDialog.e52454b7f6", "Open as Folder")}
+ {translate('auto.components.sidebar.NonGitFolderDialog.05b33a17a9', 'Cancel')}
+
+
+ {translate('auto.components.sidebar.NonGitFolderDialog.e52454b7f6', 'Open as Folder')}
+
diff --git a/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx b/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx
index d24ccde4747..7b341a3ab15 100644
--- a/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx
+++ b/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx
@@ -104,19 +104,48 @@ const OrcaYamlTrustDialog = React.memo(function OrcaYamlTrustDialog() {
{previouslyApproved
- ? translate("auto.components.sidebar.OrcaYamlTrustDialog.02b0ede5ad", "{{value0}}'s {{value1}} changed — run the new version?", { value0: repoName, value1: SCRIPT_KIND_LABEL[scriptKind] })
- : translate("auto.components.sidebar.OrcaYamlTrustDialog.e4a51dc4b3", "Run {{value0}} from {{value1}}?", { value0: SCRIPT_KIND_LABEL[scriptKind], value1: repoName })}
+ ? translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.02b0ede5ad',
+ "{{value0}}'s {{value1}} changed — run the new version?",
+ { value0: repoName, value1: SCRIPT_KIND_LABEL[scriptKind] }
+ )
+ : translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.e4a51dc4b3',
+ 'Run {{value0}} from {{value1}}?',
+ { value0: SCRIPT_KIND_LABEL[scriptKind], value1: repoName }
+ )}
{previouslyApproved ? (
<>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b", "orca.yaml")} {translate("auto.components.sidebar.OrcaYamlTrustDialog.c55beddbf8", "changed since you last approved. Re-review before it runs")}{' '}
+
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b', 'orca.yaml')}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.c55beddbf8',
+ 'changed since you last approved. Re-review before it runs'
+ )}{' '}
{SCRIPT_KIND_TRIGGER[scriptKind]}.
>
) : (
<>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.aa3ffb33fb", "This repository's")}{translate("auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b", "orca.yaml")} {translate("auto.components.sidebar.OrcaYamlTrustDialog.831f2cd9f0", "runs on your machine")}{' '}
- {SCRIPT_KIND_TRIGGER[scriptKind]}{translate("auto.components.sidebar.OrcaYamlTrustDialog.bf800b7e04", ". Only run if you trust")}{repoName}.
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.aa3ffb33fb',
+ "This repository's"
+ )}
+
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b', 'orca.yaml')}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.831f2cd9f0',
+ 'runs on your machine'
+ )}{' '}
+ {SCRIPT_KIND_TRIGGER[scriptKind]}
+ {translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.bf800b7e04',
+ '. Only run if you trust'
+ )}
+ {repoName}.
>
)}
@@ -125,7 +154,17 @@ const OrcaYamlTrustDialog = React.memo(function OrcaYamlTrustDialog() {
{scriptContent && (
- {previouslyApproved ? translate("auto.components.sidebar.OrcaYamlTrustDialog.9e52effffd", "New {{value0}} script", { value0: scriptKind }) : translate("auto.components.sidebar.OrcaYamlTrustDialog.95bf974a1a", "{{value0}} script", { value0: scriptKind })}
+ {previouslyApproved
+ ? translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.9e52effffd',
+ 'New {{value0}} script',
+ { value0: scriptKind }
+ )
+ : translate(
+ 'auto.components.sidebar.OrcaYamlTrustDialog.95bf974a1a',
+ '{{value0}} script',
+ { value0: scriptKind }
+ )}
{scriptContent}
@@ -147,14 +186,22 @@ const OrcaYamlTrustDialog = React.memo(function OrcaYamlTrustDialog() {
onChange={(event) => setAlwaysTrust(event.target.checked)}
/>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.531689199b", "Always trust")}{translate("auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b", "orca.yaml")} {translate("auto.components.sidebar.OrcaYamlTrustDialog.c494b3ccb1", "in")}{repoName}
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.531689199b', 'Always trust')}
+
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.79afc6772b', 'orca.yaml')}
+ {' '}
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.c494b3ccb1', 'in')}
+ {repoName}
resolveAndClose('skip')}>
- {translate("auto.components.sidebar.OrcaYamlTrustDialog.43b7bec4cd", "Don't run")}
- resolveAndClose('run')}>{translate("auto.components.sidebar.OrcaYamlTrustDialog.f3e2b868fb", "Run hooks")}
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.43b7bec4cd', "Don't run")}
+
+ resolveAndClose('run')}>
+ {translate('auto.components.sidebar.OrcaYamlTrustDialog.f3e2b868fb', 'Run hooks')}
+
diff --git a/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx b/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx
index 47b569bd558..38b66950e49 100644
--- a/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx
+++ b/src/renderer/src/components/sidebar/PendingWorktreeRow.tsx
@@ -76,8 +76,11 @@ export function PendingWorktreeRow({
useAppStore.getState().removePendingWorktreeCreation(creationId)}
className={cn(
'mr-1 flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground transition-opacity hover:bg-sidebar-accent hover:text-foreground focus-visible:opacity-100',
diff --git a/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx b/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx
index c907be3d5a8..4dfeb1a6490 100644
--- a/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx
+++ b/src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx
@@ -77,9 +77,20 @@ export function ProjectGroupDeleteDialog({
showCloseButton={false}
>
- {translate("auto.components.sidebar.ProjectGroupDeleteDialog.591f330288", "Delete Project Group")}
+
+ {translate(
+ 'auto.components.sidebar.ProjectGroupDeleteDialog.591f330288',
+ 'Delete Project Group'
+ )}
+
- {translate("auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0", "Delete")}{groupName} {translate("auto.components.sidebar.ProjectGroupDeleteDialog.9be10d49ea", "and ungroup its projects.")}
+ {translate('auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0', 'Delete')}
+ {groupName} {' '}
+ {translate(
+ 'auto.components.sidebar.ProjectGroupDeleteDialog.9be10d49ea',
+ 'and ungroup its projects.'
+ )}
+
onOpenChange(false)}
>
- {translate("auto.components.sidebar.ProjectGroupDeleteDialog.ca65b78f78", "Cancel")}
+ {translate('auto.components.sidebar.ProjectGroupDeleteDialog.ca65b78f78', 'Cancel')}
+
- {deleting ? translate("auto.components.sidebar.ProjectGroupDeleteDialog.2c14ce677a", "Deleting...") : translate("auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0", "Delete")}
+ {deleting
+ ? translate(
+ 'auto.components.sidebar.ProjectGroupDeleteDialog.2c14ce677a',
+ 'Deleting...'
+ )
+ : translate('auto.components.sidebar.ProjectGroupDeleteDialog.69f5cb97d0', 'Delete')}
diff --git a/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx b/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx
index 11ac3140394..e2cbc96db3f 100644
--- a/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx
+++ b/src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx
@@ -95,7 +95,8 @@ export function ProjectGroupNameDialog({
- {translate("auto.components.sidebar.ProjectGroupNameDialog.83dfbc5313", "Group Name")}
+ {translate('auto.components.sidebar.ProjectGroupNameDialog.83dfbc5313', 'Group Name')}
+
onOpenChange(false)}
>
- {translate("auto.components.sidebar.ProjectGroupNameDialog.d99a034073", "Cancel")}
+ {translate('auto.components.sidebar.ProjectGroupNameDialog.d99a034073', 'Cancel')}
+
- {submitting ? translate("auto.components.sidebar.ProjectGroupNameDialog.4a64e78822", "Saving...") : confirmLabel}
+ {submitting
+ ? translate(
+ 'auto.components.sidebar.ProjectGroupNameDialog.4a64e78822',
+ 'Saving...'
+ )
+ : confirmLabel}
diff --git a/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx b/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx
index 465f68aa3e7..2abaebe4365 100644
--- a/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx
+++ b/src/renderer/src/components/sidebar/RemoteFileBrowser.tsx
@@ -639,7 +639,10 @@ export function RemoteFileBrowser({
onChange={(e) => handleInputChange(e.target.value)}
onPaste={handleInputPaste}
onKeyDown={handleFilterKeyDown}
- placeholder={translate("auto.components.sidebar.RemoteFileBrowser.2300612806", "Type to filter or enter a path…")}
+ placeholder={translate(
+ 'auto.components.sidebar.RemoteFileBrowser.2300612806',
+ 'Type to filter or enter a path…'
+ )}
aria-invalid={!!preview?.error}
aria-describedby={preview?.error ? 'remote-file-browser-path-error' : undefined}
className={cn(
@@ -683,13 +686,24 @@ export function RemoteFileBrowser({
) : !isPreviewActive && entries.length === 0 ? (
-
{translate("auto.components.sidebar.RemoteFileBrowser.51001182e3", "Empty directory")}
+
+ {translate(
+ 'auto.components.sidebar.RemoteFileBrowser.51001182e3',
+ 'Empty directory'
+ )}
+
) : displayEntries.length === 0 && !preview?.error ? (
// Directory has contents; filter hides them all. Distinguishing
// filter emptiness from directory emptiness keeps copy accurate.
-
{translate("auto.components.sidebar.RemoteFileBrowser.00c4235c10", "No matches for '{{value0}}'", { value0: isPreviewActive ? preview!.filter : filter })}
+
+ {translate(
+ 'auto.components.sidebar.RemoteFileBrowser.00c4235c10',
+ "No matches for '{{value0}}'",
+ { value0: isPreviewActive ? preview!.filter : filter }
+ )}
+
) : (
displayEntries.map((entry) => {
@@ -730,11 +744,18 @@ export function RemoteFileBrowser({
className="block text-[10px] text-muted-foreground truncate w-full"
title={fileHint ? undefined : resolvedPath}
>
- {fileHint ? FILE_HINT_TEXT : translate("auto.components.sidebar.RemoteFileBrowser.971d85cc84", "Opens as a remote project · {{value0}}", { value0: resolvedPath })}
+ {fileHint
+ ? FILE_HINT_TEXT
+ : translate(
+ 'auto.components.sidebar.RemoteFileBrowser.971d85cc84',
+ 'Opens as a remote project · {{value0}}',
+ { value0: resolvedPath }
+ )}
- {translate("auto.components.sidebar.RemoteFileBrowser.f8b1deb1a4", "Cancel")}
+ {translate('auto.components.sidebar.RemoteFileBrowser.f8b1deb1a4', 'Cancel')}
+
- {translate("auto.components.sidebar.RemoteFileBrowser.9e060f5815", "Select folder")}
+ {translate('auto.components.sidebar.RemoteFileBrowser.9e060f5815', 'Select folder')}
+
)
diff --git a/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx b/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx
index 2f6e8d4502c..8e37ecf0aed 100644
--- a/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx
+++ b/src/renderer/src/components/sidebar/RemoveFolderDialog.tsx
@@ -41,16 +41,28 @@ const RemoveFolderDialog = React.memo(function RemoveFolderDialog() {
- {translate("auto.components.sidebar.RemoveFolderDialog.b79b39d865", "Remove Project")}
+
+ {translate('auto.components.sidebar.RemoveFolderDialog.b79b39d865', 'Remove Project')}
+
- {translate("auto.components.sidebar.RemoveFolderDialog.e62415c3d0", "This only removes")}{' '}
- {displayName} {translate("auto.components.sidebar.RemoveFolderDialog.8c097ef04e", "from Orca. It is still on your disk.")}
+ {translate(
+ 'auto.components.sidebar.RemoveFolderDialog.e62415c3d0',
+ 'This only removes'
+ )}{' '}
+ {displayName} {' '}
+ {translate(
+ 'auto.components.sidebar.RemoveFolderDialog.8c097ef04e',
+ 'from Orca. It is still on your disk.'
+ )}
+
handleOpenChange(false)}>
- {translate("auto.components.sidebar.RemoveFolderDialog.d36883e046", "Cancel")}
+ {translate('auto.components.sidebar.RemoveFolderDialog.d36883e046', 'Cancel')}
+
- {translate("auto.components.sidebar.RemoveFolderDialog.4dc5b5065b", "Remove")}
+ {translate('auto.components.sidebar.RemoveFolderDialog.4dc5b5065b', 'Remove')}
+
diff --git a/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx b/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx
index 177a1b69d35..0ac1b3241b4 100644
--- a/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx
+++ b/src/renderer/src/components/sidebar/ScrollToCurrentWorkspaceToolbarButton.tsx
@@ -13,7 +13,10 @@ export function ScrollToCurrentWorkspaceToolbarButton(): React.JSX.Element {
variant="ghost"
size="icon-xs"
type="button"
- aria-label={translate("auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663", "Reveal active workspace")}
+ aria-label={translate(
+ 'auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663',
+ 'Reveal active workspace'
+ )}
onClick={requestScrollToCurrentWorkspaceReveal}
className="text-muted-foreground"
>
@@ -21,7 +24,11 @@ export function ScrollToCurrentWorkspaceToolbarButton(): React.JSX.Element {
- {translate("auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663", "Reveal active workspace")}
+ {translate(
+ 'auto.components.sidebar.ScrollToCurrentWorkspaceToolbarButton.23989bb663',
+ 'Reveal active workspace'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx b/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx
index 4dbba6d943e..7cbaf215812 100644
--- a/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx
+++ b/src/renderer/src/components/sidebar/SetupGuideSidebarEntry.tsx
@@ -92,14 +92,23 @@ export function SetupGuideSidebarEntry(): React.JSX.Element | null {
sizeClassName="size-4"
/>
- {translate("auto.components.sidebar.SetupGuideSidebarEntry.88d402b71d", "Onboarding checklist")}
+
+ {translate(
+ 'auto.components.sidebar.SetupGuideSidebarEntry.88d402b71d',
+ 'Onboarding checklist'
+ )}
+
- {translate("auto.components.sidebar.SetupGuideSidebarEntry.b0a7bfc34c", "Hide from sidebar")}
+ {translate(
+ 'auto.components.sidebar.SetupGuideSidebarEntry.b0a7bfc34c',
+ 'Hide from sidebar'
+ )}
+
)
diff --git a/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx b/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx
index 8f3428df6a5..810b468a859 100644
--- a/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx
+++ b/src/renderer/src/components/sidebar/SetupScriptPromptCardViews.tsx
@@ -17,7 +17,10 @@ function DismissButton({ onDismiss }: DismissButtonProps): React.JSX.Element {
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.sidebar.SetupScriptPromptCardViews.5bfd5c8779", "Dismiss setup scripts")}
+ aria-label={translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.5bfd5c8779',
+ 'Dismiss setup scripts'
+ )}
className="-mr-1 text-muted-foreground"
onClick={onDismiss}
>
@@ -25,7 +28,8 @@ function DismissButton({ onDismiss }: DismissButtonProps): React.JSX.Element {
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.822ff300ad", "Dismiss")}
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.822ff300ad', 'Dismiss')}
+
)
}
@@ -45,10 +49,17 @@ export function DetectedSetupPreview({
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.7275f674cc", "Detected setup")}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.7275f674cc',
+ 'Detected setup'
+ )}
+
onSetupChange(event.target.value)}
spellCheck={false}
rows={Math.min(Math.max(setup.split('\n').length, 2), 6)}
@@ -56,7 +67,11 @@ export function DetectedSetupPreview({
/>
{provenance ? (
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.d02e6a42b1", "Detected from")}{provenance}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.d02e6a42b1',
+ 'Detected from'
+ )}
+ {provenance}
) : null}
@@ -89,7 +104,9 @@ export function PackageManagerActions({
) : (
)}
-
{translate("auto.components.sidebar.SetupScriptPromptCardViews.ca4efcbc25", "Save")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.ca4efcbc25', 'Save')}
+
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.eefa756190", "Configure manually")}
+
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.eefa756190',
+ 'Configure manually'
+ )}
+
)
@@ -119,24 +141,65 @@ export function SetupScriptPromptBody({
candidateSource
}: SetupScriptPromptBodyProps): React.JSX.Element {
if (isInspectionError) {
- return <>{translate("auto.components.sidebar.SetupScriptPromptCardViews.0155fb9ed3", "Couldn't verify this repo's setup script right now.")}>
+ return (
+ <>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.0155fb9ed3',
+ "Couldn't verify this repo's setup script right now."
+ )}
+ >
+ )
}
if (sharedSetupIgnored) {
return (
<>
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.bb879db364", "This repo ignores shared")}{translate("auto.components.sidebar.SetupScriptPromptCardViews.8f6be51aa1", "orca.yaml")} {translate("auto.components.sidebar.SetupScriptPromptCardViews.660cdc17f8", "setup scripts. Add a local command, or change the source in Settings.")}>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.bb879db364',
+ 'This repo ignores shared'
+ )}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.8f6be51aa1', 'orca.yaml')}
+ {' '}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.660cdc17f8',
+ 'setup scripts. Add a local command, or change the source in Settings.'
+ )}
+ >
)
}
if (isPackageManagerSuggestion) {
- return <>{translate("auto.components.sidebar.SetupScriptPromptCardViews.aef6c0a213", "Save the detected command to run it whenever Orca creates a worktree.")}>
+ return (
+ <>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.aef6c0a213',
+ 'Save the detected command to run it whenever Orca creates a worktree.'
+ )}
+ >
+ )
}
if (candidateSource) {
return (
<>
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.b56d1322f7", "Found a setup command in")}{candidateSource} {translate("auto.components.sidebar.SetupScriptPromptCardViews.8349e3fa4c", ". Save it to run for new worktrees.")}>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.b56d1322f7',
+ 'Found a setup command in'
+ )}
+ {candidateSource}
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.8349e3fa4c',
+ '. Save it to run for new worktrees.'
+ )}
+ >
)
}
- return <>{translate("auto.components.sidebar.SetupScriptPromptCardViews.0a98169776", "Add a setup command to run when Orca creates new worktrees.")}>
+ return (
+ <>
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.0a98169776',
+ 'Add a setup command to run when Orca creates new worktrees.'
+ )}
+ >
+ )
}
export type InspectionErrorActionsProps = {
@@ -158,7 +221,9 @@ export function InspectionErrorActions({
onClick={onRetry}
>
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.4a98f907ae", "Retry")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.4a98f907ae', 'Retry')}
+
- {translate("auto.components.sidebar.SetupScriptPromptCardViews.31b8b01a45", "Settings")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.31b8b01a45', 'Settings')}
+
)
@@ -188,7 +255,9 @@ export function ConfigureOnlyAction({ onConfigure }: ConfigureOnlyActionProps):
onClick={onConfigure}
>
-
{translate("auto.components.sidebar.SetupScriptPromptCardViews.3933401d28", "Configure")}
+
+ {translate('auto.components.sidebar.SetupScriptPromptCardViews.3933401d28', 'Configure')}
+
)
}
@@ -216,7 +285,12 @@ export function SaveLocalSetupAction({
) : (
)}
-
{translate("auto.components.sidebar.SetupScriptPromptCardViews.96a7f4198c", "Save local setup")}
+
+ {translate(
+ 'auto.components.sidebar.SetupScriptPromptCardViews.96a7f4198c',
+ 'Save local setup'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx b/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx
index afe8a38fc7d..0c9f194827c 100644
--- a/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx
+++ b/src/renderer/src/components/sidebar/SidebarFeedbackDialog.tsx
@@ -93,7 +93,12 @@ export function SidebarFeedbackDialog({
const handleSubmit = async (): Promise
=> {
const trimmed = feedback.trim()
if (!trimmed) {
- toast.warning(translate("auto.components.sidebar.SidebarFeedbackDialog.a2fd890d9e", "Please enter feedback before submitting."))
+ toast.warning(
+ translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.a2fd890d9e',
+ 'Please enter feedback before submitting.'
+ )
+ )
return
}
@@ -117,14 +122,24 @@ export function SidebarFeedbackDialog({
}
if (mountedRef.current) {
- toast.success(translate("auto.components.sidebar.SidebarFeedbackDialog.7a46c228b8", "Thanks for the feedback."))
+ toast.success(
+ translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.7a46c228b8',
+ 'Thanks for the feedback.'
+ )
+ )
setFeedback('')
setSubmitAnonymously(false)
onOpenChange(false)
}
} catch (err) {
if (mountedRef.current) {
- toast.error(translate("auto.components.sidebar.SidebarFeedbackDialog.60b721e857", "Failed to submit feedback. Please try again."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.60b721e857',
+ 'Failed to submit feedback. Please try again.'
+ )
+ )
}
console.error('Failed to submit feedback:', err)
} finally {
@@ -138,13 +153,24 @@ export function SidebarFeedbackDialog({
- {translate("auto.components.sidebar.SidebarFeedbackDialog.0eb643f07f", "Send Feedback")}
+
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.0eb643f07f', 'Send Feedback')}
+
- {translate("auto.components.sidebar.SidebarFeedbackDialog.a828fa4aee", "Share what's working, what's broken, or what Orca should do next.")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.a828fa4aee',
+ "Share what's working, what's broken, or what Orca should do next."
+ )}
+
-
{translate("auto.components.sidebar.SidebarFeedbackDialog.9b33530b3d", "Other ways to reach us")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.9b33530b3d',
+ 'Other ways to reach us'
+ )}
+
openExternalUrl(GITHUB_ISSUES_URL)}
>
- {translate("auto.components.sidebar.SidebarFeedbackDialog.d245c4ef6c", "GitHub issues")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.d245c4ef6c',
+ 'GitHub issues'
+ )}
+
- {translate("auto.components.sidebar.SidebarFeedbackDialog.26108d3699", "Join Discord")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.26108d3699',
+ 'Join Discord'
+ )}
+
- {translate("auto.components.sidebar.SidebarFeedbackDialog.3460258a54", "Follow on X")}
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.3460258a54', 'Follow on X')}
+
@@ -187,7 +222,10 @@ export function SidebarFeedbackDialog({
autoFocus
value={feedback}
onChange={(event) => setFeedback(event.target.value)}
- placeholder={translate("auto.components.sidebar.SidebarFeedbackDialog.d46ddd66fc", "What could we improve?")}
+ placeholder={translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.d46ddd66fc',
+ 'What could we improve?'
+ )}
rows={7}
className="min-h-32 w-full rounded-md border border-border bg-background px-3 py-2 text-sm outline-none ring-offset-background placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
/>
@@ -196,7 +234,7 @@ export function SidebarFeedbackDialog({
{viewer ? (
- {translate("auto.components.sidebar.SidebarFeedbackDialog.c9e5ea0791", "GitHub:")}{' '}
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.c9e5ea0791', 'GitHub:')}{' '}
{viewer.login}
{viewer.email ? ` (${viewer.email})` : ''}
@@ -212,20 +250,36 @@ export function SidebarFeedbackDialog({
'accent-foreground'
)}
/>
- {translate("auto.components.sidebar.SidebarFeedbackDialog.5b120b9634", "Submit anonymously")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.5b120b9634',
+ 'Submit anonymously'
+ )}
+
) : isViewerLoading ? (
- {translate("auto.components.sidebar.SidebarFeedbackDialog.d20439c560", "Checking GitHub identity…")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.d20439c560',
+ 'Checking GitHub identity…'
+ )}
+
) : (
- {translate("auto.components.sidebar.SidebarFeedbackDialog.8de03e23c5", "Submit with your typed feedback only, or connect `gh` to include GitHub identity.")}
+ {translate(
+ 'auto.components.sidebar.SidebarFeedbackDialog.8de03e23c5',
+ 'Submit with your typed feedback only, or connect `gh` to include GitHub identity.'
+ )}
+
)}
onOpenChange(false)} disabled={isSubmitting}>
- {translate("auto.components.sidebar.SidebarFeedbackDialog.8bf619e4cf", "Cancel")}
+ {translate('auto.components.sidebar.SidebarFeedbackDialog.8bf619e4cf', 'Cancel')}
+
void handleSubmit()} disabled={isSubmitting || !feedback.trim()}>
- {isSubmitting ? translate("auto.components.sidebar.SidebarFeedbackDialog.69969ba364", "Sending…") : translate("auto.components.sidebar.SidebarFeedbackDialog.f2e42e1307", "Send")}
+ {isSubmitting
+ ? translate('auto.components.sidebar.SidebarFeedbackDialog.69969ba364', 'Sending…')
+ : translate('auto.components.sidebar.SidebarFeedbackDialog.f2e42e1307', 'Send')}
diff --git a/src/renderer/src/components/sidebar/SidebarFilter.tsx b/src/renderer/src/components/sidebar/SidebarFilter.tsx
index 589c8bf8179..da811a736a7 100644
--- a/src/renderer/src/components/sidebar/SidebarFilter.tsx
+++ b/src/renderer/src/components/sidebar/SidebarFilter.tsx
@@ -120,7 +120,16 @@ const SidebarFilter = React.memo(function SidebarFilter({
size="icon-xs"
type="button"
aria-label={
- hasAnyFilter ? translate("auto.components.sidebar.SidebarFilter.75405270ed", "Edit filters ({{value0}} active)", { value0: activeFilterCount }) : translate("auto.components.sidebar.SidebarFilter.f506a1262a", "Filter workspaces")
+ hasAnyFilter
+ ? translate(
+ 'auto.components.sidebar.SidebarFilter.75405270ed',
+ 'Edit filters ({{value0}} active)',
+ { value0: activeFilterCount }
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarFilter.f506a1262a',
+ 'Filter workspaces'
+ )
}
className="relative text-muted-foreground"
data-workspace-board-preserve-open={preserveWorkspaceBoardOpen ? '' : undefined}
@@ -140,7 +149,9 @@ const SidebarFilter = React.memo(function SidebarFilter({
- {hasAnyFilter ? translate("auto.components.sidebar.SidebarFilter.ee240a39eb", "Edit filters") : translate("auto.components.sidebar.SidebarFilter.f506a1262a", "Filter workspaces")}
+ {hasAnyFilter
+ ? translate('auto.components.sidebar.SidebarFilter.ee240a39eb', 'Edit filters')
+ : translate('auto.components.sidebar.SidebarFilter.f506a1262a', 'Filter workspaces')}
}
- label={translate("auto.components.sidebar.SidebarFilter.638a2d221d", "Hide sleeping")}
+ label={translate('auto.components.sidebar.SidebarFilter.638a2d221d', 'Hide sleeping')}
checked={!showSleepingWorkspaces}
onChange={(hideSleeping) => setShowSleepingWorkspaces(!hideSleeping)}
/>
}
- label={translate("auto.components.sidebar.SidebarFilter.e5cb32a898", "Hide default branch")}
+ label={translate(
+ 'auto.components.sidebar.SidebarFilter.e5cb32a898',
+ 'Hide default branch'
+ )}
checked={hideDefaultBranchWorkspace}
onChange={setHideDefaultBranchWorkspace}
/>
@@ -168,7 +182,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
- {translate("auto.components.sidebar.SidebarFilter.5f7085a077", "Projects")}{hasRepoFilter && (
+ {translate('auto.components.sidebar.SidebarFilter.5f7085a077', 'Projects')}
+ {hasRepoFilter && (
· {selectedCount}
@@ -181,14 +196,16 @@ const SidebarFilter = React.memo(function SidebarFilter({
className="rounded-full px-2 py-0.5 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:opacity-40 disabled:hover:bg-transparent"
disabled={allSelected}
>
- {translate("auto.components.sidebar.SidebarFilter.139877b384", "Select all")}
+ {translate('auto.components.sidebar.SidebarFilter.139877b384', 'Select all')}
+
- {translate("auto.components.sidebar.SidebarFilter.779b7ba05d", "Clear")}
+ {translate('auto.components.sidebar.SidebarFilter.779b7ba05d', 'Clear')}
+
@@ -200,7 +217,10 @@ const SidebarFilter = React.memo(function SidebarFilter({
>
{
// Why: typing creates a new filtered list, so keyboard
@@ -214,7 +234,12 @@ const SidebarFilter = React.memo(function SidebarFilter({
iconClassName="h-3.5 w-3.5"
/>
- {translate("auto.components.sidebar.SidebarFilter.b9e8802e73", "No projects match")}
+
+ {translate(
+ 'auto.components.sidebar.SidebarFilter.b9e8802e73',
+ 'No projects match'
+ )}
+
{filteredRepos.map((r) => {
const checked = selectedRepoIdSet.has(r.id)
return (
@@ -233,7 +258,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
{r.connectionId && (
- {translate("auto.components.sidebar.SidebarFilter.81ded53722", "SSH")}
+ {translate('auto.components.sidebar.SidebarFilter.81ded53722', 'SSH')}
+
)}
{checked && (
@@ -258,7 +284,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
onClick={clearAll}
className="rounded-[5px] px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.sidebar.SidebarFilter.92a23e6d07", "Reset filters")}
+ {translate('auto.components.sidebar.SidebarFilter.92a23e6d07', 'Reset filters')}
+
) : (
)}
@@ -268,7 +295,8 @@ const SidebarFilter = React.memo(function SidebarFilter({
className="inline-flex items-center gap-1.5 rounded-[5px] px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.sidebar.SidebarFilter.e3b3898218", "Add project")}
+ {translate('auto.components.sidebar.SidebarFilter.e3b3898218', 'Add project')}
+
diff --git a/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx b/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx
index baf73b9d3a0..7c75d54f37f 100644
--- a/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx
+++ b/src/renderer/src/components/sidebar/SidebarRepositoryFilterSection.tsx
@@ -149,7 +149,17 @@ const SidebarRepositoryFilterSection = React.memo(function SidebarRepositoryFilt
0 ? translate("auto.components.sidebar.SidebarRepositoryFilterSection.5a273fbfce", "Add project...") : translate("auto.components.sidebar.SidebarRepositoryFilterSection.83a820fa71", "Filter projects...")}
+ placeholder={
+ selectedRepos.length > 0
+ ? translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.5a273fbfce',
+ 'Add project...'
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.83a820fa71',
+ 'Filter projects...'
+ )
+ }
value={query}
onValueChange={setQuery}
onKeyDown={handleInputKeyDown}
@@ -159,7 +169,15 @@ const SidebarRepositoryFilterSection = React.memo(function SidebarRepositoryFilt
/>
- {hasRepoFilter ? translate("auto.components.sidebar.SidebarRepositoryFilterSection.bbbc6e8e3b", "No unselected projects match") : translate("auto.components.sidebar.SidebarRepositoryFilterSection.4815c70605", "No projects match")}
+ {hasRepoFilter
+ ? translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.bbbc6e8e3b',
+ 'No unselected projects match'
+ )
+ : translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.4815c70605',
+ 'No projects match'
+ )}
{availableRepos.map((repo) => (
- {translate("auto.components.sidebar.SidebarRepositoryFilterSection.2656053db4", "SSH")}
+ {translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.2656053db4',
+ 'SSH'
+ )}
+
)}
@@ -218,7 +240,11 @@ function SelectedProjectPills({
type="button"
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.sidebar.SidebarRepositoryFilterSection.f10ca29601", "Remove {{value0}} filter", { value0: repo.displayName })}
+ aria-label={translate(
+ 'auto.components.sidebar.SidebarRepositoryFilterSection.f10ca29601',
+ 'Remove {{value0}} filter',
+ { value0: repo.displayName }
+ )}
className="-mr-1 size-4 rounded-full text-muted-foreground hover:bg-muted hover:text-foreground"
onMouseDown={(event) => event.preventDefault()}
onClick={() => onRemoveProject(repo.id)}
@@ -243,7 +269,8 @@ function ProjectFilterHeader({
return (
- {translate("auto.components.sidebar.SidebarRepositoryFilterSection.7679f0c268", "Projects")}{hasRepoFilter && (
+ {translate('auto.components.sidebar.SidebarRepositoryFilterSection.7679f0c268', 'Projects')}
+ {hasRepoFilter && (
- {translate("auto.components.sidebar.SidebarRepositoryFilterSection.d3a9c4cea1", "Clear")}
+ {translate('auto.components.sidebar.SidebarRepositoryFilterSection.d3a9c4cea1', 'Clear')}
+
)
}
diff --git a/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx b/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx
index 994d8ce464b..54654aaf3bd 100644
--- a/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx
+++ b/src/renderer/src/components/sidebar/SidebarSettingsHelpMenu.tsx
@@ -78,13 +78,21 @@ export function SidebarSettingsHelpMenu(): React.JSX.Element {
return
}
setIsRestartingOrca(true)
- toast.info(translate("auto.components.sidebar.SidebarSettingsHelpMenu.5161eef55d", "Restarting Orca…"))
+ toast.info(
+ translate('auto.components.sidebar.SidebarSettingsHelpMenu.5161eef55d', 'Restarting Orca…')
+ )
void window.api.app.restart().catch((error) => {
if (mountedRef.current) {
setIsRestartingOrca(false)
- toast.error(translate("auto.components.sidebar.SidebarSettingsHelpMenu.4e8f5710d3", "Couldn't restart Orca."), {
- description: error instanceof Error ? error.message : undefined
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.4e8f5710d3',
+ "Couldn't restart Orca."
+ ),
+ {
+ description: error instanceof Error ? error.message : undefined
+ }
+ )
}
})
}
@@ -109,7 +117,10 @@ export function SidebarSettingsHelpMenu(): React.JSX.Element {
variant="ghost"
size="icon-xs"
type="button"
- aria-label={translate("auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c", "Help")}
+ aria-label={translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c',
+ 'Help'
+ )}
className="text-muted-foreground"
onPointerDown={(event) => revealAdminOptions(event.altKey)}
onClick={(event) => revealAdminOptions(event.altKey)}
@@ -119,26 +130,52 @@ export function SidebarSettingsHelpMenu(): React.JSX.Element {
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c", "Help")}
+ {translate('auto.components.sidebar.SidebarSettingsHelpMenu.2991a0106c', 'Help')}
+
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.a428c25998", "Settings")}{settingsShortcut}
+ {translate('auto.components.sidebar.SidebarSettingsHelpMenu.a428c25998', 'Settings')}
+ {settingsShortcut}
setFeedbackOpen(true)}>
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.4cf5b868d7", "Send Feedback")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.4cf5b868d7',
+ 'Send Feedback'
+ )}
+
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.e565171a7c", "Keyboard Shortcuts")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.e565171a7c',
+ 'Keyboard Shortcuts'
+ )}
+
-
-
-
+
+
+
openExternalUrl(DISCORD_URL)}>
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.eb9884e55b", "Discord")}
+ {translate('auto.components.sidebar.SidebarSettingsHelpMenu.eb9884e55b', 'Discord')}
+
)}
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.29c56f30ee", "Check for Updates")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.29c56f30ee',
+ 'Check for Updates'
+ )}
+
{showAdminOptions ? (
<>
- {translate("auto.components.sidebar.SidebarSettingsHelpMenu.ad3d3ed7f1", "Restart Orca")}
+ {translate(
+ 'auto.components.sidebar.SidebarSettingsHelpMenu.ad3d3ed7f1',
+ 'Restart Orca'
+ )}
+
>
) : null}
diff --git a/src/renderer/src/components/sidebar/SidebarToolbar.tsx b/src/renderer/src/components/sidebar/SidebarToolbar.tsx
index 3895ad455d2..3d8e274c3c7 100644
--- a/src/renderer/src/components/sidebar/SidebarToolbar.tsx
+++ b/src/renderer/src/components/sidebar/SidebarToolbar.tsx
@@ -22,11 +22,17 @@ const SidebarToolbar = React.memo(function SidebarToolbar() {
className="gap-1.5 text-muted-foreground"
>
- {translate("auto.components.sidebar.SidebarToolbar.abc62b6328", "Add Project")}
+
+ {translate('auto.components.sidebar.SidebarToolbar.abc62b6328', 'Add Project')}
+
- {translate("auto.components.sidebar.SidebarToolbar.19e32d0e5f", "Open folder picker to add a project")}
+ {translate(
+ 'auto.components.sidebar.SidebarToolbar.19e32d0e5f',
+ 'Open folder picker to add a project'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx b/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx
index 742081cfcd0..8a2a492cddc 100644
--- a/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx
+++ b/src/renderer/src/components/sidebar/SidebarWorkspaceFilterSection.tsx
@@ -13,17 +13,25 @@ const SidebarWorkspaceFilterSection = React.memo(function SidebarWorkspaceFilter
return (
<>
- {translate("auto.components.sidebar.SidebarWorkspaceFilterSection.82594419ba", "Filters")}
+
+ {translate('auto.components.sidebar.SidebarWorkspaceFilterSection.82594419ba', 'Filters')}
+
}
- label={translate("auto.components.sidebar.SidebarWorkspaceFilterSection.ed1611b65b", "Hide sleeping")}
+ label={translate(
+ 'auto.components.sidebar.SidebarWorkspaceFilterSection.ed1611b65b',
+ 'Hide sleeping'
+ )}
checked={!showSleepingWorkspaces}
onChange={(hideSleeping) => setShowSleepingWorkspaces(!hideSleeping)}
/>
}
- label={translate("auto.components.sidebar.SidebarWorkspaceFilterSection.c3fa13dc2e", "Hide default branch")}
+ label={translate(
+ 'auto.components.sidebar.SidebarWorkspaceFilterSection.c3fa13dc2e',
+ 'Hide default branch'
+ )}
checked={hideDefaultBranchWorkspace}
onChange={setHideDefaultBranchWorkspace}
/>
diff --git a/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx b/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
index c5327ddee0b..77e745bc6ad 100644
--- a/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
+++ b/src/renderer/src/components/sidebar/SshDisconnectedDialog.tsx
@@ -27,7 +27,10 @@ const STATUS_MESSAGES: Partial
> = {
disconnected: 'This remote repository is not connected.',
reconnecting: 'Reconnecting to the remote host...',
'reconnection-failed': 'Reconnection to the remote host failed.',
- error: translate("auto.components.sidebar.SshDisconnectedDialog.376bed88e5", "The connection to the remote host encountered an error."),
+ error: translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.376bed88e5',
+ 'The connection to the remote host encountered an error.'
+ ),
'auth-failed': 'Authentication to the remote host failed.'
}
@@ -53,7 +56,14 @@ export function SshDisconnectedDialog({
onOpenChange(false)
}
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.sidebar.SshDisconnectedDialog.656368f3a2", "Reconnection failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.656368f3a2',
+ 'Reconnection failed'
+ )
+ )
} finally {
if (mountedRef.current) {
setConnecting(false)
@@ -105,7 +115,15 @@ export function SshDisconnectedDialog({
) : (
)}
- {isConnecting ? translate("auto.components.sidebar.SshDisconnectedDialog.cb5938ae79", "Reconnecting...") : translate("auto.components.sidebar.SshDisconnectedDialog.11552bf786", "SSH Disconnected")}
+ {isConnecting
+ ? translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.cb5938ae79',
+ 'Reconnecting...'
+ )
+ : translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.11552bf786',
+ 'SSH Disconnected'
+ )}
{message}
@@ -129,15 +147,20 @@ export function SshDisconnectedDialog({
onClick={() => onOpenChange(false)}
disabled={isConnecting}
>
- {translate("auto.components.sidebar.SshDisconnectedDialog.89385db176", "Dismiss")}
+ {translate('auto.components.sidebar.SshDisconnectedDialog.89385db176', 'Dismiss')}
+
{showReconnect && (
void handleReconnect()} disabled={isConnecting}>
{isConnecting ? (
<>
- {translate("auto.components.sidebar.SshDisconnectedDialog.ca4a7892af", "Connecting...")}>
+ {translate(
+ 'auto.components.sidebar.SshDisconnectedDialog.ca4a7892af',
+ 'Connecting...'
+ )}
+ >
) : (
- translate("auto.components.sidebar.SshDisconnectedDialog.4afcca1d24", "Reconnect")
+ translate('auto.components.sidebar.SshDisconnectedDialog.4afcca1d24', 'Reconnect')
)}
)}
diff --git a/src/renderer/src/components/sidebar/SshTargetRow.tsx b/src/renderer/src/components/sidebar/SshTargetRow.tsx
index 209d6c2c872..77a3bf955dc 100644
--- a/src/renderer/src/components/sidebar/SshTargetRow.tsx
+++ b/src/renderer/src/components/sidebar/SshTargetRow.tsx
@@ -96,9 +96,10 @@ export function SshTargetRow({
{isBusy ? (
<>
- {translate("auto.components.sidebar.SshTargetRow.4677394048", "Connecting…")}>
+ {translate('auto.components.sidebar.SshTargetRow.4677394048', 'Connecting…')}
+ >
) : (
- translate("auto.components.sidebar.SshTargetRow.75ad429b5d", "Connect")
+ translate('auto.components.sidebar.SshTargetRow.75ad429b5d', 'Connect')
)}
)}
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
index 9415240f83c..5df17c4a309 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanCard.tsx
@@ -46,7 +46,7 @@ function WorkspaceKanbanCard({
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx
index 8be0c1a9171..70a91a20bf7 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx
@@ -36,14 +36,28 @@ export default function WorkspaceKanbanDrawerHeader({
<>
- {translate("auto.components.sidebar.WorkspaceKanbanDrawerHeader.c6a77ab0f4", "Workspace board")}
+
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanDrawerHeader.c6a77ab0f4',
+ 'Workspace board'
+ )}
+
{selectedCount > 1 ? (
- {selectedCount} {translate("auto.components.sidebar.WorkspaceKanbanDrawerHeader.81870af08f", "selected")}
+ {selectedCount}{' '}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanDrawerHeader.81870af08f',
+ 'selected'
+ )}
+
) : null}
- {translate("auto.components.sidebar.WorkspaceKanbanDrawerHeader.e1a34450fc", "Organize workspaces by status and open workspace cards.")}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanDrawerHeader.e1a34450fc',
+ 'Organize workspaces by status and open workspace cards.'
+ )}
+
@@ -62,7 +76,15 @@ export default function WorkspaceKanbanDrawerHeader({
onRemoveStatus={onRemoveStatus}
onAddStatus={onAddStatus}
/>
-
+
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx
index 657fe0c7bf5..d7e5aa21992 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanPinDropTarget.tsx
@@ -26,8 +26,15 @@ export default function WorkspaceKanbanPinDropTarget({
onDragLeave={onDragLeave}
>
- {translate("auto.components.sidebar.WorkspaceKanbanPinDropTarget.8fae2d0862", "Pinned")}
- {translate("auto.components.sidebar.WorkspaceKanbanPinDropTarget.c30151c5ee", "Drop here to pin without changing status.")}
+
+ {translate('auto.components.sidebar.WorkspaceKanbanPinDropTarget.8fae2d0862', 'Pinned')}
+
+
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanPinDropTarget.c30151c5ee',
+ 'Drop here to pin without changing status.'
+ )}
+
)
}
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx
index 46a61e2a9ce..bd435b5a237 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx
@@ -41,7 +41,10 @@ export default function WorkspaceKanbanSettingsMenu({
@@ -50,7 +53,11 @@ export default function WorkspaceKanbanSettingsMenu({
- {translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.34f03eb0de", "Board settings")}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.34f03eb0de',
+ 'Board settings'
+ )}
+
- {translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.395e541d5d", "Statuses")}
+
+ {translate('auto.components.sidebar.WorkspaceKanbanSettingsMenu.395e541d5d', 'Statuses')}
+
{workspaceStatuses.map((status, index) => {
const meta = getWorkspaceStatusVisualMeta(status)
@@ -88,7 +97,11 @@ export default function WorkspaceKanbanSettingsMenu({
}
}}
className="h-7 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-[12px] text-foreground outline-none focus-visible:ring-1 focus-visible:ring-ring"
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.8ce44af9a8", "Rename {{value0}}", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.8ce44af9a8',
+ 'Rename {{value0}}',
+ { value0: status.label }
+ )}
/>
onMoveStatus(status.id, -1)}
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0", "Move {{value0}} left", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0',
+ 'Move {{value0}} left',
+ { value0: status.label }
+ )}
>
@@ -113,7 +130,11 @@ export default function WorkspaceKanbanSettingsMenu({
className="size-7"
disabled={index === workspaceStatuses.length - 1}
onClick={() => onMoveStatus(status.id, 1)}
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0", "Move {{value0}} right", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.b45b350eb0',
+ 'Move {{value0}} right',
+ { value0: status.label }
+ )}
>
@@ -124,7 +145,11 @@ export default function WorkspaceKanbanSettingsMenu({
className="size-7 text-muted-foreground hover:text-destructive"
disabled={workspaceStatuses.length <= 1}
onClick={() => onRemoveStatus(status.id)}
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.054cb50df7", "Remove {{value0}}", { value0: status.label })}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.054cb50df7',
+ 'Remove {{value0}}',
+ { value0: status.label }
+ )}
>
@@ -140,7 +165,11 @@ export default function WorkspaceKanbanSettingsMenu({
onClick={onAddStatus}
>
- {translate("auto.components.sidebar.WorkspaceKanbanSettingsMenu.79eb990aa4", "Add status")}
+ {translate(
+ 'auto.components.sidebar.WorkspaceKanbanSettingsMenu.79eb990aa4',
+ 'Add status'
+ )}
+
diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx
index 46e018bd445..aef39b12e1d 100644
--- a/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx
+++ b/src/renderer/src/components/sidebar/WorkspaceKanbanStatusLane.tsx
@@ -101,7 +101,10 @@ export default function WorkspaceKanbanStatusLane({
data-workspace-board-column-resize-handle=""
role="separator"
aria-orientation="vertical"
- aria-label={translate("auto.components.sidebar.WorkspaceKanbanStatusLane.3611d1ae7f", "Resize workspace board columns")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorkspaceKanbanStatusLane.3611d1ae7f',
+ 'Resize workspace board columns'
+ )}
aria-valuemin={WORKSPACE_BOARD_COLUMN_WIDTH_MIN}
aria-valuemax={WORKSPACE_BOARD_COLUMN_WIDTH_MAX}
aria-valuenow={columnWidth}
@@ -169,7 +172,8 @@ export default function WorkspaceKanbanStatusLane({
) : (
- {translate("auto.components.sidebar.WorkspaceKanbanStatusLane.8ad104642b", "Empty")}
+ {translate('auto.components.sidebar.WorkspaceKanbanStatusLane.8ad104642b', 'Empty')}
+
)}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx b/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx
index 0224f7ec27a..265ba436f40 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardAgents.tsx
@@ -394,7 +394,7 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
onMouseDown={stopBubble}
onPointerDown={stopBubble}
role={hasLineage ? 'tree' : 'group'}
- aria-label={translate("auto.components.sidebar.WorktreeCardAgents.1b0a156717", "Agents")}
+ aria-label={translate('auto.components.sidebar.WorktreeCardAgents.1b0a156717', 'Agents')}
data-compact-agent-list="true"
>
{agents.length === 0 ? null : shouldUseSummaryRow ? (
@@ -436,7 +436,7 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
onMouseDown={stopBubble}
onPointerDown={stopBubble}
role={hasLineage ? 'tree' : 'group'}
- aria-label={translate("auto.components.sidebar.WorktreeCardAgents.1b0a156717", "Agents")}
+ aria-label={translate('auto.components.sidebar.WorktreeCardAgents.1b0a156717', 'Agents')}
>
{rootAgents.map((rootAgent) => renderAgentBranch(rootAgent))}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx b/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx
index 5dfc3d48a04..3cd3fece64c 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardMetadataStatusBadges.tsx
@@ -34,7 +34,10 @@ export function IssueStateBadge({ state }: { state: IssueInfo['state'] }): React
if (state === 'closed') {
return (
@@ -44,7 +47,10 @@ export function IssueStateBadge({ state }: { state: IssueInfo['state'] }): React
return (
@@ -67,7 +73,14 @@ export function LinearStateBadge({ stateName }: { stateName: string }): React.JS
: 'border-border bg-muted/30 text-muted-foreground'
return (
-
+
)
@@ -87,7 +100,10 @@ export function ReviewStateBadge({
if (state === 'merged') {
return (
@@ -98,7 +114,10 @@ export function ReviewStateBadge({
if (state === 'closed') {
return (
@@ -109,7 +128,11 @@ export function ReviewStateBadge({
if (state === 'draft') {
return (
@@ -119,10 +142,13 @@ export function ReviewStateBadge({
return (
- {label === "MR" ? : }
+ {label === 'MR' ? : }
)
}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx b/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx
index 091d23e1c2f..3545454a918 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardPorts.tsx
@@ -41,7 +41,11 @@ export function WorktreeCardPortsTrigger({
{
event.stopPropagation()
recordFeatureInteraction('ports')
@@ -116,7 +120,13 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
openInOrcaBrowser: shouldOpenWorkspacePortInOrcaBrowser(settings)
}).then((result) => {
if (!result.ok) {
- toast.error(translate("auto.components.sidebar.WorktreeCardPorts.d1113f4660", "Failed to open browser"), { description: result.reason })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.WorktreeCardPorts.d1113f4660',
+ 'Failed to open browser'
+ ),
+ { description: result.reason }
+ )
}
})
},
@@ -136,7 +146,11 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
recordFeatureInteraction('ports')
const address = addressForPort(port)
void window.api.ui.writeClipboardText(address)
- toast.success(translate("auto.components.sidebar.WorktreeCardPorts.c89f290e25", "Copied {{value0}}", { value0: address }))
+ toast.success(
+ translate('auto.components.sidebar.WorktreeCardPorts.c89f290e25', 'Copied {{value0}}', {
+ value0: address
+ })
+ )
},
[port, recordFeatureInteraction]
)
@@ -158,16 +172,28 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
toast.error(result.reason)
return
}
- toast.success(translate("auto.components.sidebar.WorktreeCardPorts.5d1a5d51bb", "Stopped process on {{value0}}", { value0: port.port }))
+ toast.success(
+ translate(
+ 'auto.components.sidebar.WorktreeCardPorts.5d1a5d51bb',
+ 'Stopped process on {{value0}}',
+ { value0: port.port }
+ )
+ )
const refreshResult = await refreshWorkspacePortScanAfterStop({
runtimeTarget,
setWorkspacePortScan,
setWorkspacePortScanRefreshing
})
if (!refreshResult.ok) {
- toast.error(translate("auto.components.sidebar.WorktreeCardPorts.9950fe2d20", "Failed to refresh ports"), {
- description: refreshResult.reason
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.WorktreeCardPorts.9950fe2d20',
+ 'Failed to refresh ports'
+ ),
+ {
+ description: refreshResult.reason
+ }
+ )
}
}
void run()
@@ -206,13 +232,33 @@ function WorktreePortRow({ port }: { port: WorkspacePort }): React.JSX.Element {
@@ -231,7 +277,9 @@ export function WorktreeCardPortsDetails({
recordFeatureInteraction('ports')
const ownerPort = ports[0]
if (!ownerPort || !goToWorkspacePortOwner(ownerPort)) {
- toast.error(translate("auto.components.sidebar.WorktreeCardPorts.3e5f66564e", "Workspace unavailable"))
+ toast.error(
+ translate('auto.components.sidebar.WorktreeCardPorts.3e5f66564e', 'Workspace unavailable')
+ )
}
},
[ports, recordFeatureInteraction]
@@ -245,9 +293,17 @@ export function WorktreeCardPortsDetails({
-
{translate("auto.components.sidebar.WorktreeCardPorts.3240f320d7", "Live Ports")}
+
+ {translate('auto.components.sidebar.WorktreeCardPorts.3240f320d7', 'Live Ports')}
+
-
+
{ports.length}
diff --git a/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx b/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
index b3d4a7c108e..665c7294612 100644
--- a/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
@@ -512,11 +512,14 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
/>
- {translate("auto.components.sidebar.WorktreeContextMenu.3350101edb", "Copy Path")}
+ {translate('auto.components.sidebar.WorktreeContextMenu.3350101edb', 'Copy Path')}
+
{worktree.isPinned ? : }
- {worktree.isPinned ? translate("auto.components.sidebar.WorktreeContextMenu.697d0f6e1b", "Unpin") : translate("auto.components.sidebar.WorktreeContextMenu.3baa7d6507", "Pin")}
+ {worktree.isPinned
+ ? translate('auto.components.sidebar.WorktreeContextMenu.697d0f6e1b', 'Unpin')
+ : translate('auto.components.sidebar.WorktreeContextMenu.3baa7d6507', 'Pin')}
{worktree.isUnread ? (
@@ -524,19 +527,32 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
) : (
)}
- {worktree.isUnread ? translate("auto.components.sidebar.WorktreeContextMenu.8dacff1fe0", "Mark Read") : translate("auto.components.sidebar.WorktreeContextMenu.f50603c6b2", "Mark Unread")}
+ {worktree.isUnread
+ ? translate('auto.components.sidebar.WorktreeContextMenu.8dacff1fe0', 'Mark Read')
+ : translate(
+ 'auto.components.sidebar.WorktreeContextMenu.f50603c6b2',
+ 'Mark Unread'
+ )}
{repo ? (
<>
- {translate("auto.components.sidebar.WorktreeContextMenu.503ec0f8e6", "New group from project")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.503ec0f8e6',
+ 'New group from project'
+ )}
+
{projectGroups.length > 0 ? (
- {translate("auto.components.sidebar.WorktreeContextMenu.76865d827f", "Move to group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.76865d827f',
+ 'Move to group'
+ )}
+
{projectGroups.map((group) => (
- {translate("auto.components.sidebar.WorktreeContextMenu.d35dfeae58", "Remove from group")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.d35dfeae58',
+ 'Remove from group'
+ )}
+
) : null}
>
) : null}
@@ -563,12 +583,20 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{validParentWorktreeId && (
- {translate("auto.components.sidebar.WorktreeContextMenu.8d9cd19d09", "Open Parent Workspace")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.8d9cd19d09',
+ 'Open Parent Workspace'
+ )}
+
)}
{lineage && (
- {translate("auto.components.sidebar.WorktreeContextMenu.579b1a8e61", "Remove from Parent")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.579b1a8e61',
+ 'Remove from Parent'
+ )}
+
)}
>
@@ -580,7 +608,11 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{hasAnyContextLineage && (
- {translate("auto.components.sidebar.WorktreeContextMenu.579b1a8e61", "Remove from Parent")}
+ {translate(
+ 'auto.components.sidebar.WorktreeContextMenu.579b1a8e61',
+ 'Remove from Parent'
+ )}
+
)}
>
@@ -588,7 +620,15 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
- {isMultiContext ? translate("auto.components.sidebar.WorktreeContextMenu.56cde9e8e6", "Move Statuses To") : translate("auto.components.sidebar.WorktreeContextMenu.84cdbb7e30", "Move to Status")}
+ {isMultiContext
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.56cde9e8e6',
+ 'Move Statuses To'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeContextMenu.84cdbb7e30',
+ 'Move to Status'
+ )}
@@ -611,7 +651,8 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{!isMultiContext && (
- {translate("auto.components.sidebar.WorktreeContextMenu.439fa94d53", "Update")}
+ {translate('auto.components.sidebar.WorktreeContextMenu.439fa94d53', 'Update')}
+
)}
@@ -626,8 +667,14 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
{isMultiContext
- ? translate("auto.components.sidebar.WorktreeContextMenu.7d190f7d2b", "Close all active panels in the selected workspaces to free up memory and CPU.")
- : translate("auto.components.sidebar.WorktreeContextMenu.0918b35e4f", "Close all active panels in this workspace to free up memory and CPU.")}
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.7d190f7d2b',
+ 'Close all active panels in the selected workspaces to free up memory and CPU.'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeContextMenu.0918b35e4f',
+ 'Close all active panels in this workspace to free up memory and CPU.'
+ )}
{/* Why: primary checkout rows remove the project from Orca instead of
@@ -644,25 +691,37 @@ const WorktreeContextMenu = React.memo(function WorktreeContextMenu({
}
title={
!isMultiContext && worktree.isMainWorktree && !removesProject
- ? translate("auto.components.sidebar.WorktreeContextMenu.e091caab15", "The project could not be found")
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.e091caab15',
+ 'The project could not be found'
+ )
: undefined
}
>
{deletingContext
- ? translate("auto.components.sidebar.WorktreeContextMenu.b42391d8bf", "Deleting…")
+ ? translate('auto.components.sidebar.WorktreeContextMenu.b42391d8bf', 'Deleting…')
: isMultiContext
? deleteLabel
: removesProject
- ? translate("auto.components.sidebar.WorktreeContextMenu.f5ac91531d", "Remove Project from Orca")
- : translate("auto.components.sidebar.WorktreeContextMenu.f4475537d8", "Delete")}
+ ? translate(
+ 'auto.components.sidebar.WorktreeContextMenu.f5ac91531d',
+ 'Remove Project from Orca'
+ )
+ : translate('auto.components.sidebar.WorktreeContextMenu.f4475537d8', 'Delete')}
- {entry.target === "file-manager" ? (
+ {entry.target === 'file-manager' ? (
) : entry.command ? (
@@ -162,7 +185,8 @@ export function WorktreeOpenInSubMenu({
- {translate("auto.components.sidebar.WorktreeOpenInMenu.8009ab69a6", "Open in")}
+ {translate('auto.components.sidebar.WorktreeOpenInMenu.8009ab69a6', 'Open in')}
+
- {translate("auto.components.sidebar.WorktreeOpenInMenu.1417fd8380", "Customize apps...")}
+ {translate('auto.components.sidebar.WorktreeOpenInMenu.1417fd8380', 'Customize apps...')}
+
)
diff --git a/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx b/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
index 2a8a1c4a975..06c2e12b0b6 100644
--- a/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
@@ -189,7 +189,14 @@ export function WorktreeTitleInlineRename({
}
} catch (err) {
if (mountedRef.current) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.sidebar.WorktreeTitleInlineRename.8df295a78d", "Failed to rename workspace."))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate(
+ 'auto.components.sidebar.WorktreeTitleInlineRename.8df295a78d',
+ 'Failed to rename workspace.'
+ )
+ )
}
} finally {
savingRef.current = false
@@ -237,7 +244,10 @@ export function WorktreeTitleInlineRename({
value={value}
style={{ font: 'inherit' }}
disabled={saving}
- aria-label={translate("auto.components.sidebar.WorktreeTitleInlineRename.bff3bdd00c", "Rename workspace")}
+ aria-label={translate(
+ 'auto.components.sidebar.WorktreeTitleInlineRename.bff3bdd00c',
+ 'Rename workspace'
+ )}
data-worktree-title-rename-input="true"
onChange={(event) => setValue(event.target.value)}
onBlur={() => void commitRename()}
@@ -273,7 +283,11 @@ export function WorktreeTitleInlineRename({
tabIndex={disabled ? undefined : 0}
>
{/* Why: visible text alone misses the unread state for assistive tech. */}
- {showUnreadEmphasis && {translate("auto.components.sidebar.WorktreeTitleInlineRename.2f42ae024f", "Unread:")} }
+ {showUnreadEmphasis && (
+
+ {translate('auto.components.sidebar.WorktreeTitleInlineRename.2f42ae024f', 'Unread:')}
+
+ )}
{displayName}
)
diff --git a/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx b/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx
index 94e9f24cf1d..e794250be77 100644
--- a/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsx
@@ -62,7 +62,12 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
!open && closeModal()}>
- {translate("auto.components.sidebar.WorktreeVisibilityDialog.83a5ba8dd1", "Non-Orca worktrees")}
+
+ {translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.83a5ba8dd1',
+ 'Non-Orca worktrees'
+ )}
+
{repo.displayName}
@@ -72,12 +77,28 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
- {showOther ? translate("auto.components.sidebar.WorktreeVisibilityDialog.3e045d4cb8", "Shown in sidebar") : translate("auto.components.sidebar.WorktreeVisibilityDialog.5d02a5647f", "Hidden from sidebar")}
+ {showOther
+ ? translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.3e045d4cb8',
+ 'Shown in sidebar'
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.5d02a5647f',
+ 'Hidden from sidebar'
+ )}
{showOther
- ? translate("auto.components.sidebar.WorktreeVisibilityDialog.8372e4bbd9", "{{value0}} currently shown", { value0: shownWorktreeLabel })
- : translate("auto.components.sidebar.WorktreeVisibilityDialog.25ddf19920", "{{value0}} available to import", { value0: hiddenWorktreeLabel })}
+ ? translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.8372e4bbd9',
+ '{{value0}} currently shown',
+ { value0: shownWorktreeLabel }
+ )
+ : translate(
+ 'auto.components.sidebar.WorktreeVisibilityDialog.25ddf19920',
+ '{{value0}} available to import',
+ { value0: hiddenWorktreeLabel }
+ )}
- {showOther ? translate("auto.components.sidebar.WorktreeVisibilityDialog.759371df43", "Hide") : translate("auto.components.sidebar.WorktreeVisibilityDialog.f1f71b9f02", "Import")}
+ {showOther
+ ? translate('auto.components.sidebar.WorktreeVisibilityDialog.759371df43', 'Hide')
+ : translate('auto.components.sidebar.WorktreeVisibilityDialog.f1f71b9f02', 'Import')}
diff --git a/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts b/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
index 005b29940df..259b6b8f3b7 100644
--- a/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
+++ b/src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
@@ -30,30 +30,54 @@ export function getAddRepoLocalStartActions({
const primaryAction = {
kind: 'browse' as const,
icon: FolderOpen,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.2281fdc8c7", "Browse folder"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.fb4fc5380e", "Local project, Git repo, or folder with many repos"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.2281fdc8c7',
+ 'Browse folder'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.fb4fc5380e',
+ 'Local project, Git repo, or folder with many repos'
+ ),
onClick: onBrowse
}
const remote = {
kind: 'remote' as const,
icon: Monitor,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.3d162cc76f", "Remote project"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.a6c20dca96", "Open a project from an SSH target"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.3d162cc76f',
+ 'Remote project'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.a6c20dca96',
+ 'Open a project from an SSH target'
+ ),
onClick: onOpenRemoteStep
}
const clone = {
kind: 'clone' as const,
icon: Globe,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.7edb8ebe24", "Clone from URL"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.5f9ffac036", "Clone a remote Git repository"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.7edb8ebe24',
+ 'Clone from URL'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.5f9ffac036',
+ 'Clone a remote Git repository'
+ ),
onClick: onOpenCloneStep
}
const create = {
kind: 'create' as const,
icon: Plus,
- title: translate("auto.components.sidebar.add.repo.local.start.actions.c709860596", "Create new project"),
- description: translate("auto.components.sidebar.add.repo.local.start.actions.d72789705e", "Start from an empty folder"),
+ title: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.c709860596',
+ 'Create new project'
+ ),
+ description: translate(
+ 'auto.components.sidebar.add.repo.local.start.actions.d72789705e',
+ 'Start from an empty folder'
+ ),
onClick: onOpenCreateStep
}
diff --git a/src/renderer/src/components/sidebar/delete-worktree-flow.ts b/src/renderer/src/components/sidebar/delete-worktree-flow.ts
index 01426498eed..2195f48bd65 100644
--- a/src/renderer/src/components/sidebar/delete-worktree-flow.ts
+++ b/src/renderer/src/components/sidebar/delete-worktree-flow.ts
@@ -125,37 +125,58 @@ export function runWorktreeDeleteWithToast(
description: toastCopy.description,
duration: 10000,
cancel: {
- label: translate("auto.components.sidebar.delete.worktree.flow.7488ed8711", "View"),
+ label: translate('auto.components.sidebar.delete.worktree.flow.7488ed8711', 'View'),
onClick: () => viewWorktreeDiff(worktreeId)
},
action: canForceDelete
? {
- label: translate("auto.components.sidebar.delete.worktree.flow.2b20ce87b3", "Force Delete"),
+ label: translate(
+ 'auto.components.sidebar.delete.worktree.flow.2b20ce87b3',
+ 'Force Delete'
+ ),
onClick: () => {
useAppStore
.getState()
.removeWorktree(worktreeId, true)
.then((forceResult) => {
if (!forceResult.ok) {
- toast.error(translate("auto.components.sidebar.delete.worktree.flow.4f3876c0f5", "Force delete failed"), {
- description: forceResult.error,
- action: {
- label: translate("auto.components.sidebar.delete.worktree.flow.7488ed8711", "View"),
- onClick: () => viewWorktreeDiff(worktreeId)
+ toast.error(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.4f3876c0f5',
+ 'Force delete failed'
+ ),
+ {
+ description: forceResult.error,
+ action: {
+ label: translate(
+ 'auto.components.sidebar.delete.worktree.flow.7488ed8711',
+ 'View'
+ ),
+ onClick: () => viewWorktreeDiff(worktreeId)
+ }
}
- })
+ )
return
}
options.onForceDeleted?.(worktreeId)
})
.catch((err: unknown) => {
- toast.error(translate("auto.components.sidebar.delete.worktree.flow.ae57cbf6e4", "Failed to delete workspace"), {
- description: err instanceof Error ? err.message : String(err),
- action: {
- label: translate("auto.components.sidebar.delete.worktree.flow.7488ed8711", "View"),
- onClick: () => viewWorktreeDiff(worktreeId)
+ toast.error(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.ae57cbf6e4',
+ 'Failed to delete workspace'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err),
+ action: {
+ label: translate(
+ 'auto.components.sidebar.delete.worktree.flow.7488ed8711',
+ 'View'
+ ),
+ onClick: () => viewWorktreeDiff(worktreeId)
+ }
}
- })
+ )
})
}
}
@@ -164,9 +185,15 @@ export function runWorktreeDeleteWithToast(
return false
})
.catch((err: unknown) => {
- toast.error(translate("auto.components.sidebar.delete.worktree.flow.ae57cbf6e4", "Failed to delete workspace"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.ae57cbf6e4',
+ 'Failed to delete workspace'
+ ),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
return false
})
}
@@ -227,9 +254,18 @@ export function runWorktreeBatchDelete(
.filter((worktree): worktree is Worktree => worktree != null && !worktree.isMainWorktree)
if (targets.length === 0) {
- toast.info(translate("auto.components.sidebar.delete.worktree.flow.7243145cd6", "No deletable workspaces selected"), {
- description: translate("auto.components.sidebar.delete.worktree.flow.b81b4e40ca", "Refresh Space and try again if the workspace list looks stale.")
- })
+ toast.info(
+ translate(
+ 'auto.components.sidebar.delete.worktree.flow.7243145cd6',
+ 'No deletable workspaces selected'
+ ),
+ {
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.flow.b81b4e40ca',
+ 'Refresh Space and try again if the workspace list looks stale.'
+ )
+ }
+ )
return false
}
diff --git a/src/renderer/src/components/sidebar/delete-worktree-toast.ts b/src/renderer/src/components/sidebar/delete-worktree-toast.ts
index 4090c63c13e..9ae69262ac5 100644
--- a/src/renderer/src/components/sidebar/delete-worktree-toast.ts
+++ b/src/renderer/src/components/sidebar/delete-worktree-toast.ts
@@ -13,9 +13,15 @@ export function getDeleteWorktreeToastCopy(
if (canForceDelete) {
if (error.includes('Worktree is no longer registered with Git but its directory remains.')) {
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
- description:
- translate("auto.components.sidebar.delete.worktree.toast.0899ebdb28", "Git already forgot this workspace, but its directory is still on disk. Use Force Delete to remove the orphaned directory."),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.toast.0899ebdb28',
+ 'Git already forgot this workspace, but its directory is still on disk. Use Force Delete to remove the orphaned directory.'
+ ),
isDestructive: false
}
}
@@ -23,14 +29,28 @@ export function getDeleteWorktreeToastCopy(
error.includes('Worktree is no longer registered with Git and its directory is already gone.')
) {
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
- description: translate("auto.components.sidebar.delete.worktree.toast.905fc8efac", "Git already removed this workspace. Use Force Delete to clear it from Orca."),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.toast.905fc8efac',
+ 'Git already removed this workspace. Use Force Delete to clear it from Orca.'
+ ),
isDestructive: false
}
}
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
- description: translate("auto.components.sidebar.delete.worktree.toast.ead7b8ee15", "It has changed files. Use Force Delete to delete it anyway."),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
+ description: translate(
+ 'auto.components.sidebar.delete.worktree.toast.ead7b8ee15',
+ 'It has changed files. Use Force Delete to delete it anyway.'
+ ),
// Why: git commonly refuses the first delete when the worktree still has
// modified or untracked files. Showing raw stderr in a destructive toast
// made a normal cleanup step look like an Orca bug, so this common case
@@ -40,7 +60,11 @@ export function getDeleteWorktreeToastCopy(
}
return {
- title: translate("auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5", "Failed to delete workspace {{value0}}", { value0: worktreeName }),
+ title: translate(
+ 'auto.components.sidebar.delete.worktree.toast.1d0fa5c0a5',
+ 'Failed to delete workspace {{value0}}',
+ { value0: worktreeName }
+ ),
description: error,
isDestructive: true
}
diff --git a/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts b/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts
index 1e8c8be33ad..e11def20b50 100644
--- a/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts
+++ b/src/renderer/src/components/sidebar/remote-file-browser-helpers.ts
@@ -179,7 +179,14 @@ export function resolveSegmentStep(
}
// Stop resolution: prefix-matching to a similarly-named folder here would
// silently bypass a real file the user pointed at.
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7", "{{value0}} isn't a directory in {{value1}}", { value0: segment, value1: basePath }) }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7',
+ "{{value0}} isn't a directory in {{value1}}",
+ { value0: segment, value1: basePath }
+ )
+ }
}
// Fall back to case-insensitive matching so segment resolution agrees with
// the case-insensitive filter input. Without this, typing `documents/`
@@ -192,7 +199,14 @@ export function resolveSegmentStep(
if (ciExact.isDirectory) {
return { type: 'descend', name: ciExact.name }
}
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7", "{{value0}} isn't a directory in {{value1}}", { value0: segment, value1: basePath }) }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7',
+ "{{value0}} isn't a directory in {{value1}}",
+ { value0: segment, value1: basePath }
+ )
+ }
}
const dirMatches = baseEntries.filter(
(e) => e.isDirectory && e.name.toLowerCase().startsWith(segLower)
@@ -201,7 +215,21 @@ export function resolveSegmentStep(
return { type: 'descend', name: dirMatches[0].name }
}
if (dirMatches.length > 1) {
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.be266af66c", "{{value0}} matches multiple directories in {{value1}}", { value0: segment, value1: basePath }) }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.be266af66c',
+ '{{value0}} matches multiple directories in {{value1}}',
+ { value0: segment, value1: basePath }
+ )
+ }
+ }
+ return {
+ type: 'error',
+ message: translate(
+ 'auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7',
+ "{{value0}} isn't a directory in {{value1}}",
+ { value0: segment, value1: basePath }
+ )
}
- return { type: 'error', message: translate("auto.components.sidebar.remote.file.browser.helpers.4dbd72a7d7", "{{value0}} isn't a directory in {{value1}}", { value0: segment, value1: basePath }) }
}
diff --git a/src/renderer/src/components/sidebar/repo-header-create-state.ts b/src/renderer/src/components/sidebar/repo-header-create-state.ts
index 81c66217919..6b369f1e287 100644
--- a/src/renderer/src/components/sidebar/repo-header-create-state.ts
+++ b/src/renderer/src/components/sidebar/repo-header-create-state.ts
@@ -19,8 +19,16 @@ export function getRepoHeaderCreateState(input: {
if (!isGitRepoKind(input.repo)) {
return {
disabled: false,
- tooltip: translate("auto.components.sidebar.repo.header.create.state.62e71f2d5d", "Create workspace for {{value0}}", { value0: input.label }),
- ariaLabel: translate("auto.components.sidebar.repo.header.create.state.62e71f2d5d", "Create workspace for {{value0}}", { value0: input.label }),
+ tooltip: translate(
+ 'auto.components.sidebar.repo.header.create.state.62e71f2d5d',
+ 'Create workspace for {{value0}}',
+ { value0: input.label }
+ ),
+ ariaLabel: translate(
+ 'auto.components.sidebar.repo.header.create.state.62e71f2d5d',
+ 'Create workspace for {{value0}}',
+ { value0: input.label }
+ ),
requiresSshReconnect: false
}
}
@@ -32,16 +40,31 @@ export function getRepoHeaderCreateState(input: {
if (sshGate.selectedRepoRequiresConnection) {
return {
disabled: true,
- tooltip: translate("auto.components.sidebar.repo.header.create.state.6d022563a8", "Reconnect SSH target before creating workspaces"),
- ariaLabel: translate("auto.components.sidebar.repo.header.create.state.3a70acd808", "Reconnect SSH target before creating workspaces for {{value0}}", { value0: input.label }),
+ tooltip: translate(
+ 'auto.components.sidebar.repo.header.create.state.6d022563a8',
+ 'Reconnect SSH target before creating workspaces'
+ ),
+ ariaLabel: translate(
+ 'auto.components.sidebar.repo.header.create.state.3a70acd808',
+ 'Reconnect SSH target before creating workspaces for {{value0}}',
+ { value0: input.label }
+ ),
requiresSshReconnect: true
}
}
return {
disabled: false,
- tooltip: translate("auto.components.sidebar.repo.header.create.state.992cfbc44b", "Create new worktree for {{value0}}", { value0: input.label }),
- ariaLabel: translate("auto.components.sidebar.repo.header.create.state.992cfbc44b", "Create new worktree for {{value0}}", { value0: input.label }),
+ tooltip: translate(
+ 'auto.components.sidebar.repo.header.create.state.992cfbc44b',
+ 'Create new worktree for {{value0}}',
+ { value0: input.label }
+ ),
+ ariaLabel: translate(
+ 'auto.components.sidebar.repo.header.create.state.992cfbc44b',
+ 'Create new worktree for {{value0}}',
+ { value0: input.label }
+ ),
requiresSshReconnect: false
}
}
diff --git a/src/renderer/src/components/sidebar/sidebar-project-drop.ts b/src/renderer/src/components/sidebar/sidebar-project-drop.ts
index a1715d5edce..42c29ded37f 100644
--- a/src/renderer/src/components/sidebar/sidebar-project-drop.ts
+++ b/src/renderer/src/components/sidebar/sidebar-project-drop.ts
@@ -41,22 +41,40 @@ export function getSidebarProjectDropAffordance(args: {
return {
visible: true,
tone: 'busy',
- label: translate("auto.components.sidebar.sidebar.project.drop.18d3cf40e9", "Checking folder"),
- description: translate("auto.components.sidebar.sidebar.project.drop.d0f8943f8b", "Preparing the project add flow")
+ label: translate(
+ 'auto.components.sidebar.sidebar.project.drop.18d3cf40e9',
+ 'Checking folder'
+ ),
+ description: translate(
+ 'auto.components.sidebar.sidebar.project.drop.d0f8943f8b',
+ 'Preparing the project add flow'
+ )
}
}
if (args.remoteRuntimeActive) {
return {
visible: true,
tone: 'blocked',
- label: translate("auto.components.sidebar.sidebar.project.drop.e344666fb8", "Server runtime active"),
- description: translate("auto.components.sidebar.sidebar.project.drop.740e8d0d46", "Use Add Project for server paths")
+ label: translate(
+ 'auto.components.sidebar.sidebar.project.drop.e344666fb8',
+ 'Server runtime active'
+ ),
+ description: translate(
+ 'auto.components.sidebar.sidebar.project.drop.740e8d0d46',
+ 'Use Add Project for server paths'
+ )
}
}
return {
visible: true,
tone: 'ready',
- label: translate("auto.components.sidebar.sidebar.project.drop.ffc769ca29", "Drop folder to add project"),
- description: translate("auto.components.sidebar.sidebar.project.drop.669e12dd97", "Local folders and Git repositories")
+ label: translate(
+ 'auto.components.sidebar.sidebar.project.drop.ffc769ca29',
+ 'Drop folder to add project'
+ ),
+ description: translate(
+ 'auto.components.sidebar.sidebar.project.drop.669e12dd97',
+ 'Local folders and Git repositories'
+ )
}
}
diff --git a/src/renderer/src/components/sidebar/sleep-worktree-flow.ts b/src/renderer/src/components/sidebar/sleep-worktree-flow.ts
index adf181eee34..c6cee3f6288 100644
--- a/src/renderer/src/components/sidebar/sleep-worktree-flow.ts
+++ b/src/renderer/src/components/sidebar/sleep-worktree-flow.ts
@@ -144,7 +144,15 @@ export async function runSleepWorktrees(worktreeIds: readonly string[]): Promise
// otherwise continue — the active-worktree reset already happened so we
// don't leave the UI in a stale state.
toast.error(
- worktreeIds.length === 1 ? translate("auto.components.sidebar.sleep.worktree.flow.8bc3fc0671", "Failed to sleep workspace") : translate("auto.components.sidebar.sleep.worktree.flow.c460fecc4a", "Failed to sleep some workspaces"),
+ worktreeIds.length === 1
+ ? translate(
+ 'auto.components.sidebar.sleep.worktree.flow.8bc3fc0671',
+ 'Failed to sleep workspace'
+ )
+ : translate(
+ 'auto.components.sidebar.sleep.worktree.flow.c460fecc4a',
+ 'Failed to sleep some workspaces'
+ ),
{
description: errors.join('\n')
}
diff --git a/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts b/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts
index ba1dc380eea..44ff4b94b55 100644
--- a/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts
+++ b/src/renderer/src/components/sidebar/useAddRepoCloneFlow.ts
@@ -82,7 +82,12 @@ export function useAddRepoCloneFlow({
if (activeRuntimeEnvironmentId?.trim()) {
// Why: the native folder picker returns a client-local path. Runtime
// clone destinations must be typed as server paths.
- toast.error(translate("auto.components.sidebar.useAddRepoCloneFlow.0dc4d1b657", "Enter a server path for the clone destination."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useAddRepoCloneFlow.0dc4d1b657',
+ 'Enter a server path for the clone destination.'
+ )
+ )
return
}
const gen = cloneGenRef.current
@@ -124,7 +129,10 @@ export function useAddRepoCloneFlow({
if (gen !== cloneGenRef.current) {
return
}
- toast.success(translate("auto.components.sidebar.useAddRepoCloneFlow.4d0013cc93", "Repository cloned"), { description: repo.displayName })
+ toast.success(
+ translate('auto.components.sidebar.useAddRepoCloneFlow.4d0013cc93', 'Repository cloned'),
+ { description: repo.displayName }
+ )
// Why: eagerly upsert so step 2 finds the repo before the IPC event.
const state = useAppStore.getState()
const existingIdx = state.repos.findIndex((r) => r.id === repo.id)
diff --git a/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts b/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
index c9ea876afa7..6f3c8eeeb48 100644
--- a/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
+++ b/src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
@@ -69,7 +69,12 @@ export function useAddRepoLocalFolderFlow({
const handleAddLocalPath = useCallback(
async (path: string, source: AddRepoExistingWorkspaceSource): Promise => {
if (activeRuntimeEnvironmentId?.trim()) {
- toast.error(translate("auto.components.sidebar.useAddRepoLocalFolderFlow.7ab10e4974", "Use a server path to add projects from a remote runtime."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useAddRepoLocalFolderFlow.7ab10e4974',
+ 'Use a server path to add projects from a remote runtime.'
+ )
+ )
closeModal()
return
}
diff --git a/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts b/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
index c2c03a37119..b71012d50bb 100644
--- a/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
+++ b/src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
@@ -151,9 +151,15 @@ export function useAddRepoNestedImportFlow({
if (!firstRepoId) {
const firstFailure = result.projects.find((entry) => entry.status === 'failed')?.error
if (gen === nestedImportGenRef.current) {
- toast.error(translate("auto.components.sidebar.useAddRepoNestedImportFlow.1b33c5f090", "No repositories imported"), {
- description: firstFailure ?? undefined
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useAddRepoNestedImportFlow.1b33c5f090',
+ 'No repositories imported'
+ ),
+ {
+ description: firstFailure ?? undefined
+ }
+ )
}
return
}
@@ -166,9 +172,19 @@ export function useAddRepoNestedImportFlow({
return
}
if (result.failedCount > 0) {
- toast.warning(translate("auto.components.sidebar.useAddRepoNestedImportFlow.cbfbc7a797", "Some repositories could not be imported"), {
- description: translate("auto.components.sidebar.useAddRepoNestedImportFlow.680cac2c82", "{{value0}} failed", { value0: result.failedCount })
- })
+ toast.warning(
+ translate(
+ 'auto.components.sidebar.useAddRepoNestedImportFlow.cbfbc7a797',
+ 'Some repositories could not be imported'
+ ),
+ {
+ description: translate(
+ 'auto.components.sidebar.useAddRepoNestedImportFlow.680cac2c82',
+ '{{value0}} failed',
+ { value0: result.failedCount }
+ )
+ }
+ )
}
const repo = useAppStore.getState().repos.find((entry) => entry.id === firstRepoId)
if (repo) {
diff --git a/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts b/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts
index 0357cefad7f..2f0ba7539b2 100644
--- a/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts
+++ b/src/renderer/src/components/sidebar/useSidebarProjectDrop.ts
@@ -53,13 +53,27 @@ export function useSidebarProjectDrop(): {
return
}
if (pathResolution.status === 'multiple') {
- toast.warning(translate("auto.components.sidebar.useSidebarProjectDrop.c0315153d1", "Drop one folder at a time."))
+ toast.warning(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.c0315153d1',
+ 'Drop one folder at a time.'
+ )
+ )
return
}
if (remoteRuntimeActive) {
- toast.error(translate("auto.components.sidebar.useSidebarProjectDrop.849ef13dc0", "Local folder drops are unavailable for server runtimes."), {
- description: translate("auto.components.sidebar.useSidebarProjectDrop.5ccb56c7be", "Use Add Project to enter a server path.")
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.849ef13dc0',
+ 'Local folder drops are unavailable for server runtimes.'
+ ),
+ {
+ description: translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.5ccb56c7be',
+ 'Use Add Project to enter a server path.'
+ )
+ }
+ )
return
}
@@ -71,15 +85,26 @@ export function useSidebarProjectDrop(): {
return
}
if (!stat.isDirectory) {
- toast.error(translate("auto.components.sidebar.useSidebarProjectDrop.451a4638db", "Drop a folder to add it as a project."))
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.451a4638db',
+ 'Drop a folder to add it as a project.'
+ )
+ )
return
}
openModal('add-repo', { droppedLocalPath: pathResolution.path })
} catch (error) {
if (mountedRef.current) {
- toast.error(translate("auto.components.sidebar.useSidebarProjectDrop.f34a286c0d", "Could not add dropped folder."), {
- description: error instanceof Error ? error.message : String(error)
- })
+ toast.error(
+ translate(
+ 'auto.components.sidebar.useSidebarProjectDrop.f34a286c0d',
+ 'Could not add dropped folder.'
+ ),
+ {
+ description: error instanceof Error ? error.message : String(error)
+ }
+ )
}
} finally {
if (mountedRef.current) {
diff --git a/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx b/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx
index 3e5fbcb5281..a7cb8c2fdac 100644
--- a/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx
+++ b/src/renderer/src/components/sidebar/worktree-card-compact-agents.tsx
@@ -178,7 +178,17 @@ export function CompactAgentSummaryButton({
: 'border border-worktree-sidebar-border/70 bg-worktree-sidebar-accent/35'
)}
aria-label={
- expanded ? translate("auto.components.sidebar.worktree.card.compact.agents.0c1debfe84", "Collapse {{value0}}", { value0: subjectLabel }) : translate("auto.components.sidebar.worktree.card.compact.agents.289a1d2ca7", "Expand {{value0}}. {{value1}}", { value0: summary, value1: agentIdentitySummary })
+ expanded
+ ? translate(
+ 'auto.components.sidebar.worktree.card.compact.agents.0c1debfe84',
+ 'Collapse {{value0}}',
+ { value0: subjectLabel }
+ )
+ : translate(
+ 'auto.components.sidebar.worktree.card.compact.agents.289a1d2ca7',
+ 'Expand {{value0}}. {{value1}}',
+ { value0: summary, value1: agentIdentitySummary }
+ )
}
aria-expanded={expanded}
onClick={handleToggle}
@@ -298,7 +308,15 @@ export const CompactAgentRow = React.memo(function CompactAgentRow({
= {
done: {
- label: translate("auto.components.sidebar.worktree.list.groups.5076efc3d2", "Done"),
+ label: translate('auto.components.sidebar.worktree.list.groups.5076efc3d2', 'Done'),
icon: ConductorDoneIcon,
tone: 'text-[#c7a594]'
},
'in-review': {
- label: translate("auto.components.sidebar.worktree.list.groups.6798dc7c94", "In review"),
+ label: translate('auto.components.sidebar.worktree.list.groups.6798dc7c94', 'In review'),
icon: ConductorReviewIcon,
tone: 'text-[#16a34a]'
},
'in-progress': {
- label: translate("auto.components.sidebar.worktree.list.groups.7c2f009786", "In progress"),
+ label: translate('auto.components.sidebar.worktree.list.groups.7c2f009786', 'In progress'),
icon: ConductorProgressIcon,
tone: 'text-[#d4a300]'
},
closed: {
- label: translate("auto.components.sidebar.worktree.list.groups.682ed5d551", "Closed"),
+ label: translate('auto.components.sidebar.worktree.list.groups.682ed5d551', 'Closed'),
icon: CircleX,
tone: 'text-zinc-600 dark:text-zinc-300'
}
@@ -146,7 +146,7 @@ export function getProjectGroupHeaderKey(groupId: string | null): string {
export const PINNED_GROUP_KEY = 'pinned'
export const PINNED_GROUP_META = {
- label: translate("auto.components.sidebar.worktree.list.groups.4aeefc5996", "Pinned"),
+ label: translate('auto.components.sidebar.worktree.list.groups.4aeefc5996', 'Pinned'),
tone: 'text-foreground',
icon: Pin
} as const
@@ -154,7 +154,7 @@ export const PINNED_GROUP_META = {
export const ALL_GROUP_KEY = 'all'
export const ALL_GROUP_META = {
- label: translate("auto.components.sidebar.worktree.list.groups.0ed04075b8", "All"),
+ label: translate('auto.components.sidebar.worktree.list.groups.0ed04075b8', 'All'),
tone: 'text-foreground',
icon: List
} as const
diff --git a/src/renderer/src/components/skills/SkillsPage.tsx b/src/renderer/src/components/skills/SkillsPage.tsx
index 0be4ba4b569..302e16f4886 100644
--- a/src/renderer/src/components/skills/SkillsPage.tsx
+++ b/src/renderer/src/components/skills/SkillsPage.tsx
@@ -59,7 +59,9 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
const revealSkill = async (): Promise => {
const result = await window.api.shell.openInFileManager(skill.skillFilePath)
if (!result.ok) {
- toast.error(translate("auto.components.skills.SkillsPage.995fde8337", "Could not reveal skill file"))
+ toast.error(
+ translate('auto.components.skills.SkillsPage.995fde8337', 'Could not reveal skill file')
+ )
}
}
@@ -77,7 +79,9 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
variant={skill.installed ? 'secondary' : 'outline'}
className="h-5 text-[10px]"
>
- {skill.installed ? translate("auto.components.skills.SkillsPage.0c74e7ff34", "Local") : translate("auto.components.skills.SkillsPage.35b9a724a0", "Available")}
+ {skill.installed
+ ? translate('auto.components.skills.SkillsPage.0c74e7ff34', 'Local')
+ : translate('auto.components.skills.SkillsPage.35b9a724a0', 'Available')}
{sourceLabels[skill.sourceKind]}
@@ -88,7 +92,9 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
{skill.description}
) : (
- {translate("auto.components.skills.SkillsPage.9963dff6d3", "No description found.")}
+
+ {translate('auto.components.skills.SkillsPage.9963dff6d3', 'No description found.')}
+
)}
@@ -106,7 +112,8 @@ function SkillCard({ skill }: { skill: DiscoveredSkill }): React.JSX.Element {
- {translate("auto.components.skills.SkillsPage.dc4c3328ee", "Reveal file")}
+ {translate('auto.components.skills.SkillsPage.dc4c3328ee', 'Reveal file')}
+
@@ -154,18 +161,32 @@ function EmptyState({
)}
- {loading ? translate("auto.components.skills.SkillsPage.cd7893fbc1", "Scanning skills") : hasSkills ? translate("auto.components.skills.SkillsPage.6a62a0168c", "No matches") : translate("auto.components.skills.SkillsPage.4acd6d68ec", "No local skills found")}
+ {loading
+ ? translate('auto.components.skills.SkillsPage.cd7893fbc1', 'Scanning skills')
+ : hasSkills
+ ? translate('auto.components.skills.SkillsPage.6a62a0168c', 'No matches')
+ : translate(
+ 'auto.components.skills.SkillsPage.4acd6d68ec',
+ 'No local skills found'
+ )}
{hasSkills
- ? translate("auto.components.skills.SkillsPage.08a321a984", "Adjust the search or filters.")
- : translate("auto.components.skills.SkillsPage.ab5b777350", "Checked local home, repository, bundled, and plugin skill folders.")}
+ ? translate(
+ 'auto.components.skills.SkillsPage.08a321a984',
+ 'Adjust the search or filters.'
+ )
+ : translate(
+ 'auto.components.skills.SkillsPage.ab5b777350',
+ 'Checked local home, repository, bundled, and plugin skill folders.'
+ )}
{!loading ? (
- {translate("auto.components.skills.SkillsPage.cb142070b4", "Refresh")}
+ {translate('auto.components.skills.SkillsPage.cb142070b4', 'Refresh')}
+
) : null}
@@ -193,7 +214,9 @@ export default function SkillsPage(): React.JSX.Element {
} catch (error) {
console.error('Failed to discover skills:', error)
if (mountedRef.current) {
- toast.error(translate("auto.components.skills.SkillsPage.ea72d6185b", "Could not scan local skills"))
+ toast.error(
+ translate('auto.components.skills.SkillsPage.ea72d6185b', 'Could not scan local skills')
+ )
}
} finally {
if (mountedRef.current) {
@@ -259,16 +282,23 @@ export default function SkillsPage(): React.JSX.Element {
- {translate("auto.components.skills.SkillsPage.7e828fb2c6", "Back")}
+ {translate('auto.components.skills.SkillsPage.7e828fb2c6', 'Back')}
+
-
{translate("auto.components.skills.SkillsPage.f43ad6edf3", "Skills")}
- {translate("auto.components.skills.SkillsPage.b088e0785d", "Beta")}
+
+ {translate('auto.components.skills.SkillsPage.f43ad6edf3', 'Skills')}
+
+
+ {translate('auto.components.skills.SkillsPage.b088e0785d', 'Beta')}
+
- {pluralize(skills.length, 'skill')} {translate("auto.components.skills.SkillsPage.e46e162e2e", "from")}{pluralize(activeSourceCount, 'source')}
+ {pluralize(skills.length, 'skill')}{' '}
+ {translate('auto.components.skills.SkillsPage.e46e162e2e', 'from')}
+ {pluralize(activeSourceCount, 'source')}
@@ -281,7 +311,10 @@ export default function SkillsPage(): React.JSX.Element {
setFilters((next) => ({ ...next, query: event.target.value }))}
- placeholder={translate("auto.components.skills.SkillsPage.a68dee6a32", "Search skills")}
+ placeholder={translate(
+ 'auto.components.skills.SkillsPage.a68dee6a32',
+ 'Search skills'
+ )}
className="h-8 pl-8 text-sm"
/>
@@ -299,10 +332,18 @@ export default function SkillsPage(): React.JSX.Element {
- {translate("auto.components.skills.SkillsPage.39b6998ddb", "All providers")}
- {translate("auto.components.skills.SkillsPage.426be2aac6", "Codex")}
- {translate("auto.components.skills.SkillsPage.fb6bf60b52", "Claude")}
- {translate("auto.components.skills.SkillsPage.38e0951c3a", "Agent Skills")}
+
+ {translate('auto.components.skills.SkillsPage.39b6998ddb', 'All providers')}
+
+
+ {translate('auto.components.skills.SkillsPage.426be2aac6', 'Codex')}
+
+
+ {translate('auto.components.skills.SkillsPage.fb6bf60b52', 'Claude')}
+
+
+ {translate('auto.components.skills.SkillsPage.38e0951c3a', 'Agent Skills')}
+
- {translate("auto.components.skills.SkillsPage.0bc1379f4c", "All sources")}
- {translate("auto.components.skills.SkillsPage.571c5818c1", "Home")}
- {translate("auto.components.skills.SkillsPage.aa59462502", "Repository")}
- {translate("auto.components.skills.SkillsPage.4d177feabd", "Bundled")}
- {translate("auto.components.skills.SkillsPage.984405683f", "Plugin")}
+
+ {translate('auto.components.skills.SkillsPage.0bc1379f4c', 'All sources')}
+
+
+ {translate('auto.components.skills.SkillsPage.571c5818c1', 'Home')}
+
+
+ {translate('auto.components.skills.SkillsPage.aa59462502', 'Repository')}
+
+
+ {translate('auto.components.skills.SkillsPage.4d177feabd', 'Bundled')}
+
+
+ {translate('auto.components.skills.SkillsPage.984405683f', 'Plugin')}
+
- {translate("auto.components.skills.SkillsPage.cb142070b4", "Refresh")}
+ {translate('auto.components.skills.SkillsPage.cb142070b4', 'Refresh')}
+
diff --git a/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx b/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx
index 2bc458676a5..785c33f0faa 100644
--- a/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx
+++ b/src/renderer/src/components/stats/ClaudeUsageDailyChart.tsx
@@ -36,9 +36,15 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
return (
-
{translate("auto.components.stats.ClaudeUsageDailyChart.c9f7cd30e9", "Daily usage")}
+
+ {translate('auto.components.stats.ClaudeUsageDailyChart.c9f7cd30e9', 'Daily usage')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.059945f71d", "Input, output, cache read, and cache write totals by day.")}
+ {translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.059945f71d',
+ 'Input, output, cache read, and cache write totals by day.'
+ )}
+
{daily.slice(-10).map((entry) => {
@@ -46,23 +52,34 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
const segments = [
{
key: 'cache-write',
- label: translate("auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb", "Cache write"),
+ label: translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb',
+ 'Cache write'
+ ),
value: entry.cacheWriteTokens,
className: 'bg-fuchsia-500/70'
},
{
key: 'cache-read',
- label: translate("auto.components.stats.ClaudeUsageDailyChart.61c58f8976", "Cache read"),
+ label: translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.61c58f8976',
+ 'Cache read'
+ ),
value: entry.cacheReadTokens,
className: 'bg-amber-500/70'
},
{
key: 'output',
- label: translate("auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e", "Output"),
+ label: translate('auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e', 'Output'),
value: entry.outputTokens,
className: 'bg-emerald-500/80'
},
- { key: 'input', label: translate("auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b", "Input"), value: entry.inputTokens, className: 'bg-sky-500/80' }
+ {
+ key: 'input',
+ label: translate('auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b', 'Input'),
+ value: entry.inputTokens,
+ className: 'bg-sky-500/80'
+ }
]
return (
@@ -86,7 +103,12 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
{entry.day}
- {segment.label}: {segment.value.toLocaleString()} {translate("auto.components.stats.ClaudeUsageDailyChart.a7902d3c1d", "tokens")}
+ {segment.label}: {segment.value.toLocaleString()}{' '}
+ {translate(
+ 'auto.components.stats.ClaudeUsageDailyChart.a7902d3c1d',
+ 'tokens'
+ )}
+
@@ -106,16 +128,20 @@ export function ClaudeUsageDailyChart({ daily }: ClaudeUsageDailyChartProps): Re
- {translate("auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b", "Input")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.d7fb787e6b', 'Input')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e", "Output")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.7d2efeff5e', 'Output')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.61c58f8976", "Cache read")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.61c58f8976', 'Cache read')}
+
- {translate("auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb", "Cache write")}
+ {translate('auto.components.stats.ClaudeUsageDailyChart.2a6360c7cb', 'Cache write')}
+
)
diff --git a/src/renderer/src/components/stats/CodexUsageDailyChart.tsx b/src/renderer/src/components/stats/CodexUsageDailyChart.tsx
index 3d6fbcda4b4..3ac8b94dadb 100644
--- a/src/renderer/src/components/stats/CodexUsageDailyChart.tsx
+++ b/src/renderer/src/components/stats/CodexUsageDailyChart.tsx
@@ -32,34 +32,46 @@ export function CodexUsageDailyChart({ daily }: CodexUsageDailyChartProps): Reac
return (
-
{translate("auto.components.stats.CodexUsageDailyChart.609aa96e8b", "Daily usage")}
+
+ {translate('auto.components.stats.CodexUsageDailyChart.609aa96e8b', 'Daily usage')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.c756cda6a8", "Input, cached input, output, and reasoning totals by day.")}
+ {translate(
+ 'auto.components.stats.CodexUsageDailyChart.c756cda6a8',
+ 'Input, cached input, output, and reasoning totals by day.'
+ )}
+
{daily.slice(-10).map((entry) => {
const segments = [
{
key: 'input',
- label: translate("auto.components.stats.CodexUsageDailyChart.99a91d3143", "Input"),
+ label: translate('auto.components.stats.CodexUsageDailyChart.99a91d3143', 'Input'),
value: entry.inputTokens,
className: 'bg-sky-500/80'
},
{
key: 'output',
- label: translate("auto.components.stats.CodexUsageDailyChart.7b596a88b2", "Output"),
+ label: translate('auto.components.stats.CodexUsageDailyChart.7b596a88b2', 'Output'),
value: entry.outputTokens,
className: 'bg-emerald-500/80'
},
{
key: 'cached-input',
- label: translate("auto.components.stats.CodexUsageDailyChart.c646e1783c", "Cached input"),
+ label: translate(
+ 'auto.components.stats.CodexUsageDailyChart.c646e1783c',
+ 'Cached input'
+ ),
value: entry.cachedInputTokens,
className: 'bg-amber-500/70'
},
{
key: 'reasoning',
- label: translate("auto.components.stats.CodexUsageDailyChart.1e6f62d7e3", "Reasoning"),
+ label: translate(
+ 'auto.components.stats.CodexUsageDailyChart.1e6f62d7e3',
+ 'Reasoning'
+ ),
value: entry.reasoningOutputTokens,
className: 'bg-fuchsia-500/70'
}
@@ -86,7 +98,12 @@ export function CodexUsageDailyChart({ daily }: CodexUsageDailyChartProps): Reac
{entry.day}
- {segment.label}: {segment.value.toLocaleString()} {translate("auto.components.stats.CodexUsageDailyChart.e4bdcf0071", "tokens")}
+ {segment.label}: {segment.value.toLocaleString()}{' '}
+ {translate(
+ 'auto.components.stats.CodexUsageDailyChart.e4bdcf0071',
+ 'tokens'
+ )}
+
@@ -106,16 +123,20 @@ export function CodexUsageDailyChart({ daily }: CodexUsageDailyChartProps): Reac
- {translate("auto.components.stats.CodexUsageDailyChart.99a91d3143", "Input")}
+ {translate('auto.components.stats.CodexUsageDailyChart.99a91d3143', 'Input')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.7b596a88b2", "Output")}
+ {translate('auto.components.stats.CodexUsageDailyChart.7b596a88b2', 'Output')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.c646e1783c", "Cached input")}
+ {translate('auto.components.stats.CodexUsageDailyChart.c646e1783c', 'Cached input')}
+
- {translate("auto.components.stats.CodexUsageDailyChart.1e6f62d7e3", "Reasoning")}
+ {translate('auto.components.stats.CodexUsageDailyChart.1e6f62d7e3', 'Reasoning')}
+
)
diff --git a/src/renderer/src/components/stats/ShareUsageButton.tsx b/src/renderer/src/components/stats/ShareUsageButton.tsx
index 44dcdb2a9cd..fe009152d43 100644
--- a/src/renderer/src/components/stats/ShareUsageButton.tsx
+++ b/src/renderer/src/components/stats/ShareUsageButton.tsx
@@ -126,19 +126,25 @@ export function ShareUsageButton(props: ShareUsageButtonProps): React.JSX.Elemen
ref={setShareButtonRef}
variant="ghost"
size="icon-xs"
- aria-label={translate("auto.components.stats.ShareUsageButton.bce08eccb9", "Share usage")}
+ aria-label={translate(
+ 'auto.components.stats.ShareUsageButton.bce08eccb9',
+ 'Share usage'
+ )}
>
- {translate("auto.components.stats.ShareUsageButton.cecefa7c32", "Share")}
+ {translate('auto.components.stats.ShareUsageButton.cecefa7c32', 'Share')}
+
- {translate("auto.components.stats.ShareUsageButton.bce08eccb9", "Share usage")}
+
+ {translate('auto.components.stats.ShareUsageButton.bce08eccb9', 'Share usage')}
+
@@ -147,11 +153,13 @@ export function ShareUsageButton(props: ShareUsageButtonProps): React.JSX.Elemen
{copied ? (
<>
- {translate("auto.components.stats.ShareUsageButton.bd82c76a70", "Copied")}>
+ {translate('auto.components.stats.ShareUsageButton.bd82c76a70', 'Copied')}
+ >
) : (
<>
- {translate("auto.components.stats.ShareUsageButton.b295c1c75d", "Copy image")}>
+ {translate('auto.components.stats.ShareUsageButton.b295c1c75d', 'Copy image')}
+ >
)}
- {translate("auto.components.stats.ShareUsageButton.7d6b25323d", "Share on X")}
+ {translate('auto.components.stats.ShareUsageButton.7d6b25323d', 'Share on X')}
+
diff --git a/src/renderer/src/components/stats/ShareUsageCard.tsx b/src/renderer/src/components/stats/ShareUsageCard.tsx
index b82ffd20cde..cb6eb5c92bf 100644
--- a/src/renderer/src/components/stats/ShareUsageCard.tsx
+++ b/src/renderer/src/components/stats/ShareUsageCard.tsx
@@ -44,8 +44,14 @@ export const ShareUsageCard = forwardRef(
const turnsOrEvents =
provider === 'claude'
- ? { label: translate("auto.components.stats.ShareUsageCard.6adac63cfe", "turns"), count: (summary as ClaudeUsageSummary).turns }
- : { label: translate("auto.components.stats.ShareUsageCard.960324e9b8", "events"), count: (summary as CodexUsageSummary).events }
+ ? {
+ label: translate('auto.components.stats.ShareUsageCard.6adac63cfe', 'turns'),
+ count: (summary as ClaudeUsageSummary).turns
+ }
+ : {
+ label: translate('auto.components.stats.ShareUsageCard.960324e9b8', 'events'),
+ count: (summary as CodexUsageSummary).events
+ }
const providerLabel = provider === 'claude' ? 'Claude' : 'Codex'
@@ -106,9 +112,12 @@ function CardHeader(props: { providerLabel: string; range: string }): React.JSX.
- {translate("auto.components.stats.ShareUsageCard.0eb31e79ee", "Orca IDE")}
+ {translate('auto.components.stats.ShareUsageCard.0eb31e79ee', 'Orca IDE')}
+
- {props.providerLabel} {translate("auto.components.stats.ShareUsageCard.da62578d9d", "Usage")}
+ {props.providerLabel}{' '}
+ {translate('auto.components.stats.ShareUsageCard.da62578d9d', 'Usage')}
+
@@ -138,7 +147,7 @@ function StatsGrid(props: {
const cards = [
{
value: formatCost(props.summary.estimatedCostUsd ?? null),
- label: translate("auto.components.stats.ShareUsageCard.beb6f24f37", "Est. cost"),
+ label: translate('auto.components.stats.ShareUsageCard.beb6f24f37', 'Est. cost'),
bg: 'rgba(20, 71, 230, 0.1)',
border: '1px solid rgba(20, 71, 230, 0.2)',
valueColor: '#93b4ff',
@@ -146,7 +155,7 @@ function StatsGrid(props: {
},
{
value: formatTokens(props.totalTokens),
- label: translate("auto.components.stats.ShareUsageCard.2d9eb39264", "Total tokens"),
+ label: translate('auto.components.stats.ShareUsageCard.2d9eb39264', 'Total tokens'),
bg: 'rgba(255, 255, 255, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.06)',
valueColor: '#fafafa',
@@ -154,7 +163,7 @@ function StatsGrid(props: {
},
{
value: props.topModel,
- label: translate("auto.components.stats.ShareUsageCard.b760c0b622", "Top model"),
+ label: translate('auto.components.stats.ShareUsageCard.b760c0b622', 'Top model'),
bg: 'rgba(255, 255, 255, 0.04)',
border: '1px solid rgba(255, 255, 255, 0.06)',
valueColor: '#fafafa',
@@ -218,11 +227,14 @@ function ChartHeader(props: {
textTransform: 'uppercase' as const
}}
>
- {translate("auto.components.stats.ShareUsageCard.66c83284cf", "Daily tokens")}
+ {translate('auto.components.stats.ShareUsageCard.66c83284cf', 'Daily tokens')}
+
- {props.sessions} {translate("auto.components.stats.ShareUsageCard.4a4c6c79a3", "sessions ·")}{props.turnsOrEvents.count} {props.turnsOrEvents.label}
+ {props.sessions}{' '}
+ {translate('auto.components.stats.ShareUsageCard.4a4c6c79a3', 'sessions ·')}
+ {props.turnsOrEvents.count} {props.turnsOrEvents.label}
diff --git a/src/renderer/src/components/stats/UsageOverviewPane.tsx b/src/renderer/src/components/stats/UsageOverviewPane.tsx
index a4fff2d6cf6..1f2080c995d 100644
--- a/src/renderer/src/components/stats/UsageOverviewPane.tsx
+++ b/src/renderer/src/components/stats/UsageOverviewPane.tsx
@@ -107,10 +107,17 @@ export function UsageOverviewPane(): React.JSX.Element {
-
{translate("auto.components.stats.UsageOverviewPane.c760c481c5", "Usage Overview")}
+
+ {translate('auto.components.stats.UsageOverviewPane.c760c481c5', 'Usage Overview')}
+
{formatUpdatedAt(overview.lastUpdatedAt)}
- {overview.hasPartialCost ? translate("auto.components.stats.UsageOverviewPane.55c910f4f1", "- some model prices are unavailable") : ''}
+ {overview.hasPartialCost
+ ? translate(
+ 'auto.components.stats.UsageOverviewPane.55c910f4f1',
+ '- some model prices are unavailable'
+ )
+ : ''}
@@ -120,13 +127,17 @@ export function UsageOverviewPane(): React.JSX.Element {
size="icon-xs"
onClick={handleRefresh}
disabled={!overview.hasAnyEnabledProvider || isScanning}
- aria-label={translate("auto.components.stats.UsageOverviewPane.e06d1baf5c", "Refresh usage overview")}
+ aria-label={translate(
+ 'auto.components.stats.UsageOverviewPane.e06d1baf5c',
+ 'Refresh usage overview'
+ )}
>
- {translate("auto.components.stats.UsageOverviewPane.ca6bc5fded", "Refresh")}
+ {translate('auto.components.stats.UsageOverviewPane.ca6bc5fded', 'Refresh')}
+
@@ -134,9 +145,18 @@ export function UsageOverviewPane(): React.JSX.Element {
-
{translate("auto.components.stats.UsageOverviewPane.49405ccc8d", "Start tracking tokens")}
+
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.49405ccc8d',
+ 'Start tracking tokens'
+ )}
+
- {translate("auto.components.stats.UsageOverviewPane.6c00c46815", "Enable a provider to scan local agent logs and build the combined token ledger.")}
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.6c00c46815',
+ 'Enable a provider to scan local agent logs and build the combined token ledger.'
+ )}
+
- {translate("auto.components.stats.UsageOverviewPane.0ea0cae435", "Enable Claude")}
+ {translate('auto.components.stats.UsageOverviewPane.0ea0cae435', 'Enable Claude')}
+
- {translate("auto.components.stats.UsageOverviewPane.2f1ee2878b", "Enable Codex")}
+ {translate('auto.components.stats.UsageOverviewPane.2f1ee2878b', 'Enable Codex')}
+
- {translate("auto.components.stats.UsageOverviewPane.2d13e57f72", "Enable OpenCode")}
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.2d13e57f72',
+ 'Enable OpenCode'
+ )}
+
@@ -172,22 +198,31 @@ export function UsageOverviewPane(): React.JSX.Element {
<>
}
/>
}
/>
}
/>
}
/>
@@ -195,7 +230,11 @@ export function UsageOverviewPane(): React.JSX.Element {
{!overview.hasAnyData ? (
- {translate("auto.components.stats.UsageOverviewPane.60002bb22f", "No local Claude, Codex, or OpenCode usage found yet. The overview will populate after the next agent session writes token logs.")}
+ {translate(
+ 'auto.components.stats.UsageOverviewPane.60002bb22f',
+ 'No local Claude, Codex, or OpenCode usage found yet. The overview will populate after the next agent session writes token logs.'
+ )}
+
) : (
@@ -209,13 +248,21 @@ export function UsageOverviewPane(): React.JSX.Element {
-
{translate("auto.components.stats.UsageOverviewPane.33f7b043d2", "Providers")}
+
+ {translate('auto.components.stats.UsageOverviewPane.33f7b043d2', 'Providers')}
+
- {overview.enabledProviderCount} {translate("auto.components.stats.UsageOverviewPane.ecb0cd8a4c", "enabled -")}{overview.dataProviderCount} {translate("auto.components.stats.UsageOverviewPane.444585cb41", "with data")}
+ {overview.enabledProviderCount}{' '}
+ {translate('auto.components.stats.UsageOverviewPane.ecb0cd8a4c', 'enabled -')}
+ {overview.dataProviderCount}{' '}
+ {translate('auto.components.stats.UsageOverviewPane.444585cb41', 'with data')}
+
- {overview.sessions.toLocaleString()} {translate("auto.components.stats.UsageOverviewPane.22ed1b7669", "sessions")}
+ {overview.sessions.toLocaleString()}{' '}
+ {translate('auto.components.stats.UsageOverviewPane.22ed1b7669', 'sessions')}
+
{overview.providers.map((provider) => (
diff --git a/src/renderer/src/components/stats/share-card-utils.tsx b/src/renderer/src/components/stats/share-card-utils.tsx
index 07179bdbdc8..a63ba5e18ec 100644
--- a/src/renderer/src/components/stats/share-card-utils.tsx
+++ b/src/renderer/src/components/stats/share-card-utils.tsx
@@ -89,17 +89,41 @@ export function getDailySegments(
export function getLegendItems(provider: 'claude' | 'codex') {
if (provider === 'claude') {
return [
- { label: translate("auto.components.stats.share.card.utils.c2d7b23d57", "Input"), color: 'rgba(56, 189, 248, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.33d38e2177", "Output"), color: 'rgba(52, 211, 153, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.cc28cb965e", "Cache read"), color: 'rgba(251, 191, 36, 0.7)' },
- { label: translate("auto.components.stats.share.card.utils.9d166247ee", "Cache write"), color: 'rgba(217, 70, 239, 0.7)' }
+ {
+ label: translate('auto.components.stats.share.card.utils.c2d7b23d57', 'Input'),
+ color: 'rgba(56, 189, 248, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.33d38e2177', 'Output'),
+ color: 'rgba(52, 211, 153, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.cc28cb965e', 'Cache read'),
+ color: 'rgba(251, 191, 36, 0.7)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.9d166247ee', 'Cache write'),
+ color: 'rgba(217, 70, 239, 0.7)'
+ }
]
}
return [
- { label: translate("auto.components.stats.share.card.utils.c2d7b23d57", "Input"), color: 'rgba(56, 189, 248, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.33d38e2177", "Output"), color: 'rgba(52, 211, 153, 0.8)' },
- { label: translate("auto.components.stats.share.card.utils.4ee864629a", "Cached input"), color: 'rgba(251, 191, 36, 0.7)' },
- { label: translate("auto.components.stats.share.card.utils.7080aeaebb", "Reasoning"), color: 'rgba(217, 70, 239, 0.7)' }
+ {
+ label: translate('auto.components.stats.share.card.utils.c2d7b23d57', 'Input'),
+ color: 'rgba(56, 189, 248, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.33d38e2177', 'Output'),
+ color: 'rgba(52, 211, 153, 0.8)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.4ee864629a', 'Cached input'),
+ color: 'rgba(251, 191, 36, 0.7)'
+ },
+ {
+ label: translate('auto.components.stats.share.card.utils.7080aeaebb', 'Reasoning'),
+ color: 'rgba(217, 70, 239, 0.7)'
+ }
]
}
@@ -168,10 +192,13 @@ export function CardFooter(props: {
>
- {formatTokens(props.summary.inputTokens)} {translate("auto.components.stats.share.card.utils.5d66fdd7c2", "input")}
+ {formatTokens(props.summary.inputTokens)} {' '}
+ {translate('auto.components.stats.share.card.utils.5d66fdd7c2', 'input')}
+
{formatTokens(props.summary.outputTokens)} {' '}
- {translate("auto.components.stats.share.card.utils.d864fc5f98", "output")}
+ {translate('auto.components.stats.share.card.utils.d864fc5f98', 'output')}
+
@@ -186,7 +213,11 @@ export function CardFooter(props: {
marginLeft: 5
}}
>
- {translate("auto.components.stats.share.card.utils.19f4b4dc75", "github.com/stablyai/orca")}
+ {translate(
+ 'auto.components.stats.share.card.utils.19f4b4dc75',
+ 'github.com/stablyai/orca'
+ )}
+
)
diff --git a/src/renderer/src/components/stats/usage-overview-model.ts b/src/renderer/src/components/stats/usage-overview-model.ts
index e8db99164d5..db419949825 100644
--- a/src/renderer/src/components/stats/usage-overview-model.ts
+++ b/src/renderer/src/components/stats/usage-overview-model.ts
@@ -136,7 +136,7 @@ function createClaudeProvider(input: UsageOverviewInput['claude']): UsageProvide
.map((entry) => entry.day)
return {
id: 'claude',
- label: translate("auto.components.stats.usage.overview.model.544d6d4c16", "Claude"),
+ label: translate('auto.components.stats.usage.overview.model.544d6d4c16', 'Claude'),
enabled: input.scanState?.enabled ?? false,
isScanning: input.scanState?.isScanning ?? false,
hasData: summary?.hasAnyClaudeData ?? input.scanState?.hasAnyClaudeData ?? false,
@@ -169,7 +169,7 @@ function createCodexProvider(input: UsageOverviewInput['codex']): UsageProviderO
.map((entry) => entry.day)
return {
id: 'codex',
- label: translate("auto.components.stats.usage.overview.model.eb220d193b", "Codex"),
+ label: translate('auto.components.stats.usage.overview.model.eb220d193b', 'Codex'),
enabled: input.scanState?.enabled ?? false,
isScanning: input.scanState?.isScanning ?? false,
hasData: summary?.hasAnyCodexData ?? input.scanState?.hasAnyCodexData ?? false,
@@ -197,7 +197,7 @@ function createOpenCodeProvider(input: UsageOverviewInput['opencode']): UsagePro
.map((entry) => entry.day)
return {
id: 'opencode',
- label: translate("auto.components.stats.usage.overview.model.bc474051e5", "OpenCode"),
+ label: translate('auto.components.stats.usage.overview.model.bc474051e5', 'OpenCode'),
enabled: input.scanState?.enabled ?? false,
isScanning: input.scanState?.isScanning ?? false,
hasData: summary?.hasAnyOpenCodeData ?? input.scanState?.hasAnyOpenCodeData ?? false,
diff --git a/src/renderer/src/components/status-bar/PetStatusSegment.tsx b/src/renderer/src/components/status-bar/PetStatusSegment.tsx
index bf816d22d04..b927e29351e 100644
--- a/src/renderer/src/components/status-bar/PetStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/PetStatusSegment.tsx
@@ -46,7 +46,12 @@ function PetStatusSegmentInner(): React.JSX.Element {
console.log('[pet-overlay] upload: click')
if (!window.api?.pet?.import) {
console.warn('[pet-overlay] upload: window.api.pet.import missing — restart Orca')
- toast.error(translate("auto.components.status.bar.PetStatusSegment.e6234bcc17", "Custom pet upload needs a full app restart (not just reload)."))
+ toast.error(
+ translate(
+ 'auto.components.status.bar.PetStatusSegment.e6234bcc17',
+ 'Custom pet upload needs a full app restart (not just reload).'
+ )
+ )
return
}
try {
@@ -62,13 +67,25 @@ function PetStatusSegmentInner(): React.JSX.Element {
setPetId(model.id)
} catch (error) {
console.error('[pet-overlay] upload: error', error)
- toast.error(error instanceof Error ? error.message : translate("auto.components.status.bar.PetStatusSegment.f395c9a685", "Failed to import file"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.status.bar.PetStatusSegment.f395c9a685',
+ 'Failed to import file'
+ )
+ )
}
}
const handleImportPetBundle = async (): Promise => {
if (!window.api?.pet?.importPetBundle) {
- toast.error(translate("auto.components.status.bar.PetStatusSegment.2021d4f6db", "Pet bundle import needs a full app restart (not just reload)."))
+ toast.error(
+ translate(
+ 'auto.components.status.bar.PetStatusSegment.2021d4f6db',
+ 'Pet bundle import needs a full app restart (not just reload).'
+ )
+ )
return
}
try {
@@ -83,7 +100,14 @@ function PetStatusSegmentInner(): React.JSX.Element {
setPetId(model.id)
} catch (error) {
console.error('[pet-overlay] pet bundle: error', error)
- toast.error(error instanceof Error ? error.message : translate("auto.components.status.bar.PetStatusSegment.cef0ab4636", "Failed to import pet bundle"))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.status.bar.PetStatusSegment.cef0ab4636',
+ 'Failed to import pet bundle'
+ )
+ )
}
}
@@ -93,7 +117,10 @@ function PetStatusSegmentInner(): React.JSX.Element {
- {translate("auto.components.status.bar.PetStatusSegment.34c25dfe9c", "Pet")}
+
+ {translate('auto.components.status.bar.PetStatusSegment.34c25dfe9c', 'Pet')}
+
{
event.preventDefault()
setPetVisible(!petVisible)
}}
>
- {petVisible ? translate("auto.components.status.bar.PetStatusSegment.1fbc51cc77", "Hide pet") : translate("auto.components.status.bar.PetStatusSegment.6d0a8cd179", "Show pet")}
+ {petVisible
+ ? translate('auto.components.status.bar.PetStatusSegment.1fbc51cc77', 'Hide pet')
+ : translate('auto.components.status.bar.PetStatusSegment.6d0a8cd179', 'Show pet')}
{/* Why: in-menu range so users can resize the overlay without leaving
the dropdown — pet sprites can import larger than the default 180px
@@ -123,8 +154,13 @@ function PetStatusSegmentInner(): React.JSX.Element {
onKeyDown={(e) => e.stopPropagation()}
>
- {translate("auto.components.status.bar.PetStatusSegment.2f7bbaa457", "Size")}
- {petSize}{translate("auto.components.status.bar.PetStatusSegment.c6aa805b1b", "px")}
+
+ {translate('auto.components.status.bar.PetStatusSegment.2f7bbaa457', 'Size')}
+
+
+ {petSize}
+ {translate('auto.components.status.bar.PetStatusSegment.c6aa805b1b', 'px')}
+
setPetSize(Number(e.target.value))}
className="w-full"
- aria-label={translate("auto.components.status.bar.PetStatusSegment.b75484a01a", "Pet size")}
+ aria-label={translate(
+ 'auto.components.status.bar.PetStatusSegment.b75484a01a',
+ 'Pet size'
+ )}
/>
- {translate("auto.components.status.bar.PetStatusSegment.0608ad02a2", "Choose pet")}
+
+ {translate('auto.components.status.bar.PetStatusSegment.0608ad02a2', 'Choose pet')}
+
{/* Why: portal so the submenu escapes the parent Content's overflow
clipping — without this, the submenu opens inside the scroll
container and gets clipped. Matches the convention used in
@@ -185,7 +226,11 @@ function PetStatusSegmentInner(): React.JSX.Element {
{
event.stopPropagation()
event.preventDefault()
@@ -208,14 +253,22 @@ function PetStatusSegmentInner(): React.JSX.Element {
}}
>
- {translate("auto.components.status.bar.PetStatusSegment.59b5955621", "Upload your own…")}
+ {translate(
+ 'auto.components.status.bar.PetStatusSegment.59b5955621',
+ 'Upload your own…'
+ )}
+
{
void handleImportPetBundle()
}}
>
- {translate("auto.components.status.bar.PetStatusSegment.ed176ad68f", "Import .codex-pet bundle…")}
+ {translate(
+ 'auto.components.status.bar.PetStatusSegment.ed176ad68f',
+ 'Import .codex-pet bundle…'
+ )}
+
@@ -230,7 +283,8 @@ function PetStatusSegmentInner(): React.JSX.Element {
openSettingsPage()
}}
>
- {translate("auto.components.status.bar.PetStatusSegment.cd8c6c654c", "Pet settings…")}
+ {translate('auto.components.status.bar.PetStatusSegment.cd8c6c654c', 'Pet settings…')}
+
)
diff --git a/src/renderer/src/components/status-bar/SshStatusSegment.tsx b/src/renderer/src/components/status-bar/SshStatusSegment.tsx
index 329426f743c..9a959648c4d 100644
--- a/src/renderer/src/components/status-bar/SshStatusSegment.tsx
+++ b/src/renderer/src/components/status-bar/SshStatusSegment.tsx
@@ -126,7 +126,11 @@ function TargetRow({
await window.api.ssh.connect({ targetId })
recordFeatureInteraction('ssh')
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.status.bar.SshStatusSegment.2c29e2de68", "Connection failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate('auto.components.status.bar.SshStatusSegment.2c29e2de68', 'Connection failed')
+ )
} finally {
if (mountedRef.current) {
setBusy(false)
@@ -140,7 +144,11 @@ function TargetRow({
await window.api.ssh.disconnect({ targetId })
recordFeatureInteraction('ssh')
} catch (err) {
- toast.error(err instanceof Error ? err.message : translate("auto.components.status.bar.SshStatusSegment.bf07aee59e", "Disconnect failed"))
+ toast.error(
+ err instanceof Error
+ ? err.message
+ : translate('auto.components.status.bar.SshStatusSegment.bf07aee59e', 'Disconnect failed')
+ )
} finally {
if (mountedRef.current) {
setBusy(false)
@@ -157,9 +165,9 @@ function TargetRow({
{STATUS_LABELS[status]}
·
- {syncStatus?.phase === "pulling" || syncStatus?.phase === "pushing" ? (
+ {syncStatus?.phase === 'pulling' || syncStatus?.phase === 'pushing' ? (
- ) : syncStatus?.phase === "conflict" || syncStatus?.phase === 'error' ? (
+ ) : syncStatus?.phase === 'conflict' || syncStatus?.phase === 'error' ? (
) : (
@@ -176,14 +184,16 @@ function TargetRow({
onClick={() => void handleConnect()}
className="shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium text-foreground hover:bg-accent/70"
>
- {translate("auto.components.status.bar.SshStatusSegment.63f36455cc", "Connect")}
- ) : status === "connected" ? (
+ {translate('auto.components.status.bar.SshStatusSegment.63f36455cc', 'Connect')}
+
+ ) : status === 'connected' ? (
void handleDisconnect()}
className="shrink-0 rounded px-1.5 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/70 hover:text-foreground"
>
- {translate("auto.components.status.bar.SshStatusSegment.59b553e2aa", "Disconnect")}
+ {translate('auto.components.status.bar.SshStatusSegment.59b553e2aa', 'Disconnect')}
+
) : null}
)
@@ -243,7 +253,10 @@ export function SshStatusSegment({
{iconOnly ? (
@@ -266,16 +279,16 @@ export function SshStatusSegment({
) : anyConnecting ? (
- ) : overall === "connected" ? (
+ ) : overall === 'connected' ? (
- ) : overall === "partial" ? (
+ ) : overall === 'partial' ? (
) : (
)}
{!compact && (
- {translate("auto.components.status.bar.SshStatusSegment.d09ec41831", "SSH")}{' '}
+ {translate('auto.components.status.bar.SshStatusSegment.d09ec41831', 'SSH')}{' '}
{syncProblemLabel ?? overallLabel(overall)}
@@ -297,7 +310,8 @@ export function SshStatusSegment({
className="w-[min(20rem,calc(100vw-1rem))]"
>
- {translate("auto.components.status.bar.SshStatusSegment.6e8a9a4242", "SSH Connections")}
+ {translate('auto.components.status.bar.SshStatusSegment.6e8a9a4242', 'SSH Connections')}
+
{targets.map((t) => (
- {translate("auto.components.status.bar.SshStatusSegment.3ad70e0365", "Manage SSH…")}
+ {translate('auto.components.status.bar.SshStatusSegment.3ad70e0365', 'Manage SSH…')}
+
)
diff --git a/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx b/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx
index cd513384622..33b1adb6269 100644
--- a/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx
+++ b/src/renderer/src/components/status-bar/StatusBarUsageEmptyCta.tsx
@@ -36,17 +36,30 @@ export function StatusBarUsageEmptyCta(): React.JSX.Element {
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.d663430cf9", "Connect an AI account to see usage")}
+
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.d663430cf9',
+ 'Connect an AI account to see usage'
+ )}
+
-
{translate("auto.components.status.bar.StatusBarUsageEmptyCta.84c3b15dca", "Agent usage limits")}
+
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.84c3b15dca',
+ 'Agent usage limits'
+ )}
+
{/* Why: permanently hide the teaching CTA — styling mirrors the
SetupGuideSidebarEntry hover-state icon (muted → foreground). */}
@@ -54,22 +67,38 @@ export function StatusBarUsageEmptyCta(): React.JSX.Element {
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.9a542f46c7", "Hide from status bar")}
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.9a542f46c7',
+ 'Hide from status bar'
+ )}
+
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.97957ad3a3", "Connect your AI provider accounts to see their usage in real time and easily switch between accounts.")}
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.97957ad3a3',
+ 'Connect your AI provider accounts to see their usage in real time and easily switch between accounts.'
+ )}
+
{/* Why: name the full provider set so the feature doesn't read as
support for just one agent. */}
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.caa0f39811", "Supports:")}
+
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.caa0f39811',
+ 'Supports:'
+ )}
+
@@ -83,7 +112,11 @@ export function StatusBarUsageEmptyCta(): React.JSX.Element {
onClick={handleOpenSettings}
className="mt-0.5 h-7 w-full text-xs"
>
- {translate("auto.components.status.bar.StatusBarUsageEmptyCta.828c764a79", "Connect an account")}
+ {translate(
+ 'auto.components.status.bar.StatusBarUsageEmptyCta.828c764a79',
+ 'Connect an account'
+ )}
+
diff --git a/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx b/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx
index 3839c9b498a..639ca8fb08f 100644
--- a/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx
+++ b/src/renderer/src/components/status-bar/WorkspaceSpaceCompactPanel.tsx
@@ -40,20 +40,54 @@ export function WorkspaceSpaceCompactPanel({
- {translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.8ff597593d", "Space")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.8ff597593d',
+ 'Space'
+ )}
+
- {translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.c361440dc0", "Beta")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.c361440dc0',
+ 'Beta'
+ )}
+
{analysis
? isScanning
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.3d8d47ce77", "{{value0}} · last result kept", { value0: progressLabel ?? 'Scanning workspace sizes' })
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.3d8d47ce77',
+ '{{value0}} · last result kept',
+ { value0: progressLabel ?? 'Scanning workspace sizes' }
+ )
: analysis.unavailableWorktreeCount > 0
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457", "{{value0}} reclaimable · {{value1}} unavailable", { value0: formatBytes(analysis.reclaimableBytes), value1: analysis.unavailableWorktreeCount })
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457", "{{value0}} reclaimable · {{value1}} workspaces", { value0: formatBytes(analysis.reclaimableBytes), value1: analysis.scannedWorktreeCount })
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457',
+ '{{value0}} reclaimable · {{value1}} unavailable',
+ {
+ value0: formatBytes(analysis.reclaimableBytes),
+ value1: analysis.unavailableWorktreeCount
+ }
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.bef4dc0457',
+ '{{value0}} reclaimable · {{value1}} workspaces',
+ {
+ value0: formatBytes(analysis.reclaimableBytes),
+ value1: analysis.scannedWorktreeCount
+ }
+ )
: isScanning
- ? (progressLabel ?? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.39786e3b73", "Scanning workspace sizes."))
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.0583c806ac", "Workspace disk usage is not scanned.")}
+ ? (progressLabel ??
+ translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.39786e3b73',
+ 'Scanning workspace sizes.'
+ ))
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.0583c806ac',
+ 'Workspace disk usage is not scanned.'
+ )}
@@ -67,7 +101,7 @@ export function WorkspaceSpaceCompactPanel({
className="w-24"
>
{isScanning ? (
- progress?.state === "cancelling" ? (
+ progress?.state === 'cancelling' ? (
) : (
@@ -76,34 +110,65 @@ export function WorkspaceSpaceCompactPanel({
)}
{isScanning
- ? progress?.state === "cancelling"
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.5691353a21", "Stopping")
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.2af2174d6d", "Cancel")
+ ? progress?.state === 'cancelling'
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.5691353a21',
+ 'Stopping'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.2af2174d6d',
+ 'Cancel'
+ )
: analysis
- ? translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.f5e1a84d79", "Refresh")
- : translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.0582df6d2e", "Scan")}
+ ? translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.f5e1a84d79',
+ 'Refresh'
+ )
+ : translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.0582df6d2e',
+ 'Scan'
+ )}
- {translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.6a5dc3c61a", "Review")}
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.6a5dc3c61a',
+ 'Review'
+ )}
+
{analysis ? (
-
{translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.f4d2651498", "Scanned")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.f4d2651498',
+ 'Scanned'
+ )}
+
{formatBytes(analysis.totalSizeBytes)}
-
{translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.9be86c46a0", "Freeable")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.9be86c46a0',
+ 'Freeable'
+ )}
+
{formatBytes(analysis.reclaimableBytes)}
-
{translate("auto.components.status.bar.WorkspaceSpaceCompactPanel.a471aa9c24", "Updated")}
+
+ {translate(
+ 'auto.components.status.bar.WorkspaceSpaceCompactPanel.a471aa9c24',
+ 'Updated'
+ )}
+
{getWorkspaceSpaceScanTimeLabel(analysis.scannedAt)}
diff --git a/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx b/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx
index d71f8127513..ccb52012710 100644
--- a/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx
+++ b/src/renderer/src/components/status-bar/ports-status-popover-rows.tsx
@@ -96,7 +96,13 @@ export function PortRow({
openInOrcaBrowser
}).then((result) => {
if (!result.ok) {
- toast.error(translate("auto.components.status.bar.ports.status.popover.rows.b854ec9ff5", "Failed to open browser"), { description: result.reason })
+ toast.error(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.b854ec9ff5',
+ 'Failed to open browser'
+ ),
+ { description: result.reason }
+ )
}
})
},
@@ -117,7 +123,13 @@ export function PortRow({
recordFeatureInteraction('ports')
const address = addressForPort(port)
void window.api.ui.writeClipboardText(address)
- toast.success(translate("auto.components.status.bar.ports.status.popover.rows.480d8f2347", "Copied {{value0}}", { value0: address }))
+ toast.success(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.480d8f2347',
+ 'Copied {{value0}}',
+ { value0: address }
+ )
+ )
},
[port, recordFeatureInteraction]
)
@@ -139,16 +151,28 @@ export function PortRow({
toast.error(result.reason)
return
}
- toast.success(translate("auto.components.status.bar.ports.status.popover.rows.acdb6df590", "Stopped process on {{value0}}", { value0: port.port }))
+ toast.success(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.acdb6df590',
+ 'Stopped process on {{value0}}',
+ { value0: port.port }
+ )
+ )
const refreshResult = await refreshWorkspacePortScanAfterStop({
runtimeTarget,
setWorkspacePortScan,
setWorkspacePortScanRefreshing
})
if (!refreshResult.ok) {
- toast.error(translate("auto.components.status.bar.ports.status.popover.rows.e4a709548c", "Failed to refresh ports"), {
- description: refreshResult.reason
- })
+ toast.error(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.e4a709548c',
+ 'Failed to refresh ports'
+ ),
+ {
+ description: refreshResult.reason
+ }
+ )
}
}
void run()
@@ -180,13 +204,34 @@ export function PortRow({
@@ -211,7 +256,12 @@ export function WorkspaceGroupRows({
event.stopPropagation()
const ownerPort = group.ports[0]
if (!ownerPort || !goToWorkspacePortOwner(ownerPort)) {
- toast.error(translate("auto.components.status.bar.ports.status.popover.rows.f2b813345f", "Workspace unavailable"))
+ toast.error(
+ translate(
+ 'auto.components.status.bar.ports.status.popover.rows.f2b813345f',
+ 'Workspace unavailable'
+ )
+ )
}
},
[group.ports]
@@ -225,7 +275,10 @@ export function WorkspaceGroupRows({
diff --git a/src/renderer/src/components/status-bar/tooltip.tsx b/src/renderer/src/components/status-bar/tooltip.tsx
index d9bc5baa49f..6e720f88ce4 100644
--- a/src/renderer/src/components/status-bar/tooltip.tsx
+++ b/src/renderer/src/components/status-bar/tooltip.tsx
@@ -79,7 +79,12 @@ function ErrorMessage({
return (
- {stale ? translate("auto.components.status.bar.tooltip.a9a318b7a3", "Refresh failed — showing cached data") : translate("auto.components.status.bar.tooltip.7567cd1c6b", "Usage unavailable")}
+ {stale
+ ? translate(
+ 'auto.components.status.bar.tooltip.a9a318b7a3',
+ 'Refresh failed — showing cached data'
+ )
+ : translate('auto.components.status.bar.tooltip.7567cd1c6b', 'Usage unavailable')}
{message}
@@ -95,14 +100,29 @@ export function getWindowSections(
): { label: string; window: RateLimitWindow | null }[] {
if (p.buckets?.length) {
const bucketSections = p.buckets.map((b) => ({ label: b.name, window: b as RateLimitWindow }))
- return [...bucketSections, { label: translate("auto.components.status.bar.tooltip.252c096536", "Weekly"), window: p.weekly }]
+ return [
+ ...bucketSections,
+ {
+ label: translate('auto.components.status.bar.tooltip.252c096536', 'Weekly'),
+ window: p.weekly
+ }
+ ]
}
const sections: { label: string; window: RateLimitWindow | null }[] = [
- { label: translate("auto.components.status.bar.tooltip.94038ad2fa", "Session"), window: p.session },
- { label: translate("auto.components.status.bar.tooltip.252c096536", "Weekly"), window: p.weekly }
+ {
+ label: translate('auto.components.status.bar.tooltip.94038ad2fa', 'Session'),
+ window: p.session
+ },
+ {
+ label: translate('auto.components.status.bar.tooltip.252c096536', 'Weekly'),
+ window: p.weekly
+ }
]
if (p.monthly !== undefined && p.monthly !== null) {
- sections.push({ label: translate("auto.components.status.bar.tooltip.7f7f208060", "Monthly"), window: p.monthly })
+ sections.push({
+ label: translate('auto.components.status.bar.tooltip.7f7f208060', 'Monthly'),
+ window: p.monthly
+ })
}
return sections
}
@@ -144,7 +164,11 @@ export function ProviderPanel({
const emptyBarClass = inverted ? 'bg-background/20' : 'bg-muted'
if (!p) {
- return {translate("auto.components.status.bar.tooltip.6d6df77f41", "No data available")}
+ return (
+
+ {translate('auto.components.status.bar.tooltip.6d6df77f41', 'No data available')}
+
+ )
}
const name =
@@ -167,7 +191,9 @@ export function ProviderPanel({
{name}
-
{p.error ?? translate("auto.components.status.bar.tooltip.1292d4f2ee", "Unavailable")}
+
+ {p.error ?? translate('auto.components.status.bar.tooltip.1292d4f2ee', 'Unavailable')}
+
)
}
@@ -180,7 +206,13 @@ export function ProviderPanel({
{name}
-
+
)
@@ -211,7 +243,10 @@ export function ProviderPanel({
/>
- {leftPct}{translate("auto.components.status.bar.tooltip.cedb7b99e3", "% left")}
+
+ {leftPct}
+ {translate('auto.components.status.bar.tooltip.cedb7b99e3', '% left')}
+
{resetLabel && {resetLabel} }
diff --git a/src/renderer/src/components/tab-bar/BrowserTab.tsx b/src/renderer/src/components/tab-bar/BrowserTab.tsx
index 30e470aee22..cbf2aceabea 100644
--- a/src/renderer/src/components/tab-bar/BrowserTab.tsx
+++ b/src/renderer/src/components/tab-bar/BrowserTab.tsx
@@ -275,20 +275,25 @@ export default function BrowserTab({
>
onSplitGroup('up', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.96354ed249", "Split Up")}
+ {translate('auto.components.tab.bar.BrowserTab.96354ed249', 'Split Up')}
+
onSplitGroup('down', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.2186a8407c", "Split Down")}
+ {translate('auto.components.tab.bar.BrowserTab.2186a8407c', 'Split Down')}
+
onSplitGroup('left', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.7e8106899f", "Split Left")}
+ {translate('auto.components.tab.bar.BrowserTab.7e8106899f', 'Split Left')}
+
onSplitGroup('right', tab.id)}>
- {translate("auto.components.tab.bar.BrowserTab.966feb9ad5", "Split Right")}
+ {translate('auto.components.tab.bar.BrowserTab.966feb9ad5', 'Split Right')}
+
- {translate("auto.components.tab.bar.BrowserTab.5d6e89891f", "Duplicate Tab")}
+ {translate('auto.components.tab.bar.BrowserTab.5d6e89891f', 'Duplicate Tab')}
+
{isPinned ? (
@@ -296,19 +301,24 @@ export default function BrowserTab({
) : (
)}
- {isPinned ? translate("auto.components.tab.bar.BrowserTab.c5aaee8c39", "Unpin Tab") : translate("auto.components.tab.bar.BrowserTab.911542656f", "Pin Tab")}
+ {isPinned
+ ? translate('auto.components.tab.bar.BrowserTab.c5aaee8c39', 'Unpin Tab')
+ : translate('auto.components.tab.bar.BrowserTab.911542656f', 'Pin Tab')}
!isPinned && onClose()} disabled={isPinned}>
- {translate("auto.components.tab.bar.BrowserTab.1611a1324b", "Close")}
+ {translate('auto.components.tab.bar.BrowserTab.1611a1324b', 'Close')}
+
- {translate("auto.components.tab.bar.BrowserTab.9dd880bd56", "Close Tabs To The Right")}
+ {translate('auto.components.tab.bar.BrowserTab.9dd880bd56', 'Close Tabs To The Right')}
+
void window.api.shell.openUrl(openInBrowserUrl)}
disabled={!isHttpUrl}
>
- {translate("auto.components.tab.bar.BrowserTab.6e0bc8f3a8", "Open In Browser")}
+ {translate('auto.components.tab.bar.BrowserTab.6e0bc8f3a8', 'Open In Browser')}
+
>
diff --git a/src/renderer/src/components/tab-bar/EditorFileTab.tsx b/src/renderer/src/components/tab-bar/EditorFileTab.tsx
index 5fa53c041cb..bbc737ec9ef 100644
--- a/src/renderer/src/components/tab-bar/EditorFileTab.tsx
+++ b/src/renderer/src/components/tab-bar/EditorFileTab.tsx
@@ -258,7 +258,11 @@ export default function EditorFileTab({
onSplitGroup('up', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.6b3efb106e", "Split Up")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.6b3efb106e', 'Split Up')}
+
onSplitGroup('down', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.1d04b1630b", "Split Down")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.1d04b1630b', 'Split Down')}
+
onSplitGroup('left', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.e3ff145b98", "Split Left")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.e3ff145b98', 'Split Left')}
+
onSplitGroup('right', sourceVisibleTabId)}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.f7c3d7d5af", "Split Right")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.f7c3d7d5af', 'Split Right')}
+
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.68cc610e7f", "Rename")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.68cc610e7f', 'Rename')}
+
{isPinned ? : }
- {isPinned ? translate("auto.components.tab.bar.EditorFileTabContextMenu.8e9d603a09", "Unpin Tab") : translate("auto.components.tab.bar.EditorFileTabContextMenu.fdd29eb669", "Pin Tab")}
+ {isPinned
+ ? translate('auto.components.tab.bar.EditorFileTabContextMenu.8e9d603a09', 'Unpin Tab')
+ : translate('auto.components.tab.bar.EditorFileTabContextMenu.fdd29eb669', 'Pin Tab')}
!isPinned && onClose()} disabled={isPinned}>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.1ba8492c5b", "Close")}
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.ba1369dd24", "Close All Editor Tabs")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.1ba8492c5b', 'Close')}
+
+
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.ba1369dd24',
+ 'Close All Editor Tabs'
+ )}
+
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.e5ff31ccaf", "Close Tabs To The Right")}
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.e5ff31ccaf',
+ 'Close Tabs To The Right'
+ )}
+
{canShowMarkdownPreview ? (
<>
@@ -152,7 +169,11 @@ export function EditorFileTabContextMenu({
)
}}
>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.bfd5797ef4", "Open Markdown Preview")}
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.bfd5797ef4',
+ 'Open Markdown Preview'
+ )}
+
>
) : null}
@@ -162,14 +183,19 @@ export function EditorFileTabContextMenu({
}}
>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.5b85754786", "Copy Path")}
+ {translate('auto.components.tab.bar.EditorFileTabContextMenu.5b85754786', 'Copy Path')}
+
{
void window.api.ui.writeClipboardText(file.relativePath)
}}
>
- {translate("auto.components.tab.bar.EditorFileTabContextMenu.52ce4f4605", "Copy Relative Path")}
+ {translate(
+ 'auto.components.tab.bar.EditorFileTabContextMenu.52ce4f4605',
+ 'Copy Relative Path'
+ )}
+
{
diff --git a/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx b/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx
index 2e2f37a9f93..85e47fe9fe2 100644
--- a/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx
+++ b/src/renderer/src/components/tab-bar/RecentTabSwitcher.tsx
@@ -147,10 +147,14 @@ export default function RecentTabSwitcher(): React.JSX.Element | null {
- {translate("auto.components.tab.bar.RecentTabSwitcher.329638ff6f", "Switch Tab")}
+ {translate('auto.components.tab.bar.RecentTabSwitcher.329638ff6f', 'Switch Tab')}
+
{switcher.items.map((item, index) => {
const selected = index === switcher.selectedIndex
diff --git a/src/renderer/src/components/tab-bar/SortableTab.tsx b/src/renderer/src/components/tab-bar/SortableTab.tsx
index c7c60ff95a6..94e4c9b5203 100644
--- a/src/renderer/src/components/tab-bar/SortableTab.tsx
+++ b/src/renderer/src/components/tab-bar/SortableTab.tsx
@@ -309,7 +309,11 @@ export default function SortableTab({
ref={setRenameInputElement}
data-tab-rename-input="true"
value={renameValue}
- aria-label={translate("auto.components.tab.bar.SortableTab.ab19f603eb", "Rename tab {{value0}}", { value0: tabTitle })}
+ aria-label={translate(
+ 'auto.components.tab.bar.SortableTab.ab19f603eb',
+ 'Rename tab {{value0}}',
+ { value0: tabTitle }
+ )}
onChange={(event) => setRenameValue(event.target.value)}
onBlur={commitRename}
onKeyDown={(event) => {
@@ -379,8 +383,8 @@ export default function SortableTab({
e.stopPropagation()
onToggleExpand(tab.id)
}}
- title={translate("auto.components.tab.bar.SortableTab.fdb2691425", "Collapse pane")}
- aria-label={translate("auto.components.tab.bar.SortableTab.fdb2691425", "Collapse pane")}
+ title={translate('auto.components.tab.bar.SortableTab.fdb2691425', 'Collapse pane')}
+ aria-label={translate('auto.components.tab.bar.SortableTab.fdb2691425', 'Collapse pane')}
>
@@ -397,7 +401,11 @@ export default function SortableTab({
// instead of bypassing the render layer by calling closeTab() on
// the store — a store-only assertion would pass even if this
// button had been accidentally unmounted.
- aria-label={translate("auto.components.tab.bar.SortableTab.6df69d9388", "Close tab {{value0}}", { value0: tabTitle })}
+ aria-label={translate(
+ 'auto.components.tab.bar.SortableTab.6df69d9388',
+ 'Close tab {{value0}}',
+ { value0: tabTitle }
+ )}
type="button"
data-tab-close-button="true"
onPointerDown={(e) => {
diff --git a/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx b/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx
index f17e028a667..9aca62ba847 100644
--- a/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx
+++ b/src/renderer/src/components/tab-bar/SortableTabContextMenu.tsx
@@ -10,16 +10,46 @@ import type { TerminalTab } from '../../../../shared/types'
import { translate } from '@/i18n/i18n'
const TAB_COLORS = [
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.20baa43c05", "None"), value: null },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.cb3eadefd2", "Blue"), value: '#3b82f6' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.c2d8b0991f", "Purple"), value: '#a855f7' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.03cf6dab1a", "Pink"), value: '#ec4899' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.620aec6729", "Red"), value: '#ef4444' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.a47629b3cf", "Orange"), value: '#f97316' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.69682e2ce4", "Yellow"), value: '#eab308' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.be905e9b0a", "Green"), value: '#22c55e' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.845576bed1", "Teal"), value: '#14b8a6' },
- { label: translate("auto.components.tab.bar.SortableTabContextMenu.7703990447", "Gray"), value: '#9ca3af' }
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.20baa43c05', 'None'),
+ value: null
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.cb3eadefd2', 'Blue'),
+ value: '#3b82f6'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.c2d8b0991f', 'Purple'),
+ value: '#a855f7'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.03cf6dab1a', 'Pink'),
+ value: '#ec4899'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.620aec6729', 'Red'),
+ value: '#ef4444'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.a47629b3cf', 'Orange'),
+ value: '#f97316'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.69682e2ce4', 'Yellow'),
+ value: '#eab308'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.be905e9b0a', 'Green'),
+ value: '#22c55e'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.845576bed1', 'Teal'),
+ value: '#14b8a6'
+ },
+ {
+ label: translate('auto.components.tab.bar.SortableTabContextMenu.7703990447', 'Gray'),
+ value: '#9ca3af'
+ }
] as const
type SortableTabContextMenuProps = {
@@ -68,32 +98,48 @@ export function SortableTabContextMenu({
onSplitGroup('up', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.591f9b12c1", "Split Up")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.591f9b12c1', 'Split Up')}
+
onSplitGroup('down', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.af80ed83c1", "Split Down")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.af80ed83c1', 'Split Down')}
+
onSplitGroup('left', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.0ce4bae39d", "Split Left")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.0ce4bae39d', 'Split Left')}
+
onSplitGroup('right', tab.id)}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.21132389e9", "Split Right")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.21132389e9', 'Split Right')}
+
{isPinned ? : }
- {isPinned ? translate("auto.components.tab.bar.SortableTabContextMenu.417722e9c2", "Unpin Tab") : translate("auto.components.tab.bar.SortableTabContextMenu.60f958ec75", "Pin Tab")}
+ {isPinned
+ ? translate('auto.components.tab.bar.SortableTabContextMenu.417722e9c2', 'Unpin Tab')
+ : translate('auto.components.tab.bar.SortableTabContextMenu.60f958ec75', 'Pin Tab')}
!isPinned && onClose(tab.id)} disabled={isPinned}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.89359a36f7", "Close")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.89359a36f7', 'Close')}
+
onCloseOthers(tab.id)} disabled={tabCount <= 1}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.8d16f9cd30", "Close Others")}
+ {translate('auto.components.tab.bar.SortableTabContextMenu.8d16f9cd30', 'Close Others')}
+
onCloseToRight(tab.id)} disabled={!hasTabsToRight}>
- {translate("auto.components.tab.bar.SortableTabContextMenu.c1ee099c7e", "Close Tabs To The Right")}
+ {translate(
+ 'auto.components.tab.bar.SortableTabContextMenu.c1ee099c7e',
+ 'Close Tabs To The Right'
+ )}
+
- {translate("auto.components.tab.bar.SortableTabContextMenu.2f697b3c31", "Change Title")}
+
+ {translate('auto.components.tab.bar.SortableTabContextMenu.2f697b3c31', 'Change Title')}
+
-
{translate("auto.components.tab.bar.SortableTabContextMenu.35e8892fd0", "Tab Color")}
+
+ {translate('auto.components.tab.bar.SortableTabContextMenu.35e8892fd0', 'Tab Color')}
+
{TAB_COLORS.map((color) => {
const isSelected = tab.color === color.value
diff --git a/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx b/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx
index 3826299e35e..173170a4330 100644
--- a/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx
+++ b/src/renderer/src/components/tab-bar/TabBarQuickCommandsButton.tsx
@@ -125,9 +125,19 @@ export function TabBarQuickCommandsButton({
const handleDeleteCommand = async (command: TerminalQuickCommand): Promise
=> {
setMenuOpen(false)
const confirmed = await confirm({
- title: translate("auto.components.tab.bar.TabBarQuickCommandsButton.e8e1a52edb", "Delete \"{{value0}}\"?", { value0: command.label }),
- description: translate("auto.components.tab.bar.TabBarQuickCommandsButton.3220e2da27", "This quick command will be removed from your saved list."),
- confirmLabel: translate("auto.components.tab.bar.TabBarQuickCommandsButton.be8f0ff166", "Delete"),
+ title: translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.e8e1a52edb',
+ 'Delete "{{value0}}"?',
+ { value0: command.label }
+ ),
+ description: translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.3220e2da27',
+ 'This quick command will be removed from your saved list.'
+ ),
+ confirmLabel: translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.be8f0ff166',
+ 'Delete'
+ ),
confirmVariant: 'destructive'
})
if (!confirmed) {
@@ -160,14 +170,26 @@ export function TabBarQuickCommandsButton({
})
}
className="my-auto flex h-7 shrink-0 items-center gap-1 rounded-md px-1.5 text-muted-foreground hover:bg-accent/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
- aria-label={translate("auto.components.tab.bar.TabBarQuickCommandsButton.8f1e971966", "Add quick command")}
+ aria-label={translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.8f1e971966',
+ 'Add quick command'
+ )}
>
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831", "Add command")}
+
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831',
+ 'Add command'
+ )}
+
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.1d411fb6a5", "Save a quick command for this repo")}
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.1d411fb6a5',
+ 'Save a quick command for this repo'
+ )}
+
@@ -232,7 +258,11 @@ export function TabBarQuickCommandsButton({
void handleDeleteCommand(command)
}}
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-destructive"
- aria-label={translate("auto.components.tab.bar.TabBarQuickCommandsButton.196593b6a9", "Remove {{value0}}", { value0: command.label })}
+ aria-label={translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.196593b6a9',
+ 'Remove {{value0}}',
+ { value0: command.label }
+ )}
>
@@ -251,21 +281,45 @@ export function TabBarQuickCommandsButton({
disabled={!mostRecent}
className={cn(innerButtonBase, 'gap-1.5 rounded-l-md rounded-r-none px-1.5')}
aria-label={
- mostRecent ? translate("auto.components.tab.bar.TabBarQuickCommandsButton.b775303755", "Run quick command: {{value0}}", { value0: mostRecent.label }) : translate("auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc", "Run quick command")
+ mostRecent
+ ? translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.b775303755',
+ 'Run quick command: {{value0}}',
+ { value0: mostRecent.label }
+ )
+ : translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc',
+ 'Run quick command'
+ )
}
>
- {mostRecent?.label ?? translate("auto.components.tab.bar.TabBarQuickCommandsButton.7b1c9d6ae1", "Run")}
+ {mostRecent?.label ??
+ translate('auto.components.tab.bar.TabBarQuickCommandsButton.7b1c9d6ae1', 'Run')}
{mostRecent
? isTerminalAgentQuickCommand(mostRecent)
- ? translate("auto.components.tab.bar.TabBarQuickCommandsButton.77ac113df0", "Start {{value0}}: {{value1}}", { value0: getAgentLabel(mostRecent.agent), value1: getTerminalQuickCommandBody(mostRecent) })
- : translate("auto.components.tab.bar.TabBarQuickCommandsButton.37e1bb90ce", "Run: {{value0}}", { value0: getTerminalQuickCommandBody(mostRecent) })
- : translate("auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc", "Run quick command")}
+ ? translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.77ac113df0',
+ 'Start {{value0}}: {{value1}}',
+ {
+ value0: getAgentLabel(mostRecent.agent),
+ value1: getTerminalQuickCommandBody(mostRecent)
+ }
+ )
+ : translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.37e1bb90ce',
+ 'Run: {{value0}}',
+ { value0: getTerminalQuickCommandBody(mostRecent) }
+ )
+ : translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.85482c57bc',
+ 'Run quick command'
+ )}
@@ -276,7 +330,10 @@ export function TabBarQuickCommandsButton({
innerButtonBase,
'justify-center rounded-l-none rounded-r-md border-l border-border/60 px-1'
)}
- aria-label={translate("auto.components.tab.bar.TabBarQuickCommandsButton.b82e237a4b", "More quick commands")}
+ aria-label={translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.b82e237a4b',
+ 'More quick commands'
+ )}
>
@@ -290,7 +347,12 @@ export function TabBarQuickCommandsButton({
>
{totalVisible === 0 ? (
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.20bbd75896", "No commands")}
+
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.20bbd75896',
+ 'No commands'
+ )}
+
) : null}
{repoCommands.map(renderItem)}
{repoCommands.length > 0 && globalCommands.length > 0 ? (
@@ -311,7 +373,11 @@ export function TabBarQuickCommandsButton({
className="flex w-full items-center gap-2 rounded-[5px] px-2 py-1.5 text-[12px] text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
- {translate("auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831", "Add command")}
+ {translate(
+ 'auto.components.tab.bar.TabBarQuickCommandsButton.a2c7a33831',
+ 'Add command'
+ )}
+
diff --git a/src/renderer/src/components/tab-bar/shell-icons.tsx b/src/renderer/src/components/tab-bar/shell-icons.tsx
index ab1469735b3..03930a5dfbe 100644
--- a/src/renderer/src/components/tab-bar/shell-icons.tsx
+++ b/src/renderer/src/components/tab-bar/shell-icons.tsx
@@ -73,7 +73,8 @@ function WslIcon({ size = 14 }: { size?: number }): React.JSX.Element {
fill="#1F1F1F"
fontFamily="system-ui, -apple-system, sans-serif"
>
- {translate("auto.components.tab.bar.shell.icons.e9b2e70613", "WSL")}
+ {translate('auto.components.tab.bar.shell.icons.e9b2e70613', 'WSL')}
+
)
}
@@ -97,7 +98,8 @@ function GitBashIcon({ size = 14 }: { size?: number }): React.JSX.Element {
fill="#ffffff"
fontFamily="system-ui, -apple-system, sans-serif"
>
- {translate("auto.components.tab.bar.shell.icons.d4ceaa227c", "Git")}
+ {translate('auto.components.tab.bar.shell.icons.d4ceaa227c', 'Git')}
+
)
}
diff --git a/src/renderer/src/components/tab-group/TabGroupPanel.tsx b/src/renderer/src/components/tab-group/TabGroupPanel.tsx
index bf54396e474..6b00012a20d 100644
--- a/src/renderer/src/components/tab-group/TabGroupPanel.tsx
+++ b/src/renderer/src/components/tab-group/TabGroupPanel.tsx
@@ -272,8 +272,14 @@ export default function TabGroupPanel({
{
event.stopPropagation()
}}
@@ -289,28 +295,32 @@ export default function TabGroupPanel({
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.ab1e2bff04", "Split Right")}
+ {translate('auto.components.tab.group.TabGroupPanel.ab1e2bff04', 'Split Right')}
+
{
commands.createSplitGroup('down')
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.4df2a06d36", "Split Down")}
+ {translate('auto.components.tab.group.TabGroupPanel.4df2a06d36', 'Split Down')}
+
{
commands.createSplitGroup('left')
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.30137df7d0", "Split Left")}
+ {translate('auto.components.tab.group.TabGroupPanel.30137df7d0', 'Split Left')}
+
{
commands.createSplitGroup('up')
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.0db2081805", "Split Up")}
+ {translate('auto.components.tab.group.TabGroupPanel.0db2081805', 'Split Up')}
+
{hasSplitGroups ? (
<>
@@ -321,7 +331,11 @@ export default function TabGroupPanel({
}}
>
- {translate("auto.components.tab.group.TabGroupPanel.f7d6ce445e", "Close Group")}
+ {translate(
+ 'auto.components.tab.group.TabGroupPanel.f7d6ce445e',
+ 'Close Group'
+ )}
+
>
) : null}
@@ -366,16 +380,20 @@ export default function TabGroupPanel({
) : null}
{activeDropZone ? : null}
{activeTab &&
- activeTab.contentType !== "terminal" &&
- activeTab.contentType !== "browser" &&
- activeTab.contentType !== "simulator" && (
+ activeTab.contentType !== 'terminal' &&
+ activeTab.contentType !== 'browser' &&
+ activeTab.contentType !== 'simulator' && (
{/* Why: split groups render editor content inside a plain relative pane body
instead of the legacy flex column in Terminal.tsx. */}
- {translate("auto.components.tab.group.TabGroupPanel.814fb04c43", "Loading editor...")}
+ {translate(
+ 'auto.components.tab.group.TabGroupPanel.814fb04c43',
+ 'Loading editor...'
+ )}
+
}
>
diff --git a/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx b/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx
index 966245639a7..9ca464e8b60 100644
--- a/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx
+++ b/src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx
@@ -29,15 +29,26 @@ export default function CloseTerminalDialog({
>
- {translate("auto.components.terminal.pane.CloseTerminalDialog.78b79d854d", "Close Terminal?")}
+
+ {translate(
+ 'auto.components.terminal.pane.CloseTerminalDialog.78b79d854d',
+ 'Close Terminal?'
+ )}
+
- {translate("auto.components.terminal.pane.CloseTerminalDialog.6b9a6975f8", "The terminal still has a running process. If you close the terminal, the process will be killed.")}
+ {translate(
+ 'auto.components.terminal.pane.CloseTerminalDialog.6b9a6975f8',
+ 'The terminal still has a running process. If you close the terminal, the process will be killed.'
+ )}
+
- {translate("auto.components.terminal.pane.CloseTerminalDialog.1d1a7a9c1f", "Cancel")}
+ {translate('auto.components.terminal.pane.CloseTerminalDialog.1d1a7a9c1f', 'Cancel')}
+
- {translate("auto.components.terminal.pane.CloseTerminalDialog.ebd2fa844d", "Close")}
+ {translate('auto.components.terminal.pane.CloseTerminalDialog.ebd2fa844d', 'Close')}
+
diff --git a/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx b/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx
index 2953674b7c8..80e950dd863 100644
--- a/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx
+++ b/src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx
@@ -74,7 +74,10 @@ export function MobileDriverOverlay({
return (
{onCollapse && (
- {translate("auto.components.terminal.pane.MobileDriverOverlay.7cffad954c", "Collapse")}
+ {translate(
+ 'auto.components.terminal.pane.MobileDriverOverlay.7cffad954c',
+ 'Collapse'
+ )}
+
)}
{/* Focus is moved to this button only when no user input is active; see effect above. */}
- {translate("auto.components.terminal.pane.MobileDriverOverlay.c44659e09f", "Mobile driving")}
+ {translate(
+ 'auto.components.terminal.pane.MobileDriverOverlay.c44659e09f',
+ 'Mobile driving'
+ )}
+
- {translate("auto.components.terminal.pane.MobileDriverOverlay.c6460cf584", "Take back")}
+ {translate('auto.components.terminal.pane.MobileDriverOverlay.c6460cf584', 'Take back')}
+
)
}
diff --git a/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx b/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx
index e9afa311134..84148129289 100644
--- a/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalAgentSessionForkDialog.tsx
@@ -73,27 +73,57 @@ export function TerminalAgentSessionForkDialog({
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.64e292e8e3", "Fork Agent Session")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.64e292e8e3',
+ 'Fork Agent Session'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.619b5a35d2", "Create a top-level workspace fork and start a fresh agent tab with captured context.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.619b5a35d2',
+ 'Create a top-level workspace fork and start a fresh agent tab with captured context.'
+ )}
+
-
{translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.620461df22", "Top-level fork")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.620461df22',
+ 'Top-level fork'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.0c8a8629b1", "The fork appears as its own workspace, not as a nested child. The new agent receives a bounded transcript as an editable draft.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.0c8a8629b1',
+ 'The fork appears as its own workspace, not as a nested child. The new agent receives a bounded transcript as an editable draft.'
+ )}
+
void handleCopyContext()}>
- {translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.17fc841e59", "Copy context")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.17fc841e59',
+ 'Copy context'
+ )}
+
void handleStartFork()}>
- {busy ? translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.2b10412cfc", "Creating...") : translate("auto.components.terminal.pane.TerminalAgentSessionForkDialog.9d25de2920", "Create fork")}
+ {busy
+ ? translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.2b10412cfc',
+ 'Creating...'
+ )
+ : translate(
+ 'auto.components.terminal.pane.TerminalAgentSessionForkDialog.9d25de2920',
+ 'Create fork'
+ )}
diff --git a/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx b/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx
index d421204c40a..9912a7bc0f6 100644
--- a/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalContextMenu.tsx
@@ -118,7 +118,9 @@ export default function TerminalContextMenu({
)}
{command.label}
{!isTerminalAgentQuickCommand(command) && !command.appendEnter ? (
- {translate("auto.components.terminal.pane.TerminalContextMenu.c2f0b72b8d", "Insert")}
+
+ {translate('auto.components.terminal.pane.TerminalContextMenu.c2f0b72b8d', 'Insert')}
+
) : null}
)
@@ -169,16 +171,22 @@ export default function TerminalContextMenu({
>
- {translate("auto.components.terminal.pane.TerminalContextMenu.f3eeb1de13", "Copy")}{shortcuts.copy}
+ {translate('auto.components.terminal.pane.TerminalContextMenu.f3eeb1de13', 'Copy')}
+ {shortcuts.copy}
- {translate("auto.components.terminal.pane.TerminalContextMenu.0a917b591a", "Paste")}{shortcuts.paste}
+ {translate('auto.components.terminal.pane.TerminalContextMenu.0a917b591a', 'Paste')}
+ {shortcuts.paste}
- {translate("auto.components.terminal.pane.TerminalContextMenu.ec85df5914", "Quick Commands")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.ec85df5914',
+ 'Quick Commands'
+ )}
+
{hasQuickCommands ? (
<>
@@ -194,7 +202,12 @@ export default function TerminalContextMenu({
<>
{repoQuickCommands.length > 0 ? : null}
{repoQuickCommands.length > 0 ? (
- {translate("auto.components.terminal.pane.TerminalContextMenu.3ce594a4a0", "Global")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.3ce594a4a0',
+ 'Global'
+ )}
+
) : null}
{globalQuickCommands.map(renderQuickCommandItem)}
>
@@ -202,7 +215,11 @@ export default function TerminalContextMenu({
>
) : (
- {translate("auto.components.terminal.pane.TerminalContextMenu.9528a65ef8", "No quick commands")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.9528a65ef8',
+ 'No quick commands'
+ )}
+
)}
- {translate("auto.components.terminal.pane.TerminalContextMenu.0a82b0608c", "Add Quick Command…")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.0a82b0608c',
+ 'Add Quick Command…'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalContextMenu.8a7ddb8b8a", "Fork Agent Session…")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.8a7ddb8b8a',
+ 'Fork Agent Session…'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalContextMenu.20e565d865", "Split Terminal Right")}{shortcuts.splitRight}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.20e565d865',
+ 'Split Terminal Right'
+ )}
+ {shortcuts.splitRight}
- {translate("auto.components.terminal.pane.TerminalContextMenu.98bccf4fa2", "Split Terminal Down")}{shortcuts.splitDown}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.98bccf4fa2',
+ 'Split Terminal Down'
+ )}
+ {shortcuts.splitDown}
{canEqualizePaneSizes && (
- {translate("auto.components.terminal.pane.TerminalContextMenu.06c2b0f043", "Equalize Pane Sizes")}{showEqualizeShortcut ? (
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.06c2b0f043',
+ 'Equalize Pane Sizes'
+ )}
+ {showEqualizeShortcut ? (
{shortcuts.equalize}
) : null}
@@ -240,30 +277,51 @@ export default function TerminalContextMenu({
{canExpandPane && (
{menuPaneIsExpanded ? : }
- {menuPaneIsExpanded ? translate("auto.components.terminal.pane.TerminalContextMenu.df766809e0", "Collapse Pane") : translate("auto.components.terminal.pane.TerminalContextMenu.925f49f210", "Expand Pane")}
+ {menuPaneIsExpanded
+ ? translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.df766809e0',
+ 'Collapse Pane'
+ )
+ : translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.925f49f210',
+ 'Expand Pane'
+ )}
{shortcuts.expand}
)}
- {translate("auto.components.terminal.pane.TerminalContextMenu.39809d152f", "Set Title…")}
+ {translate('auto.components.terminal.pane.TerminalContextMenu.39809d152f', 'Set Title…')}
+
- {translate("auto.components.terminal.pane.TerminalContextMenu.2cf85a6a55", "Copy Pane ID")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.2cf85a6a55',
+ 'Copy Pane ID'
+ )}
+
{canClosePane && (
<>
- {translate("auto.components.terminal.pane.TerminalContextMenu.8c17d6786d", "Close Pane")}{shortcuts.close}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.8c17d6786d',
+ 'Close Pane'
+ )}
+ {shortcuts.close}
>
)}
- {translate("auto.components.terminal.pane.TerminalContextMenu.b4cdd9314e", "Clear Screen")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalContextMenu.b4cdd9314e',
+ 'Clear Screen'
+ )}
+
)
diff --git a/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx b/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx
index 7e1f6f226cf..a71cd881624 100644
--- a/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalErrorToast.tsx
@@ -56,16 +56,27 @@ export function TerminalErrorToast({
{showDaemonRestart ? (
<>
{'\n'}
- {translate("auto.components.terminal.pane.TerminalErrorToast.cc6d997c65", "Restart the terminal daemon from here to clear stale daemon state.")}>
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.cc6d997c65',
+ 'Restart the terminal daemon from here to clear stale daemon state.'
+ )}
+ >
) : !ssh ? (
<>
{'\n'}
- {translate("auto.components.terminal.pane.TerminalErrorToast.5c8ce20be6", "If this persists, please")}{' '}
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.5c8ce20be6',
+ 'If this persists, please'
+ )}{' '}
- {translate("auto.components.terminal.pane.TerminalErrorToast.a7e2fd2699", "file an issue")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.a7e2fd2699',
+ 'file an issue'
+ )}
+
.
>
) : null}
@@ -86,7 +97,11 @@ export function TerminalErrorToast({
flexShrink: 0
}}
>
- {translate("auto.components.terminal.pane.TerminalErrorToast.e4aa243f8c", "Restart daemon")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalErrorToast.e4aa243f8c',
+ 'Restart daemon'
+ )}
+
) : null}
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.678c780a2c", "Disk space is unavailable")}
+
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.678c780a2c',
+ 'Disk space is unavailable'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.e2fcf07c0d", "Orca could not save this terminal session because local storage is full or not writable. Open the disk space analyzer to find workspace storage you can clean up.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.e2fcf07c0d',
+ 'Orca could not save this terminal session because local storage is full or not writable. Open the disk space analyzer to find workspace storage you can clean up.'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.38c282a2c4", "The analyzer opens directly from here. You can also open it later from the lower-left toolbox menu by choosing Space Analyzer.")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.38c282a2c4',
+ 'The analyzer opens directly from here. You can also open it later from the lower-left toolbox menu by choosing Space Analyzer.'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.ae20d0ffc2", "Dismiss")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.ae20d0ffc2',
+ 'Dismiss'
+ )}
+
- {translate("auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.6bee0c8f17", "Open Disk Space Analyzer")}
+ {translate(
+ 'auto.components.terminal.pane.TerminalSessionStateSaveFailureDialog.6bee0c8f17',
+ 'Open Disk Space Analyzer'
+ )}
+
diff --git a/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts b/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts
index 8bc70b62211..127f40f7a99 100644
--- a/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts
+++ b/src/renderer/src/components/terminal-pane/osc52-clipboard-blocked-toast.ts
@@ -11,24 +11,35 @@ export function showOsc52ClipboardBlockedToast(): void {
}
hasShownOsc52ClipboardBlockedToast = true
- toast.info(translate("auto.components.terminal.pane.osc52.clipboard.blocked.toast.89eaa3e80b", "Terminal clipboard write blocked"), {
- description:
- translate("auto.components.terminal.pane.osc52.clipboard.blocked.toast.7cf51f74fd", "Enable TUI clipboard writes in Terminal settings to copy from SSH, tmux, Neovim, or fzf."),
- duration: 12_000,
- action: {
- label: translate("auto.components.terminal.pane.osc52.clipboard.blocked.toast.97c98f1afe", "Open Setting"),
- onClick: () => {
- const store = useAppStore.getState()
- // Why: open the exact row instead of a generic Terminal page so the
- // remote-copy failure points to the setting named by the shell message.
- store.setSettingsSearchQuery('')
- store.openSettingsTarget({
- pane: 'terminal',
- repoId: null,
- sectionId: OSC52_CLIPBOARD_SETTING_ID
- })
- store.openSettingsPage()
+ toast.info(
+ translate(
+ 'auto.components.terminal.pane.osc52.clipboard.blocked.toast.89eaa3e80b',
+ 'Terminal clipboard write blocked'
+ ),
+ {
+ description: translate(
+ 'auto.components.terminal.pane.osc52.clipboard.blocked.toast.7cf51f74fd',
+ 'Enable TUI clipboard writes in Terminal settings to copy from SSH, tmux, Neovim, or fzf.'
+ ),
+ duration: 12_000,
+ action: {
+ label: translate(
+ 'auto.components.terminal.pane.osc52.clipboard.blocked.toast.97c98f1afe',
+ 'Open Setting'
+ ),
+ onClick: () => {
+ const store = useAppStore.getState()
+ // Why: open the exact row instead of a generic Terminal page so the
+ // remote-copy failure points to the setting named by the shell message.
+ store.setSettingsSearchQuery('')
+ store.openSettingsTarget({
+ pane: 'terminal',
+ repoId: null,
+ sectionId: OSC52_CLIPBOARD_SETTING_ID
+ })
+ store.openSettingsPage()
+ }
}
}
- })
+ )
}
diff --git a/src/renderer/src/components/terminal-pane/stale-agent-row.ts b/src/renderer/src/components/terminal-pane/stale-agent-row.ts
index acfcd5f5400..c08f176691e 100644
--- a/src/renderer/src/components/terminal-pane/stale-agent-row.ts
+++ b/src/renderer/src/components/terminal-pane/stale-agent-row.ts
@@ -10,9 +10,19 @@ export function dismissStaleAgentRowByKey(paneKey: string): void {
store.dropAgentStatus(paneKey)
store.dismissRetainedAgent(paneKey)
if (liveExisted || retainedExisted) {
- toast.info(translate("auto.components.terminal.pane.stale.agent.row.ad991ece5c", "Agent's pane is no longer available."), {
- id: translate("auto.components.terminal.pane.stale.agent.row.090d607412", "stale-agent-row-{{value0}}", { value0: paneKey })
- })
+ toast.info(
+ translate(
+ 'auto.components.terminal.pane.stale.agent.row.ad991ece5c',
+ "Agent's pane is no longer available."
+ ),
+ {
+ id: translate(
+ 'auto.components.terminal.pane.stale.agent.row.090d607412',
+ 'stale-agent-row-{{value0}}',
+ { value0: paneKey }
+ )
+ }
+ )
}
}
diff --git a/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts b/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
index cc41fc4f6e6..65c9ec93926 100644
--- a/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
+++ b/src/renderer/src/components/terminal-pane/terminal-agent-session-fork.ts
@@ -61,11 +61,23 @@ function getUsableForkBase(
async function copyForkContext(prompt: string, pane: ManagedPane): Promise {
try {
await window.api.ui.writeClipboardText(prompt)
- toast.message(translate("auto.components.terminal.pane.terminal.agent.session.fork.c00421d320", "Fork context copied. Launch an agent and paste it to start the fork."))
+ toast.message(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.c00421d320',
+ 'Fork context copied. Launch an agent and paste it to start the fork.'
+ )
+ )
pane.terminal.focus()
return true
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.terminal.pane.terminal.agent.session.fork.2317900211", "Failed to copy fork context."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.2317900211',
+ 'Failed to copy fork context.'
+ )
+ )
pane.terminal.focus()
return false
}
@@ -123,7 +135,12 @@ export function prepareAgentSessionForkFromPane({
})
if (!prompt) {
- toast.error(translate("auto.components.terminal.pane.terminal.agent.session.fork.046e8d853c", "No terminal context to fork"))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.046e8d853c',
+ 'No terminal context to fork'
+ )
+ )
pane.terminal.focus()
return null
}
@@ -146,13 +163,23 @@ export async function startAgentSessionFork(fork: PreparedAgentSessionFork): Pro
const store = useAppStore.getState()
const sourceWorktree = store.getKnownWorktreeById(fork.worktreeId)
if (!sourceWorktree) {
- toast.error(translate("auto.components.terminal.pane.terminal.agent.session.fork.f867385bb5", "Could not find the source workspace for this fork."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.f867385bb5',
+ 'Could not find the source workspace for this fork.'
+ )
+ )
return false
}
const sourceRepo = store.repos.find((repo) => repo.id === sourceWorktree.repoId)
const sourceBranch = getUsableForkBase(sourceWorktree, sourceRepo, fork.worktreeId)
if (!sourceBranch) {
- toast.error(translate("auto.components.terminal.pane.terminal.agent.session.fork.38e41edc6e", "This workspace cannot be forked into a git worktree."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.38e41edc6e',
+ 'This workspace cannot be forked into a git worktree.'
+ )
+ )
return false
}
const forkName = buildForkWorkspaceName(sourceWorktree.displayName || sourceBranch)
@@ -172,7 +199,14 @@ export async function startAgentSessionFork(fork: PreparedAgentSessionFork): Pro
fork.agent ?? undefined
)
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.components.terminal.pane.terminal.agent.session.fork.fd3d12a1e1", "Failed to create fork workspace."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.fd3d12a1e1',
+ 'Failed to create fork workspace.'
+ )
+ )
return false
}
const forkWorktreeId = created.worktree.id
@@ -204,7 +238,12 @@ export async function startAgentSessionFork(fork: PreparedAgentSessionFork): Pro
return copyAgentSessionForkContext(fork)
}
- toast.success(translate("auto.components.terminal.pane.terminal.agent.session.fork.88e34d00eb", "Top-level session fork opened in a new workspace"))
+ toast.success(
+ translate(
+ 'auto.components.terminal.pane.terminal.agent.session.fork.88e34d00eb',
+ 'Top-level session fork opened in a new workspace'
+ )
+ )
return true
}
diff --git a/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts b/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts
index e86724203cc..966d4e0e9c1 100644
--- a/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts
+++ b/src/renderer/src/components/terminal-pane/terminal-drop-handler.ts
@@ -69,7 +69,12 @@ export async function handleTerminalFileDrop(args: Args): Promise {
const activeRuntimeEnvironmentId = settings?.activeRuntimeEnvironmentId?.trim()
const worktreePath = resolveWorktreePath(worktreeId, cwd)
if (!worktreePath) {
- toast.error(translate("auto.components.terminal.pane.terminal.drop.handler.ce8248b835", "Worktree path not available."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.ce8248b835',
+ 'Worktree path not available.'
+ )
+ )
return
}
@@ -77,7 +82,11 @@ export async function handleTerminalFileDrop(args: Args): Promise {
const targetShell = getTerminalTargetShellForWorktreePath(worktreePath)
const destinationDir = joinRuntimeDropDir(worktreePath)
const pending = toast.loading(
- translate("auto.components.terminal.pane.terminal.drop.handler.29c031b49a", "Uploading {{value0}} file{{value1}} to runtime…", { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' })
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.29c031b49a',
+ 'Uploading {{value0}} file{{value1}} to runtime…',
+ { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' }
+ )
)
try {
const { results } = await importExternalPathsToRuntime(
@@ -117,7 +126,12 @@ export async function handleTerminalFileDrop(args: Args): Promise {
// silently paste local paths into a remote shell.
const connectionId = getConnectionId(worktreeId)
if (connectionId === undefined) {
- toast.error(translate("auto.components.terminal.pane.terminal.drop.handler.0c77693641", "Worktree not ready — try again in a moment."))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.0c77693641',
+ 'Worktree not ready — try again in a moment.'
+ )
+ )
return
}
const isRemote = connectionId !== null
@@ -139,7 +153,11 @@ export async function handleTerminalFileDrop(args: Args): Promise {
}
const pending = toast.loading(
- translate("auto.components.terminal.pane.terminal.drop.handler.29c031b49a", "Uploading {{value0}} file{{value1}} to remote…", { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' })
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.29c031b49a',
+ 'Uploading {{value0}} file{{value1}} to remote…',
+ { value0: data.paths.length, value1: data.paths.length === 1 ? '' : 's' }
+ )
)
try {
const { resolvedPaths, skipped, failed } = await window.api.fs.resolveDroppedPathsForAgent({
@@ -178,13 +196,27 @@ function reportUploadSkipsAndFailures(
const noun = skipped.length === 1 ? 'item' : 'items'
toast.message(
symlinkCount === skipped.length
- ? translate("auto.components.terminal.pane.terminal.drop.handler.53f015fd85", "Skipped {{value0}} symlink{{value1}}.", { value0: skipped.length, value1: skipped.length === 1 ? '' : 's' })
- : translate("auto.components.terminal.pane.terminal.drop.handler.53f015fd85", "Skipped {{value0}} {{value1}}.", { value0: skipped.length, value1: noun })
+ ? translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.53f015fd85',
+ 'Skipped {{value0}} symlink{{value1}}.',
+ { value0: skipped.length, value1: skipped.length === 1 ? '' : 's' }
+ )
+ : translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.53f015fd85',
+ 'Skipped {{value0}} {{value1}}.',
+ { value0: skipped.length, value1: noun }
+ )
)
}
if (failed.length > 0) {
const noun = failed.length === 1 ? 'file' : 'files'
- toast.error(translate("auto.components.terminal.pane.terminal.drop.handler.1e072f611e", "Failed to upload {{value0}} {{value1}}.", { value0: failed.length, value1: noun }))
+ toast.error(
+ translate(
+ 'auto.components.terminal.pane.terminal.drop.handler.1e072f611e',
+ 'Failed to upload {{value0}} {{value1}}.',
+ { value0: failed.length, value1: noun }
+ )
+ )
}
}
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx
index 0cdd2a78dc1..85a008cd5f7 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandActionToggle.tsx
@@ -25,9 +25,17 @@ export function TerminalQuickCommandActionToggle({
variant="outline"
>
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b5ea4d64f6", "Terminal Command")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b5ea4d64f6',
+ 'Terminal Command'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b0d58e37ed", "Agent Prompt")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandActionToggle.b0d58e37ed',
+ 'Agent Prompt'
+ )}
+
)
}
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx
index 437948b7e69..ad45db4b08d 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandAppendEnterSwitch.tsx
@@ -11,15 +11,27 @@ export function TerminalQuickCommandAppendEnterSwitch({
return (
-
{translate("auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.5fa607d807", "Append Enter")}
+
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.5fa607d807',
+ 'Append Enter'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.c936c2d6d2", "Submit immediately instead of only inserting text.")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.c936c2d6d2',
+ 'Submit immediately instead of only inserting text.'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.28370f16b9", "Cancel")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.28370f16b9',
+ 'Cancel'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.2e2b958dfc", "Save")}{submitShortcutLabel}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandDialogFooter.2e2b958dfc',
+ 'Save'
+ )}
+ {submitShortcutLabel}
)
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx
index e45d7bebeba..a337be4361e 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandLabelField.tsx
@@ -15,11 +15,19 @@ export function TerminalQuickCommandLabelField({
}: TerminalQuickCommandLabelFieldProps): React.JSX.Element {
return (
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.db17f1e41e", "Label")}
+
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.db17f1e41e',
+ 'Label'
+ )}
+
setDraft((current) => ({ ...current, label: event.target.value }))}
- placeholder={translate("auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.66ea254301", "Start dev server")}
+ placeholder={translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandLabelField.66ea254301',
+ 'Start dev server'
+ )}
/>
)
diff --git a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx
index 7a9f2ac8641..fe09ee6acb4 100644
--- a/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx
+++ b/src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandScopeField.tsx
@@ -49,7 +49,12 @@ export function TerminalQuickCommandScopeField({
}: TerminalQuickCommandScopeFieldProps): React.JSX.Element {
return (
-
{translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.c25cf350ef", "Scope")}
+
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.c25cf350ef',
+ 'Scope'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.b83efc79e2", "Global")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.b83efc79e2',
+ 'Global'
+ )}
+
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.3834d24243", "Project")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.3834d24243',
+ 'Project'
+ )}
+
- {selectedScope.type === "repo" && repos.length > 0 ? (
+ {selectedScope.type === 'repo' && repos.length > 0 ? (
@@ -112,7 +135,11 @@ export function TerminalQuickCommandScopeField({
{selectedRepoMissing ? (
- {translate("auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.2db6edede7", "Saving keeps the existing project scope unless you choose another.")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandScopeField.2db6edede7',
+ 'Saving keeps the existing project scope unless you choose another.'
+ )}
+
) : null}
) : null}
diff --git a/src/renderer/src/components/ui/color-picker.tsx b/src/renderer/src/components/ui/color-picker.tsx
index a6dec56fe84..2ae3ba66d81 100644
--- a/src/renderer/src/components/ui/color-picker.tsx
+++ b/src/renderer/src/components/ui/color-picker.tsx
@@ -93,12 +93,18 @@ export function ColorPicker({
- {translate("auto.components.ui.color.picker.faa855a582", "Hex")}
+
+ {translate('auto.components.ui.color.picker.faa855a582', 'Hex')}
+
{swatchColor}
- {hasInvalidDraft ?
{translate("auto.components.ui.color.picker.ebcf6ba29e", "Invalid hex color.")}
: null}
+ {hasInvalidDraft ? (
+
+ {translate('auto.components.ui.color.picker.ebcf6ba29e', 'Invalid hex color.')}
+
+ ) : null}
diff --git a/src/renderer/src/components/ui/dialog.tsx b/src/renderer/src/components/ui/dialog.tsx
index 63b5434aac4..8b1badf9ab3 100644
--- a/src/renderer/src/components/ui/dialog.tsx
+++ b/src/renderer/src/components/ui/dialog.tsx
@@ -76,7 +76,9 @@ function DialogContent({
className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
-
{translate("auto.components.ui.dialog.f26c4baeda", "Close")}
+
+ {translate('auto.components.ui.dialog.f26c4baeda', 'Close')}
+
)}
@@ -111,7 +113,9 @@ function DialogFooter({
{children}
{showCloseButton && (
- {translate("auto.components.ui.dialog.f26c4baeda", "Close")}
+
+ {translate('auto.components.ui.dialog.f26c4baeda', 'Close')}
+
)}
diff --git a/src/renderer/src/components/ui/repo-multi-combobox.tsx b/src/renderer/src/components/ui/repo-multi-combobox.tsx
index 473bae28d70..0b89a5bda10 100644
--- a/src/renderer/src/components/ui/repo-multi-combobox.tsx
+++ b/src/renderer/src/components/ui/repo-multi-combobox.tsx
@@ -33,10 +33,18 @@ type RepoMultiComboboxProps = {
function renderTriggerLabel(repos: Repo[], selected: ReadonlySet): React.JSX.Element {
if (repos.length === 0) {
- return {translate("auto.components.ui.repo.multi.combobox.65a3dae41d", "No projects")}
+ return (
+
+ {translate('auto.components.ui.repo.multi.combobox.65a3dae41d', 'No projects')}
+
+ )
}
if (selected.size === repos.length) {
- return {translate("auto.components.ui.repo.multi.combobox.bfd8ce21c6", "All projects")}
+ return (
+
+ {translate('auto.components.ui.repo.multi.combobox.bfd8ce21c6', 'All projects')}
+
+ )
}
const selectedRepos = repos.filter((r) => selected.has(r.id))
const [first, second, ...rest] = selectedRepos
@@ -136,7 +144,10 @@ export default function RepoMultiCombobox({
- {translate("auto.components.ui.repo.multi.combobox.bfd8ce21c6", "All projects")}
+
+ {translate('auto.components.ui.repo.multi.combobox.bfd8ce21c6', 'All projects')}
+
- {translate("auto.components.ui.repo.multi.combobox.4471d4a1c0", "No projects match your search.")}
+
+ {translate(
+ 'auto.components.ui.repo.multi.combobox.4471d4a1c0',
+ 'No projects match your search.'
+ )}
+
{filteredRepos.map((repo) => {
const isSelected = selected.has(repo.id)
const isLastSelected = isSelected && selected.size <= 1
@@ -194,7 +212,8 @@ export default function RepoMultiCombobox({
{repo.connectionId && (
- {translate("auto.components.ui.repo.multi.combobox.286ce70256", "SSH")}
+ {translate('auto.components.ui.repo.multi.combobox.286ce70256', 'SSH')}
+
)}
{repo.path}
diff --git a/src/renderer/src/components/ui/sheet.tsx b/src/renderer/src/components/ui/sheet.tsx
index 161d2a25a75..0e722f1a4f5 100644
--- a/src/renderer/src/components/ui/sheet.tsx
+++ b/src/renderer/src/components/ui/sheet.tsx
@@ -104,7 +104,9 @@ function SheetContent({
className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
- {translate("auto.components.ui.sheet.1189e9fe0a", "Close")}
+
+ {translate('auto.components.ui.sheet.1189e9fe0a', 'Close')}
+
)}
diff --git a/src/renderer/src/components/ui/team-multi-combobox.tsx b/src/renderer/src/components/ui/team-multi-combobox.tsx
index 57ebfa47b7a..0007c389bc0 100644
--- a/src/renderer/src/components/ui/team-multi-combobox.tsx
+++ b/src/renderer/src/components/ui/team-multi-combobox.tsx
@@ -23,10 +23,18 @@ type TeamMultiComboboxProps = {
function renderTriggerLabel(teams: LinearTeam[], selected: ReadonlySet): React.JSX.Element {
if (teams.length === 0) {
- return {translate("auto.components.ui.team.multi.combobox.301f2a796e", "All teams")}
+ return (
+
+ {translate('auto.components.ui.team.multi.combobox.301f2a796e', 'All teams')}
+
+ )
}
if (selected.size === teams.length) {
- return {translate("auto.components.ui.team.multi.combobox.301f2a796e", "All teams")}
+ return (
+
+ {translate('auto.components.ui.team.multi.combobox.301f2a796e', 'All teams')}
+
+ )
}
const selectedTeams = teams.filter((t) => selected.has(t.id))
const [first, second, ...rest] = selectedTeams
@@ -120,7 +128,10 @@ export default function TeamMultiCombobox({
- {translate("auto.components.ui.team.multi.combobox.301f2a796e", "All teams")}
+
+ {translate('auto.components.ui.team.multi.combobox.301f2a796e', 'All teams')}
+
- {translate("auto.components.ui.team.multi.combobox.de83523bf9", "No teams match your search.")}
+
+ {translate(
+ 'auto.components.ui.team.multi.combobox.de83523bf9',
+ 'No teams match your search.'
+ )}
+
{filteredTeams.map((team) => {
const isSelected = selected.has(team.id)
const isLastSelected = isSelected && selected.size <= 1
diff --git a/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx b/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx
index 86faec53322..ccff6b69572 100644
--- a/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx
+++ b/src/renderer/src/components/workspace-space/WorkspaceSpacePage.tsx
@@ -58,18 +58,30 @@ export default function WorkspaceSpacePage(): React.JSX.Element {
- {translate("auto.components.workspace.space.WorkspaceSpacePage.ecf72fdc3b", "Back")}
+ {translate('auto.components.workspace.space.WorkspaceSpacePage.ecf72fdc3b', 'Back')}
+
-
{translate("auto.components.workspace.space.WorkspaceSpacePage.45f6302dbc", "Space")}
- {translate("auto.components.workspace.space.WorkspaceSpacePage.e8d6ba11ab", "Beta")}
+
+ {translate(
+ 'auto.components.workspace.space.WorkspaceSpacePage.45f6302dbc',
+ 'Space'
+ )}
+
+
+ {translate('auto.components.workspace.space.WorkspaceSpacePage.e8d6ba11ab', 'Beta')}
+
- {translate("auto.components.workspace.space.WorkspaceSpacePage.8d0048e1cb", "Workspace disk usage and reclaimable worktree storage.")}
+ {translate(
+ 'auto.components.workspace.space.WorkspaceSpacePage.8d0048e1cb',
+ 'Workspace disk usage and reclaimable worktree storage.'
+ )}
+
diff --git a/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx b/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx
index 00d7598dc6d..ea10d9bccc8 100644
--- a/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx
+++ b/src/renderer/src/components/worktree-creation/WorktreeCreationPanel.tsx
@@ -45,8 +45,14 @@ export default function WorktreeCreationPanel({
{title}
@@ -61,9 +67,18 @@ export default function WorktreeCreationPanel({
{isError ? (
- {translate("auto.components.worktree.creation.WorktreeCreationPanel.ed2a664f8b", "Couldn’t create worktree")}
+
+ {translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.ed2a664f8b',
+ 'Couldn’t create worktree'
+ )}
+
- {entry.error ?? translate("auto.components.worktree.creation.WorktreeCreationPanel.767951265d", "Something went wrong while creating the worktree.")}
+ {entry.error ??
+ translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.767951265d',
+ 'Something went wrong while creating the worktree.'
+ )}
- {translate("auto.components.worktree.creation.WorktreeCreationPanel.34dd5ee38b", "Retry")}
+ {translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.34dd5ee38b',
+ 'Retry'
+ )}
+
- {translate("auto.components.worktree.creation.WorktreeCreationPanel.dabd226118", "Dismiss")}
+ {translate(
+ 'auto.components.worktree.creation.WorktreeCreationPanel.dabd226118',
+ 'Dismiss'
+ )}
+
) : (
diff --git a/src/renderer/src/hooks/useAutomationDispatchEvents.ts b/src/renderer/src/hooks/useAutomationDispatchEvents.ts
index a4ef614ece4..cbc17bbf783 100644
--- a/src/renderer/src/hooks/useAutomationDispatchEvents.ts
+++ b/src/renderer/src/hooks/useAutomationDispatchEvents.ts
@@ -72,7 +72,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_unavailable',
workspaceId: run.workspaceId,
workspaceDisplayName: run.workspaceDisplayName ?? null,
- error: translate("auto.hooks.useAutomationDispatchEvents.386db94f3e", "The target project is no longer available.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.386db94f3e',
+ 'The target project is no longer available.'
+ )
})
return
}
@@ -87,7 +90,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_needs_interactive_auth',
workspaceId: dispatchWorkspaceId,
workspaceDisplayName: dispatchWorkspaceDisplayName,
- error: translate("auto.hooks.useAutomationDispatchEvents.16a21d6413", "SSH reconnect requires interactive credentials.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.16a21d6413',
+ 'SSH reconnect requires interactive credentials.'
+ )
})
return
}
@@ -117,7 +123,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_unavailable',
workspaceId: automation.workspaceId,
workspaceDisplayName: dispatchWorkspaceDisplayName,
- error: translate("auto.hooks.useAutomationDispatchEvents.59718b120b", "The target workspace is no longer available.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.59718b120b',
+ 'The target workspace is no longer available.'
+ )
})
return
}
@@ -170,7 +179,10 @@ export function useAutomationDispatchEvents(): void {
status: 'skipped_unavailable',
workspaceId: automation.workspaceId,
workspaceDisplayName: dispatchWorkspaceDisplayName,
- error: translate("auto.hooks.useAutomationDispatchEvents.59718b120b", "The target workspace is no longer available.")
+ error: translate(
+ 'auto.hooks.useAutomationDispatchEvents.59718b120b',
+ 'The target workspace is no longer available.'
+ )
})
return
}
diff --git a/src/renderer/src/hooks/useGlobalFileDrop.ts b/src/renderer/src/hooks/useGlobalFileDrop.ts
index 5b1ed3bd6ee..0d3039fbd44 100644
--- a/src/renderer/src/hooks/useGlobalFileDrop.ts
+++ b/src/renderer/src/hooks/useGlobalFileDrop.ts
@@ -41,7 +41,12 @@ export function useGlobalFileDrop(): void {
const runtimeEnvironmentId = dropSettings?.activeRuntimeEnvironmentId?.trim() || undefined
if (shouldUploadRemoteEditorFileDrop(dropSettings, connectionId)) {
if (!worktreePath) {
- toast.error(translate("auto.hooks.useGlobalFileDrop.245faa95b9", "No remote workspace path is available for dropped files."))
+ toast.error(
+ translate(
+ 'auto.hooks.useGlobalFileDrop.245faa95b9',
+ 'No remote workspace path is available for dropped files.'
+ )
+ )
return
}
void (async () => {
@@ -80,10 +85,20 @@ export function useGlobalFileDrop(): void {
)
}
if (results.some((result) => result.status !== 'imported')) {
- toast.error(translate("auto.hooks.useGlobalFileDrop.d720e2f855", "Some dropped files could not be uploaded."))
+ toast.error(
+ translate(
+ 'auto.hooks.useGlobalFileDrop.d720e2f855',
+ 'Some dropped files could not be uploaded.'
+ )
+ )
}
} catch {
- toast.error(translate("auto.hooks.useGlobalFileDrop.38c9f034ff", "Failed to upload dropped files."))
+ toast.error(
+ translate(
+ 'auto.hooks.useGlobalFileDrop.38c9f034ff',
+ 'Failed to upload dropped files.'
+ )
+ )
}
})()
return
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
index e3bf53d5413..429750daced 100644
--- a/src/renderer/src/i18n/locales/es.json
+++ b/src/renderer/src/i18n/locales/es.json
@@ -4901,12 +4901,12 @@
"95a0411b3e": "plantilla",
"175daba180": "Ejemplo",
"b20c5df6ca": "Agregue un archivo `orca.yaml` para habilitar los valores predeterminados de configuración, archivo o automatización de problemas compartidos para este repositorio. Plantilla de ejemplo:",
- "56f9a4a1d0": "Usando `orca.yaml`",
- "623e0c9f31": "No se pudo analizar `orca.yaml`",
- "5a67e4793d": "No se detectó `orca.yaml`",
- "07ba35bc68": "Comprueba la sangría bajo `scripts:`. Las claves de hook deben usar dos espacios y las líneas de comando deben usar cuatro.",
- "787ca433ef": "Define solo las claves compatibles: `scripts`, `setup`, `archive` y `issueCommand`.",
- "ecc73d9125": "Compara tu archivo con la plantilla funcional de abajo y copia esa estructura si es necesario.",
+ "56f9a4a1d0": "Using `orca.yaml`",
+ "623e0c9f31": "`orca.yaml` could not be parsed",
+ "5a67e4793d": "No `orca.yaml` detected",
+ "07ba35bc68": "Check the indentation under `scripts:`. Hook keys should use two spaces, and command lines should use four.",
+ "787ca433ef": "Define only the supported keys: `scripts`, `setup`, `archive`, and `issueCommand`.",
+ "ecc73d9125": "Compare your file against the working template below and copy that shape if needed.",
"925f9e0dc4": "texto-primer plano",
"0cc712b823": "El archivo de configuración principal existe en la raíz del repositorio, pero Orca aún no pudo analizar las definiciones de gancho admitidas.",
"c90b858573": "texto-ámbar-700 oscuro:texto-ámbar-300",
@@ -4948,13 +4948,7 @@
"2b6356e744": "Guardado",
"81057d5f71": "Ahorro...",
"da37d6f10e": "Copiar",
- "3149964b66": "copiado",
- "56f9a4a1d0": "Using `orca.yaml`",
- "623e0c9f31": "`orca.yaml` could not be parsed",
- "5a67e4793d": "No `orca.yaml` detected",
- "07ba35bc68": "Check the indentation under `scripts:`. Hook keys should use two spaces, and command lines should use four.",
- "787ca433ef": "Define only the supported keys: `scripts`, `setup`, `archive`, and `issueCommand`.",
- "ecc73d9125": "Compare your file against the working template below and copy that shape if needed."
+ "3149964b66": "copiado"
},
"RepositoryIconPicker": {
"2b7d27b93c": "Utilice el color del repositorio {{value0}}",
@@ -5211,7 +5205,11 @@
"fac59213fc": "Buscar temas integrados",
"cb330ef7f8": "de {{value0}}",
"c822571b2e": "coincidente con \"{{value0}}\"",
- "3119c012a5": "cadena"
+ "3119c012a5": "cadena",
+ "builtin_themes": "Built-in",
+ "imported_from": "Imported from {{value0}}",
+ "imported_themes": "Imported",
+ "search_terminal_themes": "Search terminal themes"
},
"SettingsSidebar": {
"e0900f83e7": "SSH",
@@ -5588,7 +5586,9 @@
"b739d2abfe": "Color divisor oscuro",
"7add204bd5": "Elija el tema del terminal utilizado en modo oscuro.",
"9499ad1dc4": "Tema oscuro",
- "f012172e21": "Elija el tema utilizado para los paneles de terminal en modo oscuro."
+ "f012172e21": "Elija el tema utilizado para los paneles de terminal en modo oscuro.",
+ "import_themes_title": "Import Themes",
+ "import_themes_description": "Imported themes are available in both the dark and light theme pickers."
},
"TerminalWindowSection": {
"1705318506": "color magenta ANSI",
@@ -7123,7 +7123,20 @@
"e989914ad6": "Familia de fuentes",
"33031c1465": "tamaño del texto",
"0fe0073f0c": "Tamaño de fuente de terminal predeterminado para nuevos paneles y actualizaciones en vivo.",
- "5930244899": "Tamaño de fuente"
+ "5930244899": "Tamaño de fuente",
+ "warp_import": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "keyword_warp": "warp",
+ "keyword_themes": "themes",
+ "keyword_yaml": "yaml"
+ },
+ "yaml_import": {
+ "title": "Import from YAML",
+ "description": "Import theme YAML files as Orca terminal themes.",
+ "keyword_yaml": "yaml",
+ "keyword_custom": "custom"
+ }
},
"windows": {
"search": {
@@ -7219,6 +7232,42 @@
"agent-generated-tab-title-copy": {
"19ad21615a": "Generar títulos de pestañas automáticamente",
"b036c7a409": "Derive nombres breves de pestañas estables a partir del primer mensaje de agente conocido. Los cambios de nombre manuales siempre ganan."
+ },
+ "WarpThemeImportModal": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "yaml_title": "Import theme YAML",
+ "yaml_description": "Import theme YAML files (Warp format) as Orca terminal themes.",
+ "yaml_no_themes_found": "No themes found in the selected files.",
+ "choose_file": "Choose File",
+ "choose_folder": "Choose Folder",
+ "loading": "Loading Warp themes...",
+ "found_theme_one": "Found 1 theme",
+ "found_theme_other": "Found {{value0}} themes",
+ "found_in_source": " in {{value0}}",
+ "clear_all": "Clear all",
+ "select_all": "Select all",
+ "colors_only": "Colors only",
+ "no_themes_found": "No custom Warp themes found.",
+ "builtin_themes_hint": "Warp's preloaded themes are part of the Warp app and can't be read from disk. Orca already includes most of them, like Dracula, Gruvbox, Solarized, and Tokyo Night.",
+ "choose_manually": "Choose a theme YAML file or folder to import manually.",
+ "skipped_files": "Skipped files",
+ "more_skipped_files": "{{value0}} more skipped files.",
+ "cancel": "Cancel",
+ "import_theme_one": "Import 1 Theme",
+ "import_theme_other": "Import {{value0}} Themes",
+ "import_themes": "Import Themes"
+ },
+ "useWarpThemeImport": {
+ "unknown_error": "Unknown error",
+ "imported_one": "Imported 1 theme",
+ "imported_other": "Imported {{value0}} themes",
+ "import_failed": "Failed to import themes",
+ "over_limit_one": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect 1 new theme and try again.",
+ "over_limit_other": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect {{value1}} new themes and try again."
+ },
+ "YamlThemeImportButton": {
+ "label": "Import from YAML"
}
},
"right": {
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 2270c43cb16..243637d8485 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -5190,7 +5190,11 @@
"fac59213fc": "내장 테마 검색",
"cb330ef7f8": "{{value0}} 중",
"c822571b2e": "\"{{value0}}\"과 일치",
- "3119c012a5": "문자열"
+ "3119c012a5": "문자열",
+ "builtin_themes": "Built-in",
+ "imported_from": "Imported from {{value0}}",
+ "imported_themes": "Imported",
+ "search_terminal_themes": "Search terminal themes"
},
"SettingsSidebar": {
"e0900f83e7": "SSH",
@@ -5567,7 +5571,9 @@
"b739d2abfe": "다크 디바이더 색상",
"7add204bd5": "다크 모드에서 사용되는 터미널 테마를 선택하세요.",
"9499ad1dc4": "어두운 테마",
- "f012172e21": "어두운 모드에서 터미널 패널에 사용되는 테마를 선택합니다."
+ "f012172e21": "어두운 모드에서 터미널 패널에 사용되는 테마를 선택합니다.",
+ "import_themes_title": "Import Themes",
+ "import_themes_description": "Imported themes are available in both the dark and light theme pickers."
},
"TerminalWindowSection": {
"1705318506": "ANSI 마젠타색",
@@ -7102,7 +7108,20 @@
"e989914ad6": "글꼴군",
"33031c1465": "텍스트 크기",
"0fe0073f0c": "새 창 및 라이브 업데이트의 기본 터미널 글꼴 크기입니다.",
- "5930244899": "글꼴 크기"
+ "5930244899": "글꼴 크기",
+ "warp_import": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "keyword_warp": "warp",
+ "keyword_themes": "themes",
+ "keyword_yaml": "yaml"
+ },
+ "yaml_import": {
+ "title": "Import from YAML",
+ "description": "Import theme YAML files as Orca terminal themes.",
+ "keyword_yaml": "yaml",
+ "keyword_custom": "custom"
+ }
},
"windows": {
"search": {
@@ -7213,6 +7232,42 @@
}
}
}
+ },
+ "WarpThemeImportModal": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "yaml_title": "Import theme YAML",
+ "yaml_description": "Import theme YAML files (Warp format) as Orca terminal themes.",
+ "yaml_no_themes_found": "No themes found in the selected files.",
+ "choose_file": "Choose File",
+ "choose_folder": "Choose Folder",
+ "loading": "Loading Warp themes...",
+ "found_theme_one": "Found 1 theme",
+ "found_theme_other": "Found {{value0}} themes",
+ "found_in_source": " in {{value0}}",
+ "clear_all": "Clear all",
+ "select_all": "Select all",
+ "colors_only": "Colors only",
+ "no_themes_found": "No custom Warp themes found.",
+ "builtin_themes_hint": "Warp's preloaded themes are part of the Warp app and can't be read from disk. Orca already includes most of them, like Dracula, Gruvbox, Solarized, and Tokyo Night.",
+ "choose_manually": "Choose a theme YAML file or folder to import manually.",
+ "skipped_files": "Skipped files",
+ "more_skipped_files": "{{value0}} more skipped files.",
+ "cancel": "Cancel",
+ "import_theme_one": "Import 1 Theme",
+ "import_theme_other": "Import {{value0}} Themes",
+ "import_themes": "Import Themes"
+ },
+ "useWarpThemeImport": {
+ "unknown_error": "Unknown error",
+ "imported_one": "Imported 1 theme",
+ "imported_other": "Imported {{value0}} themes",
+ "import_failed": "Failed to import themes",
+ "over_limit_one": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect 1 new theme and try again.",
+ "over_limit_other": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect {{value1}} new themes and try again."
+ },
+ "YamlThemeImportButton": {
+ "label": "Import from YAML"
}
},
"right": {
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index 61527811e59..cc3be1d6294 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -5190,7 +5190,11 @@
"fac59213fc": "搜索内置主题",
"cb330ef7f8": "{{value0}} 的",
"c822571b2e": "匹配“{{value0}}”",
- "3119c012a5": "字符串"
+ "3119c012a5": "字符串",
+ "builtin_themes": "Built-in",
+ "imported_from": "Imported from {{value0}}",
+ "imported_themes": "Imported",
+ "search_terminal_themes": "Search terminal themes"
},
"SettingsSidebar": {
"e0900f83e7": "SSH",
@@ -5567,7 +5571,9 @@
"b739d2abfe": "深色分隔线颜色",
"7add204bd5": "选择深色模式下使用的终端主题。",
"9499ad1dc4": "黑暗主题",
- "f012172e21": "选择深色模式下用于终端窗格的主题。"
+ "f012172e21": "选择深色模式下用于终端窗格的主题。",
+ "import_themes_title": "Import Themes",
+ "import_themes_description": "Imported themes are available in both the dark and light theme pickers."
},
"TerminalWindowSection": {
"1705318506": "ANSI 洋红色",
@@ -7102,7 +7108,20 @@
"e989914ad6": "字体家族",
"33031c1465": "文字大小",
"0fe0073f0c": "新窗格和实时更新的默认终端字体大小。",
- "5930244899": "字体大小"
+ "5930244899": "字体大小",
+ "warp_import": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "keyword_warp": "warp",
+ "keyword_themes": "themes",
+ "keyword_yaml": "yaml"
+ },
+ "yaml_import": {
+ "title": "Import from YAML",
+ "description": "Import theme YAML files as Orca terminal themes.",
+ "keyword_yaml": "yaml",
+ "keyword_custom": "custom"
+ }
},
"windows": {
"search": {
@@ -7213,6 +7232,42 @@
}
}
}
+ },
+ "WarpThemeImportModal": {
+ "title": "Import themes from Warp",
+ "description": "Import Warp themes as Orca terminal themes.",
+ "yaml_title": "Import theme YAML",
+ "yaml_description": "Import theme YAML files (Warp format) as Orca terminal themes.",
+ "yaml_no_themes_found": "No themes found in the selected files.",
+ "choose_file": "Choose File",
+ "choose_folder": "Choose Folder",
+ "loading": "Loading Warp themes...",
+ "found_theme_one": "Found 1 theme",
+ "found_theme_other": "Found {{value0}} themes",
+ "found_in_source": " in {{value0}}",
+ "clear_all": "Clear all",
+ "select_all": "Select all",
+ "colors_only": "Colors only",
+ "no_themes_found": "No custom Warp themes found.",
+ "builtin_themes_hint": "Warp's preloaded themes are part of the Warp app and can't be read from disk. Orca already includes most of them, like Dracula, Gruvbox, Solarized, and Tokyo Night.",
+ "choose_manually": "Choose a theme YAML file or folder to import manually.",
+ "skipped_files": "Skipped files",
+ "more_skipped_files": "{{value0}} more skipped files.",
+ "cancel": "Cancel",
+ "import_theme_one": "Import 1 Theme",
+ "import_theme_other": "Import {{value0}} Themes",
+ "import_themes": "Import Themes"
+ },
+ "useWarpThemeImport": {
+ "unknown_error": "Unknown error",
+ "imported_one": "Imported 1 theme",
+ "imported_other": "Imported {{value0}} themes",
+ "import_failed": "Failed to import themes",
+ "over_limit_one": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect 1 new theme and try again.",
+ "over_limit_other": "Importing these themes would exceed the {{value0}} custom terminal theme limit. Deselect {{value1}} new themes and try again."
+ },
+ "YamlThemeImportButton": {
+ "label": "Import from YAML"
}
},
"right": {
diff --git a/src/renderer/src/lib/agent-skill-cli-prerequisite.ts b/src/renderer/src/lib/agent-skill-cli-prerequisite.ts
index b4394f861cc..06dd6d76bc3 100644
--- a/src/renderer/src/lib/agent-skill-cli-prerequisite.ts
+++ b/src/renderer/src/lib/agent-skill-cli-prerequisite.ts
@@ -43,7 +43,14 @@ export async function ensureOrcaCliAvailableForAgentSkillTerminal({
return status
} catch (error) {
- toast.error(error instanceof Error ? error.message : translate("auto.lib.agent.skill.cli.prerequisite.8d6eedf97e", "Failed to register the Orca CLI in PATH."))
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : translate(
+ 'auto.lib.agent.skill.cli.prerequisite.8d6eedf97e',
+ 'Failed to register the Orca CLI in PATH.'
+ )
+ )
return null
}
}
@@ -64,25 +71,57 @@ function delay(ms: number): Promise
{
function showCliPrerequisiteWarning(status: CliInstallStatus): void {
if (!status.supported) {
- toast.warning(translate("auto.lib.agent.skill.cli.prerequisite.2db0bd7515", "Orca CLI registration is unavailable"), {
- description: status.detail ?? translate("auto.lib.agent.skill.cli.prerequisite.15cbedc3e3", "Install the Orca CLI before running agent skill setup.")
- })
+ toast.warning(
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.2db0bd7515',
+ 'Orca CLI registration is unavailable'
+ ),
+ {
+ description:
+ status.detail ??
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.15cbedc3e3',
+ 'Install the Orca CLI before running agent skill setup.'
+ )
+ }
+ )
return
}
if (status.state !== 'installed') {
- toast.warning(translate("auto.lib.agent.skill.cli.prerequisite.e99d7dc36f", "Orca CLI registration needs attention"), {
- description: status.detail ?? translate("auto.lib.agent.skill.cli.prerequisite.15cbedc3e3", "Install the Orca CLI before running agent skill setup.")
- })
+ toast.warning(
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.e99d7dc36f',
+ 'Orca CLI registration needs attention'
+ ),
+ {
+ description:
+ status.detail ??
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.15cbedc3e3',
+ 'Install the Orca CLI before running agent skill setup.'
+ )
+ }
+ )
return
}
if (!status.pathConfigured) {
// Why: the skill installer opens a real shell; agents only get the expected
// Orca affordances when that shell can resolve the Orca CLI command.
- toast.warning(translate("auto.lib.agent.skill.cli.prerequisite.79371593b0", "Orca CLI is not visible on PATH yet"), {
- description:
- status.detail ?? translate("auto.lib.agent.skill.cli.prerequisite.0f116999f1", "Restart your shell or add the Orca CLI directory to PATH before setup.")
- })
+ toast.warning(
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.79371593b0',
+ 'Orca CLI is not visible on PATH yet'
+ ),
+ {
+ description:
+ status.detail ??
+ translate(
+ 'auto.lib.agent.skill.cli.prerequisite.0f116999f1',
+ 'Restart your shell or add the Orca CLI directory to PATH before setup.'
+ )
+ }
+ )
}
}
diff --git a/src/renderer/src/lib/ensure-simulator-tab.ts b/src/renderer/src/lib/ensure-simulator-tab.ts
index 5822ff6e938..7edeafb16bf 100644
--- a/src/renderer/src/lib/ensure-simulator-tab.ts
+++ b/src/renderer/src/lib/ensure-simulator-tab.ts
@@ -66,7 +66,7 @@ export function ensureSimulatorTab(
)
if (reusableRightGroupId) {
const tab = store.createUnifiedTab(worktreeId, 'simulator', {
- label: translate("auto.lib.ensure.simulator.tab.372d21d428", "Mobile Emulator"),
+ label: translate('auto.lib.ensure.simulator.tab.372d21d428', 'Mobile Emulator'),
targetGroupId: reusableRightGroupId,
activate: true
})
@@ -86,7 +86,7 @@ export function ensureSimulatorTab(
splitDirection: 'right'
},
{
- label: translate("auto.lib.ensure.simulator.tab.372d21d428", "Mobile Emulator"),
+ label: translate('auto.lib.ensure.simulator.tab.372d21d428', 'Mobile Emulator'),
activate: true
}
)
@@ -96,7 +96,7 @@ export function ensureSimulatorTab(
}
const tab = store.createUnifiedTab(worktreeId, 'simulator', {
- label: translate("auto.lib.ensure.simulator.tab.372d21d428", "Mobile Emulator"),
+ label: translate('auto.lib.ensure.simulator.tab.372d21d428', 'Mobile Emulator'),
targetGroupId: sourceGroupId,
activate: shouldSurface
})
diff --git a/src/renderer/src/lib/fix-checks-agent-launch.ts b/src/renderer/src/lib/fix-checks-agent-launch.ts
index c4e88a354e8..65db5771090 100644
--- a/src/renderer/src/lib/fix-checks-agent-launch.ts
+++ b/src/renderer/src/lib/fix-checks-agent-launch.ts
@@ -67,7 +67,12 @@ async function resolveSavedAgentOverride(
}
const detectedAgents = await detectAgentsForConnection(connectionId)
if (!isAgentAvailable(savedAgent, detectedAgents)) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.4c7f783a7a", "Saved checks agent is not available on this workspace host."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.4c7f783a7a',
+ 'Saved checks agent is not available on this workspace host.'
+ )
+ )
return { kind: 'blocked' }
}
return { kind: 'agent', agent: savedAgent }
@@ -84,7 +89,12 @@ async function pickExistingWorktreeAgent(
if (isAgentAvailable(savedAgent, detectedAgents)) {
return savedAgent
}
- toast.error(translate("auto.lib.fix.checks.agent.launch.4c7f783a7a", "Saved checks agent is not available on this workspace host."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.4c7f783a7a',
+ 'Saved checks agent is not available on this workspace host.'
+ )
+ )
return null
}
const settings = useAppStore.getState().settings
@@ -94,7 +104,12 @@ async function pickExistingWorktreeAgent(
disabledAgents: settings?.disabledTuiAgents
})
if (!agent) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.2ebf794906", "No enabled AI agent was detected on this workspace host."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.2ebf794906',
+ 'No enabled AI agent was detected on this workspace host.'
+ )
+ )
}
return agent
}
@@ -113,7 +128,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
{ basePrompt: args.basePrompt }
).trim()
if (!commandInput) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.9f00d7df0c", "Fix checks prompt is empty. Update Source Control AI settings."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.9f00d7df0c',
+ 'Fix checks prompt is empty. Update Source Control AI settings.'
+ )
+ )
return false
}
@@ -125,7 +145,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
if (targetWorktreeId) {
const targetWorktree = store.allWorktrees().find((worktree) => worktree.id === targetWorktreeId)
if (!targetWorktree) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.dfb4dd7c00", "Unable to find the workspace attached to these checks."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.dfb4dd7c00',
+ 'Unable to find the workspace attached to these checks.'
+ )
+ )
return false
}
const targetConnectionId = getConnectionId(targetWorktreeId) ?? repo?.connectionId ?? null
@@ -142,7 +167,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
worktreePath: targetWorktree.path
})
if (!launchPlatform) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.822bf52295", "Unable to resolve the workspace launch platform."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.822bf52295',
+ 'Unable to resolve the workspace launch platform.'
+ )
+ )
return false
}
const agentArgsPlan = planAgentCliArgsSuffix(
@@ -154,7 +184,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
return false
}
if (!activateAndRevealWorktree(targetWorktreeId)) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.03c1d61f83", "Unable to open the workspace attached to these checks."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.03c1d61f83',
+ 'Unable to open the workspace attached to these checks.'
+ )
+ )
return false
}
const result = launchAgentInNewTab({
@@ -168,7 +203,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
launchSource: args.launchSource
})
if (!result) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.fb6c294e85", "Could not build the agent launch command."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.fb6c294e85',
+ 'Could not build the agent launch command.'
+ )
+ )
return false
}
if (result.tabId) {
@@ -178,7 +218,12 @@ export async function startFixChecksAgent(args: StartFixChecksAgentArgs): Promis
}
if (!args.item || !args.openModalFallback) {
- toast.error(translate("auto.lib.fix.checks.agent.launch.027228a06b", "Unable to find a workspace for these checks."))
+ toast.error(
+ translate(
+ 'auto.lib.fix.checks.agent.launch.027228a06b',
+ 'Unable to find a workspace for these checks.'
+ )
+ )
return false
}
diff --git a/src/renderer/src/lib/floating-workspace-tab-creation.ts b/src/renderer/src/lib/floating-workspace-tab-creation.ts
index 5b119df89c1..12814ca7813 100644
--- a/src/renderer/src/lib/floating-workspace-tab-creation.ts
+++ b/src/renderer/src/lib/floating-workspace-tab-creation.ts
@@ -69,7 +69,7 @@ export async function createFloatingWorkspaceBrowserTab(
}
return store.createBrowserTab(FLOATING_TERMINAL_WORKTREE_ID, url, {
- title: translate("auto.lib.floating.workspace.tab.creation.f3785eddc2", "New Browser Tab"),
+ title: translate('auto.lib.floating.workspace.tab.creation.f3785eddc2', 'New Browser Tab'),
focusAddressBar: true,
targetGroupId
})
diff --git a/src/renderer/src/lib/launch-agent-background-session.ts b/src/renderer/src/lib/launch-agent-background-session.ts
index 11fcadd8bf5..6128b354e0e 100644
--- a/src/renderer/src/lib/launch-agent-background-session.ts
+++ b/src/renderer/src/lib/launch-agent-background-session.ts
@@ -257,7 +257,12 @@ export async function launchAgentBackgroundSession(
agent,
submit: true,
onTimeout: () => {
- toast.message(translate("auto.lib.launch.agent.background.session.4ca0651d56", "Your automation prompt wasn't sent — open the workspace and paste it."))
+ toast.message(
+ translate(
+ 'auto.lib.launch.agent.background.session.4ca0651d56',
+ "Your automation prompt wasn't sent — open the workspace and paste it."
+ )
+ )
track('agent_error', {
error_class: 'paste_readiness_timeout',
agent_kind: tuiAgentToAgentKind(agent)
diff --git a/src/renderer/src/lib/launch-agent-in-new-tab.ts b/src/renderer/src/lib/launch-agent-in-new-tab.ts
index 33752db7bf6..7eacb32e70a 100644
--- a/src/renderer/src/lib/launch-agent-in-new-tab.ts
+++ b/src/renderer/src/lib/launch-agent-in-new-tab.ts
@@ -232,7 +232,13 @@ export function launchAgentInNewTab(args: LaunchAgentInNewTabArgs): LaunchAgentI
// exists; keep pruning stale local rows until the snapshot mirrors.
removeStaleLocalAgentTabsForWebHostLaunch(worktreeId)
if (!created) {
- toast.error(translate("auto.lib.launch.agent.in.new.tab.11cce5cc77", "Could not launch {{value0}} in a new terminal.", { value0: agent }))
+ toast.error(
+ translate(
+ 'auto.lib.launch.agent.in.new.tab.11cce5cc77',
+ 'Could not launch {{value0}} in a new terminal.',
+ { value0: agent }
+ )
+ )
return
}
store.setActiveTabType('terminal')
@@ -308,7 +314,13 @@ export function launchAgentInNewTab(args: LaunchAgentInNewTabArgs): LaunchAgentI
return
}
const label = submitPastedPrompt ? 'prompt' : 'notes'
- toast.message(translate("auto.lib.launch.agent.in.new.tab.a5a1f7033f", "Your {{value0}} wasn't sent — paste it once the agent is ready.", { value0: label }))
+ toast.message(
+ translate(
+ 'auto.lib.launch.agent.in.new.tab.a5a1f7033f',
+ "Your {{value0}} wasn't sent — paste it once the agent is ready.",
+ { value0: label }
+ )
+ )
track('agent_error', {
error_class: 'paste_readiness_timeout',
agent_kind: tuiAgentToAgentKind(agent)
diff --git a/src/renderer/src/lib/launch-work-item-direct-agent.ts b/src/renderer/src/lib/launch-work-item-direct-agent.ts
index 8e592b49346..065c093e95f 100644
--- a/src/renderer/src/lib/launch-work-item-direct-agent.ts
+++ b/src/renderer/src/lib/launch-work-item-direct-agent.ts
@@ -47,7 +47,11 @@ export async function pasteDirectWorkItemDraftWhenAgentReady(args: {
onTimeout: () => {
const label = submit ? 'prompt' : 'work item context'
toast.message(
- translate("auto.lib.launch.work.item.direct.agent.ceeeb509b5", "Agent took too long to start. The workspace is ready — paste the {{value0}} when the agent is idle.", { value0: label })
+ translate(
+ 'auto.lib.launch.work.item.direct.agent.ceeeb509b5',
+ 'Agent took too long to start. The workspace is ready — paste the {{value0}} when the agent is idle.',
+ { value0: label }
+ )
)
// Why: process-startup timeout has no v1 enum slot; the `unknown` slice
// on the dashboard is the trigger to add one.
diff --git a/src/renderer/src/lib/local-path-open-guard.ts b/src/renderer/src/lib/local-path-open-guard.ts
index 23b3ab959e1..7fed28d8e10 100644
--- a/src/renderer/src/lib/local-path-open-guard.ts
+++ b/src/renderer/src/lib/local-path-open-guard.ts
@@ -12,5 +12,10 @@ export function isLocalPathOpenBlocked(
export function showLocalPathOpenBlockedToast(): void {
// Why: local OS reveal/open actions receive client filesystem paths. Remote
// runtime and SSH paths belong to another machine, not this client.
- toast.error(translate("auto.lib.local.path.open.guard.edc1908653", "Opening remote paths in the local OS is not available."))
+ toast.error(
+ translate(
+ 'auto.lib.local.path.open.guard.edc1908653',
+ 'Opening remote paths in the local OS is not available.'
+ )
+ )
}
diff --git a/src/renderer/src/lib/resume-sleeping-agent-session.ts b/src/renderer/src/lib/resume-sleeping-agent-session.ts
index 3664eb99a12..585d41dd498 100644
--- a/src/renderer/src/lib/resume-sleeping-agent-session.ts
+++ b/src/renderer/src/lib/resume-sleeping-agent-session.ts
@@ -45,7 +45,12 @@ function launchSleepingAgentSession(record: SleepingAgentSessionRecord): boolean
platform: getResumeLaunchPlatform(record.worktreeId)
})
if (!startupPlan) {
- toast.error(translate("auto.lib.resume.sleeping.agent.session.f235f604fd", "This agent session cannot be resumed."))
+ toast.error(
+ translate(
+ 'auto.lib.resume.sleeping.agent.session.f235f604fd',
+ 'This agent session cannot be resumed.'
+ )
+ )
return false
}
diff --git a/src/renderer/src/lib/source-control-agent-action-plan.ts b/src/renderer/src/lib/source-control-agent-action-plan.ts
index 88af0afccf3..ca5ac2a54a6 100644
--- a/src/renderer/src/lib/source-control-agent-action-plan.ts
+++ b/src/renderer/src/lib/source-control-agent-action-plan.ts
@@ -39,18 +39,42 @@ export function planSourceControlAgentActionLaunch(args: {
}): SourceControlLaunchPlanResult {
const agent = args.agent
if (!agent) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.a7ac8717c7", "Choose an agent before starting.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.a7ac8717c7',
+ 'Choose an agent before starting.'
+ )
+ }
}
if (!isTuiAgentEnabled(agent, args.disabledAgents)) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.b96e091fc9", "The selected agent is disabled in Settings.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.b96e091fc9',
+ 'The selected agent is disabled in Settings.'
+ )
+ }
}
if (!args.detectedAgents.includes(agent)) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.8eb541cc83", "The selected agent was not detected on this workspace host.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.8eb541cc83',
+ 'The selected agent was not detected on this workspace host.'
+ )
+ }
}
const trimmedInput = args.commandInput.trim()
if (!trimmedInput) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.46f1a2c9bd", "Command input is empty.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.46f1a2c9bd',
+ 'Command input is empty.'
+ )
+ }
}
const cmdOverrides = args.cmdOverrides ?? {}
@@ -124,7 +148,13 @@ export function planSourceControlAgentActionLaunch(args: {
}
if (!startupPlan) {
- return { ok: false, error: translate("auto.lib.source.control.agent.action.plan.3f0ea9aa0d", "Could not build the agent launch command.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.agent.action.plan.3f0ea9aa0d',
+ 'Could not build the agent launch command.'
+ )
+ }
}
const summary =
diff --git a/src/renderer/src/lib/source-control-generation-plan.ts b/src/renderer/src/lib/source-control-generation-plan.ts
index e3b5db94a57..2f76fd62927 100644
--- a/src/renderer/src/lib/source-control-generation-plan.ts
+++ b/src/renderer/src/lib/source-control-generation-plan.ts
@@ -60,7 +60,13 @@ export function planSourceControlTextGeneration(
)
: SYNTHETIC_BASE_PROMPTS[actionId]
if (!prompt.trim()) {
- return { ok: false, error: translate("auto.lib.source.control.generation.plan.dc480d5897", "Command input is empty.") }
+ return {
+ ok: false,
+ error: translate(
+ 'auto.lib.source.control.generation.plan.dc480d5897',
+ 'Command input is empty.'
+ )
+ }
}
const planned = planCommitMessageGeneration(params, prompt)
if (!planned.ok) {
diff --git a/src/renderer/src/lib/sparse-preset-draft.ts b/src/renderer/src/lib/sparse-preset-draft.ts
index 1e4d2db8a71..56c30f57986 100644
--- a/src/renderer/src/lib/sparse-preset-draft.ts
+++ b/src/renderer/src/lib/sparse-preset-draft.ts
@@ -16,7 +16,10 @@ export function parseSparsePresetDirectories(value: string): SparsePresetDirecto
if (rawEntries.some(isAbsoluteSparseDirectoryPath)) {
return {
directories: [],
- error: translate("auto.lib.sparse.preset.draft.5915a0a1f6", "Use repo-relative directories, not root, absolute paths, or parent segments.")
+ error: translate(
+ 'auto.lib.sparse.preset.draft.5915a0a1f6',
+ 'Use repo-relative directories, not root, absolute paths, or parent segments.'
+ )
}
}
@@ -25,14 +28,17 @@ export function parseSparsePresetDirectories(value: string): SparsePresetDirecto
if (directories.length === 0) {
return {
directories,
- error: translate("auto.lib.sparse.preset.draft.efc05d1820", "Add at least one directory.")
+ error: translate('auto.lib.sparse.preset.draft.efc05d1820', 'Add at least one directory.')
}
}
if (directories.some((entry) => entry === '.' || entry.split('/').includes('..'))) {
return {
directories: [],
- error: translate("auto.lib.sparse.preset.draft.5915a0a1f6", "Use repo-relative directories, not root, absolute paths, or parent segments.")
+ error: translate(
+ 'auto.lib.sparse.preset.draft.5915a0a1f6',
+ 'Use repo-relative directories, not root, absolute paths, or parent segments.'
+ )
}
}
diff --git a/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx b/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx
index 768a73820c4..0e1c9e04634 100644
--- a/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx
+++ b/src/renderer/src/lib/terminal-shortcut-capture-notification.tsx
@@ -64,23 +64,32 @@ export function showTerminalShortcutCaptureNotification({
)
// Why: this toast stays up longer than normal, so keep it compact while still
// exposing the captured shortcut and the edit path.
- toast.message(translate("auto.lib.terminal.shortcut.capture.notification.141ad6c004", "Terminal shortcut handled"), {
- description: `${definition.title} (${bindingLabel})`,
- // Why: this is the user's one-time rebind path for a captured shortcut; it
- // needs enough reading time without becoming persistent chrome.
- duration: NOTICE_DURATION_MS,
- dismissible: true,
- className: '!w-[420px] !max-w-[calc(100vw-2rem)] !gap-2 !py-2 !pl-3 !pr-2',
- classNames: {
- content: 'min-w-0 flex-1 !gap-0.5',
- title: 'truncate !leading-5',
- description: 'truncate !leading-4',
- actionButton: '!h-7 !shrink-0 !rounded-md !px-2.5'
- },
- icon: ,
- action: {
- label: translate("auto.lib.terminal.shortcut.capture.notification.b0536028c9", "Open Shortcuts"),
- onClick: openShortcutSettings
+ toast.message(
+ translate(
+ 'auto.lib.terminal.shortcut.capture.notification.141ad6c004',
+ 'Terminal shortcut handled'
+ ),
+ {
+ description: `${definition.title} (${bindingLabel})`,
+ // Why: this is the user's one-time rebind path for a captured shortcut; it
+ // needs enough reading time without becoming persistent chrome.
+ duration: NOTICE_DURATION_MS,
+ dismissible: true,
+ className: '!w-[420px] !max-w-[calc(100vw-2rem)] !gap-2 !py-2 !pl-3 !pr-2',
+ classNames: {
+ content: 'min-w-0 flex-1 !gap-0.5',
+ title: 'truncate !leading-5',
+ description: 'truncate !leading-4',
+ actionButton: '!h-7 !shrink-0 !rounded-md !px-2.5'
+ },
+ icon: ,
+ action: {
+ label: translate(
+ 'auto.lib.terminal.shortcut.capture.notification.b0536028c9',
+ 'Open Shortcuts'
+ ),
+ onClick: openShortcutSettings
+ }
}
- })
+ )
}
diff --git a/src/renderer/src/lib/workspace-create-error-format.ts b/src/renderer/src/lib/workspace-create-error-format.ts
index 89ed71576b3..d33f0d066fe 100644
--- a/src/renderer/src/lib/workspace-create-error-format.ts
+++ b/src/renderer/src/lib/workspace-create-error-format.ts
@@ -12,8 +12,11 @@ export function formatWorkspaceCreateError(error: unknown): WorkspaceCreateError
if (message.toLowerCase().includes(MISSING_BASE_REF_ANCHOR)) {
return {
- title: translate("auto.lib.workspace.create.error.format.64555d0014", "No base branch found"),
- message: translate("auto.lib.workspace.create.error.format.37cf0bc991", "Orca could not resolve a usable base ref for this workspace."),
+ title: translate('auto.lib.workspace.create.error.format.64555d0014', 'No base branch found'),
+ message: translate(
+ 'auto.lib.workspace.create.error.format.37cf0bc991',
+ 'Orca could not resolve a usable base ref for this workspace.'
+ ),
help: 'Create an initial commit (for example on main), or select an existing branch in Create From, then try again.'
}
}
diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx
index e74ab1406e8..69e07a61aa0 100644
--- a/src/renderer/src/main.tsx
+++ b/src/renderer/src/main.tsx
@@ -41,7 +41,10 @@ createRoot(rootElement).render(
boundaryId="app.root"
surface="app-root"
title={translate('app.recoverableError.rootTitle', 'Orca hit a renderer error.')}
- description={translate('app.recoverableError.rootDescription', 'The app shell could not finish rendering. Retry to remount it, or relaunch Orca if the error persists.')}
+ description={translate(
+ 'app.recoverableError.rootDescription',
+ 'The app shell could not finish rendering. Retry to remount it, or relaunch Orca if the error persists.'
+ )}
>
diff --git a/src/renderer/src/store/slices/browser.test.ts b/src/renderer/src/store/slices/browser.test.ts
index 989a0d9b614..d07fa741299 100644
--- a/src/renderer/src/store/slices/browser.test.ts
+++ b/src/renderer/src/store/slices/browser.test.ts
@@ -38,6 +38,8 @@ function createTestStore() {
(...a) =>
({
settings: { activeRuntimeEnvironmentId: null } as AppState['settings'],
+ activeWorktreeId: 'wt-1',
+ browserDefaultUrl: 'about:blank',
unifiedTabsByWorktree: {},
tabBarOrderByWorktree: {},
tabsByWorktree: {},
@@ -49,6 +51,7 @@ function createTestStore() {
closeUnifiedTab: vi.fn(),
activateTab: vi.fn(),
setTabLabel: vi.fn(),
+ recordFeatureInteraction: vi.fn(),
...createBrowserSlice(...a)
}) as unknown as AppState
)
@@ -143,6 +146,19 @@ function makeAnnotation(pageId: string, id = 'annotation-1'): BrowserPageAnnotat
}
describe('createBrowserSlice annotations', () => {
+ it('records browser-tab-created only for the explicit new-tab action', async () => {
+ const store = createTestStore()
+
+ store.getState().createBrowserTab('wt-1', 'https://example.com')
+ expect(store.getState().recordFeatureInteraction).not.toHaveBeenCalledWith(
+ 'browser-tab-created'
+ )
+
+ await store.getState().openNewBrowserTabInActiveWorkspace('group-1')
+
+ expect(store.getState().recordFeatureInteraction).toHaveBeenCalledWith('browser-tab-created')
+ })
+
it('clears page annotations when the browser page URL changes', () => {
const store = createTestStore()
const tab = store.getState().createBrowserTab('wt-1', 'https://example.com')
diff --git a/src/renderer/src/store/slices/browser.ts b/src/renderer/src/store/slices/browser.ts
index c04bf89f9ff..19c4de9fb2a 100644
--- a/src/renderer/src/store/slices/browser.ts
+++ b/src/renderer/src/store/slices/browser.ts
@@ -298,7 +298,7 @@ function mirrorWorkspaceFromActivePage(
activePageId: null,
pageIds: pages.map((page) => page.id),
url: 'about:blank',
- title: translate("auto.store.slices.browser.08fc23631d", "Browser"),
+ title: translate('auto.store.slices.browser.08fc23631d', 'Browser'),
loading: false,
faviconUrl: null,
canGoBack: false,
@@ -542,13 +542,15 @@ export const createBrowserSlice: StateCreator =
url: defaultUrl,
targetGroupId: groupId
})
+ get().recordFeatureInteraction('browser-tab-created')
return
}
get().createBrowserTab(worktreeId, defaultUrl, {
- title: translate("auto.store.slices.browser.d175274b6d", "New Browser Tab"),
+ title: translate('auto.store.slices.browser.d175274b6d', 'New Browser Tab'),
focusAddressBar: true,
targetGroupId: groupId
})
+ get().recordFeatureInteraction('browser-tab-created')
},
closeBrowserTab: (tabId) => {
diff --git a/src/renderer/src/store/slices/editor.test.ts b/src/renderer/src/store/slices/editor.test.ts
index 13fc6b7d516..03b87fd3bed 100644
--- a/src/renderer/src/store/slices/editor.test.ts
+++ b/src/renderer/src/store/slices/editor.test.ts
@@ -34,6 +34,7 @@ function createEditorStore(): StoreApi {
browserTabsByWorktree: {},
activeBrowserTabId: null,
activeBrowserTabIdByWorktree: {},
+ recordFeatureInteraction: vi.fn(),
...createEditorSlice(...(args as Parameters))
})) as unknown as StoreApi
}
@@ -46,6 +47,7 @@ function createEditorTabsStore(): StoreApi {
browserTabsByWorktree: {},
activeBrowserTabId: null,
activeBrowserTabIdByWorktree: {},
+ recordFeatureInteraction: vi.fn(),
...createTabsSlice(...(args as Parameters)),
...createEditorSlice(...(args as Parameters))
})) as unknown as StoreApi
@@ -66,6 +68,22 @@ function ownedEditorFileId(
}
describe('createEditorSlice right sidebar state', () => {
+ it('does not record markdown-file-created when opening an existing markdown file', () => {
+ const store = createEditorStore()
+
+ store.getState().openFile({
+ filePath: '/repo/docs/existing.md',
+ relativePath: 'docs/existing.md',
+ worktreeId: 'wt-1',
+ language: 'markdown',
+ mode: 'edit'
+ })
+
+ expect(store.getState().recordFeatureInteraction).not.toHaveBeenCalledWith(
+ 'markdown-file-created'
+ )
+ })
+
it('right sidebar is closed by default', () => {
const store = createEditorStore()
expect(store.getState().rightSidebarOpen).toBe(false)
diff --git a/src/renderer/src/store/slices/editor.ts b/src/renderer/src/store/slices/editor.ts
index bb6bc010da1..8a70a8477d5 100644
--- a/src/renderer/src/store/slices/editor.ts
+++ b/src/renderer/src/store/slices/editor.ts
@@ -1705,6 +1705,7 @@ export const createEditorSlice: StateCreator = (s
return
}
get().openFile(fileInfo, { preview: false, targetGroupId: groupId })
+ get().recordFeatureInteraction('markdown-file-created')
} catch (err) {
toast.error(extractIpcErrorMessage(err, 'Failed to create untitled markdown file.'))
}
@@ -3679,11 +3680,19 @@ export const createEditorSlice: StateCreator = (s
try {
stats = await statRuntimePath(fileContext, target.absolutePath)
} catch {
- toast.error(translate("auto.store.slices.editor.f2e00db373", "File not found: {{value0}}", { value0: target.relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.f2e00db373', 'File not found: {{value0}}', {
+ value0: target.relativePath
+ })
+ )
return
}
if (stats.isDirectory) {
- toast.error(translate("auto.store.slices.editor.51f15c37d3", "Cannot open directory: {{value0}}", { value0: target.relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.51f15c37d3', 'Cannot open directory: {{value0}}', {
+ value0: target.relativePath
+ })
+ )
return
}
}
@@ -3716,11 +3725,19 @@ export const createEditorSlice: StateCreator = (s
try {
stats = await statRuntimePath(fileContext, absolutePath)
} catch {
- toast.error(translate("auto.store.slices.editor.f2e00db373", "File not found: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.f2e00db373', 'File not found: {{value0}}', {
+ value0: relativePath
+ })
+ )
return
}
if (stats.isDirectory) {
- toast.error(translate("auto.store.slices.editor.51f15c37d3", "Cannot open directory: {{value0}}", { value0: relativePath }))
+ toast.error(
+ translate('auto.store.slices.editor.51f15c37d3', 'Cannot open directory: {{value0}}', {
+ value0: relativePath
+ })
+ )
return
}
@@ -3988,7 +4005,10 @@ function toOpenConflictMetadata(entry: GitStatusEntry): OpenConflictMetadata | u
conflictKind: entry.conflictKind,
conflictStatus: entry.conflictStatus,
conflictStatusSource: entry.conflictStatusSource,
- message: translate("auto.store.slices.editor.dcb521ed29", "This file is in a conflict state, but no working-tree file is available to edit."),
+ message: translate(
+ 'auto.store.slices.editor.dcb521ed29',
+ 'This file is in a conflict state, but no working-tree file is available to edit.'
+ ),
guidance: 'Resolve the conflict in Git or restore one side before reopening it.'
}
}
diff --git a/src/renderer/src/store/slices/repos.ts b/src/renderer/src/store/slices/repos.ts
index 61618009e39..2488cd99081 100644
--- a/src/renderer/src/store/slices/repos.ts
+++ b/src/renderer/src/store/slices/repos.ts
@@ -285,9 +285,12 @@ export const createRepoSlice: StateCreator = (set,
return result
} catch (err) {
console.error('Failed to import nested repos:', err)
- toast.error(translate("auto.store.slices.repos.6d3318e813", "Failed to import repositories"), {
- description: err instanceof Error ? err.message : String(err)
- })
+ toast.error(
+ translate('auto.store.slices.repos.6d3318e813', 'Failed to import repositories'),
+ {
+ description: err instanceof Error ? err.message : String(err)
+ }
+ )
return null
}
},
@@ -453,18 +456,25 @@ export const createRepoSlice: StateCreator = (set,
return { repos: [...s.repos, repo] }
})
if (alreadyAdded) {
- toast.info(translate("auto.store.slices.repos.a8e4b3af5b", "Project already added"), { description: repo.displayName })
- } else {
- toast.success(isGitRepoKind(repo) ? translate("auto.store.slices.repos.8bb3ad7935", "Project added") : translate("auto.store.slices.repos.90d129b48b", "Folder added"), {
+ toast.info(translate('auto.store.slices.repos.a8e4b3af5b', 'Project already added'), {
description: repo.displayName
})
+ } else {
+ toast.success(
+ isGitRepoKind(repo)
+ ? translate('auto.store.slices.repos.8bb3ad7935', 'Project added')
+ : translate('auto.store.slices.repos.90d129b48b', 'Folder added'),
+ {
+ description: repo.displayName
+ }
+ )
}
return repo
} catch (err) {
console.error('Failed to add project:', err)
const message = err instanceof Error ? err.message : String(err)
const duration = ERROR_TOAST_DURATION
- toast.error(translate("auto.store.slices.repos.c6e022ddfc", "Failed to add project"), {
+ toast.error(translate('auto.store.slices.repos.c6e022ddfc', 'Failed to add project'), {
description: message,
duration
})
@@ -477,7 +487,12 @@ export const createRepoSlice: StateCreator = (set,
if (target.kind !== 'local') {
// Why: OS folder pickers return client-local paths. Remote environments
// need an explicit server path, which the Add Project dialog handles.
- toast.error(translate("auto.store.slices.repos.e649269645", "Use a server path to add projects from a remote runtime."))
+ toast.error(
+ translate(
+ 'auto.store.slices.repos.e649269645',
+ 'Use a server path to add projects from a remote runtime.'
+ )
+ )
return null
}
const path = await window.api.repos.pickFolder()
@@ -523,7 +538,10 @@ export const createRepoSlice: StateCreator = (set,
} catch (err) {
console.error('Failed to add folder:', err)
const message = err instanceof Error ? err.message : String(err)
- toast.error(translate("auto.store.slices.repos.b7e14472ae", "Failed to add folder"), { description: message, duration: ERROR_TOAST_DURATION })
+ toast.error(translate('auto.store.slices.repos.b7e14472ae', 'Failed to add folder'), {
+ description: message,
+ duration: ERROR_TOAST_DURATION
+ })
return null
}
},
diff --git a/src/renderer/src/store/slices/sparse-presets.ts b/src/renderer/src/store/slices/sparse-presets.ts
index 3c9a18a6e9a..5a111cad84d 100644
--- a/src/renderer/src/store/slices/sparse-presets.ts
+++ b/src/renderer/src/store/slices/sparse-presets.ts
@@ -74,10 +74,18 @@ export const createSparsePresetsSlice: StateCreator ({
sparsePresetsByRepo: { ...s.sparsePresetsByRepo, [repoId]: previous }
}))
const message = err instanceof Error ? err.message : String(err)
- toast.error(translate("auto.store.slices.sparse.presets.6ed7d6010a", "Failed to remove preset"), {
- description: message,
- duration: ERROR_TOAST_DURATION
- })
+ toast.error(
+ translate('auto.store.slices.sparse.presets.6ed7d6010a', 'Failed to remove preset'),
+ {
+ description: message,
+ duration: ERROR_TOAST_DURATION
+ }
+ )
// Why: settings UI keeps confirmation/edit state until persistence succeeds.
throw err
}
diff --git a/src/renderer/src/store/slices/store-test-helpers.ts b/src/renderer/src/store/slices/store-test-helpers.ts
index 77b60c8f5e9..e76a315529d 100644
--- a/src/renderer/src/store/slices/store-test-helpers.ts
+++ b/src/renderer/src/store/slices/store-test-helpers.ts
@@ -124,7 +124,7 @@ export function makeTab(
): TerminalTab {
return {
ptyId: null,
- title: translate("auto.store.slices.store.test.helpers.b9a8117c33", "Terminal 1"),
+ title: translate('auto.store.slices.store.test.helpers.b9a8117c33', 'Terminal 1'),
customTitle: null,
color: null,
sortOrder: 0,
@@ -156,7 +156,7 @@ export function makeUnifiedTab(
return {
entityId: overrides.id,
contentType: 'terminal',
- label: translate("auto.store.slices.store.test.helpers.b9a8117c33", "Terminal 1"),
+ label: translate('auto.store.slices.store.test.helpers.b9a8117c33', 'Terminal 1'),
customLabel: null,
color: null,
sortOrder: 0,
diff --git a/src/renderer/src/store/slices/ui.test.ts b/src/renderer/src/store/slices/ui.test.ts
index 074af763623..e6a6b1c609d 100644
--- a/src/renderer/src/store/slices/ui.test.ts
+++ b/src/renderer/src/store/slices/ui.test.ts
@@ -4,6 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { getDefaultUIState } from '../../../../shared/constants'
import type {
GitHubWorkItem,
+ LinearIssue,
PersistedUIState,
TerminalTab,
Worktree,
@@ -117,6 +118,26 @@ function makeGitHubWorkItem(overrides: Partial = {}): GitHubWork
}
}
+function makeLinearIssue(overrides: Partial = {}): LinearIssue {
+ return {
+ id: 'lin-1',
+ identifier: 'ORC-1',
+ title: 'Fix task flow',
+ url: 'https://linear.app/orca/issue/ORC-1/fix-task-flow',
+ state: { name: 'Todo', type: 'unstarted', color: '#999' },
+ priority: 0,
+ estimate: null,
+ assignee: null,
+ labels: [],
+ labelIds: [],
+ team: { id: 'team-1', name: 'Orca', key: 'ORC' },
+ workspaceId: 'workspace-1',
+ updatedAt: '2026-05-30T00:00:00.000Z',
+ createdAt: '2026-05-30T00:00:00.000Z',
+ ...overrides
+ } as LinearIssue
+}
+
function makePersistedUI(overrides: Partial = {}): PersistedUIState {
return {
...getDefaultUIState(),
@@ -1368,6 +1389,46 @@ describe('createUISlice page navigation history', () => {
expect(store.getState().worktreeNavHistoryIndex).toBe(0)
})
+ it('records provider-depth interactions for direct Tasks detail opens', () => {
+ const store = createUIStore()
+ const recordFeatureInteraction = vi.fn()
+ store.setState({ recordFeatureInteraction } as Partial)
+ const workItem = makeGitHubWorkItem()
+ const linearIssue = makeLinearIssue()
+
+ store.getState().openTaskPage({ taskSource: 'github', openGitHubWorkItem: workItem })
+ store.getState().openTaskPage({ taskSource: 'linear', openLinearIssue: linearIssue })
+
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('github-tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('linear-tasks')
+ })
+
+ it('can suppress the Tasks surface interaction for in-page provider navigation', () => {
+ const store = createUIStore()
+ const recordFeatureInteraction = vi.fn()
+ store.setState({ recordFeatureInteraction } as Partial)
+ const workItem = makeGitHubWorkItem()
+ const linearIssue = makeLinearIssue()
+
+ store
+ .getState()
+ .openTaskPage(
+ { taskSource: 'github', openGitHubWorkItem: workItem },
+ { recordTasksInteraction: false }
+ )
+ store
+ .getState()
+ .openTaskPage(
+ { taskSource: 'linear', openLinearIssue: linearIssue },
+ { recordTasksInteraction: false }
+ )
+
+ expect(recordFeatureInteraction).not.toHaveBeenCalledWith('tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('github-tasks')
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('linear-tasks')
+ })
+
it('skips the whole Tasks detail stack on close', () => {
const store = createUIStore()
const workItem = makeGitHubWorkItem()
diff --git a/src/renderer/src/store/slices/ui.ts b/src/renderer/src/store/slices/ui.ts
index 38c30e43fb5..4c90d1f0abe 100644
--- a/src/renderer/src/store/slices/ui.ts
+++ b/src/renderer/src/store/slices/ui.ts
@@ -634,7 +634,10 @@ export type UISlice = {
// Absent means "use the repo's effective base ref".
baseBranch?: string
} | null
- openTaskPage: (data?: UISlice['taskPageData']) => void
+ openTaskPage: (
+ data?: UISlice['taskPageData'],
+ options?: { recordTasksInteraction?: boolean }
+ ) => void
closeTaskPage: () => void
openActivityPage: () => void
closeActivityPage: () => void
@@ -693,6 +696,7 @@ export type UISlice = {
activeContextualTourSource: string | null
activeContextualTourSourceDetached: boolean
activeContextualTourWasFeaturePreviouslyInteracted: boolean
+ contextualTourNavigationInteractionSnapshot: Partial>
activeContextualTourSuppressed: boolean
contextualTourShownThisSession: boolean
contextualToursOnboardingVisible: boolean
@@ -1050,7 +1054,23 @@ export const createUISlice: StateCreator = (set, get)
taskResumeState: undefined,
githubTaskDrawerWorkItem: null,
newWorkspaceDraft: null,
- openTaskPage: (data = {}) => {
+ openTaskPage: (data = {}, options = {}) => {
+ if (options.recordTasksInteraction !== false) {
+ const wasTasksPreviouslyInteracted = hasFeatureInteraction(get().featureInteractions, 'tasks')
+ set((state) => ({
+ contextualTourNavigationInteractionSnapshot: {
+ ...state.contextualTourNavigationInteractionSnapshot,
+ tasks: wasTasksPreviouslyInteracted
+ }
+ }))
+ get().recordFeatureInteraction?.('tasks')
+ }
+ if (data.openGitHubWorkItem) {
+ get().recordFeatureInteraction?.('github-tasks')
+ }
+ if (data.openLinearIssue) {
+ get().recordFeatureInteraction?.('linear-tasks')
+ }
// Why: record a Tasks visit in the shared back/forward history so the
// titlebar Back/Forward buttons can return to Tasks. All task-source
// variants (github/linear presets) collapse to a single 'tasks' entry;
@@ -1389,6 +1409,7 @@ export const createUISlice: StateCreator = (set, get)
activeContextualTourSource: null,
activeContextualTourSourceDetached: false,
activeContextualTourWasFeaturePreviouslyInteracted: false,
+ contextualTourNavigationInteractionSnapshot: {},
activeContextualTourSuppressed: false,
contextualTourShownThisSession: false,
contextualToursOnboardingVisible: false,
@@ -1432,15 +1453,28 @@ export const createUISlice: StateCreator = (set, get)
targetExists: hasContextualTourTarget
})
if (decision.kind !== 'start') {
- return s
+ if (s.contextualTourNavigationInteractionSnapshot[id] === undefined) {
+ return s
+ }
+ const { [id]: _consumed, ...remainingNavigationSnapshot } =
+ s.contextualTourNavigationInteractionSnapshot
+ void _consumed
+ return { contextualTourNavigationInteractionSnapshot: remainingNavigationSnapshot }
}
+ const navigationSnapshot = s.contextualTourNavigationInteractionSnapshot[id]
+ const { [id]: _consumed, ...remainingNavigationSnapshot } =
+ s.contextualTourNavigationInteractionSnapshot
+ void _consumed
return {
activeContextualTourId: id,
activeContextualTourStepIndex: decision.stepIndex,
activeContextualTourSource: source,
activeContextualTourSourceDetached: false,
activeContextualTourWasFeaturePreviouslyInteracted:
- wasFeaturePreviouslyInteracted ?? hasFeatureInteraction(s.featureInteractions, id),
+ wasFeaturePreviouslyInteracted ??
+ navigationSnapshot ??
+ hasFeatureInteraction(s.featureInteractions, id),
+ contextualTourNavigationInteractionSnapshot: remainingNavigationSnapshot,
activeContextualTourSuppressed: false,
contextualTourShownThisSession: true,
lastCompletedContextualTourId: null
diff --git a/src/renderer/src/store/slices/workspace-cleanup.ts b/src/renderer/src/store/slices/workspace-cleanup.ts
index 9f3fb4e069d..159e0b50b40 100644
--- a/src/renderer/src/store/slices/workspace-cleanup.ts
+++ b/src/renderer/src/store/slices/workspace-cleanup.ts
@@ -398,7 +398,10 @@ async function preflightWorkspaceCleanupCandidate(
failure: {
worktreeId,
displayName: worktreeId,
- message: translate("auto.store.slices.workspace.cleanup.9d6e531da6", "Workspace no longer exists.")
+ message: translate(
+ 'auto.store.slices.workspace.cleanup.9d6e531da6',
+ 'Workspace no longer exists.'
+ )
}
}
}
diff --git a/src/renderer/src/web/WebConnect.tsx b/src/renderer/src/web/WebConnect.tsx
index 3d2bf010bcd..9a6709e04e1 100644
--- a/src/renderer/src/web/WebConnect.tsx
+++ b/src/renderer/src/web/WebConnect.tsx
@@ -78,14 +78,22 @@ export default function WebConnect({
-
{translate("auto.web.WebConnect.e3bcd082ac", "Connect to Orca")}
+
+ {translate('auto.web.WebConnect.e3bcd082ac', 'Connect to Orca')}
+
- {translate("auto.web.WebConnect.3affe7de3a", "Paste a pairing URL from an Orca server that this browser can reach.")}
+ {translate(
+ 'auto.web.WebConnect.3affe7de3a',
+ 'Paste a pairing URL from an Orca server that this browser can reach.'
+ )}
+
-
{translate("auto.web.WebConnect.cb4d287238", "Server name")}
+
+ {translate('auto.web.WebConnect.cb4d287238', 'Server name')}
+
-
{translate("auto.web.WebConnect.7a566540de", "Pairing URL or code")}
+
+ {translate('auto.web.WebConnect.7a566540de', 'Pairing URL or code')}
+
setPairingCode(event.target.value)}
- placeholder={translate("auto.web.WebConnect.27393856e4", "orca://pair?code=...")}
+ placeholder={translate('auto.web.WebConnect.27393856e4', 'orca://pair?code=...')}
autoComplete="off"
spellCheck={false}
/>
@@ -108,7 +118,7 @@ export default function WebConnect({
{parsedOffer && (
- {translate("auto.web.WebConnect.4a4c017be1", "Endpoint:")} {parsedOffer.endpoint}
+ {translate('auto.web.WebConnect.4a4c017be1', 'Endpoint:')} {parsedOffer.endpoint}
)}
@@ -121,7 +131,8 @@ export default function WebConnect({
- {translate("auto.web.WebConnect.2cf9e5a294", "Clear saved server")}
+ {translate('auto.web.WebConnect.2cf9e5a294', 'Clear saved server')}
+
void connect()}
@@ -133,7 +144,8 @@ export default function WebConnect({
) : (
)}
- {translate("auto.web.WebConnect.b411ec0069", "Connect")}
+ {translate('auto.web.WebConnect.b411ec0069', 'Connect')}
+
diff --git a/src/renderer/src/web/main.tsx b/src/renderer/src/web/main.tsx
index 30ad178b2cd..6ebb49937ea 100644
--- a/src/renderer/src/web/main.tsx
+++ b/src/renderer/src/web/main.tsx
@@ -58,7 +58,10 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
boundaryId="web.root"
surface="web-root"
title={translate('app.recoverableError.webTitle', 'Orca web hit a renderer error.')}
- description={translate('app.recoverableError.webDescription', 'Retry the web client or reconnect to the paired runtime.')}
+ description={translate(
+ 'app.recoverableError.webDescription',
+ 'Retry the web client or reconnect to the paired runtime.'
+ )}
>
diff --git a/src/renderer/src/web/web-preload-api.test.ts b/src/renderer/src/web/web-preload-api.test.ts
index 5ebce3603e9..b060df6b51b 100644
--- a/src/renderer/src/web/web-preload-api.test.ts
+++ b/src/renderer/src/web/web-preload-api.test.ts
@@ -159,7 +159,7 @@ describe('web keybindings preload API', () => {
bindings: null
})
expect(reset.overrides['worktree.palette']).toBeUndefined()
- })
+ }, 15_000)
it('rejects conflicts before mutating browser storage', async () => {
const { api } = await installApi('Linux')
@@ -782,6 +782,46 @@ describe('web UI preload API', () => {
expect(stored.contextualToursSeenIds).toEqual(['tasks', 'browser'])
})
+ it('does not keep a local shadow copy of main-owned feature telemetry markers', async () => {
+ vi.doMock('./web-runtime-client', () => ({
+ WebRuntimeClient: class {
+ call(method: string): Promise> {
+ return Promise.resolve({
+ id: method,
+ ok: true,
+ result: { ui: {} },
+ _meta: { runtimeId: 'runtime-1' }
+ })
+ }
+
+ close(): void {}
+ }
+ }))
+
+ const globals = installBrowserGlobals('Linux')
+ writeStoredRuntimeEnvironment(globals.storage)
+ globals.storage.setItem(
+ 'orca.web.ui.v1',
+ JSON.stringify({
+ featureInteractionTelemetryBuckets: { tasks: 'count_1000_plus' }
+ })
+ )
+ const { installWebPreloadApi } = await import('./web-preload-api')
+ installWebPreloadApi()
+
+ await globals.window.api.ui.set({
+ featureInteractionTelemetryBuckets: { tasks: 'count_500_999' }
+ } as never)
+ const ui = await globals.window.api.ui.get()
+ const stored = JSON.parse(globals.storage.getItem('orca.web.ui.v1') ?? '{}') as Record<
+ string,
+ unknown
+ >
+
+ expect('featureInteractionTelemetryBuckets' in (ui as Record)).toBe(false)
+ expect(stored.featureInteractionTelemetryBuckets).toBeUndefined()
+ })
+
it('union-merges local contextual tour seen ids when recordFeatureInteraction returns stale host state', async () => {
vi.doMock('./web-runtime-client', () => ({
WebRuntimeClient: class {
diff --git a/src/renderer/src/web/web-preload-api.ts b/src/renderer/src/web/web-preload-api.ts
index d99cf3b6473..099e95d39b6 100644
--- a/src/renderer/src/web/web-preload-api.ts
+++ b/src/renderer/src/web/web-preload-api.ts
@@ -2605,11 +2605,16 @@ function mergeWebUIState(
base: PersistedUIState,
updates: Partial
): PersistedUIState {
+ const { featureInteractionTelemetryBuckets: _reserved, ...safeUpdates } =
+ updates as Partial & {
+ featureInteractionTelemetryBuckets?: unknown
+ }
+ void _reserved
return {
...base,
- ...updates,
+ ...safeUpdates,
agentActivityDisplayMode: normalizeAgentActivityDisplayMode(
- updates.agentActivityDisplayMode ?? base.agentActivityDisplayMode
+ safeUpdates.agentActivityDisplayMode ?? base.agentActivityDisplayMode
)
}
}
diff --git a/src/renderer/src/web/web-runtime-environment.ts b/src/renderer/src/web/web-runtime-environment.ts
index 30b1fa72cf2..ea378cb8c90 100644
--- a/src/renderer/src/web/web-runtime-environment.ts
+++ b/src/renderer/src/web/web-runtime-environment.ts
@@ -58,7 +58,7 @@ export function createStoredWebRuntimeEnvironment(args: {
{
id: `ws-${id}`,
kind: 'websocket',
- label: translate("auto.web.web.runtime.environment.07f788de83", "WebSocket"),
+ label: translate('auto.web.web.runtime.environment.07f788de83', 'WebSocket'),
endpoint: args.offer.endpoint,
deviceToken: args.offer.deviceToken,
publicKeyB64: args.offer.publicKeyB64
diff --git a/src/shared/constants.ts b/src/shared/constants.ts
index 78d1c3e850f..4d330aa5823 100644
--- a/src/shared/constants.ts
+++ b/src/shared/constants.ts
@@ -391,7 +391,8 @@ export function getDefaultPersistedState(homedir: string): PersistedState {
legacyPaneKeyAliasEntries: [],
automations: [],
automationRuns: [],
- onboarding: getDefaultOnboardingState()
+ onboarding: getDefaultOnboardingState(),
+ featureInteractionTelemetryBuckets: {}
}
}
diff --git a/src/shared/feature-interaction-catalog.ts b/src/shared/feature-interaction-catalog.ts
new file mode 100644
index 00000000000..917a9295b65
--- /dev/null
+++ b/src/shared/feature-interaction-catalog.ts
@@ -0,0 +1,162 @@
+export type FeatureInteractionId =
+ | 'workspace-board'
+ | 'workspace-agent-sessions'
+ | 'workspace-board-actions'
+ | 'cmd-j'
+ | 'cmd-j-workspace-open'
+ | 'cmd-j-browser-page-open'
+ | 'cmd-j-settings-open'
+ | 'cmd-j-quick-action'
+ | 'cmd-j-create-workspace'
+ | 'browser'
+ | 'browser-tab-created'
+ | 'tasks'
+ | 'github-tasks'
+ | 'gitlab-tasks'
+ | 'linear-tasks'
+ | 'automations'
+ | 'automation-created'
+ | 'automation-run'
+ | 'browser-annotations'
+ | 'browser-annotations-sent-to-agent'
+ | 'browser-grab'
+ | 'markdown-file-created'
+ | 'workspace-creation'
+ | 'agent-browser-setup'
+ | 'agent-browser-use'
+ | 'agent-orchestration-setup'
+ | 'agent-orchestration'
+ | 'ai-commit-generation'
+ | 'ai-pr-generation'
+ | 'claude-account-switching'
+ | 'computer-use-setup'
+ | 'computer-use'
+ | 'codex-account-switching'
+ | 'cookie-import'
+ | 'floating-workspace'
+ | 'floating-workspace-hidden'
+ | 'mobile-pairing'
+ | 'notifications'
+ | 'ports'
+ | 'quick-commands'
+ | 'resource-manager'
+ | 'review-notes'
+ | 'ssh'
+ | 'terminal-pane-split'
+ | 'terminal-panes'
+ | 'terminal-tabs'
+ | 'tab-splits'
+ | 'usage-tracking'
+ | 'voice-dictation'
+ | 'workspace-cleanup'
+
+export type FeatureInteractionDefinition = {
+ id: FeatureInteractionId
+ /** The product action that counts as "the user has interacted with this feature." */
+ interaction: string
+}
+
+// Why: these ids become persisted product state; see
+// docs/reference/feature-discovery-interaction-tracking.md before changing them.
+export const FEATURE_INTERACTIONS = [
+ { id: 'workspace-board', interaction: 'workspace board opened' },
+ {
+ id: 'workspace-agent-sessions',
+ interaction: 'workspace agent-session surface opened'
+ },
+ {
+ id: 'workspace-board-actions',
+ interaction: 'workspace board card, lane, density, or status action used'
+ },
+ { id: 'cmd-j', interaction: 'Cmd+J palette opened' },
+ { id: 'cmd-j-workspace-open', interaction: 'workspace opened from Cmd+J' },
+ { id: 'cmd-j-browser-page-open', interaction: 'browser page opened from Cmd+J' },
+ { id: 'cmd-j-settings-open', interaction: 'settings opened from Cmd+J' },
+ { id: 'cmd-j-quick-action', interaction: 'quick action run from Cmd+J' },
+ { id: 'cmd-j-create-workspace', interaction: 'workspace creation started from Cmd+J' },
+ { id: 'browser', interaction: 'in-app browser opened' },
+ { id: 'browser-tab-created', interaction: 'browser tab explicitly created' },
+ { id: 'tasks', interaction: 'Tasks page opened' },
+ { id: 'github-tasks', interaction: 'GitHub task item workflow used' },
+ { id: 'gitlab-tasks', interaction: 'GitLab task item workflow used' },
+ { id: 'linear-tasks', interaction: 'Linear task item workflow used' },
+ { id: 'automations', interaction: 'Automations page opened' },
+ { id: 'automation-created', interaction: 'automation created' },
+ { id: 'automation-run', interaction: 'automation run queued' },
+ { id: 'browser-annotations', interaction: 'browser annotation added, copied, or cleared' },
+ {
+ id: 'browser-annotations-sent-to-agent',
+ interaction: 'browser annotations sent to an agent'
+ },
+ { id: 'browser-grab', interaction: 'browser element grab or screenshot used' },
+ { id: 'markdown-file-created', interaction: 'untitled markdown file explicitly created' },
+ { id: 'workspace-creation', interaction: 'workspace creation flow opened' },
+ { id: 'agent-browser-setup', interaction: 'Agent Browser Use setup enabled or opened' },
+ { id: 'agent-browser-use', interaction: 'agent browser runtime method used' },
+ {
+ id: 'agent-orchestration-setup',
+ interaction: 'Agent Orchestration setup enabled or opened'
+ },
+ { id: 'agent-orchestration', interaction: 'agent orchestration runtime method used' },
+ {
+ id: 'ai-commit-generation',
+ interaction: 'AI commit message generation enabled or used'
+ },
+ { id: 'ai-pr-generation', interaction: 'AI pull request generation used' },
+ {
+ id: 'claude-account-switching',
+ interaction: 'Claude managed account added, selected, reauthenticated, or removed'
+ },
+ {
+ id: 'computer-use-setup',
+ interaction: 'Computer Use setup or permission flow opened'
+ },
+ { id: 'computer-use', interaction: 'computer-use runtime method used' },
+ {
+ id: 'codex-account-switching',
+ interaction: 'Codex managed account added, selected, reauthenticated, or removed'
+ },
+ { id: 'cookie-import', interaction: 'browser cookies imported or cleared' },
+ { id: 'floating-workspace', interaction: 'Floating Workspace opened or configured' },
+ {
+ id: 'floating-workspace-hidden',
+ interaction: 'Floating Workspace explicitly hidden or disabled'
+ },
+ { id: 'mobile-pairing', interaction: 'mobile pairing enabled or QR code generated' },
+ { id: 'notifications', interaction: 'desktop notifications enabled or tested' },
+ { id: 'ports', interaction: 'Ports popover opened, configured, or port action used' },
+ { id: 'quick-commands', interaction: 'terminal quick command created or edited' },
+ { id: 'resource-manager', interaction: 'Resource Manager opened or configured' },
+ { id: 'review-notes', interaction: 'review note added or sent to an agent' },
+ {
+ id: 'ssh',
+ interaction: 'SSH target added, imported, tested, connected, disconnected, or configured'
+ },
+ {
+ id: 'terminal-pane-split',
+ interaction: 'terminal pane split from the split-pane command'
+ },
+ {
+ id: 'terminal-panes',
+ interaction: 'terminal/editor/browser pane created, resized, or merged'
+ },
+ {
+ id: 'terminal-tabs',
+ interaction: 'workspace tab created, moved, reordered, pinned, renamed, recolored, or closed'
+ },
+ { id: 'tab-splits', interaction: 'workspace tab split into another pane' },
+ {
+ id: 'usage-tracking',
+ interaction: 'Stats & Usage or provider usage details opened or configured'
+ },
+ { id: 'voice-dictation', interaction: 'dictation session started' },
+ {
+ id: 'workspace-cleanup',
+ interaction: 'workspace disk space scan, review, or cleanup action used'
+ }
+] as const satisfies readonly FeatureInteractionDefinition[]
+
+export const FEATURE_INTERACTION_IDS = FEATURE_INTERACTIONS.map((feature) => feature.id) as [
+ FeatureInteractionId,
+ ...FeatureInteractionId[]
+]
diff --git a/src/shared/feature-interaction-categories.ts b/src/shared/feature-interaction-categories.ts
new file mode 100644
index 00000000000..72b05ceca7e
--- /dev/null
+++ b/src/shared/feature-interaction-categories.ts
@@ -0,0 +1,79 @@
+import type { FeatureInteractionId } from './feature-interaction-catalog'
+
+export const FEATURE_INTERACTION_CATEGORIES = [
+ 'workspace',
+ 'agent',
+ 'browser',
+ 'launcher',
+ 'task_management',
+ 'notes',
+ 'review',
+ 'setup',
+ 'settings',
+ 'automation',
+ 'terminal',
+ 'collaboration',
+ 'resource_management',
+ 'voice',
+ 'source_control'
+] as const
+export type FeatureInteractionCategory = (typeof FEATURE_INTERACTION_CATEGORIES)[number]
+
+export const FEATURE_INTERACTION_CATEGORY_BY_ID = {
+ 'workspace-board': 'workspace',
+ 'workspace-agent-sessions': 'workspace',
+ 'workspace-board-actions': 'workspace',
+ 'cmd-j': 'launcher',
+ 'cmd-j-workspace-open': 'launcher',
+ 'cmd-j-browser-page-open': 'launcher',
+ 'cmd-j-settings-open': 'launcher',
+ 'cmd-j-quick-action': 'launcher',
+ 'cmd-j-create-workspace': 'launcher',
+ browser: 'browser',
+ 'browser-tab-created': 'browser',
+ tasks: 'task_management',
+ 'github-tasks': 'task_management',
+ 'gitlab-tasks': 'task_management',
+ 'linear-tasks': 'task_management',
+ automations: 'automation',
+ 'automation-created': 'automation',
+ 'automation-run': 'automation',
+ 'browser-annotations': 'browser',
+ 'browser-annotations-sent-to-agent': 'browser',
+ 'browser-grab': 'browser',
+ 'markdown-file-created': 'notes',
+ 'workspace-creation': 'workspace',
+ 'agent-browser-setup': 'setup',
+ 'agent-browser-use': 'agent',
+ 'agent-orchestration-setup': 'setup',
+ 'agent-orchestration': 'collaboration',
+ 'ai-commit-generation': 'source_control',
+ 'ai-pr-generation': 'source_control',
+ 'claude-account-switching': 'settings',
+ 'computer-use-setup': 'setup',
+ 'computer-use': 'agent',
+ 'codex-account-switching': 'settings',
+ 'cookie-import': 'browser',
+ 'floating-workspace': 'workspace',
+ 'floating-workspace-hidden': 'workspace',
+ 'mobile-pairing': 'collaboration',
+ notifications: 'settings',
+ ports: 'resource_management',
+ 'quick-commands': 'launcher',
+ 'resource-manager': 'resource_management',
+ 'review-notes': 'review',
+ ssh: 'setup',
+ 'terminal-pane-split': 'terminal',
+ 'terminal-panes': 'terminal',
+ 'terminal-tabs': 'terminal',
+ 'tab-splits': 'terminal',
+ 'usage-tracking': 'settings',
+ 'voice-dictation': 'voice',
+ 'workspace-cleanup': 'workspace'
+} as const satisfies Record
+
+export function getFeatureInteractionCategory(
+ id: FeatureInteractionId
+): FeatureInteractionCategory {
+ return FEATURE_INTERACTION_CATEGORY_BY_ID[id]
+}
diff --git a/src/shared/feature-interaction-usage-buckets.ts b/src/shared/feature-interaction-usage-buckets.ts
new file mode 100644
index 00000000000..692eacadcfe
--- /dev/null
+++ b/src/shared/feature-interaction-usage-buckets.ts
@@ -0,0 +1,69 @@
+export const FEATURE_INTERACTION_USAGE_BUCKETS = [
+ 'count_1',
+ 'count_2',
+ 'count_3_4',
+ 'count_5_9',
+ 'count_10_19',
+ 'count_20_49',
+ 'count_50_99',
+ 'count_100_199',
+ 'count_200_499',
+ 'count_500_999',
+ 'count_1000_plus'
+] as const
+export type FeatureInteractionUsageBucket = (typeof FEATURE_INTERACTION_USAGE_BUCKETS)[number]
+
+export const FEATURE_INTERACTION_USAGE_BUCKET_SPECS = [
+ { bucket: 'count_1', min: 1 },
+ { bucket: 'count_2', min: 2 },
+ { bucket: 'count_3_4', min: 3 },
+ { bucket: 'count_5_9', min: 5 },
+ { bucket: 'count_10_19', min: 10 },
+ { bucket: 'count_20_49', min: 20 },
+ { bucket: 'count_50_99', min: 50 },
+ { bucket: 'count_100_199', min: 100 },
+ { bucket: 'count_200_499', min: 200 },
+ { bucket: 'count_500_999', min: 500 },
+ { bucket: 'count_1000_plus', min: 1000 }
+] as const satisfies readonly {
+ bucket: FeatureInteractionUsageBucket
+ min: number
+}[]
+
+const FEATURE_INTERACTION_USAGE_BUCKET_INDEX = new Map(
+ FEATURE_INTERACTION_USAGE_BUCKETS.map((bucket, index) => [bucket, index])
+)
+
+export function getFeatureInteractionUsageBucket(
+ count: number
+): FeatureInteractionUsageBucket | null {
+ if (!Number.isInteger(count) || count <= 0) {
+ return null
+ }
+ let bucket: FeatureInteractionUsageBucket | null = null
+ for (const spec of FEATURE_INTERACTION_USAGE_BUCKET_SPECS) {
+ if (count >= spec.min) {
+ bucket = spec.bucket
+ }
+ }
+ return bucket
+}
+
+export function compareFeatureInteractionUsageBuckets(
+ a: FeatureInteractionUsageBucket,
+ b: FeatureInteractionUsageBucket
+): number {
+ return (
+ (FEATURE_INTERACTION_USAGE_BUCKET_INDEX.get(a) ?? -1) -
+ (FEATURE_INTERACTION_USAGE_BUCKET_INDEX.get(b) ?? -1)
+ )
+}
+
+export function isFeatureInteractionUsageBucket(
+ value: unknown
+): value is FeatureInteractionUsageBucket {
+ return (
+ typeof value === 'string' &&
+ FEATURE_INTERACTION_USAGE_BUCKETS.includes(value as FeatureInteractionUsageBucket)
+ )
+}
diff --git a/src/shared/feature-interactions.test.ts b/src/shared/feature-interactions.test.ts
index ba9987280db..3778f979925 100644
--- a/src/shared/feature-interactions.test.ts
+++ b/src/shared/feature-interactions.test.ts
@@ -3,7 +3,12 @@ import { join, relative } from 'node:path'
import { describe, expect, it } from 'vitest'
import {
FEATURE_INTERACTIONS,
+ FEATURE_INTERACTION_CATEGORIES,
+ FEATURE_INTERACTION_CATEGORY_BY_ID,
+ FEATURE_INTERACTION_USAGE_BUCKETS,
+ getFeatureInteractionUsageBucket,
hasFeatureInteraction,
+ normalizeFeatureInteractionTelemetryBuckets,
normalizeFeatureInteractions,
type FeatureInteractionId
} from './feature-interactions'
@@ -29,13 +34,25 @@ describe('feature interactions', () => {
'workspace-board',
'workspace-agent-sessions',
'workspace-board-actions',
+ 'cmd-j',
+ 'cmd-j-workspace-open',
+ 'cmd-j-browser-page-open',
+ 'cmd-j-settings-open',
+ 'cmd-j-quick-action',
+ 'cmd-j-create-workspace',
'browser',
+ 'browser-tab-created',
'tasks',
+ 'github-tasks',
+ 'gitlab-tasks',
+ 'linear-tasks',
'automations',
'automation-created',
'automation-run',
'browser-annotations',
+ 'browser-annotations-sent-to-agent',
'browser-grab',
+ 'markdown-file-created',
'workspace-creation',
'agent-browser-setup',
'agent-browser-use',
@@ -49,6 +66,7 @@ describe('feature interactions', () => {
'codex-account-switching',
'cookie-import',
'floating-workspace',
+ 'floating-workspace-hidden',
'mobile-pairing',
'notifications',
'ports',
@@ -105,6 +123,77 @@ describe('feature interactions', () => {
).toBe(false)
})
+ it('maps interaction counts to the exact top-coded telemetry buckets', () => {
+ expect(FEATURE_INTERACTION_USAGE_BUCKETS).toEqual([
+ 'count_1',
+ 'count_2',
+ 'count_3_4',
+ 'count_5_9',
+ 'count_10_19',
+ 'count_20_49',
+ 'count_50_99',
+ 'count_100_199',
+ 'count_200_499',
+ 'count_500_999',
+ 'count_1000_plus'
+ ])
+ expect(getFeatureInteractionUsageBucket(0)).toBeNull()
+ expect(getFeatureInteractionUsageBucket(1)).toBe('count_1')
+ expect(getFeatureInteractionUsageBucket(2)).toBe('count_2')
+ expect(getFeatureInteractionUsageBucket(3)).toBe('count_3_4')
+ expect(getFeatureInteractionUsageBucket(4)).toBe('count_3_4')
+ expect(getFeatureInteractionUsageBucket(5)).toBe('count_5_9')
+ expect(getFeatureInteractionUsageBucket(999)).toBe('count_500_999')
+ expect(getFeatureInteractionUsageBucket(1000)).toBe('count_1000_plus')
+ expect(getFeatureInteractionUsageBucket(1001)).toBe('count_1000_plus')
+ })
+
+ it('covers every feature id with a telemetry category', () => {
+ expect(FEATURE_INTERACTION_CATEGORIES).toEqual([
+ 'workspace',
+ 'agent',
+ 'browser',
+ 'launcher',
+ 'task_management',
+ 'notes',
+ 'review',
+ 'setup',
+ 'settings',
+ 'automation',
+ 'terminal',
+ 'collaboration',
+ 'resource_management',
+ 'voice',
+ 'source_control'
+ ])
+ expect(Object.keys(FEATURE_INTERACTION_CATEGORY_BY_ID).sort()).toEqual(
+ FEATURE_INTERACTIONS.map((feature) => feature.id).sort()
+ )
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID.tasks).toBe('task_management')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['github-tasks']).toBe('task_management')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['markdown-file-created']).toBe('notes')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['agent-browser-setup']).toBe('setup')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['terminal-tabs']).toBe('terminal')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['voice-dictation']).toBe('voice')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['ai-commit-generation']).toBe('source_control')
+ expect(FEATURE_INTERACTION_CATEGORY_BY_ID['resource-manager']).toBe('resource_management')
+ })
+
+ it('normalizes persisted telemetry bucket markers by removing unknown ids and buckets', () => {
+ expect(
+ normalizeFeatureInteractionTelemetryBuckets({
+ tasks: 'count_1',
+ browser: 'count_1000_plus',
+ automations: 'count_4',
+ unknown: 'count_1',
+ 'voice-dictation': null
+ })
+ ).toEqual({
+ tasks: 'count_1',
+ browser: 'count_1000_plus'
+ })
+ })
+
it('keeps every catalog id wired to a production writer', () => {
const productionText = collectProductionSourceText()
const missingWriters = FEATURE_INTERACTIONS.map((feature) => feature.id).filter((id) => {
@@ -122,7 +211,7 @@ describe('feature interactions', () => {
})
expect(missingWriters).toEqual([])
- })
+ }, 15_000)
})
function collectProductionSourceText(): string {
diff --git a/src/shared/feature-interactions.ts b/src/shared/feature-interactions.ts
index 45abcea76be..fb995bc5e5e 100644
--- a/src/shared/feature-interactions.ts
+++ b/src/shared/feature-interactions.ts
@@ -1,47 +1,29 @@
-export type FeatureInteractionId =
- | 'workspace-board'
- | 'workspace-agent-sessions'
- | 'workspace-board-actions'
- | 'browser'
- | 'tasks'
- | 'automations'
- | 'automation-created'
- | 'automation-run'
- | 'browser-annotations'
- | 'browser-grab'
- | 'workspace-creation'
- | 'agent-browser-setup'
- | 'agent-browser-use'
- | 'agent-orchestration-setup'
- | 'agent-orchestration'
- | 'ai-commit-generation'
- | 'ai-pr-generation'
- | 'claude-account-switching'
- | 'computer-use-setup'
- | 'computer-use'
- | 'codex-account-switching'
- | 'cookie-import'
- | 'floating-workspace'
- | 'mobile-pairing'
- | 'notifications'
- | 'ports'
- | 'quick-commands'
- | 'resource-manager'
- | 'review-notes'
- | 'ssh'
- | 'terminal-pane-split'
- | 'terminal-panes'
- | 'terminal-tabs'
- | 'tab-splits'
- | 'usage-tracking'
- | 'voice-dictation'
- | 'workspace-cleanup'
+import { FEATURE_INTERACTION_IDS, type FeatureInteractionId } from './feature-interaction-catalog'
+import {
+ isFeatureInteractionUsageBucket,
+ type FeatureInteractionUsageBucket
+} from './feature-interaction-usage-buckets'
-export type FeatureInteractionDefinition = {
- id: FeatureInteractionId
- /** The product action that counts as "the user has interacted with this feature." */
- interaction: string
-}
+export {
+ FEATURE_INTERACTIONS,
+ FEATURE_INTERACTION_IDS,
+ type FeatureInteractionDefinition,
+ type FeatureInteractionId
+} from './feature-interaction-catalog'
+export {
+ FEATURE_INTERACTION_CATEGORIES,
+ FEATURE_INTERACTION_CATEGORY_BY_ID,
+ getFeatureInteractionCategory,
+ type FeatureInteractionCategory
+} from './feature-interaction-categories'
+export {
+ compareFeatureInteractionUsageBuckets,
+ FEATURE_INTERACTION_USAGE_BUCKETS,
+ FEATURE_INTERACTION_USAGE_BUCKET_SPECS,
+ getFeatureInteractionUsageBucket,
+ isFeatureInteractionUsageBucket,
+ type FeatureInteractionUsageBucket
+} from './feature-interaction-usage-buckets'
export type FeatureInteractionRecord = {
/** Unix timestamp in milliseconds for the first local interaction. */
@@ -54,160 +36,9 @@ export type FeatureInteractionState = Partial<
Record
>
-// Why: these ids become persisted product state; see
-// docs/reference/feature-discovery-interaction-tracking.md before changing them.
-export const FEATURE_INTERACTIONS = [
- {
- id: 'workspace-board',
- interaction: 'workspace board opened'
- },
- {
- id: 'workspace-agent-sessions',
- interaction: 'workspace agent-session surface opened'
- },
- {
- id: 'workspace-board-actions',
- interaction: 'workspace board card, lane, density, or status action used'
- },
- {
- id: 'browser',
- interaction: 'in-app browser opened'
- },
- {
- id: 'tasks',
- interaction: 'Tasks page opened'
- },
- {
- id: 'automations',
- interaction: 'Automations page opened'
- },
- {
- id: 'automation-created',
- interaction: 'automation created'
- },
- {
- id: 'automation-run',
- interaction: 'automation run queued'
- },
- {
- id: 'browser-annotations',
- interaction: 'browser annotation added, copied, or cleared'
- },
- {
- id: 'browser-grab',
- interaction: 'browser element grab or screenshot used'
- },
- {
- id: 'workspace-creation',
- interaction: 'workspace creation flow opened'
- },
- {
- id: 'agent-browser-setup',
- interaction: 'Agent Browser Use setup enabled or opened'
- },
- {
- id: 'agent-browser-use',
- interaction: 'agent browser runtime method used'
- },
- {
- id: 'agent-orchestration-setup',
- interaction: 'Agent Orchestration setup enabled or opened'
- },
- {
- id: 'agent-orchestration',
- interaction: 'agent orchestration runtime method used'
- },
- {
- id: 'ai-commit-generation',
- interaction: 'AI commit message generation enabled or used'
- },
- {
- id: 'ai-pr-generation',
- interaction: 'AI pull request generation used'
- },
- {
- id: 'claude-account-switching',
- interaction: 'Claude managed account added, selected, reauthenticated, or removed'
- },
- {
- id: 'computer-use-setup',
- interaction: 'Computer Use setup or permission flow opened'
- },
- {
- id: 'computer-use',
- interaction: 'computer-use runtime method used'
- },
- {
- id: 'codex-account-switching',
- interaction: 'Codex managed account added, selected, reauthenticated, or removed'
- },
- {
- id: 'cookie-import',
- interaction: 'browser cookies imported or cleared'
- },
- {
- id: 'floating-workspace',
- interaction: 'Floating Workspace opened or configured'
- },
- {
- id: 'mobile-pairing',
- interaction: 'mobile pairing enabled or QR code generated'
- },
- {
- id: 'notifications',
- interaction: 'desktop notifications enabled or tested'
- },
- {
- id: 'ports',
- interaction: 'Ports popover opened, configured, or port action used'
- },
- {
- id: 'quick-commands',
- interaction: 'terminal quick command created or edited'
- },
- {
- id: 'resource-manager',
- interaction: 'Resource Manager opened or configured'
- },
- {
- id: 'review-notes',
- interaction: 'review note added or sent to an agent'
- },
- {
- id: 'ssh',
- interaction: 'SSH target added, imported, tested, connected, disconnected, or configured'
- },
- {
- id: 'terminal-pane-split',
- interaction: 'terminal pane split from the split-pane command'
- },
- {
- id: 'terminal-panes',
- interaction: 'terminal/editor/browser pane created, resized, or merged'
- },
- {
- id: 'terminal-tabs',
- interaction: 'workspace tab created, moved, reordered, pinned, renamed, recolored, or closed'
- },
- {
- id: 'tab-splits',
- interaction: 'workspace tab split into another pane'
- },
- {
- id: 'usage-tracking',
- interaction: 'Stats & Usage or provider usage details opened or configured'
- },
- {
- id: 'voice-dictation',
- interaction: 'dictation session started'
- },
- {
- id: 'workspace-cleanup',
- interaction: 'workspace disk space scan, review, or cleanup action used'
- }
-] as const satisfies readonly FeatureInteractionDefinition[]
-
-export const FEATURE_INTERACTION_IDS = FEATURE_INTERACTIONS.map((feature) => feature.id)
+export type FeatureInteractionTelemetryBucketState = Partial<
+ Record
+>
export function isFeatureInteractionId(value: unknown): value is FeatureInteractionId {
return (
@@ -222,6 +53,24 @@ export function hasFeatureInteraction(
return normalizeFeatureInteractionRecord(state?.[id]) !== null
}
+export function normalizeFeatureInteractionTelemetryBuckets(
+ value: unknown
+): FeatureInteractionTelemetryBucketState {
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
+ return {}
+ }
+
+ const input = value as Record
+ const out: FeatureInteractionTelemetryBucketState = {}
+ for (const id of FEATURE_INTERACTION_IDS) {
+ const bucket = input[id]
+ if (isFeatureInteractionUsageBucket(bucket)) {
+ out[id] = bucket
+ }
+ }
+ return out
+}
+
export function normalizeFeatureInteractions(value: unknown): FeatureInteractionState {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
return {}
diff --git a/src/shared/telemetry-events.test.ts b/src/shared/telemetry-events.test.ts
index 4f33fa39c5e..9d32a1bff30 100644
--- a/src/shared/telemetry-events.test.ts
+++ b/src/shared/telemetry-events.test.ts
@@ -12,11 +12,120 @@ import {
agentKindSchema,
errorClassSchema,
eventSchemas,
+ isCohortExtendedEvent,
SETTINGS_CHANGED_WHITELIST,
settingsChangedKeySchema
} from './telemetry-events'
+import { FEATURE_INTERACTION_IDS, getFeatureInteractionCategory } from './feature-interactions'
import { appStarSourceSchema } from './gh-star-source'
+describe('feature_interaction_usage_bucket_reached schema', () => {
+ it('accepts a valid bucket payload', () => {
+ const parsed = eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ feature_id: 'browser-tab-created',
+ feature_category: 'browser',
+ count_bucket: 'count_3_4',
+ bucket_source: 'crossed_now',
+ nth_repo_added: 2
+ })
+ expect(parsed.success).toBe(true)
+ })
+
+ it('is in the runtime cohort-injection roster', () => {
+ expect(isCohortExtendedEvent('feature_interaction_usage_bucket_reached')).toBe(true)
+ })
+
+ it('keeps the feature id enum in sync with the catalog', () => {
+ const schema = eventSchemas.feature_interaction_usage_bucket_reached
+ for (const feature_id of FEATURE_INTERACTION_IDS) {
+ expect(
+ schema.safeParse({
+ feature_id,
+ feature_category: getFeatureInteractionCategory(feature_id),
+ count_bucket: 'count_1',
+ bucket_source: 'crossed_now'
+ }).success
+ ).toBe(true)
+ }
+ })
+
+ it('rejects unknown enum values and mismatched categories', () => {
+ const valid = {
+ feature_id: 'github-tasks',
+ feature_category: 'task_management',
+ count_bucket: 'count_1',
+ bucket_source: 'observed_existing'
+ }
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ feature_id: 'unknown-feature'
+ }).success
+ ).toBe(false)
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ feature_category: 'browser'
+ }).success
+ ).toBe(false)
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ count_bucket: 'count_4'
+ }).success
+ ).toBe(false)
+ expect(
+ eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ ...valid,
+ bucket_source: 'renderer'
+ }).success
+ ).toBe(false)
+ })
+
+ it('rejects raw privacy fields via .strict()', () => {
+ const rawFields = [
+ 'prompt',
+ 'command',
+ 'path',
+ 'repo',
+ 'branch',
+ 'url',
+ 'hostname',
+ 'error',
+ 'text',
+ 'query',
+ 'result_label',
+ 'workspace_name',
+ 'setting_name',
+ 'target_id',
+ 'annotation_text',
+ 'dom_snippet',
+ 'screenshot',
+ 'page_title',
+ 'trusted_directory',
+ 'trigger_x',
+ 'trigger_y',
+ 'focus_state',
+ 'minimize_state',
+ 'audio',
+ 'transcript',
+ 'model',
+ 'device',
+ 'error_detail'
+ ]
+ for (const field of rawFields) {
+ const parsed = eventSchemas.feature_interaction_usage_bucket_reached.safeParse({
+ feature_id: 'browser-annotations-sent-to-agent',
+ feature_category: 'browser',
+ count_bucket: 'count_1',
+ bucket_source: 'crossed_now',
+ [field]: 'raw'
+ })
+ expect(parsed.success).toBe(false)
+ }
+ })
+})
+
describe('app_starred_orca schema', () => {
it('accepts every declared app star source', () => {
for (const source of appStarSourceSchema.options) {
diff --git a/src/shared/telemetry-events.ts b/src/shared/telemetry-events.ts
index bff2794fb0e..1203e21d357 100644
--- a/src/shared/telemetry-events.ts
+++ b/src/shared/telemetry-events.ts
@@ -25,6 +25,12 @@ import {
TERMINAL_PANE_SPLIT_SOURCES
} from './feature-education-telemetry'
import { FEATURE_WALL_SETUP_STEP_IDS } from './feature-wall-setup-steps'
+import {
+ FEATURE_INTERACTION_CATEGORIES,
+ FEATURE_INTERACTION_IDS,
+ FEATURE_INTERACTION_USAGE_BUCKETS,
+ getFeatureInteractionCategory
+} from './feature-interactions'
import { SETUP_SCRIPT_IMPORT_PROVIDERS } from './setup-script-import-providers'
import { WORKSPACE_SOURCE_VALUES, type WorkspaceSource } from './workspace-source'
import { appStarSourceSchema } from './gh-star-source'
@@ -301,6 +307,27 @@ const nthRepoAddedSchema = z.number().int().nonnegative().optional()
const appOpenedSchema = z.object({ nth_repo_added: nthRepoAddedSchema }).strict()
+export const featureInteractionIdSchema = z.enum(FEATURE_INTERACTION_IDS)
+export const featureInteractionCategorySchema = z.enum(FEATURE_INTERACTION_CATEGORIES)
+export const featureInteractionUsageBucketSchema = z.enum(FEATURE_INTERACTION_USAGE_BUCKETS)
+export const featureInteractionUsageBucketSourceSchema = z.enum([
+ 'crossed_now',
+ 'observed_existing'
+])
+const featureInteractionUsageBucketReachedSchema = z
+ .object({
+ feature_id: featureInteractionIdSchema,
+ feature_category: featureInteractionCategorySchema,
+ count_bucket: featureInteractionUsageBucketSchema,
+ bucket_source: featureInteractionUsageBucketSourceSchema,
+ nth_repo_added: nthRepoAddedSchema
+ })
+ .strict()
+ .refine((value) => getFeatureInteractionCategory(value.feature_id) === value.feature_category, {
+ message: 'feature_category must match feature_id',
+ path: ['feature_category']
+ })
+
const repoAddedSchema = z
// Why: `is_git_repo` is the real git-vs-folder signal, sourced from git
// detection at the add point. It moved here from `onboarding_completed`
@@ -1255,6 +1282,7 @@ const terminalPaneSplitSchema = z
export const eventSchemas = {
app_opened: appOpenedSchema,
app_starred_orca: appStarredOrcaSchema,
+ feature_interaction_usage_bucket_reached: featureInteractionUsageBucketReachedSchema,
repo_added: repoAddedSchema,
add_repo_setup_step_action: addRepoSetupStepActionEventSchema,
@@ -1335,10 +1363,27 @@ export type EventProps = EventMap[N]
// Safely skips non-`ZodObject` schemas (e.g. a future `z.discriminatedUnion`
// or `z.union`) — those have no `.shape`, and probing `key in undefined`
// would throw at module load and take the telemetry module down on import.
+function eventSchemaShape(schema: z.ZodTypeAny): z.ZodRawShape | null {
+ if (schema instanceof z.ZodObject) {
+ return schema.shape
+ }
+
+ const shapeBearingSchema = schema as { shape?: unknown }
+ // Why: refined object schemas may still expose `.shape` even if a Zod
+ // version stops preserving `instanceof ZodObject` through refinement.
+ if (shapeBearingSchema.shape && typeof shapeBearingSchema.shape === 'object') {
+ return shapeBearingSchema.shape as z.ZodRawShape
+ }
+ return null
+}
+
function eventsWithShapeKey(key: string): ReadonlySet {
return new Set(
(Object.entries(eventSchemas) as [EventName, z.ZodTypeAny][])
- .filter(([, schema]) => schema instanceof z.ZodObject && key in schema.shape)
+ .filter(([, schema]) => {
+ const shape = eventSchemaShape(schema)
+ return shape !== null && key in shape
+ })
.map(([name]) => name)
)
}
@@ -1363,6 +1408,7 @@ export const COHORT_EXTENDED: readonly EventName[] = Array.from(COHORT_EXTENDED_
type _CohortExtendedRoster =
| 'app_opened'
| 'app_starred_orca'
+ | 'feature_interaction_usage_bucket_reached'
| 'repo_added'
| 'add_repo_setup_step_action'
| 'add_repo_existing_workspaces_detected'
diff --git a/src/shared/types.ts b/src/shared/types.ts
index 2957a78084a..dec39ee090d 100644
--- a/src/shared/types.ts
+++ b/src/shared/types.ts
@@ -14,7 +14,10 @@ import type { GitLabProjectSettings } from './gitlab-types'
import type { TaskProvider } from './task-providers'
import type { FeatureTipId } from './feature-tips'
import type { ContextualTourId } from './contextual-tours'
-import type { FeatureInteractionState } from './feature-interactions'
+import type {
+ FeatureInteractionState,
+ FeatureInteractionTelemetryBucketState
+} from './feature-interactions'
import type { GitBranchChangeStatus } from './git-status-types'
import type { KeybindingOverrides, TerminalShortcutPolicy } from './keybindings'
import type { RepoIcon } from './repo-icon'
@@ -2880,6 +2883,8 @@ export type PersistedState = {
automations: Automation[]
automationRuns: AutomationRun[]
onboarding: OnboardingState
+ /** Main-owned telemetry de-dupe marker; never exposed through PersistedUIState. */
+ featureInteractionTelemetryBuckets?: FeatureInteractionTelemetryBucketState
}
// ─── Filesystem ─────────────────────────────────────────────
From 36ab59d640a0ef098a34373a40fe2b873a2963aa Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 13:41:05 -0700
Subject: [PATCH 039/165] Reset WebGL glyph atlases globally to stop
cross-terminal glyph corruption (#5122)
Co-authored-by: Orca
---
.../components/terminal-pane/TerminalPane.tsx | 5 +-
.../terminal-webgl-paste-recovery.test.ts | 34 +-
.../terminal-webgl-paste-recovery.ts | 17 +-
.../use-terminal-pane-context-menu.ts | 5 +-
.../use-terminal-pane-global-effects.test.ts | 24 ++
.../use-terminal-pane-global-effects.ts | 11 +-
.../pane-manager-registry.test.ts | 44 ++
.../lib/pane-manager/pane-manager-registry.ts | 28 ++
.../src/lib/pane-manager/pane-manager.ts | 5 +
...ating-workspace-shared-glyph-atlas.spec.ts | 403 ++++++++++++++++++
10 files changed, 551 insertions(+), 25 deletions(-)
create mode 100644 src/renderer/src/lib/pane-manager/pane-manager-registry.test.ts
create mode 100644 src/renderer/src/lib/pane-manager/pane-manager-registry.ts
create mode 100644 tests/e2e/floating-workspace-shared-glyph-atlas.spec.ts
diff --git a/src/renderer/src/components/terminal-pane/TerminalPane.tsx b/src/renderer/src/components/terminal-pane/TerminalPane.tsx
index 8d674c69953..2d6b8dff3d3 100644
--- a/src/renderer/src/components/terminal-pane/TerminalPane.tsx
+++ b/src/renderer/src/components/terminal-pane/TerminalPane.tsx
@@ -1255,10 +1255,7 @@ export default function TerminalPane({
pasteText: (text, options) => {
pasteTerminalText(pane.terminal, text, options)
if (options?.forceBracketedPaste) {
- const manager = managerRef.current
- if (manager) {
- scheduleImagePasteWebglAtlasRecovery(manager)
- }
+ scheduleImagePasteWebglAtlasRecovery()
}
},
onImagePasteError: (error) => setTerminalError(formatClipboardImagePasteError(error))
diff --git a/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.test.ts b/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.test.ts
index ed5472efdf3..61b93ed1e08 100644
--- a/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.test.ts
+++ b/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.test.ts
@@ -1,8 +1,24 @@
-import { afterEach, describe, expect, it, vi } from 'vitest'
+import { afterEach, describe, expect, it, vi, type Mock } from 'vitest'
+import {
+ registerLivePaneManager,
+ unregisterLivePaneManager
+} from '@/lib/pane-manager/pane-manager-registry'
import { scheduleImagePasteWebglAtlasRecovery } from './terminal-webgl-paste-recovery'
describe('terminal image paste WebGL recovery', () => {
+ const registeredManagers: { resetWebglTextureAtlases(): void }[] = []
+
+ function registerManager(): { resetWebglTextureAtlases: Mock<() => void> } {
+ const manager = { resetWebglTextureAtlases: vi.fn<() => void>() }
+ registerLivePaneManager(manager)
+ registeredManagers.push(manager)
+ return manager
+ }
+
afterEach(() => {
+ for (const manager of registeredManagers.splice(0)) {
+ unregisterLivePaneManager(manager)
+ }
vi.useRealTimers()
vi.unstubAllGlobals()
})
@@ -17,13 +33,17 @@ describe('terminal image paste WebGL recovery', () => {
return rafCallbacks.length
})
)
- const manager = { resetWebglTextureAtlases: vi.fn() }
+ // Why: resets go through the live-manager registry so every terminal
+ // sharing the glyph atlas rebuilds, not just the pasted-into pane.
+ const manager = registerManager()
+ const otherManager = registerManager()
- scheduleImagePasteWebglAtlasRecovery(manager)
+ scheduleImagePasteWebglAtlasRecovery()
expect(manager.resetWebglTextureAtlases).not.toHaveBeenCalled()
rafCallbacks[0]?.(0)
expect(manager.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
+ expect(otherManager.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
vi.advanceTimersByTime(120)
expect(manager.resetWebglTextureAtlases).toHaveBeenCalledTimes(2)
@@ -34,9 +54,9 @@ describe('terminal image paste WebGL recovery', () => {
it('falls back to a timeout when animation frames are unavailable', () => {
vi.useFakeTimers()
vi.stubGlobal('requestAnimationFrame', undefined)
- const manager = { resetWebglTextureAtlases: vi.fn() }
+ const manager = registerManager()
- scheduleImagePasteWebglAtlasRecovery(manager)
+ scheduleImagePasteWebglAtlasRecovery()
expect(manager.resetWebglTextureAtlases).not.toHaveBeenCalled()
vi.advanceTimersByTime(0)
@@ -57,8 +77,10 @@ describe('terminal image paste WebGL recovery', () => {
throw new Error('pane disposed')
})
}
+ registerLivePaneManager(manager)
+ registeredManagers.push(manager)
- expect(() => scheduleImagePasteWebglAtlasRecovery(manager)).not.toThrow()
+ expect(() => scheduleImagePasteWebglAtlasRecovery()).not.toThrow()
expect(() => vi.runAllTimers()).not.toThrow()
})
})
diff --git a/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.ts b/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.ts
index 8f0827398b7..8975913aed1 100644
--- a/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.ts
+++ b/src/renderer/src/components/terminal-pane/terminal-webgl-paste-recovery.ts
@@ -1,6 +1,4 @@
-type TerminalWebglRecoveryManager = {
- resetWebglTextureAtlases: () => void
-}
+import { resetAllTerminalWebglAtlases } from '@/lib/pane-manager/pane-manager-registry'
const IMAGE_PASTE_ATLAS_RECOVERY_DELAYS_MS = [120, 500]
@@ -12,20 +10,23 @@ function scheduleNextFrame(callback: () => void): void {
globalThis.setTimeout(callback, 0)
}
-function resetAtlas(manager: TerminalWebglRecoveryManager): void {
+function resetAtlases(): void {
try {
- manager.resetWebglTextureAtlases()
+ // Why: the glyph atlas is shared across same-config terminals, so the
+ // recovery reset must rebuild every live terminal's render model — a
+ // single-manager reset would garble the others.
+ resetAllTerminalWebglAtlases()
} catch {
/* ignore - terminal pane may have unmounted after paste */
}
}
-export function scheduleImagePasteWebglAtlasRecovery(manager: TerminalWebglRecoveryManager): void {
+export function scheduleImagePasteWebglAtlasRecovery(): void {
// Why: Claude Code redraws its image chip immediately after bracketed paste,
// and xterm WebGL atlas corruption can appear after that redraw without a
// context-loss event. A few cheap resets cover the post-paste paint window.
- scheduleNextFrame(() => resetAtlas(manager))
+ scheduleNextFrame(() => resetAtlases())
for (const delayMs of IMAGE_PASTE_ATLAS_RECOVERY_DELAYS_MS) {
- globalThis.setTimeout(() => resetAtlas(manager), delayMs)
+ globalThis.setTimeout(() => resetAtlases(), delayMs)
}
}
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-context-menu.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-context-menu.ts
index c529392cca3..9e5938f9eb8 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-context-menu.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-context-menu.ts
@@ -171,10 +171,7 @@ export function useTerminalPaneContextMenu({
pasteText: (text, options) => {
pasteTerminalText(pane.terminal, text, options)
if (options?.forceBracketedPaste) {
- const manager = managerRef.current
- if (manager) {
- scheduleImagePasteWebglAtlasRecovery(manager)
- }
+ scheduleImagePasteWebglAtlasRecovery()
}
},
onImagePasteError: (error) => {
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
index 245165b5b67..35501087505 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.test.ts
@@ -2,6 +2,10 @@
import type * as ReactModule from 'react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { SYNC_FIT_PANES_EVENT } from '@/constants/terminal'
+import {
+ registerLivePaneManager,
+ unregisterLivePaneManager
+} from '@/lib/pane-manager/pane-manager-registry'
import { useTerminalPaneGlobalEffects } from './use-terminal-pane-global-effects'
const mocks = vi.hoisted(() => ({
@@ -135,6 +139,16 @@ function useMountForFileDrop(
}
describe('useTerminalPaneGlobalEffects', () => {
+ // Why: the live-manager registry is module-global; unregister in afterEach
+ // so a failed assertion cannot leak fake managers into later tests.
+ const registeredManagers: { resetWebglTextureAtlases(): void }[] = []
+
+ function registerManagerForReset(manager: T): T {
+ registerLivePaneManager(manager)
+ registeredManagers.push(manager)
+ return manager
+ }
+
beforeEach(() => {
resetHookRefs()
vi.clearAllMocks()
@@ -154,6 +168,9 @@ describe('useTerminalPaneGlobalEffects', () => {
})
afterEach(() => {
+ for (const manager of registeredManagers.splice(0)) {
+ unregisterLivePaneManager(manager)
+ }
delete (globalThis as unknown as { window?: unknown }).window
delete (globalThis as unknown as { ResizeObserver?: unknown }).ResizeObserver
})
@@ -189,6 +206,10 @@ describe('useTerminalPaneGlobalEffects', () => {
})
mocks.fitAndFocusPanes.mockImplementation(() => order.push('fit-focus'))
+ // Why: the resume path resets atlases through the live-manager registry
+ // (shared glyph atlas), so the fake manager must be registered to observe
+ // its reset in the ordering assertion.
+ registerManagerForReset(manager)
const isActiveRef = { current: false }
const isVisibleRef = { current: false }
beginHookRender()
@@ -328,6 +349,9 @@ describe('useTerminalPaneGlobalEffects', () => {
getActivePane: vi.fn(() => null)
}
+ // Why: focus recovery resets every registered manager (shared glyph
+ // atlas), so the fake manager observes the reset through the registry.
+ registerManagerForReset(manager)
beginHookRender()
useTerminalPaneGlobalEffects({
tabId: 'tab-1',
diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
index 902004d5a99..7b6b435b6a7 100644
--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
+++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-global-effects.ts
@@ -7,6 +7,7 @@ import {
type PasteTerminalTextDetail
} from '@/constants/terminal'
import type { PaneManager } from '@/lib/pane-manager/pane-manager'
+import { resetAllTerminalWebglAtlases } from '@/lib/pane-manager/pane-manager-registry'
import { fitAndFocusPanes, fitPanes } from './pane-helpers'
import type { PtyTransport } from './pty-transport'
import { handleTerminalFileDrop } from './terminal-drop-handler'
@@ -118,7 +119,9 @@ export function useTerminalPaneGlobalEffects({
restoreScrollStateAfterLayout(pane.terminal, position)
}
}
- manager.resetWebglTextureAtlases()
+ // Why: this clear wipes the glyph atlas shared with other same-config
+ // terminals; the global reset rebuilds their render models too.
+ resetAllTerminalWebglAtlases()
})
wasVisibleRef.current = true
applyPendingFollowOutputRequests()
@@ -143,11 +146,13 @@ export function useTerminalPaneGlobalEffects({
const onFocus = (): void => {
// Why: WebGL atlas corruption does not always raise context loss; window
// focus regain is a low-cost recovery point for agent TUI glyph damage.
- managerRef.current?.resetWebglTextureAtlases()
+ // Reset globally — a per-manager reset clears the shared glyph atlas
+ // under every other visible same-config terminal and garbles it.
+ resetAllTerminalWebglAtlases()
}
window.addEventListener('focus', onFocus)
return () => window.removeEventListener('focus', onFocus)
- }, [isActive, isVisible, managerRef])
+ }, [isActive, isVisible])
useEffect(() => {
const manager = managerRef.current
diff --git a/src/renderer/src/lib/pane-manager/pane-manager-registry.test.ts b/src/renderer/src/lib/pane-manager/pane-manager-registry.test.ts
new file mode 100644
index 00000000000..ed588872755
--- /dev/null
+++ b/src/renderer/src/lib/pane-manager/pane-manager-registry.test.ts
@@ -0,0 +1,44 @@
+import { afterEach, describe, expect, it, vi, type Mock } from 'vitest'
+import {
+ registerLivePaneManager,
+ resetAllTerminalWebglAtlases,
+ unregisterLivePaneManager
+} from './pane-manager-registry'
+
+describe('pane manager registry', () => {
+ // Why: the registry is module-global; unregister in afterEach so a failed
+ // assertion cannot leak fake managers into later tests.
+ const registeredManagers: { resetWebglTextureAtlases(): void }[] = []
+
+ function registerManager(): { resetWebglTextureAtlases: Mock<() => void> } {
+ const manager = { resetWebglTextureAtlases: vi.fn<() => void>() }
+ registerLivePaneManager(manager)
+ registeredManagers.push(manager)
+ return manager
+ }
+
+ afterEach(() => {
+ for (const manager of registeredManagers.splice(0)) {
+ unregisterLivePaneManager(manager)
+ }
+ })
+
+ it('resets atlases on every registered manager', () => {
+ const first = registerManager()
+ const second = registerManager()
+
+ resetAllTerminalWebglAtlases()
+
+ expect(first.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
+ expect(second.resetWebglTextureAtlases).toHaveBeenCalledTimes(1)
+ })
+
+ it('stops resetting managers after they unregister', () => {
+ const manager = registerManager()
+ unregisterLivePaneManager(manager)
+
+ resetAllTerminalWebglAtlases()
+
+ expect(manager.resetWebglTextureAtlases).not.toHaveBeenCalled()
+ })
+})
diff --git a/src/renderer/src/lib/pane-manager/pane-manager-registry.ts b/src/renderer/src/lib/pane-manager/pane-manager-registry.ts
new file mode 100644
index 00000000000..da33aceb5cf
--- /dev/null
+++ b/src/renderer/src/lib/pane-manager/pane-manager-registry.ts
@@ -0,0 +1,28 @@
+type AtlasResettablePaneManager = {
+ resetWebglTextureAtlases(): void
+}
+
+const liveManagers = new Set()
+
+export function registerLivePaneManager(manager: AtlasResettablePaneManager): void {
+ liveManagers.add(manager)
+}
+
+export function unregisterLivePaneManager(manager: AtlasResettablePaneManager): void {
+ liveManagers.delete(manager)
+}
+
+/**
+ * Resets the WebGL glyph atlases of every live pane manager, not just one.
+ *
+ * Why: @xterm/addon-webgl keeps a module-global atlas cache, so terminals with
+ * identical font configs share one glyph texture atlas. Clearing it through a
+ * single manager invalidates the cached glyph coordinates of every other
+ * sharing terminal without rebuilding their render models, which paints them
+ * as garbled glyphs. Recovery resets must therefore rebuild all terminals.
+ */
+export function resetAllTerminalWebglAtlases(): void {
+ for (const manager of liveManagers) {
+ manager.resetWebglTextureAtlases()
+ }
+}
diff --git a/src/renderer/src/lib/pane-manager/pane-manager.ts b/src/renderer/src/lib/pane-manager/pane-manager.ts
index fc5aab65647..53bd10f44fa 100644
--- a/src/renderer/src/lib/pane-manager/pane-manager.ts
+++ b/src/renderer/src/lib/pane-manager/pane-manager.ts
@@ -36,6 +36,7 @@ import {
suspendPaneRendering
} from './pane-rendering-control'
import type { TerminalLeafId } from '../../../../shared/stable-pane-id'
+import { registerLivePaneManager, unregisterLivePaneManager } from './pane-manager-registry'
import { PaneIdentityRegistry } from './pane-identity-registry'
import { closeManagedPane, splitManagedPane } from './pane-split-close'
import { FIRST_PANE_ID } from '../../../../shared/pane-key'
@@ -62,6 +63,9 @@ export class PaneManager {
this.root = root
this.options = options
this.renderingSuspended = options.initialRenderingSuspended === true
+ // Why: atlas recovery must reach every live manager — see
+ // resetAllTerminalWebglAtlases for the shared-atlas rationale.
+ registerLivePaneManager(this)
}
createInitialPane(opts?: { focus?: boolean; leafId?: string }): ManagedPane {
@@ -289,6 +293,7 @@ export class PaneManager {
destroy(): void {
this.destroyed = true
+ unregisterLivePaneManager(this)
cancelActivePaneDrag(this.dragState)
this.cancelPendingPaneReparentFrames()
for (const pane of this.panes.values()) {
diff --git a/tests/e2e/floating-workspace-shared-glyph-atlas.spec.ts b/tests/e2e/floating-workspace-shared-glyph-atlas.spec.ts
new file mode 100644
index 00000000000..dc2ff23366c
--- /dev/null
+++ b/tests/e2e/floating-workspace-shared-glyph-atlas.spec.ts
@@ -0,0 +1,403 @@
+import type { Page } from '@stablyai/playwright-test'
+import { test, expect } from './helpers/orca-app'
+import { ensureTerminalVisible, waitForActiveWorktree, waitForSessionReady } from './helpers/store'
+import { sendToTerminal, waitForActivePanePtyId } from './helpers/terminal'
+
+// Why: mirrors FLOATING_TERMINAL_WORKTREE_ID in src/shared/constants.ts.
+// e2e specs avoid importing renderer/shared modules into the Playwright runner.
+const FLOATING_WORKTREE_ID = 'global-floating-terminal'
+const PANEL_SELECTOR = '[data-floating-terminal-panel]'
+
+// Why: the floating panel toggles via this window event
+// (src/renderer/src/lib/floating-terminal.ts); dispatching it exercises the
+// same code path as the status bar button and the keyboard shortcut.
+const TOGGLE_EVENT = 'orca-toggle-floating-terminal'
+
+// Why: a silent foreground command blocks the shell so no prompt framework
+// (e.g. async p10k segments) repaints while screenshots are compared.
+const SILENT_FOREGROUND_COMMAND = 'node -e "setInterval(() => {}, 1000)"\r'
+
+// Why: distinct glyph populations per terminal. After a shared-atlas clear the
+// pages refill in first-use order, so terminals with different content put
+// different glyphs at the coordinates a stale render model still points to.
+const WORKSPACE_GLYPH_ROW = 'abcdefghijklmnopqrstuvwxyz 0123456789 []{}<>/\\#@%&*+=~'
+const FLOATING_GLYPH_ROW = 'ZYXWVUTSRQPONMLKJIHGFEDCBA 9876543210 !?^"\'();:,.|$_-'
+
+async function dumpFloatingDiagnostics(page: Page, label: string): Promise {
+ const probe = await page.evaluate((worktreeId) => {
+ const state = window.__store?.getState()
+ const tabs = state?.tabsByWorktree?.[worktreeId] ?? []
+ return tabs.map((tab) => ({
+ tabId: tab.id,
+ diagnostics: window.__paneManagers?.get(tab.id)?.getRenderingDiagnostics?.() ?? null
+ }))
+ }, FLOATING_WORKTREE_ID)
+ console.log(`[shared-atlas] ${label}: ${JSON.stringify(probe)}`)
+}
+
+async function setSharedAtlasSettings(page: Page): Promise {
+ await page.evaluate(() => {
+ const store = window.__store
+ const state = store?.getState()
+ if (!store || !state?.settings) {
+ throw new Error('Store unavailable')
+ }
+ store.setState({
+ settings: {
+ ...state.settings,
+ floatingTerminalEnabled: true,
+ terminalGpuAcceleration: 'on'
+ }
+ })
+ })
+}
+
+async function ensureFloatingTabs(page: Page, count: number): Promise {
+ const tabIds = await page.evaluate(
+ ({ worktreeId, wanted }) => {
+ const store = window.__store
+ if (!store) {
+ throw new Error('Store unavailable')
+ }
+ while ((store.getState().tabsByWorktree[worktreeId] ?? []).length < wanted) {
+ store.getState().createTab(worktreeId, undefined, undefined, { activate: false })
+ }
+ const tabs = store.getState().tabsByWorktree[worktreeId] ?? []
+ store.getState().activateTab(tabs[0].id)
+ return tabs.slice(0, wanted).map((tab) => tab.id)
+ },
+ { worktreeId: FLOATING_WORKTREE_ID, wanted: count }
+ )
+ // Why: the toggle event listener closes over floatingTerminalEnabled; wait
+ // for the (lazy) panel to mount so React has committed the enabled state
+ // before the toggle event is dispatched, otherwise the event is dropped.
+ await page.waitForFunction(
+ (panelSelector) => Boolean(document.querySelector(panelSelector)),
+ PANEL_SELECTOR,
+ { timeout: 30_000 }
+ )
+ return tabIds
+}
+
+async function activateFloatingTab(page: Page, tabId: string): Promise {
+ await page.evaluate((id) => {
+ window.__store?.getState().activateTab(id)
+ }, tabId)
+}
+
+async function toggleFloatingPanel(page: Page, open: boolean): Promise {
+ await page.evaluate((eventName) => {
+ window.dispatchEvent(new Event(eventName))
+ }, TOGGLE_EVENT)
+ await (open
+ ? expect(page.locator(PANEL_SELECTOR)).toBeVisible()
+ : expect(page.locator(PANEL_SELECTOR)).toBeHidden())
+}
+
+async function waitForWebglOnTab(page: Page, tabId: string): Promise {
+ // Why: a pane that mounted before the GPU setting landed needs the manager
+ // call too — mirrors forceWebgl in terminal-image-paste-webgl-recovery.spec.
+ await page.evaluate((id) => {
+ window.__paneManagers?.get(id)?.setTerminalGpuAcceleration?.('on')
+ }, tabId)
+ // Why: getPanes()/getActivePane() return a public projection without
+ // webglAddon; getRenderingDiagnostics() is the supported way to observe
+ // whether WebGL is attached.
+ return page
+ .waitForFunction(
+ (id) => {
+ const diagnostics = window.__paneManagers?.get(id)?.getRenderingDiagnostics?.() ?? []
+ return diagnostics.some((diagnostic) => diagnostic.hasWebgl)
+ },
+ tabId,
+ { timeout: 15_000 }
+ )
+ .then(() => true)
+ .catch(() => false)
+}
+
+async function waitForPanePtyIdOnTab(page: Page, tabId: string): Promise {
+ await expect
+ .poll(
+ () =>
+ page.evaluate((id) => {
+ const manager = window.__paneManagers?.get(id)
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ return pane?.container?.dataset?.ptyId ?? null
+ }, tabId),
+ { timeout: 15_000, message: `Pane for tab ${tabId} did not receive a PTY binding` }
+ )
+ .not.toBeNull()
+ const ptyId = await page.evaluate((id) => {
+ const manager = window.__paneManagers?.get(id)
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ return pane?.container?.dataset?.ptyId ?? null
+ }, tabId)
+ if (!ptyId) {
+ throw new Error(`Pane for tab ${tabId} has no PTY binding`)
+ }
+ return ptyId
+}
+
+async function writeStaticContent(
+ page: Page,
+ tabId: string,
+ marker: string,
+ glyphRow: string
+): Promise {
+ await page.evaluate(
+ async ({ id, content }) => {
+ const manager = window.__paneManagers?.get(id)
+ const pane = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
+ if (!pane) {
+ throw new Error(`Pane unavailable for tab ${id}`)
+ }
+ await new Promise((resolve) => pane.terminal.write(content, resolve))
+ },
+ {
+ id: tabId,
+ // Why: clear screen + scrollback and hide the cursor so screenshots are
+ // time-invariant, then render dense mixed glyphs so the shared WebGL
+ // atlas region this terminal depends on is populated. Default-colored
+ // ASCII only: a small glyph population avoids atlas page merges, whose
+ // one-shot clear-model flag would let a stale renderer accidentally
+ // self-heal and mask the corruption this spec reproduces.
+ content: `\x1b[2J\x1b[3J\x1b[H\x1b[?25l${Array.from(
+ { length: 14 },
+ (_, row) => `${marker} row ${row} | ${glyphRow} |\r\n`
+ ).join('')}`
+ }
+ )
+ await page.evaluate(
+ () => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)))
+ )
+}
+
+async function refreshTerminalOnTab(page: Page, tabId: string): Promise {
+ // Why: stands in for the steady output stream of a real agent session. The
+ // workspace shell is blocked, so without a repaint trigger the stale-model
+ // corruption would stay latent and the comparison would prove nothing.
+ await page.evaluate((id) => {
+ const manager = window.__paneManagers?.get(id)
+ for (const pane of manager?.getPanes?.() ?? []) {
+ pane.terminal.refresh(0, pane.terminal.rows - 1)
+ }
+ }, tabId)
+ await page.evaluate(
+ () => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)))
+ )
+}
+
+/**
+ * True when both tabs' WebGL renderers draw from the same glyph texture atlas.
+ * @xterm/addon-webgl keeps a module-global atlas cache keyed by font config,
+ * so terminals with identical settings share pages — the precondition for the
+ * cross-terminal corruption this spec reproduces.
+ */
+async function tabsShareGlyphAtlas(page: Page, tabIdA: string, tabIdB: string): Promise {
+ return page.evaluate(
+ ({ a, b }) => {
+ const atlasCanvasOf = (tabId: string): HTMLCanvasElement | null => {
+ const manager = window.__paneManagers?.get(tabId)
+ // Why: the public pane projection omits webglAddon; reach the internal
+ // pane map (runtime-visible) to compare addon.textureAtlas identity.
+ const internalPanes = (
+ manager as unknown as
+ | { panes?: Map }
+ | undefined
+ )?.panes
+ const pane = internalPanes ? [...internalPanes.values()][0] : undefined
+ return pane?.webglAddon?.textureAtlas ?? null
+ }
+ const atlasA = atlasCanvasOf(a)
+ return Boolean(atlasA) && atlasA === atlasCanvasOf(b)
+ },
+ { a: tabIdA, b: tabIdB }
+ )
+}
+
+async function resetAtlasOnTab(page: Page, tabId: string): Promise {
+ await page.evaluate((id) => {
+ window.__paneManagers?.get(id)?.resetWebglTextureAtlases?.()
+ }, tabId)
+}
+
+function workspaceScreenLocator(page: Page, ptyId: string): ReturnType {
+ return page.locator(`[data-pty-id="${ptyId}"] .xterm-screen`).first()
+}
+
+async function screenshotWorkspaceTerminal(page: Page, ptyId: string): Promise {
+ const screen = workspaceScreenLocator(page, ptyId)
+ await expect(screen).toBeVisible()
+ return screen.screenshot({ animations: 'disabled' })
+}
+
+async function captureStableWorkspaceShot(page: Page, ptyId: string): Promise {
+ // Why: two consecutive identical captures prove the surface is byte-stable
+ // before screenshot-equality comparisons begin.
+ let previous = await screenshotWorkspaceTerminal(page, ptyId)
+ for (let attempt = 0; attempt < 10; attempt += 1) {
+ await page.waitForTimeout(250)
+ const next = await screenshotWorkspaceTerminal(page, ptyId)
+ if (next.equals(previous)) {
+ return next
+ }
+ previous = next
+ }
+ throw new Error('Workspace terminal surface did not stabilize for a screenshot')
+}
+
+async function settleAtlasActivity(page: Page): Promise {
+ // Why: atlas warm-up re-rasterization runs in idle callbacks and scheduled
+ // recovery resets fire up to 500ms after their trigger; wait past both.
+ await page.waitForTimeout(800)
+}
+
+type SharedAtlasScenario = {
+ workspaceTabId: string
+ workspacePtyId: string
+ floatingTabIds: string[]
+ baseline: Buffer
+}
+
+/**
+ * Stage: a visible workspace terminal with stable static content, plus two
+ * floating workspace terminal tabs whose WebGL renderers share its glyph
+ * atlas. Returns a workspace baseline screenshot taken with the panel closed
+ * (the panel can overlap the workspace terminal region).
+ */
+async function setUpSharedAtlasScenario(page: Page): Promise {
+ await waitForSessionReady(page)
+ await waitForActiveWorktree(page)
+ await ensureTerminalVisible(page)
+ await setSharedAtlasSettings(page)
+
+ const workspaceTabId = await page.evaluate(() => {
+ const state = window.__store?.getState()
+ return state?.activeTabId ?? null
+ })
+ if (!workspaceTabId) {
+ return null
+ }
+ const workspacePtyId = await waitForActivePanePtyId(page)
+ if (!(await waitForWebglOnTab(page, workspaceTabId))) {
+ console.log('[shared-atlas] workspace terminal never attached WebGL')
+ return null
+ }
+ await sendToTerminal(page, workspacePtyId, SILENT_FOREGROUND_COMMAND)
+ // Why: give the shell a beat to echo the command and start blocking before
+ // the screen is cleared; later captures verify stability explicitly.
+ await page.waitForTimeout(1_000)
+ await writeStaticContent(page, workspaceTabId, 'WORKSPACE', WORKSPACE_GLYPH_ROW)
+
+ const floatingTabIds = await ensureFloatingTabs(page, 2)
+ await toggleFloatingPanel(page, true)
+ if (!(await waitForWebglOnTab(page, floatingTabIds[0]))) {
+ await dumpFloatingDiagnostics(page, 'active floating tab never attached WebGL')
+ return null
+ }
+ for (const tabId of floatingTabIds) {
+ const ptyId = await waitForPanePtyIdOnTab(page, tabId)
+ await sendToTerminal(page, ptyId, SILENT_FOREGROUND_COMMAND)
+ }
+ await page.waitForTimeout(1_000)
+ // Why: the hidden second tab accepts writes too — its buffer paints on
+ // resume, refilling the cleared shared atlas with a different glyph layout.
+ for (const tabId of floatingTabIds) {
+ await writeStaticContent(page, tabId, 'FLOATING', FLOATING_GLYPH_ROW)
+ }
+
+ if (!(await tabsShareGlyphAtlas(page, workspaceTabId, floatingTabIds[0]))) {
+ console.log('[shared-atlas] workspace and floating terminals do not share an atlas')
+ return null
+ }
+
+ // Why: glyphs rasterized during startup can predate web font readiness; a
+ // clean rebuild here makes the baseline byte-identical to any later
+ // re-rasterization, so equality is a sound "intact" oracle.
+ await resetAtlasOnTab(page, workspaceTabId)
+ await settleAtlasActivity(page)
+
+ // Why: the panel overlay can cover the workspace terminal region, so all
+ // workspace screenshots are taken with the panel closed. Closing only
+ // suspends the floating renderer; it never mutates the shared atlas.
+ await toggleFloatingPanel(page, false)
+ // Why: closing the panel can refit the workspace terminal; rebuild once more
+ // so the baseline model/atlas state matches the post-trigger capture path.
+ await resetAtlasOnTab(page, workspaceTabId)
+ const baseline = await captureStableWorkspaceShot(page, workspacePtyId)
+
+ return { workspaceTabId, workspacePtyId, floatingTabIds, baseline }
+}
+
+async function captureWorkspaceAfterTrigger(
+ page: Page,
+ scenario: SharedAtlasScenario
+): Promise {
+ await settleAtlasActivity(page)
+ // Why: a real agent session repaints continuously; the blocked test shell
+ // does not, so force the equivalent full repaint before comparing.
+ await refreshTerminalOnTab(page, scenario.workspaceTabId)
+ return captureStableWorkspaceShot(page, scenario.workspacePtyId)
+}
+
+test.describe('floating workspace shared glyph atlas @headful', () => {
+ test('switching floating workspace tabs keeps workspace terminal glyphs intact', async ({
+ orcaPage
+ }, testInfo) => {
+ // Why: xterm WebGL terminals with identical font configs share one glyph
+ // texture atlas. The floating tab switch resumes a hidden renderer, whose
+ // atlas reset clears those shared pages; unless every sharing terminal
+ // rebuilds its render model too, the visible workspace terminal keeps
+ // stale glyph coordinates and paints garbage (the bug this guards).
+ const scenario = await setUpSharedAtlasScenario(orcaPage)
+ test.skip(!scenario, 'WebGL inactive or terminals do not share a glyph atlas')
+ const { baseline, floatingTabIds } = scenario!
+
+ await toggleFloatingPanel(orcaPage, true)
+ await activateFloatingTab(orcaPage, floatingTabIds[1])
+ // Why: the switched-to tab attaching WebGL proves the suspend/resume
+ // (and with it the atlas reset trigger) actually ran.
+ expect(
+ await waitForWebglOnTab(orcaPage, floatingTabIds[1]),
+ 'switched-to floating tab should resume WebGL'
+ ).toBe(true)
+ await settleAtlasActivity(orcaPage)
+ await toggleFloatingPanel(orcaPage, false)
+
+ const afterSwitch = await captureWorkspaceAfterTrigger(orcaPage, scenario!)
+ await testInfo.attach('baseline', { body: baseline, contentType: 'image/png' })
+ await testInfo.attach('after-tab-switch', { body: afterSwitch, contentType: 'image/png' })
+ console.log(`[shared-atlas] tabSwitchIntact=${afterSwitch.equals(baseline)}`)
+
+ expect(
+ afterSwitch.equals(baseline),
+ 'workspace terminal must render identically after floating tab switching'
+ ).toBe(true)
+ })
+
+ test('reopening the floating workspace keeps workspace terminal glyphs intact', async ({
+ orcaPage
+ }, testInfo) => {
+ // Why: reopening the panel resumes its terminal, whose atlas reset clears
+ // the shared pages just like a tab switch — the other user flow that
+ // garbled visible workspace terminals before resets went global.
+ const scenario = await setUpSharedAtlasScenario(orcaPage)
+ test.skip(!scenario, 'WebGL inactive or terminals do not share a glyph atlas')
+ const { baseline } = scenario!
+
+ await toggleFloatingPanel(orcaPage, true)
+ await settleAtlasActivity(orcaPage)
+ await toggleFloatingPanel(orcaPage, false)
+
+ const afterReopen = await captureWorkspaceAfterTrigger(orcaPage, scenario!)
+ await testInfo.attach('baseline', { body: baseline, contentType: 'image/png' })
+ await testInfo.attach('after-reopen', { body: afterReopen, contentType: 'image/png' })
+ console.log(`[shared-atlas] reopenIntact=${afterReopen.equals(baseline)}`)
+
+ expect(
+ afterReopen.equals(baseline),
+ 'workspace terminal must render identically after a floating panel reopen'
+ ).toBe(true)
+ })
+})
From 5f6b454c3aae420ad89a92ff517433a0bcb64558 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 13:41:22 -0700
Subject: [PATCH 040/165] perf(windows): fix 60s startup ACL walk and OpenCode
streaming freeze, with benchmark harnesses (#5124)
---
notes/windows-perf-progress.md | 248 ++++++++++
.../opencode-message-part-flood-bench.test.ts | 137 ++++++
src/main/agent-hooks/server.test.ts | 32 ++
src/main/daemon/history-manager.ts | 14 +-
src/main/index.ts | 44 +-
.../hook-plugin-message-part-throttle.test.ts | 203 ++++++++
src/main/opencode/hook-service.test.ts | 4 +-
src/main/opencode/hook-service.ts | 63 ++-
src/main/startup/hydrate-shell-path.test.ts | 20 +-
.../startup/windows-user-data-acl.test.ts | 135 ++++++
src/main/startup/windows-user-data-acl.ts | 163 +++++++
src/main/win32-utils.ts | 4 +
src/shared/agent-hook-listener.ts | 17 +-
...rtup-acl-fix-2026-06-10T19-37-58-671Z.json | 445 ++++++++++++++++++
...l-fix-steady-2026-06-10T19-41-40-683Z.json | 363 ++++++++++++++
...tup-baseline-2026-06-10T19-36-01-305Z.json | 363 ++++++++++++++
tools/benchmarks/startup-time-bench.mjs | 330 +++++++++++++
17 files changed, 2560 insertions(+), 25 deletions(-)
create mode 100644 notes/windows-perf-progress.md
create mode 100644 src/main/agent-hooks/opencode-message-part-flood-bench.test.ts
create mode 100644 src/main/opencode/hook-plugin-message-part-throttle.test.ts
create mode 100644 src/main/startup/windows-user-data-acl.test.ts
create mode 100644 src/main/startup/windows-user-data-acl.ts
create mode 100644 tools/benchmarks/results/startup-acl-fix-2026-06-10T19-37-58-671Z.json
create mode 100644 tools/benchmarks/results/startup-acl-fix-steady-2026-06-10T19-41-40-683Z.json
create mode 100644 tools/benchmarks/results/startup-baseline-2026-06-10T19-36-01-305Z.json
create mode 100644 tools/benchmarks/startup-time-bench.mjs
diff --git a/notes/windows-perf-progress.md b/notes/windows-perf-progress.md
new file mode 100644
index 00000000000..5cd3b89ff20
--- /dev/null
+++ b/notes/windows-perf-progress.md
@@ -0,0 +1,248 @@
+# Windows Performance Investigation — Progress Log
+
+Goal: (1) significantly improve Windows startup time (~1 min cold start reported),
+(2) fix OpenCode-driven UI freezes, (3) improve overall Windows performance.
+All changes must be proven with before/after benchmark numbers.
+
+## Status
+
+- [x] Benchmark harness for startup time (`tools/benchmarks/startup-time-bench.mjs`)
+- [x] Startup bottleneck FIXED + verified: **19.31s → 1.80s median** (fixture);
+ real-world profile was 62s of blocked main thread → now 0 icacls spawns steady-state
+- [x] OpenCode freeze ROOT CAUSE found + fixed: MessagePart hook flood (see F5/D2).
+ Benchmark: 22.9 MB / 540 ms / 400 main-process fanouts per turn → 469 KB / 79 ms / 120
+ (legacy vs throttled plugin behavior through the real hook HTTP pipeline)
+- [x] General Windows sync-work audit (results below); audit item #2 (readHooksJson per
+ status IPC) investigated and found NOT hot — renderer barely calls those handlers.
+ Fixed pre-existing Windows-only test failures (hydrate-shell-path delimiter).
+- [x] Windows ConPTY e2e perf validation (F7 below)
+
+## Key facts / environment
+
+- Branch: `Jinwoo-H/windows-launch-time`
+- Electron app, entry: `src/main/index.ts` (~1557 lines)
+- Existing startup diagnostics: `ORCA_STARTUP_DIAGNOSTICS=1` writes `[startup] ` lines to stderr
+ (`src/main/startup/startup-diagnostics.ts`)
+- Prior art: PR #4618 "perf: speed up desktop startup", #5011 "stop main-thread PowerShell ACL storm
+ on env-store reads", #4526 "Avoid OpenCode config cleanup freezes on Windows", b240d5eee
+ "Measure startup hydration phases"
+
+## Follow-ups / known issues (out of scope for this branch)
+
+- Pre-existing Windows-only unit test failures: `daemon-pty-adapter.test.ts` (61) and
+ `history-manager.test.ts` (3, chmod-based fs-error simulation is a no-op on Windows).
+ Identical with/without this branch's changes. CI never sees them (ubuntu-only).
+- Consider a Windows CI lane for the terminal-perf e2e suite (F6/F7) and these unit suites.
+- Typing-latency load-sensitivity (F7): possible deeper work on daemon checkpoint
+ scheduling/priority if user reports persist after D3.
+- Audit leftovers (F4): non-recursive `grantDirAcl` execFileSync on hook install
+ (installer-utils.ts:210) could be async; readHooksJson caching unnecessary (not hot).
+
+### D3 — Async checkpoint writes (implemented)
+
+`HistoryManager.checkpoint` (every ~5s per dirty session, Electron main process) switched
+from writeFileSync+renameSync (~1MB snapshot JSON, inflated by Defender on Windows) to
+fs.promises with the same tmp+rename atomicity; ordering preserved by the adapter's
+checkpointInFlight guard.
+
+## Suspects (startup)
+
+1. **`grantDirAcl(userData, { recursive: true })`** — `src/main/index.ts:517-523`, win32 only,
+ runs **synchronously on the main process inside `openMainWindow()` before window creation**.
+ Spawns `icacls /grant:r :(OI)(CI)(F) /T /C` with a **60s timeout**.
+ The comment itself admits large userData dirs (tens of thousands of Chromium cache files)
+ can take >10s. This blocks first paint for the whole walk. Matches "1 minute launch" and
+ "Windows only".
+2. Windows Defender real-time scan of exe/asar/native modules on cold start (environmental,
+ can't fix in code, but reducing file count / sync IO helps).
+3. TBD: store sync load, daemon init, i18n init, sherpa-onnx native module load.
+
+### F3 — Baseline benchmark (2026-06-10)
+
+Harness: `node tools/benchmarks/startup-time-bench.mjs --label baseline --iterations 3 --files 28000`
+(28k-file synthetic Chromium-cache-shaped userData fixture in %TEMP%, headless launch of
+the electron-vite build with `ORCA_STARTUP_DIAGNOSTICS=1`, milestones parsed from stderr).
+
+| phase (median of 3) | baseline |
+|---|---|
+| spawnToAppReady | 857ms |
+| appReadyToServices | 178ms |
+| servicesToI18n | 2ms |
+| i18nToOpenWindow | 7ms |
+| **aclGrantMs** | **15.65s** |
+| windowCreatedToLoaded | 1.06s |
+| **totalToDidFinishLoad** | **19.31s** |
+
+ACL walk = 81% of total. (Fixture is kinder than the real profile: same file count but
+freshly-written small files → real %APPDATA%\Orca measured 62s for the same command.)
+JSON: tools/benchmarks/results/startup-baseline-2026-06-10T19-36-01-305Z.json
+
+### F4 — Sync main-thread audit (subagent, 2026-06-10)
+
+Ranked offenders beyond the ACL grant (#1):
+2. `readHooksJson` + JSON.parse re-read per agent-status IPC call across ~10 hook services
+ (`src/main/*/hook-service.ts` via `agent-hooks/installer-utils.ts:50`) — 10-100ms per
+ status snapshot, all platforms. Remediation: in-memory cache.
+3. `whoami.exe` SID resolution (win32-utils.ts:92) — already cached, OK.
+4. macOS-only `defaults read` per browser probe — not Windows.
+5. `installer-utils.ts:210` non-recursive grantDirAcl on hook install (execFileSync,
+ 500ms-2s) — infrequent write path, low priority.
+6. `secure-file.ts` sync PowerShell on credential write path — by design (#5011), leave.
+
+## Suspects (OpenCode freeze)
+
+- User report: UI freezes ~5s after sending prompt; OpenCode session itself continues fine
+ (visible from external terminal). So the agent process is healthy — the freeze is in Orca's
+ main process or renderer. Spinner in left panel still animates (= renderer compositor alive?
+ or just that one timer). Need to find sync main-process work triggered by OpenCode activity.
+- Prior fix #4526 "Avoid OpenCode config cleanup freezes on Windows" — re-check that path.
+
+### Research results (subagent, 2026-06-10) — ranked candidates
+
+1. **ConPTY output flood vs PTY batching/backpressure** (HIGH): Windows ConPTY re-renders
+ full TUI frames → 10-100x output volume vs macOS. Batching in `src/main/ipc/pty.ts`
+ (16KB chunks / 8ms flush, 512KB renderer in-flight window). If renderer xterm.write is
+ slow, ACKs stall → in-flight fills → main stalls. Tests: terminal-foreground-redraw-freeze,
+ artificial-opencode-terminal-load e2e.
+2. **Sync `runtime.onPtyData` per data event before batching** (MED-HIGH):
+ `src/main/ipc/pty.ts:1376-1430` → `orca-runtime.ts:3256-3420`: normalizeTerminalChunk +
+ tail-buffer append + agent-status OSC parsing run synchronously per chunk on main.
+ Daemon PTY path. High event rate × per-event cost can saturate the main loop.
+3. **`mirrorUserConfig` recursive fs work in `buildPtyEnv` on PTY spawn** (MED):
+ `src/main/opencode/hook-service.ts:359-524` + `pty/overlay-mirror.ts:63-110` —
+ readdir/safeRemoveTree/symlinks on main thread at spawn; #4526 fixed only clearPty side.
+ Timing mismatch with "5s after prompt" though.
+4. Agent-status event fan-out per OSC title (LOW-MED). 5. Tail-buffer O(n²) (LOW).
+
+Gap in coverage: no test exercises rapid continuous ConPTY-scale data + sync onPtyData
+accumulation on Windows.
+
+### F5 — ROOT CAUSE (2026-06-10): OpenCode MessagePart hook flood
+
+Eliminated candidates first: ran `terminal-foreground-redraw-freeze.spec.ts` on THIS Windows
+machine (real ConPTY + daemon provider) — passes; renderer output scheduler protections hold.
+The raw TUI-output-flood theory doesn't explain an OpenCode-specific permanent freeze.
+
+The actual mechanism (src/main/opencode/hook-service.ts plugin source):
+- OpenCode publishes `message.part.updated` with the FULL accumulated text of the part on
+ every streamed append (architecture: parts are republished, not deltas).
+- Orca's plugin POSTed that full text to the agent-hook server on EVERY event →
+ **O(n²) bytes per streaming turn**. A 120KB reply in 400 updates = ~23 MB through
+ loopback HTTP + main-process JSON.parse; real turns are worse (per-token updates).
+- Main process spends its whole loop on HTTP receive + parse + normalize + fanout. UI symptom
+ matches the user report exactly: everything dead (window close needs main + renderer
+ round-trip), EXCEPT the sidebar agent indicator — which is the one thing fed by the very
+ agentStatus:set flood that's starving everything else.
+- Why Windows-biased: same flood exists on macOS but combines on Windows with ConPTY
+ full-frame redraw volume and generally slower process IO; also Windows daemon-PTY path
+ adds main-process onPtyData work.
+- Why "5 seconds after sending the prompt": that's when the accumulated text gets big.
+- Why OpenCode keeps working: plugin POST failures are swallowed; the session is healthy.
+- Downstream payloads were already bounded (prompt 200 chars, lastAssistantMessage 8000
+ chars via agent-status-types normalization) — the renderer wasn't the bottleneck; the
+ main-process ingest was.
+
+### F7 — Windows ConPTY e2e perf validation (2026-06-10)
+
+Ran the terminal-perf budget specs on this Windows machine (real ConPTY + daemon PTY
+provider — a path CI never exercises):
+- `terminal-output-scheduler.spec.ts`: PASS (all tests)
+- `terminal-foreground-redraw-freeze.spec.ts`: PASS
+- `terminal-typing-latency.spec.ts`: PASSES in isolation, repeatedly — median 13.6-23.1ms,
+ worst 34-42ms (budgets: 250ms median / 1000ms worst). Two earlier runs that exceeded the
+ worst-key budget (1054.9ms, 2016.1ms outlier on a single key) occurred while other heavy
+ tooling (vitest/tsgo/builds) ran concurrently on the machine → load-sensitivity, not a
+ deterministic product defect. Note the product implication: under heavy host load
+ (exactly what coding agents generate), a keystroke can stall >1s on Windows. Plausible
+ contributors for follow-up: daemon checkpoint ticks (5s interval; snapshot serialize in
+ daemon + sync writeFileSync of checkpoint JSON on main — daemon-pty-adapter.ts:592,
+ history-manager.ts:109), Defender scanning fresh build artifacts.
+
+### F6 — Windows e2e perf coverage gap
+
+All terminal-perf e2e specs run on ubuntu-latest in CI. Verified they DO run on a Windows
+dev machine (`npx playwright test ... --project electron-headless` works locally). Consider
+a Windows CI lane for the terminal-perf suite.
+
+## OpenCode fix (D2)
+
+1. **Plugin throttle + cap (source fix)** — `src/main/opencode/hook-service.ts`:
+ assistant MessagePart posts are trailing-edge coalesced to ≥250ms apart and text is
+ capped at 4000 chars (leading edge posts immediately so previews stay snappy; pending
+ snapshot flushed before SessionIdle so the done-row preview is the final message; user
+ prompts bypass the throttle slot). Plugin file is rewritten on every Orca-launched
+ OpenCode spawn, so the fix deploys to new sessions immediately.
+2. **Listener-side cap (stale-plugin defense)** — `src/shared/agent-hook-listener.ts`:
+ OpenCode MessagePart text capped at 8000 chars at ingest (OPENCODE_HOOK_TEXT_MAX_CHARS)
+ so pre-fix plugins in long-running OpenCode processes can't blow up state maps.
+3. **Benchmark/regression test** — `src/main/agent-hooks/opencode-message-part-flood-bench.test.ts`
+ drives the real hook HTTP pipeline with both behaviors. Measured on this machine:
+ | metric/turn | legacy plugin | throttled plugin |
+ |---|---|---|
+ | posts | 400 | 120 |
+ | bytes through main | 22.9 MB | 469 KB (49x less) |
+ | wall time | 540 ms | 79 ms |
+ | listener fanouts | 400 | 120 |
+4. Behavioral plugin tests — `src/main/opencode/hook-plugin-message-part-throttle.test.ts`
+ executes the generated plugin with fake timers + stubbed fetch.
+
+## Findings
+
+### F1 — Recursive icacls walk is the ~1 min startup (CONFIRMED, 2026-06-10)
+
+- This machine's real packaged-Orca userData: `%APPDATA%\Orca` = **28,650 files / 2.06 GB**
+ (mostly Chromium caches: Cache, Code Cache, GPUCache, blob_storage…).
+- Measured the exact command Orca runs in `openMainWindow()` (src/main/index.ts:517-523):
+ - `icacls /grant:r :(OI)(CI)(F) /T /C` → **62.0 s**
+ - App runs it with `execFileSync` (main thread, BLOCKING, before BrowserWindow creation)
+ with a **60s timeout** → every cold launch freezes ~60s, then the grant *times out and
+ silently fails* (execFileSync throws, caught). Users pay the full minute and get nothing.
+ - Non-recursive root-only grant: **4.8 s** (NTFS propagates inheritable ACE internally).
+ - `icacls \* /grant:r …` (immediate children, 48 entries): **4.7 s**.
+- Why it exists (PR #1152): Chromium's BrowserWindow ctor resets userData DACL with
+ Inherit-Only ACEs → EPERM on writes in existing subdirs (codex-runtime-home, agent-hooks…).
+ Explicit child ACEs survive propagation. Per-write EPERM retries exist as backstop in
+ `codex-accounts/fs-utils.ts` + `agent-hooks/installer-utils.ts`.
+- Windows ACL inheritance recalculates from the immediate parent during propagation, so
+ explicit ACEs on userData + immediate children are sufficient; per-file ACEs on 28k
+ Chromium cache files are useless work.
+
+### F2 — Instrumentation prior art
+
+- `ORCA_STARTUP_DIAGNOSTICS=1` → `[startup] ` lines on stderr (startup-diagnostics.ts).
+ Only 2 events exist today (single-instance lock). Commit b240d5eee (branch
+ perf/startup-first-window, NOT merged here) has a full StartupPhaseTimer framework —
+ too large to cherry-pick; adding minimal milestone logs instead.
+- Hermetic benchmark launch path: `ORCA_E2E_USER_DATA_DIR=` redirects userData
+ (works packaged + dev), `ORCA_E2E_HEADLESS=1` keeps window hidden. Dev/preview mode
+ skips single-instance lock → safe alongside installed Orca.
+
+## Decisions / fixes
+
+### D0 — RESULTS: ACL fix benchmark (2026-06-10)
+
+| phase (median) | baseline (3 it.) | after fix (4 it.) | steady state (3 it.) |
+|---|---|---|---|
+| aclGrantMs | **15.65s sync/blocking** | async (off critical path) | **0ms (marker hit)** |
+| totalToWindowCreated | 18.25s | 930ms | 814ms |
+| totalToDidFinishLoad | **19.31s** | **2.04s** | **1.80s** |
+
+- First launch after fix: total 2.06s while the background grant ran 6.81s concurrently.
+- Marker verified written by real icacls run; subsequent launches log `acl-grant-done
+ mode=marker-hit` with zero spawns.
+- JSON evidence: tools/benchmarks/results/startup-{baseline,acl-fix,acl-fix-steady}-*.json
+- Files: src/main/startup/windows-user-data-acl.ts (+tests), src/main/index.ts (wire-up +
+ startup milestones), src/main/win32-utils.ts (export identity resolver),
+ tools/benchmarks/startup-time-bench.mjs (harness).
+
+### D1 — ACL grant fix (implemented as planned)
+
+Replace the synchronous recursive walk with:
+1. A persisted marker (`windows-acl-grant.json` in userData, keyed on identity + scheme
+ version): when present → skip everything (steady-state launches: 0 icacls spawns, 0 ms).
+2. When marker missing (first launch after install/profile import): grant root +
+ immediate children via **async spawn** (never blocks window creation); write marker
+ on success. Per-write EPERM retries remain the backstop during the async window —
+ that's exactly what they're for (#1152 comment says so).
+3. Drop the /T full-tree walk entirely; it grants nothing the immediate-children
+ ACEs + inheritance propagation don't already cover.
diff --git a/src/main/agent-hooks/opencode-message-part-flood-bench.test.ts b/src/main/agent-hooks/opencode-message-part-flood-bench.test.ts
new file mode 100644
index 00000000000..2c51371050a
--- /dev/null
+++ b/src/main/agent-hooks/opencode-message-part-flood-bench.test.ts
@@ -0,0 +1,137 @@
+/**
+ * Benchmark-style regression test for the OpenCode MessagePart flood.
+ *
+ * Drives the REAL agent-hook HTTP pipeline (loopback socket, body read,
+ * JSON.parse, normalization, listener fanout) with two client behaviors:
+ *
+ * - "legacy plugin": one POST per streamed part update, each carrying the
+ * FULL accumulated reply text (how plugin builds before the throttle fix
+ * behaved) — O(n²) bytes per turn.
+ * - "throttled plugin": leading + trailing-edge coalesced posts at 250ms
+ * cadence with text capped at 4000 chars (current plugin behavior).
+ *
+ * The byte/post-count assertions are deterministic; wall-clock timings are
+ * logged as benchmark evidence (see notes/windows-perf-progress.md) but not
+ * asserted, to keep CI stable.
+ */
+import { mkdtempSync, rmSync } from 'node:fs'
+import { tmpdir } from 'node:os'
+import { join } from 'node:path'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+import { makePaneKey } from '../../shared/stable-pane-id'
+
+const { getCohortAtEmitMock, trackMock } = vi.hoisted(() => ({
+ getCohortAtEmitMock: vi.fn(),
+ trackMock: vi.fn()
+}))
+
+vi.mock('../telemetry/client', () => ({
+ track: trackMock
+}))
+
+vi.mock('../telemetry/cohort-classifier', () => ({
+ getCohortAtEmit: getCohortAtEmitMock
+}))
+
+import { AgentHookServer } from './server'
+
+const PANE = makePaneKey('tab-bench', '99999999-9999-4999-8999-999999999999')
+
+// A realistic long streaming reply: ~120 KB final text arriving in 400
+// part updates (OpenCode re-publishes the whole part per append).
+const FINAL_REPLY_CHARS = 120_000
+const LEGACY_PART_UPDATES = 400
+// Throttled plugin posts at most one MessagePart per 250ms. A ~30s turn
+// yields ~120 posts; we use that worst-case count with the 4000-char cap.
+const THROTTLED_POSTS = 120
+const THROTTLED_TEXT_CAP = 4_000
+
+describe('OpenCode MessagePart flood benchmark', () => {
+ let server: AgentHookServer
+ let tempDir: string
+ let listenerEvents: number
+
+ beforeEach(async () => {
+ getCohortAtEmitMock.mockReturnValue({ nth_repo_added: 2 })
+ tempDir = mkdtempSync(join(tmpdir(), 'orca-hook-bench-'))
+ server = new AgentHookServer()
+ listenerEvents = 0
+ server.setListener(() => {
+ listenerEvents++
+ })
+ await server.start({ env: 'production', userDataPath: tempDir })
+ })
+
+ afterEach(() => {
+ server.stop()
+ rmSync(tempDir, { recursive: true, force: true })
+ })
+
+ async function postMessagePart(env: Record, text: string): Promise {
+ const response = await fetch(`http://127.0.0.1:${env.ORCA_AGENT_HOOK_PORT}/hook/opencode`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Orca-Agent-Hook-Token': env.ORCA_AGENT_HOOK_TOKEN
+ },
+ body: JSON.stringify({
+ paneKey: PANE,
+ tabId: 'tab-bench',
+ worktreeId: 'wt-bench',
+ env: 'production',
+ payload: {
+ hook_event_name: 'MessagePart',
+ role: 'assistant',
+ text,
+ messageID: 'msg-bench',
+ sessionID: 'session-bench'
+ }
+ })
+ })
+ expect(response.status).toBe(204)
+ }
+
+ it('throttled plugin behavior cuts per-turn hook-pipeline bytes by >40x', async () => {
+ const env = server.buildPtyEnv()
+ expect(env.ORCA_AGENT_HOOK_PORT).toBeTruthy()
+
+ // Legacy: full accumulated text per part update.
+ let legacyBytes = 0
+ const legacyStart = performance.now()
+ for (let i = 1; i <= LEGACY_PART_UPDATES; i++) {
+ const text = 'x'.repeat(Math.floor((FINAL_REPLY_CHARS * i) / LEGACY_PART_UPDATES))
+ legacyBytes += text.length
+ await postMessagePart(env, text)
+ }
+ const legacyMs = performance.now() - legacyStart
+ const legacyEvents = listenerEvents
+
+ listenerEvents = 0
+
+ // Throttled: bounded post count, bounded text.
+ let throttledBytes = 0
+ const throttledStart = performance.now()
+ for (let i = 1; i <= THROTTLED_POSTS; i++) {
+ const text = 'x'.repeat(THROTTLED_TEXT_CAP)
+ throttledBytes += text.length
+ await postMessagePart(env, text)
+ }
+ const throttledMs = performance.now() - throttledStart
+ const throttledEvents = listenerEvents
+
+ // eslint-disable-next-line no-console
+ console.log(
+ `[bench] legacy: ${LEGACY_PART_UPDATES} posts, ${(legacyBytes / 1024 / 1024).toFixed(1)} MB, ` +
+ `${legacyMs.toFixed(0)} ms, ${legacyEvents} listener fanouts | ` +
+ `throttled: ${THROTTLED_POSTS} posts, ${(throttledBytes / 1024).toFixed(0)} KB, ` +
+ `${throttledMs.toFixed(0)} ms, ${throttledEvents} listener fanouts`
+ )
+
+ // Deterministic: the turn's total text volume through the main process
+ // drops from O(n²) (~23 MB here) to O(posts × cap) (~470 KB here, >40x
+ // less). Real turns stream far more than 400 part updates, so the
+ // real-world ratio is larger still.
+ expect(throttledBytes).toBeLessThan(legacyBytes / 40)
+ expect(THROTTLED_POSTS).toBeLessThan(LEGACY_PART_UPDATES / 3 + 1)
+ }, 120_000)
+})
diff --git a/src/main/agent-hooks/server.test.ts b/src/main/agent-hooks/server.test.ts
index c87c864b373..d173acf8bc7 100644
--- a/src/main/agent-hooks/server.test.ts
+++ b/src/main/agent-hooks/server.test.ts
@@ -3842,6 +3842,38 @@ describe('OpenCode hook normalization', () => {
expect(result?.payload.lastAssistantMessage).toBe('Hello! How can I help?')
})
+ it('caps oversized MessagePart text from stale (pre-throttle) plugin builds', () => {
+ // Why: plugin builds installed before the throttle/cap fix re-post the
+ // full accumulated reply on every streamed part update. The listener must
+ // bound the text so each event's status compare, IPC fanout, and renderer
+ // store update stay O(cap) instead of O(reply length).
+ const assistant = _internals.normalizeHookPayload(
+ 'opencode',
+ buildBody({
+ hook_event_name: 'MessagePart',
+ role: 'assistant',
+ text: 'a'.repeat(500_000)
+ }),
+ 'production'
+ )
+ expect(assistant?.payload.lastAssistantMessage?.length).toBe(8_000)
+
+ // Why: prompt has always been single-line-capped at 200 by
+ // normalizeAgentStatusObject; this asserts the oversized input still
+ // flows through without blowing past that bound.
+ const user = _internals.normalizeHookPayload(
+ 'opencode',
+ buildBody({
+ hook_event_name: 'MessagePart',
+ role: 'user',
+ text: 'u'.repeat(500_000),
+ messageID: 'msg-cap'
+ }),
+ 'production'
+ )
+ expect(user?.payload.prompt?.length).toBe(200)
+ })
+
it('subsequent SessionIdle preserves cached prompt + assistant message', () => {
_internals.normalizeHookPayload(
'opencode',
diff --git a/src/main/daemon/history-manager.ts b/src/main/daemon/history-manager.ts
index 4cc9a85f191..c9fe0d1873f 100644
--- a/src/main/daemon/history-manager.ts
+++ b/src/main/daemon/history-manager.ts
@@ -5,8 +5,8 @@ import {
readFileSync,
existsSync,
rmSync,
- renameSync,
- unlinkSync
+ unlinkSync,
+ promises as fsPromises
} from 'fs'
import { getHistorySessionDirName } from './history-paths'
import type { TerminalSnapshot } from './types'
@@ -139,10 +139,14 @@ export class HistoryManager {
})
// Why: atomic write via tmp+rename prevents half-written checkpoints
// on crash. Reading a corrupt checkpoint is worse than reading a
- // slightly stale one.
+ // slightly stale one. Async IO — this runs every ~5s per dirty session
+ // on the Electron main process, and a sync ~MB write (worse under
+ // antivirus scanning on Windows) would stall input/IPC for its
+ // duration. Overlap is prevented by the adapter's checkpointInFlight
+ // guard, which awaits this promise before the next tick.
const tmpPath = `${writer.checkpointPath}.tmp`
- writeFileSync(tmpPath, data)
- renameSync(tmpPath, writer.checkpointPath)
+ await fsPromises.writeFile(tmpPath, data)
+ await fsPromises.rename(tmpPath, writer.checkpointPath)
} catch (err) {
this.handleWriteError(sessionId, err)
}
diff --git a/src/main/index.ts b/src/main/index.ts
index 678ac7ad14b..542731d09d2 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -2,7 +2,6 @@
it owns app lifecycle, service wiring, window creation, and hook/daemon
startup. Splitting by line count would fragment tightly coupled startup
logic across files without a cleaner ownership seam. */
-import { grantDirAcl } from './win32-utils'
import { existsSync } from 'fs'
import { join } from 'path'
import os from 'node:os'
@@ -72,6 +71,7 @@ import {
shouldBypassSingleInstanceLock
} from './startup/single-instance-lock'
import { isStartupDiagnosticsEnabled, logStartupDiagnostic } from './startup/startup-diagnostics'
+import { ensureWindowsUserDataAclGrant } from './startup/windows-user-data-acl'
import { RateLimitService } from './rate-limits/service'
import { getInitialClaudeRateLimitTarget } from './rate-limits/claude-rate-limit-target'
import { getInitialCodexRateLimitTarget } from './rate-limits/codex-rate-limit-target'
@@ -281,6 +281,14 @@ if (startupDiagnosticsEnabled) {
})
}
+// Why: startup benchmarking needs in-process timestamps — harness-side stderr
+// arrival times include pipe buffering jitter. `t` is ms since process start.
+function logStartupMilestone(event: string, details: Record = {}): void {
+ if (startupDiagnosticsEnabled) {
+ logStartupDiagnostic(event, { t: Math.round(performance.now()), ...details })
+ }
+}
+
function focusExistingWindow(): void {
focusExistingMainWindow({
app,
@@ -467,6 +475,7 @@ function prepareCodexRuntimeHomeForLaunch(target?: CodexAccountSelectionTarget):
}
function openMainWindow(): BrowserWindow {
+ logStartupMilestone('open-main-window-start')
if (!store) {
throw new Error('Store must be initialized before opening the main window')
}
@@ -510,16 +519,21 @@ function openMainWindow(): BrowserWindow {
}
// Why: Chromium's BrowserWindow constructor resets the userData DACL to a
- // Protected DACL. Grant explicit Full Control ACEs on all existing children
- // before the constructor runs so they survive the upcoming DACL reset.
- // Per-write EPERM retries in fs-utils/installer-utils serve as the backstop
- // for any directories created after startup.
+ // Protected DACL, breaking writes in pre-existing subdirs. Explicit ACEs on
+ // userData + immediate children fix the tree permanently; the grant runs in
+ // the background on first launch only (marker-gated) because the previous
+ // synchronous recursive walk blocked startup ~60s on large profiles. See
+ // startup/windows-user-data-acl.ts; per-write EPERM retries are the backstop.
if (process.platform === 'win32') {
- try {
- grantDirAcl(app.getPath('userData'), { recursive: true })
- } catch {
- // Non-fatal; per-call retries are the backstop.
- }
+ logStartupMilestone('acl-grant-start')
+ ensureWindowsUserDataAclGrant(app.getPath('userData'), {
+ onDone: (result) => {
+ logStartupMilestone('acl-grant-done', { mode: result.mode })
+ if (result.mode === 'failed') {
+ console.warn('[win32-acl] userData ACL grant failed:', result.reason)
+ }
+ }
+ })
}
const window = createMainWindow(store, {
@@ -564,6 +578,10 @@ function openMainWindow(): BrowserWindow {
}
})
recordCrashBreadcrumb('main_window_created')
+ logStartupMilestone('window-created')
+ window.once('ready-to-show', () => {
+ logStartupMilestone('ready-to-show')
+ })
// Why: telemetry-plan.md§First-launch experience anchors default-on
// `app_opened` to the first main-window load. Existing users in the
@@ -573,6 +591,7 @@ function openMainWindow(): BrowserWindow {
const onFirstWindowLoad = (): void => {
clearExpectedRendererReload(rendererWebContentsId)
recordCrashBreadcrumb('main_window_loaded')
+ logStartupMilestone('did-finish-load')
if (!store) {
return
}
@@ -715,6 +734,7 @@ function openMainWindow(): BrowserWindow {
})
}
})
+ logStartupMilestone('load-start')
loadMainWindow(window)
return window
}
@@ -1112,10 +1132,12 @@ function driveSyntheticTitleFromHook(
}
app.whenReady().then(async () => {
+ logStartupMilestone('app-ready')
electronApp.setAppUserModelId(devInstanceIdentity.appUserModelId)
app.setName(devInstanceIdentity.name)
store = new Store()
+ logStartupMilestone('store-loaded')
applyAppIcon(store.getSettings().appIcon)
if (shouldSuppressDevEducation({ isDev: is.dev })) {
suppressDevEducationForStore(store)
@@ -1276,8 +1298,10 @@ app.whenReady().then(async () => {
})
})
+ logStartupMilestone('services-initialized')
await ensureMainI18n()
await setMainUiLanguage(store.getSettings().uiLanguage)
+ logStartupMilestone('i18n-ready')
registerAppMenu({
onCheckForUpdates: (options) => checkForUpdatesFromMenu(options),
diff --git a/src/main/opencode/hook-plugin-message-part-throttle.test.ts b/src/main/opencode/hook-plugin-message-part-throttle.test.ts
new file mode 100644
index 00000000000..d53fe826665
--- /dev/null
+++ b/src/main/opencode/hook-plugin-message-part-throttle.test.ts
@@ -0,0 +1,203 @@
+/**
+ * Executes the generated OpenCode plugin source (the artifact that runs inside
+ * OpenCode's process) to verify streamed message.part.updated events are
+ * coalesced and capped before POSTing to Orca's agent-hook server. The
+ * un-throttled plugin re-posted the full accumulated reply per streamed
+ * append — O(n²) bytes per turn — which saturated Orca's main + renderer
+ * event loops on Windows and froze the UI mid-reply.
+ */
+import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
+import { tmpdir } from 'node:os'
+import { join } from 'node:path'
+import { pathToFileURL } from 'node:url'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+
+const { getPathMock } = vi.hoisted(() => ({
+ getPathMock: vi.fn<(name: string) => string>()
+}))
+
+vi.mock('electron', () => ({
+ app: {
+ getPath: getPathMock
+ }
+}))
+
+import { _internals } from './hook-service'
+
+type RecordedPost = {
+ url: string
+ body: {
+ paneKey: string
+ payload: { hook_event_name: string; role?: string; text?: string }
+ }
+}
+
+type PluginEventHandler = (input: { event: unknown }) => Promise
+
+const ENV_KEYS = ['ORCA_PANE_KEY', 'ORCA_AGENT_HOOK_PORT', 'ORCA_AGENT_HOOK_TOKEN'] as const
+
+describe('OpenCode plugin MessagePart throttling', () => {
+ let tempDir: string
+ let posts: RecordedPost[]
+ let savedEnv: Record
+ let savedFetch: typeof globalThis.fetch
+
+ beforeEach(() => {
+ tempDir = mkdtempSync(join(tmpdir(), 'orca-opencode-plugin-test-'))
+ posts = []
+ savedEnv = {}
+ for (const key of ENV_KEYS) {
+ savedEnv[key] = process.env[key]
+ }
+ process.env.ORCA_PANE_KEY = 'tab-1:leaf-1'
+ process.env.ORCA_AGENT_HOOK_PORT = '45678'
+ process.env.ORCA_AGENT_HOOK_TOKEN = 'test-token'
+ savedFetch = globalThis.fetch
+ globalThis.fetch = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {
+ posts.push({ url: String(url), body: JSON.parse(String(init?.body)) })
+ return new Response(null, { status: 204 })
+ }) as typeof globalThis.fetch
+ vi.useFakeTimers()
+ })
+
+ afterEach(() => {
+ vi.useRealTimers()
+ globalThis.fetch = savedFetch
+ for (const key of ENV_KEYS) {
+ if (savedEnv[key] === undefined) {
+ delete process.env[key]
+ } else {
+ process.env[key] = savedEnv[key]
+ }
+ }
+ rmSync(tempDir, { recursive: true, force: true })
+ })
+
+ async function loadPluginEventHandler(): Promise {
+ const pluginPath = join(tempDir, 'orca-opencode-status.mjs')
+ writeFileSync(pluginPath, _internals.getOpenCodePluginSource())
+ const module = (await import(pathToFileURL(pluginPath).href)) as {
+ OrcaOpenCodeStatusPlugin: (ctx: unknown) => Promise<{ event: PluginEventHandler }>
+ }
+ const client = {
+ session: {
+ // No parentID → root session, events flow through.
+ list: async () => ({ data: [{ id: 'session-1' }] })
+ }
+ }
+ const hooks = await module.OrcaOpenCodeStatusPlugin({ client })
+ return hooks.event
+ }
+
+ function assistantPartEvent(text: string): { event: unknown } {
+ return {
+ event: {
+ type: 'message.part.updated',
+ properties: {
+ sessionID: 'session-1',
+ part: { type: 'text', text, messageID: 'msg-assistant' }
+ }
+ }
+ }
+ }
+
+ async function seedAssistantRole(handler: PluginEventHandler): Promise {
+ await handler({
+ event: {
+ type: 'message.updated',
+ properties: {
+ sessionID: 'session-1',
+ info: { id: 'msg-assistant', role: 'assistant' }
+ }
+ }
+ })
+ }
+
+ function messagePartPosts(): RecordedPost[] {
+ return posts.filter((post) => post.body.payload.hook_event_name === 'MessagePart')
+ }
+
+ it('coalesces a streamed reply into leading + trailing posts with capped text', async () => {
+ const handler = await loadPluginEventHandler()
+ await seedAssistantRole(handler)
+
+ // Simulate a streaming turn: 50 part updates, each carrying the full
+ // accumulated text so far (how OpenCode actually publishes parts).
+ let text = ''
+ for (let i = 0; i < 50; i++) {
+ text += 'chunk-of-streamed-reply-text-'.repeat(10)
+ await handler(assistantPartEvent(text))
+ }
+
+ // Leading edge only — everything else is pending behind the throttle.
+ expect(messagePartPosts()).toHaveLength(1)
+
+ await vi.advanceTimersByTimeAsync(300)
+
+ const parts = messagePartPosts()
+ expect(parts).toHaveLength(2)
+ // Trailing post carries the LATEST snapshot, capped.
+ const trailing = parts[1].body.payload
+ expect(trailing.text!.length).toBeLessThanOrEqual(4000)
+ expect(text.startsWith(trailing.text!)).toBe(true)
+ })
+
+ it('flushes the pending reply snapshot before posting SessionIdle', async () => {
+ const handler = await loadPluginEventHandler()
+ await seedAssistantRole(handler)
+ // Mark the session busy so the idle transition is not deduped away.
+ await handler({
+ event: {
+ type: 'session.status',
+ properties: { sessionID: 'session-1', status: { type: 'busy' } }
+ }
+ })
+ posts.length = 0
+
+ await handler(assistantPartEvent('first'))
+ await handler(assistantPartEvent('first final'))
+ expect(messagePartPosts()).toHaveLength(1)
+
+ await handler({
+ event: { type: 'session.idle', properties: { sessionID: 'session-1' } }
+ })
+
+ const eventNames = posts.map((post) => post.body.payload.hook_event_name)
+ expect(eventNames).toEqual(['MessagePart', 'MessagePart', 'SessionIdle'])
+ expect(posts[1].body.payload.text).toBe('first final')
+ })
+
+ it('posts user prompts immediately without consuming the assistant throttle slot', async () => {
+ const handler = await loadPluginEventHandler()
+ await handler({
+ event: {
+ type: 'message.updated',
+ properties: {
+ sessionID: 'session-1',
+ info: { id: 'msg-user', role: 'user' }
+ }
+ }
+ })
+
+ await handler({
+ event: {
+ type: 'message.part.updated',
+ properties: {
+ sessionID: 'session-1',
+ part: { type: 'text', text: 'u'.repeat(10_000), messageID: 'msg-user' }
+ }
+ }
+ })
+
+ const parts = messagePartPosts()
+ expect(parts).toHaveLength(1)
+ expect(parts[0].body.payload.role).toBe('user')
+ expect(parts[0].body.payload.text!.length).toBe(4000)
+
+ // An assistant part right after the user prompt still posts immediately
+ // (leading edge) because user posts do not touch the throttle clock.
+ await seedAssistantRole(handler)
+ await handler(assistantPartEvent('assistant reply'))
+ expect(messagePartPosts()).toHaveLength(2)
+ })
+})
diff --git a/src/main/opencode/hook-service.test.ts b/src/main/opencode/hook-service.test.ts
index add20ca79e2..99b6b070ef4 100644
--- a/src/main/opencode/hook-service.test.ts
+++ b/src/main/opencode/hook-service.test.ts
@@ -114,8 +114,10 @@ describe('OpenCode hook plugin source', () => {
const source = _internals.getOpenCodePluginSource()
expect(source).toContain(
- 'await post("MessagePart", { role, text: part.text, messageID: part.messageID, sessionID });'
+ 'await post("MessagePart", { role, text: capMessagePartText(part.text), messageID: part.messageID, sessionID });'
)
+ expect(source).toContain('messageID: pending.messageID,')
+ expect(source).toContain('sessionID: pending.sessionID,')
expect(source).toContain('await setStatus("busy", { sessionID });')
expect(source.match(/await setStatus\("idle", \{ sessionID \}\);/g) ?? []).toHaveLength(2)
})
diff --git a/src/main/opencode/hook-service.ts b/src/main/opencode/hook-service.ts
index ff0d9bde7d8..ddc727d534c 100644
--- a/src/main/opencode/hook-service.ts
+++ b/src/main/opencode/hook-service.ts
@@ -160,6 +160,57 @@ function getOpenCodePluginSource(): string {
'let lastStatus = "idle";',
'const childSessionById = new Map();',
'',
+ '// Why: message.part.updated re-sends the FULL accumulated text of the part',
+ '// after every streamed append, so posting each event forwards O(n^2) bytes',
+ '// per turn through Orca (loopback HTTP -> main JSON parse -> status compare',
+ '// -> IPC -> renderer store update -> React commit). On Windows that flood',
+ '// saturated both event loops and froze the whole UI a few seconds into a',
+ '// streaming reply. The dashboard only needs a bounded preview at a human',
+ '// cadence: cap the text and trailing-edge coalesce assistant parts.',
+ 'const MESSAGE_PART_THROTTLE_MS = 250;',
+ 'const MESSAGE_PART_MAX_CHARS = 4000;',
+ 'let pendingAssistantPart = null;',
+ 'let assistantPartFlushTimer = null;',
+ 'let lastAssistantPartPostAt = 0;',
+ '',
+ 'function capMessagePartText(text) {',
+ ' return text.length > MESSAGE_PART_MAX_CHARS ? text.slice(0, MESSAGE_PART_MAX_CHARS) : text;',
+ '}',
+ '',
+ 'async function flushPendingAssistantPart() {',
+ ' if (assistantPartFlushTimer) {',
+ ' clearTimeout(assistantPartFlushTimer);',
+ ' assistantPartFlushTimer = null;',
+ ' }',
+ ' const pending = pendingAssistantPart;',
+ ' pendingAssistantPart = null;',
+ ' if (!pending) return;',
+ ' lastAssistantPartPostAt = Date.now();',
+ ' await post("MessagePart", {',
+ ' role: pending.role,',
+ ' text: capMessagePartText(pending.text),',
+ ' messageID: pending.messageID,',
+ ' sessionID: pending.sessionID,',
+ ' });',
+ '}',
+ '',
+ 'function queueAssistantPart(part) {',
+ ' // Why: keep only the latest snapshot — each event already contains the',
+ ' // full accumulated text, so intermediate snapshots are pure waste.',
+ ' pendingAssistantPart = part;',
+ ' const sinceLastPost = Date.now() - lastAssistantPartPostAt;',
+ ' if (sinceLastPost >= MESSAGE_PART_THROTTLE_MS) {',
+ ' void flushPendingAssistantPart();',
+ ' return;',
+ ' }',
+ ' if (!assistantPartFlushTimer) {',
+ ' assistantPartFlushTimer = setTimeout(() => {',
+ ' void flushPendingAssistantPart();',
+ ' }, MESSAGE_PART_THROTTLE_MS - sinceLastPost);',
+ ' if (assistantPartFlushTimer.unref) assistantPartFlushTimer.unref();',
+ ' }',
+ '}',
+ '',
'// Why: message.part.updated fires for every Part (text, tool, reasoning)',
'// but does not include the message role — that lives on the parent',
'// message.updated event. Cache the role per messageID so the plugin can',
@@ -312,11 +363,21 @@ function getOpenCodePluginSource(): string {
' if (!part || part.type !== "text" || !part.text) return;',
' const role = messageRoleById.get(part.messageID);',
' if (!role) return;',
- ' await post("MessagePart", { role, text: part.text, messageID: part.messageID, sessionID });',
+ ' if (role === "user") {',
+ ' // Why: user prompts arrive as a single event, not a stream — post',
+ ' // immediately (still capped) so the throttle slot stays free for',
+ ' // the assistant reply that follows within the same window.',
+ ' await post("MessagePart", { role, text: capMessagePartText(part.text), messageID: part.messageID, sessionID });',
+ ' return;',
+ ' }',
+ ' queueAssistantPart({ role, text: part.text, messageID: part.messageID, sessionID });',
' return;',
' }',
'',
' if (event.type === "session.idle" || event.type === "session.error") {',
+ ' // Why: flush the coalesced final reply snapshot before the idle',
+ ' // transition so the done-state preview shows the completed message.',
+ ' await flushPendingAssistantPart();',
' await setStatus("idle", { sessionID });',
' return;',
' }',
diff --git a/src/main/startup/hydrate-shell-path.test.ts b/src/main/startup/hydrate-shell-path.test.ts
index ebd235d59cc..77213324903 100644
--- a/src/main/startup/hydrate-shell-path.test.ts
+++ b/src/main/startup/hydrate-shell-path.test.ts
@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { EventEmitter } from 'events'
+import { delimiter } from 'node:path'
import type { ChildProcessWithoutNullStreams } from 'child_process'
import {
_resetHydrateShellPathCache,
@@ -169,30 +170,37 @@ describe('mergePathSegments', () => {
}
})
+ // Why: mergePathSegments joins with the platform PATH delimiter, so the
+ // expectations must too — hardcoding ':' made this suite fail on Windows
+ // dev machines even though the code under test was correct.
+ const joinPath = (...segments: string[]): string => segments.join(delimiter)
+
it('prepends new segments ahead of existing PATH entries', () => {
- process.env.PATH = '/usr/bin:/bin'
+ process.env.PATH = joinPath('/usr/bin', '/bin')
const added = mergePathSegments(['/Users/tester/.opencode/bin', '/Users/tester/.cargo/bin'])
expect(added).toEqual(['/Users/tester/.opencode/bin', '/Users/tester/.cargo/bin'])
expect(process.env.PATH).toBe(
- '/Users/tester/.opencode/bin:/Users/tester/.cargo/bin:/usr/bin:/bin'
+ joinPath('/Users/tester/.opencode/bin', '/Users/tester/.cargo/bin', '/usr/bin', '/bin')
)
})
it('skips segments already on PATH so re-hydration is a no-op', () => {
- process.env.PATH = '/Users/tester/.cargo/bin:/usr/bin'
+ process.env.PATH = joinPath('/Users/tester/.cargo/bin', '/usr/bin')
const added = mergePathSegments(['/Users/tester/.cargo/bin', '/Users/tester/.opencode/bin'])
expect(added).toEqual(['/Users/tester/.opencode/bin'])
- expect(process.env.PATH).toBe('/Users/tester/.opencode/bin:/Users/tester/.cargo/bin:/usr/bin')
+ expect(process.env.PATH).toBe(
+ joinPath('/Users/tester/.opencode/bin', '/Users/tester/.cargo/bin', '/usr/bin')
+ )
})
it('returns [] and leaves PATH untouched when given nothing', () => {
- process.env.PATH = '/usr/bin:/bin'
+ process.env.PATH = joinPath('/usr/bin', '/bin')
expect(mergePathSegments([])).toEqual([])
- expect(process.env.PATH).toBe('/usr/bin:/bin')
+ expect(process.env.PATH).toBe(joinPath('/usr/bin', '/bin'))
})
})
diff --git a/src/main/startup/windows-user-data-acl.test.ts b/src/main/startup/windows-user-data-acl.test.ts
new file mode 100644
index 00000000000..b49510b0bb1
--- /dev/null
+++ b/src/main/startup/windows-user-data-acl.test.ts
@@ -0,0 +1,135 @@
+import { EventEmitter } from 'node:events'
+import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
+import os from 'node:os'
+import { join } from 'node:path'
+import { afterEach, beforeEach, describe, expect, it } from 'vitest'
+import {
+ ensureWindowsUserDataAclGrant,
+ WINDOWS_ACL_GRANT_MARKER_FILE,
+ WINDOWS_ACL_GRANT_SCHEME_VERSION,
+ type WindowsAclGrantResult
+} from './windows-user-data-acl'
+
+type SpawnCall = { target: string; args: string[] }
+
+function createFakeSpawn(exitCode: number): {
+ calls: SpawnCall[]
+ spawnFn: (command: string, args?: readonly string[], options?: unknown) => EventEmitter
+} {
+ const calls: SpawnCall[] = []
+ return {
+ calls,
+ spawnFn: (_command: string, args: readonly string[] = []) => {
+ calls.push({ target: args[0] ?? '', args: [...args] })
+ const child = new EventEmitter() as EventEmitter & { kill: () => void }
+ child.kill = () => undefined
+ setImmediate(() => child.emit('exit', exitCode))
+ return child
+ }
+ }
+}
+
+function awaitResult(
+ userDataPath: string,
+ options: Parameters[1]
+): Promise {
+ return new Promise((resolve) => {
+ ensureWindowsUserDataAclGrant(userDataPath, { ...options, onDone: resolve })
+ })
+}
+
+describe('ensureWindowsUserDataAclGrant', () => {
+ let userDataPath: string
+
+ beforeEach(() => {
+ userDataPath = mkdtempSync(join(os.tmpdir(), 'orca-acl-test-'))
+ })
+
+ afterEach(() => {
+ rmSync(userDataPath, { recursive: true, force: true })
+ })
+
+ it('grants children + root then writes the marker', async () => {
+ const fake = createFakeSpawn(0)
+ const result = await awaitResult(userDataPath, {
+ identity: 'testuser',
+ spawnFn: fake.spawnFn as never
+ })
+ expect(result).toEqual({ mode: 'granted' })
+ expect(fake.calls).toHaveLength(2)
+ expect(fake.calls[0].target).toBe(join(userDataPath, '*'))
+ expect(fake.calls[1].target).toBe(userDataPath)
+ expect(fake.calls[0].args).toContain('testuser:(OI)(CI)(F)')
+ const marker = JSON.parse(
+ readFileSync(join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE), 'utf-8')
+ )
+ expect(marker.schemeVersion).toBe(WINDOWS_ACL_GRANT_SCHEME_VERSION)
+ expect(marker.identity).toBe('testuser')
+ })
+
+ it('skips all spawns when the marker matches the identity', async () => {
+ writeFileSync(
+ join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE),
+ JSON.stringify({
+ schemeVersion: WINDOWS_ACL_GRANT_SCHEME_VERSION,
+ identity: 'testuser',
+ grantedAt: 1
+ })
+ )
+ const fake = createFakeSpawn(0)
+ const result = await awaitResult(userDataPath, {
+ identity: 'testuser',
+ spawnFn: fake.spawnFn as never
+ })
+ expect(result).toEqual({ mode: 'marker-hit' })
+ expect(fake.calls).toHaveLength(0)
+ })
+
+ it('re-grants when the marker belongs to a different identity', async () => {
+ writeFileSync(
+ join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE),
+ JSON.stringify({
+ schemeVersion: WINDOWS_ACL_GRANT_SCHEME_VERSION,
+ identity: 'someone-else',
+ grantedAt: 1
+ })
+ )
+ const fake = createFakeSpawn(0)
+ const result = await awaitResult(userDataPath, {
+ identity: 'testuser',
+ spawnFn: fake.spawnFn as never
+ })
+ expect(result).toEqual({ mode: 'granted' })
+ expect(fake.calls).toHaveLength(2)
+ })
+
+ it('does not write the marker when icacls fails, so the next launch retries', async () => {
+ const fake = createFakeSpawn(5)
+ const result = await awaitResult(userDataPath, {
+ identity: 'testuser',
+ spawnFn: fake.spawnFn as never
+ })
+ expect(result).toEqual({ mode: 'failed', reason: 'exit 5; exit 5' })
+ expect(() => readFileSync(join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE))).toThrow()
+ })
+
+ it('no-ops without a resolvable identity', async () => {
+ const fake = createFakeSpawn(0)
+ const result = await awaitResult(userDataPath, {
+ identity: null,
+ spawnFn: fake.spawnFn as never
+ })
+ expect(result).toEqual({ mode: 'no-identity' })
+ expect(fake.calls).toHaveLength(0)
+ })
+
+ it('ignores a corrupt marker and re-grants', async () => {
+ writeFileSync(join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE), '{not json')
+ const fake = createFakeSpawn(0)
+ const result = await awaitResult(userDataPath, {
+ identity: 'testuser',
+ spawnFn: fake.spawnFn as never
+ })
+ expect(result).toEqual({ mode: 'granted' })
+ })
+})
diff --git a/src/main/startup/windows-user-data-acl.ts b/src/main/startup/windows-user-data-acl.ts
new file mode 100644
index 00000000000..bf1e1d01f05
--- /dev/null
+++ b/src/main/startup/windows-user-data-acl.ts
@@ -0,0 +1,163 @@
+import { spawn } from 'node:child_process'
+import { readFileSync, writeFileSync } from 'node:fs'
+import { join } from 'node:path'
+import { getIcaclsExePath, resolveCurrentWindowsIdentity } from '../win32-utils'
+
+/**
+ * Startup ACL grant for the win32 userData tree.
+ *
+ * Why this exists (PR #1152): Chromium's BrowserWindow constructor resets the
+ * userData DACL to a Protected DACL whose propagated child ACEs carry the
+ * Inherit-Only flag, so file writes inside pre-existing subdirectories
+ * (codex-runtime-home, agent-hooks, …) fail with EPERM. Explicit ACEs survive
+ * future DACL propagation, so granting them once fixes the tree permanently.
+ *
+ * Why not `icacls /T` synchronously (the previous implementation): NTFS
+ * inheritance is recalculated from the immediate parent, so explicit ACEs on
+ * userData + its immediate children already protect the whole tree — per-file
+ * ACEs on tens of thousands of Chromium cache files are pure waste. On a real
+ * 28k-file profile the recursive walk measured 62s, blocking the main thread
+ * before first paint and then *timing out* (60s cap), so users paid ~1 minute
+ * per launch for a grant that never completed.
+ *
+ * Strategy:
+ * - A marker file records that the grant completed for this identity. When it
+ * matches, startup performs zero icacls spawns.
+ * - When absent, the grant runs asynchronously (never blocks window creation):
+ * userData root + immediate children (`\*`). Per-write EPERM
+ * retries in codex-accounts/fs-utils and agent-hooks/installer-utils remain
+ * the backstop during the brief async window, exactly as they already were
+ * for the (common) case where the old synchronous walk timed out.
+ */
+
+export const WINDOWS_ACL_GRANT_MARKER_FILE = 'windows-acl-grant.json'
+export const WINDOWS_ACL_GRANT_SCHEME_VERSION = 1
+
+const GRANT_TIMEOUT_MS = 120_000
+
+type WindowsAclGrantMarker = {
+ schemeVersion: number
+ identity: string
+ grantedAt: number
+}
+
+export type WindowsAclGrantResult =
+ | { mode: 'marker-hit' }
+ | { mode: 'granted' }
+ | { mode: 'failed'; reason: string }
+ | { mode: 'no-identity' }
+
+type EnsureOptions = {
+ onDone?: (result: WindowsAclGrantResult) => void
+ /** Test seam — defaults to node:child_process spawn. */
+ spawnFn?: typeof spawn
+ /** Test seam — defaults to the real current-user identity. */
+ identity?: string | null
+}
+
+function readMarker(userDataPath: string): WindowsAclGrantMarker | null {
+ try {
+ const parsed = JSON.parse(
+ readFileSync(join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE), 'utf-8')
+ ) as Partial
+ if (
+ parsed.schemeVersion === WINDOWS_ACL_GRANT_SCHEME_VERSION &&
+ typeof parsed.identity === 'string'
+ ) {
+ return parsed as WindowsAclGrantMarker
+ }
+ } catch {
+ // missing or corrupt → re-grant
+ }
+ return null
+}
+
+function writeMarker(userDataPath: string, identity: string): void {
+ const marker: WindowsAclGrantMarker = {
+ schemeVersion: WINDOWS_ACL_GRANT_SCHEME_VERSION,
+ identity,
+ grantedAt: Date.now()
+ }
+ writeFileSync(join(userDataPath, WINDOWS_ACL_GRANT_MARKER_FILE), JSON.stringify(marker))
+}
+
+function runIcaclsGrant(
+ spawnFn: typeof spawn,
+ target: string,
+ identity: string
+): Promise<{ ok: boolean; reason?: string }> {
+ return new Promise((resolve) => {
+ // /C continues past per-entry errors (e.g. files locked by another
+ // process); a partial grant is still strictly better than none and the
+ // per-write EPERM backstop covers stragglers.
+ const child = spawnFn(
+ getIcaclsExePath(),
+ [target, '/grant:r', `${identity}:(OI)(CI)(F)`, '/C'],
+ {
+ stdio: 'ignore',
+ windowsHide: true
+ }
+ )
+ let settled = false
+ const settle = (ok: boolean, reason?: string): void => {
+ if (settled) {
+ return
+ }
+ settled = true
+ clearTimeout(timer)
+ resolve(ok ? { ok } : { ok, reason })
+ }
+ const timer = setTimeout(() => {
+ child.kill()
+ settle(false, 'timeout')
+ }, GRANT_TIMEOUT_MS)
+ timer.unref?.()
+ child.on('error', (error) => settle(false, error.message))
+ child.on('exit', (code) => settle(code === 0, code === 0 ? undefined : `exit ${code}`))
+ })
+}
+
+/**
+ * Ensure the userData tree carries explicit Full Control ACEs for the current
+ * user. Returns immediately; the grant itself (first launch only) runs in the
+ * background. Call before BrowserWindow creation on win32.
+ */
+export function ensureWindowsUserDataAclGrant(
+ userDataPath: string,
+ options: EnsureOptions = {}
+): void {
+ const onDone = options.onDone ?? ((): void => undefined)
+ const identity =
+ options.identity !== undefined ? options.identity : resolveCurrentWindowsIdentity()
+ if (!identity) {
+ onDone({ mode: 'no-identity' })
+ return
+ }
+ const marker = readMarker(userDataPath)
+ if (marker && marker.identity === identity) {
+ onDone({ mode: 'marker-hit' })
+ return
+ }
+ const spawnFn = options.spawnFn ?? spawn
+ void (async () => {
+ // Immediate children first: those explicit ACEs are the durable fix
+ // (Chromium replaces the root DACL on every BrowserWindow construction,
+ // but never strips explicit ACEs from children). Root second so writes
+ // directly under userData succeed before Chromium's first reset.
+ const children = await runIcaclsGrant(spawnFn, join(userDataPath, '*'), identity)
+ const root = await runIcaclsGrant(spawnFn, userDataPath, identity)
+ if (children.ok && root.ok) {
+ try {
+ writeMarker(userDataPath, identity)
+ onDone({ mode: 'granted' })
+ } catch (error) {
+ onDone({ mode: 'failed', reason: `marker write: ${String(error)}` })
+ }
+ return
+ }
+ onDone({
+ mode: 'failed',
+ reason: [children.reason, root.reason].filter(Boolean).join('; ') || 'unknown'
+ })
+ })()
+}
diff --git a/src/main/win32-utils.ts b/src/main/win32-utils.ts
index 550b16d03c3..a4b8dae1286 100644
--- a/src/main/win32-utils.ts
+++ b/src/main/win32-utils.ts
@@ -80,6 +80,10 @@ export function isPermissionError(error: unknown): boolean {
// and always available on Windows. Cached because it never changes in-process.
let cachedIdentity: string | null | undefined
+export function resolveCurrentWindowsIdentity(): string | null {
+ return resolveCurrentIdentity()
+}
+
function resolveCurrentIdentity(): string | null {
if (cachedIdentity !== undefined) {
return cachedIdentity
diff --git a/src/shared/agent-hook-listener.ts b/src/shared/agent-hook-listener.ts
index 1479e441280..8fae9c02995 100644
--- a/src/shared/agent-hook-listener.ts
+++ b/src/shared/agent-hook-listener.ts
@@ -47,6 +47,19 @@ const MAX_WARNED_KEYS = 32
/** Slowloris cap: drop requests that have not finished sending after 5 s. */
export const HOOK_REQUEST_SLOWLORIS_MS = 5_000
+/** Why: OpenCode plugin builds installed before the throttle/cap fix re-post
+ * the full accumulated reply text on every streamed part update (O(n²) bytes
+ * per turn). Capping at ingest bounds the per-event cost of the status
+ * compare, IPC fanout, renderer store update, and disk persist regardless of
+ * which plugin version is running inside the OpenCode process. */
+export const OPENCODE_HOOK_TEXT_MAX_CHARS = 8_000
+
+function capOpenCodeHookText(text: string): string {
+ return text.length > OPENCODE_HOOK_TEXT_MAX_CHARS
+ ? text.slice(0, OPENCODE_HOOK_TEXT_MAX_CHARS)
+ : text
+}
+
/** Bound paneKey size — `${tabId}:${leafUuid}` is well under 200 chars in
* practice; cap defends per-pane caches against pathological input.
* Exported so non-HTTP ingest paths (e.g. Orca's `ingestRemote`) can apply
@@ -320,7 +333,7 @@ function extractPromptText(hookPayload: Record): ExtractedPromp
// role === 'user', the text *is* the prompt — surface it even though
// OpenCode has no UserPromptSubmit-equivalent.
if (hookPayload.role === 'user' && typeof hookPayload.text === 'string') {
- const trimmed = hookPayload.text.trim()
+ const trimmed = capOpenCodeHookText(hookPayload.text.trim())
if (trimmed.length > 0) {
return { text: trimmed, source: 'role_user_text' }
}
@@ -1207,7 +1220,7 @@ function extractOpenCodeToolFields(
if (eventName === 'MessagePart' && hookPayload.role === 'assistant') {
const text = readString(hookPayload, 'text')
if (text) {
- return { lastAssistantMessage: text }
+ return { lastAssistantMessage: capOpenCodeHookText(text) }
}
}
return {}
diff --git a/tools/benchmarks/results/startup-acl-fix-2026-06-10T19-37-58-671Z.json b/tools/benchmarks/results/startup-acl-fix-2026-06-10T19-37-58-671Z.json
new file mode 100644
index 00000000000..4ad36ad4c6b
--- /dev/null
+++ b/tools/benchmarks/results/startup-acl-fix-2026-06-10T19-37-58-671Z.json
@@ -0,0 +1,445 @@
+{
+ "label": "acl-fix",
+ "platform": "win32",
+ "arch": "x64",
+ "cpus": "Intel(R) Core(TM) Ultra 9 185H",
+ "fixtureDir": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "fixtureFiles": 28000,
+ "exe": null,
+ "iterations": [
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 1734.3
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 1734.4
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 1741
+ },
+ "harnessMs": 1770.3
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 1747
+ },
+ "harnessMs": 1776
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 1890
+ },
+ "harnessMs": 1919.4
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 1892
+ },
+ "harnessMs": 1921.1
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 1899
+ },
+ "harnessMs": 1928.3
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 1899
+ },
+ "harnessMs": 1928.3
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 1935
+ },
+ "harnessMs": 1964.6
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 1958
+ },
+ "harnessMs": 1987.2
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 3263
+ },
+ "harnessMs": 3292.4
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 3264
+ },
+ "harnessMs": 3292.8
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 1770.3,
+ "appReadyToServices": 149,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": null,
+ "windowCreatedToLoaded": 1329,
+ "totalToWindowCreated": 1964.6,
+ "totalToDidFinishLoad": 3292.8
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 716.3
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 716.3
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 731
+ },
+ "harnessMs": 762.5
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 738
+ },
+ "harnessMs": 769.1
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 886
+ },
+ "harnessMs": 917.3
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 888
+ },
+ "harnessMs": 919.2
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 894
+ },
+ "harnessMs": 925.4
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 894
+ },
+ "harnessMs": 925.4
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 938
+ },
+ "harnessMs": 968.6
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 957
+ },
+ "harnessMs": 988
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 2088
+ },
+ "harnessMs": 2119.2
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 2089
+ },
+ "harnessMs": 2119.5
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 762.5,
+ "appReadyToServices": 155,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 6,
+ "aclGrantMs": null,
+ "windowCreatedToLoaded": 1151,
+ "totalToWindowCreated": 968.6,
+ "totalToDidFinishLoad": 2119.5
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 600.7
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 600.7
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 613
+ },
+ "harnessMs": 639.3
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 618
+ },
+ "harnessMs": 644.5
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 744
+ },
+ "harnessMs": 771
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 746
+ },
+ "harnessMs": 772.5
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 751
+ },
+ "harnessMs": 777.6
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 751
+ },
+ "harnessMs": 777.6
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 786
+ },
+ "harnessMs": 812.8
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 808
+ },
+ "harnessMs": 834.3
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 1873
+ },
+ "harnessMs": 1899.5
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 1873
+ },
+ "harnessMs": 1899.7
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 639.3,
+ "appReadyToServices": 131,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 5,
+ "aclGrantMs": null,
+ "windowCreatedToLoaded": 1087,
+ "totalToWindowCreated": 812.8,
+ "totalToDidFinishLoad": 1899.7
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 652.2
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 652.2
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 665
+ },
+ "harnessMs": 690.3
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 672
+ },
+ "harnessMs": 697.7
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 824
+ },
+ "harnessMs": 848.8
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 825
+ },
+ "harnessMs": 850.6
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 832
+ },
+ "harnessMs": 856.8
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 832
+ },
+ "harnessMs": 856.8
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 867
+ },
+ "harnessMs": 892
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 889
+ },
+ "harnessMs": 913.8
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 1926
+ },
+ "harnessMs": 1951.4
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 1927
+ },
+ "harnessMs": 1951.6
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 690.3,
+ "appReadyToServices": 159,
+ "servicesToI18n": 1,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": null,
+ "windowCreatedToLoaded": 1060,
+ "totalToWindowCreated": 892,
+ "totalToDidFinishLoad": 1951.6
+ }
+ }
+ ],
+ "summaryMedianMs": {
+ "spawnToAppReady": 726.4,
+ "appReadyToServices": 152,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 6.5,
+ "aclGrantMs": null,
+ "windowCreatedToLoaded": 1119,
+ "totalToWindowCreated": 930.3,
+ "totalToDidFinishLoad": 2035.55
+ }
+}
diff --git a/tools/benchmarks/results/startup-acl-fix-steady-2026-06-10T19-41-40-683Z.json b/tools/benchmarks/results/startup-acl-fix-steady-2026-06-10T19-41-40-683Z.json
new file mode 100644
index 00000000000..b0bb1076a43
--- /dev/null
+++ b/tools/benchmarks/results/startup-acl-fix-steady-2026-06-10T19-41-40-683Z.json
@@ -0,0 +1,363 @@
+{
+ "label": "acl-fix-steady",
+ "platform": "win32",
+ "arch": "x64",
+ "cpus": "Intel(R) Core(TM) Ultra 9 185H",
+ "fixtureDir": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "fixtureFiles": 28000,
+ "exe": null,
+ "iterations": [
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 690.7
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 690.7
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 700
+ },
+ "harnessMs": 733.2
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 707
+ },
+ "harnessMs": 740.1
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 865
+ },
+ "harnessMs": 897.8
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 866
+ },
+ "harnessMs": 899.6
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 873
+ },
+ "harnessMs": 906
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 873
+ },
+ "harnessMs": 906
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 913
+ },
+ "harnessMs": 946.6
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 936
+ },
+ "harnessMs": 969.2
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 2026
+ },
+ "harnessMs": 2059.3
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 2026
+ },
+ "harnessMs": 2059.4
+ },
+ {
+ "event": "acl-grant-done",
+ "details": {
+ "t": 7686,
+ "mode": "granted"
+ },
+ "harnessMs": 7719
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 733.2,
+ "appReadyToServices": 165,
+ "servicesToI18n": 1,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": 6813,
+ "windowCreatedToLoaded": 1113,
+ "totalToWindowCreated": 946.6,
+ "totalToDidFinishLoad": 2059.4
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 605.1
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 605.1
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 611
+ },
+ "harnessMs": 638.3
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 617
+ },
+ "harnessMs": 644.2
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 748
+ },
+ "harnessMs": 775.3
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 750
+ },
+ "harnessMs": 777.6
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 757
+ },
+ "harnessMs": 784.2
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 757
+ },
+ "harnessMs": 784.2
+ },
+ {
+ "event": "acl-grant-done",
+ "details": {
+ "t": 757,
+ "mode": "marker-hit"
+ },
+ "harnessMs": 784.7
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 786
+ },
+ "harnessMs": 813.9
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 808
+ },
+ "harnessMs": 835.1
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 1768
+ },
+ "harnessMs": 1795.2
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 1768
+ },
+ "harnessMs": 1795.3
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 638.3,
+ "appReadyToServices": 137,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": 0,
+ "windowCreatedToLoaded": 982,
+ "totalToWindowCreated": 813.9,
+ "totalToDidFinishLoad": 1795.3
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 575
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 575
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 584
+ },
+ "harnessMs": 607.5
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 589
+ },
+ "harnessMs": 613.1
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 724
+ },
+ "harnessMs": 747.2
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 725
+ },
+ "harnessMs": 749
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 731
+ },
+ "harnessMs": 754.1
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 731
+ },
+ "harnessMs": 754.1
+ },
+ {
+ "event": "acl-grant-done",
+ "details": {
+ "t": 731,
+ "mode": "marker-hit"
+ },
+ "harnessMs": 754.5
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 757
+ },
+ "harnessMs": 780.3
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 777
+ },
+ "harnessMs": 801
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 1685
+ },
+ "harnessMs": 1708.4
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 1685
+ },
+ "harnessMs": 1708.6
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 607.5,
+ "appReadyToServices": 140,
+ "servicesToI18n": 1,
+ "i18nToOpenWindow": 6,
+ "aclGrantMs": 0,
+ "windowCreatedToLoaded": 928,
+ "totalToWindowCreated": 780.3,
+ "totalToDidFinishLoad": 1708.6
+ }
+ }
+ ],
+ "summaryMedianMs": {
+ "spawnToAppReady": 638.3,
+ "appReadyToServices": 140,
+ "servicesToI18n": 1,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": 0,
+ "windowCreatedToLoaded": 982,
+ "totalToWindowCreated": 813.9,
+ "totalToDidFinishLoad": 1795.3
+ }
+}
diff --git a/tools/benchmarks/results/startup-baseline-2026-06-10T19-36-01-305Z.json b/tools/benchmarks/results/startup-baseline-2026-06-10T19-36-01-305Z.json
new file mode 100644
index 00000000000..f535defe03b
--- /dev/null
+++ b/tools/benchmarks/results/startup-baseline-2026-06-10T19-36-01-305Z.json
@@ -0,0 +1,363 @@
+{
+ "label": "baseline",
+ "platform": "win32",
+ "arch": "x64",
+ "cpus": "Intel(R) Core(TM) Ultra 9 185H",
+ "fixtureDir": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "fixtureFiles": 28000,
+ "exe": null,
+ "iterations": [
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 7624.5
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 7624.6
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 7639
+ },
+ "harnessMs": 7672.5
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 7642
+ },
+ "harnessMs": 7674.8
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 8477
+ },
+ "harnessMs": 8510.9
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 8480
+ },
+ "harnessMs": 8513
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 8488
+ },
+ "harnessMs": 8521
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 8488
+ },
+ "harnessMs": 8521
+ },
+ {
+ "event": "acl-grant-done",
+ "details": {
+ "t": 24135,
+ "ok": true
+ },
+ "harnessMs": 24168.5
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 24164
+ },
+ "harnessMs": 24197.8
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 24184
+ },
+ "harnessMs": 24217.3
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 26021
+ },
+ "harnessMs": 26054
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 26021
+ },
+ "harnessMs": 26054.2
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 7672.5,
+ "appReadyToServices": 838,
+ "servicesToI18n": 3,
+ "i18nToOpenWindow": 8,
+ "aclGrantMs": 15647,
+ "windowCreatedToLoaded": 1857,
+ "totalToWindowCreated": 24197.8,
+ "totalToDidFinishLoad": 26054.2
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 811.3
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 811.4
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 822
+ },
+ "harnessMs": 857.3
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 830
+ },
+ "harnessMs": 864.8
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 1000
+ },
+ "harnessMs": 1035.6
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 1002
+ },
+ "harnessMs": 1037.3
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 1009
+ },
+ "harnessMs": 1044.4
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 1009
+ },
+ "harnessMs": 1044.5
+ },
+ {
+ "event": "acl-grant-done",
+ "details": {
+ "t": 18191,
+ "ok": true
+ },
+ "harnessMs": 18226.3
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 18219
+ },
+ "harnessMs": 18254.6
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 18241
+ },
+ "harnessMs": 18275.9
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 19278
+ },
+ "harnessMs": 19312.8
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 19278
+ },
+ "harnessMs": 19313
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 857.3,
+ "appReadyToServices": 178,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": 17182,
+ "windowCreatedToLoaded": 1059,
+ "totalToWindowCreated": 18254.6,
+ "totalToDidFinishLoad": 19313
+ }
+ },
+ {
+ "outcome": "ok",
+ "events": [
+ {
+ "event": "before-single-instance-lock",
+ "details": {
+ "version": "1.4.58",
+ "packaged": false,
+ "platform": "win32",
+ "osRelease": "10.0.26200",
+ "userData": "C:\\Users\\jinwo\\AppData\\Local\\Temp\\orca-startup-bench\\userdata-28000",
+ "e2eUserData": true
+ },
+ "harnessMs": 583.2
+ },
+ {
+ "event": "single-instance-lock-result",
+ "details": {
+ "acquired": true,
+ "bypassed": false,
+ "skippedForDev": true
+ },
+ "harnessMs": 583.2
+ },
+ {
+ "event": "app-ready",
+ "details": {
+ "t": 593
+ },
+ "harnessMs": 616.4
+ },
+ {
+ "event": "store-loaded",
+ "details": {
+ "t": 599
+ },
+ "harnessMs": 622.3
+ },
+ {
+ "event": "services-initialized",
+ "details": {
+ "t": 732
+ },
+ "harnessMs": 755.5
+ },
+ {
+ "event": "i18n-ready",
+ "details": {
+ "t": 734
+ },
+ "harnessMs": 757.6
+ },
+ {
+ "event": "open-main-window-start",
+ "details": {
+ "t": 740
+ },
+ "harnessMs": 763.7
+ },
+ {
+ "event": "acl-grant-start",
+ "details": {
+ "t": 740
+ },
+ "harnessMs": 763.7
+ },
+ {
+ "event": "acl-grant-done",
+ "details": {
+ "t": 14595,
+ "ok": true
+ },
+ "harnessMs": 14618.2
+ },
+ {
+ "event": "window-created",
+ "details": {
+ "t": 14621
+ },
+ "harnessMs": 14645
+ },
+ {
+ "event": "load-start",
+ "details": {
+ "t": 14640
+ },
+ "harnessMs": 14664
+ },
+ {
+ "event": "ready-to-show",
+ "details": {
+ "t": 15621
+ },
+ "harnessMs": 15644.5
+ },
+ {
+ "event": "did-finish-load",
+ "details": {
+ "t": 15621
+ },
+ "harnessMs": 15644.7
+ }
+ ],
+ "phases": {
+ "spawnToAppReady": 616.4,
+ "appReadyToServices": 139,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 6,
+ "aclGrantMs": 13855,
+ "windowCreatedToLoaded": 1000,
+ "totalToWindowCreated": 14645,
+ "totalToDidFinishLoad": 15644.7
+ }
+ }
+ ],
+ "summaryMedianMs": {
+ "spawnToAppReady": 857.3,
+ "appReadyToServices": 178,
+ "servicesToI18n": 2,
+ "i18nToOpenWindow": 7,
+ "aclGrantMs": 15647,
+ "windowCreatedToLoaded": 1059,
+ "totalToWindowCreated": 18254.6,
+ "totalToDidFinishLoad": 19313
+ }
+}
diff --git a/tools/benchmarks/startup-time-bench.mjs b/tools/benchmarks/startup-time-bench.mjs
new file mode 100644
index 00000000000..5e2f390bb79
--- /dev/null
+++ b/tools/benchmarks/startup-time-bench.mjs
@@ -0,0 +1,330 @@
+#!/usr/bin/env node
+/**
+ * Orca startup-time benchmark.
+ *
+ * Launches the built app (out/) against a synthetic userData fixture that
+ * mimics a long-lived real profile (tens of thousands of Chromium cache
+ * files — the documented pathological case for the win32 startup ACL grant),
+ * parses `ORCA_STARTUP_DIAGNOSTICS=1` milestone lines from stderr, and
+ * reports per-phase timings across iterations.
+ *
+ * Usage:
+ * node tools/benchmarks/startup-time-bench.mjs --label baseline
+ * [--iterations 5] [--files 28000] [--fixture-dir ]
+ * [--exe ] [--timeout-ms 240000]
+ *
+ * Prereq (when not using --exe): `pnpm build:electron-vite` so out/ exists.
+ * Results: tools/benchmarks/results/startup--.json
+ */
+import { spawn, spawnSync } from 'node:child_process'
+import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
+import os from 'node:os'
+import { dirname, join, resolve } from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+const scriptDir = dirname(fileURLToPath(import.meta.url))
+const repoRoot = resolve(scriptDir, '..', '..')
+
+function parseArgs(argv) {
+ const args = {
+ label: 'run',
+ iterations: 5,
+ files: 28000,
+ fixtureDir: null,
+ exe: null,
+ timeoutMs: 240000,
+ // How long the app stays alive after did-finish-load before the harness
+ // kills it. Raise to let background work (e.g. the async win32 ACL grant)
+ // complete the way it would in a real session.
+ lingerMs: 500
+ }
+ for (let i = 2; i < argv.length; i++) {
+ const next = () => argv[++i]
+ switch (argv[i]) {
+ case '--label':
+ args.label = next()
+ break
+ case '--iterations':
+ args.iterations = Number(next())
+ break
+ case '--files':
+ args.files = Number(next())
+ break
+ case '--fixture-dir':
+ args.fixtureDir = next()
+ break
+ case '--exe':
+ args.exe = next()
+ break
+ case '--timeout-ms':
+ args.timeoutMs = Number(next())
+ break
+ case '--linger-ms':
+ args.lingerMs = Number(next())
+ break
+ default:
+ throw new Error(`Unknown argument: ${argv[i]}`)
+ }
+ }
+ return args
+}
+
+/**
+ * Build a userData tree shaped like a real long-lived profile. The file count
+ * drives the win32 icacls walk cost; contents are irrelevant, so files are
+ * tiny. Layout mirrors Chromium cache dirs plus a few Orca-owned dirs.
+ */
+function ensureFixture(fixtureDir, fileCount) {
+ const manifestPath = join(fixtureDir, 'bench-fixture-manifest.json')
+ if (existsSync(manifestPath)) {
+ try {
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'))
+ if (manifest.files === fileCount) {
+ console.log(`[fixture] reusing ${fixtureDir} (${fileCount} files)`)
+ return
+ }
+ } catch {
+ // fall through and rebuild
+ }
+ }
+ console.log(`[fixture] creating ${fixtureDir} with ~${fileCount} synthetic files…`)
+ const buckets = [
+ ['Cache', 'Cache_Data'],
+ ['Code Cache', 'js'],
+ ['Code Cache', 'wasm'],
+ ['GPUCache'],
+ ['DawnGraphiteCache'],
+ ['blob_storage', 'blobs'],
+ ['Service Worker', 'CacheStorage'],
+ ['terminal-scrollback-snapshots']
+ ]
+ const payload = 'x'.repeat(1024)
+ let written = 0
+ const started = Date.now()
+ for (let b = 0; written < fileCount; b = (b + 1) % buckets.length) {
+ const dir = join(fixtureDir, ...buckets[b], `g${Math.floor(written / 512)}`)
+ mkdirSync(dir, { recursive: true })
+ const batch = Math.min(512, fileCount - written)
+ for (let i = 0; i < batch; i++) {
+ writeFileSync(join(dir, `f_${String(written + i).padStart(6, '0')}`), payload)
+ }
+ written += batch
+ }
+ writeFileSync(manifestPath, JSON.stringify({ files: fileCount, createdAt: Date.now() }))
+ console.log(`[fixture] done in ${((Date.now() - started) / 1000).toFixed(1)}s`)
+}
+
+function killProcessTree(proc) {
+ if (proc.exitCode !== null || proc.signalCode !== null) {
+ return
+ }
+ if (process.platform === 'win32') {
+ spawnSync('taskkill', ['/PID', String(proc.pid), '/T', '/F'], { stdio: 'ignore' })
+ } else {
+ try {
+ proc.kill('SIGKILL')
+ } catch {
+ // already gone
+ }
+ }
+}
+
+function parseStartupLine(line) {
+ const match = /^\[startup\] (\S+)(.*)$/.exec(line)
+ if (!match) {
+ return null
+ }
+ const details = {}
+ const detailText = match[2].trim()
+ if (detailText) {
+ for (const pair of detailText.match(/(\S+?)=("[^"]*"|\S+)/g) ?? []) {
+ const eq = pair.indexOf('=')
+ const key = pair.slice(0, eq)
+ let value = pair.slice(eq + 1)
+ try {
+ value = JSON.parse(value)
+ } catch {
+ // keep raw string
+ }
+ details[key] = value
+ }
+ }
+ return { event: match[1], details }
+}
+
+function runIteration({ exe, fixtureDir, timeoutMs, lingerMs }) {
+ return new Promise((resolvePromise) => {
+ const command = exe ?? join(repoRoot, 'node_modules', 'electron', 'dist', 'electron.exe')
+ const commandArgs = exe ? [] : [repoRoot]
+ const events = []
+ const startedAt = process.hrtime.bigint()
+ const child = spawn(command, commandArgs, {
+ env: {
+ ...process.env,
+ ORCA_STARTUP_DIAGNOSTICS: '1',
+ ORCA_E2E_USER_DATA_DIR: fixtureDir,
+ ORCA_E2E_HEADLESS: '1'
+ },
+ stdio: ['ignore', 'ignore', 'pipe']
+ })
+ let finished = false
+ let buffer = ''
+ const finish = (outcome) => {
+ if (finished) {
+ return
+ }
+ finished = true
+ clearTimeout(timer)
+ // Keep the app alive briefly so trailing diagnostic lines (and, with
+ // --linger-ms raised, background work like the async ACL grant) finish.
+ setTimeout(() => {
+ killProcessTree(child)
+ resolvePromise({ outcome, events })
+ }, lingerMs)
+ }
+ const timer = setTimeout(() => finish('timeout'), timeoutMs)
+ child.stderr.setEncoding('utf-8')
+ child.stderr.on('data', (chunk) => {
+ buffer += chunk
+ let newlineIndex = buffer.indexOf('\n')
+ while (newlineIndex !== -1) {
+ const line = buffer.slice(0, newlineIndex).trimEnd()
+ buffer = buffer.slice(newlineIndex + 1)
+ newlineIndex = buffer.indexOf('\n')
+ const parsed = parseStartupLine(line)
+ if (!parsed) {
+ continue
+ }
+ const harnessMs = Number(process.hrtime.bigint() - startedAt) / 1e6
+ events.push({ ...parsed, harnessMs: Math.round(harnessMs * 10) / 10 })
+ if (parsed.event === 'did-finish-load') {
+ finish('ok')
+ }
+ }
+ })
+ child.on('exit', () => finish('early-exit'))
+ child.on('error', () => finish('spawn-error'))
+ })
+}
+
+function eventTime(events, name, key) {
+ const entry = events.find((event) => event.event === name)
+ if (!entry) {
+ return null
+ }
+ return key === 't'
+ ? typeof entry.details.t === 'number'
+ ? entry.details.t
+ : null
+ : entry.harnessMs
+}
+
+function derivePhases(events) {
+ const aclStart = eventTime(events, 'acl-grant-start', 't')
+ const aclDone = eventTime(events, 'acl-grant-done', 't')
+ return {
+ spawnToAppReady: eventTime(events, 'app-ready', 'harness'),
+ appReadyToServices: delta(events, 'app-ready', 'services-initialized'),
+ servicesToI18n: delta(events, 'services-initialized', 'i18n-ready'),
+ i18nToOpenWindow: delta(events, 'i18n-ready', 'open-main-window-start'),
+ aclGrantMs: aclStart !== null && aclDone !== null ? aclDone - aclStart : null,
+ windowCreatedToLoaded: delta(events, 'window-created', 'did-finish-load'),
+ totalToWindowCreated: eventTime(events, 'window-created', 'harness'),
+ totalToDidFinishLoad: eventTime(events, 'did-finish-load', 'harness')
+ }
+}
+
+function delta(events, from, to) {
+ const a = eventTime(events, from, 't')
+ const b = eventTime(events, to, 't')
+ return a !== null && b !== null ? b - a : null
+}
+
+function median(values) {
+ const usable = values.filter((value) => typeof value === 'number').sort((a, b) => a - b)
+ if (usable.length === 0) {
+ return null
+ }
+ const mid = Math.floor(usable.length / 2)
+ return usable.length % 2 ? usable[mid] : (usable[mid - 1] + usable[mid]) / 2
+}
+
+function formatMs(value) {
+ if (value === null) {
+ return 'n/a'
+ }
+ return value >= 1000 ? `${(value / 1000).toFixed(2)}s` : `${Math.round(value)}ms`
+}
+
+async function main() {
+ const args = parseArgs(process.argv)
+ const fixtureDir = resolve(
+ args.fixtureDir ?? join(os.tmpdir(), 'orca-startup-bench', `userdata-${args.files}`)
+ )
+ mkdirSync(fixtureDir, { recursive: true })
+ ensureFixture(fixtureDir, args.files)
+
+ if (!args.exe && !existsSync(join(repoRoot, 'out', 'main', 'index.js'))) {
+ throw new Error('out/main/index.js missing — run `pnpm build:electron-vite` first')
+ }
+
+ const iterations = []
+ for (let i = 0; i < args.iterations; i++) {
+ process.stdout.write(`[bench] iteration ${i + 1}/${args.iterations}… `)
+ const result = await runIteration({
+ exe: args.exe,
+ fixtureDir,
+ timeoutMs: args.timeoutMs,
+ lingerMs: args.lingerMs
+ })
+ const phases = derivePhases(result.events)
+ iterations.push({ ...result, phases })
+ console.log(
+ `${result.outcome} total=${formatMs(phases.totalToDidFinishLoad)} acl=${formatMs(phases.aclGrantMs)}`
+ )
+ // Let the OS settle between launches (process teardown, file handles).
+ await new Promise((resolveSleep) => setTimeout(resolveSleep, 1500))
+ }
+
+ const phaseNames = Object.keys(iterations[0]?.phases ?? {})
+ const summary = {}
+ for (const name of phaseNames) {
+ summary[name] = median(iterations.map((iteration) => iteration.phases[name]))
+ }
+
+ const resultsDir = join(scriptDir, 'results')
+ mkdirSync(resultsDir, { recursive: true })
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-')
+ const outPath = join(resultsDir, `startup-${args.label}-${stamp}.json`)
+ writeFileSync(
+ outPath,
+ JSON.stringify(
+ {
+ label: args.label,
+ platform: process.platform,
+ arch: process.arch,
+ cpus: os.cpus()[0]?.model,
+ fixtureDir,
+ fixtureFiles: args.files,
+ exe: args.exe,
+ iterations,
+ summaryMedianMs: summary
+ },
+ null,
+ 2
+ )
+ )
+
+ console.log(`\n[bench] label=${args.label} (medians over ${iterations.length} runs)`)
+ console.log('| phase | median |')
+ console.log('|---|---|')
+ for (const name of phaseNames) {
+ console.log(`| ${name} | ${formatMs(summary[name])} |`)
+ }
+ console.log(`\n[bench] results written to ${outPath}`)
+}
+
+main().catch((error) => {
+ console.error(error)
+ process.exit(1)
+})
From c34b9cdce6f8ead276a27d174df4a9a26883cd43 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 10 Jun 2026 20:42:33 +0000
Subject: [PATCH 041/165] release: v1.4.59-rc.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 77964440fa9..6340418dbad 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca",
- "version": "1.4.58",
+ "version": "1.4.59-rc.0",
"description": "Next-gen IDE for parallel agentic development",
"homepage": "https://github.com/stablyai/orca",
"author": "stablyai",
From 6d7d25f7840de3f9f343c14e4451285a38eb2eac Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 14:03:55 -0700
Subject: [PATCH 042/165] Fix packaged shell PATH order (#5125)
Co-authored-by: Orca
---
src/main/startup/hydrate-shell-path.test.ts | 20 ++++++++++++--
src/main/startup/hydrate-shell-path.ts | 30 ++++++++++++---------
2 files changed, 36 insertions(+), 14 deletions(-)
diff --git a/src/main/startup/hydrate-shell-path.test.ts b/src/main/startup/hydrate-shell-path.test.ts
index 77213324903..5496fa93a8d 100644
--- a/src/main/startup/hydrate-shell-path.test.ts
+++ b/src/main/startup/hydrate-shell-path.test.ts
@@ -186,14 +186,30 @@ describe('mergePathSegments', () => {
)
})
- it('skips segments already on PATH so re-hydration is a no-op', () => {
+ it('promotes shell segments already on PATH so shell ordering wins', () => {
process.env.PATH = joinPath('/Users/tester/.cargo/bin', '/usr/bin')
const added = mergePathSegments(['/Users/tester/.cargo/bin', '/Users/tester/.opencode/bin'])
expect(added).toEqual(['/Users/tester/.opencode/bin'])
expect(process.env.PATH).toBe(
- joinPath('/Users/tester/.opencode/bin', '/Users/tester/.cargo/bin', '/usr/bin')
+ joinPath('/Users/tester/.cargo/bin', '/Users/tester/.opencode/bin', '/usr/bin')
+ )
+ })
+
+ it('moves user-local shell paths ahead of packaged Homebrew fallbacks', () => {
+ process.env.PATH = joinPath(
+ '/opt/homebrew/bin',
+ '/Users/tester/.local/bin',
+ '/usr/bin',
+ '/bin'
+ )
+
+ const added = mergePathSegments(['/Users/tester/.local/bin', '/opt/homebrew/bin'])
+
+ expect(added).toEqual([])
+ expect(process.env.PATH).toBe(
+ joinPath('/Users/tester/.local/bin', '/opt/homebrew/bin', '/usr/bin', '/bin')
)
})
diff --git a/src/main/startup/hydrate-shell-path.ts b/src/main/startup/hydrate-shell-path.ts
index 96c22145ba2..81768bbc272 100644
--- a/src/main/startup/hydrate-shell-path.ts
+++ b/src/main/startup/hydrate-shell-path.ts
@@ -181,25 +181,31 @@ export function hydrateShellPath(options: HydrateOptions = {}): Promise !existing.has(segment))
+ const merged = [
+ ...shellSegments,
+ ...currentSegments.filter((segment) => !shellSegmentSet.has(segment))
+ ]
+ const next = merged.join(delimiter)
+ if (next === current) {
return []
}
- // Why: prepend so shell-provided entries win over the hardcoded fallbacks.
- // The user's rc files are the source of truth for `which`-style resolution.
- process.env.PATH = [...added, ...current.split(delimiter).filter(Boolean)].join(delimiter)
+ // Why: shell-provided entries must win over hardcoded packaged-app fallbacks.
+ // A seeded fallback can point at a stale CLI while the user's shell resolves
+ // a healthy one from the same directory list in a different order.
+ process.env.PATH = next
return added
}
From 64acad300d7cb6caf6183d0d009f2423e1553ea0 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Wed, 10 Jun 2026 14:12:07 -0700
Subject: [PATCH 043/165] Add Floating Workspace contextual tour (#5062)
* Add floating workspace contextual tour
Co-authored-by: Orca
* Clarify floating workspace tour intro copy
Co-authored-by: Orca
* Differentiate floating workspace tour steps instead of repeating examples
Co-authored-by: Orca
* Lead floating workspace tour with the user benefit
Co-authored-by: Orca
* Pitch floating workspace tour around cross-repo agents
Co-authored-by: Orca
* Refine floating workspace tour step 1 copy
Co-authored-by: Orca
* Anchor floating workspace tour step 2 on the minimize control
Co-authored-by: Orca
* Restore floating workspace tour step 2
Co-authored-by: Orca
* Anchor floating workspace tour steps on New Terminal and New Markdown Note
Co-authored-by: Orca
* Retitle floating workspace tour step 2 as scratchpad
Co-authored-by: Orca
* Add why-comments for tour selector fallback and placement flipping
Co-authored-by: Orca
---------
Co-authored-by: Orca
---
.../feature-discovery-interaction-tracking.md | 3 +-
src/renderer/src/App.tsx | 11 +-
.../contextual-tour-gate.test.ts | 20 +++
.../contextual-tour-panel-position.test.ts | 39 ++++++
.../contextual-tour-panel-position.ts | 62 ++++++++-
.../use-contextual-tour.test.ts | 82 +++++++++++-
.../contextual-tours/use-contextual-tour.ts | 69 ++++++++--
.../FloatingTerminalPanel.test.tsx | 121 +++++++++++++++++-
.../FloatingTerminalPanel.tsx | 27 +++-
...orkspace-tour-interaction-snapshot.test.ts | 66 ++++++++++
...ing-workspace-tour-interaction-snapshot.ts | 31 +++++
src/shared/contextual-tours.test.ts | 25 ++++
src/shared/contextual-tours.ts | 23 ++++
.../feature-education-telemetry.test.ts | 3 +
src/shared/feature-education-telemetry.ts | 2 +
15 files changed, 563 insertions(+), 21 deletions(-)
create mode 100644 src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.test.ts
create mode 100644 src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.ts
diff --git a/docs/reference/feature-discovery-interaction-tracking.md b/docs/reference/feature-discovery-interaction-tracking.md
index e18aae4c2c7..a9e9eb1a46f 100644
--- a/docs/reference/feature-discovery-interaction-tracking.md
+++ b/docs/reference/feature-discovery-interaction-tracking.md
@@ -26,7 +26,7 @@ Do not upload this state as broad analytics. Product analytics should continue t
| Review notes to agent | `review-notes` | A diff or markdown review note is added, or review notes are marked sent to an agent. | Suppress or target a future review-notes tour/tip about adding line notes and sending focused feedback back to an agent. |
| AI commit generation | `ai-commit-generation` | AI commit-message generation is enabled or an AI commit message is generated. | Suppress future education about AI commit generation. No contextual tour is planned for this branch. |
| AI PR generation | `ai-pr-generation` | AI pull-request title/body/draft fields are generated. | Suppress future education about AI PR generation. No contextual tour is planned for this branch. |
-| Floating Workspace | `floating-workspace` | The floating workspace opens, is enabled, or is configured. | Suppress future tips about the global terminal/browser/markdown workspace. No contextual tour is planned for this branch. |
+| Floating Workspace | `floating-workspace` | The floating workspace opens, is enabled, or is configured. | Keep the existing Floating Workspace tour, and suppress future education about the global terminal/browser/markdown workspace. |
| Quick Commands | `quick-commands` | A terminal quick command is created or edited. | Suppress future tips about saved terminal commands. No contextual tour is planned for this branch. |
| Computer Use setup | `computer-use-setup` | Computer Use was selected in legacy onboarding, a permission setup is opened, or the skill setup terminal opens. | Suppress setup-focused tips once the user has started setup. |
| Computer Use | `computer-use` | A successful `computer.*` runtime method other than capability probing is handled. | Suppress future usage tips once an agent has actually invoked Computer Use. |
@@ -62,6 +62,7 @@ Orca also records surface-level interactions for feature areas where opening the
- `browser`: non-blank browser page viewed
- `tasks`: Tasks page opened
- `automations`: Automations page opened
+- `floating-workspace`: floating workspace opened
- `workspace-creation`: workspace creation flow opened
These remain intentionally separate from action-level IDs such as `workspace-board-actions`, `automation-created`, and `automation-run`. Surface-level IDs answer "has the user entered the feature area?" Action-level IDs answer "has the user performed the deeper workflow?"
diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx
index 6246d80c576..0c7b82ebb24 100644
--- a/src/renderer/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -55,6 +55,7 @@ import {
isFloatingWorkspaceTerminalInputTarget,
shouldMinimizeFloatingWorkspacePanelOnCloseShortcut
} from '@/lib/floating-workspace-terminal-actions'
+import { createFloatingWorkspaceTourInteractionSnapshot } from '@/lib/floating-workspace-tour-interaction-snapshot'
import { requestScrollToCurrentWorkspaceRevealAndRename } from '@/lib/scroll-to-current-workspace-status'
import { WorkspacePortScanner } from './components/ports/WorkspacePortScanner'
import { CrashReportDialog } from './components/crash-report/CrashReportDialog'
@@ -313,6 +314,11 @@ function App(): React.JSX.Element {
useRadixBodyPointerEventsRecovery()
useWebSessionTabsSync()
const [floatingTerminalOpen, setFloatingTerminalOpen] = useState(false)
+ const floatingWorkspaceTourInteractionSnapshotRef = useRef<{
+ wasPreviouslyInteracted?: boolean
+ persisted?: Promise
+ recordFeatureInteractionForTour: boolean
+ } | null>(null)
// Why: Zustand actions are referentially stable, but each individual
// useAppStore(s => s.someAction) still registers a subscription that React
@@ -477,7 +483,9 @@ function App(): React.JSX.Element {
// Why: recordFeatureInteraction updates Zustand subscribers; doing it
// inside React's state updater logs a render-phase update warning.
if (resolvedOpen && !floatingTerminalOpen) {
- useAppStore.getState().recordFeatureInteraction('floating-workspace')
+ const state = useAppStore.getState()
+ floatingWorkspaceTourInteractionSnapshotRef.current =
+ createFloatingWorkspaceTourInteractionSnapshot(state)
rememberFloatingTerminalReturnFocus()
} else if (!resolvedOpen && floatingTerminalOpen) {
restoreFloatingTerminalReturnFocus()
@@ -2017,6 +2025,7 @@ function App(): React.JSX.Element {
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-gate.test.ts b/src/renderer/src/components/contextual-tours/contextual-tour-gate.test.ts
index 5ba4deeaa70..f9f07a1817e 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-gate.test.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-gate.test.ts
@@ -40,6 +40,26 @@ describe('contextual tour gate', () => {
expect(decision).toEqual({ kind: 'blocked', reason: 'missing-start-target' })
})
+ it('can start the floating workspace tour from the non-empty surface fallback', () => {
+ const tour = getContextualTour('floating-workspace')
+ const fallbackSelector =
+ '[data-contextual-tour-target="floating-workspace-new-terminal"], [data-contextual-tour-target="floating-workspace-surface"]'
+ const decision = getContextualTourRequestDecision({
+ tour,
+ persistedUIReady: true,
+ autoEligible: true,
+ onboardingVisible: false,
+ seenIds: [],
+ sessionConsumed: false,
+ activeTourId: null,
+ activeModal: 'none',
+ blockingSurfaceVisible: false,
+ targetExists: (selector) => selector === fallbackSelector
+ })
+
+ expect(decision).toEqual({ kind: 'start', stepIndex: 0 })
+ })
+
it('returns null when selector lookup or measurement throws', () => {
expect(
getMeasurableContextualTourTarget('[', {
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts
index 6ad3fa36cc7..03c8aa098bb 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.test.ts
@@ -92,4 +92,43 @@ describe('contextual tour panel position', () => {
expect(position.top).toBe(465)
expect(position.left).toBe(560)
})
+
+ it('keeps the floating workspace surface fallback panel outside the taught surface', () => {
+ const targetRect = { left: 360, right: 1080, top: 96, bottom: 536, width: 720, height: 440 }
+ const position = clampContextualTourPanelPosition({
+ targetRect,
+ viewport: { width: 1280, height: 720 },
+ panel: { width: 320, height: 160 },
+ preferredPlacement: 'left'
+ })
+
+ expect(position.placement).toBe('left')
+ expect(position.left + 320).toBeLessThanOrEqual(targetRect.left - 12)
+ })
+
+ it('flips a preferred side placement instead of clamping over the target', () => {
+ const targetRect = { left: 12, right: 360, top: 96, bottom: 536, width: 348, height: 440 }
+ const position = clampContextualTourPanelPosition({
+ targetRect,
+ viewport: { width: 1280, height: 720 },
+ panel: { width: 320, height: 160 },
+ preferredPlacement: 'left'
+ })
+
+ expect(position.placement).toBe('right')
+ expect(position.left).toBeGreaterThanOrEqual(targetRect.right + 12)
+ })
+
+ it('uses side room when a preferred vertical placement cannot fit above or below', () => {
+ const targetRect = { left: 120, right: 220, top: 40, bottom: 680, width: 100, height: 640 }
+ const position = clampContextualTourPanelPosition({
+ targetRect,
+ viewport: { width: 1280, height: 720 },
+ panel: { width: 320, height: 160 },
+ preferredPlacement: 'bottom'
+ })
+
+ expect(position.placement).toBe('right')
+ expect(position.left).toBeGreaterThanOrEqual(targetRect.right + 12)
+ })
})
diff --git a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts
index 5b50e663078..07c53b61305 100644
--- a/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts
+++ b/src/renderer/src/components/contextual-tours/contextual-tour-panel-position.ts
@@ -41,7 +41,15 @@ export function clampContextualTourPanelPosition(args: {
let left: number
let top: number
if (args.preferredPlacement) {
- placement = args.preferredPlacement
+ placement = resolvePreferredPlacement({
+ preferredPlacement: args.preferredPlacement,
+ roomAbove,
+ roomBelow,
+ roomLeft,
+ roomRight,
+ panel,
+ gap
+ })
const preferredPosition = getUnclampedPanelPosition({
placement,
targetRect,
@@ -94,6 +102,58 @@ export function clampContextualTourPanelPosition(args: {
return { left: clampedLeft, top: clampedTop, placement, arrowOffset }
}
+// Why: flip to the opposite side when the preferred side lacks room, and fall
+// back to the horizontal axis when neither vertical side fits.
+function resolvePreferredPlacement(args: {
+ preferredPlacement: ContextualTourPanelPlacement
+ roomAbove: number
+ roomBelow: number
+ roomLeft: number
+ roomRight: number
+ panel: PanelSize
+ gap: number
+}): ContextualTourPanelPlacement {
+ const horizontalRoom = args.panel.width + args.gap
+ const verticalRoom = args.panel.height + args.gap
+ if (args.preferredPlacement === 'left') {
+ return args.roomLeft < horizontalRoom && args.roomRight >= horizontalRoom ? 'right' : 'left'
+ }
+ if (args.preferredPlacement === 'right') {
+ return args.roomRight < horizontalRoom && args.roomLeft >= horizontalRoom ? 'left' : 'right'
+ }
+ if (args.preferredPlacement === 'top') {
+ if (args.roomAbove >= verticalRoom) {
+ return 'top'
+ }
+ if (args.roomBelow >= verticalRoom) {
+ return 'bottom'
+ }
+ return getPreferredHorizontalPlacement(args)
+ }
+ if (args.roomBelow >= verticalRoom) {
+ return 'bottom'
+ }
+ if (args.roomAbove >= verticalRoom) {
+ return 'top'
+ }
+ return getPreferredHorizontalPlacement(args)
+}
+
+// Why: prefer right when it fits or has at least as much room as left,
+// matching the no-preference placement heuristic above.
+function getPreferredHorizontalPlacement(args: {
+ roomLeft: number
+ roomRight: number
+ panel: PanelSize
+ gap: number
+}): ContextualTourPanelPlacement {
+ const horizontalRoom = args.panel.width + args.gap
+ if (args.roomRight >= horizontalRoom || args.roomRight >= args.roomLeft) {
+ return 'right'
+ }
+ return 'left'
+}
+
/** Returns the raw (unclamped) top-left position for a panel at the given placement side. */
function getUnclampedPanelPosition(args: {
placement: ContextualTourPanelPlacement
diff --git a/src/renderer/src/components/contextual-tours/use-contextual-tour.test.ts b/src/renderer/src/components/contextual-tours/use-contextual-tour.test.ts
index d43cb0aaf4f..f6c7cffb929 100644
--- a/src/renderer/src/components/contextual-tours/use-contextual-tour.test.ts
+++ b/src/renderer/src/components/contextual-tours/use-contextual-tour.test.ts
@@ -1,5 +1,8 @@
-import { describe, expect, it } from 'vitest'
-import { shouldRequestContextualTourAfterInteraction } from './use-contextual-tour'
+import { describe, expect, it, vi } from 'vitest'
+import {
+ createContextualTourInteractionSnapshot,
+ shouldRequestContextualTourAfterInteraction
+} from './use-contextual-tour'
import type { ContextualTourId } from '../../../../shared/contextual-tours'
describe('shouldRequestContextualTourAfterInteraction', () => {
@@ -40,3 +43,78 @@ describe('shouldRequestContextualTourAfterInteraction', () => {
).resolves.toBe(true)
})
})
+
+describe('createContextualTourInteractionSnapshot', () => {
+ it('records regular contextual-tour feature interactions before requesting', async () => {
+ const persisted = Promise.resolve()
+ const recordFeatureInteraction = vi.fn(() => persisted)
+
+ const snapshot = createContextualTourInteractionSnapshot({
+ id: 'tasks',
+ featureInteractions: {},
+ recordFeatureInteraction,
+ recordFeatureInteractionForTour: true
+ })
+
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('tasks')
+ expect(snapshot.wasPreviouslyInteracted).toBe(false)
+ await expect(snapshot.persisted).resolves.toBeUndefined()
+ })
+
+ it('reuses the floating workspace pre-open snapshot without double-recording', async () => {
+ const persisted = Promise.resolve()
+ const recordFeatureInteraction = vi.fn(() => Promise.resolve())
+
+ const snapshot = createContextualTourInteractionSnapshot({
+ id: 'floating-workspace',
+ featureInteractions: {
+ 'floating-workspace': {
+ firstInteractedAt: 1,
+ interactionCount: 1
+ }
+ },
+ recordFeatureInteraction,
+ recordFeatureInteractionForTour: false,
+ featureInteractionPersisted: persisted,
+ wasFeaturePreviouslyInteracted: false
+ })
+
+ expect(recordFeatureInteraction).not.toHaveBeenCalled()
+ expect(snapshot.wasPreviouslyInteracted).toBe(false)
+ expect(snapshot.persisted).toBe(persisted)
+ })
+
+ it('marks existing floating workspace users from the explicit pre-open snapshot', () => {
+ const snapshot = createContextualTourInteractionSnapshot({
+ id: 'floating-workspace',
+ featureInteractions: {},
+ recordFeatureInteraction: vi.fn(() => Promise.resolve()),
+ recordFeatureInteractionForTour: false,
+ wasFeaturePreviouslyInteracted: true
+ })
+
+ expect(snapshot.wasPreviouslyInteracted).toBe(true)
+ })
+
+ it('can record after hydration while preserving an explicit pre-open snapshot', () => {
+ const persisted = Promise.resolve()
+ const recordFeatureInteraction = vi.fn(() => persisted)
+
+ const snapshot = createContextualTourInteractionSnapshot({
+ id: 'floating-workspace',
+ featureInteractions: {
+ 'floating-workspace': {
+ firstInteractedAt: 1,
+ interactionCount: 1
+ }
+ },
+ recordFeatureInteraction,
+ recordFeatureInteractionForTour: true,
+ wasFeaturePreviouslyInteracted: false
+ })
+
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('floating-workspace')
+ expect(snapshot.wasPreviouslyInteracted).toBe(false)
+ expect(snapshot.persisted).toBe(persisted)
+ })
+})
diff --git a/src/renderer/src/components/contextual-tours/use-contextual-tour.ts b/src/renderer/src/components/contextual-tours/use-contextual-tour.ts
index 3cac4dba65d..158e43865f8 100644
--- a/src/renderer/src/components/contextual-tours/use-contextual-tour.ts
+++ b/src/renderer/src/components/contextual-tours/use-contextual-tour.ts
@@ -1,6 +1,9 @@
import { useEffect, useRef } from 'react'
import type { ContextualTourId } from '../../../../shared/contextual-tours'
-import { hasFeatureInteraction } from '../../../../shared/feature-interactions'
+import {
+ hasFeatureInteraction,
+ type FeatureInteractionState
+} from '../../../../shared/feature-interactions'
import { useAppStore } from '@/store'
const TOUR_SOURCES = {
@@ -9,9 +12,34 @@ const TOUR_SOURCES = {
browser: 'browser_visible',
tasks: 'tasks_open',
automations: 'automations_open',
+ 'floating-workspace': 'floating_workspace_visible',
'workspace-creation': 'workspace_creation_visible'
} satisfies Record
+export type UseContextualTourOptions = {
+ recordFeatureInteraction?: boolean | undefined
+ featureInteractionPersisted?: Promise | undefined
+ wasFeaturePreviouslyInteracted?: boolean | undefined
+}
+
+export function createContextualTourInteractionSnapshot(args: {
+ id: ContextualTourId
+ featureInteractions: FeatureInteractionState
+ recordFeatureInteraction: (id: ContextualTourId) => Promise
+ recordFeatureInteractionForTour: boolean
+ featureInteractionPersisted?: Promise | undefined
+ wasFeaturePreviouslyInteracted?: boolean | undefined
+}): { persisted: Promise; wasPreviouslyInteracted: boolean } {
+ const wasPreviouslyInteracted =
+ args.wasFeaturePreviouslyInteracted ?? hasFeatureInteraction(args.featureInteractions, args.id)
+ return {
+ wasPreviouslyInteracted,
+ persisted: args.recordFeatureInteractionForTour
+ ? args.recordFeatureInteraction(args.id)
+ : (args.featureInteractionPersisted ?? Promise.resolve())
+ }
+}
+
export async function shouldRequestContextualTourAfterInteraction(args: {
id: ContextualTourId
persisted: Promise
@@ -25,8 +53,14 @@ export async function shouldRequestContextualTourAfterInteraction(args: {
export function useContextualTour(
id: ContextualTourId,
enabled: boolean,
- source: string = TOUR_SOURCES[id]
+ source: string = TOUR_SOURCES[id],
+ options: UseContextualTourOptions = {}
): void {
+ const {
+ recordFeatureInteraction: shouldRecordFeatureInteraction = true,
+ featureInteractionPersisted,
+ wasFeaturePreviouslyInteracted
+ } = options
const requestContextualTour = useAppStore((s) => s.requestContextualTour)
const suppressContextualTour = useAppStore((s) => s.suppressContextualTour)
const recordFeatureInteraction = useAppStore((s) => s.recordFeatureInteraction)
@@ -62,19 +96,32 @@ export function useContextualTour(
) {
return
}
- const wasPreviouslyInteracted = hasFeatureInteraction(
- useAppStore.getState().featureInteractions,
- id
- )
+ const snapshot = createContextualTourInteractionSnapshot({
+ id,
+ featureInteractions: useAppStore.getState().featureInteractions,
+ recordFeatureInteraction,
+ recordFeatureInteractionForTour: shouldRecordFeatureInteraction,
+ featureInteractionPersisted,
+ wasFeaturePreviouslyInteracted
+ })
enabledInteractionSnapshotRef.current = {
id,
source,
- // Why: recording writes featureInteractions; subscribing here would retrigger
- // this effect and repeatedly persist the same enabled source.
- wasPreviouslyInteracted,
- persisted: recordFeatureInteraction(id)
+ // Why: recording writes featureInteractions; subscribing here would
+ // retrigger this effect and repeatedly persist the same enabled source.
+ wasPreviouslyInteracted: snapshot.wasPreviouslyInteracted,
+ persisted: snapshot.persisted
}
- }, [enabled, id, persistedUIReady, recordFeatureInteraction, source])
+ }, [
+ enabled,
+ featureInteractionPersisted,
+ id,
+ persistedUIReady,
+ recordFeatureInteraction,
+ shouldRecordFeatureInteraction,
+ source,
+ wasFeaturePreviouslyInteracted
+ ])
useEffect(() => {
// Why: source disable should end through the overlay so a shown tour gets
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
index 1773a295335..978927350a9 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.test.tsx
@@ -100,7 +100,8 @@ const mocks = vi.hoisted(() => ({
setActiveTab: vi.fn(),
setTabColor: vi.fn(),
setTabCustomTitle: vi.fn(),
- setTabPaneExpanded: vi.fn()
+ setTabPaneExpanded: vi.fn(),
+ useContextualTour: vi.fn()
}))
const saveDialogBox = vi.hoisted(() => ({
@@ -186,6 +187,10 @@ vi.mock('@/components/ui/button', () => ({
}
}))
+vi.mock('@/components/contextual-tours/use-contextual-tour', () => ({
+ useContextualTour: mocks.useContextualTour
+}))
+
vi.mock('@/components/ui/dialog', () => ({
Dialog: function Dialog(props: { children?: unknown }) {
return props.children
@@ -478,6 +483,17 @@ function findByProp(node: unknown, propName: string): ReactElementLike {
return found
}
+function collectPropValues(node: unknown, propName: string): unknown[] {
+ const values: unknown[] = []
+ visit(node, (entry) => {
+ const value = entry.props[propName]
+ if (value !== undefined) {
+ values.push(value)
+ }
+ })
+ return values
+}
+
function runEffects(): void {
const layoutEffects = hookRuntime.layoutEffects.splice(0)
for (const effect of layoutEffects) {
@@ -502,10 +518,18 @@ async function flushAsyncWork(): Promise {
await Promise.resolve()
}
-async function renderPanel(open: boolean, onOpenChange = vi.fn()): Promise {
+async function renderPanel(
+ open: boolean,
+ onOpenChange = vi.fn(),
+ tourInteractionSnapshot?: {
+ wasPreviouslyInteracted: boolean
+ persisted?: Promise
+ recordFeatureInteractionForTour: boolean
+ } | null
+): Promise {
hookRuntime.index = 0
const { FloatingTerminalPanel } = await import('./FloatingTerminalPanel')
- return FloatingTerminalPanel({ open, onOpenChange })
+ return FloatingTerminalPanel({ open, onOpenChange, tourInteractionSnapshot })
}
function getPanelStyleBounds(element: unknown): FloatingTerminalPanelBounds {
@@ -897,6 +921,97 @@ describe('FloatingTerminalPanel close behavior', () => {
expect(mocks.createTab).not.toHaveBeenCalled()
})
+ it('requests the floating workspace tour only when the panel is open', async () => {
+ const persisted = Promise.resolve()
+
+ await renderPanel(false, vi.fn(), {
+ wasPreviouslyInteracted: false,
+ persisted,
+ recordFeatureInteractionForTour: false
+ })
+
+ expect(mocks.useContextualTour).toHaveBeenLastCalledWith(
+ 'floating-workspace',
+ false,
+ 'floating_workspace_visible',
+ {
+ recordFeatureInteraction: false,
+ featureInteractionPersisted: persisted,
+ wasFeaturePreviouslyInteracted: false
+ }
+ )
+
+ await renderPanel(true, vi.fn(), {
+ wasPreviouslyInteracted: true,
+ persisted,
+ recordFeatureInteractionForTour: false
+ })
+
+ expect(mocks.useContextualTour).toHaveBeenLastCalledWith(
+ 'floating-workspace',
+ true,
+ 'floating_workspace_visible',
+ {
+ recordFeatureInteraction: false,
+ featureInteractionPersisted: persisted,
+ wasFeaturePreviouslyInteracted: true
+ }
+ )
+ })
+
+ it('records the floating workspace tour interaction when the open snapshot deferred persistence', async () => {
+ await renderPanel(true, vi.fn(), {
+ wasPreviouslyInteracted: false,
+ recordFeatureInteractionForTour: true
+ })
+
+ expect(mocks.useContextualTour).toHaveBeenLastCalledWith(
+ 'floating-workspace',
+ true,
+ 'floating_workspace_visible',
+ {
+ recordFeatureInteraction: true,
+ featureInteractionPersisted: undefined,
+ wasFeaturePreviouslyInteracted: false
+ }
+ )
+ })
+
+ it('targets the empty-state actions without co-mounting the surface fallback', async () => {
+ const element = await renderPanel(true)
+ const emptyState = findByTypeName(element, 'FloatingTerminalEmptyState')
+ const renderedEmptyState = (
+ emptyState.type as (props: Record) => ReactElementLike
+ )(emptyState.props)
+
+ expect(collectPropValues(element, 'data-contextual-tour-target')).not.toContain(
+ 'floating-workspace-surface'
+ )
+ expect(collectPropValues(renderedEmptyState, 'data-contextual-tour-target')).toEqual([
+ 'floating-workspace-new-terminal',
+ 'floating-workspace-new-markdown'
+ ])
+ })
+
+ it('targets the non-empty panel surface when the empty-state actions are absent', async () => {
+ setFloatingTabs([makeTab({ id: 'tab-1' })])
+
+ const element = await renderPanel(true)
+
+ expect(() => findByTypeName(element, 'FloatingTerminalEmptyState')).toThrow(
+ 'FloatingTerminalEmptyState not found'
+ )
+ expect(collectPropValues(element, 'data-contextual-tour-target')).toContain(
+ 'floating-workspace-surface'
+ )
+ expect(collectPropValues(element, 'data-contextual-tour-target')).not.toContain(
+ 'floating-workspace-new-terminal'
+ )
+ expect(collectPropValues(element, 'data-contextual-tour-target')).not.toContain(
+ 'floating-workspace-new-markdown'
+ )
+ })
+
it('focuses the empty floating workspace when opened for immediate shortcuts', async () => {
const element = await renderPanel(true)
const panel = findByProp(element, 'data-floating-terminal-panel')
diff --git a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
index 151041ab648..fd2c02da4c7 100644
--- a/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
+++ b/src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx
@@ -16,6 +16,7 @@ import { FileText, Globe, Minus, TerminalSquare } from 'lucide-react'
import { toast } from 'sonner'
import BrowserPane from '@/components/browser-pane/BrowserPane'
import { ShortcutKeyCombo } from '@/components/ShortcutKeyCombo'
+import { useContextualTour } from '@/components/contextual-tours/use-contextual-tour'
import TabBar from '@/components/tab-bar/TabBar'
import { resolveGroupTabFromVisibleId } from '@/components/tab-group/tab-group-visible-id'
import TerminalPane from '@/components/terminal-pane/TerminalPane'
@@ -106,6 +107,13 @@ const EditorPanel = lazy(() => import('@/components/editor/EditorPanel'))
type FloatingTerminalPanelProps = {
open: boolean
onOpenChange: (open: boolean) => void
+ tourInteractionSnapshot?: FloatingWorkspaceTourInteractionSnapshot | null | undefined
+}
+
+type FloatingWorkspaceTourInteractionSnapshot = {
+ wasPreviouslyInteracted?: boolean
+ persisted?: Promise
+ recordFeatureInteractionForTour: boolean
}
const FLOATING_TERMINAL_NO_DRAG_SELECTOR =
@@ -150,7 +158,8 @@ function areFloatingTerminalPanelCommittedBoundsEqual(
export function FloatingTerminalPanel({
open,
- onOpenChange
+ onOpenChange,
+ tourInteractionSnapshot
}: FloatingTerminalPanelProps): React.JSX.Element | null {
const tabsByWorktree = useAppStore((s) => s.tabsByWorktree)
const browserTabsByWorktree = useAppStore((s) => s.browserTabsByWorktree)
@@ -342,6 +351,13 @@ export function FloatingTerminalPanel({
: activeTab?.contentType === 'terminal'
? 'terminal'
: 'editor'
+
+ useContextualTour('floating-workspace', open, 'floating_workspace_visible', {
+ recordFeatureInteraction: tourInteractionSnapshot?.recordFeatureInteractionForTour ?? false,
+ featureInteractionPersisted: tourInteractionSnapshot?.persisted,
+ wasFeaturePreviouslyInteracted: tourInteractionSnapshot?.wasPreviouslyInteracted
+ })
+
const {
saveDialogFileId,
saveDialogFile,
@@ -1349,7 +1365,12 @@ export function FloatingTerminalPanel({
/>
-
+
{cwd
? tabs.map((tab) => {
const isActive = tab.id === activeTerminalId
@@ -1592,6 +1613,7 @@ function FloatingTerminalEmptyState({
type="button"
variant="ghost"
className="grid h-8 w-full grid-cols-[1rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md px-3 py-0 text-sm font-normal text-foreground hover:bg-muted/40 hover:text-foreground"
+ data-contextual-tour-target="floating-workspace-new-terminal"
onClick={onNewTerminal}
>
@@ -1607,6 +1629,7 @@ function FloatingTerminalEmptyState({
type="button"
variant="ghost"
className="grid h-8 w-full grid-cols-[1rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md px-3 py-0 text-sm font-normal text-foreground hover:bg-muted/40 hover:text-foreground"
+ data-contextual-tour-target="floating-workspace-new-markdown"
onClick={onNewMarkdown}
>
diff --git a/src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.test.ts b/src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.test.ts
new file mode 100644
index 00000000000..5865056b861
--- /dev/null
+++ b/src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.test.ts
@@ -0,0 +1,66 @@
+import { describe, expect, it, vi } from 'vitest'
+import { createFloatingWorkspaceTourInteractionSnapshot } from './floating-workspace-tour-interaction-snapshot'
+import type { FeatureInteractionState } from '../../../shared/feature-interactions'
+
+describe('createFloatingWorkspaceTourInteractionSnapshot', () => {
+ it('captures first-open state before recording the floating workspace interaction', () => {
+ const featureInteractions: FeatureInteractionState = {}
+ const persisted = Promise.resolve()
+ const recordFeatureInteraction = vi.fn(() => {
+ featureInteractions['floating-workspace'] = {
+ firstInteractedAt: 100,
+ interactionCount: 1
+ }
+ return persisted
+ })
+
+ const snapshot = createFloatingWorkspaceTourInteractionSnapshot({
+ featureInteractions,
+ persistedUIReady: true,
+ recordFeatureInteraction
+ })
+
+ expect(recordFeatureInteraction).toHaveBeenCalledOnce()
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('floating-workspace')
+ expect(snapshot.wasPreviouslyInteracted).toBe(false)
+ expect(snapshot.persisted).toBe(persisted)
+ expect(snapshot.recordFeatureInteractionForTour).toBe(false)
+ })
+
+ it('defers recording to the tour hook when opened before persisted UI is ready', () => {
+ const featureInteractions: FeatureInteractionState = {}
+ const recordFeatureInteraction = vi.fn(() => Promise.resolve())
+
+ const snapshot = createFloatingWorkspaceTourInteractionSnapshot({
+ featureInteractions,
+ persistedUIReady: false,
+ recordFeatureInteraction
+ })
+
+ expect(recordFeatureInteraction).not.toHaveBeenCalled()
+ expect(snapshot.wasPreviouslyInteracted).toBeUndefined()
+ expect(snapshot.persisted).toBeUndefined()
+ expect(snapshot.recordFeatureInteractionForTour).toBe(true)
+ })
+
+ it('preserves returning-user state while recording the new open interaction', () => {
+ const persisted = Promise.resolve()
+ const recordFeatureInteraction = vi.fn(() => persisted)
+
+ const snapshot = createFloatingWorkspaceTourInteractionSnapshot({
+ featureInteractions: {
+ 'floating-workspace': {
+ firstInteractedAt: 100,
+ interactionCount: 1
+ }
+ },
+ persistedUIReady: true,
+ recordFeatureInteraction
+ })
+
+ expect(recordFeatureInteraction).toHaveBeenCalledWith('floating-workspace')
+ expect(snapshot.wasPreviouslyInteracted).toBe(true)
+ expect(snapshot.persisted).toBe(persisted)
+ expect(snapshot.recordFeatureInteractionForTour).toBe(false)
+ })
+})
diff --git a/src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.ts b/src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.ts
new file mode 100644
index 00000000000..d2b826b9aea
--- /dev/null
+++ b/src/renderer/src/lib/floating-workspace-tour-interaction-snapshot.ts
@@ -0,0 +1,31 @@
+import {
+ hasFeatureInteraction,
+ type FeatureInteractionState
+} from '../../../shared/feature-interactions'
+
+export type FloatingWorkspaceTourInteractionSnapshot = {
+ wasPreviouslyInteracted?: boolean
+ persisted?: Promise
+ recordFeatureInteractionForTour: boolean
+}
+
+export function createFloatingWorkspaceTourInteractionSnapshot(args: {
+ featureInteractions: FeatureInteractionState
+ persistedUIReady: boolean
+ recordFeatureInteraction: (id: 'floating-workspace') => Promise
+}): FloatingWorkspaceTourInteractionSnapshot {
+ const wasPreviouslyInteracted = hasFeatureInteraction(
+ args.featureInteractions,
+ 'floating-workspace'
+ )
+ if (!args.persistedUIReady) {
+ return {
+ recordFeatureInteractionForTour: true
+ }
+ }
+ return {
+ wasPreviouslyInteracted,
+ persisted: args.recordFeatureInteraction('floating-workspace'),
+ recordFeatureInteractionForTour: false
+ }
+}
diff --git a/src/shared/contextual-tours.test.ts b/src/shared/contextual-tours.test.ts
index 8159b4b5e2a..a73dcb6438b 100644
--- a/src/shared/contextual-tours.test.ts
+++ b/src/shared/contextual-tours.test.ts
@@ -14,6 +14,7 @@ describe('contextual tour definitions', () => {
'browser',
'tasks',
'automations',
+ 'floating-workspace',
'workspace-creation'
]
@@ -161,6 +162,30 @@ describe('contextual tour definitions', () => {
])
})
+ it('defines the floating workspace tour on the action list with a surface fallback', () => {
+ const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'floating-workspace') as
+ | ContextualTour
+ | undefined
+
+ expect(tour?.steps.map((step) => step.title)).toEqual([
+ 'Run an agent across every repo',
+ 'Or use it as a scratchpad'
+ ])
+ expect(tour?.steps.map((step) => step.body)).toEqual([
+ 'Agents here run in any folder you choose. Point one at the directory above your services to work across all your repos at once.',
+ 'Open agents, scratch terminals, notes, and browser tabs without cluttering the worktree you’re focused on.'
+ ])
+ expect(tour?.steps[0]).toMatchObject({
+ requiredForStart: true,
+ preferredPlacement: 'left'
+ })
+ expect(tour?.steps[1]?.preferredPlacement).toBe('left')
+ expect(tour?.steps.map((step) => step.targetSelector)).toEqual([
+ '[data-contextual-tour-target="floating-workspace-new-terminal"], [data-contextual-tour-target="floating-workspace-surface"]',
+ '[data-contextual-tour-target="floating-workspace-new-markdown"], [data-contextual-tour-target="floating-workspace-surface"]'
+ ])
+ })
+
it('allows only workspace creation over its workspace composer modal', () => {
const modalTours = (CONTEXTUAL_TOURS as readonly ContextualTour[]).filter(
(tour) => tour.allowedActiveModals?.length
diff --git a/src/shared/contextual-tours.ts b/src/shared/contextual-tours.ts
index e3bf241be3b..c3b3f67d506 100644
--- a/src/shared/contextual-tours.ts
+++ b/src/shared/contextual-tours.ts
@@ -6,6 +6,7 @@ export type ContextualTourId =
| 'browser'
| 'tasks'
| 'automations'
+ | 'floating-workspace'
| 'workspace-creation'
export type ContextualTourStepControl = {
@@ -163,6 +164,28 @@ export const CONTEXTUAL_TOURS = [
}
]
},
+ {
+ id: 'floating-workspace',
+ steps: [
+ {
+ title: 'Run an agent across every repo',
+ body: 'Agents here run in any folder you choose. Point one at the directory above your services to work across all your repos at once.',
+ // Why: the per-action anchors only render in the empty state; fall back
+ // to the panel surface when floating tabs already exist.
+ targetSelector:
+ '[data-contextual-tour-target="floating-workspace-new-terminal"], [data-contextual-tour-target="floating-workspace-surface"]',
+ requiredForStart: true,
+ preferredPlacement: 'left'
+ },
+ {
+ title: 'Or use it as a scratchpad',
+ body: 'Open agents, scratch terminals, notes, and browser tabs without cluttering the worktree you’re focused on.',
+ targetSelector:
+ '[data-contextual-tour-target="floating-workspace-new-markdown"], [data-contextual-tour-target="floating-workspace-surface"]',
+ preferredPlacement: 'left'
+ }
+ ]
+ },
{
id: 'workspace-creation',
allowedActiveModals: ['new-workspace-composer'],
diff --git a/src/shared/feature-education-telemetry.test.ts b/src/shared/feature-education-telemetry.test.ts
index 1be574155f9..7b1f8732e25 100644
--- a/src/shared/feature-education-telemetry.test.ts
+++ b/src/shared/feature-education-telemetry.test.ts
@@ -16,6 +16,9 @@ describe('feature education telemetry constants', () => {
expect(normalizeFeatureEducationSource('workspace_agent_sessions_visible')).toBe(
'workspace_agent_sessions_visible'
)
+ expect(normalizeFeatureEducationSource('floating_workspace_visible')).toBe(
+ 'floating_workspace_visible'
+ )
expect(normalizeFeatureEducationSource('setup_guide_parallel_work')).toBe(
'setup_guide_parallel_work'
)
diff --git a/src/shared/feature-education-telemetry.ts b/src/shared/feature-education-telemetry.ts
index ea0a32ee614..4e620a97ba8 100644
--- a/src/shared/feature-education-telemetry.ts
+++ b/src/shared/feature-education-telemetry.ts
@@ -6,6 +6,7 @@ export const FEATURE_EDUCATION_CONTEXTUAL_TOUR_IDS = [
'browser',
'tasks',
'automations',
+ 'floating-workspace',
'workspace-creation'
] as const satisfies readonly ContextualTourId[]
@@ -15,6 +16,7 @@ export const FEATURE_EDUCATION_SOURCES = [
'browser_visible',
'tasks_open',
'automations_open',
+ 'floating_workspace_visible',
'workspace_creation_visible',
'workspace_creation_modal',
'setup_guide_parallel_work',
From 24f8eaa55a8e217dce3de846a8a0e254601b12f4 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 14:12:12 -0700
Subject: [PATCH 044/165] Fix source control compare base ambiguity (#5127)
Co-authored-by: Orca
---
src/main/git/status.test.ts | 55 ++++++++++++++++++++++++++-
src/main/git/status.ts | 11 +++++-
src/main/ipc/worktree-remote.ts | 14 +++++--
src/main/ipc/worktrees.test.ts | 43 +++++++++++----------
src/main/runtime/orca-runtime.test.ts | 5 ++-
src/main/runtime/orca-runtime.ts | 7 +++-
6 files changed, 104 insertions(+), 31 deletions(-)
diff --git a/src/main/git/status.test.ts b/src/main/git/status.test.ts
index 5dbf9aa5ec4..c1fd590775d 100644
--- a/src/main/git/status.test.ts
+++ b/src/main/git/status.test.ts
@@ -905,6 +905,7 @@ describe('getBranchCompare', () => {
it('returns a pinned branch compare snapshot and parsed branch entries', async () => {
gitExecFileAsyncMock
.mockResolvedValueOnce({ stdout: 'main\n' })
+ .mockResolvedValueOnce({ stdout: 'remote-base-oid\n' })
.mockResolvedValueOnce({ stdout: 'head-oid\n' })
.mockResolvedValueOnce({ stdout: 'base-oid\n' })
.mockResolvedValueOnce({ stdout: 'merge-base-oid\n' })
@@ -939,6 +940,8 @@ describe('getBranchCompare', () => {
it('returns invalid-base when the compare ref does not resolve', async () => {
gitExecFileAsyncMock
.mockResolvedValueOnce({ stdout: 'main\n' })
+ .mockRejectedValueOnce(new Error('missing remote base'))
+ .mockRejectedValueOnce(new Error('missing local base'))
.mockResolvedValueOnce({ stdout: 'head-oid\n' })
.mockRejectedValueOnce(new Error('missing base'))
@@ -952,6 +955,7 @@ describe('getBranchCompare', () => {
it('returns unborn-head when HEAD cannot be resolved', async () => {
gitExecFileAsyncMock
.mockResolvedValueOnce({ stdout: 'main\n' })
+ .mockResolvedValueOnce({ stdout: 'remote-base-oid\n' })
.mockRejectedValueOnce(new Error('unborn'))
.mockRejectedValueOnce(new Error('missing base'))
@@ -965,6 +969,7 @@ describe('getBranchCompare', () => {
it('treats an unborn branch with a resolvable base as having no committed branch changes', async () => {
gitExecFileAsyncMock
.mockResolvedValueOnce({ stdout: 'feature\n' })
+ .mockResolvedValueOnce({ stdout: 'remote-base-oid\n' })
.mockRejectedValueOnce(new Error('unborn'))
.mockResolvedValueOnce({ stdout: 'base-oid\n' })
@@ -986,6 +991,7 @@ describe('getBranchCompare', () => {
it('returns no-merge-base when histories do not intersect', async () => {
gitExecFileAsyncMock
.mockResolvedValueOnce({ stdout: 'main\n' })
+ .mockResolvedValueOnce({ stdout: 'remote-base-oid\n' })
.mockResolvedValueOnce({ stdout: 'head-oid\n' })
.mockResolvedValueOnce({ stdout: 'base-oid\n' })
.mockRejectedValueOnce(new Error('no merge base'))
@@ -1000,6 +1006,7 @@ describe('getBranchCompare', () => {
it('passes core.quotePath=false to diff --name-status and parses UTF-8 paths', async () => {
gitExecFileAsyncMock
.mockResolvedValueOnce({ stdout: 'main\n' })
+ .mockResolvedValueOnce({ stdout: 'remote-base-oid\n' })
.mockResolvedValueOnce({ stdout: 'head-oid\n' })
.mockResolvedValueOnce({ stdout: 'base-oid\n' })
.mockResolvedValueOnce({ stdout: 'merge-base-oid\n' })
@@ -1010,7 +1017,7 @@ describe('getBranchCompare', () => {
const result = await getBranchCompare('/repo', 'origin/main')
expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(
- 5,
+ 6,
[
'-c',
'core.quotePath=false',
@@ -1028,6 +1035,52 @@ describe('getBranchCompare', () => {
])
})
+ it('compares short remote labels through fully qualified remote-tracking refs', async () => {
+ gitExecFileAsyncMock.mockImplementation((args: string[]) => {
+ if (args[0] === 'branch') {
+ return Promise.resolve({ stdout: 'feature\n' })
+ }
+ if (
+ args[0] === 'rev-parse' &&
+ args.includes('--quiet') &&
+ args.includes('refs/remotes/origin/main^{commit}')
+ ) {
+ return Promise.resolve({ stdout: 'remote-base-oid\n' })
+ }
+ if (args[0] === 'rev-parse' && args.includes('HEAD')) {
+ return Promise.resolve({ stdout: 'head-oid\n' })
+ }
+ if (args[0] === 'rev-parse' && args.includes('refs/remotes/origin/main')) {
+ return Promise.resolve({ stdout: 'base-oid\n' })
+ }
+ if (args[0] === 'merge-base') {
+ return Promise.resolve({ stdout: 'merge-base-oid\n' })
+ }
+ if (args.includes('--name-status')) {
+ return Promise.resolve({ stdout: '' })
+ }
+ if (args.includes('--numstat')) {
+ return Promise.resolve({ stdout: '' })
+ }
+ if (args[0] === 'rev-list') {
+ return Promise.resolve({ stdout: '0\n' })
+ }
+ throw new Error(`unexpected git args: ${args.join(' ')}`)
+ })
+
+ const result = await getBranchCompare('/repo', 'origin/main')
+
+ expect(result.summary).toMatchObject({
+ baseRef: 'origin/main',
+ baseOid: 'base-oid',
+ status: 'ready'
+ })
+ expect(gitExecFileAsyncMock).toHaveBeenCalledWith(
+ ['rev-parse', '--verify', '--end-of-options', 'refs/remotes/origin/main'],
+ { cwd: '/repo' }
+ )
+ })
+
it('attaches counts for branch compare paths containing rename markers', async () => {
gitExecFileAsyncMock.mockImplementation((args: string[]) => {
if (args[0] === 'branch') {
diff --git a/src/main/git/status.ts b/src/main/git/status.ts
index 6ffc44b9cd5..8af5a4aaac6 100644
--- a/src/main/git/status.ts
+++ b/src/main/git/status.ts
@@ -35,6 +35,8 @@ import {
removeSafeUntrackedDiscardTarget,
removeSafeUntrackedDiscardTargets
} from '../../shared/git-discard-path-safety'
+import { resolveWorktreeAddBaseRef } from '../../shared/worktree-base-ref'
+import { hasWorktreeBaseCommitRef } from './worktree-base-ref-probe'
const MAX_GIT_SHOW_BYTES = 10 * 1024 * 1024
const MAX_STAGED_COMMIT_CONTEXT_BYTES = MAX_GIT_SHOW_BYTES
@@ -702,6 +704,11 @@ export async function getBranchCompare(
const compareRef = await resolveCompareRef(worktreePath)
summary.compareRef = compareRef
+ // Why: short remote display refs like "origin/main" can collide with a local
+ // branch of the same name. Compare against the proven remote-tracking ref.
+ const resolvedBaseRef = await resolveWorktreeAddBaseRef(baseRef, (qualifiedRef) =>
+ hasWorktreeBaseCommitRef(worktreePath, qualifiedRef)
+ )
let headOid = ''
let baseOid = ''
@@ -710,7 +717,7 @@ export async function getBranchCompare(
summary.headOid = headOid
} catch {
try {
- baseOid = await resolveRefOid(worktreePath, baseRef)
+ baseOid = await resolveRefOid(worktreePath, resolvedBaseRef)
summary.baseOid = baseOid
// Why: new remote worktrees can be on an unborn branch until the first
// commit. There are no committed branch changes yet; surfacing this as a
@@ -730,7 +737,7 @@ export async function getBranchCompare(
}
try {
- baseOid = await resolveRefOid(worktreePath, baseRef)
+ baseOid = await resolveRefOid(worktreePath, resolvedBaseRef)
summary.baseOid = baseOid
} catch {
summary.status = 'invalid-base'
diff --git a/src/main/ipc/worktree-remote.ts b/src/main/ipc/worktree-remote.ts
index e876168fc6f..92e4db55102 100644
--- a/src/main/ipc/worktree-remote.ts
+++ b/src/main/ipc/worktree-remote.ts
@@ -1402,6 +1402,9 @@ export async function createRemoteWorktree(
const worktreeId = `${repo.id}::${created.path}`
const now = Date.now()
+ // Why: persisted compare refs must survive local branches whose names look
+ // like remote labels, e.g. a local branch literally named "origin/main".
+ const metadataBaseRef = remoteTrackingBase?.ref ?? baseBranch
let configuredPushTarget: GitPushTarget | undefined
if (preparedPushTarget) {
configuredPushTarget = await configureCreatedWorktreePushTargetSsh(
@@ -1427,7 +1430,7 @@ export async function createRemoteWorktree(
orcaCreatedAt: now,
orcaCreationSource: 'ssh',
orcaCreationWorkspaceLayout: getWorktreeCreationLayout(repo, settings),
- baseRef: baseBranch,
+ baseRef: metadataBaseRef,
...(checkoutExistingBranch ? { preserveBranchOnDelete: true } : {}),
...(configuredPushTarget ? { pushTarget: configuredPushTarget } : {}),
...(requestedDisplayName
@@ -1442,7 +1445,7 @@ export async function createRemoteWorktree(
...(sparseDirectories.length > 0
? {
sparseDirectories,
- sparseBaseRef: baseBranch,
+ sparseBaseRef: metadataBaseRef,
sparsePresetId
}
: {}),
@@ -1905,6 +1908,9 @@ export async function createLocalWorktree(
const worktreeId = `${repo.id}::${created.path}`
const now = Date.now()
+ // Why: persisted compare refs must survive local branches whose names look
+ // like remote labels, e.g. a local branch literally named "origin/main".
+ const metadataBaseRef = remoteTrackingBase?.ref ?? baseBranch
const metaUpdates: Partial = {
// Why: path-derived worktree IDs can be reused after external deletion.
// Fresh creations must rotate instance identity so stale lineage cannot
@@ -1920,7 +1926,7 @@ export async function createLocalWorktree(
orcaCreatedAt: now,
orcaCreationSource: 'desktop',
orcaCreationWorkspaceLayout: getWorktreeCreationLayout(repo, settings),
- baseRef: baseBranch,
+ baseRef: metadataBaseRef,
...(checkoutExistingBranch ? { preserveBranchOnDelete: true } : {}),
...(configuredPushTarget ? { pushTarget: configuredPushTarget } : {}),
...(requestedDisplayName
@@ -1931,7 +1937,7 @@ export async function createLocalWorktree(
...(sparseDirectories.length > 0
? {
sparseDirectories,
- sparseBaseRef: baseBranch,
+ sparseBaseRef: metadataBaseRef,
sparsePresetId
}
: {}),
diff --git a/src/main/ipc/worktrees.test.ts b/src/main/ipc/worktrees.test.ts
index f58b343a3b4..6d222d3d5df 100644
--- a/src/main/ipc/worktrees.test.ts
+++ b/src/main/ipc/worktrees.test.ts
@@ -547,10 +547,10 @@ describe('registerWorktreeHandlers', () => {
}
])
- const result = await handlers['worktrees:create'](null, {
+ const result = (await handlers['worktrees:create'](null, {
repoId: 'repo-1',
name: 'improve-dashboard'
- })
+ })) as CreateWorktreeResult
expect(addWorktreeMock).toHaveBeenCalledWith(
'/workspace/repo',
@@ -2155,7 +2155,8 @@ describe('registerWorktreeHandlers', () => {
'repo-ssh::/remote/sparse-dashboard',
expect.objectContaining({
sparseDirectories: ['apps/mobile', 'packages/shared'],
- sparseBaseRef: 'origin/main',
+ baseRef: 'refs/remotes/origin/main',
+ sparseBaseRef: 'refs/remotes/origin/main',
sparsePresetId: 'preset-1'
})
)
@@ -2163,7 +2164,7 @@ describe('registerWorktreeHandlers', () => {
worktree: expect.objectContaining({
isSparse: true,
sparseDirectories: ['apps/mobile', 'packages/shared'],
- sparseBaseRef: 'origin/main',
+ sparseBaseRef: 'refs/remotes/origin/main',
sparsePresetId: 'preset-1'
})
})
@@ -2880,12 +2881,12 @@ describe('registerWorktreeHandlers', () => {
)
expect(runtimeStub.fetchRemoteWithCache).not.toHaveBeenCalled()
resolveFetch()
- const result = await createPromise
+ const result = (await createPromise) as CreateWorktreeResult
expect(addWorktreeMock).toHaveBeenCalled()
- expect(result).toEqual(
- expect.objectContaining({
- worktree: expect.objectContaining({ id: 'repo-1::/workspace/improve-dashboard' })
- })
+ expect(result.worktree.id).toBe('repo-1::/workspace/improve-dashboard')
+ expect(store.setWorktreeMeta).toHaveBeenCalledWith(
+ 'repo-1::/workspace/improve-dashboard',
+ expect.objectContaining({ baseRef: 'refs/remotes/origin/main' })
)
})
@@ -2935,10 +2936,10 @@ describe('registerWorktreeHandlers', () => {
])
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'created-sha\n', stderr: '' })
- const result = await handlers['worktrees:create'](null, {
+ const result = (await handlers['worktrees:create'](null, {
repoId: 'repo-1',
name: 'improve-dashboard'
- })
+ })) as CreateWorktreeResult
expect(runtimeStub.getOrStartRemoteTrackingBaseRefresh).toHaveBeenCalledWith(
'/workspace/repo',
@@ -2978,10 +2979,10 @@ describe('registerWorktreeHandlers', () => {
])
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'created-sha\n', stderr: '' })
- const result = await handlers['worktrees:create'](null, {
+ const result = (await handlers['worktrees:create'](null, {
repoId: 'repo-1',
name: 'improve-dashboard'
- })
+ })) as CreateWorktreeResult
expect(addWorktreeMock).toHaveBeenCalledWith(
'/workspace/repo',
@@ -3000,15 +3001,15 @@ describe('registerWorktreeHandlers', () => {
}
}
)
- expect(result).toEqual(
- expect.objectContaining({
- localBaseRefUpdateSuggestion: {
- baseRef: 'origin/main',
- localBranch: 'main',
- behind: 2
- }
- })
+ expect(store.setWorktreeMeta).toHaveBeenCalledWith(
+ 'repo-1::/workspace/improve-dashboard',
+ expect.objectContaining({ baseRef: 'refs/remotes/origin/main' })
)
+ expect(result.localBaseRefUpdateSuggestion).toEqual({
+ baseRef: 'origin/main',
+ localBranch: 'main',
+ behind: 2
+ })
})
it('throws a clear error when no default base ref can be resolved', async () => {
diff --git a/src/main/runtime/orca-runtime.test.ts b/src/main/runtime/orca-runtime.test.ts
index 6a08ce06039..e251bd666f6 100644
--- a/src/main/runtime/orca-runtime.test.ts
+++ b/src/main/runtime/orca-runtime.test.ts
@@ -1397,7 +1397,10 @@ describe('OrcaRuntimeService', () => {
}
}
)
- expect(result.worktree).toMatchObject({ path: createdWorktree.path })
+ expect(result.worktree).toMatchObject({
+ path: createdWorktree.path,
+ baseRef: 'refs/remotes/origin/main'
+ })
} finally {
gitSpy.mockRestore()
}
diff --git a/src/main/runtime/orca-runtime.ts b/src/main/runtime/orca-runtime.ts
index fce1fdb2720..afc5038d126 100644
--- a/src/main/runtime/orca-runtime.ts
+++ b/src/main/runtime/orca-runtime.ts
@@ -9335,6 +9335,9 @@ export class OrcaRuntimeService {
const worktreeId = `${repo.id}::${created.path}`
const now = Date.now()
+ // Why: persisted compare refs must survive local branches whose names look
+ // like remote labels, e.g. a local branch literally named "origin/main".
+ const metadataBaseRef = remoteTrackingBase?.ref ?? baseBranch
const displayNameMeta = requestedDisplayName
? { displayName: requestedDisplayName }
: shouldSetDisplayName(effectiveRequestedName, branchName, effectiveSanitizedName)
@@ -9355,13 +9358,13 @@ export class OrcaRuntimeService {
orcaCreationSource: 'runtime',
orcaCreationWorkspaceLayout: getWorktreeCreationLayout(repo, settings),
...displayNameMeta,
- baseRef: baseBranch,
+ baseRef: metadataBaseRef,
...(checkoutExistingBranch ? { preserveBranchOnDelete: true } : {}),
...(configuredPushTarget ? { pushTarget: configuredPushTarget } : {}),
...(sparseDirectories.length > 0
? {
sparseDirectories,
- sparseBaseRef: baseBranch,
+ sparseBaseRef: metadataBaseRef,
sparsePresetId: args.sparseCheckout?.presetId
}
: {}),
From eadd8d2e427600f5bc036c0422d8f31558b4e56e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 10 Jun 2026 22:40:41 +0000
Subject: [PATCH 045/165] release: v1.4.59-rc.1 [rc-slot:2026-06-10-15]
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 6340418dbad..55c79110415 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca",
- "version": "1.4.59-rc.0",
+ "version": "1.4.59-rc.1",
"description": "Next-gen IDE for parallel agentic development",
"homepage": "https://github.com/stablyai/orca",
"author": "stablyai",
From 96b8fe7e92c067b2a51c97119a2648c530ee7e43 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 10 Jun 2026 23:05:21 +0000
Subject: [PATCH 046/165] release: v1.4.59
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 55c79110415..7dd881a1210 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca",
- "version": "1.4.59-rc.1",
+ "version": "1.4.59",
"description": "Next-gen IDE for parallel agentic development",
"homepage": "https://github.com/stablyai/orca",
"author": "stablyai",
From 6d6ad8b3ec7b3054a94b657cb3622ce120ed4c6e Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Wed, 10 Jun 2026 16:18:52 -0700
Subject: [PATCH 047/165] Default-driven create-project flow: name-first form
with sensible defaults (#5115)
Co-authored-by: Orca
---
src/main/ipc/repos-create.test.ts | 56 +-
src/main/ipc/repos.ts | 26 +
src/main/runtime/orca-runtime.test.ts | 27 +
src/main/runtime/orca-runtime.ts | 12 +
src/main/runtime/rpc/methods/repo.test.ts | 16 +
src/main/runtime/rpc/methods/repo.ts | 5 +
src/main/runtime/runtime-rpc.ts | 1 +
src/preload/api-types.ts | 2 +
src/preload/index.ts | 5 +
.../sidebar/AddRepoCreateStep.test.tsx | 74 +++
.../components/sidebar/AddRepoCreateStep.tsx | 543 ++++++++----------
.../src/components/sidebar/AddRepoDialog.tsx | 56 +-
.../sidebar/AddRepoDialogStepContent.test.tsx | 8 +-
.../sidebar/AddRepoDialogStepContent.tsx | 13 +
.../sidebar/CreateProjectLocationField.tsx | 5 +-
.../add-repo-existing-workspaces-telemetry.ts | 14 +
.../sidebar/create-project-defaults.test.ts | 90 +++
.../sidebar/create-project-defaults.ts | 88 +++
.../sidebar/useCreateProjectDefaults.test.ts | 260 +++++++++
.../sidebar/useCreateProjectDefaults.ts | 307 ++++++++++
...=> useCreateRepo.default-checkout.test.ts} | 29 +-
.../src/components/sidebar/useCreateRepo.ts | 189 ++++++
src/renderer/src/i18n/locales/en.json | 10 +-
src/renderer/src/i18n/locales/es.json | 14 +-
src/renderer/src/i18n/locales/ja.json | 12 +-
src/renderer/src/i18n/locales/ko.json | 16 +-
src/renderer/src/i18n/locales/zh.json | 16 +-
src/renderer/src/web/web-preload-api.test.ts | 47 ++
src/renderer/src/web/web-preload-api.ts | 9 +
29 files changed, 1589 insertions(+), 361 deletions(-)
create mode 100644 src/renderer/src/components/sidebar/AddRepoCreateStep.test.tsx
create mode 100644 src/renderer/src/components/sidebar/create-project-defaults.test.ts
create mode 100644 src/renderer/src/components/sidebar/create-project-defaults.ts
create mode 100644 src/renderer/src/components/sidebar/useCreateProjectDefaults.test.ts
create mode 100644 src/renderer/src/components/sidebar/useCreateProjectDefaults.ts
rename src/renderer/src/components/sidebar/{AddRepoCreateStep.default-checkout.test.ts => useCreateRepo.default-checkout.test.ts} (80%)
create mode 100644 src/renderer/src/components/sidebar/useCreateRepo.ts
diff --git a/src/main/ipc/repos-create.test.ts b/src/main/ipc/repos-create.test.ts
index c5a330461d2..e0d716a15c6 100644
--- a/src/main/ipc/repos-create.test.ts
+++ b/src/main/ipc/repos-create.test.ts
@@ -21,6 +21,7 @@ const {
readdirMock,
rmMock,
gitExecFileAsyncMock,
+ homedirMock,
invalidateAuthorizedRootsCacheMock
} = vi.hoisted(() => ({
handleMock: vi.fn(),
@@ -37,6 +38,7 @@ const {
readdirMock: vi.fn(),
rmMock: vi.fn(),
gitExecFileAsyncMock: vi.fn(),
+ homedirMock: vi.fn(),
invalidateAuthorizedRootsCacheMock: vi.fn()
}))
@@ -55,6 +57,10 @@ vi.mock('fs/promises', () => ({
rm: rmMock
}))
+vi.mock('os', () => ({
+ homedir: homedirMock
+}))
+
vi.mock('../git/runner', () => ({
gitExecFileAsync: gitExecFileAsyncMock,
gitSpawn: vi.fn()
@@ -88,7 +94,7 @@ type CreateResult =
| { error: string }
describe('repos:create', () => {
- const handlers = new Map Promise>()
+ const handlers = new Map unknown>()
const mockWindow = {
isDestroyed: () => false,
webContents: { send: vi.fn() }
@@ -101,12 +107,19 @@ describe('repos:create', () => {
}
return handler(null, args) as Promise
}
+ const callDefaultCreateProjectParent = (): Promise => {
+ const handler = handlers.get('repos:getDefaultCreateProjectParent')
+ if (!handler) {
+ throw new Error('repos:getDefaultCreateProjectParent handler was never registered')
+ }
+ return Promise.resolve(handler(null, undefined)).then((value) => value as string)
+ }
beforeEach(() => {
handlers.clear()
handleMock.mockReset()
handleMock.mockImplementation((channel: string, handler: (...a: unknown[]) => unknown) => {
- handlers.set(channel, handler as (event: unknown, args: unknown) => Promise)
+ handlers.set(channel, handler as (event: unknown, args: unknown) => unknown)
})
removeHandlerMock.mockReset()
mockStore.getRepos.mockReset().mockReturnValue([])
@@ -120,6 +133,7 @@ describe('repos:create', () => {
mkdirMock.mockReset().mockResolvedValue(undefined)
rmMock.mockReset().mockResolvedValue(undefined)
gitExecFileAsyncMock.mockReset().mockResolvedValue({ stdout: '', stderr: '' })
+ homedirMock.mockReset().mockReturnValue('/Users/alice')
registerRepoHandlers(mockWindow as never, mockStore as never)
})
@@ -128,11 +142,17 @@ describe('repos:create', () => {
expect(handlers.has('repos:create')).toBe(true)
})
+ it('registers the home-backed create-project default handler', async () => {
+ expect(handlers.has('repos:getDefaultCreateProjectParent')).toBe(true)
+ await expect(callDefaultCreateProjectParent()).resolves.toBe('/Users/alice/orca/projects')
+ })
+
it('unregisters any previously-registered repos:create handler', () => {
// registerRepoHandlers must call removeHandler('repos:create') before
// ipcMain.handle to avoid the "second handler for same channel" throw
// when this module is re-registered (e.g., after a reload).
expect(removeHandlerMock).toHaveBeenCalledWith('repos:create')
+ expect(removeHandlerMock).toHaveBeenCalledWith('repos:getDefaultCreateProjectParent')
})
// ── input validation ──────────────────────────────────────────────
@@ -172,24 +192,26 @@ describe('repos:create', () => {
// ── existing-directory handling ───────────────────────────────────
- it('rejects a non-empty existing directory without calling mkdir', async () => {
+ it('rejects a non-empty existing directory without creating the target', async () => {
accessMock.mockResolvedValueOnce(undefined) // exists
readdirMock.mockResolvedValueOnce(['README.md', '.DS_Store'])
const result = await callCreate({ parentPath: '/tmp', name: 'busy', kind: 'git' })
expect(result).toMatchObject({ error: expect.stringContaining('not empty') })
- expect(mkdirMock).not.toHaveBeenCalled()
+ expect(mkdirMock).toHaveBeenCalledWith('/tmp', { recursive: true })
+ expect(mkdirMock).not.toHaveBeenCalledWith('/tmp/busy', expect.anything())
expect(mockStore.addRepo).not.toHaveBeenCalled()
})
- it('accepts an empty existing directory and does not call mkdir', async () => {
+ it('accepts an empty existing directory and does not create the target', async () => {
accessMock.mockResolvedValueOnce(undefined) // exists
readdirMock.mockResolvedValueOnce([])
const result = await callCreate({ parentPath: '/tmp', name: 'empty', kind: 'folder' })
- expect(mkdirMock).not.toHaveBeenCalled()
+ expect(mkdirMock).toHaveBeenCalledWith('/tmp', { recursive: true })
+ expect(mkdirMock).not.toHaveBeenCalledWith('/tmp/empty', expect.anything())
expect(mockStore.addRepo).toHaveBeenCalledWith(
expect.objectContaining({ path: '/tmp/empty', kind: 'folder' })
)
@@ -200,7 +222,24 @@ describe('repos:create', () => {
// accessMock rejects by default → path does not exist
await callCreate({ parentPath: '/tmp', name: 'brand-new', kind: 'folder' })
- expect(mkdirMock).toHaveBeenCalledWith('/tmp/brand-new', { recursive: false })
+ expect(mkdirMock).toHaveBeenNthCalledWith(1, '/tmp', { recursive: true })
+ expect(mkdirMock).toHaveBeenNthCalledWith(2, '/tmp/brand-new', { recursive: false })
+ })
+
+ it('creates a missing default parent before creating the project directory', async () => {
+ const result = await callCreate({
+ parentPath: '/Users/alice/orca/projects',
+ name: 'first-project',
+ kind: 'folder'
+ })
+
+ expect(mkdirMock).toHaveBeenNthCalledWith(1, '/Users/alice/orca/projects', {
+ recursive: true
+ })
+ expect(mkdirMock).toHaveBeenNthCalledWith(2, '/Users/alice/orca/projects/first-project', {
+ recursive: false
+ })
+ expect(result).toHaveProperty('repo.path', '/Users/alice/orca/projects/first-project')
})
// ── plain folder happy path ───────────────────────────────────────
@@ -233,7 +272,8 @@ describe('repos:create', () => {
it('creates a git repo with an empty initial commit (in order)', async () => {
const result = await callCreate({ parentPath: '/tmp', name: 'gitproj', kind: 'git' })
- expect(mkdirMock).toHaveBeenCalledWith('/tmp/gitproj', { recursive: false })
+ expect(mkdirMock).toHaveBeenNthCalledWith(1, '/tmp', { recursive: true })
+ expect(mkdirMock).toHaveBeenNthCalledWith(2, '/tmp/gitproj', { recursive: false })
expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(1, ['init'], { cwd: '/tmp/gitproj' })
expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(
2,
diff --git a/src/main/ipc/repos.ts b/src/main/ipc/repos.ts
index 7adcb8c0659..ac1927617ef 100644
--- a/src/main/ipc/repos.ts
+++ b/src/main/ipc/repos.ts
@@ -4,6 +4,7 @@ boundary. Splitting by line count would scatter tightly coupled repo behavior. *
import type { BrowserWindow, IpcMainInvokeEvent } from 'electron'
import { dialog, ipcMain } from 'electron'
import { randomUUID } from 'crypto'
+import { homedir } from 'os'
import { z } from 'zod'
import type { Store } from '../persistence'
import type {
@@ -130,6 +131,7 @@ type CompletedNestedRepoScan = {
}
const completedNestedRepoScans = new Map()
const MAX_COMPLETED_NESTED_SCAN_RESULTS = 50
+const GIT_AVAILABILITY_TIMEOUT_MS = 1500
const ProjectGroupCreateArgs = z.object({
name: z.string().min(1),
@@ -272,6 +274,22 @@ async function cleanupOwnedCloneTarget(metadata: ActiveCloneMetadata): Promise {
+ try {
+ await gitExecFileAsync(['--version'], {
+ cwd: process.cwd(),
+ timeout: GIT_AVAILABILITY_TIMEOUT_MS
+ })
+ return true
+ } catch {
+ return false
+ }
+}
+
+function getDefaultCreateProjectParent(): string {
+ return join(homedir(), 'orca', 'projects')
+}
+
function markCloneAbortCleanupPending(metadata: ActiveCloneMetadata): void {
if (metadata.resolvePendingAbortCleanup) {
return
@@ -456,6 +474,8 @@ export function registerRepoHandlers(mainWindow: BrowserWindow, store: Store): v
ipcMain.removeHandler('repos:pickDirectory')
ipcMain.removeHandler('repos:clone')
ipcMain.removeHandler('repos:cloneAbort')
+ ipcMain.removeHandler('repos:isGitAvailable')
+ ipcMain.removeHandler('repos:getDefaultCreateProjectParent')
ipcMain.removeHandler('repos:getGitUsername')
ipcMain.removeHandler('repos:getBaseRefDefault')
ipcMain.removeHandler('repos:searchBaseRefs')
@@ -470,6 +490,9 @@ export function registerRepoHandlers(mainWindow: BrowserWindow, store: Store): v
return store.getRepos()
})
+ ipcMain.handle('repos:isGitAvailable', () => isGitAvailable())
+ ipcMain.handle('repos:getDefaultCreateProjectParent', () => getDefaultCreateProjectParent())
+
ipcMain.handle('projectGroups:list', () => store.getProjectGroups())
ipcMain.handle('projectGroups:create', (_event, rawArgs: unknown): ProjectGroup => {
@@ -901,6 +924,9 @@ export function registerRepoHandlers(mainWindow: BrowserWindow, store: Store): v
let createdDir = false
let targetExists = false
try {
+ // Why: the name-first default points at ~/orca/projects, which may not
+ // exist yet on a fresh install; create only the parent before probing target.
+ await mkdir(parentPath, { recursive: true })
await access(targetPath)
targetExists = true
} catch (err) {
diff --git a/src/main/runtime/orca-runtime.test.ts b/src/main/runtime/orca-runtime.test.ts
index e251bd666f6..f50f1607f9f 100644
--- a/src/main/runtime/orca-runtime.test.ts
+++ b/src/main/runtime/orca-runtime.test.ts
@@ -3179,6 +3179,33 @@ describe('OrcaRuntimeService', () => {
}
})
+ it('creates a missing runtime parent before creating the project directory', async () => {
+ const added: Record[] = []
+ const createStore = {
+ ...store,
+ getRepos: () => [...added] as never,
+ addRepo: (repo: Record) => {
+ added.push(repo)
+ },
+ getRepo: (id: string) => added.find((repo) => repo.id === id) as never
+ }
+ const runtime = new OrcaRuntimeService(createStore as never)
+ const tempRoot = await mkdtemp('/tmp/orca-runtime-create-parent-')
+ const parentDir = join(tempRoot, 'orca', 'projects')
+ try {
+ const result = await runtime.createRepo(parentDir, 'first-project', 'folder')
+ if ('error' in result) {
+ throw new Error(result.error)
+ }
+
+ expect((await lstat(parentDir)).isDirectory()).toBe(true)
+ expect((await lstat(join(parentDir, 'first-project'))).isDirectory()).toBe(true)
+ expect(result).toHaveProperty('repo.path', join(parentDir, 'first-project'))
+ } finally {
+ await rm(tempRoot, { recursive: true, force: true })
+ }
+ })
+
it('preserves existing badgeColor on runtime createRepo dedupe', async () => {
const existing = {
id: 'runtime-existing-create',
diff --git a/src/main/runtime/orca-runtime.ts b/src/main/runtime/orca-runtime.ts
index afc5038d126..2fe3104d4bb 100644
--- a/src/main/runtime/orca-runtime.ts
+++ b/src/main/runtime/orca-runtime.ts
@@ -6525,6 +6525,15 @@ export class OrcaRuntimeService {
return { resolvedPath: dirPath, entries: mapped }
}
+ async isGitAvailable(): Promise {
+ try {
+ await gitExecFileAsync(['--version'], { cwd: process.cwd(), timeout: 3000 })
+ return true
+ } catch {
+ return false
+ }
+ }
+
async importNestedRepos(args: {
parentPath: string
groupName: string
@@ -6722,6 +6731,9 @@ export class OrcaRuntimeService {
let createdDir = false
try {
+ // Why: default create-project parents are host-home based and may not exist
+ // before the first project is created on a fresh runtime.
+ await mkdir(trimmedParentPath, { recursive: true })
const existingStat = await stat(targetPath).catch((error: unknown) => {
if (isENOENT(error)) {
return null
diff --git a/src/main/runtime/rpc/methods/repo.test.ts b/src/main/runtime/rpc/methods/repo.test.ts
index aa4723be693..d6e3cc65526 100644
--- a/src/main/runtime/rpc/methods/repo.test.ts
+++ b/src/main/runtime/rpc/methods/repo.test.ts
@@ -33,6 +33,22 @@ describe('repo RPC methods', () => {
})
})
+ it('reports runtime Git availability without exposing command details', async () => {
+ const runtime = {
+ getRuntimeId: () => 'test-runtime',
+ isGitAvailable: vi.fn().mockResolvedValue(true)
+ } as unknown as OrcaRuntimeService
+ const dispatcher = new RpcDispatcher({ runtime, methods: REPO_METHODS })
+
+ const response = await dispatcher.dispatch(makeRequest('repo.gitAvailable'))
+
+ expect(runtime.isGitAvailable).toHaveBeenCalled()
+ expect(response).toMatchObject({
+ ok: true,
+ result: { available: true }
+ })
+ })
+
it('clones a repo on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
diff --git a/src/main/runtime/rpc/methods/repo.ts b/src/main/runtime/rpc/methods/repo.ts
index a2e3f6fea10..5cf4926868c 100644
--- a/src/main/runtime/rpc/methods/repo.ts
+++ b/src/main/runtime/rpc/methods/repo.ts
@@ -228,6 +228,11 @@ export const REPO_METHODS: RpcMethod[] = [
handler: async (params, { runtime }) =>
runtime.createRepo(params.parentPath, params.name, params.kind)
}),
+ defineMethod({
+ name: 'repo.gitAvailable',
+ params: null,
+ handler: async (_params, { runtime }) => ({ available: await runtime.isGitAvailable() })
+ }),
defineMethod({
name: 'repo.clone',
params: RepoClone,
diff --git a/src/main/runtime/runtime-rpc.ts b/src/main/runtime/runtime-rpc.ts
index 68994b1d045..5f75556e69e 100644
--- a/src/main/runtime/runtime-rpc.ts
+++ b/src/main/runtime/runtime-rpc.ts
@@ -251,6 +251,7 @@ const MOBILE_RPC_METHOD_ALLOWLIST = new Set([
'preflight.detectAgents',
'preflight.detectRemoteAgents',
'repo.baseRefDefault',
+ 'repo.gitAvailable',
'repo.hooks',
'repo.list',
'repo.saveSparsePreset',
diff --git a/src/preload/api-types.ts b/src/preload/api-types.ts
index d04d442ad75..7736aed6a82 100644
--- a/src/preload/api-types.ts
+++ b/src/preload/api-types.ts
@@ -764,6 +764,8 @@ export type PreloadApi = {
name: string
kind: 'git' | 'folder'
}) => Promise<{ repo: Repo } | { error: string }>
+ isGitAvailable: () => Promise
+ getDefaultCreateProjectParent: () => Promise
onCloneProgress: (callback: (data: { phase: string; percent: number }) => void) => () => void
getGitUsername: (args: { repoId: string }) => Promise
getBaseRefDefault: (args: { repoId: string }) => Promise
diff --git a/src/preload/index.ts b/src/preload/index.ts
index 517aaadb679..dd4fea25960 100644
--- a/src/preload/index.ts
+++ b/src/preload/index.ts
@@ -460,6 +460,11 @@ const api = {
create: (args) => ipcRenderer.invoke('repos:create', args),
+ isGitAvailable: (): Promise => ipcRenderer.invoke('repos:isGitAvailable'),
+
+ getDefaultCreateProjectParent: (): Promise =>
+ ipcRenderer.invoke('repos:getDefaultCreateProjectParent'),
+
remove: (args) => ipcRenderer.invoke('repos:remove', args),
reorder: (args) => ipcRenderer.invoke('repos:reorder', args),
diff --git a/src/renderer/src/components/sidebar/AddRepoCreateStep.test.tsx b/src/renderer/src/components/sidebar/AddRepoCreateStep.test.tsx
new file mode 100644
index 00000000000..5aa81139153
--- /dev/null
+++ b/src/renderer/src/components/sidebar/AddRepoCreateStep.test.tsx
@@ -0,0 +1,74 @@
+import { renderToStaticMarkup } from 'react-dom/server'
+import { describe, expect, it, vi } from 'vitest'
+import { Dialog } from '@/components/ui/dialog'
+import { TooltipProvider } from '@/components/ui/tooltip'
+import { CreateStep } from './AddRepoCreateStep'
+import type { GitAvailability, RepoKind } from './create-project-defaults'
+
+function renderCreateStep({
+ createName = '',
+ createKind = 'git',
+ gitAvailability = 'available',
+ createParent = '/Users/alice/orca/projects',
+ parentDefaultPending = false
+}: {
+ createName?: string
+ createKind?: RepoKind
+ gitAvailability?: GitAvailability
+ createParent?: string
+ parentDefaultPending?: boolean
+} = {}): string {
+ return renderToStaticMarkup(
+
+
+
+
+
+ )
+}
+
+describe('CreateStep', () => {
+ it('renders the name-first create UI with advanced controls collapsed', () => {
+ const html = renderCreateStep()
+
+ expect(html).toContain('Create a new project')
+ expect(html).toContain('Name')
+ expect(html).toContain('Git repository in ~/orca/projects')
+ // The summary card itself is the collapsed disclosure for the uncommon settings.
+ expect(html).toContain('aria-expanded="false"')
+ expect(html).not.toContain('Project kind')
+ expect(html).not.toContain('Location')
+ expect(html).not.toContain('aria-label="Browse server filesystem"')
+ })
+
+ it('shows the Git fallback explanation in the collapsed summary', () => {
+ const html = renderCreateStep({ createKind: 'folder', gitAvailability: 'unavailable' })
+
+ expect(html).toContain('Folder in ~/orca/projects')
+ expect(html).toContain('Git isn't installed, so a plain folder is the default.')
+ })
+
+ it('disables create while an auto-filled parent belongs to a previous target', () => {
+ const html = renderCreateStep({
+ createName: 'demo-project',
+ parentDefaultPending: true
+ })
+
+ expect(html).toContain('disabled=""')
+ })
+})
diff --git a/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx b/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
index 204ef5bc410..863b1121238 100644
--- a/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoCreateStep.tsx
@@ -1,272 +1,25 @@
// Step for AddRepoDialog (orca#763), split out so create-project state stays scoped.
-import React, { useCallback, useRef, useState } from 'react'
-import { toast } from 'sonner'
-import { Folder, GitBranch } from 'lucide-react'
-import { useAppStore } from '@/store'
-import { useMountedRef } from '@/hooks/useMountedRef'
+import React, { useCallback, useMemo, useRef, useState } from 'react'
+import { ChevronDown, Folder, GitBranch, Loader2 } from 'lucide-react'
import { DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
-import { activateAndRevealWorktree } from '@/lib/worktree-activation'
-import { markOnboardingProjectAdded } from '@/lib/onboarding-project-checklist'
-import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
-import { isGitRepoKind } from '../../../../shared/repo-kind'
-import type { Repo } from '../../../../shared/types'
+import { cn } from '@/lib/utils'
import {
CreateProjectLocationField,
CreateProjectParentBrowser
} from './CreateProjectLocationField'
import { translate } from '@/i18n/i18n'
-
-type RepoKind = 'git' | 'folder'
-
-export function useCreateRepo(
- fetchWorktrees: (
- repoId: string,
- options?: { requireAuthoritative?: boolean }
- ) => Promise,
- closeModal: () => void,
- onGitRepoReady?: (repoId: string) => void | Promise
-) {
- const [createName, setCreateName] = useState('')
- const [createParent, setCreateParent] = useState('')
- const [createKind, setCreateKind] = useState('git')
- const [createError, setCreateError] = useState(null)
- const [isCreating, setIsCreating] = useState(false)
- const mountedRef = useMountedRef()
-
- // Why: monotonic ID so stale create callbacks can detect they were superseded
- // when the user clicks Back or closes the dialog mid-create. Mirrors the
- // cloneGenRef pattern in AddRepoDialog.
- const createGenRef = useRef(0)
-
- const resetCreateState = useCallback(() => {
- createGenRef.current++
- setCreateName('')
- setCreateParent('')
- setCreateKind('git')
- setCreateError(null)
- setIsCreating(false)
- }, [])
-
- const handlePickParent = useCallback(async () => {
- if (useAppStore.getState().settings?.activeRuntimeEnvironmentId?.trim()) {
- // Why: the native folder picker returns a client-local path. Runtime
- // project creation needs an explicit server parent path.
- toast.error(
- translate(
- 'auto.components.sidebar.AddRepoCreateStep.875dda0995',
- 'Enter a server parent path.'
- )
- )
- return
- }
- const gen = createGenRef.current
- const dir = await window.api.repos.pickDirectory()
- if (dir && gen === createGenRef.current && mountedRef.current) {
- setCreateParent(dir)
- setCreateError(null)
- }
- }, [mountedRef])
-
- const handleCreate = useCallback(async () => {
- const name = createName.trim()
- const parentPath = createParent.trim()
- if (!name || !parentPath) {
- return
- }
- const gen = ++createGenRef.current
- setIsCreating(true)
- setCreateError(null)
- try {
- const target = getActiveRuntimeTarget(useAppStore.getState().settings)
- const result =
- target.kind === 'environment'
- ? await callRuntimeRpc<{ repo: Repo } | { error: string }>(
- target,
- 'repo.create',
- {
- parentPath,
- name,
- kind: createKind
- },
- { timeoutMs: 60_000 }
- )
- : await window.api.repos.create({
- parentPath,
- name,
- kind: createKind
- })
- // Why: if the user closed the dialog or clicked Back mid-create,
- // createGenRef was bumped by resetCreateState. Ignore stale results.
- if (gen !== createGenRef.current || !mountedRef.current) {
- return
- }
- if ('error' in result) {
- setCreateError(result.error)
- return
- }
- const repo = result.repo
- // Upsert into the store before the repos:changed event round-trips,
- // so the next step can find the repo immediately.
- const state = useAppStore.getState()
- const existingIdx = state.repos.findIndex((r) => r.id === repo.id)
- // Why: the IPC handler dedupes by path (see repos:create) and returns
- // the existing repo unchanged. If its ID is already in our store, the
- // handler took the dedup path — no new project was created, so don't
- // claim one was.
- const wasDeduped = existingIdx !== -1
- if (existingIdx === -1) {
- useAppStore.setState({ repos: [...state.repos, repo] })
- } else {
- const updated = [...state.repos]
- updated[existingIdx] = repo
- useAppStore.setState({ repos: updated })
- }
- if (wasDeduped) {
- toast.info(
- translate(
- 'auto.components.sidebar.AddRepoCreateStep.2c12db1511',
- 'Project already added'
- ),
- {
- description: repo.displayName
- }
- )
- } else {
- toast.success(
- translate('auto.components.sidebar.AddRepoCreateStep.5e97f0c4b9', 'Project created'),
- {
- description: repo.displayName
- }
- )
- }
- if (isGitRepoKind(repo)) {
- // Why: Git repos use the shared default-checkout completion path.
- // Why: if refresh is temporarily non-authoritative, the shared opener
- // still reveals the project so the user is not left in a completed add flow.
- await fetchWorktrees(repo.id, { requireAuthoritative: true })
- if (gen !== createGenRef.current || !mountedRef.current) {
- return
- }
- await onGitRepoReady?.(repo.id)
- } else {
- // Why: folder repos skip the Git default-checkout handoff, so activate the synthetic
- // root workspace before closing. Matches addNonGitFolder's behavior.
- await fetchWorktrees(repo.id)
- if (gen !== createGenRef.current || !mountedRef.current) {
- return
- }
- const folderWorktree = useAppStore.getState().worktreesByRepo[repo.id]?.[0]
- if (folderWorktree) {
- activateAndRevealWorktree(folderWorktree.id, { sidebarRevealBehavior: 'auto' })
- }
- await markOnboardingProjectAdded('addedFolder')
- closeModal()
- }
- } catch (err) {
- if (gen !== createGenRef.current || !mountedRef.current) {
- return
- }
- setCreateError(err instanceof Error ? err.message : String(err))
- } finally {
- // Why: only clear the loading state if this invocation is still current;
- // a superseded create must not flip the flag back off for a new flow.
- if (gen === createGenRef.current && mountedRef.current) {
- setIsCreating(false)
- }
- }
- }, [createName, createParent, createKind, fetchWorktrees, mountedRef, closeModal, onGitRepoReady])
-
- return {
- createName,
- createParent,
- createKind,
- createError,
- isCreating,
- setCreateName,
- setCreateParent,
- setCreateKind,
- setCreateError,
- resetCreateState,
- handlePickParent,
- handleCreate
- }
-}
+import {
+ formatCreateProjectParentSummary,
+ joinCreateProjectPath,
+ type GitAvailability,
+ type RepoKind
+} from './create-project-defaults'
// ── UI helpers ───────────────────────────────────────────────────────
-type KindCardProps = {
- kind: RepoKind
- selected: boolean
- disabled: boolean
- onSelect: () => void
- onArrowNav: () => void
- icon: React.ReactNode
- title: string
- caption: string
-}
-
-function KindCard({
- kind,
- selected,
- disabled,
- onSelect,
- onArrowNav,
- icon,
- title,
- caption
-}: KindCardProps): React.JSX.Element {
- return (
- {
- // Why: WAI-ARIA radiogroup spec expects all four arrow keys to move
- // selection. Left/Right handle the horizontal grid layout; Up/Down
- // are added so vertical nav (e.g. screen-reader users, future layout
- // changes) behaves the same.
- if (
- e.key === 'ArrowLeft' ||
- e.key === 'ArrowRight' ||
- e.key === 'ArrowUp' ||
- e.key === 'ArrowDown'
- ) {
- e.preventDefault()
- onArrowNav()
- } else if (e.key === ' ' || e.key === 'Enter') {
- e.preventDefault()
- onSelect()
- }
- }}
- disabled={disabled}
- data-kind={kind}
- className={`group relative flex items-center gap-3 rounded-md border px-3.5 py-3.5 text-left text-xs transition-colors cursor-pointer outline-none ${
- selected ? 'border-foreground/30 bg-accent' : 'border-border hover:bg-accent/50'
- } focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60`}
- >
- {/* Icon chip gives the glyph enough weight to sit balanced next to the title block. */}
-
- {icon}
-
-
- {title}
-
- {caption}
-
-
-
- )
-}
+const CREATE_PROJECT_NAME_PLACEHOLDER = 'project-name'
type CreateStepProps = {
createName: string
@@ -274,6 +27,10 @@ type CreateStepProps = {
createKind: RepoKind
createError: string | null
isCreating: boolean
+ defaultParent?: string
+ gitAvailability?: GitAvailability
+ runtimeParentStatus?: 'idle' | 'checking' | 'failed'
+ parentDefaultPending?: boolean
manualParentEntry?: boolean
runtimeEnvironmentId?: string | null
onNameChange: (value: string) => void
@@ -289,6 +46,10 @@ export function CreateStep({
createKind,
createError,
isCreating,
+ defaultParent = '',
+ gitAvailability = 'unknown',
+ runtimeParentStatus = 'idle',
+ parentDefaultPending = false,
manualParentEntry = false,
runtimeEnvironmentId,
onNameChange,
@@ -300,6 +61,7 @@ export function CreateStep({
const radioGroupRef = useRef(null)
const radioFocusFrameRef = useRef(null)
const [browsingParent, setBrowsingParent] = useState(false)
+ const [advancedOpen, setAdvancedOpen] = useState(false)
const cancelRadioFocusFrame = useCallback((): void => {
if (radioFocusFrameRef.current === null) {
@@ -334,7 +96,50 @@ export function CreateStep({
})
}, [cancelRadioFocusFrame, createKind, onKindChange])
- const canSubmit = createName.trim().length > 0 && createParent.trim().length > 0 && !isCreating
+ const canSubmit =
+ createName.trim().length > 0 &&
+ createParent.trim().length > 0 &&
+ gitAvailability !== 'checking' &&
+ !parentDefaultPending &&
+ !isCreating
+ const missingLocationLabel = translate(
+ 'auto.components.sidebar.AddRepoCreateStep.3a13f6e88b',
+ 'location not selected'
+ )
+ const missingServerLocationLabel = translate(
+ 'auto.components.sidebar.AddRepoCreateStep.6ed14c0281',
+ 'server folder not selected'
+ )
+
+ const summaryParent = useMemo(
+ () =>
+ formatCreateProjectParentSummary({
+ parent: createParent,
+ defaultParent,
+ runtimeEnvironmentId,
+ missingLocationLabel,
+ missingServerLocationLabel
+ }),
+ [
+ createParent,
+ defaultParent,
+ missingLocationLabel,
+ missingServerLocationLabel,
+ runtimeEnvironmentId
+ ]
+ )
+ const targetPathPreview = useMemo(() => {
+ const name = createName.trim() || CREATE_PROJECT_NAME_PLACEHOLDER
+ return createParent.trim() ? joinCreateProjectPath(createParent, name) : ''
+ }, [createName, createParent])
+ const kindLabel =
+ createKind === 'git'
+ ? translate('auto.components.sidebar.AddRepoCreateStep.11fd2a7db8', 'Git repository')
+ : translate('auto.components.sidebar.AddRepoCreateStep.038729c107', 'Folder')
+ const showGitFallback = gitAvailability === 'unavailable'
+ const showGitChecking = gitAvailability === 'checking'
+ const showRuntimeMissingParent =
+ runtimeEnvironmentId && !createParent.trim() && runtimeParentStatus !== 'checking'
if (browsingParent && runtimeEnvironmentId) {
return (
@@ -351,12 +156,15 @@ export function CreateStep({
<>
- {translate('auto.components.sidebar.AddRepoCreateStep.db9be12229', 'Start a new project')}
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.c7b9f94456',
+ 'Create a new project'
+ )}
{translate(
- 'auto.components.sidebar.AddRepoCreateStep.d877ece0d6',
- 'Create a Git repository or a plain folder and open it in Orca.'
+ 'auto.components.sidebar.AddRepoCreateStep.b100311784',
+ 'Name it and Orca will create a real project with sensible defaults.'
)}
@@ -366,41 +174,6 @@ export function CreateStep({
the dialog width even with flex + truncate on the row itself. min-w-0
here caps the grid track at the dialog's max-width. */}
- {/* Kind toggle. Real radiogroup so screen readers announce it as a choice. */}
-
- onKindChange('git')}
- onArrowNav={cycleKind}
- icon={ }
- title={translate(
- 'auto.components.sidebar.AddRepoCreateStep.11fd2a7db8',
- 'Git repository'
- )}
- caption="Initializes an empty Git repo"
- />
- onKindChange('folder')}
- onArrowNav={cycleKind}
- icon={ }
- title={translate('auto.components.sidebar.AddRepoCreateStep.038729c107', 'Folder')}
- caption="Create a new folder"
- />
-
-
{/* Name. Monospaced because it ends up as a directory name. */}
- {/* The local picker returns client paths; runtime servers browse host paths via RPC. */}
-
setBrowsingParent(true)}
- />
+ {/* Summary card doubles as the disclosure for the uncommon settings, so the
+ defaults and the controls to change them live in one place. */}
+
+
setAdvancedOpen((open) => !open)}
+ aria-expanded={advancedOpen}
+ className="flex w-full min-w-0 items-start gap-2.5 rounded-md px-3 py-2.5 text-left transition-colors cursor-pointer hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
+ >
+
+ {createKind === 'git' ? (
+
+ ) : (
+
+ )}
+
+
+
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.685b5eefe1',
+ '{{kind}} in {{parent}}',
+ {
+ kind: kindLabel,
+ parent: summaryParent
+ }
+ )}
+
+ {showGitChecking ? (
+
+
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.2a762f3b19',
+ 'Checking Git on this host...'
+ )}
+
+ ) : showGitFallback ? (
+
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.fe1e616c5b',
+ "Git isn't installed, so a plain folder is the default."
+ )}
+
+ ) : showRuntimeMissingParent ? (
+
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.c234df77f7',
+ 'Choose or enter a server parent folder before creating.'
+ )}
+
+ ) : targetPathPreview ? (
+
+ {targetPathPreview}
+
+ ) : null}
+
+
+
+
+ {advancedOpen && (
+
+ {/* Real radiogroup so screen readers announce the segmented choice. */}
+
+
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.180e9b5e48',
+ 'Project kind'
+ )}
+
+
+ {(['git', 'folder'] as const).map((kind) => {
+ const selected = createKind === kind
+ const label =
+ kind === 'git'
+ ? translate(
+ 'auto.components.sidebar.AddRepoCreateStep.11fd2a7db8',
+ 'Git repository'
+ )
+ : translate(
+ 'auto.components.sidebar.AddRepoCreateStep.038729c107',
+ 'Folder'
+ )
+ const Icon = kind === 'git' ? GitBranch : Folder
+ return (
+ onKindChange(kind)}
+ onKeyDown={(e) => {
+ // Why: keep keyboard radio navigation intact inside the compact segmented control.
+ if (
+ e.key === 'ArrowLeft' ||
+ e.key === 'ArrowRight' ||
+ e.key === 'ArrowUp' ||
+ e.key === 'ArrowDown'
+ ) {
+ e.preventDefault()
+ cycleKind()
+ } else if (e.key === ' ' || e.key === 'Enter') {
+ e.preventDefault()
+ onKindChange(kind)
+ }
+ }}
+ disabled={isCreating}
+ data-kind={kind}
+ className={cn(
+ 'inline-flex min-w-0 items-center justify-center gap-1.5 rounded-sm border px-2.5 py-2 text-xs font-medium outline-none transition-colors',
+ // Why: the segment sits on a muted card, so bg-background alone
+ // is too subtle; the border makes the selected state legible.
+ selected
+ ? 'border-border bg-background text-foreground shadow-xs'
+ : 'border-transparent text-muted-foreground hover:text-foreground',
+ 'focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-60'
+ )}
+ >
+
+ {label}
+
+ )
+ })}
+
+ {showGitFallback && (
+
+ {translate(
+ 'auto.components.sidebar.AddRepoCreateStep.fe1e616c5b',
+ "Git isn't installed, so a plain folder is the default."
+ )}
+
+ )}
+
+
+ {/* The local picker returns client paths; runtime servers browse host paths via RPC. */}
+
setBrowsingParent(true)}
+ />
+
+ {targetPathPreview && (
+
+ {targetPathPreview}
+
+ )}
+
+ )}
+
{createError && (
diff --git a/src/renderer/src/components/sidebar/AddRepoDialog.tsx b/src/renderer/src/components/sidebar/AddRepoDialog.tsx
index f9975630ded..5bf06950be3 100644
--- a/src/renderer/src/components/sidebar/AddRepoDialog.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoDialog.tsx
@@ -3,7 +3,7 @@ import { useAppStore } from '@/store'
import { Dialog, DialogContent } from '@/components/ui/dialog'
import { track } from '@/lib/telemetry'
import { useRemoteRepo } from './AddRepoSteps'
-import { useCreateRepo } from './AddRepoCreateStep'
+import { useCreateRepo } from './useCreateRepo'
import { buildNestedRepoScanTelemetry } from '../../../../shared/nested-repo-telemetry'
import type { AddRepoExistingWorkspaceSource } from '../../../../shared/telemetry-events'
import { AddRepoStepIndicator } from './AddRepoStepIndicator'
@@ -14,11 +14,9 @@ import { useAddRepoCloneFlow } from './useAddRepoCloneFlow'
import { useAddRepoLocalFolderFlow } from './useAddRepoLocalFolderFlow'
import { useAddRepoServerPathFlow } from './useAddRepoServerPathFlow'
import { useAddRepoNestedImportFlow } from './useAddRepoNestedImportFlow'
-import {
- buildAddRepoExistingWorkspacesTelemetry,
- shouldTrackAddRepoExistingWorkspacesDetected
-} from './add-repo-existing-workspaces-telemetry'
+import { buildAddRepoExistingWorkspacesDetectedEvent } from './add-repo-existing-workspaces-telemetry'
import { finishProjectAddWithDefaultCheckout } from './project-added-default-checkout'
+import { useCreateProjectDefaults } from './useCreateProjectDefaults'
const AddRepoDialog = React.memo(function AddRepoDialog() {
const activeModal = useAppStore((s) => s.activeModal)
@@ -68,21 +66,11 @@ const AddRepoDialog = React.memo(function AddRepoDialog() {
const completeGitRepoAdd = useCallback(
async (repoId: string, source: AddRepoExistingWorkspaceSource): Promise => {
const worktrees = useAppStore.getState().worktreesByRepo[repoId] ?? []
- const sortedWorktrees = [...worktrees].sort((a, b) => {
- if (a.lastActivityAt !== b.lastActivityAt) {
- return b.lastActivityAt - a.lastActivityAt
- }
- return a.displayName.localeCompare(b.displayName)
- })
- const existingWorkspaceTelemetry = buildAddRepoExistingWorkspacesTelemetry(
+ const existingWorkspaceTelemetry = buildAddRepoExistingWorkspacesDetectedEvent(
source,
- sortedWorktrees
+ worktrees
)
- if (
- existingWorkspaceTelemetry &&
- shouldTrackAddRepoExistingWorkspacesDetected(existingWorkspaceTelemetry) &&
- !detectedTelemetryTrackedRef.current.has(repoId)
- ) {
+ if (existingWorkspaceTelemetry && !detectedTelemetryTrackedRef.current.has(repoId)) {
detectedTelemetryTrackedRef.current.add(repoId)
track('add_repo_existing_workspaces_detected', existingWorkspaceTelemetry)
}
@@ -159,6 +147,22 @@ const AddRepoDialog = React.memo(function AddRepoDialog() {
completeGitRepoAdd(repoId, 'create_project')
)
+ const {
+ createDefaultParent,
+ createGitAvailability,
+ createRuntimeParentStatus,
+ createParentDefaultPending,
+ resetCreateDefaultState,
+ markCreateParentTouched,
+ markCreateKindTouched
+ } = useCreateProjectDefaults({
+ step,
+ activeRuntimeEnvironmentId: settings?.activeRuntimeEnvironmentId,
+ createParent,
+ setCreateParent,
+ setCreateKind
+ })
+
const {
cloneUrl,
cloneDestination,
@@ -252,12 +256,14 @@ const AddRepoDialog = React.memo(function AddRepoDialog() {
resetCloneFlow()
resetNestedImportFlow()
resetNestedRepoReviewState()
+ resetCreateDefaultState()
resetCreateState()
resetRemoteState()
}, [
resetCloneFlow,
resetLocalFolderFlow,
resetNestedRepoReviewState,
+ resetCreateDefaultState,
resetServerPathFlow,
resetNestedImportFlow,
resetRemoteState,
@@ -329,6 +335,10 @@ const AddRepoDialog = React.memo(function AddRepoDialog() {
createKind={createKind}
createError={createError}
isCreating={isCreating}
+ createDefaultParent={createDefaultParent}
+ createGitAvailability={createGitAvailability}
+ createRuntimeParentStatus={createRuntimeParentStatus}
+ createParentDefaultPending={createParentDefaultPending}
onBrowse={handleBrowse}
onOpenCloneStep={() => {
setCloneError(null)
@@ -376,14 +386,22 @@ const AddRepoDialog = React.memo(function AddRepoDialog() {
setCreateError(null)
}}
onCreateParentChange={(value) => {
+ markCreateParentTouched(value)
setCreateParent(value)
setCreateError(null)
}}
onCreateKindChange={(kind) => {
+ markCreateKindTouched()
setCreateKind(kind)
setCreateError(null)
}}
- onPickCreateParent={handlePickParent}
+ onPickCreateParent={() => {
+ void handlePickParent().then((dir) => {
+ if (dir) {
+ markCreateParentTouched(dir)
+ }
+ })
+ }}
onCreate={handleCreate}
/>
diff --git a/src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx b/src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx
index d37cb4c32ef..c54501d6c81 100644
--- a/src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx
@@ -56,6 +56,10 @@ function renderStepContent(overrides: Partial): string {
createKind: 'git',
createError: null,
isCreating: false,
+ createDefaultParent: '',
+ createGitAvailability: 'unknown',
+ createRuntimeParentStatus: 'idle',
+ createParentDefaultPending: false,
onBrowse: vi.fn(),
onOpenCloneStep: vi.fn(),
onOpenCreateStep: vi.fn(),
@@ -123,8 +127,8 @@ describe('AddRepoDialogStepContent nested imports', () => {
activeRuntimeEnvironmentId: 'env-1'
})
- expect(html).toContain('Start a new project')
- expect(html).toContain('aria-label="Browse server filesystem"')
+ expect(html).toContain('Create a new project')
+ expect(html).toContain('server folder not selected')
})
it('offers server browsing for remote clone destinations', () => {
diff --git a/src/renderer/src/components/sidebar/AddRepoDialogStepContent.tsx b/src/renderer/src/components/sidebar/AddRepoDialogStepContent.tsx
index 8172131de76..4ac9bc2e523 100644
--- a/src/renderer/src/components/sidebar/AddRepoDialogStepContent.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoDialogStepContent.tsx
@@ -8,6 +8,7 @@ import { AddRepoNestedImportStep } from './AddRepoNestedImportStep'
import type { AddRepoDialogStep } from './add-repo-dialog-types'
import type { NestedRepoScanResult } from '../../../../shared/types'
import type { SshConnectionState, SshTarget } from '../../../../shared/ssh-types'
+import type { GitAvailability } from './create-project-defaults'
type AddRepoDialogStepContentProps = {
step: AddRepoDialogStep
@@ -40,6 +41,10 @@ type AddRepoDialogStepContentProps = {
createKind: 'git' | 'folder'
createError: string | null
isCreating: boolean
+ createDefaultParent: string
+ createGitAvailability: GitAvailability
+ createRuntimeParentStatus: 'idle' | 'checking' | 'failed'
+ createParentDefaultPending: boolean
onBrowse: () => void
onOpenCloneStep: () => void
onOpenCreateStep: () => void
@@ -98,6 +103,10 @@ export function AddRepoDialogStepContent({
createKind,
createError,
isCreating,
+ createDefaultParent,
+ createGitAvailability,
+ createRuntimeParentStatus,
+ createParentDefaultPending,
onBrowse,
onOpenCloneStep,
onOpenCreateStep,
@@ -219,6 +228,10 @@ export function AddRepoDialogStepContent({
createKind={createKind}
createError={createError}
isCreating={isCreating}
+ defaultParent={createDefaultParent}
+ gitAvailability={createGitAvailability}
+ runtimeParentStatus={createRuntimeParentStatus}
+ parentDefaultPending={createParentDefaultPending}
manualParentEntry={isRuntimeEnvironmentActive}
runtimeEnvironmentId={activeRuntimeEnvironmentId}
onNameChange={onCreateNameChange}
diff --git a/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx b/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
index 025045b7938..9b0ae00c3f9 100644
--- a/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
+++ b/src/renderer/src/components/sidebar/CreateProjectLocationField.tsx
@@ -1,4 +1,4 @@
-import { Folder, FolderOpen, Home, Pencil } from 'lucide-react'
+import { Folder, FolderOpen, Pencil } from 'lucide-react'
import { DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
@@ -113,9 +113,6 @@ export function CreateProjectLocationField({
) : createParent ? (
-
-
-
{createParent}
diff --git a/src/renderer/src/components/sidebar/add-repo-existing-workspaces-telemetry.ts b/src/renderer/src/components/sidebar/add-repo-existing-workspaces-telemetry.ts
index f1511e2bf5f..9b423ed5ca3 100644
--- a/src/renderer/src/components/sidebar/add-repo-existing-workspaces-telemetry.ts
+++ b/src/renderer/src/components/sidebar/add-repo-existing-workspaces-telemetry.ts
@@ -60,6 +60,20 @@ export function buildAddRepoExistingWorkspacesTelemetry(
}
}
+export function buildAddRepoExistingWorkspacesDetectedEvent(
+ source: AddRepoExistingWorkspaceSource,
+ worktrees: readonly Worktree[]
+): ExistingWorkspacesDetectedProps | null {
+ const sortedWorktrees = [...worktrees].sort((a, b) => {
+ if (a.lastActivityAt !== b.lastActivityAt) {
+ return b.lastActivityAt - a.lastActivityAt
+ }
+ return a.displayName.localeCompare(b.displayName)
+ })
+ const payload = buildAddRepoExistingWorkspacesTelemetry(source, sortedWorktrees)
+ return payload && shouldTrackAddRepoExistingWorkspacesDetected(payload) ? payload : null
+}
+
export function shouldTrackAddRepoExistingWorkspacesDetected(
payload: ExistingWorkspacesDetectedProps | null
): boolean {
diff --git a/src/renderer/src/components/sidebar/create-project-defaults.test.ts b/src/renderer/src/components/sidebar/create-project-defaults.test.ts
new file mode 100644
index 00000000000..4691b605081
--- /dev/null
+++ b/src/renderer/src/components/sidebar/create-project-defaults.test.ts
@@ -0,0 +1,90 @@
+import { describe, expect, it } from 'vitest'
+import {
+ formatCreateProjectParentSummary,
+ getCreateProjectDefaultParentAutoFill,
+ getDefaultCreateProjectParent,
+ joinCreateProjectPath
+} from './create-project-defaults'
+
+describe('create project defaults', () => {
+ it('builds the POSIX default project parent', () => {
+ expect(getDefaultCreateProjectParent('/Users/alice')).toBe('/Users/alice/orca/projects')
+ })
+
+ it('builds the Windows default project parent', () => {
+ expect(getDefaultCreateProjectParent('C:\\Users\\alice')).toBe(
+ 'C:\\Users\\alice\\orca\\projects'
+ )
+ })
+
+ it('derives the runtime project default from a resolved server home', () => {
+ expect(getDefaultCreateProjectParent('/home/alice')).toBe('/home/alice/orca/projects')
+ })
+
+ it('joins path previews without mixing separators', () => {
+ expect(joinCreateProjectPath('/home/alice/orca/projects', 'demo')).toBe(
+ '/home/alice/orca/projects/demo'
+ )
+ expect(joinCreateProjectPath('C:\\Users\\alice\\orca\\projects', 'demo')).toBe(
+ 'C:\\Users\\alice\\orca\\projects\\demo'
+ )
+ })
+
+ it('auto-fills only the first empty local create step', () => {
+ expect(
+ getCreateProjectDefaultParentAutoFill({
+ step: 'create',
+ createParent: '',
+ activeRuntimeEnvironmentId: null,
+ defaultParent: '/Users/alice/orca/projects',
+ createStepAutoFilled: false
+ })
+ ).toEqual({ parent: '/Users/alice/orca/projects' })
+ expect(
+ getCreateProjectDefaultParentAutoFill({
+ step: 'create',
+ createParent: '/tmp/project',
+ activeRuntimeEnvironmentId: null,
+ defaultParent: '/Users/alice/orca/projects',
+ createStepAutoFilled: false
+ })
+ ).toBeNull()
+ expect(
+ getCreateProjectDefaultParentAutoFill({
+ step: 'create',
+ createParent: '',
+ activeRuntimeEnvironmentId: null,
+ defaultParent: '/Users/alice/orca/projects',
+ createStepAutoFilled: true
+ })
+ ).toBeNull()
+ })
+
+ it('does not apply a local default while a runtime environment is active', () => {
+ expect(
+ getCreateProjectDefaultParentAutoFill({
+ step: 'create',
+ createParent: '',
+ activeRuntimeEnvironmentId: 'env-1',
+ defaultParent: '/Users/alice/orca/projects',
+ createStepAutoFilled: false
+ })
+ ).toBeNull()
+ })
+
+ it('uses a short local summary only for the local default parent', () => {
+ expect(
+ formatCreateProjectParentSummary({
+ parent: '/Users/alice/orca/projects',
+ defaultParent: '/Users/alice/orca/projects'
+ })
+ ).toBe('~/orca/projects')
+ expect(
+ formatCreateProjectParentSummary({
+ parent: '',
+ defaultParent: '',
+ runtimeEnvironmentId: 'env-1'
+ })
+ ).toBe('server folder not selected')
+ })
+})
diff --git a/src/renderer/src/components/sidebar/create-project-defaults.ts b/src/renderer/src/components/sidebar/create-project-defaults.ts
new file mode 100644
index 00000000000..e5df269a967
--- /dev/null
+++ b/src/renderer/src/components/sidebar/create-project-defaults.ts
@@ -0,0 +1,88 @@
+export type RepoKind = 'git' | 'folder'
+
+export type GitAvailability = 'checking' | 'available' | 'unavailable' | 'unknown'
+
+function pathSeparatorFor(pathValue: string): '/' | '\\' {
+ return pathValue.includes('\\') ? '\\' : '/'
+}
+
+function trimTrailingSeparators(pathValue: string): string {
+ const trimmed = pathValue.replace(/[\\/]+$/, '')
+ if (trimmed === '' && pathValue.startsWith('/')) {
+ return '/'
+ }
+ if (/^[A-Za-z]:$/.test(trimmed)) {
+ return `${trimmed}${pathSeparatorFor(pathValue)}`
+ }
+ return trimmed
+}
+
+export function joinCreateProjectPath(parentPath: string, childName: string): string {
+ const parent = trimTrailingSeparators(parentPath.trim())
+ const child = childName.trim().replace(/^[\\/]+/, '')
+ if (!parent || !child) {
+ return parent || child
+ }
+ const separator = pathSeparatorFor(parent)
+ if (parent === '/' || /^[A-Za-z]:[\\/]$/.test(parent)) {
+ return `${parent}${child}`
+ }
+ return `${parent}${separator}${child}`
+}
+
+export function getDefaultCreateProjectParent(homeDir: string): string {
+ const trimmedHomeDir = trimTrailingSeparators(homeDir.trim())
+ if (!trimmedHomeDir) {
+ return ''
+ }
+ return joinCreateProjectPath(joinCreateProjectPath(trimmedHomeDir, 'orca'), 'projects')
+}
+
+export function getCreateProjectDefaultParentAutoFill({
+ step,
+ createParent,
+ activeRuntimeEnvironmentId,
+ defaultParent,
+ createStepAutoFilled
+}: {
+ step: string
+ createParent: string
+ activeRuntimeEnvironmentId: string | null | undefined
+ defaultParent?: string
+ createStepAutoFilled: boolean
+}): { parent: string } | null {
+ if (step !== 'create' || createStepAutoFilled || createParent) {
+ return null
+ }
+ if (activeRuntimeEnvironmentId?.trim()) {
+ return null
+ }
+ const parent = defaultParent ?? ''
+ if (!parent) {
+ return null
+ }
+ return { parent }
+}
+
+export function formatCreateProjectParentSummary({
+ parent,
+ defaultParent,
+ runtimeEnvironmentId,
+ missingLocationLabel = 'location not selected',
+ missingServerLocationLabel = 'server folder not selected'
+}: {
+ parent: string
+ defaultParent: string
+ runtimeEnvironmentId?: string | null
+ missingLocationLabel?: string
+ missingServerLocationLabel?: string
+}): string {
+ const trimmedParent = parent.trim()
+ if (!trimmedParent) {
+ return runtimeEnvironmentId ? missingServerLocationLabel : missingLocationLabel
+ }
+ if (defaultParent && trimmedParent === defaultParent && !runtimeEnvironmentId) {
+ return '~/orca/projects'
+ }
+ return trimmedParent
+}
diff --git a/src/renderer/src/components/sidebar/useCreateProjectDefaults.test.ts b/src/renderer/src/components/sidebar/useCreateProjectDefaults.test.ts
new file mode 100644
index 00000000000..3508458daa4
--- /dev/null
+++ b/src/renderer/src/components/sidebar/useCreateProjectDefaults.test.ts
@@ -0,0 +1,260 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import type * as ReactModule from 'react'
+
+const mocks = vi.hoisted(() => ({
+ stateValues: [] as unknown[],
+ stateIndex: 0,
+ refValues: [] as { current: unknown }[],
+ refIndex: 0,
+ browseRuntimeServerDirectory: vi.fn(),
+ callRuntimeRpc: vi.fn(),
+ isGitAvailable: vi.fn(),
+ getDefaultCreateProjectParent: vi.fn()
+}))
+
+vi.mock('react', async (importOriginal) => {
+ const actual = await importOriginal
()
+ return {
+ ...actual,
+ useCallback: unknown>(fn: T) => fn,
+ useRef: (value: T) => {
+ const index = mocks.refIndex++
+ if (!(index in mocks.refValues)) {
+ mocks.refValues[index] = { current: value }
+ }
+ return mocks.refValues[index] as { current: T }
+ },
+ useEffect: (effect: () => void | (() => void)) => {
+ void effect()
+ },
+ useState: (initial: T) => {
+ const index = mocks.stateIndex++
+ if (!(index in mocks.stateValues)) {
+ mocks.stateValues[index] = initial
+ }
+ const setter = (value: T) => {
+ mocks.stateValues[index] = value
+ }
+ return [mocks.stateValues[index] as T, setter]
+ }
+ }
+})
+
+vi.mock('@/runtime/runtime-server-directory-browser', () => ({
+ browseRuntimeServerDirectory: mocks.browseRuntimeServerDirectory
+}))
+
+vi.mock('@/runtime/runtime-rpc-client', () => ({
+ callRuntimeRpc: mocks.callRuntimeRpc
+}))
+
+import { useCreateProjectDefaults } from './useCreateProjectDefaults'
+
+// State order inside the hook: [defaultParent, gitAvailability, runtimeParentStatus].
+const DEFAULT_PARENT_STATE = 0
+const GIT_AVAILABILITY_STATE = 1
+const RUNTIME_PARENT_STATUS_STATE = 2
+
+function flushAsync(): Promise {
+ return new Promise((resolve) => setTimeout(resolve, 0))
+}
+
+function useHarness(overrides: Partial[0]> = {}) {
+ mocks.stateIndex = 0
+ mocks.refIndex = 0
+ const setCreateParent = vi.fn()
+ const setCreateKind = vi.fn()
+ const result = useCreateProjectDefaults({
+ step: 'create',
+ activeRuntimeEnvironmentId: null,
+ createParent: '',
+ setCreateParent,
+ setCreateKind,
+ ...overrides
+ })
+ return { result, setCreateParent, setCreateKind }
+}
+
+describe('useCreateProjectDefaults', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ mocks.stateValues = []
+ mocks.stateIndex = 0
+ mocks.refValues = []
+ mocks.refIndex = 0
+ vi.stubGlobal('window', {
+ api: {
+ repos: {
+ isGitAvailable: mocks.isGitAvailable,
+ getDefaultCreateProjectParent: mocks.getDefaultCreateProjectParent
+ }
+ }
+ })
+ mocks.getDefaultCreateProjectParent.mockResolvedValue('/Users/alice/orca/projects')
+ })
+
+ it('auto-fills the local default parent and defaults to git when available', async () => {
+ mocks.isGitAvailable.mockResolvedValue(true)
+
+ const { setCreateParent, setCreateKind } = useHarness()
+ await flushAsync()
+
+ expect(setCreateParent).toHaveBeenCalledWith('/Users/alice/orca/projects')
+ expect(mocks.stateValues[DEFAULT_PARENT_STATE]).toBe('/Users/alice/orca/projects')
+ expect(mocks.stateValues[GIT_AVAILABILITY_STATE]).toBe('available')
+ expect(setCreateKind).toHaveBeenCalledWith('git')
+ expect(mocks.getDefaultCreateProjectParent).toHaveBeenCalled()
+ expect(mocks.callRuntimeRpc).not.toHaveBeenCalled()
+ })
+
+ it('auto-fills the local home default regardless of workspace directory settings', async () => {
+ mocks.isGitAvailable.mockResolvedValue(true)
+
+ const { setCreateParent } = useHarness()
+ await flushAsync()
+
+ expect(mocks.getDefaultCreateProjectParent).toHaveBeenCalled()
+ expect(setCreateParent).toHaveBeenCalledWith('/Users/alice/orca/projects')
+ expect(mocks.stateValues[DEFAULT_PARENT_STATE]).toBe('/Users/alice/orca/projects')
+ })
+
+ it('keeps the local default marker after the auto-filled parent rerenders the hook', async () => {
+ mocks.isGitAvailable.mockResolvedValue(true)
+
+ useHarness()
+ await flushAsync()
+ useHarness({ createParent: '/Users/alice/orca/projects' })
+
+ expect(mocks.stateValues[DEFAULT_PARENT_STATE]).toBe('/Users/alice/orca/projects')
+ })
+
+ it('defaults to folder with a visible fallback when Git is unavailable', async () => {
+ mocks.isGitAvailable.mockResolvedValue(false)
+
+ const { setCreateKind } = useHarness()
+ await flushAsync()
+
+ expect(mocks.stateValues[GIT_AVAILABILITY_STATE]).toBe('unavailable')
+ expect(setCreateKind).toHaveBeenCalledWith('folder')
+ })
+
+ it('reports unknown availability and keeps the kind when the Git probe fails', async () => {
+ mocks.isGitAvailable.mockRejectedValue(new Error('probe failed'))
+
+ const { setCreateKind } = useHarness()
+ await flushAsync()
+
+ expect(mocks.stateValues[GIT_AVAILABILITY_STATE]).toBe('unknown')
+ expect(setCreateKind).not.toHaveBeenCalled()
+ })
+
+ it('does not overwrite a parent the user already chose', async () => {
+ mocks.isGitAvailable.mockResolvedValue(true)
+
+ const { setCreateParent } = useHarness({ createParent: '/tmp/custom' })
+ await flushAsync()
+
+ expect(setCreateParent).not.toHaveBeenCalled()
+ })
+
+ it('resolves the runtime default parent from the host home directory', async () => {
+ mocks.browseRuntimeServerDirectory.mockResolvedValue({ resolvedPath: '/home/alice' })
+ mocks.callRuntimeRpc.mockResolvedValue({ available: true })
+
+ const { setCreateParent, setCreateKind } = useHarness({ activeRuntimeEnvironmentId: 'env-1' })
+ await flushAsync()
+
+ expect(mocks.browseRuntimeServerDirectory).toHaveBeenCalledWith('env-1', '~')
+ expect(setCreateParent).toHaveBeenCalledWith('/home/alice/orca/projects')
+ expect(mocks.stateValues[DEFAULT_PARENT_STATE]).toBe('/home/alice/orca/projects')
+ expect(mocks.stateValues[RUNTIME_PARENT_STATUS_STATE]).toBe('idle')
+ // Why: runtime Git availability must be probed on the host, not the client.
+ expect(mocks.callRuntimeRpc).toHaveBeenCalledWith(
+ { kind: 'environment', environmentId: 'env-1' },
+ 'repo.gitAvailable',
+ undefined,
+ { timeoutMs: 3000 }
+ )
+ expect(mocks.isGitAvailable).not.toHaveBeenCalled()
+ expect(setCreateKind).toHaveBeenCalledWith('git')
+ })
+
+ it('replaces an untouched local default when switching to a runtime target', async () => {
+ mocks.isGitAvailable.mockResolvedValue(true)
+ mocks.browseRuntimeServerDirectory.mockResolvedValue({ resolvedPath: '/home/alice' })
+ mocks.callRuntimeRpc.mockResolvedValue({ available: true })
+
+ const local = useHarness()
+ await flushAsync()
+ expect(local.setCreateParent).toHaveBeenCalledWith('/Users/alice/orca/projects')
+
+ const runtime = useHarness({
+ activeRuntimeEnvironmentId: 'env-1',
+ createParent: '/Users/alice/orca/projects'
+ })
+
+ expect(runtime.result.createParentDefaultPending).toBe(true)
+ expect(runtime.setCreateParent).toHaveBeenCalledWith('')
+ expect(mocks.stateValues[RUNTIME_PARENT_STATUS_STATE]).toBe('checking')
+ expect(mocks.browseRuntimeServerDirectory).not.toHaveBeenCalled()
+
+ const resolvedRuntime = useHarness({
+ activeRuntimeEnvironmentId: 'env-1',
+ createParent: ''
+ })
+ await flushAsync()
+
+ expect(mocks.browseRuntimeServerDirectory).toHaveBeenCalledWith('env-1', '~')
+ expect(resolvedRuntime.setCreateParent).toHaveBeenCalledWith('/home/alice/orca/projects')
+ expect(mocks.stateValues[DEFAULT_PARENT_STATE]).toBe('/home/alice/orca/projects')
+ expect(resolvedRuntime.result.createParentDefaultPending).toBe(false)
+ })
+
+ it('does not replace a touched parent when switching to a runtime target', async () => {
+ mocks.isGitAvailable.mockResolvedValue(true)
+ mocks.browseRuntimeServerDirectory.mockResolvedValue({ resolvedPath: '/home/alice' })
+ mocks.callRuntimeRpc.mockResolvedValue({ available: true })
+
+ const local = useHarness({ createParent: '/Users/alice/orca/projects' })
+ local.result.markCreateParentTouched('/Users/alice/orca/projects/pr5115-target-switch')
+
+ const runtime = useHarness({
+ activeRuntimeEnvironmentId: 'env-1',
+ createParent: '/Users/alice/orca/projects/pr5115-target-switch'
+ })
+ await flushAsync()
+
+ expect(runtime.result.createParentDefaultPending).toBe(true)
+ expect(mocks.browseRuntimeServerDirectory).not.toHaveBeenCalled()
+ expect(runtime.setCreateParent).not.toHaveBeenCalled()
+
+ runtime.result.markCreateParentTouched('/home/alice/projects')
+ const runtimeEdited = useHarness({
+ activeRuntimeEnvironmentId: 'env-1',
+ createParent: '/home/alice/projects'
+ })
+
+ expect(runtimeEdited.result.createParentDefaultPending).toBe(false)
+ })
+
+ it('marks the runtime parent lookup failed without filling a parent', async () => {
+ mocks.browseRuntimeServerDirectory.mockRejectedValue(new Error('disconnected'))
+ mocks.callRuntimeRpc.mockResolvedValue({ available: true })
+
+ const { setCreateParent } = useHarness({ activeRuntimeEnvironmentId: 'env-1' })
+ await flushAsync()
+
+ expect(mocks.stateValues[RUNTIME_PARENT_STATUS_STATE]).toBe('failed')
+ expect(setCreateParent).not.toHaveBeenCalled()
+ })
+
+ it('does nothing outside the create step', async () => {
+ const { setCreateParent, setCreateKind } = useHarness({ step: 'add' })
+ await flushAsync()
+
+ expect(setCreateParent).not.toHaveBeenCalled()
+ expect(setCreateKind).not.toHaveBeenCalled()
+ expect(mocks.isGitAvailable).not.toHaveBeenCalled()
+ expect(mocks.browseRuntimeServerDirectory).not.toHaveBeenCalled()
+ })
+})
diff --git a/src/renderer/src/components/sidebar/useCreateProjectDefaults.ts b/src/renderer/src/components/sidebar/useCreateProjectDefaults.ts
new file mode 100644
index 00000000000..9c94cba1629
--- /dev/null
+++ b/src/renderer/src/components/sidebar/useCreateProjectDefaults.ts
@@ -0,0 +1,307 @@
+// Default-driven create-project state for AddRepoDialog: resolves the default
+// parent (local/runtime host home) and probes Git
+// availability, guarding against stale async results when the target changes.
+import { useCallback, useEffect, useRef, useState } from 'react'
+import { browseRuntimeServerDirectory } from '@/runtime/runtime-server-directory-browser'
+import { callRuntimeRpc } from '@/runtime/runtime-rpc-client'
+import type { AddRepoDialogStep } from './add-repo-dialog-types'
+import {
+ getDefaultCreateProjectParent,
+ type GitAvailability,
+ type RepoKind
+} from './create-project-defaults'
+
+const LOCAL_GIT_AVAILABILITY_TIMEOUT_MS = 1500
+const RUNTIME_GIT_AVAILABILITY_TIMEOUT_MS = 3000
+
+export type CreateRuntimeParentStatus = 'idle' | 'checking' | 'failed'
+
+type AutoFilledCreateParent = {
+ parent: string
+ runtimeEnvironmentId: string | null
+}
+
+type CreateParentProvenance = {
+ parent: string
+ runtimeEnvironmentId: string | null
+}
+
+function withTimeout(promise: Promise, timeoutMs: number): Promise {
+ let timeout: ReturnType | null = null
+ return new Promise((resolve, reject) => {
+ timeout = setTimeout(() => reject(new Error('Timed out')), timeoutMs)
+ promise.then(
+ (value) => {
+ if (timeout) {
+ clearTimeout(timeout)
+ }
+ resolve(value)
+ },
+ (error) => {
+ if (timeout) {
+ clearTimeout(timeout)
+ }
+ reject(error)
+ }
+ )
+ })
+}
+
+export function useCreateProjectDefaults({
+ step,
+ activeRuntimeEnvironmentId,
+ createParent,
+ setCreateParent,
+ setCreateKind
+}: {
+ step: AddRepoDialogStep
+ activeRuntimeEnvironmentId: string | null | undefined
+ createParent: string
+ setCreateParent: (value: string) => void
+ setCreateKind: (kind: RepoKind) => void
+}): {
+ createDefaultParent: string
+ createGitAvailability: GitAvailability
+ createRuntimeParentStatus: CreateRuntimeParentStatus
+ createParentDefaultPending: boolean
+ resetCreateDefaultState: () => void
+ markCreateParentTouched: (value?: string) => void
+ markCreateKindTouched: () => void
+} {
+ const [createDefaultParent, setCreateDefaultParent] = useState('')
+ const [createGitAvailability, setCreateGitAvailability] = useState('unknown')
+ const [createRuntimeParentStatus, setCreateRuntimeParentStatus] =
+ useState('idle')
+ const createStepAutoFilledRef = useRef(false)
+ const autoFilledCreateParentRef = useRef(null)
+ const createParentProvenanceRef = useRef(null)
+ const createParentTouchedRef = useRef(false)
+ const createKindTouchedRef = useRef(false)
+ const createParentDefaultGenRef = useRef(0)
+ const createGitProbeGenRef = useRef(0)
+ const activeCreateParentRuntimeEnvironmentId = activeRuntimeEnvironmentId?.trim() || null
+
+ const canReplaceCreateParentDefault = useCallback((parent: string): boolean => {
+ if (createParentTouchedRef.current) {
+ return false
+ }
+ const trimmedParent = parent.trim()
+ return !trimmedParent || autoFilledCreateParentRef.current?.parent === trimmedParent
+ }, [])
+
+ const resetCreateDefaultState = useCallback(() => {
+ createParentDefaultGenRef.current++
+ createGitProbeGenRef.current++
+ createStepAutoFilledRef.current = false
+ autoFilledCreateParentRef.current = null
+ createParentProvenanceRef.current = null
+ createParentTouchedRef.current = false
+ createKindTouchedRef.current = false
+ setCreateDefaultParent('')
+ setCreateGitAvailability('unknown')
+ setCreateRuntimeParentStatus('idle')
+ }, [])
+
+ // Why: a default must never clobber a parent or kind the user picked themselves.
+ const markCreateParentTouched = useCallback(
+ (value?: string) => {
+ autoFilledCreateParentRef.current = null
+ createParentProvenanceRef.current = {
+ parent: (value ?? createParent).trim(),
+ runtimeEnvironmentId: activeCreateParentRuntimeEnvironmentId
+ }
+ createParentTouchedRef.current = true
+ },
+ [activeCreateParentRuntimeEnvironmentId, createParent]
+ )
+ const markCreateKindTouched = useCallback(() => {
+ createKindTouchedRef.current = true
+ }, [])
+
+ const createParentDefaultPending =
+ step === 'create' &&
+ !createParentTouchedRef.current &&
+ Boolean(createParent.trim()) &&
+ autoFilledCreateParentRef.current?.parent === createParent.trim() &&
+ autoFilledCreateParentRef.current.runtimeEnvironmentId !==
+ activeCreateParentRuntimeEnvironmentId
+ const createParentTargetPending =
+ step === 'create' &&
+ Boolean(createParent.trim()) &&
+ createParentProvenanceRef.current?.parent === createParent.trim() &&
+ createParentProvenanceRef.current.runtimeEnvironmentId !==
+ activeCreateParentRuntimeEnvironmentId
+ const createParentPending = createParentDefaultPending || createParentTargetPending
+
+ useEffect(() => {
+ if (step !== 'create') {
+ return
+ }
+ if (activeCreateParentRuntimeEnvironmentId) {
+ return
+ }
+ // Why: invalidate any in-flight runtime parent probe once local mode owns the default.
+ const gen = ++createParentDefaultGenRef.current
+ if (!canReplaceCreateParentDefault(createParent)) {
+ return
+ }
+ if (
+ createParent.trim() &&
+ autoFilledCreateParentRef.current?.runtimeEnvironmentId !== null &&
+ autoFilledCreateParentRef.current?.parent === createParent.trim()
+ ) {
+ setCreateDefaultParent('')
+ setCreateParent('')
+ return
+ }
+ if (
+ autoFilledCreateParentRef.current?.runtimeEnvironmentId === null &&
+ autoFilledCreateParentRef.current.parent === createParent.trim()
+ ) {
+ return
+ }
+ setCreateDefaultParent('')
+ void window.api.repos
+ .getDefaultCreateProjectParent()
+ .then((parent) => {
+ if (
+ gen !== createParentDefaultGenRef.current ||
+ !canReplaceCreateParentDefault(createParent) ||
+ !parent
+ ) {
+ return
+ }
+ setCreateDefaultParent(parent)
+ createStepAutoFilledRef.current = true
+ autoFilledCreateParentRef.current = { parent, runtimeEnvironmentId: null }
+ createParentProvenanceRef.current = { parent, runtimeEnvironmentId: null }
+ setCreateParent(parent)
+ })
+ .catch(() => {
+ // Keep the field empty if the local host cannot provide a submit-ready default.
+ })
+ }, [
+ activeRuntimeEnvironmentId,
+ activeCreateParentRuntimeEnvironmentId,
+ canReplaceCreateParentDefault,
+ createParent,
+ setCreateParent,
+ step
+ ])
+
+ useEffect(() => {
+ if (step !== 'create') {
+ return
+ }
+ const runtimeEnvironmentId = activeCreateParentRuntimeEnvironmentId
+ if (!runtimeEnvironmentId) {
+ setCreateRuntimeParentStatus('idle')
+ return
+ }
+ if (!canReplaceCreateParentDefault(createParent)) {
+ setCreateRuntimeParentStatus('idle')
+ return
+ }
+ if (
+ createParent.trim() &&
+ autoFilledCreateParentRef.current?.runtimeEnvironmentId !== runtimeEnvironmentId &&
+ autoFilledCreateParentRef.current?.parent === createParent.trim()
+ ) {
+ setCreateDefaultParent('')
+ setCreateRuntimeParentStatus('checking')
+ setCreateParent('')
+ return
+ }
+ if (
+ autoFilledCreateParentRef.current?.runtimeEnvironmentId === runtimeEnvironmentId &&
+ autoFilledCreateParentRef.current.parent === createParent.trim()
+ ) {
+ setCreateRuntimeParentStatus('idle')
+ return
+ }
+ setCreateDefaultParent('')
+
+ const gen = ++createParentDefaultGenRef.current
+ setCreateRuntimeParentStatus('checking')
+ void withTimeout(
+ browseRuntimeServerDirectory(runtimeEnvironmentId, '~'),
+ RUNTIME_GIT_AVAILABILITY_TIMEOUT_MS
+ )
+ .then((result) => {
+ if (
+ gen !== createParentDefaultGenRef.current ||
+ !canReplaceCreateParentDefault(createParent)
+ ) {
+ return
+ }
+ const parent = getDefaultCreateProjectParent(result.resolvedPath)
+ createStepAutoFilledRef.current = true
+ autoFilledCreateParentRef.current = { parent, runtimeEnvironmentId }
+ createParentProvenanceRef.current = { parent, runtimeEnvironmentId }
+ setCreateDefaultParent(parent)
+ setCreateParent(parent)
+ setCreateRuntimeParentStatus('idle')
+ })
+ .catch(() => {
+ if (gen !== createParentDefaultGenRef.current) {
+ return
+ }
+ setCreateRuntimeParentStatus('failed')
+ })
+ }, [
+ activeRuntimeEnvironmentId,
+ activeCreateParentRuntimeEnvironmentId,
+ canReplaceCreateParentDefault,
+ createParent,
+ setCreateParent,
+ step
+ ])
+
+ useEffect(() => {
+ if (step !== 'create') {
+ return
+ }
+ const runtimeEnvironmentId = activeRuntimeEnvironmentId?.trim()
+ const gen = ++createGitProbeGenRef.current
+ setCreateGitAvailability('checking')
+ const probe = runtimeEnvironmentId
+ ? callRuntimeRpc<{ available: boolean }>(
+ { kind: 'environment', environmentId: runtimeEnvironmentId },
+ 'repo.gitAvailable',
+ undefined,
+ { timeoutMs: RUNTIME_GIT_AVAILABILITY_TIMEOUT_MS }
+ ).then((result) => result.available)
+ : window.api.repos.isGitAvailable()
+ const timeoutMs = runtimeEnvironmentId
+ ? RUNTIME_GIT_AVAILABILITY_TIMEOUT_MS
+ : LOCAL_GIT_AVAILABILITY_TIMEOUT_MS
+
+ void withTimeout(probe, timeoutMs)
+ .then((available) => {
+ if (gen !== createGitProbeGenRef.current) {
+ return
+ }
+ setCreateGitAvailability(available ? 'available' : 'unavailable')
+ if (createKindTouchedRef.current) {
+ return
+ }
+ setCreateKind(available ? 'git' : 'folder')
+ })
+ .catch(() => {
+ if (gen !== createGitProbeGenRef.current) {
+ return
+ }
+ setCreateGitAvailability('unknown')
+ })
+ }, [activeRuntimeEnvironmentId, setCreateKind, step])
+
+ return {
+ createDefaultParent,
+ createGitAvailability,
+ createRuntimeParentStatus,
+ createParentDefaultPending: createParentPending,
+ resetCreateDefaultState,
+ markCreateParentTouched,
+ markCreateKindTouched
+ }
+}
diff --git a/src/renderer/src/components/sidebar/AddRepoCreateStep.default-checkout.test.ts b/src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts
similarity index 80%
rename from src/renderer/src/components/sidebar/AddRepoCreateStep.default-checkout.test.ts
rename to src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts
index 8dd45bbff85..4afc7041c91 100644
--- a/src/renderer/src/components/sidebar/AddRepoCreateStep.default-checkout.test.ts
+++ b/src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts
@@ -92,6 +92,7 @@ describe('useCreateRepo default-checkout handoff', () => {
mocks.stateValues = ['created', '/projects', 'git', null, false]
mocks.storeState.repos = []
mocks.storeState.worktreesByRepo = {}
+ mocks.storeState.settings.activeRuntimeEnvironmentId = null
vi.stubGlobal('window', {
api: {
repos: {
@@ -106,7 +107,7 @@ describe('useCreateRepo default-checkout handoff', () => {
const repo = makeRepo()
mocks.createRepo.mockResolvedValue({ repo })
mocks.fetchWorktrees.mockResolvedValue(true)
- const { useCreateRepo } = await import('./AddRepoCreateStep')
+ const { useCreateRepo } = await import('./useCreateRepo')
const result = useCreateRepo(mocks.fetchWorktrees, vi.fn(), mocks.onGitRepoReady)
await result.handleCreate()
@@ -122,11 +123,33 @@ describe('useCreateRepo default-checkout handoff', () => {
expect(mocks.onGitRepoReady).toHaveBeenCalledWith(repo.id)
})
+ it('returns the selected parent directory after the local picker applies it', async () => {
+ const pickedDir = '/Users/alice/custom-projects'
+ vi.mocked(window.api.repos.pickDirectory).mockResolvedValue(pickedDir)
+ const { useCreateRepo } = await import('./useCreateRepo')
+
+ const result = useCreateRepo(mocks.fetchWorktrees, vi.fn(), mocks.onGitRepoReady)
+ await expect(result.handlePickParent()).resolves.toBe(pickedDir)
+
+ expect(mocks.stateSetters[1]).toHaveBeenCalledWith(pickedDir)
+ })
+
+ it('does not return a parent path when the runtime target blocks the local picker', async () => {
+ mocks.storeState.settings.activeRuntimeEnvironmentId = 'env-1'
+ const { useCreateRepo } = await import('./useCreateRepo')
+
+ const result = useCreateRepo(mocks.fetchWorktrees, vi.fn(), mocks.onGitRepoReady)
+ await expect(result.handlePickParent()).resolves.toBeNull()
+
+ expect(window.api.repos.pickDirectory).not.toHaveBeenCalled()
+ expect(mocks.stateSetters[1]).not.toHaveBeenCalled()
+ })
+
it('continues to completion when refresh is not authoritative after create', async () => {
const repo = makeRepo()
mocks.createRepo.mockResolvedValue({ repo })
mocks.fetchWorktrees.mockResolvedValue(false)
- const { useCreateRepo } = await import('./AddRepoCreateStep')
+ const { useCreateRepo } = await import('./useCreateRepo')
const result = useCreateRepo(mocks.fetchWorktrees, vi.fn(), mocks.onGitRepoReady)
await result.handleCreate()
@@ -150,7 +173,7 @@ describe('useCreateRepo default-checkout handoff', () => {
mocks.storeState.worktreesByRepo = { [repoId]: [worktree] }
return true
})
- const { useCreateRepo } = await import('./AddRepoCreateStep')
+ const { useCreateRepo } = await import('./useCreateRepo')
const result = useCreateRepo(mocks.fetchWorktrees, closeModal, mocks.onGitRepoReady)
await result.handleCreate()
diff --git a/src/renderer/src/components/sidebar/useCreateRepo.ts b/src/renderer/src/components/sidebar/useCreateRepo.ts
new file mode 100644
index 00000000000..bb12da03eb7
--- /dev/null
+++ b/src/renderer/src/components/sidebar/useCreateRepo.ts
@@ -0,0 +1,189 @@
+// Create-project flow hook for AddRepoDialog (orca#763), split from
+// AddRepoCreateStep so the create-state machine stays scoped and testable.
+import { useCallback, useRef, useState } from 'react'
+import { toast } from 'sonner'
+import { useAppStore } from '@/store'
+import { useMountedRef } from '@/hooks/useMountedRef'
+import { activateAndRevealWorktree } from '@/lib/worktree-activation'
+import { markOnboardingProjectAdded } from '@/lib/onboarding-project-checklist'
+import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
+import { isGitRepoKind } from '../../../../shared/repo-kind'
+import type { Repo } from '../../../../shared/types'
+import { translate } from '@/i18n/i18n'
+import type { RepoKind } from './create-project-defaults'
+
+export function useCreateRepo(
+ fetchWorktrees: (
+ repoId: string,
+ options?: { requireAuthoritative?: boolean }
+ ) => Promise,
+ closeModal: () => void,
+ onGitRepoReady?: (repoId: string) => void | Promise
+) {
+ const [createName, setCreateName] = useState('')
+ const [createParent, setCreateParent] = useState('')
+ const [createKind, setCreateKind] = useState('git')
+ const [createError, setCreateError] = useState(null)
+ const [isCreating, setIsCreating] = useState(false)
+ const mountedRef = useMountedRef()
+
+ // Why: monotonic ID so stale create callbacks can detect they were superseded
+ // when the user clicks Back or closes the dialog mid-create. Mirrors the
+ // cloneGenRef pattern in AddRepoDialog.
+ const createGenRef = useRef(0)
+
+ const resetCreateState = useCallback(() => {
+ createGenRef.current++
+ setCreateName('')
+ setCreateParent('')
+ setCreateKind('git')
+ setCreateError(null)
+ setIsCreating(false)
+ }, [])
+
+ const handlePickParent = useCallback(async (): Promise => {
+ if (useAppStore.getState().settings?.activeRuntimeEnvironmentId?.trim()) {
+ // Why: the native folder picker returns a client-local path. Runtime
+ // project creation needs an explicit server parent path.
+ toast.error(
+ translate(
+ 'auto.components.sidebar.AddRepoCreateStep.875dda0995',
+ 'Enter a server parent path.'
+ )
+ )
+ return null
+ }
+ const gen = createGenRef.current
+ const dir = await window.api.repos.pickDirectory()
+ if (dir && gen === createGenRef.current && mountedRef.current) {
+ setCreateParent(dir)
+ setCreateError(null)
+ return dir
+ }
+ return null
+ }, [mountedRef])
+
+ const handleCreate = useCallback(async () => {
+ const name = createName.trim()
+ const parentPath = createParent.trim()
+ if (!name || !parentPath) {
+ return
+ }
+ const gen = ++createGenRef.current
+ setIsCreating(true)
+ setCreateError(null)
+ try {
+ const target = getActiveRuntimeTarget(useAppStore.getState().settings)
+ const result =
+ target.kind === 'environment'
+ ? await callRuntimeRpc<{ repo: Repo } | { error: string }>(
+ target,
+ 'repo.create',
+ {
+ parentPath,
+ name,
+ kind: createKind
+ },
+ { timeoutMs: 60_000 }
+ )
+ : await window.api.repos.create({
+ parentPath,
+ name,
+ kind: createKind
+ })
+ // Why: if the user closed the dialog or clicked Back mid-create,
+ // createGenRef was bumped by resetCreateState. Ignore stale results.
+ if (gen !== createGenRef.current || !mountedRef.current) {
+ return
+ }
+ if ('error' in result) {
+ setCreateError(result.error)
+ return
+ }
+ const repo = result.repo
+ // Upsert into the store before the repos:changed event round-trips,
+ // so the next step can find the repo immediately.
+ const state = useAppStore.getState()
+ const existingIdx = state.repos.findIndex((r) => r.id === repo.id)
+ // Why: the IPC handler dedupes by path (see repos:create) and returns
+ // the existing repo unchanged. If its ID is already in our store, the
+ // handler took the dedup path — no new project was created, so don't
+ // claim one was.
+ const wasDeduped = existingIdx !== -1
+ if (existingIdx === -1) {
+ useAppStore.setState({ repos: [...state.repos, repo] })
+ } else {
+ const updated = [...state.repos]
+ updated[existingIdx] = repo
+ useAppStore.setState({ repos: updated })
+ }
+ if (wasDeduped) {
+ toast.info(
+ translate(
+ 'auto.components.sidebar.AddRepoCreateStep.2c12db1511',
+ 'Project already added'
+ ),
+ {
+ description: repo.displayName
+ }
+ )
+ } else {
+ toast.success(
+ translate('auto.components.sidebar.AddRepoCreateStep.5e97f0c4b9', 'Project created'),
+ {
+ description: repo.displayName
+ }
+ )
+ }
+ if (isGitRepoKind(repo)) {
+ // Why: Git repos use the shared default-checkout completion path.
+ // Why: if refresh is temporarily non-authoritative, the shared opener
+ // still reveals the project so the user is not left in a completed add flow.
+ await fetchWorktrees(repo.id, { requireAuthoritative: true })
+ if (gen !== createGenRef.current || !mountedRef.current) {
+ return
+ }
+ await onGitRepoReady?.(repo.id)
+ } else {
+ // Why: folder repos skip the Git default-checkout handoff, so activate the synthetic
+ // root workspace before closing. Matches addNonGitFolder's behavior.
+ await fetchWorktrees(repo.id)
+ if (gen !== createGenRef.current || !mountedRef.current) {
+ return
+ }
+ const folderWorktree = useAppStore.getState().worktreesByRepo[repo.id]?.[0]
+ if (folderWorktree) {
+ activateAndRevealWorktree(folderWorktree.id, { sidebarRevealBehavior: 'auto' })
+ }
+ await markOnboardingProjectAdded('addedFolder')
+ closeModal()
+ }
+ } catch (err) {
+ if (gen !== createGenRef.current || !mountedRef.current) {
+ return
+ }
+ setCreateError(err instanceof Error ? err.message : String(err))
+ } finally {
+ // Why: only clear the loading state if this invocation is still current;
+ // a superseded create must not flip the flag back off for a new flow.
+ if (gen === createGenRef.current && mountedRef.current) {
+ setIsCreating(false)
+ }
+ }
+ }, [createName, createParent, createKind, fetchWorktrees, mountedRef, closeModal, onGitRepoReady])
+
+ return {
+ createName,
+ createParent,
+ createKind,
+ createError,
+ isCreating,
+ setCreateName,
+ setCreateParent,
+ setCreateKind,
+ setCreateError,
+ resetCreateState,
+ handlePickParent,
+ handleCreate
+ }
+}
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index dcdca638d64..a7597e98752 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -3024,8 +3024,14 @@
"038729c107": "Folder",
"11fd2a7db8": "Git repository",
"180e9b5e48": "Project kind",
- "d877ece0d6": "Create a Git repository or a plain folder and open it in Orca.",
- "db9be12229": "Start a new project",
+ "c7b9f94456": "Create a new project",
+ "b100311784": "Name it and Orca will create a real project with sensible defaults.",
+ "685b5eefe1": "{{kind}} in {{parent}}",
+ "2a762f3b19": "Checking Git on this host...",
+ "fe1e616c5b": "Git isn't installed, so a plain folder is the default.",
+ "c234df77f7": "Choose or enter a server parent folder before creating.",
+ "3a13f6e88b": "location not selected",
+ "6ed14c0281": "server folder not selected",
"5e97f0c4b9": "Project created",
"2c12db1511": "Project already added",
"875dda0995": "Enter a server parent path.",
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
index 429750daced..cd442f403e2 100644
--- a/src/renderer/src/i18n/locales/es.json
+++ b/src/renderer/src/i18n/locales/es.json
@@ -3022,15 +3022,21 @@
"0ae45b8238": "mi-proyecto",
"a8149a3a5a": "Nombre",
"038729c107": "Carpeta",
- "11fd2a7db8": "repositorio git",
+ "11fd2a7db8": "Repositorio Git",
"180e9b5e48": "Tipo de proyecto",
- "d877ece0d6": "Cree un repositorio Git o una carpeta simple y ábralo en Orca.",
- "db9be12229": "Iniciar un nuevo proyecto",
"5e97f0c4b9": "Proyecto creado",
"2c12db1511": "Proyecto ya agregado",
"875dda0995": "Introduzca una ruta principal del servidor.",
"45b7c26034": "Crear proyecto",
- "85085d74d2": "Creando…"
+ "85085d74d2": "Creando…",
+ "c7b9f94456": "Crear un proyecto nuevo",
+ "b100311784": "Ponle un nombre y Orca creará un proyecto real con valores predeterminados sensatos.",
+ "685b5eefe1": "{{kind}} en {{parent}}",
+ "2a762f3b19": "Comprobando Git en este host...",
+ "fe1e616c5b": "Git no está instalado, así que una carpeta simple será el valor predeterminado.",
+ "c234df77f7": "Elige o introduce una carpeta principal del servidor antes de crear.",
+ "3a13f6e88b": "ubicación no seleccionada",
+ "6ed14c0281": "carpeta del servidor no seleccionada"
},
"AddRepoNestedImportStep": {
"496f68cf8c": "Escaneo de repositorios. Haga clic para detener.",
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
index 2ba6e38c06d..8dfe8748268 100644
--- a/src/renderer/src/i18n/locales/ja.json
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -3005,13 +3005,19 @@
"038729c107": "フォルダ",
"11fd2a7db8": "Gitリポジトリ",
"180e9b5e48": "プロジェクトの種類",
- "d877ece0d6": "Git リポジトリまたはプレーン フォルダーを作成し、Orca で開きます。",
- "db9be12229": "新規プロジェクトを開始する",
"5e97f0c4b9": "プロジェクトが作成されました",
"2c12db1511": "プロジェクトはすでに追加されています",
"875dda0995": "サーバーの親パスを入力します。",
"45b7c26034": "プロジェクトの作成",
- "85085d74d2": "作成…"
+ "85085d74d2": "作成中…",
+ "c7b9f94456": "新しいプロジェクトを作成",
+ "b100311784": "名前を付けると、Orca が適切な既定値で実際のプロジェクトを作成します。",
+ "685b5eefe1": "{{parent}} の {{kind}}",
+ "2a762f3b19": "このホストで Git を確認中...",
+ "fe1e616c5b": "Git がインストールされていないため、通常のフォルダが既定になります。",
+ "c234df77f7": "作成する前に、サーバーの親フォルダを選択または入力してください。",
+ "3a13f6e88b": "場所が選択されていません",
+ "6ed14c0281": "サーバーフォルダが選択されていません"
},
"AddRepoNestedImportStep": {
"496f68cf8c": "リポジトリをスキャンしています。クリックして停止します。",
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 243637d8485..6aae0819947 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -3002,16 +3002,22 @@
"AddRepoCreateStep": {
"0ae45b8238": "내 프로젝트",
"a8149a3a5a": "이름",
- "038729c107": "접는 사람",
- "11fd2a7db8": "힘내 저장소",
+ "038729c107": "폴더",
+ "11fd2a7db8": "Git 저장소",
"180e9b5e48": "프로젝트 종류",
- "d877ece0d6": "Git 저장소 또는 일반 폴더를 생성하고 Orca에서 엽니다.",
- "db9be12229": "새 프로젝트 시작",
"5e97f0c4b9": "프로젝트가 생성되었습니다.",
"2c12db1511": "프로젝트가 이미 추가되었습니다.",
"875dda0995": "서버 상위 경로를 입력하세요.",
"45b7c26034": "프로젝트 생성",
- "85085d74d2": "만드는 중…"
+ "85085d74d2": "만드는 중…",
+ "c7b9f94456": "새 프로젝트 만들기",
+ "b100311784": "이름을 지정하면 Orca가 적절한 기본값으로 실제 프로젝트를 만듭니다.",
+ "685b5eefe1": "{{parent}}의 {{kind}}",
+ "2a762f3b19": "이 호스트에서 Git 확인 중...",
+ "fe1e616c5b": "Git이 설치되어 있지 않아 일반 폴더가 기본값입니다.",
+ "c234df77f7": "만들기 전에 서버 상위 폴더를 선택하거나 입력하세요.",
+ "3a13f6e88b": "위치가 선택되지 않음",
+ "6ed14c0281": "서버 폴더가 선택되지 않음"
},
"AddRepoNestedImportStep": {
"496f68cf8c": "저장소를 스캔하는 중입니다. 중지하려면 클릭하세요.",
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index cc3be1d6294..f397b380599 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -3001,17 +3001,23 @@
},
"AddRepoCreateStep": {
"0ae45b8238": "我的项目",
- "a8149a3a5a": "姓名",
+ "a8149a3a5a": "名称",
"038729c107": "文件夹",
"11fd2a7db8": "Git 存储库",
- "180e9b5e48": "项目种类",
- "d877ece0d6": "创建 Git 存储库或普通文件夹并在 Orca 中打开它。",
- "db9be12229": "开始一个新项目",
+ "180e9b5e48": "项目类型",
"5e97f0c4b9": "项目已创建",
"2c12db1511": "项目已添加",
"875dda0995": "输入服务器父路径。",
"45b7c26034": "创建项目",
- "85085d74d2": "创建中…"
+ "85085d74d2": "创建中…",
+ "c7b9f94456": "创建新项目",
+ "b100311784": "为它命名,Orca 会使用合理的默认设置创建一个真实项目。",
+ "685b5eefe1": "{{parent}} 中的 {{kind}}",
+ "2a762f3b19": "正在检查此主机上的 Git...",
+ "fe1e616c5b": "未安装 Git,因此默认创建普通文件夹。",
+ "c234df77f7": "创建前请选择或输入服务器父文件夹。",
+ "3a13f6e88b": "未选择位置",
+ "6ed14c0281": "未选择服务器文件夹"
},
"AddRepoNestedImportStep": {
"496f68cf8c": "扫描存储库。单击停止。",
diff --git a/src/renderer/src/web/web-preload-api.test.ts b/src/renderer/src/web/web-preload-api.test.ts
index b060df6b51b..340dd3147b9 100644
--- a/src/renderer/src/web/web-preload-api.test.ts
+++ b/src/renderer/src/web/web-preload-api.test.ts
@@ -997,6 +997,53 @@ describe('web UI preload API', () => {
})
})
+describe('web repos preload API', () => {
+ beforeEach(() => {
+ vi.resetModules()
+ })
+
+ afterEach(() => {
+ vi.unstubAllGlobals()
+ vi.doUnmock('./web-runtime-client')
+ })
+
+ it.each([
+ ['/home/alice', '/home/alice/orca/projects'],
+ ['/', '/orca/projects'],
+ ['C:\\', 'C:\\orca\\projects']
+ ])(
+ 'resolves the default create-project parent from runtime host home %s',
+ async (resolvedPath, expectedParent) => {
+ const runtimeCalls: { method: string; params: unknown }[] = []
+ vi.doMock('./web-runtime-client', () => ({
+ WebRuntimeClient: class {
+ call(method: string, params?: unknown): Promise> {
+ runtimeCalls.push({ method, params })
+ return Promise.resolve({
+ id: method,
+ ok: true,
+ result: { resolvedPath, entries: [] },
+ _meta: { runtimeId: 'runtime-1' }
+ })
+ }
+
+ close(): void {}
+ }
+ }))
+
+ const globals = installBrowserGlobals('Linux')
+ writeStoredRuntimeEnvironment(globals.storage)
+ const { installWebPreloadApi } = await import('./web-preload-api')
+ installWebPreloadApi()
+
+ await expect(globals.window.api.repos.getDefaultCreateProjectParent()).resolves.toBe(
+ expectedParent
+ )
+ expect(runtimeCalls).toEqual([{ method: 'files.browseServerDir', params: { path: '~' } }])
+ }
+ )
+})
+
describe('web worktree preload API', () => {
beforeEach(() => {
vi.resetModules()
diff --git a/src/renderer/src/web/web-preload-api.ts b/src/renderer/src/web/web-preload-api.ts
index 099e95d39b6..8c979721c22 100644
--- a/src/renderer/src/web/web-preload-api.ts
+++ b/src/renderer/src/web/web-preload-api.ts
@@ -77,6 +77,7 @@ import {
} from '../../../shared/feature-interactions'
import { normalizeContextualTourIds, type ContextualTourId } from '../../../shared/contextual-tours'
import { translate } from '@/i18n/i18n'
+import { getDefaultCreateProjectParent } from '@/components/sidebar/create-project-defaults'
const SETTINGS_STORAGE_KEY = 'orca.web.settings.v1'
const UI_STORAGE_KEY = 'orca.web.ui.v1'
@@ -1014,6 +1015,14 @@ function createReposApi(): NonNullable['repos']> {
invalidateRuntimeWorktreeCaches()
return callRuntimeResult('repo.create', { parentPath, name, kind })
},
+ isGitAvailable: async () =>
+ (await callRuntimeResult<{ available: boolean }>('repo.gitAvailable')).available,
+ getDefaultCreateProjectParent: async () => {
+ const result = await callRuntimeResult<{ resolvedPath: string }>('files.browseServerDir', {
+ path: '~'
+ })
+ return getDefaultCreateProjectParent(result.resolvedPath)
+ },
onCloneProgress: () => noopUnsubscribe,
getGitUsername: () => Promise.resolve(''),
getBaseRefDefault: async ({ repoId }) =>
From 855b2fb09cab16333b0c6181afe4540c946b17f9 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Wed, 10 Jun 2026 17:05:54 -0700
Subject: [PATCH 048/165] Redesign Connect integrations (#4531)
Co-authored-by: Orca
---
src/renderer/src/components/TaskPage.tsx | 185 +++-
.../ConnectIntegrationsList.test.tsx | 224 +++++
.../feature-wall/ConnectIntegrationsList.tsx | 184 ++++
.../FeatureWallSetupChecklist.tsx | 47 +-
.../feature-wall/connect-integration-step.tsx | 119 +++
.../feature-wall-setup-progress.test.ts | 6 +
...e-feature-wall-task-source-presentation.ts | 68 +-
.../use-integration-connection-status.test.ts | 466 +++++++++
.../use-integration-connection-status.ts | 255 +++++
.../src/components/jira-connect-dialog.tsx | 249 +++++
.../new-workspace/SmartWorkspaceNameField.tsx | 13 +-
.../components/settings/IntegrationsPane.tsx | 917 +-----------------
.../cli-source-control-integration-cards.tsx | 265 +++++
.../settings/integration-card-shell.tsx | 68 ++
.../settings/jira-integration-card.tsx | 375 +++----
.../source-control-integration-cards.tsx | 11 +
.../source-control-preflight-card-status.ts | 95 ++
.../task-tracker-integration-cards.tsx | 212 ++++
...token-source-control-integration-cards.tsx | 365 +++++++
...use-integration-provider-status-refresh.ts | 51 +
.../setup-guide-progress-readiness.ts | 2 +
.../setup-guide/setup-script-probe-cache.ts | 34 +
.../use-setup-guide-progress.test.ts | 4 +-
.../setup-guide/use-setup-guide-progress.ts | 106 +-
.../src/components/sidebar/SidebarNav.tsx | 19 +-
src/renderer/src/i18n/locales/en.json | 152 ++-
src/renderer/src/i18n/locales/es.json | 152 ++-
src/renderer/src/i18n/locales/ja.json | 152 ++-
src/renderer/src/i18n/locales/ko.json | 152 ++-
src/renderer/src/i18n/locales/zh.json | 152 ++-
.../src/lib/local-preflight-context.test.ts | 15 +
.../src/lib/local-preflight-context.ts | 11 +-
.../src/lib/provider-runtime-context.ts | 22 +
src/renderer/src/store/slices/jira.test.ts | 129 ++-
src/renderer/src/store/slices/jira.ts | 278 +++++-
src/renderer/src/store/slices/linear.test.ts | 78 ++
src/renderer/src/store/slices/linear.ts | 605 ++++++++++--
.../src/store/slices/preflight.test.ts | 66 +-
src/renderer/src/store/slices/preflight.ts | 17 +-
src/renderer/src/store/slices/settings.ts | 4 +
40 files changed, 4911 insertions(+), 1414 deletions(-)
create mode 100644 src/renderer/src/components/feature-wall/ConnectIntegrationsList.test.tsx
create mode 100644 src/renderer/src/components/feature-wall/ConnectIntegrationsList.tsx
create mode 100644 src/renderer/src/components/feature-wall/connect-integration-step.tsx
create mode 100644 src/renderer/src/components/feature-wall/use-integration-connection-status.test.ts
create mode 100644 src/renderer/src/components/feature-wall/use-integration-connection-status.ts
create mode 100644 src/renderer/src/components/jira-connect-dialog.tsx
create mode 100644 src/renderer/src/components/settings/cli-source-control-integration-cards.tsx
create mode 100644 src/renderer/src/components/settings/integration-card-shell.tsx
create mode 100644 src/renderer/src/components/settings/source-control-integration-cards.tsx
create mode 100644 src/renderer/src/components/settings/source-control-preflight-card-status.ts
create mode 100644 src/renderer/src/components/settings/task-tracker-integration-cards.tsx
create mode 100644 src/renderer/src/components/settings/token-source-control-integration-cards.tsx
create mode 100644 src/renderer/src/components/settings/use-integration-provider-status-refresh.ts
create mode 100644 src/renderer/src/components/setup-guide/setup-script-probe-cache.ts
create mode 100644 src/renderer/src/lib/provider-runtime-context.ts
diff --git a/src/renderer/src/components/TaskPage.tsx b/src/renderer/src/components/TaskPage.tsx
index 48a6ad87eb2..7acce76d664 100644
--- a/src/renderer/src/components/TaskPage.tsx
+++ b/src/renderer/src/components/TaskPage.tsx
@@ -41,6 +41,8 @@ import { toast } from 'sonner'
import { useAppStore } from '@/store'
import { useAllWorktrees, useRepoMap } from '@/store/selectors'
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
import { Button } from '@/components/ui/button'
import { ButtonGroup } from '@/components/ui/button-group'
import { Input } from '@/components/ui/input'
@@ -2464,8 +2466,10 @@ export default function TaskPage(): React.JSX.Element {
const workItemsInvalidationNonce = useAppStore((s) => s.workItemsInvalidationNonce)
const linearStatus = useAppStore((s) => s.linearStatus)
const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
+ const linearStatusContextKey = useAppStore((s) => s.linearStatusContextKey)
const preflightStatus = useAppStore((s) => s.preflightStatus)
const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
const selectLinearWorkspace = useAppStore((s) => s.selectLinearWorkspace)
const searchLinearIssues = useAppStore((s) => s.searchLinearIssues)
const listLinearIssues = useAppStore((s) => s.listLinearIssues)
@@ -2484,13 +2488,27 @@ export default function TaskPage(): React.JSX.Element {
const patchLinearIssue = useAppStore((s) => s.patchLinearIssue)
const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
const jiraStatus = useAppStore((s) => s.jiraStatus)
const jiraStatusChecked = useAppStore((s) => s.jiraStatusChecked)
+ const jiraStatusContextKey = useAppStore((s) => s.jiraStatusContextKey)
const connectJira = useAppStore((s) => s.connectJira)
const selectJiraSite = useAppStore((s) => s.selectJiraSite)
const searchJiraIssues = useAppStore((s) => s.searchJiraIssues)
const listJiraIssues = useAppStore((s) => s.listJiraIssues)
const checkJiraConnection = useAppStore((s) => s.checkJiraConnection)
+ const providerRuntimeContextKey = getProviderRuntimeContextKey(settings)
+ const providerRuntimeContextKeyRef = useRef(providerRuntimeContextKey)
+ providerRuntimeContextKeyRef.current = providerRuntimeContextKey
+ const linearStatusCurrent = linearStatusContextKey === providerRuntimeContextKey
+ const jiraStatusCurrent = jiraStatusContextKey === providerRuntimeContextKey
+ const preflightStatusCurrent = preflightStatusContextKey === expectedPreflightContextKey
+ const linearStatusReady = linearStatusCurrent && linearStatusChecked
+ const jiraStatusReady = jiraStatusCurrent && jiraStatusChecked
+ const linearConnected = linearStatusCurrent && linearStatus.connected
+ const jiraConnected = jiraStatusCurrent && jiraStatus.connected
const submitShortcutLabel = getScreenSubmitShortcutLabel()
const eligibleRepos = useMemo(() => repos.filter((repo) => isGitRepoKind(repo)), [repos])
@@ -2585,15 +2603,16 @@ export default function TaskPage(): React.JSX.Element {
restoreAvailableDefaultTaskProvider(
preferredVisibleTaskProviders,
{
- gitlabInstalled: preflightStatus?.glab?.installed === true,
- linearConnected: linearStatus.connected === true
+ gitlabInstalled: preflightStatusCurrent && preflightStatus?.glab?.installed === true,
+ linearConnected: linearConnected === true
},
defaultTaskSource
),
[
defaultTaskSource,
- linearStatus.connected,
+ linearConnected,
preferredVisibleTaskProviders,
+ preflightStatusCurrent,
preflightStatus?.glab?.installed
]
)
@@ -3405,7 +3424,7 @@ export default function TaskPage(): React.JSX.Element {
linearContextResumeAttemptedRef.current ||
!taskResumeApplied ||
taskSource !== 'linear' ||
- !linearStatus.connected ||
+ !linearConnected ||
!context
) {
return
@@ -3482,7 +3501,7 @@ export default function TaskPage(): React.JSX.Element {
fetchLinearCustomView,
fetchLinearProject,
listLinearCustomViews,
- linearStatus.connected,
+ linearConnected,
setTaskResumeState,
taskResumeApplied,
taskResumeState?.linearContext,
@@ -3499,7 +3518,7 @@ export default function TaskPage(): React.JSX.Element {
if (!taskResumeApplied) {
return
}
- if (taskSource !== 'linear' || !linearStatus.connected) {
+ if (taskSource !== 'linear' || !linearConnected) {
setAvailableTeams([])
return
}
@@ -3526,7 +3545,7 @@ export default function TaskPage(): React.JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
taskSource,
- linearStatus.connected,
+ linearConnected,
selectedLinearWorkspaceId,
linearTeamRefreshNonce,
taskResumeApplied,
@@ -3541,7 +3560,7 @@ export default function TaskPage(): React.JSX.Element {
if (!taskResumeApplied) {
return
}
- if (taskSource !== 'jira' || !jiraStatus.connected) {
+ if (taskSource !== 'jira' || !jiraConnected) {
setAvailableJiraProjects([])
setJiraProjectsLoading(false)
return
@@ -3568,7 +3587,7 @@ export default function TaskPage(): React.JSX.Element {
return () => {
cancelled = true
}
- }, [settings, taskSource, jiraStatus.connected, selectedJiraSiteId, taskResumeApplied])
+ }, [settings, taskSource, jiraConnected, selectedJiraSiteId, taskResumeApplied])
// Why: stable key for `selectedRepos` so the GitLab fetch effect below
// doesn't re-run on every parent re-render just because the array
@@ -4321,7 +4340,7 @@ export default function TaskPage(): React.JSX.Element {
useEffect(() => {
let cancelled = false
- if (!newLinearIssueTargetTeam) {
+ if (!newLinearIssueOpen || !linearConnected || !newLinearIssueTargetTeam) {
setNewLinearIssueProjects([])
setNewLinearIssueProjectsLoading(false)
return
@@ -4347,7 +4366,13 @@ export default function TaskPage(): React.JSX.Element {
// populate the composer after a team/workspace switch.
cancelled = true
}
- }, [newLinearIssueTargetTeam, settings, selectedLinearWorkspaceId])
+ }, [
+ linearConnected,
+ newLinearIssueOpen,
+ newLinearIssueTargetTeam,
+ settings,
+ selectedLinearWorkspaceId
+ ])
useEffect(() => {
// Why: the selected team can change indirectly when the available Linear
@@ -4367,17 +4392,17 @@ export default function TaskPage(): React.JSX.Element {
}, [newLinearIssueTargetTeam?.id, newLinearIssueTargetTeam?.workspaceId, selectedLinearProject])
const newLinearStates = useTeamStates(
- newLinearIssueTargetTeam?.id || null,
+ linearConnected ? newLinearIssueTargetTeam?.id || null : null,
settings,
newLinearIssueTargetTeam?.workspaceId
)
const newLinearMembers = useTeamMembers(
- newLinearIssueTargetTeam?.id || null,
+ linearConnected ? newLinearIssueTargetTeam?.id || null : null,
settings,
newLinearIssueTargetTeam?.workspaceId
)
const newLinearLabels = useTeamLabels(
- newLinearIssueTargetTeam?.id || null,
+ linearConnected ? newLinearIssueTargetTeam?.id || null : null,
settings,
newLinearIssueTargetTeam?.workspaceId
)
@@ -4447,6 +4472,45 @@ export default function TaskPage(): React.JSX.Element {
const [jiraConnectState, setJiraConnectState] = useState<'idle' | 'connecting' | 'error'>('idle')
const [jiraConnectError, setJiraConnectError] = useState(null)
const includeJiraSiteNameInProjectLabel = selectedJiraSiteId === 'all'
+ const previousProviderRuntimeContextKeyRef = useRef(providerRuntimeContextKey)
+
+ useEffect(() => {
+ if (previousProviderRuntimeContextKeyRef.current === providerRuntimeContextKey) {
+ return
+ }
+ previousProviderRuntimeContextKeyRef.current = providerRuntimeContextKey
+ if (newLinearIssueOpen) {
+ setNewLinearIssueOpen(false)
+ setNewLinearIssueTitle('')
+ setNewLinearIssueBody('')
+ setNewLinearIssueTeamId(null)
+ setNewLinearIssueStateId(null)
+ setNewLinearIssueAssigneeId(null)
+ setNewLinearIssuePriority(0)
+ setNewLinearIssueProjectId(null)
+ setNewLinearIssueLabelIds([])
+ setNewLinearIssueProjects([])
+ setNewLinearIssueProjectsLoading(false)
+ setNewLinearIssueSubmitting(false)
+ }
+ if (newJiraIssueOpen) {
+ setNewJiraIssueOpen(false)
+ setNewJiraIssueTitle('')
+ setNewJiraIssueBody('')
+ setNewJiraIssueProjectId(null)
+ setNewJiraIssueProjectComboboxOpen(false)
+ setNewJiraIssueProjectQuery('')
+ setNewJiraIssueProjectCommandValue('')
+ setNewJiraIssueTypeId(null)
+ setAvailableJiraIssueTypes([])
+ setJiraIssueTypesLoading(false)
+ setJiraCreateFields([])
+ setJiraCreateFieldsLoading(false)
+ setJiraCreateFieldsError(null)
+ setNewJiraIssueCustomFieldValues({})
+ setNewJiraIssueSubmitting(false)
+ }
+ }, [newJiraIssueOpen, newLinearIssueOpen, providerRuntimeContextKey])
const sortedAvailableJiraProjects = useMemo(
() =>
@@ -4562,7 +4626,7 @@ export default function TaskPage(): React.JSX.Element {
)
useEffect(() => {
- if (!newJiraIssueOpen || !newJiraIssueTargetProject) {
+ if (!newJiraIssueOpen || !jiraConnected || !newJiraIssueTargetProject) {
setAvailableJiraIssueTypes([])
setJiraIssueTypesLoading(false)
return
@@ -4597,10 +4661,15 @@ export default function TaskPage(): React.JSX.Element {
return () => {
cancelled = true
}
- }, [settings, newJiraIssueOpen, newJiraIssueTargetProject])
+ }, [settings, jiraConnected, newJiraIssueOpen, newJiraIssueTargetProject])
useEffect(() => {
- if (!newJiraIssueOpen || !newJiraIssueTargetProject || !newJiraIssueTargetType) {
+ if (
+ !newJiraIssueOpen ||
+ !jiraConnected ||
+ !newJiraIssueTargetProject ||
+ !newJiraIssueTargetType
+ ) {
setJiraCreateFields([])
setJiraCreateFieldsLoading(false)
setJiraCreateFieldsError(null)
@@ -4638,7 +4707,7 @@ export default function TaskPage(): React.JSX.Element {
// responses after the user switches either selector.
cancelled = true
}
- }, [settings, newJiraIssueOpen, newJiraIssueTargetProject, newJiraIssueTargetType])
+ }, [settings, jiraConnected, newJiraIssueOpen, newJiraIssueTargetProject, newJiraIssueTargetType])
// Why: defense-in-depth safety net applied to the current page's items.
// The active tab scopes requests to issues or PRs, and this keeps stale
@@ -5536,6 +5605,7 @@ export default function TaskPage(): React.JSX.Element {
return
}
setNewLinearIssueSubmitting(true)
+ const submitProviderRuntimeContextKey = providerRuntimeContextKey
try {
const result = await linearCreateIssue(settings, {
teamId: newLinearIssueTargetTeam.id,
@@ -5548,6 +5618,9 @@ export default function TaskPage(): React.JSX.Element {
projectId: newLinearIssueProjectId || null,
labelIds: newLinearIssueLabelIds.length > 0 ? newLinearIssueLabelIds : undefined
})
+ if (submitProviderRuntimeContextKey !== providerRuntimeContextKeyRef.current) {
+ return
+ }
if (!result.ok) {
toast.error(
result.error ||
@@ -5583,13 +5656,18 @@ export default function TaskPage(): React.JSX.Element {
// sees exactly what was filed, mirroring the GitHub create-issue flow.
void linearGetIssue(settings, result.id, newLinearIssueTargetTeam.workspaceId)
.then((full) => {
+ if (submitProviderRuntimeContextKey !== providerRuntimeContextKeyRef.current) {
+ return
+ }
if (full) {
setSelectedLinearIssue(full, { allowOutsideList: true })
}
})
.catch(() => {})
} finally {
- setNewLinearIssueSubmitting(false)
+ if (submitProviderRuntimeContextKey === providerRuntimeContextKeyRef.current) {
+ setNewLinearIssueSubmitting(false)
+ }
}
}, [
newLinearIssueBody,
@@ -5601,6 +5679,7 @@ export default function TaskPage(): React.JSX.Element {
newLinearIssueAssigneeId,
newLinearIssueProjectId,
newLinearIssueLabelIds,
+ providerRuntimeContextKey,
selectedLinearProject,
setSelectedLinearIssue,
settings
@@ -5619,6 +5698,7 @@ export default function TaskPage(): React.JSX.Element {
newJiraIssueCustomFieldValues
)
setNewJiraIssueSubmitting(true)
+ const submitProviderRuntimeContextKey = providerRuntimeContextKey
try {
const result = await jiraCreateIssue(settings, {
siteId: newJiraIssueTargetProject.siteId,
@@ -5628,6 +5708,9 @@ export default function TaskPage(): React.JSX.Element {
description: newJiraIssueBody || undefined,
customFields
})
+ if (submitProviderRuntimeContextKey !== providerRuntimeContextKeyRef.current) {
+ return
+ }
if (!result.ok) {
toast.error(
result.error ||
@@ -5656,6 +5739,9 @@ export default function TaskPage(): React.JSX.Element {
void jiraGetIssue(settings, result.key, newJiraIssueTargetProject.siteId)
.then((full) => {
+ if (submitProviderRuntimeContextKey !== providerRuntimeContextKeyRef.current) {
+ return
+ }
if (full) {
// Why: the list cache may still be fresh after create; insert the
// new row locally before selecting it so the inspector stays open.
@@ -5665,7 +5751,9 @@ export default function TaskPage(): React.JSX.Element {
})
.catch(() => {})
} finally {
- setNewJiraIssueSubmitting(false)
+ if (submitProviderRuntimeContextKey === providerRuntimeContextKeyRef.current) {
+ setNewJiraIssueSubmitting(false)
+ }
}
}, [
hasMissingJiraCreateField,
@@ -5676,6 +5764,7 @@ export default function TaskPage(): React.JSX.Element {
newJiraIssueTargetProject,
newJiraIssueTargetType,
newJiraIssueTitle,
+ providerRuntimeContextKey,
settings,
setSelectedJiraIssue,
visibleJiraCreateFields
@@ -5737,21 +5826,27 @@ export default function TaskPage(): React.JSX.Element {
])
useEffect(() => {
- if (!preflightStatusChecked) {
+ if (!preflightStatusCurrent || !preflightStatusChecked) {
void refreshPreflightStatus()
}
- if (!linearStatusChecked) {
+ if (!linearStatusReady) {
void checkLinearConnection()
}
- if (!jiraStatusChecked) {
+ if (!jiraStatusReady) {
void checkJiraConnection()
}
}, [
checkJiraConnection,
checkLinearConnection,
- jiraStatusChecked,
- linearStatusChecked,
+ expectedPreflightContextKey,
+ jiraStatusContextKey,
+ jiraStatusReady,
+ linearStatusContextKey,
+ linearStatusReady,
+ providerRuntimeContextKey,
+ preflightStatusContextKey,
preflightStatusChecked,
+ preflightStatusCurrent,
refreshPreflightStatus
])
@@ -5804,7 +5899,7 @@ export default function TaskPage(): React.JSX.Element {
if (linearMode !== 'issues') {
return
}
- if (!linearStatus.connected) {
+ if (!linearConnected) {
return
}
@@ -5918,7 +6013,7 @@ export default function TaskPage(): React.JSX.Element {
}, [
taskSource,
linearMode,
- linearStatus.connected,
+ linearConnected,
selectedLinearWorkspaceId,
appliedLinearSearch,
linearIssueLimit,
@@ -5941,7 +6036,7 @@ export default function TaskPage(): React.JSX.Element {
if (!taskResumeApplied || taskSource !== 'linear' || linearMode !== 'projects') {
return
}
- if (!linearStatus.connected || selectedLinearProject) {
+ if (!linearConnected || selectedLinearProject) {
return
}
let cancelled = false
@@ -5978,7 +6073,7 @@ export default function TaskPage(): React.JSX.Element {
taskResumeApplied,
taskSource,
linearMode,
- linearStatus.connected,
+ linearConnected,
selectedLinearWorkspaceId,
selectedLinearProject,
appliedLinearProjectSearch,
@@ -6066,7 +6161,7 @@ export default function TaskPage(): React.JSX.Element {
if (!taskResumeApplied || taskSource !== 'linear' || linearMode !== 'views') {
return
}
- if (!linearStatus.connected || selectedLinearCustomView) {
+ if (!linearConnected || selectedLinearCustomView) {
return
}
let cancelled = false
@@ -6111,7 +6206,7 @@ export default function TaskPage(): React.JSX.Element {
taskResumeApplied,
taskSource,
linearMode,
- linearStatus.connected,
+ linearConnected,
selectedLinearWorkspaceId,
selectedLinearCustomView,
linearRefreshNonce,
@@ -6179,7 +6274,7 @@ export default function TaskPage(): React.JSX.Element {
return
}
- if (!linearStatus.connected) {
+ if (!linearConnected) {
clearSelectedLinearIssue()
return
}
@@ -6205,7 +6300,7 @@ export default function TaskPage(): React.JSX.Element {
}, [
clearSelectedLinearIssue,
filteredLinearIssues,
- linearStatus.connected,
+ linearConnected,
selectedLinearIssueCanFloat,
selectedLinearIssueId,
taskResumeApplied,
@@ -6240,7 +6335,7 @@ export default function TaskPage(): React.JSX.Element {
if (taskSource !== 'jira') {
return
}
- if (!jiraStatus.connected) {
+ if (!jiraConnected) {
return
}
@@ -6276,7 +6371,7 @@ export default function TaskPage(): React.JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
taskSource,
- jiraStatus.connected,
+ jiraConnected,
selectedJiraSiteId,
appliedJiraSearch,
activeJiraPreset,
@@ -6288,7 +6383,7 @@ export default function TaskPage(): React.JSX.Element {
if (!taskResumeApplied || taskSource !== 'jira') {
return
}
- if (!jiraStatus.connected || displayedJiraIssues.length === 0) {
+ if (!jiraConnected || displayedJiraIssues.length === 0) {
if (selectedJiraIssueKey !== null) {
setSelectedJiraIssueKey(null)
}
@@ -6306,7 +6401,7 @@ export default function TaskPage(): React.JSX.Element {
}
}, [
displayedJiraIssues,
- jiraStatus.connected,
+ jiraConnected,
selectedJiraIssueFallback,
selectedJiraIssueKey,
taskResumeApplied,
@@ -6557,7 +6652,7 @@ export default function TaskPage(): React.JSX.Element {
)
})}
- {taskSource === 'linear' && linearStatus.connected ? (
+ {taskSource === 'linear' && linearConnected ? (
) : null}
- {taskSource === 'jira' && jiraStatus.connected ? (
+ {taskSource === 'jira' && jiraConnected ? (
{jiraSites.length > 1 ? (
- ) : taskSource === 'linear' && linearStatus.connected ? (
+ ) : taskSource === 'linear' && linearConnected ? (
) : null}
- ) : taskSource === 'jira' && jiraStatus.connected ? (
+ ) : taskSource === 'jira' && jiraConnected ? (
@@ -8305,11 +8400,11 @@ export default function TaskPage(): React.JSX.Element {
) : taskSource === 'jira' ? (
- !jiraStatusChecked ? (
+ !jiraStatusReady ? (
- ) : !jiraStatus.connected ? (
+ ) : !jiraConnected ? (
@@ -8602,11 +8697,11 @@ export default function TaskPage(): React.JSX.Element {
onOpenIssue={openRelatedLinearIssue}
onClose={closeTaskDetailPage}
/>
- ) : !linearStatusChecked ? (
+ ) : !linearStatusReady ? (
- ) : !linearStatus.connected ? (
+ ) : !linearConnected ? (
diff --git a/src/renderer/src/components/feature-wall/ConnectIntegrationsList.test.tsx b/src/renderer/src/components/feature-wall/ConnectIntegrationsList.test.tsx
new file mode 100644
index 00000000000..58846c0e350
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/ConnectIntegrationsList.test.tsx
@@ -0,0 +1,224 @@
+import { renderToStaticMarkup } from 'react-dom/server'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+import type { PreflightStatus } from '../../../../preload/api-types'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+import { ConnectIntegrationsList } from './ConnectIntegrationsList'
+
+type StoreState = {
+ activeRepoId: string | null
+ activeWorktreeId: string | null
+ worktreesByRepo: Record
+ repos: unknown[]
+ settings: { activeRuntimeEnvironmentId?: string | null }
+ preflightStatus: PreflightStatus | null
+ preflightStatusChecked: boolean
+ preflightStatusContextKey: string
+ preflightStatusError: string | null
+ preflightStatusLoading: boolean
+ refreshPreflightStatus: () => Promise
+ linearStatus: { connected: boolean; workspaces?: unknown[] }
+ linearStatusChecked: boolean
+ linearStatusContextKey: string | null
+ checkLinearConnection: () => Promise
+ testLinearConnection: () => Promise<{ ok: boolean; error?: string }>
+ disconnectLinear: () => Promise
+ disconnectLinearWorkspace: () => Promise
+ jiraStatus: { connected: boolean; sites?: unknown[] }
+ jiraStatusChecked: boolean
+ jiraStatusContextKey: string | null
+ checkJiraConnection: () => Promise
+ testJiraConnection: () => Promise<{ ok: boolean; error?: string }>
+ disconnectJira: () => Promise
+}
+
+const { storeState } = vi.hoisted(() => ({
+ storeState: { current: null as StoreState | null }
+}))
+
+vi.mock('@/store', () => ({
+ useAppStore: (selector: (state: StoreState) => unknown) => {
+ if (!storeState.current) {
+ throw new Error('Store state was not installed')
+ }
+ return selector(storeState.current)
+ }
+}))
+
+vi.mock('@/components/linear-api-key-dialog', () => ({
+ LinearApiKeyDialog: () => null
+}))
+
+vi.mock('@/components/jira-connect-dialog', () => ({
+ JiraConnectDialog: () => null
+}))
+
+function makePreflightStatus(overrides: Partial = {}): PreflightStatus {
+ const status: PreflightStatus = {
+ git: { installed: true },
+ gh: { installed: true, authenticated: false },
+ glab: { installed: true, authenticated: false },
+ bitbucket: {
+ configured: false,
+ authenticated: false,
+ account: null
+ },
+ azureDevOps: {
+ configured: false,
+ authenticated: false,
+ account: null,
+ baseUrl: null,
+ tokenConfigured: false
+ },
+ gitea: {
+ configured: false,
+ authenticated: false,
+ account: null,
+ baseUrl: null,
+ tokenConfigured: false
+ }
+ }
+ return { ...status, ...overrides }
+}
+
+function installStore(preflightStatus: PreflightStatus): void {
+ const settings = { activeRuntimeEnvironmentId: null }
+ const providerContextKey = getProviderRuntimeContextKey(settings)
+ storeState.current = {
+ activeRepoId: null,
+ activeWorktreeId: null,
+ worktreesByRepo: {},
+ repos: [],
+ settings,
+ preflightStatus,
+ preflightStatusChecked: true,
+ preflightStatusContextKey: 'host',
+ preflightStatusError: null,
+ preflightStatusLoading: false,
+ refreshPreflightStatus: vi.fn(async () => {}),
+ linearStatus: { connected: false, workspaces: [] },
+ linearStatusChecked: true,
+ linearStatusContextKey: providerContextKey,
+ checkLinearConnection: vi.fn(async () => {}),
+ testLinearConnection: vi.fn(async () => ({ ok: true })),
+ disconnectLinear: vi.fn(async () => {}),
+ disconnectLinearWorkspace: vi.fn(async () => {}),
+ jiraStatus: { connected: false, sites: [] },
+ jiraStatusChecked: true,
+ jiraStatusContextKey: providerContextKey,
+ checkJiraConnection: vi.fn(async () => {}),
+ testJiraConnection: vi.fn(async () => ({ ok: true })),
+ disconnectJira: vi.fn(async () => {})
+ }
+}
+
+async function renderConnectIntegrationsList(): Promise<{
+ markup: string
+}> {
+ return { markup: renderToStaticMarkup( ) }
+}
+
+describe('ConnectIntegrationsList', () => {
+ beforeEach(() => {
+ vi.stubGlobal('window', {
+ api: {
+ shell: {
+ openUrl: vi.fn()
+ }
+ }
+ })
+ })
+
+ afterEach(() => {
+ storeState.current = null
+ vi.unstubAllGlobals()
+ vi.restoreAllMocks()
+ })
+
+ it('renders the settings review cards in the review step without an inline auth terminal', async () => {
+ installStore(makePreflightStatus())
+
+ const { markup } = await renderConnectIntegrationsList()
+
+ for (const provider of ['GitHub', 'GitLab', 'Bitbucket', 'Azure DevOps', 'Gitea']) {
+ expect(markup).toContain(provider)
+ }
+ expect(markup).toContain('gh auth login')
+ expect(markup).toContain('glab auth login')
+ expect(markup).not.toContain('Run in terminal')
+ })
+
+ it('keeps the upcoming task step collapsed but openable, not inert', async () => {
+ installStore(makePreflightStatus())
+
+ const { markup } = await renderConnectIntegrationsList()
+
+ // Step 1 is not a prerequisite: the task step starts collapsed but offers
+ // an "Open" affordance instead of a disabled, dimmed row.
+ expect(markup).toContain('Open')
+ expect(markup).not.toContain('opacity-55')
+ expect(markup).not.toContain('Add Linear access')
+ })
+
+ it('collapses the task step to its summary when a tracker connects first', async () => {
+ installStore(makePreflightStatus())
+ if (!storeState.current) {
+ throw new Error('Store state was not installed')
+ }
+ storeState.current.linearStatus = { connected: true, workspaces: [] }
+
+ const { markup } = await renderConnectIntegrationsList()
+
+ expect(markup).toContain('connected for tasks')
+ expect(markup).not.toContain('Connect Jira')
+ })
+
+ it('auto-resolves the task step from a connected code host but keeps it open for trackers', async () => {
+ installStore(makePreflightStatus({ gh: { installed: true, authenticated: true } }))
+
+ const { markup } = await renderConnectIntegrationsList()
+
+ expect(markup).toContain('GitHub')
+ expect(markup).toContain('issues available as tasks')
+ expect(markup).toContain('add Linear or Jira if your team plans work there')
+ expect(markup).not.toContain('Use GitHub issues')
+ // The step is done but stays expanded so Linear/Jira remain discoverable
+ // for teams that plan work in a dedicated tracker.
+ expect(markup).toContain('Add Linear access')
+ expect(markup).toContain('Connect Jira')
+ })
+
+ it('offers GitHub and GitLab as task sources when review came from a non-task provider', async () => {
+ // Bitbucket satisfies review but cannot serve tasks, so step 2 must still
+ // offer the code hosts as connectable task sources alongside the trackers.
+ installStore(
+ makePreflightStatus({
+ bitbucket: { configured: true, authenticated: true, account: 'acme' }
+ })
+ )
+
+ const { markup } = await renderConnectIntegrationsList()
+
+ expect(markup).toContain('issues also work as tasks.')
+ expect(markup).toContain('gh auth login')
+ expect(markup).toContain('glab auth login')
+ expect(markup).toContain('Linear')
+ expect(markup).toContain('Jira')
+ })
+
+ it('lists the code host alongside a connected tracker in the task summary', async () => {
+ installStore(makePreflightStatus({ gh: { installed: true, authenticated: true } }))
+ if (!storeState.current) {
+ throw new Error('Store state was not installed')
+ }
+ storeState.current.linearStatus = { connected: true, workspaces: [] }
+
+ const { markup } = await renderConnectIntegrationsList()
+
+ expect(markup).toContain('Linear')
+ expect(markup).toContain('GitHub')
+ expect(markup).toContain('connected for tasks')
+ expect(markup).toContain(' and ')
+ // A connected tracker collapses the step to its summary.
+ expect(markup).not.toContain('Connect Jira')
+ })
+})
diff --git a/src/renderer/src/components/feature-wall/ConnectIntegrationsList.tsx b/src/renderer/src/components/feature-wall/ConnectIntegrationsList.tsx
new file mode 100644
index 00000000000..2a51c2c47e9
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/ConnectIntegrationsList.tsx
@@ -0,0 +1,184 @@
+import { Fragment, useState } from 'react'
+import {
+ AzureDevOpsIntegrationCard,
+ BitbucketIntegrationCard,
+ GiteaIntegrationCard,
+ GitHubIntegrationCard,
+ GitLabIntegrationCard
+} from '@/components/settings/source-control-integration-cards'
+import {
+ JiraIntegrationCard,
+ LinearIntegrationCard
+} from '@/components/settings/task-tracker-integration-cards'
+import { useIntegrationProviderStatusRefresh } from '@/components/settings/use-integration-provider-status-refresh'
+import { IntegrationProgress, IntegrationStep } from './connect-integration-step'
+import {
+ deriveIntegrationFlowState,
+ useIntegrationConnectionStatus
+} from './use-integration-connection-status'
+import { translate } from '@/i18n/i18n'
+
+// Bold provider names joined into a natural-language list ("Linear and
+// GitHub", "Linear, Jira, and GitHub") for the task-step summary.
+function TaskSourceNameList(props: { names: readonly string[] }): React.JSX.Element {
+ return (
+ <>
+ {props.names.map((name, index) => (
+
+ {index > 0
+ ? index === props.names.length - 1
+ ? props.names.length > 2
+ ? translate('auto.components.feature.wall.ConnectIntegrationsList.list_end', ', and ')
+ : translate('auto.components.feature.wall.ConnectIntegrationsList.list_pair', ' and ')
+ : translate('auto.components.feature.wall.ConnectIntegrationsList.list_mid', ', ')
+ : null}
+ {name}
+
+ ))}
+ >
+ )
+}
+
+// Progressive two-step integration setup: first connect a code host for review
+// status, then a task source. The order is a recommendation, not a gate — step
+// 2 starts collapsed but opens on click so tracker-first users aren't blocked.
+// Connecting step 1 collapses it to a summary and expands step 2, which stays
+// open until a dedicated tracker connects so Linear/Jira remain discoverable.
+// Done-state is driven by real provider connection status, never an
+// optimistic click.
+export function ConnectIntegrationsList(): React.JSX.Element {
+ useIntegrationProviderStatusRefresh()
+ const status = useIntegrationConnectionStatus()
+ // Lets the done review step reopen inline via "Change" without losing its
+ // connected state. Cleared once the user collapses it again.
+ const [reviewReopened, setReviewReopened] = useState(false)
+
+ // A code host doubles as a task source, so a connected GitHub/GitLab
+ // resolves step 2 on its own. The collapsed summary still invites a
+ // dedicated tracker, and "Change" reopens the step to connect one.
+ const flow = deriveIntegrationFlowState({
+ reviewConnected: status.reviewConnected,
+ trackerProviderName: status.trackerProviderName,
+ codeHostTaskProviderName: status.codeHostTaskProviderName,
+ trackerChecking: status.trackerChecking
+ })
+ const reviewDone = status.reviewConnected
+ const trackerDone = status.trackerProviderName !== null
+ const reviewExpanded = !reviewDone || reviewReopened
+ const reviewCanToggle = reviewDone
+ // User's explicit expand/collapse of step 2, snapshotted against the
+ // connection state so a provider connecting (or disconnecting) restores the
+ // default for the new state instead of keeping a stale manual choice.
+ const [taskToggle, setTaskToggle] = useState<{
+ expanded: boolean
+ whenTrackerDone: boolean
+ whenReviewDone: boolean
+ } | null>(null)
+ const taskToggleCurrent =
+ taskToggle !== null &&
+ taskToggle.whenTrackerDone === trackerDone &&
+ taskToggle.whenReviewDone === reviewDone
+ // Step 2 defaults collapsed while step 1 is still active (but opens on
+ // click — review is not a prerequisite for connecting a tracker), stays open
+ // even when the code host already resolved it so Linear/Jira remain
+ // discoverable, and collapses only once a dedicated tracker connects.
+ const taskExpanded = taskToggleCurrent ? taskToggle.expanded : reviewDone && !trackerDone
+
+ return (
+
+
+
+ {translate(
+ 'auto.components.feature.wall.ConnectIntegrationsList.3a1fcdddad',
+ 'Two quick steps: connect where your code is reviewed, then where your team plans work.'
+ )}
+
+
+
+
+
+ {status.reviewProviderName} {' '}
+ {translate(
+ 'auto.components.feature.wall.ConnectIntegrationsList.5b3577a492',
+ 'connected for review status'
+ )}
+ >
+ }
+ onToggle={() => setReviewReopened((value) => !value)}
+ canToggle={reviewCanToggle}
+ >
+
+
+
+
+
+
+
+
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ConnectIntegrationsList.3dddb2d565',
+ 'connected for tasks'
+ )}
+ >
+ ) : (
+ <>
+
+ {status.codeHostTaskProviderName}
+ {' '}
+ {translate(
+ 'auto.components.feature.wall.ConnectIntegrationsList.code_host_tasks_summary',
+ 'issues available as tasks · add Linear or Jira if your team plans work there'
+ )}
+ >
+ )
+ }
+ onToggle={() =>
+ setTaskToggle({
+ expanded: !taskExpanded,
+ whenTrackerDone: trackerDone,
+ whenReviewDone: reviewDone
+ })
+ }
+ >
+
+
+
+ {translate(
+ 'auto.components.feature.wall.ConnectIntegrationsList.code_host_tasks_caption',
+ "Your code host's issues also work as tasks."
+ )}
+
+
+
+
+
+ )
+}
diff --git a/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx b/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
index 260f6f4d060..a6cd18e24b6 100644
--- a/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
+++ b/src/renderer/src/components/feature-wall/FeatureWallSetupChecklist.tsx
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo } from 'react'
-import { ArrowUpRight, Check } from 'lucide-react'
+import { Check } from 'lucide-react'
import type {
FeatureWallSetupStep,
FeatureWallSetupStepId
@@ -15,6 +15,7 @@ import {
TwoAgentsAction,
WorkspacesAction
} from './FeatureWallSetupWorkflowActions'
+import { ConnectIntegrationsList } from './ConnectIntegrationsList'
import { BrowserAction } from './FeatureWallBrowserAction'
import {
SetupBrowserVisual,
@@ -22,12 +23,11 @@ import {
SetupTwoAgentsVisual,
SetupWorkspacesVisual
} from './FeatureWallSetupStepVisuals'
-import { Button } from '@/components/ui/button'
-import { GitHubRow, LinearRow } from '../onboarding/IntegrationsStep'
import { AgentStep } from '../onboarding/AgentStep'
import { NotificationStep } from '../onboarding/NotificationStep'
import { useAppStore } from '@/store'
import type { TuiAgent } from '../../../../shared/types'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
import { translate } from '@/i18n/i18n'
type FeatureWallSetupChecklistLayout = 'modal' | 'embedded'
@@ -234,31 +234,26 @@ function NotificationAction(): React.JSX.Element {
}
function TaskSourcesAction(): React.JSX.Element {
- const closeModal = useAppStore((s) => s.closeModal)
- const openTaskPage = useAppStore((s) => s.openTaskPage)
+ const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
+ const checkJiraConnection = useAppStore((s) => s.checkJiraConnection)
+ const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
+ const settings = useAppStore((s) => s.settings)
+ const providerRuntimeContextKey = getProviderRuntimeContextKey(settings)
+
+ useEffect(() => {
+ void refreshPreflightStatus()
+ void checkJiraConnection()
+ void checkLinearConnection()
+ }, [
+ refreshPreflightStatus,
+ checkJiraConnection,
+ checkLinearConnection,
+ providerRuntimeContextKey
+ ])
+
return (
-
-
-
-
-
-
{
- closeModal()
- openTaskPage()
- }}
- >
-
- {translate(
- 'auto.components.feature.wall.FeatureWallSetupChecklist.b1f1981c5e',
- 'See tasks'
- )}
-
-
+
)
}
diff --git a/src/renderer/src/components/feature-wall/connect-integration-step.tsx b/src/renderer/src/components/feature-wall/connect-integration-step.tsx
new file mode 100644
index 00000000000..d63b53421a9
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/connect-integration-step.tsx
@@ -0,0 +1,119 @@
+import { Check } from 'lucide-react'
+import { cn } from '@/lib/utils'
+import type { IntegrationStepState } from './use-integration-connection-status'
+import { translate } from '@/i18n/i18n'
+
+export type { IntegrationStepState }
+
+// One progressive step. The active step shows its instructional copy and
+// provider rows; a done step collapses to a one-line summary with a "Change"
+// affordance that reopens it inline; upcoming steps start collapsed but open
+// on click so the step order never blocks anyone. `expanded` (body visibility)
+// is tracked separately from `state` so a done step can reopen while still
+// reading as connected.
+export function IntegrationStep(props: {
+ index: number
+ state: IntegrationStepState
+ expanded: boolean
+ title: string
+ description: string
+ summary?: React.ReactNode
+ onToggle?: () => void
+ canToggle?: boolean
+ children?: React.ReactNode
+}): React.JSX.Element {
+ const { state, expanded, onToggle } = props
+ const done = state === 'done'
+ const active = state === 'active'
+ // Upcoming steps are openable too — the order is a recommendation, not a
+ // prerequisite, so a Linear/Jira-first user can connect tasks right away.
+ const canToggle = !active && (props.canToggle ?? true)
+
+ return (
+
+
+
+ {done ? : props.index + 1}
+
+
+
+ {props.title}
+
+
+ {done ? props.summary : props.description}
+
+
+ {canToggle ? (
+
+ {done
+ ? expanded
+ ? translate(
+ 'auto.components.feature.wall.connect.integration.step.5538eb6743',
+ 'Done'
+ )
+ : translate(
+ 'auto.components.feature.wall.connect.integration.step.0f47ff17c6',
+ 'Change'
+ )
+ : expanded
+ ? translate(
+ 'auto.components.feature.wall.connect.integration.step.close_step',
+ 'Close'
+ )
+ : translate(
+ 'auto.components.feature.wall.connect.integration.step.open_step',
+ 'Open'
+ )}
+
+ ) : null}
+
+ {expanded ? (
+
{props.children}
+ ) : null}
+
+ )
+}
+
+// Two progress dots tracking step state; the active one stretches into a bar.
+export function IntegrationProgress(props: {
+ states: readonly IntegrationStepState[]
+}): React.JSX.Element {
+ return (
+
+ {props.states.map((state, i) => (
+
+ ))}
+
+ )
+}
diff --git a/src/renderer/src/components/feature-wall/feature-wall-setup-progress.test.ts b/src/renderer/src/components/feature-wall/feature-wall-setup-progress.test.ts
index 740cc8a32e6..9c2f35839e7 100644
--- a/src/renderer/src/components/feature-wall/feature-wall-setup-progress.test.ts
+++ b/src/renderer/src/components/feature-wall/feature-wall-setup-progress.test.ts
@@ -297,6 +297,12 @@ describe('getFeatureWallSetupProgress', () => {
expect(progress.stepDone['task-sources']).toBe(true)
})
+ it('does not mark task sources complete while provider checks are pending', () => {
+ const progress = getFeatureWallSetupProgress(makeInput({ hasConnectedTaskSource: false }))
+
+ expect(progress.stepDone['task-sources']).toBe(false)
+ })
+
it('does not mark agent capabilities complete from setup-start interactions alone', () => {
const progress = getFeatureWallSetupProgress(
makeInput({
diff --git a/src/renderer/src/components/feature-wall/use-feature-wall-task-source-presentation.ts b/src/renderer/src/components/feature-wall/use-feature-wall-task-source-presentation.ts
index 9d9b20cce63..3946a8afa56 100644
--- a/src/renderer/src/components/feature-wall/use-feature-wall-task-source-presentation.ts
+++ b/src/renderer/src/components/feature-wall/use-feature-wall-task-source-presentation.ts
@@ -1,13 +1,16 @@
import { useEffect } from 'react'
import type { FeatureWallWorkflow } from '../../../../shared/feature-wall-workflows'
import { useAppStore } from '@/store'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+import { deriveIntegrationConnectionStatus } from './use-integration-connection-status'
export type FeatureWallTaskSourcePresentation = {
workflow: FeatureWallWorkflow
hasConnectedTaskSource: boolean
- // True until the first preflight + Linear status check has resolved. Callers
- // should treat unknown state as "don't show the disconnected setup affordance
- // yet" so we don't flash inline integration rows for a connected user.
+ // True until the first provider status checks resolve. Callers should treat
+ // unknown state as "don't show the disconnected setup affordance yet" so we
+ // don't flash inline integration rows for a connected user.
isCheckingTaskSources: boolean
}
@@ -17,11 +20,26 @@ export function useFeatureWallTaskSourcePresentation(
): FeatureWallTaskSourcePresentation {
const preflightStatus = useAppStore((s) => s.preflightStatus)
const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
+ const preflightStatusError = useAppStore((s) => s.preflightStatusError)
const preflightStatusLoading = useAppStore((s) => s.preflightStatusLoading)
const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
const linearStatus = useAppStore((s) => s.linearStatus)
const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
+ const linearStatusContextKey = useAppStore((s) => s.linearStatusContextKey)
const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
+ const jiraStatus = useAppStore((s) => s.jiraStatus)
+ const jiraStatusChecked = useAppStore((s) => s.jiraStatusChecked)
+ const jiraStatusContextKey = useAppStore((s) => s.jiraStatusContextKey)
+ const checkJiraConnection = useAppStore((s) => s.checkJiraConnection)
+ const settings = useAppStore((s) => s.settings)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
+ const providerRuntimeContextKey = getProviderRuntimeContextKey(settings)
+ const linearStatusCurrent = linearStatusContextKey === providerRuntimeContextKey
+ const jiraStatusCurrent = jiraStatusContextKey === providerRuntimeContextKey
+ const preflightStatusCurrent = preflightStatusContextKey === expectedPreflightContextKey
useEffect(() => {
if (!isOpen) {
@@ -29,26 +47,52 @@ export function useFeatureWallTaskSourcePresentation(
}
// Why: the Tasks tour copy depends on whether a task source is already
// usable, so connected users should not see setup-oriented guidance.
- if (!preflightStatusChecked) {
+ if (!preflightStatusCurrent || !preflightStatusChecked) {
void refreshPreflightStatus()
}
- if (!linearStatusChecked) {
+ if (!linearStatusCurrent || !linearStatusChecked) {
void checkLinearConnection()
}
+ if (!jiraStatusCurrent || !jiraStatusChecked) {
+ void checkJiraConnection()
+ }
}, [
+ checkJiraConnection,
checkLinearConnection,
+ expectedPreflightContextKey,
isOpen,
+ jiraStatusCurrent,
+ jiraStatusChecked,
+ jiraStatusContextKey,
+ linearStatusCurrent,
linearStatusChecked,
+ linearStatusContextKey,
+ preflightStatusContextKey,
+ preflightStatusCurrent,
preflightStatusChecked,
+ providerRuntimeContextKey,
refreshPreflightStatus
])
- const hasConnectedTaskSource =
- (preflightStatus?.gh.installed === true && preflightStatus.gh.authenticated === true) ||
- (preflightStatus?.glab?.installed === true && preflightStatus.glab.authenticated === true) ||
- linearStatus.connected === true
- const isCheckingTaskSources =
- preflightStatusLoading || !preflightStatusChecked || !linearStatusChecked
+ const taskSourceStatus = deriveIntegrationConnectionStatus({
+ preflightStatus,
+ preflightStatusChecked,
+ preflightStatusContextKey,
+ preflightStatusError,
+ preflightStatusLoading,
+ expectedPreflightContextKey,
+ linearStatus,
+ linearStatusChecked,
+ linearStatusContextKey,
+ jiraStatus,
+ jiraStatusChecked,
+ jiraStatusContextKey,
+ providerRuntimeContextKey
+ })
- return { workflow: selected, hasConnectedTaskSource, isCheckingTaskSources }
+ return {
+ workflow: selected,
+ hasConnectedTaskSource: taskSourceStatus.trackerConnected,
+ isCheckingTaskSources: taskSourceStatus.checking
+ }
}
diff --git a/src/renderer/src/components/feature-wall/use-integration-connection-status.test.ts b/src/renderer/src/components/feature-wall/use-integration-connection-status.test.ts
new file mode 100644
index 00000000000..11d4ebef48b
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/use-integration-connection-status.test.ts
@@ -0,0 +1,466 @@
+import { describe, expect, it } from 'vitest'
+import {
+ deriveIntegrationConnectionStatus,
+ deriveIntegrationFlowState,
+ deriveIntegrationStepStates
+} from './use-integration-connection-status'
+import { deriveCliProviderCardState } from '@/components/settings/source-control-integration-cards'
+
+type StatusFacts = Parameters[0]
+
+function statusFacts(overrides: Partial = {}): StatusFacts {
+ return {
+ preflightStatus: {
+ gh: { installed: false, authenticated: false },
+ glab: { installed: false, authenticated: false },
+ bitbucket: { configured: false, authenticated: false },
+ azureDevOps: {
+ configured: false,
+ authenticated: false,
+ tokenConfigured: false,
+ baseUrl: null
+ },
+ gitea: {
+ configured: false,
+ authenticated: false,
+ tokenConfigured: false,
+ baseUrl: null
+ }
+ },
+ preflightStatusChecked: true,
+ preflightStatusContextKey: 'host',
+ preflightStatusError: null,
+ preflightStatusLoading: false,
+ expectedPreflightContextKey: 'host',
+ linearStatus: { connected: false },
+ linearStatusChecked: true,
+ linearStatusContextKey: 'local#0',
+ jiraStatus: { connected: false },
+ jiraStatusChecked: true,
+ jiraStatusContextKey: 'local#0',
+ providerRuntimeContextKey: 'local#0',
+ ...overrides
+ }
+}
+
+describe('deriveIntegrationStepStates', () => {
+ it('starts with review active and tasks upcoming when nothing is connected', () => {
+ expect(
+ deriveIntegrationStepStates({
+ reviewConnected: false,
+ trackerConnected: false,
+ codeHostTaskConnected: false
+ })
+ ).toEqual({ review: 'active', task: 'upcoming', complete: false })
+ })
+
+ it('promotes tasks to active once a non-task review provider connects', () => {
+ expect(
+ deriveIntegrationStepStates({
+ reviewConnected: true,
+ trackerConnected: false,
+ codeHostTaskConnected: false
+ })
+ ).toEqual({ review: 'done', task: 'active', complete: false })
+ })
+
+ it('completes both steps when a dedicated tracker connects', () => {
+ expect(
+ deriveIntegrationStepStates({
+ reviewConnected: true,
+ trackerConnected: true,
+ codeHostTaskConnected: false
+ })
+ ).toEqual({ review: 'done', task: 'done', complete: true })
+ })
+
+ it('completes the task step from a connected code host without a tracker', () => {
+ // GitHub/GitLab issues double as a task source, so a connected code host
+ // resolves step 2 outright instead of asking for an extra acknowledgement.
+ expect(
+ deriveIntegrationStepStates({
+ reviewConnected: true,
+ trackerConnected: false,
+ codeHostTaskConnected: true
+ })
+ ).toEqual({ review: 'done', task: 'done', complete: true })
+ })
+
+ it('ignores the code host for tasks until review is connected', () => {
+ // Step 2 is unreachable until step 1 is done, so the code host alone must
+ // not resolve tasks or complete the flow.
+ expect(
+ deriveIntegrationStepStates({
+ reviewConnected: false,
+ trackerConnected: false,
+ codeHostTaskConnected: true
+ })
+ ).toEqual({ review: 'active', task: 'upcoming', complete: false })
+ })
+
+ it('marks tasks done if a tracker is already connected before a code host', () => {
+ // A pre-existing Linear/Jira connection is a real, truthful task source even
+ // if the user has not yet connected a code host for review.
+ expect(
+ deriveIntegrationStepStates({
+ reviewConnected: false,
+ trackerConnected: true,
+ codeHostTaskConnected: false
+ })
+ ).toEqual({ review: 'active', task: 'done', complete: false })
+ })
+})
+
+describe('deriveIntegrationConnectionStatus', () => {
+ it('does not expose cached GitHub review readiness while preflight is unresolved', () => {
+ const cachedGitHub = {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ }
+ const unresolvedFacts: Partial[] = [
+ { preflightStatus: cachedGitHub, preflightStatusLoading: true },
+ { preflightStatus: cachedGitHub, preflightStatusChecked: false },
+ { preflightStatus: cachedGitHub, preflightStatusContextKey: 'wsl:Ubuntu' }
+ ]
+
+ for (const overrides of unresolvedFacts) {
+ expect(deriveIntegrationConnectionStatus(statusFacts(overrides))).toMatchObject({
+ reviewConnected: false,
+ reviewProviderName: null,
+ reviewChecking: true
+ })
+ }
+ })
+
+ it('treats current preflight errors as settled without exposing cached auth', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ },
+ preflightStatusError: 'failed to check gh'
+ })
+ )
+ ).toMatchObject({
+ reviewConnected: false,
+ reviewProviderName: null,
+ reviewChecking: false,
+ checking: false
+ })
+ })
+
+ it('does not expose cached GitLab review readiness while preflight is stale', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: false, authenticated: false },
+ glab: { installed: true, authenticated: true }
+ },
+ preflightStatusContextKey: 'wsl:Debian'
+ })
+ )
+ ).toMatchObject({
+ reviewConnected: false,
+ reviewProviderName: null,
+ reviewChecking: true
+ })
+ })
+
+ it('does not expose cached Linear or Jira tracker readiness while checks are stale', () => {
+ const staleTrackerFacts: Partial[] = [
+ {
+ linearStatus: { connected: true },
+ linearStatusContextKey: 'runtime:old#0'
+ },
+ {
+ jiraStatus: { connected: true },
+ jiraStatusChecked: false
+ }
+ ]
+
+ for (const overrides of staleTrackerFacts) {
+ expect(deriveIntegrationConnectionStatus(statusFacts(overrides))).toMatchObject({
+ trackerProviderName: null,
+ trackerChecking: true
+ })
+ }
+ })
+
+ it('keeps a current connected tracker usable when the other tracker is stale', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ linearStatus: { connected: true },
+ jiraStatusContextKey: 'runtime:old#0'
+ })
+ )
+ ).toMatchObject({
+ trackerConnected: true,
+ trackerProviderName: 'Linear',
+ trackerChecking: false,
+ checking: false
+ })
+ })
+
+ it('does not report task-source checking when a tracker is usable but preflight is stale', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ },
+ preflightStatusContextKey: 'wsl:Ubuntu',
+ linearStatus: { connected: true }
+ })
+ )
+ ).toMatchObject({
+ reviewConnected: false,
+ trackerConnected: true,
+ trackerProviderName: 'Linear',
+ checking: false
+ })
+ })
+
+ it('exposes provider readiness once the relevant checks are resolved and current', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ },
+ linearStatus: { connected: true }
+ })
+ )
+ ).toMatchObject({
+ reviewConnected: true,
+ reviewProviderName: 'GitHub',
+ codeHostTaskProviderName: 'GitHub',
+ trackerConnected: true,
+ trackerProviderName: 'Linear',
+ // Trackers lead, but the code host stays listed so task summaries do not
+ // under-report what is usable.
+ taskSourceNames: ['Linear', 'GitHub'],
+ checking: false
+ })
+ })
+
+ it('lists every connected task source with trackers before code hosts', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: true, authenticated: true }
+ },
+ linearStatus: { connected: true },
+ jiraStatus: { connected: true }
+ })
+ )
+ ).toMatchObject({
+ taskSourceNames: ['Linear', 'Jira', 'GitHub', 'GitLab']
+ })
+
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ }
+ })
+ )
+ ).toMatchObject({
+ trackerProviderName: null,
+ taskSourceNames: ['GitHub']
+ })
+ })
+
+ it('counts token-backed review providers as review-ready without treating them as task sources', () => {
+ const cases: {
+ name: 'Bitbucket' | 'Azure DevOps' | 'Gitea'
+ preflightStatus: StatusFacts['preflightStatus']
+ }[] = [
+ {
+ name: 'Bitbucket',
+ preflightStatus: {
+ gh: { installed: false, authenticated: false },
+ glab: { installed: false, authenticated: false },
+ bitbucket: { configured: true, authenticated: true }
+ }
+ },
+ {
+ name: 'Azure DevOps',
+ preflightStatus: {
+ gh: { installed: false, authenticated: false },
+ glab: { installed: false, authenticated: false },
+ azureDevOps: {
+ configured: true,
+ authenticated: true,
+ tokenConfigured: true,
+ baseUrl: 'https://dev.azure.com/acme'
+ }
+ }
+ },
+ {
+ name: 'Gitea',
+ preflightStatus: {
+ gh: { installed: false, authenticated: false },
+ glab: { installed: false, authenticated: false },
+ gitea: {
+ configured: true,
+ authenticated: true,
+ tokenConfigured: true,
+ baseUrl: 'https://gitea.example.test/api/v1'
+ }
+ }
+ }
+ ]
+
+ for (const testCase of cases) {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: testCase.preflightStatus
+ })
+ )
+ ).toMatchObject({
+ reviewConnected: true,
+ reviewProviderName: testCase.name,
+ codeHostTaskProviderName: null,
+ trackerConnected: false,
+ trackerProviderName: null,
+ checking: false
+ })
+ }
+ })
+
+ it('does not count failed token-backed review provider auth as review-ready', () => {
+ expect(
+ deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: false, authenticated: false },
+ glab: { installed: false, authenticated: false },
+ azureDevOps: {
+ configured: true,
+ authenticated: false,
+ tokenConfigured: true,
+ baseUrl: 'https://dev.azure.com/acme'
+ },
+ gitea: {
+ configured: true,
+ authenticated: false,
+ tokenConfigured: true,
+ baseUrl: 'https://gitea.example.test/api/v1'
+ }
+ }
+ })
+ )
+ ).toMatchObject({
+ reviewConnected: false,
+ reviewProviderName: null,
+ codeHostTaskProviderName: null
+ })
+ })
+})
+
+describe('deriveCliProviderCardState', () => {
+ it('does not show cached CLI auth as connected while preflight is stale or errored', () => {
+ const connectedCli = { installed: true, authenticated: true }
+
+ expect(
+ deriveCliProviderCardState({
+ cliStatus: connectedCli,
+ preflightStatusAvailable: true,
+ preflightStatusChecked: true,
+ preflightStatusCurrent: false,
+ preflightStatusError: null,
+ preflightStatusLoading: false
+ })
+ ).toBe('checking')
+
+ expect(
+ deriveCliProviderCardState({
+ cliStatus: connectedCli,
+ preflightStatusAvailable: true,
+ preflightStatusChecked: true,
+ preflightStatusCurrent: true,
+ preflightStatusError: 'failed to check gh',
+ preflightStatusLoading: false
+ })
+ ).toBe('unavailable')
+ })
+})
+
+describe('deriveIntegrationFlowState', () => {
+ it('does not complete progress from the code host while tracker facts are unresolved', () => {
+ const status = deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ },
+ linearStatus: { connected: true },
+ linearStatusContextKey: 'runtime:old#0'
+ })
+ )
+
+ expect(
+ deriveIntegrationFlowState({
+ reviewConnected: status.reviewConnected,
+ trackerProviderName: status.trackerProviderName,
+ codeHostTaskProviderName: status.codeHostTaskProviderName,
+ trackerChecking: status.trackerChecking
+ })
+ ).toMatchObject({
+ review: 'done',
+ task: 'active',
+ complete: false
+ })
+ })
+
+ it('completes the flow from a connected code host once tracker checks settle', () => {
+ const status = deriveIntegrationConnectionStatus(
+ statusFacts({
+ preflightStatus: {
+ gh: { installed: true, authenticated: true },
+ glab: { installed: false, authenticated: false }
+ }
+ })
+ )
+
+ expect(
+ deriveIntegrationFlowState({
+ reviewConnected: status.reviewConnected,
+ trackerProviderName: status.trackerProviderName,
+ codeHostTaskProviderName: status.codeHostTaskProviderName,
+ trackerChecking: status.trackerChecking
+ })
+ ).toMatchObject({
+ review: 'done',
+ task: 'done',
+ complete: true,
+ taskResolved: true
+ })
+ })
+
+ it('keeps tracker-before-code-host completion scoped to the task step only', () => {
+ expect(
+ deriveIntegrationFlowState({
+ reviewConnected: false,
+ trackerProviderName: 'Jira',
+ codeHostTaskProviderName: null,
+ trackerChecking: false
+ })
+ ).toMatchObject({
+ review: 'active',
+ task: 'done',
+ complete: false
+ })
+ })
+})
diff --git a/src/renderer/src/components/feature-wall/use-integration-connection-status.ts b/src/renderer/src/components/feature-wall/use-integration-connection-status.ts
new file mode 100644
index 00000000000..7a5202071d9
--- /dev/null
+++ b/src/renderer/src/components/feature-wall/use-integration-connection-status.ts
@@ -0,0 +1,255 @@
+import { useAppStore } from '@/store'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+
+export type IntegrationStepState = 'active' | 'done' | 'upcoming'
+
+// Pure derivation of the two-step flow's step states from connection facts,
+// extracted so the progressive logic is testable without the store or DOM.
+// `codeHostTaskConnected` means a connected code host whose issues double as
+// a task source (GitHub/GitLab), which resolves step 2 without a tracker.
+export function deriveIntegrationStepStates(input: {
+ reviewConnected: boolean
+ trackerConnected: boolean
+ codeHostTaskConnected: boolean
+}): { review: IntegrationStepState; task: IntegrationStepState; complete: boolean } {
+ const review: IntegrationStepState = input.reviewConnected ? 'done' : 'active'
+ // A dedicated tracker resolves tasks outright. The code host only counts
+ // once review is connected, since step 2 is unreachable before then.
+ const taskResolved =
+ input.trackerConnected || (input.reviewConnected && input.codeHostTaskConnected)
+ const task: IntegrationStepState = taskResolved
+ ? 'done'
+ : input.reviewConnected
+ ? 'active'
+ : 'upcoming'
+ return { review, task, complete: input.reviewConnected && taskResolved }
+}
+
+export function deriveIntegrationFlowState(input: {
+ reviewConnected: boolean
+ trackerProviderName: 'Linear' | 'Jira' | null
+ codeHostTaskProviderName: 'GitHub' | 'GitLab' | null
+ trackerChecking: boolean
+}): {
+ review: IntegrationStepState
+ task: IntegrationStepState
+ complete: boolean
+ taskResolved: boolean
+} {
+ const trackerConnected = input.trackerProviderName !== null
+ // The code host resolves the task step only after dedicated tracker facts
+ // have settled for this runtime, so the collapsed summary names the right
+ // completion reason instead of flashing the code-host fallback copy.
+ const codeHostTaskReady = input.codeHostTaskProviderName !== null && !input.trackerChecking
+ const stepStates = deriveIntegrationStepStates({
+ reviewConnected: input.reviewConnected,
+ trackerConnected,
+ codeHostTaskConnected: codeHostTaskReady
+ })
+ return {
+ ...stepStates,
+ taskResolved: stepStates.task === 'done'
+ }
+}
+
+type CliStatus = {
+ installed?: boolean
+ authenticated?: boolean
+}
+
+type BitbucketStatus = {
+ configured?: boolean
+ authenticated?: boolean
+}
+
+type TokenReviewStatus = {
+ configured?: boolean
+ authenticated?: boolean
+ baseUrl?: string | null
+ tokenConfigured?: boolean
+}
+
+type ProviderStatusFacts = {
+ preflightStatus: {
+ gh?: CliStatus
+ glab?: CliStatus
+ bitbucket?: BitbucketStatus
+ azureDevOps?: TokenReviewStatus
+ gitea?: TokenReviewStatus
+ } | null
+ preflightStatusChecked: boolean
+ preflightStatusContextKey: string | null
+ preflightStatusError: string | null
+ preflightStatusLoading: boolean
+ expectedPreflightContextKey: string
+ linearStatus: { connected?: boolean }
+ linearStatusChecked: boolean
+ linearStatusContextKey: string | null
+ jiraStatus: { connected?: boolean }
+ jiraStatusChecked: boolean
+ jiraStatusContextKey: string | null
+ providerRuntimeContextKey: string
+}
+
+export type IntegrationConnectionStatus = {
+ // True once any review provider is connected/configured for this context.
+ reviewConnected: boolean
+ // Display name of the connected review provider, or null while none is.
+ reviewProviderName: 'GitHub' | 'GitLab' | 'Bitbucket' | 'Azure DevOps' | 'Gitea' | null
+ // GitHub/GitLab issues can double as tasks; token/env review providers do not.
+ codeHostTaskProviderName: 'GitHub' | 'GitLab' | null
+ // True once any task source is usable: a code host (its issues double as a
+ // task source) or a dedicated tracker (Linear/Jira).
+ trackerConnected: boolean
+ // Display name of the connected tracker, or null. Code hosts are surfaced
+ // via reviewProviderName, so this only names Linear/Jira.
+ trackerProviderName: 'Linear' | 'Jira' | null
+ // Every connected task source, trackers first, for "Linear and GitHub
+ // connected for tasks" summaries that don't under-report what's usable.
+ taskSourceNames: ('Linear' | 'Jira' | 'GitHub' | 'GitLab')[]
+ // True while the code-host check is unresolved, stale, loading, or errored.
+ reviewChecking: boolean
+ // True while either dedicated tracker check is unresolved or stale.
+ trackerChecking: boolean
+ // True until the underlying provider checks have resolved for this surface.
+ // Callers should treat unknown state as "not connected yet" rather than
+ // flashing summaries.
+ checking: boolean
+}
+
+function isBitbucketReviewConnected(status: BitbucketStatus | undefined): boolean {
+ return status?.configured === true && status.authenticated === true
+}
+
+function isAzureDevOpsReviewConfigured(status: TokenReviewStatus | undefined): boolean {
+ if (status?.configured !== true) {
+ return false
+ }
+ if (status.tokenConfigured === true && status.baseUrl && status.authenticated !== true) {
+ return false
+ }
+ return true
+}
+
+function isGiteaReviewConfigured(status: TokenReviewStatus | undefined): boolean {
+ if (status?.configured !== true) {
+ return false
+ }
+ if (status.tokenConfigured === true && status.authenticated !== true) {
+ return false
+ }
+ return true
+}
+
+export function deriveIntegrationConnectionStatus(
+ facts: ProviderStatusFacts
+): IntegrationConnectionStatus {
+ const preflightCurrent = facts.preflightStatusContextKey === facts.expectedPreflightContextKey
+ const reviewChecking =
+ facts.preflightStatusLoading || !facts.preflightStatusChecked || !preflightCurrent
+ const reviewReadyForConnection = !reviewChecking && facts.preflightStatusError === null
+ const githubConnected =
+ reviewReadyForConnection &&
+ facts.preflightStatus?.gh?.installed === true &&
+ facts.preflightStatus.gh.authenticated === true
+ const gitlabConnected =
+ reviewReadyForConnection &&
+ facts.preflightStatus?.glab?.installed === true &&
+ facts.preflightStatus.glab.authenticated === true
+ const bitbucketConnected =
+ reviewReadyForConnection && isBitbucketReviewConnected(facts.preflightStatus?.bitbucket)
+ const azureDevOpsConnected =
+ reviewReadyForConnection && isAzureDevOpsReviewConfigured(facts.preflightStatus?.azureDevOps)
+ const giteaConnected =
+ reviewReadyForConnection && isGiteaReviewConfigured(facts.preflightStatus?.gitea)
+
+ const linearStatusCurrent = facts.linearStatusContextKey === facts.providerRuntimeContextKey
+ const jiraStatusCurrent = facts.jiraStatusContextKey === facts.providerRuntimeContextKey
+ const linearChecking = !linearStatusCurrent || !facts.linearStatusChecked
+ const jiraChecking = !jiraStatusCurrent || !facts.jiraStatusChecked
+ const linearConnected =
+ !linearChecking && linearStatusCurrent && facts.linearStatus.connected === true
+ const jiraConnected = !jiraChecking && jiraStatusCurrent && facts.jiraStatus.connected === true
+
+ const reviewProviderName = githubConnected
+ ? 'GitHub'
+ : gitlabConnected
+ ? 'GitLab'
+ : bitbucketConnected
+ ? 'Bitbucket'
+ : azureDevOpsConnected
+ ? 'Azure DevOps'
+ : giteaConnected
+ ? 'Gitea'
+ : null
+ const codeHostTaskProviderName = githubConnected ? 'GitHub' : gitlabConnected ? 'GitLab' : null
+ const trackerProviderName = linearConnected ? 'Linear' : jiraConnected ? 'Jira' : null
+ const taskSourceNames: IntegrationConnectionStatus['taskSourceNames'] = [
+ ...(linearConnected ? (['Linear'] as const) : []),
+ ...(jiraConnected ? (['Jira'] as const) : []),
+ ...(githubConnected ? (['GitHub'] as const) : []),
+ ...(gitlabConnected ? (['GitLab'] as const) : [])
+ ]
+ const hasUsableTaskSource = taskSourceNames.length > 0
+ // Why: one resolved task source is enough for parent setup readiness, but the
+ // local "use code host issues" acknowledgement waits until tracker checks
+ // settle so the banner uses the right completion reason.
+ const trackerChecking = trackerProviderName === null && (linearChecking || jiraChecking)
+
+ return {
+ reviewConnected:
+ githubConnected ||
+ gitlabConnected ||
+ bitbucketConnected ||
+ azureDevOpsConnected ||
+ giteaConnected,
+ reviewProviderName,
+ codeHostTaskProviderName,
+ trackerConnected: hasUsableTaskSource,
+ trackerProviderName,
+ taskSourceNames,
+ reviewChecking,
+ trackerChecking,
+ checking: !hasUsableTaskSource && (reviewChecking || trackerChecking)
+ }
+}
+
+// Derives the two-step progressive flow's done-state from real provider
+// connection status, mirroring use-feature-wall-task-source-presentation so a
+// code host counts as both a review source and a task source.
+export function useIntegrationConnectionStatus(): IntegrationConnectionStatus {
+ const preflightStatus = useAppStore((s) => s.preflightStatus)
+ const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
+ const preflightStatusError = useAppStore((s) => s.preflightStatusError)
+ const preflightStatusLoading = useAppStore((s) => s.preflightStatusLoading)
+ const linearStatus = useAppStore((s) => s.linearStatus)
+ const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
+ const linearStatusContextKey = useAppStore((s) => s.linearStatusContextKey)
+ const jiraStatus = useAppStore((s) => s.jiraStatus)
+ const jiraStatusChecked = useAppStore((s) => s.jiraStatusChecked)
+ const jiraStatusContextKey = useAppStore((s) => s.jiraStatusContextKey)
+ const settings = useAppStore((s) => s.settings)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
+
+ const providerRuntimeContextKey = getProviderRuntimeContextKey(settings)
+
+ return deriveIntegrationConnectionStatus({
+ preflightStatus,
+ preflightStatusChecked,
+ preflightStatusContextKey,
+ preflightStatusError,
+ preflightStatusLoading,
+ expectedPreflightContextKey,
+ linearStatus,
+ linearStatusChecked,
+ linearStatusContextKey,
+ jiraStatus,
+ jiraStatusChecked,
+ jiraStatusContextKey,
+ providerRuntimeContextKey
+ })
+}
diff --git a/src/renderer/src/components/jira-connect-dialog.tsx b/src/renderer/src/components/jira-connect-dialog.tsx
new file mode 100644
index 00000000000..eff9f0cde24
--- /dev/null
+++ b/src/renderer/src/components/jira-connect-dialog.tsx
@@ -0,0 +1,249 @@
+import { useId, useState } from 'react'
+import { LoaderCircle, Lock } from 'lucide-react'
+import { useAppStore } from '@/store'
+import { useMountedRef } from '@/hooks/useMountedRef'
+import { Button } from '@/components/ui/button'
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle
+} from '@/components/ui/dialog'
+import { Input } from '@/components/ui/input'
+import { Label } from '@/components/ui/label'
+import { cn } from '@/lib/utils'
+import { hasRemoteProviderRuntime } from '@/lib/provider-runtime-context'
+import { translate } from '@/i18n/i18n'
+
+type JiraConnectDialogProps = {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ onConnected?: () => void
+ overlayClassName?: string
+ contentClassName?: string
+}
+
+type ConnectState = 'idle' | 'connecting' | 'error'
+
+// Why: mirrors the inline Jira connect dialog in TaskPage so the onboarding
+// "Connect integrations" step can reuse the same site URL + email + API token
+// flow without depending on TaskPage's local state.
+export function JiraConnectDialog({
+ open,
+ onOpenChange,
+ onConnected,
+ overlayClassName,
+ contentClassName
+}: JiraConnectDialogProps): React.JSX.Element {
+ const connectJira = useAppStore((s) => s.connectJira)
+ const settings = useAppStore((s) => s.settings)
+ const mountedRef = useMountedRef()
+ const siteUrlId = useId()
+ const emailId = useId()
+ const tokenId = useId()
+ const errorId = useId()
+
+ const [siteUrl, setSiteUrl] = useState('')
+ const [email, setEmail] = useState('')
+ const [apiToken, setApiToken] = useState('')
+ const [connectState, setConnectState] = useState('idle')
+ const [connectError, setConnectError] = useState(null)
+
+ const canSubmit =
+ Boolean(siteUrl.trim()) &&
+ Boolean(email.trim()) &&
+ Boolean(apiToken.trim()) &&
+ connectState !== 'connecting'
+ const credentialStorageCopy = hasRemoteProviderRuntime(settings)
+ ? 'Your token is sent to the selected remote runtime and stored there with runtime-supported encryption.'
+ : 'Your token is stored locally and encrypted when local runtime storage supports it.'
+
+ const clearErrorOnEdit = (): void => {
+ if (connectState === 'error') {
+ setConnectState('idle')
+ setConnectError(null)
+ }
+ }
+
+ const handleOpenChange = (nextOpen: boolean): void => {
+ if (connectState !== 'connecting') {
+ onOpenChange(nextOpen)
+ }
+ }
+
+ const handleConnect = async (): Promise => {
+ const trimmedSite = siteUrl.trim()
+ const trimmedEmail = email.trim()
+ const trimmedToken = apiToken.trim()
+ if (!trimmedSite || !trimmedEmail || !trimmedToken || connectState === 'connecting') {
+ return
+ }
+ setConnectState('connecting')
+ setConnectError(null)
+ try {
+ const result = await connectJira({
+ siteUrl: trimmedSite,
+ email: trimmedEmail,
+ apiToken: trimmedToken
+ })
+ if (!mountedRef.current) {
+ return
+ }
+ if (result.ok) {
+ setSiteUrl('')
+ setEmail('')
+ setApiToken('')
+ setConnectState('idle')
+ onOpenChange(false)
+ onConnected?.()
+ return
+ }
+ setConnectState('error')
+ setConnectError(result.error)
+ } catch (error) {
+ if (mountedRef.current) {
+ setConnectState('error')
+ setConnectError(error instanceof Error ? error.message : 'Connection failed')
+ }
+ }
+ }
+
+ return (
+
+
+
+
+ {translate('auto.components.jira.connect.dialog.8388bdea2b', 'Connect Jira site')}
+
+
+ {translate(
+ 'auto.components.jira.connect.dialog.d785c42b8b',
+ 'Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.'
+ )}
+
+
+ {
+ event.preventDefault()
+ void handleConnect()
+ }}
+ >
+
+
+
+ {translate('auto.components.jira.connect.dialog.e176f9d0c5', 'Jira Cloud site URL')}
+
+ {
+ setSiteUrl(event.target.value)
+ clearErrorOnEdit()
+ }}
+ disabled={connectState === 'connecting'}
+ />
+
+
+
+ {translate('auto.components.jira.connect.dialog.2849ddb295', 'Atlassian email')}
+
+ {
+ setEmail(event.target.value)
+ clearErrorOnEdit()
+ }}
+ disabled={connectState === 'connecting'}
+ />
+
+
+
+ {translate('auto.components.jira.connect.dialog.3d81bf3ab3', 'API token')}
+
+ {
+ setApiToken(event.target.value)
+ clearErrorOnEdit()
+ }}
+ disabled={connectState === 'connecting'}
+ aria-invalid={connectState === 'error'}
+ aria-describedby={connectState === 'error' ? errorId : undefined}
+ />
+
+ {connectState === 'error' && connectError ? (
+
+ {connectError}
+
+ ) : null}
+
+ {translate('auto.components.jira.connect.dialog.8090504a3e', 'Create a token in')}{' '}
+
+ window.api.shell.openUrl(
+ 'https://id.atlassian.com/manage-profile/security/api-tokens'
+ )
+ }
+ >
+ {translate(
+ 'auto.components.jira.connect.dialog.fdd26d81cc',
+ 'Atlassian account settings'
+ )}
+
+ .
+
+
+
+ {credentialStorageCopy}
+
+
+
+ onOpenChange(false)}
+ disabled={connectState === 'connecting'}
+ >
+ {translate('auto.components.jira.connect.dialog.79e7aaed39', 'Cancel')}
+
+
+ {connectState === 'connecting' ? (
+ <>
+
+ {translate('auto.components.jira.connect.dialog.4a2ab52781', 'Verifying…')}
+ >
+ ) : (
+ translate('auto.components.jira.connect.dialog.63ce735809', 'Connect')
+ )}
+
+
+
+
+
+ )
+}
diff --git a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
index b31edc93171..4548743d04a 100644
--- a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
+++ b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx
@@ -41,6 +41,7 @@ import {
} from '@/lib/github-links'
import { lookupSmartGitHubSubmitItem } from '@/lib/smart-github-submit'
import { parseGitLabIssueOrMRLink } from '@/lib/gitlab-links'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
import { cn } from '@/lib/utils'
import { LinearIcon } from '@/components/icons/LinearIcon'
import { JiraIcon } from '@/components/icons/JiraIcon'
@@ -189,6 +190,8 @@ export default function SmartWorkspaceNameField({
listLinearIssues,
preflightStatus,
preflightStatusChecked,
+ preflightStatusContextKey,
+ expectedPreflightContextKey,
refreshPreflightStatus,
searchLinearIssues,
settings
@@ -203,6 +206,8 @@ export default function SmartWorkspaceNameField({
listLinearIssues: s.listLinearIssues,
preflightStatus: s.preflightStatus,
preflightStatusChecked: s.preflightStatusChecked,
+ preflightStatusContextKey: s.preflightStatusContextKey,
+ expectedPreflightContextKey: localPreflightContextKey(getLocalPreflightContext(s)),
refreshPreflightStatus: s.refreshPreflightStatus,
searchLinearIssues: s.searchLinearIssues,
settings: s.settings
@@ -239,13 +244,14 @@ export default function SmartWorkspaceNameField({
link: NonNullable>
matchingRepo: RepoOption | null
} | null>(null)
+ const preflightStatusCurrent = preflightStatusContextKey === expectedPreflightContextKey
const availableTaskProviders = useMemo(
() =>
filterAvailableTaskProviders(['github', 'gitlab', 'linear'], {
- gitlabInstalled: preflightStatus?.glab?.installed === true,
+ gitlabInstalled: preflightStatusCurrent && preflightStatus?.glab?.installed === true,
linearConnected: linearStatus.connected === true
}),
- [linearStatus.connected, preflightStatus?.glab?.installed]
+ [linearStatus.connected, preflightStatus?.glab?.installed, preflightStatusCurrent]
)
const gitlabAvailable = availableTaskProviders.includes('gitlab')
const linearAvailable = availableTaskProviders.includes('linear')
@@ -314,7 +320,7 @@ export default function SmartWorkspaceNameField({
if (disabled || textOnly) {
return
}
- if (!preflightStatusChecked) {
+ if (!preflightStatusChecked || !preflightStatusCurrent) {
void refreshPreflightStatus()
}
if (!linearStatusChecked) {
@@ -325,6 +331,7 @@ export default function SmartWorkspaceNameField({
disabled,
linearStatusChecked,
preflightStatusChecked,
+ preflightStatusCurrent,
refreshPreflightStatus,
textOnly
])
diff --git a/src/renderer/src/components/settings/IntegrationsPane.tsx b/src/renderer/src/components/settings/IntegrationsPane.tsx
index e99a671b301..c2414372ba0 100644
--- a/src/renderer/src/components/settings/IntegrationsPane.tsx
+++ b/src/renderer/src/components/settings/IntegrationsPane.tsx
@@ -1,891 +1,58 @@
-/* eslint-disable max-lines -- Why: this pane co-locates source-host and
- Linear integration cards so the preflight-check + status-badge +
- install/auth-prompt scaffolding lives in one place rather than fanning
- out across per-integration files that would each repeat the same
- pattern. Splitting buys nothing while the surface stays this narrow. */
-import { useEffect, useState } from 'react'
import {
- Github,
- Gitlab,
- GitPullRequestArrow,
- ExternalLink,
- LoaderCircle,
- Terminal,
- Unlink,
- CheckCircle2,
- AlertCircle
-} from 'lucide-react'
-import { useAppStore } from '../../store'
-import { Button } from '../ui/button'
-import { useMountedRef } from '@/hooks/useMountedRef'
-import { LinearApiKeyDialog } from '@/components/linear-api-key-dialog'
-import {
- getPreflightIntegrationStatuses,
- type PreflightRefreshProvider
-} from './integrations-pane-status'
-import { JiraIntegrationCard } from './jira-integration-card'
+ AzureDevOpsIntegrationCard,
+ BitbucketIntegrationCard,
+ GiteaIntegrationCard,
+ GitHubIntegrationCard,
+ GitLabIntegrationCard
+} from './source-control-integration-cards'
+import { JiraIntegrationCard, LinearIntegrationCard } from './task-tracker-integration-cards'
+import { useIntegrationProviderStatusRefresh } from './use-integration-provider-status-refresh'
import { translate } from '@/i18n/i18n'
export { getIntegrationsPaneSearchEntries } from './integrations-search'
-function LinearIcon({ className }: { className?: string }): React.JSX.Element {
- return (
-
-
-
- )
-}
-
export function IntegrationsPane(): React.JSX.Element {
- const linearStatus = useAppStore((s) => s.linearStatus)
- const preflightStatus = useAppStore((s) => s.preflightStatus)
- const disconnectLinear = useAppStore((s) => s.disconnectLinear)
- const disconnectLinearWorkspace = useAppStore((s) => s.disconnectLinearWorkspace)
- const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
- const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
- const testLinearConnection = useAppStore((s) => s.testLinearConnection)
- const linearWorkspaces = linearStatus.workspaces ?? []
- const mountedRef = useMountedRef()
-
- const [refreshingPreflightProviders, setRefreshingPreflightProviders] = useState<
- Set
- >(new Set())
- const [linearDialogOpen, setLinearDialogOpen] = useState(false)
- const [linearTestingWorkspaceId, setLinearTestingWorkspaceId] = useState(null)
- const [linearTestResultByWorkspace, setLinearTestResultByWorkspace] = useState<
- Record
- >({})
-
- useEffect(() => {
- void checkLinearConnection()
- void refreshPreflightStatus()
- }, [checkLinearConnection, refreshPreflightStatus])
-
- const {
- ghStatus,
- glabStatus,
- bitbucketStatus,
- bitbucketAccount,
- azureDevOpsStatus,
- azureDevOpsAccount,
- azureDevOpsBaseUrl,
- giteaStatus,
- giteaAccount,
- giteaBaseUrl
- } = getPreflightIntegrationStatuses(preflightStatus, refreshingPreflightProviders)
-
- const handleLinearDisconnect = async (workspaceId?: string): Promise => {
- await (workspaceId ? disconnectLinearWorkspace(workspaceId) : disconnectLinear())
- if (!mountedRef.current) {
- return
- }
- setLinearTestResultByWorkspace({})
- }
-
- // Why: explicit user-triggered verification. This is the *only* path in
- // settings that decrypts the stored API key, so the macOS Keychain prompt
- // (if the app signature has changed since the item was stored) only
- // appears when the user clicks Test — not just for opening Settings.
- const handleLinearTest = async (workspaceId: string): Promise => {
- setLinearTestingWorkspaceId(workspaceId)
- setLinearTestResultByWorkspace((prev) => {
- const next = { ...prev }
- delete next[workspaceId]
- return next
- })
- const result = await testLinearConnection(workspaceId)
- if (!mountedRef.current) {
- return
- }
- if (result.ok) {
- setLinearTestResultByWorkspace((prev) => ({
- ...prev,
- [workspaceId]: { state: 'ok' }
- }))
- } else {
- setLinearTestResultByWorkspace((prev) => ({
- ...prev,
- [workspaceId]: { state: 'error', error: result.error }
- }))
- }
- setLinearTestingWorkspaceId(null)
- }
-
- const refreshPreflightProvider = (provider: PreflightRefreshProvider): void => {
- setRefreshingPreflightProviders((prev) => new Set(prev).add(provider))
- void refreshPreflightStatus({ force: true }).finally(() => {
- if (!mountedRef.current) {
- return
- }
- setRefreshingPreflightProviders((prev) => {
- if (!prev.has(provider)) {
- return prev
- }
- const next = new Set(prev)
- next.delete(provider)
- return next
- })
- })
- }
-
- const handleRefreshGlab = (): void => refreshPreflightProvider('glab')
-
- const handleRefreshGh = (): void => refreshPreflightProvider('gh')
-
- const handleRefreshBitbucket = (): void => refreshPreflightProvider('bitbucket')
-
- const handleRefreshAzureDevOps = (): void => refreshPreflightProvider('azureDevOps')
-
- const handleRefreshGitea = (): void => refreshPreflightProvider('gitea')
+ useIntegrationProviderStatusRefresh()
return (
-
- {/* GitHub */}
-
-
-
-
-
- {translate('auto.components.settings.IntegrationsPane.70c5f74f36', 'GitHub')}
-
-
- {translate(
- 'auto.components.settings.IntegrationsPane.de6a0d13ab',
- 'Pull requests, issues, and checks via the'
- )}{' '}
-
- {translate('auto.components.settings.IntegrationsPane.f36365ed45', 'gh')}
- {' '}
- {translate('auto.components.settings.IntegrationsPane.ea160a9978', 'CLI.')}
-
-
- {ghStatus === 'checking' ? (
-
- ) : ghStatus === 'connected' ? (
-
- {translate('auto.components.settings.IntegrationsPane.6432f6522e', 'Connected')}
-
- ) : (
-
- {ghStatus === 'not-installed'
- ? translate('auto.components.settings.IntegrationsPane.f7eb5f0b24', 'Not installed')
- : translate(
- 'auto.components.settings.IntegrationsPane.15cf990798',
- 'Not authenticated'
- )}
-
- )}
-
-
- {ghStatus !== 'checking' && ghStatus !== 'connected' && (
-
- {ghStatus === 'not-installed' ? (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.c0c8575e05',
- 'Install the GitHub CLI to enable pull requests, issues, and checks.'
- )}
-
-
- window.api.shell.openUrl('https://cli.github.com')}
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.399cf46867',
- 'Install GitHub CLI'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- ) : (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.09285e9fe6',
- 'The GitHub CLI is installed but not authenticated. Run this command in a terminal:'
- )}
-
-
-
- {translate(
- 'auto.components.settings.IntegrationsPane.51000487c4',
- 'gh auth login'
- )}
-
-
-
- window.api.shell.openUrl('https://cli.github.com/manual/gh_auth_login')
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
+
+
+
+
+ {translate('auto.components.settings.IntegrationsPane.298c65ecac', 'Review providers')}
+
+
+ {translate(
+ 'auto.components.settings.IntegrationsPane.1683acbac4',
+ 'Connect the source hosts Orca can use for pull requests, merge requests, checks, and review status.'
)}
-
- )}
-
-
- {/* GitLab */}
-
-
-
-
-
- {translate('auto.components.settings.IntegrationsPane.513abfe47d', 'GitLab')}
-
-
- {translate(
- 'auto.components.settings.IntegrationsPane.027440e1cb',
- 'Merge requests, issues, todos, and pipelines via the'
- )}{' '}
-
- {translate('auto.components.settings.IntegrationsPane.a3326f6f1b', 'glab')}
- {' '}
- {translate('auto.components.settings.IntegrationsPane.ea160a9978', 'CLI.')}
-
-
- {glabStatus === 'checking' ? (
-
- ) : glabStatus === 'connected' ? (
-
- {translate('auto.components.settings.IntegrationsPane.6432f6522e', 'Connected')}
-
- ) : (
-
- {glabStatus === 'not-installed'
- ? translate('auto.components.settings.IntegrationsPane.f7eb5f0b24', 'Not installed')
- : translate(
- 'auto.components.settings.IntegrationsPane.15cf990798',
- 'Not authenticated'
- )}
-
- )}
+
+
+
- {glabStatus !== 'checking' && glabStatus !== 'connected' && (
-
- {glabStatus === 'not-installed' ? (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.35a3379372',
- 'Install the GitLab CLI to enable merge requests, issues, and pipelines.'
- )}
-
-
-
- window.api.shell.openUrl('https://gitlab.com/gitlab-org/cli#installation')
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.a83cac5726',
- 'Install GitLab CLI'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- ) : (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.05e5245af7',
- 'The GitLab CLI is installed but not authenticated. Run this command in a terminal:'
- )}
-
-
-
- {translate(
- 'auto.components.settings.IntegrationsPane.e74de656ce',
- 'glab auth login'
- )}
-
-
-
- window.api.shell.openUrl(
- 'https://gitlab.com/gitlab-org/cli/-/blob/main/docs/source/auth/login.md'
- )
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
+
+
+
+ {translate('auto.components.settings.IntegrationsPane.70e885705b', 'Task providers')}
+
+
+ {translate(
+ 'auto.components.settings.IntegrationsPane.3ba07f933b',
+ 'Connect issue trackers Orca can use to browse tasks and start workspaces with linked context.'
)}
-
- )}
-
-
- {/* Bitbucket */}
-
-
-
-
-
- {translate('auto.components.settings.IntegrationsPane.8489c0aa49', 'Bitbucket')}
-
-
- {bitbucketStatus === 'connected'
- ? bitbucketAccount
- ? translate(
- 'auto.components.settings.IntegrationsPane.277fc23929',
- '{{value0}} · Pull requests and build statuses',
- { value0: bitbucketAccount }
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.9707523939',
- 'Pull requests and build statuses'
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.0879860c58',
- 'Pull requests and build statuses via Bitbucket Cloud API tokens.'
- )}
-
-
- {bitbucketStatus === 'checking' ? (
-
- ) : bitbucketStatus === 'connected' ? (
-
- {translate('auto.components.settings.IntegrationsPane.6432f6522e', 'Connected')}
-
- ) : (
-
- {bitbucketStatus === 'not-configured'
- ? translate(
- 'auto.components.settings.IntegrationsPane.f92fbf11aa',
- 'Not configured'
- )
- : translate('auto.components.settings.IntegrationsPane.45bf5e6e4b', 'Auth failed')}
-
- )}
+
-
- {bitbucketStatus !== 'checking' && bitbucketStatus !== 'connected' && (
-
- {bitbucketStatus === 'not-configured' ? (
- <>
-
- {translate('auto.components.settings.IntegrationsPane.4ee74d1470', 'Set')}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.b8a7efb3f6',
- 'ORCA_BITBUCKET_EMAIL'
- )}
- {' '}
- {translate('auto.components.settings.IntegrationsPane.a6c2816115', 'and')}{' '}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.44cde4aa01',
- 'ORCA_BITBUCKET_API_TOKEN'
- )}
-
- {translate('auto.components.settings.IntegrationsPane.ce3c58cd63', ', or set')}{' '}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.6e0ff3403e',
- 'ORCA_BITBUCKET_ACCESS_TOKEN'
- )}
-
- .
-
-
-
- window.api.shell.openUrl(
- 'https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/'
- )
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- ) : (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.3c3cf05c63',
- 'Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.'
- )}
-
-
-
- window.api.shell.openUrl(
- 'https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/'
- )
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- )}
-
- )}
-
-
- {/* Azure DevOps */}
-
-
-
-
-
- {translate('auto.components.settings.IntegrationsPane.5efce6953d', 'Azure DevOps')}
-
-
- {azureDevOpsStatus === 'configured'
- ? azureDevOpsAccount
- ? translate(
- 'auto.components.settings.IntegrationsPane.277fc23929',
- '{{value0}} · Pull requests and build statuses',
- { value0: azureDevOpsAccount }
- )
- : azureDevOpsBaseUrl
- ? translate(
- 'auto.components.settings.IntegrationsPane.277fc23929',
- '{{value0}} · Pull requests and build statuses',
- { value0: azureDevOpsBaseUrl }
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.e3d5a24979',
- 'Pull requests and build statuses for detected Azure Repos'
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.6791d7af95',
- 'Pull requests and build statuses via Azure DevOps REST API tokens.'
- )}
-
-
- {azureDevOpsStatus === 'checking' ? (
-
- ) : azureDevOpsStatus === 'configured' ? (
-
- {azureDevOpsAccount
- ? translate('auto.components.settings.IntegrationsPane.6432f6522e', 'Connected')
- : translate('auto.components.settings.IntegrationsPane.e7a961e1c5', 'Configured')}
-
- ) : (
-
- {azureDevOpsStatus === 'not-configured'
- ? translate(
- 'auto.components.settings.IntegrationsPane.f92fbf11aa',
- 'Not configured'
- )
- : translate('auto.components.settings.IntegrationsPane.45bf5e6e4b', 'Auth failed')}
-
- )}
+
+
+
-
- {azureDevOpsStatus !== 'checking' && azureDevOpsStatus !== 'configured' && (
-
- {azureDevOpsStatus === 'not-configured' ? (
- <>
-
- {translate('auto.components.settings.IntegrationsPane.4ee74d1470', 'Set')}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.5ee6ef6405',
- 'ORCA_AZURE_DEVOPS_TOKEN'
- )}
-
- {translate('auto.components.settings.IntegrationsPane.ce3c58cd63', ', or set')}{' '}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.8f960935c1',
- 'ORCA_AZURE_DEVOPS_ACCESS_TOKEN'
- )}
-
- {translate('auto.components.settings.IntegrationsPane.67a9f26a80', '. Set')}{' '}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.ae6b7f5f40',
- 'ORCA_AZURE_DEVOPS_API_BASE_URL'
- )}
- {' '}
- {translate(
- 'auto.components.settings.IntegrationsPane.6f317f5132',
- 'only when Orca cannot derive the API base URL from the git remote.'
- )}
-
-
-
- window.api.shell.openUrl(
- 'https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate'
- )
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- ) : (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.953b7bf6f7',
- 'Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.'
- )}
-
-
-
- window.api.shell.openUrl(
- 'https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/get-pull-requests'
- )
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- )}
-
- )}
-
-
- {/* Gitea */}
-
-
-
-
-
- {translate('auto.components.settings.IntegrationsPane.4ab9b96925', 'Gitea')}
-
-
- {giteaStatus === 'configured'
- ? giteaAccount
- ? translate(
- 'auto.components.settings.IntegrationsPane.1fac9b4910',
- '{{value0}} · Pull requests and commit statuses',
- { value0: giteaAccount }
- )
- : giteaBaseUrl
- ? translate(
- 'auto.components.settings.IntegrationsPane.1fac9b4910',
- '{{value0}} · Pull requests and commit statuses',
- { value0: giteaBaseUrl }
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.6355fe585e',
- 'Pull requests and commit statuses for detected repositories'
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.6bd148dcb5',
- 'Pull requests and commit statuses via the Gitea REST API.'
- )}
-
-
- {giteaStatus === 'checking' ? (
-
- ) : giteaStatus === 'configured' ? (
-
- {giteaAccount
- ? translate('auto.components.settings.IntegrationsPane.6432f6522e', 'Connected')
- : translate('auto.components.settings.IntegrationsPane.e7a961e1c5', 'Configured')}
-
- ) : (
-
- {giteaStatus === 'not-configured'
- ? translate(
- 'auto.components.settings.IntegrationsPane.e1bd5364e6',
- 'Optional setup'
- )
- : translate('auto.components.settings.IntegrationsPane.45bf5e6e4b', 'Auth failed')}
-
- )}
-
-
- {giteaStatus !== 'checking' && giteaStatus !== 'configured' && (
-
- {giteaStatus === 'not-configured' ? (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.d9467ab026',
- 'Public repositories are detected from their git remote. Set'
- )}{' '}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.e678d89e8c',
- 'ORCA_GITEA_TOKEN'
- )}
- {' '}
- {translate(
- 'auto.components.settings.IntegrationsPane.2c0330ec3e',
- 'for private repositories, and set'
- )}{' '}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.6193444689',
- 'ORCA_GITEA_API_BASE_URL'
- )}
- {' '}
- {translate(
- 'auto.components.settings.IntegrationsPane.5a1f86225a',
- 'only when Orca cannot derive the API URL from the remote.'
- )}
-
-
-
- window.api.shell.openUrl('https://docs.gitea.com/next/development/api-usage')
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- ) : (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.1a62c295c6',
- 'Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.'
- )}
-
-
-
- window.api.shell.openUrl('https://docs.gitea.com/next/development/api-usage')
- }
- >
-
- {translate(
- 'auto.components.settings.IntegrationsPane.01f6c7582e',
- 'Learn more'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.4831ba1083', 'Re-check')}
-
-
- >
- )}
-
- )}
-
-
- {/* Linear */}
-
-
-
-
-
- {translate('auto.components.settings.IntegrationsPane.264a9b6128', 'Linear')}
-
-
- {linearStatus.connected
- ? translate(
- 'auto.components.settings.IntegrationsPane.98ded79cd7',
- '{{value0}} workspace{{value1}} connected',
- {
- value0: linearWorkspaces.length,
- value1: linearWorkspaces.length === 1 ? '' : 's'
- }
- )
- : translate(
- 'auto.components.settings.IntegrationsPane.33ae9730a8',
- 'Add Linear access to browse and link issues.'
- )}
-
- {linearStatus.credentialError ? (
-
-
- {linearStatus.credentialError}
-
- ) : null}
-
- {linearStatus.connected ? (
-
- setLinearDialogOpen(true)}>
- {translate(
- 'auto.components.settings.IntegrationsPane.077844591a',
- 'Add workspace access'
- )}
-
-
- {translate('auto.components.settings.IntegrationsPane.6432f6522e', 'Connected')}
-
-
- ) : (
-
setLinearDialogOpen(true)}
- >
- {translate(
- 'auto.components.settings.IntegrationsPane.f5c5246514',
- 'Add Linear access'
- )}
-
- )}
-
-
- {linearStatus.connected && (
-
- {linearWorkspaces.map((workspace) => {
- const testResult = linearTestResultByWorkspace[workspace.id]
- const testing = linearTestingWorkspaceId === workspace.id
- return (
-
-
-
- {workspace.organizationName}
-
-
- {workspace.displayName}
- {workspace.email ? ` · ${workspace.email}` : ''}
-
-
- {testResult?.state === 'ok' ? (
-
-
- {translate(
- 'auto.components.settings.IntegrationsPane.fe4d378dc4',
- 'Verified'
- )}
-
- ) : null}
- {testResult?.state === 'error' ? (
-
-
- {testResult.error}
-
- ) : null}
-
void handleLinearTest(workspace.id)}
- disabled={testing}
- >
- {testing ? (
- <>
-
- {translate(
- 'auto.components.settings.IntegrationsPane.e7b2dd46f9',
- 'Testing…'
- )}
- >
- ) : (
- translate('auto.components.settings.IntegrationsPane.95b9a87e7e', 'Test')
- )}
-
-
void handleLinearDisconnect(workspace.id)}
- aria-label={translate(
- 'auto.components.settings.IntegrationsPane.8e078e480c',
- 'Disconnect {{value0}}',
- { value0: workspace.organizationName }
- )}
- className="rounded-md p-1 text-muted-foreground/50 transition-colors hover:text-destructive"
- >
-
-
-
- )
- })}
-
- {translate(
- 'auto.components.settings.IntegrationsPane.2122e15517',
- 'Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.'
- )}
-
-
- )}
-
-
-
-
-
setLinearTestResultByWorkspace({})}
- />
+
)
}
diff --git a/src/renderer/src/components/settings/cli-source-control-integration-cards.tsx b/src/renderer/src/components/settings/cli-source-control-integration-cards.tsx
new file mode 100644
index 00000000000..33332c451f8
--- /dev/null
+++ b/src/renderer/src/components/settings/cli-source-control-integration-cards.tsx
@@ -0,0 +1,265 @@
+import { ExternalLink, Github, Gitlab, Terminal } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { IntegrationCardDetails, IntegrationCardShell } from './integration-card-shell'
+import { usePreflightCardStatuses } from './source-control-preflight-card-status'
+import { translate } from '@/i18n/i18n'
+
+export function GitHubIntegrationCard(): React.JSX.Element {
+ const { statuses, unavailable, refresh } = usePreflightCardStatuses('gh')
+ const status = unavailable ? 'unavailable' : statuses.ghStatus
+ const connected = status === 'connected'
+
+ return (
+
}
+ name="GitHub"
+ description={
+ <>
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.b4d900e7f1',
+ 'Pull requests, issues, and checks via the'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.6b2cfb52b4',
+ 'gh'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.a47f71e357',
+ 'CLI.'
+ )}
+ >
+ }
+ checking={status === 'checking'}
+ statusTone={connected ? 'connected' : 'attention'}
+ statusLabel={
+ connected
+ ? 'Connected'
+ : status === 'unavailable'
+ ? 'Unavailable'
+ : status === 'not-installed'
+ ? 'Not installed'
+ : 'Not authenticated'
+ }
+ >
+ {status !== 'checking' && !connected ? (
+
+ {status === 'unavailable' ? (
+ <>
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.6f30fc4216',
+ 'GitHub CLI status is not available in this runtime yet.'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.d5b3be8ecd',
+ 'Re-check'
+ )}
+
+ >
+ ) : status === 'not-installed' ? (
+ <>
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.23cb5a0dee',
+ 'Install the GitHub CLI to enable pull requests, issues, and checks.'
+ )}
+
+
+ window.api.shell.openUrl('https://cli.github.com')}
+ >
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.7755c28af5',
+ 'Install GitHub CLI'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.d5b3be8ecd',
+ 'Re-check'
+ )}
+
+
+ >
+ ) : (
+ <>
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.2e44dda68a',
+ 'The GitHub CLI is installed but not authenticated. Run this command in a terminal:'
+ )}
+
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.8d90249d22',
+ 'gh auth login'
+ )}
+
+
+
+ window.api.shell.openUrl('https://cli.github.com/manual/gh_auth_login')
+ }
+ >
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.8cbc39f862',
+ 'Learn more'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.d5b3be8ecd',
+ 'Re-check'
+ )}
+
+
+ >
+ )}
+
+ ) : null}
+
+ )
+}
+
+export function GitLabIntegrationCard(): React.JSX.Element {
+ const { statuses, unavailable, refresh } = usePreflightCardStatuses('glab')
+ const status = unavailable ? 'unavailable' : statuses.glabStatus
+ const connected = status === 'connected'
+
+ return (
+
}
+ name="GitLab"
+ description={
+ <>
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.1f2b347bd3',
+ 'Merge requests, issues, todos, and pipelines via the'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.2a6b359e75',
+ 'glab'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.a47f71e357',
+ 'CLI.'
+ )}
+ >
+ }
+ checking={status === 'checking'}
+ statusTone={connected ? 'connected' : 'attention'}
+ statusLabel={
+ connected
+ ? 'Connected'
+ : status === 'unavailable'
+ ? 'Unavailable'
+ : status === 'not-installed'
+ ? 'Not installed'
+ : 'Not authenticated'
+ }
+ >
+ {status !== 'checking' && !connected ? (
+
+ {status === 'unavailable' ? (
+ <>
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.faddeb763d',
+ 'GitLab CLI status is not available in this runtime yet.'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.d5b3be8ecd',
+ 'Re-check'
+ )}
+
+ >
+ ) : status === 'not-installed' ? (
+ <>
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.b56fd5676a',
+ 'Install the GitLab CLI to enable merge requests, issues, and pipelines.'
+ )}
+
+
+
+ window.api.shell.openUrl('https://gitlab.com/gitlab-org/cli#installation')
+ }
+ >
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.54a640af7a',
+ 'Install GitLab CLI'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.d5b3be8ecd',
+ 'Re-check'
+ )}
+
+
+ >
+ ) : (
+ <>
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.4be0616873',
+ 'The GitLab CLI is installed but not authenticated. Run this command in a terminal:'
+ )}
+
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.707180d09c',
+ 'glab auth login'
+ )}
+
+
+
+ window.api.shell.openUrl(
+ 'https://gitlab.com/gitlab-org/cli/-/blob/main/docs/source/auth/login.md'
+ )
+ }
+ >
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.8cbc39f862',
+ 'Learn more'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.cli.source.control.integration.cards.d5b3be8ecd',
+ 'Re-check'
+ )}
+
+
+ >
+ )}
+
+ ) : null}
+
+ )
+}
diff --git a/src/renderer/src/components/settings/integration-card-shell.tsx b/src/renderer/src/components/settings/integration-card-shell.tsx
new file mode 100644
index 00000000000..898619f96c4
--- /dev/null
+++ b/src/renderer/src/components/settings/integration-card-shell.tsx
@@ -0,0 +1,68 @@
+import { LoaderCircle } from 'lucide-react'
+import { cn } from '@/lib/utils'
+
+export type IntegrationCardStatusTone = 'connected' | 'attention' | 'neutral'
+
+const STATUS_TONE_CLASSES: Record
= {
+ connected: 'border-status-success-border bg-status-success-background text-status-success',
+ attention: 'border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300',
+ neutral: 'border-border bg-background text-muted-foreground'
+}
+
+export function IntegrationCardShell(props: {
+ icon: React.ReactNode
+ name: string
+ description: React.ReactNode
+ statusLabel: string
+ statusTone: IntegrationCardStatusTone
+ checking?: boolean
+ className?: string
+ actions?: React.ReactNode
+ children?: React.ReactNode
+}): React.JSX.Element {
+ return (
+
+
+
{props.icon}
+
+
{props.name}
+
{props.description}
+
+ {props.actions ? (
+
{props.actions}
+ ) : null}
+ {props.checking ? (
+
+ ) : (
+
+ {props.statusLabel}
+
+ )}
+
+ {props.children}
+
+ )
+}
+
+export function IntegrationCardDetails(props: {
+ className?: string
+ children: React.ReactNode
+}): React.JSX.Element {
+ return (
+
+ {props.children}
+
+ )
+}
diff --git a/src/renderer/src/components/settings/jira-integration-card.tsx b/src/renderer/src/components/settings/jira-integration-card.tsx
index 9abdb29c210..bd27b1cc8ed 100644
--- a/src/renderer/src/components/settings/jira-integration-card.tsx
+++ b/src/renderer/src/components/settings/jira-integration-card.tsx
@@ -1,100 +1,47 @@
-import { useEffect, useState } from 'react'
-import { AlertCircle, CheckCircle2, ExternalLink, LoaderCircle, Unlink } from 'lucide-react'
+import { useState } from 'react'
+import { AlertCircle, CheckCircle2, LoaderCircle, Unlink } from 'lucide-react'
+import { JiraConnectDialog } from '@/components/jira-connect-dialog'
import { JiraIcon } from '@/components/icons/JiraIcon'
+import { Button } from '@/components/ui/button'
import { useMountedRef } from '@/hooks/useMountedRef'
+import {
+ getProviderRuntimeContextKey,
+ hasRemoteProviderRuntime
+} from '@/lib/provider-runtime-context'
import { useAppStore } from '@/store'
-import type { JiraSite } from '../../../../shared/types'
-import { Button } from '../ui/button'
-import { Input } from '../ui/input'
+import { IntegrationCardDetails, IntegrationCardShell } from './integration-card-shell'
import { translate } from '@/i18n/i18n'
-type JiraFormMode =
- | { kind: 'add' }
- | {
- kind: 'update'
- site: JiraSite
- }
-
-type JiraTestResult = { state: 'ok' | 'error'; error?: string }
-
-function getJiraSiteLabel(site: JiraSite): string {
- return `${site.displayName} · ${site.email}`
-}
+type VerificationResult = { state: 'ok' | 'error'; error?: string }
export function JiraIntegrationCard(): React.JSX.Element {
const jiraStatus = useAppStore((s) => s.jiraStatus)
+ const jiraStatusChecked = useAppStore((s) => s.jiraStatusChecked)
+ const jiraStatusContextKey = useAppStore((s) => s.jiraStatusContextKey)
const checkJiraConnection = useAppStore((s) => s.checkJiraConnection)
- const connectJira = useAppStore((s) => s.connectJira)
const disconnectJira = useAppStore((s) => s.disconnectJira)
const testJiraConnection = useAppStore((s) => s.testJiraConnection)
+ const settings = useAppStore((s) => s.settings)
const mountedRef = useMountedRef()
- const [formMode, setFormMode] = useState(null)
- const [siteUrlDraft, setSiteUrlDraft] = useState('')
- const [emailDraft, setEmailDraft] = useState('')
- const [apiTokenDraft, setApiTokenDraft] = useState('')
- const [connectState, setConnectState] = useState<'idle' | 'connecting' | 'error'>('idle')
- const [connectError, setConnectError] = useState(null)
+ const [dialogOpen, setDialogOpen] = useState(false)
const [testingSiteId, setTestingSiteId] = useState(null)
- const [testResultBySite, setTestResultBySite] = useState>({})
+ const [testResultBySite, setTestResultBySite] = useState>({})
- const jiraSites = jiraStatus.sites ?? []
+ const contextMatches = jiraStatusContextKey === getProviderRuntimeContextKey(settings)
+ const checking = !contextMatches || !jiraStatusChecked
+ const connected = contextMatches && jiraStatus.connected
+ const sites = jiraStatus.sites ?? []
+ const siteCount = sites.length || (connected ? 1 : 0)
+ const credentialCopy = hasRemoteProviderRuntime(settings)
+ ? 'Connect a Jira Cloud site with your Atlassian email and an API token. Credentials are sent to the selected remote runtime and stored there with runtime-supported encryption.'
+ : 'Connect a Jira Cloud site with your Atlassian email and an API token. Credentials are stored locally and encrypted when local runtime storage supports it.'
- useEffect(() => {
- void checkJiraConnection()
- }, [checkJiraConnection])
-
- const openAddForm = (): void => {
- setFormMode({ kind: 'add' })
- setSiteUrlDraft('')
- setEmailDraft('')
- setApiTokenDraft('')
- setConnectState('idle')
- setConnectError(null)
- }
-
- const openUpdateForm = (site: JiraSite): void => {
- setFormMode({ kind: 'update', site })
- setSiteUrlDraft(site.siteUrl)
- setEmailDraft(site.email)
- setApiTokenDraft('')
- setConnectState('idle')
- setConnectError(null)
- }
-
- const closeForm = (): void => {
- if (connectState === 'connecting') {
- return
- }
- setFormMode(null)
- setConnectError(null)
- setConnectState('idle')
- }
-
- const handleConnect = async (): Promise => {
- const siteUrl = siteUrlDraft.trim()
- const email = emailDraft.trim()
- const apiToken = apiTokenDraft.trim()
- if (!siteUrl || !email || !apiToken) {
- return
- }
- setConnectState('connecting')
- setConnectError(null)
- const result = await connectJira({ siteUrl, email, apiToken })
- if (!mountedRef.current) {
- return
- }
- if (result.ok) {
- setFormMode(null)
- setSiteUrlDraft('')
- setEmailDraft('')
- setApiTokenDraft('')
- setConnectState('idle')
+ const handleDisconnect = async (siteId?: string): Promise => {
+ await disconnectJira(siteId)
+ if (mountedRef.current) {
setTestResultBySite({})
- return
}
- setConnectState('error')
- setConnectError(result.error)
}
const handleTest = async (siteId: string): Promise => {
@@ -115,167 +62,53 @@ export function JiraIntegrationCard(): React.JSX.Element {
setTestingSiteId(null)
}
- const handleDisconnect = async (siteId: string): Promise => {
- await disconnectJira(siteId)
- if (!mountedRef.current) {
- return
- }
- setTestResultBySite((prev) => {
- const next = { ...prev }
- delete next[siteId]
- return next
- })
- }
-
return (
-
-
-
-
-
- {translate('auto.components.settings.jira.integration.card.09742875cd', 'Jira')}
-
-
- {jiraStatus.connected
+ }
+ name="Jira"
+ description={
+ connected
+ ? translate(
+ 'auto.components.settings.task.tracker.integration.cards.9fa04a032e',
+ '{{value0}} site{{value1}} connected',
+ { value0: siteCount, value1: siteCount === 1 ? '' : 's' }
+ )
+ : checking
+ ? translate(
+ 'auto.components.settings.task.tracker.integration.cards.a1093a06c7',
+ 'Checking Jira access before showing setup actions.'
+ )
+ : translate(
+ 'auto.components.settings.task.tracker.integration.cards.7ca5ffffdb',
+ 'Browse, create, and start work from Jira Cloud issues.'
+ )
+ }
+ checking={checking}
+ statusTone={connected ? 'connected' : 'attention'}
+ statusLabel={connected ? 'Connected' : 'Not connected'}
+ actions={
+ !checking ? (
+ setDialogOpen(true)}
+ >
+ {connected
? translate(
- 'auto.components.settings.jira.integration.card.74f3063026',
- '{{value0}} site{{value1}} connected',
- { value0: jiraSites.length, value1: jiraSites.length === 1 ? '' : 's' }
+ 'auto.components.settings.task.tracker.integration.cards.60996beda6',
+ 'Add Jira site'
)
: translate(
- 'auto.components.settings.jira.integration.card.9a9f8d4910',
- 'Connect Jira Cloud to browse, create, and link issues.'
+ 'auto.components.settings.task.tracker.integration.cards.e2ff968276',
+ 'Connect Jira'
)}
-
-
- {jiraStatus.connected ? (
-
-
- {translate('auto.components.settings.jira.integration.card.efaab83c5d', 'Add site')}
-
-
- {translate('auto.components.settings.jira.integration.card.9bb34706ca', 'Connected')}
-
-
- ) : (
-
- {translate('auto.components.settings.jira.integration.card.a28f417220', 'Connect Jira')}
-
- )}
-
-
- {formMode ? (
-
-
- {
- setSiteUrlDraft(e.target.value)
- setConnectError(null)
- setConnectState('idle')
- }}
- disabled={connectState === 'connecting'}
- />
- {
- setEmailDraft(e.target.value)
- setConnectError(null)
- setConnectState('idle')
- }}
- disabled={connectState === 'connecting'}
- />
- {
- setApiTokenDraft(e.target.value)
- setConnectError(null)
- setConnectState('idle')
- }}
- disabled={connectState === 'connecting'}
- />
-
- {connectState === 'error' && connectError ? (
-
{connectError}
- ) : null}
-
-
- window.api.shell.openUrl(
- 'https://id.atlassian.com/manage-profile/security/api-tokens'
- )
- }
- >
-
- {translate(
- 'auto.components.settings.jira.integration.card.1666f8d562',
- 'Create an Atlassian API token'
- )}
-
-
-
- {translate('auto.components.settings.jira.integration.card.5936977fcd', 'Cancel')}
-
- void handleConnect()}
- disabled={
- !siteUrlDraft.trim() ||
- !emailDraft.trim() ||
- !apiTokenDraft.trim() ||
- connectState === 'connecting'
- }
- >
- {connectState === 'connecting' ? (
- <>
-
- {translate(
- 'auto.components.settings.jira.integration.card.d914d7ab70',
- 'Verifying…'
- )}
- >
- ) : formMode.kind === 'update' ? (
- translate(
- 'auto.components.settings.jira.integration.card.33a8b261ee',
- 'Update credentials'
- )
- ) : (
- translate('auto.components.settings.jira.integration.card.2e8bb790fd', 'Connect')
- )}
-
-
-
-
- ) : null}
-
- {jiraStatus.connected ? (
+
+ ) : null
+ }
+ >
+ {connected && sites.length > 0 ? (
- {jiraSites.map((site) => {
+ {sites.map((site) => {
const testResult = testResultBySite[site.id]
const testing = testingSiteId === site.id
return (
@@ -284,16 +117,17 @@ export function JiraIntegrationCard(): React.JSX.Element {
className="flex items-center gap-3 rounded-md border border-border/50 bg-background/60 px-3 py-2"
>
-
- {getJiraSiteLabel(site)}
+
{site.displayName}
+
+ {site.siteUrl}
+ {site.email ? ` · ${site.email}` : ''}
-
{site.siteUrl}
{testResult?.state === 'ok' ? (
-
+
{translate(
- 'auto.components.settings.jira.integration.card.ab350991b8',
+ 'auto.components.settings.task.tracker.integration.cards.a2c0015fb8',
'Verified'
)}
@@ -314,23 +148,23 @@ export function JiraIntegrationCard(): React.JSX.Element {
<>
{translate(
- 'auto.components.settings.jira.integration.card.cec06a0f79',
- 'Testing…'
+ 'auto.components.settings.task.tracker.integration.cards.3e7c10d286',
+ 'Testing...'
)}
>
) : (
- translate('auto.components.settings.jira.integration.card.255bfe98ec', 'Test')
+ translate(
+ 'auto.components.settings.task.tracker.integration.cards.c24e56c532',
+ 'Test'
+ )
)}
- openUpdateForm(site)}>
- {translate('auto.components.settings.jira.integration.card.eaffa454e9', 'Update')}
-
void handleDisconnect(site.id)}
aria-label={translate(
- 'auto.components.settings.jira.integration.card.9046a20d4c',
+ 'auto.components.settings.task.tracker.integration.cards.dd3529015d',
'Disconnect {{value0}}',
- { value0: getJiraSiteLabel(site) }
+ { value0: site.displayName }
)}
className="rounded-md p-1 text-muted-foreground/50 transition-colors hover:text-destructive"
>
@@ -341,12 +175,53 @@ export function JiraIntegrationCard(): React.JSX.Element {
})}
{translate(
- 'auto.components.settings.jira.integration.card.8ff73fef62',
- "Jira tokens are encrypted by the active runtime and stored locally. Re-entering the same site URL and email replaces that site's API token."
+ 'auto.components.settings.task.tracker.integration.cards.8c20e76308',
+ 'Each connected Jira site has one token stored by the active runtime.'
)}
+ ) : connected ? (
+
+
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.8b2408a8e5',
+ 'Jira is connected for this runtime. Re-check if the connected site list looks stale.'
+ )}
+
+
+ void checkJiraConnection()}>
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.c90f2ef419',
+ 'Re-check'
+ )}
+
+ void handleDisconnect()}>
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.disconnect_all',
+ 'Disconnect'
+ )}
+
+
+
+ ) : !checking ? (
+
+ {credentialCopy}
+ void checkJiraConnection()}>
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.c90f2ef419',
+ 'Re-check'
+ )}
+
+
) : null}
-
+
+ setTestResultBySite({})}
+ overlayClassName="z-[110]"
+ contentClassName="z-[120]"
+ />
+
)
}
diff --git a/src/renderer/src/components/settings/source-control-integration-cards.tsx b/src/renderer/src/components/settings/source-control-integration-cards.tsx
new file mode 100644
index 00000000000..f43b1003d43
--- /dev/null
+++ b/src/renderer/src/components/settings/source-control-integration-cards.tsx
@@ -0,0 +1,11 @@
+export {
+ GitHubIntegrationCard,
+ GitLabIntegrationCard
+} from './cli-source-control-integration-cards'
+export { deriveCliProviderCardState } from './source-control-preflight-card-status'
+export type { CliProviderCardState } from './source-control-preflight-card-status'
+export {
+ AzureDevOpsIntegrationCard,
+ BitbucketIntegrationCard,
+ GiteaIntegrationCard
+} from './token-source-control-integration-cards'
diff --git a/src/renderer/src/components/settings/source-control-preflight-card-status.ts b/src/renderer/src/components/settings/source-control-preflight-card-status.ts
new file mode 100644
index 00000000000..b4b3935b535
--- /dev/null
+++ b/src/renderer/src/components/settings/source-control-preflight-card-status.ts
@@ -0,0 +1,95 @@
+import { useState } from 'react'
+import { useMountedRef } from '@/hooks/useMountedRef'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
+import { useAppStore } from '@/store'
+import {
+ getPreflightIntegrationStatuses,
+ type PreflightIntegrationStatuses,
+ type PreflightRefreshProvider
+} from './integrations-pane-status'
+
+type CliStatus = {
+ installed?: boolean
+ authenticated?: boolean
+}
+
+export type CliProviderCardState =
+ | 'checking'
+ | 'connected'
+ | 'not-installed'
+ | 'not-authenticated'
+ | 'unavailable'
+
+export function deriveCliProviderCardState(input: {
+ cliStatus?: CliStatus
+ preflightStatusAvailable: boolean
+ preflightStatusChecked: boolean
+ preflightStatusCurrent: boolean
+ preflightStatusError: string | null
+ preflightStatusLoading: boolean
+}): CliProviderCardState {
+ if (
+ input.preflightStatusLoading ||
+ !input.preflightStatusChecked ||
+ !input.preflightStatusCurrent
+ ) {
+ return 'checking'
+ }
+ if (input.preflightStatusError !== null || !input.preflightStatusAvailable || !input.cliStatus) {
+ return 'unavailable'
+ }
+ if (!input.cliStatus.installed) {
+ return 'not-installed'
+ }
+ return input.cliStatus.authenticated ? 'connected' : 'not-authenticated'
+}
+
+export type PreflightCardStatuses = {
+ statuses: PreflightIntegrationStatuses
+ unavailable: boolean
+ refresh: () => void
+}
+
+export function usePreflightCardStatuses(
+ provider: PreflightRefreshProvider
+): PreflightCardStatuses {
+ const preflightStatus = useAppStore((s) => s.preflightStatus)
+ const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
+ const preflightStatusError = useAppStore((s) => s.preflightStatusError)
+ const preflightStatusLoading = useAppStore((s) => s.preflightStatusLoading)
+ const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
+ const mountedRef = useMountedRef()
+ const [refreshing, setRefreshing] = useState(false)
+ const refreshingProviders: ReadonlySet = refreshing
+ ? new Set([provider])
+ : new Set()
+ const preflightCurrent = preflightStatusContextKey === expectedPreflightContextKey
+ const unavailable =
+ !preflightStatusLoading &&
+ preflightStatusChecked &&
+ preflightCurrent &&
+ preflightStatusError !== null
+ const statusInput =
+ !preflightStatusLoading && preflightStatusChecked && preflightCurrent && !unavailable
+ ? preflightStatus
+ : null
+
+ const refresh = (): void => {
+ setRefreshing(true)
+ void refreshPreflightStatus({ force: true }).finally(() => {
+ if (mountedRef.current) {
+ setRefreshing(false)
+ }
+ })
+ }
+
+ return {
+ statuses: getPreflightIntegrationStatuses(statusInput, refreshingProviders),
+ unavailable,
+ refresh
+ }
+}
diff --git a/src/renderer/src/components/settings/task-tracker-integration-cards.tsx b/src/renderer/src/components/settings/task-tracker-integration-cards.tsx
new file mode 100644
index 00000000000..c73686da024
--- /dev/null
+++ b/src/renderer/src/components/settings/task-tracker-integration-cards.tsx
@@ -0,0 +1,212 @@
+import { useState } from 'react'
+import { AlertCircle, CheckCircle2, LoaderCircle, Unlink } from 'lucide-react'
+import { LinearIcon } from '@/components/icons/LinearIcon'
+import { LinearApiKeyDialog } from '@/components/linear-api-key-dialog'
+import { Button } from '@/components/ui/button'
+import { useMountedRef } from '@/hooks/useMountedRef'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+import { useAppStore } from '@/store'
+import { IntegrationCardDetails, IntegrationCardShell } from './integration-card-shell'
+import { translate } from '@/i18n/i18n'
+
+type VerificationResult = { state: 'ok' | 'error'; error?: string }
+
+export function LinearIntegrationCard(): React.JSX.Element {
+ const linearStatus = useAppStore((s) => s.linearStatus)
+ const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
+ const linearStatusContextKey = useAppStore((s) => s.linearStatusContextKey)
+ const disconnectLinear = useAppStore((s) => s.disconnectLinear)
+ const disconnectLinearWorkspace = useAppStore((s) => s.disconnectLinearWorkspace)
+ const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
+ const testLinearConnection = useAppStore((s) => s.testLinearConnection)
+ const settings = useAppStore((s) => s.settings)
+ const mountedRef = useMountedRef()
+
+ const [dialogOpen, setDialogOpen] = useState(false)
+ const [testingWorkspaceId, setTestingWorkspaceId] = useState(null)
+ const [testResultByWorkspace, setTestResultByWorkspace] = useState<
+ Record
+ >({})
+
+ const contextMatches = linearStatusContextKey === getProviderRuntimeContextKey(settings)
+ const checking = !contextMatches || !linearStatusChecked
+ const connected = contextMatches && linearStatus.connected
+ const workspaces = linearStatus.workspaces ?? []
+
+ const handleDisconnect = async (workspaceId?: string): Promise => {
+ await (workspaceId ? disconnectLinearWorkspace(workspaceId) : disconnectLinear())
+ if (mountedRef.current) {
+ setTestResultByWorkspace({})
+ }
+ }
+
+ // Why: explicit user-triggered verification. This is the only settings path
+ // that decrypts a stored Linear key, avoiding surprise keychain prompts.
+ const handleTest = async (workspaceId: string): Promise => {
+ setTestingWorkspaceId(workspaceId)
+ setTestResultByWorkspace((prev) => {
+ const next = { ...prev }
+ delete next[workspaceId]
+ return next
+ })
+ const result = await testLinearConnection(workspaceId)
+ if (!mountedRef.current) {
+ return
+ }
+ setTestResultByWorkspace((prev) => ({
+ ...prev,
+ [workspaceId]: result.ok ? { state: 'ok' } : { state: 'error', error: result.error }
+ }))
+ setTestingWorkspaceId(null)
+ }
+
+ return (
+ }
+ name="Linear"
+ description={
+ connected
+ ? translate(
+ 'auto.components.settings.task.tracker.integration.cards.e1f5e6424c',
+ '{{value0}} workspace{{value1}} connected',
+ { value0: workspaces.length, value1: workspaces.length === 1 ? '' : 's' }
+ )
+ : checking
+ ? translate(
+ 'auto.components.settings.task.tracker.integration.cards.fe9231215b',
+ 'Checking Linear access before showing setup actions.'
+ )
+ : translate(
+ 'auto.components.settings.task.tracker.integration.cards.eae4a9f16b',
+ 'Add Linear access to browse and link issues.'
+ )
+ }
+ checking={checking}
+ statusTone={connected ? 'connected' : 'attention'}
+ statusLabel={connected ? 'Connected' : 'Not connected'}
+ actions={
+ !checking ? (
+ setDialogOpen(true)}
+ >
+ {connected
+ ? translate(
+ 'auto.components.settings.task.tracker.integration.cards.622c224082',
+ 'Add workspace access'
+ )
+ : translate(
+ 'auto.components.settings.task.tracker.integration.cards.1a12e33fe5',
+ 'Add Linear access'
+ )}
+
+ ) : null
+ }
+ >
+ {connected ? (
+
+ {workspaces.map((workspace) => {
+ const testResult = testResultByWorkspace[workspace.id]
+ const testing = testingWorkspaceId === workspace.id
+ return (
+
+
+
+ {workspace.organizationName}
+
+
+ {workspace.displayName}
+ {workspace.email ? ` · ${workspace.email}` : ''}
+
+
+ {testResult?.state === 'ok' ? (
+
+
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.a2c0015fb8',
+ 'Verified'
+ )}
+
+ ) : null}
+ {testResult?.state === 'error' ? (
+
+
+ {testResult.error}
+
+ ) : null}
+
void handleTest(workspace.id)}
+ disabled={testing}
+ >
+ {testing ? (
+ <>
+
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.3e7c10d286',
+ 'Testing...'
+ )}
+ >
+ ) : (
+ translate(
+ 'auto.components.settings.task.tracker.integration.cards.c24e56c532',
+ 'Test'
+ )
+ )}
+
+
void handleDisconnect(workspace.id)}
+ aria-label={translate(
+ 'auto.components.settings.task.tracker.integration.cards.dd3529015d',
+ 'Disconnect {{value0}}',
+ { value0: workspace.organizationName }
+ )}
+ className="rounded-md p-1 text-muted-foreground/50 transition-colors hover:text-destructive"
+ >
+
+
+
+ )
+ })}
+
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.6224fe9d34',
+ 'Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.'
+ )}
+
+
+ ) : !checking ? (
+
+
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.cef18762a2',
+ 'Add access with a Personal API key from your Linear settings. Full-access keys can see every team the key owner can reach.'
+ )}
+
+ void checkLinearConnection(true)}>
+ {translate(
+ 'auto.components.settings.task.tracker.integration.cards.c90f2ef419',
+ 'Re-check'
+ )}
+
+
+ ) : null}
+
+ setTestResultByWorkspace({})}
+ overlayClassName="z-[110]"
+ contentClassName="z-[120]"
+ />
+
+ )
+}
+
+export { JiraIntegrationCard } from './jira-integration-card'
diff --git a/src/renderer/src/components/settings/token-source-control-integration-cards.tsx b/src/renderer/src/components/settings/token-source-control-integration-cards.tsx
new file mode 100644
index 00000000000..fe83e1e6b62
--- /dev/null
+++ b/src/renderer/src/components/settings/token-source-control-integration-cards.tsx
@@ -0,0 +1,365 @@
+import { ExternalLink, GitPullRequestArrow } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { IntegrationCardDetails, IntegrationCardShell } from './integration-card-shell'
+import { usePreflightCardStatuses } from './source-control-preflight-card-status'
+import { translate } from '@/i18n/i18n'
+
+export function BitbucketIntegrationCard(): React.JSX.Element {
+ const { statuses, unavailable, refresh } = usePreflightCardStatuses('bitbucket')
+ const status = unavailable ? 'unavailable' : statuses.bitbucketStatus
+ const connected = status === 'connected'
+
+ return (
+ }
+ name="Bitbucket"
+ description={
+ connected
+ ? statuses.bitbucketAccount
+ ? translate(
+ 'auto.components.settings.token.source.control.integration.cards.ea204f5e03',
+ '{{value0}} · Pull requests and build statuses',
+ { value0: statuses.bitbucketAccount }
+ )
+ : translate(
+ 'auto.components.settings.token.source.control.integration.cards.0fa5629dad',
+ 'Pull requests and build statuses'
+ )
+ : translate(
+ 'auto.components.settings.token.source.control.integration.cards.a924e8dcd1',
+ 'Pull requests and build statuses via Bitbucket Cloud API tokens.'
+ )
+ }
+ checking={status === 'checking'}
+ statusTone={connected ? 'connected' : 'attention'}
+ statusLabel={
+ connected
+ ? 'Connected'
+ : status === 'unavailable'
+ ? 'Unavailable'
+ : status === 'not-configured'
+ ? 'Not configured'
+ : 'Auth failed'
+ }
+ >
+ {status !== 'checking' && !connected ? (
+
+
+ {status === 'unavailable' ? (
+ translate(
+ 'auto.components.settings.token.source.control.integration.cards.24ac1c69dc',
+ 'Bitbucket status is not available in this runtime yet.'
+ )
+ ) : status === 'not-configured' ? (
+ <>
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.7bbc9c64f0',
+ 'Set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.63a7f47392',
+ 'ORCA_BITBUCKET_EMAIL'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.fc71a0e7aa',
+ 'and'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.19416c874c',
+ 'ORCA_BITBUCKET_API_TOKEN'
+ )}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.087feb92f1',
+ ', or set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.e63fe8f627',
+ 'ORCA_BITBUCKET_ACCESS_TOKEN'
+ )}
+
+ .
+ >
+ ) : (
+ translate(
+ 'auto.components.settings.token.source.control.integration.cards.6154b02093',
+ 'Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.'
+ )
+ )}
+
+
+
+ window.api.shell.openUrl(
+ 'https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/'
+ )
+ }
+ >
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.1a9475dace',
+ 'Learn more'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.793a06e899',
+ 'Re-check'
+ )}
+
+
+
+ ) : null}
+
+ )
+}
+
+export function AzureDevOpsIntegrationCard(): React.JSX.Element {
+ const { statuses, unavailable, refresh } = usePreflightCardStatuses('azureDevOps')
+ const status = unavailable ? 'unavailable' : statuses.azureDevOpsStatus
+ const configured = status === 'configured'
+
+ return (
+ }
+ name="Azure DevOps"
+ description={
+ configured
+ ? statuses.azureDevOpsAccount
+ ? translate(
+ 'auto.components.settings.token.source.control.integration.cards.ea204f5e03',
+ '{{value0}} · Pull requests and build statuses',
+ { value0: statuses.azureDevOpsAccount }
+ )
+ : statuses.azureDevOpsBaseUrl
+ ? translate(
+ 'auto.components.settings.token.source.control.integration.cards.ea204f5e03',
+ '{{value0}} · Pull requests and build statuses',
+ { value0: statuses.azureDevOpsBaseUrl }
+ )
+ : translate(
+ 'auto.components.settings.token.source.control.integration.cards.54636c65d4',
+ 'Pull requests and build statuses for detected Azure Repos'
+ )
+ : translate(
+ 'auto.components.settings.token.source.control.integration.cards.0eb50d5593',
+ 'Pull requests and build statuses via Azure DevOps REST API tokens.'
+ )
+ }
+ checking={status === 'checking'}
+ statusTone={configured ? 'connected' : 'attention'}
+ statusLabel={
+ configured
+ ? statuses.azureDevOpsAccount
+ ? 'Connected'
+ : 'Configured'
+ : status === 'unavailable'
+ ? 'Unavailable'
+ : status === 'not-configured'
+ ? 'Not configured'
+ : 'Auth failed'
+ }
+ >
+ {status !== 'checking' && !configured ? (
+
+
+ {status === 'unavailable' ? (
+ translate(
+ 'auto.components.settings.token.source.control.integration.cards.f3f47dc7de',
+ 'Azure DevOps status is not available in this runtime yet.'
+ )
+ ) : status === 'not-configured' ? (
+ <>
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.7bbc9c64f0',
+ 'Set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.48842720d2',
+ 'ORCA_AZURE_DEVOPS_TOKEN'
+ )}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.087feb92f1',
+ ', or set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.fbfd237f5e',
+ 'ORCA_AZURE_DEVOPS_ACCESS_TOKEN'
+ )}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.b8a10b07c1',
+ '. Set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.186a6689df',
+ 'ORCA_AZURE_DEVOPS_API_BASE_URL'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.7bd345e3f6',
+ 'only when Orca cannot derive the API base URL from the git remote.'
+ )}
+ >
+ ) : (
+ translate(
+ 'auto.components.settings.token.source.control.integration.cards.40f678df73',
+ 'Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.'
+ )
+ )}
+
+
+
+ window.api.shell.openUrl(
+ status === 'not-configured'
+ ? 'https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate'
+ : 'https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/get-pull-requests'
+ )
+ }
+ >
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.1a9475dace',
+ 'Learn more'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.793a06e899',
+ 'Re-check'
+ )}
+
+
+
+ ) : null}
+
+ )
+}
+
+export function GiteaIntegrationCard(): React.JSX.Element {
+ const { statuses, unavailable, refresh } = usePreflightCardStatuses('gitea')
+ const status = unavailable ? 'unavailable' : statuses.giteaStatus
+ const configured = status === 'configured'
+
+ return (
+ }
+ name="Gitea"
+ description={
+ configured
+ ? statuses.giteaAccount
+ ? translate(
+ 'auto.components.settings.token.source.control.integration.cards.0b5242f8a2',
+ '{{value0}} · Pull requests and commit statuses',
+ { value0: statuses.giteaAccount }
+ )
+ : statuses.giteaBaseUrl
+ ? translate(
+ 'auto.components.settings.token.source.control.integration.cards.0b5242f8a2',
+ '{{value0}} · Pull requests and commit statuses',
+ { value0: statuses.giteaBaseUrl }
+ )
+ : translate(
+ 'auto.components.settings.token.source.control.integration.cards.52f75876be',
+ 'Pull requests and commit statuses for detected repositories'
+ )
+ : translate(
+ 'auto.components.settings.token.source.control.integration.cards.05863d2599',
+ 'Pull requests and commit statuses via the Gitea REST API.'
+ )
+ }
+ checking={status === 'checking'}
+ statusTone={configured ? 'connected' : 'attention'}
+ statusLabel={
+ configured
+ ? statuses.giteaAccount
+ ? 'Connected'
+ : 'Configured'
+ : status === 'unavailable'
+ ? 'Unavailable'
+ : status === 'not-configured'
+ ? 'Optional setup'
+ : 'Auth failed'
+ }
+ >
+ {status !== 'checking' && !configured ? (
+
+
+ {status === 'unavailable' ? (
+ translate(
+ 'auto.components.settings.token.source.control.integration.cards.0613928cb3',
+ 'Gitea status is not available in this runtime yet.'
+ )
+ ) : status === 'not-configured' ? (
+ <>
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.fcbe0469fd',
+ 'Public repositories are detected from their git remote. Set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.6d5c2a3005',
+ 'ORCA_GITEA_TOKEN'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.6da9dfa5de',
+ 'for private repositories, and set'
+ )}{' '}
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.709057ad91',
+ 'ORCA_GITEA_API_BASE_URL'
+ )}
+ {' '}
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.60708f23da',
+ 'only when Orca cannot derive the API URL from the remote.'
+ )}
+ >
+ ) : (
+ translate(
+ 'auto.components.settings.token.source.control.integration.cards.19fb419c12',
+ 'Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.'
+ )
+ )}
+
+
+
+ window.api.shell.openUrl('https://docs.gitea.com/next/development/api-usage')
+ }
+ >
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.1a9475dace',
+ 'Learn more'
+ )}
+
+
+ {translate(
+ 'auto.components.settings.token.source.control.integration.cards.793a06e899',
+ 'Re-check'
+ )}
+
+
+
+ ) : null}
+
+ )
+}
diff --git a/src/renderer/src/components/settings/use-integration-provider-status-refresh.ts b/src/renderer/src/components/settings/use-integration-provider-status-refresh.ts
new file mode 100644
index 00000000000..465477d3ade
--- /dev/null
+++ b/src/renderer/src/components/settings/use-integration-provider-status-refresh.ts
@@ -0,0 +1,51 @@
+import { useEffect } from 'react'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+import { useAppStore } from '@/store'
+
+export function useIntegrationProviderStatusRefresh(): void {
+ const settings = useAppStore((s) => s.settings)
+ const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
+ const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
+ const linearStatusContextKey = useAppStore((s) => s.linearStatusContextKey)
+ const jiraStatusChecked = useAppStore((s) => s.jiraStatusChecked)
+ const jiraStatusContextKey = useAppStore((s) => s.jiraStatusContextKey)
+ const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
+ const checkJiraConnection = useAppStore((s) => s.checkJiraConnection)
+ const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
+ const providerRuntimeContextKey = getProviderRuntimeContextKey(settings)
+ const preflightStatusCurrent = preflightStatusContextKey === expectedPreflightContextKey
+ const linearStatusCurrent = linearStatusContextKey === providerRuntimeContextKey
+ const jiraStatusCurrent = jiraStatusContextKey === providerRuntimeContextKey
+
+ useEffect(() => {
+ if (!linearStatusCurrent || !linearStatusChecked) {
+ void checkLinearConnection()
+ }
+ if (!jiraStatusCurrent || !jiraStatusChecked) {
+ void checkJiraConnection()
+ }
+ if (!preflightStatusCurrent || !preflightStatusChecked) {
+ void refreshPreflightStatus()
+ }
+ }, [
+ checkJiraConnection,
+ checkLinearConnection,
+ jiraStatusChecked,
+ jiraStatusCurrent,
+ jiraStatusContextKey,
+ linearStatusChecked,
+ linearStatusCurrent,
+ linearStatusContextKey,
+ expectedPreflightContextKey,
+ preflightStatusChecked,
+ preflightStatusContextKey,
+ preflightStatusCurrent,
+ providerRuntimeContextKey,
+ refreshPreflightStatus
+ ])
+}
diff --git a/src/renderer/src/components/setup-guide/setup-guide-progress-readiness.ts b/src/renderer/src/components/setup-guide/setup-guide-progress-readiness.ts
index dfa4f7dae70..f74ffeaa612 100644
--- a/src/renderer/src/components/setup-guide/setup-guide-progress-readiness.ts
+++ b/src/renderer/src/components/setup-guide/setup-guide-progress-readiness.ts
@@ -13,6 +13,7 @@ export type SetupGuideProgressReadinessInput = {
settingsLoaded: boolean
preflightStatusChecked: boolean
linearStatusChecked: boolean
+ jiraStatusChecked: boolean
browserUseSkillDiscoveryLoading: boolean
computerUseSkillDiscoveryLoading: boolean
orchestrationSkillDiscoveryLoading: boolean
@@ -82,6 +83,7 @@ export function getSetupGuideProgressReady(input: SetupGuideProgressReadinessInp
input.settingsLoaded &&
input.preflightStatusChecked &&
input.linearStatusChecked &&
+ input.jiraStatusChecked &&
!input.browserUseSkillDiscoveryLoading &&
!input.computerUseSkillDiscoveryLoading &&
!input.orchestrationSkillDiscoveryLoading &&
diff --git a/src/renderer/src/components/setup-guide/setup-script-probe-cache.ts b/src/renderer/src/components/setup-guide/setup-script-probe-cache.ts
new file mode 100644
index 00000000000..366f41e0e1d
--- /dev/null
+++ b/src/renderer/src/components/setup-guide/setup-script-probe-cache.ts
@@ -0,0 +1,34 @@
+import {
+ INITIAL_SETUP_SCRIPT_PROBE_STATE,
+ type SetupScriptProbeState
+} from './setup-guide-progress-readiness'
+
+// Why: probe results are shared across every mounted setup-guide consumer so a
+// single bounded probe can settle readiness for all of them at once.
+const setupScriptProbeCacheListeners = new Set<() => void>()
+let setupScriptProbeCache = INITIAL_SETUP_SCRIPT_PROBE_STATE
+
+export function readSetupScriptProbeCache(): SetupScriptProbeState {
+ return setupScriptProbeCache
+}
+
+export function subscribeSetupScriptProbeCache(listener: () => void): () => void {
+ setupScriptProbeCacheListeners.add(listener)
+ return () => {
+ setupScriptProbeCacheListeners.delete(listener)
+ }
+}
+
+export function setSetupScriptProbeCache(next: SetupScriptProbeState): void {
+ if (
+ setupScriptProbeCache.signature === next.signature &&
+ setupScriptProbeCache.ready === next.ready &&
+ setupScriptProbeCache.hasSetupScript === next.hasSetupScript
+ ) {
+ return
+ }
+ setupScriptProbeCache = next
+ for (const listener of setupScriptProbeCacheListeners) {
+ listener()
+ }
+}
diff --git a/src/renderer/src/components/setup-guide/use-setup-guide-progress.test.ts b/src/renderer/src/components/setup-guide/use-setup-guide-progress.test.ts
index 48c514b43c5..7062696e74a 100644
--- a/src/renderer/src/components/setup-guide/use-setup-guide-progress.test.ts
+++ b/src/renderer/src/components/setup-guide/use-setup-guide-progress.test.ts
@@ -137,6 +137,7 @@ describe('getSetupGuideProgressReady', () => {
settingsLoaded: true,
preflightStatusChecked: true,
linearStatusChecked: true,
+ jiraStatusChecked: true,
browserUseSkillDiscoveryLoading: false,
computerUseSkillDiscoveryLoading: false,
orchestrationSkillDiscoveryLoading: false,
@@ -194,9 +195,10 @@ describe('getSetupGuideProgressReady', () => {
).toBe(false)
})
- it('waits for preflight and Linear checks', () => {
+ it('waits for preflight, Linear, and Jira checks', () => {
expect(getSetupGuideProgressReady({ ...readyInput, preflightStatusChecked: false })).toBe(false)
expect(getSetupGuideProgressReady({ ...readyInput, linearStatusChecked: false })).toBe(false)
+ expect(getSetupGuideProgressReady({ ...readyInput, jiraStatusChecked: false })).toBe(false)
})
})
diff --git a/src/renderer/src/components/setup-guide/use-setup-guide-progress.ts b/src/renderer/src/components/setup-guide/use-setup-guide-progress.ts
index dab9ef02d4f..96e3673da59 100644
--- a/src/renderer/src/components/setup-guide/use-setup-guide-progress.ts
+++ b/src/renderer/src/components/setup-guide/use-setup-guide-progress.ts
@@ -3,7 +3,9 @@ import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore
import { useAppStore } from '@/store'
import { isGitRepoKind } from '../../../../shared/repo-kind'
import { checkRuntimeHooks } from '@/runtime/runtime-hooks-client'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
import { hasEffectiveSetupCommand } from '@/lib/setup-script-status'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
import {
COMPUTER_USE_SKILL_NAME,
ORCA_CLI_SKILL_NAME,
@@ -17,46 +19,22 @@ import {
getFeatureWallSetupProgress,
type FeatureWallSetupProgress
} from '../feature-wall/feature-wall-setup-progress'
+import { deriveIntegrationConnectionStatus } from '../feature-wall/use-integration-connection-status'
import { useSetupGuideBrowserMilestoneProgress } from './setup-guide-browser-milestone-progress'
import {
getComputerUsePermissionSetupState,
getCurrentSetupScriptProbeState,
getSetupGuideProgressReady,
- getSetupScriptProbeSignature,
- INITIAL_SETUP_SCRIPT_PROBE_STATE,
- type SetupScriptProbeState
+ getSetupScriptProbeSignature
} from './setup-guide-progress-readiness'
+import {
+ readSetupScriptProbeCache,
+ setSetupScriptProbeCache,
+ subscribeSetupScriptProbeCache
+} from './setup-script-probe-cache'
const SETUP_SCRIPT_PROBE_SETTLE_TIMEOUT_MS = 15_000
-const setupScriptProbeCacheListeners = new Set<() => void>()
-let setupScriptProbeCache = INITIAL_SETUP_SCRIPT_PROBE_STATE
-
-function readSetupScriptProbeCache(): SetupScriptProbeState {
- return setupScriptProbeCache
-}
-
-function subscribeSetupScriptProbeCache(listener: () => void): () => void {
- setupScriptProbeCacheListeners.add(listener)
- return () => {
- setupScriptProbeCacheListeners.delete(listener)
- }
-}
-
-function setSetupScriptProbeCache(next: SetupScriptProbeState): void {
- if (
- setupScriptProbeCache.signature === next.signature &&
- setupScriptProbeCache.ready === next.ready &&
- setupScriptProbeCache.hasSetupScript === next.hasSetupScript
- ) {
- return
- }
- setupScriptProbeCache = next
- for (const listener of setupScriptProbeCacheListeners) {
- listener()
- }
-}
-
export function useSetupGuideProgress(
shouldRefreshCoreState: boolean,
orchestrationSkillInstalled: boolean,
@@ -69,12 +47,23 @@ export function useSetupGuideProgress(
const terminalLayoutsByTabId = useAppStore((s) => s.terminalLayoutsByTabId)
const preflightStatus = useAppStore((s) => s.preflightStatus)
const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
+ const preflightStatusError = useAppStore((s) => s.preflightStatusError)
+ const preflightStatusLoading = useAppStore((s) => s.preflightStatusLoading)
const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
const linearStatus = useAppStore((s) => s.linearStatus)
const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
+ const linearStatusContextKey = useAppStore((s) => s.linearStatusContextKey)
const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
+ const jiraStatus = useAppStore((s) => s.jiraStatus)
+ const jiraStatusChecked = useAppStore((s) => s.jiraStatusChecked)
+ const jiraStatusContextKey = useAppStore((s) => s.jiraStatusContextKey)
+ const checkJiraConnection = useAppStore((s) => s.checkJiraConnection)
const repos = useAppStore((s) => s.repos)
const activeRepoId = useAppStore((s) => s.activeRepoId)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
const setupScriptProbe = useSyncExternalStore(
subscribeSetupScriptProbeCache,
readSetupScriptProbeCache,
@@ -101,21 +90,38 @@ export function useSetupGuideProgress(
enabled: shouldRefreshCoreState,
sourceKinds: GLOBAL_AGENT_SKILL_SOURCE_KINDS
})
+ const providerRuntimeContextKey = getProviderRuntimeContextKey(settings)
+ const linearStatusCurrent = linearStatusContextKey === providerRuntimeContextKey
+ const jiraStatusCurrent = jiraStatusContextKey === providerRuntimeContextKey
+ const preflightStatusCurrent = preflightStatusContextKey === expectedPreflightContextKey
useEffect(() => {
if (!shouldRefreshCoreState) {
return
}
- if (!preflightStatusChecked) {
+ if (!preflightStatusCurrent || !preflightStatusChecked) {
void refreshPreflightStatus()
}
- if (!linearStatusChecked) {
+ if (!linearStatusCurrent || !linearStatusChecked) {
void checkLinearConnection()
}
+ if (!jiraStatusCurrent || !jiraStatusChecked) {
+ void checkJiraConnection()
+ }
}, [
+ checkJiraConnection,
checkLinearConnection,
+ jiraStatusCurrent,
+ jiraStatusChecked,
+ jiraStatusContextKey,
+ linearStatusCurrent,
linearStatusChecked,
+ linearStatusContextKey,
+ expectedPreflightContextKey,
+ preflightStatusContextKey,
+ preflightStatusCurrent,
preflightStatusChecked,
+ providerRuntimeContextKey,
refreshPreflightStatus,
shouldRefreshCoreState
])
@@ -185,6 +191,7 @@ export function useSetupGuideProgress(
return
}
const permissionState = getComputerUsePermissionSetupState(status)
+ // oxlint-disable-next-line react-doctor/no-adjust-state-on-prop-change -- Why: async permission checks update setup progress after external OS state changes.
setComputerUsePermissionStatusChecked(true)
setComputerUsePermissionsReady(permissionState.ready)
setComputerUseUnavailable(permissionState.unavailable)
@@ -192,12 +199,18 @@ export function useSetupGuideProgress(
useEffect(() => {
if (!shouldRefreshCoreState || !computerUseSkillInstalled) {
+ // Why: unavailable setup-guide steps must clear stale permission state before
+ // readiness is derived for the visible checklist.
+ setComputerUsePermissionStatusChecked(false)
+ setComputerUsePermissionsReady(false)
+ setComputerUseUnavailable(false)
return
}
let stale = false
const refreshComputerUsePermissions = (): void => {
void readComputerUsePermissions(() => stale)
}
+ // oxlint-disable-next-line react-doctor/no-adjust-state-on-prop-change -- Why: refresh the setup checklist when the permission step becomes active.
refreshComputerUsePermissions()
const handleFocus = (): void => {
void refreshComputerUsePermissions()
@@ -218,10 +231,22 @@ export function useSetupGuideProgress(
}
}, [computerUseSkillInstalled, readComputerUsePermissions, shouldRefreshCoreState])
- const hasConnectedTaskSource =
- (preflightStatus?.gh.installed === true && preflightStatus.gh.authenticated === true) ||
- (preflightStatus?.glab?.installed === true && preflightStatus.glab.authenticated === true) ||
- linearStatus.connected === true
+ const taskSourceStatus = deriveIntegrationConnectionStatus({
+ preflightStatus,
+ preflightStatusChecked,
+ preflightStatusContextKey,
+ preflightStatusError,
+ preflightStatusLoading,
+ expectedPreflightContextKey,
+ linearStatus,
+ linearStatusChecked,
+ linearStatusContextKey,
+ jiraStatus,
+ jiraStatusChecked,
+ jiraStatusContextKey,
+ providerRuntimeContextKey
+ })
+ const hasConnectedTaskSource = taskSourceStatus.trackerConnected
const gitRepoCount = orderedGitRepos.length
const currentSetupScriptProbe = getCurrentSetupScriptProbeState(
setupScriptProbe,
@@ -236,8 +261,11 @@ export function useSetupGuideProgress(
const ready = getSetupGuideProgressReady({
refreshEnabled: shouldRefreshCoreState,
settingsLoaded: settings !== null,
- preflightStatusChecked,
- linearStatusChecked,
+ // Why: task-source readiness is a capability group. Once any provider is
+ // usable, unrelated stale provider checks should not hide setup progress.
+ preflightStatusChecked: !taskSourceStatus.checking,
+ linearStatusChecked: true,
+ jiraStatusChecked: true,
browserUseSkillDiscoveryLoading: detectedBrowserUseSkillLoading,
computerUseSkillDiscoveryLoading: computerUseSkillLoading,
orchestrationSkillDiscoveryLoading: detectedOrchestrationSkillLoading,
diff --git a/src/renderer/src/components/sidebar/SidebarNav.tsx b/src/renderer/src/components/sidebar/SidebarNav.tsx
index 5c8b50ade67..8071ae40f86 100644
--- a/src/renderer/src/components/sidebar/SidebarNav.tsx
+++ b/src/renderer/src/components/sidebar/SidebarNav.tsx
@@ -15,6 +15,7 @@ import {
} from '../../../../shared/task-providers'
import { useActivityUnreadCount } from '@/components/activity/useActivityUnreadCount'
import { useShortcutLabel } from '@/hooks/useShortcutLabel'
+import { getLocalPreflightContext, localPreflightContextKey } from '@/lib/local-preflight-context'
import { useMobileSidebarOnboardingBadge } from './mobile-sidebar-onboarding-badge'
import {
ContextMenu,
@@ -108,7 +109,11 @@ const SidebarNav = React.memo(function SidebarNav() {
const defaultTaskSource = useAppStore((s) => s.settings?.defaultTaskSource ?? 'github')
const preflightStatus = useAppStore((s) => s.preflightStatus)
const preflightStatusChecked = useAppStore((s) => s.preflightStatusChecked)
+ const preflightStatusContextKey = useAppStore((s) => s.preflightStatusContextKey)
const refreshPreflightStatus = useAppStore((s) => s.refreshPreflightStatus)
+ const expectedPreflightContextKey = useAppStore((s) =>
+ localPreflightContextKey(getLocalPreflightContext(s))
+ )
const linearStatus = useAppStore((s) => s.linearStatus)
const linearStatusChecked = useAppStore((s) => s.linearStatusChecked)
const checkLinearConnection = useAppStore((s) => s.checkLinearConnection)
@@ -119,12 +124,13 @@ const SidebarNav = React.memo(function SidebarNav() {
() => normalizeVisibleTaskProviders(rawVisibleTaskProviders),
[rawVisibleTaskProviders]
)
+ const preflightStatusCurrent = preflightStatusContextKey === expectedPreflightContextKey
const visibleTaskProviders = React.useMemo(
() =>
restoreAvailableDefaultTaskProvider(
preferredVisibleTaskProviders,
{
- gitlabInstalled: preflightStatus?.glab?.installed === true,
+ gitlabInstalled: preflightStatusCurrent && preflightStatus?.glab?.installed === true,
linearConnected: linearStatus.connected === true
},
defaultTaskSource
@@ -133,6 +139,7 @@ const SidebarNav = React.memo(function SidebarNav() {
defaultTaskSource,
linearStatus.connected,
preferredVisibleTaskProviders,
+ preflightStatusCurrent,
preflightStatus?.glab?.installed
]
)
@@ -142,13 +149,19 @@ const SidebarNav = React.memo(function SidebarNav() {
)
React.useEffect(() => {
- if (!preflightStatusChecked) {
+ if (!preflightStatusChecked || !preflightStatusCurrent) {
void refreshPreflightStatus()
}
if (!linearStatusChecked) {
void checkLinearConnection()
}
- }, [checkLinearConnection, linearStatusChecked, preflightStatusChecked, refreshPreflightStatus])
+ }, [
+ checkLinearConnection,
+ linearStatusChecked,
+ preflightStatusChecked,
+ preflightStatusCurrent,
+ refreshPreflightStatus
+ ])
// Why: warm the GitHub work-item cache on hover/focus so by the time the
// user's click finishes the round-trip has either completed or is already
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index a7597e98752..693d49f8310 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -232,6 +232,12 @@
"ui": {
"66e3bd7ce6": "Sent to {{value0}}",
"53883b7bc3": "Couldn't send to {{value0}}"
+ },
+ "jira": {
+ "856083302c": "Jira connection was superseded by a newer request."
+ },
+ "linear": {
+ "37d36984d0": "Linear connection was superseded by a newer request."
}
}
},
@@ -4580,7 +4586,11 @@
"9707523939": "Pull requests and build statuses",
"a565377c38": "not-installed",
"15cf990798": "Not authenticated",
- "f7eb5f0b24": "Not installed"
+ "f7eb5f0b24": "Not installed",
+ "3ba07f933b": "Connect issue trackers Orca can use to browse tasks and start workspaces with linked context.",
+ "70e885705b": "Task providers",
+ "1683acbac4": "Connect the source hosts Orca can use for pull requests, merge requests, checks, and review status.",
+ "298c65ecac": "Review providers"
},
"KagiSessionLinkForm": {
"92f0b4e472": "Clear",
@@ -7274,6 +7284,103 @@
"agent-generated-tab-title-copy": {
"19ad21615a": "Auto-generate tab titles",
"b036c7a409": "Derive short stable tab names from the first known agent prompt. Manual renames always win."
+ },
+ "cli": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "d5b3be8ecd": "Re-check",
+ "8cbc39f862": "Learn more",
+ "707180d09c": "glab auth login",
+ "4be0616873": "The GitLab CLI is installed but not authenticated. Run this command in a terminal:",
+ "54a640af7a": "Install GitLab CLI",
+ "b56fd5676a": "Install the GitLab CLI to enable merge requests, issues, and pipelines.",
+ "faddeb763d": "GitLab CLI status is not available in this runtime yet.",
+ "a47f71e357": "CLI.",
+ "2a6b359e75": "glab",
+ "1f2b347bd3": "Merge requests, issues, todos, and pipelines via the",
+ "8d90249d22": "gh auth login",
+ "2e44dda68a": "The GitHub CLI is installed but not authenticated. Run this command in a terminal:",
+ "7755c28af5": "Install GitHub CLI",
+ "23cb5a0dee": "Install the GitHub CLI to enable pull requests, issues, and checks.",
+ "6f30fc4216": "GitHub CLI status is not available in this runtime yet.",
+ "6b2cfb52b4": "gh",
+ "b4d900e7f1": "Pull requests, issues, and checks via the"
+ }
+ }
+ }
+ }
+ },
+ "task": {
+ "tracker": {
+ "integration": {
+ "cards": {
+ "c90f2ef419": "Re-check",
+ "dd3529015d": "Disconnect {{value0}}",
+ "8b2408a8e5": "Jira is connected for this runtime. Re-check if the connected site list looks stale.",
+ "8c20e76308": "Each connected Jira site has one token stored by the active runtime.",
+ "c24e56c532": "Test",
+ "3e7c10d286": "Testing...",
+ "a2c0015fb8": "Verified",
+ "e2ff968276": "Connect Jira",
+ "60996beda6": "Add Jira site",
+ "7ca5ffffdb": "Browse, create, and start work from Jira Cloud issues.",
+ "a1093a06c7": "Checking Jira access before showing setup actions.",
+ "9fa04a032e": "{{value0}} site{{value1}} connected",
+ "cef18762a2": "Add access with a Personal API key from your Linear settings. Full-access keys can see every team the key owner can reach.",
+ "6224fe9d34": "Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.",
+ "1a12e33fe5": "Add Linear access",
+ "622c224082": "Add workspace access",
+ "eae4a9f16b": "Add Linear access to browse and link issues.",
+ "fe9231215b": "Checking Linear access before showing setup actions.",
+ "e1f5e6424c": "{{value0}} workspace{{value1}} connected",
+ "disconnect_all": "Disconnect"
+ }
+ }
+ }
+ },
+ "token": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "793a06e899": "Re-check",
+ "1a9475dace": "Learn more",
+ "19fb419c12": "Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "60708f23da": "only when Orca cannot derive the API URL from the remote.",
+ "709057ad91": "ORCA_GITEA_API_BASE_URL",
+ "6da9dfa5de": "for private repositories, and set",
+ "6d5c2a3005": "ORCA_GITEA_TOKEN",
+ "fcbe0469fd": "Public repositories are detected from their git remote. Set",
+ "0613928cb3": "Gitea status is not available in this runtime yet.",
+ "05863d2599": "Pull requests and commit statuses via the Gitea REST API.",
+ "52f75876be": "Pull requests and commit statuses for detected repositories",
+ "0b5242f8a2": "{{value0}} · Pull requests and commit statuses",
+ "40f678df73": "Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "7bd345e3f6": "only when Orca cannot derive the API base URL from the git remote.",
+ "186a6689df": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "b8a10b07c1": ". Set",
+ "fbfd237f5e": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "087feb92f1": ", or set",
+ "48842720d2": "ORCA_AZURE_DEVOPS_TOKEN",
+ "7bbc9c64f0": "Set",
+ "f3f47dc7de": "Azure DevOps status is not available in this runtime yet.",
+ "0eb50d5593": "Pull requests and build statuses via Azure DevOps REST API tokens.",
+ "54636c65d4": "Pull requests and build statuses for detected Azure Repos",
+ "ea204f5e03": "{{value0}} · Pull requests and build statuses",
+ "6154b02093": "Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.",
+ "e63fe8f627": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "19416c874c": "ORCA_BITBUCKET_API_TOKEN",
+ "fc71a0e7aa": "and",
+ "63a7f47392": "ORCA_BITBUCKET_EMAIL",
+ "24ac1c69dc": "Bitbucket status is not available in this runtime yet.",
+ "a924e8dcd1": "Pull requests and build statuses via Bitbucket Cloud API tokens.",
+ "0fa5629dad": "Pull requests and build statuses"
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -8828,6 +8935,30 @@
"b7345c18db": "An unexpected error occurred.",
"5f97caf76b": "Installing…",
"c2df599513": "Install CLI & Skill"
+ },
+ "ConnectIntegrationsList": {
+ "3dddb2d565": "connected for tasks",
+ "33b650af52": "Connect where your team tracks work. Orca starts workspaces with the issue title, link, and context already attached.",
+ "5b3577a492": "connected for review status",
+ "3a1fcdddad": "Two quick steps: connect where your code is reviewed, then where your team plans work.",
+ "list_end": ", and ",
+ "list_pair": " and ",
+ "list_mid": ", ",
+ "code_host_tasks_summary": "issues available as tasks · add Linear or Jira if your team plans work there",
+ "code_host_tasks_caption": "Your code host's issues also work as tasks.",
+ "review_step_title": "See PR status while agents work",
+ "review_step_description": "Connect a review provider so Orca can show PR or MR status, checks, and reviews.",
+ "task_step_title": "Start agents on your tasks without leaving Orca"
+ },
+ "connect": {
+ "integration": {
+ "step": {
+ "0f47ff17c6": "Change",
+ "5538eb6743": "Done",
+ "open_step": "Open",
+ "close_step": "Close"
+ }
+ }
}
},
"tips": {
@@ -10032,6 +10163,25 @@
"8490e5d36a": "Confirm",
"56f5c60e0c": "Cancel"
}
+ },
+ "jira": {
+ "connect": {
+ "dialog": {
+ "63ce735809": "Connect",
+ "4a2ab52781": "Verifying…",
+ "79e7aaed39": "Cancel",
+ "fdd26d81cc": "Atlassian account settings",
+ "8090504a3e": "Create a token in",
+ "7b3967c12f": "Atlassian API token",
+ "3d81bf3ab3": "API token",
+ "e91b9a4073": "you@example.com",
+ "2849ddb295": "Atlassian email",
+ "70fcd360c4": "https://example.atlassian.net",
+ "e176f9d0c5": "Jira Cloud site URL",
+ "d785c42b8b": "Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.",
+ "8388bdea2b": "Connect Jira site"
+ }
+ }
}
},
"i18n": {
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
index cd442f403e2..2f41ecd5eca 100644
--- a/src/renderer/src/i18n/locales/es.json
+++ b/src/renderer/src/i18n/locales/es.json
@@ -232,6 +232,12 @@
"ui": {
"66e3bd7ce6": "Enviado a {{value0}}",
"53883b7bc3": "No se pudo enviar a {{value0}}"
+ },
+ "jira": {
+ "856083302c": "Jira connection was superseded by a newer request."
+ },
+ "linear": {
+ "37d36984d0": "Linear connection was superseded by a newer request."
}
}
},
@@ -4544,7 +4550,11 @@
"9707523939": "Solicitudes de extracción y estados de compilación",
"a565377c38": "no instalado",
"15cf990798": "No autenticado",
- "f7eb5f0b24": "No instalado"
+ "f7eb5f0b24": "No instalado",
+ "3ba07f933b": "Connect issue trackers Orca can use to browse tasks and start workspaces with linked context.",
+ "70e885705b": "Task providers",
+ "1683acbac4": "Connect the source hosts Orca can use for pull requests, merge requests, checks, and review status.",
+ "298c65ecac": "Review providers"
},
"KagiSessionLinkForm": {
"92f0b4e472": "Claro",
@@ -7274,6 +7284,103 @@
},
"YamlThemeImportButton": {
"label": "Import from YAML"
+ },
+ "cli": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "d5b3be8ecd": "Re-check",
+ "8cbc39f862": "Learn more",
+ "707180d09c": "glab auth login",
+ "4be0616873": "The GitLab CLI is installed but not authenticated. Run this command in a terminal:",
+ "54a640af7a": "Install GitLab CLI",
+ "b56fd5676a": "Install the GitLab CLI to enable merge requests, issues, and pipelines.",
+ "faddeb763d": "GitLab CLI status is not available in this runtime yet.",
+ "a47f71e357": "CLI.",
+ "2a6b359e75": "glab",
+ "1f2b347bd3": "Merge requests, issues, todos, and pipelines via the",
+ "8d90249d22": "gh auth login",
+ "2e44dda68a": "The GitHub CLI is installed but not authenticated. Run this command in a terminal:",
+ "7755c28af5": "Install GitHub CLI",
+ "23cb5a0dee": "Install the GitHub CLI to enable pull requests, issues, and checks.",
+ "6f30fc4216": "GitHub CLI status is not available in this runtime yet.",
+ "6b2cfb52b4": "gh",
+ "b4d900e7f1": "Pull requests, issues, and checks via the"
+ }
+ }
+ }
+ }
+ },
+ "task": {
+ "tracker": {
+ "integration": {
+ "cards": {
+ "c90f2ef419": "Re-check",
+ "dd3529015d": "Disconnect {{value0}}",
+ "8b2408a8e5": "Jira is connected for this runtime. Re-check if the connected site list looks stale.",
+ "8c20e76308": "Each connected Jira site has one token stored by the active runtime.",
+ "c24e56c532": "Test",
+ "3e7c10d286": "Testing...",
+ "a2c0015fb8": "Verified",
+ "e2ff968276": "Connect Jira",
+ "60996beda6": "Add Jira site",
+ "7ca5ffffdb": "Browse, create, and start work from Jira Cloud issues.",
+ "a1093a06c7": "Checking Jira access before showing setup actions.",
+ "9fa04a032e": "{{value0}} site{{value1}} connected",
+ "cef18762a2": "Add access with a Personal API key from your Linear settings. Full-access keys can see every team the key owner can reach.",
+ "6224fe9d34": "Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.",
+ "1a12e33fe5": "Add Linear access",
+ "622c224082": "Add workspace access",
+ "eae4a9f16b": "Add Linear access to browse and link issues.",
+ "fe9231215b": "Checking Linear access before showing setup actions.",
+ "e1f5e6424c": "{{value0}} workspace{{value1}} connected",
+ "disconnect_all": "Disconnect"
+ }
+ }
+ }
+ },
+ "token": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "793a06e899": "Re-check",
+ "1a9475dace": "Learn more",
+ "19fb419c12": "Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "60708f23da": "only when Orca cannot derive the API URL from the remote.",
+ "709057ad91": "ORCA_GITEA_API_BASE_URL",
+ "6da9dfa5de": "for private repositories, and set",
+ "6d5c2a3005": "ORCA_GITEA_TOKEN",
+ "fcbe0469fd": "Public repositories are detected from their git remote. Set",
+ "0613928cb3": "Gitea status is not available in this runtime yet.",
+ "05863d2599": "Pull requests and commit statuses via the Gitea REST API.",
+ "52f75876be": "Pull requests and commit statuses for detected repositories",
+ "0b5242f8a2": "{{value0}} · Pull requests and commit statuses",
+ "40f678df73": "Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "7bd345e3f6": "only when Orca cannot derive the API base URL from the git remote.",
+ "186a6689df": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "b8a10b07c1": ". Set",
+ "fbfd237f5e": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "087feb92f1": ", or set",
+ "48842720d2": "ORCA_AZURE_DEVOPS_TOKEN",
+ "7bbc9c64f0": "Set",
+ "f3f47dc7de": "Azure DevOps status is not available in this runtime yet.",
+ "0eb50d5593": "Pull requests and build statuses via Azure DevOps REST API tokens.",
+ "54636c65d4": "Pull requests and build statuses for detected Azure Repos",
+ "ea204f5e03": "{{value0}} · Pull requests and build statuses",
+ "6154b02093": "Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.",
+ "e63fe8f627": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "19416c874c": "ORCA_BITBUCKET_API_TOKEN",
+ "fc71a0e7aa": "and",
+ "63a7f47392": "ORCA_BITBUCKET_EMAIL",
+ "24ac1c69dc": "Bitbucket status is not available in this runtime yet.",
+ "a924e8dcd1": "Pull requests and build statuses via Bitbucket Cloud API tokens.",
+ "0fa5629dad": "Pull requests and build statuses"
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -8828,6 +8935,30 @@
"b7345c18db": "Se produjo un error inesperado.",
"5f97caf76b": "Instalando…",
"c2df599513": "Instalar CLI y habilidad"
+ },
+ "ConnectIntegrationsList": {
+ "3dddb2d565": "connected for tasks",
+ "33b650af52": "Connect where your team tracks work. Orca starts workspaces with the issue title, link, and context already attached.",
+ "5b3577a492": "connected for review status",
+ "3a1fcdddad": "Two quick steps: connect where your code is reviewed, then where your team plans work.",
+ "list_end": ", and ",
+ "list_pair": " and ",
+ "list_mid": ", ",
+ "code_host_tasks_summary": "issues available as tasks · add Linear or Jira if your team plans work there",
+ "code_host_tasks_caption": "Your code host's issues also work as tasks.",
+ "review_step_title": "See PR status while agents work",
+ "review_step_description": "Connect a review provider so Orca can show PR or MR status, checks, and reviews.",
+ "task_step_title": "Start agents on your tasks without leaving Orca"
+ },
+ "connect": {
+ "integration": {
+ "step": {
+ "0f47ff17c6": "Change",
+ "5538eb6743": "Done",
+ "open_step": "Open",
+ "close_step": "Close"
+ }
+ }
}
},
"tips": {
@@ -10032,6 +10163,25 @@
"8490e5d36a": "Confirmar",
"56f5c60e0c": "Cancelar"
}
+ },
+ "jira": {
+ "connect": {
+ "dialog": {
+ "63ce735809": "Connect",
+ "4a2ab52781": "Verifying…",
+ "79e7aaed39": "Cancel",
+ "fdd26d81cc": "Atlassian account settings",
+ "8090504a3e": "Create a token in",
+ "7b3967c12f": "Atlassian API token",
+ "3d81bf3ab3": "API token",
+ "e91b9a4073": "you@example.com",
+ "2849ddb295": "Atlassian email",
+ "70fcd360c4": "https://example.atlassian.net",
+ "e176f9d0c5": "Jira Cloud site URL",
+ "d785c42b8b": "Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.",
+ "8388bdea2b": "Connect Jira site"
+ }
+ }
}
},
"i18n": {
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
index 8dfe8748268..13f46e9198e 100644
--- a/src/renderer/src/i18n/locales/ja.json
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -232,6 +232,12 @@
"ui": {
"66e3bd7ce6": "{{value0}} に送信されました",
"53883b7bc3": "{{value0}} に送信できませんでした"
+ },
+ "jira": {
+ "856083302c": "Jira connection was superseded by a newer request."
+ },
+ "linear": {
+ "37d36984d0": "Linear connection was superseded by a newer request."
}
}
},
@@ -4565,7 +4571,11 @@
"9707523939": "PR とビルドステータス",
"a565377c38": "未インストール",
"15cf990798": "認証されていません",
- "f7eb5f0b24": "未インストール"
+ "f7eb5f0b24": "未インストール",
+ "3ba07f933b": "Connect issue trackers Orca can use to browse tasks and start workspaces with linked context.",
+ "70e885705b": "Task providers",
+ "1683acbac4": "Connect the source hosts Orca can use for pull requests, merge requests, checks, and review status.",
+ "298c65ecac": "Review providers"
},
"KagiSessionLinkForm": {
"92f0b4e472": "クリア",
@@ -7274,6 +7284,103 @@
}
}
}
+ },
+ "cli": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "d5b3be8ecd": "Re-check",
+ "8cbc39f862": "Learn more",
+ "707180d09c": "glab auth login",
+ "4be0616873": "The GitLab CLI is installed but not authenticated. Run this command in a terminal:",
+ "54a640af7a": "Install GitLab CLI",
+ "b56fd5676a": "Install the GitLab CLI to enable merge requests, issues, and pipelines.",
+ "faddeb763d": "GitLab CLI status is not available in this runtime yet.",
+ "a47f71e357": "CLI.",
+ "2a6b359e75": "glab",
+ "1f2b347bd3": "Merge requests, issues, todos, and pipelines via the",
+ "8d90249d22": "gh auth login",
+ "2e44dda68a": "The GitHub CLI is installed but not authenticated. Run this command in a terminal:",
+ "7755c28af5": "Install GitHub CLI",
+ "23cb5a0dee": "Install the GitHub CLI to enable pull requests, issues, and checks.",
+ "6f30fc4216": "GitHub CLI status is not available in this runtime yet.",
+ "6b2cfb52b4": "gh",
+ "b4d900e7f1": "Pull requests, issues, and checks via the"
+ }
+ }
+ }
+ }
+ },
+ "task": {
+ "tracker": {
+ "integration": {
+ "cards": {
+ "c90f2ef419": "Re-check",
+ "dd3529015d": "Disconnect {{value0}}",
+ "8b2408a8e5": "Jira is connected for this runtime. Re-check if the connected site list looks stale.",
+ "8c20e76308": "Each connected Jira site has one token stored by the active runtime.",
+ "c24e56c532": "Test",
+ "3e7c10d286": "Testing...",
+ "a2c0015fb8": "Verified",
+ "e2ff968276": "Connect Jira",
+ "60996beda6": "Add Jira site",
+ "7ca5ffffdb": "Browse, create, and start work from Jira Cloud issues.",
+ "a1093a06c7": "Checking Jira access before showing setup actions.",
+ "9fa04a032e": "{{value0}} site{{value1}} connected",
+ "cef18762a2": "Add access with a Personal API key from your Linear settings. Full-access keys can see every team the key owner can reach.",
+ "6224fe9d34": "Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.",
+ "1a12e33fe5": "Add Linear access",
+ "622c224082": "Add workspace access",
+ "eae4a9f16b": "Add Linear access to browse and link issues.",
+ "fe9231215b": "Checking Linear access before showing setup actions.",
+ "e1f5e6424c": "{{value0}} workspace{{value1}} connected",
+ "disconnect_all": "Disconnect"
+ }
+ }
+ }
+ },
+ "token": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "793a06e899": "Re-check",
+ "1a9475dace": "Learn more",
+ "19fb419c12": "Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "60708f23da": "only when Orca cannot derive the API URL from the remote.",
+ "709057ad91": "ORCA_GITEA_API_BASE_URL",
+ "6da9dfa5de": "for private repositories, and set",
+ "6d5c2a3005": "ORCA_GITEA_TOKEN",
+ "fcbe0469fd": "Public repositories are detected from their git remote. Set",
+ "0613928cb3": "Gitea status is not available in this runtime yet.",
+ "05863d2599": "Pull requests and commit statuses via the Gitea REST API.",
+ "52f75876be": "Pull requests and commit statuses for detected repositories",
+ "0b5242f8a2": "{{value0}} · Pull requests and commit statuses",
+ "40f678df73": "Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "7bd345e3f6": "only when Orca cannot derive the API base URL from the git remote.",
+ "186a6689df": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "b8a10b07c1": ". Set",
+ "fbfd237f5e": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "087feb92f1": ", or set",
+ "48842720d2": "ORCA_AZURE_DEVOPS_TOKEN",
+ "7bbc9c64f0": "Set",
+ "f3f47dc7de": "Azure DevOps status is not available in this runtime yet.",
+ "0eb50d5593": "Pull requests and build statuses via Azure DevOps REST API tokens.",
+ "54636c65d4": "Pull requests and build statuses for detected Azure Repos",
+ "ea204f5e03": "{{value0}} · Pull requests and build statuses",
+ "6154b02093": "Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.",
+ "e63fe8f627": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "19416c874c": "ORCA_BITBUCKET_API_TOKEN",
+ "fc71a0e7aa": "and",
+ "63a7f47392": "ORCA_BITBUCKET_EMAIL",
+ "24ac1c69dc": "Bitbucket status is not available in this runtime yet.",
+ "a924e8dcd1": "Pull requests and build statuses via Bitbucket Cloud API tokens.",
+ "0fa5629dad": "Pull requests and build statuses"
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -8828,6 +8935,30 @@
"b7345c18db": "予期しないエラーが発生しました。",
"5f97caf76b": "インストール中…",
"c2df599513": "CLI とスキルをインストール"
+ },
+ "ConnectIntegrationsList": {
+ "3dddb2d565": "connected for tasks",
+ "33b650af52": "Connect where your team tracks work. Orca starts workspaces with the issue title, link, and context already attached.",
+ "5b3577a492": "connected for review status",
+ "3a1fcdddad": "Two quick steps: connect where your code is reviewed, then where your team plans work.",
+ "list_end": ", and ",
+ "list_pair": " and ",
+ "list_mid": ", ",
+ "code_host_tasks_summary": "issues available as tasks · add Linear or Jira if your team plans work there",
+ "code_host_tasks_caption": "Your code host's issues also work as tasks.",
+ "review_step_title": "See PR status while agents work",
+ "review_step_description": "Connect a review provider so Orca can show PR or MR status, checks, and reviews.",
+ "task_step_title": "Start agents on your tasks without leaving Orca"
+ },
+ "connect": {
+ "integration": {
+ "step": {
+ "0f47ff17c6": "Change",
+ "5538eb6743": "Done",
+ "open_step": "Open",
+ "close_step": "Close"
+ }
+ }
}
},
"tips": {
@@ -10032,6 +10163,25 @@
"8490e5d36a": "確認する",
"56f5c60e0c": "キャンセル"
}
+ },
+ "jira": {
+ "connect": {
+ "dialog": {
+ "63ce735809": "Connect",
+ "4a2ab52781": "Verifying…",
+ "79e7aaed39": "Cancel",
+ "fdd26d81cc": "Atlassian account settings",
+ "8090504a3e": "Create a token in",
+ "7b3967c12f": "Atlassian API token",
+ "3d81bf3ab3": "API token",
+ "e91b9a4073": "you@example.com",
+ "2849ddb295": "Atlassian email",
+ "70fcd360c4": "https://example.atlassian.net",
+ "e176f9d0c5": "Jira Cloud site URL",
+ "d785c42b8b": "Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.",
+ "8388bdea2b": "Connect Jira site"
+ }
+ }
}
},
"i18n": {
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 6aae0819947..53d749bc621 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -232,6 +232,12 @@
"ui": {
"66e3bd7ce6": "{{value0}}(으)로 보냄",
"53883b7bc3": "{{value0}}(으)로 보낼 수 없습니다."
+ },
+ "jira": {
+ "856083302c": "Jira connection was superseded by a newer request."
+ },
+ "linear": {
+ "37d36984d0": "Linear connection was superseded by a newer request."
}
}
},
@@ -4529,7 +4535,11 @@
"9707523939": "PR 및 빌드 상태",
"a565377c38": "설치되지 않은",
"15cf990798": "인증되지 않음",
- "f7eb5f0b24": "설치되지 않음"
+ "f7eb5f0b24": "설치되지 않음",
+ "3ba07f933b": "Connect issue trackers Orca can use to browse tasks and start workspaces with linked context.",
+ "70e885705b": "Task providers",
+ "1683acbac4": "Connect the source hosts Orca can use for pull requests, merge requests, checks, and review status.",
+ "298c65ecac": "Review providers"
},
"KagiSessionLinkForm": {
"92f0b4e472": "지우기",
@@ -7274,6 +7284,103 @@
},
"YamlThemeImportButton": {
"label": "Import from YAML"
+ },
+ "cli": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "d5b3be8ecd": "Re-check",
+ "8cbc39f862": "Learn more",
+ "707180d09c": "glab auth login",
+ "4be0616873": "The GitLab CLI is installed but not authenticated. Run this command in a terminal:",
+ "54a640af7a": "Install GitLab CLI",
+ "b56fd5676a": "Install the GitLab CLI to enable merge requests, issues, and pipelines.",
+ "faddeb763d": "GitLab CLI status is not available in this runtime yet.",
+ "a47f71e357": "CLI.",
+ "2a6b359e75": "glab",
+ "1f2b347bd3": "Merge requests, issues, todos, and pipelines via the",
+ "8d90249d22": "gh auth login",
+ "2e44dda68a": "The GitHub CLI is installed but not authenticated. Run this command in a terminal:",
+ "7755c28af5": "Install GitHub CLI",
+ "23cb5a0dee": "Install the GitHub CLI to enable pull requests, issues, and checks.",
+ "6f30fc4216": "GitHub CLI status is not available in this runtime yet.",
+ "6b2cfb52b4": "gh",
+ "b4d900e7f1": "Pull requests, issues, and checks via the"
+ }
+ }
+ }
+ }
+ },
+ "task": {
+ "tracker": {
+ "integration": {
+ "cards": {
+ "c90f2ef419": "Re-check",
+ "dd3529015d": "Disconnect {{value0}}",
+ "8b2408a8e5": "Jira is connected for this runtime. Re-check if the connected site list looks stale.",
+ "8c20e76308": "Each connected Jira site has one token stored by the active runtime.",
+ "c24e56c532": "Test",
+ "3e7c10d286": "Testing...",
+ "a2c0015fb8": "Verified",
+ "e2ff968276": "Connect Jira",
+ "60996beda6": "Add Jira site",
+ "7ca5ffffdb": "Browse, create, and start work from Jira Cloud issues.",
+ "a1093a06c7": "Checking Jira access before showing setup actions.",
+ "9fa04a032e": "{{value0}} site{{value1}} connected",
+ "cef18762a2": "Add access with a Personal API key from your Linear settings. Full-access keys can see every team the key owner can reach.",
+ "6224fe9d34": "Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.",
+ "1a12e33fe5": "Add Linear access",
+ "622c224082": "Add workspace access",
+ "eae4a9f16b": "Add Linear access to browse and link issues.",
+ "fe9231215b": "Checking Linear access before showing setup actions.",
+ "e1f5e6424c": "{{value0}} workspace{{value1}} connected",
+ "disconnect_all": "Disconnect"
+ }
+ }
+ }
+ },
+ "token": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "793a06e899": "Re-check",
+ "1a9475dace": "Learn more",
+ "19fb419c12": "Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "60708f23da": "only when Orca cannot derive the API URL from the remote.",
+ "709057ad91": "ORCA_GITEA_API_BASE_URL",
+ "6da9dfa5de": "for private repositories, and set",
+ "6d5c2a3005": "ORCA_GITEA_TOKEN",
+ "fcbe0469fd": "Public repositories are detected from their git remote. Set",
+ "0613928cb3": "Gitea status is not available in this runtime yet.",
+ "05863d2599": "Pull requests and commit statuses via the Gitea REST API.",
+ "52f75876be": "Pull requests and commit statuses for detected repositories",
+ "0b5242f8a2": "{{value0}} · Pull requests and commit statuses",
+ "40f678df73": "Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "7bd345e3f6": "only when Orca cannot derive the API base URL from the git remote.",
+ "186a6689df": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "b8a10b07c1": ". Set",
+ "fbfd237f5e": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "087feb92f1": ", or set",
+ "48842720d2": "ORCA_AZURE_DEVOPS_TOKEN",
+ "7bbc9c64f0": "Set",
+ "f3f47dc7de": "Azure DevOps status is not available in this runtime yet.",
+ "0eb50d5593": "Pull requests and build statuses via Azure DevOps REST API tokens.",
+ "54636c65d4": "Pull requests and build statuses for detected Azure Repos",
+ "ea204f5e03": "{{value0}} · Pull requests and build statuses",
+ "6154b02093": "Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.",
+ "e63fe8f627": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "19416c874c": "ORCA_BITBUCKET_API_TOKEN",
+ "fc71a0e7aa": "and",
+ "63a7f47392": "ORCA_BITBUCKET_EMAIL",
+ "24ac1c69dc": "Bitbucket status is not available in this runtime yet.",
+ "a924e8dcd1": "Pull requests and build statuses via Bitbucket Cloud API tokens.",
+ "0fa5629dad": "Pull requests and build statuses"
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -8828,6 +8935,30 @@
"b7345c18db": "예기치 않은 오류가 발생했습니다.",
"5f97caf76b": "설치 중…",
"c2df599513": "CLI 및 스킬 설치"
+ },
+ "ConnectIntegrationsList": {
+ "3dddb2d565": "connected for tasks",
+ "33b650af52": "Connect where your team tracks work. Orca starts workspaces with the issue title, link, and context already attached.",
+ "5b3577a492": "connected for review status",
+ "3a1fcdddad": "Two quick steps: connect where your code is reviewed, then where your team plans work.",
+ "list_end": ", and ",
+ "list_pair": " and ",
+ "list_mid": ", ",
+ "code_host_tasks_summary": "issues available as tasks · add Linear or Jira if your team plans work there",
+ "code_host_tasks_caption": "Your code host's issues also work as tasks.",
+ "review_step_title": "See PR status while agents work",
+ "review_step_description": "Connect a review provider so Orca can show PR or MR status, checks, and reviews.",
+ "task_step_title": "Start agents on your tasks without leaving Orca"
+ },
+ "connect": {
+ "integration": {
+ "step": {
+ "0f47ff17c6": "Change",
+ "5538eb6743": "Done",
+ "open_step": "Open",
+ "close_step": "Close"
+ }
+ }
}
},
"tips": {
@@ -10032,6 +10163,25 @@
"8490e5d36a": "확인",
"56f5c60e0c": "취소"
}
+ },
+ "jira": {
+ "connect": {
+ "dialog": {
+ "63ce735809": "Connect",
+ "4a2ab52781": "Verifying…",
+ "79e7aaed39": "Cancel",
+ "fdd26d81cc": "Atlassian account settings",
+ "8090504a3e": "Create a token in",
+ "7b3967c12f": "Atlassian API token",
+ "3d81bf3ab3": "API token",
+ "e91b9a4073": "you@example.com",
+ "2849ddb295": "Atlassian email",
+ "70fcd360c4": "https://example.atlassian.net",
+ "e176f9d0c5": "Jira Cloud site URL",
+ "d785c42b8b": "Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.",
+ "8388bdea2b": "Connect Jira site"
+ }
+ }
}
},
"i18n": {
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index f397b380599..681538b1222 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -232,6 +232,12 @@
"ui": {
"66e3bd7ce6": "发送至 {{value0}}",
"53883b7bc3": "无法发送至 {{value0}}"
+ },
+ "jira": {
+ "856083302c": "Jira connection was superseded by a newer request."
+ },
+ "linear": {
+ "37d36984d0": "Linear connection was superseded by a newer request."
}
}
},
@@ -4529,7 +4535,11 @@
"9707523939": "拉取请求和构建状态",
"a565377c38": "未安装",
"15cf990798": "未经过验证",
- "f7eb5f0b24": "未安装"
+ "f7eb5f0b24": "未安装",
+ "3ba07f933b": "Connect issue trackers Orca can use to browse tasks and start workspaces with linked context.",
+ "70e885705b": "Task providers",
+ "1683acbac4": "Connect the source hosts Orca can use for pull requests, merge requests, checks, and review status.",
+ "298c65ecac": "Review providers"
},
"KagiSessionLinkForm": {
"92f0b4e472": "清除",
@@ -7274,6 +7284,103 @@
},
"YamlThemeImportButton": {
"label": "Import from YAML"
+ },
+ "cli": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "d5b3be8ecd": "Re-check",
+ "8cbc39f862": "Learn more",
+ "707180d09c": "glab auth login",
+ "4be0616873": "The GitLab CLI is installed but not authenticated. Run this command in a terminal:",
+ "54a640af7a": "Install GitLab CLI",
+ "b56fd5676a": "Install the GitLab CLI to enable merge requests, issues, and pipelines.",
+ "faddeb763d": "GitLab CLI status is not available in this runtime yet.",
+ "a47f71e357": "CLI.",
+ "2a6b359e75": "glab",
+ "1f2b347bd3": "Merge requests, issues, todos, and pipelines via the",
+ "8d90249d22": "gh auth login",
+ "2e44dda68a": "The GitHub CLI is installed but not authenticated. Run this command in a terminal:",
+ "7755c28af5": "Install GitHub CLI",
+ "23cb5a0dee": "Install the GitHub CLI to enable pull requests, issues, and checks.",
+ "6f30fc4216": "GitHub CLI status is not available in this runtime yet.",
+ "6b2cfb52b4": "gh",
+ "b4d900e7f1": "Pull requests, issues, and checks via the"
+ }
+ }
+ }
+ }
+ },
+ "task": {
+ "tracker": {
+ "integration": {
+ "cards": {
+ "c90f2ef419": "Re-check",
+ "dd3529015d": "Disconnect {{value0}}",
+ "8b2408a8e5": "Jira is connected for this runtime. Re-check if the connected site list looks stale.",
+ "8c20e76308": "Each connected Jira site has one token stored by the active runtime.",
+ "c24e56c532": "Test",
+ "3e7c10d286": "Testing...",
+ "a2c0015fb8": "Verified",
+ "e2ff968276": "Connect Jira",
+ "60996beda6": "Add Jira site",
+ "7ca5ffffdb": "Browse, create, and start work from Jira Cloud issues.",
+ "a1093a06c7": "Checking Jira access before showing setup actions.",
+ "9fa04a032e": "{{value0}} site{{value1}} connected",
+ "cef18762a2": "Add access with a Personal API key from your Linear settings. Full-access keys can see every team the key owner can reach.",
+ "6224fe9d34": "Each connected Linear workspace has one key stored by the active runtime. Full-access keys can cover all teams the key owner can access; restricted keys can be replaced any time.",
+ "1a12e33fe5": "Add Linear access",
+ "622c224082": "Add workspace access",
+ "eae4a9f16b": "Add Linear access to browse and link issues.",
+ "fe9231215b": "Checking Linear access before showing setup actions.",
+ "e1f5e6424c": "{{value0}} workspace{{value1}} connected",
+ "disconnect_all": "Disconnect"
+ }
+ }
+ }
+ },
+ "token": {
+ "source": {
+ "control": {
+ "integration": {
+ "cards": {
+ "793a06e899": "Re-check",
+ "1a9475dace": "Learn more",
+ "19fb419c12": "Gitea credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "60708f23da": "only when Orca cannot derive the API URL from the remote.",
+ "709057ad91": "ORCA_GITEA_API_BASE_URL",
+ "6da9dfa5de": "for private repositories, and set",
+ "6d5c2a3005": "ORCA_GITEA_TOKEN",
+ "fcbe0469fd": "Public repositories are detected from their git remote. Set",
+ "0613928cb3": "Gitea status is not available in this runtime yet.",
+ "05863d2599": "Pull requests and commit statuses via the Gitea REST API.",
+ "52f75876be": "Pull requests and commit statuses for detected repositories",
+ "0b5242f8a2": "{{value0}} · Pull requests and commit statuses",
+ "40f678df73": "Azure DevOps credentials are configured but could not authenticate. Check the token, API base URL, and repository permissions, then restart Orca if environment variables changed.",
+ "7bd345e3f6": "only when Orca cannot derive the API base URL from the git remote.",
+ "186a6689df": "ORCA_AZURE_DEVOPS_API_BASE_URL",
+ "b8a10b07c1": ". Set",
+ "fbfd237f5e": "ORCA_AZURE_DEVOPS_ACCESS_TOKEN",
+ "087feb92f1": ", or set",
+ "48842720d2": "ORCA_AZURE_DEVOPS_TOKEN",
+ "7bbc9c64f0": "Set",
+ "f3f47dc7de": "Azure DevOps status is not available in this runtime yet.",
+ "0eb50d5593": "Pull requests and build statuses via Azure DevOps REST API tokens.",
+ "54636c65d4": "Pull requests and build statuses for detected Azure Repos",
+ "ea204f5e03": "{{value0}} · Pull requests and build statuses",
+ "6154b02093": "Bitbucket credentials are configured but could not authenticate. Check the token and repository permissions, then restart Orca if environment variables changed.",
+ "e63fe8f627": "ORCA_BITBUCKET_ACCESS_TOKEN",
+ "19416c874c": "ORCA_BITBUCKET_API_TOKEN",
+ "fc71a0e7aa": "and",
+ "63a7f47392": "ORCA_BITBUCKET_EMAIL",
+ "24ac1c69dc": "Bitbucket status is not available in this runtime yet.",
+ "a924e8dcd1": "Pull requests and build statuses via Bitbucket Cloud API tokens.",
+ "0fa5629dad": "Pull requests and build statuses"
+ }
+ }
+ }
+ }
}
},
"right": {
@@ -8828,6 +8935,30 @@
"b7345c18db": "发生了意外错误。",
"5f97caf76b": "正在安装…",
"c2df599513": "安装 CLI 和技能"
+ },
+ "ConnectIntegrationsList": {
+ "3dddb2d565": "connected for tasks",
+ "33b650af52": "Connect where your team tracks work. Orca starts workspaces with the issue title, link, and context already attached.",
+ "5b3577a492": "connected for review status",
+ "3a1fcdddad": "Two quick steps: connect where your code is reviewed, then where your team plans work.",
+ "list_end": ", and ",
+ "list_pair": " and ",
+ "list_mid": ", ",
+ "code_host_tasks_summary": "issues available as tasks · add Linear or Jira if your team plans work there",
+ "code_host_tasks_caption": "Your code host's issues also work as tasks.",
+ "review_step_title": "See PR status while agents work",
+ "review_step_description": "Connect a review provider so Orca can show PR or MR status, checks, and reviews.",
+ "task_step_title": "Start agents on your tasks without leaving Orca"
+ },
+ "connect": {
+ "integration": {
+ "step": {
+ "0f47ff17c6": "Change",
+ "5538eb6743": "Done",
+ "open_step": "Open",
+ "close_step": "Close"
+ }
+ }
}
},
"tips": {
@@ -10032,6 +10163,25 @@
"8490e5d36a": "确认",
"56f5c60e0c": "取消"
}
+ },
+ "jira": {
+ "connect": {
+ "dialog": {
+ "63ce735809": "Connect",
+ "4a2ab52781": "Verifying…",
+ "79e7aaed39": "Cancel",
+ "fdd26d81cc": "Atlassian account settings",
+ "8090504a3e": "Create a token in",
+ "7b3967c12f": "Atlassian API token",
+ "3d81bf3ab3": "API token",
+ "e91b9a4073": "you@example.com",
+ "2849ddb295": "Atlassian email",
+ "70fcd360c4": "https://example.atlassian.net",
+ "e176f9d0c5": "Jira Cloud site URL",
+ "d785c42b8b": "Use a Jira Cloud site URL, Atlassian email, and API token to browse issues.",
+ "8388bdea2b": "Connect Jira site"
+ }
+ }
}
},
"i18n": {
diff --git a/src/renderer/src/lib/local-preflight-context.test.ts b/src/renderer/src/lib/local-preflight-context.test.ts
index 67ebdbcab55..e53f22365d1 100644
--- a/src/renderer/src/lib/local-preflight-context.test.ts
+++ b/src/renderer/src/lib/local-preflight-context.test.ts
@@ -88,6 +88,21 @@ describe('local preflight context', () => {
expect(localPreflightContextKey(getLocalPreflightContext(state))).toBe('host')
})
+ it('keys preflight by active runtime before local WSL or host context', () => {
+ const state = {
+ ...makeState({
+ repoPath: String.raw`\\wsl.localhost\Ubuntu\home\alice\repo`
+ }),
+ settings: {
+ activeRuntimeEnvironmentId: 'runtime-1'
+ }
+ } as AppState
+
+ const context = getLocalPreflightContext(state)
+ expect(context?.runtimeContextKey).toMatch(/^runtime:runtime-1#\d+$/)
+ expect(localPreflightContextKey(context)).toBe(context?.runtimeContextKey)
+ })
+
it('uses the selected WSL distro for local agent checks when WSL is the default shell', () => {
const state = {
...makeState({ repoPath: 'C:\\Users\\alice\\repo' }),
diff --git a/src/renderer/src/lib/local-preflight-context.ts b/src/renderer/src/lib/local-preflight-context.ts
index ed61a7619ec..8f28f805e17 100644
--- a/src/renderer/src/lib/local-preflight-context.ts
+++ b/src/renderer/src/lib/local-preflight-context.ts
@@ -1,7 +1,10 @@
import type { AppState } from '@/store/types'
import { parseWslUncPath } from '../../../shared/wsl-paths'
+import { getProviderRuntimeContextKey } from './provider-runtime-context'
-export type LocalPreflightContext = { wslDistro?: string | null; wslDefault?: boolean } | undefined
+export type LocalPreflightContext =
+ | { wslDistro?: string | null; wslDefault?: boolean; runtimeContextKey?: string }
+ | undefined
const wslPreflightContextsByDistro = new Map>()
const wslDefaultPreflightContext = Object.freeze({ wslDefault: true })
@@ -24,6 +27,9 @@ function getWslPreflightContext(wslDistro: string): NonNullable | null | undefined
+): string {
+ const environmentId = settings?.activeRuntimeEnvironmentId?.trim()
+ const baseKey = environmentId ? `runtime:${environmentId}` : 'local'
+ return `${baseKey}#${providerRuntimeSessionGeneration}`
+}
+
+export function hasRemoteProviderRuntime(
+ settings: Pick | null | undefined
+): boolean {
+ return Boolean(settings?.activeRuntimeEnvironmentId?.trim())
+}
+
+let providerRuntimeSessionGeneration = 0
+
+export function bumpProviderRuntimeSessionGeneration(): number {
+ providerRuntimeSessionGeneration += 1
+ return providerRuntimeSessionGeneration
+}
diff --git a/src/renderer/src/store/slices/jira.test.ts b/src/renderer/src/store/slices/jira.test.ts
index 6d117f9b703..2d6addc7972 100644
--- a/src/renderer/src/store/slices/jira.test.ts
+++ b/src/renderer/src/store/slices/jira.test.ts
@@ -1,24 +1,36 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { create } from 'zustand'
import type { AppState } from '../types'
-import type { JiraIssue } from '../../../../shared/types'
+import type { JiraConnectionStatus, JiraIssue, JiraViewer } from '../../../../shared/types'
import { credentialDecryptionMessage } from '../../../../shared/integration-credential-errors'
import { createJiraSlice } from './jira'
+const jiraStatus = vi.fn()
+const jiraConnect = vi.fn()
+const jiraDisconnect = vi.fn()
const jiraGetIssue = vi.fn()
const jiraListIssues = vi.fn()
const jiraSearchIssues = vi.fn()
-const jiraStatus = vi.fn()
+const jiraSelectSite = vi.fn()
+const jiraTestConnection = vi.fn()
vi.mock('@/runtime/runtime-jira-client', () => ({
- jiraConnect: vi.fn(),
- jiraDisconnect: vi.fn(),
+ jiraAddIssueComment: vi.fn(),
+ jiraConnect: (...args: unknown[]) => jiraConnect(...args),
+ jiraCreateIssue: vi.fn(),
+ jiraDisconnect: (...args: unknown[]) => jiraDisconnect(...args),
jiraGetIssue: (...args: unknown[]) => jiraGetIssue(...args),
+ jiraIssueComments: vi.fn(),
+ jiraListCreateFields: vi.fn(),
+ jiraListIssueTypes: vi.fn(),
jiraListIssues: (...args: unknown[]) => jiraListIssues(...args),
+ jiraListPriorities: vi.fn(),
+ jiraListProjects: vi.fn(),
jiraSearchIssues: (...args: unknown[]) => jiraSearchIssues(...args),
- jiraSelectSite: vi.fn(),
+ jiraSelectSite: (...args: unknown[]) => jiraSelectSite(...args),
jiraStatus: (...args: unknown[]) => jiraStatus(...args),
- jiraTestConnection: vi.fn()
+ jiraTestConnection: (...args: unknown[]) => jiraTestConnection(...args),
+ jiraUpdateIssue: vi.fn()
}))
function createTestStore() {
@@ -31,6 +43,18 @@ function createTestStore() {
)
}
+function deferred() {
+ let resolve!: (value: T) => void
+ const promise = new Promise((res) => {
+ resolve = res
+ })
+ return { promise, resolve }
+}
+
+function status(email: string): JiraConnectionStatus {
+ return { connected: true, viewer: { email } as JiraViewer }
+}
+
function issue(key: string): JiraIssue {
return {
id: key,
@@ -48,6 +72,99 @@ function issue(key: string): JiraIssue {
}
}
+describe('createJiraSlice runtime context', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it('ignores stale status responses after the active runtime changes', async () => {
+ const store = createTestStore()
+ const localStatus = deferred()
+ const remoteStatus = deferred()
+ jiraStatus.mockReturnValueOnce(localStatus.promise).mockReturnValueOnce(remoteStatus.promise)
+
+ const localRequest = store.getState().checkJiraConnection()
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+ const remoteRequest = store.getState().checkJiraConnection()
+
+ remoteStatus.resolve(status('remote@example.com'))
+ await remoteRequest
+ expect(store.getState().jiraStatus.viewer?.email).toBe('remote@example.com')
+ expect(store.getState().jiraStatusContextKey).toBe('runtime:runtime-1#0')
+
+ localStatus.resolve(status('local@example.com'))
+ await localRequest
+ expect(store.getState().jiraStatus.viewer?.email).toBe('remote@example.com')
+ expect(store.getState().jiraStatusContextKey).toBe('runtime:runtime-1#0')
+ })
+
+ it('ignores stale issue cache writes after the active runtime changes', async () => {
+ const store = createTestStore()
+ const localIssue = deferred()
+ const remoteIssue = deferred()
+ jiraGetIssue.mockReturnValueOnce(localIssue.promise).mockReturnValueOnce(remoteIssue.promise)
+
+ const localRequest = store.getState().fetchJiraIssue('ORC-1')
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+ const remoteRequest = store.getState().fetchJiraIssue('ORC-1')
+
+ remoteIssue.resolve({ ...issue('ORC-1'), title: 'Remote issue' })
+ await remoteRequest
+ expect(store.getState().jiraIssueCache['selected::ORC-1']?.data?.title).toBe('Remote issue')
+
+ localIssue.resolve({ ...issue('ORC-1'), title: 'Local issue' })
+ await localRequest
+ expect(store.getState().jiraIssueCache['selected::ORC-1']?.data?.title).toBe('Remote issue')
+ })
+
+ it('returns a failed Jira connect result when the active runtime changes before completion', async () => {
+ const store = createTestStore()
+ const connectResult = deferred<{ ok: true; viewer: JiraViewer }>()
+ jiraConnect.mockReturnValueOnce(connectResult.promise)
+
+ const request = store.getState().connectJira({
+ siteUrl: 'https://example.atlassian.net',
+ email: 'local@example.com',
+ apiToken: 'token'
+ })
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+
+ connectResult.resolve({ ok: true, viewer: { email: 'local@example.com' } as JiraViewer })
+ await expect(request).resolves.toEqual({
+ ok: false,
+ error: 'Jira connection was superseded by a newer request.'
+ })
+ expect(store.getState().jiraStatus.connected).toBe(false)
+ expect(store.getState().jiraStatusContextKey).toBeNull()
+ })
+
+ it('does not run a stale test follow-up status check after the active runtime changes', async () => {
+ const store = createTestStore()
+ const testResult = deferred<{ ok: true; viewer: JiraViewer }>()
+ jiraTestConnection.mockReturnValueOnce(testResult.promise)
+
+ const request = store.getState().testJiraConnection()
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+
+ testResult.resolve({ ok: true, viewer: { email: 'local@example.com' } as JiraViewer })
+ await request
+ expect(jiraStatus).not.toHaveBeenCalled()
+ })
+
+ it('does not clear or refresh stale disconnect results after the active runtime changes', async () => {
+ const store = createTestStore()
+ const disconnectResult = deferred()
+ jiraDisconnect.mockReturnValueOnce(disconnectResult.promise)
+
+ const request = store.getState().disconnectJira()
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+
+ disconnectResult.resolve()
+ await request
+ expect(jiraStatus).not.toHaveBeenCalled()
+ })
+})
+
describe('createJiraSlice credential errors', () => {
beforeEach(() => {
vi.clearAllMocks()
diff --git a/src/renderer/src/store/slices/jira.ts b/src/renderer/src/store/slices/jira.ts
index 40a80db707c..1ee48d0de21 100644
--- a/src/renderer/src/store/slices/jira.ts
+++ b/src/renderer/src/store/slices/jira.ts
@@ -22,6 +22,8 @@ import {
jiraStatus,
jiraTestConnection
} from '@/runtime/runtime-jira-client'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+import { translate } from '@/i18n/i18n'
const CACHE_TTL = 60_000
const MAX_CACHE_ENTRIES = 500
@@ -51,9 +53,17 @@ function looksLikeAuthError(error: unknown): boolean {
return /authenticat|unauthorized|forbidden|401|403/i.test(msg)
}
-const inflightIssueRequests = new Map>()
-const inflightSearchRequests = new Map>()
-const inflightListRequests = new Map>()
+type InflightJiraReadRequest = {
+ promise: Promise
+ contextKey: string
+ mutationGeneration: number
+}
+
+const inflightIssueRequests = new Map>()
+const inflightSearchRequests = new Map>()
+const inflightListRequests = new Map>()
+let jiraStatusReadGeneration = 0
+let jiraMutationGeneration = 0
function getSelectedSiteId(status: JiraConnectionStatus): JiraSiteSelection | null {
return status.selectedSiteId ?? status.activeSiteId ?? null
@@ -65,9 +75,34 @@ function clearJiraInflight(): void {
inflightListRequests.clear()
}
+function beginJiraMutation(): number {
+ jiraMutationGeneration += 1
+ return jiraMutationGeneration
+}
+
+function isCurrentJiraMutation(generation: number): boolean {
+ return generation === jiraMutationGeneration
+}
+
+function isCurrentJiraRuntimeContext(contextKey: string, settings: AppState['settings']): boolean {
+ return getProviderRuntimeContextKey(settings) === contextKey
+}
+
+function canWriteJiraReadResult(
+ contextKey: string,
+ mutationGeneration: number,
+ settings: AppState['settings']
+): boolean {
+ return (
+ mutationGeneration === jiraMutationGeneration &&
+ isCurrentJiraRuntimeContext(contextKey, settings)
+ )
+}
+
export type JiraSlice = {
jiraStatus: JiraConnectionStatus
jiraStatusChecked: boolean
+ jiraStatusContextKey: string | null
jiraIssueCache: Record>
jiraSearchCache: Record>
@@ -91,12 +126,26 @@ export type JiraSlice = {
export const createJiraSlice: StateCreator = (set, get) => ({
jiraStatus: { connected: false, viewer: null },
jiraStatusChecked: false,
+ jiraStatusContextKey: null,
jiraIssueCache: {},
jiraSearchCache: {},
checkJiraConnection: async () => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
+ const statusReadGeneration = (jiraStatusReadGeneration += 1)
+ const mutationGeneration = jiraMutationGeneration
+ if (get().jiraStatusContextKey !== contextKey) {
+ set({ jiraStatusChecked: false })
+ }
try {
const status = await jiraStatus(get().settings)
+ if (
+ mutationGeneration !== jiraMutationGeneration ||
+ statusReadGeneration !== jiraStatusReadGeneration ||
+ getProviderRuntimeContextKey(get().settings) !== contextKey
+ ) {
+ return
+ }
const prev = get().jiraStatus
if (
prev.connected !== status.connected ||
@@ -105,25 +154,58 @@ export const createJiraSlice: StateCreator = (set,
getSelectedSiteId(prev) !== getSelectedSiteId(status) ||
(prev.sites?.length ?? 0) !== (status.sites?.length ?? 0)
) {
- set({ jiraStatus: status, jiraStatusChecked: true })
+ set({ jiraStatus: status, jiraStatusChecked: true, jiraStatusContextKey: contextKey })
} else if (!get().jiraStatusChecked) {
- set({ jiraStatusChecked: true })
+ set({ jiraStatusChecked: true, jiraStatusContextKey: contextKey })
+ } else if (get().jiraStatusContextKey !== contextKey) {
+ set({ jiraStatusContextKey: contextKey })
}
} catch {
+ if (
+ mutationGeneration !== jiraMutationGeneration ||
+ statusReadGeneration !== jiraStatusReadGeneration ||
+ getProviderRuntimeContextKey(get().settings) !== contextKey
+ ) {
+ return
+ }
if (get().jiraStatus.connected) {
- set({ jiraStatus: { connected: false, viewer: null }, jiraStatusChecked: true })
+ set({
+ jiraStatus: { connected: false, viewer: null },
+ jiraStatusChecked: true,
+ jiraStatusContextKey: contextKey
+ })
} else if (!get().jiraStatusChecked) {
- set({ jiraStatusChecked: true })
+ set({ jiraStatusChecked: true, jiraStatusContextKey: contextKey })
+ } else if (get().jiraStatusContextKey !== contextKey) {
+ set({ jiraStatusContextKey: contextKey })
}
}
},
connectJira: async (args) => {
+ const requestGeneration = beginJiraMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
try {
const result = await jiraConnect(get().settings, args)
- if (result.ok) {
- set({ jiraStatus: { connected: true, viewer: result.viewer }, jiraStatusChecked: true })
+ if (
+ result.ok &&
+ isCurrentJiraMutation(requestGeneration) &&
+ isCurrentJiraRuntimeContext(contextKey, get().settings)
+ ) {
+ set({
+ jiraStatus: { connected: true, viewer: result.viewer },
+ jiraStatusChecked: true,
+ jiraStatusContextKey: contextKey
+ })
void get().checkJiraConnection()
+ } else if (result.ok) {
+ return {
+ ok: false as const,
+ error: translate(
+ 'auto.store.slices.jira.856083302c',
+ 'Jira connection was superseded by a newer request.'
+ )
+ }
}
return result
} catch (error) {
@@ -133,10 +215,23 @@ export const createJiraSlice: StateCreator = (set,
},
testJiraConnection: async (siteId) => {
+ const requestGeneration = beginJiraMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
try {
const result = await jiraTestConnection(get().settings, siteId)
+ if (
+ !isCurrentJiraMutation(requestGeneration) ||
+ !isCurrentJiraRuntimeContext(contextKey, get().settings)
+ ) {
+ return result
+ }
const status = await jiraStatus(get().settings)
- set({ jiraStatus: status, jiraStatusChecked: true })
+ if (
+ isCurrentJiraMutation(requestGeneration) &&
+ isCurrentJiraRuntimeContext(contextKey, get().settings)
+ ) {
+ set({ jiraStatus: status, jiraStatusChecked: true, jiraStatusContextKey: contextKey })
+ }
return result
} catch (error) {
const message = error instanceof Error ? error.message : 'Test failed'
@@ -145,65 +240,111 @@ export const createJiraSlice: StateCreator = (set,
},
selectJiraSite: async (siteId) => {
+ const requestGeneration = beginJiraMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const status = await jiraSelectSite(get().settings, siteId)
+ if (
+ !isCurrentJiraMutation(requestGeneration) ||
+ getProviderRuntimeContextKey(get().settings) !== contextKey
+ ) {
+ return
+ }
clearJiraInflight()
set({
jiraStatus: status,
jiraIssueCache: {},
jiraSearchCache: {},
- jiraStatusChecked: true
+ jiraStatusChecked: true,
+ jiraStatusContextKey: contextKey
})
},
disconnectJira: async (siteId) => {
+ const requestGeneration = beginJiraMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
await jiraDisconnect(get().settings, siteId)
+ if (
+ !isCurrentJiraMutation(requestGeneration) ||
+ !isCurrentJiraRuntimeContext(contextKey, get().settings)
+ ) {
+ return
+ }
clearJiraInflight()
const status = await jiraStatus(get().settings)
+ if (
+ !isCurrentJiraMutation(requestGeneration) ||
+ !isCurrentJiraRuntimeContext(contextKey, get().settings)
+ ) {
+ return
+ }
set({
jiraStatus: status.connected ? status : { connected: false, viewer: null },
jiraIssueCache: {},
jiraSearchCache: {},
- jiraStatusChecked: true
+ jiraStatusChecked: true,
+ jiraStatusContextKey: contextKey
})
},
fetchJiraIssue: async (key, siteId) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const issueCacheKey = `${siteId ?? 'selected'}::${key}`
const cached = get().jiraIssueCache[issueCacheKey] ?? get().jiraIssueCache[key]
if (isFresh(cached)) {
return cached.data
}
const inflight = inflightIssueRequests.get(issueCacheKey)
- if (inflight) {
- return inflight
+ if (
+ inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === jiraMutationGeneration
+ ) {
+ return inflight.promise
}
+ let entry: InflightJiraReadRequest
+ const requestMutationGeneration = jiraMutationGeneration
const promise = jiraGetIssue(get().settings, key, siteId)
.then((issue) => {
- set((s) => ({
- jiraIssueCache: evictStaleEntries({
- ...s.jiraIssueCache,
- [issueCacheKey]: { data: issue, fetchedAt: Date.now() }
- })
- }))
+ if (
+ inflightIssueRequests.get(issueCacheKey) === entry &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
+ set((s) => ({
+ jiraIssueCache: evictStaleEntries({
+ ...s.jiraIssueCache,
+ [issueCacheKey]: { data: issue, fetchedAt: Date.now() }
+ })
+ }))
+ }
return issue
})
.catch((error) => {
console.warn('[jira] fetchJiraIssue failed:', error)
- if (isIntegrationCredentialDecryptionError(error)) {
+ if (
+ isIntegrationCredentialDecryptionError(error) &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
void get().checkJiraConnection()
- } else if (looksLikeAuthError(error)) {
+ } else if (
+ looksLikeAuthError(error) &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
set({ jiraStatus: { connected: false, viewer: null } })
}
return null
})
.finally(() => {
- inflightIssueRequests.delete(issueCacheKey)
+ if (inflightIssueRequests.get(issueCacheKey) === entry) {
+ inflightIssueRequests.delete(issueCacheKey)
+ }
})
- inflightIssueRequests.set(issueCacheKey, promise)
+ entry = { promise, contextKey, mutationGeneration: requestMutationGeneration }
+ inflightIssueRequests.set(issueCacheKey, entry)
return promise
},
searchJiraIssues: async (jql, limit = 30) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const siteId = getSelectedSiteId(get().jiraStatus)
const cacheKey = `${siteId ?? 'default'}::${jql}::${limit}`
const cached = get().jiraSearchCache[cacheKey]
@@ -211,36 +352,57 @@ export const createJiraSlice: StateCreator = (set,
return cached.data ?? []
}
const inflight = inflightSearchRequests.get(cacheKey)
- if (inflight) {
- return inflight
+ if (
+ inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === jiraMutationGeneration
+ ) {
+ return inflight.promise
}
+ let entry: InflightJiraReadRequest
+ const requestMutationGeneration = jiraMutationGeneration
const promise = jiraSearchIssues(get().settings, jql, limit, siteId)
.then((issues) => {
- set((s) => ({
- jiraSearchCache: evictStaleEntries({
- ...s.jiraSearchCache,
- [cacheKey]: { data: issues, fetchedAt: Date.now() }
- })
- }))
+ if (
+ inflightSearchRequests.get(cacheKey) === entry &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
+ set((s) => ({
+ jiraSearchCache: evictStaleEntries({
+ ...s.jiraSearchCache,
+ [cacheKey]: { data: issues, fetchedAt: Date.now() }
+ })
+ }))
+ }
return issues
})
.catch((error) => {
console.warn('[jira] searchJiraIssues failed:', error)
- if (isIntegrationCredentialDecryptionError(error)) {
+ if (
+ isIntegrationCredentialDecryptionError(error) &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
void get().checkJiraConnection()
- } else if (looksLikeAuthError(error)) {
+ } else if (
+ looksLikeAuthError(error) &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
set({ jiraStatus: { connected: false, viewer: null } })
}
return []
})
.finally(() => {
- inflightSearchRequests.delete(cacheKey)
+ if (inflightSearchRequests.get(cacheKey) === entry) {
+ inflightSearchRequests.delete(cacheKey)
+ }
})
- inflightSearchRequests.set(cacheKey, promise)
+ entry = { promise, contextKey, mutationGeneration: requestMutationGeneration }
+ inflightSearchRequests.set(cacheKey, entry)
return promise
},
listJiraIssues: async (filter = 'assigned', limit = 30) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const siteId = getSelectedSiteId(get().jiraStatus)
const cacheKey = `${siteId ?? 'default'}::list::${filter}::${limit}`
const cached = get().jiraSearchCache[cacheKey]
@@ -248,32 +410,52 @@ export const createJiraSlice: StateCreator = (set,
return cached.data ?? []
}
const inflight = inflightListRequests.get(cacheKey)
- if (inflight) {
- return inflight
+ if (
+ inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === jiraMutationGeneration
+ ) {
+ return inflight.promise
}
+ let entry: InflightJiraReadRequest
+ const requestMutationGeneration = jiraMutationGeneration
const promise = jiraListIssues(get().settings, filter, limit, siteId)
.then((issues) => {
- set((s) => ({
- jiraSearchCache: evictStaleEntries({
- ...s.jiraSearchCache,
- [cacheKey]: { data: issues, fetchedAt: Date.now() }
- })
- }))
+ if (
+ inflightListRequests.get(cacheKey) === entry &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
+ set((s) => ({
+ jiraSearchCache: evictStaleEntries({
+ ...s.jiraSearchCache,
+ [cacheKey]: { data: issues, fetchedAt: Date.now() }
+ })
+ }))
+ }
return issues
})
.catch((error) => {
console.warn('[jira] listJiraIssues failed:', error)
- if (isIntegrationCredentialDecryptionError(error)) {
+ if (
+ isIntegrationCredentialDecryptionError(error) &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
void get().checkJiraConnection()
- } else if (looksLikeAuthError(error)) {
+ } else if (
+ looksLikeAuthError(error) &&
+ canWriteJiraReadResult(contextKey, requestMutationGeneration, get().settings)
+ ) {
set({ jiraStatus: { connected: false, viewer: null } })
}
return []
})
.finally(() => {
- inflightListRequests.delete(cacheKey)
+ if (inflightListRequests.get(cacheKey) === entry) {
+ inflightListRequests.delete(cacheKey)
+ }
})
- inflightListRequests.set(cacheKey, promise)
+ entry = { promise, contextKey, mutationGeneration: requestMutationGeneration }
+ inflightListRequests.set(cacheKey, entry)
return promise
},
diff --git a/src/renderer/src/store/slices/linear.test.ts b/src/renderer/src/store/slices/linear.test.ts
index 6f40e1adc7b..60a39897eae 100644
--- a/src/renderer/src/store/slices/linear.test.ts
+++ b/src/renderer/src/store/slices/linear.test.ts
@@ -757,6 +757,61 @@ describe('createLinearSlice', () => {
expect(store.getState().linearStatus.viewer?.email).toBe('test@example.com')
})
+ it('ignores stale status responses after the active runtime changes', async () => {
+ const localStatus = deferred()
+ const remoteStatus = deferred()
+ const localViewer = {
+ displayName: 'Local User',
+ email: 'local@example.com',
+ organizationName: 'Local Org'
+ }
+ const remoteViewer = {
+ displayName: 'Remote User',
+ email: 'remote@example.com',
+ organizationName: 'Remote Org'
+ }
+ linearStatus.mockReturnValueOnce(localStatus.promise).mockReturnValueOnce(remoteStatus.promise)
+ const store = createTestStore()
+
+ const localRequest = store.getState().checkLinearConnection()
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+ const remoteRequest = store.getState().checkLinearConnection()
+
+ remoteStatus.resolve({ connected: true, viewer: remoteViewer })
+ await remoteRequest
+ expect(store.getState().linearStatus.viewer?.email).toBe('remote@example.com')
+ expect(store.getState().linearStatusContextKey).toBe('runtime:runtime-1#0')
+
+ localStatus.resolve({ connected: true, viewer: localViewer })
+ await localRequest
+ expect(store.getState().linearStatus.viewer?.email).toBe('remote@example.com')
+ expect(store.getState().linearStatusContextKey).toBe('runtime:runtime-1#0')
+ })
+
+ it('ignores stale list cache writes after the active runtime changes', async () => {
+ const localList = deferred>()
+ const remoteList = deferred>()
+ linearListIssues.mockReturnValueOnce(localList.promise).mockReturnValueOnce(remoteList.promise)
+ const store = createTestStore()
+ store.setState({ linearStatus: { connected: true, viewer: null } })
+
+ const localRequest = store.getState().listLinearIssues('assigned', 20)
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+ const remoteRequest = store.getState().listLinearIssues('assigned', 20)
+
+ remoteList.resolve({ items: [issue('LIN-REMOTE')] })
+ await remoteRequest
+ expect(
+ store.getState().getCachedLinearIssues({ kind: 'list', filter: 'assigned', limit: 20 })
+ ).toMatchObject({ items: [{ id: 'LIN-REMOTE' }] })
+
+ localList.resolve({ items: [issue('LIN-LOCAL')] })
+ await localRequest
+ expect(
+ store.getState().getCachedLinearIssues({ kind: 'list', filter: 'assigned', limit: 20 })
+ ).toMatchObject({ items: [{ id: 'LIN-REMOTE' }] })
+ })
+
it('ignores stale status checks after a successful connect', async () => {
const staleMountCheck = deferred()
const freshConnectCheck = deferred()
@@ -787,6 +842,29 @@ describe('createLinearSlice', () => {
expect(store.getState().linearStatus.viewer?.email).toBe('test@example.com')
})
+ it('ignores stale connect results after the active runtime changes', async () => {
+ const connectResult = deferred<{ ok: true; viewer: LinearViewer }>()
+ const viewer = {
+ displayName: 'Local User',
+ email: 'local@example.com',
+ organizationName: 'Local Org'
+ }
+ linearConnect.mockReturnValueOnce(connectResult.promise)
+ const store = createTestStore()
+
+ const connectPromise = store.getState().connectLinear('linear-key')
+ store.setState({ settings: { activeRuntimeEnvironmentId: 'runtime-1' } as never })
+
+ connectResult.resolve({ ok: true, viewer })
+ await expect(connectPromise).resolves.toEqual({
+ ok: false,
+ error: 'Linear connection was superseded by a newer request.'
+ })
+
+ expect(store.getState().linearStatus.connected).toBe(false)
+ expect(store.getState().linearStatusContextKey).toBeNull()
+ })
+
it('does not let a background status refresh cancel an in-flight connect', async () => {
const connectResult = deferred<{ ok: true; viewer: LinearViewer }>()
const backgroundStatus = deferred()
diff --git a/src/renderer/src/store/slices/linear.ts b/src/renderer/src/store/slices/linear.ts
index eb078d53cf9..27fa90cdee6 100644
--- a/src/renderer/src/store/slices/linear.ts
+++ b/src/renderer/src/store/slices/linear.ts
@@ -40,6 +40,8 @@ import {
linearStatus,
linearTestConnection
} from '@/runtime/runtime-linear-client'
+import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
+import { translate } from '@/i18n/i18n'
const CACHE_TTL = 60_000 // 60s — same as GitHub work-items revalidation TTL
const TEAM_CACHE_TTL = 10 * 60_000 // Teams change rarely and block visible Linear rows.
@@ -73,6 +75,8 @@ function looksLikeAuthError(error: unknown): boolean {
type InflightLinearIssueRequest = {
promise: Promise
generation: number
+ contextKey: string
+ mutationGeneration: number
}
function workspaceErrorType(error: unknown): LinearWorkspaceError['type'] {
@@ -105,20 +109,28 @@ type InflightLinearListRequest = {
promise: Promise
force: boolean
generation: number
+ contextKey: string
+ mutationGeneration: number
}
type InflightLinearPlainListRequest = {
promise: Promise>
force: boolean
generation: number
+ contextKey: string
+ mutationGeneration: number
}
type InflightLinearCollectionRequest = {
promise: Promise>
force: boolean
generation: number
+ contextKey: string
+ mutationGeneration: number
}
type InflightLinearDetailRequest = {
promise: Promise
force: boolean
+ contextKey: string
+ mutationGeneration: number
}
const inflightSearchRequests = new Map()
@@ -127,6 +139,8 @@ type InflightLinearTeamRequest = {
promise: Promise
force: boolean
generation: number
+ contextKey: string
+ mutationGeneration: number
}
const inflightTeamRequests = new Map()
@@ -155,7 +169,7 @@ const inflightCustomViewProjectRequests = new Map<
string,
InflightLinearCollectionRequest
>()
-let inflightStatusRequest: Promise | null = null
+let inflightStatusRequest: { contextKey: string; promise: Promise } | null = null
let linearStatusReadGeneration = 0
let linearMutationGeneration = 0
let linearCacheGeneration = 0
@@ -341,9 +355,30 @@ function isCurrentLinearMutation(generation: number): boolean {
return generation === linearMutationGeneration
}
+function isCurrentLinearRuntimeContext(
+ contextKey: string,
+ settings: AppState['settings']
+): boolean {
+ return getProviderRuntimeContextKey(settings) === contextKey
+}
+
+function canWriteLinearReadResult(
+ contextKey: string,
+ generation: number,
+ mutationGeneration: number,
+ settings: AppState['settings']
+): boolean {
+ return (
+ generation === linearCacheGeneration &&
+ mutationGeneration === linearMutationGeneration &&
+ isCurrentLinearRuntimeContext(contextKey, settings)
+ )
+}
+
export type LinearSlice = {
linearStatus: LinearConnectionStatus
linearStatusChecked: boolean
+ linearStatusContextKey: string | null
linearIssueCache: Record>
linearSearchCache: Record>
linearListCache: Record>>
@@ -446,6 +481,7 @@ export type LinearSlice = {
export const createLinearSlice: StateCreator = (set, get) => ({
linearStatus: { connected: false, viewer: null },
linearStatusChecked: false,
+ linearStatusContextKey: null,
linearIssueCache: {},
linearSearchCache: {},
linearListCache: {},
@@ -459,17 +495,22 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewProjectCache: {},
checkLinearConnection: async (force = false) => {
- if (inflightStatusRequest && !force) {
- return inflightStatusRequest
+ const contextKey = getProviderRuntimeContextKey(get().settings)
+ if (inflightStatusRequest && !force && inflightStatusRequest.contextKey === contextKey) {
+ return inflightStatusRequest.promise
+ }
+ if (get().linearStatusContextKey !== contextKey) {
+ set({ linearStatusChecked: false })
}
const mutationGeneration = linearMutationGeneration
const statusReadGeneration = (linearStatusReadGeneration += 1)
- inflightStatusRequest = linearStatus(get().settings)
+ const request = linearStatus(get().settings)
.then((status) => {
if (
mutationGeneration !== linearMutationGeneration ||
- statusReadGeneration !== linearStatusReadGeneration
+ statusReadGeneration !== linearStatusReadGeneration ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
) {
return
}
@@ -492,16 +533,20 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewDetailCache: {},
linearCustomViewIssueCache: {},
linearCustomViewProjectCache: {},
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
} else if (!get().linearStatusChecked) {
- set({ linearStatusChecked: true })
+ set({ linearStatusChecked: true, linearStatusContextKey: contextKey })
+ } else if (get().linearStatusContextKey !== contextKey) {
+ set({ linearStatusContextKey: contextKey })
}
})
.catch(() => {
if (
mutationGeneration !== linearMutationGeneration ||
- statusReadGeneration !== linearStatusReadGeneration
+ statusReadGeneration !== linearStatusReadGeneration ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
) {
return
}
@@ -520,29 +565,46 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewDetailCache: {},
linearCustomViewIssueCache: {},
linearCustomViewProjectCache: {},
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
} else if (!get().linearStatusChecked) {
- set({ linearStatusChecked: true })
+ set({ linearStatusChecked: true, linearStatusContextKey: contextKey })
+ } else if (get().linearStatusContextKey !== contextKey) {
+ set({ linearStatusContextKey: contextKey })
}
})
.finally(() => {
- if (statusReadGeneration === linearStatusReadGeneration) {
+ if (
+ statusReadGeneration === linearStatusReadGeneration &&
+ inflightStatusRequest?.promise === request
+ ) {
inflightStatusRequest = null
}
})
+ inflightStatusRequest = { contextKey, promise: request }
- return inflightStatusRequest
+ return request
},
testLinearConnection: async (workspaceId) => {
const requestGeneration = beginLinearMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
try {
const result = (await linearTestConnection(get().settings, workspaceId)) as
| { ok: true; viewer: LinearViewer }
| { ok: false; error: string }
+ if (
+ !isCurrentLinearMutation(requestGeneration) ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
+ return result
+ }
const status = await linearStatus(get().settings)
- if (isCurrentLinearMutation(requestGeneration)) {
+ if (
+ isCurrentLinearMutation(requestGeneration) &&
+ isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
const prev = get().linearStatus
if (linearStatusScopeSignature(prev) !== linearStatusScopeSignature(status)) {
invalidateLinearCaches()
@@ -559,10 +621,15 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewDetailCache: {},
linearCustomViewIssueCache: {},
linearCustomViewProjectCache: {},
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
} else {
- set({ linearStatus: status, linearStatusChecked: true })
+ set({
+ linearStatus: status,
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
+ })
}
}
return result
@@ -574,9 +641,14 @@ export const createLinearSlice: StateCreator = (s
connectLinear: async (apiKey: string) => {
const requestGeneration = beginLinearMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
try {
const result = await linearConnect(get().settings, apiKey)
- if (result.ok && isCurrentLinearMutation(requestGeneration)) {
+ if (
+ result.ok &&
+ isCurrentLinearMutation(requestGeneration) &&
+ isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
invalidateLinearCaches()
set({
linearIssueCache: {},
@@ -592,13 +664,31 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewProjectCache: {}
})
const status = await linearStatus(get().settings)
- if (!isCurrentLinearMutation(requestGeneration)) {
- return result as { ok: true; viewer: LinearViewer } | { ok: false; error: string }
+ if (
+ !isCurrentLinearMutation(requestGeneration) ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
+ return {
+ ok: false as const,
+ error: translate(
+ 'auto.store.slices.linear.37d36984d0',
+ 'Linear connection was superseded by a newer request.'
+ )
+ }
}
set({
linearStatus: status,
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
+ } else if (result.ok) {
+ return {
+ ok: false as const,
+ error: translate(
+ 'auto.store.slices.linear.37d36984d0',
+ 'Linear connection was superseded by a newer request.'
+ )
+ }
}
return result as { ok: true; viewer: LinearViewer } | { ok: false; error: string }
} catch (error) {
@@ -609,8 +699,12 @@ export const createLinearSlice: StateCreator = (s
selectLinearWorkspace: async (workspaceId) => {
const requestGeneration = beginLinearMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const status = await linearSelectWorkspace(get().settings, workspaceId)
- if (!isCurrentLinearMutation(requestGeneration)) {
+ if (
+ !isCurrentLinearMutation(requestGeneration) ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
return
}
invalidateLinearCaches()
@@ -627,14 +721,19 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewDetailCache: {},
linearCustomViewIssueCache: {},
linearCustomViewProjectCache: {},
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
},
disconnectLinear: async () => {
const requestGeneration = beginLinearMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
await linearDisconnect(get().settings)
- if (!isCurrentLinearMutation(requestGeneration)) {
+ if (
+ !isCurrentLinearMutation(requestGeneration) ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
return
}
invalidateLinearCaches()
@@ -651,15 +750,26 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewDetailCache: {},
linearCustomViewIssueCache: {},
linearCustomViewProjectCache: {},
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
},
disconnectLinearWorkspace: async (workspaceId) => {
const requestGeneration = beginLinearMutation()
+ const contextKey = getProviderRuntimeContextKey(get().settings)
await linearDisconnectWorkspace(get().settings, workspaceId)
+ if (
+ !isCurrentLinearMutation(requestGeneration) ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
+ return
+ }
const status = await linearStatus(get().settings)
- if (!isCurrentLinearMutation(requestGeneration)) {
+ if (
+ !isCurrentLinearMutation(requestGeneration) ||
+ !isCurrentLinearRuntimeContext(contextKey, get().settings)
+ ) {
return
}
invalidateLinearCaches()
@@ -676,11 +786,13 @@ export const createLinearSlice: StateCreator = (s
linearCustomViewDetailCache: {},
linearCustomViewIssueCache: {},
linearCustomViewProjectCache: {},
- linearStatusChecked: true
+ linearStatusChecked: true,
+ linearStatusContextKey: contextKey
})
},
fetchLinearIssue: async (id: string, workspaceId?: string | null) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const issueCacheKey = `${workspaceId ?? 'selected'}::${id}`
const cached = get().linearIssueCache[issueCacheKey] ?? get().linearIssueCache[id]
if (isFresh(cached)) {
@@ -688,18 +800,28 @@ export const createLinearSlice: StateCreator = (s
}
const inflight = inflightIssueRequests.get(issueCacheKey)
- if (inflight) {
+ if (
+ inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === linearMutationGeneration
+ ) {
return inflight.promise
}
let entry: InflightLinearIssueRequest
const requestCacheGeneration = linearCacheGeneration
+ const requestMutationGeneration = linearMutationGeneration
const promise = linearGetIssue(get().settings, id, workspaceId)
.then((issue) => {
const data = issue as LinearIssue | null
if (
inflightIssueRequests.get(issueCacheKey) === entry &&
- requestCacheGeneration === linearCacheGeneration
+ canWriteLinearReadResult(
+ contextKey,
+ requestCacheGeneration,
+ requestMutationGeneration,
+ get().settings
+ )
) {
set((s) => ({
linearIssueCache: evictStaleEntries({
@@ -712,7 +834,15 @@ export const createLinearSlice: StateCreator = (s
})
.catch((error) => {
console.warn('[linear] fetchLinearIssue failed:', error)
- if (isIntegrationCredentialDecryptionError(error) || looksLikeAuthError(error)) {
+ if (
+ (isIntegrationCredentialDecryptionError(error) || looksLikeAuthError(error)) &&
+ canWriteLinearReadResult(
+ contextKey,
+ requestCacheGeneration,
+ requestMutationGeneration,
+ get().settings
+ )
+ ) {
void get().checkLinearConnection(true)
}
return null
@@ -723,7 +853,12 @@ export const createLinearSlice: StateCreator = (s
}
})
- entry = { promise, generation: requestCacheGeneration }
+ entry = {
+ promise,
+ generation: requestCacheGeneration,
+ contextKey,
+ mutationGeneration: requestMutationGeneration
+ }
inflightIssueRequests.set(issueCacheKey, entry)
return promise
},
@@ -740,11 +875,18 @@ export const createLinearSlice: StateCreator = (s
},
prefetchLinearIssues: (args) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const workspaceId = getSelectedWorkspaceId(get().linearStatus)
if (args.kind === 'search') {
const limit = args.limit ?? 20
const cacheKey = linearSearchCacheKey(workspaceId, args.query, limit)
- if (isFresh(get().linearSearchCache[cacheKey]) || inflightSearchRequests.has(cacheKey)) {
+ const inflight = inflightSearchRequests.get(cacheKey)
+ if (
+ isFresh(get().linearSearchCache[cacheKey]) ||
+ (inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === linearMutationGeneration)
+ ) {
return
}
void get()
@@ -754,7 +896,13 @@ export const createLinearSlice: StateCreator = (s
}
const limit = clampLinearIssueListLimit(args.limit)
const cacheKey = linearListCacheKey(workspaceId, args.filter ?? 'assigned', limit)
- if (isFresh(get().linearListCache[cacheKey]) || inflightListRequests.has(cacheKey)) {
+ const inflight = inflightListRequests.get(cacheKey)
+ if (
+ isFresh(get().linearListCache[cacheKey]) ||
+ (inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === linearMutationGeneration)
+ ) {
return
}
void get()
@@ -763,6 +911,7 @@ export const createLinearSlice: StateCreator = (s
},
searchLinearIssues: async (query: string, limit = 20, options) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const workspaceId = getSelectedWorkspaceId(get().linearStatus)
const cacheKey = linearSearchCacheKey(workspaceId, query, limit)
const cached = get().linearSearchCache[cacheKey]
@@ -771,18 +920,29 @@ export const createLinearSlice: StateCreator = (s
}
const inflight = inflightSearchRequests.get(cacheKey)
- if (inflight && (!options?.force || inflight.force)) {
+ if (
+ inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === linearMutationGeneration &&
+ (!options?.force || inflight.force)
+ ) {
return inflight.promise
}
let entry: InflightLinearListRequest
const requestCacheGeneration = linearCacheGeneration
+ const requestMutationGeneration = linearMutationGeneration
const promise = linearSearchIssues(get().settings, query, limit, workspaceId)
.then((issues) => {
const data = issues as LinearIssue[]
if (
inflightSearchRequests.get(cacheKey) === entry &&
- requestCacheGeneration === linearCacheGeneration
+ canWriteLinearReadResult(
+ contextKey,
+ requestCacheGeneration,
+ requestMutationGeneration,
+ get().settings
+ )
) {
set((s) => ({
linearSearchCache: evictStaleEntries({
@@ -795,7 +955,15 @@ export const createLinearSlice: StateCreator = (s
})
.catch((error) => {
console.warn('[linear] searchLinearIssues failed:', error)
- if (isIntegrationCredentialDecryptionError(error) || looksLikeAuthError(error)) {
+ if (
+ (isIntegrationCredentialDecryptionError(error) || looksLikeAuthError(error)) &&
+ canWriteLinearReadResult(
+ contextKey,
+ requestCacheGeneration,
+ requestMutationGeneration,
+ get().settings
+ )
+ ) {
if (!shouldRefreshStatusAfterRead(workspaceId)) {
void get().checkLinearConnection(true)
}
@@ -809,18 +977,30 @@ export const createLinearSlice: StateCreator = (s
}
if (
shouldRefreshStatusAfterRead(workspaceId) &&
- requestCacheGeneration === linearCacheGeneration
+ canWriteLinearReadResult(
+ contextKey,
+ requestCacheGeneration,
+ requestMutationGeneration,
+ get().settings
+ )
) {
void get().checkLinearConnection(true)
}
})
- entry = { promise, force: Boolean(options?.force), generation: requestCacheGeneration }
+ entry = {
+ promise,
+ force: Boolean(options?.force),
+ generation: requestCacheGeneration,
+ contextKey,
+ mutationGeneration: requestMutationGeneration
+ }
inflightSearchRequests.set(cacheKey, entry)
return promise
},
listLinearIssues: async (filter = 'assigned', limit = 20, options) => {
+ const contextKey = getProviderRuntimeContextKey(get().settings)
const workspaceId = getSelectedWorkspaceId(get().linearStatus)
const effectiveLimit = clampLinearIssueListLimit(limit)
const cacheKey = linearListCacheKey(workspaceId, filter, effectiveLimit)
@@ -830,12 +1010,18 @@ export const createLinearSlice: StateCreator = (s
}
const inflight = inflightListRequests.get(cacheKey)
- if (inflight && (!options?.force || inflight.force)) {
+ if (
+ inflight &&
+ inflight.contextKey === contextKey &&
+ inflight.mutationGeneration === linearMutationGeneration &&
+ (!options?.force || inflight.force)
+ ) {
return inflight.promise
}
let entry: InflightLinearPlainListRequest
const requestCacheGeneration = linearCacheGeneration
+ const requestMutationGeneration = linearMutationGeneration
const promise: Promise> = linearListIssues(
get().settings,
filter,
@@ -846,7 +1032,12 @@ export const createLinearSlice: StateCreator = (s
const data = result as LinearCollectionResult
if (
inflightListRequests.get(cacheKey) === entry &&
- requestCacheGeneration === linearCacheGeneration
+ canWriteLinearReadResult(
+ contextKey,
+ requestCacheGeneration,
+ requestMutationGeneration,
+ get().settings
+ )
) {
set((s) => ({
linearListCache: evictStaleEntries({
@@ -859,7 +1050,15 @@ export const createLinearSlice: StateCreator