From 94a89500ae1d9c576f98332dceae83b499fe5ac9 Mon Sep 17 00:00:00 2001 From: Serhii Vecherenko Date: Thu, 30 Jul 2026 14:01:48 -0700 Subject: [PATCH] feat(browser): add downloads, passwords, import, find, and device tools --- .../scripts/poracode-browser-smoke.mjs | 257 ++++++- .../scripts/smoke-scenarios.mjs | 3 +- .../browser/BrowserCredentialStore.test.ts | 181 +++++ src/main/browser/BrowserCredentialStore.ts | 209 +++++ .../browser/BrowserDownloadManager.test.ts | 224 ++++++ src/main/browser/BrowserDownloadManager.ts | 322 ++++++++ src/main/browser/BrowserPanelManager.test.ts | 287 ++++++- src/main/browser/BrowserPanelManager.ts | 240 +++++- src/main/browser/BrowserTab.test.ts | 279 +++++++ src/main/browser/BrowserTab.ts | 159 ++++ .../WindowsChromiumImportService.test.ts | 403 ++++++++++ .../browser/WindowsChromiumImportService.ts | 726 ++++++++++++++++++ src/main/ipc/localHandlers.ts | 45 ++ src/main/main.ts | 4 +- .../components/find/findController.test.ts | 33 +- .../components/find/findController.ts | 12 +- src/renderer/locales/de/messages.po | 456 ++++++++++- src/renderer/locales/en/messages.po | 458 ++++++++++- src/renderer/locales/es/messages.po | 456 ++++++++++- src/renderer/locales/fr/messages.po | 456 ++++++++++- src/renderer/locales/ja/messages.po | 458 ++++++++++- src/renderer/locales/ko/messages.po | 456 ++++++++++- src/renderer/locales/pl/messages.po | 456 ++++++++++- src/renderer/locales/pt-BR/messages.po | 458 ++++++++++- src/renderer/locales/ru/messages.po | 458 ++++++++++- src/renderer/locales/tr/messages.po | 458 ++++++++++- src/renderer/locales/uk/messages.po | 458 ++++++++++- src/renderer/locales/vi/messages.po | 456 ++++++++++- src/renderer/locales/zh-CN/messages.po | 456 ++++++++++- src/renderer/state/browserCredentialsStore.ts | 16 + .../state/browserDownloadsStore.test.ts | 46 ++ src/renderer/state/browserDownloadsStore.ts | 30 + src/renderer/state/browserFindStore.ts | 52 ++ src/renderer/state/browserImportStore.ts | 11 + src/renderer/state/browserPanelStore.ts | 25 +- .../parts/BrowserPanel/BrowserPanel.test.tsx | 303 +++++++- .../parts/BrowserPanel/BrowserPanel.tsx | 136 ++-- .../BrowserPanel/hooks/useBrowserSync.ts | 23 + .../parts/BrowserDeviceToolbar.test.tsx | 115 +++ .../parts/BrowserDeviceToolbar.tsx | 267 +++++++ .../parts/BrowserDownloadsPage.test.tsx | 76 ++ .../parts/BrowserDownloadsPage.tsx | 295 +++++++ .../parts/BrowserFindBar.test.tsx | 161 ++++ .../BrowserPanel/parts/BrowserFindBar.tsx | 88 +++ .../parts/BrowserImportModal.test.tsx | 100 +++ .../BrowserPanel/parts/BrowserImportModal.tsx | 222 ++++++ .../BrowserPanel/parts/BrowserMenu.test.tsx | 96 +++ .../parts/BrowserPanel/parts/BrowserMenu.tsx | 459 +++++++++++ .../parts/BrowserPasswordsPage.test.tsx | 72 ++ .../parts/BrowserPasswordsPage.tsx | 449 +++++++++++ .../BrowserPanel/parts/BrowserTabStrip.tsx | 23 +- .../BrowserPanel/parts/BrowserTabWebview.tsx | 190 +++++ .../parts/BrowserToolbar.test.tsx | 52 ++ .../BrowserPanel/parts/BrowserToolbar.tsx | 274 +------ src/shared/ipc/events.ts | 12 +- src/shared/ipc/index.ts | 10 + src/shared/ipc/procedureMap.ts | 14 + src/shared/ipc/procedures/browser.ts | 211 +++++ 58 files changed, 12581 insertions(+), 571 deletions(-) create mode 100644 src/main/browser/BrowserCredentialStore.test.ts create mode 100644 src/main/browser/BrowserCredentialStore.ts create mode 100644 src/main/browser/BrowserDownloadManager.test.ts create mode 100644 src/main/browser/BrowserDownloadManager.ts create mode 100644 src/main/browser/WindowsChromiumImportService.test.ts create mode 100644 src/main/browser/WindowsChromiumImportService.ts create mode 100644 src/renderer/state/browserCredentialsStore.ts create mode 100644 src/renderer/state/browserDownloadsStore.test.ts create mode 100644 src/renderer/state/browserDownloadsStore.ts create mode 100644 src/renderer/state/browserFindStore.ts create mode 100644 src/renderer/state/browserImportStore.ts create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.test.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.test.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.test.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.test.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.test.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.test.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabWebview.tsx create mode 100644 src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.test.tsx diff --git a/.agents/skills/interactive-testing/scripts/poracode-browser-smoke.mjs b/.agents/skills/interactive-testing/scripts/poracode-browser-smoke.mjs index 122f1b48c..826a6ab3d 100644 --- a/.agents/skills/interactive-testing/scripts/poracode-browser-smoke.mjs +++ b/.agents/skills/interactive-testing/scripts/poracode-browser-smoke.mjs @@ -18,6 +18,9 @@ await mkdir(outDir, { recursive: true }); const appTarget = await waitForAppTarget(); const app = await connectTarget(appTarget); +let externalTabId = null; +let deviceEmulationEnabled = false; +let findActive = false; try { step("connected to Poracode renderer"); @@ -58,6 +61,7 @@ try { assert(state.activeTabId !== null, "Active tab", "browser state has an active tab"); assert(activeTab(state)?.url === firstUrl, "Navigate", "active tab reached first smoke URL"); const tabId = state.activeTabId; + externalTabId = tabId; await screenshot(app, "smoke-browser-02-tab.png"); await wait(500); @@ -116,6 +120,136 @@ try { ); await screenshot(app, "smoke-browser-04-navigation.png"); + step("checking downloads internal page creation and reuse"); + await callBridge("browserOpenInternalPage", { page: "downloads" }); + state = await waitForBrowserState( + (s) => activeTab(s)?.internalPage === "downloads", + "downloads internal tab", + ); + const downloadsTabId = state.activeTabId; + const downloadsTabCount = state.tabs.filter((tab) => tab.internalPage === "downloads").length; + const downloadsPage = await waitForInternalPage(downloadsTabId, "Download history"); + assert(downloadsPage.headingVisible, "Downloads heading", "Download history heading is visible"); + assert( + downloadsPage.activeTabWebview === false, + "Downloads guest omission", + "active downloads tab has no webview", + ); + await screenshot(app, "smoke-browser-05-downloads.png"); + + step("checking passwords internal page creation and reuse"); + await callBridge("browserOpenInternalPage", { page: "passwords" }); + state = await waitForBrowserState( + (s) => activeTab(s)?.internalPage === "passwords", + "passwords internal tab", + ); + const passwordsTabId = state.activeTabId; + const passwordsTabCount = state.tabs.filter((tab) => tab.internalPage === "passwords").length; + const passwordsPage = await waitForInternalPage(passwordsTabId, "Manage passwords"); + assert(passwordsPage.headingVisible, "Passwords heading", "Manage passwords heading is visible"); + assert( + passwordsPage.activeTabWebview === false, + "Passwords guest omission", + "active passwords tab has no webview", + ); + await screenshot(app, "smoke-browser-06-passwords.png"); + + await callBridge("browserOpenInternalPage", { page: "downloads" }); + state = await waitForBrowserState( + (s) => s.activeTabId === downloadsTabId, + "reused downloads internal tab", + ); + assert( + state.tabs.filter((tab) => tab.internalPage === "downloads").length === downloadsTabCount, + "Reuse downloads tab", + "opening downloads again activates the existing internal tab", + ); + + await callBridge("browserOpenInternalPage", { page: "passwords" }); + state = await waitForBrowserState( + (s) => s.activeTabId === passwordsTabId, + "reused passwords internal tab", + ); + assert( + state.tabs.filter((tab) => tab.internalPage === "passwords").length === passwordsTabCount, + "Reuse passwords tab", + "opening passwords again activates the existing internal tab", + ); + + step("checking device emulation state and toolbar"); + await callBridge("browserActivateTab", { tabId }); + await waitForBrowserState((s) => s.activeTabId === tabId, "reactivated external smoke tab"); + const emulation = { + width: 833, + height: 970, + deviceScaleFactor: 1, + scale: 1, + mobile: false, + touch: false, + preset: "Responsive", + }; + await callBridge("browserSetDeviceEmulation", { tabId, emulation }); + deviceEmulationEnabled = true; + state = await waitForBrowserState((s) => { + const active = activeTab(s); + return ( + active?.tabId === tabId && + active.deviceEmulation?.width === emulation.width && + active.deviceEmulation?.height === emulation.height && + active.deviceEmulation?.scale === emulation.scale && + active.deviceEmulation?.preset === emulation.preset + ); + }, "device emulation state"); + assert( + activeTab(state)?.deviceEmulation?.preset === "Responsive", + "Device emulation state", + "active external tab exposes Responsive emulation state", + ); + const deviceToolbar = await waitForDeviceToolbar(tabId, emulation.width, emulation.height); + assert( + deviceToolbar.visible, + "Device toolbar", + "device controls are visible with the expected dimensions", + ); + assert( + deviceToolbar.activeTabWebview, + "Emulated guest preserved", + "active external tab keeps its webview while emulated", + ); + await screenshot(app, "smoke-browser-07-device-toolbar.png"); + + await callBridge("browserSetDeviceEmulation", { tabId, emulation: null }); + deviceEmulationEnabled = false; + state = await waitForBrowserState( + (s) => s.activeTabId === tabId && activeTab(s)?.deviceEmulation === undefined, + "cleared device emulation state", + ); + assert( + activeTab(state)?.deviceEmulation === undefined, + "Clear device emulation", + "active external tab returns to its normal viewport", + ); + const toolbarCleared = await evaluate( + `document.querySelector('[data-poracode-browser] [aria-label="Close device toolbar"]') === null`, + ); + assert(toolbarCleared, "Hide device toolbar", "device controls disappear after clearing state"); + + step("checking Find in page against the generated data page"); + await openFindBar(); + findActive = true; + await setFindQuery("second page"); + const findResult = await waitForFindResult("1 of 1"); + assert(findResult.visible, "Find in page", "find bar reports one match in the data page"); + await screenshot(app, "smoke-browser-08-find.png"); + await clickButton("Close find"); + findActive = false; + await waitFor(async () => { + const closed = await evaluate( + `document.querySelector('input[placeholder="Find in page"]') === null`, + ); + return closed ? true : null; + }, "closed browser find bar"); + step("checking Browser settings"); let settingsOpened = await settingsOverlayVisible(); if (!settingsOpened.ok) { @@ -134,7 +268,7 @@ try { }); if (settingsText.ok) { assert(true, "Browser settings", "Browser settings page is reachable"); - await screenshot(app, "smoke-browser-05-settings.png"); + await screenshot(app, "smoke-browser-09-settings.png"); } else { findings.push("Settings opened, but Browser settings page was not reachable by text click."); } @@ -155,6 +289,27 @@ try { printReport(errors); process.exitCode = results.some((result) => result.status === "FAIL") ? 1 : 0; } finally { + if (findActive && externalTabId) { + try { + await clickButton("Close find", { optional: true }); + await callBridge("browserStopFindInPage", { + tabId: externalTabId, + action: "clearSelection", + }); + } catch (error) { + findings.push(`Find cleanup failed: ${error.message}`); + } + } + if (deviceEmulationEnabled && externalTabId) { + try { + await callBridge("browserSetDeviceEmulation", { + tabId: externalTabId, + emulation: null, + }); + } catch (error) { + findings.push(`Device emulation cleanup failed: ${error.message}`); + } + } app.close(); } @@ -415,6 +570,106 @@ function activeTab(state) { return state.tabs.find((tab) => tab.tabId === state.activeTabId); } +async function waitForInternalPage(tabId, heading) { + return waitFor(async () => { + const snapshot = await evaluate( + `(() => { + const root = document.querySelector('[data-poracode-browser]'); + const tabId = ${JSON.stringify(tabId)}; + const headingText = ${JSON.stringify(heading)}; + const heading = [...(root?.querySelectorAll('h1') ?? [])].find( + (candidate) => candidate.textContent?.trim() === headingText, + ); + return { + headingVisible: Boolean(heading && heading.getClientRects().length > 0), + activeTabWebview: Boolean(root?.querySelector('webview[data-tab-id="' + CSS.escape(tabId) + '"]')), + }; + })()`, + ); + return snapshot.headingVisible ? snapshot : null; + }, `${heading} internal page`); +} + +async function waitForDeviceToolbar(tabId, width, height) { + return waitFor(async () => { + const snapshot = await evaluate( + `(() => { + const root = document.querySelector('[data-poracode-browser]'); + const widthInput = root?.querySelector('[aria-label="Viewport width"]'); + const heightInput = root?.querySelector('[aria-label="Viewport height"]'); + const close = root?.querySelector('[aria-label="Close device toolbar"]'); + const tabId = ${JSON.stringify(tabId)}; + return { + visible: Boolean(close && close.getClientRects().length > 0) && + widthInput?.value === ${JSON.stringify(String(width))} && + heightInput?.value === ${JSON.stringify(String(height))}, + activeTabWebview: Boolean(root?.querySelector('webview[data-tab-id="' + CSS.escape(tabId) + '"]')), + }; + })()`, + ); + return snapshot.visible ? snapshot : null; + }, "device toolbar dimensions"); +} + +async function openFindBar() { + await clickButton("Browser menu"); + await waitFor(async () => { + const clicked = await evaluate( + `(() => { + const item = [...document.querySelectorAll('[role="menuitem"]')].find((candidate) => + candidate.querySelector('label')?.textContent?.trim() === "Find in page" + ); + if (!item || item.getAttribute('aria-disabled') === 'true') return false; + item.click(); + return true; + })()`, + ); + return clicked ? true : null; + }, "Find in page menu item"); + await waitFor(async () => { + const visible = await evaluate( + `Boolean(document.querySelector('input[placeholder="Find in page"]'))`, + ); + return visible ? true : null; + }, "browser find bar"); +} + +async function setFindQuery(query) { + const focused = await evaluate( + `(() => { + const input = document.querySelector('input[placeholder="Find in page"]'); + if (!input) return false; + input.focus(); + input.select(); + return true; + })()`, + ); + if (!focused) throw new Error("Browser find input was not available"); + await send(app, "Input.insertText", { text: query }); + await waitFor(async () => { + const value = await evaluate( + `document.querySelector('input[placeholder="Find in page"]')?.value ?? null`, + ); + return value === query ? true : null; + }, "browser find query input"); +} + +async function waitForFindResult(counter) { + return waitFor(async () => { + const snapshot = await evaluate( + `(() => { + const input = document.querySelector('input[placeholder="Find in page"]'); + const search = input?.closest('[role="search"]'); + return { + visible: Boolean(search && search.getClientRects().length > 0), + text: search?.textContent ?? '', + }; + })()`, + ); + return snapshot.visible && snapshot.text.includes(counter) ? snapshot : null; + }, `browser find result ${counter}`); +} + async function callBridge(method, payload) { const result = await evaluate( `(() => { diff --git a/.agents/skills/interactive-testing/scripts/smoke-scenarios.mjs b/.agents/skills/interactive-testing/scripts/smoke-scenarios.mjs index 308dd040b..b19186827 100644 --- a/.agents/skills/interactive-testing/scripts/smoke-scenarios.mjs +++ b/.agents/skills/interactive-testing/scripts/smoke-scenarios.mjs @@ -68,7 +68,8 @@ export const functionalAreas = [ }, { id: "browser", - title: "In-app Browser, browser MCP, picker, bookmarks, and Chrome extension", + title: + "In-app Browser, internal pages, downloads, passwords, device emulation, find, browser MCP, picker, bookmarks, and Chrome extension", patterns: [/browser/i, /chrome-extension/i, /ChromeMcp/i, /picker/i], automated: ["baseline", "browser"], manual: [], diff --git a/src/main/browser/BrowserCredentialStore.test.ts b/src/main/browser/BrowserCredentialStore.test.ts new file mode 100644 index 000000000..db46f19bd --- /dev/null +++ b/src/main/browser/BrowserCredentialStore.test.ts @@ -0,0 +1,181 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const state = new Map(); +const writes: string[] = []; +vi.mock("../db", () => ({ + dbGetState: (key: string) => state.get(key) ?? null, + dbSetState: (key: string, value: string) => { + state.set(key, value); + writes.push(value); + }, +})); + +import { BrowserCredentialStore, normalizeBrowserCredentialOrigin } from "./BrowserCredentialStore"; + +describe("BrowserCredentialStore", () => { + beforeEach(() => { + state.clear(); + writes.length = 0; + }); + + it("normalizes HTTP(S) origins and rejects other protocols", () => { + expect(normalizeBrowserCredentialOrigin("HTTPS://Example.com:443/login?q=1")).toBe( + "https://example.com", + ); + expect(normalizeBrowserCredentialOrigin("http://example.com:8080/path")).toBe( + "http://example.com:8080", + ); + expect(() => normalizeBrowserCredentialOrigin("file:///tmp/login")).toThrow("HTTP(S) origin"); + }); + + it("persists only sealed passwords and returns metadata-only lists", () => { + const store = new BrowserCredentialStore(); + const metadata = store.upsert({ + origin: "https://example.com/login", + username: "ada@example.com", + password: "correct horse battery staple", + }); + + expect(metadata).not.toHaveProperty("password"); + expect(metadata).not.toHaveProperty("sealedPassword"); + expect(store.list()).toEqual([metadata]); + const raw = [...state.values()][0]; + expect(raw).toBeDefined(); + expect(raw).not.toContain("correct horse battery staple"); + expect(raw).toContain("lc-safe:v1:"); + }); + + it("decrypts only through explicit get and survives a new store instance", () => { + const metadata = new BrowserCredentialStore().upsert({ + origin: "https://example.com", + username: "ada", + password: "secret", + }); + + expect(new BrowserCredentialStore().get(metadata.id)).toEqual({ + ...metadata, + password: "secret", + }); + }); + + it("encrypts passwords that resemble the shared sealed-value format", () => { + const password = "lc-safe:v1:not-really-encrypted"; + const metadata = new BrowserCredentialStore().upsert({ + origin: "https://example.com", + username: "ada", + password, + }); + + expect([...state.values()][0]).not.toContain(password); + expect(new BrowserCredentialStore().get(metadata.id)?.password).toBe(password); + }); + + it("upserts by exact normalized origin and username", () => { + const store = new BrowserCredentialStore(); + const original = store.upsert({ + origin: "https://EXAMPLE.com/login", + username: "ada", + password: "old", + }); + const updated = store.upsert({ + origin: "https://example.com:443/account", + username: "ada", + password: "new", + }); + + expect(updated.id).toBe(original.id); + expect(store.list()).toHaveLength(1); + expect(store.get(original.id)?.password).toBe("new"); + }); + + it("persists successful batch entries once and reports invalid rows", () => { + const store = new BrowserCredentialStore(); + const result = store.upsertMany([ + { origin: "https://example.com/login", username: "ada", password: "one" }, + { origin: "file:///invalid", username: "skip", password: "two" }, + { origin: "https://example.org/login", username: "grace", password: "three" }, + ]); + + expect(result).toMatchObject({ failed: 1 }); + expect(result.saved).toHaveLength(2); + expect( + store + .list() + .map((credential) => credential.username) + .sort(), + ).toEqual(["ada", "grace"]); + expect(writes).toHaveLength(1); + }); + + it("updates metadata by id while preserving an existing import source", () => { + const store = new BrowserCredentialStore(); + const original = store.upsert({ + origin: "https://example.com", + username: "ada", + password: "old", + source: "chrome:Default", + }); + const updated = store.upsert({ + id: original.id, + origin: "https://example.org/account", + username: "grace", + password: "new", + }); + + expect(updated).toMatchObject({ + id: original.id, + origin: "https://example.org", + username: "grace", + source: "chrome:Default", + }); + expect(store.get(original.id)?.password).toBe("new"); + }); + + it("filters metadata by exact origin instead of parent or subdomains", () => { + const store = new BrowserCredentialStore(); + store.upsert({ origin: "https://example.com", username: "root", password: "one" }); + store.upsert({ origin: "https://sub.example.com", username: "sub", password: "two" }); + + expect(store.list("https://example.com/path").map((entry) => entry.username)).toEqual(["root"]); + expect(() => store.list("")).toThrow("Invalid URL"); + }); + + it("deletes credentials by id", () => { + const store = new BrowserCredentialStore(); + const metadata = store.upsert({ + origin: "https://example.com", + username: "ada", + password: "secret", + }); + + expect(store.delete(metadata.id)).toBe(true); + expect(store.delete(metadata.id)).toBe(false); + expect(store.get(metadata.id)).toBeUndefined(); + }); + + it("ignores persisted plaintext and malformed origins", () => { + state.set( + "browser-credentials-v1", + JSON.stringify([ + { + id: "plaintext", + origin: "https://example.com", + username: "ada", + sealedPassword: "secret", + createdAt: 1, + updatedAt: 1, + }, + { + id: "file-origin", + origin: "file://example.com", + username: "ada", + sealedPassword: "lc-safe:v1:invalid", + createdAt: 1, + updatedAt: 1, + }, + ]), + ); + + expect(new BrowserCredentialStore().list()).toEqual([]); + }); +}); diff --git a/src/main/browser/BrowserCredentialStore.ts b/src/main/browser/BrowserCredentialStore.ts new file mode 100644 index 000000000..bc91e9fa9 --- /dev/null +++ b/src/main/browser/BrowserCredentialStore.ts @@ -0,0 +1,209 @@ +import { randomUUID } from "node:crypto"; +import type { BrowserCredentialInfo } from "@/shared/ipc"; +import { decryptSecret, encryptSecret, isEncryptedSecret } from "@/shared/secretStorage"; +import { dbGetState, dbSetState } from "../db"; + +const CREDENTIALS_KEY = "browser-credentials-v1"; +const NO_BASE_DIR = ""; +const PASSWORD_PAYLOAD_PREFIX = "browser-password:v1:"; + +export interface BrowserCredential extends BrowserCredentialInfo { + password: string; +} + +export interface BrowserCredentialInput { + id?: string; + origin: string; + username: string; + password: string; + source?: string; +} + +export interface BrowserCredentialBatchResult { + saved: BrowserCredentialInfo[]; + failed: number; +} + +interface PersistedBrowserCredential extends BrowserCredentialInfo { + sealedPassword: string; +} + +/** Normalize a page URL to the exact HTTP(S) origin used for credential matching. */ +export function normalizeBrowserCredentialOrigin(value: string): string { + const url = new URL(value); + if (url.protocol !== "http:" && url.protocol !== "https:") { + throw new Error("Browser credentials require an HTTP(S) origin."); + } + return url.origin; +} + +/** + * Encrypted browser credentials. List operations return metadata only; callers + * must explicitly request a credential by id to obtain its decrypted password. + */ +export class BrowserCredentialStore { + private credentials: PersistedBrowserCredential[] = []; + private loaded = false; + + list(origin?: string): BrowserCredentialInfo[] { + this.load(); + const normalizedOrigin = + origin === undefined ? undefined : normalizeBrowserCredentialOrigin(origin); + return this.credentials + .filter( + (credential) => normalizedOrigin === undefined || credential.origin === normalizedOrigin, + ) + .map(toMetadata) + .sort((a, b) => b.updatedAt - a.updatedAt); + } + + get(id: string): BrowserCredential | undefined { + this.load(); + const credential = this.credentials.find((entry) => entry.id === id); + if (!credential) return undefined; + try { + return { + ...toMetadata(credential), + password: unsealPassword(credential.sealedPassword), + }; + } catch { + return undefined; + } + } + + upsert(input: BrowserCredentialInput): BrowserCredentialInfo { + this.load(); + const credentials = this.credentials.map((credential) => ({ ...credential })); + const metadata = upsertCredential(credentials, input); + this.persist(credentials); + this.credentials = credentials; + return metadata; + } + + upsertMany(inputs: readonly BrowserCredentialInput[]): BrowserCredentialBatchResult { + this.load(); + const credentials = this.credentials.map((credential) => ({ ...credential })); + const saved: BrowserCredentialInfo[] = []; + let failed = 0; + for (const input of inputs) { + try { + saved.push(upsertCredential(credentials, input)); + } catch { + failed += 1; + } + } + if (saved.length > 0) { + this.persist(credentials); + this.credentials = credentials; + } + return { saved, failed }; + } + + delete(id: string): boolean { + this.load(); + const next = this.credentials.filter((credential) => credential.id !== id); + if (next.length === this.credentials.length) return false; + this.credentials = next; + this.persist(this.credentials); + return true; + } + + private load(): void { + if (this.loaded) return; + this.loaded = true; + try { + const raw = dbGetState(CREDENTIALS_KEY); + if (!raw) return; + const parsed = JSON.parse(raw) as unknown; + if (!Array.isArray(parsed)) return; + this.credentials = parsed.filter(isPersistedBrowserCredential); + } catch {} + } + + private persist(credentials: PersistedBrowserCredential[]): void { + dbSetState(CREDENTIALS_KEY, JSON.stringify(credentials)); + } +} + +function upsertCredential( + credentials: PersistedBrowserCredential[], + input: BrowserCredentialInput, +): BrowserCredentialInfo { + const origin = normalizeBrowserCredentialOrigin(input.origin); + const now = Date.now(); + const existing = input.id + ? credentials.find((credential) => credential.id === input.id) + : credentials.find( + (credential) => credential.origin === origin && credential.username === input.username, + ); + if (existing) { + existing.origin = origin; + existing.username = input.username; + existing.sealedPassword = sealPassword(input.password); + existing.updatedAt = now; + if (input.source !== undefined) existing.source = input.source; + return toMetadata(existing); + } + + const credential: PersistedBrowserCredential = { + id: `credential-${randomUUID()}`, + origin, + username: input.username, + sealedPassword: sealPassword(input.password), + createdAt: now, + updatedAt: now, + ...(input.source !== undefined ? { source: input.source } : {}), + }; + credentials.push(credential); + return toMetadata(credential); +} + +function sealPassword(password: string): string { + // `encryptSecret` deliberately accepts already-sealed values unchanged. Add + // an application payload prefix so a real password beginning with the shared + // secret marker is still encrypted rather than mistaken for ciphertext. + return encryptSecret(NO_BASE_DIR, `${PASSWORD_PAYLOAD_PREFIX}${password}`); +} + +function unsealPassword(sealedPassword: string): string { + const payload = decryptSecret(NO_BASE_DIR, sealedPassword); + if (!payload.startsWith(PASSWORD_PAYLOAD_PREFIX)) { + throw new Error("Invalid browser credential payload."); + } + return payload.slice(PASSWORD_PAYLOAD_PREFIX.length); +} + +function toMetadata(credential: PersistedBrowserCredential): BrowserCredentialInfo { + return { + id: credential.id, + origin: credential.origin, + username: credential.username, + createdAt: credential.createdAt, + updatedAt: credential.updatedAt, + ...(credential.source !== undefined ? { source: credential.source } : {}), + }; +} + +function isPersistedBrowserCredential(value: unknown): value is PersistedBrowserCredential { + if (!value || typeof value !== "object") return false; + const credential = value as Partial; + if ( + typeof credential.id !== "string" || + typeof credential.origin !== "string" || + typeof credential.username !== "string" || + typeof credential.sealedPassword !== "string" || + !isEncryptedSecret(credential.sealedPassword) || + typeof credential.createdAt !== "number" || + !Number.isFinite(credential.createdAt) || + typeof credential.updatedAt !== "number" || + !Number.isFinite(credential.updatedAt) || + (credential.source !== undefined && typeof credential.source !== "string") + ) { + return false; + } + try { + return normalizeBrowserCredentialOrigin(credential.origin) === credential.origin; + } catch { + return false; + } +} diff --git a/src/main/browser/BrowserDownloadManager.test.ts b/src/main/browser/BrowserDownloadManager.test.ts new file mode 100644 index 000000000..8951d6ee0 --- /dev/null +++ b/src/main/browser/BrowserDownloadManager.test.ts @@ -0,0 +1,224 @@ +import { EventEmitter } from "node:events"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const dbGetState = vi.hoisted(() => vi.fn<(key: string) => string | null>()); +const dbSetState = vi.hoisted(() => vi.fn<(key: string, value: string) => void>()); +const openPath = vi.hoisted(() => vi.fn<(path: string) => Promise>()); +const showItemInFolder = vi.hoisted(() => vi.fn<(path: string) => void>()); + +vi.mock("../db", () => ({ dbGetState, dbSetState })); +vi.mock("electron", () => ({ shell: { openPath, showItemInFolder } })); + +class FakeSession extends EventEmitter { + emitDownload(item: FakeDownloadItem, webContentsId = 91): void { + this.emit("will-download", {}, item, { id: webContentsId }); + } +} + +class FakeDownloadItem extends EventEmitter { + state: "progressing" | "completed" | "cancelled" | "interrupted" = "progressing"; + receivedBytes = 10; + totalBytes = 100; + paused = false; + resumable = true; + endTime = 0; + savePath = "C:\\Users\\demo\\Downloads\\report.pdf"; + readonly pause = vi.fn<() => void>(() => { + this.paused = true; + }); + readonly resume = vi.fn<() => void>(() => { + this.paused = false; + this.state = "progressing"; + }); + readonly cancel = vi.fn<() => void>(() => { + this.state = "cancelled"; + }); + + getFilename(): string { + return "report.pdf"; + } + getURL(): string { + return "https://example.test/report.pdf"; + } + getMimeType(): string { + return "application/pdf"; + } + getState(): typeof this.state { + return this.state; + } + getReceivedBytes(): number { + return this.receivedBytes; + } + getTotalBytes(): number { + return this.totalBytes; + } + getStartTime(): number { + return 1_700_000_000; + } + getEndTime(): number { + return this.endTime; + } + isPaused(): boolean { + return this.paused; + } + canResume(): boolean { + return this.resumable; + } + getSavePath(): string { + return this.savePath; + } +} + +describe("BrowserDownloadManager", () => { + beforeEach(() => { + vi.clearAllMocks(); + dbGetState.mockReturnValue(null); + openPath.mockResolvedValue(""); + }); + + it("subscribes once, emits renderer-safe metadata, and disposes all listeners", async () => { + const { BrowserDownloadManager } = await import("./BrowserDownloadManager"); + const session = new FakeSession(); + const item = new FakeDownloadItem(); + const onEvent = vi.fn<(event: unknown) => void>(); + const manager = new BrowserDownloadManager(session as never, { onEvent }); + + expect(session.listenerCount("will-download")).toBe(1); + session.emitDownload(item, 17); + + const download = manager.list()[0]!; + expect(download).toMatchObject({ + filename: "report.pdf", + url: "https://example.test/report.pdf", + state: "progressing", + }); + expect(download).not.toHaveProperty("savePath"); + expect(onEvent).toHaveBeenCalledWith({ + type: "created", + download, + webContentsId: 17, + }); + expect(item.listenerCount("updated")).toBe(1); + expect(item.listenerCount("done")).toBe(1); + + manager.dispose(); + + expect(session.listenerCount("will-download")).toBe(0); + expect(item.listenerCount("updated")).toBe(0); + expect(item.listenerCount("done")).toBe(0); + }); + + it("controls a live DownloadItem by opaque ID and tracks progress", async () => { + const { BrowserDownloadManager } = await import("./BrowserDownloadManager"); + const session = new FakeSession(); + const item = new FakeDownloadItem(); + const manager = new BrowserDownloadManager(session as never); + session.emitDownload(item); + const id = manager.list()[0]!.id; + + expect(manager.pause(id)).toBe(true); + expect(item.pause).toHaveBeenCalledOnce(); + expect(manager.list()[0]).toMatchObject({ state: "paused" }); + + expect(manager.resume(id)).toBe(true); + expect(item.resume).toHaveBeenCalledOnce(); + expect(manager.list()[0]).toMatchObject({ state: "progressing" }); + + item.receivedBytes = 60; + item.emit("updated", {}, "progressing"); + expect(manager.list()[0]).toMatchObject({ receivedBytes: 60 }); + + expect(manager.cancel(id)).toBe(true); + expect(item.cancel).toHaveBeenCalledOnce(); + expect(manager.list()[0]).toMatchObject({ state: "cancelled" }); + manager.dispose(); + }); + + it("opens and reveals only completed downloads using the stored main-process path", async () => { + const { BrowserDownloadManager } = await import("./BrowserDownloadManager"); + const session = new FakeSession(); + const item = new FakeDownloadItem(); + const manager = new BrowserDownloadManager(session as never); + session.emitDownload(item); + const id = manager.list()[0]!.id; + + expect(await manager.open(id)).toBe(false); + expect(manager.reveal(id)).toBe(false); + item.state = "completed"; + item.receivedBytes = 100; + item.endTime = 1_700_000_010; + item.resumable = false; + item.emit("done", {}, "completed"); + + expect(await manager.open(id)).toBe(true); + expect(openPath).toHaveBeenCalledWith(item.savePath); + expect(manager.reveal(id)).toBe(true); + expect(showItemInFolder).toHaveBeenCalledWith(item.savePath); + expect(await manager.open("missing-id")).toBe(false); + expect(manager.reveal("missing-id")).toBe(false); + manager.dispose(); + }); + + it("persists history, marks stale in-flight entries interrupted, and never restores handles", async () => { + dbGetState.mockReturnValue( + JSON.stringify({ + downloads: [ + { + id: "persisted-id", + filename: "archive.zip", + url: "https://example.test/archive.zip", + mimeType: "application/zip", + state: "progressing", + receivedBytes: 50, + totalBytes: 100, + bytesPerSecond: 20, + percentComplete: 50, + startTime: 1_700_000_000_000, + paused: false, + canResume: true, + savePath: "C:\\Users\\demo\\Downloads\\archive.zip", + urlChain: ["https://example.test/archive.zip"], + eTag: '"etag"', + lastModified: "Tue, 01 Jan 2026 00:00:00 GMT", + }, + ], + }), + ); + const { BrowserDownloadManager } = await import("./BrowserDownloadManager"); + const manager = new BrowserDownloadManager(new FakeSession() as never); + + expect(manager.list()).toEqual([ + expect.objectContaining({ + id: "persisted-id", + state: "interrupted", + canResume: false, + }), + ]); + expect(manager.pause("persisted-id")).toBe(false); + expect(manager.resume("persisted-id")).toBe(false); + manager.dispose(); + }); + + it("removes terminal history without deleting the file", async () => { + const { BrowserDownloadManager } = await import("./BrowserDownloadManager"); + const session = new FakeSession(); + const item = new FakeDownloadItem(); + const onEvent = vi.fn<(event: unknown) => void>(); + const manager = new BrowserDownloadManager(session as never, { onEvent }); + session.emitDownload(item); + const id = manager.list()[0]!.id; + + expect(manager.remove(id)).toBe(false); + item.state = "completed"; + item.resumable = false; + item.emit("done", {}, "completed"); + expect(manager.remove(id)).toBe(true); + expect(manager.list()).toEqual([]); + expect(onEvent).toHaveBeenLastCalledWith({ type: "removed", downloadId: id }); + expect(dbSetState).toHaveBeenLastCalledWith( + "browser-downloads-v1", + JSON.stringify({ downloads: [] }), + ); + manager.dispose(); + }); +}); diff --git a/src/main/browser/BrowserDownloadManager.ts b/src/main/browser/BrowserDownloadManager.ts new file mode 100644 index 000000000..f4e28d5e3 --- /dev/null +++ b/src/main/browser/BrowserDownloadManager.ts @@ -0,0 +1,322 @@ +import { randomUUID } from "node:crypto"; +import { shell, type DownloadItem, type Session, type WebContents } from "electron"; +import { + browserDownloadStateSchema, + type BrowserDownloadInfo, + type BrowserDownloadState, +} from "@/shared/ipc"; +import { dbGetState, dbSetState } from "../db"; + +const PERSIST_KEY = "browser-downloads-v1"; +const PERSIST_DEBOUNCE_MS = 250; +const MAX_DOWNLOADS = 500; + +export type BrowserDownloadManagerEvent = + | { type: "created"; download: BrowserDownloadInfo; webContentsId: number } + | { type: "updated"; download: BrowserDownloadInfo } + | { type: "removed"; downloadId: string }; + +export interface BrowserDownloadManagerOptions { + onEvent?(event: BrowserDownloadManagerEvent): void; +} + +interface BrowserDownloadRecord extends BrowserDownloadInfo { + savePath: string; +} + +interface LiveDownload { + item: DownloadItem; + cleanup(): void; +} + +interface PersistedBrowserDownloads { + downloads: BrowserDownloadRecord[]; +} + +/** + * Owns downloads initiated by the embedded browser session. Callers operate on + * opaque IDs; paths and Electron DownloadItem instances never leave main. + */ +export class BrowserDownloadManager { + private readonly records = new Map(); + private readonly liveItems = new Map(); + private persistTimer: ReturnType | null = null; + private disposed = false; + + private readonly onWillDownload = ( + _event: Electron.Event, + item: DownloadItem, + webContents: WebContents, + ): void => { + if (this.disposed) return; + const id = randomUUID(); + const record = recordFromItem(id, item); + this.records.set(id, record); + this.bindItem(id, item); + this.prune(); + this.persistNow(); + this.emit({ type: "created", download: toInfo(record), webContentsId: webContents.id }); + }; + + constructor( + private readonly session: Session, + private readonly options: BrowserDownloadManagerOptions = {}, + ) { + this.load(); + this.session.on("will-download", this.onWillDownload); + } + + list(): BrowserDownloadInfo[] { + return this.sortedRecords().map(toInfo); + } + + pause(downloadId: string): boolean { + const item = this.liveItems.get(downloadId)?.item; + const record = this.records.get(downloadId); + if (!item || !record || record.state !== "progressing" || item.isPaused()) return false; + item.pause(); + this.updateRecord(downloadId, item, "paused"); + return true; + } + + resume(downloadId: string): boolean { + const item = this.liveItems.get(downloadId)?.item; + const record = this.records.get(downloadId); + if (!item || !record || !item.canResume()) return false; + if ( + record.state !== "paused" && + record.state !== "interrupted" && + record.state !== "cancelled" + ) { + return false; + } + item.resume(); + this.updateRecord(downloadId, item, "progressing"); + return true; + } + + cancel(downloadId: string): boolean { + const item = this.liveItems.get(downloadId)?.item; + const record = this.records.get(downloadId); + if (!item || !record || isTerminal(record.state)) return false; + item.cancel(); + this.updateRecord(downloadId, item, "cancelled", Date.now()); + return true; + } + + /** Removes history only; the downloaded file is not deleted. */ + remove(downloadId: string): boolean { + const record = this.records.get(downloadId); + if (!record || !isTerminal(record.state)) return false; + this.cleanupItem(downloadId); + this.records.delete(downloadId); + this.persistNow(); + this.emit({ type: "removed", downloadId }); + return true; + } + + async open(downloadId: string): Promise { + const record = this.records.get(downloadId); + if (!record || record.state !== "completed" || !record.savePath) return false; + try { + return (await shell.openPath(record.savePath)) === ""; + } catch { + return false; + } + } + + reveal(downloadId: string): boolean { + const record = this.records.get(downloadId); + if (!record || record.state !== "completed" || !record.savePath) return false; + try { + shell.showItemInFolder(record.savePath); + return true; + } catch { + return false; + } + } + + dispose(): void { + if (this.disposed) return; + this.disposed = true; + this.session.removeListener("will-download", this.onWillDownload); + for (const live of this.liveItems.values()) live.cleanup(); + this.liveItems.clear(); + if (this.persistTimer) { + clearTimeout(this.persistTimer); + this.persistTimer = null; + this.persistNow(); + } + } + + private bindItem(id: string, item: DownloadItem): void { + const onUpdated = (_event: Electron.Event, state: "progressing" | "interrupted"): void => { + this.updateRecord(id, item, state === "progressing" && item.isPaused() ? "paused" : state); + }; + const onDone = ( + _event: Electron.Event, + state: "completed" | "cancelled" | "interrupted", + ): void => { + const endTime = item.getEndTime(); + this.updateRecord(id, item, state, endTime > 0 ? secondsToMilliseconds(endTime) : Date.now()); + if (state === "completed" || !item.canResume()) this.cleanupItem(id); + this.persistNow(); + }; + item.on("updated", onUpdated); + item.on("done", onDone); + this.liveItems.set(id, { + item, + cleanup: () => { + item.removeListener("updated", onUpdated); + item.removeListener("done", onDone); + }, + }); + } + + private cleanupItem(id: string): void { + this.liveItems.get(id)?.cleanup(); + this.liveItems.delete(id); + } + + private updateRecord( + id: string, + item: DownloadItem, + state: BrowserDownloadState, + endTime?: number, + ): void { + const previous = this.records.get(id); + if (!previous) return; + const next = recordFromItem(id, item, state, previous.startTime, endTime); + this.records.set(id, next); + this.schedulePersist(); + this.emit({ type: "updated", download: toInfo(next) }); + } + + private load(): void { + try { + const raw = dbGetState(PERSIST_KEY); + if (!raw) return; + const parsed = JSON.parse(raw) as PersistedBrowserDownloads; + if (!parsed || !Array.isArray(parsed.downloads)) return; + for (const candidate of parsed.downloads) { + if (!isBrowserDownloadRecord(candidate)) continue; + // DownloadItem handles are session-local. In-flight records remain as + // history after restart but cannot claim resumability without a handle. + const staleInFlight = candidate.state === "progressing" || candidate.state === "paused"; + this.records.set(candidate.id, { + ...toInfo(candidate), + ...(staleInFlight ? { state: "interrupted" as const } : {}), + canResume: false, + savePath: candidate.savePath, + }); + } + this.prune(); + } catch {} + } + + private prune(): void { + if (this.records.size <= MAX_DOWNLOADS) return; + for (const record of [...this.records.values()].sort((a, b) => a.startTime - b.startTime)) { + if (this.records.size <= MAX_DOWNLOADS) break; + if (this.liveItems.has(record.id)) continue; + this.records.delete(record.id); + } + } + + private sortedRecords(): BrowserDownloadRecord[] { + return [...this.records.values()].sort((a, b) => b.startTime - a.startTime); + } + + private schedulePersist(): void { + if (this.persistTimer) clearTimeout(this.persistTimer); + this.persistTimer = setTimeout(() => { + this.persistTimer = null; + this.persistNow(); + }, PERSIST_DEBOUNCE_MS); + } + + private persistNow(): void { + if (this.persistTimer) { + clearTimeout(this.persistTimer); + this.persistTimer = null; + } + try { + dbSetState(PERSIST_KEY, JSON.stringify({ downloads: this.sortedRecords() })); + } catch {} + } + + private emit(event: BrowserDownloadManagerEvent): void { + try { + this.options.onEvent?.(event); + } catch {} + } +} + +function recordFromItem( + id: string, + item: DownloadItem, + state: BrowserDownloadState = normalizeItemState(item), + startTime: number = secondsToMilliseconds(item.getStartTime()), + endTime?: number, +): BrowserDownloadRecord { + const totalBytes = Math.max(0, item.getTotalBytes()); + const receivedBytes = Math.max(0, item.getReceivedBytes()); + return { + id, + filename: item.getFilename(), + url: item.getURL(), + mimeType: item.getMimeType(), + state, + receivedBytes, + totalBytes, + startTime: startTime > 0 ? startTime : Date.now(), + ...(endTime !== undefined ? { endTime } : {}), + canResume: item.canResume(), + savePath: item.getSavePath(), + }; +} + +function normalizeItemState(item: DownloadItem): BrowserDownloadState { + const state = item.getState(); + return state === "progressing" && item.isPaused() ? "paused" : state; +} + +function secondsToMilliseconds(value: number): number { + return Math.round(value * 1000); +} + +function isTerminal(state: BrowserDownloadState): boolean { + return state === "completed" || state === "cancelled" || state === "interrupted"; +} + +function toInfo(record: BrowserDownloadRecord): BrowserDownloadInfo { + return { + id: record.id, + filename: record.filename, + url: record.url, + mimeType: record.mimeType, + state: record.state, + receivedBytes: record.receivedBytes, + totalBytes: record.totalBytes, + startTime: record.startTime, + ...(record.endTime !== undefined ? { endTime: record.endTime } : {}), + canResume: record.canResume, + }; +} + +function isBrowserDownloadRecord(value: unknown): value is BrowserDownloadRecord { + if (!value || typeof value !== "object") return false; + const record = value as Partial; + return ( + typeof record.id === "string" && + typeof record.filename === "string" && + typeof record.url === "string" && + typeof record.mimeType === "string" && + browserDownloadStateSchema.safeParse(record.state).success && + typeof record.receivedBytes === "number" && + typeof record.totalBytes === "number" && + typeof record.startTime === "number" && + typeof record.canResume === "boolean" && + typeof record.savePath === "string" + ); +} diff --git a/src/main/browser/BrowserPanelManager.test.ts b/src/main/browser/BrowserPanelManager.test.ts index 768242940..25fb35911 100644 --- a/src/main/browser/BrowserPanelManager.test.ts +++ b/src/main/browser/BrowserPanelManager.test.ts @@ -1,7 +1,14 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import type { BrowserTabGroupInfo } from "@/shared/ipc"; +import type { BrowserDownloadInfo, BrowserImportResult, BrowserTabGroupInfo } from "@/shared/ipc"; +import type { BrowserCredentialStore } from "./BrowserCredentialStore"; +import type { BrowserDownloadManager, BrowserDownloadManagerEvent } from "./BrowserDownloadManager"; +import type { WindowsChromiumImportService } from "./WindowsChromiumImportService"; const resolveWebContentsById = vi.hoisted(() => vi.fn<(id: number) => unknown>()); +const browserTabHarness = vi.hoisted(() => ({ + attach: vi.fn<(webContents: unknown) => void>(), + whenAttached: vi.fn<() => Promise>(() => Promise.resolve()), +})); vi.mock("electron", () => ({ BrowserWindow: class BrowserWindow {}, @@ -41,7 +48,59 @@ vi.mock("./picker/pickerScript", () => ({ })); vi.mock("./BrowserTab", () => ({ - BrowserTab: class BrowserTab {}, + BrowserTab: class BrowserTab { + readonly tabId: string; + private url: string; + private title = ""; + + constructor( + private readonly options: { + tabId: string; + initialUrl?: string; + onUpdate(snapshot: { + tabId: string; + url: string; + title: string; + loading: boolean; + canGoBack: boolean; + canGoForward: boolean; + devToolsOpen: boolean; + zoomFactor: number; + }): void; + }, + ) { + this.tabId = options.tabId; + this.url = options.initialUrl ?? "about:blank"; + } + + snapshot() { + return { + tabId: this.tabId, + url: this.url, + title: this.title, + loading: false, + canGoBack: false, + canGoForward: false, + devToolsOpen: false, + zoomFactor: 1, + }; + } + + isAttached() { + return false; + } + + attach = browserTabHarness.attach; + + whenAttached = browserTabHarness.whenAttached; + + async loadURL(url: string) { + this.url = url; + this.options.onUpdate(this.snapshot()); + } + + async destroy() {} + }, resolveWebContentsById, })); @@ -98,6 +157,47 @@ function seedGroupState( } } +function createBrowserSession() { + return { + on: vi.fn<(event: string, listener: (...args: unknown[]) => void) => void>(), + removeListener: vi.fn<(event: string, listener: (...args: unknown[]) => void) => void>(), + clearStorageData: vi.fn<() => Promise>(() => Promise.resolve()), + clearCache: vi.fn<() => Promise>(() => Promise.resolve()), + }; +} + +function browserDataServices(manager: unknown): { + credentials: BrowserCredentialStore; + downloads: BrowserDownloadManager | null; + importer: WindowsChromiumImportService | null; +} { + return manager as { + credentials: BrowserCredentialStore; + downloads: BrowserDownloadManager | null; + importer: WindowsChromiumImportService | null; + }; +} + +function emptyImportResult(): BrowserImportResult { + return { + passwordsImported: 0, + cookiesImported: 0, + passwordsSkipped: 0, + cookiesSkipped: 0, + protectedItemsSkipped: 0, + errors: [], + }; +} + +function isCredentialsUpdatedEvent(value: unknown): boolean { + return ( + typeof value === "object" && + value !== null && + "type" in value && + value.type === "credentials-updated" + ); +} + describe("BrowserPanelManager", () => { beforeEach(() => { vi.clearAllMocks(); @@ -137,6 +237,189 @@ describe("BrowserPanelManager", () => { expect(tab.attach).toHaveBeenCalledWith(guestWebContents); }); + it("opens app-owned download history once and reuses the existing tab", async () => { + const { BrowserPanelManager } = await import("./BrowserPanelManager"); + const manager = new BrowserPanelManager( + { settingsPath: "settings.json" } as never, + "Mozilla/5.0 Chrome/141.0.0.0 Safari/537.36", + ); + + const first = await manager.openInternalPage("downloads"); + const second = await manager.openInternalPage("downloads"); + + expect(first).toMatchObject({ + url: "chrome://downloads/", + title: "Download history", + internalPage: "downloads", + }); + expect(second.tabId).toBe(first.tabId); + expect(manager.snapshot().tabs).toHaveLength(1); + expect(manager.getTab(first.tabId)).toBeNull(); + expect(manager.getActiveTab()).toBeNull(); + + manager.attachWebContents(first.tabId, 99); + expect(resolveWebContentsById).not.toHaveBeenCalled(); + expect(browserTabHarness.attach).not.toHaveBeenCalled(); + }); + + it("replaces an internal page when the tab navigates to the web", async () => { + const { BrowserPanelManager } = await import("./BrowserPanelManager"); + const manager = new BrowserPanelManager( + { settingsPath: "settings.json" } as never, + "Mozilla/5.0 Chrome/141.0.0.0 Safari/537.36", + ); + const internal = await manager.openInternalPage("passwords"); + + await manager.navigate(internal.tabId, "https://example.com/"); + + expect(manager.snapshot().tabs[0]?.url).toBe("https://example.com/"); + expect(manager.snapshot().tabs[0]?.internalPage).toBeUndefined(); + + const guestWebContents = { id: 99 }; + resolveWebContentsById.mockReturnValue(guestWebContents); + manager.attachWebContents(internal.tabId, 99); + expect(resolveWebContentsById).toHaveBeenCalledWith(99); + expect(browserTabHarness.attach).toHaveBeenCalledWith(guestWebContents); + }); + + it("wires the shared browser session into browser data services", async () => { + const { BrowserPanelManager } = await import("./BrowserPanelManager"); + const session = createBrowserSession(); + const manager = new BrowserPanelManager( + { settingsPath: "settings.json" } as never, + "Mozilla/5.0 Chrome/141.0.0.0 Safari/537.36", + { browserSession: session as never }, + ); + const services = browserDataServices(manager); + const downloadWiring = services.downloads as unknown as { session: unknown }; + const importWiring = services.importer as unknown as { + session: unknown; + credentialStore: unknown; + }; + + expect(downloadWiring.session).toBe(session); + expect(importWiring.session).toBe(session); + expect(importWiring.credentialStore).toBe(services.credentials); + expect(session.on).toHaveBeenCalledWith("will-download", expect.any(Function)); + + const internal = await manager.openInternalPage("downloads"); + await manager.clearCookies(internal.tabId); + await manager.clearCache(internal.tabId); + + expect(session.clearStorageData).toHaveBeenCalledWith({ storages: ["cookies"] }); + expect(session.clearCache).toHaveBeenCalledOnce(); + + manager.dispose(); + expect(session.removeListener).toHaveBeenCalledWith("will-download", expect.any(Function)); + }); + + it("forwards download updates and opaque-id actions through the download manager", async () => { + const { BrowserPanelManager } = await import("./BrowserPanelManager"); + const manager = new BrowserPanelManager( + { settingsPath: "settings.json" } as never, + "Mozilla/5.0 Chrome/141.0.0.0 Safari/537.36", + { browserSession: createBrowserSession() as never }, + ); + const downloads = browserDataServices(manager).downloads; + if (!downloads) throw new Error("Expected the download manager"); + const download = { + id: "download-1", + filename: "report.pdf", + url: "https://example.test/report.pdf", + mimeType: "application/pdf", + state: "progressing", + receivedBytes: 10, + totalBytes: 100, + startTime: 1, + canResume: true, + } satisfies BrowserDownloadInfo; + const list = vi.spyOn(downloads, "list").mockReturnValue([download]); + const pause = vi.spyOn(downloads, "pause"); + const resume = vi.spyOn(downloads, "resume"); + const cancel = vi.spyOn(downloads, "cancel"); + const remove = vi.spyOn(downloads, "remove"); + const open = vi.spyOn(downloads, "open").mockResolvedValue(true); + const reveal = vi.spyOn(downloads, "reveal").mockReturnValue(true); + const events: unknown[] = []; + manager.addEventListener((event) => events.push(event)); + const { onEvent } = ( + downloads as unknown as { + options: { onEvent?(event: BrowserDownloadManagerEvent): void }; + } + ).options; + + onEvent?.({ type: "updated", download }); + onEvent?.({ type: "removed", downloadId: download.id }); + + expect(events).toContainEqual({ type: "download-updated", download }); + expect(events).toContainEqual({ type: "download-removed", downloadId: download.id }); + expect(list).not.toHaveBeenCalled(); + expect(manager.getDownloads()).toEqual([download]); + + await manager.downloadAction(download.id, "pause"); + await manager.downloadAction(download.id, "resume"); + await manager.downloadAction(download.id, "cancel"); + await manager.downloadAction(download.id, "remove"); + await manager.downloadAction(download.id, "open"); + await manager.downloadAction(download.id, "show-in-folder"); + + expect(pause).toHaveBeenCalledWith(download.id); + expect(resume).toHaveBeenCalledWith(download.id); + expect(cancel).toHaveBeenCalledWith(download.id); + expect(remove).toHaveBeenCalledWith(download.id); + expect(open).toHaveBeenCalledWith(download.id); + expect(reveal).toHaveBeenCalledWith(download.id); + + open.mockResolvedValueOnce(false); + await expect(manager.downloadAction(download.id, "open")).rejects.toThrow( + "Unable to open download", + ); + reveal.mockReturnValueOnce(false); + await expect(manager.downloadAction(download.id, "show-in-folder")).rejects.toThrow( + "Unable to show download in folder", + ); + }); + + it("notifies credential consumers only after credential data changes", async () => { + const { BrowserPanelManager } = await import("./BrowserPanelManager"); + const manager = new BrowserPanelManager( + { settingsPath: "settings.json" } as never, + "Mozilla/5.0 Chrome/141.0.0.0 Safari/537.36", + { browserSession: createBrowserSession() as never }, + ); + const importer = browserDataServices(manager).importer; + if (!importer) throw new Error("Expected the browser importer"); + const events: unknown[] = []; + manager.addEventListener((event) => events.push(event)); + + const credential = manager.upsertCredential({ + origin: "https://example.test", + username: "alice", + password: "secret", + }); + manager.deleteCredential("missing"); + manager.deleteCredential(credential.id); + const importData = vi + .spyOn(importer, "importData") + .mockResolvedValueOnce(emptyImportResult()) + .mockResolvedValueOnce({ ...emptyImportResult(), passwordsImported: 1 }); + await manager.importBrowserData({ + sourceId: "source-1", + passwords: true, + cookies: false, + acknowledgeProtectedData: true, + }); + await manager.importBrowserData({ + sourceId: "source-1", + passwords: true, + cookies: false, + acknowledgeProtectedData: true, + }); + + expect(events.filter((event) => isCredentialsUpdatedEvent(event))).toHaveLength(3); + expect(importData).toHaveBeenCalledTimes(2); + }); + it("moves ungrouped tabs into the target tab's group", async () => { const { BrowserPanelManager } = await import("./BrowserPanelManager"); const manager = new BrowserPanelManager( diff --git a/src/main/browser/BrowserPanelManager.ts b/src/main/browser/BrowserPanelManager.ts index c5888d1c2..ee5ab43bf 100644 --- a/src/main/browser/BrowserPanelManager.ts +++ b/src/main/browser/BrowserPanelManager.ts @@ -1,8 +1,15 @@ import { randomUUID } from "node:crypto"; -import { BrowserWindow, shell } from "electron"; +import { BrowserWindow, shell, type Session } from "electron"; import { IPC_EVENT_CHANNELS, type BrowserEvent, + type BrowserCredentialInfo, + type BrowserDeviceEmulation, + type BrowserDownloadInfo, + type BrowserInternalPage, + type BrowserImportResult, + type BrowserImportSourceInfo, + type BrowserPrintResult, type BrowserState, type BrowserStartPickerResult, type BrowserTabGroupInfo, @@ -15,7 +22,10 @@ import { dbGetState, dbSetState } from "../db"; import { readSharedSettingsFile } from "../sharedSettingsFile"; import { saveClipboardImageFile } from "../attachments/localFiles"; import { BrowserLoginCaptureCoordinator } from "./BrowserLoginCaptureCoordinator"; -import { BrowserTab, resolveWebContentsById } from "./BrowserTab"; +import { BrowserCredentialStore } from "./BrowserCredentialStore"; +import { BrowserDownloadManager } from "./BrowserDownloadManager"; +import { BrowserTab, resolveWebContentsById, type BrowserTabSnapshot } from "./BrowserTab"; +import { WindowsChromiumImportService } from "./WindowsChromiumImportService"; import { BrowserTabGroups } from "./BrowserTabGroups"; import { BrowserHistoryStore, fetchSearchSuggestions } from "./browserHistory"; import { BrowserBookmarkStore, type BrowserBookmark } from "./browserBookmarks"; @@ -30,6 +40,10 @@ const ATTACH_TIMEOUT_MS = 8000; const AUTOMATION_GRACE_MS = 45_000; const INTERNAL_BROWSER_PROTOCOLS = new Set(["http:", "https:"]); const SYSTEM_BROWSER_PROTOCOLS = new Set(["http:", "https:", "mailto:"]); +const INTERNAL_PAGES: Record = { + downloads: { url: "chrome://downloads/", title: "Download history" }, + passwords: { url: "chrome://password-manager/passwords", title: "Password Manager" }, +}; interface PersistedTabsState { tabs: Array<{ url: string; title: string; groupId?: string }>; @@ -57,6 +71,7 @@ type PickerPayload = interface BrowserPanelManagerOptions { isExtracted?: () => boolean; focusExtractedWindow?: () => void; + browserSession?: Session; } export class BrowserPanelManager { @@ -72,6 +87,10 @@ export class BrowserPanelManager { private persistTimer: ReturnType | null = null; private readonly history = new BrowserHistoryStore(); private readonly bookmarks = new BrowserBookmarkStore(); + private readonly credentials = new BrowserCredentialStore(); + private readonly downloads: BrowserDownloadManager | null; + private readonly importer: WindowsChromiumImportService | null; + private readonly internalPages = new Map(); private restored = false; private automationActive = false; private automationTimer: ReturnType | null = null; @@ -89,6 +108,20 @@ export class BrowserPanelManager { private readonly browserUserAgent: string, private readonly options: BrowserPanelManagerOptions = {}, ) { + this.downloads = options.browserSession + ? new BrowserDownloadManager(options.browserSession, { + onEvent: (event) => { + if (event.type === "removed") { + this.emit({ type: "download-removed", downloadId: event.downloadId }); + } else { + this.emit({ type: "download-updated", download: event.download }); + } + }, + }) + : null; + this.importer = options.browserSession + ? new WindowsChromiumImportService(options.browserSession, this.credentials) + : null; this.unsubscribePicker = onPickerCommit((commit) => { void this.onPickerCommit(commit); }); @@ -102,7 +135,7 @@ export class BrowserPanelManager { const groups = this.tabGroups.serialize(); const state: PersistedTabsState = { tabs: this.tabs.map((t) => { - const s = t.snapshot(); + const s = this.toInfo(t); const groupId = this.tabGroups.groupIdForTab(t.tabId); return { url: s.url, title: s.title, ...(groupId ? { groupId } : {}) }; }), @@ -179,10 +212,12 @@ export class BrowserPanelManager { } this.clearPickerShortcut(); this.loginCoordinator.cancelLoginConfirmations(); + this.downloads?.dispose(); for (const t of this.tabs) { void t.destroy(); } this.tabs = []; + this.internalPages.clear(); this.activeTabId = null; this.hosts.clear(); } @@ -278,7 +313,7 @@ export class BrowserPanelManager { async ensureTabReady(tabId: string): Promise { this.markAutomationActivity(); const tab = this.findTab(tabId); - if (!tab || tab.isAttached()) return; + if (!tab || this.internalPages.has(tabId) || tab.isAttached()) return; await this.awaitAttach(tab); } @@ -346,18 +381,22 @@ export class BrowserPanelManager { return true; } - private toInfo(t: BrowserTab): BrowserTabInfo { - const s = t.snapshot(); + private toInfo(t: BrowserTab, s: BrowserTabSnapshot = t.snapshot()): BrowserTabInfo { const groupId = this.tabGroups.groupIdForTab(s.tabId); + const internalPage = this.internalPages.get(s.tabId); + const internal = internalPage ? INTERNAL_PAGES[internalPage] : null; return { tabId: s.tabId, - url: s.url, - title: s.title, - loading: s.loading, - canGoBack: s.canGoBack, - canGoForward: s.canGoForward, + url: internal?.url ?? s.url, + title: internal?.title ?? s.title, + loading: internal ? false : s.loading, + canGoBack: internal ? false : s.canGoBack, + canGoForward: internal ? false : s.canGoForward, devToolsOpen: s.devToolsOpen, - ...(s.faviconUrl ? { faviconUrl: s.faviconUrl } : {}), + zoomFactor: s.zoomFactor, + ...(internalPage ? { internalPage } : {}), + ...(!internal && s.deviceEmulation ? { deviceEmulation: s.deviceEmulation } : {}), + ...(!internal && s.faviconUrl ? { faviconUrl: s.faviconUrl } : {}), ...(groupId ? { groupId } : {}), }; } @@ -438,7 +477,7 @@ export class BrowserPanelManager { attachWebContents(tabId: string, webContentsId: number): void { const tab = this.findTab(tabId); - if (!tab) return; + if (!tab || this.internalPages.has(tabId)) return; // Reject a host window's own WebContents by id first, before resolving it. for (const host of this.hosts) { if (host.webContents.id === webContentsId) return; @@ -465,13 +504,18 @@ export class BrowserPanelManager { // passes markActivity:false so reopening the app doesn't wake dormant tabs. if (opts.markActivity !== false) this.markAutomationActivity(); const tabId = `tab-${randomUUID()}`; + const internalPage = payload.url ? internalPageForUrl(payload.url) : undefined; + if (internalPage) this.internalPages.set(tabId, internalPage); const tab = new BrowserTab({ tabId, - ...(payload.url ? { initialUrl: payload.url } : {}), + ...(payload.url && !internalPage ? { initialUrl: payload.url } : {}), userAgent: this.browserUserAgent, - onUpdate: (snap) => { - this.emit({ type: "tab-updated", tab: { ...snap } }); - if (!snap.loading) this.history.record(snap.url, snap.title, Date.now()); + onUpdate: (snapshot) => { + const info = this.toInfo(tab, snapshot); + this.emit({ type: "tab-updated", tab: info }); + if (!info.loading && !info.internalPage) { + this.history.record(info.url, info.title, Date.now()); + } this.schedulePersist(); }, onAttention: (id) => { @@ -480,6 +524,12 @@ export class BrowserPanelManager { onPopup: (_sourceTabId, popupUrl) => { void this.openLink(popupUrl).catch(() => {}); }, + onFindRequested: (id) => { + this.emit({ type: "find-open-requested", tabId: id }); + }, + onFindResult: (id, result) => { + this.emit({ type: "find-result", result: { tabId: id, ...result } }); + }, }); this.tabs.push(tab); // Agent-created tabs auto-join a group (parity with the external extension) @@ -497,7 +547,7 @@ export class BrowserPanelManager { this.schedulePersist(); // Wait for the renderer to mount the and attach its webContents // so callers (e.g. MCP) can immediately use cdp / dialogs / network. - if (opts.awaitAttach !== false) { + if (opts.awaitAttach !== false && !internalPage) { await this.awaitAttach(tab); } return this.toInfo(tab); @@ -535,6 +585,7 @@ export class BrowserPanelManager { if (idx < 0) return; const [tab] = this.tabs.splice(idx, 1); if (!tab) return; + this.internalPages.delete(tabId); await tab.destroy(); this.tabGroups.removeTab(tabId); if (this.activeTabId === tabId) { @@ -548,12 +599,32 @@ export class BrowserPanelManager { async navigate(tabId: string, url: string): Promise { const t = this.findTab(tabId); if (!t) throw new Error(`No browser tab: ${tabId}`); + const internalPage = internalPageForUrl(url); + if (internalPage) { + this.internalPages.set(tabId, internalPage); + this.emitState(); + this.schedulePersist(); + return; + } + this.internalPages.delete(tabId); await t.loadURL(url); } + async openInternalPage(page: BrowserInternalPage): Promise { + const existing = this.tabs.find((tab) => this.internalPages.get(tab.tabId) === page); + if (existing) { + this.setActiveTab(existing.tabId); + return this.toInfo(existing); + } + return await this.createTab( + { url: INTERNAL_PAGES[page].url, activate: true }, + { awaitAttach: false }, + ); + } + async back(tabId: string): Promise { const t = this.findTab(tabId); - if (!t || !t.isAttached()) return; + if (!t || this.internalPages.has(tabId) || !t.isAttached()) return; const wc = t.webContents; if (wc.navigationHistory.canGoBack()) { wc.navigationHistory.goBack(); @@ -562,7 +633,7 @@ export class BrowserPanelManager { async forward(tabId: string): Promise { const t = this.findTab(tabId); - if (!t || !t.isAttached()) return; + if (!t || this.internalPages.has(tabId) || !t.isAttached()) return; const wc = t.webContents; if (wc.navigationHistory.canGoForward()) { wc.navigationHistory.goForward(); @@ -571,22 +642,123 @@ export class BrowserPanelManager { async reload(tabId: string): Promise { const t = this.findTab(tabId); - if (!t || !t.isAttached()) return; + if (!t || this.internalPages.has(tabId) || !t.isAttached()) return; t.webContents.reload(); } async hardReload(tabId: string): Promise { const t = this.findTab(tabId); - if (!t) return; + if (!t || this.internalPages.has(tabId)) return; t.hardReload(); } async toggleDevTools(tabId: string): Promise { const t = this.findTab(tabId); - if (!t) return; + if (!t || this.internalPages.has(tabId)) return; t.toggleDevTools(); } + findInPage( + tabId: string, + text: string, + options: { forward: boolean; findNext: boolean; matchCase: boolean }, + ): void { + if (this.internalPages.has(tabId)) return; + this.findTab(tabId)?.findInPage(text, options); + } + + stopFindInPage( + tabId: string, + action: "clearSelection" | "keepSelection" | "activateSelection", + ): void { + if (this.internalPages.has(tabId)) return; + this.findTab(tabId)?.stopFindInPage(action); + } + + async print(tabId: string): Promise { + const tab = this.findTab(tabId); + if (!tab || this.internalPages.has(tabId)) return { ok: false }; + return await tab.print(); + } + + setZoomFactor(tabId: string, zoomFactor: number): void { + if (this.internalPages.has(tabId)) return; + this.findTab(tabId)?.setZoomFactor(zoomFactor); + } + + setDeviceEmulation(tabId: string, emulation: BrowserDeviceEmulation | null): void { + if (this.internalPages.has(tabId)) return; + this.findTab(tabId)?.setDeviceEmulation(emulation); + } + + getDownloads(): BrowserDownloadInfo[] { + return this.downloads?.list() ?? []; + } + + async downloadAction( + downloadId: string, + action: "pause" | "resume" | "cancel" | "remove" | "open" | "show-in-folder", + ): Promise { + if (!this.downloads) return; + if (action === "pause") this.downloads.pause(downloadId); + else if (action === "resume") this.downloads.resume(downloadId); + else if (action === "cancel") this.downloads.cancel(downloadId); + else if (action === "remove") this.downloads.remove(downloadId); + else if (action === "open") { + if (!(await this.downloads.open(downloadId))) throw new Error("Unable to open download"); + } else if (!this.downloads.reveal(downloadId)) { + throw new Error("Unable to show download in folder"); + } + } + + listCredentials(): BrowserCredentialInfo[] { + return this.credentials.list(); + } + + getCredentialPassword(id: string): string | null { + return this.credentials.get(id)?.password ?? null; + } + + upsertCredential(input: { + id?: string; + origin: string; + username: string; + password: string; + }): BrowserCredentialInfo { + const credential = this.credentials.upsert(input); + this.emit({ type: "credentials-updated" }); + return credential; + } + + deleteCredential(id: string): void { + if (this.credentials.delete(id)) this.emit({ type: "credentials-updated" }); + } + + async listImportSources(): Promise { + return (await this.importer?.listSources()) ?? []; + } + + async importBrowserData(input: { + sourceId: string; + passwords: boolean; + cookies: boolean; + acknowledgeProtectedData: boolean; + }): Promise { + if (!this.importer) { + return { + passwordsImported: 0, + cookiesImported: 0, + passwordsSkipped: 0, + cookiesSkipped: 0, + protectedItemsSkipped: 0, + errors: ["browser-import-unavailable"], + }; + } + const result = await this.importer.importData(input); + if (result.passwordsImported > 0) this.emit({ type: "credentials-updated" }); + return result; + } + async clearHistory(tabId: string): Promise { this.history.clear(); const t = this.findTab(tabId); @@ -608,12 +780,20 @@ export class BrowserPanelManager { } async clearCookies(tabId: string): Promise { + if (this.options.browserSession) { + await this.options.browserSession.clearStorageData({ storages: ["cookies"] }); + return; + } const t = this.findTab(tabId); if (!t) return; await t.clearCookies(); } async clearCache(tabId: string): Promise { + if (this.options.browserSession) { + await this.options.browserSession.clearCache(); + return; + } const t = this.findTab(tabId); if (!t) return; await t.clearCache(); @@ -621,7 +801,7 @@ export class BrowserPanelManager { async capturePng(tabId: string): Promise { const t = this.findTab(tabId); - if (!t || !t.isAttached()) return null; + if (!t || this.internalPages.has(tabId) || !t.isAttached()) return null; return await t.capturePng(); } @@ -681,10 +861,12 @@ export class BrowserPanelManager { } getActiveTab(): BrowserTab | null { - return this.activeTabId ? (this.findTab(this.activeTabId) ?? null) : null; + if (!this.activeTabId || this.internalPages.has(this.activeTabId)) return null; + return this.findTab(this.activeTabId) ?? null; } getTab(tabId: string): BrowserTab | null { + if (this.internalPages.has(tabId)) return null; return this.findTab(tabId) ?? null; } @@ -693,7 +875,7 @@ export class BrowserPanelManager { tabId: string; }): Promise { const tab = this.findTab(payload.tabId); - if (!tab) { + if (!tab || this.internalPages.has(payload.tabId)) { return { ok: false, error: `No browser tab: ${payload.tabId}` }; } if (!tab.isAttached()) { @@ -821,6 +1003,12 @@ function isEscapeKeyDown(input: Electron.Input): boolean { return input.key === "Escape" || input.key === "Esc" || input.code === "Escape"; } +function internalPageForUrl(url: string): BrowserInternalPage | undefined { + return ( + Object.entries(INTERNAL_PAGES) as Array<[BrowserInternalPage, { url: string; title: string }]> + ).find(([, page]) => page.url === url)?.[0]; +} + function isPickerPayload(value: unknown): value is PickerPayload { if (!value || typeof value !== "object") return false; const kind = (value as { kind?: unknown }).kind; diff --git a/src/main/browser/BrowserTab.test.ts b/src/main/browser/BrowserTab.test.ts index 2c28eb542..b70c46602 100644 --- a/src/main/browser/BrowserTab.test.ts +++ b/src/main/browser/BrowserTab.test.ts @@ -5,6 +5,11 @@ const installNavigationGuards = vi.hoisted(() => vi.fn<() => () => void>(() => vi.fn<() => void>()), ); const dialogEnable = vi.hoisted(() => vi.fn<() => Promise>().mockResolvedValue(undefined)); +const cdpSend = vi.hoisted(() => + vi.fn<(method: string, params?: Record) => Promise>(() => + Promise.resolve(), + ), +); vi.mock("electron", () => ({ webContents: { fromId: vi.fn<() => null>(() => null) }, @@ -14,6 +19,7 @@ vi.mock("./cdp/cdpClient", () => ({ CdpClient: class CdpClient { attach = vi.fn<() => Promise>().mockResolvedValue(undefined); detach = vi.fn<() => void>(); + send = cdpSend; }, })); @@ -42,6 +48,18 @@ function createWebContents(initialUrl = "https://example.com/") { return { session: {}, setUserAgent: vi.fn<(userAgent: string) => void>(), + setZoomFactor: vi.fn<(zoomFactor: number) => void>(), + enableDeviceEmulation: vi.fn<(parameters: Electron.Parameters) => void>(), + disableDeviceEmulation: vi.fn<() => void>(), + findInPage: vi.fn<(text: string, options: Electron.FindInPageOptions) => number>(() => 17), + stopFindInPage: + vi.fn<(action: "clearSelection" | "keepSelection" | "activateSelection") => void>(), + print: vi.fn< + ( + options: Electron.WebContentsPrintOptions, + callback: (success: boolean, failureReason: string) => void, + ) => void + >((_options, callback) => callback(true, "")), getURL: vi.fn<() => string>(() => currentUrl), getTitle: vi.fn<() => string>(() => "Example"), isDestroyed: vi.fn<() => boolean>(() => false), @@ -60,6 +78,7 @@ function createWebContents(initialUrl = "https://example.com/") { clear: vi.fn<() => void>(), }, reload: vi.fn<() => void>(), + reloadIgnoringCache: vi.fn<() => void>(), loadURL: vi.fn<(url: string) => Promise>((url) => { currentUrl = url; return Promise.resolve(); @@ -102,6 +121,8 @@ describe("BrowserTab", () => { onUpdate: vi.fn<() => void>(), onAttention: vi.fn<() => void>(), onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), }); const webContents = createWebContents(); @@ -112,6 +133,237 @@ describe("BrowserTab", () => { expect(installNavigationGuards).toHaveBeenCalled(); }); + it("requests find from the guest shortcut and forwards find results", async () => { + const { BrowserTab } = await import("./BrowserTab"); + const onFindRequested = vi.fn<(tabId: string) => void>(); + const onFindResult = vi.fn< + ( + tabId: string, + result: { + requestId: number; + activeMatchOrdinal: number; + matches: number; + finalUpdate: boolean; + }, + ) => void + >(); + const tab = new BrowserTab({ + tabId: "tab-1", + userAgent: "ua", + onUpdate: vi.fn<() => void>(), + onAttention: vi.fn<() => void>(), + onPopup: vi.fn<() => void>(), + onFindRequested, + onFindResult, + }); + const webContents = createWebContents(); + tab.attach(webContents as never); + + const handler = captureBeforeInput(webContents); + const shortcut = { preventDefault: vi.fn<() => void>() }; + handler(shortcut, { type: "keyDown", control: true, key: "f" }); + + expect(shortcut.preventDefault).toHaveBeenCalledOnce(); + expect(onFindRequested).toHaveBeenCalledWith("tab-1"); + + expect(tab.findInPage("needle", { forward: true, findNext: true, matchCase: true })).toBe(17); + expect(webContents.findInPage).toHaveBeenCalledWith("needle", { + forward: true, + findNext: true, + matchCase: true, + }); + + webContents.emit( + "found-in-page", + {}, + { + requestId: 16, + activeMatchOrdinal: 1, + matches: 1, + finalUpdate: true, + }, + ); + expect(onFindResult).not.toHaveBeenCalled(); + + webContents.emit( + "found-in-page", + {}, + { + requestId: 17, + activeMatchOrdinal: 2, + matches: 4, + finalUpdate: true, + }, + ); + expect(onFindResult).toHaveBeenCalledWith("tab-1", { + requestId: 17, + activeMatchOrdinal: 2, + matches: 4, + finalUpdate: true, + }); + + tab.stopFindInPage("clearSelection"); + expect(webContents.stopFindInPage).toHaveBeenCalledWith("clearSelection"); + }); + + it("prints natively from the method and guest shortcut", async () => { + const { BrowserTab } = await import("./BrowserTab"); + const tab = new BrowserTab({ + tabId: "tab-1", + userAgent: "ua", + onUpdate: vi.fn<() => void>(), + onAttention: vi.fn<() => void>(), + onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), + }); + const webContents = createWebContents(); + tab.attach(webContents as never); + + await expect(tab.print()).resolves.toEqual({ ok: true }); + expect(webContents.print).toHaveBeenCalledWith({ silent: false }, expect.any(Function)); + + const handler = captureBeforeInput(webContents); + const shortcut = { preventDefault: vi.fn<() => void>() }; + handler(shortcut, { type: "keyDown", meta: true, key: "p" }); + + expect(shortcut.preventDefault).toHaveBeenCalledOnce(); + expect(webContents.print).toHaveBeenCalledTimes(2); + + webContents.print.mockImplementationOnce((_options, callback) => { + callback(false, "Print job canceled"); + }); + await expect(tab.print()).resolves.toEqual({ ok: false, error: "Print job canceled" }); + }); + + it("applies zoom and device emulation and exposes them in the snapshot", async () => { + const { BrowserTab } = await import("./BrowserTab"); + const onUpdate = vi.fn<() => void>(); + const tab = new BrowserTab({ + tabId: "tab-1", + userAgent: "ua", + onUpdate, + onAttention: vi.fn<() => void>(), + onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), + }); + const webContents = createWebContents(); + tab.attach(webContents as never); + onUpdate.mockClear(); + + tab.setZoomFactor(1.25); + expect(webContents.setZoomFactor).toHaveBeenLastCalledWith(1.25); + expect(tab.snapshot().zoomFactor).toBe(1.25); + + const emulation = { + width: 430, + height: 932, + deviceScaleFactor: 3, + scale: 0.75, + mobile: true, + touch: true, + preset: "iPhone 15 Pro Max", + }; + tab.setDeviceEmulation(emulation); + + expect(webContents.enableDeviceEmulation).toHaveBeenCalledWith({ + screenPosition: "mobile", + screenSize: { width: 430, height: 932 }, + viewPosition: { x: 0, y: 0 }, + deviceScaleFactor: 3, + viewSize: { width: 430, height: 932 }, + scale: 0.75, + }); + expect(cdpSend).toHaveBeenCalledWith("Emulation.setTouchEmulationEnabled", { + enabled: true, + maxTouchPoints: 5, + }); + expect(tab.snapshot()).toMatchObject({ zoomFactor: 1.25, deviceEmulation: emulation }); + + webContents.enableDeviceEmulation.mockClear(); + cdpSend.mockClear(); + tab.setDeviceEmulation(emulation); + expect(webContents.enableDeviceEmulation).not.toHaveBeenCalled(); + expect(cdpSend).not.toHaveBeenCalled(); + + tab.setDeviceEmulation(null); + expect(webContents.disableDeviceEmulation).toHaveBeenCalledOnce(); + expect(cdpSend).toHaveBeenLastCalledWith("Emulation.setTouchEmulationEnabled", { + enabled: false, + }); + expect(tab.snapshot().deviceEmulation).toBeUndefined(); + expect(onUpdate).toHaveBeenCalled(); + }); + + it("reapplies zoom and device emulation when webContents reattaches", async () => { + const { BrowserTab } = await import("./BrowserTab"); + const tab = new BrowserTab({ + tabId: "tab-1", + userAgent: "ua", + onUpdate: vi.fn<() => void>(), + onAttention: vi.fn<() => void>(), + onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), + }); + const emulation = { + width: 1024, + height: 768, + deviceScaleFactor: 1, + scale: 1, + mobile: false, + touch: false, + }; + tab.setZoomFactor(1.5); + tab.setDeviceEmulation(emulation); + + const first = createWebContents(); + tab.attach(first as never); + expect(first.setZoomFactor).toHaveBeenCalledWith(1.5); + expect(first.enableDeviceEmulation).toHaveBeenCalledOnce(); + + first.emit("destroyed"); + const second = createWebContents(); + tab.attach(second as never); + + expect(second.setZoomFactor).toHaveBeenCalledWith(1.5); + expect(second.enableDeviceEmulation).toHaveBeenCalledWith({ + screenPosition: "desktop", + screenSize: { width: 1024, height: 768 }, + viewPosition: { x: 0, y: 0 }, + deviceScaleFactor: 1, + viewSize: { width: 1024, height: 768 }, + scale: 1, + }); + }); + + it("preserves reload and hard-reload guest shortcuts", async () => { + const { BrowserTab } = await import("./BrowserTab"); + const tab = new BrowserTab({ + tabId: "tab-1", + userAgent: "ua", + onUpdate: vi.fn<() => void>(), + onAttention: vi.fn<() => void>(), + onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), + }); + const webContents = createWebContents(); + tab.attach(webContents as never); + + const handler = captureBeforeInput(webContents); + const reload = { preventDefault: vi.fn<() => void>() }; + handler(reload, { type: "keyDown", control: true, key: "r" }); + expect(reload.preventDefault).toHaveBeenCalledOnce(); + expect(webContents.reload).toHaveBeenCalledOnce(); + + const hardReload = { preventDefault: vi.fn<() => void>() }; + handler(hardReload, { type: "keyDown", meta: true, shift: true, key: "r" }); + expect(hardReload.preventDefault).toHaveBeenCalledOnce(); + expect(webContents.reloadIgnoringCache).toHaveBeenCalledOnce(); + }); + it("does not clear newly navigated history after initial page cleanup", async () => { vi.useFakeTimers(); try { @@ -123,6 +375,8 @@ describe("BrowserTab", () => { onUpdate: vi.fn<() => void>(), onAttention: vi.fn<() => void>(), onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), }); const webContents = createWebContents("data:text/html,first"); tab.attach(webContents as never); @@ -142,6 +396,25 @@ describe("BrowserTab", () => { } }); + it("clears synthetic history when an unmounted tab receives its first navigation", async () => { + const { BrowserTab } = await import("./BrowserTab"); + const tab = new BrowserTab({ + tabId: "tab-1", + userAgent: "ua", + onUpdate: vi.fn<() => void>(), + onAttention: vi.fn<() => void>(), + onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), + }); + + await tab.loadURL("data:text/html,first"); + const webContents = createWebContents("data:text/html,first"); + tab.attach(webContents as never); + + expect(webContents.navigationHistory.clear).toHaveBeenCalledOnce(); + }); + it("navigates back/forward on Ctrl+[ and Ctrl+] keydown", async () => { const { BrowserTab } = await import("./BrowserTab"); const tab = new BrowserTab({ @@ -150,6 +423,8 @@ describe("BrowserTab", () => { onUpdate: vi.fn<() => void>(), onAttention: vi.fn<() => void>(), onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), }); const webContents = createWebContents(); tab.attach(webContents as never); @@ -175,6 +450,8 @@ describe("BrowserTab", () => { onUpdate: vi.fn<() => void>(), onAttention: vi.fn<() => void>(), onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), }); const webContents = createWebContents(); tab.attach(webContents as never); @@ -194,6 +471,8 @@ describe("BrowserTab", () => { onUpdate: vi.fn<() => void>(), onAttention: vi.fn<() => void>(), onPopup: vi.fn<() => void>(), + onFindRequested: vi.fn<() => void>(), + onFindResult: vi.fn<() => void>(), }); const webContents = createWebContents(); tab.attach(webContents as never); diff --git a/src/main/browser/BrowserTab.ts b/src/main/browser/BrowserTab.ts index 079dec369..6c282ee71 100644 --- a/src/main/browser/BrowserTab.ts +++ b/src/main/browser/BrowserTab.ts @@ -1,4 +1,5 @@ import { webContents as webContentsModule, type WebContents } from "electron"; +import type { BrowserDeviceEmulation, BrowserFindResult, BrowserPrintResult } from "@/shared/ipc"; import { CdpClient } from "./cdp/cdpClient"; import { DialogController } from "./cdp/dialogController"; import { NetworkCapture } from "./cdp/networkCapture"; @@ -16,9 +17,21 @@ export interface BrowserTabSnapshot { canGoBack: boolean; canGoForward: boolean; devToolsOpen: boolean; + zoomFactor: number; + deviceEmulation?: BrowserDeviceEmulation; faviconUrl?: string; } +export interface BrowserFindInPageOptions { + forward: boolean; + findNext: boolean; + matchCase: boolean; +} + +export type BrowserStopFindInPageAction = "clearSelection" | "keepSelection" | "activateSelection"; + +export type BrowserTabFindResult = Omit; + export interface BrowserTabOptions { tabId: string; initialUrl?: string; @@ -26,6 +39,8 @@ export interface BrowserTabOptions { onUpdate(snapshot: BrowserTabSnapshot): void; onAttention(tabId: string): void; onPopup(tabId: string, url: string): void; + onFindRequested(tabId: string): void; + onFindResult(tabId: string, result: BrowserTabFindResult): void; } export interface ConsoleEntry { @@ -56,6 +71,9 @@ export class BrowserTab { private initialHistoryUrl: string | null = null; private clearInitialHistoryTimer: ReturnType | null = null; private devToolsVisible = false; + private findRequestId: number | null = null; + private zoomFactor = 1; + private deviceEmulation: BrowserDeviceEmulation | undefined; private wcCleanups: Array<() => void> = []; private attachedPromise: Promise; private resolveAttached: (() => void) | null = null; @@ -104,8 +122,14 @@ export class BrowserTab { this.teardownListeners(); } this._webContents = webContents; + this.findRequestId = null; webContents.setUserAgent(this.opts.userAgent); + webContents.setZoomFactor(this.zoomFactor); this._cdp = new CdpClient(webContents); + if (this.deviceEmulation) { + this.applyDeviceEmulation(webContents, this.deviceEmulation); + this.applyTouchEmulation(this.deviceEmulation.touch); + } installSessionPermissions(webContents.session); const removeNavGuards = installNavigationGuards(webContents, (popupUrl) => { this.opts.onPopup(this.tabId, popupUrl); @@ -185,7 +209,29 @@ export class BrowserTab { wc.on("will-prevent-unload", onWillPreventUnload); this.wcCleanups.push(() => wc.removeListener("will-prevent-unload", onWillPreventUnload)); + const onFoundInPage = (_event: Electron.Event, result: Electron.Result) => { + if (this.findRequestId !== result.requestId) return; + this.opts.onFindResult(this.tabId, { + requestId: result.requestId, + activeMatchOrdinal: result.activeMatchOrdinal, + matches: result.matches, + finalUpdate: result.finalUpdate, + }); + }; + wc.on("found-in-page", onFoundInPage); + this.wcCleanups.push(() => wc.removeListener("found-in-page", onFoundInPage)); + const onBeforeInputEvent = (event: Electron.Event, input: Electron.Input) => { + if (isBrowserFindKeyDown(input)) { + event.preventDefault(); + this.opts.onFindRequested(this.tabId); + return; + } + if (isBrowserPrintKeyDown(input)) { + event.preventDefault(); + void this.print(); + return; + } if (isBrowserReloadKeyDown(input)) { event.preventDefault(); if (isBrowserHardReloadKeyDown(input)) { @@ -261,6 +307,7 @@ export class BrowserTab { this.teardownListeners(); this._webContents = null; this._cdp = null; + this.findRequestId = null; // The tab can be unmounted when the headless browser goes idle, then // remounted on the next automation. Re-arm the attach promise so a later // whenAttached() waits for that fresh attach instead of resolving stale. @@ -368,6 +415,8 @@ export class BrowserTab { canGoBack: wc?.navigationHistory.canGoBack() ?? false, canGoForward: wc?.navigationHistory.canGoForward() ?? false, devToolsOpen: this.devToolsVisible, + zoomFactor: this.zoomFactor, + ...(this.deviceEmulation ? { deviceEmulation: this.deviceEmulation } : {}), ...(this.faviconUrl ? { faviconUrl: this.faviconUrl } : {}), }; } @@ -381,6 +430,7 @@ export class BrowserTab { // initial `` (or a later attach) reflects the request. this.currentUrl = url; this.clearInitialHistoryOnLoad = true; + this.initialHistoryUrl = url; this.emit(); return; } @@ -421,6 +471,83 @@ export class BrowserTab { } catch {} } + findInPage(text: string, options: BrowserFindInPageOptions): number | null { + if (this.destroyed || !this.isAttached()) return null; + this.findRequestId = this.webContents.findInPage(text, options); + return this.findRequestId; + } + + stopFindInPage(action: BrowserStopFindInPageAction): void { + if (this.destroyed || !this.isAttached()) return; + this.findRequestId = null; + this.webContents.stopFindInPage(action); + } + + async print(): Promise { + if (this.destroyed || !this.isAttached()) { + return { ok: false }; + } + return await new Promise((resolve) => { + try { + this.webContents.print({ silent: false }, (success, failureReason) => { + resolve( + success + ? { ok: true } + : { ok: false, ...(failureReason ? { error: failureReason } : {}) }, + ); + }); + } catch (error) { + resolve({ + ok: false, + error: error instanceof Error ? error.message : String(error), + }); + } + }); + } + + setZoomFactor(zoomFactor: number): void { + if (this.destroyed) return; + if (this.isAttached()) this.webContents.setZoomFactor(zoomFactor); + this.zoomFactor = zoomFactor; + this.emit(); + } + + setDeviceEmulation(emulation: BrowserDeviceEmulation | null): void { + if (this.destroyed) return; + const next = emulation ? { ...emulation } : undefined; + if (deviceEmulationEqual(this.deviceEmulation, next)) return; + const touchChanged = this.deviceEmulation?.touch !== next?.touch; + if (this.isAttached()) { + if (next) { + this.applyDeviceEmulation(this.webContents, next); + } else { + this.webContents.disableDeviceEmulation(); + } + if (touchChanged) this.applyTouchEmulation(next?.touch === true); + } + this.deviceEmulation = next; + this.emit(); + } + + private applyDeviceEmulation(wc: WebContents, emulation: BrowserDeviceEmulation): void { + const size = { width: emulation.width, height: emulation.height }; + wc.enableDeviceEmulation({ + screenPosition: emulation.mobile ? "mobile" : "desktop", + screenSize: size, + viewPosition: { x: 0, y: 0 }, + deviceScaleFactor: emulation.deviceScaleFactor, + viewSize: size, + scale: emulation.scale, + }); + } + + private applyTouchEmulation(enabled: boolean): void { + const params: Record = enabled + ? { enabled: true, maxTouchPoints: 5 } + : { enabled: false }; + void this.cdp.send("Emulation.setTouchEmulationEnabled", params).catch(() => {}); + } + clearHistory(): void { if (this.destroyed) return; this.clearNavigationHistory(); @@ -479,10 +606,42 @@ function snapshotsEqual(a: BrowserTabSnapshot, b: BrowserTabSnapshot): boolean { a.canGoBack === b.canGoBack && a.canGoForward === b.canGoForward && a.devToolsOpen === b.devToolsOpen && + a.zoomFactor === b.zoomFactor && + deviceEmulationEqual(a.deviceEmulation, b.deviceEmulation) && a.faviconUrl === b.faviconUrl ); } +function deviceEmulationEqual( + a: BrowserDeviceEmulation | undefined, + b: BrowserDeviceEmulation | undefined, +): boolean { + if (!a || !b) return a === b; + return ( + a.width === b.width && + a.height === b.height && + a.deviceScaleFactor === b.deviceScaleFactor && + a.scale === b.scale && + a.mobile === b.mobile && + a.touch === b.touch && + a.preset === b.preset + ); +} + +function isBrowserFindKeyDown(input: Electron.Input): boolean { + if (input.type !== "keyDown") return false; + return ( + (input.control || input.meta) && !input.shift && !input.alt && input.key.toLowerCase() === "f" + ); +} + +function isBrowserPrintKeyDown(input: Electron.Input): boolean { + if (input.type !== "keyDown") return false; + return ( + (input.control || input.meta) && !input.shift && !input.alt && input.key.toLowerCase() === "p" + ); +} + function isBrowserReloadKeyDown(input: Electron.Input): boolean { if (input.type !== "keyDown") return false; if (input.key === "F5" || input.code === "F5") return true; diff --git a/src/main/browser/WindowsChromiumImportService.test.ts b/src/main/browser/WindowsChromiumImportService.test.ts new file mode 100644 index 000000000..4c4505a53 --- /dev/null +++ b/src/main/browser/WindowsChromiumImportService.test.ts @@ -0,0 +1,403 @@ +import { createCipheriv, createHash, randomBytes } from "node:crypto"; +import { existsSync } from "node:fs"; +import { access, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; +import { basename, dirname, join } from "node:path"; +import { tmpdir } from "node:os"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import type { BrowserCredentialInput } from "./BrowserCredentialStore"; +import { + BROWSER_IMPORT_ERROR_CODES, + WindowsChromiumImportService, + type BrowserImportCookieDetails, + type BrowserImportDatabase, + type BrowserImportDatabaseFactory, +} from "./WindowsChromiumImportService"; + +const browserRoots = { + chrome: join("Google", "Chrome", "User Data"), + edge: join("Microsoft", "Edge", "User Data"), + brave: join("BraveSoftware", "Brave-Browser", "User Data"), + chromium: join("Chromium", "User Data"), +} as const; + +interface FixtureProfileOptions { + browser: keyof typeof browserRoots; + profile?: string; + profileLabel?: string; + passwords?: boolean; + cookies?: boolean; + encryptedKey?: Buffer; + appBound?: boolean; + wal?: boolean; +} + +let fixtureRoot: string; + +beforeEach(async () => { + fixtureRoot = await mkdtemp(join(tmpdir(), "poracode-chromium-import-test-")); +}); + +afterEach(async () => { + await rm(fixtureRoot, { recursive: true, force: true }); +}); + +describe("WindowsChromiumImportService", () => { + it("discovers Chrome, Edge, Brave, and Chromium profiles without exposing paths", async () => { + await Promise.all( + (Object.keys(browserRoots) as Array).map((browser, index) => + createProfile({ + browser, + profile: index === 0 ? "Default" : `Profile ${index}`, + profileLabel: `${browser} profile`, + passwords: true, + cookies: true, + appBound: browser === "chrome", + }), + ), + ); + const { service } = createService({ databaseFactory: emptyDatabaseFactory() }); + + const sources = await service.listSources(); + + expect(sources.map((source) => source.browser).sort()).toEqual([ + "brave", + "chrome", + "chromium", + "edge", + ]); + expect(sources.find((source) => source.browser === "chrome")).toMatchObject({ + profileLabel: "chrome profile", + supportsPasswords: true, + supportsCookies: true, + hasAppBoundData: true, + }); + for (const source of sources) { + expect(source.id).toMatch(/^chromium-(brave|chrome|chromium|edge)-[a-f0-9]{20}$/u); + expect(source.id).not.toContain("Default"); + expect(source).not.toHaveProperty("profilePath"); + } + }); + + it("imports v10/v11 passwords and cookies from read-only WAL snapshots", async () => { + const key = randomBytes(32); + const wrappedKey = Buffer.from("wrapped-chromium-key"); + await createProfile({ + browser: "chrome", + passwords: true, + cookies: true, + encryptedKey: Buffer.concat([Buffer.from("DPAPI"), wrappedKey]), + wal: true, + }); + const loginRows = [ + { + origin_url: "https://example.test/login", + action_url: "https://example.test/session", + signon_realm: "https://example.test/", + username_value: "alice", + password_value: encryptChromiumValue("v10", key, Buffer.from("correct horse")), + blacklisted_by_user: 0, + }, + ]; + const cookieRows = [ + { + host_key: ".example.test", + name: "session", + value: "", + encrypted_value: encryptChromiumValue( + "v11", + key, + Buffer.concat([ + createHash("sha256").update(".example.test").digest(), + Buffer.from("cookie-value"), + ]), + ), + path: "/account", + expires_utc: 11_644_473_600_000_000 + 3_600_000_000, + is_secure: 1, + is_httponly: 1, + samesite: 1, + }, + ]; + const snapshotChecks: boolean[] = []; + const databaseFactory = vi.fn((path, options) => { + expect(options).toEqual({ readonly: true, fileMustExist: true }); + snapshotChecks.push(fileExistsSyncForTest(`${path}-wal`)); + return databaseFor( + basename(path) === "Login Data" ? loginRows : cookieRows, + basename(path) === "Cookies" ? 24 : undefined, + ); + }); + const dpapiDecrypt = vi.fn<(encrypted: Buffer) => Promise>(async (encrypted) => { + expect(encrypted).toEqual(wrappedKey); + return key; + }); + const { service, cookieSet, credentialUpsertMany } = createService({ + databaseFactory, + dpapiDecrypt, + }); + const [source] = await service.listSources(); + + const result = await service.importData({ + sourceId: source!.id, + passwords: true, + cookies: true, + }); + + expect(result).toEqual({ + passwordsImported: 1, + cookiesImported: 1, + passwordsSkipped: 0, + cookiesSkipped: 0, + protectedItemsSkipped: 0, + errors: [], + }); + expect(dpapiDecrypt).toHaveBeenCalledOnce(); + expect(credentialUpsertMany).toHaveBeenCalledWith([ + { + origin: "https://example.test/login", + username: "alice", + password: "correct horse", + source: "Google Chrome — Default", + }, + ]); + expect(cookieSet).toHaveBeenCalledWith({ + url: "https://example.test/account", + name: "session", + value: "cookie-value", + domain: ".example.test", + path: "/account", + secure: true, + httpOnly: true, + sameSite: "lax", + expirationDate: 3600, + }); + expect(snapshotChecks).toEqual([true, true]); + const snapshotParents = new Set(databaseFactory.mock.calls.map(([path]) => dirname(path))); + expect(snapshotParents.size).toBe(1); + for (const directory of snapshotParents) await expectPathMissing(directory); + }); + + it("preserves host-only Chromium cookies without broadening them to subdomains", async () => { + await createProfile({ browser: "chromium", cookies: true }); + const databaseFactory: BrowserImportDatabaseFactory = () => + databaseFor([ + { + host_key: "example.test", + name: "host-only", + value: "cookie-value", + encrypted_value: Buffer.alloc(0), + path: "/", + expires_utc: 0, + is_secure: 1, + is_httponly: 0, + samesite: 1, + }, + ]); + const { service, cookieSet } = createService({ databaseFactory }); + const [source] = await service.listSources(); + + const result = await service.importData({ + sourceId: source!.id, + passwords: false, + cookies: true, + }); + + expect(result.cookiesImported).toBe(1); + expect(cookieSet).toHaveBeenCalledWith({ + url: "https://example.test/", + name: "host-only", + value: "cookie-value", + path: "/", + secure: true, + httpOnly: false, + sameSite: "lax", + }); + }); + + it("skips partitioned Chromium cookies that Electron cannot preserve", async () => { + await createProfile({ browser: "chrome", cookies: true }); + const databaseFactory: BrowserImportDatabaseFactory = (_path, _options) => + databaseFor( + [ + { + host_key: ".example.test", + name: "partitioned", + value: "cookie-value", + encrypted_value: Buffer.alloc(0), + path: "/", + expires_utc: 0, + is_secure: 1, + is_httponly: 0, + samesite: 0, + top_frame_site_key: "https://top-level.test", + }, + ], + 24, + ); + const { service, cookieSet } = createService({ databaseFactory }); + const [source] = await service.listSources(); + + const result = await service.importData({ + sourceId: source!.id, + passwords: false, + cookies: true, + }); + + expect(result.cookiesImported).toBe(0); + expect(result.cookiesSkipped).toBe(1); + expect(result.errors).toEqual([BROWSER_IMPORT_ERROR_CODES.partitionedCookieSkipped]); + expect(cookieSet).not.toHaveBeenCalled(); + }); + + it("counts v20 App-Bound values as protected without invoking DPAPI", async () => { + await createProfile({ + browser: "edge", + passwords: true, + cookies: true, + appBound: true, + }); + const databaseFactory: BrowserImportDatabaseFactory = (path) => + databaseFor( + basename(path) === "Login Data" + ? [ + { + origin_url: "https://protected.test/", + username_value: "user", + password_value: Buffer.concat([Buffer.from("v20"), Buffer.alloc(32, 1)]), + blacklisted_by_user: 0, + }, + ] + : [ + { + host_key: ".protected.test", + name: "session", + value: "", + encrypted_value: Buffer.concat([Buffer.from("v20"), Buffer.alloc(32, 2)]), + path: "/", + expires_utc: 0, + is_secure: 1, + is_httponly: 1, + samesite: -1, + }, + ], + ); + const dpapiDecrypt = vi.fn<(encrypted: Buffer) => Promise>(); + const { service, cookieSet, credentialUpsertMany } = createService({ + databaseFactory, + dpapiDecrypt, + }); + const [source] = await service.listSources(); + + const result = await service.importData({ + sourceId: source!.id, + passwords: true, + cookies: true, + }); + + expect(result).toEqual({ + passwordsImported: 0, + cookiesImported: 0, + passwordsSkipped: 1, + cookiesSkipped: 1, + protectedItemsSkipped: 2, + errors: [BROWSER_IMPORT_ERROR_CODES.appBoundSkipped], + }); + expect(dpapiDecrypt).not.toHaveBeenCalled(); + expect(credentialUpsertMany).not.toHaveBeenCalled(); + expect(cookieSet).not.toHaveBeenCalled(); + }); + + it("rejects path-like source IDs instead of resolving caller-controlled paths", async () => { + await createProfile({ browser: "brave", passwords: true, cookies: true }); + const databaseFactory = vi.fn(); + const { service, cookieSet, credentialUpsertMany } = createService({ databaseFactory }); + + const result = await service.importData({ + sourceId: "../../Google/Chrome/User Data/Default", + passwords: true, + cookies: true, + }); + + expect(result.errors).toEqual([BROWSER_IMPORT_ERROR_CODES.sourceNotFound]); + expect(databaseFactory).not.toHaveBeenCalled(); + expect(cookieSet).not.toHaveBeenCalled(); + expect(credentialUpsertMany).not.toHaveBeenCalled(); + }); +}); + +async function createProfile(options: FixtureProfileOptions): Promise { + const profile = options.profile ?? "Default"; + const userDataPath = join(fixtureRoot, browserRoots[options.browser]); + const profilePath = join(userDataPath, profile); + await mkdir(join(profilePath, "Network"), { recursive: true }); + const localState = { + profile: { info_cache: { [profile]: { name: options.profileLabel ?? profile } } }, + os_crypt: { + ...(options.encryptedKey ? { encrypted_key: options.encryptedKey.toString("base64") } : {}), + ...(options.appBound + ? { app_bound_encrypted_key: Buffer.from("APPBprotected").toString("base64") } + : {}), + }, + }; + await writeFile(join(userDataPath, "Local State"), JSON.stringify(localState)); + if (options.passwords) { + const path = join(profilePath, "Login Data"); + await writeFile(path, "fixture"); + if (options.wal) await writeFile(`${path}-wal`, "wal"); + } + if (options.cookies) { + const path = join(profilePath, "Network", "Cookies"); + await writeFile(path, "fixture"); + if (options.wal) await writeFile(`${path}-wal`, "wal"); + } +} + +function createService(options: { + databaseFactory: BrowserImportDatabaseFactory; + dpapiDecrypt?: (encrypted: Buffer) => Promise; +}) { + const cookieSet = vi.fn<(details: BrowserImportCookieDetails) => Promise>(async () => {}); + const credentialUpsertMany = vi.fn<(inputs: readonly BrowserCredentialInput[]) => unknown>( + (inputs) => ({ saved: inputs.map(() => ({ id: "credential-id" })), failed: 0 }), + ); + const service = new WindowsChromiumImportService( + { cookies: { set: cookieSet } }, + { upsertMany: credentialUpsertMany } as never, + { + localAppData: fixtureRoot, + tempRoot: fixtureRoot, + platform: "win32", + databaseFactory: options.databaseFactory, + ...(options.dpapiDecrypt ? { dpapiDecrypt: options.dpapiDecrypt } : {}), + }, + ); + return { service, cookieSet, credentialUpsertMany }; +} + +function emptyDatabaseFactory(): BrowserImportDatabaseFactory { + return () => databaseFor([]); +} + +function databaseFor(rows: unknown[], version?: number): BrowserImportDatabase { + return { + prepare: (sql) => ({ + all: () => (sql.includes("FROM meta") && version !== undefined ? [{ value: version }] : rows), + }), + close: vi.fn<() => void>(), + }; +} + +function encryptChromiumValue(version: "v10" | "v11", key: Buffer, plaintext: Buffer): Buffer { + const nonce = Buffer.alloc(12, version === "v10" ? 10 : 11); + const cipher = createCipheriv("aes-256-gcm", key, nonce); + const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]); + return Buffer.concat([Buffer.from(version), nonce, ciphertext, cipher.getAuthTag()]); +} + +function fileExistsSyncForTest(path: string): boolean { + return existsSync(path); +} + +async function expectPathMissing(path: string): Promise { + await expect(access(path)).rejects.toMatchObject({ code: "ENOENT" }); +} diff --git a/src/main/browser/WindowsChromiumImportService.ts b/src/main/browser/WindowsChromiumImportService.ts new file mode 100644 index 000000000..7637bef93 --- /dev/null +++ b/src/main/browser/WindowsChromiumImportService.ts @@ -0,0 +1,726 @@ +import { spawn } from "node:child_process"; +import { createDecipheriv, createHash } from "node:crypto"; +import type { Dirent } from "node:fs"; +import { + access, + copyFile, + lstat, + mkdtemp, + readFile, + readdir, + realpath, + rm, +} from "node:fs/promises"; +import { basename, dirname, join, relative, resolve, sep } from "node:path"; +import { tmpdir } from "node:os"; +import Database from "better-sqlite3"; +import type { BrowserImportResult, BrowserImportSourceInfo } from "@/shared/ipc"; +import type { BrowserCredentialInput, BrowserCredentialStore } from "./BrowserCredentialStore"; + +const TEMP_PREFIX = "poracode-browser-import-"; +const DPAPI_PREFIX = Buffer.from("DPAPI"); +const WINDOWS_EPOCH_OFFSET_MICROSECONDS = 11_644_473_600_000_000; +const DPAPI_TIMEOUT_MS = 15_000; +const MAX_DPAPI_OUTPUT_BYTES = 1024 * 1024; + +const BROWSERS = [ + { + id: "chrome", + label: "Google Chrome", + relativeUserDataPath: join("Google", "Chrome", "User Data"), + }, + { + id: "edge", + label: "Microsoft Edge", + relativeUserDataPath: join("Microsoft", "Edge", "User Data"), + }, + { + id: "brave", + label: "Brave", + relativeUserDataPath: join("BraveSoftware", "Brave-Browser", "User Data"), + }, + { + id: "chromium", + label: "Chromium", + relativeUserDataPath: join("Chromium", "User Data"), + }, +] as const; + +type ChromiumBrowserId = BrowserImportSourceInfo["browser"]; + +export interface BrowserImportRequest { + sourceId: string; + passwords: boolean; + cookies: boolean; +} + +export const BROWSER_IMPORT_ERROR_CODES = { + sourceNotFound: "source-not-found", + sourceUnavailable: "source-unavailable", + passwordsUnavailable: "passwords-unavailable", + cookiesUnavailable: "cookies-unavailable", + passwordDatabaseFailed: "password-database-failed", + cookieDatabaseFailed: "cookie-database-failed", + cookieIntegrityFailed: "cookie-integrity-check-failed", + partitionedCookieSkipped: "partitioned-cookie-skipped", + legacyKeyFailed: "legacy-key-decryption-failed", + legacyValueFailed: "legacy-value-decryption-failed", + appBoundSkipped: "app-bound-data-skipped", + passwordWriteFailed: "password-write-failed", + cookieWriteFailed: "cookie-write-failed", +} as const; + +export interface BrowserImportCookieDetails { + url: string; + name: string; + value: string; + domain?: string; + path: string; + secure: boolean; + httpOnly: boolean; + sameSite: "unspecified" | "no_restriction" | "lax" | "strict"; + expirationDate?: number; +} + +export interface BrowserImportCookieSession { + cookies: { + set(details: BrowserImportCookieDetails): Promise; + }; +} + +export interface BrowserImportDatabase { + prepare(sql: string): { all(): unknown[] }; + close(): void; +} + +export type BrowserImportDatabaseFactory = ( + path: string, + options: { readonly: true; fileMustExist: true }, +) => BrowserImportDatabase; + +export type DpapiDecryptor = (encrypted: Buffer) => Promise; + +export interface WindowsChromiumImportServiceOptions { + localAppData?: string; + tempRoot?: string; + platform?: NodeJS.Platform; + dpapiDecrypt?: DpapiDecryptor; + databaseFactory?: BrowserImportDatabaseFactory; +} + +interface DiscoveredSource { + info: BrowserImportSourceInfo; + userDataPath: string; + profilePath: string; + localStatePath: string; + loginDataPath: string; + cookiesPath: string; +} + +interface ChromiumLocalState { + profile?: { info_cache?: Record }; + os_crypt?: { encrypted_key?: string; app_bound_encrypted_key?: string }; +} + +interface ChromiumLoginRow { + origin_url?: unknown; + action_url?: unknown; + signon_realm?: unknown; + username_value?: unknown; + password_value?: unknown; + blacklisted_by_user?: unknown; +} + +interface ChromiumCookieRow { + host_key?: unknown; + name?: unknown; + value?: unknown; + encrypted_value?: unknown; + path?: unknown; + expires_utc?: unknown; + is_secure?: unknown; + is_httponly?: unknown; + samesite?: unknown; + top_frame_site_key?: unknown; +} + +interface ImportContext { + result: BrowserImportResult; + legacyKey: Promise | null; +} + +/** + * Imports legacy Windows Chromium browser data without accepting filesystem + * paths from IPC callers. App-Bound (v20) values are counted and skipped. + */ +export class WindowsChromiumImportService { + private readonly sources = new Map(); + private readonly localAppData: string | undefined; + private readonly tempRoot: string; + private readonly platform: NodeJS.Platform; + private readonly dpapiDecrypt: DpapiDecryptor; + private readonly databaseFactory: BrowserImportDatabaseFactory; + + constructor( + private readonly session: BrowserImportCookieSession, + private readonly credentialStore: Pick, + options: WindowsChromiumImportServiceOptions = {}, + ) { + this.localAppData = options.localAppData ?? process.env.LOCALAPPDATA; + this.tempRoot = resolve(options.tempRoot ?? tmpdir()); + this.platform = options.platform ?? process.platform; + this.dpapiDecrypt = options.dpapiDecrypt ?? decryptDpapiWithPowerShell; + this.databaseFactory = options.databaseFactory ?? defaultDatabaseFactory; + } + + async listSources(): Promise { + await this.discover(); + return [...this.sources.values()] + .map((source) => ({ ...source.info })) + .sort( + (a, b) => + a.browserLabel.localeCompare(b.browserLabel) || + a.profileLabel.localeCompare(b.profileLabel), + ); + } + + async importData(request: BrowserImportRequest): Promise { + const context: ImportContext = { + result: emptyResult(), + legacyKey: null, + }; + if (this.sources.size === 0) await this.discover(); + const source = this.sources.get(request.sourceId); + if (!source) { + addError(context, BROWSER_IMPORT_ERROR_CODES.sourceNotFound); + return context.result; + } + if (!(await this.isSourceStillValid(source))) { + this.sources.delete(request.sourceId); + addError(context, BROWSER_IMPORT_ERROR_CODES.sourceUnavailable); + return context.result; + } + + const tempDirectory = await mkdtemp(join(this.tempRoot, TEMP_PREFIX)); + try { + const localState = await readLocalState(source.localStatePath); + const getLegacyKey = (): Promise => { + context.legacyKey ??= this.readLegacyKey(localState, context); + return context.legacyKey; + }; + + if (request.passwords) { + if (!source.info.supportsPasswords) { + addError(context, BROWSER_IMPORT_ERROR_CODES.passwordsUnavailable); + } else { + await this.importPasswords(source, tempDirectory, getLegacyKey, context); + } + } + if (request.cookies) { + if (!source.info.supportsCookies) { + addError(context, BROWSER_IMPORT_ERROR_CODES.cookiesUnavailable); + } else { + await this.importCookies(source, tempDirectory, getLegacyKey, context); + } + } + return context.result; + } finally { + await removeImportTempDirectory(this.tempRoot, tempDirectory); + } + } + + private async discover(): Promise { + this.sources.clear(); + if (this.platform !== "win32" || !this.localAppData) return; + for (const browser of BROWSERS) { + const userDataPath = resolve(this.localAppData, browser.relativeUserDataPath); + const localStatePath = join(userDataPath, "Local State"); + const localState = await readLocalState(localStatePath); + let entries: Dirent[]; + try { + entries = await readdir(userDataPath, { withFileTypes: true, encoding: "utf8" }); + } catch { + continue; + } + let realUserDataPath: string; + try { + realUserDataPath = await realpath(userDataPath); + } catch { + continue; + } + for (const entry of entries) { + if (!entry.isDirectory() || !isChromiumProfileDirectory(entry.name)) continue; + const profilePath = join(userDataPath, entry.name); + if (!(await isSafeDiscoveredDirectory(realUserDataPath, profilePath))) continue; + const loginDataPath = join(profilePath, "Login Data"); + const networkCookiesPath = join(profilePath, "Network", "Cookies"); + const legacyCookiesPath = join(profilePath, "Cookies"); + const supportsPasswords = await fileExists(loginDataPath); + const cookiesPath = (await fileExists(networkCookiesPath)) + ? networkCookiesPath + : legacyCookiesPath; + const supportsCookies = await fileExists(cookiesPath); + if (!supportsPasswords && !supportsCookies) continue; + const id = sourceId(browser.id, profilePath); + const info: BrowserImportSourceInfo = { + id, + browser: browser.id, + browserLabel: browser.label, + profileLabel: localState.profile?.info_cache?.[entry.name]?.name || entry.name, + supportsPasswords, + supportsCookies, + hasAppBoundData: !!localState.os_crypt?.app_bound_encrypted_key, + }; + this.sources.set(id, { + info, + userDataPath, + profilePath, + localStatePath, + loginDataPath, + cookiesPath, + }); + } + } + } + + private async isSourceStillValid(source: DiscoveredSource): Promise { + try { + const realUserDataPath = await realpath(source.userDataPath); + return await isSafeDiscoveredDirectory(realUserDataPath, source.profilePath); + } catch { + return false; + } + } + + private async readLegacyKey( + localState: ChromiumLocalState, + context: ImportContext, + ): Promise { + const encoded = localState.os_crypt?.encrypted_key; + if (!encoded) { + addError(context, BROWSER_IMPORT_ERROR_CODES.legacyKeyFailed); + return null; + } + try { + const wrapped = Buffer.from(encoded, "base64"); + if (!wrapped.subarray(0, DPAPI_PREFIX.length).equals(DPAPI_PREFIX)) { + throw new Error("Unexpected Chromium encrypted-key format"); + } + return await this.dpapiDecrypt(wrapped.subarray(DPAPI_PREFIX.length)); + } catch { + addError(context, BROWSER_IMPORT_ERROR_CODES.legacyKeyFailed); + return null; + } + } + + private async importPasswords( + source: DiscoveredSource, + tempDirectory: string, + getLegacyKey: () => Promise, + context: ImportContext, + ): Promise { + const snapshotPath = join(tempDirectory, "Login Data"); + try { + await snapshotDatabase(source.loginDataPath, snapshotPath); + await withReadOnlyDatabase(this.databaseFactory, snapshotPath, async (database) => { + const rows = database + .prepare( + "SELECT origin_url, action_url, signon_realm, username_value, password_value, blacklisted_by_user FROM logins", + ) + .all() as ChromiumLoginRow[]; + const credentials: BrowserCredentialInput[] = []; + for (const row of rows) { + if (toBoolean(row.blacklisted_by_user)) continue; + const encrypted = toBuffer(row.password_value); + const decrypted = await this.decryptValue(encrypted, getLegacyKey, context); + if (decrypted.kind === "protected") { + context.result.passwordsSkipped += 1; + context.result.protectedItemsSkipped += 1; + continue; + } + if (decrypted.kind === "failed" || decrypted.value.length === 0) { + context.result.passwordsSkipped += 1; + continue; + } + const origin = firstString(row.origin_url, row.action_url, row.signon_realm); + if (!origin) { + context.result.passwordsSkipped += 1; + continue; + } + credentials.push({ + origin, + username: stringValue(row.username_value), + password: decrypted.value.toString("utf8"), + source: `${source.info.browserLabel} — ${source.info.profileLabel}`, + }); + } + if (credentials.length === 0) return; + try { + const batch = this.credentialStore.upsertMany(credentials); + context.result.passwordsImported += batch.saved.length; + context.result.passwordsSkipped += batch.failed; + if (batch.failed > 0) { + addError(context, BROWSER_IMPORT_ERROR_CODES.passwordWriteFailed); + } + } catch { + context.result.passwordsSkipped += credentials.length; + addError(context, BROWSER_IMPORT_ERROR_CODES.passwordWriteFailed); + } + }); + } catch { + addError(context, BROWSER_IMPORT_ERROR_CODES.passwordDatabaseFailed); + } + } + + private async importCookies( + source: DiscoveredSource, + tempDirectory: string, + getLegacyKey: () => Promise, + context: ImportContext, + ): Promise { + const snapshotPath = join(tempDirectory, "Cookies"); + try { + await snapshotDatabase(source.cookiesPath, snapshotPath); + await withReadOnlyDatabase(this.databaseFactory, snapshotPath, async (database) => { + const databaseVersion = readCookieDatabaseVersion(database); + const partitionKeyColumn = databaseVersion >= 15 ? ", top_frame_site_key" : ""; + const rows = database + .prepare( + `SELECT host_key, name, value, encrypted_value, path, expires_utc, is_secure, is_httponly, samesite${partitionKeyColumn} FROM cookies`, + ) + .all() as ChromiumCookieRow[]; + for (const row of rows) { + if (stringValue(row.top_frame_site_key)) { + context.result.cookiesSkipped += 1; + addError(context, BROWSER_IMPORT_ERROR_CODES.partitionedCookieSkipped); + continue; + } + const hostKey = stringValue(row.host_key); + const host = hostKey.replace(/^\./u, ""); + if (!host || !isValidCookieHost(host)) { + context.result.cookiesSkipped += 1; + continue; + } + const plaintext = stringValue(row.value); + let value = plaintext; + if (!plaintext) { + const decrypted = await this.decryptValue( + toBuffer(row.encrypted_value), + getLegacyKey, + context, + ); + if (decrypted.kind === "protected") { + context.result.cookiesSkipped += 1; + context.result.protectedItemsSkipped += 1; + continue; + } + if (decrypted.kind === "failed") { + context.result.cookiesSkipped += 1; + continue; + } + const cookieValue = decodeCookieValue(decrypted.value, hostKey, databaseVersion); + if (!cookieValue) { + context.result.cookiesSkipped += 1; + addError(context, BROWSER_IMPORT_ERROR_CODES.cookieIntegrityFailed); + continue; + } + value = cookieValue.toString("utf8"); + } + const secure = toBoolean(row.is_secure); + const path = normalizeCookiePath(stringValue(row.path)); + const expirationDate = chromiumTimeToUnixSeconds(row.expires_utc); + const details: BrowserImportCookieDetails = { + url: `${secure ? "https" : "http"}://${host}${path}`, + name: stringValue(row.name), + value, + ...(hostKey.startsWith(".") ? { domain: hostKey } : {}), + path, + secure, + httpOnly: toBoolean(row.is_httponly), + sameSite: chromiumSameSite(row.samesite), + ...(expirationDate !== undefined ? { expirationDate } : {}), + }; + try { + await this.session.cookies.set(details); + context.result.cookiesImported += 1; + } catch { + context.result.cookiesSkipped += 1; + addError(context, BROWSER_IMPORT_ERROR_CODES.cookieWriteFailed); + } + } + }); + } catch { + addError(context, BROWSER_IMPORT_ERROR_CODES.cookieDatabaseFailed); + } + } + + private async decryptValue( + encrypted: Buffer, + getLegacyKey: () => Promise, + context: ImportContext, + ): Promise<{ kind: "ok"; value: Buffer } | { kind: "protected" } | { kind: "failed" }> { + if (encrypted.subarray(0, 3).toString("ascii") === "v20") { + addError(context, BROWSER_IMPORT_ERROR_CODES.appBoundSkipped); + return { kind: "protected" }; + } + const version = encrypted.subarray(0, 3).toString("ascii"); + try { + if (version === "v10" || version === "v11") { + const key = await getLegacyKey(); + if (!key) return { kind: "failed" }; + return { kind: "ok", value: decryptAesGcm(encrypted.subarray(3), key) }; + } + if (encrypted.length === 0) return { kind: "ok", value: Buffer.alloc(0) }; + return { kind: "ok", value: await this.dpapiDecrypt(encrypted) }; + } catch { + addError(context, BROWSER_IMPORT_ERROR_CODES.legacyValueFailed); + return { kind: "failed" }; + } + } +} + +/** Current-user DPAPI only. It deliberately does not elevate or unwrap v20 data. */ +export function decryptDpapiWithPowerShell(encrypted: Buffer): Promise { + if (process.platform !== "win32") { + return Promise.reject(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed)); + } + const script = [ + "$ErrorActionPreference = 'Stop'", + "Add-Type -AssemblyName System.Security", + "$encoded = [Console]::In.ReadToEnd().Trim()", + "$encrypted = [Convert]::FromBase64String($encoded)", + "$plain = [Security.Cryptography.ProtectedData]::Unprotect($encrypted, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)", + "[Console]::Out.Write([Convert]::ToBase64String($plain))", + ].join("; "); + return new Promise((resolvePromise, rejectPromise) => { + const child = spawn( + "powershell.exe", + ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script], + { windowsHide: true, stdio: ["pipe", "pipe", "ignore"] }, + ); + const chunks: Buffer[] = []; + let outputBytes = 0; + let settled = false; + const finish = (error?: Error, value?: Buffer): void => { + if (settled) return; + settled = true; + clearTimeout(timer); + if (error) rejectPromise(error); + else resolvePromise(value ?? Buffer.alloc(0)); + }; + const timer = setTimeout(() => { + child.kill(); + finish(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed)); + }, DPAPI_TIMEOUT_MS); + child.stdout.on("data", (chunk: Buffer) => { + outputBytes += chunk.length; + if (outputBytes > MAX_DPAPI_OUTPUT_BYTES) { + child.kill(); + finish(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed)); + return; + } + chunks.push(chunk); + }); + child.once("error", () => finish(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed))); + child.once("close", (code) => { + if (code !== 0) { + finish(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed)); + return; + } + const encoded = Buffer.concat(chunks).toString("ascii").trim(); + if (!/^[A-Za-z0-9+/]*={0,2}$/u.test(encoded)) { + finish(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed)); + return; + } + finish(undefined, Buffer.from(encoded, "base64")); + }); + child.stdin.once("error", () => + finish(new Error(BROWSER_IMPORT_ERROR_CODES.legacyValueFailed)), + ); + child.stdin.end(encrypted.toString("base64")); + }); +} + +const defaultDatabaseFactory: BrowserImportDatabaseFactory = (path, options) => + new Database(path, options) as unknown as BrowserImportDatabase; + +async function withReadOnlyDatabase( + factory: BrowserImportDatabaseFactory, + path: string, + operation: (database: BrowserImportDatabase) => Promise, +): Promise { + const database = factory(path, { readonly: true, fileMustExist: true }); + try { + await operation(database); + } finally { + database.close(); + } +} + +async function snapshotDatabase(source: string, target: string): Promise { + await copyFile(source, target); + await copyIfPresent(`${source}-wal`, `${target}-wal`); + await copyIfPresent(`${source}-shm`, `${target}-shm`); +} + +async function copyIfPresent(source: string, target: string): Promise { + try { + await copyFile(source, target); + } catch (error) { + if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; + } +} + +async function removeImportTempDirectory(tempRoot: string, directory: string): Promise { + const resolvedRoot = resolve(tempRoot); + const resolvedDirectory = resolve(directory); + if ( + dirname(resolvedDirectory) !== resolvedRoot || + !basename(resolvedDirectory).startsWith(TEMP_PREFIX) + ) { + throw new Error("Refusing to remove an unexpected browser-import directory"); + } + await rm(resolvedDirectory, { recursive: true, force: true }); +} + +async function readLocalState(path: string): Promise { + try { + return JSON.parse(await readFile(path, "utf8")) as ChromiumLocalState; + } catch { + return {}; + } +} + +async function fileExists(path: string): Promise { + try { + await access(path); + return true; + } catch { + return false; + } +} + +async function isSafeDiscoveredDirectory( + realUserDataPath: string, + profilePath: string, +): Promise { + try { + const stats = await lstat(profilePath); + if (!stats.isDirectory() || stats.isSymbolicLink()) return false; + const realProfilePath = await realpath(profilePath); + return isPathInside(realUserDataPath, realProfilePath); + } catch { + return false; + } +} + +function isPathInside(parent: string, child: string): boolean { + const childRelative = relative(resolve(parent), resolve(child)); + return childRelative !== "" && childRelative !== ".." && !childRelative.startsWith(`..${sep}`); +} + +function isChromiumProfileDirectory(name: string): boolean { + return name === "Default" || /^Profile \d+$/u.test(name); +} + +function sourceId(browser: ChromiumBrowserId, profilePath: string): string { + const digest = createHash("sha256").update(resolve(profilePath).toLowerCase()).digest("hex"); + return `chromium-${browser}-${digest.slice(0, 20)}`; +} + +function decryptAesGcm(payload: Buffer, key: Buffer): Buffer { + if (payload.length < 12 + 16) throw new Error("Invalid Chromium AES-GCM payload"); + const nonce = payload.subarray(0, 12); + const ciphertextAndTag = payload.subarray(12); + const tag = ciphertextAndTag.subarray(ciphertextAndTag.length - 16); + const ciphertext = ciphertextAndTag.subarray(0, ciphertextAndTag.length - 16); + const decipher = createDecipheriv("aes-256-gcm", key, nonce); + decipher.setAuthTag(tag); + return Buffer.concat([decipher.update(ciphertext), decipher.final()]); +} + +function readCookieDatabaseVersion(database: BrowserImportDatabase): number { + try { + const [row] = database + .prepare("SELECT value FROM meta WHERE key = 'version' LIMIT 1") + .all() as Array<{ + value?: unknown; + }>; + const version = Number(row?.value); + return Number.isInteger(version) && version >= 0 ? version : 0; + } catch { + return 0; + } +} + +function decodeCookieValue(value: Buffer, hostKey: string, databaseVersion: number): Buffer | null { + const hostDigest = createHash("sha256").update(hostKey).digest(); + const hasHostDigest = + value.length >= hostDigest.length && value.subarray(0, hostDigest.length).equals(hostDigest); + if (hasHostDigest) return value.subarray(hostDigest.length); + return databaseVersion >= 24 ? null : value; +} + +function toBuffer(value: unknown): Buffer { + if (Buffer.isBuffer(value)) return value; + if (value instanceof Uint8Array) return Buffer.from(value); + return Buffer.alloc(0); +} + +function firstString(...values: unknown[]): string | undefined { + for (const value of values) { + if (typeof value === "string" && value.length > 0) return value; + } + return undefined; +} + +function stringValue(value: unknown): string { + return typeof value === "string" ? value : ""; +} + +function toBoolean(value: unknown): boolean { + return value === true || value === 1; +} + +function normalizeCookiePath(value: string): string { + return value.startsWith("/") ? value : "/"; +} + +function isValidCookieHost(value: string): boolean { + if (value.includes("/") || value.includes("\\") || value.includes("://")) return false; + try { + return new URL(`https://${value}/`).hostname === value; + } catch { + return false; + } +} + +function chromiumSameSite(value: unknown): BrowserImportCookieDetails["sameSite"] { + if (value === 0) return "no_restriction"; + if (value === 1) return "lax"; + if (value === 2) return "strict"; + return "unspecified"; +} + +function chromiumTimeToUnixSeconds(value: unknown): number | undefined { + const microseconds = typeof value === "number" ? value : Number(value); + if (!Number.isFinite(microseconds) || microseconds <= WINDOWS_EPOCH_OFFSET_MICROSECONDS) { + return undefined; + } + return (microseconds - WINDOWS_EPOCH_OFFSET_MICROSECONDS) / 1_000_000; +} + +function emptyResult(): BrowserImportResult { + return { + passwordsImported: 0, + cookiesImported: 0, + passwordsSkipped: 0, + cookiesSkipped: 0, + protectedItemsSkipped: 0, + errors: [], + }; +} + +function addError(context: ImportContext, code: string): void { + if (!context.result.errors.includes(code)) context.result.errors.push(code); +} diff --git a/src/main/ipc/localHandlers.ts b/src/main/ipc/localHandlers.ts index 198ce25ba..1a1f6956b 100644 --- a/src/main/ipc/localHandlers.ts +++ b/src/main/ipc/localHandlers.ts @@ -444,6 +444,8 @@ export function createLocalIpcHandlers( ...(payload.url !== undefined ? { url: payload.url } : {}), ...(payload.activate !== undefined ? { activate: payload.activate } : {}), }), + browserOpenInternalPage: ({ page }) => + requireBrowserPanel(options.getBrowserPanelManager).openInternalPage(page), browserCloseTab: ({ tabId }) => requireBrowserPanel(options.getBrowserPanelManager).closeTab(tabId), browserActivateTab: ({ tabId }) => { @@ -479,6 +481,23 @@ export function createLocalIpcHandlers( requireBrowserPanel(options.getBrowserPanelManager).hardReload(tabId), browserToggleDevTools: ({ tabId }) => requireBrowserPanel(options.getBrowserPanelManager).toggleDevTools(tabId), + browserFindInPage: ({ tabId, text, forward, findNext, matchCase }) => { + requireBrowserPanel(options.getBrowserPanelManager).findInPage(tabId, text, { + forward, + findNext, + matchCase, + }); + }, + browserStopFindInPage: ({ tabId, action }) => { + requireBrowserPanel(options.getBrowserPanelManager).stopFindInPage(tabId, action); + }, + browserPrint: ({ tabId }) => requireBrowserPanel(options.getBrowserPanelManager).print(tabId), + browserSetZoomFactor: ({ tabId, zoomFactor }) => { + requireBrowserPanel(options.getBrowserPanelManager).setZoomFactor(tabId, zoomFactor); + }, + browserSetDeviceEmulation: ({ tabId, emulation }) => { + requireBrowserPanel(options.getBrowserPanelManager).setDeviceEmulation(tabId, emulation); + }, browserClearHistory: ({ tabId }) => requireBrowserPanel(options.getBrowserPanelManager).clearHistory(tabId), browserClearCookies: ({ tabId }) => @@ -522,6 +541,32 @@ export function createLocalIpcHandlers( }, browserRecentHistory: ({ limit }) => requireBrowserPanel(options.getBrowserPanelManager).recentHistory(limit), + browserGetDownloads: () => requireBrowserPanel(options.getBrowserPanelManager).getDownloads(), + browserDownloadAction: ({ id, action }) => + requireBrowserPanel(options.getBrowserPanelManager).downloadAction(id, action), + browserListCredentials: () => + requireBrowserPanel(options.getBrowserPanelManager).listCredentials(), + browserGetCredentialPassword: ({ id }) => { + const password = requireBrowserPanel(options.getBrowserPanelManager).getCredentialPassword( + id, + ); + if (password === null) throw new Error("Browser credential not found"); + return { password }; + }, + browserUpsertCredential: ({ id, origin, username, password }) => + requireBrowserPanel(options.getBrowserPanelManager).upsertCredential({ + ...(id !== undefined ? { id } : {}), + origin, + username, + password, + }), + browserDeleteCredential: ({ id }) => { + requireBrowserPanel(options.getBrowserPanelManager).deleteCredential(id); + }, + browserListImportSources: () => + requireBrowserPanel(options.getBrowserPanelManager).listImportSources(), + browserImportData: (payload) => + requireBrowserPanel(options.getBrowserPanelManager).importBrowserData(payload), browserExtractToWindow: () => { options.extractBrowserToWindow(); }, diff --git a/src/main/main.ts b/src/main/main.ts index 81152f4d3..10a8bdb3d 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -580,7 +580,8 @@ if (!hasSingleInstanceLock) { installLocalFileProtocolHandler(); installPickerProtocolHandler(); // Keep the pre-rebrand partition so browser cookies and sign-ins survive. - electronSession.fromPartition("persist:lightcode-browser").setUserAgent(browserUserAgent); + const browserSession = electronSession.fromPartition("persist:lightcode-browser"); + browserSession.setUserAgent(browserUserAgent); const paths = requirePoracodePaths(); const initialSettings = readSharedSettingsFile(paths.settingsPath); @@ -738,6 +739,7 @@ if (!hasSingleInstanceLock) { browserPanelManager = new BrowserPanelManager(paths, browserUserAgent, { isExtracted: () => browserExtractWindow !== null && !browserExtractWindow.isDestroyed(), focusExtractedWindow: focusBrowserExtractWindow, + browserSession, }); browserMcpIngress = new BrowserMcpIngress(); browserMcpIngress.setManagerAccessor(() => browserPanelManager); diff --git a/src/renderer/components/find/findController.test.ts b/src/renderer/components/find/findController.test.ts index bf1287b4c..e14592c20 100644 --- a/src/renderer/components/find/findController.test.ts +++ b/src/renderer/components/find/findController.test.ts @@ -1,8 +1,10 @@ import { afterEach, describe, expect, it } from "vitest"; import { useCommandPaletteStore } from "@/renderer/commands/commandPaletteStore"; import { useAppStore } from "@/renderer/state/appStore"; +import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; import { usePanelStore } from "@/renderer/state/panelStore"; -import { resolveFindTarget } from "./findController"; +import { openFindForActiveSurface, resolveFindTarget } from "./findController"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; function resetFindRoutingState(): void { document.body.innerHTML = ""; @@ -17,6 +19,8 @@ function resetFindRoutingState(): void { cloneProjectModalOpen: false, }); useAppStore.setState({ view: { kind: "home" } }); + useBrowserPanelStore.setState({ tabs: [], activeTabId: null }); + useBrowserFindStore.setState({ tabId: null }); } describe("resolveFindTarget", () => { @@ -30,12 +34,35 @@ describe("resolveFindTarget", () => { expect(resolveFindTarget()).toBe("chat"); }); - it("does not route browser chrome focus to chat find", () => { + it("routes browser chrome focus to browser find", () => { useAppStore.setState({ view: { kind: "thread", panes: ["thread-1"] } }); document.body.innerHTML = `
`; document.getElementById("address")?.focus(); - expect(resolveFindTarget()).toBeNull(); + expect(resolveFindTarget()).toBe("browser"); + }); + + it("does not open browser find on an app-owned internal page", () => { + document.body.innerHTML = `
`; + document.getElementById("address")?.focus(); + useBrowserPanelStore.setState({ + activeTabId: "tab-1", + tabs: [ + { + tabId: "tab-1", + url: "chrome://downloads/", + title: "Download history", + loading: false, + canGoBack: false, + canGoForward: false, + internalPage: "downloads", + }, + ], + }); + + openFindForActiveSurface(); + + expect(useBrowserFindStore.getState().tabId).toBeNull(); }); it("lets the command palette keep Ctrl+F", () => { diff --git a/src/renderer/components/find/findController.ts b/src/renderer/components/find/findController.ts index b9b3ff259..3c982323b 100644 --- a/src/renderer/components/find/findController.ts +++ b/src/renderer/components/find/findController.ts @@ -1,4 +1,6 @@ import { useAppStore } from "@/renderer/state/appStore"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; +import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; import { useChatFindStore } from "@/renderer/state/chatFindStore"; import { useFileEditorStore } from "@/renderer/state/fileEditorStore"; import { useFindFocusStore } from "@/renderer/state/findFocusStore"; @@ -9,7 +11,7 @@ import { isEditorFocusElement, isTerminalFocusElement } from "@/renderer/command import { openEditorFind } from "./editorFindBridge"; import { openTerminalFind } from "./terminalFindBridge"; -export type FindTarget = "editor" | "terminal" | "settings" | "git" | "tree" | "chat"; +export type FindTarget = "browser" | "editor" | "terminal" | "settings" | "git" | "tree" | "chat"; /** * Decide which surface a Find (Ctrl+F) press should target. Focus wins first @@ -28,7 +30,7 @@ export function resolveFindTarget(): FindTarget | null { if (scope === "git" || scope === "settings" || scope === "tree" || scope === "chat") { return scope; } - if (element?.closest("[data-poracode-browser]")) return null; + if (element?.closest("[data-poracode-browser]")) return "browser"; const panel = usePanelStore.getState(); // Blocking modals trap their own input — leave Ctrl+F to them. @@ -52,6 +54,12 @@ export function openFindForActiveSurface(): void { const target = resolveFindTarget(); if (!target) return; switch (target) { + case "browser": { + const browser = useBrowserPanelStore.getState(); + const tab = browser.tabs.find((candidate) => candidate.tabId === browser.activeTabId); + if (tab && !tab.internalPage) useBrowserFindStore.getState().open(tab.tabId); + return; + } case "editor": openEditorFind(); return; diff --git a/src/renderer/locales/de/messages.po b/src/renderer/locales/de/messages.po index 55c0738d3..7986046f5 100644 --- a/src/renderer/locales/de/messages.po +++ b/src/renderer/locales/de/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30 T" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7 T" @@ -618,6 +622,10 @@ msgstr "Hinzufügen" msgid "Add a local project" msgstr "Lokales Projekt hinzufügen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Passwort hinzufügen oder eines aus einem anderen Browser importieren." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Modell hinzufügen" msgid "Add one manually or import from another agent." msgstr "Fügen Sie einen manuell hinzu oder importieren Sie ihn aus einem anderen Agenten." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Passwort hinzufügen" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Muster hinzufügen" @@ -751,6 +763,10 @@ msgstr "Zu Favoriten hinzufügen" msgid "Add to Home Screen" msgstr "Zum Home-Bildschirm hinzufügen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Erweitert" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Eine benutzerdefinierte Basis-URL bekanntgeben, z. B. für einen Reverse-Proxy oder Tunnel. Für automatisch leer lassen." @@ -1301,11 +1317,12 @@ msgstr "blockiert:" msgid "Bold" msgstr "Fett" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Diese Seite als Lesezeichen speichern" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Lesezeichen" @@ -1342,6 +1359,10 @@ msgstr "Zurück ins Panel holen" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Holen Sie ihn zurück in dieses Panel oder wechseln Sie zum Fenster, in dem er läuft." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Gespeicherte Passwörter und Cookies aus einem installierten Browser übernehmen." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Durchsuchen" @@ -1387,7 +1408,7 @@ msgstr "Browser-MCP für OpenCode aktiviert" msgid "Browser MCP enabled for this thread" msgstr "Browser-MCP für diesen Thread aktiviert" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Browser-Menü" @@ -1487,6 +1508,8 @@ msgstr "Ports konnten nicht geladen werden" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Ports konnten nicht geladen werden" msgid "Cancel" msgstr "Abbrechen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Download abbrechen" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Neues Claude-Profil abbrechen" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "abgebrochen" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Abgebrochen" @@ -1682,6 +1710,10 @@ msgstr "Übergeordneten Ordner auswählen" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Eine MCP-Server-Konfigurationsdatei auswählen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Daten für die Übernahme in den integrierten Browser auswählen." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Wählen Sie aus, wie Sie sich für {env} anmelden möchten." @@ -1754,22 +1786,34 @@ msgstr "Claude-Profil entfernt." msgid "Cleanup script" msgstr "Bereinigungsskript" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Browserdaten löschen" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Browserverlauf löschen" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Browserverlauf löschen" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Cache leeren" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "Cache leeren" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Cookies löschen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Cookies löschen" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "Composer schließen" msgid "Close connection actions" msgstr "Verbindungsaktionen schließen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Geräteleiste schließen" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Editor schließen" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "abgeschlossen" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Abgeschlossen" @@ -2401,6 +2450,10 @@ msgstr "Steuert den gekoppelten Desktop, während der Agent klickt oder tippt" msgid "Conversation" msgstr "Gespräch" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookies" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Alle Lightcode-Daten in Poracode kopieren. Poracode wird neu gestartet u msgid "Copy code" msgstr "Code kopieren" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Aktuelle URL kopieren" @@ -2479,6 +2532,10 @@ msgstr "Kopplungslink kopieren" msgid "Copy pairing token" msgstr "Kopplungstoken kopieren" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Passwort kopieren" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Pfad kopieren" @@ -2807,6 +2864,7 @@ msgstr "Standardmäßiges Entfernen von Threads" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Datei löschen" msgid "Delete permanently" msgstr "Dauerhaft löschen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Gespeichertes Passwort löschen" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Gespeichertes Passwort löschen?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Zeitplan löschen" @@ -2998,6 +3064,10 @@ msgstr "Dev-Server, die auf dem localhost Ihres Desktops lauschen." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Überschreibungen nur für die Entwicklung. Nur im PORACODE DEV-Build sichtbar." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Gerätevoreinstellung" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Von der Composer-Spracheingabetaste verwendetes Gerät." msgid "Devices can pair while this desktop is reachable." msgstr "Geräte können gekoppelt werden, solange dieser Desktop erreichbar ist." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Abmessungen:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Direkte Verbindung erforderlich" @@ -3164,10 +3238,27 @@ msgstr "Fertig" msgid "Done · Waiting for your input" msgstr "Fertig · Warten auf Ihre Eingabe" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Download fehlgeschlagen" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Downloadverlauf" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Bild herunterladen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Downloadfortschritt" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Wird heruntergeladen" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Sprachmodell wird heruntergeladen {0}%" msgid "Downloading voice model..." msgstr "Sprachmodell wird heruntergeladen..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Downloads" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Downloads aus dem integrierten Browser werden in diesem Verlauf gespeichert." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Datei bearbeiten" msgid "Edit MCP server" msgstr "MCP-Server bearbeiten" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Passwort bearbeiten" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Profil bearbeiten" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Gespeichertes Passwort bearbeiten" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Dateien für {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Dateien, die mit diesen Globs übereinstimmen, werden bei der @file-Erwähnungssuche ausgeblendet." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Heruntergeladene Dateien werden hier angezeigt" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Nach Projekt filtern" @@ -3713,6 +3824,11 @@ msgstr "Im Chat suchen" msgid "Find in diff" msgstr "Im Diff suchen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Auf Seite suchen" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Im Terminal suchen" @@ -3877,6 +3993,10 @@ msgstr "Häufigkeit" msgid "Friday at 4:00 PM" msgstr "Freitag um 16:00 Uhr" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Von" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Die Seitenleiste mit dem Unschärfe-Material des Systems (Vibrancy) mattieren, angelehnt an aktuelle macOS-Versionen. Wo nicht unterstützt, wird auf eine durchscheinende Tönung zurückgegriffen." @@ -4086,7 +4206,7 @@ msgstr "handle" msgid "Handle" msgstr "Handle" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Hart neu laden" @@ -4149,6 +4269,10 @@ msgstr "Blenden Sie Modelle, die Sie nicht verwenden, bei allen Anbietern in der msgid "Hide panel" msgstr "Panel ausblenden" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Passwort ausblenden" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Laufzeit-Debug-Panel ausblenden" @@ -4171,7 +4295,7 @@ msgstr "Skills von {0} ausblenden" msgid "Hide terminal" msgstr "Terminal ausblenden" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Verlauf" @@ -4203,10 +4327,18 @@ msgstr "Stündlich" msgid "HTTP (streamable)" msgstr "HTTP (streamfähig)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Ich verstehe, dass geschützte Browserdaten möglicherweise übersprungen werden." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Bild" msgid "Image preview" msgstr "Bildvorschau" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Importieren" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Erneut importieren" @@ -4248,10 +4384,23 @@ msgstr "Erneut importieren" msgid "Import and restart" msgstr "Importieren und neu starten" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Browserdaten importieren" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Importkonflikt" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Cookies importieren" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Cookies und Passwörter importieren" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Externe Agent-Skills importieren" msgid "Import external skills" msgstr "Externe Skills importieren" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Aus deinem Browser importieren" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Lightcode-Daten importieren" @@ -4285,10 +4438,18 @@ msgstr "MCP-Server importieren" msgid "Import method" msgstr "Importmethode" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Passwörter importieren" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Ausgewählte importieren" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Importquelle" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "In {destinationProjectName} importieren" @@ -4316,6 +4477,17 @@ msgstr "{0} Skills importiert." msgid "Imported 1 skill." msgstr "1 Skill importiert." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Importiert aus {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Importierte Passwörter: {0}. Importierte Cookies: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Verbessert" @@ -4469,6 +4641,7 @@ msgstr "Anweisungen, denen Agenten folgen, wenn sie auswählen, an welchen Agent msgid "Interrupt" msgstr "Unterbrechen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Unterbrochen" @@ -4477,6 +4650,26 @@ msgstr "Unterbrochen" msgid "Interrupted: agent session ended before completion." msgstr "Unterbrochen: Agentensitzung wurde vorzeitig beendet." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Kursiv" @@ -4530,6 +4723,14 @@ msgstr "Sprache für KI-generierte Commit-Nachrichten und PR-Zusammenfassungen. msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Sprache, die das Sprachmodell beim Transkribieren des Diktats im Eingabefeld erwarten sollte." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Lokal" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Lokale Änderungen müssen vor dem Pull von {branch} gestasht werden" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Lokaler Passwortschutz" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Längste Serie" msgid "Longest task" msgstr "Längste Aufgabe" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Browserprofile werden gesucht…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Suche nach Dev-Servern…" @@ -4791,6 +5000,10 @@ msgstr "Die Seitenleiste durchscheinend machen — das Unschärfe-Material des S #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Globale und projektbezogene Agent-Skills verwalten, einschließlich der von anderen Anbietern importierten Skills." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Passwörter verwalten" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Remote-Umgebungen verwalten" @@ -5399,8 +5612,8 @@ msgstr "Neuer Zeitplan" #~ msgstr "Neue geplante Aufgabe" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Neuer Tab" @@ -5611,6 +5824,10 @@ msgstr "Für {0} ist kein Unterschied verfügbar." msgid "No diff for {visiblePath}" msgstr "Kein Unterschied für {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Keine Downloads entsprechen der Suche" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "In diesem Geltungsbereich wurden keine externen Skills gefunden." @@ -5630,7 +5847,7 @@ msgstr "Keine Dateien stimmen mit „{0}“ überein." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Keine GitHub-CLI-Konten gefunden. Melden Sie sich mit <0>gh auth login an oder <1>fügen Sie eine Klon-URL ein." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Noch kein Verlauf" @@ -5705,6 +5922,10 @@ msgstr "Keine anderen Agenten installiert" msgid "No paired devices yet." msgstr "Noch keine gekoppelten Geräte." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Keine Passwörter entsprechen der Suche" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Keine Muster." @@ -5771,6 +5992,10 @@ msgstr "Noch keine Ausführungen." msgid "No runtime items yet for this thread." msgstr "Für diesen Thread gibt es noch keine Laufzeitelemente." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Keine gespeicherten Passwörter" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Noch keine Server verbunden." @@ -5808,6 +6033,10 @@ msgstr "Auf diesem Remotecomputer sind keine unterstützten Agenten installiert. msgid "No supported agents detected" msgstr "Keine unterstützten Agenten erkannt" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "Auf diesem Gerät wurden keine unterstützten Browserprofile gefunden." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Kein Thread ausgewählt" @@ -6047,6 +6276,10 @@ msgstr "Öffnen Sie den Konfliktlöser in" msgid "Open dialog" msgstr "Dialog öffnen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Heruntergeladene Datei öffnen" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Datei öffnen" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Passphrase (optional)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Passwort" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Passwort kopiert." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Passwortmanager" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Passwortmanager-Bereich" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Passwörter" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Passwörter und automatisches Ausfüllen" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Passwörter werden im lokalen Anmeldedatenspeicher von Poracode verschlüsselt. Passwortwerte werden nur beim Einblenden, Kopieren oder Bearbeiten angefordert." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Fügen Sie den privaten SSH-Schlüssel ein." msgid "Pause" msgstr "Pausieren" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Download pausieren" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Angehalten" @@ -6476,6 +6741,10 @@ msgstr "Oben anheften" msgid "Pinned" msgstr "Angepinnt" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Frühere Ausführungen" msgid "Previous tab" msgstr "Vorheriger Tab" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Drucken" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Privater Schlüssel" @@ -6730,6 +7003,10 @@ msgstr "Prompts" msgid "Proposed plan" msgstr "Vorgeschlagener Plan" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Geschützte Browserdaten" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Von Poracode für unterstützte Agenten bereitgestellt und verwaltet." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Aktion entfernen" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Lesezeichen entfernen" @@ -7143,6 +7421,10 @@ msgstr "Verbindung entfernen" msgid "Remove environment variable" msgstr "Umgebungsvariable entfernen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Aus Downloadverlauf entfernen" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Aus Favoriten entfernen" @@ -7304,6 +7586,10 @@ msgstr "Mattierung der Seitenleiste auf Standard zurücksetzen" msgid "Reset to default" msgstr "Auf Standard zurücksetzen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Zoom zurücksetzen" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Größe der Browser-Schublade ändern" @@ -7337,11 +7623,27 @@ msgstr "Größe der Teilung ändern" msgid "Resize terminal panel" msgstr "Größe des Terminal-Panels ändern" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Größe des Ansichtsbereichs ändern" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Höhe des Ansichtsbereichs ändern" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Breite des Ansichtsbereichs ändern" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Löst Zusammenführungskonflikte während des Rebasierens oder Zusammenführens." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Responsiv" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Wiederherstellen" @@ -7367,6 +7669,10 @@ msgstr "Thread wiederherstellen" msgid "Resume" msgstr "Fortsetzen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Download fortsetzen" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Im Datei-Explorer anzeigen" msgid "Reveal in file tree" msgstr "Im Dateibaum anzeigen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Passwort einblenden" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Rechtes Panel" msgid "Right-click to switch ring" msgstr "Rechtsklicken, um den Ring zu wechseln" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Ansichtsbereich drehen" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Laufzeit-Debug" msgid "Runtime options" msgstr "Laufzeitoptionen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Agenten suchen..." msgid "Search branches..." msgstr "Branches durchsuchen..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Downloads durchsuchen" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Modelle suchen..." msgid "Search or enter address" msgstr "Adresse suchen oder eingeben" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Passwörter durchsuchen" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Pull Requests durchsuchen" @@ -7980,7 +8307,7 @@ msgstr "Tastenkürzel festlegen" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Zeigen Sie einen projektlosen Home-Bereich für Agentensitzungen auf Bet msgid "Show all" msgstr "Alle anzeigen" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Lesezeichenleiste anzeigen" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Lesezeichenleiste anzeigen" @@ -8054,6 +8381,10 @@ msgstr "Composer anzeigen" msgid "Show context usage details" msgstr "Details zur Kontextverwendung anzeigen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Geräteleiste anzeigen" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Geschätzte Kosten anzeigen" msgid "Show in file explorer" msgstr "Im Datei-Explorer anzeigen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Im Ordner anzeigen" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Übersprungen" msgid "Slash commands" msgstr "Slash-Befehle" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Einige Browserdaten wurden übersprungen. Übersprungene geschützte Elemente: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Einige Prüfungen schlagen fehl oder stehen noch aus." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Einige Chromium-Browser schützen Cookies und Passwörter mit App-Bound-Verschlüsselung. Poracode umgeht diesen Schutz nicht. Daten, die vom Betriebssystem nicht bereitgestellt werden, werden übersprungen." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Einige Anbieterordner konnten nicht gescannt werden. Erfolgreich geladene Skills werden weiterhin angezeigt." @@ -8694,6 +9038,14 @@ msgstr "Unterstützung:" msgid "Supports Fast mode" msgstr "Unterstützt Schnellmodus" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Notizen und Aufgaben tauschen" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "Tailscale-URL" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Screenshot aufnehmen" @@ -9125,6 +9477,11 @@ msgstr "Dieses Remote-Projekt ist nicht verfügbar. Verbinden Sie die Umgebung e msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Dadurch werden spätere Nachrichten entfernt und Dateien wiederhergestellt, wenn ein Prüfpunkt-Snapshot verfügbar ist." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Dadurch wird das gespeicherte Passwort für <0>{0} aus Poracode entfernt." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Dadurch werden der Zeitplan und sein letztes Ergebnis von diesem Gerät entfernt." @@ -9428,14 +9785,34 @@ msgstr "Kopplungstoken kann nicht kopiert werden." msgid "Unable to copy Tailscale URL." msgstr "Tailscale-URL konnte nicht kopiert werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Das Passwort konnte nicht kopiert werden." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Das WSL-Worktree-Verzeichnis „{path}“ kann nicht erstellt werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Das gespeicherte Passwort konnte nicht gelöscht werden." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Der Worktree kann nicht gelöscht werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Das gespeicherte Passwort konnte nicht bearbeitet werden." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Es konnten keine Browserdaten zum Importieren gefunden werden." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Browserdaten konnten nicht importiert werden." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "{0}-Hooks können nicht installiert werden." msgid "Unable to install {0}." msgstr "{0} konnte nicht installiert werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Downloads konnten nicht geladen werden." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Remotezugriff-Kopplung konnte nicht geladen werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Gespeicherte Passwörter konnten nicht geladen werden." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Thread konnte nicht geladen werden." @@ -9515,6 +9900,10 @@ msgstr "Das Home-Verzeichnis für die WSL-Distribution „{distro}“ kann nicht msgid "Unable to restore the SSH connection." msgstr "Die SSH-Verbindung konnte nicht wiederhergestellt werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Das Passwort konnte nicht eingeblendet werden." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Remote-Sitzung konnte nicht widerrufen werden." @@ -9528,6 +9917,10 @@ msgstr "{0}-Anmeldeinformationen können nicht gespeichert werden." msgid "Unable to save Claude {displayLabel} profile." msgstr "Claude-Profil {displayLabel} konnte nicht gespeichert werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Das Passwort konnte nicht gespeichert werden." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "{label} kann nicht gestartet werden." @@ -9595,6 +9988,10 @@ msgstr "Remotezugriff kann nicht aktualisiert werden." msgid "Unable to update Tailscale HTTPS." msgstr "Tailscale HTTPS konnte nicht aktualisiert werden." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Der Download konnte nicht aktualisiert werden." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Die öffentliche URL konnte nicht aktualisiert werden." @@ -9897,6 +10294,10 @@ msgstr "Von {conflict} verwendet" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Benutzername" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Die integrierte Claude-Modellliste wird verwendet." @@ -9970,6 +10371,18 @@ msgstr "Änderungsprotokoll ansehen" msgid "View-only — this connection can't manage projects." msgstr "Nur Lesezugriff – diese Verbindung kann keine Projekte verwalten." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Höhe des Ansichtsbereichs" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Skalierung des Ansichtsbereichs" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Breite des Ansichtsbereichs" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Webserver" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Website" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Website-Ursprung" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Wochentags" @@ -10347,10 +10765,16 @@ msgstr "WSL-Basisordner" msgid "Your name" msgstr "Ihr Name" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Zoom" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Vergrößern" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Verkleinern" diff --git a/src/renderer/locales/en/messages.po b/src/renderer/locales/en/messages.po index e033acf1f..95581eac7 100644 --- a/src/renderer/locales/en/messages.po +++ b/src/renderer/locales/en/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30d" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7d" @@ -618,6 +622,10 @@ msgstr "Add" msgid "Add a local project" msgstr "Add a local project" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Add a password or import one from another browser." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Add model" msgid "Add one manually or import from another agent." msgstr "Add one manually or import from another agent." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Add password" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Add pattern" @@ -751,6 +763,10 @@ msgstr "Add to favorites" msgid "Add to Home Screen" msgstr "Add to Home Screen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Advanced" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." @@ -1301,11 +1317,12 @@ msgstr "blocked:" msgid "Bold" msgstr "Bold" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Bookmark this page" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Bookmarks" @@ -1342,6 +1359,10 @@ msgstr "Bring back to panel" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Bring it back into this panel, or jump to the window it’s running in." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Bring saved passwords and cookies over from an installed browser." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Browse" @@ -1387,7 +1408,7 @@ msgstr "Browser MCP enabled for OpenCode" msgid "Browser MCP enabled for this thread" msgstr "Browser MCP enabled for this thread" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Browser menu" @@ -1487,6 +1508,8 @@ msgstr "Can't load ports" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Can't load ports" msgid "Cancel" msgstr "Cancel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Cancel download" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Cancel new Claude profile" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "cancelled" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Cancelled" @@ -1682,6 +1710,10 @@ msgstr "Choose a parent folder" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Choose an MCP server configuration file" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Choose data to bring over to the built-in browser." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Choose how to sign in for {env}." @@ -1754,21 +1786,33 @@ msgstr "Claude profile removed." msgid "Cleanup script" msgstr "Cleanup script" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Clear browsing data" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Clear browsing history" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Clear Browsing History" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" +msgstr "Clear cache" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" -msgstr "Clear Cache" +#~ msgid "Clear Cache" +#~ msgstr "Clear Cache" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" +msgstr "Clear cookies" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" -msgstr "Clear Cookies" +#~ msgid "Clear Cookies" +#~ msgstr "Clear Cookies" #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx @@ -1859,6 +1903,10 @@ msgstr "Close composer" msgid "Close connection actions" msgstr "Close connection actions" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Close device toolbar" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Close editor" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "completed" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Completed" @@ -2401,6 +2450,10 @@ msgstr "Controls the paired desktop while the agent clicks or types" msgid "Conversation" msgstr "Conversation" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookies" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Copy all Lightcode data into Poracode. Poracode restarts and keeps a com msgid "Copy code" msgstr "Copy code" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Copy Current URL" @@ -2479,6 +2532,10 @@ msgstr "Copy pairing link" msgid "Copy pairing token" msgstr "Copy pairing token" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Copy password" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Copy Path" @@ -2807,6 +2864,7 @@ msgstr "Default thread removal" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Delete file" msgid "Delete permanently" msgstr "Delete permanently" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Delete saved password" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Delete saved password?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Delete schedule" @@ -2998,6 +3064,10 @@ msgstr "Dev servers listening on your desktop's localhost." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Development-only overrides. Only visible in the PORACODE DEV build." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Device preset" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Device used by the composer voice input button." msgid "Devices can pair while this desktop is reachable." msgstr "Devices can pair while this desktop is reachable." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Dimensions:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Direct connection required" @@ -3164,10 +3238,27 @@ msgstr "Done" msgid "Done · Waiting for your input" msgstr "Done · Waiting for your input" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Download failed" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Download history" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Download image" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Download progress" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Downloading" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Downloading voice model {0}%" msgid "Downloading voice model..." msgstr "Downloading voice model..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Downloads" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Downloads from the built-in browser are saved in this history." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Edit file" msgid "Edit MCP server" msgstr "Edit MCP server" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Edit password" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Edit profile" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Edit saved password" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Files for {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Files matching these globs are hidden from the @file mention search." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Files you download appear here" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Filter by project" @@ -3713,6 +3824,11 @@ msgstr "Find in chat" msgid "Find in diff" msgstr "Find in diff" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Find in page" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Find in terminal" @@ -3877,6 +3993,10 @@ msgstr "Frequency" msgid "Friday at 4:00 PM" msgstr "Friday at 4:00 PM" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "From" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." @@ -4086,7 +4206,7 @@ msgstr "handle" msgid "Handle" msgstr "Handle" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Hard Reload" @@ -4149,6 +4269,10 @@ msgstr "Hide models you don't use from the model picker across every provider." msgid "Hide panel" msgstr "Hide panel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Hide password" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Hide runtime debug panel" @@ -4171,7 +4295,7 @@ msgstr "Hide skills from {0}" msgid "Hide terminal" msgstr "Hide terminal" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "History" @@ -4203,10 +4327,18 @@ msgstr "Hourly" msgid "HTTP (streamable)" msgstr "HTTP (streamable)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "I understand that protected browser data may be skipped." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Image" msgid "Image preview" msgstr "Image preview" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Import" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Import again" @@ -4248,10 +4384,23 @@ msgstr "Import again" msgid "Import and restart" msgstr "Import and restart" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Import browser data" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Import conflict" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Import cookies" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Import cookies and passwords" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Import external agent skills" msgid "Import external skills" msgstr "Import external skills" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Import from your browser" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Import Lightcode data" @@ -4285,10 +4438,18 @@ msgstr "Import MCP servers" msgid "Import method" msgstr "Import method" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Import passwords" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Import selected" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Import source" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Import to {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "Imported {0} skills." msgid "Imported 1 skill." msgstr "Imported 1 skill." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Imported from {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Imported passwords: {0}. Imported cookies: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Improved" @@ -4469,6 +4641,7 @@ msgstr "Instructions agents follow when choosing which agent or model to delegat msgid "Interrupt" msgstr "Interrupt" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Interrupted" @@ -4477,6 +4650,26 @@ msgstr "Interrupted" msgid "Interrupted: agent session ended before completion." msgstr "Interrupted: agent session ended before completion." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Italic" @@ -4530,6 +4723,14 @@ msgstr "Language for AI-generated commit messages and pull request summaries. Th msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Language the speech model should expect when transcribing composer dictation." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Local" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Local changes need to be stashed before pulling from {branch}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Local password protection" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Longest streak" msgid "Longest task" msgstr "Longest task" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Looking for browser profiles…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Looking for dev servers…" @@ -4791,6 +5000,10 @@ msgstr "Make the sidebar translucent — the system blur material on Windows 11, #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Manage global and project agent skills, including skills imported from other providers." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Manage passwords" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Manage remote environments" @@ -5399,8 +5612,8 @@ msgstr "New schedule" #~ msgstr "New scheduled task" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "New tab" @@ -5611,6 +5824,10 @@ msgstr "No diff available for {0}" msgid "No diff for {visiblePath}" msgstr "No diff for {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "No downloads match your search" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "No external skills were found in this scope." @@ -5630,7 +5847,7 @@ msgstr "No files match \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "No history yet" @@ -5705,6 +5922,10 @@ msgstr "No other agents installed" msgid "No paired devices yet." msgstr "No paired devices yet." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "No passwords match your search" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "No patterns." @@ -5771,6 +5992,10 @@ msgstr "No runs yet." msgid "No runtime items yet for this thread." msgstr "No runtime items yet for this thread." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "No saved passwords" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "No servers connected yet." @@ -5808,6 +6033,10 @@ msgstr "No supported agents are installed on this remote machine. Install and si msgid "No supported agents detected" msgstr "No supported agents detected" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "No supported browser profiles were found on this device." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "No thread selected" @@ -6047,6 +6276,10 @@ msgstr "Open conflict resolver in" msgid "Open dialog" msgstr "Open dialog" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Open downloaded file" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Open File" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Passphrase (optional)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Password" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Password copied." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Password manager" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Password manager section" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Passwords" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Passwords and autofill" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Paste the SSH private key." msgid "Pause" msgstr "Pause" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Pause download" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Paused" @@ -6476,6 +6741,10 @@ msgstr "Pin to top" msgid "Pinned" msgstr "Pinned" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Previous runs" msgid "Previous tab" msgstr "Previous tab" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Print" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Private key" @@ -6730,6 +7003,10 @@ msgstr "Prompts" msgid "Proposed plan" msgstr "Proposed plan" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Protected browser data" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Provided and managed by Poracode for supported agents." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Remove action" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Remove bookmark" @@ -7143,6 +7421,10 @@ msgstr "Remove connection" msgid "Remove environment variable" msgstr "Remove environment variable" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Remove from download history" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Remove from favorites" @@ -7304,6 +7586,10 @@ msgstr "Reset sidebar frosting to default" msgid "Reset to default" msgstr "Reset to default" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Reset zoom" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Resize browser drawer" @@ -7337,11 +7623,27 @@ msgstr "Resize split" msgid "Resize terminal panel" msgstr "Resize terminal panel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Resize viewport" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Resize viewport height" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Resize viewport width" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Resolves merge conflicts during rebase or merge." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Responsive" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Restore" @@ -7367,6 +7669,10 @@ msgstr "Restore thread" msgid "Resume" msgstr "Resume" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Resume download" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Reveal in File Explorer" msgid "Reveal in file tree" msgstr "Reveal in file tree" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Reveal password" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Right panel" msgid "Right-click to switch ring" msgstr "Right-click to switch ring" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Rotate viewport" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Runtime debug" msgid "Runtime options" msgstr "Runtime options" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Search agents..." msgid "Search branches..." msgstr "Search branches..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Search downloads" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Search models..." msgid "Search or enter address" msgstr "Search or enter address" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Search passwords" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Search pull requests" @@ -7980,7 +8307,7 @@ msgstr "Set shortcut" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Show a projectless Home scope for OS-level agent sessions." msgid "Show all" msgstr "Show all" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Show bookmark bar" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Show Bookmark Bar" @@ -8054,6 +8381,10 @@ msgstr "Show composer" msgid "Show context usage details" msgstr "Show context usage details" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Show device toolbar" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Show estimated cost" msgid "Show in file explorer" msgstr "Show in file explorer" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Show in folder" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Skipped" msgid "Slash commands" msgstr "Slash commands" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Some browser data was skipped. Protected items skipped: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Some checks are failing or pending." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." @@ -8694,6 +9038,14 @@ msgstr "Support:" msgid "Supports Fast mode" msgstr "Supports Fast mode" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Swap notes and to-dos" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "Tailscale URL" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Take Screenshot" @@ -9125,6 +9477,11 @@ msgstr "This remote project is unavailable. Reconnect the environment and try ag msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "This removes later messages and restores files when a checkpoint snapshot is available." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "This removes the saved password for <0>{0} from Poracode." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "This removes the schedule and its latest result from this device." @@ -9428,14 +9785,34 @@ msgstr "Unable to copy pairing token." msgid "Unable to copy Tailscale URL." msgstr "Unable to copy Tailscale URL." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Unable to copy the password." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Unable to create WSL worktree directory \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Unable to delete the saved password." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Unable to delete the worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Unable to edit the saved password." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Unable to find browser data to import." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Unable to import browser data." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "Unable to install {0} hooks." msgid "Unable to install {0}." msgstr "Unable to install {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Unable to load downloads." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Unable to load remote access pairing." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Unable to load saved passwords." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Unable to load thread." @@ -9515,6 +9900,10 @@ msgstr "Unable to resolve home directory for WSL distro \"{distro}\"" msgid "Unable to restore the SSH connection." msgstr "Unable to restore the SSH connection." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Unable to reveal the password." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Unable to revoke remote session." @@ -9528,6 +9917,10 @@ msgstr "Unable to save {0} credentials." msgid "Unable to save Claude {displayLabel} profile." msgstr "Unable to save Claude {displayLabel} profile." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Unable to save the password." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Unable to start {label}." @@ -9595,6 +9988,10 @@ msgstr "Unable to update remote access." msgid "Unable to update Tailscale HTTPS." msgstr "Unable to update Tailscale HTTPS." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Unable to update the download." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Unable to update the public URL." @@ -9897,6 +10294,10 @@ msgstr "Used by {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Username" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Using the built-in Claude model list." @@ -9970,6 +10371,18 @@ msgstr "View the changelog" msgid "View-only — this connection can't manage projects." msgstr "View-only — this connection can't manage projects." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Viewport height" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Viewport scale" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Viewport width" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Web server" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Website" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Website origin" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Weekdays" @@ -10347,10 +10765,16 @@ msgstr "WSL base folder" msgid "Your name" msgstr "Your name" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Zoom" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Zoom in" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Zoom out" diff --git a/src/renderer/locales/es/messages.po b/src/renderer/locales/es/messages.po index 7d1734c49..0dcb33b74 100644 --- a/src/renderer/locales/es/messages.po +++ b/src/renderer/locales/es/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30d" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7d" @@ -618,6 +622,10 @@ msgstr "Añadir" msgid "Add a local project" msgstr "Agregar un proyecto local" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Agrega una contraseña o importa una desde otro navegador." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Añadir modelo" msgid "Add one manually or import from another agent." msgstr "Añade uno manualmente o impórtalo desde otro agente." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Agregar contraseña" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Añadir patrón" @@ -751,6 +763,10 @@ msgstr "Agregar a favoritos" msgid "Add to Home Screen" msgstr "Agregar a la pantalla de inicio" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Avanzado" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Anuncia una URL base personalizada, por ejemplo un proxy inverso o un túnel. Déjalo vacío para que sea automático." @@ -1301,11 +1317,12 @@ msgstr "bloqueado:" msgid "Bold" msgstr "Negrita" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Añadir esta página a marcadores" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Marcadores" @@ -1342,6 +1359,10 @@ msgstr "Devolver al panel" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Devuélvelo a este panel o ve a la ventana en la que se está ejecutando." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Importa las contraseñas y cookies guardadas desde un navegador instalado." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Examinar" @@ -1387,7 +1408,7 @@ msgstr "Browser MCP habilitado para OpenCode" msgid "Browser MCP enabled for this thread" msgstr "Browser MCP habilitado para este hilo" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Menú del navegador" @@ -1487,6 +1508,8 @@ msgstr "No se pudieron cargar los puertos" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "No se pudieron cargar los puertos" msgid "Cancel" msgstr "Cancelar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Cancelar descarga" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Cancelar nuevo perfil de Claude" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "cancelado" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Cancelado" @@ -1682,6 +1710,10 @@ msgstr "Elige una carpeta principal" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Elegir un archivo de configuración de servidor MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Elige los datos que quieres transferir al navegador integrado." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Elige cómo iniciar sesión para {env}." @@ -1754,22 +1786,34 @@ msgstr "Perfil de Claude eliminado." msgid "Cleanup script" msgstr "Script de limpieza" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Borrar datos de navegación" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Borrar historial de navegación" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Borrar historial de navegación" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Borrar caché" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "Borrar caché" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Borrar cookies" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Borrar cookies" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "Cerrar el Composer" msgid "Close connection actions" msgstr "Cerrar acciones de conexión" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Cerrar barra de herramientas de dispositivos" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Cerrar editor" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "completado" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Completado" @@ -2401,6 +2450,10 @@ msgstr "Controla el escritorio emparejado mientras el agente hace clic o escribe msgid "Conversation" msgstr "Conversación" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookies" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Copia todos los datos de Lightcode en Poracode. Poracode se reiniciará msgid "Copy code" msgstr "Copiar código" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Copiar la URL actual" @@ -2479,6 +2532,10 @@ msgstr "Copiar enlace de emparejamiento" msgid "Copy pairing token" msgstr "Copiar token de emparejamiento" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Copiar contraseña" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Copiar ruta" @@ -2807,6 +2864,7 @@ msgstr "Eliminación de hilos predeterminada" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Eliminar archivo" msgid "Delete permanently" msgstr "Eliminar permanentemente" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Eliminar contraseña guardada" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "¿Eliminar contraseña guardada?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Eliminar programación" @@ -2998,6 +3064,10 @@ msgstr "Servidores de desarrollo escuchando en el localhost de tu escritorio." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Sustituciones solo para desarrollo. Solo visibles en la compilación PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Dispositivo predefinido" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Dispositivo que usa el botón de entrada de voz del redactor." msgid "Devices can pair while this desktop is reachable." msgstr "Los dispositivos pueden emparejarse mientras este escritorio esté accesible." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Dimensiones:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Se requiere una conexión directa" @@ -3164,10 +3238,27 @@ msgstr "Listo" msgid "Done · Waiting for your input" msgstr "Listo · Esperando tu entrada" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Error en la descarga" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Historial de descargas" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Descargar imagen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Progreso de la descarga" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Descargando" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Descargando modelo de voz {0}%" msgid "Downloading voice model..." msgstr "Descargando modelo de voz..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Descargas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Las descargas del navegador integrado se guardan en este historial." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Editar archivo" msgid "Edit MCP server" msgstr "Editar servidor MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Editar contraseña" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Editar perfil" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Editar contraseña guardada" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Archivos de {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Los archivos que coinciden con estos globs se ocultan de la búsqueda de menciones @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Los archivos que descargues aparecerán aquí" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Filtrar por proyecto" @@ -3713,6 +3824,11 @@ msgstr "Buscar en el chat" msgid "Find in diff" msgstr "Buscar en el diff" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Buscar en la página" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Buscar en el terminal" @@ -3877,6 +3993,10 @@ msgstr "Frecuencia" msgid "Friday at 4:00 PM" msgstr "Viernes a las 4:00 p. m." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Desde" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Aplica al panel lateral el efecto esmerilado del desenfoque del sistema (vibrancy), al estilo de las versiones recientes de macOS. Si no es compatible, usa un tinte translúcido." @@ -4086,7 +4206,7 @@ msgstr "identificador" msgid "Handle" msgstr "Identificador" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Recarga forzada" @@ -4149,6 +4269,10 @@ msgstr "Oculta los modelos que no usas del selector de modelos en todos los prov msgid "Hide panel" msgstr "Ocultar panel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Ocultar contraseña" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Ocultar panel de depuración del runtime" @@ -4171,7 +4295,7 @@ msgstr "Ocultar skills de {0}" msgid "Hide terminal" msgstr "Ocultar terminal" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Historial" @@ -4203,10 +4327,18 @@ msgstr "Cada hora" msgid "HTTP (streamable)" msgstr "HTTP (transmisión continua)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Entiendo que algunos datos protegidos del navegador podrían omitirse." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Imagen" msgid "Image preview" msgstr "Vista previa de imagen" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Importar" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Importar de nuevo" @@ -4248,10 +4384,23 @@ msgstr "Importar de nuevo" msgid "Import and restart" msgstr "Importar y reiniciar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Importar datos del navegador" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Conflicto de importación" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Importar cookies" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Importar cookies y contraseñas" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Importar skills de agentes externos" msgid "Import external skills" msgstr "Importar skills externos" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Importar desde tu navegador" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Importar datos de Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Importar servidores MCP" msgid "Import method" msgstr "Método de importación" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Importar contraseñas" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Importar seleccionados" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Origen de importación" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Importar a {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "Se importaron {0} skills." msgid "Imported 1 skill." msgstr "Se importó 1 skill." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Importado desde {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Contraseñas importadas: {0}. Cookies importadas: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Mejorado" @@ -4469,6 +4641,7 @@ msgstr "Instrucciones que siguen los agentes al elegir a qué agente o modelo de msgid "Interrupt" msgstr "Interrumpir" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Interrumpida" @@ -4477,6 +4650,26 @@ msgstr "Interrumpida" msgid "Interrupted: agent session ended before completion." msgstr "Interrumpido: la sesión del agente terminó antes de completarse." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Cursiva" @@ -4530,6 +4723,14 @@ msgstr "Idioma de los mensajes de commit y los resúmenes de pull request genera msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Idioma que debe esperar el modelo de voz al transcribir el dictado del redactor." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Local" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Es necesario guardar los cambios locales en stash antes de hacer pull desde {branch}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Protección local de contraseñas" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Racha más larga" msgid "Longest task" msgstr "Tarea más larga" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Buscando perfiles de navegador…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Buscando servidores de desarrollo…" @@ -4791,6 +5000,10 @@ msgstr "Hace translúcido el panel lateral: el efecto de desenfoque del sistema #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Gestiona los skills globales y de proyecto de los agentes, incluidos los importados de otros proveedores." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Administrar contraseñas" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Administrar entornos remotos" @@ -5399,8 +5612,8 @@ msgstr "Nueva programación" #~ msgstr "Nueva tarea programada" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Nueva pestaña" @@ -5611,6 +5824,10 @@ msgstr "No hay diff disponible para {0}" msgid "No diff for {visiblePath}" msgstr "No hay diff para {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Ninguna descarga coincide con tu búsqueda" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "No se encontraron skills externos en este ámbito." @@ -5630,7 +5847,7 @@ msgstr "Ningún archivo coincide con \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "No se encontraron cuentas de GitHub CLI. Inicia sesión con <0>gh auth login, o <1>pega una URL de clonación." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Aún no hay historial" @@ -5705,6 +5922,10 @@ msgstr "No hay otros agentes instalados" msgid "No paired devices yet." msgstr "Aún no hay dispositivos emparejados." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Ninguna contraseña coincide con tu búsqueda" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Sin patrones." @@ -5771,6 +5992,10 @@ msgstr "Aún no hay ejecuciones." msgid "No runtime items yet for this thread." msgstr "Aún no hay elementos de runtime para este hilo." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "No hay contraseñas guardadas" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Aún no hay servidores conectados." @@ -5808,6 +6033,10 @@ msgstr "No hay agentes compatibles instalados en esta máquina remota. Instala u msgid "No supported agents detected" msgstr "No se detectaron agentes compatibles" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "No se encontraron perfiles de navegador compatibles en este dispositivo." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "No hay hilo seleccionado" @@ -6047,6 +6276,10 @@ msgstr "Abrir el resolutor de conflictos en" msgid "Open dialog" msgstr "Abrir diálogo" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Abrir archivo descargado" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Abrir archivo" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Frase de contraseña (opcional)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Contraseña" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Contraseña copiada." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Gestor de contraseñas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Sección del gestor de contraseñas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Contraseñas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Contraseñas y autocompletado" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Las contraseñas se cifran en el almacén local de credenciales de Poracode. Los valores de las contraseñas solo se solicitan cuando las muestras, copias o editas." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Pega la clave privada SSH." msgid "Pause" msgstr "Pausar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Pausar descarga" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "En pausa" @@ -6476,6 +6741,10 @@ msgstr "Fijar arriba" msgid "Pinned" msgstr "Fijado" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Ejecuciones anteriores" msgid "Previous tab" msgstr "Pestaña anterior" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Imprimir" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Clave privada" @@ -6730,6 +7003,10 @@ msgstr "Prompts" msgid "Proposed plan" msgstr "Plan propuesto" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Datos protegidos del navegador" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Poracode lo proporciona y administra para los agentes compatibles." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Eliminar acción" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Eliminar marcador" @@ -7143,6 +7421,10 @@ msgstr "Eliminar conexión" msgid "Remove environment variable" msgstr "Eliminar variable de entorno" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Eliminar del historial de descargas" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Quitar de favoritos" @@ -7304,6 +7586,10 @@ msgstr "Restablecer el esmerilado del panel lateral a sus valores predeterminado msgid "Reset to default" msgstr "Restablecer valores predeterminados" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Restablecer zoom" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Redimensionar cajón del navegador" @@ -7337,11 +7623,27 @@ msgstr "Redimensionar división" msgid "Resize terminal panel" msgstr "Redimensionar panel de terminal" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Cambiar el tamaño del área de visualización" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Cambiar la altura del área de visualización" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Cambiar la anchura del área de visualización" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Resuelve conflictos de fusión durante el rebase o la fusión." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Adaptable" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Restaurar" @@ -7367,6 +7669,10 @@ msgstr "Restaurar hilo" msgid "Resume" msgstr "Reanudar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Reanudar descarga" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Mostrar en el Explorador de archivos" msgid "Reveal in file tree" msgstr "Mostrar en el árbol de archivos" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Mostrar contraseña" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Panel derecho" msgid "Right-click to switch ring" msgstr "Haz clic derecho para cambiar de anillo" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Girar el área de visualización" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Depuración de runtime" msgid "Runtime options" msgstr "Opciones de runtime" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Buscar agentes..." msgid "Search branches..." msgstr "Buscar ramas..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Buscar descargas" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Buscar modelos..." msgid "Search or enter address" msgstr "Buscar o introducir dirección" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Buscar contraseñas" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Buscar pull requests" @@ -7980,7 +8307,7 @@ msgstr "Asignar atajo" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Mostrar un ámbito de inicio sin proyecto para las sesiones de agente a msgid "Show all" msgstr "Mostrar todo" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Mostrar la barra de marcadores" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Mostrar barra de marcadores" @@ -8054,6 +8381,10 @@ msgstr "Mostrar Composer" msgid "Show context usage details" msgstr "Mostrar detalles del uso de contexto" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Mostrar barra de herramientas de dispositivos" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Mostrar coste estimado" msgid "Show in file explorer" msgstr "Mostrar en el explorador de archivos" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Mostrar en la carpeta" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Omitido" msgid "Slash commands" msgstr "Comandos con barra" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Se omitieron algunos datos del navegador. Elementos protegidos omitidos: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Algunas comprobaciones están fallando o pendientes." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Algunos navegadores Chromium protegen las cookies y contraseñas con cifrado App-Bound. Poracode no elude esa protección. Los datos que el sistema operativo no ponga a disposición se omitirán." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "No se pudieron analizar algunas carpetas de proveedores. Los skills cargados correctamente se siguen mostrando." @@ -8694,6 +9038,14 @@ msgstr "Soporte:" msgid "Supports Fast mode" msgstr "Compatible con el modo rápido" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Intercambiar notas y tareas pendientes" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "URL de Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Hacer captura de pantalla" @@ -9125,6 +9477,11 @@ msgstr "Este proyecto remoto no está disponible. Vuelve a conectar el entorno e msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Esto elimina los mensajes posteriores y restaura los archivos cuando hay disponible una instantánea de punto de control." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Esto elimina de Poracode la contraseña guardada de <0>{0}." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Esto elimina la programación y su resultado más reciente de este dispositivo." @@ -9428,14 +9785,34 @@ msgstr "No se pudo copiar el token de emparejamiento." msgid "Unable to copy Tailscale URL." msgstr "No se pudo copiar la URL de Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "No se pudo copiar la contraseña." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "No se pudo crear el directorio de worktree de WSL \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "No se pudo eliminar la contraseña guardada." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "No se pudo eliminar el worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "No se pudo editar la contraseña guardada." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "No se encontraron datos del navegador para importar." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "No se pudieron importar los datos del navegador." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "No se pueden instalar los hooks de {0}." msgid "Unable to install {0}." msgstr "No se pudo instalar {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "No se pudieron cargar las descargas." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "No se pudo cargar el emparejamiento de acceso remoto." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "No se pudieron cargar las contraseñas guardadas." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "No se pudo cargar el hilo." @@ -9515,6 +9900,10 @@ msgstr "No se pudo resolver el directorio de inicio para la distro de WSL \"{dis msgid "Unable to restore the SSH connection." msgstr "No se pudo restaurar la conexión SSH." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "No se pudo mostrar la contraseña." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "No se pudo revocar la sesión remota." @@ -9528,6 +9917,10 @@ msgstr "No se pueden guardar las credenciales de {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "No se pudo guardar el perfil {displayLabel} de Claude." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "No se pudo guardar la contraseña." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "No se pudo iniciar {label}." @@ -9595,6 +9988,10 @@ msgstr "No se pudo actualizar el acceso remoto." msgid "Unable to update Tailscale HTTPS." msgstr "No se pudo actualizar el HTTPS de Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "No se pudo actualizar la descarga." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "No se pudo actualizar la URL pública." @@ -9897,6 +10294,10 @@ msgstr "Lo usa {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Nombre de usuario" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Usando la lista de modelos integrada de Claude." @@ -9970,6 +10371,18 @@ msgstr "Ver el registro de cambios" msgid "View-only — this connection can't manage projects." msgstr "Solo lectura: esta conexión no puede gestionar proyectos." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Altura del área de visualización" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Escala del área de visualización" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Anchura del área de visualización" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Servidor web" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Sitio web" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Origen del sitio web" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Días laborables" @@ -10347,10 +10765,16 @@ msgstr "Carpeta base de WSL" msgid "Your name" msgstr "Tu nombre" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Zoom" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Acercar" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Alejar" diff --git a/src/renderer/locales/fr/messages.po b/src/renderer/locales/fr/messages.po index 563b5cf75..cbb189f7f 100644 --- a/src/renderer/locales/fr/messages.po +++ b/src/renderer/locales/fr/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30 j" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7 j" @@ -618,6 +622,10 @@ msgstr "Ajouter" msgid "Add a local project" msgstr "Ajouter un projet local" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Ajoutez un mot de passe ou importez-en un depuis un autre navigateur." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Ajouter un modèle" msgid "Add one manually or import from another agent." msgstr "Ajoutez-en un manuellement ou importez-le depuis un autre agent." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Ajouter un mot de passe" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Ajouter un motif" @@ -751,6 +763,10 @@ msgstr "Ajouter aux favoris" msgid "Add to Home Screen" msgstr "Ajouter à l'écran d'accueil" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Avancé" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Annoncez une URL de base personnalisée, par ex. un proxy inverse ou un tunnel. Laissez vide pour un choix automatique." @@ -1301,11 +1317,12 @@ msgstr "bloqué :" msgid "Bold" msgstr "Gras" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Ajouter cette page aux favoris" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Favoris" @@ -1342,6 +1359,10 @@ msgstr "Ramener dans le panneau" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Ramenez-le dans ce panneau ou accédez à la fenêtre dans laquelle il s’exécute." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Importez les mots de passe et les cookies enregistrés depuis un navigateur installé." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Parcourir" @@ -1387,7 +1408,7 @@ msgstr "Navigateur MCP activé pour OpenCode" msgid "Browser MCP enabled for this thread" msgstr "Navigateur MCP activé pour ce fil de discussion" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Menu du navigateur" @@ -1487,6 +1508,8 @@ msgstr "Impossible de charger les ports" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Impossible de charger les ports" msgid "Cancel" msgstr "Annuler" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Annuler le téléchargement" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Annuler le nouveau profil Claude" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "annulé" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Annulé" @@ -1682,6 +1710,10 @@ msgstr "Choisissez un dossier parent" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Choisir un fichier de configuration de serveur MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Choisissez les données à transférer vers le navigateur intégré." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Choisissez comment vous connecter à {env}." @@ -1754,22 +1786,34 @@ msgstr "Profil de Claude supprimé." msgid "Cleanup script" msgstr "Script de nettoyage" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Effacer les données de navigation" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Effacer l’historique de navigation" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Effacer l'historique de navigation" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Vider le cache" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "Vider le cache" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Effacer les cookies" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Effacer les cookies" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "Fermer le compositeur" msgid "Close connection actions" msgstr "Fermer les actions de la connexion" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Fermer la barre d’outils des appareils" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Fermer l'éditeur" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "terminé" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Terminé" @@ -2401,6 +2450,10 @@ msgstr "Contrôle le bureau associé pendant que l'agent clique ou tape" msgid "Conversation" msgstr "Conversation" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookies" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Copiez toutes les données Lightcode dans Poracode. Poracode redémarrer msgid "Copy code" msgstr "Copier le code" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Copier l'URL actuelle" @@ -2479,6 +2532,10 @@ msgstr "Copier le lien d’association" msgid "Copy pairing token" msgstr "Copier le jeton d'association" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Copier le mot de passe" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Copier le chemin" @@ -2807,6 +2864,7 @@ msgstr "Suppression du fil par défaut" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Supprimer le fichier" msgid "Delete permanently" msgstr "Supprimer définitivement" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Supprimer le mot de passe enregistré" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Supprimer le mot de passe enregistré ?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Supprimer la planification" @@ -2998,6 +3064,10 @@ msgstr "Serveurs de développement à l'écoute sur le localhost de votre bureau msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Remplacements réservés au développement. Visible uniquement dans la version PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Préréglage d’appareil" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Appareil utilisé par le bouton de saisie vocale du composeur." msgid "Devices can pair while this desktop is reachable." msgstr "Les appareils peuvent s’appairer lorsque ce bureau est joignable." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Dimensions :" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Connexion directe requise" @@ -3164,10 +3238,27 @@ msgstr "Terminé" msgid "Done · Waiting for your input" msgstr "Terminé · En attente de votre saisie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Échec du téléchargement" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Historique des téléchargements" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Télécharger l'image" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Progression du téléchargement" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Téléchargement en cours" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Téléchargement du modèle vocal {0}%" msgid "Downloading voice model..." msgstr "Téléchargement du modèle vocal..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Téléchargements" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Les téléchargements du navigateur intégré sont enregistrés dans cet historique." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Modifier le fichier" msgid "Edit MCP server" msgstr "Modifier le serveur MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Modifier le mot de passe" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Modifier le profil" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Modifier le mot de passe enregistré" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Fichiers pour {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Les fichiers correspondant à ces globs sont masqués dans la recherche de mention @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Les fichiers que vous téléchargez apparaissent ici" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Filtrer par projet" @@ -3713,6 +3824,11 @@ msgstr "Rechercher dans le chat" msgid "Find in diff" msgstr "Rechercher dans la différence" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Rechercher dans la page" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Rechercher dans le terminal" @@ -3877,6 +3993,10 @@ msgstr "Fréquence" msgid "Friday at 4:00 PM" msgstr "Vendredi à 16 h 00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Depuis" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Givre la barre latérale avec le flou système (vibrancy), à la manière des versions récentes de macOS. Bascule sur une teinte translucide là où ce n'est pas pris en charge." @@ -4086,7 +4206,7 @@ msgstr "identifiant" msgid "Handle" msgstr "Identifiant" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Rechargement forcé" @@ -4149,6 +4269,10 @@ msgstr "Masquez les modèles que vous n’utilisez pas dans le sélecteur de mod msgid "Hide panel" msgstr "Masquer le panneau" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Masquer le mot de passe" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Masquer le panneau de débogage d'exécution" @@ -4171,7 +4295,7 @@ msgstr "Masquer les compétences de {0}" msgid "Hide terminal" msgstr "Masquer le terminal" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Historique" @@ -4203,10 +4327,18 @@ msgstr "Toutes les heures" msgid "HTTP (streamable)" msgstr "HTTP (diffusion en continu)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Je comprends que certaines données protégées du navigateur peuvent être ignorées." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Image" msgid "Image preview" msgstr "Aperçu de l'image" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Importer" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Importer à nouveau" @@ -4248,10 +4384,23 @@ msgstr "Importer à nouveau" msgid "Import and restart" msgstr "Importer et redémarrer" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Importer les données du navigateur" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Conflit d’importation" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Importer les cookies" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Importer les cookies et les mots de passe" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Importer des compétences d’agents externes" msgid "Import external skills" msgstr "Importer des compétences externes" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Importer depuis votre navigateur" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Importer les données Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Importer des serveurs MCP" msgid "Import method" msgstr "Méthode d’importation" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Importer les mots de passe" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Importer la sélection" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Source de l’importation" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Importer dans {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "{0} compétences importées." msgid "Imported 1 skill." msgstr "1 compétence importée." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Importé depuis {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Mots de passe importés : {0}. Cookies importés : {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Amélioré" @@ -4469,6 +4641,7 @@ msgstr "Instructions que les agents suivent pour choisir à quel agent ou modèl msgid "Interrupt" msgstr "Interrompre" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Interrompue" @@ -4477,6 +4650,26 @@ msgstr "Interrompue" msgid "Interrupted: agent session ended before completion." msgstr "Interrompu : la session de l'agent s'est terminée avant la fin." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Italique" @@ -4530,6 +4723,14 @@ msgstr "Langue des messages de commit et des résumés de pull request généré msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Langue que le modèle vocal doit attendre lors de la transcription de la dictée dans le composeur." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Local" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Les modifications locales doivent être mises de côté (stash) avant de récupérer depuis {branch}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Protection locale des mots de passe" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Plus longue série" msgid "Longest task" msgstr "Tâche la plus longue" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Recherche des profils de navigateur…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Recherche de serveurs de développement…" @@ -4791,6 +5000,10 @@ msgstr "Rend la barre latérale translucide — le flou système sur Windows 11, #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Gérez les compétences globales et de projet des agents, y compris celles importées depuis d’autres fournisseurs." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Gérer les mots de passe" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Gérer les environnements distants" @@ -5398,8 +5611,8 @@ msgstr "Nouvelle planification" #~ msgstr "Nouvelle tâche planifiée" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Nouvel onglet" @@ -5610,6 +5823,10 @@ msgstr "Aucune différence disponible pour {0}" msgid "No diff for {visiblePath}" msgstr "Aucune différence pour {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Aucun téléchargement ne correspond à votre recherche" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Aucune compétence externe n’a été trouvée dans cette portée." @@ -5629,7 +5846,7 @@ msgstr "Aucun fichier ne correspond à \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Aucun compte GitHub CLI trouvé. Connectez-vous avec <0>gh auth login ou <1>collez une URL de clonage." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Aucun historique pour l’instant" @@ -5704,6 +5921,10 @@ msgstr "Aucun autre agent installé" msgid "No paired devices yet." msgstr "Aucun appareil associé pour le moment." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Aucun mot de passe ne correspond à votre recherche" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Aucun motif." @@ -5770,6 +5991,10 @@ msgstr "Aucune exécution pour l'instant." msgid "No runtime items yet for this thread." msgstr "Aucun élément d'exécution pour ce fil pour l'instant." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Aucun mot de passe enregistré" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Aucun serveur connecté pour l'instant." @@ -5807,6 +6032,10 @@ msgstr "Aucun agent compatible n’est installé sur cette machine distante. Ins msgid "No supported agents detected" msgstr "Aucun agent pris en charge détecté" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "Aucun profil de navigateur pris en charge n’a été trouvé sur cet appareil." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Aucun fil sélectionné" @@ -6046,6 +6275,10 @@ msgstr "Ouvrir le résolveur de conflits dans" msgid "Open dialog" msgstr "Ouvrir la boîte de dialogue" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Ouvrir le fichier téléchargé" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Ouvrir le fichier" @@ -6375,9 +6608,36 @@ msgid "Passphrase (optional)" msgstr "Phrase secrète (facultatif)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Mot de passe" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Mot de passe copié." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Gestionnaire de mots de passe" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Section du gestionnaire de mots de passe" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Mots de passe" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Mots de passe et remplissage automatique" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Les mots de passe sont chiffrés dans le magasin local d’identifiants de Poracode. Leur valeur n’est demandée que lorsque vous les affichez, les copiez ou les modifiez." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6410,7 +6670,12 @@ msgstr "Collez la clé privée SSH." msgid "Pause" msgstr "Mettre en pause" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Mettre le téléchargement en pause" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "En pause" @@ -6475,6 +6740,10 @@ msgstr "Épingler en haut" msgid "Pinned" msgstr "Épinglé" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6642,6 +6911,10 @@ msgstr "Exécutions précédentes" msgid "Previous tab" msgstr "Onglet précédent" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Imprimer" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Clé privée" @@ -6729,6 +7002,10 @@ msgstr "Prompts" msgid "Proposed plan" msgstr "Plan proposé" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Données de navigateur protégées" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Fourni et géré par Poracode pour les agents compatibles." @@ -7126,6 +7403,7 @@ msgid "Remove action" msgstr "Supprimer l'action" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Supprimer le favori" @@ -7142,6 +7420,10 @@ msgstr "Supprimer la connexion" msgid "Remove environment variable" msgstr "Supprimer la variable d'environnement" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Supprimer de l’historique des téléchargements" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Supprimer des favoris" @@ -7303,6 +7585,10 @@ msgstr "Réinitialiser le givrage de la barre latérale" msgid "Reset to default" msgstr "Réinitialiser par défaut" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Réinitialiser le zoom" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Redimensionner le tiroir du navigateur" @@ -7336,11 +7622,27 @@ msgstr "Redimensionner la division" msgid "Resize terminal panel" msgstr "Redimensionner le panneau de terminal" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Redimensionner la zone d’affichage" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Redimensionner la hauteur de la zone d’affichage" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Redimensionner la largeur de la zone d’affichage" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Résout les conflits de fusion lors du rebase ou de la fusion." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Adaptatif" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Restaurer" @@ -7366,6 +7668,10 @@ msgstr "Restaurer le fil" msgid "Resume" msgstr "Reprendre" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Reprendre le téléchargement" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7408,6 +7714,10 @@ msgstr "Révéler dans l'explorateur de fichiers" msgid "Reveal in file tree" msgstr "Révéler dans l'arborescence des fichiers" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Afficher le mot de passe" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7494,6 +7804,10 @@ msgstr "Panneau droit" msgid "Right-click to switch ring" msgstr "Clic droit pour changer d'anneau" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Faire pivoter la zone d’affichage" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7606,9 +7920,14 @@ msgstr "Débogage d'exécution" msgid "Runtime options" msgstr "Options d'exécution" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7739,6 +8058,10 @@ msgstr "Rechercher des agents..." msgid "Search branches..." msgstr "Rechercher des branches..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Rechercher dans les téléchargements" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7772,6 +8095,10 @@ msgstr "Rechercher des modèles..." msgid "Search or enter address" msgstr "Rechercher ou saisir une adresse" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Rechercher dans les mots de passe" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Rechercher des pull requests" @@ -7979,7 +8306,7 @@ msgstr "Définir un raccourci" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8027,11 +8354,11 @@ msgstr "Afficher une portée Accueil sans projet pour les sessions d'agent au ni msgid "Show all" msgstr "Afficher tout" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Afficher la barre de favoris" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Afficher la barre de favoris" @@ -8053,6 +8380,10 @@ msgstr "Afficher le compositeur" msgid "Show context usage details" msgstr "Afficher les détails d'utilisation du contexte" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Afficher la barre d’outils des appareils" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8062,6 +8393,10 @@ msgstr "Afficher le coût estimé" msgid "Show in file explorer" msgstr "Afficher dans l'explorateur de fichiers" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Afficher dans le dossier" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8301,11 +8636,20 @@ msgstr "Ignoré" msgid "Slash commands" msgstr "Commandes slash" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Certaines données du navigateur ont été ignorées. Éléments protégés ignorés : {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Certaines vérifications échouent ou sont en attente." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Certains navigateurs Chromium protègent les cookies et les mots de passe avec le chiffrement App-Bound. Poracode ne contourne pas cette protection. Les données que le système d’exploitation ne rend pas disponibles seront ignorées." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Certains dossiers de fournisseurs n’ont pas pu être analysés. Les compétences chargées avec succès restent affichées." @@ -8693,6 +9037,14 @@ msgstr "Prise en charge :" msgid "Supports Fast mode" msgstr "Compatible avec le mode rapide" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Basculer entre les notes et les tâches" @@ -8808,7 +9160,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "URL Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Prendre une capture d'écran" @@ -9124,6 +9476,11 @@ msgstr "Ce projet distant est indisponible. Reconnectez l’environnement et ré msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Cela supprime les messages ultérieurs et restaure les fichiers lorsqu'un instantané de point de contrôle est disponible." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Cette action supprime de Poracode le mot de passe enregistré pour <0>{0}." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Cela supprime la planification et son dernier résultat de cet appareil." @@ -9427,14 +9784,34 @@ msgstr "Impossible de copier le jeton d'association." msgid "Unable to copy Tailscale URL." msgstr "Impossible de copier l'URL Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Impossible de copier le mot de passe." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Impossible de créer le répertoire d'arbre de travail WSL \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Impossible de supprimer le mot de passe enregistré." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Impossible de supprimer l'arbre de travail." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Impossible de modifier le mot de passe enregistré." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Impossible de trouver des données de navigateur à importer." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Impossible d’importer les données du navigateur." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9445,10 +9822,18 @@ msgstr "Impossible d'installer les hooks {0}." msgid "Unable to install {0}." msgstr "Impossible d'installer {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Impossible de charger les téléchargements." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Impossible de charger l’association d’accès distant." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Impossible de charger les mots de passe enregistrés." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Impossible de charger le fil." @@ -9514,6 +9899,10 @@ msgstr "Impossible de résoudre le répertoire personnel pour la distribution WS msgid "Unable to restore the SSH connection." msgstr "Impossible de rétablir la connexion SSH." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Impossible d’afficher le mot de passe." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Impossible de révoquer la session distante." @@ -9527,6 +9916,10 @@ msgstr "Impossible d'enregistrer les informations d'identification {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "Impossible d'enregistrer le profil Claude {displayLabel}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Impossible d’enregistrer le mot de passe." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Impossible de démarrer {label}." @@ -9594,6 +9987,10 @@ msgstr "Impossible de mettre à jour l’accès distant." msgid "Unable to update Tailscale HTTPS." msgstr "Impossible de mettre à jour Tailscale HTTPS." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Impossible de mettre à jour le téléchargement." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Impossible de mettre à jour l'URL publique." @@ -9896,6 +10293,10 @@ msgstr "Utilisé par {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Nom d’utilisateur" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Utilisation de la liste de modèles Claude intégrée." @@ -9969,6 +10370,18 @@ msgstr "Voir le journal des modifications" msgid "View-only — this connection can't manage projects." msgstr "Lecture seule — cette connexion ne peut pas gérer les projets." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Hauteur de la zone d’affichage" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Échelle de la zone d’affichage" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Largeur de la zone d’affichage" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10061,11 +10474,16 @@ msgid "Web server" msgstr "Serveur web" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Site Web" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Origine du site web" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Jours de semaine" @@ -10346,10 +10764,16 @@ msgstr "Dossier de base WSL" msgid "Your name" msgstr "Votre nom" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Zoom" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Zoom avant" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Zoom arrière" diff --git a/src/renderer/locales/ja/messages.po b/src/renderer/locales/ja/messages.po index b1b2e6c34..54bcae908 100644 --- a/src/renderer/locales/ja/messages.po +++ b/src/renderer/locales/ja/messages.po @@ -502,6 +502,10 @@ msgstr "22" msgid "30d" msgstr "30日" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7日" @@ -617,6 +621,10 @@ msgstr "追加" msgid "Add a local project" msgstr "ローカルプロジェクトを追加" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "パスワードを追加するか、別のブラウザからインポートしてください。" + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -697,6 +705,10 @@ msgstr "モデルを追加" msgid "Add one manually or import from another agent." msgstr "手動で追加するか、別のエージェントからインポートしてください。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "パスワードを追加" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "パターンを追加する" @@ -750,6 +762,10 @@ msgstr "お気に入りに追加" msgid "Add to Home Screen" msgstr "ホーム画面に追加" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "詳細設定" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "カスタムのベースURLを通知します(例: リバースプロキシやトンネル)。空欄の場合は自動的に設定されます。" @@ -1300,11 +1316,12 @@ msgstr "ブロックされました:" msgid "Bold" msgstr "太字" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "このページをブックマーク" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "ブックマーク" @@ -1341,6 +1358,10 @@ msgstr "パネルに戻す" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "このパネルに戻すか、実行中のウィンドウに移動します。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "インストール済みのブラウザから保存されたパスワードと Cookie を取り込みます。" + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "参照" @@ -1386,7 +1407,7 @@ msgstr "OpenCode に対応したブラウザ MCP" msgid "Browser MCP enabled for this thread" msgstr "このスレッドに対してブラウザ MCP が有効になっています" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "ブラウザメニュー" @@ -1486,6 +1507,8 @@ msgstr "ポートを読み込めません" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1497,6 +1520,10 @@ msgstr "ポートを読み込めません" msgid "Cancel" msgstr "キャンセル" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "ダウンロードをキャンセル" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "新しい Claude プロファイルをキャンセル" @@ -1518,6 +1545,7 @@ msgid "cancelled" msgstr "キャンセルされました" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "キャンセル済み" @@ -1681,6 +1709,10 @@ msgstr "親フォルダーを選択" #~ msgid "Choose an MCP server configuration file" #~ msgstr "MCPサーバー設定ファイルを選択" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "内蔵ブラウザに取り込むデータを選択してください。" + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "{env}にサインインする方法を選択します。" @@ -1753,22 +1785,34 @@ msgstr "Claude プロファイルが削除されました。" msgid "Cleanup script" msgstr "クリーンアップスクリプト" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "閲覧データを消去" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "閲覧履歴を消去" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "閲覧履歴を消去" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" -msgstr "キャッシュのクリア" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" +msgstr "キャッシュを消去" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "キャッシュのクリア" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Cookie を消去" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Cookie を消去" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1858,6 +1902,10 @@ msgstr "コンポーザーを閉じる" msgid "Close connection actions" msgstr "接続の操作メニューを閉じる" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "デバイス ツールバーを閉じる" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "エディタを閉じる" @@ -2182,6 +2230,7 @@ msgid "completed" msgstr "完了しました" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "完了" @@ -2400,6 +2449,10 @@ msgstr "エージェントがクリックや入力をしている間、ペアリ msgid "Conversation" msgstr "会話" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookie" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2435,7 +2488,7 @@ msgstr "すべての Lightcode データを Poracode にコピーします。Por msgid "Copy code" msgstr "コードをコピーする" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "現在の URL をコピー" @@ -2478,6 +2531,10 @@ msgstr "ペアリングリンクをコピー" msgid "Copy pairing token" msgstr "ペアリングトークンをコピー" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "パスワードをコピー" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "パスのコピー" @@ -2806,6 +2863,7 @@ msgstr "デフォルトのスレッドの削除" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2857,6 +2915,14 @@ msgstr "ファイルの削除" msgid "Delete permanently" msgstr "完全に削除" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "保存済みパスワードを削除" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "保存済みパスワードを削除しますか?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "スケジュールを削除" @@ -2997,6 +3063,10 @@ msgstr "デスクトップの localhost で待ち受けている開発サーバ msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "開発専用の上書き。 PORACODE DEV ビルドでのみ表示されます。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "デバイス プリセット" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3006,6 +3076,10 @@ msgstr "コンポーザーの音声入力ボタンで使用されるデバイス msgid "Devices can pair while this desktop is reachable." msgstr "このデスクトップに到達できる間、デバイスをペアリングできます。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "サイズ:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "直接接続が必要です" @@ -3163,10 +3237,27 @@ msgstr "完了" msgid "Done · Waiting for your input" msgstr "完了 · 入力を待っています" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "ダウンロードに失敗しました" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "ダウンロード履歴" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "画像をダウンロード" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "ダウンロードの進行状況" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "ダウンロード中" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3186,6 +3277,14 @@ msgstr "音声モデルをダウンロード中{0}%" msgid "Downloading voice model..." msgstr "音声モデルをダウンロードしています..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "ダウンロード" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "内蔵ブラウザからのダウンロードはこの履歴に保存されます。" + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3239,10 +3338,18 @@ msgstr "ファイルを編集する" msgid "Edit MCP server" msgstr "MCPサーバーを編集" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "パスワードを編集" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "プロフィールを編集" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "保存済みパスワードを編集" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3679,6 +3786,10 @@ msgstr "{0}のファイル" msgid "Files matching these globs are hidden from the @file mention search." msgstr "これらのグロブに一致するファイルは、@file メンション検索から非表示になります。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "ダウンロードしたファイルがここに表示されます" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "プロジェクトで絞り込み" @@ -3712,6 +3823,11 @@ msgstr "チャット内を検索" msgid "Find in diff" msgstr "差分内を検索" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "ページ内検索" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "ターミナル内を検索" @@ -3876,6 +3992,10 @@ msgstr "頻度" msgid "Friday at 4:00 PM" msgstr "金曜日午後4:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "インポート元" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "システムのぼかし素材(vibrancy)でサイドバーをすりガラス調にし、最近のmacOSの質感を再現します。非対応の環境では半透明の色付けに切り替わります。" @@ -4085,7 +4205,7 @@ msgstr "ハンドル" msgid "Handle" msgstr "ハンドル" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "ハードリロード" @@ -4148,6 +4268,10 @@ msgstr "すべてのプロバイダーのモデル ピッカーから使用し msgid "Hide panel" msgstr "パネルを非表示にする" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "パスワードを隠す" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "ランタイムデバッグパネルを非表示にする" @@ -4170,7 +4294,7 @@ msgstr "{0} のスキルを非表示" msgid "Hide terminal" msgstr "ターミナルを隠す" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "履歴" @@ -4202,10 +4326,18 @@ msgstr "毎時" msgid "HTTP (streamable)" msgstr "HTTP(ストリーミング対応)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "保護されたブラウザ データがスキップされる場合があることを理解しました。" + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4239,6 +4371,10 @@ msgstr "画像" msgid "Image preview" msgstr "画像プレビュー" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "インポート" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "再度インポート" @@ -4247,10 +4383,23 @@ msgstr "再度インポート" msgid "Import and restart" msgstr "インポートして再起動" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "ブラウザ データをインポート" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "インポートの競合" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Cookie をインポート" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Cookie とパスワードをインポート" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4268,6 +4417,10 @@ msgstr "外部エージェントのスキルをインポート" msgid "Import external skills" msgstr "外部スキルをインポート" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "ブラウザからインポート" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Lightcode データをインポート" @@ -4284,10 +4437,18 @@ msgstr "MCPサーバーをインポート" msgid "Import method" msgstr "インポート方法" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "パスワードをインポート" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "選択項目をインポート" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "インポート元" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "{destinationProjectName} にインポート" @@ -4315,6 +4476,17 @@ msgstr "{0} 個のスキルをインポートしました。" msgid "Imported 1 skill." msgstr "1 個のスキルをインポートしました。" +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "{0} からインポート済み" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "インポートしたパスワード:{0}。インポートした Cookie:{1}。" + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "改善" @@ -4468,6 +4640,7 @@ msgstr "どのエージェントやモデルに委任するかを選ぶ際に、 msgid "Interrupt" msgstr "中断" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "中断" @@ -4476,6 +4649,26 @@ msgstr "中断" msgid "Interrupted: agent session ended before completion." msgstr "中断されました: エージェントセッションが完了前に終了しました。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "イタリック体" @@ -4529,6 +4722,14 @@ msgstr "AI が生成するコミットメッセージとプルリクエストの msgid "Language the speech model should expect when transcribing composer dictation." msgstr "コンポーザーでの音声入力を文字起こしする際に音声モデルが想定する言語。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4712,6 +4913,10 @@ msgstr "ローカル" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "ローカルの変更は{branch}からプルする前に隠しておく必要があります" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "ローカル パスワード保護" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4778,6 +4983,10 @@ msgstr "最長の連続日数" msgid "Longest task" msgstr "最長のタスク" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "ブラウザ プロファイルを検索しています…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "開発サーバーを検索しています…" @@ -4790,6 +4999,10 @@ msgstr "サイドバーを半透明にします。Windows 11ではシステム #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "他のプロバイダーからインポートしたスキルを含む、グローバルおよびプロジェクトのエージェントスキルを管理します。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "パスワードを管理" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "リモート環境を管理" @@ -5397,8 +5610,8 @@ msgstr "新しいスケジュール" #~ msgstr "新しいスケジュールタスク" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "新しいタブ" @@ -5609,6 +5822,10 @@ msgstr "{0}に利用できる差分はありません" msgid "No diff for {visiblePath}" msgstr "{visiblePath}の差分はありません" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "検索条件に一致するダウンロードはありません" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "このスコープには外部スキルが見つかりませんでした。" @@ -5628,7 +5845,7 @@ msgstr "「{0}」に一致するファイルはありません。" msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "GitHub CLI アカウントが見つかりません。 <0>gh auth loginでサインインするか、<1>クローン URL を貼り付けます。" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "履歴はまだありません" @@ -5703,6 +5920,10 @@ msgstr "他のエージェントはインストールされていません" msgid "No paired devices yet." msgstr "ペアリング済みデバイスはまだありません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "検索条件に一致するパスワードはありません" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "パターンはありません。" @@ -5769,6 +5990,10 @@ msgstr "まだ実行はありません。" msgid "No runtime items yet for this thread." msgstr "このスレッドにはランタイム アイテムがまだありません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "保存済みパスワードはありません" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "接続済みのサーバーはまだありません。" @@ -5806,6 +6031,10 @@ msgstr "このリモートマシンには対応エージェントがインスト msgid "No supported agents detected" msgstr "サポートされているエージェントが検出されませんでした" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "このデバイスに対応するブラウザ プロファイルが見つかりませんでした。" + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "スレッドが選択されていません" @@ -6045,6 +6274,10 @@ msgstr "競合リゾルバーを開く" msgid "Open dialog" msgstr "ダイアログを開く" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "ダウンロードしたファイルを開く" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "ファイルを開く" @@ -6374,9 +6607,36 @@ msgid "Passphrase (optional)" msgstr "パスフレーズ(任意)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "パスワード" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "パスワードをコピーしました。" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "パスワード マネージャー" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "パスワード マネージャー セクション" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "パスワード" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "パスワードと自動入力" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "パスワードは Poracode のローカル資格情報ストアで暗号化されています。パスワードの値は、表示、コピー、編集するときにのみ取得されます。" + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6409,7 +6669,12 @@ msgstr "SSH 秘密鍵を貼り付けてください。" msgid "Pause" msgstr "一時停止" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "ダウンロードを一時停止" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "一時停止中" @@ -6474,6 +6739,10 @@ msgstr "トップにピン留めする" msgid "Pinned" msgstr "固定された" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6641,6 +6910,10 @@ msgstr "過去の実行" msgid "Previous tab" msgstr "前のタブ" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "印刷" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "秘密鍵" @@ -6728,6 +7001,10 @@ msgstr "プロンプト" msgid "Proposed plan" msgstr "提案された計画" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "保護されたブラウザ データ" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "対応エージェント向けにPoracodeによって提供および管理されています。" @@ -7125,6 +7402,7 @@ msgid "Remove action" msgstr "アクションの削除" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "ブックマークを削除" @@ -7141,6 +7419,10 @@ msgstr "接続を削除" msgid "Remove environment variable" msgstr "環境変数を削除" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "ダウンロード履歴から削除" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "お気に入りから削除" @@ -7302,6 +7584,10 @@ msgstr "サイドバーのすりガラス効果をデフォルトに戻す" msgid "Reset to default" msgstr "デフォルトに戻す" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "ズームをリセット" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "ブラウザドロワーのサイズを変更する" @@ -7335,11 +7621,27 @@ msgstr "分割のサイズ変更" msgid "Resize terminal panel" msgstr "ターミナルパネルのサイズを変更する" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "ビューポートのサイズを変更" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "ビューポートの高さを変更" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "ビューポートの幅を変更" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "リベースまたはマージ中のマージ競合を解決します。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "レスポンシブ" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "復元" @@ -7365,6 +7667,10 @@ msgstr "スレッドを復元する" msgid "Resume" msgstr "再開" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "ダウンロードを再開" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7407,6 +7713,10 @@ msgstr "ファイルエクスプローラーで表示" msgid "Reveal in file tree" msgstr "ファイルツリーに表示" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "パスワードを表示" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7493,6 +7803,10 @@ msgstr "右パネル" msgid "Right-click to switch ring" msgstr "右クリックでリングを切り替え" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "ビューポートを回転" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7605,9 +7919,14 @@ msgstr "ランタイムデバッグ" msgid "Runtime options" msgstr "実行時オプション" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7738,6 +8057,10 @@ msgstr "エージェントを検索..." msgid "Search branches..." msgstr "ブランチを検索..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "ダウンロードを検索" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7771,6 +8094,10 @@ msgstr "モデルを検索..." msgid "Search or enter address" msgstr "アドレスを検索または入力" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "パスワードを検索" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "プルリクエストを検索" @@ -7978,7 +8305,7 @@ msgstr "ショートカットを設定" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8026,11 +8353,11 @@ msgstr "OS レベルのエージェント セッション用に、プロジェ msgid "Show all" msgstr "すべて表示" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "ブックマークバーを表示" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "ブックマークバーを表示" @@ -8052,6 +8379,10 @@ msgstr "コンポーザーを表示" msgid "Show context usage details" msgstr "コンテキストの使用状況の詳細を表示する" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "デバイス ツールバーを表示" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8061,6 +8392,10 @@ msgstr "推定コストを表示" msgid "Show in file explorer" msgstr "ファイルエクスプローラーで表示" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "フォルダーに表示" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8300,11 +8635,20 @@ msgstr "スキップ済み" msgid "Slash commands" msgstr "スラッシュコマンド" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "一部のブラウザ データがスキップされました。スキップされた保護項目:{0}。" + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "一部のチェックが失敗または保留中です。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "一部の Chromium ブラウザは、App-Bound Encryption で Cookie とパスワードを保護しています。Poracode はこの保護を回避しません。オペレーティング システムから利用できないデータはスキップされます。" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "一部のプロバイダーフォルダーをスキャンできませんでした。正常に読み込まれたスキルは引き続き表示されます。" @@ -8692,6 +9036,14 @@ msgstr "サポート:" msgid "Supports Fast mode" msgstr "高速モードに対応" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "メモやToDoを交換する" @@ -8807,7 +9159,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "Tailscale URL" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "スクリーンショットを撮る" @@ -9123,6 +9475,11 @@ msgstr "このリモートプロジェクトは利用できません。環境に msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "これにより、後続のメッセージが削除され、チェックポイント スナップショットが利用可能な場合はファイルが復元されます。" +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Poracode から <0>{0} の保存済みパスワードを削除します。" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "このデバイスからスケジュールと最新の結果を削除します。" @@ -9426,14 +9783,34 @@ msgstr "ペアリングトークンをコピーできません。" msgid "Unable to copy Tailscale URL." msgstr "Tailscale URL をコピーできませんでした。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "パスワードをコピーできませんでした。" + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "WSL ワークツリー ディレクトリ \"{path}\" を作成できません" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "保存済みパスワードを削除できませんでした。" + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "worktreeを削除できませんでした。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "保存済みパスワードを編集できませんでした。" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "インポートするブラウザ データが見つかりませんでした。" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "ブラウザ データをインポートできませんでした。" + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9444,10 +9821,18 @@ msgstr "{0}フックをインストールできません。" msgid "Unable to install {0}." msgstr "{0}をインストールできません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "ダウンロードを読み込めませんでした。" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "リモートアクセスのペアリングを読み込めませんでした。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "保存済みパスワードを読み込めませんでした。" + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "スレッドを読み込めません。" @@ -9513,6 +9898,10 @@ msgstr "WSL ディストリビューション「{distro}」のホーム ディ msgid "Unable to restore the SSH connection." msgstr "SSH 接続を復元できません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "パスワードを表示できませんでした。" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "リモートセッションを取り消せませんでした。" @@ -9526,6 +9915,10 @@ msgstr "{0}資格情報を保存できません。" msgid "Unable to save Claude {displayLabel} profile." msgstr "Claudeの{displayLabel}プロファイルを保存できません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "パスワードを保存できませんでした。" + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "{label}を開始できません。" @@ -9593,6 +9986,10 @@ msgstr "リモートアクセスを更新できません。" msgid "Unable to update Tailscale HTTPS." msgstr "Tailscale HTTPS を更新できません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "ダウンロードを更新できませんでした。" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "公開URLを更新できません。" @@ -9895,6 +10292,10 @@ msgstr "{conflict}で使用中" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "ユーザー名" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "組み込みのClaudeモデル一覧を使用しています。" @@ -9968,6 +10369,18 @@ msgstr "変更履歴を表示" msgid "View-only — this connection can't manage projects." msgstr "閲覧のみ — この接続ではプロジェクトを管理できません。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "ビューポートの高さ" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "ビューポートの倍率" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "ビューポートの幅" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10060,11 +10473,16 @@ msgid "Web server" msgstr "Webサーバー" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "ウェブサイト" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "ウェブサイトのオリジン" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "平日" @@ -10345,10 +10763,16 @@ msgstr "WSL ベースフォルダー" msgid "Your name" msgstr "あなたの名前" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "ズーム" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "ズームイン" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "ズームアウト" diff --git a/src/renderer/locales/ko/messages.po b/src/renderer/locales/ko/messages.po index 7e5a9fac7..007653bf4 100644 --- a/src/renderer/locales/ko/messages.po +++ b/src/renderer/locales/ko/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30일" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7일" @@ -618,6 +622,10 @@ msgstr "추가" msgid "Add a local project" msgstr "로컬 프로젝트 추가" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "암호를 추가하거나 다른 브라우저에서 가져오세요." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "모델 추가" msgid "Add one manually or import from another agent." msgstr "직접 추가하거나 다른 에이전트에서 가져오세요." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "암호 추가" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "패턴 추가" @@ -751,6 +763,10 @@ msgstr "즐겨찾기에 추가" msgid "Add to Home Screen" msgstr "홈 화면에 추가" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "고급" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "사용자 정의 기본 URL을 게시합니다(예: 리버스 프록시 또는 터널). 자동으로 설정하려면 비워 두세요." @@ -1301,11 +1317,12 @@ msgstr "차단됨:" msgid "Bold" msgstr "굵게" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "이 페이지 북마크" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "북마크" @@ -1342,6 +1359,10 @@ msgstr "패널로 되돌리기" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "이 패널로 되돌리거나 실행 중인 창으로 이동하세요." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "설치된 브라우저에서 저장된 암호와 쿠키를 가져옵니다." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "찾아보기" @@ -1387,7 +1408,7 @@ msgstr "OpenCode에 브라우저 MCP가 활성화됨" msgid "Browser MCP enabled for this thread" msgstr "이 스레드에 대해 브라우저 MCP가 활성화되었습니다." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "브라우저 메뉴" @@ -1487,6 +1508,8 @@ msgstr "포트를 불러올 수 없습니다" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "포트를 불러올 수 없습니다" msgid "Cancel" msgstr "취소" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "다운로드 취소" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "새 Claude 프로필 취소" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "취소됨" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "취소됨" @@ -1682,6 +1710,10 @@ msgstr "상위 폴더 선택" #~ msgid "Choose an MCP server configuration file" #~ msgstr "MCP 서버 구성 파일 선택" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "내장 브라우저로 가져올 데이터를 선택하세요." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "{env}에 로그인하는 방법을 선택하세요." @@ -1754,22 +1786,34 @@ msgstr "Claude 프로필이 삭제되었습니다." msgid "Cleanup script" msgstr "정리 스크립트" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "인터넷 사용 기록 삭제" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "방문 기록 지우기" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "검색 기록 지우기" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "캐시 지우기" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "캐시 지우기" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "쿠키 지우기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "쿠키 지우기" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "작성기 닫기" msgid "Close connection actions" msgstr "연결 작업 닫기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "기기 툴바 닫기" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "편집기 닫기" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "완료" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "완료됨" @@ -2401,6 +2450,10 @@ msgstr "에이전트가 클릭하거나 입력하는 동안 페어링된 데스 msgid "Conversation" msgstr "대화" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "쿠키" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "모든 Lightcode 데이터를 Poracode로 복사합니다. Poracode가 msgid "Copy code" msgstr "코드 복사" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "현재 URL 복사" @@ -2479,6 +2532,10 @@ msgstr "페어링 링크 복사" msgid "Copy pairing token" msgstr "페어링 토큰 복사" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "암호 복사" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "경로 복사" @@ -2807,6 +2864,7 @@ msgstr "기본 스레드 제거" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "파일 삭제" msgid "Delete permanently" msgstr "영구 삭제" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "저장된 암호 삭제" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "저장된 암호를 삭제할까요?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "일정 삭제" @@ -2998,6 +3064,10 @@ msgstr "데스크톱의 localhost에서 대기 중인 개발 서버입니다." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "개발 전용 재정의. PORACODE DEV 빌드에서만 볼 수 있습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "기기 프리셋" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "컴포저 음성 입력 버튼에 사용되는 장치입니다." msgid "Devices can pair while this desktop is reachable." msgstr "이 데스크톱에 연결할 수 있는 동안 기기를 페어링할 수 있습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "크기:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "직접 연결이 필요합니다" @@ -3164,10 +3238,27 @@ msgstr "완료" msgid "Done · Waiting for your input" msgstr "완료 · 귀하의 의견을 기다리는 중" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "다운로드 실패" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "다운로드 기록" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "이미지 다운로드" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "다운로드 진행률" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "다운로드 중" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "음성 모델 다운로드 중{0}%" msgid "Downloading voice model..." msgstr "음성 모델 다운로드 중..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "다운로드" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "내장 브라우저에서 다운로드한 항목은 이 기록에 저장됩니다." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "파일 편집" msgid "Edit MCP server" msgstr "MCP 서버 편집" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "암호 편집" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "프로필 편집" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "저장된 암호 편집" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "{0}에 대한 파일" msgid "Files matching these globs are hidden from the @file mention search." msgstr "이러한 glob과 일치하는 파일은 @file 멘션 검색에서 숨겨집니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "다운로드한 파일이 여기에 표시됩니다" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "프로젝트별 필터" @@ -3713,6 +3824,11 @@ msgstr "채팅에서 찾기" msgid "Find in diff" msgstr "diff에서 찾기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "페이지에서 찾기" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "터미널에서 찾기" @@ -3877,6 +3993,10 @@ msgstr "빈도" msgid "Friday at 4:00 PM" msgstr "금요일 오후 4:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "출처" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "최신 macOS와 유사하게 시스템 블러 효과(비브런시)로 사이드바에 프로스트 효과를 적용합니다. 지원되지 않는 환경에서는 반투명 색조로 대체됩니다." @@ -4086,7 +4206,7 @@ msgstr "핸들" msgid "Handle" msgstr "핸들" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "강제 새로고침" @@ -4149,6 +4269,10 @@ msgstr "모든 공급자의 모델 선택기에서 사용하지 않는 모델을 msgid "Hide panel" msgstr "패널 숨기기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "암호 숨기기" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "런타임 디버그 패널 숨기기" @@ -4171,7 +4295,7 @@ msgstr "{0}의 스킬 숨기기" msgid "Hide terminal" msgstr "터미널 숨기기" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "기록" @@ -4203,10 +4327,18 @@ msgstr "매시간" msgid "HTTP (streamable)" msgstr "HTTP(스트리밍 가능)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "보호된 브라우저 데이터가 건너뛰어질 수 있음을 이해합니다." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "이미지" msgid "Image preview" msgstr "이미지 미리보기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "가져오기" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "다시 가져오기" @@ -4248,10 +4384,23 @@ msgstr "다시 가져오기" msgid "Import and restart" msgstr "가져오고 다시 시작" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "브라우저 데이터 가져오기" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "가져오기 충돌" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "쿠키 가져오기" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "쿠키 및 암호 가져오기" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "외부 에이전트 스킬 가져오기" msgid "Import external skills" msgstr "외부 스킬 가져오기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "브라우저에서 가져오기" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Lightcode 데이터 가져오기" @@ -4285,10 +4438,18 @@ msgstr "MCP 서버 가져오기" msgid "Import method" msgstr "가져오기 방법" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "암호 가져오기" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "선택 항목 가져오기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "가져오기 원본" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "{destinationProjectName}(으)로 가져오기" @@ -4316,6 +4477,17 @@ msgstr "스킬 {0}개를 가져왔습니다." msgid "Imported 1 skill." msgstr "스킬 1개를 가져왔습니다." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "{0}에서 가져옴" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "가져온 암호: {0}. 가져온 쿠키: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "개선됨" @@ -4469,6 +4641,7 @@ msgstr "에이전트가 어떤 에이전트나 모델에 위임할지 선택할 msgid "Interrupt" msgstr "중단" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "중단됨" @@ -4477,6 +4650,26 @@ msgstr "중단됨" msgid "Interrupted: agent session ended before completion." msgstr "중단됨: 에이전트 세션이 완료되기 전에 종료되었습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "이탤릭체" @@ -4530,6 +4723,14 @@ msgstr "AI가 생성하는 커밋 메시지와 풀 요청 요약에 사용할 msgid "Language the speech model should expect when transcribing composer dictation." msgstr "작성기 받아쓰기를 기록할 때 음성 모델이 예상해야 하는 언어입니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "로컬" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "{branch}에서 가져오기 전에 로컬 변경 사항을 숨겨야 합니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "로컬 암호 보호" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "최장 연속 기록" msgid "Longest task" msgstr "최장 작업" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "브라우저 프로필을 찾는 중…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "개발 서버를 찾는 중…" @@ -4791,6 +5000,10 @@ msgstr "사이드바를 반투명하게 만듭니다 — Windows 11에서는 시 #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "다른 제공자에서 가져온 스킬을 포함하여 전역 및 프로젝트 에이전트 스킬을 관리합니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "암호 관리" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "원격 환경 관리" @@ -5399,8 +5612,8 @@ msgstr "새 일정" #~ msgstr "새 예약 작업" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "새 탭" @@ -5611,6 +5824,10 @@ msgstr "{0}에 대한 차이점이 없습니다." msgid "No diff for {visiblePath}" msgstr "{visiblePath}에는 차이가 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "검색과 일치하는 다운로드가 없습니다" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "이 범위에서 외부 스킬을 찾지 못했습니다." @@ -5630,7 +5847,7 @@ msgstr "\"{0}\"과(와) 일치하는 파일이 없습니다." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "GitHub CLI 계정을 찾을 수 없습니다. <0>gh auth login으로 로그인하거나 <1>복제 URL을 붙여넣으세요." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "아직 기록이 없습니다" @@ -5705,6 +5922,10 @@ msgstr "다른 에이전트가 설치되어 있지 않습니다." msgid "No paired devices yet." msgstr "아직 페어링된 기기가 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "검색과 일치하는 암호가 없습니다" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "패턴이 없습니다." @@ -5771,6 +5992,10 @@ msgstr "아직 실행이 없습니다." msgid "No runtime items yet for this thread." msgstr "이 스레드에는 아직 런타임 항목이 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "저장된 암호가 없습니다" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "아직 연결된 서버가 없습니다." @@ -5808,6 +6033,10 @@ msgstr "이 원격 머신에 지원되는 에이전트가 설치되어 있지 msgid "No supported agents detected" msgstr "지원되는 에이전트가 감지되지 않았습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "이 기기에서 지원되는 브라우저 프로필을 찾지 못했습니다." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "선택된 스레드 없음" @@ -6047,6 +6276,10 @@ msgstr "충돌 해결 도구 열기 위치:" msgid "Open dialog" msgstr "대화상자 열기" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "다운로드한 파일 열기" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "파일 열기" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "암호 문구(선택 사항)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "암호" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "암호를 복사했습니다." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "암호 관리자" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "암호 관리자 섹션" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "암호" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "암호 및 자동 완성" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "암호는 Poracode의 로컬 자격 증명 저장소에 암호화됩니다. 암호 값은 표시하거나 복사하거나 편집할 때만 요청됩니다." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "SSH 개인 키를 붙여 넣으세요." msgid "Pause" msgstr "일시 중지" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "다운로드 일시 중지" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "일시중지됨" @@ -6476,6 +6741,10 @@ msgstr "상단에 고정" msgid "Pinned" msgstr "고정됨" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "이전 실행" msgid "Previous tab" msgstr "이전 탭" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "인쇄" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "개인 키" @@ -6730,6 +7003,10 @@ msgstr "프롬프트" msgid "Proposed plan" msgstr "제안된 계획" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "보호된 브라우저 데이터" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "지원되는 에이전트를 위해 Poracode에서 제공하고 관리합니다." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "작업 제거" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "북마크 삭제" @@ -7143,6 +7421,10 @@ msgstr "연결 제거" msgid "Remove environment variable" msgstr "환경 변수 제거" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "다운로드 기록에서 제거" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "즐겨찾기에서 제거" @@ -7304,6 +7586,10 @@ msgstr "사이드바 프로스트를 기본값으로 재설정" msgid "Reset to default" msgstr "기본값으로 재설정" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "확대/축소 재설정" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "브라우저 서랍 크기 조정" @@ -7337,11 +7623,27 @@ msgstr "분할 크기 조정" msgid "Resize terminal panel" msgstr "터미널 패널 크기 조정" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "뷰포트 크기 조절" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "뷰포트 높이 조절" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "뷰포트 너비 조절" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "리베이스 또는 병합 중 병합 충돌을 해결합니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "반응형" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "복원" @@ -7367,6 +7669,10 @@ msgstr "스레드 복원" msgid "Resume" msgstr "재개" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "다운로드 재개" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "파일 탐색기에 표시" msgid "Reveal in file tree" msgstr "파일 트리에 표시" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "암호 표시" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "오른쪽 패널" msgid "Right-click to switch ring" msgstr "마우스 오른쪽 버튼을 클릭해 링 전환" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "뷰포트 회전" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "런타임 디버그" msgid "Runtime options" msgstr "런타임 옵션" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "에이전트 검색..." msgid "Search branches..." msgstr "브랜치 검색..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "다운로드 검색" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "모델 검색..." msgid "Search or enter address" msgstr "주소 검색 또는 입력" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "암호 검색" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "풀 리퀘스트 검색" @@ -7980,7 +8307,7 @@ msgstr "단축키 설정" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "OS 수준 에이전트 세션에 대해 프로젝트 없는 홈 범위 msgid "Show all" msgstr "모두 표시" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "북마크 막대 표시" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "북마크바 표시" @@ -8054,6 +8381,10 @@ msgstr "작성기 표시" msgid "Show context usage details" msgstr "컨텍스트 사용 세부정보 표시" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "기기 툴바 표시" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "예상 비용 표시" msgid "Show in file explorer" msgstr "파일 탐색기에 표시" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "폴더에서 보기" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "건너뜀" msgid "Slash commands" msgstr "슬래시 명령" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "일부 브라우저 데이터를 건너뛰었습니다. 건너뛴 보호된 항목: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "일부 검사가 실패했거나 보류 중입니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "일부 Chromium 브라우저는 App-Bound Encryption으로 쿠키와 암호를 보호합니다. Poracode는 이 보호를 우회하지 않습니다. 운영 체제에서 제공하지 않는 데이터는 건너뜁니다." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "일부 제공자 폴더를 검사하지 못했습니다. 성공적으로 불러온 스킬은 계속 표시됩니다." @@ -8694,6 +9038,14 @@ msgstr "지원:" msgid "Supports Fast mode" msgstr "고속 모드 지원" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "메모와 할 일 바꾸기" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "Tailscale URL" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "스크린샷 찍기" @@ -9125,6 +9477,11 @@ msgstr "이 원격 프로젝트를 사용할 수 없습니다. 환경에 다시 msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "이렇게 하면 체크포인트 스냅샷을 사용할 수 있을 때 이후 메시지가 제거되고 파일이 복원됩니다." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Poracode에서 <0>{0}의 저장된 암호를 삭제합니다." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "이 기기에서 일정과 최신 결과를 삭제합니다." @@ -9428,14 +9785,34 @@ msgstr "페어링 토큰을 복사할 수 없습니다." msgid "Unable to copy Tailscale URL." msgstr "Tailscale URL을 복사할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "암호를 복사할 수 없습니다." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "WSL 작업 트리 디렉터리 \"{path}\"을(를) 생성할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "저장된 암호를 삭제할 수 없습니다." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "worktree를 삭제할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "저장된 암호를 편집할 수 없습니다." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "가져올 브라우저 데이터를 찾을 수 없습니다." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "브라우저 데이터를 가져올 수 없습니다." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "{0} 후크를 설치할 수 없습니다." msgid "Unable to install {0}." msgstr "{0}을(를) 설치할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "다운로드를 불러올 수 없습니다." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "원격 액세스 페어링을 로드할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "저장된 암호를 불러올 수 없습니다." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "스레드를 불러올 수 없습니다." @@ -9515,6 +9900,10 @@ msgstr "WSL 배포판 \"{distro}\"의 홈 디렉터리를 확인할 수 없습 msgid "Unable to restore the SSH connection." msgstr "SSH 연결을 복원할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "암호를 표시할 수 없습니다." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "원격 세션을 해지할 수 없습니다." @@ -9528,6 +9917,10 @@ msgstr "{0} 자격 증명을 저장할 수 없습니다." msgid "Unable to save Claude {displayLabel} profile." msgstr "Claude {displayLabel} 프로필을 저장할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "암호를 저장할 수 없습니다." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "{label}을(를) 시작할 수 없습니다." @@ -9595,6 +9988,10 @@ msgstr "원격 액세스를 업데이트할 수 없습니다." msgid "Unable to update Tailscale HTTPS." msgstr "Tailscale HTTPS를 업데이트할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "다운로드를 업데이트할 수 없습니다." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "공개 URL을 업데이트할 수 없습니다." @@ -9897,6 +10294,10 @@ msgstr "{conflict}에서 사용 중" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "사용자 이름" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "내장 Claude 모델 목록을 사용합니다." @@ -9970,6 +10371,18 @@ msgstr "변경 내역 보기" msgid "View-only — this connection can't manage projects." msgstr "읽기 전용 — 이 연결로는 프로젝트를 관리할 수 없습니다." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "뷰포트 높이" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "뷰포트 배율" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "뷰포트 너비" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "웹 서버" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "웹사이트" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "웹사이트 출처" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "평일" @@ -10347,10 +10765,16 @@ msgstr "WSL 기본 폴더" msgid "Your name" msgstr "이름" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "확대/축소" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "확대" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "축소" diff --git a/src/renderer/locales/pl/messages.po b/src/renderer/locales/pl/messages.po index df06a2dd7..e3d4e7b42 100644 --- a/src/renderer/locales/pl/messages.po +++ b/src/renderer/locales/pl/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30d" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7d" @@ -618,6 +622,10 @@ msgstr "Dodaj" msgid "Add a local project" msgstr "Dodaj projekt lokalny" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Dodaj hasło lub zaimportuj je z innej przeglądarki." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Dodaj model" msgid "Add one manually or import from another agent." msgstr "Dodaj ręcznie lub zaimportuj z innego agenta." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Dodaj hasło" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Dodaj wzór" @@ -751,6 +763,10 @@ msgstr "Dodaj do ulubionych" msgid "Add to Home Screen" msgstr "Dodaj do ekranu głównego" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Zaawansowane" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Ustaw niestandardowy bazowy URL, np. reverse proxy lub tunel. Pozostaw puste, aby ustawić automatycznie." @@ -1301,11 +1317,12 @@ msgstr "zablokowane:" msgid "Bold" msgstr "Pogrubienie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Dodaj tę stronę do zakładek" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Zakładki" @@ -1342,6 +1359,10 @@ msgstr "Przywróć do panelu" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Przywróć ją do tego panelu lub przejdź do okna, w którym działa." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Przenieś zapisane hasła i pliki cookie z zainstalowanej przeglądarki." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Przeglądaj" @@ -1387,7 +1408,7 @@ msgstr "Przeglądarka MCP włączona dla OpenCode" msgid "Browser MCP enabled for this thread" msgstr "W przeglądarce włączono MCP dla tego wątku" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Menu przeglądarki" @@ -1487,6 +1508,8 @@ msgstr "Nie można wczytać portów" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Nie można wczytać portów" msgid "Cancel" msgstr "Anuluj" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Anuluj pobieranie" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Anuluj nowy profil Claude" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "anulowane" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Anulowano" @@ -1682,6 +1710,10 @@ msgstr "Wybierz folder nadrzędny" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Wybierz plik konfiguracji serwera MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Wybierz dane do przeniesienia do wbudowanej przeglądarki." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Wybierz sposób logowania się do {env}." @@ -1754,22 +1786,34 @@ msgstr "Usunięto profil Claude'a." msgid "Cleanup script" msgstr "Skrypt czyszczący" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Wyczyść dane przeglądania" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Wyczyść historię przeglądania" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Wyczyść historię przeglądania" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Wyczyść pamięć podręczną" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "Wyczyść pamięć podręczną" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Wyczyść pliki cookie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Wyczyść pliki cookie" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "Zamknij kompozytor" msgid "Close connection actions" msgstr "Zamknij akcje połączenia" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Zamknij pasek urządzeń" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Zamknij edytor" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "ukończone" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Ukończono" @@ -2401,6 +2450,10 @@ msgstr "Steruje sparowanym pulpitem, gdy agent klika lub pisze" msgid "Conversation" msgstr "Rozmowa" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Pliki cookie" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Skopiuj wszystkie dane Lightcode do Poracode. Poracode uruchomi się pon msgid "Copy code" msgstr "Skopiuj kod" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Skopiuj bieżący adres URL" @@ -2479,6 +2532,10 @@ msgstr "Skopiuj link parowania" msgid "Copy pairing token" msgstr "Kopiuj token parowania" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Kopiuj hasło" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Skopiuj ścieżkę" @@ -2807,6 +2864,7 @@ msgstr "Domyślne usuwanie wątku" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Usuń plik" msgid "Delete permanently" msgstr "Usuń trwale" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Usuń zapisane hasło" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Usunąć zapisane hasło?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Usuń harmonogram" @@ -2998,6 +3064,10 @@ msgstr "Serwery deweloperskie nasłuchujące na localhost Twojego komputera." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Zastąpienia tylko w fazie rozwojowej. Widoczne tylko w kompilacji PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Profil urządzenia" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Urządzenie używane przez przycisk wprowadzania głosowego kompozytora. msgid "Devices can pair while this desktop is reachable." msgstr "Urządzenia mogą się parować, gdy ten komputer jest osiągalny." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Wymiary:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Wymagane jest bezpośrednie połączenie" @@ -3164,10 +3238,27 @@ msgstr "Gotowe" msgid "Done · Waiting for your input" msgstr "Gotowe · Oczekiwanie na Twoją odpowiedź" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Pobieranie nie powiodło się" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Historia pobierania" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Pobierz obraz" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Postęp pobierania" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Pobieranie" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Pobieranie modelu głosu {0}%" msgid "Downloading voice model..." msgstr "Pobieranie modelu głosu..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Pobrane pliki" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Pliki pobrane we wbudowanej przeglądarce są zapisywane w tej historii." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Edytuj plik" msgid "Edit MCP server" msgstr "Edytuj serwer MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Edytuj hasło" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Edytuj profil" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Edytuj zapisane hasło" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Pliki dla {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Pliki pasujące do tych globów są ukryte przed wyszukiwaniem wzmianek @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Tutaj pojawią się pobrane pliki" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Filtruj według projektu" @@ -3713,6 +3824,11 @@ msgstr "Znajdź w czacie" msgid "Find in diff" msgstr "Znajdź w różnicach" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Znajdź na stronie" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Znajdź w terminalu" @@ -3877,6 +3993,10 @@ msgstr "Częstotliwość" msgid "Friday at 4:00 PM" msgstr "Piątek o 16:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Z" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Zmatowienie paska bocznego systemowym efektem rozmycia (vibrancy), nawiązujące do nowszych wersji macOS. Tam, gdzie nie jest obsługiwane, używa półprzezroczystego odcienia." @@ -4086,7 +4206,7 @@ msgstr "identyfikator" msgid "Handle" msgstr "Identyfikator" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Twarde przeładowanie" @@ -4149,6 +4269,10 @@ msgstr "Ukryj modele, których nie używasz, w selektorze modeli u każdego dost msgid "Hide panel" msgstr "Ukryj panel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Ukryj hasło" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Ukryj panel debugowania środowiska wykonawczego" @@ -4171,7 +4295,7 @@ msgstr "Ukryj umiejętności z {0}" msgid "Hide terminal" msgstr "Ukryj terminal" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Historia" @@ -4203,10 +4327,18 @@ msgstr "Co godzinę" msgid "HTTP (streamable)" msgstr "HTTP (strumieniowy)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Rozumiem, że chronione dane przeglądarki mogą zostać pominięte." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Obraz" msgid "Image preview" msgstr "Podgląd obrazu" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Importuj" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Importuj ponownie" @@ -4248,10 +4384,23 @@ msgstr "Importuj ponownie" msgid "Import and restart" msgstr "Importuj i uruchom ponownie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Importuj dane przeglądarki" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Konflikt importu" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Importuj pliki cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Importuj pliki cookie i hasła" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Importuj umiejętności zewnętrznych agentów" msgid "Import external skills" msgstr "Importuj zewnętrzne umiejętności" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Importuj ze swojej przeglądarki" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Importuj dane Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Importuj serwery MCP" msgid "Import method" msgstr "Metoda importu" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Importuj hasła" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Importuj wybrane" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Źródło importu" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Importuj do {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "Zaimportowano umiejętności: {0}." msgid "Imported 1 skill." msgstr "Zaimportowano 1 umiejętność." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Zaimportowano z {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Liczba zaimportowanych haseł: {0}. Liczba zaimportowanych plików cookie: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Ulepszono" @@ -4469,6 +4641,7 @@ msgstr "Instrukcje, którymi kierują się agenci przy wyborze agenta lub modelu msgid "Interrupt" msgstr "Przerwij" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Przerwano" @@ -4477,6 +4650,26 @@ msgstr "Przerwano" msgid "Interrupted: agent session ended before completion." msgstr "Przerwano: sesja agenta zakończyła się przed jej ukończeniem." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Kursywa" @@ -4530,6 +4723,14 @@ msgstr "Język komunikatów zatwierdzeń i podsumowań żądań ściągnięcia g msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Język, jakiego powinien spodziewać się model mowy podczas transkrypcji dyktowania w polu wprowadzania." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Lokalny" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Lokalne zmiany muszą zostać schowane przed pobraniem z {branch}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Lokalna ochrona haseł" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Najdłuższa seria" msgid "Longest task" msgstr "Najdłuższe zadanie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Wyszukiwanie profili przeglądarek…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Szukanie serwerów deweloperskich…" @@ -4791,6 +5000,10 @@ msgstr "Uczyń pasek boczny półprzezroczystym — systemowy efekt rozmycia w W #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Zarządzaj globalnymi umiejętnościami agentów i umiejętnościami projektu, w tym zaimportowanymi od innych dostawców." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Zarządzaj hasłami" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Zarządzaj środowiskami zdalnymi" @@ -5399,8 +5612,8 @@ msgstr "Nowy harmonogram" #~ msgstr "Nowe zaplanowane zadanie" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Nowa zakładka" @@ -5611,6 +5824,10 @@ msgstr "Brak dostępnych różnic dla {0}" msgid "No diff for {visiblePath}" msgstr "Brak różnicy dla {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Brak pobrań pasujących do wyszukiwania" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Nie znaleziono zewnętrznych umiejętności w tym zakresie." @@ -5630,7 +5847,7 @@ msgstr "Żadne pliki nie pasują do „{0}”." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Nie znaleziono kont GitHub CLI. Zaloguj się za pomocą <0>gh auth login lub <1>wklej sklonowany adres URL." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Brak historii" @@ -5705,6 +5922,10 @@ msgstr "Nie zainstalowano żadnych innych agentów" msgid "No paired devices yet." msgstr "Brak sparowanych urządzeń." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Brak haseł pasujących do wyszukiwania" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Żadnych wzorów." @@ -5771,6 +5992,10 @@ msgstr "Brak uruchomień." msgid "No runtime items yet for this thread." msgstr "Brak jeszcze elementów wykonawczych dla tego wątku." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Brak zapisanych haseł" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Brak połączonych serwerów." @@ -5808,6 +6033,10 @@ msgstr "Na tym komputerze zdalnym nie zainstalowano obsługiwanych agentów. Zai msgid "No supported agents detected" msgstr "Nie wykryto obsługiwanych agentów" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "Na tym urządzeniu nie znaleziono profili obsługiwanych przeglądarek." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Nie wybrano wątku" @@ -6047,6 +6276,10 @@ msgstr "Otwórz narzędzie do rozwiązywania konfliktów w" msgid "Open dialog" msgstr "Otwórz okno dialogowe" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Otwórz pobrany plik" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Otwórz plik" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Fraza hasła (opcjonalnie)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Hasło" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Skopiowano hasło." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Menedżer haseł" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Sekcja menedżera haseł" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Hasła" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Hasła i autouzupełnianie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Hasła są szyfrowane w lokalnym magazynie poświadczeń Poracode. Wartości haseł są pobierane tylko wtedy, gdy je wyświetlasz, kopiujesz lub edytujesz." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Wklej klucz prywatny SSH." msgid "Pause" msgstr "Wstrzymaj" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Wstrzymaj pobieranie" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Wstrzymano" @@ -6476,6 +6741,10 @@ msgstr "Przypnij do góry" msgid "Pinned" msgstr "Przypięty" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Poprzednie uruchomienia" msgid "Previous tab" msgstr "Poprzednia karta" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Drukuj" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Klucz prywatny" @@ -6730,6 +7003,10 @@ msgstr "Prompty" msgid "Proposed plan" msgstr "Proponowany plan" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Chronione dane przeglądarki" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Udostępniany i zarządzany przez Poracode na potrzeby obsługiwanych agentów." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Usuń akcję" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Usuń zakładkę" @@ -7143,6 +7421,10 @@ msgstr "Usuń połączenie" msgid "Remove environment variable" msgstr "Usuń zmienną środowiskową" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Usuń z historii pobierania" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Usuń z ulubionych" @@ -7304,6 +7586,10 @@ msgstr "Przywróć domyślne zmatowienie paska bocznego" msgid "Reset to default" msgstr "Przywróć domyślne" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Zresetuj powiększenie" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Zmień rozmiar szuflady przeglądarki" @@ -7337,11 +7623,27 @@ msgstr "Zmień rozmiar podziału" msgid "Resize terminal panel" msgstr "Zmień rozmiar panelu terminali" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Zmień rozmiar obszaru wyświetlania" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Zmień wysokość obszaru wyświetlania" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Zmień szerokość obszaru wyświetlania" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Rozwiązuje konflikty scalania podczas zmiany bazy lub scalania." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Responsywny" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Przywróć" @@ -7367,6 +7669,10 @@ msgstr "Przywróć wątek" msgid "Resume" msgstr "Wznów" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Wznów pobieranie" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Pokaż w Eksploratorze plików" msgid "Reveal in file tree" msgstr "Pokaż w drzewie plików" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Pokaż hasło" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Prawy panel" msgid "Right-click to switch ring" msgstr "Kliknij prawym przyciskiem, aby przełączyć pierścień" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Obróć obszar wyświetlania" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Debugowanie w czasie wykonywania" msgid "Runtime options" msgstr "Opcje środowiska wykonawczego" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Wyszukaj agentów..." msgid "Search branches..." msgstr "Szukaj gałęzi..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Szukaj w pobranych plikach" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Wyszukaj modele..." msgid "Search or enter address" msgstr "Wyszukaj lub wpisz adres" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Szukaj haseł" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Szukaj żądań ściągnięcia" @@ -7980,7 +8307,7 @@ msgstr "Ustaw skrót" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Wyświetl bezprojektowy zakres główny dla sesji agenta na poziomie sys msgid "Show all" msgstr "Pokaż wszystko" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Pokaż pasek zakładek" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Pokaż pasek zakładek" @@ -8054,6 +8381,10 @@ msgstr "Pokaż pole tworzenia wiadomości" msgid "Show context usage details" msgstr "Pokaż szczegóły użycia kontekstu" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Pokaż pasek urządzeń" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Pokaż szacunkowy koszt" msgid "Show in file explorer" msgstr "Pokaż w eksploratorze plików" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Pokaż w folderze" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Pominięto" msgid "Slash commands" msgstr "Polecenia z ukośnikiem" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Pominięto część danych przeglądarki. Liczba pominiętych chronionych elementów: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Niektóre kontrole kończą się niepowodzeniem lub oczekują na realizację." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Niektóre przeglądarki Chromium chronią pliki cookie i hasła za pomocą mechanizmu App-Bound Encryption. Poracode nie omija tej ochrony. Dane, których system operacyjny nie udostępnia, zostaną pominięte." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Nie udało się przeskanować niektórych folderów dostawców. Pomyślnie wczytane umiejętności są nadal wyświetlane." @@ -8694,6 +9038,14 @@ msgstr "Wsparcie:" msgid "Supports Fast mode" msgstr "Obsługuje tryb szybki" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Zamień notatki i zadania" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "URL Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Zrób zrzut ekranu" @@ -9125,6 +9477,11 @@ msgstr "Ten projekt zdalny jest niedostępny. Połącz środowisko ponownie i sp msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Spowoduje to usunięcie późniejszych wiadomości i przywrócenie plików, gdy dostępna będzie migawka punktu kontrolnego." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Spowoduje to usunięcie zapisanego hasła dla <0>{0} z Poracode." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Usuwa harmonogram i jego ostatni wynik z tego urządzenia." @@ -9428,14 +9785,34 @@ msgstr "Nie można skopiować tokenu parowania." msgid "Unable to copy Tailscale URL." msgstr "Nie można skopiować URL Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Nie udało się skopiować hasła." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Nie można utworzyć katalogu drzewa roboczego WSL „{path}”" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Nie udało się usunąć zapisanego hasła." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Nie można usunąć worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Nie udało się edytować zapisanego hasła." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Nie udało się znaleźć danych przeglądarki do zaimportowania." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Nie udało się zaimportować danych przeglądarki." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "Nie można zainstalować haków {0}." msgid "Unable to install {0}." msgstr "Nie można zainstalować {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Nie udało się wczytać pobranych plików." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Nie można załadować parowania dostępu zdalnego." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Nie udało się wczytać zapisanych haseł." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Nie można załadować wątku." @@ -9515,6 +9900,10 @@ msgstr "Nie można znaleźć katalogu domowego dla dystrybucji WSL „{distro} msgid "Unable to restore the SSH connection." msgstr "Nie można przywrócić połączenia SSH." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Nie udało się wyświetlić hasła." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Nie można unieważnić sesji zdalnej." @@ -9528,6 +9917,10 @@ msgstr "Nie można zapisać danych uwierzytelniających {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "Nie można zapisać profilu Claude {displayLabel}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Nie udało się zapisać hasła." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Nie można uruchomić {label}." @@ -9595,6 +9988,10 @@ msgstr "Nie można zaktualizować dostępu zdalnego." msgid "Unable to update Tailscale HTTPS." msgstr "Nie można zaktualizować Tailscale HTTPS." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Nie udało się zaktualizować pobierania." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Nie można zaktualizować publicznego adresu URL." @@ -9897,6 +10294,10 @@ msgstr "Używany przez {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Nazwa użytkownika" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Używana jest wbudowana lista modeli Claude." @@ -9970,6 +10371,18 @@ msgstr "Zobacz dziennik zmian" msgid "View-only — this connection can't manage projects." msgstr "Tylko do odczytu — to połączenie nie może zarządzać projektami." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Wysokość obszaru wyświetlania" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Skala obszaru wyświetlania" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Szerokość obszaru wyświetlania" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Serwer WWW" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Strona internetowa" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Adres witryny" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Dni robocze" @@ -10347,10 +10765,16 @@ msgstr "Folder bazowy WSL" msgid "Your name" msgstr "Twoje imię" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Powiększenie" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Powiększ" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Pomniejsz" diff --git a/src/renderer/locales/pt-BR/messages.po b/src/renderer/locales/pt-BR/messages.po index 45926af85..2dba55770 100644 --- a/src/renderer/locales/pt-BR/messages.po +++ b/src/renderer/locales/pt-BR/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30d" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7d" @@ -618,6 +622,10 @@ msgstr "Adicionar" msgid "Add a local project" msgstr "Adicione um projeto local" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Adicione uma senha ou importe uma de outro navegador." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Adicionar modelo" msgid "Add one manually or import from another agent." msgstr "Adicione um manualmente ou importe de outro agente." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Adicionar senha" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Adicionar padrão" @@ -751,6 +763,10 @@ msgstr "Adicionar aos favoritos" msgid "Add to Home Screen" msgstr "Adicionar à tela inicial" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Avançado" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Anuncie uma URL base personalizada, por exemplo, um proxy reverso ou túnel. Deixe em branco para automático." @@ -1301,11 +1317,12 @@ msgstr "bloqueado:" msgid "Bold" msgstr "Negrito" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Adicionar esta página aos favoritos" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Favoritos" @@ -1342,6 +1359,10 @@ msgstr "Trazer de volta ao painel" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Traga-o de volta para este painel ou vá para a janela em que ele está sendo executado." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Importe senhas e cookies salvos de um navegador instalado." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Procurar" @@ -1387,7 +1408,7 @@ msgstr "MCP do navegador habilitado para OpenCode" msgid "Browser MCP enabled for this thread" msgstr "MCP do navegador ativado para este tópico" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Menu do navegador" @@ -1487,6 +1508,8 @@ msgstr "Não foi possível carregar as portas" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Não foi possível carregar as portas" msgid "Cancel" msgstr "Cancelar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Cancelar download" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Cancelar novo perfil de Claude" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "cancelado" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Cancelado" @@ -1682,6 +1710,10 @@ msgstr "Escolha uma pasta pai" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Escolher um arquivo de configuração de servidor MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Escolha os dados que deseja transferir para o navegador integrado." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Escolha como fazer login em {env}." @@ -1754,22 +1786,34 @@ msgstr "Perfil de Claude removido." msgid "Cleanup script" msgstr "Script de limpeza" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Limpar dados de navegação" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Limpar histórico de navegação" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Limpar histórico de navegação" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" -msgstr "Limpar Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" +msgstr "Limpar cache" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "Limpar Cache" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Limpar cookies" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Limpar cookies" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "Fechar compositor" msgid "Close connection actions" msgstr "Fechar ações da conexão" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Fechar barra de ferramentas do dispositivo" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Fechar editor" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "concluído" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Concluído" @@ -2401,6 +2450,10 @@ msgstr "Controla a área de trabalho emparelhada enquanto o agente clica ou digi msgid "Conversation" msgstr "Conversa" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookies" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Copie todos os dados do Lightcode para o Poracode. O Poracode será rein msgid "Copy code" msgstr "Copiar código" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Copiar URL atual" @@ -2479,6 +2532,10 @@ msgstr "Copiar link de pareamento" msgid "Copy pairing token" msgstr "Copiar token de pareamento" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Copiar senha" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Copiar caminho" @@ -2807,6 +2864,7 @@ msgstr "Remoção de thread padrão" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Excluir arquivo" msgid "Delete permanently" msgstr "Excluir permanentemente" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Excluir senha salva" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Excluir senha salva?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Excluir agendamento" @@ -2998,6 +3064,10 @@ msgstr "Servidores de desenvolvimento escutando no localhost do seu desktop." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Substituições apenas de desenvolvimento. Visível apenas na compilação PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Predefinição de dispositivo" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Dispositivo usado pelo botão de entrada de voz do compositor." msgid "Devices can pair while this desktop is reachable." msgstr "Dispositivos podem parear enquanto este desktop estiver acessível." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Dimensões:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Conexão direta necessária" @@ -3164,10 +3238,27 @@ msgstr "Concluído" msgid "Done · Waiting for your input" msgstr "Concluído · Aguardando sua resposta" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Falha no download" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Histórico de downloads" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Baixar imagem" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Progresso do download" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Baixando" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Baixando modelo de voz {0}%" msgid "Downloading voice model..." msgstr "Baixando modelo de voz..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Downloads" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Os downloads do navegador integrado são salvos neste histórico." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Editar arquivo" msgid "Edit MCP server" msgstr "Editar servidor MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Editar senha" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Editar perfil" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Editar senha salva" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Arquivos para {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Os arquivos que correspondem a esses globs ficam ocultos na pesquisa de menção @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Os arquivos que você baixar aparecerão aqui" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Filtrar por projeto" @@ -3713,6 +3824,11 @@ msgstr "Localizar no chat" msgid "Find in diff" msgstr "Localizar na comparação" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Localizar na página" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Localizar no terminal" @@ -3877,6 +3993,10 @@ msgstr "Frequência" msgid "Friday at 4:00 PM" msgstr "Sexta-feira às 16:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "De" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Aplica o efeito fosco à barra lateral com o material de desfoque do sistema (vibrância), à semelhança do macOS recente. Recorre a um tom translúcido onde não houver suporte." @@ -4086,7 +4206,7 @@ msgstr "identificador" msgid "Handle" msgstr "Identificador" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Recarregar forçado" @@ -4149,6 +4269,10 @@ msgstr "Oculte os modelos que você não usa no seletor de modelos de todos os p msgid "Hide panel" msgstr "Ocultar painel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Ocultar senha" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Ocultar painel de depuração de tempo de execução" @@ -4171,7 +4295,7 @@ msgstr "Ocultar skills de {0}" msgid "Hide terminal" msgstr "Ocultar terminal" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Histórico" @@ -4203,10 +4327,18 @@ msgstr "A cada hora" msgid "HTTP (streamable)" msgstr "HTTP (com streaming)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Entendo que dados protegidos do navegador podem ser ignorados." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Imagem" msgid "Image preview" msgstr "Visualização da imagem" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Importar" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Importar novamente" @@ -4248,10 +4384,23 @@ msgstr "Importar novamente" msgid "Import and restart" msgstr "Importar e reiniciar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Importar dados do navegador" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Conflito de importação" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Importar cookies" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Importar cookies e senhas" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Importar skills de agentes externos" msgid "Import external skills" msgstr "Importar skills externas" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Importar do seu navegador" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Importar dados do Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Importar servidores MCP" msgid "Import method" msgstr "Método de importação" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Importar senhas" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Importar selecionadas" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Origem da importação" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Importar para {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "{0} skills importadas." msgid "Imported 1 skill." msgstr "1 skill importada." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Importado de {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Senhas importadas: {0}. Cookies importados: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Melhorado" @@ -4469,6 +4641,7 @@ msgstr "Instruções que os agentes seguem ao escolher para qual agente ou model msgid "Interrupt" msgstr "Interromper" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Interrompida" @@ -4477,6 +4650,26 @@ msgstr "Interrompida" msgid "Interrupted: agent session ended before completion." msgstr "Interrompida: a sessão do agente terminou antes da conclusão." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Itálico" @@ -4530,6 +4723,14 @@ msgstr "Idioma das mensagens de commit e dos resumos de pull request gerados por msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Idioma que o modelo de fala deve esperar ao transcrever o ditado do compositor." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Locais" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "As alterações locais precisam ser armazenadas (stash) antes de fazer pull de {branch}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Proteção local de senhas" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Maior sequência" msgid "Longest task" msgstr "Tarefa mais longa" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Procurando perfis de navegador…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Procurando servidores de desenvolvimento…" @@ -4791,6 +5000,10 @@ msgstr "Torna a barra lateral translúcida — o material de desfoque do sistema #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Gerencie skills globais e de projeto dos agentes, inclusive skills importadas de outros provedores." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Gerenciar senhas" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Gerenciar ambientes remotos" @@ -5399,8 +5612,8 @@ msgstr "Novo agendamento" #~ msgstr "Nova tarefa agendada" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Nova guia" @@ -5611,6 +5824,10 @@ msgstr "Nenhuma diferença disponível para {0}" msgid "No diff for {visiblePath}" msgstr "Sem diferença para {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Nenhum download corresponde à sua pesquisa" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Nenhuma skill externa foi encontrada neste escopo." @@ -5630,7 +5847,7 @@ msgstr "Nenhum arquivo corresponde a \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Nenhuma conta GitHub CLI encontrada. Faça login com <0>gh auth login ou <1>cole um URL clone." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Ainda não há histórico" @@ -5705,6 +5922,10 @@ msgstr "Nenhum outro agente instalado" msgid "No paired devices yet." msgstr "Ainda não há dispositivos pareados." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Nenhuma senha corresponde à sua pesquisa" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Sem padrões." @@ -5771,6 +5992,10 @@ msgstr "Ainda não há execuções." msgid "No runtime items yet for this thread." msgstr "Ainda não há itens de tempo de execução para este tópico." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Nenhuma senha salva" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Nenhum servidor conectado ainda." @@ -5808,6 +6033,10 @@ msgstr "Nenhum agente compatível está instalado nesta máquina remota. Instale msgid "No supported agents detected" msgstr "Nenhum agente compatível detectado" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "Nenhum perfil de navegador compatível foi encontrado neste dispositivo." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Nenhuma thread selecionada" @@ -6047,6 +6276,10 @@ msgstr "Abrir resolvedor de conflitos em" msgid "Open dialog" msgstr "Abrir caixa de diálogo" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Abrir arquivo baixado" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Abrir arquivo" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Frase secreta (opcional)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Senha" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Senha copiada." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Gerenciador de senhas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Seção do gerenciador de senhas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Senhas" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Senhas e preenchimento automático" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "As senhas são criptografadas no armazenamento local de credenciais do Poracode. Os valores das senhas só são solicitados quando você as revela, copia ou edita." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Cole a chave privada SSH." msgid "Pause" msgstr "Pausar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Pausar download" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Pausado" @@ -6476,6 +6741,10 @@ msgstr "Fixar no topo" msgid "Pinned" msgstr "Fixado" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Execuções anteriores" msgid "Previous tab" msgstr "Guia anterior" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Imprimir" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Chave privada" @@ -6730,6 +7003,10 @@ msgstr "Prompts" msgid "Proposed plan" msgstr "Plano proposto" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Dados protegidos do navegador" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Fornecido e gerenciado pelo Poracode para agentes compatíveis." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Remover ação" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Remover favorito" @@ -7143,6 +7421,10 @@ msgstr "Remover conexão" msgid "Remove environment variable" msgstr "Remover variável de ambiente" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Remover do histórico de downloads" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Remover dos favoritos" @@ -7304,6 +7586,10 @@ msgstr "Redefinir efeito fosco da barra lateral para o padrão" msgid "Reset to default" msgstr "Redefinir para o padrão" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Redefinir zoom" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Redimensionar gaveta do navegador" @@ -7337,11 +7623,27 @@ msgstr "Redimensionar divisão" msgid "Resize terminal panel" msgstr "Redimensionar painel terminal" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Redimensionar área de visualização" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Redimensionar a altura da área de visualização" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Redimensionar a largura da área de visualização" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Resolve conflitos de mesclagem durante rebase ou mesclagem." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Responsivo" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Restaurar" @@ -7367,6 +7669,10 @@ msgstr "Restaurar tópico" msgid "Resume" msgstr "Retomar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Retomar download" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Revelar no Explorador de Arquivos" msgid "Reveal in file tree" msgstr "Revelar na árvore de arquivos" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Revelar senha" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Painel direito" msgid "Right-click to switch ring" msgstr "Clique com o botão direito para trocar o anel" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Girar área de visualização" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Depuração de tempo de execução" msgid "Runtime options" msgstr "Opções de tempo de execução" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Procurar agentes..." msgid "Search branches..." msgstr "Pesquisar branches..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Pesquisar downloads" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Pesquisar modelos..." msgid "Search or enter address" msgstr "Pesquise ou digite o endereço" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Pesquisar senhas" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Buscar pull requests" @@ -7980,7 +8307,7 @@ msgstr "Definir atalho" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Mostre um escopo inicial sem projeto para sessões de agente no nível d msgid "Show all" msgstr "Mostrar tudo" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Mostrar barra de favoritos" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Mostrar barra de favoritos" @@ -8054,6 +8381,10 @@ msgstr "Mostrar compositor" msgid "Show context usage details" msgstr "Mostrar detalhes de uso do contexto" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Mostrar barra de ferramentas do dispositivo" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Mostrar custo estimado" msgid "Show in file explorer" msgstr "Mostrar no explorador de arquivos" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Mostrar na pasta" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Ignorado" msgid "Slash commands" msgstr "Comandos de barra" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Alguns dados do navegador foram ignorados. Itens protegidos ignorados: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Algumas verificações estão falhando ou pendentes." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Alguns navegadores Chromium protegem cookies e senhas com Criptografia App-Bound. O Poracode não contorna essa proteção. Os dados que o sistema operacional não disponibilizar serão ignorados." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Não foi possível verificar algumas pastas de provedores. As skills carregadas com sucesso continuam sendo exibidas." @@ -8694,6 +9038,14 @@ msgstr "Suporte:" msgid "Supports Fast mode" msgstr "Compatível com o modo rápido" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Alternar entre notas e tarefas" @@ -8809,7 +9161,7 @@ msgstr "HTTPS do Tailscale" msgid "Tailscale URL" msgstr "URL do Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Tirar captura de tela" @@ -9125,6 +9477,11 @@ msgstr "Este projeto remoto não está disponível. Reconecte o ambiente e tente msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Isso remove mensagens posteriores e restaura arquivos quando um instantâneo do ponto de verificação estiver disponível." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Isso remove do Poracode a senha salva para <0>{0}." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Isso remove o agendamento e seu resultado mais recente deste dispositivo." @@ -9428,14 +9785,34 @@ msgstr "Não foi possível copiar o token de pareamento." msgid "Unable to copy Tailscale URL." msgstr "Não foi possível copiar a URL do Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Não foi possível copiar a senha." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Não foi possível criar o diretório da árvore de trabalho WSL \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Não foi possível excluir a senha salva." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Não foi possível excluir o worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Não foi possível editar a senha salva." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Não foi possível encontrar dados do navegador para importar." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Não foi possível importar os dados do navegador." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "Não foi possível instalar os ganchos do {0}." msgid "Unable to install {0}." msgstr "Não foi possível instalar {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Não foi possível carregar os downloads." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Não foi possível carregar o pareamento de acesso remoto." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Não foi possível carregar as senhas salvas." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Não foi possível carregar a thread." @@ -9515,6 +9900,10 @@ msgstr "Não foi possível resolver o diretório inicial da distribuição WSL \ msgid "Unable to restore the SSH connection." msgstr "Não foi possível restaurar a conexão SSH." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Não foi possível revelar a senha." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Não foi possível revogar a sessão remota." @@ -9528,6 +9917,10 @@ msgstr "Não foi possível salvar as credenciais do {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "Não foi possível salvar o perfil {displayLabel} do Claude." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Não foi possível salvar a senha." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Não foi possível iniciar {label}." @@ -9595,6 +9988,10 @@ msgstr "Não foi possível atualizar o acesso remoto." msgid "Unable to update Tailscale HTTPS." msgstr "Não foi possível atualizar o HTTPS do Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Não foi possível atualizar o download." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Não foi possível atualizar a URL pública." @@ -9897,6 +10294,10 @@ msgstr "Usado por {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Nome de usuário" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Usando a lista de modelos integrada do Claude." @@ -9970,6 +10371,18 @@ msgstr "Ver o registro de alterações" msgid "View-only — this connection can't manage projects." msgstr "Somente leitura — esta conexão não pode gerenciar projetos." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Altura da área de visualização" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Escala da área de visualização" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Largura da área de visualização" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Servidor web" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Site" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Origem do site" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Dias úteis" @@ -10347,10 +10765,16 @@ msgstr "Pasta base do WSL" msgid "Your name" msgstr "Seu nome" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Zoom" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Aumentar zoom" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Diminuir zoom" diff --git a/src/renderer/locales/ru/messages.po b/src/renderer/locales/ru/messages.po index 3a28ffbcf..0f32633e6 100644 --- a/src/renderer/locales/ru/messages.po +++ b/src/renderer/locales/ru/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30 дн" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7 дн" @@ -618,6 +622,10 @@ msgstr "Добавить" msgid "Add a local project" msgstr "Добавить локальный проект" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Добавьте пароль или импортируйте его из другого браузера." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Добавить модель" msgid "Add one manually or import from another agent." msgstr "Добавьте сервер вручную или импортируйте его из другого агента." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Добавить пароль" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Добавить шаблон" @@ -751,6 +763,10 @@ msgstr "Добавить в избранное" msgid "Add to Home Screen" msgstr "Добавить на главный экран" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Дополнительно" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Укажите собственный базовый URL, например обратный прокси или туннель. Оставьте пустым для автоматического режима." @@ -1301,11 +1317,12 @@ msgstr "заблокировано:" msgid "Bold" msgstr "Полужирный" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Добавить страницу в закладки" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Закладки" @@ -1342,6 +1359,10 @@ msgstr "Вернуть на панель" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Верните его на эту панель или перейдите к окну, в котором он запущен." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Перенесите сохранённые пароли и cookie из установленного браузера." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Обзор" @@ -1387,7 +1408,7 @@ msgstr "Browser MCP включён для OpenCode" msgid "Browser MCP enabled for this thread" msgstr "Browser MCP включён для этого треда" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Меню браузера" @@ -1487,6 +1508,8 @@ msgstr "Не удалось загрузить порты" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Не удалось загрузить порты" msgid "Cancel" msgstr "Отмена" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Отменить загрузку" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Отменить новый профиль Claude" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "отменено" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Отменено" @@ -1682,6 +1710,10 @@ msgstr "Выберите родительскую папку" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Выбрать файл конфигурации сервера MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Выберите данные для переноса во встроенный браузер." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Выберите способ входа для {env}." @@ -1754,21 +1786,33 @@ msgstr "Профиль Claude удалён." msgid "Cleanup script" msgstr "Скрипт очистки" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Очистить данные браузера" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Очистить историю просмотров" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Очистить историю просмотров" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Очистить кэш" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" -msgstr "Очистить cookies" +#~ msgid "Clear Cache" +#~ msgstr "Очистить кэш" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" +msgstr "Очистить cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Очистить cookies" #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx @@ -1859,6 +1903,10 @@ msgstr "Закрыть Composer" msgid "Close connection actions" msgstr "Закрыть действия с подключением" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Закрыть панель устройств" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Закрыть редактор" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "завершено" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Завершено" @@ -2401,6 +2450,10 @@ msgstr "Управляет сопряжённым рабочим столом, msgid "Conversation" msgstr "Разговор" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookie" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Скопируйте все данные Lightcode в Poracode. Poracode msgid "Copy code" msgstr "Копировать код" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Копировать текущий URL" @@ -2479,6 +2532,10 @@ msgstr "Скопировать ссылку для сопряжения" msgid "Copy pairing token" msgstr "Скопировать токен привязки" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Копировать пароль" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Копировать путь" @@ -2807,6 +2864,7 @@ msgstr "Удаление тредов по умолчанию" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Удалить файл" msgid "Delete permanently" msgstr "Удалить безвозвратно" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Удалить сохранённый пароль" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Удалить сохранённый пароль?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Удалить расписание" @@ -2998,6 +3064,10 @@ msgstr "Серверы разработки, слушающие localhost ваш msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Переопределения только для разработки. Видны только в сборке PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Профиль устройства" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Устройство, используемое кнопкой голос msgid "Devices can pair while this desktop is reachable." msgstr "Устройства могут подключаться, пока этот рабочий стол доступен." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Размеры:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Требуется прямое подключение" @@ -3164,10 +3238,27 @@ msgstr "Готово" msgid "Done · Waiting for your input" msgstr "Готово · Ожидается ваш ввод" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Ошибка загрузки" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "История загрузок" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Скачать изображение" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Ход загрузки" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Загрузка" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Загрузка голосовой модели {0}%" msgid "Downloading voice model..." msgstr "Загрузка голосовой модели..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Загрузки" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Загрузки из встроенного браузера сохраняются в этой истории." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Изменить файл" msgid "Edit MCP server" msgstr "Изменить сервер MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Изменить пароль" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Редактировать профиль" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Изменить сохранённый пароль" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Файлы для {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Файлы, соответствующие этим glob-шаблонам, скрыты из поиска упоминаний @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Здесь появятся скачанные файлы" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Фильтр по проекту" @@ -3713,6 +3824,11 @@ msgstr "Найти в чате" msgid "Find in diff" msgstr "Найти в diff" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Найти на странице" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Найти в терминале" @@ -3877,6 +3993,10 @@ msgstr "Частота" msgid "Friday at 4:00 PM" msgstr "В пятницу в 16:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Из" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Сделать боковую панель матовой за счёт системного размытия (vibrancy) в духе свежих версий macOS. При отсутствии поддержки используется полупрозрачный оттенок." @@ -4086,7 +4206,7 @@ msgstr "никнейм" msgid "Handle" msgstr "Никнейм" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Жёсткая перезагрузка" @@ -4149,6 +4269,10 @@ msgstr "Скрывает модели, которые вы не использу msgid "Hide panel" msgstr "Скрыть панель" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Скрыть пароль" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Скрыть панель отладки среды выполнения" @@ -4171,7 +4295,7 @@ msgstr "Скрыть навыки из {0}" msgid "Hide terminal" msgstr "Скрыть терминал" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "История" @@ -4203,10 +4327,18 @@ msgstr "Ежечасно" msgid "HTTP (streamable)" msgstr "HTTP (потоковый)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Я понимаю, что защищённые данные браузера могут быть пропущены." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Изображение" msgid "Image preview" msgstr "Предпросмотр изображения" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Импортировать" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Импортировать снова" @@ -4248,10 +4384,23 @@ msgstr "Импортировать снова" msgid "Import and restart" msgstr "Импортировать и перезапустить" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Импортировать данные браузера" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Конфликт импорта" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Импортировать cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Импортировать cookie и пароли" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Импортировать навыки внешних агентов" msgid "Import external skills" msgstr "Импортировать внешние навыки" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Импортировать из вашего браузера" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Импортировать данные Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Импортировать серверы MCP" msgid "Import method" msgstr "Способ импорта" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Импортировать пароли" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Импортировать выбранные" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Источник импорта" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Импортировать в {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "Импортировано навыков: {0}." msgid "Imported 1 skill." msgstr "Импортирован 1 навык." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Импортировано из {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Импортировано паролей: {0}. Импортировано cookie: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Улучшено" @@ -4469,6 +4641,7 @@ msgstr "Инструкции, которым следуют агенты при msgid "Interrupt" msgstr "Прервать" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Прервано" @@ -4477,6 +4650,26 @@ msgstr "Прервано" msgid "Interrupted: agent session ended before completion." msgstr "Прервано: сессия агента завершилась до окончания." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Курсив" @@ -4530,6 +4723,14 @@ msgstr "Язык сообщений коммитов и сводок pull reques msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Язык, который должна ожидать модель распознавания речи при транскрибировании диктовки в поле ввода." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Ноутбук" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Ноутбук L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Локальный" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Перед выполнением pull из {branch} локальные изменения нужно поместить в stash" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Локальная защита паролей" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Самая длинная серия" msgid "Longest task" msgstr "Самая длинная задача" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Поиск профилей браузера…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Поиск серверов разработки…" @@ -4791,6 +5000,10 @@ msgstr "Сделать боковую панель полупрозрачной #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Управляйте глобальными навыками агентов и навыками проекта, включая импортированные из других провайдеров." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Управление паролями" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Управление удалёнными средами" @@ -5399,8 +5612,8 @@ msgstr "Новое расписание" #~ msgstr "Новая запланированная задача" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Новая вкладка" @@ -5611,6 +5824,10 @@ msgstr "Нет доступного diff для {0}" msgid "No diff for {visiblePath}" msgstr "Нет diff для {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Нет загрузок, соответствующих поиску" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "В этой области не найдено внешних навыков." @@ -5630,7 +5847,7 @@ msgstr "Нет файлов, соответствующих \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Учётные записи GitHub CLI не найдены. Войдите с помощью <0>gh auth login или <1>вставьте URL для клонирования." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Истории пока нет" @@ -5705,6 +5922,10 @@ msgstr "Других установленных агентов нет" msgid "No paired devices yet." msgstr "Пока нет сопряженных устройств." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Нет паролей, соответствующих поиску" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Нет шаблонов." @@ -5771,6 +5992,10 @@ msgstr "Запусков ещё нет." msgid "No runtime items yet for this thread." msgstr "Для этого треда пока нет runtime-элементов." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Нет сохранённых паролей" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Пока нет подключённых серверов." @@ -5808,6 +6033,10 @@ msgstr "На этом удалённом компьютере не устано msgid "No supported agents detected" msgstr "Поддерживаемые агенты не обнаружены" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "На этом устройстве не найдены профили поддерживаемых браузеров." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Поток не выбран" @@ -6047,6 +6276,10 @@ msgstr "Открыть средство разрешения конфликто msgid "Open dialog" msgstr "Открывать диалог" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Открыть скачанный файл" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Открыть файл" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Кодовая фраза (необязательно)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Пароль" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Пароль скопирован." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Менеджер паролей" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Раздел менеджера паролей" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Пароли" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Пароли и автозаполнение" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Пароли шифруются в локальном хранилище учётных данных Poracode. Значения паролей запрашиваются только при их отображении, копировании или изменении." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Вставьте закрытый ключ SSH." msgid "Pause" msgstr "Приостановить" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Приостановить загрузку" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Приостановлено" @@ -6476,6 +6741,10 @@ msgstr "Закрепить вверху" msgid "Pinned" msgstr "Закреплено" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Предыдущие запуски" msgid "Previous tab" msgstr "Предыдущая вкладка" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Печать" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Закрытый ключ" @@ -6730,6 +7003,10 @@ msgstr "Запросы" msgid "Proposed plan" msgstr "Предложенный план" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Защищённые данные браузера" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Предоставляется и управляется Poracode для поддерживаемых агентов." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Удалить действие" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Удалить закладку" @@ -7143,6 +7421,10 @@ msgstr "Удалить подключение" msgid "Remove environment variable" msgstr "Удалить переменную окружения" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Удалить из истории загрузок" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Удалить из избранного" @@ -7304,6 +7586,10 @@ msgstr "Сбросить матовость боковой панели к зн msgid "Reset to default" msgstr "Сбросить к значению по умолчанию" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Сбросить масштаб" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Изменить размер панели браузера" @@ -7337,11 +7623,27 @@ msgstr "Изменить размер разделения" msgid "Resize terminal panel" msgstr "Изменить размер панели терминала" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Изменить размер области просмотра" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Изменить высоту области просмотра" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Изменить ширину области просмотра" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Разрешает конфликты слияния во время rebase или слияния." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Адаптивный" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Восстановить" @@ -7367,6 +7669,10 @@ msgstr "Восстановить тред" msgid "Resume" msgstr "Возобновить" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Возобновить загрузку" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Показать в Проводнике" msgid "Reveal in file tree" msgstr "Показать в дереве файлов" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Показать пароль" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Панель справа" msgid "Right-click to switch ring" msgstr "Щелкните правой кнопкой, чтобы переключить кольцо" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Повернуть область просмотра" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Отладка среды выполнения" msgid "Runtime options" msgstr "Параметры среды выполнения" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Поиск агентов..." msgid "Search branches..." msgstr "Поиск веток..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Поиск загрузок" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Поиск моделей..." msgid "Search or enter address" msgstr "Поиск или ввод адреса" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Поиск паролей" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Искать pull request" @@ -7980,7 +8307,7 @@ msgstr "Назначить сочетание клавиш" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Показывать домашнюю область без проект msgid "Show all" msgstr "Показать всё" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Показать панель закладок" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Показать панель закладок" @@ -8054,6 +8381,10 @@ msgstr "Показать Composer" msgid "Show context usage details" msgstr "Показать детали использования контекста" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Показать панель устройств" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Показывать оценочную стоимость" msgid "Show in file explorer" msgstr "Показать в проводнике" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Показать в папке" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Пропущено" msgid "Slash commands" msgstr "Slash-команды" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Часть данных браузера была пропущена. Пропущено защищённых элементов: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Некоторые проверки не пройдены или ожидают выполнения." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Некоторые браузеры Chromium защищают cookie и пароли с помощью App-Bound Encryption. Poracode не обходит эту защиту. Данные, к которым операционная система не предоставляет доступ, будут пропущены." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Некоторые папки провайдеров не удалось просканировать. Успешно загруженные навыки по-прежнему отображаются." @@ -8694,6 +9038,14 @@ msgstr "Поддержка:" msgid "Supports Fast mode" msgstr "Поддерживает быстрый режим" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Поменять местами заметки и задачи" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "URL Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Сделать снимок экрана" @@ -9125,6 +9477,11 @@ msgstr "Этот удалённый проект недоступен. Пере msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Это удаляет последующие сообщения и восстанавливает файлы, если доступен снимок контрольной точки." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Сохранённый пароль для <0>{0} будет удалён из Poracode." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Удаляет расписание и его последний результат с этого устройства." @@ -9428,14 +9785,34 @@ msgstr "Не удалось скопировать токен привязки." msgid "Unable to copy Tailscale URL." msgstr "Не удалось скопировать URL Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Не удалось скопировать пароль." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Не удалось создать каталог worktree WSL \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Не удалось удалить сохранённый пароль." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Не удалось удалить worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Не удалось изменить сохранённый пароль." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Не удалось найти данные браузера для импорта." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Не удалось импортировать данные браузера." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "Не удалось установить хуки {0}." msgid "Unable to install {0}." msgstr "Не удалось установить {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Не удалось загрузить список загрузок." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Не удалось загрузить сопряжение удаленного доступа." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Не удалось загрузить сохранённые пароли." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Не удалось загрузить поток." @@ -9515,6 +9900,10 @@ msgstr "Не удалось определить домашний каталог msgid "Unable to restore the SSH connection." msgstr "Не удалось восстановить SSH-подключение." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Не удалось показать пароль." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Не удалось отозвать удаленную сессию." @@ -9528,6 +9917,10 @@ msgstr "Не удалось сохранить учётные данные {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "Не удалось сохранить профиль Claude {displayLabel}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Не удалось сохранить пароль." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Не удалось запустить {label}." @@ -9595,6 +9988,10 @@ msgstr "Не удалось обновить удаленный доступ." msgid "Unable to update Tailscale HTTPS." msgstr "Не удалось обновить Tailscale HTTPS." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Не удалось обновить загрузку." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Не удалось обновить публичный URL." @@ -9897,6 +10294,10 @@ msgstr "Используется командой {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Имя пользователя" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Используется встроенный список моделей Claude." @@ -9970,6 +10371,18 @@ msgstr "Открыть список изменений" msgid "View-only — this connection can't manage projects." msgstr "Только просмотр — это подключение не может управлять проектами." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Высота области просмотра" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Масштаб области просмотра" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Ширина области просмотра" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Веб-сервер" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Веб-сайт" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Адрес сайта" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "По будням" @@ -10347,10 +10765,16 @@ msgstr "Базовая папка WSL" msgid "Your name" msgstr "Ваше имя" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Масштаб" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Увеличить" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Уменьшить" diff --git a/src/renderer/locales/tr/messages.po b/src/renderer/locales/tr/messages.po index 888b96b26..59944836b 100644 --- a/src/renderer/locales/tr/messages.po +++ b/src/renderer/locales/tr/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30g" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7g" @@ -618,6 +622,10 @@ msgstr "Ekle" msgid "Add a local project" msgstr "Yerel bir proje ekle" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Bir parola ekleyin veya başka bir tarayıcıdan içe aktarın." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Model ekle" msgid "Add one manually or import from another agent." msgstr "Birini elle ekleyin veya başka bir ajandan içe aktarın." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Parola ekle" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Desen ekle" @@ -751,6 +763,10 @@ msgstr "Favorilere ekle" msgid "Add to Home Screen" msgstr "Ana Ekrana ekle" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Gelişmiş" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Özel bir temel URL duyurun, örn. bir ters proxy veya tünel. Otomatik için boş bırakın." @@ -1301,11 +1317,12 @@ msgstr "engellendi:" msgid "Bold" msgstr "Kalın" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Bu sayfayı yer imlerine ekle" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Yer imleri" @@ -1342,6 +1359,10 @@ msgstr "Panele geri getir" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Bu panele geri getirin veya çalıştığı pencereye geçin." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Kayıtlı parolaları ve çerezleri yüklü bir tarayıcıdan aktarın." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Gözat" @@ -1387,7 +1408,7 @@ msgstr "OpenCode için tarayıcı MCP'si etkinleştirildi" msgid "Browser MCP enabled for this thread" msgstr "Bu konu için Tarayıcı MCP'si etkinleştirildi" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Tarayıcı menüsü" @@ -1487,6 +1508,8 @@ msgstr "Portlar yüklenemedi" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Portlar yüklenemedi" msgid "Cancel" msgstr "İptal" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "İndirmeyi iptal et" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Yeni Claude profilini iptal et" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "iptal edildi" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "İptal edildi" @@ -1682,6 +1710,10 @@ msgstr "Bir ana klasör seçin" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Bir MCP sunucusu yapılandırma dosyası seçin" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Yerleşik tarayıcıya aktarılacak verileri seçin." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "{env} için nasıl oturum açacağınızı seçin." @@ -1754,21 +1786,33 @@ msgstr "Claude profili kaldırıldı." msgid "Cleanup script" msgstr "Temizleme komut dosyası" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Tarama verilerini temizle" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Tarama geçmişini temizle" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Tarama Geçmişini Temizle" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" +msgstr "Önbelleği temizle" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" -msgstr "Önbelleği Temizle" +#~ msgid "Clear Cache" +#~ msgstr "Önbelleği Temizle" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" +msgstr "Çerezleri temizle" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" -msgstr "Çerezleri Temizle" +#~ msgid "Clear Cookies" +#~ msgstr "Çerezleri Temizle" #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx @@ -1859,6 +1903,10 @@ msgstr "Yazma alanını kapat" msgid "Close connection actions" msgstr "Bağlantı eylemlerini kapat" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Cihaz araç çubuğunu kapat" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Düzenleyiciyi kapat" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "tamamlandı" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Tamamlandı" @@ -2401,6 +2450,10 @@ msgstr "Ajan tıklarken veya yazarken eşleştirilmiş masaüstünü kontrol ede msgid "Conversation" msgstr "Konuşma" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Çerezler" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Tüm Lightcode verilerini Poracode'a kopyalayın. Poracode yeniden başl msgid "Copy code" msgstr "Kodu kopyala" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Mevcut URL'yi Kopyala" @@ -2479,6 +2532,10 @@ msgstr "Eşleştirme bağlantısını kopyala" msgid "Copy pairing token" msgstr "Eşleştirme token'ını kopyala" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Parolayı kopyala" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Yolu Kopyala" @@ -2807,6 +2864,7 @@ msgstr "Varsayılan konu kaldırma" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Dosyayı sil" msgid "Delete permanently" msgstr "Kalıcı olarak sil" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Kayıtlı parolayı sil" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Kayıtlı parola silinsin mi?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Zamanlamayı sil" @@ -2998,6 +3064,10 @@ msgstr "Masaüstünüzün localhost'unda dinleyen geliştirme sunucuları." msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Yalnızca geliştirme amaçlı geçersiz kılmalar. Yalnızca PORACODE DEV yapısında görünür." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Cihaz ön ayarı" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Oluşturucu ses giriş düğmesi tarafından kullanılan cihaz." msgid "Devices can pair while this desktop is reachable." msgstr "Cihazlar bu masaüstüne erişilebildiği sürece eşleşebilir." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Boyutlar:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Doğrudan bağlantı gerekiyor" @@ -3164,10 +3238,27 @@ msgstr "Bitti" msgid "Done · Waiting for your input" msgstr "Bitti · Girişinizi bekliyorum" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "İndirme başarısız oldu" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "İndirme geçmişi" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Görseli indir" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "İndirme ilerlemesi" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "İndiriliyor" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Ses modeli indiriliyor {0}%" msgid "Downloading voice model..." msgstr "Ses modeli indiriliyor..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "İndirilenler" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Yerleşik tarayıcıdan indirilenler bu geçmişe kaydedilir." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Dosyayı düzenle" msgid "Edit MCP server" msgstr "MCP sunucusunu düzenle" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Parolayı düzenle" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Profili düzenle" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Kayıtlı parolayı düzenle" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "{0} için dosyalar" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Bu glob'larla eşleşen dosyalar, @file bahsetme aramasında gizlenir." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "İndirdiğiniz dosyalar burada görünür" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Projeye göre filtrele" @@ -3713,6 +3824,11 @@ msgstr "Sohbette bul" msgid "Find in diff" msgstr "Farkta bul" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Sayfada bul" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Terminalde bul" @@ -3877,6 +3993,10 @@ msgstr "Sıklık" msgid "Friday at 4:00 PM" msgstr "Cuma 16:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Kaynak" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Kenar çubuğunu, son macOS sürümlerini andıran sistem bulanıklık materyaliyle (vibrancy) buzlu cama dönüştürün. Desteklenmediğinde yarı saydam bir tona geri döner." @@ -4086,7 +4206,7 @@ msgstr "kullanıcı adı" msgid "Handle" msgstr "Kullanıcı adı" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Sert Yeniden Yükleme" @@ -4149,6 +4269,10 @@ msgstr "Kullanmadığınız modelleri her sağlayıcıdaki model seçiciden gizl msgid "Hide panel" msgstr "Paneli gizle" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Parolayı gizle" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Çalışma zamanı hata ayıklama panelini gizle" @@ -4171,7 +4295,7 @@ msgstr "{0} becerilerini gizle" msgid "Hide terminal" msgstr "Terminali gizle" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Geçmiş" @@ -4203,10 +4327,18 @@ msgstr "Saatlik" msgid "HTTP (streamable)" msgstr "HTTP (akış destekli)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Korunan tarayıcı verilerinin atlanabileceğini anlıyorum." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Resim" msgid "Image preview" msgstr "Resim önizlemesi" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "İçe aktar" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Tekrar içe aktar" @@ -4248,10 +4384,23 @@ msgstr "Tekrar içe aktar" msgid "Import and restart" msgstr "İçe aktar ve yeniden başlat" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Tarayıcı verilerini içe aktar" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "İçe aktarma çakışması" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Çerezleri içe aktar" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Çerezleri ve parolaları içe aktar" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Harici aracı becerilerini içe aktar" msgid "Import external skills" msgstr "Harici becerileri içe aktar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Tarayıcınızdan içe aktar" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Lightcode verilerini içe aktar" @@ -4285,10 +4438,18 @@ msgstr "MCP sunucularını içe aktar" msgid "Import method" msgstr "İçe aktarma yöntemi" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Parolaları içe aktar" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Seçilenleri içe aktar" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "İçe aktarma kaynağı" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "{destinationProjectName} projesine içe aktar" @@ -4316,6 +4477,17 @@ msgstr "{0} beceri içe aktarıldı." msgid "Imported 1 skill." msgstr "1 beceri içe aktarıldı." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "{0} kaynağından içe aktarıldı" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "İçe aktarılan parolalar: {0}. İçe aktarılan çerezler: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "İyileştirildi" @@ -4469,6 +4641,7 @@ msgstr "Aracıların hangi aracıya veya modele devredeceğini seçerken izledi msgid "Interrupt" msgstr "Kes" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Kesintiye uğradı" @@ -4477,6 +4650,26 @@ msgstr "Kesintiye uğradı" msgid "Interrupted: agent session ended before completion." msgstr "Kesintiye uğradı: Ajan oturumu tamamlanmadan sona erdi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "italik" @@ -4530,6 +4723,14 @@ msgstr "Yapay zeka tarafından oluşturulan commit mesajları ve çekme isteği msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Yazma alanı diktesini yazıya dökerken konuşma modelinin beklemesi gereken dil." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Dizüstü bilgisayar" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Dizüstü bilgisayar L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Yerel" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "{branch}'dan çekilmeden önce yerel değişikliklerin saklanması gerekiyor" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Yerel parola koruması" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "En uzun seri" msgid "Longest task" msgstr "En uzun görev" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Tarayıcı profilleri aranıyor…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Geliştirme sunucuları aranıyor…" @@ -4791,6 +5000,10 @@ msgstr "Kenar çubuğunu yarı saydam yapın — Windows 11'de sistem bulanıkl #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Diğer sağlayıcılardan içe aktarılanlar dahil olmak üzere genel ve proje aracı becerilerini yönetin." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Parolaları yönet" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Uzak ortamları yönet" @@ -5399,8 +5612,8 @@ msgstr "Yeni zamanlama" #~ msgstr "Yeni zamanlanmış görev" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Yeni sekme" @@ -5611,6 +5824,10 @@ msgstr "{0} için fark mevcut değil" msgid "No diff for {visiblePath}" msgstr "{visiblePath} için fark yok" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Aramanızla eşleşen indirme yok" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Bu kapsamda harici beceri bulunamadı." @@ -5630,7 +5847,7 @@ msgstr "\"{0}\" ile eşleşen dosya yok." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "GitHub CLI hesabı bulunamadı. <0>gh auth login ile oturum açın veya <1>bir klon URL'si yapıştırın." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Henüz geçmiş yok" @@ -5705,6 +5922,10 @@ msgstr "Başka aracı yüklü değil" msgid "No paired devices yet." msgstr "Henüz eşleştirilmiş cihaz yok." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Aramanızla eşleşen parola yok" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Desen yok." @@ -5771,6 +5992,10 @@ msgstr "Henüz çalıştırma yok." msgid "No runtime items yet for this thread." msgstr "Bu konu için henüz çalışma zamanı öğesi yok." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Kayıtlı parola yok" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Henüz bağlı sunucu yok." @@ -5808,6 +6033,10 @@ msgstr "Bu uzak makinede desteklenen bir aracı yüklü değil. Bir iş parçac msgid "No supported agents detected" msgstr "Desteklenen aracı algılanmadı" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "Bu cihazda desteklenen bir tarayıcı profili bulunamadı." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "İş parçacığı seçilmedi" @@ -6047,6 +6276,10 @@ msgstr "Çakışma çözümleyiciyi şurada açın" msgid "Open dialog" msgstr "İletişim kutusunu aç" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "İndirilen dosyayı aç" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Dosyayı Aç" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Parola ifadesi (isteğe bağlı)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Parola" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Parola kopyalandı." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Parola yöneticisi" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Parola yöneticisi bölümü" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Parolalar" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Parolalar ve otomatik doldurma" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Parolalar, Poracode'un yerel kimlik bilgisi deposunda şifrelenir. Parola değerleri yalnızca onları gösterdiğinizde, kopyaladığınızda veya düzenlediğinizde istenir." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "SSH özel anahtarını yapıştırın." msgid "Pause" msgstr "Duraklat" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "İndirmeyi duraklat" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Duraklatıldı" @@ -6476,6 +6741,10 @@ msgstr "En üste sabitle" msgid "Pinned" msgstr "Sabitlendi" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Önceki çalıştırmalar" msgid "Previous tab" msgstr "Önceki sekme" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Yazdır" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Özel anahtar" @@ -6730,6 +7003,10 @@ msgstr "İstemler" msgid "Proposed plan" msgstr "Önerilen plan" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Korunan tarayıcı verileri" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Desteklenen aracılar için Poracode tarafından sağlanır ve yönetilir." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Eylemi kaldır" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Yer imini kaldır" @@ -7143,6 +7421,10 @@ msgstr "Bağlantıyı kaldır" msgid "Remove environment variable" msgstr "Ortam değişkenini kaldır" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "İndirme geçmişinden kaldır" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Favorilerden kaldır" @@ -7304,6 +7586,10 @@ msgstr "Kenar çubuğu buzlu cam efektini varsayılana sıfırla" msgid "Reset to default" msgstr "Varsayılana sıfırla" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Yakınlaştırmayı sıfırla" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Tarayıcı çekmecesini yeniden boyutlandır" @@ -7337,11 +7623,27 @@ msgstr "Bölmeyi yeniden boyutlandır" msgid "Resize terminal panel" msgstr "Terminal panelini yeniden boyutlandır" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Görüntü alanını yeniden boyutlandır" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Görüntü alanının yüksekliğini değiştir" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Görüntü alanının genişliğini değiştir" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Yeniden temel alma veya birleştirme sırasındaki birleştirme çakışmalarını çözer." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Duyarlı" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Geri yükle" @@ -7367,6 +7669,10 @@ msgstr "Konuyu geri yükle" msgid "Resume" msgstr "Sürdür" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "İndirmeyi sürdür" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Dosya Gezgini'nde Göster" msgid "Reveal in file tree" msgstr "Dosya ağacında göster" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Parolayı göster" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Sağ panel" msgid "Right-click to switch ring" msgstr "Halkayı değiştirmek için sağ tıklayın" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Görüntü alanını döndür" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Çalışma zamanı hata ayıklaması" msgid "Runtime options" msgstr "Çalışma zamanı seçenekleri" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Aracıları ara..." msgid "Search branches..." msgstr "Şube ara..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "İndirilenlerde ara" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Modelleri ara..." msgid "Search or enter address" msgstr "Adres arayın veya girin" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Parolalarda ara" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Çekme isteklerinde ara" @@ -7980,7 +8307,7 @@ msgstr "Kısayol belirle" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "İşletim sistemi düzeyindeki aracı oturumları için projesiz bir Ana msgid "Show all" msgstr "Tümünü göster" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Yer imi çubuğunu göster" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Yer İşareti Çubuğunu Göster" @@ -8054,6 +8381,10 @@ msgstr "Composer'ı göster" msgid "Show context usage details" msgstr "Bağlam kullanım ayrıntılarını göster" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Cihaz araç çubuğunu göster" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Tahmini maliyeti göster" msgid "Show in file explorer" msgstr "Dosya gezgininde göster" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Klasörde göster" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Atlandı" msgid "Slash commands" msgstr "Eğik çizgi komutları" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Bazı tarayıcı verileri atlandı. Atlanan korunan öğe sayısı: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Bazı kontroller başarısız oluyor veya beklemede." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Bazı Chromium tarayıcıları çerezleri ve parolaları App-Bound Encryption ile korur. Poracode bu korumayı aşmaz. İşletim sisteminin erişime açmadığı veriler atlanır." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Bazı sağlayıcı klasörleri taranamadı. Başarıyla yüklenen beceriler gösterilmeye devam ediyor." @@ -8694,6 +9038,14 @@ msgstr "Destek:" msgid "Supports Fast mode" msgstr "Hızlı modu destekler" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Notları ve yapılacak işleri değiştir" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "Tailscale URL'si" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Ekran Görüntüsü Al" @@ -9125,6 +9477,11 @@ msgstr "Bu uzak proje kullanılamıyor. Ortamı yeniden bağlayıp tekrar deneyi msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Bu, daha sonraki mesajları kaldırır ve bir denetim noktası anlık görüntüsü mevcut olduğunda dosyaları geri yükler." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Bu işlem, <0>{0} için kaydedilen parolayı Poracode'dan kaldırır." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Zamanlamayı ve en son sonucunu bu cihazdan kaldırır." @@ -9428,14 +9785,34 @@ msgstr "Eşleştirme token'ı kopyalanamadı." msgid "Unable to copy Tailscale URL." msgstr "Tailscale URL'si kopyalanamadı." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Parola kopyalanamadı." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "\"{path}\" WSL çalışma ağacı dizini oluşturulamıyor" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Kayıtlı parola silinemedi." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Worktree silinemedi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Kayıtlı parola düzenlenemedi." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "İçe aktarılacak tarayıcı verileri bulunamadı." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Tarayıcı verileri içe aktarılamadı." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "{0} kancaları yüklenemiyor." msgid "Unable to install {0}." msgstr "{0} yüklenemiyor." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "İndirilenler yüklenemedi." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Uzaktan erişim eşleştirmesi yüklenemedi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Kayıtlı parolalar yüklenemedi." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "İş parçacığı yüklenemiyor." @@ -9515,6 +9900,10 @@ msgstr "\"{distro}\" WSL dağıtımı için giriş dizini çözümlenemiyor" msgid "Unable to restore the SSH connection." msgstr "SSH bağlantısı geri yüklenemedi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Parola gösterilemedi." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Uzak oturum iptal edilemedi." @@ -9528,6 +9917,10 @@ msgstr "{0} kimlik bilgileri kaydedilemiyor." msgid "Unable to save Claude {displayLabel} profile." msgstr "Claude {displayLabel} profili kaydedilemedi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Parola kaydedilemedi." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "{label} başlatılamıyor." @@ -9595,6 +9988,10 @@ msgstr "Uzaktan erişim güncellenemedi." msgid "Unable to update Tailscale HTTPS." msgstr "Tailscale HTTPS güncellenemedi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "İndirme güncellenemedi." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Genel URL güncellenemedi." @@ -9897,6 +10294,10 @@ msgstr "{conflict} tarafından kullanılıyor" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Kullanıcı adı" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Yerleşik Claude model listesi kullanılıyor." @@ -9970,6 +10371,18 @@ msgstr "Değişiklik günlüğünü görüntüle" msgid "View-only — this connection can't manage projects." msgstr "Yalnızca görüntüleme — bu bağlantı projeleri yönetemez." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Görüntü alanı yüksekliği" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Görüntü alanı ölçeği" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Görüntü alanı genişliği" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Web sunucusu" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Web sitesi" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Web sitesi adresi" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Hafta içi" @@ -10347,10 +10765,16 @@ msgstr "WSL temel klasörü" msgid "Your name" msgstr "Adınız" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Yakınlaştırma" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Yakınlaştır" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Uzaklaştır" diff --git a/src/renderer/locales/uk/messages.po b/src/renderer/locales/uk/messages.po index b37be18c0..a968ec5de 100644 --- a/src/renderer/locales/uk/messages.po +++ b/src/renderer/locales/uk/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30 дн" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7 дн" @@ -618,6 +622,10 @@ msgstr "Додати" msgid "Add a local project" msgstr "Додати локальний проєкт" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Додайте пароль або імпортуйте його з іншого браузера." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Додати модель" msgid "Add one manually or import from another agent." msgstr "Додайте сервер вручну або імпортуйте його з іншого агента." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Додати пароль" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Додати шаблон" @@ -751,6 +763,10 @@ msgstr "Додати до обраного" msgid "Add to Home Screen" msgstr "Додати на головний екран" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Додатково" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Оголосіть власний базовий URL, наприклад зворотний проксі або тунель. Залиште порожнім для автоматичного режиму." @@ -1301,11 +1317,12 @@ msgstr "заблоковано:" msgid "Bold" msgstr "Жирний" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Додати сторінку в закладки" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Закладки" @@ -1342,6 +1359,10 @@ msgstr "Повернути на панель" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Поверніть його на цю панель або перейдіть до вікна, де він запущений." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Перенесіть збережені паролі та файли cookie зі встановленого браузера." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Огляд" @@ -1387,7 +1408,7 @@ msgstr "Browser MCP увімкнено для OpenCode" msgid "Browser MCP enabled for this thread" msgstr "Browser MCP увімкнено для цього треду" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Меню браузера" @@ -1487,6 +1508,8 @@ msgstr "Не вдалося завантажити порти" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Не вдалося завантажити порти" msgid "Cancel" msgstr "Скасувати" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Скасувати завантаження" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Скасувати новий профіль Claude" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "скасовано" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Скасовано" @@ -1682,6 +1710,10 @@ msgstr "Виберіть батьківську папку" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Вибрати файл конфігурації сервера MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Виберіть дані для перенесення до вбудованого браузера." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Виберіть спосіб входу для {env}." @@ -1754,21 +1786,33 @@ msgstr "Профіль Claude видалено." msgid "Cleanup script" msgstr "Скрипт очищення" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Очистити дані браузера" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Очистити історію перегляду" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Очистити історію переглядів" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Очистити кеш" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" -msgstr "Очистити cookies" +#~ msgid "Clear Cache" +#~ msgstr "Очистити кеш" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" +msgstr "Очистити файли cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Очистити cookies" #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx @@ -1859,6 +1903,10 @@ msgstr "Закрити Composer" msgid "Close connection actions" msgstr "Закрити дії підключення" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Закрити панель пристроїв" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Закрити редактор" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "завершено" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Завершено" @@ -2401,6 +2450,10 @@ msgstr "Керує спареним робочим столом, поки аге msgid "Conversation" msgstr "Розмова" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Файли cookie" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Скопіюйте всі дані Lightcode до Poracode. Poracode п msgid "Copy code" msgstr "Копіювати код" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Копіювати поточний URL" @@ -2479,6 +2532,10 @@ msgstr "Скопіювати посилання для спарення" msgid "Copy pairing token" msgstr "Скопіювати токен підключення" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Копіювати пароль" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Копіювати шлях" @@ -2807,6 +2864,7 @@ msgstr "Типове видалення треду" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Видалити файл" msgid "Delete permanently" msgstr "Видалити назавжди" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Видалити збережений пароль" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Видалити збережений пароль?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Видалити розклад" @@ -2998,6 +3064,10 @@ msgstr "Сервери розробки, що слухають localhost ваш msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Перевизначення лише для розробки. Видимі лише у збірці PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Профіль пристрою" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Пристрій, який використовує кнопка гол msgid "Devices can pair while this desktop is reachable." msgstr "Пристрої можуть сполучатися, доки цей робочий стіл доступний." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Розміри:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Потрібне пряме підключення" @@ -3164,10 +3238,27 @@ msgstr "Завершено" msgid "Done · Waiting for your input" msgstr "Готово · Очікується ваш ввід" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Помилка завантаження" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Історія завантажень" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Завантажити зображення" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Перебіг завантаження" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Триває завантаження" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Завантаження голосової моделі {0}%" msgid "Downloading voice model..." msgstr "Завантаження голосової моделі..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Завантаження" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Завантаження з вбудованого браузера зберігаються в цій історії." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Змінити файл" msgid "Edit MCP server" msgstr "Редагувати сервер MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Змінити пароль" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Редагувати профіль" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Змінити збережений пароль" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Файли для {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Файли, що відповідають цим glob-шаблонам, приховані з пошуку згадок @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Тут з’являться завантажені вами файли" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Фільтр за проєктом" @@ -3713,6 +3824,11 @@ msgstr "Пошук у чаті" msgid "Find in diff" msgstr "Пошук у diff" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Знайти на сторінці" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Пошук у терміналі" @@ -3877,6 +3993,10 @@ msgstr "Частота" msgid "Friday at 4:00 PM" msgstr "У п’ятницю о 16:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Звідки" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Зробіть бічну панель матовою за допомогою системного розмиття (vibrancy) у стилі сучасної macOS. Там, де це не підтримується, застосовується напівпрозоре тонування." @@ -4086,7 +4206,7 @@ msgstr "нік" msgid "Handle" msgstr "Нік" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Жорстке перезавантаження" @@ -4149,6 +4269,10 @@ msgstr "Приховує моделі, які ви не використовує msgid "Hide panel" msgstr "Сховати панель" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Приховати пароль" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Сховати панель налагодження середовища виконання" @@ -4171,7 +4295,7 @@ msgstr "Приховати навички з {0}" msgid "Hide terminal" msgstr "Сховати термінал" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Історія" @@ -4203,10 +4327,18 @@ msgstr "Щогодини" msgid "HTTP (streamable)" msgstr "HTTP (потоковий)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Я розумію, що захищені дані браузера можуть бути пропущені." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Зображення" msgid "Image preview" msgstr "Попередній перегляд зображення" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Імпортувати" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Імпортувати знову" @@ -4248,10 +4384,23 @@ msgstr "Імпортувати знову" msgid "Import and restart" msgstr "Імпортувати й перезапустити" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Імпортувати дані браузера" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Конфлікт імпорту" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Імпортувати файли cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Імпортувати файли cookie та паролі" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Імпортувати навички зовнішніх агентів" msgid "Import external skills" msgstr "Імпортувати зовнішні навички" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Імпортувати з вашого браузера" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Імпортувати дані Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Імпортувати сервери MCP" msgid "Import method" msgstr "Спосіб імпорту" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Імпортувати паролі" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Імпортувати вибрані" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Джерело імпорту" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Імпортувати до {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "Імпортовано навичок: {0}." msgid "Imported 1 skill." msgstr "Імпортовано 1 навичку." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Імпортовано з {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Імпортовано паролів: {0}. Імпортовано файлів cookie: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Покращено" @@ -4469,6 +4641,7 @@ msgstr "Інструкції, яких дотримуються агенти, о msgid "Interrupt" msgstr "Перервати" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Перервано" @@ -4477,6 +4650,26 @@ msgstr "Перервано" msgid "Interrupted: agent session ended before completion." msgstr "Перервано: сесія агента завершилася до завершення." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Курсив" @@ -4530,6 +4723,14 @@ msgstr "Мова для згенерованих ШІ повідомлень к msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Мова, яку модель розпізнавання мовлення має очікувати під час транскрибування диктування в полі вводу." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Ноутбук" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Ноутбук L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Локальний" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Перед виконанням pull з {branch} локальні зміни потрібно помістити у stash" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Локальний захист паролів" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Найдовша серія" msgid "Longest task" msgstr "Найдовше завдання" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Пошук профілів браузера…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Пошук серверів розробки…" @@ -4791,6 +5000,10 @@ msgstr "Зробіть бічну панель напівпрозорою — с #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Керуйте глобальними навичками агентів і навичками проєкту, зокрема імпортованими від інших провайдерів." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Керування паролями" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Керування віддаленими середовищами" @@ -5399,8 +5612,8 @@ msgstr "Новий розклад" #~ msgstr "Нове заплановане завдання" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Нова вкладка" @@ -5611,6 +5824,10 @@ msgstr "Немає доступного diff для {0}" msgid "No diff for {visiblePath}" msgstr "Немає diff для {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Немає завантажень, що відповідають пошуку" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "У цій області не знайдено зовнішніх навичок." @@ -5630,7 +5847,7 @@ msgstr "Немає файлів, що відповідають \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Облікові записи GitHub CLI не знайдено. Увійдіть за допомогою <0>gh auth login або <1>вставте URL для клонування." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Історії ще немає" @@ -5705,6 +5922,10 @@ msgstr "Інших встановлених агентів немає" msgid "No paired devices yet." msgstr "Ще немає спарених пристроїв." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Немає паролів, що відповідають пошуку" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Немає шаблонів." @@ -5771,6 +5992,10 @@ msgstr "Запусків ще немає." msgid "No runtime items yet for this thread." msgstr "Для цього треду ще немає runtime-елементів." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Немає збережених паролів" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Ще немає підключених серверів." @@ -5808,6 +6033,10 @@ msgstr "На цьому віддаленому комп’ютері не вст msgid "No supported agents detected" msgstr "Підтримуваних агентів не виявлено" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "На цьому пристрої не знайдено профілів підтримуваних браузерів." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Потік не вибрано" @@ -6047,6 +6276,10 @@ msgstr "Відкрити засіб розв'язання конфліктів msgid "Open dialog" msgstr "Відкрити діалог" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Відкрити завантажений файл" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Відкрити файл" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Парольна фраза (необов’язково)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Пароль" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Пароль скопійовано." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Менеджер паролів" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Розділ менеджера паролів" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Паролі" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Паролі й автозаповнення" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Паролі зашифровано в локальному сховищі облікових даних Poracode. Значення паролів запитуються лише тоді, коли ви їх показуєте, копіюєте або редагуєте." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Вставте закритий ключ SSH." msgid "Pause" msgstr "Призупинити" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Призупинити завантаження" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Призупинено" @@ -6476,6 +6741,10 @@ msgstr "Закріпити вгорі" msgid "Pinned" msgstr "Закріплено" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Попередні запуски" msgid "Previous tab" msgstr "Попередня вкладка" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "Друк" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Закритий ключ" @@ -6730,6 +7003,10 @@ msgstr "Запити" msgid "Proposed plan" msgstr "Запропонований план" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Захищені дані браузера" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Надається та керується Poracode для підтримуваних агентів." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Видалити дію" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Видалити закладку" @@ -7143,6 +7421,10 @@ msgstr "Видалити підключення" msgid "Remove environment variable" msgstr "Видалити змінну середовища" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Видалити з історії завантажень" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Видалити з обраного" @@ -7304,6 +7586,10 @@ msgstr "Скинути матовість бічної панелі до тип msgid "Reset to default" msgstr "Скинути до типового" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Скинути масштаб" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Змінити розмір панелі браузера" @@ -7337,11 +7623,27 @@ msgstr "Змінити розмір розділення" msgid "Resize terminal panel" msgstr "Змінити розмір панелі термінала" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Змінити розмір області перегляду" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Змінити висоту області перегляду" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Змінити ширину області перегляду" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Розв'язує конфлікти злиття під час rebase або злиття." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Адаптивний" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Відновити" @@ -7367,6 +7669,10 @@ msgstr "Відновити тред" msgid "Resume" msgstr "Продовжити" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Продовжити завантаження" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Показати в Провіднику" msgid "Reveal in file tree" msgstr "Показати в дереві файлів" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Показати пароль" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Права панель" msgid "Right-click to switch ring" msgstr "Клацніть правою кнопкою, щоб перемкнути кільце" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Повернути область перегляду" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Налагодження середовища виконання" msgid "Runtime options" msgstr "Параметри середовища виконання" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Пошук агентів..." msgid "Search branches..." msgstr "Пошук гілок..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Пошук завантажень" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Пошук моделей..." msgid "Search or enter address" msgstr "Пошук або введення адреси" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Пошук паролів" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Шукати pull request" @@ -7980,7 +8307,7 @@ msgstr "Призначити комбінацію клавіш" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Показувати домашню область без проєкту msgid "Show all" msgstr "Показати все" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Показати панель закладок" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Показати панель закладок" @@ -8054,6 +8381,10 @@ msgstr "Показати Composer" msgid "Show context usage details" msgstr "Показати деталі використання контексту" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Показати панель пристроїв" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Показувати орієнтовну вартість" msgid "Show in file explorer" msgstr "Показати в провіднику файлів" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Показати в папці" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Пропущено" msgid "Slash commands" msgstr "Slash-команди" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Деякі дані браузера було пропущено. Пропущено захищених елементів: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Деякі перевірки не пройдені або очікують виконання." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Деякі браузери Chromium захищають файли cookie та паролі за допомогою App-Bound Encryption. Poracode не обходить цей захист. Дані, до яких операційна система не надає доступу, буде пропущено." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Деякі папки провайдерів не вдалося просканувати. Успішно завантажені навички все одно відображаються." @@ -8694,6 +9038,14 @@ msgstr "Підтримка:" msgid "Supports Fast mode" msgstr "Підтримує швидкий режим" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Поміняти місцями нотатки та завдання" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "URL Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Зробити знімок екрана" @@ -9125,6 +9477,11 @@ msgstr "Цей віддалений проєкт недоступний. Пер msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Це видаляє наступні повідомлення та відновлює файли, якщо доступний знімок контрольної точки." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Збережений пароль для <0>{0} буде видалено з Poracode." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Видаляє розклад і його останній результат із цього пристрою." @@ -9428,14 +9785,34 @@ msgstr "Не вдалося скопіювати токен підключенн msgid "Unable to copy Tailscale URL." msgstr "Не вдалося скопіювати URL Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Не вдалося скопіювати пароль." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Не вдалося створити каталог worktree WSL \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Не вдалося видалити збережений пароль." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Не вдалося видалити worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Не вдалося змінити збережений пароль." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Не вдалося знайти дані браузера для імпорту." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Не вдалося імпортувати дані браузера." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "Не вдалося встановити хуки {0}." msgid "Unable to install {0}." msgstr "Не вдалося встановити {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Не вдалося завантажити список завантажень." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Не вдалося завантажити спарення віддаленого доступу." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Не вдалося завантажити збережені паролі." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Не удалось загрузить поток." @@ -9515,6 +9900,10 @@ msgstr "Не вдалося визначити домашній каталог msgid "Unable to restore the SSH connection." msgstr "Не вдалося відновити SSH-підключення." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Не вдалося показати пароль." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Не вдалося відкликати віддалену сесію." @@ -9528,6 +9917,10 @@ msgstr "Не вдалося зберегти облікові дані {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "Не вдалося зберегти профіль Claude {displayLabel}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Не вдалося зберегти пароль." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Не вдалося запустити {label}." @@ -9595,6 +9988,10 @@ msgstr "Не вдалося оновити віддалений доступ." msgid "Unable to update Tailscale HTTPS." msgstr "Не вдалося оновити Tailscale HTTPS." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Не вдалося оновити завантаження." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Не вдалося оновити публічний URL." @@ -9897,6 +10294,10 @@ msgstr "Використовується для {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Ім’я користувача" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Використовується вбудований список моделей Claude." @@ -9970,6 +10371,18 @@ msgstr "Відкрити список змін" msgid "View-only — this connection can't manage projects." msgstr "Лише перегляд — це підключення не може керувати проєктами." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Висота області перегляду" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Масштаб області перегляду" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Ширина області перегляду" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Веб-сервер" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Вебсайт" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Адреса вебсайту" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "У будні" @@ -10347,10 +10765,16 @@ msgstr "Базова папка WSL" msgid "Your name" msgstr "Ваше ім'я" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Масштаб" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Збільшити" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Зменшити" diff --git a/src/renderer/locales/vi/messages.po b/src/renderer/locales/vi/messages.po index f8392a14f..e42b68b19 100644 --- a/src/renderer/locales/vi/messages.po +++ b/src/renderer/locales/vi/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30 ngày" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7 ngày" @@ -618,6 +622,10 @@ msgstr "Thêm vào" msgid "Add a local project" msgstr "Thêm một dự án cục bộ" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "Thêm mật khẩu hoặc nhập từ một trình duyệt khác." + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "Thêm mô hình" msgid "Add one manually or import from another agent." msgstr "Thêm thủ công hoặc nhập từ một tác nhân khác." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "Thêm mật khẩu" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "Thêm mẫu" @@ -751,6 +763,10 @@ msgstr "Thêm vào mục yêu thích" msgid "Add to Home Screen" msgstr "Thêm vào màn hình chính" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "Nâng cao" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "Công bố một URL cơ sở tùy chỉnh, ví dụ một reverse proxy hoặc tunnel. Để trống để dùng tự động." @@ -1301,11 +1317,12 @@ msgstr "bị chặn:" msgid "Bold" msgstr "Đậm" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "Đánh dấu trang này" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "Dấu trang" @@ -1342,6 +1359,10 @@ msgstr "Đưa về bảng điều khiển" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "Đưa trở lại bảng điều khiển này, hoặc chuyển đến cửa sổ đang chạy." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "Chuyển mật khẩu và cookie đã lưu từ một trình duyệt đã cài đặt." + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "Duyệt" @@ -1387,7 +1408,7 @@ msgstr "MCP trình duyệt được bật cho OpenCode" msgid "Browser MCP enabled for this thread" msgstr "Đã bật MCP trình duyệt cho chủ đề này" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "Trình đơn trình duyệt" @@ -1487,6 +1508,8 @@ msgstr "Không thể tải danh sách cổng" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "Không thể tải danh sách cổng" msgid "Cancel" msgstr "Hủy bỏ" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "Hủy tải xuống" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "Hủy tạo hồ sơ Claude mới" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "đã hủy" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "Đã hủy" @@ -1682,6 +1710,10 @@ msgstr "Chọn một thư mục cha" #~ msgid "Choose an MCP server configuration file" #~ msgstr "Chọn tệp cấu hình máy chủ MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "Chọn dữ liệu cần chuyển sang trình duyệt tích hợp." + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "Chọn cách đăng nhập cho {env}." @@ -1754,22 +1786,34 @@ msgstr "Hồ sơ Claude đã bị xóa." msgid "Cleanup script" msgstr "Tập lệnh dọn dẹp" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "Xóa dữ liệu duyệt web" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "Xóa lịch sử duyệt web" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "Xóa lịch sử duyệt web" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "Xóa bộ nhớ đệm" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "Xóa bộ nhớ đệm" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "Xóa cookie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "Xóa cookie" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "Đóng trình soạn thảo" msgid "Close connection actions" msgstr "Đóng các thao tác kết nối" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "Đóng thanh công cụ thiết bị" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "Đóng trình chỉnh sửa" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "hoàn thành" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "Đã hoàn tất" @@ -2401,6 +2450,10 @@ msgstr "Điều khiển máy tính đã ghép nối khi agent nhấp hoặc gõ" msgid "Conversation" msgstr "Cuộc trò chuyện" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookie" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "Sao chép toàn bộ dữ liệu Lightcode vào Poracode. Poracode sẽ msgid "Copy code" msgstr "Sao chép mã" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "Sao chép URL hiện tại" @@ -2479,6 +2532,10 @@ msgstr "Sao chép liên kết ghép đôi" msgid "Copy pairing token" msgstr "Sao chép token ghép đôi" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "Sao chép mật khẩu" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "Sao chép đường dẫn" @@ -2807,6 +2864,7 @@ msgstr "Hành vi xóa chủ đề mặc định" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "Xóa tập tin" msgid "Delete permanently" msgstr "Xóa vĩnh viễn" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "Xóa mật khẩu đã lưu" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "Xóa mật khẩu đã lưu?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "Xóa lịch" @@ -2998,6 +3064,10 @@ msgstr "Máy chủ phát triển đang lắng nghe trên localhost của máy t msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "Ghi đè chỉ dành cho phát triển. Chỉ hiển thị trong bản dựng PORACODE DEV." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "Cấu hình thiết bị" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "Thiết bị được dùng cho nút nhập giọng nói của khung so msgid "Devices can pair while this desktop is reachable." msgstr "Thiết bị có thể ghép nối khi máy tính này có thể truy cập được." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "Kích thước:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "Cần kết nối trực tiếp" @@ -3164,10 +3238,27 @@ msgstr "Xong" msgid "Done · Waiting for your input" msgstr "Xong · Đang chờ bạn nhập" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "Tải xuống không thành công" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "Lịch sử tải xuống" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "Tải hình ảnh" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "Tiến trình tải xuống" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "Đang tải xuống" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "Đang tải xuống mẫu giọng nói {0}%" msgid "Downloading voice model..." msgstr "Đang tải xuống mẫu giọng nói..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "Nội dung tải xuống" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "Các tệp tải xuống từ trình duyệt tích hợp được lưu trong lịch sử này." + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "Chỉnh sửa tập tin" msgid "Edit MCP server" msgstr "Chỉnh sửa máy chủ MCP" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "Chỉnh sửa mật khẩu" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "Chỉnh sửa hồ sơ" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "Chỉnh sửa mật khẩu đã lưu" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "Tập tin cho {0}" msgid "Files matching these globs are hidden from the @file mention search." msgstr "Các tệp khớp với các mẫu glob này sẽ bị ẩn khỏi tìm kiếm @file." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "Các tệp bạn tải xuống sẽ xuất hiện tại đây" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "Lọc theo dự án" @@ -3713,6 +3824,11 @@ msgstr "Tìm trong cuộc trò chuyện" msgid "Find in diff" msgstr "Tìm trong diff" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "Tìm trong trang" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "Tìm trong terminal" @@ -3877,6 +3993,10 @@ msgstr "Tần suất" msgid "Friday at 4:00 PM" msgstr "Thứ Sáu lúc 4:00 CH" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "Nguồn" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "Làm mờ thanh bên bằng hiệu ứng làm mờ của hệ thống (vibrancy), gợi nhớ macOS gần đây. Sẽ dùng lớp màu mờ trong suốt nếu không được hỗ trợ." @@ -4086,7 +4206,7 @@ msgstr "handle" msgid "Handle" msgstr "Handle" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "Tải lại cứng" @@ -4149,6 +4269,10 @@ msgstr "Ẩn các mô hình bạn không sử dụng khỏi bộ chọn mô hìn msgid "Hide panel" msgstr "Ẩn bảng điều khiển" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "Ẩn mật khẩu" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "Ẩn bảng gỡ lỗi thời gian chạy" @@ -4171,7 +4295,7 @@ msgstr "Ẩn skill từ {0}" msgid "Hide terminal" msgstr "Ẩn thiết bị đầu cuối" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "Lịch sử" @@ -4203,10 +4327,18 @@ msgstr "Hằng giờ" msgid "HTTP (streamable)" msgstr "HTTP (hỗ trợ truyền phát)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "Tôi hiểu rằng dữ liệu trình duyệt được bảo vệ có thể bị bỏ qua." + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "Hình ảnh" msgid "Image preview" msgstr "Xem trước hình ảnh" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "Nhập" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "Nhập lại" @@ -4248,10 +4384,23 @@ msgstr "Nhập lại" msgid "Import and restart" msgstr "Nhập và khởi động lại" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "Nhập dữ liệu trình duyệt" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "Xung đột khi nhập" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "Nhập cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "Nhập cookie và mật khẩu" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "Nhập skill của tác tử bên ngoài" msgid "Import external skills" msgstr "Nhập skill bên ngoài" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "Nhập từ trình duyệt của bạn" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "Nhập dữ liệu Lightcode" @@ -4285,10 +4438,18 @@ msgstr "Nhập máy chủ MCP" msgid "Import method" msgstr "Phương thức nhập" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "Nhập mật khẩu" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "Nhập mục đã chọn" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "Nguồn nhập" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "Nhập vào {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "Đã nhập {0} skill." msgid "Imported 1 skill." msgstr "Đã nhập 1 skill." +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "Đã nhập từ {0}" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "Mật khẩu đã nhập: {0}. Cookie đã nhập: {1}." + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "Cải thiện" @@ -4469,6 +4641,7 @@ msgstr "Hướng dẫn mà các tác nhân tuân theo khi chọn tác nhân ho msgid "Interrupt" msgstr "Ngắt" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "Bị gián đoạn" @@ -4477,6 +4650,26 @@ msgstr "Bị gián đoạn" msgid "Interrupted: agent session ended before completion." msgstr "Bị gián đoạn: phiên tác nhân đã kết thúc trước khi hoàn thành." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "Nghiêng" @@ -4530,6 +4723,14 @@ msgstr "Ngôn ngữ cho thông điệp commit và tóm tắt pull request do AI msgid "Language the speech model should expect when transcribing composer dictation." msgstr "Ngôn ngữ mà mô hình giọng nói cần dùng khi phiên âm lời đọc trong trình soạn thảo." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "Cục bộ" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "Các thay đổi cục bộ cần được lưu tạm trước khi kéo từ {branch}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "Bảo vệ mật khẩu cục bộ" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "Chuỗi ngày dài nhất" msgid "Longest task" msgstr "Tác vụ dài nhất" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "Đang tìm hồ sơ trình duyệt…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "Đang tìm máy chủ phát triển…" @@ -4791,6 +5000,10 @@ msgstr "Làm thanh bên trong suốt — hiệu ứng làm mờ của hệ thố #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "Quản lý skill tác tử toàn cục và theo dự án, bao gồm cả skill được nhập từ nhà cung cấp khác." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "Quản lý mật khẩu" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "Quản lý môi trường từ xa" @@ -5399,8 +5612,8 @@ msgstr "Lịch mới" #~ msgstr "Tác vụ đã lên lịch mới" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "Tab mới" @@ -5611,6 +5824,10 @@ msgstr "Không có sự khác biệt nào cho {0}" msgid "No diff for {visiblePath}" msgstr "Không có sự khác biệt đối với {visiblePath}" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "Không có bản tải xuống nào khớp với tìm kiếm của bạn" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "Không tìm thấy skill bên ngoài trong phạm vi này." @@ -5630,7 +5847,7 @@ msgstr "Không có tệp nào khớp với \"{0}\"." msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "Không tìm thấy tài khoản GitHub CLI nào. Đăng nhập bằng <0>gh auth login hoặc <1>dán URL sao chép." -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "Chưa có lịch sử" @@ -5705,6 +5922,10 @@ msgstr "Không có tác nhân nào khác được cài đặt" msgid "No paired devices yet." msgstr "Chưa có thiết bị nào được ghép đôi." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "Không có mật khẩu nào khớp với tìm kiếm của bạn" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "Không có mẫu." @@ -5771,6 +5992,10 @@ msgstr "Chưa có lần chạy nào." msgid "No runtime items yet for this thread." msgstr "Chưa có mục thời gian chạy nào cho luồng này." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "Không có mật khẩu đã lưu" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "Chưa có máy chủ nào được kết nối." @@ -5808,6 +6033,10 @@ msgstr "Không có tác tử được hỗ trợ nào được cài đặt trên msgid "No supported agents detected" msgstr "Không phát hiện thấy tác nhân được hỗ trợ nào" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "Không tìm thấy hồ sơ trình duyệt được hỗ trợ nào trên thiết bị này." + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "Chưa chọn luồng" @@ -6047,6 +6276,10 @@ msgstr "Mở trình giải quyết xung đột trong" msgid "Open dialog" msgstr "Mở hộp thoại" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "Mở tệp đã tải xuống" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "Mở tệp" @@ -6376,9 +6609,36 @@ msgid "Passphrase (optional)" msgstr "Cụm mật khẩu (không bắt buộc)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "Mật khẩu" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "Đã sao chép mật khẩu." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "Trình quản lý mật khẩu" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "Phần trình quản lý mật khẩu" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "Mật khẩu" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "Mật khẩu và tự động điền" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "Mật khẩu được mã hóa trong kho thông tin xác thực cục bộ của Poracode. Giá trị mật khẩu chỉ được yêu cầu khi bạn hiển thị, sao chép hoặc chỉnh sửa chúng." + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6411,7 +6671,12 @@ msgstr "Dán khóa riêng SSH." msgid "Pause" msgstr "Tạm dừng" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "Tạm dừng tải xuống" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "Đã tạm dừng" @@ -6476,6 +6741,10 @@ msgstr "Ghim lên đầu" msgid "Pinned" msgstr "Đã ghim" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6643,6 +6912,10 @@ msgstr "Các lần chạy trước" msgid "Previous tab" msgstr "Tab trước" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "In" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "Khóa riêng" @@ -6730,6 +7003,10 @@ msgstr "Prompt" msgid "Proposed plan" msgstr "Kế hoạch đề xuất" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "Dữ liệu trình duyệt được bảo vệ" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "Do Poracode cung cấp và quản lý cho các tác nhân được hỗ trợ." @@ -7127,6 +7404,7 @@ msgid "Remove action" msgstr "Xóa hành động" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "Xóa dấu trang" @@ -7143,6 +7421,10 @@ msgstr "Xóa kết nối" msgid "Remove environment variable" msgstr "Xóa biến môi trường" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "Xóa khỏi lịch sử tải xuống" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "Xóa khỏi mục yêu thích" @@ -7304,6 +7586,10 @@ msgstr "Đặt lại độ mờ thanh bên về mặc định" msgid "Reset to default" msgstr "Đặt lại về mặc định" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "Đặt lại mức thu phóng" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "Thay đổi kích thước ngăn trình duyệt" @@ -7337,11 +7623,27 @@ msgstr "Thay đổi kích thước phần chia" msgid "Resize terminal panel" msgstr "Thay đổi kích thước bảng điều khiển thiết bị đầu cuối" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "Thay đổi kích thước khung nhìn" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "Thay đổi chiều cao khung nhìn" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "Thay đổi chiều rộng khung nhìn" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "Giải quyết xung đột hợp nhất trong quá trình rebase hoặc hợp nhất." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "Đáp ứng" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "Khôi phục" @@ -7367,6 +7669,10 @@ msgstr "Khôi phục luồng" msgid "Resume" msgstr "Tiếp tục" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "Tiếp tục tải xuống" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7409,6 +7715,10 @@ msgstr "Hiển thị trong File Explorer" msgid "Reveal in file tree" msgstr "Hiển thị trong cây tập tin" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "Hiển thị mật khẩu" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7495,6 +7805,10 @@ msgstr "Bảng bên phải" msgid "Right-click to switch ring" msgstr "Nhấp chuột phải để đổi vòng" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "Xoay khung nhìn" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7607,9 +7921,14 @@ msgstr "Gỡ lỗi thời gian chạy" msgid "Runtime options" msgstr "Tùy chọn thời gian chạy" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7740,6 +8059,10 @@ msgstr "Tìm kiếm tác nhân..." msgid "Search branches..." msgstr "Tìm kiếm nhánh..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "Tìm kiếm bản tải xuống" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7773,6 +8096,10 @@ msgstr "Tìm kiếm mô hình..." msgid "Search or enter address" msgstr "Tìm kiếm hoặc nhập địa chỉ" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "Tìm kiếm mật khẩu" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "Tìm kiếm pull request" @@ -7980,7 +8307,7 @@ msgstr "Đặt phím tắt" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8028,11 +8355,11 @@ msgstr "Hiển thị phạm vi Trang chủ không có dự án cho các phiên t msgid "Show all" msgstr "Hiển thị tất cả" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "Hiển thị thanh dấu trang" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "Hiển thị thanh dấu trang" @@ -8054,6 +8381,10 @@ msgstr "Hiển thị trình soạn thảo" msgid "Show context usage details" msgstr "Hiển thị chi tiết sử dụng ngữ cảnh" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "Hiển thị thanh công cụ thiết bị" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8063,6 +8394,10 @@ msgstr "Hiển thị chi phí ước tính" msgid "Show in file explorer" msgstr "Hiển thị trong trình duyệt tệp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "Hiển thị trong thư mục" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8302,11 +8637,20 @@ msgstr "Đã bỏ qua" msgid "Slash commands" msgstr "Lệnh gạch chéo" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "Một số dữ liệu trình duyệt đã bị bỏ qua. Số mục được bảo vệ bị bỏ qua: {0}." + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "Một số kiểm tra không thành công hoặc đang chờ xử lý." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "Một số trình duyệt Chromium bảo vệ cookie và mật khẩu bằng App-Bound Encryption. Poracode không vượt qua cơ chế bảo vệ đó. Dữ liệu mà hệ điều hành không cung cấp sẽ bị bỏ qua." + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "Không thể quét một số thư mục của nhà cung cấp. Các skill đã tải thành công vẫn được hiển thị." @@ -8694,6 +9038,14 @@ msgstr "Hỗ trợ:" msgid "Supports Fast mode" msgstr "Hỗ trợ chế độ nhanh" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "Hoán đổi ghi chú và việc cần làm" @@ -8809,7 +9161,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "URL Tailscale" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "Chụp ảnh màn hình" @@ -9125,6 +9477,11 @@ msgstr "Dự án từ xa này không khả dụng. Hãy kết nối lại môi t msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "Thao tác này sẽ xóa các tin nhắn sau này và khôi phục các tệp khi có ảnh chụp nhanh điểm kiểm tra." +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "Thao tác này sẽ xóa mật khẩu đã lưu cho <0>{0} khỏi Poracode." + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "Thao tác này xóa lịch biểu và kết quả mới nhất khỏi thiết bị này." @@ -9428,14 +9785,34 @@ msgstr "Không thể sao chép token ghép đôi." msgid "Unable to copy Tailscale URL." msgstr "Không thể sao chép URL Tailscale." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "Không thể sao chép mật khẩu." + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "Không thể tạo thư mục cây làm việc WSL \"{path}\"" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "Không thể xóa mật khẩu đã lưu." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "Không thể xóa worktree." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "Không thể chỉnh sửa mật khẩu đã lưu." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "Không thể tìm thấy dữ liệu trình duyệt để nhập." + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "Không thể nhập dữ liệu trình duyệt." + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9446,10 +9823,18 @@ msgstr "Không thể cài đặt hook {0}." msgid "Unable to install {0}." msgstr "Không thể cài đặt {0}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "Không thể tải nội dung tải xuống." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "Không thể tải ghép đôi truy cập từ xa." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "Không thể tải các mật khẩu đã lưu." + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "Không thể tải luồng." @@ -9515,6 +9900,10 @@ msgstr "Không thể giải quyết thư mục chính cho bản phân phối WSL msgid "Unable to restore the SSH connection." msgstr "Không thể khôi phục kết nối SSH." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "Không thể hiển thị mật khẩu." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "Không thể thu hồi phiên từ xa." @@ -9528,6 +9917,10 @@ msgstr "Không thể lưu thông tin xác thực {0}." msgid "Unable to save Claude {displayLabel} profile." msgstr "Không thể lưu hồ sơ Claude {displayLabel}." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "Không thể lưu mật khẩu." + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "Không thể khởi động {label}." @@ -9595,6 +9988,10 @@ msgstr "Không thể cập nhật quyền truy cập từ xa." msgid "Unable to update Tailscale HTTPS." msgstr "Không thể cập nhật Tailscale HTTPS." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "Không thể cập nhật nội dung tải xuống." + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "Không thể cập nhật URL công khai." @@ -9897,6 +10294,10 @@ msgstr "Đã được dùng bởi {conflict}" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "Tên người dùng" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "Đang dùng danh sách mô hình Claude tích hợp sẵn." @@ -9970,6 +10371,18 @@ msgstr "Xem nhật ký thay đổi" msgid "View-only — this connection can't manage projects." msgstr "Chỉ xem — kết nối này không thể quản lý dự án." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "Chiều cao khung nhìn" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "Tỷ lệ khung nhìn" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "Chiều rộng khung nhìn" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10062,11 +10475,16 @@ msgid "Web server" msgstr "Máy chủ web" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "Trang web" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "Nguồn trang web" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "Ngày trong tuần" @@ -10347,10 +10765,16 @@ msgstr "Thư mục gốc WSL" msgid "Your name" msgstr "Tên của bạn" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "Thu phóng" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "Phóng to" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "Thu nhỏ" diff --git a/src/renderer/locales/zh-CN/messages.po b/src/renderer/locales/zh-CN/messages.po index d5676e332..5fd89c681 100644 --- a/src/renderer/locales/zh-CN/messages.po +++ b/src/renderer/locales/zh-CN/messages.po @@ -503,6 +503,10 @@ msgstr "22" msgid "30d" msgstr "30天" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "4K" +msgstr "4K" + #: src/renderer/views/SettingsOverlay/parts/ProfileSettings.tsx msgid "7d" msgstr "7天" @@ -618,6 +622,10 @@ msgstr "添加" msgid "Add a local project" msgstr "添加本地项目" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add a password or import one from another browser." +msgstr "添加密码或从其他浏览器导入。" + #: src/mobile/setupEmptyState.tsx #: src/mobile/views/ManageProjectsView.tsx #: src/renderer/views/QuickComposerOverlay/QuickComposerOverlay.tsx @@ -698,6 +706,10 @@ msgstr "添加模型" msgid "Add one manually or import from another agent." msgstr "手动添加一个,或从其他代理导入。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Add password" +msgstr "添加密码" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "Add pattern" msgstr "添加模式" @@ -751,6 +763,10 @@ msgstr "添加到收藏夹" msgid "Add to Home Screen" msgstr "添加到主屏幕" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Advanced" +msgstr "高级" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Advertise a custom base URL, e.g. a reverse proxy or tunnel. Leave empty for automatic." msgstr "公布自定义基础 URL,例如反向代理或隧道。留空则自动设置。" @@ -1301,11 +1317,12 @@ msgstr "已阻止:" msgid "Bold" msgstr "加粗" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Bookmark this page" msgstr "将此页加入书签" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Bookmarks" msgstr "书签" @@ -1342,6 +1359,10 @@ msgstr "移回面板" msgid "Bring it back into this panel, or jump to the window it’s running in." msgstr "将其移回此面板,或跳转到正在运行它的窗口。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Bring saved passwords and cookies over from an installed browser." +msgstr "从已安装的浏览器导入已保存的密码和 Cookie。" + #: src/renderer/views/SettingsOverlay/parts/SshConnectionForm.tsx msgid "Browse" msgstr "浏览" @@ -1387,7 +1408,7 @@ msgstr "为 OpenCode 启用的浏览器 MCP" msgid "Browser MCP enabled for this thread" msgstr "为此线程启用浏览器 MCP" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Browser menu" msgstr "浏览器菜单" @@ -1487,6 +1508,8 @@ msgstr "无法加载端口" #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx @@ -1498,6 +1521,10 @@ msgstr "无法加载端口" msgid "Cancel" msgstr "取消" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Cancel download" +msgstr "取消下载" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Cancel new Claude profile" msgstr "取消新的 Claude 配置文件" @@ -1519,6 +1546,7 @@ msgid "cancelled" msgstr "已取消" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Cancelled" msgstr "已取消" @@ -1682,6 +1710,10 @@ msgstr "选择父文件夹" #~ msgid "Choose an MCP server configuration file" #~ msgstr "选择 MCP 服务器配置文件" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Choose data to bring over to the built-in browser." +msgstr "选择要导入内置浏览器的数据。" + #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/AgentEnvironmentRow.tsx msgid "Choose how to sign in for {env}." msgstr "选择登录 {env} 的方式。" @@ -1754,22 +1786,34 @@ msgstr "Claude 配置文件已删除。" msgid "Cleanup script" msgstr "清理脚本" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear browsing data" +msgstr "清除浏览数据" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear browsing history" msgstr "清除浏览历史记录" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Clear Browsing History" msgstr "清除浏览历史记录" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cache" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cache" msgstr "清除缓存" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx -msgid "Clear Cookies" +#~ msgid "Clear Cache" +#~ msgstr "清除缓存" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Clear cookies" msgstr "清除 Cookie" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#~ msgid "Clear Cookies" +#~ msgstr "清除 Cookie" + #: src/mobile/views/FilesView.tsx #: src/mobile/views/ThreadsView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx @@ -1859,6 +1903,10 @@ msgstr "关闭输入框" msgid "Close connection actions" msgstr "关闭连接操作" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Close device toolbar" +msgstr "关闭设备工具栏" + #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx msgid "Close editor" msgstr "关闭编辑器" @@ -2183,6 +2231,7 @@ msgid "completed" msgstr "已完成" #: src/renderer/utils/prStatus.ts +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx msgid "Completed" msgstr "已完成" @@ -2401,6 +2450,10 @@ msgstr "代理点击或输入时控制已配对的桌面" msgid "Conversation" msgstr "对话" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Cookies" +msgstr "Cookie" + #: src/mobile/UserMessageActionsSheet.tsx #: src/mobile/views/PortsView.tsx #: src/renderer/components/thread/ChatPane/parts/items/CopyTextButton.tsx @@ -2436,7 +2489,7 @@ msgstr "将所有 Lightcode 数据复制到 Poracode。Poracode 将重新启动 msgid "Copy code" msgstr "复制代码" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Copy Current URL" msgstr "复制当前网址" @@ -2479,6 +2532,10 @@ msgstr "复制配对链接" msgid "Copy pairing token" msgstr "复制配对令牌" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Copy password" +msgstr "复制密码" + #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx msgid "Copy Path" msgstr "复制路径" @@ -2807,6 +2864,7 @@ msgstr "默认线程删除" #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx @@ -2858,6 +2916,14 @@ msgstr "删除文件" msgid "Delete permanently" msgstr "永久删除" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password" +msgstr "删除已保存的密码" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Delete saved password?" +msgstr "删除已保存的密码?" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx msgid "Delete schedule" msgstr "删除计划" @@ -2998,6 +3064,10 @@ msgstr "监听桌面端 localhost 的开发服务器。" msgid "Development-only overrides. Only visible in the PORACODE DEV build." msgstr "仅开发覆盖。仅在 PORACODE DEV 版本中可见。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Device preset" +msgstr "设备预设" + #: src/renderer/views/SettingsOverlay/parts/AudioSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Device used by the composer voice input button." @@ -3007,6 +3077,10 @@ msgstr "输入框语音输入按钮使用的设备。" msgid "Devices can pair while this desktop is reachable." msgstr "当此桌面可访问时,设备可以配对。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Dimensions:" +msgstr "尺寸:" + #: src/mobile/views/PortsView.tsx #~ msgid "Direct connection required" #~ msgstr "需要直接连接" @@ -3164,10 +3238,27 @@ msgstr "完成" msgid "Done · Waiting for your input" msgstr "完成 · 等待您的输入" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download failed" +msgstr "下载失败" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Download history" +msgstr "下载记录" + #: src/renderer/components/thread/ChatPane/parts/items/ImageView.tsx msgid "Download image" msgstr "下载图片" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Download progress" +msgstr "下载进度" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloading" +msgstr "正在下载" + #. placeholder {0}: name || t`the chosen folder` #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx msgid "Downloading into “{0}”. This can take a moment for large repositories." @@ -3187,6 +3278,14 @@ msgstr "下载语音模型{0}%" msgid "Downloading voice model..." msgstr "正在下载语音模型..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Downloads" +msgstr "下载内容" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Downloads from the built-in browser are saved in this history." +msgstr "内置浏览器中的下载内容会保存在此记录中。" + #: src/renderer/views/PrReviewOverlay/parts/PrMetaRow.tsx #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Draft" @@ -3240,10 +3339,18 @@ msgstr "编辑文件" msgid "Edit MCP server" msgstr "编辑 MCP 服务器" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit password" +msgstr "编辑密码" + #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx msgid "Edit profile" msgstr "编辑资料" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Edit saved password" +msgstr "编辑已保存的密码" + #: src/renderer/views/SchedulesView/parts/ScheduleRow.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Edit schedule" @@ -3680,6 +3787,10 @@ msgstr "{0}的文件" msgid "Files matching these globs are hidden from the @file mention search." msgstr "与这些 glob 匹配的文件在 @file 提及搜索中隐藏。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Files you download appear here" +msgstr "您下载的文件会显示在这里" + #: src/mobile/views/ThreadsView.tsx msgid "Filter by project" msgstr "按项目筛选" @@ -3713,6 +3824,11 @@ msgstr "在聊天中查找" msgid "Find in diff" msgstr "在差异中查找" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Find in page" +msgstr "在页面中查找" + #: src/renderer/components/terminal/XTermSurface.tsx msgid "Find in terminal" msgstr "在终端中查找" @@ -3877,6 +3993,10 @@ msgstr "频率" msgid "Friday at 4:00 PM" msgstr "星期五下午 4:00" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "From" +msgstr "来源" + #: src/renderer/views/SettingsOverlay/parts/AppearanceSettings.tsx msgid "Frost the sidebar with the system blur material (vibrancy), echoing recent macOS. Falls back to a translucent tint where unsupported." msgstr "使用系统模糊材质(vibrancy)为侧边栏添加磨砂效果,呼应新版macOS。不支持时回退为半透明着色。" @@ -4086,7 +4206,7 @@ msgstr "用户名" msgid "Handle" msgstr "用户名" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Hard Reload" msgstr "硬重载" @@ -4149,6 +4269,10 @@ msgstr "从每个提供商的模型选择器中隐藏您不使用的模型。" msgid "Hide panel" msgstr "隐藏面板" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Hide password" +msgstr "隐藏密码" + #: src/renderer/components/thread/ThreadView.tsx msgid "Hide runtime debug panel" msgstr "隐藏运行时调试面板" @@ -4171,7 +4295,7 @@ msgstr "隐藏来自 {0} 的技能" msgid "Hide terminal" msgstr "隐藏终端" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "History" msgstr "历史记录" @@ -4203,10 +4327,18 @@ msgstr "每小时" msgid "HTTP (streamable)" msgstr "HTTP(流式)" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "https://example.com" +msgstr "https://example.com" + #: src/renderer/components/mcp/McpServerEditor.tsx msgid "https://example.com/mcp" msgstr "https://example.com/mcp" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "I understand that protected browser data may be skipped." +msgstr "我了解受保护的浏览器数据可能会被跳过。" + #. placeholder {0}: agent.id #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "ID: {0}" @@ -4240,6 +4372,10 @@ msgstr "图片" msgid "Image preview" msgstr "图片预览" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import" +msgstr "导入" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import again" msgstr "再次导入" @@ -4248,10 +4384,23 @@ msgstr "再次导入" msgid "Import and restart" msgstr "导入并重新启动" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import browser data" +msgstr "导入浏览器数据" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Import conflict" msgstr "导入冲突" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import cookies" +msgstr "导入 Cookie" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Import cookies and passwords" +msgstr "导入 Cookie 和密码" + #: src/renderer/components/mcp/McpExternalImportModal.tsx #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import destination" @@ -4269,6 +4418,10 @@ msgstr "导入外部智能体技能" msgid "Import external skills" msgstr "导入外部技能" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import from your browser" +msgstr "从浏览器导入" + #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx msgid "Import Lightcode data" msgstr "导入 Lightcode 数据" @@ -4285,10 +4438,18 @@ msgstr "导入 MCP 服务器" msgid "Import method" msgstr "导入方式" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import passwords" +msgstr "导入密码" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "Import selected" msgstr "导入所选项" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Import source" +msgstr "导入来源" + #: src/renderer/components/mcp/McpExternalImportModal.tsx msgid "Import to {destinationProjectName}" msgstr "导入到 {destinationProjectName}" @@ -4316,6 +4477,17 @@ msgstr "已导入 {0} 个技能。" msgid "Imported 1 skill." msgstr "已导入 1 个技能。" +#. placeholder {0}: credential.source +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Imported from {0}" +msgstr "已从 {0} 导入" + +#. placeholder {0}: result.passwordsImported +#. placeholder {1}: result.cookiesImported +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Imported passwords: {0}. Imported cookies: {1}." +msgstr "已导入密码:{0}。已导入 Cookie:{1}。" + #: src/renderer/components/changelog/ChangelogView.tsx msgid "Improved" msgstr "已改进" @@ -4469,6 +4641,7 @@ msgstr "代理在选择要委派给哪个代理或模型时遵循的说明。" msgid "Interrupt" msgstr "中断" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/parts/PreviousRunsModal.tsx msgid "Interrupted" msgstr "已中断" @@ -4477,6 +4650,26 @@ msgstr "已中断" msgid "Interrupted: agent session ended before completion." msgstr "已中断:代理会话在完成之前结束。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Air" +msgstr "iPad Air" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPad Mini" +msgstr "iPad Mini" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro" +msgstr "iPhone 15 Pro" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone 15 Pro Max" +msgstr "iPhone 15 Pro Max" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "iPhone SE" +msgstr "iPhone SE" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesEditor.tsx msgid "Italic" msgstr "斜体" @@ -4530,6 +4723,14 @@ msgstr "AI 生成的提交信息和拉取请求摘要所使用的语言。线程 msgid "Language the speech model should expect when transcribing composer dictation." msgstr "语音模型在转录编辑器口述输入时应预期的语言。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop" +msgstr "Laptop" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Laptop L" +msgstr "Laptop L" + #. placeholder {0}: agent.lastToolName #: src/renderer/components/thread/ChatPane/parts/items/WorkflowOverlayBody.tsx msgid "Last tool: <0>{0}" @@ -4713,6 +4914,10 @@ msgstr "本地" msgid "Local changes need to be stashed before pulling from {branch}" msgstr "从 {branch} 拉取之前需要暂存(stash)本地更改" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Local password protection" +msgstr "本地密码保护" + #. placeholder {0}: forward.targetPort #: src/mobile/views/PortsView.tsx msgid "localhost:{0} on desktop" @@ -4779,6 +4984,10 @@ msgstr "最长连续天数" msgid "Longest task" msgstr "最长任务" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Looking for browser profiles…" +msgstr "正在查找浏览器配置文件…" + #: src/mobile/views/PortsView.tsx msgid "Looking for dev servers…" msgstr "正在查找开发服务器…" @@ -4791,6 +5000,10 @@ msgstr "将侧边栏设为半透明——在Windows 11上使用系统模糊材 #~ msgid "Manage global and project agent skills, including skills imported from other providers." #~ msgstr "管理全局和项目智能体技能,包括从其他提供商导入的技能。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Manage passwords" +msgstr "管理密码" + #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarRemoteServers.tsx msgid "Manage remote environments" msgstr "管理远程环境" @@ -5398,8 +5611,8 @@ msgstr "新建计划" #~ msgstr "新建计划任务" #: src/mobile/views/BrowserView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "New tab" msgstr "新标签页" @@ -5610,6 +5823,10 @@ msgstr "{0}没有可用的差异" msgid "No diff for {visiblePath}" msgstr "{visiblePath}没有差异" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "No downloads match your search" +msgstr "没有与搜索匹配的下载内容" + #: src/renderer/components/skills/SkillImportModal.tsx msgid "No external skills were found in this scope." msgstr "在此范围内未找到外部技能。" @@ -5629,7 +5846,7 @@ msgstr "没有文件匹配“{0}”。" msgid "No GitHub CLI accounts found. Sign in with <0>gh auth login, or <1>paste a clone URL." msgstr "未找到 GitHub CLI 帐户。使用<0>gh auth login登录,或<1>粘贴克隆网址。" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "No history yet" msgstr "暂无历史记录" @@ -5704,6 +5921,10 @@ msgstr "没有安装其他代理" msgid "No paired devices yet." msgstr "还没有已配对的设备。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No passwords match your search" +msgstr "没有与搜索匹配的密码" + #: src/renderer/views/SettingsOverlay/parts/SearchExcludeBody.tsx msgid "No patterns." msgstr "没有模式。" @@ -5770,6 +5991,10 @@ msgstr "尚无运行记录。" msgid "No runtime items yet for this thread." msgstr "该线程还没有运行时项目。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "No saved passwords" +msgstr "没有已保存的密码" + #: src/renderer/views/SettingsOverlay/parts/RemoteServersSettings.tsx #~ msgid "No servers connected yet." #~ msgstr "尚未连接任何服务器。" @@ -5807,6 +6032,10 @@ msgstr "此远程计算机上未安装受支持的代理。请先在远程安装 msgid "No supported agents detected" msgstr "未检测到支持的代理" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "No supported browser profiles were found on this device." +msgstr "在此设备上未找到受支持的浏览器配置文件。" + #: src/mobile/views/ThreadView.tsx msgid "No thread selected" msgstr "未选择线程" @@ -6046,6 +6275,10 @@ msgstr "在以下位置打开冲突解决器" msgid "Open dialog" msgstr "打开对话框" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Open downloaded file" +msgstr "打开已下载的文件" + #: src/renderer/commands/registry.ts msgid "Open File" msgstr "打开文件" @@ -6375,9 +6608,36 @@ msgid "Passphrase (optional)" msgstr "密码短语(可选)" #: src/mobile/views/DesktopsView.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx msgid "Password" msgstr "密码" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password copied." +msgstr "密码已复制。" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +msgid "Password manager" +msgstr "密码管理器" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Password manager section" +msgstr "密码管理器部分" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords" +msgstr "密码" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Passwords and autofill" +msgstr "密码和自动填充" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Passwords are encrypted in Poracode's local credential store. Password values are requested only when you reveal, copy, or edit them." +msgstr "密码在 Poracode 的本地凭据存储中加密。只有在您显示、复制或编辑密码时,才会请求密码值。" + #: src/renderer/commands/shortcutCatalog.ts #: src/renderer/components/terminal/XTermSurface.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -6410,7 +6670,12 @@ msgstr "请粘贴 SSH 私钥。" msgid "Pause" msgstr "暂停" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Pause download" +msgstr "暂停下载" + #: src/renderer/components/thread/ThreadGoalDock.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "Paused" msgstr "已暂停" @@ -6475,6 +6740,10 @@ msgstr "固定到顶部" msgid "Pinned" msgstr "已固定" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Pixel 8" +msgstr "Pixel 8" + #: src/renderer/components/providers/composerControlBuilders.tsx #: src/renderer/components/thread/ThreadTodoDock.tsx msgid "Plan" @@ -6642,6 +6911,10 @@ msgstr "历史运行" msgid "Previous tab" msgstr "上一个选项卡" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Print" +msgstr "打印" + #: src/mobile/views/DesktopsView.tsx msgid "Private key" msgstr "私钥" @@ -6729,6 +7002,10 @@ msgstr "提示" msgid "Proposed plan" msgstr "拟议计划" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Protected browser data" +msgstr "受保护的浏览器数据" + #: src/renderer/components/mcp/McpServersManager.tsx msgid "Provided and managed by Poracode for supported agents." msgstr "由 Poracode 为受支持的代理提供和管理。" @@ -7126,6 +7403,7 @@ msgid "Remove action" msgstr "删除动作" #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserBookmarkBar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx msgid "Remove bookmark" msgstr "移除书签" @@ -7142,6 +7420,10 @@ msgstr "删除连接" msgid "Remove environment variable" msgstr "移除环境变量" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Remove from download history" +msgstr "从下载记录中移除" + #: src/renderer/components/common/ProviderModelMenu/ProviderModelMenu.tsx msgid "Remove from favorites" msgstr "从收藏夹中删除" @@ -7303,6 +7585,10 @@ msgstr "将侧边栏磨砂效果重置为默认" msgid "Reset to default" msgstr "重置为默认" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Reset zoom" +msgstr "重置缩放" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserHost.tsx msgid "Resize browser drawer" msgstr "调整浏览器抽屉的大小" @@ -7336,11 +7622,27 @@ msgstr "调整分割大小" msgid "Resize terminal panel" msgstr "调整终端面板大小" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport" +msgstr "调整视口大小" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport height" +msgstr "调整视口高度" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +msgid "Resize viewport width" +msgstr "调整视口宽度" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Resolves merge conflicts during rebase or merge." msgstr "解决变基或合并期间的合并冲突。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Responsive" +msgstr "响应式" + #: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx msgid "Restore" msgstr "恢复" @@ -7366,6 +7668,10 @@ msgstr "恢复线程" msgid "Resume" msgstr "继续" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Resume download" +msgstr "继续下载" + #: src/mobile/views/BrowserView.tsx #: src/mobile/views/PortsView.tsx #: src/mobile/views/TerminalView.tsx @@ -7408,6 +7714,10 @@ msgstr "在文件资源管理器中显示" msgid "Reveal in file tree" msgstr "在文件树中显示" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Reveal password" +msgstr "显示密码" + #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/FileRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitStackedDiff.tsx @@ -7494,6 +7804,10 @@ msgstr "右面板" msgid "Right-click to switch ring" msgstr "右键点击以切换环" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Rotate viewport" +msgstr "旋转视口" + #: src/renderer/components/thread/ChatPane/parts/items/commandSummary.ts #: src/renderer/components/thread/ChatPane/parts/items/toolDisplay.ts #: src/renderer/views/MainView/parts/Sidebar/parts/SidebarProjectHeader.tsx @@ -7606,9 +7920,14 @@ msgstr "运行时调试" msgid "Runtime options" msgstr "运行时选项" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Samsung Galaxy S24 Ultra" +msgstr "Samsung Galaxy S24 Ultra" + #: src/mobile/views/FilesView.tsx #: src/renderer/components/mcp/McpServerEditor.tsx #: src/renderer/views/FileEditorOverlay/parts/FileEditorPane/parts/EditorToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/SingleAgentSettings.tsx @@ -7739,6 +8058,10 @@ msgstr "搜索代理..." msgid "Search branches..." msgstr "搜索分支..." +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Search downloads" +msgstr "搜索下载内容" + #: src/mobile/views/FilesView.tsx #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/ProjectTreeView.tsx msgid "Search files" @@ -7772,6 +8095,10 @@ msgstr "搜索模型..." msgid "Search or enter address" msgstr "搜索或输入地址" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Search passwords" +msgstr "搜索密码" + #: src/renderer/views/PullRequestsView/PullRequestsView.tsx msgid "Search pull requests" msgstr "搜索拉取请求" @@ -7979,7 +8306,7 @@ msgstr "设置快捷键" #: src/mobile/NarrowShell.tsx #: src/mobile/WideShell.tsx #: src/renderer/components/thread/ThreadAuthRequiredDock.tsx -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx #: src/renderer/views/MainView/parts/Sidebar/Sidebar.tsx #: src/renderer/views/SettingsOverlay/SettingsOverlay.tsx msgid "Settings" @@ -8027,11 +8354,11 @@ msgstr "为操作系统级别的代理会话显示一个无项目的主页范围 msgid "Show all" msgstr "显示全部" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show bookmark bar" msgstr "显示书签栏" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Show Bookmark Bar" msgstr "显示书签栏" @@ -8053,6 +8380,10 @@ msgstr "显示编辑器" msgid "Show context usage details" msgstr "显示上下文使用详细信息" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Show device toolbar" +msgstr "显示设备工具栏" + #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts #: src/renderer/views/SettingsOverlay/parts/UsageSettings.tsx msgid "Show estimated cost" @@ -8062,6 +8393,10 @@ msgstr "显示预计费用" msgid "Show in file explorer" msgstr "在文件资源管理器中显示" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Show in folder" +msgstr "在文件夹中显示" + #: src/renderer/components/thread/ChatPane/parts/items/ToolCallGroup.tsx #: src/renderer/components/thread/ChatPane/parts/items/UserMessage.tsx msgid "Show less" @@ -8301,11 +8636,20 @@ msgstr "已跳过" msgid "Slash commands" msgstr "斜杠命令" +#. placeholder {0}: result.protectedItemsSkipped +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some browser data was skipped. Protected items skipped: {0}." +msgstr "某些浏览器数据已被跳过。跳过的受保护项目:{0}。" + #: src/mobile/views/pr/PrOverviewPage.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/PrSection.tsx msgid "Some checks are failing or pending." msgstr "一些检查失败或待处理。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Some Chromium browsers protect cookies and passwords with App-Bound Encryption. Poracode does not bypass that protection. Data the operating system does not make available will be skipped." +msgstr "某些 Chromium 浏览器使用 App-Bound Encryption 保护 Cookie 和密码。Poracode 不会绕过此保护。操作系统不提供的数据将被跳过。" + #: src/renderer/components/skills/SkillsManager.tsx msgid "Some provider folders couldn't be scanned. Successfully loaded skills are still shown." msgstr "无法扫描某些提供商文件夹。已成功加载的技能仍会显示。" @@ -8693,6 +9037,14 @@ msgstr "支持:" msgid "Supports Fast mode" msgstr "支持快速模式" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Duo" +msgstr "Surface Duo" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Surface Pro 7" +msgstr "Surface Pro 7" + #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/NotesPanel.tsx msgid "Swap notes and to-dos" msgstr "切换笔记和待办事项" @@ -8808,7 +9160,7 @@ msgstr "Tailscale HTTPS" msgid "Tailscale URL" msgstr "Tailscale URL" -#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserToolbar.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Take Screenshot" msgstr "截图" @@ -9124,6 +9476,11 @@ msgstr "此远程项目不可用。请重新连接环境后重试。" msgid "This removes later messages and restores files when a checkpoint snapshot is available." msgstr "当检查点快照可用时,这会删除稍后的消息并恢复文件。" +#. placeholder {0}: pendingDelete?.origin +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "This removes the saved password for <0>{0} from Poracode." +msgstr "这会从 Poracode 中删除 <0>{0} 的已保存密码。" + #: src/renderer/views/SchedulesView/SchedulesView.tsx msgid "This removes the schedule and its latest result from this device." msgstr "这会从此设备中删除计划及其最新结果。" @@ -9427,14 +9784,34 @@ msgstr "无法复制配对令牌。" msgid "Unable to copy Tailscale URL." msgstr "无法复制 Tailscale URL。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to copy the password." +msgstr "无法复制密码。" + #: src/renderer/i18n/sharedMessages.ts msgid "Unable to create WSL worktree directory \"{path}\"" msgstr "无法创建 WSL 工作树目录“{path}”" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to delete the saved password." +msgstr "无法删除已保存的密码。" + #: src/mobile/useRemoteDesktop.ts msgid "Unable to delete the worktree." msgstr "无法删除 worktree。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to edit the saved password." +msgstr "无法编辑已保存的密码。" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to find browser data to import." +msgstr "无法找到要导入的浏览器数据。" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx +msgid "Unable to import browser data." +msgstr "无法导入浏览器数据。" + #. placeholder {0}: props.selectedAgent.label #: src/renderer/components/thread/ThreadDraftComposerArea.tsx msgid "Unable to install {0} hooks." @@ -9445,10 +9822,18 @@ msgstr "无法安装{0}挂钩。" msgid "Unable to install {0}." msgstr "无法安装{0}。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to load downloads." +msgstr "无法加载下载内容。" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to load remote access pairing." msgstr "无法加载远程访问配对。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to load saved passwords." +msgstr "无法加载已保存的密码。" + #: src/mobile/useRemoteDesktop.ts msgid "Unable to load thread." msgstr "无法加载线程。" @@ -9514,6 +9899,10 @@ msgstr "无法解析 WSL 发行版“{distro}”的主目录" msgid "Unable to restore the SSH connection." msgstr "无法恢复 SSH 连接。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to reveal the password." +msgstr "无法显示密码。" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to revoke remote session." msgstr "无法撤销远程会话。" @@ -9527,6 +9916,10 @@ msgstr "无法保存{0}凭据。" msgid "Unable to save Claude {displayLabel} profile." msgstr "无法保存Claude {displayLabel}配置。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Unable to save the password." +msgstr "无法保存密码。" + #: src/renderer/utils/shellUtils.ts msgid "Unable to start {label}." msgstr "无法启动{label}。" @@ -9594,6 +9987,10 @@ msgstr "无法更新远程访问。" msgid "Unable to update Tailscale HTTPS." msgstr "无法更新 Tailscale HTTPS。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDownloadsPage.tsx +msgid "Unable to update the download." +msgstr "无法更新下载内容。" + #: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx msgid "Unable to update the public URL." msgstr "无法更新公共 URL。" @@ -9896,6 +10293,10 @@ msgstr "已被{conflict}使用" msgid "user@example.com" msgstr "user@example.com" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Username" +msgstr "用户名" + #: src/renderer/views/SettingsOverlay/parts/ClaudeProfileSettings.tsx msgid "Using the built-in Claude model list." msgstr "正在使用内置的Claude模型列表。" @@ -9969,6 +10370,18 @@ msgstr "查看变更日志" msgid "View-only — this connection can't manage projects." msgstr "仅查看 — 此连接无法管理项目。" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport height" +msgstr "视口高度" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport scale" +msgstr "视口缩放" + +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx +msgid "Viewport width" +msgstr "视口宽度" + #. placeholder {0}: provider.label #: src/renderer/views/SettingsOverlay/parts/SingleAgentSettings/parts/ModelVisibilityDropdown.tsx msgid "Visible {0} models" @@ -10061,11 +10474,16 @@ msgid "Web server" msgstr "Web 服务器" #. External link to the product website +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx #: src/renderer/views/SettingsOverlay/parts/AboutSettings.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx msgid "Website" msgstr "网站" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserPasswordsPage.tsx +msgid "Website origin" +msgstr "网站来源" + #: src/renderer/views/SchedulesView/ScheduleEditor.tsx msgid "Weekdays" msgstr "工作日" @@ -10346,10 +10764,16 @@ msgstr "WSL 基础文件夹" msgid "Your name" msgstr "你的名字" +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx +msgid "Zoom" +msgstr "缩放" + #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom in" msgstr "放大" #: src/renderer/components/composer/ImageLightbox.tsx +#: src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserMenu.tsx msgid "Zoom out" msgstr "缩小" diff --git a/src/renderer/state/browserCredentialsStore.ts b/src/renderer/state/browserCredentialsStore.ts new file mode 100644 index 000000000..6643878be --- /dev/null +++ b/src/renderer/state/browserCredentialsStore.ts @@ -0,0 +1,16 @@ +import { create } from "zustand"; +import type { BrowserCredentialInfo } from "@/shared/ipc"; + +interface BrowserCredentialsState { + credentials: BrowserCredentialInfo[]; + revision: number; + setCredentials: (credentials: BrowserCredentialInfo[]) => void; + invalidate: () => void; +} + +export const useBrowserCredentialsStore = create((set) => ({ + credentials: [], + revision: 0, + setCredentials: (credentials) => set({ credentials }), + invalidate: () => set((state) => ({ revision: state.revision + 1 })), +})); diff --git a/src/renderer/state/browserDownloadsStore.test.ts b/src/renderer/state/browserDownloadsStore.test.ts new file mode 100644 index 000000000..5a66d41df --- /dev/null +++ b/src/renderer/state/browserDownloadsStore.test.ts @@ -0,0 +1,46 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import type { BrowserDownloadInfo } from "@/shared/ipc"; +import { useBrowserDownloadsStore } from "./browserDownloadsStore"; + +const olderDownload: BrowserDownloadInfo = { + id: "older", + filename: "older.zip", + url: "https://example.test/older.zip", + mimeType: "application/zip", + state: "progressing", + receivedBytes: 10, + totalBytes: 100, + startTime: 1, + canResume: true, +}; + +const newerDownload: BrowserDownloadInfo = { + ...olderDownload, + id: "newer", + filename: "newer.zip", + startTime: 2, +}; + +describe("browserDownloadsStore", () => { + beforeEach(() => useBrowserDownloadsStore.getState().setDownloads([])); + + it("inserts downloads in newest-first order and replaces updates in place", () => { + const store = useBrowserDownloadsStore.getState(); + store.upsertDownload(olderDownload); + store.upsertDownload(newerDownload); + store.upsertDownload({ ...olderDownload, state: "paused", receivedBytes: 50 }); + + expect(useBrowserDownloadsStore.getState().downloads).toEqual([ + newerDownload, + { ...olderDownload, state: "paused", receivedBytes: 50 }, + ]); + }); + + it("removes a download by id", () => { + const store = useBrowserDownloadsStore.getState(); + store.setDownloads([newerDownload, olderDownload]); + store.removeDownload(newerDownload.id); + + expect(useBrowserDownloadsStore.getState().downloads).toEqual([olderDownload]); + }); +}); diff --git a/src/renderer/state/browserDownloadsStore.ts b/src/renderer/state/browserDownloadsStore.ts new file mode 100644 index 000000000..6a61b454b --- /dev/null +++ b/src/renderer/state/browserDownloadsStore.ts @@ -0,0 +1,30 @@ +import { create } from "zustand"; +import type { BrowserDownloadInfo } from "@/shared/ipc"; + +interface BrowserDownloadsState { + downloads: BrowserDownloadInfo[]; + setDownloads: (downloads: BrowserDownloadInfo[]) => void; + upsertDownload: (download: BrowserDownloadInfo) => void; + removeDownload: (downloadId: string) => void; +} + +export const useBrowserDownloadsStore = create((set) => ({ + downloads: [], + setDownloads: (downloads) => set({ downloads }), + upsertDownload: (download) => + set((state) => { + const index = state.downloads.findIndex((candidate) => candidate.id === download.id); + if (index < 0) { + return { + downloads: [...state.downloads, download].sort((a, b) => b.startTime - a.startTime), + }; + } + const downloads = [...state.downloads]; + downloads[index] = download; + return { downloads }; + }), + removeDownload: (downloadId) => + set((state) => ({ + downloads: state.downloads.filter((download) => download.id !== downloadId), + })), +})); diff --git a/src/renderer/state/browserFindStore.ts b/src/renderer/state/browserFindStore.ts new file mode 100644 index 000000000..8eecad2fc --- /dev/null +++ b/src/renderer/state/browserFindStore.ts @@ -0,0 +1,52 @@ +import { create } from "zustand"; +import type { BrowserFindResult } from "@/shared/ipc"; + +interface BrowserFindState { + tabId: string | null; + query: string; + matchCase: boolean; + matches: number; + currentIndex: number; + openToken: number; + open: (tabId: string) => void; + close: () => void; + setQuery: (query: string) => void; + toggleMatchCase: () => void; + applyResult: (result: BrowserFindResult) => void; +} + +export const useBrowserFindStore = create((set) => ({ + tabId: null, + query: "", + matchCase: false, + matches: 0, + currentIndex: -1, + openToken: 0, + open: (tabId) => + set((state) => ({ + tabId, + query: state.tabId === tabId ? state.query : "", + matches: state.tabId === tabId ? state.matches : 0, + currentIndex: state.tabId === tabId ? state.currentIndex : -1, + openToken: state.openToken + 1, + })), + close: () => + set((state) => + state.tabId === null ? {} : { tabId: null, query: "", matches: 0, currentIndex: -1 }, + ), + setQuery: (query) => + set((state) => (state.query === query ? {} : { query, matches: 0, currentIndex: -1 })), + toggleMatchCase: () => + set((state) => ({ + matchCase: !state.matchCase, + matches: 0, + currentIndex: -1, + })), + applyResult: (result) => + set((state) => { + if (state.tabId !== result.tabId) return {}; + const currentIndex = result.activeMatchOrdinal > 0 ? result.activeMatchOrdinal - 1 : -1; + if (state.matches === result.matches && state.currentIndex === currentIndex) return {}; + return { matches: result.matches, currentIndex }; + }), +})); diff --git a/src/renderer/state/browserImportStore.ts b/src/renderer/state/browserImportStore.ts new file mode 100644 index 000000000..49ee6ffec --- /dev/null +++ b/src/renderer/state/browserImportStore.ts @@ -0,0 +1,11 @@ +import { create } from "zustand"; + +interface BrowserImportState { + open: boolean; + setOpen: (open: boolean) => void; +} + +export const useBrowserImportStore = create((set) => ({ + open: false, + setOpen: (open) => set((state) => (state.open === open ? {} : { open })), +})); diff --git a/src/renderer/state/browserPanelStore.ts b/src/renderer/state/browserPanelStore.ts index 02cfede28..a8348cc14 100644 --- a/src/renderer/state/browserPanelStore.ts +++ b/src/renderer/state/browserPanelStore.ts @@ -90,10 +90,9 @@ export const useBrowserPanelStore = create((set) => ({ if (idx < 0) { return { tabs: [...s.tabs, tab] }; } - const nextTab = { ...s.tabs[idx]!, ...tab }; - if (tabInfoEqual(s.tabs[idx]!, nextTab)) return {}; + if (tabInfoEqual(s.tabs[idx]!, tab)) return {}; const next = s.tabs.slice(); - next[idx] = nextTab; + next[idx] = tab; return { tabs: next }; }), setActive: (tabId) => set((state) => (state.activeTabId === tabId ? {} : { activeTabId: tabId })), @@ -157,6 +156,26 @@ function tabInfoEqual(a: BrowserTabInfo, b: BrowserTabInfo): boolean { a.canGoBack === b.canGoBack && a.canGoForward === b.canGoForward && a.devToolsOpen === b.devToolsOpen && + a.internalPage === b.internalPage && + a.zoomFactor === b.zoomFactor && + deviceEmulationEqual(a.deviceEmulation, b.deviceEmulation) && a.groupId === b.groupId ); } + +function deviceEmulationEqual( + a: BrowserTabInfo["deviceEmulation"], + b: BrowserTabInfo["deviceEmulation"], +): boolean { + if (a === b) return true; + if (!a || !b) return false; + return ( + a.width === b.width && + a.height === b.height && + a.deviceScaleFactor === b.deviceScaleFactor && + a.scale === b.scale && + a.mobile === b.mobile && + a.touch === b.touch && + a.preset === b.preset + ); +} diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.test.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.test.tsx index eda3eea6e..cbdf41904 100644 --- a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.test.tsx +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.test.tsx @@ -1,6 +1,7 @@ -import { act, fireEvent } from "@testing-library/react"; +import { act, fireEvent, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; import { usePanelStore } from "@/renderer/state/panelStore"; import { BrowserPanel } from "./BrowserPanel"; @@ -8,8 +9,12 @@ import { BrowserPanel } from "./BrowserPanel"; const bridge = vi.hoisted(() => ({ browserCreateTab: vi.fn<() => Promise>().mockResolvedValue(undefined), browserAttachWebContents: vi.fn<() => Promise>().mockResolvedValue(undefined), + browserSetDeviceEmulation: vi.fn<() => Promise>().mockResolvedValue(undefined), browserReload: vi.fn<() => Promise>().mockResolvedValue(undefined), browserHardReload: vi.fn<() => Promise>().mockResolvedValue(undefined), + browserFindInPage: vi.fn<() => Promise>().mockResolvedValue(undefined), + browserStopFindInPage: vi.fn<() => Promise>().mockResolvedValue(undefined), + browserPrint: vi.fn<() => Promise<{ ok: true }>>().mockResolvedValue({ ok: true }), browserExtractToWindow: vi.fn<() => Promise>().mockResolvedValue(undefined), browserInjectToMain: vi.fn<() => Promise>().mockResolvedValue(undefined), })); @@ -33,14 +38,31 @@ vi.mock("./parts/BrowserTabStrip", () => ({ BrowserTabStrip: () =>
, })); +vi.mock("./parts/BrowserDownloadsPage", () => ({ + BrowserDownloadsPage: () =>
, +})); + +vi.mock("./parts/BrowserPasswordsPage", () => ({ + BrowserPasswordsPage: () =>
, +})); + +vi.mock("./parts/BrowserImportModal", () => ({ + BrowserImportModal: () => null, +})); + vi.mock("@/renderer/bridge", () => ({ isMac: () => false, isWindows: () => false, + isRemoteSession: () => false, readBridge: () => ({ browserCreateTab: bridge.browserCreateTab, browserAttachWebContents: bridge.browserAttachWebContents, + browserSetDeviceEmulation: bridge.browserSetDeviceEmulation, browserReload: bridge.browserReload, browserHardReload: bridge.browserHardReload, + browserFindInPage: bridge.browserFindInPage, + browserStopFindInPage: bridge.browserStopFindInPage, + browserPrint: bridge.browserPrint, browserExtractToWindow: bridge.browserExtractToWindow, browserInjectToMain: bridge.browserInjectToMain, }), @@ -60,6 +82,14 @@ describe("BrowserPanel", () => { attentionTabId: null, automationActive: false, }); + useBrowserFindStore.setState({ + tabId: null, + query: "", + matchCase: false, + matches: 0, + currentIndex: -1, + openToken: 0, + }); usePanelStore.setState({ browserPanelOpen: false, browserOverlayOpen: false, @@ -99,8 +129,38 @@ describe("BrowserPanel", () => { expect(webviews).toHaveLength(2); expect(webviews[0]?.getAttribute("partition")).toBe("persist:lightcode-browser"); expect(webviews[0]?.getAttribute("allowpopups")).toBe("true"); - expect((webviews[0] as HTMLElement).style.display).toBe("flex"); - expect((webviews[1] as HTMLElement).style.display).toBe("none"); + expect((webviews[0]!.parentElement!.parentElement as HTMLElement).style.display).toBe("block"); + expect((webviews[1]!.parentElement!.parentElement as HTMLElement).style.display).toBe("none"); + }); + + it("does not mount webviews for internal browser pages", () => { + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }, + { + tabId: "downloads", + url: "poracode://downloads", + title: "Downloads", + loading: false, + canGoBack: false, + canGoForward: false, + internalPage: "downloads", + }, + ], + activeTabId: "downloads", + }); + + const { container } = render(); + const webviews = container.querySelectorAll("webview"); + expect(webviews).toHaveLength(1); + expect(webviews[0]?.getAttribute("data-tab-id")).toBe("tab-1"); }); it("updates tab group membership from browser state", () => { @@ -132,6 +192,38 @@ describe("BrowserPanel", () => { expect(useBrowserPanelStore.getState().tabs[0]?.groupId).toBe("group-1"); }); + it("clears optional tab state when a full tab update omits it", () => { + const tab = { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }; + useBrowserPanelStore.setState({ + tabs: [ + { + ...tab, + internalPage: "downloads", + deviceEmulation: { + width: 1280, + height: 720, + deviceScaleFactor: 1, + scale: 0.75, + mobile: false, + touch: false, + }, + }, + ], + activeTabId: "tab-1", + }); + + act(() => useBrowserPanelStore.getState().upsertTab(tab)); + + expect(useBrowserPanelStore.getState().tabs[0]).toEqual(tab); + }); + it("keeps the same webview mounted when browser panel goes fullscreen", () => { useBrowserPanelStore.setState({ tabs: [ @@ -164,6 +256,163 @@ describe("BrowserPanel", () => { expect(container.querySelector("webview")).toBe(webview); }); + it("focuses the browser when its overlay opens", () => { + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }, + ], + activeTabId: "tab-1", + }); + const { container } = render(); + const outside = document.createElement("input"); + document.body.append(outside); + outside.focus(); + + act(() => usePanelStore.setState({ browserOverlayOpen: true })); + + expect(document.activeElement).toBe(container.querySelector("[data-poracode-browser]")); + outside.remove(); + }); + + it("focuses the standalone browser window on mount", () => { + const outside = document.createElement("input"); + document.body.append(outside); + outside.focus(); + + const { container } = render(); + + expect(document.activeElement).toBe(container.querySelector("[data-poracode-browser]")); + outside.remove(); + }); + + it("keeps the same webview mounted when device emulation changes", () => { + const tab = { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }; + useBrowserPanelStore.setState({ tabs: [tab], activeTabId: "tab-1" }); + const { container } = render(); + const webview = container.querySelector("webview"); + + act(() => { + useBrowserPanelStore.getState().setState({ + tabs: [ + { + ...tab, + deviceEmulation: { + width: 833, + height: 970, + deviceScaleFactor: 1, + scale: 1, + mobile: false, + touch: false, + preset: "Responsive", + }, + }, + ], + activeTabId: "tab-1", + }); + }); + + expect(container.querySelector("webview")).toBe(webview); + expect((webview!.parentElement as HTMLElement).style.width).toBe("833px"); + expect((webview!.parentElement as HTMLElement).style.height).toBe("970px"); + }); + + it("resizes an emulated viewport without remounting its webview", async () => { + const emulation = { + width: 833, + height: 970, + deviceScaleFactor: 1, + scale: 0.5, + mobile: false, + touch: false, + preset: "Responsive", + }; + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + deviceEmulation: emulation, + }, + ], + activeTabId: "tab-1", + }); + const { container, getByRole } = render(); + const webview = container.querySelector("webview"); + const viewport = webview?.parentElement as HTMLElement; + + fireEvent.pointerDown(getByRole("button", { name: "Resize viewport" }), { + clientX: 100, + clientY: 100, + }); + fireEvent.pointerMove(window, { clientX: 150, clientY: 125 }); + + await waitFor(() => { + expect(viewport.style.width).toBe("466.5px"); + expect(viewport.style.height).toBe("510px"); + }); + expect(container.querySelector("webview")).toBe(webview); + + fireEvent.pointerUp(window); + expect(bridge.browserSetDeviceEmulation).toHaveBeenLastCalledWith({ + tabId: "tab-1", + emulation: { ...emulation, width: 933, height: 1020 }, + }); + }); + + it("stops an emulated viewport drag when the webview unmounts", () => { + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + deviceEmulation: { + width: 833, + height: 970, + deviceScaleFactor: 1, + scale: 1, + mobile: false, + touch: false, + }, + }, + ], + activeTabId: "tab-1", + }); + const { getByRole, unmount } = render(); + + fireEvent.pointerDown(getByRole("button", { name: "Resize viewport" }), { + clientX: 100, + clientY: 100, + }); + unmount(); + bridge.browserSetDeviceEmulation.mockClear(); + fireEvent.pointerMove(window, { clientX: 150, clientY: 150 }); + fireEvent.pointerUp(window); + + expect(bridge.browserSetDeviceEmulation).not.toHaveBeenCalled(); + }); + it("attaches the right-panel webview contents to the browser tab", () => { useBrowserPanelStore.setState({ tabs: [ @@ -251,6 +500,54 @@ describe("BrowserPanel", () => { expect(bridge.browserHardReload).toHaveBeenCalledTimes(2); }); + it("opens Find in page from the panel shortcut", () => { + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }, + ], + activeTabId: "tab-1", + }); + const { container, getByRole } = render(); + + fireEvent.keyDown(container.querySelector("[data-poracode-browser]")!, { + key: "f", + ctrlKey: true, + }); + + expect(getByRole("textbox", { name: "Find in page" })).toBeTruthy(); + }); + + it("does not treat Ctrl+Alt chords as Find or Print shortcuts", () => { + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }, + ], + activeTabId: "tab-1", + }); + const { container, queryByRole } = render(); + const panel = container.querySelector("[data-poracode-browser]")!; + + fireEvent.keyDown(panel, { key: "f", ctrlKey: true, altKey: true }); + fireEvent.keyDown(panel, { key: "p", ctrlKey: true, altKey: true }); + + expect(queryByRole("textbox", { name: "Find in page" })).toBeNull(); + expect(bridge.browserPrint).not.toHaveBeenCalled(); + }); + it("moves the overlay browser to a separate window", () => { usePanelStore.setState({ browserOverlayOpen: true, diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx index c20204829..8a009534f 100644 --- a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/BrowserPanel.tsx @@ -12,6 +12,7 @@ import { } from "lucide-react"; import { isMac, readBridge } from "@/renderer/bridge"; import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; import { usePanelStore } from "@/renderer/state/panelStore"; import { macosTrafficLightGutterClass, @@ -19,7 +20,13 @@ import { panelHeaderIconButtonClass, } from "@/renderer/components/layout/sidebarChrome"; import { BrowserBookmarkBar } from "./parts/BrowserBookmarkBar"; +import { BrowserDeviceToolbar } from "./parts/BrowserDeviceToolbar"; +import { BrowserDownloadsPage } from "./parts/BrowserDownloadsPage"; import { BrowserEmptyState } from "./parts/BrowserEmptyState"; +import { BrowserFindBar } from "./parts/BrowserFindBar"; +import { BrowserImportModal } from "./parts/BrowserImportModal"; +import { BrowserPasswordsPage } from "./parts/BrowserPasswordsPage"; +import { BrowserTabWebview } from "./parts/BrowserTabWebview"; import { BrowserTabStrip } from "./parts/BrowserTabStrip"; import { BrowserToolbar } from "./parts/BrowserToolbar"; import { extractBrowserToWindow, injectBrowserToMain } from "./browserWindowActions"; @@ -51,8 +58,13 @@ export function BrowserPanel(props: { visible: boolean; surface?: "main" | "wind } = useElementPicker(); const everHadTabsRef = useRef(false); const hasActiveTab = tabs.length > 0 && activeTabId !== null; + const activeTab = activeTabId ? tabs.find((tab) => tab.tabId === activeTabId) : undefined; const rootRef = useRef(null); + useEffect(() => { + if (browserOverlayOpen || isWindowSurface) rootRef.current?.focus({ preventScroll: true }); + }, [browserOverlayOpen, isWindowSurface]); + const createTab = useCallback(() => { void readBridge() .browserCreateTab({ url: DEFAULT_HOME, activate: true }) @@ -67,7 +79,24 @@ export function BrowserPanel(props: { visible: boolean; surface?: "main" | "wind const el = rootRef.current; if (!el) return; const handleKeyDown = (event: KeyboardEvent) => { - if (!activeTabId || !isBrowserReloadShortcut(event)) return; + if (!activeTabId) return; + if (isBrowserFindShortcut(event)) { + if (activeTab?.internalPage) return; + event.preventDefault(); + event.stopPropagation(); + useBrowserFindStore.getState().open(activeTabId); + return; + } + if (isBrowserPrintShortcut(event)) { + if (activeTab?.internalPage) return; + event.preventDefault(); + event.stopPropagation(); + readBridge() + .browserPrint({ tabId: activeTabId }) + .catch(() => {}); + return; + } + if (!isBrowserReloadShortcut(event)) return; event.preventDefault(); event.stopPropagation(); const bridge = readBridge(); @@ -79,7 +108,7 @@ export function BrowserPanel(props: { visible: boolean; surface?: "main" | "wind }; el.addEventListener("keydown", handleKeyDown); return () => el.removeEventListener("keydown", handleKeyDown); - }, [activeTabId]); + }, [activeTab?.internalPage, activeTabId]); const onPick = useCallback(() => { void startPicker(); @@ -130,6 +159,7 @@ export function BrowserPanel(props: { visible: boolean; surface?: "main" | "wind ref={rootRef} data-poracode-browser="" role="group" + tabIndex={-1} aria-label={t`Browser`} className="flex h-full w-full min-h-0 flex-col bg-[var(--content-background)]" > @@ -232,15 +262,29 @@ export function BrowserPanel(props: { visible: boolean; surface?: "main" | "wind /> {hasWindowHeader ? null : } +
- {tabs.map((tab) => ( - - ))} + {tabs + .filter((tab) => !tab.internalPage) + .map((tab) => ( + + ))} + {activeTab?.internalPage === "downloads" ? ( +
+ +
+ ) : activeTab?.internalPage === "passwords" ? ( +
+ +
+ ) : null} + {menuPreviewDataUrl ? ( ) : null}
+
); } @@ -333,64 +378,25 @@ function BrowserDeviceCodeButton() { ); } -function BrowserTabWebview(props: { tabId: string; initialSrc: string; visible: boolean }) { - const ref = useRef(null); - const initialSrcRef = useRef(props.initialSrc); - - useEffect(() => { - const el = ref.current; - if (!el) return; - let cancelled = false; - const onDomReady = () => { - if (cancelled) return; - let webContentsId: number; - try { - webContentsId = el.getWebContentsId(); - } catch { - return; - } - readBridge() - .browserAttachWebContents({ tabId: props.tabId, webContentsId }) - .catch(() => {}); - }; - el.addEventListener("dom-ready", onDomReady); - return () => { - cancelled = true; - el.removeEventListener("dom-ready", onDomReady); - }; - }, [props.tabId]); - - useEffect(() => { - if (!props.visible) return; - const el = ref.current; - if (!el) return; - let webContentsId: number; - try { - webContentsId = el.getWebContentsId(); - } catch { - return; - } - readBridge() - .browserAttachWebContents({ tabId: props.tabId, webContentsId }) - .catch(() => {}); - }, [props.tabId, props.visible]); +function isBrowserReloadShortcut(event: KeyboardEvent): boolean { + if (event.key === "F5") return true; + return (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "r"; +} +function isBrowserFindShortcut(event: KeyboardEvent): boolean { return ( - + (event.ctrlKey || event.metaKey) && + !event.shiftKey && + !event.altKey && + event.key.toLowerCase() === "f" ); } -function isBrowserReloadShortcut(event: KeyboardEvent): boolean { - if (event.key === "F5") return true; - return (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "r"; +function isBrowserPrintShortcut(event: KeyboardEvent): boolean { + return ( + (event.ctrlKey || event.metaKey) && + !event.shiftKey && + !event.altKey && + event.key.toLowerCase() === "p" + ); } diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/hooks/useBrowserSync.ts b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/hooks/useBrowserSync.ts index 2731fffef..ed1d21fbe 100644 --- a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/hooks/useBrowserSync.ts +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/hooks/useBrowserSync.ts @@ -1,5 +1,8 @@ import { useEffect } from "react"; import { readBridge } from "@/renderer/bridge"; +import { useBrowserCredentialsStore } from "@/renderer/state/browserCredentialsStore"; +import { useBrowserDownloadsStore } from "@/renderer/state/browserDownloadsStore"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; import { selectAnyObstructingOverlayOpen, usePanelStore } from "@/renderer/state/panelStore"; @@ -13,6 +16,11 @@ export function useBrowserSync(): void { const clearUsageLoginConfirmation = useBrowserPanelStore((s) => s.clearUsageLoginConfirmation); const setUsageLoginDeviceCode = useBrowserPanelStore((s) => s.setUsageLoginDeviceCode); const clearUsageLoginDeviceCode = useBrowserPanelStore((s) => s.clearUsageLoginDeviceCode); + const applyFindResult = useBrowserFindStore((s) => s.applyResult); + const openFind = useBrowserFindStore((s) => s.open); + const upsertDownload = useBrowserDownloadsStore((s) => s.upsertDownload); + const removeDownload = useBrowserDownloadsStore((s) => s.removeDownload); + const invalidateCredentials = useBrowserCredentialsStore((s) => s.invalidate); useEffect(() => { let cancelled = false; @@ -40,6 +48,16 @@ export function useBrowserSync(): void { upsertTab(event.tab); } else if (event.type === "tab-attention") { setAttention(event.tabId); + } else if (event.type === "find-open-requested") { + openFind(event.tabId); + } else if (event.type === "find-result") { + applyFindResult(event.result); + } else if (event.type === "download-updated") { + upsertDownload(event.download); + } else if (event.type === "download-removed") { + removeDownload(event.downloadId); + } else if (event.type === "credentials-updated") { + invalidateCredentials(); } else if (event.type === "open-panel") { if (!reactsToPresentation()) return; const panel = usePanelStore.getState(); @@ -91,5 +109,10 @@ export function useBrowserSync(): void { clearUsageLoginConfirmation, setUsageLoginDeviceCode, clearUsageLoginDeviceCode, + applyFindResult, + openFind, + upsertDownload, + removeDownload, + invalidateCredentials, ]); } diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.test.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.test.tsx new file mode 100644 index 000000000..769cc51e1 --- /dev/null +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.test.tsx @@ -0,0 +1,115 @@ +import { act, fireEvent } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; +import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import { BrowserDeviceToolbar } from "./BrowserDeviceToolbar"; + +const bridge = vi.hoisted(() => ({ + browserSetDeviceEmulation: vi.fn<() => Promise>().mockResolvedValue(undefined), +})); + +vi.mock("@/renderer/bridge", () => ({ + readBridge: () => bridge, + isRemoteSession: () => false, +})); + +const emulation = { + width: 833, + height: 970, + deviceScaleFactor: 1, + scale: 1, + mobile: false, + touch: false, + preset: "Responsive", +}; + +describe("BrowserDeviceToolbar", () => { + beforeEach(() => { + vi.clearAllMocks(); + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + deviceEmulation: emulation, + }, + ], + activeTabId: "tab-1", + }); + }); + + it("updates dimensions, rotates the viewport, and closes emulation", () => { + const { getByRole } = render(); + const width = getByRole("spinbutton", { name: "Viewport width" }); + + fireEvent.change(width, { target: { value: "500" } }); + fireEvent.blur(width); + expect(bridge.browserSetDeviceEmulation).toHaveBeenLastCalledWith({ + tabId: "tab-1", + emulation: { ...emulation, width: 500, preset: "Responsive" }, + }); + + fireEvent.click(getByRole("button", { name: "Rotate viewport" })); + expect(bridge.browserSetDeviceEmulation).toHaveBeenLastCalledWith({ + tabId: "tab-1", + emulation: { ...emulation, width: 970, height: 833 }, + }); + + fireEvent.click(getByRole("button", { name: "Close device toolbar" })); + expect(bridge.browserSetDeviceEmulation).toHaveBeenLastCalledWith({ + tabId: "tab-1", + emulation: null, + }); + }); + + it("does not render for an internal browser page", () => { + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "poracode://downloads", + title: "Downloads", + loading: false, + canGoBack: false, + canGoForward: false, + internalPage: "downloads", + deviceEmulation: emulation, + }, + ], + }); + + const { queryByText } = render(); + expect(queryByText("Dimensions:")).toBeNull(); + }); + + it("discards an uncommitted dimension when the active tab changes", () => { + const { getByRole } = render(); + fireEvent.change(getByRole("spinbutton", { name: "Viewport width" }), { + target: { value: "500" }, + }); + + act(() => { + useBrowserPanelStore.setState({ + tabs: [ + ...useBrowserPanelStore.getState().tabs, + { + tabId: "tab-2", + url: "https://example.org/", + title: "Example 2", + loading: false, + canGoBack: false, + canGoForward: false, + deviceEmulation: emulation, + }, + ], + activeTabId: "tab-2", + }); + }); + + expect(getByRole("spinbutton", { name: "Viewport width" })).toHaveValue(833); + }); +}); diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx new file mode 100644 index 000000000..38a7f24a1 --- /dev/null +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserDeviceToolbar.tsx @@ -0,0 +1,267 @@ +import { useEffect, useState } from "react"; +import { Button, Input, TextField } from "@heroui/react"; +import { Trans, useLingui } from "@lingui/react/macro"; +import { RotateCw, X } from "lucide-react"; +import { readBridge } from "@/renderer/bridge"; +import { Select } from "@/renderer/components/common"; +import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; +import type { BrowserDeviceEmulation, BrowserTabInfo } from "@/shared/ipc"; + +interface DevicePreset extends Omit { + id: string; + label: string; +} + +const scaleValues = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2] as const; + +export function BrowserDeviceToolbar() { + const activeTab = useBrowserPanelStore((state) => + state.activeTabId ? state.tabs.find((tab) => tab.tabId === state.activeTabId) : undefined, + ); + if (!activeTab?.deviceEmulation || activeTab.internalPage) return null; + return ; +} + +function ActiveBrowserDeviceToolbar({ tab }: { tab: BrowserTabInfo }) { + const { t } = useLingui(); + const emulation = tab.deviceEmulation!; + const [widthDraft, setWidthDraft] = useState(String(emulation.width)); + const [heightDraft, setHeightDraft] = useState(String(emulation.height)); + + useEffect(() => setWidthDraft(String(emulation.width)), [emulation.width]); + useEffect(() => setHeightDraft(String(emulation.height)), [emulation.height]); + + const presets: DevicePreset[] = [ + { + id: "Responsive", + label: t`Responsive`, + width: emulation.width, + height: emulation.height, + deviceScaleFactor: 1, + mobile: false, + touch: false, + }, + { + id: "4K", + label: t`4K`, + width: 3840, + height: 2160, + deviceScaleFactor: 1, + mobile: false, + touch: false, + }, + { + id: "Laptop L", + label: t`Laptop L`, + width: 1440, + height: 900, + deviceScaleFactor: 1, + mobile: false, + touch: false, + }, + { + id: "Laptop", + label: t`Laptop`, + width: 1024, + height: 768, + deviceScaleFactor: 1, + mobile: false, + touch: false, + }, + { + id: "Surface Pro 7", + label: t`Surface Pro 7`, + width: 912, + height: 1368, + deviceScaleFactor: 2, + mobile: true, + touch: true, + }, + { + id: "iPad Air", + label: t`iPad Air`, + width: 820, + height: 1180, + deviceScaleFactor: 2, + mobile: true, + touch: true, + }, + { + id: "iPad Mini", + label: t`iPad Mini`, + width: 768, + height: 1024, + deviceScaleFactor: 2, + mobile: true, + touch: true, + }, + { + id: "Surface Duo", + label: t`Surface Duo`, + width: 540, + height: 720, + deviceScaleFactor: 2.5, + mobile: true, + touch: true, + }, + { + id: "iPhone 15 Pro Max", + label: t`iPhone 15 Pro Max`, + width: 430, + height: 932, + deviceScaleFactor: 3, + mobile: true, + touch: true, + }, + { + id: "Pixel 8", + label: t`Pixel 8`, + width: 412, + height: 915, + deviceScaleFactor: 2.625, + mobile: true, + touch: true, + }, + { + id: "iPhone 15 Pro", + label: t`iPhone 15 Pro`, + width: 393, + height: 852, + deviceScaleFactor: 3, + mobile: true, + touch: true, + }, + { + id: "Samsung Galaxy S24 Ultra", + label: t`Samsung Galaxy S24 Ultra`, + width: 412, + height: 915, + deviceScaleFactor: 3.5, + mobile: true, + touch: true, + }, + { + id: "iPhone SE", + label: t`iPhone SE`, + width: 375, + height: 667, + deviceScaleFactor: 2, + mobile: true, + touch: true, + }, + ]; + const scaleOptions = scaleValues.map((scale) => ({ + id: String(scale), + label: `${Math.round(scale * 100)}%`, + })); + + function update(nextEmulation: BrowserDeviceEmulation | null) { + readBridge() + .browserSetDeviceEmulation({ tabId: tab.tabId, emulation: nextEmulation }) + .catch(() => {}); + } + + function selectPreset(id: string) { + const preset = presets.find((candidate) => candidate.id === id); + if (!preset) return; + update({ + width: preset.width, + height: preset.height, + deviceScaleFactor: preset.deviceScaleFactor, + scale: emulation.scale, + mobile: preset.mobile, + touch: preset.touch, + preset: preset.id, + }); + } + + function commitDimension(dimension: "width" | "height", draft: string) { + const value = Number.parseInt(draft, 10); + if (!Number.isInteger(value) || value < 240 || value > 7680) { + if (dimension === "width") setWidthDraft(String(emulation.width)); + else setHeightDraft(String(emulation.height)); + return; + } + update({ ...emulation, [dimension]: value, preset: "Responsive" }); + } + + return ( +
+ + Dimensions: + + { + if (event.key === "Enter") event.currentTarget.blur(); + }} + /> + + + × + + commitDimension("height", heightDraft)} + > + { + if (event.key === "Enter") event.currentTarget.blur(); + }} + /> + + + setQuery(event.currentTarget.value)} + className="pl-8 text-xs" + /> +
+
+ + + {visibleDownloads.length === 0 ? ( +
+
+ + + +
+
+

+ {downloads.length === 0 ? ( + Files you download appear here + ) : ( + No downloads match your search + )} +

+ {downloads.length === 0 ? ( +

+ Downloads from the built-in browser are saved in this history. +

+ ) : null} +
+
+ ) : ( +
+
+ {visibleDownloads.map((download) => ( + void runAction(download, action)} + /> + ))} +
+
+ )} +
+ ); +} + +function DownloadRow(props: { + download: BrowserDownloadInfo; + busy: boolean; + onAction: (action: DownloadAction) => void; +}) { + const { t } = useLingui(); + const { download } = props; + const progress = + download.totalBytes > 0 + ? Math.min(100, Math.round((download.receivedBytes / download.totalBytes) * 100)) + : download.state === "completed" + ? 100 + : null; + const transferLabel = + download.totalBytes > 0 + ? `${formatBytes(download.receivedBytes)} / ${formatBytes(download.totalBytes)}` + : formatBytes(download.receivedBytes); + const indeterminate = progress === null && download.state === "progressing"; + + return ( +
+
+ + + +
+

+ {download.filename} +

+

+ {downloadSource(download.url)} +

+
+
+ {download.state === "progressing" || download.state === "paused" ? ( + + ) : null} + {download.state === "interrupted" && download.canResume ? ( + + ) : null} + {download.state === "progressing" || download.state === "paused" ? ( + + ) : null} + {download.state === "completed" ? ( + <> + + + + ) : null} + {download.state === "completed" || + download.state === "cancelled" || + download.state === "interrupted" ? ( + + ) : null} +
+
+ +
+
+
+
+
+ + {transferLabel} +
+
+
+ ); +} + +function DownloadStateLabel(props: { download: BrowserDownloadInfo }) { + switch (props.download.state) { + case "progressing": + return Downloading; + case "paused": + return Paused; + case "completed": + return Completed; + case "cancelled": + return Cancelled; + case "interrupted": + return props.download.canResume ? Interrupted : Download failed; + } +} + +function downloadSource(url: string): string { + try { + return new URL(url).hostname || url; + } catch { + return url; + } +} diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.test.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.test.tsx new file mode 100644 index 000000000..7b47dff56 --- /dev/null +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.test.tsx @@ -0,0 +1,161 @@ +import { act, fireEvent } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; +import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; +import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import { BrowserFindBar } from "./BrowserFindBar"; + +const bridge = vi.hoisted(() => ({ + browserFindInPage: vi.fn<() => Promise>().mockResolvedValue(undefined), + browserStopFindInPage: vi.fn<() => Promise>().mockResolvedValue(undefined), +})); + +vi.mock("@/renderer/bridge", () => ({ readBridge: () => bridge })); + +describe("BrowserFindBar", () => { + beforeEach(() => { + vi.clearAllMocks(); + useBrowserFindStore.setState({ + tabId: null, + query: "", + matchCase: false, + matches: 0, + currentIndex: -1, + openToken: 0, + }); + useBrowserPanelStore.setState({ + tabs: [ + { + tabId: "tab-1", + url: "https://example.com/", + title: "Example", + loading: false, + canGoBack: false, + canGoForward: false, + }, + ], + activeTabId: "tab-1", + }); + }); + + it("starts a new search for edits and continues it for match navigation", () => { + act(() => useBrowserFindStore.getState().open("tab-1")); + const { getByRole } = render(); + const input = getByRole("textbox", { name: "Find in page" }); + + fireEvent.change(input, { target: { value: "needle" } }); + expect(bridge.browserFindInPage).toHaveBeenNthCalledWith(1, { + tabId: "tab-1", + text: "needle", + forward: true, + findNext: true, + matchCase: false, + }); + + fireEvent.keyDown(input, { key: "Enter" }); + expect(bridge.browserFindInPage).toHaveBeenNthCalledWith(2, { + tabId: "tab-1", + text: "needle", + forward: true, + findNext: false, + matchCase: false, + }); + + fireEvent.keyDown(input, { key: "Enter", shiftKey: true }); + expect(bridge.browserFindInPage).toHaveBeenNthCalledWith(3, { + tabId: "tab-1", + text: "needle", + forward: false, + findNext: false, + matchCase: false, + }); + + fireEvent.click(getByRole("button", { name: "Match case" })); + expect(bridge.browserFindInPage).toHaveBeenNthCalledWith(4, { + tabId: "tab-1", + text: "needle", + forward: true, + findNext: true, + matchCase: true, + }); + }); + + it("clears the native selection when the query is cleared or the bar closes", () => { + act(() => useBrowserFindStore.getState().open("tab-1")); + const { getByRole, queryByRole } = render(); + const input = getByRole("textbox", { name: "Find in page" }); + + fireEvent.change(input, { target: { value: "needle" } }); + fireEvent.change(input, { target: { value: "" } }); + expect(bridge.browserStopFindInPage).toHaveBeenLastCalledWith({ + tabId: "tab-1", + action: "clearSelection", + }); + + bridge.browserStopFindInPage.mockClear(); + fireEvent.click(getByRole("button", { name: "Close find" })); + expect(bridge.browserStopFindInPage).toHaveBeenCalledWith({ + tabId: "tab-1", + action: "clearSelection", + }); + expect(useBrowserFindStore.getState().tabId).toBeNull(); + expect(queryByRole("textbox", { name: "Find in page" })).toBeNull(); + }); + + it("focuses and selects the query again when find is reopened", () => { + useBrowserFindStore.setState({ tabId: "tab-1", query: "needle", openToken: 1 }); + const { getByRole } = render(); + const input = getByRole("textbox", { name: "Find in page" }) as HTMLInputElement; + expect(document.activeElement).toBe(input); + + input.setSelectionRange(0, 0); + act(() => useBrowserFindStore.getState().open("tab-1")); + + expect(document.activeElement).toBe(input); + expect(input.selectionStart).toBe(0); + expect(input.selectionEnd).toBe(6); + }); + + it("hides a find session that does not belong to the active page", () => { + useBrowserFindStore.setState({ tabId: "tab-1", query: "needle", openToken: 1 }); + useBrowserPanelStore.setState({ activeTabId: null }); + + const { queryByRole } = render(); + expect(queryByRole("textbox", { name: "Find in page" })).toBeNull(); + }); + + it("stops and closes the find session when the active page changes", () => { + useBrowserFindStore.setState({ tabId: "tab-1", query: "needle", openToken: 1 }); + render(); + + act(() => useBrowserPanelStore.setState({ activeTabId: null })); + + expect(bridge.browserStopFindInPage).toHaveBeenCalledWith({ + tabId: "tab-1", + action: "clearSelection", + }); + expect(useBrowserFindStore.getState().tabId).toBeNull(); + }); + + it("does not restore stale find results after switching away and back", () => { + useBrowserFindStore.setState({ + tabId: "tab-1", + query: "needle", + matches: 2, + currentIndex: 0, + openToken: 1, + }); + const { queryByRole } = render(); + + act(() => useBrowserPanelStore.setState({ activeTabId: null })); + act(() => useBrowserPanelStore.setState({ activeTabId: "tab-1" })); + + expect(queryByRole("textbox", { name: "Find in page" })).toBeNull(); + expect(useBrowserFindStore.getState()).toMatchObject({ + tabId: null, + query: "", + matches: 0, + currentIndex: -1, + }); + }); +}); diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx new file mode 100644 index 000000000..9b166b3b1 --- /dev/null +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserFindBar.tsx @@ -0,0 +1,88 @@ +import { useEffect, useRef } from "react"; +import { useLingui } from "@lingui/react/macro"; +import { readBridge } from "@/renderer/bridge"; +import { FindBar } from "@/renderer/components/find/FindBar"; +import { useFindBarChrome } from "@/renderer/components/find/useFindBarChrome"; +import { useBrowserFindStore } from "@/renderer/state/browserFindStore"; +import { useBrowserPanelStore } from "@/renderer/state/browserPanelStore"; + +export function BrowserFindBar() { + const tabId = useBrowserFindStore((state) => state.tabId); + const activeTab = useBrowserPanelStore((state) => + state.activeTabId ? state.tabs.find((tab) => tab.tabId === state.activeTabId) : undefined, + ); + if (!tabId || activeTab?.tabId !== tabId || activeTab.internalPage) return null; + return ; +} + +function ActiveBrowserFindBar({ tabId }: { tabId: string }) { + const { t } = useLingui(); + const inputRef = useRef(null); + const query = useBrowserFindStore((state) => state.query); + const matchCase = useBrowserFindStore((state) => state.matchCase); + const matches = useBrowserFindStore((state) => state.matches); + const currentIndex = useBrowserFindStore((state) => state.currentIndex); + const openToken = useBrowserFindStore((state) => state.openToken); + const setQuery = useBrowserFindStore((state) => state.setQuery); + const toggleMatchCase = useBrowserFindStore((state) => state.toggleMatchCase); + const close = useBrowserFindStore((state) => state.close); + + useEffect( + () => () => { + readBridge() + .browserStopFindInPage({ tabId, action: "clearSelection" }) + .catch(() => {}); + const findState = useBrowserFindStore.getState(); + if (findState.tabId === tabId) findState.close(); + }, + [tabId], + ); + + function find(text: string, forward: boolean, findNext: boolean, nextMatchCase = matchCase) { + if (!text) return; + readBridge() + .browserFindInPage({ tabId, text, forward, findNext, matchCase: nextMatchCase }) + .catch(() => {}); + } + + function onQueryChange(nextQuery: string) { + setQuery(nextQuery); + if (!nextQuery) { + readBridge() + .browserStopFindInPage({ tabId, action: "clearSelection" }) + .catch(() => {}); + return; + } + find(nextQuery, true, true); + } + + function onToggleMatchCase() { + const nextMatchCase = !matchCase; + toggleMatchCase(); + find(query, true, true, nextMatchCase); + } + + function onClose() { + close(); + } + + useFindBarChrome(inputRef, openToken, onClose); + + return ( +
+ find(query, true, false)} + onPrev={() => find(query, false, false)} + onClose={onClose} + placeholder={t`Find in page`} + /> +
+ ); +} diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.test.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.test.tsx new file mode 100644 index 000000000..3fcdc6f2f --- /dev/null +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.test.tsx @@ -0,0 +1,100 @@ +import { fireEvent, screen, waitFor } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useBrowserImportStore } from "@/renderer/state/browserImportStore"; +import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import type { BrowserImportResult, BrowserImportSourceInfo } from "@/shared/ipc"; +import { BrowserImportModal } from "./BrowserImportModal"; + +type ImportDataPayload = { + sourceId: string; + passwords: boolean; + cookies: boolean; + acknowledgeProtectedData: boolean; +}; + +const bridge = vi.hoisted(() => ({ + browserListImportSources: vi.fn<() => Promise>(), + browserImportData: vi.fn<(payload: ImportDataPayload) => Promise>(), +})); + +vi.mock("@/renderer/bridge", () => ({ + readBridge: () => bridge, + isRemoteSession: () => false, +})); + +const source: BrowserImportSourceInfo = { + id: "chrome:default", + browser: "chrome", + browserLabel: "Google Chrome", + profileLabel: "Default", + supportsPasswords: true, + supportsCookies: true, + hasAppBoundData: true, +}; + +describe("BrowserImportModal", () => { + beforeEach(() => { + bridge.browserListImportSources.mockReset().mockResolvedValue([source]); + bridge.browserImportData.mockReset().mockResolvedValue({ + passwordsImported: 1, + cookiesImported: 2, + passwordsSkipped: 0, + cookiesSkipped: 0, + protectedItemsSkipped: 0, + errors: [], + }); + useBrowserImportStore.setState({ open: true }); + }); + + it("requires acknowledgement before importing App-Bound protected data", async () => { + render(); + + expect(await screen.findByText("Protected browser data")).toBeInTheDocument(); + expect(screen.getByText(/Poracode does not bypass that protection/)).toBeInTheDocument(); + + const importButton = screen.getByRole("button", { name: "Import" }); + expect(importButton).toBeDisabled(); + + fireEvent.click( + screen.getByRole("checkbox", { + name: "I understand that protected browser data may be skipped.", + }), + ); + expect(importButton).toBeEnabled(); + + fireEvent.click(importButton); + + await waitFor(() => + expect(bridge.browserImportData).toHaveBeenCalledWith({ + sourceId: "chrome:default", + passwords: true, + cookies: true, + acknowledgeProtectedData: true, + }), + ); + expect(useBrowserImportStore.getState().open).toBe(false); + }); + + it("keeps the dialog open when no browser data could be imported", async () => { + bridge.browserImportData.mockResolvedValue({ + passwordsImported: 0, + cookiesImported: 0, + passwordsSkipped: 1, + cookiesSkipped: 1, + protectedItemsSkipped: 2, + errors: ["app-bound-data-skipped"], + }); + render(); + + await screen.findByText("Protected browser data"); + fireEvent.click( + screen.getByRole("checkbox", { + name: "I understand that protected browser data may be skipped.", + }), + ); + fireEvent.click(screen.getByRole("button", { name: "Import" })); + + await waitFor(() => expect(bridge.browserImportData).toHaveBeenCalledOnce()); + expect(useBrowserImportStore.getState().open).toBe(true); + }); +}); diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx new file mode 100644 index 000000000..974faa8ba --- /dev/null +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserImportModal.tsx @@ -0,0 +1,222 @@ +import { useEffect, useState } from "react"; +import { Button, Checkbox, Modal, toast } from "@heroui/react"; +import { Trans, useLingui } from "@lingui/react/macro"; +import { Cookie, KeyRound, Loader2, ShieldAlert } from "lucide-react"; +import { readBridge } from "@/renderer/bridge"; +import { Select, ToggleSwitch } from "@/renderer/components/common"; +import { useBrowserImportStore } from "@/renderer/state/browserImportStore"; +import type { BrowserImportSourceInfo } from "@/shared/ipc"; + +export function BrowserImportModal() { + const { t } = useLingui(); + const open = useBrowserImportStore((state) => state.open); + const setOpen = useBrowserImportStore((state) => state.setOpen); + const [sources, setSources] = useState([]); + const [sourceId, setSourceId] = useState(""); + const [passwords, setPasswords] = useState(true); + const [cookies, setCookies] = useState(true); + const [acknowledgeProtectedData, setAcknowledgeProtectedData] = useState(false); + const [loading, setLoading] = useState(false); + const [importing, setImporting] = useState(false); + + useEffect(() => { + if (!open) return; + let cancelled = false; + setSources([]); + setSourceId(""); + setLoading(true); + setAcknowledgeProtectedData(false); + readBridge() + .browserListImportSources() + .then((items) => { + if (cancelled) return; + setSources(items); + const first = items[0]; + setSourceId(first?.id ?? ""); + setPasswords(first?.supportsPasswords === true); + setCookies(first?.supportsCookies === true); + }) + .catch(() => { + if (!cancelled) toast.danger(t`Unable to find browser data to import.`); + }) + .finally(() => { + if (!cancelled) setLoading(false); + }); + return () => { + cancelled = true; + }; + }, [open, t]); + + const selectedSource = sources.find((source) => source.id === sourceId); + const needsProtectedDataAcknowledgement = + selectedSource?.hasAppBoundData === true && (passwords || cookies); + const canImport = + !!selectedSource && + ((passwords && selectedSource.supportsPasswords) || + (cookies && selectedSource.supportsCookies)) && + (!needsProtectedDataAcknowledgement || acknowledgeProtectedData); + const sourceOptions = sources.map((source) => ({ + id: source.id, + label: `${source.browserLabel} — ${source.profileLabel}`, + })); + + function selectSource(id: string) { + const source = sources.find((item) => item.id === id); + setSourceId(id); + setPasswords(source?.supportsPasswords === true); + setCookies(source?.supportsCookies === true); + setAcknowledgeProtectedData(false); + } + + async function importData() { + if (!selectedSource || !canImport) return; + setImporting(true); + try { + const result = await readBridge().browserImportData({ + sourceId: selectedSource.id, + passwords: passwords && selectedSource.supportsPasswords, + cookies: cookies && selectedSource.supportsCookies, + acknowledgeProtectedData, + }); + if (result.passwordsImported + result.cookiesImported === 0) { + toast.danger(t`Unable to import browser data.`); + return; + } + toast.success( + t`Imported passwords: ${result.passwordsImported}. Imported cookies: ${result.cookiesImported}.`, + ); + const skipped = + result.passwordsSkipped + result.cookiesSkipped + result.protectedItemsSkipped; + if (skipped > 0 || result.errors.length > 0) { + toast.warning( + t`Some browser data was skipped. Protected items skipped: ${result.protectedItemsSkipped}.`, + ); + } + setOpen(false); + } catch { + toast.danger(t`Unable to import browser data.`); + } finally { + setImporting(false); + } + } + + return ( + !nextOpen && !importing && setOpen(false)} + > + + + + + + Import from your browser + +

+ Choose data to bring over to the built-in browser. +

+
+ + {loading ? ( +
+ + Looking for browser profiles… +
+ ) : sources.length === 0 ? ( +
+ No supported browser profiles were found on this device. +
+ ) : ( + <> + setQuery(event.currentTarget.value)} + className="pl-8 text-xs" + /> + + + + + {visibleCredentials.length === 0 ? ( +
+ + + +
+

+ {credentials.length === 0 ? ( + No saved passwords + ) : ( + No passwords match your search + )} +

+ {credentials.length === 0 ? ( +

+ Add a password or import one from another browser. +

+ ) : null} +
+
+ ) : ( +
+ {visibleCredentials.map((credential, index) => { + const revealedPassword = revealedPasswords[credential.id]; + const busy = busyCredentialId === credential.id; + return ( +
0 ? "border-t border-border" : ""}`} + > + + + +
+

+ {credential.origin} +

+

{credential.username}

+ {credential.source ? ( +

+ Imported from {credential.source} +

+ ) : null} +
+ + {revealedPassword ?? "••••••••"} + +
+ + + + +
+
+ ); + })} +
+ )} + + ) : ( +
+
+ + + +

+ Import browser data +

+

+ Bring saved passwords and cookies over from an installed browser. +

+ +
+
+ + + +

+ Local password protection +

+

+ + Passwords are encrypted in Poracode's local credential store. Password values + are requested only when you reveal, copy, or edit them. + +

+
+
+ )} + + + + {editor ? ( + setEditor(null)} + onSaved={() => { + setEditor(null); + }} + /> + ) : null} + + This removes the saved password for {pendingDelete?.origin} from + Poracode. + + } + confirmLabel={t`Delete`} + onConfirm={() => void deleteCredential()} + onClose={() => setPendingDelete(null)} + /> + + ); +} + +function CredentialEditorModal(props: { + initial: CredentialDraft; + onClose: () => void; + onSaved: () => void; +}) { + const { t } = useLingui(); + const [origin, setOrigin] = useState(props.initial.origin); + const [username, setUsername] = useState(props.initial.username); + const [password, setPassword] = useState(props.initial.password); + const [saving, setSaving] = useState(false); + + async function save() { + setSaving(true); + try { + await readBridge().browserUpsertCredential({ + ...(props.initial.id ? { id: props.initial.id } : {}), + origin: origin.trim(), + username, + password, + }); + props.onSaved(); + } catch { + toast.danger(t`Unable to save the password.`); + } finally { + setSaving(false); + } + } + + return ( + !open && !saving && props.onClose()} + > + + + + + + {props.initial.id ? Edit password : Add password} + + + + + + + + + + + + + + + ); +} diff --git a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx index 3e92809d7..ce8b11ca4 100644 --- a/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx +++ b/src/renderer/views/MainView/parts/RightPanel/parts/BrowserPanel/parts/BrowserTabStrip.tsx @@ -1,4 +1,4 @@ -import { Globe, Plus, X } from "lucide-react"; +import { Download, Globe, KeyRound, Plus, X } from "lucide-react"; import { useState, type MouseEvent as ReactMouseEvent, type ReactNode } from "react"; import { useLingui } from "@lingui/react/macro"; import { useShallow } from "zustand/shallow"; @@ -9,7 +9,11 @@ import type { BrowserTabGroupInfo, BrowserTabInfo } from "@/shared/ipc"; import { BrowserTabGroupMenu } from "./BrowserTabGroupMenu"; import { groupColor } from "./groupColors"; -function TabFavicon(props: { faviconUrl?: string; loading: boolean }) { +function TabFavicon(props: { + faviconUrl?: string; + loading: boolean; + internalPage?: BrowserTabInfo["internalPage"]; +}) { if (props.loading) { return ( @@ -17,6 +21,12 @@ function TabFavicon(props: { faviconUrl?: string; loading: boolean }) { ); } + if (props.internalPage === "downloads") { + return ; + } + if (props.internalPage === "passwords") { + return ; + } if (props.faviconUrl) { return ( void; variant?: "row ) => { const active = tab.tabId === activeTabId; const attention = !active && tab.tabId === attentionTabId; + const displayTitle = + tab.internalPage === "downloads" + ? t`Download history` + : tab.internalPage === "passwords" + ? t`Password manager` + : tab.title || tab.url || t`New tab`; const activate = () => { if (!active) { readBridge() @@ -206,8 +222,9 @@ export function BrowserTabStrip(props: { onCreateTab: () => void; variant?: "row - {tab.title || tab.url || t`New tab`} + {displayTitle} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {bookmarks.length > 0 ? : null} - {bookmarks.slice(0, 20).map((b) => ( - - {b.faviconUrl ? ( - { - (e.currentTarget as HTMLImageElement).style.display = "none"; - }} - /> - ) : ( - - - - )} - - - ))} - - - - - - - - - - - - - - {recentHistory.length === 0 ? ( - - - - ) : ( - recentHistory.map((h) => ( - - - - - - - )) - )} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ); } diff --git a/src/shared/ipc/events.ts b/src/shared/ipc/events.ts index 2fe112ec1..0c80539a0 100644 --- a/src/shared/ipc/events.ts +++ b/src/shared/ipc/events.ts @@ -15,7 +15,12 @@ import type { UsageLoginDeviceCode, UsageSnapshot, } from "../contracts"; -import type { BrowserState, BrowserTabInfo } from "./procedures/browser"; +import type { + BrowserDownloadInfo, + BrowserFindResult, + BrowserState, + BrowserTabInfo, +} from "./procedures/browser"; import type { BrowserLinkPresentationMode } from "../settings"; import type { IpcProcedurePayload, SupervisorProcedureName } from "./procedureMap"; @@ -136,6 +141,11 @@ export type BrowserEvent = | { type: "state"; state: BrowserState } | { type: "tab-updated"; tab: BrowserTabInfo } | { type: "tab-attention"; tabId: string } + | { type: "find-open-requested"; tabId: string } + | { type: "find-result"; result: BrowserFindResult } + | { type: "download-updated"; download: BrowserDownloadInfo } + | { type: "download-removed"; downloadId: string } + | { type: "credentials-updated" } | { type: "open-panel"; mode?: BrowserLinkPresentationMode } | { type: "usage-login-confirmation"; request: UsageLoginConfirmationRequest } | { type: "usage-login-confirmation-closed"; requestId: string } diff --git a/src/shared/ipc/index.ts b/src/shared/ipc/index.ts index d524bbecf..8474d803d 100644 --- a/src/shared/ipc/index.ts +++ b/src/shared/ipc/index.ts @@ -42,13 +42,23 @@ export { type UpdateStatus, } from "./events"; export { + browserDownloadStateSchema, browserPickResultSchema, browserStateSchema, browserTabGroupSchema, browserTabSchema, type BrowserBookmarkInfo, + type BrowserCredentialInfo, + type BrowserDeviceEmulation, + type BrowserDownloadInfo, + type BrowserDownloadState, + type BrowserFindResult, type BrowserHistoryEntryInfo, + type BrowserImportResult, + type BrowserImportSourceInfo, + type BrowserInternalPage, type BrowserPickResult, + type BrowserPrintResult, type BrowserRect, type BrowserState, type BrowserStartPickerResult, diff --git a/src/shared/ipc/procedureMap.ts b/src/shared/ipc/procedureMap.ts index 824312b29..4bbd098cb 100644 --- a/src/shared/ipc/procedureMap.ts +++ b/src/shared/ipc/procedureMap.ts @@ -124,6 +124,7 @@ export const MAIN_LOCAL_PROCEDURE_NAMES = [ "installUpdate", "browserGetState", "browserCreateTab", + "browserOpenInternalPage", "browserCloseTab", "browserActivateTab", "browserMoveTab", @@ -139,6 +140,11 @@ export const MAIN_LOCAL_PROCEDURE_NAMES = [ "browserReload", "browserHardReload", "browserToggleDevTools", + "browserFindInPage", + "browserStopFindInPage", + "browserPrint", + "browserSetZoomFactor", + "browserSetDeviceEmulation", "browserClearHistory", "browserClearCookies", "browserClearCache", @@ -152,6 +158,14 @@ export const MAIN_LOCAL_PROCEDURE_NAMES = [ "browserRemoveBookmark", "browserSetBookmarkBarVisible", "browserRecentHistory", + "browserGetDownloads", + "browserDownloadAction", + "browserListCredentials", + "browserGetCredentialPassword", + "browserUpsertCredential", + "browserDeleteCredential", + "browserListImportSources", + "browserImportData", "browserExtractToWindow", "browserInjectToMain", "startUsageLogin", diff --git a/src/shared/ipc/procedures/browser.ts b/src/shared/ipc/procedures/browser.ts index 2fd92fb57..caf2c9621 100644 --- a/src/shared/ipc/procedures/browser.ts +++ b/src/shared/ipc/procedures/browser.ts @@ -32,6 +32,20 @@ export const browserTabGroupSchema = z.object({ }); export type BrowserTabGroupInfo = z.infer; +export const browserInternalPageSchema = z.enum(["downloads", "passwords"]); +export type BrowserInternalPage = z.infer; + +export const browserDeviceEmulationSchema = z.object({ + width: z.number().int().min(240).max(7680), + height: z.number().int().min(240).max(7680), + deviceScaleFactor: z.number().min(0.5).max(4), + scale: z.number().min(0.25).max(2), + mobile: z.boolean(), + touch: z.boolean(), + preset: z.string().optional(), +}); +export type BrowserDeviceEmulation = z.infer; + export const browserTabSchema = z.object({ tabId: z.string(), url: z.string(), @@ -41,6 +55,9 @@ export const browserTabSchema = z.object({ canGoBack: z.boolean(), canGoForward: z.boolean(), devToolsOpen: z.boolean().optional(), + internalPage: browserInternalPageSchema.optional(), + zoomFactor: z.number().min(0.25).max(5).optional(), + deviceEmulation: browserDeviceEmulationSchema.optional(), groupId: z.string().optional(), }); export type BrowserTabInfo = z.infer; @@ -174,6 +191,133 @@ export const browserSetBookmarkBarVisiblePayloadSchema = z.object({ visible: z.boolean(), }); +export const browserOpenInternalPagePayloadSchema = z.object({ + page: browserInternalPageSchema, +}); + +export const browserFindInPagePayloadSchema = z.object({ + tabId: z.string().min(1), + text: z.string().min(1), + forward: z.boolean(), + findNext: z.boolean(), + matchCase: z.boolean(), +}); + +export const browserStopFindInPagePayloadSchema = z.object({ + tabId: z.string().min(1), + action: z.enum(["clearSelection", "keepSelection", "activateSelection"]), +}); + +export const browserFindResultSchema = z.object({ + tabId: z.string(), + requestId: z.number().int(), + activeMatchOrdinal: z.number().int().nonnegative(), + matches: z.number().int().nonnegative(), + finalUpdate: z.boolean(), +}); +export type BrowserFindResult = z.infer; + +export const browserPrintResultSchema = z.object({ + ok: z.boolean(), + error: z.string().optional(), +}); +export type BrowserPrintResult = z.infer; + +export const browserSetZoomFactorPayloadSchema = z.object({ + tabId: z.string().min(1), + zoomFactor: z.number().min(0.25).max(5), +}); + +export const browserSetDeviceEmulationPayloadSchema = z.object({ + tabId: z.string().min(1), + emulation: browserDeviceEmulationSchema.nullable(), +}); + +export const browserDownloadStateSchema = z.enum([ + "progressing", + "paused", + "completed", + "cancelled", + "interrupted", +]); +export type BrowserDownloadState = z.infer; + +export const browserDownloadSchema = z.object({ + id: z.string(), + filename: z.string(), + url: z.string(), + mimeType: z.string(), + state: browserDownloadStateSchema, + receivedBytes: z.number().int().nonnegative(), + totalBytes: z.number().int().nonnegative(), + startTime: z.number(), + endTime: z.number().optional(), + canResume: z.boolean(), +}); +export type BrowserDownloadInfo = z.infer; + +export const browserDownloadActionPayloadSchema = z.object({ + id: z.string().min(1), + action: z.enum(["pause", "resume", "cancel", "remove", "open", "show-in-folder"]), +}); + +export const browserCredentialSchema = z.object({ + id: z.string(), + origin: z.string(), + username: z.string(), + createdAt: z.number(), + updatedAt: z.number(), + source: z.string().optional(), +}); +export type BrowserCredentialInfo = z.infer; + +export const browserCredentialIdPayloadSchema = z.object({ + id: z.string().min(1), +}); + +export const browserCredentialPasswordResultSchema = z.object({ + password: z.string(), +}); + +export const browserUpsertCredentialPayloadSchema = z.object({ + id: z.string().optional(), + origin: z.string().min(1), + username: z.string(), + password: z.string(), +}); + +export const browserImportSourceSchema = z.object({ + id: z.string(), + browser: z.enum(["chrome", "edge", "brave", "chromium"]), + browserLabel: z.string(), + profileLabel: z.string(), + supportsPasswords: z.boolean(), + supportsCookies: z.boolean(), + hasAppBoundData: z.boolean(), +}); +export type BrowserImportSourceInfo = z.infer; + +export const browserImportDataPayloadSchema = z + .object({ + sourceId: z.string().min(1), + passwords: z.boolean(), + cookies: z.boolean(), + acknowledgeProtectedData: z.boolean(), + }) + .refine((value) => value.passwords || value.cookies, { + message: "Select at least one browser data type", + }); + +export const browserImportResultSchema = z.object({ + passwordsImported: z.number().int().nonnegative(), + cookiesImported: z.number().int().nonnegative(), + passwordsSkipped: z.number().int().nonnegative(), + cookiesSkipped: z.number().int().nonnegative(), + protectedItemsSkipped: z.number().int().nonnegative(), + errors: z.array(z.string()), +}); +export type BrowserImportResult = z.infer; + export const browserRecentHistoryPayloadSchema = z.object({ limit: z.number().int().positive().max(50), }); @@ -188,6 +332,11 @@ export const browserProcedures = { BrowserTabInfo, "main-local" >("browserCreateTab", "main-local", browserCreateTabPayloadSchema), + browserOpenInternalPage: definePayloadProcedure< + z.infer, + BrowserTabInfo, + "main-local" + >("browserOpenInternalPage", "main-local", browserOpenInternalPagePayloadSchema), browserCloseTab: definePayloadProcedure< z.infer, void, @@ -263,6 +412,31 @@ export const browserProcedures = { void, "main-local" >("browserToggleDevTools", "main-local", browserTabIdPayloadSchema), + browserFindInPage: definePayloadProcedure< + z.infer, + void, + "main-local" + >("browserFindInPage", "main-local", browserFindInPagePayloadSchema), + browserStopFindInPage: definePayloadProcedure< + z.infer, + void, + "main-local" + >("browserStopFindInPage", "main-local", browserStopFindInPagePayloadSchema), + browserPrint: definePayloadProcedure< + z.infer, + BrowserPrintResult, + "main-local" + >("browserPrint", "main-local", browserTabIdPayloadSchema), + browserSetZoomFactor: definePayloadProcedure< + z.infer, + void, + "main-local" + >("browserSetZoomFactor", "main-local", browserSetZoomFactorPayloadSchema), + browserSetDeviceEmulation: definePayloadProcedure< + z.infer, + void, + "main-local" + >("browserSetDeviceEmulation", "main-local", browserSetDeviceEmulationPayloadSchema), browserClearHistory: definePayloadProcedure< z.infer, void, @@ -327,6 +501,43 @@ export const browserProcedures = { BrowserHistoryEntryInfo[], "main-local" >("browserRecentHistory", "main-local", browserRecentHistoryPayloadSchema), + browserGetDownloads: defineNoArgProcedure( + "browserGetDownloads", + "main-local", + ), + browserDownloadAction: definePayloadProcedure< + z.infer, + void, + "main-local" + >("browserDownloadAction", "main-local", browserDownloadActionPayloadSchema), + browserListCredentials: defineNoArgProcedure( + "browserListCredentials", + "main-local", + ), + browserGetCredentialPassword: definePayloadProcedure< + z.infer, + z.infer, + "main-local" + >("browserGetCredentialPassword", "main-local", browserCredentialIdPayloadSchema), + browserUpsertCredential: definePayloadProcedure< + z.infer, + BrowserCredentialInfo, + "main-local" + >("browserUpsertCredential", "main-local", browserUpsertCredentialPayloadSchema), + browserDeleteCredential: definePayloadProcedure< + z.infer, + void, + "main-local" + >("browserDeleteCredential", "main-local", browserCredentialIdPayloadSchema), + browserListImportSources: defineNoArgProcedure( + "browserListImportSources", + "main-local", + ), + browserImportData: definePayloadProcedure< + z.infer, + BrowserImportResult, + "main-local" + >("browserImportData", "main-local", browserImportDataPayloadSchema), browserExtractToWindow: defineNoArgProcedure( "browserExtractToWindow", "main-local",