@@ -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'
+ )}
@@ -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 {
@@ -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")}
{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.'
+ )}
{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.'
+ )}
- {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.'
+ )}
+
{/* 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.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.'
+ )}
+
- {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.'
+ )}
+
@@ -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 005/297] 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 006/297] 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 007/297] 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 008/297] 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 009/297] 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 010/297] 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 011/297] 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 012/297] 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 013/297] 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
- {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.'
+ )}
- {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.af49e2a19e", "The file is present, but Orca could not find valid `scripts` or `issueCommand` definitions.")}
+ {translate(
+ 'auto.components.settings.RepositoryHooksSection.af49e2a19e',
+ 'The file is present, but Orca could not find valid `scripts` or `issueCommand` definitions.'
+ )}
+
- {PARSE_ERROR_FIXES.map((fix) => (
+ {parseErrorFixes.map((fix) => (
{fix}
@@ -1001,12 +1327,6 @@ export function RepositoryHooksSection({
)
}
-const PARSE_ERROR_FIXES = [
- 'Check the indentation under `scripts:`. Hook keys should use two spaces, and command lines should use four.',
- 'Define only the supported keys: `scripts`, `setup`, `archive`, and `issueCommand`.',
- 'Compare your file against the working template below and copy that shape if needed.'
-]
-
function renderYamlScriptPreview(hooks: OrcaHooks | null): string {
const fmt = (key: string, cmd?: string): string =>
cmd ? `\n ${key}: |\n${cmd.replace(/^/gm, ' ')}` : ''
diff --git a/src/renderer/src/components/sidebar/local-base-ref-suggestion-toast.tsx b/src/renderer/src/components/sidebar/local-base-ref-suggestion-toast.tsx
index 2516c43657b..1396c4875ee 100644
--- a/src/renderer/src/components/sidebar/local-base-ref-suggestion-toast.tsx
+++ b/src/renderer/src/components/sidebar/local-base-ref-suggestion-toast.tsx
@@ -34,7 +34,10 @@ function SuggestionToastBody({
deps: SuggestionToastDeps
}): React.JSX.Element {
const { updateSettings, getSettings, openSettingsPage, openSettingsTarget } = deps
- const commitNoun = suggestion.behind === 1 ? 'commit' : 'commits'
+ const commitNoun =
+ suggestion.behind === 1
+ ? translate('auto.components.sidebar.local.base.ref.suggestion.toast.commit', 'commit')
+ : translate('auto.components.sidebar.local.base.ref.suggestion.toast.commits', 'commits')
const keepLocalMainUpToDateTitle = getKeepLocalMainUpToDateTitle()
const turnOn = (): void => {
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index 9a46909a64b..ac912830e0e 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -3004,7 +3004,9 @@
"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}}"
+ "4a18052018": "Local {{value0}} is behind {{value1}}",
+ "commit": "commit",
+ "commits": "commits"
}
}
}
@@ -4902,6 +4904,12 @@
"95a0411b3e": "template",
"175daba180": "Example",
"b20c5df6ca": "Add an `orca.yaml` file to enable shared setup, archive, or issue-automation defaults for this repo. Example template:",
+ "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": "text-foreground",
"0cc712b823": "The core configuration file exists in the repo root, but Orca could not parse the supported hook definitions yet.",
"c90b858573": "text-amber-700 dark:text-amber-300",
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
index 5ec82f9370e..9f5aedddb0d 100644
--- a/src/renderer/src/i18n/locales/ja.json
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -3735,12 +3735,14 @@
"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}}"
+ "84c62e4d7f": "{{value0}} をオンにできませんでした",
+ "442552c656": "設定を開いてもう一度お試しください。",
+ "f15fd80989": "新しいワークツリーは最新ですが、ローカル {{value0}} は {{value1}} {{value2}} 遅れているため、AI diff が古い履歴と比較する可能性があります。Orca が自動で最新状態を保つようにできます。これはいつでもここで変更できます",
+ "3d260e1a5d": "設定 › {{value0}}",
+ "34a03a6565": "{{value0}} を最新の状態に保つ",
+ "4a18052018": "ローカル {{value0}} は {{value1}} より遅れています",
+ "commit": "コミット",
+ "commits": "コミット"
}
}
}
@@ -4887,6 +4889,12 @@
"95a0411b3e": "テンプレート",
"175daba180": "例",
"b20c5df6ca": "「orca.yaml」ファイルを追加して、このリポジトリの共有セットアップ、アーカイブ、またはイシュー自動化のデフォルトを有効にします。テンプレートの例:",
+ "56f9a4a1d0": "`orca.yaml` を使用中",
+ "623e0c9f31": "`orca.yaml` を解析できませんでした",
+ "5a67e4793d": "`orca.yaml` が見つかりません",
+ "07ba35bc68": "`scripts:` の下のインデントを確認してください。フックキーは2スペース、コマンド行は4スペースにします。",
+ "787ca433ef": "サポートされているキーのみを定義してください: `scripts`、`setup`、`archive`、`issueCommand`。",
+ "ecc73d9125": "下の動作するテンプレートと比較し、必要に応じてその形式をコピーしてください。",
"925f9e0dc4": "テキスト前景",
"0cc712b823": "コア構成ファイルはリポジトリ ルートに存在しますが、Orca はサポートされているフック定義をまだ解析できませんでした。",
"c90b858573": "テキスト-アンバー-700 ダーク:テキスト-アンバー-300",
@@ -7201,7 +7209,7 @@
"to": {
"date": {
"setting": {
- "f8bda25f29": "Keep Local Main Up to Date"
+ "f8bda25f29": "ローカル main を最新の状態に保つ"
}
}
}
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index 43d62cd9d26..ecd659e4778 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -3735,12 +3735,14 @@
"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}}"
+ "84c62e4d7f": "{{value0}}을(를) 켤 수 없습니다.",
+ "442552c656": "설정을 열고 다시 시도하세요.",
+ "f15fd80989": "새 워크트리는 최신 상태이지만 로컬 {{value0}}이(가) {{value1}} {{value2}} 뒤처져 있어 AI diff가 오래된 기록과 비교될 수 있습니다. Orca가 자동으로 최신 상태를 유지하도록 하세요. 언제든지 여기에서 변경할 수 있습니다",
+ "3d260e1a5d": "설정 › {{value0}}",
+ "34a03a6565": "{{value0}} 최신 상태로 유지",
+ "4a18052018": "로컬 {{value0}}이(가) {{value1}}보다 뒤처져 있습니다",
+ "commit": "커밋",
+ "commits": "커밋"
}
}
}
@@ -4887,6 +4889,12 @@
"95a0411b3e": "주형",
"175daba180": "예",
"b20c5df6ca": "이 저장소에 대한 공유 설정, 아카이브 또는 발행 자동화 기본값을 활성화하려면 `orca.yaml` 파일을 추가하세요. 예제 템플릿:",
+ "56f9a4a1d0": "`orca.yaml` 사용 중",
+ "623e0c9f31": "`orca.yaml`을 구문 분석할 수 없습니다",
+ "5a67e4793d": "`orca.yaml`을 찾을 수 없습니다",
+ "07ba35bc68": "`scripts:` 아래의 들여쓰기를 확인하세요. 후크 키는 두 칸, 명령 줄은 네 칸을 사용해야 합니다.",
+ "787ca433ef": "지원되는 키만 정의하세요: `scripts`, `setup`, `archive`, `issueCommand`.",
+ "ecc73d9125": "아래의 작동하는 템플릿과 비교하고 필요한 경우 그 형식을 복사하세요.",
"925f9e0dc4": "텍스트 전경",
"0cc712b823": "핵심 구성 파일이 저장소 루트에 있지만 Orca가 아직 지원되는 후크 정의를 구문 분석할 수 없습니다.",
"c90b858573": "텍스트-호박-700 어두움:텍스트-호박-300",
@@ -7201,7 +7209,7 @@
"to": {
"date": {
"setting": {
- "f8bda25f29": "Keep Local Main Up to Date"
+ "f8bda25f29": "로컬 main을 최신 상태로 유지"
}
}
}
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index ca63204c284..5ae4d89cbb7 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -3735,12 +3735,14 @@
"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}}"
+ "84c62e4d7f": "无法开启 {{value0}}",
+ "442552c656": "打开设置并重试。",
+ "f15fd80989": "新工作树是最新的,但本地 {{value0}} 落后 {{value1}} {{value2}},因此 AI 差异可能会与过时历史比较。让 Orca 自动保持它最新。可随时在",
+ "3d260e1a5d": "设置 › {{value0}}",
+ "34a03a6565": "保持 {{value0}} 最新",
+ "4a18052018": "本地 {{value0}} 落后于 {{value1}}",
+ "commit": "次提交",
+ "commits": "次提交"
}
}
}
@@ -4887,6 +4889,12 @@
"95a0411b3e": "模板",
"175daba180": "例子",
"b20c5df6ca": "添加“orca.yaml”文件以启用此存储库的共享设置、存档或议题自动化默认值。示例模板:",
+ "56f9a4a1d0": "正在使用 `orca.yaml`",
+ "623e0c9f31": "无法解析 `orca.yaml`",
+ "5a67e4793d": "未检测到 `orca.yaml`",
+ "07ba35bc68": "检查 `scripts:` 下的缩进。钩子键应使用两个空格,命令行应使用四个空格。",
+ "787ca433ef": "仅定义支持的键:`scripts`、`setup`、`archive` 和 `issueCommand`。",
+ "ecc73d9125": "将你的文件与下面可用的模板进行比较,并在需要时复制该结构。",
"925f9e0dc4": "文本前景",
"0cc712b823": "核心配置文件存在于存储库根目录中,但 Orca 尚无法解析支持的钩子定义。",
"c90b858573": "文本-Amber-700 深色:文本-Amber-300",
@@ -6400,7 +6408,7 @@
"28192e3a63": "掌握",
"e3e9adde59": "主要的",
"0e993bf00f": "当您创建工作区时,Orca 会刷新远程库并安全地快进匹配的本地分支,例如 main 或 master。这使得像 git diff main...HEAD 这样的命令无法与过时的历史记录进行比较。如果该分支有未提交的更改或仅限本地提交,Orca 会跳过更新。",
- "f8bda25f29": "保持本地主要更新",
+ "f8bda25f29": "保持本地 main 最新",
"769ddd7f81": "风俗",
"1d2fae1fa2": "git 用户名",
"f83c8937c4": "分支命名",
@@ -7201,7 +7209,7 @@
"to": {
"date": {
"setting": {
- "f8bda25f29": "Keep Local Main Up to Date"
+ "f8bda25f29": "保持本地 main 最新"
}
}
}
From b07cfae966ae072e578607a89bfbff4db08de0dd Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 09:10:37 -0700
Subject: [PATCH 014/297] Fix task page labels after language changes (#5086)
Co-authored-by: Orca
---
src/renderer/src/components/TaskPage.tsx | 243 ++++--------------
.../task-page-localized-options.test.ts | 58 +++++
.../task-page-localized-options.tsx | 207 +++++++++++++++
3 files changed, 314 insertions(+), 194 deletions(-)
create mode 100644 src/renderer/src/components/task-page-localized-options.test.ts
create mode 100644 src/renderer/src/components/task-page-localized-options.tsx
diff --git a/src/renderer/src/components/TaskPage.tsx b/src/renderer/src/components/TaskPage.tsx
index ae2c66caa3a..e1480a4dd15 100644
--- a/src/renderer/src/components/TaskPage.tsx
+++ b/src/renderer/src/components/TaskPage.tsx
@@ -3,6 +3,7 @@ task source controls, and GitHub task list co-located so the wiring between the
selected repo, the task filters, and the work-item list stays readable in one
place while this surface is still evolving. */
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { useTranslation } from 'react-i18next'
import { useShallow } from 'zustand/react/shallow'
import {
AlertCircle,
@@ -19,11 +20,8 @@ import {
ExternalLink,
Eye,
Files,
- Github,
- Gitlab,
GitMerge,
GitPullRequest,
- LayoutGrid,
List,
LoaderCircle,
Lock,
@@ -224,26 +222,30 @@ import {
resolveVisibleTaskProvider
} from '../../../shared/task-providers'
import { translate } from '@/i18n/i18n'
-
-type TaskSource = TaskProvider
-
-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') }
-]
-
-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')
- }
-]
+import {
+ getGitHubModeButtons,
+ getGitHubTaskKindPresets,
+ getGitLabIssueFilters,
+ getGitLabMRFilters,
+ getJiraPresets,
+ getLinearDisplayProperties,
+ getLinearGroupOptions,
+ getLinearModeOptions,
+ getLinearOrderOptions,
+ getLinearPriorityLabel,
+ getLinearViewOptions,
+ getSourceOptions,
+ type GitHubTaskKind,
+ type GitLabIssueFilter,
+ type GitLabTaskFilter,
+ type JiraPresetId,
+ LinearIcon,
+ type LinearDisplayProperty,
+ type LinearGroupBy,
+ type LinearMode,
+ type LinearOrderBy,
+ type LinearViewMode
+} from '@/components/task-page-localized-options'
function isGitLabMRFilter(value: GitLabTaskFilter | GitLabIssueFilter): value is GitLabTaskFilter {
return value === 'opened' || value === 'merged' || value === 'closed' || value === 'all'
@@ -254,95 +256,6 @@ function isGitLabIssueFilter(
): value is GitLabIssueFilter {
return value === 'opened' || value === 'assigned-to-me'
}
-type TaskQueryPreset = {
- id: TaskViewPresetId
- label: string
- query: string
-}
-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')
- }
-]
-
-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')
- }
-]
-
-function getGitHubTaskKindPresets(kind: GitHubTaskKind): TaskQueryPreset[] {
- return kind === 'prs' ? PR_TASK_QUERY_PRESETS : ISSUE_TASK_QUERY_PRESETS
-}
-
-type SourceOption = {
- id: TaskSource
- label: string
- Icon: (props: { className?: string }) => React.JSX.Element
- disabled?: boolean
-}
-
-function LinearIcon({ className }: { className?: string }): React.JSX.Element {
- return (
-
- )
-}
-
-const SOURCE_OPTIONS: SourceOption[] = [
- {
- id: 'github',
- label: translate('auto.components.TaskPage.acef77f7ca', 'GitHub'),
- Icon: ({ className }) =>
- },
- {
- id: 'gitlab',
- label: translate('auto.components.TaskPage.11a828abf8', 'GitLab'),
- Icon: ({ className }) =>
- },
- {
- id: 'linear',
- label: translate('auto.components.TaskPage.8675cd6188', 'Linear'),
- Icon: ({ className }) =>
- },
- {
- id: 'jira',
- label: translate('auto.components.TaskPage.9cd11ba218', 'Jira'),
- Icon: ({ className }) =>
- }
-]
-
-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') }
-]
const TASK_SEARCH_DEBOUNCE_MS = 300
const LINEAR_ITEM_LIMIT = 36
@@ -407,14 +320,6 @@ const GITHUB_TASK_STICKY_TITLE_CELL_CLASS = cn(
GITHUB_TASK_ROW_HOVER_SURFACE_CLASS
)
-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') }
-]
-
function isPRFocusedTaskView(preset: TaskViewPresetId | null, query: string): boolean {
if (preset === 'prs' || preset === 'my-prs' || preset === 'review') {
return true
@@ -483,22 +388,7 @@ function formatRelativeTime(input: string): string {
return relativeTimeFormatter.format(diffDays, 'day')
}
-// Why: Linear encodes priority as an integer (0–4). Map to human-readable
-// labels so the table column is scannable without memorising the scale.
-const LINEAR_PRIORITY_LABELS: Record = {
- 0: 'None',
- 1: 'Urgent',
- 2: 'High',
- 3: 'Medium',
- 4: 'Low'
-}
-
-type LinearViewMode = 'list' | 'board'
-type LinearMode = 'issues' | 'projects' | 'views'
type LinearProjectTab = 'overview' | 'issues'
-type LinearGroupBy = 'none' | 'status' | 'assignee' | 'priority' | 'team'
-type LinearOrderBy = 'priority' | 'updated' | 'identifier'
-type LinearDisplayProperty = 'state' | 'priority' | 'assignee' | 'team' | 'labels' | 'updated'
type LinearGroupSection = {
key: string
@@ -512,27 +402,8 @@ 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') }
-]
-
const LINEAR_CUSTOM_VIEW_MODELS = ['issue', 'project'] satisfies readonly LinearCustomViewModel[]
-const LINEAR_VIEW_OPTIONS: {
- id: LinearViewMode
- 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
- }
-]
-
function mergeLinearCollectionResults(
results: LinearCollectionResult[]
): LinearCollectionResult {
@@ -544,29 +415,6 @@ 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') }
-]
-
-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') }
-]
-
-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') }
-]
-
const DEFAULT_LINEAR_DISPLAY_PROPERTIES: LinearDisplayProperty[] = [
'state',
'priority',
@@ -576,10 +424,6 @@ const DEFAULT_LINEAR_DISPLAY_PROPERTIES: LinearDisplayProperty[] = [
'updated'
]
-function getLinearPriorityLabel(priority: number): string {
- return LINEAR_PRIORITY_LABELS[priority] ?? `P${priority}`
-}
-
function getLinearStatusSectionState(section: LinearGroupSection): LinearIssue['state'] | null {
if (!section.key.startsWith('status:')) {
return null
@@ -2587,6 +2431,7 @@ const hasUpstreamCandidateDivergence = (
!sameGitHubOwnerRepo(s.sources.prs, s.sources.upstreamCandidate)
export default function TaskPage(): React.JSX.Element {
+ useTranslation()
const settings = useAppStore((s) => s.settings)
const persistedUIReady = useAppStore((s) => s.persistedUIReady)
const taskResumeState = useAppStore((s) => s.taskResumeState)
@@ -2744,9 +2589,19 @@ export default function TaskPage(): React.JSX.Element {
preflightStatus?.glab?.installed
]
)
+ const sourceOptions = getSourceOptions()
+ const githubModeButtons = getGitHubModeButtons()
+ const linearModeOptions = getLinearModeOptions()
+ const jiraPresets = getJiraPresets()
+ const gitLabIssueFilters = getGitLabIssueFilters()
+ const gitLabMRFilters = getGitLabMRFilters()
+ const linearViewOptions = getLinearViewOptions()
+ const linearGroupOptions = getLinearGroupOptions()
+ const linearOrderOptions = getLinearOrderOptions()
+ const linearDisplayPropertyOptions = getLinearDisplayProperties()
const visibleSourceOptions = useMemo(
- () => SOURCE_OPTIONS.filter((source) => visibleTaskProviders.includes(source.id)),
- [visibleTaskProviders]
+ () => sourceOptions.filter((source) => visibleTaskProviders.includes(source.id)),
+ [sourceOptions, visibleTaskProviders]
)
const hideTaskSource = useCallback(
(provider: TaskProvider, label: string) => {
@@ -2785,7 +2640,7 @@ export default function TaskPage(): React.JSX.Element {
const initialTaskQuery = getTaskPresetQuery(defaultTaskViewPreset)
const preferredTaskSource = pageData.taskSource ?? defaultTaskSource
- const [taskSource, setTaskSource] = useState(
+ const [taskSource, setTaskSource] = useState(
resolveVisibleTaskProvider(preferredTaskSource, visibleTaskProviders)
)
const taskSourceManuallyChangedRef = useRef(false)
@@ -6778,7 +6633,7 @@ export default function TaskPage(): React.JSX.Element {
- {JIRA_PRESETS.map((preset) => {
+ {jiraPresets.map((preset) => {
const active = !jiraSearchInput && activeJiraPreset === preset.id
return (
{gitlabView === 'issues' || gitlabView === 'mrs'
? (gitlabView === 'issues'
- ? GITLAB_ISSUE_FILTERS
- : GITLAB_MR_FILTERS
+ ? gitLabIssueFilters
+ : gitLabMRFilters
).map(({ id, label }) => {
const active = activeGitlabFilter === id
return (
@@ -8968,7 +8823,7 @@ export default function TaskPage(): React.JSX.Element {
'Linear view mode'
)}
>
- {LINEAR_VIEW_OPTIONS.map(({ id, label, Icon }) => {
+ {linearViewOptions.map(({ id, label, Icon }) => {
const active = linearViewMode === id
return (
@@ -9019,7 +8874,7 @@ export default function TaskPage(): React.JSX.Element {
value={linearViewMode}
onValueChange={(value) => setLinearViewMode(value as LinearViewMode)}
>
- {LINEAR_VIEW_OPTIONS.map(({ id, label, Icon }) => (
+ {linearViewOptions.map(({ id, label, Icon }) => (
{label}
@@ -9035,7 +8890,7 @@ export default function TaskPage(): React.JSX.Element {
value={linearGroupBy}
onValueChange={(value) => setLinearGroupBy(value as LinearGroupBy)}
>
- {LINEAR_GROUP_OPTIONS.map((option) => (
+ {linearGroupOptions.map((option) => (
{option.label}
@@ -9050,7 +8905,7 @@ export default function TaskPage(): React.JSX.Element {
value={linearOrderBy}
onValueChange={(value) => setLinearOrderBy(value as LinearOrderBy)}
>
- {LINEAR_ORDER_OPTIONS.map((option) => (
+ {linearOrderOptions.map((option) => (
{option.label}
@@ -9061,7 +8916,7 @@ export default function TaskPage(): React.JSX.Element {
{translate('auto.components.TaskPage.a26a48252e', 'Display properties')}
- {LINEAR_DISPLAY_PROPERTIES.map((property) => (
+ {linearDisplayPropertyOptions.map((property) => (
{
+ beforeEach(async () => {
+ await i18n.changeLanguage('en')
+ })
+
+ it('refreshes GitHub task labels when the UI language changes', async () => {
+ expect(getGitHubTaskKindPresets('issues').map((preset) => preset.label)).toEqual([
+ 'Open',
+ 'Assigned to me'
+ ])
+ expect(getGitHubModeButtons().map((button) => button.label)).toEqual([
+ 'Issues',
+ 'PRs',
+ 'Projects'
+ ])
+
+ await i18n.changeLanguage('ko')
+
+ expect(getGitHubTaskKindPresets('issues').map((preset) => preset.label)).toEqual([
+ '열기',
+ '나에게 할당됨'
+ ])
+ expect(getGitHubModeButtons().map((button) => button.label)).toEqual(['이슈', 'PR', '프로젝트'])
+
+ await i18n.changeLanguage('en')
+
+ expect(getGitHubTaskKindPresets('issues').map((preset) => preset.label)).toEqual([
+ 'Open',
+ 'Assigned to me'
+ ])
+ expect(getGitHubModeButtons().map((button) => button.label)).toEqual([
+ 'Issues',
+ 'PRs',
+ 'Projects'
+ ])
+ })
+
+ it('refreshes Linear priority labels when the UI language changes', async () => {
+ expect(getLinearPriorityLabel(0)).toBe('No priority')
+
+ await i18n.changeLanguage('ko')
+
+ expect(getLinearPriorityLabel(0)).toBe('우선순위 없음')
+
+ await i18n.changeLanguage('en')
+
+ expect(getLinearPriorityLabel(0)).toBe('No priority')
+ })
+})
diff --git a/src/renderer/src/components/task-page-localized-options.tsx b/src/renderer/src/components/task-page-localized-options.tsx
new file mode 100644
index 00000000000..3d0215785bb
--- /dev/null
+++ b/src/renderer/src/components/task-page-localized-options.tsx
@@ -0,0 +1,207 @@
+import React from 'react'
+import { Github, Gitlab, LayoutGrid, List } from 'lucide-react'
+
+import { JiraIcon } from '@/components/icons/JiraIcon'
+import { createLocalizedCatalog } from '@/i18n/localized-catalog'
+import { translate } from '@/i18n/i18n'
+import { getTaskPresetQuery } from '@/lib/new-workspace'
+import type { TaskProvider, TaskViewPresetId } from '../../../shared/types'
+
+export type GitLabTaskFilter = 'opened' | 'merged' | 'closed' | 'all'
+export type GitLabIssueFilter = 'opened' | 'assigned-to-me'
+
+export type TaskQueryPreset = {
+ id: TaskViewPresetId
+ label: string
+ query: string
+}
+
+export type GitHubTaskKind = 'issues' | 'prs'
+
+export type SourceOption = {
+ id: TaskProvider
+ label: string
+ Icon: (props: { className?: string }) => React.JSX.Element
+ disabled?: boolean
+}
+
+export type JiraPresetId = 'assigned' | 'reported' | 'all' | 'done'
+export type JiraPreset = { id: JiraPresetId; label: string }
+
+export type GitHubModeButton = { id: GitHubTaskKind | 'project'; label: string }
+
+export type LinearViewMode = 'list' | 'board'
+export type LinearMode = 'issues' | 'projects' | 'views'
+export type LinearGroupBy = 'none' | 'status' | 'assignee' | 'priority' | 'team'
+export type LinearOrderBy = 'priority' | 'updated' | 'identifier'
+export type LinearDisplayProperty =
+ | 'state'
+ | 'priority'
+ | 'assignee'
+ | 'team'
+ | 'labels'
+ | 'updated'
+
+export function LinearIcon({ className }: { className?: string }): React.JSX.Element {
+ return (
+
+ )
+}
+
+export const getGitLabMRFilters = createLocalizedCatalog(
+ (): { 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') }
+ ]
+)
+
+export const getGitLabIssueFilters = createLocalizedCatalog(
+ (): { 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')
+ }
+ ]
+)
+
+const getIssueTaskQueryPresets = createLocalizedCatalog((): 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')
+ }
+])
+
+const getPRTaskQueryPresets = createLocalizedCatalog((): 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')
+ }
+])
+
+export function getGitHubTaskKindPresets(kind: GitHubTaskKind): TaskQueryPreset[] {
+ return kind === 'prs' ? getPRTaskQueryPresets() : getIssueTaskQueryPresets()
+}
+
+export const getSourceOptions = createLocalizedCatalog((): SourceOption[] => [
+ {
+ id: 'github',
+ label: translate('auto.components.TaskPage.acef77f7ca', 'GitHub'),
+ Icon: ({ className }) =>
+ },
+ {
+ id: 'gitlab',
+ label: translate('auto.components.TaskPage.11a828abf8', 'GitLab'),
+ Icon: ({ className }) =>
+ },
+ {
+ id: 'linear',
+ label: translate('auto.components.TaskPage.8675cd6188', 'Linear'),
+ Icon: ({ className }) =>
+ },
+ {
+ id: 'jira',
+ label: translate('auto.components.TaskPage.9cd11ba218', 'Jira'),
+ Icon: ({ className }) =>
+ }
+])
+
+export const getJiraPresets = createLocalizedCatalog((): 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') }
+])
+
+export const getGitHubModeButtons = createLocalizedCatalog((): 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') }
+])
+
+export const getLinearModeOptions = createLocalizedCatalog(
+ (): { 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') }
+ ]
+)
+
+export const getLinearViewOptions = createLocalizedCatalog(
+ (): {
+ id: LinearViewMode
+ 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
+ }
+ ]
+)
+
+export const getLinearGroupOptions = createLocalizedCatalog(
+ (): { 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') }
+ ]
+)
+
+export const getLinearOrderOptions = createLocalizedCatalog(
+ (): { 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') }
+ ]
+)
+
+export const getLinearDisplayProperties = createLocalizedCatalog(
+ (): { 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') }
+ ]
+)
+
+export const getLinearPriorityLabels = createLocalizedCatalog(
+ (): Record => ({
+ 0: translate('auto.components.TaskPage.713179dfdc', 'No priority'),
+ 1: translate('auto.components.TaskPage.f373ab1a4f', 'Urgent'),
+ 2: translate('auto.components.TaskPage.345b169f1f', 'High'),
+ 3: translate('auto.components.TaskPage.7fd59c18d8', 'Medium'),
+ 4: translate('auto.components.TaskPage.69591944e7', 'Low')
+ })
+)
+
+export function getLinearPriorityLabel(priority: number): string {
+ return getLinearPriorityLabels()[priority] ?? `P${priority}`
+}
From 6c5522943e572017bcebe91e02c8776ca8c5e0d7 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 10 Jun 2026 16:55:12 +0000
Subject: [PATCH 015/297] release: v1.4.57
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 643026963b2..0fe629e2782 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca",
- "version": "1.4.56",
+ "version": "1.4.57",
"description": "Next-gen IDE for parallel agentic development",
"homepage": "https://github.com/stablyai/orca",
"author": "stablyai",
From 178b9bde86c2431feedfdd0383730cf2c450fb8c Mon Sep 17 00:00:00 2001
From: Borja <3930245+BorjaLL@users.noreply.github.com>
Date: Wed, 10 Jun 2026 18:41:32 +0100
Subject: [PATCH 016/297] Fix automation tabs showing a shell instead of the
live agent (#5099)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Fix automation tabs showing a shell instead of the live agent
Opening a background automation's terminal tab showed a bare shell while
the agent (Claude) kept running headless — the sidebar updated but the
pane was attached to the wrong PTY.
On first mount the restored ptyId equals the tab ptyId, and
isSessionOwnedByWorktree() returns true for it, so connectPanePty routed
the still-live eagerly-spawned PTY into the daemon-reattach branch
(transport.connect({ sessionId })), which spawns a fresh shell and
orphans the live agent PTY instead of adopting it via attach()+replay.
Part A: gate the deferred reattach on the absence of a live eager buffer.
A live eager buffer means the PTY is a still-running local session to
adopt (attach + replay), not a daemon session to re-connect. Daemon
reattach and remote PTYs are unaffected (gated on the eager buffer).
Part B: publish never-mounted background automation tabs into the runtime
graph (gated on a live eager buffer) so the live agent PTY binds to its
real tab instead of surfacing as an orphan `pty:` terminal — fixing
`orca terminal list`, the CLI, and automation session-reuse.
Adds a characterization test (fails on the old code, passes now) and a
runtime-graph publish test.
Co-Authored-By: Claude Opus 4.8 (1M context)
* Harden eager PTY tab adoption
Co-authored-by: Orca
---------
Co-authored-by: Claude Opus 4.8 (1M context)
Co-authored-by: Jinwoo-H
Co-authored-by: Orca
---
.../terminal-pane/pty-connection.test.ts | 103 +++++++++++++++
.../terminal-pane/pty-connection.ts | 30 ++++-
...sync-runtime-graph-automation-leaf.test.ts | 124 ++++++++++++++++++
.../src/runtime/sync-runtime-graph.ts | 50 +++++++
4 files changed, 305 insertions(+), 2 deletions(-)
create mode 100644 src/renderer/src/runtime/sync-runtime-graph-automation-leaf.test.ts
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 56a26406d8f..671e5e77beb 100644
--- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts
+++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts
@@ -7,6 +7,7 @@ import {
RESET_TERMINAL_CURSOR_STYLE
} from './layout-serialization'
import type * as UseNotificationDispatchModule from './use-notification-dispatch'
+import { getEagerPtyBufferHandle } from './pty-dispatcher'
import { makePaneKey } from '../../../../shared/stable-pane-id'
import type { TerminalLayoutSnapshot } from '../../../../shared/types'
@@ -209,6 +210,18 @@ vi.mock('./remote-runtime-pty-transport', () => ({
)
}))
+// Why: the adopt-vs-reattach decision consults the eager-PTY buffer registry to
+// tell a still-live locally-spawned PTY (attach + replay) from a daemon session
+// to re-connect. Keep the real module but stub the lookup so tests can simulate
+// a live eager buffer without standing up the real IPC dispatcher.
+vi.mock('./pty-dispatcher', async (importOriginal) => {
+ const actual = await importOriginal>()
+ return {
+ ...actual,
+ getEagerPtyBufferHandle: vi.fn(() => undefined)
+ }
+})
+
function createMockTransport(initialPtyId: string | null = null): MockTransport {
let ptyId = initialPtyId
const transport = {
@@ -2554,6 +2567,96 @@ describe('connectPanePty', () => {
expect(deps.syncPanePtyLayoutBinding).toHaveBeenCalledWith(2, 'leaf-pty-2')
})
+ it('adopts a still-live background PTY via attach instead of reattaching when an eager buffer exists', async () => {
+ // Why: background automation tabs spawn the agent PTY eagerly and register an
+ // eager buffer, then never mount until opened. On first mount the restored
+ // ptyId equals the tab ptyId, so without this guard the pane mis-routes into
+ // the daemon-reattach branch (connect) and spawns a fresh shell, orphaning the
+ // live agent PTY. A live eager buffer means "attach + replay", not "reattach".
+ const eagerPtyId = 'auto-eager-pty'
+ vi.mocked(getEagerPtyBufferHandle).mockImplementation((ptyId: string) =>
+ ptyId === eagerPtyId ? { flush: () => '', dispose: () => {} } : undefined
+ )
+ const { connectPanePty } = await import('./pty-connection')
+ const transport = createMockTransport()
+ transportFactoryQueue.push(transport)
+ mockStoreState = {
+ ...mockStoreState,
+ tabsByWorktree: { 'wt-1': [{ id: 'tab-1', ptyId: eagerPtyId }] },
+ ptyIdsByTabId: { 'tab-1': [eagerPtyId] },
+ terminalLayoutsByTabId: {
+ 'tab-1': {
+ root: { type: 'leaf', leafId: LEAF_1 },
+ activeLeafId: LEAF_1,
+ expandedLeafId: null,
+ ptyIdsByLeafId: { [LEAF_1]: eagerPtyId }
+ }
+ }
+ } as StoreState
+ const deps = createDeps({
+ restoredLeafId: LEAF_1,
+ restoredPtyIdByLeafId: { [LEAF_1]: eagerPtyId }
+ })
+
+ connectPanePty(createPane(1) as never, createManager(1) as never, deps as never)
+ await flushAsyncTicks()
+
+ expect(transport.attach).toHaveBeenCalledWith(
+ expect.objectContaining({ existingPtyId: eagerPtyId })
+ )
+ expect(transport.connect).not.toHaveBeenCalledWith(
+ expect.objectContaining({ sessionId: eagerPtyId })
+ )
+ const { hasPtySerializer } = await import('./pty-buffer-serializer')
+ expect(hasPtySerializer(eagerPtyId)).toBe(true)
+ })
+
+ it('does not adopt another tab live eager PTY from a stale restored leaf binding', async () => {
+ // Why: restored leaf bindings can outlive tab ownership. A global eager
+ // buffer only proves the PTY is alive; ptyIdsByTabId proves this tab owns it.
+ const otherTabPtyId = 'other-tab-eager-pty'
+ vi.mocked(getEagerPtyBufferHandle).mockImplementation((ptyId: string) =>
+ ptyId === otherTabPtyId ? { flush: () => '', dispose: () => {} } : undefined
+ )
+ const { connectPanePty } = await import('./pty-connection')
+ const transport = createMockTransport()
+ transport.connect.mockImplementation(async (opts: { sessionId?: string }) => {
+ if (opts.sessionId) {
+ return { id: opts.sessionId }
+ }
+ return 'fresh-pty'
+ })
+ transportFactoryQueue.push(transport)
+ mockStoreState = {
+ ...mockStoreState,
+ tabsByWorktree: {
+ 'wt-1': [
+ { id: 'tab-1', ptyId: 'tab-pty' },
+ { id: 'tab-2', ptyId: otherTabPtyId }
+ ]
+ },
+ ptyIdsByTabId: {
+ 'tab-1': ['tab-pty'],
+ 'tab-2': [otherTabPtyId]
+ }
+ } as StoreState
+ const deps = createDeps({
+ restoredLeafId: LEAF_1,
+ restoredPtyIdByLeafId: { [LEAF_1]: otherTabPtyId }
+ })
+
+ connectPanePty(createPane(1) as never, createManager(1) as never, deps as never)
+ await flushAsyncTicks()
+
+ expect(transport.attach).not.toHaveBeenCalledWith(
+ expect.objectContaining({ existingPtyId: otherTabPtyId })
+ )
+ expect(transport.connect).not.toHaveBeenCalledWith(
+ expect.objectContaining({ sessionId: otherTabPtyId })
+ )
+ expect(deps.updateTabPtyId).not.toHaveBeenCalledWith('tab-1', otherTabPtyId)
+ })
+
it('spawns a fresh PTY when a restored daemon split session cannot reattach', async () => {
const { connectPanePty } = await import('./pty-connection')
const transport = createMockTransport()
diff --git a/src/renderer/src/components/terminal-pane/pty-connection.ts b/src/renderer/src/components/terminal-pane/pty-connection.ts
index 8778c102758..4e76375ed50 100644
--- a/src/renderer/src/components/terminal-pane/pty-connection.ts
+++ b/src/renderer/src/components/terminal-pane/pty-connection.ts
@@ -75,6 +75,7 @@ import {
} from './terminal-bracketed-paste'
import { createCommandCodeOutputStatusDetector } from './command-code-output-status'
import type { PtyDataMeta } from './pty-dispatcher'
+import { getEagerPtyBufferHandle } from './pty-dispatcher'
import { createTerminalGitHubPRLinkDetector } from '@/lib/terminal-github-pr-link-detector'
import { installConptyDeviceAttributesHandler } from './terminal-conpty-device-attributes'
import {
@@ -3030,6 +3031,24 @@ export function connectPanePty(
restoredSessionId && restoredSessionId !== detachedLivePtyId
? restoredSessionId
: detachedLivePtyId
+ const currentTabLivePtyIds = storeSnapshot.ptyIdsByTabId[deps.tabId] ?? []
+ const candidateHasEagerBuffer = Boolean(
+ candidateReattachSessionId &&
+ !isRemoteRuntimePtyId(candidateReattachSessionId) &&
+ getEagerPtyBufferHandle(candidateReattachSessionId)
+ )
+ // Why: a still-live locally-spawned PTY (e.g. a background automation agent
+ // launched before its tab mounts) keeps an eager buffer until a pane adopts
+ // it. Such a PTY must be adopted via attach()+replay, not re-connected as a
+ // daemon session — connect({ sessionId }) on a non-session ptyId spawns a
+ // fresh shell and orphans the live agent. Presence of an eager buffer plus
+ // current-tab live ownership is the discriminator; route these to attach.
+ const eagerLivePtyId =
+ candidateReattachSessionId &&
+ candidateHasEagerBuffer &&
+ currentTabLivePtyIds.includes(candidateReattachSessionId)
+ ? candidateReattachSessionId
+ : null
// Why: daemon session IDs encode `${worktreeId}@@${uuid}`. After a daemon
// crash + cold restore, corrupted or stale session-to-tab mappings can
// cause a tab in workspace A to hold a ptyId from workspace B. Restoring
@@ -3038,6 +3057,7 @@ export function connectPanePty(
const deferredReattachSessionId =
candidateReattachSessionId &&
!isRemoteRuntimePtyId(candidateReattachSessionId) &&
+ !candidateHasEagerBuffer &&
isSessionOwnedByWorktree(candidateReattachSessionId, deps.worktreeId)
? candidateReattachSessionId
: null
@@ -3130,11 +3150,14 @@ export function connectPanePty(
prepareColdRestoreAgentResumeCommand()
startFreshSpawn()
})
- } else if (detachedRemoteLeafPtyId || detachedLivePtyId) {
+ } else if (detachedRemoteLeafPtyId || detachedLivePtyId || eagerLivePtyId) {
// Why: mirrored web terminal layouts mount one pane per host leaf.
// Later leaves already have a pane transport, but must still attach to
// their exact remote PTY instead of spawning replacement host tabs.
- const attachPtyId = detachedRemoteLeafPtyId ?? detachedLivePtyId!
+ // eagerLivePtyId covers a still-live background PTY (e.g. an automation
+ // agent) whose restored id may not equal the tab ptyId yet still has a
+ // live eager buffer to adopt.
+ const attachPtyId = detachedRemoteLeafPtyId ?? detachedLivePtyId ?? eagerLivePtyId!
recordPtyConnectDiagnostic(`pane=${pane.id} -> ATTACH detached=${attachPtyId}`)
allowInitialIdleCacheSeed = false
// Why: surface synchronous attach failures (e.g., the PTY died between
@@ -3160,6 +3183,9 @@ export function connectPanePty(
deps.syncPanePtyLayoutBinding(pane.id, attachPtyId)
deps.updateTabPtyId(deps.tabId, attachPtyId)
agentCompletionCoordinator.startProcessTracking()
+ if (attachPtyId === eagerLivePtyId) {
+ registerPaneSerializerFor(attachPtyId)
+ }
} catch (err) {
reportError(err instanceof Error ? err.message : String(err))
deps.clearTabPtyId(deps.tabId, attachPtyId)
diff --git a/src/renderer/src/runtime/sync-runtime-graph-automation-leaf.test.ts b/src/renderer/src/runtime/sync-runtime-graph-automation-leaf.test.ts
new file mode 100644
index 00000000000..8bab08206b2
--- /dev/null
+++ b/src/renderer/src/runtime/sync-runtime-graph-automation-leaf.test.ts
@@ -0,0 +1,124 @@
+import { afterEach, describe, expect, it, vi } from 'vitest'
+import type { RuntimeSyncWindowGraph } from '../../../shared/runtime-types'
+import type { AppState } from '../store/types'
+import type { TerminalTab } from '../../../shared/types'
+
+// Why: Part B publishes never-mounted background automation tabs into the
+// runtime graph, gated on a live eager buffer. Stub the eager-buffer lookup so
+// the test can flip "still-live unmounted PTY" on and off without the real IPC
+// dispatcher, and spy on the anomaly warning to prove it stays scoped to mounted
+// tabs.
+const { warnTerminalLifecycleAnomaly } = vi.hoisted(() => ({
+ warnTerminalLifecycleAnomaly: vi.fn()
+}))
+vi.mock('@/components/terminal-pane/pty-dispatcher', async (importOriginal) => {
+ const actual = await importOriginal>()
+ return { ...actual, getEagerPtyBufferHandle: vi.fn(() => undefined) }
+})
+vi.mock('@/components/terminal-pane/terminal-lifecycle-diagnostics', async (importOriginal) => {
+ const actual = await importOriginal>()
+ return { ...actual, warnTerminalLifecycleAnomaly }
+})
+
+import { getEagerPtyBufferHandle } from '@/components/terminal-pane/pty-dispatcher'
+import { setRuntimeGraphStoreStateGetter, setRuntimeGraphSyncEnabled } from './sync-runtime-graph'
+
+const LEAF = '11111111-1111-4111-8111-111111111111'
+const AUTO_PTY = 'auto-bg-pty'
+
+function makeState(overrides: Partial = {}): AppState {
+ return {
+ tabsByWorktree: {},
+ terminalLayoutsByTabId: {} as AppState['terminalLayoutsByTabId'],
+ runtimePaneTitlesByTabId: {} as AppState['runtimePaneTitlesByTabId'],
+ groupsByWorktree: {},
+ activeGroupIdByWorktree: {},
+ layoutByWorktree: {},
+ unifiedTabsByWorktree: {},
+ tabBarOrderByWorktree: {},
+ activeFileId: null,
+ activeFileIdByWorktree: {},
+ openFiles: [],
+ editorDrafts: {},
+ activeTabId: null,
+ ...overrides
+ } as AppState
+}
+
+function makeAutomationTab(): TerminalTab {
+ return {
+ id: 'auto-tab-1',
+ ptyId: AUTO_PTY,
+ worktreeId: 'wt-1',
+ title: 'Generate PO review prep brief',
+ customTitle: null,
+ color: null,
+ sortOrder: 0,
+ createdAt: 1
+ }
+}
+
+function automationState(): AppState {
+ return makeState({
+ tabsByWorktree: { 'wt-1': [makeAutomationTab()] } as AppState['tabsByWorktree'],
+ terminalLayoutsByTabId: {
+ 'auto-tab-1': {
+ root: { type: 'leaf', leafId: LEAF },
+ activeLeafId: LEAF,
+ expandedLeafId: null,
+ ptyIdsByLeafId: { [LEAF]: AUTO_PTY }
+ }
+ } as AppState['terminalLayoutsByTabId']
+ })
+}
+
+async function flushMicrotasks(): Promise {
+ await Promise.resolve()
+ await Promise.resolve()
+}
+
+afterEach(() => {
+ setRuntimeGraphSyncEnabled(false)
+ setRuntimeGraphStoreStateGetter(null)
+ vi.mocked(getEagerPtyBufferHandle).mockReturnValue(undefined)
+ warnTerminalLifecycleAnomaly.mockClear()
+ vi.unstubAllGlobals()
+})
+
+async function captureGraph(): Promise {
+ const syncWindowGraph = vi.fn().mockResolvedValue(undefined)
+ vi.stubGlobal('window', { api: { runtime: { syncWindowGraph } } })
+ vi.stubGlobal('HTMLElement', class HTMLElement {})
+ setRuntimeGraphStoreStateGetter(() => automationState())
+ setRuntimeGraphSyncEnabled(true)
+ await flushMicrotasks()
+ expect(syncWindowGraph).toHaveBeenCalledTimes(1)
+ return syncWindowGraph.mock.calls[0]![0] as RuntimeSyncWindowGraph
+}
+
+describe('syncRuntimeGraph background automation tabs', () => {
+ it('publishes an unmounted automation tab leaf when its PTY is still live (eager buffer present)', async () => {
+ vi.mocked(getEagerPtyBufferHandle).mockImplementation((ptyId: string) =>
+ ptyId === AUTO_PTY ? { flush: () => '', dispose: () => {} } : undefined
+ )
+
+ const graph = await captureGraph()
+
+ expect(graph.leaves).toContainEqual(
+ expect.objectContaining({ tabId: 'auto-tab-1', leafId: LEAF, ptyId: AUTO_PTY })
+ )
+ expect(graph.tabs).toContainEqual(expect.objectContaining({ tabId: 'auto-tab-1' }))
+ // Why: the no-live-transport anomaly must stay scoped to mounted tabs; an
+ // unmounted background tab legitimately has no live transport yet.
+ expect(warnTerminalLifecycleAnomaly).not.toHaveBeenCalled()
+ })
+
+ it('does not publish an unmounted tab whose saved PTY is no longer live (no eager buffer)', async () => {
+ vi.mocked(getEagerPtyBufferHandle).mockReturnValue(undefined)
+
+ const graph = await captureGraph()
+
+ expect(graph.leaves).not.toContainEqual(expect.objectContaining({ tabId: 'auto-tab-1' }))
+ expect(graph.tabs).not.toContainEqual(expect.objectContaining({ tabId: 'auto-tab-1' }))
+ })
+})
diff --git a/src/renderer/src/runtime/sync-runtime-graph.ts b/src/renderer/src/runtime/sync-runtime-graph.ts
index 112f60a3bb4..80a8b27b70a 100644
--- a/src/renderer/src/runtime/sync-runtime-graph.ts
+++ b/src/renderer/src/runtime/sync-runtime-graph.ts
@@ -5,6 +5,7 @@ import {
normalizeTerminalLayoutSnapshot
} from '@/components/terminal-pane/layout-serialization'
import { warnTerminalLifecycleAnomaly } from '@/components/terminal-pane/terminal-lifecycle-diagnostics'
+import { getEagerPtyBufferHandle } from '@/components/terminal-pane/pty-dispatcher'
import { createBrowserUuid } from '@/lib/browser-uuid'
import type { PaneManager } from '@/lib/pane-manager/pane-manager'
import { resolveLeafIdForManager } from '@/lib/pane-manager/pane-key-resolution'
@@ -570,6 +571,55 @@ async function syncRuntimeGraph(): Promise {
}
}
+ // Why: background automation tabs spawn their agent PTY eagerly and are created
+ // inactive, so they never mount a TerminalPane and never enter `registeredTabs`.
+ // Without this pass their leaf+ptyId is never published, so the runtime treats
+ // the live agent PTY as orphaned (surfaced as a synthetic `pty:` terminal)
+ // and `orca terminal list` / session-reuse can't see the real tab. Publish them
+ // from the persisted layout, gated on a live eager buffer so we only adopt a
+ // still-running unmounted PTY (never a stale saved ptyId).
+ for (const [worktreeId, tabs] of Object.entries(state.tabsByWorktree)) {
+ for (const tab of tabs) {
+ if (registeredTabs.has(tab.id) || isWebOnlyMirroredTerminalTab(state, tab)) {
+ continue
+ }
+ const layout = state.terminalLayoutsByTabId[tab.id]
+ const savedPtyIdsByLeafId = layout?.ptyIdsByLeafId
+ if (!savedPtyIdsByLeafId) {
+ continue
+ }
+ const liveLeaves = Object.entries(savedPtyIdsByLeafId).filter(
+ ([leafId, ptyId]) =>
+ typeof ptyId === 'string' &&
+ ptyId.length > 0 &&
+ isTerminalLeafId(leafId) &&
+ Boolean(getEagerPtyBufferHandle(ptyId))
+ )
+ if (liveLeaves.length === 0) {
+ continue
+ }
+ const title = resolveRuntimeTerminalTitle(tab, generatedTitlesEnabled)
+ graph.tabs.push({
+ tabId: tab.id,
+ worktreeId,
+ title,
+ activeLeafId: layout?.activeLeafId ?? liveLeaves[0][0],
+ layout: layout?.root ?? fallbackLayoutForLeafIds(liveLeaves.map(([leafId]) => leafId))
+ })
+ liveLeaves.forEach(([leafId, ptyId], index) => {
+ graph.leaves.push({
+ tabId: tab.id,
+ worktreeId,
+ leafId,
+ paneRuntimeId: index + 1,
+ ptyId,
+ paneTitle: null,
+ title
+ })
+ })
+ }
+ }
+
try {
const result = await window.api.runtime.syncWindowGraph(graph)
getStoreState()?.setRuntimeAgentOrchestrationByPaneKey?.(
From e2e95f41001608f1ddb65b244e526fb3388fd2bc Mon Sep 17 00:00:00 2001
From: Parker Rex
Date: Wed, 10 Jun 2026 13:42:34 -0400
Subject: [PATCH 017/297] Fix i18n label spacing in menus and settings (#5108)
* fix i18n label spacing
* Fix localized account runtime labels
Co-authored-by: Orca
---------
Co-authored-by: Jinwoo-H
Co-authored-by: Orca
---
.../browser-pane/BrowserImportHintButton.tsx | 8 ++--
.../components/settings/AccountsPane.test.tsx | 24 +++++++++-
.../src/components/settings/AccountsPane.tsx | 46 ++++++++-----------
src/renderer/src/i18n/locales/en.json | 15 +++---
src/renderer/src/i18n/locales/es.json | 25 ++++++----
src/renderer/src/i18n/locales/ja.json | 15 +++---
src/renderer/src/i18n/locales/ko.json | 15 +++---
src/renderer/src/i18n/locales/zh.json | 15 +++---
8 files changed, 84 insertions(+), 79 deletions(-)
diff --git a/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx b/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx
index 788174ceae7..96f1abab344 100644
--- a/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx
+++ b/src/renderer/src/components/browser-pane/BrowserImportHintButton.tsx
@@ -215,9 +215,9 @@ export function BrowserImportHintButton({
{translate(
'auto.components.browser.pane.BrowserImportHintButton.0c6d254eca',
- 'From'
+ 'From {{value0}}',
+ { value0: browser.label }
)}
- {browser.label}
@@ -241,9 +241,9 @@ export function BrowserImportHintButton({
>
{translate(
'auto.components.browser.pane.BrowserImportHintButton.0c6d254eca',
- 'From'
+ 'From {{value0}}',
+ { value0: browser.label }
)}
- {browser.label}
)
)}
diff --git a/src/renderer/src/components/settings/AccountsPane.test.tsx b/src/renderer/src/components/settings/AccountsPane.test.tsx
index 2da3c01e10d..0bf97d581ea 100644
--- a/src/renderer/src/components/settings/AccountsPane.test.tsx
+++ b/src/renderer/src/components/settings/AccountsPane.test.tsx
@@ -3,6 +3,7 @@ import { renderToStaticMarkup } from 'react-dom/server'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { getDefaultSettings } from '../../../../shared/constants'
import type { GlobalSettings } from '../../../../shared/types'
+import { i18n } from '../../i18n/i18n'
import { useAppStore } from '../../store'
import { AccountsPane } from './AccountsPane'
@@ -20,7 +21,8 @@ function renderPane(
}
describe('AccountsPane', () => {
- beforeEach(() => {
+ beforeEach(async () => {
+ await i18n.changeLanguage('en')
useAppStore.setState({ settingsSearchQuery: '' })
})
@@ -48,4 +50,24 @@ describe('AccountsPane', () => {
expect(markup).toContain('aria-label="Account location"')
expect(markup).toContain('role="radio" aria-checked="true" disabled=""')
})
+
+ it('keeps the runtime label inside the localized account copy', () => {
+ const markup = renderPane(getDefaultSettings('/tmp'))
+
+ expect(markup).toContain('Showing accounts for This device. New accounts are added there.')
+ expect(markup).toContain('authenticate with Google for This device. This uses credentials')
+ expect(markup).not.toContain('ShowingThis device')
+ expect(markup).not.toContain('forThis device')
+ })
+
+ it('localizes the runtime label before interpolating account copy', async () => {
+ await i18n.changeLanguage('es')
+
+ const markup = renderPane(getDefaultSettings('/tmp'))
+
+ expect(markup).toContain(
+ 'Mostrando cuentas para este dispositivo. Las nuevas cuentas se agregan allí.'
+ )
+ expect(markup).not.toContain('This device')
+ })
})
diff --git a/src/renderer/src/components/settings/AccountsPane.tsx b/src/renderer/src/components/settings/AccountsPane.tsx
index befe801df0a..35540a2b880 100644
--- a/src/renderer/src/components/settings/AccountsPane.tsx
+++ b/src/renderer/src/components/settings/AccountsPane.tsx
@@ -56,7 +56,9 @@ type AccountsPaneProps = {
}
function getHostRuntimeLabel(): string {
- return navigator.userAgent.includes('Windows') ? 'Windows' : 'This device'
+ return navigator.userAgent.includes('Windows')
+ ? 'Windows'
+ : translate('auto.components.settings.AccountsPane.9baf45d071', 'This device')
}
function getCodexAccountLabel(
@@ -229,7 +231,9 @@ function getSelectedAccountRuntime(
return {
runtime: 'wsl',
wslDistro: selectedDistro,
- label: selectedDistro ? `WSL ${selectedDistro}` : 'WSL default'
+ label: selectedDistro
+ ? `WSL ${selectedDistro}`
+ : translate('auto.components.settings.AccountsPane.2358ac71d2', 'WSL default')
}
}
return { runtime: 'host', label: getHostRuntimeLabel() }
@@ -597,11 +601,10 @@ export function AccountsPane({
{translate('auto.components.settings.AccountsPane.94d351af4a', 'Accounts')}
- {translate('auto.components.settings.AccountsPane.c0a52abfc5', 'Showing')}
- {accountRuntime.label}{' '}
{translate(
- 'auto.components.settings.AccountsPane.5568bb6d5c',
- 'accounts. New accounts are added there.'
+ 'auto.components.settings.AccountsPane.c0a52abfc5',
+ 'Showing accounts for {{value0}}. New accounts are added there.',
+ { value0: accountRuntime.label }
)}
@@ -679,12 +682,8 @@ export function AccountsPane({
{translate(
'auto.components.settings.AccountsPane.3fe7862418',
- 'No managed Claude accounts for'
- )}
- {accountRuntime.label}
- {translate(
- 'auto.components.settings.AccountsPane.dea08560b4',
- ". Orca will use that environment's system default Claude login until you add one here."
+ "No managed Claude accounts for {{value0}}. Orca will use that environment's system default Claude login until you add one here.",
+ { value0: accountRuntime.label }
)}
- {translate('auto.components.settings.AccountsPane.c0a52abfc5', 'Showing')}
- {accountRuntime.label}{' '}
{translate(
- 'auto.components.settings.AccountsPane.5568bb6d5c',
- 'accounts. New accounts are added there.'
+ 'auto.components.settings.AccountsPane.c0a52abfc5',
+ 'Showing accounts for {{value0}}. New accounts are added there.',
+ { value0: accountRuntime.label }
)}
@@ -960,12 +958,8 @@ export function AccountsPane({
{translate(
'auto.components.settings.AccountsPane.b4c9450319',
- 'No managed Codex accounts for'
- )}
- {accountRuntime.label}
- {translate(
- 'auto.components.settings.AccountsPane.d46f735a85',
- ". Orca will use that environment's system default Codex login until you add one here."
+ "No managed Codex accounts for {{value0}}. Orca will use that environment's system default Codex login until you add one here.",
+ { value0: accountRuntime.label }
)}
) : (
@@ -1162,12 +1156,8 @@ export function AccountsPane({
{translate(
'auto.components.settings.AccountsPane.c2aee76420',
- 'Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google for'
- )}
- {accountRuntime.label}
- {translate(
- 'auto.components.settings.AccountsPane.d708749337',
- '. This uses credentials issued to the Gemini CLI app, not Orca. May break if Google updates the CLI. Use at your own risk.'
+ 'Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google for {{value0}}. This uses credentials issued to the Gemini CLI app, not Orca. May break if Google updates the CLI. Use at your own risk.',
+ { value0: accountRuntime.label }
)}
diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json
index ac912830e0e..a57bd1a5f35 100644
--- a/src/renderer/src/i18n/locales/en.json
+++ b/src/renderer/src/i18n/locales/en.json
@@ -3824,8 +3824,7 @@
"36223200ac": "OpenCode Go Session Cookie",
"ea631977b5": "Configure OpenCode Go provider settings.",
"4ac10b4d08": "OpenCode Go",
- "d708749337": ". This uses credentials issued to the Gemini CLI app, not Orca. May break if Google updates the CLI. Use at your own risk.",
- "c2aee76420": "Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google for",
+ "c2aee76420": "Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google for {{value0}}. This uses credentials issued to the Gemini CLI app, not Orca. May break if Google updates the CLI. Use at your own risk.",
"96f3649526": "Use Gemini CLI credentials (experimental)",
"d676c41fc6": "Extracts OAuth credentials from your local Gemini CLI installation to authenticate with Google. This uses credentials issued to the Gemini CLI app, not Orca. May break if Google updates the CLI. Use at your own risk.",
"0c7f915b01": "Use Gemini CLI credentials",
@@ -3836,21 +3835,18 @@
"3d245ef7d9": "Codex reported this sign-in is out of date",
"589eba1eee": "Needs re-auth",
"e74831fb6b": "Active",
- "d46f735a85": ". Orca will use that environment's system default Codex login until you add one here.",
- "b4c9450319": "No managed Codex accounts for",
+ "b4c9450319": "No managed Codex accounts for {{value0}}. Orca will use that environment's system default Codex login until you add one here.",
"93c47b333a": "Needs sign-in",
"f2a265f8c7": "System default",
"b0e948a4f9": "Add Account",
- "5568bb6d5c": "accounts. New accounts are added there.",
- "c0a52abfc5": "Showing",
+ "c0a52abfc5": "Showing accounts for {{value0}}. New accounts are added there.",
"94d351af4a": "Accounts",
"d0d53b7eb0": "Manage which Codex account Orca uses for live rate limit fetching.",
"3180536c7a": "Codex Accounts",
"340d6f7a85": "Each account keeps its own local sign-in context in Orca. Account auth stays on this device.",
"cedfab35ab": "Optional. Orca can use your normal Codex login; add accounts only if you want quick switching in Orca.",
"ef91cfa06b": "Codex",
- "dea08560b4": ". Orca will use that environment's system default Claude login until you add one here.",
- "3fe7862418": "No managed Claude accounts for",
+ "3fe7862418": "No managed Claude accounts for {{value0}}. Orca will use that environment's system default Claude login until you add one here.",
"3455cf43fa": "Claude login.",
"fcc4093fc1": "Use your current {{value0}} Codex login.",
"79e484c3b2": "Optional account switcher for the shared Claude auth files.",
@@ -3861,6 +3857,7 @@
"b15ce90870": "{{value0}} -> {{value1}}. Restart live Claude terminals before continuing old sessions.",
"f921d32606": "Claude account updated.",
"5bf8764953": "Codex account update failed.",
+ "9baf45d071": "This device",
"2358ac71d2": "WSL default",
"ad47a33f72": "Loading WSL",
"8619f9afa9": "WSL",
@@ -9490,7 +9487,7 @@
"05e675fe96": "Hide Hint",
"77351d22f5": "Browser Settings",
"e0e125e074": "From File…",
- "0c6d254eca": "From",
+ "0c6d254eca": "From {{value0}}",
"244266c122": "Import…",
"e52a955e6f": "You can always find this in Settings > Browser.",
"4f5ffaa6a1": "Import browser data",
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
index 4d5d4f94423..ad50da45396 100644
--- a/src/renderer/src/i18n/locales/es.json
+++ b/src/renderer/src/i18n/locales/es.json
@@ -3004,7 +3004,9 @@
"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}}"
+ "4a18052018": "El local {{value0}} está detrás de {{value1}}",
+ "commit": "commit",
+ "commits": "commits"
}
}
}
@@ -3822,8 +3824,7 @@
"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",
+ "c2aee76420": "Extrae las credenciales de OAuth de su instalación local de CLI de Gemini para autenticarse con Google para {{value0}}. 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.",
"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",
@@ -3834,21 +3835,18 @@
"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",
+ "b4c9450319": "No hay cuentas gestionadas de Codex para {{value0}}. Orca utilizará el inicio de sesión de Codex predeterminado del sistema de ese entorno hasta que agregue uno aquí.",
"93c47b333a": "Necesita iniciar sesión",
"f2a265f8c7": "Valor predeterminado del sistema",
"b0e948a4f9": "Agregar cuenta",
- "5568bb6d5c": "cuentas. Allí se agregan nuevas cuentas.",
- "c0a52abfc5": "Demostración",
+ "c0a52abfc5": "Mostrando cuentas para {{value0}}. Las nuevas cuentas se agregan allí.",
"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",
+ "3fe7862418": "No hay cuentas administradas de Claude para {{value0}}. Orca utilizará el inicio de sesión de Claude predeterminado del sistema de ese entorno hasta que agregue uno aquí.",
"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.",
@@ -3859,6 +3857,7 @@
"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.",
+ "9baf45d071": "este dispositivo",
"2358ac71d2": "WSL predeterminado",
"ad47a33f72": "Cargando WSL",
"8619f9afa9": "WSL",
@@ -4902,6 +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.",
"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",
@@ -9482,7 +9487,7 @@
"05e675fe96": "Ocultar pista",
"77351d22f5": "Configuración del navegador",
"e0e125e074": "Desde archivo…",
- "0c6d254eca": "De",
+ "0c6d254eca": "Desde {{value0}}",
"244266c122": "Importar…",
"e52a955e6f": "Siempre puedes encontrar esto en Configuración > Navegador.",
"4f5ffaa6a1": "Importar datos del navegador",
diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json
index 9f5aedddb0d..1aedd3822ee 100644
--- a/src/renderer/src/i18n/locales/ja.json
+++ b/src/renderer/src/i18n/locales/ja.json
@@ -3809,8 +3809,7 @@
"36223200ac": "OpenCode Go セッション Cookie",
"ea631977b5": "OpenCode Go プロバイダー設定を構成します。",
"4ac10b4d08": "OpenCode Go",
- "d708749337": "。これは、Orca ではなく、Gemini CLI アプリに発行された認証情報を使用します。 Google が CLI を更新すると壊れる可能性があります。ご自身の責任でご使用ください。",
- "c2aee76420": "ローカルの Gemini CLI インストールから OAuth 認証情報を抽出して、Google で認証します。",
+ "c2aee76420": "ローカルの Gemini CLI インストールから OAuth 認証情報を抽出し、{{value0}} の Google 認証に使用します。これは、Orca ではなく、Gemini CLI アプリに発行された認証情報を使用します。Google が CLI を更新すると壊れる可能性があります。ご自身の責任でご使用ください。",
"96f3649526": "Gemini CLI 認証情報を使用する (実験的機能)",
"d676c41fc6": "ローカルの Gemini CLI インストールから OAuth 認証情報を抽出して、Google で認証します。これは、Orca ではなく、Gemini CLI アプリに発行された認証情報を使用します。 Google が CLI を更新すると壊れる可能性があります。ご自身の責任でご使用ください。",
"0c7f915b01": "Gemini CLI 認証情報を使用する",
@@ -3821,21 +3820,18 @@
"3d245ef7d9": "Codex はこのサインインが古いと報告しました",
"589eba1eee": "再認証が必要です",
"e74831fb6b": "アクティブ",
- "d46f735a85": "。ここで追加するまで、Orca はその環境のシステムのデフォルトの Codex ログインを使用します。",
- "b4c9450319": "管理対象の Codex アカウントがありません",
+ "b4c9450319": "{{value0}} の管理対象 Codex アカウントはありません。ここで追加するまで、Orca はその環境のシステムデフォルトの Codex ログインを使用します。",
"93c47b333a": "サインインが必要です",
"f2a265f8c7": "システムのデフォルト",
"b0e948a4f9": "アカウントの追加",
- "5568bb6d5c": "アカウント。そこに新規アカウントが追加されます。",
- "c0a52abfc5": "表示中",
+ "c0a52abfc5": "{{value0}} のアカウントを表示中です。新規アカウントはそこに追加されます。",
"94d351af4a": "アカウント",
"d0d53b7eb0": "Orca がライブ レート制限の取得に使用する Codex アカウントを管理します。",
"3180536c7a": "Codexアカウント",
"340d6f7a85": "各アカウントは、Orca で独自のローカル サインイン コンテキストを保持します。アカウント認証はこのデバイスに残ります。",
"cedfab35ab": "オプション。 Orca は通常の Codex ログインを使用できます。 Orca で素早く切り替えたい場合にのみアカウントを追加。",
"ef91cfa06b": "Codex",
- "dea08560b4": "。ここで追加するまで、Orca はその環境のシステムのデフォルトのClaude ログインを使用します。",
- "3fe7862418": "管理対象の Claude アカウントはありません",
+ "3fe7862418": "{{value0}} の管理対象 Claude アカウントはありません。ここで追加するまで、Orca はその環境のシステムデフォルトの Claude ログインを使用します。",
"3455cf43fa": "Claudeのログイン。",
"fcc4093fc1": "現在の {{value0}} Codex ログインを使用します。",
"79e484c3b2": "共有Claude認証ファイル用のオプションのアカウント スイッチャー。",
@@ -3846,6 +3842,7 @@
"b15ce90870": "{{value0}} -> {{value1}}。古いセッションを続行する前に、ライブ Claude ターミナルを再起動します。",
"f921d32606": "Claudeアカウントが更新されました。",
"5bf8764953": "Codex アカウントの更新に失敗しました。",
+ "9baf45d071": "このデバイス",
"2358ac71d2": "WSLのデフォルト",
"ad47a33f72": "WSLの読み込み中",
"8619f9afa9": "WSL",
@@ -9490,7 +9487,7 @@
"05e675fe96": "ヒントを隠す",
"77351d22f5": "ブラウザの設定",
"e0e125e074": "ファイルから…",
- "0c6d254eca": "から",
+ "0c6d254eca": "{{value0}} から",
"244266c122": "輸入…",
"e52a955e6f": "これは、[設定] > [ブラウザ] でいつでも見つけることができます。",
"4f5ffaa6a1": "ブラウザデータをインポートする",
diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json
index ecd659e4778..2270c43cb16 100644
--- a/src/renderer/src/i18n/locales/ko.json
+++ b/src/renderer/src/i18n/locales/ko.json
@@ -3809,8 +3809,7 @@
"36223200ac": "OpenCode Go 세션 쿠키",
"ea631977b5": "OpenCode Go 공급자 설정을 구성합니다.",
"4ac10b4d08": "OpenCode Go",
- "d708749337": ". 이는 Orca가 아닌 Gemini CLI 앱에 발급된 자격 증명을 사용합니다. Google이 CLI를 업데이트하면 중단될 수 있습니다. 자신의 책임하에 사용하십시오.",
- "c2aee76420": "Google에 인증하기 위해 로컬 Gemini CLI 설치에서 OAuth 자격 증명을 추출합니다.",
+ "c2aee76420": "{{value0}}에서 Google에 인증하기 위해 로컬 Gemini CLI 설치에서 OAuth 자격 증명을 추출합니다. 이는 Orca가 아닌 Gemini CLI 앱에 발급된 자격 증명을 사용합니다. Google이 CLI를 업데이트하면 중단될 수 있습니다. 자신의 책임하에 사용하십시오.",
"96f3649526": "Gemini CLI 자격 증명 사용(실험적)",
"d676c41fc6": "Google 인증을 위해 로컬 Gemini CLI 설치에서 OAuth 자격 증명을 추출합니다. 이는 Orca가 아닌 Gemini CLI 앱에 발급된 자격 증명을 사용합니다. Google이 CLI를 업데이트하면 중단될 수 있습니다. 자신의 책임하에 사용하십시오.",
"0c7f915b01": "Gemini CLI 자격 증명 사용",
@@ -3821,21 +3820,18 @@
"3d245ef7d9": "Codex에서 이 로그인이 오래되었다고 보고했습니다.",
"589eba1eee": "재인증 필요",
"e74831fb6b": "활성",
- "d46f735a85": ". Orca는 여기에 추가할 때까지 해당 환경의 시스템 기본 Codex 로그인을 사용합니다.",
- "b4c9450319": "다음에 대한 관리되는 Codex 계정이 없습니다.",
+ "b4c9450319": "{{value0}}에 대한 관리되는 Codex 계정이 없습니다. Orca는 여기에 추가할 때까지 해당 환경의 시스템 기본 Codex 로그인을 사용합니다.",
"93c47b333a": "로그인 필요",
"f2a265f8c7": "시스템 기본값",
"b0e948a4f9": "계정 추가",
- "5568bb6d5c": "계정. 여기에 새 계정이 추가됩니다.",
- "c0a52abfc5": "표시 중",
+ "c0a52abfc5": "{{value0}} 계정을 표시 중입니다. 새 계정은 여기에 추가됩니다.",
"94d351af4a": "계정",
"d0d53b7eb0": "Orca가 실시간 속도 제한 가져오기에 사용하는 Codex 계정을 관리합니다.",
"3180536c7a": "Codex 계정",
"340d6f7a85": "각 계정은 Orca에서 자체 로컬 로그인 컨텍스트를 유지합니다. 계정 인증은 이 기기에 유지됩니다.",
"cedfab35ab": "선택 사항. Orca는 일반 Codex 로그인을 사용할 수 있습니다. Orca에서 빠른 전환을 원하는 경우에만 계정을 추가하세요.",
"ef91cfa06b": "Codex",
- "dea08560b4": ". Orca는 여기에 로그인을 추가할 때까지 해당 환경의 시스템 기본 Claude 로그인을 사용합니다.",
- "3fe7862418": "다음에 대한 관리된 Claude 계정이 없습니다.",
+ "3fe7862418": "{{value0}}에 대한 관리된 Claude 계정이 없습니다. Orca는 여기에 추가할 때까지 해당 환경의 시스템 기본 Claude 로그인을 사용합니다.",
"3455cf43fa": "Claude 로그인.",
"fcc4093fc1": "현재 {{value0}} Codex 로그인을 사용하세요.",
"79e484c3b2": "공유 Claude 인증 파일에 대한 선택적 계정 전환기입니다.",
@@ -3846,6 +3842,7 @@
"b15ce90870": "{{value0}} -> {{value1}}. 이전 세션을 계속하기 전에 라이브 Claude 터미널을 다시 시작하십시오.",
"f921d32606": "Claude 계정이 업데이트되었습니다.",
"5bf8764953": "Codex 계정 업데이트에 실패했습니다.",
+ "9baf45d071": "이 기기",
"2358ac71d2": "WSL 기본값",
"ad47a33f72": "WSL 로드 중",
"8619f9afa9": "WSL",
@@ -9490,7 +9487,7 @@
"05e675fe96": "힌트 숨기기",
"77351d22f5": "브라우저 설정",
"e0e125e074": "파일에서…",
- "0c6d254eca": "에서",
+ "0c6d254eca": "{{value0}}에서",
"244266c122": "수입…",
"e52a955e6f": "언제든지 설정 > 브라우저에서 찾을 수 있습니다.",
"4f5ffaa6a1": "브라우저 데이터 가져오기",
diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json
index 5ae4d89cbb7..61527811e59 100644
--- a/src/renderer/src/i18n/locales/zh.json
+++ b/src/renderer/src/i18n/locales/zh.json
@@ -3809,8 +3809,7 @@
"36223200ac": "OpenCode Go 会话 Cookie",
"ea631977b5": "配置 OpenCode Go 提供商设置。",
"4ac10b4d08": "OpenCode Go",
- "d708749337": "。这将使用颁发给 Gemini CLI 应用的凭据,而非 Orca。若 Google 更新 CLI,可能会失效。请自行承担风险。",
- "c2aee76420": "从本地 Gemini CLI 安装中提取 OAuth 凭据,以通过 Google 进行身份验证",
+ "c2aee76420": "从本地 Gemini CLI 安装中提取 OAuth 凭据,用于在 {{value0}} 通过 Google 进行身份验证。这将使用颁发给 Gemini CLI 应用的凭据,而非 Orca。若 Google 更新 CLI,可能会失效。请自行承担风险。",
"96f3649526": "使用 Gemini CLI 凭据(实验)",
"d676c41fc6": "从本地 Gemini CLI 安装中提取 OAuth 凭据以通过 Google 认证。这将使用颁发给 Gemini CLI 应用的凭据,而非 Orca。若 Google 更新 CLI,可能会失效。请自行承担风险。",
"0c7f915b01": "使用 Gemini CLI 凭据",
@@ -3821,21 +3820,18 @@
"3d245ef7d9": "Codex 报告此登录已过时",
"589eba1eee": "需要重新授权",
"e74831fb6b": "当前",
- "d46f735a85": "。 Orca 将使用该环境的系统默认 Codex 登录信息,直到您在此处添加登录信息。",
- "b4c9450319": "没有受管理的 Codex 账户",
+ "b4c9450319": "{{value0}} 没有受管理的 Codex 账户。Orca 将使用该环境的系统默认 Codex 登录,直到您在此处添加一个。",
"93c47b333a": "需要登录",
"f2a265f8c7": "系统默认",
"b0e948a4f9": "添加账户",
- "5568bb6d5c": "账户。新账户已添加到此处。",
- "c0a52abfc5": "显示中",
+ "c0a52abfc5": "正在显示 {{value0}} 的账户。新账户会添加到此处。",
"94d351af4a": "账户",
"d0d53b7eb0": "管理 Orca 使用哪个 Codex 账户进行实时速率限制提取。",
"3180536c7a": "Codex 账户",
"340d6f7a85": "每个账户在 Orca 中都保留自己的本地登录上下文。账户身份验证保留在此设备上。",
"cedfab35ab": "可选。Orca 可使用系统默认 Codex 登录;仅当你需要在 Orca 中快速切换账户时才添加账户。",
"ef91cfa06b": "Codex",
- "dea08560b4": "。 Orca 将使用该环境的系统默认 Claude 登录名,直到您在此处添加登录名。",
- "3fe7862418": "没有受管理的 Claude 账户",
+ "3fe7862418": "{{value0}} 没有受管理的 Claude 账户。Orca 将使用该环境的系统默认 Claude 登录,直到您在此处添加一个。",
"3455cf43fa": "Claude 登录。",
"fcc4093fc1": "使用您当前 {{value0}} Codex 登录名。",
"79e484c3b2": "用于共享 Claude 身份验证文件的可选账户切换器。",
@@ -3846,6 +3842,7 @@
"b15ce90870": "{{value0}} -> {{value1}}。在继续旧会话之前重新启动实时 Claude 终端。",
"f921d32606": "Claude 账户已更新。",
"5bf8764953": "Codex 账户更新失败。",
+ "9baf45d071": "此设备",
"2358ac71d2": "WSL 默认值",
"ad47a33f72": "正在加载 WSL",
"8619f9afa9": "WSL",
@@ -9490,7 +9487,7 @@
"05e675fe96": "隐藏提示",
"77351d22f5": "浏览器设置",
"e0e125e074": "从文件...",
- "0c6d254eca": "从",
+ "0c6d254eca": "从 {{value0}}",
"244266c122": "导入…",
"e52a955e6f": "您始终可以在“设置”>“浏览器”中找到它。",
"4f5ffaa6a1": "导入浏览器数据",
From 44d1e2760f1c0120f9bc3494ea9cbe330d3f4f09 Mon Sep 17 00:00:00 2001
From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
Date: Wed, 10 Jun 2026 11:13:01 -0700
Subject: [PATCH 018/297] Improve localization catalog sync workflow (#5110)
Co-authored-by: Orca
---
config/localization-audit.md | 12 ++
.../scripts/verify-localization-catalog.mjs | 174 +++++++++++++++++-
.../verify-localization-catalog.test.mjs | 82 +++++++++
package.json | 1 +
src/renderer/src/i18n/locales/es.json | 8 +-
5 files changed, 270 insertions(+), 7 deletions(-)
create mode 100644 config/scripts/verify-localization-catalog.test.mjs
diff --git a/config/localization-audit.md b/config/localization-audit.md
index 20c0a3ab6f0..a9047504243 100644
--- a/config/localization-audit.md
+++ b/config/localization-audit.md
@@ -46,6 +46,18 @@ Run the maintained coverage gate:
pnpm run verify:localization-coverage
```
+Sync catalog keys after adding or removing `translate(...)` calls:
+
+```sh
+pnpm run sync:localization-catalog
+```
+
+The sync command adds missing `en.json` entries from each call's string fallback,
+copies untranslated English placeholders into other locale catalogs to keep
+parity, removes locale entries whose English key was deleted, and repairs
+placeholder mismatches. Run the machine-translation bootstrap commands only when
+refreshing real translations, not for ordinary UI copy changes.
+
The coverage gate compares current candidates against
`config/localization-coverage-allowlist.json`. The committed allowlist is empty:
new candidates fail the check and must be localized or added with a reviewed
diff --git a/config/scripts/verify-localization-catalog.mjs b/config/scripts/verify-localization-catalog.mjs
index aee2fdea5dd..e49c9413da3 100644
--- a/config/scripts/verify-localization-catalog.mjs
+++ b/config/scripts/verify-localization-catalog.mjs
@@ -9,6 +9,8 @@ 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
+const LOCALES_RELATIVE_DIR = path.join('src', 'renderer', 'src', 'i18n', 'locales')
+const SOURCE_RELATIVE_ROOTS = [path.join('src', 'renderer', 'src'), path.join('src', 'main')]
function normalizePath(root, filePath) {
return path.relative(root, filePath).split(path.sep).join('/')
@@ -208,7 +210,61 @@ function flattenCatalogEntries(value, prefix = '', entries = new Map()) {
return entries
}
-function verifyLocaleParity(enCatalog, localeName, localeCatalog) {
+function getCatalogEntry(catalog, key) {
+ return key.split('.').reduce((cursor, part) => cursor?.[part], catalog)
+}
+
+function setCatalogEntry(catalog, key, value) {
+ const parts = key.split('.')
+ let cursor = catalog
+ for (const part of parts.slice(0, -1)) {
+ if (typeof cursor[part] !== 'object' || cursor[part] === null || Array.isArray(cursor[part])) {
+ cursor[part] = {}
+ }
+ cursor = cursor[part]
+ }
+ cursor[parts.at(-1)] = value
+}
+
+function deleteCatalogEntry(catalog, key) {
+ const parts = key.split('.')
+ const stack = []
+ let cursor = catalog
+
+ for (const part of parts.slice(0, -1)) {
+ if (
+ typeof cursor?.[part] !== 'object' ||
+ cursor[part] === null ||
+ Array.isArray(cursor[part])
+ ) {
+ return false
+ }
+ stack.push([cursor, part])
+ cursor = cursor[part]
+ }
+
+ const leafKey = parts.at(-1)
+ if (!Object.hasOwn(cursor, leafKey)) {
+ return false
+ }
+
+ delete cursor[leafKey]
+ for (let index = stack.length - 1; index >= 0; index -= 1) {
+ const [parent, part] = stack[index]
+ const child = parent[part]
+ if (
+ typeof child === 'object' &&
+ child !== null &&
+ !Array.isArray(child) &&
+ Object.keys(child).length === 0
+ ) {
+ delete parent[part]
+ }
+ }
+ return true
+}
+
+function collectLocaleParityIssues(enCatalog, localeCatalog) {
const enEntries = flattenCatalogEntries(enCatalog)
const localeEntries = flattenCatalogEntries(localeCatalog)
const missingInLocale = [...enEntries.keys()].filter((key) => !localeEntries.has(key))
@@ -226,6 +282,71 @@ function verifyLocaleParity(enCatalog, localeName, localeCatalog) {
}
}
+ return { enEntries, localeEntries, missingInLocale, extraInLocale, interpolationMismatches }
+}
+
+function repairLocaleParity(enCatalog, localeCatalog) {
+ const { enEntries, missingInLocale, extraInLocale, interpolationMismatches } =
+ collectLocaleParityIssues(enCatalog, localeCatalog)
+ let changed = 0
+
+ for (const key of missingInLocale) {
+ setCatalogEntry(localeCatalog, key, enEntries.get(key))
+ changed += 1
+ }
+
+ for (const key of extraInLocale) {
+ if (deleteCatalogEntry(localeCatalog, key)) {
+ changed += 1
+ }
+ }
+
+ for (const key of interpolationMismatches) {
+ setCatalogEntry(localeCatalog, key, enEntries.get(key))
+ changed += 1
+ }
+
+ return changed
+}
+
+function referencesMissingFallbacks(missing) {
+ return missing.filter((reference) => typeof reference.fallback !== 'string')
+}
+
+function collectMissingCatalogEntries(missing) {
+ const entries = new Map()
+
+ for (const reference of missing) {
+ if (typeof reference.fallback !== 'string') {
+ continue
+ }
+ if (!entries.has(reference.key)) {
+ entries.set(reference.key, reference.fallback)
+ }
+ }
+
+ return entries
+}
+
+function applyMissingEnglishEntries(catalog, missing) {
+ const entries = collectMissingCatalogEntries(missing)
+ let changed = 0
+
+ for (const [key, fallback] of entries) {
+ if (getCatalogEntry(catalog, key) !== undefined) {
+ continue
+ }
+ setCatalogEntry(catalog, key, fallback)
+ changed += 1
+ }
+
+ return changed
+}
+
+function verifyLocaleParity(enCatalog, localeName, localeCatalog) {
+ const { localeEntries, missingInLocale, extraInLocale, interpolationMismatches } =
+ collectLocaleParityIssues(enCatalog, localeCatalog)
+
if (
missingInLocale.length > 0 ||
extraInLocale.length > 0 ||
@@ -262,12 +383,18 @@ function verifyLocaleParity(enCatalog, localeName, localeCatalog) {
return 0
}
-export async function main(root = process.cwd()) {
- const localesDir = path.join(root, 'src', 'renderer', 'src', 'i18n', 'locales')
+function parseArgs(argv) {
+ return {
+ fix: argv.includes('--fix')
+ }
+}
+
+export async function main(root = process.cwd(), options = parseArgs(process.argv.slice(2))) {
+ const localesDir = path.join(root, LOCALES_RELATIVE_DIR)
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')]
+ let catalogKeys = new Set(flattenCatalogKeys(catalog))
+ const sourceRoots = SOURCE_RELATIVE_ROOTS.map((sourceRoot) => path.join(root, sourceRoot))
const references = []
for (const sourceRoot of sourceRoots) {
@@ -281,9 +408,33 @@ export async function main(root = process.cwd()) {
const missing = references.filter((reference) => !catalogKeys.has(reference.key))
if (missing.length > 0) {
+ const missingFallbacks = referencesMissingFallbacks(missing)
+ if (options.fix && missingFallbacks.length === 0) {
+ const added = applyMissingEnglishEntries(catalog, missing)
+ await fs.writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`, 'utf8')
+ catalogKeys = new Set(flattenCatalogKeys(catalog))
+ console.log(`Added ${added} missing localization key(s) to en.json.`)
+ } else {
+ if (options.fix && missingFallbacks.length > 0) {
+ console.error('Some missing localization keys do not have string fallbacks to bootstrap.')
+ console.error('')
+ console.error(formatMissingReferences(missingFallbacks))
+ return 1
+ }
+ console.error('Localization keys are missing from src/renderer/src/i18n/locales/en.json.')
+ console.error('')
+ console.error(formatMissingReferences(missing))
+ console.error('')
+ console.error('Run `pnpm run sync:localization-catalog` to add keys with string fallbacks.')
+ return 1
+ }
+ }
+
+ const remainingMissing = references.filter((reference) => !catalogKeys.has(reference.key))
+ if (remainingMissing.length > 0) {
console.error('Localization keys are missing from src/renderer/src/i18n/locales/en.json.')
console.error('')
- console.error(formatMissingReferences(missing))
+ console.error(formatMissingReferences(remainingMissing))
return 1
}
@@ -311,8 +462,19 @@ export async function main(root = process.cwd()) {
const localeName = fileName.replace(/\.json$/, '')
const localeCatalogPath = path.join(localesDir, fileName)
const localeCatalog = JSON.parse(await fs.readFile(localeCatalogPath, 'utf8'))
+ if (options.fix) {
+ const repaired = repairLocaleParity(catalog, localeCatalog)
+ if (repaired > 0) {
+ await fs.writeFile(localeCatalogPath, `${JSON.stringify(localeCatalog, null, 2)}\n`, 'utf8')
+ console.log(`Repaired ${fileName} parity (${repaired} key update(s)).`)
+ }
+ }
const exitCode = verifyLocaleParity(catalog, localeName, localeCatalog)
if (exitCode !== 0) {
+ if (!options.fix) {
+ console.error('')
+ console.error('Run `pnpm run sync:localization-catalog` to repair locale parity.')
+ }
return exitCode
}
}
diff --git a/config/scripts/verify-localization-catalog.test.mjs b/config/scripts/verify-localization-catalog.test.mjs
new file mode 100644
index 00000000000..ce148c7890f
--- /dev/null
+++ b/config/scripts/verify-localization-catalog.test.mjs
@@ -0,0 +1,82 @@
+import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs'
+import { tmpdir } from 'node:os'
+import path from 'node:path'
+
+import { describe, expect, it } from 'vitest'
+
+import { main as verifyLocalizationCatalog } from './verify-localization-catalog.mjs'
+
+function writeJson(filePath, value) {
+ writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
+}
+
+function readJson(filePath) {
+ return JSON.parse(readFileSync(filePath, 'utf8'))
+}
+
+function makeProject({ sourceText, enCatalog = {}, esCatalog = {} }) {
+ const root = mkdtempSync(path.join(tmpdir(), 'orca-localization-catalog-'))
+ const rendererDir = path.join(root, 'src', 'renderer', 'src', 'components')
+ const mainDir = path.join(root, 'src', 'main')
+ const localesDir = path.join(root, 'src', 'renderer', 'src', 'i18n', 'locales')
+
+ mkdirSync(rendererDir, { recursive: true })
+ mkdirSync(mainDir, { recursive: true })
+ mkdirSync(localesDir, { recursive: true })
+
+ writeFileSync(path.join(rendererDir, 'Example.tsx'), sourceText, 'utf8')
+ writeFileSync(path.join(mainDir, 'empty.ts'), 'export {}\n', 'utf8')
+ writeJson(path.join(localesDir, 'en.json'), enCatalog)
+ writeJson(path.join(localesDir, 'es.json'), esCatalog)
+
+ return { root, localesDir }
+}
+
+describe('verify-localization-catalog', () => {
+ it('bootstraps missing catalog entries from string fallbacks', async () => {
+ const { root, localesDir } = makeProject({
+ sourceText:
+ "import { translate } from '@/i18n/i18n'\nexport const label = translate('auto.example.greeting', 'Hello {{name}}', { name: 'Orca' })\n"
+ })
+
+ await expect(verifyLocalizationCatalog(root, { fix: false })).resolves.toBe(1)
+ await expect(verifyLocalizationCatalog(root, { fix: true })).resolves.toBe(0)
+
+ expect(readJson(path.join(localesDir, 'en.json'))).toEqual({
+ auto: { example: { greeting: 'Hello {{name}}' } }
+ })
+ expect(readJson(path.join(localesDir, 'es.json'))).toEqual({
+ auto: { example: { greeting: 'Hello {{name}}' } }
+ })
+ })
+
+ it('repairs stale locale keys and interpolation mismatches', async () => {
+ const { root, localesDir } = makeProject({
+ sourceText:
+ "import { translate } from '@/i18n/i18n'\nexport const label = translate('auto.example.greeting', 'Hello {{name}}', { name: 'Orca' })\n",
+ enCatalog: { auto: { example: { greeting: 'Hello {{name}}' } } },
+ esCatalog: {
+ auto: {
+ example: { greeting: 'Hola' },
+ stale: { removed: 'Viejo' }
+ }
+ }
+ })
+
+ await expect(verifyLocalizationCatalog(root, { fix: true })).resolves.toBe(0)
+
+ expect(readJson(path.join(localesDir, 'es.json'))).toEqual({
+ auto: { example: { greeting: 'Hello {{name}}' } }
+ })
+ })
+
+ it('does not invent values for keys without string fallbacks', async () => {
+ const { root, localesDir } = makeProject({
+ sourceText:
+ "import { translate } from '@/i18n/i18n'\nexport const label = translate('auto.example.noFallback')\n"
+ })
+
+ await expect(verifyLocalizationCatalog(root, { fix: true })).resolves.toBe(1)
+ expect(readJson(path.join(localesDir, 'en.json'))).toEqual({})
+ })
+})
diff --git a/package.json b/package.json
index 0fe629e2782..9fa35f80662 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"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",
+ "sync:localization-catalog": "node config/scripts/verify-localization-catalog.mjs --fix",
"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",
diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json
index ad50da45396..e3bf53d5413 100644
--- a/src/renderer/src/i18n/locales/es.json
+++ b/src/renderer/src/i18n/locales/es.json
@@ -4948,7 +4948,13 @@
"2b6356e744": "Guardado",
"81057d5f71": "Ahorro...",
"da37d6f10e": "Copiar",
- "3149964b66": "copiado"
+ "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."
},
"RepositoryIconPicker": {
"2b7d27b93c": "Utilice el color del repositorio {{value0}}",
From 738ccc5518f14c1061a3547237b9f106503526f6 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Wed, 10 Jun 2026 11:16:36 -0700
Subject: [PATCH 019/297] Add Warp terminal theme import (#4714)
Co-authored-by: Orca
---
electron.vite.config.ts | 1 +
src/main/ipc/settings.test.ts | 97 ++++
src/main/ipc/settings.ts | 10 +
src/main/persistence.ts | 9 +
src/main/warp-themes/discovery.test.ts | 39 ++
src/main/warp-themes/discovery.ts | 29 +
src/main/warp-themes/index.test.ts | 541 ++++++++++++++++++
src/main/warp-themes/index.ts | 267 +++++++++
.../warp-themes/manual-warp-theme-files.ts | 89 +++
src/main/warp-themes/parser-runner.test.ts | 105 ++++
src/main/warp-themes/parser-runner.ts | 76 +++
src/main/warp-themes/parser.test.ts | 137 +++++
src/main/warp-themes/parser.ts | 228 ++++++++
.../warp-themes/preview-operation-budget.ts | 43 ++
src/main/warp-themes/theme-file-scanner.ts | 233 ++++++++
.../warp-theme-import-source-validation.ts | 18 +
.../warp-themes/warp-theme-parser-worker.ts | 23 +
src/preload/api-types.ts | 5 +
src/preload/index.ts | 7 +
.../src/components/icons/WarpIcon.tsx | 12 +
.../settings/AppearancePane.test.tsx | 19 +
.../components/settings/AppearancePane.tsx | 12 +-
.../src/components/settings/Settings.tsx | 3 +
.../settings/SettingsFormControls.tsx | 206 +++++--
.../TerminalAppearanceSection.ghostty.test.ts | 175 +++++-
.../settings/TerminalAppearanceSection.tsx | 40 +-
.../settings/TerminalSettingsPreview.tsx | 32 +-
.../TerminalThemeSections.lifecycle.test.ts | 71 ++-
.../settings/TerminalThemeSections.tsx | 186 +++++-
.../settings/WarpThemeImportButton.tsx | 24 +
.../settings/WarpThemeImportModal.tsx | 331 +++++++++++
.../settings/YamlThemeImportButton.tsx | 24 +
.../components/settings/appearance-search.ts | 48 +-
.../settings/terminal-search.test.ts | 9 +
.../components/settings/terminal-search.ts | 32 +-
.../settings/terminal-theme-search.ts | 42 ++
.../settings/useWarpThemeImport.test.ts | 420 ++++++++++++++
.../components/settings/useWarpThemeImport.ts | 220 +++++++
src/renderer/src/i18n/locales/en.json | 55 ++
src/renderer/src/i18n/locales/ja.json | 55 ++
src/renderer/src/lib/terminal-theme.test.ts | 99 +++-
src/renderer/src/lib/terminal-theme.ts | 80 ++-
src/renderer/src/store/slices/settings.ts | 15 +-
src/renderer/src/web/web-preload-api.ts | 6 +
src/shared/constants.ts | 1 +
src/shared/terminal-custom-themes.test.ts | 93 +++
src/shared/terminal-custom-themes.ts | 238 ++++++++
src/shared/types.ts | 2 +
48 files changed, 4405 insertions(+), 102 deletions(-)
create mode 100644 src/main/warp-themes/discovery.test.ts
create mode 100644 src/main/warp-themes/discovery.ts
create mode 100644 src/main/warp-themes/index.test.ts
create mode 100644 src/main/warp-themes/index.ts
create mode 100644 src/main/warp-themes/manual-warp-theme-files.ts
create mode 100644 src/main/warp-themes/parser-runner.test.ts
create mode 100644 src/main/warp-themes/parser-runner.ts
create mode 100644 src/main/warp-themes/parser.test.ts
create mode 100644 src/main/warp-themes/parser.ts
create mode 100644 src/main/warp-themes/preview-operation-budget.ts
create mode 100644 src/main/warp-themes/theme-file-scanner.ts
create mode 100644 src/main/warp-themes/warp-theme-import-source-validation.ts
create mode 100644 src/main/warp-themes/warp-theme-parser-worker.ts
create mode 100644 src/renderer/src/components/icons/WarpIcon.tsx
create mode 100644 src/renderer/src/components/settings/WarpThemeImportButton.tsx
create mode 100644 src/renderer/src/components/settings/WarpThemeImportModal.tsx
create mode 100644 src/renderer/src/components/settings/YamlThemeImportButton.tsx
create mode 100644 src/renderer/src/components/settings/useWarpThemeImport.test.ts
create mode 100644 src/renderer/src/components/settings/useWarpThemeImport.ts
create mode 100644 src/shared/terminal-custom-themes.test.ts
create mode 100644 src/shared/terminal-custom-themes.ts
diff --git a/electron.vite.config.ts b/electron.vite.config.ts
index b8a66ca2f5e..04b20738a3d 100644
--- a/electron.vite.config.ts
+++ b/electron.vite.config.ts
@@ -180,6 +180,7 @@ export default defineConfig({
'daemon-entry': resolve('src/main/daemon/daemon-entry.ts'),
'computer-sidecar': resolve('src/main/computer/sidecar-entry.ts'),
'stt-worker': resolve('src/main/speech/stt-worker.ts'),
+ 'warp-theme-parser-worker': resolve('src/main/warp-themes/warp-theme-parser-worker.ts'),
// Why: electron-vite cleans out/main in dev. The dev CLI imports
// this path for `orca agent hooks ...`, so it must survive rebuilds.
'agent-hooks/managed-agent-hook-controls': resolve(
diff --git a/src/main/ipc/settings.test.ts b/src/main/ipc/settings.test.ts
index 278bf41bec1..ef58ec34f72 100644
--- a/src/main/ipc/settings.test.ts
+++ b/src/main/ipc/settings.test.ts
@@ -6,6 +6,7 @@ const {
browserWindowGetAllWindowsMock,
handleMock,
previewGhosttyImportMock,
+ previewWarpThemeImportMock,
rebuildAppMenuMock
} = vi.hoisted(() => ({
applyAppIconMock: vi.fn(),
@@ -13,6 +14,7 @@ const {
browserWindowGetAllWindowsMock: vi.fn(),
handleMock: vi.fn(),
previewGhosttyImportMock: vi.fn(),
+ previewWarpThemeImportMock: vi.fn(),
rebuildAppMenuMock: vi.fn()
}))
@@ -26,6 +28,10 @@ vi.mock('../ghostty/index', () => ({
previewGhosttyImport: previewGhosttyImportMock
}))
+vi.mock('../warp-themes', () => ({
+ previewWarpThemeImport: previewWarpThemeImportMock
+}))
+
vi.mock('../network/proxy-settings', () => ({
applyElectronProxySettings: applyElectronProxySettingsMock
}))
@@ -62,6 +68,7 @@ describe('registerSettingsHandlers', () => {
applyElectronProxySettingsMock.mockClear()
applyElectronProxySettingsMock.mockResolvedValue({ source: 'settings' })
previewGhosttyImportMock.mockClear()
+ previewWarpThemeImportMock.mockClear()
rebuildAppMenuMock.mockClear()
browserWindowGetAllWindowsMock.mockReset()
store.getSettings.mockReset()
@@ -75,6 +82,12 @@ describe('registerSettingsHandlers', () => {
expect(channels).toContain('settings:previewGhosttyImport')
})
+ it('registers settings:previewWarpThemeImport handler', () => {
+ registerSettingsHandlers(store as never)
+ const channels = handleMock.mock.calls.map((call) => call[0])
+ expect(channels).toContain('settings:previewWarpThemeImport')
+ })
+
it('settings:previewGhosttyImport returns preview result', async () => {
const expected = { found: false, diff: {}, unsupportedKeys: [] }
previewGhosttyImportMock.mockResolvedValue(expected)
@@ -89,6 +102,45 @@ describe('registerSettingsHandlers', () => {
expect(previewGhosttyImportMock).toHaveBeenCalledWith(store)
})
+ it('settings:previewWarpThemeImport returns preview result', async () => {
+ const expected = { found: false, themes: [], skippedFiles: [] }
+ previewWarpThemeImportMock.mockResolvedValue(expected)
+ registerSettingsHandlers(store as never)
+
+ const handler = handleMock.mock.calls.find(
+ (call) => call[0] === 'settings:previewWarpThemeImport'
+ )?.[1] as (event: { sender: unknown }, args: { kind: 'auto' }) => Promise
+
+ const sender = { id: 3 }
+ const result = await handler!({ sender }, { kind: 'auto' })
+ expect(result).toEqual(expected)
+ expect(previewWarpThemeImportMock).toHaveBeenCalledWith(store, { kind: 'auto' }, sender)
+ })
+
+ it('settings:previewWarpThemeImport forwards malformed sources for main validation', async () => {
+ const expected = {
+ found: false,
+ themes: [],
+ skippedFiles: [],
+ error: 'Invalid Warp theme import source.'
+ }
+ previewWarpThemeImportMock.mockResolvedValue(expected)
+ registerSettingsHandlers(store as never)
+
+ const handler = handleMock.mock.calls.find(
+ (call) => call[0] === 'settings:previewWarpThemeImport'
+ )?.[1] as (event: { sender: unknown }, args: unknown) => Promise
+
+ const invalidSource = { kind: 'unknown' }
+ const sender = { id: 3 }
+ const result = await handler!({ sender }, invalidSource)
+ expect(result).toEqual(expected)
+ expect(previewWarpThemeImportMock).toHaveBeenCalledWith(store, invalidSource, sender)
+
+ await handler!({ sender }, null)
+ expect(previewWarpThemeImportMock).toHaveBeenCalledWith(store, null, sender)
+ })
+
it('broadcasts store-level settings changes to open windows', () => {
const send = vi.fn()
browserWindowGetAllWindowsMock.mockReturnValue([
@@ -181,6 +233,51 @@ describe('registerSettingsHandlers', () => {
)
})
+ it('normalizes custom terminal themes from renderer settings IPC', async () => {
+ store.getSettings.mockReturnValue({ terminalCustomThemes: [] })
+ store.updateSettings.mockReturnValue({ terminalCustomThemes: [] })
+ registerSettingsHandlers(store as never)
+
+ const handler = handleMock.mock.calls.find((call) => call[0] === 'settings:set')?.[1] as (
+ _event: unknown,
+ args: unknown
+ ) => Promise
+
+ await handler(settingsInvokeEvent, {
+ terminalCustomThemes: [
+ {
+ id: 'warp:Test Theme',
+ name: 'Test Theme',
+ source: 'warp',
+ mode: 'dark',
+ terminal: {
+ background: '000',
+ foreground: 'fff',
+ black: '123',
+ red: 'nope'
+ },
+ sourcePath: '/Users/alice/.warp/themes/test.yaml'
+ }
+ ]
+ })
+
+ expect(store.updateSettings).toHaveBeenCalledWith(
+ {
+ terminalCustomThemes: [
+ expect.objectContaining({
+ id: 'warp:test-theme',
+ terminal: {
+ background: '#000000',
+ foreground: '#ffffff',
+ black: '#112233'
+ }
+ })
+ ]
+ },
+ { notifyListeners: true, originWebContentsId: 1 }
+ )
+ })
+
it('sanitizes and applies proxy settings from renderer settings IPC', async () => {
store.getSettings.mockReturnValue({ httpProxyUrl: '' })
store.updateSettings.mockReturnValue({
diff --git a/src/main/ipc/settings.ts b/src/main/ipc/settings.ts
index 5272fbf2902..8d593ca3c75 100644
--- a/src/main/ipc/settings.ts
+++ b/src/main/ipc/settings.ts
@@ -3,6 +3,7 @@ import type { Store } from '../persistence'
import type { GlobalSettings, PersistedState } from '../../shared/types'
import { listSystemFontFamilies } from '../system-fonts'
import { previewGhosttyImport } from '../ghostty/index'
+import { previewWarpThemeImport } from '../warp-themes'
import { setMainUiLanguage } from '../i18n/main-i18n'
import { rebuildAppMenu } from '../menu/register-app-menu'
import { track } from '../telemetry/client'
@@ -15,6 +16,7 @@ import { normalizeProxyBypassRules, normalizeProxyUrl } from '../../shared/netwo
import { normalizeAppIconId } from '../../shared/app-icon'
import { normalizeUiLanguage } from '../../shared/ui-language'
import { applyAppIcon } from '../app-icon'
+import { normalizeTerminalCustomThemes } from '../../shared/terminal-custom-themes'
// Why: the whitelist is the source-of-truth for which keys we emit on. Casting
// to a Set once at module load lets the IPC handler's per-key membership
@@ -71,6 +73,9 @@ export function registerSettingsHandlers(
if ('appIcon' in args) {
sanitizedArgs.appIcon = normalizeAppIconId(args.appIcon)
}
+ if ('terminalCustomThemes' in args) {
+ sanitizedArgs.terminalCustomThemes = normalizeTerminalCustomThemes(args.terminalCustomThemes)
+ }
if ('uiLanguage' in args) {
sanitizedArgs.uiLanguage = normalizeUiLanguage(args.uiLanguage)
}
@@ -155,6 +160,11 @@ export function registerSettingsHandlers(
return previewGhosttyImport(store)
})
+ ipcMain.handle('settings:previewWarpThemeImport', (event, args?: unknown) => {
+ const source = args === undefined ? { kind: 'auto' } : args
+ return previewWarpThemeImport(store, source, event.sender)
+ })
+
ipcMain.handle('cache:getGitHub', () => {
return store.getGitHubCache()
})
diff --git a/src/main/persistence.ts b/src/main/persistence.ts
index 7b9ff692c03..395049ca32b 100644
--- a/src/main/persistence.ts
+++ b/src/main/persistence.ts
@@ -92,6 +92,7 @@ import { normalizeAutoRenameBranchFromWorkDefaultOn } from '../shared/auto-renam
import { normalizeOpenInApplications } from '../shared/open-in-applications'
import { normalizeTerminalShortcutPolicy } from '../shared/keybindings'
import { normalizeAppIconId } from '../shared/app-icon'
+import { normalizeTerminalCustomThemes } from '../shared/terminal-custom-themes'
import {
normalizeFeatureInteractions,
type FeatureInteractionId
@@ -1941,6 +1942,9 @@ export class Store {
terminalQuickCommands: normalizeTerminalQuickCommands(
parsed.settings?.terminalQuickCommands
),
+ terminalCustomThemes: normalizeTerminalCustomThemes(
+ parsed.settings?.terminalCustomThemes
+ ),
appIcon: normalizeAppIconId(parsed.settings?.appIcon),
uiLanguage: normalizeUiLanguage(parsed.settings?.uiLanguage),
defaultTaskSource: taskProviderSettings.defaultTaskSource,
@@ -3073,6 +3077,11 @@ export class Store {
updates.terminalQuickCommands
)
}
+ if ('terminalCustomThemes' in updates) {
+ sanitizedUpdates.terminalCustomThemes = normalizeTerminalCustomThemes(
+ updates.terminalCustomThemes
+ )
+ }
if ('visibleTaskProviders' in updates || 'defaultTaskSource' in updates) {
const taskProviderSettings = normalizeTaskProviderSettings({
visibleTaskProviders:
diff --git a/src/main/warp-themes/discovery.test.ts b/src/main/warp-themes/discovery.test.ts
new file mode 100644
index 00000000000..48a2daf0a2e
--- /dev/null
+++ b/src/main/warp-themes/discovery.test.ts
@@ -0,0 +1,39 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+
+const platformMock = vi.hoisted(() => vi.fn())
+const homedirMock = vi.hoisted(() => vi.fn(() => '/Users/alice'))
+
+vi.mock('os', () => ({
+ homedir: homedirMock,
+ platform: platformMock
+}))
+
+import { getWarpThemeDirectories } from './discovery'
+
+describe('getWarpThemeDirectories', () => {
+ beforeEach(() => {
+ vi.unstubAllEnvs()
+ platformMock.mockReset()
+ homedirMock.mockReturnValue('/Users/alice')
+ })
+
+ it('returns the macOS Warp theme directory', () => {
+ platformMock.mockReturnValue('darwin')
+ expect(getWarpThemeDirectories()).toEqual(['/Users/alice/.warp/themes'])
+ })
+
+ it('returns the Linux XDG data theme directory', () => {
+ platformMock.mockReturnValue('linux')
+ vi.stubEnv('XDG_DATA_HOME', '/data/alice')
+ expect(getWarpThemeDirectories()).toEqual(['/data/alice/warp-terminal/themes'])
+ })
+
+ it('returns the Windows app data theme directory with Windows separators', () => {
+ platformMock.mockReturnValue('win32')
+ homedirMock.mockReturnValue('C:\\Users\\alice')
+ vi.stubEnv('APPDATA', 'C:\\Users\\alice\\AppData\\Roaming')
+ expect(getWarpThemeDirectories()).toEqual([
+ 'C:\\Users\\alice\\AppData\\Roaming\\warp\\Warp\\data\\themes'
+ ])
+ })
+})
diff --git a/src/main/warp-themes/discovery.ts b/src/main/warp-themes/discovery.ts
new file mode 100644
index 00000000000..8403051d630
--- /dev/null
+++ b/src/main/warp-themes/discovery.ts
@@ -0,0 +1,29 @@
+import { homedir, platform } from 'os'
+import path from 'path'
+
+export function getWarpThemeDirectories(): string[] {
+ const home = homedir()
+ const plat = platform()
+
+ switch (plat) {
+ case 'darwin':
+ return [path.join(home, '.warp', 'themes')]
+ case 'linux': {
+ const dataHome = process.env.XDG_DATA_HOME || path.join(home, '.local', 'share')
+ return [path.join(dataHome, 'warp-terminal', 'themes')]
+ }
+ case 'win32': {
+ const appData = process.env.APPDATA || home
+ return [path.win32.join(appData, 'warp', 'Warp', 'data', 'themes')]
+ }
+ case 'aix':
+ case 'android':
+ case 'cygwin':
+ case 'freebsd':
+ case 'haiku':
+ case 'netbsd':
+ case 'openbsd':
+ case 'sunos':
+ return []
+ }
+}
diff --git a/src/main/warp-themes/index.test.ts b/src/main/warp-themes/index.test.ts
new file mode 100644
index 00000000000..f8c5e21383a
--- /dev/null
+++ b/src/main/warp-themes/index.test.ts
@@ -0,0 +1,541 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import path from 'path'
+
+const opendirMock = vi.hoisted(() => vi.fn())
+const readFileMock = vi.hoisted(() => vi.fn())
+const statMock = vi.hoisted(() => vi.fn())
+const getWarpThemeDirectoriesMock = vi.hoisted(() => vi.fn(() => ['/Users/alice/.warp/themes']))
+const parseWarpThemeYamlWithTimeoutMock = vi.hoisted(() => vi.fn())
+const showOpenDialogMock = vi.hoisted(() => vi.fn())
+
+vi.mock('electron', () => ({
+ BrowserWindow: { fromWebContents: vi.fn() },
+ dialog: { showOpenDialog: showOpenDialogMock }
+}))
+
+vi.mock('fs/promises', () => ({
+ opendir: opendirMock,
+ readFile: readFileMock,
+ stat: statMock
+}))
+
+vi.mock('./discovery', () => ({
+ getWarpThemeDirectories: getWarpThemeDirectoriesMock
+}))
+
+vi.mock('./parser-runner', () => ({
+ parseWarpThemeYamlWithTimeout: parseWarpThemeYamlWithTimeoutMock
+}))
+
+import { previewWarpThemeImport } from './index'
+import { parseWarpThemeYaml } from './parser'
+import type { Store } from '../persistence'
+
+const VALID_THEME = `
+name: Duplicate
+background: '#111111'
+foreground: '#eeeeee'
+terminal_colors:
+ normal:
+ black: '#000000'
+`
+
+function fileEntry(name: string) {
+ return {
+ name,
+ isFile: () => true,
+ isDirectory: () => false
+ }
+}
+
+function directoryEntry(name: string) {
+ return {
+ name,
+ isFile: () => false,
+ isDirectory: () => true
+ }
+}
+
+function mockDirectory(
+ entries: { name: string; isFile: () => boolean; isDirectory: () => boolean }[]
+) {
+ return {
+ async *[Symbol.asyncIterator]() {
+ for (const entry of entries) {
+ yield entry
+ }
+ }
+ }
+}
+
+function mockStat(filePath: string) {
+ return filePath.endsWith('themes')
+ ? { isDirectory: () => true }
+ : { isFile: () => true, size: VALID_THEME.length }
+}
+
+describe('previewWarpThemeImport', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ getWarpThemeDirectoriesMock.mockReturnValue(['/Users/alice/.warp/themes'])
+ statMock.mockImplementation(mockStat)
+ readFileMock.mockResolvedValue(VALID_THEME)
+ opendirMock.mockResolvedValue(mockDirectory([fileEntry('z.yml'), fileEntry('a.yml')]))
+ parseWarpThemeYamlWithTimeoutMock.mockImplementation(parseWarpThemeYaml)
+ })
+
+ it('sorts theme files before duplicate id suffixing', async () => {
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes.map((theme) => theme.id)).toEqual([
+ 'warp:duplicate:a-yml',
+ 'warp:duplicate:z-yml'
+ ])
+ expect(readFileMock.mock.calls.map(([filePath]) => path.basename(filePath as string))).toEqual([
+ 'a.yml',
+ 'z.yml'
+ ])
+ })
+
+ it('returns an empty errorless preview when no local Warp theme folder exists', async () => {
+ statMock.mockImplementation(() => {
+ throw new Error('missing local themes')
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview).toMatchObject({
+ found: false,
+ sourceLabel: 'Warp themes',
+ themes: [],
+ skippedFiles: []
+ })
+ expect(preview.error).toBeUndefined()
+ expect(readFileMock).not.toHaveBeenCalled()
+ })
+
+ it('returns an empty errorless preview for an empty readable local Warp theme folder', async () => {
+ opendirMock.mockResolvedValue(mockDirectory([]))
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview).toMatchObject({
+ found: false,
+ sourceLabel: 'Warp themes',
+ themes: [],
+ skippedFiles: []
+ })
+ expect(preview.error).toBeUndefined()
+ expect(readFileMock).not.toHaveBeenCalled()
+ })
+
+ it('reports bounded skips when local Warp folders are unreadable', async () => {
+ opendirMock.mockRejectedValue(
+ new Error("EACCES: permission denied, scandir '/Users/alice/.warp/themes'")
+ )
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.found).toBe(false)
+ expect(preview.sourceLabel).toBe('Warp themes')
+ expect(preview.skippedFiles).toEqual([{ label: 'themes', reason: 'Could not read folder.' }])
+ expect(preview.themes).toEqual([])
+ })
+
+ it('labels auto-discovered themes as local Warp themes', async () => {
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.sourceLabel).toBe('Warp themes')
+ expect(preview.themes.map((theme) => theme.name)).toEqual(['Duplicate', 'Duplicate'])
+ expect(preview.themes.map((theme) => theme.sourceLabel)).toEqual([
+ 'Local Warp themes',
+ 'Local Warp themes'
+ ])
+ })
+
+ it('returns a bounded preview error for invalid sources without auto discovery', async () => {
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'surprise' })
+ const nullPreview = await previewWarpThemeImport({} as Store, null)
+ const extraFieldPreview = await previewWarpThemeImport({} as Store, {
+ kind: 'auto',
+ path: '/Users/alice/.warp/themes'
+ })
+
+ expect(preview).toEqual({
+ found: false,
+ themes: [],
+ skippedFiles: [],
+ error: 'Invalid Warp theme import source.'
+ })
+ expect(nullPreview.error).toBe('Invalid Warp theme import source.')
+ expect(extraFieldPreview.error).toBe('Invalid Warp theme import source.')
+ expect(getWarpThemeDirectoriesMock).not.toHaveBeenCalled()
+ })
+
+ it('uses stable file labels in imported theme ids', async () => {
+ opendirMock.mockImplementation((directoryPath: string) => {
+ if (directoryPath.endsWith('themes')) {
+ return Promise.resolve(
+ mockDirectory([directoryEntry('standard'), directoryEntry('custom')])
+ )
+ }
+ if (directoryPath.endsWith('standard')) {
+ return Promise.resolve(mockDirectory([fileEntry('duplicate.yaml')]))
+ }
+ if (directoryPath.endsWith('custom')) {
+ return Promise.resolve(mockDirectory([fileEntry('duplicate.yaml')]))
+ }
+ return Promise.resolve(mockDirectory([]))
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes.map((theme) => theme.id)).toEqual([
+ 'warp:duplicate:custom-duplicate-yaml',
+ 'warp:duplicate:standard-duplicate-yaml'
+ ])
+ })
+
+ it('stops scheduling parser work when the preview budget expires', async () => {
+ let currentTime = 0
+ parseWarpThemeYamlWithTimeoutMock.mockImplementation(
+ (...args: Parameters) => {
+ currentTime = 10
+ return parseWarpThemeYaml(...args)
+ }
+ )
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' }, undefined, {
+ operationBudgetMs: 5,
+ now: () => currentTime
+ })
+
+ expect(preview.themes).toHaveLength(1)
+ expect(parseWarpThemeYamlWithTimeoutMock).toHaveBeenCalledTimes(1)
+ expect(parseWarpThemeYamlWithTimeoutMock.mock.calls[0]?.[3]).toEqual({ timeoutMs: 5 })
+ expect(preview.skippedFiles).toContainEqual({
+ label: 'Warp themes',
+ reason: 'Preview budget expired before 1 theme file could be parsed.'
+ })
+ })
+
+ it('keeps same-basename manual file ids stable independent of dialog order', async () => {
+ const firstPath = path.join('/Users/alice/light', 'duplicate.yaml')
+ const secondPath = path.join('/Users/alice/dark', 'duplicate.yaml')
+ readFileMock.mockImplementation((filePath: string) =>
+ filePath === firstPath
+ ? VALID_THEME.replace("background: '#111111'", "background: '#222222'")
+ : VALID_THEME.replace("background: '#111111'", "background: '#333333'")
+ )
+ showOpenDialogMock.mockResolvedValueOnce({
+ canceled: false,
+ filePaths: [firstPath, secondPath]
+ })
+ const firstPreview = await previewWarpThemeImport({} as Store, { kind: 'chooseFile' })
+
+ showOpenDialogMock.mockResolvedValueOnce({
+ canceled: false,
+ filePaths: [secondPath, firstPath]
+ })
+ const secondPreview = await previewWarpThemeImport({} as Store, { kind: 'chooseFile' })
+
+ expect(firstPreview.themes.map((theme) => theme.id)).toEqual(
+ secondPreview.themes.map((theme) => theme.id)
+ )
+ const ids = firstPreview.themes.map((theme) => theme.id)
+ expect(ids).toHaveLength(2)
+ expect(new Set(ids).size).toBe(2)
+ expect(ids.join(' ')).not.toContain('/Users/alice')
+ expect(ids.every((id) => id.startsWith('warp:duplicate:duplicate-yaml-'))).toBe(true)
+ })
+
+ it('marks dismissed file pickers as canceled', async () => {
+ showOpenDialogMock.mockResolvedValueOnce({ canceled: true, filePaths: [] })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'chooseFile' })
+
+ expect(preview).toEqual({ found: false, canceled: true, themes: [], skippedFiles: [] })
+ })
+
+ it('starts the preview budget after a manual file picker returns', async () => {
+ let currentTime = 0
+ showOpenDialogMock.mockImplementationOnce(() => {
+ currentTime = 10
+ return Promise.resolve({
+ canceled: false,
+ filePaths: [path.join('/Users/alice/themes', 'manual.yaml')]
+ })
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'chooseFile' }, undefined, {
+ operationBudgetMs: 5,
+ now: () => currentTime
+ })
+
+ expect(preview.themes).toHaveLength(1)
+ expect(parseWarpThemeYamlWithTimeoutMock.mock.calls[0]?.[3]).toEqual({ timeoutMs: 5 })
+ expect(preview.skippedFiles).toEqual([])
+ })
+
+ it('starts the preview budget after a manual folder picker returns', async () => {
+ let currentTime = 0
+ showOpenDialogMock.mockImplementationOnce(() => {
+ currentTime = 10
+ return Promise.resolve({
+ canceled: false,
+ filePaths: ['/Users/alice/themes']
+ })
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'chooseFolder' }, undefined, {
+ operationBudgetMs: 5,
+ now: () => currentTime
+ })
+
+ expect(preview.themes).toHaveLength(2)
+ expect(parseWarpThemeYamlWithTimeoutMock.mock.calls[0]?.[3]).toEqual({ timeoutMs: 5 })
+ expect(preview.skippedFiles).toEqual([])
+ })
+
+ it('finds themes in a cloned Warp themes repository layout', async () => {
+ opendirMock.mockImplementation((directoryPath: string) => {
+ if (directoryPath.endsWith('themes')) {
+ return Promise.resolve(
+ mockDirectory([directoryEntry('standard'), directoryEntry('warp_bundled')])
+ )
+ }
+ if (directoryPath.endsWith('standard')) {
+ return Promise.resolve(mockDirectory([fileEntry('tokyo-night.yaml')]))
+ }
+ if (directoryPath.endsWith('warp_bundled')) {
+ return Promise.resolve(mockDirectory([fileEntry('dracula.yml')]))
+ }
+ return Promise.resolve(mockDirectory([]))
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.found).toBe(true)
+ expect(readFileMock.mock.calls.map(([filePath]) => filePath)).toEqual([
+ path.join('/Users/alice/.warp/themes', 'standard', 'tokyo-night.yaml'),
+ path.join('/Users/alice/.warp/themes', 'warp_bundled', 'dracula.yml')
+ ])
+ expect(preview.themes.map((theme) => theme.sourceLabel)).toEqual([
+ 'Local Warp themes',
+ 'Local Warp themes'
+ ])
+ })
+
+ it('caps broad folder scans before walking unbounded child directories', async () => {
+ opendirMock.mockImplementation((directoryPath: string) => {
+ if (directoryPath.endsWith('themes')) {
+ return Promise.resolve(
+ mockDirectory(
+ Array.from({ length: 100 }, (_, index) => directoryEntry(`folder-${index}`))
+ )
+ )
+ }
+ return Promise.resolve(mockDirectory([fileEntry(`${path.basename(directoryPath)}.yaml`)]))
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes).toHaveLength(79)
+ expect(preview.skippedFiles).toContainEqual({
+ label: 'themes',
+ reason: 'Only the first 80 folders were scanned.'
+ })
+ })
+
+ it('reports the theme cap when a nested folder fills the cap before later folders', async () => {
+ opendirMock.mockImplementation((directoryPath: string) => {
+ if (directoryPath.endsWith('themes')) {
+ return Promise.resolve(
+ mockDirectory([directoryEntry('standard'), directoryEntry('warp_bundled')])
+ )
+ }
+ if (directoryPath.endsWith('standard')) {
+ return Promise.resolve(
+ mockDirectory(Array.from({ length: 200 }, (_, index) => fileEntry(`theme-${index}.yaml`)))
+ )
+ }
+ if (directoryPath.endsWith('warp_bundled')) {
+ return Promise.resolve(mockDirectory([fileEntry('extra.yaml')]))
+ }
+ return Promise.resolve(mockDirectory([]))
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(preview.skippedFiles).toContainEqual({
+ label: 'themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ })
+ expect(opendirMock).not.toHaveBeenCalledWith(
+ path.join('/Users/alice/.warp/themes', 'warp_bundled'),
+ expect.anything()
+ )
+ })
+
+ it('caps entries processed from one large folder', async () => {
+ opendirMock.mockResolvedValue(
+ mockDirectory(Array.from({ length: 501 }, (_, index) => fileEntry(`theme-${index}.yaml`)))
+ )
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(preview.skippedFiles).toEqual(
+ expect.arrayContaining([
+ {
+ label: 'themes',
+ reason: 'Only the first 500 folder entries were scanned.'
+ },
+ {
+ label: 'themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ }
+ ])
+ )
+ })
+
+ it('does not report a skipped theme file warning for exactly the folder cap', async () => {
+ opendirMock.mockResolvedValue(
+ mockDirectory(Array.from({ length: 200 }, (_, index) => fileEntry(`theme-${index}.yaml`)))
+ )
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(preview.skippedFiles).not.toContainEqual({
+ label: 'themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ })
+ })
+
+ it('does not report the theme cap for exactly the folder cap plus non-theme files', async () => {
+ opendirMock.mockResolvedValue(
+ mockDirectory([
+ ...Array.from({ length: 200 }, (_, index) => fileEntry(`theme-${index}.yaml`)),
+ fileEntry('z-readme.md')
+ ])
+ )
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(preview.skippedFiles).not.toContainEqual({
+ label: 'themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ })
+ })
+
+ it('does not report the theme cap when a nested folder fills the cap before non-theme siblings', async () => {
+ opendirMock.mockImplementation((directoryPath: string) => {
+ if (directoryPath.endsWith('themes')) {
+ return Promise.resolve(
+ mockDirectory([directoryEntry('standard'), fileEntry('z-readme.md')])
+ )
+ }
+ if (directoryPath.endsWith('standard')) {
+ return Promise.resolve(
+ mockDirectory(Array.from({ length: 200 }, (_, index) => fileEntry(`theme-${index}.yaml`)))
+ )
+ }
+ return Promise.resolve(mockDirectory([]))
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(preview.skippedFiles).not.toContainEqual({
+ label: 'themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ })
+ })
+
+ it('reports capped manually selected theme files after deterministic YAML sorting', async () => {
+ const themePaths = Array.from({ length: 201 }, (_, index) =>
+ path.join('/Users/alice/warp-themes', `theme-${String(index).padStart(3, '0')}.yaml`)
+ )
+ showOpenDialogMock.mockResolvedValue({
+ canceled: false,
+ filePaths: [
+ path.join('/Users/alice/warp-themes', 'aaa-not-theme.txt'),
+ ...themePaths
+ ].reverse()
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'chooseFile' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(readFileMock.mock.calls[0]?.[0]).toBe(themePaths[0])
+ expect(readFileMock.mock.calls.at(-1)?.[0]).toBe(themePaths[199])
+ expect(preview.skippedFiles).toContainEqual({
+ label: 'Selected Warp themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ })
+ })
+
+ it('does not report the manual theme cap for extra non-YAML selections', async () => {
+ const themePaths = Array.from({ length: 200 }, (_, index) =>
+ path.join('/Users/alice/warp-themes', `theme-${String(index).padStart(3, '0')}.yaml`)
+ )
+ showOpenDialogMock.mockResolvedValue({
+ canceled: false,
+ filePaths: [...themePaths, path.join('/Users/alice/warp-themes', 'readme.txt')]
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'chooseFile' })
+
+ expect(preview.themes).toHaveLength(200)
+ expect(preview.skippedFiles).not.toContainEqual({
+ label: 'Selected Warp themes',
+ reason: 'Only the first 200 theme files were scanned.'
+ })
+ })
+
+ it('stops streaming a large folder after the entry budget', async () => {
+ const yieldedNames: string[] = []
+ opendirMock.mockResolvedValue({
+ async *[Symbol.asyncIterator]() {
+ for (let index = 0; index < 1000; index += 1) {
+ const name = `theme-${index}.yaml`
+ yieldedNames.push(name)
+ yield fileEntry(name)
+ }
+ }
+ })
+
+ await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(yieldedNames).toHaveLength(501)
+ expect(yieldedNames).not.toContain('theme-501.yaml')
+ expect(yieldedNames).not.toContain('theme-999.yaml')
+ })
+
+ it('does not copy absolute folder paths into skipped reasons', async () => {
+ opendirMock.mockRejectedValue(
+ new Error("ENOENT: no such file or directory, scandir '/Users/alice/.warp/themes'")
+ )
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.skippedFiles).toEqual([{ label: 'themes', reason: 'Could not read folder.' }])
+ })
+
+ it('does not copy absolute file paths into skipped reasons', async () => {
+ opendirMock.mockResolvedValue(mockDirectory([fileEntry('private.yml')]))
+ statMock.mockImplementation((filePath: string) => {
+ if (filePath.endsWith('private.yml')) {
+ throw new Error("EACCES: permission denied, stat '/Users/alice/.warp/themes/private.yml'")
+ }
+ return mockStat(filePath)
+ })
+
+ const preview = await previewWarpThemeImport({} as Store, { kind: 'auto' })
+
+ expect(preview.skippedFiles).toEqual([{ label: 'private.yml', reason: 'Could not read file.' }])
+ })
+})
diff --git a/src/main/warp-themes/index.ts b/src/main/warp-themes/index.ts
new file mode 100644
index 00000000000..93411aa3b8b
--- /dev/null
+++ b/src/main/warp-themes/index.ts
@@ -0,0 +1,267 @@
+import { readFile, stat } from 'fs/promises'
+import type { WebContents } from 'electron'
+import type { Store } from '../persistence'
+import type {
+ WarpThemeImportPreview,
+ WarpThemeImportSource,
+ WarpThemeImportSkippedFile
+} from '../../shared/terminal-custom-themes'
+import { makeCustomTerminalThemeSelection } from '../../shared/terminal-custom-themes'
+import { getWarpThemeDirectories } from './discovery'
+import { parseWarpThemeYamlWithTimeout } from './parser-runner'
+import {
+ sanitizeReadError,
+ scanWarpThemeDirectory,
+ type ThemeFileCandidate
+} from './theme-file-scanner'
+import {
+ createPreviewOperationBudget,
+ pushPreviewBudgetSkippedFile,
+ type PreviewOperationBudget,
+ type WarpThemePreviewOptions
+} from './preview-operation-budget'
+import { validateWarpThemeImportSource } from './warp-theme-import-source-validation'
+import {
+ chooseManualWarpThemeFiles,
+ chooseManualWarpThemeFolderPath,
+ manualWarpThemeContentDiscriminator
+} from './manual-warp-theme-files'
+
+const MAX_THEME_FILE_BYTES = 1_000_000
+
+type ThemeSourceSelection =
+ | { canceled: true }
+ | {
+ canceled: false
+ sourceLabel: string
+ files: ThemeFileCandidate[]
+ skippedFiles: WarpThemeImportSkippedFile[]
+ rootReadable?: boolean
+ }
+
+type ThemeSourceResolution = {
+ selection: ThemeSourceSelection
+ budget: PreviewOperationBudget
+}
+
+async function filesFromDirectory(
+ directoryPath: string,
+ sourceLabelOverride?: string,
+ budget?: PreviewOperationBudget
+): Promise {
+ const { sourceLabel, rootReadable, files, skippedFiles } = await scanWarpThemeDirectory(
+ directoryPath,
+ budget
+ )
+ const effectiveSourceLabel = sourceLabelOverride ?? sourceLabel
+ return {
+ canceled: false,
+ sourceLabel: effectiveSourceLabel,
+ files: files.map((file) => ({ ...file, sourceLabel: effectiveSourceLabel })),
+ skippedFiles,
+ rootReadable
+ }
+}
+
+async function filesFromAutoDirectories(
+ budget?: PreviewOperationBudget
+): Promise {
+ const directories = getWarpThemeDirectories()
+ let localSelection: ThemeSourceSelection | null = null
+ const unreadableSkippedFiles: WarpThemeImportSkippedFile[] = []
+ let autoDiscoveryExpired = false
+ for (const directoryPath of directories) {
+ if (budget?.isExpired()) {
+ autoDiscoveryExpired = true
+ break
+ }
+ try {
+ const info = await stat(directoryPath)
+ if (!info.isDirectory()) {
+ continue
+ }
+ } catch {
+ continue
+ }
+ const selection = await filesFromDirectory(directoryPath, 'Local Warp themes', budget)
+ if (!selection.canceled && selection.rootReadable) {
+ localSelection = selection
+ break
+ }
+ if (!selection.canceled) {
+ unreadableSkippedFiles.push(...selection.skippedFiles)
+ }
+ }
+ if (localSelection) {
+ return {
+ canceled: false,
+ sourceLabel: 'Warp themes',
+ files: localSelection.files,
+ skippedFiles: localSelection.skippedFiles
+ }
+ }
+ if (autoDiscoveryExpired) {
+ return {
+ canceled: false,
+ sourceLabel: 'Warp themes',
+ files: [],
+ skippedFiles: [
+ {
+ label: 'Warp themes',
+ reason: 'Preview budget expired before local Warp theme folders could be scanned.'
+ }
+ ]
+ }
+ }
+ // Why: Warp's preloaded themes live inside the Warp app binary, not on disk,
+ // so an absent or empty themes folder is a genuine empty result — the
+ // renderer explains this and points at Orca's built-in equivalents.
+ return {
+ canceled: false,
+ sourceLabel: 'Warp themes',
+ files: [],
+ skippedFiles: unreadableSkippedFiles
+ }
+}
+
+async function resolveThemeSource(
+ source: WarpThemeImportSource,
+ webContents?: WebContents,
+ options: WarpThemePreviewOptions = {}
+): Promise {
+ switch (source.kind) {
+ case 'auto': {
+ const budget = createPreviewOperationBudget(options)
+ return { selection: await filesFromAutoDirectories(budget), budget }
+ }
+ case 'chooseFile': {
+ const selection = await chooseManualWarpThemeFiles(webContents)
+ return { selection, budget: createPreviewOperationBudget(options) }
+ }
+ case 'chooseFolder': {
+ const folderPath = await chooseManualWarpThemeFolderPath(webContents)
+ const budget = createPreviewOperationBudget(options)
+ return {
+ selection: folderPath
+ ? await filesFromDirectory(folderPath, undefined, budget)
+ : { canceled: true },
+ budget
+ }
+ }
+ }
+}
+
+export async function previewWarpThemeImport(
+ _store: Store,
+ source: unknown = { kind: 'auto' },
+ webContents?: WebContents,
+ options: WarpThemePreviewOptions = {}
+): Promise {
+ const validatedSource = validateWarpThemeImportSource(source)
+ if (!validatedSource) {
+ return {
+ found: false,
+ themes: [],
+ skippedFiles: [],
+ error: 'Invalid Warp theme import source.'
+ }
+ }
+
+ const { selection, budget } = await resolveThemeSource(validatedSource, webContents, options)
+ if (selection.canceled) {
+ return { found: false, canceled: true, themes: [], skippedFiles: [] }
+ }
+
+ const skippedFiles = [...selection.skippedFiles]
+ const themes: WarpThemeImportPreview['themes'] = []
+ const idCounts = new Map()
+ const importedAt = new Date().toISOString()
+
+ for (const [index, file] of selection.files.entries()) {
+ if (budget.isExpired()) {
+ pushPreviewBudgetSkippedFile(
+ skippedFiles,
+ selection.sourceLabel,
+ budget.remainingThemeFiles(index, selection.files.length)
+ )
+ break
+ }
+ let content: string
+ if (file.content !== undefined) {
+ content = file.content
+ } else {
+ try {
+ const info = await stat(file.path)
+ if (!info.isFile()) {
+ skippedFiles.push({ label: file.label, reason: 'Not a file.' })
+ continue
+ }
+ if (info.size > MAX_THEME_FILE_BYTES) {
+ skippedFiles.push({
+ label: file.label,
+ reason: `File is too large to import (${info.size} bytes, limit ${MAX_THEME_FILE_BYTES}).`
+ })
+ continue
+ }
+ content = await readFile(file.path, 'utf-8')
+ } catch {
+ skippedFiles.push({
+ label: file.label,
+ reason: sanitizeReadError('Could not read file.')
+ })
+ continue
+ }
+ }
+ if (budget.isExpired()) {
+ pushPreviewBudgetSkippedFile(
+ skippedFiles,
+ selection.sourceLabel,
+ budget.remainingThemeFiles(index, selection.files.length)
+ )
+ break
+ }
+
+ const parsed = await parseWarpThemeYamlWithTimeout(
+ content,
+ file.label,
+ {
+ idDiscriminator:
+ file.idDiscriminator ||
+ (file.contentHashDiscriminator
+ ? manualWarpThemeContentDiscriminator(file.label, content)
+ : file.label || file.sourceLabel || selection.sourceLabel),
+ importedAt,
+ sourceLabel: file.sourceLabel ?? selection.sourceLabel
+ },
+ {
+ timeoutMs: budget.remainingMs()
+ }
+ )
+ if (!parsed.ok) {
+ skippedFiles.push({ label: file.label, reason: parsed.reason })
+ continue
+ }
+
+ const count = idCounts.get(parsed.theme.id) ?? 0
+ idCounts.set(parsed.theme.id, count + 1)
+ if (count > 0) {
+ const id = `${parsed.theme.id}-${count + 1}`
+ themes.push({
+ ...parsed.theme,
+ id,
+ selectionValue: makeCustomTerminalThemeSelection(id)
+ })
+ continue
+ }
+ themes.push(parsed.theme)
+ }
+
+ // Why: an empty result carries no error — the renderer owns the localized
+ // empty-state copy; `error` is reserved for genuine failures.
+ return {
+ found: themes.length > 0,
+ sourceLabel: selection.sourceLabel,
+ themes,
+ skippedFiles
+ }
+}
diff --git a/src/main/warp-themes/manual-warp-theme-files.ts b/src/main/warp-themes/manual-warp-theme-files.ts
new file mode 100644
index 00000000000..801eaadc547
--- /dev/null
+++ b/src/main/warp-themes/manual-warp-theme-files.ts
@@ -0,0 +1,89 @@
+import { createHash } from 'crypto'
+import path from 'path'
+import { BrowserWindow, dialog, type OpenDialogOptions, type WebContents } from 'electron'
+import type { WarpThemeImportSkippedFile } from '../../shared/terminal-custom-themes'
+import {
+ compareThemeFileLabels,
+ isYamlFile,
+ MAX_THEME_FILES,
+ type ThemeFileCandidate
+} from './theme-file-scanner'
+
+export function createManualWarpThemeFileCandidates(filePaths: string[]): ThemeFileCandidate[] {
+ return filePaths
+ .map((filePath) => ({
+ path: filePath,
+ label: path.basename(filePath),
+ contentHashDiscriminator: true
+ }))
+ .sort((left, right) => {
+ const labelComparison = compareThemeFileLabels(left, right)
+ if (labelComparison !== 0) {
+ return labelComparison
+ }
+ // Why: manual dialogs can return selections in click order. Sort only in
+ // main so duplicate basenames get deterministic IDs without persisting paths.
+ return left.path.localeCompare(right.path, undefined, { sensitivity: 'base' })
+ })
+}
+
+export function manualWarpThemeContentDiscriminator(label: string, content: string): string {
+ return `${label}-${createHash('sha256').update(content).digest('hex').slice(0, 12)}`
+}
+
+export async function chooseManualWarpThemeFiles(webContents?: WebContents): Promise<
+ | { canceled: true }
+ | {
+ canceled: false
+ sourceLabel: string
+ files: ThemeFileCandidate[]
+ skippedFiles: WarpThemeImportSkippedFile[]
+ }
+> {
+ const ownerWindow = webContents ? BrowserWindow.fromWebContents(webContents) : null
+ const options: OpenDialogOptions = {
+ title: 'Import Warp Theme',
+ properties: ['openFile', 'multiSelections'],
+ filters: [{ name: 'Warp theme YAML', extensions: ['yaml', 'yml'] }]
+ }
+ const result = ownerWindow
+ ? await dialog.showOpenDialog(ownerWindow, options)
+ : await dialog.showOpenDialog(options)
+ if (result.canceled || result.filePaths.length === 0) {
+ return { canceled: true }
+ }
+ const selectedYamlFiles = result.filePaths.filter(isYamlFile)
+ const files = createManualWarpThemeFileCandidates(selectedYamlFiles).slice(0, MAX_THEME_FILES)
+ const skippedFiles: WarpThemeImportSkippedFile[] =
+ selectedYamlFiles.length > MAX_THEME_FILES
+ ? [
+ {
+ label: 'Selected Warp themes',
+ reason: `Only the first ${MAX_THEME_FILES} theme files were scanned.`
+ }
+ ]
+ : []
+ return {
+ canceled: false,
+ sourceLabel: files.length === 1 ? (files[0]?.label ?? 'Warp theme') : 'Selected Warp themes',
+ files,
+ skippedFiles
+ }
+}
+
+export async function chooseManualWarpThemeFolderPath(
+ webContents?: WebContents
+): Promise {
+ const ownerWindow = webContents ? BrowserWindow.fromWebContents(webContents) : null
+ const options: OpenDialogOptions = {
+ title: 'Import Warp Theme Folder',
+ properties: ['openDirectory']
+ }
+ const result = ownerWindow
+ ? await dialog.showOpenDialog(ownerWindow, options)
+ : await dialog.showOpenDialog(options)
+ if (result.canceled || result.filePaths.length === 0) {
+ return null
+ }
+ return result.filePaths[0]!
+}
diff --git a/src/main/warp-themes/parser-runner.test.ts b/src/main/warp-themes/parser-runner.test.ts
new file mode 100644
index 00000000000..c6362b8ce7d
--- /dev/null
+++ b/src/main/warp-themes/parser-runner.test.ts
@@ -0,0 +1,105 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+
+const workerState = vi.hoisted(() => ({
+ instances: [] as {
+ terminated: boolean
+ workerData: unknown
+ listeners: Map void>
+ emit: (event: string, arg?: unknown) => void
+ terminate: () => Promise
+ removeAllListeners: () => void
+ }[]
+}))
+
+vi.mock('electron', () => ({
+ app: { isPackaged: false }
+}))
+
+vi.mock('worker_threads', () => ({
+ Worker: class MockWorker {
+ terminated = false
+ workerData: unknown
+ listeners = new Map void>()
+
+ constructor(_workerPath: string, options: { workerData?: unknown }) {
+ this.workerData = options.workerData
+ workerState.instances.push(this)
+ }
+
+ once(event: string, listener: (arg?: unknown) => void): this {
+ this.listeners.set(event, listener)
+ return this
+ }
+
+ removeAllListeners(): void {
+ this.listeners.clear()
+ }
+
+ async terminate(): Promise {
+ this.terminated = true
+ return 0
+ }
+
+ emit(event: string, arg?: unknown): void {
+ this.listeners.get(event)?.(arg)
+ }
+ }
+}))
+
+import { parseWarpThemeYamlWithTimeout, WARP_THEME_PARSE_TIMEOUT_MS } from './parser-runner'
+
+describe('parseWarpThemeYamlWithTimeout', () => {
+ beforeEach(() => {
+ vi.useFakeTimers()
+ workerState.instances.length = 0
+ })
+
+ afterEach(() => {
+ vi.useRealTimers()
+ })
+
+ it('returns worker parser results', async () => {
+ const resultPromise = parseWarpThemeYamlWithTimeout('name: Test', 'test.yaml')
+ const worker = workerState.instances[0]
+ worker?.emit('message', { ok: false, reason: 'Invalid YAML' })
+
+ await expect(resultPromise).resolves.toEqual({ ok: false, reason: 'Invalid YAML' })
+ expect(worker?.terminated).toBe(false)
+ })
+
+ it('terminates the worker when parsing exceeds the budget', async () => {
+ const resultPromise = parseWarpThemeYamlWithTimeout('name: Slow', 'slow.yaml')
+ const worker = workerState.instances[0]
+
+ await vi.advanceTimersByTimeAsync(WARP_THEME_PARSE_TIMEOUT_MS)
+
+ await expect(resultPromise).resolves.toEqual({
+ ok: false,
+ reason: 'Theme file took too long to parse.'
+ })
+ expect(worker?.terminated).toBe(true)
+ })
+
+ it('uses the shorter operation-budget timeout when provided', async () => {
+ const resultPromise = parseWarpThemeYamlWithTimeout(
+ 'name: Slow',
+ 'slow.yaml',
+ {},
+ {
+ timeoutMs: 25
+ }
+ )
+ const worker = workerState.instances[0]
+
+ await vi.advanceTimersByTimeAsync(24)
+ expect(worker?.terminated).toBe(false)
+
+ await vi.advanceTimersByTimeAsync(1)
+
+ await expect(resultPromise).resolves.toEqual({
+ ok: false,
+ reason: 'Theme file took too long to parse.'
+ })
+ expect(worker?.terminated).toBe(true)
+ })
+})
diff --git a/src/main/warp-themes/parser-runner.ts b/src/main/warp-themes/parser-runner.ts
new file mode 100644
index 00000000000..4d12007e929
--- /dev/null
+++ b/src/main/warp-themes/parser-runner.ts
@@ -0,0 +1,76 @@
+import { Worker } from 'worker_threads'
+import { app } from 'electron'
+import { join } from 'path'
+import type { ParsedWarpThemeResult, ParseWarpThemeOptions } from './parser'
+
+export const WARP_THEME_PARSE_TIMEOUT_MS = 1_000
+
+type ParseWarpThemeTimeoutOptions = {
+ timeoutMs?: number
+}
+
+function getParserWorkerPath(): string {
+ if (app.isPackaged) {
+ return join(process.resourcesPath, 'app.asar', 'out', 'main', 'warp-theme-parser-worker.js')
+ }
+ return join(__dirname, 'warp-theme-parser-worker.js')
+}
+
+function isParsedWarpThemeResult(value: unknown): value is ParsedWarpThemeResult {
+ if (!value || typeof value !== 'object') {
+ return false
+ }
+ const record = value as Record
+ return record.ok === true || record.ok === false
+}
+
+export function parseWarpThemeYamlWithTimeout(
+ content: string,
+ fileLabel: string,
+ options: ParseWarpThemeOptions = {},
+ timeoutOptions: ParseWarpThemeTimeoutOptions = {}
+): Promise {
+ return new Promise((resolve) => {
+ const worker = new Worker(getParserWorkerPath(), {
+ workerData: { content, fileLabel, options }
+ })
+ let settled = false
+ // Why: callers may shorten the parse timeout (preview budget) but never
+ // extend it past the default cap, keeping untrusted-input parse time bounded.
+ const timeoutMs = Math.max(
+ 0,
+ Math.min(WARP_THEME_PARSE_TIMEOUT_MS, timeoutOptions.timeoutMs ?? WARP_THEME_PARSE_TIMEOUT_MS)
+ )
+ const timeout = setTimeout(() => {
+ settle({ ok: false, reason: 'Theme file took too long to parse.' })
+ void worker.terminate()
+ }, timeoutMs)
+ timeout.unref?.()
+
+ function settle(result: ParsedWarpThemeResult): void {
+ if (settled) {
+ return
+ }
+ settled = true
+ clearTimeout(timeout)
+ worker.removeAllListeners()
+ resolve(result)
+ }
+
+ worker.once('message', (message: unknown) => {
+ settle(
+ isParsedWarpThemeResult(message)
+ ? message
+ : { ok: false, reason: 'Theme parser returned an invalid result.' }
+ )
+ })
+ worker.once('error', () => {
+ settle({ ok: false, reason: 'Invalid YAML' })
+ })
+ worker.once('exit', (code) => {
+ if (code !== 0) {
+ settle({ ok: false, reason: 'Theme parser exited before returning a result.' })
+ }
+ })
+ })
+}
diff --git a/src/main/warp-themes/parser.test.ts b/src/main/warp-themes/parser.test.ts
new file mode 100644
index 00000000000..5295be639ca
--- /dev/null
+++ b/src/main/warp-themes/parser.test.ts
@@ -0,0 +1,137 @@
+import { afterEach, describe, expect, it, vi } from 'vitest'
+import { parseWarpThemeYaml } from './parser'
+
+const VALID_THEME = `
+name: Tokyo Night
+accent: '#7aa2f7'
+background: '#1a1b26'
+foreground: '#c0caf5'
+cursor: '#c0caf5'
+details: darker
+terminal_colors:
+ normal:
+ black: '#15161e'
+ red: '#f7768e'
+ green: '#9ece6a'
+ yellow: '#e0af68'
+ blue: '#7aa2f7'
+ magenta: '#bb9af7'
+ cyan: '#7dcfff'
+ white: '#a9b1d6'
+ bright:
+ black: '#414868'
+ red: '#f7768e'
+ green: '#9ece6a'
+ yellow: '#e0af68'
+ blue: '#7aa2f7'
+ magenta: '#bb9af7'
+ cyan: '#7dcfff'
+ white: '#c0caf5'
+`
+
+describe('parseWarpThemeYaml', () => {
+ afterEach(() => {
+ vi.restoreAllMocks()
+ })
+
+ it('maps Warp normal and bright palettes to Orca terminal colors', () => {
+ const result = parseWarpThemeYaml(VALID_THEME, 'tokyo_night.yaml', {
+ importedAt: '2026-06-05T00:00:00.000Z',
+ sourceLabel: 'themes'
+ })
+
+ expect(result.ok).toBe(true)
+ if (!result.ok) {
+ return
+ }
+ expect(result.theme).toMatchObject({
+ id: 'warp:tokyo-night',
+ selectionValue: 'custom:warp:tokyo-night',
+ name: 'Tokyo Night',
+ source: 'warp',
+ mode: 'dark',
+ importedAt: '2026-06-05T00:00:00.000Z',
+ sourceLabel: 'themes'
+ })
+ expect(result.theme.terminal).toMatchObject({
+ background: '#1a1b26',
+ foreground: '#c0caf5',
+ cursor: '#c0caf5',
+ black: '#15161e',
+ red: '#f7768e',
+ brightBlack: '#414868',
+ brightWhite: '#c0caf5'
+ })
+ })
+
+ it('derives name from filename and light mode from background luminance', () => {
+ const result = parseWarpThemeYaml(
+ VALID_THEME.replace('name: Tokyo Night', '').replace(
+ "background: '#1a1b26'",
+ "background: '#ffffff'"
+ ),
+ 'bright-theme.yaml'
+ )
+
+ expect(result.ok).toBe(true)
+ if (result.ok) {
+ expect(result.theme.name).toBe('bright-theme')
+ expect(result.theme.mode).toBe('light')
+ }
+ })
+
+ it('reports unsupported background images and gradients', () => {
+ const result = parseWarpThemeYaml(
+ `${VALID_THEME}\nbackground_image:\n path: ./image.png\nbackground_gradient: []\n`,
+ 'image.yaml'
+ )
+
+ expect(result.ok).toBe(true)
+ if (result.ok) {
+ expect(result.theme.unsupportedFeatures).toEqual([
+ 'background image not supported',
+ 'gradient not supported'
+ ])
+ }
+ })
+
+ it('uses a gradient endpoint as the terminal background', () => {
+ const result = parseWarpThemeYaml(
+ VALID_THEME.replace(
+ "background: '#1a1b26'",
+ 'background:\n top: "#002633"\n bottom: "#000000"'
+ ).replace("accent: '#7aa2f7'", 'accent:\n left: "#007972"\n right: "#7b008f"'),
+ 'cyber-wave.yaml'
+ )
+
+ expect(result.ok).toBe(true)
+ if (result.ok) {
+ expect(result.theme.terminal.background).toBe('#002633')
+ expect(result.theme.unsupportedFeatures).toEqual([
+ 'background gradient not supported',
+ 'accent gradient not supported'
+ ])
+ }
+ })
+
+ it('rejects non-object or unusable themes', () => {
+ expect(parseWarpThemeYaml('- one\n- two', 'list.yaml')).toEqual({
+ ok: false,
+ reason: 'Theme file must contain a YAML object.'
+ })
+ const partial = parseWarpThemeYaml(
+ 'background: "#000000"\nforeground: "#ffffff"',
+ 'partial.yaml'
+ )
+ expect(partial.ok).toBe(false)
+ })
+
+ it('rejects themes that exceed the parse-time budget', () => {
+ vi.spyOn(Date, 'now').mockReturnValueOnce(0).mockReturnValueOnce(2_000)
+
+ expect(parseWarpThemeYaml(VALID_THEME, 'slow.yaml')).toEqual({
+ ok: false,
+ reason: 'Theme file took too long to parse.'
+ })
+ })
+})
diff --git a/src/main/warp-themes/parser.ts b/src/main/warp-themes/parser.ts
new file mode 100644
index 00000000000..40647355917
--- /dev/null
+++ b/src/main/warp-themes/parser.ts
@@ -0,0 +1,228 @@
+import path from 'path'
+import { parseDocument } from 'yaml'
+import type { TerminalColorOverrides } from '../../shared/types'
+import {
+ hasUsableTerminalThemeColors,
+ makeCustomTerminalThemeSelection,
+ normalizeTerminalHexColor,
+ normalizeTerminalThemeId,
+ normalizeTerminalThemeName,
+ type TerminalCustomTheme,
+ type TerminalCustomThemeMode,
+ type WarpThemeImportPreviewTheme
+} from '../../shared/terminal-custom-themes'
+
+const WARP_COLOR_NAMES = [
+ 'black',
+ 'red',
+ 'green',
+ 'yellow',
+ 'blue',
+ 'magenta',
+ 'cyan',
+ 'white'
+] as const
+
+const MAX_PARSE_MS = 1_000
+
+const NORMAL_COLOR_KEYS = {
+ black: 'black',
+ red: 'red',
+ green: 'green',
+ yellow: 'yellow',
+ blue: 'blue',
+ magenta: 'magenta',
+ cyan: 'cyan',
+ white: 'white'
+} as const satisfies Record<(typeof WARP_COLOR_NAMES)[number], keyof TerminalColorOverrides>
+
+const BRIGHT_COLOR_KEYS = {
+ black: 'brightBlack',
+ red: 'brightRed',
+ green: 'brightGreen',
+ yellow: 'brightYellow',
+ blue: 'brightBlue',
+ magenta: 'brightMagenta',
+ cyan: 'brightCyan',
+ white: 'brightWhite'
+} as const satisfies Record<(typeof WARP_COLOR_NAMES)[number], keyof TerminalColorOverrides>
+
+export type ParsedWarpThemeResult =
+ | { ok: true; theme: WarpThemeImportPreviewTheme }
+ | { ok: false; reason: string }
+
+export type ParseWarpThemeOptions = {
+ idDiscriminator?: string
+ idSuffix?: string
+ importedAt?: string
+ sourceLabel?: string
+}
+
+function isRecord(value: unknown): value is Record {
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value))
+}
+
+function readColorValue(value: unknown): string | null {
+ const scalar = normalizeTerminalHexColor(value)
+ if (scalar) {
+ return scalar
+ }
+ if (!isRecord(value)) {
+ return null
+ }
+ return (
+ normalizeTerminalHexColor(value.top) ??
+ normalizeTerminalHexColor(value.bottom) ??
+ normalizeTerminalHexColor(value.left) ??
+ normalizeTerminalHexColor(value.right)
+ )
+}
+
+function readColor(input: Record, key: string): string | null {
+ return readColorValue(input[key])
+}
+
+function addWarpPalette(
+ terminal: TerminalColorOverrides,
+ palette: unknown,
+ keys: Record<(typeof WARP_COLOR_NAMES)[number], keyof TerminalColorOverrides>
+): void {
+ if (!isRecord(palette)) {
+ return
+ }
+ for (const name of WARP_COLOR_NAMES) {
+ const color = normalizeTerminalHexColor(palette[name])
+ if (color) {
+ terminal[keys[name]] = color
+ }
+ }
+}
+
+function luminance(hexColor: string): number {
+ const hex = hexColor.slice(1)
+ const red = parseInt(hex.slice(0, 2), 16) / 255
+ const green = parseInt(hex.slice(2, 4), 16) / 255
+ const blue = parseInt(hex.slice(4, 6), 16) / 255
+ return 0.2126 * red + 0.7152 * green + 0.0722 * blue
+}
+
+function inferMode(background: string | undefined, details: unknown): TerminalCustomThemeMode {
+ if (background) {
+ return luminance(background) >= 0.55 ? 'light' : 'dark'
+ }
+ if (details === 'lighter') {
+ return 'light'
+ }
+ if (details === 'darker') {
+ return 'dark'
+ }
+ return 'unknown'
+}
+
+function detectUnsupportedFeatures(input: Record): string[] | undefined {
+ const unsupported = new Set()
+ if ('background_image' in input) {
+ unsupported.add('background image not supported')
+ }
+ if (isRecord(input.background)) {
+ unsupported.add('background gradient not supported')
+ }
+ if (isRecord(input.accent)) {
+ unsupported.add('accent gradient not supported')
+ }
+ if ('background_gradient' in input || 'gradient' in input || 'gradients' in input) {
+ unsupported.add('gradient not supported')
+ }
+ return unsupported.size > 0 ? [...unsupported] : undefined
+}
+
+export function parseWarpThemeYaml(
+ content: string,
+ fileLabel: string,
+ options: ParseWarpThemeOptions = {}
+): ParsedWarpThemeResult {
+ let value: unknown
+ const parseStartedAt = Date.now()
+ const parseTimedOut = (): boolean => Date.now() - parseStartedAt > MAX_PARSE_MS
+ try {
+ const document = parseDocument(content, {
+ keepSourceTokens: false,
+ logLevel: 'silent',
+ prettyErrors: false,
+ uniqueKeys: true
+ })
+ if (parseTimedOut()) {
+ return { ok: false, reason: 'Theme file took too long to parse.' }
+ }
+ if (document.errors.length > 0) {
+ return { ok: false, reason: document.errors[0]?.message ?? 'Invalid YAML' }
+ }
+ // Why: cap alias expansion so a malicious YAML alias bomb can't blow up memory.
+ value = document.toJS({ maxAliasCount: 20 })
+ if (parseTimedOut()) {
+ return { ok: false, reason: 'Theme file took too long to parse.' }
+ }
+ } catch (error) {
+ return {
+ ok: false,
+ reason: error instanceof Error ? error.message : 'Invalid YAML'
+ }
+ }
+
+ if (!isRecord(value)) {
+ return { ok: false, reason: 'Theme file must contain a YAML object.' }
+ }
+
+ const fallbackName = path.basename(fileLabel, path.extname(fileLabel))
+ const name = normalizeTerminalThemeName(value.name, fallbackName)
+ const terminal: TerminalColorOverrides = {}
+ const background = readColor(value, 'background')
+ const foreground = readColor(value, 'foreground')
+ const cursor = readColor(value, 'cursor') ?? readColor(value, 'accent')
+
+ if (background) {
+ terminal.background = background
+ }
+ if (foreground) {
+ terminal.foreground = foreground
+ }
+ if (cursor) {
+ terminal.cursor = cursor
+ }
+
+ const terminalColors = isRecord(value.terminal_colors) ? value.terminal_colors : {}
+ addWarpPalette(terminal, terminalColors.normal, NORMAL_COLOR_KEYS)
+ addWarpPalette(terminal, terminalColors.bright, BRIGHT_COLOR_KEYS)
+
+ if (!hasUsableTerminalThemeColors(terminal)) {
+ return {
+ ok: false,
+ reason: 'Theme must include background, foreground, and at least one ANSI color.'
+ }
+ }
+
+ const safeDiscriminator = normalizeTerminalThemeId(options.idDiscriminator, '')
+ const idBase = normalizeTerminalThemeId(
+ safeDiscriminator ? `warp:${name}:${safeDiscriminator}` : `warp:${name}`
+ )
+ const id = options.idSuffix ? `${idBase}-${options.idSuffix}` : idBase
+ const unsupportedFeatures = detectUnsupportedFeatures(value)
+ const theme: TerminalCustomTheme = {
+ id,
+ name,
+ source: 'warp',
+ mode: inferMode(background ?? undefined, value.details),
+ terminal,
+ importedAt: options.importedAt ?? new Date().toISOString(),
+ sourceLabel: options.sourceLabel ?? fileLabel,
+ ...(unsupportedFeatures ? { unsupportedFeatures } : {})
+ }
+
+ return {
+ ok: true,
+ theme: {
+ ...theme,
+ selectionValue: makeCustomTerminalThemeSelection(theme.id)
+ }
+ }
+}
diff --git a/src/main/warp-themes/preview-operation-budget.ts b/src/main/warp-themes/preview-operation-budget.ts
new file mode 100644
index 00000000000..36985475d95
--- /dev/null
+++ b/src/main/warp-themes/preview-operation-budget.ts
@@ -0,0 +1,43 @@
+import type { WarpThemeImportSkippedFile } from '../../shared/terminal-custom-themes'
+import type { WarpThemeScanBudget } from './theme-file-scanner'
+
+const DEFAULT_PREVIEW_BUDGET_MS = 5_000
+
+export type WarpThemePreviewOptions = {
+ operationBudgetMs?: number
+ now?: () => number
+}
+
+export type PreviewOperationBudget = WarpThemeScanBudget & {
+ remainingMs: () => number
+ remainingThemeFiles: (scheduledCount: number, totalCount: number) => number
+}
+
+export function createPreviewOperationBudget(
+ options: WarpThemePreviewOptions = {}
+): PreviewOperationBudget {
+ const now = options.now ?? Date.now
+ const budgetMs = options.operationBudgetMs ?? DEFAULT_PREVIEW_BUDGET_MS
+ const deadline = now() + Math.max(0, budgetMs)
+ return {
+ isExpired: () => now() >= deadline,
+ remainingMs: () => Math.max(0, deadline - now()),
+ remainingThemeFiles: (scheduledCount, totalCount) => Math.max(0, totalCount - scheduledCount)
+ }
+}
+
+export function pushPreviewBudgetSkippedFile(
+ skippedFiles: WarpThemeImportSkippedFile[],
+ sourceLabel: string,
+ remainingCount: number
+): void {
+ skippedFiles.push({
+ label: sourceLabel,
+ reason:
+ remainingCount > 0
+ ? `Preview budget expired before ${remainingCount} theme file${
+ remainingCount === 1 ? '' : 's'
+ } could be parsed.`
+ : 'Preview budget expired before all theme files could be parsed.'
+ })
+}
diff --git a/src/main/warp-themes/theme-file-scanner.ts b/src/main/warp-themes/theme-file-scanner.ts
new file mode 100644
index 00000000000..1b6951f103a
--- /dev/null
+++ b/src/main/warp-themes/theme-file-scanner.ts
@@ -0,0 +1,233 @@
+import { opendir } from 'fs/promises'
+import type { Dirent } from 'fs'
+import path from 'path'
+import type { WarpThemeImportSkippedFile } from '../../shared/terminal-custom-themes'
+
+export const MAX_THEME_FILES = 200
+const MAX_THEME_DIRECTORY_DEPTH = 3
+const MAX_THEME_DIRECTORIES = 80
+const MAX_THEME_ENTRIES_PER_DIRECTORY = 500
+const YAML_EXTENSIONS = new Set(['.yaml', '.yml'])
+
+export type ThemeFileCandidate = {
+ path: string
+ label: string
+ content?: string
+ contentHashDiscriminator?: boolean
+ idDiscriminator?: string
+ sourceLabel?: string
+}
+
+export type WarpThemeScanBudget = {
+ isExpired: () => boolean
+}
+
+type DirectoryScanBudget = {
+ directoriesVisited: number
+ directoryLimitReported: boolean
+ entryLimitReported: boolean
+ themeFileLimitHit: boolean
+ previewBudgetReported: boolean
+}
+
+type DirectoryScanState = {
+ rootReadable: boolean
+}
+
+export function isYamlFile(filePath: string): boolean {
+ return YAML_EXTENSIONS.has(path.extname(filePath).toLowerCase())
+}
+
+export function compareThemeFileLabels(
+ left: ThemeFileCandidate,
+ right: ThemeFileCandidate
+): number {
+ return left.label.localeCompare(right.label, undefined, { sensitivity: 'base' })
+}
+
+function compareDirentNames(left: Dirent, right: Dirent): number {
+ return left.name.localeCompare(right.name, undefined, { sensitivity: 'base' })
+}
+
+function couldContainThemeFile(entry: Dirent): boolean {
+ return (entry.isFile() && isYamlFile(entry.name)) || entry.isDirectory()
+}
+
+function reportPreviewBudgetExpired(
+ sourceLabel: string,
+ skippedFiles: WarpThemeImportSkippedFile[],
+ budget: DirectoryScanBudget
+): void {
+ if (budget.previewBudgetReported) {
+ return
+ }
+ skippedFiles.push({
+ label: sourceLabel,
+ reason: 'Preview budget expired before all theme files were scanned.'
+ })
+ budget.previewBudgetReported = true
+}
+
+export function sanitizeReadError(fallback: string): string {
+ // Why: importer previews cross the IPC boundary, so filesystem paths must stay in main.
+ return fallback
+}
+
+async function collectYamlFilesFromDirectory(
+ directoryPath: string,
+ sourceLabel: string,
+ relativeDirectory: string,
+ depth: number,
+ files: ThemeFileCandidate[],
+ skippedFiles: WarpThemeImportSkippedFile[],
+ budget: DirectoryScanBudget,
+ state: DirectoryScanState,
+ scanBudget?: WarpThemeScanBudget
+): Promise {
+ if (scanBudget?.isExpired()) {
+ reportPreviewBudgetExpired(sourceLabel, skippedFiles, budget)
+ return
+ }
+ if (files.length >= MAX_THEME_FILES) {
+ return
+ }
+ if (budget.directoriesVisited >= MAX_THEME_DIRECTORIES) {
+ if (!budget.directoryLimitReported) {
+ skippedFiles.push({
+ label: sourceLabel,
+ reason: `Only the first ${MAX_THEME_DIRECTORIES} folders were scanned.`
+ })
+ budget.directoryLimitReported = true
+ }
+ return
+ }
+ budget.directoriesVisited += 1
+
+ const entries: Dirent[] = []
+ let entryLimitHit = false
+ let previewBudgetExpiredWhileReading = false
+ try {
+ const directory = await opendir(directoryPath, { encoding: 'utf8' })
+ if (depth === 0) {
+ state.rootReadable = true
+ }
+ for await (const entry of directory) {
+ if (scanBudget?.isExpired()) {
+ previewBudgetExpiredWhileReading = true
+ reportPreviewBudgetExpired(sourceLabel, skippedFiles, budget)
+ break
+ }
+ if (entries.length >= MAX_THEME_ENTRIES_PER_DIRECTORY) {
+ entryLimitHit = true
+ break
+ }
+ entries.push(entry)
+ }
+ } catch {
+ skippedFiles.push({
+ label: relativeDirectory || sourceLabel,
+ reason: sanitizeReadError('Could not read folder.')
+ })
+ return
+ }
+
+ const sortedEntries = entries.sort(compareDirentNames)
+ if (previewBudgetExpiredWhileReading) {
+ return
+ }
+ if (entryLimitHit && !budget.entryLimitReported) {
+ skippedFiles.push({
+ label: relativeDirectory || sourceLabel,
+ reason: `Only the first ${MAX_THEME_ENTRIES_PER_DIRECTORY} folder entries were scanned.`
+ })
+ budget.entryLimitReported = true
+ }
+
+ for (const [index, entry] of sortedEntries.entries()) {
+ if (scanBudget?.isExpired()) {
+ if (sortedEntries.slice(index).some(couldContainThemeFile)) {
+ reportPreviewBudgetExpired(sourceLabel, skippedFiles, budget)
+ }
+ return
+ }
+ if (files.length >= MAX_THEME_FILES) {
+ if (sortedEntries.slice(index).some(couldContainThemeFile)) {
+ budget.themeFileLimitHit = true
+ }
+ return
+ }
+ const relativeLabel = relativeDirectory ? path.join(relativeDirectory, entry.name) : entry.name
+ const entryPath = path.join(directoryPath, entry.name)
+ if (entry.isFile() && isYamlFile(entry.name)) {
+ files.push({ path: entryPath, label: relativeLabel })
+ continue
+ }
+ if (entry.isDirectory()) {
+ if (depth >= MAX_THEME_DIRECTORY_DEPTH) {
+ skippedFiles.push({
+ label: relativeLabel,
+ reason: 'Nested folder depth limit reached.'
+ })
+ continue
+ }
+ await collectYamlFilesFromDirectory(
+ entryPath,
+ sourceLabel,
+ relativeLabel,
+ depth + 1,
+ files,
+ skippedFiles,
+ budget,
+ state,
+ scanBudget
+ )
+ if (
+ files.length >= MAX_THEME_FILES &&
+ sortedEntries.slice(index + 1).some(couldContainThemeFile)
+ ) {
+ budget.themeFileLimitHit = true
+ return
+ }
+ }
+ }
+}
+
+export async function scanWarpThemeDirectory(
+ directoryPath: string,
+ scanBudget?: WarpThemeScanBudget
+): Promise<{
+ sourceLabel: string
+ rootReadable: boolean
+ files: ThemeFileCandidate[]
+ skippedFiles: WarpThemeImportSkippedFile[]
+}> {
+ const sourceLabel = path.basename(directoryPath) || 'Warp themes'
+ const files: ThemeFileCandidate[] = []
+ const skippedFiles: WarpThemeImportSkippedFile[] = []
+ const budget: DirectoryScanBudget = {
+ directoriesVisited: 0,
+ directoryLimitReported: false,
+ entryLimitReported: false,
+ themeFileLimitHit: false,
+ previewBudgetReported: false
+ }
+ const state: DirectoryScanState = { rootReadable: false }
+ await collectYamlFilesFromDirectory(
+ directoryPath,
+ sourceLabel,
+ '',
+ 0,
+ files,
+ skippedFiles,
+ budget,
+ state,
+ scanBudget
+ )
+ if (budget.themeFileLimitHit) {
+ skippedFiles.push({
+ label: sourceLabel,
+ reason: `Only the first ${MAX_THEME_FILES} theme files were scanned.`
+ })
+ }
+ return { sourceLabel, rootReadable: state.rootReadable, files, skippedFiles }
+}
diff --git a/src/main/warp-themes/warp-theme-import-source-validation.ts b/src/main/warp-themes/warp-theme-import-source-validation.ts
new file mode 100644
index 00000000000..df78a531a33
--- /dev/null
+++ b/src/main/warp-themes/warp-theme-import-source-validation.ts
@@ -0,0 +1,18 @@
+import type { WarpThemeImportSource } from '../../shared/terminal-custom-themes'
+
+const VALID_SOURCE_KINDS = new Set(['auto', 'chooseFile', 'chooseFolder'])
+
+export function validateWarpThemeImportSource(source: unknown): WarpThemeImportSource | null {
+ if (!source || typeof source !== 'object' || Array.isArray(source)) {
+ return null
+ }
+ const entries = Object.entries(source)
+ if (entries.length !== 1 || entries[0]?.[0] !== 'kind') {
+ return null
+ }
+ const kind = entries[0][1]
+ if (typeof kind !== 'string' || !VALID_SOURCE_KINDS.has(kind)) {
+ return null
+ }
+ return { kind } as WarpThemeImportSource
+}
diff --git a/src/main/warp-themes/warp-theme-parser-worker.ts b/src/main/warp-themes/warp-theme-parser-worker.ts
new file mode 100644
index 00000000000..e5cc55d2722
--- /dev/null
+++ b/src/main/warp-themes/warp-theme-parser-worker.ts
@@ -0,0 +1,23 @@
+import { parentPort, workerData } from 'worker_threads'
+import { parseWarpThemeYaml } from './parser'
+import type { ParseWarpThemeOptions } from './parser'
+
+const data = workerData as {
+ content?: unknown
+ fileLabel?: unknown
+ options?: unknown
+}
+const options =
+ data.options && typeof data.options === 'object' ? (data.options as ParseWarpThemeOptions) : {}
+
+if (!parentPort) {
+ throw new Error('Warp theme parser worker must run with a parent port.')
+}
+
+parentPort.postMessage(
+ parseWarpThemeYaml(
+ typeof data.content === 'string' ? data.content : '',
+ typeof data.fileLabel === 'string' ? data.fileLabel : 'theme.yaml',
+ options
+ )
+)
diff --git a/src/preload/api-types.ts b/src/preload/api-types.ts
index e5f6ced121b..d04d442ad75 100644
--- a/src/preload/api-types.ts
+++ b/src/preload/api-types.ts
@@ -145,6 +145,10 @@ import type {
WorkspaceSessionPatch,
WorkspaceSessionState
} from '../shared/types'
+import type {
+ WarpThemeImportPreview,
+ WarpThemeImportSource
+} from '../shared/terminal-custom-themes'
import type { SetupScriptImportCandidate } from '../shared/setup-script-imports'
import type { GitHistoryOptions, GitHistoryResult } from '../shared/git-history'
import type { PublicKnownRuntimeEnvironment } from '../shared/runtime-environments'
@@ -1616,6 +1620,7 @@ export type PreloadApi = {
set: (args: Partial) => Promise
listFonts: () => Promise
previewGhosttyImport: () => Promise
+ previewWarpThemeImport: (source: WarpThemeImportSource) => Promise
/** Subscribe to out-of-band settings updates (e.g. the View > Appearance
* menu toggles) so the renderer can stay in sync with main's persisted
* state without round-tripping through settings:get. */
diff --git a/src/preload/index.ts b/src/preload/index.ts
index d0fd0930552..517aaadb679 100644
--- a/src/preload/index.ts
+++ b/src/preload/index.ts
@@ -44,6 +44,10 @@ import type {
WorktreeDefaultTabsLaunch,
WorktreeRemoteBranchConflictEvent
} from '../shared/types'
+import type {
+ WarpThemeImportPreview,
+ WarpThemeImportSource
+} from '../shared/terminal-custom-themes'
import type { GitHistoryOptions, GitHistoryResult } from '../shared/git-history'
import type { ShellOpenLocalPathResult } from '../shared/shell-open-types'
import type { SkillDiscoveryResult, SkillDiscoveryTarget } from '../shared/skills'
@@ -1502,6 +1506,9 @@ const api = {
previewGhosttyImport: (): Promise =>
ipcRenderer.invoke('settings:previewGhosttyImport'),
+ previewWarpThemeImport: (source: WarpThemeImportSource): Promise =>
+ ipcRenderer.invoke('settings:previewWarpThemeImport', source),
+
onChanged: (callback: (updates: Record) => void): (() => void) => {
const listener = (
_event: Electron.IpcRendererEvent,
diff --git a/src/renderer/src/components/icons/WarpIcon.tsx b/src/renderer/src/components/icons/WarpIcon.tsx
new file mode 100644
index 00000000000..7a9626a4eeb
--- /dev/null
+++ b/src/renderer/src/components/icons/WarpIcon.tsx
@@ -0,0 +1,12 @@
+import React from 'react'
+
+// Why: the Warp brand mark labels the "Import themes from Warp" action. Keeping
+// it as a currentColor glyph (like the other brand icons here) lets it inherit
+// button text color and stay theme-aware. Path from simple-icons.
+export function WarpIcon({ className }: { className?: string }): React.JSX.Element {
+ return (
+
+ )
+}
diff --git a/src/renderer/src/components/settings/AppearancePane.test.tsx b/src/renderer/src/components/settings/AppearancePane.test.tsx
index 553984bb0c3..6a54b0c63e9 100644
--- a/src/renderer/src/components/settings/AppearancePane.test.tsx
+++ b/src/renderer/src/components/settings/AppearancePane.test.tsx
@@ -100,6 +100,24 @@ function createGhosttyStub() {
}
}
+function createWarpThemesStub() {
+ return {
+ open: false,
+ preview: null,
+ loading: false,
+ desktopOnly: false,
+ applyError: null,
+ importSignal: 0,
+ selectedThemeIds: new Set(),
+ handleClick: vi.fn(),
+ handlePreviewSource: vi.fn(),
+ handleToggleTheme: vi.fn(),
+ handleToggleAll: vi.fn(),
+ handleApply: vi.fn(),
+ handleOpenChange: vi.fn()
+ }
+}
+
async function renderAppearancePane(
settings: GlobalSettings,
updateSettings: (updates: Partial) => void = vi.fn()
@@ -120,6 +138,7 @@ async function renderAppearancePane(
terminalFontSuggestions={[]}
systemPrefersDark={false}
ghostty={createGhosttyStub() as never}
+ warpThemes={createWarpThemesStub() as never}
/>
)
diff --git a/src/renderer/src/components/settings/AppearancePane.tsx b/src/renderer/src/components/settings/AppearancePane.tsx
index b3ec84bdca2..18ea6b1762f 100644
--- a/src/renderer/src/components/settings/AppearancePane.tsx
+++ b/src/renderer/src/components/settings/AppearancePane.tsx
@@ -38,7 +38,9 @@ import {
import { getTerminalAppearanceSearchEntries } from './terminal-search'
import { TerminalAppearanceSection } from './TerminalAppearanceSection'
import type { UseGhosttyImportReturn } from './useGhosttyImport'
+import type { UseWarpThemeImportReturn } from './useWarpThemeImport'
import { AppIconSelector } from './AppIconSelector'
+import { isWebClientLocation } from '@/hooks/useSettingsNavigationMetadata'
import {
getUiLanguageChoiceLabel,
SHOW_UI_LANGUAGE_SETTING,
@@ -56,6 +58,7 @@ type AppearancePaneProps = {
terminalFontSuggestions: string[]
systemPrefersDark: boolean
ghostty: UseGhosttyImportReturn
+ warpThemes: UseWarpThemeImportReturn
}
function ShortcutHintList({ combos }: { combos: string[][] }): React.JSX.Element {
@@ -88,7 +91,8 @@ export function AppearancePane({
fontSuggestions,
terminalFontSuggestions,
systemPrefersDark,
- ghostty
+ ghostty,
+ warpThemes
}: AppearancePaneProps): React.JSX.Element {
const searchQuery = useAppStore((state) => state.settingsSearchQuery)
const zoomInKeyCombos = useShortcutKeyCombos('zoom.in')
@@ -97,6 +101,9 @@ export function AppearancePane({
const toggleStatusBarItem = useAppStore((state) => state.toggleStatusBarItem)
const recordFeatureInteraction = useAppStore((state) => state.recordFeatureInteraction)
const visibleStatusBarToggles = useAvailableStatusBarToggles(getStatusBarToggles())
+ const terminalAppearanceSearchEntries = getTerminalAppearanceSearchEntries({
+ showWarpImport: !isWebClientLocation()
+ })
const visibleSections = [
matchesSettingsSearch(searchQuery, getThemeEntries()) ||
(SHOW_UI_LANGUAGE_SETTING && matchesSettingsSearch(searchQuery, getLanguageEntries())) ||
@@ -256,7 +263,7 @@ export function AppearancePane({
) : null}
) : null,
- matchesSettingsSearch(searchQuery, getTerminalAppearanceSearchEntries()) ? (
+ matchesSettingsSearch(searchQuery, terminalAppearanceSearchEntries) ? (
) : null,
matchesSettingsSearch(searchQuery, getLayoutEntries()) ? (
diff --git a/src/renderer/src/components/settings/Settings.tsx b/src/renderer/src/components/settings/Settings.tsx
index 1fa6703d4b1..7b5ef155881 100644
--- a/src/renderer/src/components/settings/Settings.tsx
+++ b/src/renderer/src/components/settings/Settings.tsx
@@ -24,6 +24,7 @@ import { ShortcutsPane } from './ShortcutsPane'
import { TerminalPane } from './TerminalPane'
import { FloatingWorkspacePane } from './FloatingWorkspacePane'
import { useGhosttyImport } from './useGhosttyImport'
+import { useWarpThemeImport } from './useWarpThemeImport'
import { RepositoryPane } from './RepositoryPane'
import { GitPane } from './GitPane'
import { CommitMessageAiPane } from './CommitMessageAiPane'
@@ -249,6 +250,7 @@ function Settings(): React.JSX.Element {
// Why: Appearance owns terminal visual controls, but the Ghostty import flow
// still needs Settings-level state so the modal survives section remounts.
const ghostty = useGhosttyImport(updateSettings, settings)
+ const warpThemes = useWarpThemeImport(updateSettings, settings)
const [fontSuggestions, setFontSuggestions] = useState(
Array.from(new Set([DEFAULT_APP_FONT_FAMILY, ...getFallbackTerminalFonts()]))
)
@@ -1277,6 +1279,7 @@ function Settings(): React.JSX.Element {
)}
systemPrefersDark={systemPrefersDark}
ghostty={ghostty}
+ warpThemes={warpThemes}
/>
) : null}
diff --git a/src/renderer/src/components/settings/SettingsFormControls.tsx b/src/renderer/src/components/settings/SettingsFormControls.tsx
index 1c6e5588bb3..40b8b144bea 100644
--- a/src/renderer/src/components/settings/SettingsFormControls.tsx
+++ b/src/renderer/src/components/settings/SettingsFormControls.tsx
@@ -7,7 +7,7 @@ import { ScrollArea } from '../ui/scroll-area'
import { Input } from '../ui/input'
import { Label } from '../ui/label'
import { Check, ChevronsUpDown, CircleX } from 'lucide-react'
-import { BUILTIN_TERMINAL_THEME_NAMES, normalizeColor } from '@/lib/terminal-theme'
+import { normalizeColor, type TerminalThemeOption } from '@/lib/terminal-theme'
import { MAX_THEME_RESULTS } from './SettingsConstants'
import { cn } from '@/lib/utils'
import { translate } from '@/i18n/i18n'
@@ -236,9 +236,13 @@ type ThemePickerProps = {
label: string
description: string
selectedTheme: string
+ themeOptions: TerminalThemeOption[]
query: string
onQueryChange: (value: string) => void
onSelectTheme: (theme: string) => void
+ /** Bumps when themes are imported; scrolls the Imported group into view and
+ * briefly highlights it so freshly-imported themes are easy to find. */
+ importedHighlightSignal?: number
}
type ColorFieldProps = {
@@ -277,14 +281,49 @@ export function ThemePicker({
label,
description,
selectedTheme,
+ themeOptions,
query,
onQueryChange,
- onSelectTheme
+ onSelectTheme,
+ importedHighlightSignal
}: ThemePickerProps): React.JSX.Element {
+ const importedGroupRef = useRef(null)
+ const [highlightImported, setHighlightImported] = useState(false)
+
+ // Why: imported themes render below the built-in list inside a fixed-height
+ // scroll area, so after an import they sit off-screen. On each import signal,
+ // scroll the Imported group into view and flash a highlight so it's easy to spot.
+ useEffect(() => {
+ if (!importedHighlightSignal) {
+ return
+ }
+ importedGroupRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
+ setHighlightImported(true)
+ const timer = setTimeout(() => setHighlightImported(false), 2000)
+ return () => clearTimeout(timer)
+ }, [importedHighlightSignal])
+
const normalizedQuery = query.trim().toLowerCase()
- const filteredThemes = BUILTIN_TERMINAL_THEME_NAMES.filter((theme) =>
- theme.toLowerCase().includes(normalizedQuery)
- ).slice(0, MAX_THEME_RESULTS)
+ const matchingThemes = themeOptions.filter((theme) =>
+ `${theme.label} ${theme.sourceLabel ?? ''}`.toLowerCase().includes(normalizedQuery)
+ )
+ const selectedThemeLabel =
+ themeOptions.find((option) => option.value === selectedTheme)?.label ?? selectedTheme
+ const groupedThemes = [
+ {
+ label: translate('auto.components.settings.SettingsFormControls.builtin_themes', 'Built-in'),
+ themes: matchingThemes
+ .filter((theme) => theme.group === 'built-in')
+ .slice(0, MAX_THEME_RESULTS)
+ },
+ {
+ label: translate('auto.components.settings.SettingsFormControls.imported_themes', 'Imported'),
+ themes: matchingThemes
+ .filter((theme) => theme.group === 'imported')
+ .slice(0, MAX_THEME_RESULTS)
+ }
+ ].filter((group) => group.themes.length > 0)
+ const visibleThemeCount = groupedThemes.reduce((sum, group) => sum + group.themes.length, 0)
return (
- {translate("auto.components.CodexRestartChip.9263e75f49", "Codex is using the previous account")}
+ {translate(
+ 'auto.components.CodexRestartChip.9263e75f49',
+ 'Codex is using the previous account'
+ )}
+
diff --git a/src/renderer/src/components/FirstLaunchBanner.tsx b/src/renderer/src/components/FirstLaunchBanner.tsx
index 9a44ed3a6ed..2237770e2f2 100644
--- a/src/renderer/src/components/FirstLaunchBanner.tsx
+++ b/src/renderer/src/components/FirstLaunchBanner.tsx
@@ -128,21 +128,30 @@ export function FirstLaunchBanner({
{/* Text column — title + body stack on the left, takes remaining
width so the action column never pushes copy into a wrap. */}
-
{translate("auto.components.FirstLaunchBanner.9784b4d7bc", "Help us decide what to build next")}
+
+ {translate(
+ 'auto.components.FirstLaunchBanner.9784b4d7bc',
+ 'Help us decide what to build next'
+ )}
+
- {translate("auto.components.FirstLaunchBanner.958d2cc31b", "Anonymous counts of which features you use help us prioritize what to build. No file contents, prompts, terminal output, or anything that identifies you. Change anytime in Settings -> Privacy & Telemetry.")}{' '}
+ {translate(
+ 'auto.components.FirstLaunchBanner.958d2cc31b',
+ 'Anonymous counts of which features you use help us prioritize what to build. No file contents, prompts, terminal output, or anything that identifies you. Change anytime in Settings -> Privacy & Telemetry.'
+ )}{' '}
void window.api.shell.openUrl(PRIVACY_URL)}
>
- {translate("auto.components.FirstLaunchBanner.d1deebb050", "Privacy policy")}
+ {translate('auto.components.FirstLaunchBanner.d1deebb050', 'Privacy policy')}
+
.
- {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.")}
{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.'
+ )}
{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'
+ )}
+
- {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.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.'
+ )}
+
- {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.'
+ )}
+
- {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 && (
-
- {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.'
+ )}
@@ -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 (
- {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.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 (
-
- {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.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.”")}
{/* 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.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}.
- {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/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.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'
+ )}
+
- {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'
+ )}
+
{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.'
+ )}
{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.'
+ )}
{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.'
+ )}
- {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.'
+ )}
+
@@ -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')}
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}
- {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.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.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.'
+ )}
+
- {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.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.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.'
+ )}
+
{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.'
+ )}
+
- {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.'
+ )}
+
- {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.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({
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.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.'
+ )}
+
- {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.'
+ )}
+
)}
- {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.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 ?
- {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}
-
+
- {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).')}
+
- {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.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.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({
+ {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.'
+ )}
+
>
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.'
+ )}
+
- {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. */}
)
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({
- {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.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 {
{/* 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. */}
{/* 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...")}
}
>
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({
)
@@ -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.c936c2d6d2", "Submit immediately instead of only inserting text.")}
+ {translate(
+ 'auto.components.terminal.quick.commands.TerminalQuickCommandAppendEnterSwitch.c936c2d6d2',
+ 'Submit immediately instead of only inserting text.'
+ )}
+